[
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "### Introduction\n\nThis Code of Conduct applies to all spaces managed by the Gravity Recovery Object Oriented Programming System (GROOPS) project, including all public and private mailing lists, issue trackers, discussions, wikis, blogs, meetings, workshops and any other channel used by our community.\n\nThis Code of Conduct should be honored by everyone who participates in the GROOPS community formally or informally, or claims any affiliation with the project, in any project-related activities and especially when representing the project, in any role.\n\nThis code is not exhaustive or complete. It serves to distill our common understanding of a collaborative, shared environment and goals. Please try to follow this code in spirit as much as in letter, to create a friendly and productive environment that enriches the surrounding community.\n\n### Specific Guidelines\n\nWe strive to:\n\n1. Be open. We invite anyone to participate in our community. We prefer to use public methods of communication for project-related messages, unless discussing something sensitive. This applies to messages for help or project-related support, too; not only is a public support request much more likely to result in an answer to a question, it also ensures that any inadvertent mistakes in answering are more easily detected and corrected.\n2. Be empathetic, welcoming, friendly, and patient. We work together to resolve conflict, and assume good intentions. We may all experience some frustration from time to time, but we do not allow frustration to turn into a personal attack. A community where people feel uncomfortable or threatened is not a productive one. Most project members answer questions or investigate issues in their spare time, so be patient when waiting for a response.\n3. Be collaborative. Our work will be used by other people, and in turn we will depend on the work of others. When we make something for the benefit of the project, we are willing to explain to others how it works, so that they can build on the work to make it even better. Any decision we make will affect users and colleagues, and we take those consequences seriously when making decisions.\n4. Be inquisitive. Nobody knows everything! Asking questions early avoids many problems later, so we encourage questions, although we may direct them to the appropriate forum. We will try hard to be responsive and helpful.\n5. Be careful in the words that we choose. We are careful and respectful in our communication, and we take responsibility for our own speech. Be kind to others. Do not insult or put down other participants. We will not accept harassment or other exclusionary behaviour, such as:\n   * Violent threats or language directed against another person.\n   * Sexist, racist, or otherwise discriminatory jokes and language.\n   * Posting sexually explicit or violent material.\n   * Posting (or threatening to post) other people’s personally identifying information (“doxing”).\n   * Sharing private content, such as emails sent privately or non-publicly, without the sender’s consent.\n   * Personal insults, especially those using racist or sexist terms.\n   * Unwelcome sexual attention.\n   * Excessive profanity. Please avoid swearwords; people differ greatly in their sensitivity to swearing.\n   * Repeated harassment of others. In general, if someone asks you to stop, then stop.\n   * Advocating for, or encouraging, any of the above behaviour.\n\n### Diversity Statement\n\nThe GROOPS project welcomes and encourages participation by everyone. No matter how you identify yourself or how others perceive you: we welcome you. We are committed to being a community that everyone enjoys being part of. Although we may not always be able to accommodate each individual’s preferences, we try our best to treat everyone kindly.\n\nThough no list can hope to be comprehensive, we explicitly honour diversity in: age, culture, ethnicity, genotype, gender identity or expression, language, national origin, neurotype, phenotype, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, subculture and technical ability, to the extent that these do not conflict with this Code of Conduct.\n\n### Enforcement and Reporting Guidelines\n\nWe encourage all community members to resolve issues on their own whenever possible. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the [project committee](https://github.com/orgs/groops-devs/people).\n\nIn case of severe and obvious breaches, we will immediately disconnect the originator from the GROOPS communication channels. In cases not involving clear severe and obvious breaches of this Code of Conduct, the process for acting on any received Code of Conduct violation report will be:\n\n1. Acknowledgement that the report has been received\n2. Reasonable discussion/feedback\n3. Mediation (if feedback didn’t help, and only if both reporter and reportee agree to this)\n4. Enforcement via transparent decision by the [project committee](https://github.com/orgs/groops-devs/people) leading to one of the following resolutions:\n   1. Correction\n\n      A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.\n   2. Warning\n\n      Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.\n   3. Temporary Ban\n\n      Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.\n   4. Permanent Ban\n\n      Consequence: A permanent ban from any sort of public interaction within the community.\n\n### Attribution\n\nThis Code of Conduct is adapted from the [SciPy Code of Conduct](https://docs.scipy.org/doc/scipy/dev/conduct/code_of_conduct.html), the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) and the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: File a bug report.\nlabels: [\"bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n        Please make sure you have checked the [GROOPS documentation](https://groops-devs.github.io/groops/html/) before submitting a bug report.\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: |\n        - A clear and concise description of what the bug is.\n        - Also tell us what you expected to happen.\n        - If possible, append a **minimum working example** (GROOPS config file plus any required data) that leads to the bug.\n        - Otherwise, include step-by-step instructions on how to reproduce the bug.\n      placeholder: Tell us what the issue is about.\n    validations:\n      required: true\n  - type: dropdown\n    id: version\n    attributes:\n      label: GROOPS version\n      description: What version of GROOPS are you running?\n      options:\n        - main (latest commit)\n        - Release 2021-09-06\n        - Release 2021-02-02\n        - Release 2020-11-12\n        - Other (please specify in the description)\n    validations:\n      required: true\n  - type: checkboxes\n    id: operating-systems\n    attributes:\n      label: Operating systems\n      description: Which operating systems are you using? You may select more than one.\n      options:\n        - label: Linux\n        - label: Windows\n        - label: macOS\n        - label: Other (please specify in the description)\n  - type: textarea\n    id: logs\n    attributes:\n      label: Log output\n      description: Please copy and paste any relevant log output. Run ```groops -l logfile.txt <config.xml>``` to create a log file. If the log output is too long, please attach the log file in the description instead.\n      placeholder: Paste any relevant log output here.\n      render: dircolors\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: Question\n    url: https://github.com/groops-devs/groops/discussions\n    about: Ask about GROOPS usage or other topics in the Discussions section.\n  - name: GROOPS Documentation\n    url: https://groops-devs.github.io/groops/html/\n    about: Please check the GROOPS documentation before opening a new issue.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Suggest a new feature.\nlabels: [\"enhancement\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to suggest a new feature!\n        Please make sure you have checked the [GROOPS documentation](https://groops-devs.github.io/groops/html/) before submitting a feature request.\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: |\n        - Is your feature request related to a problem? Please describe.\n        - Describe the solution you would like.\n        - Describe alternatives you have considered.\n      placeholder: Tell us about the feature.\n    validations:\n      required: true\n"
  },
  {
    "path": ".gitignore",
    "content": "# miscellaneous\n# -------------\n*.*~\n*.bak\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# main\n- New program:      Accelerometer2GraceL1b.\n- New program:      Orbit2GraceL1b.\n- New program:      SatelliteTracking2GraceL1b.\n- New program:      StarCamera2GraceL1b.\n- New class:        ParameterSelector: group.\n- New option:       conditionStringContains/MatchPattern: supports wildcards.\n- Bugfix:           ConditionFileExist: fixed bug with wildcards.\n- Bugfix:           GUI: fixed MatchCaseSensitive for schema selction.\n- Bugfix:           GUI: fixed bug when moving elements to same position.\n- Bugfix:           GNSS, WriteNormalEquations: check non-matching parameter selection.\n- Bugfix:           Instrument2AllanVariance: Fix sample counting.\n- Bugfix:           The parser was sometimes applied twice to filenames.\n- Bugfix:           Tle2Orbit: Fixed bug when first record in file is used.\n- Other:            NetCDF: enable to read multidimensional variables to store in muliple columns.\n- Other:            Changed ftp.tugraz.at/outgoing/ITSG to ftp.tugraz.at/pub/ITSG.\n- Other:            ModelEquilibriumTide: Taking into account spatially varying density.\n- Other:            GnssTroposphere2TropoSinex: Revised interface.\n- Other:            GnssAntex2AntennaDefinition: Handling of changing antennas of a SVN.\n\n# Release 2025-11-15\n- New program:      StarCamera2Orbex (replaces GnssAttitude2Orbex).\n- New program:      DoodsonHarmonicsChangePartialTides.\n- New program:      Conversion: OceanTidesDTU2GriddedData.\n- New program:      GnssResiduals2TransmitterAccuracyDefinition.\n- New program:      SynthesisSphericalHarmonicsMatrix.\n- New program:      Gravityfield2GravityVector.\n- New program:      NormalsReorderAndAccumulate.\n- New class:        PlotDegreeAmplitudes: degreeAmplitudesSimple.\n- New class:        Loop: SortAndRemoveDuplicates of an arbitrary loop.\n- New option:       GnssAntennaNormalsConstraint: gnssType selection for TEC constraint.\n- New option:       PlotAxisLabeled: majorTickSpacing, minorTickSpacing, gridLineSpacing.\n- New option:       GNSS/SLR: optional disabling of stations without precise apriori positions.\n- New option:       condition->fileExist: minimumSize.\n- New option:       GNNS->parametrizationVTEC: optional gradient estimation.\n- New option:       GNNS->TransmitterGeneratorGnss: option to disable clock interpolation.\n- File format:      TideGeneratingPotential includes now degree 3 tides.\n- File format:      Each file is now readable/writable in JSON format as well.\n- File format:      Removed deprecated GnssStationInfo (replaced by Platform).\n- Bugfix:           GUI: fixed Ctrl+Shift+Up/Down for variables.\n- Bugfix:           slrParametrizationRangeBiasStationSatellite: Fix station index.\n- Bugfix:           parameterNames: fixed wrong order.\n- Bugfix:           GraceAod2DoodsonHarmonics: fixed phase error.\n- Bugfix:           GnssOrbex2StarCamera: reads now free format.\n- Bugfix:           GnssNormals2Sinex: fixed parser error.\n- Bugfix:           GnssParametrizationIonosphereSTEC: constant sigmaSTEC>0 was evaluated always to one.\n- Bugfix:           ParameterVector2GnssAntennaDefinition: Sometimes the parameters were assigned incorrectly.\n- Bugfix:           GNSS: Fixed bug in preprocessing when only one phase observation is available.\n- Bugfix:           GNSS: Fixed bug in gnssParametrizationTemporalBias when reading apriori values.\n- Other:            GUI: offer links for numbers and strings of different types.\n- Other:            GUI: Open multiple config files with the file selector.\n- Other:            GUI: Inform about deprecated elements.\n- Other:            gnss: set margin for polynomial orbit interpolation to 1e-7 seconds.\n- Other:            gnss: simulation considers more apriori models (e.g. TEC maps).\n- Other:            IGRF: Updated International Geomagnetic Reference Field (IGRF) to 14th Generation Release\n- Other:            GNSS: Improved setup of ambiguity parameters. Considers splitted network, splitted observations (e.g. L2LG, L2WG).\n- Other:            GNSS: More stable estimation of ambiguities. Faster ambiguity resolution (decorrelation step).\n- Other:            GNSS: range scale due to transmitter frequency offset/clock drift.\n- Other:            Store more double digits in xml format.\n- Other:            NormalsEliminate: regularize unused eliminated parameters.\n- Other:            Sinex2StationPosition: Apply frequencies to all intervals.\n- Other:            GNSS: apriori ionospheric map is interpolated in solar-geomagentic frame.\n- Other:            Tle2Orbit: Use closest record if multiple records for the same satellites are given.\n- Other:            Loop: revised interface.\n- Other:            Config: The variables groopsConfigFile and workingDir are set automatically.\n\n# Release 2024-06-24\n- Interface change: Variables can now declared at any place in the config file (not only in the global section).\n                    They have local scope within the hierarchy level.\n                    Loop and conditions attributed to elements no longer need to be declared in the global section.\n- SLR Processing:   New processing of SLR data with estimation of all relevant geodetic parameters.\n  - New program:      SlrProcessing\n  - New program:      conversion: Cpf2Orbit\n  - New program:      conversion: Crd2NormalPoints\n  - New program:      conversion: Cstg2NormalPoints\n  - New program:      conversion: Merit2FullRate\n  - New program:      conversion: Merit2NormalPoints\n  - New program:      conversion: Orbit2Cpf\n  - New program:      conversion: SinexEccentricties2SlrPlatform\n  - New program:      conversion: SlrComModel2RangeBiasStationSatellite\n  - New program:      conversion: SlrSinexDataHandling2Files\n  - New class:        slrParametrization\n  - New class:        slrProcessingStep\n  - New class:        slrSatelliteGenerator\n  - New class:        slrStationGenerator\n  - New class:        In Troposphere: MendesAndPavlis\n  - New instrument file format: SATELLITELASERRANGING\n  - New instrument file format: METEOROLOGICAL\n- New program:      eclipseFactor2GriddedData.cpp: returns a global grid with eclipse factors.\n- New program:      orbit2EarhFixedOrbit: Rotate an orbit into a rotation earth fixed frame.\n- New program:      GriddedDataTimeSeries2PotentialCoefficients.\n- New program:      SinexMetadata2GlonassFrequencyNumber.\n- New program:      SimulateStarCameraTerrasar.\n- New class:        In PlatformSelector: Equipment.\n- New class:        In Gravityfield/Tides/MiscAccelerations: Group.\n- New option:       GnssAntennaDefinitionCreate: setZero and removeCenterMean.\n- New option:       Sp3Fromat2Orbit: Write all satellites (identifier is appended to each file).\n- New option:       GriddedData2PotentialCoefficients: Handle multiple input data columns at once.\n- New option:       GriddedDataReduceSampling: tesseroid volume conserving for digital elevation models.\n- New option:       Loop: optional condition for each loop step.\n- New option:       gnssParametrizationStaticPositions: no net scale constraint.\n- New option:       GnssProcessingStepResolveAmbiguities: partial ambiguity resolution with selectTransmitters/Receivers.\n- New option:       GnssParametrizationCodeBiases: option to define ionosphere-free clock datum.\n- New option:       GnssParametrizationIonosphereMap: option to read/write VTEC maps.\n- New option:       PlatformSelector: new selection algorithm with exclude option.\n- New option:       GoceXmlEggNom1b: write also linear common mode accelerations.\n- Removed program:  GnssPrn2SvnBlockVariables: This program will no longer work from the next release! See documentation for help.\n- Removed program:  NetCdf2PotentialCoefficients: Use NetCdf2GriddedDataTimeSeries and GriddedDataTimeSeries2PotentialCoefficients instead.\n- Removed program:  Metop2Starcamera: Use Champ2AccStar instead.\n- Bugfix:           GnssParametrizationStaticPositions: ignored inputfileNoNetPositions.\n- Bugfix:           SphericalHarmonicsFilter->DDK: corrected filter for level 4 onwards (Compatible with ICGEM definition).\n- Bugfix:           ObservationDeflections: fixed index bug.\n- Bugfix:           NormalEquationFile: corrected contribution computation.\n- Bugfix:           NetCdf: in some cases the data has been swapped.\n- Bugfix:           GnssRinexNavigation2OrbitClock: reimplementation of source code.\n- Other:            GnssAntennaDefinition2ParameterVector: with area weights.\n- Other:            GnssAntex2AntennaDefinition/GnssGlonassFrequencyNumberUpdate: write Platform files instead of deprecated GnssStationInfo files.\n- Other:            EarthRotation::rotaryAxis: if EOP time series is too short, use simplified equations.\n- Other:            Gravityfield2Deflections: Computation based now on normal gravity.\n- Other:            SimulateStarCamera: new optional nadir pointing mode.\n- Other:            SimulateOrbit: Improved temporal numerical precision.\n- Other:            GnssRinexNavigation2OrbitClock: add SBAS support.\n- Other:            Updated documentation to explain parameter names.\n- Other:            GriddedData: reworked area computations.\n- Other:            IersC04IAU2000EarthOrientationParameter: works also with new file format.\n- Other:            condition->fileExist: Supports now wildcards: * and ?.\n- Other:            Champ2Orbit: simplified interface.\n\n# Release 2023-08-25\n- New program:      FileMove.\n- New program:      FileTextCreate.\n- New program:      InstrumentRemoveEpochsThruster.\n- New program:      InstrumentApplyTimeOffset.\n- New program:      InstrumentAccelerometerEstimateParameters (replaces InstrumentAccelerometerEstimateBiasScale).\n- New program:      GraceOrbit2TransplantTimeOffset.\n- New program:      GraceThrusterResponse2Accelerometer.\n- New program:      GnssReceiver2RinexObservation.\n- New program:      Sinex2StationPositions: replaces Sinex2StationPosition and Sinex2StationPostSeismicDeformation.\n- New program:      ObservationEquations2Files.\n- New program:      Variational2OrbitAndStarCamera (renamed Variational2Orbit): added possibility to also extract Earth rotation.\n- New program:      PlatformCreate: replaces gnssStationInfoCreate.\n- New program:      Tle2Orbit: Orbit from Two Line Elements (TLE).\n- New program:      GriddedData2NetCdf, GriddedDataTimeSeries2NetCdf (replaces GridRectangular2NectCdf).\n- New program:      NetCdf2GriddedData, NetCdf2GriddedDataTimeSeries (replaces NectCdf2DridRectangular).\n- New program:      DoodsonAdmittance2SupplementaryFiles: for publication of ocean tide models.\n- New program:      Gravityfield2TrendPotentialCoefficients: Estimate trend, annual, ...\n- New class:        In Loop: DirectoryListing.\n- New class:        In Loop: FileLines.\n- New class:        In InstrumentResample/interpolatorTimeSeries: FillGapsLeastSquaresPolynomialFit.\n- New class:        In MiscAccelerations: AtmosphericDragFromDensityFile.\n- New class:        In MiscAccelerations: RadiationPressure, replaces SolarRadiatinPressure, Albedo\n- New class:        In Loop: PlatformEquipment (replaces FileGnssStationInfo).\n- Bugfix:           Gravityfield2Deflections: fixed initialization bug.\n- Bugfix:           GnssRinexNavigation2OrbitClock: updated to be usable for rinex4 and fixes for rinex3.\n- Bugfix:           Plot: various fixes for GMT Versions >6.1.\n- Bugfix:           GriddedData: unwrap longitude before computing area elements.\n- Bugfix:           InstrumentResample/polynomial: corrected interpolation vs. extrapolation.\n- Bugfix:           GnssResiduals2Skyplot: consider also the PRN in type.\n- Bugfix:           GssProcessingStepDisableTransmitterShadowEpochs.\n- Bugfix:           Sinex2StationPositions: Correct sign for approx. positions.\n- Other:            Reworked of GRACE-(FO) L1A conversion.\n- Other:            GnssReceiver: Improved preprocessing (initial clock and cycleslip detection).\n- Other:            GnssParametrizationStaticPositions: better selection of noNet stations.\n- Other:            GnssParametrizationLeoDynamicOrbits: handling of mutliple arcs.\n- Other:            GnssRinexNavigation2OrbitClock: works also for glonass.\n- Other:            PlotMisc: set minimum size of points in legend to 3p.\n- Other:            Preparation to replace GnssStationInfo file format by the more general Platform file format.\n- Other:            Text parser: new {text/regex/replace}.\n- Other:            GUI: added new multi-line comment elements, revised code.\n\n# Release 2022-07-28\n- New programs:     GriddedData2GriddedDataTimeSeries and GriddedDataTimeSeries2GriddedData.\n- New programs:     MagneticField2GriddedData and Orbit2MagneticField.\n- New class:        In MiscAccelerations: FromParametrization\n- New option:       GnssAntennaDefinitionCreate: rename antennas.\n- New option:       gnssReceiverGeneratorStationNetwork: inputfileClock.\n- New option:       gnssReceiverGenerator: print preprocessing infos.\n- New option:       GroupPrograms: silently and additional outputfileLog.\n- New option:       MatrixGenerator->NormalsFile: observationCount.\n- Bugfix:           instrument files: empty files are now compatible to other instrument types.\n- Bugfix:           gnssProcessingStep: uninitialized normalEquationInfo.\n- Bugfix:           gnssProcessingStep: wrong counting of observations.\n- Bugfix:           gnssProcessingStepForEachReceiverSeparately: variableReceiver was not set.\n- Bugfix:           gnssProcessingStepResolveAmbiguities: for writing empty ambiguity file.\n- Bugfix:           gnssParametrizationClocksModel: Fixed zero mean constraint.\n- Bugfix:           gnssParametrizationLeoDynamicOrbits: in parallel excecution.\n- Bugfix:           gnssParametrizationKinematicPositions: in parallel excecution.\n- Bugfix:           gnssTransmitter: noAntennaPatternFound->ignoreObservation not working correctly.\n- Bugfix:           gnssReceiver: Simulating GLONASS ambiguities now correctly considers frequency channel.\n- Bugfix:           sp3Format2Orbit: no/invalid orbit positions/velocities are now excluded.\n- Bugfix:           Conversion of GRACE L1B/L1A data: revised source code.\n- Bugfix:           loopFileAscii: Fixed uninitialized variable that could lead to the loop ending prematurely.\n- Bugfix:           GnssAntex2AntennaDefinition: Fixed handling of frequency RMS blocks.\n- Other:            File GriddedDataTimeSeries: includes now the last epoch; interval [...] instead of [...).\n- Other:            File TimeSplinesGravityfield: includes now the last epoch; interval [...] instead of [...).\n- Other:            Removed inputfileGlobal option.\n- Other:            GnssAttitude2Orbex: can now handle different sampling per satellite.\n- Other:            GnssRinexNavigation2OrbitClock/RinexObservation2GnssReceiver: Added basic support for RINEX v4.00.\n- Other:            gnssParametrization*DynamicOrbits: integration starts and ends with first/last valid epoch.\n- Other:            GnssLowEarthOrbiter: createTracks() before removing outlier epochs leads to less track splits.\n- Other:            GUI: Added 'Open Documentation' to the context menu.\n\n# Release 2021-09-06\n- Interface change: Complete redesign of GnssProcessing to make usage a little bit easier and more flexible.\n    - Direct use of orbits without integrating variational equations in case of fixed transmitters (e.g., PPP).\n    - New class to add flexible parametrizations to the normal equation system.\n    - New class to select transmitters/receivers for each parametrization.\n    - Unified all transmitter classes into single class and merged all transmitter data and metadata into one folder at https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/.\n    - Example scenarios with config files at https://ftp.tugraz.at/pub/ITSG/groops/scenario/.\n    - Updated and expanded documentation and cookbooks to reflect all GNSS-related changes.\n- New program:      InstrumentAccelerometer2ThermosphericDensity: Estimate neutral density from accelerometer data.\n- New class:        In Thermosphere: new model nrlmsis2\n- New class:        In Condition: Matrix to evaluate matrix elements.\n- New class:        In PlotMapProjection: added Mollweide map projection.\n- Bugfix:           FileSatelliteModel: removed if-statement for shaded plates, not necessary when applying the algorithm following Sentman 1961\n- Other:            Expression parser: constants are now defined with brackets, e.g pi().\n- Other:            Additional constants in the mathematical parser like speed of light c().\n\n# Release 2021-02-02\n- Interface change: GnssProcessing, GnssSimulateReceiver: Removed intervals (use program within LoopPrograms instead).\n- Interface change: SimulateStarCameraGnss: Full reimplementation with interface change.\n                    Added support for all known attitude modes used by GPS, GLONASS, Galileo, BeiDou, and QZSS. Now requires GnssAttitudeInfo file.\n- Interface change: Renamed program KalmanStaticTemporalNormals to NormalsBuildShortTimeStaticLongTime.\n- New program:      GnssAttitudeInfoCreate: Creates attitude info file used by SimulateStarCameraGnss.\n- New program:      PreprocessingDualSst: Analyze GRACE-FO KBR and LRI together.\n- New class:        In Observation: DualSstVariational to use GRACE-FO KBR and LRI together.\n- New class:        In ParametrizationGravity: LinearTransformation: Gravity field parametrization based on the linear transformation of another parametrizationGravity.\n- New option:       LoopPrograms: processCountPerIteration (when running the loop on multiple processes), parallelLog (output to screen/log files from all processes).\n- New option:       IfPrograms: elsePrograms (executed if condition evaluates to false).\n- New option:       GroupPrograms: catchErrors (prevents program termination on error and optionally runs additional programs, i.e. try-catch).\n- Bugfix:           Orbit2Kepler: Fixed angular output values (DEG2RAD -> RAD2DEG).\n- Bugfix:           GnssClockRinex2InstrumentClock: 9-character identifier field width is now used starting from v3.04, not (incorrectly) from v3.00.\n- Bugfix:           SphericalHarmonicsFilterMatrix: Input coefficient vector is now sorted correctly into filter matrix numbering.\n- Bugfix:           MatrixDistributed: choleskyInverse(): Fixed a bug with sparse matrices.\n- Bugfix:           Rectangular grids with one row or column (i.e. parallels or meridians) are now handled correctly.\n- Bugfix:           InstrumentEstimateEmpiricalCovariance: Computation of autocovariance now works as expected.\n- Bugfix:           Parallel: Multiple bugfixes and improvements for better support of different MPI implementations.\n- Other:            Gnss: Updated BeiDou signal definition according to RINEX 3.05 and added support for BeiDou composite types.\n- Other:            Sp3Format2Orbit: Added support for SP3d format.\n- Other:            LoopPrograms: continueAfterError now works in parallel execution.\n- Other:            Improved CMake installation process (see updated INSTALL.md). Now supports parallel compilation and install target.\n\n# Release 2020-11-12\n- Initial release\n"
  },
  {
    "path": "CITATION.bib",
    "content": "@article{Mayer-Gurr2021,\n  author = {Mayer-G{\\\"{u}}rr, Torsten and Behzadpour, Saniya and Eicker, Annette and Ellmer, Matthias and Koch, Beate and Krauss, Sandro and Pock, Christian and Rieser, Daniel and Strasser, Sebastian and S{\\\"{u}}sser-Rechberger, Barbara and Zehentner, Norbert and Kvas, Andreas},\n  doi = {https://doi.org/10.1016/j.cageo.2021.104864},\n  issn = {0098-3004},\n  journal = {Computers & Geosciences},\n  keywords = {GNSS processing,Gravity field recovery,Orbit determination},\n  pages = {104864},\n  title = {{GROOPS: A software toolkit for gravity field recovery and GNSS processing}},\n  url = {https://www.sciencedirect.com/science/article/pii/S009830042100159X},\n  year = {2021}\n}"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to GROOPS\n\nWe appreciate all contributions such as improving the documentation, reporting or fixing bugs,\nimplementing new features and answering questions from users.\n\n## Getting Started\n\n### Improving Documentation and Examples\n\nPlease inform us about your intention to work on the documentation by\n[creating an issue](https://github.com/groops-devs/groops/issues).\n\nWhen your contribution is finished, please submit a Pull Request (PR)\nto https://github.com/groops-devs/groops.\n\nYour contribution will then be reviewed.\n\n### Reporting and Fixing Bugs\n\nIf you encounter a bug, please let us know by [filing an issue](https://github.com/groops-devs/groops/issues).\nPlease include as much information as possible on how to reproduce the bug\nand about your software environment (operating system, compiler version, GROOPS version).\n\nIf you want to provide a bug fix, please get in contact with us before you start coding.\nThe best way to do so is by posting your intent in the issue related to that bug.\nWhen your contribution is finished, please submit a Pull Request (PR)\nto https://github.com/groops-devs/groops.\n\nYour contribution will then be reviewed.\n\n### Implementing New Features\n\n[Create an issue](https://github.com/groops-devs/groops/issues) and we will discuss together how to\nbest integrate the new functionality into the existing code base.\nOnce we together agree on a way forward, you can go ahead and implement it.\n\nWhen your contribution is implemented and tested, please submit a Pull Request (PR)\nto https://github.com/groops-devs/groops.\n\nYour contribution will then be reviewed.\n\nReviewing large PRs is difficult and will take time, so please be patient.\n\n### Answering User Questions\n\nYou can answer questions from users in the\n[Discussions](https://github.com/groops-devs/groops/discussions) section.\n"
  },
  {
    "path": "INSTALL.md",
    "content": "# Installation\n\nThis guide provides step-by-step instructions for compiling and running GROOPS from scratch.\n\n- [Get the GROOPS Source Code](#get-the-groops-source-code)\n- [Microsoft Windows](#microsoft-windows)\n- [Linux](#linux)\n    - [Ubuntu](#ubuntu)\n    - [OpenSUSE](#opensuse)\n    - [Arch Linux](#arch-linux)\n\n## Overview\n\nWhile GROOPS is intended to be a standalone software package, some functionality depends on external libraries.\nThe installation instructions provided further below include steps to install these dependencies.\nHard dependencies are:\n\n - [the Expat XML parser](https://libexpat.github.io)\n - an implementation of the Linear Algebra Package (LAPACK), for example:\n    - [OpenBLAS](https://github.com/xianyi/OpenBLAS)\n    - [Intel MKL](https://software.intel.com/content/www/us/en/develop/tools/math-kernel-library.html)\n\nAdditional libraries extend the feature set of GROOPS and can be optionally enabled at compile time.\nAt the moment, these include:\n\n- [NetCDF](https://www.unidata.ucar.edu/software/netcdf) for reading and writing NetCDF files\n- [zlib](https://zlib.net) for reading and writing compressed files\n- the Essential Routines for Fundamental Astronomy ([liberfa](https://github.com/liberfa/erfa)) for high-precision\n  Earth rotation\n\nAnother optional dependency is an implementation of the Message Passing Interface standard (MPI,\nfor example [MPICH](https://www.mpich.org/) or [Microsoft MPI](https://docs.microsoft.com/en-us/message-passing-interface/microsoft-mpi)).\nResource intensive tasks and algorithms are designed and implemented to be optionally run in\nparallel on distributed systems.\n\nTo visualize data sets, GROOPS requires an installation of the [Generic Mapping Tools (GMT)](https://www.generic-mapping-tools.org/).\n\n## Get the GROOPS Source Code\n\nYou can download the source code of a specific version on the\n[Releases](https://github.com/groops-devs/groops/releases) page, or\nclone the repository to always get the latest updates:\n\n```\ngit clone https://github.com/groops-devs/groops.git\n```\n\n## Microsoft Windows\n\nGROOPS under Windows requires CMake, and 64bit C++14 and Fortan compilers.\nA convenient way to install all required tools is through [MSYS2](https://www.msys2.org).\nThis installation guide assumes that the GROOPS source code is located in `C:\\groops`.\n\n1. Download the MSYS2 installer and follow the [installation guide](https://www.msys2.org/#installation).\n\n2. **Important**: After successful installation, close the MSYS2 terminal from step 1 and open the **MSYS2 MinGW 64-bit terminal**\n    through `Start Menu > MSYS2 64-bit > MSYS2 MinGW 64-bit`.\n\n    The command prompt in the terminal window should now read `username@hostname MINGW64`.\n\n3. Install compilers, cmake, expat, OpenBLAS, and LAPACK:\n    ```\n    pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-gcc-fortran mingw-w64-x86_64-cmake expat mingw64/mingw-w64-x86_64-openblas\n    ```\n\n4. *(Optional)* Install the NetCDF library:\n    ```\n    pacman -S mingw-w64-x86_64-netcdf\n    ```\n\n5. *(Optional)* Download and install liberfa:\n\n    5.1. Install the `tar` utility and required build tool:\n    ```\n    pacman -S tar make\n    ```\n\n    5.2. Download and build the ERFA library:\n    ```\n    mkdir -p /c/groops/lib && cd /c/groops/lib\n    wget https://github.com/liberfa/erfa/releases/download/v1.7.0/erfa-1.7.0.tar.gz\n    tar -xvf erfa-1.7.0.tar.gz\n    cd erfa-1.7.0\n    ./configure\n    make\n    make install\n    ```\n\n6. *(Optional)* Install Microsoft MPI:\n\n    6.1 Download and install the [Microsoft MPI](https://docs.microsoft.com/en-us/message-passing-interface/microsoft-mpi).\n\n    6.2 Install the MSYS2 `msmpi` package:\n    ```\n    pacman -S mingw-w64-x86_64-msmpi\n    ```\n\n7. Create the build directory and compile GROOPS:\n    ```\n    mkdir /c/groops/source/build && cd /c/groops/source/build\n    cmake.exe .. -G \"MinGW Makefiles\" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"C:\\groops\"\n    mingw32-make.exe -j4\n    mingw32-make.exe install\n    ```\n\n8. Make sure to also read the [post-installation steps](#windows-post-installation-steps).\n\n### Graphical User Interface (GUI)\n\nThe GROOPS GUI is based on [Qt](https://www.qt.io/) and is tested with Qt version 5.15.1.\n\nWe recommend installing the GROOPS GUI via the precompiled Windows binaries provided with\neach [release](https://github.com/groops-devs/groops/releases).\n\nIn case you want to compile the GUI yourself, you need to:\n\n1. [Download and install](https://www.qt.io/download-qt-installer) Qt (registration required).\n\n2. When prompted to choose which Qt components to install, select `Select Package Categories > LTS` and\n   then select `Qt > Qt 5.15.1` or a newer version. Under `Developer and Designer Tools`, `Qt Creator Debugger Support`,\n   `Debugging Tools for Windows`, `cmake`, and `Ninja` should be selected automatically.\n\n3. Open the project file `C:\\groops\\gui\\groopsGui.pro` in Qt Creator and build the project.\n\n### Generic Mapping Tools (GMT)\n\nThe Generic Mapping Tools (GMT) are an optional dependency of GROOPS and enable the generation of high-quality\nfigures.\nGMT provides [Windows binaries](https://github.com/GenericMappingTools/gmt/releases) which can be easily installed.\nThe current GROOPS release is tested against GMT version 6.4.0.\n\n### Windows post-installation steps\n\nAfter the installation of GROOPS and GROOPS GUI, we recommend some post-installation configuration steps to make\nworking with GROOPS easier.\n\n1. To use the GROOPS and GROOPS GUI binaries without directory prefix, you have to add the required\n   directories to the system path.\n\n    1.1. Open the Control Panel through the Windows Start Menu: `Windows System > Control Panel`.\n\n    1.2. In the Control Panel window, go to `User Accounts > User Accounts`.\n\n    1.3. There you should click on `Change my environment variables`, which will open a new window.\n\n    1.4. In the environment variable window, select `Path` and click `Edit...`. A pop-up window will appear\n    where you can add the following directories to your system path:\n    ```\n    \"C:\\msys64\\mingw64\\bin\"\n    \"C:\\groops\\bin\"\n    \"C:\\Program Files\\Microsoft MPI\\Bin\"\n    ```\n    In case you manually compiled the GUI, additionally add the directory:\n    ```\n    \"C:\\Qt\\5.15.1\\mingw81_64\\bin\"\n    ```\n    The `mingw64` path should be in the first line of the list.\n\n2. *(Optional)* Set the environment variable `OPENBLAS_NUM_THREADS` or `OMP_NUM_THREADS` to the number of threads to use for matrix operations.\n\n    :warning: When running GROOPS in parallel, threaded BLAS/LAPACK libraries may conflict with MPI processes and cause a deterioration of performance. In that case, the number of threads for matrix operations should be set to 1.\n\nGROOPS depends on data files such as Earth rotation, Love numbers, and wavelet coefficients.\nAn initial data set that is regularly updated is available on [our FTP server](https://ftp.tugraz.at/pub/ITSG/groops/).\nYou can choose between downloading the data directory or a single [zip file](https://ftp.tugraz.at/pub/ITSG/groops/data.zip) with the same content.\n\n## Linux\n\nMost Linux distributions provide all GROOPS dependencies through their package managers.\nWe provide a detailed installation guide for Ubuntu and OpenSUSE, the installation steps\nare however very similar for other distributions.\n\n### Ubuntu\n\nThe installation procedure for Ubuntu is representative for all Debian based distributions,\nhowever the individual package names may differ.\nCheck your distribution's documentation to find the correct packages.\nThis installation guide assumes that the GROOPS source code is located in `$HOME/groops`.\n\n1. First, make sure your system is up to date:\n    ```\n    sudo apt update && sudo apt upgrade\n    ```\n\n2. Install dependencies and build tools:\n    ```\n    sudo apt-get install g++ gfortran cmake libexpat1-dev libopenblas-dev\n    ```\n\n3. *(Optional)* Install the NetCDF development package:\n    ```\n    sudo apt-get install libnetcdf-dev\n    ```\n\n4. *(Optional)* Install liberfa development packages:\n    ```\n    sudo apt-get install liberfa-dev\n    ```\n\n5. *(Optional)* Install MPI development packages:\n    ```\n    sudo apt-get install mpi-default-dev\n    ```\n\n6. Create the build directory and compile GROOPS:\n    ```\n    mkdir $HOME/groops/source/build && cd $HOME/groops/source/build\n    cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/groops\n    make -j4\n    make install\n    ```\n\n7. Make sure to also read the [post-installation steps](#linux-post-installation-steps).\n\n#### Graphical User Interface (GUI)\n\nThe GROOPS GUI depends on Qt packages.\nTo install the required packages, run:\n```\nsudo apt-get install qtbase5-dev\n```\nThen, change into the `gui` directory and compile the source code:\n```\ncd $HOME/groops/gui\nqmake\nmake\n```\n\n#### Generic Mapping Tools (GMT)\n\nUbuntu provides packages for the Generic Mapping Tools:\n```\nsudo apt-get install gmt gmt-gshhg\n```\n\n### OpenSUSE\n\n1. First, make sure your system is up to date:\n    ```\n    sudo zypper up\n    ```\n2. Install dependencies and build tools:\n    ```\n    sudo zypper install gcc-c++ gcc-fortran cmake libexpat-devel openblas-devel\n    ```\n\n3. *(Optional)* Install the NetCDF development package:\n    ```\n    sudo zypper install netcdf-devel\n    ```\n\n4. *(Optional)* Install liberfa development packages:\n\n    ```\n    sudo zypper install erfa-devel\n    ```\n\n5. *(Optional)* Install MPI development packages:\n    ```\n    sudo zypper install openmpi4 openmpi4-devel\n    ```\n\n6. Create the build directory and compile GROOPS:\n    ```\n    mkdir $HOME/groops/source/build && cd $HOME/groops/source/build\n    cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/groops\n    make -j4\n    make install\n    ```\n\n7. Make sure to also read the [post-installation steps](#linux-post-installation-steps).\n\n#### Graphical User Interface (GUI)\n\nThe GROOPS GUI depends on Qt packages.\nTo install the required packages, run:\n```\nsudo zypper install libqt5-qtbase-devel\n```\nThen, change into the `gui` directory and compile the source code:\n```\ncd $HOME/groops/gui\nqmake-qt5\nmake\n```\n\n#### Generic Mapping Tools (GMT)\n\nThe OpenSUSE packages for the Generic Mapping Tools are available in the `GEO` repository\n(change OpenSUSE release version if necessary):\n```\nsudo zypper addrepo http://download.opensuse.org/repositories/Application:/Geo/15.4/ GEO\n```\nThen install the packages:\n```\nsudo zypper install GMT GMT-doc GMT-coastlines\n```\n\n### Arch Linux\n\nGROOPS is packaged for the [Arch User Repository](https://wiki.archlinux.org/index.php/Arch_User_Repository).\nYou can install the [groops-git](https://aur.archlinux.org/packages/groops-git/) package providing the core GROOPS executables,\nand the [groopsgui-git](https://aur.archlinux.org/packages/groopsgui-git/) package providing the GUI and documentation.\n\nThe easiest way to do this is through an [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers). If you are using `yay`,\nfor example, you can install GROOPS and the GUI by executing:\n```\nyay -S groops-git groopsgui-git\n```\n\nIf you want to develop for GROOPS, a manual installation is preferable.\nThis installation guide assumes that the GROOPS source code is located in `$HOME/groops`.\n\n1. First, make sure your system is up to date:\n    ```\n    sudo pacman -Syu\n    ```\n2. Install dependencies and build tools:\n    ```\n    sudo pacman -S cmake gcc gcc-gfortran expat lapack zlib\n    ```\n3. *(Optional)* Install the NetCDF development package:\n    ```\n    sudo pacman -S netcdf-cxx\n    ```\n4. *(Optional)* Install liberfa development packages. liberfa is available as an [AUR package](https://aur.archlinux.org/packages/erfa/).\n\n5. *(Optional)* Install an MPI development package, for example `openmpi`:\n    ```\n    sudo pacman -S openmpi\n    ```\n6. Create the build directory and compile GROOPS.\n    ```\n    mkdir $HOME/groops/source/build && cd $HOME/groops/source/build\n    cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/groops\n    make -j4\n    make install\n    ```\n7. Make sure to also read the [post-installation steps](#linux-post-installation-steps).\n\n#### Graphical User Interface (GUI)\n\nThe GROOPS GUI depends on Qt packages.\nTo install the required packages, run:\n```\nsudo pacman -S qt5-base\n```\nThen, change into the `gui` directory and compile the source code:\n```\ncd $HOME/groops/gui\nqmake\nmake\n```\n\n#### Generic Mapping Tools (GMT)\n\nThe Generic Mapping Tools are available from the [Arch User Repository](https://wiki.archlinux.org/index.php/Arch_User_Repository).\nInstall the [gmt](https://archlinux.org/packages/extra/x86_64/gmt/) and [gmt-coast](https://aur.archlinux.org/packages/gmt-coast) packages.\n\n### Linux post-installation steps\n\nAfter the installation of GROOPS and GROOPS GUI, we recommend some post-installation configuration steps to make\nworking with GROOPS easier.\n\n1. To use the GROOPS and GROOPS GUI binaries without directory prefix, you have to add the required\n   directories to the system path:\n\n   ```\n   echo \"export PATH=$PATH:$HOME/groops/bin\" >> $HOME/.bashrc\n   source $HOME/.bashrc\n   ```\n\n2. *(Optional)* Set the environment variable `OPENBLAS_NUM_THREADS` or `OMP_NUM_THREADS`  to the number of threads to use for matrix operations.\n\n    :warning: When running GROOPS in parallel, threaded BLAS/LAPACK libraries may conflict with MPI processes and cause a deterioration of performance. In that case, the number of threads for matrix operations should be set to 1.\n\nGROOPS depends on data files such as Earth rotation, Love numbers, and wavelet coefficients.\nAn initial data set that is regularly updated is available on [our FTP server](https://ftp.tugraz.at/pub/ITSG/groops/).\nYou can choose between downloading the data directory or a single [zip file](https://ftp.tugraz.at/pub/ITSG/groops/data.zip) with the same content.\n\n## Disabling external source files\n\nWhile GROOPS is intended to be a standalone software package, some functionality depends on external software.\nInformation about external source code contained in the repository which is licensed differently can be found in the\n[corresponding README](https://github.com/groops-devs/groops/blob/main/source/external/README.md).\n\nTo compile GROOPS without these external source files, variables can be passed to CMake in the configuration step,\nfor example:\n```\ncmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/groops -DDISABLE_IERS=TRUE\n```\nAvailable variables are ```DISABLE_HWM14```, ```DISABLE_NRLMSIS```, ```DISABLE_JB2008```,\n```DISABLE_IGRF```, ```DISABLE_IERS```, ```DISABLE_ERFA```, ```DISABLE_Z```, and ```DISABLE_NETCDF```.\nSetting these to ```TRUE``` will skip compilation of the respective source files.\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "![GROOPS Logo](https://github.com/groops-devs/groops/blob/main/docs/html/static/groops_banner.png)\n\n> [!IMPORTANT]\n> The link for retrieving data has changed to [ftp.tugraz.at/pub/ITSG/groops](https://ftp.tugraz.at/pub/ITSG/groops).\n\nThe Gravity Recovery Object Oriented Programming System (GROOPS) is a software toolkit written in C++\nthat enables the user to perform core geodetic tasks.\nKey features of the software include gravity field recovery from satellite and terrestrial data,\nthe determination of satellite orbits from global navigation satellite system (GNSS) measurements,\nand the processing of GNSS constellations and ground station networks.\n\nMost tasks and algorithms are (optionally) parallelized through the Message Passing Interface (MPI), thus\nthe software enables a smooth transition from single-CPU desktop computers to large distributed\ncomputing environments for resource intensive tasks.\n\nFor an easy and intuitive setup of complex workflows, GROOPS contains a graphical\nuser interface where configuration files can be created and edited.\n\n- [Citing GROOPS](#citing-groops)\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n- [Contributing](#contributing)\n- [License](#license)\n- [Contributors](#contributors)\n\n## Citing GROOPS\n\nIf you use data sets computed with GROOPS in a publication or publish the data itself,\nplease cite our [reference paper](https://doi.org/10.1016/j.cageo.2021.104864):\n\n*Mayer-Guerr, T., Behzadpour, S., Eicker, A., Ellmer, M., Koch, B., Krauss, S., Pock, C., Rieser, D., Strasser, S., Suesser-Rechberger, B., Zehentner, N.,  Kvas, A. (2021). GROOPS: A software toolkit for gravity field recovery and GNSS processing. Computers & Geosciences, 104864. https://doi.org/10.1016/j.cageo.2021.104864*\n\n```\n@article{Mayer-Gurr2021,\n  author = {Mayer-Guerr, Torsten and Behzadpour, Saniya and Eicker, Annette and Ellmer, Matthias and Koch, Beate and Krauss, Sandro and Pock, Christian and Rieser, Daniel and Strasser, Sebastian and Suesser-Rechberger, Barbara and Zehentner, Norbert and Kvas, Andreas},\n  doi = {https://doi.org/10.1016/j.cageo.2021.104864},\n  issn = {0098-3004},\n  journal = {Computers & Geosciences},\n  keywords = {GNSS processing,Gravity field recovery,Orbit determination},\n  pages = {104864},\n  title = {{GROOPS: A software toolkit for gravity field recovery and GNSS processing}},\n  url = {https://www.sciencedirect.com/science/article/pii/S009830042100159X},\n  year = {2021}\n}\n```\n\n## Installation\n\nGROOPS is written in C++ and contains some legacy Fortran code.\nTo enable an intuitive interaction with the software, GROOPS includes a\ngraphical user interface (GUI).\nThe GUI is also written in C++ and depends on the Qt toolkit.\n\nA detailed installation guide for Microsoft Windows and various Linux distributions can be found\non the [Installation page](https://github.com/groops-devs/groops/blob/main/INSTALL.md).\n\n## Getting Started\n\nAfter a successful installation our [Documentation](https://groops-devs.github.io/groops/html/index.html)\nis the perfect way to get familiar with the different features of GROOPS.\n\nGROOPS depends on data files such as Earth rotation, Love numbers, and wavelet coefficients.\nAn initial data set that is regularly updated is available on [our FTP server](https://ftp.tugraz.at/pub/ITSG/groops/).\nYou can choose between downloading the data directory or\na single [zip file](https://ftp.tugraz.at/pub/ITSG/groops/data.zip) with the same content.\n\n## Contributing\n\nWe appreciate all contributions such as improving the documentation, reporting or fixing bugs,\nimplementing new features. Answering user questions in the\n[Discussions](https://github.com/groops-devs/groops/discussions) section is another great way\nof contributing to the GROOPS community.\n\nIf you encounter a bug, please let us know by [filing an issue](https://github.com/groops-devs/groops/issues).\nPlease include as much information as possible on how to reproduce the bug\nand about your software environment (operating system, compiler version, GROOPS version).\n\nIf you want to provide a bug fix or implement a new features,\nplease get in contact with us in the [Discussions](https://github.com/groops-devs/groops/discussions)\nbefore you start coding.\n\n## License\n\nGROOPS is licensed under GPLv3, as found in the [LICENSE](https://github.com/groops-devs/groops/blob/main/LICENSE) file.\nThis license applies to all files in the repository unless otherwise indicated.\n\nInformation about external source code contained in the repository which is licensed differently can be found in the\n[corresponding README](https://github.com/groops-devs/groops/blob/main/source/external/README.md).\n\n## Contributors\n\nParts of GROOPS originate from developments in the Astronomical, Physical and Mathematical Geodesy Group\nat the University of Bonn, Germany.\nSince 2010 it is developed and maintained at Graz University of Technology, Austria.\n\nHere is a list of current and past contributors:\n\n[Torsten Mayer-Guerr](https://github.com/tmayerguerr), Annette Eicker, Daniel Rieser, Norbert Zehentner,\nChristian Pock, [Matthias Ellmer](https://github.com/x49), Beate Koch, [Andreas Kvas](https://github.com/akvas), Saniya Behzadpour,\n[Sebastian Strasser](https://github.com/sestras), Sandro Krauss, Barbara Suesser-Rechberger,\n[Patrick Dumitraschkewitz](https://github.com/zhedumi), Felix Oehlinger, [Andreas Strasser](https://github.com/ajs8041)\n"
  },
  {
    "path": "bin/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "docs/documentation.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <!-- This code is licensed under GNU GPL v3 -->\n    <!-- You are allowed to freely copy, distribute and use this code, but removing author credit is strictly prohibited -->\n    <!-- Generated by http://insider.zone/tools/client-side-url-redirect-generator/ -->\n\n    <!-- REDIRECTING STARTS -->\n    <link rel=\"canonical\" href=\"html/index.html\"/>\n    <noscript>\n        <meta http-equiv=\"refresh\" content=\"0;URL=html/index.html\">\n    </noscript>\n    <!--[if lt IE 9]><script type=\"text/javascript\">var IE_fix=true;</script><![endif]-->\n    <script type=\"text/javascript\">\n        var url = \"html/index.html\";\n        if(typeof IE_fix != \"undefined\") // IE8 and lower fix to pass the http referer\n        {\n            document.write(\"redirecting...\"); // Don't remove this line or appendChild() will fail because it is called before document.onload to make the redirect as fast as possible. Nobody will see this text, it is only a tech fix.\n            var referLink = document.createElement(\"a\");\n            referLink.href = url;\n            document.body.appendChild(referLink);\n            referLink.click();\n        }\n        else { window.location.replace(url); } // All other browsers\n    </script>\n    <!-- Credit goes to http://insider.zone/ -->\n    <!-- REDIRECTING ENDS -->\n  </head>\n  <body>\n    <a href=\"html/index.html\">link to documentation</a>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/documentationSource.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <!-- This code is licensed under GNU GPL v3 -->\n    <!-- You are allowed to freely copy, distribute and use this code, but removing author credit is strictly prohibited -->\n    <!-- Generated by http://insider.zone/tools/client-side-url-redirect-generator/ -->\n\n    <!-- REDIRECTING STARTS -->\n    <link rel=\"canonical\" href=\"source/html/index.html\"/>\n    <noscript>\n        <meta http-equiv=\"refresh\" content=\"0;URL=source/html/index.html\">\n    </noscript>\n    <!--[if lt IE 9]><script type=\"text/javascript\">var IE_fix=true;</script><![endif]-->\n    <script type=\"text/javascript\">\n        var url = \"source/html/index.html\";\n        if(typeof IE_fix != \"undefined\") // IE8 and lower fix to pass the http referer\n        {\n            document.write(\"redirecting...\"); // Don't remove this line or appendChild() will fail because it is called before document.onload to make the redirect as fast as possible. Nobody will see this text, it is only a tech fix.\n            var referLink = document.createElement(\"a\");\n            referLink.href = url;\n            document.body.appendChild(referLink);\n            referLink.click();\n        }\n        else { window.location.replace(url); } // All other browsers\n    </script>\n    <!-- Credit goes to http://insider.zone/ -->\n    <!-- REDIRECTING ENDS -->\n  </head>\n  <body>\n    <a href=\"source/html/index.html\">link to documentation</a>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/html/Accelerometer2GraceL1b.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Accelerometer2GraceL1b</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Accelerometer2GraceL1b</h1><p>\n\nThis program converts accelerometer data from the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ACCELEROMETER)</a>\nformat into GRACE SDS format.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>.\nThe <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables <code>{epochmin}</code>, <code>{epochmax}</code>,\nand <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>ACT1B</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileHeader</div></div></td><td>filename</td><td>YAML Header, {epochmin}, {epochmax}, {epochcount} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAngularAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileFlags</div></div></td><td>filename</td><td>MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">satelliteId</div></div></td><td>string</td><td>A, B, C or D</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/AutoregressiveModel2CovarianceMatrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - AutoregressiveModel2CovarianceMatrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>AutoregressiveModel2CovarianceMatrix</h1><p>\n\nThis program computes the covariance structure of a random process represented by an AR model sequence.\nThe covariance matrix is determined by accumulating the normal equations of all AR models in <strong class=\"groops-config-element\">autoregressiveModelSequence</strong>\nand inverting the combined normal equation matrix.\nFor each output file in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovarianceMatrix</a>,\nthe covariance matrix of appropriate time lag is saved (the first file contains the auto-covariance,\nsecond file cross covariance and so on). The matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\Sigma(t-h, t)$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfileCovarianceMatrix</div></div></td><td>filename</td><td>covariance matrix for each lag</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">autoregressiveModelSequence</div></div></td><td><a href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a></td><td>AR model sequence</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/BerneseKinematic2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - BerneseKinematic2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>BerneseKinematic2Orbit</h1><p>\n\nRead kinematic orbits in Bernese format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCovariance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>from TRF to CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Champ2AccStar.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Champ2AccStar</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Champ2AccStar</h1><p>\n\nThis program reads in CHAMP accelerometer and star camera data given in the special CHAMP format.\nIn case of CHAMP accelerometer and star camera data is both stored in one file.\nA description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularAcceleration</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Champ2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Champ2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Champ2Orbit</h1><p>\n\nThis program reads in CHAMP precise science orbits in the special CHORB format.\nA description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Cosmic2OrbitStar.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Cosmic2OrbitStar</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Cosmic2OrbitStar</h1><p>\n\nThis program reads in cosmic orbit and star camera data given in the CHAMP format.\nIn case of cosmic orbit and star camera data is stored in one file.\nA description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/CovarianceFunction2DigitalFilter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - CovarianceFunction2DigitalFilter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>CovarianceFunction2DigitalFilter</h1><p>\n\nComputes digital filter coefficients for a <a class=\"groops-class\" href=\"digitalFilterType.html\">digital filter</a> of given degree and\norder. The filter coefficients are computed by fitting them to an approximated\nimpulse response represented by the cholesky factor of the covariance matrix.</p><p>The parameter <strong class=\"groops-config-element\">warmup</strong> determines from which element of the cholesky matrix the\ncoefficients (default: half the covariance length) are fitted.</p><p>Per default, the program computes filter coefficients which generate colored noise\nwhen applied to a white noise sequence. When <strong class=\"groops-config-element\">decorrelationFilter</strong> is set,\na decorrelation filter is computed which yields white noise when applied to colored noise.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileFilter</div></div></td><td>filename</td><td>filter coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCovariance</div></div></td><td>filename</td><td>first column: time steps, following columns: covariance functions</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">column</div></div></td><td>uint</td><td>Column with covariance function to be fitted</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">warmup</div></div></td><td>uint</td><td>number of samples until diagonal of Cholesky factor is flat (default: half covariance length)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">numeratorDegree</div></div></td><td>uint</td><td>Maximum degree of numerator polynomial (MA constituent)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">denominatorDegree</div></div></td><td>uint</td><td>Maximum degree of denominator polynomial (AR constitutent)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">decorrelationFilter</div></div></td><td>boolean</td><td>compute a decorrelation filter</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/CovarianceFunction2PowerSpectralDensity.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - CovarianceFunction2PowerSpectralDensity</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>CovarianceFunction2PowerSpectralDensity</h1><p>\n\nOne sided Power Spectral Density (PSD) from a covariance function. The first column of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceFunction</a>\nshould contain the time lag in seconds.\nMultiple covariance functions (in the following column)s are supported.\nThe output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> with first column contains the frequency $[Hz]$ and the other columns the PSD $[unit^2/Hz]$.</p><p>Conversion between covariance function $c_j$ and PSD $p_k$ is performed by discrete cosine transformation:\n\\[\np_k = 2\\Delta t\\left(c_0 + c_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 c_j \\cos(\\pi jk/(n-1))\\right).\n\\]\nSee also <a class=\"groops-program\" href=\"PowerSpectralDensity2CovarianceFunction.html\">PowerSpectralDensity2CovarianceFunction</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePSD</div></div></td><td>filename</td><td>first column: frequency [Hz], other columns PSD [unit^2/Hz]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>first column: time steps, following columns: covariance functions</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/CovarianceMatrix2AutoregressiveModel.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - CovarianceMatrix2AutoregressiveModel</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>CovarianceMatrix2AutoregressiveModel</h1><p>\n\nThis program computes a VAR(p) model from empirical covariance matrices.\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceMatrix</a> represent the covariance structure of the process:\nthe first file should contain the auto-covariance, the second the cross-covariance of lag one,\nthe next cross-covariance of lag two and so on.</p><p>Cross-covariance matrices $\\Sigma_{\\Delta_k}$ are defined as the cross-covariance between epoch $t-k$ and $t$.\nIf the process realizations $x_{t}$ are arrange by ascending time stamps\n($\\{\\dots, x_{t-2}, x_{t-1}, x_{t}, x_{t+1}, x_{t+2},\\dots\\}$),\nthe covariance structure of the (stationary) process is therefore given by\n\\[\n\\begin{bmatrix}\n\\Sigma & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\cdots \\\\\n\\Sigma_{\\Delta_1}^T & \\Sigma & \\Sigma_{\\Delta_1} &  \\cdots \\\\\n\\Sigma_{\\Delta_2}^T & \\Sigma_{\\Delta_1}^T & \\Sigma & \\cdots \\\\\n\\vdots & \\vdots & \\vdots & \\ddots \\\\\n\\end{bmatrix}.\n\\]\nThe estimate AR model is saved as single matrix <strong class=\"groops-config-element\">outputfileAutoregressiveModel</strong> according to the GROOPS AR model conventions.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAutoregressiveModel</div></div></td><td>filename</td><td>coefficients and white noise covariance of AR(p) model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileCovarianceMatrix</div></div></td><td>filename</td><td>file name of covariance matrix</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/CovarianceMatrix2Correlation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - CovarianceMatrix2Correlation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>CovarianceMatrix2Correlation</h1><p>\n\nThis program computes the pearson correlation coefficient\n\\[\n  \\rho_{ij} = \\frac{\\sigma_{ij}}{\\sigma_i \\sigma_j}\n\\]from a given covariance matrix stored in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceMatrix</a>.\nThe result is stored in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCorrelationMatrix</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCorrelationMatrix</div></div></td><td>filename</td><td>correlation matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCovarianceMatrix</div></div></td><td>filename</td><td>covariance matrix</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Cpf2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Cpf2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Cpf2Orbit</h1><p>\n\nConverts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html\">CPF file</a>\nand writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.</p><p>The time format of the CPF file is UTC.\nThe coordinate system used in the CPF format is usually represented in TRF.\nIf <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided the data are transformed\nfrom terrestrial (TRF) to celestial reference frame (CRF).</p><p>See also <a class=\"groops-program\" href=\"Orbit2Cpf.html\">Orbit2Cpf</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td>SLR CPF file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Crd2NormalPoints.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Crd2NormalPoints</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Crd2NormalPoints</h1><p>\n\nConverts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/formats/crd.html\">CRD file</a>\nand writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like\ntemperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a>\nincluding normal point data like range, accuracy, redundancy, wavelength and window size.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalPoints</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMeteorological</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSlrData</div></div></td><td>filename</td><td>SLR CRD files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Cstg2NormalPoints.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Cstg2NormalPoints</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Cstg2NormalPoints</h1><p>\n\nConverts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html\">CSTG file</a> provided by the <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a>\nand writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like\ntemperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a>\nincluding normal point data like range, accuracy, redundancy, wavelength and window size.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalPoints</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMeteorological</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSlrData</div></div></td><td>filename</td><td>SLR CSTG file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DigitalFilter2FrequencyResponse.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DigitalFilter2FrequencyResponse</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DigitalFilter2FrequencyResponse</h1><p>\n\nCompute amplitude-, phase-, group delay and frequency response of a <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> cascade.\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileResponse</a> is a matrix with following columns:\nfreq $[Hz]$, ampl, phase $[rad]$, group delay $[-]$, real, imag.</p><p>When <strong class=\"groops-config-element\">unwrapPhase</strong> is set to true, $2\\pi$ jumps of the phase response are removed before writing the output to file.</p><p>The response of the filter cascade is given by the product of each individual frequency response:\n\\[\n  H(f) = \\prod_f H_j(f).\n\\]Amplitude and phase response are computed from the frequency response via\n\\[\n  A(f) = |H(f)| \\hspace{5pt}\\text{and}\\hspace{5pt} \\Phi(f) = \\arctan \\frac{\\mathcal{I}(H(f))}{\\mathcal{R}(H(f))}.\n\\]The group delay is computed by numerically differentiating the phase response\n\\[\n  \\tau_g(f_k) = \\frac{1}{2} \\left[\\frac{\\Phi(f_k) - \\Phi(f_{k-1})}{2\\pi(f_k-f_{k-1})} + \\frac{\\Phi(f_{k+1}) - \\Phi(f_{k})}{2\\pi(f_{k+1}-f_{k})}\\right] \\approx \\frac{d\\Phi}{df}\\frac{df}{d\\omega}.\n\\]The frequency vector for a <strong class=\"groops-config-element\">length</strong> $N$ and a <strong class=\"groops-config-element\">sampling</strong> $\\Delta t$ is given by\n\\[\n  f_k = \\frac{k}{N \\Delta t}, \\hspace{15pt} k \\in \\{0, \\dots, \\left\\lfloor\\frac{N+2}{2}\\right\\rfloor-1\\}.\n\\]\nSee also <a class=\"groops-program\" href=\"DigitalFilter2ImpulseResponse.html\">DigitalFilter2ImpulseResponse</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileResponse</div></div></td><td>filename</td><td>columns: freq [Hz], ampl, phase [rad], group delay [-], real, imag</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">digitalFilter</div></div></td><td><a href=\"digitalFilterType.html\">digitalFilter</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">length</div></div></td><td>uint</td><td>length of the data series in time domain</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>sampling to determine frequency [seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">skipZeroFrequency</div></div></td><td>boolean</td><td>omit zero frequency when writing to file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">unwrapPhase</div></div></td><td>boolean</td><td>unwrap phase response</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DigitalFilter2ImpulseResponse.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DigitalFilter2ImpulseResponse</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DigitalFilter2ImpulseResponse</h1><p>\n\nImpulse response of a <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> cascade.\nThe impulse response is computed by filtering a sequence with <strong class=\"groops-config-element\">length</strong> samples and a unit impulse at index <strong class=\"groops-config-element\">pulseLag</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileResponse</a> is a matrix with the time stamp (zero at <strong class=\"groops-config-element\">pulseLag</strong>)\nin the first column and the impulse response $h_k$ in the second column.</p><p>See also <a class=\"groops-program\" href=\"DigitalFilter2FrequencyResponse.html\">DigitalFilter2FrequencyResponse</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileResponse</div></div></td><td>filename</td><td>columns: time [seconds], response</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">digitalFilter</div></div></td><td><a href=\"digitalFilterType.html\">digitalFilter</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">length</div></div></td><td>uint</td><td>length of the impulse response</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">pulseLag</div></div></td><td>uint</td><td>start of the pulse in the data series</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonAdmittance2SupplementaryFiles.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonAdmittance2SupplementaryFiles</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonAdmittance2SupplementaryFiles</h1><p>\n\nThe publication of an ocean tide model includes not only the atlas\nin the form of spherical harmonics coefficients,\nbut also the matrix of Doodson multipliers (<strong class=\"groops-config-element\">outputfileDoodsonMatrix</strong>)\nand the <strong class=\"groops-config-element\">outputfileAdmittanceMatrix</strong>.</p><p>The <strong class=\"groops-config-element\">outputfileMajorTideList</strong> contains the <strong class=\"groops-config-element\">fileNames</strong>\nfor each contituent.\nThe required information is taken from the\n<a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.</p><p>See also <a class=\"groops-program\" href=\"DoodsonHarmonics2PotentialCoefficients.html\">DoodsonHarmonics2PotentialCoefficients</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileMajorTideList</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fileNames</div></div></td><td>filename</td><td>template for fileList, variables: doodson, name, cossin</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileDoodsonMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAdmittanceMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAdmittance</div></div></td><td>filename</td><td>interpolation of minor constituents</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonAdmittanceInterpolation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonAdmittanceInterpolation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonAdmittanceInterpolation</h1><p>\n\nTo visualize the interpolation of the minor tides.\nThe output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> with the first column containing the tidal frequency,\nthe second column is the tide generating amplitude (from <a class=\"groops-class\" href=\"fileFormat_tideGeneratingPotential.html\">inputfileTideGeneratingPotential</a>), and the following\ncolumns the contribution of the major tides to the this tidal frequency as defined in in <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/doodsonAdmittanceInterpolation.png\" alt=\"doodsonAdmittanceInterpolation\"><figcaption class=\"center\">Figure: Linear interpolation of minor tides in the diurnal band.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAdmittance</div></div></td><td>filename</td><td>interpolation of minor constituents</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonAdmittanceTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonAdmittanceTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonAdmittanceTimeSeries</h1><p>\n\nTo visualize the interpolation of the minor tides it computes cosine multipliers of all major tides.\nWithout admittance this would be a simple cos oscillation.\nThe <strong class=\"groops-config-element\">outputfileTimeSeries</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) containining the cos of all the major tides.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/doodsonAdmittanceTimeSeries.png\" alt=\"doodsonAdmittanceTimeSeries\"><figcaption class=\"center\">Figure: Cosine of the Mf tidal frequency with modulation from the interpolated minor tides.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>MISCVALUES (cos of major tides, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAdmittance</div></div></td><td>filename</td><td>cos/sin multipliers of the major tides</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonArguments2TimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonArguments2TimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonArguments2TimeSeries</h1><p>\n\nTime series of doodson/fundamental arguments.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> contains the six Doodson arguments,\nfollowed by the five fundamental arguments in radians.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>each epoch: 6 doodson args, 5 fundamental args [rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonHarmonics2GriddedAmplitudeAndPhase.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonics2GriddedAmplitudeAndPhase</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonics2GriddedAmplitudeAndPhase</h1><p>\n\nThis program reads a <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonics</a> and evaluates a single tidal\nconstituent selected by <strong class=\"groops-config-element\">dooddson</strong> (Doodson number or Darwin´s name, e.g. 255.555 or M2).\nThis program computes the amplitude and phase from the cos and sin coefficients on\na given <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The type of functional (e.g gravity anomalies or geoid heights)\ncan be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\nTo visualize the results use <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.</p><p><figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/doodsonHarmonics2GriddedAmplitudeAndPhase.png\" alt=\"doodsonHarmonics2GriddedAmplitudeAndPhase\"><figcaption class=\"center\">Figure: M2 amplitude and phase of FES2014b.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGrid</div></div></td><td>filename</td><td>ampl, phase [-pi,pi], cos, sin</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">doodson</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td>tidal constituent</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">filter</div></div></td><td><a href=\"sphericalHarmonicsFilterType.html\">sphericalHarmonicsFilter</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the values on grid are multiplied by this factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonHarmonics2IersPotential.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonics2IersPotential</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonics2IersPotential</h1><p>\n\nConvert doodson harmonics to IERS conventions according to FES2004.\ncf. <a href=\"ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\" target=\"_blank\">ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>according to IERS2010, chapter 6.3.2, footnote 7</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDoodsonHarmoncis</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">header</div></div></td><td>string</td><td>info for output header</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonHarmonics2IersWaterHeight.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonics2IersWaterHeight</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonics2IersWaterHeight</h1><p>\n\nConvert doodson harmonics to IERS conventions according to FES2004.\ncf. <a href=\"ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\" target=\"_blank\">ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>according to IERS2010, chapter 6.3.2, footnote 7</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDoodsonHarmoncis</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td>to compute Xi phase correction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">header</div></div></td><td>string</td><td>info for output header</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>data type of output values</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>e.g. from [m] to [cm]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonHarmonics2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonics2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonics2PotentialCoefficients</h1><p>\n\nThe <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonics</a> contains a Fourier series of a time variable\ngravitational potential at specific tidal frequencies (tides)\n\\[\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\theta_f(t)) + V_f^s(\\M x)\\sin(\\theta_f(t)),\n\\]where $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics expansions.\nIf set the expansions are limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong>\nand the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> is not a single file but a series of files.\nFor each spherical harmonics expansion $V_f^c(\\M x)$ and $V_f^s(\\M x)$ a separate file is created\nwhere the variables <strong class=\"groops-config-element\">variableLoopName</strong>, <strong class=\"groops-config-element\">variableLoopDoodson</strong>, <strong class=\"groops-config-element\">variableLoopCosSin</strong> are set accordingly.\nThe file name should contain these variables, e.g. <code>coeff.{name}.{doodson}.{cossin}.gfc</code>.</p><p>If <strong class=\"groops-config-element\">applyXi</strong> the Doodson-Warburg phase correction (see IERS conventions) is applied to the cos/sin\npotentialCoefficients before.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopName</div></div></td><td>string</td><td>variable with darwins's name of each constituent</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopDoodson</div></div></td><td>string</td><td>variable with doodson code of each constituent</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCosSin</div></div></td><td>string</td><td>variable with 'cos' or 'sin' of each constituent</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of each constituent (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of constituents</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td>to compute Xi phase correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">applyXi</div></div></td><td>boolean</td><td>apply Doodson-Warburg phase correction (see IERS conventions)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonHarmonicsCalculateAdmittance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonicsCalculateAdmittance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonicsCalculateAdmittance</h1><p>\n\nComputes the admittance function to interpolate minor tides from\ntides given in <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonics</a>\nusing <a class=\"groops-class\" href=\"fileFormat_tideGeneratingPotential.html\">inputfileTideGeneratingPotential</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAdmittance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td>TGP</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">threshold</div></div></td><td>double</td><td>[m^2/s^2] only interpolate tides with TGP greater than threshold</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">degreeInterpolation</div></div></td><td>uint</td><td>polynomial degree for interpolation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">degreeExtrapolation</div></div></td><td>uint</td><td>polynomial degree for extrapolation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">excludeDoodsonForInterpolation</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td>major tides not used for interpolation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/DoodsonHarmonicsChangePartialTides.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonicsChangePartialTides</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonicsChangePartialTides</h1><p>\n\nReads a file <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonic</a> and write it to\n<a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">outputfileDoodsonHarmonics</a>. If set the spherical harmonics\nexpansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.\nThe <a class=\"groops-class\" href=\"doodson.html\">useDoodson</a> and <a class=\"groops-class\" href=\"doodson.html\">ignoreDoodson</a> can be used\nto filter the partial types that will be exported.\nAdditional partial tides can be interpolated using the file <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAdmittance</div></div></td><td>filename</td><td>interpolation of minor constituents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">useDoodson</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td>use only these partial tides (additional tides will be interpolated)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">ignoreDoodson</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td>ignore these partial tides</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/EarthOrientationParameterTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - EarthOrientationParameterTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>EarthOrientationParameterTimeSeries</h1><p>\n\nComputes a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> (GPS time) of Earth Orientation Parameter (EOP).\nThe <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) contains the elements at each epoch in the following order:\n<ul>\n\n<li>$x_p$ [rad]\n</li><li>\n$y_p$ [rad]\n</li><li>\n$s_p$ [rad]\n</li><li>\n$UT1-UTC$ [seconds]\n</li><li>\nlength of day (LOD) [seconds]\n</li><li>\n$X$ [rad]\n</li><li>\n$Y$ [rad]\n</li><li>\n$S$ [rad]\n</li></ul>\n\nThe values are in situ values with all corrections and models applied. The time series can be used to\nprecompute Earth rotation with a low temporal resolution (e.g. 10 min) and reuse the file in\n<a class=\"groops-class\" href=\"earthRotationType.html#file\">earthRotation:file</a> to interpolate the data to the needed epochs\n(e.g. to rotate orbit data). As some Earth rotation models are quite slow this can accelerate the computation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEOP</div></div></td><td>filename</td><td>each row: mjd(GPS), xp, yp, sp, dUT1, LOD, X, Y, S</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/EarthRotaryVectorTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - EarthRotaryVectorTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>EarthRotaryVectorTimeSeries</h1><p>\n\nComputes a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> of Earth's rotary axis\nand its temporal derivative at <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> (GPS time).\nThe <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) contains the elements at each epoch in the following order:\n<ul>\n\n<li>$\\omega_x [rad/s]$\n</li><li>\n$\\omega_y [rad/s]$\n</li><li>\n$\\omega_z [rad/s]$\n</li><li>\n$\\dot{\\omega}_x [rad/s^2]$\n</li><li>\n$\\dot{\\omega}_y [rad/s^2]$\n</li><li>\n$\\dot{\\omega}_z [rad/s^2]$.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>wx, wy, wz [rad], dwx, dwy, dwz [rad/s^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inTRF</div></div></td><td>boolean</td><td>terrestrial reference frame, otherwise celestial</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/EclipseFactor2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - EclipseFactor2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>EclipseFactor2GriddedData</h1><p>\n\nThis program converts the output of a <a class=\"groops-class\" href=\"eclipseType.html\">eclipse</a> model on a given\n<a class=\"groops-class\" href=\"gridType.html\">grid</a>. The time for the evaluation can be specified in <strong class=\"groops-config-element\">time</strong>.\nThe values will be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong>\nand <strong class=\"groops-config-element\">inverseFlattening</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>eclipse factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/EnsembleAveragingScaleModel.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - EnsembleAveragingScaleModel</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>EnsembleAveragingScaleModel</h1><p>\n\nThis programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits from residuals.\nThe ensemble averaging method is used to characterize the average properties of signal shapes across all transit events.\nEach shape is assigned to one arc of 3 hours (default). This can be modefied by enabling <strong class=\"groops-config-element\">averagingInterval</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileScaleModel</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGrace1EclipseFactor</div></div></td><td>filename</td><td>GRACE-A eclipse factors computed with integrated orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGrace2EclipseFactor</div></div></td><td>filename</td><td>GRACE-B eclipse factors computed with integrated orbit</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGraceResiduals</div></div></td><td>filename</td><td>SST Residuals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeMargin</div></div></td><td>uint</td><td>epochs before eclipse mode</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">waveLength</div></div></td><td>uint</td><td>length of the sample wave</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">averagingInterval</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">nearestNeighborNumber</div></div></td><td>uint</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FileConvert.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FileConvert</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FileConvert</h1><p>\n\nConverts GROOPS file between different file formats (ASCII, XML, JSON, binary),\nsee <a class=\"groops-ref\" href=\"general.fileFormat.html\">file formats</a> for details.\nWith an additional extension of '.gz' files are directly compressed and uncompressed.\nIt prints also some information about the content.\nTherefore it can be used to get an idea about the content of binary files.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfile</div></div></td><td>filename</td><td>GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td>GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FileCreateDirectories.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FileCreateDirectories</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FileCreateDirectories</h1><p>\n\nCreates the directory and parent directories as needed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">directory</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FileMove.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FileMove</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FileMove</h1><p>\n\nMove/rename file or directory. If the <strong class=\"groops-config-element\">outputfile</strong> is an existing directory\nthe <strong class=\"groops-config-element\">inputfile</strong> is moved into it.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>target name or directory for the move/rename</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FileRemove.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FileRemove</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FileRemove</h1><p>\n\nRemove files or directories.\nDeletes also the content recursivley if one of <strong class=\"groops-config-element\">files</strong> is a directory.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">files</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FileTextCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FileTextCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FileTextCreate</h1><p>\n\nCreate text <strong class=\"groops-config-element\">outputfile</strong> containing <strong class=\"groops-config-element\">line</strong>s.\nThis program can be a powerful tool,\nif the <strong class=\"groops-config-element\">line</strong> is repeated with a <a class=\"groops-class\" href=\"loopType.html\">loop</a>\ntogether with the <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">line</div></div></td><td>string</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FilterMatrixWindowedPotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FilterMatrixWindowedPotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FilterMatrixWindowedPotentialCoefficients</h1><p>\n\nCreate a spherical harmonic window matrix. The window matrix $\\mathbf{W}$ is generated in space domain through\nspherical harmonic synthesis and analysis matrices.\nThe resulting linear operator can be written as\n\\[\n\\mathbf{W} = \\mathbf{K} \\mathbf{A} \\mathbf{\\Omega} \\mathbf{S} \\mathbf{K}^{-1}.\n\\]Here, $\\mathbf{K}$ is a diagonal matrix with the <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> coefficients on the main diagonal,\n$\\mathbf{S}$ is the spherical harmonic synthesis matrix, $\\mathbf{\\Omega}$ is defined by the values in\n<a class=\"groops-file\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> and the\nexpression <strong class=\"groops-config-element\">value</strong>, $\\mathbf{A}$ is the spherical harmonic analysis matrix.\nThe resulting window matrix is written to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file.</p><p>The spherical harmonic degree range, and coefficient numbering are defined by\n<strong class=\"groops-config-element\">minDegree</strong>, <strong class=\"groops-config-element\">maxDegree</strong>, and <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.</p><p>Note that a proper window function $\\mathbf{\\Omega}$ should contain values in the range [0, 1].\nThe window function $\\mathbf{\\Omega}$ can feature a smooth transition between 0 and 1 to avoid ringing effects.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileWindowMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>gridded data which defines the window function in space domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">value</div></div></td><td>expression</td><td>expression to compute the window function (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>kernel for windowing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme for solution vector</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/FunctionsCalculate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - FunctionsCalculate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>FunctionsCalculate</h1><p>\n\nThis program manipulates <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix files</a> with data in columns.\nIf several <strong class=\"groops-config-element\">inputfile</strong>s are given the data columns are copied side by side.\nAll <strong class=\"groops-config-element\">inputfile</strong>s must contain the same number of rows.\nThe columns are enumerated by <code>data0</code>, <code>data1</code>, &hellip; .</p><p>The content of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfile</a> is controlled by <strong class=\"groops-config-element\">outColumn</strong>.\nThe algorithm to compute the output is as follows:\nThe expressions in <strong class=\"groops-config-element\">outColumn</strong> are evaluated once for each row of the input.\nThe variables <code>data0</code>, <code>data1</code>, &hellip; are replaced by the according values from the input columns before.\nAdditional variables are available, e.g. <code>index</code>, <code>data0rms</code>, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\nIf no <strong class=\"groops-config-element\">outColumn</strong> are specified all input columns are used instead directly.</p><p>For a simplified handling <strong class=\"groops-config-element\">constant</strong>s can be defined by <code>name=value</code>, e.g. <code>annual=365.25</code>.\nIt is also possible to estimate <strong class=\"groops-config-element\">parameter</strong>s in a least squares adjustment.\nThe <strong class=\"groops-config-element\">leastSquares</strong> serves as template for observation equations for every row.\nThe expression <strong class=\"groops-config-element\">leastSquares</strong> is evaluated for each row in the <strong class=\"groops-config-element\">inputfile</strong>.\nThe variables <code>data0</code>, <code>data1</code>, &hellip; are replaced by the according values from the input columns before.\nIn the next step the parameters are estimated in order to minimize the expressions in <strong class=\"groops-config-element\">leastSquares</strong>\nin the sense of least squares.</p><p>Afterwards complete rows are removed if one of the <strong class=\"groops-config-element\">removalCriteria</strong> expressions for this row evaluates true (not zero).</p><p>An extra <strong class=\"groops-config-element\">statistics</strong> file can be generated with one row of data. For the computation of the <strong class=\"groops-config-element\">outColumn</strong> values\nall <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available (e.g. <code>data3mean</code>, <code>data4std</code>)\ninclusively the <strong class=\"groops-config-element\">constant</strong>s and estimated <strong class=\"groops-config-element\">parameter</strong>s but without the <code>data0</code>, <code>data1</code>, &hellip; itself.\nThe variables and the numbering of the columns refers to the <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfile</a>.</p><p>First example: To calculate the mean of two values at each row set <strong class=\"groops-config-element\">outColumn</strong> to <code>0.5*(data1+data0)</code>.</p><p>Second example: An input file contain a column with times and a column with values.\nTo remove a trend from the values define the <strong class=\"groops-config-element\">parameter</strong>s <code>trend</code> and <code>bias</code>.\nThe observation equation in <strong class=\"groops-config-element\">leastSquares</strong> is <code>data1 - (trend*data0+bias)</code>.\nFor output you can define the following columns for example:\n<ul>\n\n<li><strong class=\"groops-config-element\">outColumn</strong>=<code>data0</code>: points in time.\n</li><li>\n<strong class=\"groops-config-element\">outColumn</strong>=<code>data1</code>: the values itself.\n</li><li>\n<strong class=\"groops-config-element\">outColumn</strong>=<code>trend*data0+bias</code>: the linear fit.\n</li><li>\n<strong class=\"groops-config-element\">outColumn</strong>=<code>data1-trend*data0-bias</code>: the residuals.\n</li></ul>\n\nThe extra statistics file could contain in this case:\n<ul>\n\n<li><strong class=\"groops-config-element\">outColumn</strong>=<code>data0max-data0min</code>: time span.\n</li><li>\n<strong class=\"groops-config-element\">outColumn</strong>=<code>bias</code>: estimated parameter.\n</li><li>\n<strong class=\"groops-config-element\">outColumn</strong>=<code>trend</code>: estimated parameter.\n</li><li>\n<strong class=\"groops-config-element\">outColumn</strong>=<code>data3rms</code>: root mean square of the residuals.\n</li></ul>\n</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>, <a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>, <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">constant</div></div></td><td>expression</td><td>define a constant by name=value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameter</div></div></td><td>expression</td><td>define a parameter by name[=value]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">leastSquares</div></div></td><td>expression</td><td>try to minimize the expression by adjustment of the parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">removalCriteria</div></div></td><td>expression</td><td>row is removed if one criterion evaluates true.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outColumn</div></div></td><td>expression</td><td>expression to compute output columns (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">statistics</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>matrix with one row, columns are user defined</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">outColumn</div></div></td><td>expression</td><td>expression to compute statistics columns, data* are the outputColumns</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAntennaDefinition2ParameterVector.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAntennaDefinition2ParameterVector</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAntennaDefinition2ParameterVector</h1><p>\n\nEstimates parameters of a parametrization of <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>,\nwhich represents all antennas from <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>\nmatching the wildcard patterns of <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">serial</strong>, <strong class=\"groops-config-element\">radome</strong>.</p><p>The provided values at the area weighted grid points of the pattern of each gnssType are used as pseudo-observations.\nA subset of patterns can be selected with <a class=\"groops-class\" href=\"gnssType.html\">types</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> can be modified to the demands before with\n<a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.</p><p>See also <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSolution</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterNames</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antennaCenterVariations</div></div></td><td><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">types</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>if not set, all types in the file are used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">zeroNaN</div></div></td><td>boolean</td><td>treat NaN values as zero, otherwise values are ignored</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAntennaDefinition2Skyplot.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAntennaDefinition2Skyplot</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAntennaDefinition2Skyplot</h1><p>\n\nProduce a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">skyplot</a> of antenna center variations\nwhich can be plotted with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.</p><p>The first antenna from <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>\nmatching the wildcard patterns of <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">serial</strong>, <strong class=\"groops-config-element\">radome</strong> is used.</p><p>For each antenna pattern (gnssType) a separate data column is computed.\nA subset of patterns can be selected with <a class=\"groops-class\" href=\"gnssType.html\">types</a>.</p><p>Azimuth and elevation are written as ellipsoidal longitude and latitude in a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData file</a>.\nThe choosen ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are arbitrary but should be the same\nas in <a class=\"groops-class\" href=\"gridType.html\">grid</a> and <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.</p><p><figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/fileFormatGnssAntennaDefinition.png\" alt=\"fileFormatGnssAntennaDefinition\"><figcaption class=\"center\">Figure: Antenna Center Variations of ASH701945D\\_M for two frequencies of GPS and GLONASS</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>data column for each gnssType</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">types</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>if not set, all types in the file are used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAntennaDefinitionCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAntennaDefinitionCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAntennaDefinitionCreate</h1><p>\n\nCreate a <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GNSS antenna definition file</a> (Antenna Center Variations, ACV) consisting of multiple antennas.\nThe antennas can be created from scratch or can be selected from existing files.\nThis program can also be used to modify existing files.</p><p>Furthermore it can be used to create accuracy definition files containing azimuth and elevation dependent accuracy values for antennas.\nTo create an accuracy pattern for phase observations with <code>1 mm</code> accuracy at zenith and no azimuth dependency, define a\npattern with <strong class=\"groops-config-element\">type</strong>=<code>L</code>, <strong class=\"groops-config-element\">values</strong>=<code>0.001/cos(zenith/rho)</code>.</p><p>The antennas in <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaDefinition</a>\nare sorted by names and duplicates are removed (first one is kept).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAntennaDefinition</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAntennaNormalsConstraint.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAntennaNormalsConstraint</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAntennaNormalsConstraint</h1><p>\n\nApply constraints to <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a>\ncontaining <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>.\nUsually the antenna center variations are estimated together with other parameters\nlike station coordinates, signal biases and slant TEC in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.\nThis results in a rank deficient matrix as not all parameters can be separated.\nThe deficient can be solved by adding pseudo observation equations as constraints.</p><p>To separate antenna center variations and signal biases\napply <strong class=\"groops-config-element\">constraint:mean</strong> for each GNSS <a class=\"groops-class\" href=\"gnssType.html\">type</a>.\nThe observation equation for the integral mean of antenna center variations (ACV)\nin all azimuth $A$ and elevation $E$ dependent directions\n\\[\n  0 = \\iint ACV(A,E)\\, d\\Phi \\approx \\sum_i ACV(A_i,E_i)\\, \\Delta\\Phi_i\n\\]is approximated by a grid defined by\n<strong class=\"groops-config-element\">deltaAzimuth</strong>, <strong class=\"groops-config-element\">deltaZenith</strong>, and <strong class=\"groops-config-element\">maxZenith</strong>.</p><p>To separate from station coordinates use <strong class=\"groops-config-element\">constraint:centerMean</strong>\nand from slant TEC parameters use <strong class=\"groops-config-element\">constraint:TEC</strong>.</p><p>The constraints are applied separately to all antennas matching\nthe wildcard patterns of <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">serial</strong>, <strong class=\"groops-config-element\">radome</strong>.</p><p>See also <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td>with applied constraints</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">constraint</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">center</div></div></td><td>sequence</td><td>zero center (x,y,z) of a single pattern</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>applied for each matching types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">applyWeight</div></div></td><td>boolean</td><td>from normal equations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">centerMean</div></div></td><td>sequence</td><td>zero center (x,y,z) as (weighted) mean of all patterns</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">applyWeight</div></div></td><td>boolean</td><td>from normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td>sequence</td><td>zero constant (mean of all directions) of a single pattern</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>applied for each matching types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">applyWeight</div></div></td><td>boolean</td><td>from normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constantMean</div></div></td><td>sequence</td><td>zero constant (mean of all directions) as (weighted) mean of all patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">applyWeight</div></div></td><td>boolean</td><td>from normal equations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">TEC</div></div></td><td>sequence</td><td>zero TEC computed as (weighetd) least squares from all types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>applied for combination of matching types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">applyWeight</div></div></td><td>boolean</td><td>from normal equations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>[TECU]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antennaCenterVariations</div></div></td><td><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">antennaName</div></div></td><td>string</td><td>apply constraints to all machting antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">antennaSerial</div></div></td><td>string</td><td>apply constraints to all machting antennas</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">antennaRadome</div></div></td><td>string</td><td>apply constraints to all machting antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaAzimuth</div></div></td><td>angle</td><td>[degree] sampling of pattern to estimate center/constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaZenith</div></div></td><td>angle</td><td>[degree] sampling of pattern to estimate center/constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxZenith</div></div></td><td>angle</td><td>[degree] sampling of pattern to estimate center/constant</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAntex2AntennaDefinition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAntex2AntennaDefinition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAntex2AntennaDefinition</h1><p>\n\nConverts metadata and antenna definitions from the <a href=\"https://files.igs.org/pub/data/format/antex14.txt\">IGS ANTEX format</a>.\nto <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">antennaDefinition</a>, <a class=\"groops-class\" href=\"fileFormat_platform.html\">transmitterInfo</a>, and\n<a class=\"groops-class\" href=\"fileFormat_stringList.html\">transmitterList</a> files for the respective GNSS and for the list of ground station antennas.</p><p>The <a class=\"groops-file\" href=\"fileFormat_platform.html\">transmitterInfo</a> files for GLONASS satellites should then be updated using <a class=\"groops-program\" href=\"GnssGlonassFrequencyNumberUpdate.html\">GnssGlonassFrequencyNumberUpdate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntennaDefinitionStation</div></div></td><td>filename</td><td>antenna center variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntennaDefinitionTransmitter</div></div></td><td>filename</td><td>antenna center variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterInfo</div></div></td><td>filename</td><td>PRN is appended to file name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterListGps</div></div></td><td>filename</td><td>list of PRNs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterListGlonass</div></div></td><td>filename</td><td>list of PRNs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterListGalileo</div></div></td><td>filename</td><td>list of PRNs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterListBeiDou</div></div></td><td>filename</td><td>list of PRNs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterListQzss</div></div></td><td>filename</td><td>list of PRNs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterListIrnss</div></div></td><td>filename</td><td>list of PRNs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntex</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>ignore older antenna definitions</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">createZeroModel</div></div></td><td>boolean</td><td>create empty antenna patterns</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAttitude2Orbex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAttitude2Orbex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAttitude2Orbex</h1><p>\n\nDEPRECATED since 2024-11-30. Please use <a class=\"groops-program\" href=\"StarCamera2Orbex.html\">StarCamera2Orbex</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbex</div></div></td><td>filename</td><td>ORBEX file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileTransmitterList</div></div></td><td>filename</td><td>ASCII list with transmitter PRNs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAttitude</div></div></td><td>filename</td><td>instrument file containing attitude</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variablePrn</div></div></td><td>string</td><td>loop variable for PRNs from transmitter list</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>resample to these epochs (otherwise input file epochs are used)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotate data into Earth-fixed frame</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">interpolationDegree</div></div></td><td>uint</td><td>for attitude and Earth rotation interpolation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">description</div></div></td><td>string</td><td>description of file contents</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">createdBy</div></div></td><td>string</td><td>name of agency</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputData</div></div></td><td>string</td><td>description of input data (see ORBEX description)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">contact</div></div></td><td>string</td><td>email address</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">referenceFrame</div></div></td><td>string</td><td>reference frame used in file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssAttitudeInfoCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAttitudeInfoCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAttitudeInfoCreate</h1><p>\n\nCreates attitude info file (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">Instrument(MISCVALUES)</a>)\nused by <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>. One or more <strong class=\"groops-config-element\">attitudeInfo</strong>s can be specified.\nThey are valid from <strong class=\"groops-config-element\">timeStart</strong> until the start of the subsequent <strong class=\"groops-config-element\">attitudeInfo</strong>.\n<strong class=\"groops-config-element\">maxManeuverTime</strong> is used by <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> to look\nfor ongoing orbit maneuvers before/after the given orbit that might affect the attitude at\nthe beginning or end of a given orbit.</p><p><figure><img class=\"figure\" style=\"width:90%;\" src=\"../figures/gnssAttitudeModes.png\" alt=\"gnssAttitudeModes\"><figcaption class=\"center\">Figure: Overview of attitude modes used by GNSS satellites</figcaption></figure></p><p>Here is a list of GNSS satellite types for which the attitude behavior is known and their\nrespective attitude modes and required parameters:\n<ul>\n\n<li><b>GPS-II/IIA</b> [1]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: shadowMaxYawSteeringAndRecovery\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: catchUpYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.12 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">yawBias</strong>: 0.5 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 2 h\n</li></ul>\n\n<li><b>GPS-IIR/IIR-M</b> [1]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: catchUpYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: catchUpYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.2 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 30 min\n</li></ul>\n\n<li><b>GPS-IIF</b> [2]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: shadowConstantYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: catchUpYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.11 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">yawBias</strong>: -0.7 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h\n</li></ul>\n\n<li><b>GLO-M</b> [3]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: shadowMaxYawSteeringAndStop\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: centeredMaxYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.25 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 2 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h\n</li></ul>\n\n<li><b>GAL-1</b> [4]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering1\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering1\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h\n</li></ul>\n\n<li><b>GAL-2</b> [4]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering2\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering2\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 4.1 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 4.1 deg\n  </li><li>\n<strong class=\"groops-config-element\">activationThreshold</strong>: 10 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 5656 s\n</li></ul>\n\n<li><b>BDS-2G/3G</b> [5, 6]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: orbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: orbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: orbitNormal\n</li></ul>\n\n<li><b>BDS-2I</b> [5]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: betaDependentOrbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: betaDependentOrbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.085 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 4 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 4 deg\n  </li><li>\n<strong class=\"groops-config-element\">activationThreshold</strong>: 5 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 24 h\n</li></ul>\n\n<li><b>BDS-2M</b> [5]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: betaDependentOrbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: betaDependentOrbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.159 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 4 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 4 deg\n  </li><li>\n<strong class=\"groops-config-element\">activationThreshold</strong>: 5 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 13 h\n</li></ul>\n\n<li><b>BDS-3I/3SI</b> [6]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering2\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering2\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 3 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 3 deg\n  </li><li>\n<strong class=\"groops-config-element\">activationThreshold</strong>: 6 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 5740 s\n</li></ul>\n\n<li><b>BDS-3M/3SM</b> [6]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering2\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering2\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 3 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 3 deg\n  </li><li>\n<strong class=\"groops-config-element\">activationThreshold</strong>: 6 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 3090 s\n</li></ul>\n\n<li><b>QZS-1</b> [7]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: betaDependentOrbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: betaDependentOrbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.01 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">yawBias</strong>: 180 deg\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 20 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 20 deg\n  </li><li>\n<strong class=\"groops-config-element\">activationThreshold</strong>: 18.5 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 24 h\n</li></ul>\n\n<li><b>QZS-2G</b> [7]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: orbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: orbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: orbitNormal\n  </li><li>\n<strong class=\"groops-config-element\">yawBias</strong>: 180 deg\n</li></ul>\n\n<li><b>QZS-2I</b> [7]\n<ul>\n\n  </li><li>\n<strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">midnightMode</strong>: centeredMaxYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">noonMode</strong>: centeredMaxYawSteering\n  </li><li>\n<strong class=\"groops-config-element\">maxYawRate</strong>: 0.055 deg/s\n  </li><li>\n<strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 5 deg\n  </li><li>\n<strong class=\"groops-config-element\">noonBetaThreshold</strong>: 5 deg\n  </li><li>\n<strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h\n</li></ul>\n\n</ul></p><p>Some specific satellites may deviate in their attitude behavior or parameters\n(e.g. G013-G040, R713, C005, C015, C017, J001).</p><p>References for the attitude behavior information:\n<ol>\n\n<li><a href=\"https://doi.org/10.1007/s10291-008-0092-1\">Kouba (2009)</a>\n</li><li>\n<a href=\"https://doi.org/10.1007/s10291-016-0562-9\">Kuang et al. (2017)</a>\n</li><li>\n<a href=\"https://doi.org/10.1016/j.asr.2010.09.007\">Dilssner et al. (2011)</a>\n</li><li>\n<a href=\"https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3\" target=\"_blank\">https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3</a>\n</li><li>\n<a href=\"https://doi.org/10.1007/s10291-018-0783-1\">Wang et al. (2018)</a>\n</li><li>\n<a href=\"https://doi.org/10.1017/S0373463318000103\">Li et al. (2018)</a>\n</li><li>\n<a href=\"https://qzss.go.jp/en/technical/qzssinfo/index.html\" target=\"_blank\">https://qzss.go.jp/en/technical/qzssinfo/index.html</a>\n</li></ol>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAttitudeInfo</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">attitudeInfo</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">defaultMode</div></div></td><td>choice</td><td>default attitude mode</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">nominalYawSteering</div></div></td><td></td><td>yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">orbitNormal</div></div></td><td></td><td>keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">midnightMode</div></div></td><td>choice</td><td>attitude mode for maneuvers around orbit midnight</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">nominalYawSteering</div></div></td><td></td><td>yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">orbitNormal</div></div></td><td></td><td>keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">catchUpYawSteering</div></div></td><td></td><td>yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">shadowMaxYawSteeringAndRecovery</div></div></td><td></td><td>yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight))</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">shadowMaxYawSteeringAndStop</div></div></td><td></td><td>yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached, then stop (e.g. GLO-M (midnight))</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">shadowConstantYawSteering</div></div></td><td></td><td>yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight))</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">centeredMaxYawSteering</div></div></td><td></td><td>yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">smoothedYawSteering1</div></div></td><td></td><td>yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">smoothedYawSteering2</div></div></td><td></td><td>yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">betaDependentOrbitNormal</div></div></td><td></td><td>switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">noonMode</div></div></td><td>choice</td><td>attitude mode for maneuvers around orbit noon</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">nominalYawSteering</div></div></td><td></td><td>yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">orbitNormal</div></div></td><td></td><td>keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">catchUpYawSteering</div></div></td><td></td><td>yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">centeredMaxYawSteering</div></div></td><td></td><td>yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">smoothedYawSteering1</div></div></td><td></td><td>yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">smoothedYawSteering2</div></div></td><td></td><td>yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">betaDependentOrbitNormal</div></div></td><td></td><td>switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">maxYawRate</div></div></td><td>double</td><td>[degree/s] maximum yaw rate of the satellite</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">yawBias</div></div></td><td>double</td><td>[degree] yaw bias applied in satellite attitude control system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">midnightBetaThreshold</div></div></td><td>double</td><td>[degree] limit midnight maneuver to this absolute angle of the Sun above/below the satellite orbital plane</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">noonBetaThreshold</div></div></td><td>double</td><td>[degree] limit noon maneuver to this absolute angle of the Sun above/below the satellite orbital plane</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">activationThreshold</div></div></td><td>double</td><td>[degree] limit maneuver to this yaw/Earth-spacecraft-Sun angle (depending on mode)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">maxManeuverTime</div></div></td><td>double</td><td>[s] maximum duration of maneuver or maximum maneuver lookup time before/after orbit start/end</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssBiasClockAlignment.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssBiasClockAlignment</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssBiasClockAlignment</h1><p>\n\nThis program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks).\nEach 'group' of <strong class=\"groops-config-element\">transmitter</strong>s, usually a system like GPS or Galileo, is aligned individually by a constant shift over all transmitters.\nIf <strong class=\"groops-config-element\">alignClocksByFreqNo</strong> is set, GLONASS transmitters will be divided by frequency number into groups of nominally two transmitters.\nThe offset between clocks and reference clocks will be shifted into receiver code biases, if <strong class=\"groops-config-element\">receiver</strong> is provided.\"</p><p>By setting <strong class=\"groops-config-element\">alignFreqNoBiasesAtReceiver</strong> and providing <strong class=\"groops-config-element\">receiver</strong>, this program can further align GLONASS transmitter signal\nbiases so that the differences between frequency number-dependent receiver signal biases are minimal, which helps if PPP users don't set\nup individual signal biases per frequency number at the receiver. Alignment is done by computing signal bias residuals to the mean over all\nfrequency numbers of a signal type at each receiver and then computing the means over all receivers for each frequency number and shifting\nthose from the receiver signal biases to the transmitter signal biases. Internal consistency of the biases is not affected by this.</p><p>If you only want to align GLONASS frequency numbers, provide the same clocks in\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileReferenceClock</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">transmitter</div></div></td><td>sequence</td><td>one element per satellite</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfileClock</div></div></td><td>filename</td><td>aligned clock instrument file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSignalBias</div></div></td><td>filename</td><td>(GLONASS only) aligned signal bias file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileClock</div></div></td><td>filename</td><td>clock instrument file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileReferenceClock</div></div></td><td>filename</td><td>reference clock instrument file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSignalBias</div></div></td><td>filename</td><td>(GLONASS only) signal bias file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileTransmitterInfo</div></div></td><td>filename</td><td>transmitter platform file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">receiver</div></div></td><td>sequence</td><td>one element per station</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfileSignalBias</div></div></td><td>filename</td><td>aligned signal bias file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td>signal bias file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">alignClocksByFreqNo</div></div></td><td>boolean</td><td>align clocks for each GLONASS frequency number separately</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">alignFreqNoBiasesAtReceiver</div></div></td><td>boolean</td><td>align frequency number-dependent code biases for each receiver</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssClock2ClockRinex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssClock2ClockRinex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssClock2ClockRinex</h1><p>\n\nConverts GNSS clocks from GROOPS format to <a href=\"https://files.igs.org/pub/data/format/rinex_clock304.txt\">IGS clock RINEX format</a>.\nClocks can be provided via <strong class=\"groops-config-element\">satelliteData</strong> and/or <strong class=\"groops-config-element\">stationData</strong>.\nObserved signal types are inferred from <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBias</a>.\nSatellites/stations used as clock references can be provided via <strong class=\"groops-config-element\">referenceClock</strong>.</p><p>See IGS clock RINEX format description for further details on header information.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileClockRinex</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">satelliteData</div></div></td><td>sequence</td><td>one element per satellite</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileClock</div></div></td><td>filename</td><td>clock instrument file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td>signal bias file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">identifier</div></div></td><td>string</td><td>PRN (e.g. G23)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationData</div></div></td><td>sequence</td><td>one element per station</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileClock</div></div></td><td>filename</td><td>clock instrument file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfilePosition</div></div></td><td>filename</td><td>station position file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>station info file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">identifier</div></div></td><td>string</td><td>station name (e.g. wtzz)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comment in header</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">program</div></div></td><td>string</td><td>name of program (for first line)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">institution</div></div></td><td>string</td><td>name of agency (for first line)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">analysisCenter</div></div></td><td>string</td><td>name of analysis center</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">differentialCodeBias</div></div></td><td>string</td><td>program and source for applied differential code bias</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">phaseCenterVariations</div></div></td><td>string</td><td>program and source for applied phase center variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">referenceClock</div></div></td><td>string</td><td>identifier of reference satellite/station</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">referenceFrame</div></div></td><td>string</td><td>terrestrial reference frame for the stations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssClockRinex2InstrumentClock.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssClockRinex2InstrumentClock</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssClockRinex2InstrumentClock</h1><p>\n\nThis program converts clocks from the <a href=\"https://files.igs.org/pub/data/format/rinex_clock304.txt\">IGS clock RINEX format</a>,\nwhich contains the clocks of all satellites and stations in a single file,\ninto an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a> for each <strong class=\"groops-config-element\">identifier</strong>\n(satellite and/or station).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>identifier is appended to each file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileClockRinex</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">identifier</div></div></td><td>string</td><td>satellite or station identifier, e.g. G23 or alic</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">intervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minEpochsPerInterval</div></div></td><td>uint</td><td>minimum number of epochs in an interval</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssEop2IgsErp.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssEop2IgsErp</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssEop2IgsErp</h1><p>\n\nWrite GNSS Earth orientation parameters to <a href=\"https://files.igs.org/pub/data/format/erp.txt\">IGS ERP file format</a>.</p><p>Requires polar motion, polar motion rate, dUT1 and LOD parameters in the solution\nvector <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a> and their sigmas in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmax</a>.\nSolution usually comes out of <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileIgsErp</div></div></td><td>filename</td><td>IGS ERP file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">epoch</div></div></td><td>sequence</td><td>e.g. daily solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSolution</div></div></td><td>filename</td><td>parameter vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileParameterNames</div></div></td><td>filename</td><td>parameter names</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileTransmitterList</div></div></td><td>filename</td><td>transmitter PRNs used in solution (used for transmitter count)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileStationList</div></div></td><td>filename</td><td>stations used in solution (used for station count)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td>reference time for epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssEstimateClockShift.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssEstimateClockShift</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssEstimateClockShift</h1><p>\n\nThis program estimates an epoch-wise clock shift in a constellation of GNSS satellites.\nEach separate <strong class=\"groops-config-element\">data</strong> represents a satellite... (e.g. 32 GPS satellites).\nThe shift to reference clocks can be estimated by providing <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentRef</a>.\nClock shifts are estimated for each epoch given by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileShiftTimeSeries</div></div></td><td>filename</td><td>columns: mjd, clock shift</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">data</div></div></td><td>sequence</td><td>e.g. satellite</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td>corrected clocks</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileInstrumentDiff</div></div></td><td>filename</td><td>clock difference after correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td>input clocks</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileInstrumentRef</div></div></td><td>filename</td><td>reference clocks (subtracted from input clocks)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>clock epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>[s] margin for time comparison</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssGlonassFrequencyNumberUpdate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssGlonassFrequencyNumberUpdate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssGlonassFrequencyNumberUpdate</h1><p>\n\nUpdate/set GLONASS frequency number in <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a> files.\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePrn2FrequencyNumber</a> can be generated with\n<a class=\"groops-program\" href=\"SinexMetadata2GlonassFrequencyNumber.html\">SinexMetadata2GlonassFrequencyNumber</a>.</p><p>See also <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTransmitterInfo</div></div></td><td>filename</td><td>templated for PRN list (variableNamePrn)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTransmitterInfo</div></div></td><td>filename</td><td>templated for PRN list (variableNamePrn)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePrn2FrequencyNumber</div></div></td><td>filename</td><td>matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">prn</div></div></td><td>string</td><td>PRN (e.g. R01) for transmitter info files</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableNamePrn</div></div></td><td>string</td><td>variable name for PRN in transmitter info files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssGriddedDataTimeSeries2Ionex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssGriddedDataTimeSeries2Ionex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssGriddedDataTimeSeries2Ionex</h1><p>\n\nConverts TEC maps from GROOPS <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">gridded data time series</a> format\nto IGS <a href=\"https://files.igs.org/pub/data/format/ionex1.pdf\">IONEX file format</a>.</p><p>Currently only supports 2D TEC maps.</p><p>See also <a class=\"groops-program\" href=\"GnssIonex2GriddedDataTimeSeries.html\">GnssIonex2GriddedDataTimeSeries</a>, <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">IonosphereMap</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileIonex</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td>must contain regular grid</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">value</div></div></td><td>expression</td><td>expression (e.g. data column)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>(empty = use input file time series)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">program</div></div></td><td>string</td><td>name of program (for first line)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">institution</div></div></td><td>string</td><td>name of agency (for first line)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">description</div></div></td><td>string</td><td>description in header</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comment in header</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mappingFunction</div></div></td><td>string</td><td>see IONEX documentation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">elevationCutoff</div></div></td><td>double</td><td>see IONEX documentation (0 if unknown)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">observablesUsed</div></div></td><td>string</td><td>see IONEX documentation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exponent</div></div></td><td>int</td><td>factor 10^exponent is applied to all values</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssIonex2GriddedDataTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssIonex2GriddedDataTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssIonex2GriddedDataTimeSeries</h1><p>\n\nConverts TEC maps from IGS <a href=\"https://files.igs.org/pub/data/format/ionex1.pdf\">IONEX file format</a>\nto GROOPS <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">gridded data time series</a> format.</p><p>Currently only supports 2D TEC maps.</p><p>See also <a class=\"groops-program\" href=\"GnssGriddedDataTimeSeries2Ionex.html\">GnssGriddedDataTimeSeries2Ionex</a>, <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">IonosphereMap</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileIonex</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssNormals2Sinex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssNormals2Sinex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssNormals2Sinex</h1><p>\n\nWrite GNSS data/metadata and <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> to\n<a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a>.</p><p>Normal equations usually come from <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>\n(e.g. from <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>).\nMetadata input files include <a class=\"groops-class\" href=\"fileFormat_platform.html\">stationInfo/transmitterInfo</a>, <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">antennaDefinition</a>,\nand <a class=\"groops-class\" href=\"fileFormat_stringList.html\">stationList/transmitterList</a>, see <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.</p><p>See also <a class=\"groops-program\" href=\"Sinex2Normals.html\">Sinex2Normals</a> and <a class=\"groops-program\" href=\"NormalsSphericalHarmonics2Sinex.html\">NormalsSphericalHarmonics2Sinex</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSinexNormals</div></div></td><td>filename</td><td>full SINEX file including normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSinexCoordinates</div></div></td><td>filename</td><td>SINEX file without normal equations (station coordinates file)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormals</div></div></td><td>filename</td><td>normal equation matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSolution</div></div></td><td>filename</td><td>parameter vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileApriori</div></div></td><td>filename</td><td>apriori parameter vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAprioriSigma</div></div></td><td>filename</td><td>constraint sigmas for apriori parameter vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAprioriMatrix</div></div></td><td>filename</td><td>normal equation matrix of applied constraints</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">transmitterConstellation</div></div></td><td>sequence</td><td>transmitter constellation metadata</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileTransmitterList</div></div></td><td>filename</td><td>transmitter PRNs used in solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileTransmitterInfo</div></div></td><td>filename</td><td>transmitter info file template</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>transmitter phase centers and variations (ANTEX)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">variablePrn</div></div></td><td>string</td><td>loop variable for PRNs from transmitter list</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">stations</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileStationList</div></div></td><td>filename</td><td>stations contained in normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>station info file template</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>station phase centers and variations (ANTEX)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">variableStationName</div></div></td><td>string</td><td>loop variable for station names from station list</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationTimeStart</div></div></td><td>time</td><td>start time for which solution has observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationTimeEnd</div></div></td><td>time</td><td>end time for which solution has observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td>reference time for parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] observation sampling</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">antennaCalibrationModel</div></div></td><td>string</td><td>e.g. IGS14_WWWW (WWWW = ANTEX release GPS week)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sinexHeader</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">agencyCode</div></div></td><td>string</td><td>identify the agency providing the data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>start time of the data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td>end time of the data </td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">observationCode</div></div></td><td>string</td><td>technique used to generate the SINEX solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">constraintCode</div></div></td><td>string</td><td>0: tight constraint, 1: siginficant constraint, 2: unconstrained</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">solutionContent</div></div></td><td>string</td><td>solution types contained in the SINEX solution (S O E T C A)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>organizitions gathering/alerting the file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">contact</div></div></td><td>string</td><td>Address of the relevant contact. e-mail</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">output</div></div></td><td>string</td><td>Description of the file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">input</div></div></td><td>string</td><td>Brief description of the input used to generate this solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">software</div></div></td><td>string</td><td>Software used to generate the file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">hardware</div></div></td><td>string</td><td>Computer hardware on which above software was run</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileComment</div></div></td><td>filename</td><td>comments in the comment block from a file (truncated at 80 characters)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comments in the comment block</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssOrbex2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssOrbex2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssOrbex2StarCamera</h1><p>\n\nConverts GNSS satellite attitude from <a href=\"http://acc.igs.org/misc/proposal_orbex_april2019.pdf\">ORBEX file format</a>\n(quaternions) to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>.\nThe resulting star camera files contain the rotation from satellite body frame to TRF, or to CRF in case\n<a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided.</p><p>See also <a class=\"groops-program\" href=\"GnssAttitude2Orbex.html\">GnssAttitude2Orbex</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>rotation from body frame to TRF/CRF, identifier is appended to each file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbex</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">identifier</div></div></td><td>string</td><td>(empty = all) satellite identifier, e.g. G23 or E05</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotation from TRF to CRF</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssPrn2SvnBlockVariables.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssPrn2SvnBlockVariables</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssPrn2SvnBlockVariables</h1><p>\n\nDEPRECATED since 2024-02-12. This program no longer works!</p><p>Setup up a <a class=\"groops-class\" href=\"loopType.html#platformEquipment\">loop:platformEquipment</a> instead with\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfilePlatform</a>: the old <strong class=\"groops-config-element\">inputfileTransmitterInfo</strong>\n  </li><li>\n<strong class=\"groops-config-element\">equipmentType</strong>         = <code>gnssAntenna</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopName</strong>      = <code>block</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopSerial</strong>    = <code>svn</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopTimeStart</strong> = <code>svnTimeStart</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopTimeEnd</strong>   = <code>svnTimeEnd</code>\n  </li><li>\n<a class=\"groops-class\" href=\"conditionType.html#expression\">condition:expression</a>\n  <ul>\n\n    </li><li>\n<strong class=\"groops-config-element\">expression</strong> = <code>(svnTimeStart &lt;= time) && (time &lt; svnTimeEnd)</code>\n  </li></ul>\n\n</ul>\nAttribute this loop to programs, which uses the variables.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssProcessing.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssProcessing</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssProcessing</h1><p>\n\nThis program processes GNSS observations. It calculates the linearized observation equations,\naccumulates them into a system of normal equations and solves it.</p><p>The primary use cases of this program are:\n<ul>\n\n  <li><a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>\n  </li><li>\n<a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a>\n  </li><li>\n<a class=\"groops-ref\" href=\"cookbook.gnssPpp.html\">GNSS precise point positioning (PPP)</a>\n</li></ul>\n</p><p>The observation epochs are defined by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>\nand only observations at these epochs (within a <strong class=\"groops-config-element\">timeMargin</strong>) are considered.</p><p>To calculate observation equations from the tracks, the model parameters or unknown parameters need to be\ndefined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined\n<a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a>.\nSome of the <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a> also include a priori models.</p><p>Lastly it is required to define the process flow of the gnssProcessing. This is accomplished\nwith a list of <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>.\nEach step is processed consecutively. Some steps allow the selection of parameters, epochs,\nor the normal equation structure, which affects all subsequent steps.\nA minimal example consists of following steps:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: iterative float solution with outlier downeighting\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>:\n        fix ambiguities to integer and remove them from the normals\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: few iteration for final outlier downweighting\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>:\n        write the output files defined in <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a>\n</li></ul>\n</p><p>If the program is run on multiple processes the <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>s\n(stations or LEO satellites) are distributed over the processes.</p><p>See also <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>defines observation epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeMargin</div></div></td><td>double</td><td>[seconds] margin to consider two times identical</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">transmitter</div></div></td><td><a href=\"gnssTransmitterGeneratorType.html\">gnssTransmitterGenerator</a></td><td>constellation of GNSS satellites</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">receiver</div></div></td><td><a href=\"gnssReceiverGeneratorType.html\">gnssReceiverGenerator</a></td><td>ground station network or LEO satellite</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>apriori earth rotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"gnssParametrizationType.html\">gnssParametrization</a></td><td>models and parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">processingStep</div></div></td><td><a href=\"gnssProcessingStepType.html\">gnssProcessingStep</a></td><td>steps are processed consecutively</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssReceiver2RinexObservation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssReceiver2RinexObservation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssReceiver2RinexObservation</h1><p>\n\nConverts a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileGnssReceiver</a> into a\n<a href=\"https://files.igs.org/pub/data/format/rinex_4.00.pdf\">RINEX</a> observation file.\nThe <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> contains the antenna\nand receiver information for the RINEX header.\nThe <a class=\"groops-class\" href=\"gnssType.html\">useType</a> and <a class=\"groops-class\" href=\"gnssType.html\">ignoreType</a> can be used to filter\nthe observation types that will be exported.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileRinexObservation</div></div></td><td>filename</td><td>RINEX observation file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGnssReceiver</div></div></td><td>filename</td><td>GNSS instrument file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>antenna and receiver info</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>write comments at begin of header</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">observer</div></div></td><td>string</td><td>header information</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">angency</div></div></td><td>string</td><td>header information</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">useType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>only use observations that match any of these patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">ignoreType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>ignore observations that match any of these patterns</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssReceiverDefinitionCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssReceiverDefinitionCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssReceiverDefinitionCreate</h1><p>\n\nCreate a <a class=\"groops-file\" href=\"fileFormat_gnssReceiverDefinition.html\">GNSS receiver definition file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGnssReceiverDefinition</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">receiverDefinition</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">version</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">gnssType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssResiduals2AccuracyDefinition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssResiduals2AccuracyDefinition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssResiduals2AccuracyDefinition</h1><p>\n\nCompute antenna accuracies from observation <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileResiduals</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> is needed to assign\nthe residuals to the equipped antenna at observation times.</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAccuracyDefinition</a> contains\nat first step the same accuracy information for all antennas as the input file.\nOnly the azimuth $A$ and elevation $E$ dependent grid points of the patterns\nwhere enough residuals are available ($>$ <strong class=\"groops-config-element\">minRedundancy</strong>)\nare replaced by estimated accuracy\n\\[\n \\sigma(A,E) = \\sqrt{\\frac{\\sum_i e_i^2(A,E)}{\\sum_i r_i(A,E)}},\n\\]where $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the\ncorresponding redundancies (number of observations minus the contribution to\nthe estimated parameters).</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> can be modified\nto the demands before with <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>\n(e.g. with <strong class=\"groops-config-element\">antenna:resample</strong>).</p><p>To verify the results the <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaMean</a>\nand the accumulated <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaRedundancy</a>\nof the computed pattern grid points can be written.</p><p>Example: Analysis of TerraSAR-X residuals of one month shows that low elevation\nGPS satellites are not tracked by the onboard receiver. An estimation of accuracies\nfor these directions is not possible from the residuals and the apriori accuracies\nare left untouched. The other directions show very low phase noise hardly elevation\nand azimuth dependent for L2W. A nearly zero mean indicates the use of adequate antennca\ncenter variations in the processing.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/gnssResiduals2AccuracyDefinition.png\" alt=\"gnssResiduals2AccuracyDefinition\"><figcaption class=\"center\">Figure: L2W accuracies of TerraSAR-X determined from residuals of one month</figcaption></figure></p><p>See also <a class=\"groops-program\" href=\"GnssResiduals2TransmitterAccuracyDefinition.html\">GnssResiduals2TransmitterAccuracyDefinition</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAccuracyDefinition</div></div></td><td>filename</td><td>elevation and azimuth dependent accuracy</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntennaMean</div></div></td><td>filename</td><td>weighted mean of the residuals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntennaRedundancy</div></div></td><td>filename</td><td>redundancy of adjustment</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccuracyDefinition</div></div></td><td>filename</td><td>apriori accuracies</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>to assign residuals to antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">isTransmitter</div></div></td><td>boolean</td><td>stationInfo is of a transmitter</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">thresholdOutlier</div></div></td><td>double</td><td>ignore residuals with sigma/sigma0 greater than threshold</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minRedundancy</div></div></td><td>double</td><td>min number of residuals. to estimate sigma</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileResiduals</div></div></td><td>filename</td><td>GNSS receiver residuals</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssResiduals2Skyplot.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssResiduals2Skyplot</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssResiduals2Skyplot</h1><p>\n\nWrite GNSS residuals together with azimuth and elevation to be plotted with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.\nAzimuth and elevation are written as ellipsoidal longitude and latitude in a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData file</a>.\nThe choosen ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are arbitrary but should be the same\nas in <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>. If with <a class=\"groops-class\" href=\"gnssType.html\">typeTransmitter</a> (e.g. '<code>***G18</code>')\na single transmitter is selected the azimuth and elevation are computed from the transmitter point of view.</p><p>For each GNSS <a class=\"groops-class\" href=\"gnssType.html\">type</a> an extra data column is created.</p><p>A <a class=\"groops-file\" href=\"fileFormat_instrument.html\">GNSS residual file</a> includes additional information\nbesides the residuals, which can also be selected with <a class=\"groops-class\" href=\"gnssType.html\">type</a>\n<ul>\n\n<li><code>A1*</code>, <code>E1*</code>: azimuth and elevation at receiver\n</li><li>\n<code>A2*</code>, <code>E2*</code>: azimuth and elevation at transmitter\n</li><li>\n<code>I**</code>: Estimated slant total electron content (STEC)\n</li></ul>\n</p><p>Furthermore these files may include for each residual <a class=\"groops-class\" href=\"gnssType.html\">type</a>\ninformation about the redundancy and the accuracy relation $\\sigma/\\sigma_0$\nof the estimated $\\sigma$ versus the apriori $\\sigma_0$ from the least squares adjustment.\nThe 3 values (residuals, redundancy, $\\sigma/\\sigma_0$) are coded with the same type.\nTo get access to all values the corresponding type must be repeated in <a class=\"groops-class\" href=\"gnssType.html\">type</a>.</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/gnssResiduals2Skyplot.png\" alt=\"gnssResiduals2Skyplot\"><figcaption class=\"center\">Figure: GPS C2W residuals of GRAZ station at 2012-01-01</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">typeTransmitter</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>choose transmitter view, e.g. '***G18'</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileResiduals</div></div></td><td>filename</td><td>GNSS receiver residuals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssResiduals2TransmitterAccuracyDefinition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssResiduals2TransmitterAccuracyDefinition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssResiduals2TransmitterAccuracyDefinition</h1><p>\n\nCompute antenna accuracies from observation <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileResiduals</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a> is needed to assign\nthe residuals to the equipped antenna at observation times.</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAccuracyDefinition</a> contains\nat first step the same accuracy information for all antennas as the input file.\nOnly the azimuth $A$ and elevation $E$ dependent grid points of the patterns\nwhere enough residuals are available ($>$ <strong class=\"groops-config-element\">minRedundancy</strong>)\nare replaced by estimated accuracy\n\\[\n \\sigma(A,E) = \\sqrt{\\frac{\\sum_i e_i^2(A,E)}{\\sum_i r_i(A,E)}},\n\\]where $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the\ncorresponding redundancies (number of observations minus the contribution to\nthe estimated parameters).</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> can be modified\nto the demands before with <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>\n(e.g. with <strong class=\"groops-config-element\">antenna:resample</strong>).</p><p>To verify the results the <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaMean</a>\nand the accumulated <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaRedundancy</a>\nof the computed pattern grid points can be written.</p><p>See also <a class=\"groops-program\" href=\"GnssResiduals2AccuracyDefinition.html\">GnssResiduals2AccuracyDefinition</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAccuracyDefinition</div></div></td><td>filename</td><td>elevation and azimuth dependent accuracy</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntennaMean</div></div></td><td>filename</td><td>weighted mean of the residuals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntennaRedundancy</div></div></td><td>filename</td><td>redundancy of adjustment</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccuracyDefinition</div></div></td><td>filename</td><td>apriori accuracies</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTransmitterInfo</div></div></td><td>filename</td><td>to assign residuals to antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minRedundancy</div></div></td><td>double</td><td>min number of residuals. to estimate sigma</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileResiduals</div></div></td><td>filename</td><td>GNSS receiver residuals</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssRinexNavigation2OrbitClock.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssRinexNavigation2OrbitClock</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssRinexNavigation2OrbitClock</h1><p>\n\nEvaluates orbit and clock parameters from <a href=\"https://files.igs.org/pub/data/format/rinex_4.00.pdf\">RINEX</a> (version 2, 3, and 4)\nnavigation file <strong class=\"groops-config-element\">inputfileRinex</strong> at epochs given by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> and writes them to\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileClock</a>, respectively.</p><p>Orbits are rotated from TRF (as broadcasted) to CRF via <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>,\nbut system-specific TRFs (WGS84, PZ-90, etc.) are not aligned to a common TRF.</p><p>Furthermore, option is available to remove any satellite ephemeris data that has their satellite flag set to unhealthy.</p><p>See also <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>PRN is appended to file name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClock</div></div></td><td>filename</td><td>PRN is appended to file name</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileRinex</div></div></td><td>filename</td><td>RINEX navigation file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>orbit and clock evaluation epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>for rotation from TRF to CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">useType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>(e.g. ***G12) only use satellites with PRN that match any of these patterns</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">ignoreType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>(e.g. ***R**) ignore satellites PRN that match any of these patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeUnhealthySatellites</div></div></td><td>boolean</td><td>Remove satellite ephemeris that have their sat flags set to unhealthy</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssSignalBias2Matrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssSignalBias2Matrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssSignalBias2Matrix</h1><p>\n\nComputes signal biases for a given list of <a class=\"groops-class\" href=\"gnssType.html\">types</a>.\nIf the type list is empty, all types contained in <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBias</a> are used.\nThe resulting <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> contains a vector with an entry for each type.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTypes</div></div></td><td>filename</td><td>ASCII list of types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">types</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>if not set, all types in the file are used</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssSignalBias2SinexBias.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssSignalBias2SinexBias</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssSignalBias2SinexBias</h1><p>\n\nConvert <a class=\"groops-file\" href=\"fileFormat_gnssSignalBias.html\">GNSS signal biases</a> from GROOPS format to <a href=\"https://files.igs.org/pub/data/format/sinex_bias_100.pdf\">IGS SINEX Bias format</a>.\nBiases can be provided via <strong class=\"groops-config-element\">transmitterBiases</strong> and/or <strong class=\"groops-config-element\">receiverBiases</strong>.\nPhase biases without attribute (e.g. <code>L1*</code>) are automatically expanded so each code\nbias has a corresponding phase bias\n(Example: <code>C1C</code>, <code>C1W</code>, <code>L1*</code> are converted to <code>C1C</code>, <code>C1W</code>, <code>L1C</code>, <code>L1W</code>).</p><p>Time-variable biases (e.g. GPS L5 satellite phase bias) can be provided via <strong class=\"groops-config-element\">timeVariableBias</strong>.\nTheir time span will be based on the provided epochs ($t \\pm \\Delta t / 2$).\nThe slope of the bias can be optionally provided in the second data column.</p><p>If GLONASS receiver biases depend on frequency number, those must be defined in <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a>\nto get the correct PRN/SVN assignment to the biases.</p><p>See IGS SINEX Bias format description for further details on header information.</p><p>See also <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a> and <a class=\"groops-program\" href=\"GnssBiasClockAlignment.html\">GnssBiasClockAlignment</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSinexBias</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileTransmitterInfo</div></div></td><td>filename</td><td>one file per satellite</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">transmitterBiases</div></div></td><td>sequence</td><td>one element per satellite</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td>signal bias file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">timeVariableBias</div></div></td><td>sequence</td><td>one entry per time variable bias type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td>columns: mjd, bias [m], (biasSlope [m/s])</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>bias type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">identifier</div></div></td><td>string</td><td>PRN or station name (e.g. G23 or wtzz)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">receiverBiases</div></div></td><td>sequence</td><td>one element per station</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td>signal bias file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">timeVariableBias</div></div></td><td>sequence</td><td>one entry per time variable bias type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileSignalBias</div></div></td><td>filename</td><td>columns: mjd, bias [m], (biasSlope [m/s])</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>bias type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">identifier</div></div></td><td>string</td><td>PRN or station name (e.g. G23 or wtzz)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">agencyCode</div></div></td><td>string</td><td>identify the agency providing the data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">fileAgencyCode</div></div></td><td>string</td><td>identify the agency creating the file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>start time of the data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeEnd</div></div></td><td>time</td><td>end time of the data </td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">biasMode</div></div></td><td>choice</td><td>absolute or relative bias estimates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">absolute</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">relative</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">observationSampling</div></div></td><td>double</td><td>[seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">intervalLength</div></div></td><td>double</td><td>[seconds] interval for bias parameter representation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">determinationMethod</div></div></td><td>string</td><td>determination method used to generate the bias results (see SINEX Bias format description)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">receiverClockReferenceGnss</div></div></td><td>string</td><td>(G, R, E, C) reference GNSS used for receiver clock estimation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">satelliteClockReferenceObservables</div></div></td><td>string</td><td>one per system, reference code observable on first and second frequency (RINEX3 format)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>organization gathering/altering the file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">contact</div></div></td><td>string</td><td>contact name and/or email address</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">input</div></div></td><td>string</td><td>brief description of the input used to generate this solution</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">output</div></div></td><td>string</td><td>description of the file contents</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">software</div></div></td><td>string</td><td>software used to generate the file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">hardware</div></div></td><td>string</td><td>computer hardware on which above software was run</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comments in the comment block</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssSimulateReceiver.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssSimulateReceiver</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssSimulateReceiver</h1><p>\n\nThis program simulates observations from receivers to GNSS satellites.\nThese simulated observations can then be used in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>, for example to conduct closed-loop simulations.</p><p>One or more GNSS constellations must be defined via <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html\">transmitter</a>.\nReceivers such as ground station networks or Low Earth Orbit (LEO) satellites can be defined via <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>.</p><p>If multiple receivers defined an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileGnssReceiver</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileClock</a>\nare written for each single receiver with the <a class=\"groops-ref\" href=\"general.parser.html\">variable</a> <code>{station}</code> being replaced by the receiver name.</p><p>A list of simulated observation types can be defined via <a class=\"groops-class\" href=\"gnssType.html\">observationType</a>. Noise can be added to both observations and clock errors\nvia <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseObervation</a> and <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseClockReceiver</a>, respectively. Observation noise is\ninterpreted as a factor that is multiplied to the accuracy derived from the accuracy pattern of the respective observation type\n(see <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>).</p><p>The <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a> are used to simulate a priori models (e.g. troposphere, signal biases).\nParameter settings and outputfiles are ignored.</p><p>If the program is run on multiple processes the <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>s\n(stations or LEO satellites) are distributed over the processes.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGnssReceiver</div></div></td><td>filename</td><td>variable {station} available, simulated observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClock</div></div></td><td>filename</td><td>variable {station} available, simulated receiver clock errors</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>defines observation epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeMargin</div></div></td><td>double</td><td>[seconds] margin to consider two times identical</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">transmitter</div></div></td><td><a href=\"gnssTransmitterGeneratorType.html\">gnssTransmitterGenerator</a></td><td>constellation of GNSS satellites</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">receiver</div></div></td><td><a href=\"gnssReceiverGeneratorType.html\">gnssReceiverGenerator</a></td><td>ground station network or LEO satellite</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>apriori earth rotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrization</div></div></td><td><a href=\"gnssParametrizationType.html\">gnssParametrization</a></td><td>models and parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">observationType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>simulated observation types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseObservation</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[-] noise is multiplied with type accuracy pattern of receiver</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseClockReceiver</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m] noise added to the simulated receiver clock</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssSinexBias2SignalBias.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssSinexBias2SignalBias</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssSinexBias2SignalBias</h1><p>\n\nConverts GNSS signal biases from <a href=\"https://files.igs.org/pub/data/format/sinex_bias_100.pdf\">IGS SINEX Bias format</a>\nto <a class=\"groops-file\" href=\"fileFormat_gnssSignalBias.html\">GnssSignalBias format</a>.</p><p>Only satellite observable-specific signal biases (OSB) are supported at the moment.\nIf multiple entries exist for the same bias, the weighted average (based on time span) of all entries is used.\nTime-variable biases are not supported at the moment.</p><p>See also <a class=\"groops-program\" href=\"GnssSignalBias2SinexBias.html\">GnssSignalBias2SinexBias</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSignalBias</div></div></td><td>filename</td><td>identifier is appended to file name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinexBias</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileGlonassSignalDefinition</div></div></td><td>filename</td><td>GLONASS frequency number mapping</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">identifier</div></div></td><td>string</td><td>(empty = all) satellite PRN, e.g. G23 or E05</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssStationInfoCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssStationInfoCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssStationInfoCreate</h1><p>\n\nDEPRECATED since 2024-12-02. Please use <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStationInfo</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">markerName</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">markerNumber</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approxPositionX</div></div></td><td>double</td><td>[m] in TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approxPositionY</div></div></td><td>double</td><td>[m] in TRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approxPositionZ</div></div></td><td>double</td><td>[m] in TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">positionX</div></div></td><td>double</td><td>[m] ARP in north, east, up or vehicle system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">positionY</div></div></td><td>double</td><td>[m] ARP in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">positionZ</div></div></td><td>double</td><td>[m] ARP in north, east, up or vehicle system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">rotationX</div></div></td><td>angle</td><td>[degree] from local/vehicle to left-handed antenna system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">rotationY</div></div></td><td>angle</td><td>[degree] from local/vehicle to left-handed antenna system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">rotationZ</div></div></td><td>angle</td><td>[degree] from local/vehicle to left-handed antenna system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">flipX</div></div></td><td>boolean</td><td>flip x-axis (after rotation)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">flipY</div></div></td><td>boolean</td><td>flip y-axis (after rotation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">flipZ</div></div></td><td>boolean</td><td>flip z-axis (after rotation)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">receiver</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">version</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">referencePoint</div></div></td><td>sequence</td><td>e.g. center of mass in satellite frame</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">xStart</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">yStart</div></div></td><td>double</td><td>linear motion between start and end</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zStart</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">xEnd</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">yEnd</div></div></td><td>double</td><td>linear motion between start and end</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zEnd</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssStationLog2Platform.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssStationLog2Platform</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssStationLog2Platform</h1><p>\n\nConverts <a href=\"https://files.igs.org/pub/station/general/blank.log\">IGS station log format</a> or\n<a href=\"https://files.igs.org/pub/station/general/blank_v2.0.log\">IGS station log format v2.0</a> to <a class=\"groops-class\" href=\"fileFormat_platform.html\">outputfileStationPlatform</a>.</p><p>If <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a> is provided, station log data is cross-checked with the given antenna definitions.\nCross-checking station log data with a <a href=\"https://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX file</a> is\npossible with <a class=\"groops-program\" href=\"CheckStationsPlatformsWithSinex.html\">CheckStationsPlatformsWithSinex</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStationPlatform</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationLog</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>used to check antennas</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GnssTroposphere2TropoSinex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssTroposphere2TropoSinex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssTroposphere2TropoSinex</h1><p>\n\nConvert GNSS troposphere data from GROOPS format as estimated by <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>\nto <a href=\"https://files.igs.org/pub/data/format/sinex_tro_v2.00.pdf\">IGS SINEX TRO</a> format.</p><p>For each station folling files are needed:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a>,\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTroposphereData</a>(MISVALUES),\n  </li><li>\noptional standard deviations with <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTroposphereSigmas</a>(MISVALUES),\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfilePosition</a>(VECTOR3D).\n</li></ul>\n\nThe <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a> contains antenna center offsets and variations\nof all used antennas. Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.</p><p>For considering the geoid height use <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedGeoidHeight</a>\nas it might be computed by <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>.\nThe height closest to the station's position is used in each case.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTropoSinex</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">station</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>platform file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileTroposphereData</div></div></td><td>filename</td><td>Troposphere data estimates (columns: mjd, trodry, trowet, tgndry, tgnwet, tgedry, tgewet)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileTroposphereSigmas</div></div></td><td>filename</td><td>Troposphere data sigmas (columns: mjd, sigma_trowet, sigma_tgnwet, sigma_tgewet)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfilePosition</div></div></td><td>filename</td><td>Precise station position (columns: mjd, x, y, z [m in TRF])</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>station phase centers and variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileGriddedGeoidHeight</div></div></td><td>filename</td><td>value closest to the station's position is used in each case</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">dataSamplingInterval</div></div></td><td>double</td><td>[sec] GNSS data sampling rate</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">tropoSamplingInterval</div></div></td><td>double</td><td>[sec] Tropospheric parameter sampling interval</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">tropoModelingMethod</div></div></td><td>string</td><td>Tropospheric estimation method: Filter, Smoother, Least Squares, Piece-Wise Linear Interpolation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">aPrioriTropoModel</div></div></td><td>string</td><td>A priori tropospheric model used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">tropoMappingFunction</div></div></td><td>string</td><td>Name of mapping function used for hydrostatic and wet delay</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gradientMappingFunction</div></div></td><td>string</td><td>Name of mapping function used for gradients</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">metDataSource</div></div></td><td>string</td><td>source of surface meteorological observations used (see format desc.)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">observationWeighting</div></div></td><td>string</td><td>observation weighting model applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">elevationCutoff</div></div></td><td>double</td><td>[deg]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gnssSystems</div></div></td><td>string</td><td>G=GPS, R=GLONASS, E=Galileo, C=BeiDou</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeSystem</div></div></td><td>string</td><td>G (GPS) or UTC</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">oceanTideModel</div></div></td><td>string</td><td>Name of applied Ocean tide loading model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">atmosphericTideModel</div></div></td><td>string</td><td>Name of applied Atmospheric tide loading model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">geoidModel</div></div></td><td>string</td><td>Geoid model name for undulation values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">systemCode</div></div></td><td>string</td><td>Terrestrial reference system code</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">remark</div></div></td><td>string</td><td>Remark used to identify the origin of the coordinates (AC acronym)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">antennaCalibrationModel</div></div></td><td>string</td><td>e.g. IGS20_WWWW (WWWW = ANTEX release GPS week)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sinexTroHeader</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">agencyCode</div></div></td><td>string</td><td>Identify the agency providing the data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>Start time of the data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td>End time of the data </td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">observationCode</div></div></td><td>string</td><td>Technique used to generate the SINEX solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">solutionContents</div></div></td><td>string</td><td>Marker name if single station, MIX if multiple stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>Organizitions gathering/alerting the file contents</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">output</div></div></td><td>string</td><td>Description of the file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">contact</div></div></td><td>string</td><td>Address of the relevant contact e-mail</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">software</div></div></td><td>string</td><td>Software used to generate the file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">hardware</div></div></td><td>string</td><td>Computer hardware on which above software was run</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">input</div></div></td><td>string</td><td>Brief description of the input used to generate this solution</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">versionNumber</div></div></td><td>string</td><td>Unique identifier of the product, same as in file name, e.g. 000</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileComment</div></div></td><td>filename</td><td>comments in the comment block from a file (truncated at 80 characters per line)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comments in the comment block</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GoceXml2Gradiometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GoceXml2Gradiometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GoceXml2Gradiometer</h1><p>\n\nRead ESA XML GOCE Data.\nThe <strong class=\"groops-config-element\">outputfileGradiometer</strong> is written as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (GRADIOMETER)</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGradiometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GoceXml2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GoceXml2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GoceXml2Orbit</h1><p>\n\nRead ESA XML GOCE Data.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotation from TRF to CRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GoceXml2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GoceXml2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GoceXml2StarCamera</h1><p>\n\nRead ESA XML GOCE Data.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GoceXmlEggNom1b.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GoceXmlEggNom1b</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GoceXmlEggNom1b</h1><p>\n\nRead ESA XML GOCE Data.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGradiometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularRate</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularAcc</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Grace2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Grace2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Grace2PotentialCoefficients</h1><p>\n\nThis program converts potential coefficients from the GRACE SDS format\ninto <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">potential coefficients file</a>.\nThe program supports file formats for RL04 to RL06.</p><p>Within the program, the variables <code>epochStart</code>, <code>epochEnd</code> and <code>epochMid</code>\nare populated with the corresponding time-stamps in the file.\nThese can be used in to <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>\nto auto-generate the file name.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td>variables: epochStart, epochEnd, epochMid</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceAccelerometer2L1bAscii.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceAccelerometer2L1bAscii</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceAccelerometer2L1bAscii</h1><p>\n\nConvert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAscii</div></div></td><td>filename</td><td>ASCII outputfile</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td>GROOPS acceleromter file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">satelliteIdentifier</div></div></td><td>string</td><td>satellite identifier (A or B for GRACE, C or D for GRACE-FO)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">globalAttributes</div></div></td><td>string</td><td>additional attributes as 'key: value' pairs</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceAntennaCenterCorrectionArcCovariance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceAntennaCenterCorrectionArcCovariance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceAntennaCenterCorrectionArcCovariance</h1><p>\n\nThis program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC)\nfrom the orientation covariance matrices provided in Level-1B products via variance propagation.\nBy using the output <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSatelliteTrackingCovariance</a> in <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a>,\nnoise model distinguishes between the stationary noise of ranging observations and the non­stationary AOC noise.</p><p>The covariances are derived from the partial derivative of the AOC w.r.t. the roll/pitch/yaw rotations\nand star camera covariances <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileScaCovariance1</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileScaCovariance2</a>.</p><p>The covariances for the range-rates and range-acceleration are computed by differentiating\nan interpolation polynomial of degree <strong class=\"groops-config-element\">interpolationDegree</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSatelliteTrackingCovariance</div></div></td><td>filename</td><td>corrections for range, range-rate, and range-accelerations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeAcceleration</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileScaCovariance1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileScaCovariance2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaAccelerometerX</div></div></td><td>double</td><td>[rad/s^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaAccelerometerY</div></div></td><td>double</td><td>[rad/s^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaAccelerometerZ</div></div></td><td>double</td><td>[rad/s^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">antennaCenters</div></div></td><td>choice</td><td>KBR antenna phase center</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1X</div></div></td><td>double</td><td>x-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1Y</div></div></td><td>double</td><td>y-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1Z</div></div></td><td>double</td><td>z-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2X</div></div></td><td>double</td><td>x-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2Y</div></div></td><td>double</td><td>y-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2Z</div></div></td><td>double</td><td>z-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">file</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputAntennaCenters</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>differentiation by polynomial approximation of degree n</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceAod2DoodsonHarmonics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceAod2DoodsonHarmonics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceAod2DoodsonHarmonics</h1><p>\n\nThis program converts the atmospheric and ocean tidal products (AOD1B)\nfrom the GRACE SDS format into <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">outputfileDoodsonHarmonics</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td>to compute Xi phase correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceAod2TimeSplines.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceAod2TimeSplines</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceAod2TimeSplines</h1><p>\n\nThis program converts the atmospheric and ocean de-aliasing product (AOD1B)\nfrom the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_timeSplinesGravityField.html\">time spline files</a>.\nMultiple <strong class=\"groops-config-element\">inputfile</strong>s must be given in the correct time order.\nA linear method is assumed for the interpolation between the given points in time.</p><p>The GRACE SDS format is described in \"AOD1B Product Description Document\"\ngiven at <a href=\"http://podaac.jpl.nasa.gov/grace/documentation.html\" target=\"_blank\">http://podaac.jpl.nasa.gov/grace/documentation.html</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileDealiasing</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAtmosphere</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOcean</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileBottomPressure</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileMisc</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceCoefficients2BlockMeanTimeSplines.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceCoefficients2BlockMeanTimeSplines</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceCoefficients2BlockMeanTimeSplines</h1><p>\n\nThis program converts potential coefficients from the GRACE SDS RL06 format\ninto <a class=\"groops-class\" href=\"fileFormat_timeSplinesGravityField.html\">outputfileTimeSplines</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> contains the mid points\nof non-empty intervals and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeIntervals</a>\ncontains the monthly interval boundaries from first to last solution.</p><p>The output will always be monthly block means. If the SDS solutions do vary or overlap,\nthe nearest solution in terms of reference epoch is used.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSplines</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTimeSplinesCovariance</div></div></td><td>filename</td><td>only the variances are saved</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTimeSeries</div></div></td><td>filename</td><td>mid points of non-empty intervals</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTimeIntervals</div></div></td><td>filename</td><td>monthly interval boundaries from first to last solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1a2Accelerometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1a2Accelerometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1a2Accelerometer</h1><p>\n\nThis program converts Level-1A accelerometer data (ACC1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in <code>GRACEiolib.h</code> given at\n<a href=\"http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz\" target=\"_blank\">http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz</a>.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER in SRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER in SRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>ACC1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1a2SatelliteTracking.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1a2SatelliteTracking</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1a2SatelliteTracking</h1><p>\n\nThis program converts Level-1A satellite tracking data (KBR1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in <code>GRACEiolib.h</code> given at\n<a href=\"http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz\" target=\"_blank\">http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz</a>.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSatelliteTracking</div></div></td><td>filename</td><td>MISCVALUES(ant_id, K_phase, Ka_phase, K_SNR, Ka_SNR)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>KBR1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1a2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1a2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1a2StarCamera</h1><p>\n\nThis program converts orientation data measured by the star cameras\nfrom the GRACE Level-1A format (SCA1A) to the GROOPS instrument file format.\nFor further information see <a class=\"groops-program\" href=\"GraceL1a2Accelerometer.html\">GraceL1a2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera1</div></div></td><td>filename</td><td>STARCAMERA1A, head 1</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera2</div></div></td><td>filename</td><td>STARCAMERA1A, head 2</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>SCA1A, !GRACE-FO is not working!</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1a2Temperature.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1a2Temperature</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1a2Temperature</h1><p>\n\nThis program converts Level-1A temperature measurments (HRT1B or HRT1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in GRACE given at <a href=\"http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz\" target=\"_blank\">http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz</a>.\nMultiple <strong class=\"groops-config-element\">inputfile</strong>s must be given in the correct time order.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTemperature</div></div></td><td>filename</td><td>MISCVALUES</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>HRT1B or HRT1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2AccHousekeeping.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2AccHousekeeping</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2AccHousekeeping</h1><p>\n\nThis program converts ACC housekeeping data (AHK1B or AHK1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ACCHOUSEKEEPING)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccHousekeeping</div></div></td><td>filename</td><td>ACCHOUSEKEEPING</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>AHK1B or AHK1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Accelerometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Accelerometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Accelerometer</h1><p>\n\nThis program converts accelerometer data (ACC1B or ACT1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ACCELEROMETER)</a>.</p><p>Multiple <strong class=\"groops-config-element\">inputfile</strong>s must be given in the correct time order.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p>The GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\"\ngiven at <a href=\"https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf\" target=\"_blank\">https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileFlags</div></div></td><td>filename</td><td>MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>ACC1B or ACT1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2ClockOffset.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2ClockOffset</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2ClockOffset</h1><p>\n\nThis program converts clock data (CLK1B or LLK1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileClock</div></div></td><td>filename</td><td>MISCVALUE</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>CLK1B or LLK1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2GnssReceiver.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2GnssReceiver</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2GnssReceiver</h1><p>\n\nThis program converts GPS receiver data (phase and pseudo range) data\nfrom the GRACE SDS format (GPS1B or GPS1A) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (GNSSRECEIVER)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGnssReceiver</div></div></td><td>filename</td><td>GNSSRECEIVER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>GPS1B or GPS1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Magnetometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Magnetometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Magnetometer</h1><p>\n\nThis program converts magnetometer data (MAG1B or MAG1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MAGNETOMETER)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMagnetometer</div></div></td><td>filename</td><td>MAGNETOMETER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>MAG1B or MAG1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Mass.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Mass</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Mass</h1><p>\n\nThis program converts mass data (MAS1B or MAS1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MASS)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMass</div></div></td><td>filename</td><td>MASS</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>MAS1B or MAS1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Orbit</h1><p>\n\nThis program converts the reduced dynamical orbit\nfrom the GRACE/GRACE-FO SDS format (GNV1B, GNI1B) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.</p><p>When GNV1B is used, the orbit can be rotated from the terrestrial reference frame (TRF) transformed into the celestial reference frame (CRF) by\nspecifying <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>.</p><p>For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>to rotate GNV1B into CRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>GNV1B/GNI1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2SatelliteTracking.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2SatelliteTracking</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2SatelliteTracking</h1><p>\n\nThis program converts low-low satellite data measured by the K-band ranging system\nfrom the GRACE SDS format (KBR1B or LRI1B) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITETRACKING)</a>.\nThe <strong class=\"groops-config-element\">inputfile</strong>s contain also corrections to antenna offsets\nand the so called light time correction. The corrections can be stored in additional files\nin the same format as the observations.\nIf a phase break is found an artificial gap is created.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSatelliteTracking</div></div></td><td>filename</td><td>SATELLITETRACKING</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntCentr</div></div></td><td>filename</td><td>SATELLITETRACKING</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileLighttime</div></div></td><td>filename</td><td>SATELLITETRACKING</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSNR</div></div></td><td>filename</td><td>MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileIonoCorr</div></div></td><td>filename</td><td>MISCVALUE</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>KBR1B or LRI1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2StarCamera</h1><p>\n\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GRACE SDS format (SCA1B) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCameraFlags</div></div></td><td>filename</td><td>MISCVALUES(sca_id, qual_rss, qualflg)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>SCA1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2StarCameraCovariance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2StarCameraCovariance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2StarCameraCovariance</h1><p>\n\nThis program computes star camera covariance matrices (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file, COVARIANE3D</a>)\nfor a GRACE satellite under consideration of the active camera heads and an a priori variance factor.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCameraCovariance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCameraFlags</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSequenceOfEventsQSA</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigma0</div></div></td><td>double</td><td>[seconds of arc]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2SteeringMirror.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2SteeringMirror</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2SteeringMirror</h1><p>\n\nThis program converts GRACE-FO Steering Mirror output (LSM1B) to an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>LSM1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Thruster.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Thruster</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Thruster</h1><p>\n\nThis program converts thruster data (THR1B or THR1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (THRUSTER)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileThruster</div></div></td><td>filename</td><td>THRUSTER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>THR1B or THR1A</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2TimeOffset.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2TimeOffset</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2TimeOffset</h1><p>\n\nThis program converts time data (TIM1A or TIM1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTime</div></div></td><td>filename</td><td>MISCVALUE</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">fractionalScale</div></div></td><td>double</td><td>1e-6 for GRACE, 1e-9 for GRACE-FO</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>TIM1A or TIM1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Uso.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Uso</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Uso</h1><p>\n\nThis program converts clock data (USO1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUES)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileUso</div></div></td><td>filename</td><td>MISCVALUES(uso_freq, K_freq, Ka_freq)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>USO1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceL1b2Vector.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceL1b2Vector</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceL1b2Vector</h1><p>\n\nThis program reads vector orientation data (positions of instruments in the satellite frame) from the GRACE SDS format\n(VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B).\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileVector</a> is a $(3n\\times1)$ matrix containing $(x,y,z)$ for each record.\nThe GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\"\ngiven at <a href=\"http://podaac.jpl.nasa.gov/grace/documentation.html\" target=\"_blank\">http://podaac.jpl.nasa.gov/grace/documentation.html</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileVector</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td>VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceOrbit2TransplantTimeOffset.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceOrbit2TransplantTimeOffset</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceOrbit2TransplantTimeOffset</h1><p>\n\nThis program computes the time shift between two co-orbiting satellites based on dynamic orbit data.\nWhen applied to data of the first satellite, the computed time shift virtually shifts data of first satellite into the location of the second satellite.\nNote that <strong class=\"groops-config-element\">inputfileOrbit1</strong> and <strong class=\"groops-config-element\">inputfileOrbit2</strong> need velocity and acceleration data, which\ncan be computed with <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>.\nThe program tries to find a minimum of the objective function\n\\[\n  f(\\Delta t) = \\| r_1(t) - r_2(t + \\Delta t) \\|^2,\n\\]by applying Newton's method to the first derivative, thus iteratively computing\n\\[\n  \\Delta t_{k+1} = \\Delta t_k + \\frac{f'(\\Delta t_k)}{f''(\\Delta t_k)}.\n\\]This iteration is stopped when the difference between to consecutive time shift values falls below <strong class=\"groops-config-element\">threshold</strong> or\n<strong class=\"groops-config-element\">maximumIterations</strong> is reached. An <strong class=\"groops-config-element\">initialGuess</strong> of the time shift can speed up convergence.</p><p>See also <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a> and <a class=\"groops-program\" href=\"InstrumentApplyTimeOffset.html\">InstrumentApplyTimeOffset</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeOffset</div></div></td><td>filename</td><td>estimated time offset in seconds (MISCVALUE)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td>orbit data of satellite 1</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td>orbit data of satellite 2</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>polynomial degree for the interpolation of position, velocity and acceleration</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">initialGuess</div></div></td><td>double</td><td>initial guess for the time shift [seconds]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maximumIterations</div></div></td><td>uint</td><td>maximum number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">threshold</div></div></td><td>double</td><td>when the maximum difference between two iterations is below this value, stop [seconds]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceSequenceOfEvents.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceSequenceOfEvents</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceSequenceOfEvents</h1><p>\n\nThis program converts the GRACE SOE (sequence of events) file/format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUES)</a>.\nThe GRACE SOE format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" and \"TN-03_SOE_format.txt\"\ngiven at <a href=\"http://podaac.jpl.nasa.gov/grace/documentation.html\" target=\"_blank\">http://podaac.jpl.nasa.gov/grace/documentation.html</a>.\nThe output is one arc of satellite data which can include data gaps.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGraceA</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGraceB</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td>SoE file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">events</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ACCT</div></div></td><td>sequence</td><td>DSHL HeaterDisconnect</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">mode</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">Heater</div></div></td><td></td><td>DSHL HeaterDisconnect</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">SetPoint</div></div></td><td></td><td>temperature set point</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">AOCS</div></div></td><td>sequence</td><td>coarse pointing mode or attitude hold mode</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">mode</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">CPM</div></div></td><td></td><td>coarse pointing mode</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">AHM</div></div></td><td></td><td>attitude hold mode</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">SM</div></div></td><td></td><td>science mode</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ACCR</div></div></td><td></td><td>ACCR</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">CMCAL</div></div></td><td>sequence</td><td>CoM calibration maneuver</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] create events between start and end of maneuver</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">KBRCAL</div></div></td><td>sequence</td><td>KBR calibration maneuver</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] create events between start and end of maneuver</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">VCM</div></div></td><td></td><td>CoM coordinates in SRF (m)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">VKB</div></div></td><td></td><td>KBR phase center coordinates in SRF (m)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ICUVP</div></div></td><td></td><td>ICUVP</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">IPU</div></div></td><td></td><td>IPU</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">IPUR</div></div></td><td></td><td>IPUR</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">KAMI</div></div></td><td></td><td>KAMI: time tag offset to Ka-phase meas.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">KMI</div></div></td><td></td><td>K_MI: time tag offset to K-phase meas.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">KTOFF</div></div></td><td></td><td>KTOFF: time tag offset to KBR meas.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MANV</div></div></td><td></td><td>MANV</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MTE1</div></div></td><td></td><td>MTE1</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MTE2</div></div></td><td></td><td>MTE2</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">OCC</div></div></td><td></td><td>OCC</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">QSA</div></div></td><td></td><td>SCA to SRF frame rotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">QKS</div></div></td><td></td><td>SCA to KBR frame rotation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceSstResidualAnalysis.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceSstResidualAnalysis</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceSstResidualAnalysis</h1><p>\n\nThis program applies the Multi-Resolution Analysis (MRA) using\nDiscrete Wavelet Transform (DWT) to the monthly GRACE SST post-fit residuals.\nFirst, the residuals are transferred into wavelet domain by applying an 8 level\nDaubechies wavelet transform (default).\nIn the next step, detail coefficients are merged into three major groups\ndue to their approximate frequency subbands:\n<ul>\n\n<li>Low scale details, corresponding to the frequency band above 10 mHz;\n</li><li>\nIntermediate scale details, corresponding to the approximate frequency\n      range above 3 mHz up to 10 mHz;\n</li><li>\nHigh scale details, corresponding to the approximate frequency range\nabove 0.5 mHz up to 10 mHz.\n</li></ul>\n\nIn the last step, each group is reconstructed back into time domain.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrumentHighScale</div></div></td><td>filename</td><td>High scale details</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrumentMidScale</div></div></td><td>filename</td><td>Intermediate scale details</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrumentLowScale</div></div></td><td>filename</td><td>Low scale details</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td>GRACE SST Residuals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileWavelet</div></div></td><td>filename</td><td>wavelet coefficients</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceSstScaleModel.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceSstScaleModel</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceSstScaleModel</h1><p>\n\nThis programs estimate satellite-to-satellite-tracking (SST) deterministic signals\ndue to eclipse transits and low-SNR values from post-fit residuals.\nThe low-SNR effects are estimated by directly using the residual values.\nThe ensemble averaging method is used to characterize the average properties of eclipse transit signal shapes across all transit events.\nEach shape is assigned to one arc of 3 hours (default). This can be modefied by enabling <strong class=\"groops-config-element\">averagingInterval</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGraceResiduals</div></div></td><td>filename</td><td>SST Residuals</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeMargin</div></div></td><td>uint</td><td>epochs before instrumental events</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">waveLength</div></div></td><td>uint</td><td>length of the sample wave</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateEclipseTransitScale</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfileScaleModel</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGrace1EclipseFactor</div></div></td><td>filename</td><td>GRACE-A eclipse factors computed with integrated orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGrace2EclipseFactor</div></div></td><td>filename</td><td>GRACE-B eclipse factors computed with integrated orbit</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">averagingInterval</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">nearestNeighborNumber</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateLowSnrScale</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfileScaleModel</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGraceSstSNR</div></div></td><td>filename</td><td>GRACE SNR values</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceSstSpecialEvents.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceSstSpecialEvents</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceSstSpecialEvents</h1><p>\n\nTime-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions\ninto the star camera baffles of GRACE-A and eclipse transits of the satellites.\nThe events are determined by satellites' position (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit1/2</a>)\nand orientation (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera1/2</a>). Each type of event is represented\nby its mid-interval point per orbit revolution and is reported in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileEvents</a>.</p><p>The waveform of each event is nearly constant within one month and can be approximated by a polynomial.\nFor the purpose of gravity field recovery, each waveform is parameterized by a polynomial and the coefficients\nof this polynomial are estimated as additional instrument calibration parameters in a common adjustment\nwith all other instrument, satellite, and gravity field parameters,\nsee <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html#specialEffect\">parametrizationSatelliteTracking:specialEffect</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEvents</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileIntervals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">marginLeft</div></div></td><td>double</td><td>margin size (on both sides) [seconds]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">marginRight</div></div></td><td>double</td><td>margin size (on both sides) [seconds]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GraceThrusterResponse2Accelerometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GraceThrusterResponse2Accelerometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GraceThrusterResponse2Accelerometer</h1><p>\n\nAdd modeled thruster responses to accelerometer data.\nThe epochs and durations are given in the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileThruster</a> (THRUSTER).</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileThrusterResponse</a> is a $(6\\times 3)$ matrix with\nthe linear accelerations in the SRF ($x, y, z$) in one line per pair:\n<ol>\n\n<li>Negative Yaw,\n</li><li>\nPositive Pitch,\n</li><li>\nPositive Yaw,\n</li><li>\nNegative Pitch,\n</li><li>\nNegative Roll,\n</li><li>\nPositive Roll.\n</li></ol>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td>ACCELEROMETER</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileThruster</div></div></td><td>filename</td><td>THRUSTER</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileThrusterResponse</div></div></td><td>filename</td><td>thruster model (matrix with one line per pair)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GrailCdr2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GrailCdr2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GrailCdr2Orbit</h1><p>\n\nThis program converts the orbit from the GRAIL SDS format into  <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GrailCdr2SatelliteTracking.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GrailCdr2SatelliteTracking</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GrailCdr2SatelliteTracking</h1><p>\n\nThis program converts low-low satellite data measured by the K-band ranging system\nfrom the GRAIL format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITETRACKING)</a>.\nThe <strong class=\"groops-config-element\">inputfile</strong>s contain also corrections for antenna offsets\nand the so called light time correction.\nThe corrections can be stored in additional files in the same format as the observations.\nIf a phase break is found an artificial gap is created.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSatelliteTracking</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAntCentr</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileLighttime</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTemperature</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approximateTimeBias</div></div></td><td>double</td><td>[seconds]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GrailCdr2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GrailCdr2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GrailCdr2StarCamera</h1><p>\n\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GRAIL SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>.\nFor further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2AbsoluteGravity.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2AbsoluteGravity</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2AbsoluteGravity</h1><p>\n\nThis program computes the absolute value of gravity $\\left\\lVert{\\M g}\\right\\rVert$\nof a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>.\nThe result is multiplicated with <strong class=\"groops-config-element\">factor</strong>.\nTo get the full gravity vector in a terrestrial frame add\nthe centrifugal part, see <a class=\"groops-class\" href=\"tidesType.html#centrifugal\">gravityfield:tides:centrifugal</a>.</p><p>The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.</p><p>It is intended to compute gravity anomalies from absolute gravity observations.\nTo visualize the results use <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2AreaMeanTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2AreaMeanTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2AreaMeanTimeSeries</h1><p>\n\nThis program computes a time series of time variable\n<a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> functionals averaged over a given area,\ne.g. equivalent water heights in the amazon basin.  The type of functional\n(e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nThe average is performed at each time step by a weigthed average over all <a class=\"groops-class\" href=\"gridType.html\">grid</a>\npoints where the weight is the associated area at each point. If <strong class=\"groops-config-element\">removeMean</strong> is set\nthe temporal mean is removed from the time series. To speed up the computation\nthe gravity field can be converted to spherical harmonics before the computation\nwith <strong class=\"groops-config-element\">convertToHarmonics</strong>.</p><p>Additionally the root mean square of the values in the area at each time step\ncan is computed if <strong class=\"groops-config-element\">compueRms</strong> is set.</p><p>Additionally the accuracy of the value at each time step can be computed if <strong class=\"groops-config-element\">compueSigma</strong> is set.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> is an instrument file with one, two, or three data columns.\nFirst data column contains the computed functionals and the following columns contain the RMS and the accuracies (optionally).</p><p>To visualize the results use <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/gravityfield2AreaMeanTimeSeries.png\" alt=\"gravityfield2AreaMeanTimeSeries\"><figcaption class=\"center\">Figure: Amazon basin: Area mean values of ITSG-Grace2016 monthly solutions with error bars from computed sigma.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">convertToHarmonics</div></div></td><td>boolean</td><td>gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">multiplyWithArea</div></div></td><td>boolean</td><td>multiply time series with total area (useful for mass estimates)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeMean</div></div></td><td>boolean</td><td>remove the temporal mean of the series</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeRms</div></div></td><td>boolean</td><td>additional rms each time step</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeSigma</div></div></td><td>boolean</td><td>additional error bars at each time step</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2Deflections.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2Deflections</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2Deflections</h1><p>\n\nThis program computes the deflections of the vertical $\\xi$ in north direction\nand $\\eta$ in east direction in radian\naccording to\n\\[\n\\xi = g_x/\\gamma \\qquad\\text{and}\\qquad \\eta=g_y/\\gamma,\n\\]where $\\M g=\\nabla V$ is the gravity vector from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> in\nthe local ellipsoidal system (north, east, up) and $\\gamma$ is the normal gravity at that point.</p><p>The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>xi (north), eta (east) [rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2DegreeAmplitudes.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2DegreeAmplitudes</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2DegreeAmplitudes</h1><p>\n\nThis program computes degree amplitudes from a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nand saves them to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file with three columns: the degree, the degree amplitude, and the formal errors.</p><p>The coefficients can be converted to different functionals with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nThe gravity field can be evaluated at different altitudes by specifying <strong class=\"groops-config-element\">evaluationRadius</strong>.\nPolar regions can be excluded by setting <strong class=\"groops-config-element\">polarGap</strong>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.\nThe coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong>\nand the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>See also <a class=\"groops-program\" href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>three column matrix with degree, signal amplitude, formal error</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td>type of variances</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rms</div></div></td><td></td><td>degree amplitudes (square root of degree variances)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">accumulation</div></div></td><td></td><td>cumulate variances over degrees</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">median</div></div></td><td></td><td>median of absolute values per degree</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">evaluationRadius</div></div></td><td>double</td><td>evaluate the gravity field at this radius (default: evaluate at surface</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">polarGap</div></div></td><td>angle</td><td>exclude polar regions (aperture angle in degrees)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2DegreeAmplitudesPlotGrid.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2DegreeAmplitudesPlotGrid</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2DegreeAmplitudesPlotGrid</h1><p>\n\nThis program computes a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>\nof a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and saves it as degree amplitudes.\nThe expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly\n\\[\n  \\sigma_n = \\frac{GM}{R}\\left(\\frac{R}{r}\\right)^{n+1}k_n\\sqrt{\\sum_{m=0}^n c_{nm}^2+s_{nm}^2}.\n\\]\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileTimeSeries</a> is a matrix with\nevery row containing the time, degree, degree amplitude, and the formal error.</p><p>To visualize the results use <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>).</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a>.</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/gravityfield2DegreeAmplitudesPlotGrid.png\" alt=\"gravityfield2DegreeAmplitudesPlotGrid\"><figcaption class=\"center\">Figure: Degree amplitudes of monthly ITSG-Grace2016 solutions relative to GOCO05s.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>each row: mjd, degree, amplitude, formal error</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">evaluationRadius</div></div></td><td>double</td><td>evaluate the gravity field at this radius (default: evaluate at surface</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">polarGap</div></div></td><td>angle</td><td>exclude polar regions (aperture angle in degrees)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td>minimal degree</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>maximal degree</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2DisplacementTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2DisplacementTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2DisplacementTimeSeries</h1><p>\n\nThis program computes a time series of displacements of a list of stations (<a class=\"groops-class\" href=\"gridType.html\">grid</a>)\ndue to the effect of time variable loading masses. The displacement $\\M u$ of a station is calculated according to\n\\[\\label{eq:displacement}\n\\M u(\\M r) = \\frac{1}{\\gamma}\\sum_{n=0}^\\infty \\left[\\frac{h_n}{1+k_n}V_n(\\M r)\\,\\M e_{up}\n+ R\\frac{l_n}{1+k_n}\\left(\n \\frac{\\partial V_n(\\M r)}{\\partial \\M e_{north}}\\M e_{north}\n+\\frac{\\partial V_n(\\M r)}{\\partial \\M e_{east}} \\M e_{east}\\right)\\right],\n\\]where $\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDeformationLoadLoveNumber</a> and the load Love numbers $k_n$ are given by\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePotentialLoadLoveNumber</a>. The $V_n$ are the spherical harmonics expansion of\nthe full time variable gravitational potential (potential of the loading mass + deformation potential):\n\\[\nV(\\M r) = \\sum_{n=0}^\\infty V_n(\\M r).\n\\]Deformations due to Earth tide and due to polar tides are computed using the IERS conventions.\nEq. \\eqref{eq:displacement} is not used in these cases.</p><p>The <strong class=\"groops-config-element\">outputfileTimeSeries</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>, MISCVALUES.\nThe data columns contain the deformation of each station in $x,y,z$ in a global terrestrial\nreference frame or alternatively in a local elliposidal frame (north, east, up)\nif <strong class=\"groops-config-element\">localReferenceFrame</strong> is set.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>x,y,z [m] per station</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td>station list</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">tides</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDeformationLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfilePotentialLoadLoveNumber</div></div></td><td>filename</td><td>if full potential is given and not only loading potential</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeMean</div></div></td><td>boolean</td><td>remove the temporal mean of each coordinate</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">localReferenceFrame</div></div></td><td>boolean</td><td>local left handed reference frame (north, east, up)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2EmpiricalCovariance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2EmpiricalCovariance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2EmpiricalCovariance</h1><p>\n\nThis program estimates an spatial and temporal covariance matrix from\na time series of gravity fields.</p><p>Firstly for every time step $t_i$\na spherical harmonics vector $\\M x_i$ from the time variable gravity field\nis generated. The coefficients of the spherical harmonics expansion are\nin the sequence given by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the\nreference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>In the next step the empirical covariance matrix is estimated according to\n\\[\n\\M\\Sigma(\\Delta i)_{full} = \\frac{1}{N}\\sum_{i=1}^N \\M x_i \\M x_{i+\\Delta i}^T,\n\\]where $\\Delta i$ is given by <strong class=\"groops-config-element\">differenceStep</strong>.</p><p>From the diagonal elements of $\\M\\Sigma(\\Delta i)$ the isotropic accuracies\nare computed\n\\[\n\\sigma_n^2 = \\frac{1}{2n+1}\\sum_{m=0}^n \\sigma_{cnm}^2+\\sigma_{snm}^2,\n\\]and a diagonal matrix is constructed $\\Sigma_{iso} = \\text{diag}(\\sigma_2^2,\\ldots,\\sigma_N^2)$.\nThe result is computed:\n\\[\n\\M\\Sigma(\\Delta i) = \\alpha_{full}\\M\\Sigma(\\Delta i)_{full}+\\alpha_{iso}\\M\\Sigma(\\Delta i)_{iso}.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCovarianceMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme for solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeMean</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>sampling of the gravityfield</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">differenceStep</div></div></td><td>uint</td><td>choose dt for: x,i(t) - x,j(t+dt)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factorFullMatrixPart</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factorIsotropicPart</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">intervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2Gradients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2Gradients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2Gradients</h1><p>\n\nThis program computes gravity gradients from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\non a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in a global terrestrial reference frame\nor alternatively in a local elliposidal frame (north, east, up) if <strong class=\"groops-config-element\">localReferenceFrame</strong> is set.\nIn <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> the values $[Vxx, Vyy, Vzz, Vxy, Vxz, Vyz]$\nwill be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>Vxx Vyy Vzz Vxy Vxz Vyz</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">localReferenceFrame</div></div></td><td>boolean</td><td>local left handed reference frame (north, east, up)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2GravityVector.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2GravityVector</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2GravityVector</h1><p>\n\nThis program computes gravity vectors from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\non a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in a global terrestrial reference frame\nor alternatively in a local elliposidal frame (north, east, up) if <strong class=\"groops-config-element\">localReferenceFrame</strong> is set.\nIn <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> the values $[gx, gy, gz]$\nwill be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>gx, gy, gz</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">localReferenceFrame</div></div></td><td>boolean</td><td>local left handed reference frame (north, east, up)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2GridCovarianceMatrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2GridCovarianceMatrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2GridCovarianceMatrix</h1><p>\n\nThis program propagates the covariance matrix of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nevaluated at <strong class=\"groops-config-element\">time</strong> to a <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The full variance-covariance matrix is computed\nand written to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix file</a>:\n\\[\n\\mathbf{\\Sigma}_\\mathbf{y} = \\mathbf{F}\\mathbf{\\Sigma}_\\mathbf{x}\\mathbf{F}^T\n\\]The <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> determines the quantity of the grid values, for example,\n<a class=\"groops-class\" href=\"kernelType.html#waterHeight\">kernel:waterHeight</a>.</p><p>See also <a class=\"groops-program\" href=\"GravityfieldCovariancesPropagation2GriddedData.html\">GravityfieldCovariancesPropagation2GriddedData</a>, <a class=\"groops-program\" href=\"GravityfieldVariancesPropagation2GriddedData.html\">GravityfieldVariancesPropagation2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>symmetric grid covariance matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2GriddedData</h1><p>\n\nThis program computes values of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>.\nThe type of value (e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nIf a time is given the gravity field will be evaluated at this point of time otherwise only the static part will be used.\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\nTo speed up the computation the gravity field can be converted to spherical harmonics before the computation\nwith <strong class=\"groops-config-element\">convertToHarmonics</strong>.</p><p>To visualize the results use <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">convertToHarmonics</div></div></td><td>boolean</td><td>gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2GriddedDataTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2GriddedDataTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2GriddedDataTimeSeries</h1><p>\n\nThis program computes values of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>\nfor each time step of <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>.\nThe type of value (e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nTo speed up the computation the gravity field can be converted to spherical harmonics before the computation\nwith <strong class=\"groops-config-element\">convertToHarmonics</strong>.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> is an instrument (MISCVALUES) file with a data column\nfor each grid point per epoch.</p><p>This program enables the use of all instrument programs like <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a>,\n<a class=\"groops-program\" href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a> or <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> to analyze and manipulate time series of gridded data.</p><p>See also <a class=\"groops-program\" href=\"TimeSeries2GriddedData.html\">TimeSeries2GriddedData</a>, <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>each epoch: data of grid points (MISCVALUES)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">convertToHarmonics</div></div></td><td>boolean</td><td>gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2PotentialCoefficients</h1><p>\n\nThis program evaluates a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nat a given <strong class=\"groops-config-element\">time</strong> and saves it as a <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">spherical harmonics file</a>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.\nThe coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong>\nand the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2PotentialCoefficientsTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2PotentialCoefficientsTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2PotentialCoefficientsTimeSeries</h1><p>\n\nThis program computes a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>\nof a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nand converts to coefficients of a spherical harmonics expansion.\nThe expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.\nThe coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong>\nand the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> contains the potential coefficients\nas data columns for each epoch in the sequence given by\n<a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>instrument file (MISCVALUES)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2SphericalHarmonicsVector.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2SphericalHarmonicsVector</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2SphericalHarmonicsVector</h1><p>\n\nThis program evaluates a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> at a given <strong class=\"groops-config-element\">time</strong>\nand saves a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">vector</a> with the coefficients of a spherical harmonics expansion in the sequence given by\n<a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusively.\nThe coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>This coefficients vector can be used as a approximate solution, see <a class=\"groops-program\" href=\"NormalsMultiplyAdd.html\">NormalsMultiplyAdd</a>,\nor as pseudo oberservations for regularization,\nsee <a class=\"groops-class\" href=\"normalEquationType.html#regularization\">normalEquation:regularization</a>.</p><p>For back transformation use <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a>\nwith <a class=\"groops-class\" href=\"gravityfieldType.html#fromParametrization\">gravityfield:fromParametrization</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileVector</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>start index to put the coefficients in the solution vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme for solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useSigma</div></div></td><td>boolean</td><td>use formal errors instead of coefficients</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2TimeSplines.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2TimeSplines</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2TimeSplines</h1><p>\n\nThis program estimates splines in time domain from a time variable gravity field\nand writes <a class=\"groops-class\" href=\"fileFormat_timeSplinesGravityField.html\">outputfileTimeSplines</a>.\nThe <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is sampled at <a class=\"groops-class\" href=\"timeSeriesType.html\">sampling</a>, converted to potential coefficients\nin the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusively.\nThe time series of spherical harmonics can be temporal filtered with <a class=\"groops-class\" href=\"digitalFilterType.html\">temporalFilter</a>.</p><p>In the next step temporal splines with <strong class=\"groops-config-element\">splineDegree</strong> and nodal points given\nat <a class=\"groops-class\" href=\"timeSeriesType.html\">splineTimeSeries</a> are adjusted to the time series in a least squares sense.\nThis is very fast for block means (splineDegree = 0) but for other splines a large systems of equations\nmust be solved. In the adjustment process the time series of gravity fields can be interpreted as samples\nat the given times or as continuous function with linear behaviour between sampled points (<strong class=\"groops-config-element\">linearInterpolation</strong>).</p><p>To combine a series of potential coefficients to a spline file with block means (splineDegree = 0)\nuse the fast <a class=\"groops-program\" href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSplines</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">temporalFilter</div></div></td><td><a href=\"digitalFilterType.html\">digitalFilter</a></td><td>filter sampled gravity field in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">sampling</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>gravity field is sampled at these times</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeMean</div></div></td><td>boolean</td><td>remove the temporal mean of the series before estimating the splines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">linearInterpolation</div></div></td><td>boolean</td><td>assume linear behavior between sampled points</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">splineDegree</div></div></td><td>uint</td><td>degree of splines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">splineTimeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>nodal points of splines in time domain</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Gravityfield2TrendPotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravityfield2TrendPotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Gravityfield2TrendPotentialCoefficients</h1><p>\n\nThis program estimates <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>\n(e.g. mean, trend, annual) from a time variable gravity field.</p><p>In a first step a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nis sampled at <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>\nand converted to coefficients of a spherical harmonics expansion.\nThe expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusively.\nThe coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong>\nand the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>These coefficients serves as observations of\na <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a> to estimate\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> parameters.\nFor each temporal parameter an\n<a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>\nis generated.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td>for each temporal parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberMaxIteration</div></div></td><td>uint</td><td>(maximum) number of iterations for robust estimation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GravityfieldCovariancesPropagation2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GravityfieldCovariancesPropagation2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GravityfieldCovariancesPropagation2GriddedData</h1><p>\n\nThis program computes the covariance between a source point given\nby longitude/latitude (<strong class=\"groops-config-element\">L</strong>, <strong class=\"groops-config-element\">B</strong>) and the points of a <a class=\"groops-class\" href=\"gridType.html\">grid</a>\nin terms of the functional given by <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> from the variance-covariance\nmatrix of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> evaluated at <strong class=\"groops-config-element\">time</strong>.</p><p>If <strong class=\"groops-config-element\">computeCorrelation</strong> is set, the program returns the correlation according to\n\\[\nr_{ij} = \\frac{\\sigma_{ij}}{\\sigma_i \\sigma_j}\n\\]in the range of [-1, 1] instead of the covariance.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2GridCovarianceMatrix.html\">Gravityfield2GridCovarianceMatrix</a>, <a class=\"groops-program\" href=\"GravityfieldVariancesPropagation2GriddedData.html\">GravityfieldVariancesPropagation2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>gridded data file containing the covariance betwenn source point and grid points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>functional</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">L</div></div></td><td>angle</td><td>longitude of variance point</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">B</div></div></td><td>angle</td><td>latitude of variance point</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>ellipsoidal height of source point</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeCorrelation</div></div></td><td>boolean</td><td>compute correlations instead of covariances</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GravityfieldReplacePotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GravityfieldReplacePotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GravityfieldReplacePotentialCoefficients</h1><p>\n\nReplaces single potential coefficients in a gravity field.\nBoth <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nand <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfieldReplacement</a> are evaluated\nat <strong class=\"groops-config-element\">time</strong> and converted to spherical harmonic coefficients.\nSingle <strong class=\"groops-config-element\">coefficients</strong> are then replaced in <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nby the values from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfieldReplacement</a>\nand the result is written to <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>\nfrom <strong class=\"groops-config-element\">minDegree</strong> to <strong class=\"groops-config-element\">maxDegree</strong>,\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>single coefficients are replaced by the other gravityfield</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfieldReplacement</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>contains the coefficients for replacement</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">coefficients</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">cnm</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">degree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">snm</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">degree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GravityfieldVariancesPropagation2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GravityfieldVariancesPropagation2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GravityfieldVariancesPropagation2GriddedData</h1><p>\n\nThis program propagates variance-covariance matrix of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>\nevaluated at <strong class=\"groops-config-element\">time</strong> to the points of a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in terms of the functional\ngiven by <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nThe resulting <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> contains the standard deviations of the grid\npoints.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2GridCovarianceMatrix.html\">Gravityfield2GridCovarianceMatrix</a>, <a class=\"groops-program\" href=\"GravityfieldCovariancesPropagation2GriddedData.html\">GravityfieldCovariancesPropagation2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>standard deviation at each grid point</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>functional</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GridRectangular2NetCdf.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GridRectangular2NetCdf</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GridRectangular2NetCdf</h1><p>\n\nDEPRECATED since 2023-07-06. Please use <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a> or <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNetCdf</div></div></td><td>filename</td><td>file name of NetCDF output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGridRectangular</div></div></td><td>filename</td><td>input grid sequence</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">times</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>values for time axis (COARDS specification)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">dataVariable</div></div></td><td>sequence</td><td>metadata for data variables</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">selectDataField</div></div></td><td>uint</td><td>input data column</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td>netCDF variable name</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">attribute</div></div></td><td>choice</td><td>netCDF attributes</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">text</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">value</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">globalAttribute</div></div></td><td>choice</td><td>additional meta data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">text</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2AreaMeanTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2AreaMeanTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2AreaMeanTimeSeries</h1><p>\n\nThis program computes a time series of area mean values\nin a basin represented by <a class=\"groops-class\" href=\"borderType.html\">border</a> from a sequence of grid files.\nIf a file is not found, the epoch is skipped. Per default\nthe weighted average of all points in the given border is computed where the points are weighted by their area element.</p><p>If <strong class=\"groops-config-element\">computeMean</strong> is set, the time average of each grid points is subtracted before the computation.\nIf <strong class=\"groops-config-element\">multiplyWithArea</strong> is set, the weighted average is multiplied with the total basin area.\nThis is useful for computing the total mass in the basin.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> is an instrument file, where the first columns are the\nmean value each data column in the grid files, followed by the the weighted RMS\nfor each data column in the grid files if <strong class=\"groops-config-element\">computeRms</strong> is set.\nIf the number of data columns differs between the grid files, the remaining columns are padded with zeros.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2AreaMeanTimeSeries.html\">Gravityfield2AreaMeanTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">multiplyWithArea</div></div></td><td>boolean</td><td>multiply time series with total area (useful for mass estimates)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeMean</div></div></td><td>boolean</td><td>remove the temporal mean of the series</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeRms</div></div></td><td>boolean</td><td>additional rms each time step</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2GriddedDataStatistics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2GriddedDataStatistics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2GriddedDataStatistics</h1><p>\n\nThis program assigns values <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to the nearest points\nof a new <a class=\"groops-class\" href=\"gridType.html\">grid</a>. If some of the new points are not filled in with data\n<strong class=\"groops-config-element\">emptyValue</strong> is used instead. If multiple points of the input fall on the same node\nthe result can be selected with <strong class=\"groops-config-element\">statistics</strong> (e.g. mean, root mean square, min, max, &hellip; ).\nIt also is possible to simply count the number of data points that were assigned to each point.</p><p>Be aware in case borders are given within <a class=\"groops-class\" href=\"gridType.html\">grid</a>, the <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> will have points excluded before the assignement of old points to the new points.\nThe data from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> will not be limited by the given borders! See <a class=\"groops-ref\" href=\"GriddedDataConcatenate.html\">GriddedDataConcatenate</a> to limit the\n<a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to given borders.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/griddedData2GriddedDataStatistics.png\" alt=\"griddedData2GriddedDataStatistics\"><figcaption class=\"center\">Figure: Assignement of irregular distributed data to grid.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">statistic</div></div></td><td>choice</td><td>statistic used if multiple values fall on the same cell</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">mean</div></div></td><td></td><td>mean</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">wmean</div></div></td><td></td><td>area weighted mean</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rms</div></div></td><td></td><td>root mean square</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">wrms</div></div></td><td></td><td>area weighted root mean square</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">std</div></div></td><td></td><td>standard deviation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">wstd</div></div></td><td></td><td>area weighted standard deviation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">sum</div></div></td><td></td><td>sum</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">min</div></div></td><td></td><td>minimum value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">max</div></div></td><td></td><td>maximum value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">count</div></div></td><td></td><td>number of values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">first</div></div></td><td></td><td>first value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">last</div></div></td><td></td><td>last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">emptyValue</div></div></td><td>double</td><td>value for nodes without data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2GriddedDataTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2GriddedDataTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2GriddedDataTimeSeries</h1><p>\n\nWrite a series of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>\nwith the corresponding <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>\nas a single <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">gridded data time series file</a>.\nThe <strong class=\"groops-config-element\">splineDegree</strong> defines the possible temporal interpolation of data in the output file.\nFor a file with spline degree 0 (temporal block means) the time intervals\nin which the grids are valid are defined between adjacent points in time.\nTherefore one more point in time is needed than the number of input grid files for degree 0.</p><p>See also <a class=\"groops-program\" href=\"GriddedDataTimeSeries2GriddedData.html\">GriddedDataTimeSeries2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGriddedData</div></div></td><td>filename</td><td>file count must agree with number of times+splineDegre-1</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">splineDegree</div></div></td><td>uint</td><td>degree of splines</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2Matrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2Matrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2Matrix</h1><p>\n\nThis program converts <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>\nto <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> with data columns.\nThe grid is expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\nThe content of the output matrix can be controlled by <strong class=\"groops-config-element\">outColumn</strong> expressions\napplied to every grid point. The common data variables for grids are available,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>point list as matrix with longitude and latitude values in columns and possible additional columns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outColumn</div></div></td><td>expression</td><td>expression (variables: longitude, latitude, height, area, data0, data1, ...)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2NetCdf.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2NetCdf</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2NetCdf</h1><p>\n\nThis program converts a <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>\nto a COARDS compliant NetCDF file. The output data can be defined with <strong class=\"groops-config-element\">dataVariable</strong>.\nYou should add at least the attributes <code>units</code>, <code>long_name</code>, and maybe <code>_FillValue</code>\nto the variables. For the <strong class=\"groops-config-element\">dataVariable:value</strong> the standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNetCdf</div></div></td><td>filename</td><td>file name of NetCDF output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>input grid sequence</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">dataVariable</div></div></td><td>sequence</td><td>metadata for data variables</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td>netCDF variable name</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">value</div></div></td><td>expression</td><td>expression (variables 'height', 'data', 'longitude', 'latitude' and, 'area' are taken from the gridded data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">attribute</div></div></td><td>choice</td><td>netCDF attributes</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">text</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">value</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">globalAttribute</div></div></td><td>choice</td><td>additional meta data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">text</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2PotentialCoefficients</h1><p>\n\nThis program estimate potential coefficients from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>\ngravity field functionals. It used a simple quadrature formular\n\\[\n  c_{nm} = \\frac{1}{4\\pi}\\frac{R}{GM} \\sum_i f_i \\left(\\frac{r_i}{R}\\right)^{n+1} k_n C_{nm}(\\lambda_i,\\vartheta_i)\\,\\Delta\\Phi_i\n\\]or a <strong class=\"groops-config-element\">leastSquares</strong> adjustment with block diagonal normal matrix (order by order).\nFor the latter one the data must be regular distributed.</p><p>The <strong class=\"groops-config-element\">value</strong>s $f_i$ and the <strong class=\"groops-config-element\">weight</strong>s $\\Delta\\Phi_i$ are expressions\nusing the common data variables for grids, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\nMultiple <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> can be estimated in one step.\nFor each an indivdual <strong class=\"groops-config-element\">value</strong> must be specified.\nThe type of the gridded data (e.g gravity anomalies or geoid heights)\nmust be set with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> $k_n$.</p><p>The expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusively. The coefficients are related\nto the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>For irregular distributed data and using the full variance covariance matrix use\n<a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a> together with <a class=\"groops-class\" href=\"observationType.html#terrestrial\">oberservation:terrestrial</a>\nand <a class=\"groops-class\" href=\"parametrizationGravityType.html#sphericalHarmonics\">parametrizationGravity:sphericalHarmonics</a>.</p><p>See also <a class=\"groops-program\" href=\"GriddedDataTimeSeries2PotentialCoefficients.html\">GriddedDataTimeSeries2PotentialCoefficients</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td>one file for each value expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>expression</td><td>expression to compute values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">weight</div></div></td><td>expression</td><td>expression to compute values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>data type of input values</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">leastSquares</div></div></td><td>boolean</td><td>false: quadrature formular, true: least squares adjustment order by order</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2SphericalDistance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2SphericalDistance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2SphericalDistance</h1><p>\n\nCompute the spherical distance on the unit sphere in radians between all point pairs of two grids.\nThe spherical distance is computed by\n\\[\n  \\psi_{12} = \\arccos(\\M n_1 \\cdot \\M n_2),\n\\]where $\\M n_i$ is the (normalized) position. This implies that all points are projected onto the unit sphere.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>matrix containing the spherical distance between all point pairs [rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid1</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid2</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedData2TimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData2TimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData2TimeSeries</h1><p>\n\nWrite a series of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> with the corresponding\n<a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> as a single time series file\n(<a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument</a>, MISCVALUES).</p><p>If <strong class=\"groops-config-element\">groupDataByPoints</strong> is true the <strong class=\"groops-config-element\">outputfileTimeSeries</strong> starts\nfor each epoch with all data (<code>data0</code>, <code>data1</code>&hellip; ) for the first point,\nfollowed by all data of the second point and so on.\nIf <strong class=\"groops-config-element\">groupDataByPoints</strong> is false, the file starts with <code>data0</code>\nfor all points, followed by all <code>data1</code> and so on.</p><p>This enables the use of all instrument programs like <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a> or\n<a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> to analyze and manipulate time series of gridded data.</p><p>See also <a class=\"groops-program\" href=\"TimeSeries2GriddedData.html\">TimeSeries2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>each epoch: multiple data for points (MISCVALUES)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGriddedData</div></div></td><td>filename</td><td>file count must agree with number of times</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">groupDataByPoints</div></div></td><td>boolean</td><td>multiple data are given point by point, otherwise: data0 for all points, followed by all data1</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataCalculate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataCalculate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataCalculate</h1><p>\n\nThis program manipulates <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">grid files</a> with data in columns similar to\n<a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, see there for more details.\nIf several <strong class=\"groops-config-element\">inputfile</strong>s are given the data columns are copied side by side.\nAll <strong class=\"groops-config-element\">inputfile</strong>s must contain the same grid points.\nThe columns are enumerated by <code>data0</code>, <code>data1</code>, &hellip; .</p><p>The content of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> is controlled by <strong class=\"groops-config-element\">outColumn</strong>.\nThe algorithm to compute the output is as follows:\nThe expressions in <strong class=\"groops-config-element\">outColumn</strong> are evaluated once for each grid point of the input.\nThe variables <code>data0</code>, <code>data1</code>, &hellip; are replaced by the according values\nfrom the input columns before.\nAdditional variables are available, e.g. <code>index</code>, <code>data0rms</code>,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>For a simplified handling <strong class=\"groops-config-element\">constant</strong>s can be defined by <code>name=value</code>.\nIt is also possible to estimate <strong class=\"groops-config-element\">parameter</strong>s in a least squares adjustment.\nThe <strong class=\"groops-config-element\">leastSquares</strong> serves as template for observation equations for every point.\nThe expression <strong class=\"groops-config-element\">leastSquares</strong> is evaluated for each grid point.\nThe variables <code>data0</code>, <code>data1</code>, &hellip; are replaced by the according values from the input columns before.\nIn the next step the parameters are estimated in order to minimize the expressions in <strong class=\"groops-config-element\">leastSquares</strong>\nin the sense of least squares.</p><p>Afterwards grid points are removed if one of the <strong class=\"groops-config-element\">removalCriteria</strong> expressions\nfor this grid point evaluates true (not zero).</p><p>An extra <a class=\"groops-class\" href=\"fileFormat_matrix.html\">statistics:outputfile</a> can be generated with one row of data.\nFor the computation of the <strong class=\"groops-config-element\">outColumn</strong> values\nall <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available\n(e.g. <code>data3mean</code>, <code>data4std</code>) inclusively the <strong class=\"groops-config-element\">constant</strong>s and\nestimated <strong class=\"groops-config-element\">parameter</strong>s but without the <code>data0</code>, <code>data1</code>, &hellip; itself.\nThe variables and the numbering of the columns refers to the <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>.</p><p>See also <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>, <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">constant</div></div></td><td>expression</td><td>define a constant by name=value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameter</div></div></td><td>expression</td><td>define a parameter by name[=value]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">leastSquares</div></div></td><td>expression</td><td>try to minimize the expression by adjustment of the parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">removalCriteria</div></div></td><td>expression</td><td>points are removed if one criterion evaluates true. data0 is the first data field.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">longitude</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">latitude</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">height</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">area</div></div></td><td>expression</td><td>expression: e.g. deltaL * 2.0 * sin(deltaB/2.0) * cos(latitude/rho)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">value</div></div></td><td>expression</td><td>expression to compute values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeArea</div></div></td><td>boolean</td><td>automatically area computation of rectangular grids (overwrite area)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">statistics</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>matrix with one row, columns are user defined</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">outColumn</div></div></td><td>expression</td><td>expression to compute statistics columns, data* are the outputColumns</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataConcatenate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataConcatenate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataConcatenate</h1><p>\n\nThis program concatenate grid from several <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>\nand write it to a new <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>.\nInput files must have the same number of data columns.\nIf <strong class=\"groops-config-element\">sort</strong> is enabled, the points are sorted by latitudes starting from north/west to south east.\nIdentical points (within a <strong class=\"groops-config-element\">margin</strong>) can be removed with <strong class=\"groops-config-element\">removeDuplicates</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sortPoints</div></div></td><td>boolean</td><td>sort from north/west to south east</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeDuplicates</div></div></td><td>choice</td><td>remove duplicate points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">keepFirst</div></div></td><td>sequence</td><td>keep first point, remove all other identicals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin distance for identical points [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">keepLast</div></div></td><td>sequence</td><td>keep last point, remove all other identicals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin distance for identical points [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataCreate</h1><p>\n\nThis program creates a <a class=\"groops-class\" href=\"gridType.html\">grid</a> and writes it to <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGrid</a>.\nThe grid is expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\nExtra <strong class=\"groops-config-element\">value</strong> columns can be appended using expressions\nwith the common <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">data variables</a> for gridded data.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGrid</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">value</div></div></td><td>expression</td><td>expression (variables as 'longitude', 'height', 'area' are taken from the gridded data)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataInterpolate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataInterpolate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataInterpolate</h1><p>\n\nInterpolate values of a regular rectangular <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>\nto new points given by <a class=\"groops-class\" href=\"gridType.html\">grid</a> and write as <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>.\nOnly longitude and latitude of points are considered; the height is ignored for interpolation.</p><p>(Only nearest neighbor method is implemented at the moment.)</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/griddedDataInterpolate.png\" alt=\"griddedDataInterpolate\"><figcaption class=\"center\">Figure: Interpolation of point data from rectangular gridded data.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>must be rectangular</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">method</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">nearestNeighbor</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataReduceSampling.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataReduceSampling</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataReduceSampling</h1><p>\n\nGenerate coarse grid by computing area weighted mean values.\nThe number of points is decimated by averaging integer multiplies of grid points\n(<strong class=\"groops-config-element\">multiplierLongitude</strong>, <strong class=\"groops-config-element\">multiplierLatitude</strong>).</p><p>if <strong class=\"groops-config-element\">volumeConserving</strong> is set, data are interpreted as heights above ellipsoid\nand the tesseroid volume\n\\[\n  V=\\int_r^{r+H}\\int_{\\varphi_1}^{\\varphi_2}\\int_{\\lambda_1}^{\\lambda_2} r^2\\cos\\varphi\\,d\\varphi\\,d\\lambda\\,dr\n\\]is conserved, where $r$ is the radius of the ellipsoid at grid center and\n$(\\varphi_1-\\varphi_2)\\times(\\lambda_1-\\lambda_2)$ are the grid cell boundaries.\nThis is meaninful for Digital Elevation Models (DEM).</p><p>The fine grid can be written, where the first coarse grid values (data0) are additionally appended.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCoarseGridRectangular</div></div></td><td>filename</td><td>coarse grid</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileFineGridRectangular</div></div></td><td>filename</td><td>fine grid with additional coarse grid values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileFineGridRectangular</div></div></td><td>filename</td><td>Digital Terrain Model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">multiplierLongitude</div></div></td><td>uint</td><td>Generalizing factor</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">multiplierLatitude</div></div></td><td>uint</td><td>Generalizing factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">volumeConserving</div></div></td><td>boolean</td><td>data are interpreted as heights above ellipsoid</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataTimeSeries2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataTimeSeries2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataTimeSeries2GriddedData</h1><p>\n\nRead a <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a>\nand write for each epoch a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data file</a> where\nthe <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> are expanded for\neach point of the given <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>\nto create the file name for this epoch (see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>).</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is not set\nthe temporal nodal points from the inputfile are used.</p><p>See also <a class=\"groops-program\" href=\"GriddedData2GriddedDataTimeSeries.html\">GriddedData2GriddedDataTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilesGriddedData</div></div></td><td>filename</td><td>for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTime</div></div></td><td>string</td><td>variable with time of each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current epoch (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>otherwise times from inputfile are used</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataTimeSeries2NetCdf.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataTimeSeries2NetCdf</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataTimeSeries2NetCdf</h1><p>\n\nRead a <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a>\nand converts it to a COARDS compliant NetCDF file.</p><p>The output data can be defined with <strong class=\"groops-config-element\">dataVariable</strong>.\nYou should add at least the attributes <code>units</code>, <code>long_name</code>, and maybe <code>_FillValue</code>\nto the variables. The <strong class=\"groops-config-element\">dataVariable:inputColumn</strong> selects the data from the input file.</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is not set\nthe temporal nodal points from the inputfile are used.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNetCdf</div></div></td><td>filename</td><td>file name of NetCDF output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>otherwise times from inputfile are used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">dataVariable</div></div></td><td>sequence</td><td>metadata for data variables</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td>netCDF variable name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputColumn</div></div></td><td>uint</td><td>input data column</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">attribute</div></div></td><td>choice</td><td>netCDF attributes</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">text</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">value</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-4\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">globalAttribute</div></div></td><td>choice</td><td>additional meta data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">text</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">dataType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">double</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">float</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">int</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedDataTimeSeries2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataTimeSeries2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataTimeSeries2PotentialCoefficients</h1><p>\n\nThis program estimate potential coefficients from\n<a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a>\nin the same way as <a class=\"groops-program\" href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a>\nbut not only for one grid but for each epoch of\n<a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> of if not set\nfor the temporal nodal points from the inputfile.\nThe <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>\n(one for each <strong class=\"groops-config-element\">value</strong>) are written for each epoch with the expansion\nof <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong>\n(see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>).</p><p>See also <a class=\"groops-program\" href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfilesPotentialCoefficients</div></div></td><td>filename</td><td>for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTime</div></div></td><td>string</td><td>variable with time of each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current epoch (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>otherwise times from inputfile are used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">value</div></div></td><td>expression</td><td>expression (variables: longitude, latitude, height, area, data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">weight</div></div></td><td>expression</td><td>expression to compute values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>kernel in which the grid values are given</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for potential coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">leastSquares</div></div></td><td>boolean</td><td>false: quadrature formular, true: least squares adjustment order by order</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedTopography2AtmospherePotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedTopography2AtmospherePotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedTopography2AtmospherePotentialCoefficients</h1><p>\n\nEstimate interior and exterior potential coefficients for atmosphere above digital terrain models.\nCoefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.\nThe density of the atmosphere is assumed to be (Sjöberg, 1998)\n\\[\n\\rho_0\\left(\\frac{R}{R+h}\\right)^\\nu,\n\\]where $R$ is the radial distance of the ellipsoid at each point, $h$ the radial height above the ellipsoid,\n$\\rho_0$ is <strong class=\"groops-config-element\">densitySeaLevel</strong> and <strong class=\"groops-config-element\">nu</strong> $\\nu$ is a constant factor. The density is integrated\nfrom <strong class=\"groops-config-element\">radialLowerBound</strong> and <strong class=\"groops-config-element\">upperAtmosphericBoundary</strong> above the ellipsoid.\nThe <strong class=\"groops-config-element\">radialLowerBound</strong> is typically the topography and can be computed as expression at every point\nfrom <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePotentialCoefficientsExterior</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePotentialCoefficientsInterior</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>Digital Terrain Model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">densitySeaLevel</div></div></td><td>double</td><td>[kg/m**3]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ny</div></div></td><td>double</td><td>Constant for Atmosphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radialLowerBound</div></div></td><td>expression</td><td>expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">upperAtmosphericBoundary</div></div></td><td>double</td><td>constant upper bound [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedTopography2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedTopography2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedTopography2PotentialCoefficients</h1><p>\n\nEstimate potential coefficients from digital terrain models.\nCoefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePotentialCoefficientsInterior</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>Digital Terrain Model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">density</div></div></td><td>expression</td><td>expression [kg/m^3]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radialUpperBound</div></div></td><td>expression</td><td>expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radialLowerBound</div></div></td><td>expression</td><td>expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GriddedTopographyEllipsoidal2Radial.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedTopographyEllipsoidal2Radial</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedTopographyEllipsoidal2Radial</h1><p>\n\nInterpolate digital terrain models from ellipoidal heights to radial heights.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>Digital Terrain Model</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GroopsAscii2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GroopsAscii2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GroopsAscii2Orbit</h1><p>\n\nRead Orbits given in groops kinematic orbit ASCII format with covariance information.</p><p>See also <a class=\"groops-program\" href=\"Orbit2GroopsAscii.html\">Orbit2GroopsAscii</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovariance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/GroupPrograms.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GroupPrograms</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GroupPrograms</h1><p>\n\nRuns <strong class=\"groops-config-element\">program</strong>s in a group, which can be used to structure a config file.\nIf <strong class=\"groops-config-element\">catchErrors</strong> is enabled and an error occurs, the remaining <strong class=\"groops-config-element\">program</strong>s\nare skipped and execution continues with <strong class=\"groops-config-element\">errorProgram</strong>s, in case any are defined.\nOtherwise an exception is thrown.</p><p>The <strong class=\"groops-config-element\">silently</strong> option disables the screen ouput of the <strong class=\"groops-config-element\">program</strong>s.\nWith <strong class=\"groops-config-element\">outputfileLog</strong> a log file is written for this group additional to a global log file.\nThis might be helpful within <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> with parallel iterations.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileLog</div></div></td><td>filename</td><td>additional log file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">silently</div></div></td><td>boolean</td><td>without showing the output.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">program</div></div></td><td>programType</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">catchErrors</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">errorProgram</div></div></td><td>programType</td><td>executed if an error occured</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Grs2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Grs2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Grs2PotentialCoefficients</h1><p>\n\nThis program creates potential coefficients from the defining constants\nof a Geodetic Reference System (GRS). The potential coeffiencts excludes the centrifugal part.\nThe form of the reference ellipsoid is either determined by the dynamical form factor <strong class=\"groops-config-element\">J2</strong>,\nor the geometric <strong class=\"groops-config-element\">inverseFlattening</strong>. One of those form parameters must be specified.</p><p>The default values create the GRS80.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">omega</div></div></td><td>double</td><td>Angular velocity of rotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">J2</div></div></td><td>double</td><td>Dynamical form factor</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>Geometric inverse flattening of reference ellipsoid (0: sphere, ignored when J2 is set)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Hw2TideGeneratingPotential.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Hw2TideGeneratingPotential</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Hw2TideGeneratingPotential</h1><p>\n\nWrite <a class=\"groops-file\" href=\"fileFormat_tideGeneratingPotential.html\">tide generating potential</a>\nfrom Hartmann and Wenzel 1995 file, <a href=\"https://doi.org/10.1029/95GL03324\" target=\"_blank\">https://doi.org/10.1029/95GL03324</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTideGeneratingPotential</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">headerLines</div></div></td><td>uint</td><td>skip number of header lines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">referenceTime</div></div></td><td>time</td><td>reference time</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Icgem2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Icgem2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Icgem2PotentialCoefficients</h1><p>\n\nRead spherical harmonics in ICGEM format (<a href=\"http://icgem.gfz-potsdam.de/\" target=\"_blank\">http://icgem.gfz-potsdam.de/</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStaticCoefficients</div></div></td><td>filename</td><td>static potential coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTrendCoefficients</div></div></td><td>filename</td><td>trend potential coefficients in GROOPS gfc format.  Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOscillationCosine</div></div></td><td>filename</td><td>oscillation cosine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOscillationSine</div></div></td><td>filename</td><td>oscillation sine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileIntervals</div></div></td><td>filename</td><td>two column ASCII file with all intervals found (only sensible for icgem2.0). The base name will be extended with .static, .trend, .annualCos, and .annualSin.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileIcgem</div></div></td><td>filename</td><td>ICGEM GFC file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useFormalErrors</div></div></td><td>boolean</td><td>use formal errors if both formal and calibrated errors are given</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Iers2OceanPoleTide.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Iers2OceanPoleTide</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Iers2OceanPoleTide</h1><p>\n\nRead ocean pole tide model according to IERS conventions\nand convert into <a class=\"groops-file\" href=\"fileFormat_oceanPoleTide.html\">oceanPoleTide file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOceanPole</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileLoadingLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>Reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">Omega</div></div></td><td>double</td><td>[rad/s] earth rotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rho</div></div></td><td>double</td><td>[kg/m**3] density of sea water</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">G</div></div></td><td>double</td><td>[m**3/(kg*s**2)] gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">g</div></div></td><td>double</td><td>[m/s**2] gravity</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/IersC04IAU2000EarthOrientationParameter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - IersC04IAU2000EarthOrientationParameter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>IersC04IAU2000EarthOrientationParameter</h1><p>\n\nRead a IERS Earth orientation data C04 (IAU2000A) file\nand write it as <a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">outputfileEOP</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/IersHighFrequentEop2DoodsonEop.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - IersHighFrequentEop2DoodsonEop</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>IersHighFrequentEop2DoodsonEop</h1><p>\n\nRead Diurnal and Subdiurnal Earth Orientation variations according to updated IERS 2010 conventions\nand write them as <a class=\"groops-class\" href=\"fileFormat_doodsonEarthOrientationParameter.html\">outputfileDoodsonEOP</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDoodsonEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/IersPotential2DoodsonHarmonics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - IersPotential2DoodsonHarmonics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>IersPotential2DoodsonHarmonics</h1><p>\n\nRead ocean tide file in IERS format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDoodsonHarmoncis</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">headerLines</div></div></td><td>uint</td><td>skip number of header lines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/IersRapidIAU2000EarthOrientationParameter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - IersRapidIAU2000EarthOrientationParameter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>IersRapidIAU2000EarthOrientationParameter</h1><p>\n\nRead a IERS Earth orientation rapid data and prediction file (IAU2000)\nand write it as <a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">outputfileEOP</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/IersWaterHeight2DoodsonHarmonics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - IersWaterHeight2DoodsonHarmonics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>IersWaterHeight2DoodsonHarmonics</h1><p>\n\nRead ocean tide file in IERS format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDoodsonHarmoncis</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">headerLines</div></div></td><td>uint</td><td>skip number of header lines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td>to compute Xi phase correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>data type of input values</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>to convert in SI units</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/IfPrograms.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - IfPrograms</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>IfPrograms</h1><p>\n\nRuns a list of <strong class=\"groops-config-element\">program</strong>s if a <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is met.\nOtherwise <strong class=\"groops-config-element\">elseProgram</strong>s are executed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">program</div></div></td><td>programType</td><td>executed if condition evaluates to true</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">elseProgram</div></div></td><td>programType</td><td>executed if condition evaluates to false</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Igs2EarthOrientationParameter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Igs2EarthOrientationParameter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Igs2EarthOrientationParameter</h1><p>\n\nRead Rapid Earth Orientation Parameter from IGS daily file\nand write it as <a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">outputfileEOP</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2AllanVariance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2AllanVariance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2AllanVariance</h1><p>\n\nThis program computes the overlapping Allan variance from an\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>.\nThe estimate is averaged over all arcs (arcs are assumed to contain no data gaps).</p><p>The overlapping Allan variance is defined as\n\\[\n  \\sigma^2(m\\tau_0) = \\frac{1}{2(m\\tau_0)^2(N-2m)} \\sum_{n=1}^{N-2m}(x_{n+2m}-2x_{n+m}+x_n)^2,\n\\]where $m\\tau_0$ is the averaging interval defined by the median sampling $\\tau_0$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAllanVariance</div></div></td><td>filename</td><td>column 0: averaging interval [seconds], column 1-(n-1): Allan variance for each data column</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2CovarianceFunctionVCE.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2CovarianceFunctionVCE</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2CovarianceFunctionVCE</h1><p>\n\nThis estimates a covariance function of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\nfor all selected columns with <strong class=\"groops-config-element\">startDataFields</strong> and <strong class=\"groops-config-element\">countDataFields</strong>.\nThe estimation is performed robustly via variance component estimation.\nBad arcs are downweigthed and the accuracies can be written with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmasPerArc</a>.\nThe length of the covariance functions are determined by the longest arc.\nAdditionaly the data can be detrended with <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parameter</a>\nand <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parameterPerArc</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCovarianceFunction</div></div></td><td>filename</td><td>covariance functions</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSigmasPerArc</div></div></td><td>filename</td><td>accuracies of each arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileResiduals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>estimated parameter vector (global part only)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameter</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>data is reduced by temporal representation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameterPerArc</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>data is reduced by temporal representation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>number of iterations for the estimation</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2CrossCorrelationFunction.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2CrossCorrelationFunction</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2CrossCorrelationFunction</h1><p>\n\nThis program computes the cross correlation between all corresponding data columns\nin two <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a>. The instrument files must be synchronized (<a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCorrelation</a> is a matrix with the first column containing the time lag followed by\ncross-correlation function for each data column. The maximum lag is defined by the maximum arc length.</p><p>The correlation is based on the unbiased estimate of the cross-covariance between data columns $x$ and $y$,\n\\[\n  \\sigma_{xy}(h) = \\frac{1}{N}\\sum_{k=1} x_{k+h} y_k,\n\\]which is averaged over all arcs. From this estimate, the correlation for each lag is then computed via\n\\[\n  r_{xy}(h) = \\frac{\\sigma_{xy}(h)}{\\sigma_x(0)\\sigma_y(0)},\n\\]which is the ratio between the biased estimates of the cross-covariance at lag $h$ and the auto-covariance of the individual data columns.</p><p>For instrument with data gaps, lag bins without any data are set to NAN.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCorrelation</div></div></td><td>filename</td><td>column 1: time lag, column 2..n cross-correlation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrumentReference</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2Histogram.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2Histogram</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2Histogram</h1><p>\n\nThis program computes the arc-wise histogram from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\nThe output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> with the first column containing the lower bound of each bin.\nThe other columns contain the histograms for each arc.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrument2Histogram.png\" alt=\"instrument2Histogram\"><figcaption class=\"center\">Figure: GRACE range-rate residuals of one month (one arc) divided into 50 bins.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>column 1: lower bin bound; columns 2 to N: histogram of each arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">selectDataField</div></div></td><td>uint</td><td>select channel for histogram computation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">binCount</div></div></td><td>uint</td><td>(default: Freedman-Diaconis' choice, maximum of all channels)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lowerBound</div></div></td><td>expression</td><td>lower bound for bins (default: global minimum, data values outside are ignored)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">upperBound</div></div></td><td>expression</td><td>upper bound for bins (default: global maximum, data values outside are ignored)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">relative</div></div></td><td>boolean</td><td>output relative frequencies</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">cumulative</div></div></td><td>boolean</td><td>accumulate frequencies</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2PowerSpectralDensity.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2PowerSpectralDensity</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2PowerSpectralDensity</h1><p>\n\nThis program computes the power spectral density (PSD) for all data fields in an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\nThe PSD is computed using Lomb's method. For each arc and each frequency $f$, a sinusoid is fit to the data\n\\[\n  l_i = a \\cos(2\\pi f t_i) + b \\sin(2\\pi f t_i) + e_i\n\\]\nThe PSD for this frequency is then computed by forming the square sum of adjusted observations:\n\\[\n  P(f) = \\sum_i \\hat{l}^2_i.\n\\]\nThe resulting PSD is the average over all arcs. For regularly sampled time series,\nthis method yields the same results as FFT based PSD estimates.</p><p>A regular frequency grid based on the longest arc and the median sampling is computed.\nThe maximum number of epochs per arc is determined by\n\\[\n  N = \\frac{t_{\\text{end}} - t_{\\text{start}}}{\\Delta t_{\\text{median}} } + 1,\n\\]the Nyquist frequency is given by\n\\[\n  f_{\\text{nyq}} = \\frac{1}{2\\Delta t_{\\text{median}}}.\n\\]\nIf it is suspected that <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> contains secular variations,\nthe input should be detrended using <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a>.</p><p>See also <a class=\"groops-program\" href=\"Instrument2CovarianceFunctionVCE.html\">Instrument2CovarianceFunctionVCE</a>,\n<a class=\"groops-program\" href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a>, <a class=\"groops-program\" href=\"PowerSpectralDensity2CovarianceFunction.html\">PowerSpectralDensity2CovarianceFunction</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePSD</div></div></td><td>filename</td><td>estimated PSD: column 0: frequency vector, column 1-(n-1): PSD estimate for each channel</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2RmsPlotGrid.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2RmsPlotGrid</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2RmsPlotGrid</h1><p>\n\nThis program computes an RMS plot grid from one or more <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\ncontaining 3D data (e.g. orbits or station positions), which can then be plotted as gridded data in <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\nThe RMS is computed from the difference between <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> and\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentReference</a>.\nAll instrument files must be synchronized (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>Each separate <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> represents an entry (e.g. a satellite or station)\nin the resulting grid. Therefore, providing, for example, 32 orbit files of GPS satellites\nresults in a grid with columns: mjd, id (0-31), rms.</p><p>The first three data columns of the instrument data are considered for computation of the RMS values.\nThe <strong class=\"groops-config-element\">factor</strong> can be set to, for example, sqrt(3) to get 3D instead of 1D RMS values.</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeIntervals</a> are provided, each <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\nand <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentReference</a> serves as a template with variable <code>loopTime</code>.\nThis allows concatenation of instrument files, for example to create a month-long RMS plot grid from daily GPS\norbit files (see below).</p><p>Helmert parameters between the two frames can be estimated each epoch optionally if\n<strong class=\"groops-config-element\">estimateShift</strong>, <strong class=\"groops-config-element\">estimateScale</strong>, or <strong class=\"groops-config-element\">estimateRotation</strong> are set.\nIt uses a <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrument2RmsPlotGrid.png\" alt=\"instrument2RmsPlotGrid\"><figcaption class=\"center\">Figure: Comparison of estimated GPS orbits with IGS final solution.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileRmsPlotGrid</div></div></td><td>filename</td><td>columns: mjd, id, rms</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileHelmertTimeSeries</div></div></td><td>filename</td><td>columns: mjd, tx, ty, tz, scale, rx, ry, rz</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>one file per satellite/station</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileInstrumentReference</div></div></td><td>filename</td><td>one file per satellite/station, same order as above</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeIntervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>for {loopTime} variable in inputfile</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>e.g. sqrt(3) for 3D RMS</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateShift</div></div></td><td>boolean</td><td>coordinate center every epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateScale</div></div></td><td>boolean</td><td>scale factor of position every epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateRotation</div></div></td><td>boolean</td><td>rotation every epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberMaxIteration</div></div></td><td>uint</td><td>(maximum) number of iterations for robust estimation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2Scaleogram.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2Scaleogram</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2Scaleogram</h1><p>\n\nThis program computes the wavelet transform of a time series up to a <strong class=\"groops-config-element\">maxLevel</strong>.\nThe scalogram is written to a matrix which can be plotted by using a gridded layer in <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\nIndividual detail levels can be written to matrix files by setting <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileLevels</a>.\nThe data column to be decomposed must be set by <strong class=\"groops-config-element\">selectDataField</strong>.</p><p>The wavelet transform is implemented as a filter bank, so care should be taken when the input contains data gaps.\nLow/highpass wavelet filters are applied in forward and backward direction, input is padded symmetric.\nSee <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> for details.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrument2Scaleogram.png\" alt=\"instrument2Scaleogram\"><figcaption class=\"center\">Figure: GRACE range-rate residuals of one month.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileScaleogram</div></div></td><td>filename</td><td>matrix columns: mjd, level, value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileLevels</div></div></td><td>filename</td><td>use loopLevel as variable</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileWavelet</div></div></td><td>filename</td><td>wavelet coefficients</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">selectDataField</div></div></td><td>uint</td><td>data column to transform</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxLevel</div></div></td><td>uint</td><td>maximum level of decomposition (default: full)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2SpectralCoherence.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2SpectralCoherence</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2SpectralCoherence</h1><p>\n\nThis program computes the spectral coherence between two <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a>.</p><p>The (magnitude-squared) coherence is defined as\n\\[\n  C_{xy}(f) = \\frac{|P_{xy}(f)|^2}{P_{xx}(f)P_{yy}(f)}\n\\]and is a measure in the range [0, 1] for the similarity of the signals $x$ and $y$ in frequency domain.\n$P_{xy}$ is the cross-spectral density between $x$ and $y$ and $P_{xx}$, $P_{yy}$ are auto-spectral densities.\nAuto- and cross-spectral densities are computed using Lomb's method (see <a class=\"groops-program\" href=\"Instrument2PowerSpectralDensity.html\">Instrument2PowerSpectralDensity</a> for details).</p><p>The resulting PSD is the average over all arcs. For regularly sampled time series,\nthis method yields the same results as FFT based PSD estimates.</p><p>A regular frequency grid based on the longest arc and the median sampling is computed.\nThe maximum number of epochs per arc is determined by\n\\[\n  N = \\frac{t_{\\text{end}} - t_{\\text{start}}}{\\Delta t_{\\text{median}} } + 1,\n\\]the Nyquist frequency is given by\n\\[\n  f_{\\text{nyq}} = \\frac{1}{2\\Delta t_{\\text{median}}}.\n\\]\nIf it is suspected that <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> contains secular variations,\nthe input should be detrended using <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCoherence</a> contains a matrix with the frequency vector as first column,\nthe coherence for each instrument channel is saved in the following columns.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCoherence</div></div></td><td>filename</td><td>column 1: frequency, column 2-n coherence</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrumentReference</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Instrument2Spectrogram.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument2Spectrogram</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument2Spectrogram</h1><p>\n\nThis program applies the Short Time Fourier Transform (STFT) to selected data columns\nof <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> and computes the spectrogram.\nThe STFT is computed at centered <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> with\nan (possible overlapping) rectangular window with <strong class=\"groops-config-element\">windowLength</strong> seconds.\nData gaps are zero padded within the window.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSpectrogram</a> is a matrix with each row the time (MJD),\nthe frequency $[Hz]$, and the amplitudes $[unit/\\sqrt{Hz}]$ for the selected data columns.\nIt can be plotted with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrument2Spectrogram.png\" alt=\"instrument2Spectrogram\"><figcaption class=\"center\">Figure: GRACE range-rate residuals of one month (window of 6 hours).</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSpectrogram</div></div></td><td>filename</td><td>mjd, freq, ampl0, ampl1, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>center of SFFT window</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">windowLength</div></div></td><td>double</td><td>[seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all)</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentAccelerometer2ThermosphericDensity.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentAccelerometer2ThermosphericDensity</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentAccelerometer2ThermosphericDensity</h1><p>\n\nThis program estimates neutral mass densities along the satellite trajectory based on <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>.\nIn order to determine the neutral mass density the accelerometer input should only reflect the accelerations due to drag\n(e.g. <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">miscAccelerations:atmosphericDrag</a>).\nThus, influences from solar and Earth radiation pressure must be reduced beforehand.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDensity</div></div></td><td>filename</td><td>MISCVALUE (kg/m^3)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">satelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td>add non-gravitational forces in satellite reference frame</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">thermosphere</div></div></td><td><a href=\"thermosphereType.html\">thermosphere</a></td><td>used to compute temperature and wind</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerTemperature</div></div></td><td>boolean</td><td>compute drag and lift, otherwise simple drag coefficient is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerWind</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentAccelerometerApplyEstimatedParameters.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentAccelerometerApplyEstimatedParameters</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentAccelerometerApplyEstimatedParameters</h1><p>\n\nThis program evaluates estimated satellite parameters and writes the result to an accelerometer file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAccelerometer</div></div></td><td>filename</td><td>add non-gravitational forces in satellite reference frame</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileParameter</div></div></td><td>filename</td><td>estimated orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">indexStart</div></div></td><td>int</td><td>position in the solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rightSide</div></div></td><td>int</td><td>if solution contains several right hand sides, select one</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentAccelerometerEstimateBiasScale.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentAccelerometerEstimateBiasScale</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentAccelerometerEstimateBiasScale</h1><p>\n\nThis program calibrates <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> with respect to\nsimulated accelerometer data, see <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>.\nThe parameters <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>\nof <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>\nare estimated and the effect is reduced to calibrate the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>.</p><p>If <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileThruster</a> is given, the corresponding epochs\n(within <strong class=\"groops-config-element\">marginThruster</strong>) are not used for the parameter estimation,\nbut the accelerometer epochs are still calibrated afterwards.\nAn arbitrary instrument file is allowed here.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>,\n<a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>, <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a>,\nand <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">satelliteModel</a> are only needed for some special parametrizations.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometerSim</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileThruster</div></div></td><td>filename</td><td>remove thruster events</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">marginThruster</div></div></td><td>double</td><td>margin size (on both sides) [seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentAccelerometerEstimateParameters.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentAccelerometerEstimateParameters</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentAccelerometerEstimateParameters</h1><p>\n\nThis program estimates calibration parameters for acceleration data given given an optional reference acceleration.\nSpecifically, the program solves the equation\n\\[\n  \\mathbf{a} - \\mathbf{a}_\\text{ref} = \\mathbf{f}(\\mathbf{x}) + \\mathbf{e}\n\\]for the unknown parameters $\\mathbf{x}$, where $\\mathbf{a}$ is given in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> and\n$\\mathbf{a}_\\text{ref}$ is given in  <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometerReference</a>.\nThe parametrization of $\\mathbf{x}$ can be set via <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>.\nOptionally, the empirical covariance functions for the accelerations $\\mathbf{a}$ can be estimated by enabling <strong class=\"groops-config-element\">estimateCovarianceFunctions</strong>.</p><p>The estimated parameters are written to the file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> and can be used by\n<a class=\"groops-program\" href=\"InstrumentAccelerometerApplyEstimatedParameters.html\">InstrumentAccelerometerApplyEstimatedParameters</a> to calibrate accelerometer measurements.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSolution</div></div></td><td>filename</td><td>values for estimated parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterNames</div></div></td><td>filename</td><td>names of the estimated parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateArcSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileArcSigmas</div></div></td><td>filename</td><td>accuracies of each arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateEpochSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileEpochSigmas</div></div></td><td>filename</td><td>estimated epoch-wise sigmas</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateCovarianceFunctions</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunction</div></div></td><td>filename</td><td>covariance functions for x, y, z direction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAccelerometerReference</div></div></td><td>filename</td><td>if not given, reference acceleration is assumed zero</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileOrbit</div></div></td><td>filename</td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCamera</div></div></td><td>filename</td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model (may be needed by parametrizationAcceleration)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaX</div></div></td><td>double</td><td>apriori accuracy in x-axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaY</div></div></td><td>double</td><td>apriori accuracy in y-axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaZ</div></div></td><td>double</td><td>apriori accuracy in z-axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>iteration count for determining the covariance function</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentApplyTimeOffset.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentApplyTimeOffset</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentApplyTimeOffset</h1><p>\n\nThis program applies a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeOffset</a> (MISCVALUE)\nto an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>.\nThe time offsets in seconds are multiplicated with a <strong class=\"groops-config-element\">factor</strong>.\nThe instrument files must be synchronized (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTimeOffset</div></div></td><td>filename</td><td>MISCVALUE with time offset in seconds</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>applied to time offset</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentArcCalculate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentArcCalculate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentArcCalculate</h1><p>\n\nThis program manipulates the data columns every arc of an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> similar to\n<a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, see there for more details.\nIf several <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>s are given the data columns are copied side by side.\nFor this the instrument files must be synchronized (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>). For the data\ncolumns the standard data variables are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\nFor the time column (MJD) a variable <code>epoch</code> (together with <code>epochmean</code>, <code>epochmin</code>, &hellip; )\nis defined additionally.</p><p>The content of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> is controlled by <strong class=\"groops-config-element\">outColumn</strong>.\nThe number of <strong class=\"groops-config-element\">outColumn</strong> must agree with the selected <a class=\"groops-class\" href=\"instrumentTypeType.html\">outType</a>.\nThe algorithm to compute the output is as follows:\nThe expressions in <strong class=\"groops-config-element\">outColumn</strong> are evaluated once for each epoch of the input.\nThe variables <code>data0</code>, <code>data1</code>, &hellip; are replaced by the according values from the input columns before.\nIf no <strong class=\"groops-config-element\">outColumn</strong> are specified all input columns are used instead directly.\nThe <a class=\"groops-class\" href=\"instrumentTypeType.html\">instrument type</a> can be specified with <strong class=\"groops-config-element\">outType</strong> and must be agree with the number of columns.</p><p>An extra <strong class=\"groops-config-element\">statistics</strong> file can be generated with one mid epoch per arc. For the computation of the <strong class=\"groops-config-element\">outColumn</strong> values\nall <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available (e.g. <code>epochmin</code>, <code>data0mean</code>, <code>data1std</code>, &hellip; )\ninclusively the <strong class=\"groops-config-element\">constant</strong>s and estimated <strong class=\"groops-config-element\">parameter</strong>s but without the <code>data0</code>, <code>data1</code>, &hellip; itself.\nThe variables and the numbering of the columns refers to the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a>.</p><p>See also <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data columns are appended to the right</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">constant</div></div></td><td>expression</td><td>define a constant by name=value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameter</div></div></td><td>expression</td><td>define a parameter by name[=value]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">leastSquares</div></div></td><td>expression</td><td>try to minimize the expression by adjustment of the parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">removalCriteria</div></div></td><td>expression</td><td>row is removed if one criterion evaluates true.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outType</div></div></td><td><a href=\"instrumentTypeType.html\">instrumentType</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outColumn</div></div></td><td>expression</td><td>expression of output columns, extra 'epoch' variable</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">statistics</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>instrument file with mid epoch per arc, data columns are user defined</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">outColumn</div></div></td><td>expression</td><td>expression to compute statistics columns, data* are from outColumn</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentArcCrossStatistics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentArcCrossStatistics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentArcCrossStatistics</h1><p>\n\nComputes statistics of selected data columns between two <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a> arc wise.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStatisticsTimeSeries</a> contains for every arc one (mid) epoch\nwith statistics column(s). Possible statistics are\n<ul>\n\n  <li>Correlation\n  \\[\n    \\rho = \\frac{\\sum_i x_i y_i}{\\sqrt{(\\sum_i x_i^2) (\\sum_i y_i^2})},\n  \\]  </li><li>\nError RMS\n  \\[\n    rms = \\sqrt{\\frac{1}{N}\\sum_i (x_i-y_i)^2},\n  \\]  </li><li>\nNash-Sutcliffe coefficient (NSC)\n  \\[\n    nsc = 1- \\frac{\\sum_i (x_i-y_i)^2}{\\sum_i (y_i-\\bar{y})^2}.\n  \\]</li></ul>\n\nWith <strong class=\"groops-config-element\">removeArcMean</strong> the mean of each data column of each arc is reduced before.</p><p>With <strong class=\"groops-config-element\">perColumn</strong> separate statistics for each selected data column are computed,\notherwise an overall value is computed.</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a>, <a class=\"groops-program\" href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStatisticsTimeSeries</div></div></td><td>filename</td><td>statistics column(s) per arc, MISCVALUES</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrumentReference</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">statistics</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">correlation</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">errorRMS</div></div></td><td></td><td>rms of differences</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">nashSutcliffe</div></div></td><td></td><td>with respect to reference field</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeArcMean</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perColumn</div></div></td><td>boolean</td><td>compute statistic per column</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentArcStatistics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentArcStatistics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentArcStatistics</h1><p>\n\nComputes statistics of selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> arc wise.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStatisticsTimeSeries</a> contains for every arc one (mid) epoch\nwith statistics column(s). Possible statistics are root mean square, standard deviation,\nmean, median, min, and max.</p><p>With <strong class=\"groops-config-element\">perColumn</strong> separate statistics for each selected data column are computed,\notherwise an overall value is computed.</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcCrossStatistics.html\">InstrumentArcCrossStatistics</a>, <a class=\"groops-program\" href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStatisticsTimeSeries</div></div></td><td>filename</td><td>columns: mjd, statistics column(s) per instrument file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">statistics</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rootMeanSquare</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">standardDeviation</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">mean</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">median</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">min</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">max</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">epochCount</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perColumn</div></div></td><td>boolean</td><td>compute statistic per column</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ignoreNan</div></div></td><td>boolean</td><td>ignore NaN values in input</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentConcatenate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentConcatenate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentConcatenate</h1><p>\n\nThis program concatenate the arcs from several <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a>\nand write it to a new <a class=\"groops-file\" href=\"fileFormat_instrument.html\">file</a>. Input files must be of the same type.\nThe arcs are merged to one arc even though there is a gap inbetween.\nTo split the data into arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\nThree options are available: <strong class=\"groops-config-element\">sort</strong>, <strong class=\"groops-config-element\">removeDuplicates</strong> and <strong class=\"groops-config-element\">checkForNaNs</strong>.\nIf <strong class=\"groops-config-element\">sort</strong> is enabled, the program reads all files, no matter if they are sorted correctly in time, and\nthen sorts the epochs. If <strong class=\"groops-config-element\">removeDuplicates</strong> is enabled, the program checks the whole data set\nfor epochs that are contained twice. And if <strong class=\"groops-config-element\">checkForNaNs</strong> is enabled the data set is checked for\ninvalid epochs containing NaNs.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sort</div></div></td><td>boolean</td><td>sort epochs with increasing time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeDuplicates</div></div></td><td>choice</td><td>remove duplicate epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">keepFirst</div></div></td><td>sequence</td><td>keep first epoch with the same time stamp, remove all others</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin for identical times [seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">keepLast</div></div></td><td>sequence</td><td>keep last epoch with the same time stamp, remove all others</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin for identical times [seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">checkForNaNs</div></div></td><td>boolean</td><td>remove epochs with NaN values in one of the data fields</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentCovarianceCheck.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentCovarianceCheck</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentCovarianceCheck</h1><p>\n\nThis program checks <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariance3d</a>\n3x3 covariance matrices if they are invertible or not and removes the invalid epochs.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCovariance3d</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCovariance3d</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentDetrend.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentDetrend</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentDetrend</h1><p>\n\nReduces <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> (e.g. const, trend, polynomial)\nper arc from selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\nusing a robust <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeriesArcParameters</a> contains for every arc one (mid) epoch\nwith the estimated parameters. The order is: first all data (<code>data0</code>, <code>data1</code>, &hellip; )\nof first temporal parameter, followed by all data of the second temporal parameter and so on.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>detrended instrument time series</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTimeSeriesArcParameters</div></div></td><td>filename</td><td>time series of estimated parameters per arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>per arc, data is reduced by temporal representation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberMaxIteration</div></div></td><td>uint</td><td>(maximum) number of iterations for robust estimation</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentEarthRotation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentEarthRotation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentEarthRotation</h1><p>\n\nPrecompute Earth rotation matrix from celestial to terrestrial frame\nand save as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">StarCamera file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>rotation from CRF to TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentEstimateEmpiricalCovariance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentEstimateEmpiricalCovariance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentEstimateEmpiricalCovariance</h1><p>\n\nThis program estimates the empirical auto- and cross-covariance of selected data columns per arc\nof <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>.\nThe maximum computed lag is determined by the number of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovarianceMatrix</a> specified\n(for a single output file only the auto-covariance is determined, for two output files auto- and cross-covariance is computed and so on).</p><p>Stationarity is assumed for the input time series, which means the temporal covariance matrix has Toeplitz structure.\n\\[\n\\begin{bmatrix}\n\\Sigma & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\Sigma_{\\Delta_3} & \\Sigma_{\\Delta_4} \\\\\n       & \\Sigma            & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\Sigma_{\\Delta_3} \\\\\n       &                   & \\Sigma            & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} \\\\\n       &                   &                   & \\Sigma            & \\Sigma_{\\Delta_1} \\\\\n       &                   &                   &                   & \\Sigma            \\\\\n\\end{bmatrix}\n\\]\nThe matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\Sigma(t-h, t)$.</p><p>To get a reliable estimate, <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> should be called first.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfileCovarianceMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentEstimateHelmertTransformation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentEstimateHelmertTransformation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentEstimateHelmertTransformation</h1><p>\n\nThis program estimates a 3D Helmert transformation between two networks\n(frame realizations, e.g. GNSS satellite or station network).\nEach separate <strong class=\"groops-config-element\">data</strong> represents a satellite/station/&hellip; (e.g. 32 GPS satellites).\nThe instrument data (x,y,z position) considered can be set with <strong class=\"groops-config-element\">startData</strong>.\nThe Helmert parameters are set up according to <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>\nfor each <a class=\"groops-class\" href=\"timeSeriesType.html\">timeIntervals</a> and are estimated using a\n<a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileHelmertTimeSeries</div></div></td><td>filename</td><td>columns: mjd, Tx,Ty,Tz,s,Rx,Ry,Rz according to temporal parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">data</div></div></td><td>sequence</td><td>e.g. satellite, station</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td>transformed positions as instrument type Vector3d</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileInstrumentDiff</div></div></td><td>filename</td><td>position difference as instrument type Vector3d</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileInstrumentReference</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start index of position (x,y,z) columns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeIntervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>parameters are estimated per interval</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>temporal parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateShift</div></div></td><td>boolean</td><td>coordinate center</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateScale</div></div></td><td>boolean</td><td>scale factor of position</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateRotation</div></div></td><td>boolean</td><td>rotation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>for robust least squares</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberMaxIteration</div></div></td><td>uint</td><td>(maximum) number of iterations for robust estimation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentFilter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentFilter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentFilter</h1><p>\n\nThis program filter selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\nwith <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> arc wise.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">digitalFilter</div></div></td><td><a href=\"digitalFilterType.html\">digitalFilter</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentGnssReceiver2TimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentGnssReceiver2TimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentGnssReceiver2TimeSeries</h1><p>\n\nConvert selected GNSS observations or residuals into a simpler time series format.\nThe <strong class=\"groops-config-element\">outputfileTimeSeries</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES).\nFor each epoch the first data column contains the PRN, the second the satellite system,\nfollowed by a column for each GNSS <a class=\"groops-class\" href=\"gnssType.html\">type</a>.\nAs normally more than one GNSS transmitter is tracked per epoch, the output file\nhas several lines per observed epoch (epochs with the same time, one for each transmitter).</p><p>The second data column of the output contains a number representating the system\n<ul>\n\n<li>71: 'G', GPS\n</li><li>\n82: 'R', GLONASS\n</li><li>\n69: 'E', GALILEO\n</li><li>\n67: 'C', BDS\n</li><li>\n83: 'S', SBAS\n</li><li>\n74: 'J', QZSS\n</li><li>\n73: 'I', IRNSS .\n</li></ul>\n</p><p>A <a class=\"groops-file\" href=\"fileFormat_instrument.html\">GNSS residual file</a> includes additional information\nbesides the residuals, which can also be selected with <a class=\"groops-class\" href=\"gnssType.html\">type</a>\n<ul>\n\n<li><code>A1*</code>, <code>E1*</code>: azimuth and elevation at receiver\n</li><li>\n<code>A2*</code>, <code>E2*</code>: azimuth and elevation at transmitter\n</li><li>\n<code>I**</code>: Estimated slant total electron content (STEC)\n</li></ul>\n</p><p>Furthermore these files may include for each residual <a class=\"groops-class\" href=\"gnssType.html\">type</a>\ninformation about the redundancy and the accuracy relation $\\sigma/\\sigma_0$\nof the estimated $\\sigma$ versus the apriori $\\sigma_0$ from the least squares adjustment.\nThe three values (residuals, redundancy, $\\sigma/\\sigma_0$) are coded with the same type.\nTo get access to all values the corresponding type must be repeated in <a class=\"groops-class\" href=\"gnssType.html\">type</a>.</p><p>Example: Selected GPS phase residuals (<a class=\"groops-class\" href=\"gnssType.html\">type</a>='<code>L1*G</code>' and <a class=\"groops-class\" href=\"gnssType.html\">type</a>='<code>L2*G</code>').\nPlotted with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a> with two <a class=\"groops-class\" href=\"plotGraphLayerType.html\">layer:linesAndPoints</a>\n(<strong class=\"groops-config-element\">valueX</strong>='<code>data0</code>',  <strong class=\"groops-config-element\">valueY</strong>='<code>100*data3+data1</code>' and <strong class=\"groops-config-element\">valueY</strong>='<code>100*data4+data1</code>' respectively).\n<figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentGnssReceiver2TimeSeries.png\" alt=\"instrumentGnssReceiver2TimeSeries\"><figcaption class=\"center\">Figure: GPS residuals in cm, shifted by PRN</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>Instrument (MISCVALUES): prn, system, values for each type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileGnssReceiver</div></div></td><td>filename</td><td>GNSS receiver observations or residuals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentInsertNAN.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentInsertNAN</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentInsertNAN</h1><p>\n\nThis program inserts NAN epochs into <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> files,\neither at specific <a class=\"groops-class\" href=\"timeSeriesType.html\">times</a> or where gaps in the instrument are detected.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">times</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>Insert NAN at specific times.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">atGaps</div></div></td><td>boolean</td><td>Insert NAN where epochs are more than 1.5 times the median sampling apart.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">atArcEnds</div></div></td><td>boolean</td><td>Insert one epoch with data NAN at arc ends</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentMultiplyAdd.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentMultiplyAdd</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentMultiplyAdd</h1><p>\n\nThis program multiply <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> with a factor and add them together.\nAfterwards the mean of each arc and data column can be removed with <strong class=\"groops-config-element\">removeArcMean</strong>.\nThe instrument files must be synchronized (<a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">instrument</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeArcMean</div></div></td><td>boolean</td><td>remove mean value of each arc</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentReduceSampling.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentReduceSampling</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentReduceSampling</h1><p>\n\nThis program reduce the sampling of a instrument file. Only epochs with a time stamp\nwith a division by <strong class=\"groops-config-element\">sampling</strong> without remainder are kept (inside <strong class=\"groops-config-element\">margin</strong>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sampling</div></div></td><td>double</td><td>new sampling in seconds</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin around the new sampling in seconds</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">relative2FirstEpoch</div></div></td><td>boolean</td><td>compute sampling relative to time of first epoch</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentRemoveEpochsByCriteria.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentRemoveEpochsByCriteria</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentRemoveEpochsByCriteria</h1><p>\n\nThis program removes epochs from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\nby evaluating a set of <strong class=\"groops-config-element\">removalCriteria</strong> expressions. For the data\ncolumns the standard data variables are available,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The instrument data can be reduced by data from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentReference</a>\nprior to evaluation of the expressions.</p><p>To reduce the data by its median, use an expression like <code>data1-data1mean</code>.\nTo remove epochs that deviate by more than 3 sigma use <code>abs(data1)>3*data1std</code>\nor <code>abs(data0-data0median)>3*1.4826*data0mad</code>.</p><p>All arcs in the input instrument file are concatenated, meaning expressions\nlike <code>data1mean</code> refer to the complete dataset. The removed epochs can be saved\nin a separate <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrumentRemovedEpochs</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td>all data is stored in one arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrumentRemovedEpochs</div></div></td><td>filename</td><td>all data is stored in one arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td>arcs are concatenated for processing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileInstrumentReference</div></div></td><td>filename</td><td>if given, the reference data is reduced prior to the expressions being evaluated</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">removalCriteria</div></div></td><td>expression</td><td>epochs are removed if one criterion evaluates true. data0 is the first data field.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>remove data around identified epochs (on both sides) [seconds]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentRemoveEpochsByTimes.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentRemoveEpochsByTimes</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentRemoveEpochsByTimes</h1><p>\n\nThis program compares an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> with a\n<a class=\"groops-class\" href=\"timeSeriesType.html\">time series</a>.\nEpochs contained within the time series (including a defined margin)\nare removed from the instrument file. The margin is added on\nboth sides of the epochs. The arcs of the instrument file are\nconcatenated to one arc. The removed epochs can be saved\nin a separate instrument file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td>all epochs are concatenated in one arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrumentRemovedEpochs</div></div></td><td>filename</td><td>all epochs are concatenated in one arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timePoints</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin size (on both sides) [seconds]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentRemoveEpochsThruster.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentRemoveEpochsThruster</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentRemoveEpochsThruster</h1><p>\n\nThis program remove epochs from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\nThe epochs are defined by a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">thruster file</a>\nplus a defined margin before and after the thruster firings.\nThe arcs of the instrument file are concatenated to one arc.\nThe removed epochs can be saved in a separate instrument file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td>all epochs are concatenated in one arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileInstrumentRemovedEpochs</div></div></td><td>filename</td><td>all epochs are concatenated in one arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileThruster</div></div></td><td>filename</td><td>THRUSTER</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">marginBefore</div></div></td><td>double</td><td>margin before start of firing [seconds]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">marginAfter</div></div></td><td>double</td><td>margin after end of firing [seconds]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentResample.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentResample</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentResample</h1><p>\n\nThis program resamples <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> to a given\n<a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> using a resampling\n<a class=\"groops-class\" href=\"interpolatorTimeSeriesType.html\">method</a>.</p><p>This program can also be used to reduce the sampling of an instrument file,\nbut a better way to reduce the sampling of noisy data with regular sampling\nis to use a low pass filter first with <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a> and then thin\nout the data with <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">method</div></div></td><td><a href=\"interpolatorTimeSeriesType.html\">interpolatorTimeSeries</a></td><td>resampling method</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>resampled points in time</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentRotate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentRotate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentRotate</h1><p>\n\nThis program rotates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> into a new reference frame\n(using <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>).\nThe rotation is usually done from satellite frame into inertial frame.</p><p>To apply Earth rotation to orbits use <a class=\"groops-program\" href=\"Orbit2EarthFixedOrbit.html\">Orbit2EarthFixedOrbit</a>\nFor other instrument data use <a class=\"groops-program\" href=\"InstrumentEarthRotation.html\">InstrumentEarthRotation</a> before.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseRotate</div></div></td><td>boolean</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentSatelliteTrackingAntennaCenterCorrection.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentSatelliteTrackingAntennaCenterCorrection</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentSatelliteTrackingAntennaCenterCorrection</h1><p>\n\nThis program computes the correction due to offset of the antenna center relative the center of mass.\nThe offsets $\\M c_A$ and $\\M c_B$ in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileAntennaCenters</a> are given in the satellite\nreference frame. These offsets are rotated into the the inertial frame with $\\M D_A$ and $\\M D_B$ from\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> and projected onto the line of sight (LOS)\n\\[\n  \\rho_{AOC} = \\M e_{AB}\\cdot(\\M D_A\\,\\M c_A - \\M D_B\\,\\M c_B),\n\\]with the unit vector in line of sight direction\n\\[\n  \\M e_{AB} = \\frac{\\M r_B - \\M r_A}{\\left\\lVert{\\M r_B - \\M r_A}\\right\\rVert}.\n\\]The corrections for the range-rates and range-acceleration are computed by differentiating\nan interpolation polynomial of degree <strong class=\"groops-config-element\">interpolationDegree</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSatelliteTracking</div></div></td><td>filename</td><td>corrections for range, range-rate, and range-accelerations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">antennaCenters</div></div></td><td>choice</td><td>KBR antenna phase center</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1X</div></div></td><td>double</td><td>x-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1Y</div></div></td><td>double</td><td>y-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1Z</div></div></td><td>double</td><td>z-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2X</div></div></td><td>double</td><td>x-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2Y</div></div></td><td>double</td><td>y-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2Z</div></div></td><td>double</td><td>z-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">file</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputAntennaCenters</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>differentiation by polynomial approximation of degree n</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentSetType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentSetType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentSetType</h1><p>\n\nConvert <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> into instrument data with new <a class=\"groops-class\" href=\"instrumentTypeType.html\">type</a>.\nThe selected number of data columns must agree with the <a class=\"groops-class\" href=\"instrumentTypeType.html\">type</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">type</div></div></td><td><a href=\"instrumentTypeType.html\">instrumentType</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentStarCamera2AccAngularRate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentStarCamera2AccAngularRate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentStarCamera2AccAngularRate</h1><p>\n\nThis program derivate from a time series of quaternions\na series of angular rates and angular accelerations.\nThe derivatives are computed by a polynomial interpolation\nwith <strong class=\"groops-config-element\">interpolationDegree</strong> of the quaternions.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularRate</div></div></td><td>filename</td><td>[rad/s], VECTOR3D</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularAcc</div></div></td><td>filename</td><td>[rad/s**2], VECTOR3D</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>derivation by polynomial interpolation of degree n</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentStarCamera2RollPitchYaw.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentStarCamera2RollPitchYaw</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentStarCamera2RollPitchYaw</h1><p>\n\nCompute roll, pitch, yaw angles from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> data.\nOptional the angles are computed relative\nto a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCameraReference</a>.</p><p>See also <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>roll, pitch, yaw [rad], VECTOR3D</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCameraReference</div></div></td><td>filename</td><td>nominal orientation</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentStarCamera2RotaryMatrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentStarCamera2RotaryMatrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentStarCamera2RotaryMatrix</h1><p>\n\nWrite <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> rotations\nas <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> rotary matrices\n(for each epoch $xx, xy, xz, yx, yy, yz, zx, zy, zz$).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>xx, xy, xz, yx, yy, yz, zx, zy, zz (MISCVALUES)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentStarCameraAngularAccelerometerFusion.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentStarCameraAngularAccelerometerFusion</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentStarCameraAngularAccelerometerFusion</h1><p>\n\nThis program estimates the satellites orientation from star camera data\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> and angular accelerometer data\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAngularAcc</a>. The combination of both observation types\nis achieved in a least square adjustment. The optimal weighting between the two different\nobservation groups is achieved by means of VCE in combination with a robust estimator.\nThe system of linearized observation equations within the sensor fusion approach can be formulated as:\n\\[\n  \\begin{bmatrix}\n  \\M l_{ACC1B}\\\\\n  \\M l_{SCA1B}\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  \\M A_{ACC1B} & \\M B_{ACC1B}\\\\\n  \\M A_{SCA1B} & \\M 0\n  \\end{bmatrix}\n  \\begin{bmatrix}\n  \\M q\\\\\n  \\M b\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  \\frac{\\partial \\dot{\\boldsymbol{\\omega}}}{\\partial \\M q} & \\frac{\\partial \\dot{\\boldsymbol{\\omega}}}{\\partial \\M b}\\\\\n  \\M I & \\M 0\n  \\end{bmatrix}\n  \\begin{bmatrix}\n  \\M q\\\\\n  \\M b\n  \\end{bmatrix}\n\\]with\n\\[\\begin{split}\n  \\M l_{ACC1B}  &= \\dot{\\boldsymbol{\\omega}}_{ACC1B} - \\dot{\\boldsymbol{\\omega}}_{0}, \\\\\n  \\M l_{SCA1B}  &= \\M q_{SCA1B} - \\M q_{0}, \\\\\n  \\M q_{Fusion} &= \\M q + \\M q_{0}.\n\\end{split}\\]The reference values $\\M q_{0}$ and $\\dot{\\boldsymbol{\\omega}}_{0}$ are derived\nfrom <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCameraReference</a>. In the course of the estimation,\nthe accelerometer data is calibrated, by setting a bias factor $\\M b$ with <strong class=\"groops-config-element\">accBias</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>combined quaternions</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovariance</div></div></td><td>filename</td><td>epoch-wise covariance matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovarianceMatrix</div></div></td><td>filename</td><td>full arc-wise covariance matrix per arc. arc number is appended to filename</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileEpochSigmaStarCamera</div></div></td><td>filename</td><td>from vce and outlier detection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileEpochSigmaAccelerometer</div></div></td><td>filename</td><td>from vce and outlier detection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAngularAcc</div></div></td><td>filename</td><td>angular acceleration observations (bias removed)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>estimated parameter (one column for each arc)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCameraReference</div></div></td><td>filename</td><td>quaternions as taylor point</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td>star camera observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCameraCovariance</div></div></td><td>filename</td><td>star camera observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAngularAcc</div></div></td><td>filename</td><td>angular acceleration observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">correctAccNonQuadratic</div></div></td><td>boolean</td><td>apply correction (non-square proof mass)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">accBias</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>accelerometer bias per interval and axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">accScale</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>accelerometer scale per interval and axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaStarcamera</div></div></td><td>double</td><td>[rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaAccelerometerX</div></div></td><td>double</td><td>[rad/s^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaAccelerometerY</div></div></td><td>double</td><td>[rad/s^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaAccelerometerZ</div></div></td><td>double</td><td>[rad/s^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateSigmaScaPerAxis</div></div></td><td>boolean</td><td>separate variance factor for roll, pitch, yaw, instead of one common factor.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateSigmaAccPerAxis</div></div></td><td>boolean</td><td>separate variance factor for each accelerometer axis, instead of one common factor.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>residuals > huber*sigma0 are downweighted</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>residuals > huber: sigma=(e/huber)^power*sigma0</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>non linear equation solved iteratively</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentStarCameraMultiply.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentStarCameraMultiply</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentStarCameraMultiply</h1><p>\n\nThis program applies several rotations given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>.\nThe resulting rotation is written as <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStarCamera</a>.\nAll instrument files must be synchronized (<a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">instrument</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inverse</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentStatisticsTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentStatisticsTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentStatisticsTimeSeries</h1><p>\n\nThis program computes a time series of statistics for one or more instrument files.\nPossible statistics are root mean square, standard deviation, mean, median, min, and max.\nThe columns of the output time series are defined either as one per <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>\nor, if <strong class=\"groops-config-element\">perColumn</strong> is true, statistics are computed per column for each file.\nProviding e.g. 32 orbit files of GPS satellites results in a time series matrix\nwith columns: mjd, statisticsG01, statisticsG02, ..., statisticsG32.\nIf <strong class=\"groops-config-element\">intervals</strong> are provided, the input data is split into these intervals\nand one statistic is computed per interval. Otherwise, overall statistics are computed.\nThe instrument data considered for computation of the component-wise statistics\ncan be set with <strong class=\"groops-config-element\">startDataFields</strong> and <strong class=\"groops-config-element\">countDataFields</strong>.\nThe <strong class=\"groops-config-element\">factor</strong> can be set to e.g. sqrt(3) to get 3D instead of 1D RMS values.</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a>, <a class=\"groops-program\" href=\"InstrumentArcCrossStatistics.html\">InstrumentArcCrossStatistics</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStatisticsTimeSeries</div></div></td><td>filename</td><td>columns: mjd, statistics column(s) per instrument file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">statistics</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rootMeanSquare</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">standardDeviation</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">mean</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">median</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">sum</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">min</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">max</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">epochCount</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perColumn</div></div></td><td>boolean</td><td>compute statistic per column</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ignoreNan</div></div></td><td>boolean</td><td>ignore NaN values in statistic computation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">intervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>intervals for statistics computation (one statistic per interval)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>e.g. sqrt(3) for 3D RMS</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentSynchronize.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentSynchronize</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentSynchronize</h1><p>\n\nThis program reads several <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a> and synchronize the data.\nEvery epoch with some missing data will be deleted so the remaining epochs\nhave data from every instrument.</p><p>In a second step the epochs are divided into arcs with maximal epochs\n(or <strong class=\"groops-config-element\">maxArcLen</strong>) without having a gap inside an arc.\nA Gap is defined by a time step with at least <strong class=\"groops-config-element\">minGap</strong> seconds\nbetween consecutive epochs or if not set the 1.5 of the median sampling.\nArc with an epoch count less than <strong class=\"groops-config-element\">minArcLen</strong> will be rejected.</p><p>A specific region can be selected with <a class=\"groops-class\" href=\"borderType.html\">border</a>.\nIn this case one of the instrument data must be an orbit.</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeIntervals</a> is given the data are also divided into time bins.\nThe assignment of arcs to the bins can be saved in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">outputfileArcList</a>.\nThis file can be used for the variational equation approach or <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>.</p><p>Instrument files from <strong class=\"groops-config-element\">irregularData</strong> are not synchronized but\ndivided into the same number of arcs within the same time intervals.\nData outside the defined arcs will be deleted.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">data</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>margin for identical times [seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minGap</div></div></td><td>double</td><td>minimal time to define a gap and to begin a new arc, 0: no dividing [seconds], if not set 1.5*median sampling is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minArcLength</div></div></td><td>uint</td><td>minimal number of epochs of an arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxArcLength</div></div></td><td>uint</td><td>maximal number of epochs of an arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">arcType</div></div></td><td>choice</td><td>all arcs or only ascending or descending arcs are selected</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ascending</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">descending</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td>only data in a specific region is selected</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeIntervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>divide data into time bins</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileArcList</div></div></td><td>filename</td><td>arc and time bin mapping</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">irregularData</div></div></td><td>sequence</td><td>instrument files with irregular sampling</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">minArcLength</div></div></td><td>uint</td><td>minimal number of epochs in an arc</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/InstrumentWaveletDecomposition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - InstrumentWaveletDecomposition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>InstrumentWaveletDecomposition</h1><p>\n\nThis program performs a multilevel one-dimensional wavelet analysis on one <strong class=\"groops-config-element\">selectDataField</strong>\ndata column of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> contains the decomposed levels in time domain ${a_J,d_J,...,d_1}$\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>MISCVALUES, decomposed levels in time domain a_J,d_J,...,d_1</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">selectDataField</div></div></td><td>uint</td><td>select a data column for decomposition</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileWavelet</div></div></td><td>filename</td><td>wavelet coefficients</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">level</div></div></td><td>uint</td><td>level of decomposition</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Jason2Starcamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Jason2Starcamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Jason2Starcamera</h1><p>\n\nThis program reads in Jason star camera data given in a special  format.\nFiles available at: <a href=\"cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/\" target=\"_blank\">cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/</a>.\nA description of the format can be found under:\n<a href=\"ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf\" target=\"_blank\">ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">jasonNumber</div></div></td><td>uint</td><td>Jason number (different file format), 1 for Sentinel</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/JplAscii2Ephemerides.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - JplAscii2Ephemerides</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>JplAscii2Ephemerides</h1><p>\n\nRead JPL DExxx (ASCII) ephemerides.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEphemerides</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileHeader</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileData</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/KalmanBuildNormals.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - KalmanBuildNormals</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>KalmanBuildNormals</h1><p>\n\nThis program sets up normal equations based on <a class=\"groops-class\" href=\"observationType.html\">observation</a>\nfor short-term gravity field variations.\nIt computes the normal equations based on the intervals $i \\in \\{1, ..., N\\}$ given in the <a class=\"groops-class\" href=\"fileFormat_arcList.html\">arcList</a>.\nIt sets up the least squares adjustment\n\\[\n    \\begin{bmatrix}\n    \\mathbf{l}_1 \\\\\n    \\mathbf{l}_2 \\\\\n    \\vdots \\\\\n    \\mathbf{l}_N \\\\\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n    \\mathbf{A}_1  &  & & \\\\\n    & \\mathbf{A}_2  & &\\\\\n    &  & \\ddots & \\\\\n    & & & \\mathbf{A}_N \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{x}^{(1)} \\\\\n    \\mathbf{x}^{(2)} \\\\\n    \\vdots \\\\\n    \\mathbf{x}^{(N)} \\\\\n  \\end{bmatrix}\n  +\n  \\begin{bmatrix}\n    \\mathbf{e}_1 \\\\\n    \\mathbf{e}_2 \\\\\n    \\vdots \\\\\n    \\mathbf{e}_N \\\\\n  \\end{bmatrix},\n\\]and subsequently computes the normal equations $\\mathbf{N}_i, \\mathbf{n}_i$ for each interval.\nIf <strong class=\"groops-config-element\">eliminateNonGravityParameters</strong> is true, all non-gravity parameters are eliminated before the normals\nare written to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a>.\nFor each time interval in <strong class=\"groops-config-element\">arcList</strong> a single <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equation file</a> is written.</p><p>This program computes the input normals for <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> and <a class=\"groops-program\" href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td>outputfile for normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td><a href=\"observationType.html\">observation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileArcList</div></div></td><td>filename</td><td>list to correspond points of time to arc numbers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">eliminateNonGravityParameters</div></div></td><td>boolean</td><td>eliminate additional parameters from normals, 0: all parameter are saved</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/KalmanFilter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - KalmanFilter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>KalmanFilter</h1><p>\n\nThe program computes time variable gravity fields using the Kalman filter approach of</p><p>Kurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012).\nImproved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.\n<a href=\"https://doi.org/10.1016/j.jog.2012.02.006\" target=\"_blank\">https://doi.org/10.1016/j.jog.2012.02.006</a>.</p><p>The updated state $\\mathbf{x}_t^+$ is determined by solving the least squares adjustment\n\\[\n\\mathbf{l}_t = \\mathbf{A}_t \\mathbf{x}_t + \\mathbf{e}_t \\hspace{25pt} \\mathbf{e}_t \\sim \\mathcal{N}(0, \\mathbf{R}_t)\\\\\n\\mathbf{B} \\mathbf{x}^+_{t-1} = \\mathbf{I} \\mathbf{x}_t + \\mathbf{v}_t\\hspace{25pt} \\mathbf{v} \\sim \\mathcal{N}(0,\\mathbf{Q} + \\mathbf{B} \\mathbf{P}^+_{t-1}\\mathbf{B}^T).\n\\]In normal equation form this can be written as\n\\[\n\\hat{\\mathbf{x}}_t = \\mathbf{x}^+_t = (\\mathbf{N}_t + \\mathbf{P}^{-^{-1}}_t)^{-1}(\\mathbf{n}_t + \\mathbf{P}^{-^{-1}}_t \\mathbf{x}^-_t),\n\\]where $\\mathbf{x}_t^- = \\mathbf{B} \\mathbf{x}^+_{t-1}$ and $\\mathbf{P}_t^{-} = \\mathbf{Q} + \\mathbf{B} \\mathbf{P}^+_{t-1}\\mathbf{B}^T$\nare the predicted state and its covariance matrix.</p><p>The process dynamic $\\mathbf{B}, \\mathbf{Q}$ is represented as an <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">autoregressive model</a>,\nand passed to the program through <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileAutoregressiveModel</a>.\nThe sequence of normal equations $\\mathbf{N}_t, \\mathbf{n}_t$ are given as list of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquations</a>,\nwhich can be generated using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.\nIn the same way, the <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix files</a> for <strong class=\"groops-config-element\">outputfileUpdatedState</strong> and <strong class=\"groops-config-element\">inputfileUpdatedStateCovariance</strong>\ncan also be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.</p><p>If no <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileInitialState</a> is set, a zero vector with appropriate dimensions is used.\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileInitialStateCovarianceMatrix</a> however must be given.</p><p>See also <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>, <a class=\"groops-program\" href=\"KalmanSmoother.html\">KalmanSmoother</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfileUpdatedState</div></div></td><td>filename</td><td>estimated state x+ (nx1-matrix)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outputfileUpdatedStateCovarianceMatrix</div></div></td><td>filename</td><td>estimated state' s covariance matrix Cov(x+)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileNormalEquations</div></div></td><td>filename</td><td>normal equations input file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileInitialState</div></div></td><td>filename</td><td>initial state x0</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInitialStateCovarianceMatrix</div></div></td><td>filename</td><td>initial state's covariance matrix Cov(x0)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAutoregressiveModel</div></div></td><td>filename</td><td>file name of autoregressive model</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/KalmanSmoother.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - KalmanSmoother</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>KalmanSmoother</h1><p>\n\nApply the Rauch-Tung-Striebel smoother to a gravity field time series computed by <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a>.\nThis is the implementation of the approach presented in</p><p>Kurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012).\nImproved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.\n<a href=\"https://doi.org/10.1016/j.jog.2012.02.006\" target=\"_blank\">https://doi.org/10.1016/j.jog.2012.02.006</a>.</p><p>The result has zero phase and the squared magnitude response of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileAutoregressiveModel</a>\n(see <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">autoregressiveModel</a> for details).\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedState</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedStateCovariance</a>\nare the output of a <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> forward sweep.\nThe matrix files for<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileUpdatedState</a>, <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedState</a>\nand <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedStateCovariance</a> can also be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.</p><p>See also <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>, <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> and <a class=\"groops-program\" href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfileState</div></div></td><td>filename</td><td>estimated parameters (nx1-matrix)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outputfileStateCovarianceMatrix</div></div></td><td>filename</td><td>estimated parameters' covariance matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileUpdatedState</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileUpdatedStateCovarianceMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAutoregressiveModel</div></div></td><td>filename</td><td>file name of autoregressive model</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/KalmanSmootherLeastSquares.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - KalmanSmootherLeastSquares</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>KalmanSmootherLeastSquares</h1><p>\n\nThis program estimates temporal gravity field variations with a constraint least squares adjustment.\nPrior information is introduced by means of a <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>\nwhich represent a stationary random process (see the <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">autoregressive model description</a>) for details.</p><p>The output files for the estimated gravity field (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>), the\ncorresponding standard deviations (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>) and the full covariance matrix\n(<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovariance</a>) can be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.\nSimilarly, the <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquations</a>\ncan also be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.</p><p>See also <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>, <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> and<a class=\"groops-program\" href=\"KalmanSmoother.html\">KalmanSmoother</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">outputfileSolution</div></div></td><td>filename</td><td>file name of solution vector (use time tags)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outputfileSigmax</div></div></td><td>filename</td><td>file name of sigma vector (use time tags)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outputfileCovariance</div></div></td><td>filename</td><td>file name of full covariance matrix (use time tags)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileNormalEquations</div></div></td><td>filename</td><td>input normal equations (loopTime will be expanded)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">autoregressiveModelSequence</div></div></td><td><a href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a></td><td>file containing AR model for spatiotemporal constraint</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Kaula2SigmaPotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Kaula2SigmaPotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Kaula2SigmaPotentialCoefficients</h1><p>\n\nCreate signal standard deviations of potential coefficients according Kaula's rule of thumb\n\\[\n  \\sigma_n = \\frac{f}{n^p},\n\\]with the degree $n$, the <strong class=\"groops-config-element\">factor</strong> $f$, and the <strong class=\"groops-config-element\">power</strong> $p$.</p><p>The standard deviations are written as formal errors of\n <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">power</div></div></td><td>double</td><td>sigma = factor/degree^power</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>sigma = factor/degree^power</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Kernel2Coefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Kernel2Coefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Kernel2Coefficients</h1><p>\n\nThis program computes and returns the coefficients and inverse coefficients of a <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>\nfrom from <strong class=\"groops-config-element\">minDegree</strong> to <strong class=\"groops-config-element\">maxDegree</strong> at a given <strong class=\"groops-config-element\">height</strong>.</p><p>The main purpose is for visualization with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>matrix with columns degree, coefficients and inverse coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td>minimum degree of returned coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegre</div></div></td><td>uint</td><td>compute coefficients up to maxDegree</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>evaluate kernel at R+height [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Kernel2SigmaPotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Kernel2SigmaPotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Kernel2SigmaPotentialCoefficients</h1><p>\n\nCreate variances of spherical harmonics by convolution a kernel with white noise,\ne.g. to display filter coefficients of a Gaussian filter.\nThe coefficients are written as formal errors of <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/KernelEvaluate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - KernelEvaluate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>KernelEvaluate</h1><p>\n\nCompute <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> values for distant angles.\nThe main purpose is for visualization with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>matrix with first column the angle [degree], second the kernel value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minAngle</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxAngle</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampling</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>evaluate at R+height [m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/LocalLevelFrame2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - LocalLevelFrame2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>LocalLevelFrame2StarCamera</h1><p>\n\nCompute rotation (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">StarCamera file</a>) from local level frame (ellipsoidal north, east, down)\nto TRF for positions given in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> (first 3 data columns).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>rotation matrix from local level frame (ellipsoidal north, east, down) to TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td>origin of local level frame</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">constantOriginPerArc</div></div></td><td>boolean</td><td>use constant origin for all epochs of an arc (median position)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/LoopPrograms.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - LoopPrograms</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>LoopPrograms</h1><p>\n\nThis program runs a list of programs in a <a class=\"groops-class\" href=\"loopType.html\">loop</a>.</p><p>If <strong class=\"groops-config-element\">continueAfterError</strong>=<code>yes</code> and an error occurs, the remaining programs in the current iteration\nare skipped and the loop continues with the next iteration. Otherwise an exception is thrown.</p><p>If this program is executed on multiple processing nodes, the iterations can be computed in parallel,\nsee <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelization</a>. The first process serves as load balancer\nand the other processes are assigned to iterations according to <strong class=\"groops-config-element\">processCountPerIteration</strong>.\nFor example, running a loop containing three iterations on 13 processes with <strong class=\"groops-config-element\">processCountPerIteration</strong>=<code>4</code>,\nruns the three iterations in parallel, with each iteration being assigned four processes.\nWith <strong class=\"groops-config-element\">parallelLog</strong>=<code>yes</code> all processes write output to screen and the log file.\nAs the output can be quite confusing in this case, running <a class=\"groops-program\" href=\"GroupPrograms.html\">GroupPrograms</a> with an extra <strong class=\"groops-config-element\">outputfileLog</strong>\nfor each iteration (use the loop variables for the name of the log files) might be helpful.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">loop</div></div></td><td><a href=\"loopType.html\">loop</a></td><td>subprograms are called for every iteration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">continueAfterError</div></div></td><td>boolean</td><td>continue with next iteration after error, otherwise throw exception</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">processCountPerIteration</div></div></td><td>uint</td><td>0: use all processes for each iteration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">parallelLog</div></div></td><td>boolean</td><td>write to screen/log file from all processing nodes in parallelized loops</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">program</div></div></td><td>programType</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/MagneticField2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - MagneticField2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>MagneticField2GriddedData</h1><p>\n\nComputes x, y, z of the magentic field vector.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>x, y, z [Tesla = kg/A/s**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">magnetosphere</div></div></td><td><a href=\"magnetosphereType.html\">magnetosphere</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">localReferenceFrame</div></div></td><td>boolean</td><td>local left handed reference frame (north, east, up)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Matrix2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Matrix2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Matrix2GriddedData</h1><p>\n\nThis program reads a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix file</a> with data in columns\nand convert into <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a>.\nThe input columns are enumerated by <code>data0</code>, <code>data1</code>, &hellip; ,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">points</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ellipsoidal</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">longitude</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">latitude</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">height</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">cartesian</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">x</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">y</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">z</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">area</div></div></td><td>expression</td><td>expression (e.g. deltaL*2*sin(deltaB/2)*cos(data1/RHO))</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">value</div></div></td><td>expression</td><td>expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sortPoints</div></div></td><td>boolean</td><td>sort from north/west to south east</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeArea</div></div></td><td>boolean</td><td>the area can be computed automatically for rectangular grids</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/MatrixCalculate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - MatrixCalculate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>MatrixCalculate</h1><p>\n\nThis program creates a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> from multiple matrices.\nAll <a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrices</a> are summed up. The size of the resulting matrix is exandeded to fit all matrices.\nThe class <a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrixGenerator</a> allows complex matrix operations before.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/MatrixRectangular2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - MatrixRectangular2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>MatrixRectangular2GriddedData</h1><p>\n\nRead gridded data (matrix).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rowMajor</div></div></td><td>boolean</td><td>true: data is ordered row by row, false: columnwise</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">startLongitude</div></div></td><td>angle</td><td>longitude of upper left corner of the grid</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">startLatitude</div></div></td><td>angle</td><td>latitude of upper left corner of the grid</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">deltaLongitude</div></div></td><td>angle</td><td>sampling, negative for east to west data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">deltaLatitude</div></div></td><td>angle</td><td>sampling, negative for south to north data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Merit2FullRate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Merit2FullRate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Merit2FullRate</h1><p>\n\nConverts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html\">MERIT II file</a>\nand writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like\ntemperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a>\nincluding full rate data like range, accuracy, wavelength, azimuth and elevation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalPoints</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMeteorological</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSlrData</div></div></td><td>filename</td><td>SLR MERIT II file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Merit2NormalPoints.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Merit2NormalPoints</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Merit2NormalPoints</h1><p>\n\nConverts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html\">MERIT II file</a>\nand writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like\ntemperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a>\nincluding normal point data like range, accuracy, redundancy, wavelength, window size, azimuth and elevation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalPoints</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMeteorological</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSlrData</div></div></td><td>filename</td><td>SLR MERIT II file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ModelEquilibriumTide.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ModelEquilibriumTide</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ModelEquilibriumTide</h1><p>\n\nComputes the equilibrium ocean tide of the long periodic <strong class=\"groops-config-element\">tideGeneratingPotential</strong>.\nThe spherical harmonics expansion up to <strong class=\"groops-config-element\">maxDegree</strong> with <strong class=\"groops-config-element\">GM</strong> and <strong class=\"groops-config-element\">R</strong>\nis estimated using a least squares adjustment.</p><p>The <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileDensityGrid</a> must be a global regular grid with the\nvertically averaged seawater density over the ocean and zero over land.</p><p>It takes iteratively self attraction and loading into account using the Love numbers\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePotentialLoadLoveNumber</a> and\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDeformationLoadLoveNumber</a>.</p><p>Additionally the effects of the solid Earth tide are considered,\nboth the gravitational (Love numbers <strong class=\"groops-config-element\">k20</strong>, <strong class=\"groops-config-element\">k20plus</strong>)\nand the geometrical (Love numbers <strong class=\"groops-config-element\">h20,0</strong>, <strong class=\"groops-config-element\">h20,2</strong>) effect.</p><p>See also <a class=\"groops-program\" href=\"PotentialCoefficients2DoodsonHarmonics.html\">PotentialCoefficients2DoodsonHarmonics</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/modelEquilibriumTide.png\" alt=\"modelEquilibriumTide\"><figcaption class=\"center\">Figure: Equilibrium tide of SA constituent</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePotentialCoefficients</div></div></td><td>filename</td><td>includes the loading</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDensityGrid</div></div></td><td>filename</td><td>[kg/m^3] density of sea water, zero over land</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">tideGeneratingPotential</div></div></td><td>double</td><td>[m^2/s^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">k20</div></div></td><td>double</td><td>earth tide love number</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">k20plus</div></div></td><td>double</td><td>earth tide love number</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">h20_0</div></div></td><td>double</td><td>earth tide love number</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">h20_2</div></div></td><td>double</td><td>earth tide love number</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePotentialLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDeformationLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NetCdf2GridRectangular.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NetCdf2GridRectangular</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NetCdf2GridRectangular</h1><p>\n\nDEPRECATED since 2023-07-06. Please use <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a> or <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGridRectangular</div></div></td><td>filename</td><td>One grid for each epoch in the NetCDF file is written. Use loopTimeVariable as template.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">loopTimeVariable</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNetCdf</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameLongitude</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameLatitude</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableNameTime</div></div></td><td>string</td><td>name of NetCDF variable (leave blank for static grids)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">variableNameData</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NetCdf2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NetCdf2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NetCdf2GriddedData</h1><p>\n\nThis program converts a COARDS compliant NetCDF file into an\n<a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>.\nIf no specific input <strong class=\"groops-config-element\">variableNameData</strong> are selected all suitable data are used.</p><p>If the NETCDF file contains a time axis (<strong class=\"groops-config-element\">variableNameData</strong>) an specific epoch\ncan be selected with <strong class=\"groops-config-element\">time</strong>. The nearest epoch in file is used.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNetCdf</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameLongitude</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameLatitude</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableNameTime</div></div></td><td>string</td><td>if with time axis: name of NetCDF variable</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">variableNameData</div></div></td><td>string</td><td>data variables, otherwise all suitable data are used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>if with time axis: nearest epoch is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NetCdf2GriddedDataTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NetCdf2GriddedDataTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NetCdf2GriddedDataTimeSeries</h1><p>\n\nThis program converts a COARDS compliant NetCDF file into\n<a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">outputfileGriddedDataTimeSeries</a>.\nIf no specific input <strong class=\"groops-config-element\">variableNameData</strong> are selected all suitable data are used.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a>, <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNetCdf</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameLongitude</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameLatitude</div></div></td><td>string</td><td>name of NetCDF variable</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">variableNameTime</div></div></td><td>string</td><td>name of NetCDF variable)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">variableNameData</div></div></td><td>string</td><td>data variables, otherwise all suitable data are used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NetCdfInfo.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NetCdfInfo</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NetCdfInfo</h1><p>\n\nPrint content information of a NetCDF file like\ndimensions, variables and attributes.</p><p>See also <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a>,\n<a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a>, <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNetCdf</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseAccelerometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseAccelerometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseAccelerometer</h1><p>\n\nThis program adds noise and biases to simulated <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>\ngenerated by <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>.\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">biasAlong</div></div></td><td>double</td><td>[m/s**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">biasCross</div></div></td><td>double</td><td>[m/s**2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">biasRadial</div></div></td><td>double</td><td>[m/s**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseAlong</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m/s**2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseCross</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m/s**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseRadial</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m/s**2]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseGriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseGriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseGriddedData</h1><p>\n\nThis program adds noise to <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data data</a>.\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseInstrument.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseInstrument</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseInstrument</h1><p>\n\nThis program adds noise to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a>.\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>start</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countDataFields</div></div></td><td>uint</td><td>number of data fields (default: all after start)</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseNormalsSolution.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseNormalsSolution</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseNormalsSolution</h1><p>\n\nThe inverse of the normal matrix of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>\nrepresents the covariance matrix of the estimated parameters. This program generates a noise vector with\n\\[\n\\M\\Sigma(\\M e) = \\M N^{-1},\n\\]if generated input noise is standard white noise.</p><p>The noise vector is computed with\n\\[\n\\M e = \\M W^{-T} \\M z,\n\\]where $\\M z$ is the generated <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noise</a> and\n$\\M W$ is the cholesky upper triangle matrix of the normal matrix $\\M N=\\M W^T\\M W$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNoise</div></div></td><td>filename</td><td>generated noise as matrix: parameterCount x sampleCount</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampleCount</div></div></td><td>uint</td><td>number of samples to be generated</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useEigenvalueDecomposition</div></div></td><td>boolean</td><td>use eigenvalue decomposition</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseOrbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseOrbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseOrbit</h1><p>\n\nThis program adds noise to simulated <a class=\"groops-file\" href=\"fileFormat_instrument.html\">satellite</a>'s positions\nand velocities generated by <a class=\"groops-program\" href=\"SimulateOrbit.html\">SimulateOrbit</a> (along, cross, radial).\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise options.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noisePosition</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>along, cross, radial [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseVelocity</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>along, cross, radial [m/s]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseSatelliteTracking.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseSatelliteTracking</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseSatelliteTracking</h1><p>\n\nThis program adds noise to simulated satellite tracking data generated by <a class=\"groops-program\" href=\"SimulateSatelliteTracking.html\">SimulateSatelliteTracking</a>.\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSatelliteTracking</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteTracking</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseRange</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseRangeRate</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m/s]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">noiseRangeAcceleration</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[m/s^2]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseStarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseStarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseStarCamera</h1><p>\n\nThis program adds noise to rotation observations. The noise is computed via a pseudo random sequence.\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise options.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noiseRoll</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noisePitch</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[rad]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noiseYaw</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>[rad]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NoiseTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NoiseTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NoiseTimeSeries</h1><p>\n\nThis program generates <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileNoise</a> with the requested characteristics.\nSee <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise options.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNoise</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovarianceFunction</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">columns</div></div></td><td>uint</td><td>number of noise series (columns)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsAccumulate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsAccumulate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsAccumulate</h1><p>\n\nThis program accumulates normal equations and writes the total combined system to\n<a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalequation</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>s must have all the same size and the same block structure.</p><p>This program is the simplified and fast version of the more general program <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>.\nFor input normals with different parameters, see <a class=\"groops-program\" href=\"NormalsReorderAndAccumulate.html\">NormalsReorderAndAccumulate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsBuild.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsBuild</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsBuild</h1><p>\n\nThis program accumulates <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>s and\nwrites the total combined system to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalequation</a>.\nFor a detailed description of the used algorithm see <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>.\nLarge normal equation systems can be divided into blocks with <strong class=\"groops-config-element\">normalsBlockSize</strong>.</p><p>A simplifed and fast version of this program is <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>.\nFor input normals with different parameters see <a class=\"groops-program\" href=\"NormalsReorderAndAccumulate.html\">NormalsReorderAndAccumulate</a>.\nTo solve the system of normal equations use <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">normalEquation</div></div></td><td><a href=\"normalEquationType.html\">normalEquation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">normalsBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsBuildShortTimeStaticLongTime.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsBuildShortTimeStaticLongTime</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsBuildShortTimeStaticLongTime</h1><p>\n\nThis program sets up normal equations based on <a class=\"groops-class\" href=\"observationType.html\">observation</a>.\nAdditionally short time and long time variations can be parametrized based on the static parameters\nin <a class=\"groops-class\" href=\"observationType.html\">observation</a> in an efficient way. The observation equations\nare divided into time intervals $i \\in \\{1, ..., N\\}$ (e.g. daily) as defined in\n<a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a>.</p><p>With <strong class=\"groops-config-element\">estimateLongTimeVariations</strong> additional temporal variations can be co-estimated\nfor a subset of the parameters selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>.\nThese parameters might be spherical harmonic coefficients with a limited maximum degree.\nThe temporal variations are represented by base functions $\\Phi_k(t_i)$ (e.g. trend and annual oscillation)\ngiven by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.\nThe temporal base functions are evaluated at the mid time $t_i$ of each interval $i$, multiplicated\nwith the design matrix $\\M A_i$ of the selected parameters, and the design matrix is extended\naccordingly.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/normalsBuildShortTimeStaticLongTime.png\" alt=\"normalsBuildShortTimeStaticLongTime\"><figcaption class=\"center\">Figure: Schema of the extended design matrix.</figcaption></figure></p><p>With <strong class=\"groops-config-element\">estimateShortTimeVariations</strong> short time variations of the gravity field can be co-estimated.\nTheir purpose is to mitigate temporal aliasing.\nThe short time parameters selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>\n(e.g. daily constant or linear splines every 6 hour) are constrained by an\n<a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>. If only a static parameter\nset is selected the coressponding part of the design matrix is copied and modeled as a constant value\nper interval in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a> additionally so the corresponding temporal factor can be expressed as\n\\[\n  \\Phi_i(t)  =\n  \\begin{cases}\n    1 &\\text{if} \\hspace{5pt} t \\in [t_i, t_{i+1}) \\\\\n    0 & \\text{otherwise}\n  \\end{cases}.\n\\]\nBefore writing the normal equations to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a>\nshort time gravity and satellite specific parameters can be eliminated with <strong class=\"groops-config-element\">eliminateParameter</strong>.</p><p>Example: For the computation of the mean gravity field ITSG-Grace2018s with additional trend and annual signal\nthe normal equations are computed month by month and accumulated afterwards (see <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>).\nThe observations were divided into daily intervals with <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a>.\nThe static gravity field has been parametrized as spherical harmonics\nup to degree $n=200$ in <a class=\"groops-class\" href=\"parametrizationGravityType.html\">observation:parametrizationGravity</a>.\nThe trend and annual signals defined by\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">estimateLongTimeVariations:parametrizationTemporal</a>\nwere estimated for selected parameters up to degree $n=120$.\nTo mitigate temporal aliasing daily gravity fields up to degree $n=40$ were setup and constrained\nwith an <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a> up to order three.</p><p>A detailed description of the approach is given in:\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). <a href=\"https://doi.org/10.1007/s00190-019-01314-1\" target=\"_blank\">https://doi.org/10.1007/s00190-019-01314-1</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td>outputfile for normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td><a href=\"observationType.html\">observation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateShortTimeVariations</div></div></td><td>sequence</td><td>co-estimate short time gravity field variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">autoregressiveModelSequence</div></div></td><td><a href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a></td><td>AR model sequence for constraining short time gravity variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameters describing the short time gravity field</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateLongTimeVariations</div></div></td><td>sequence</td><td>co-estimate long time gravity field variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>parametrization of time variations (trend, annual, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameters describing the long time gravity field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileArcList</div></div></td><td>filename</td><td>list to correspond points of time to arc numbers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">eliminateParameter</div></div></td><td>boolean</td><td>eliminate short time and state parameter</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsCreate</h1><p>\n\nCreate <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a>\nfrom calculated matrices (<a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrixGenerator</a>).</p><p>The <a class=\"groops-class\" href=\"fileFormat_parameterName.html\">inputfileParameterNames</a> can be created with <a class=\"groops-program\" href=\"ParameterNamesCreate.html\">ParameterNamesCreate</a>.</p><p>The <a class=\"groops-class\" href=\"matrixGeneratorType.html\">normalMatrix</a> must be symmetric.\nThe <a class=\"groops-class\" href=\"matrixGeneratorType.html\">rightHandSide</a> must have the same number of rows\nand can contain multiple columns for multiple solutions.</p><p>The Vector $\\M l^T\\M P\\M l$ is the quadratic sum of observations for each column of the right hand side.\nIt is used to determine the aposteriori accuracy\n\\[\n\\hat{\\sigma}^2 = \\frac{\\hat{\\M e}^T\\M P\\hat{\\M e}}{n-m} = \\frac{\\M l^T\\M P\\M l - \\M n^T\\hat{\\M x}}{n-m}.\n\\]If the vector is not given, it is automatically determined by assuming $\\hat{\\sigma}^2=1$.</p><p>The number of observations $n$ is given by the expression <strong class=\"groops-config-element\">observationCount</strong>.\nThe variable <code>observationCount</code> can be used, if it is set by a normal equation file\n<a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquationObsCount</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileParameterNames</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">normalMatrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">lPl</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td>vector with size of rhs columns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileNormalEquationObsCount</div></div></td><td>filename</td><td>sets the variable observationCount</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observationCount</div></div></td><td>expression</td><td>(variables: rows, columns (rhs), observationCount)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsEliminate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsEliminate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsEliminate</h1><p>\n\nThis program eliminates parameters from a system of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>s.\nTo just remove (cutting out) parameters use <a class=\"groops-program\" href=\"NormalsReorder.html\">NormalsReorder</a>.</p><p>The <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a> allows the selection\nof parameters that will remain, all others will be eliminated. The order of remaining parameters\ncan be modified via the parameter selection. Block size of the output normal matrix can be adjusted with\n<strong class=\"groops-config-element\">outBlockSize</strong>. If it is set to zero, the <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a>\nis written to a single block file.</p><p>For example the normal equations are divided into two groups of\nparameters $\\hat{\\M x}_1$ and $\\hat{\\M x}_2$ according to\n\\[\n\\begin{pmatrix}\n  \\M N_{11} & \\M N_{12} \\\\\n  \\M N_{21} & \\M N_{22}\n\\end{pmatrix}\n\\begin{pmatrix} \\hat{\\M x}_1 \\\\ \\hat{\\M x}_2 \\end{pmatrix}\n=\n\\begin{pmatrix}\n  \\M n_1 \\\\\n  \\M n_2\n\\end{pmatrix}.\n\\]and $\\hat{\\M x}_2$ shall be eliminated, the reduced system of normal equations is given by\n\\[\n\\bar{\\M N}\\hat{\\M x} = \\bar{\\M n}\n\\qquad\\text{with}\\qquad\n\\bar{\\M N}=\\M N_{11}-\\M N_{12}\\M N_{22}^{-1}\\M N_{12}^T\n\\qquad\\text{and}\\qquad\\bar{\\M n} =  \\M n_1 - \\M N_{12}\\M N_{22}^{-1}\\M n_2.\n\\]\nSee also <a class=\"groops-program\" href=\"NormalsReorder.html\">NormalsReorder</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">remainingParameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of output normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsMultiplyAdd.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsMultiplyAdd</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsMultiplyAdd</h1><p>\n\nThis program modifies <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> in a way\nthat $\\bar{\\M x}$ is estimated instead of $\\M x$.\n\\[\n \\bar{\\M x} := \\M x + \\alpha\\, \\M x_0,\n\\]where $\\M x_0$ is <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileParameter</a> and $\\alpha$ is <strong class=\"groops-config-element\">factor</strong>.\nThis can be used to re-add reduced reference fields before a combined estimation\nat normal equation level.\nTherefore the right hand side of the normal equations is modified by\n\\[\n \\bar{\\M n} := \\M n + \\alpha\\,\\M N\\M x_0,\n\\]and the quadratic sum of observations by\n\\[\n \\bar{\\M l^T\\M P\\M l} := \\M l^T\\M P\\M l + \\alpha^2\\,\\M x_0^T\\M N\\M x_0 + 2\\alpha\\,\\M x_0^T\\M n\n\\]\nAs the normal matrix itself is not modified, rewriting of the matrix can be disabled by setting\n<strong class=\"groops-config-element\">writeNormalMatrix</strong> to false.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileParameter</div></div></td><td>filename</td><td>x</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>alpha</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">writeNormalMatrix</div></div></td><td>boolean</td><td>write full coefficient matrix, right hand sides and info files</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsRegularizationBorders.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsRegularizationBorders</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsRegularizationBorders</h1><p>\n\nThis program sets up two regularization matrices for two different regional areas.\nFor a given set of points defined by <a class=\"groops-class\" href=\"gridType.html\">grid</a> it is evaluated, whether each point\n(corresponding to an unknown parameter of a respective parameterization by space localizing basis functions)\nis inside or outside a certain area given by <a class=\"groops-class\" href=\"borderType.html\">border</a>.\nEach regularization matrix is a diagonal matrix, one of them features a one if the\npoint is inside, and a zero if the point lies outside the area. The other matrix features\na zero if the point is inside, and a one if the point lies outside the area\nThis results in two regularization matrices with\n\\[\n\\M R_1+\\M R_2=\\M I.\n\\]The two matrices are provided as vectors of the diagonal\nin the output files <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileOutside</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileInside</a>.\nThe regularization matrices are then used by <a class=\"groops-class\" href=\"normalEquationType.html#regularization\">normalEquation:regularization</a>.\nAs an example, the two different areas could be oceanic regions on the one hand and continental areas on the other hand.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInside</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOutside</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td>nodal point distribution of parameters, e.g harmonics splines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td>regularization areas, e.g land and ocean</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates for border</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates for border, 0: spherical coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsRegularizationSphericalHarmonics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsRegularizationSphericalHarmonics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsRegularizationSphericalHarmonics</h1><p>\n\nDiagonal regularization matrix from gravity field accuracies,\nif not given from signal (cnm,snm), if not given from kaulas rule.\nThe inverse accuracies $1/\\sigma_n^2$ are used as weights in the regularization matrix.\nThe diagonal is saved as Vector.</p><p>The corresponding pseudo observations can be computed with <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDiagonalmatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minRegularizationDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxRegularizationDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme for regul matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">makeIsotropic</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">kaulaPower</div></div></td><td>double</td><td>sigma = kaulaFactor*degree**kaulaPower</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">kaulaFactor</div></div></td><td>double</td><td>sigma = kaulaFactor*degree**kaulaPower</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsReorder.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsReorder</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsReorder</h1><p>\n\nReorder <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> by selecting parameters in a specific order.\nThe <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> also allows one to change dimension of the normal equations,\neither by cutting parameters or by inserting zero rows/columns for additional parameters.\nWithout <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> the order of parameters remains the same.\nAdditionally the block sizes of the files can be adjusted. If <strong class=\"groops-config-element\">outBlockSize</strong> is set to zero,\nthe normal matrix is written to a single block file, which is needed by some programs.</p><p>To eliminate parameters without changing the result of the other parameters use <a class=\"groops-program\" href=\"NormalsEliminate.html\">NormalsEliminate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of output normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsReorderAndAccumulate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsReorderAndAccumulate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsReorderAndAccumulate</h1><p>\n\nThis program accumulates <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>s with respect\nto the parameter names and writes the total combined system to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalequation</a>.</p><p>The combined normal equation is extended to include all parameter names uniquely from all input normals.\nThe input normals are sorted so that parameters with the same name are accumulated.\nThis requires that the names in each normal equation are unique.</p><p>The output can be written as multiple small block files with <strong class=\"groops-config-element\">outBlockSize</strong>,\nor as single block with <strong class=\"groops-config-element\">outBlockSize</strong>=0,\nor blocked with respect to the first part of the parameter names (object), if <strong class=\"groops-config-element\">outBlockSize</strong> left empty.</p><p>See also <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a> and <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block, empty: blocking by objects</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsScale.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsScale</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsScale</h1><p>\n\nScales rows and columns of a system of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>\ngiven by a diagonal matrix <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileFactorVector</a> $\\M S$\n\\[\n  \\bar{\\M N} := \\M S \\M N \\M S \\qquad\\text{and}\\qquad \\bar{\\M n} := \\M S \\M n.\n\\]The estimated solution is now\n\\[\n  \\bar{\\M x} := \\M S^{-1} \\M x.\n\\]This is effectively the same as rescaling columns of the design matrix.\nThis program is useful when combining normal equations from different sources,\nfor example in case the units of certain parameters don't match.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileFactorVector</div></div></td><td>filename</td><td>Vector containing the factors</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsSolverVCE.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsSolverVCE</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsSolverVCE</h1><p>\n\nThis program accumulates <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>\nand solves the total combined system.\nThe relative weigthing between the individual normals is determined iteratively\nby means of variance component estimation (VCE). For a detailed description\nof the used algorithm see <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>.</p><p>Besides the estimated parameter vector (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>) the\nestimated accuracies (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>) and the full covariance matrix\n(<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovariance</a>) can be saved. Also the combined normal system\ncan be written to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileContribution</a> is a matrix with rows for each estimated\nparameter and columns for each <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>\nand indicates the contribution of the individual normals to the estimated parameters.\nEach row sum up to one.</p><p>See also <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>parameter vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovariance</div></div></td><td>filename</td><td>full covariance matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileContribution</div></div></td><td>filename</td><td>contribution of normal system components to the solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileVarianceFactors</div></div></td><td>filename</td><td>estimated variance factors as vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileNormalEquation</div></div></td><td>filename</td><td>the combined normal equation system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">normalEquation</div></div></td><td><a href=\"normalEquationType.html\">normalEquation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileApproxSolution</div></div></td><td>filename</td><td>to accelerate convergence</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rightHandSideNumberVCE</div></div></td><td>uint</td><td>the right hand side number for estimation of variance factors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">normalsBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxIterationCount</div></div></td><td>uint</td><td>maximum number of iterations for variance component estimation</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsSphericalHarmonics2Sinex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsSphericalHarmonics2Sinex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsSphericalHarmonics2Sinex</h1><p>\n\nWrite potential coefficients and <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> to\n<a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a>.</p><p>See also <a class=\"groops-program\" href=\"Sinex2Normals.html\">Sinex2Normals</a> and <a class=\"groops-program\" href=\"GnssNormals2Sinex.html\">GnssNormals2Sinex</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSinex</div></div></td><td>filename</td><td>solutions in SINEX format</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormals</div></div></td><td>filename</td><td>normal equation matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSolution</div></div></td><td>filename</td><td>parameter vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileApriori</div></div></td><td>filename</td><td>apriori parameter vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAprioriMatrix</div></div></td><td>filename</td><td>normal equation matrix of applied constraints</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td>reference time for parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sinexHeader</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">agencyCode</div></div></td><td>string</td><td>identify the agency providing the data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>start time of the data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td>end time of the data </td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">observationCode</div></div></td><td>string</td><td>technique used to generate the SINEX solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">constraintCode</div></div></td><td>string</td><td>0: tight constraint, 1: siginficant constraint, 2: unconstrained</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">solutionContent</div></div></td><td>string</td><td>solution types contained in the SINEX solution (S O E T C A)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>organizitions gathering/alerting the file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">contact</div></div></td><td>string</td><td>Address of the relevant contact. e-mail</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">output</div></div></td><td>string</td><td>Description of the file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">input</div></div></td><td>string</td><td>Brief description of the input used to generate this solution</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">software</div></div></td><td>string</td><td>Software used to generate the file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">hardware</div></div></td><td>string</td><td>Computer hardware on which above software was run</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileComment</div></div></td><td>filename</td><td>comments in the comment block from a file (truncated at 80 characters)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comments in the comment block</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/NormalsTemporalCombination.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalsTemporalCombination</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalsTemporalCombination</h1><p>\n\nThis program reads a times series of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalequation</a>\nwith asscociated <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> and setup a new combined normal equation system.\nFor each parameter a <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> is used.</p><p>It can be used to estimate trend and annual spherical harmonic coefficients from monthly GRACE normal equations.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileNormalEquation</div></div></td><td>filename</td><td>normal equations for each point in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>times of each normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ObservationEquations2Files.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ObservationEquations2Files</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ObservationEquations2Files</h1><p>\n\nThis program computes the linearized and decorrelated equation system for each arc $i$:\n\\[\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i\n\\]using class <a class=\"groops-class\" href=\"observationType.html\">observation</a> and writes $\\M A_i$, $\\M B_i$ and $\\M l_i$ as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> files.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileObservationVector</div></div></td><td>filename</td><td>one file for each arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileDesignMatrix</div></div></td><td>filename</td><td>one file for each arc, without arc related parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileDesignMatrixArc</div></div></td><td>filename</td><td>one file for each arc, arc related parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableArc</div></div></td><td>string</td><td>variable with arc number</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterNames</div></div></td><td>filename</td><td>without arc related parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td><a href=\"observationType.html\">observation</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/OceanTidesDTU2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - OceanTidesDTU2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>OceanTidesDTU2GriddedData</h1><p>\n\nConvert DTU ocean tide grids to griddedData (amplitude, phase).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>data0=amplitude, data1=phase</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2ArgumentOfLatitude.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2ArgumentOfLatitude</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2ArgumentOfLatitude</h1><p>\n\nThis program computes the argument of latitude of an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a>\nand writes it as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUE(S)).\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentOrbit2ArgumentOfLatitude.png\" alt=\"instrumentOrbit2ArgumentOfLatitude\"><figcaption class=\"center\">Figure: Derivation filtered GRACE range-rate residuals.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileArgOfLatitude</div></div></td><td>filename</td><td>instrument file (MISCVALUE(S): argLat, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data are appended</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2BetaPrimeAngle.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2BetaPrimeAngle</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2BetaPrimeAngle</h1><p>\n\nThis program computes the beta prime angle (between the orbital plane and earth-sun direction)\nand writes it as MISCVALUE(S) <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The angle is calculated w.r.t the sun (per default),\nbut can be changed.\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileBetaAngle</div></div></td><td>filename</td><td>instrument file (MISCVALUE(S): beta', ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data are appended</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">planet</div></div></td><td><a href=\"planetType.html\">planet</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2Cpf.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2Cpf</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2Cpf</h1><p>\n\nWrites groops orbits to <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html\">CPF file</a>.</p><p>The coordinate system used in the CPF format is usually presented in ITRF.\nThe required time format for the input orbit file is GPS.\nThe time format of the output CPF file is given in UTC.</p><p>See also <a class=\"groops-program\" href=\"Cpf2Orbit.html\">Cpf2Orbit</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteInfo</div></div></td><td>filename</td><td>Platform File</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">versionNumber</div></div></td><td>uint</td><td>Version number of production day with zero leading fill, e.g. 01</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">targetClass</div></div></td><td>uint</td><td>set 1 for passive retroreflector, set 0 for no retroreflector (includes debris)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2EarthFixedOrbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2EarthFixedOrbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2EarthFixedOrbit</h1><p>\n\nNormally the orbits in GROOPS are given in the celestial reference frame (CRF) with the\norigin in the center of mass (CoM). This program rotates the orbit with\n<a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> from CRF to the TRF.</p><p>To additionally tranform into the center of solid Earth (CE) frame (or center of Figure (CF)),\na correction can be applied by providing degree one coefficients of a\n<a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> (e.g. ocean tides).</p><p>If <strong class=\"groops-config-element\">celestial2terrestrial</strong> is set to no, the inverse transformation is applied.</p><p>See also <a class=\"groops-program\" href=\"InstrumentRotate.html\">InstrumentRotate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>transformation from CRF to TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>degree 1 fluid mantle for CM2CE correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">celestial2terrestrial</div></div></td><td>boolean</td><td>yes: crf->trf, no: trf->crf</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2EclipseFactor.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2EclipseFactor</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2EclipseFactor</h1><p>\n\nThis program generates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUE(S)) containing the eclipse factor for a given set of orbit.\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileEclipseFactor</div></div></td><td>filename</td><td>instrument file (MISCVALUE(S): eclipse, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data are appended</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2GraceL1b.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2GraceL1b</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2GraceL1b</h1><p>\n\nThis program converts an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a> specified in the celestial reference frame (CRF)\nto the GRACE/GRACE-FO SDS format (GNV1B, GNI1B). If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided,\nthe orbit is rotated into the terrestrial reference frame as required for the GNV1B product; otherwise,\na GNI1B product is written.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>.\nThe <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables <code>{epochmin}</code>, <code>{epochmax}</code>,\nand <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2Orbit.html\">GraceL1b2Orbit</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>GNV1B/GNI1B</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileHeader</div></div></td><td>filename</td><td>YAML Header, {epochmin}, {epochmax}, {epochcount} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">satelliteId</div></div></td><td>string</td><td>A, B, C or D</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotation into Earth fixed frame</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2GroopsAscii.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2GroopsAscii</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2GroopsAscii</h1><p>\n\nConvert groops orbits and corresponding covariance information to ASCII format.\nThe format is used to publish TUG orbits. It contains a two line header\nwith a short description of the orbit defined in <strong class=\"groops-config-element\">firstLine</strong>.\nThe orbit is rotated to the Earth fixed frame (TRF) with <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> and given as one line per epoch.\nThe epoch lines contained time [MJD GPS time], position x, y and z [m], and the epoch covariance xx, yy, zz, xy, xz and yz [$m^2$].</p><p>See also <a class=\"groops-program\" href=\"GroopsAscii2Orbit.html\">GroopsAscii2Orbit</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCovariance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">firstLine</div></div></td><td>string</td><td>Text for first line</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2Groundtracks.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2Groundtracks</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2Groundtracks</h1><p>\n\nThis program write <a class=\"groops-file\" href=\"fileFormat_instrument.html\">satellites positions</a> as <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a>\n(<strong class=\"groops-config-element\">outputfileTrackGriddedData</strong>) in a terrestrial reference frame. The points are expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and\n<strong class=\"groops-config-element\">inverseFlattening</strong>. The orbit data are given in the celestial frame so <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>\nis needed to transform the data into the terrestrial frame.\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each point.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>positions as gridded data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>values at grid points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>transformation from CRF to TRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2Kepler.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2Kepler</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2Kepler</h1><p>\n\nThis program computes the osculating Keplerian elements from position and velocity\nof a given <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain positions and velocities (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>).</p><p>The <strong class=\"groops-config-element\">outputfileKepler</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES)\nwith the Keplerian elements at each epoch in the following order\n<ul>\n\n<li>Ascending Node $\\Omega$ [degree]\n</li><li>\nInclination $i$ [degree]\n</li><li>\nArgument of perigee $\\omega$ [degree]\n</li><li>\nmajor axis $a$ [m]\n</li><li>\neccentricity $e$\n</li><li>\nmean anomaly $M$ [degree]\n</li><li>\ntransit time of perigee $\\tau$ [mjd]\n</li></ul>\n\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileKepler</div></div></td><td>filename</td><td>instrument file (MISCVALUES: Omega, i, omega [degree], a [m], e, M [degree], tau [mjd], ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>position and velocity at each epoch define the kepler orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data is appended</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2MagneticField.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2MagneticField</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2MagneticField</h1><p>\n\nThis program computes the magentic field vector($x, y, z$ $[Tesla = kg/A/s^2]$ in CRF))\nalong an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> and writes it as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES).\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as data columns to each epoch.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMagneticField</div></div></td><td>filename</td><td>instrument file (x,y,z in CRF [Tesla = kg/A/s^2]), ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data are appended to output file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">magnetosphere</div></div></td><td><a href=\"magnetosphereType.html\">magnetosphere</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2Sp3Format.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2Sp3Format</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2Sp3Format</h1><p>\n\nWrites orbits to <a href=\"https://files.igs.org/pub/data/format/sp3d.pdf\">SP3 format</a>.</p><p>SP3 orbits are usually given in the terrestrial reference frame (TRF), so providing <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>\nautomatically rotates the orbits from the celestial reference frame (CRF) to the TRF.\nSince SP3 orbits often use the center of Earth as a reference, a correction from center of mass to center\nof Earth can be applied to the orbits by providing <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> (e.g. ocean tides).</p><p>See also <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">satellite</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileClock</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">identifier</div></div></td><td>string</td><td>3 characters (e.g. GNSS PRN: G01)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">orbitAccuracy</div></div></td><td>double</td><td>[m] used for accuracy codes in header (0 = unknown)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotate data into Earth-fixed frame</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comment lines (77 char max)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">firstLine</div></div></td><td>string</td><td>Text for first line e.g:  u+U  IGb14 KIN ITSG</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">writeVelocity</div></div></td><td>boolean</td><td>write velocity in addition to position</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useSp3kFormat</div></div></td><td>boolean</td><td>use the extended sp3k format</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Orbit2ThermosphericState.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Orbit2ThermosphericState</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Orbit2ThermosphericState</h1><p>\n\nThis program computes the thermosperic state (density, temperature, wind (x,y,z in CRF))\nbased on emprical models along an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a>\nand writes it as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES).\nThe wind is given in an celestial reference frame (CRF).\nThe data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileThermosphericState</div></div></td><td>filename</td><td>instrument file (MISCVALUES: density, temperature, wind (x,y,z in CRF), ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td>data are appended to output file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">thermosphere</div></div></td><td><a href=\"thermosphereType.html\">thermosphere</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/OrbitAddVelocityAndAcceleration.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - OrbitAddVelocityAndAcceleration</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>OrbitAddVelocityAndAcceleration</h1><p>\n\nThis program computes velocities and accelerations from a given <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a>\nby differentiating a moving polynomial.\nThe values are saved in one output file which then contains orbit, velocity and acceleration.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">polynomialDegree</div></div></td><td>uint</td><td>Polynomial degree, must be even!</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ParameterNamesCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ParameterNamesCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ParameterNamesCreate</h1><p>\n\nGenerate a <a class=\"groops-class\" href=\"fileFormat_parameterName.html\">outputfileParameterNames</a> by <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>.\nThis file can be used in <a class=\"groops-program\" href=\"NormalsCreate.html\">NormalsCreate</a> or in the class <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelector</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileParameterNames</div></div></td><td>filename</td><td>output parameter names file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterName</div></div></td><td><a href=\"parameterNamesType.html\">parameterNames</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ParameterSelection2IndexVector.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ParameterSelection2IndexVector</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ParameterSelection2IndexVector</h1><p>\n\nGenerate index vector from parameter selection in <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix format</a>.\nThis vector can be used in <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>\nwith <a class=\"groops-class\" href=\"matrixGeneratorType.html#reorder\">matrix:reorder</a>\nto reorder arbitrary vectors and matrices similar to <a class=\"groops-program\" href=\"NormalsReorder.html\">NormalsReorder</a>.</p><p>The <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> allows reordering and dimension changes,\neither by cutting parameters or by inserting additional parameters.\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileIndexVector</a> contains indices of parameters in\n<a class=\"groops-class\" href=\"fileFormat_parameterName.html\">inputfileParameterNames</a> or -1 for newly added parameters.\n<a class=\"groops-class\" href=\"fileFormat_parameterName.html\">outputfileParameterNames</a> contains the selected parameter names.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileIndexVector</div></div></td><td>filename</td><td>indices of source parameters in target normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterNames</div></div></td><td>filename</td><td>output parameter names file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileParameterNames</div></div></td><td>filename</td><td>parameter names file of source normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of target normal equations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ParameterVector2GnssAntennaDefinition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ParameterVector2GnssAntennaDefinition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ParameterVector2GnssAntennaDefinition</h1><p>\n\nUpdates an <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> with estimated parameters which belongs\nto the parametrization <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outfileAntennaDefinition</a> contains all antennas\nfrom <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>.\nThe antenna center variations representend by the <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a> are added\nto the matching antennas.</p><p>The <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> can be modified to the demands before with\n<a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.</p><p>The following steps are used to estimate antenna center variations:\n<ul>\n\n<li><a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a> or <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>\n</li><li>\n<a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> with <strong class=\"groops-config-element\">inputfileAntennaDefinition</strong> as apriori\n      and writing <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> with\n      parametrization of <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>\n</li><li>\n<a class=\"groops-program\" href=\"NormalsEliminate.html\">NormalsEliminate</a>: eliminate all other than antenna parameters\n</li><li>\n<a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>: accumulate normals over a sufficient long period\n</li><li>\n<a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a>: constrain unsolvable parameter linear combinations\n</li><li>\n<a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>: estimate the parameter vector\n</li><li>\n<a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>: update <strong class=\"groops-config-element\">inputfileAntennaDefinition</strong>\n</li></ul>\n</p><p>See also <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>, <a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outfileAntennaDefinition</div></div></td><td>filename</td><td>all apriori antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>apriori antennas</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antennaCenterVariations</div></div></td><td><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSolution</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileParameterNames</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlanetOrbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlanetOrbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlanetOrbit</h1><p>\n\nCreates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit file</a> of sun, moon, or planets.\nThe orbit is given in the celestial reference frame (CRF)\nor alternatively in the terrestrial reference frame (TRF)\nif <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">planet</div></div></td><td><a href=\"planetType.html\">planet</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>transform orbits into TRF</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlatformCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlatformCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlatformCreate</h1><p>\n\nCreate a <a class=\"groops-file\" href=\"fileFormat_platform.html\">Platform file</a> from scratch by defining attributes such as\n<strong class=\"groops-config-element\">markerName</strong>, <strong class=\"groops-config-element\">markerNumber</strong>, <strong class=\"groops-config-element\">comment</strong>, <strong class=\"groops-config-element\">approxPosition</strong>,\n<strong class=\"groops-config-element\">equipment</strong>.</p><p>See also <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> and <a class=\"groops-program\" href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/fileFormatPlatform.png\" alt=\"fileFormatPlatform\"><figcaption class=\"center\">Figure: Platform for stations, LEOs, and GNSS satellites.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilePlatform</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">markerName</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">markerNumber</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approxPositionX</div></div></td><td>double</td><td>[m] in TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approxPositionY</div></div></td><td>double</td><td>[m] in TRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">approxPositionZ</div></div></td><td>double</td><td>[m] in TRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">equipment</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gnssAntenna</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">positionX</div></div></td><td>double</td><td>[m] ARP in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">positionY</div></div></td><td>double</td><td>[m] ARP in north, east, up or vehicle system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">positionZ</div></div></td><td>double</td><td>[m] ARP in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">rotationX</div></div></td><td>angle</td><td>[degree] from local/vehicle to left-handed antenna system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">rotationY</div></div></td><td>angle</td><td>[degree] from local/vehicle to left-handed antenna system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">rotationZ</div></div></td><td>angle</td><td>[degree] from local/vehicle to left-handed antenna system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">flipX</div></div></td><td>boolean</td><td>flip x-axis (after rotation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">flipY</div></div></td><td>boolean</td><td>flip y-axis (after rotation)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">flipZ</div></div></td><td>boolean</td><td>flip z-axis (after rotation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gnssReceiver</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">version</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">laserRetroReflector</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td>e.g. GFZ, ITE, IPIE</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">positionX</div></div></td><td>double</td><td>[m] optial reference point RP in satellite system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">positionY</div></div></td><td>double</td><td>[m] optial reference point RP in satellite system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">positionZ</div></div></td><td>double</td><td>[m] optial reference point RP in satellite system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">rotationX</div></div></td><td>angle</td><td>[degree] from local/vehicle to LRR system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">rotationY</div></div></td><td>angle</td><td>[degree] from local/vehicle to LRR system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">rotationZ</div></div></td><td>angle</td><td>[degree] from local/vehicle to LRR system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">flipX</div></div></td><td>boolean</td><td>flip x-axis (after rotation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">flipY</div></div></td><td>boolean</td><td>flip y-axis (after rotation)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">flipZ</div></div></td><td>boolean</td><td>flip z-axis (after rotation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">range</div></div></td><td>double</td><td>[m] range bias (only without range matrix)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">inputfileRangeMatrix</div></div></td><td>filename</td><td>[m] (azimuth(0..360) x zenith(0..dZenit*rows)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">dZenit</div></div></td><td>angle</td><td>[degree] increment of range matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">geodeticSatellite</div></div></td><td>sequence</td><td>e.g. LAGEOS</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">range</div></div></td><td>double</td><td>[m] standard center-of-mass correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">slrStation</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td>CDP SOD 8-digit No.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td>IERS DOMES</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">positionX</div></div></td><td>double</td><td>[m] eccentricity in north</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">positionY</div></div></td><td>double</td><td>[m] eccentricity in east</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">positionZ</div></div></td><td>double</td><td>[m] eccentricity in up</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">satelliteIdentifier</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">cospar</div></div></td><td>string</td><td>Satellite COSPAR ID</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">norad</div></div></td><td>string</td><td>Satellite Catalog (NORAD) Number</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sic</div></div></td><td>string</td><td>SIC Code</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sp3</div></div></td><td>string</td><td>SP3</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">other</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">positionX</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">positionY</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">positionZ</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">referencePoint</div></div></td><td>sequence</td><td>e.g. center of mass in satellite frame</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">xStart</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">yStart</div></div></td><td>double</td><td>linear motion between start and end</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zStart</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">xEnd</div></div></td><td>double</td><td>[m] in north, east, up or vehicle system</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">yEnd</div></div></td><td>double</td><td>linear motion between start and end</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zEnd</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlotDegreeAmplitudes.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlotDegreeAmplitudes</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlotDegreeAmplitudes</h1><p>\n\nPlot degree amplitudes of potential coefficients computed by <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a>\nor <a class=\"groops-program\" href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a> using the GMT Generic Mapping Tools\n(<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.\nThis is a convenience program with meaningful default values. The same plots can be generated with the more general <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/plotDegreeAmplitudes.png\" alt=\"plotDegreeAmplitudes\"><figcaption class=\"center\">Figure: Comparison of GRACE solutions (2008-06) with GOCO06s.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>*.png, *.jpg, *.eps, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">title</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">layer</div></div></td><td><a href=\"plotGraphLayerType.html\">plotGraphLayer</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacingDegree</div></div></td><td>double</td><td>boundary annotation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacingDegree</div></div></td><td>double</td><td>frame tick spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacingDegree</div></div></td><td>double</td><td>gridline spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">labelDegree</div></div></td><td>string</td><td>description of the x-axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">logarithmicDegree</div></div></td><td>boolean</td><td>use logarithmic scale for the x-axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minY</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxY</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacingY</div></div></td><td>double</td><td>boundary annotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacingY</div></div></td><td>double</td><td>frame tick spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacingY</div></div></td><td>double</td><td>gridline spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">unitY</div></div></td><td>string</td><td>appended to axis values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">labelY</div></div></td><td>string</td><td>description of the y-axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">logarithmicY</div></div></td><td>boolean</td><td>use logarithmic scale for the y-axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>The style of the grid lines.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">legend</div></div></td><td><a href=\"plotLegendType.html\">plotLegend</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">options</div></div></td><td>sequence</td><td>further options...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">titleFontSize</div></div></td><td>uint</td><td>in pt</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">marginTitle</div></div></td><td>double</td><td>between title and figure [cm]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">drawGridOnTop</div></div></td><td>boolean</td><td>grid lines above all other lines/points</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">options</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">transparent</div></div></td><td>boolean</td><td>make background transparent</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">dpi</div></div></td><td>uint</td><td>use this resolution when rasterizing postscript file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">removeFiles</div></div></td><td>boolean</td><td>remove .gmt and script files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlotGraph.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlotGraph</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlotGraph</h1><p>\n\nGenerates a two dimensional xy plot using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The plotting area is defined by the two axes <a class=\"groops-class\" href=\"plotAxisType.html\">axisX/Y</a>. An alternative <a class=\"groops-class\" href=\"plotAxisType.html\">axisY2</a>\non the right hand side can be added. The content of the graph itself is defined\nby one or more <a class=\"groops-class\" href=\"plotGraphLayerType.html\">layer</a>s.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\",\nsee <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p>See also: <a class=\"groops-program\" href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a>, <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>*.png, *.jpg, *.eps, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">title</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">layer</div></div></td><td><a href=\"plotGraphLayerType.html\">plotGraphLayer</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">axisX</div></div></td><td><a href=\"plotAxisType.html\">plotAxis</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">axisY</div></div></td><td><a href=\"plotAxisType.html\">plotAxis</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">axisY2</div></div></td><td><a href=\"plotAxisType.html\">plotAxis</a></td><td>Second y-axis on right hand side</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">colorbar</div></div></td><td><a href=\"plotColorbarType.html\">plotColorbar</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">legend</div></div></td><td><a href=\"plotLegendType.html\">plotLegend</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">options</div></div></td><td>sequence</td><td>further options...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">titleFontSize</div></div></td><td>uint</td><td>in pt</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">marginTitle</div></div></td><td>double</td><td>between title and figure [cm]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">drawGridOnTop</div></div></td><td>boolean</td><td>grid lines above all other lines/points</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">options</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">transparent</div></div></td><td>boolean</td><td>make background transparent</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">dpi</div></div></td><td>uint</td><td>use this resolution when rasterizing postscript file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">removeFiles</div></div></td><td>boolean</td><td>remove .gmt and script files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlotMap.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlotMap</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlotMap</h1><p>\n\nGenerates a map using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The base map is defined by a <a class=\"groops-class\" href=\"plotMapProjectionType.html\">projection</a> of an ellipsoid (<strong class=\"groops-config-element\">R</strong>, <strong class=\"groops-config-element\">inverseFlattening</strong>).\nThe content of the map itself is defined by one or more <a class=\"groops-class\" href=\"plotMapLayerType.html\">layer</a>s.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\",\nsee <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p>See also: <a class=\"groops-program\" href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a>, <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/plotMap.png\" alt=\"plotMap\"><figcaption class=\"center\">Figure: A Robinson projection with griddedData (geoid), coast, polygon (amazon), and points (IGS stations) layer.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>*.png, *.jpg, *.eps, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">title</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">statisticInfos</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">layer</div></div></td><td><a href=\"plotMapLayerType.html\">plotMapLayer</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minLambda</div></div></td><td>angle</td><td>min. longitude (default: compute from input data)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxLambda</div></div></td><td>angle</td><td>max. longitude (default: compute from input data)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minPhi</div></div></td><td>angle</td><td>min. latitude (default: compute from input data)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxPhi</div></div></td><td>angle</td><td>max. latitude (default: compute from input data)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacing</div></div></td><td>angle</td><td>boundary annotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacing</div></div></td><td>angle</td><td>frame tick spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacing</div></div></td><td>angle</td><td>gridline spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">colorbar</div></div></td><td><a href=\"plotColorbarType.html\">plotColorbar</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">projection</div></div></td><td><a href=\"plotMapProjectionType.html\">plotMapProjection</a></td><td>map projection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">options</div></div></td><td>sequence</td><td>further options...</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">titleFontSize</div></div></td><td>uint</td><td>in pt</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">marginTitle</div></div></td><td>double</td><td>between title and figure [cm]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">drawGridOnTop</div></div></td><td>boolean</td><td>grid lines above all other lines/points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">options</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">transparent</div></div></td><td>boolean</td><td>make background transparent</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">dpi</div></div></td><td>uint</td><td>use this resolution when rasterizing postscript file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">removeFiles</div></div></td><td>boolean</td><td>remove .gmt and script files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlotMatrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlotMatrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlotMatrix</h1><p>\n\nPlot the coefficients of a <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>\nusing the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\",\nsee <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p><figure><img class=\"figure\" style=\"width:60%;\" src=\"../figures/plotMatrix.png\" alt=\"plotMatrix\"><figcaption class=\"center\">Figure: Upper left part of the DDK filter matrix.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>*.png, *.jpg, *.eps, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">title</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minColumn</div></div></td><td>uint</td><td>minimum column index to plot</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxColumn</div></div></td><td>uint</td><td>maximum column index to plot</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacingX</div></div></td><td>double</td><td>boundary annotation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacingX</div></div></td><td>double</td><td>frame tick spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacingX</div></div></td><td>double</td><td>gridline spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minRow</div></div></td><td>uint</td><td>minimum row index to plot</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxRow</div></div></td><td>uint</td><td>maximum row index to plot</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacingY</div></div></td><td>double</td><td>boundary annotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacingY</div></div></td><td>double</td><td>frame tick spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacingY</div></div></td><td>double</td><td>gridline spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>The style of the grid lines.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">colorbar</div></div></td><td><a href=\"plotColorbarType.html\">plotColorbar</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">options</div></div></td><td>sequence</td><td>further options...</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">titleFontSize</div></div></td><td>uint</td><td>in pt</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">marginTitle</div></div></td><td>double</td><td>between title and figure [cm]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">drawGridOnTop</div></div></td><td>boolean</td><td>grid lines above all other lines/points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">options</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">transparent</div></div></td><td>boolean</td><td>make background transparent</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">dpi</div></div></td><td>uint</td><td>use this resolution when rasterizing postscript file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">removeFiles</div></div></td><td>boolean</td><td>remove .gmt and script files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PlotSphericalHarmonicsTriangle.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PlotSphericalHarmonicsTriangle</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PlotSphericalHarmonicsTriangle</h1><p>\n\nPlot the potential coefficients of a spherical harmonic expansion\nusing the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>This program plots the formal errors (sigmas).\nIf <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> provides no sigmas\ne.g. with <strong class=\"groops-config-element\">setSigmasToZero</strong> in <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>\nthe coefficients itself are plotted instead.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\",\nsee <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/plotSphericalHarmonicsTriangle.png\" alt=\"plotSphericalHarmonicsTriangle\"><figcaption class=\"center\">Figure: Formal errors of GOCO06s.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>*.png, *.jpg, *.eps, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">title</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>use sigmas, if not given use signal (cnm,snm)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacing</div></div></td><td>double</td><td>boundary annotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacing</div></div></td><td>double</td><td>frame tick spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacing</div></div></td><td>double</td><td>gridline spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>The style of the grid lines.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">colorbar</div></div></td><td><a href=\"plotColorbarType.html\">plotColorbar</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">options</div></div></td><td>sequence</td><td>further options...</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>in cm</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">titleFontSize</div></div></td><td>uint</td><td>in pt</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">marginTitle</div></div></td><td>double</td><td>between title and figure [cm]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">drawGridOnTop</div></div></td><td>boolean</td><td>grid lines above all other lines/points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">options</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">transparent</div></div></td><td>boolean</td><td>make background transparent</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">dpi</div></div></td><td>uint</td><td>use this resolution when rasterizing postscript file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">removeFiles</div></div></td><td>boolean</td><td>remove .gmt and script files</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PotentialCoefficients2BlockMeanTimeSplines.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PotentialCoefficients2BlockMeanTimeSplines</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PotentialCoefficients2BlockMeanTimeSplines</h1><p>\n\nThis program is a simplified version of <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>.\nIt reads a series of potential coefficient files (<a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">inputfilePotentialCoefficients</a>)\nand creates a time splines file with spline degree 0 (temporal block means) or degree 1 (linear splines).\nThe time intervals in which the potential coefficients are valid are defined between adjacent\npoints in time given by <strong class=\"groops-config-element\">splineTimeSeries</strong>. Therefore one more point in time is needed\nthan the number of potential coefficient files for degree 0.</p><p>The coefficients can be filtered with <a class=\"groops-class\" href=\"sphericalHarmonicsFilterType.html\">filter</a>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.\nThe coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>This program is useful e.g. to combine monthly GRACE solutions to one file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSplines</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTimeSplinesCovariance</div></div></td><td>filename</td><td>only the variances are saved</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">filter</div></div></td><td><a href=\"sphericalHarmonicsFilterType.html\">sphericalHarmonicsFilter</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeMean</div></div></td><td>boolean</td><td>remove the temporal mean of the series before estimating the splines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolate</div></div></td><td>boolean</td><td>interpolate missing files</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">splineTimeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>input files must be between points in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">splineDegree</div></div></td><td>uint</td><td>degree of splines</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PotentialCoefficients2DegreeAmplitudes.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PotentialCoefficients2DegreeAmplitudes</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PotentialCoefficients2DegreeAmplitudes</h1><p>\n\nThis program computes degree amplitudes from\n<a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">potentialCoefficients files</a>\nand saves them to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file.</p><p>The coefficients can be filtered with <a class=\"groops-class\" href=\"sphericalHarmonicsFilterType.html\">filter</a> and converted\nto different functionals with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. The gravity field can be evaluated at\ndifferent altitudes by specifying <strong class=\"groops-config-element\">evaluationRadius</strong>. Polar regions can be excluded\nby setting <strong class=\"groops-config-element\">polarGap</strong>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong>\nand the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> contains in the first 3 columns the degree, the degree amplitude, and\nthe formal errors. For each additional <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">inputfilePotentialCoefficients</a> three columns\nare appended: the degree amplitude, the formal errors, and the difference to the first file.</p><p>For example the data columns for 4 <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">inputfilePotentialCoefficients</a> are\n<ul>\n\n<li>degree=<code>data0</code>\n</li><li>\nPotentialCoefficients0: signal=<code>data1</code>, error=<code>data2</code>,\n</li><li>\nPotentialCoefficients1: signal=<code>data3</code>, error=<code>data4</code>,  difference=<code>data5</code>,\n</li><li>\nPotentialCoefficients2: signal=<code>data6</code>, error=<code>data7</code>,  difference=<code>data8</code>,\n</li><li>\nPotentialCoefficients3: signal=<code>data9</code>, error=<code>data10</code>, difference=<code>data11</code>.\n</li></ul>\n</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>matrix with degree, signal amplitude, formal error, differences</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">filter</div></div></td><td><a href=\"sphericalHarmonicsFilterType.html\">sphericalHarmonicsFilter</a></td><td>filter the coefficients</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td>type of variances</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rms</div></div></td><td></td><td>degree amplitudes (square root of degree variances)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">accumulation</div></div></td><td></td><td>cumulate variances over degrees</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">evaluationRadius</div></div></td><td>double</td><td>evaluate the gravity field at this radius (default: evaluate at surface</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">polarGap</div></div></td><td>angle</td><td>exclude polar regions (aperture angle in degrees)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PotentialCoefficients2DoodsonHarmonics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PotentialCoefficients2DoodsonHarmonics</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PotentialCoefficients2DoodsonHarmonics</h1><p>\n\nCreate a <a class=\"groops-file\" href=\"fileFormat_doodsonHarmonic.html\">DoodsonHarmonic file</a> from a list of\ncos/sin <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">potentialCoefficients</a> for given <strong class=\"groops-config-element\">doodson</strong>\n(Doodson number or Darwin´s name, e.g. 255.555 or M2) tidal constituents.\nIf <strong class=\"groops-config-element\">applyXi</strong> the Doodson-Warburg phase correction (see IERS conventions) is applied before.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileDoodsonHarmonics</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileTideGeneratingPotential</div></div></td><td>filename</td><td>to compute Xi phase correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">constituent</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">doodson</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileCosPotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSinPotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">applyXi</div></div></td><td>boolean</td><td>apply Doodson-Warburg phase correction (see IERS conventions)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PotentialCoefficients2Icgem.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PotentialCoefficients2Icgem</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PotentialCoefficients2Icgem</h1><p>\n\nWrite spherical harmonics in ICGEM format.\nGROOPS uses this format as default but this program enables\nthe possibility to include comments and set the modelname.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileTrend</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">oscillation</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileCosPotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileSinPotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">period</div></div></td><td>string</td><td>period of oscillation [year]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td>comment in header</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileComment</div></div></td><td>filename</td><td>file containing comments for header</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">modelname</div></div></td><td>string</td><td>name of the model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">tideSystem</div></div></td><td>choice</td><td>tide system of model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero_tide</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">tide_free</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>reference time</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PowerSpectralDensity2CovarianceFunction.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PowerSpectralDensity2CovarianceFunction</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PowerSpectralDensity2CovarianceFunction</h1><p>\n\nCovariance function from Power Spectral Density (PSD).\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePSD</a> contains in the first column the frequency $[Hz]$, followed by (possibly multiple) PSDs $[unit^2/Hz]$.\nThe output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>, the first column containing time lag $[s]$ and the other columns the covariance functions $[unit^2]$.\nConversion between PSD $p_j$ and covariance function $c_k$ is performed by discrete cosine transformation:\n\\[\nc_k = \\frac{1}{4\\Delta t (n-1)}\\left(p_0 + p_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 p_j \\cos(\\pi jk/(n-1))\\right).\n\\]\nSee also <a class=\"groops-program\" href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCovarianceFunction</div></div></td><td>filename</td><td>first column: time steps [seconds], following columns: covariance functions</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePSD</div></div></td><td>filename</td><td>first column: frequency [Hz], following columns PSD [unit^2/Hz]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingDualSst.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingDualSst</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingDualSst</h1><p>\n\nThis programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration.\nFour different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites.\nThis program works similar to <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a>, see there for details. Here only the settings explained,\nwhich are different.</p><p>Both SST observation types are reduced by the same background models and the same impact\nof accelerometer measurements. The covariance matrix of the reduced observations should not consider\nthe the instrument noise only (<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst1/2</a>) but must\ntake the cross correlations <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceAcc</a> into account.\nThe covariance matrix of the reduced observations is given by\n\\[\n  \\M\\Sigma(\\begin{bmatrix} \\Delta l_{SST1} \\\\ \\Delta l_{SST2} \\end{bmatrix})\n  = \\begin{bmatrix} \\M\\Sigma_{SST1} + \\M\\Sigma_{ACC} & \\M\\Sigma_{ACC} \\\\\n                   \\M\\Sigma_{ACC} & \\M\\Sigma_{SST2} + \\M\\Sigma_{ACC}\n    \\end{bmatrix}.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>estimated parameter vector (static part only)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterName</div></div></td><td>filename</td><td>estimated signal parameters (index is appended)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateArcSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcSst1</div></div></td><td>filename</td><td>accuracies of each arc (SST1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcSst2</div></div></td><td>filename</td><td>accuracies of each arc (SST2)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcAcc</div></div></td><td>filename</td><td>accuracies of each arc (ACC)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcPod1</div></div></td><td>filename</td><td>accuracies of each arc (POD1)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcPod2</div></div></td><td>filename</td><td>accuracies of each arc (POD2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateEpochSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochSst1</div></div></td><td>filename</td><td>accuracies of each epoch (SST1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochSst2</div></div></td><td>filename</td><td>accuracies of each epoch (SST2)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochAcc</div></div></td><td>filename</td><td>accuracies of each epoch (ACC)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochPod1</div></div></td><td>filename</td><td>accuracies of each epoch (POD1)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochPod2</div></div></td><td>filename</td><td>accuracies of each epoch (POD2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateCovarianceFunctions</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionSst1</div></div></td><td>filename</td><td>covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionSst2</div></div></td><td>filename</td><td>covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionAcc</div></div></td><td>filename</td><td>covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionPod1</div></div></td><td>filename</td><td>covariance functions for along, cross, radial direction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionPod2</div></div></td><td>filename</td><td>covariance functions for along, cross, radial direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeResiduals</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSst1Residuals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSst2Residuals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileAccResiduals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfilePod1Residuals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfilePod2Residuals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td>choice</td><td>obervation equations (Sst)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">dualSstVariational</div></div></td><td>sequence</td><td>two SST observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking1</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking2</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">inputfileOrbit1</div></div></td><td>filename</td><td>kinematic positions of satellite A as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">inputfileOrbit2</div></div></td><td>filename</td><td>kinematic positions of satellite B as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileVariational1</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileVariational2</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationSst1</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter for first ranging observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationSst2</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter for second ranging observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst1</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileCovarianceMatrixArc</div></div></td><td>filename</td><td>Must be given per sst arc with correct dimensions.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasCovarianceMatrixArc</div></div></td><td>filename</td><td>Vector with one sigma for each <inputfileCovarianceMatrixArc></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst2</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileCovarianceMatrixArc</div></div></td><td>filename</td><td>Must be given per sst arc with correct dimensions.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasCovarianceMatrixArc</div></div></td><td>filename</td><td>Vector with one sigma for each <inputfileCovarianceMatrixArc></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceAcc</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileCovarianceMatrixArc</div></div></td><td>filename</td><td>Must be given per sst arc with correct dimensions.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasCovarianceMatrixArc</div></div></td><td>filename</td><td>Vector with one sigma for each <inputfileCovarianceMatrixArc></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod1</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch covariances</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod2</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch covariances</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateShortTimeVariations</div></div></td><td>sequence</td><td>co-estimate short time gravity field variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">estimateSigma</div></div></td><td>boolean</td><td>estimate standard deviation via VCE</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">autoregressiveModelSequence</div></div></td><td><a href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a></td><td>AR model sequence for constraining short time gravity variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameters describing the short time gravity field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">downweightPod</div></div></td><td>double</td><td>downweight factor for POD</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileArcList</div></div></td><td>filename</td><td>list to correspond points of time to arc numbers</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>(maximum) number of iterations for the estimation of calibration parameter and error PSD</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableNameIterations</div></div></td><td>string</td><td>All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockSize</div></div></td><td>uint</td><td>block size of static normal equation blocks</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingGradiometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingGradiometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingGradiometer</h1><p>\n\nThis program estimates empirical covariance functions of the gradiometer instrument noise and determine arc wise variances to\ndownweight arcs with outliers. This program works similar to <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>, see there for details.\nHere only the settings explained, which are different.</p><p>...\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovarianceFunction</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSigmasPerArc</div></div></td><td>filename</td><td>accuracies of each arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSggResiduals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td><a href=\"sggRightSideType.html\">sggRightSide</a></td><td>input for the observation vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationBias</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>per arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSgg</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">covarianceLength</div></div></td><td>uint</td><td>counts observation epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>for the estimation of calibration parameter and error PSD</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingPod.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingPod</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingPod</h1><p>\n\nThis program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to\ndownweight arcs with outliers.</p><p>A complete least squares adjustment for gravity field determination is performed by computing the <strong class=\"groops-config-element\">observation</strong>\nequations, see <a class=\"groops-class\" href=\"observationType.html#podIntegral\">observation:podIntegral</a> or\n<a class=\"groops-class\" href=\"observationType.html#podVariational\">observation:podVariational</a> for details. The normal equations\nare accumulated and solved to <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> together with the estimated accuracies\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>. The estimated residuals $\\hat{\\M e}=\\M l-\\M A\\hat{\\M x}$ can be computed with\n<strong class=\"groops-config-element\">computeResiduals</strong>.</p><p>For each component (along, cross, radial) of the kinematic orbit positions a noise covariance function is estimated\n\\[\n  \\text{cov}(\\Delta t_i) = \\sum_{n=0}^{N-1} a_n^2 \\cos\\left(\\frac{\\pi}{T} n\\Delta t_i\\right).\n\\]The covariance matrix is composed of the sum of matrices $F_n$ and unknown variance factors\n\\[\n  \\M\\Sigma = a_1^2\\M F_1 + a_2^2 \\M F_2 + \\cdots + a_N^2\\M F_N,\n\\]with the cosine transformation matrices\n\\[\n  \\M F_n = \\left(\\cos\\left(\\frac{\\pi}{T} n(t_i-t_k)\\right)\\right)_{ik}.\n\\]\nAn additional variance factor can be computed (<strong class=\"groops-config-element\">estimateArcSigmas</strong>) for each arc $k$  according to\n\\[\n  \\hat{\\sigma}_k^2 = \\frac{\\hat{\\M e}_k^T\\M\\Sigma^{-1}\\hat{\\M e}_k}{r_k},\n\\]where $r_k$ is the redundancy. This variance factor should be around one for normally behaving arcs\nas the noise characteristics are already considered by the covariance matrix but bad arcs get a much larger variance.\nBy applying this factor bad arcs or arcs with large outliers are downweighted.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>estimated parameter vector (static part only)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterName</div></div></td><td>filename</td><td>names of estimated parameters (static part only)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateArcSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcPod</div></div></td><td>filename</td><td>accuracies of each arc (POD2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateCovarianceFunctions</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionPod</div></div></td><td>filename</td><td>covariance functions for along, cross, radial direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeResiduals</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfilePodResiduals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td>choice</td><td>obervation equations (POD)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">podIntegral</div></div></td><td>sequence</td><td>precise orbit data (integral approach)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"podRightSideType.html\">podRightSide</a></td><td>input for the reduced observation vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">gradientfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>low order field to estimate the change of the gravity by position adjustement</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">keepSatelliteStates</div></div></td><td>boolean</td><td>set boundary values of each arc global</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">accelerateComputation</div></div></td><td>boolean</td><td>acceleration of computation by transforming the observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">podVariational</div></div></td><td>sequence</td><td>precise orbit data (variational equations)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>kinematic positions as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">accelerateComputation</div></div></td><td>boolean</td><td>acceleration of computation by transforming the observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuracies for each arc (multiplied with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch covariances</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileArcList</div></div></td><td>filename</td><td>list to correspond points of time to arc numbers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">adjustmentThreshold</div></div></td><td>double</td><td>Adjustment factor threshold: Iteration will be stopped once both SST and POD adjustment factors are under this threshold</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>(maximum) number of iterations for the estimation of calibration parameters and error PSD</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingSst.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingSst</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingSst</h1><p>\n\nThis program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration.\nThree different observation groups are considered separately: SST and POD1/POD2 for the two satellites.\nThis program works similar to <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>, see there for details. Here only deviations\nin the settings are explained.</p><p>Precise orbit data (POD) often contains systematic errors in addition to stochastic noise. In this case the\nvariance component estimation fails and assigns too much weight to the POD data. Therefore an additional\n<strong class=\"groops-config-element\">downweightPod</strong> factor can be applied to the standard deviation of POD for the next least squares adjustment\nin the iteration. This factor should also applied as <strong class=\"groops-config-element\">sigma</strong> in <a class=\"groops-class\" href=\"observationType.html\">observation</a>\nfor computation of the final solution e.g. with <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>.</p><p>Short time variations of the gravity field can be co-estimated together with the static/monthly\nmean gravity field. The short time parameters must also be set in <a class=\"groops-class\" href=\"parametrizationGravityType.html\">observation:parametrizationGravity</a> and\ncan then be selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">estimateShortTimeVariations:parameterSelection</a>.\nIf these parameters are not time variable, for example when a range of static parameters is selected,\nthey are set up as constant for each time interval defined in <strong class=\"groops-config-element\">inputfileArcList</strong>. The parameters are constrained by an\n<a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">estimateShortTimeVariations:autoregressiveModelSequence</a>. The weight of\nthe constrain equations in terms of the standard deviation can be estimated by means of\nVariance Component Estimation (VCE) if <strong class=\"groops-config-element\">estimateShortTimeVariations:estimateSigma</strong> is set.\nThe mathematical background of this co-estimation can be found in:</p><p>Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). <a href=\"https://doi.org/10.1007/s00190-019-01314-1\" target=\"_blank\">https://doi.org/10.1007/s00190-019-01314-1</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>estimated parameter vector (static part only)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSigmax</div></div></td><td>filename</td><td>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterName</div></div></td><td>filename</td><td>estimated signal parameters (index is appended)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateArcSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcSst</div></div></td><td>filename</td><td>accuracies of each arc (SST)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcPod1</div></div></td><td>filename</td><td>accuracies of each arc (POD1)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerArcPod2</div></div></td><td>filename</td><td>accuracies of each arc (POD2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateEpochSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochSst</div></div></td><td>filename</td><td>accuracies of each epoch (SST)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochPod1</div></div></td><td>filename</td><td>accuracies of each epoch (POD1)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasPerEpochPod2</div></div></td><td>filename</td><td>accuracies of each epoch (POD2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateCovarianceFunctions</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionSst</div></div></td><td>filename</td><td>covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionPod1</div></div></td><td>filename</td><td>covariance functions for along, cross, radial direction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileCovarianceFunctionPod2</div></div></td><td>filename</td><td>covariance functions for along, cross, radial direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateSstArcCovarianceSigmas</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSigmasCovarianceMatrixArc</div></div></td><td>filename</td><td>one variance factor per matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeResiduals</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileSstResiduals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfilePod1Residuals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfilePod2Residuals</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td>choice</td><td>obervation equations (Sst)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">sstIntegral</div></div></td><td>sequence</td><td>integral approach</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">inputfileSatelliteModel1</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">inputfileSatelliteModel2</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"sstRightSideType.html\">sstRightSide</a></td><td>input for the reduced observation vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">rangeAcceleration</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileStarCamera1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileStarCamera2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">gradientfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>low order field to estimate the change of the gravity by position adjustement</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationSst</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">keepSatelliteStates</div></div></td><td>boolean</td><td>set boundary values of each arc global</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">sstVariational</div></div></td><td>sequence</td><td>variational equations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">inputfileOrbit1</div></div></td><td>filename</td><td>kinematic positions of satellite A as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">inputfileOrbit2</div></div></td><td>filename</td><td>kinematic positions of satellite B as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileVariational1</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileVariational2</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional-unbounded\">parametrizationSst</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileCovarianceMatrixArc</div></div></td><td>filename</td><td>Must be given per sst arc with correct dimensions.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasCovarianceMatrixArc</div></div></td><td>filename</td><td>Vector with one sigma for each <inputfileCovarianceMatrixArc></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod1</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch covariances</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod2</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>apriori factor of covariance function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>apriori different accuaries for each arc (multiplicated with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>apriori different accuaries for each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>approximate covariances in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch covariances</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>[seconds] sampling of the covariance function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateShortTimeVariations</div></div></td><td>sequence</td><td>co-estimate short time gravity field variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">estimateSigma</div></div></td><td>boolean</td><td>estimate standard deviation via VCE</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">autoregressiveModelSequence</div></div></td><td><a href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a></td><td>AR model sequence for constraining short time gravity variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameters describing the short time gravity field</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">downweightPod</div></div></td><td>double</td><td>downweight factor for POD</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileArcList</div></div></td><td>filename</td><td>list to correspond points of time to arc numbers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>(maximum) number of iterations for the estimation of calibration parameter and error PSD</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableNameIterations</div></div></td><td>string</td><td>All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockSize</div></div></td><td>uint</td><td>block size of static normal equation blocks</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingVariationalEquation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingVariationalEquation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingVariationalEquation</h1><p>\n\nThis program integrates an orbit dynamically using the given forces and set up the state transition matrix\nfor each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using\nthe variational equation approach. The variational equations are computed arc-wise as defined by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nThis means for each arc new initial state parameters are set up.</p><p>In a first step the <a class=\"groops-class\" href=\"forcesType.html\">forces</a> acting on the satellite are evaluated at the apriori positions given\nby <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. Non-conservative forces like solar radiation pressure need the orientation of the\nsatellite (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>) and additionally, a satellite macro model (<strong class=\"groops-config-element\">satelliteModel</strong>)\nwith the surface properties. Furthermore <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> observations are also considered.</p><p>In a second step the accelerations are integrated twice to a dynamic orbit using a moving polynomial with the degree\n<strong class=\"groops-config-element\">integrationDegree</strong>. The orbit is corrected to be self-consistent. This means the forces should be evaluated\nat the new integrated positions instead of the apriori ones. This correction is computed in a linear approximation\nusing the gradient of the forces with respect to the positions (<strong class=\"groops-config-element\">gradientfield</strong>). As this term is small generally\nonly the largest force components have to be considered. A low degree spherical harmonic expansion of the static gravity\nfield (about up to degree 5) is sufficient in almost all cases. In this step also the state transition matrix (the partial\nderivatives of the current state, position and velocity) with respect to the initial state is computed.\nThe integrated orbit together with the state transitions are stored in <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">outputfileVariational</a>,\nthe integrated orbit only in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>.</p><p>To improve the numerical stability a reference ellipse can be reduced beforehand using Enke's method (<strong class=\"groops-config-element\">useEnke</strong>).\nMathematically the result is the same, but as the large central term is removed before and restored\nafterwards more digits are available for the computation.</p><p>The integrated orbit should be fitted to observations afterwards by the programs\n<a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> and/or <a class=\"groops-program\" href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a>.\nThey apply a least squares adjustment by estimating some satellite parameters (e.g. an accelerometer bias).\nIf the fitted orbit is too far away from the original <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> the linearization may not be\naccurate enough. In this case <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a> should be run again with the fitted orbit\nas <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> and introducing the <strong class=\"groops-config-element\">estimatedParameters</strong> as additional forces.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileVariational</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>integrated orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>approximate position, used to evaluate the force</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td>rotation from body frame to CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAccelerometer</div></div></td><td>filename</td><td>non-gravitational forces in satellite reference frame</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">forces</div></div></td><td><a href=\"forcesType.html\">forces</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimatedParameters</div></div></td><td>sequence</td><td>satellite parameters e.g. from orbit fit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileParameter</div></div></td><td>filename</td><td>estimated orbit force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gradientfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>low order field to estimate the change of the gravity by position adjustement</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useEnke</div></div></td><td>sequence</td><td>integrate differential forces to an elliptical reference trajectory</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>geocentric gravitational constant used for elliptical reference orbit</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingVariationalEquationOrbitFit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingVariationalEquationOrbitFit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingVariationalEquationOrbitFit</h1><p>\n\nThis program fits an <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> to an observed <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> by estimating parameters\nin a least squares adjustment. Additional to the initial satellite state for each arc, these parameters can be\n<a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>, satellite <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>\nand stochastic pulses (velocity jumps) at given times, <a class=\"groops-class\" href=\"timeSeriesType.html\">stochasticPulse</a>. The estimated parameters can be stored with\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> and an extra file with the parameter names is created. The fitted orbit is written\nas new reference in <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">outputfileVariational</a> and additionally in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>.</p><p>The observed orbit positions (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>) together with the epoch-wise covariance matrix\n(<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>) must be split in the same arcs as the variational equations but not\nnecessarily uniformly distributed (use irregularData in <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>). An iterative downweighting of\noutliers is performed by M-Huber method.</p><p>The observation equations (parameter sensitivity matrix) are computed by integration of the variational equations\n(<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) using a polynomial with <strong class=\"groops-config-element\">integrationDegree</strong> and interpolated to the\nobservation epochs using a polynomial with <strong class=\"groops-config-element\">interpolationDegree</strong>.</p><p>All parameters used here must be reestimated in the full least squares adjustment\nfor the gravity field determination to get a solution which is not biased towards the reference field.\nThe solutions of additional estimations are relative (deltas) as the parameters are already used as Taylor point\nin the reference orbit.</p><p>See also <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileVariational</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>integrated orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>estimated calibration and state parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>kinematic positions of satellite as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch wise covariances</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td>may be needed by parametrizationAcceleration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stochasticPulse</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>for the estimation of calibration parameter and error PSD</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PreprocessingVariationalEquationSstFit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PreprocessingVariationalEquationSstFit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PreprocessingVariationalEquationSstFit</h1><p>\n\nThis program fits two <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1/2</a> to satellite-to-satellite-tracking (SST) and orbit\nobservations in a GRACE like configuration. It works similar to <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>,\nsee there for details.</p><p>As the relative weighting of the observation types is important complex description of the covariances can be set with\n<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>, <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod1</a>, <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod2</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileVariational1</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileVariational2</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit1</div></div></td><td>filename</td><td>integrated orbit</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit2</div></div></td><td>filename</td><td>integrated orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution1</div></div></td><td>filename</td><td>estimated calibration and state parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution2</div></div></td><td>filename</td><td>estimated calibration and state parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit1</div></div></td><td>filename</td><td>kinematic positions of satellite A as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit2</div></div></td><td>filename</td><td>kinematic positions of satellite B as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational1</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational2</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationSst</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst</div></div></td><td><a href=\"covarianceSstType.html\">covarianceSst</a></td><td>covariance matrix of satellite to satellite tracking observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod1</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod2</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 2)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">iterationCount</div></div></td><td>uint</td><td>for the estimation of calibration parameter and error PSD</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/PsmslOceanBottomPressure2TimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PsmslOceanBottomPressure2TimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PsmslOceanBottomPressure2TimeSeries</h1><p>\n\nThis programs reads ocean bottom pressure time series from the Permanent Service for Mean Sea Level (PSMSL).</p><p>In addition to the OBP measurements, the recorder position can be written to a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">grid file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePosition</div></div></td><td>filename</td><td>recorder position as gridded data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">isDaily</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ignoreBadData</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/RadialBasisSplines2KernelCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - RadialBasisSplines2KernelCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>RadialBasisSplines2KernelCoefficients</h1><p>\n\nThis program calculates the coefficients $k_n$ of a <a class=\"groops-class\" href=\"kernelType.html#coefficients\">kernel:coefficients</a> according to\n\\[\n  k_n = \\frac{GM}{4\\pi R}\\frac{\\sigma_n}{\\sqrt{2n+1}}.\n\\]from a given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>,\nwith <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">GM</strong> describing the reference radius and the geocentric constant, respectively.\nThe $\\sigma_n$\nstand for the gravity field accuracies (from degree <strong class=\"groops-config-element\">minDegree</strong> to <strong class=\"groops-config-element\">maxDegree</strong>), if they are given.\nIf no accuracies are provided, the $\\sigma_n$\nrepresent the square root of the degree variances of the gravity field.\nIf <strong class=\"groops-config-element\">maxDegree</strong> exceeds the maximum degree given by <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>,\nthe higher degrees are complemented by Kaula's rule\nThe output of the coefficients is given in the file  <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCoefficients</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">kaulaPower</div></div></td><td>double</td><td>sigma = kaulaFactor/degree^kaulaPower</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">kaulaFactor</div></div></td><td>double</td><td>sigma = kaulaFactor/degree^kaulaPower</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/RinexObservation2GnssReceiver.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - RinexObservation2GnssReceiver</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>RinexObservation2GnssReceiver</h1><p>\n\nConverts <a href=\"https://files.igs.org/pub/data/format/rinex_4.00.pdf\">RINEX</a> (version 2, 3, and 4) and\n<a href=\"https://terras.gsi.go.jp/ja/crx2rnx.html\">Compact RINEX</a> observation files to\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileGnssReceiver</a>.</p><p>In case of <a href=\"https://files.igs.org/pub/data/format/rinex211.txt\">RINEX v2.x</a> observation files\ncontaining GLONASS satellites, a mapping from PRN to frequency number must be provided via\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrixPrn2FrequencyNumber</a>, see <a class=\"groops-program\" href=\"SinexMetadata2GlonassFrequencyNumber.html\">SinexMetadata2GlonassFrequencyNumber</a>.\nRINEX v3+ observation files already contain this information.</p><p><a class=\"groops-class\" href=\"gnssType.html\">useType</a> and <a class=\"groops-class\" href=\"gnssType.html\">ignoreType</a> can be used to filter\nthe observation types that will be exported.</p><p>If <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> is set, RINEX antenna and receiver info\nwill be cross-checked with the provided file and warnings are raised in case of differences.</p><p>A list of semi-codeless GPS receivers (observing C2D instead of C2W) can be provided via\n<a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileSemiCodelessReceivers</a> with one receiver name per line.\nObservation types will be automatically corrected for these receivers.</p><p>Some LEO satellites use special RINEX observation types, either from the unofficial RINEX v2.20\nor custom ones. These can be provided via <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileSpecialObservationTypes</a>.\nThe file must  must contain a table with two columns, the first being the special type,\nand the second being the equivalent RINEX v3 type.</p><p>\n\n\n\n\n\n\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGnssReceiver</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileRinexObservation</div></div></td><td>filename</td><td>RINEX or Compact RINEX observation files</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileMatrixPrn2FrequencyNumber</div></div></td><td>filename</td><td>(required for RINEX v2 files containing GLONASS observations), matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStationInfo</div></div></td><td>filename</td><td>used to determine semi-codeless receivers and to cross-check antenna and receiver info</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSemiCodelessReceivers</div></div></td><td>filename</td><td>list with one receiver name per line</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSpecialObservationTypes</div></div></td><td>filename</td><td>table mapping special observation types to RINEX 3 types, e.g.: LA L1C</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">useType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>only use observations that match any of these patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">ignoreType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>ignore observations that match any of these patterns</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/RunCommand.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - RunCommand</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>RunCommand</h1><p>\n\nExecute system <strong class=\"groops-config-element\">command</strong>s. If <strong class=\"groops-config-element\">executeParallel</strong> is set and\nmultiple <strong class=\"groops-config-element\">command</strong>s are given they are executed in parallel at\ndistributed nodes, otherwise they are executed consecutively at master node only.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">command</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">silently</div></div></td><td>boolean</td><td>without showing the output.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">continueAfterError</div></div></td><td>boolean</td><td>continue with next command after error, otherwise throw exception</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">executeParallel</div></div></td><td>boolean</td><td>execute several commands in parallel</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sacc2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sacc2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sacc2Orbit</h1><p>\n\nThis program reads in SACC orbit data.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SatelliteModelCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SatelliteModelCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SatelliteModelCreate</h1><p>\n\nThis program creates a satellite macro model for the estimation of non-gravitational accelerations acting on a satellite.\nMandatory input values are the <strong class=\"groops-config-element\">satelliteName</strong>, <strong class=\"groops-config-element\">mass</strong>, <strong class=\"groops-config-element\">coefficientDrag</strong> and information\nabout the satellite <strong class=\"groops-config-element\">surfaces</strong>. For low Earth orbiting satellites, like GRACE for instance, a good guess\nfor the drag coefficient could be 2.3. Apart from that, it is latter on possible to estimate a more precise variable drag coefficient\n(e.g. <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">miscAccelerations:atmosphericDrag</a>), which will override this initial guess.\nConcerning the satellite surfaces an external file must be imported which must contain information about each single\n satellite plate in terms of plate <strong class=\"groops-config-element\">area</strong>, the associated plate normal and re-radiation properties\n(reflexion, diffusion and absorption) properties in the visible and IR part. Examplarily, a description of\nthe macro model for GRACE can be found under:\n<a href=\"https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf\" target=\"_blank\">https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf</a>\nAdditionally, it is possible to add further information like antennaThrust, solar panel, temporal mass changes and\nmassInstrument using the modules option.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSatelliteModel</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">satellite</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">satelliteName</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">mass</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">coefficientDrag</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">surfaces</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td>each line must contain one surface element</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">type</div></div></td><td>expression</td><td>0: plate, 1: sphere, 2: cylinder</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">area</div></div></td><td>expression</td><td>[m^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">normalX</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">normalY</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">normalZ</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">reflexionVisible</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">diffusionVisible</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">absorptionVisible</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">reflexionInfrared</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">diffusionInfrared</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">absorptionInfrared</div></div></td><td>expression</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">specificHeatCapacity</div></div></td><td>expression</td><td>0: no thermal radiation, -1: direct reemission [Ws/K/m^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">module</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">antennaThrust</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">thrustX</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">thrustY</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">thrustZ</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">solarPanel</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">rotationAxisX</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">rotationAxisY</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">rotationAxisZ</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">normalX</div></div></td><td>double</td><td>Direction to sun</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">normalY</div></div></td><td>double</td><td>Direction to sun</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config optional\">normalZ</div></div></td><td>double</td><td>Direction to sun</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">indexSurface</div></div></td><td>uint</td><td>index of solar panel surfaces</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">massChange</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">time</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">mass</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">massInstrument</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SatelliteTracking2GraceL1b.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SatelliteTracking2GraceL1b</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SatelliteTracking2GraceL1b</h1><p>\n\nThis program converts low-low satellite tracking data (KBR or LRI) from\nthe GROOPS format <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITETRACKING)</a>\nto the GRACE SDS format (KBR1B or LRI1B).\nIt reads the satellite tracking data and optionally corrections\n(antenna offsets and light time corrections) and flags into one <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>.\nThe <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables <code>{epochmin}</code>, <code>{epochmax}</code>,\nand <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2SatelliteTracking.html\">GraceL1b2SatelliteTracking</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>KBR1B or LRI1B</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileHeader</div></div></td><td>filename</td><td>YAML Header, {epochmin}, {epochmax}, {epochcount} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteTracking</div></div></td><td>filename</td><td>SATELLITETRACKING</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileIonoCorr</div></div></td><td>filename</td><td>MISCVALUE</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileLighttime</div></div></td><td>filename</td><td>SATELLITETRACKING</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAntCentr</div></div></td><td>filename</td><td>SATELLITETRACKING</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSNR</div></div></td><td>filename</td><td>MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sentinel2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sentinel2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sentinel2StarCamera</h1><p>\n\nThis program reads in Sentinel-1/2/3 star camera data given in the special format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SentinelXml2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SentinelXml2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SentinelXml2Orbit</h1><p>\n\nRead Sentinel orbits from XML format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateAccelerometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateAccelerometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateAccelerometer</h1><p>\n\nThis program simulate <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>. The orientation of the accelerometer\nis given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> otherwise the celestial reference frame (CRF) is used.\nFor computation of non-conservative forces a <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">satelliteModel</a> is needed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">forces</div></div></td><td><a href=\"forcesType.html\">forces</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateAccelerometerCoMOffset.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateAccelerometerCoMOffset</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateAccelerometerCoMOffset</h1><p>\n\nThis program generates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer file</a> containing perturbing accelerations\ndue to a given center of mass (CoM) offset. This includes centrifugal effects,\nEuler forces and the effect of gravity gradients.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileAccelerometer</div></div></td><td>filename</td><td>effect of offset</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">applyAngularRate</div></div></td><td>boolean</td><td>compute effect of centrifugal forces</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">applyAngularAccelerations</div></div></td><td>boolean</td><td>compute effect of Euler forces</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gradientfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>low order field to estimate the change of the gravity by position adjustement</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>derivation of quaternions by polynomial interpolation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">CoMOffsetX</div></div></td><td>double</td><td>offset [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">CoMOffsetY</div></div></td><td>double</td><td>offset [m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">CoMOffsetZ</div></div></td><td>double</td><td>offset [m]</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateGradiometer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateGradiometer</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateGradiometer</h1><p>\n\nThis program simulates error free <a class=\"groops-file\" href=\"fileFormat_instrument.html\">gradiometer data</a> along a satellite's orbit.\nThe orientation of the full tensor gradiometer is given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>\notherwise the celestial reference frame (CRF) is used.\nThe gravity gradients are given by <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and\n<a class=\"groops-class\" href=\"tidesType.html\">tides</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGradiometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">tides</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateKeplerOrbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateKeplerOrbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateKeplerOrbit</h1><p>\n\nThis program simulates a Keplerian <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> at a given <strong class=\"groops-config-element\">timeSeries</strong>\nstarting from the given <strong class=\"groops-config-element\">integrationConstants</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">integrationConstants</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">kepler</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">majorAxis</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">eccentricity</div></div></td><td>double</td><td>[-]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inclination</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">ascendingNode</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">argumentOfPerigee</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">meanAnomaly</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td>integration constants are valid at this epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">positionAndVelocity</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">position0x</div></div></td><td>double</td><td>[m] in CRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">position0y</div></div></td><td>double</td><td>[m] in CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">position0z</div></div></td><td>double</td><td>[m] in CRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">velocity0x</div></div></td><td>double</td><td>[m/s]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">velocity0y</div></div></td><td>double</td><td>[m/s]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">velocity0z</div></div></td><td>double</td><td>[m/s]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td>integration constants are valid at this epoch</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateOrbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateOrbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateOrbit</h1><p>\n\nThis program integrates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> from a given force function (dynamic orbit).\nThe force functions are given by <a class=\"groops-class\" href=\"forcesType.html\">forces</a>.\nFor computation of non-conservative forces a <a class=\"groops-file\" href=\"fileFormat_satelliteModel.html\">satelliteModel</a> is needed.\nThe integration method must be selected with <a class=\"groops-class\" href=\"orbitPropagatorType.html\">propagator</a>.\nBecause the orbit data are calculated in the celestial reference frame (CRF) you need\n<a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> to transform the force function\nfrom the terrestrial reference frame (TRF).\nThe integration start and end time, as well as the sampling, are derived from\nthe <strong class=\"groops-config-element\">timeSeries</strong> option. It is possible to integrate the arc in <strong class=\"groops-config-element\">reverse</strong>,\nwhere the initial conditions are assumed to be met at the end time of the <strong class=\"groops-config-element\">timeSeries</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td>orbit file to be written.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>time points for simulated orbit epochs.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">integrationConstants</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">kepler</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">majorAxis</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">eccentricity</div></div></td><td>double</td><td>[-]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inclination</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">ascendingNode</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">argumentOfPerigee</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">meanAnomaly</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">positionAndVelocity</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">position0x</div></div></td><td>double</td><td>[m] in CRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">position0y</div></div></td><td>double</td><td>[m] in CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">position0z</div></div></td><td>double</td><td>[m] in CRF</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">velocity0x</div></div></td><td>double</td><td>[m/s]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">velocity0y</div></div></td><td>double</td><td>[m/s]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">velocity0z</div></div></td><td>double</td><td>[m/s]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">file</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>only epoch at timeStart is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>[seconds] used when finding initial epoch in orbitFile</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">propagator</div></div></td><td><a href=\"orbitPropagatorType.html\">orbitPropagator</a></td><td>orbit propagation method.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">forces</div></div></td><td><a href=\"forcesType.html\">forces</a></td><td>considered in orbit propagation.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">reverse</div></div></td><td>boolean</td><td>start integration at last epoch in timeSeries, going backward in time.</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateSatelliteTracking.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateSatelliteTracking</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateSatelliteTracking</h1><p>\n\nThis program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">tracking data</a> (range, range-rate, range-accelerations)\nbetween 2 satellites. The range is given by\n\\[\n\\rho(t) = \\left\\lVert{\\M r_B(t) - \\M r_A(t)}\\right\\rVert = \\M e_{AB}(t)\\cdot\\M r_{AB}(t),\n\\]with $\\M r_{AB} = \\M r_B - \\M r_A$ and the unit vector in line of sight (LOS) direction\n\\[\\label{sst.los}\n\\M e_{AB} = \\frac{\\M r_{AB}}{\\left\\lVert{\\M r_{AB}}\\right\\rVert}=\\frac{\\M r_{AB}}{\\rho}.\n\\]Range-rates $\\dot{\\rho}$ and range accelrations $\\ddot{\\rho}$ are obtained by differentation\n\\[\\label{obsRangeRate}\n\\dot{\\rho}  = \\M e_{AB}\\cdot\\dot{\\M r}_{AB} + \\dot{\\M e}_{AB}\\cdot\\M r_{AB}\n            = \\M e_{AB}\\cdot\\dot{\\M r}_{AB},\n\\]\\[\\label{obsRangeAccl}\n\\begin{split}\n\\ddot{\\rho} &= \\M e_{AB}\\cdot\\ddot{\\M r}_{AB} +\\dot{\\M e}_{AB}\\cdot\\dot{\\M r}_{AB}\n            = \\M e_{AB}\\cdot\\ddot{\\M r}_{AB} +\n   \\frac{1}{\\rho}\\left(\\dot{\\M r}_{AB}^2-\\dot{\\rho}^2\\right). \\\\\n\\end{split}\n\\]with the derivative of the unit vector\n\\[\n\\dot{\\M e}_{AB}=\\frac{d}{dt}\\left(\\frac{\\M r_{AB}}{\\rho}\\right)\n=\\frac{\\dot{\\M r}_{AB}}{\\rho}-\\frac{\\dot{\\rho}\\cdot\\M r_{AB}}{\\rho^2}\n=\\frac{1}{\\rho}\\left({\\dot{\\M r}_{AB}-\\dot{\\rho}\\cdot\\M e_{AB}}\\right).\n\\]The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>s must contain positions, velocities, and acceleration\n(see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSatelliteTracking</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td></td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateStarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateStarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateStarCamera</h1><p>\n\nThis program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera</a> measurements at each satellite's position.\nThe satellite's orientation follows a local orbit frame with the x-axis in along track (along velocity),\ny-axis is cross track (normal to position and velocity vector) and z-axis pointing nadir (negative position vector).\nAs for non circular orbit the position and velocity are not exact normal, the default is the x-axis to be exact\nalong velocity and the z-axis forms a right hand system (not exact nadir) or with <strong class=\"groops-config-element\">nadirPointing</strong> the z-axis\nis exact nadir and x-axis approximates along.\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>rotation from satellite to inertial frame (x: along, y: cross, z: nadir)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>position and velocity defines the orientation of the satellite at each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nadirPointing</div></div></td><td>boolean</td><td>false: exact along and nearly nadir, true: nearly along and exact nadir</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateStarCameraGnss.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateStarCameraGnss</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateStarCameraGnss</h1><p>\n\nThis program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera</a> measurements at each satellite position\nof <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nThe resulting rotation matrices rotate from body frame to inertial frame. The body frame refers\nto the IGS-specific (not the manufacturer-specific) body frame, as described by\n<a href=\"https://doi.org/10.1016/j.asr.2015.06.019\">Montenbruck et al. (2015)</a>.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain velocities\n(use <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a> if needed).</p><p>Information about the attitude mode(s) used by the GNSS satellite may be provided via\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitudeInfo</a>. This file can be created with\n<a class=\"groops-program\" href=\"GnssAttitudeInfoCreate.html\">GnssAttitudeInfoCreate</a>. It contains one or more time-dependent entries,\neach defining the default attitude mode, the attitude modes used around orbit noon and\nmidnight, and some parameters required by the various modes.\nIf no <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitudeInfo</a> is selected, the program defaults\nto a nominal yaw-steering attitude model.\nA sufficiently high <strong class=\"groops-config-element\">modelingResolution</strong> ensures that the attitude behavior is modeled properly\nat all times.</p><p>The attitude behavior is defined by the respective mode. Here is a list of the supported\nmodes with a brief explanation and references:\n<ul>\n\n<li><b>nominalYawSteering</b>:\n      Yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) [1]\n</li><li>\n<b>orbitNormal</b>:\n      Keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) [1]\n</li><li>\n<b>catchUpYawSteering</b>:\n      Yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) [2, 3]\n</li><li>\n<b>shadowMaxYawSteeringAndRecovery</b>:\n      Yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight)) [2]\n</li><li>\n<b>shadowMaxYawSteeringAndStop</b>:\n      Yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached,\n      then stop (e.g. GLO-M (midnight)) [4]\n</li><li>\n<b>shadowConstantYawSteering</b>:\n      Yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight)) [3]\n</li><li>\n<b>centeredMaxYawSteering</b>:\n      Yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) [4, 8]\n</li><li>\n<b>smoothedYawSteering1</b>:\n      Yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) [5]\n</li><li>\n<b>smoothedYawSteering2</b>:\n      Yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) [5, 6]\n</li><li>\n<b>betaDependentOrbitNormal</b>:\n      Switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) [7, 8]\n</li></ul>\n</p><p><figure><img class=\"figure\" style=\"width:90%;\" src=\"../figures/gnssAttitudeModes.png\" alt=\"gnssAttitudeModes\"><figcaption class=\"center\">Figure: Overview of attitude modes used by GNSS satellites</figcaption></figure></p><p>See <a class=\"groops-program\" href=\"GnssAttitudeInfoCreate.html\">GnssAttitudeInfoCreate</a> for more details on which satellite uses which attitude modes\nand the required parameters for each mode.</p><p>References for the attitude modes:\n<ol>\n\n<li><a href=\"https://doi.org/10.1016/j.asr.2015.06.019\">Montenbruck et al. (2015)</a>\n</li><li>\n<a href=\"https://doi.org/10.1007/s10291-008-0092-1\">Kouba (2009)</a>\n</li><li>\n<a href=\"https://doi.org/10.1007/s10291-016-0562-9\">Kuang et al. (2017)</a>\n</li><li>\n<a href=\"https://doi.org/10.1016/j.asr.2010.09.007\">Dilssner et al. (2011)</a>\n</li><li>\n<a href=\"https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3\" target=\"_blank\">https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3</a>\n</li><li>\n<a href=\"https://doi.org/10.1007/s10291-018-0783-1\">Wang et al. (2018)</a>\n</li><li>\n<a href=\"https://doi.org/10.1017/S0373463318000103\">Li et al. (2018)</a>\n</li><li>\n<a href=\"https://qzss.go.jp/en/technical/qzssinfo/index.html\" target=\"_blank\">https://qzss.go.jp/en/technical/qzssinfo/index.html</a>\n</li></ol>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>rotation from body frame to CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>attitude is modeled based on this orbit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAttitudeInfo</div></div></td><td>filename</td><td>attitude modes used by the satellite and respective parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>polynomial degree for orbit interpolation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">modelingResolution</div></div></td><td>double</td><td>[s] resolution for attitude model evaluation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td>model to determine if satellite is in Earth's shadow</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateStarCameraGrace.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateStarCameraGrace</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateStarCameraGrace</h1><p>\n\nSimulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera data</a> of the two GRACE satellites.\n<ul>\n\n<li>x: the antenna center pointing to the other satellite.\n</li><li>\ny: normal to line of sight and the radial direction.\n</li><li>\nz: forms a right handed system.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td>position define the orientation of the satellite at each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td>position define the orientation of the satellite at each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">antennaCenters</div></div></td><td>choice</td><td>KBR antenna phase center</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">value</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1X</div></div></td><td>double</td><td>x-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1Y</div></div></td><td>double</td><td>y-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center1Z</div></div></td><td>double</td><td>z-coordinate of antenna position in SRF [m] for GRACEA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2X</div></div></td><td>double</td><td>x-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2Y</div></div></td><td>double</td><td>y-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">center2Z</div></div></td><td>double</td><td>z-coordinate of antenna position in SRF [m] for GRACEB</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">file</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">inputAntennaCenters</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateStarCameraSentinel1.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateStarCameraSentinel1</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateStarCameraSentinel1</h1><p>\n\nThis program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera</a> measurements at each satellite's position for the Sentinel 1A satellite.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain positions and velocities (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>).\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>position and velocity defines the orientation of the satellite at each epoch</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SimulateStarCameraTerrasar.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SimulateStarCameraTerrasar</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SimulateStarCameraTerrasar</h1><p>\n\nThis program simulates <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStarCamera</a> measurements at each satellite's position for the Terrasar satellite.\nThe <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain positions and velocities (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>).\nThe resulting rotation matrices rotate from satellite frame to inertial frame.</p><p>H. Fiedler, E. Boerner, J. Mittermayer and G. Krieger,\nTotal zero Doppler Steering-a new method for minimizing the Doppler centroid,\nin IEEE Geoscience and Remote Sensing Letters, vol. 2, no. 2, pp. 141-145, April 2005, <a href=\"https://www.doi.org/10.1109/LGRS.2005.844591\" target=\"_blank\">https://www.doi.org/10.1109/LGRS.2005.844591</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td>rotation from satellite to inertial frame (x: along, y: cross, z: nadir)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>position and velocity defines the orientation of the satellite at each epoch</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sinex2Normals.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sinex2Normals</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sinex2Normals</h1><p>\n\nConvert normal equations from <a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a>\nto <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a>.</p><p>See also <a class=\"groops-program\" href=\"GnssNormals2Sinex.html\">GnssNormals2Sinex</a> and <a class=\"groops-program\" href=\"NormalsSphericalHarmonics2Sinex.html\">NormalsSphericalHarmonics2Sinex</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileNormals</div></div></td><td>filename</td><td>N, n: unconstrained normal equations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileNormalsConstraint</div></div></td><td>filename</td><td>N0, n0: normal equations of applied constraints</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolution</div></div></td><td>filename</td><td>x: parameter vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSolutionApriori</div></div></td><td>filename</td><td>x0: a priori parameter vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputFileSinex</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sinex2StationDiscontinuities.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sinex2StationDiscontinuities</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sinex2StationDiscontinuities</h1><p>\n\nConvert station discontinuities from\n<a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a>\n(e.g. ITRF20) to <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> (MISCVALUE).\nA value of 1 means position discontinuity, a value of 2 means velocity discontinuity.\nStart and end epochs with value 0 are added in addition to the discontinuities from\nSINEX to define continuity interval borders.</p><p>See also <a class=\"groops-program\" href=\"Sinex2StationPosition.html\">Sinex2StationPosition</a> and <a class=\"groops-program\" href=\"Sinex2StationPostSeismicDeformation.html\">Sinex2StationPostSeismicDeformation</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>loop variable is replaced with station name (e.g. wtzz)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDiscontinuities</div></div></td><td>filename</td><td>SINEX (e.g. ITRF20) station discontinuities</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopStation</div></div></td><td>string</td><td>variable name for station loop</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationName</div></div></td><td>string</td><td>only export these stations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sinex2StationPosition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sinex2StationPosition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sinex2StationPosition</h1><p>\n\nDEPRECATED since 2023-02-16. Please use <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>loop variable is replaced with station name (e.g. wtzz)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinex</div></div></td><td>filename</td><td>SINEX file (.snx or .ssc)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileDiscontinuities</div></div></td><td>filename</td><td>discontinuities file per station; loop variable is replaced with station name (e.g. wtzz)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopStation</div></div></td><td>string</td><td>variable name for station loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationName</div></div></td><td>string</td><td>convert only these stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>compute positions for these epochs based on velocity</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">extrapolateForward</div></div></td><td>boolean</td><td>also compute positions for epochs after last interval defined in SINEX file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">extrapolateBackward</div></div></td><td>boolean</td><td>also compute positions for epochs before first interval defined in SINEX file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sinex2StationPositions.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sinex2StationPositions</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sinex2StationPositions</h1><p>\n\nExtracts station positions from <strong class=\"groops-config-element\">inputfileSinexSolution</strong>\n(<a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format description</a>)\nand writes an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> of type VECTOR3D\nfor each station.  Positions will be computed at <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> based on position and velocity\nof each provided interval in the SINEX file.\nWith <strong class=\"groops-config-element\">inputfileSinexDiscontinuities</strong> the bounds of these time spans are adjusted to the exact epochs of discontinuities.\nThe <strong class=\"groops-config-element\">inputfileSinexPostSeismicDeformations</strong> adds the ITRF post-seismic deformation model to the affected stations.\nThe <strong class=\"groops-config-element\">inputfileSinexFrequencies</strong> adds annual and semi-annual frequencies.</p><p>If <strong class=\"groops-config-element\">extrapolateBackward</strong> or <strong class=\"groops-config-element\">extrapolateForward</strong> are provided, positions will also be computed for epochs\nbefore the first interval/after the last interval, based on the position and velocity of the first/last interval.\nPosition extrapolation will stop at the first discontinuity before the first interval/after the last interval.</p><p>Stations can be limited via <strong class=\"groops-config-element\">stationName</strong>, otherwise all stations in <strong class=\"groops-config-element\">inputfileSinexSolution</strong> will be used.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>loop variable is replaced with station name (e.g. wtzz)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopStation</div></div></td><td>string</td><td>variable name for station loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinexSolution</div></div></td><td>filename</td><td>SINEX file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSinexDiscontinuities</div></div></td><td>filename</td><td>SINEX file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSinexPostSeismicDeformations</div></div></td><td>filename</td><td>SINEX file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSinexFrequencies</div></div></td><td>filename</td><td>SINEX file (XYZ or ENU)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>compute positions for these epochs based on velocity</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">extrapolateForward</div></div></td><td>boolean</td><td>also compute positions for epochs after last interval defined in SINEX file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">extrapolateBackward</div></div></td><td>boolean</td><td>also compute positions for epochs before first interval defined in SINEX file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationName</div></div></td><td>string</td><td>convert only these stations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sinex2StationPostSeismicDeformation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sinex2StationPostSeismicDeformation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sinex2StationPostSeismicDeformation</h1><p>\n\nDEPRECATED since 2023-02-16. Please use <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a> instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileInstrument</div></div></td><td>filename</td><td>deformation time series</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinex</div></div></td><td>filename</td><td>ITRF post-seismic deformation SINEX file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>compute deformation for these epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">stationName</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">localLevelFrame</div></div></td><td>boolean</td><td>output in North, East, Up local-level frame</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SinexEccentricties2SlrPlatform.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SinexEccentricties2SlrPlatform</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SinexEccentricties2SlrPlatform</h1><p>\n\nReads metadata like station name, station number, approximate station position and station eccentricities\nfrom <a href=\"https://ilrs.gsfc.nasa.gov/network/site_procedures/eccentricity.html\">Station Eccentricities Sinex File</a>\n(une version) and write them to the <a class=\"groops-class\" href=\"fileFormat_platform.html\">outputfileStationInfo</a> for each station.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStationInfo</div></div></td><td>filename</td><td>loop variable is replaced with station name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopStation</div></div></td><td>string</td><td>variable name for station loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinex</div></div></td><td>filename</td><td>SINEX file (.snx or .ssc)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationName</div></div></td><td>string</td><td>convert only these stations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SinexMetadata2GlonassFrequencyNumber.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SinexMetadata2GlonassFrequencyNumber</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SinexMetadata2GlonassFrequencyNumber</h1><p>\n\nCreate <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrixPrn2FrequencyNumber</a> matrix\nfrom <a href=\"https://www.igs.org/mgex/metadata/#metadata\">IGS SINEX metadata format</a>\nwith the columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber.</p><p>See also <a class=\"groops-program\" href=\"GnssGlonassFrequencyNumberUpdate.html\">GnssGlonassFrequencyNumberUpdate</a>, <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>,\n<a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrixPrn2FrequencyNumber</div></div></td><td>filename</td><td>GROOPS matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinexMetadata</div></div></td><td>filename</td><td>IGS SINEX metadata file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SinexMetadata2SatelliteModel.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SinexMetadata2SatelliteModel</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SinexMetadata2SatelliteModel</h1><p>\n\nCreate <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">outputfileSatelliteModel</a> from <a href=\"https://www.igs.org/mgex/metadata/#metadata\">IGS SINEX metadata format</a>.</p><p>If <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">inputfileSatelliteModel</a> is provided it is used as a basis and values are updated from the metadata file.</p><p>See also <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileSatelliteModel</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinexMetadata</div></div></td><td>filename</td><td>IGS SINEX metadata file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>base satellite model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">svn</div></div></td><td>string</td><td>e.g. G040, R736, E204, C211</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SlrComModel2RangeBiasStationSatellite.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SlrComModel2RangeBiasStationSatellite</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SlrComModel2RangeBiasStationSatellite</h1><p>\n\nConverts the tables of CoM corrections of José Rodríguez\n(<a href=\"https://icts-yebes.oan.es/slr/com_models/models/\" target=\"_blank\">https://icts-yebes.oan.es/slr/com_models/models/</a>) into station/satellite\nspecific <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileRangeBias</a>. Only the deviations to the default value in\n<a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileSatelliteInfo</a> are written. This program must be called for every\nprovided satellite. The range bias values can be used in\n<a class=\"groops-class\" href=\"slrParametrizationType.html#rangeBiasStationSatelliteApriori\">parametrization:rangeBiasStationSatelliteApriori</a>\nin <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.</p><p>Reference:\nRodriguez J., Otsubo T., Appleby G. Upgraded Modelling for the\nDetermination of Centre of Mass Corrections of Geodetic SLR\nSatellites: Impact on Key Parameters of the Terrestrial Reference\nFrame. Journal of Geodesy, 2019. doi: 10.1007/s00190-019-01315-0\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileRangeBias</div></div></td><td>filename</td><td>MISCVALUE, variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteInfo</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td>from Rodriguez model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopStation</div></div></td><td>string</td><td>variable name for station loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationName</div></div></td><td>string</td><td>convert only these stations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SlrProcessing.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SlrProcessing</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SlrProcessing</h1><p>\n\nThis program processes SLR normal point or full rate observations. It calculates the linearized observation equations,\naccumulates them into a system of normal equations and solves it.</p><p>To calculate observation equations from the passes, the model parameters or unknown parameters need to be\ndefined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined\n<a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrization</a>.\nSome of the <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrization</a> also include a priori models.</p><p>Lastly it is required to define the process flow of the SLR processing. This is accomplished\nwith a list of <a class=\"groops-class\" href=\"slrProcessingStepType.html\">processingSteps</a>.\nEach step is processed consecutively. Some steps allow the selection of parameters, station, or satellites,\nwhich affects all subsequent steps.</p><p>The <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is used to precompute Earth rotation and station displacements\nwith a uniform sampling. In a second step these values are interpolated to the observation epochs.\nA sampling of about 10 minutes should be adequate.</p><p>It should be noted that GROOPS uses GPS time format, but normal point/full rate data files and CPF files, provided by ILRS data centers\nare given in UTC time format.\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>defines station movements and earth rotation epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">satellite</div></div></td><td><a href=\"slrSatelliteGeneratorType.html\">slrSatelliteGenerator</a></td><td>satellites</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">station</div></div></td><td><a href=\"slrStationGeneratorType.html\">slrStationGenerator</a></td><td>ground station network</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>apriori earth rotation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"slrParametrizationType.html\">slrParametrization</a></td><td>models and parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">processingStep</div></div></td><td><a href=\"slrProcessingStepType.html\">slrProcessingStep</a></td><td>steps are processed consecutively</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SlrSinexDataHandling2Files.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SlrSinexDataHandling2Files</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SlrSinexDataHandling2Files</h1><p>\n\nConverts SLR range and time bias from <code>ILRS_Data_Handling_File_xxxx.xx.xx.snx</code> provided at\n<a href=\"https://cddis.nasa.gov/archive/slr/products/resource/\" target=\"_blank\">https://cddis.nasa.gov/archive/slr/products/resource/</a>. The range and time bias values can be used in\n<a class=\"groops-class\" href=\"slrParametrizationType.html#rangeBiasStationApriori\">parametrization:rangeBiasXxxApriori</a>\nin <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileRangeBiasStation</div></div></td><td>filename</td><td>MISCVALUE [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileRangeBiasStationSatellite</div></div></td><td>filename</td><td>MISCVALUE [m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTimeBias</div></div></td><td>filename</td><td>MISCVALUES(bias [s], drift [s/d])</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopStation</div></div></td><td>string</td><td>variable name for station loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopSatellite</div></div></td><td>string</td><td>variable name for satellite loop</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSinex</div></div></td><td>filename</td><td>SINEX file (.snx)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteId</div></div></td><td>filename</td><td>table SP3 and satellite name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stationName</div></div></td><td>string</td><td>convert only these stations</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Sp3Format2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Sp3Format2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Sp3Format2Orbit</h1><p>\n\nRead orbits from <a href=\"https://files.igs.org/pub/data/format/sp3d.pdf\">SP3 format</a>\nand write an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.\nThe additional <strong class=\"groops-config-element\">outputfileClock</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a>\nand <strong class=\"groops-config-element\">outputfileCovariance</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (COVARIANCE3D)</a>.</p><p>With <strong class=\"groops-config-element\">satelliteIdentifier</strong> a single satellite can be selected if the <strong class=\"groops-config-element\">inputfile</strong>s\ncontain more than one satellites. If <strong class=\"groops-config-element\">satelliteIdentifier</strong> is empty the first satellite is taken.\nAll satellites can be selected with <strong class=\"groops-config-element\">satelliteIdentifier</strong>=<code>&lt;all></code>.\nIn this case the identifier is appended to each output file.</p><p>If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided the data are transformed\nfrom terrestrial (TRF) to celestial reference frame (CRF).\nSince SP3 orbits often use the center of Earth as a reference, a correction from center\nof Earth to center of mass can be applied to the orbits by providing <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> (e.g. ocean tides).</p><p>See also <a class=\"groops-program\" href=\"Orbit2Sp3Format.html\">Orbit2Sp3Format</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClock</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovariance</div></div></td><td>filename</td><td>3x3 epoch covariance</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">satelliteIdentifier</div></div></td><td>string</td><td>e.g. L09 for GRACE A, empty: take first satellite, <all>: identifier is appended to each file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotation from TRF to CRF</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>orbits in SP3 format</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/StarCamera2GraceL1b.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - StarCamera2GraceL1b</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>StarCamera2GraceL1b</h1><p>\n\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GROOPS format <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a> to the GRACE SDS format (SCA1B).</p><p>It reads one <strong class=\"groops-config-element\">inputfileStarCamera</strong> and optionally one\n<strong class=\"groops-config-element\">inputfileStarCameraFlags</strong> containing <a class=\"groops-file\" href=\"fileFormat_instrument.html\">MISCVALUES</a>(sca_id, qual_rss, qualflg),\nand writes one SDS output file.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>.\nThe <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables <code>{epochmin}</code>, |<code>{epochmax}</code>,\nand <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2StarCamera.html\">GraceL1b2StarCamera</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfile</div></div></td><td>filename</td><td>SCA1B</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileHeader</div></div></td><td>filename</td><td>YAML Header, {epochmin}, {epochmax}, {epochcount} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td>STARCAMERA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStarCameraFlags</div></div></td><td>filename</td><td>MISCVALUES(sca_id, qual_rss, qualflg)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">satelliteId</div></div></td><td>string</td><td>A, B, C or D</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/StarCamera2Orbex.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - StarCamera2Orbex</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>StarCamera2Orbex</h1><p>\n\nConverts satellite attitude from <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a> to\n<a href=\"http://acc.igs.org/misc/ORBEX009.pdf\">ORBEX file format</a> (quaternions).</p><p>If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided, the output file contains quaternions\nfor rotation from TRF to satellite body frame (IGS/ORBEX convention),\notherwise the rotation is from CRF to satellite body frame.</p><p>See also <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>, <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbex</div></div></td><td>filename</td><td>ORBEX file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">satellite</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">identifier</div></div></td><td>string</td><td>string identifier (e.g. GNSS PRN: G01)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>e.g. BLOCK IIR-B, GRACE</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotate data into Earth-fixed frame</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>resample to these epochs (otherwise input file epochs are used)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">interpolationDegree</div></div></td><td>uint</td><td>for attitude and Earth rotation interpolation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">description</div></div></td><td>string</td><td>description of file contents</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">createdBy</div></div></td><td>string</td><td>name of agency</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputData</div></div></td><td>string</td><td>description of input data (see ORBEX description)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">contact</div></div></td><td>string</td><td>email address</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">referenceFrame</div></div></td><td>string</td><td>reference frame used in file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">comment</div></div></td><td>string</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Swarm2Starcamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Swarm2Starcamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Swarm2Starcamera</h1><p>\n\nThis program reads SWARM star camera data given in the cdf format\nand before converted to an ascii file using the program <code>cdfexport</code>\nprovided by the Goddard Space Flight Center (<a href=\"http://cdf.gsfc.nasa.gov/\" target=\"_blank\">http://cdf.gsfc.nasa.gov/</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/SynthesisSphericalHarmonicsMatrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SynthesisSphericalHarmonicsMatrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SynthesisSphericalHarmonicsMatrix</h1><p>\n\nThis program builds a linear operator matrix for spherical harmonic analysis or synthesis based on\nthe points defined in <a class=\"groops-class\" href=\"gridType.html\">grid</a>. Depending on the chosen\n<strong class=\"groops-config-element\">type</strong> (synthesis, quadrature, or leastSquares), the resulting matrix can be used to:\n<ul>\n\n  <li><b>synthesis</b>: Map spherical harmonic coefficients to values on a grid,\n  </li><li>\n<b>quadrature</b>: Integrate grid-based functionals into spherical harmonic coefficients by\n        a simple quadrature formula,\n  </li><li>\n<b>leastSquares</b>: Estimate coefficients from grid data via a least squares approach.\n</li></ul>\n</p><p>he spherical harmonic degree range is constrained by\n<strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong>, and the ordering of the coefficients is given by\n<a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>. The reference gravitational\nconstant is <strong class=\"groops-config-element\">GM</strong>, and the reference radius is <strong class=\"groops-config-element\">R</strong>.</p><p>The computed matrix is written to <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> with dimensions\n(number of grid points) $\\times$ (number of spherical harmonic coefficients). For\n<strong class=\"groops-config-element\">type</strong> = <em>leastSquares</em>, the program applies a QR-based pseudo-inverse so that the\noutput matrix can directly form the normal-equation building blocks for a blockwise\nleast-squares solution in spherical harmonic space.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>, <a class=\"groops-program\" href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a>,\n<a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a>, and <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a> for additional\ntools to convert between grids and spherical harmonics.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme of sh coefficients</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">synthesis</div></div></td><td></td><td>synthesize spherical harmonics on a grid</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">quadrature</div></div></td><td></td><td>calculate spherical harmonics from grid</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">leastSquares</div></div></td><td></td><td>estimated spherical harmonics from grid</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/TemporalRepresentation2TimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TemporalRepresentation2TimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TemporalRepresentation2TimeSeries</h1><p>\n\nThis program computes the design matrix of temporal representation at a given time series.\nThe output matrix contains the time steps in MJD in the first column, the other columns contain the design matrix.\nThe intention of this program is to visualize the parametrization together with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileMatrix</div></div></td><td>filename</td><td>Time (MJD) in first column, design matrix follows</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/TerraSarTandem2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TerraSarTandem2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TerraSarTandem2Orbit</h1><p>\n\nThis program reads in TerraSar-X or Tandem-X orbits in the special CHORB format and takes the appropriate\ntime frame as stated in the document header.\nA description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>orbits in CHORB format</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/TerraSarTandem2StarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TerraSarTandem2StarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TerraSarTandem2StarCamera</h1><p>\n\nThis program reads in TerraSar-X or Tandem-X star camera data given in the special format.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ThermosphericState2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ThermosphericState2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ThermosphericState2GriddedData</h1><p>\n\nThis program converts the output (neutral mass density,temperature) of an empirical thermosphere model (e.g. JB2008) on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>.\nAdditionally, also the thermospheric winds estimated by using the horizontal wind model HWM 2014 can be assessed.\nThe time for the evaluation can be specified in <strong class=\"groops-config-element\">time</strong>. The values will be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.\n<figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/thermosphericState2GriddedData.png\" alt=\"thermosphericState2GriddedData\"><figcaption class=\"center\">Figure: JB2008 model in 300 km height at 2003-07-01 12:00.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileGriddedData</div></div></td><td>filename</td><td>density [kg/m**3], temperature [K], wind (x, y, z) [m/s**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">thermosphere</div></div></td><td><a href=\"thermosphereType.html\">thermosphere</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time</div></div></td><td>time</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">localReferenceFrame</div></div></td><td>boolean</td><td>wind in local north, east, up, otherwise global terrestrial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\nThis program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/TimeSeries2GriddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TimeSeries2GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TimeSeries2GriddedData</h1><p>\n\nInterpret the data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeSeries</a>\nas data points of a corresponding <a class=\"groops-class\" href=\"gridType.html\">grid</a>.</p><p>For each epoch a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data file</a> is written where\nthe <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> are expanded for\neach point of the given time series to create the file name for this epoch\n(see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>).</p><p>The number of input data columns must be a multiple of the number $n$ of grid points.\nIf <strong class=\"groops-config-element\">isGroupedDataByPoint</strong> is true the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeSeries</a> starts\nwith all data (<code>data0</code>, <code>data1</code>&hellip; ) for the first point, followed by all data of the second point and so on.\nIf <strong class=\"groops-config-element\">isGroupedDataByPoint</strong> is false, the file starts with <code>data0</code> for all points, followed by all <code>data1</code> and so on.</p><p>See also <a class=\"groops-program\" href=\"GriddedData2TimeSeries.html\">GriddedData2TimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilesGriddedData</div></div></td><td>filename</td><td>for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTime</div></div></td><td>string</td><td>variable with time of each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current epoch (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTimeSeries</div></div></td><td>filename</td><td>each epoch: multiple data for points (MISCVALUES)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td>corresponding grid points</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">isDataGroupedByPoint</div></div></td><td>boolean</td><td>multiple data are given point by point, otherwise: first data0 for all points, followed by all data1</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoidal coordinates on output</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/TimeSeries2PotentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TimeSeries2PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TimeSeries2PotentialCoefficients</h1><p>\n\nInterpret the data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeSeries</a>\nas potential coefficients. The sequence of coefficients is given by\n<a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a> starting from data column <strong class=\"groops-config-element\">startDataFields</strong>.</p><p>For each epoch a <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilesPotentialCoefficients</a>\nis written where the <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> are expanded for\neach point of the given time series to create the file name for this epoch,\nsee <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficientsTimeSeries.html\">Gravityfield2PotentialCoefficientsTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfilesPotentialCoefficients</div></div></td><td>filename</td><td>for each epoch</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTime</div></div></td><td>string</td><td>variable with time of each epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current epoch (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of epochs</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTimeSeries</div></div></td><td>filename</td><td>each epoch: multiple data for points (MISCVALUES)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startDataFields</div></div></td><td>uint</td><td>first data column</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td>minimal degree</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>maximal degree</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/TimeSeriesCreate.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TimeSeriesCreate</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TimeSeriesCreate</h1><p>\n\nThis program generates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>,\ncontaining a time series.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileTimeSeries</div></div></td><td>filename</td><td>instrument file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>time series to be created</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">data</div></div></td><td>expression</td><td>expression of output columns, extra 'epoch' variable</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Tle2Orbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Tle2Orbit</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Tle2Orbit</h1><p>\n\nThis program computes the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>\nfrom two-line elements (TLE/3LE)\nas can be found at e.g. <a href=\"http://celestrak.org/NORAD/elements/\" target=\"_blank\">http://celestrak.org/NORAD/elements/</a>.\nThe first satellite in the input file that matches the wildcard of <strong class=\"groops-config-element\">satelliteName</strong> is used.\nIf more records with exactly the same name are found, the one with the closest reference epoch\nis used for each point in the <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>.</p><p>The program uses the Simplified General Perturbation (SGP) model. More information can\nbe found in the Revisiting Spacetrack Report 3 by Vallado et al. 2006.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTLE</div></div></td><td>filename</td><td>two line elements (TLE/3LE)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">satelliteName</div></div></td><td>string</td><td>first name of wildcard match is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>output orbit at these times</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td>rotation to CRF</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/Variational2OrbitAndStarCamera.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Variational2OrbitAndStarCamera</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Variational2OrbitAndStarCamera</h1><p>\n\nExtracts the reference <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStarCamera</a>,\nand <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileEarthRotation</a> from <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>output orbit (instrument) file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileStarCamera</div></div></td><td>filename</td><td>output satellite attidude as star camera (instrument) file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileEarthRotation</div></div></td><td>filename</td><td>output Earth rotation as star camera (instrument) file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>input variational file</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ViennaMappingFunctionGrid2File.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ViennaMappingFunctionGrid2File</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ViennaMappingFunctionGrid2File</h1><p>\n\nThis program converts the gridded time series of the Vienna Mapping Functions (VMF) into\nthe <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">GROOPS file format</a>.</p><p>Gridded VMF data is available at: <a href=\"https://vmf.geo.tuwien.ac.at/trop_products/GRID/\" target=\"_blank\">https://vmf.geo.tuwien.ac.at/trop_products/GRID/</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileVmfCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>files must be given for each point in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>times of input files</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaLambda</div></div></td><td>angle</td><td>[deg] sampling in longitude</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaPhi</div></div></td><td>angle</td><td>[deg] sampling in latitude</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">isCellRegistered</div></div></td><td>boolean</td><td>grid points represent cells (VMF3), not grid corners (VMF1)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ViennaMappingFunctionStation2File.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ViennaMappingFunctionStation2File</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ViennaMappingFunctionStation2File</h1><p>\n\nConverts Vienna Mapping Functions (VMF) station time series into <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">GROOPS file format</a>.</p><p>Station-wise VMF data for GNSS is available at: <a href=\"https://vmf.geo.tuwien.ac.at/trop_products/GNSS/\" target=\"_blank\">https://vmf.geo.tuwien.ac.at/trop_products/GNSS/</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileVmfCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVmf</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/autoregressiveModelSequenceType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - autoregressiveModelSequenceType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"autoregressiveModelSequenceType\">AutoregressiveModelSequence</h1><p>\nRepresents a sequence of multivariate autoregressive (AR) models with increasing order $p$.\nThe AR models should be stored as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix file</a> in the <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">GROOPS definition of\nAR models</a>.\nThe required AR models can be computed with <a class=\"groops-program\" href=\"CovarianceMatrix2AutoregressiveModel.html\">CovarianceMatrix2AutoregressiveModel</a>,\nand passed to this class through\n<strong class=\"groops-config-element\">inputfileAutoregressiveModel</strong> in increasing order.</p><p>The main purpose of AutoregressiveModelSequence is to use AR models of the form\n\\[\n  \\label{eq:ar-model}\n  \\mathbf{y}_e(t_i) = \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{w}(t_i),\n  \\hspace{5pt} \\mathbf{w}(t_i) \\sim \\mathcal{N}(0, \\mathbf{\\Sigma}^{(p)}_\\mathbf{w}),\n\\]to create pseudo-observation equations\n\\[\n  \\label{eq:pseudo-observations-transformed}\n  0 = \\bar{\\mathbf{\\Phi}} \\Delta\\mathbf{y} + \\bar{\\mathbf{w}}, \\hspace{5pt} \\bar{\\mathbf{w}} \\sim\n  \\mathcal{N}(0, \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}}),\n\\]with\n\\[\n  \\label{eq:pseudo-observations-ar}\n  \\bar{\\mathbf{\\Phi}} =\n  \\begin{bmatrix}\n    \\mathbf{I} & & & & & \\\\\n    -\\mathbf{\\Phi}^{(1)}_1 & \\mathbf{I} & & & &  \\\\\n    -\\mathbf{\\Phi}^{(2)}_2 & -\\mathbf{\\Phi}^{(2)}_1 & \\mathbf{I} & & & \\\\\n    -\\mathbf{\\Phi}^{(3)}_3 & -\\mathbf{\\Phi}^ {(3)}_2 & -\\mathbf{\\Phi}^ {(3)}_1 & \\mathbf{I} & &  \\\\\n    & -\\mathbf{\\Phi}^{(3)}_3 & -\\mathbf{\\Phi}^ {(3)}_2 & -\\mathbf{\\Phi}^ {(3)}_1 & \\mathbf{I} &  \\\\\n    & & \\ddots & \\ddots & \\ddots & \\ddots  \\\\\n  \\end{bmatrix},\n  \\hspace{15pt}\n  \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}} =\n  \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}} =\n  \\begin{bmatrix}\n    \\mathbf{\\Sigma}^{(0)}_{\\mathbf{w}} & & & & & \\\\\n    & \\mathbf{\\Sigma}^{(1)}_{\\mathbf{w}} & & & & \\\\\n    & & \\mathbf{\\Sigma}^{(2)}_{\\mathbf{w}} & & & \\\\\n    & & & \\mathbf{\\Sigma}^{(3)}_{\\mathbf{w}} & & \\\\\n    & & & & \\mathbf{\\Sigma}^{(3)}_{\\mathbf{w}} &  \\\\\n    & & & & & \\ddots \\\\\n  \\end{bmatrix}.\n\\]used to constrain high-frequency temporal gravity field variations (see\n<a class=\"groops-program\" href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a>, <a class=\"groops-program\" href=\"NormalsBuildShortTimeStaticLongTime.html\">NormalsBuildShortTimeStaticLongTime</a>,\n<a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a>).</p><p>The corresponding normal equation coefficient matrix is given by\n\\[\n  \\label{eq:ar-normals}\n  \\bar{\\mathbf{\\Phi}}^T\\bar{\\mathbf{\\Sigma}}^{-1}_{\\bar{\\mathbf{w}}}\\bar{\\mathbf{\\Phi}}\n\\]and if all AR models are estimated from the same sample its inverse is a block-Toeplitz covariance matrix\n\\[\n  (\\mathbf{\\Sigma}_{\\mathbf{y}_m})_{ij} =\n  \\begin{cases}\n \\mathbf{\\Sigma}(|j-i|) & \\text{for } i \\leq j \\\\\n \\mathbf{\\Sigma}(|j-i|))^T & \\text{otherwise}\n \\end{cases},\n\\]which can be computed using <a class=\"groops-program\" href=\"AutoregressiveModel2CovarianceMatrix.html\">AutoregressiveModel2CovarianceMatrix</a>.</p><p>A detailed description with applications can be found in:\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). <a href=\"https://doi.org/10.1007/s00190-019-01314-1\" target=\"_blank\">https://doi.org/10.1007/s00190-019-01314-1</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">autoregressiveModelSequenceType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">inputfileAutoregressiveModel</div></div></td><td>filename</td><td>matrix file containing an AR model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma0</div></div></td><td>double</td><td>a-priori sigma for white noise covariance</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/borderType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - borderType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"borderType\">Border</h1><p>\nWith this class you can select one or more region on the surface of the Earth.\nIn every instance of Border you can choose whether the specific region is excluded\nfrom the overall result with the switch <strong class=\"groops-config-element\">exclude</strong>.\nTo determine whether a specific point will be used furthermore the following algorithm will be applied:\nIn a first step all points are selected if first border excludes points otherwise all points excluded.\nWhen every point will be tested for each instance of border from top to bottom.\nIf the point is not in the selected region nothing happens.\nOtherwise it will included or excluded depending on the switch <strong class=\"groops-config-element\">exclude</strong>.</p><p>First Example: The border excludes all continental areas.\nThe result are points on the oceans only.</p><p>Second Example: First border describes the continent north america. The next borders\nexcludes the great lakes and the last border describes Washington island.\nIn this configuration points are selected if they are inside north america\nbut not in the area of the great lakes. But if the point is on Washington island\nit will be included again.\n</p>\n\n<h2>Rectangle</h2><p>\nThe region is restricted along lines of geographical coordinates.\n<strong class=\"groops-config-element\">minPhi</strong> and <strong class=\"groops-config-element\">maxPhi</strong> describe the lower and the upper bound of the region.\n<strong class=\"groops-config-element\">minLambda</strong> and <strong class=\"groops-config-element\">maxLambda</strong> define the left and right bound.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minLambda</div></div></td><td>angle</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxLambda</div></div></td><td>angle</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minPhi</div></div></td><td>angle</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxPhi</div></div></td><td>angle</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exclude</div></div></td><td>boolean</td><td>dismiss points inside</td></tr>\n</table>\n\n<h2>Cap</h2><p>\nThe region is defined by a spherical cap with the center given in geographical coordinates\nlongitude (<strong class=\"groops-config-element\">lambdaCenter</strong>) and latitude (<strong class=\"groops-config-element\">phiCenter</strong>).\nThe radius of the cap is given as aperture angle <strong class=\"groops-config-element\">psi</strong>.</p><p><figure><img class=\"figure\" style=\"width:40%;\" src=\"../figures/borderCap.png\" alt=\"borderCap\"><figcaption class=\"center\">Figure: spherical cap</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">lambdaCenter</div></div></td><td>angle</td><td>longitude of the center of the cap</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">phiCenter</div></div></td><td>angle</td><td>latitude of the center of the cap</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">psi</div></div></td><td>angle</td><td>aperture angle (radius)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exclude</div></div></td><td>boolean</td><td>dismiss points inside</td></tr>\n</table>\n\n<h2 id=\"polygon\">Polygon</h2><p>\nThe region is defined by <a class=\"groops-class\" href=\"fileFormat_polygon.html\">inputfilePolygon</a>\ncontaining one or more polygons given in longitude and latitude.\nAn additional <strong class=\"groops-config-element\">buffer</strong> around the polygon can be defined.\nUse a negative value to shrink the polygon area.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePolygon</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">buffer</div></div></td><td>double</td><td>buffer around polygon [km], <0: inside</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exclude</div></div></td><td>boolean</td><td>dismiss points inside</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/classes.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Classes</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Classes</h1>\n<p>This reference manual details classes included in GROOPS, describing what they are and what they do.\n      For usage examples see the cookbook in the <a href=\"index.html\">documentation overview</a>.</p>\n<p><ul>\n<li><a href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a></li>\n<li><a href=\"borderType.html\">border</a></li>\n<li><a href=\"conditionType.html\">condition</a></li>\n<li><a href=\"covariancePodType.html\">covariancePod</a></li>\n<li><a href=\"covarianceSstType.html\">covarianceSst</a></li>\n<li><a href=\"digitalFilterType.html\">digitalFilter</a></li>\n<li><a href=\"doodson.html\">doodson</a></li>\n<li><a href=\"earthRotationType.html\">earthRotation</a></li>\n<li><a href=\"eclipseType.html\">eclipse</a></li>\n<li><a href=\"ephemeridesType.html\">ephemerides</a></li>\n<li><a href=\"forcesType.html\">forces</a></li>\n<li><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></li>\n<li><a href=\"gnssParametrizationType.html\">gnssParametrization</a></li>\n<li><a href=\"gnssProcessingStepType.html\">gnssProcessingStep</a></li>\n<li><a href=\"gnssReceiverGeneratorType.html\">gnssReceiverGenerator</a></li>\n<li><a href=\"gnssTransmitterGeneratorType.html\">gnssTransmitterGenerator</a></li>\n<li><a href=\"gnssType.html\">gnssType</a></li>\n<li><a href=\"gravityfieldType.html\">gravityfield</a></li>\n<li><a href=\"gridType.html\">grid</a></li>\n<li><a href=\"instrumentTypeType.html\">instrumentType</a></li>\n<li><a href=\"interpolatorTimeSeriesType.html\">interpolatorTimeSeries</a></li>\n<li><a href=\"kernelType.html\">kernel</a></li>\n<li><a href=\"loopType.html\">loop</a></li>\n<li><a href=\"magnetosphereType.html\">magnetosphere</a></li>\n<li><a href=\"matrixGeneratorType.html\">matrixGenerator</a></li>\n<li><a href=\"miscAccelerationsType.html\">miscAccelerations</a></li>\n<li><a href=\"noiseGeneratorType.html\">noiseGenerator</a></li>\n<li><a href=\"normalEquationType.html\">normalEquation</a></li>\n<li><a href=\"observationType.html\">observation</a></li>\n<li><a href=\"orbitPropagatorType.html\">orbitPropagator</a></li>\n<li><a href=\"parameterNamesType.html\">parameterNames</a></li>\n<li><a href=\"parameterSelectorType.html\">parameterSelector</a></li>\n<li><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></li>\n<li><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></li>\n<li><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></li>\n<li><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></li>\n<li><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></li>\n<li><a href=\"planetType.html\">planet</a></li>\n<li><a href=\"platformSelectorType.html\">platformSelector</a></li>\n<li><a href=\"plotAxisType.html\">plotAxis</a></li>\n<li><a href=\"plotColorType.html\">plotColor</a></li>\n<li><a href=\"plotColorbarType.html\">plotColorbar</a></li>\n<li><a href=\"plotGraphLayerType.html\">plotGraphLayer</a></li>\n<li><a href=\"plotLegendType.html\">plotLegend</a></li>\n<li><a href=\"plotLineType.html\">plotLine</a></li>\n<li><a href=\"plotMapLayerType.html\">plotMapLayer</a></li>\n<li><a href=\"plotMapProjectionType.html\">plotMapProjection</a></li>\n<li><a href=\"plotSymbolType.html\">plotSymbol</a></li>\n<li><a href=\"podRightSideType.html\">podRightSide</a></li>\n<li><a href=\"sggRightSideType.html\">sggRightSide</a></li>\n<li><a href=\"slrParametrizationType.html\">slrParametrization</a></li>\n<li><a href=\"slrProcessingStepType.html\">slrProcessingStep</a></li>\n<li><a href=\"slrSatelliteGeneratorType.html\">slrSatelliteGenerator</a></li>\n<li><a href=\"slrStationGeneratorType.html\">slrStationGenerator</a></li>\n<li><a href=\"sphericalHarmonicsFilterType.html\">sphericalHarmonicsFilter</a></li>\n<li><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></li>\n<li><a href=\"sstRightSideType.html\">sstRightSide</a></li>\n<li><a href=\"thermosphereType.html\">thermosphere</a></li>\n<li><a href=\"tidesType.html\">tides</a></li>\n<li><a href=\"timeSeriesType.html\">timeSeries</a></li>\n<li><a href=\"troposphereType.html\">troposphere</a></li>\n</ul></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/conditionType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - conditionType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"conditionType\">Condition</h1><p>\nTest for conditions. See <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">Loop and conditions</a> for usage.\n</p>\n\n<h2>FileExist</h2><p>\nCheck for a file or directory existing.\nSupports wildcards * for any number of characters and ? for exactly one character.\nFiles smaller than <strong class=\"groops-config-element\">minSize</strong> are treated as non-existent.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">file</div></div></td><td>filename</td><td>supports wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minimumSize</div></div></td><td>uint</td><td>minimum file size in byte.</td></tr>\n</table>\n\n<h2>Command</h2><p>\nExecute command and check success.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">command</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">silently</div></div></td><td>boolean</td><td>without showing the output.</td></tr>\n</table>\n\n<h2 id=\"expression\">Expression</h2><p>\nEvaluate expression.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">expression</div></div></td><td>expression</td><td></td></tr>\n</table>\n\n<h2>Matrix</h2><p>\nEvaluate elements of a <a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrix</a> based on an expression.\nIf <strong class=\"groops-config-element\">all</strong>=<code>yes</code>, all elements of the matrix must evaluate to true\nfor the condition to be fulfilled, otherwise any element evaluating to true is sufficient.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td>expression is evaluated for each element of resulting matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">expression</div></div></td><td>expression</td><td>(variable: data) evaluated for each element</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">all</div></div></td><td>boolean</td><td>all (=yes)/any (=no) elements must evaluate to true</td></tr>\n</table>\n\n<h2>MatrixEmpty</h2><p>\nEvaluate if <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> (or <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument</a>) file is empty/has zero size.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>StringContainsPattern</h2><p>\nDetermines if there is a match between a <strong class=\"groops-config-element\">pattern</strong> and some subsequence in a <strong class=\"groops-config-element\">string</strong>.\nSupports wildcards * for any number of characters and ? for exactly one character.\nIf <strong class=\"groops-config-element\">isRegularExpression</strong> is set, <strong class=\"groops-config-element\">pattern</strong> is interpreted as a\nregular expression instead. In any case, the <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>\nis applied beforehand.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">string</div></div></td><td>filename</td><td>should contain a {variable}</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">pattern</div></div></td><td>filename</td><td>supports wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">isRegularExpression</div></div></td><td>boolean</td><td>pattern is  a regular expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">caseSensitive</div></div></td><td>boolean</td><td>treat lower and upper case as distinct</td></tr>\n</table>\n\n<h2>StringMatchPattern</h2><p>\nDetermines if a <strong class=\"groops-config-element\">pattern</strong> matches the entire <strong class=\"groops-config-element\">string</strong>.\nSupports wildcards * for any number of characters and ? for exactly one character.\nIf <strong class=\"groops-config-element\">isRegularExpression</strong> is set, <strong class=\"groops-config-element\">pattern</strong> is interpreted as a\nregular expression instead. In any case, the <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>\nis applied beforehand.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">string</div></div></td><td>filename</td><td>should contain a {variable}</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">pattern</div></div></td><td>filename</td><td>supports wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">isRegularExpression</div></div></td><td>boolean</td><td>pattern is  a regular expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">caseSensitive</div></div></td><td>boolean</td><td>treat lower and upper case as distinct</td></tr>\n</table>\n\n<h2>And</h2><p>\nAll conditions must be met (with short-circuit evaluation).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td></td></tr>\n</table>\n\n<h2>Or</h2><p>\nOne of the conditions must be met (with short-circuit evaluation).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td></td></tr>\n</table>\n\n<h2>Not</h2><p>\nThe result of the condition is inverted.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.gnssNetwork.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GNSS satellite orbit determination and station network analysis</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.gnssNetwork\">GNSS satellite orbit determination and station network analysis</h1><p>\nThis cookbook chapter describes an example of global GNSS processing as done by analysis centers of the\nInternational GNSS Service (IGS). Resulting products usually comprise:\n<ul>\n\n  <li>Satellite orbits, clocks, and signal biases\n  </li><li>\nStation positions, clocks, signal biases, and troposphere estimates\n  </li><li>\nEarth orientation parameters\n</li></ul>\n</p><p>Scientific details about the underlying processing approach and the applied parametrizations, models, and corrections\ncan be found in a doctoral thesis available under DOI <a href=\"https://doi.org/10.3217/978-3-85125-885-1\">10.3217/978-3-85125-885-1</a>.</p><p>An example scenario for this task is available at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip</a>.\nIt includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (data folder or zipped archive).\nThe scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.</p><p><em>Note: Global GNSS processing can become very computationally intensive. Depending on the number of satellites\nand stations, the observation and processing sampling, and parametrizations it can quickly exceed the capabilities\nof a normal desktop computer and may require computer clusters or number crunchers (see section</em>\n<a class=\"groops-ref\" href=\"general.parallelization.html\">Parallelization</a><em>).</em></p><p><h2 id=\"metadata\">Data preparation</h2><p>\nMost of the required metadata files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>.\nThese files are regularly updated.</p><p>Data that has to be gathered from other sources comprises:\n<ul>\n\n  <li><b>Receiver observations</b>: GNSS measurements converted from RINEX format (see <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>).\n  </li><li>\n<b>Approximate orbits</b>: broadcast or precise orbits in CRF for orbit integration (see <a class=\"groops-program\" href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a> or <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>).\n  </li><li>\n<b>Approximate clocks</b>: broadcast or precise clocks (see <a class=\"groops-program\" href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a> or <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a>)\n</li></ul>\n\nReceiver observations, broadcast ephemerides, and precise satellite orbits and clocks can be downloaded from the\n<a href=\"https://igs.org/data-products-overview/\">IGS Data Centers</a>.\nGPS, GLONASS, and Galileo orbits and clocks for the period 1994-2020 are also available as part of\n<a href=\"https://doi.org/10.3217/dataset-4528-0723-0867\">Graz University of Technology's contribution to IGS repro3</a>.</p><p>The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\">example scenario</a> includes a small set of this data.\nThe script <code>010groopsConvert.xml</code> can be used to convert these external formats into GROOPS formats.</p><p>Prepare a <a class=\"groops-file\" href=\"fileFormat_stringTable.html\">station list file</a> that contains the stations to be processed.\nEach line can contain more than one station. The first station in each line that has data available is used for the processing.\nIf your network contains more than 60-70 stations, it is recommended to start processing with a core network (see <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#advanced\">Advanced</a>).\nIn this case, define an additional <a class=\"groops-file\" href=\"fileFormat_stringTable.html\">core station list file</a> that can also have multiple stations per line.</p><p><h2 id=\"orbitIntegration\">Preprocessing: Orbit integration</h2><p>\nNumerical integration of the satellite orbits is the first step in global GNSS processing.\nDynamic orbits are integrated based on <a class=\"groops-class\" href=\"forcesType.html\">force models</a> and then fitted to the approximate orbits\nby estimating their initial state and additional empirical parameters for solar radiation pressure to improve the orbit fit.\nThe resulting <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">variational equations</a> file contains the integrated orbit, derivatives\nwith respect to the satellite state vector, attitude, Earth rotation and satellite model.</p><p>Orbit preprocessing is covered by the script <code>020groopsGnssPreprocessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\">example scenario</a>.</p><p>It is recommended to perform the steps below in a <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">loop</a> over all\nsatellites/PRNs using <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a>. To get the relation between <code>{prn}</code> and <code>{svn}</code> setup\nan additional <a class=\"groops-class\" href=\"loopType.html#platformEquipment\">loop:platformEquipment</a> inside\n<a class=\"groops-class\" href=\"loopType.html#loop\">loop:loop</a> with\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfilePlatform</a>: the old <strong class=\"groops-config-element\">inputfileTransmitterInfo</strong>\n  </li><li>\n<strong class=\"groops-config-element\">equipmentType</strong>         = <code>gnssAntenna</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopName</strong>      = <code>block</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopSerial</strong>    = <code>svn</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopTimeStart</strong> = <code>svnTimeStart</code>\n  </li><li>\n<strong class=\"groops-config-element\">variableLoopTimeEnd</strong>   = <code>svnTimeEnd</code>\n  </li><li>\n<a class=\"groops-class\" href=\"conditionType.html#expression\">condition:expression</a>\n  <ul>\n\n    </li><li>\n<strong class=\"groops-config-element\">expression</strong> = <code>(svnTimeStart &lt;= loopTime) && (loopTime &lt; svnTimeEnd)</code>\n  </li></ul>\n\n</ul>\nThis second loop should perform only one step. The following programs are looped over all <code>{prn}</code>:\n<ul>\n\n  <li><a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>: resample approximate orbits from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">data preparation</a> to target sampling (e.g., 1 minute) by defining a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> based on a <strong class=\"groops-config-element\">method:polynomial</strong> (<strong class=\"groops-config-element\">polynomialDegree</strong>=<code>7</code>, <strong class=\"groops-config-element\">maxDataPointRange</strong>=<code>7200</code>, <strong class=\"groops-config-element\">maxExtrapolationDistance</strong>=<code>900</code>).\n  </li><li>\n<a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>: add velocity via running polynomial (<strong class=\"groops-config-element\">polynomialDegree</strong>=<code>2</code>) derivation (needed for attitude computation)\n  </li><li>\n<a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>\n  </li><li>\n<a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>:\n        <ul>\n\n          </li><li>\n<a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">inputfileSatelliteModel</a>=<code>{groopsDataDir}/gnss/transmitter/satelliteModel/satelliteModel_boxWing.{svn}.xml</code>\n          </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: the resampled approximate orbit from <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>\n          </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>: the attitude file from <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>\n          </li><li>\n<strong class=\"groops-config-element\">forces</strong>: see below\n          </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gradientfield:potentialCoefficients</a>: a static gravity field (e.g. GOCO06s) with <strong class=\"groops-config-element\">maxDegree</strong>=<code>4</code>.\n        </li></ul>\n\n  <li><a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>: fit the integrated orbit (<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) to the approximate orbit (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>) by least squares adjustment.\n        Add <a class=\"groops-class\" href=\"parametrizationAccelerationType.html#gnssSolarRadiation\">parametrizationAcceleration:gnssSolarRadiation</a>\n        and select the <a href=\"https://doi.org/10.1007/s00190-015-0814-4\">ECOM2</a> parameters to be estimated.\n</li></ul>\n</p><p>Force models usually include:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:\n        static gravity field (e.g. GOCO06s)\n  </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#trend\">gravityfield:trend</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:\n          trend component of time-variable gravity field (e.g. GOCO06s)\n  </li></ul>\n\n  <li><a class=\"groops-class\" href=\"gravityfieldType.html#oscillation\">gravityfield:oscillation</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldCos:potentialCoefficients</a>:\n          annual cosine component of time-variable gravity field (e.g. GOCO06s)\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldSin:potentialCoefficients</a>:\n          annual sine component of time-variable gravity field (e.g. GOCO06s)\n  </li></ul>\n\n  <li><a class=\"groops-class\" href=\"tidesType.html#astronomicalTide\">tides:astronomicalTide</a>: astronomical tides (e.g. based on JPL ephemeris)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#earthTide\">tides:earthTide</a>: Earth tide (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">tides:doodsonHarmonicTide</a>: ocean tides (e.g. FES 2014b)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#poleTide\">tides:poleTide</a>: pole tides (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">tides:poleOceanTide</a>: ocean pole tides (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"miscAccelerationsType.html#solarRadiationPressure\">miscAccelerations:solarRadiationPressure</a>:\n        solar radiation pressure (box-wing model)\n  </li><li>\n<a class=\"groops-class\" href=\"miscAccelerationsType.html#albedo\">miscAccelerations:albedo</a>: Earth radiation pressure (albedo model)\n  </li><li>\n<a class=\"groops-class\" href=\"miscAccelerationsType.html#antennaThrust\">miscAccelerations:antennaThrust</a>:\n        antenna thrust (e.g. from IGS metadata SINEX file)\n  </li><li>\n<a class=\"groops-class\" href=\"miscAccelerationsType.html#relativisticEffect\">miscAccelerations:relativisticEffect</a>:\n        relativistic effects (IERS conventions)\n</li></ul>\n\nFor the spherical harmonics expansions a <strong class=\"groops-config-element\">maxDegree</strong>=<code>60</code> is more than enough.</p><p>The result of the preprocessing should be a <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">variational equations file</a>,\na <a class=\"groops-file\" href=\"fileFormat_instrument.html\">reduced dynamic orbit file</a> from <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>\nand an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">attitude file</a> from <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> for each satellite.</p><p><h2 id=\"processing\">GNSS processing</h2><p>\nThe script <code>030groopsGnssProcessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\">example scenario</a>\nimplements the following steps and settings.</p><p>These are the settings for <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. If not otherwise stated use the default values.</p><p>The first step is setting the processing sampling, in this example it is 30 seconds.\nThe processing interval usually is a single 24-hour day, therefore define\n<a class=\"groops-class\" href=\"timeSeriesType.html#uniformSampling\">timeSeries:uniformSampling</a> with <strong class=\"groops-config-element\">timeStart</strong>=<code>&lt;mjd></code>,\n<strong class=\"groops-config-element\">timeEnd</strong>=<code>&lt;mjd>+1</code>, <strong class=\"groops-config-element\">sampling</strong>=<code>30/86400</code> (processing sampling).</p><p>Add the appropriate <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html#gnss\">transmitters:gnss</a> (e.g. GPS, GLONASS, and Galileo)\nand provide the required files:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> from <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#orbitIntegration\">preprocessing</a>\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a> from <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#orbitIntegration\">preprocessing</a>\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a> from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">data preparation</a>\n</li></ul>\n</p><p>The following settings are needed in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>:\n<ul>\n\n   <li><a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStationList</a>: list of all stations to be processed\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: The converted RINEX observation files.\n   </li><li>\n<a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>: Use the settings described in <a class=\"groops-ref\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>.\n   </li><li>\n<a class=\"groops-class\" href=\"gnssType.html\">excludeType</a>: Signals you might want to exclude are <code>C*?G</code> (old unknown GPS code observations), <code>*3*R</code> (GLONASS G3 freq.), <code>*6*E</code> (Galileo E6 freq.).\n</li></ul>\n</p><p>Add the following <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>\nand define the <strong class=\"groops-config-element\">outputfiles</strong> you are interested in inside each of them:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">ionosphereSTEC</a>: add a constraint of <strong class=\"groops-config-element\">sigmaSTEC</strong>=<code>40</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">ionosphereMap</a>: add <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">temporal:splines</a>\n        with linear (<strong class=\"groops-config-element\">degree</strong>=<code>1</code>) 2-hourly splines\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">clocks</a>: optionally change <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitterZeroMeans</a> to <a class=\"groops-class\" href=\"platformSelectorType.html#wildcard\">wildcard</a> with <strong class=\"groops-config-element\">name</strong>=<code>G*</code> to align clocks to mean over GPS (instead of all) satellites\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">signalBiases</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">ambiguities</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">codeBiases</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">tecBiases</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#temporalBias\">temporalBias</a>: time-variable GPS L5 phase bias with <a class=\"groops-class\" href=\"gnssType.html\">type</a>=<code>L5*G</code>\n        and <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">parametrizationTemporal:splines</a> with degree 3 and hourly nodes.\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#staticPositions\">staticPositions</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#troposphere\">troposphere</a>: select <a class=\"groops-class\" href=\"troposphereType.html#viennaMapping\">troposphere:viennaMapping</a>\n        with the appropriate vmf3grid file. Add <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereWetEstimation:splines</a>\n        with linear (<strong class=\"groops-config-element\">degree</strong>=<code>1</code>) 2-hourly splines\n        and <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereGradientEstimation:splines</a> with linear daily splines.\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#transmitterDynamicOrbits\">transmitterDynamicOrbit</a>:\n        provide <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>=<code>preprocessing/variational.{prn}.dat</code>\n        from the preprocessing step.\n        Add <a class=\"groops-class\" href=\"parametrizationAccelerationType.html#gnssSolarRadiation\">parametrizationAcceleration:gnssSolarRadiation</a> and\n        <a class=\"groops-class\" href=\"timeSeriesType.html#irregular\">stochasticPulse:irregular</a> parameter at center of day to further improve orbit fit.\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#earthRotation\">earthRotation</a>\n        <ul>\n\n          </li><li>\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html#constant\">estimatePole:constant</a>: polar motion\n          </li><li>\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">estimatePole:trend</a> polar motion rate\n                (at center of day with <strong class=\"groops-config-element\">timeStep</strong>=<code>1</code>)\n          </li><li>\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">estimateUT1:trend</a>: length of day (at center of day with\n                <strong class=\"groops-config-element\">timeStep</strong>=<code>-1</code> to match IGS sign convention)\n        </li></ul>\n\n    <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: loose constraint on GPS L5 phase biases,\n        <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>signalBias.L5*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>5</code> meters, and <strong class=\"groops-config-element\">relativeToApriori</strong>=<code>yes</code>\n    </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: loose constraint troposphere estimates,\n        <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>troposphere*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>5</code> meters, and <strong class=\"groops-config-element\">relativeToApriori</strong>=<code>yes</code>\n    </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: constraint on stochastic pulses,\n        <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>stochasticPulse*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>0.1</code> micrometers/second.\n</li></ul>\n</p><p>Finally, define the <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>.\nThis can be overwhelming at first, but offers a lot of flexibility.\nThe example script uses a 5-minute processing sampling with subsequent clock densification to 30 seconds.</p><p><ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>10</code> to reduce sampling to 5 minutes.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:\n            disable <code>constraint.STEC</code>, <code>*VTEC</code>, <code>*.tecBiases</code> as the ionosphere parameters are estimated in the final steps only.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:\n            enable <code>*</code> (all) parameters\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>: final iterations (with 5-minute sampling) and ionosphere parameters\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#group\">group</a>: clock densification to 30-second sampling\n      <ul>\n\n            </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> to set full 30-second sampling\n            </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:\n            disable <code>*</code> (all) parameters and reenable <code>*.clock*</code> and <code>*.STEC</code> parameters\n            </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>\n            </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>: with <strong class=\"groops-config-element\">suffix</strong>=<code>30s</code> to write 30-second clock files\n      </li></ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>: write the final results\n</li></ul>\n</p><p>With some additional steps, the full 30-second sampling can be used to estimate all parameters (not only the clocks).\nThese steps are disabled in the example script, as they require at least 16 GB of system memory.\nIn this case, it is not necessary to separately write the 30-second clock files as listed above.</p><p><ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> to set full 30-second sampling\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">selectNormalsBlockStructure</a>: As the system of normal\n      equations can be very large, the memory consumption might be reduced with <strong class=\"groops-config-element\">keepEpochNormalsinMemory</strong>=<code>no</code>.\n      In this case the epoch parameters are directly eliminated during the accumulation and reconstructed in the solving step.\n      This might lead to longer computation times.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>2</code>: final iterations with full sampling\n</li></ul>\n</p><p><h2 id=\"advanced\">Advanced: Processing large station networks</h2><p></p><p>Processing large station networks requires some additional steps to keep the computational load to a reasonable degree.\nThe general processing strategy is to first process a well-distributed subset of stations (i.e. a core network)\nto get good estimates of all satellite parameters, which then enables integer ambiguity resolution (IAR). Once\nthe ambiguities of the core network are resolved and stable estimates for satellite phase biases are available, all\nother (non-core) stations can be processed individually (including IAR) while keeping the satellite parameters fixed.\nAt last, all stations can be processed together with all satellite parameters and ionosphere parameters.</p><p>Let's start with the <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a> of the core network:\n<ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a> with <a class=\"groops-class\" href=\"platformSelectorType.html#file\">selectReceivers:file</a>\n      using the core network station list file from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">data preparation</a> as <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStringTable</a>.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>10</code> to reduce sampling to 5 minutes.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:\n            disable <code>constraint.STEC</code>, <code>*VTEC</code>, <code>*.tecBiases</code> as the ionosphere parameters are estimated in the final steps only.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>: final iterations (with 5-minute sampling)\n</li></ul>\n</p><p>Now all other (non-core) stations can be processed separately:\n<ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">forEachReceiverSeparately</a>:\n            with <a class=\"groops-class\" href=\"platformSelectorType.html#file\">selectReceivers:file</a> inside <a class=\"groops-class\" href=\"platformSelectorType.html#exclude\">selectReceivers:exclude</a>\n            using the station list from the core network above to process all non-core stations individually with fixed transmitter parameters\n      <ul>\n\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">processingStep:resolveAmbiguities</a>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>\n      </li></ul>\n\n</ul></p><p>Next all stations are processed together with all parameters:\n<ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a>: with <a class=\"groops-class\" href=\"platformSelectorType.html#all\">selectReceivers:all</a>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> to set full 30-second sampling\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#group\">group</a>: clock densification to 30-second sampling\n      <ul>\n\n            </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:\n            disable <code>*</code> (all) parameters and reenable <code>*.clock*</code> and <code>*.STEC</code> parameters\n            </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>\n      </li></ul>\n\n      <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>: enable <code>*</code> (all) parameters.\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">selectNormalsBlockStructure</a>: with <strong class=\"groops-config-element\">keepEpochNormalsinMemory</strong>=<code>no</code>\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>: final iterations with full sampling and all parameters\n      </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>: write the final results\n</li></ul>\n</p><p>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.gnssPpp.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GNSS precise point positioning (PPP)</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.gnssPpp\">GNSS precise point positioning (PPP)</h1><p>\nThis cookbook chapter describes an example of GNSS precise point positioning (PPP) for a ground station using GPS, GLONASS, and Galileo.\nFor information on how to generate the GNSS products (orbits, clocks, signal biases, etc.) required for PPP,\nsee the cookbook <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>.</p><p>Scientific details about the underlying processing approach and the applied parametrizations, models, and corrections\ncan be found in a doctoral thesis available under DOI <a href=\"https://doi.org/10.3217/978-3-85125-885-1\">10.3217/978-3-85125-885-1</a>.</p><p>An example scenario for this task is available at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip</a>.\nIt includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (data folder or zipped archive).\nThe scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.</p><p><h2 id=\"metadata\">Data preparation</h2><p>\nMost of the required metadata files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>.\nThese files are regularly updated.</p><p>Data that has to be gathered from other sources comprises:\n<ul>\n\n  <li><b>Receiver observations</b>: GNSS measurements converted from RINEX format (see <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>)\n  </li><li>\n<b>Precise orbits</b>: precise orbits in CRF for orbit integration (see <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>)\n  </li><li>\n<b>Precise clocks</b>: precise clocks (see <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a>)\n  </li><li>\n<b>Attitude</b>: rotation from body frame to CRF (see <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> or <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>)\n  </li><li>\n<b>Signal biases</b>: code (and phase) biases (see <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>)\n</li></ul>\n\nReceiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the\n<a href=\"https://igs.org/data-products-overview/\">IGS Data Centers</a>.\nGPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of\n<a href=\"https://doi.org/10.3217/dataset-4528-0723-0867\">Graz University of Technology's contribution to IGS repro3</a>.</p><p>The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip\">example scenario</a> includes a small set of this data.\nThe script <code>010groopsConvert.xml</code> can be used to convert these external formats into GROOPS formats.</p><p>Prepare a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">station list file</a> that contains the stations (one per line) to be processed.</p><p><h2 id=\"processing\">Processing of a ground station</h2><p>\nThe script <code>02groopsGnssProcessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip\">example scenario</a>\nimplements the following steps and settings.</p><p>These are the settings for <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. If not otherwise stated use the default values.</p><p>The first step is setting the processing sampling, in this example it is 30 seconds.\nThe processing interval usually is a single 24-hour day,\n<a class=\"groops-class\" href=\"timeSeriesType.html#uniformSampling\">timeSeries:uniformSampling</a> with <strong class=\"groops-config-element\">timeStart</strong>=<code>&lt;mjd></code>,\n<strong class=\"groops-config-element\">timeEnd</strong>=<code>&lt;mjd>+1</code>, <strong class=\"groops-config-element\">sampling</strong>=<code>30/86400</code> (processing sampling).</p><p>Add the appropriate <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html#gnss\">transmitters:gnss</a> (e.g. GPS, GLONASS, and Galileo)\nand provide the required files (from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">Data preparation</a>):\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a>\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a>\n</li></ul>\n</p><p>The following settings are needed in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>:\n<ul>\n\n   <li><a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileStationList</a>: list of all stations to be processed\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: The converted RINEX observation file.\n   </li><li>\n<a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>: Use the settings described in <a class=\"groops-ref\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>.\n   </li><li>\n<a class=\"groops-class\" href=\"gnssType.html\">useType</a>: We recommend to explicitly specify the signals to be processed\n            and to make sure that at least transmitter code biases are provided for each of them, e.g. <code>C1CG</code>,\n            <code>C1WG</code>, <code>C2WG</code>, <code>L1*G</code>, <code>L2*G</code>, ...).\n   </li><li>\n<a class=\"groops-class\" href=\"gnssType.html\">excludeType</a>: Signals you might want to exclude are <code>L5*G</code> (GPS L5 phase due to time-variable bias on block IIF satellites), <code>*3*R</code> (GLONASS G3 freq.), <code>*6*E</code> (Galileo E6 freq.)\n</li></ul>\n</p><p>Add the following <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>\nand define the <strong class=\"groops-config-element\">outputfiles</strong> you are interested in inside each of them:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">ionosphereSTEC</a>: add a constraint of <strong class=\"groops-config-element\">sigmaSTEC</strong>=<code>40</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">ionosphereVTEC</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">clocks</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">signalBiases</a>: provide <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBiasTransmitter</a> from\n        <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">Data preparation</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">ambiguities</a>: if precise transmitter phase biases are available you can delete <a class=\"groops-class\" href=\"platformSelectorType.html\">estimateTransmitterPhaseBiases</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">codeBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">tecBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#kinematicPositions\">kinematicPositions</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#troposphere\">troposphere</a>: select <a class=\"groops-class\" href=\"troposphereType.html#viennaMapping\">troposphere:viennaMapping</a>\n        with the appropriate vmf3grid file. Add <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereWetEstimation:splines</a>\n        with linear (<strong class=\"groops-config-element\">degree</strong>=<code>1</code>) 2-hourly splines\n        and <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereGradientEstimation:splines</a> with linear daily splines.\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: loose constraint troposphere estimates,\n        <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>troposphere*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>5</code>, and <strong class=\"groops-config-element\">relativeToApriori</strong>=<code>yes</code>\n</li></ul>\n</p><p>Add the following <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>8</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>2</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>\n</li></ul>\n</p><p>When processing multiple stations at the same time, moving <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>\nand <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a> into the processing step\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">forEachReceiverSeparately</a> sets up and solves\nthe normal equations independently for each station.</p><p>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.gravityFieldGrace.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GRACE gravity field recovery</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.gravityFieldGrace\">GRACE gravity field recovery</h1><p>\nThis cookbook chapter describes an example of estimating a gravity field solution using GRACE observation\ndata. For the respective month a set of spherical harmonic coefficients up to a maximum degree is determined.\nAn example scenario for this task can be found at\n<a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGraceGravityfieldRecovery.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGraceGravityfieldRecovery.zip</a>\nincluding the required GROOPS scripts and data sets for the gravity field recovery process.\nThe provided scenario consists of a slightly simplified example as compared to the operational one.\nThe background models are provided at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data/\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/data/</a>.</p><p>\n<h2 id=\"backgroundModels\">Background models</h2><p>\nThe following background models were used during the data processing:\n<ul>\n\n  <li><b>Earth rotation</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a> \n  </li><li>\n<b>Moon, sun and planets ephemerides</b>: <a href=\"https://ipnpr.jpl.nasa.gov/progress_report/42-196/196C.pdf\">JPL DE432</a> \n  </li><li>\n<b>Earth tide</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a> \n  </li><li>\n<b>Ocean tide</b>: <a href=\"https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes/description-fes2014.html\">FES2014b</a> \n  </li><li>\n<b>Pole tide</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a> \n  </li><li>\n<b>Ocean pole tide</b>: <a href=\"https://doi.org/10.1029/2001JC001224\">Desai 2004</a> \n  </li><li>\n<b>Atmospheric tides</b>: <a href=\"https://doi.org/10.1029/2022MS003193\">TiME22</a> \n  </li><li>\n<b>Atmosphere and Ocean Dealiasing</b>: <a href=\"https://doi.org/10.1093/gji/ggx302\">AOD1B RL06</a> \n  </li><li>\n<b>Sub-monthly continental hydrology</b>: <a href=\"https://doi.org/10.2312/GFZ.b103-08095\">LSDM (ESMGFZ)</a> \n  </li><li>\n<b>Relativistic corrections</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a> \n</li></ul>\n\nThese models were reduced during the analysis process and are not present in the solution.\nThe <a href=\"https://doi.org/10.5194/essd-13-99-2021\">GOCO06s</a>\nmodel was used as the static gravity field as well as for the trend component and annual oscillation.\nIn the script <code>000groopsBackgroundModels.xml</code> a monthly mean of the GOCO06s including the time-variable components is determined\nin form of time splines using <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>. This model is later added back to the final gravity solution.</p><p><h2 id=\"metadata\">Instrument data preparation</h2><p>\nThe ITSG gravity field solutions are computed from the official GRACE L1B <a href=\"https://doi.org/10.5067/GRJPL-L1B03\">JPL (2018)</a>\nand GRACE-FO L1B <a href=\"https://doi.org/10.5067/GFL1B-ASJ04\">JPL (2019)</a> observation data. The data sets for this example are provided\nin GROOPS file format in the scenario folder.</p><p>The satellite-to-satellite-tracking (SST) data consists of:\n<ul>\n\n  <li><b>K-band range rates</b>\n  </li><li>\n<b>Light time correction</b>\n  </li><li>\n<b>Antenna offset corrections</b>\n</li></ul>\n</p><p>Additional observation data required for the processing comprises:\n<ul>\n\n  <li><b>Star camera observations</b>\n  </li><li>\n<b>Accelerometer data</b>\n  </li><li>\n<b>Approximate orbits</b> \n  </li><li>\n<b>Thruster data</b>\n</li></ul>\n</p><p>The determination of\n<ul>\n\n  <li><b>Kinematic orbits</b>\n  </li><li>\n<b>3x3 epoch covariances</b>\n</li></ul>\n\nis depicted in <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a>.\nThese data sets are also provided in the scenario folder.</p><p>Data preparation is handled in the script <code>010groopsInstruments.xml</code>. The approximate orbits (initial dynamic orbits)\nof the satellites, the star camera observations, the accelerometer data and the thruster data are resampled with a 5s sampling\nand small gaps in the data are filled using <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>. Gross outliers are removed using <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a>\nand the data is synchronized using  <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p>The approximate orbits are later used as a priori information for the dynamic orbit integration.\nIn addition to the observed orientation of the spacecrafts (star camera observations),\nthe nominal orientation is computed using <a class=\"groops-program\" href=\"SimulateStarCameraGrace.html\">SimulateStarCameraGrace</a>. The difference between\nobserved and simulated orientation is determined using <a class=\"groops-program\" href=\"InstrumentStarCameraMultiply.html\">InstrumentStarCameraMultiply</a>\nand is employed in the outlier detection.</p><p>The accelerometer data is initially calibrated by estimating a bias using\n<a class=\"groops-program\" href=\"InstrumentAccelerometerEstimateBiasScale.html\">InstrumentAccelerometerEstimateBiasScale</a> with respect to simulated data created\nwith <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>. For simulating accelerometer data a satellite model\nimplying the satellite's mass and surfaces is required. Such a model can be created with\n<a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a>. Models for the GRACE and GRACE-FO satellites are also provided\nat <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data/satelliteModel/\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/data/satelliteModel/</a>. Non-gravitational forces\ncomprising atmospheric drag, solar radiation pressure and albedo have to be modeled when simulating\nthe accelerometer data. The acceleration bias parameters are determined as degree 3 time splines\nwith 6h nodes. When determining these parameters the thruster events are excluded from the estimation.</p><p>The SST observations, the light time corrections and the antenna center corrections are synchronized\nwith a 5s sampling together with simulated SST data created with <a class=\"groops-program\" href=\"SimulateSatelliteTracking.html\">SimulateSatelliteTracking</a>.\nSimulated data is used for the outlier detection of the original SST observations.</p><p>The sampling of the kinematic orbits is reduced to 60s using <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a> and\nan outlier detection is performed using the approximate dynamic orbits.</p><p>The approximate orbits, the star camera observations and the accelerometer data are divided into 24h arcs\n(variational arcs). The kinematic orbits, its 3x3 epoch covariances, KBR observations,\nlight time corrections, antenna center corrections and star camera observations are divided into 3h arcs\nper day (short arcs). Additionally the approximate orbits and the star camera observations are also\nsynchronized to short arcs.</p><p>Further information on instrument data preparation can be found in\n<a class=\"groops-ref\" href=\"cookbook.instrument.html\">Instrument data handling</a>.</p><p><h2 id=\"variational\">Variational equations</h2><p>\nIn this processing step dynamic orbits are computed for a complete 24h orbit arc by integrating\nthe forces acting on the GRACE/GRACE-FO satellites. Additionally, the state transition matrix is set up.\nThe dynamic orbits are then fitted to kinematic orbits and SST observations in a least squares adjustment\nby co-estimating additional accelerometer calibration parameters together with the initial state vector.\nThe newly estimated parameters are then used to re-estimate the dynamic orbits and setting up the new\nstate transition matrix.</p><p>The script <code>020groopsVariational.xml</code> in the scenario folder implements the required processing steps.\nTime splines from a time-variable gravity field are estimated using <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>.\nIn this step the static gravity field (GOCO06s) is combined with the following time-variable components:\n<ul>\n\n    <li><a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:\n    static gravity field\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#trend\">gravityfield:trend</a>\n    <ul>\n\n        </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:\n      trend component of gravity field\n    </li></ul>\n\n    <li><a class=\"groops-class\" href=\"gravityfieldType.html#oscillation\">gravityfield:oscillation</a>\n    <ul>\n\n        </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldCos:potentialCoefficients</a>:\n      annual cosine component of gravity field\n        </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldSin:potentialCoefficients</a>:\n      annual sine component of gravity field\n    </li></ul>\n\n    <li><a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>: atmosphere and ocean dealiasing (AOD1B RL06)\n    </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: ocean tides (FES2014b)\n    </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: atmospheric tides (TiME22)\n    </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#poleTide\">tides:poleTide</a>: pole tides (IERS 2010)\n    </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">tides:poleOceanTide</a>: ocean pole tides (IERS 2010)\n</li></ul>\n\n<strong class=\"groops-config-element\">maxDegree</strong>=<code>220</code> and <strong class=\"groops-config-element\">sampling</strong>=<code>10/1440</code> is sufficient.</p><p>In <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a> the <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">variational equations</a>\ncomprising the integrated orbit together with the state transition matrix are stored in\n<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">outputfileVariational</a>.</p><p>This program has to be executed for both GRACE or GRACE-FO satellites and it is recommended\nto use <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a>.\n<ul>\n\n    <li><a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">inputfileSatelliteModel</a>: satellite model from <code>020groopsInstruments.xml</code>\n    </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: the approximate orbits from <code>020groopsInstruments.xml</code>\n    </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>: the attitude file from <code>020groopsInstruments.xml</code>\n    </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a>: the accelerometer data from\n    <code>020groopsInstruments.xml</code>\n    </li><li>\n<strong class=\"groops-config-element\">forces</strong>: see below\n    </li><li>\n<a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a>: JPL DE432\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gradientfield:potentialCoefficients</a>: a static gravity field (GOCO06s) with <strong class=\"groops-config-element\">maxDegree</strong>=<code>10</code> is more than sufficient.\n</li></ul>\n</p><p>The <a class=\"groops-class\" href=\"forcesType.html\">force models</a> include:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>:\n        the previously estimated time-variable gravity field\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#astronomicalTide\">tides:astronomicalTide</a>: astronomical tides (based on JPL DE432 ephemerides)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#earthTide\">tides:earthTide</a>: Earth tide (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"miscAccelerationsType.html#relativisticEffect\">miscAccelerations:relativisticEffect</a>:\n        relativistic effects (IERS conventions)\n</li></ul>\n</p><p>In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> the integrated orbit\n(<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) is fitted to the kinematic orbit\n(<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>) by least squares adjustment. The additional accelerometer\ncalibration parameters can be defined by\n<ul>\n\n  <li><a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>: accelerometer scale factor (once per day)\n  </li><li>\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>: accelerometer bias (time spline with 6h nodes)\n</li></ul>\n</p><p>The observation equations (parameter sensitivity matrix) are computed by integration of the variational\nequations (<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) using a polynomial with\n<strong class=\"groops-config-element\">integrationDegree</strong>=<code>7</code>. <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> has to be\nexecuted per satellite.</p><p><a class=\"groops-program\" href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a> fits two dynamic orbits\n<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1/2</a> to the SST observations and the kinematic orbits.\n<ul>\n\n    <li><strong class=\"groops-config-element\">rightHandSide</strong>: input for observation vectors\n        <ul>\n\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: K-band range rate observations\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: light time correction\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: antenna offset corrections\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit1</a>: kinematic orbit of satellite 1\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit2</a>: kinematic orbit of satellite 2\n        </li></ul>\n\n    <li><strong class=\"groops-config-element\">sstType</strong>: rangeRate\n    </li><li>\n<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1</a>: dynamic orbit and integrated state matrix of satellite 1\n    </li><li>\n<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational2</a>: dynamic orbit and integrated state matrix of satellite 2\n    </li><li>\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration1</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>\n    </li><li>\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration2</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>\n    </li><li>\n<strong class=\"groops-config-element\">integrationDegree</strong>: <code>7</code>\n    </li><li>\n<strong class=\"groops-config-element\">interpolationDegree</strong>: <code>7</code>\n    </li><li>\n<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>\n        <ul>\n\n            </li><li>\n<strong class=\"groops-config-element\">sigma</strong>: <code>1</code>\n        </li></ul>\n\n    <li><a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod1</a>\n        <ul>\n\n            </li><li>\n<strong class=\"groops-config-element\">sigma</strong>: 1\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>: 3x3 epoch covariances\n        </li></ul>\n\n    <li><a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod2</a>\n        <ul>\n\n            </li><li>\n<strong class=\"groops-config-element\">sigma</strong>: 1\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>: 3x3 epoch covariances\n        </li></ul>\n\n</ul>\nThe estimated accelerometer calibration parameters from <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>\nand <a class=\"groops-program\" href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a> are determined as corrections and stored\nin <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>. Both correction estimates have to be summed up using\n<a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>.</p><p>The dynamic orbit and the resulting accelerometer calibration parameters are now used to re-integrate\nthe orbit once more using <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a> and introducing\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> as <strong class=\"groops-config-element\">estimatedParameters</strong>.\nThis step usually ensures convergence. If the maximum orbit difference is still not sufficient this step\ncan be repeated again.</p><p><h2 id=\"preprocessing\">Preprocessing</h2><p>\nThe script <code>030groopsPreprocessing.xml</code> implements the following steps and settings.\nThe program <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a> processes SST observations and kinematic orbit data, and\nperforms a complete least squares adjustment for gravity field determination by computing\nthe observations equations. It also allows for an iterative refinement of the stochastic model\nof the observations along with arc-wise variance factors through variance component estimation (VCE).\nForce model parameters (gravitational potential coefficients and accelerometer calibration parameters)\nare computed by integrating the parameter sensitivity matrix from the variational equations.\nParameters describing effects due to the SST observation system and geometry (KBR antenna phase\ncenter variations) are computed using the dynamic orbits as a Taylor point.\nShort time gravity variations can be co-estimated together with the monthly mean gravity field.\nThe autoregressive model sequence constraining the short time parameters is provided in the data folder.\nIt is precomputed from hydrology and nontidal atmospheric and ocean background models.\nSee <a href=\"https://doi.org/10.1007/s00190-019-01314-1\">Kvas 2019</a> for more information about\nthis co-estimation.</p><p><ul>\n\n    <li><a class=\"groops-class\" href=\"observationType.html\">observation</a>: sstVariational\n        <ul>\n\n            </li><li>\n<strong class=\"groops-config-element\">rightHandSide</strong>:\n            <ul>\n\n                </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: KBR range rates\n                </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: light time correction\n                </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: antenna offset corrections\n                </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit1</a>: kinematic orbit of satellite 1\n                </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit2</a>: kinematic orbit of satellite 2\n            </li></ul>\n\n            <li><strong class=\"groops-config-element\">sstType</strong>: rangeRate\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1</a>: dynamic orbit and integrated state matrix of satellite 1\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational2</a>: dynamic orbit and integrated state matrix of satellite 2\n            </li><li>\n<a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a>: JPL DE432\n            </li><li>\n<a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>: spherical harmonics from <strong class=\"groops-config-element\">minDegree</strong>=<code>2</code> to <strong class=\"groops-config-element\">maxDegree</strong>=<code>60</code>\n            </li><li>\n<a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>: high frequency parametrization\n            </li><li>\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration1</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>\n            </li><li>\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration2</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>\n            </li><li>\n<a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>: antenna phase center variations (y and z for both satellites)\n            </li><li>\n<strong class=\"groops-config-element\">integrationDegree</strong>: 7\n            </li><li>\n<strong class=\"groops-config-element\">interpolationDegree</strong>: 7\n        </li></ul>\n\n    <li><a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>\n        <ul>\n\n            </li><li>\n<strong class=\"groops-config-element\">sigma</strong>: <code>1e-7</code>\n            </li><li>\n<strong class=\"groops-config-element\">sampling</strong>: 5 [seconds]\n        </li></ul>\n\n    <li><a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod1/2</a>\n        <ul>\n\n            </li><li>\n<strong class=\"groops-config-element\">sigma</strong>:  <code>2</code>\n            </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>: 3x3 epoch covariances\n            </li><li>\n<strong class=\"groops-config-element\">sampling</strong>: 60 [seconds]\n        </li></ul>\n\n    <li><strong class=\"groops-config-element\">estimateShortTimeVariations</strong>\n        <ul>\n\n            </li><li>\n<a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>: AR models\n            </li><li>\n<a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>: names\n                <ul>\n\n                    </li><li>\n<a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>: parametrizationGravity\n                    <ul>\n\n                        </li><li>\n<a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrization</a>: high frequency parametrization\n                    </li></ul>\n\n                </ul>\n        </ul>\n</ul></p><p><a class=\"groops-program\" href=\"ParameterSelection2IndexVector.html\">ParameterSelection2IndexVector</a> and <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a> with\n<a class=\"groops-class\" href=\"matrixGeneratorType.html#reorder\">matrix:reorder</a> can be used to extract the desired\nspherical harmonic coefficients from <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> and the respective\nstandard deviations from <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a> up to a certain degree.</p><p>In the program <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> the estimated spherical harmonics\ncoefficients are read with\n<a class=\"groops-class\" href=\"gravityfieldType.html#fromParametrization\">gravityfield:fromParametrization</a>.\nThe monthly mean gravity field can be added back by additionally selecting the time splines created\nin <code>000groopsBackgroundModels.xml</code> using\n<a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>. The preprocessing solution\nis saved as a <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">spherical harmonics file</a>.</p><p><h2 id=\"monthlyNormals\">Setting up normal equations</h2><p>\nNormal equations are set up in the script <code>040groopsMonthlyNormals120.xml</code> using\nthe program <a class=\"groops-program\" href=\"NormalsBuildShortTimeStaticLongTime.html\">NormalsBuildShortTimeStaticLongTime</a>. The time intervals which the normal\nequations are divided into are defined in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a>.\nThe normal equations are based on <a class=\"groops-class\" href=\"observationType.html\">observation</a> including the SST data,\nthe kinematic orbits and the variational equations. The parametrization of the gravity field can\nbe set with <a class=\"groops-class\" href=\"parametrizationGravityType.html\">observation:parametrizationGravity</a>\n(e.g. spherical harmonics up to degree and order 120). Accelerometer calibration parameters\nand KBR antenna phase center variations can be parameterized using\n<a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> and\n<a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>.\nWith <strong class=\"groops-config-element\">estimateShortTimeVariations</strong> short time variations of the gravity\nfield can be co-estimated. The parameters selected by\n<a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> (e.g. linear splines with 6h nodes) are\nconstrained by an <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>.\nAdditional temporal variations (e.g. trend and annual oscillation) could be estimated with\n<strong class=\"groops-config-element\">estimateLongTimeVariations</strong>.</p><p><h2 id=\"monhtlySolve\">Solving normal equations</h2><p>\nThe desired spherical harmonic coefficients are determined in the script <code>050groopsMonthlySolve.xml</code>.\n<a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a> accumulates <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a> and solves\nthe total combined system. Variance component estimation is used to determine the relative weighting\nof the individual normals, i.e. the arc-wise variances. The previously computed stochastic model of\nthe observations remains unchanged. The estimated parameter vector (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>),\nthe estimated accuracies (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>) and the full covariance matrix\n(<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovariance</a>) can be saved.\nUsing <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> the final solution can be saved as\na <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">spherical harmonics file</a> by adding back the monthly mean gravity\nfield to the estimated spherical harmonic coefficients.</p><p>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.gravityFieldPod.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Gravity field determination from POD data</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.gravityFieldPod\">Gravity field determination from precise orbit data (POD)</h1><p></p><p>This cookbook chapter describes exemplarily the steps for determining the monthly gravity variations from precise orbit data (POD).</p><p><h2>Step 1: Preperation of data</h2><p></p><p>Following data have to be prepared monthly with an adequate sampling, e.g. 10 s using\n<a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>:\n<ul>\n\n  <li>Precise (kinematic) orbit data\n  </li><li>\n3x3 covariance matrices data\n  </li><li>\nInitial orbit data used for precise orbit determination\n  </li><li>\nStar camera data\n  </li><li>\nAccelerometer data\n</li></ul>\n\nReduced sampling can be achieved by <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a>. If the satellite mission does not provide any required\naccelerometer data, these data can be generated via <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>.</p><p>For satellite missions with less knowledge about the acting forces, it makes sense to consider more than one state vector within an orbit revolution.\nOtherwise the accuracy of the estimated parameters will decrease. This implies that shorter arcs are necessary. The assignment of the kinematic orbit\ndata as well as the 3x3 covariance matrices data to the arcs can be done with <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p><h2>Step 2: Conversion of the background gravity field</h2><p>\n<a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a> converts the static respectively background gravity field into spherical harmonics.</p><p><h2>Step 3: Preprocessing POD</h2><p>\nFor determining the accuracies and weights of the kinematic orbits it is sufficient to make a least-square estimation with only certain parameters, due\nto the fact that some parameters do not influence the estimation of the accuracies and weights.\nThis estimation is done with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>. Additionally, this program determines the temporal correlation of the kinematic orbit positions\nx, y and z. If short arcs are used the setting <a class=\"groops-class\" href=\"observationType.html#podIntegral\">observation:podIntegral</a> shall be used. This setting\nconsiders the frictional forces by means of a macro model as well as the conservative and non-conservative forces.</p><p><h2>Step 4: Solving of normal equations system</h2><p>\n<a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a> sets up the observation equations and summarized them to a normal equations system. The subsequent least-square estimation delivers\nthe parameters surcharges.</p><p><h2>Step 5: Determination of the estimated gravity field parameters</h2><p>\nThe estimated parameters result from the re-addition of the background field, which is done in <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.</p><p><h2>Step 6: Conversion of the gravity field parameters</h2><p>\n<a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> converts the gravity field parameters into spherical harmonics.</p><p>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.instrument.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument data handling</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.instrument\">Instrument data handling</h1><p></p><p>GROOPS provides functions and programs to read/write, preprocess, analyze and visualize uniformly and non-uniformly sampled instrument data.\nThis includes tools for filter design and analysis, re-sampling, smoothing, detrending, and power spectrum estimation.\nThis tutorial goes through exemplary steps for data handling procedures.</p><p><h2>Reading data</h2><p></p><p><ul>\n\n<li>GROOPS is able to read and convert relevant data from various LEO and GNSS satellites. Instrument files need to be converted into the respective GROOPS format using conversion programs.Depending on the content of the input file, the data is stored with a specific <a class=\"groops-class\" href=\"instrumentTypeType.html\">instrument type</a>. User also has the option to change the type later on with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>.</p><p></li><li>\nMultiple files can be concatenated to one file using <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>. Using this program, it is also possible to sort the epochs, remove the duplicates and NaN values.\n</li><li>\n<em>Example: Concatenating instrument files</em>\n  <ul>\n\n  </li><li>\nCreate three successively daily sinusoidal signals with <a class=\"groops-program\" href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a> and set their type to MISCVALUE with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>. In this example, each data set has an overlap of 1 hour with their following dataset.\n  </li><li>\nMerge all datasets to one single file with <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>.\n  <figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentDataHandeling_concatenating.png\" alt=\"instrumentDataHandeling_concatenating\"><figcaption class=\"center\">Figure: Example 1: Concatenating instrument files into one dataset.</figcaption></figure>\n  </li></ul>\n\n <li>Many measurements involve data collected asynchronously by multiple sensors with different sampling. Use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a> for a continuous harmonization of the data over time or segmentation of the data into arcs.\n</li></ul>\n</p><p><h2>Preprocessing</h2><p>\nReal-world data is often incomplete, inconsistent, and/or lacking in certain behaviors or trends, and is likely to contain many errors. Data preprocessing is a proven method of resolving such issues. Following steps are usually required to be taken:</p><p><ul>\n\n<li>Gross outlier removal:\n  <ul>\n\n  </li><li>\nCreate reference values to compare the input data with. Depending on the instrument type, this can be done by simulation programs such as <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a> or <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a>. If no reference data is available, the outlier detection is based on the data itself. If needed, synchronize the reference data file and the input data with <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p>  </li><li>\nIn case of star camera data, compute the differences between the input data and the reference data with <a class=\"groops-program\" href=\"InstrumentStarCameraMultiply.html\">InstrumentStarCameraMultiply</a>.</p><p>  </li><li>\nSet a threshold for outlier detection in <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a>. The threshold is defined empirically according to the accuracy characteristics of each data products. If the differences exceed a predefined threshold, the corresponding epochs are removed. An arbitrary margin can be defined to additionally remove epochs before and after the identified outliers. It is also possible to remove epochs at specific times using <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByTimes.html\">InstrumentRemoveEpochsByTimes</a>.\n  </li><li>\nMissing epochs can be filled by reference data with <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>.\n  </li><li>\nIt is also possible to interpolate the missing epochs with <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>.\n  </li><li>\n<em>Example: Removing outliers in a synthetic data.</em>\n  <ul>\n\n  </li><li>\nCreate a sinusoidal signal with an amplitude of 1.0 using <a class=\"groops-program\" href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a> and set its type to MISCVALUE with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>.\n  </li><li>\nAdd zero-mean, white Gaussian noise with a standard deviation of 0.1 with <a class=\"groops-program\" href=\"NoiseInstrument.html\">NoiseInstrument</a>. Interpret this data as a real measurement file.\n  </li><li>\nSet the threshold criteria to 0.2 in <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a> and remove the outliers and their nearest epochs in 20 second interval.\n  </li><li>\nFill the data gaps with <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>.\n  <figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentDataHandeling_outlierRemoval.png\" alt=\"instrumentDataHandeling_outlierRemoval\"><figcaption class=\"center\">Figure: Example 2: Removing gross outliers.</figcaption></figure>\n  </li></ul>\n\n  </ul></p><p>\n<li>Downsampling:\n  <ul>\n\n  </li><li>\nIf the sampling is irregular use <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a> to make the sampling equidistant.\n  </li><li>\nUse <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a> to divide the data at gaps into arcs.\n  </li><li>\nApply a lowpass filter (e.g. Butterworth) with the Nyquist frequency of the target sampling as cutoff with <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a>. Apply the filter in both directions to avoid phase shifts.\n  </li><li>\nUse <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a> to down-sample the data.\n  </li></ul>\n</p><p><li>Calibration:\n  <ul>\n\n  </li><li>\nFor a general instrument file, <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> subtracts offsets or linear/nonlinear trends from the input data. This can be achieved also with <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a> or <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a> by applying determined calibration factors or solving a least-square adjustment.\n  </li><li>\nFor accelerometer data, <a class=\"groops-program\" href=\"InstrumentAccelerometerEstimateBiasScale.html\">InstrumentAccelerometerEstimateBiasScale</a> is designed to estimate and subtract complex biases or scales with respect to simulated accelerometer data. If a thruster file is given, the corresponding epochs are eliminated during estimation process.\n  </li><li>\n<em>Example: GRACE-C accelerometer calibration</em>\n  <ul>\n\n  </li><li>\nFor one particular date, read and convert Level-1B GRACE-C orbit, star camera, accelerometer, and thruster data with <a class=\"groops-program\" href=\"GraceL1b2Orbit.html\">GraceL1b2Orbit</a>, <a class=\"groops-program\" href=\"GraceL1b2StarCamera.html\">GraceL1b2StarCamera</a>, <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>, and <a class=\"groops-program\" href=\"GraceL1b2Thruster.html\">GraceL1b2Thruster</a> respectively. It is also required to read the macro-model data of the satellite using the related information in the official document and convert it to GROOPS format with <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a>.\n  </li><li>\nUse <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a> to generate simulated accelerations due to non-gravitational force models including: <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">miscAccelerations:atmosphericDrag</a>, <a class=\"groops-class\" href=\"miscAccelerationsType.html#solarRadiationPressure\">miscAccelerations:solarRadiationPressure</a>, and <a class=\"groops-class\" href=\"miscAccelerationsType.html#albedo\">miscAccelerations:albedo</a>.\n  </li><li>\nCalibrate the real measurements with a daily constant accelerometer bias by choosing a constant parameter per axis in <a class=\"groops-class\" href=\"parametrizationAccelerationType.html#accBias\">parametrizationAcceleration:accBias</a>.\n  <figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentDataHandeling_calibration.png\" alt=\"instrumentDataHandeling_calibration\"><figcaption class=\"center\">Figure: Example 3: Calibrating GRACE-C ACT1B data.</figcaption></figure>\n  </li></ul>\n\n  </ul>\n</ul></p><p><h2>Statistical analysis</h2><p>\n<ul>\n\n<li><a class=\"groops-program\" href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a> returns statistics for one or more instrument files. <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a> is also able to generate a <strong class=\"groops-config-element\">statistics</strong> file with one mid epoch per arc.\n</li></ul>\n</p><p><h2>Spectral analysis</h2><p>\nSpectral analysis studies the frequency spectrum contained in discrete, uniformly sampled data. The Fourier transform is a tool that reveals frequency components of a signal by representing it in frequency space. The Power Spectral Density (PSD) is a measurement of the energy at each frequency.</p><p><ul>\n\n<li>If the sampling is irregular use <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a> to make the sampling equidistant.\n</li><li>\nUse <a class=\"groops-program\" href=\"Instrument2PowerSpectralDensity.html\">Instrument2PowerSpectralDensity</a> to compute PSD.\n</li><li>\nIf covariance function of a dataset is available, use <a class=\"groops-program\" href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a>.\n</li><li>\n<em>Example: Spectral analysis of a synthetic signal.</em>\n  <ul>\n\n  </li><li>\nCreate a sinusoidal signal with an amplitude of 1.0 using <a class=\"groops-program\" href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a> and set its type to MISCVALUE with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>. Interpret this data as a simulation data file.\n  </li><li>\nAdd zero-mean, white Gaussian noise with a standard deviation of 0.1 with <a class=\"groops-program\" href=\"NoiseInstrument.html\">NoiseInstrument</a>. Interpret this data as a real measurement file.\n  </li><li>\nCompute PSD of the simulated and measurement data and represent the results with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n  <figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentDataHandeling_psd.png\" alt=\"instrumentDataHandeling_psd\"><figcaption class=\"center\">Figure: Example 4: Spectral analysis of a synthetic signal.</figcaption></figure>\n  </li></ul>\n\n</ul></p><p><h2>Data visualization</h2><p>\n<ul>\n\n<li>Argument of latitude plot\nPlotting instrument data as a function of satellite position in orbit and time reveals features related to the orbit geometry or environmental conditions. For circular orbits, the position of  satellite can be specified by the argument of latitude.\n<ul>\n\n</li><li>\nSynchronize the instrument data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n</li><li>\nUse <a class=\"groops-program\" href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a> to compute argument of latitude at each epoch.\n</li><li>\nPlot the instrument data versus argument of latitude and time with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n</li><li>\n<em>Example: Argument of latitude representation of GRACE-C eclipse factors</em>\n  <ul>\n\n  </li><li>\nCompute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using <a class=\"groops-program\" href=\"Orbit2EclipseFactor.html\">Orbit2EclipseFactor</a>.\n  </li><li>\nSynchronize the eclipse factor data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n  </li><li>\nUse <a class=\"groops-program\" href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a> to compute argument of latitude at each epoch and visualize the results with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n  <figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentDataHandeling_aol.png\" alt=\"instrumentDataHandeling_aol\"><figcaption class=\"center\">Figure: Example 5: GRACE-C eclipse factors represented in argument of latitude plot.</figcaption></figure>\n  </li></ul>\n\n</ul></p><p><li>Ground-track plot\nPlotting instrument data with respect to the satellite ground track is useful to identify any features of geophysical origin in the data.\n<ul>\n\n</li><li>\nSynchronize the instrument data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n</li><li>\nUse <a class=\"groops-program\" href=\"Orbit2Groundtracks.html\">Orbit2Groundtracks</a> to map instrument data to satellite ground-track.\n</li><li>\nVisualize the output with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.\n</li><li>\n<em>Example 6: Ground-track representation of GRACE-C eclipse factors</em>\n  <ul>\n\n  </li><li>\nCompute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using <a class=\"groops-program\" href=\"Orbit2EclipseFactor.html\">Orbit2EclipseFactor</a>.\n  </li><li>\nSynchronize the eclipse factor data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n  </li><li>\nUse <a class=\"groops-program\" href=\"Orbit2Groundtracks.html\">Orbit2Groundtracks</a> to generate the gridded data. Each grid value represents the mean value of eclipse factor over the instrument time period (1 month).  visualize the results with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.\n  </li></ul>\n\n  <figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/instrumentDataHandeling_groundTrack.png\" alt=\"instrumentDataHandeling_groundTrack\"><figcaption class=\"center\">Figure: Example 6: GRACE-C eclipse factors represented in ground-track plot.</figcaption></figure>\n</ul></p><p></ul>\n\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.kinematicOrbit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Kinematic orbit determination of LEO satellites</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.kinematicOrbit\">Kinematic orbit determination of LEO satellites</h1><p>\nThis cookbook chapter describes exemplarily the steps for determining kinematic orbits of low-Earth orbit (LEO) satellites.</p><p>An example scenario for this task is available at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip</a>.\nIt includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (data folder or zipped archive).\nThe scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.</p><p><h2 id=\"gnssMetadata\">Prepare GNSS satellite data</h2><p>\nMost of the required metadata files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>.\nThese files are regularly updated.</p><p>Data that has to be gathered from other sources comprises:\n<ul>\n\n  <li><b>Receiver observations</b>: GNSS measurements converted from RINEX format (see <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>)\n  </li><li>\n<b>Precise orbits</b>: precise orbits in CRF for orbit integration (see <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>)\n  </li><li>\n<b>Precise clocks</b>: precise clocks (see <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a>)\n  </li><li>\n<b>Attitude</b>: rotation from body frame to CRF (see <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> or <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>)\n  </li><li>\n<b>Signal biases</b>: code (and phase) biases (see <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>)\n</li></ul>\n\nReceiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the\n<a href=\"https://igs.org/data-products-overview/\">IGS Data Centers</a>.\nGPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of\n<a href=\"https://doi.org/10.3217/dataset-4528-0723-0867\">Graz University of Technology's contribution to IGS repro3</a>.</p><p>The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\">example scenario</a> includes a small set of this data.\nThe script <code>010groopsConvert.xml</code> can be used to convert these external formats into GROOPS formats.</p><p><h2 id=\"leoMetadata\">Prepare LEO metadata</h2><p>\nMetadata for several LEO missions is availabe at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/receiverLowEarthOrbiter\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/receiverLowEarthOrbiter</a>.</p><p>If you want to process another mission, you can create the necessary files with these steps:\n<ul>\n\n  <li>For creating the <a class=\"groops-file\" href=\"fileFormat_platform.html\">GnssSatelliteInfo file</a> use <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>. Note that the rotation from the\n  satellite reference frame into the antenna reference frame, as well as the change of the center of mass due to fuel consumption, has to be considered here.\n  </li><li>\nThe <a class=\"groops-file\" href=\"fileFormat_gnssReceiverDefinition.html\">GnssReceiverDefinition file</a> can be created by using <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a>. Here you can specify which GNSS signal types the receiver observes.\n  </li><li>\nFor creating the <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> use <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>. Here you can define phase center offsets for the antenna.\n  </li><li>\nFor determining the elevation dependent accuracies the program <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a> is used again.\n  <ul>\n\n    </li><li>\n<strong class=\"groops-config-element\">antenna</strong>: set to new\n    </li><li>\nSet the <strong class=\"groops-config-element\">pattern</strong>s for code (<strong class=\"groops-config-element\">type</strong>=<code>C**</code>) and phase\n    (<strong class=\"groops-config-element\">type</strong>=<code>L**</code>). The standard deviation is expressed e.g. with <strong class=\"groops-config-element\">values</strong>=<code>0.001/cos(2*PI/180*zenith)</code>.\n  </li></ul>\n\n</ul></p><p><h2 id=\"leoData\">Prepare LEO data</h2><p>\nThe <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\">example scenario</a> includes a small set of this data for the GRACE-FO mission.\nThe script <code>020groopsConvertGracefo.xml</code> can be used to convert these external formats into GROOPS formats.</p><p>The data preparation steps are:\n<ul>\n\n  <li>Conversion of the approximate orbit and star camera data into GROOPS format using a conversion program.\n  </li><li>\nIf no attitude data is given the star camera data can be simulated by using <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a> or <a class=\"groops-program\" href=\"SimulateStarCameraSentinel1.html\">SimulateStarCameraSentinel1</a>.\n  </li><li>\nThe GNSS observation data (given in RINEX format) can be converted with <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>.\n  </li><li>\nSuitable programs to get daily data are <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a> and <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n  </li><li>\nFor interpolating the orbit and star camera data to GNSS receiver epochs use <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a> and provide the converted RINEX observation file as input for\n  <a class=\"groops-class\" href=\"timeSeriesType.html#instrument\">timeSeries:instrument</a>.\n  </li><li>\nFor synchronizing these data use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.\n</li></ul>\n\nDetailed description of instrument data handling can be found in <a class=\"groops-ref\" href=\"cookbook.instrument.html\">Instrument data handling</a>.</p><p><h2 id=\"processing\">Estimate kinematic orbits</h2><p>\nThe script <code>03groopsGnssProcessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\">example scenario</a>\nimplements the following steps and settings.</p><p>These are the settings for <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. If not otherwise stated use the default values.</p><p>As we have only one receiver the processing sampling can be directly taken from the observation file:\n<a class=\"groops-class\" href=\"timeSeriesType.html#instrument\">timeSeries:instrument</a>.</p><p>Add the appropriate <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html#gnss\">transmitters:gnss</a> (e.g. GPS)\nand provide the required files (from <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html#gnssMetadata\">Prepare GNSS satellite data</a>):\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a>\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a>\n</li></ul>\n</p><p>The following files (from <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html#leoMetadata\">Prepare LEO metadata</a> and <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html#leoData\">Prepare LEO data</a>) and settings are needed in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html#lowEarthOrbiter\">receiver:lowEarthOrbiter</a>:\n<ul>\n\n   <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a>: The satellite info file.\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a>\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a>\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: The converted RINEX observation file.\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: The approximate orbit.\n   </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>: The convered or simulated attitude.\n   </li><li>\n<a class=\"groops-class\" href=\"gnssType.html\">useType</a>: We recommend to explicitly specify the signals to be processed\n            and to make sure that at least transmitter code biases are provided for each of them, e.g. <code>C1CG</code>,\n            <code>C1WG</code>, <code>C2WG</code>, <code>L1*G</code>, <code>L2*G</code>, ...).\n</li></ul>\n</p><p>Add the following <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>\nand define the <strong class=\"groops-config-element\">outputfiles</strong> within you are interested in:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">ionosphereSTEC</a>: add a constraint of <strong class=\"groops-config-element\">sigmaSTEC</strong>=<code>40</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">ionosphereVTEC</a>:\n        set <strong class=\"groops-config-element\">mapR</strong>=<code>6371e3+450e3</code> to satellite height and ionosphere height <strong class=\"groops-config-element\">mapH</strong>=<code>50e3</code> above.\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">clocks</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">signalBiases</a>: provide <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBiasTransmitter</a> created with <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">ambiguities</a>: if precise transmitter phase biases are available you can delete <a class=\"groops-class\" href=\"platformSelectorType.html\">estimateTransmitterPhaseBiases</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">codeBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">tecBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#kinematicPositions\">kinematicPositions</a>\n</li></ul>\n</p><p>Add the following <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>8</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>2</code>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#computeCovarianceMatrix\">computeCovarianceMatrix</a>\n  </li><li>\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>\n</li></ul>\n</p><p>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/cookbook.regionalGeoid.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Regional geoid determination</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"cookbook.regionalGeoid\">Regional geoid determination</h1><p>\nThis shows the exemplary computation of a regional geoid using terrestrial gravimetric observations\nin combination with a global satellite model such as GOCO06s. The geoid is estimated in a least squares adjustment with\na parametrization using radial basis functions. A detailed desciption of the method is given in\nChristian Pock (2017), Consistent Combination of Satellite and Terrestrial Gravity Field Observations in Regional Geoid Modeling.\nDissertation TU Graz.</p><p>\n<h2>Gravimetric data</h2><p>\nHere it is assumed that the measured absolute gravity data is given at points in ellipsoidal coordinates.\nThe observed values should be converted to SI units $m/s^2$.\n<ul>\n\n  <li><a class=\"groops-program\" href=\"Matrix2GriddedData.html\">Matrix2GriddedData</a> to convert data from text file in tabular form.\n</li></ul>\n</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/regionalGeoidGravimetricData.png\" alt=\"regionalGeoidGravimetricData\"><figcaption class=\"center\">Figure: Distribution of gravimetric observations</figcaption></figure></p><p><h2>Topography</h2><p>\nA high resolution topography model is needed to reduce the observations.\nAs the model heights are usually given in physical heights a reference geoid is needed to compute the correct ellipsoidal height.\n<ul>\n\n  <li><a class=\"groops-program\" href=\"NetCdf2GridRectangular.html\">NetCdf2GridRectangular</a> convert into groops format.\n  </li><li>\n<a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>: Compute geoid heights using the GOCO06s model with\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gridType.html#file\">grid:file</a> The topography grid\n    </li><li>\n<a class=\"groops-class\" href=\"kernelType.html#geoidHeight\">kernel:geoidHeight</a>\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> the GOCO06s model\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>\n    Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) GRS680 normal field.\n  </li></ul>\n\n  <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>: Generate a new combined griddedData file\n        with the orthometric height (<code>data0</code>) and the geoid height (<code>data1</code>).\n  </li><li>\n<a class=\"groops-program\" href=\"GriddedTopography2PotentialCoefficients.html\">GriddedTopography2PotentialCoefficients</a>: Compute the gravitational potential in terms\n        of spherical harmonics up to a maximum degree of the global satellite model.\n        This is the part of the topography, which is already included in the global satellite model.\n        The integration boundaries are <strong class=\"groops-config-element\">radialUpperBound</strong>=<code>data0+data1</code>\n        and <strong class=\"groops-config-element\">radialLowerBound</strong>=<code>data1</code>.\n</li></ul>\n</p><p><figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/regionalGeoidTopography.png\" alt=\"regionalGeoidTopography\"><figcaption class=\"center\">Figure: Topography and geoid heights</figcaption></figure></p><p><h2>Reduce</h2><p>\nCalculate approximate reference gravity to reduce it from the observations.\n<ul>\n\n  <li><a class=\"groops-program\" href=\"Gravityfield2AbsoluteGravity.html\">Gravityfield2AbsoluteGravity</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gridType.html#file\">grid:File</a> at observation positions\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#tides\">gravityfield:tides</a> Centrifugal potential\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> full GOCO06s model\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#topography\">gravityfield:topography</a>\n          (<strong class=\"groops-config-element\">radialUpperBound</strong>=<code>data0+data1</code>, <strong class=\"groops-config-element\">radialLowerBound</strong>=<code>data1</code>)\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>\n          Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) the potential part of the topography already included in the GOCO06s model.\n  </li></ul>\n\n  <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a> to calculate observed minus computed.\n  </li><li>\nLarge outliers can be removed in <a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a> with <strong class=\"groops-config-element\">removalCriteria</strong>.\n</li></ul>\n</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/regionalGeoidObserved-computed.png\" alt=\"regionalGeoidObserved-computed\"><figcaption class=\"center\">Figure: Gravity disturbances: observed minus computed</figcaption></figure></p><p>\n<h2>Radial Basis Functions (RBF)</h2><p>\nThe residual gravity is parametrized in terms of Radial Basis Functions\n<a class=\"groops-class\" href=\"parametrizationGravityType.html#radialBasis\">parametrizationGravity:radialBasis</a>.\nThe basis functions should be distributed on a regular <a class=\"groops-class\" href=\"gridType.html\">grid</a> covering\na somewhat larger area than the observations, see <a class=\"groops-class\" href=\"borderType.html\">border</a>.\nThe shape of the functions <a class=\"groops-class\" href=\"kernelType.html#coefficients\">kernel:coefficients</a> should reflect\nthe signal content of reduced observations and are defined by the coefficients.\n<ul>\n\n  <li><a class=\"groops-program\" href=\"RadialBasisSplines2KernelCoefficients.html\">RadialBasisSplines2KernelCoefficients</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> accuracies of GOCO06s model\n    </li><li>\n<strong class=\"groops-config-element\">maxDegree</strong>=7000. Complemented by Kaula's rule of thumb\n  </li></ul>\n\n</ul>\nThe maximum degree should correspond to the spatial resolution.\nRule of thumb: the number of spherical harmonic coefficients $(\\text{maxDegree}+1)^2$ should roughly agree\nto the number of grid points if they would cover the complete Earth.</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/regionalGeoidDegreeAmplitudes.png\" alt=\"regionalGeoidDegreeAmplitudes\"><figcaption class=\"center\">Figure: Degree amplitudes for the shape of the radial basis functions</figcaption></figure></p><p><h2>Compute: Estimate parameters in a least squares adjustment</h2><p>\nSetup the observation equations and accumulate the system of normal equations.\n<ul>\n\n<li><a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"normalEquationType.html#design\">normalEquation:design</a> with\n          <a class=\"groops-class\" href=\"observationType.html#terrestrial\">observation:terrestrial</a>\n    <ul>\n\n      </li><li>\n<a class=\"groops-class\" href=\"kernelType.html#disturbance\">kernel:disturbance</a>\n      </li><li>\n<a class=\"groops-class\" href=\"parametrizationGravityType.html#radialBasis\">parametrizationGravity:radialBasis</a>\n            with <a class=\"groops-class\" href=\"kernelType.html#coefficients\">kernel:coefficients</a>\n    </li></ul>\n\n  </ul>\n<li><a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"normalEquationType.html#file\">normalEquation:file</a> from <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>\n    </li><li>\n<a class=\"groops-class\" href=\"normalEquationType.html#regularization\">normalEquation:regularization</a>\n           towards zero means regularization towards the GOCO06s, which is reduced from the data.\n  </li></ul>\n\n</ul></p><p><h2>Restore: Calculate the geoid solution</h2><p>\nEvaluate the estimated parameters and add back the reduced reference models.\n<ul>\n\n  <li><a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>: Compute approximate geoid heights using the GOCO06s model with\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gridType.html\">grid</a> select a grid with target resolution at elliposid\n    </li><li>\n<a class=\"groops-class\" href=\"kernelType.html#geoidHeight\">kernel:geoidHeight</a>\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> GOCO06s model\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>\n    Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) GRS80 normal field.\n  </li></ul>\n\n  <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>: Move points from ellipsoid to geoid with <strong class=\"groops-config-element\">height</strong>=<code>data0</code>\n  </li><li>\n<a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>\n  <ul>\n\n    </li><li>\n<a class=\"groops-class\" href=\"gridType.html#file\">grid:file</a> from above.\n    </li><li>\n<a class=\"groops-class\" href=\"kernelType.html#geoidHeight\">kernel:geoidHeight</a>\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#fromParametrization\">gravityfield:fromParametrization</a>\n          The solution vector $\\M x$ together with the RBF parametrization\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> GOCO06s model\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#topography\">gravityfield:topography</a>\n          (<strong class=\"groops-config-element\">radialUpperBound</strong>=<code>data0+data1</code>, <strong class=\"groops-config-element\">radialLowerBound</strong>=<code>data1</code>)\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>\n          Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) the potential part of the topography already included in the GOCO06s model.\n    </li><li>\n<a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>\n          Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) GRS80 normal field.\n    </li><li>\n<strong class=\"groops-config-element\">convertToHarmonics</strong>=<code>no</code>, otherwise the RBF are converted to harmonics up to degree 7000.\n  </li></ul>\n\n  <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>: Set <strong class=\"groops-config-element\">height</strong>=0 of the computed geoid grid.\n  </li><li>\n<a class=\"groops-program\" href=\"GridRectangular2NetCdf.html\">GridRectangular2NetCdf</a>\n</li></ul>\n</p><p><figure><img class=\"figure\" style=\"width:60%;\" src=\"../figures/regionalGeoidGeoid.png\" alt=\"regionalGeoidGeoid\"><figcaption class=\"center\">Figure: Estimated geoid</figcaption></figure></p><p>\n\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/covariancePodType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - covariancePodType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"covariancePodType\">CovariancePod</h1><p>\nProvides arc-wise covariance matrices for precise orbit data.\nTemporal correlations are modeled in the orbit system (along, cross, radial).\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceFunction</a> provides temporal covariance functions for each axis.\nFrom the diagonal matrix for each time step\n\\[\n  Cov_{3\\times3}(t) = \\text{diag}(cov_x(t), cov_y(t), cov_z(t))\n\\]the Toeplitz covariance matrix for an arc is constructed\n\\[\n  \\M C = \\begin{pmatrix}\n    Cov(t_0) & Cov(t_1) & \\cdots   &          &        &        \\\\\n    Cov(t_1) & Cov(t_0) & Cov(t_1) & \\cdots   &        &        \\\\\n    \\cdots   & Cov(t_1) & Cov(t_0) & Cov(t_1) & \\cdots &        \\\\\n             & \\cdots   & \\ddots   & \\ddots   & \\ddots & \\cdots \\\\\n  \\end{pmatrix}\n\\]\nThe epoch-wise $3\\times3$ covariance matrices given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>\nare eigenvalue-decomposed\n\\[\n  \\M C_{3\\times3}(t_i) = \\M Q \\M\\Lambda \\M Q^T,\n\\]where $\\M Q$ is an orthogonal matrix and $\\M\\Lambda$ diagonal.\nThis is used to split the covariances matrices\n\\[\n  \\M C_{3\\times3}(t_i) = \\M D(t_i) \\M D(t_i)^T = (\\M Q \\M\\Lambda^{1/2} \\M Q^T)(\\M Q \\M\\Lambda^{1/2} \\M Q^T)^T,\n\\]and to compose a block diagonal matrix for an arc\n\\[\n  \\M D = \\text{diag}(\\M D(t_1), \\M D(t_2), \\ldots, \\M D(t_2)).\n\\]\nThe complete covariance matrix of an arc is given by\n\\[\n  \\M C_{arc} = \\sigma_0^2 \\sigma_{arc}^2 \\M D \\M C \\M D^T +\n  \\text{diag}(\\sigma_1^2\\M I_{3\\times3}, \\sigma_2^2\\M I_{3\\times3}, \\ldots, \\sigma_n^2\\M I_{3\\times3})\n\\]where <strong class=\"groops-config-element\">sigma</strong> $\\sigma_0$ is an overall factor\nand the arc specific factors $\\sigma_{arc}$ can be provided with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmasPerArc</a>.\nThe last matrix can be used to downweight outliers in single epochs and will be added if\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSigmasPerEpoch</a> is provided.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePodType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>general variance factor</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>different accuracies for each arc (multiplied with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>different accuracies for each epoch (added)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>covariances in time for along, cross, and radial direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovariancePodEpoch</div></div></td><td>filename</td><td>3x3 epoch-wise covariances</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/covarianceSstType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - covarianceSstType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"covarianceSstType\">CovarianceSst</h1><p>\nProvides arc-wise covariance matrices for satellite-to-satellite observations (SST).\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceFunction</a> provides a temporal covariance function.\nFrom it the Toeplitz covariance matrix is constructed\n\\[\n  \\M C = \\begin{pmatrix}\n    cov(t_0) & cov(t_1) & \\cdots   &          &        &        \\\\\n    cov(t_1) & cov(t_0) & cov(t_1) & \\cdots   &        &        \\\\\n    \\cdots   & cov(t_1) & cov(t_0) & cov(t_1) & \\cdots &        \\\\\n             & \\cdots   & \\ddots   & \\ddots   & \\ddots & \\cdots \\\\\n  \\end{pmatrix} \\\\\n\\]\nThe complete covariance matrix of an arc is given by\n\\[\n  \\M C_{arc} = \\sigma_0^2 \\sigma_{arc}^2 \\M C + \\sigma_{S,arc}^2 \\M S_{arc}+ \\text{diag}(\\sigma_1^2, \\sigma_2^2, \\ldots, \\sigma_n^2)\n\\]where <strong class=\"groops-config-element\">sigma</strong> $\\sigma_0$ is an overall factor and the arc specific factors $\\sigma_{arc}$\ncan be provided with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmasPerArc</a>.\nThe second term describes general covariance matrices for each arc\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceMatrixArc</a> together with the factors $\\sigma_{S,arc}$ from <strong class=\"groops-config-element\">sigmasCovarianceMatrixArc</strong>.\nThe last matrix can be used to downweight outliers in single epochs and will be added if\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSigmasPerEpoch</a> is provided.</p><p></p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSstType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>general variance factor</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>different accuaries for each arc (multplicated with sigma)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerEpoch</div></div></td><td>filename</td><td>different accuaries for each epoch (added)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>covariance function in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileCovarianceMatrixArc</div></div></td><td>filename</td><td>one matrix file per arc. Use {arcNo} as template</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigmasCovarianceMatrixArc</div></div></td><td>filename</td><td>vector with one sigma for each covarianceMatrixArc</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/digitalFilterType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - digitalFilterType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"digitalFilterType\">DigitalFilter</h1><p>\nDigital filter implementation for the filtering of equally spaced time series. This class implements the filter equations as\n\\[\\label{digitalFilterType:arma}\n  \\sum_{l=0}^Q a_l y_{n-l} = \\sum_{k=-p_0}^{P-p_0-1} b_k x_{n-k}, \\hspace{25pt} a_0 = 1,\n\\]where $Q$ is the autoregressive (AR) order and $P$ is the moving average (MA) order. Note that the MA part can also be non-causal.\nThe characteristics of a filter cascade can be computed by the programs <a class=\"groops-program\" href=\"DigitalFilter2FrequencyResponse.html\">DigitalFilter2FrequencyResponse</a> and <a class=\"groops-program\" href=\"DigitalFilter2ImpulseResponse.html\">DigitalFilter2ImpulseResponse</a>.\nTo apply a filter cascade to a time series (or an instrument file ) use <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a>.\nEach filter can be applyed in forward and backward direction by setting <strong class=\"groops-config-element\">backwardDirection</strong>.\nIf the same filter is applied in both directions, the combined filter has zero phase and the squared magnitude response.\nSetting <strong class=\"groops-config-element\">inFrequencyDomain</strong> to true applies the transfer function of the filter to the DFT of the input and synthesizes the result, i.e.:\n\\[\n  y_n = \\mathcal{F}^{-1}\\{H\\cdot\\mathcal{F}\\{x_n\\}\\}.\n\\]This is equivalent to setting <strong class=\"groops-config-element\">padType</strong> to <strong class=\"groops-config-element\">periodic</strong>.</p><p>To reduce warmup effects, the input time series can be padded by choosing a <strong class=\"groops-config-element\">padType</strong>:\n<ul>\n\n<li><strong class=\"groops-config-element\">none</strong>: no padding is applied\n</li><li>\n<strong class=\"groops-config-element\">zero</strong>: zeros are appended at the beginning and end of the input time series\n</li><li>\n<strong class=\"groops-config-element\">constant</strong>: the beginning of the input time series is padded with the first value, the end is padded with the last value\n</li><li>\n<strong class=\"groops-config-element\">periodic</strong>: periodic continuation of the input time series (i.,e. the beginning is padded with the last epochs and the end is padded with the first epochs)\n</li><li>\n<strong class=\"groops-config-element\">symmetric</strong>: beginning and end are reflected around the first and last epoch respectively\n</li></ul>\n\n</p>\n\n<h2>MovingAverage</h2><p>\nMoving average (boxcar) filter. For odd lengths, this filter is symmetric and has therefore no phase shift. For even lengths, a phase shift of half a cycle is introduced.</p><p>\\[\n  y_n = \\sum_{k=-\\lfloor\\frac{P}{2}\\rfloor}^{\\lfloor\\frac{P}{2}\\rfloor} \\frac{1}{P}x_{n-k}\n\\]</p><p></p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">length</div></div></td><td>uint</td><td>number of epochs in averaging operator</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Median</h2><p>\nMoving median filter of length $n$. The filter output at epoch $k$ is the median of the set start at $k-n/2$ to $k+n/2$.\nThe filter length $n$ should be uneven to avoid a phase shift.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">length</div></div></td><td>uint</td><td>length of the moving window [epochs]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Derivative</h2><p>\nSymmetric MA filter for numerical differentiation using polynomial approximation. The input time series is approximated by a moving polynomial of degree <strong class=\"groops-config-element\">polynomialDegree</strong>, by solving\n\\[\n  \\begin{bmatrix} x(t_k+\\tau_0) \\\\ \\vdots \\\\ x(t_k+\\tau_M) \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  1      & \\tau_0 & \\tau_0^2 & \\cdots & \\tau_0^M \\\\\n  \\vdots & \\vdots & \\vdots   &        & \\vdots   \\\\\n  1      & \\tau_M & \\tau_M^2 & \\cdots & \\tau_M^M \\\\\n  \\end{bmatrix}%^{-1}\n  \\begin{bmatrix}\n  a_0 \\\\ \\vdots \\\\ a_M\n  \\end{bmatrix}\n  \\qquad\\text{with}\\quad\n  \\tau_j =  (j-M/2)\\cdot \\Delta t,\n\\]for each time step $t_k$ ($\\Delta t$ is the <strong class=\"groops-config-element\">sampling</strong> of the time series).\nThe filter coefficients for the $k$-th derivative are obtained by taking the appropriate row of the inverse coefficient matrix $\\mathbf{W}$:\n\\[\n  b_n = \\prod_{i=0}^{k-1} (k-i) \\mathbf{w}_{2,:}.\n\\]The <strong class=\"groops-config-element\">polynomialDegree</strong> should be even if no phase shift should be introduced.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>degree of approximation polynomial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">derivative</div></div></td><td>uint</td><td>take kth derivative</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>assumed time step between points</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Integral</h2><p>\nNumerical integration using polynomial approximation.\nThe input time series is approximated by a moving polynomial of degree <strong class=\"groops-config-element\">polynomialDegree</strong>\nby solving\n\\[\n  \\begin{bmatrix} x(t_k+\\tau_0) \\\\ \\vdots \\\\ x(t_k+\\tau_M) \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  1      & \\tau_0 & \\tau_0^2 & \\cdots & \\tau_0^M \\\\\n  \\vdots & \\vdots & \\vdots   &        & \\vdots   \\\\\n  1      & \\tau_M & \\tau_M^2 & \\cdots & \\tau_M^M \\\\\n  \\end{bmatrix}%^{-1}\n  \\begin{bmatrix}\n  a_0 \\\\ \\vdots \\\\ a_M\n  \\end{bmatrix}\n  \\qquad\\text{with}\\quad\n  \\tau_j =  (j-M/2)\\cdot \\Delta t,\n\\]for each time step $t_k$ ($\\Delta t$ is the <strong class=\"groops-config-element\">sampling</strong> of the time series).\nThe numerical integral for each time step $t_k$ is approximated by the center interval of the estimated polynomial.</p><p><figure><img class=\"figure\" style=\"width:70%;\" src=\"../figures/DigitalFilter_integral.png\" alt=\"DigitalFilter_integral\"><figcaption class=\"center\">Figure: Numerical integration by polynomial approximation.</figcaption></figure></p><p><strong class=\"groops-config-element\">polynomialDegree</strong> should be even to avoid a phase shift.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>degree of approximation polynomial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sampling</div></div></td><td>double</td><td>assumed time step between points</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Correlation</h2><p>\nCorrelation ($\\rho$) of <strong class=\"groops-config-element\">corr</strong> is introduced into the time series:\n\\[\n  y_n = \\rho\\cdot y_{n-1} + \\sqrt{1-\\rho^2}x_n.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">correlation</div></div></td><td>double</td><td>correlation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">backwardDirection</div></div></td><td>boolean</td><td>apply filter in backward direction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>GraceLowpass</h2><p>\nLow pass and differentation filter as used for GRACE KBR and ACC data in the Level1A processing.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/DigitalFilter_graceLowpass.png\" alt=\"DigitalFilter_graceLowpass\"><figcaption class=\"center\">Figure: Amplitude response of the low pass filter used in the L1A processing.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rawDataRate</div></div></td><td>double</td><td>sampling frequency in Hz (fs).</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">convolutionNumber</div></div></td><td>uint</td><td>number of self convolutions of the filter kernel</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fitInterval</div></div></td><td>double</td><td>length of the filter kernel [seconds]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lowPassBandwith</div></div></td><td>double</td><td>target low pass bandwidth</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">normFrequency</div></div></td><td>double</td><td>norm filter at this frequency [Hz] (default: GRACE dominant (J2) signal frequency)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">reduceQuadraticFit</div></div></td><td>boolean</td><td>remove->filter->restore quadratic fit</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">derivative</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">derivative1st</div></div></td><td></td><td>range rate</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">derivative2nd</div></div></td><td></td><td>range acceleration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Butterworth</h2><p>\nDigital implementation of the Butterworth filter. The design of the filter is done by modifying the analog (continuous time) transfer function, which is\nthen transformed into the digital domain by using the bilinear transform. The filter coefficients are then determined by a least squares adjustment in time domain.</p><p>The <strong class=\"groops-config-element\">filterType</strong> can be <strong class=\"groops-config-element\">lowpass</strong>, <strong class=\"groops-config-element\">highpass</strong>, where one cutoff frequency has to be specified, and <strong class=\"groops-config-element\">bandpass</strong> and <strong class=\"groops-config-element\">bandstop</strong> where to cutoff frequencies have to be specified.\nCutoff frequencies must be given as normalized frequency $w_n = f/f_{\\text{nyq}}$. For a cutoff frequency of 30 mHz for a time series sampled with 5 seconds gives a normalized frequency of $0.03/0.1 = 0.3$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td>filter order</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td>filter type</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">lowpass</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">Wn</div></div></td><td>double</td><td>normalized cutoff frequency (f_c / f_nyq)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">highpass</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">Wn</div></div></td><td>double</td><td>normalized cutoff frequency (f_c / f_nyq)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">bandpass</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">Wn1</div></div></td><td>double</td><td>lower normalized cutoff frequency (f_c / f_nyq)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">Wn2</div></div></td><td>double</td><td>upper normalized cutoff frequency (f_c / f_nyq)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">bandstop</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">Wn1</div></div></td><td>double</td><td>lower normalized cutoff frequency (f_c / f_nyq)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">Wn2</div></div></td><td>double</td><td>upper normalized cutoff frequency (f_c / f_nyq)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">backwardDirection</div></div></td><td>boolean</td><td>apply filter in backward direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>File</h2><p>\nRead filter coefficients of \\eqref{digitalFilterType:arma} from a coefficient file.\nOne column might define the index $n$\nof the coefficients $a_n$ and $b_n$ in the other columns.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>matrix with filter coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">index</div></div></td><td>expression</td><td>index of coefficients (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">bn</div></div></td><td>expression</td><td>MA coefficients (moving average) (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">an</div></div></td><td>expression</td><td>AR coefficients (autoregressive) (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">backwardDirection</div></div></td><td>boolean</td><td>apply filter in backward direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Wavelet</h2><p>\nFilter representation of a wavelet.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileWavelet</div></div></td><td>filename</td><td>wavelet coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td>filter type</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">lowpass</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">highpass</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">level</div></div></td><td>uint</td><td>compute filter for specific decomposition level</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">backwardDirection</div></div></td><td>boolean</td><td>apply filter in backward direction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Notch</h2><p>\nImplemented after Christian Siemes' dissertation, page 106.</p><p><figure><img class=\"figure\" style=\"width:60%;\" src=\"../figures/DigitalFilter_notch.png\" alt=\"DigitalFilter_notch\"><figcaption class=\"center\">Figure: Amplitude response of a notch filter of order three with default settings.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">notchFrequency</div></div></td><td>double</td><td>normalized notch frequency w_n = (f_n/f_nyq)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">bandWidth</div></div></td><td>double</td><td>bandwidth at -3db. Quality factor of filter Q = w_n/bw</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">backwardDirection</div></div></td><td>boolean</td><td>apply filter in backward direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>Decorrelation</h2><p>\nMoving average decorrelation filter based on eigendecomposition of a Toeplitz covariance matrix.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>covariance function of time series</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>TimeLag</h2><p>\nLag operator in digital filter representation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">lag</div></div></td><td>int</td><td>lag epochs: 1 (lag); -1 (lead)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inFrequencyDomain</div></div></td><td>boolean</td><td>apply filter in frequency domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">padType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td>no padding is applied</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">zero</div></div></td><td></td><td>zero padding</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">constant</div></div></td><td></td><td>pad using first and last value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">periodic</div></div></td><td></td><td>periodic continuation of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">symmetric</div></div></td><td></td><td>symmetric continuation around the matrix edges</td></tr>\n</table>\n\n<h2>ReduceFilterOutput</h2><p>\nRemoves the filtered signal from the input, i.e. the input is passed\nthrough a <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> with a frequency response of $1-H(f)$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">filter</div></div></td><td><a href=\"digitalFilterType.html\">digitalFilter</a></td><td>remove filter output from input signal</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/documentationSearchIndex.js",
    "content": "var documents = {\n'general.configFiles': { 'name': 'general.configFiles', 'key': 'general.configFiles', 'description': 'GROOPS is controlled by XML configuration files. One or more configuration files must be passed as arguments to GROOPS:     groops config1.xml config2.xml [...]   These files can be created with the graphical user interface program  groopsGui  in a convenient way (see section  GUI ). A complete formal (computer readable) description of a configuration file in the form of an XSD schema file can be created with the command     groops --xsd groops.xsd  A configuration file consists of a list of  programs  that are executed in sequential order. Each program comes with its own config options and they work independently without any internal communication between programs. Data flow between programs is realized via files. An  outputfile  of one program can serve as an  inputfile  for the next program. Most programs are deliberately kept small and focused on a specific task. This modularity combined with the general purpose design of many programs enables the creation of complex workflows with little effort. Including  loops and conditions  in a config file provides even more flexibility. Individual programs (and also other optional config elements) can be disabled and are ignored during execution. Mandatory config elements are indicated by a star ( * ). Empty optional elements are ignored or a meaningful default value is assumed. The elements of a configuration file can be one of the following basic data types:    int : integer number  uint : unsigned integer number  double : floating point number  angle : given in degree  time : given in modified Julian date (MJD)  boolean : 0: false, 1: true  string : text  filename : absolute path to a file or path relative to the working directory  expression : numerical expression evaluated during execution  doodson : Doodson number or Darwin\\'s name of a tidal frequency  gnssType : GNSS observation type according to the RINEX 3 definition   The first 5 data types also allow numerical expressions as input in addition to pure numbers. In addition to these basic types, there are a large number of complex data types called classes, which are described in section  Classes .  In addition to programs, a config file can also include elements called variables. These elements are comparable to read-only variables in programming and can be referenced from any program and config element. This can be done by either linking an element directly to a variable or by using the name as a variable in an expression of an input field (see section  Parsers and variables ). While elements can only be directly linked to variables of the same type, this also supports complex data types such as  section . Thus it is possible to, for example, define a reference gravity field once in the global section and use it multiple times in different programs. Variables can be declared anywhere in the configuration file. Variables in locations other than the global section have a local scope and hide global variables or variables from a hierarchy level above. They are valid after declaration until the end of the hierarchy level is reached or a new variable with the same name is declared. Variables are not evaluated directly when they are declared, but only later when they are used in a config element. This means, for example, that a variable  satelliteFile  with  data/swarm_orbit_{loopTime:%D}.dat  can be declared in the global section without the variable  loopTime  having to be known at this time. One special variable is  groopsDataDir , which is used as a variable in most default file paths throughout many GROOPS programs. Since this variable is going to be needed in most config files, it is recommended to define it in a template file that is used when creating new config files in the GUI. See section  Graphical User Interface (GUI)  for details on how to set up a template file. In addition, the variables  groopsConfigFile  and  workingDir  are set automatically. Global variables can be manipulated when running a config file by passing the argument  --global &lt;name>=&lt;value> . For example, running the command     groops --global timeStart=58849 --global satellite=swarm config.xml   runs the config file  config.xml  but replaces the values of the global variable  timeStart  and  satellite  with  58849  and  swarm , respectively. If a global variable passed as an argument does not already exist in the config file, it will be added with the type  string . Only the basic data types listed above are supported. This feature can be useful when running GROOPS from the command line or from an external script file.', 'config_table': '', 'display_text': 'GROOPS is controlled by XML configuration files. One or more configuration files must be passed as arguments to GROOPS: <pre>   groops config1.xml config2.xml [...] </pre> These files can be created with the graphical user interface program <code>groopsGui</code> in a convenient way (see section <a class=\"groops-ref\" href=\"general.gui.html\">GUI</a>). A complete formal (computer readable) description of a configuration file in the form of an XSD schema file can be created with the command <pre>   groops --xsd groops.xsd </pre></p><p>A configuration file consists of a list of <a class=\"groops-ref\" href=\"programType.html\">programs</a> that are executed in sequential order. Each program comes with its own config options and they work independently without any internal communication between programs. Data flow between programs is realized via files. An <strong class=\"groops-config-element\">outputfile</strong> of one program can serve as an <strong class=\"groops-config-element\">inputfile</strong> for the next program. Most programs are deliberately kept small and focused on a specific task. This modularity combined with the general purpose design of many programs enables the creation of complex workflows with little effort. Including <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">loops and conditions</a> in a config file provides even more flexibility.</p><p>Individual programs (and also other optional config elements) can be disabled and are ignored during execution. Mandatory config elements are indicated by a star (<code>*</code>). Empty optional elements are ignored or a meaningful default value is assumed.</p><p>The elements of a configuration file can be one of the following basic data types: <ul>  <li><code>int</code>: integer number </li><li> <code>uint</code>: unsigned integer number </li><li> <code>double</code>: floating point number </li><li> <code>angle</code>: given in degree </li><li> <code>time</code>: given in modified Julian date (MJD) </li><li> <code>boolean</code>: 0: false, 1: true </li><li> <code>string</code>: text </li><li> <code>filename</code>: absolute path to a file or path relative to the working directory </li><li> <code>expression</code>: numerical expression evaluated during execution </li><li> <code>doodson</code>: Doodson number or Darwin\\'s name of a tidal frequency </li><li> <code>gnssType</code>: GNSS observation type according to the RINEX 3 definition </li></ul>  The first 5 data types also allow numerical expressions as input in addition to pure numbers. In addition to these basic types, there are a large number of complex data types called classes, which are described in section <a class=\"groops-ref\" href=\"classes.html\">Classes</a>.</p><p><h2 id=\"variables\">Variables</h2><p> In addition to programs, a config file can also include elements called variables. These elements are comparable to read-only variables in programming and can be referenced from any program and config element. This can be done by either linking an element directly to a variable or by using the name as a variable in an expression of an input field (see section <a class=\"groops-ref\" href=\"general.parser.html\">Parsers and variables</a>). While elements can only be directly linked to variables of the same type, this also supports complex data types such as <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>. Thus it is possible to, for example, define a reference gravity field once in the global section and use it multiple times in different programs.</p><p>Variables can be declared anywhere in the configuration file. Variables in locations other than the global section have a local scope and hide global variables or variables from a hierarchy level above. They are valid after declaration until the end of the hierarchy level is reached or a new variable with the same name is declared.</p><p>Variables are not evaluated directly when they are declared, but only later when they are used in a config element. This means, for example, that a variable <code>satelliteFile</code> with <code>data/swarm_orbit_{loopTime:%D}.dat</code> can be declared in the global section without the variable <code>loopTime</code> having to be known at this time.</p><p>One special variable is <code>groopsDataDir</code>, which is used as a variable in most default file paths throughout many GROOPS programs. Since this variable is going to be needed in most config files, it is recommended to define it in a template file that is used when creating new config files in the GUI. See section <a class=\"groops-ref\" href=\"general.gui.html\">Graphical User Interface (GUI)</a> for details on how to set up a template file.</p><p>In addition, the variables <code>groopsConfigFile</code> and <code>workingDir</code> are set automatically.</p><p>Global variables can be manipulated when running a config file by passing the argument <code>--global &lt;name>=&lt;value></code>. For example, running the command <pre>   groops --global timeStart=58849 --global satellite=swarm config.xml </pre> runs the config file <code>config.xml</code> but replaces the values of the global variable <code>timeStart</code> and <code>satellite</code> with <code>58849</code> and <code>swarm</code>, respectively. If a global variable passed as an argument does not already exist in the config file, it will be added with the type <code>string</code>. Only the basic data types listed above are supported. This feature can be useful when running GROOPS from the command line or from an external script file.'},\n'general.parser': { 'name': 'general.parser', 'key': 'general.parser', 'description': 'In all input fields that accept numbers (int, uint, double, angle, time) numerical expressions are also allowed. Declared variables can be accessed via their name. The following operations and functions are defined:    Constants:     pi() ,  rho()=180/pi() ,  nan() ,  c() : light velocity,                      G() : gravitational constant,  GM() : gravitational constant of the Earth,  R() : reference radius of the Earth  Mathematical:  + ,  - ,  * ,  / ,  ^   Comparison:    == ,  != ,  &lt; ,  &lt;= ,  > ,  >= , result is 1 or 0  Logical:      not  ! , and  && ,  || , or  isnan(x) , result is 1 or 0  Functions:     sqrt(x) ,  exp(x) ,                      sin(x) ,   cos(x) ,  tan(x) ,                      asin(x) ,   acos(x) ,   atan(x) ,                      abs(x) ,   round(x) ,   ceil(x) ,   floor(x) ,                      deg2rad(x) ,  rad2deg(x)   Functions with 2 arguments:  atan2(y,x) ,  min(x,y) ,  max(x,y) ,  mod(x,y)   Time functions:  now() : local time in MJD,  date2mjd(year, month, day) ,  gps2utc(mjd) ,  utc2gps(mjd) ,  dayofyear(mjd) ,  decimalyear(mjd)   Condition:  if(c,x,y) : If the first argument is true (not 0), the second argument is evaluated, otherwise the third.     Before the mathematical expression parser evaluates the expression, a simple text parser is applied. The text parser is used for all input fields (also file names). It scans the text for terms like  {variable}  and replaces it by the text content of the  variable . A literal \\' { \\' character must be escaped with \\' #{ \\'. The text parser allows regex replacements in the form  {text/regex/replace} . All matches of  regex  in the  text  are replaced by  replace . Possible  {variables}  in the three parts are evaluated beforehand. Capturing groups  ()  can be accessed by  $1 ,  $2 ,  in the replacement ( $0  is the complete match). Additional escape sequences are:    \\\\l  lowercase next char,  \\\\u  uppercase next char,  \\\\L  lowercase until  \\\\E ,  \\\\U  uppercase until  \\\\E ,  \\\\Q  quote (disable) pattern metacharacters until  \\\\E ,  \\\\E  end either case modification or quoted section.  Examples:    {{variable}/test/text}  replaces all occurrences of  test  by  text .  {TEXT/.+/\\\\L$0}  converts text to lower case.  {012345/.#{2}(.#{3}).*/$1}  extracts the substring at index 2 and length 3 resulting in  234 .       Note the escaping  #{ .  The text parser also evaluates terms in the form  {expression:format}  and replaces it by a formatted output. In order not to get confused with the regex replacements, the \\' / \\' character must be escaped with \\' #/ \\' in the expression. The  format  contains the text to be written as output. It can contain embedded format specifiers that are replaced by the value of the expression and formatted as requested (also multiple times). In the following, the resulting formatted output is given in the brackets for an expression with the example value of 57493.8:    %i : Integer [57494]  %f : Decimal floating point [57493.800000]  %e : Scientific notation [5.749380e+04]  %g : Use the shortest representation:  %e  or  %f  [57493.8]  %c : Interpret number as ASCII character  %% : Write a single literal  %  character   The following specifiers interpret the value of the expression as MJD (modified Julian date):    %y : Four digit year [2016]  %Y : Two digit year [16]  %m : Month [04]  %d : Day of month [15]  %H : Hour [19]  %M : Minute [12]  %S : Second [00]  %D : Date (same as  %y-%m-%d ) [2016-04-15]  %T : Time (same as  %H-%M-%S ) [19-12-00]  %W : GPS week [1892]  %w : Day of GPS week (0..6) [5]  %O : Day of year (1..366)   The format can be specified further with  %[width][.precision]specifier , where  [width]  is the minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces (or zeros if  [width]  starts with a zero). The  [.precision]  defines the number of digits after the period (for  %g  the number of significant digits instead). Example: Two variables  time = 57493+19/24+12/1440  and  satellite = swarm  are set in the global section. The  inputfile = data/{time:%y}/{satellite}_{time:%D}.dat  is expanded to  \"data/2016/swarm_2016-04-15.dat\" . Example: The variable  x = 3+5  is set in the global section. The expression  number = 2*x  is evaluated by the expression parser to  =16 . In contrast if we use brackets like in  number = 2*{x}  the expression is first evaluated by the text parser to  \"2*3+5\"  and the expression parser now gives the result  =11 .    Some programs (e.g.  FunctionsCalculate ,  InstrumentArcCalculate ,  GriddedDataCalculate , or the plot programs) read data ( matrix ) or  gridded data  and evaluate input/output expressions for each data row. For these kind of expressions additional variables are automatically defined for each data column ( X  stands for the data column number:  ):    index : the row number, starting with zero  dataX : the value itself  dataXcount : number of rows  dataXmin   dataXmax   dataXsum   dataXmean   dataXrms : root mean square  dataXstd : standard deviation  dataXmedian   dataXmad : median absolute deviation  dataXstep : the minimal difference between two neighboring data points in the column   For  gridded data  input the following variables are additionally defined for each data point:    longitude  in degrees  latitude  in degrees  height  in meters  cartesianX  coordinate in meters  cartesianY  coordinate in meters  cartesianZ  coordinate in meters  area  of the unit sphere  dataXwmean : area-weighted mean  dataXwrms : area-weighted root mean square  dataXwstd : area-weighted standard deviation    The XML configuration file is evaluated by two parsers. In a first step a text parser is applied. In the second step mathematical expressions are resolved to a number. Variables (see section  variables ) can be referenced via their name directly for the expression parser or in the form  {name}  for the text parser.', 'config_table': '', 'display_text': 'The XML configuration file is evaluated by two parsers. In a first step a text parser is applied. In the second step mathematical expressions are resolved to a number. Variables (see section <a class=\"groops-ref\" href=\"general.configFiles.html#variables\">variables</a>) can be referenced via their name directly for the expression parser or in the form <code>{name}</code> for the text parser.</p><p><h2 id=\"expression\">Mathematical expression parser</h2><p> In all input fields that accept numbers (int, uint, double, angle, time) numerical expressions are also allowed. Declared variables can be accessed via their name. The following operations and functions are defined: <ul>  <li>Constants:    <code>pi()</code>, <code>rho()=180/pi()</code>, <code>nan()</code>, <code>c()</code>: light velocity,                     <code>G()</code>: gravitational constant, <code>GM()</code>: gravitational constant of the Earth, <code>R()</code>: reference radius of the Earth </li><li> Mathematical: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>^</code> </li><li> Comparison:   <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&lt;=</code>, <code>></code>, <code>>=</code>, result is 1 or 0 </li><li> Logical:      not <code>!</code>, and <code>&&</code>, <code>||</code>, or <code>isnan(x)</code>, result is 1 or 0 </li><li> Functions:    <code>sqrt(x)</code>, <code>exp(x)</code>,                     <code>sin(x)</code>,  <code>cos(x)</code>, <code>tan(x)</code>,                     <code>asin(x)</code>,  <code>acos(x)</code>,  <code>atan(x)</code>,                     <code>abs(x)</code>,  <code>round(x)</code>,  <code>ceil(x)</code>,  <code>floor(x)</code>,                     <code>deg2rad(x)</code>, <code>rad2deg(x)</code> </li><li> Functions with 2 arguments: <code>atan2(y,x)</code>, <code>min(x,y)</code>, <code>max(x,y)</code>, <code>mod(x,y)</code> </li><li> Time functions: <code>now()</code>: local time in MJD, <code>date2mjd(year, month, day)</code>, <code>gps2utc(mjd)</code>, <code>utc2gps(mjd)</code>, <code>dayofyear(mjd)</code>, <code>decimalyear(mjd)</code> </li><li> Condition: <code>if(c,x,y)</code>: If the first argument is true (not 0), the second argument is evaluated, otherwise the third. </li></ul> </p><p> <h2 id=\"text\">Text parser</h2><p> Before the mathematical expression parser evaluates the expression, a simple text parser is applied. The text parser is used for all input fields (also file names). It scans the text for terms like <code>{variable}</code> and replaces it by the text content of the <code>variable</code>. A literal \\'<code>{</code>\\' character must be escaped with \\'<code>#{</code>\\'.</p><p>The text parser allows regex replacements in the form <code>{text/regex/replace}</code>. All matches of <code>regex</code> in the <code>text</code> are replaced by <code>replace</code>. Possible <code>{variables}</code> in the three parts are evaluated beforehand. Capturing groups <code>()</code> can be accessed by <code>$1</code>, <code>$2</code>, in the replacement (<code>$0</code> is the complete match). Additional escape sequences are: <ul>  <li><code>\\\\l</code> lowercase next char, </li><li> <code>\\\\u</code> uppercase next char, </li><li> <code>\\\\L</code> lowercase until <code>\\\\E</code>, </li><li> <code>\\\\U</code> uppercase until <code>\\\\E</code>, </li><li> <code>\\\\Q</code> quote (disable) pattern metacharacters until <code>\\\\E</code>, </li><li> <code>\\\\E</code> end either case modification or quoted section. </li></ul> </p><p>Examples: <ul>  <li><code>{{variable}/test/text}</code> replaces all occurrences of <code>test</code> by <code>text</code>. </li><li> <code>{TEXT/.+/\\\\L$0}</code> converts text to lower case. </li><li> <code>{012345/.#{2}(.#{3}).*/$1}</code> extracts the substring at index 2 and length 3 resulting in <code>234</code>.       Note the escaping <code>#{</code>. </li></ul> </p><p>The text parser also evaluates terms in the form <code>{expression:format}</code> and replaces it by a formatted output. In order not to get confused with the regex replacements, the \\'<code>/</code>\\' character must be escaped with \\'<code>#/</code>\\' in the expression. The <code>format</code> contains the text to be written as output. It can contain embedded format specifiers that are replaced by the value of the expression and formatted as requested (also multiple times). In the following, the resulting formatted output is given in the brackets for an expression with the example value of 57493.8: <ul>  <li><code>%i</code>: Integer [57494] </li><li> <code>%f</code>: Decimal floating point [57493.800000] </li><li> <code>%e</code>: Scientific notation [5.749380e+04] </li><li> <code>%g</code>: Use the shortest representation: <code>%e</code> or <code>%f</code> [57493.8] </li><li> <code>%c</code>: Interpret number as ASCII character </li><li> <code>%%</code>: Write a single literal <code>%</code> character </li></ul>  The following specifiers interpret the value of the expression as MJD (modified Julian date): <ul>  <li><code>%y</code>: Four digit year [2016] </li><li> <code>%Y</code>: Two digit year [16] </li><li> <code>%m</code>: Month [04] </li><li> <code>%d</code>: Day of month [15] </li><li> <code>%H</code>: Hour [19] </li><li> <code>%M</code>: Minute [12] </li><li> <code>%S</code>: Second [00] </li><li> <code>%D</code>: Date (same as <code>%y-%m-%d</code>) [2016-04-15] </li><li> <code>%T</code>: Time (same as <code>%H-%M-%S</code>) [19-12-00] </li><li> <code>%W</code>: GPS week [1892] </li><li> <code>%w</code>: Day of GPS week (0..6) [5] </li><li> <code>%O</code>: Day of year (1..366) </li></ul>  The format can be specified further with <code>%[width][.precision]specifier</code>, where <code>[width]</code> is the minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces (or zeros if <code>[width]</code> starts with a zero). The <code>[.precision]</code> defines the number of digits after the period (for <code>%g</code> the number of significant digits instead).</p><p>Example: Two variables <strong class=\"groops-config-element\">time</strong>=<code>57493+19/24+12/1440</code> and <strong class=\"groops-config-element\">satellite</strong>=<code>swarm</code> are set in the global section. The <strong class=\"groops-config-element\">inputfile</strong>=<code>data/{time:%y}/{satellite}_{time:%D}.dat</code> is expanded to <code>\"data/2016/swarm_2016-04-15.dat\"</code>.</p><p>Example: The variable <strong class=\"groops-config-element\">x</strong>=<code>3+5</code> is set in the global section. The expression <strong class=\"groops-config-element\">number</strong>=<code>2*x</code> is evaluated by the expression parser to <code>=16</code>. In contrast if we use brackets like in <strong class=\"groops-config-element\">number</strong>=<code>2*{x}</code> the expression is first evaluated by the text parser to <code>\"2*3+5\"</code> and the expression parser now gives the result <code>=11</code>.</p><p> <h2 id=\"dataVariables\">Variables for data</h2><p> Some programs (e.g. <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>, <a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>, or the plot programs) read data (<a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>) or <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a> and evaluate input/output expressions for each data row. For these kind of expressions additional variables are automatically defined for each data column (<code>X</code> stands for the data column number: $0\\\\ldots n$): <ul>  <li><code>index</code>: the row number, starting with zero </li><li> <code>dataX</code>: the value itself </li><li> <code>dataXcount</code>: number of rows </li><li> <code>dataXmin</code> </li><li> <code>dataXmax</code> </li><li> <code>dataXsum</code> </li><li> <code>dataXmean</code> </li><li> <code>dataXrms</code>: root mean square </li><li> <code>dataXstd</code>: standard deviation </li><li> <code>dataXmedian</code> </li><li> <code>dataXmad</code>: median absolute deviation </li><li> <code>dataXstep</code>: the minimal difference between two neighboring data points in the column </li></ul>  For <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a> input the following variables are additionally defined for each data point: <ul>  <li><code>longitude</code> in degrees </li><li> <code>latitude</code> in degrees </li><li> <code>height</code> in meters </li><li> <code>cartesianX</code> coordinate in meters </li><li> <code>cartesianY</code> coordinate in meters </li><li> <code>cartesianZ</code> coordinate in meters </li><li> <code>area</code> of the unit sphere </li><li> <code>dataXwmean</code>: area-weighted mean </li><li> <code>dataXwrms</code>: area-weighted root mean square </li><li> <code>dataXwstd</code>: area-weighted standard deviation </li></ul> </p><p>'},\n'general.loopsAndConditions': { 'name': 'general.loopsAndConditions', 'key': 'general.loopsAndConditions', 'description': 'The program flow within a config file can be controlled by the classes  section  and  section . The easiest way to access these classes is with the programs  LoopPrograms  and  IfPrograms . The programs defined in  IfPrograms  are only executed if the defined  section  is met. A typical example is to check whether a file that should have been created in previous programs actually exists. Further options are string comparisons and checking the result of a numerical expression or the return value of an external command. With  LoopPrograms  it is possible to repeat the programs defined inside within a loop. The class  section  creates a sequence to loop over and defines  variables  that contain the index and element for the current iteration. The  section  and  section  can also be attributed to single config elements (including programs). Config elements with an assigned loop are repeated, with the loop variables being evaluated for each element. If a  section  is attributed to a config element in addition to a loop, each element within the loop is only created if the condition is met. Conditions can also be attributed to optional elements without an associated loop. If the condition is not met, the optional element will be treated as if it was not provided. Example: A program needs all files in a download directory as input. All the  inputfile s can be selected manually of course, but it is much easier to assign a loop variable with  inputfile = {loopFile}  and attribute a  section . The loop lists the content of the download directory and assigns each file name to the  variableLoopFile = loopFile .', 'config_table': '', 'display_text': 'The program flow within a config file can be controlled by the classes <a class=\"groops-class\" href=\"loopType.html\">loop</a> and <a class=\"groops-class\" href=\"conditionType.html\">condition</a>. The easiest way to access these classes is with the programs <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> and <a class=\"groops-program\" href=\"IfPrograms.html\">IfPrograms</a>.</p><p>The programs defined in <a class=\"groops-program\" href=\"IfPrograms.html\">IfPrograms</a> are only executed if the defined <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is met. A typical example is to check whether a file that should have been created in previous programs actually exists. Further options are string comparisons and checking the result of a numerical expression or the return value of an external command.</p><p>With <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> it is possible to repeat the programs defined inside within a loop. The class <a class=\"groops-class\" href=\"loopType.html\">loop</a> creates a sequence to loop over and defines <a class=\"groops-ref\" href=\"general.parser.html\">variables</a> that contain the index and element for the current iteration.</p><p>The <a class=\"groops-class\" href=\"loopType.html\">loop</a> and <a class=\"groops-class\" href=\"conditionType.html\">condition</a> can also be attributed to single config elements (including programs). Config elements with an assigned loop are repeated, with the loop variables being evaluated for each element. If a <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is attributed to a config element in addition to a loop, each element within the loop is only created if the condition is met. Conditions can also be attributed to optional elements without an associated loop. If the condition is not met, the optional element will be treated as if it was not provided.</p><p>Example: A program needs all files in a download directory as input. All the <strong class=\"groops-config-element\">inputfile</strong>s can be selected manually of course, but it is much easier to assign a loop variable with <strong class=\"groops-config-element\">inputfile</strong>=<code>{loopFile}</code> and attribute a <a class=\"groops-class\" href=\"loopType.html#directoryListing\">loop:directoryListing</a>. The loop lists the content of the download directory and assigns each file name to the <strong class=\"groops-config-element\">variableLoopFile</strong>=<code>loopFile</code>.'},\n'general.gui': { 'name': 'general.gui', 'key': 'general.gui', 'description': 'The graphical user interface program  groopsGui  enables the convenient creation of GROOPS config files. It uses the   for cross-platform support. The GUI depends on an XSD schema file containing the complete formal (computer readable) description of a GROOPS config file. This schema file can be created with the command:     groops --xsd &lt;groopsDir>/groops.xsd   At least one schema file has to be set via the menu  Settings - Default Paths and Files . Setting more than one schema files enables the  schema selector  in the toolbar. The selected schema will be used when (re-)opening or creating a config file. This feature is useful when working with different versions of GROOPS at the same time. It is possible to set a  template file  via the menu  Settings - Default Paths and Files . This can be any GROOPS config file. Whenever a new config file is created via the GUI, all global elements and programs defined in the template file are automatically created in the new config file. It is highly recommended to create a template file containing at least the global element  groopsDataDir  of type  filename . This element is used as a  variable  in most default file paths throughout many GROOPS programs. Thus, setting the path to the base directory containing all GROOPS data once in the template file, for example as  groopsDataDir = /home/&lt;user>/groops/data , is the most convenient way to handle default paths in GROOPS. The template file can also contain other often-used global elements, for example  tmpDir  or   timeStart  and   timeEnd . A  working directory  can be set via  Settings - Default Paths and Files . This directory is used as the default directory in the save dialog of new config files. The GUI offers the option to open the GROOPS documentation for a selected program. To use this feature, the GROOPS documentation must be generated (if not already present) with the command:     groops --doc &lt;groopsDir>/docs/   In the menu  Settings - Default Paths and Files  the path to the HTML version of the documentation must be set (i.e.  &lt;groopsDir>/docs/html ). Selecting any program and pressing  F1  opens the documentation for this program in an external browser. Pressing  F1  without having any program selected opens the main page of the GROOPS documentation. Executing a config file from the GUI requires the setup of a run command in the menu  Settings - Commands . It is recommended for this command to open a new terminal in which GROOPS is executed with the config file given as an argument. The placeholders  %w  and  %f  are replaced by the directory and file name of the selected config file, respectively. Multiple commands can be set up, with the option to choose one of them in the run dialog. Example commands:   \t Windows:  cd /d %w && groops.exe %f  \t Linux (KDE):  konsole --workdir %w -e bash -ic \"groops %f; bash\"  \t Linux (GNOME):  gnome-terminal --working-directory=%w -x bash -ic \"groops %f; bash\"  \t Windows, MPI with 4 processes:  cd /d %w && mpiexec -n 4 groopsMPI.exe %f  \t Linux (KDE), MPI with 4 processes:  konsole --workdir %w -e bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"  \t Linux (GNOME), MPI with 4 processes:  gnome-terminal --working-directory=%w -x bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"   Most basic features used to manipulate a config element are accessible via the context menu, for example attributing  loops and conditions  or setting an element global. Global elements automatically appear in the dropdown value list of config elements of the same type. Selecting a global element from the dropdown list as a value links this config element to the global element. In case the global element is removed, all linked elements\\' values are replaced by the value of the deleted global element. The sidebar features three widgets:   \t Open Files : An overview of all open config files (select to change current tree) \t Program List : A list of all programs defined in the schema of the active tree (filterable, supports drag and drop to tree, double click appends program) \t Undo Stack : Tracks all changes in a config file (select to change state of tree)  In case the names of programs or config elements change over time, the GUI offers a rename feature to update outdated config files. The changes must be documented in the schema using GROOPS\\' rename feature. Affected elements will be marked with an icon and the context menu item  Update name  will be available to change the element to the new name defined in the schema.  \t Tree navigation: \t  \t\t Enter : Switch focus from tree to input field of selected row \t\t Escape : Switch focus from input field back to tree \t\t Tab : Next sibling element (or next sibling of parent if there is no next sibling, or next child otherwise) \t\t Shift+Tab : Previous sibling element (or parent if there is no previous sibling) \t\t Ctrl+Tab : Next tab/tree \t\t Ctrl+Shift+Tab : Previous tab/tree \t\t Ctrl+Space : Interact with the element (e.g. filename/program: open dialog; time: switch focus between input fields) \t\t Ctrl+Up/Down : Next/previous sibling element \t\t Ctrl+Left/Right : Fold/expand (complex) element \t  \t Tree manipulation: \t  \t\t Ctrl+Shift+Up/Down : Move unbounded list element (e.g. program, layer) up/down \t  \t Drag and Drop of tabs to other programs (i.e. text editors) or other GUI windows: \t  \t\t Drag : Copy tab (= keep in source window) \t\t Shift+Drag : Move tab (= remove from source window) \t  \t Drag and Drop GROOPS config file(s) into GUI: \t  \t\t Drag : Open file(s) in new tab(s) \t\t Shift+Drag : Open file in current tab (replaces current tab, only works with a single file)', 'config_table': '', 'display_text': '</p><p>The graphical user interface program <code>groopsGui</code> enables the convenient creation of GROOPS config files. It uses the <a href=\"https://qt.io\">Qt5 framework</a> for cross-platform support.</p><p></p><p><h2>Settings and first-time setup</h2><p></p><p>The GUI depends on an XSD schema file containing the complete formal (computer readable) description of a GROOPS config file. This schema file can be created with the command: <pre>   groops --xsd &lt;groopsDir>/groops.xsd </pre> At least one schema file has to be set via the menu <code>Settings - Default Paths and Files</code>. Setting more than one schema files enables the <em>schema selector</em> in the toolbar. The selected schema will be used when (re-)opening or creating a config file. This feature is useful when working with different versions of GROOPS at the same time.</p><p>It is possible to set a <em>template file</em> via the menu <code>Settings - Default Paths and Files</code>. This can be any GROOPS config file. Whenever a new config file is created via the GUI, all global elements and programs defined in the template file are automatically created in the new config file. It is highly recommended to create a template file containing at least the global element <code>groopsDataDir</code> of type <code>filename</code>. This element is used as a <a class=\"groops-ref\" href=\"general.parser.html\">variable</a> in most default file paths throughout many GROOPS programs. Thus, setting the path to the base directory containing all GROOPS data once in the template file, for example as <strong class=\"groops-config-element\">groopsDataDir</strong>=<code>/home/&lt;user>/groops/data</code>, is the most convenient way to handle default paths in GROOPS. The template file can also contain other often-used global elements, for example <code>tmpDir</code> or  <code>timeStart</code> and  <code>timeEnd</code>.</p><p>A <em>working directory</em> can be set via <code>Settings - Default Paths and Files</code>. This directory is used as the default directory in the save dialog of new config files.</p><p>The GUI offers the option to open the GROOPS documentation for a selected program. To use this feature, the GROOPS documentation must be generated (if not already present) with the command: <pre>   groops --doc &lt;groopsDir>/docs/ </pre> In the menu <code>Settings - Default Paths and Files</code> the path to the HTML version of the documentation must be set (i.e. <code>&lt;groopsDir>/docs/html</code>). Selecting any program and pressing <code>F1</code> opens the documentation for this program in an external browser. Pressing <code>F1</code> without having any program selected opens the main page of the GROOPS documentation.</p><p>Executing a config file from the GUI requires the setup of a run command in the menu <code>Settings - Commands</code>. It is recommended for this command to open a new terminal in which GROOPS is executed with the config file given as an argument. The placeholders <code>%w</code> and <code>%f</code> are replaced by the directory and file name of the selected config file, respectively. Multiple commands can be set up, with the option to choose one of them in the run dialog.</p><p>Example commands: <ul>  \t<li>Windows: <code>cd /d %w && groops.exe %f</code> \t</li><li> Linux (KDE): <code>konsole --workdir %w -e bash -ic \"groops %f; bash\"</code> \t</li><li> Linux (GNOME): <code>gnome-terminal --working-directory=%w -x bash -ic \"groops %f; bash\"</code> \t</li><li> Windows, MPI with 4 processes: <code>cd /d %w && mpiexec -n 4 groopsMPI.exe %f</code> \t</li><li> Linux (KDE), MPI with 4 processes: <code>konsole --workdir %w -e bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"</code> \t</li><li> Linux (GNOME), MPI with 4 processes: <code>gnome-terminal --working-directory=%w -x bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"</code> </li></ul> </p><p><h2>Basic features</h2><p></p><p>Most basic features used to manipulate a config element are accessible via the context menu, for example attributing <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">loops and conditions</a> or setting an element global. Global elements automatically appear in the dropdown value list of config elements of the same type. Selecting a global element from the dropdown list as a value links this config element to the global element. In case the global element is removed, all linked elements\\' values are replaced by the value of the deleted global element.</p><p>The sidebar features three widgets: <ul>  \t<li><code>Open Files</code>: An overview of all open config files (select to change current tree) \t</li><li> <code>Program List</code>: A list of all programs defined in the schema of the active tree (filterable, supports drag and drop to tree, double click appends program) \t</li><li> <code>Undo Stack</code>: Tracks all changes in a config file (select to change state of tree) </li></ul> </p><p>In case the names of programs or config elements change over time, the GUI offers a rename feature to update outdated config files. The changes must be documented in the schema using GROOPS\\' rename feature. Affected elements will be marked with an icon and the context menu item <code>Update name</code> will be available to change the element to the new name defined in the schema.</p><p><h2>Additional keyboard shortcuts</h2><p></p><p><ul>  \t<li>Tree navigation: \t<ul>  \t\t</li><li> <code>Enter</code>: Switch focus from tree to input field of selected row \t\t</li><li> <code>Escape</code>: Switch focus from input field back to tree \t\t</li><li> <code>Tab</code>: Next sibling element (or next sibling of parent if there is no next sibling, or next child otherwise) \t\t</li><li> <code>Shift+Tab</code>: Previous sibling element (or parent if there is no previous sibling) \t\t</li><li> <code>Ctrl+Tab</code>: Next tab/tree \t\t</li><li> <code>Ctrl+Shift+Tab</code>: Previous tab/tree \t\t</li><li> <code>Ctrl+Space</code>: Interact with the element (e.g. filename/program: open dialog; time: switch focus between input fields) \t\t</li><li> <code>Ctrl+Up/Down</code>: Next/previous sibling element \t\t</li><li> <code>Ctrl+Left/Right</code>: Fold/expand (complex) element \t</li></ul>  \t<li>Tree manipulation: \t<ul>  \t\t</li><li> <code>Ctrl+Shift+Up/Down</code>: Move unbounded list element (e.g. program, layer) up/down \t</li></ul>  \t<li>Drag and Drop of tabs to other programs (i.e. text editors) or other GUI windows: \t<ul>  \t\t</li><li> <code>Drag</code>: Copy tab (= keep in source window) \t\t</li><li> <code>Shift+Drag</code>: Move tab (= remove from source window) \t</li></ul>  \t<li>Drag and Drop GROOPS config file(s) into GUI: \t<ul>  \t\t</li><li> <code>Drag</code>: Open file(s) in new tab(s) \t\t</li><li> <code>Shift+Drag</code>: Open file in current tab (replaces current tab, only works with a single file) \t</li></ul>  </ul>'},\n'general.constants': { 'name': 'general.constants', 'key': 'general.constants', 'description': 'GROOPS uses some built-in constants like  DEFAULT_GM  or the definition of leap seconds, which are defined in   source/base/constants.cpp . A complete list of the constants can be written to an XML file with:     groops --write-settings &lt;groopsDefaults.xml>  The built-in constants can be overwritten by a  groopsDefaults.xml  file in the working directory or by explicitly passing the file as an argument at execution:     groops --settings &lt;groopsDefaults.xml> &lt;config.xml>  It might also be useful to adjust the default values in the schema file used by the  GUI :     groops --settings &lt;groopsDefaults.xml> --xsd &lt;groops.xsd>  Example file:   &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops>   &lt;LIGHT_VELOCITY>299792458&lt;/LIGHT_VELOCITY>   &lt;DEFAULT_GM>3.986004415e+14&lt;/DEFAULT_GM>   &lt;DEFAULT_R>6378136.3&lt;/DEFAULT_R>   &lt;GRS80_a>6378137.0&lt;/GRS80_a>   &lt;GRS80_f>298.2572221010&lt;/GRS80_f>   &lt;GRAVITATIONALCONSTANT>6.6730e-11&lt;/GRAVITATIONALCONSTANT>   &lt;R_Earth>6.37813630000000e+06&lt;/R_Earth>   &lt;R_Moon>1.73800000000000e+06&lt;/R_Moon>   &lt;GM_Earth>3.98600441500000e+14&lt;/GM_Earth>   &lt;GM_Sun>1.32712442076000e+20&lt;/GM_Sun>   &lt;GM_Moon>4.90280105600000e+12&lt;/GM_Moon>   &lt;GM_MERCURY>2.20320808280762e+13&lt;/GM_MERCURY>   &lt;GM_VENUS>3.24858603864143e+14&lt;/GM_VENUS>   &lt;GM_MARS>4.28283149222192e+13&lt;/GM_MARS>   &lt;GM_JUPITER>1.26712769822770e+17&lt;/GM_JUPITER>   &lt;GM_SATURN>3.79406266494906e+16&lt;/GM_SATURN>   &lt;TIME_EPSILON>1.0e-05&lt;/TIME_EPSILON>   &lt;DELTA_TAI_GPS>19&lt;/DELTA_TAI_GPS>   &lt;DELTA_TT_GPS>51.184&lt;/DELTA_TT_GPS>   &lt;J2000>51544.5&lt;/J2000>   &lt;leapSecond>     &lt;MJD>57754&lt;/MJD>     &lt;DELTA_UTC_GPS>-18&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   &lt;leapSecond>     &lt;MJD>57204&lt;/MJD>     &lt;DELTA_UTC_GPS>-17&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   &lt;leapSecond>     &lt;MJD>56109&lt;/MJD>     &lt;DELTA_UTC_GPS>-16&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   ...   &lt;leapSecond>     &lt;MJD>41317&lt;/MJD>     &lt;DELTA_UTC_GPS>9&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   &lt;leapSecond>     &lt;MJD>0&lt;/MJD>     &lt;DELTA_UTC_GPS>10&lt;/DELTA_UTC_GPS>   &lt;/leapSecond> &lt;/groops>', 'config_table': '', 'display_text': 'GROOPS uses some built-in constants like <code>DEFAULT_GM</code> or the definition of leap seconds, which are defined in  <code>source/base/constants.cpp</code>.</p><p>A complete list of the constants can be written to an XML file with: <pre>   groops --write-settings &lt;groopsDefaults.xml> </pre></p><p>The built-in constants can be overwritten by a <code>groopsDefaults.xml</code> file in the working directory or by explicitly passing the file as an argument at execution: <pre>   groops --settings &lt;groopsDefaults.xml> &lt;config.xml> </pre></p><p>It might also be useful to adjust the default values in the schema file used by the <a class=\"groops-ref\" href=\"general.gui.html\">GUI</a>: <pre>   groops --settings &lt;groopsDefaults.xml> --xsd &lt;groops.xsd> </pre></p><p>Example file: <pre> &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops>   &lt;LIGHT_VELOCITY>299792458&lt;/LIGHT_VELOCITY>   &lt;DEFAULT_GM>3.986004415e+14&lt;/DEFAULT_GM>   &lt;DEFAULT_R>6378136.3&lt;/DEFAULT_R>   &lt;GRS80_a>6378137.0&lt;/GRS80_a>   &lt;GRS80_f>298.2572221010&lt;/GRS80_f>   &lt;GRAVITATIONALCONSTANT>6.6730e-11&lt;/GRAVITATIONALCONSTANT>   &lt;R_Earth>6.37813630000000e+06&lt;/R_Earth>   &lt;R_Moon>1.73800000000000e+06&lt;/R_Moon>   &lt;GM_Earth>3.98600441500000e+14&lt;/GM_Earth>   &lt;GM_Sun>1.32712442076000e+20&lt;/GM_Sun>   &lt;GM_Moon>4.90280105600000e+12&lt;/GM_Moon>   &lt;GM_MERCURY>2.20320808280762e+13&lt;/GM_MERCURY>   &lt;GM_VENUS>3.24858603864143e+14&lt;/GM_VENUS>   &lt;GM_MARS>4.28283149222192e+13&lt;/GM_MARS>   &lt;GM_JUPITER>1.26712769822770e+17&lt;/GM_JUPITER>   &lt;GM_SATURN>3.79406266494906e+16&lt;/GM_SATURN>   &lt;TIME_EPSILON>1.0e-05&lt;/TIME_EPSILON>   &lt;DELTA_TAI_GPS>19&lt;/DELTA_TAI_GPS>   &lt;DELTA_TT_GPS>51.184&lt;/DELTA_TT_GPS>   &lt;J2000>51544.5&lt;/J2000>   &lt;leapSecond>     &lt;MJD>57754&lt;/MJD>     &lt;DELTA_UTC_GPS>-18&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   &lt;leapSecond>     &lt;MJD>57204&lt;/MJD>     &lt;DELTA_UTC_GPS>-17&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   &lt;leapSecond>     &lt;MJD>56109&lt;/MJD>     &lt;DELTA_UTC_GPS>-16&lt;/DELTA_UTC_GPS>   &lt;/leapSecond></p><p>  ...</p><p>  &lt;leapSecond>     &lt;MJD>41317&lt;/MJD>     &lt;DELTA_UTC_GPS>9&lt;/DELTA_UTC_GPS>   &lt;/leapSecond>   &lt;leapSecond>     &lt;MJD>0&lt;/MJD>     &lt;DELTA_UTC_GPS>10&lt;/DELTA_UTC_GPS>   &lt;/leapSecond> &lt;/groops> </pre>'},\n'general.parallelization': { 'name': 'general.parallelization', 'key': 'general.parallelization', 'description': 'If GROOPS is compiled with the   (MPI), most GROOPS  programs  can be run in parallel on multiple processor cores. Processing on computer clusters with distributed memory is also supported. Many loops are parallelized by computing each loop step at a different core. Usually the first node distributes the work load, assigns loop steps to different cores, and is not participating on the actual loop computation. This means running GROOPS with only two nodes has no advantages in almost all cases. Non-parallel parts and  programs  without parallel support are executed at the first node only. Large systems of  normal equations , which are divided into blocks, are distributed over the nodes to reduce the memory consumption on each single node. As all nodes may read and write files (at least reading the  config files ) the required part of the file system must be available on all participating computers.', 'config_table': '', 'display_text': 'If GROOPS is compiled with the <a href=\"https://en.wikipedia.org/wiki/Message_Passing_Interface\">Message Passing Interface</a> (MPI), most GROOPS <a class=\"groops-ref\" href=\"programType.html\">programs</a> can be run in parallel on multiple processor cores. Processing on computer clusters with distributed memory is also supported.</p><p>Many loops are parallelized by computing each loop step at a different core. Usually the first node distributes the work load, assigns loop steps to different cores, and is not participating on the actual loop computation. This means running GROOPS with only two nodes has no advantages in almost all cases. Non-parallel parts and <a class=\"groops-ref\" href=\"programType.html\">programs</a> without parallel support are executed at the first node only.</p><p>Large systems of <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a>, which are divided into blocks, are distributed over the nodes to reduce the memory consumption on each single node.</p><p>As all nodes may read and write files (at least reading the <a class=\"groops-ref\" href=\"general.configFiles.html\">config files</a>) the required part of the file system must be available on all participating computers.'},\n'fundamentals.robustLeastSquares': { 'name': 'fundamentals.robustLeastSquares', 'key': 'fundamentals.robustLeastSquares', 'description': 'The robust least squares adjustment used in GROOPS is based on a modified Huber estimator. It downweights observations with large otuliers iteratively. The algorithm starts with a first solution with equal weights    The solution is used to compute the residuals  and the redundancies of all observations  For observations with large residuals a new standard deviation is assigned  where   is  huber ,   is  huberPower , and   a robust overall variance factor computed from all residuals. The estimation is repeated  huberMaxIteration  times with a new weight matrix   or until convergence is reached.', 'config_table': '', 'display_text': 'The robust least squares adjustment used in GROOPS is based on a modified Huber estimator. It downweights observations with large otuliers iteratively.</p><p>The algorithm starts with a first solution with equal weights $\\\\M P =\\\\M I$ \\\\[   \\\\hat{\\\\M x} = (\\\\M A^T\\\\M P\\\\M A)^{-1}\\\\M A^T\\\\M P\\\\M l. \\\\]The solution is used to compute the residuals \\\\[   \\\\hat{e}_i = \\\\left(\\\\M l - \\\\M A \\\\hat{\\\\M x}\\\\right)_i \\\\]and the redundancies of all observations \\\\[   r_i = \\\\left(\\\\M I - \\\\M A(\\\\M A^T\\\\M P\\\\M A)^{-1}\\\\M A^T\\\\M P\\\\right)_{ii}. \\\\]For observations with large residuals a new standard deviation is assigned \\\\[   \\\\sigma_i =   \\\\begin{cases}     1                                     & \\\\text{for } \\\\left|\\\\frac{\\\\hat{e}_i}{r_i}\\\\right| \\\\le h\\\\cdot\\\\hat{\\\\sigma} \\\\\\\\     \\\\left|\\\\frac{\\\\hat{e}_i}{r_ih}\\\\right|^p & \\\\text{for } \\\\left|\\\\frac{\\\\hat{e}_i}{r_i}\\\\right| > h\\\\cdot\\\\hat{\\\\sigma},   \\\\end{cases} \\\\]where $h$ is <strong class=\"groops-config-element\">huber</strong>, $p$ is <strong class=\"groops-config-element\">huberPower</strong>, and $\\\\hat{\\\\sigma}^2$ a robust overall variance factor computed from all residuals. The estimation is repeated <strong class=\"groops-config-element\">huberMaxIteration</strong> times with a new weight matrix \\\\[   \\\\M P = \\\\text{diag}\\\\left(\\\\frac{1}{\\\\sigma_1^2}, \\\\frac{1}{\\\\sigma_2^2}, \\\\ldots, \\\\frac{1}{\\\\sigma_n^2}\\\\right) \\\\] or until convergence is reached.'},\n'fundamentals.basisSplines': { 'name': 'fundamentals.basisSplines', 'key': 'fundamentals.basisSplines', 'description': 'A time variable function is given by  with the (spatial) coefficients   as parameters and the temporal basis functions  . Basis splines are defined as polynomials of degree   in intervals between nodal points in time  :    Block mean values ( )  Linear splines ( )  Quadratic splines ( )  Cubic splines ( )   where   is the normlized time in each time interval  The total number of coefficients   is  , where   is the count of nodal time points   and   is the degree.', 'config_table': '', 'display_text': 'A time variable function is given by \\\\[ f(x,t) =  \\\\sum_i f_i(x)\\\\Psi_i(t), \\\\]with the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions $\\\\Psi_i(t)$. Basis splines are defined as polynomials of degree $n$ in intervals between nodal points in time $t_i$: <ul>  <li>Block mean values ($n=0$) \\\\[   \\\\Psi_i(t) = \\\\begin{cases}   1 & \\\\text{if } t\\\\in[t_i,t_{i+1}), \\\\\\\\   0 & \\\\text{otherwise} \\\\end{cases} \\\\]</li><li> Linear splines ($n=1$) \\\\[   \\\\Psi_i(t) = \\\\begin{cases}     \\\\tau_{i-1}  & \\\\text{if } t_{i-1} \\\\le t \\\\le t_i, \\\\\\\\   1-\\\\tau_i      & \\\\text{if } t_{i}   \\\\le t \\\\le t_{i+1}, \\\\\\\\   0 & \\\\text{otherwise}. \\\\end{cases} \\\\]</li><li> Quadratic splines ($n=2$) \\\\[   \\\\Psi_i(t) = \\\\begin{cases}   \\\\frac{1}{2}\\\\tau^2_{i-1}                           & \\\\text{if } t_{i-1} \\\\le t \\\\le t_i, \\\\\\\\             -\\\\tau^2_{i}   +\\\\tau_{i}   +\\\\frac{1}{2}  & \\\\text{if } t_{i}   \\\\le t \\\\le t_{i+1}, \\\\\\\\   \\\\frac{1}{2}\\\\tau^2_{i+1} -\\\\tau_{i+1} +\\\\frac{1}{2}  & \\\\text{if } t_{i+1} \\\\le t \\\\le t_{i+2}, \\\\\\\\   0 & \\\\text{otherwise}. \\\\end{cases} \\\\]</li><li> Cubic splines ($n=3$) \\\\[   \\\\Psi_i(t) = \\\\begin{cases}    \\\\frac{1}{6}\\\\tau^3_{i-2}                                                               & \\\\text{if } t_{i-2} \\\\le t \\\\le t_{i-1}, \\\\\\\\   -\\\\frac{3}{6}\\\\tau^3_{i-1} +\\\\frac{3}{6}\\\\tau^2_{i-1} +\\\\frac{3}{6}\\\\tau_{i-1} +\\\\frac{1}{6}  & \\\\text{if } t_{i-1} \\\\le t \\\\le t_i,     \\\\\\\\    \\\\frac{3}{6}\\\\tau^3_{i}   -           \\\\tau^2_{i}   +\\\\frac{4}{6}                         & \\\\text{if } t_{i}   \\\\le t \\\\le t_{i+1}, \\\\\\\\   -\\\\frac{1}{6}\\\\tau^3_{i+1} +\\\\frac{3}{6}\\\\tau^2_{i+1} -\\\\frac{3}{6}\\\\tau_{i+1} +\\\\frac{1}{6}  & \\\\text{if } t_{i+1} \\\\le t \\\\le t_{i+2}, \\\\\\\\   0 & \\\\text{otherwise}. \\\\end{cases} \\\\]</li></ul>  where $\\\\tau$ is the normlized time in each time interval \\\\[   \\\\tau_i = \\\\frac{t-t_i}{t_{i+1}-t_i}. \\\\]The total number of coefficients $f_i(x)$ is $N=N_t+n-1$, where $N_t$ is the count of nodal time points $t_i$ and $n$ is the degree.</p><p>'},\n'fundamentals.autoregressiveModel': { 'name': 'fundamentals.autoregressiveModel', 'key': 'fundamentals.autoregressiveModel', 'description': 'A multivariate (or vector) autoregressive model is one possible representation of a random process. It specifies, that the output at epoch   depends on the   previous epochs, where   is denoted process order, plus a stochastic term. In the following, finite order vector autoregressive - VAR( ) in short - models as implemented in GROOPS will be described. A finite order VAR( ) model is defined as  where   are realizations of a random vector process Subtracting the right hand side and substituting the stochastic term   with the residual   gives us  which can be used as pseudo-observation equations in the determination of the parameters  . In matrix notation this reads  After rearranging the vectors   to have ascending time stamps  For practical purposes, the residuals above are further decorrelated using the inverse square root of the white noise covariance matrix, leading to  The used square root is in principle arbitrary, but should satisfy  . This means that both eigendecomposition based roots and Cholesky factors can be used. After the applying the matrix from the left, we arrive at the observation equations  which yields fully decorrelated residuals. Currenty, VAR( ) models are saved to a single  file which contains this matrix.', 'config_table': '', 'display_text': 'A multivariate (or vector) autoregressive model is one possible representation of a random process. It specifies, that the output at epoch $t$ depends on the $p$ previous epochs, where $p$ is denoted process order, plus a stochastic term. In the following, finite order vector autoregressive - VAR($p$) in short - models as implemented in GROOPS will be described.</p><p><h2>Definition</h2><p></p><p>A finite order VAR($p$) model is defined as \\\\[   \\\\mathbf{y}_e(t_i) = \\\\sum_{k=1}^p \\\\mathbf{\\\\Phi}^{(p)}_k\\\\mathbf{y}_e(t_{i-k}) + \\\\mathbf{w}(t_i),   \\\\hspace{5pt} \\\\mathbf{w}(t_i) \\\\sim \\\\mathcal{N}(0, \\\\mathbf{\\\\Sigma}^{(p)}_\\\\mathbf{w}), \\\\]where $\\\\mathbf{y}_e(t_i)$ are realizations of a random vector process Subtracting the right hand side and substituting the stochastic term $-\\\\mathbf{w}(t_i)$ with the residual $\\\\mathbf{v}(t_i)$ gives us \\\\[   \\\\mathbf{0}  = \\\\mathbf{y}_e(t_i) - \\\\sum_{k=1}^p \\\\mathbf{\\\\Phi}^{(p)}_k\\\\mathbf{y}_e(t_{i-k}) + \\\\mathbf{v}(t_i) \\\\]which can be used as pseudo-observation equations in the determination of the parameters $\\\\mathbf{y}_e(t_i)$. In matrix notation this reads \\\\[   0 =   \\\\begin{bmatrix}     \\\\mathbf{I} & -\\\\mathbf{\\\\Phi}^{(p)}_1 & \\\\cdots & -\\\\mathbf{\\\\Phi}^{(p)}_p \\\\\\\\   \\\\end{bmatrix}   \\\\begin{bmatrix}     \\\\mathbf{y}_e(t_i) \\\\\\\\     \\\\mathbf{y}_e(t_{i-1}) \\\\\\\\     \\\\vdots \\\\\\\\     \\\\mathbf{y}_e(t_{i-p}) \\\\\\\\   \\\\end{bmatrix}   + \\\\mathbf{v}(t_i). \\\\]After rearranging the vectors $\\\\mathbf{x}_t$ to have ascending time stamps \\\\[   0 =   \\\\begin{bmatrix}     -\\\\mathbf{\\\\Phi}^{(p)}_p & \\\\cdots & -\\\\mathbf{\\\\Phi}^{(p)}_1 & \\\\mathbf{I} \\\\\\\\   \\\\end{bmatrix}   \\\\begin{bmatrix}     \\\\mathbf{y}_e(t_{i-p}) \\\\\\\\     \\\\vdots \\\\\\\\     \\\\mathbf{y}_e(t_{i-1}) \\\\\\\\     \\\\mathbf{y}_e(t_i) \\\\\\\\   \\\\end{bmatrix}   + \\\\mathbf{v}(t_i) \\\\]For practical purposes, the residuals above are further decorrelated using the inverse square root of the white noise covariance matrix, leading to \\\\[   \\\\bar{\\\\mathbf{v}}(t_i) = \\\\underbrace{\\\\mathbf{\\\\Sigma}^{(p)^{-\\\\frac{1}{2}}}_\\\\mathbf{w}}_{=\\\\mathbf{W}}\\\\mathbf{v}(t_i), \\\\hspace{25pt}  \\\\bar{\\\\mathbf{v}}(t_i) \\\\sim \\\\mathcal{N}(0, \\\\mathbf{I}). \\\\]The used square root is in principle arbitrary, but should satisfy $\\\\mathbf{W}^T\\\\mathbf{W} = \\\\mathbf{\\\\Sigma}^{(p)}_\\\\mathbf{w} $. This means that both eigendecomposition based roots and Cholesky factors can be used. After the applying the matrix from the left, we arrive at the observation equations \\\\[   0 =   \\\\begin{bmatrix}     -\\\\mathbf{W}\\\\mathbf{\\\\Phi}^{(p)}_p & \\\\cdots & -\\\\mathbf{W}\\\\mathbf{\\\\Phi}^{(p)}_1 & \\\\mathbf{W} \\\\\\\\   \\\\end{bmatrix}   \\\\begin{bmatrix}     \\\\mathbf{y}_e(t_{i-p}) \\\\\\\\     \\\\vdots \\\\\\\\     \\\\mathbf{y}_e(t_{i-1}) \\\\\\\\     \\\\mathbf{y}_e(t_i) \\\\\\\\   \\\\end{bmatrix}   + \\\\bar{\\\\mathbf{v}}(t_i) \\\\]which yields fully decorrelated residuals. Currenty, VAR($p$) models are saved to a single  file which contains this matrix.'},\n'cookbook.instrument': { 'name': 'cookbook.instrument', 'key': 'cookbook.instrument', 'description': 'GROOPS provides functions and programs to read/write, preprocess, analyze and visualize uniformly and non-uniformly sampled instrument data. This includes tools for filter design and analysis, re-sampling, smoothing, detrending, and power spectrum estimation. This tutorial goes through exemplary steps for data handling procedures.   GROOPS is able to read and convert relevant data from various LEO and GNSS satellites. Instrument files need to be converted into the respective GROOPS format using conversion programs.Depending on the content of the input file, the data is stored with a specific  section . User also has the option to change the type later on with  InstrumentSetType . Multiple files can be concatenated to one file using  InstrumentConcatenate . Using this program, it is also possible to sort the epochs, remove the duplicates and NaN values.  Example: Concatenating instrument files         Create three successively daily sinusoidal signals with  TimeSeriesCreate  and set their type to MISCVALUE with  InstrumentSetType . In this example, each data set has an overlap of 1 hour with their following dataset.    Merge all datasets to one single file with  InstrumentConcatenate .           Many measurements involve data collected asynchronously by multiple sensors with different sampling. Use  InstrumentSynchronize  for a continuous harmonization of the data over time or segmentation of the data into arcs.   Real-world data is often incomplete, inconsistent, and/or lacking in certain behaviors or trends, and is likely to contain many errors. Data preprocessing is a proven method of resolving such issues. Following steps are usually required to be taken:   Gross outlier removal:        Create reference values to compare the input data with. Depending on the instrument type, this can be done by simulation programs such as  SimulateAccelerometer  or  SimulateStarCamera . If no reference data is available, the outlier detection is based on the data itself. If needed, synchronize the reference data file and the input data with  InstrumentSynchronize .    In case of star camera data, compute the differences between the input data and the reference data with  InstrumentStarCameraMultiply .    Set a threshold for outlier detection in  InstrumentRemoveEpochsByCriteria . The threshold is defined empirically according to the accuracy characteristics of each data products. If the differences exceed a predefined threshold, the corresponding epochs are removed. An arbitrary margin can be defined to additionally remove epochs before and after the identified outliers. It is also possible to remove epochs at specific times using  InstrumentRemoveEpochsByTimes .    Missing epochs can be filled by reference data with  InstrumentConcatenate .    It is also possible to interpolate the missing epochs with  InstrumentResample .    Example: Removing outliers in a synthetic data.         Create a sinusoidal signal with an amplitude of 1.0 using  TimeSeriesCreate  and set its type to MISCVALUE with  InstrumentSetType .    Add zero-mean, white Gaussian noise with a standard deviation of 0.1 with  NoiseInstrument . Interpret this data as a real measurement file.    Set the threshold criteria to 0.2 in  InstrumentRemoveEpochsByCriteria  and remove the outliers and their nearest epochs in 20 second interval.    Fill the data gaps with  InstrumentResample .              Downsampling:        If the sampling is irregular use  InstrumentResample  to make the sampling equidistant.    Use  InstrumentSynchronize  to divide the data at gaps into arcs.    Apply a lowpass filter (e.g. Butterworth) with the Nyquist frequency of the target sampling as cutoff with  InstrumentFilter . Apply the filter in both directions to avoid phase shifts.    Use  InstrumentReduceSampling  to down-sample the data.    Calibration:        For a general instrument file,  InstrumentDetrend  subtracts offsets or linear/nonlinear trends from the input data. This can be achieved also with  FunctionsCalculate  or  InstrumentArcCalculate  by applying determined calibration factors or solving a least-square adjustment.    For accelerometer data,  InstrumentAccelerometerEstimateBiasScale  is designed to estimate and subtract complex biases or scales with respect to simulated accelerometer data. If a thruster file is given, the corresponding epochs are eliminated during estimation process.    Example: GRACE-C accelerometer calibration         For one particular date, read and convert Level-1B GRACE-C orbit, star camera, accelerometer, and thruster data with  GraceL1b2Orbit ,  GraceL1b2StarCamera ,  GraceL1b2Accelerometer , and  GraceL1b2Thruster  respectively. It is also required to read the macro-model data of the satellite using the related information in the official document and convert it to GROOPS format with  SatelliteModelCreate .    Use  SimulateAccelerometer  to generate simulated accelerations due to non-gravitational force models including:  section ,  section , and  section .    Calibrate the real measurements with a daily constant accelerometer bias by choosing a constant parameter per axis in  section .                  InstrumentStatisticsTimeSeries  returns statistics for one or more instrument files.  InstrumentArcCalculate  is also able to generate a  statistics  file with one mid epoch per arc.   Spectral analysis studies the frequency spectrum contained in discrete, uniformly sampled data. The Fourier transform is a tool that reveals frequency components of a signal by representing it in frequency space. The Power Spectral Density (PSD) is a measurement of the energy at each frequency.   If the sampling is irregular use  InstrumentResample  to make the sampling equidistant.  Use  Instrument2PowerSpectralDensity  to compute PSD.  If covariance function of a dataset is available, use  CovarianceFunction2PowerSpectralDensity .  Example: Spectral analysis of a synthetic signal.         Create a sinusoidal signal with an amplitude of 1.0 using  TimeSeriesCreate  and set its type to MISCVALUE with  InstrumentSetType . Interpret this data as a simulation data file.    Add zero-mean, white Gaussian noise with a standard deviation of 0.1 with  NoiseInstrument . Interpret this data as a real measurement file.    Compute PSD of the simulated and measurement data and represent the results with  PlotGraph .              Argument of latitude plot Plotting instrument data as a function of satellite position in orbit and time reveals features related to the orbit geometry or environmental conditions. For circular orbits, the position of  satellite can be specified by the argument of latitude.    Synchronize the instrument data file with the related orbit data using  InstrumentSynchronize .  Use  Orbit2ArgumentOfLatitude  to compute argument of latitude at each epoch.  Plot the instrument data versus argument of latitude and time with  PlotGraph .  Example: Argument of latitude representation of GRACE-C eclipse factors         Compute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using  Orbit2EclipseFactor .    Synchronize the eclipse factor data file with the related orbit data using  InstrumentSynchronize .    Use  Orbit2ArgumentOfLatitude  to compute argument of latitude at each epoch and visualize the results with  PlotGraph .          Ground-track plot Plotting instrument data with respect to the satellite ground track is useful to identify any features of geophysical origin in the data.    Synchronize the instrument data file with the related orbit data using  InstrumentSynchronize .  Use  Orbit2Groundtracks  to map instrument data to satellite ground-track.  Visualize the output with  PlotMap .  Example 6: Ground-track representation of GRACE-C eclipse factors         Compute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using  Orbit2EclipseFactor .    Synchronize the eclipse factor data file with the related orbit data using  InstrumentSynchronize .    Use  Orbit2Groundtracks  to generate the gridded data. Each grid value represents the mean value of eclipse factor over the instrument time period (1 month).  visualize the results with  PlotMap .', 'config_table': '', 'display_text': '</p><p>GROOPS provides functions and programs to read/write, preprocess, analyze and visualize uniformly and non-uniformly sampled instrument data. This includes tools for filter design and analysis, re-sampling, smoothing, detrending, and power spectrum estimation. This tutorial goes through exemplary steps for data handling procedures.</p><p><h2>Reading data</h2><p></p><p><ul>  <li>GROOPS is able to read and convert relevant data from various LEO and GNSS satellites. Instrument files need to be converted into the respective GROOPS format using conversion programs.Depending on the content of the input file, the data is stored with a specific <a class=\"groops-class\" href=\"instrumentTypeType.html\">instrument type</a>. User also has the option to change the type later on with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>.</p><p></li><li> Multiple files can be concatenated to one file using <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>. Using this program, it is also possible to sort the epochs, remove the duplicates and NaN values. </li><li> <em>Example: Concatenating instrument files</em>   <ul>    </li><li> Create three successively daily sinusoidal signals with <a class=\"groops-program\" href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a> and set their type to MISCVALUE with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>. In this example, each data set has an overlap of 1 hour with their following dataset.   </li><li> Merge all datasets to one single file with <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>.      </li></ul>   <li>Many measurements involve data collected asynchronously by multiple sensors with different sampling. Use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a> for a continuous harmonization of the data over time or segmentation of the data into arcs. </li></ul> </p><p><h2>Preprocessing</h2><p> Real-world data is often incomplete, inconsistent, and/or lacking in certain behaviors or trends, and is likely to contain many errors. Data preprocessing is a proven method of resolving such issues. Following steps are usually required to be taken:</p><p><ul>  <li>Gross outlier removal:   <ul>    </li><li> Create reference values to compare the input data with. Depending on the instrument type, this can be done by simulation programs such as <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a> or <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a>. If no reference data is available, the outlier detection is based on the data itself. If needed, synchronize the reference data file and the input data with <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p>  </li><li> In case of star camera data, compute the differences between the input data and the reference data with <a class=\"groops-program\" href=\"InstrumentStarCameraMultiply.html\">InstrumentStarCameraMultiply</a>.</p><p>  </li><li> Set a threshold for outlier detection in <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a>. The threshold is defined empirically according to the accuracy characteristics of each data products. If the differences exceed a predefined threshold, the corresponding epochs are removed. An arbitrary margin can be defined to additionally remove epochs before and after the identified outliers. It is also possible to remove epochs at specific times using <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByTimes.html\">InstrumentRemoveEpochsByTimes</a>.   </li><li> Missing epochs can be filled by reference data with <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>.   </li><li> It is also possible to interpolate the missing epochs with <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>.   </li><li> <em>Example: Removing outliers in a synthetic data.</em>   <ul>    </li><li> Create a sinusoidal signal with an amplitude of 1.0 using <a class=\"groops-program\" href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a> and set its type to MISCVALUE with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>.   </li><li> Add zero-mean, white Gaussian noise with a standard deviation of 0.1 with <a class=\"groops-program\" href=\"NoiseInstrument.html\">NoiseInstrument</a>. Interpret this data as a real measurement file.   </li><li> Set the threshold criteria to 0.2 in <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a> and remove the outliers and their nearest epochs in 20 second interval.   </li><li> Fill the data gaps with <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>.      </li></ul>    </ul></p><p> <li>Downsampling:   <ul>    </li><li> If the sampling is irregular use <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a> to make the sampling equidistant.   </li><li> Use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a> to divide the data at gaps into arcs.   </li><li> Apply a lowpass filter (e.g. Butterworth) with the Nyquist frequency of the target sampling as cutoff with <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a>. Apply the filter in both directions to avoid phase shifts.   </li><li> Use <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a> to down-sample the data.   </li></ul> </p><p><li>Calibration:   <ul>    </li><li> For a general instrument file, <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> subtracts offsets or linear/nonlinear trends from the input data. This can be achieved also with <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a> or <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a> by applying determined calibration factors or solving a least-square adjustment.   </li><li> For accelerometer data, <a class=\"groops-program\" href=\"InstrumentAccelerometerEstimateBiasScale.html\">InstrumentAccelerometerEstimateBiasScale</a> is designed to estimate and subtract complex biases or scales with respect to simulated accelerometer data. If a thruster file is given, the corresponding epochs are eliminated during estimation process.   </li><li> <em>Example: GRACE-C accelerometer calibration</em>   <ul>    </li><li> For one particular date, read and convert Level-1B GRACE-C orbit, star camera, accelerometer, and thruster data with <a class=\"groops-program\" href=\"GraceL1b2Orbit.html\">GraceL1b2Orbit</a>, <a class=\"groops-program\" href=\"GraceL1b2StarCamera.html\">GraceL1b2StarCamera</a>, <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>, and <a class=\"groops-program\" href=\"GraceL1b2Thruster.html\">GraceL1b2Thruster</a> respectively. It is also required to read the macro-model data of the satellite using the related information in the official document and convert it to GROOPS format with <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a>.   </li><li> Use <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a> to generate simulated accelerations due to non-gravitational force models including: <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">miscAccelerations:atmosphericDrag</a>, <a class=\"groops-class\" href=\"miscAccelerationsType.html#solarRadiationPressure\">miscAccelerations:solarRadiationPressure</a>, and <a class=\"groops-class\" href=\"miscAccelerationsType.html#albedo\">miscAccelerations:albedo</a>.   </li><li> Calibrate the real measurements with a daily constant accelerometer bias by choosing a constant parameter per axis in <a class=\"groops-class\" href=\"parametrizationAccelerationType.html#accBias\">parametrizationAcceleration:accBias</a>.      </li></ul>    </ul> </ul></p><p><h2>Statistical analysis</h2><p> <ul>  <li><a class=\"groops-program\" href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a> returns statistics for one or more instrument files. <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a> is also able to generate a <strong class=\"groops-config-element\">statistics</strong> file with one mid epoch per arc. </li></ul> </p><p><h2>Spectral analysis</h2><p> Spectral analysis studies the frequency spectrum contained in discrete, uniformly sampled data. The Fourier transform is a tool that reveals frequency components of a signal by representing it in frequency space. The Power Spectral Density (PSD) is a measurement of the energy at each frequency.</p><p><ul>  <li>If the sampling is irregular use <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a> to make the sampling equidistant. </li><li> Use <a class=\"groops-program\" href=\"Instrument2PowerSpectralDensity.html\">Instrument2PowerSpectralDensity</a> to compute PSD. </li><li> If covariance function of a dataset is available, use <a class=\"groops-program\" href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a>. </li><li> <em>Example: Spectral analysis of a synthetic signal.</em>   <ul>    </li><li> Create a sinusoidal signal with an amplitude of 1.0 using <a class=\"groops-program\" href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a> and set its type to MISCVALUE with <a class=\"groops-program\" href=\"InstrumentSetType.html\">InstrumentSetType</a>. Interpret this data as a simulation data file.   </li><li> Add zero-mean, white Gaussian noise with a standard deviation of 0.1 with <a class=\"groops-program\" href=\"NoiseInstrument.html\">NoiseInstrument</a>. Interpret this data as a real measurement file.   </li><li> Compute PSD of the simulated and measurement data and represent the results with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.      </li></ul>  </ul></p><p><h2>Data visualization</h2><p> <ul>  <li>Argument of latitude plot Plotting instrument data as a function of satellite position in orbit and time reveals features related to the orbit geometry or environmental conditions. For circular orbits, the position of  satellite can be specified by the argument of latitude. <ul>  </li><li> Synchronize the instrument data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>. </li><li> Use <a class=\"groops-program\" href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a> to compute argument of latitude at each epoch. </li><li> Plot the instrument data versus argument of latitude and time with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>. </li><li> <em>Example: Argument of latitude representation of GRACE-C eclipse factors</em>   <ul>    </li><li> Compute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using <a class=\"groops-program\" href=\"Orbit2EclipseFactor.html\">Orbit2EclipseFactor</a>.   </li><li> Synchronize the eclipse factor data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.   </li><li> Use <a class=\"groops-program\" href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a> to compute argument of latitude at each epoch and visualize the results with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.      </li></ul>  </ul></p><p><li>Ground-track plot Plotting instrument data with respect to the satellite ground track is useful to identify any features of geophysical origin in the data. <ul>  </li><li> Synchronize the instrument data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>. </li><li> Use <a class=\"groops-program\" href=\"Orbit2Groundtracks.html\">Orbit2Groundtracks</a> to map instrument data to satellite ground-track. </li><li> Visualize the output with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>. </li><li> <em>Example 6: Ground-track representation of GRACE-C eclipse factors</em>   <ul>    </li><li> Compute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using <a class=\"groops-program\" href=\"Orbit2EclipseFactor.html\">Orbit2EclipseFactor</a>.   </li><li> Synchronize the eclipse factor data file with the related orbit data using <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.   </li><li> Use <a class=\"groops-program\" href=\"Orbit2Groundtracks.html\">Orbit2Groundtracks</a> to generate the gridded data. Each grid value represents the mean value of eclipse factor over the instrument time period (1 month).  visualize the results with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.   </li></ul>     </ul></p><p></ul>'},\n'cookbook.gnssNetwork': { 'name': 'cookbook.gnssNetwork', 'key': 'cookbook.gnssNetwork', 'description': 'This cookbook chapter describes an example of global GNSS processing as done by analysis centers of the International GNSS Service (IGS). Resulting products usually comprise:      Satellite orbits, clocks, and signal biases    Station positions, clocks, signal biases, and troposphere estimates    Earth orientation parameters  Scientific details about the underlying processing approach and the applied parametrizations, models, and corrections can be found in a doctoral thesis available under DOI  . An example scenario for this task is available at  https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip . It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at  https://ftp.tugraz.at/pub/ITSG/groops  (data folder or zipped archive). The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings. Note: Global GNSS processing can become very computationally intensive. Depending on the number of satellites and stations, the observation and processing sampling, and parametrizations it can quickly exceed the capabilities of a normal desktop computer and may require computer clusters or number crunchers (see section   Parallelization ).  Most of the required metadata files are provided in GROOPS file formats at  https://ftp.tugraz.at/pub/ITSG/groops . These files are regularly updated. Data that has to be gathered from other sources comprises:      Receiver observations : GNSS measurements converted from RINEX format (see  RinexObservation2GnssReceiver ).    Approximate orbits : broadcast or precise orbits in CRF for orbit integration (see  GnssRinexNavigation2OrbitClock  or  Sp3Format2Orbit ).    Approximate clocks : broadcast or precise clocks (see  GnssRinexNavigation2OrbitClock  or  GnssClockRinex2InstrumentClock )   Receiver observations, broadcast ephemerides, and precise satellite orbits and clocks can be downloaded from the  . GPS, GLONASS, and Galileo orbits and clocks for the period 1994-2020 are also available as part of  . The   includes a small set of this data. The script  010groopsConvert.xml  can be used to convert these external formats into GROOPS formats. Prepare a  station list file  that contains the stations to be processed. Each line can contain more than one station. The first station in each line that has data available is used for the processing. If your network contains more than 60-70 stations, it is recommended to start processing with a core network (see  Advanced ). In this case, define an additional  core station list file  that can also have multiple stations per line.  Numerical integration of the satellite orbits is the first step in global GNSS processing. Dynamic orbits are integrated based on  section  and then fitted to the approximate orbits by estimating their initial state and additional empirical parameters for solar radiation pressure to improve the orbit fit. The resulting  variational equations  file contains the integrated orbit, derivatives with respect to the satellite state vector, attitude, Earth rotation and satellite model. Orbit preprocessing is covered by the script  020groopsGnssPreprocessing.xml  in the  . It is recommended to perform the steps below in a  loop  over all satellites/PRNs using  LoopPrograms . To get the relation between  {prn}  and  {svn}  setup an additional  section  inside  section  with      section : the old  inputfileTransmitterInfo     equipmentType          =  gnssAntenna     variableLoopName       =  block     variableLoopSerial     =  svn     variableLoopTimeStart  =  svnTimeStart     variableLoopTimeEnd    =  svnTimeEnd     section           expression  =  (svnTimeStart &lt;= loopTime) && (loopTime &lt; svnTimeEnd)        This second loop should perform only one step. The following programs are looped over all  {prn} :      InstrumentResample : resample approximate orbits from  data preparation  to target sampling (e.g., 1 minute) by defining a  section  based on a  method:polynomial  ( polynomialDegree = 7 ,  maxDataPointRange = 7200 ,  maxExtrapolationDistance = 900 ).    OrbitAddVelocityAndAcceleration : add velocity via running polynomial ( polynomialDegree = 2 ) derivation (needed for attitude computation)    SimulateStarCameraGnss     PreprocessingVariationalEquation :                      section = {groopsDataDir}/gnss/transmitter/satelliteModel/satelliteModel_boxWing.{svn}.xml             section : the resampled approximate orbit from  InstrumentResample             section : the attitude file from  SimulateStarCameraGnss             forces : see below            section : a static gravity field (e.g. GOCO06s) with  maxDegree = 4 .              PreprocessingVariationalEquationOrbitFit : fit the integrated orbit ( section ) to the approximate orbit ( section ) by least squares adjustment.         Add  section          and select the   parameters to be estimated.  Force models usually include:      section :         static gravity field (e.g. GOCO06s)    section           section :           trend component of time-variable gravity field (e.g. GOCO06s)        section           section :           annual cosine component of time-variable gravity field (e.g. GOCO06s)      section :           annual sine component of time-variable gravity field (e.g. GOCO06s)        section : astronomical tides (e.g. based on JPL ephemeris)    section : Earth tide (IERS conventions)    section : ocean tides (e.g. FES 2014b)    section : pole tides (IERS conventions)    section : ocean pole tides (IERS conventions)    section :         solar radiation pressure (box-wing model)    section : Earth radiation pressure (albedo model)    section :         antenna thrust (e.g. from IGS metadata SINEX file)    section :         relativistic effects (IERS conventions)   For the spherical harmonics expansions a  maxDegree = 60  is more than enough. The result of the preprocessing should be a  variational equations file , a  reduced dynamic orbit file  from  PreprocessingVariationalEquationOrbitFit  and an  attitude file  from  SimulateStarCameraGnss  for each satellite.  The script  030groopsGnssProcessing.xml  in the   implements the following steps and settings. These are the settings for  GnssProcessing . If not otherwise stated use the default values. The first step is setting the processing sampling, in this example it is 30 seconds. The processing interval usually is a single 24-hour day, therefore define  section  with  timeStart = &lt;mjd> ,  timeEnd = &lt;mjd>+1 ,  sampling = 30/86400  (processing sampling). Add the appropriate  section  (e.g. GPS, GLONASS, and Galileo) and provide the required files:      section  from  preprocessing     section  from  preprocessing     section  from  data preparation   The following settings are needed in  section :       section : list of all stations to be processed     section : The converted RINEX observation files.     section : Use the settings described in  receiver:stationNetwork .     section : Signals you might want to exclude are  C*?G  (old unknown GPS code observations),  *3*R  (GLONASS G3 freq.),  *6*E  (Galileo E6 freq.).  Add the following  section  and define the  outputfiles  you are interested in inside each of them:      section : add a constraint of  sigmaSTEC = 40     section : add  section          with linear ( degree = 1 ) 2-hourly splines    section : optionally change  section  to  section  with  name = G*  to align clocks to mean over GPS (instead of all) satellites    section     section     section     section     section : time-variable GPS L5 phase bias with  section = L5*G          and  section  with degree 3 and hourly nodes.    section     section : select  section          with the appropriate vmf3grid file. Add  section          with linear ( degree = 1 ) 2-hourly splines         and  section  with linear daily splines.    section :         provide  section = preprocessing/variational.{prn}.dat          from the preprocessing step.         Add  section  and          section  parameter at center of day to further improve orbit fit.    section                       section : polar motion            section  polar motion rate                 (at center of day with  timeStep = 1 )            section : length of day (at center of day with                  timeStep = -1  to match IGS sign convention)                section : loose constraint on GPS L5 phase biases,          section = signalBias.L5* ,  sigma = 5  meters, and  relativeToApriori = yes       section : loose constraint troposphere estimates,          section = troposphere* ,  sigma = 5  meters, and  relativeToApriori = yes       section : constraint on stochastic pulses,          section = stochasticPulse* ,  sigma = 0.1  micrometers/second.  Finally, define the  section . This can be overwhelming at first, but offers a lot of flexibility. The example script uses a 5-minute processing sampling with subsequent clock densification to 30 seconds.         section : with  nthEpoch = 10  to reduce sampling to 5 minutes.        section :             disable  constraint.STEC ,  *VTEC ,  *.tecBiases  as the ionosphere parameters are estimated in the final steps only.        section : with  maxIterationCount = 6         section         section :             enable  *  (all) parameters        section : with  maxIterationCount = 4 : final iterations (with 5-minute sampling) and ionosphere parameters        section : clock densification to 30-second sampling                      section : with  nthEpoch = 1  to set full 30-second sampling              section :             disable  *  (all) parameters and reenable  *.clock*  and  *.STEC  parameters              section : with  maxIterationCount = 6               section : with  suffix = 30s  to write 30-second clock files                section : write the final results  With some additional steps, the full 30-second sampling can be used to estimate all parameters (not only the clocks). These steps are disabled in the example script, as they require at least 16 GB of system memory. In this case, it is not necessary to separately write the 30-second clock files as listed above.         section : with  nthEpoch = 1  to set full 30-second sampling        section : As the system of normal       equations can be very large, the memory consumption might be reduced with  keepEpochNormalsinMemory = no .       In this case the epoch parameters are directly eliminated during the accumulation and reconstructed in the solving step.       This might lead to longer computation times.        section : with  maxIterationCount = 2 : final iterations with full sampling  Processing large station networks requires some additional steps to keep the computational load to a reasonable degree. The general processing strategy is to first process a well-distributed subset of stations (i.e. a core network) to get good estimates of all satellite parameters, which then enables integer ambiguity resolution (IAR). Once the ambiguities of the core network are resolved and stable estimates for satellite phase biases are available, all other (non-core) stations can be processed individually (including IAR) while keeping the satellite parameters fixed. At last, all stations can be processed together with all satellite parameters and ionosphere parameters. Let\\'s start with the  section  of the core network:          section  with  section        using the core network station list file from  data preparation  as  section .        section : with  nthEpoch = 10  to reduce sampling to 5 minutes.        section :             disable  constraint.STEC ,  *VTEC ,  *.tecBiases  as the ionosphere parameters are estimated in the final steps only.        section : with  maxIterationCount = 6         section         section : with  maxIterationCount = 4 : final iterations (with 5-minute sampling)  Now all other (non-core) stations can be processed separately:          section :             with  section  inside  section              using the station list from the core network above to process all non-core stations individually with fixed transmitter parameters                section : with  maxIterationCount = 6         section         section : with  maxIterationCount = 4           Next all stations are processed together with all parameters:          section : with  section         section : with  nthEpoch = 1  to set full 30-second sampling        section : clock densification to 30-second sampling                      section :             disable  *  (all) parameters and reenable  *.clock*  and  *.STEC  parameters              section : with  maxIterationCount = 6                 section : enable  *  (all) parameters.        section : with  keepEpochNormalsinMemory = no         section : with  maxIterationCount = 4 : final iterations with full sampling and all parameters        section : write the final results', 'config_table': '', 'display_text': 'This cookbook chapter describes an example of global GNSS processing as done by analysis centers of the International GNSS Service (IGS). Resulting products usually comprise: <ul>    <li>Satellite orbits, clocks, and signal biases   </li><li> Station positions, clocks, signal biases, and troposphere estimates   </li><li> Earth orientation parameters </li></ul> </p><p>Scientific details about the underlying processing approach and the applied parametrizations, models, and corrections can be found in a doctoral thesis available under DOI <a href=\"https://doi.org/10.3217/978-3-85125-885-1\">10.3217/978-3-85125-885-1</a>.</p><p>An example scenario for this task is available at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip</a>. It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (data folder or zipped archive). The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.</p><p><em>Note: Global GNSS processing can become very computationally intensive. Depending on the number of satellites and stations, the observation and processing sampling, and parametrizations it can quickly exceed the capabilities of a normal desktop computer and may require computer clusters or number crunchers (see section</em> <a class=\"groops-ref\" href=\"general.parallelization.html\">Parallelization</a><em>).</em></p><p><h2 id=\"metadata\">Data preparation</h2><p> Most of the required metadata files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>. These files are regularly updated.</p><p>Data that has to be gathered from other sources comprises: <ul>    <li><b>Receiver observations</b>: GNSS measurements converted from RINEX format (see <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>).   </li><li> <b>Approximate orbits</b>: broadcast or precise orbits in CRF for orbit integration (see <a class=\"groops-program\" href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a> or <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>).   </li><li> <b>Approximate clocks</b>: broadcast or precise clocks (see <a class=\"groops-program\" href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a> or <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a>) </li></ul>  Receiver observations, broadcast ephemerides, and precise satellite orbits and clocks can be downloaded from the <a href=\"https://igs.org/data-products-overview/\">IGS Data Centers</a>. GPS, GLONASS, and Galileo orbits and clocks for the period 1994-2020 are also available as part of <a href=\"https://doi.org/10.3217/dataset-4528-0723-0867\">Graz University of Technology\\'s contribution to IGS repro3</a>.</p><p>The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\">example scenario</a> includes a small set of this data. The script <code>010groopsConvert.xml</code> can be used to convert these external formats into GROOPS formats.</p><p>Prepare a <a class=\"groops-file\" href=\"fileFormat_stringTable.html\">station list file</a> that contains the stations to be processed. Each line can contain more than one station. The first station in each line that has data available is used for the processing. If your network contains more than 60-70 stations, it is recommended to start processing with a core network (see <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#advanced\">Advanced</a>). In this case, define an additional <a class=\"groops-file\" href=\"fileFormat_stringTable.html\">core station list file</a> that can also have multiple stations per line.</p><p><h2 id=\"orbitIntegration\">Preprocessing: Orbit integration</h2><p> Numerical integration of the satellite orbits is the first step in global GNSS processing. Dynamic orbits are integrated based on <a class=\"groops-class\" href=\"forcesType.html\">force models</a> and then fitted to the approximate orbits by estimating their initial state and additional empirical parameters for solar radiation pressure to improve the orbit fit. The resulting <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">variational equations</a> file contains the integrated orbit, derivatives with respect to the satellite state vector, attitude, Earth rotation and satellite model.</p><p>Orbit preprocessing is covered by the script <code>020groopsGnssPreprocessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\">example scenario</a>.</p><p>It is recommended to perform the steps below in a <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">loop</a> over all satellites/PRNs using <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a>. To get the relation between <code>{prn}</code> and <code>{svn}</code> setup an additional <a class=\"groops-class\" href=\"loopType.html#platformEquipment\">loop:platformEquipment</a> inside <a class=\"groops-class\" href=\"loopType.html#loop\">loop:loop</a> with <ul>    <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfilePlatform</a>: the old <strong class=\"groops-config-element\">inputfileTransmitterInfo</strong>   </li><li> <strong class=\"groops-config-element\">equipmentType</strong>         = <code>gnssAntenna</code>   </li><li> <strong class=\"groops-config-element\">variableLoopName</strong>      = <code>block</code>   </li><li> <strong class=\"groops-config-element\">variableLoopSerial</strong>    = <code>svn</code>   </li><li> <strong class=\"groops-config-element\">variableLoopTimeStart</strong> = <code>svnTimeStart</code>   </li><li> <strong class=\"groops-config-element\">variableLoopTimeEnd</strong>   = <code>svnTimeEnd</code>   </li><li> <a class=\"groops-class\" href=\"conditionType.html#expression\">condition:expression</a>   <ul>      </li><li> <strong class=\"groops-config-element\">expression</strong> = <code>(svnTimeStart &lt;= loopTime) && (loopTime &lt; svnTimeEnd)</code>   </li></ul>  </ul> This second loop should perform only one step. The following programs are looped over all <code>{prn}</code>: <ul>    <li><a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>: resample approximate orbits from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">data preparation</a> to target sampling (e.g., 1 minute) by defining a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> based on a <strong class=\"groops-config-element\">method:polynomial</strong> (<strong class=\"groops-config-element\">polynomialDegree</strong>=<code>7</code>, <strong class=\"groops-config-element\">maxDataPointRange</strong>=<code>7200</code>, <strong class=\"groops-config-element\">maxExtrapolationDistance</strong>=<code>900</code>).   </li><li> <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>: add velocity via running polynomial (<strong class=\"groops-config-element\">polynomialDegree</strong>=<code>2</code>) derivation (needed for attitude computation)   </li><li> <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>   </li><li> <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>:         <ul>            </li><li> <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">inputfileSatelliteModel</a>=<code>{groopsDataDir}/gnss/transmitter/satelliteModel/satelliteModel_boxWing.{svn}.xml</code>           </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: the resampled approximate orbit from <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>           </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>: the attitude file from <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>           </li><li> <strong class=\"groops-config-element\">forces</strong>: see below           </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gradientfield:potentialCoefficients</a>: a static gravity field (e.g. GOCO06s) with <strong class=\"groops-config-element\">maxDegree</strong>=<code>4</code>.         </li></ul>    <li><a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>: fit the integrated orbit (<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) to the approximate orbit (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>) by least squares adjustment.         Add <a class=\"groops-class\" href=\"parametrizationAccelerationType.html#gnssSolarRadiation\">parametrizationAcceleration:gnssSolarRadiation</a>         and select the <a href=\"https://doi.org/10.1007/s00190-015-0814-4\">ECOM2</a> parameters to be estimated. </li></ul> </p><p>Force models usually include: <ul>    <li><a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:         static gravity field (e.g. GOCO06s)   </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#trend\">gravityfield:trend</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:           trend component of time-variable gravity field (e.g. GOCO06s)   </li></ul>    <li><a class=\"groops-class\" href=\"gravityfieldType.html#oscillation\">gravityfield:oscillation</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldCos:potentialCoefficients</a>:           annual cosine component of time-variable gravity field (e.g. GOCO06s)     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldSin:potentialCoefficients</a>:           annual sine component of time-variable gravity field (e.g. GOCO06s)   </li></ul>    <li><a class=\"groops-class\" href=\"tidesType.html#astronomicalTide\">tides:astronomicalTide</a>: astronomical tides (e.g. based on JPL ephemeris)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#earthTide\">tides:earthTide</a>: Earth tide (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">tides:doodsonHarmonicTide</a>: ocean tides (e.g. FES 2014b)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#poleTide\">tides:poleTide</a>: pole tides (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">tides:poleOceanTide</a>: ocean pole tides (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"miscAccelerationsType.html#solarRadiationPressure\">miscAccelerations:solarRadiationPressure</a>:         solar radiation pressure (box-wing model)   </li><li> <a class=\"groops-class\" href=\"miscAccelerationsType.html#albedo\">miscAccelerations:albedo</a>: Earth radiation pressure (albedo model)   </li><li> <a class=\"groops-class\" href=\"miscAccelerationsType.html#antennaThrust\">miscAccelerations:antennaThrust</a>:         antenna thrust (e.g. from IGS metadata SINEX file)   </li><li> <a class=\"groops-class\" href=\"miscAccelerationsType.html#relativisticEffect\">miscAccelerations:relativisticEffect</a>:         relativistic effects (IERS conventions) </li></ul>  For the spherical harmonics expansions a <strong class=\"groops-config-element\">maxDegree</strong>=<code>60</code> is more than enough.</p><p>The result of the preprocessing should be a <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">variational equations file</a>, a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">reduced dynamic orbit file</a> from <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> and an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">attitude file</a> from <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> for each satellite.</p><p><h2 id=\"processing\">GNSS processing</h2><p> The script <code>030groopsGnssProcessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip\">example scenario</a> implements the following steps and settings.</p><p>These are the settings for <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. If not otherwise stated use the default values.</p><p>The first step is setting the processing sampling, in this example it is 30 seconds. The processing interval usually is a single 24-hour day, therefore define <a class=\"groops-class\" href=\"timeSeriesType.html#uniformSampling\">timeSeries:uniformSampling</a> with <strong class=\"groops-config-element\">timeStart</strong>=<code>&lt;mjd></code>, <strong class=\"groops-config-element\">timeEnd</strong>=<code>&lt;mjd>+1</code>, <strong class=\"groops-config-element\">sampling</strong>=<code>30/86400</code> (processing sampling).</p><p>Add the appropriate <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html#gnss\">transmitters:gnss</a> (e.g. GPS, GLONASS, and Galileo) and provide the required files: <ul>    <li><a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> from <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#orbitIntegration\">preprocessing</a>   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a> from <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#orbitIntegration\">preprocessing</a>   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a> from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">data preparation</a> </li></ul> </p><p>The following settings are needed in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>: <ul>     <li><a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStationList</a>: list of all stations to be processed    </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: The converted RINEX observation files.    </li><li> <a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>: Use the settings described in <a class=\"groops-ref\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>.    </li><li> <a class=\"groops-class\" href=\"gnssType.html\">excludeType</a>: Signals you might want to exclude are <code>C*?G</code> (old unknown GPS code observations), <code>*3*R</code> (GLONASS G3 freq.), <code>*6*E</code> (Galileo E6 freq.). </li></ul> </p><p>Add the following <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a> and define the <strong class=\"groops-config-element\">outputfiles</strong> you are interested in inside each of them: <ul>    <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">ionosphereSTEC</a>: add a constraint of <strong class=\"groops-config-element\">sigmaSTEC</strong>=<code>40</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">ionosphereMap</a>: add <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">temporal:splines</a>         with linear (<strong class=\"groops-config-element\">degree</strong>=<code>1</code>) 2-hourly splines   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">clocks</a>: optionally change <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitterZeroMeans</a> to <a class=\"groops-class\" href=\"platformSelectorType.html#wildcard\">wildcard</a> with <strong class=\"groops-config-element\">name</strong>=<code>G*</code> to align clocks to mean over GPS (instead of all) satellites   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">signalBiases</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">ambiguities</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">codeBiases</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">tecBiases</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#temporalBias\">temporalBias</a>: time-variable GPS L5 phase bias with <a class=\"groops-class\" href=\"gnssType.html\">type</a>=<code>L5*G</code>         and <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">parametrizationTemporal:splines</a> with degree 3 and hourly nodes.   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#staticPositions\">staticPositions</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#troposphere\">troposphere</a>: select <a class=\"groops-class\" href=\"troposphereType.html#viennaMapping\">troposphere:viennaMapping</a>         with the appropriate vmf3grid file. Add <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereWetEstimation:splines</a>         with linear (<strong class=\"groops-config-element\">degree</strong>=<code>1</code>) 2-hourly splines         and <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereGradientEstimation:splines</a> with linear daily splines.   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#transmitterDynamicOrbits\">transmitterDynamicOrbit</a>:         provide <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>=<code>preprocessing/variational.{prn}.dat</code>         from the preprocessing step.         Add <a class=\"groops-class\" href=\"parametrizationAccelerationType.html#gnssSolarRadiation\">parametrizationAcceleration:gnssSolarRadiation</a> and         <a class=\"groops-class\" href=\"timeSeriesType.html#irregular\">stochasticPulse:irregular</a> parameter at center of day to further improve orbit fit.   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#earthRotation\">earthRotation</a>         <ul>            </li><li> <a class=\"groops-class\" href=\"parametrizationTemporalType.html#constant\">estimatePole:constant</a>: polar motion           </li><li> <a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">estimatePole:trend</a> polar motion rate                 (at center of day with <strong class=\"groops-config-element\">timeStep</strong>=<code>1</code>)           </li><li> <a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">estimateUT1:trend</a>: length of day (at center of day with                 <strong class=\"groops-config-element\">timeStep</strong>=<code>-1</code> to match IGS sign convention)         </li></ul>      <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: loose constraint on GPS L5 phase biases,         <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>signalBias.L5*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>5</code> meters, and <strong class=\"groops-config-element\">relativeToApriori</strong>=<code>yes</code>     </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: loose constraint troposphere estimates,         <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>troposphere*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>5</code> meters, and <strong class=\"groops-config-element\">relativeToApriori</strong>=<code>yes</code>     </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: constraint on stochastic pulses,         <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>stochasticPulse*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>0.1</code> micrometers/second. </li></ul> </p><p>Finally, define the <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>. This can be overwhelming at first, but offers a lot of flexibility. The example script uses a 5-minute processing sampling with subsequent clock densification to 30 seconds.</p><p><ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>10</code> to reduce sampling to 5 minutes.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:             disable <code>constraint.STEC</code>, <code>*VTEC</code>, <code>*.tecBiases</code> as the ionosphere parameters are estimated in the final steps only.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:             enable <code>*</code> (all) parameters       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>: final iterations (with 5-minute sampling) and ionosphere parameters       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#group\">group</a>: clock densification to 30-second sampling       <ul>              </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> to set full 30-second sampling             </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:             disable <code>*</code> (all) parameters and reenable <code>*.clock*</code> and <code>*.STEC</code> parameters             </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>             </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>: with <strong class=\"groops-config-element\">suffix</strong>=<code>30s</code> to write 30-second clock files       </li></ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>: write the final results </li></ul> </p><p>With some additional steps, the full 30-second sampling can be used to estimate all parameters (not only the clocks). These steps are disabled in the example script, as they require at least 16 GB of system memory. In this case, it is not necessary to separately write the 30-second clock files as listed above.</p><p><ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> to set full 30-second sampling       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">selectNormalsBlockStructure</a>: As the system of normal       equations can be very large, the memory consumption might be reduced with <strong class=\"groops-config-element\">keepEpochNormalsinMemory</strong>=<code>no</code>.       In this case the epoch parameters are directly eliminated during the accumulation and reconstructed in the solving step.       This might lead to longer computation times.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>2</code>: final iterations with full sampling </li></ul> </p><p><h2 id=\"advanced\">Advanced: Processing large station networks</h2><p></p><p>Processing large station networks requires some additional steps to keep the computational load to a reasonable degree. The general processing strategy is to first process a well-distributed subset of stations (i.e. a core network) to get good estimates of all satellite parameters, which then enables integer ambiguity resolution (IAR). Once the ambiguities of the core network are resolved and stable estimates for satellite phase biases are available, all other (non-core) stations can be processed individually (including IAR) while keeping the satellite parameters fixed. At last, all stations can be processed together with all satellite parameters and ionosphere parameters.</p><p>Let\\'s start with the <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a> of the core network: <ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a> with <a class=\"groops-class\" href=\"platformSelectorType.html#file\">selectReceivers:file</a>       using the core network station list file from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">data preparation</a> as <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStringTable</a>.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>10</code> to reduce sampling to 5 minutes.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:             disable <code>constraint.STEC</code>, <code>*VTEC</code>, <code>*.tecBiases</code> as the ionosphere parameters are estimated in the final steps only.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>: final iterations (with 5-minute sampling) </li></ul> </p><p>Now all other (non-core) stations can be processed separately: <ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">forEachReceiverSeparately</a>:             with <a class=\"groops-class\" href=\"platformSelectorType.html#file\">selectReceivers:file</a> inside <a class=\"groops-class\" href=\"platformSelectorType.html#exclude\">selectReceivers:exclude</a>             using the station list from the core network above to process all non-core stations individually with fixed transmitter parameters       <ul>        </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">processingStep:resolveAmbiguities</a>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>       </li></ul>  </ul></p><p>Next all stations are processed together with all parameters: <ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a>: with <a class=\"groops-class\" href=\"platformSelectorType.html#all\">selectReceivers:all</a>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>: with <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> to set full 30-second sampling       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#group\">group</a>: clock densification to 30-second sampling       <ul>              </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>:             disable <code>*</code> (all) parameters and reenable <code>*.clock*</code> and <code>*.STEC</code> parameters             </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>6</code>       </li></ul>        <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>: enable <code>*</code> (all) parameters.       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">selectNormalsBlockStructure</a>: with <strong class=\"groops-config-element\">keepEpochNormalsinMemory</strong>=<code>no</code>       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>4</code>: final iterations with full sampling and all parameters       </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>: write the final results </li></ul> </p><p>'},\n'cookbook.gnssPpp': { 'name': 'cookbook.gnssPpp', 'key': 'cookbook.gnssPpp', 'description': 'This cookbook chapter describes an example of GNSS precise point positioning (PPP) for a ground station using GPS, GLONASS, and Galileo. For information on how to generate the GNSS products (orbits, clocks, signal biases, etc.) required for PPP, see the cookbook  GNSS satellite orbit determination and station network analysis . Scientific details about the underlying processing approach and the applied parametrizations, models, and corrections can be found in a doctoral thesis available under DOI  . An example scenario for this task is available at  https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip . It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at  https://ftp.tugraz.at/pub/ITSG/groops  (data folder or zipped archive). The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.  Most of the required metadata files are provided in GROOPS file formats at  https://ftp.tugraz.at/pub/ITSG/groops . These files are regularly updated. Data that has to be gathered from other sources comprises:      Receiver observations : GNSS measurements converted from RINEX format (see  RinexObservation2GnssReceiver )    Precise orbits : precise orbits in CRF for orbit integration (see  Sp3Format2Orbit )    Precise clocks : precise clocks (see  GnssClockRinex2InstrumentClock )    Attitude : rotation from body frame to CRF (see  SimulateStarCameraGnss  or  GnssOrbex2StarCamera )    Signal biases : code (and phase) biases (see  GnssSinexBias2SignalBias )   Receiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the  . GPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of  . The   includes a small set of this data. The script  010groopsConvert.xml  can be used to convert these external formats into GROOPS formats. Prepare a  station list file  that contains the stations (one per line) to be processed.  The script  02groopsGnssProcessing.xml  in the   implements the following steps and settings. These are the settings for  GnssProcessing . If not otherwise stated use the default values. The first step is setting the processing sampling, in this example it is 30 seconds. The processing interval usually is a single 24-hour day,  section  with  timeStart = &lt;mjd> ,  timeEnd = &lt;mjd>+1 ,  sampling = 30/86400  (processing sampling). Add the appropriate  section  (e.g. GPS, GLONASS, and Galileo) and provide the required files (from  Data preparation ):      section     section     section   The following settings are needed in  section :       section : list of all stations to be processed     section : The converted RINEX observation file.     section : Use the settings described in  receiver:stationNetwork .     section : We recommend to explicitly specify the signals to be processed             and to make sure that at least transmitter code biases are provided for each of them, e.g.  C1CG ,              C1WG ,  C2WG ,  L1*G ,  L2*G , ...).     section : Signals you might want to exclude are  L5*G  (GPS L5 phase due to time-variable bias on block IIF satellites),  *3*R  (GLONASS G3 freq.),  *6*E  (Galileo E6 freq.)  Add the following  section  and define the  outputfiles  you are interested in inside each of them:      section : add a constraint of  sigmaSTEC = 40     section     section : delete  section     section : provide  section  from          Data preparation .    section : if precise transmitter phase biases are available you can delete  section     section : delete  section , set  sigmaZeroMeanConstraint = 0     section : delete  section , set  sigmaZeroMeanConstraint = 0     section     section : select  section          with the appropriate vmf3grid file. Add  section          with linear ( degree = 1 ) 2-hourly splines         and  section  with linear daily splines.    section : loose constraint troposphere estimates,          section = troposphere* ,  sigma = 5 , and  relativeToApriori = yes   Add the following  section :      section : with  maxIterationCount = 8     section     section : with  maxIterationCount = 2     section   When processing multiple stations at the same time, moving  section  and  section  into the processing step  section  sets up and solves the normal equations independently for each station.', 'config_table': '', 'display_text': 'This cookbook chapter describes an example of GNSS precise point positioning (PPP) for a ground station using GPS, GLONASS, and Galileo. For information on how to generate the GNSS products (orbits, clocks, signal biases, etc.) required for PPP, see the cookbook <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>.</p><p>Scientific details about the underlying processing approach and the applied parametrizations, models, and corrections can be found in a doctoral thesis available under DOI <a href=\"https://doi.org/10.3217/978-3-85125-885-1\">10.3217/978-3-85125-885-1</a>.</p><p>An example scenario for this task is available at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip</a>. It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (data folder or zipped archive). The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.</p><p><h2 id=\"metadata\">Data preparation</h2><p> Most of the required metadata files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>. These files are regularly updated.</p><p>Data that has to be gathered from other sources comprises: <ul>    <li><b>Receiver observations</b>: GNSS measurements converted from RINEX format (see <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>)   </li><li> <b>Precise orbits</b>: precise orbits in CRF for orbit integration (see <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>)   </li><li> <b>Precise clocks</b>: precise clocks (see <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a>)   </li><li> <b>Attitude</b>: rotation from body frame to CRF (see <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> or <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>)   </li><li> <b>Signal biases</b>: code (and phase) biases (see <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>) </li></ul>  Receiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the <a href=\"https://igs.org/data-products-overview/\">IGS Data Centers</a>. GPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of <a href=\"https://doi.org/10.3217/dataset-4528-0723-0867\">Graz University of Technology\\'s contribution to IGS repro3</a>.</p><p>The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip\">example scenario</a> includes a small set of this data. The script <code>010groopsConvert.xml</code> can be used to convert these external formats into GROOPS formats.</p><p>Prepare a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">station list file</a> that contains the stations (one per line) to be processed.</p><p><h2 id=\"processing\">Processing of a ground station</h2><p> The script <code>02groopsGnssProcessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip\">example scenario</a> implements the following steps and settings.</p><p>These are the settings for <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. If not otherwise stated use the default values.</p><p>The first step is setting the processing sampling, in this example it is 30 seconds. The processing interval usually is a single 24-hour day, <a class=\"groops-class\" href=\"timeSeriesType.html#uniformSampling\">timeSeries:uniformSampling</a> with <strong class=\"groops-config-element\">timeStart</strong>=<code>&lt;mjd></code>, <strong class=\"groops-config-element\">timeEnd</strong>=<code>&lt;mjd>+1</code>, <strong class=\"groops-config-element\">sampling</strong>=<code>30/86400</code> (processing sampling).</p><p>Add the appropriate <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html#gnss\">transmitters:gnss</a> (e.g. GPS, GLONASS, and Galileo) and provide the required files (from <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">Data preparation</a>): <ul>    <li><a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a>   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a> </li></ul> </p><p>The following settings are needed in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>: <ul>     <li><a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileStationList</a>: list of all stations to be processed    </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: The converted RINEX observation file.    </li><li> <a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>: Use the settings described in <a class=\"groops-ref\" href=\"gnssReceiverGeneratorType.html#stationNetwork\">receiver:stationNetwork</a>.    </li><li> <a class=\"groops-class\" href=\"gnssType.html\">useType</a>: We recommend to explicitly specify the signals to be processed             and to make sure that at least transmitter code biases are provided for each of them, e.g. <code>C1CG</code>,             <code>C1WG</code>, <code>C2WG</code>, <code>L1*G</code>, <code>L2*G</code>, ...).    </li><li> <a class=\"groops-class\" href=\"gnssType.html\">excludeType</a>: Signals you might want to exclude are <code>L5*G</code> (GPS L5 phase due to time-variable bias on block IIF satellites), <code>*3*R</code> (GLONASS G3 freq.), <code>*6*E</code> (Galileo E6 freq.) </li></ul> </p><p>Add the following <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a> and define the <strong class=\"groops-config-element\">outputfiles</strong> you are interested in inside each of them: <ul>    <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">ionosphereSTEC</a>: add a constraint of <strong class=\"groops-config-element\">sigmaSTEC</strong>=<code>40</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">ionosphereVTEC</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">clocks</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">signalBiases</a>: provide <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBiasTransmitter</a> from         <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html#metadata\">Data preparation</a>.   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">ambiguities</a>: if precise transmitter phase biases are available you can delete <a class=\"groops-class\" href=\"platformSelectorType.html\">estimateTransmitterPhaseBiases</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">codeBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">tecBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#kinematicPositions\">kinematicPositions</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#troposphere\">troposphere</a>: select <a class=\"groops-class\" href=\"troposphereType.html#viennaMapping\">troposphere:viennaMapping</a>         with the appropriate vmf3grid file. Add <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereWetEstimation:splines</a>         with linear (<strong class=\"groops-config-element\">degree</strong>=<code>1</code>) 2-hourly splines         and <a class=\"groops-class\" href=\"parametrizationTemporalType.html#splines\">troposphereGradientEstimation:splines</a> with linear daily splines.   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">constraints</a>: loose constraint troposphere estimates,         <a class=\"groops-class\" href=\"parameterSelectorType.html#wildcard\">parameters:wildcard:type</a>=<code>troposphere*</code>, <strong class=\"groops-config-element\">sigma</strong>=<code>5</code>, and <strong class=\"groops-config-element\">relativeToApriori</strong>=<code>yes</code> </li></ul> </p><p>Add the following <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>: <ul>    <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>8</code>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>2</code>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a> </li></ul> </p><p>When processing multiple stations at the same time, moving <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a> and <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a> into the processing step <a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">forEachReceiverSeparately</a> sets up and solves the normal equations independently for each station.</p><p>'},\n'cookbook.kinematicOrbit': { 'name': 'cookbook.kinematicOrbit', 'key': 'cookbook.kinematicOrbit', 'description': 'This cookbook chapter describes exemplarily the steps for determining kinematic orbits of low-Earth orbit (LEO) satellites. An example scenario for this task is available at  https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip . It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at  https://ftp.tugraz.at/pub/ITSG/groops  (data folder or zipped archive). The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.  Most of the required metadata files are provided in GROOPS file formats at  https://ftp.tugraz.at/pub/ITSG/groops . These files are regularly updated. Data that has to be gathered from other sources comprises:      Receiver observations : GNSS measurements converted from RINEX format (see  RinexObservation2GnssReceiver )    Precise orbits : precise orbits in CRF for orbit integration (see  Sp3Format2Orbit )    Precise clocks : precise clocks (see  GnssClockRinex2InstrumentClock )    Attitude : rotation from body frame to CRF (see  SimulateStarCameraGnss  or  GnssOrbex2StarCamera )    Signal biases : code (and phase) biases (see  GnssSinexBias2SignalBias )   Receiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the  . GPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of  . The   includes a small set of this data. The script  010groopsConvert.xml  can be used to convert these external formats into GROOPS formats.  Metadata for several LEO missions is availabe at  https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/receiverLowEarthOrbiter . If you want to process another mission, you can create the necessary files with these steps:      For creating the  GnssSatelliteInfo file  use  PlatformCreate . Note that the rotation from the   satellite reference frame into the antenna reference frame, as well as the change of the center of mass due to fuel consumption, has to be considered here.    The  GnssReceiverDefinition file  can be created by using  GnssReceiverDefinitionCreate . Here you can specify which GNSS signal types the receiver observes.    For creating the  GnssAntennaDefinition file use  GnssAntennaDefinitionCreate . Here you can define phase center offsets for the antenna.    For determining the elevation dependent accuracies the program  GnssAntennaDefinitionCreate  is used again.          antenna : set to new      Set the  pattern s for code ( type = C** ) and phase     ( type = L** ). The standard deviation is expressed e.g. with  values = 0.001/cos(2*PI/180*zenith) .       The   includes a small set of this data for the GRACE-FO mission. The script  020groopsConvertGracefo.xml  can be used to convert these external formats into GROOPS formats. The data preparation steps are:      Conversion of the approximate orbit and star camera data into GROOPS format using a conversion program.    If no attitude data is given the star camera data can be simulated by using  SimulateStarCamera  or  SimulateStarCameraSentinel1 .    The GNSS observation data (given in RINEX format) can be converted with  RinexObservation2GnssReceiver .    Suitable programs to get daily data are  InstrumentConcatenate  and  InstrumentSynchronize .    For interpolating the orbit and star camera data to GNSS receiver epochs use  InstrumentResample  and provide the converted RINEX observation file as input for    section .    For synchronizing these data use  InstrumentSynchronize .   Detailed description of instrument data handling can be found in  Instrument data handling .  The script  03groopsGnssProcessing.xml  in the   implements the following steps and settings. These are the settings for  GnssProcessing . If not otherwise stated use the default values. As we have only one receiver the processing sampling can be directly taken from the observation file:  section . Add the appropriate  section  (e.g. GPS) and provide the required files (from  Prepare GNSS satellite data ):      section     section     section   The following files (from  Prepare LEO metadata  and  Prepare LEO data ) and settings are needed in  section :       section : The satellite info file.     section      section      section      section : The converted RINEX observation file.     section : The approximate orbit.     section : The convered or simulated attitude.     section : We recommend to explicitly specify the signals to be processed             and to make sure that at least transmitter code biases are provided for each of them, e.g.  C1CG ,              C1WG ,  C2WG ,  L1*G ,  L2*G , ...).  Add the following  section  and define the  outputfiles  within you are interested in:      section : add a constraint of  sigmaSTEC = 40     section :         set  mapR = 6371e3+450e3  to satellite height and ionosphere height  mapH = 50e3  above.    section : delete  section     section : provide  section  created with  GnssSinexBias2SignalBias     section : if precise transmitter phase biases are available you can delete  section     section : delete  section , set  sigmaZeroMeanConstraint = 0     section : delete  section , set  sigmaZeroMeanConstraint = 0     section   Add the following  section :      section : with  maxIterationCount = 8     section     section : with  maxIterationCount = 2     section     section', 'config_table': '', 'display_text': 'This cookbook chapter describes exemplarily the steps for determining kinematic orbits of low-Earth orbit (LEO) satellites.</p><p>An example scenario for this task is available at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip</a>. It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (data folder or zipped archive). The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.</p><p><h2 id=\"gnssMetadata\">Prepare GNSS satellite data</h2><p> Most of the required metadata files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>. These files are regularly updated.</p><p>Data that has to be gathered from other sources comprises: <ul>    <li><b>Receiver observations</b>: GNSS measurements converted from RINEX format (see <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>)   </li><li> <b>Precise orbits</b>: precise orbits in CRF for orbit integration (see <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>)   </li><li> <b>Precise clocks</b>: precise clocks (see <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a>)   </li><li> <b>Attitude</b>: rotation from body frame to CRF (see <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> or <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>)   </li><li> <b>Signal biases</b>: code (and phase) biases (see <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>) </li></ul>  Receiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the <a href=\"https://igs.org/data-products-overview/\">IGS Data Centers</a>. GPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of <a href=\"https://doi.org/10.3217/dataset-4528-0723-0867\">Graz University of Technology\\'s contribution to IGS repro3</a>.</p><p>The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\">example scenario</a> includes a small set of this data. The script <code>010groopsConvert.xml</code> can be used to convert these external formats into GROOPS formats.</p><p><h2 id=\"leoMetadata\">Prepare LEO metadata</h2><p> Metadata for several LEO missions is availabe at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/receiverLowEarthOrbiter\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/receiverLowEarthOrbiter</a>.</p><p>If you want to process another mission, you can create the necessary files with these steps: <ul>    <li>For creating the <a class=\"groops-file\" href=\"fileFormat_platform.html\">GnssSatelliteInfo file</a> use <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>. Note that the rotation from the   satellite reference frame into the antenna reference frame, as well as the change of the center of mass due to fuel consumption, has to be considered here.   </li><li> The <a class=\"groops-file\" href=\"fileFormat_gnssReceiverDefinition.html\">GnssReceiverDefinition file</a> can be created by using <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a>. Here you can specify which GNSS signal types the receiver observes.   </li><li> For creating the <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> use <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>. Here you can define phase center offsets for the antenna.   </li><li> For determining the elevation dependent accuracies the program <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a> is used again.   <ul>      </li><li> <strong class=\"groops-config-element\">antenna</strong>: set to new     </li><li> Set the <strong class=\"groops-config-element\">pattern</strong>s for code (<strong class=\"groops-config-element\">type</strong>=<code>C**</code>) and phase     (<strong class=\"groops-config-element\">type</strong>=<code>L**</code>). The standard deviation is expressed e.g. with <strong class=\"groops-config-element\">values</strong>=<code>0.001/cos(2*PI/180*zenith)</code>.   </li></ul>  </ul></p><p><h2 id=\"leoData\">Prepare LEO data</h2><p> The <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\">example scenario</a> includes a small set of this data for the GRACE-FO mission. The script <code>020groopsConvertGracefo.xml</code> can be used to convert these external formats into GROOPS formats.</p><p>The data preparation steps are: <ul>    <li>Conversion of the approximate orbit and star camera data into GROOPS format using a conversion program.   </li><li> If no attitude data is given the star camera data can be simulated by using <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a> or <a class=\"groops-program\" href=\"SimulateStarCameraSentinel1.html\">SimulateStarCameraSentinel1</a>.   </li><li> The GNSS observation data (given in RINEX format) can be converted with <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>.   </li><li> Suitable programs to get daily data are <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a> and <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.   </li><li> For interpolating the orbit and star camera data to GNSS receiver epochs use <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a> and provide the converted RINEX observation file as input for   <a class=\"groops-class\" href=\"timeSeriesType.html#instrument\">timeSeries:instrument</a>.   </li><li> For synchronizing these data use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>. </li></ul>  Detailed description of instrument data handling can be found in <a class=\"groops-ref\" href=\"cookbook.instrument.html\">Instrument data handling</a>.</p><p><h2 id=\"processing\">Estimate kinematic orbits</h2><p> The script <code>03groopsGnssProcessing.xml</code> in the <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip\">example scenario</a> implements the following steps and settings.</p><p>These are the settings for <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. If not otherwise stated use the default values.</p><p>As we have only one receiver the processing sampling can be directly taken from the observation file: <a class=\"groops-class\" href=\"timeSeriesType.html#instrument\">timeSeries:instrument</a>.</p><p>Add the appropriate <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html#gnss\">transmitters:gnss</a> (e.g. GPS) and provide the required files (from <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html#gnssMetadata\">Prepare GNSS satellite data</a>): <ul>    <li><a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a>   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a> </li></ul> </p><p>The following files (from <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html#leoMetadata\">Prepare LEO metadata</a> and <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html#leoData\">Prepare LEO data</a>) and settings are needed in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html#lowEarthOrbiter\">receiver:lowEarthOrbiter</a>: <ul>     <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a>: The satellite info file.    </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>    </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a>    </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a>    </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: The converted RINEX observation file.    </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: The approximate orbit.    </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>: The convered or simulated attitude.    </li><li> <a class=\"groops-class\" href=\"gnssType.html\">useType</a>: We recommend to explicitly specify the signals to be processed             and to make sure that at least transmitter code biases are provided for each of them, e.g. <code>C1CG</code>,             <code>C1WG</code>, <code>C2WG</code>, <code>L1*G</code>, <code>L2*G</code>, ...). </li></ul> </p><p>Add the following <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a> and define the <strong class=\"groops-config-element\">outputfiles</strong> within you are interested in: <ul>    <li><a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">ionosphereSTEC</a>: add a constraint of <strong class=\"groops-config-element\">sigmaSTEC</strong>=<code>40</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">ionosphereVTEC</a>:         set <strong class=\"groops-config-element\">mapR</strong>=<code>6371e3+450e3</code> to satellite height and ionosphere height <strong class=\"groops-config-element\">mapH</strong>=<code>50e3</code> above.   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">clocks</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">signalBiases</a>: provide <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBiasTransmitter</a> created with <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">ambiguities</a>: if precise transmitter phase biases are available you can delete <a class=\"groops-class\" href=\"platformSelectorType.html\">estimateTransmitterPhaseBiases</a>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">codeBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">tecBiases</a>: delete <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>, set <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>=<code>0</code>   </li><li> <a class=\"groops-class\" href=\"gnssParametrizationType.html#kinematicPositions\">kinematicPositions</a> </li></ul> </p><p>Add the following <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>: <ul>    <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>8</code>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: with <strong class=\"groops-config-element\">maxIterationCount</strong>=<code>2</code>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#computeCovarianceMatrix\">computeCovarianceMatrix</a>   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a> </li></ul> </p><p>'},\n'cookbook.gravityFieldPod': { 'name': 'cookbook.gravityFieldPod', 'key': 'cookbook.gravityFieldPod', 'description': 'This cookbook chapter describes exemplarily the steps for determining the monthly gravity variations from precise orbit data (POD). Following data have to be prepared monthly with an adequate sampling, e.g. 10 s using  InstrumentConcatenate :      Precise (kinematic) orbit data    3x3 covariance matrices data    Initial orbit data used for precise orbit determination    Star camera data    Accelerometer data   Reduced sampling can be achieved by  InstrumentReduceSampling . If the satellite mission does not provide any required accelerometer data, these data can be generated via  SimulateAccelerometer . For satellite missions with less knowledge about the acting forces, it makes sense to consider more than one state vector within an orbit revolution. Otherwise the accuracy of the estimated parameters will decrease. This implies that shorter arcs are necessary. The assignment of the kinematic orbit data as well as the 3x3 covariance matrices data to the arcs can be done with  InstrumentSynchronize .   Gravityfield2SphericalHarmonicsVector  converts the static respectively background gravity field into spherical harmonics.  For determining the accuracies and weights of the kinematic orbits it is sufficient to make a least-square estimation with only certain parameters, due to the fact that some parameters do not influence the estimation of the accuracies and weights. This estimation is done with  PreprocessingPod . Additionally, this program determines the temporal correlation of the kinematic orbit positions x, y and z. If short arcs are used the setting  section  shall be used. This setting considers the frictional forces by means of a macro model as well as the conservative and non-conservative forces.   NormalsSolverVCE  sets up the observation equations and summarized them to a normal equations system. The subsequent least-square estimation delivers the parameters surcharges.  The estimated parameters result from the re-addition of the background field, which is done in  MatrixCalculate .   Gravityfield2PotentialCoefficients  converts the gravity field parameters into spherical harmonics.', 'config_table': '', 'display_text': '</p><p>This cookbook chapter describes exemplarily the steps for determining the monthly gravity variations from precise orbit data (POD).</p><p><h2>Step 1: Preperation of data</h2><p></p><p>Following data have to be prepared monthly with an adequate sampling, e.g. 10 s using <a class=\"groops-program\" href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a>: <ul>    <li>Precise (kinematic) orbit data   </li><li> 3x3 covariance matrices data   </li><li> Initial orbit data used for precise orbit determination   </li><li> Star camera data   </li><li> Accelerometer data </li></ul>  Reduced sampling can be achieved by <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a>. If the satellite mission does not provide any required accelerometer data, these data can be generated via <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>.</p><p>For satellite missions with less knowledge about the acting forces, it makes sense to consider more than one state vector within an orbit revolution. Otherwise the accuracy of the estimated parameters will decrease. This implies that shorter arcs are necessary. The assignment of the kinematic orbit data as well as the 3x3 covariance matrices data to the arcs can be done with <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p><h2>Step 2: Conversion of the background gravity field</h2><p> <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a> converts the static respectively background gravity field into spherical harmonics.</p><p><h2>Step 3: Preprocessing POD</h2><p> For determining the accuracies and weights of the kinematic orbits it is sufficient to make a least-square estimation with only certain parameters, due to the fact that some parameters do not influence the estimation of the accuracies and weights. This estimation is done with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>. Additionally, this program determines the temporal correlation of the kinematic orbit positions x, y and z. If short arcs are used the setting <a class=\"groops-class\" href=\"observationType.html#podIntegral\">observation:podIntegral</a> shall be used. This setting considers the frictional forces by means of a macro model as well as the conservative and non-conservative forces.</p><p><h2>Step 4: Solving of normal equations system</h2><p> <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a> sets up the observation equations and summarized them to a normal equations system. The subsequent least-square estimation delivers the parameters surcharges.</p><p><h2>Step 5: Determination of the estimated gravity field parameters</h2><p> The estimated parameters result from the re-addition of the background field, which is done in <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.</p><p><h2>Step 6: Conversion of the gravity field parameters</h2><p> <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> converts the gravity field parameters into spherical harmonics.</p><p>'},\n'cookbook.gravityFieldGrace': { 'name': 'cookbook.gravityFieldGrace', 'key': 'cookbook.gravityFieldGrace', 'description': 'This cookbook chapter describes an example of estimating a gravity field solution using GRACE observation data. For the respective month a set of spherical harmonic coefficients up to a maximum degree is determined. An example scenario for this task can be found at  https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGraceGravityfieldRecovery.zip  including the required GROOPS scripts and data sets for the gravity field recovery process. The provided scenario consists of a slightly simplified example as compared to the operational one. The background models are provided at  https://ftp.tugraz.at/pub/ITSG/groops/data/ .    The following background models were used during the data processing:      Earth rotation :        Moon, sun and planets ephemerides :        Earth tide :        Ocean tide :        Pole tide :        Ocean pole tide :        Atmospheric tides :        Atmosphere and Ocean Dealiasing :        Sub-monthly continental hydrology :        Relativistic corrections :       These models were reduced during the analysis process and are not present in the solution. The   model was used as the static gravity field as well as for the trend component and annual oscillation. In the script  000groopsBackgroundModels.xml  a monthly mean of the GOCO06s including the time-variable components is determined in form of time splines using  Gravityfield2TimeSplines . This model is later added back to the final gravity solution.  The ITSG gravity field solutions are computed from the official GRACE L1B   and GRACE-FO L1B   observation data. The data sets for this example are provided in GROOPS file format in the scenario folder. The satellite-to-satellite-tracking (SST) data consists of:      K-band range rates     Light time correction     Antenna offset corrections   Additional observation data required for the processing comprises:      Star camera observations     Accelerometer data     Approximate orbits       Thruster data   The determination of      Kinematic orbits     3x3 epoch covariances    is depicted in  Kinematic orbit determination of LEO satellites . These data sets are also provided in the scenario folder. Data preparation is handled in the script  010groopsInstruments.xml . The approximate orbits (initial dynamic orbits) of the satellites, the star camera observations, the accelerometer data and the thruster data are resampled with a 5s sampling and small gaps in the data are filled using  InstrumentResample . Gross outliers are removed using  InstrumentRemoveEpochsByCriteria  and the data is synchronized using   InstrumentSynchronize . The approximate orbits are later used as a priori information for the dynamic orbit integration. In addition to the observed orientation of the spacecrafts (star camera observations), the nominal orientation is computed using  SimulateStarCameraGrace . The difference between observed and simulated orientation is determined using  InstrumentStarCameraMultiply  and is employed in the outlier detection. The accelerometer data is initially calibrated by estimating a bias using  InstrumentAccelerometerEstimateBiasScale  with respect to simulated data created with  SimulateAccelerometer . For simulating accelerometer data a satellite model implying the satellite\\'s mass and surfaces is required. Such a model can be created with  SatelliteModelCreate . Models for the GRACE and GRACE-FO satellites are also provided at  https://ftp.tugraz.at/pub/ITSG/groops/data/satelliteModel/ . Non-gravitational forces comprising atmospheric drag, solar radiation pressure and albedo have to be modeled when simulating the accelerometer data. The acceleration bias parameters are determined as degree 3 time splines with 6h nodes. When determining these parameters the thruster events are excluded from the estimation. The SST observations, the light time corrections and the antenna center corrections are synchronized with a 5s sampling together with simulated SST data created with  SimulateSatelliteTracking . Simulated data is used for the outlier detection of the original SST observations. The sampling of the kinematic orbits is reduced to 60s using  InstrumentReduceSampling  and an outlier detection is performed using the approximate dynamic orbits. The approximate orbits, the star camera observations and the accelerometer data are divided into 24h arcs (variational arcs). The kinematic orbits, its 3x3 epoch covariances, KBR observations, light time corrections, antenna center corrections and star camera observations are divided into 3h arcs per day (short arcs). Additionally the approximate orbits and the star camera observations are also synchronized to short arcs. Further information on instrument data preparation can be found in  Instrument data handling .  In this processing step dynamic orbits are computed for a complete 24h orbit arc by integrating the forces acting on the GRACE/GRACE-FO satellites. Additionally, the state transition matrix is set up. The dynamic orbits are then fitted to kinematic orbits and SST observations in a least squares adjustment by co-estimating additional accelerometer calibration parameters together with the initial state vector. The newly estimated parameters are then used to re-estimate the dynamic orbits and setting up the new state transition matrix. The script  020groopsVariational.xml  in the scenario folder implements the required processing steps. Time splines from a time-variable gravity field are estimated using  Gravityfield2TimeSplines . In this step the static gravity field (GOCO06s) is combined with the following time-variable components:        section :     static gravity field      section                 section :       trend component of gravity field            section                 section :       annual cosine component of gravity field          section :       annual sine component of gravity field            section : atmosphere and ocean dealiasing (AOD1B RL06)      section : ocean tides (FES2014b)      section : atmospheric tides (TiME22)      section : pole tides (IERS 2010)      section : ocean pole tides (IERS 2010)    maxDegree = 220  and  sampling = 10/1440  is sufficient. In  PreprocessingVariationalEquation  the  variational equations  comprising the integrated orbit together with the state transition matrix are stored in  section . This program has to be executed for both GRACE or GRACE-FO satellites and it is recommended to use  LoopPrograms .        section : satellite model from  020groopsInstruments.xml       section : the approximate orbits from  020groopsInstruments.xml       section : the attitude file from  020groopsInstruments.xml       section : the accelerometer data from      020groopsInstruments.xml       forces : see below      section : JPL DE432      section : a static gravity field (GOCO06s) with  maxDegree = 10  is more than sufficient.  The  section  include:      section :         the previously estimated time-variable gravity field    section : astronomical tides (based on JPL DE432 ephemerides)    section : Earth tide (IERS conventions)    section :         relativistic effects (IERS conventions)  In  PreprocessingVariationalEquationOrbitFit  the integrated orbit ( section ) is fitted to the kinematic orbit ( section ) by least squares adjustment. The additional accelerometer calibration parameters can be defined by      section : accelerometer scale factor (once per day)    section : accelerometer bias (time spline with 6h nodes)  The observation equations (parameter sensitivity matrix) are computed by integration of the variational equations ( section ) using a polynomial with  integrationDegree = 7 .  PreprocessingVariationalEquationOrbitFit  has to be executed per satellite. PreprocessingVariationalEquationSstFit  fits two dynamic orbits  section  to the SST observations and the kinematic orbits.        rightHandSide : input for observation vectors                        section : K-band range rate observations              section : light time correction              section : antenna offset corrections              section : kinematic orbit of satellite 1              section : kinematic orbit of satellite 2                sstType : rangeRate      section : dynamic orbit and integrated state matrix of satellite 1      section : dynamic orbit and integrated state matrix of satellite 2      section : same as in In  PreprocessingVariationalEquationOrbitFit       section : same as in In  PreprocessingVariationalEquationOrbitFit       integrationDegree :  7       interpolationDegree :  7       section                         sigma :  1                 section                         sigma : 1              section : 3x3 epoch covariances                section                         sigma : 1              section : 3x3 epoch covariances             The estimated accelerometer calibration parameters from  PreprocessingVariationalEquationOrbitFit  and  PreprocessingVariationalEquationSstFit  are determined as corrections and stored in  section . Both correction estimates have to be summed up using  FunctionsCalculate . The dynamic orbit and the resulting accelerometer calibration parameters are now used to re-integrate the orbit once more using  PreprocessingVariationalEquation  and introducing  section  as  estimatedParameters . This step usually ensures convergence. If the maximum orbit difference is still not sufficient this step can be repeated again.  The script  030groopsPreprocessing.xml  implements the following steps and settings. The program  PreprocessingSst  processes SST observations and kinematic orbit data, and performs a complete least squares adjustment for gravity field determination by computing the observations equations. It also allows for an iterative refinement of the stochastic model of the observations along with arc-wise variance factors through variance component estimation (VCE). Force model parameters (gravitational potential coefficients and accelerometer calibration parameters) are computed by integrating the parameter sensitivity matrix from the variational equations. Parameters describing effects due to the SST observation system and geometry (KBR antenna phase center variations) are computed using the dynamic orbits as a Taylor point. Short time gravity variations can be co-estimated together with the monthly mean gravity field. The autoregressive model sequence constraining the short time parameters is provided in the data folder. It is precomputed from hydrology and nontidal atmospheric and ocean background models. See   for more information about this co-estimation.       section : sstVariational                        rightHandSide :                                section : KBR range rates                  section : light time correction                  section : antenna offset corrections                  section : kinematic orbit of satellite 1                  section : kinematic orbit of satellite 2                            sstType : rangeRate              section : dynamic orbit and integrated state matrix of satellite 1              section : dynamic orbit and integrated state matrix of satellite 2              section : JPL DE432              section : spherical harmonics from  minDegree = 2  to  maxDegree = 60               section : high frequency parametrization              section : same as in In  PreprocessingVariationalEquationOrbitFit               section : same as in In  PreprocessingVariationalEquationOrbitFit               section : antenna phase center variations (y and z for both satellites)              integrationDegree : 7              interpolationDegree : 7                section                         sigma :  1e-7               sampling : 5 [seconds]                section                         sigma :   2               section : 3x3 epoch covariances              sampling : 60 [seconds]                estimateShortTimeVariations                         section : AR models              section : names                                        section : parametrizationGravity                                                section : high frequency parametrization                                                    ParameterSelection2IndexVector  and  MatrixCalculate  with  section  can be used to extract the desired spherical harmonic coefficients from  section  and the respective standard deviations from  section  up to a certain degree. In the program  Gravityfield2PotentialCoefficients  the estimated spherical harmonics coefficients are read with  section . The monthly mean gravity field can be added back by additionally selecting the time splines created in  000groopsBackgroundModels.xml  using  section . The preprocessing solution is saved as a  spherical harmonics file .  Normal equations are set up in the script  040groopsMonthlyNormals120.xml  using the program  NormalsBuildShortTimeStaticLongTime . The time intervals which the normal equations are divided into are defined in  section . The normal equations are based on  section  including the SST data, the kinematic orbits and the variational equations. The parametrization of the gravity field can be set with  section  (e.g. spherical harmonics up to degree and order 120). Accelerometer calibration parameters and KBR antenna phase center variations can be parameterized using  section  and  section . With  estimateShortTimeVariations  short time variations of the gravity field can be co-estimated. The parameters selected by  section  (e.g. linear splines with 6h nodes) are constrained by an  section . Additional temporal variations (e.g. trend and annual oscillation) could be estimated with  estimateLongTimeVariations .  The desired spherical harmonic coefficients are determined in the script  050groopsMonthlySolve.xml .  NormalsSolverVCE  accumulates  section  and solves the total combined system. Variance component estimation is used to determine the relative weighting of the individual normals, i.e. the arc-wise variances. The previously computed stochastic model of the observations remains unchanged. The estimated parameter vector ( section ), the estimated accuracies ( section ) and the full covariance matrix ( section ) can be saved. Using  Gravityfield2PotentialCoefficients  the final solution can be saved as a  spherical harmonics file  by adding back the monthly mean gravity field to the estimated spherical harmonic coefficients.', 'config_table': '', 'display_text': 'This cookbook chapter describes an example of estimating a gravity field solution using GRACE observation data. For the respective month a set of spherical harmonic coefficients up to a maximum degree is determined. An example scenario for this task can be found at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGraceGravityfieldRecovery.zip\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGraceGravityfieldRecovery.zip</a> including the required GROOPS scripts and data sets for the gravity field recovery process. The provided scenario consists of a slightly simplified example as compared to the operational one. The background models are provided at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data/\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/data/</a>.</p><p> <h2 id=\"backgroundModels\">Background models</h2><p> The following background models were used during the data processing: <ul>    <li><b>Earth rotation</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a>    </li><li> <b>Moon, sun and planets ephemerides</b>: <a href=\"https://ipnpr.jpl.nasa.gov/progress_report/42-196/196C.pdf\">JPL DE432</a>    </li><li> <b>Earth tide</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a>    </li><li> <b>Ocean tide</b>: <a href=\"https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes/description-fes2014.html\">FES2014b</a>    </li><li> <b>Pole tide</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a>    </li><li> <b>Ocean pole tide</b>: <a href=\"https://doi.org/10.1029/2001JC001224\">Desai 2004</a>    </li><li> <b>Atmospheric tides</b>: <a href=\"https://doi.org/10.1029/2022MS003193\">TiME22</a>    </li><li> <b>Atmosphere and Ocean Dealiasing</b>: <a href=\"https://doi.org/10.1093/gji/ggx302\">AOD1B RL06</a>    </li><li> <b>Sub-monthly continental hydrology</b>: <a href=\"https://doi.org/10.2312/GFZ.b103-08095\">LSDM (ESMGFZ)</a>    </li><li> <b>Relativistic corrections</b>: <a href=\"https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html\">IERS 2010</a>  </li></ul>  These models were reduced during the analysis process and are not present in the solution. The <a href=\"https://doi.org/10.5194/essd-13-99-2021\">GOCO06s</a> model was used as the static gravity field as well as for the trend component and annual oscillation. In the script <code>000groopsBackgroundModels.xml</code> a monthly mean of the GOCO06s including the time-variable components is determined in form of time splines using <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>. This model is later added back to the final gravity solution.</p><p><h2 id=\"metadata\">Instrument data preparation</h2><p> The ITSG gravity field solutions are computed from the official GRACE L1B <a href=\"https://doi.org/10.5067/GRJPL-L1B03\">JPL (2018)</a> and GRACE-FO L1B <a href=\"https://doi.org/10.5067/GFL1B-ASJ04\">JPL (2019)</a> observation data. The data sets for this example are provided in GROOPS file format in the scenario folder.</p><p>The satellite-to-satellite-tracking (SST) data consists of: <ul>    <li><b>K-band range rates</b>   </li><li> <b>Light time correction</b>   </li><li> <b>Antenna offset corrections</b> </li></ul> </p><p>Additional observation data required for the processing comprises: <ul>    <li><b>Star camera observations</b>   </li><li> <b>Accelerometer data</b>   </li><li> <b>Approximate orbits</b>    </li><li> <b>Thruster data</b> </li></ul> </p><p>The determination of <ul>    <li><b>Kinematic orbits</b>   </li><li> <b>3x3 epoch covariances</b> </li></ul>  is depicted in <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a>. These data sets are also provided in the scenario folder.</p><p>Data preparation is handled in the script <code>010groopsInstruments.xml</code>. The approximate orbits (initial dynamic orbits) of the satellites, the star camera observations, the accelerometer data and the thruster data are resampled with a 5s sampling and small gaps in the data are filled using <a class=\"groops-program\" href=\"InstrumentResample.html\">InstrumentResample</a>. Gross outliers are removed using <a class=\"groops-program\" href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a> and the data is synchronized using  <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p>The approximate orbits are later used as a priori information for the dynamic orbit integration. In addition to the observed orientation of the spacecrafts (star camera observations), the nominal orientation is computed using <a class=\"groops-program\" href=\"SimulateStarCameraGrace.html\">SimulateStarCameraGrace</a>. The difference between observed and simulated orientation is determined using <a class=\"groops-program\" href=\"InstrumentStarCameraMultiply.html\">InstrumentStarCameraMultiply</a> and is employed in the outlier detection.</p><p>The accelerometer data is initially calibrated by estimating a bias using <a class=\"groops-program\" href=\"InstrumentAccelerometerEstimateBiasScale.html\">InstrumentAccelerometerEstimateBiasScale</a> with respect to simulated data created with <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>. For simulating accelerometer data a satellite model implying the satellite\\'s mass and surfaces is required. Such a model can be created with <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a>. Models for the GRACE and GRACE-FO satellites are also provided at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data/satelliteModel/\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops/data/satelliteModel/</a>. Non-gravitational forces comprising atmospheric drag, solar radiation pressure and albedo have to be modeled when simulating the accelerometer data. The acceleration bias parameters are determined as degree 3 time splines with 6h nodes. When determining these parameters the thruster events are excluded from the estimation.</p><p>The SST observations, the light time corrections and the antenna center corrections are synchronized with a 5s sampling together with simulated SST data created with <a class=\"groops-program\" href=\"SimulateSatelliteTracking.html\">SimulateSatelliteTracking</a>. Simulated data is used for the outlier detection of the original SST observations.</p><p>The sampling of the kinematic orbits is reduced to 60s using <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a> and an outlier detection is performed using the approximate dynamic orbits.</p><p>The approximate orbits, the star camera observations and the accelerometer data are divided into 24h arcs (variational arcs). The kinematic orbits, its 3x3 epoch covariances, KBR observations, light time corrections, antenna center corrections and star camera observations are divided into 3h arcs per day (short arcs). Additionally the approximate orbits and the star camera observations are also synchronized to short arcs.</p><p>Further information on instrument data preparation can be found in <a class=\"groops-ref\" href=\"cookbook.instrument.html\">Instrument data handling</a>.</p><p><h2 id=\"variational\">Variational equations</h2><p> In this processing step dynamic orbits are computed for a complete 24h orbit arc by integrating the forces acting on the GRACE/GRACE-FO satellites. Additionally, the state transition matrix is set up. The dynamic orbits are then fitted to kinematic orbits and SST observations in a least squares adjustment by co-estimating additional accelerometer calibration parameters together with the initial state vector. The newly estimated parameters are then used to re-estimate the dynamic orbits and setting up the new state transition matrix.</p><p>The script <code>020groopsVariational.xml</code> in the scenario folder implements the required processing steps. Time splines from a time-variable gravity field are estimated using <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>. In this step the static gravity field (GOCO06s) is combined with the following time-variable components: <ul>      <li><a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:     static gravity field     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#trend\">gravityfield:trend</a>     <ul>          </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>:       trend component of gravity field     </li></ul>      <li><a class=\"groops-class\" href=\"gravityfieldType.html#oscillation\">gravityfield:oscillation</a>     <ul>          </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldCos:potentialCoefficients</a>:       annual cosine component of gravity field         </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfieldSin:potentialCoefficients</a>:       annual sine component of gravity field     </li></ul>      <li><a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>: atmosphere and ocean dealiasing (AOD1B RL06)     </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: ocean tides (FES2014b)     </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: atmospheric tides (TiME22)     </li><li> <a class=\"groops-class\" href=\"tidesType.html#poleTide\">tides:poleTide</a>: pole tides (IERS 2010)     </li><li> <a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">tides:poleOceanTide</a>: ocean pole tides (IERS 2010) </li></ul>  <strong class=\"groops-config-element\">maxDegree</strong>=<code>220</code> and <strong class=\"groops-config-element\">sampling</strong>=<code>10/1440</code> is sufficient.</p><p>In <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a> the <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">variational equations</a> comprising the integrated orbit together with the state transition matrix are stored in <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">outputfileVariational</a>.</p><p>This program has to be executed for both GRACE or GRACE-FO satellites and it is recommended to use <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a>. <ul>      <li><a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">inputfileSatelliteModel</a>: satellite model from <code>020groopsInstruments.xml</code>     </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: the approximate orbits from <code>020groopsInstruments.xml</code>     </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>: the attitude file from <code>020groopsInstruments.xml</code>     </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a>: the accelerometer data from     <code>020groopsInstruments.xml</code>     </li><li> <strong class=\"groops-config-element\">forces</strong>: see below     </li><li> <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a>: JPL DE432     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gradientfield:potentialCoefficients</a>: a static gravity field (GOCO06s) with <strong class=\"groops-config-element\">maxDegree</strong>=<code>10</code> is more than sufficient. </li></ul> </p><p>The <a class=\"groops-class\" href=\"forcesType.html\">force models</a> include: <ul>    <li><a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>:         the previously estimated time-variable gravity field   </li><li> <a class=\"groops-class\" href=\"tidesType.html#astronomicalTide\">tides:astronomicalTide</a>: astronomical tides (based on JPL DE432 ephemerides)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#earthTide\">tides:earthTide</a>: Earth tide (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"miscAccelerationsType.html#relativisticEffect\">miscAccelerations:relativisticEffect</a>:         relativistic effects (IERS conventions) </li></ul> </p><p>In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> the integrated orbit (<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) is fitted to the kinematic orbit (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>) by least squares adjustment. The additional accelerometer calibration parameters can be defined by <ul>    <li><a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>: accelerometer scale factor (once per day)   </li><li> <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>: accelerometer bias (time spline with 6h nodes) </li></ul> </p><p>The observation equations (parameter sensitivity matrix) are computed by integration of the variational equations (<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) using a polynomial with <strong class=\"groops-config-element\">integrationDegree</strong>=<code>7</code>. <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> has to be executed per satellite.</p><p><a class=\"groops-program\" href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a> fits two dynamic orbits <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1/2</a> to the SST observations and the kinematic orbits. <ul>      <li><strong class=\"groops-config-element\">rightHandSide</strong>: input for observation vectors         <ul>              </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: K-band range rate observations             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: light time correction             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: antenna offset corrections             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit1</a>: kinematic orbit of satellite 1             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit2</a>: kinematic orbit of satellite 2         </li></ul>      <li><strong class=\"groops-config-element\">sstType</strong>: rangeRate     </li><li> <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1</a>: dynamic orbit and integrated state matrix of satellite 1     </li><li> <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational2</a>: dynamic orbit and integrated state matrix of satellite 2     </li><li> <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration1</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>     </li><li> <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration2</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>     </li><li> <strong class=\"groops-config-element\">integrationDegree</strong>: <code>7</code>     </li><li> <strong class=\"groops-config-element\">interpolationDegree</strong>: <code>7</code>     </li><li> <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>         <ul>              </li><li> <strong class=\"groops-config-element\">sigma</strong>: <code>1</code>         </li></ul>      <li><a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod1</a>         <ul>              </li><li> <strong class=\"groops-config-element\">sigma</strong>: 1             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>: 3x3 epoch covariances         </li></ul>      <li><a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod2</a>         <ul>              </li><li> <strong class=\"groops-config-element\">sigma</strong>: 1             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>: 3x3 epoch covariances         </li></ul>  </ul> The estimated accelerometer calibration parameters from <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> and <a class=\"groops-program\" href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a> are determined as corrections and stored in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>. Both correction estimates have to be summed up using <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>.</p><p>The dynamic orbit and the resulting accelerometer calibration parameters are now used to re-integrate the orbit once more using <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a> and introducing <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> as <strong class=\"groops-config-element\">estimatedParameters</strong>. This step usually ensures convergence. If the maximum orbit difference is still not sufficient this step can be repeated again.</p><p><h2 id=\"preprocessing\">Preprocessing</h2><p> The script <code>030groopsPreprocessing.xml</code> implements the following steps and settings. The program <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a> processes SST observations and kinematic orbit data, and performs a complete least squares adjustment for gravity field determination by computing the observations equations. It also allows for an iterative refinement of the stochastic model of the observations along with arc-wise variance factors through variance component estimation (VCE). Force model parameters (gravitational potential coefficients and accelerometer calibration parameters) are computed by integrating the parameter sensitivity matrix from the variational equations. Parameters describing effects due to the SST observation system and geometry (KBR antenna phase center variations) are computed using the dynamic orbits as a Taylor point. Short time gravity variations can be co-estimated together with the monthly mean gravity field. The autoregressive model sequence constraining the short time parameters is provided in the data folder. It is precomputed from hydrology and nontidal atmospheric and ocean background models. See <a href=\"https://doi.org/10.1007/s00190-019-01314-1\">Kvas 2019</a> for more information about this co-estimation.</p><p><ul>      <li><a class=\"groops-class\" href=\"observationType.html\">observation</a>: sstVariational         <ul>              </li><li> <strong class=\"groops-config-element\">rightHandSide</strong>:             <ul>                  </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: KBR range rates                 </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: light time correction                 </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>: antenna offset corrections                 </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit1</a>: kinematic orbit of satellite 1                 </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit2</a>: kinematic orbit of satellite 2             </li></ul>              <li><strong class=\"groops-config-element\">sstType</strong>: rangeRate             </li><li> <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1</a>: dynamic orbit and integrated state matrix of satellite 1             </li><li> <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational2</a>: dynamic orbit and integrated state matrix of satellite 2             </li><li> <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a>: JPL DE432             </li><li> <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>: spherical harmonics from <strong class=\"groops-config-element\">minDegree</strong>=<code>2</code> to <strong class=\"groops-config-element\">maxDegree</strong>=<code>60</code>             </li><li> <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>: high frequency parametrization             </li><li> <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration1</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>             </li><li> <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration2</a>: same as in In <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>             </li><li> <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>: antenna phase center variations (y and z for both satellites)             </li><li> <strong class=\"groops-config-element\">integrationDegree</strong>: 7             </li><li> <strong class=\"groops-config-element\">interpolationDegree</strong>: 7         </li></ul>      <li><a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>         <ul>              </li><li> <strong class=\"groops-config-element\">sigma</strong>: <code>1e-7</code>             </li><li> <strong class=\"groops-config-element\">sampling</strong>: 5 [seconds]         </li></ul>      <li><a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod1/2</a>         <ul>              </li><li> <strong class=\"groops-config-element\">sigma</strong>:  <code>2</code>             </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>: 3x3 epoch covariances             </li><li> <strong class=\"groops-config-element\">sampling</strong>: 60 [seconds]         </li></ul>      <li><strong class=\"groops-config-element\">estimateShortTimeVariations</strong>         <ul>              </li><li> <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>: AR models             </li><li> <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>: names                 <ul>                      </li><li> <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>: parametrizationGravity                     <ul>                          </li><li> <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrization</a>: high frequency parametrization                     </li></ul>                  </ul>         </ul> </ul></p><p><a class=\"groops-program\" href=\"ParameterSelection2IndexVector.html\">ParameterSelection2IndexVector</a> and <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a> with <a class=\"groops-class\" href=\"matrixGeneratorType.html#reorder\">matrix:reorder</a> can be used to extract the desired spherical harmonic coefficients from <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> and the respective standard deviations from <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a> up to a certain degree.</p><p>In the program <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> the estimated spherical harmonics coefficients are read with <a class=\"groops-class\" href=\"gravityfieldType.html#fromParametrization\">gravityfield:fromParametrization</a>. The monthly mean gravity field can be added back by additionally selecting the time splines created in <code>000groopsBackgroundModels.xml</code> using <a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>. The preprocessing solution is saved as a <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">spherical harmonics file</a>.</p><p><h2 id=\"monthlyNormals\">Setting up normal equations</h2><p> Normal equations are set up in the script <code>040groopsMonthlyNormals120.xml</code> using the program <a class=\"groops-program\" href=\"NormalsBuildShortTimeStaticLongTime.html\">NormalsBuildShortTimeStaticLongTime</a>. The time intervals which the normal equations are divided into are defined in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a>. The normal equations are based on <a class=\"groops-class\" href=\"observationType.html\">observation</a> including the SST data, the kinematic orbits and the variational equations. The parametrization of the gravity field can be set with <a class=\"groops-class\" href=\"parametrizationGravityType.html\">observation:parametrizationGravity</a> (e.g. spherical harmonics up to degree and order 120). Accelerometer calibration parameters and KBR antenna phase center variations can be parameterized using <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> and <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>. With <strong class=\"groops-config-element\">estimateShortTimeVariations</strong> short time variations of the gravity field can be co-estimated. The parameters selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> (e.g. linear splines with 6h nodes) are constrained by an <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>. Additional temporal variations (e.g. trend and annual oscillation) could be estimated with <strong class=\"groops-config-element\">estimateLongTimeVariations</strong>.</p><p><h2 id=\"monhtlySolve\">Solving normal equations</h2><p> The desired spherical harmonic coefficients are determined in the script <code>050groopsMonthlySolve.xml</code>. <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a> accumulates <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a> and solves the total combined system. Variance component estimation is used to determine the relative weighting of the individual normals, i.e. the arc-wise variances. The previously computed stochastic model of the observations remains unchanged. The estimated parameter vector (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>), the estimated accuracies (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>) and the full covariance matrix (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovariance</a>) can be saved. Using <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> the final solution can be saved as a <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">spherical harmonics file</a> by adding back the monthly mean gravity field to the estimated spherical harmonic coefficients.</p><p>'},\n'cookbook.regionalGeoid': { 'name': 'cookbook.regionalGeoid', 'key': 'cookbook.regionalGeoid', 'description': 'This shows the exemplary computation of a regional geoid using terrestrial gravimetric observations in combination with a global satellite model such as GOCO06s. The geoid is estimated in a least squares adjustment with a parametrization using radial basis functions. A detailed desciption of the method is given in Christian Pock (2017), Consistent Combination of Satellite and Terrestrial Gravity Field Observations in Regional Geoid Modeling. Dissertation TU Graz.    Here it is assumed that the measured absolute gravity data is given at points in ellipsoidal coordinates. The observed values should be converted to SI units  .      Matrix2GriddedData  to convert data from text file in tabular form.   A high resolution topography model is needed to reduce the observations. As the model heights are usually given in physical heights a reference geoid is needed to compute the correct ellipsoidal height.      NetCdf2GridRectangular  convert into groops format.    Gravityfield2GriddedData : Compute geoid heights using the GOCO06s model with          section  The topography grid      section       section  the GOCO06s model      section      Subtract ( factor =-1) GRS680 normal field.        GriddedDataCalculate : Generate a new combined griddedData file         with the orthometric height ( data0 ) and the geoid height ( data1 ).    GriddedTopography2PotentialCoefficients : Compute the gravitational potential in terms         of spherical harmonics up to a maximum degree of the global satellite model.         This is the part of the topography, which is already included in the global satellite model.         The integration boundaries are  radialUpperBound = data0+data1          and  radialLowerBound = data1 .   Calculate approximate reference gravity to reduce it from the observations.      Gravityfield2AbsoluteGravity           section  at observation positions      section  Centrifugal potential      section  full GOCO06s model      section            ( radialUpperBound = data0+data1 ,  radialLowerBound = data1 )      section            Subtract ( factor =-1) the potential part of the topography already included in the GOCO06s model.        GriddedDataCalculate  to calculate observed minus computed.    Large outliers can be removed in  GriddedDataCalculate  with  removalCriteria .     The residual gravity is parametrized in terms of Radial Basis Functions  section . The basis functions should be distributed on a regular  section  covering a somewhat larger area than the observations, see  section . The shape of the functions  section  should reflect the signal content of reduced observations and are defined by the coefficients.      RadialBasisSplines2KernelCoefficients           section  accuracies of GOCO06s model      maxDegree =7000. Complemented by Kaula\\'s rule of thumb       The maximum degree should correspond to the spatial resolution. Rule of thumb: the number of spherical harmonic coefficients   should roughly agree to the number of grid points if they would cover the complete Earth.  Setup the observation equations and accumulate the system of normal equations.    NormalsBuild           section  with            section               section         section              with  section             NormalsSolverVCE           section  from  NormalsBuild       section             towards zero means regularization towards the GOCO06s, which is reduced from the data.       Evaluate the estimated parameters and add back the reduced reference models.      Gravityfield2GriddedData : Compute approximate geoid heights using the GOCO06s model with          section  select a grid with target resolution at elliposid      section       section  GOCO06s model      section      Subtract ( factor =-1) GRS80 normal field.        GriddedDataCalculate : Move points from ellipsoid to geoid with  height = data0     Gravityfield2GriddedData           section  from above.      section       section            The solution vector   together with the RBF parametrization      section  GOCO06s model      section            ( radialUpperBound = data0+data1 ,  radialLowerBound = data1 )      section            Subtract ( factor =-1) the potential part of the topography already included in the GOCO06s model.      section            Subtract ( factor =-1) GRS80 normal field.      convertToHarmonics = no , otherwise the RBF are converted to harmonics up to degree 7000.        GriddedDataCalculate : Set  height =0 of the computed geoid grid.    GridRectangular2NetCdf', 'config_table': '', 'display_text': 'This shows the exemplary computation of a regional geoid using terrestrial gravimetric observations in combination with a global satellite model such as GOCO06s. The geoid is estimated in a least squares adjustment with a parametrization using radial basis functions. A detailed desciption of the method is given in Christian Pock (2017), Consistent Combination of Satellite and Terrestrial Gravity Field Observations in Regional Geoid Modeling. Dissertation TU Graz.</p><p> <h2>Gravimetric data</h2><p> Here it is assumed that the measured absolute gravity data is given at points in ellipsoidal coordinates. The observed values should be converted to SI units $m/s^2$. <ul>    <li><a class=\"groops-program\" href=\"Matrix2GriddedData.html\">Matrix2GriddedData</a> to convert data from text file in tabular form. </li></ul> </p><p></p><p><h2>Topography</h2><p> A high resolution topography model is needed to reduce the observations. As the model heights are usually given in physical heights a reference geoid is needed to compute the correct ellipsoidal height. <ul>    <li><a class=\"groops-program\" href=\"NetCdf2GridRectangular.html\">NetCdf2GridRectangular</a> convert into groops format.   </li><li> <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>: Compute geoid heights using the GOCO06s model with   <ul>      </li><li> <a class=\"groops-class\" href=\"gridType.html#file\">grid:file</a> The topography grid     </li><li> <a class=\"groops-class\" href=\"kernelType.html#geoidHeight\">kernel:geoidHeight</a>     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> the GOCO06s model     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>     Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) GRS680 normal field.   </li></ul>    <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>: Generate a new combined griddedData file         with the orthometric height (<code>data0</code>) and the geoid height (<code>data1</code>).   </li><li> <a class=\"groops-program\" href=\"GriddedTopography2PotentialCoefficients.html\">GriddedTopography2PotentialCoefficients</a>: Compute the gravitational potential in terms         of spherical harmonics up to a maximum degree of the global satellite model.         This is the part of the topography, which is already included in the global satellite model.         The integration boundaries are <strong class=\"groops-config-element\">radialUpperBound</strong>=<code>data0+data1</code>         and <strong class=\"groops-config-element\">radialLowerBound</strong>=<code>data1</code>. </li></ul> </p><p></p><p><h2>Reduce</h2><p> Calculate approximate reference gravity to reduce it from the observations. <ul>    <li><a class=\"groops-program\" href=\"Gravityfield2AbsoluteGravity.html\">Gravityfield2AbsoluteGravity</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"gridType.html#file\">grid:File</a> at observation positions     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#tides\">gravityfield:tides</a> Centrifugal potential     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> full GOCO06s model     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#topography\">gravityfield:topography</a>           (<strong class=\"groops-config-element\">radialUpperBound</strong>=<code>data0+data1</code>, <strong class=\"groops-config-element\">radialLowerBound</strong>=<code>data1</code>)     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>           Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) the potential part of the topography already included in the GOCO06s model.   </li></ul>    <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a> to calculate observed minus computed.   </li><li> Large outliers can be removed in <a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a> with <strong class=\"groops-config-element\">removalCriteria</strong>. </li></ul> </p><p></p><p> <h2>Radial Basis Functions (RBF)</h2><p> The residual gravity is parametrized in terms of Radial Basis Functions <a class=\"groops-class\" href=\"parametrizationGravityType.html#radialBasis\">parametrizationGravity:radialBasis</a>. The basis functions should be distributed on a regular <a class=\"groops-class\" href=\"gridType.html\">grid</a> covering a somewhat larger area than the observations, see <a class=\"groops-class\" href=\"borderType.html\">border</a>. The shape of the functions <a class=\"groops-class\" href=\"kernelType.html#coefficients\">kernel:coefficients</a> should reflect the signal content of reduced observations and are defined by the coefficients. <ul>    <li><a class=\"groops-program\" href=\"RadialBasisSplines2KernelCoefficients.html\">RadialBasisSplines2KernelCoefficients</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> accuracies of GOCO06s model     </li><li> <strong class=\"groops-config-element\">maxDegree</strong>=7000. Complemented by Kaula\\'s rule of thumb   </li></ul>  </ul> The maximum degree should correspond to the spatial resolution. Rule of thumb: the number of spherical harmonic coefficients $(\\\\text{maxDegree}+1)^2$ should roughly agree to the number of grid points if they would cover the complete Earth.</p><p></p><p><h2>Compute: Estimate parameters in a least squares adjustment</h2><p> Setup the observation equations and accumulate the system of normal equations. <ul>  <li><a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"normalEquationType.html#design\">normalEquation:design</a> with           <a class=\"groops-class\" href=\"observationType.html#terrestrial\">observation:terrestrial</a>     <ul>        </li><li> <a class=\"groops-class\" href=\"kernelType.html#disturbance\">kernel:disturbance</a>       </li><li> <a class=\"groops-class\" href=\"parametrizationGravityType.html#radialBasis\">parametrizationGravity:radialBasis</a>             with <a class=\"groops-class\" href=\"kernelType.html#coefficients\">kernel:coefficients</a>     </li></ul>    </ul> <li><a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"normalEquationType.html#file\">normalEquation:file</a> from <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>     </li><li> <a class=\"groops-class\" href=\"normalEquationType.html#regularization\">normalEquation:regularization</a>            towards zero means regularization towards the GOCO06s, which is reduced from the data.   </li></ul>  </ul></p><p><h2>Restore: Calculate the geoid solution</h2><p> Evaluate the estimated parameters and add back the reduced reference models. <ul>    <li><a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>: Compute approximate geoid heights using the GOCO06s model with   <ul>      </li><li> <a class=\"groops-class\" href=\"gridType.html\">grid</a> select a grid with target resolution at elliposid     </li><li> <a class=\"groops-class\" href=\"kernelType.html#geoidHeight\">kernel:geoidHeight</a>     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> GOCO06s model     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>     Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) GRS80 normal field.   </li></ul>    <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>: Move points from ellipsoid to geoid with <strong class=\"groops-config-element\">height</strong>=<code>data0</code>   </li><li> <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>   <ul>      </li><li> <a class=\"groops-class\" href=\"gridType.html#file\">grid:file</a> from above.     </li><li> <a class=\"groops-class\" href=\"kernelType.html#geoidHeight\">kernel:geoidHeight</a>     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#fromParametrization\">gravityfield:fromParametrization</a>           The solution vector $\\\\M x$ together with the RBF parametrization     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> GOCO06s model     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#topography\">gravityfield:topography</a>           (<strong class=\"groops-config-element\">radialUpperBound</strong>=<code>data0+data1</code>, <strong class=\"groops-config-element\">radialLowerBound</strong>=<code>data1</code>)     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>           Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) the potential part of the topography already included in the GOCO06s model.     </li><li> <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a>           Subtract (<strong class=\"groops-config-element\">factor</strong>=-1) GRS80 normal field.     </li><li> <strong class=\"groops-config-element\">convertToHarmonics</strong>=<code>no</code>, otherwise the RBF are converted to harmonics up to degree 7000.   </li></ul>    <li><a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>: Set <strong class=\"groops-config-element\">height</strong>=0 of the computed geoid grid.   </li><li> <a class=\"groops-program\" href=\"GridRectangular2NetCdf.html\">GridRectangular2NetCdf</a> </li></ul> </p><p></p><p>'},\n'AutoregressiveModel2CovarianceMatrix': { 'name': 'AutoregressiveModel2CovarianceMatrix', 'key': 'AutoregressiveModel2CovarianceMatrix', 'description': 'This program computes the covariance structure of a random process represented by an AR model sequence. The covariance matrix is determined by accumulating the normal equations of all AR models in  autoregressiveModelSequence  and inverting the combined normal equation matrix. For each output file in   This program computes the covariance structure of a random process represented by an AR model sequence. The covariance matrix is determined by accumulating the normal equations of all AR models in  , the covariance matrix of appropriate time lag is saved (the first file contains the auto-covariance, second file cross covariance and so on). The matrix for lag   describes the covariance between   and  , i.e.  .', 'config_table': 'outputfileCovarianceMatrix filename covariance matrix for each lag autoregressiveModelSequence autoregressiveModelSequenceType AR model sequence', 'display_text': 'This program computes the covariance structure of a random process represented by an AR model sequence. The covariance matrix is determined by accumulating the normal equations of all AR models in <strong class=\"groops-config-element\">autoregressiveModelSequence</strong> and inverting the combined normal equation matrix. For each output file in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovarianceMatrix</a>, the covariance matrix of appropriate time lag is saved (the first file contains the auto-covariance, second file cross covariance and so on). The matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\\\Sigma(t-h, t)$.'},\n'CovarianceFunction2DigitalFilter': { 'name': 'CovarianceFunction2DigitalFilter', 'key': 'CovarianceFunction2DigitalFilter', 'description': 'Computes digital filter coefficients for a   Computes digital filter coefficients for a   of given degree and order. The filter coefficients are computed by fitting them to an approximated impulse response represented by the cholesky factor of the covariance matrix. The parameter  warmup  determines from which element of the cholesky matrix the coefficients (default: half the covariance length) are fitted. Per default, the program computes filter coefficients which generate colored noise when applied to a white noise sequence. When  decorrelationFilter  is set, a decorrelation filter is computed which yields white noise when applied to colored noise.', 'config_table': 'outputfileFilter filename filter coefficients inputfileCovariance filename first column: time steps, following columns: covariance functions column uint Column with covariance function to be fitted warmup uint number of samples until diagonal of Cholesky factor is flat (default: half covariance length) numeratorDegree uint Maximum degree of numerator polynomial (MA constituent) denominatorDegree uint Maximum degree of denominator polynomial (AR constitutent) decorrelationFilter boolean compute a decorrelation filter', 'display_text': 'Computes digital filter coefficients for a <a class=\"groops-class\" href=\"digitalFilterType.html\">digital filter</a> of given degree and order. The filter coefficients are computed by fitting them to an approximated impulse response represented by the cholesky factor of the covariance matrix.</p><p>The parameter <strong class=\"groops-config-element\">warmup</strong> determines from which element of the cholesky matrix the coefficients (default: half the covariance length) are fitted.</p><p>Per default, the program computes filter coefficients which generate colored noise when applied to a white noise sequence. When <strong class=\"groops-config-element\">decorrelationFilter</strong> is set, a decorrelation filter is computed which yields white noise when applied to colored noise.'},\n'CovarianceFunction2PowerSpectralDensity': { 'name': 'CovarianceFunction2PowerSpectralDensity', 'key': 'CovarianceFunction2PowerSpectralDensity', 'description': 'One sided Power Spectral Density (PSD) from a covariance function. The first column of   One sided Power Spectral Density (PSD) from a covariance function. The first column of   should contain the time lag in seconds. Multiple covariance functions (in the following column)s are supported. The output is a  matrix  with first column contains the frequency   and the other columns the PSD  . Conversion between covariance function   and PSD   is performed by discrete cosine transformation:   See also  PowerSpectralDensity2CovarianceFunction .', 'config_table': 'outputfilePSD filename first column: frequency [Hz], other columns PSD [unit^2/Hz] inputfileCovarianceFunction filename first column: time steps, following columns: covariance functions', 'display_text': 'One sided Power Spectral Density (PSD) from a covariance function. The first column of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceFunction</a> should contain the time lag in seconds. Multiple covariance functions (in the following column)s are supported. The output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> with first column contains the frequency $[Hz]$ and the other columns the PSD $[unit^2/Hz]$.</p><p>Conversion between covariance function $c_j$ and PSD $p_k$ is performed by discrete cosine transformation: \\\\[ p_k = 2\\\\Delta t\\\\left(c_0 + c_{n-1} (-1)^k + \\\\sum_{j=1}^{n-2} 2 c_j \\\\cos(\\\\pi jk/(n-1))\\\\right). \\\\] See also <a class=\"groops-program\" href=\"PowerSpectralDensity2CovarianceFunction.html\">PowerSpectralDensity2CovarianceFunction</a>.'},\n'CovarianceMatrix2AutoregressiveModel': { 'name': 'CovarianceMatrix2AutoregressiveModel', 'key': 'CovarianceMatrix2AutoregressiveModel', 'description': 'This program computes a VAR(p) model from empirical covariance matrices. The   This program computes a VAR(p) model from empirical covariance matrices. The   represent the covariance structure of the process: the first file should contain the auto-covariance, the second the cross-covariance of lag one, the next cross-covariance of lag two and so on. Cross-covariance matrices   are defined as the cross-covariance between epoch   and  . If the process realizations   are arrange by ascending time stamps ( ), the covariance structure of the (stationary) process is therefore given by   The estimate AR model is saved as single matrix  outputfileAutoregressiveModel  according to the GROOPS AR model conventions.', 'config_table': 'outputfileAutoregressiveModel filename coefficients and white noise covariance of AR(p) model inputfileCovarianceMatrix filename file name of covariance matrix', 'display_text': 'This program computes a VAR(p) model from empirical covariance matrices. The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceMatrix</a> represent the covariance structure of the process: the first file should contain the auto-covariance, the second the cross-covariance of lag one, the next cross-covariance of lag two and so on.</p><p>Cross-covariance matrices $\\\\Sigma_{\\\\Delta_k}$ are defined as the cross-covariance between epoch $t-k$ and $t$. If the process realizations $x_{t}$ are arrange by ascending time stamps ($\\\\{\\\\dots, x_{t-2}, x_{t-1}, x_{t}, x_{t+1}, x_{t+2},\\\\dots\\\\}$), the covariance structure of the (stationary) process is therefore given by \\\\[ \\\\begin{bmatrix} \\\\Sigma & \\\\Sigma_{\\\\Delta_1} & \\\\Sigma_{\\\\Delta_2} & \\\\cdots \\\\\\\\ \\\\Sigma_{\\\\Delta_1}^T & \\\\Sigma & \\\\Sigma_{\\\\Delta_1} &  \\\\cdots \\\\\\\\ \\\\Sigma_{\\\\Delta_2}^T & \\\\Sigma_{\\\\Delta_1}^T & \\\\Sigma & \\\\cdots \\\\\\\\ \\\\vdots & \\\\vdots & \\\\vdots & \\\\ddots \\\\\\\\ \\\\end{bmatrix}. \\\\] The estimate AR model is saved as single matrix <strong class=\"groops-config-element\">outputfileAutoregressiveModel</strong> according to the GROOPS AR model conventions.'},\n'CovarianceMatrix2Correlation': { 'name': 'CovarianceMatrix2Correlation', 'key': 'CovarianceMatrix2Correlation', 'description': 'This program computes the pearson correlation coefficient  from a given covariance matrix stored in   This program computes the pearson correlation coefficient  . The result is stored in   This program computes the pearson correlation coefficient  .', 'config_table': 'outputfileCorrelationMatrix filename correlation matrix inputfileCovarianceMatrix filename covariance matrix', 'display_text': 'This program computes the pearson correlation coefficient \\\\[   \\\\rho_{ij} = \\\\frac{\\\\sigma_{ij}}{\\\\sigma_i \\\\sigma_j} \\\\]from a given covariance matrix stored in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceMatrix</a>. The result is stored in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCorrelationMatrix</a>.'},\n'PowerSpectralDensity2CovarianceFunction': { 'name': 'PowerSpectralDensity2CovarianceFunction', 'key': 'PowerSpectralDensity2CovarianceFunction', 'description': 'Covariance function from Power Spectral Density (PSD). The   Covariance function from Power Spectral Density (PSD). The   contains in the first column the frequency  , followed by (possibly multiple) PSDs  . The output is a  matrix , the first column containing time lag   and the other columns the covariance functions  . Conversion between PSD   and covariance function   is performed by discrete cosine transformation:   See also  CovarianceFunction2PowerSpectralDensity .', 'config_table': 'outputfileCovarianceFunction filename first column: time steps [seconds], following columns: covariance functions inputfilePSD filename first column: frequency [Hz], following columns PSD [unit^2/Hz]', 'display_text': 'Covariance function from Power Spectral Density (PSD). The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePSD</a> contains in the first column the frequency $[Hz]$, followed by (possibly multiple) PSDs $[unit^2/Hz]$. The output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>, the first column containing time lag $[s]$ and the other columns the covariance functions $[unit^2]$. Conversion between PSD $p_j$ and covariance function $c_k$ is performed by discrete cosine transformation: \\\\[ c_k = \\\\frac{1}{4\\\\Delta t (n-1)}\\\\left(p_0 + p_{n-1} (-1)^k + \\\\sum_{j=1}^{n-2} 2 p_j \\\\cos(\\\\pi jk/(n-1))\\\\right). \\\\] See also <a class=\"groops-program\" href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a>.'},\n'DoodsonAdmittanceInterpolation': { 'name': 'DoodsonAdmittanceInterpolation', 'key': 'DoodsonAdmittanceInterpolation', 'description': 'To visualize the interpolation of the minor tides. The output is a  matrix  with the first column containing the tidal frequency, the second column is the tide generating amplitude (from   To visualize the interpolation of the minor tides. The output is a  ), and the following columns the contribution of the major tides to the this tidal frequency as defined in in   To visualize the interpolation of the minor tides. The output is a  .', 'config_table': 'outputfile filename  inputfileAdmittance filename interpolation of minor constituents inputfileTideGeneratingPotential filename', 'display_text': 'To visualize the interpolation of the minor tides. The output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> with the first column containing the tidal frequency, the second column is the tide generating amplitude (from <a class=\"groops-class\" href=\"fileFormat_tideGeneratingPotential.html\">inputfileTideGeneratingPotential</a>), and the following columns the contribution of the major tides to the this tidal frequency as defined in in <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.</p><p>'},\n'DoodsonAdmittanceTimeSeries': { 'name': 'DoodsonAdmittanceTimeSeries', 'key': 'DoodsonAdmittanceTimeSeries', 'description': 'To visualize the interpolation of the minor tides it computes cosine multipliers of all major tides. Without admittance this would be a simple cos oscillation. The  outputfileTimeSeries  is an  instrument file  (MISCVALUES) containining the cos of all the major tides.', 'config_table': 'outputfileTimeSeries filename MISCVALUES (cos of major tides, ...) inputfileAdmittance filename cos/sin multipliers of the major tides timeSeries timeSeriesType', 'display_text': 'To visualize the interpolation of the minor tides it computes cosine multipliers of all major tides. Without admittance this would be a simple cos oscillation. The <strong class=\"groops-config-element\">outputfileTimeSeries</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) containining the cos of all the major tides.</p><p>'},\n'DoodsonArguments2TimeSeries': { 'name': 'DoodsonArguments2TimeSeries', 'key': 'DoodsonArguments2TimeSeries', 'description': 'Time series of doodson/fundamental arguments. The   Time series of doodson/fundamental arguments. The   contains the six Doodson arguments, followed by the five fundamental arguments in radians.', 'config_table': 'outputfileTimeSeries filename each epoch: 6 doodson args, 5 fundamental args [rad] timeSeries timeSeriesType', 'display_text': 'Time series of doodson/fundamental arguments. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> contains the six Doodson arguments, followed by the five fundamental arguments in radians.'},\n'DoodsonHarmonics2GriddedAmplitudeAndPhase': { 'name': 'DoodsonHarmonics2GriddedAmplitudeAndPhase', 'key': 'DoodsonHarmonics2GriddedAmplitudeAndPhase', 'description': 'This program reads a   This program reads a   and evaluates a single tidal constituent selected by  dooddson  (Doodson number or Darwin´s name, e.g. 255.555 or M2). This program computes the amplitude and phase from the cos and sin coefficients on a given   This program reads a  . The type of functional (e.g gravity anomalies or geoid heights) can be choosen with   This program reads a  . The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening . To visualize the results use  PlotMap .', 'config_table': 'outputfileGrid filename ampl, phase [-pi,pi], cos, sin inputfileDoodsonHarmonics filename  doodson doodson tidal constituent filter sphericalHarmonicsFilterType  grid gridType  kernel kernelType  minDegree uint  maxDegree uint  factor double the values on grid are multiplied by this factor R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program reads a <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonics</a> and evaluates a single tidal constituent selected by <strong class=\"groops-config-element\">dooddson</strong> (Doodson number or Darwin´s name, e.g. 255.555 or M2). This program computes the amplitude and phase from the cos and sin coefficients on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The type of functional (e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>. To visualize the results use <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.</p><p>'},\n'DoodsonHarmonics2PotentialCoefficients': { 'name': 'DoodsonHarmonics2PotentialCoefficients', 'key': 'DoodsonHarmonics2PotentialCoefficients', 'description': 'The   The   contains a Fourier series of a time variable gravitational potential at specific tidal frequencies (tides)  where   and   are spherical harmonics expansions. If set the expansions are limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . The   The   is not a single file but a series of files. For each spherical harmonics expansion   and   a separate file is created where the variables  variableLoopName ,  variableLoopDoodson ,  variableLoopCosSin  are set accordingly. The file name should contain these variables, e.g.  coeff.{name}.{doodson}.{cossin}.gfc . If  applyXi  the Doodson-Warburg phase correction (see IERS conventions) is applied to the cos/sin potentialCoefficients before.', 'config_table': 'outputfilePotentialCoefficients filename  variableLoopName string variable with darwins\\'s name of each constituent variableLoopDoodson string variable with doodson code of each constituent variableLoopCosSin string variable with \\'cos\\' or \\'sin\\' of each constituent variableLoopIndex string variable with index of each constituent (starts with zero) variableLoopCount string variable with total number of constituents inputfileDoodsonHarmonics filename  inputfileTideGeneratingPotential filename to compute Xi phase correction minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius applyXi boolean apply Doodson-Warburg phase correction (see IERS conventions)', 'display_text': 'The <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonics</a> contains a Fourier series of a time variable gravitational potential at specific tidal frequencies (tides) \\\\[ V(\\\\M x,t) = \\\\sum_{f} V_f^c(\\\\M x)\\\\cos(\\\\theta_f(t)) + V_f^s(\\\\M x)\\\\sin(\\\\theta_f(t)), \\\\]where $V_f^c(\\\\M x)$ and $V_f^s(\\\\M x)$ are spherical harmonics expansions. If set the expansions are limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> is not a single file but a series of files. For each spherical harmonics expansion $V_f^c(\\\\M x)$ and $V_f^s(\\\\M x)$ a separate file is created where the variables <strong class=\"groops-config-element\">variableLoopName</strong>, <strong class=\"groops-config-element\">variableLoopDoodson</strong>, <strong class=\"groops-config-element\">variableLoopCosSin</strong> are set accordingly. The file name should contain these variables, e.g. <code>coeff.{name}.{doodson}.{cossin}.gfc</code>.</p><p>If <strong class=\"groops-config-element\">applyXi</strong> the Doodson-Warburg phase correction (see IERS conventions) is applied to the cos/sin potentialCoefficients before.'},\n'DoodsonHarmonicsCalculateAdmittance': { 'name': 'DoodsonHarmonicsCalculateAdmittance', 'key': 'DoodsonHarmonicsCalculateAdmittance', 'description': 'Computes the admittance function to interpolate minor tides from tides given in   Computes the admittance function to interpolate minor tides from tides given in   using   Computes the admittance function to interpolate minor tides from tides given in  .', 'config_table': 'outputfileAdmittance filename  inputfileDoodsonHarmonics filename  inputfileTideGeneratingPotential filename TGP threshold double [m^2/s^2] only interpolate tides with TGP greater than threshold degreeInterpolation uint polynomial degree for interpolation degreeExtrapolation uint polynomial degree for extrapolation excludeDoodsonForInterpolation doodson major tides not used for interpolation', 'display_text': 'Computes the admittance function to interpolate minor tides from tides given in <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonics</a> using <a class=\"groops-class\" href=\"fileFormat_tideGeneratingPotential.html\">inputfileTideGeneratingPotential</a>.'},\n'DoodsonHarmonicsChangePartialTides': { 'name': 'DoodsonHarmonicsChangePartialTides', 'key': 'DoodsonHarmonicsChangePartialTides', 'description': 'Reads a file   Reads a file   and write it to   Reads a file  . If set the spherical harmonics expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The   Reads a file   and   Reads a file   can be used to filter the partial types that will be exported. Additional partial tides can be interpolated using the file   Reads a file  .', 'config_table': 'outputfileDoodsonHarmonics filename  inputfileDoodsonHarmonics filename  inputfileAdmittance filename interpolation of minor constituents useDoodson doodson use only these partial tides (additional tides will be interpolated) ignoreDoodson doodson ignore these partial tides minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'Reads a file <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonic</a> and write it to <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">outputfileDoodsonHarmonics</a>. If set the spherical harmonics expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The <a class=\"groops-class\" href=\"doodson.html\">useDoodson</a> and <a class=\"groops-class\" href=\"doodson.html\">ignoreDoodson</a> can be used to filter the partial types that will be exported. Additional partial tides can be interpolated using the file <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.'},\n'ModelEquilibriumTide': { 'name': 'ModelEquilibriumTide', 'key': 'ModelEquilibriumTide', 'description': 'Computes the equilibrium ocean tide of the long periodic  tideGeneratingPotential . The spherical harmonics expansion up to  maxDegree  with  GM  and  R  is estimated using a least squares adjustment. The   Computes the equilibrium ocean tide of the long periodic   must be a global regular grid with the vertically averaged seawater density over the ocean and zero over land. It takes iteratively self attraction and loading into account using the Love numbers   Computes the equilibrium ocean tide of the long periodic   and   Computes the equilibrium ocean tide of the long periodic  . Additionally the effects of the solid Earth tide are considered, both the gravitational (Love numbers  k20 ,  k20plus ) and the geometrical (Love numbers  h20,0 ,  h20,2 ) effect. See also  PotentialCoefficients2DoodsonHarmonics .', 'config_table': 'outputfilePotentialCoefficients filename includes the loading maxDegree uint  GM double Geocentric gravitational constant R double reference radius inputfileDensityGrid filename [kg/m^3] density of sea water, zero over land tideGeneratingPotential double [m^2/s^2] k20 double earth tide love number k20plus double earth tide love number h20_0 double earth tide love number h20_2 double earth tide love number inputfilePotentialLoadLoveNumber filename  inputfileDeformationLoadLoveNumber filename  iterationCount uint', 'display_text': 'Computes the equilibrium ocean tide of the long periodic <strong class=\"groops-config-element\">tideGeneratingPotential</strong>. The spherical harmonics expansion up to <strong class=\"groops-config-element\">maxDegree</strong> with <strong class=\"groops-config-element\">GM</strong> and <strong class=\"groops-config-element\">R</strong> is estimated using a least squares adjustment.</p><p>The <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileDensityGrid</a> must be a global regular grid with the vertically averaged seawater density over the ocean and zero over land.</p><p>It takes iteratively self attraction and loading into account using the Love numbers <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePotentialLoadLoveNumber</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDeformationLoadLoveNumber</a>.</p><p>Additionally the effects of the solid Earth tide are considered, both the gravitational (Love numbers <strong class=\"groops-config-element\">k20</strong>, <strong class=\"groops-config-element\">k20plus</strong>) and the geometrical (Love numbers <strong class=\"groops-config-element\">h20,0</strong>, <strong class=\"groops-config-element\">h20,2</strong>) effect.</p><p>See also <a class=\"groops-program\" href=\"PotentialCoefficients2DoodsonHarmonics.html\">PotentialCoefficients2DoodsonHarmonics</a>.</p><p>'},\n'PotentialCoefficients2DoodsonHarmonics': { 'name': 'PotentialCoefficients2DoodsonHarmonics', 'key': 'PotentialCoefficients2DoodsonHarmonics', 'description': 'Create a  DoodsonHarmonic file  from a list of cos/sin  potentialCoefficients  for given  doodson  (Doodson number or Darwin´s name, e.g. 255.555 or M2) tidal constituents. If  applyXi  the Doodson-Warburg phase correction (see IERS conventions) is applied before.', 'config_table': 'outputfileDoodsonHarmonics filename  inputfileTideGeneratingPotential filename to compute Xi phase correction constituent sequence  doodson doodson  inputfileCosPotentialCoefficients filename  inputfileSinPotentialCoefficients filename  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius applyXi boolean apply Doodson-Warburg phase correction (see IERS conventions)', 'display_text': 'Create a <a class=\"groops-file\" href=\"fileFormat_doodsonHarmonic.html\">DoodsonHarmonic file</a> from a list of cos/sin <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">potentialCoefficients</a> for given <strong class=\"groops-config-element\">doodson</strong> (Doodson number or Darwin´s name, e.g. 255.555 or M2) tidal constituents. If <strong class=\"groops-config-element\">applyXi</strong> the Doodson-Warburg phase correction (see IERS conventions) is applied before.'},\n'GnssAntennaDefinition2ParameterVector': { 'name': 'GnssAntennaDefinition2ParameterVector', 'key': 'GnssAntennaDefinition2ParameterVector', 'description': 'Estimates parameters of a parametrization of   Estimates parameters of a parametrization of  , which represents all antennas from   Estimates parameters of a parametrization of   matching the wildcard patterns of  name ,  serial ,  radome . The provided values at the area weighted grid points of the pattern of each gnssType are used as pseudo-observations. A subset of patterns can be selected with   Estimates parameters of a parametrization of  . The  GnssAntennaDefinition file  can be modified to the demands before with  GnssAntennaDefinitionCreate . See also  ParameterVector2GnssAntennaDefinition .', 'config_table': 'outputfileSolution filename  outputfileParameterNames filename  antennaCenterVariations parametrizationGnssAntennaType  inputfileAntennaDefinition filename  name string  serial string  radome string  types gnssType if not set, all types in the file are used zeroNaN boolean treat NaN values as zero, otherwise values are ignored', 'display_text': 'Estimates parameters of a parametrization of <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>, which represents all antennas from <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a> matching the wildcard patterns of <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">serial</strong>, <strong class=\"groops-config-element\">radome</strong>.</p><p>The provided values at the area weighted grid points of the pattern of each gnssType are used as pseudo-observations. A subset of patterns can be selected with <a class=\"groops-class\" href=\"gnssType.html\">types</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> can be modified to the demands before with <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.</p><p>See also <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>.'},\n'GnssAntennaDefinition2Skyplot': { 'name': 'GnssAntennaDefinition2Skyplot', 'key': 'GnssAntennaDefinition2Skyplot', 'description': 'Produce a  skyplot  of antenna center variations which can be plotted with  PlotMap . The first antenna from   Produce a   matching the wildcard patterns of  name ,  serial ,  radome  is used. For each antenna pattern (gnssType) a separate data column is computed. A subset of patterns can be selected with   Produce a  . Azimuth and elevation are written as ellipsoidal longitude and latitude in a  griddedData file . The choosen ellipsoid parameters  R  and  inverseFlattening  are arbitrary but should be the same as in   Produce a   and  PlotMap .', 'config_table': 'outputfileGriddedData filename data column for each gnssType inputfileAntennaDefinition filename  grid gridType  name string  serial string  radome string  types gnssType if not set, all types in the file are used R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'Produce a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">skyplot</a> of antenna center variations which can be plotted with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.</p><p>The first antenna from <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a> matching the wildcard patterns of <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">serial</strong>, <strong class=\"groops-config-element\">radome</strong> is used.</p><p>For each antenna pattern (gnssType) a separate data column is computed. A subset of patterns can be selected with <a class=\"groops-class\" href=\"gnssType.html\">types</a>.</p><p>Azimuth and elevation are written as ellipsoidal longitude and latitude in a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData file</a>. The choosen ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are arbitrary but should be the same as in <a class=\"groops-class\" href=\"gridType.html\">grid</a> and <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.</p><p>'},\n'GnssAntennaDefinitionCreate': { 'name': 'GnssAntennaDefinitionCreate', 'key': 'GnssAntennaDefinitionCreate', 'description': 'Create a  GNSS antenna definition file  (Antenna Center Variations, ACV) consisting of multiple antennas. The antennas can be created from scratch or can be selected from existing files. This program can also be used to modify existing files. Furthermore it can be used to create accuracy definition files containing azimuth and elevation dependent accuracy values for antennas. To create an accuracy pattern for phase observations with  1 mm  accuracy at zenith and no azimuth dependency, define a pattern with  type = L ,  values = 0.001/cos(zenith/rho) . The antennas in   Create a   are sorted by names and duplicates are removed (first one is kept).', 'config_table': 'outputfileAntennaDefinition filename  antenna gnssAntennaDefintionListType', 'display_text': 'Create a <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GNSS antenna definition file</a> (Antenna Center Variations, ACV) consisting of multiple antennas. The antennas can be created from scratch or can be selected from existing files. This program can also be used to modify existing files.</p><p>Furthermore it can be used to create accuracy definition files containing azimuth and elevation dependent accuracy values for antennas. To create an accuracy pattern for phase observations with <code>1 mm</code> accuracy at zenith and no azimuth dependency, define a pattern with <strong class=\"groops-config-element\">type</strong>=<code>L</code>, <strong class=\"groops-config-element\">values</strong>=<code>0.001/cos(zenith/rho)</code>.</p><p>The antennas in <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaDefinition</a> are sorted by names and duplicates are removed (first one is kept).'},\n'GnssAntennaNormalsConstraint': { 'name': 'GnssAntennaNormalsConstraint', 'key': 'GnssAntennaNormalsConstraint', 'description': 'Apply constraints to  normal equations  containing   Apply constraints to  . Usually the antenna center variations are estimated together with other parameters like station coordinates, signal biases and slant TEC in  GnssProcessing . This results in a rank deficient matrix as not all parameters can be separated. The deficient can be solved by adding pseudo observation equations as constraints. To separate antenna center variations and signal biases apply  constraint:mean  for each GNSS   Apply constraints to  . The observation equation for the integral mean of antenna center variations (ACV) in all azimuth   and elevation   dependent directions  is approximated by a grid defined by  deltaAzimuth ,  deltaZenith , and  maxZenith . To separate from station coordinates use  constraint:centerMean  and from slant TEC parameters use  constraint:TEC . The constraints are applied separately to all antennas matching the wildcard patterns of  name ,  serial ,  radome . See also  ParameterVector2GnssAntennaDefinition .', 'config_table': 'outputfileNormalEquation filename with applied constraints inputfileNormalEquation filename  constraint choice  center sequence zero center (x,y,z) of a single pattern type gnssType applied for each matching types applyWeight boolean from normal equations sigma double [m] centerMean sequence zero center (x,y,z) as (weighted) mean of all patterns applyWeight boolean from normal equations sigma double [m] constant sequence zero constant (mean of all directions) of a single pattern type gnssType applied for each matching types applyWeight boolean from normal equations sigma double [m] constantMean sequence zero constant (mean of all directions) as (weighted) mean of all patterns applyWeight boolean from normal equations sigma double [m] TEC sequence zero TEC computed as (weighetd) least squares from all types type gnssType applied for combination of matching types applyWeight boolean from normal equations sigma double [TECU] antennaCenterVariations parametrizationGnssAntennaType  antennaName string apply constraints to all machting antennas antennaSerial string apply constraints to all machting antennas antennaRadome string apply constraints to all machting antennas deltaAzimuth angle [degree] sampling of pattern to estimate center/constant deltaZenith angle [degree] sampling of pattern to estimate center/constant maxZenith angle [degree] sampling of pattern to estimate center/constant', 'display_text': 'Apply constraints to <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> containing <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>. Usually the antenna center variations are estimated together with other parameters like station coordinates, signal biases and slant TEC in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. This results in a rank deficient matrix as not all parameters can be separated. The deficient can be solved by adding pseudo observation equations as constraints.</p><p>To separate antenna center variations and signal biases apply <strong class=\"groops-config-element\">constraint:mean</strong> for each GNSS <a class=\"groops-class\" href=\"gnssType.html\">type</a>. The observation equation for the integral mean of antenna center variations (ACV) in all azimuth $A$ and elevation $E$ dependent directions \\\\[   0 = \\\\iint ACV(A,E)\\\\, d\\\\Phi \\\\approx \\\\sum_i ACV(A_i,E_i)\\\\, \\\\Delta\\\\Phi_i \\\\]is approximated by a grid defined by <strong class=\"groops-config-element\">deltaAzimuth</strong>, <strong class=\"groops-config-element\">deltaZenith</strong>, and <strong class=\"groops-config-element\">maxZenith</strong>.</p><p>To separate from station coordinates use <strong class=\"groops-config-element\">constraint:centerMean</strong> and from slant TEC parameters use <strong class=\"groops-config-element\">constraint:TEC</strong>.</p><p>The constraints are applied separately to all antennas matching the wildcard patterns of <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">serial</strong>, <strong class=\"groops-config-element\">radome</strong>.</p><p>See also <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>.'},\n'GnssAttitudeInfoCreate': { 'name': 'GnssAttitudeInfoCreate', 'key': 'GnssAttitudeInfoCreate', 'description': 'Creates attitude info file ( Instrument(MISCVALUES) ) used by  SimulateStarCameraGnss . One or more  attitudeInfo s can be specified. They are valid from  timeStart  until the start of the subsequent  attitudeInfo .  maxManeuverTime  is used by  SimulateStarCameraGnss  to look for ongoing orbit maneuvers before/after the given orbit that might affect the attitude at the beginning or end of a given orbit. Here is a list of GNSS satellite types for which the attitude behavior is known and their respective attitude modes and required parameters:    GPS-II/IIA  [1]      defaultMode : nominalYawSteering    midnightMode : shadowMaxYawSteeringAndRecovery    noonMode : catchUpYawSteering    maxYawRate : 0.12 deg/s    yawBias : 0.5 deg    maxManeuverTime : 2 h    GPS-IIR/IIR-M  [1]      defaultMode : nominalYawSteering    midnightMode : catchUpYawSteering    noonMode : catchUpYawSteering    maxYawRate : 0.2 deg/s    maxManeuverTime : 30 min    GPS-IIF  [2]      defaultMode : nominalYawSteering    midnightMode : shadowConstantYawSteering    noonMode : catchUpYawSteering    maxYawRate : 0.11 deg/s    yawBias : -0.7 deg    maxManeuverTime : 1.5 h    GLO-M  [3]      defaultMode : nominalYawSteering    midnightMode : shadowMaxYawSteeringAndStop    noonMode : centeredMaxYawSteering    maxYawRate : 0.25 deg/s    noonBetaThreshold : 2 deg    maxManeuverTime : 1.5 h    GAL-1  [4]      defaultMode : nominalYawSteering    midnightMode : smoothedYawSteering1    noonMode : smoothedYawSteering1    maxManeuverTime : 1.5 h    GAL-2  [4]      defaultMode : nominalYawSteering    midnightMode : smoothedYawSteering2    noonMode : smoothedYawSteering2    midnightBetaThreshold : 4.1 deg    noonBetaThreshold : 4.1 deg    activationThreshold : 10 deg    maxManeuverTime : 5656 s    BDS-2G/3G  [5, 6]      defaultMode : orbitNormal    midnightMode : orbitNormal    noonMode : orbitNormal    BDS-2I  [5]      defaultMode : nominalYawSteering    midnightMode : betaDependentOrbitNormal    noonMode : betaDependentOrbitNormal    maxYawRate : 0.085 deg/s    midnightBetaThreshold : 4 deg    noonBetaThreshold : 4 deg    activationThreshold : 5 deg    maxManeuverTime : 24 h    BDS-2M  [5]      defaultMode : nominalYawSteering    midnightMode : betaDependentOrbitNormal    noonMode : betaDependentOrbitNormal    maxYawRate : 0.159 deg/s    midnightBetaThreshold : 4 deg    noonBetaThreshold : 4 deg    activationThreshold : 5 deg    maxManeuverTime : 13 h    BDS-3I/3SI  [6]      defaultMode : nominalYawSteering    midnightMode : smoothedYawSteering2    noonMode : smoothedYawSteering2    midnightBetaThreshold : 3 deg    noonBetaThreshold : 3 deg    activationThreshold : 6 deg    maxManeuverTime : 5740 s    BDS-3M/3SM  [6]      defaultMode : nominalYawSteering    midnightMode : smoothedYawSteering2    noonMode : smoothedYawSteering2    midnightBetaThreshold : 3 deg    noonBetaThreshold : 3 deg    activationThreshold : 6 deg    maxManeuverTime : 3090 s    QZS-1  [7]      defaultMode : nominalYawSteering    midnightMode : betaDependentOrbitNormal    noonMode : betaDependentOrbitNormal    maxYawRate : 0.01 deg/s    yawBias : 180 deg    midnightBetaThreshold : 20 deg    noonBetaThreshold : 20 deg    activationThreshold : 18.5 deg    maxManeuverTime : 24 h    QZS-2G  [7]      defaultMode : orbitNormal    midnightMode : orbitNormal    noonMode : orbitNormal    yawBias : 180 deg    QZS-2I  [7]      defaultMode : nominalYawSteering    midnightMode : centeredMaxYawSteering    noonMode : centeredMaxYawSteering    maxYawRate : 0.055 deg/s    midnightBetaThreshold : 5 deg    noonBetaThreshold : 5 deg    maxManeuverTime : 1.5 h    Some specific satellites may deviate in their attitude behavior or parameters (e.g. G013-G040, R713, C005, C015, C017, J001). References for the attitude behavior information:          https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3       https://qzss.go.jp/en/technical/qzssinfo/index.html', 'config_table': 'outputfileAttitudeInfo filename  attitudeInfo sequence  timeStart time  defaultMode choice default attitude mode nominalYawSteering  yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) orbitNormal  keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) midnightMode choice attitude mode for maneuvers around orbit midnight nominalYawSteering  yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) orbitNormal  keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) catchUpYawSteering  yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) shadowMaxYawSteeringAndRecovery  yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight)) shadowMaxYawSteeringAndStop  yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached, then stop (e.g. GLO-M (midnight)) shadowConstantYawSteering  yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight)) centeredMaxYawSteering  yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) smoothedYawSteering1  yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) smoothedYawSteering2  yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) betaDependentOrbitNormal  switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) noonMode choice attitude mode for maneuvers around orbit noon nominalYawSteering  yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) orbitNormal  keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) catchUpYawSteering  yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) centeredMaxYawSteering  yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) smoothedYawSteering1  yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) smoothedYawSteering2  yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) betaDependentOrbitNormal  switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) maxYawRate double [degree/s] maximum yaw rate of the satellite yawBias double [degree] yaw bias applied in satellite attitude control system midnightBetaThreshold double [degree] limit midnight maneuver to this absolute angle of the Sun above/below the satellite orbital plane noonBetaThreshold double [degree] limit noon maneuver to this absolute angle of the Sun above/below the satellite orbital plane activationThreshold double [degree] limit maneuver to this yaw/Earth-spacecraft-Sun angle (depending on mode) maxManeuverTime double [s] maximum duration of maneuver or maximum maneuver lookup time before/after orbit start/end', 'display_text': 'Creates attitude info file (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">Instrument(MISCVALUES)</a>) used by <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>. One or more <strong class=\"groops-config-element\">attitudeInfo</strong>s can be specified. They are valid from <strong class=\"groops-config-element\">timeStart</strong> until the start of the subsequent <strong class=\"groops-config-element\">attitudeInfo</strong>. <strong class=\"groops-config-element\">maxManeuverTime</strong> is used by <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> to look for ongoing orbit maneuvers before/after the given orbit that might affect the attitude at the beginning or end of a given orbit.</p><p></p><p>Here is a list of GNSS satellite types for which the attitude behavior is known and their respective attitude modes and required parameters: <ul>  <li><b>GPS-II/IIA</b> [1] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: shadowMaxYawSteeringAndRecovery   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: catchUpYawSteering   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.12 deg/s   </li><li> <strong class=\"groops-config-element\">yawBias</strong>: 0.5 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 2 h </li></ul>  <li><b>GPS-IIR/IIR-M</b> [1] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: catchUpYawSteering   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: catchUpYawSteering   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.2 deg/s   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 30 min </li></ul>  <li><b>GPS-IIF</b> [2] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: shadowConstantYawSteering   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: catchUpYawSteering   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.11 deg/s   </li><li> <strong class=\"groops-config-element\">yawBias</strong>: -0.7 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h </li></ul>  <li><b>GLO-M</b> [3] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: shadowMaxYawSteeringAndStop   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: centeredMaxYawSteering   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.25 deg/s   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 2 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h </li></ul>  <li><b>GAL-1</b> [4] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering1   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering1   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h </li></ul>  <li><b>GAL-2</b> [4] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering2   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering2   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 4.1 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 4.1 deg   </li><li> <strong class=\"groops-config-element\">activationThreshold</strong>: 10 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 5656 s </li></ul>  <li><b>BDS-2G/3G</b> [5, 6] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: orbitNormal   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: orbitNormal   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: orbitNormal </li></ul>  <li><b>BDS-2I</b> [5] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: betaDependentOrbitNormal   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: betaDependentOrbitNormal   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.085 deg/s   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 4 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 4 deg   </li><li> <strong class=\"groops-config-element\">activationThreshold</strong>: 5 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 24 h </li></ul>  <li><b>BDS-2M</b> [5] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: betaDependentOrbitNormal   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: betaDependentOrbitNormal   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.159 deg/s   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 4 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 4 deg   </li><li> <strong class=\"groops-config-element\">activationThreshold</strong>: 5 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 13 h </li></ul>  <li><b>BDS-3I/3SI</b> [6] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering2   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering2   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 3 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 3 deg   </li><li> <strong class=\"groops-config-element\">activationThreshold</strong>: 6 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 5740 s </li></ul>  <li><b>BDS-3M/3SM</b> [6] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: smoothedYawSteering2   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: smoothedYawSteering2   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 3 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 3 deg   </li><li> <strong class=\"groops-config-element\">activationThreshold</strong>: 6 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 3090 s </li></ul>  <li><b>QZS-1</b> [7] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: betaDependentOrbitNormal   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: betaDependentOrbitNormal   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.01 deg/s   </li><li> <strong class=\"groops-config-element\">yawBias</strong>: 180 deg   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 20 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 20 deg   </li><li> <strong class=\"groops-config-element\">activationThreshold</strong>: 18.5 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 24 h </li></ul>  <li><b>QZS-2G</b> [7] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: orbitNormal   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: orbitNormal   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: orbitNormal   </li><li> <strong class=\"groops-config-element\">yawBias</strong>: 180 deg </li></ul>  <li><b>QZS-2I</b> [7] <ul>    </li><li> <strong class=\"groops-config-element\">defaultMode</strong>: nominalYawSteering   </li><li> <strong class=\"groops-config-element\">midnightMode</strong>: centeredMaxYawSteering   </li><li> <strong class=\"groops-config-element\">noonMode</strong>: centeredMaxYawSteering   </li><li> <strong class=\"groops-config-element\">maxYawRate</strong>: 0.055 deg/s   </li><li> <strong class=\"groops-config-element\">midnightBetaThreshold</strong>: 5 deg   </li><li> <strong class=\"groops-config-element\">noonBetaThreshold</strong>: 5 deg   </li><li> <strong class=\"groops-config-element\">maxManeuverTime</strong>: 1.5 h </li></ul>  </ul></p><p>Some specific satellites may deviate in their attitude behavior or parameters (e.g. G013-G040, R713, C005, C015, C017, J001).</p><p>References for the attitude behavior information: <ol>  <li><a href=\"https://doi.org/10.1007/s10291-008-0092-1\">Kouba (2009)</a> </li><li> <a href=\"https://doi.org/10.1007/s10291-016-0562-9\">Kuang et al. (2017)</a> </li><li> <a href=\"https://doi.org/10.1016/j.asr.2010.09.007\">Dilssner et al. (2011)</a> </li><li> <a href=\"https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3\" target=\"_blank\">https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3</a> </li><li> <a href=\"https://doi.org/10.1007/s10291-018-0783-1\">Wang et al. (2018)</a> </li><li> <a href=\"https://doi.org/10.1017/S0373463318000103\">Li et al. (2018)</a> </li><li> <a href=\"https://qzss.go.jp/en/technical/qzssinfo/index.html\" target=\"_blank\">https://qzss.go.jp/en/technical/qzssinfo/index.html</a> </li></ol>'},\n'GnssBiasClockAlignment': { 'name': 'GnssBiasClockAlignment', 'key': 'GnssBiasClockAlignment', 'description': 'This program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks). Each \\'group\\' of  transmitter s, usually a system like GPS or Galileo, is aligned individually by a constant shift over all transmitters. If  alignClocksByFreqNo  is set, GLONASS transmitters will be divided by frequency number into groups of nominally two transmitters. The offset between clocks and reference clocks will be shifted into receiver code biases, if  receiver  is provided.\" By setting  alignFreqNoBiasesAtReceiver  and providing  receiver , this program can further align GLONASS transmitter signal biases so that the differences between frequency number-dependent receiver signal biases are minimal, which helps if PPP users don\\'t set up individual signal biases per frequency number at the receiver. Alignment is done by computing signal bias residuals to the mean over all frequency numbers of a signal type at each receiver and then computing the means over all receivers for each frequency number and shifting those from the receiver signal biases to the transmitter signal biases. Internal consistency of the biases is not affected by this. If you only want to align GLONASS frequency numbers, provide the same clocks in   This program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks). Each \\'group\\' of   and   This program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks). Each \\'group\\' of  .', 'config_table': 'transmitter sequence one element per satellite outputfileClock filename aligned clock instrument file outputfileSignalBias filename (GLONASS only) aligned signal bias file inputfileClock filename clock instrument file inputfileReferenceClock filename reference clock instrument file inputfileSignalBias filename (GLONASS only) signal bias file inputfileTransmitterInfo filename transmitter platform file receiver sequence one element per station outputfileSignalBias filename aligned signal bias file inputfileSignalBias filename signal bias file alignClocksByFreqNo boolean align clocks for each GLONASS frequency number separately alignFreqNoBiasesAtReceiver boolean align frequency number-dependent code biases for each receiver', 'display_text': 'This program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks). Each \\'group\\' of <strong class=\"groops-config-element\">transmitter</strong>s, usually a system like GPS or Galileo, is aligned individually by a constant shift over all transmitters. If <strong class=\"groops-config-element\">alignClocksByFreqNo</strong> is set, GLONASS transmitters will be divided by frequency number into groups of nominally two transmitters. The offset between clocks and reference clocks will be shifted into receiver code biases, if <strong class=\"groops-config-element\">receiver</strong> is provided.\"</p><p>By setting <strong class=\"groops-config-element\">alignFreqNoBiasesAtReceiver</strong> and providing <strong class=\"groops-config-element\">receiver</strong>, this program can further align GLONASS transmitter signal biases so that the differences between frequency number-dependent receiver signal biases are minimal, which helps if PPP users don\\'t set up individual signal biases per frequency number at the receiver. Alignment is done by computing signal bias residuals to the mean over all frequency numbers of a signal type at each receiver and then computing the means over all receivers for each frequency number and shifting those from the receiver signal biases to the transmitter signal biases. Internal consistency of the biases is not affected by this.</p><p>If you only want to align GLONASS frequency numbers, provide the same clocks in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileReferenceClock</a>.'},\n'GnssEstimateClockShift': { 'name': 'GnssEstimateClockShift', 'key': 'GnssEstimateClockShift', 'description': 'This program estimates an epoch-wise clock shift in a constellation of GNSS satellites. Each separate  data  represents a satellite... (e.g. 32 GPS satellites). The shift to reference clocks can be estimated by providing   This program estimates an epoch-wise clock shift in a constellation of GNSS satellites. Each separate  . Clock shifts are estimated for each epoch given by   This program estimates an epoch-wise clock shift in a constellation of GNSS satellites. Each separate  .', 'config_table': 'outputfileShiftTimeSeries filename columns: mjd, clock shift data sequence e.g. satellite outputfileInstrument filename corrected clocks outputfileInstrumentDiff filename clock difference after correction inputfileInstrument filename input clocks inputfileInstrumentRef filename reference clocks (subtracted from input clocks) timeSeries timeSeriesType clock epochs margin double [s] margin for time comparison', 'display_text': 'This program estimates an epoch-wise clock shift in a constellation of GNSS satellites. Each separate <strong class=\"groops-config-element\">data</strong> represents a satellite... (e.g. 32 GPS satellites). The shift to reference clocks can be estimated by providing <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentRef</a>. Clock shifts are estimated for each epoch given by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>.'},\n'GnssGlonassFrequencyNumberUpdate': { 'name': 'GnssGlonassFrequencyNumberUpdate', 'key': 'GnssGlonassFrequencyNumberUpdate', 'description': 'Update/set GLONASS frequency number in   Update/set GLONASS frequency number in   files. The   Update/set GLONASS frequency number in   can be generated with  SinexMetadata2GlonassFrequencyNumber . See also  GnssAntex2AntennaDefinition .', 'config_table': 'outputfileTransmitterInfo filename templated for PRN list (variableNamePrn) inputfileTransmitterInfo filename templated for PRN list (variableNamePrn) inputfilePrn2FrequencyNumber filename matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber prn string PRN (e.g. R01) for transmitter info files variableNamePrn string variable name for PRN in transmitter info files', 'display_text': 'Update/set GLONASS frequency number in <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a> files. The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePrn2FrequencyNumber</a> can be generated with <a class=\"groops-program\" href=\"SinexMetadata2GlonassFrequencyNumber.html\">SinexMetadata2GlonassFrequencyNumber</a>.</p><p>See also <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.'},\n'GnssProcessing': { 'name': 'GnssProcessing', 'key': 'GnssProcessing', 'description': 'This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. The primary use cases of this program are:      GNSS satellite orbit determination and station network analysis     Kinematic orbit determination of LEO satellites     GNSS precise point positioning (PPP)   The observation epochs are defined by   This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.  and only observations at these epochs (within a  timeMargin ) are considered. To calculate observation equations from the tracks, the model parameters or unknown parameters need to be defined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined   This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. . Some of the   This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.  also include a priori models. Lastly it is required to define the process flow of the gnssProcessing. This is accomplished with a list of   This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. . Each step is processed consecutively. Some steps allow the selection of parameters, epochs, or the normal equation structure, which affects all subsequent steps. A minimal example consists of following steps:       This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. : iterative float solution with outlier downeighting     This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. :         fix ambiguities to integer and remove them from the normals     This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. : few iteration for final outlier downweighting     This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. :         write the output files defined in   This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.   If the program is run on multiple processes the   This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. s (stations or LEO satellites) are distributed over the processes. See also  GnssSimulateReceiver .', 'config_table': 'timeSeries timeSeriesType defines observation epochs timeMargin double [seconds] margin to consider two times identical transmitter gnssTransmitterGeneratorType constellation of GNSS satellites receiver gnssReceiverGeneratorType ground station network or LEO satellite earthRotation earthRotationType apriori earth rotation parametrization gnssParametrizationType models and parameters processingStep gnssProcessingStepType steps are processed consecutively', 'display_text': 'This program processes GNSS observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.</p><p>The primary use cases of this program are: <ul>    <li><a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>   </li><li> <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a>   </li><li> <a class=\"groops-ref\" href=\"cookbook.gnssPpp.html\">GNSS precise point positioning (PPP)</a> </li></ul> </p><p>The observation epochs are defined by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> and only observations at these epochs (within a <strong class=\"groops-config-element\">timeMargin</strong>) are considered.</p><p>To calculate observation equations from the tracks, the model parameters or unknown parameters need to be defined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a>. Some of the <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a> also include a priori models.</p><p>Lastly it is required to define the process flow of the gnssProcessing. This is accomplished with a list of <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingSteps</a>. Each step is processed consecutively. Some steps allow the selection of parameters, epochs, or the normal equation structure, which affects all subsequent steps. A minimal example consists of following steps: <ul>    <li><a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: iterative float solution with outlier downeighting   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">resolveAmbiguities</a>:         fix ambiguities to integer and remove them from the normals   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>: few iteration for final outlier downweighting   </li><li> <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>:         write the output files defined in <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a> </li></ul> </p><p>If the program is run on multiple processes the <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>s (stations or LEO satellites) are distributed over the processes.</p><p>See also <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>.'},\n'GnssReceiverDefinitionCreate': { 'name': 'GnssReceiverDefinitionCreate', 'key': 'GnssReceiverDefinitionCreate', 'description': 'Create a  GNSS receiver definition file .', 'config_table': 'outputfileGnssReceiverDefinition filename  receiverDefinition sequence  name string  serial string  version string  comment string  gnssType gnssType', 'display_text': 'Create a <a class=\"groops-file\" href=\"fileFormat_gnssReceiverDefinition.html\">GNSS receiver definition file</a>.'},\n'GnssResiduals2AccuracyDefinition': { 'name': 'GnssResiduals2AccuracyDefinition', 'key': 'GnssResiduals2AccuracyDefinition', 'description': 'Compute antenna accuracies from observation   Compute antenna accuracies from observation  . The   Compute antenna accuracies from observation   is needed to assign the residuals to the equipped antenna at observation times. The   Compute antenna accuracies from observation   contains at first step the same accuracy information for all antennas as the input file. Only the azimuth   and elevation   dependent grid points of the patterns where enough residuals are available (   minRedundancy ) are replaced by estimated accuracy  where   are the azimuth and elevation dependent residuals and   the corresponding redundancies (number of observations minus the contribution to the estimated parameters). The   Compute antenna accuracies from observation   can be modified to the demands before with  GnssAntennaDefinitionCreate  (e.g. with  antenna:resample ). To verify the results the   Compute antenna accuracies from observation   and the accumulated   Compute antenna accuracies from observation   of the computed pattern grid points can be written. Example: Analysis of TerraSAR-X residuals of one month shows that low elevation GPS satellites are not tracked by the onboard receiver. An estimation of accuracies for these directions is not possible from the residuals and the apriori accuracies are left untouched. The other directions show very low phase noise hardly elevation and azimuth dependent for L2W. A nearly zero mean indicates the use of adequate antennca center variations in the processing. See also  GnssResiduals2TransmitterAccuracyDefinition .', 'config_table': 'outputfileAccuracyDefinition filename elevation and azimuth dependent accuracy outputfileAntennaMean filename weighted mean of the residuals outputfileAntennaRedundancy filename redundancy of adjustment inputfileAccuracyDefinition filename apriori accuracies inputfileStationInfo filename to assign residuals to antennas isTransmitter boolean stationInfo is of a transmitter thresholdOutlier double ignore residuals with sigma/sigma0 greater than threshold minRedundancy double min number of residuals. to estimate sigma inputfileResiduals filename GNSS receiver residuals', 'display_text': 'Compute antenna accuracies from observation <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileResiduals</a>. The <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> is needed to assign the residuals to the equipped antenna at observation times.</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAccuracyDefinition</a> contains at first step the same accuracy information for all antennas as the input file. Only the azimuth $A$ and elevation $E$ dependent grid points of the patterns where enough residuals are available ($>$ <strong class=\"groops-config-element\">minRedundancy</strong>) are replaced by estimated accuracy \\\\[  \\\\sigma(A,E) = \\\\sqrt{\\\\frac{\\\\sum_i e_i^2(A,E)}{\\\\sum_i r_i(A,E)}}, \\\\]where $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the corresponding redundancies (number of observations minus the contribution to the estimated parameters).</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> can be modified to the demands before with <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a> (e.g. with <strong class=\"groops-config-element\">antenna:resample</strong>).</p><p>To verify the results the <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaMean</a> and the accumulated <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaRedundancy</a> of the computed pattern grid points can be written.</p><p>Example: Analysis of TerraSAR-X residuals of one month shows that low elevation GPS satellites are not tracked by the onboard receiver. An estimation of accuracies for these directions is not possible from the residuals and the apriori accuracies are left untouched. The other directions show very low phase noise hardly elevation and azimuth dependent for L2W. A nearly zero mean indicates the use of adequate antennca center variations in the processing.</p><p></p><p>See also <a class=\"groops-program\" href=\"GnssResiduals2TransmitterAccuracyDefinition.html\">GnssResiduals2TransmitterAccuracyDefinition</a>.'},\n'GnssResiduals2Skyplot': { 'name': 'GnssResiduals2Skyplot', 'key': 'GnssResiduals2Skyplot', 'description': 'Write GNSS residuals together with azimuth and elevation to be plotted with  PlotMap . Azimuth and elevation are written as ellipsoidal longitude and latitude in a  griddedData file . The choosen ellipsoid parameters  R  and  inverseFlattening  are arbitrary but should be the same as in  PlotMap . If with   Write GNSS residuals together with azimuth and elevation to be plotted with   (e.g. \\' ***G18 \\') a single transmitter is selected the azimuth and elevation are computed from the transmitter point of view. For each GNSS   Write GNSS residuals together with azimuth and elevation to be plotted with   an extra data column is created. A  GNSS residual file  includes additional information besides the residuals, which can also be selected with   Write GNSS residuals together with azimuth and elevation to be plotted with      A1* ,  E1* : azimuth and elevation at receiver  A2* ,  E2* : azimuth and elevation at transmitter  I** : Estimated slant total electron content (STEC)  Furthermore these files may include for each residual   Write GNSS residuals together with azimuth and elevation to be plotted with   information about the redundancy and the accuracy relation   of the estimated   versus the apriori   from the least squares adjustment. The 3 values (residuals, redundancy,  ) are coded with the same type. To get access to all values the corresponding type must be repeated in   Write GNSS residuals together with azimuth and elevation to be plotted with  .', 'config_table': 'outputfileGriddedData filename  type gnssType  typeTransmitter gnssType choose transmitter view, e.g. \\'***G18\\' inputfileResiduals filename GNSS receiver residuals R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'Write GNSS residuals together with azimuth and elevation to be plotted with <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>. Azimuth and elevation are written as ellipsoidal longitude and latitude in a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData file</a>. The choosen ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are arbitrary but should be the same as in <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>. If with <a class=\"groops-class\" href=\"gnssType.html\">typeTransmitter</a> (e.g. \\'<code>***G18</code>\\') a single transmitter is selected the azimuth and elevation are computed from the transmitter point of view.</p><p>For each GNSS <a class=\"groops-class\" href=\"gnssType.html\">type</a> an extra data column is created.</p><p>A <a class=\"groops-file\" href=\"fileFormat_instrument.html\">GNSS residual file</a> includes additional information besides the residuals, which can also be selected with <a class=\"groops-class\" href=\"gnssType.html\">type</a> <ul>  <li><code>A1*</code>, <code>E1*</code>: azimuth and elevation at receiver </li><li> <code>A2*</code>, <code>E2*</code>: azimuth and elevation at transmitter </li><li> <code>I**</code>: Estimated slant total electron content (STEC) </li></ul> </p><p>Furthermore these files may include for each residual <a class=\"groops-class\" href=\"gnssType.html\">type</a> information about the redundancy and the accuracy relation $\\\\sigma/\\\\sigma_0$ of the estimated $\\\\sigma$ versus the apriori $\\\\sigma_0$ from the least squares adjustment. The 3 values (residuals, redundancy, $\\\\sigma/\\\\sigma_0$) are coded with the same type. To get access to all values the corresponding type must be repeated in <a class=\"groops-class\" href=\"gnssType.html\">type</a>.</p><p>'},\n'GnssResiduals2TransmitterAccuracyDefinition': { 'name': 'GnssResiduals2TransmitterAccuracyDefinition', 'key': 'GnssResiduals2TransmitterAccuracyDefinition', 'description': 'Compute antenna accuracies from observation   Compute antenna accuracies from observation  . The   Compute antenna accuracies from observation   is needed to assign the residuals to the equipped antenna at observation times. The   Compute antenna accuracies from observation   contains at first step the same accuracy information for all antennas as the input file. Only the azimuth   and elevation   dependent grid points of the patterns where enough residuals are available (   minRedundancy ) are replaced by estimated accuracy  where   are the azimuth and elevation dependent residuals and   the corresponding redundancies (number of observations minus the contribution to the estimated parameters). The   Compute antenna accuracies from observation   can be modified to the demands before with  GnssAntennaDefinitionCreate  (e.g. with  antenna:resample ). To verify the results the   Compute antenna accuracies from observation   and the accumulated   Compute antenna accuracies from observation   of the computed pattern grid points can be written. See also  GnssResiduals2AccuracyDefinition .', 'config_table': 'outputfileAccuracyDefinition filename elevation and azimuth dependent accuracy outputfileAntennaMean filename weighted mean of the residuals outputfileAntennaRedundancy filename redundancy of adjustment inputfileAccuracyDefinition filename apriori accuracies inputfileTransmitterInfo filename to assign residuals to antennas minRedundancy double min number of residuals. to estimate sigma inputfileResiduals filename GNSS receiver residuals', 'display_text': 'Compute antenna accuracies from observation <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileResiduals</a>. The <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a> is needed to assign the residuals to the equipped antenna at observation times.</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAccuracyDefinition</a> contains at first step the same accuracy information for all antennas as the input file. Only the azimuth $A$ and elevation $E$ dependent grid points of the patterns where enough residuals are available ($>$ <strong class=\"groops-config-element\">minRedundancy</strong>) are replaced by estimated accuracy \\\\[  \\\\sigma(A,E) = \\\\sqrt{\\\\frac{\\\\sum_i e_i^2(A,E)}{\\\\sum_i r_i(A,E)}}, \\\\]where $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the corresponding redundancies (number of observations minus the contribution to the estimated parameters).</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> can be modified to the demands before with <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a> (e.g. with <strong class=\"groops-config-element\">antenna:resample</strong>).</p><p>To verify the results the <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaMean</a> and the accumulated <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outputfileAntennaRedundancy</a> of the computed pattern grid points can be written.</p><p>See also <a class=\"groops-program\" href=\"GnssResiduals2AccuracyDefinition.html\">GnssResiduals2AccuracyDefinition</a>.'},\n'GnssSignalBias2Matrix': { 'name': 'GnssSignalBias2Matrix', 'key': 'GnssSignalBias2Matrix', 'description': 'Computes signal biases for a given list of   Computes signal biases for a given list of  . If the type list is empty, all types contained in   Computes signal biases for a given list of   are used. The resulting   Computes signal biases for a given list of   contains a vector with an entry for each type.', 'config_table': 'outputfileMatrix filename  outputfileTypes filename ASCII list of types inputfileSignalBias filename  types gnssType if not set, all types in the file are used', 'display_text': 'Computes signal biases for a given list of <a class=\"groops-class\" href=\"gnssType.html\">types</a>. If the type list is empty, all types contained in <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBias</a> are used. The resulting <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> contains a vector with an entry for each type.'},\n'GnssSimulateReceiver': { 'name': 'GnssSimulateReceiver', 'key': 'GnssSimulateReceiver', 'description': 'This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  GnssProcessing , for example to conduct closed-loop simulations. One or more GNSS constellations must be defined via   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  . Receivers such as ground station networks or Low Earth Orbit (LEO) satellites can be defined via   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  . If multiple receivers defined an   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in   and   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in   are written for each single receiver with the  variable   {station}  being replaced by the receiver name. A list of simulated observation types can be defined via   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  . Noise can be added to both observations and clock errors via   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in   and   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  , respectively. Observation noise is interpreted as a factor that is multiplied to the accuracy derived from the accuracy pattern of the respective observation type (see   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in   in   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  ). The   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in   are used to simulate a priori models (e.g. troposphere, signal biases). Parameter settings and outputfiles are ignored. If the program is run on multiple processes the   This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in  s (stations or LEO satellites) are distributed over the processes.', 'config_table': 'outputfileGnssReceiver filename variable {station} available, simulated observations outputfileClock filename variable {station} available, simulated receiver clock errors timeSeries timeSeriesType defines observation epochs timeMargin double [seconds] margin to consider two times identical transmitter gnssTransmitterGeneratorType constellation of GNSS satellites receiver gnssReceiverGeneratorType ground station network or LEO satellite earthRotation earthRotationType apriori earth rotation parametrization gnssParametrizationType models and parameters observationType gnssType simulated observation types noiseObservation noiseGeneratorType [-] noise is multiplied with type accuracy pattern of receiver noiseClockReceiver noiseGeneratorType [m] noise added to the simulated receiver clock', 'display_text': 'This program simulates observations from receivers to GNSS satellites. These simulated observations can then be used in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>, for example to conduct closed-loop simulations.</p><p>One or more GNSS constellations must be defined via <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html\">transmitter</a>. Receivers such as ground station networks or Low Earth Orbit (LEO) satellites can be defined via <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>.</p><p>If multiple receivers defined an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileGnssReceiver</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileClock</a> are written for each single receiver with the <a class=\"groops-ref\" href=\"general.parser.html\">variable</a> <code>{station}</code> being replaced by the receiver name.</p><p>A list of simulated observation types can be defined via <a class=\"groops-class\" href=\"gnssType.html\">observationType</a>. Noise can be added to both observations and clock errors via <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseObervation</a> and <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseClockReceiver</a>, respectively. Observation noise is interpreted as a factor that is multiplied to the accuracy derived from the accuracy pattern of the respective observation type (see <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> in <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>).</p><p>The <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrization</a> are used to simulate a priori models (e.g. troposphere, signal biases). Parameter settings and outputfiles are ignored.</p><p>If the program is run on multiple processes the <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">receiver</a>s (stations or LEO satellites) are distributed over the processes.'},\n'InstrumentGnssReceiver2TimeSeries': { 'name': 'InstrumentGnssReceiver2TimeSeries', 'key': 'InstrumentGnssReceiver2TimeSeries', 'description': 'Convert selected GNSS observations or residuals into a simpler time series format. The  outputfileTimeSeries  is an  instrument file  (MISCVALUES). For each epoch the first data column contains the PRN, the second the satellite system, followed by a column for each GNSS   Convert selected GNSS observations or residuals into a simpler time series format. The  . As normally more than one GNSS transmitter is tracked per epoch, the output file has several lines per observed epoch (epochs with the same time, one for each transmitter). The second data column of the output contains a number representating the system    71: \\'G\\', GPS  82: \\'R\\', GLONASS  69: \\'E\\', GALILEO  67: \\'C\\', BDS  83: \\'S\\', SBAS  74: \\'J\\', QZSS  73: \\'I\\', IRNSS .  A  GNSS residual file  includes additional information besides the residuals, which can also be selected with   Convert selected GNSS observations or residuals into a simpler time series format. The      A1* ,  E1* : azimuth and elevation at receiver  A2* ,  E2* : azimuth and elevation at transmitter  I** : Estimated slant total electron content (STEC)  Furthermore these files may include for each residual   Convert selected GNSS observations or residuals into a simpler time series format. The   information about the redundancy and the accuracy relation   of the estimated   versus the apriori   from the least squares adjustment. The three values (residuals, redundancy,  ) are coded with the same type. To get access to all values the corresponding type must be repeated in   Convert selected GNSS observations or residuals into a simpler time series format. The  . Example: Selected GPS phase residuals (  Convert selected GNSS observations or residuals into a simpler time series format. The  =\\' L1*G \\' and   Convert selected GNSS observations or residuals into a simpler time series format. The  =\\' L2*G \\'). Plotted with  PlotGraph  with two   Convert selected GNSS observations or residuals into a simpler time series format. The   ( valueX =\\' data0 \\',   valueY =\\' 100*data3+data1 \\' and  valueY =\\' 100*data4+data1 \\' respectively).', 'config_table': 'outputfileTimeSeries filename Instrument (MISCVALUES): prn, system, values for each type inputfileGnssReceiver filename GNSS receiver observations or residuals type gnssType', 'display_text': 'Convert selected GNSS observations or residuals into a simpler time series format. The <strong class=\"groops-config-element\">outputfileTimeSeries</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES). For each epoch the first data column contains the PRN, the second the satellite system, followed by a column for each GNSS <a class=\"groops-class\" href=\"gnssType.html\">type</a>. As normally more than one GNSS transmitter is tracked per epoch, the output file has several lines per observed epoch (epochs with the same time, one for each transmitter).</p><p>The second data column of the output contains a number representating the system <ul>  <li>71: \\'G\\', GPS </li><li> 82: \\'R\\', GLONASS </li><li> 69: \\'E\\', GALILEO </li><li> 67: \\'C\\', BDS </li><li> 83: \\'S\\', SBAS </li><li> 74: \\'J\\', QZSS </li><li> 73: \\'I\\', IRNSS . </li></ul> </p><p>A <a class=\"groops-file\" href=\"fileFormat_instrument.html\">GNSS residual file</a> includes additional information besides the residuals, which can also be selected with <a class=\"groops-class\" href=\"gnssType.html\">type</a> <ul>  <li><code>A1*</code>, <code>E1*</code>: azimuth and elevation at receiver </li><li> <code>A2*</code>, <code>E2*</code>: azimuth and elevation at transmitter </li><li> <code>I**</code>: Estimated slant total electron content (STEC) </li></ul> </p><p>Furthermore these files may include for each residual <a class=\"groops-class\" href=\"gnssType.html\">type</a> information about the redundancy and the accuracy relation $\\\\sigma/\\\\sigma_0$ of the estimated $\\\\sigma$ versus the apriori $\\\\sigma_0$ from the least squares adjustment. The three values (residuals, redundancy, $\\\\sigma/\\\\sigma_0$) are coded with the same type. To get access to all values the corresponding type must be repeated in <a class=\"groops-class\" href=\"gnssType.html\">type</a>.</p><p>Example: Selected GPS phase residuals (<a class=\"groops-class\" href=\"gnssType.html\">type</a>=\\'<code>L1*G</code>\\' and <a class=\"groops-class\" href=\"gnssType.html\">type</a>=\\'<code>L2*G</code>\\'). Plotted with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a> with two <a class=\"groops-class\" href=\"plotGraphLayerType.html\">layer:linesAndPoints</a> (<strong class=\"groops-config-element\">valueX</strong>=\\'<code>data0</code>\\',  <strong class=\"groops-config-element\">valueY</strong>=\\'<code>100*data3+data1</code>\\' and <strong class=\"groops-config-element\">valueY</strong>=\\'<code>100*data4+data1</code>\\' respectively).'},\n'ParameterVector2GnssAntennaDefinition': { 'name': 'ParameterVector2GnssAntennaDefinition', 'key': 'ParameterVector2GnssAntennaDefinition', 'description': 'Updates an  GnssAntennaDefinition file  with estimated parameters which belongs to the parametrization   Updates an  . The   Updates an   contains all antennas from   Updates an  . The antenna center variations representend by the   Updates an   are added to the matching antennas. The  GnssAntennaDefinition file  can be modified to the demands before with  GnssAntennaDefinitionCreate . The following steps are used to estimate antenna center variations:    GnssAntennaDefinitionCreate  or  GnssAntex2AntennaDefinition   GnssProcessing  with  inputfileAntennaDefinition  as apriori       and writing  normal equations  with       parametrization of   Updates an    NormalsEliminate : eliminate all other than antenna parameters  NormalsAccumulate : accumulate normals over a sufficient long period  GnssAntennaNormalsConstraint : constrain unsolvable parameter linear combinations  NormalsSolverVCE : estimate the parameter vector  ParameterVector2GnssAntennaDefinition : update  inputfileAntennaDefinition   See also  ParameterVector2GnssAntennaDefinition ,  GnssAntennaNormalsConstraint .', 'config_table': 'outfileAntennaDefinition filename all apriori antennas inputfileAntennaDefinition filename apriori antennas antennaCenterVariations parametrizationGnssAntennaType  inputfileSolution filename  inputfileParameterNames filename', 'display_text': 'Updates an <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> with estimated parameters which belongs to the parametrization <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>. The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">outfileAntennaDefinition</a> contains all antennas from <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>. The antenna center variations representend by the <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a> are added to the matching antennas.</p><p>The <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition file</a> can be modified to the demands before with <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.</p><p>The following steps are used to estimate antenna center variations: <ul>  <li><a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a> or <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> </li><li> <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> with <strong class=\"groops-config-element\">inputfileAntennaDefinition</strong> as apriori       and writing <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> with       parametrization of <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a> </li><li> <a class=\"groops-program\" href=\"NormalsEliminate.html\">NormalsEliminate</a>: eliminate all other than antenna parameters </li><li> <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>: accumulate normals over a sufficient long period </li><li> <a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a>: constrain unsolvable parameter linear combinations </li><li> <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>: estimate the parameter vector </li><li> <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>: update <strong class=\"groops-config-element\">inputfileAntennaDefinition</strong> </li></ul> </p><p>See also <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>, <a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a>.'},\n'EnsembleAveragingScaleModel': { 'name': 'EnsembleAveragingScaleModel', 'key': 'EnsembleAveragingScaleModel', 'description': 'This programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits from residuals. The ensemble averaging method is used to characterize the average properties of signal shapes across all transit events. Each shape is assigned to one arc of 3 hours (default). This can be modefied by enabling  averagingInterval .', 'config_table': 'outputfileScaleModel filename  inputfileGrace1EclipseFactor filename GRACE-A eclipse factors computed with integrated orbit inputfileGrace2EclipseFactor filename GRACE-B eclipse factors computed with integrated orbit inputfileGraceResiduals filename SST Residuals timeMargin uint epochs before eclipse mode waveLength uint length of the sample wave averagingInterval sequence  nearestNeighborNumber uint', 'display_text': 'This programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits from residuals. The ensemble averaging method is used to characterize the average properties of signal shapes across all transit events. Each shape is assigned to one arc of 3 hours (default). This can be modefied by enabling <strong class=\"groops-config-element\">averagingInterval</strong>.'},\n'GraceAntennaCenterCorrectionArcCovariance': { 'name': 'GraceAntennaCenterCorrectionArcCovariance', 'key': 'GraceAntennaCenterCorrectionArcCovariance', 'description': 'This program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC) from the orientation covariance matrices provided in Level-1B products via variance propagation. By using the output   This program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC) from the orientation covariance matrices provided in Level-1B products via variance propagation. By using the output   in  PreprocessingSst , noise model distinguishes between the stationary noise of ranging observations and the non­stationary AOC noise. The covariances are derived from the partial derivative of the AOC w.r.t. the roll/pitch/yaw rotations and star camera covariances   This program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC) from the orientation covariance matrices provided in Level-1B products via variance propagation. By using the output   and   This program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC) from the orientation covariance matrices provided in Level-1B products via variance propagation. By using the output  . The covariances for the range-rates and range-acceleration are computed by differentiating an interpolation polynomial of degree  interpolationDegree .', 'config_table': 'outputfileSatelliteTrackingCovariance filename corrections for range, range-rate, and range-accelerations sstType choice  range   rangeRate   rangeAcceleration   inputfileOrbit1 filename  inputfileOrbit2 filename  inputfileStarCamera1 filename  inputfileStarCamera2 filename  inputfileScaCovariance1 filename  inputfileScaCovariance2 filename  sigmaAccelerometerX double [rad/s^2] sigmaAccelerometerY double [rad/s^2] sigmaAccelerometerZ double [rad/s^2] antennaCenters choice KBR antenna phase center value sequence  center1X double x-coordinate of antenna position in SRF [m] for GRACEA center1Y double y-coordinate of antenna position in SRF [m] for GRACEA center1Z double z-coordinate of antenna position in SRF [m] for GRACEA center2X double x-coordinate of antenna position in SRF [m] for GRACEB center2Y double y-coordinate of antenna position in SRF [m] for GRACEB center2Z double z-coordinate of antenna position in SRF [m] for GRACEB file sequence  inputAntennaCenters filename  interpolationDegree uint differentiation by polynomial approximation of degree n', 'display_text': 'This program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC) from the orientation covariance matrices provided in Level-1B products via variance propagation. By using the output <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSatelliteTrackingCovariance</a> in <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a>, noise model distinguishes between the stationary noise of ranging observations and the non­stationary AOC noise.</p><p>The covariances are derived from the partial derivative of the AOC w.r.t. the roll/pitch/yaw rotations and star camera covariances <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileScaCovariance1</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileScaCovariance2</a>.</p><p>The covariances for the range-rates and range-acceleration are computed by differentiating an interpolation polynomial of degree <strong class=\"groops-config-element\">interpolationDegree</strong>.'},\n'GraceOrbit2TransplantTimeOffset': { 'name': 'GraceOrbit2TransplantTimeOffset', 'key': 'GraceOrbit2TransplantTimeOffset', 'description': 'This program computes the time shift between two co-orbiting satellites based on dynamic orbit data. When applied to data of the first satellite, the computed time shift virtually shifts data of first satellite into the location of the second satellite. Note that  inputfileOrbit1  and  inputfileOrbit2  need velocity and acceleration data, which can be computed with  OrbitAddVelocityAndAcceleration . The program tries to find a minimum of the objective function  by applying Newton\\'s method to the first derivative, thus iteratively computing  This iteration is stopped when the difference between to consecutive time shift values falls below  threshold  or  maximumIterations  is reached. An  initialGuess  of the time shift can speed up convergence. See also  OrbitAddVelocityAndAcceleration  and  InstrumentApplyTimeOffset .', 'config_table': 'outputfileTimeOffset filename estimated time offset in seconds (MISCVALUE) inputfileOrbit1 filename orbit data of satellite 1 inputfileOrbit2 filename orbit data of satellite 2 interpolationDegree uint polynomial degree for the interpolation of position, velocity and acceleration initialGuess double initial guess for the time shift [seconds] maximumIterations uint maximum number of iterations threshold double when the maximum difference between two iterations is below this value, stop [seconds]', 'display_text': 'This program computes the time shift between two co-orbiting satellites based on dynamic orbit data. When applied to data of the first satellite, the computed time shift virtually shifts data of first satellite into the location of the second satellite. Note that <strong class=\"groops-config-element\">inputfileOrbit1</strong> and <strong class=\"groops-config-element\">inputfileOrbit2</strong> need velocity and acceleration data, which can be computed with <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>. The program tries to find a minimum of the objective function \\\\[   f(\\\\Delta t) = \\\\| r_1(t) - r_2(t + \\\\Delta t) \\\\|^2, \\\\]by applying Newton\\'s method to the first derivative, thus iteratively computing \\\\[   \\\\Delta t_{k+1} = \\\\Delta t_k + \\\\frac{f\\'(\\\\Delta t_k)}{f\\'\\'(\\\\Delta t_k)}. \\\\]This iteration is stopped when the difference between to consecutive time shift values falls below <strong class=\"groops-config-element\">threshold</strong> or <strong class=\"groops-config-element\">maximumIterations</strong> is reached. An <strong class=\"groops-config-element\">initialGuess</strong> of the time shift can speed up convergence.</p><p>See also <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a> and <a class=\"groops-program\" href=\"InstrumentApplyTimeOffset.html\">InstrumentApplyTimeOffset</a>.'},\n'GraceSstResidualAnalysis': { 'name': 'GraceSstResidualAnalysis', 'key': 'GraceSstResidualAnalysis', 'description': 'This program applies the Multi-Resolution Analysis (MRA) using Discrete Wavelet Transform (DWT) to the monthly GRACE SST post-fit residuals. First, the residuals are transferred into wavelet domain by applying an 8 level Daubechies wavelet transform (default). In the next step, detail coefficients are merged into three major groups due to their approximate frequency subbands:    Low scale details, corresponding to the frequency band above 10 mHz;  Intermediate scale details, corresponding to the approximate frequency       range above 3 mHz up to 10 mHz;  High scale details, corresponding to the approximate frequency range above 0.5 mHz up to 10 mHz.   In the last step, each group is reconstructed back into time domain.', 'config_table': 'outputfileInstrumentHighScale filename High scale details outputfileInstrumentMidScale filename Intermediate scale details outputfileInstrumentLowScale filename Low scale details inputfileInstrument filename GRACE SST Residuals inputfileWavelet filename wavelet coefficients', 'display_text': 'This program applies the Multi-Resolution Analysis (MRA) using Discrete Wavelet Transform (DWT) to the monthly GRACE SST post-fit residuals. First, the residuals are transferred into wavelet domain by applying an 8 level Daubechies wavelet transform (default). In the next step, detail coefficients are merged into three major groups due to their approximate frequency subbands: <ul>  <li>Low scale details, corresponding to the frequency band above 10 mHz; </li><li> Intermediate scale details, corresponding to the approximate frequency       range above 3 mHz up to 10 mHz; </li><li> High scale details, corresponding to the approximate frequency range above 0.5 mHz up to 10 mHz. </li></ul>  In the last step, each group is reconstructed back into time domain.'},\n'GraceSstScaleModel': { 'name': 'GraceSstScaleModel', 'key': 'GraceSstScaleModel', 'description': 'This programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits and low-SNR values from post-fit residuals. The low-SNR effects are estimated by directly using the residual values. The ensemble averaging method is used to characterize the average properties of eclipse transit signal shapes across all transit events. Each shape is assigned to one arc of 3 hours (default). This can be modefied by enabling  averagingInterval .', 'config_table': 'inputfileGraceResiduals filename SST Residuals timeMargin uint epochs before instrumental events waveLength uint length of the sample wave estimateEclipseTransitScale sequence  outputfileScaleModel filename  inputfileGrace1EclipseFactor filename GRACE-A eclipse factors computed with integrated orbit inputfileGrace2EclipseFactor filename GRACE-B eclipse factors computed with integrated orbit averagingInterval sequence  nearestNeighborNumber uint  estimateLowSnrScale sequence  outputfileScaleModel filename  inputfileGraceSstSNR filename GRACE SNR values', 'display_text': 'This programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits and low-SNR values from post-fit residuals. The low-SNR effects are estimated by directly using the residual values. The ensemble averaging method is used to characterize the average properties of eclipse transit signal shapes across all transit events. Each shape is assigned to one arc of 3 hours (default). This can be modefied by enabling <strong class=\"groops-config-element\">averagingInterval</strong>.'},\n'GraceSstSpecialEvents': { 'name': 'GraceSstSpecialEvents', 'key': 'GraceSstSpecialEvents', 'description': 'Time-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. The events are determined by satellites\\' position (  Time-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. The events are determined by satellites\\' position ( ) and orientation (  Time-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. The events are determined by satellites\\' position ( ). Each type of event is represented by its mid-interval point per orbit revolution and is reported in   Time-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. The events are determined by satellites\\' position ( . The waveform of each event is nearly constant within one month and can be approximated by a polynomial. For the purpose of gravity field recovery, each waveform is parameterized by a polynomial and the coefficients of this polynomial are estimated as additional instrument calibration parameters in a common adjustment with all other instrument, satellite, and gravity field parameters, see   Time-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. The events are determined by satellites\\' position ( .', 'config_table': 'outputfileEvents filename  outputfileIntervals filename  inputfileOrbit1 filename  inputfileOrbit2 filename  inputfileStarCamera1 filename  inputfileStarCamera2 filename  ephemerides ephemeridesType  eclipse eclipseType  marginLeft double margin size (on both sides) [seconds] marginRight double margin size (on both sides) [seconds]', 'display_text': 'Time-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. The events are determined by satellites\\' position (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit1/2</a>) and orientation (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera1/2</a>). Each type of event is represented by its mid-interval point per orbit revolution and is reported in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileEvents</a>.</p><p>The waveform of each event is nearly constant within one month and can be approximated by a polynomial. For the purpose of gravity field recovery, each waveform is parameterized by a polynomial and the coefficients of this polynomial are estimated as additional instrument calibration parameters in a common adjustment with all other instrument, satellite, and gravity field parameters, see <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html#specialEffect\">parametrizationSatelliteTracking:specialEffect</a>.'},\n'GraceThrusterResponse2Accelerometer': { 'name': 'GraceThrusterResponse2Accelerometer', 'key': 'GraceThrusterResponse2Accelerometer', 'description': 'Add modeled thruster responses to accelerometer data. The epochs and durations are given in the   Add modeled thruster responses to accelerometer data. The epochs and durations are given in the   (THRUSTER). The   Add modeled thruster responses to accelerometer data. The epochs and durations are given in the   is a   matrix with the linear accelerations in the SRF ( ) in one line per pair:    Negative Yaw,  Positive Pitch,  Positive Yaw,  Negative Pitch,  Negative Roll,  Positive Roll.', 'config_table': 'outputfileAccelerometer filename ACCELEROMETER inputfileAccelerometer filename ACCELEROMETER inputfileThruster filename THRUSTER inputfileThrusterResponse filename thruster model (matrix with one line per pair)', 'display_text': 'Add modeled thruster responses to accelerometer data. The epochs and durations are given in the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileThruster</a> (THRUSTER).</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileThrusterResponse</a> is a $(6\\\\times 3)$ matrix with the linear accelerations in the SRF ($x, y, z$) in one line per pair: <ol>  <li>Negative Yaw, </li><li> Positive Pitch, </li><li> Positive Yaw, </li><li> Negative Pitch, </li><li> Negative Roll, </li><li> Positive Roll. </li></ol>'},\n'InstrumentSatelliteTrackingAntennaCenterCorrection': { 'name': 'InstrumentSatelliteTrackingAntennaCenterCorrection', 'key': 'InstrumentSatelliteTrackingAntennaCenterCorrection', 'description': 'This program computes the correction due to offset of the antenna center relative the center of mass. The offsets   and   in   This program computes the correction due to offset of the antenna center relative the center of mass. The offsets   are given in the satellite reference frame. These offsets are rotated into the the inertial frame with   and   from   This program computes the correction due to offset of the antenna center relative the center of mass. The offsets   and projected onto the line of sight (LOS)  with the unit vector in line of sight direction  The corrections for the range-rates and range-acceleration are computed by differentiating an interpolation polynomial of degree  interpolationDegree .', 'config_table': 'outputfileSatelliteTracking filename corrections for range, range-rate, and range-accelerations inputfileOrbit1 filename  inputfileOrbit2 filename  inputfileStarCamera1 filename  inputfileStarCamera2 filename  antennaCenters choice KBR antenna phase center value sequence  center1X double x-coordinate of antenna position in SRF [m] for GRACEA center1Y double y-coordinate of antenna position in SRF [m] for GRACEA center1Z double z-coordinate of antenna position in SRF [m] for GRACEA center2X double x-coordinate of antenna position in SRF [m] for GRACEB center2Y double y-coordinate of antenna position in SRF [m] for GRACEB center2Z double z-coordinate of antenna position in SRF [m] for GRACEB file sequence  inputAntennaCenters filename  interpolationDegree uint differentiation by polynomial approximation of degree n', 'display_text': 'This program computes the correction due to offset of the antenna center relative the center of mass. The offsets $\\\\M c_A$ and $\\\\M c_B$ in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileAntennaCenters</a> are given in the satellite reference frame. These offsets are rotated into the the inertial frame with $\\\\M D_A$ and $\\\\M D_B$ from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> and projected onto the line of sight (LOS) \\\\[   \\\\rho_{AOC} = \\\\M e_{AB}\\\\cdot(\\\\M D_A\\\\,\\\\M c_A - \\\\M D_B\\\\,\\\\M c_B), \\\\]with the unit vector in line of sight direction \\\\[   \\\\M e_{AB} = \\\\frac{\\\\M r_B - \\\\M r_A}{\\\\left\\\\lVert{\\\\M r_B - \\\\M r_A}\\\\right\\\\rVert}. \\\\]The corrections for the range-rates and range-acceleration are computed by differentiating an interpolation polynomial of degree <strong class=\"groops-config-element\">interpolationDegree</strong>.'},\n'InstrumentStarCameraAngularAccelerometerFusion': { 'name': 'InstrumentStarCameraAngularAccelerometerFusion', 'key': 'InstrumentStarCameraAngularAccelerometerFusion', 'description': 'This program estimates the satellites orientation from star camera data   This program estimates the satellites orientation from star camera data   and angular accelerometer data   This program estimates the satellites orientation from star camera data  . The combination of both observation types is achieved in a least square adjustment. The optimal weighting between the two different observation groups is achieved by means of VCE in combination with a robust estimator. The system of linearized observation equations within the sensor fusion approach can be formulated as:  with  The reference values   and   are derived from   This program estimates the satellites orientation from star camera data  . In the course of the estimation, the accelerometer data is calibrated, by setting a bias factor   with  accBias .', 'config_table': 'outputfileStarCamera filename combined quaternions outputfileCovariance filename epoch-wise covariance matrix outputfileCovarianceMatrix filename full arc-wise covariance matrix per arc. arc number is appended to filename outputfileEpochSigmaStarCamera filename from vce and outlier detection outputfileEpochSigmaAccelerometer filename from vce and outlier detection outputfileAngularAcc filename angular acceleration observations (bias removed) outputfileSolution filename estimated parameter (one column for each arc) inputfileStarCameraReference filename quaternions as taylor point inputfileStarCamera filename star camera observations inputfileStarCameraCovariance filename star camera observations inputfileAngularAcc filename angular acceleration observations correctAccNonQuadratic boolean apply correction (non-square proof mass) accBias parametrizationTemporalType accelerometer bias per interval and axis accScale parametrizationTemporalType accelerometer scale per interval and axis sigmaStarcamera double [rad] sigmaAccelerometerX double [rad/s^2] sigmaAccelerometerY double [rad/s^2] sigmaAccelerometerZ double [rad/s^2] estimateSigmaScaPerAxis boolean separate variance factor for roll, pitch, yaw, instead of one common factor. estimateSigmaAccPerAxis boolean separate variance factor for each accelerometer axis, instead of one common factor. huber double residuals > huber*sigma0 are downweighted huberPower double residuals > huber: sigma=(e/huber)^power*sigma0 interpolationDegree uint  iterationCount uint non linear equation solved iteratively', 'display_text': 'This program estimates the satellites orientation from star camera data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> and angular accelerometer data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAngularAcc</a>. The combination of both observation types is achieved in a least square adjustment. The optimal weighting between the two different observation groups is achieved by means of VCE in combination with a robust estimator. The system of linearized observation equations within the sensor fusion approach can be formulated as: \\\\[   \\\\begin{bmatrix}   \\\\M l_{ACC1B}\\\\\\\\   \\\\M l_{SCA1B}   \\\\end{bmatrix}   =   \\\\begin{bmatrix}   \\\\M A_{ACC1B} & \\\\M B_{ACC1B}\\\\\\\\   \\\\M A_{SCA1B} & \\\\M 0   \\\\end{bmatrix}   \\\\begin{bmatrix}   \\\\M q\\\\\\\\   \\\\M b   \\\\end{bmatrix}   =   \\\\begin{bmatrix}   \\\\frac{\\\\partial \\\\dot{\\\\boldsymbol{\\\\omega}}}{\\\\partial \\\\M q} & \\\\frac{\\\\partial \\\\dot{\\\\boldsymbol{\\\\omega}}}{\\\\partial \\\\M b}\\\\\\\\   \\\\M I & \\\\M 0   \\\\end{bmatrix}   \\\\begin{bmatrix}   \\\\M q\\\\\\\\   \\\\M b   \\\\end{bmatrix} \\\\]with \\\\[\\\\begin{split}   \\\\M l_{ACC1B}  &= \\\\dot{\\\\boldsymbol{\\\\omega}}_{ACC1B} - \\\\dot{\\\\boldsymbol{\\\\omega}}_{0}, \\\\\\\\   \\\\M l_{SCA1B}  &= \\\\M q_{SCA1B} - \\\\M q_{0}, \\\\\\\\   \\\\M q_{Fusion} &= \\\\M q + \\\\M q_{0}. \\\\end{split}\\\\]The reference values $\\\\M q_{0}$ and $\\\\dot{\\\\boldsymbol{\\\\omega}}_{0}$ are derived from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCameraReference</a>. In the course of the estimation, the accelerometer data is calibrated, by setting a bias factor $\\\\M b$ with <strong class=\"groops-config-element\">accBias</strong>.'},\n'Gravityfield2AbsoluteGravity': { 'name': 'Gravityfield2AbsoluteGravity', 'key': 'Gravityfield2AbsoluteGravity', 'description': 'This program computes the absolute value of gravity   of a   This program computes the absolute value of gravity   on a given   This program computes the absolute value of gravity  . The result is multiplicated with  factor . To get the full gravity vector in a terrestrial frame add the centrifugal part, see   This program computes the absolute value of gravity  . The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening . It is intended to compute gravity anomalies from absolute gravity observations. To visualize the results use  PlotMap .', 'config_table': 'outputfileGriddedData filename  grid gridType  gravityfield gravityfieldType  factor double the result is multiplied by this factor, set -1 to subtract the field time time at this time the gravity field will be evaluated R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program computes the absolute value of gravity $\\\\left\\\\lVert{\\\\M g}\\\\right\\\\rVert$ of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The result is multiplicated with <strong class=\"groops-config-element\">factor</strong>. To get the full gravity vector in a terrestrial frame add the centrifugal part, see <a class=\"groops-class\" href=\"tidesType.html#centrifugal\">gravityfield:tides:centrifugal</a>.</p><p>The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.</p><p>It is intended to compute gravity anomalies from absolute gravity observations. To visualize the results use <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.'},\n'Gravityfield2AreaMeanTimeSeries': { 'name': 'Gravityfield2AreaMeanTimeSeries', 'key': 'Gravityfield2AreaMeanTimeSeries', 'description': 'This program computes a time series of time variable   This program computes a time series of time variable   functionals averaged over a given area, e.g. equivalent water heights in the amazon basin.  The type of functional (e.g gravity anomalies or geoid heights) can be choosen with   This program computes a time series of time variable  . The average is performed at each time step by a weigthed average over all   This program computes a time series of time variable   points where the weight is the associated area at each point. If  removeMean  is set the temporal mean is removed from the time series. To speed up the computation the gravity field can be converted to spherical harmonics before the computation with  convertToHarmonics . Additionally the root mean square of the values in the area at each time step can is computed if  compueRms  is set. Additionally the accuracy of the value at each time step can be computed if  compueSigma  is set. The   This program computes a time series of time variable   is an instrument file with one, two, or three data columns. First data column contains the computed functionals and the following columns contain the RMS and the accuracies (optionally). To visualize the results use  PlotGraph .', 'config_table': 'outputfileTimeSeries filename  grid gridType  timeSeries timeSeriesType  kernel kernelType  gravityfield gravityfieldType  convertToHarmonics boolean gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation multiplyWithArea boolean multiply time series with total area (useful for mass estimates) removeMean boolean remove the temporal mean of the series computeRms boolean additional rms each time step computeSigma boolean additional error bars at each time step', 'display_text': 'This program computes a time series of time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> functionals averaged over a given area, e.g. equivalent water heights in the amazon basin.  The type of functional (e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. The average is performed at each time step by a weigthed average over all <a class=\"groops-class\" href=\"gridType.html\">grid</a> points where the weight is the associated area at each point. If <strong class=\"groops-config-element\">removeMean</strong> is set the temporal mean is removed from the time series. To speed up the computation the gravity field can be converted to spherical harmonics before the computation with <strong class=\"groops-config-element\">convertToHarmonics</strong>.</p><p>Additionally the root mean square of the values in the area at each time step can is computed if <strong class=\"groops-config-element\">compueRms</strong> is set.</p><p>Additionally the accuracy of the value at each time step can be computed if <strong class=\"groops-config-element\">compueSigma</strong> is set.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> is an instrument file with one, two, or three data columns. First data column contains the computed functionals and the following columns contain the RMS and the accuracies (optionally).</p><p>To visualize the results use <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.</p><p>'},\n'Gravityfield2Deflections': { 'name': 'Gravityfield2Deflections', 'key': 'Gravityfield2Deflections', 'description': 'This program computes the deflections of the vertical   in north direction and   in east direction in radian according to  where   is the gravity vector from   This program computes the deflections of the vertical   in the local ellipsoidal system (north, east, up) and   is the normal gravity at that point. The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening .', 'config_table': 'outputfileGriddedData filename xi (north), eta (east) [rad] grid gridType  gravityfield gravityfieldType  time time at this time the gravity field will be evaluated R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program computes the deflections of the vertical $\\\\xi$ in north direction and $\\\\eta$ in east direction in radian according to \\\\[ \\\\xi = g_x/\\\\gamma \\\\qquad\\\\text{and}\\\\qquad \\\\eta=g_y/\\\\gamma, \\\\]where $\\\\M g=\\\\nabla V$ is the gravity vector from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> in the local ellipsoidal system (north, east, up) and $\\\\gamma$ is the normal gravity at that point.</p><p>The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.'},\n'Gravityfield2DegreeAmplitudes': { 'name': 'Gravityfield2DegreeAmplitudes', 'key': 'Gravityfield2DegreeAmplitudes', 'description': 'This program computes degree amplitudes from a   This program computes degree amplitudes from a   and saves them to a  matrix  file with three columns: the degree, the degree amplitude, and the formal errors. The coefficients can be converted to different functionals with   This program computes degree amplitudes from a  . The gravity field can be evaluated at different altitudes by specifying  evaluationRadius . Polar regions can be excluded by setting  polarGap . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . See also  PotentialCoefficients2DegreeAmplitudes .', 'config_table': 'outputfileMatrix filename three column matrix with degree, signal amplitude, formal error gravityfield gravityfieldType  kernel kernelType  type choice type of variances rms  degree amplitudes (square root of degree variances) accumulation  cumulate variances over degrees median  median of absolute values per degree time time at this time the gravity field will be evaluated evaluationRadius double evaluate the gravity field at this radius (default: evaluate at surface polarGap angle exclude polar regions (aperture angle in degrees) minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'This program computes degree amplitudes from a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and saves them to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file with three columns: the degree, the degree amplitude, and the formal errors.</p><p>The coefficients can be converted to different functionals with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. The gravity field can be evaluated at different altitudes by specifying <strong class=\"groops-config-element\">evaluationRadius</strong>. Polar regions can be excluded by setting <strong class=\"groops-config-element\">polarGap</strong>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>See also <a class=\"groops-program\" href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a>.'},\n'Gravityfield2DegreeAmplitudesPlotGrid': { 'name': 'Gravityfield2DegreeAmplitudesPlotGrid', 'key': 'Gravityfield2DegreeAmplitudesPlotGrid', 'description': 'This program computes a   This program computes a   of a time variable   This program computes a   and saves it as degree amplitudes. The expansion is limited in the range between  minDegree  and  maxDegree  inclusivly   The   This program computes a   is a matrix with every row containing the time, degree, degree amplitude, and the formal error. To visualize the results use  PlotGraph ). See also  Gravityfield2DegreeAmplitudes .', 'config_table': 'outputfileTimeSeries filename each row: mjd, degree, amplitude, formal error gravityfield gravityfieldType  kernel kernelType  timeSeries timeSeriesType  evaluationRadius double evaluate the gravity field at this radius (default: evaluate at surface polarGap angle exclude polar regions (aperture angle in degrees) minDegree uint minimal degree maxDegree uint maximal degree GM double Geocentric gravitational constant R double reference radius', 'display_text': 'This program computes a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> of a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and saves it as degree amplitudes. The expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly \\\\[   \\\\sigma_n = \\\\frac{GM}{R}\\\\left(\\\\frac{R}{r}\\\\right)^{n+1}k_n\\\\sqrt{\\\\sum_{m=0}^n c_{nm}^2+s_{nm}^2}. \\\\] The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileTimeSeries</a> is a matrix with every row containing the time, degree, degree amplitude, and the formal error.</p><p>To visualize the results use <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>).</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a>.</p><p>'},\n'Gravityfield2DisplacementTimeSeries': { 'name': 'Gravityfield2DisplacementTimeSeries', 'key': 'Gravityfield2DisplacementTimeSeries', 'description': 'This program computes a time series of displacements of a list of stations (  This program computes a time series of displacements of a list of stations ( ) due to the effect of time variable loading masses. The displacement   of a station is calculated according to  where   is the normal gravity, the load Love and Shida numbers   are given by   This program computes a time series of displacements of a list of stations (  and the load Love numbers   are given by   This program computes a time series of displacements of a list of stations ( . The   are the spherical harmonics expansion of the full time variable gravitational potential (potential of the loading mass + deformation potential):  Deformations due to Earth tide and due to polar tides are computed using the IERS conventions. Eq.   is not used in these cases. The  outputfileTimeSeries  is an  instrument file , MISCVALUES. The data columns contain the deformation of each station in   in a global terrestrial reference frame or alternatively in a local elliposidal frame (north, east, up) if  localReferenceFrame  is set.', 'config_table': 'outputfileTimeSeries filename x,y,z [m] per station grid gridType station list timeSeries timeSeriesType  gravityfield gravityfieldType  tides tidesType  earthRotation earthRotationType  ephemerides ephemeridesType  inputfileDeformationLoadLoveNumber filename  inputfilePotentialLoadLoveNumber filename if full potential is given and not only loading potential removeMean boolean remove the temporal mean of each coordinate localReferenceFrame boolean local left handed reference frame (north, east, up)', 'display_text': 'This program computes a time series of displacements of a list of stations (<a class=\"groops-class\" href=\"gridType.html\">grid</a>) due to the effect of time variable loading masses. The displacement $\\\\M u$ of a station is calculated according to \\\\[\\\\label{eq:displacement} \\\\M u(\\\\M r) = \\\\frac{1}{\\\\gamma}\\\\sum_{n=0}^\\\\infty \\\\left[\\\\frac{h_n}{1+k_n}V_n(\\\\M r)\\\\,\\\\M e_{up} + R\\\\frac{l_n}{1+k_n}\\\\left(  \\\\frac{\\\\partial V_n(\\\\M r)}{\\\\partial \\\\M e_{north}}\\\\M e_{north} +\\\\frac{\\\\partial V_n(\\\\M r)}{\\\\partial \\\\M e_{east}} \\\\M e_{east}\\\\right)\\\\right], \\\\]where $\\\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDeformationLoadLoveNumber</a> and the load Love numbers $k_n$ are given by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePotentialLoadLoveNumber</a>. The $V_n$ are the spherical harmonics expansion of the full time variable gravitational potential (potential of the loading mass + deformation potential): \\\\[ V(\\\\M r) = \\\\sum_{n=0}^\\\\infty V_n(\\\\M r). \\\\]Deformations due to Earth tide and due to polar tides are computed using the IERS conventions. Eq. \\\\eqref{eq:displacement} is not used in these cases.</p><p>The <strong class=\"groops-config-element\">outputfileTimeSeries</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>, MISCVALUES. The data columns contain the deformation of each station in $x,y,z$ in a global terrestrial reference frame or alternatively in a local elliposidal frame (north, east, up) if <strong class=\"groops-config-element\">localReferenceFrame</strong> is set.'},\n'Gravityfield2EmpiricalCovariance': { 'name': 'Gravityfield2EmpiricalCovariance', 'key': 'Gravityfield2EmpiricalCovariance', 'description': 'This program estimates an spatial and temporal covariance matrix from a time series of gravity fields. Firstly for every time step   a spherical harmonics vector   from the time variable gravity field is generated. The coefficients of the spherical harmonics expansion are in the sequence given by   This program estimates an spatial and temporal covariance matrix from a time series of gravity fields. . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . In the next step the empirical covariance matrix is estimated according to  where   is given by  differenceStep . From the diagonal elements of   the isotropic accuracies are computed  and a diagonal matrix is constructed  . The result is computed:', 'config_table': 'outputfileCovarianceMatrix filename  outputfilePotentialCoefficients filename  gravityfield gravityfieldType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme for solution vector removeMean boolean  timeSeries timeSeriesType sampling of the gravityfield differenceStep uint choose dt for: x,i(t) - x,j(t+dt) factorFullMatrixPart double  factorIsotropicPart double  intervals timeSeriesType', 'display_text': 'This program estimates an spatial and temporal covariance matrix from a time series of gravity fields.</p><p>Firstly for every time step $t_i$ a spherical harmonics vector $\\\\M x_i$ from the time variable gravity field is generated. The coefficients of the spherical harmonics expansion are in the sequence given by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>In the next step the empirical covariance matrix is estimated according to \\\\[ \\\\M\\\\Sigma(\\\\Delta i)_{full} = \\\\frac{1}{N}\\\\sum_{i=1}^N \\\\M x_i \\\\M x_{i+\\\\Delta i}^T, \\\\]where $\\\\Delta i$ is given by <strong class=\"groops-config-element\">differenceStep</strong>.</p><p>From the diagonal elements of $\\\\M\\\\Sigma(\\\\Delta i)$ the isotropic accuracies are computed \\\\[ \\\\sigma_n^2 = \\\\frac{1}{2n+1}\\\\sum_{m=0}^n \\\\sigma_{cnm}^2+\\\\sigma_{snm}^2, \\\\]and a diagonal matrix is constructed $\\\\Sigma_{iso} = \\\\text{diag}(\\\\sigma_2^2,\\\\ldots,\\\\sigma_N^2)$. The result is computed: \\\\[ \\\\M\\\\Sigma(\\\\Delta i) = \\\\alpha_{full}\\\\M\\\\Sigma(\\\\Delta i)_{full}+\\\\alpha_{iso}\\\\M\\\\Sigma(\\\\Delta i)_{iso}. \\\\]'},\n'Gravityfield2Gradients': { 'name': 'Gravityfield2Gradients', 'key': 'Gravityfield2Gradients', 'description': 'This program computes gravity gradients from   This program computes gravity gradients from   on a   This program computes gravity gradients from   in a global terrestrial reference frame or alternatively in a local elliposidal frame (north, east, up) if  localReferenceFrame  is set. In   This program computes gravity gradients from   the values   will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening .', 'config_table': 'outputfileGriddedData filename Vxx Vyy Vzz Vxy Vxz Vyz grid gridType  gravityfield gravityfieldType  localReferenceFrame boolean local left handed reference frame (north, east, up) time time at this time the gravity field will be evaluated R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program computes gravity gradients from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in a global terrestrial reference frame or alternatively in a local elliposidal frame (north, east, up) if <strong class=\"groops-config-element\">localReferenceFrame</strong> is set. In <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> the values $[Vxx, Vyy, Vzz, Vxy, Vxz, Vyz]$ will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.'},\n'Gravityfield2GravityVector': { 'name': 'Gravityfield2GravityVector', 'key': 'Gravityfield2GravityVector', 'description': 'This program computes gravity vectors from   This program computes gravity vectors from   on a   This program computes gravity vectors from   in a global terrestrial reference frame or alternatively in a local elliposidal frame (north, east, up) if  localReferenceFrame  is set. In   This program computes gravity vectors from   the values   will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening .', 'config_table': 'outputfileGriddedData filename gx, gy, gz grid gridType  gravityfield gravityfieldType  localReferenceFrame boolean local left handed reference frame (north, east, up) time time at this time the gravity field will be evaluated R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program computes gravity vectors from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in a global terrestrial reference frame or alternatively in a local elliposidal frame (north, east, up) if <strong class=\"groops-config-element\">localReferenceFrame</strong> is set. In <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> the values $[gx, gy, gz]$ will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.'},\n'Gravityfield2GridCovarianceMatrix': { 'name': 'Gravityfield2GridCovarianceMatrix', 'key': 'Gravityfield2GridCovarianceMatrix', 'description': 'This program propagates the covariance matrix of a   This program propagates the covariance matrix of a   evaluated at  time  to a   This program propagates the covariance matrix of a  . The full variance-covariance matrix is computed and written to a  matrix file :  The   This program propagates the covariance matrix of a   determines the quantity of the grid values, for example,   This program propagates the covariance matrix of a  . See also  GravityfieldCovariancesPropagation2GriddedData ,  GravityfieldVariancesPropagation2GriddedData .', 'config_table': 'outputfileMatrix filename symmetric grid covariance matrix grid gridType  kernel kernelType  gravityfield gravityfieldType  time time at this time the gravity field will be evaluated', 'display_text': 'This program propagates the covariance matrix of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> evaluated at <strong class=\"groops-config-element\">time</strong> to a <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The full variance-covariance matrix is computed and written to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix file</a>: \\\\[ \\\\mathbf{\\\\Sigma}_\\\\mathbf{y} = \\\\mathbf{F}\\\\mathbf{\\\\Sigma}_\\\\mathbf{x}\\\\mathbf{F}^T \\\\]The <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> determines the quantity of the grid values, for example, <a class=\"groops-class\" href=\"kernelType.html#waterHeight\">kernel:waterHeight</a>.</p><p>See also <a class=\"groops-program\" href=\"GravityfieldCovariancesPropagation2GriddedData.html\">GravityfieldCovariancesPropagation2GriddedData</a>, <a class=\"groops-program\" href=\"GravityfieldVariancesPropagation2GriddedData.html\">GravityfieldVariancesPropagation2GriddedData</a>.'},\n'Gravityfield2GriddedData': { 'name': 'Gravityfield2GriddedData', 'key': 'Gravityfield2GriddedData', 'description': 'This program computes values of a   This program computes values of a   on a given   This program computes values of a  . The type of value (e.g gravity anomalies or geoid heights) can be choosen with   This program computes values of a  . If a time is given the gravity field will be evaluated at this point of time otherwise only the static part will be used. The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening . To speed up the computation the gravity field can be converted to spherical harmonics before the computation with  convertToHarmonics . To visualize the results use  PlotMap .', 'config_table': 'outputfileGriddedData filename  grid gridType  kernel kernelType  gravityfield gravityfieldType  convertToHarmonics boolean gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation time time at this time the gravity field will be evaluated R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program computes values of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The type of value (e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. If a time is given the gravity field will be evaluated at this point of time otherwise only the static part will be used. The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>. To speed up the computation the gravity field can be converted to spherical harmonics before the computation with <strong class=\"groops-config-element\">convertToHarmonics</strong>.</p><p>To visualize the results use <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.'},\n'Gravityfield2GriddedDataTimeSeries': { 'name': 'Gravityfield2GriddedDataTimeSeries', 'key': 'Gravityfield2GriddedDataTimeSeries', 'description': 'This program computes values of a   This program computes values of a   on a given   This program computes values of a   for each time step of   This program computes values of a  . The type of value (e.g gravity anomalies or geoid heights) can be choosen with   This program computes values of a  . To speed up the computation the gravity field can be converted to spherical harmonics before the computation with  convertToHarmonics . The   This program computes values of a   is an instrument (MISCVALUES) file with a data column for each grid point per epoch. This program enables the use of all instrument programs like  InstrumentFilter ,  InstrumentArcStatistics  or  InstrumentDetrend  to analyze and manipulate time series of gridded data. See also  TimeSeries2GriddedData ,  Gravityfield2GriddedData', 'config_table': 'outputfileTimeSeries filename each epoch: data of grid points (MISCVALUES) grid gridType  kernel kernelType  gravityfield gravityfieldType  convertToHarmonics boolean gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation timeSeries timeSeriesType', 'display_text': 'This program computes values of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a> for each time step of <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>. The type of value (e.g gravity anomalies or geoid heights) can be choosen with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. To speed up the computation the gravity field can be converted to spherical harmonics before the computation with <strong class=\"groops-config-element\">convertToHarmonics</strong>. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> is an instrument (MISCVALUES) file with a data column for each grid point per epoch.</p><p>This program enables the use of all instrument programs like <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a>, <a class=\"groops-program\" href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a> or <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> to analyze and manipulate time series of gridded data.</p><p>See also <a class=\"groops-program\" href=\"TimeSeries2GriddedData.html\">TimeSeries2GriddedData</a>, <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>'},\n'Gravityfield2PotentialCoefficients': { 'name': 'Gravityfield2PotentialCoefficients', 'key': 'Gravityfield2PotentialCoefficients', 'description': 'This program evaluates a time variable   This program evaluates a time variable   at a given  time  and saves it as a  spherical harmonics file . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM .', 'config_table': 'outputfilePotentialCoefficients filename  gravityfield gravityfieldType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius time time at this time the gravity field will be evaluated', 'display_text': 'This program evaluates a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> at a given <strong class=\"groops-config-element\">time</strong> and saves it as a <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">spherical harmonics file</a>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.'},\n'Gravityfield2PotentialCoefficientsTimeSeries': { 'name': 'Gravityfield2PotentialCoefficientsTimeSeries', 'key': 'Gravityfield2PotentialCoefficientsTimeSeries', 'description': 'This program computes a   This program computes a   of a time variable   This program computes a   and converts to coefficients of a spherical harmonics expansion. The expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . The   This program computes a   contains the potential coefficients as data columns for each epoch in the sequence given by   This program computes a  .', 'config_table': 'outputfileTimeSeries filename instrument file (MISCVALUES) gravityfield gravityfieldType  timeSeries timeSeriesType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme', 'display_text': 'This program computes a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> of a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and converts to coefficients of a spherical harmonics expansion. The expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> contains the potential coefficients as data columns for each epoch in the sequence given by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.'},\n'Gravityfield2SphericalHarmonicsVector': { 'name': 'Gravityfield2SphericalHarmonicsVector', 'key': 'Gravityfield2SphericalHarmonicsVector', 'description': 'This program evaluates a time variable   This program evaluates a time variable   at a given  time  and saves a  vector  with the coefficients of a spherical harmonics expansion in the sequence given by   This program evaluates a time variable  . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusively. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . This coefficients vector can be used as a approximate solution, see  NormalsMultiplyAdd , or as pseudo oberservations for regularization, see   This program evaluates a time variable  . For back transformation use  Gravityfield2PotentialCoefficients  with   This program evaluates a time variable  .', 'config_table': 'outputfileVector filename  gravityfield gravityfieldType  startIndex uint start index to put the coefficients in the solution vector minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme for solution vector time time at this time the gravity field will be evaluated useSigma boolean use formal errors instead of coefficients', 'display_text': 'This program evaluates a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> at a given <strong class=\"groops-config-element\">time</strong> and saves a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">vector</a> with the coefficients of a spherical harmonics expansion in the sequence given by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusively. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>This coefficients vector can be used as a approximate solution, see <a class=\"groops-program\" href=\"NormalsMultiplyAdd.html\">NormalsMultiplyAdd</a>, or as pseudo oberservations for regularization, see <a class=\"groops-class\" href=\"normalEquationType.html#regularization\">normalEquation:regularization</a>.</p><p>For back transformation use <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a> with <a class=\"groops-class\" href=\"gravityfieldType.html#fromParametrization\">gravityfield:fromParametrization</a>.'},\n'Gravityfield2TimeSplines': { 'name': 'Gravityfield2TimeSplines', 'key': 'Gravityfield2TimeSplines', 'description': 'This program estimates splines in time domain from a time variable gravity field and writes   This program estimates splines in time domain from a time variable gravity field and writes  . The   This program estimates splines in time domain from a time variable gravity field and writes   is sampled at   This program estimates splines in time domain from a time variable gravity field and writes  , converted to potential coefficients in the range between  minDegree  and  maxDegree  inclusively. The time series of spherical harmonics can be temporal filtered with   This program estimates splines in time domain from a time variable gravity field and writes  . In the next step temporal splines with  splineDegree  and nodal points given at   This program estimates splines in time domain from a time variable gravity field and writes   are adjusted to the time series in a least squares sense. This is very fast for block means (splineDegree = 0) but for other splines a large systems of equations must be solved. In the adjustment process the time series of gravity fields can be interpreted as samples at the given times or as continuous function with linear behaviour between sampled points ( linearInterpolation ). To combine a series of potential coefficients to a spline file with block means (splineDegree = 0) use the fast  PotentialCoefficients2BlockMeanTimeSplines  instead.', 'config_table': 'outputfileTimeSplines filename  gravityfield gravityfieldType  temporalFilter digitalFilterType filter sampled gravity field in time minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius sampling timeSeriesType gravity field is sampled at these times removeMean boolean remove the temporal mean of the series before estimating the splines linearInterpolation boolean assume linear behavior between sampled points splineDegree uint degree of splines splineTimeSeries timeSeriesType nodal points of splines in time domain', 'display_text': 'This program estimates splines in time domain from a time variable gravity field and writes <a class=\"groops-class\" href=\"fileFormat_timeSplinesGravityField.html\">outputfileTimeSplines</a>. The <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is sampled at <a class=\"groops-class\" href=\"timeSeriesType.html\">sampling</a>, converted to potential coefficients in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusively. The time series of spherical harmonics can be temporal filtered with <a class=\"groops-class\" href=\"digitalFilterType.html\">temporalFilter</a>.</p><p>In the next step temporal splines with <strong class=\"groops-config-element\">splineDegree</strong> and nodal points given at <a class=\"groops-class\" href=\"timeSeriesType.html\">splineTimeSeries</a> are adjusted to the time series in a least squares sense. This is very fast for block means (splineDegree = 0) but for other splines a large systems of equations must be solved. In the adjustment process the time series of gravity fields can be interpreted as samples at the given times or as continuous function with linear behaviour between sampled points (<strong class=\"groops-config-element\">linearInterpolation</strong>).</p><p>To combine a series of potential coefficients to a spline file with block means (splineDegree = 0) use the fast <a class=\"groops-program\" href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a> instead.'},\n'Gravityfield2TrendPotentialCoefficients': { 'name': 'Gravityfield2TrendPotentialCoefficients', 'key': 'Gravityfield2TrendPotentialCoefficients', 'description': 'This program estimates   This program estimates   (e.g. mean, trend, annual) from a time variable gravity field. In a first step a time variable   This program estimates   is sampled at   This program estimates   and converted to coefficients of a spherical harmonics expansion. The expansion is limited in the range between  minDegree  and  maxDegree  inclusively. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . These coefficients serves as observations of a  robust least squares adjustment  to estimate   This program estimates   parameters. For each temporal parameter an   This program estimates   is generated.', 'config_table': 'outputfilePotentialCoefficients filename for each temporal parameter gravityfield gravityfieldType  timeSeries timeSeriesType  parametrizationTemporal parametrizationTemporalType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius huber double for robust least squares huberPower double for robust least squares huberMaxIteration uint (maximum) number of iterations for robust estimation', 'display_text': 'This program estimates <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> (e.g. mean, trend, annual) from a time variable gravity field.</p><p>In a first step a time variable <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is sampled at <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> and converted to coefficients of a spherical harmonics expansion. The expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusively. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>These coefficients serves as observations of a <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a> to estimate <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> parameters. For each temporal parameter an <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> is generated.'},\n'GravityfieldCovariancesPropagation2GriddedData': { 'name': 'GravityfieldCovariancesPropagation2GriddedData', 'key': 'GravityfieldCovariancesPropagation2GriddedData', 'description': 'This program computes the covariance between a source point given by longitude/latitude ( L ,  B ) and the points of a   This program computes the covariance between a source point given by longitude/latitude (  in terms of the functional given by   This program computes the covariance between a source point given by longitude/latitude (  from the variance-covariance matrix of a   This program computes the covariance between a source point given by longitude/latitude (  evaluated at  time . If  computeCorrelation  is set, the program returns the correlation according to  in the range of [-1, 1] instead of the covariance. See also  Gravityfield2GridCovarianceMatrix ,  GravityfieldVariancesPropagation2GriddedData .', 'config_table': 'outputfileGriddedData filename gridded data file containing the covariance betwenn source point and grid points grid gridType  kernel kernelType functional gravityfield gravityfieldType  time time at this time the gravity field will be evaluated L angle longitude of variance point B angle latitude of variance point height double ellipsoidal height of source point computeCorrelation boolean compute correlations instead of covariances R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program computes the covariance between a source point given by longitude/latitude (<strong class=\"groops-config-element\">L</strong>, <strong class=\"groops-config-element\">B</strong>) and the points of a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in terms of the functional given by <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> from the variance-covariance matrix of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> evaluated at <strong class=\"groops-config-element\">time</strong>.</p><p>If <strong class=\"groops-config-element\">computeCorrelation</strong> is set, the program returns the correlation according to \\\\[ r_{ij} = \\\\frac{\\\\sigma_{ij}}{\\\\sigma_i \\\\sigma_j} \\\\]in the range of [-1, 1] instead of the covariance.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2GridCovarianceMatrix.html\">Gravityfield2GridCovarianceMatrix</a>, <a class=\"groops-program\" href=\"GravityfieldVariancesPropagation2GriddedData.html\">GravityfieldVariancesPropagation2GriddedData</a>.'},\n'GravityfieldReplacePotentialCoefficients': { 'name': 'GravityfieldReplacePotentialCoefficients', 'key': 'GravityfieldReplacePotentialCoefficients', 'description': 'Replaces single potential coefficients in a gravity field. Both   Replaces single potential coefficients in a gravity field. Both   and   Replaces single potential coefficients in a gravity field. Both   are evaluated at  time  and converted to spherical harmonic coefficients. Single  coefficients  are then replaced in   Replaces single potential coefficients in a gravity field. Both   by the values from   Replaces single potential coefficients in a gravity field. Both   and the result is written to   Replaces single potential coefficients in a gravity field. Both   from  minDegree  to  maxDegree ,', 'config_table': 'outputfilePotentialCoefficients filename  gravityfield gravityfieldType single coefficients are replaced by the other gravityfield gravityfieldReplacement gravityfieldType contains the coefficients for replacement coefficients choice  cnm sequence  degree uint  order uint  snm sequence  degree uint  order uint  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius time time at this time the gravity field will be evaluated', 'display_text': 'Replaces single potential coefficients in a gravity field. Both <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfieldReplacement</a> are evaluated at <strong class=\"groops-config-element\">time</strong> and converted to spherical harmonic coefficients. Single <strong class=\"groops-config-element\">coefficients</strong> are then replaced in <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> by the values from <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfieldReplacement</a> and the result is written to <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> from <strong class=\"groops-config-element\">minDegree</strong> to <strong class=\"groops-config-element\">maxDegree</strong>,'},\n'GravityfieldVariancesPropagation2GriddedData': { 'name': 'GravityfieldVariancesPropagation2GriddedData', 'key': 'GravityfieldVariancesPropagation2GriddedData', 'description': 'This program propagates variance-covariance matrix of a   This program propagates variance-covariance matrix of a   evaluated at  time  to the points of a   This program propagates variance-covariance matrix of a   in terms of the functional given by   This program propagates variance-covariance matrix of a  . The resulting  outputfileGriddedData  contains the standard deviations of the grid points. See also  Gravityfield2GridCovarianceMatrix ,  GravityfieldCovariancesPropagation2GriddedData .', 'config_table': 'outputfileGriddedData filename standard deviation at each grid point grid gridType  kernel kernelType functional gravityfield gravityfieldType  time time at this time the gravity field will be evaluated R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program propagates variance-covariance matrix of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> evaluated at <strong class=\"groops-config-element\">time</strong> to the points of a <a class=\"groops-class\" href=\"gridType.html\">grid</a> in terms of the functional given by <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. The resulting <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> contains the standard deviations of the grid points.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2GridCovarianceMatrix.html\">Gravityfield2GridCovarianceMatrix</a>, <a class=\"groops-program\" href=\"GravityfieldCovariancesPropagation2GriddedData.html\">GravityfieldCovariancesPropagation2GriddedData</a>.'},\n'GriddedData2AreaMeanTimeSeries': { 'name': 'GriddedData2AreaMeanTimeSeries', 'key': 'GriddedData2AreaMeanTimeSeries', 'description': 'This program computes a time series of area mean values in a basin represented by   This program computes a time series of area mean values in a basin represented by   from a sequence of grid files. If a file is not found, the epoch is skipped. Per default the weighted average of all points in the given border is computed where the points are weighted by their area element. If  computeMean  is set, the time average of each grid points is subtracted before the computation. If  multiplyWithArea  is set, the weighted average is multiplied with the total basin area. This is useful for computing the total mass in the basin. The   This program computes a time series of area mean values in a basin represented by   is an instrument file, where the first columns are the mean value each data column in the grid files, followed by the the weighted RMS for each data column in the grid files if  computeRms  is set. If the number of data columns differs between the grid files, the remaining columns are padded with zeros. See also  Gravityfield2AreaMeanTimeSeries .', 'config_table': 'outputfileTimeSeries filename  inputfileGriddedData filename  border borderType  timeSeries timeSeriesType  multiplyWithArea boolean multiply time series with total area (useful for mass estimates) removeMean boolean remove the temporal mean of the series computeRms boolean additional rms each time step', 'display_text': 'This program computes a time series of area mean values in a basin represented by <a class=\"groops-class\" href=\"borderType.html\">border</a> from a sequence of grid files. If a file is not found, the epoch is skipped. Per default the weighted average of all points in the given border is computed where the points are weighted by their area element.</p><p>If <strong class=\"groops-config-element\">computeMean</strong> is set, the time average of each grid points is subtracted before the computation. If <strong class=\"groops-config-element\">multiplyWithArea</strong> is set, the weighted average is multiplied with the total basin area. This is useful for computing the total mass in the basin.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> is an instrument file, where the first columns are the mean value each data column in the grid files, followed by the the weighted RMS for each data column in the grid files if <strong class=\"groops-config-element\">computeRms</strong> is set. If the number of data columns differs between the grid files, the remaining columns are padded with zeros.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2AreaMeanTimeSeries.html\">Gravityfield2AreaMeanTimeSeries</a>.'},\n'GriddedData2GriddedDataStatistics': { 'name': 'GriddedData2GriddedDataStatistics', 'key': 'GriddedData2GriddedDataStatistics', 'description': 'This program assigns values   This program assigns values   to the nearest points of a new   This program assigns values  . If some of the new points are not filled in with data  emptyValue  is used instead. If multiple points of the input fall on the same node the result can be selected with  statistics  (e.g. mean, root mean square, min, max,  ). It also is possible to simply count the number of data points that were assigned to each point. Be aware in case borders are given within   This program assigns values  , the   This program assigns values   will have points excluded before the assignement of old points to the new points. The data from   This program assigns values   will not be limited by the given borders! See  GriddedDataConcatenate  to limit the   This program assigns values   to given borders.', 'config_table': 'outputfileGriddedData filename  inputfileGriddedData filename  grid gridType  statistic choice statistic used if multiple values fall on the same cell mean  mean wmean  area weighted mean rms  root mean square wrms  area weighted root mean square std  standard deviation wstd  area weighted standard deviation sum  sum min  minimum value max  maximum value count  number of values first  first value last  last value emptyValue double value for nodes without data R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'This program assigns values <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to the nearest points of a new <a class=\"groops-class\" href=\"gridType.html\">grid</a>. If some of the new points are not filled in with data <strong class=\"groops-config-element\">emptyValue</strong> is used instead. If multiple points of the input fall on the same node the result can be selected with <strong class=\"groops-config-element\">statistics</strong> (e.g. mean, root mean square, min, max, ). It also is possible to simply count the number of data points that were assigned to each point.</p><p>Be aware in case borders are given within <a class=\"groops-class\" href=\"gridType.html\">grid</a>, the <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> will have points excluded before the assignement of old points to the new points. The data from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> will not be limited by the given borders! See <a class=\"groops-ref\" href=\"GriddedDataConcatenate.html\">GriddedDataConcatenate</a> to limit the <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to given borders.</p><p>'},\n'GriddedData2GriddedDataTimeSeries': { 'name': 'GriddedData2GriddedDataTimeSeries', 'key': 'GriddedData2GriddedDataTimeSeries', 'description': 'Write a series of   Write a series of   with the corresponding   Write a series of   as a single  gridded data time series file . The  splineDegree  defines the possible temporal interpolation of data in the output file. For a file with spline degree 0 (temporal block means) the time intervals in which the grids are valid are defined between adjacent points in time. Therefore one more point in time is needed than the number of input grid files for degree 0. See also  GriddedDataTimeSeries2GriddedData .', 'config_table': 'outputfileGriddedDataTimeSeries filename  inputfileGriddedData filename file count must agree with number of times+splineDegre-1 timeSeries timeSeriesType  splineDegree uint degree of splines', 'display_text': 'Write a series of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> with the corresponding <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> as a single <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">gridded data time series file</a>. The <strong class=\"groops-config-element\">splineDegree</strong> defines the possible temporal interpolation of data in the output file. For a file with spline degree 0 (temporal block means) the time intervals in which the grids are valid are defined between adjacent points in time. Therefore one more point in time is needed than the number of input grid files for degree 0.</p><p>See also <a class=\"groops-program\" href=\"GriddedDataTimeSeries2GriddedData.html\">GriddedDataTimeSeries2GriddedData</a>.'},\n'GriddedData2Matrix': { 'name': 'GriddedData2Matrix', 'key': 'GriddedData2Matrix', 'description': 'This program converts   This program converts   to   This program converts   with data columns. The grid is expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening . The content of the output matrix can be controlled by  outColumn  expressions applied to every grid point. The common data variables for grids are available, see  dataVariables .', 'config_table': 'outputfileMatrix filename point list as matrix with longitude and latitude values in columns and possible additional columns inputfileGriddedData filename  R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates outColumn expression expression (variables: longitude, latitude, height, area, data0, data1, ...)', 'display_text': 'This program converts <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> with data columns. The grid is expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>. The content of the output matrix can be controlled by <strong class=\"groops-config-element\">outColumn</strong> expressions applied to every grid point. The common data variables for grids are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.'},\n'GriddedData2PotentialCoefficients': { 'name': 'GriddedData2PotentialCoefficients', 'key': 'GriddedData2PotentialCoefficients', 'description': 'This program estimate potential coefficients from   This program estimate potential coefficients from   gravity field functionals. It used a simple quadrature formular  or a  leastSquares  adjustment with block diagonal normal matrix (order by order). For the latter one the data must be regular distributed. The  value s   and the  weight s   are expressions using the common data variables for grids, see  dataVariables . Multiple   This program estimate potential coefficients from   can be estimated in one step. For each an indivdual  value  must be specified. The type of the gridded data (e.g gravity anomalies or geoid heights) must be set with   This program estimate potential coefficients from    . The expansion is limited in the range between  minDegree  and  maxDegree  inclusively. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . For irregular distributed data and using the full variance covariance matrix use  NormalsSolverVCE  together with   This program estimate potential coefficients from   and   This program estimate potential coefficients from  . See also  GriddedDataTimeSeries2PotentialCoefficients .', 'config_table': 'outputfilePotentialCoefficients filename one file for each value expression inputfileGriddedData filename  value expression expression to compute values (input columns are named data0, data1, ...) weight expression expression to compute values (input columns are named data0, data1, ...) kernel kernelType data type of input values minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius leastSquares boolean false: quadrature formular, true: least squares adjustment order by order', 'display_text': 'This program estimate potential coefficients from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> gravity field functionals. It used a simple quadrature formular \\\\[   c_{nm} = \\\\frac{1}{4\\\\pi}\\\\frac{R}{GM} \\\\sum_i f_i \\\\left(\\\\frac{r_i}{R}\\\\right)^{n+1} k_n C_{nm}(\\\\lambda_i,\\\\vartheta_i)\\\\,\\\\Delta\\\\Phi_i \\\\]or a <strong class=\"groops-config-element\">leastSquares</strong> adjustment with block diagonal normal matrix (order by order). For the latter one the data must be regular distributed.</p><p>The <strong class=\"groops-config-element\">value</strong>s $f_i$ and the <strong class=\"groops-config-element\">weight</strong>s $\\\\Delta\\\\Phi_i$ are expressions using the common data variables for grids, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>. Multiple <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> can be estimated in one step. For each an indivdual <strong class=\"groops-config-element\">value</strong> must be specified. The type of the gridded data (e.g gravity anomalies or geoid heights) must be set with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> $k_n$.</p><p>The expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusively. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>For irregular distributed data and using the full variance covariance matrix use <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a> together with <a class=\"groops-class\" href=\"observationType.html#terrestrial\">oberservation:terrestrial</a> and <a class=\"groops-class\" href=\"parametrizationGravityType.html#sphericalHarmonics\">parametrizationGravity:sphericalHarmonics</a>.</p><p>See also <a class=\"groops-program\" href=\"GriddedDataTimeSeries2PotentialCoefficients.html\">GriddedDataTimeSeries2PotentialCoefficients</a>.'},\n'GriddedData2SphericalDistance': { 'name': 'GriddedData2SphericalDistance', 'key': 'GriddedData2SphericalDistance', 'description': 'Compute the spherical distance on the unit sphere in radians between all point pairs of two grids. The spherical distance is computed by  where   is the (normalized) position. This implies that all points are projected onto the unit sphere.', 'config_table': 'outputfileMatrix filename matrix containing the spherical distance between all point pairs [rad] grid1 gridType  grid2 gridType', 'display_text': 'Compute the spherical distance on the unit sphere in radians between all point pairs of two grids. The spherical distance is computed by \\\\[   \\\\psi_{12} = \\\\arccos(\\\\M n_1 \\\\cdot \\\\M n_2), \\\\]where $\\\\M n_i$ is the (normalized) position. This implies that all points are projected onto the unit sphere.'},\n'GriddedData2TimeSeries': { 'name': 'GriddedData2TimeSeries', 'key': 'GriddedData2TimeSeries', 'description': 'Write a series of   Write a series of   with the corresponding   Write a series of   as a single time series file ( instrument , MISCVALUES). If  groupDataByPoints  is true the  outputfileTimeSeries  starts for each epoch with all data ( data0 ,  data1 ) for the first point, followed by all data of the second point and so on. If  groupDataByPoints  is false, the file starts with  data0  for all points, followed by all  data1  and so on. This enables the use of all instrument programs like  InstrumentFilter  or  InstrumentDetrend  to analyze and manipulate time series of gridded data. See also  TimeSeries2GriddedData .', 'config_table': 'outputfileTimeSeries filename each epoch: multiple data for points (MISCVALUES) inputfileGriddedData filename file count must agree with number of times timeSeries timeSeriesType  groupDataByPoints boolean multiple data are given point by point, otherwise: data0 for all points, followed by all data1', 'display_text': 'Write a series of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> with the corresponding <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> as a single time series file (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument</a>, MISCVALUES).</p><p>If <strong class=\"groops-config-element\">groupDataByPoints</strong> is true the <strong class=\"groops-config-element\">outputfileTimeSeries</strong> starts for each epoch with all data (<code>data0</code>, <code>data1</code>) for the first point, followed by all data of the second point and so on. If <strong class=\"groops-config-element\">groupDataByPoints</strong> is false, the file starts with <code>data0</code> for all points, followed by all <code>data1</code> and so on.</p><p>This enables the use of all instrument programs like <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a> or <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> to analyze and manipulate time series of gridded data.</p><p>See also <a class=\"groops-program\" href=\"TimeSeries2GriddedData.html\">TimeSeries2GriddedData</a>.'},\n'GriddedDataCalculate': { 'name': 'GriddedDataCalculate', 'key': 'GriddedDataCalculate', 'description': 'This program manipulates  grid files  with data in columns similar to  FunctionsCalculate , see there for more details. If several  inputfile s are given the data columns are copied side by side. All  inputfile s must contain the same grid points. The columns are enumerated by  data0 ,  data1 ,  . The content of   This program manipulates   is controlled by  outColumn . The algorithm to compute the output is as follows: The expressions in  outColumn  are evaluated once for each grid point of the input. The variables  data0 ,  data1 ,  are replaced by the according values from the input columns before. Additional variables are available, e.g.  index ,  data0rms , see  dataVariables . For a simplified handling  constant s can be defined by  name=value . It is also possible to estimate  parameter s in a least squares adjustment. The  leastSquares  serves as template for observation equations for every point. The expression  leastSquares  is evaluated for each grid point. The variables  data0 ,  data1 ,  are replaced by the according values from the input columns before. In the next step the parameters are estimated in order to minimize the expressions in  leastSquares  in the sense of least squares. Afterwards grid points are removed if one of the  removalCriteria  expressions for this grid point evaluates true (not zero). An extra   This program manipulates   can be generated with one row of data. For the computation of the  outColumn  values all  dataVariables  are available (e.g.  data3mean ,  data4std ) inclusively the  constant s and estimated  parameter s but without the  data0 ,  data1 ,  itself. The variables and the numbering of the columns refers to the   This program manipulates  . See also  FunctionsCalculate ,  InstrumentArcCalculate ,  MatrixCalculate .', 'config_table': 'outputfileGriddedData filename  inputfileGriddedData filename  constant expression define a constant by name=value parameter expression define a parameter by name[=value] leastSquares expression try to minimize the expression by adjustment of the parameters removalCriteria expression points are removed if one criterion evaluates true. data0 is the first data field. longitude expression expression latitude expression expression height expression expression area expression expression: e.g. deltaL * 2.0 * sin(deltaB/2.0) * cos(latitude/rho) value expression expression to compute values (input columns are named data0, data1, ...) computeArea boolean automatically area computation of rectangular grids (overwrite area) R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates statistics sequence  outputfile filename matrix with one row, columns are user defined outColumn expression expression to compute statistics columns, data* are the outputColumns', 'display_text': 'This program manipulates <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">grid files</a> with data in columns similar to <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, see there for more details. If several <strong class=\"groops-config-element\">inputfile</strong>s are given the data columns are copied side by side. All <strong class=\"groops-config-element\">inputfile</strong>s must contain the same grid points. The columns are enumerated by <code>data0</code>, <code>data1</code>, .</p><p>The content of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a> is controlled by <strong class=\"groops-config-element\">outColumn</strong>. The algorithm to compute the output is as follows: The expressions in <strong class=\"groops-config-element\">outColumn</strong> are evaluated once for each grid point of the input. The variables <code>data0</code>, <code>data1</code>, are replaced by the according values from the input columns before. Additional variables are available, e.g. <code>index</code>, <code>data0rms</code>, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>For a simplified handling <strong class=\"groops-config-element\">constant</strong>s can be defined by <code>name=value</code>. It is also possible to estimate <strong class=\"groops-config-element\">parameter</strong>s in a least squares adjustment. The <strong class=\"groops-config-element\">leastSquares</strong> serves as template for observation equations for every point. The expression <strong class=\"groops-config-element\">leastSquares</strong> is evaluated for each grid point. The variables <code>data0</code>, <code>data1</code>, are replaced by the according values from the input columns before. In the next step the parameters are estimated in order to minimize the expressions in <strong class=\"groops-config-element\">leastSquares</strong> in the sense of least squares.</p><p>Afterwards grid points are removed if one of the <strong class=\"groops-config-element\">removalCriteria</strong> expressions for this grid point evaluates true (not zero).</p><p>An extra <a class=\"groops-class\" href=\"fileFormat_matrix.html\">statistics:outputfile</a> can be generated with one row of data. For the computation of the <strong class=\"groops-config-element\">outColumn</strong> values all <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available (e.g. <code>data3mean</code>, <code>data4std</code>) inclusively the <strong class=\"groops-config-element\">constant</strong>s and estimated <strong class=\"groops-config-element\">parameter</strong>s but without the <code>data0</code>, <code>data1</code>, itself. The variables and the numbering of the columns refers to the <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>.</p><p>See also <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>, <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.'},\n'GriddedDataConcatenate': { 'name': 'GriddedDataConcatenate', 'key': 'GriddedDataConcatenate', 'description': 'This program concatenate grid from several   This program concatenate grid from several   and write it to a new   This program concatenate grid from several  . Input files must have the same number of data columns. If  sort  is enabled, the points are sorted by latitudes starting from north/west to south east. Identical points (within a  margin ) can be removed with  removeDuplicates .', 'config_table': 'outputfileGriddedData filename  inputfileGriddedData filename  border borderType  sortPoints boolean sort from north/west to south east removeDuplicates choice remove duplicate points keepFirst sequence keep first point, remove all other identicals margin double margin distance for identical points [m] keepLast sequence keep last point, remove all other identicals margin double margin distance for identical points [m] R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'This program concatenate grid from several <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> and write it to a new <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>. Input files must have the same number of data columns. If <strong class=\"groops-config-element\">sort</strong> is enabled, the points are sorted by latitudes starting from north/west to south east. Identical points (within a <strong class=\"groops-config-element\">margin</strong>) can be removed with <strong class=\"groops-config-element\">removeDuplicates</strong>.'},\n'GriddedDataCreate': { 'name': 'GriddedDataCreate', 'key': 'GriddedDataCreate', 'description': 'This program creates a   This program creates a   and writes it to   This program creates a  . The grid is expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening . Extra  value  columns can be appended using expressions with the common  data variables  for gridded data.', 'config_table': 'outputfileGrid filename  grid gridType  R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates value expression expression (variables as \\'longitude\\', \\'height\\', \\'area\\' are taken from the gridded data)', 'display_text': 'This program creates a <a class=\"groops-class\" href=\"gridType.html\">grid</a> and writes it to <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGrid</a>. The grid is expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>. Extra <strong class=\"groops-config-element\">value</strong> columns can be appended using expressions with the common <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">data variables</a> for gridded data.'},\n'GriddedDataInterpolate': { 'name': 'GriddedDataInterpolate', 'key': 'GriddedDataInterpolate', 'description': 'Interpolate values of a regular rectangular   Interpolate values of a regular rectangular   to new points given by   Interpolate values of a regular rectangular   and write as   Interpolate values of a regular rectangular  . Only longitude and latitude of points are considered; the height is ignored for interpolation. (Only nearest neighbor method is implemented at the moment.)', 'config_table': 'outputfileGriddedData filename  inputfileGriddedData filename must be rectangular grid gridType  method choice  nearestNeighbor', 'display_text': 'Interpolate values of a regular rectangular <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to new points given by <a class=\"groops-class\" href=\"gridType.html\">grid</a> and write as <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>. Only longitude and latitude of points are considered; the height is ignored for interpolation.</p><p>(Only nearest neighbor method is implemented at the moment.)</p><p>'},\n'GriddedDataReduceSampling': { 'name': 'GriddedDataReduceSampling', 'key': 'GriddedDataReduceSampling', 'description': 'Generate coarse grid by computing area weighted mean values. The number of points is decimated by averaging integer multiplies of grid points ( multiplierLongitude ,  multiplierLatitude ). if  volumeConserving  is set, data are interpreted as heights above ellipsoid and the tesseroid volume  is conserved, where   is the radius of the ellipsoid at grid center and   are the grid cell boundaries. This is meaninful for Digital Elevation Models (DEM). The fine grid can be written, where the first coarse grid values (data0) are additionally appended.', 'config_table': 'outputfileCoarseGridRectangular filename coarse grid outputfileFineGridRectangular filename fine grid with additional coarse grid values inputfileFineGridRectangular filename Digital Terrain Model multiplierLongitude uint Generalizing factor multiplierLatitude uint Generalizing factor volumeConserving boolean data are interpreted as heights above ellipsoid', 'display_text': 'Generate coarse grid by computing area weighted mean values. The number of points is decimated by averaging integer multiplies of grid points (<strong class=\"groops-config-element\">multiplierLongitude</strong>, <strong class=\"groops-config-element\">multiplierLatitude</strong>).</p><p>if <strong class=\"groops-config-element\">volumeConserving</strong> is set, data are interpreted as heights above ellipsoid and the tesseroid volume \\\\[   V=\\\\int_r^{r+H}\\\\int_{\\\\varphi_1}^{\\\\varphi_2}\\\\int_{\\\\lambda_1}^{\\\\lambda_2} r^2\\\\cos\\\\varphi\\\\,d\\\\varphi\\\\,d\\\\lambda\\\\,dr \\\\]is conserved, where $r$ is the radius of the ellipsoid at grid center and $(\\\\varphi_1-\\\\varphi_2)\\\\times(\\\\lambda_1-\\\\lambda_2)$ are the grid cell boundaries. This is meaninful for Digital Elevation Models (DEM).</p><p>The fine grid can be written, where the first coarse grid values (data0) are additionally appended.'},\n'GriddedDataTimeSeries2GriddedData': { 'name': 'GriddedDataTimeSeries2GriddedData', 'key': 'GriddedDataTimeSeries2GriddedData', 'description': 'Read a   Read a   and write for each epoch a  gridded data file  where the  variableLoopTime  and  variableLoopIndex  are expanded for each point of the given   Read a   to create the file name for this epoch (see  text parser ). If   Read a   is not set the temporal nodal points from the inputfile are used. See also  GriddedData2GriddedDataTimeSeries .', 'config_table': 'outputfilesGriddedData filename for each epoch variableLoopTime string variable with time of each epoch variableLoopIndex string variable with index of current epoch (starts with zero) variableLoopCount string variable with total number of epochs inputfileGriddedDataTimeSeries filename  timeSeries timeSeriesType otherwise times from inputfile are used', 'display_text': 'Read a <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a> and write for each epoch a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data file</a> where the <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> are expanded for each point of the given <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> to create the file name for this epoch (see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>).</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is not set the temporal nodal points from the inputfile are used.</p><p>See also <a class=\"groops-program\" href=\"GriddedData2GriddedDataTimeSeries.html\">GriddedData2GriddedDataTimeSeries</a>.'},\n'GriddedDataTimeSeries2PotentialCoefficients': { 'name': 'GriddedDataTimeSeries2PotentialCoefficients', 'key': 'GriddedDataTimeSeries2PotentialCoefficients', 'description': 'This program estimate potential coefficients from   This program estimate potential coefficients from   in the same way as  GriddedData2PotentialCoefficients  but not only for one grid but for each epoch of   This program estimate potential coefficients from   of if not set for the temporal nodal points from the inputfile. The   This program estimate potential coefficients from   (one for each  value ) are written for each epoch with the expansion of  variableLoopTime  and  variableLoopIndex  (see  text parser ). See also  GriddedData2PotentialCoefficients .', 'config_table': 'outputfilesPotentialCoefficients filename for each epoch variableLoopTime string variable with time of each epoch variableLoopIndex string variable with index of current epoch (starts with zero) variableLoopCount string variable with total number of epochs inputfileGriddedDataTimeSeries filename  timeSeries timeSeriesType otherwise times from inputfile are used value expression expression (variables: longitude, latitude, height, area, data0, data1, ...) weight expression expression to compute values (input columns are named data0, data1, ...) kernel kernelType kernel in which the grid values are given minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius for potential coefficients leastSquares boolean false: quadrature formular, true: least squares adjustment order by order', 'display_text': 'This program estimate potential coefficients from <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a> in the same way as <a class=\"groops-program\" href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a> but not only for one grid but for each epoch of <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> of if not set for the temporal nodal points from the inputfile. The <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> (one for each <strong class=\"groops-config-element\">value</strong>) are written for each epoch with the expansion of <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> (see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>).</p><p>See also <a class=\"groops-program\" href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a>.'},\n'GriddedTopography2AtmospherePotentialCoefficients': { 'name': 'GriddedTopography2AtmospherePotentialCoefficients', 'key': 'GriddedTopography2AtmospherePotentialCoefficients', 'description': 'Estimate interior and exterior potential coefficients for atmosphere above digital terrain models. Coefficients for interior   and exterior ( ) are computed. The density of the atmosphere is assumed to be (Sjöberg, 1998)  where   is the radial distance of the ellipsoid at each point,   the radial height above the ellipsoid,   is  densitySeaLevel  and  nu    is a constant factor. The density is integrated from  radialLowerBound  and  upperAtmosphericBoundary  above the ellipsoid. The  radialLowerBound  is typically the topography and can be computed as expression at every point from   Estimate interior and exterior potential coefficients for atmosphere above digital terrain models. Coefficients for interior  .', 'config_table': 'outputfilePotentialCoefficientsExterior filename  outputfilePotentialCoefficientsInterior filename  inputfileGriddedData filename Digital Terrain Model densitySeaLevel double [kg/m**3] ny double Constant for Atmosphere radialLowerBound expression expression (variables \\'L\\', \\'B\\', \\'height\\', \\'data\\', and \\'area\\' are taken from the gridded data upperAtmosphericBoundary double constant upper bound [m] factor double the result is multiplied by this factor, set -1 to subtract the field minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'Estimate interior and exterior potential coefficients for atmosphere above digital terrain models. Coefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed. The density of the atmosphere is assumed to be (Sjöberg, 1998) \\\\[ \\\\rho_0\\\\left(\\\\frac{R}{R+h}\\\\right)^\\\\nu, \\\\]where $R$ is the radial distance of the ellipsoid at each point, $h$ the radial height above the ellipsoid, $\\\\rho_0$ is <strong class=\"groops-config-element\">densitySeaLevel</strong> and <strong class=\"groops-config-element\">nu</strong> $\\\\nu$ is a constant factor. The density is integrated from <strong class=\"groops-config-element\">radialLowerBound</strong> and <strong class=\"groops-config-element\">upperAtmosphericBoundary</strong> above the ellipsoid. The <strong class=\"groops-config-element\">radialLowerBound</strong> is typically the topography and can be computed as expression at every point from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.'},\n'GriddedTopography2PotentialCoefficients': { 'name': 'GriddedTopography2PotentialCoefficients', 'key': 'GriddedTopography2PotentialCoefficients', 'description': 'Estimate potential coefficients from digital terrain models. Coefficients for interior   and exterior ( ) are computed.', 'config_table': 'outputfilePotentialCoefficients filename  outputfilePotentialCoefficientsInterior filename  inputfileGriddedData filename Digital Terrain Model density expression expression [kg/m^3] radialUpperBound expression expression (variables \\'L\\', \\'B\\', \\'height\\', \\'data\\', and \\'area\\' are taken from the gridded data radialLowerBound expression expression (variables \\'L\\', \\'B\\', \\'height\\', \\'data\\', and \\'area\\' are taken from the gridded data factor double the result is multiplied by this factor minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'Estimate potential coefficients from digital terrain models. Coefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.'},\n'GriddedTopographyEllipsoidal2Radial': { 'name': 'GriddedTopographyEllipsoidal2Radial', 'key': 'GriddedTopographyEllipsoidal2Radial', 'description': 'Interpolate digital terrain models from ellipoidal heights to radial heights.', 'config_table': 'outputfileGriddedData filename  inputfileGriddedData filename Digital Terrain Model', 'display_text': 'Interpolate digital terrain models from ellipoidal heights to radial heights.'},\n'Matrix2GriddedData': { 'name': 'Matrix2GriddedData', 'key': 'Matrix2GriddedData', 'description': 'This program reads a  matrix file  with data in columns and convert into  gridded data . The input columns are enumerated by  data0 ,  data1 ,  , see  dataVariables .', 'config_table': 'outputfileGriddedData filename  inputfileMatrix filename  points choice  ellipsoidal sequence  longitude expression expression latitude expression expression height expression expression cartesian sequence  x expression expression y expression expression z expression expression area expression expression (e.g. deltaL*2*sin(deltaB/2)*cos(data1/RHO)) value expression expression sortPoints boolean sort from north/west to south east computeArea boolean the area can be computed automatically for rectangular grids R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'This program reads a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix file</a> with data in columns and convert into <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a>. The input columns are enumerated by <code>data0</code>, <code>data1</code>, , see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.'},\n'MatrixRectangular2GriddedData': { 'name': 'MatrixRectangular2GriddedData', 'key': 'MatrixRectangular2GriddedData', 'description': 'Read gridded data (matrix).', 'config_table': 'outputfileGriddedData filename  inputfileMatrix filename  rowMajor boolean true: data is ordered row by row, false: columnwise startLongitude angle longitude of upper left corner of the grid startLatitude angle latitude of upper left corner of the grid deltaLongitude angle sampling, negative for east to west data deltaLatitude angle sampling, negative for south to north data R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'Read gridded data (matrix).'},\n'TimeSeries2GriddedData': { 'name': 'TimeSeries2GriddedData', 'key': 'TimeSeries2GriddedData', 'description': 'Interpret the data columns of   Interpret the data columns of   as data points of a corresponding   Interpret the data columns of  . For each epoch a  gridded data file  is written where the  variableLoopTime  and  variableLoopIndex  are expanded for each point of the given time series to create the file name for this epoch (see  text parser ). The number of input data columns must be a multiple of the number   of grid points. If  isGroupedDataByPoint  is true the   Interpret the data columns of   starts with all data ( data0 ,  data1 ) for the first point, followed by all data of the second point and so on. If  isGroupedDataByPoint  is false, the file starts with  data0  for all points, followed by all  data1  and so on. See also  GriddedData2TimeSeries .', 'config_table': 'outputfilesGriddedData filename for each epoch variableLoopTime string variable with time of each epoch variableLoopIndex string variable with index of current epoch (starts with zero) variableLoopCount string variable with total number of epochs inputfileTimeSeries filename each epoch: multiple data for points (MISCVALUES) grid gridType corresponding grid points isDataGroupedByPoint boolean multiple data are given point by point, otherwise: first data0 for all points, followed by all data1 R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'Interpret the data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeSeries</a> as data points of a corresponding <a class=\"groops-class\" href=\"gridType.html\">grid</a>.</p><p>For each epoch a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data file</a> is written where the <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> are expanded for each point of the given time series to create the file name for this epoch (see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>).</p><p>The number of input data columns must be a multiple of the number $n$ of grid points. If <strong class=\"groops-config-element\">isGroupedDataByPoint</strong> is true the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeSeries</a> starts with all data (<code>data0</code>, <code>data1</code>) for the first point, followed by all data of the second point and so on. If <strong class=\"groops-config-element\">isGroupedDataByPoint</strong> is false, the file starts with <code>data0</code> for all points, followed by all <code>data1</code> and so on.</p><p>See also <a class=\"groops-program\" href=\"GriddedData2TimeSeries.html\">GriddedData2TimeSeries</a>.'},\n'Instrument2AllanVariance': { 'name': 'Instrument2AllanVariance', 'key': 'Instrument2AllanVariance', 'description': 'This program computes the overlapping Allan variance from an   This program computes the overlapping Allan variance from an  . The estimate is averaged over all arcs (arcs are assumed to contain no data gaps). The overlapping Allan variance is defined as  where   is the averaging interval defined by the median sampling  .', 'config_table': 'outputfileAllanVariance filename column 0: averaging interval [seconds], column 1-(n-1): Allan variance for each data column inputfileInstrument filename', 'display_text': 'This program computes the overlapping Allan variance from an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>. The estimate is averaged over all arcs (arcs are assumed to contain no data gaps).</p><p>The overlapping Allan variance is defined as \\\\[   \\\\sigma^2(m\\\\tau_0) = \\\\frac{1}{2(m\\\\tau_0)^2(N-2m)} \\\\sum_{n=1}^{N-2m}(x_{n+2m}-2x_{n+m}+x_n)^2, \\\\]where $m\\\\tau_0$ is the averaging interval defined by the median sampling $\\\\tau_0$.'},\n'Instrument2CovarianceFunctionVCE': { 'name': 'Instrument2CovarianceFunctionVCE', 'key': 'Instrument2CovarianceFunctionVCE', 'description': 'This estimates a covariance function of   This estimates a covariance function of   for all selected columns with  startDataFields  and  countDataFields . The estimation is performed robustly via variance component estimation. Bad arcs are downweigthed and the accuracies can be written with   This estimates a covariance function of  . The length of the covariance functions are determined by the longest arc. Additionaly the data can be detrended with   This estimates a covariance function of   and   This estimates a covariance function of  .', 'config_table': 'outputfileCovarianceFunction filename covariance functions outputfileSigmasPerArc filename accuracies of each arc outputfileResiduals filename  outputfileSolution filename estimated parameter vector (global part only) inputfileInstrument filename  startDataFields uint start countDataFields uint number of data fields (default: all after start) parameter parametrizationTemporalType data is reduced by temporal representation parameterPerArc parametrizationTemporalType data is reduced by temporal representation iterationCount uint number of iterations for the estimation', 'display_text': 'This estimates a covariance function of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> for all selected columns with <strong class=\"groops-config-element\">startDataFields</strong> and <strong class=\"groops-config-element\">countDataFields</strong>. The estimation is performed robustly via variance component estimation. Bad arcs are downweigthed and the accuracies can be written with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmasPerArc</a>. The length of the covariance functions are determined by the longest arc. Additionaly the data can be detrended with <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parameter</a> and <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parameterPerArc</a>.'},\n'Instrument2CrossCorrelationFunction': { 'name': 'Instrument2CrossCorrelationFunction', 'key': 'Instrument2CrossCorrelationFunction', 'description': 'This program computes the cross correlation between all corresponding data columns in two  instrument files . The instrument files must be synchronized ( InstrumentSynchronize ). The   This program computes the cross correlation between all corresponding data columns in two   is a matrix with the first column containing the time lag followed by cross-correlation function for each data column. The maximum lag is defined by the maximum arc length. The correlation is based on the unbiased estimate of the cross-covariance between data columns   and  ,  which is averaged over all arcs. From this estimate, the correlation for each lag is then computed via  which is the ratio between the biased estimates of the cross-covariance at lag   and the auto-covariance of the individual data columns. For instrument with data gaps, lag bins without any data are set to NAN.', 'config_table': 'outputfileCorrelation filename column 1: time lag, column 2..n cross-correlation inputfileInstrument filename  inputfileInstrumentReference filename', 'display_text': 'This program computes the cross correlation between all corresponding data columns in two <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a>. The instrument files must be synchronized (<a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>). The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCorrelation</a> is a matrix with the first column containing the time lag followed by cross-correlation function for each data column. The maximum lag is defined by the maximum arc length.</p><p>The correlation is based on the unbiased estimate of the cross-covariance between data columns $x$ and $y$, \\\\[   \\\\sigma_{xy}(h) = \\\\frac{1}{N}\\\\sum_{k=1} x_{k+h} y_k, \\\\]which is averaged over all arcs. From this estimate, the correlation for each lag is then computed via \\\\[   r_{xy}(h) = \\\\frac{\\\\sigma_{xy}(h)}{\\\\sigma_x(0)\\\\sigma_y(0)}, \\\\]which is the ratio between the biased estimates of the cross-covariance at lag $h$ and the auto-covariance of the individual data columns.</p><p>For instrument with data gaps, lag bins without any data are set to NAN.'},\n'Instrument2Histogram': { 'name': 'Instrument2Histogram', 'key': 'Instrument2Histogram', 'description': 'This program computes the arc-wise histogram from an  instrument file . The output is a  matrix  with the first column containing the lower bound of each bin. The other columns contain the histograms for each arc.', 'config_table': 'outputfileMatrix filename column 1: lower bin bound; columns 2 to N: histogram of each arc inputfileInstrument filename  selectDataField uint select channel for histogram computation binCount uint (default: Freedman-Diaconis\\' choice, maximum of all channels) lowerBound expression lower bound for bins (default: global minimum, data values outside are ignored) upperBound expression upper bound for bins (default: global maximum, data values outside are ignored) relative boolean output relative frequencies cumulative boolean accumulate frequencies', 'display_text': 'This program computes the arc-wise histogram from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The output is a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> with the first column containing the lower bound of each bin. The other columns contain the histograms for each arc.</p><p>'},\n'Instrument2PowerSpectralDensity': { 'name': 'Instrument2PowerSpectralDensity', 'key': 'Instrument2PowerSpectralDensity', 'description': 'This program computes the power spectral density (PSD) for all data fields in an  instrument file . The PSD is computed using Lomb\\'s method. For each arc and each frequency  , a sinusoid is fit to the data   The PSD for this frequency is then computed by forming the square sum of adjusted observations:   The resulting PSD is the average over all arcs. For regularly sampled time series, this method yields the same results as FFT based PSD estimates. A regular frequency grid based on the longest arc and the median sampling is computed. The maximum number of epochs per arc is determined by  the Nyquist frequency is given by   If it is suspected that   This program computes the power spectral density (PSD) for all data fields in an   contains secular variations, the input should be detrended using  InstrumentDetrend . See also  Instrument2CovarianceFunctionVCE ,  CovarianceFunction2PowerSpectralDensity ,  PowerSpectralDensity2CovarianceFunction .', 'config_table': 'outputfilePSD filename estimated PSD: column 0: frequency vector, column 1-(n-1): PSD estimate for each channel inputfileInstrument filename', 'display_text': 'This program computes the power spectral density (PSD) for all data fields in an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The PSD is computed using Lomb\\'s method. For each arc and each frequency $f$, a sinusoid is fit to the data \\\\[   l_i = a \\\\cos(2\\\\pi f t_i) + b \\\\sin(2\\\\pi f t_i) + e_i \\\\] The PSD for this frequency is then computed by forming the square sum of adjusted observations: \\\\[   P(f) = \\\\sum_i \\\\hat{l}^2_i. \\\\] The resulting PSD is the average over all arcs. For regularly sampled time series, this method yields the same results as FFT based PSD estimates.</p><p>A regular frequency grid based on the longest arc and the median sampling is computed. The maximum number of epochs per arc is determined by \\\\[   N = \\\\frac{t_{\\\\text{end}} - t_{\\\\text{start}}}{\\\\Delta t_{\\\\text{median}} } + 1, \\\\]the Nyquist frequency is given by \\\\[   f_{\\\\text{nyq}} = \\\\frac{1}{2\\\\Delta t_{\\\\text{median}}}. \\\\] If it is suspected that <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> contains secular variations, the input should be detrended using <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a>.</p><p>See also <a class=\"groops-program\" href=\"Instrument2CovarianceFunctionVCE.html\">Instrument2CovarianceFunctionVCE</a>, <a class=\"groops-program\" href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a>, <a class=\"groops-program\" href=\"PowerSpectralDensity2CovarianceFunction.html\">PowerSpectralDensity2CovarianceFunction</a>.'},\n'Instrument2RmsPlotGrid': { 'name': 'Instrument2RmsPlotGrid', 'key': 'Instrument2RmsPlotGrid', 'description': 'This program computes an RMS plot grid from one or more   This program computes an RMS plot grid from one or more   containing 3D data (e.g. orbits or station positions), which can then be plotted as gridded data in  PlotGraph . The RMS is computed from the difference between   This program computes an RMS plot grid from one or more   and   This program computes an RMS plot grid from one or more  . All instrument files must be synchronized (see  InstrumentSynchronize ). Each separate   This program computes an RMS plot grid from one or more   represents an entry (e.g. a satellite or station) in the resulting grid. Therefore, providing, for example, 32 orbit files of GPS satellites results in a grid with columns: mjd, id (0-31), rms. The first three data columns of the instrument data are considered for computation of the RMS values. The  factor  can be set to, for example, sqrt(3) to get 3D instead of 1D RMS values. If   This program computes an RMS plot grid from one or more   are provided, each   This program computes an RMS plot grid from one or more   and   This program computes an RMS plot grid from one or more   serves as a template with variable  loopTime . This allows concatenation of instrument files, for example to create a month-long RMS plot grid from daily GPS orbit files (see below). Helmert parameters between the two frames can be estimated each epoch optionally if  estimateShift ,  estimateScale , or  estimateRotation  are set. It uses a  robust least squares adjustment .', 'config_table': 'outputfileRmsPlotGrid filename columns: mjd, id, rms outputfileHelmertTimeSeries filename columns: mjd, tx, ty, tz, scale, rx, ry, rz inputfileInstrument filename one file per satellite/station inputfileInstrumentReference filename one file per satellite/station, same order as above timeIntervals timeSeriesType for {loopTime} variable in inputfile factor double e.g. sqrt(3) for 3D RMS estimateShift boolean coordinate center every epoch estimateScale boolean scale factor of position every epoch estimateRotation boolean rotation every epoch huber double for robust least squares huberPower double for robust least squares huberMaxIteration uint (maximum) number of iterations for robust estimation', 'display_text': 'This program computes an RMS plot grid from one or more <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> containing 3D data (e.g. orbits or station positions), which can then be plotted as gridded data in <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>. The RMS is computed from the difference between <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentReference</a>. All instrument files must be synchronized (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>Each separate <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> represents an entry (e.g. a satellite or station) in the resulting grid. Therefore, providing, for example, 32 orbit files of GPS satellites results in a grid with columns: mjd, id (0-31), rms.</p><p>The first three data columns of the instrument data are considered for computation of the RMS values. The <strong class=\"groops-config-element\">factor</strong> can be set to, for example, sqrt(3) to get 3D instead of 1D RMS values.</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeIntervals</a> are provided, each <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentReference</a> serves as a template with variable <code>loopTime</code>. This allows concatenation of instrument files, for example to create a month-long RMS plot grid from daily GPS orbit files (see below).</p><p>Helmert parameters between the two frames can be estimated each epoch optionally if <strong class=\"groops-config-element\">estimateShift</strong>, <strong class=\"groops-config-element\">estimateScale</strong>, or <strong class=\"groops-config-element\">estimateRotation</strong> are set. It uses a <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>'},\n'Instrument2Scaleogram': { 'name': 'Instrument2Scaleogram', 'key': 'Instrument2Scaleogram', 'description': 'This program computes the wavelet transform of a time series up to a  maxLevel . The scalogram is written to a matrix which can be plotted by using a gridded layer in  PlotGraph . Individual detail levels can be written to matrix files by setting   This program computes the wavelet transform of a time series up to a  . The data column to be decomposed must be set by  selectDataField . The wavelet transform is implemented as a filter bank, so care should be taken when the input contains data gaps. Low/highpass wavelet filters are applied in forward and backward direction, input is padded symmetric. See   This program computes the wavelet transform of a time series up to a   for details.', 'config_table': 'outputfileScaleogram filename matrix columns: mjd, level, value outputfileLevels filename use loopLevel as variable inputfileInstrument filename  inputfileWavelet filename wavelet coefficients selectDataField uint data column to transform maxLevel uint maximum level of decomposition (default: full)', 'display_text': 'This program computes the wavelet transform of a time series up to a <strong class=\"groops-config-element\">maxLevel</strong>. The scalogram is written to a matrix which can be plotted by using a gridded layer in <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>. Individual detail levels can be written to matrix files by setting <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileLevels</a>. The data column to be decomposed must be set by <strong class=\"groops-config-element\">selectDataField</strong>.</p><p>The wavelet transform is implemented as a filter bank, so care should be taken when the input contains data gaps. Low/highpass wavelet filters are applied in forward and backward direction, input is padded symmetric. See <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> for details.</p><p>'},\n'Instrument2SpectralCoherence': { 'name': 'Instrument2SpectralCoherence', 'key': 'Instrument2SpectralCoherence', 'description': 'This program computes the spectral coherence between two  instrument files . The (magnitude-squared) coherence is defined as  and is a measure in the range [0, 1] for the similarity of the signals   and   in frequency domain.   is the cross-spectral density between   and   and  ,   are auto-spectral densities. Auto- and cross-spectral densities are computed using Lomb\\'s method (see  Instrument2PowerSpectralDensity  for details). The resulting PSD is the average over all arcs. For regularly sampled time series, this method yields the same results as FFT based PSD estimates. A regular frequency grid based on the longest arc and the median sampling is computed. The maximum number of epochs per arc is determined by  the Nyquist frequency is given by   If it is suspected that   This program computes the spectral coherence between two   contains secular variations, the input should be detrended using  InstrumentDetrend . The   This program computes the spectral coherence between two   contains a matrix with the frequency vector as first column, the coherence for each instrument channel is saved in the following columns.', 'config_table': 'outputfileCoherence filename column 1: frequency, column 2-n coherence inputfileInstrument filename  inputfileInstrumentReference filename', 'display_text': 'This program computes the spectral coherence between two <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a>.</p><p>The (magnitude-squared) coherence is defined as \\\\[   C_{xy}(f) = \\\\frac{|P_{xy}(f)|^2}{P_{xx}(f)P_{yy}(f)} \\\\]and is a measure in the range [0, 1] for the similarity of the signals $x$ and $y$ in frequency domain. $P_{xy}$ is the cross-spectral density between $x$ and $y$ and $P_{xx}$, $P_{yy}$ are auto-spectral densities. Auto- and cross-spectral densities are computed using Lomb\\'s method (see <a class=\"groops-program\" href=\"Instrument2PowerSpectralDensity.html\">Instrument2PowerSpectralDensity</a> for details).</p><p>The resulting PSD is the average over all arcs. For regularly sampled time series, this method yields the same results as FFT based PSD estimates.</p><p>A regular frequency grid based on the longest arc and the median sampling is computed. The maximum number of epochs per arc is determined by \\\\[   N = \\\\frac{t_{\\\\text{end}} - t_{\\\\text{start}}}{\\\\Delta t_{\\\\text{median}} } + 1, \\\\]the Nyquist frequency is given by \\\\[   f_{\\\\text{nyq}} = \\\\frac{1}{2\\\\Delta t_{\\\\text{median}}}. \\\\] If it is suspected that <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> contains secular variations, the input should be detrended using <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCoherence</a> contains a matrix with the frequency vector as first column, the coherence for each instrument channel is saved in the following columns.'},\n'Instrument2Spectrogram': { 'name': 'Instrument2Spectrogram', 'key': 'Instrument2Spectrogram', 'description': 'This program applies the Short Time Fourier Transform (STFT) to selected data columns of   This program applies the Short Time Fourier Transform (STFT) to selected data columns of   and computes the spectrogram. The STFT is computed at centered   This program applies the Short Time Fourier Transform (STFT) to selected data columns of   with an (possible overlapping) rectangular window with  windowLength  seconds. Data gaps are zero padded within the window. The   This program applies the Short Time Fourier Transform (STFT) to selected data columns of   is a matrix with each row the time (MJD), the frequency  , and the amplitudes   for the selected data columns. It can be plotted with  PlotGraph .', 'config_table': 'outputfileSpectrogram filename mjd, freq, ampl0, ampl1, ... inputfileInstrument filename  timeSeries timeSeriesType center of SFFT window windowLength double [seconds] startDataFields uint start countDataFields uint number of data fields (default: all)', 'display_text': 'This program applies the Short Time Fourier Transform (STFT) to selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> and computes the spectrogram. The STFT is computed at centered <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> with an (possible overlapping) rectangular window with <strong class=\"groops-config-element\">windowLength</strong> seconds. Data gaps are zero padded within the window.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSpectrogram</a> is a matrix with each row the time (MJD), the frequency $[Hz]$, and the amplitudes $[unit/\\\\sqrt{Hz}]$ for the selected data columns. It can be plotted with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.</p><p>'},\n'InstrumentAccelerometer2ThermosphericDensity': { 'name': 'InstrumentAccelerometer2ThermosphericDensity', 'key': 'InstrumentAccelerometer2ThermosphericDensity', 'description': 'This program estimates neutral mass densities along the satellite trajectory based on  accelerometer data . In order to determine the neutral mass density the accelerometer input should only reflect the accelerations due to drag (e.g.   This program estimates neutral mass densities along the satellite trajectory based on  ). Thus, influences from solar and Earth radiation pressure must be reduced beforehand.', 'config_table': 'outputfileDensity filename MISCVALUE (kg/m^3) satelliteModel filename satellite macro model inputfileOrbit filename  inputfileStarCamera filename  inputfileAccelerometer filename add non-gravitational forces in satellite reference frame thermosphere thermosphereType used to compute temperature and wind considerTemperature boolean compute drag and lift, otherwise simple drag coefficient is used considerWind boolean  earthRotation earthRotationType  ephemerides ephemeridesType', 'display_text': 'This program estimates neutral mass densities along the satellite trajectory based on <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>. In order to determine the neutral mass density the accelerometer input should only reflect the accelerations due to drag (e.g. <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">miscAccelerations:atmosphericDrag</a>). Thus, influences from solar and Earth radiation pressure must be reduced beforehand.'},\n'InstrumentAccelerometerApplyEstimatedParameters': { 'name': 'InstrumentAccelerometerApplyEstimatedParameters', 'key': 'InstrumentAccelerometerApplyEstimatedParameters', 'description': 'This program evaluates estimated satellite parameters and writes the result to an accelerometer file.', 'config_table': 'outputfileAccelerometer filename  inputfileSatelliteModel filename satellite macro model inputfileOrbit filename  inputfileStarCamera filename  inputfileAccelerometer filename add non-gravitational forces in satellite reference frame earthRotation earthRotationType  ephemerides ephemeridesType may be needed by parametrizationAcceleration parametrizationAcceleration parametrizationAccelerationType orbit force parameters inputfileParameter filename estimated orbit force parameters indexStart int position in the solution vector rightSide int if solution contains several right hand sides, select one factor double the result is multiplied by this factor', 'display_text': 'This program evaluates estimated satellite parameters and writes the result to an accelerometer file.'},\n'InstrumentAccelerometerEstimateBiasScale': { 'name': 'InstrumentAccelerometerEstimateBiasScale', 'key': 'InstrumentAccelerometerEstimateBiasScale', 'description': 'This program calibrates   This program calibrates   with respect to simulated accelerometer data, see  SimulateAccelerometer . The parameters   This program calibrates   of   This program calibrates   are estimated and the effect is reduced to calibrate the  accelerometer data . If   This program calibrates   is given, the corresponding epochs (within  marginThruster ) are not used for the parameter estimation, but the accelerometer epochs are still calibrated afterwards. An arbitrary instrument file is allowed here. The   This program calibrates  ,   This program calibrates  ,   This program calibrates  ,   This program calibrates  , and   This program calibrates   are only needed for some special parametrizations.', 'config_table': 'outputfileAccelerometer filename  outputfileSolution filename  inputfileAccelerometer filename  inputfileAccelerometerSim filename  inputfileThruster filename remove thruster events marginThruster double margin size (on both sides) [seconds] inputfileOrbit filename  inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType may be needed by parametrizationAcceleration inputfileSatelliteModel filename satellite macro model parametrizationAcceleration parametrizationAccelerationType', 'display_text': 'This program calibrates <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> with respect to simulated accelerometer data, see <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>. The parameters <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> of <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> are estimated and the effect is reduced to calibrate the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>.</p><p>If <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileThruster</a> is given, the corresponding epochs (within <strong class=\"groops-config-element\">marginThruster</strong>) are not used for the parameter estimation, but the accelerometer epochs are still calibrated afterwards. An arbitrary instrument file is allowed here.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>, <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>, <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a>, and <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">satelliteModel</a> are only needed for some special parametrizations.'},\n'InstrumentAccelerometerEstimateParameters': { 'name': 'InstrumentAccelerometerEstimateParameters', 'key': 'InstrumentAccelerometerEstimateParameters', 'description': 'This program estimates calibration parameters for acceleration data given given an optional reference acceleration. Specifically, the program solves the equation  for the unknown parameters  , where   is given in   This program estimates calibration parameters for acceleration data given given an optional reference acceleration. Specifically, the program solves the equation   and   is given in    This program estimates calibration parameters for acceleration data given given an optional reference acceleration. Specifically, the program solves the equation  . The parametrization of   can be set via   This program estimates calibration parameters for acceleration data given given an optional reference acceleration. Specifically, the program solves the equation  . Optionally, the empirical covariance functions for the accelerations   can be estimated by enabling  estimateCovarianceFunctions . The estimated parameters are written to the file   This program estimates calibration parameters for acceleration data given given an optional reference acceleration. Specifically, the program solves the equation   and can be used by  InstrumentAccelerometerApplyEstimatedParameters  to calibrate accelerometer measurements.', 'config_table': 'outputfileSolution filename values for estimated parameters outputfileParameterNames filename names of the estimated parameters estimateArcSigmas sequence  outputfileArcSigmas filename accuracies of each arc estimateEpochSigmas sequence  outputfileEpochSigmas filename estimated epoch-wise sigmas estimateCovarianceFunctions sequence  outputfileCovarianceFunction filename covariance functions for x, y, z direction inputfileAccelerometer filename  inputfileAccelerometerReference filename if not given, reference acceleration is assumed zero inputfileOrbit filename may be needed by parametrizationAcceleration inputfileStarCamera filename may be needed by parametrizationAcceleration inputfileSatelliteModel filename satellite macro model (may be needed by parametrizationAcceleration) earthRotation earthRotationType may be needed by parametrizationAcceleration ephemerides ephemeridesType may be needed by parametrizationAcceleration parametrizationAcceleration parametrizationAccelerationType  sigmaX double apriori accuracy in x-axis sigmaY double apriori accuracy in y-axis sigmaZ double apriori accuracy in z-axis iterationCount uint iteration count for determining the covariance function', 'display_text': 'This program estimates calibration parameters for acceleration data given given an optional reference acceleration. Specifically, the program solves the equation \\\\[   \\\\mathbf{a} - \\\\mathbf{a}_\\\\text{ref} = \\\\mathbf{f}(\\\\mathbf{x}) + \\\\mathbf{e} \\\\]for the unknown parameters $\\\\mathbf{x}$, where $\\\\mathbf{a}$ is given in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> and $\\\\mathbf{a}_\\\\text{ref}$ is given in  <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometerReference</a>. The parametrization of $\\\\mathbf{x}$ can be set via <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a>. Optionally, the empirical covariance functions for the accelerations $\\\\mathbf{a}$ can be estimated by enabling <strong class=\"groops-config-element\">estimateCovarianceFunctions</strong>.</p><p>The estimated parameters are written to the file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> and can be used by <a class=\"groops-program\" href=\"InstrumentAccelerometerApplyEstimatedParameters.html\">InstrumentAccelerometerApplyEstimatedParameters</a> to calibrate accelerometer measurements.'},\n'InstrumentApplyTimeOffset': { 'name': 'InstrumentApplyTimeOffset', 'key': 'InstrumentApplyTimeOffset', 'description': 'This program applies a   This program applies a   (MISCVALUE) to an   This program applies a  . The time offsets in seconds are multiplicated with a  factor . The instrument files must be synchronized (see  InstrumentSynchronize ).', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  inputfileTimeOffset filename MISCVALUE with time offset in seconds factor double applied to time offset', 'display_text': 'This program applies a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeOffset</a> (MISCVALUE) to an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>. The time offsets in seconds are multiplicated with a <strong class=\"groops-config-element\">factor</strong>. The instrument files must be synchronized (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).'},\n'InstrumentArcCalculate': { 'name': 'InstrumentArcCalculate', 'key': 'InstrumentArcCalculate', 'description': 'This program manipulates the data columns every arc of an  instrument file  similar to  FunctionsCalculate , see there for more details. If several   This program manipulates the data columns every arc of an  s are given the data columns are copied side by side. For this the instrument files must be synchronized (see  InstrumentSynchronize ). For the data columns the standard data variables are available, see  dataVariables . For the time column (MJD) a variable  epoch  (together with  epochmean ,  epochmin ,  ) is defined additionally. The content of   This program manipulates the data columns every arc of an   is controlled by  outColumn . The number of  outColumn  must agree with the selected   This program manipulates the data columns every arc of an  . The algorithm to compute the output is as follows: The expressions in  outColumn  are evaluated once for each epoch of the input. The variables  data0 ,  data1 ,  are replaced by the according values from the input columns before. If no  outColumn  are specified all input columns are used instead directly. The   This program manipulates the data columns every arc of an   can be specified with  outType  and must be agree with the number of columns. An extra  statistics  file can be generated with one mid epoch per arc. For the computation of the  outColumn  values all  dataVariables  are available (e.g.  epochmin ,  data0mean ,  data1std ,  ) inclusively the  constant s and estimated  parameter s but without the  data0 ,  data1 ,  itself. The variables and the numbering of the columns refers to the   This program manipulates the data columns every arc of an  . See also  FunctionsCalculate ,  MatrixCalculate .', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename data columns are appended to the right constant expression define a constant by name=value parameter expression define a parameter by name[=value] leastSquares expression try to minimize the expression by adjustment of the parameters removalCriteria expression row is removed if one criterion evaluates true. outType instrumentTypeType  outColumn expression expression of output columns, extra \\'epoch\\' variable statistics sequence  outputfileInstrument filename instrument file with mid epoch per arc, data columns are user defined outColumn expression expression to compute statistics columns, data* are from outColumn', 'display_text': 'This program manipulates the data columns every arc of an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> similar to <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, see there for more details. If several <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>s are given the data columns are copied side by side. For this the instrument files must be synchronized (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>). For the data columns the standard data variables are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>. For the time column (MJD) a variable <code>epoch</code> (together with <code>epochmean</code>, <code>epochmin</code>, ) is defined additionally.</p><p>The content of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> is controlled by <strong class=\"groops-config-element\">outColumn</strong>. The number of <strong class=\"groops-config-element\">outColumn</strong> must agree with the selected <a class=\"groops-class\" href=\"instrumentTypeType.html\">outType</a>. The algorithm to compute the output is as follows: The expressions in <strong class=\"groops-config-element\">outColumn</strong> are evaluated once for each epoch of the input. The variables <code>data0</code>, <code>data1</code>, are replaced by the according values from the input columns before. If no <strong class=\"groops-config-element\">outColumn</strong> are specified all input columns are used instead directly. The <a class=\"groops-class\" href=\"instrumentTypeType.html\">instrument type</a> can be specified with <strong class=\"groops-config-element\">outType</strong> and must be agree with the number of columns.</p><p>An extra <strong class=\"groops-config-element\">statistics</strong> file can be generated with one mid epoch per arc. For the computation of the <strong class=\"groops-config-element\">outColumn</strong> values all <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available (e.g. <code>epochmin</code>, <code>data0mean</code>, <code>data1std</code>, ) inclusively the <strong class=\"groops-config-element\">constant</strong>s and estimated <strong class=\"groops-config-element\">parameter</strong>s but without the <code>data0</code>, <code>data1</code>, itself. The variables and the numbering of the columns refers to the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a>.</p><p>See also <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.'},\n'InstrumentArcCrossStatistics': { 'name': 'InstrumentArcCrossStatistics', 'key': 'InstrumentArcCrossStatistics', 'description': 'Computes statistics of selected data columns between two  instrument files  arc wise. The   Computes statistics of selected data columns between two   contains for every arc one (mid) epoch with statistics column(s). Possible statistics are      Correlation       Error RMS       Nash-Sutcliffe coefficient (NSC)     With  removeArcMean  the mean of each data column of each arc is reduced before. With  perColumn  separate statistics for each selected data column are computed, otherwise an overall value is computed. See also  InstrumentArcStatistics ,  InstrumentStatisticsTimeSeries .', 'config_table': 'outputfileStatisticsTimeSeries filename statistics column(s) per arc, MISCVALUES inputfileInstrument filename  inputfileInstrumentReference filename  statistics choice  correlation   errorRMS  rms of differences nashSutcliffe  with respect to reference field removeArcMean boolean  startDataFields uint start countDataFields uint number of data fields (default: all) perColumn boolean compute statistic per column', 'display_text': 'Computes statistics of selected data columns between two <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a> arc wise. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStatisticsTimeSeries</a> contains for every arc one (mid) epoch with statistics column(s). Possible statistics are <ul>    <li>Correlation   \\\\[     \\\\rho = \\\\frac{\\\\sum_i x_i y_i}{\\\\sqrt{(\\\\sum_i x_i^2) (\\\\sum_i y_i^2})},   \\\\]  </li><li> Error RMS   \\\\[     rms = \\\\sqrt{\\\\frac{1}{N}\\\\sum_i (x_i-y_i)^2},   \\\\]  </li><li> Nash-Sutcliffe coefficient (NSC)   \\\\[     nsc = 1- \\\\frac{\\\\sum_i (x_i-y_i)^2}{\\\\sum_i (y_i-\\\\bar{y})^2}.   \\\\]</li></ul>  With <strong class=\"groops-config-element\">removeArcMean</strong> the mean of each data column of each arc is reduced before.</p><p>With <strong class=\"groops-config-element\">perColumn</strong> separate statistics for each selected data column are computed, otherwise an overall value is computed.</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a>, <a class=\"groops-program\" href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a>.'},\n'InstrumentArcStatistics': { 'name': 'InstrumentArcStatistics', 'key': 'InstrumentArcStatistics', 'description': 'Computes statistics of selected data columns of   Computes statistics of selected data columns of   arc wise. The   Computes statistics of selected data columns of   contains for every arc one (mid) epoch with statistics column(s). Possible statistics are root mean square, standard deviation, mean, median, min, and max. With  perColumn  separate statistics for each selected data column are computed, otherwise an overall value is computed. See also  InstrumentArcCrossStatistics ,  InstrumentStatisticsTimeSeries .', 'config_table': 'outputfileStatisticsTimeSeries filename columns: mjd, statistics column(s) per instrument file inputfileInstrument filename  statistics choice  rootMeanSquare   standardDeviation   mean   median   min   max   epochCount   startDataFields uint start countDataFields uint number of data fields (default: all) perColumn boolean compute statistic per column ignoreNan boolean ignore NaN values in input', 'display_text': 'Computes statistics of selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> arc wise. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStatisticsTimeSeries</a> contains for every arc one (mid) epoch with statistics column(s). Possible statistics are root mean square, standard deviation, mean, median, min, and max.</p><p>With <strong class=\"groops-config-element\">perColumn</strong> separate statistics for each selected data column are computed, otherwise an overall value is computed.</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcCrossStatistics.html\">InstrumentArcCrossStatistics</a>, <a class=\"groops-program\" href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a>.'},\n'InstrumentConcatenate': { 'name': 'InstrumentConcatenate', 'key': 'InstrumentConcatenate', 'description': 'This program concatenate the arcs from several  instrument files  and write it to a new  file . Input files must be of the same type. The arcs are merged to one arc even though there is a gap inbetween. To split the data into arcs use  InstrumentSynchronize . Three options are available:  sort ,  removeDuplicates  and  checkForNaNs . If  sort  is enabled, the program reads all files, no matter if they are sorted correctly in time, and then sorts the epochs. If  removeDuplicates  is enabled, the program checks the whole data set for epochs that are contained twice. And if  checkForNaNs  is enabled the data set is checked for invalid epochs containing NaNs.', 'config_table': 'outputfile filename  inputfile filename  sort boolean sort epochs with increasing time removeDuplicates choice remove duplicate epochs keepFirst sequence keep first epoch with the same time stamp, remove all others margin double margin for identical times [seconds] keepLast sequence keep last epoch with the same time stamp, remove all others margin double margin for identical times [seconds] checkForNaNs boolean remove epochs with NaN values in one of the data fields', 'display_text': 'This program concatenate the arcs from several <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a> and write it to a new <a class=\"groops-file\" href=\"fileFormat_instrument.html\">file</a>. Input files must be of the same type. The arcs are merged to one arc even though there is a gap inbetween. To split the data into arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>. Three options are available: <strong class=\"groops-config-element\">sort</strong>, <strong class=\"groops-config-element\">removeDuplicates</strong> and <strong class=\"groops-config-element\">checkForNaNs</strong>. If <strong class=\"groops-config-element\">sort</strong> is enabled, the program reads all files, no matter if they are sorted correctly in time, and then sorts the epochs. If <strong class=\"groops-config-element\">removeDuplicates</strong> is enabled, the program checks the whole data set for epochs that are contained twice. And if <strong class=\"groops-config-element\">checkForNaNs</strong> is enabled the data set is checked for invalid epochs containing NaNs.'},\n'InstrumentCovarianceCheck': { 'name': 'InstrumentCovarianceCheck', 'key': 'InstrumentCovarianceCheck', 'description': 'This program checks   This program checks   3x3 covariance matrices if they are invertible or not and removes the invalid epochs.', 'config_table': 'outputfileCovariance3d filename  inputfileCovariance3d filename', 'display_text': 'This program checks <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariance3d</a> 3x3 covariance matrices if they are invertible or not and removes the invalid epochs.'},\n'InstrumentDetrend': { 'name': 'InstrumentDetrend', 'key': 'InstrumentDetrend', 'description': 'Reduces   Reduces   (e.g. const, trend, polynomial) per arc from selected data columns of   Reduces   using a robust  robust least squares adjustment . The   Reduces   contains for every arc one (mid) epoch with the estimated parameters. The order is: first all data ( data0 ,  data1 ,  ) of first temporal parameter, followed by all data of the second temporal parameter and so on.', 'config_table': 'outputfileInstrument filename detrended instrument time series outputfileTimeSeriesArcParameters filename time series of estimated parameters per arc inputfileInstrument filename  parametrizationTemporal parametrizationTemporalType per arc, data is reduced by temporal representation startDataFields uint start countDataFields uint number of data fields (default: all after start) huber double for robust least squares huberPower double for robust least squares huberMaxIteration uint (maximum) number of iterations for robust estimation', 'display_text': 'Reduces <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> (e.g. const, trend, polynomial) per arc from selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> using a robust <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeriesArcParameters</a> contains for every arc one (mid) epoch with the estimated parameters. The order is: first all data (<code>data0</code>, <code>data1</code>, ) of first temporal parameter, followed by all data of the second temporal parameter and so on.'},\n'InstrumentEarthRotation': { 'name': 'InstrumentEarthRotation', 'key': 'InstrumentEarthRotation', 'description': 'Precompute Earth rotation matrix from celestial to terrestrial frame and save as  StarCamera file .', 'config_table': 'outputfileStarCamera filename rotation from CRF to TRF earthRotation earthRotationType  timeSeries timeSeriesType', 'display_text': 'Precompute Earth rotation matrix from celestial to terrestrial frame and save as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">StarCamera file</a>.'},\n'InstrumentEstimateEmpiricalCovariance': { 'name': 'InstrumentEstimateEmpiricalCovariance', 'key': 'InstrumentEstimateEmpiricalCovariance', 'description': 'This program estimates the empirical auto- and cross-covariance of selected data columns per arc of   This program estimates the empirical auto- and cross-covariance of selected data columns per arc of  . The maximum computed lag is determined by the number of   This program estimates the empirical auto- and cross-covariance of selected data columns per arc of   specified (for a single output file only the auto-covariance is determined, for two output files auto- and cross-covariance is computed and so on). Stationarity is assumed for the input time series, which means the temporal covariance matrix has Toeplitz structure.   The matrix for lag   describes the covariance between   and  , i.e.  . To get a reliable estimate,  InstrumentDetrend  should be called first.', 'config_table': 'outputfileCovarianceMatrix filename  inputfileInstrument filename  startDataFields uint start countDataFields uint number of data fields (default: all after start)', 'display_text': 'This program estimates the empirical auto- and cross-covariance of selected data columns per arc of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>. The maximum computed lag is determined by the number of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovarianceMatrix</a> specified (for a single output file only the auto-covariance is determined, for two output files auto- and cross-covariance is computed and so on).</p><p>Stationarity is assumed for the input time series, which means the temporal covariance matrix has Toeplitz structure. \\\\[ \\\\begin{bmatrix} \\\\Sigma & \\\\Sigma_{\\\\Delta_1} & \\\\Sigma_{\\\\Delta_2} & \\\\Sigma_{\\\\Delta_3} & \\\\Sigma_{\\\\Delta_4} \\\\\\\\        & \\\\Sigma            & \\\\Sigma_{\\\\Delta_1} & \\\\Sigma_{\\\\Delta_2} & \\\\Sigma_{\\\\Delta_3} \\\\\\\\        &                   & \\\\Sigma            & \\\\Sigma_{\\\\Delta_1} & \\\\Sigma_{\\\\Delta_2} \\\\\\\\        &                   &                   & \\\\Sigma            & \\\\Sigma_{\\\\Delta_1} \\\\\\\\        &                   &                   &                   & \\\\Sigma            \\\\\\\\ \\\\end{bmatrix} \\\\] The matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\\\Sigma(t-h, t)$.</p><p>To get a reliable estimate, <a class=\"groops-program\" href=\"InstrumentDetrend.html\">InstrumentDetrend</a> should be called first.'},\n'InstrumentEstimateHelmertTransformation': { 'name': 'InstrumentEstimateHelmertTransformation', 'key': 'InstrumentEstimateHelmertTransformation', 'description': 'This program estimates a 3D Helmert transformation between two networks (frame realizations, e.g. GNSS satellite or station network). Each separate  data  represents a satellite/station/ (e.g. 32 GPS satellites). The instrument data (x,y,z position) considered can be set with  startData . The Helmert parameters are set up according to   This program estimates a 3D Helmert transformation between two networks (frame realizations, e.g. GNSS satellite or station network). Each separate   for each   This program estimates a 3D Helmert transformation between two networks (frame realizations, e.g. GNSS satellite or station network). Each separate   and are estimated using a  robust least squares adjustment .', 'config_table': 'outputfileHelmertTimeSeries filename columns: mjd, Tx,Ty,Tz,s,Rx,Ry,Rz according to temporal parametrization data sequence e.g. satellite, station outputfileInstrument filename transformed positions as instrument type Vector3d outputfileInstrumentDiff filename position difference as instrument type Vector3d inputfileInstrument filename  inputfileInstrumentReference filename  startDataFields uint start index of position (x,y,z) columns timeIntervals timeSeriesType parameters are estimated per interval parametrizationTemporal parametrizationTemporalType temporal parametrization estimateShift boolean coordinate center estimateScale boolean scale factor of position estimateRotation boolean rotation huber double for robust least squares huberPower double for robust least squares huberMaxIteration uint (maximum) number of iterations for robust estimation', 'display_text': 'This program estimates a 3D Helmert transformation between two networks (frame realizations, e.g. GNSS satellite or station network). Each separate <strong class=\"groops-config-element\">data</strong> represents a satellite/station/(e.g. 32 GPS satellites). The instrument data (x,y,z position) considered can be set with <strong class=\"groops-config-element\">startData</strong>. The Helmert parameters are set up according to <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> for each <a class=\"groops-class\" href=\"timeSeriesType.html\">timeIntervals</a> and are estimated using a <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.'},\n'InstrumentFilter': { 'name': 'InstrumentFilter', 'key': 'InstrumentFilter', 'description': 'This program filter selected data columns of   This program filter selected data columns of   with   This program filter selected data columns of   arc wise.', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  digitalFilter digitalFilterType  startDataFields uint start countDataFields uint number of data fields (default: all after start)', 'display_text': 'This program filter selected data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> with <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> arc wise.'},\n'InstrumentInsertNAN': { 'name': 'InstrumentInsertNAN', 'key': 'InstrumentInsertNAN', 'description': 'This program inserts NAN epochs into   This program inserts NAN epochs into   files, either at specific   This program inserts NAN epochs into   or where gaps in the instrument are detected.', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  times timeSeriesType Insert NAN at specific times. atGaps boolean Insert NAN where epochs are more than 1.5 times the median sampling apart. atArcEnds boolean Insert one epoch with data NAN at arc ends', 'display_text': 'This program inserts NAN epochs into <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> files, either at specific <a class=\"groops-class\" href=\"timeSeriesType.html\">times</a> or where gaps in the instrument are detected.'},\n'InstrumentMultiplyAdd': { 'name': 'InstrumentMultiplyAdd', 'key': 'InstrumentMultiplyAdd', 'description': 'This program multiply  instrument data  with a factor and add them together. Afterwards the mean of each arc and data column can be removed with  removeArcMean . The instrument files must be synchronized ( InstrumentSynchronize ). See also  InstrumentArcCalculate .', 'config_table': 'outputfileInstrument filename  instrument sequence  inputfileInstrument filename  factor double  removeArcMean boolean remove mean value of each arc', 'display_text': 'This program multiply <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> with a factor and add them together. Afterwards the mean of each arc and data column can be removed with <strong class=\"groops-config-element\">removeArcMean</strong>. The instrument files must be synchronized (<a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>.'},\n'InstrumentReduceSampling': { 'name': 'InstrumentReduceSampling', 'key': 'InstrumentReduceSampling', 'description': 'This program reduce the sampling of a instrument file. Only epochs with a time stamp with a division by  sampling  without remainder are kept (inside  margin ).', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  sampling double new sampling in seconds margin double margin around the new sampling in seconds relative2FirstEpoch boolean compute sampling relative to time of first epoch', 'display_text': 'This program reduce the sampling of a instrument file. Only epochs with a time stamp with a division by <strong class=\"groops-config-element\">sampling</strong> without remainder are kept (inside <strong class=\"groops-config-element\">margin</strong>).'},\n'InstrumentRemoveEpochsByCriteria': { 'name': 'InstrumentRemoveEpochsByCriteria', 'key': 'InstrumentRemoveEpochsByCriteria', 'description': 'This program removes epochs from   This program removes epochs from   by evaluating a set of  removalCriteria  expressions. For the data columns the standard data variables are available, see  dataVariables . The instrument data can be reduced by data from   This program removes epochs from   prior to evaluation of the expressions. To reduce the data by its median, use an expression like  data1-data1mean . To remove epochs that deviate by more than 3 sigma use  abs(data1)>3*data1std  or  abs(data0-data0median)>3*1.4826*data0mad . All arcs in the input instrument file are concatenated, meaning expressions like  data1mean  refer to the complete dataset. The removed epochs can be saved in a separate   This program removes epochs from  .', 'config_table': 'outputfileInstrument filename all data is stored in one arc outputfileInstrumentRemovedEpochs filename all data is stored in one arc inputfileInstrument filename arcs are concatenated for processing inputfileInstrumentReference filename if given, the reference data is reduced prior to the expressions being evaluated removalCriteria expression epochs are removed if one criterion evaluates true. data0 is the first data field. margin double remove data around identified epochs (on both sides) [seconds]', 'display_text': 'This program removes epochs from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> by evaluating a set of <strong class=\"groops-config-element\">removalCriteria</strong> expressions. For the data columns the standard data variables are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The instrument data can be reduced by data from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrumentReference</a> prior to evaluation of the expressions.</p><p>To reduce the data by its median, use an expression like <code>data1-data1mean</code>. To remove epochs that deviate by more than 3 sigma use <code>abs(data1)>3*data1std</code> or <code>abs(data0-data0median)>3*1.4826*data0mad</code>.</p><p>All arcs in the input instrument file are concatenated, meaning expressions like <code>data1mean</code> refer to the complete dataset. The removed epochs can be saved in a separate <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrumentRemovedEpochs</a>.'},\n'InstrumentRemoveEpochsByTimes': { 'name': 'InstrumentRemoveEpochsByTimes', 'key': 'InstrumentRemoveEpochsByTimes', 'description': 'This program compares an  instrument file  with a   This program compares an  . Epochs contained within the time series (including a defined margin) are removed from the instrument file. The margin is added on both sides of the epochs. The arcs of the instrument file are concatenated to one arc. The removed epochs can be saved in a separate instrument file.', 'config_table': 'outputfileInstrument filename all epochs are concatenated in one arc outputfileInstrumentRemovedEpochs filename all epochs are concatenated in one arc inputfileInstrument filename  timePoints timeSeriesType  margin double margin size (on both sides) [seconds]', 'display_text': 'This program compares an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> with a <a class=\"groops-class\" href=\"timeSeriesType.html\">time series</a>. Epochs contained within the time series (including a defined margin) are removed from the instrument file. The margin is added on both sides of the epochs. The arcs of the instrument file are concatenated to one arc. The removed epochs can be saved in a separate instrument file.'},\n'InstrumentRemoveEpochsThruster': { 'name': 'InstrumentRemoveEpochsThruster', 'key': 'InstrumentRemoveEpochsThruster', 'description': 'This program remove epochs from an  instrument file . The epochs are defined by a  thruster file  plus a defined margin before and after the thruster firings. The arcs of the instrument file are concatenated to one arc. The removed epochs can be saved in a separate instrument file.', 'config_table': 'outputfileInstrument filename all epochs are concatenated in one arc outputfileInstrumentRemovedEpochs filename all epochs are concatenated in one arc inputfileInstrument filename  inputfileThruster filename THRUSTER marginBefore double margin before start of firing [seconds] marginAfter double margin after end of firing [seconds]', 'display_text': 'This program remove epochs from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The epochs are defined by a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">thruster file</a> plus a defined margin before and after the thruster firings. The arcs of the instrument file are concatenated to one arc. The removed epochs can be saved in a separate instrument file.'},\n'InstrumentResample': { 'name': 'InstrumentResample', 'key': 'InstrumentResample', 'description': 'This program resamples  instrument data  to a given   This program resamples   using a resampling   This program resamples  . This program can also be used to reduce the sampling of an instrument file, but a better way to reduce the sampling of noisy data with regular sampling is to use a low pass filter first with  InstrumentFilter  and then thin out the data with  InstrumentReduceSampling .', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  method interpolatorTimeSeriesType resampling method timeSeries timeSeriesType resampled points in time', 'display_text': 'This program resamples <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> to a given <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> using a resampling <a class=\"groops-class\" href=\"interpolatorTimeSeriesType.html\">method</a>.</p><p>This program can also be used to reduce the sampling of an instrument file, but a better way to reduce the sampling of noisy data with regular sampling is to use a low pass filter first with <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a> and then thin out the data with <a class=\"groops-program\" href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a>.'},\n'InstrumentRotate': { 'name': 'InstrumentRotate', 'key': 'InstrumentRotate', 'description': 'This program rotates  instrument data  into a new reference frame (using   This program rotates  ). The rotation is usually done from satellite frame into inertial frame. To apply Earth rotation to orbits use  Orbit2EarthFixedOrbit  For other instrument data use  InstrumentEarthRotation  before.', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  inputfileStarCamera filename  inverseRotate boolean', 'display_text': 'This program rotates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> into a new reference frame (using <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>). The rotation is usually done from satellite frame into inertial frame.</p><p>To apply Earth rotation to orbits use <a class=\"groops-program\" href=\"Orbit2EarthFixedOrbit.html\">Orbit2EarthFixedOrbit</a> For other instrument data use <a class=\"groops-program\" href=\"InstrumentEarthRotation.html\">InstrumentEarthRotation</a> before.'},\n'InstrumentSetType': { 'name': 'InstrumentSetType', 'key': 'InstrumentSetType', 'description': 'Convert  instrument data  into instrument data with new   Convert  . The selected number of data columns must agree with the   Convert  .', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  type instrumentTypeType  startDataFields uint start countDataFields uint number of data fields (default: all after start)', 'display_text': 'Convert <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a> into instrument data with new <a class=\"groops-class\" href=\"instrumentTypeType.html\">type</a>. The selected number of data columns must agree with the <a class=\"groops-class\" href=\"instrumentTypeType.html\">type</a>.'},\n'InstrumentStarCamera2AccAngularRate': { 'name': 'InstrumentStarCamera2AccAngularRate', 'key': 'InstrumentStarCamera2AccAngularRate', 'description': 'This program derivate from a time series of quaternions a series of angular rates and angular accelerations. The derivatives are computed by a polynomial interpolation with  interpolationDegree  of the quaternions.', 'config_table': 'outputfileAngularRate filename [rad/s], VECTOR3D outputfileAngularAcc filename [rad/s**2], VECTOR3D inputfileStarCamera filename  interpolationDegree uint derivation by polynomial interpolation of degree n', 'display_text': 'This program derivate from a time series of quaternions a series of angular rates and angular accelerations. The derivatives are computed by a polynomial interpolation with <strong class=\"groops-config-element\">interpolationDegree</strong> of the quaternions.'},\n'InstrumentStarCamera2RollPitchYaw': { 'name': 'InstrumentStarCamera2RollPitchYaw', 'key': 'InstrumentStarCamera2RollPitchYaw', 'description': 'Compute roll, pitch, yaw angles from   Compute roll, pitch, yaw angles from   data. Optional the angles are computed relative to a   Compute roll, pitch, yaw angles from  . See also  SimulateStarCamera .', 'config_table': 'outputfileInstrument filename roll, pitch, yaw [rad], VECTOR3D inputfileStarCamera filename  inputfileStarCameraReference filename nominal orientation', 'display_text': 'Compute roll, pitch, yaw angles from <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> data. Optional the angles are computed relative to a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCameraReference</a>.</p><p>See also <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a>.'},\n'InstrumentStarCamera2RotaryMatrix': { 'name': 'InstrumentStarCamera2RotaryMatrix', 'key': 'InstrumentStarCamera2RotaryMatrix', 'description': 'Write   Write   rotations as   Write   rotary matrices (for each epoch  ).', 'config_table': 'outputfileInstrument filename xx, xy, xz, yx, yy, yz, zx, zy, zz (MISCVALUES) inputfileStarCamera filename', 'display_text': 'Write <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> rotations as <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> rotary matrices (for each epoch $xx, xy, xz, yx, yy, yz, zx, zy, zz$).'},\n'InstrumentStarCameraMultiply': { 'name': 'InstrumentStarCameraMultiply', 'key': 'InstrumentStarCameraMultiply', 'description': 'This program applies several rotations given by   This program applies several rotations given by  . The resulting rotation is written as   This program applies several rotations given by  . All instrument files must be synchronized ( InstrumentSynchronize ).', 'config_table': 'outputfileStarCamera filename  instrument sequence  inputfileStarCamera filename  inverse boolean', 'display_text': 'This program applies several rotations given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>. The resulting rotation is written as <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStarCamera</a>. All instrument files must be synchronized (<a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).'},\n'InstrumentStatisticsTimeSeries': { 'name': 'InstrumentStatisticsTimeSeries', 'key': 'InstrumentStatisticsTimeSeries', 'description': 'This program computes a time series of statistics for one or more instrument files. Possible statistics are root mean square, standard deviation, mean, median, min, and max. The columns of the output time series are defined either as one per   This program computes a time series of statistics for one or more instrument files. Possible statistics are root mean square, standard deviation, mean, median, min, and max. The columns of the output time series are defined either as one per   or, if  perColumn  is true, statistics are computed per column for each file. Providing e.g. 32 orbit files of GPS satellites results in a time series matrix with columns: mjd, statisticsG01, statisticsG02, ..., statisticsG32. If  intervals  are provided, the input data is split into these intervals and one statistic is computed per interval. Otherwise, overall statistics are computed. The instrument data considered for computation of the component-wise statistics can be set with  startDataFields  and  countDataFields . The  factor  can be set to e.g. sqrt(3) to get 3D instead of 1D RMS values. See also  InstrumentArcStatistics ,  InstrumentArcCrossStatistics .', 'config_table': 'outputfileStatisticsTimeSeries filename columns: mjd, statistics column(s) per instrument file inputfileInstrument filename  statistics choice  rootMeanSquare   standardDeviation   mean   median   sum   min   max   epochCount   startDataFields uint start countDataFields uint number of data fields (default: all) perColumn boolean compute statistic per column ignoreNan boolean ignore NaN values in statistic computation intervals timeSeriesType intervals for statistics computation (one statistic per interval) factor double e.g. sqrt(3) for 3D RMS', 'display_text': 'This program computes a time series of statistics for one or more instrument files. Possible statistics are root mean square, standard deviation, mean, median, min, and max. The columns of the output time series are defined either as one per <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> or, if <strong class=\"groops-config-element\">perColumn</strong> is true, statistics are computed per column for each file. Providing e.g. 32 orbit files of GPS satellites results in a time series matrix with columns: mjd, statisticsG01, statisticsG02, ..., statisticsG32. If <strong class=\"groops-config-element\">intervals</strong> are provided, the input data is split into these intervals and one statistic is computed per interval. Otherwise, overall statistics are computed. The instrument data considered for computation of the component-wise statistics can be set with <strong class=\"groops-config-element\">startDataFields</strong> and <strong class=\"groops-config-element\">countDataFields</strong>. The <strong class=\"groops-config-element\">factor</strong> can be set to e.g. sqrt(3) to get 3D instead of 1D RMS values.</p><p>See also <a class=\"groops-program\" href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a>, <a class=\"groops-program\" href=\"InstrumentArcCrossStatistics.html\">InstrumentArcCrossStatistics</a>.'},\n'InstrumentSynchronize': { 'name': 'InstrumentSynchronize', 'key': 'InstrumentSynchronize', 'description': 'This program reads several  instrument files  and synchronize the data. Every epoch with some missing data will be deleted so the remaining epochs have data from every instrument. In a second step the epochs are divided into arcs with maximal epochs (or  maxArcLen ) without having a gap inside an arc. A Gap is defined by a time step with at least  minGap  seconds between consecutive epochs or if not set the 1.5 of the median sampling. Arc with an epoch count less than  minArcLen  will be rejected. A specific region can be selected with   This program reads several  . In this case one of the instrument data must be an orbit. If   This program reads several   is given the data are also divided into time bins. The assignment of arcs to the bins can be saved in   This program reads several  . This file can be used for the variational equation approach or  KalmanBuildNormals . Instrument files from  irregularData  are not synchronized but divided into the same number of arcs within the same time intervals. Data outside the defined arcs will be deleted.', 'config_table': 'data sequence  outputfileInstrument filename  inputfileInstrument filename  margin double margin for identical times [seconds] minGap double minimal time to define a gap and to begin a new arc, 0: no dividing [seconds], if not set 1.5*median sampling is used minArcLength uint minimal number of epochs of an arc maxArcLength uint maximal number of epochs of an arc arcType choice all arcs or only ascending or descending arcs are selected ascending   descending   border borderType only data in a specific region is selected timeIntervals timeSeriesType divide data into time bins outputfileArcList filename arc and time bin mapping irregularData sequence instrument files with irregular sampling outputfileInstrument filename  inputfileInstrument filename  minArcLength uint minimal number of epochs in an arc', 'display_text': 'This program reads several <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument files</a> and synchronize the data. Every epoch with some missing data will be deleted so the remaining epochs have data from every instrument.</p><p>In a second step the epochs are divided into arcs with maximal epochs (or <strong class=\"groops-config-element\">maxArcLen</strong>) without having a gap inside an arc. A Gap is defined by a time step with at least <strong class=\"groops-config-element\">minGap</strong> seconds between consecutive epochs or if not set the 1.5 of the median sampling. Arc with an epoch count less than <strong class=\"groops-config-element\">minArcLen</strong> will be rejected.</p><p>A specific region can be selected with <a class=\"groops-class\" href=\"borderType.html\">border</a>. In this case one of the instrument data must be an orbit.</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeIntervals</a> is given the data are also divided into time bins. The assignment of arcs to the bins can be saved in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">outputfileArcList</a>. This file can be used for the variational equation approach or <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>.</p><p>Instrument files from <strong class=\"groops-config-element\">irregularData</strong> are not synchronized but divided into the same number of arcs within the same time intervals. Data outside the defined arcs will be deleted.'},\n'InstrumentWaveletDecomposition': { 'name': 'InstrumentWaveletDecomposition', 'key': 'InstrumentWaveletDecomposition', 'description': 'This program performs a multilevel one-dimensional wavelet analysis on one  selectDataField  data column of   This program performs a multilevel one-dimensional wavelet analysis on one  . The   This program performs a multilevel one-dimensional wavelet analysis on one   contains the decomposed levels in time domain', 'config_table': 'outputfileInstrument filename MISCVALUES, decomposed levels in time domain a_J,d_J,...,d_1 inputfileInstrument filename  selectDataField uint select a data column for decomposition inputfileWavelet filename wavelet coefficients level uint level of decomposition', 'display_text': 'This program performs a multilevel one-dimensional wavelet analysis on one <strong class=\"groops-config-element\">selectDataField</strong> data column of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a>. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> contains the decomposed levels in time domain ${a_J,d_J,...,d_1}$'},\n'LocalLevelFrame2StarCamera': { 'name': 'LocalLevelFrame2StarCamera', 'key': 'LocalLevelFrame2StarCamera', 'description': 'Compute rotation ( StarCamera file ) from local level frame (ellipsoidal north, east, down) to TRF for positions given in   Compute rotation (  (first 3 data columns).', 'config_table': 'outputfileStarCamera filename rotation matrix from local level frame (ellipsoidal north, east, down) to TRF inputfileInstrument filename origin of local level frame constantOriginPerArc boolean use constant origin for all epochs of an arc (median position) R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates, 0: spherical coordinates', 'display_text': 'Compute rotation (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">StarCamera file</a>) from local level frame (ellipsoidal north, east, down) to TRF for positions given in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> (first 3 data columns).'},\n'KalmanBuildNormals': { 'name': 'KalmanBuildNormals', 'key': 'KalmanBuildNormals', 'description': 'This program sets up normal equations based on   This program sets up normal equations based on   for short-term gravity field variations. It computes the normal equations based on the intervals   given in the   This program sets up normal equations based on  . It sets up the least squares adjustment  and subsequently computes the normal equations   for each interval. If  eliminateNonGravityParameters  is true, all non-gravity parameters are eliminated before the normals are written to   This program sets up normal equations based on  . For each time interval in  arcList  a single  normal equation file  is written. This program computes the input normals for  KalmanFilter  and  KalmanSmootherLeastSquares .', 'config_table': 'outputfileNormalEquation filename outputfile for normal equations observation observationType  inputfileArcList filename list to correspond points of time to arc numbers eliminateNonGravityParameters boolean eliminate additional parameters from normals, 0: all parameter are saved', 'display_text': 'This program sets up normal equations based on <a class=\"groops-class\" href=\"observationType.html\">observation</a> for short-term gravity field variations. It computes the normal equations based on the intervals $i \\\\in \\\\{1, ..., N\\\\}$ given in the <a class=\"groops-class\" href=\"fileFormat_arcList.html\">arcList</a>. It sets up the least squares adjustment \\\\[     \\\\begin{bmatrix}     \\\\mathbf{l}_1 \\\\\\\\     \\\\mathbf{l}_2 \\\\\\\\     \\\\vdots \\\\\\\\     \\\\mathbf{l}_N \\\\\\\\   \\\\end{bmatrix}   =   \\\\begin{bmatrix}     \\\\mathbf{A}_1  &  & & \\\\\\\\     & \\\\mathbf{A}_2  & &\\\\\\\\     &  & \\\\ddots & \\\\\\\\     & & & \\\\mathbf{A}_N \\\\\\\\   \\\\end{bmatrix}   \\\\begin{bmatrix}     \\\\mathbf{x}^{(1)} \\\\\\\\     \\\\mathbf{x}^{(2)} \\\\\\\\     \\\\vdots \\\\\\\\     \\\\mathbf{x}^{(N)} \\\\\\\\   \\\\end{bmatrix}   +   \\\\begin{bmatrix}     \\\\mathbf{e}_1 \\\\\\\\     \\\\mathbf{e}_2 \\\\\\\\     \\\\vdots \\\\\\\\     \\\\mathbf{e}_N \\\\\\\\   \\\\end{bmatrix}, \\\\]and subsequently computes the normal equations $\\\\mathbf{N}_i, \\\\mathbf{n}_i$ for each interval. If <strong class=\"groops-config-element\">eliminateNonGravityParameters</strong> is true, all non-gravity parameters are eliminated before the normals are written to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a>. For each time interval in <strong class=\"groops-config-element\">arcList</strong> a single <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equation file</a> is written.</p><p>This program computes the input normals for <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> and <a class=\"groops-program\" href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a>.'},\n'KalmanFilter': { 'name': 'KalmanFilter', 'key': 'KalmanFilter', 'description': 'The program computes time variable gravity fields using the Kalman filter approach of Kurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012). Improved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.  https://doi.org/10.1016/j.jog.2012.02.006 . The updated state   is determined by solving the least squares adjustment  In normal equation form this can be written as  where   and   are the predicted state and its covariance matrix. The process dynamic   is represented as an  autoregressive model , and passed to the program through   The program computes time variable gravity fields using the Kalman filter approach of . The sequence of normal equations   are given as list of   The program computes time variable gravity fields using the Kalman filter approach of , which can be generated using   The program computes time variable gravity fields using the Kalman filter approach of . In the same way, the  matrix files  for  outputfileUpdatedState  and  inputfileUpdatedStateCovariance  can also be specified using   The program computes time variable gravity fields using the Kalman filter approach of . If no   The program computes time variable gravity fields using the Kalman filter approach of  is set, a zero vector with appropriate dimensions is used. The   The program computes time variable gravity fields using the Kalman filter approach of  however must be given. See also  KalmanBuildNormals ,  KalmanSmoother .', 'config_table': 'outputfileUpdatedState filename estimated state x+ (nx1-matrix) outputfileUpdatedStateCovarianceMatrix filename estimated state\\' s covariance matrix Cov(x+) inputfileNormalEquations filename normal equations input file inputfileInitialState filename initial state x0 inputfileInitialStateCovarianceMatrix filename initial state\\'s covariance matrix Cov(x0) inputfileAutoregressiveModel filename file name of autoregressive model', 'display_text': 'The program computes time variable gravity fields using the Kalman filter approach of</p><p>Kurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012). Improved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48. <a href=\"https://doi.org/10.1016/j.jog.2012.02.006\" target=\"_blank\">https://doi.org/10.1016/j.jog.2012.02.006</a>.</p><p>The updated state $\\\\mathbf{x}_t^+$ is determined by solving the least squares adjustment \\\\[ \\\\mathbf{l}_t = \\\\mathbf{A}_t \\\\mathbf{x}_t + \\\\mathbf{e}_t \\\\hspace{25pt} \\\\mathbf{e}_t \\\\sim \\\\mathcal{N}(0, \\\\mathbf{R}_t)\\\\\\\\ \\\\mathbf{B} \\\\mathbf{x}^+_{t-1} = \\\\mathbf{I} \\\\mathbf{x}_t + \\\\mathbf{v}_t\\\\hspace{25pt} \\\\mathbf{v} \\\\sim \\\\mathcal{N}(0,\\\\mathbf{Q} + \\\\mathbf{B} \\\\mathbf{P}^+_{t-1}\\\\mathbf{B}^T). \\\\]In normal equation form this can be written as \\\\[ \\\\hat{\\\\mathbf{x}}_t = \\\\mathbf{x}^+_t = (\\\\mathbf{N}_t + \\\\mathbf{P}^{-^{-1}}_t)^{-1}(\\\\mathbf{n}_t + \\\\mathbf{P}^{-^{-1}}_t \\\\mathbf{x}^-_t), \\\\]where $\\\\mathbf{x}_t^- = \\\\mathbf{B} \\\\mathbf{x}^+_{t-1}$ and $\\\\mathbf{P}_t^{-} = \\\\mathbf{Q} + \\\\mathbf{B} \\\\mathbf{P}^+_{t-1}\\\\mathbf{B}^T$ are the predicted state and its covariance matrix.</p><p>The process dynamic $\\\\mathbf{B}, \\\\mathbf{Q}$ is represented as an <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">autoregressive model</a>, and passed to the program through <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileAutoregressiveModel</a>. The sequence of normal equations $\\\\mathbf{N}_t, \\\\mathbf{n}_t$ are given as list of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquations</a>, which can be generated using <a class=\"groops-class\" href=\"loopType.html\">loops</a>. In the same way, the <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix files</a> for <strong class=\"groops-config-element\">outputfileUpdatedState</strong> and <strong class=\"groops-config-element\">inputfileUpdatedStateCovariance</strong> can also be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.</p><p>If no <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileInitialState</a> is set, a zero vector with appropriate dimensions is used. The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileInitialStateCovarianceMatrix</a> however must be given.</p><p>See also <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>, <a class=\"groops-program\" href=\"KalmanSmoother.html\">KalmanSmoother</a>.'},\n'KalmanSmoother': { 'name': 'KalmanSmoother', 'key': 'KalmanSmoother', 'description': 'Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by  KalmanFilter . This is the implementation of the approach presented in Kurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012). Improved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.  https://doi.org/10.1016/j.jog.2012.02.006 . The result has zero phase and the squared magnitude response of   Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by   (see  autoregressiveModel  for details).   Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by   and   Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by   are the output of a  KalmanFilter  forward sweep. The matrix files for  Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by  ,   Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by   and   Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by   can also be specified using   Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by  . See also  KalmanBuildNormals ,  KalmanFilter  and  KalmanSmootherLeastSquares .', 'config_table': 'outputfileState filename estimated parameters (nx1-matrix) outputfileStateCovarianceMatrix filename estimated parameters\\' covariance matrix inputfileUpdatedState filename  inputfileUpdatedStateCovarianceMatrix filename  inputfileAutoregressiveModel filename file name of autoregressive model', 'display_text': 'Apply the Rauch-Tung-Striebel smoother to a gravity field time series computed by <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a>. This is the implementation of the approach presented in</p><p>Kurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012). Improved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48. <a href=\"https://doi.org/10.1016/j.jog.2012.02.006\" target=\"_blank\">https://doi.org/10.1016/j.jog.2012.02.006</a>.</p><p>The result has zero phase and the squared magnitude response of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileAutoregressiveModel</a> (see <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">autoregressiveModel</a> for details). <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedState</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedStateCovariance</a> are the output of a <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> forward sweep. The matrix files for<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileUpdatedState</a>, <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedState</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileUpdatedStateCovariance</a> can also be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.</p><p>See also <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>, <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> and <a class=\"groops-program\" href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a>.'},\n'KalmanSmootherLeastSquares': { 'name': 'KalmanSmootherLeastSquares', 'key': 'KalmanSmootherLeastSquares', 'description': 'This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a   This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a   which represent a stationary random process (see the  autoregressive model description ) for details. The output files for the estimated gravity field (  This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a  ), the corresponding standard deviations (  This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a  ) and the full covariance matrix (  This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a  ) can be specified using   This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a  . Similarly, the   This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a   can also be specified using   This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a  . See also  KalmanBuildNormals ,  KalmanFilter  and KalmanSmoother', 'config_table': 'outputfileSolution filename file name of solution vector (use time tags) outputfileSigmax filename file name of sigma vector (use time tags) outputfileCovariance filename file name of full covariance matrix (use time tags) inputfileNormalEquations filename input normal equations (loopTime will be expanded) autoregressiveModelSequence autoregressiveModelSequenceType file containing AR model for spatiotemporal constraint', 'display_text': 'This program estimates temporal gravity field variations with a constraint least squares adjustment. Prior information is introduced by means of a <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a> which represent a stationary random process (see the <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">autoregressive model description</a>) for details.</p><p>The output files for the estimated gravity field (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>), the corresponding standard deviations (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>) and the full covariance matrix (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovariance</a>) can be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>. Similarly, the <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquations</a> can also be specified using <a class=\"groops-class\" href=\"loopType.html\">loops</a>.</p><p>See also <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>, <a class=\"groops-program\" href=\"KalmanFilter.html\">KalmanFilter</a> and<a class=\"groops-program\" href=\"KalmanSmoother.html\">KalmanSmoother</a>'},\n'DigitalFilter2FrequencyResponse': { 'name': 'DigitalFilter2FrequencyResponse', 'key': 'DigitalFilter2FrequencyResponse', 'description': 'Compute amplitude-, phase-, group delay and frequency response of a   Compute amplitude-, phase-, group delay and frequency response of a   cascade. The   Compute amplitude-, phase-, group delay and frequency response of a   is a matrix with following columns: freq  , ampl, phase  , group delay  , real, imag. When  unwrapPhase  is set to true,   jumps of the phase response are removed before writing the output to file. The response of the filter cascade is given by the product of each individual frequency response:  Amplitude and phase response are computed from the frequency response via  The group delay is computed by numerically differentiating the phase response  The frequency vector for a  length    and a  sampling    is given by   See also  DigitalFilter2ImpulseResponse .', 'config_table': 'outputfileResponse filename columns: freq [Hz], ampl, phase [rad], group delay [-], real, imag digitalFilter digitalFilterType  length uint length of the data series in time domain sampling double sampling to determine frequency [seconds] skipZeroFrequency boolean omit zero frequency when writing to file unwrapPhase boolean unwrap phase response', 'display_text': 'Compute amplitude-, phase-, group delay and frequency response of a <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> cascade. The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileResponse</a> is a matrix with following columns: freq $[Hz]$, ampl, phase $[rad]$, group delay $[-]$, real, imag.</p><p>When <strong class=\"groops-config-element\">unwrapPhase</strong> is set to true, $2\\\\pi$ jumps of the phase response are removed before writing the output to file.</p><p>The response of the filter cascade is given by the product of each individual frequency response: \\\\[   H(f) = \\\\prod_f H_j(f). \\\\]Amplitude and phase response are computed from the frequency response via \\\\[   A(f) = |H(f)| \\\\hspace{5pt}\\\\text{and}\\\\hspace{5pt} \\\\Phi(f) = \\\\arctan \\\\frac{\\\\mathcal{I}(H(f))}{\\\\mathcal{R}(H(f))}. \\\\]The group delay is computed by numerically differentiating the phase response \\\\[   \\\\tau_g(f_k) = \\\\frac{1}{2} \\\\left[\\\\frac{\\\\Phi(f_k) - \\\\Phi(f_{k-1})}{2\\\\pi(f_k-f_{k-1})} + \\\\frac{\\\\Phi(f_{k+1}) - \\\\Phi(f_{k})}{2\\\\pi(f_{k+1}-f_{k})}\\\\right] \\\\approx \\\\frac{d\\\\Phi}{df}\\\\frac{df}{d\\\\omega}. \\\\]The frequency vector for a <strong class=\"groops-config-element\">length</strong> $N$ and a <strong class=\"groops-config-element\">sampling</strong> $\\\\Delta t$ is given by \\\\[   f_k = \\\\frac{k}{N \\\\Delta t}, \\\\hspace{15pt} k \\\\in \\\\{0, \\\\dots, \\\\left\\\\lfloor\\\\frac{N+2}{2}\\\\right\\\\rfloor-1\\\\}. \\\\] See also <a class=\"groops-program\" href=\"DigitalFilter2ImpulseResponse.html\">DigitalFilter2ImpulseResponse</a>.'},\n'DigitalFilter2ImpulseResponse': { 'name': 'DigitalFilter2ImpulseResponse', 'key': 'DigitalFilter2ImpulseResponse', 'description': 'Impulse response of a   Impulse response of a   cascade. The impulse response is computed by filtering a sequence with  length  samples and a unit impulse at index  pulseLag . The   Impulse response of a   is a matrix with the time stamp (zero at  pulseLag ) in the first column and the impulse response   in the second column. See also  DigitalFilter2FrequencyResponse .', 'config_table': 'outputfileResponse filename columns: time [seconds], response digitalFilter digitalFilterType  length uint length of the impulse response pulseLag uint start of the pulse in the data series sampling double [seconds]', 'display_text': 'Impulse response of a <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> cascade. The impulse response is computed by filtering a sequence with <strong class=\"groops-config-element\">length</strong> samples and a unit impulse at index <strong class=\"groops-config-element\">pulseLag</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileResponse</a> is a matrix with the time stamp (zero at <strong class=\"groops-config-element\">pulseLag</strong>) in the first column and the impulse response $h_k$ in the second column.</p><p>See also <a class=\"groops-program\" href=\"DigitalFilter2FrequencyResponse.html\">DigitalFilter2FrequencyResponse</a>.'},\n'EarthOrientationParameterTimeSeries': { 'name': 'EarthOrientationParameterTimeSeries', 'key': 'EarthOrientationParameterTimeSeries', 'description': 'Computes a   Computes a   (GPS time) of Earth Orientation Parameter (EOP). The  instrument file  (MISCVALUES) contains the elements at each epoch in the following order:     [rad]   [rad]   [rad]   [seconds]  length of day (LOD) [seconds]   [rad]   [rad]   [rad]   The values are in situ values with all corrections and models applied. The time series can be used to precompute Earth rotation with a low temporal resolution (e.g. 10 min) and reuse the file in   Computes a   to interpolate the data to the needed epochs (e.g. to rotate orbit data). As some Earth rotation models are quite slow this can accelerate the computation.', 'config_table': 'outputfileEOP filename each row: mjd(GPS), xp, yp, sp, dUT1, LOD, X, Y, S earthRotation earthRotationType  timeSeries timeSeriesType', 'display_text': 'Computes a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> (GPS time) of Earth Orientation Parameter (EOP). The <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) contains the elements at each epoch in the following order: <ul>  <li>$x_p$ [rad] </li><li> $y_p$ [rad] </li><li> $s_p$ [rad] </li><li> $UT1-UTC$ [seconds] </li><li> length of day (LOD) [seconds] </li><li> $X$ [rad] </li><li> $Y$ [rad] </li><li> $S$ [rad] </li></ul>  The values are in situ values with all corrections and models applied. The time series can be used to precompute Earth rotation with a low temporal resolution (e.g. 10 min) and reuse the file in <a class=\"groops-class\" href=\"earthRotationType.html#file\">earthRotation:file</a> to interpolate the data to the needed epochs (e.g. to rotate orbit data). As some Earth rotation models are quite slow this can accelerate the computation.'},\n'EarthRotaryVectorTimeSeries': { 'name': 'EarthRotaryVectorTimeSeries', 'key': 'EarthRotaryVectorTimeSeries', 'description': 'Computes a   Computes a   of Earth\\'s rotary axis and its temporal derivative at   Computes a   (GPS time). The  instrument file  (MISCVALUES) contains the elements at each epoch in the following order:              .', 'config_table': 'outputfileTimeSeries filename wx, wy, wz [rad], dwx, dwy, dwz [rad/s^2] earthRotation earthRotationType  timeSeries timeSeriesType  inTRF boolean terrestrial reference frame, otherwise celestial', 'display_text': 'Computes a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> of Earth\\'s rotary axis and its temporal derivative at <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> (GPS time). The <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) contains the elements at each epoch in the following order: <ul>  <li>$\\\\omega_x [rad/s]$ </li><li> $\\\\omega_y [rad/s]$ </li><li> $\\\\omega_z [rad/s]$ </li><li> $\\\\dot{\\\\omega}_x [rad/s^2]$ </li><li> $\\\\dot{\\\\omega}_y [rad/s^2]$ </li><li> $\\\\dot{\\\\omega}_z [rad/s^2]$. </li></ul>'},\n'EclipseFactor2GriddedData': { 'name': 'EclipseFactor2GriddedData', 'key': 'EclipseFactor2GriddedData', 'description': 'This program converts the output of a   This program converts the output of a   model on a given   This program converts the output of a  . The time for the evaluation can be specified in  time . The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening .', 'config_table': 'outputfileGriddedData filename eclipse factor grid gridType  eclipse eclipseType  ephemerides ephemeridesType  earthRotation earthRotationType  time time  R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program converts the output of a <a class=\"groops-class\" href=\"eclipseType.html\">eclipse</a> model on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>. The time for the evaluation can be specified in <strong class=\"groops-config-element\">time</strong>. The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.'},\n'FilterMatrixWindowedPotentialCoefficients': { 'name': 'FilterMatrixWindowedPotentialCoefficients', 'key': 'FilterMatrixWindowedPotentialCoefficients', 'description': 'Create a spherical harmonic window matrix. The window matrix   is generated in space domain through spherical harmonic synthesis and analysis matrices. The resulting linear operator can be written as  Here,   is a diagonal matrix with the   Create a spherical harmonic window matrix. The window matrix   coefficients on the main diagonal,   is the spherical harmonic synthesis matrix,   is defined by the values in  inputfileGriddedData  and the expression  value ,   is the spherical harmonic analysis matrix. The resulting window matrix is written to a  matrix  file. The spherical harmonic degree range, and coefficient numbering are defined by  minDegree ,  maxDegree , and   Create a spherical harmonic window matrix. The window matrix  . Note that a proper window function   should contain values in the range [0, 1]. The window function   can feature a smooth transition between 0 and 1 to avoid ringing effects.', 'config_table': 'outputfileWindowMatrix filename  inputfileGriddedData filename gridded data which defines the window function in space domain value expression expression to compute the window function (input columns are named data0, data1, ...) kernel kernelType kernel for windowing minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme for solution vector', 'display_text': 'Create a spherical harmonic window matrix. The window matrix $\\\\mathbf{W}$ is generated in space domain through spherical harmonic synthesis and analysis matrices. The resulting linear operator can be written as \\\\[ \\\\mathbf{W} = \\\\mathbf{K} \\\\mathbf{A} \\\\mathbf{\\\\Omega} \\\\mathbf{S} \\\\mathbf{K}^{-1}. \\\\]Here, $\\\\mathbf{K}$ is a diagonal matrix with the <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> coefficients on the main diagonal, $\\\\mathbf{S}$ is the spherical harmonic synthesis matrix, $\\\\mathbf{\\\\Omega}$ is defined by the values in <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> and the expression <strong class=\"groops-config-element\">value</strong>, $\\\\mathbf{A}$ is the spherical harmonic analysis matrix. The resulting window matrix is written to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file.</p><p>The spherical harmonic degree range, and coefficient numbering are defined by <strong class=\"groops-config-element\">minDegree</strong>, <strong class=\"groops-config-element\">maxDegree</strong>, and <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.</p><p>Note that a proper window function $\\\\mathbf{\\\\Omega}$ should contain values in the range [0, 1]. The window function $\\\\mathbf{\\\\Omega}$ can feature a smooth transition between 0 and 1 to avoid ringing effects.'},\n'FunctionsCalculate': { 'name': 'FunctionsCalculate', 'key': 'FunctionsCalculate', 'description': 'This program manipulates  matrix files  with data in columns. If several  inputfile s are given the data columns are copied side by side. All  inputfile s must contain the same number of rows. The columns are enumerated by  data0 ,  data1 ,  . The content of   This program manipulates   is controlled by  outColumn . The algorithm to compute the output is as follows: The expressions in  outColumn  are evaluated once for each row of the input. The variables  data0 ,  data1 ,  are replaced by the according values from the input columns before. Additional variables are available, e.g.  index ,  data0rms , see  dataVariables . If no  outColumn  are specified all input columns are used instead directly. For a simplified handling  constant s can be defined by  name=value , e.g.  annual=365.25 . It is also possible to estimate  parameter s in a least squares adjustment. The  leastSquares  serves as template for observation equations for every row. The expression  leastSquares  is evaluated for each row in the  inputfile . The variables  data0 ,  data1 ,  are replaced by the according values from the input columns before. In the next step the parameters are estimated in order to minimize the expressions in  leastSquares  in the sense of least squares. Afterwards complete rows are removed if one of the  removalCriteria  expressions for this row evaluates true (not zero). An extra  statistics  file can be generated with one row of data. For the computation of the  outColumn  values all  dataVariables  are available (e.g.  data3mean ,  data4std ) inclusively the  constant s and estimated  parameter s but without the  data0 ,  data1 ,  itself. The variables and the numbering of the columns refers to the   This program manipulates  . First example: To calculate the mean of two values at each row set  outColumn  to  0.5*(data1+data0) . Second example: An input file contain a column with times and a column with values. To remove a trend from the values define the  parameter s  trend  and  bias . The observation equation in  leastSquares  is  data1 - (trend*data0+bias) . For output you can define the following columns for example:    outColumn = data0 : points in time.  outColumn = data1 : the values itself.  outColumn = trend*data0+bias : the linear fit.  outColumn = data1-trend*data0-bias : the residuals.   The extra statistics file could contain in this case:    outColumn = data0max-data0min : time span.  outColumn = bias : estimated parameter.  outColumn = trend : estimated parameter.  outColumn = data3rms : root mean square of the residuals.  See also  InstrumentArcCalculate ,  GriddedDataCalculate ,  MatrixCalculate .', 'config_table': 'outputfile filename  inputfile filename  constant expression define a constant by name=value parameter expression define a parameter by name[=value] leastSquares expression try to minimize the expression by adjustment of the parameters removalCriteria expression row is removed if one criterion evaluates true. outColumn expression expression to compute output columns (input columns are named data0, data1, ...) statistics sequence  outputfile filename matrix with one row, columns are user defined outColumn expression expression to compute statistics columns, data* are the outputColumns', 'display_text': 'This program manipulates <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix files</a> with data in columns. If several <strong class=\"groops-config-element\">inputfile</strong>s are given the data columns are copied side by side. All <strong class=\"groops-config-element\">inputfile</strong>s must contain the same number of rows. The columns are enumerated by <code>data0</code>, <code>data1</code>, .</p><p>The content of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfile</a> is controlled by <strong class=\"groops-config-element\">outColumn</strong>. The algorithm to compute the output is as follows: The expressions in <strong class=\"groops-config-element\">outColumn</strong> are evaluated once for each row of the input. The variables <code>data0</code>, <code>data1</code>, are replaced by the according values from the input columns before. Additional variables are available, e.g. <code>index</code>, <code>data0rms</code>, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>. If no <strong class=\"groops-config-element\">outColumn</strong> are specified all input columns are used instead directly.</p><p>For a simplified handling <strong class=\"groops-config-element\">constant</strong>s can be defined by <code>name=value</code>, e.g. <code>annual=365.25</code>. It is also possible to estimate <strong class=\"groops-config-element\">parameter</strong>s in a least squares adjustment. The <strong class=\"groops-config-element\">leastSquares</strong> serves as template for observation equations for every row. The expression <strong class=\"groops-config-element\">leastSquares</strong> is evaluated for each row in the <strong class=\"groops-config-element\">inputfile</strong>. The variables <code>data0</code>, <code>data1</code>, are replaced by the according values from the input columns before. In the next step the parameters are estimated in order to minimize the expressions in <strong class=\"groops-config-element\">leastSquares</strong> in the sense of least squares.</p><p>Afterwards complete rows are removed if one of the <strong class=\"groops-config-element\">removalCriteria</strong> expressions for this row evaluates true (not zero).</p><p>An extra <strong class=\"groops-config-element\">statistics</strong> file can be generated with one row of data. For the computation of the <strong class=\"groops-config-element\">outColumn</strong> values all <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available (e.g. <code>data3mean</code>, <code>data4std</code>) inclusively the <strong class=\"groops-config-element\">constant</strong>s and estimated <strong class=\"groops-config-element\">parameter</strong>s but without the <code>data0</code>, <code>data1</code>, itself. The variables and the numbering of the columns refers to the <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfile</a>.</p><p>First example: To calculate the mean of two values at each row set <strong class=\"groops-config-element\">outColumn</strong> to <code>0.5*(data1+data0)</code>.</p><p>Second example: An input file contain a column with times and a column with values. To remove a trend from the values define the <strong class=\"groops-config-element\">parameter</strong>s <code>trend</code> and <code>bias</code>. The observation equation in <strong class=\"groops-config-element\">leastSquares</strong> is <code>data1 - (trend*data0+bias)</code>. For output you can define the following columns for example: <ul>  <li><strong class=\"groops-config-element\">outColumn</strong>=<code>data0</code>: points in time. </li><li> <strong class=\"groops-config-element\">outColumn</strong>=<code>data1</code>: the values itself. </li><li> <strong class=\"groops-config-element\">outColumn</strong>=<code>trend*data0+bias</code>: the linear fit. </li><li> <strong class=\"groops-config-element\">outColumn</strong>=<code>data1-trend*data0-bias</code>: the residuals. </li></ul>  The extra statistics file could contain in this case: <ul>  <li><strong class=\"groops-config-element\">outColumn</strong>=<code>data0max-data0min</code>: time span. </li><li> <strong class=\"groops-config-element\">outColumn</strong>=<code>bias</code>: estimated parameter. </li><li> <strong class=\"groops-config-element\">outColumn</strong>=<code>trend</code>: estimated parameter. </li><li> <strong class=\"groops-config-element\">outColumn</strong>=<code>data3rms</code>: root mean square of the residuals. </li></ul> </p><p>See also <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>, <a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>, <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.'},\n'Grs2PotentialCoefficients': { 'name': 'Grs2PotentialCoefficients', 'key': 'Grs2PotentialCoefficients', 'description': 'This program creates potential coefficients from the defining constants of a Geodetic Reference System (GRS). The potential coeffiencts excludes the centrifugal part. The form of the reference ellipsoid is either determined by the dynamical form factor  J2 , or the geometric  inverseFlattening . One of those form parameters must be specified. The default values create the GRS80.', 'config_table': 'outputfilePotentialCoefficients filename  maxDegree uint  GM double Geocentric gravitational constant R double reference radius omega double Angular velocity of rotation J2 double Dynamical form factor inverseFlattening double Geometric inverse flattening of reference ellipsoid (0: sphere, ignored when J2 is set)', 'display_text': 'This program creates potential coefficients from the defining constants of a Geodetic Reference System (GRS). The potential coeffiencts excludes the centrifugal part. The form of the reference ellipsoid is either determined by the dynamical form factor <strong class=\"groops-config-element\">J2</strong>, or the geometric <strong class=\"groops-config-element\">inverseFlattening</strong>. One of those form parameters must be specified.</p><p>The default values create the GRS80.'},\n'Kaula2SigmaPotentialCoefficients': { 'name': 'Kaula2SigmaPotentialCoefficients', 'key': 'Kaula2SigmaPotentialCoefficients', 'description': 'Create signal standard deviations of potential coefficients according Kaula\\'s rule of thumb  with the degree  , the  factor   , and the  power   . The standard deviations are written as formal errors of    Create signal standard deviations of potential coefficients according Kaula\\'s rule of thumb  .', 'config_table': 'outputfilePotentialCoefficients filename  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius power double sigma = factor/degree^power factor double sigma = factor/degree^power', 'display_text': 'Create signal standard deviations of potential coefficients according Kaula\\'s rule of thumb \\\\[   \\\\sigma_n = \\\\frac{f}{n^p}, \\\\]with the degree $n$, the <strong class=\"groops-config-element\">factor</strong> $f$, and the <strong class=\"groops-config-element\">power</strong> $p$.</p><p>The standard deviations are written as formal errors of  <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>.'},\n'Kernel2Coefficients': { 'name': 'Kernel2Coefficients', 'key': 'Kernel2Coefficients', 'description': 'This program computes and returns the coefficients and inverse coefficients of a   This program computes and returns the coefficients and inverse coefficients of a   from from  minDegree  to  maxDegree  at a given  height . The main purpose is for visualization with  PlotGraph .', 'config_table': 'outputfileMatrix filename matrix with columns degree, coefficients and inverse coefficients kernel kernelType  minDegree uint minimum degree of returned coefficients maxDegre uint compute coefficients up to maxDegree height double evaluate kernel at R+height [m] R double reference radius', 'display_text': 'This program computes and returns the coefficients and inverse coefficients of a <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> from from <strong class=\"groops-config-element\">minDegree</strong> to <strong class=\"groops-config-element\">maxDegree</strong> at a given <strong class=\"groops-config-element\">height</strong>.</p><p>The main purpose is for visualization with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.'},\n'Kernel2SigmaPotentialCoefficients': { 'name': 'Kernel2SigmaPotentialCoefficients', 'key': 'Kernel2SigmaPotentialCoefficients', 'description': 'Create variances of spherical harmonics by convolution a kernel with white noise, e.g. to display filter coefficients of a Gaussian filter. The coefficients are written as formal errors of   Create variances of spherical harmonics by convolution a kernel with white noise, e.g. to display filter coefficients of a Gaussian filter. The coefficients are written as formal errors of  .', 'config_table': 'outputfilePotentialCoefficients filename  kernel kernelType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius factor double', 'display_text': 'Create variances of spherical harmonics by convolution a kernel with white noise, e.g. to display filter coefficients of a Gaussian filter. The coefficients are written as formal errors of <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a>.'},\n'KernelEvaluate': { 'name': 'KernelEvaluate', 'key': 'KernelEvaluate', 'description': 'Compute   Compute   values for distant angles. The main purpose is for visualization with  PlotGraph .', 'config_table': 'outputfileMatrix filename matrix with first column the angle [degree], second the kernel value kernel kernelType  minAngle angle [degree] maxAngle angle [degree] sampling angle [degree] height double evaluate at R+height [m] R double reference radius', 'display_text': 'Compute <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> values for distant angles. The main purpose is for visualization with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.'},\n'MagneticField2GriddedData': { 'name': 'MagneticField2GriddedData', 'key': 'MagneticField2GriddedData', 'description': 'Computes x, y, z of the magentic field vector.', 'config_table': 'outputfileGriddedData filename x, y, z [Tesla = kg/A/s**2] magnetosphere magnetosphereType  grid gridType  time time  localReferenceFrame boolean local left handed reference frame (north, east, up) R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'Computes x, y, z of the magentic field vector.'},\n'MatrixCalculate': { 'name': 'MatrixCalculate', 'key': 'MatrixCalculate', 'description': 'This program creates a  matrix  from multiple matrices. All   This program creates a   are summed up. The size of the resulting matrix is exandeded to fit all matrices. The class   This program creates a   allows complex matrix operations before.', 'config_table': 'outputfileMatrix filename  matrix matrixGeneratorType', 'display_text': 'This program creates a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> from multiple matrices. All <a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrices</a> are summed up. The size of the resulting matrix is exandeded to fit all matrices. The class <a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrixGenerator</a> allows complex matrix operations before.'},\n'ObservationEquations2Files': { 'name': 'ObservationEquations2Files', 'key': 'ObservationEquations2Files', 'description': 'This program computes the linearized and decorrelated equation system for each arc  :  using class   This program computes the linearized and decorrelated equation system for each arc   and writes  ,   and   as  matrix  files.', 'config_table': 'outputfileObservationVector filename one file for each arc outputfileDesignMatrix filename one file for each arc, without arc related parameters outputfileDesignMatrixArc filename one file for each arc, arc related parameters variableArc string variable with arc number outputfileParameterNames filename without arc related parameters observation observationType', 'display_text': 'This program computes the linearized and decorrelated equation system for each arc $i$: \\\\[ \\\\M l_i  = \\\\M A_i \\\\M x + \\\\M B_i \\\\M y_i + \\\\M e_i \\\\]using class <a class=\"groops-class\" href=\"observationType.html\">observation</a> and writes $\\\\M A_i$, $\\\\M B_i$ and $\\\\M l_i$ as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> files.'},\n'PlatformCreate': { 'name': 'PlatformCreate', 'key': 'PlatformCreate', 'description': 'Create a  Platform file  from scratch by defining attributes such as  markerName ,  markerNumber ,  comment ,  approxPosition ,  equipment . See also  GnssAntex2AntennaDefinition  and  GnssStationLog2Platform .', 'config_table': 'outputfilePlatform filename  markerName string  markerNumber string  comment string  approxPositionX double [m] in TRF approxPositionY double [m] in TRF approxPositionZ double [m] in TRF equipment choice  gnssAntenna sequence  name string  serial string  radome string  comment string  timeStart time  timeEnd time  positionX double [m] ARP in north, east, up or vehicle system positionY double [m] ARP in north, east, up or vehicle system positionZ double [m] ARP in north, east, up or vehicle system rotationX angle [degree] from local/vehicle to left-handed antenna system rotationY angle [degree] from local/vehicle to left-handed antenna system rotationZ angle [degree] from local/vehicle to left-handed antenna system flipX boolean flip x-axis (after rotation) flipY boolean flip y-axis (after rotation) flipZ boolean flip z-axis (after rotation) gnssReceiver sequence  name string  serial string  version string  comment string  timeStart time  timeEnd time  laserRetroReflector sequence  name string e.g. GFZ, ITE, IPIE serial string  comment string  timeStart time  timeEnd time  positionX double [m] optial reference point RP in satellite system positionY double [m] optial reference point RP in satellite system positionZ double [m] optial reference point RP in satellite system rotationX angle [degree] from local/vehicle to LRR system rotationY angle [degree] from local/vehicle to LRR system rotationZ angle [degree] from local/vehicle to LRR system flipX boolean flip x-axis (after rotation) flipY boolean flip y-axis (after rotation) flipZ boolean flip z-axis (after rotation) range double [m] range bias (only without range matrix) inputfileRangeMatrix filename [m] (azimuth(0..360) x zenith(0..dZenit*rows) dZenit angle [degree] increment of range matrix geodeticSatellite sequence e.g. LAGEOS name string  serial string  comment string  timeStart time  timeEnd time  range double [m] standard center-of-mass correction slrStation sequence  name string CDP SOD 8-digit No. serial string IERS DOMES comment string  timeStart time  timeEnd time  positionX double [m] eccentricity in north positionY double [m] eccentricity in east positionZ double [m] eccentricity in up satelliteIdentifier sequence  name string  serial string  cospar string Satellite COSPAR ID norad string Satellite Catalog (NORAD) Number sic string SIC Code sp3 string SP3 comment string  timeStart time  timeEnd time  other sequence  name string  serial string  comment string  timeStart time  timeEnd time  positionX double [m] in north, east, up or vehicle system positionY double [m] in north, east, up or vehicle system positionZ double [m] in north, east, up or vehicle system referencePoint sequence e.g. center of mass in satellite frame comment string  xStart double [m] in north, east, up or vehicle system yStart double linear motion between start and end zStart double  xEnd double [m] in north, east, up or vehicle system yEnd double linear motion between start and end zEnd double  timeStart time  timeEnd time', 'display_text': 'Create a <a class=\"groops-file\" href=\"fileFormat_platform.html\">Platform file</a> from scratch by defining attributes such as <strong class=\"groops-config-element\">markerName</strong>, <strong class=\"groops-config-element\">markerNumber</strong>, <strong class=\"groops-config-element\">comment</strong>, <strong class=\"groops-config-element\">approxPosition</strong>, <strong class=\"groops-config-element\">equipment</strong>.</p><p>See also <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> and <a class=\"groops-program\" href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a>.</p><p>'},\n'PotentialCoefficients2BlockMeanTimeSplines': { 'name': 'PotentialCoefficients2BlockMeanTimeSplines', 'key': 'PotentialCoefficients2BlockMeanTimeSplines', 'description': 'This program is a simplified version of  Gravityfield2TimeSplines . It reads a series of potential coefficient files (  This program is a simplified version of  ) and creates a time splines file with spline degree 0 (temporal block means) or degree 1 (linear splines). The time intervals in which the potential coefficients are valid are defined between adjacent points in time given by  splineTimeSeries . Therefore one more point in time is needed than the number of potential coefficient files for degree 0. The coefficients can be filtered with   This program is a simplified version of  . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . This program is useful e.g. to combine monthly GRACE solutions to one file.', 'config_table': 'outputfileTimeSplines filename  outputfileTimeSplinesCovariance filename only the variances are saved inputfilePotentialCoefficients filename  filter sphericalHarmonicsFilterType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius removeMean boolean remove the temporal mean of the series before estimating the splines interpolate boolean interpolate missing files splineTimeSeries timeSeriesType input files must be between points in time splineDegree uint degree of splines', 'display_text': 'This program is a simplified version of <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>. It reads a series of potential coefficient files (<a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">inputfilePotentialCoefficients</a>) and creates a time splines file with spline degree 0 (temporal block means) or degree 1 (linear splines). The time intervals in which the potential coefficients are valid are defined between adjacent points in time given by <strong class=\"groops-config-element\">splineTimeSeries</strong>. Therefore one more point in time is needed than the number of potential coefficient files for degree 0.</p><p>The coefficients can be filtered with <a class=\"groops-class\" href=\"sphericalHarmonicsFilterType.html\">filter</a>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>This program is useful e.g. to combine monthly GRACE solutions to one file.'},\n'PotentialCoefficients2DegreeAmplitudes': { 'name': 'PotentialCoefficients2DegreeAmplitudes', 'key': 'PotentialCoefficients2DegreeAmplitudes', 'description': 'This program computes degree amplitudes from  potentialCoefficients files  and saves them to a  matrix  file. The coefficients can be filtered with   This program computes degree amplitudes from   and converted to different functionals with   This program computes degree amplitudes from  . The gravity field can be evaluated at different altitudes by specifying  evaluationRadius . Polar regions can be excluded by setting  polarGap . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The coefficients are related to the reference radius  R  and the Earth gravitational constant  GM . The   This program computes degree amplitudes from   contains in the first 3 columns the degree, the degree amplitude, and the formal errors. For each additional   This program computes degree amplitudes from   three columns are appended: the degree amplitude, the formal errors, and the difference to the first file. For example the data columns for 4   This program computes degree amplitudes from   are    degree= data0   PotentialCoefficients0: signal= data1 , error= data2 ,  PotentialCoefficients1: signal= data3 , error= data4 ,  difference= data5 ,  PotentialCoefficients2: signal= data6 , error= data7 ,  difference= data8 ,  PotentialCoefficients3: signal= data9 , error= data10 , difference= data11 .  See also  Gravityfield2DegreeAmplitudes .', 'config_table': 'outputfileMatrix filename matrix with degree, signal amplitude, formal error, differences inputfilePotentialCoefficients filename  kernel kernelType  filter sphericalHarmonicsFilterType filter the coefficients type choice type of variances rms  degree amplitudes (square root of degree variances) accumulation  cumulate variances over degrees evaluationRadius double evaluate the gravity field at this radius (default: evaluate at surface polarGap angle exclude polar regions (aperture angle in degrees) minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'This program computes degree amplitudes from <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">potentialCoefficients files</a> and saves them to a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file.</p><p>The coefficients can be filtered with <a class=\"groops-class\" href=\"sphericalHarmonicsFilterType.html\">filter</a> and converted to different functionals with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. The gravity field can be evaluated at different altitudes by specifying <strong class=\"groops-config-element\">evaluationRadius</strong>. Polar regions can be excluded by setting <strong class=\"groops-config-element\">polarGap</strong>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The coefficients are related to the reference radius <strong class=\"groops-config-element\">R</strong> and the Earth gravitational constant <strong class=\"groops-config-element\">GM</strong>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> contains in the first 3 columns the degree, the degree amplitude, and the formal errors. For each additional <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">inputfilePotentialCoefficients</a> three columns are appended: the degree amplitude, the formal errors, and the difference to the first file.</p><p>For example the data columns for 4 <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">inputfilePotentialCoefficients</a> are <ul>  <li>degree=<code>data0</code> </li><li> PotentialCoefficients0: signal=<code>data1</code>, error=<code>data2</code>, </li><li> PotentialCoefficients1: signal=<code>data3</code>, error=<code>data4</code>,  difference=<code>data5</code>, </li><li> PotentialCoefficients2: signal=<code>data6</code>, error=<code>data7</code>,  difference=<code>data8</code>, </li><li> PotentialCoefficients3: signal=<code>data9</code>, error=<code>data10</code>, difference=<code>data11</code>. </li></ul> </p><p>See also <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a>.'},\n'RadialBasisSplines2KernelCoefficients': { 'name': 'RadialBasisSplines2KernelCoefficients', 'key': 'RadialBasisSplines2KernelCoefficients', 'description': 'This program calculates the coefficients   of a   This program calculates the coefficients   according to  from a given   This program calculates the coefficients  , with  R  and  GM  describing the reference radius and the geocentric constant, respectively. The   stand for the gravity field accuracies (from degree  minDegree  to  maxDegree ), if they are given. If no accuracies are provided, the   represent the square root of the degree variances of the gravity field. If  maxDegree  exceeds the maximum degree given by   This program calculates the coefficients  , the higher degrees are complemented by Kaula\\'s rule The output of the coefficients is given in the file    This program calculates the coefficients  .', 'config_table': 'outputfileCoefficients filename  gravityfield gravityfieldType use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius kaulaPower double sigma = kaulaFactor/degree^kaulaPower kaulaFactor double sigma = kaulaFactor/degree^kaulaPower', 'display_text': 'This program calculates the coefficients $k_n$ of a <a class=\"groops-class\" href=\"kernelType.html#coefficients\">kernel:coefficients</a> according to \\\\[   k_n = \\\\frac{GM}{4\\\\pi R}\\\\frac{\\\\sigma_n}{\\\\sqrt{2n+1}}. \\\\]from a given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>, with <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">GM</strong> describing the reference radius and the geocentric constant, respectively. The $\\\\sigma_n$ stand for the gravity field accuracies (from degree <strong class=\"groops-config-element\">minDegree</strong> to <strong class=\"groops-config-element\">maxDegree</strong>), if they are given. If no accuracies are provided, the $\\\\sigma_n$ represent the square root of the degree variances of the gravity field. If <strong class=\"groops-config-element\">maxDegree</strong> exceeds the maximum degree given by <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>, the higher degrees are complemented by Kaula\\'s rule The output of the coefficients is given in the file  <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCoefficients</a>.'},\n'SatelliteModelCreate': { 'name': 'SatelliteModelCreate', 'key': 'SatelliteModelCreate', 'description': 'This program creates a satellite macro model for the estimation of non-gravitational accelerations acting on a satellite. Mandatory input values are the  satelliteName ,  mass ,  coefficientDrag  and information about the satellite  surfaces . For low Earth orbiting satellites, like GRACE for instance, a good guess for the drag coefficient could be 2.3. Apart from that, it is latter on possible to estimate a more precise variable drag coefficient (e.g.   This program creates a satellite macro model for the estimation of non-gravitational accelerations acting on a satellite. Mandatory input values are the  ), which will override this initial guess. Concerning the satellite surfaces an external file must be imported which must contain information about each single  satellite plate in terms of plate  area , the associated plate normal and re-radiation properties (reflexion, diffusion and absorption) properties in the visible and IR part. Examplarily, a description of the macro model for GRACE can be found under:  https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf  Additionally, it is possible to add further information like antennaThrust, solar panel, temporal mass changes and massInstrument using the modules option.', 'config_table': 'outputfileSatelliteModel filename  satellite sequence  satelliteName string  mass double  coefficientDrag double  surfaces sequence  inputfile filename each line must contain one surface element type expression 0: plate, 1: sphere, 2: cylinder area expression [m^2] normalX expression  normalY expression  normalZ expression  reflexionVisible expression  diffusionVisible expression  absorptionVisible expression  reflexionInfrared expression  diffusionInfrared expression  absorptionInfrared expression  specificHeatCapacity expression 0: no thermal radiation, -1: direct reemission [Ws/K/m^2] module choice  antennaThrust sequence  thrustX double  thrustY double  thrustZ double  solarPanel sequence  rotationAxisX double  rotationAxisY double  rotationAxisZ double  normalX double Direction to sun normalY double Direction to sun normalZ double Direction to sun indexSurface uint index of solar panel surfaces massChange sequence  time time  mass double  massInstrument sequence  inputfileInstrument filename', 'display_text': 'This program creates a satellite macro model for the estimation of non-gravitational accelerations acting on a satellite. Mandatory input values are the <strong class=\"groops-config-element\">satelliteName</strong>, <strong class=\"groops-config-element\">mass</strong>, <strong class=\"groops-config-element\">coefficientDrag</strong> and information about the satellite <strong class=\"groops-config-element\">surfaces</strong>. For low Earth orbiting satellites, like GRACE for instance, a good guess for the drag coefficient could be 2.3. Apart from that, it is latter on possible to estimate a more precise variable drag coefficient (e.g. <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">miscAccelerations:atmosphericDrag</a>), which will override this initial guess. Concerning the satellite surfaces an external file must be imported which must contain information about each single  satellite plate in terms of plate <strong class=\"groops-config-element\">area</strong>, the associated plate normal and re-radiation properties (reflexion, diffusion and absorption) properties in the visible and IR part. Examplarily, a description of the macro model for GRACE can be found under: <a href=\"https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf\" target=\"_blank\">https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf</a> Additionally, it is possible to add further information like antennaThrust, solar panel, temporal mass changes and massInstrument using the modules option.'},\n'SynthesisSphericalHarmonicsMatrix': { 'name': 'SynthesisSphericalHarmonicsMatrix', 'key': 'SynthesisSphericalHarmonicsMatrix', 'description': 'This program builds a linear operator matrix for spherical harmonic analysis or synthesis based on the points defined in   This program builds a linear operator matrix for spherical harmonic analysis or synthesis based on the points defined in  . Depending on the chosen  type  (synthesis, quadrature, or leastSquares), the resulting matrix can be used to:      synthesis : Map spherical harmonic coefficients to values on a grid,    quadrature : Integrate grid-based functionals into spherical harmonic coefficients by         a simple quadrature formula,    leastSquares : Estimate coefficients from grid data via a least squares approach.  he spherical harmonic degree range is constrained by  minDegree  and  maxDegree , and the ordering of the coefficients is given by   This program builds a linear operator matrix for spherical harmonic analysis or synthesis based on the points defined in  . The reference gravitational constant is  GM , and the reference radius is  R . The computed matrix is written to   This program builds a linear operator matrix for spherical harmonic analysis or synthesis based on the points defined in   with dimensions (number of grid points)   (number of spherical harmonic coefficients). For  type  =  leastSquares , the program applies a QR-based pseudo-inverse so that the output matrix can directly form the normal-equation building blocks for a blockwise least-squares solution in spherical harmonic space. See also  Gravityfield2GriddedData ,  GriddedData2PotentialCoefficients ,  Gravityfield2SphericalHarmonicsVector , and  MatrixCalculate  for additional tools to convert between grids and spherical harmonics.', 'config_table': 'outputfileMatrix filename  grid gridType  kernel kernelType  minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme of sh coefficients type choice  synthesis  synthesize spherical harmonics on a grid quadrature  calculate spherical harmonics from grid leastSquares  estimated spherical harmonics from grid', 'display_text': 'This program builds a linear operator matrix for spherical harmonic analysis or synthesis based on the points defined in <a class=\"groops-class\" href=\"gridType.html\">grid</a>. Depending on the chosen <strong class=\"groops-config-element\">type</strong> (synthesis, quadrature, or leastSquares), the resulting matrix can be used to: <ul>    <li><b>synthesis</b>: Map spherical harmonic coefficients to values on a grid,   </li><li> <b>quadrature</b>: Integrate grid-based functionals into spherical harmonic coefficients by         a simple quadrature formula,   </li><li> <b>leastSquares</b>: Estimate coefficients from grid data via a least squares approach. </li></ul> </p><p>he spherical harmonic degree range is constrained by <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong>, and the ordering of the coefficients is given by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>. The reference gravitational constant is <strong class=\"groops-config-element\">GM</strong>, and the reference radius is <strong class=\"groops-config-element\">R</strong>.</p><p>The computed matrix is written to <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrix</a> with dimensions (number of grid points) $\\\\times$ (number of spherical harmonic coefficients). For <strong class=\"groops-config-element\">type</strong> = <em>leastSquares</em>, the program applies a QR-based pseudo-inverse so that the output matrix can directly form the normal-equation building blocks for a blockwise least-squares solution in spherical harmonic space.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>, <a class=\"groops-program\" href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a>, <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a>, and <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a> for additional tools to convert between grids and spherical harmonics.'},\n'TemporalRepresentation2TimeSeries': { 'name': 'TemporalRepresentation2TimeSeries', 'key': 'TemporalRepresentation2TimeSeries', 'description': 'This program computes the design matrix of temporal representation at a given time series. The output matrix contains the time steps in MJD in the first column, the other columns contain the design matrix. The intention of this program is to visualize the parametrization together with  PlotGraph .', 'config_table': 'outputfileMatrix filename Time (MJD) in first column, design matrix follows timeSeries timeSeriesType  temporal parametrizationTemporalType', 'display_text': 'This program computes the design matrix of temporal representation at a given time series. The output matrix contains the time steps in MJD in the first column, the other columns contain the design matrix. The intention of this program is to visualize the parametrization together with <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.'},\n'ThermosphericState2GriddedData': { 'name': 'ThermosphericState2GriddedData', 'key': 'ThermosphericState2GriddedData', 'description': 'This program converts the output (neutral mass density,temperature) of an empirical thermosphere model (e.g. JB2008) on a given   This program converts the output (neutral mass density,temperature) of an empirical thermosphere model (e.g. JB2008) on a given  . Additionally, also the thermospheric winds estimated by using the horizontal wind model HWM 2014 can be assessed. The time for the evaluation can be specified in  time . The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening .', 'config_table': 'outputfileGriddedData filename density [kg/m**3], temperature [K], wind (x, y, z) [m/s**2] thermosphere thermosphereType  grid gridType  time time  localReferenceFrame boolean wind in local north, east, up, otherwise global terrestrial R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates', 'display_text': 'This program converts the output (neutral mass density,temperature) of an empirical thermosphere model (e.g. JB2008) on a given <a class=\"groops-class\" href=\"gridType.html\">grid</a>. Additionally, also the thermospheric winds estimated by using the horizontal wind model HWM 2014 can be assessed. The time for the evaluation can be specified in <strong class=\"groops-config-element\">time</strong>. The values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>.'},\n'TimeSeries2PotentialCoefficients': { 'name': 'TimeSeries2PotentialCoefficients', 'key': 'TimeSeries2PotentialCoefficients', 'description': 'Interpret the data columns of   Interpret the data columns of   as potential coefficients. The sequence of coefficients is given by   Interpret the data columns of   starting from data column  startDataFields . For each epoch a   Interpret the data columns of   is written where the  variableLoopTime  and  variableLoopIndex  are expanded for each point of the given time series to create the file name for this epoch, see  text parser . See also  Gravityfield2PotentialCoefficientsTimeSeries .', 'config_table': 'outputfilesPotentialCoefficients filename for each epoch variableLoopTime string variable with time of each epoch variableLoopIndex string variable with index of current epoch (starts with zero) variableLoopCount string variable with total number of epochs inputfileTimeSeries filename each epoch: multiple data for points (MISCVALUES) startDataFields uint first data column minDegree uint minimal degree maxDegree uint maximal degree GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme', 'display_text': 'Interpret the data columns of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTimeSeries</a> as potential coefficients. The sequence of coefficients is given by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a> starting from data column <strong class=\"groops-config-element\">startDataFields</strong>.</p><p>For each epoch a <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilesPotentialCoefficients</a> is written where the <strong class=\"groops-config-element\">variableLoopTime</strong> and <strong class=\"groops-config-element\">variableLoopIndex</strong> are expanded for each point of the given time series to create the file name for this epoch, see <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>.</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2PotentialCoefficientsTimeSeries.html\">Gravityfield2PotentialCoefficientsTimeSeries</a>.'},\n'TimeSeriesCreate': { 'name': 'TimeSeriesCreate', 'key': 'TimeSeriesCreate', 'description': 'This program generates an  instrument file , containing a time series.', 'config_table': 'outputfileTimeSeries filename instrument file timeSeries timeSeriesType time series to be created data expression expression of output columns, extra \\'epoch\\' variable', 'display_text': 'This program generates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>, containing a time series.'},\n'Variational2OrbitAndStarCamera': { 'name': 'Variational2OrbitAndStarCamera', 'key': 'Variational2OrbitAndStarCamera', 'description': 'Extracts the reference   Extracts the reference  ,   Extracts the reference  , and   Extracts the reference   from   Extracts the reference  .', 'config_table': 'outputfileOrbit filename output orbit (instrument) file outputfileStarCamera filename output satellite attidude as star camera (instrument) file outputfileEarthRotation filename output Earth rotation as star camera (instrument) file inputfileVariational filename input variational file', 'display_text': 'Extracts the reference <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStarCamera</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileEarthRotation</a> from <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>.'},\n'NormalsAccumulate': { 'name': 'NormalsAccumulate', 'key': 'NormalsAccumulate', 'description': 'This program accumulates normal equations and writes the total combined system to   This program accumulates normal equations and writes the total combined system to  . The   This program accumulates normal equations and writes the total combined system to  s must have all the same size and the same block structure. This program is the simplified and fast version of the more general program  NormalsBuild . For input normals with different parameters, see  NormalsReorderAndAccumulate .', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename', 'display_text': 'This program accumulates normal equations and writes the total combined system to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalequation</a>. The <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>s must have all the same size and the same block structure.</p><p>This program is the simplified and fast version of the more general program <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>. For input normals with different parameters, see <a class=\"groops-program\" href=\"NormalsReorderAndAccumulate.html\">NormalsReorderAndAccumulate</a>.'},\n'NormalsBuild': { 'name': 'NormalsBuild', 'key': 'NormalsBuild', 'description': 'This program accumulates   This program accumulates  s and writes the total combined system to   This program accumulates  . For a detailed description of the used algorithm see   This program accumulates  . Large normal equation systems can be divided into blocks with  normalsBlockSize . A simplifed and fast version of this program is  NormalsAccumulate . For input normals with different parameters see  NormalsReorderAndAccumulate . To solve the system of normal equations use  NormalsSolverVCE .', 'config_table': 'outputfileNormalEquation filename  normalEquation normalEquationType  normalsBlockSize uint block size for distributing the normal equations, 0: one block', 'display_text': 'This program accumulates <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>s and writes the total combined system to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalequation</a>. For a detailed description of the used algorithm see <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>. Large normal equation systems can be divided into blocks with <strong class=\"groops-config-element\">normalsBlockSize</strong>.</p><p>A simplifed and fast version of this program is <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>. For input normals with different parameters see <a class=\"groops-program\" href=\"NormalsReorderAndAccumulate.html\">NormalsReorderAndAccumulate</a>. To solve the system of normal equations use <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>.'},\n'NormalsBuildShortTimeStaticLongTime': { 'name': 'NormalsBuildShortTimeStaticLongTime', 'key': 'NormalsBuildShortTimeStaticLongTime', 'description': 'This program sets up normal equations based on   This program sets up normal equations based on  . Additionally short time and long time variations can be parametrized based on the static parameters in   This program sets up normal equations based on   in an efficient way. The observation equations are divided into time intervals   (e.g. daily) as defined in   This program sets up normal equations based on  . With  estimateLongTimeVariations  additional temporal variations can be co-estimated for a subset of the parameters selected by   This program sets up normal equations based on  . These parameters might be spherical harmonic coefficients with a limited maximum degree. The temporal variations are represented by base functions   (e.g. trend and annual oscillation) given by   This program sets up normal equations based on  . The temporal base functions are evaluated at the mid time   of each interval  , multiplicated with the design matrix   of the selected parameters, and the design matrix is extended accordingly. With  estimateShortTimeVariations  short time variations of the gravity field can be co-estimated. Their purpose is to mitigate temporal aliasing. The short time parameters selected by   This program sets up normal equations based on   (e.g. daily constant or linear splines every 6 hour) are constrained by an   This program sets up normal equations based on  . If only a static parameter set is selected the coressponding part of the design matrix is copied and modeled as a constant value per interval in   This program sets up normal equations based on   additionally so the corresponding temporal factor can be expressed as   Before writing the normal equations to   This program sets up normal equations based on   short time gravity and satellite specific parameters can be eliminated with  eliminateParameter . Example: For the computation of the mean gravity field ITSG-Grace2018s with additional trend and annual signal the normal equations are computed month by month and accumulated afterwards (see  NormalsAccumulate ). The observations were divided into daily intervals with   This program sets up normal equations based on  . The static gravity field has been parametrized as spherical harmonics up to degree   in   This program sets up normal equations based on  . The trend and annual signals defined by   This program sets up normal equations based on   were estimated for selected parameters up to degree  . To mitigate temporal aliasing daily gravity fields up to degree   were setup and constrained with an   This program sets up normal equations based on   up to order three. A detailed description of the approach is given in: Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties. J Geod 93, 2543–2552 (2019).  https://doi.org/10.1007/s00190-019-01314-1 .', 'config_table': 'outputfileNormalEquation filename outputfile for normal equations observation observationType  estimateShortTimeVariations sequence co-estimate short time gravity field variations autoregressiveModelSequence autoregressiveModelSequenceType AR model sequence for constraining short time gravity variations parameterSelection parameterSelectorType parameters describing the short time gravity field estimateLongTimeVariations sequence co-estimate long time gravity field variations parametrizationTemporal parametrizationTemporalType parametrization of time variations (trend, annual, ...) parameterSelection parameterSelectorType parameters describing the long time gravity field inputfileArcList filename list to correspond points of time to arc numbers defaultBlockSize uint block size for distributing the normal equations, 0: one block eliminateParameter boolean eliminate short time and state parameter', 'display_text': 'This program sets up normal equations based on <a class=\"groops-class\" href=\"observationType.html\">observation</a>. Additionally short time and long time variations can be parametrized based on the static parameters in <a class=\"groops-class\" href=\"observationType.html\">observation</a> in an efficient way. The observation equations are divided into time intervals $i \\\\in \\\\{1, ..., N\\\\}$ (e.g. daily) as defined in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a>.</p><p>With <strong class=\"groops-config-element\">estimateLongTimeVariations</strong> additional temporal variations can be co-estimated for a subset of the parameters selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>. These parameters might be spherical harmonic coefficients with a limited maximum degree. The temporal variations are represented by base functions $\\\\Phi_k(t_i)$ (e.g. trend and annual oscillation) given by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>. The temporal base functions are evaluated at the mid time $t_i$ of each interval $i$, multiplicated with the design matrix $\\\\M A_i$ of the selected parameters, and the design matrix is extended accordingly.</p><p></p><p>With <strong class=\"groops-config-element\">estimateShortTimeVariations</strong> short time variations of the gravity field can be co-estimated. Their purpose is to mitigate temporal aliasing. The short time parameters selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> (e.g. daily constant or linear splines every 6 hour) are constrained by an <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a>. If only a static parameter set is selected the coressponding part of the design matrix is copied and modeled as a constant value per interval in <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a> additionally so the corresponding temporal factor can be expressed as \\\\[   \\\\Phi_i(t)  =   \\\\begin{cases}     1 &\\\\text{if} \\\\hspace{5pt} t \\\\in [t_i, t_{i+1}) \\\\\\\\     0 & \\\\text{otherwise}   \\\\end{cases}. \\\\] Before writing the normal equations to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a> short time gravity and satellite specific parameters can be eliminated with <strong class=\"groops-config-element\">eliminateParameter</strong>.</p><p>Example: For the computation of the mean gravity field ITSG-Grace2018s with additional trend and annual signal the normal equations are computed month by month and accumulated afterwards (see <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>). The observations were divided into daily intervals with <a class=\"groops-class\" href=\"fileFormat_arcList.html\">inputfileArcList</a>. The static gravity field has been parametrized as spherical harmonics up to degree $n=200$ in <a class=\"groops-class\" href=\"parametrizationGravityType.html\">observation:parametrizationGravity</a>. The trend and annual signals defined by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">estimateLongTimeVariations:parametrizationTemporal</a> were estimated for selected parameters up to degree $n=120$. To mitigate temporal aliasing daily gravity fields up to degree $n=40$ were setup and constrained with an <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">autoregressiveModelSequence</a> up to order three.</p><p>A detailed description of the approach is given in: Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties. J Geod 93, 2543–2552 (2019). <a href=\"https://doi.org/10.1007/s00190-019-01314-1\" target=\"_blank\">https://doi.org/10.1007/s00190-019-01314-1</a>.'},\n'NormalsCreate': { 'name': 'NormalsCreate', 'key': 'NormalsCreate', 'description': 'Create  normal equations  from calculated matrices (  Create  ). The   Create   can be created with  ParameterNamesCreate . The   Create   must be symmetric. The   Create   must have the same number of rows and can contain multiple columns for multiple solutions. The Vector   is the quadratic sum of observations for each column of the right hand side. It is used to determine the aposteriori accuracy  If the vector is not given, it is automatically determined by assuming  . The number of observations   is given by the expression  observationCount . The variable  observationCount  can be used, if it is set by a normal equation file   Create  .', 'config_table': 'outputfileNormalEquation filename  inputfileParameterNames filename  normalMatrix matrixGeneratorType  rightHandSide matrixGeneratorType  lPl matrixGeneratorType vector with size of rhs columns inputfileNormalEquationObsCount filename sets the variable observationCount observationCount expression (variables: rows, columns (rhs), observationCount)', 'display_text': 'Create <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> from calculated matrices (<a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrixGenerator</a>).</p><p>The <a class=\"groops-class\" href=\"fileFormat_parameterName.html\">inputfileParameterNames</a> can be created with <a class=\"groops-program\" href=\"ParameterNamesCreate.html\">ParameterNamesCreate</a>.</p><p>The <a class=\"groops-class\" href=\"matrixGeneratorType.html\">normalMatrix</a> must be symmetric. The <a class=\"groops-class\" href=\"matrixGeneratorType.html\">rightHandSide</a> must have the same number of rows and can contain multiple columns for multiple solutions.</p><p>The Vector $\\\\M l^T\\\\M P\\\\M l$ is the quadratic sum of observations for each column of the right hand side. It is used to determine the aposteriori accuracy \\\\[ \\\\hat{\\\\sigma}^2 = \\\\frac{\\\\hat{\\\\M e}^T\\\\M P\\\\hat{\\\\M e}}{n-m} = \\\\frac{\\\\M l^T\\\\M P\\\\M l - \\\\M n^T\\\\hat{\\\\M x}}{n-m}. \\\\]If the vector is not given, it is automatically determined by assuming $\\\\hat{\\\\sigma}^2=1$.</p><p>The number of observations $n$ is given by the expression <strong class=\"groops-config-element\">observationCount</strong>. The variable <code>observationCount</code> can be used, if it is set by a normal equation file <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquationObsCount</a>.'},\n'NormalsEliminate': { 'name': 'NormalsEliminate', 'key': 'NormalsEliminate', 'description': 'This program eliminates parameters from a system of   This program eliminates parameters from a system of  s. To just remove (cutting out) parameters use  NormalsReorder . The   This program eliminates parameters from a system of   allows the selection of parameters that will remain, all others will be eliminated. The order of remaining parameters can be modified via the parameter selection. Block size of the output normal matrix can be adjusted with  outBlockSize . If it is set to zero, the   This program eliminates parameters from a system of   is written to a single block file. For example the normal equations are divided into two groups of parameters   and   according to  and   shall be eliminated, the reduced system of normal equations is given by   See also  NormalsReorder .', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename  remainingParameters parameterSelectorType parameter order/selection of output normal equations outBlockSize uint block size for distributing the normal equations, 0: one block', 'display_text': 'This program eliminates parameters from a system of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>s. To just remove (cutting out) parameters use <a class=\"groops-program\" href=\"NormalsReorder.html\">NormalsReorder</a>.</p><p>The <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a> allows the selection of parameters that will remain, all others will be eliminated. The order of remaining parameters can be modified via the parameter selection. Block size of the output normal matrix can be adjusted with <strong class=\"groops-config-element\">outBlockSize</strong>. If it is set to zero, the <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a> is written to a single block file.</p><p>For example the normal equations are divided into two groups of parameters $\\\\hat{\\\\M x}_1$ and $\\\\hat{\\\\M x}_2$ according to \\\\[ \\\\begin{pmatrix}   \\\\M N_{11} & \\\\M N_{12} \\\\\\\\   \\\\M N_{21} & \\\\M N_{22} \\\\end{pmatrix} \\\\begin{pmatrix} \\\\hat{\\\\M x}_1 \\\\\\\\ \\\\hat{\\\\M x}_2 \\\\end{pmatrix} = \\\\begin{pmatrix}   \\\\M n_1 \\\\\\\\   \\\\M n_2 \\\\end{pmatrix}. \\\\]and $\\\\hat{\\\\M x}_2$ shall be eliminated, the reduced system of normal equations is given by \\\\[ \\\\bar{\\\\M N}\\\\hat{\\\\M x} = \\\\bar{\\\\M n} \\\\qquad\\\\text{with}\\\\qquad \\\\bar{\\\\M N}=\\\\M N_{11}-\\\\M N_{12}\\\\M N_{22}^{-1}\\\\M N_{12}^T \\\\qquad\\\\text{and}\\\\qquad\\\\bar{\\\\M n} =  \\\\M n_1 - \\\\M N_{12}\\\\M N_{22}^{-1}\\\\M n_2. \\\\] See also <a class=\"groops-program\" href=\"NormalsReorder.html\">NormalsReorder</a>.'},\n'NormalsMultiplyAdd': { 'name': 'NormalsMultiplyAdd', 'key': 'NormalsMultiplyAdd', 'description': 'This program modifies   This program modifies   in a way that   is estimated instead of  .  where   is   This program modifies   and   is  factor . This can be used to re-add reduced reference fields before a combined estimation at normal equation level. Therefore the right hand side of the normal equations is modified by  and the quadratic sum of observations by   As the normal matrix itself is not modified, rewriting of the matrix can be disabled by setting  writeNormalMatrix  to false.', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename  inputfileParameter filename x factor double alpha writeNormalMatrix boolean write full coefficient matrix, right hand sides and info files', 'display_text': 'This program modifies <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> in a way that $\\\\bar{\\\\M x}$ is estimated instead of $\\\\M x$. \\\\[  \\\\bar{\\\\M x} := \\\\M x + \\\\alpha\\\\, \\\\M x_0, \\\\]where $\\\\M x_0$ is <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileParameter</a> and $\\\\alpha$ is <strong class=\"groops-config-element\">factor</strong>. This can be used to re-add reduced reference fields before a combined estimation at normal equation level. Therefore the right hand side of the normal equations is modified by \\\\[  \\\\bar{\\\\M n} := \\\\M n + \\\\alpha\\\\,\\\\M N\\\\M x_0, \\\\]and the quadratic sum of observations by \\\\[  \\\\bar{\\\\M l^T\\\\M P\\\\M l} := \\\\M l^T\\\\M P\\\\M l + \\\\alpha^2\\\\,\\\\M x_0^T\\\\M N\\\\M x_0 + 2\\\\alpha\\\\,\\\\M x_0^T\\\\M n \\\\] As the normal matrix itself is not modified, rewriting of the matrix can be disabled by setting <strong class=\"groops-config-element\">writeNormalMatrix</strong> to false.'},\n'NormalsRegularizationBorders': { 'name': 'NormalsRegularizationBorders', 'key': 'NormalsRegularizationBorders', 'description': 'This program sets up two regularization matrices for two different regional areas. For a given set of points defined by   This program sets up two regularization matrices for two different regional areas. For a given set of points defined by   it is evaluated, whether each point (corresponding to an unknown parameter of a respective parameterization by space localizing basis functions) is inside or outside a certain area given by   This program sets up two regularization matrices for two different regional areas. For a given set of points defined by  . Each regularization matrix is a diagonal matrix, one of them features a one if the point is inside, and a zero if the point lies outside the area. The other matrix features a zero if the point is inside, and a one if the point lies outside the area This results in two regularization matrices with  The two matrices are provided as vectors of the diagonal in the output files   This program sets up two regularization matrices for two different regional areas. For a given set of points defined by   and   This program sets up two regularization matrices for two different regional areas. For a given set of points defined by  . The regularization matrices are then used by   This program sets up two regularization matrices for two different regional areas. For a given set of points defined by  . As an example, the two different areas could be oceanic regions on the one hand and continental areas on the other hand.', 'config_table': 'outputfileInside filename  outputfileOutside filename  grid gridType nodal point distribution of parameters, e.g harmonics splines border borderType regularization areas, e.g land and ocean R double reference radius for ellipsoidal coordinates for border inverseFlattening double reference flattening for ellipsoidal coordinates for border, 0: spherical coordinates', 'display_text': 'This program sets up two regularization matrices for two different regional areas. For a given set of points defined by <a class=\"groops-class\" href=\"gridType.html\">grid</a> it is evaluated, whether each point (corresponding to an unknown parameter of a respective parameterization by space localizing basis functions) is inside or outside a certain area given by <a class=\"groops-class\" href=\"borderType.html\">border</a>. Each regularization matrix is a diagonal matrix, one of them features a one if the point is inside, and a zero if the point lies outside the area. The other matrix features a zero if the point is inside, and a one if the point lies outside the area This results in two regularization matrices with \\\\[ \\\\M R_1+\\\\M R_2=\\\\M I. \\\\]The two matrices are provided as vectors of the diagonal in the output files <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileOutside</a> and <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileInside</a>. The regularization matrices are then used by <a class=\"groops-class\" href=\"normalEquationType.html#regularization\">normalEquation:regularization</a>. As an example, the two different areas could be oceanic regions on the one hand and continental areas on the other hand.'},\n'NormalsRegularizationSphericalHarmonics': { 'name': 'NormalsRegularizationSphericalHarmonics', 'key': 'NormalsRegularizationSphericalHarmonics', 'description': 'Diagonal regularization matrix from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule. The inverse accuracies   are used as weights in the regularization matrix. The diagonal is saved as Vector. The corresponding pseudo observations can be computed with  Gravityfield2SphericalHarmonicsVector .', 'config_table': 'outputfileDiagonalmatrix filename  gravityfield gravityfieldType use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule minRegularizationDegree uint  maxRegularizationDegree uint  minDegree uint  maxDegree uint  numbering sphericalHarmonicsNumberingType numbering scheme for regul matrix GM double Geocentric gravitational constant R double reference radius makeIsotropic boolean  kaulaPower double sigma = kaulaFactor*degree**kaulaPower kaulaFactor double sigma = kaulaFactor*degree**kaulaPower', 'display_text': 'Diagonal regularization matrix from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule. The inverse accuracies $1/\\\\sigma_n^2$ are used as weights in the regularization matrix. The diagonal is saved as Vector.</p><p>The corresponding pseudo observations can be computed with <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a>.'},\n'NormalsReorder': { 'name': 'NormalsReorder', 'key': 'NormalsReorder', 'description': 'Reorder   Reorder   by selecting parameters in a specific order. The   Reorder   also allows one to change dimension of the normal equations, either by cutting parameters or by inserting zero rows/columns for additional parameters. Without   Reorder   the order of parameters remains the same. Additionally the block sizes of the files can be adjusted. If  outBlockSize  is set to zero, the normal matrix is written to a single block file, which is needed by some programs. To eliminate parameters without changing the result of the other parameters use  NormalsEliminate .', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename  parameterSelection parameterSelectorType parameter order/selection of output normal equations outBlockSize uint block size for distributing the normal equations, 0: one block', 'display_text': 'Reorder <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> by selecting parameters in a specific order. The <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> also allows one to change dimension of the normal equations, either by cutting parameters or by inserting zero rows/columns for additional parameters. Without <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> the order of parameters remains the same. Additionally the block sizes of the files can be adjusted. If <strong class=\"groops-config-element\">outBlockSize</strong> is set to zero, the normal matrix is written to a single block file, which is needed by some programs.</p><p>To eliminate parameters without changing the result of the other parameters use <a class=\"groops-program\" href=\"NormalsEliminate.html\">NormalsEliminate</a>.'},\n'NormalsReorderAndAccumulate': { 'name': 'NormalsReorderAndAccumulate', 'key': 'NormalsReorderAndAccumulate', 'description': 'This program accumulates   This program accumulates  s with respect to the parameter names and writes the total combined system to   This program accumulates  . The combined normal equation is extended to include all parameter names uniquely from all input normals. The input normals are sorted so that parameters with the same name are accumulated. This requires that the names in each normal equation are unique. The output can be written as multiple small block files with  outBlockSize , or as single block with  outBlockSize =0, or blocked with respect to the first part of the parameter names (object), if  outBlockSize  left empty. See also  NormalsBuild  and  NormalsAccumulate .', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename  outBlockSize uint block size for distributing the normal equations, 0: one block, empty: blocking by objects', 'display_text': 'This program accumulates <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>s with respect to the parameter names and writes the total combined system to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalequation</a>.</p><p>The combined normal equation is extended to include all parameter names uniquely from all input normals. The input normals are sorted so that parameters with the same name are accumulated. This requires that the names in each normal equation are unique.</p><p>The output can be written as multiple small block files with <strong class=\"groops-config-element\">outBlockSize</strong>, or as single block with <strong class=\"groops-config-element\">outBlockSize</strong>=0, or blocked with respect to the first part of the parameter names (object), if <strong class=\"groops-config-element\">outBlockSize</strong> left empty.</p><p>See also <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a> and <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>.'},\n'NormalsScale': { 'name': 'NormalsScale', 'key': 'NormalsScale', 'description': 'Scales rows and columns of a system of   Scales rows and columns of a system of   given by a diagonal matrix   Scales rows and columns of a system of      The estimated solution is now  This is effectively the same as rescaling columns of the design matrix. This program is useful when combining normal equations from different sources, for example in case the units of certain parameters don\\'t match.', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename  inputfileFactorVector filename Vector containing the factors', 'display_text': 'Scales rows and columns of a system of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> given by a diagonal matrix <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileFactorVector</a> $\\\\M S$ \\\\[   \\\\bar{\\\\M N} := \\\\M S \\\\M N \\\\M S \\\\qquad\\\\text{and}\\\\qquad \\\\bar{\\\\M n} := \\\\M S \\\\M n. \\\\]The estimated solution is now \\\\[   \\\\bar{\\\\M x} := \\\\M S^{-1} \\\\M x. \\\\]This is effectively the same as rescaling columns of the design matrix. This program is useful when combining normal equations from different sources, for example in case the units of certain parameters don\\'t match.'},\n'NormalsSolverVCE': { 'name': 'NormalsSolverVCE', 'key': 'NormalsSolverVCE', 'description': 'This program accumulates   This program accumulates   and solves the total combined system. The relative weigthing between the individual normals is determined iteratively by means of variance component estimation (VCE). For a detailed description of the used algorithm see   This program accumulates  . Besides the estimated parameter vector (  This program accumulates  ) the estimated accuracies (  This program accumulates  ) and the full covariance matrix (  This program accumulates  ) can be saved. Also the combined normal system can be written to   This program accumulates  . The   This program accumulates   is a matrix with rows for each estimated parameter and columns for each   This program accumulates   and indicates the contribution of the individual normals to the estimated parameters. Each row sum up to one. See also  NormalsBuild .', 'config_table': 'outputfileSolution filename parameter vector outputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) outputfileCovariance filename full covariance matrix outputfileContribution filename contribution of normal system components to the solution vector outputfileVarianceFactors filename estimated variance factors as vector outputfileNormalEquation filename the combined normal equation system normalEquation normalEquationType  inputfileApproxSolution filename to accelerate convergence rightHandSideNumberVCE uint the right hand side number for estimation of variance factors normalsBlockSize uint block size for distributing the normal equations, 0: one block maxIterationCount uint maximum number of iterations for variance component estimation', 'display_text': 'This program accumulates <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a> and solves the total combined system. The relative weigthing between the individual normals is determined iteratively by means of variance component estimation (VCE). For a detailed description of the used algorithm see <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a>.</p><p>Besides the estimated parameter vector (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a>) the estimated accuracies (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>) and the full covariance matrix (<a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileCovariance</a>) can be saved. Also the combined normal system can be written to <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">outputfileNormalEquation</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileContribution</a> is a matrix with rows for each estimated parameter and columns for each <a class=\"groops-class\" href=\"normalEquationType.html\">normalEquation</a> and indicates the contribution of the individual normals to the estimated parameters. Each row sum up to one.</p><p>See also <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>.'},\n'NormalsTemporalCombination': { 'name': 'NormalsTemporalCombination', 'key': 'NormalsTemporalCombination', 'description': 'This program reads a times series of   This program reads a times series of   with asscociated   This program reads a times series of   and setup a new combined normal equation system. For each parameter a   This program reads a times series of   is used. It can be used to estimate trend and annual spherical harmonic coefficients from monthly GRACE normal equations.', 'config_table': 'outputfileNormalEquation filename  inputfileNormalEquation filename normal equations for each point in time timeSeries timeSeriesType times of each normal equations parametrizationTemporal parametrizationTemporalType', 'display_text': 'This program reads a times series of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalequation</a> with asscociated <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> and setup a new combined normal equation system. For each parameter a <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> is used.</p><p>It can be used to estimate trend and annual spherical harmonic coefficients from monthly GRACE normal equations.'},\n'ParameterNamesCreate': { 'name': 'ParameterNamesCreate', 'key': 'ParameterNamesCreate', 'description': 'Generate a   Generate a   by   Generate a  . This file can be used in  NormalsCreate  or in the class   Generate a  .', 'config_table': 'outputfileParameterNames filename output parameter names file parameterName parameterNamesType', 'display_text': 'Generate a <a class=\"groops-class\" href=\"fileFormat_parameterName.html\">outputfileParameterNames</a> by <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>. This file can be used in <a class=\"groops-program\" href=\"NormalsCreate.html\">NormalsCreate</a> or in the class <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelector</a>.'},\n'ParameterSelection2IndexVector': { 'name': 'ParameterSelection2IndexVector', 'key': 'ParameterSelection2IndexVector', 'description': 'Generate index vector from parameter selection in  matrix format . This vector can be used in  MatrixCalculate  with   Generate index vector from parameter selection in   to reorder arbitrary vectors and matrices similar to  NormalsReorder . The   Generate index vector from parameter selection in   allows reordering and dimension changes, either by cutting parameters or by inserting additional parameters.   Generate index vector from parameter selection in   contains indices of parameters in   Generate index vector from parameter selection in   or -1 for newly added parameters.   Generate index vector from parameter selection in   contains the selected parameter names.', 'config_table': 'outputfileIndexVector filename indices of source parameters in target normal equations outputfileParameterNames filename output parameter names file inputfileParameterNames filename parameter names file of source normal equations parameterSelection parameterSelectorType parameter order/selection of target normal equations', 'display_text': 'Generate index vector from parameter selection in <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix format</a>. This vector can be used in <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a> with <a class=\"groops-class\" href=\"matrixGeneratorType.html#reorder\">matrix:reorder</a> to reorder arbitrary vectors and matrices similar to <a class=\"groops-program\" href=\"NormalsReorder.html\">NormalsReorder</a>.</p><p>The <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a> allows reordering and dimension changes, either by cutting parameters or by inserting additional parameters. <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileIndexVector</a> contains indices of parameters in <a class=\"groops-class\" href=\"fileFormat_parameterName.html\">inputfileParameterNames</a> or -1 for newly added parameters. <a class=\"groops-class\" href=\"fileFormat_parameterName.html\">outputfileParameterNames</a> contains the selected parameter names.'},\n'Orbit2ArgumentOfLatitude': { 'name': 'Orbit2ArgumentOfLatitude', 'key': 'Orbit2ArgumentOfLatitude', 'description': 'This program computes the argument of latitude of an  orbit  and writes it as  instrument file  (MISCVALUE(S)). The data of   This program computes the argument of latitude of an   are appended as values to each epoch.', 'config_table': 'outputfileArgOfLatitude filename instrument file (MISCVALUE(S): argLat, ...) inputfileOrbit filename  inputfileInstrument filename data are appended', 'display_text': 'This program computes the argument of latitude of an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> and writes it as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUE(S)). The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.</p><p>'},\n'Orbit2BetaPrimeAngle': { 'name': 'Orbit2BetaPrimeAngle', 'key': 'Orbit2BetaPrimeAngle', 'description': 'This program computes the beta prime angle (between the orbital plane and earth-sun direction) and writes it as MISCVALUE(S)  instrument file . The angle is calculated w.r.t the sun (per default), but can be changed. The data of   This program computes the beta prime angle (between the orbital plane and earth-sun direction) and writes it as MISCVALUE(S)   are appended as values to each epoch.', 'config_table': 'outputfileBetaAngle filename instrument file (MISCVALUE(S): beta\\', ...) inputfileOrbit filename  inputfileInstrument filename data are appended ephemerides ephemeridesType  planet planetType', 'display_text': 'This program computes the beta prime angle (between the orbital plane and earth-sun direction) and writes it as MISCVALUE(S) <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The angle is calculated w.r.t the sun (per default), but can be changed. The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.'},\n'Orbit2EarthFixedOrbit': { 'name': 'Orbit2EarthFixedOrbit', 'key': 'Orbit2EarthFixedOrbit', 'description': 'Normally the orbits in GROOPS are given in the celestial reference frame (CRF) with the origin in the center of mass (CoM). This program rotates the orbit with   Normally the orbits in GROOPS are given in the celestial reference frame (CRF) with the origin in the center of mass (CoM). This program rotates the orbit with   from CRF to the TRF. To additionally tranform into the center of solid Earth (CE) frame (or center of Figure (CF)), a correction can be applied by providing degree one coefficients of a   Normally the orbits in GROOPS are given in the celestial reference frame (CRF) with the origin in the center of mass (CoM). This program rotates the orbit with   (e.g. ocean tides). If  celestial2terrestrial  is set to no, the inverse transformation is applied. See also  InstrumentRotate .', 'config_table': 'outputfileOrbit filename  inputfileOrbit filename  earthRotation earthRotationType transformation from CRF to TRF gravityfield gravityfieldType degree 1 fluid mantle for CM2CE correction celestial2terrestrial boolean yes: crf->trf, no: trf->crf', 'display_text': 'Normally the orbits in GROOPS are given in the celestial reference frame (CRF) with the origin in the center of mass (CoM). This program rotates the orbit with <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> from CRF to the TRF.</p><p>To additionally tranform into the center of solid Earth (CE) frame (or center of Figure (CF)), a correction can be applied by providing degree one coefficients of a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> (e.g. ocean tides).</p><p>If <strong class=\"groops-config-element\">celestial2terrestrial</strong> is set to no, the inverse transformation is applied.</p><p>See also <a class=\"groops-program\" href=\"InstrumentRotate.html\">InstrumentRotate</a>.'},\n'Orbit2EclipseFactor': { 'name': 'Orbit2EclipseFactor', 'key': 'Orbit2EclipseFactor', 'description': 'This program generates an  instrument file  (MISCVALUE(S)) containing the eclipse factor for a given set of orbit. The data of   This program generates an   are appended as values to each epoch.', 'config_table': 'outputfileEclipseFactor filename instrument file (MISCVALUE(S): eclipse, ...) inputfileOrbit filename  inputfileInstrument filename data are appended ephemerides ephemeridesType  eclipse eclipseType', 'display_text': 'This program generates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUE(S)) containing the eclipse factor for a given set of orbit. The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.'},\n'Orbit2Groundtracks': { 'name': 'Orbit2Groundtracks', 'key': 'Orbit2Groundtracks', 'description': 'This program write  satellites positions  as  gridded data  ( outputfileTrackGriddedData ) in a terrestrial reference frame. The points are expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters  R  and  inverseFlattening . The orbit data are given in the celestial frame so   This program write   is needed to transform the data into the terrestrial frame. The data of   This program write   are appended as values to each point.', 'config_table': 'outputfileGriddedData filename positions as gridded data inputfileOrbit filename  inputfileInstrument filename values at grid points earthRotation earthRotationType transformation from CRF to TRF R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'This program write <a class=\"groops-file\" href=\"fileFormat_instrument.html\">satellites positions</a> as <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a> (<strong class=\"groops-config-element\">outputfileTrackGriddedData</strong>) in a terrestrial reference frame. The points are expressed as ellipsoidal coordinates (longitude, latitude, height) based on a reference ellipsoid with parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong>. The orbit data are given in the celestial frame so <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is needed to transform the data into the terrestrial frame. The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each point.'},\n'Orbit2Kepler': { 'name': 'Orbit2Kepler', 'key': 'Orbit2Kepler', 'description': 'This program computes the osculating Keplerian elements from position and velocity of a given   This program computes the osculating Keplerian elements from position and velocity of a given  . The   This program computes the osculating Keplerian elements from position and velocity of a given   must contain positions and velocities (see  OrbitAddVelocityAndAcceleration ). The  outputfileKepler  is an  instrument file  (MISCVALUES) with the Keplerian elements at each epoch in the following order    Ascending Node   [degree]  Inclination   [degree]  Argument of perigee   [degree]  major axis   [m]  eccentricity    mean anomaly   [degree]  transit time of perigee   [mjd]   The data of   This program computes the osculating Keplerian elements from position and velocity of a given   are appended as values to each epoch.', 'config_table': 'outputfileKepler filename instrument file (MISCVALUES: Omega, i, omega [degree], a [m], e, M [degree], tau [mjd], ...) inputfileOrbit filename position and velocity at each epoch define the kepler orbit inputfileInstrument filename data is appended GM double Geocentric gravitational constant', 'display_text': 'This program computes the osculating Keplerian elements from position and velocity of a given <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain positions and velocities (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>).</p><p>The <strong class=\"groops-config-element\">outputfileKepler</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES) with the Keplerian elements at each epoch in the following order <ul>  <li>Ascending Node $\\\\Omega$ [degree] </li><li> Inclination $i$ [degree] </li><li> Argument of perigee $\\\\omega$ [degree] </li><li> major axis $a$ [m] </li><li> eccentricity $e$ </li><li> mean anomaly $M$ [degree] </li><li> transit time of perigee $\\\\tau$ [mjd] </li></ul>  The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.'},\n'Orbit2MagneticField': { 'name': 'Orbit2MagneticField', 'key': 'Orbit2MagneticField', 'description': 'This program computes the magentic field vector(    in CRF)) along an  orbit  and writes it as  instrument file  (MISCVALUES). The data of   This program computes the magentic field vector(  are appended as data columns to each epoch.', 'config_table': 'outputfileMagneticField filename instrument file (x,y,z in CRF [Tesla = kg/A/s^2]), ...) inputfileOrbit filename  inputfileInstrument filename data are appended to output file magnetosphere magnetosphereType  earthRotation earthRotationType', 'display_text': 'This program computes the magentic field vector($x, y, z$ $[Tesla = kg/A/s^2]$ in CRF)) along an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> and writes it as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES). The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as data columns to each epoch.'},\n'Orbit2ThermosphericState': { 'name': 'Orbit2ThermosphericState', 'key': 'Orbit2ThermosphericState', 'description': 'This program computes the thermosperic state (density, temperature, wind (x,y,z in CRF)) based on emprical models along an  orbit  and writes it as  instrument file  (MISCVALUES). The wind is given in an celestial reference frame (CRF). The data of   This program computes the thermosperic state (density, temperature, wind (x,y,z in CRF)) based on emprical models along an   are appended as values to each epoch.', 'config_table': 'outputfileThermosphericState filename instrument file (MISCVALUES: density, temperature, wind (x,y,z in CRF), ...) inputfileOrbit filename  inputfileInstrument filename data are appended to output file thermosphere thermosphereType  earthRotation earthRotationType', 'display_text': 'This program computes the thermosperic state (density, temperature, wind (x,y,z in CRF)) based on emprical models along an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> and writes it as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> (MISCVALUES). The wind is given in an celestial reference frame (CRF). The data of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> are appended as values to each epoch.'},\n'OrbitAddVelocityAndAcceleration': { 'name': 'OrbitAddVelocityAndAcceleration', 'key': 'OrbitAddVelocityAndAcceleration', 'description': 'This program computes velocities and accelerations from a given  orbit  by differentiating a moving polynomial. The values are saved in one output file which then contains orbit, velocity and acceleration.', 'config_table': 'outputfileOrbit filename  inputfileOrbit filename  polynomialDegree uint Polynomial degree, must be even!', 'display_text': 'This program computes velocities and accelerations from a given <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> by differentiating a moving polynomial. The values are saved in one output file which then contains orbit, velocity and acceleration.'},\n'PlanetOrbit': { 'name': 'PlanetOrbit', 'key': 'PlanetOrbit', 'description': 'Creates an  orbit file  of sun, moon, or planets. The orbit is given in the celestial reference frame (CRF) or alternatively in the terrestrial reference frame (TRF) if   Creates an   is provided.', 'config_table': 'outputfileOrbit filename  planet planetType  timeSeries timeSeriesType  ephemerides ephemeridesType  earthRotation earthRotationType transform orbits into TRF', 'display_text': 'Creates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit file</a> of sun, moon, or planets. The orbit is given in the celestial reference frame (CRF) or alternatively in the terrestrial reference frame (TRF) if <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided.'},\n'PlotDegreeAmplitudes': { 'name': 'PlotDegreeAmplitudes', 'key': 'PlotDegreeAmplitudes', 'description': 'Plot degree amplitudes of potential coefficients computed by  Gravityfield2DegreeAmplitudes  or  PotentialCoefficients2DegreeAmplitudes  using the GMT Generic Mapping Tools ( https://www.generic-mapping-tools.org ). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of  outputfile . This is a convenience program with meaningful default values. The same plots can be generated with the more general  PlotGraph .', 'config_table': 'outputfile filename *.png, *.jpg, *.eps, ... title string  layer plotGraphLayerType  minDegree uint  maxDegree uint  majorTickSpacingDegree double boundary annotation minorTickSpacingDegree double frame tick spacing gridLineSpacingDegree double gridline spacing labelDegree string description of the x-axis logarithmicDegree boolean use logarithmic scale for the x-axis minY double  maxY double  majorTickSpacingY double boundary annotation minorTickSpacingY double frame tick spacing gridLineSpacingY double gridline spacing unitY string appended to axis values labelY string description of the y-axis logarithmicY boolean use logarithmic scale for the y-axis gridLine plotLineType The style of the grid lines. legend plotLegendType  options sequence further options... width double in cm height double in cm titleFontSize uint in pt marginTitle double between title and figure [cm] drawGridOnTop boolean grid lines above all other lines/points options string  transparent boolean make background transparent dpi uint use this resolution when rasterizing postscript file removeFiles boolean remove .gmt and script files', 'display_text': 'Plot degree amplitudes of potential coefficients computed by <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a> or <a class=\"groops-program\" href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a> using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>. This is a convenience program with meaningful default values. The same plots can be generated with the more general <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.</p><p>'},\n'PlotGraph': { 'name': 'PlotGraph', 'key': 'PlotGraph', 'description': 'Generates a two dimensional xy plot using the GMT Generic Mapping Tools ( https://www.generic-mapping-tools.org ). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of  outputfile . The plotting area is defined by the two axes   Generates a two dimensional xy plot using the GMT Generic Mapping Tools ( . An alternative   Generates a two dimensional xy plot using the GMT Generic Mapping Tools (  on the right hand side can be added. The content of the graph itself is defined by one or more   Generates a two dimensional xy plot using the GMT Generic Mapping Tools ( s. The plot programs create a temporary directory in the path of  outputfile , writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting  options:removeFiles =false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with  options:options =\" FORMAT=value \", see  https://docs.generic-mapping-tools.org/latest/gmt.conf.html . See also:  PlotDegreeAmplitudes ,  PlotMap ,  PlotMatrix ,  PlotSphericalHarmonicsTriangle .', 'config_table': 'outputfile filename *.png, *.jpg, *.eps, ... title string  layer plotGraphLayerType  axisX plotAxisType  axisY plotAxisType  axisY2 plotAxisType Second y-axis on right hand side colorbar plotColorbarType  legend plotLegendType  options sequence further options... width double in cm height double in cm titleFontSize uint in pt marginTitle double between title and figure [cm] drawGridOnTop boolean grid lines above all other lines/points options string  transparent boolean make background transparent dpi uint use this resolution when rasterizing postscript file removeFiles boolean remove .gmt and script files', 'display_text': 'Generates a two dimensional xy plot using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The plotting area is defined by the two axes <a class=\"groops-class\" href=\"plotAxisType.html\">axisX/Y</a>. An alternative <a class=\"groops-class\" href=\"plotAxisType.html\">axisY2</a> on the right hand side can be added. The content of the graph itself is defined by one or more <a class=\"groops-class\" href=\"plotGraphLayerType.html\">layer</a>s.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\", see <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p>See also: <a class=\"groops-program\" href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a>, <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.'},\n'PlotMap': { 'name': 'PlotMap', 'key': 'PlotMap', 'description': 'Generates a map using the GMT Generic Mapping Tools ( https://www.generic-mapping-tools.org ). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of  outputfile . The base map is defined by a   Generates a map using the GMT Generic Mapping Tools (  of an ellipsoid ( R ,  inverseFlattening ). The content of the map itself is defined by one or more   Generates a map using the GMT Generic Mapping Tools ( s. The plot programs create a temporary directory in the path of  outputfile , writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting  options:removeFiles =false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with  options:options =\" FORMAT=value \", see  https://docs.generic-mapping-tools.org/latest/gmt.conf.html . See also:  PlotDegreeAmplitudes ,  PlotGraph ,  PlotMatrix ,  PlotSphericalHarmonicsTriangle .', 'config_table': 'outputfile filename *.png, *.jpg, *.eps, ... title string  statisticInfos boolean  layer plotMapLayerType  R double reference radius for ellipsoidal coordinates on output inverseFlattening double reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates minLambda angle min. longitude (default: compute from input data) maxLambda angle max. longitude (default: compute from input data) minPhi angle min. latitude (default: compute from input data) maxPhi angle max. latitude (default: compute from input data) majorTickSpacing angle boundary annotation minorTickSpacing angle frame tick spacing gridLineSpacing angle gridline spacing colorbar plotColorbarType  projection plotMapProjectionType map projection options sequence further options... width double in cm height double in cm titleFontSize uint in pt marginTitle double between title and figure [cm] drawGridOnTop boolean grid lines above all other lines/points options string  transparent boolean make background transparent dpi uint use this resolution when rasterizing postscript file removeFiles boolean remove .gmt and script files', 'display_text': 'Generates a map using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The base map is defined by a <a class=\"groops-class\" href=\"plotMapProjectionType.html\">projection</a> of an ellipsoid (<strong class=\"groops-config-element\">R</strong>, <strong class=\"groops-config-element\">inverseFlattening</strong>). The content of the map itself is defined by one or more <a class=\"groops-class\" href=\"plotMapLayerType.html\">layer</a>s.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\", see <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p>See also: <a class=\"groops-program\" href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a>, <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.</p><p>'},\n'PlotMatrix': { 'name': 'PlotMatrix', 'key': 'PlotMatrix', 'description': 'Plot the coefficients of a   Plot the coefficients of a   using the GMT Generic Mapping Tools ( https://www.generic-mapping-tools.org ). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of  outputfile . The plot programs create a temporary directory in the path of  outputfile , writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting  options:removeFiles =false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with  options:options =\" FORMAT=value \", see  https://docs.generic-mapping-tools.org/latest/gmt.conf.html .', 'config_table': 'outputfile filename *.png, *.jpg, *.eps, ... title string  inputfileMatrix filename  minColumn uint minimum column index to plot maxColumn uint maximum column index to plot majorTickSpacingX double boundary annotation minorTickSpacingX double frame tick spacing gridLineSpacingX double gridline spacing minRow uint minimum row index to plot maxRow uint maximum row index to plot majorTickSpacingY double boundary annotation minorTickSpacingY double frame tick spacing gridLineSpacingY double gridline spacing gridLine plotLineType The style of the grid lines. colorbar plotColorbarType  options sequence further options... width double in cm height double in cm titleFontSize uint in pt marginTitle double between title and figure [cm] drawGridOnTop boolean grid lines above all other lines/points options string  transparent boolean make background transparent dpi uint use this resolution when rasterizing postscript file removeFiles boolean remove .gmt and script files', 'display_text': 'Plot the coefficients of a <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a> using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\", see <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p>'},\n'PlotSphericalHarmonicsTriangle': { 'name': 'PlotSphericalHarmonicsTriangle', 'key': 'PlotSphericalHarmonicsTriangle', 'description': 'Plot the potential coefficients of a spherical harmonic expansion using the GMT Generic Mapping Tools ( https://www.generic-mapping-tools.org ). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of  outputfile . This program plots the formal errors (sigmas). If   Plot the potential coefficients of a spherical harmonic expansion using the GMT Generic Mapping Tools (  provides no sigmas e.g. with  setSigmasToZero  in   Plot the potential coefficients of a spherical harmonic expansion using the GMT Generic Mapping Tools (  the coefficients itself are plotted instead. The plot programs create a temporary directory in the path of  outputfile , writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting  options:removeFiles =false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with  options:options =\" FORMAT=value \", see  https://docs.generic-mapping-tools.org/latest/gmt.conf.html .', 'config_table': 'outputfile filename *.png, *.jpg, *.eps, ... title string  gravityfield gravityfieldType use sigmas, if not given use signal (cnm,snm) time time at this time the gravity field will be evaluated minDegree uint  maxDegree uint  majorTickSpacing double boundary annotation minorTickSpacing double frame tick spacing gridLineSpacing double gridline spacing gridLine plotLineType The style of the grid lines. colorbar plotColorbarType  options sequence further options... width double in cm height double in cm titleFontSize uint in pt marginTitle double between title and figure [cm] drawGridOnTop boolean grid lines above all other lines/points options string  transparent boolean make background transparent dpi uint use this resolution when rasterizing postscript file removeFiles boolean remove .gmt and script files', 'display_text': 'Plot the potential coefficients of a spherical harmonic expansion using the GMT Generic Mapping Tools (<a href=\"https://www.generic-mapping-tools.org\" target=\"_blank\">https://www.generic-mapping-tools.org</a>). A variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of <strong class=\"groops-config-element\">outputfile</strong>.</p><p>This program plots the formal errors (sigmas). If <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> provides no sigmas e.g. with <strong class=\"groops-config-element\">setSigmasToZero</strong> in <a class=\"groops-class\" href=\"gravityfieldType.html#potentialCoefficients\">gravityfield:potentialCoefficients</a> the coefficients itself are plotted instead.</p><p>The plot programs create a temporary directory in the path of <strong class=\"groops-config-element\">outputfile</strong>, writes all needed data into it, generates a batch/shell script with the GMT commands, execute it, and remove the temporary directory. With setting <strong class=\"groops-config-element\">options:removeFiles</strong>=false the last step is skipped and it is possible to adjust the plot manually to specific publication needs. Individual GMT settings are adjusted with <strong class=\"groops-config-element\">options:options</strong>=\"<code>FORMAT=value</code>\", see <a href=\"https://docs.generic-mapping-tools.org/latest/gmt.conf.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/gmt.conf.html</a>.</p><p>'},\n'PreprocessingDualSst': { 'name': 'PreprocessingDualSst', 'key': 'PreprocessingDualSst', 'description': 'This programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration. Four different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites. This program works similar to  PreprocessingSst , see there for details. Here only the settings explained, which are different. Both SST observation types are reduced by the same background models and the same impact of accelerometer measurements. The covariance matrix of the reduced observations should not consider the the instrument noise only (  This programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration. Four different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites. This program works similar to  ) but must take the cross correlations   This programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration. Four different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites. This program works similar to   into account. The covariance matrix of the reduced observations is given by', 'config_table': 'outputfileSolution filename estimated parameter vector (static part only) outputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) outputfileParameterName filename estimated signal parameters (index is appended) estimateArcSigmas sequence  outputfileSigmasPerArcSst1 filename accuracies of each arc (SST1) outputfileSigmasPerArcSst2 filename accuracies of each arc (SST2) outputfileSigmasPerArcAcc filename accuracies of each arc (ACC) outputfileSigmasPerArcPod1 filename accuracies of each arc (POD1) outputfileSigmasPerArcPod2 filename accuracies of each arc (POD2) estimateEpochSigmas sequence  outputfileSigmasPerEpochSst1 filename accuracies of each epoch (SST1) outputfileSigmasPerEpochSst2 filename accuracies of each epoch (SST2) outputfileSigmasPerEpochAcc filename accuracies of each epoch (ACC) outputfileSigmasPerEpochPod1 filename accuracies of each epoch (POD1) outputfileSigmasPerEpochPod2 filename accuracies of each epoch (POD2) estimateCovarianceFunctions sequence  outputfileCovarianceFunctionSst1 filename covariance function outputfileCovarianceFunctionSst2 filename covariance function outputfileCovarianceFunctionAcc filename covariance function outputfileCovarianceFunctionPod1 filename covariance functions for along, cross, radial direction outputfileCovarianceFunctionPod2 filename covariance functions for along, cross, radial direction computeResiduals sequence  outputfileSst1Residuals filename  outputfileSst2Residuals filename  outputfileAccResiduals filename  outputfilePod1Residuals filename  outputfilePod2Residuals filename  observation choice obervation equations (Sst) dualSstVariational sequence two SST observations rightHandSide sequence input for observation vectors inputfileSatelliteTracking1 filename ranging observations and corrections inputfileSatelliteTracking2 filename ranging observations and corrections inputfileOrbit1 filename kinematic positions of satellite A as observations inputfileOrbit2 filename kinematic positions of satellite B as observations sstType choice  range   rangeRate   none   inputfileVariational1 filename approximate position and integrated state matrix inputfileVariational2 filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst1 parametrizationSatelliteTrackingType satellite tracking parameter for first ranging observations parametrizationSst2 parametrizationSatelliteTrackingType satellite tracking parameter for second ranging observations integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n covarianceSst1 sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovarianceMatrixArc filename Must be given per sst arc with correct dimensions. inputfileSigmasCovarianceMatrixArc filename Vector with one sigma for each <inputfileCovarianceMatrixArc> sampling double [seconds] sampling of the covariance function covarianceSst2 sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovarianceMatrixArc filename Must be given per sst arc with correct dimensions. inputfileSigmasCovarianceMatrixArc filename Vector with one sigma for each <inputfileCovarianceMatrixArc> sampling double [seconds] sampling of the covariance function covarianceAcc sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovarianceMatrixArc filename Must be given per sst arc with correct dimensions. inputfileSigmasCovarianceMatrixArc filename Vector with one sigma for each <inputfileCovarianceMatrixArc> sampling double [seconds] sampling of the covariance function covariancePod1 sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovariancePodEpoch filename 3x3 epoch covariances sampling double [seconds] sampling of the covariance function covariancePod2 sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovariancePodEpoch filename 3x3 epoch covariances sampling double [seconds] sampling of the covariance function estimateShortTimeVariations sequence co-estimate short time gravity field variations estimateSigma boolean estimate standard deviation via VCE autoregressiveModelSequence autoregressiveModelSequenceType AR model sequence for constraining short time gravity variations parameterSelection parameterSelectorType parameters describing the short time gravity field downweightPod double downweight factor for POD inputfileArcList filename list to correspond points of time to arc numbers iterationCount uint (maximum) number of iterations for the estimation of calibration parameter and error PSD variableNameIterations string All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk defaultBlockSize uint block size of static normal equation blocks', 'display_text': 'This programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration. Four different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites. This program works similar to <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a>, see there for details. Here only the settings explained, which are different.</p><p>Both SST observation types are reduced by the same background models and the same impact of accelerometer measurements. The covariance matrix of the reduced observations should not consider the the instrument noise only (<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst1/2</a>) but must take the cross correlations <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceAcc</a> into account. The covariance matrix of the reduced observations is given by \\\\[   \\\\M\\\\Sigma(\\\\begin{bmatrix} \\\\Delta l_{SST1} \\\\\\\\ \\\\Delta l_{SST2} \\\\end{bmatrix})   = \\\\begin{bmatrix} \\\\M\\\\Sigma_{SST1} + \\\\M\\\\Sigma_{ACC} & \\\\M\\\\Sigma_{ACC} \\\\\\\\                    \\\\M\\\\Sigma_{ACC} & \\\\M\\\\Sigma_{SST2} + \\\\M\\\\Sigma_{ACC}     \\\\end{bmatrix}. \\\\]'},\n'PreprocessingGradiometer': { 'name': 'PreprocessingGradiometer', 'key': 'PreprocessingGradiometer', 'description': 'This program estimates empirical covariance functions of the gradiometer instrument noise and determine arc wise variances to downweight arcs with outliers. This program works similar to  PreprocessingPod , see there for details. Here only the settings explained, which are different. ...', 'config_table': 'outputfileCovarianceFunction filename  outputfileSigmasPerArc filename accuracies of each arc outputfileSggResiduals filename  rightHandSide sggRightSideType input for the observation vector inputfileOrbit filename  inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  parametrizationBias parametrizationTemporalType per arc covarianceSgg sequence  inputfileCovarianceFunction filename approximate covariances in time covarianceLength uint counts observation epochs sampling double [seconds] sampling of the covariance function iterationCount uint for the estimation of calibration parameter and error PSD', 'display_text': 'This program estimates empirical covariance functions of the gradiometer instrument noise and determine arc wise variances to downweight arcs with outliers. This program works similar to <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>, see there for details. Here only the settings explained, which are different.</p><p>...'},\n'PreprocessingPod': { 'name': 'PreprocessingPod', 'key': 'PreprocessingPod', 'description': 'This program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to downweight arcs with outliers. A complete least squares adjustment for gravity field determination is performed by computing the  observation  equations, see   This program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to downweight arcs with outliers.  or   This program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to downweight arcs with outliers.  for details. The normal equations are accumulated and solved to   This program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to downweight arcs with outliers.  together with the estimated accuracies   This program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to downweight arcs with outliers. . The estimated residuals   can be computed with  computeResiduals . For each component (along, cross, radial) of the kinematic orbit positions a noise covariance function is estimated  The covariance matrix is composed of the sum of matrices   and unknown variance factors  with the cosine transformation matrices   An additional variance factor can be computed ( estimateArcSigmas ) for each arc    according to  where   is the redundancy. This variance factor should be around one for normally behaving arcs as the noise characteristics are already considered by the covariance matrix but bad arcs get a much larger variance. By applying this factor bad arcs or arcs with large outliers are downweighted.', 'config_table': 'outputfileSolution filename estimated parameter vector (static part only) outputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) outputfileParameterName filename names of estimated parameters (static part only) estimateArcSigmas sequence  outputfileSigmasPerArcPod filename accuracies of each arc (POD2) estimateCovarianceFunctions sequence  outputfileCovarianceFunctionPod filename covariance functions for along, cross, radial direction computeResiduals sequence  outputfilePodResiduals filename  observation choice obervation equations (POD) podIntegral sequence precise orbit data (integral approach) inputfileSatelliteModel filename satellite macro model rightHandSide podRightSideType input for the reduced observation vector inputfileOrbit filename used to evaluate the observation equations, not used as observations inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  gradientfield gravityfieldType low order field to estimate the change of the gravity by position adjustement parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration parametrizationAccelerationType orbit force parameters keepSatelliteStates boolean set boundary values of each arc global integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n accelerateComputation boolean acceleration of computation by transforming the observations podVariational sequence precise orbit data (variational equations) rightHandSide sequence input for observation vectors inputfileOrbit filename kinematic positions as observations inputfileVariational filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration parametrizationAccelerationType orbit force parameters integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n accelerateComputation boolean acceleration of computation by transforming the observations covariancePod sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuracies for each arc (multiplied with sigma) inputfileCovarianceFunction filename approximate covariances in time inputfileCovariancePodEpoch filename 3x3 epoch covariances sampling double [seconds] sampling of the covariance function inputfileArcList filename list to correspond points of time to arc numbers adjustmentThreshold double Adjustment factor threshold: Iteration will be stopped once both SST and POD adjustment factors are under this threshold iterationCount uint (maximum) number of iterations for the estimation of calibration parameters and error PSD', 'display_text': 'This program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to downweight arcs with outliers.</p><p>A complete least squares adjustment for gravity field determination is performed by computing the <strong class=\"groops-config-element\">observation</strong> equations, see <a class=\"groops-class\" href=\"observationType.html#podIntegral\">observation:podIntegral</a> or <a class=\"groops-class\" href=\"observationType.html#podVariational\">observation:podVariational</a> for details. The normal equations are accumulated and solved to <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> together with the estimated accuracies <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSigmax</a>. The estimated residuals $\\\\hat{\\\\M e}=\\\\M l-\\\\M A\\\\hat{\\\\M x}$ can be computed with <strong class=\"groops-config-element\">computeResiduals</strong>.</p><p>For each component (along, cross, radial) of the kinematic orbit positions a noise covariance function is estimated \\\\[   \\\\text{cov}(\\\\Delta t_i) = \\\\sum_{n=0}^{N-1} a_n^2 \\\\cos\\\\left(\\\\frac{\\\\pi}{T} n\\\\Delta t_i\\\\right). \\\\]The covariance matrix is composed of the sum of matrices $F_n$ and unknown variance factors \\\\[   \\\\M\\\\Sigma = a_1^2\\\\M F_1 + a_2^2 \\\\M F_2 + \\\\cdots + a_N^2\\\\M F_N, \\\\]with the cosine transformation matrices \\\\[   \\\\M F_n = \\\\left(\\\\cos\\\\left(\\\\frac{\\\\pi}{T} n(t_i-t_k)\\\\right)\\\\right)_{ik}. \\\\] An additional variance factor can be computed (<strong class=\"groops-config-element\">estimateArcSigmas</strong>) for each arc $k$  according to \\\\[   \\\\hat{\\\\sigma}_k^2 = \\\\frac{\\\\hat{\\\\M e}_k^T\\\\M\\\\Sigma^{-1}\\\\hat{\\\\M e}_k}{r_k}, \\\\]where $r_k$ is the redundancy. This variance factor should be around one for normally behaving arcs as the noise characteristics are already considered by the covariance matrix but bad arcs get a much larger variance. By applying this factor bad arcs or arcs with large outliers are downweighted.'},\n'PreprocessingSst': { 'name': 'PreprocessingSst', 'key': 'PreprocessingSst', 'description': 'This program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration. Three different observation groups are considered separately: SST and POD1/POD2 for the two satellites. This program works similar to  PreprocessingPod , see there for details. Here only deviations in the settings are explained. Precise orbit data (POD) often contains systematic errors in addition to stochastic noise. In this case the variance component estimation fails and assigns too much weight to the POD data. Therefore an additional  downweightPod  factor can be applied to the standard deviation of POD for the next least squares adjustment in the iteration. This factor should also applied as  sigma  in   This program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration. Three different observation groups are considered separately: SST and POD1/POD2 for the two satellites. This program works similar to   for computation of the final solution e.g. with  NormalsSolverVCE . Short time variations of the gravity field can be co-estimated together with the static/monthly mean gravity field. The short time parameters must also be set in   This program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration. Three different observation groups are considered separately: SST and POD1/POD2 for the two satellites. This program works similar to   and can then be selected by   This program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration. Three different observation groups are considered separately: SST and POD1/POD2 for the two satellites. This program works similar to  . If these parameters are not time variable, for example when a range of static parameters is selected, they are set up as constant for each time interval defined in  inputfileArcList . The parameters are constrained by an   This program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration. Three different observation groups are considered separately: SST and POD1/POD2 for the two satellites. This program works similar to  . The weight of the constrain equations in terms of the standard deviation can be estimated by means of Variance Component Estimation (VCE) if  estimateShortTimeVariations:estimateSigma  is set. The mathematical background of this co-estimation can be found in: Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties. J Geod 93, 2543–2552 (2019).  https://doi.org/10.1007/s00190-019-01314-1 .', 'config_table': 'outputfileSolution filename estimated parameter vector (static part only) outputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) outputfileParameterName filename estimated signal parameters (index is appended) estimateArcSigmas sequence  outputfileSigmasPerArcSst filename accuracies of each arc (SST) outputfileSigmasPerArcPod1 filename accuracies of each arc (POD1) outputfileSigmasPerArcPod2 filename accuracies of each arc (POD2) estimateEpochSigmas sequence  outputfileSigmasPerEpochSst filename accuracies of each epoch (SST) outputfileSigmasPerEpochPod1 filename accuracies of each epoch (POD1) outputfileSigmasPerEpochPod2 filename accuracies of each epoch (POD2) estimateCovarianceFunctions sequence  outputfileCovarianceFunctionSst filename covariance function outputfileCovarianceFunctionPod1 filename covariance functions for along, cross, radial direction outputfileCovarianceFunctionPod2 filename covariance functions for along, cross, radial direction estimateSstArcCovarianceSigmas sequence  outputfileSigmasCovarianceMatrixArc filename one variance factor per matrix computeResiduals sequence  outputfileSstResiduals filename  outputfilePod1Residuals filename  outputfilePod2Residuals filename  observation choice obervation equations (Sst) sstIntegral sequence integral approach inputfileSatelliteModel1 filename satellite macro model inputfileSatelliteModel2 filename satellite macro model rightHandSide sstRightSideType input for the reduced observation vector sstType choice  range   rangeRate   rangeAcceleration   none   inputfileOrbit1 filename used to evaluate the observation equations, not used as observations inputfileOrbit2 filename used to evaluate the observation equations, not used as observations inputfileStarCamera1 filename  inputfileStarCamera2 filename  earthRotation earthRotationType  ephemerides ephemeridesType  gradientfield gravityfieldType low order field to estimate the change of the gravity by position adjustement parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst parametrizationSatelliteTrackingType satellite tracking parameter keepSatelliteStates boolean set boundary values of each arc global integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n sstVariational sequence variational equations rightHandSide sequence input for observation vectors inputfileSatelliteTracking filename ranging observations and corrections inputfileOrbit1 filename kinematic positions of satellite A as observations inputfileOrbit2 filename kinematic positions of satellite B as observations sstType choice  range   rangeRate   none   inputfileVariational1 filename approximate position and integrated state matrix inputfileVariational2 filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst parametrizationSatelliteTrackingType satellite tracking parameter integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n covarianceSst sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovarianceMatrixArc filename Must be given per sst arc with correct dimensions. inputfileSigmasCovarianceMatrixArc filename Vector with one sigma for each <inputfileCovarianceMatrixArc> sampling double [seconds] sampling of the covariance function covariancePod1 sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovariancePodEpoch filename 3x3 epoch covariances sampling double [seconds] sampling of the covariance function covariancePod2 sequence  sigma double apriori factor of covariance function inputfileSigmasPerArc filename apriori different accuaries for each arc (multiplicated with sigma) inputfileSigmasPerEpoch filename apriori different accuaries for each epoch inputfileCovarianceFunction filename approximate covariances in time inputfileCovariancePodEpoch filename 3x3 epoch covariances sampling double [seconds] sampling of the covariance function estimateShortTimeVariations sequence co-estimate short time gravity field variations estimateSigma boolean estimate standard deviation via VCE autoregressiveModelSequence autoregressiveModelSequenceType AR model sequence for constraining short time gravity variations parameterSelection parameterSelectorType parameters describing the short time gravity field downweightPod double downweight factor for POD inputfileArcList filename list to correspond points of time to arc numbers iterationCount uint (maximum) number of iterations for the estimation of calibration parameter and error PSD variableNameIterations string All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk defaultBlockSize uint block size of static normal equation blocks', 'display_text': 'This program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration. Three different observation groups are considered separately: SST and POD1/POD2 for the two satellites. This program works similar to <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>, see there for details. Here only deviations in the settings are explained.</p><p>Precise orbit data (POD) often contains systematic errors in addition to stochastic noise. In this case the variance component estimation fails and assigns too much weight to the POD data. Therefore an additional <strong class=\"groops-config-element\">downweightPod</strong> factor can be applied to the standard deviation of POD for the next least squares adjustment in the iteration. This factor should also applied as <strong class=\"groops-config-element\">sigma</strong> in <a class=\"groops-class\" href=\"observationType.html\">observation</a> for computation of the final solution e.g. with <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>.</p><p>Short time variations of the gravity field can be co-estimated together with the static/monthly mean gravity field. The short time parameters must also be set in <a class=\"groops-class\" href=\"parametrizationGravityType.html\">observation:parametrizationGravity</a> and can then be selected by <a class=\"groops-class\" href=\"parameterSelectorType.html\">estimateShortTimeVariations:parameterSelection</a>. If these parameters are not time variable, for example when a range of static parameters is selected, they are set up as constant for each time interval defined in <strong class=\"groops-config-element\">inputfileArcList</strong>. The parameters are constrained by an <a class=\"groops-class\" href=\"autoregressiveModelSequenceType.html\">estimateShortTimeVariations:autoregressiveModelSequence</a>. The weight of the constrain equations in terms of the standard deviation can be estimated by means of Variance Component Estimation (VCE) if <strong class=\"groops-config-element\">estimateShortTimeVariations:estimateSigma</strong> is set. The mathematical background of this co-estimation can be found in:</p><p>Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties. J Geod 93, 2543–2552 (2019). <a href=\"https://doi.org/10.1007/s00190-019-01314-1\" target=\"_blank\">https://doi.org/10.1007/s00190-019-01314-1</a>.'},\n'PreprocessingVariationalEquation': { 'name': 'PreprocessingVariationalEquation', 'key': 'PreprocessingVariationalEquation', 'description': 'This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by  . This means for each arc new initial state parameters are set up. In a first step the   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by   acting on the satellite are evaluated at the apriori positions given by   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by  . Non-conservative forces like solar radiation pressure need the orientation of the satellite (  This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by  ) and additionally, a satellite macro model ( satelliteModel ) with the surface properties. Furthermore   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by   observations are also considered. In a second step the accelerations are integrated twice to a dynamic orbit using a moving polynomial with the degree  integrationDegree . The orbit is corrected to be self-consistent. This means the forces should be evaluated at the new integrated positions instead of the apriori ones. This correction is computed in a linear approximation using the gradient of the forces with respect to the positions ( gradientfield ). As this term is small generally only the largest force components have to be considered. A low degree spherical harmonic expansion of the static gravity field (about up to degree 5) is sufficient in almost all cases. In this step also the state transition matrix (the partial derivatives of the current state, position and velocity) with respect to the initial state is computed. The integrated orbit together with the state transitions are stored in   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by  , the integrated orbit only in   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by  . To improve the numerical stability a reference ellipse can be reduced beforehand using Enke\\'s method ( useEnke ). Mathematically the result is the same, but as the large central term is removed before and restored afterwards more digits are available for the computation. The integrated orbit should be fitted to observations afterwards by the programs  PreprocessingVariationalEquationOrbitFit  and/or  PreprocessingVariationalEquationSstFit . They apply a least squares adjustment by estimating some satellite parameters (e.g. an accelerometer bias). If the fitted orbit is too far away from the original   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by   the linearization may not be accurate enough. In this case  PreprocessingVariationalEquation  should be run again with the fitted orbit as   This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by   and introducing the  estimatedParameters  as additional forces.', 'config_table': 'outputfileVariational filename approximate position and integrated state matrix outputfileOrbit filename integrated orbit inputfileSatelliteModel filename satellite macro model inputfileOrbit filename approximate position, used to evaluate the force inputfileStarCamera filename rotation from body frame to CRF inputfileAccelerometer filename non-gravitational forces in satellite reference frame forces forcesType  estimatedParameters sequence satellite parameters e.g. from orbit fit parametrizationAcceleration parametrizationAccelerationType orbit force parameters inputfileParameter filename estimated orbit force parameters earthRotation earthRotationType  ephemerides ephemeridesType  gradientfield gravityfieldType low order field to estimate the change of the gravity by position adjustement integrationDegree uint integration of forces by polynomial approximation of degree n useEnke sequence integrate differential forces to an elliptical reference trajectory GM double geocentric gravitational constant used for elliptical reference orbit', 'display_text': 'This program integrates an orbit dynamically using the given forces and set up the state transition matrix for each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using the variational equation approach. The variational equations are computed arc-wise as defined by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. This means for each arc new initial state parameters are set up.</p><p>In a first step the <a class=\"groops-class\" href=\"forcesType.html\">forces</a> acting on the satellite are evaluated at the apriori positions given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. Non-conservative forces like solar radiation pressure need the orientation of the satellite (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>) and additionally, a satellite macro model (<strong class=\"groops-config-element\">satelliteModel</strong>) with the surface properties. Furthermore <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> observations are also considered.</p><p>In a second step the accelerations are integrated twice to a dynamic orbit using a moving polynomial with the degree <strong class=\"groops-config-element\">integrationDegree</strong>. The orbit is corrected to be self-consistent. This means the forces should be evaluated at the new integrated positions instead of the apriori ones. This correction is computed in a linear approximation using the gradient of the forces with respect to the positions (<strong class=\"groops-config-element\">gradientfield</strong>). As this term is small generally only the largest force components have to be considered. A low degree spherical harmonic expansion of the static gravity field (about up to degree 5) is sufficient in almost all cases. In this step also the state transition matrix (the partial derivatives of the current state, position and velocity) with respect to the initial state is computed. The integrated orbit together with the state transitions are stored in <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">outputfileVariational</a>, the integrated orbit only in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>.</p><p>To improve the numerical stability a reference ellipse can be reduced beforehand using Enke\\'s method (<strong class=\"groops-config-element\">useEnke</strong>). Mathematically the result is the same, but as the large central term is removed before and restored afterwards more digits are available for the computation.</p><p>The integrated orbit should be fitted to observations afterwards by the programs <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a> and/or <a class=\"groops-program\" href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a>. They apply a least squares adjustment by estimating some satellite parameters (e.g. an accelerometer bias). If the fitted orbit is too far away from the original <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> the linearization may not be accurate enough. In this case <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a> should be run again with the fitted orbit as <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> and introducing the <strong class=\"groops-config-element\">estimatedParameters</strong> as additional forces.'},\n'PreprocessingVariationalEquationOrbitFit': { 'name': 'PreprocessingVariationalEquationOrbitFit', 'key': 'PreprocessingVariationalEquationOrbitFit', 'description': 'This program fits an   This program fits an   to an observed   This program fits an   by estimating parameters in a least squares adjustment. Additional to the initial satellite state for each arc, these parameters can be   This program fits an  , satellite   This program fits an   and stochastic pulses (velocity jumps) at given times,   This program fits an  . The estimated parameters can be stored with   This program fits an   and an extra file with the parameter names is created. The fitted orbit is written as new reference in   This program fits an   and additionally in   This program fits an  . The observed orbit positions (  This program fits an  ) together with the epoch-wise covariance matrix (  This program fits an  ) must be split in the same arcs as the variational equations but not necessarily uniformly distributed (use irregularData in  InstrumentSynchronize ). An iterative downweighting of outliers is performed by M-Huber method. The observation equations (parameter sensitivity matrix) are computed by integration of the variational equations (  This program fits an  ) using a polynomial with  integrationDegree  and interpolated to the observation epochs using a polynomial with  interpolationDegree . All parameters used here must be reestimated in the full least squares adjustment for the gravity field determination to get a solution which is not biased towards the reference field. The solutions of additional estimations are relative (deltas) as the parameters are already used as Taylor point in the reference orbit. See also  PreprocessingVariationalEquation .', 'config_table': 'outputfileVariational filename approximate position and integrated state matrix outputfileOrbit filename integrated orbit outputfileSolution filename estimated calibration and state parameters inputfileVariational filename approximate position and integrated state matrix inputfileOrbit filename kinematic positions of satellite as observations inputfileCovariancePodEpoch filename 3x3 epoch wise covariances ephemerides ephemeridesType may be needed by parametrizationAcceleration parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration parametrizationAccelerationType orbit force parameters stochasticPulse timeSeriesType  integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n iterationCount uint for the estimation of calibration parameter and error PSD', 'display_text': 'This program fits an <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> to an observed <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> by estimating parameters in a least squares adjustment. Additional to the initial satellite state for each arc, these parameters can be <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>, satellite <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> and stochastic pulses (velocity jumps) at given times, <a class=\"groops-class\" href=\"timeSeriesType.html\">stochasticPulse</a>. The estimated parameters can be stored with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileSolution</a> and an extra file with the parameter names is created. The fitted orbit is written as new reference in <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">outputfileVariational</a> and additionally in <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a>.</p><p>The observed orbit positions (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>) together with the epoch-wise covariance matrix (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a>) must be split in the same arcs as the variational equations but not necessarily uniformly distributed (use irregularData in <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>). An iterative downweighting of outliers is performed by M-Huber method.</p><p>The observation equations (parameter sensitivity matrix) are computed by integration of the variational equations (<a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a>) using a polynomial with <strong class=\"groops-config-element\">integrationDegree</strong> and interpolated to the observation epochs using a polynomial with <strong class=\"groops-config-element\">interpolationDegree</strong>.</p><p>All parameters used here must be reestimated in the full least squares adjustment for the gravity field determination to get a solution which is not biased towards the reference field. The solutions of additional estimations are relative (deltas) as the parameters are already used as Taylor point in the reference orbit.</p><p>See also <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.'},\n'PreprocessingVariationalEquationSstFit': { 'name': 'PreprocessingVariationalEquationSstFit', 'key': 'PreprocessingVariationalEquationSstFit', 'description': 'This program fits two   This program fits two   to satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration. It works similar to  PreprocessingVariationalEquationOrbitFit , see there for details. As the relative weighting of the observation types is important complex description of the covariances can be set with   This program fits two  ,   This program fits two  ,   This program fits two  .', 'config_table': 'outputfileVariational1 filename approximate position and integrated state matrix outputfileVariational2 filename approximate position and integrated state matrix outputfileOrbit1 filename integrated orbit outputfileOrbit2 filename integrated orbit outputfileSolution1 filename estimated calibration and state parameters outputfileSolution2 filename estimated calibration and state parameters rightHandSide sequence input for observation vectors inputfileSatelliteTracking filename ranging observations and corrections inputfileOrbit1 filename kinematic positions of satellite A as observations inputfileOrbit2 filename kinematic positions of satellite B as observations sstType choice  range   rangeRate   none   inputfileVariational1 filename approximate position and integrated state matrix inputfileVariational2 filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst parametrizationSatelliteTrackingType satellite tracking parameter integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n covarianceSst covarianceSstType covariance matrix of satellite to satellite tracking observations covariancePod1 covariancePodType covariance matrix of kinematic orbits (satellite 1) covariancePod2 covariancePodType covariance matrix of kinematic orbits (satellite 2) iterationCount uint for the estimation of calibration parameter and error PSD', 'display_text': 'This program fits two <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational1/2</a> to satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration. It works similar to <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>, see there for details.</p><p>As the relative weighting of the observation types is important complex description of the covariances can be set with <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>, <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod1</a>, <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod2</a>.'},\n'NoiseAccelerometer': { 'name': 'NoiseAccelerometer', 'key': 'NoiseAccelerometer', 'description': 'This program adds noise and biases to simulated  accelerometer data  generated by  SimulateAccelerometer . See   This program adds noise and biases to simulated   for details on noise generation.', 'config_table': 'outputfileAccelerometer filename  inputfileAccelerometer filename  biasAlong double [m/s**2] biasCross double [m/s**2] biasRadial double [m/s**2] noiseAlong noiseGeneratorType [m/s**2] noiseCross noiseGeneratorType [m/s**2] noiseRadial noiseGeneratorType [m/s**2]', 'display_text': 'This program adds noise and biases to simulated <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a> generated by <a class=\"groops-program\" href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a>. See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.'},\n'NoiseGriddedData': { 'name': 'NoiseGriddedData', 'key': 'NoiseGriddedData', 'description': 'This program adds noise to  gridded data data . See   This program adds noise to   for details on noise generation.', 'config_table': 'outputfileGriddedData filename  inputfileGriddedData filename  noise noiseGeneratorType  startDataFields uint start countDataFields uint number of data fields (default: all after start)', 'display_text': 'This program adds noise to <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data data</a>. See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.'},\n'NoiseInstrument': { 'name': 'NoiseInstrument', 'key': 'NoiseInstrument', 'description': 'This program adds noise to  instrument data . See   This program adds noise to   for details on noise generation.', 'config_table': 'outputfileInstrument filename  inputfileInstrument filename  noise noiseGeneratorType  startDataFields uint start countDataFields uint number of data fields (default: all after start)', 'display_text': 'This program adds noise to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument data</a>. See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.'},\n'NoiseNormalsSolution': { 'name': 'NoiseNormalsSolution', 'key': 'NoiseNormalsSolution', 'description': 'The inverse of the normal matrix of   The inverse of the normal matrix of   represents the covariance matrix of the estimated parameters. This program generates a noise vector with  if generated input noise is standard white noise. The noise vector is computed with  where   is the generated   The inverse of the normal matrix of   and   is the cholesky upper triangle matrix of the normal matrix  .', 'config_table': 'outputfileNoise filename generated noise as matrix: parameterCount x sampleCount inputfileNormalEquation filename  noise noiseGeneratorType  sampleCount uint number of samples to be generated useEigenvalueDecomposition boolean use eigenvalue decomposition', 'display_text': 'The inverse of the normal matrix of <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> represents the covariance matrix of the estimated parameters. This program generates a noise vector with \\\\[ \\\\M\\\\Sigma(\\\\M e) = \\\\M N^{-1}, \\\\]if generated input noise is standard white noise.</p><p>The noise vector is computed with \\\\[ \\\\M e = \\\\M W^{-T} \\\\M z, \\\\]where $\\\\M z$ is the generated <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noise</a> and $\\\\M W$ is the cholesky upper triangle matrix of the normal matrix $\\\\M N=\\\\M W^T\\\\M W$.'},\n'NoiseOrbit': { 'name': 'NoiseOrbit', 'key': 'NoiseOrbit', 'description': 'This program adds noise to simulated  satellite \\'s positions and velocities generated by  SimulateOrbit  (along, cross, radial). See   This program adds noise to simulated   for details on noise options.', 'config_table': 'outputfileOrbit filename  inputfileOrbit filename  noisePosition noiseGeneratorType along, cross, radial [m] noiseVelocity noiseGeneratorType along, cross, radial [m/s]', 'display_text': 'This program adds noise to simulated <a class=\"groops-file\" href=\"fileFormat_instrument.html\">satellite</a>\\'s positions and velocities generated by <a class=\"groops-program\" href=\"SimulateOrbit.html\">SimulateOrbit</a> (along, cross, radial). See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise options.'},\n'NoiseSatelliteTracking': { 'name': 'NoiseSatelliteTracking', 'key': 'NoiseSatelliteTracking', 'description': 'This program adds noise to simulated satellite tracking data generated by  SimulateSatelliteTracking . See   This program adds noise to simulated satellite tracking data generated by   for details on noise generation.', 'config_table': 'outputfileSatelliteTracking filename  inputfileSatelliteTracking filename  noiseRange noiseGeneratorType [m] noiseRangeRate noiseGeneratorType [m/s] noiseRangeAcceleration noiseGeneratorType [m/s^2]', 'display_text': 'This program adds noise to simulated satellite tracking data generated by <a class=\"groops-program\" href=\"SimulateSatelliteTracking.html\">SimulateSatelliteTracking</a>. See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise generation.'},\n'NoiseStarCamera': { 'name': 'NoiseStarCamera', 'key': 'NoiseStarCamera', 'description': 'This program adds noise to rotation observations. The noise is computed via a pseudo random sequence. See   This program adds noise to rotation observations. The noise is computed via a pseudo random sequence. See   for details on noise options.', 'config_table': 'outputfileStarCamera filename  inputfileStarCamera filename  noiseRoll noiseGeneratorType [rad] noisePitch noiseGeneratorType [rad] noiseYaw noiseGeneratorType [rad]', 'display_text': 'This program adds noise to rotation observations. The noise is computed via a pseudo random sequence. See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise options.'},\n'NoiseTimeSeries': { 'name': 'NoiseTimeSeries', 'key': 'NoiseTimeSeries', 'description': 'This program generates   This program generates   with the requested characteristics. See   This program generates   for details on noise options.', 'config_table': 'outputfileNoise filename  outputfileCovarianceFunction filename  noise noiseGeneratorType  timeSeries timeSeriesType  columns uint number of noise series (columns)', 'display_text': 'This program generates <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileNoise</a> with the requested characteristics. See <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noiseGenerator</a> for details on noise options.'},\n'SimulateAccelerometer': { 'name': 'SimulateAccelerometer', 'key': 'SimulateAccelerometer', 'description': 'This program simulate  accelerometer data . The orientation of the accelerometer is given by   This program simulate   otherwise the celestial reference frame (CRF) is used. For computation of non-conservative forces a   This program simulate   is needed.', 'config_table': 'outputfileAccelerometer filename  inputfileSatelliteModel filename satellite macro model inputfileOrbit filename  inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  forces forcesType', 'display_text': 'This program simulate <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer data</a>. The orientation of the accelerometer is given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> otherwise the celestial reference frame (CRF) is used. For computation of non-conservative forces a <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">satelliteModel</a> is needed.'},\n'SimulateAccelerometerCoMOffset': { 'name': 'SimulateAccelerometerCoMOffset', 'key': 'SimulateAccelerometerCoMOffset', 'description': 'This program generates an  accelerometer file  containing perturbing accelerations due to a given center of mass (CoM) offset. This includes centrifugal effects, Euler forces and the effect of gravity gradients.', 'config_table': 'outputfileAccelerometer filename effect of offset inputfileOrbit filename  inputfileStarCamera filename  applyAngularRate boolean compute effect of centrifugal forces applyAngularAccelerations boolean compute effect of Euler forces gradientfield gravityfieldType low order field to estimate the change of the gravity by position adjustement earthRotation earthRotationType  interpolationDegree uint derivation of quaternions by polynomial interpolation of degree n CoMOffsetX double offset [m] CoMOffsetY double offset [m] CoMOffsetZ double offset [m]', 'display_text': 'This program generates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">accelerometer file</a> containing perturbing accelerations due to a given center of mass (CoM) offset. This includes centrifugal effects, Euler forces and the effect of gravity gradients.'},\n'SimulateGradiometer': { 'name': 'SimulateGradiometer', 'key': 'SimulateGradiometer', 'description': 'This program simulates error free  gradiometer data  along a satellite\\'s orbit. The orientation of the full tensor gradiometer is given by   This program simulates error free   otherwise the celestial reference frame (CRF) is used. The gravity gradients are given by   This program simulates error free   and   This program simulates error free  .', 'config_table': 'outputfileGradiometer filename  inputfileOrbit filename  inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  gravityfield gravityfieldType  tides tidesType', 'display_text': 'This program simulates error free <a class=\"groops-file\" href=\"fileFormat_instrument.html\">gradiometer data</a> along a satellite\\'s orbit. The orientation of the full tensor gradiometer is given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> otherwise the celestial reference frame (CRF) is used. The gravity gradients are given by <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and <a class=\"groops-class\" href=\"tidesType.html\">tides</a>.'},\n'SimulateKeplerOrbit': { 'name': 'SimulateKeplerOrbit', 'key': 'SimulateKeplerOrbit', 'description': 'This program simulates a Keplerian  orbit  at a given  timeSeries  starting from the given  integrationConstants .', 'config_table': 'outputfileOrbit filename  timeSeries timeSeriesType  GM double Geocentric gravitational constant integrationConstants choice  kepler sequence  majorAxis double [m] eccentricity double [-] inclination angle [degree] ascendingNode angle [degree] argumentOfPerigee angle [degree] meanAnomaly angle [degree] time time integration constants are valid at this epoch positionAndVelocity sequence  position0x double [m] in CRF position0y double [m] in CRF position0z double [m] in CRF velocity0x double [m/s] velocity0y double [m/s] velocity0z double [m/s] time time integration constants are valid at this epoch', 'display_text': 'This program simulates a Keplerian <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> at a given <strong class=\"groops-config-element\">timeSeries</strong> starting from the given <strong class=\"groops-config-element\">integrationConstants</strong>.'},\n'SimulateOrbit': { 'name': 'SimulateOrbit', 'key': 'SimulateOrbit', 'description': 'This program integrates an  orbit  from a given force function (dynamic orbit). The force functions are given by   This program integrates an  . For computation of non-conservative forces a  satelliteModel  is needed. The integration method must be selected with   This program integrates an  . Because the orbit data are calculated in the celestial reference frame (CRF) you need   This program integrates an   to transform the force function from the terrestrial reference frame (TRF). The integration start and end time, as well as the sampling, are derived from the  timeSeries  option. It is possible to integrate the arc in  reverse , where the initial conditions are assumed to be met at the end time of the  timeSeries .', 'config_table': 'outputfileOrbit filename orbit file to be written. inputfileSatelliteModel filename satellite macro model timeSeries timeSeriesType time points for simulated orbit epochs. integrationConstants choice  kepler sequence  majorAxis double [m] eccentricity double [-] inclination angle [degree] ascendingNode angle [degree] argumentOfPerigee angle [degree] meanAnomaly angle [degree] GM double Geocentric gravitational constant positionAndVelocity sequence  position0x double [m] in CRF position0y double [m] in CRF position0z double [m] in CRF velocity0x double [m/s] velocity0y double [m/s] velocity0z double [m/s] file sequence  inputfileOrbit filename only epoch at timeStart is used margin double [seconds] used when finding initial epoch in orbitFile propagator orbitPropagatorType orbit propagation method. earthRotation earthRotationType  ephemerides ephemeridesType  forces forcesType considered in orbit propagation. reverse boolean start integration at last epoch in timeSeries, going backward in time.', 'display_text': 'This program integrates an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit</a> from a given force function (dynamic orbit). The force functions are given by <a class=\"groops-class\" href=\"forcesType.html\">forces</a>. For computation of non-conservative forces a <a class=\"groops-file\" href=\"fileFormat_satelliteModel.html\">satelliteModel</a> is needed. The integration method must be selected with <a class=\"groops-class\" href=\"orbitPropagatorType.html\">propagator</a>. Because the orbit data are calculated in the celestial reference frame (CRF) you need <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> to transform the force function from the terrestrial reference frame (TRF). The integration start and end time, as well as the sampling, are derived from the <strong class=\"groops-config-element\">timeSeries</strong> option. It is possible to integrate the arc in <strong class=\"groops-config-element\">reverse</strong>, where the initial conditions are assumed to be met at the end time of the <strong class=\"groops-config-element\">timeSeries</strong>.'},\n'SimulateSatelliteTracking': { 'name': 'SimulateSatelliteTracking', 'key': 'SimulateSatelliteTracking', 'description': 'This program simulates  tracking data  (range, range-rate, range-accelerations) between 2 satellites. The range is given by  with   and the unit vector in line of sight (LOS) direction  Range-rates   and range accelrations   are obtained by differentation  with the derivative of the unit vector  The   This program simulates  s must contain positions, velocities, and acceleration (see  OrbitAddVelocityAndAcceleration ).', 'config_table': 'outputfileSatelliteTracking filename  inputfileOrbit1 filename  inputfileOrbit2 filename', 'display_text': 'This program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">tracking data</a> (range, range-rate, range-accelerations) between 2 satellites. The range is given by \\\\[ \\\\rho(t) = \\\\left\\\\lVert{\\\\M r_B(t) - \\\\M r_A(t)}\\\\right\\\\rVert = \\\\M e_{AB}(t)\\\\cdot\\\\M r_{AB}(t), \\\\]with $\\\\M r_{AB} = \\\\M r_B - \\\\M r_A$ and the unit vector in line of sight (LOS) direction \\\\[\\\\label{sst.los} \\\\M e_{AB} = \\\\frac{\\\\M r_{AB}}{\\\\left\\\\lVert{\\\\M r_{AB}}\\\\right\\\\rVert}=\\\\frac{\\\\M r_{AB}}{\\\\rho}. \\\\]Range-rates $\\\\dot{\\\\rho}$ and range accelrations $\\\\ddot{\\\\rho}$ are obtained by differentation \\\\[\\\\label{obsRangeRate} \\\\dot{\\\\rho}  = \\\\M e_{AB}\\\\cdot\\\\dot{\\\\M r}_{AB} + \\\\dot{\\\\M e}_{AB}\\\\cdot\\\\M r_{AB}             = \\\\M e_{AB}\\\\cdot\\\\dot{\\\\M r}_{AB}, \\\\]\\\\[\\\\label{obsRangeAccl} \\\\begin{split} \\\\ddot{\\\\rho} &= \\\\M e_{AB}\\\\cdot\\\\ddot{\\\\M r}_{AB} +\\\\dot{\\\\M e}_{AB}\\\\cdot\\\\dot{\\\\M r}_{AB}             = \\\\M e_{AB}\\\\cdot\\\\ddot{\\\\M r}_{AB} +    \\\\frac{1}{\\\\rho}\\\\left(\\\\dot{\\\\M r}_{AB}^2-\\\\dot{\\\\rho}^2\\\\right). \\\\\\\\ \\\\end{split} \\\\]with the derivative of the unit vector \\\\[ \\\\dot{\\\\M e}_{AB}=\\\\frac{d}{dt}\\\\left(\\\\frac{\\\\M r_{AB}}{\\\\rho}\\\\right) =\\\\frac{\\\\dot{\\\\M r}_{AB}}{\\\\rho}-\\\\frac{\\\\dot{\\\\rho}\\\\cdot\\\\M r_{AB}}{\\\\rho^2} =\\\\frac{1}{\\\\rho}\\\\left({\\\\dot{\\\\M r}_{AB}-\\\\dot{\\\\rho}\\\\cdot\\\\M e_{AB}}\\\\right). \\\\]The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>s must contain positions, velocities, and acceleration (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>).'},\n'SimulateStarCamera': { 'name': 'SimulateStarCamera', 'key': 'SimulateStarCamera', 'description': 'This program simulates  star camera  measurements at each satellite\\'s position. The satellite\\'s orientation follows a local orbit frame with the x-axis in along track (along velocity), y-axis is cross track (normal to position and velocity vector) and z-axis pointing nadir (negative position vector). As for non circular orbit the position and velocity are not exact normal, the default is the x-axis to be exact along velocity and the z-axis forms a right hand system (not exact nadir) or with  nadirPointing  the z-axis is exact nadir and x-axis approximates along. The resulting rotation matrices rotate from satellite frame to inertial frame.', 'config_table': 'outputfileStarCamera filename rotation from satellite to inertial frame (x: along, y: cross, z: nadir) inputfileOrbit filename position and velocity defines the orientation of the satellite at each epoch nadirPointing boolean false: exact along and nearly nadir, true: nearly along and exact nadir', 'display_text': 'This program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera</a> measurements at each satellite\\'s position. The satellite\\'s orientation follows a local orbit frame with the x-axis in along track (along velocity), y-axis is cross track (normal to position and velocity vector) and z-axis pointing nadir (negative position vector). As for non circular orbit the position and velocity are not exact normal, the default is the x-axis to be exact along velocity and the z-axis forms a right hand system (not exact nadir) or with <strong class=\"groops-config-element\">nadirPointing</strong> the z-axis is exact nadir and x-axis approximates along. The resulting rotation matrices rotate from satellite frame to inertial frame.'},\n'SimulateStarCameraGnss': { 'name': 'SimulateStarCameraGnss', 'key': 'SimulateStarCameraGnss', 'description': 'This program simulates  star camera  measurements at each satellite position of   This program simulates  . The resulting rotation matrices rotate from body frame to inertial frame. The body frame refers to the IGS-specific (not the manufacturer-specific) body frame, as described by  . The   This program simulates   must contain velocities (use  OrbitAddVelocityAndAcceleration  if needed). Information about the attitude mode(s) used by the GNSS satellite may be provided via   This program simulates  . This file can be created with  GnssAttitudeInfoCreate . It contains one or more time-dependent entries, each defining the default attitude mode, the attitude modes used around orbit noon and midnight, and some parameters required by the various modes. If no   This program simulates   is selected, the program defaults to a nominal yaw-steering attitude model. A sufficiently high  modelingResolution  ensures that the attitude behavior is modeled properly at all times. The attitude behavior is defined by the respective mode. Here is a list of the supported modes with a brief explanation and references:    nominalYawSteering :       Yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) [1]  orbitNormal :       Keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) [1]  catchUpYawSteering :       Yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) [2, 3]  shadowMaxYawSteeringAndRecovery :       Yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight)) [2]  shadowMaxYawSteeringAndStop :       Yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached,       then stop (e.g. GLO-M (midnight)) [4]  shadowConstantYawSteering :       Yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight)) [3]  centeredMaxYawSteering :       Yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) [4, 8]  smoothedYawSteering1 :       Yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) [5]  smoothedYawSteering2 :       Yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) [5, 6]  betaDependentOrbitNormal :       Switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) [7, 8]  See  GnssAttitudeInfoCreate  for more details on which satellite uses which attitude modes and the required parameters for each mode. References for the attitude modes:            https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3       https://qzss.go.jp/en/technical/qzssinfo/index.html', 'config_table': 'outputfileStarCamera filename rotation from body frame to CRF inputfileOrbit filename attitude is modeled based on this orbit inputfileAttitudeInfo filename attitude modes used by the satellite and respective parameters interpolationDegree uint polynomial degree for orbit interpolation modelingResolution double [s] resolution for attitude model evaluation ephemerides ephemeridesType  eclipse eclipseType model to determine if satellite is in Earth\\'s shadow', 'display_text': 'This program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera</a> measurements at each satellite position of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. The resulting rotation matrices rotate from body frame to inertial frame. The body frame refers to the IGS-specific (not the manufacturer-specific) body frame, as described by <a href=\"https://doi.org/10.1016/j.asr.2015.06.019\">Montenbruck et al. (2015)</a>. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain velocities (use <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a> if needed).</p><p>Information about the attitude mode(s) used by the GNSS satellite may be provided via <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitudeInfo</a>. This file can be created with <a class=\"groops-program\" href=\"GnssAttitudeInfoCreate.html\">GnssAttitudeInfoCreate</a>. It contains one or more time-dependent entries, each defining the default attitude mode, the attitude modes used around orbit noon and midnight, and some parameters required by the various modes. If no <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitudeInfo</a> is selected, the program defaults to a nominal yaw-steering attitude model. A sufficiently high <strong class=\"groops-config-element\">modelingResolution</strong> ensures that the attitude behavior is modeled properly at all times.</p><p>The attitude behavior is defined by the respective mode. Here is a list of the supported modes with a brief explanation and references: <ul>  <li><b>nominalYawSteering</b>:       Yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) [1] </li><li> <b>orbitNormal</b>:       Keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) [1] </li><li> <b>catchUpYawSteering</b>:       Yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) [2, 3] </li><li> <b>shadowMaxYawSteeringAndRecovery</b>:       Yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight)) [2] </li><li> <b>shadowMaxYawSteeringAndStop</b>:       Yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached,       then stop (e.g. GLO-M (midnight)) [4] </li><li> <b>shadowConstantYawSteering</b>:       Yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight)) [3] </li><li> <b>centeredMaxYawSteering</b>:       Yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) [4, 8] </li><li> <b>smoothedYawSteering1</b>:       Yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) [5] </li><li> <b>smoothedYawSteering2</b>:       Yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) [5, 6] </li><li> <b>betaDependentOrbitNormal</b>:       Switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) [7, 8] </li></ul> </p><p></p><p>See <a class=\"groops-program\" href=\"GnssAttitudeInfoCreate.html\">GnssAttitudeInfoCreate</a> for more details on which satellite uses which attitude modes and the required parameters for each mode.</p><p>References for the attitude modes: <ol>  <li><a href=\"https://doi.org/10.1016/j.asr.2015.06.019\">Montenbruck et al. (2015)</a> </li><li> <a href=\"https://doi.org/10.1007/s10291-008-0092-1\">Kouba (2009)</a> </li><li> <a href=\"https://doi.org/10.1007/s10291-016-0562-9\">Kuang et al. (2017)</a> </li><li> <a href=\"https://doi.org/10.1016/j.asr.2010.09.007\">Dilssner et al. (2011)</a> </li><li> <a href=\"https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3\" target=\"_blank\">https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3</a> </li><li> <a href=\"https://doi.org/10.1007/s10291-018-0783-1\">Wang et al. (2018)</a> </li><li> <a href=\"https://doi.org/10.1017/S0373463318000103\">Li et al. (2018)</a> </li><li> <a href=\"https://qzss.go.jp/en/technical/qzssinfo/index.html\" target=\"_blank\">https://qzss.go.jp/en/technical/qzssinfo/index.html</a> </li></ol>'},\n'SimulateStarCameraGrace': { 'name': 'SimulateStarCameraGrace', 'key': 'SimulateStarCameraGrace', 'description': 'Simulates  star camera data  of the two GRACE satellites.    x: the antenna center pointing to the other satellite.  y: normal to line of sight and the radial direction.  z: forms a right handed system.', 'config_table': 'outputfileStarCamera1 filename  outputfileStarCamera2 filename  inputfileOrbit1 filename position define the orientation of the satellite at each epoch inputfileOrbit2 filename position define the orientation of the satellite at each epoch antennaCenters choice KBR antenna phase center value sequence  center1X double x-coordinate of antenna position in SRF [m] for GRACEA center1Y double y-coordinate of antenna position in SRF [m] for GRACEA center1Z double z-coordinate of antenna position in SRF [m] for GRACEA center2X double x-coordinate of antenna position in SRF [m] for GRACEB center2Y double y-coordinate of antenna position in SRF [m] for GRACEB center2Z double z-coordinate of antenna position in SRF [m] for GRACEB file sequence  inputAntennaCenters filename', 'display_text': 'Simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera data</a> of the two GRACE satellites. <ul>  <li>x: the antenna center pointing to the other satellite. </li><li> y: normal to line of sight and the radial direction. </li><li> z: forms a right handed system. </li></ul>'},\n'SimulateStarCameraSentinel1': { 'name': 'SimulateStarCameraSentinel1', 'key': 'SimulateStarCameraSentinel1', 'description': 'This program simulates  star camera  measurements at each satellite\\'s position for the Sentinel 1A satellite. The   This program simulates   must contain positions and velocities (see  OrbitAddVelocityAndAcceleration ). The resulting rotation matrices rotate from satellite frame to inertial frame.', 'config_table': 'outputfileStarCamera filename  inputfileOrbit filename position and velocity defines the orientation of the satellite at each epoch', 'display_text': 'This program simulates <a class=\"groops-file\" href=\"fileFormat_instrument.html\">star camera</a> measurements at each satellite\\'s position for the Sentinel 1A satellite. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain positions and velocities (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>). The resulting rotation matrices rotate from satellite frame to inertial frame.'},\n'SimulateStarCameraTerrasar': { 'name': 'SimulateStarCameraTerrasar', 'key': 'SimulateStarCameraTerrasar', 'description': 'This program simulates   This program simulates   measurements at each satellite\\'s position for the Terrasar satellite. The   This program simulates   must contain positions and velocities (see  OrbitAddVelocityAndAcceleration ). The resulting rotation matrices rotate from satellite frame to inertial frame. H. Fiedler, E. Boerner, J. Mittermayer and G. Krieger, Total zero Doppler Steering-a new method for minimizing the Doppler centroid, in IEEE Geoscience and Remote Sensing Letters, vol. 2, no. 2, pp. 141-145, April 2005,  https://www.doi.org/10.1109/LGRS.2005.844591 .', 'config_table': 'outputfileStarCamera filename rotation from satellite to inertial frame (x: along, y: cross, z: nadir) inputfileOrbit filename position and velocity defines the orientation of the satellite at each epoch', 'display_text': 'This program simulates <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileStarCamera</a> measurements at each satellite\\'s position for the Terrasar satellite. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a> must contain positions and velocities (see <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>). The resulting rotation matrices rotate from satellite frame to inertial frame.</p><p>H. Fiedler, E. Boerner, J. Mittermayer and G. Krieger, Total zero Doppler Steering-a new method for minimizing the Doppler centroid, in IEEE Geoscience and Remote Sensing Letters, vol. 2, no. 2, pp. 141-145, April 2005, <a href=\"https://www.doi.org/10.1109/LGRS.2005.844591\" target=\"_blank\">https://www.doi.org/10.1109/LGRS.2005.844591</a>.'},\n'SlrProcessing': { 'name': 'SlrProcessing', 'key': 'SlrProcessing', 'description': 'This program processes SLR normal point or full rate observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. To calculate observation equations from the passes, the model parameters or unknown parameters need to be defined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined   This program processes SLR normal point or full rate observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. . Some of the   This program processes SLR normal point or full rate observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.  also include a priori models. Lastly it is required to define the process flow of the SLR processing. This is accomplished with a list of   This program processes SLR normal point or full rate observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it. . Each step is processed consecutively. Some steps allow the selection of parameters, station, or satellites, which affects all subsequent steps. The   This program processes SLR normal point or full rate observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.  is used to precompute Earth rotation and station displacements with a uniform sampling. In a second step these values are interpolated to the observation epochs. A sampling of about 10 minutes should be adequate. It should be noted that GROOPS uses GPS time format, but normal point/full rate data files and CPF files, provided by ILRS data centers are given in UTC time format.', 'config_table': 'timeSeries timeSeriesType defines station movements and earth rotation epochs satellite slrSatelliteGeneratorType satellites station slrStationGeneratorType ground station network earthRotation earthRotationType apriori earth rotation parametrization slrParametrizationType models and parameters processingStep slrProcessingStepType steps are processed consecutively', 'display_text': 'This program processes SLR normal point or full rate observations. It calculates the linearized observation equations, accumulates them into a system of normal equations and solves it.</p><p>To calculate observation equations from the passes, the model parameters or unknown parameters need to be defined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrization</a>. Some of the <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrization</a> also include a priori models.</p><p>Lastly it is required to define the process flow of the SLR processing. This is accomplished with a list of <a class=\"groops-class\" href=\"slrProcessingStepType.html\">processingSteps</a>. Each step is processed consecutively. Some steps allow the selection of parameters, station, or satellites, which affects all subsequent steps.</p><p>The <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is used to precompute Earth rotation and station displacements with a uniform sampling. In a second step these values are interpolated to the observation epochs. A sampling of about 10 minutes should be adequate.</p><p>It should be noted that GROOPS uses GPS time format, but normal point/full rate data files and CPF files, provided by ILRS data centers are given in UTC time format.'},\n'FileConvert': { 'name': 'FileConvert', 'key': 'FileConvert', 'description': 'Converts GROOPS file between different file formats (ASCII, XML, JSON, binary), see  file formats  for details. With an additional extension of \\'.gz\\' files are directly compressed and uncompressed. It prints also some information about the content. Therefore it can be used to get an idea about the content of binary files.', 'config_table': 'outputfile filename GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz) inputfile filename GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)', 'display_text': 'Converts GROOPS file between different file formats (ASCII, XML, JSON, binary), see <a class=\"groops-ref\" href=\"general.fileFormat.html\">file formats</a> for details. With an additional extension of \\'.gz\\' files are directly compressed and uncompressed. It prints also some information about the content. Therefore it can be used to get an idea about the content of binary files.'},\n'FileCreateDirectories': { 'name': 'FileCreateDirectories', 'key': 'FileCreateDirectories', 'description': 'Creates the directory and parent directories as needed.', 'config_table': 'directory filename', 'display_text': 'Creates the directory and parent directories as needed.'},\n'FileMove': { 'name': 'FileMove', 'key': 'FileMove', 'description': 'Move/rename file or directory. If the  outputfile  is an existing directory the  inputfile  is moved into it.', 'config_table': 'outputfile filename target name or directory for the move/rename inputfile filename', 'display_text': 'Move/rename file or directory. If the <strong class=\"groops-config-element\">outputfile</strong> is an existing directory the <strong class=\"groops-config-element\">inputfile</strong> is moved into it.'},\n'FileRemove': { 'name': 'FileRemove', 'key': 'FileRemove', 'description': 'Remove files or directories. Deletes also the content recursivley if one of  files  is a directory.', 'config_table': 'files filename', 'display_text': 'Remove files or directories. Deletes also the content recursivley if one of <strong class=\"groops-config-element\">files</strong> is a directory.'},\n'FileTextCreate': { 'name': 'FileTextCreate', 'key': 'FileTextCreate', 'description': 'Create text  outputfile  containing  line s. This program can be a powerful tool, if the  line  is repeated with a   Create text   together with the  text parser .', 'config_table': 'outputfile filename  line string', 'display_text': 'Create text <strong class=\"groops-config-element\">outputfile</strong> containing <strong class=\"groops-config-element\">line</strong>s. This program can be a powerful tool, if the <strong class=\"groops-config-element\">line</strong> is repeated with a <a class=\"groops-class\" href=\"loopType.html\">loop</a> together with the <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a>.'},\n'GroupPrograms': { 'name': 'GroupPrograms', 'key': 'GroupPrograms', 'description': 'Runs  program s in a group, which can be used to structure a config file. If  catchErrors  is enabled and an error occurs, the remaining  program s are skipped and execution continues with  errorProgram s, in case any are defined. Otherwise an exception is thrown. The  silently  option disables the screen ouput of the  program s. With  outputfileLog  a log file is written for this group additional to a global log file. This might be helpful within  LoopPrograms  with parallel iterations.', 'config_table': 'outputfileLog filename additional log file silently boolean without showing the output. program programType  catchErrors sequence  errorProgram programType executed if an error occured', 'display_text': 'Runs <strong class=\"groops-config-element\">program</strong>s in a group, which can be used to structure a config file. If <strong class=\"groops-config-element\">catchErrors</strong> is enabled and an error occurs, the remaining <strong class=\"groops-config-element\">program</strong>s are skipped and execution continues with <strong class=\"groops-config-element\">errorProgram</strong>s, in case any are defined. Otherwise an exception is thrown.</p><p>The <strong class=\"groops-config-element\">silently</strong> option disables the screen ouput of the <strong class=\"groops-config-element\">program</strong>s. With <strong class=\"groops-config-element\">outputfileLog</strong> a log file is written for this group additional to a global log file. This might be helpful within <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> with parallel iterations.'},\n'IfPrograms': { 'name': 'IfPrograms', 'key': 'IfPrograms', 'description': 'Runs a list of  program s if a   Runs a list of   is met. Otherwise  elseProgram s are executed.', 'config_table': 'condition conditionType  program programType executed if condition evaluates to true elseProgram programType executed if condition evaluates to false', 'display_text': 'Runs a list of <strong class=\"groops-config-element\">program</strong>s if a <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is met. Otherwise <strong class=\"groops-config-element\">elseProgram</strong>s are executed.'},\n'LoopPrograms': { 'name': 'LoopPrograms', 'key': 'LoopPrograms', 'description': 'This program runs a list of programs in a   This program runs a list of programs in a  . If  continueAfterError = yes  and an error occurs, the remaining programs in the current iteration are skipped and the loop continues with the next iteration. Otherwise an exception is thrown. If this program is executed on multiple processing nodes, the iterations can be computed in parallel, see  parallelization . The first process serves as load balancer and the other processes are assigned to iterations according to  processCountPerIteration . For example, running a loop containing three iterations on 13 processes with  processCountPerIteration = 4 , runs the three iterations in parallel, with each iteration being assigned four processes. With  parallelLog = yes  all processes write output to screen and the log file. As the output can be quite confusing in this case, running  GroupPrograms  with an extra  outputfileLog  for each iteration (use the loop variables for the name of the log files) might be helpful.', 'config_table': 'loop loopType subprograms are called for every iteration continueAfterError boolean continue with next iteration after error, otherwise throw exception processCountPerIteration uint 0: use all processes for each iteration parallelLog boolean write to screen/log file from all processing nodes in parallelized loops program programType', 'display_text': 'This program runs a list of programs in a <a class=\"groops-class\" href=\"loopType.html\">loop</a>.</p><p>If <strong class=\"groops-config-element\">continueAfterError</strong>=<code>yes</code> and an error occurs, the remaining programs in the current iteration are skipped and the loop continues with the next iteration. Otherwise an exception is thrown.</p><p>If this program is executed on multiple processing nodes, the iterations can be computed in parallel, see <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelization</a>. The first process serves as load balancer and the other processes are assigned to iterations according to <strong class=\"groops-config-element\">processCountPerIteration</strong>. For example, running a loop containing three iterations on 13 processes with <strong class=\"groops-config-element\">processCountPerIteration</strong>=<code>4</code>, runs the three iterations in parallel, with each iteration being assigned four processes. With <strong class=\"groops-config-element\">parallelLog</strong>=<code>yes</code> all processes write output to screen and the log file. As the output can be quite confusing in this case, running <a class=\"groops-program\" href=\"GroupPrograms.html\">GroupPrograms</a> with an extra <strong class=\"groops-config-element\">outputfileLog</strong> for each iteration (use the loop variables for the name of the log files) might be helpful.'},\n'RunCommand': { 'name': 'RunCommand', 'key': 'RunCommand', 'description': 'Execute system  command s. If  executeParallel  is set and multiple  command s are given they are executed in parallel at distributed nodes, otherwise they are executed consecutively at master node only.', 'config_table': 'command filename  silently boolean without showing the output. continueAfterError boolean continue with next command after error, otherwise throw exception executeParallel boolean execute several commands in parallel', 'display_text': 'Execute system <strong class=\"groops-config-element\">command</strong>s. If <strong class=\"groops-config-element\">executeParallel</strong> is set and multiple <strong class=\"groops-config-element\">command</strong>s are given they are executed in parallel at distributed nodes, otherwise they are executed consecutively at master node only.'},\n'Accelerometer2GraceL1b': { 'name': 'Accelerometer2GraceL1b', 'key': 'Accelerometer2GraceL1b', 'description': 'This program converts accelerometer data from the  instrument file (ACCELEROMETER)  format into GRACE SDS format. The text file  inputfileHeader  is placed at the beginning of the  outputfile . The  text parser  is applied so that all variables can be used. In addition, the times of the data are available with the variables  {epochmin} ,  {epochmax} , and  {epochcount} . See also  GraceL1b2Accelerometer .', 'config_table': 'outputfile filename ACT1B inputfileHeader filename YAML Header, {epochmin}, {epochmax}, {epochcount} available inputfileAccelerometer filename ACCELEROMETER inputfileAngularAccelerometer filename ACCELEROMETER inputfileFlags filename MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z) satelliteId string A, B, C or D', 'display_text': 'This program converts accelerometer data from the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ACCELEROMETER)</a> format into GRACE SDS format.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>. The <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used. In addition, the times of the data are available with the variables <code>{epochmin}</code>, <code>{epochmax}</code>, and <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'BerneseKinematic2Orbit': { 'name': 'BerneseKinematic2Orbit', 'key': 'BerneseKinematic2Orbit', 'description': 'Read kinematic orbits in Bernese format.', 'config_table': 'outputfileOrbit filename  outputfileCovariance filename  earthRotation earthRotationType from TRF to CRF inputfile filename', 'display_text': 'Read kinematic orbits in Bernese format.'},\n'Champ2AccStar': { 'name': 'Champ2AccStar', 'key': 'Champ2AccStar', 'description': 'This program reads in CHAMP accelerometer and star camera data given in the special CHAMP format. In case of CHAMP accelerometer and star camera data is both stored in one file. A description of the format can be found under:  http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf .', 'config_table': 'outputfileAccelerometer filename  outputfileAngularAcceleration filename  outputfileStarCamera filename  inputfile filename', 'display_text': 'This program reads in CHAMP accelerometer and star camera data given in the special CHAMP format. In case of CHAMP accelerometer and star camera data is both stored in one file. A description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf</a>.'},\n'Champ2Orbit': { 'name': 'Champ2Orbit', 'key': 'Champ2Orbit', 'description': 'This program reads in CHAMP precise science orbits in the special CHORB format. A description of the format can be found under:  http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf', 'config_table': 'outputfileOrbit filename  earthRotation earthRotationType  inputfile filename', 'display_text': 'This program reads in CHAMP precise science orbits in the special CHORB format. A description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf</a>'},\n'Cosmic2OrbitStar': { 'name': 'Cosmic2OrbitStar', 'key': 'Cosmic2OrbitStar', 'description': 'This program reads in cosmic orbit and star camera data given in the CHAMP format. In case of cosmic orbit and star camera data is stored in one file. A description of the format can be found under:  http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf', 'config_table': 'outputfileOrbit filename  outputfileStarCamera filename  inputfile filename', 'display_text': 'This program reads in cosmic orbit and star camera data given in the CHAMP format. In case of cosmic orbit and star camera data is stored in one file. A description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf</a>'},\n'Cpf2Orbit': { 'name': 'Cpf2Orbit', 'key': 'Cpf2Orbit', 'description': 'Converts   and writes an  instrument file (ORBIT) . The time format of the CPF file is UTC. The coordinate system used in the CPF format is usually represented in TRF. If   Converts   is provided the data are transformed from terrestrial (TRF) to celestial reference frame (CRF). See also  Orbit2Cpf', 'config_table': 'outputfileOrbit filename  earthRotation earthRotationType  inputfile filename SLR CPF file', 'display_text': 'Converts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html\">CPF file</a> and writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.</p><p>The time format of the CPF file is UTC. The coordinate system used in the CPF format is usually represented in TRF. If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided the data are transformed from terrestrial (TRF) to celestial reference frame (CRF).</p><p>See also <a class=\"groops-program\" href=\"Orbit2Cpf.html\">Orbit2Cpf</a>'},\n'Crd2NormalPoints': { 'name': 'Crd2NormalPoints', 'key': 'Crd2NormalPoints', 'description': 'Converts   and writes an  instrument file (METEOROLOGICAL)  including meteorological data like temperature, air pressure and humidity as well as an  instrument file (SATELLITELASERRANGING)  including normal point data like range, accuracy, redundancy, wavelength and window size.', 'config_table': 'outputfileNormalPoints filename variable {station} available outputfileMeteorological filename variable {station} available inputfileSlrData filename SLR CRD files', 'display_text': 'Converts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/formats/crd.html\">CRD file</a> and writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like temperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a> including normal point data like range, accuracy, redundancy, wavelength and window size.'},\n'Cstg2NormalPoints': { 'name': 'Cstg2NormalPoints', 'key': 'Cstg2NormalPoints', 'description': 'Converts   provided by the   and writes an  instrument file (METEOROLOGICAL)  including meteorological data like temperature, air pressure and humidity as well as an  instrument file (SATELLITELASERRANGING)  including normal point data like range, accuracy, redundancy, wavelength and window size.', 'config_table': 'outputfileNormalPoints filename variable {station} available outputfileMeteorological filename variable {station} available inputfileSlrData filename SLR CSTG file', 'display_text': 'Converts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html\">CSTG file</a> provided by the <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> and writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like temperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a> including normal point data like range, accuracy, redundancy, wavelength and window size.'},\n'DoodsonAdmittance2SupplementaryFiles': { 'name': 'DoodsonAdmittance2SupplementaryFiles', 'key': 'DoodsonAdmittance2SupplementaryFiles', 'description': 'The publication of an ocean tide model includes not only the atlas in the form of spherical harmonics coefficients, but also the matrix of Doodson multipliers ( outputfileDoodsonMatrix ) and the  outputfileAdmittanceMatrix . The  outputfileMajorTideList  contains the  fileNames  for each contituent. The required information is taken from the   The publication of an ocean tide model includes not only the atlas in the form of spherical harmonics coefficients, but also the matrix of Doodson multipliers ( . See also  DoodsonHarmonics2PotentialCoefficients .', 'config_table': 'outputfileMajorTideList filename  fileNames filename template for fileList, variables: doodson, name, cossin outputfileDoodsonMatrix filename  outputfileAdmittanceMatrix filename  inputfileAdmittance filename interpolation of minor constituents', 'display_text': 'The publication of an ocean tide model includes not only the atlas in the form of spherical harmonics coefficients, but also the matrix of Doodson multipliers (<strong class=\"groops-config-element\">outputfileDoodsonMatrix</strong>) and the <strong class=\"groops-config-element\">outputfileAdmittanceMatrix</strong>.</p><p>The <strong class=\"groops-config-element\">outputfileMajorTideList</strong> contains the <strong class=\"groops-config-element\">fileNames</strong> for each contituent. The required information is taken from the <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.</p><p>See also <a class=\"groops-program\" href=\"DoodsonHarmonics2PotentialCoefficients.html\">DoodsonHarmonics2PotentialCoefficients</a>.'},\n'DoodsonHarmonics2IersPotential': { 'name': 'DoodsonHarmonics2IersPotential', 'key': 'DoodsonHarmonics2IersPotential', 'description': 'Convert doodson harmonics to IERS conventions according to FES2004. cf.  ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat .', 'config_table': 'outputfile filename according to IERS2010, chapter 6.3.2, footnote 7 inputfileDoodsonHarmoncis filename  header string info for output header factor double  minDegree uint  maxDegree uint', 'display_text': 'Convert doodson harmonics to IERS conventions according to FES2004. cf. <a href=\"ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\" target=\"_blank\">ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat</a>.'},\n'DoodsonHarmonics2IersWaterHeight': { 'name': 'DoodsonHarmonics2IersWaterHeight', 'key': 'DoodsonHarmonics2IersWaterHeight', 'description': 'Convert doodson harmonics to IERS conventions according to FES2004. cf.  ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat .', 'config_table': 'outputfile filename according to IERS2010, chapter 6.3.2, footnote 7 inputfileDoodsonHarmoncis filename  inputfileTideGeneratingPotential filename to compute Xi phase correction header string info for output header kernel kernelType data type of output values factor double e.g. from [m] to [cm] minDegree uint  maxDegree uint', 'display_text': 'Convert doodson harmonics to IERS conventions according to FES2004. cf. <a href=\"ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\" target=\"_blank\">ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat</a>.'},\n'GnssAntex2AntennaDefinition': { 'name': 'GnssAntex2AntennaDefinition', 'key': 'GnssAntex2AntennaDefinition', 'description': 'Converts metadata and antenna definitions from the  . to   Converts metadata and antenna definitions from the  ,   Converts metadata and antenna definitions from the  , and   Converts metadata and antenna definitions from the   files for the respective GNSS and for the list of ground station antennas. The  transmitterInfo  files for GLONASS satellites should then be updated using  GnssGlonassFrequencyNumberUpdate .', 'config_table': 'outputfileAntennaDefinitionStation filename antenna center variations outputfileAntennaDefinitionTransmitter filename antenna center variations outputfileTransmitterInfo filename PRN is appended to file name outputfileTransmitterListGps filename list of PRNs outputfileTransmitterListGlonass filename list of PRNs outputfileTransmitterListGalileo filename list of PRNs outputfileTransmitterListBeiDou filename list of PRNs outputfileTransmitterListQzss filename list of PRNs outputfileTransmitterListIrnss filename list of PRNs inputfileAntex filename  timeStart time ignore older antenna definitions createZeroModel boolean create empty antenna patterns', 'display_text': 'Converts metadata and antenna definitions from the <a href=\"https://files.igs.org/pub/data/format/antex14.txt\">IGS ANTEX format</a>. to <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">antennaDefinition</a>, <a class=\"groops-class\" href=\"fileFormat_platform.html\">transmitterInfo</a>, and <a class=\"groops-class\" href=\"fileFormat_stringList.html\">transmitterList</a> files for the respective GNSS and for the list of ground station antennas.</p><p>The <a class=\"groops-file\" href=\"fileFormat_platform.html\">transmitterInfo</a> files for GLONASS satellites should then be updated using <a class=\"groops-program\" href=\"GnssGlonassFrequencyNumberUpdate.html\">GnssGlonassFrequencyNumberUpdate</a>.'},\n'GnssClock2ClockRinex': { 'name': 'GnssClock2ClockRinex', 'key': 'GnssClock2ClockRinex', 'description': 'Converts GNSS clocks from GROOPS format to  . Clocks can be provided via  satelliteData  and/or  stationData . Observed signal types are inferred from   Converts GNSS clocks from GROOPS format to  . Satellites/stations used as clock references can be provided via  referenceClock . See IGS clock RINEX format description for further details on header information.', 'config_table': 'outputfileClockRinex filename  satelliteData sequence one element per satellite inputfileClock filename clock instrument file inputfileSignalBias filename signal bias file identifier string PRN (e.g. G23) stationData sequence one element per station inputfileClock filename clock instrument file inputfilePosition filename station position file inputfileStationInfo filename station info file identifier string station name (e.g. wtzz) comment string comment in header program string name of program (for first line) institution string name of agency (for first line) analysisCenter string name of analysis center differentialCodeBias string program and source for applied differential code bias phaseCenterVariations string program and source for applied phase center variations referenceClock string identifier of reference satellite/station referenceFrame string terrestrial reference frame for the stations', 'display_text': 'Converts GNSS clocks from GROOPS format to <a href=\"https://files.igs.org/pub/data/format/rinex_clock304.txt\">IGS clock RINEX format</a>. Clocks can be provided via <strong class=\"groops-config-element\">satelliteData</strong> and/or <strong class=\"groops-config-element\">stationData</strong>. Observed signal types are inferred from <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBias</a>. Satellites/stations used as clock references can be provided via <strong class=\"groops-config-element\">referenceClock</strong>.</p><p>See IGS clock RINEX format description for further details on header information.'},\n'GnssClockRinex2InstrumentClock': { 'name': 'GnssClockRinex2InstrumentClock', 'key': 'GnssClockRinex2InstrumentClock', 'description': 'This program converts clocks from the  , which contains the clocks of all satellites and stations in a single file, into an  instrument file (MISCVALUE)  for each  identifier  (satellite and/or station).', 'config_table': 'outputfileInstrument filename identifier is appended to each file inputfileClockRinex filename  identifier string satellite or station identifier, e.g. G23 or alic intervals timeSeriesType  minEpochsPerInterval uint minimum number of epochs in an interval', 'display_text': 'This program converts clocks from the <a href=\"https://files.igs.org/pub/data/format/rinex_clock304.txt\">IGS clock RINEX format</a>, which contains the clocks of all satellites and stations in a single file, into an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a> for each <strong class=\"groops-config-element\">identifier</strong> (satellite and/or station).'},\n'GnssEop2IgsErp': { 'name': 'GnssEop2IgsErp', 'key': 'GnssEop2IgsErp', 'description': 'Write GNSS Earth orientation parameters to  . Requires polar motion, polar motion rate, dUT1 and LOD parameters in the solution vector   Write GNSS Earth orientation parameters to   and their sigmas in   Write GNSS Earth orientation parameters to  . Solution usually comes out of  GnssProcessing .', 'config_table': 'outputfileIgsErp filename IGS ERP file epoch sequence e.g. daily solution inputfileSolution filename parameter vector inputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) inputfileParameterNames filename parameter names inputfileTransmitterList filename transmitter PRNs used in solution (used for transmitter count) inputfileStationList filename stations used in solution (used for station count) time time reference time for epoch comment string', 'display_text': 'Write GNSS Earth orientation parameters to <a href=\"https://files.igs.org/pub/data/format/erp.txt\">IGS ERP file format</a>.</p><p>Requires polar motion, polar motion rate, dUT1 and LOD parameters in the solution vector <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a> and their sigmas in <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmax</a>. Solution usually comes out of <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.'},\n'GnssGriddedDataTimeSeries2Ionex': { 'name': 'GnssGriddedDataTimeSeries2Ionex', 'key': 'GnssGriddedDataTimeSeries2Ionex', 'description': 'Converts TEC maps from GROOPS  gridded data time series  format to IGS  . Currently only supports 2D TEC maps. See also  GnssIonex2GriddedDataTimeSeries ,   Converts TEC maps from GROOPS  .', 'config_table': 'outputfileIonex filename  inputfileGriddedDataTimeSeries filename must contain regular grid value expression expression (e.g. data column) timeSeries timeSeriesType (empty = use input file time series) program string name of program (for first line) institution string name of agency (for first line) description string description in header comment string comment in header mappingFunction string see IONEX documentation elevationCutoff double see IONEX documentation (0 if unknown) observablesUsed string see IONEX documentation exponent int factor 10^exponent is applied to all values', 'display_text': 'Converts TEC maps from GROOPS <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">gridded data time series</a> format to IGS <a href=\"https://files.igs.org/pub/data/format/ionex1.pdf\">IONEX file format</a>.</p><p>Currently only supports 2D TEC maps.</p><p>See also <a class=\"groops-program\" href=\"GnssIonex2GriddedDataTimeSeries.html\">GnssIonex2GriddedDataTimeSeries</a>, <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">IonosphereMap</a>.'},\n'GnssIonex2GriddedDataTimeSeries': { 'name': 'GnssIonex2GriddedDataTimeSeries', 'key': 'GnssIonex2GriddedDataTimeSeries', 'description': 'Converts TEC maps from IGS   to GROOPS  gridded data time series  format. Currently only supports 2D TEC maps. See also  GnssGriddedDataTimeSeries2Ionex ,   Converts TEC maps from IGS  .', 'config_table': 'outputfileGriddedDataTimeSeries filename  inputfileIonex filename', 'display_text': 'Converts TEC maps from IGS <a href=\"https://files.igs.org/pub/data/format/ionex1.pdf\">IONEX file format</a> to GROOPS <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">gridded data time series</a> format.</p><p>Currently only supports 2D TEC maps.</p><p>See also <a class=\"groops-program\" href=\"GnssGriddedDataTimeSeries2Ionex.html\">GnssGriddedDataTimeSeries2Ionex</a>, <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">IonosphereMap</a>.'},\n'GnssNormals2Sinex': { 'name': 'GnssNormals2Sinex', 'key': 'GnssNormals2Sinex', 'description': 'Write GNSS data/metadata and  normal equations  to  . Normal equations usually come from  GnssProcessing  (e.g. from  GNSS satellite orbit determination and station network analysis ). Metadata input files include   Write GNSS data/metadata and  ,   Write GNSS data/metadata and  , and   Write GNSS data/metadata and  , see  GnssAntex2AntennaDefinition . See also  Sinex2Normals  and  NormalsSphericalHarmonics2Sinex .', 'config_table': 'outputfileSinexNormals filename full SINEX file including normal equations outputfileSinexCoordinates filename SINEX file without normal equations (station coordinates file) inputfileNormals filename normal equation matrix inputfileSolution filename parameter vector inputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) inputfileApriori filename apriori parameter vector inputfileAprioriSigma filename constraint sigmas for apriori parameter vector inputfileAprioriMatrix filename normal equation matrix of applied constraints transmitterConstellation sequence transmitter constellation metadata inputfileTransmitterList filename transmitter PRNs used in solution inputfileTransmitterInfo filename transmitter info file template inputfileAntennaDefinition filename transmitter phase centers and variations (ANTEX) variablePrn string loop variable for PRNs from transmitter list stations sequence  inputfileStationList filename stations contained in normal equations inputfileStationInfo filename station info file template inputfileAntennaDefinition filename station phase centers and variations (ANTEX) variableStationName string loop variable for station names from station list observationTimeStart time start time for which solution has observations observationTimeEnd time end time for which solution has observations time time reference time for parameters sampling double [seconds] observation sampling antennaCalibrationModel string e.g. IGS14_WWWW (WWWW = ANTEX release GPS week) sinexHeader sequence  agencyCode string identify the agency providing the data timeStart time start time of the data timeEnd time end time of the data  observationCode string technique used to generate the SINEX solution constraintCode string 0: tight constraint, 1: siginficant constraint, 2: unconstrained solutionContent string solution types contained in the SINEX solution (S O E T C A) description string organizitions gathering/alerting the file contents contact string Address of the relevant contact. e-mail output string Description of the file contents input string Brief description of the input used to generate this solution software string Software used to generate the file hardware string Computer hardware on which above software was run inputfileComment filename comments in the comment block from a file (truncated at 80 characters) comment string comments in the comment block', 'display_text': 'Write GNSS data/metadata and <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> to <a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a>.</p><p>Normal equations usually come from <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> (e.g. from <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>). Metadata input files include <a class=\"groops-class\" href=\"fileFormat_platform.html\">stationInfo/transmitterInfo</a>, <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">antennaDefinition</a>, and <a class=\"groops-class\" href=\"fileFormat_stringList.html\">stationList/transmitterList</a>, see <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.</p><p>See also <a class=\"groops-program\" href=\"Sinex2Normals.html\">Sinex2Normals</a> and <a class=\"groops-program\" href=\"NormalsSphericalHarmonics2Sinex.html\">NormalsSphericalHarmonics2Sinex</a>.'},\n'GnssOrbex2StarCamera': { 'name': 'GnssOrbex2StarCamera', 'key': 'GnssOrbex2StarCamera', 'description': 'Converts GNSS satellite attitude from   (quaternions) to  instrument file (STARCAMERA) . The resulting star camera files contain the rotation from satellite body frame to TRF, or to CRF in case   Converts GNSS satellite attitude from   is provided. See also  GnssAttitude2Orbex .', 'config_table': 'outputfileStarCamera filename rotation from body frame to TRF/CRF, identifier is appended to each file inputfileOrbex filename  identifier string (empty = all) satellite identifier, e.g. G23 or E05 earthRotation earthRotationType rotation from TRF to CRF', 'display_text': 'Converts GNSS satellite attitude from <a href=\"http://acc.igs.org/misc/proposal_orbex_april2019.pdf\">ORBEX file format</a> (quaternions) to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>. The resulting star camera files contain the rotation from satellite body frame to TRF, or to CRF in case <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided.</p><p>See also <a class=\"groops-program\" href=\"GnssAttitude2Orbex.html\">GnssAttitude2Orbex</a>.'},\n'GnssReceiver2RinexObservation': { 'name': 'GnssReceiver2RinexObservation', 'key': 'GnssReceiver2RinexObservation', 'description': 'Converts a   Converts a   into a   observation file. The   Converts a   contains the antenna and receiver information for the RINEX header. The   Converts a   and   Converts a   can be used to filter the observation types that will be exported.', 'config_table': 'outputfileRinexObservation filename RINEX observation file inputfileGnssReceiver filename GNSS instrument file inputfileStationInfo filename antenna and receiver info comment string write comments at begin of header observer string header information angency string header information useType gnssType only use observations that match any of these patterns ignoreType gnssType ignore observations that match any of these patterns', 'display_text': 'Converts a <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileGnssReceiver</a> into a <a href=\"https://files.igs.org/pub/data/format/rinex_4.00.pdf\">RINEX</a> observation file. The <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> contains the antenna and receiver information for the RINEX header. The <a class=\"groops-class\" href=\"gnssType.html\">useType</a> and <a class=\"groops-class\" href=\"gnssType.html\">ignoreType</a> can be used to filter the observation types that will be exported.'},\n'GnssRinexNavigation2OrbitClock': { 'name': 'GnssRinexNavigation2OrbitClock', 'key': 'GnssRinexNavigation2OrbitClock', 'description': 'Evaluates orbit and clock parameters from   (version 2, 3, and 4) navigation file  inputfileRinex  at epochs given by   Evaluates orbit and clock parameters from   and writes them to   Evaluates orbit and clock parameters from   and   Evaluates orbit and clock parameters from  , respectively. Orbits are rotated from TRF (as broadcasted) to CRF via   Evaluates orbit and clock parameters from  , but system-specific TRFs (WGS84, PZ-90, etc.) are not aligned to a common TRF. Furthermore, option is available to remove any satellite ephemeris data that has their satellite flag set to unhealthy. See also  OrbitAddVelocityAndAcceleration .', 'config_table': 'outputfileOrbit filename PRN is appended to file name outputfileClock filename PRN is appended to file name inputfileRinex filename RINEX navigation file timeSeries timeSeriesType orbit and clock evaluation epochs earthRotation earthRotationType for rotation from TRF to CRF useType gnssType (e.g. ***G12) only use satellites with PRN that match any of these patterns ignoreType gnssType (e.g. ***R**) ignore satellites PRN that match any of these patterns removeUnhealthySatellites boolean Remove satellite ephemeris that have their sat flags set to unhealthy', 'display_text': 'Evaluates orbit and clock parameters from <a href=\"https://files.igs.org/pub/data/format/rinex_4.00.pdf\">RINEX</a> (version 2, 3, and 4) navigation file <strong class=\"groops-config-element\">inputfileRinex</strong> at epochs given by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> and writes them to <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileClock</a>, respectively.</p><p>Orbits are rotated from TRF (as broadcasted) to CRF via <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>, but system-specific TRFs (WGS84, PZ-90, etc.) are not aligned to a common TRF.</p><p>Furthermore, option is available to remove any satellite ephemeris data that has their satellite flag set to unhealthy.</p><p>See also <a class=\"groops-program\" href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a>.'},\n'GnssSignalBias2SinexBias': { 'name': 'GnssSignalBias2SinexBias', 'key': 'GnssSignalBias2SinexBias', 'description': 'Convert  GNSS signal biases  from GROOPS format to  . Biases can be provided via  transmitterBiases  and/or  receiverBiases . Phase biases without attribute (e.g.  L1* ) are automatically expanded so each code bias has a corresponding phase bias (Example:  C1C ,  C1W ,  L1*  are converted to  C1C ,  C1W ,  L1C ,  L1W ). Time-variable biases (e.g. GPS L5 satellite phase bias) can be provided via  timeVariableBias . Their time span will be based on the provided epochs ( ). The slope of the bias can be optionally provided in the second data column. If GLONASS receiver biases depend on frequency number, those must be defined in   Convert   to get the correct PRN/SVN assignment to the biases. See IGS SINEX Bias format description for further details on header information. See also  GnssSinexBias2SignalBias  and  GnssBiasClockAlignment .', 'config_table': 'outputfileSinexBias filename  inputfileTransmitterInfo filename one file per satellite transmitterBiases sequence one element per satellite inputfileSignalBias filename signal bias file timeVariableBias sequence one entry per time variable bias type inputfileSignalBias filename columns: mjd, bias [m], (biasSlope [m/s]) type gnssType bias type identifier string PRN or station name (e.g. G23 or wtzz) receiverBiases sequence one element per station inputfileSignalBias filename signal bias file timeVariableBias sequence one entry per time variable bias type inputfileSignalBias filename columns: mjd, bias [m], (biasSlope [m/s]) type gnssType bias type identifier string PRN or station name (e.g. G23 or wtzz) agencyCode string identify the agency providing the data fileAgencyCode string identify the agency creating the file timeStart time start time of the data timeEnd time end time of the data  biasMode choice absolute or relative bias estimates absolute   relative   observationSampling double [seconds] intervalLength double [seconds] interval for bias parameter representation determinationMethod string determination method used to generate the bias results (see SINEX Bias format description) receiverClockReferenceGnss string (G, R, E, C) reference GNSS used for receiver clock estimation satelliteClockReferenceObservables string one per system, reference code observable on first and second frequency (RINEX3 format) description string organization gathering/altering the file contents contact string contact name and/or email address input string brief description of the input used to generate this solution output string description of the file contents software string software used to generate the file hardware string computer hardware on which above software was run comment string comments in the comment block', 'display_text': 'Convert <a class=\"groops-file\" href=\"fileFormat_gnssSignalBias.html\">GNSS signal biases</a> from GROOPS format to <a href=\"https://files.igs.org/pub/data/format/sinex_bias_100.pdf\">IGS SINEX Bias format</a>. Biases can be provided via <strong class=\"groops-config-element\">transmitterBiases</strong> and/or <strong class=\"groops-config-element\">receiverBiases</strong>. Phase biases without attribute (e.g. <code>L1*</code>) are automatically expanded so each code bias has a corresponding phase bias (Example: <code>C1C</code>, <code>C1W</code>, <code>L1*</code> are converted to <code>C1C</code>, <code>C1W</code>, <code>L1C</code>, <code>L1W</code>).</p><p>Time-variable biases (e.g. GPS L5 satellite phase bias) can be provided via <strong class=\"groops-config-element\">timeVariableBias</strong>. Their time span will be based on the provided epochs ($t \\\\pm \\\\Delta t / 2$). The slope of the bias can be optionally provided in the second data column.</p><p>If GLONASS receiver biases depend on frequency number, those must be defined in <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a> to get the correct PRN/SVN assignment to the biases.</p><p>See IGS SINEX Bias format description for further details on header information.</p><p>See also <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a> and <a class=\"groops-program\" href=\"GnssBiasClockAlignment.html\">GnssBiasClockAlignment</a>.'},\n'GnssSinexBias2SignalBias': { 'name': 'GnssSinexBias2SignalBias', 'key': 'GnssSinexBias2SignalBias', 'description': 'Converts GNSS signal biases from   to  GnssSignalBias format . Only satellite observable-specific signal biases (OSB) are supported at the moment. If multiple entries exist for the same bias, the weighted average (based on time span) of all entries is used. Time-variable biases are not supported at the moment. See also  GnssSignalBias2SinexBias .', 'config_table': 'outputfileSignalBias filename identifier is appended to file name inputfileSinexBias filename  inputfileGlonassSignalDefinition filename GLONASS frequency number mapping identifier string (empty = all) satellite PRN, e.g. G23 or E05', 'display_text': 'Converts GNSS signal biases from <a href=\"https://files.igs.org/pub/data/format/sinex_bias_100.pdf\">IGS SINEX Bias format</a> to <a class=\"groops-file\" href=\"fileFormat_gnssSignalBias.html\">GnssSignalBias format</a>.</p><p>Only satellite observable-specific signal biases (OSB) are supported at the moment. If multiple entries exist for the same bias, the weighted average (based on time span) of all entries is used. Time-variable biases are not supported at the moment.</p><p>See also <a class=\"groops-program\" href=\"GnssSignalBias2SinexBias.html\">GnssSignalBias2SinexBias</a>.'},\n'GnssStationLog2Platform': { 'name': 'GnssStationLog2Platform', 'key': 'GnssStationLog2Platform', 'description': 'Converts   or   to   Converts  . If   Converts   is provided, station log data is cross-checked with the given antenna definitions. Cross-checking station log data with a   is possible with  CheckStationsPlatformsWithSinex .', 'config_table': 'outputfileStationPlatform filename  inputfileStationLog filename  inputfileAntennaDefinition filename used to check antennas', 'display_text': 'Converts <a href=\"https://files.igs.org/pub/station/general/blank.log\">IGS station log format</a> or <a href=\"https://files.igs.org/pub/station/general/blank_v2.0.log\">IGS station log format v2.0</a> to <a class=\"groops-class\" href=\"fileFormat_platform.html\">outputfileStationPlatform</a>.</p><p>If <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a> is provided, station log data is cross-checked with the given antenna definitions. Cross-checking station log data with a <a href=\"https://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX file</a> is possible with <a class=\"groops-program\" href=\"CheckStationsPlatformsWithSinex.html\">CheckStationsPlatformsWithSinex</a>.'},\n'GnssTroposphere2TropoSinex': { 'name': 'GnssTroposphere2TropoSinex', 'key': 'GnssTroposphere2TropoSinex', 'description': 'Convert GNSS troposphere data from GROOPS format as estimated by  GnssProcessing  to   format. For each station folling files are needed:       Convert GNSS troposphere data from GROOPS format as estimated by  ,     Convert GNSS troposphere data from GROOPS format as estimated by  (MISVALUES),    optional standard deviations with   Convert GNSS troposphere data from GROOPS format as estimated by  (MISVALUES),     Convert GNSS troposphere data from GROOPS format as estimated by  (VECTOR3D).   The   Convert GNSS troposphere data from GROOPS format as estimated by   contains antenna center offsets and variations of all used antennas. Created via  GnssAntex2AntennaDefinition  or  GnssAntennaDefinitionCreate . For considering the geoid height use   Convert GNSS troposphere data from GROOPS format as estimated by   as it might be computed by  Gravityfield2GriddedData . The height closest to the station\\'s position is used in each case. See also  GnssProcessing .', 'config_table': 'outputfileTropoSinex filename  station sequence  inputfileStationInfo filename platform file inputfileTroposphereData filename Troposphere data estimates (columns: mjd, trodry, trowet, tgndry, tgnwet, tgedry, tgewet) inputfileTroposphereSigmas filename Troposphere data sigmas (columns: mjd, sigma_trowet, sigma_tgnwet, sigma_tgewet) inputfilePosition filename Precise station position (columns: mjd, x, y, z [m in TRF]) inputfileAntennaDefinition filename station phase centers and variations inputfileGriddedGeoidHeight filename value closest to the station\\'s position is used in each case dataSamplingInterval double [sec] GNSS data sampling rate tropoSamplingInterval double [sec] Tropospheric parameter sampling interval tropoModelingMethod string Tropospheric estimation method: Filter, Smoother, Least Squares, Piece-Wise Linear Interpolation aPrioriTropoModel string A priori tropospheric model used tropoMappingFunction string Name of mapping function used for hydrostatic and wet delay gradientMappingFunction string Name of mapping function used for gradients metDataSource string source of surface meteorological observations used (see format desc.) observationWeighting string observation weighting model applied elevationCutoff double [deg] gnssSystems string G=GPS, R=GLONASS, E=Galileo, C=BeiDou timeSystem string G (GPS) or UTC oceanTideModel string Name of applied Ocean tide loading model atmosphericTideModel string Name of applied Atmospheric tide loading model geoidModel string Geoid model name for undulation values systemCode string Terrestrial reference system code remark string Remark used to identify the origin of the coordinates (AC acronym) antennaCalibrationModel string e.g. IGS20_WWWW (WWWW = ANTEX release GPS week) sinexTroHeader sequence  agencyCode string Identify the agency providing the data timeStart time Start time of the data timeEnd time End time of the data  observationCode string Technique used to generate the SINEX solution solutionContents string Marker name if single station, MIX if multiple stations description string Organizitions gathering/alerting the file contents output string Description of the file contents contact string Address of the relevant contact e-mail software string Software used to generate the file hardware string Computer hardware on which above software was run input string Brief description of the input used to generate this solution versionNumber string Unique identifier of the product, same as in file name, e.g. 000 inputfileComment filename comments in the comment block from a file (truncated at 80 characters per line) comment string comments in the comment block', 'display_text': 'Convert GNSS troposphere data from GROOPS format as estimated by <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> to <a href=\"https://files.igs.org/pub/data/format/sinex_tro_v2.00.pdf\">IGS SINEX TRO</a> format.</p><p>For each station folling files are needed: <ul>    <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a>,   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTroposphereData</a>(MISVALUES),   </li><li> optional standard deviations with <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileTroposphereSigmas</a>(MISVALUES),   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfilePosition</a>(VECTOR3D). </li></ul>  The <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a> contains antenna center offsets and variations of all used antennas. Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.</p><p>For considering the geoid height use <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedGeoidHeight</a> as it might be computed by <a class=\"groops-program\" href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a>. The height closest to the station\\'s position is used in each case.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.'},\n'GoceXml2Gradiometer': { 'name': 'GoceXml2Gradiometer', 'key': 'GoceXml2Gradiometer', 'description': 'Read ESA XML GOCE Data. The  outputfileGradiometer  is written as  instrument file (GRADIOMETER) .', 'config_table': 'outputfileGradiometer filename  inputfile filename', 'display_text': 'Read ESA XML GOCE Data. The <strong class=\"groops-config-element\">outputfileGradiometer</strong> is written as <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (GRADIOMETER)</a>.'},\n'GoceXml2Orbit': { 'name': 'GoceXml2Orbit', 'key': 'GoceXml2Orbit', 'description': 'Read ESA XML GOCE Data.', 'config_table': 'outputfileOrbit filename  earthRotation earthRotationType rotation from TRF to CRF inputfile filename', 'display_text': 'Read ESA XML GOCE Data.'},\n'GoceXml2StarCamera': { 'name': 'GoceXml2StarCamera', 'key': 'GoceXml2StarCamera', 'description': 'Read ESA XML GOCE Data.', 'config_table': 'outputfileStarCamera filename  inputfile filename', 'display_text': 'Read ESA XML GOCE Data.'},\n'GoceXmlEggNom1b': { 'name': 'GoceXmlEggNom1b', 'key': 'GoceXmlEggNom1b', 'description': 'Read ESA XML GOCE Data.', 'config_table': 'outputfileGradiometer filename  outputfileAccelerometer filename  outputfileStarCamera filename  outputfileAngularRate filename  outputfileAngularAcc filename  inputfile filename', 'display_text': 'Read ESA XML GOCE Data.'},\n'Grace2PotentialCoefficients': { 'name': 'Grace2PotentialCoefficients', 'key': 'Grace2PotentialCoefficients', 'description': 'This program converts potential coefficients from the GRACE SDS format into  potential coefficients file . The program supports file formats for RL04 to RL06. Within the program, the variables  epochStart ,  epochEnd  and  epochMid  are populated with the corresponding time-stamps in the file. These can be used in to   This program converts potential coefficients from the GRACE SDS format into   to auto-generate the file name.', 'config_table': 'outputfilePotentialCoefficients filename variables: epochStart, epochEnd, epochMid inputfile filename', 'display_text': 'This program converts potential coefficients from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_potentialCoefficients.html\">potential coefficients file</a>. The program supports file formats for RL04 to RL06.</p><p>Within the program, the variables <code>epochStart</code>, <code>epochEnd</code> and <code>epochMid</code> are populated with the corresponding time-stamps in the file. These can be used in to <a class=\"groops-class\" href=\"fileFormat_potentialCoefficients.html\">outputfilePotentialCoefficients</a> to auto-generate the file name.'},\n'GraceAccelerometer2L1bAscii': { 'name': 'GraceAccelerometer2L1bAscii', 'key': 'GraceAccelerometer2L1bAscii', 'description': 'Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.', 'config_table': 'outputfileAscii filename ASCII outputfile inputfileAccelerometer filename GROOPS acceleromter file satelliteIdentifier string satellite identifier (A or B for GRACE, C or D for GRACE-FO) globalAttributes string additional attributes as \\'key: value\\' pairs', 'display_text': 'Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.'},\n'GraceAod2DoodsonHarmonics': { 'name': 'GraceAod2DoodsonHarmonics', 'key': 'GraceAod2DoodsonHarmonics', 'description': 'This program converts the atmospheric and ocean tidal products (AOD1B) from the GRACE SDS format into   This program converts the atmospheric and ocean tidal products (AOD1B) from the GRACE SDS format into  .', 'config_table': 'outputfileDoodsonHarmonics filename  inputfileTideGeneratingPotential filename to compute Xi phase correction inputfile filename', 'display_text': 'This program converts the atmospheric and ocean tidal products (AOD1B) from the GRACE SDS format into <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">outputfileDoodsonHarmonics</a>.'},\n'GraceAod2TimeSplines': { 'name': 'GraceAod2TimeSplines', 'key': 'GraceAod2TimeSplines', 'description': 'This program converts the atmospheric and ocean de-aliasing product (AOD1B) from the GRACE SDS format into  time spline files . Multiple  inputfile s must be given in the correct time order. A linear method is assumed for the interpolation between the given points in time. The GRACE SDS format is described in \"AOD1B Product Description Document\" given at  http://podaac.jpl.nasa.gov/grace/documentation.html .', 'config_table': 'outputfileDealiasing filename  outputfileAtmosphere filename  outputfileOcean filename  outputfileBottomPressure filename  outputfileMisc filename  inputfile filename', 'display_text': 'This program converts the atmospheric and ocean de-aliasing product (AOD1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_timeSplinesGravityField.html\">time spline files</a>. Multiple <strong class=\"groops-config-element\">inputfile</strong>s must be given in the correct time order. A linear method is assumed for the interpolation between the given points in time.</p><p>The GRACE SDS format is described in \"AOD1B Product Description Document\" given at <a href=\"http://podaac.jpl.nasa.gov/grace/documentation.html\" target=\"_blank\">http://podaac.jpl.nasa.gov/grace/documentation.html</a>.'},\n'GraceCoefficients2BlockMeanTimeSplines': { 'name': 'GraceCoefficients2BlockMeanTimeSplines', 'key': 'GraceCoefficients2BlockMeanTimeSplines', 'description': 'This program converts potential coefficients from the GRACE SDS RL06 format into   This program converts potential coefficients from the GRACE SDS RL06 format into  . The   This program converts potential coefficients from the GRACE SDS RL06 format into   contains the mid points of non-empty intervals and   This program converts potential coefficients from the GRACE SDS RL06 format into   contains the monthly interval boundaries from first to last solution. The output will always be monthly block means. If the SDS solutions do vary or overlap, the nearest solution in terms of reference epoch is used.', 'config_table': 'outputfileTimeSplines filename  outputfileTimeSplinesCovariance filename only the variances are saved outputfileTimeSeries filename mid points of non-empty intervals outputfileTimeIntervals filename monthly interval boundaries from first to last solution inputfile filename', 'display_text': 'This program converts potential coefficients from the GRACE SDS RL06 format into <a class=\"groops-class\" href=\"fileFormat_timeSplinesGravityField.html\">outputfileTimeSplines</a>.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeSeries</a> contains the mid points of non-empty intervals and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileTimeIntervals</a> contains the monthly interval boundaries from first to last solution.</p><p>The output will always be monthly block means. If the SDS solutions do vary or overlap, the nearest solution in terms of reference epoch is used.'},\n'GraceL1a2Accelerometer': { 'name': 'GraceL1a2Accelerometer', 'key': 'GraceL1a2Accelerometer', 'description': 'This program converts Level-1A accelerometer data (ACC1A) to the GROOPS instrument file format. The GRACE Level-1A format is described in  GRACEiolib.h  given at  http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz . The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use  InstrumentSynchronize .', 'config_table': 'outputfileAccelerometer filename ACCELEROMETER in SRF outputfileAngularAccelerometer filename ACCELEROMETER in SRF inputfile filename ACC1A', 'display_text': 'This program converts Level-1A accelerometer data (ACC1A) to the GROOPS instrument file format. The GRACE Level-1A format is described in <code>GRACEiolib.h</code> given at <a href=\"http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz\" target=\"_blank\">http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz</a>. The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.'},\n'GraceL1a2SatelliteTracking': { 'name': 'GraceL1a2SatelliteTracking', 'key': 'GraceL1a2SatelliteTracking', 'description': 'This program converts Level-1A satellite tracking data (KBR1A) to the GROOPS instrument file format. The GRACE Level-1A format is described in  GRACEiolib.h  given at  http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz . The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use  InstrumentSynchronize .', 'config_table': 'outputfileSatelliteTracking filename MISCVALUES(ant_id, K_phase, Ka_phase, K_SNR, Ka_SNR) inputfile filename KBR1A', 'display_text': 'This program converts Level-1A satellite tracking data (KBR1A) to the GROOPS instrument file format. The GRACE Level-1A format is described in <code>GRACEiolib.h</code> given at <a href=\"http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz\" target=\"_blank\">http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz</a>. The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.'},\n'GraceL1a2StarCamera': { 'name': 'GraceL1a2StarCamera', 'key': 'GraceL1a2StarCamera', 'description': 'This program converts orientation data measured by the star cameras from the GRACE Level-1A format (SCA1A) to the GROOPS instrument file format. For further information see  GraceL1a2Accelerometer .', 'config_table': 'outputfileStarCamera1 filename STARCAMERA1A, head 1 outputfileStarCamera2 filename STARCAMERA1A, head 2 inputfile filename SCA1A, !GRACE-FO is not working!', 'display_text': 'This program converts orientation data measured by the star cameras from the GRACE Level-1A format (SCA1A) to the GROOPS instrument file format. For further information see <a class=\"groops-program\" href=\"GraceL1a2Accelerometer.html\">GraceL1a2Accelerometer</a>.'},\n'GraceL1a2Temperature': { 'name': 'GraceL1a2Temperature', 'key': 'GraceL1a2Temperature', 'description': 'This program converts Level-1A temperature measurments (HRT1B or HRT1A) to the GROOPS instrument file format. The GRACE Level-1A format is described in GRACE given at  http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz . Multiple  inputfile s must be given in the correct time order. The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use  InstrumentSynchronize .', 'config_table': 'outputfileTemperature filename MISCVALUES inputfile filename HRT1B or HRT1A', 'display_text': 'This program converts Level-1A temperature measurments (HRT1B or HRT1A) to the GROOPS instrument file format. The GRACE Level-1A format is described in GRACE given at <a href=\"http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz\" target=\"_blank\">http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz</a>. Multiple <strong class=\"groops-config-element\">inputfile</strong>s must be given in the correct time order. The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.'},\n'GraceL1b2AccHousekeeping': { 'name': 'GraceL1b2AccHousekeeping', 'key': 'GraceL1b2AccHousekeeping', 'description': 'This program converts ACC housekeeping data (AHK1B or AHK1A) from the GRACE SDS format into  instrument file (ACCHOUSEKEEPING) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileAccHousekeeping filename ACCHOUSEKEEPING inputfile filename AHK1B or AHK1A', 'display_text': 'This program converts ACC housekeeping data (AHK1B or AHK1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ACCHOUSEKEEPING)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2Accelerometer': { 'name': 'GraceL1b2Accelerometer', 'key': 'GraceL1b2Accelerometer', 'description': 'This program converts accelerometer data (ACC1B or ACT1B) from the GRACE SDS format into  instrument file (ACCELEROMETER) . Multiple  inputfile s must be given in the correct time order. The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use  InstrumentSynchronize . The GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" given at  https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf .', 'config_table': 'outputfileAccelerometer filename ACCELEROMETER outputfileAngularAccelerometer filename ACCELEROMETER outputfileFlags filename MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z) inputfile filename ACC1B or ACT1B', 'display_text': 'This program converts accelerometer data (ACC1B or ACT1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ACCELEROMETER)</a>.</p><p>Multiple <strong class=\"groops-config-element\">inputfile</strong>s must be given in the correct time order. The output is one arc of satellite data which can include data gaps. To split the arc in multiple gap free arcs use <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>.</p><p>The GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" given at <a href=\"https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf\" target=\"_blank\">https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf</a>.'},\n'GraceL1b2ClockOffset': { 'name': 'GraceL1b2ClockOffset', 'key': 'GraceL1b2ClockOffset', 'description': 'This program converts clock data (CLK1B or LLK1B) from the GRACE SDS format into  instrument file (MISCVALUE) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileClock filename MISCVALUE inputfile filename CLK1B or LLK1B', 'display_text': 'This program converts clock data (CLK1B or LLK1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2GnssReceiver': { 'name': 'GraceL1b2GnssReceiver', 'key': 'GraceL1b2GnssReceiver', 'description': 'This program converts GPS receiver data (phase and pseudo range) data from the GRACE SDS format (GPS1B or GPS1A) into  instrument file (GNSSRECEIVER) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileGnssReceiver filename GNSSRECEIVER inputfile filename GPS1B or GPS1A', 'display_text': 'This program converts GPS receiver data (phase and pseudo range) data from the GRACE SDS format (GPS1B or GPS1A) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (GNSSRECEIVER)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2Magnetometer': { 'name': 'GraceL1b2Magnetometer', 'key': 'GraceL1b2Magnetometer', 'description': 'This program converts magnetometer data (MAG1B or MAG1A) from the GRACE SDS format into  instrument file (MAGNETOMETER) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileMagnetometer filename MAGNETOMETER inputfile filename MAG1B or MAG1A', 'display_text': 'This program converts magnetometer data (MAG1B or MAG1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MAGNETOMETER)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2Mass': { 'name': 'GraceL1b2Mass', 'key': 'GraceL1b2Mass', 'description': 'This program converts mass data (MAS1B or MAS1A) from the GRACE SDS format into  instrument file (MASS) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileMass filename MASS inputfile filename MAS1B or MAS1A', 'display_text': 'This program converts mass data (MAS1B or MAS1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MASS)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2Orbit': { 'name': 'GraceL1b2Orbit', 'key': 'GraceL1b2Orbit', 'description': 'This program converts the reduced dynamical orbit from the GRACE/GRACE-FO SDS format (GNV1B, GNI1B) into  instrument file (ORBIT) . When GNV1B is used, the orbit can be rotated from the terrestrial reference frame (TRF) transformed into the celestial reference frame (CRF) by specifying   This program converts the reduced dynamical orbit from the GRACE/GRACE-FO SDS format (GNV1B, GNI1B) into  . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileOrbit filename  earthRotation earthRotationType to rotate GNV1B into CRF inputfile filename GNV1B/GNI1B', 'display_text': 'This program converts the reduced dynamical orbit from the GRACE/GRACE-FO SDS format (GNV1B, GNI1B) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.</p><p>When GNV1B is used, the orbit can be rotated from the terrestrial reference frame (TRF) transformed into the celestial reference frame (CRF) by specifying <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>.</p><p>For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2SatelliteTracking': { 'name': 'GraceL1b2SatelliteTracking', 'key': 'GraceL1b2SatelliteTracking', 'description': 'This program converts low-low satellite data measured by the K-band ranging system from the GRACE SDS format (KBR1B or LRI1B) into  instrument file (SATELLITETRACKING) . The  inputfile s contain also corrections to antenna offsets and the so called light time correction. The corrections can be stored in additional files in the same format as the observations. If a phase break is found an artificial gap is created. For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileSatelliteTracking filename SATELLITETRACKING outputfileAntCentr filename SATELLITETRACKING outputfileLighttime filename SATELLITETRACKING outputfileSNR filename MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg) outputfileIonoCorr filename MISCVALUE inputfile filename KBR1B or LRI1B', 'display_text': 'This program converts low-low satellite data measured by the K-band ranging system from the GRACE SDS format (KBR1B or LRI1B) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITETRACKING)</a>. The <strong class=\"groops-config-element\">inputfile</strong>s contain also corrections to antenna offsets and the so called light time correction. The corrections can be stored in additional files in the same format as the observations. If a phase break is found an artificial gap is created. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2StarCamera': { 'name': 'GraceL1b2StarCamera', 'key': 'GraceL1b2StarCamera', 'description': 'This program converts orientation data measured by a star camera (SRF to CRF) from the GRACE SDS format (SCA1B) into  instrument file (STARCAMERA) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileStarCamera filename  outputfileStarCameraFlags filename MISCVALUES(sca_id, qual_rss, qualflg) inputfile filename SCA1B', 'display_text': 'This program converts orientation data measured by a star camera (SRF to CRF) from the GRACE SDS format (SCA1B) into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2StarCameraCovariance': { 'name': 'GraceL1b2StarCameraCovariance', 'key': 'GraceL1b2StarCameraCovariance', 'description': 'This program computes star camera covariance matrices ( instrument file, COVARIANE3D ) for a GRACE satellite under consideration of the active camera heads and an a priori variance factor.', 'config_table': 'outputfileStarCameraCovariance filename  inputfileStarCameraFlags filename  inputfileSequenceOfEventsQSA filename  sigma0 double [seconds of arc]', 'display_text': 'This program computes star camera covariance matrices (<a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file, COVARIANE3D</a>) for a GRACE satellite under consideration of the active camera heads and an a priori variance factor.'},\n'GraceL1b2SteeringMirror': { 'name': 'GraceL1b2SteeringMirror', 'key': 'GraceL1b2SteeringMirror', 'description': 'This program converts GRACE-FO Steering Mirror output (LSM1B) to an  instrument file (STARCAMERA) .', 'config_table': 'outputfileStarCamera filename  inputfile filename LSM1B', 'display_text': 'This program converts GRACE-FO Steering Mirror output (LSM1B) to an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>.'},\n'GraceL1b2Thruster': { 'name': 'GraceL1b2Thruster', 'key': 'GraceL1b2Thruster', 'description': 'This program converts thruster data (THR1B or THR1A) from the GRACE SDS format into  instrument file (THRUSTER) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileThruster filename THRUSTER inputfile filename THR1B or THR1A', 'display_text': 'This program converts thruster data (THR1B or THR1A) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (THRUSTER)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2TimeOffset': { 'name': 'GraceL1b2TimeOffset', 'key': 'GraceL1b2TimeOffset', 'description': 'This program converts time data (TIM1A or TIM1B) from the GRACE SDS format into  instrument file (MISCVALUE) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileTime filename MISCVALUE fractionalScale double 1e-6 for GRACE, 1e-9 for GRACE-FO inputfile filename TIM1A or TIM1B', 'display_text': 'This program converts time data (TIM1A or TIM1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2Uso': { 'name': 'GraceL1b2Uso', 'key': 'GraceL1b2Uso', 'description': 'This program converts clock data (USO1B) from the GRACE SDS format into  instrument file (MISCVALUES) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileUso filename MISCVALUES(uso_freq, K_freq, Ka_freq) inputfile filename USO1B', 'display_text': 'This program converts clock data (USO1B) from the GRACE SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUES)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GraceL1b2Vector': { 'name': 'GraceL1b2Vector', 'key': 'GraceL1b2Vector', 'description': 'This program reads vector orientation data (positions of instruments in the satellite frame) from the GRACE SDS format (VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B). The   This program reads vector orientation data (positions of instruments in the satellite frame) from the GRACE SDS format (VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B). The   is a   matrix containing   for each record. The GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" given at  http://podaac.jpl.nasa.gov/grace/documentation.html .', 'config_table': 'outputfileVector filename  inputfile filename VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B', 'display_text': 'This program reads vector orientation data (positions of instruments in the satellite frame) from the GRACE SDS format (VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B). The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileVector</a> is a $(3n\\\\times1)$ matrix containing $(x,y,z)$ for each record. The GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" given at <a href=\"http://podaac.jpl.nasa.gov/grace/documentation.html\" target=\"_blank\">http://podaac.jpl.nasa.gov/grace/documentation.html</a>.'},\n'GraceSequenceOfEvents': { 'name': 'GraceSequenceOfEvents', 'key': 'GraceSequenceOfEvents', 'description': 'This program converts the GRACE SOE (sequence of events) file/format into  instrument file (MISCVALUES) . The GRACE SOE format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" and \"TN-03 SOE format.txt\" given at  http://podaac.jpl.nasa.gov/grace/documentation.html . The output is one arc of satellite data which can include data gaps.', 'config_table': 'outputfileGraceA filename  outputfileGraceB filename  inputfile filename SoE file events choice  ACCT sequence DSHL HeaterDisconnect mode choice  Heater  DSHL HeaterDisconnect SetPoint  temperature set point AOCS sequence coarse pointing mode or attitude hold mode mode choice  CPM  coarse pointing mode AHM  attitude hold mode SM  science mode ACCR  ACCR CMCAL sequence CoM calibration maneuver sampling double [seconds] create events between start and end of maneuver KBRCAL sequence KBR calibration maneuver sampling double [seconds] create events between start and end of maneuver VCM  CoM coordinates in SRF (m) VKB  KBR phase center coordinates in SRF (m) ICUVP  ICUVP IPU  IPU IPUR  IPUR KAMI  KAMI: time tag offset to Ka-phase meas. KMI  K_MI: time tag offset to K-phase meas. KTOFF  KTOFF: time tag offset to KBR meas. MANV  MANV MTE1  MTE1 MTE2  MTE2 OCC  OCC QSA  SCA to SRF frame rotation QKS  SCA to KBR frame rotation', 'display_text': 'This program converts the GRACE SOE (sequence of events) file/format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUES)</a>. The GRACE SOE format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" and \"TN-03_SOE_format.txt\" given at <a href=\"http://podaac.jpl.nasa.gov/grace/documentation.html\" target=\"_blank\">http://podaac.jpl.nasa.gov/grace/documentation.html</a>. The output is one arc of satellite data which can include data gaps.'},\n'GrailCdr2Orbit': { 'name': 'GrailCdr2Orbit', 'key': 'GrailCdr2Orbit', 'description': 'This program converts the orbit from the GRAIL SDS format into   instrument file (ORBIT) .', 'config_table': 'outputfileOrbit filename  inputfile filename', 'display_text': 'This program converts the orbit from the GRAIL SDS format into  <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>.'},\n'GrailCdr2SatelliteTracking': { 'name': 'GrailCdr2SatelliteTracking', 'key': 'GrailCdr2SatelliteTracking', 'description': 'This program converts low-low satellite data measured by the K-band ranging system from the GRAIL format into  instrument file (SATELLITETRACKING) . The  inputfile s contain also corrections for antenna offsets and the so called light time correction. The corrections can be stored in additional files in the same format as the observations. If a phase break is found an artificial gap is created.', 'config_table': 'outputfileSatelliteTracking filename  outputfileAntCentr filename  outputfileLighttime filename  outputfileTemperature filename  approximateTimeBias double [seconds] inputfile filename', 'display_text': 'This program converts low-low satellite data measured by the K-band ranging system from the GRAIL format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITETRACKING)</a>. The <strong class=\"groops-config-element\">inputfile</strong>s contain also corrections for antenna offsets and the so called light time correction. The corrections can be stored in additional files in the same format as the observations. If a phase break is found an artificial gap is created.'},\n'GrailCdr2StarCamera': { 'name': 'GrailCdr2StarCamera', 'key': 'GrailCdr2StarCamera', 'description': 'This program converts orientation data measured by a star camera (SRF to CRF) from the GRAIL SDS format into  instrument file (STARCAMERA) . For further information see  GraceL1b2Accelerometer .', 'config_table': 'outputfileStarCamera filename  inputfile filename', 'display_text': 'This program converts orientation data measured by a star camera (SRF to CRF) from the GRAIL SDS format into <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a>. For further information see <a class=\"groops-program\" href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a>.'},\n'GriddedData2NetCdf': { 'name': 'GriddedData2NetCdf', 'key': 'GriddedData2NetCdf', 'description': 'This program converts a   This program converts a   to a COARDS compliant NetCDF file. The output data can be defined with  dataVariable . You should add at least the attributes  units ,  long_name , and maybe  _FillValue  to the variables. For the  dataVariable:value  the standard  dataVariables  are available to select the data columns of   This program converts a  . See also  NetCdfInfo ,  GriddedDataTimeSeries2NetCdf ,  NetCdf2GriddedData .', 'config_table': 'outputfileNetCdf filename file name of NetCDF output inputfileGriddedData filename input grid sequence dataVariable sequence metadata for data variables name string netCDF variable name value expression expression (variables \\'height\\', \\'data\\', \\'longitude\\', \\'latitude\\' and, \\'area\\' are taken from the gridded data dataType choice  double   float   int   attribute choice netCDF attributes text sequence  name string  value string  value sequence  name string  value double  dataType choice  double   float   int   globalAttribute choice additional meta data text sequence  name string  value string  value sequence  name string  value double  dataType choice  double   float   int', 'display_text': 'This program converts a <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> to a COARDS compliant NetCDF file. The output data can be defined with <strong class=\"groops-config-element\">dataVariable</strong>. You should add at least the attributes <code>units</code>, <code>long_name</code>, and maybe <code>_FillValue</code> to the variables. For the <strong class=\"groops-config-element\">dataVariable:value</strong> the standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a>.'},\n'GriddedDataTimeSeries2NetCdf': { 'name': 'GriddedDataTimeSeries2NetCdf', 'key': 'GriddedDataTimeSeries2NetCdf', 'description': 'Read a   Read a   and converts it to a COARDS compliant NetCDF file. The output data can be defined with  dataVariable . You should add at least the attributes  units ,  long_name , and maybe  _FillValue  to the variables. The  dataVariable:inputColumn  selects the data from the input file. If   Read a   is not set the temporal nodal points from the inputfile are used. See also  NetCdfInfo ,  GriddedData2NetCdf ,  NetCdf2GriddedDataTimeSeries .', 'config_table': 'outputfileNetCdf filename file name of NetCDF output inputfileGriddedDataTimeSeries filename  timeSeries timeSeriesType otherwise times from inputfile are used dataVariable sequence metadata for data variables name string netCDF variable name inputColumn uint input data column dataType choice  double   float   int   attribute choice netCDF attributes text sequence  name string  value string  value sequence  name string  value double  dataType choice  double   float   int   globalAttribute choice additional meta data text sequence  name string  value string  value sequence  name string  value double  dataType choice  double   float   int', 'display_text': 'Read a <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a> and converts it to a COARDS compliant NetCDF file.</p><p>The output data can be defined with <strong class=\"groops-config-element\">dataVariable</strong>. You should add at least the attributes <code>units</code>, <code>long_name</code>, and maybe <code>_FillValue</code> to the variables. The <strong class=\"groops-config-element\">dataVariable:inputColumn</strong> selects the data from the input file.</p><p>If <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is not set the temporal nodal points from the inputfile are used.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a>.'},\n'GroopsAscii2Orbit': { 'name': 'GroopsAscii2Orbit', 'key': 'GroopsAscii2Orbit', 'description': 'Read Orbits given in groops kinematic orbit ASCII format with covariance information. See also  Orbit2GroopsAscii .', 'config_table': 'outputfileOrbit filename  outputfileCovariance filename  earthRotation earthRotationType  inputfile filename', 'display_text': 'Read Orbits given in groops kinematic orbit ASCII format with covariance information.</p><p>See also <a class=\"groops-program\" href=\"Orbit2GroopsAscii.html\">Orbit2GroopsAscii</a>.'},\n'Hw2TideGeneratingPotential': { 'name': 'Hw2TideGeneratingPotential', 'key': 'Hw2TideGeneratingPotential', 'description': 'Write  tide generating potential  from Hartmann and Wenzel 1995 file,  https://doi.org/10.1029/95GL03324 .', 'config_table': 'outputfileTideGeneratingPotential filename  inputfile filename  headerLines uint skip number of header lines referenceTime time reference time', 'display_text': 'Write <a class=\"groops-file\" href=\"fileFormat_tideGeneratingPotential.html\">tide generating potential</a> from Hartmann and Wenzel 1995 file, <a href=\"https://doi.org/10.1029/95GL03324\" target=\"_blank\">https://doi.org/10.1029/95GL03324</a>.'},\n'Icgem2PotentialCoefficients': { 'name': 'Icgem2PotentialCoefficients', 'key': 'Icgem2PotentialCoefficients', 'description': 'Read spherical harmonics in ICGEM format ( http://icgem.gfz-potsdam.de/ ).', 'config_table': 'outputfileStaticCoefficients filename static potential coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference outputfileTrendCoefficients filename trend potential coefficients in GROOPS gfc format.  Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference outputfileOscillationCosine filename oscillation cosine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod outputfileOscillationSine filename oscillation sine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod outputfileIntervals filename two column ASCII file with all intervals found (only sensible for icgem2.0). The base name will be extended with .static, .trend, .annualCos, and .annualSin. inputfileIcgem filename ICGEM GFC file useFormalErrors boolean use formal errors if both formal and calibrated errors are given', 'display_text': 'Read spherical harmonics in ICGEM format (<a href=\"http://icgem.gfz-potsdam.de/\" target=\"_blank\">http://icgem.gfz-potsdam.de/</a>).'},\n'Iers2OceanPoleTide': { 'name': 'Iers2OceanPoleTide', 'key': 'Iers2OceanPoleTide', 'description': 'Read ocean pole tide model according to IERS conventions and convert into  oceanPoleTide file .', 'config_table': 'outputfileOceanPole filename  inputfile filename  inputfileLoadingLoveNumber filename  maxDegree uint  GM double Geocentric gravitational constant R double Reference radius Omega double [rad/s] earth rotation rho double [kg/m**3] density of sea water G double [m**3/(kg*s**2)] gravitational constant g double [m/s**2] gravity', 'display_text': 'Read ocean pole tide model according to IERS conventions and convert into <a class=\"groops-file\" href=\"fileFormat_oceanPoleTide.html\">oceanPoleTide file</a>.'},\n'IersC04IAU2000EarthOrientationParameter': { 'name': 'IersC04IAU2000EarthOrientationParameter', 'key': 'IersC04IAU2000EarthOrientationParameter', 'description': 'Read a IERS Earth orientation data C04 (IAU2000A) file and write it as   Read a IERS Earth orientation data C04 (IAU2000A) file and write it as  .', 'config_table': 'outputfileEOP filename  inputfile filename  timeStart time  timeEnd time', 'display_text': 'Read a IERS Earth orientation data C04 (IAU2000A) file and write it as <a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">outputfileEOP</a>.'},\n'IersHighFrequentEop2DoodsonEop': { 'name': 'IersHighFrequentEop2DoodsonEop', 'key': 'IersHighFrequentEop2DoodsonEop', 'description': 'Read Diurnal and Subdiurnal Earth Orientation variations according to updated IERS 2010 conventions and write them as   Read Diurnal and Subdiurnal Earth Orientation variations according to updated IERS 2010 conventions and write them as  .', 'config_table': 'outputfileDoodsonEOP filename  inputfile filename', 'display_text': 'Read Diurnal and Subdiurnal Earth Orientation variations according to updated IERS 2010 conventions and write them as <a class=\"groops-class\" href=\"fileFormat_doodsonEarthOrientationParameter.html\">outputfileDoodsonEOP</a>.'},\n'IersPotential2DoodsonHarmonics': { 'name': 'IersPotential2DoodsonHarmonics', 'key': 'IersPotential2DoodsonHarmonics', 'description': 'Read ocean tide file in IERS format.', 'config_table': 'outputfileDoodsonHarmoncis filename  inputfile filename  headerLines uint skip number of header lines minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'Read ocean tide file in IERS format.'},\n'IersRapidIAU2000EarthOrientationParameter': { 'name': 'IersRapidIAU2000EarthOrientationParameter', 'key': 'IersRapidIAU2000EarthOrientationParameter', 'description': 'Read a IERS Earth orientation rapid data and prediction file (IAU2000) and write it as   Read a IERS Earth orientation rapid data and prediction file (IAU2000) and write it as  .', 'config_table': 'outputfileEOP filename  inputfile filename  timeStart time  timeEnd time', 'display_text': 'Read a IERS Earth orientation rapid data and prediction file (IAU2000) and write it as <a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">outputfileEOP</a>.'},\n'IersWaterHeight2DoodsonHarmonics': { 'name': 'IersWaterHeight2DoodsonHarmonics', 'key': 'IersWaterHeight2DoodsonHarmonics', 'description': 'Read ocean tide file in IERS format.', 'config_table': 'outputfileDoodsonHarmoncis filename  inputfile filename  headerLines uint skip number of header lines inputfileTideGeneratingPotential filename to compute Xi phase correction kernel kernelType data type of input values factor double to convert in SI units minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius', 'display_text': 'Read ocean tide file in IERS format.'},\n'Igs2EarthOrientationParameter': { 'name': 'Igs2EarthOrientationParameter', 'key': 'Igs2EarthOrientationParameter', 'description': 'Read Rapid Earth Orientation Parameter from IGS daily file and write it as   Read Rapid Earth Orientation Parameter from IGS daily file and write it as  .', 'config_table': 'outputfileEOP filename  inputfile filename  timeStart time  timeEnd time', 'display_text': 'Read Rapid Earth Orientation Parameter from IGS daily file and write it as <a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">outputfileEOP</a>.'},\n'Jason2Starcamera': { 'name': 'Jason2Starcamera', 'key': 'Jason2Starcamera', 'description': 'This program reads in Jason star camera data given in a special  format. Files available at:  cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/ . A description of the format can be found under:  ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf', 'config_table': 'outputfileStarCamera filename  jasonNumber uint Jason number (different file format), 1 for Sentinel inputfile filename', 'display_text': 'This program reads in Jason star camera data given in a special  format. Files available at: <a href=\"cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/\" target=\"_blank\">cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/</a>. A description of the format can be found under: <a href=\"ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf\" target=\"_blank\">ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf</a>'},\n'JplAscii2Ephemerides': { 'name': 'JplAscii2Ephemerides', 'key': 'JplAscii2Ephemerides', 'description': 'Read JPL DExxx (ASCII) ephemerides.', 'config_table': 'outputfileEphemerides filename  inputfileHeader filename  inputfileData filename', 'display_text': 'Read JPL DExxx (ASCII) ephemerides.'},\n'Merit2FullRate': { 'name': 'Merit2FullRate', 'key': 'Merit2FullRate', 'description': 'Converts   and writes an  instrument file (METEOROLOGICAL)  including meteorological data like temperature, air pressure and humidity as well as an  instrument file (SATELLITELASERRANGING)  including full rate data like range, accuracy, wavelength, azimuth and elevation.', 'config_table': 'outputfileNormalPoints filename variable {station} available outputfileMeteorological filename variable {station} available inputfileSlrData filename SLR MERIT II file', 'display_text': 'Converts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html\">MERIT II file</a> and writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like temperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a> including full rate data like range, accuracy, wavelength, azimuth and elevation.'},\n'Merit2NormalPoints': { 'name': 'Merit2NormalPoints', 'key': 'Merit2NormalPoints', 'description': 'Converts   and writes an  instrument file (METEOROLOGICAL)  including meteorological data like temperature, air pressure and humidity as well as an  instrument file (SATELLITELASERRANGING)  including normal point data like range, accuracy, redundancy, wavelength, window size, azimuth and elevation.', 'config_table': 'outputfileNormalPoints filename variable {station} available outputfileMeteorological filename variable {station} available inputfileSlrData filename SLR MERIT II file', 'display_text': 'Converts <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html\">MERIT II file</a> and writes an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (METEOROLOGICAL)</a> including meteorological data like temperature, air pressure and humidity as well as an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITELASERRANGING)</a> including normal point data like range, accuracy, redundancy, wavelength, window size, azimuth and elevation.'},\n'NetCdf2GriddedData': { 'name': 'NetCdf2GriddedData', 'key': 'NetCdf2GriddedData', 'description': 'This program converts a COARDS compliant NetCDF file into an   This program converts a COARDS compliant NetCDF file into an  . If no specific input  variableNameData  are selected all suitable data are used. If the NETCDF file contains a time axis ( variableNameData ) an specific epoch can be selected with  time . The nearest epoch in file is used. See also  NetCdfInfo ,  GriddedData2NetCdf ,  NetCdf2GriddedDataTimeSeries .', 'config_table': 'outputfileGriddedData filename  inputfileNetCdf filename  variableNameLongitude string name of NetCDF variable variableNameLatitude string name of NetCDF variable variableNameTime string if with time axis: name of NetCDF variable variableNameData string data variables, otherwise all suitable data are used time time if with time axis: nearest epoch is used R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'This program converts a COARDS compliant NetCDF file into an <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">outputfileGriddedData</a>. If no specific input <strong class=\"groops-config-element\">variableNameData</strong> are selected all suitable data are used.</p><p>If the NETCDF file contains a time axis (<strong class=\"groops-config-element\">variableNameData</strong>) an specific epoch can be selected with <strong class=\"groops-config-element\">time</strong>. The nearest epoch in file is used.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a>.'},\n'NetCdf2GriddedDataTimeSeries': { 'name': 'NetCdf2GriddedDataTimeSeries', 'key': 'NetCdf2GriddedDataTimeSeries', 'description': 'This program converts a COARDS compliant NetCDF file into   This program converts a COARDS compliant NetCDF file into  . If no specific input  variableNameData  are selected all suitable data are used. See also  NetCdfInfo ,  NetCdf2GriddedData ,  GriddedDataTimeSeries2NetCdf .', 'config_table': 'outputfileGriddedDataTimeSeries filename  inputfileNetCdf filename  variableNameLongitude string name of NetCDF variable variableNameLatitude string name of NetCDF variable variableNameTime string name of NetCDF variable) variableNameData string data variables, otherwise all suitable data are used R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'This program converts a COARDS compliant NetCDF file into <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">outputfileGriddedDataTimeSeries</a>. If no specific input <strong class=\"groops-config-element\">variableNameData</strong> are selected all suitable data are used.</p><p>See also <a class=\"groops-program\" href=\"NetCdfInfo.html\">NetCdfInfo</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a>, <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a>.'},\n'NetCdfInfo': { 'name': 'NetCdfInfo', 'key': 'NetCdfInfo', 'description': 'Print content information of a NetCDF file like dimensions, variables and attributes. See also  NetCdf2GriddedData ,  NetCdf2GriddedDataTimeSeries ,  GriddedData2NetCdf ,  GriddedDataTimeSeries2NetCdf .', 'config_table': 'inputfileNetCdf filename', 'display_text': 'Print content information of a NetCDF file like dimensions, variables and attributes.</p><p>See also <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a>, <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a>, <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a>, <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a>.'},\n'NormalsSphericalHarmonics2Sinex': { 'name': 'NormalsSphericalHarmonics2Sinex', 'key': 'NormalsSphericalHarmonics2Sinex', 'description': 'Write potential coefficients and  normal equations  to  . See also  Sinex2Normals  and  GnssNormals2Sinex .', 'config_table': 'outputfileSinex filename solutions in SINEX format inputfileNormals filename normal equation matrix inputfileSolution filename parameter vector inputfileSigmax filename standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation) inputfileApriori filename apriori parameter vector inputfileAprioriMatrix filename normal equation matrix of applied constraints time time reference time for parameters sinexHeader sequence  agencyCode string identify the agency providing the data timeStart time start time of the data timeEnd time end time of the data  observationCode string technique used to generate the SINEX solution constraintCode string 0: tight constraint, 1: siginficant constraint, 2: unconstrained solutionContent string solution types contained in the SINEX solution (S O E T C A) description string organizitions gathering/alerting the file contents contact string Address of the relevant contact. e-mail output string Description of the file contents input string Brief description of the input used to generate this solution software string Software used to generate the file hardware string Computer hardware on which above software was run inputfileComment filename comments in the comment block from a file (truncated at 80 characters) comment string comments in the comment block', 'display_text': 'Write potential coefficients and <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> to <a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a>.</p><p>See also <a class=\"groops-program\" href=\"Sinex2Normals.html\">Sinex2Normals</a> and <a class=\"groops-program\" href=\"GnssNormals2Sinex.html\">GnssNormals2Sinex</a>.'},\n'OceanTidesDTU2GriddedData': { 'name': 'OceanTidesDTU2GriddedData', 'key': 'OceanTidesDTU2GriddedData', 'description': 'Convert DTU ocean tide grids to griddedData (amplitude, phase).', 'config_table': 'outputfileGriddedData filename data0=amplitude, data1=phase inputfile filename  R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'Convert DTU ocean tide grids to griddedData (amplitude, phase).'},\n'Orbit2Cpf': { 'name': 'Orbit2Cpf', 'key': 'Orbit2Cpf', 'description': 'Writes groops orbits to  . The coordinate system used in the CPF format is usually presented in ITRF. The required time format for the input orbit file is GPS. The time format of the output CPF file is given in UTC. See also  Cpf2Orbit .', 'config_table': 'outputfile filename  inputfileOrbit filename  inputfileSatelliteInfo filename Platform File earthRotation earthRotationType  versionNumber uint Version number of production day with zero leading fill, e.g. 01 targetClass uint set 1 for passive retroreflector, set 0 for no retroreflector (includes debris)', 'display_text': 'Writes groops orbits to <a href=\"https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html\">CPF file</a>.</p><p>The coordinate system used in the CPF format is usually presented in ITRF. The required time format for the input orbit file is GPS. The time format of the output CPF file is given in UTC.</p><p>See also <a class=\"groops-program\" href=\"Cpf2Orbit.html\">Cpf2Orbit</a>.'},\n'Orbit2GraceL1b': { 'name': 'Orbit2GraceL1b', 'key': 'Orbit2GraceL1b', 'description': 'This program converts an  instrument file (ORBIT)  specified in the celestial reference frame (CRF) to the GRACE/GRACE-FO SDS format (GNV1B, GNI1B). If   This program converts an   is provided, the orbit is rotated into the terrestrial reference frame as required for the GNV1B product; otherwise, a GNI1B product is written. The text file  inputfileHeader  is placed at the beginning of the  outputfile . The  text parser  is applied so that all variables can be used. In addition, the times of the data are available with the variables  {epochmin} ,  {epochmax} , and  {epochcount} . See also  GraceL1b2Orbit .', 'config_table': 'outputfile filename GNV1B/GNI1B inputfileHeader filename YAML Header, {epochmin}, {epochmax}, {epochcount} available inputfileOrbit filename  satelliteId string A, B, C or D earthRotation earthRotationType rotation into Earth fixed frame', 'display_text': 'This program converts an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a> specified in the celestial reference frame (CRF) to the GRACE/GRACE-FO SDS format (GNV1B, GNI1B). If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided, the orbit is rotated into the terrestrial reference frame as required for the GNV1B product; otherwise, a GNI1B product is written.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>. The <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used. In addition, the times of the data are available with the variables <code>{epochmin}</code>, <code>{epochmax}</code>, and <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2Orbit.html\">GraceL1b2Orbit</a>.'},\n'Orbit2GroopsAscii': { 'name': 'Orbit2GroopsAscii', 'key': 'Orbit2GroopsAscii', 'description': 'Convert groops orbits and corresponding covariance information to ASCII format. The format is used to publish TUG orbits. It contains a two line header with a short description of the orbit defined in  firstLine . The orbit is rotated to the Earth fixed frame (TRF) with   Convert groops orbits and corresponding covariance information to ASCII format. The format is used to publish TUG orbits. It contains a two line header with a short description of the orbit defined in   and given as one line per epoch. The epoch lines contained time [MJD GPS time], position x, y and z [m], and the epoch covariance xx, yy, zz, xy, xz and yz [ ]. See also  GroopsAscii2Orbit .', 'config_table': 'outputfile filename  inputfileOrbit filename  inputfileCovariance filename  earthRotation earthRotationType  firstLine string Text for first line', 'display_text': 'Convert groops orbits and corresponding covariance information to ASCII format. The format is used to publish TUG orbits. It contains a two line header with a short description of the orbit defined in <strong class=\"groops-config-element\">firstLine</strong>. The orbit is rotated to the Earth fixed frame (TRF) with <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> and given as one line per epoch. The epoch lines contained time [MJD GPS time], position x, y and z [m], and the epoch covariance xx, yy, zz, xy, xz and yz [$m^2$].</p><p>See also <a class=\"groops-program\" href=\"GroopsAscii2Orbit.html\">GroopsAscii2Orbit</a>.'},\n'Orbit2Sp3Format': { 'name': 'Orbit2Sp3Format', 'key': 'Orbit2Sp3Format', 'description': 'Writes orbits to  . SP3 orbits are usually given in the terrestrial reference frame (TRF), so providing   Writes orbits to   automatically rotates the orbits from the celestial reference frame (CRF) to the TRF. Since SP3 orbits often use the center of Earth as a reference, a correction from center of mass to center of Earth can be applied to the orbits by providing   Writes orbits to   (e.g. ocean tides). See also  Sp3Format2Orbit .', 'config_table': 'outputfile filename  satellite sequence  inputfileOrbit filename  inputfileClock filename  inputfileCovariance filename  identifier string 3 characters (e.g. GNSS PRN: G01) orbitAccuracy double [m] used for accuracy codes in header (0 = unknown) earthRotation earthRotationType rotate data into Earth-fixed frame gravityfield gravityfieldType degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth) comment string comment lines (77 char max) firstLine string Text for first line e.g:  u+U  IGb14 KIN ITSG writeVelocity boolean write velocity in addition to position useSp3kFormat boolean use the extended sp3k format', 'display_text': 'Writes orbits to <a href=\"https://files.igs.org/pub/data/format/sp3d.pdf\">SP3 format</a>.</p><p>SP3 orbits are usually given in the terrestrial reference frame (TRF), so providing <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> automatically rotates the orbits from the celestial reference frame (CRF) to the TRF. Since SP3 orbits often use the center of Earth as a reference, a correction from center of mass to center of Earth can be applied to the orbits by providing <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> (e.g. ocean tides).</p><p>See also <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a>.'},\n'PotentialCoefficients2Icgem': { 'name': 'PotentialCoefficients2Icgem', 'key': 'PotentialCoefficients2Icgem', 'description': 'Write spherical harmonics in ICGEM format. GROOPS uses this format as default but this program enables the possibility to include comments and set the modelname.', 'config_table': 'outputfile filename  inputfilePotentialCoefficients filename  inputfileTrend filename  oscillation sequence  inputfileCosPotentialCoefficients filename  inputfileSinPotentialCoefficients filename  period string period of oscillation [year] comment string comment in header inputfileComment filename file containing comments for header modelname string name of the model tideSystem choice tide system of model zero_tide   tide_free   minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius time time reference time', 'display_text': 'Write spherical harmonics in ICGEM format. GROOPS uses this format as default but this program enables the possibility to include comments and set the modelname.'},\n'PsmslOceanBottomPressure2TimeSeries': { 'name': 'PsmslOceanBottomPressure2TimeSeries', 'key': 'PsmslOceanBottomPressure2TimeSeries', 'description': 'This programs reads ocean bottom pressure time series from the Permanent Service for Mean Sea Level (PSMSL). In addition to the OBP measurements, the recorder position can be written to a  grid file .', 'config_table': 'outputfileTimeSeries filename  outputfilePosition filename recorder position as gridded data inputfile filename  isDaily boolean  ignoreBadData boolean  R double  inverseFlattening double  timeSeries timeSeriesType', 'display_text': 'This programs reads ocean bottom pressure time series from the Permanent Service for Mean Sea Level (PSMSL).</p><p>In addition to the OBP measurements, the recorder position can be written to a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">grid file</a>.'},\n'RinexObservation2GnssReceiver': { 'name': 'RinexObservation2GnssReceiver', 'key': 'RinexObservation2GnssReceiver', 'description': 'Converts   (version 2, 3, and 4) and   observation files to   Converts  . In case of   observation files containing GLONASS satellites, a mapping from PRN to frequency number must be provided via   Converts  , see  SinexMetadata2GlonassFrequencyNumber . RINEX v3+ observation files already contain this information.  Converts   and   Converts   can be used to filter the observation types that will be exported. If   Converts   is set, RINEX antenna and receiver info will be cross-checked with the provided file and warnings are raised in case of differences. A list of semi-codeless GPS receivers (observing C2D instead of C2W) can be provided via   Converts   with one receiver name per line. Observation types will be automatically corrected for these receivers. Some LEO satellites use special RINEX observation types, either from the unofficial RINEX v2.20 or custom ones. These can be provided via   Converts  . The file must  must contain a table with two columns, the first being the special type, and the second being the equivalent RINEX v3 type.', 'config_table': 'outputfileGnssReceiver filename  inputfileRinexObservation filename RINEX or Compact RINEX observation files inputfileMatrixPrn2FrequencyNumber filename (required for RINEX v2 files containing GLONASS observations), matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber inputfileStationInfo filename used to determine semi-codeless receivers and to cross-check antenna and receiver info inputfileSemiCodelessReceivers filename list with one receiver name per line inputfileSpecialObservationTypes filename table mapping special observation types to RINEX 3 types, e.g.: LA L1C useType gnssType only use observations that match any of these patterns ignoreType gnssType ignore observations that match any of these patterns', 'display_text': 'Converts <a href=\"https://files.igs.org/pub/data/format/rinex_4.00.pdf\">RINEX</a> (version 2, 3, and 4) and <a href=\"https://terras.gsi.go.jp/ja/crx2rnx.html\">Compact RINEX</a> observation files to <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileGnssReceiver</a>.</p><p>In case of <a href=\"https://files.igs.org/pub/data/format/rinex211.txt\">RINEX v2.x</a> observation files containing GLONASS satellites, a mapping from PRN to frequency number must be provided via <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrixPrn2FrequencyNumber</a>, see <a class=\"groops-program\" href=\"SinexMetadata2GlonassFrequencyNumber.html\">SinexMetadata2GlonassFrequencyNumber</a>. RINEX v3+ observation files already contain this information.</p><p><a class=\"groops-class\" href=\"gnssType.html\">useType</a> and <a class=\"groops-class\" href=\"gnssType.html\">ignoreType</a> can be used to filter the observation types that will be exported.</p><p>If <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> is set, RINEX antenna and receiver info will be cross-checked with the provided file and warnings are raised in case of differences.</p><p>A list of semi-codeless GPS receivers (observing C2D instead of C2W) can be provided via <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileSemiCodelessReceivers</a> with one receiver name per line. Observation types will be automatically corrected for these receivers.</p><p>Some LEO satellites use special RINEX observation types, either from the unofficial RINEX v2.20 or custom ones. These can be provided via <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileSpecialObservationTypes</a>. The file must  must contain a table with two columns, the first being the special type, and the second being the equivalent RINEX v3 type.</p><p>'},\n'Sacc2Orbit': { 'name': 'Sacc2Orbit', 'key': 'Sacc2Orbit', 'description': 'This program reads in SACC orbit data.', 'config_table': 'outputfileOrbit filename  inputfile filename', 'display_text': 'This program reads in SACC orbit data.'},\n'SatelliteTracking2GraceL1b': { 'name': 'SatelliteTracking2GraceL1b', 'key': 'SatelliteTracking2GraceL1b', 'description': 'This program converts low-low satellite tracking data (KBR or LRI) from the GROOPS format  instrument file (SATELLITETRACKING)  to the GRACE SDS format (KBR1B or LRI1B). It reads the satellite tracking data and optionally corrections (antenna offsets and light time corrections) and flags into one  outputfile . The text file  inputfileHeader  is placed at the beginning of the  outputfile . The  text parser  is applied so that all variables can be used. In addition, the times of the data are available with the variables  {epochmin} ,  {epochmax} , and  {epochcount} . See also  GraceL1b2SatelliteTracking .', 'config_table': 'outputfile filename KBR1B or LRI1B inputfileHeader filename YAML Header, {epochmin}, {epochmax}, {epochcount} available inputfileSatelliteTracking filename SATELLITETRACKING inputfileIonoCorr filename MISCVALUE inputfileLighttime filename SATELLITETRACKING inputfileAntCentr filename SATELLITETRACKING inputfileSNR filename MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)', 'display_text': 'This program converts low-low satellite tracking data (KBR or LRI) from the GROOPS format <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (SATELLITETRACKING)</a> to the GRACE SDS format (KBR1B or LRI1B). It reads the satellite tracking data and optionally corrections (antenna offsets and light time corrections) and flags into one <strong class=\"groops-config-element\">outputfile</strong>.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>. The <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used. In addition, the times of the data are available with the variables <code>{epochmin}</code>, <code>{epochmax}</code>, and <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2SatelliteTracking.html\">GraceL1b2SatelliteTracking</a>.'},\n'Sentinel2StarCamera': { 'name': 'Sentinel2StarCamera', 'key': 'Sentinel2StarCamera', 'description': 'This program reads in Sentinel-1/2/3 star camera data given in the special format.', 'config_table': 'outputfileStarCamera filename  inputfile filename', 'display_text': 'This program reads in Sentinel-1/2/3 star camera data given in the special format.'},\n'SentinelXml2Orbit': { 'name': 'SentinelXml2Orbit', 'key': 'SentinelXml2Orbit', 'description': 'Read Sentinel orbits from XML format.', 'config_table': 'outputfileOrbit filename  earthRotation earthRotationType  inputfile filename', 'display_text': 'Read Sentinel orbits from XML format.'},\n'Sinex2Normals': { 'name': 'Sinex2Normals', 'key': 'Sinex2Normals', 'description': 'Convert normal equations from   to  normal equations . See also  GnssNormals2Sinex  and  NormalsSphericalHarmonics2Sinex .', 'config_table': 'outputfileNormals filename N, n: unconstrained normal equations outputfileNormalsConstraint filename N0, n0: normal equations of applied constraints outputfileSolution filename x: parameter vector outputfileSolutionApriori filename x0: a priori parameter vector inputFileSinex filename', 'display_text': 'Convert normal equations from <a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a> to <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a>.</p><p>See also <a class=\"groops-program\" href=\"GnssNormals2Sinex.html\">GnssNormals2Sinex</a> and <a class=\"groops-program\" href=\"NormalsSphericalHarmonics2Sinex.html\">NormalsSphericalHarmonics2Sinex</a>.'},\n'Sinex2StationDiscontinuities': { 'name': 'Sinex2StationDiscontinuities', 'key': 'Sinex2StationDiscontinuities', 'description': 'Convert station discontinuities from   (e.g. ITRF20) to   Convert station discontinuities from   (MISCVALUE). A value of 1 means position discontinuity, a value of 2 means velocity discontinuity. Start and end epochs with value 0 are added in addition to the discontinuities from SINEX to define continuity interval borders. See also  Sinex2StationPosition  and  Sinex2StationPostSeismicDeformation .', 'config_table': 'outputfileInstrument filename loop variable is replaced with station name (e.g. wtzz) inputfileDiscontinuities filename SINEX (e.g. ITRF20) station discontinuities variableLoopStation string variable name for station loop stationName string only export these stations', 'display_text': 'Convert station discontinuities from <a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format</a> (e.g. ITRF20) to <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> (MISCVALUE). A value of 1 means position discontinuity, a value of 2 means velocity discontinuity. Start and end epochs with value 0 are added in addition to the discontinuities from SINEX to define continuity interval borders.</p><p>See also <a class=\"groops-program\" href=\"Sinex2StationPosition.html\">Sinex2StationPosition</a> and <a class=\"groops-program\" href=\"Sinex2StationPostSeismicDeformation.html\">Sinex2StationPostSeismicDeformation</a>.'},\n'Sinex2StationPositions': { 'name': 'Sinex2StationPositions', 'key': 'Sinex2StationPositions', 'description': 'Extracts station positions from  inputfileSinexSolution  ( ) and writes an   Extracts station positions from   of type VECTOR3D for each station.  Positions will be computed at   Extracts station positions from   based on position and velocity of each provided interval in the SINEX file. With  inputfileSinexDiscontinuities  the bounds of these time spans are adjusted to the exact epochs of discontinuities. The  inputfileSinexPostSeismicDeformations  adds the ITRF post-seismic deformation model to the affected stations. The  inputfileSinexFrequencies  adds annual and semi-annual frequencies. If  extrapolateBackward  or  extrapolateForward  are provided, positions will also be computed for epochs before the first interval/after the last interval, based on the position and velocity of the first/last interval. Position extrapolation will stop at the first discontinuity before the first interval/after the last interval. Stations can be limited via  stationName , otherwise all stations in  inputfileSinexSolution  will be used.', 'config_table': 'outputfileInstrument filename loop variable is replaced with station name (e.g. wtzz) variableLoopStation string variable name for station loop inputfileSinexSolution filename SINEX file inputfileSinexDiscontinuities filename SINEX file inputfileSinexPostSeismicDeformations filename SINEX file inputfileSinexFrequencies filename SINEX file (XYZ or ENU) timeSeries timeSeriesType compute positions for these epochs based on velocity extrapolateForward boolean also compute positions for epochs after last interval defined in SINEX file extrapolateBackward boolean also compute positions for epochs before first interval defined in SINEX file stationName string convert only these stations', 'display_text': 'Extracts station positions from <strong class=\"groops-config-element\">inputfileSinexSolution</strong> (<a href=\"http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html\">SINEX format description</a>) and writes an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileInstrument</a> of type VECTOR3D for each station.  Positions will be computed at <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> based on position and velocity of each provided interval in the SINEX file. With <strong class=\"groops-config-element\">inputfileSinexDiscontinuities</strong> the bounds of these time spans are adjusted to the exact epochs of discontinuities. The <strong class=\"groops-config-element\">inputfileSinexPostSeismicDeformations</strong> adds the ITRF post-seismic deformation model to the affected stations. The <strong class=\"groops-config-element\">inputfileSinexFrequencies</strong> adds annual and semi-annual frequencies.</p><p>If <strong class=\"groops-config-element\">extrapolateBackward</strong> or <strong class=\"groops-config-element\">extrapolateForward</strong> are provided, positions will also be computed for epochs before the first interval/after the last interval, based on the position and velocity of the first/last interval. Position extrapolation will stop at the first discontinuity before the first interval/after the last interval.</p><p>Stations can be limited via <strong class=\"groops-config-element\">stationName</strong>, otherwise all stations in <strong class=\"groops-config-element\">inputfileSinexSolution</strong> will be used.'},\n'SinexEccentricties2SlrPlatform': { 'name': 'SinexEccentricties2SlrPlatform', 'key': 'SinexEccentricties2SlrPlatform', 'description': 'Reads metadata like station name, station number, approximate station position and station eccentricities from   (une version) and write them to the   Reads metadata like station name, station number, approximate station position and station eccentricities from   for each station.', 'config_table': 'outputfileStationInfo filename loop variable is replaced with station name variableLoopStation string variable name for station loop inputfileSinex filename SINEX file (.snx or .ssc) stationName string convert only these stations', 'display_text': 'Reads metadata like station name, station number, approximate station position and station eccentricities from <a href=\"https://ilrs.gsfc.nasa.gov/network/site_procedures/eccentricity.html\">Station Eccentricities Sinex File</a> (une version) and write them to the <a class=\"groops-class\" href=\"fileFormat_platform.html\">outputfileStationInfo</a> for each station.'},\n'SinexMetadata2GlonassFrequencyNumber': { 'name': 'SinexMetadata2GlonassFrequencyNumber', 'key': 'SinexMetadata2GlonassFrequencyNumber', 'description': 'Create   Create   matrix from   with the columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber. See also  GnssGlonassFrequencyNumberUpdate ,  GnssAntex2AntennaDefinition ,  RinexObservation2GnssReceiver .', 'config_table': 'outputfileMatrixPrn2FrequencyNumber filename GROOPS matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber inputfileSinexMetadata filename IGS SINEX metadata file', 'display_text': 'Create <a class=\"groops-class\" href=\"fileFormat_matrix.html\">outputfileMatrixPrn2FrequencyNumber</a> matrix from <a href=\"https://www.igs.org/mgex/metadata/#metadata\">IGS SINEX metadata format</a> with the columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber.</p><p>See also <a class=\"groops-program\" href=\"GnssGlonassFrequencyNumberUpdate.html\">GnssGlonassFrequencyNumberUpdate</a>, <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>, <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>.'},\n'SinexMetadata2SatelliteModel': { 'name': 'SinexMetadata2SatelliteModel', 'key': 'SinexMetadata2SatelliteModel', 'description': 'Create   Create   from  . If   Create   is provided it is used as a basis and values are updated from the metadata file. See also  SatelliteModelCreate .', 'config_table': 'outputfileSatelliteModel filename  inputfileSinexMetadata filename IGS SINEX metadata file inputfileSatelliteModel filename base satellite model svn string e.g. G040, R736, E204, C211', 'display_text': 'Create <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">outputfileSatelliteModel</a> from <a href=\"https://www.igs.org/mgex/metadata/#metadata\">IGS SINEX metadata format</a>.</p><p>If <a class=\"groops-class\" href=\"fileFormat_satelliteModel.html\">inputfileSatelliteModel</a> is provided it is used as a basis and values are updated from the metadata file.</p><p>See also <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a>.'},\n'SlrComModel2RangeBiasStationSatellite': { 'name': 'SlrComModel2RangeBiasStationSatellite', 'key': 'SlrComModel2RangeBiasStationSatellite', 'description': 'Converts the tables of CoM corrections of José Rodríguez ( https://icts-yebes.oan.es/slr/com_models/models/ ) into station/satellite specific   Converts the tables of CoM corrections of José Rodríguez ( . Only the deviations to the default value in   Converts the tables of CoM corrections of José Rodríguez (  are written. This program must be called for every provided satellite. The range bias values can be used in   Converts the tables of CoM corrections of José Rodríguez (  in  SlrProcessing . Reference: Rodriguez J., Otsubo T., Appleby G. Upgraded Modelling for the Determination of Centre of Mass Corrections of Geodetic SLR Satellites: Impact on Key Parameters of the Terrestrial Reference Frame. Journal of Geodesy, 2019. doi: 10.1007/s00190-019-01315-0', 'config_table': 'outputfileRangeBias filename MISCVALUE, variable {station} available inputfileSatelliteInfo filename  inputfile filename from Rodriguez model variableLoopStation string variable name for station loop stationName string convert only these stations', 'display_text': 'Converts the tables of CoM corrections of José Rodríguez (<a href=\"https://icts-yebes.oan.es/slr/com_models/models/\" target=\"_blank\">https://icts-yebes.oan.es/slr/com_models/models/</a>) into station/satellite specific <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileRangeBias</a>. Only the deviations to the default value in <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileSatelliteInfo</a> are written. This program must be called for every provided satellite. The range bias values can be used in <a class=\"groops-class\" href=\"slrParametrizationType.html#rangeBiasStationSatelliteApriori\">parametrization:rangeBiasStationSatelliteApriori</a> in <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.</p><p>Reference: Rodriguez J., Otsubo T., Appleby G. Upgraded Modelling for the Determination of Centre of Mass Corrections of Geodetic SLR Satellites: Impact on Key Parameters of the Terrestrial Reference Frame. Journal of Geodesy, 2019. doi: 10.1007/s00190-019-01315-0'},\n'SlrSinexDataHandling2Files': { 'name': 'SlrSinexDataHandling2Files', 'key': 'SlrSinexDataHandling2Files', 'description': 'Converts SLR range and time bias from  ILRS_Data_Handling_File_xxxx.xx.xx.snx  provided at  https://cddis.nasa.gov/archive/slr/products/resource/ . The range and time bias values can be used in   Converts SLR range and time bias from   in  SlrProcessing .', 'config_table': 'outputfileRangeBiasStation filename MISCVALUE [m] outputfileRangeBiasStationSatellite filename MISCVALUE [m] outputfileTimeBias filename MISCVALUES(bias [s], drift [s/d]) variableLoopStation string variable name for station loop variableLoopSatellite string variable name for satellite loop inputfileSinex filename SINEX file (.snx) inputfileSatelliteId filename table SP3 and satellite name stationName string convert only these stations', 'display_text': 'Converts SLR range and time bias from <code>ILRS_Data_Handling_File_xxxx.xx.xx.snx</code> provided at <a href=\"https://cddis.nasa.gov/archive/slr/products/resource/\" target=\"_blank\">https://cddis.nasa.gov/archive/slr/products/resource/</a>. The range and time bias values can be used in <a class=\"groops-class\" href=\"slrParametrizationType.html#rangeBiasStationApriori\">parametrization:rangeBiasXxxApriori</a> in <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.'},\n'Sp3Format2Orbit': { 'name': 'Sp3Format2Orbit', 'key': 'Sp3Format2Orbit', 'description': 'Read orbits from   and write an  instrument file (ORBIT) . The additional  outputfileClock  is an  instrument file (MISCVALUE)  and  outputfileCovariance  is an  instrument file (COVARIANCE3D) . With  satelliteIdentifier  a single satellite can be selected if the  inputfile s contain more than one satellites. If  satelliteIdentifier  is empty the first satellite is taken. All satellites can be selected with  satelliteIdentifier = &lt;all> . In this case the identifier is appended to each output file. If   Read orbits from   is provided the data are transformed from terrestrial (TRF) to celestial reference frame (CRF). Since SP3 orbits often use the center of Earth as a reference, a correction from center of Earth to center of mass can be applied to the orbits by providing   Read orbits from   (e.g. ocean tides). See also  Orbit2Sp3Format .', 'config_table': 'outputfileOrbit filename  outputfileClock filename  outputfileCovariance filename 3x3 epoch covariance satelliteIdentifier string e.g. L09 for GRACE A, empty: take first satellite, <all>: identifier is appended to each file earthRotation earthRotationType rotation from TRF to CRF gravityfield gravityfieldType degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth) inputfile filename orbits in SP3 format', 'display_text': 'Read orbits from <a href=\"https://files.igs.org/pub/data/format/sp3d.pdf\">SP3 format</a> and write an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (ORBIT)</a>. The additional <strong class=\"groops-config-element\">outputfileClock</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (MISCVALUE)</a> and <strong class=\"groops-config-element\">outputfileCovariance</strong> is an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (COVARIANCE3D)</a>.</p><p>With <strong class=\"groops-config-element\">satelliteIdentifier</strong> a single satellite can be selected if the <strong class=\"groops-config-element\">inputfile</strong>s contain more than one satellites. If <strong class=\"groops-config-element\">satelliteIdentifier</strong> is empty the first satellite is taken. All satellites can be selected with <strong class=\"groops-config-element\">satelliteIdentifier</strong>=<code>&lt;all></code>. In this case the identifier is appended to each output file.</p><p>If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided the data are transformed from terrestrial (TRF) to celestial reference frame (CRF). Since SP3 orbits often use the center of Earth as a reference, a correction from center of Earth to center of mass can be applied to the orbits by providing <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> (e.g. ocean tides).</p><p>See also <a class=\"groops-program\" href=\"Orbit2Sp3Format.html\">Orbit2Sp3Format</a>.'},\n'StarCamera2GraceL1b': { 'name': 'StarCamera2GraceL1b', 'key': 'StarCamera2GraceL1b', 'description': 'This program converts orientation data measured by a star camera (SRF to CRF) from the GROOPS format  instrument file (STARCAMERA)  to the GRACE SDS format (SCA1B). It reads one  inputfileStarCamera  and optionally one  inputfileStarCameraFlags  containing  MISCVALUES (sca id, qual rss, qualflg), and writes one SDS output file. The text file  inputfileHeader  is placed at the beginning of the  outputfile . The  text parser  is applied so that all variables can be used. In addition, the times of the data are available with the variables  {epochmin} , | {epochmax} , and  {epochcount} . See also  GraceL1b2StarCamera .', 'config_table': 'outputfile filename SCA1B inputfileHeader filename YAML Header, {epochmin}, {epochmax}, {epochcount} available inputfileStarCamera filename STARCAMERA inputfileStarCameraFlags filename MISCVALUES(sca_id, qual_rss, qualflg) satelliteId string A, B, C or D', 'display_text': 'This program converts orientation data measured by a star camera (SRF to CRF) from the GROOPS format <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a> to the GRACE SDS format (SCA1B).</p><p>It reads one <strong class=\"groops-config-element\">inputfileStarCamera</strong> and optionally one <strong class=\"groops-config-element\">inputfileStarCameraFlags</strong> containing <a class=\"groops-file\" href=\"fileFormat_instrument.html\">MISCVALUES</a>(sca_id, qual_rss, qualflg), and writes one SDS output file.</p><p>The text file <strong class=\"groops-config-element\">inputfileHeader</strong> is placed at the beginning of the <strong class=\"groops-config-element\">outputfile</strong>. The <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied so that all variables can be used. In addition, the times of the data are available with the variables <code>{epochmin}</code>, |<code>{epochmax}</code>, and <code>{epochcount}</code>.</p><p>See also <a class=\"groops-program\" href=\"GraceL1b2StarCamera.html\">GraceL1b2StarCamera</a>.'},\n'StarCamera2Orbex': { 'name': 'StarCamera2Orbex', 'key': 'StarCamera2Orbex', 'description': 'Converts satellite attitude from  instrument file (STARCAMERA)  to   (quaternions). If   Converts satellite attitude from   is provided, the output file contains quaternions for rotation from TRF to satellite body frame (IGS/ORBEX convention), otherwise the rotation is from CRF to satellite body frame. See also  GnssOrbex2StarCamera ,  SimulateStarCameraGnss .', 'config_table': 'outputfileOrbex filename ORBEX file satellite sequence  inputfileStarCamera filename  identifier string string identifier (e.g. GNSS PRN: G01) description string e.g. BLOCK IIR-B, GRACE earthRotation earthRotationType rotate data into Earth-fixed frame timeSeries timeSeriesType resample to these epochs (otherwise input file epochs are used) interpolationDegree uint for attitude and Earth rotation interpolation description string description of file contents createdBy string name of agency inputData string description of input data (see ORBEX description) contact string email address referenceFrame string reference frame used in file comment string', 'display_text': 'Converts satellite attitude from <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file (STARCAMERA)</a> to <a href=\"http://acc.igs.org/misc/ORBEX009.pdf\">ORBEX file format</a> (quaternions).</p><p>If <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> is provided, the output file contains quaternions for rotation from TRF to satellite body frame (IGS/ORBEX convention), otherwise the rotation is from CRF to satellite body frame.</p><p>See also <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>, <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>.'},\n'Swarm2Starcamera': { 'name': 'Swarm2Starcamera', 'key': 'Swarm2Starcamera', 'description': 'This program reads SWARM star camera data given in the cdf format and before converted to an ascii file using the program  cdfexport  provided by the Goddard Space Flight Center ( http://cdf.gsfc.nasa.gov/ ).', 'config_table': 'outputfileStarCamera filename  earthRotation earthRotationType  inputfile filename', 'display_text': 'This program reads SWARM star camera data given in the cdf format and before converted to an ascii file using the program <code>cdfexport</code> provided by the Goddard Space Flight Center (<a href=\"http://cdf.gsfc.nasa.gov/\" target=\"_blank\">http://cdf.gsfc.nasa.gov/</a>).'},\n'TerraSarTandem2Orbit': { 'name': 'TerraSarTandem2Orbit', 'key': 'TerraSarTandem2Orbit', 'description': 'This program reads in TerraSar-X or Tandem-X orbits in the special CHORB format and takes the appropriate time frame as stated in the document header. A description of the format can be found under:  http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf', 'config_table': 'outputfileOrbit filename  earthRotation earthRotationType  inputfile filename orbits in CHORB format', 'display_text': 'This program reads in TerraSar-X or Tandem-X orbits in the special CHORB format and takes the appropriate time frame as stated in the document header. A description of the format can be found under: <a href=\"http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf\" target=\"_blank\">http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf</a>'},\n'TerraSarTandem2StarCamera': { 'name': 'TerraSarTandem2StarCamera', 'key': 'TerraSarTandem2StarCamera', 'description': 'This program reads in TerraSar-X or Tandem-X star camera data given in the special format.', 'config_table': 'outputfileStarCamera filename  inputfile filename', 'display_text': 'This program reads in TerraSar-X or Tandem-X star camera data given in the special format.'},\n'Tle2Orbit': { 'name': 'Tle2Orbit', 'key': 'Tle2Orbit', 'description': 'This program computes the   This program computes the   from two-line elements (TLE/3LE) as can be found at e.g.  http://celestrak.org/NORAD/elements/ . The first satellite in the input file that matches the wildcard of  satelliteName  is used. If more records with exactly the same name are found, the one with the closest reference epoch is used for each point in the   This program computes the  . The program uses the Simplified General Perturbation (SGP) model. More information can be found in the Revisiting Spacetrack Report 3 by Vallado et al. 2006.', 'config_table': 'outputfileOrbit filename  inputfileTLE filename two line elements (TLE/3LE) satelliteName string first name of wildcard match is used timeSeries timeSeriesType output orbit at these times earthRotation earthRotationType rotation to CRF', 'display_text': 'This program computes the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileOrbit</a> from two-line elements (TLE/3LE) as can be found at e.g. <a href=\"http://celestrak.org/NORAD/elements/\" target=\"_blank\">http://celestrak.org/NORAD/elements/</a>. The first satellite in the input file that matches the wildcard of <strong class=\"groops-config-element\">satelliteName</strong> is used. If more records with exactly the same name are found, the one with the closest reference epoch is used for each point in the <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a>.</p><p>The program uses the Simplified General Perturbation (SGP) model. More information can be found in the Revisiting Spacetrack Report 3 by Vallado et al. 2006.'},\n'ViennaMappingFunctionGrid2File': { 'name': 'ViennaMappingFunctionGrid2File', 'key': 'ViennaMappingFunctionGrid2File', 'description': 'This program converts the gridded time series of the Vienna Mapping Functions (VMF) into the  GROOPS file format . Gridded VMF data is available at:  https://vmf.geo.tuwien.ac.at/trop_products/GRID/', 'config_table': 'outputfileVmfCoefficients filename  inputfile filename files must be given for each point in time timeSeries timeSeriesType times of input files deltaLambda angle [deg] sampling in longitude deltaPhi angle [deg] sampling in latitude isCellRegistered boolean grid points represent cells (VMF3), not grid corners (VMF1)', 'display_text': 'This program converts the gridded time series of the Vienna Mapping Functions (VMF) into the <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">GROOPS file format</a>.</p><p>Gridded VMF data is available at: <a href=\"https://vmf.geo.tuwien.ac.at/trop_products/GRID/\" target=\"_blank\">https://vmf.geo.tuwien.ac.at/trop_products/GRID/</a>'},\n'ViennaMappingFunctionStation2File': { 'name': 'ViennaMappingFunctionStation2File', 'key': 'ViennaMappingFunctionStation2File', 'description': 'Converts Vienna Mapping Functions (VMF) station time series into  GROOPS file format . Station-wise VMF data for GNSS is available at:  https://vmf.geo.tuwien.ac.at/trop_products/GNSS/', 'config_table': 'outputfileVmfCoefficients filename  inputfileStationInfo filename  inputfileStation filename  inputfileVmf filename', 'display_text': 'Converts Vienna Mapping Functions (VMF) station time series into <a class=\"groops-file\" href=\"fileFormat_griddedDataTimeSeries.html\">GROOPS file format</a>.</p><p>Station-wise VMF data for GNSS is available at: <a href=\"https://vmf.geo.tuwien.ac.at/trop_products/GNSS/\" target=\"_blank\">https://vmf.geo.tuwien.ac.at/trop_products/GNSS/</a>'},\n'GnssAttitude2Orbex': { 'name': 'GnssAttitude2Orbex', 'key': 'GnssAttitude2Orbex', 'description': 'DEPRECATED since 2024-11-30. Please use  StarCamera2Orbex  instead.', 'config_table': 'outputfileOrbex filename ORBEX file inputfileTransmitterList filename ASCII list with transmitter PRNs inputfileAttitude filename instrument file containing attitude variablePrn string loop variable for PRNs from transmitter list timeSeries timeSeriesType resample to these epochs (otherwise input file epochs are used) earthRotation earthRotationType rotate data into Earth-fixed frame interpolationDegree uint for attitude and Earth rotation interpolation description string description of file contents createdBy string name of agency inputData string description of input data (see ORBEX description) contact string email address referenceFrame string reference frame used in file comment string', 'display_text': 'DEPRECATED since 2024-11-30. Please use <a class=\"groops-program\" href=\"StarCamera2Orbex.html\">StarCamera2Orbex</a> instead.'},\n'GnssPrn2SvnBlockVariables': { 'name': 'GnssPrn2SvnBlockVariables', 'key': 'GnssPrn2SvnBlockVariables', 'description': 'DEPRECATED since 2024-02-12. This program no longer works! Setup up a   DEPRECATED since 2024-02-12. This program no longer works!  instead with       DEPRECATED since 2024-02-12. This program no longer works! : the old  inputfileTransmitterInfo     equipmentType          =  gnssAntenna     variableLoopName       =  block     variableLoopSerial     =  svn     variableLoopTimeStart  =  svnTimeStart     variableLoopTimeEnd    =  svnTimeEnd      DEPRECATED since 2024-02-12. This program no longer works!           expression  =  (svnTimeStart &lt;= time) && (time &lt; svnTimeEnd)        Attribute this loop to programs, which uses the variables.', 'config_table': '', 'display_text': 'DEPRECATED since 2024-02-12. This program no longer works!</p><p>Setup up a <a class=\"groops-class\" href=\"loopType.html#platformEquipment\">loop:platformEquipment</a> instead with <ul>    <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfilePlatform</a>: the old <strong class=\"groops-config-element\">inputfileTransmitterInfo</strong>   </li><li> <strong class=\"groops-config-element\">equipmentType</strong>         = <code>gnssAntenna</code>   </li><li> <strong class=\"groops-config-element\">variableLoopName</strong>      = <code>block</code>   </li><li> <strong class=\"groops-config-element\">variableLoopSerial</strong>    = <code>svn</code>   </li><li> <strong class=\"groops-config-element\">variableLoopTimeStart</strong> = <code>svnTimeStart</code>   </li><li> <strong class=\"groops-config-element\">variableLoopTimeEnd</strong>   = <code>svnTimeEnd</code>   </li><li> <a class=\"groops-class\" href=\"conditionType.html#expression\">condition:expression</a>   <ul>      </li><li> <strong class=\"groops-config-element\">expression</strong> = <code>(svnTimeStart &lt;= time) && (time &lt; svnTimeEnd)</code>   </li></ul>  </ul> Attribute this loop to programs, which uses the variables.'},\n'GnssStationInfoCreate': { 'name': 'GnssStationInfoCreate', 'key': 'GnssStationInfoCreate', 'description': 'DEPRECATED since 2024-12-02. Please use  PlatformCreate  instead.', 'config_table': 'outputfileStationInfo filename  markerName string  markerNumber string  comment string  approxPositionX double [m] in TRF approxPositionY double [m] in TRF approxPositionZ double [m] in TRF antenna sequence  name string  serial string  radome string  comment string  timeStart time  timeEnd time  positionX double [m] ARP in north, east, up or vehicle system positionY double [m] ARP in north, east, up or vehicle system positionZ double [m] ARP in north, east, up or vehicle system rotationX angle [degree] from local/vehicle to left-handed antenna system rotationY angle [degree] from local/vehicle to left-handed antenna system rotationZ angle [degree] from local/vehicle to left-handed antenna system flipX boolean flip x-axis (after rotation) flipY boolean flip y-axis (after rotation) flipZ boolean flip z-axis (after rotation) receiver sequence  name string  serial string  version string  comment string  timeStart time  timeEnd time  referencePoint sequence e.g. center of mass in satellite frame comment string  xStart double [m] in north, east, up or vehicle system yStart double linear motion between start and end zStart double  xEnd double [m] in north, east, up or vehicle system yEnd double linear motion between start and end zEnd double  timeStart time  timeEnd time', 'display_text': 'DEPRECATED since 2024-12-02. Please use <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a> instead.'},\n'GridRectangular2NetCdf': { 'name': 'GridRectangular2NetCdf', 'key': 'GridRectangular2NetCdf', 'description': 'DEPRECATED since 2023-07-06. Please use  GriddedData2NetCdf  or  GriddedDataTimeSeries2NetCdf  instead.', 'config_table': 'outputfileNetCdf filename file name of NetCDF output inputfileGridRectangular filename input grid sequence times timeSeriesType values for time axis (COARDS specification) dataVariable sequence metadata for data variables selectDataField uint input data column name string netCDF variable name dataType choice  double   float   int   attribute choice netCDF attributes text sequence  name string  value string  value sequence  name string  value double  dataType choice  double   float   int   globalAttribute choice additional meta data text sequence  name string  value string  value sequence  name string  value double  dataType choice  double   float   int', 'display_text': 'DEPRECATED since 2023-07-06. Please use <a class=\"groops-program\" href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a> or <a class=\"groops-program\" href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a> instead.'},\n'NetCdf2GridRectangular': { 'name': 'NetCdf2GridRectangular', 'key': 'NetCdf2GridRectangular', 'description': 'DEPRECATED since 2023-07-06. Please use  NetCdf2GriddedData  or  NetCdf2GriddedDataTimeSeries  instead.', 'config_table': 'outputfileGridRectangular filename One grid for each epoch in the NetCDF file is written. Use loopTimeVariable as template. loopTimeVariable string  inputfileNetCdf filename  variableNameLongitude string name of NetCDF variable variableNameLatitude string name of NetCDF variable variableNameTime string name of NetCDF variable (leave blank for static grids) variableNameData string name of NetCDF variable R double reference radius for ellipsoidal coordinates inverseFlattening double reference flattening for ellipsoidal coordinates', 'display_text': 'DEPRECATED since 2023-07-06. Please use <a class=\"groops-program\" href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a> or <a class=\"groops-program\" href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a> instead.'},\n'Sinex2StationPosition': { 'name': 'Sinex2StationPosition', 'key': 'Sinex2StationPosition', 'description': 'DEPRECATED since 2023-02-16. Please use  Sinex2StationPositions  instead.', 'config_table': 'outputfileInstrument filename loop variable is replaced with station name (e.g. wtzz) inputfileSinex filename SINEX file (.snx or .ssc) inputfileDiscontinuities filename discontinuities file per station; loop variable is replaced with station name (e.g. wtzz) variableLoopStation string variable name for station loop stationName string convert only these stations timeSeries timeSeriesType compute positions for these epochs based on velocity extrapolateForward boolean also compute positions for epochs after last interval defined in SINEX file extrapolateBackward boolean also compute positions for epochs before first interval defined in SINEX file', 'display_text': 'DEPRECATED since 2023-02-16. Please use <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a> instead.'},\n'Sinex2StationPostSeismicDeformation': { 'name': 'Sinex2StationPostSeismicDeformation', 'key': 'Sinex2StationPostSeismicDeformation', 'description': 'DEPRECATED since 2023-02-16. Please use  Sinex2StationPositions  instead.', 'config_table': 'outputfileInstrument filename deformation time series inputfileSinex filename ITRF post-seismic deformation SINEX file timeSeries timeSeriesType compute deformation for these epochs stationName string  localLevelFrame boolean output in North, East, Up local-level frame', 'display_text': 'DEPRECATED since 2023-02-16. Please use <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a> instead.'},\n'autoregressiveModelSequenceType': { 'name': 'autoregressiveModelSequenceType', 'key': 'autoregressiveModelSequenceType', 'description': 'Represents a sequence of multivariate autoregressive (AR) models with increasing order  . The AR models should be stored as  matrix file  in the  GROOPS definition of AR models . The required AR models can be computed with  CovarianceMatrix2AutoregressiveModel , and passed to this class through  inputfileAutoregressiveModel  in increasing order. The main purpose of AutoregressiveModelSequence is to use AR models of the form  to create pseudo-observation equations  with  used to constrain high-frequency temporal gravity field variations (see  KalmanSmootherLeastSquares ,  NormalsBuildShortTimeStaticLongTime ,  PreprocessingSst ). The corresponding normal equation coefficient matrix is given by  and if all AR models are estimated from the same sample its inverse is a block-Toeplitz covariance matrix  which can be computed using  AutoregressiveModel2CovarianceMatrix . A detailed description with applications can be found in: Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties. J Geod 93, 2543–2552 (2019).  https://doi.org/10.1007/s00190-019-01314-1', 'config_table': 'autoregressiveModelSequenceType sequence  inputfileAutoregressiveModel filename matrix file containing an AR model sigma0 double a-priori sigma for white noise covariance', 'display_text': 'Represents a sequence of multivariate autoregressive (AR) models with increasing order $p$. The AR models should be stored as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix file</a> in the <a class=\"groops-ref\" href=\"fundamentals.autoregressiveModel.html\">GROOPS definition of AR models</a>. The required AR models can be computed with <a class=\"groops-program\" href=\"CovarianceMatrix2AutoregressiveModel.html\">CovarianceMatrix2AutoregressiveModel</a>, and passed to this class through <strong class=\"groops-config-element\">inputfileAutoregressiveModel</strong> in increasing order.</p><p>The main purpose of AutoregressiveModelSequence is to use AR models of the form \\\\[   \\\\label{eq:ar-model}   \\\\mathbf{y}_e(t_i) = \\\\sum_{k=1}^p \\\\mathbf{\\\\Phi}^{(p)}_k\\\\mathbf{y}_e(t_{i-k}) + \\\\mathbf{w}(t_i),   \\\\hspace{5pt} \\\\mathbf{w}(t_i) \\\\sim \\\\mathcal{N}(0, \\\\mathbf{\\\\Sigma}^{(p)}_\\\\mathbf{w}), \\\\]to create pseudo-observation equations \\\\[   \\\\label{eq:pseudo-observations-transformed}   0 = \\\\bar{\\\\mathbf{\\\\Phi}} \\\\Delta\\\\mathbf{y} + \\\\bar{\\\\mathbf{w}}, \\\\hspace{5pt} \\\\bar{\\\\mathbf{w}} \\\\sim   \\\\mathcal{N}(0, \\\\bar{\\\\mathbf{\\\\Sigma}}_{\\\\bar{\\\\mathbf{w}}}), \\\\]with \\\\[   \\\\label{eq:pseudo-observations-ar}   \\\\bar{\\\\mathbf{\\\\Phi}} =   \\\\begin{bmatrix}     \\\\mathbf{I} & & & & & \\\\\\\\     -\\\\mathbf{\\\\Phi}^{(1)}_1 & \\\\mathbf{I} & & & &  \\\\\\\\     -\\\\mathbf{\\\\Phi}^{(2)}_2 & -\\\\mathbf{\\\\Phi}^{(2)}_1 & \\\\mathbf{I} & & & \\\\\\\\     -\\\\mathbf{\\\\Phi}^{(3)}_3 & -\\\\mathbf{\\\\Phi}^ {(3)}_2 & -\\\\mathbf{\\\\Phi}^ {(3)}_1 & \\\\mathbf{I} & &  \\\\\\\\     & -\\\\mathbf{\\\\Phi}^{(3)}_3 & -\\\\mathbf{\\\\Phi}^ {(3)}_2 & -\\\\mathbf{\\\\Phi}^ {(3)}_1 & \\\\mathbf{I} &  \\\\\\\\     & & \\\\ddots & \\\\ddots & \\\\ddots & \\\\ddots  \\\\\\\\   \\\\end{bmatrix},   \\\\hspace{15pt}   \\\\bar{\\\\mathbf{\\\\Sigma}}_{\\\\bar{\\\\mathbf{w}}} =   \\\\bar{\\\\mathbf{\\\\Sigma}}_{\\\\bar{\\\\mathbf{w}}} =   \\\\begin{bmatrix}     \\\\mathbf{\\\\Sigma}^{(0)}_{\\\\mathbf{w}} & & & & & \\\\\\\\     & \\\\mathbf{\\\\Sigma}^{(1)}_{\\\\mathbf{w}} & & & & \\\\\\\\     & & \\\\mathbf{\\\\Sigma}^{(2)}_{\\\\mathbf{w}} & & & \\\\\\\\     & & & \\\\mathbf{\\\\Sigma}^{(3)}_{\\\\mathbf{w}} & & \\\\\\\\     & & & & \\\\mathbf{\\\\Sigma}^{(3)}_{\\\\mathbf{w}} &  \\\\\\\\     & & & & & \\\\ddots \\\\\\\\   \\\\end{bmatrix}. \\\\]used to constrain high-frequency temporal gravity field variations (see <a class=\"groops-program\" href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a>, <a class=\"groops-program\" href=\"NormalsBuildShortTimeStaticLongTime.html\">NormalsBuildShortTimeStaticLongTime</a>, <a class=\"groops-program\" href=\"PreprocessingSst.html\">PreprocessingSst</a>).</p><p>The corresponding normal equation coefficient matrix is given by \\\\[   \\\\label{eq:ar-normals}   \\\\bar{\\\\mathbf{\\\\Phi}}^T\\\\bar{\\\\mathbf{\\\\Sigma}}^{-1}_{\\\\bar{\\\\mathbf{w}}}\\\\bar{\\\\mathbf{\\\\Phi}} \\\\]and if all AR models are estimated from the same sample its inverse is a block-Toeplitz covariance matrix \\\\[   (\\\\mathbf{\\\\Sigma}_{\\\\mathbf{y}_m})_{ij} =   \\\\begin{cases}  \\\\mathbf{\\\\Sigma}(|j-i|) & \\\\text{for } i \\\\leq j \\\\\\\\  \\\\mathbf{\\\\Sigma}(|j-i|))^T & \\\\text{otherwise}  \\\\end{cases}, \\\\]which can be computed using <a class=\"groops-program\" href=\"AutoregressiveModel2CovarianceMatrix.html\">AutoregressiveModel2CovarianceMatrix</a>.</p><p>A detailed description with applications can be found in: Kvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties. J Geod 93, 2543–2552 (2019). <a href=\"https://doi.org/10.1007/s00190-019-01314-1\" target=\"_blank\">https://doi.org/10.1007/s00190-019-01314-1</a>'},\n'borderType': { 'name': 'borderType', 'key': 'borderType', 'description': 'With this class you can select one or more region on the surface of the Earth. In every instance of Border you can choose whether the specific region is excluded from the overall result with the switch  exclude . To determine whether a specific point will be used furthermore the following algorithm will be applied: In a first step all points are selected if first border excludes points otherwise all points excluded. When every point will be tested for each instance of border from top to bottom. If the point is not in the selected region nothing happens. Otherwise it will included or excluded depending on the switch  exclude . First Example: The border excludes all continental areas. The result are points on the oceans only. Second Example: First border describes the continent north america. The next borders excludes the great lakes and the last border describes Washington island. In this configuration points are selected if they are inside north america but not in the area of the great lakes. But if the point is on Washington island it will be included again.     The region is restricted along lines of geographical coordinates.  minPhi  and  maxPhi  describe the lower and the upper bound of the region.  minLambda  and  maxLambda  define the left and right bound.     The region is defined by a spherical cap with the center given in geographical coordinates longitude ( lambdaCenter ) and latitude ( phiCenter ). The radius of the cap is given as aperture angle  psi .      The region is defined by     containing one or more polygons given in longitude and latitude. An additional  buffer  around the polygon can be defined. Use a negative value to shrink the polygon area.', 'config_table': 'minLambda angle  maxLambda angle  minPhi angle  maxPhi angle  exclude boolean dismiss points inside lambdaCenter angle longitude of the center of the cap phiCenter angle latitude of the center of the cap psi angle aperture angle (radius) exclude boolean dismiss points inside inputfilePolygon filename  buffer double buffer around polygon [km], <0: inside exclude boolean dismiss points inside', 'display_text': 'With this class you can select one or more region on the surface of the Earth. In every instance of Border you can choose whether the specific region is excluded from the overall result with the switch <strong class=\"groops-config-element\">exclude</strong>. To determine whether a specific point will be used furthermore the following algorithm will be applied: In a first step all points are selected if first border excludes points otherwise all points excluded. When every point will be tested for each instance of border from top to bottom. If the point is not in the selected region nothing happens. Otherwise it will included or excluded depending on the switch <strong class=\"groops-config-element\">exclude</strong>.</p><p>First Example: The border excludes all continental areas. The result are points on the oceans only.</p><p>Second Example: First border describes the continent north america. The next borders excludes the great lakes and the last border describes Washington island. In this configuration points are selected if they are inside north america but not in the area of the great lakes. But if the point is on Washington island it will be included again.  <h2>Rectangle</h2><p> The region is restricted along lines of geographical coordinates. <strong class=\"groops-config-element\">minPhi</strong> and <strong class=\"groops-config-element\">maxPhi</strong> describe the lower and the upper bound of the region. <strong class=\"groops-config-element\">minLambda</strong> and <strong class=\"groops-config-element\">maxLambda</strong> define the left and right bound.  <h2>Cap</h2><p> The region is defined by a spherical cap with the center given in geographical coordinates longitude (<strong class=\"groops-config-element\">lambdaCenter</strong>) and latitude (<strong class=\"groops-config-element\">phiCenter</strong>). The radius of the cap is given as aperture angle <strong class=\"groops-config-element\">psi</strong>.</p><p>  <h2 id=\"polygon\">Polygon</h2><p> The region is defined by <a class=\"groops-class\" href=\"fileFormat_polygon.html\">inputfilePolygon</a> containing one or more polygons given in longitude and latitude. An additional <strong class=\"groops-config-element\">buffer</strong> around the polygon can be defined. Use a negative value to shrink the polygon area.'},\n'conditionType': { 'name': 'conditionType', 'key': 'conditionType', 'description': 'Test for conditions. See  Loop and conditions  for usage.     Check for a file or directory existing. Supports wildcards * for any number of characters and ? for exactly one character. Files smaller than  minSize  are treated as non-existent.     Execute command and check success.     Evaluate expression.     Evaluate elements of a     based on an expression. If  all = yes , all elements of the matrix must evaluate to true for the condition to be fulfilled, otherwise any element evaluating to true is sufficient.     Evaluate if  matrix  (or  instrument ) file is empty/has zero size.     Determines if there is a match between a  pattern  and some subsequence in a  string . Supports wildcards * for any number of characters and ? for exactly one character. If  isRegularExpression  is set,  pattern  is interpreted as a regular expression instead. In any case, the  text parser  is applied beforehand.     Determines if a  pattern  matches the entire  string . Supports wildcards * for any number of characters and ? for exactly one character. If  isRegularExpression  is set,  pattern  is interpreted as a regular expression instead. In any case, the  text parser  is applied beforehand.     All conditions must be met (with short-circuit evaluation).     One of the conditions must be met (with short-circuit evaluation).     The result of the condition is inverted.', 'config_table': 'file filename supports wildcards: * and ? minimumSize uint minimum file size in byte. command filename  silently boolean without showing the output. expression expression  matrix matrixGeneratorType expression is evaluated for each element of resulting matrix expression expression (variable: data) evaluated for each element all boolean all (=yes)/any (=no) elements must evaluate to true inputfileMatrix filename  string filename should contain a {variable} pattern filename supports wildcards: * and ? isRegularExpression boolean pattern is  a regular expression caseSensitive boolean treat lower and upper case as distinct string filename should contain a {variable} pattern filename supports wildcards: * and ? isRegularExpression boolean pattern is  a regular expression caseSensitive boolean treat lower and upper case as distinct condition conditionType  condition conditionType  condition conditionType', 'display_text': 'Test for conditions. See <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">Loop and conditions</a> for usage.  <h2>FileExist</h2><p> Check for a file or directory existing. Supports wildcards * for any number of characters and ? for exactly one character. Files smaller than <strong class=\"groops-config-element\">minSize</strong> are treated as non-existent.  <h2>Command</h2><p> Execute command and check success.  <h2 id=\"expression\">Expression</h2><p> Evaluate expression.  <h2>Matrix</h2><p> Evaluate elements of a <a class=\"groops-class\" href=\"matrixGeneratorType.html\">matrix</a> based on an expression. If <strong class=\"groops-config-element\">all</strong>=<code>yes</code>, all elements of the matrix must evaluate to true for the condition to be fulfilled, otherwise any element evaluating to true is sufficient.  <h2>MatrixEmpty</h2><p> Evaluate if <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> (or <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument</a>) file is empty/has zero size.  <h2>StringContainsPattern</h2><p> Determines if there is a match between a <strong class=\"groops-config-element\">pattern</strong> and some subsequence in a <strong class=\"groops-config-element\">string</strong>. Supports wildcards * for any number of characters and ? for exactly one character. If <strong class=\"groops-config-element\">isRegularExpression</strong> is set, <strong class=\"groops-config-element\">pattern</strong> is interpreted as a regular expression instead. In any case, the <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied beforehand.  <h2>StringMatchPattern</h2><p> Determines if a <strong class=\"groops-config-element\">pattern</strong> matches the entire <strong class=\"groops-config-element\">string</strong>. Supports wildcards * for any number of characters and ? for exactly one character. If <strong class=\"groops-config-element\">isRegularExpression</strong> is set, <strong class=\"groops-config-element\">pattern</strong> is interpreted as a regular expression instead. In any case, the <a class=\"groops-ref\" href=\"general.parser.html#text\">text parser</a> is applied beforehand.  <h2>And</h2><p> All conditions must be met (with short-circuit evaluation).  <h2>Or</h2><p> One of the conditions must be met (with short-circuit evaluation).  <h2>Not</h2><p> The result of the condition is inverted.'},\n'covariancePodType': { 'name': 'covariancePodType', 'key': 'covariancePodType', 'description': 'Provides arc-wise covariance matrices for precise orbit data. Temporal correlations are modeled in the orbit system (along, cross, radial). The     provides temporal covariance functions for each axis. From the diagonal matrix for each time step  the Toeplitz covariance matrix for an arc is constructed   The epoch-wise   covariance matrices given by     are eigenvalue-decomposed  where   is an orthogonal matrix and   diagonal. This is used to split the covariances matrices  and to compose a block diagonal matrix for an arc   The complete covariance matrix of an arc is given by  where  sigma    is an overall factor and the arc specific factors   can be provided with    . The last matrix can be used to downweight outliers in single epochs and will be added if     is provided.', 'config_table': 'covariancePodType sequence  sigma double general variance factor inputfileSigmasPerArc filename different accuracies for each arc (multiplied with sigma) inputfileSigmasPerEpoch filename different accuracies for each epoch (added) inputfileCovarianceFunction filename covariances in time for along, cross, and radial direction inputfileCovariancePodEpoch filename 3x3 epoch-wise covariances', 'display_text': 'Provides arc-wise covariance matrices for precise orbit data. Temporal correlations are modeled in the orbit system (along, cross, radial). The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceFunction</a> provides temporal covariance functions for each axis. From the diagonal matrix for each time step \\\\[   Cov_{3\\\\times3}(t) = \\\\text{diag}(cov_x(t), cov_y(t), cov_z(t)) \\\\]the Toeplitz covariance matrix for an arc is constructed \\\\[   \\\\M C = \\\\begin{pmatrix}     Cov(t_0) & Cov(t_1) & \\\\cdots   &          &        &        \\\\\\\\     Cov(t_1) & Cov(t_0) & Cov(t_1) & \\\\cdots   &        &        \\\\\\\\     \\\\cdots   & Cov(t_1) & Cov(t_0) & Cov(t_1) & \\\\cdots &        \\\\\\\\              & \\\\cdots   & \\\\ddots   & \\\\ddots   & \\\\ddots & \\\\cdots \\\\\\\\   \\\\end{pmatrix} \\\\] The epoch-wise $3\\\\times3$ covariance matrices given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileCovariancePodEpoch</a> are eigenvalue-decomposed \\\\[   \\\\M C_{3\\\\times3}(t_i) = \\\\M Q \\\\M\\\\Lambda \\\\M Q^T, \\\\]where $\\\\M Q$ is an orthogonal matrix and $\\\\M\\\\Lambda$ diagonal. This is used to split the covariances matrices \\\\[   \\\\M C_{3\\\\times3}(t_i) = \\\\M D(t_i) \\\\M D(t_i)^T = (\\\\M Q \\\\M\\\\Lambda^{1/2} \\\\M Q^T)(\\\\M Q \\\\M\\\\Lambda^{1/2} \\\\M Q^T)^T, \\\\]and to compose a block diagonal matrix for an arc \\\\[   \\\\M D = \\\\text{diag}(\\\\M D(t_1), \\\\M D(t_2), \\\\ldots, \\\\M D(t_2)). \\\\] The complete covariance matrix of an arc is given by \\\\[   \\\\M C_{arc} = \\\\sigma_0^2 \\\\sigma_{arc}^2 \\\\M D \\\\M C \\\\M D^T +   \\\\text{diag}(\\\\sigma_1^2\\\\M I_{3\\\\times3}, \\\\sigma_2^2\\\\M I_{3\\\\times3}, \\\\ldots, \\\\sigma_n^2\\\\M I_{3\\\\times3}) \\\\]where <strong class=\"groops-config-element\">sigma</strong> $\\\\sigma_0$ is an overall factor and the arc specific factors $\\\\sigma_{arc}$ can be provided with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmasPerArc</a>. The last matrix can be used to downweight outliers in single epochs and will be added if <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSigmasPerEpoch</a> is provided.'},\n'covarianceSstType': { 'name': 'covarianceSstType', 'key': 'covarianceSstType', 'description': 'Provides arc-wise covariance matrices for satellite-to-satellite observations (SST). The     provides a temporal covariance function. From it the Toeplitz covariance matrix is constructed   The complete covariance matrix of an arc is given by  where  sigma    is an overall factor and the arc specific factors   can be provided with    . The second term describes general covariance matrices for each arc     together with the factors   from  sigmasCovarianceMatrixArc . The last matrix can be used to downweight outliers in single epochs and will be added if     is provided.', 'config_table': 'covarianceSstType sequence  sigma double general variance factor inputfileSigmasPerArc filename different accuaries for each arc (multplicated with sigma) inputfileSigmasPerEpoch filename different accuaries for each epoch (added) inputfileCovarianceFunction filename covariance function in time inputfileCovarianceMatrixArc filename one matrix file per arc. Use {arcNo} as template sigmasCovarianceMatrixArc filename vector with one sigma for each covarianceMatrixArc', 'display_text': 'Provides arc-wise covariance matrices for satellite-to-satellite observations (SST). The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceFunction</a> provides a temporal covariance function. From it the Toeplitz covariance matrix is constructed \\\\[   \\\\M C = \\\\begin{pmatrix}     cov(t_0) & cov(t_1) & \\\\cdots   &          &        &        \\\\\\\\     cov(t_1) & cov(t_0) & cov(t_1) & \\\\cdots   &        &        \\\\\\\\     \\\\cdots   & cov(t_1) & cov(t_0) & cov(t_1) & \\\\cdots &        \\\\\\\\              & \\\\cdots   & \\\\ddots   & \\\\ddots   & \\\\ddots & \\\\cdots \\\\\\\\   \\\\end{pmatrix} \\\\\\\\ \\\\] The complete covariance matrix of an arc is given by \\\\[   \\\\M C_{arc} = \\\\sigma_0^2 \\\\sigma_{arc}^2 \\\\M C + \\\\sigma_{S,arc}^2 \\\\M S_{arc}+ \\\\text{diag}(\\\\sigma_1^2, \\\\sigma_2^2, \\\\ldots, \\\\sigma_n^2) \\\\]where <strong class=\"groops-config-element\">sigma</strong> $\\\\sigma_0$ is an overall factor and the arc specific factors $\\\\sigma_{arc}$ can be provided with <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmasPerArc</a>. The second term describes general covariance matrices for each arc <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileCovarianceMatrixArc</a> together with the factors $\\\\sigma_{S,arc}$ from <strong class=\"groops-config-element\">sigmasCovarianceMatrixArc</strong>. The last matrix can be used to downweight outliers in single epochs and will be added if <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSigmasPerEpoch</a> is provided.</p><p>'},\n'digitalFilterType': { 'name': 'digitalFilterType', 'key': 'digitalFilterType', 'description': 'Digital filter implementation for the filtering of equally spaced time series. This class implements the filter equations as  where   is the autoregressive (AR) order and   is the moving average (MA) order. Note that the MA part can also be non-causal. The characteristics of a filter cascade can be computed by the programs  DigitalFilter2FrequencyResponse  and  DigitalFilter2ImpulseResponse . To apply a filter cascade to a time series (or an instrument file ) use  InstrumentFilter . Each filter can be applyed in forward and backward direction by setting  backwardDirection . If the same filter is applied in both directions, the combined filter has zero phase and the squared magnitude response. Setting  inFrequencyDomain  to true applies the transfer function of the filter to the DFT of the input and synthesizes the result, i.e.:  This is equivalent to setting  padType  to  periodic . To reduce warmup effects, the input time series can be padded by choosing a  padType :    none : no padding is applied  zero : zeros are appended at the beginning and end of the input time series  constant : the beginning of the input time series is padded with the first value, the end is padded with the last value  periodic : periodic continuation of the input time series (i.,e. the beginning is padded with the last epochs and the end is padded with the first epochs)  symmetric : beginning and end are reflected around the first and last epoch respectively       Moving average (boxcar) filter. For odd lengths, this filter is symmetric and has therefore no phase shift. For even lengths, a phase shift of half a cycle is introduced.     Moving median filter of length  . The filter output at epoch   is the median of the set start at   to  . The filter length   should be uneven to avoid a phase shift.     Symmetric MA filter for numerical differentiation using polynomial approximation. The input time series is approximated by a moving polynomial of degree  polynomialDegree , by solving  for each time step   (  is the  sampling  of the time series). The filter coefficients for the  -th derivative are obtained by taking the appropriate row of the inverse coefficient matrix  :  The  polynomialDegree  should be even if no phase shift should be introduced.     Numerical integration using polynomial approximation. The input time series is approximated by a moving polynomial of degree  polynomialDegree  by solving  for each time step   (  is the  sampling  of the time series). The numerical integral for each time step   is approximated by the center interval of the estimated polynomial. polynomialDegree  should be even to avoid a phase shift.     Correlation ( ) of  corr  is introduced into the time series:      Low pass and differentation filter as used for GRACE KBR and ACC data in the Level1A processing.      Digital implementation of the Butterworth filter. The design of the filter is done by modifying the analog (continuous time) transfer function, which is then transformed into the digital domain by using the bilinear transform. The filter coefficients are then determined by a least squares adjustment in time domain. The  filterType  can be  lowpass ,  highpass , where one cutoff frequency has to be specified, and  bandpass  and  bandstop  where to cutoff frequencies have to be specified. Cutoff frequencies must be given as normalized frequency  . For a cutoff frequency of 30 mHz for a time series sampled with 5 seconds gives a normalized frequency of  .     Read filter coefficients of   from a coefficient file. One column might define the index   of the coefficients   and   in the other columns.     Filter representation of a wavelet.     Implemented after Christian Siemes\\' dissertation, page 106.      Moving average decorrelation filter based on eigendecomposition of a Toeplitz covariance matrix.     Lag operator in digital filter representation.     Removes the filtered signal from the input, i.e. the input is passed through a     with a frequency response of  .', 'config_table': 'length uint number of epochs in averaging operator inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges length uint length of the moving window [epochs] padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges polynomialDegree uint degree of approximation polynomial derivative uint take kth derivative sampling double assumed time step between points padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges polynomialDegree uint degree of approximation polynomial sampling double assumed time step between points padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges correlation double correlation backwardDirection boolean apply filter in backward direction inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges rawDataRate double sampling frequency in Hz (fs). convolutionNumber uint number of self convolutions of the filter kernel fitInterval double length of the filter kernel [seconds] lowPassBandwith double target low pass bandwidth normFrequency double norm filter at this frequency [Hz] (default: GRACE dominant (J2) signal frequency) reduceQuadraticFit boolean remove->filter->restore quadratic fit derivative choice  derivative1st  range rate derivative2nd  range acceleration inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges order uint filter order type choice filter type lowpass sequence  Wn double normalized cutoff frequency (f_c / f_nyq) highpass sequence  Wn double normalized cutoff frequency (f_c / f_nyq) bandpass sequence  Wn1 double lower normalized cutoff frequency (f_c / f_nyq) Wn2 double upper normalized cutoff frequency (f_c / f_nyq) bandstop sequence  Wn1 double lower normalized cutoff frequency (f_c / f_nyq) Wn2 double upper normalized cutoff frequency (f_c / f_nyq) backwardDirection boolean apply filter in backward direction inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges inputfileMatrix filename matrix with filter coefficients index expression index of coefficients (input columns are named data0, data1, ...) bn expression MA coefficients (moving average) (input columns are named data0, data1, ...) an expression AR coefficients (autoregressive) (input columns are named data0, data1, ...) backwardDirection boolean apply filter in backward direction inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges inputfileWavelet filename wavelet coefficients type choice filter type lowpass   highpass   level uint compute filter for specific decomposition level backwardDirection boolean apply filter in backward direction inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges notchFrequency double normalized notch frequency w_n = (f_n/f_nyq) bandWidth double bandwidth at -3db. Quality factor of filter Q = w_n/bw backwardDirection boolean apply filter in backward direction inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges inputfileCovarianceFunction filename covariance function of time series inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges lag int lag epochs: 1 (lag); -1 (lead) inFrequencyDomain boolean apply filter in frequency domain padType choice  none  no padding is applied zero  zero padding constant  pad using first and last value periodic  periodic continuation of matrix symmetric  symmetric continuation around the matrix edges filter digitalFilterType remove filter output from input signal', 'display_text': 'Digital filter implementation for the filtering of equally spaced time series. This class implements the filter equations as \\\\[\\\\label{digitalFilterType:arma}   \\\\sum_{l=0}^Q a_l y_{n-l} = \\\\sum_{k=-p_0}^{P-p_0-1} b_k x_{n-k}, \\\\hspace{25pt} a_0 = 1, \\\\]where $Q$ is the autoregressive (AR) order and $P$ is the moving average (MA) order. Note that the MA part can also be non-causal. The characteristics of a filter cascade can be computed by the programs <a class=\"groops-program\" href=\"DigitalFilter2FrequencyResponse.html\">DigitalFilter2FrequencyResponse</a> and <a class=\"groops-program\" href=\"DigitalFilter2ImpulseResponse.html\">DigitalFilter2ImpulseResponse</a>. To apply a filter cascade to a time series (or an instrument file ) use <a class=\"groops-program\" href=\"InstrumentFilter.html\">InstrumentFilter</a>. Each filter can be applyed in forward and backward direction by setting <strong class=\"groops-config-element\">backwardDirection</strong>. If the same filter is applied in both directions, the combined filter has zero phase and the squared magnitude response. Setting <strong class=\"groops-config-element\">inFrequencyDomain</strong> to true applies the transfer function of the filter to the DFT of the input and synthesizes the result, i.e.: \\\\[   y_n = \\\\mathcal{F}^{-1}\\\\{H\\\\cdot\\\\mathcal{F}\\\\{x_n\\\\}\\\\}. \\\\]This is equivalent to setting <strong class=\"groops-config-element\">padType</strong> to <strong class=\"groops-config-element\">periodic</strong>.</p><p>To reduce warmup effects, the input time series can be padded by choosing a <strong class=\"groops-config-element\">padType</strong>: <ul>  <li><strong class=\"groops-config-element\">none</strong>: no padding is applied </li><li> <strong class=\"groops-config-element\">zero</strong>: zeros are appended at the beginning and end of the input time series </li><li> <strong class=\"groops-config-element\">constant</strong>: the beginning of the input time series is padded with the first value, the end is padded with the last value </li><li> <strong class=\"groops-config-element\">periodic</strong>: periodic continuation of the input time series (i.,e. the beginning is padded with the last epochs and the end is padded with the first epochs) </li><li> <strong class=\"groops-config-element\">symmetric</strong>: beginning and end are reflected around the first and last epoch respectively </li></ul>   <h2>MovingAverage</h2><p> Moving average (boxcar) filter. For odd lengths, this filter is symmetric and has therefore no phase shift. For even lengths, a phase shift of half a cycle is introduced.</p><p>\\\\[   y_n = \\\\sum_{k=-\\\\lfloor\\\\frac{P}{2}\\\\rfloor}^{\\\\lfloor\\\\frac{P}{2}\\\\rfloor} \\\\frac{1}{P}x_{n-k} \\\\]</p><p> <h2>Median</h2><p> Moving median filter of length $n$. The filter output at epoch $k$ is the median of the set start at $k-n/2$ to $k+n/2$. The filter length $n$ should be uneven to avoid a phase shift.  <h2>Derivative</h2><p> Symmetric MA filter for numerical differentiation using polynomial approximation. The input time series is approximated by a moving polynomial of degree <strong class=\"groops-config-element\">polynomialDegree</strong>, by solving \\\\[   \\\\begin{bmatrix} x(t_k+\\\\tau_0) \\\\\\\\ \\\\vdots \\\\\\\\ x(t_k+\\\\tau_M) \\\\end{bmatrix}   =   \\\\begin{bmatrix}   1      & \\\\tau_0 & \\\\tau_0^2 & \\\\cdots & \\\\tau_0^M \\\\\\\\   \\\\vdots & \\\\vdots & \\\\vdots   &        & \\\\vdots   \\\\\\\\   1      & \\\\tau_M & \\\\tau_M^2 & \\\\cdots & \\\\tau_M^M \\\\\\\\   \\\\end{bmatrix}%^{-1}   \\\\begin{bmatrix}   a_0 \\\\\\\\ \\\\vdots \\\\\\\\ a_M   \\\\end{bmatrix}   \\\\qquad\\\\text{with}\\\\quad   \\\\tau_j =  (j-M/2)\\\\cdot \\\\Delta t, \\\\]for each time step $t_k$ ($\\\\Delta t$ is the <strong class=\"groops-config-element\">sampling</strong> of the time series). The filter coefficients for the $k$-th derivative are obtained by taking the appropriate row of the inverse coefficient matrix $\\\\mathbf{W}$: \\\\[   b_n = \\\\prod_{i=0}^{k-1} (k-i) \\\\mathbf{w}_{2,:}. \\\\]The <strong class=\"groops-config-element\">polynomialDegree</strong> should be even if no phase shift should be introduced.  <h2>Integral</h2><p> Numerical integration using polynomial approximation. The input time series is approximated by a moving polynomial of degree <strong class=\"groops-config-element\">polynomialDegree</strong> by solving \\\\[   \\\\begin{bmatrix} x(t_k+\\\\tau_0) \\\\\\\\ \\\\vdots \\\\\\\\ x(t_k+\\\\tau_M) \\\\end{bmatrix}   =   \\\\begin{bmatrix}   1      & \\\\tau_0 & \\\\tau_0^2 & \\\\cdots & \\\\tau_0^M \\\\\\\\   \\\\vdots & \\\\vdots & \\\\vdots   &        & \\\\vdots   \\\\\\\\   1      & \\\\tau_M & \\\\tau_M^2 & \\\\cdots & \\\\tau_M^M \\\\\\\\   \\\\end{bmatrix}%^{-1}   \\\\begin{bmatrix}   a_0 \\\\\\\\ \\\\vdots \\\\\\\\ a_M   \\\\end{bmatrix}   \\\\qquad\\\\text{with}\\\\quad   \\\\tau_j =  (j-M/2)\\\\cdot \\\\Delta t, \\\\]for each time step $t_k$ ($\\\\Delta t$ is the <strong class=\"groops-config-element\">sampling</strong> of the time series). The numerical integral for each time step $t_k$ is approximated by the center interval of the estimated polynomial.</p><p></p><p><strong class=\"groops-config-element\">polynomialDegree</strong> should be even to avoid a phase shift.  <h2>Correlation</h2><p> Correlation ($\\\\rho$) of <strong class=\"groops-config-element\">corr</strong> is introduced into the time series: \\\\[   y_n = \\\\rho\\\\cdot y_{n-1} + \\\\sqrt{1-\\\\rho^2}x_n. \\\\] <h2>GraceLowpass</h2><p> Low pass and differentation filter as used for GRACE KBR and ACC data in the Level1A processing.</p><p>  <h2>Butterworth</h2><p> Digital implementation of the Butterworth filter. The design of the filter is done by modifying the analog (continuous time) transfer function, which is then transformed into the digital domain by using the bilinear transform. The filter coefficients are then determined by a least squares adjustment in time domain.</p><p>The <strong class=\"groops-config-element\">filterType</strong> can be <strong class=\"groops-config-element\">lowpass</strong>, <strong class=\"groops-config-element\">highpass</strong>, where one cutoff frequency has to be specified, and <strong class=\"groops-config-element\">bandpass</strong> and <strong class=\"groops-config-element\">bandstop</strong> where to cutoff frequencies have to be specified. Cutoff frequencies must be given as normalized frequency $w_n = f/f_{\\\\text{nyq}}$. For a cutoff frequency of 30 mHz for a time series sampled with 5 seconds gives a normalized frequency of $0.03/0.1 = 0.3$.  <h2>File</h2><p> Read filter coefficients of \\\\eqref{digitalFilterType:arma} from a coefficient file. One column might define the index $n$ of the coefficients $a_n$ and $b_n$ in the other columns.  <h2>Wavelet</h2><p> Filter representation of a wavelet.  <h2>Notch</h2><p> Implemented after Christian Siemes\\' dissertation, page 106.</p><p>  <h2>Decorrelation</h2><p> Moving average decorrelation filter based on eigendecomposition of a Toeplitz covariance matrix.  <h2>TimeLag</h2><p> Lag operator in digital filter representation.  <h2>ReduceFilterOutput</h2><p> Removes the filtered signal from the input, i.e. the input is passed through a <a class=\"groops-class\" href=\"digitalFilterType.html\">digitalFilter</a> with a frequency response of $1-H(f)$.'},\n'doodson': { 'name': 'doodson', 'key': 'doodson', 'description': 'This is a string which describes a tidal frequency either coded as Doodson number or using Darwin´s name, e.g.  255.555  or  M2 . The following names are defined:    055.565 :  om1    055.575 :  om2       056.554 :  sa   056.555 :  sa     057.555 :  ssa       058.554 :  sta   063.655 :  msm    065.455 :  mm        073.555 :  msf   075.555 :  mf     083.655 :  mstm      085.455 :  mtm   093.555 :  msq    093.555 :  msqm      125.755 :  2q1   127.555 :  sig1   127.555 :  sigma1    135.655 :  q1   137.455 :  ro1    137.455 :  rho1      145.555 :  o1   147.555 :  tau1   155.655 :  m1        157.455 :  chi1   162.556 :  pi1    163.555 :  p1        164.555 :  s1   165.555 :  k1     166.554 :  psi1      167.555 :  fi1   167.555 :  phi1   173.655 :  the1      173.655 :  theta1   175.455 :  j1     183.555 :  so1       185.555 :  oo1   195.455 :  v1     225.855 :  3n2       227.655 :  eps2   235.755 :  2n2    237.555 :  mu2       237.555 :  mi2   245.655 :  n2     247.455 :  nu2       247.455 :  ni2   253.755 :  gam2   254.556 :  alf2      255.555 :  m2   256.554 :  bet2   257.555 :  dlt2      263.655 :  la2   263.655 :  lmb2   263.655 :  lambda2   265.455 :  l2   271.557 :  2t2    272.556 :  t2        273.555 :  s2   274.554 :  r2     275.555 :  k2        283.655 :  ksi2   285.455 :  eta2   355.555 :  m3        381.555 :  t3   382.555 :  s3     383.555 :  r3        435.755 :  n4   445.655 :  mn4    455.555 :  m4        473.555 :  ms4   491.555 :  s4     655.555 :  m6        855.555 :  m8', 'config_table': '', 'display_text': 'This is a string which describes a tidal frequency either coded as Doodson number or using Darwin´s name, e.g. <code>255.555</code> or <code>M2</code>.</p><p>The following names are defined: <ul>  <li><code>055.565</code>: <code>om1</code>  </li><li> <code>055.575</code>: <code>om2</code>     </li><li> <code>056.554</code>: <code>sa</code> </li><li> <code>056.555</code>: <code>sa</code>   </li><li> <code>057.555</code>: <code>ssa</code>     </li><li> <code>058.554</code>: <code>sta</code> </li><li> <code>063.655</code>: <code>msm</code>  </li><li> <code>065.455</code>: <code>mm</code>      </li><li> <code>073.555</code>: <code>msf</code> </li><li> <code>075.555</code>: <code>mf</code>   </li><li> <code>083.655</code>: <code>mstm</code>    </li><li> <code>085.455</code>: <code>mtm</code> </li><li> <code>093.555</code>: <code>msq</code>  </li><li> <code>093.555</code>: <code>msqm</code>    </li><li> <code>125.755</code>: <code>2q1</code> </li><li> <code>127.555</code>: <code>sig1</code> </li><li> <code>127.555</code>: <code>sigma1</code>  </li><li> <code>135.655</code>: <code>q1</code> </li><li> <code>137.455</code>: <code>ro1</code>  </li><li> <code>137.455</code>: <code>rho1</code>    </li><li> <code>145.555</code>: <code>o1</code> </li><li> <code>147.555</code>: <code>tau1</code> </li><li> <code>155.655</code>: <code>m1</code>      </li><li> <code>157.455</code>: <code>chi1</code> </li><li> <code>162.556</code>: <code>pi1</code>  </li><li> <code>163.555</code>: <code>p1</code>      </li><li> <code>164.555</code>: <code>s1</code> </li><li> <code>165.555</code>: <code>k1</code>   </li><li> <code>166.554</code>: <code>psi1</code>    </li><li> <code>167.555</code>: <code>fi1</code> </li><li> <code>167.555</code>: <code>phi1</code> </li><li> <code>173.655</code>: <code>the1</code>    </li><li> <code>173.655</code>: <code>theta1</code> </li><li> <code>175.455</code>: <code>j1</code>   </li><li> <code>183.555</code>: <code>so1</code>     </li><li> <code>185.555</code>: <code>oo1</code> </li><li> <code>195.455</code>: <code>v1</code>   </li><li> <code>225.855</code>: <code>3n2</code>     </li><li> <code>227.655</code>: <code>eps2</code> </li><li> <code>235.755</code>: <code>2n2</code>  </li><li> <code>237.555</code>: <code>mu2</code>     </li><li> <code>237.555</code>: <code>mi2</code> </li><li> <code>245.655</code>: <code>n2</code>   </li><li> <code>247.455</code>: <code>nu2</code>     </li><li> <code>247.455</code>: <code>ni2</code> </li><li> <code>253.755</code>: <code>gam2</code> </li><li> <code>254.556</code>: <code>alf2</code>    </li><li> <code>255.555</code>: <code>m2</code> </li><li> <code>256.554</code>: <code>bet2</code> </li><li> <code>257.555</code>: <code>dlt2</code>    </li><li> <code>263.655</code>: <code>la2</code> </li><li> <code>263.655</code>: <code>lmb2</code> </li><li> <code>263.655</code>: <code>lambda2</code> </li><li> <code>265.455</code>: <code>l2</code> </li><li> <code>271.557</code>: <code>2t2</code>  </li><li> <code>272.556</code>: <code>t2</code>      </li><li> <code>273.555</code>: <code>s2</code> </li><li> <code>274.554</code>: <code>r2</code>   </li><li> <code>275.555</code>: <code>k2</code>      </li><li> <code>283.655</code>: <code>ksi2</code> </li><li> <code>285.455</code>: <code>eta2</code> </li><li> <code>355.555</code>: <code>m3</code>      </li><li> <code>381.555</code>: <code>t3</code> </li><li> <code>382.555</code>: <code>s3</code>   </li><li> <code>383.555</code>: <code>r3</code>      </li><li> <code>435.755</code>: <code>n4</code> </li><li> <code>445.655</code>: <code>mn4</code>  </li><li> <code>455.555</code>: <code>m4</code>      </li><li> <code>473.555</code>: <code>ms4</code> </li><li> <code>491.555</code>: <code>s4</code>   </li><li> <code>655.555</code>: <code>m6</code>      </li><li> <code>855.555</code>: <code>m8</code> </li></ul>'},\n'earthRotationType': { 'name': 'earthRotationType', 'key': 'earthRotationType', 'description': 'This class realize the transformation between a terestrial reference frame (TRF) and a celestial reference frame (CRF).     This class realize the transformation by interpolation from file. This file can be created with  EarthOrientationParameterTimeSeries .     This class realize the transformation according to the IERS2010 conventions given by the  International Earth Rotation and Reference Systems Service  (IERS). A file with the earth orientation parameter is needed (   ).     This class realize the transformation according to the IERS2010 conventions given by the  International Earth Rotation and Reference Systems Service  (IERS). A file with the earth orientation parameter is needed (   ). Includes additional high-frequency EOP models (   ).     This class realize the transformation according to IERS2003 conventions given by the  International Earth Rotation and Reference Systems Service  (IERS). A file with the earth orientation parameter is needed (   ). The following subroutines are used:    BPN2000.f,  ERA2000.f,  pmsdnut.f,  POM2000.f,  SP2000.f,  T2C2000.f,  XYS2000A.f   from  ftp://maia.usno.navy.mil/conv2000/chapter5/  and    orthoeop.f   from  ftp://maia.usno.navy.mil/conv2000/chapter8/      Very old.     The transformation is realized as rotation about the z-axis. The angle ist given by the Greenwich Mean Siderial Time (GMST).     Double Tu0 = (timeUTC.mjdInt()-51544.5)/36525.0;   Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))                + (8640184.812866/(24*60*60))*Tu0                + (0.093104/(24*60*60))*Tu0*Tu0                + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;   Double r = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;   GMST = fmod(2*PI*(GMST0 + r * timeUTC.mjdMod()), 2*PI);       The transformation is realized as rotation about the z-axis. The angle ist given by the Earth Rotation Angle (ERA) as     const Time T = timeUT1-mjd2time(J2000);   ERA = fmod(2*PI*(0.7790572732640 + T.mjdMod() + 0.00273781191135448*T.mjd()), 2*PI);       The transformation is realized as rotation about the z-axis. You must specify the angle ( initialAngle ) at  time0  and the angular velocity ( angularVelocity ).     This class reads quaternions from an instrument file and interpolates to the given time stamp.     This class realizes the transformation between the moon-fixed system (Principal Axis System (PA) or Mean Earth System (ME)) and the ICRS according to the JPL ephemeris file.', 'config_table': 'inputfileEOP filename  interpolationDegree uint for polynomial interpolation inputfileEOP filename  truncatedNutation boolean use truncated nutation model (IAU2006B) inputfileEOP filename  inputfileDoodsonEOP filename  inputfileEOP filename  inputfileEOP filename  inputfileNutation filename  initialAngle double Angle at time0 [rad] angularVelocity double [rad/s] time0 time  inputfileStarCamera filename  interpolationDegree uint degree of interpolation polynomial inputfileEphemerides filename librations moonfixedSystem choice  PA  Principal Axis System ME  Mean Earth System', 'display_text': 'This class realize the transformation between a terestrial reference frame (TRF) and a celestial reference frame (CRF).  <h2 id=\"file\">File</h2><p> This class realize the transformation by interpolation from file. This file can be created with <a class=\"groops-program\" href=\"EarthOrientationParameterTimeSeries.html\">EarthOrientationParameterTimeSeries</a>.  <h2>Iers2010</h2><p> This class realize the transformation according to the IERS2010 conventions given by the <em>International Earth Rotation and Reference Systems Service</em> (IERS). A file with the earth orientation parameter is needed (<a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">inputfileEOP</a>).  <h2 id=\"iers2010b\">Iers2010b</h2><p> This class realize the transformation according to the IERS2010 conventions given by the <em>International Earth Rotation and Reference Systems Service</em> (IERS). A file with the earth orientation parameter is needed (<a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">inputfileEOP</a>). Includes additional high-frequency EOP models (<a class=\"groops-class\" href=\"fileFormat_doodsonEarthOrientationParameter.html\">inputfileDoodsonEOP</a>).  <h2>Iers2003</h2><p> This class realize the transformation according to IERS2003 conventions given by the <em>International Earth Rotation and Reference Systems Service</em> (IERS). A file with the earth orientation parameter is needed (<a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">inputfileEOP</a>).</p><p>The following subroutines are used: <ul>  <li>BPN2000.f, </li><li> ERA2000.f, </li><li> pmsdnut.f, </li><li> POM2000.f, </li><li> SP2000.f, </li><li> T2C2000.f, </li><li> XYS2000A.f </li></ul>  from <a href=\"ftp://maia.usno.navy.mil/conv2000/chapter5/\" target=\"_blank\">ftp://maia.usno.navy.mil/conv2000/chapter5/</a> and <ul>  <li>orthoeop.f </li></ul>  from <a href=\"ftp://maia.usno.navy.mil/conv2000/chapter8/\" target=\"_blank\">ftp://maia.usno.navy.mil/conv2000/chapter8/</a>  <h2>Iers1996</h2><p> Very old.  <h2>Gmst</h2><p> The transformation is realized as rotation about the z-axis. The angle ist given by the Greenwich Mean Siderial Time (GMST). <pre>   Double Tu0 = (timeUTC.mjdInt()-51544.5)/36525.0;</p><p>  Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))                + (8640184.812866/(24*60*60))*Tu0                + (0.093104/(24*60*60))*Tu0*Tu0                + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;   Double r = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;   GMST = fmod(2*PI*(GMST0 + r * timeUTC.mjdMod()), 2*PI); </pre>  <h2>Earth Rotation Angle (ERA)</h2><p> The transformation is realized as rotation about the z-axis. The angle ist given by the Earth Rotation Angle (ERA) as <pre>   const Time T = timeUT1-mjd2time(J2000);   ERA = fmod(2*PI*(0.7790572732640 + T.mjdMod() + 0.00273781191135448*T.mjd()), 2*PI); </pre>  <h2>Z-Axis</h2><p> The transformation is realized as rotation about the z-axis. You must specify the angle (<strong class=\"groops-config-element\">initialAngle</strong>) at <strong class=\"groops-config-element\">time0</strong> and the angular velocity (<strong class=\"groops-config-element\">angularVelocity</strong>).  <h2>StarCamera</h2><p> This class reads quaternions from an instrument file and interpolates to the given time stamp.  <h2>MoonRotation</h2><p> This class realizes the transformation between the moon-fixed system (Principal Axis System (PA) or Mean Earth System (ME)) and the ICRS according to the JPL ephemeris file.'},\n'eclipseType': { 'name': 'eclipseType', 'key': 'eclipseType', 'description': 'Shadowing of satellites by moon and Earth provided as factor between   with 0: full shadow and 1: full sun light.           Earth’s penumbra modeling with Solar radiation pressure with Oblateness and Lower Atmospheric Absorption, Refraction, and Scattering (SOLAARS). See Robertson, Robbie. (2015), Highly Physical Solar Radiation Pressure Modeling During Penumbra Transitions (pp. 67-75).', 'config_table': '', 'display_text': 'Shadowing of satellites by moon and Earth provided as factor between $[0,1]$ with 0: full shadow and 1: full sun light.  <h2>Conical</h2><p>   <h2>SOLAARS</h2><p> Earth’s penumbra modeling with Solar radiation pressure with Oblateness and Lower Atmospheric Absorption, Refraction, and Scattering (SOLAARS). See Robertson, Robbie. (2015), Highly Physical Solar Radiation Pressure Modeling During Penumbra Transitions (pp. 67-75).'},\n'ephemeridesType': { 'name': 'ephemeridesType', 'key': 'ephemeridesType', 'description': 'Ephemerides of Sun, Moon and planets. The coordinate system is defined as center of    .     Using  DExxx  ephemerides from NASA Jet Propulsion Laboratory (JPL).', 'config_table': 'inputfileEphemerides filename  origin planetType center of coordinate system', 'display_text': 'Ephemerides of Sun, Moon and planets. The coordinate system is defined as center of <a class=\"groops-class\" href=\"planetType.html\">origin</a>.   Using <code>DExxx</code> ephemerides from NASA Jet Propulsion Laboratory (JPL).'},\n'forcesType': { 'name': 'forcesType', 'key': 'forcesType', 'description': 'This class provides the forces acting on a satellite. This encompasses    ,     and    .', 'config_table': 'forcesType sequence  gravityfield gravityfieldType  tides tidesType  miscAccelerations miscAccelerationsType', 'display_text': 'This class provides the forces acting on a satellite. This encompasses <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>, <a class=\"groops-class\" href=\"tidesType.html\">tides</a> and <a class=\"groops-class\" href=\"miscAccelerationsType.html\">miscAccelerations</a>.'},\n'gnssAntennaDefintionListType': { 'name': 'gnssAntennaDefintionListType', 'key': 'gnssAntennaDefintionListType', 'description': 'Provides a list of GnssAntennaDefinitions as used in  GnssAntennaDefinitionCreate .     Creates a new antenna.     Select all or the first antenna from an  antenna definition file  which matches the wildcards.     Select all antennas from an  antenna definition file  which are used by a station within a defined time interval. With  specializeAntenna  an individual antenna is created for each different serial number using the general type specific values from file.     The azimuth and elevation dependent antenna center variations (patterns) of all  antenna s are resampled to a new resolution.     This class can be used to separate general antenna patterns for different    s. If the  antenna s contain only one pattern for all GPS observations on the L1 frequency ( *1*G** ), the  patternTypes = C1*G**  and  L1*G**  create two patterns with the  *1*G**  patterm as template. The first matching pattern in the  antenna  is used as template. Also new  additionalPattern  can be added (e.g. for  *5*G** ). With  addExistingPatterns  all already existing patterns that don\\'t match completely to any of the above are added.     Replaces parts of the descrption of  antenna s. The star \" * \" left this part untouched.     The antenna center variations (patterns) or offsets of all  antenna s are set to zero.     The antenna offset and antenna variations (patterns) are inseparable parts of the antenna model. With  removeOffset  an estimated offset is removed from all selected patterns and added to the offset. With  removeMean  an estimated constant is removed additionally as it cannot be seperated from signal biases. The mean and offset are defined as discretized ( deltaAzimuth ,  dZenith ) integral of the spherical cap from zenith down to  maxZenith .', 'config_table': 'name string  serial string  radome string  comment string  pattern sequence  type gnssType pattern matching of observation types offsetX double [m] antenna center offset offsetY double [m] antenna center offset offsetZ double [m] antenna center offset deltaAzimuth angle [degree] step size deltaZenith angle [degree] step size maxZenith angle [degree] values expression [m] expression (zenith, azimuth: variables) inputfileAntennaDefinition filename  name string  serial string  radome string  onlyFirstMatch boolean otherwise all machting antennas included inputfileStationInfo filename  inputfileAntennaDefinition filename  timeStart time only antennas used in this time interval timeEnd time only antennas used in this time interval specializeAntenna boolean e.g. separate different serial numbers from stationInfo antenna gnssAntennaDefintionListType  deltaAzimuth angle [degree] step size, empty: no change deltaZenith angle [degree] step size, empty: no change maxZenith angle [degree], empty: no change antenna gnssAntennaDefintionListType  patternTypes gnssType gnssType for each pattern (first match is used) additionalPattern sequence additional new patterns type gnssType pattern matching of observation types offsetX double [m] antenna center offset offsetY double [m] antenna center offset offsetZ double [m] antenna center offset deltaAzimuth angle [degree] step size deltaZenith angle [degree] step size maxZenith angle [degree] values expression [m] expression (zenith, azimuth: variables) addExistingPatterns boolean add existing patterns that don\\'t match completely any of the above antenna gnssAntennaDefintionListType  name string *: left this part untouched serial string *: left this part untouched radome string *: left this part untouched comment string *: left this part untouched antenna gnssAntennaDefintionListType  patternTypes gnssType only matching patterns, default: all zeroOffset boolean  zeroPattern boolean  antenna gnssAntennaDefintionListType  patternTypes gnssType only matching patterns, default: all removeMean boolean  removeOffset boolean  deltaAzimuth angle [degree] sampling of pattern to estimate center/constant deltaZenith angle [degree] sampling of pattern to estimate center/constant maxZenith angle [degree] sampling of pattern to estimate center/constant', 'display_text': 'Provides a list of GnssAntennaDefinitions as used in <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.  <h2>New</h2><p> Creates a new antenna.  <h2>FromFile</h2><p> Select all or the first antenna from an <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a> which matches the wildcards.  <h2>FromStationInfo</h2><p> Select all antennas from an <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a> which are used by a station within a defined time interval. With <strong class=\"groops-config-element\">specializeAntenna</strong> an individual antenna is created for each different serial number using the general type specific values from file.  <h2>Resample</h2><p> The azimuth and elevation dependent antenna center variations (patterns) of all <strong class=\"groops-config-element\">antenna</strong>s are resampled to a new resolution.  <h2>Transform</h2><p> This class can be used to separate general antenna patterns for different <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>s. If the <strong class=\"groops-config-element\">antenna</strong>s contain only one pattern for all GPS observations on the L1 frequency (<code>*1*G**</code>), the <strong class=\"groops-config-element\">patternTypes</strong>=<code>C1*G**</code> and <code>L1*G**</code> create two patterns with the <code>*1*G**</code> patterm as template. The first matching pattern in the <strong class=\"groops-config-element\">antenna</strong> is used as template. Also new <strong class=\"groops-config-element\">additionalPattern</strong> can be added (e.g. for <code>*5*G**</code>). With <strong class=\"groops-config-element\">addExistingPatterns</strong> all already existing patterns that don\\'t match completely to any of the above are added.  <h2>Rename</h2><p> Replaces parts of the descrption of <strong class=\"groops-config-element\">antenna</strong>s. The star \"<code>*</code>\" left this part untouched.  <h2>SetZero</h2><p> The antenna center variations (patterns) or offsets of all <strong class=\"groops-config-element\">antenna</strong>s are set to zero.  <h2>RemoveCenterMean</h2><p> The antenna offset and antenna variations (patterns) are inseparable parts of the antenna model. With <strong class=\"groops-config-element\">removeOffset</strong> an estimated offset is removed from all selected patterns and added to the offset. With <strong class=\"groops-config-element\">removeMean</strong> an estimated constant is removed additionally as it cannot be seperated from signal biases. The mean and offset are defined as discretized (<strong class=\"groops-config-element\">deltaAzimuth</strong>, <strong class=\"groops-config-element\">dZenith</strong>) integral of the spherical cap from zenith down to <strong class=\"groops-config-element\">maxZenith</strong>.'},\n'gnssParametrizationType': { 'name': 'gnssParametrizationType', 'key': 'gnssParametrizationType', 'description': 'This class defines the models and parameters of the linearized observation equations for all phase and code measurements (see  GnssProcessing )  where the left side is the observation vector minus the effects computed from the a priori models. After each least squares adjustment (see    ) the a priori parameters are updated  The vector   can be written with    . Any  outputfiles  defined in the parametrizations are written with    . Each parametrization (and possible constraint equations) has a  name  which enables activating/deactivating the estimation of subsets of   with    . The a priori model   is unaffected and is always reduced. The model for the different observation types can be described as  The notation   describes the attribution to a signal type   (i.e., C or L), frequency  , signal attribute   (e.g., C, W, Q, X), transmitting satellite  , and observing receiver  . It follows the  , see  GnssType . See also  GnssProcessing .     The influence of the ionosphere is modelled by a STEC parameter (slant total electron content) in terms of   between each transmitter and receiver at each epoch. These parameters are pre-eliminated from the observation equations before accumulating the normal equations. This is similar to using the ionosphere-free linear combination as observations but only one STEC parameter is needed for an arbitrary number of observation types. The influence on the code and phase observation is modeled as  The second order term depends on the       and the direction of the signal  . If further information about the ionosphere is available (in the form of a prior model or as additional parametrizations such as     or    ) the STEC parameters describe local and short–term scintillations. The STEC parameters are estimated as additions to the model and it is advised to constrain them towards zero with a standard deviation of  sigmaSTEC .     The influence of the ionosphere is modelled by a VTEC parameter (vertical total electron content) in terms of   for every selected receiver at each epoch. Optionally, VTEC gradients in the North (x) and East (y) direction can be estimated via    . The slant TEC is computed based on the VTEC and the optional North and East gradients   and   using the elevation-dependent Modified Single-Layer Model (MSLM) mapping function  inserted into eq.  , where   is the azimuth angle and   is the elevation angle. The result is written as a  times series file  at epochs with observations depending on    . This class provides a simplified model of the ionosphere for single receivers and enables the separation of the TEC and signal biases, meaning     becomes estimable. Local and short-term scintillations should be considered by adding loosely constrained    . The  parameter names  are    &lt;station>:VTEC::&lt;time> ,  &lt;station>:VTECGradient.x:&lt;temporal>:&lt;interval> ,  &lt;station>:VTECGradient.y:&lt;temporal>:&lt;interval> .       Apriori VTEC maps can be removed from the observations with     (e.g. from  GnssIonex2GriddedDataTimeSeries ). The ionosphere is parametrized in terms of   in a single layer sphere with  radiusIonosphericLayer  as a    ly changing (e.g. hourly linear splines) spherical harmonics expansion  up to  maxDegree = 15  in a solar-geomagentic frame defined by    . The VTEC values are mapped to STEC values in the observation equations via eq.  . The estimated VTEC inclusive the apriori     can be written to     evaluated at     and    . Local and short-term scintillations should be considered by adding constrained    . To account for signal biases add    . The  parameter names  are    VTEC:sphericalHarmonics.c_&lt;degree>_&lt;order>:&lt;temporal>:&lt;interval> ,  VTEC:sphericalHarmonics.s_&lt;degree>_&lt;order>:&lt;temporal>:&lt;interval> .       Clock errors are estimated epoch-wise for each    . No clock errors are estimated if no valid observations are available (e.g. data gaps in the observations). If all transmitters and receivers are selected by  selectTransmitters  and  selectReceivers  respectively, these parameters will be lineary dependent which would lead to a rank deficiency in the normal equation matrix. To circumvent this issue, the estimation requires an additional zero-mean constraint added in each epoch. This is realized with an additional observation equation  summed over all     with a standard deviation of  sigmaZeroMeanConstraint . The  parameter names  are  &lt;station or prn>:clock::&lt;time> .     This parametrization is an alternative to    . Clock errors are estimated epoch-wise for each     and, opposed to    , are also estimated for epochs that have no valid observations available (e.g. data gaps). The clock error of an epoch can be predicted by the clock error of the preceding epoch and an unknown clock drift  This equation is applied as an additional constraint equation in each epoch  The variance   is estimated iteratively by variance component estimation (VCE). Clock jumps are treated as outliers and are automatically downweighted as described in    . The absolute initial clock error and clock drift cannot be determined if all receiver and transmitter clocks are estimated together due to their linear dependency. This linear dependency would lead to a rank deficiency in the normal equation matrix in the same manner as described in    . To circumvent this issue, an additional zero-mean constraint is added in each epoch as observation equation  summed over all    . This should be a loose constraint with a relatively large standard deviation of  sigmaZeroMeanConstraint . The  parameter names  are  &lt;station or prn>:clock::&lt;time>  and  &lt;station or prn>:clockDrift:: .     Each code and phase observation (e.g  C1C  or  L2W ) contains a bias at transmitter/receiver level  This class provides the apriori model   of eq.   only. The     are read for each transmitter and receiver. Those file names are interpreted as a template with the variable  {prn}  or  {station}  being replaced by transmitter PRNs or receiver station names, respectively. (Infos regarding the variables  {prn}  and  {station}  can be found in     and     respectively). Those files can be converted with  GnssSinexBias2SignalBias . The estimation of the biases is complex due to different linear dependencies, which result in rank deficiencies in the system of normal equations. For simplification the parametrization for   has been split into:    ,    , and     (including phase biases). The file handling on the other hand still remains within this class. Any prior values for the transmitter/receiver biases are read with the respective  inputfileSignalBiasTransmitter/Receiver . All biases for a transmitter/receiver are accumulated and written to the respective  outputfileSignalBiasTransmitter/Receiver .     Sets up an ambiguity parameter for each track and phase observation type.  As the phase observations contain a float bias at transmitter/receiver level, not all ambiguities are resolvable to integer values. The number of resolvable ambiguities can be increased with known phase biases read from file via    . In this case,     should not be used for the corresponding transmitters and receivers. In case of GLONASS, the phase biases at receiver level differ between different frequency channels (frequency division multiple access, FDMA) and for each channel an extra float phase bias is estimated. With  linearGlonassBias  a linear relationship between bias and frequency channel is assumed, which reduces the number of float bias parameters and increases the number of resolvable integer ambiguities. The integer ambiguities can be resolved and fixed in    . Resolved integer ambiguities are not estimated as unknown parameters in     anymore and are removed from the system of normal equations. The estimated phase biases can be written to files in    . The  parameter names  are    &lt;station>:phaseBias(&lt;gnssType>):: ,  &lt;prn>:phaseBias(&lt;gnssType>):: ,  &lt;station>.&lt;prn>:ambiguity&lt;index>of&lt;count>(&lt;GnssTypes>)::&lt;track interval> .       Each code observation (e.g  C1C  or  C2W ) contains a bias at transmitter/receiver level  The code biases cannot be estimated together with clock errors and ionospheric delays in an absolute sense as rank deficiencies will occur in the system of normal equations. Therefore, the biases are not initialized and set up as parameters directly but only estimable linear combinations are parametrized. The basic idea is to set up simplified normal equations with the biases, clock and STEC parameters of one single receiver or transmitter, eliminate clock and STEC parameters and perform an eigen value decomposition of the normal equation matrix  Instead of estimating the original bias parameter   a transformed set   is introduced:  The new parameters corresponding to eigen values   are estimable, the others are left out (set to zero). The behavior can be controlled by explicitly setting up to two bias types with     for each transmitter to zero. These then define the ionosphere-free clock datum of the transmitter. The missing linear combinations, which depend on the STEC parameters, can be added with    . Additional rank deficiencies may also occur when biases of transmitters and receivers are estimated together. The minimum norm nullspace (also via eigen value decomposition) is formulated as zero constraint equations and added with a standard deviation of  sigmaZeroMeanConstraint . In case of GLONASS the code biases at receiver level can differ between different frequency channels (frequency division multiple access, FDMA) and for each channel an extra code bias is estimated. With  linearGlonassBias  a linear relationship between bias and frequency channel is assumed, which reduces the number of bias parameters. The estimated biases can be written to files in    . The  parameter names  are  &lt;station or prn>:codeBias0&lt;index>&lt;combi of gnssTypes>:: .     Each code observation (e.g  C1C  or  C2W ) contains a bias at transmitter/receiver level  This parametrization represents the linear combination of signal biases which completely depend on the STEC parameters. Ignoring these bias combinations would result in a biased STEC estimation (all other parameters are nearly unaffected). To determine this part of the signal biases the     should be constrained. Furthermore, additional information about the ionosphere is required from     or    . Rank deficiencies due to the signal bias parameters may occur if biases of transmitters and receivers are estimated together. The minimum norm nullspace is formulated as zero constraint equations and added with a standard deviation of  sigmaZeroMeanConstraint . The accumulated estimated result can be written to files in    . The  parameter names  are  &lt;station or prn>:tecBias0&lt;index>&lt;combi of gnssTypes>:: .     This parametrization resolves the issue of some phase observations suffering from time-variable biases. Such a phenomenon has been found to affect GPS block IIF satellites on the L5 phase measurements (see Montenbruck et al. 2011, DOI:  ). For these time-variable biases an appropriate temporal representation has to be defined in    . For example, time-variable biases for GPS block IIF L5 phase observations (   = L5*G ) can be represented by a cubic spline with a nodal distance of one hour. The result is written as a  times series file  at the processing sampling or the sampling set by    ). This parametrization should be set up in addition to the constant    . Depending on the temporal representation a temporal zero-mean constraint is needed to separate this parametrization from the constant component. The constraint equations are added with a standard deviation of  sigmaZeroMeanConstraint . The  parameter names  are  &lt;prn>:signalBias.&lt;gnssType>:&lt;temporal>:&lt;interval> .     Estimates a static position for all     in the terrestrial frame. No-net constraints can be applied for a subset of stations,    , with a standard deviation of  noNetTranslationSigma  and  noNetRotationSigma  and  noNetScaleSigma . If the template     is provided the constraints are applied relatively to these positions. Only stations with an existing position file are considered. Without     the constraints are applied towards the apriori values from    . As a single corrupted station position can disturb the no-net conditions, the rotation/translation parameters are estimated in a  robust least squares adjustment  beforehand. The computed weight matrix is used to downweight corrupted stations in the constraint equations. In case you want to align to an ITRF/IGS reference frame, precise coordinates can be generated with  Sinex2StationPositions . The  parameter names  are    &lt;station>:position.x:: ,  &lt;station>:position.y:: ,  &lt;station>:position.z:: .       Estimates the epoch-wise     in an Earth-fixed frame (or in case of LEO satellites in an intertial frame). The   epoch wise     are computed within    The  parameter names  are    &lt;station>:position.x::&lt;time> ,  &lt;station>:position.y::&lt;time> ,  &lt;station>:position.z::&lt;time> .       The estimation of (reduced) dynamic orbits is formulated as variational equations. It is based on     calculated with  PreprocessingVariationalEquation . Necessary integrations are performed by integrating a moving interpolation polynomial of degree  integrationDegree . The     must include at least those parameters that were estimated in  PreprocessingVariationalEquationOrbitFit . Additional     parameters can be set up to reduce orbit mismodeling. If not enough epochs with observations are available ( minEstimableEpochsRatio ) the LEO satellite is disabled. The parameters and  parameter names  are divided into global    &lt;station>:&lt;parametrizationAcceleration>:*:* ,  &lt;station>:stochasticPulse.x::&lt;time> ,  &lt;station>:stochasticPulse.y::&lt;time> ,  &lt;station>:stochasticPulse.z::&lt;time> ,   and arc related parameters    &lt;station>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;station>:arc&lt;no>.position0.x:: ,  &lt;station>:arc&lt;no>.position0.y:: ,  &lt;station>:arc&lt;no>.position0.z:: .  &lt;station>:arc&lt;no>.velocity0.x:: ,  &lt;station>:arc&lt;no>.velocity0.y:: ,  &lt;station>:arc&lt;no>.velocity0.z:: .       Same as     but for transmitting GNSS satellites. For more details see  orbit integration .     A priori tropospheric correction is handled by a     model (e.g. Vienna Mapping Functions 3). Additional parameters in   for zenith wet delay and gradients can be set up via     (usually 2-hourly linear splines) and     (usually a daily trend). These parameters can be soft-constrained using     to avoid an unsolvable system of normal equations in case of data gaps. The  parameter names  are    &lt;station>:troposphereWet:&lt;temporal>:&lt;interval> ,  &lt;station>:troposphereGradient.x:&lt;temporal>:&lt;interval> ,  &lt;station>:troposphereGradient.y:&lt;temporal>:&lt;interval> .       Earth rotation parameters (ERPs) can be estimated by defining  estimatePole  ( ,  ) and  estimateUT1  ( ). Estimating length of day (LOD) with the sign according to IGS conventions requires a negative value in    . Constraints on the defined parameters can be added via    . An example would be to set up     so the   parameter is included in the normal equation system . Since   cannot be determined by GNSS, a hard constraint to its a priori value can then be added. The  parameter names  are    earth:polarMotion.xp:&lt;temporal>:&lt;interval> ,  earth:polarMotion.yp:&lt;temporal>:&lt;interval> ,  earth:UT1:&lt;temporal>:&lt;interval> ,  earth:nutation.X:&lt;temporal>:&lt;interval> ,  earth:nutation.Y:&lt;temporal>:&lt;interval> .       This class is for parametrization the antenna for their antenna center offsets (ACO) and antenna center variations (ACV) by    . The receivers to be estimated can be selected by    . The amount of patterns to be estimated is configurable with a list of    . For each added     a set of parameters will be evaluated. The observations will be assigned to the first     that matches their own. E.g. having the patterns:  ***G  and  L1*  would lead to all GPS observations be assigned to the observation equations of the first pattern. The pattern type  L1*  would then consist of all other GNSS L1 phase observations.  addNonMatchingTypes  will, if activated, create automatically patterns for     that are not selected within the list    . Furthermore, it is possible to group same antenna build types from different receivers by  groupAntennas . The grouping by same antenna build ignores antenna serial numbers. To estimate the antenna variation parameters, a longer period of observations might be necessary for accurate estimations. Hence one should use this parametrization by accumulating normal equations from several epochs. This can be accomplished as the last steps in the      by adding     to current selected parameters with     and write the normal equation matrix with    . The written normal equations can then be accumulated with  NormalsAccumulate  and solved by  NormalsSolverVCE . Further, one should apply constraints to the normal equations by  GnssAntennaNormalsConstraint  since the estimation  of ACO and ACV can lead to rank deficiencies in the normal equation matrix. Last the solved normal equation can be parsed to a  antenna definition file   with the program  ParameterVector2GnssAntennaDefinition . As example referring to the cookbook  GNSS satellite orbit determination and station network analysis , one could add additionally     as parametrization. Since the estimations are done on a daily basis for each receiver we add an additional     which disables  parameter.receiverAntenna . After all stations are processed together with all parameters, one adds  parameter.receiverAntenna  with      to the current selected parametrizations. The last     is     to write the daily normal equations including the parametrization     into files. These normal equation files are then processed with the programs:     NormalsAccumulate : accumulates normal equations.    GnssAntennaNormalsConstraint : apply constraint to the normal equations.    NormalsSolverVCE : solves the normal equations.    ParameterVector2GnssAntennaDefinition : writes the solution into a  antenna definition file   Note that the apriori value   for this parametrization is always zero and never updated according to eq.  . The  parameter names  are  &lt;antennaName>:&lt;antennaCenterVariations>.&lt;gnssType>:: .     Same as     but for transmitting antennas (GNSS satellites). The  parameter names  are  &lt;antennaName>:&lt;antennaCenterVariations>.&lt;gnssType>:: .     Add a pseudo observation equation (constraint) for each selected      where   is the  bias  and   is the a priori value of the parameter if  relativeToApriori  is not set. The standard deviation  sigma  is used to weight the observation equations.     Groups a set of parameters. This class can be used to structure complex parametrizations and has no further effect itself.', 'config_table': 'name string used for parameter selection apply2ndOrderCorrection boolean apply ionospheric correction apply3rdOrderCorrection boolean apply ionospheric correction applyBendingCorrection boolean apply ionospheric correction magnetosphere magnetosphereType  nameConstraint string used for parameter selection sigmaSTEC expression expr. for sigma [TECU] for STEC constraint, variable E (elevation) available name string  selectReceivers platformSelectorType  outputfileVTEC filename variable {station} available, columns: MJD, VTEC, north gradient, east gradient mapR double constant of MSLM mapping function mapH double constant of MSLM mapping function mapAlpha double constant of MSLM mapping function gradient parametrizationTemporalType parametrization of north and east gradients name string  selectReceivers platformSelectorType  outputfileGriddedDataTimeSeries filename single layer VTEC [TECU] outputGrid gridType  outputTimeSeries timeSeriesType  inputfileGriddedDataTimeSeries filename single layer VTEC [TECU] maxDegree uint spherical harmonics parametrization temporal parametrizationTemporalType temporal evolution of VTEC values radiusIonosphericLayer double [m] radius of ionospheric single layer mapR double [m] constant of MSLM mapping function mapH double [m] constant of MSLM mapping function mapAlpha double constant of MSLM mapping function magnetosphere magnetosphereType  name string used for parameter selection selectTransmitters platformSelectorType  selectReceivers platformSelectorType  outputfileClockTransmitter filename variable {prn} available outputfileClockReceiver filename variable {station} available nameConstraint string used for parameter selection selectTransmittersZeroMean platformSelectorType  selectReceiversZeroMean platformSelectorType  sigmaZeroMeanConstraint double (0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks name string used for parameter selection selectTransmitters platformSelectorType  selectReceivers platformSelectorType  outputfileClockTransmitter filename variable {prn} available outputfileClockReceiver filename variable {station} available huber double clock jumps > huber*sigma0 are downweighted huberPower double clock jumps > huber: sigma=(e/huber)^huberPower*sigma0 nameConstraint string used for parameter selection selectTransmittersZeroMean platformSelectorType use these transmitters for zero-mean constraint selectReceiversZeroMean platformSelectorType use these receivers for zero-mean constraint sigmaZeroMeanConstraint double (0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks name string used for parameter selection selectTransmitters platformSelectorType  selectReceivers platformSelectorType  outputfileSignalBiasTransmitter filename variable {prn} available outputfileSignalBiasReceiver filename variable {station} available inputfileSignalBiasTransmitter filename variable {prn} available inputfileSignalBiasReceiver filename variable {station} available name string used for parameter selection estimateTransmitterPhaseBias platformSelectorType  estimateReceiverPhaseBias platformSelectorType  linearGlonassBias boolean bias depends linear on frequency channel number name string used for parameter selection selectTransmitters platformSelectorType  selectReceivers platformSelectorType  linearGlonassBias boolean bias depends linear on frequency channel number typesClockDatum gnssType first two matching types define the ionosphere free transmitter clock (e.g. C1WG, C2WG) nameConstraint string used for parameter selection sigmaZeroMeanConstraint double (0 = unconstrained) sigma [m] for null space constraint name string used for parameter selection selectTransmitters platformSelectorType  selectReceivers platformSelectorType  linearGlonassBias boolean phase or code biases depend linear on frequency channel number nameConstraint string used for parameter selection sigmaZeroMeanConstraint double (0 = unconstrained) sigma [m] for null space constraint name string used for parameter selection selectTransmitters platformSelectorType  outputfileBiasTimeSeries filename variable {prn} available inputfileBiasTimeSeries filename variable {prn} available type gnssType  parametrizationTemporal parametrizationTemporalType  nameConstraint string used for parameter selection sigmaZeroMeanConstraint double (0 = unconstrained) sigma [m] for temporal zero-mean constraint name string used for parameter selection selectReceivers platformSelectorType  outputfileGriddedPosition filename delta north east up for all stations outputfilePosition filename variable {station} available, full estimated coordinates (in TRF) nameConstraint string used for parameter selection selectNoNetReceivers platformSelectorType  inputfileNoNetPositions filename variable {station} available, precise coordinates used for no-net constraints (in TRF) noNetTranslationSigma double (0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates noNetRotationSigma double (0 = unconstrained) sigma [m] at Earth\\'s surface for no-net rotation constraint on station coordinates noNetScaleSigma double (0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates huber double stations > huber*sigma0 are downweighted in no-net constraint huberPower double stations > huber: sigma=(e/huber)^huberPower*sigma0 name string used for parameter selection selectReceivers platformSelectorType  outputfilePositions filename variable {station} available, estimated kinematic positions/orbit outputfileCovarianceEpoch filename variable {station} available, 3x3 epoch covariances name string used for parameter selection selectReceivers platformSelectorType  outputfileOrbit filename variable {station} available outputfileParameters filename variable {station} available inputfileVariational filename variable {station} available stochasticPulse timeSeriesType [mu/s] parametrization of stochastic pulses parametrizationAcceleration parametrizationAccelerationType orbit force parameters ephemerides ephemeridesType  minEstimableEpochsRatio double drop satellites with lower ratio of estimable epochs to total epochs integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint for orbit interpolation and velocity calculation name string used for parameter selection selectTransmitters platformSelectorType  outputfileOrbit filename variable {prn} available outputfileParameters filename variable {prn} available inputfileVariational filename variable {prn} available stochasticPulse timeSeriesType [mu/s] parametrization of stochastic pulses parametrizationAcceleration parametrizationAccelerationType orbit force parameters ephemerides ephemeridesType  minEstimableEpochsRatio double drop satellites with lower ratio of estimable epochs to total epochs integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint for orbit interpolation and velocity calculation name string used for parameter selection selectReceivers platformSelectorType  outputfileTroposphere filename columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient, ... troposphere troposphereType a priori troposphere model troposphereWetEstimation parametrizationTemporalType [m] parametrization of zenith wet delays troposphereGradientEstimation parametrizationTemporalType [degree] parametrization of north and east gradients name string used for parameter selection outputfileEOP filename EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S) estimatePole parametrizationTemporalType xp, yp [mas] estimateUT1 parametrizationTemporalType rotation angle [ms] estimateNutation parametrizationTemporalType dX, dY [mas] name string used for parameter selection selectReceivers platformSelectorType  antennaCenterVariations parametrizationGnssAntennaType estimate antenna center variations patternTypes gnssType gnssType for each pattern (first match is used) addNonMatchingTypes boolean add patterns for additional observed gnssTypes that don\\'t match any of the above groupAntennas boolean common ACVs for same antenna build types (ignores antenna serial number) name string used for parameter selection selectTransmitters platformSelectorType  antennaCenterVariations parametrizationGnssAntennaType estimate antenna center variations patternTypes gnssType gnssType for each pattern (first match is used) addNonMatchingTypes boolean add patterns for additional observed gnssTypes that don\\'t match any of the above groupAntennas boolean common ACVs for same antenna build types (ignores antenna serial number) name string  parameters parameterSelectorType parameter to constrain sigma double sigma of the constraint (same unit as parameter) bias double constrain all selected parameters towards this value relativeToApriori boolean constrain only dx and not full x=dx+x0 parametrization gnssParametrizationType', 'display_text': 'This class defines the models and parameters of the linearized observation equations for all phase and code measurements (see <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>) \\\\[\\\\label{gnssParametrizationType:model}   \\\\M l - \\\\M f(\\\\M x_0) = \\\\left.\\\\frac{\\\\partial \\\\M f(\\\\M x)}{\\\\partial \\\\M x}\\\\right|_{\\\\M x_0} \\\\Delta\\\\M x + \\\\M\\\\epsilon, \\\\]where the left side is the observation vector minus the effects computed from the a priori models. After each least squares adjustment (see <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">GnssProcessing:processingStep:estimate</a>) the a priori parameters are updated \\\\[\\\\label{gnssParametrizationType:update}   \\\\M x_0 := \\\\M x_0 + \\\\Delta\\\\hat{\\\\M x}. \\\\]The vector $\\\\M x_0$ can be written with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeAprioriSolution\">GnssProcessing:processingStep:writeAprioriSolution</a>. Any <strong class=\"groops-config-element\">outputfiles</strong> defined in the parametrizations are written with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">GnssProcessing:processingStep:writeResults</a>.</p><p>Each parametrization (and possible constraint equations) has a <strong class=\"groops-config-element\">name</strong> which enables activating/deactivating the estimation of subsets of $\\\\Delta\\\\M x$ with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">GnssProcessing:processingStep:selectParametrizations</a>. The a priori model $\\\\M f(\\\\M x_0)$ is unaffected and is always reduced.</p><p>The model for the different observation types can be described as \\\\[\\\\label{gnssParametrizationType:gnssFullModel} \\\\begin{split}   f[\\\\tau\\\\nu a]_r^s(\\\\M x) &= \\\\text{geometry}(\\\\M r_r^s) + \\\\text{clock}^s(t) + \\\\text{clock}_r(t) \\\\\\\\                &+ \\\\text{ionosphere}([\\\\tau\\\\nu],t,\\\\M r_r^s) + \\\\text{troposphere}(t,\\\\M r_r^s) \\\\\\\\                &+ \\\\text{antenna}[\\\\tau\\\\nu a]^s  + \\\\text{antenna}[\\\\tau\\\\nu a]_r \\\\\\\\                &+ \\\\text{bias}[\\\\tau\\\\nu a]^s + \\\\text{bias}[\\\\tau\\\\nu a]_r                + \\\\lambda[L\\\\nu] N[L\\\\nu a]_r^s + \\\\text{other}(\\\\ldots) + \\\\epsilon[\\\\tau\\\\nu a]_r^s \\\\end{split} \\\\]The notation $[\\\\tau\\\\nu a]_r^s$ describes the attribution to a signal type $\\\\tau$ (i.e., C or L), frequency $\\\\nu$, signal attribute $a$ (e.g., C, W, Q, X), transmitting satellite $s$, and observing receiver $r$. It follows the <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>, see <a class=\"groops-ref\" href=\"gnssType.html\">GnssType</a>.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.  <h2 id=\"ionosphereSTEC\">IonosphereSTEC</h2><p> The influence of the ionosphere is modelled by a STEC parameter (slant total electron content) in terms of $[TECU]$ between each transmitter and receiver at each epoch. These parameters are pre-eliminated from the observation equations before accumulating the normal equations. This is similar to using the ionosphere-free linear combination as observations but only one STEC parameter is needed for an arbitrary number of observation types.</p><p>The influence on the code and phase observation is modeled as \\\\[\\\\label{gnssParametrizationType:IonosphereSTEC:STEC} \\\\begin{split} \\\\text{ionosphere}([C\\\\nu], STEC) &=  \\\\frac{40.3}{f_{\\\\nu}^2}STEC + \\\\frac{7525\\\\M b^T\\\\M k}{f_{\\\\nu}^3}STEC +  \\\\frac{r}{f_{\\\\nu}^4}STEC^2 \\\\\\\\ \\\\text{ionosphere}([L\\\\nu], STEC) &= -\\\\frac{40.3}{f_{\\\\nu}^2}STEC - \\\\frac{7525\\\\M b^T\\\\M k}{2f_{\\\\nu}^3}STEC - \\\\frac{r}{3f_{\\\\nu}^4}STEC^2 + \\\\text{bending}(E)STEC^2 \\\\end{split} \\\\]The second order term depends on the <a class=\"groops-class\" href=\"magnetosphereType.html\">magnetosphere</a> $\\\\M b$ and the direction of the signal $\\\\M k$.</p><p>If further information about the ionosphere is available (in the form of a prior model or as additional parametrizations such as <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">parametrization:ionosphereMap</a> or <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">parametrization:ionosphereVTEC</a>) the STEC parameters describe local and short–term scintillations. The STEC parameters are estimated as additions to the model and it is advised to constrain them towards zero with a standard deviation of <strong class=\"groops-config-element\">sigmaSTEC</strong>.  <h2 id=\"ionosphereVTEC\">IonosphereVTEC</h2><p> The influence of the ionosphere is modelled by a VTEC parameter (vertical total electron content) in terms of $[TECU]$ for every selected receiver at each epoch. Optionally, VTEC gradients in the North (x) and East (y) direction can be estimated via <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">gradient</a>. The slant TEC is computed based on the VTEC and the optional North and East gradients $\\\\Delta V_x$ and $\\\\Delta V_y$ using the elevation-dependent Modified Single-Layer Model (MSLM) mapping function \\\\[\\\\label{gnssParametrizationType:IonosphereVTEC:STEC}   STEC = \\\\frac{VTEC + \\\\cos(A) \\\\Delta V_x + \\\\sin(A) \\\\Delta V_y}{\\\\cos z\\'}   \\\\qquad\\\\text{with}\\\\qquad   \\\\sin z\\'= \\\\left(\\\\frac{R}{R+H}\\\\right)\\\\sin\\\\left(\\\\alpha(\\\\pi/2-E)\\\\right) \\\\]inserted into eq. \\\\eqref{gnssParametrizationType:IonosphereSTEC:STEC}, where $A$ is the azimuth angle and $E$ is the elevation angle.</p><p>The result is written as a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">times series file</a> at epochs with observations depending on <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">GnssProcessing:processingStep:selectEpochs</a>.</p><p>This class provides a simplified model of the ionosphere for single receivers and enables the separation of the TEC and signal biases, meaning <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a> becomes estimable. Local and short-term scintillations should be considered by adding loosely constrained <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">parametrization:ionosphereSTEC</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>&lt;station>:VTEC::&lt;time></code>, </li><li> <code>&lt;station>:VTECGradient.x:&lt;temporal>:&lt;interval></code>, </li><li> <code>&lt;station>:VTECGradient.y:&lt;temporal>:&lt;interval></code>. </li></ul>   <h2 id=\"ionosphereMap\">IonosphereMap</h2><p> Apriori VTEC maps can be removed from the observations with <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a> (e.g. from <a class=\"groops-program\" href=\"GnssIonex2GriddedDataTimeSeries.html\">GnssIonex2GriddedDataTimeSeries</a>).</p><p>The ionosphere is parametrized in terms of $[TECU]$ in a single layer sphere with <strong class=\"groops-config-element\">radiusIonosphericLayer</strong> as a <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">temporal</a>ly changing (e.g. hourly linear splines) spherical harmonics expansion \\\\[   VTEC(\\\\lambda,\\\\theta,t) = \\\\sum_{n=0}^{n_{max}} \\\\sum_{m=0}^n c_{nm}(t)C_{nm}(\\\\lambda,\\\\theta)+s_{nm}(t)S_{nm}(\\\\lambda,\\\\theta) \\\\]up to <strong class=\"groops-config-element\">maxDegree</strong>=<code>15</code> in a solar-geomagentic frame defined by <a class=\"groops-class\" href=\"magnetosphereType.html\">magnetosphere</a>. The VTEC values are mapped to STEC values in the observation equations via eq. \\\\eqref{gnssParametrizationType:IonosphereVTEC:STEC}.</p><p>The estimated VTEC inclusive the apriori <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a> can be written to <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">outputfileGriddedDataTimeSeries</a> evaluated at <a class=\"groops-class\" href=\"gridType.html\">outputGrid</a> and <a class=\"groops-class\" href=\"timeSeriesType.html\">outputTimeSeries</a>.</p><p>Local and short-term scintillations should be considered by adding constrained <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">parametrization:ionosphereSTEC</a>. To account for signal biases add <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>VTEC:sphericalHarmonics.c_&lt;degree>_&lt;order>:&lt;temporal>:&lt;interval></code>, </li><li> <code>VTEC:sphericalHarmonics.s_&lt;degree>_&lt;order>:&lt;temporal>:&lt;interval></code>. </li></ul>   <h2 id=\"clocks\">Clocks</h2><p> Clock errors are estimated epoch-wise for each <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a>. No clock errors are estimated if no valid observations are available (e.g. data gaps in the observations).</p><p>If all transmitters and receivers are selected by <strong class=\"groops-config-element\">selectTransmitters</strong> and <strong class=\"groops-config-element\">selectReceivers</strong> respectively, these parameters will be lineary dependent which would lead to a rank deficiency in the normal equation matrix. To circumvent this issue, the estimation requires an additional zero-mean constraint added in each epoch. This is realized with an additional observation equation \\\\[   0 = \\\\frac{1}{n_i + n_k} (\\\\sum_i \\\\Delta t^{s_i} + \\\\sum_k \\\\Delta t_{r_k}) \\\\]summed over all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/ReceiversZeroMean</a> with a standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:clock::&lt;time></code>.  <h2 id=\"clocksModel\">ClocksModel</h2><p> This parametrization is an alternative to <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">parametrization:clocks</a>. Clock errors are estimated epoch-wise for each <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a> and, opposed to <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">parametrization:clocks</a>, are also estimated for epochs that have no valid observations available (e.g. data gaps).</p><p>The clock error of an epoch can be predicted by the clock error of the preceding epoch and an unknown clock drift \\\\[   \\\\Delta t_{i+1} = \\\\Delta t_{i} + t_{drift} dt + \\\\epsilon_i. \\\\]This equation is applied as an additional constraint equation in each epoch \\\\[   0 = \\\\Delta t_{i+1} - \\\\Delta t_{i} - t_{drift} dt + \\\\epsilon_i. \\\\]The variance $\\\\sigma^2(\\\\epsilon)$ is estimated iteratively by variance component estimation (VCE). Clock jumps are treated as outliers and are automatically downweighted as described in <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">GnssProcessing:processingStep:estimate</a>.</p><p>The absolute initial clock error and clock drift cannot be determined if all receiver and transmitter clocks are estimated together due to their linear dependency. This linear dependency would lead to a rank deficiency in the normal equation matrix in the same manner as described in <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">parametrization:clocks</a>. To circumvent this issue, an additional zero-mean constraint is added in each epoch as observation equation \\\\[   0 = \\\\frac{1}{n_i + n_k} (\\\\sum_i \\\\Delta t^{s_i} + \\\\sum_k \\\\Delta t_{r_k}) \\\\]summed over all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/ReceiversZeroMean</a>. This should be a loose constraint with a relatively large standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:clock::&lt;time></code> and <code>&lt;station or prn>:clockDrift::</code>.  <h2 id=\"signalBiases\">SignalBiases</h2><p> Each code and phase observation (e.g <code>C1C</code> or <code>L2W</code>) contains a bias at transmitter/receiver level \\\\[   [\\\\tau\\\\nu a]_r^s(t) = \\\\dots + \\\\text{bias}[\\\\tau\\\\nu a]^s + \\\\text{bias}[\\\\tau\\\\nu a]_r + \\\\dots \\\\]This class provides the apriori model $\\\\M f(\\\\M x_0)$ of eq. \\\\eqref{gnssParametrizationType:model} only.</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBiasTransmitter/Receiver</a> are read for each transmitter and receiver. Those file names are interpreted as a template with the variable <code>{prn}</code> or <code>{station}</code> being replaced by transmitter PRNs or receiver station names, respectively. (Infos regarding the variables <code>{prn}</code> and <code>{station}</code> can be found in <a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html\">gnssTransmitterGeneratorType</a> and <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">gnssReceiverGeneratorType</a> respectively). Those files can be converted with <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>.</p><p>The estimation of the biases is complex due to different linear dependencies, which result in rank deficiencies in the system of normal equations. For simplification the parametrization for $\\\\Delta\\\\M x$ has been split into: <a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">parametrization:codeBiases</a>, <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a>, and <a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">parametrization:ambiguities</a> (including phase biases). The file handling on the other hand still remains within this class. Any prior values for the transmitter/receiver biases are read with the respective <strong class=\"groops-config-element\">inputfileSignalBiasTransmitter/Receiver</strong>. All biases for a transmitter/receiver are accumulated and written to the respective <strong class=\"groops-config-element\">outputfileSignalBiasTransmitter/Receiver</strong>.  <h2 id=\"ambiguities\">Ambiguities</h2><p> Sets up an ambiguity parameter for each track and phase observation type. \\\\[   [L\\\\nu a]_r^s(t) = \\\\dots + \\\\text{bias}[L\\\\nu a]^s + \\\\text{bias}[L\\\\nu a]_r + \\\\lambda[L\\\\nu] N[L\\\\nu a]_r^s \\\\]As the phase observations contain a float bias at transmitter/receiver level, not all ambiguities are resolvable to integer values. The number of resolvable ambiguities can be increased with known phase biases read from file via <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>. In this case, <a class=\"groops-class\" href=\"platformSelectorType.html\">estimateTransmitter/ReceiverPhaseBias</a> should not be used for the corresponding transmitters and receivers.</p><p>In case of GLONASS, the phase biases at receiver level differ between different frequency channels (frequency division multiple access, FDMA) and for each channel an extra float phase bias is estimated. With <strong class=\"groops-config-element\">linearGlonassBias</strong> a linear relationship between bias and frequency channel is assumed, which reduces the number of float bias parameters and increases the number of resolvable integer ambiguities.</p><p>The integer ambiguities can be resolved and fixed in <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">GnssProcessing:processingStep:resolveAmbiguities</a>. Resolved integer ambiguities are not estimated as unknown parameters in <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">gnssProcessingStepType:estimate</a> anymore and are removed from the system of normal equations.</p><p>The estimated phase biases can be written to files in <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>&lt;station>:phaseBias(&lt;gnssType>)::</code>, </li><li> <code>&lt;prn>:phaseBias(&lt;gnssType>)::</code>, </li><li> <code>&lt;station>.&lt;prn>:ambiguity&lt;index>of&lt;count>(&lt;GnssTypes>)::&lt;track interval></code>. </li></ul>   <h2 id=\"codeBiases\">CodeBiases</h2><p> Each code observation (e.g <code>C1C</code> or <code>C2W</code>) contains a bias at transmitter/receiver level \\\\[   [C\\\\nu a]_r^s(t) = \\\\dots + \\\\text{bias}[C\\\\nu a]^s + \\\\text{bias}[C\\\\nu a]_r + \\\\dots \\\\]The code biases cannot be estimated together with clock errors and ionospheric delays in an absolute sense as rank deficiencies will occur in the system of normal equations. Therefore, the biases are not initialized and set up as parameters directly but only estimable linear combinations are parametrized.</p><p>The basic idea is to set up simplified normal equations with the biases, clock and STEC parameters of one single receiver or transmitter, eliminate clock and STEC parameters and perform an eigen value decomposition of the normal equation matrix \\\\[   \\\\M N = \\\\M Q \\\\M\\\\Lambda \\\\M Q^T. \\\\]Instead of estimating the original bias parameter $\\\\M x$ a transformed set $\\\\bar{\\\\M x}$ is introduced: \\\\[   \\\\bar{\\\\M x} = \\\\M Q^T \\\\M x. \\\\]The new parameters corresponding to eigen values $\\\\lambda>0$ are estimable, the others are left out (set to zero). The behavior can be controlled by explicitly setting up to two bias types with <a class=\"groops-class\" href=\"gnssType.html\">typesClockDatum</a> for each transmitter to zero. These then define the ionosphere-free clock datum of the transmitter. The missing linear combinations, which depend on the STEC parameters, can be added with <a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a>.</p><p>Additional rank deficiencies may also occur when biases of transmitters and receivers are estimated together. The minimum norm nullspace (also via eigen value decomposition) is formulated as zero constraint equations and added with a standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>In case of GLONASS the code biases at receiver level can differ between different frequency channels (frequency division multiple access, FDMA) and for each channel an extra code bias is estimated. With <strong class=\"groops-config-element\">linearGlonassBias</strong> a linear relationship between bias and frequency channel is assumed, which reduces the number of bias parameters.</p><p>The estimated biases can be written to files in <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:codeBias0&lt;index>&lt;combi of gnssTypes>::</code>.  <h2 id=\"tecBiases\">TecBiases</h2><p> Each code observation (e.g <code>C1C</code> or <code>C2W</code>) contains a bias at transmitter/receiver level \\\\[   [C\\\\nu a]_r^s(t) = \\\\dots + \\\\text{bias}[C\\\\nu a]^s + \\\\text{bias}[C\\\\nu a]_r + \\\\ldots \\\\]This parametrization represents the linear combination of signal biases which completely depend on the STEC parameters. Ignoring these bias combinations would result in a biased STEC estimation (all other parameters are nearly unaffected). To determine this part of the signal biases the <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">parametrization:ionosphereSTEC</a> should be constrained. Furthermore, additional information about the ionosphere is required from <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">parametrization:ionosphereVTEC</a> or <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">parametrization:ionosphereMap</a>.</p><p>Rank deficiencies due to the signal bias parameters may occur if biases of transmitters and receivers are estimated together. The minimum norm nullspace is formulated as zero constraint equations and added with a standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The accumulated estimated result can be written to files in <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:tecBias0&lt;index>&lt;combi of gnssTypes>::</code>.  <h2 id=\"temporalBias\">TemporalBias</h2><p> This parametrization resolves the issue of some phase observations suffering from time-variable biases. Such a phenomenon has been found to affect GPS block IIF satellites on the L5 phase measurements (see Montenbruck et al. 2011, DOI: <a href=\"https://doi.org/10.1007/s10291-011-0232-x\">10.1007/s10291-011-0232-x</a>).</p><p>For these time-variable biases an appropriate temporal representation has to be defined in <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>. For example, time-variable biases for GPS block IIF L5 phase observations (<a class=\"groops-class\" href=\"gnssType.html\">type</a>=<code>L5*G</code>) can be represented by a cubic spline with a nodal distance of one hour.</p><p>The result is written as a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">times series file</a> at the processing sampling or the sampling set by <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">GnssProcessing:processingStep:selectEpochs</a>).</p><p>This parametrization should be set up in addition to the constant <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>. Depending on the temporal representation a temporal zero-mean constraint is needed to separate this parametrization from the constant component. The constraint equations are added with a standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;prn>:signalBias.&lt;gnssType>:&lt;temporal>:&lt;interval></code>.  <h2 id=\"staticPositions\">StaticPositions</h2><p> Estimates a static position for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a> in the terrestrial frame.</p><p>No-net constraints can be applied for a subset of stations, <a class=\"groops-class\" href=\"platformSelectorType.html\">selectNoNetReceivers</a>, with a standard deviation of <strong class=\"groops-config-element\">noNetTranslationSigma</strong> and <strong class=\"groops-config-element\">noNetRotationSigma</strong> and <strong class=\"groops-config-element\">noNetScaleSigma</strong>. If the template <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a> is provided the constraints are applied relatively to these positions. Only stations with an existing position file are considered. Without <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a> the constraints are applied towards the apriori values from <a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">GnssProcessing:receiver</a>. As a single corrupted station position can disturb the no-net conditions, the rotation/translation parameters are estimated in a <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a> beforehand. The computed weight matrix is used to downweight corrupted stations in the constraint equations.</p><p>In case you want to align to an ITRF/IGS reference frame, precise coordinates can be generated with <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>&lt;station>:position.x::</code>, </li><li> <code>&lt;station>:position.y::</code>, </li><li> <code>&lt;station>:position.z::</code>. </li></ul>   <h2 id=\"kinematicPositions\">KinematicPositions</h2><p> Estimates the epoch-wise <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfilePositions</a> in an Earth-fixed frame (or in case of LEO satellites in an intertial frame).</p><p>The $3\\\\times3$ epoch wise <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileCovarianceEpoch</a> are computed within <a class=\"groops-class\" href=\"gnssProcessingStepType.html#computeCovarianceMatrix\">GnssProcessing:processingStep:computeCovarianceMatrix</a></p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>&lt;station>:position.x::&lt;time></code>, </li><li> <code>&lt;station>:position.y::&lt;time></code>, </li><li> <code>&lt;station>:position.z::&lt;time></code>. </li></ul>   <h2 id=\"leoDynamicOrbits\">LeoDynamicOrbits</h2><p> The estimation of (reduced) dynamic orbits is formulated as variational equations. It is based on <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> calculated with <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>. Necessary integrations are performed by integrating a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>. The <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> must include at least those parameters that were estimated in <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>. Additional <a class=\"groops-class\" href=\"timeSeriesType.html\">stochasticPulse</a> parameters can be set up to reduce orbit mismodeling. If not enough epochs with observations are available (<strong class=\"groops-config-element\">minEstimableEpochsRatio</strong>) the LEO satellite is disabled.</p><p>The parameters and <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are divided into global <ul>  <li><code>&lt;station>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;station>:stochasticPulse.x::&lt;time></code>, </li><li> <code>&lt;station>:stochasticPulse.y::&lt;time></code>, </li><li> <code>&lt;station>:stochasticPulse.z::&lt;time></code>, </li></ul>  and arc related parameters <ul>  <li><code>&lt;station>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;station>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;station>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;station>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;station>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;station>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;station>:arc&lt;no>.velocity0.z::</code>. </li></ul>   <h2 id=\"transmitterDynamicOrbits\">TransmitterDynamicOrbits</h2><p> Same as <a class=\"groops-class\" href=\"gnssParametrizationType.html#leoDynamicOrbits\">leoDynamicOrbits</a> but for transmitting GNSS satellites. For more details see <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#orbitIntegration\">orbit integration</a>.  <h2 id=\"troposphere\">Troposphere</h2><p> A priori tropospheric correction is handled by a <a class=\"groops-class\" href=\"troposphereType.html\">troposphere</a> model (e.g. Vienna Mapping Functions 3). Additional parameters in $[m]$ for zenith wet delay and gradients can be set up via <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">troposphereWetEstimation</a> (usually 2-hourly linear splines) and <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">troposphereGradientEstimation</a> (usually a daily trend). These parameters can be soft-constrained using <a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">parametrization:constraints</a> to avoid an unsolvable system of normal equations in case of data gaps.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>&lt;station>:troposphereWet:&lt;temporal>:&lt;interval></code>, </li><li> <code>&lt;station>:troposphereGradient.x:&lt;temporal>:&lt;interval></code>, </li><li> <code>&lt;station>:troposphereGradient.y:&lt;temporal>:&lt;interval></code>. </li></ul>   <h2 id=\"earthRotation\">EarthRotation</h2><p> Earth rotation parameters (ERPs) can be estimated by defining <strong class=\"groops-config-element\">estimatePole</strong> ($x_p$, $y_p\\\\, [mas]$) and <strong class=\"groops-config-element\">estimateUT1</strong> ($dUT1\\\\, [ms], LOD$).</p><p>Estimating length of day (LOD) with the sign according to IGS conventions requires a negative value in <a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">parametrizationTemporal:trend:timeStep</a>.</p><p>Constraints on the defined parameters can be added via <a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">parametrization:constraints</a>. An example would be to set up <a class=\"groops-class\" href=\"parametrizationTemporalType.html#constant\">estimateUT1:constant</a> so the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be determined by GNSS, a hard constraint to its a priori value can then be added.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>earth:polarMotion.xp:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:polarMotion.yp:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:UT1:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:nutation.X:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:nutation.Y:&lt;temporal>:&lt;interval></code>. </li></ul>   <h2 id=\"receiverAntennas\">ReceiverAntennas</h2><p> This class is for parametrization the antenna for their antenna center offsets (ACO) and antenna center variations (ACV) by <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>. The receivers to be estimated can be selected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a>.</p><p>The amount of patterns to be estimated is configurable with a list of <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a>. For each added <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a> a set of parameters will be evaluated. The observations will be assigned to the first <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a> that matches their own. E.g. having the patterns: <code>***G</code> and <code>L1*</code> would lead to all GPS observations be assigned to the observation equations of the first pattern. The pattern type <code>L1*</code> would then consist of all other GNSS L1 phase observations. <strong class=\"groops-config-element\">addNonMatchingTypes</strong> will, if activated, create automatically patterns for <a class=\"groops-class\" href=\"gnssType.html\">observations</a> that are not selected within the list <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a>. Furthermore, it is possible to group same antenna build types from different receivers by <strong class=\"groops-config-element\">groupAntennas</strong>. The grouping by same antenna build ignores antenna serial numbers.</p><p>To estimate the antenna variation parameters, a longer period of observations might be necessary for accurate estimations. Hence one should use this parametrization by accumulating normal equations from several epochs. This can be accomplished as the last steps in the <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processing steps</a>  by adding <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">ReceiverAntennas</a> to current selected parameters with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">GnssProcessing:processingStep:selectParametrizations</a> and write the normal equation matrix with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeNormalEquations\">GnssProcessing:processingStep:writeNormalEquations</a>. The written normal equations can then be accumulated with <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a> and solved by <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>. Further, one should apply constraints to the normal equations by <a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a> since the estimation  of ACO and ACV can lead to rank deficiencies in the normal equation matrix. Last the solved normal equation can be parsed to a <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a>  with the program <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>.</p><p>As example referring to the cookbook <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>, one could add additionally <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">receiverAntennas</a> as parametrization. Since the estimations are done on a daily basis for each receiver we add an additional <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a> which disables <code>parameter.receiverAntenna</code>. After all stations are processed together with all parameters, one adds <code>parameter.receiverAntenna</code> with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>  to the current selected parametrizations. The last <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingStep</a> is <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeNormalEquations\">GnssProcessing:processingStep:writeNormalEquations</a> to write the daily normal equations including the parametrization <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">receiverAntennas</a> into files. These normal equation files are then processed with the programs:</p><p><ul>    <li><a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>: accumulates normal equations.   </li><li> <a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a>: apply constraint to the normal equations.   </li><li> <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>: solves the normal equations.   </li><li> <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>: writes the solution into a <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a> </li></ul> </p><p>Note that the apriori value $\\\\M x_0$ for this parametrization is always zero and never updated according to eq. \\\\eqref{gnssParametrizationType:update}.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;antennaName>:&lt;antennaCenterVariations>.&lt;gnssType>::</code>.  <h2 id=\"transmitterAntennas\">TransmitterAntennas</h2><p> Same as <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">receiverAntennas</a> but for transmitting antennas (GNSS satellites).</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;antennaName>:&lt;antennaCenterVariations>.&lt;gnssType>::</code>.  <h2 id=\"constraints\">Constraints</h2><p> Add a pseudo observation equation (constraint) for each selected <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameters</a> \\\\[   b-x_0 = 1 \\\\cdot dx + \\\\epsilon, \\\\]where $b$ is the <strong class=\"groops-config-element\">bias</strong> and $x_0$ is the a priori value of the parameter if <strong class=\"groops-config-element\">relativeToApriori</strong> is not set. The standard deviation <strong class=\"groops-config-element\">sigma</strong> is used to weight the observation equations.  <h2 id=\"group\">Group</h2><p> Groups a set of parameters. This class can be used to structure complex parametrizations and has no further effect itself.'},\n'gnssProcessingStepType': { 'name': 'gnssProcessingStepType', 'key': 'gnssProcessingStepType', 'description': 'Processing step in  GnssProcessing . Processing steps enable a dynamic definition of the consecutive steps performed during any kind of GNSS processing. The most common steps are    , which performs an iterative least squares adjustment, and    , which writes all output files defined in  GnssProcessing  and is usually the last step. Some steps such as    ,    ,    , and     affect all subsequent steps. In case these steps are used within a     or     step, they only affect the steps within this level. For usage examples see cookbooks on  GNSS satellite orbit determination and network analysis  or  Kinematic orbit determination of LEO satellites .     Iterative non-linear least squares adjustment. In every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters. The estimated parameters serve as a priori values in the next iteration and the following processing steps. Iterates until either every single parameter update (converted to an influence in meters) is below a  convergenceThreshold  or  maxIterationCount  is reached. With  computeResiduals  the observation equations are computed again after each update to compute the observation residuals. The overall standard deviation of a single observation used for the weighting is composed of several factors  where   is the signal type, the azimuth and elevation dependent   is given by     and the other factors are estimated iteratively from the residuals. With  computeWeights  a standardized variance   for each residual   is computed  taking the redundancy   into account. If   is above a threshold  huber  the observation gets a higher standard deviation used for weighting according to  similar to  robust least squares adjustment . With  adjustSigma0  individual variance factors can be computed for each station and all phases of a system and each code observation  type  (e.g. for each  L**G ,  L**E ,  C1CG ,  C2WG ,  C1CE ,  ) separately      Performs a least squares adjustment like     but with additional integer phase ambiguity resolution. After this step all resolved ambiguities are removed from the normal equation system. Only ambiguities involving     are resolved. If     is not set, all usable transmitters and/or  receivers are selected for ambiguity resolution. Integer ambiguity resolution is performed based on the least squares ambiguity decorrelation adjustment (LAMBDA) method (Teunissen 1995, DOI  ), specifically the modified algorithm (MLAMBDA) by Chang et al. (2005, DOI  ). First the covariance matrix of the integer ambiguity parameters is computed by eliminating all but those parameters from the full normal equation matrix and inverting it. Then, a Z-transformation is performed as described by Chang et al. (2005) to decorrelate the ambiguity parameters without losing their integer nature. The search process follows MLAMBDA and uses integer minimization of the weighted sum of squared residuals. It is computationally infeasible to search a hyper-ellipsoid with a dimension of ten thousand or more. Instead, a blocked search algorithm is performed by moving a window with a length of, for example,  searchBlockSize = 200  parameters over the decorrelated ambiguities, starting from the most accurate. In each step, the window is moved by half of its length and the overlapping parts are compared to each other. If all fixed ambiguities in the overlap agree, the algorithm continues. Otherwise, both windows are combined and the search is repeated using the combined window, again comparing with the overlapping part of the preceding window. If not all solutions could be checked for a block after  maxSearchSteps , the selected  incompleteAction  is performed. If the algorithm reaches ambiguities with a standard deviation higher than  sigmaMaxResolve , ambiguity resolution stops and the remaining ambiguities are left as float values. Otherwise, all ambiguity parameters are fixed to integer values. In contrast to an integer least squares solution over the full ambiguity vector, it is not guaranteed that the resulting solution is optimal in the sense of minimal variance with given covariance. This trade-off is necessary to cope with large numbers of ambiguities.     Accumulates the normal equations and computes the covariance matrix as inverse of the normal matrix. It is not the full inverse but only the elements which are set in the normal matrix (see     ) are computed. The matrix is passed to the    . Only used in     to get the epoch-wise covariance information at the moment.     In this step all  outputfiles  defined in     are written. It considers the settings of    ,    , and    . It is usually the last processing step, but can also be used at other points in the processing in combination with  suffix  to write intermediate results, for example before     to output the float solution.     Accumulates the normal equations matrix and writes it. If     is set only the selected parameters are written to the normal equations and all other parameters are eliminated beforehand (implicitly solved). The solution of the normals would result in   (see    ). To write the appropriate apriori vector   use    .     Writes the current apriori vector   (see    ). If     is set only the selected parameters are written.     Writes the  observation residuals  for all    . For each station a file is written. The file name is interpreted as a template with the variable  {station}  being replaced by the station name.     Writes a  list  of receivers (stations) which are used in the last step and selected by    .     Writes a  list  of transmitters which are used in the last step and selected by    .     Print residual statistics.     areq: C1CG**: factor =  0.64, sigma0 = 1.00, count =  2748, outliers =    48 (1.75  )   areq: C1WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    43 (1.56  )   areq: C2WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    59 (2.15  )   areq: C5XG**: factor =  0.46, sigma0 = 1.00, count =  1279, outliers =    23 (1.80  )   areq: L1CG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46  )   areq: L1WG**: factor =  0.86, sigma0 = 1.02, count =  2748, outliers =    40 (1.46  )   areq: L2WG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46  )   areq: L5XG**: factor =  0.86, sigma0 = 1.30, count =  1279, outliers =    14 (1.09  )   areq: C1PR**: factor =  0.48, sigma0 = 1.00, count =  1713, outliers =    53 (3.09  )   areq: C2PR**: factor =  0.55, sigma0 = 1.00, count =  1713, outliers =    51 (2.98  )   areq: L1PR**: factor =  0.85, sigma0 = 1.09, count =  1713, outliers =    29 (1.69  )   areq: L2PR**: factor =  0.85, sigma0 = 0.88, count =  1713, outliers =    29 (1.69  )   areq: C1XE**: factor =  0.44, sigma0 = 1.00, count =  1264, outliers =    21 (1.66  )   areq: C5XE**: factor =  0.33, sigma0 = 1.00, count =  1264, outliers =    27 (2.14  )   areq: C7XE**: factor =  0.28, sigma0 = 1.00, count =  1264, outliers =    41 (3.24  )   areq: L1XE**: factor =  0.82, sigma0 = 1.14, count =  1264, outliers =    15 (1.19  )   areq: L5XE**: factor =  0.82, sigma0 = 0.84, count =  1264, outliers =    15 (1.19  )   areq: L7XE**: factor =  0.82, sigma0 = 0.94, count =  1264, outliers =    15 (1.19  )   badg: C1CG**: factor =  1.25, sigma0 = 1.00, count =  2564, outliers =    47 (1.83  )   ...       Enable/disable parameter groups and constraint groups for subsequent steps, e.g.     or    . The  name  and  nameConstraint  of these groups are defined in    . Prior models or previously estimated parameters used as new apriori   values are unaffected and they are always reduced from the observations. This means all unselected parameters are kept fixed to their last result. An example would be to process at a 5-minute sampling using     and then at the end to densify the clock parameters to the full 30-second observation sampling while keeping all other parameters fixed ( disable = * ,  enable = *.clock* ,  enable = parameter.STEC ).     Select epochs for subsequent steps. This step can be used to reduce the processing sampling while keeping the original observation sampling for all preprocessing steps (e.g. outlier and cycle slip detection). Another example is to process at a 5-minute sampling by setting  nthEpoch = 10  and then at the end to densify only the clock parameters to the full 30-second observation sampling by setting  nthEpoch = 1  while keeping all other parameters fixed with    .     Select block structure of sparse normal equations for subsequent steps. This step can be used to define the structure of the different parts of the normal equation system, which can have a major impact on computing performance and memory consumption depending on the processing setup. The normal equation system is divided into three parts for epoch, interval, and ambiguity parameters. The epoch part is subdivided further into one subpart per epoch. Each part is divided into blocks and only non-zero blocks are stored in memory to reduce memory consumption and to prevent unnecessary matrix computations.  defaultBlockSizeEpoch ,  defaultBlockSizeInterval , and  defaultBlockSizeAmbiguity  control the size of the blocks within each part of the normal equations.  defaultBlockReceiverCount  can be set to group a number of receivers into one block within the epoch and interval parts. If  keepEpochNormalsInMemory = no  epoch blocks are eliminated after they are set up to reduce the number of parameters in the normal equation system.  defaultBlockCountReduction  controls after how many epoch blocks an elimination step is performed. For larger processing setups or high sampling rates epoch block elimination is recommended as the large number of clock parameters require a lot of memory.     This step can be used to process only a subset of stations in subsequent processing steps. The most common use is to start the processing with a well-distributed network of core stations as seen in  GNSS satellite orbit determination and network analysis . To later process all other stations individually, use the processing step     and select all stations excluding the core stations in that step.     Perform these processing steps for each     separately. All non-receiver-related parameters parameters are disabled in these processing steps. This step can be used for individual precise point positioning (PPP) of all stations. During  GNSS satellite orbit determination and network analysis  this step is used after the initial processing of the core network to process all other stations individually. In that case provide the same station list as     in this step that was used as     in the     step where the core network was selected.     Perform these processing steps. This step can be used to structure complex processing flows. The    s that affect the following steps (those beginning with Select) only have an effect until the end of the group.     Disable transmitter epochs during eclipse. With proper attitude modeling (see  SimulateStarCameraGnss ) this is usually not necessary.', 'config_table': 'computeResiduals boolean  adjustSigma0 boolean adjust sigma0 by scale factor (per receiver and type) computeWeights boolean downweight outliers huber double residuals > huber*sigma0 are downweighted huberPower double residuals > huber: sigma=(e/huber)^huberPower*sigma0 convergenceThreshold double [m] stop iteration once full convergence is reached maxIterationCount uint maximum number of iterations outputfileAmbiguities filename resolved ambiguities selectTransmitters platformSelectorType only resolve ambiguities with these participating transmitters selectReceivers platformSelectorType only resolve ambiguities with these participating receivers sigmaMaxResolve double max. allowed std. dev. of ambiguity to resolve [cycles] searchBlockSize uint block size for blocked integer search maxSearchSteps uint max. steps of integer search for each block incompleteAction choice if not all solutions tested after maxSearchSteps stop  stop searching, ambiguities remain float in this block resolve  use best integer solution found so far shrinkBlockSize  try again with half block size throwException  stop and throw an exception computeResiduals boolean  adjustSigma0 boolean adjust sigma0 by scale factor (per receiver and type) computeWeights boolean downweight outliers huber double residuals > huber*sigma0 are downweighted huberPower double residuals > huber: sigma=(e/huber)^huberPower*sigma0 suffix string appended to every output file name (e.g. orbit.G01.suffix.dat) outputfileNormalEquations filename normals remainingParameters parameterSelectorType parameter order/selection of output normal equations constraintsOnly boolean write only normals of constraints without observations defaultNormalsBlockSize uint block size for distributing the normal equations, 0: one block, empty: original block size outputfileAprioriSolution filename a priori parameters outputfileParameterNames filename parameter names remainingParameters parameterSelectorType parameter order/selection of output normal equations selectReceivers platformSelectorType subset of used stations outputfileResiduals filename variable {station} available selectReceivers platformSelectorType subset of used stations outputfileUsedStationList filename ascii file with names of used stations selectTransmitters platformSelectorType subset of used transmitters outputfileUsedTransmitterList filename ascii file with PRNs parametrization choice  enable sequence  name string wildcards: * and ? disable sequence  name string wildcards: * and ? nthEpoch uint use only every nth epoch in all subsequent processing steps defaultBlockSizeEpoch uint block size of epoch parameters, 0: one block defaultBlockSizeInterval uint block size of interval parameters, 0: one block defaultBlockSizeAmbiguity uint block size of ambiguity parameters, 0: one block defaultBlockReceiverCount uint number of receivers to group into one block for epoch and interval defaultBlockCountReduction uint minimum number of blocks for epoch reduction keepEpochNormalsInMemory boolean speeds up processing but uses much more memory accumulateEpochObservations boolean set up all observations per epoch and receiver at once selectReceivers platformSelectorType  selectReceivers platformSelectorType  variableReceiver string variable is set for each receiver processingStep gnssProcessingStepType steps are processed consecutively processingStep gnssProcessingStepType steps are processed consecutively selectTransmitters platformSelectorType  disableShadowEpochs boolean disable epochs if satellite is in Earth\\'s/Moon\\'s shadow disablePostShadowRecoveryEpochs boolean disable epochs if satellite is in post-shadow recovery maneuver for GPS block IIA ephemerides ephemeridesType  eclipse eclipseType eclipse model used to determine if a satellite is in Earth\\'s shadow', 'display_text': 'Processing step in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.</p><p>Processing steps enable a dynamic definition of the consecutive steps performed during any kind of GNSS processing. The most common steps are <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>, which performs an iterative least squares adjustment, and <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>, which writes all output files defined in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> and is usually the last step. Some steps such as <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>, <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>, <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">selectNormalsBlockStructure</a>, and <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a> affect all subsequent steps. In case these steps are used within a <a class=\"groops-class\" href=\"gnssProcessingStepType.html#group\">group</a> or <a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">forEachReceiverSeparately</a> step, they only affect the steps within this level.</p><p>For usage examples see cookbooks on <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#processing\">GNSS satellite orbit determination and network analysis</a> or <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a>.  <h2 id=\"estimate\">Estimate</h2><p> Iterative non-linear least squares adjustment. In every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters. The estimated parameters serve as a priori values in the next iteration and the following processing steps. Iterates until either every single parameter update (converted to an influence in meters) is below a <strong class=\"groops-config-element\">convergenceThreshold</strong> or <strong class=\"groops-config-element\">maxIterationCount</strong> is reached.</p><p>With <strong class=\"groops-config-element\">computeResiduals</strong> the observation equations are computed again after each update to compute the observation residuals.</p><p>The overall standard deviation of a single observation used for the weighting is composed of several factors \\\\[   \\\\hat{\\\\sigma}_i = \\\\hat{\\\\sigma}_i^{huber} \\\\hat{\\\\sigma}_{[\\\\tau\\\\nu a]}^{recv} \\\\sigma_{[\\\\tau\\\\nu a]}^{recv}(E,A), \\\\]where $[\\\\tau\\\\nu a]$ is the signal type, the azimuth and elevation dependent $\\\\sigma_{[\\\\tau\\\\nu a]}^{recv}(E,A)$ is given by <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">receiver:inputfileAccuracyDefinition</a> and the other factors are estimated iteratively from the residuals.</p><p>With <strong class=\"groops-config-element\">computeWeights</strong> a standardized variance $\\\\hat{s}_i^2$ for each residual $\\\\hat{\\\\epsilon}_i$ is computed \\\\[   \\\\hat{s}_i^2 = \\\\frac{1}{\\\\hat{\\\\sigma}_{[\\\\tau\\\\nu a]}^{recv} \\\\sigma_{[\\\\tau\\\\nu a]}^{recv}(E,A)}\\\\frac{\\\\hat{\\\\epsilon}_i^2}{r_i}   \\\\qquad\\\\text{with}\\\\qquad   r_i = \\\\left(\\\\M A\\\\left(\\\\M A^T\\\\M A\\\\right)^{-1}\\\\M A^T\\\\right)_{ii} \\\\]taking the redundancy $r_i$ into account. If $\\\\hat{s}_i$ is above a threshold <strong class=\"groops-config-element\">huber</strong> the observation gets a higher standard deviation used for weighting according to \\\\[   \\\\hat{\\\\sigma}_i^{huber} =   \\\\left\\\\{ \\\\begin{array}{ll}     1                              & s < huber,\\\\\\\\     (\\\\hat{s}_i/huber)^{huberPower} & s \\\\ge huber   \\\\end{array} \\\\right., \\\\]similar to <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>With <strong class=\"groops-config-element\">adjustSigma0</strong> individual variance factors can be computed for each station and all phases of a system and each code observation <a class=\"groops-ref\" href=\"gnssType.html\">type</a> (e.g. for each <code>L**G</code>, <code>L**E</code>, <code>C1CG</code>, <code>C2WG</code>, <code>C1CE</code>, ) separately \\\\[   \\\\hat{\\\\sigma}_{[\\\\tau\\\\nu a]}^{recv} = \\\\sqrt{\\\\frac{\\\\hat{\\\\M\\\\epsilon}^T\\\\M P\\\\hat{\\\\M\\\\epsilon}}{r}}. \\\\] <h2 id=\"resolveAmbiguities\">ResolveAmbiguities</h2><p> Performs a least squares adjustment like <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a> but with additional integer phase ambiguity resolution. After this step all resolved ambiguities are removed from the normal equation system. Only ambiguities involving <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a> are resolved. If <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a> is not set, all usable transmitters and/or  receivers are selected for ambiguity resolution.</p><p>Integer ambiguity resolution is performed based on the least squares ambiguity decorrelation adjustment (LAMBDA) method (Teunissen 1995, DOI <a href=\"https://doi.org/10.1007/BF00863419\">10.1007/BF00863419</a>), specifically the modified algorithm (MLAMBDA) by Chang et al. (2005, DOI <a href=\"https://doi.org/10.1007/s00190-005-0004-x\">10.1007/s00190-005-0004-x</a>). First the covariance matrix of the integer ambiguity parameters is computed by eliminating all but those parameters from the full normal equation matrix and inverting it. Then, a Z-transformation is performed as described by Chang et al. (2005) to decorrelate the ambiguity parameters without losing their integer nature.</p><p>The search process follows MLAMBDA and uses integer minimization of the weighted sum of squared residuals. It is computationally infeasible to search a hyper-ellipsoid with a dimension of ten thousand or more. Instead, a blocked search algorithm is performed by moving a window with a length of, for example, <strong class=\"groops-config-element\">searchBlockSize</strong>=<code>200</code> parameters over the decorrelated ambiguities, starting from the most accurate. In each step, the window is moved by half of its length and the overlapping parts are compared to each other. If all fixed ambiguities in the overlap agree, the algorithm continues. Otherwise, both windows are combined and the search is repeated using the combined window, again comparing with the overlapping part of the preceding window. If not all solutions could be checked for a block after <strong class=\"groops-config-element\">maxSearchSteps</strong>, the selected <strong class=\"groops-config-element\">incompleteAction</strong> is performed. If the algorithm reaches ambiguities with a standard deviation higher than <strong class=\"groops-config-element\">sigmaMaxResolve</strong>, ambiguity resolution stops and the remaining ambiguities are left as float values. Otherwise, all ambiguity parameters are fixed to integer values.</p><p>In contrast to an integer least squares solution over the full ambiguity vector, it is not guaranteed that the resulting solution is optimal in the sense of minimal variance with given covariance. This trade-off is necessary to cope with large numbers of ambiguities.  <h2 id=\"computeCovarianceMatrix\">ComputeCovarianceMatrix</h2><p> Accumulates the normal equations and computes the covariance matrix as inverse of the normal matrix. It is not the full inverse but only the elements which are set in the normal matrix (see  <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">gnssProcessingStep:selectNormalsBlockStructure</a>) are computed. The matrix is passed to the <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>. Only used in <a class=\"groops-class\" href=\"gnssParametrizationType.html#kinematicPositions\">parametrizations:kinematicPositions</a> to get the epoch-wise covariance information at the moment.  <h2 id=\"writeResults\">WriteResults</h2><p> In this step all <strong class=\"groops-config-element\">outputfiles</strong> defined in <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a> are written. It considers the settings of <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">processingStep:selectParametrizations</a>, <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">processingStep:selectEpochs</a>, and <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">processingStep:selectReceivers</a>.</p><p>It is usually the last processing step, but can also be used at other points in the processing in combination with <strong class=\"groops-config-element\">suffix</strong> to write intermediate results, for example before <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">gnssProcessingStep:resolveAmbiguities</a> to output the float solution.  <h2 id=\"writeNormalEquations\">WriteNormalEquations</h2><p> Accumulates the normal equations matrix and writes it. If <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a> is set only the selected parameters are written to the normal equations and all other parameters are eliminated beforehand (implicitly solved).</p><p>The solution of the normals would result in $\\\\Delta\\\\M x$ (see <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>). To write the appropriate apriori vector $\\\\M x_0$ use <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeAprioriSolution\">processingStep:writeAprioriSolution</a>.  <h2 id=\"writeAprioriSolution\">WriteAprioriSolution</h2><p> Writes the current apriori vector $\\\\M x_0$ (see <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>). If <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a> is set only the selected parameters are written.  <h2 id=\"writeResiduals\">WriteResiduals</h2><p> Writes the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">observation residuals</a> for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a>. For each station a file is written. The file name is interpreted as a template with the variable <code>{station}</code> being replaced by the station name.  <h2 id=\"writeUsedStationList\">WriteUsedStationList</h2><p> Writes a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of receivers (stations) which are used in the last step and selected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a>.  <h2 id=\"writeUsedTransmitterList\">WriteUsedTransmitterList</h2><p> Writes a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of transmitters which are used in the last step and selected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>.  <h2 id=\"printResidualStatistics\">PrintResidualStatistics</h2><p> Print residual statistics. <pre>   areq: C1CG**: factor =  0.64, sigma0 = 1.00, count =  2748, outliers =    48 (1.75 %)   areq: C1WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    43 (1.56 %)   areq: C2WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    59 (2.15 %)   areq: C5XG**: factor =  0.46, sigma0 = 1.00, count =  1279, outliers =    23 (1.80 %)   areq: L1CG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 %)   areq: L1WG**: factor =  0.86, sigma0 = 1.02, count =  2748, outliers =    40 (1.46 %)   areq: L2WG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 %)   areq: L5XG**: factor =  0.86, sigma0 = 1.30, count =  1279, outliers =    14 (1.09 %)   areq: C1PR**: factor =  0.48, sigma0 = 1.00, count =  1713, outliers =    53 (3.09 %)   areq: C2PR**: factor =  0.55, sigma0 = 1.00, count =  1713, outliers =    51 (2.98 %)   areq: L1PR**: factor =  0.85, sigma0 = 1.09, count =  1713, outliers =    29 (1.69 %)   areq: L2PR**: factor =  0.85, sigma0 = 0.88, count =  1713, outliers =    29 (1.69 %)   areq: C1XE**: factor =  0.44, sigma0 = 1.00, count =  1264, outliers =    21 (1.66 %)   areq: C5XE**: factor =  0.33, sigma0 = 1.00, count =  1264, outliers =    27 (2.14 %)   areq: C7XE**: factor =  0.28, sigma0 = 1.00, count =  1264, outliers =    41 (3.24 %)   areq: L1XE**: factor =  0.82, sigma0 = 1.14, count =  1264, outliers =    15 (1.19 %)   areq: L5XE**: factor =  0.82, sigma0 = 0.84, count =  1264, outliers =    15 (1.19 %)   areq: L7XE**: factor =  0.82, sigma0 = 0.94, count =  1264, outliers =    15 (1.19 %)   badg: C1CG**: factor =  1.25, sigma0 = 1.00, count =  2564, outliers =    47 (1.83 %)   ... </pre>  <h2 id=\"selectParametrizations\">SelectParametrizations</h2><p> Enable/disable parameter groups and constraint groups for subsequent steps, e.g. <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a> or <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">processingStep:writeResults</a>. The <strong class=\"groops-config-element\">name</strong> and <strong class=\"groops-config-element\">nameConstraint</strong> of these groups are defined in <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>. Prior models or previously estimated parameters used as new apriori $\\\\M x_0$ values are unaffected and they are always reduced from the observations. This means all unselected parameters are kept fixed to their last result.</p><p>An example would be to process at a 5-minute sampling using <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">processingStep:selectEpochs</a> and then at the end to densify the clock parameters to the full 30-second observation sampling while keeping all other parameters fixed (<strong class=\"groops-config-element\">disable</strong>=<code>*</code>, <strong class=\"groops-config-element\">enable</strong>=<code>*.clock*</code>, <strong class=\"groops-config-element\">enable</strong>=<code>parameter.STEC</code>).  <h2 id=\"selectEpochs\">SelectEpochs</h2><p> Select epochs for subsequent steps. This step can be used to reduce the processing sampling while keeping the original observation sampling for all preprocessing steps (e.g. outlier and cycle slip detection). Another example is to process at a 5-minute sampling by setting <strong class=\"groops-config-element\">nthEpoch</strong>=<code>10</code> and then at the end to densify only the clock parameters to the full 30-second observation sampling by setting <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> while keeping all other parameters fixed with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">processingStep:selectParametrizations</a>.  <h2 id=\"selectNormalsBlockStructure\">SelectNormalsBlockStructure</h2><p> Select block structure of sparse normal equations for subsequent steps.</p><p>This step can be used to define the structure of the different parts of the normal equation system, which can have a major impact on computing performance and memory consumption depending on the processing setup.</p><p></p><p>The normal equation system is divided into three parts for epoch, interval, and ambiguity parameters. The epoch part is subdivided further into one subpart per epoch. Each part is divided into blocks and only non-zero blocks are stored in memory to reduce memory consumption and to prevent unnecessary matrix computations. <strong class=\"groops-config-element\">defaultBlockSizeEpoch</strong>, <strong class=\"groops-config-element\">defaultBlockSizeInterval</strong>, and <strong class=\"groops-config-element\">defaultBlockSizeAmbiguity</strong> control the size of the blocks within each part of the normal equations. <strong class=\"groops-config-element\">defaultBlockReceiverCount</strong> can be set to group a number of receivers into one block within the epoch and interval parts.</p><p>If <strong class=\"groops-config-element\">keepEpochNormalsInMemory</strong>=<code>no</code> epoch blocks are eliminated after they are set up to reduce the number of parameters in the normal equation system. <strong class=\"groops-config-element\">defaultBlockCountReduction</strong> controls after how many epoch blocks an elimination step is performed. For larger processing setups or high sampling rates epoch block elimination is recommended as the large number of clock parameters require a lot of memory.  <h2 id=\"selectReceivers\">SelectReceivers</h2><p> This step can be used to process only a subset of stations in subsequent processing steps. The most common use is to start the processing with a well-distributed network of core stations as seen in <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#processing\">GNSS satellite orbit determination and network analysis</a>. To later process all other stations individually, use the processing step <a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">processingStep:forEachReceiverSeparately</a> and select all stations excluding the core stations in that step.  <h2 id=\"forEachReceiverSeparately\">ForEachReceiverSeparately</h2><p> Perform these processing steps for each <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a> separately. All non-receiver-related parameters parameters are disabled in these processing steps.</p><p>This step can be used for individual precise point positioning (PPP) of all stations. During <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#processing\">GNSS satellite orbit determination and network analysis</a> this step is used after the initial processing of the core network to process all other stations individually. In that case provide the same station list as <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileExcludeStationList</a> in this step that was used as <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileStationList</a> in the <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a> step where the core network was selected.  <h2 id=\"group\">Group</h2><p> Perform these processing steps. This step can be used to structure complex processing flows. The <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingStep</a>s that affect the following steps (those beginning with Select) only have an effect until the end of the group.  <h2 id=\"disableTransmitterShadowEpochs\">DisableTransmitterShadowEpochs</h2><p> Disable transmitter epochs during eclipse. With proper attitude modeling (see <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>) this is usually not necessary.'},\n'gnssReceiverGeneratorType': { 'name': 'gnssReceiverGeneratorType', 'key': 'gnssReceiverGeneratorType', 'description': 'Definition and basic information of GNSS receivers. Most of the input files are provided in GROOPS file formats at  https://ftp.tugraz.at/pub/ITSG/groops  (marked with  *  below). These files are regularly updated.        * :         Antenna and receiver information, antenna reference point offsets, antenna orientations.         Created via  GnssStationLog2Platform  or  PlatformCreate .      * :         Antenna center offsets and variations.         Created via  GnssAntex2AntennaDefinition  or  GnssAntennaDefinitionCreate .      :         Observed signal types (optional).         Created via  GnssReceiverDefinitionCreate  in case you want to define which signal         types a receiver model can observe.      * :         Elevation and azimuth dependent accuracy.         Created via  GnssAntennaDefinitionCreate .      :         Converted from RINEX observation files via  RinexObservation2GnssReceiver .  It is possible to limit the observation types to be used in the processing by a list of     and any observation types not defined within the list are ignored and discarded. Similarly observations defined in the list of     are ignored and discarded. The codes used follow the  . Each receiver goes through a  preprocessing  step individually, where observation outliers are removed or downweighted, continuous tracks of phase observations are defined for ambiguity parametrization, cycle slips are detected, and receivers are disabled if they do not fulfill certain requirements. The preprocessing step consists of an initial PPP estimation done by  robust least squares adjustment  and checks whether the position error of the solutions exceeds  codeMaxPositionDiff . If the error exceeds the threshold the receiver will be discarded. The preprocessing also sets initial clock error values and removes tracks that stay below a certain elevation mask ( elevationTrackMinimum ). See also  GnssProcessing  and  GnssSimulateReceiver .     A network of GNSS ground stations is defined via    . Each line can contain more than one station. The first station in each line for which     exists and contains enough observations is used for the processing. All input files except    ,    , and     are read for each station. The file name is interpreted as a template with the variable  {station}  being replaced by the station name. The effects of loading and tidal deformation on station positions can be corrected for via     and    , respectively. Tidal deformations typically include:        : Earth tidal deformations (IERS conventions)      : ocean tidal deformations         (e.g. fes2014b n720,  minDegree = 1 )      : atmospheric tidal deformation         (e.g. AOD1B RL06,  minDegree = 1 )      : pole tidal deformations (IERS conventions)      : ocean pole tidal deformations (IERS conventions)      A single low-Earth orbiting (LEO) satellite with an onboard GNSS receiver. An apriori orbit is needed as    . Attitude data must be provided via    . If no attitude data is available from the satellite operator, the star camera data can be simulated by using  SimulateStarCamera .', 'config_table': 'inputfileStationList filename ascii file with station names maxStationCount uint maximum number of stations to be used inputfileStationInfo filename variable {station} available. station metadata (antennas, receivers, ...) inputfileAntennaDefinition filename antenna center offsets and variations noAntennaPatternFound choice what should happen if no antenna pattern is found for an observation ignoreObservation  ignore observation if no matching pattern is found useNearestFrequency  use pattern of nearest frequency if no matching pattern is found throwException  throw exception if no matching pattern is found inputfileReceiverDefinition filename observed signal types inputfileAccuracyDefinition filename elevation and azimuth dependent accuracy inputfileStationPosition filename variable {station} available. disableStationWithoutPosition boolean drop stations without apriori position inputfileClock filename variable {station} available inputfileObservations filename variable {station} available loadingDisplacement gravityfieldType loading deformation tidalDisplacement tidesType tidal deformation ephemerides ephemeridesType for tidal deformation inputfileDeformationLoadLoveNumber filename  inputfilePotentialLoadLoveNumber filename if full potential is given and not only loading potential useType gnssType only use observations that match any of these patterns ignoreType gnssType ignore observations that match any of these patterns elevationCutOff angle [degree] ignore observations below cutoff elevationTrackMinimum angle [degree] ignore tracks that never exceed minimum elevation minObsCountPerTrack uint tracks with less number of epochs with observations are dropped minEstimableEpochsRatio double [0,1] drop stations with lower ratio of estimable epochs to total epochs preprocessing sequence settings for preprocessing of observations/stations printStatistics boolean print preprocesssing statistics for all receivers huber double residuals > huber*sigma0 are downweighted huberPower double residuals > huber: sigma=(e/huber)^huberPower*sigma0 codeMaxPositionDiff double [m] max. allowed position error by PPP code only clock error estimation denoisingLambda double regularization parameter for total variation denoising used in cylce slip detection tecWindowSize uint (0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection tecSigmaFactor double factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection outputfileTrackBefore filename variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection outputfileTrackAfter filename variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection inputfileStationInfo filename satellite metadata (antenna, receiver, ...) inputfileAntennaDefinition filename antenna center offsets and variations noAntennaPatternFound choice what should happen if no antenna pattern is found for an observation ignoreObservation  ignore observation if no matching pattern is found useNearestFrequency  use pattern of nearest frequency if no matching pattern is found throwException  throw exception if no matching pattern is found inputfileReceiverDefinition filename observed signal types inputfileAccuracyDefinition filename elevation and azimut dependent accuracy inputfileObservations filename  inputfileOrbit filename approximate positions inputfileStarCamera filename satellite attitude sigmaFactorPhase expression PHASE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX) sigmaFactorCode expression CODE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX) supportsIntegerAmbiguities boolean receiver tracks full cycle integer ambiguities wavelengthFactor double factor to account for half-wavelength observations (collected by codeless squaring techniques) useType gnssType only use observations that match any of these patterns ignoreType gnssType ignore observations that match any of these patterns elevationCutOff angle [degree] ignore observations below cutoff minObsCountPerTrack uint tracks with less number of epochs with observations are dropped preprocessing sequence settings for preprocessing of observations/stations printStatistics boolean print preprocesssing statistics for all receivers huber double residuals > huber*sigma0 are downweighted huberPower double residuals > huber: sigma=(e/huber)^huberPower*sigma0 codeMaxPositionDiff double [m] max. allowed position error by PPP code only clock error estimation denoisingLambda double regularization parameter for total variation denoising used in cylce slip detection tecWindowSize uint (0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection tecSigmaFactor double factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection outputfileTrackBefore filename variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection outputfileTrackAfter filename variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection', 'display_text': 'Definition and basic information of GNSS receivers.</p><p>Most of the input files are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (marked with <b>*</b> below). These files are regularly updated. <ul>    <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a><b>*</b>:         Antenna and receiver information, antenna reference point offsets, antenna orientations.         Created via <a class=\"groops-program\" href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a> or <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a><b>*</b>:         Antenna center offsets and variations.         Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a>:         Observed signal types (optional).         Created via <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a> in case you want to define which signal         types a receiver model can observe.   </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a><b>*</b>:         Elevation and azimuth dependent accuracy.         Created via <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservation</a>:         Converted from RINEX observation files via <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>. </li></ul> </p><p>It is possible to limit the observation types to be used in the processing by a list of <a class=\"groops-class\" href=\"gnssType.html\">useType</a> and any observation types not defined within the list are ignored and discarded. Similarly observations defined in the list of <a class=\"groops-class\" href=\"gnssType.html\">ignoreType</a> are ignored and discarded. The codes used follow the <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>.</p><p>Each receiver goes through a <strong class=\"groops-config-element\">preprocessing</strong> step individually, where observation outliers are removed or downweighted, continuous tracks of phase observations are defined for ambiguity parametrization, cycle slips are detected, and receivers are disabled if they do not fulfill certain requirements. The preprocessing step consists of an initial PPP estimation done by <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a> and checks whether the position error of the solutions exceeds <strong class=\"groops-config-element\">codeMaxPositionDiff</strong>. If the error exceeds the threshold the receiver will be discarded. The preprocessing also sets initial clock error values and removes tracks that stay below a certain elevation mask (<strong class=\"groops-config-element\">elevationTrackMinimum</strong>).</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> and <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>.  <h2 id=\"stationNetwork\">StationNetwork</h2><p> A network of GNSS ground stations is defined via <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStationList</a>. Each line can contain more than one station. The first station in each line for which <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a> exists and contains enough observations is used for the processing. All input files except <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>, <a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a>, and <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> are read for each station. The file name is interpreted as a template with the variable <code>{station}</code> being replaced by the station name.</p><p>The effects of loading and tidal deformation on station positions can be corrected for via <a class=\"groops-class\" href=\"gravityfieldType.html\">loadingDisplacement</a> and <a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>, respectively. Tidal deformations typically include: <ul>    <li><a class=\"groops-class\" href=\"tidesType.html#earthTide\">earthTide</a>: Earth tidal deformations (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: ocean tidal deformations         (e.g. fes2014b_n720, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: atmospheric tidal deformation         (e.g. AOD1B RL06, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#poleTide\">poleTide</a>: pole tidal deformations (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">poleOceanTide</a>: ocean pole tidal deformations (IERS conventions) </li></ul> </p><p> <h2 id=\"lowEarthOrbiter\">LowEarthOrbiter</h2><p> A single low-Earth orbiting (LEO) satellite with an onboard GNSS receiver. An apriori orbit is needed as <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. Attitude data must be provided via <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>. If no attitude data is available from the satellite operator, the star camera data can be simulated by using <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a>.'},\n'gnssTransmitterGeneratorType': { 'name': 'gnssTransmitterGeneratorType', 'key': 'gnssTransmitterGeneratorType', 'description': 'Definition and basic information of GNSS transmitters. See also  GnssProcessing  and  GnssSimulateReceiver .     A list of satellite PRNs (i.e for GPS: G01, G02, G03, ...) must be provided via    . Satellite system codes follow the  , see  GnssType . All input files except    , and     are read for each satellite. The file name is interpreted as a template with the variable  {prn}  being replaced by the satellite PRN. Metadata input files (marked with  *  below) are provided in GROOPS file formats at  https://ftp.tugraz.at/pub/ITSG/groops . These files are regularly updated.        * :         PRN-SVN mapping, antenna offsets and orientations.         Created via  GnssAntex2AntennaDefinition  or  PlatformCreate .      * :         Antenna center variations.         Created via  GnssAntex2AntennaDefinition  or  GnssAntennaDefinitionCreate .      * :         Transmitted signal types.         Created via  GnssReceiverDefinitionCreate  in case you want to define which signal         types a satellite transmits.      * :         Scale factor of transmitted signals due to frequency offset/clock drift.         Can be dreived from broadcast clocks drifts.      : Converted via  Sp3Format2Orbit  or         output of  GnssProcessing .      :         Rotation from body frame to CRF. Created via  SimulateStarCameraGnss  or converted via  GnssOrbex2StarCamera .      :         Converted via  GnssClockRinex2InstrumentClock  or  GnssRinexNavigation2OrbitClock  or         output of  GnssProcessing .', 'config_table': 'inputfileTransmitterList filename ascii file with transmitter PRNs, used to loop variable {prn} inputfileTransmitterInfo filename variable {prn} available inputfileAntennaDefintion filename phase centers and variations (ANTEX like) noAntennaPatternFound choice what should happen is no antenna pattern is found for an observation ignoreObservation  ignore observation if no matching pattern is found useNearestFrequency  use pattern of nearest frequency if no matching pattern is found throwException  throw exception if no matching pattern is found inputfileSignalDefintion filename transmitted signal types inputfileClockFrequencyScale filename variable {prn} available inputfileOrbit filename variable {prn} available inputfileAttitude filename variable {prn} available inputfileClock filename variable {prn} available interpolateClock boolean linear interpolation of missing epochs interpolationDegree uint for orbit interpolation and velocity calculation', 'display_text': 'Definition and basic information of GNSS transmitters.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> and <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>.  <h2 id=\"gnss\">GNSS</h2><p> A list of satellite PRNs (i.e for GPS: G01, G02, G03, ...) must be provided via <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileTransmitterList</a>. Satellite system codes follow the <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>, see <a class=\"groops-ref\" href=\"gnssType.html\">GnssType</a>. All input files except <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>, and <a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a> are read for each satellite. The file name is interpreted as a template with the variable <code>{prn}</code> being replaced by the satellite PRN.</p><p>Metadata input files (marked with <b>*</b> below) are provided in GROOPS file formats at <a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>. These files are regularly updated. <ul>    <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a><b>*</b>:         PRN-SVN mapping, antenna offsets and orientations.         Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a><b>*</b>:         Antenna center variations.         Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileSignalDefintion</a><b>*</b>:         Transmitted signal types.         Created via <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a> in case you want to define which signal         types a satellite transmits.   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClockFrequencyScale</a><b>*</b>:         Scale factor of transmitted signals due to frequency offset/clock drift.         Can be dreived from broadcast clocks drifts.   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: Converted via <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a> or         output of <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a>:         Rotation from body frame to CRF. Created via <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> or converted via <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>.   </li><li> <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a>:         Converted via <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a> or <a class=\"groops-program\" href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a> or         output of <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>. </li></ul>'},\n'gnssType': { 'name': 'gnssType', 'key': 'gnssType', 'description': 'A GnssType string consists of six parts (type, frequency, attribute, system, PRN, frequency number) represented by seven characters.    The first three characters (representing type, frequency, and attribute) correspond to the observation codes of the        .  The satellite system character also follows the RINEX 3 definition:                  G  = GPS          R  = GLONASS          E  = Galileo          C  = BeiDou          S  = SBAS          J  = QZSS          I  = IRNSS          PRN is a two-digit number identifying a satellite.  Frequency number is only used for GLONASS, where the range -7 to 14 is represented by letters starting with A.  Each part of a GnssType string can be replaced by a wildcard \\' * \\', enabling the use of these strings as patterns, for example to select a subset of observations (e.g.  C**G**  matches all GPS code/range observations). Trailing wildcards are optional, meaning  L1*R  is automatically expanded to  L1*R*** . For some RINEX 2 types (e.g. Galileo L5) the RINEX 3 attribute is unknown/undefined and can be replaced by  ? , for example  L5?E01 . Examples:    C1CG23  = code/range observation, L1 frequency, derived from C/A code, GPS, PRN 23  L2PR05B  = phase observation, G2 frequency, derived from P code, GLONASS, PRN 05, frequency number -6  *5*E**  = all observation types, E5a frequency, all attributes, Galileo, all PRNs', 'config_table': '', 'display_text': 'A GnssType string consists of six parts (type, frequency, attribute, system, PRN, frequency number) represented by seven characters. <ul>  <li>The first three characters (representing type, frequency, and attribute) correspond to the observation codes of the       <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>. </li><li> The satellite system character also follows the RINEX 3 definition:       <ul>          </li><li> <code>G</code> = GPS         </li><li> <code>R</code> = GLONASS         </li><li> <code>E</code> = Galileo         </li><li> <code>C</code> = BeiDou         </li><li> <code>S</code> = SBAS         </li><li> <code>J</code> = QZSS         </li><li> <code>I</code> = IRNSS       </li></ul>  <li>PRN is a two-digit number identifying a satellite. </li><li> Frequency number is only used for GLONASS, where the range -7 to 14 is represented by letters starting with A. </li></ul> </p><p>Each part of a GnssType string can be replaced by a wildcard \\'<code>*</code>\\', enabling the use of these strings as patterns, for example to select a subset of observations (e.g. <code>C**G**</code> matches all GPS code/range observations). Trailing wildcards are optional, meaning <code>L1*R</code> is automatically expanded to <code>L1*R***</code>. For some RINEX 2 types (e.g. Galileo L5) the RINEX 3 attribute is unknown/undefined and can be replaced by <code>?</code>, for example <code>L5?E01</code>.</p><p>Examples: <ul>  <li><code>C1CG23</code> = code/range observation, L1 frequency, derived from C/A code, GPS, PRN 23 </li><li> <code>L2PR05B</code> = phase observation, G2 frequency, derived from P code, GLONASS, PRN 05, frequency number -6 </li><li> <code>*5*E**</code> = all observation types, E5a frequency, all attributes, Galileo, all PRNs </li></ul>'},\n'gravityfieldType': { 'name': 'gravityfieldType', 'key': 'gravityfieldType', 'description': 'This class computes functionals of the time depending gravity field, e.g potential, gravity anomalies or gravity gradients. If several instances of the class are given the results are summed up. Before summation every single result is multiplicated by a  factor . To subtract a normal field like GRS80 from a potential to get the disturbance potential you must choose one factor by 1 and the other by -1. To get the mean of two fields just set each factor to 0.5. Some of the instances gives also information about the accuracy. The variance of the result (sum) is computed by means of variance propagation.     Reads coefficients of a spherical harmonics expansion from file. The potential is given by  If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The computed result is multiplied with  factor . If  setSigmasToZero  is true the variances are set to zero. This option is only important for variance propagation and does not change the result of the gravity field functionals.     Reads coefficients of a spherical harmonics expansion (for inner space) from file. If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. The computed result is multiplied with  factor . If  setSigmasToZero  is true the variances are set to zero. This option is only important for error propagation and does not change the result of the gravity field functionals.     Reads a solution vector from file     which may be computed by a least squares adjustment (e.g. by  NormalsSolverVCE ). The coefficients of the vector are interpreted from position  indexStart  (counting from zero) with help of    . If the solution file contains solution of several right hand sides you can choose one with number  rightSide  (counting from zero). You can also read a vector from file     containing the accuracies of the coefficients. The computed result is multiplied with  factor .     Read a time variable gravity field from file     represented by a spherical harmonics expansion in the spatial domain and spline functions in the time domain. If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. This file can be created for example by  Gravityfield2TimeSplines  or  PotentialCoefficients2BlockMeanTimeSplines . The computed result is multiplied with  factor .     The given     is interpreted as trend function and the result is computed at time   as follows  with   is  timeStart  and   is  timeStep .     The given     is interpreted as oscillation function and the result is computed at time   as follows  with  .     A     is only evaluated in the interval between  timeStart  inclusively and  timeEnd  exclusively. Outside the interval the result is zero. This class is useful to get a time series of monthly mean GRACE gravity field solutions. In each month another file of potentialCoefficients is valid. This can easily be created with    .     Treat     as gravitational forces. The tides need a realization of     to transform between the CRF and TRF and to compute rotational deformation from polar motion. It also needs     from Sun, moon, and planets.     The gravity is integrated from a topographic mass distribution. For each grid point in     a prisma with  density  is assumed. The horizontal extension is computed from the grid spacing and the vertical extension is given by  radialLowerBound  and  radialUpperBound  above ellipsoid. All values are expressions and computed for each point with given data in the grid file. The standard variables for grids are available, see  dataVariables . Example: The grid file contains the orthometric height of the topography in the first column, the geoid height in the second and the mean density of each prism in the third column. In this case the following settings should be used:    radialUpperBound  =  data0+data1 ,  radialLowerBound  =  data1 ,  density  =  data2 .  As the prim computation is time consuming a maximum distance around the evaluation point can defined with  distancePrism . Afterwards a simplified radial line (the prism mass is concentrated to a line in the center) is used up to a distance of  distanceLine . At last the prim is approximated by a point mass in the center up to a distance  distanceMax  (if set). Prisms nearby the evaluation point can be excluded with  distanceMin .     The given     is interpreted as an oscillation function in the gravitational potential field, caused by large earthquakes. The result is computed at time   as follows:  with  . In this equation,   is the attenuation factor,   is the overtone factor,   is degree,   is order, and   is time in second.   and   are computed with the elastic Earth model or observed from the long period record of superconducting gravimeter measurements after the earthquakes.     Convert     to spherical harmonics and     the coefficients.     Groups a set of     and has no further effect itself.', 'config_table': 'inputfilePotentialCoefficients filename  minDegree uint  maxDegree uint  factor double the result is multiplied by this factor, set -1 to subtract the field setSigmasToZero boolean set variances to zero, should be used by adding back reference fields inputfilePotentialCoefficients filename  minDegree uint  maxDegree uint  factor double the result is multiplied by this factor, set -1 to subtract the field setSigmasToZero boolean set variances to zero, should be used by adding back reference fields parametrization parametrizationGravityType  inputfileSolution filename solution vector inputfileSigmax filename standards deviations or covariance matrix of the solution indexStart uint position in the solution vector rightSide uint if solution contains several right hand sides, select one factor double the result is multiplied by this factor, set -1 to subtract the field inputfileTimeSplinesGravityfield filename  inputfileTimeSplinesCovariance filename  minDegree uint  maxDegree uint  factor double the result is multiplied by this factor, set -1 to subtract the field gravityfield gravityfieldType this field is multiplicated by (time-time0)/timeStep timeStart time reference time timeStep time  gravityfieldCos gravityfieldType multiplicated by cos(2pi/T(time-time0)) gravityfieldSin gravityfieldType multiplicated by sin(2pi/T(time-time0)) time0 time reference time period time [day] gravityfield gravityfieldType  timeStart time first point in time timeEnd time last point in time will be less or equal timeEnd tides tidesType  earthRotation earthRotationType  ephemerides ephemeridesType  inputfileGridRectangular filename Digital Terrain Model density expression expression [kg/m**3] radialUpperBound expression expression (variables \\'height\\', \\'data\\', \\'L\\', \\'B\\' and, \\'area\\' are taken from the gridded data radialLowerBound expression expression (variables \\'height\\', \\'data\\', \\'L\\', \\'B\\' and, \\'area\\' are taken from the gridded data distanceMin double [km] min. influence distance (ignore near zone) distancePrism double [km] max. distance for prism formular distanceLine double [km] max. distance for radial integration distanceMax double [km] max. influence distance (ignore far zone) factor double the result is multiplied by this factor, set -1 to subtract the field inputCoefficientMatrix filename oscillation model parameters time0 time the time earthquake happened minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius gravityfield gravityfieldType  filter sphericalHarmonicsFilterType  gravityfield gravityfieldType  factor double the result is multiplied by this factor, set -1 to subtract the field', 'display_text': 'This class computes functionals of the time depending gravity field, e.g potential, gravity anomalies or gravity gradients.</p><p>If several instances of the class are given the results are summed up. Before summation every single result is multiplicated by a <strong class=\"groops-config-element\">factor</strong>. To subtract a normal field like GRS80 from a potential to get the disturbance potential you must choose one factor by 1 and the other by -1. To get the mean of two fields just set each factor to 0.5.</p><p>Some of the instances gives also information about the accuracy. The variance of the result (sum) is computed by means of variance propagation.  <h2 id=\"potentialCoefficients\">PotentialCoefficients</h2><p> Reads coefficients of a spherical harmonics expansion from file. The potential is given by \\\\[ V(\\\\lambda,\\\\vartheta,r) = \\\\frac{GM}{R}\\\\sum_{n=0}^\\\\infty \\\\sum_{m=0}^n \\\\left(\\\\frac{R}{r}\\\\right)^{n+1}   \\\\left(c_{nm} C_{nm}(\\\\lambda,\\\\vartheta) + s_{nm} S_{nm}(\\\\lambda,\\\\vartheta)\\\\right). \\\\]If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>. If <strong class=\"groops-config-element\">setSigmasToZero</strong> is true the variances are set to zero. This option is only important for variance propagation and does not change the result of the gravity field functionals.  <h2>PotentialCoefficientsInterior</h2><p> Reads coefficients of a spherical harmonics expansion (for inner space) from file. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>. If <strong class=\"groops-config-element\">setSigmasToZero</strong> is true the variances are set to zero. This option is only important for error propagation and does not change the result of the gravity field functionals.  <h2 id=\"fromParametrization\">FromParametrization</h2><p> Reads a solution vector from file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a> which may be computed by a least squares adjustment (e.g. by <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>). The coefficients of the vector are interpreted from position <strong class=\"groops-config-element\">indexStart</strong> (counting from zero) with help of <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>. If the solution file contains solution of several right hand sides you can choose one with number <strong class=\"groops-config-element\">rightSide</strong> (counting from zero). You can also read a vector from file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmax</a> containing the accuracies of the coefficients.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"timeSplines\">TimeSplines</h2><p> Read a time variable gravity field from file <a class=\"groops-class\" href=\"fileFormat_timeSplinesGravityField.html\">inputfileTimeSplinesGravityfield</a> represented by a spherical harmonics expansion in the spatial domain and spline functions in the time domain. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.</p><p>This file can be created for example by <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a> or <a class=\"groops-program\" href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a>.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"trend\">Trend</h2><p> The given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is interpreted as trend function and the result is computed at time $t$ as follows \\\\[ V(\\\\M x,t) = \\\\frac{t-t_0}{\\\\Delta t}V(\\\\M x), \\\\]with $t_0$ is <strong class=\"groops-config-element\">timeStart</strong> and $\\\\Delta t$ is <strong class=\"groops-config-element\">timeStep</strong>.  <h2 id=\"oscillation\">Oscillation</h2><p> The given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is interpreted as oscillation function and the result is computed at time $t$ as follows \\\\[ V(\\\\M x,t) = \\\\cos(\\\\omega)V_{cos}(\\\\M x)+\\\\sin(\\\\omega)V_{sin}(\\\\M x), \\\\]with $\\\\omega=\\\\frac{2\\\\pi}{T}(t-t_0)$.  <h2>InInterval</h2><p> A <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is only evaluated in the interval between <strong class=\"groops-config-element\">timeStart</strong> inclusively and <strong class=\"groops-config-element\">timeEnd</strong> exclusively. Outside the interval the result is zero.</p><p>This class is useful to get a time series of monthly mean GRACE gravity field solutions. In each month another file of potentialCoefficients is valid. This can easily be created with <a class=\"groops-class\" href=\"loopType.html\">loop</a>.  <h2 id=\"tides\">Tides</h2><p> Treat <a class=\"groops-class\" href=\"tidesType.html\">tides</a> as gravitational forces. The tides need a realization of <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> to transform between the CRF and TRF and to compute rotational deformation from polar motion. It also needs <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a> from Sun, moon, and planets.  <h2 id=\"topography\">Topography</h2><p> The gravity is integrated from a topographic mass distribution. For each grid point in <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGridRectangular</a> a prisma with <strong class=\"groops-config-element\">density</strong> is assumed. The horizontal extension is computed from the grid spacing and the vertical extension is given by <strong class=\"groops-config-element\">radialLowerBound</strong> and <strong class=\"groops-config-element\">radialUpperBound</strong> above ellipsoid. All values are expressions and computed for each point with given data in the grid file. The standard variables for grids are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>Example: The grid file contains the orthometric height of the topography in the first column, the geoid height in the second and the mean density of each prism in the third column. In this case the following settings should be used: <ul>  <li><strong class=\"groops-config-element\">radialUpperBound</strong> = <code>data0+data1</code>, </li><li> <strong class=\"groops-config-element\">radialLowerBound</strong> = <code>data1</code>, </li><li> <strong class=\"groops-config-element\">density</strong> = <code>data2</code>. </li></ul> </p><p>As the prim computation is time consuming a maximum distance around the evaluation point can defined with <strong class=\"groops-config-element\">distancePrism</strong>. Afterwards a simplified radial line (the prism mass is concentrated to a line in the center) is used up to a distance of <strong class=\"groops-config-element\">distanceLine</strong>. At last the prim is approximated by a point mass in the center up to a distance <strong class=\"groops-config-element\">distanceMax</strong> (if set). Prisms nearby the evaluation point can be excluded with <strong class=\"groops-config-element\">distanceMin</strong>.  <h2>EarthquakeOscillation</h2><p> The given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is interpreted as an oscillation function in the gravitational potential field, caused by large earthquakes. The result is computed at time $t$ as follows: \\\\[ C_{lm}(\\\\M t) = \\\\sum_{n=0}^NC_{nlm}(1-\\\\cos(\\\\omega)\\\\exp(\\\\frac{-\\\\omega}{2Q_{nlm}})), \\\\]with $\\\\omega=\\\\frac{2\\\\pi}{T_{nlm}}(t-t_0)$. In this equation, $Q_{nlm}$ is the attenuation factor, $n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time in second. $T_{nlm}$ and $Q_{nlm}$ are computed with the elastic Earth model or observed from the long period record of superconducting gravimeter measurements after the earthquakes.  <h2>Filter</h2><p> Convert <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> to spherical harmonics and <a class=\"groops-class\" href=\"sphericalHarmonicsFilterType.html\">filter</a> the coefficients.  <h2 id=\"group\">Group</h2><p> Groups a set of <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and has no further effect itself.'},\n'gridType': { 'name': 'gridType', 'key': 'gridType', 'description': 'This class generates a set of grid points. In a first step, the grid is always generated globally, with     a regional subset of points can be extracted from the global grid. The parameters  R  and  inverseFlattening  define the shape of the ellipsoid on which the grid is generated. In case  inverseFlattening  is chosen as zero, a sphere is used. With  height  the distance of the points above the ellipsoid can be defined. In addition to the location of the points, weights are assigned to each of the points. These weights can be regarded as the surface element associated with each grid point.     The geographical grid is an equal-angular point distribution with points located along meridians and along circles of latitude.  deltaLambda  denotes the angular difference between adjacent points along meridians and  deltaPhi  describes the angular difference between adjacent points along circles of latitude. The point setting results as follows:  The number of grid points can be determined by  The weights are calculated according to      The zeroth level of densification coincides with the 12 icosahedron vertices, as displayed in the upper left part of Fig.  . Then, depending on the envisaged densification, each triangle edge is divided into   parts, illustrated in the upper right part of Fig.  . The new nodes on the edges are then connected by arcs of great circles parallel to the triangle edges. The intersections of each three corresponding parallel lines become nodes of the densified grid as well. As in case of a spherical triangle those three connecting lines do not exactly intersect in one point, the center of the resulting triangle is used as location for the new node (lower left part of Fig.  ). The lower right side of Fig.   finally shows the densified triangle vertex grid for a level of  . The number of grid points in dependence of the chosen level of densification can be calculated by         The points of the zeroth level are located at the centers of the icosahedron triangles. To achieve a finer grid, each of the triangles is divided into four smaller triangles by connecting the midpoints of the triangle edges. The refined grid points are again located at the center of the triangles. Subsequently, the triangles can be further densified up to the desired level of densification  , which is defined by  level . The number of global grid points for a certain level can be determined by  Thus the quantity of grid points depends exponentially on the level  , as with every additional level the number of grid points quadruplicates.      The grid features equiangular spacing along circles of latitude with   parallelsCount  defining the number   of the parallels.  Along the meridians the points are located at   parallels at the   zeros   of the Legendre polynomial of degree  ,  Consequently, the number of grid points sums up to  The weights can be calculated according to      The Reuter grid features equi-distant spacing along the meridians determined by the control parameter   according to  Thus   denotes the number of points per meridian, as the two poles are included in the point distribution as well. Along the circles of latitude, the number of grid points decreases with increasing latitude in order to achieve an evenly distributed point pattern. This number is chosen, so that the points along each circle of latitude have the same spherical distance as two adjacent latitudes. The resulting relationship is given by  The left hand side of this equation is the spherical distance between adjacent latitudes, the right hand side stands for the spherical distance between two points with the same polar distance   and a longitudinal difference of  . This longitudinal distance can be adjusted depending on   to fulfill Eq.  . The resulting formula for   is  The number of points   for each circle of latitude can then be determined by  Here the Gauss bracket   specifies the largest integer equal to or less than  . The longitudes are subsequently determined by  The number of grid points can be estimated by  The   results from the fact that the   are restricted to integer values.     This kind of grid distributes an arbitrarily chosen number of   points (defined by  globalPointsCount ) following a recursive, quasi random sequence. In longitudinal direction the pattern follows  This implies that every grid point features a unique longitude, with equi-angular longitudinal differences. The polar distance in the form   for each point is determined by the following recursive sequence:    Starting from an interval  .  If  , then the midpoint of the interval is returned as result of the sequence, and the sequence is terminated.  If the number of points is uneven, the  midpoint is included into the list of  .  Subsequently, the interval is bisected into an upper and lower half,        and the sequence is called for both halves.   from upper and lower half are alternately sorted into the list of  .  The polar distances are calculated by       The Driscoll-Healy grid, has equiangular spacing along the meridians as well as along the circles of latitude. In longitudinal direction (along the parallels), these angular differences for a given  dimension    coincide with those described for the corresponding geographical grid and Gauss grid. Along the meridians, the size of the latitudinal differences is half the size compared to the geographical grid. This results in the following point pattern,  Consequently, the number of grid points is  The weights are given by      Creates one single point.     Creates one single point.     In this class grid is read from a file, which is given by    . A corresponding file can be generated with  GriddedDataCreate  or with  Matrix2GriddedData .', 'config_table': 'deltaLambda angle  deltaPhi angle  height double ellipsoidal height expression (variables \\'height\\', \\'L\\', \\'B\\') R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  level uint division of icosahedron, point count = 10*(n+1)**2+2 R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  level uint division of icosahedron, point count = 5*4**(n+1) R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  parallelsCount uint  R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  gamma uint number of parallels height double ellipsoidal height R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  globalPointsCount uint  height double ellipsoidal height R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  dimension uint number of parallels = 2*dimension height double ellipsoidal height R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere border borderType  L angle longitude B angle latitude height double ellipsoidal height area double associated area element on unit sphere R double major axsis of the ellipsoid/sphere inverseFlattening double flattening of the ellipsoid, 0: sphere x double [m] y double [m] z double [m] area double associated area element on unit sphere inputfileGrid filename  border borderType', 'display_text': 'This class generates a set of grid points. In a first step, the grid is always generated globally, with <a class=\"groops-class\" href=\"borderType.html\">border</a> a regional subset of points can be extracted from the global grid. The parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> define the shape of the ellipsoid on which the grid is generated. In case <strong class=\"groops-config-element\">inverseFlattening</strong> is chosen as zero, a sphere is used. With <strong class=\"groops-config-element\">height</strong> the distance of the points above the ellipsoid can be defined. In addition to the location of the points, weights are assigned to each of the points. These weights can be regarded as the surface element associated with each grid point.  <h2>Geograph</h2><p> The geographical grid is an equal-angular point distribution with points located along meridians and along circles of latitude. <strong class=\"groops-config-element\">deltaLambda</strong> denotes the angular difference between adjacent points along meridians and <strong class=\"groops-config-element\">deltaPhi</strong> describes the angular difference between adjacent points along circles of latitude. The point setting results as follows: \\\\[ \\\\lambda_i=\\\\frac{\\\\Delta\\\\lambda}{2}+i\\\\cdot\\\\Delta\\\\lambda\\\\qquad\\\\mbox{with}\\\\qquad 0\\\\leq i< \\\\frac{360^\\\\circ}{\\\\Delta\\\\lambda}, \\\\]\\\\[ \\\\varphi_j=-90^\\\\circ+\\\\frac{\\\\Delta\\\\varphi}{2}+j\\\\cdot\\\\Delta\\\\varphi\\\\qquad\\\\mbox{with}\\\\qquad 0\\\\leq j<\\\\frac{180^\\\\circ}{\\\\Delta\\\\varphi}. \\\\]The number of grid points can be determined by \\\\[ I=\\\\frac{360^\\\\circ}{\\\\Delta\\\\lambda}\\\\cdot\\\\frac{180^\\\\circ}{\\\\Delta\\\\varphi}. \\\\]The weights are calculated according to \\\\[ w_i=\\\\int\\\\limits_{\\\\lambda_i-\\\\frac{\\\\Delta\\\\lambda}{2}}^{\\\\lambda_i+\\\\frac{\\\\Delta\\\\lambda}{2}}\\\\int\\\\limits_{\\\\vartheta_i-\\\\frac{\\\\Delta\\\\vartheta}{2}}^{\\\\vartheta_i+\\\\frac{\\\\Delta\\\\vartheta}{2}}=2\\\\cdot\\\\Delta\\\\lambda\\\\sin(\\\\Delta\\\\vartheta)\\\\sin(\\\\vartheta_i). \\\\] <h2>TriangleVertex</h2><p> The zeroth level of densification coincides with the 12 icosahedron vertices, as displayed in the upper left part of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a>. Then, depending on the envisaged densification, each triangle edge is divided into $n$ parts, illustrated in the upper right part of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a>. The new nodes on the edges are then connected by arcs of great circles parallel to the triangle edges. The intersections of each three corresponding parallel lines become nodes of the densified grid as well. As in case of a spherical triangle those three connecting lines do not exactly intersect in one point, the center of the resulting triangle is used as location for the new node (lower left part of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a>). The lower right side of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a> finally shows the densified triangle vertex grid for a level of $n=3$. The number of grid points in dependence of the chosen level of densification can be calculated by \\\\[\\\\label{eq:numberVertex} I=10\\\\cdot(n+1)^2+2. \\\\]   <h2>TriangleCenter</h2><p> The points of the zeroth level are located at the centers of the icosahedron triangles. To achieve a finer grid, each of the triangles is divided into four smaller triangles by connecting the midpoints of the triangle edges. The refined grid points are again located at the center of the triangles. Subsequently, the triangles can be further densified up to the desired level of densification $n$, which is defined by <strong class=\"groops-config-element\">level</strong>.</p><p>The number of global grid points for a certain level can be determined by \\\\[\\\\label{eq:numberCenter} I=20\\\\cdot 4^n. \\\\]Thus the quantity of grid points depends exponentially on the level $n$, as with every additional level the number of grid points quadruplicates.  <h2>Gauss</h2><p>  The grid features equiangular spacing along circles of latitude with  <strong class=\"groops-config-element\">parallelsCount</strong> defining the number $L$ of the parallels. \\\\[ \\\\Delta\\\\lambda=\\\\frac{\\\\pi}{L}\\\\qquad\\\\Rightarrow\\\\qquad\\\\lambda_i=\\\\frac{\\\\Delta\\\\lambda}{2}+i\\\\cdot\\\\Delta\\\\lambda\\\\qquad\\\\mbox{with}\\\\qquad 0\\\\leq i< 2L. \\\\]Along the meridians the points are located at $L$ parallels at the $L$ zeros $\\\\vartheta_j$ of the Legendre polynomial of degree $L$, \\\\[ P_L(\\\\cos\\\\vartheta_j)=0. \\\\]Consequently, the number of grid points sums up to \\\\[ I=2\\\\cdot L^2. \\\\]The weights can be calculated according to \\\\[ w_i(L)=\\\\Delta\\\\lambda\\\\frac{2}{(1-t_i^2)(P\\'_{L}(\\\\cos(\\\\vartheta _i)))^2},\\\\label{weights} \\\\] <h2>Reuter</h2><p> The Reuter grid features equi-distant spacing along the meridians determined by the control parameter $\\\\gamma$ according to \\\\[ \\\\Delta\\\\vartheta=\\\\frac{\\\\pi}{\\\\gamma}\\\\qquad\\\\Rightarrow\\\\vartheta_j=j\\\\Delta\\\\vartheta,\\\\qquad\\\\mbox{with}\\\\qquad 1\\\\leq j\\\\leq \\\\gamma-1. \\\\]Thus $\\\\gamma+1$ denotes the number of points per meridian, as the two poles are included in the point distribution as well. Along the circles of latitude, the number of grid points decreases with increasing latitude in order to achieve an evenly distributed point pattern. This number is chosen, so that the points along each circle of latitude have the same spherical distance as two adjacent latitudes. The resulting relationship is given by \\\\[\\\\label{eq:sphericalDistance} \\\\Delta\\\\vartheta=\\\\arccos\\\\left( \\\\cos^2\\\\vartheta_j+\\\\sin^2\\\\vartheta_j\\\\cos\\\\Delta\\\\lambda_j\\\\right). \\\\]The left hand side of this equation is the spherical distance between adjacent latitudes, the right hand side stands for the spherical distance between two points with the same polar distance $\\\\vartheta_j$ and a longitudinal difference of $\\\\Delta\\\\lambda_i$. This longitudinal distance can be adjusted depending on $\\\\vartheta_j$ to fulfill Eq. \\\\eqref{eq:sphericalDistance}. The resulting formula for $\\\\Delta\\\\lambda_i$ is \\\\[\\\\label{eq:deltaLambdai} \\\\Delta\\\\lambda_j=\\\\arccos\\\\left( \\\\frac{\\\\sin\\\\Delta\\\\vartheta -\\\\cos^2\\\\vartheta_j}{\\\\sin^2\\\\vartheta_j}\\\\right). \\\\]The number of points $\\\\gamma_j$ for each circle of latitude can then be determined by \\\\[\\\\label{eq:gammai} \\\\gamma_j=\\\\left[ \\\\frac{2\\\\pi}{\\\\Delta\\\\lambda_j}\\\\right] . \\\\]Here the Gauss bracket $[x]$ specifies the largest integer equal to or less than $x$. The longitudes are subsequently determined by \\\\[ \\\\lambda_{ij}=\\\\frac{\\\\Delta\\\\lambda_j}{2}+i\\\\cdot(2\\\\pi/\\\\gamma_j),\\\\qquad\\\\mbox{with}\\\\qquad 0\\\\leq i< \\\\gamma_j. \\\\]The number of grid points can be estimated by \\\\[\\\\label{eq:numberReuter} I=\\\\leq 2+\\\\frac{4}{\\\\pi}\\\\gamma^2, \\\\]The $\\\\leq$ results from the fact that the $\\\\gamma_j$ are restricted to integer values.  <h2>Corput</h2><p> This kind of grid distributes an arbitrarily chosen number of $I$ points (defined by <strong class=\"groops-config-element\">globalPointsCount</strong>) following a recursive, quasi random sequence. In longitudinal direction the pattern follows \\\\[ \\\\Delta\\\\lambda=\\\\frac{2\\\\pi}{I}\\\\qquad\\\\Rightarrow\\\\qquad\\\\frac{\\\\Delta\\\\lambda}{2}+\\\\lambda_i=i\\\\cdot\\\\Delta\\\\lambda\\\\qquad\\\\mbox{with}\\\\qquad 1\\\\leq i\\\\leq I. \\\\]This implies that every grid point features a unique longitude, with equi-angular longitudinal differences.</p><p>The polar distance in the form $t_i=\\\\cos\\\\vartheta_i$ for each point is determined by the following recursive sequence: <ul>  <li>Starting from an interval $t\\\\in[-1,1]$. </li><li> If $I=1$, then the midpoint of the interval is returned as result of the sequence, and the sequence is terminated. </li><li> If the number of points is uneven, the  midpoint is included into the list of $t_i$. </li><li> Subsequently, the interval is bisected into an upper and lower half,        and the sequence is called for both halves. </li><li> $t$ from upper and lower half are alternately sorted into the list of $t_i$. </li><li> The polar distances are calculated by \\\\[ \\\\vartheta_i=\\\\arccos\\\\, t_i. \\\\]</li></ul>   <h2>Driscoll</h2><p> The Driscoll-Healy grid, has equiangular spacing along the meridians as well as along the circles of latitude. In longitudinal direction (along the parallels), these angular differences for a given <strong class=\"groops-config-element\">dimension</strong> $L$ coincide with those described for the corresponding geographical grid and Gauss grid. Along the meridians, the size of the latitudinal differences is half the size compared to the geographical grid. This results in the following point pattern, \\\\[ \\\\begin{split} \\\\Delta\\\\lambda=\\\\frac{\\\\pi}{L}\\\\qquad&\\\\Rightarrow\\\\qquad\\\\lambda_i=\\\\frac{\\\\Delta\\\\lambda}{2}+i\\\\cdot\\\\Delta\\\\lambda\\\\qquad&\\\\mbox{with}\\\\qquad 0\\\\leq i< 2L, \\\\\\\\ \\\\Delta\\\\vartheta=\\\\frac{\\\\pi}{2L}\\\\qquad&\\\\Rightarrow\\\\qquad\\\\vartheta_j=j\\\\cdot\\\\Delta\\\\vartheta\\\\qquad&\\\\mbox{with}\\\\qquad 1\\\\leq j\\\\leq 2L. \\\\end{split} \\\\]Consequently, the number of grid points is \\\\[ I=4\\\\cdot L^2. \\\\]The weights are given by \\\\[ w_i=\\\\Delta\\\\lambda\\\\frac{4}{2L}\\\\sin(\\\\vartheta_i)\\\\sum_{l=0}^{L-1}\\\\frac{\\\\sin\\\\left[ (2l+1)\\\\;\\\\vartheta_i\\\\right] }{2l+1}. \\\\] <h2>SinglePoint</h2><p> Creates one single point.  <h2>SinglePointCartesian</h2><p> Creates one single point.  <h2 id=\"file\">File</h2><p> In this class grid is read from a file, which is given by <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGrid</a>. A corresponding file can be generated with <a class=\"groops-program\" href=\"GriddedDataCreate.html\">GriddedDataCreate</a> or with <a class=\"groops-program\" href=\"Matrix2GriddedData.html\">Matrix2GriddedData</a>.'},\n'instrumentTypeType': { 'name': 'instrumentTypeType', 'key': 'instrumentTypeType', 'description': 'Defines the type of an  instrument file .', 'config_table': 'instrumentTypeType choice instrument type INSTRUMENTTIME  time without data MISCVALUE  single value MISCVALUES  multiple values VECTOR3D  x, y, z COVARIANCE3D  xx, yy, zz, xy, xz, yz ORBIT  position [m], velocity [m/s], acceleration [m/s^2] (each x, y, z) STARCAMERA  quaternions (q0, qx, qy, qz) ACCELEROMETER  x, y, z [m/s^2] SATELLITETRACKING  range [m], range rate [m/s], range acceleration [m/s^2] GRADIOMETER  xx, yy, zz, xy, xz, yz [1/s^2] GNSSRECEIVER  GNSS phase/code observations [m] OBSERVATIONSIGMA  accuracy SATELLITELASERRANGING  range [m], accuracy [m], redundancy, window [s], wavelength [m], azimuth [rad], elevation [rad] METEOROLOGICAL  temperature [K], pressure [Pa], humidity [%], windSpeed [m/s], radiation [W/m^2], precip. [mm/d] MASS   THRUSTER   MAGNETOMETER   ACCHOUSEKEEPING', 'display_text': 'Defines the type of an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.'},\n'interpolatorTimeSeriesType': { 'name': 'interpolatorTimeSeriesType', 'key': 'interpolatorTimeSeriesType', 'description': 'This class resamples data of a times series to new poins in time.     Polynomial prediction using a moving polynomial of  polynomialDegree . The optimal polynomial is chosen based on the centricity of the data points around the resampling point and the distance to all polynomial data points. All polynomial data points must be within  maxDataPointRange . Resampling points within  maxExtrapolationDistance  of the polynomial will be extrapolated. The elements  maxDataPointRange  and  maxExtrapolationDistance  are given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.      A polynomial of  polynomialDegree  is estimated using all data points within  maxDataPointDistance  of the resampling point. This polynomial is then used to predict the resampling point. A resampling point will be extrapolated if there are only data points before/after as long as the closest one is within  maxExtrapolationDistance . The elements  maxDataPointDistance  and  maxExtrapolationDistance  are given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.', 'config_table': 'polynomialDegree uint degree of the moving polynomial maxDataPointRange double [seconds] all degree+1 data points must be within this range for a valid polynomial maxExtrapolationDistance double [seconds] resampling points within this range of the polynomial will be extrapolated polynomialDegree uint degree of the estimated polynomial maxDataPointDistance double [seconds] all data points within this distance around the resampling point will be used maxExtrapolationDistance double [seconds] resampling points within this range of the polynomial will be extrapolated polynomialDegree uint degree of the estimated polynomial maxDataGap double [seconds] max data gap to interpolate maxDataSpan double [seconds] time span on each side used for least squares fit margin double [seconds] margin for identical times', 'display_text': 'This class resamples data of a times series to new poins in time.  <h2>Polynomial</h2><p> Polynomial prediction using a moving polynomial of <strong class=\"groops-config-element\">polynomialDegree</strong>. The optimal polynomial is chosen based on the centricity of the data points around the resampling point and the distance to all polynomial data points. All polynomial data points must be within <strong class=\"groops-config-element\">maxDataPointRange</strong>. Resampling points within <strong class=\"groops-config-element\">maxExtrapolationDistance</strong> of the polynomial will be extrapolated. The elements <strong class=\"groops-config-element\">maxDataPointRange</strong> and <strong class=\"groops-config-element\">maxExtrapolationDistance</strong> are given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.</p><p>  <h2>Least squares polynomial fit</h2><p> A polynomial of <strong class=\"groops-config-element\">polynomialDegree</strong> is estimated using all data points within <strong class=\"groops-config-element\">maxDataPointDistance</strong> of the resampling point. This polynomial is then used to predict the resampling point. A resampling point will be extrapolated if there are only data points before/after as long as the closest one is within <strong class=\"groops-config-element\">maxExtrapolationDistance</strong>. The elements <strong class=\"groops-config-element\">maxDataPointDistance</strong> and <strong class=\"groops-config-element\">maxExtrapolationDistance</strong> are given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.</p><p>  <h2>Fill gaps with least squares polynomial fit</h2><p>'},\n'kernelType': { 'name': 'kernelType', 'key': 'kernelType', 'description': 'Kernel defines harmonic isotropic integral kernels  .  where   is the (disturbance)potential and   is a functional on the spherical surface  . The Kernel can be exapanded into a series of (fully normalized) legendre polynomials  On the one hand the kernel defines the type of the functionals   that are measured or have to be computed, e.g. gravity anomalies given by the Stokes-kernel. On the other hand the kernel functions can be used as basis functions to represent the gravity field, e.g. as spline functions or wavelets.     The geoid height is defined by Bruns formula  with   the disturbance potential and the normal gravity  and  where   is the ellipsoidal height in meter and   the longitude. The kernel is given by  and the coefficients in   are      Gravity anomalies in linearized form are defined by  The Stokes kernel is given by  and the coefficients in   are      Gravity disturbances in linearized form are defined by  The Hotine kernel is given by  and the coefficients in   are      The Abel-Poisson kernel is given by  and the coefficients in   are      This kernel defines a point mass or mass on a single layer ( -kernel) taking the effect of the loading into account. The coefficients of the kernel defined in   are  where   is the gravitational constant and   are the load Love numbers.     Height of equivalent water columns taking the effect of the loading into account. The coefficients of the kernel defined in   are  where   is the gravitational constant,   is the  density  of water and   are the load Love numbers.     Ocean bottom pressure caused by water and atmosphere masses columns taking the effect of the loading into account. The coefficients of the kernel defined in   are  where   is the gravitational constant,   is the normal gravity and   are the load Love numbers.     Computes the radial deformation caused by loading. The coefficients of the kernel defined in   are  where   is the normal gravity defined in  ,   and   are the load Love numbers and the load deformation Love numbers.     This kernel defines the second radial derivative of the (disturbance) potential.  The coefficients of the kernel defined in   are      The kernel is defined by the coefficients   given by file.     Another     is smoothed by a gauss filter which is defined by  with   where   is the given smoothing  radius  in km and   km is the Earth radius. The coefficients   of the  kernel  are multiplicated by      Another     is smoothed by a Blackman low-pass filter. The filter is defined through the beginning and end of the transition from pass-band to stop-band. This transition band is specified by  startDegreeTransition  ( ) and  stopDegreeTransition  ( ). The coefficients of this kernel are defined as  with      Another     is truncated before  minDegree  and after  maxDegree . The coefficients of this kernel are defined as      The selenoid height is defined by Bruns formula  with   the disturbance potential and the normal gravity   of the moon. The kernel is given by  and the coefficients in   are', 'config_table': 'inputfileLoadingLoveNumber filename  density double [kg/m**3] inputfileLoadingLoveNumber filename  inputfileLoadingLoveNumber filename  inputfileDeformationLoadLoveNumber filename  inputfilePotentialLoadLoveNumber filename if full potential is given and not only loading potential inputfileCoefficients filename  kernel kernelType  radius double filter radius [km] kernel kernelType  startDegreeTransition uint minimum degree in transition band stopDegreeTransition uint maximum degree in transition band kernel kernelType  minDegree uint truncate before minDegree maxDegree uint truncate after maxDegree', 'display_text': 'Kernel defines harmonic isotropic integral kernels $K$. \\\\[ T(P) = \\\\frac{1}{4\\\\pi}\\\\int_\\\\Omega K(P,Q)\\\\cdot f(Q)\\\\,d\\\\Omega(Q), \\\\]where $T$ is the (disturbance)potential and $f$ is a functional on the spherical surface $\\\\Omega$. The Kernel can be exapanded into a series of (fully normalized) legendre polynomials \\\\[\\\\label{eq.kernel} K(\\\\cos\\\\psi,r,R) = \\\\sum_n \\\\left(\\\\frac{R}{r}\\\\right)^{n+1} k_n\\\\sqrt{2n+1}\\\\bar{P}_n(\\\\cos\\\\psi). \\\\]On the one hand the kernel defines the type of the functionals $f$ that are measured or have to be computed, e.g. gravity anomalies given by the Stokes-kernel. On the other hand the kernel functions can be used as basis functions to represent the gravity field, e.g. as spline functions or wavelets.  <h2 id=\"geoidHeight\">GeoidHeight</h2><p> The geoid height is defined by Bruns formula \\\\[ N = \\\\frac{1}{\\\\gamma}T \\\\]with $T$ the disturbance potential and the normal gravity \\\\[\\\\label{normalgravity} \\\\gamma  = \\\\gamma_0 - 0.30877\\\\cdot 10^{-5}/s^2(1-0.00142\\\\sin^2(B))h \\\\]and \\\\[ \\\\gamma_0 = 9.780327\\\\,m/s^2(1+0.0053024\\\\sin^2(B)-0.0000058\\\\sin^2(2B)) \\\\]where $h$ is the ellipsoidal height in meter and $B$ the longitude.</p><p>The kernel is given by \\\\[ K(\\\\cos\\\\psi,r,R) = \\\\gamma\\\\frac{R(r^2-R^2)}{l^3}, \\\\]and the coefficients in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\gamma. \\\\] <h2>Anomalies</h2><p> Gravity anomalies in linearized form are defined by \\\\[ \\\\Delta g = -\\\\frac{\\\\partial T}{\\\\partial r}-\\\\frac{2}{r}T. \\\\]The Stokes kernel is given by \\\\[ K(\\\\cos\\\\psi,r,R) = \\\\frac{2R^2}{l}-3\\\\frac{Rl}{r^2}-\\\\frac{R^2}{r^2}\\\\cos\\\\psi \\\\left(5+3\\\\ln\\\\frac{l+r-R\\\\cos\\\\psi}{2r}\\\\right), \\\\]and the coefficients in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\frac{R}{n-1}. \\\\] <h2 id=\"disturbance\">Disturbance</h2><p> Gravity disturbances in linearized form are defined by \\\\[ \\\\delta g = -\\\\frac{dT}{dr}. \\\\]The Hotine kernel is given by \\\\[ K(\\\\cos\\\\psi,r,R) = \\\\frac{2R^2}{l}-R\\\\ln\\\\frac{l+R-r\\\\cos\\\\psi}{r(1-\\\\cos\\\\psi)}, \\\\]and the coefficients in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\frac{R}{n+1}. \\\\] <h2>Potential</h2><p> The Abel-Poisson kernel is given by \\\\[ K(\\\\cos\\\\psi,r,R) = \\\\frac{R(r^2-R^2)}{l^3}, \\\\]and the coefficients in \\\\eqref{eq.kernel} are \\\\[ k_n = 1. \\\\] <h2>Density</h2><p> This kernel defines a point mass or mass on a single layer ($1/l$-kernel) taking the effect of the loading into account.</p><p>The coefficients of the kernel defined in \\\\eqref{eq.kernel} are \\\\[ k_n = 4\\\\pi G R\\\\frac{1+k_n\\'}{2n+1}, \\\\]where $G$ is the gravitational constant and $k_n\\'$ are the load Love numbers.  <h2 id=\"waterHeight\">WaterHeight</h2><p> Height of equivalent water columns taking the effect of the loading into account.</p><p>The coefficients of the kernel defined in \\\\eqref{eq.kernel} are \\\\[ k_n = 4\\\\pi G \\\\rho R\\\\frac{1+k_n\\'}{2n+1}, \\\\]where $G$ is the gravitational constant, $\\\\rho$ is the <strong class=\"groops-config-element\">density</strong> of water and $k_n\\'$ are the load Love numbers.  <h2>BottomPressure</h2><p> Ocean bottom pressure caused by water and atmosphere masses columns taking the effect of the loading into account.</p><p>The coefficients of the kernel defined in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\frac{4\\\\pi G R }{\\\\gamma}\\\\frac{1+k_n\\'}{2n+1}, \\\\]where $G$ is the gravitational constant, $\\\\gamma$ is the normal gravity and $k_n\\'$ are the load Love numbers.  <h2>Deformation</h2><p> Computes the radial deformation caused by loading.</p><p>The coefficients of the kernel defined in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\gamma\\\\frac{1+k_n\\'}{h_n\\'}, \\\\]where $\\\\gamma$ is the normal gravity defined in \\\\eqref{normalgravity}, $h_n\\'$ and $k_n\\'$ are the load Love numbers and the load deformation Love numbers.  <h2>RadialGradient</h2><p> This kernel defines the second radial derivative of the (disturbance) potential. \\\\[ T_{rr} = \\\\frac{\\\\partial^2 T}{\\\\partial r^2}. \\\\]The coefficients of the kernel defined in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\frac{r^2}{(n+1)(n+2)}. \\\\] <h2 id=\"coefficients\">Coefficients</h2><p> The kernel is defined by the coefficients $k_n$ given by file.  <h2>FilterGauss</h2><p> Another <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is smoothed by a gauss filter which is defined by \\\\[ F(\\\\cos\\\\psi) = \\\\frac{b\\\\cdot e^{-b(1-\\\\cos\\\\psi)}}{1-e^{-2b}} \\\\]with $b = \\\\frac{ln(2)}{1-\\\\cos(r/R)}$ where $r$ is the given smoothing <strong class=\"groops-config-element\">radius</strong> in km and $R=6378.1366$ km is the Earth radius. The coefficients $k_n$ of the <strong class=\"groops-config-element\">kernel</strong> are multiplicated by \\\\[ f_n = \\\\frac{1}{2n+1} \\\\int_{-1}^1 F(t)\\\\cdot \\\\bar{P}_n(t)\\\\,dt. \\\\] <h2>BlackmanLowpass</h2><p> Another <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is smoothed by a Blackman low-pass filter. The filter is defined through the beginning and end of the transition from pass-band to stop-band. This transition band is specified by <strong class=\"groops-config-element\">startDegreeTransition</strong> ($n_1$) and <strong class=\"groops-config-element\">stopDegreeTransition</strong> ($n_2$).</p><p>The coefficients of this kernel are defined as \\\\[ \\\\begin{cases} 1 & \\\\text{for } n < n_1 \\\\\\\\ A_n^2 & \\\\text{for } n_1\\\\leq n \\\\leq n_2 \\\\\\\\ 0 & \\\\text{for } n > n_2 \\\\\\\\ \\\\end{cases} \\\\]with \\\\[ A_n = 0.42 + 0.5\\\\cos(\\\\pi \\\\frac{n-n_1}{n_2-n_1}) + 0.08 \\\\cos(2\\\\pi\\\\frac{n-n_1}{n_2-n_1}). \\\\] <h2>Truncation</h2><p> Another <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is truncated before <strong class=\"groops-config-element\">minDegree</strong> and after <strong class=\"groops-config-element\">maxDegree</strong>. The coefficients of this kernel are defined as \\\\[   k_n =   \\\\begin{cases}   1 & \\\\text{for } n_{\\\\text{minDegree}} \\\\leq n \\\\leq n_{\\\\text{maxDegree}}\\\\\\\\   0 & \\\\text{else.} \\\\\\\\   \\\\end{cases} \\\\] <h2>SelenoidHeight</h2><p> The selenoid height is defined by Bruns formula \\\\[ N = \\\\frac{1}{\\\\gamma}T \\\\]with $T$ the disturbance potential and the normal gravity $\\\\gamma=\\\\frac{GM}{R^2}$ of the moon.</p><p>The kernel is given by \\\\[ K(\\\\cos\\\\psi,r,R) = \\\\gamma\\\\frac{R(r^2-R^2)}{l^3}, \\\\]and the coefficients in \\\\eqref{eq.kernel} are \\\\[ k_n = \\\\gamma. \\\\]'},\n'loopType': { 'name': 'loopType', 'key': 'loopType', 'description': 'Generates a sequence with variables to loop over. The variable names can be set with  variableLoop...  and the current values are assigned to the variables for each loop step. With     only a subset of loop steps are performed. The  variableLoopIndex  and  variableLoopCount  are not affected by the condition. The result would therefore be the same as using  LoopPrograms  with a nested  IfPrograms . See  Loop and conditions  for usage.     Loop over points in time.     Loop over the intervals between points in time.     Loop over list of strings.     Loop over  row s of a table containing strings. Each row must have the same number of cells. For each column an extra  variableLoopString  can be defined.     Loop over list of strings from  files .     Loop over rows of a  table  containing strings. Each row must have the same number of columns.     Loop over lines of a text file.     Loop over rows of a  matrix . To define the loop variables the standard data variables of the matrix are available, see  dataVariables .     Loop over sequence of numbers.     Loop over files of a directory.     Loop over lines of command output.     Loop over specific equipment of a  platform file .     Loop over nested loops. First  loop  is outermost loop, every subsequent  loop  is one level below the previous  loop .     Perform the     in the alphabetically order defined by the evaluated  sortString  for each loop step. So the string must contain loop variables. If  sortString  is empty, no sorting will take place. Example: The  sortString = {loopTime:%m}  of a time series sorts the times in ascending order by month. The same principle is used to remove duplicates. If different loop steps evaluates  removeDuplicatesString  to the same string, only the first loop step is executed.     DEPRECATED since 2025-09-27. Use LoopStringTable instead.     DEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.', 'config_table': 'timeSeries timeSeriesType loop is called for every point in time variableLoopTime string variable with time of each loop variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step timeIntervals timeSeriesType loop is called for every interval variableLoopTimeStart string variable with starting time of each interval variableLoopTimeEnd string variable with ending time of each interval variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step string string explicit list of strings variableLoopString string name of the variable to be replaced variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step row sequence rows of a table cell string list of columns in a row transpose boolean loop over columns instead of rows variableLoopString string 1. variable name for the 1. column, next variable name for the 2. column, ...  variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step inputfile filename string list file variableLoopString string name of the variable to be replaced variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step inputfile filename string table file with multiple columns transpose boolean loop over columns instead of rows variableLoopString string 1. variable name for the 1. column, next variable name for the 2. column, ...  variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step inputfile filename simple text file with lines startIndex uint start at element startIndex (counting from 0) count uint use number of loops only (default: use all) variableLoopLine string name of the variable to be replaced variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step inputfile filename  transpose boolean effectively loop over columns startRow expression start at this row (variable: rows) countRows expression use this many rows (variable: rows) variableLoop expression define a variable by name = expression (input columns are named data0, data1, ...) variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step rangeStart double start of range rangeEnd double end of range (inclusive) sampling double sampling variableLoopNumber string name of the variable to be replaced variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step directory filename directory pattern string wildcard pattern isRegularExpression boolean pattern is a regular expression variableLoopFile string name of the variable to be replaced variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step command filename each output line becomes a loop iteration silently boolean without showing the output. variableLoopString string name of the variable to be replaced variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step inputfilePlatform filename platform info file equipmentType choice equipment type to loop over all  loop over all types gnssAntenna  loop over antennas gnssReceiver  loop over receivers slrStation  loop over SLR stations slrRetroReflector  loop over laser retroreflectors satelliteIdentifier  loop over satellite identifiers other  loop over other types variableLoopName string variable with name variableLoopSerial string variable with serial variableLoopInfo string variable with radome (antenna) or version (receiver) variableLoopTimeStart string variable with start time variableLoopTimeEnd string variable with end time variableLoopPositionX string variable with position x variableLoopPositionY string variable with position y variableLoopPositionY string variable with position z variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step loop loopType subloop variableLoopIndex string variable with index of current iteration (starts with zero) condition conditionType check before each loop step loop loopType  sortString string use {loopVariables}, sort alphabetically descending boolean sorting descending instead of ascending removeDuplicatesString string use {loopVariables}, remove duplicates (order is preserved) variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step table choice define table by rows/columns rowWise sequence define table by rows row sequence define table by rows cell string explicit list of cells in row/column columnWise sequence define table by columns column sequence define table by columns cell string explicit list of cells in row/column variableLoopString string 1. variable name for the 1. column, next variable name for the 2. column, ...  variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step inputfileGnssStationInfo filename station/transmitter info file infoType choice info to loop over antenna  loop over antennas receiver  loop over receivers variableLoopName string variable with antenna/receiver name variableLoopSerial string variable with antenna/receiver serial variableLoopInfo string variable with radome (antenna) or version (receiver) variableLoopTimeStart string variable with antenna/receiver start time variableLoopTimeEnd string variable with antenna/receiver end time variableLoopIndex string variable with index of current iteration (starts with zero) variableLoopCount string variable with total number of iterations condition conditionType check before each loop step', 'display_text': 'Generates a sequence with variables to loop over. The variable names can be set with <strong class=\"groops-config-element\">variableLoop...</strong> and the current values are assigned to the variables for each loop step.</p><p>With <a class=\"groops-class\" href=\"conditionType.html\">condition</a> only a subset of loop steps are performed. The <strong class=\"groops-config-element\">variableLoopIndex</strong> and <strong class=\"groops-config-element\">variableLoopCount</strong> are not affected by the condition. The result would therefore be the same as using <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> with a nested <a class=\"groops-program\" href=\"IfPrograms.html\">IfPrograms</a>.</p><p>See <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">Loop and conditions</a> for usage.  <h2 id=\"timeSeries\">TimeSeries</h2><p> Loop over points in time.  <h2 id=\"timeIntervals\">TimeIntervals</h2><p> Loop over the intervals between points in time.  <h2 id=\"stringList\">StringList</h2><p> Loop over list of strings.  <h2 id=\"stringTable\">StringTable</h2><p> Loop over <strong class=\"groops-config-element\">row</strong>s of a table containing strings. Each row must have the same number of cells. For each column an extra <strong class=\"groops-config-element\">variableLoopString</strong> can be defined.  <h2 id=\"fileStringList\">FileStringList</h2><p> Loop over list of strings from <a class=\"groops-file\" href=\"fileFormat_stringList.html\">files</a>.  <h2 id=\"fileStringTable\">FileStringTable</h2><p> Loop over rows of a <a class=\"groops-file\" href=\"fileFormat_stringTable.html\">table</a> containing strings. Each row must have the same number of columns.  <h2 id=\"fileTextLines\">FileTextLines</h2><p> Loop over lines of a text file.  <h2 id=\"matrix\">Matrix</h2><p> Loop over rows of a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>. To define the loop variables the standard data variables of the matrix are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.  <h2 id=\"numberSequence\">NumberSequence</h2><p> Loop over sequence of numbers.  <h2 id=\"directoryListing\">DirectoryListing</h2><p> Loop over files of a directory.  <h2 id=\"commandOutput\">CommandOutput</h2><p> Loop over lines of command output.  <h2 id=\"platformEquipment\">PlatformEquipment</h2><p> Loop over specific equipment of a <a class=\"groops-file\" href=\"fileFormat_platform.html\">platform file</a>.  <h2 id=\"loop\">Loop</h2><p> Loop over nested loops. First <strong class=\"groops-config-element\">loop</strong> is outermost loop, every subsequent <strong class=\"groops-config-element\">loop</strong> is one level below the previous <strong class=\"groops-config-element\">loop</strong>.  <h2 id=\"sortAndRemoveDuplicates\">SortAndRemoveDuplicates</h2><p> Perform the <a class=\"groops-class\" href=\"loopType.html\">loop</a> in the alphabetically order defined by the evaluated <strong class=\"groops-config-element\">sortString</strong> for each loop step. So the string must contain loop variables. If <strong class=\"groops-config-element\">sortString</strong> is empty, no sorting will take place.</p><p>Example: The <strong class=\"groops-config-element\">sortString</strong>=<code>{loopTime:%m}</code> of a time series sorts the times in ascending order by month.</p><p>The same principle is used to remove duplicates. If different loop steps evaluates <strong class=\"groops-config-element\">removeDuplicatesString</strong> to the same string, only the first loop step is executed.  <h2>ManualTable</h2><p> DEPRECATED since 2025-09-27. Use LoopStringTable instead.  <h2>FileGnssStationInfo</h2><p> DEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.'},\n'magnetosphereType': { 'name': 'magnetosphereType', 'key': 'magnetosphereType', 'description': 'This class provides functions of the magnetic field of the Earth.     International Geomagnetic Reference Field.', 'config_table': 'inputfileMagneticNorthPole filename time series of north pole', 'display_text': 'This class provides functions of the magnetic field of the Earth.  <h2>IGRF</h2><p> International Geomagnetic Reference Field.'},\n'matrixGeneratorType': { 'name': 'matrixGeneratorType', 'key': 'matrixGeneratorType', 'description': 'This class provides a matrix used e.g. by  MatrixCalculate . If multiple matrices are given the resulting matrix is the sum all and the size is exandeded to fit all matrices. Before the computation of each submatrix the variables  rowsBefore  and  columnsBefore  with current size of the overall matrix are set. As all matrices can be manipulated before, complex matrix operations are possible.     Matrix from  file .     Matrix from a  normal equation file . The symmetric normal matrix, the right hand side vector, the lPl vector, or the observation count   can be selected.     Matrix filled by an expression. For each element of the new matrix the variables  row  and  column  are set and the expression  element  is evaluated. Excample: The  element = if(row==column,1,0)  generates an identity matrix.     The elements of a matrix are replaced an expression. For each element of the matrix the variables  data ,  row ,  column  are set and the expression  element  is evaluated and replaces the element. Additionally the standard data variables are available (assigned each row), see  dataVariables .     Given two matrices   and   this class computes  , where   is an expression (for example  data0*data1 ). For each element of the matrix the variables  data0 ,  data1 ,  row ,  column  are set and the expression  element  is evaluated.     Append matrix to the right (first row) or bottom (first column).     Shift start row and start column of a matrix. In other words: zero lines and columns are inserted at the beginning of the matrix.     Slice of a matrix.     Matrix reshaped columnwise to new row and columns.     Reorder rows or columns of a matrix by an index vectors. The index vector can be created with  ParameterSelection2IndexVector .     Sort matrix by  column  in ascending order by default or in  descending  order.     Transposed of a matrix  .     Multiplication of matrices.     Inverse of a matrix  .     Upper triangular natrix of the cholesky decomposition of a symmetric matrix  .     Symmetric matrix from rank k update:  .     Computes the eigenvalues of a square matrix and gives a vector of eigenvalues for symmetric matrices or a matrix with 2 columns with real and imaginary parts in general case.     Extract the diagonal or subdiagnoal (  vector) of a matrix. The zero  diagonal  means the main diagonal, a positive value the superdiagonal, and a negative the subdiagonal.     Generate a matrix from a diagonal vector.     Set type (matrix, matrixSymmetricUpper, matrixSymmetricLower, matrixTriangularUpper, matrixTriangularLower) of a matrix. If the type is not matrix, the matrix must be quadratic. Symmetric matrices are filled symmetric and for triangular matrix the other triangle is set to zero.', 'config_table': 'inputfileMatrix filename  factor double  inputfileNormalEquation filename  type choice  normalMatrix   rightHandSide   lPl   observationCount   factor double  rows expression (variables: rowsBefore, columnsBefore) columns expression (variables: rowsBefore, columnsBefore) element expression for each element of matrix (variables: row, column, rows, columns, rowsBefore, columnsBefore) matrix matrixGeneratorType  element expression for each element of matrix (variables: data, row, column, rows, columns, rowsBefore, columnsBefore) matrix1 matrixGeneratorType  matrix2 matrixGeneratorType  expression expression for each element of matrix (variables: data0, data1, row, column, rows, columns, rowsBefore, columnsBefore) matrix matrixGeneratorType  side choice  right   bottom   diagonal   matrix matrixGeneratorType  startRow expression start row (variables: rowsBefore, columnsBefore, rows, columns) startColumn expression start column (variables: rowsBefore, columnsBefore, rows, columns) matrix matrixGeneratorType  startRow expression start row of matrix (variables: rowsBefore, columnsBefore, rows, columns) startColumn expression start column of matrix (variables: rowsBefore, columnsBefore, rows, columns) rows expression 0: until end (variables: rowsBefore, columnsBefore, rows, columns) columns expression 0: until end (variables: rowsBefore, columnsBefore, rows, columns) matrix matrixGeneratorType  rows expression 0: auto-determine rows, (variables: rowsBefore, columnsBefore) columns expression 0: auto-determine columns (variables: rowsBefore, columnsBefore) matrix matrixGeneratorType  inputfileIndexVectorRow filename index in input matrix or -1 for new parameter. inputfileIndexVectorColumn filename index in input matrix or -1 for new parameter. matrix matrixGeneratorType  column uint sort by column, top = highest priority descending boolean  matrix matrixGeneratorType  matrix1 matrixGeneratorType  matrix2 matrixGeneratorType  factor double  matrix matrixGeneratorType  pseudoInverse boolean compute pseudo inverse instead of regular one matrix matrixGeneratorType  matrix matrixGeneratorType  factor double  matrix matrixGeneratorType  eigenVectors boolean return eigen vectors instead of eigen values matrix matrixGeneratorType  diagonal int zero: main diagonal, positive: superdiagonal, negative: subdiagonal matrix matrixGeneratorType (nx1) or (1xn) diagonal vector diagonal int zero: main diagonal, positive: superdiagonal, negative: subdiagonal matrix matrixGeneratorType  type choice  matrix   matrixSymmetricUpper   matrixSymmetricLower   matrixTriangularUpper   matrixTriangularLower', 'display_text': 'This class provides a matrix used e.g. by <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>. If multiple matrices are given the resulting matrix is the sum all and the size is exandeded to fit all matrices. Before the computation of each submatrix the variables <code>rowsBefore</code> and <code>columnsBefore</code> with current size of the overall matrix are set. As all matrices can be manipulated before, complex matrix operations are possible.  <h2>File</h2><p> Matrix from <a class=\"groops-file\" href=\"fileFormat_matrix.html\">file</a>.  <h2>Normals file</h2><p> Matrix from a <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equation file</a>. The symmetric normal matrix, the right hand side vector, the lPl vector, or the observation count $(1\\\\times1)$ can be selected.  <h2>Expression</h2><p> Matrix filled by an expression. For each element of the new matrix the variables <code>row</code> and <code>column</code> are set and the expression <strong class=\"groops-config-element\">element</strong> is evaluated.</p><p>Excample: The <strong class=\"groops-config-element\">element</strong>=<code>if(row==column,1,0)</code> generates an identity matrix.  <h2>Element manipulation</h2><p> The elements of a matrix are replaced an expression. For each element of the matrix the variables <code>data</code>, <code>row</code>, <code>column</code> are set and the expression <strong class=\"groops-config-element\">element</strong> is evaluated and replaces the element. Additionally the standard data variables are available (assigned each row), see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.  <h2>ElementWiseOperation</h2><p> Given two matrices $\\\\mathbf{A}$ and $\\\\mathbf{B}$ this class computes $c_{ij} = f(a_{ij}, b_{ij})$, where $f$ is an expression (for example <code>data0*data1</code>). For each element of the matrix the variables <code>data0</code>, <code>data1</code>, <code>row</code>, <code>column</code> are set and the expression <strong class=\"groops-config-element\">element</strong> is evaluated.  <h2>Append</h2><p> Append matrix to the right (first row) or bottom (first column).  <h2>Shift</h2><p> Shift start row and start column of a matrix. In other words: zero lines and columns are inserted at the beginning of the matrix.  <h2>Slice</h2><p> Slice of a matrix.  <h2>Reshape</h2><p> Matrix reshaped columnwise to new row and columns.  <h2 id=\"reorder\">Reorder</h2><p> Reorder rows or columns of a matrix by an index vectors. The index vector can be created with <a class=\"groops-program\" href=\"ParameterSelection2IndexVector.html\">ParameterSelection2IndexVector</a>.  <h2>Sort</h2><p> Sort matrix by <strong class=\"groops-config-element\">column</strong> in ascending order by default or in <strong class=\"groops-config-element\">descending</strong> order.  <h2>Transpose</h2><p> Transposed of a matrix $\\\\M A^T$.  <h2>Multiplication</h2><p> Multiplication of matrices.  <h2>Inverse</h2><p> Inverse of a matrix $\\\\M A^{-1}$.  <h2>Cholesky</h2><p> Upper triangular natrix of the cholesky decomposition of a symmetric matrix $\\\\M A=\\\\M W^T\\\\M W$.  <h2>RankKUpdate</h2><p> Symmetric matrix from rank k update: $\\\\M A^T\\\\M A$.  <h2>EigenValues</h2><p> Computes the eigenvalues of a square matrix and gives a vector of eigenvalues for symmetric matrices or a matrix with 2 columns with real and imaginary parts in general case.  <h2>Diagonal</h2><p> Extract the diagonal or subdiagnoal ($n\\\\times 1$ vector) of a matrix. The zero <strong class=\"groops-config-element\">diagonal</strong> means the main diagonal, a positive value the superdiagonal, and a negative the subdiagonal.  <h2>FromDiagonal</h2><p> Generate a matrix from a diagonal vector.  <h2>Set type</h2><p> Set type (matrix, matrixSymmetricUpper, matrixSymmetricLower, matrixTriangularUpper, matrixTriangularLower) of a matrix. If the type is not matrix, the matrix must be quadratic. Symmetric matrices are filled symmetric and for triangular matrix the other triangle is set to zero.'},\n'miscAccelerationsType': { 'name': 'miscAccelerationsType', 'key': 'miscAccelerationsType', 'description': 'This class gives the non conservative forces acting on satellites.     The relativistic effect to the acceleration of an artificial Earth satellite according to IERS2010 conventions. The macro model and the attitude of the satellite is not needed.     This class computes acceleration acting on a satellite caused by Solar and Earth radiation pressure and thermal radiation. Solar radiation pressure: The solar constant at 1 AU can be set via  solarFlux . The  factorSolarRadation  can be used to scale the computed acceleration of the direct solar radiation. Earth radiation pressure: Input are a time series of gridded albedo values (unitless) as     and a time series of gridded longwave flux (W/m ) as    . Both files are optional and if not specified, the respective effect on the acceleration is not computed. The  factorEarthRadation  can be used to scale the computed acceleration of the earth radiation. The thermal radiation (TRP) of the satellite itself is either computed as direct re-emission or based on the actual temperature of the satellite surfaces, depending on the setings of the  satellite macro model . The second one uses a transient temperature model with a temporal differential equation which disallows parallel computing. The  factorThermalRadiation  can be used to scale the computed acceleration of the TRP. The algorithms are described in: Woeske et. al. (2019), GRACE accelerometer calibration by high precision non-gravitational force modeling, Advances in Space Research,  https://doi.org/10.1016/j.asr.2018.10.025 .     Atmospheric drag model. Algorithm for the atmospheric drag modelling is based on the free molecule flow theory by Sentman 1961. An analytical expression of this treatise is given in Moe and Moe 2005. Sentman L. (1961), Free molecule flow theory and its application to the determination of aerodynamic forces, Technical report. Moe K., Moe M. M. (2005), Gas-surface interactions and satellite drag coefficients, Planetary and Space Science 53(8), 793-801, doi:10.1016/j.pss.2005.03.005. Optional determination steps: Turn temperature on or off. In the first case, the model mentioned above is applied, which estimates variable drag and lift coefficients - in the latter case a constant drag coefficient can be specified. Turn wind on/off: It enables the usage of the Horizontal Wind Model 2014 to add additional thermospheric winds in the calculation process.     Atmospheric drag computed from thermospheric density along the orbit (   , MISCVALUE). The     is used to to compute temperature and wind. For further details see    .     The thrust (acceleration) in the opposite direction the antenna is facing which is generated by satellite antenna broadcasts. The thrust is defined in the satellite macro model.     Reads a solution vector from file     which may be computed by a least squares adjustment (e.g. by  NormalsSolverVCE ). The coefficients of the vector are interpreted from position  indexStart  (counting from zero) with help of    . If the solution file contains solution of several right hand sides you can choose one with number  rightSide  (counting from zero). The computed result is multiplied with  factor .     Groups a set of     and has no further effect itself.     DEPRECATED since 2022-12-19. Use radiationPressure instead.     DEPRECATED since 2022-12-19. Use radiationPressure instead.', 'config_table': 'beta double PPN (parameterized post-Newtonian) parameter gamma double PPN (parameterized post-Newtonian) parameter J double Earth’s angular momentum per unit mass [m**2/s] GM double Geocentric gravitational constant factor double the result is multiplied by this factor solarflux double solar flux constant in 1 AU [W/m^2] eclipse eclipseType  inputfileAlbedoTimeSeries filename GriddedDataTimeSeries of albedo values (unitless) inputfileLongwaveFluxTimeSeries filename GriddedDataTimeSeries of longwave flux values [W/m^2] factorSolarRadation double Solar radiation pressure is multiplied by this factor factorEarthRadation double Earth radiation preussure is multiplied by this factor factorThermalRadiation double Thermal (re-)radiation is multiplied by this factor thermosphere thermosphereType  earthRotation double [rad/s] considerTemperature boolean compute drag and lift, otherwise simple drag coefficient is used considerWind boolean  factor double the result is multiplied by this factor inputfileDensity filename density along orbit, MISCVALUE (kg/m^3) thermosphere thermosphereType used to compute temperature and wind earthRotation double [rad/s] considerTemperature boolean compute drag and lift, otherwise simple drag coefficient is used considerWind boolean  factor double the result is multiplied by this factor factor double the result is multiplied by this factor parametrization parametrizationAccelerationType  inputfileSolution filename solution vector indexStart uint position in the solution vector rightSide uint if solution contains several right hand sides, select one factor double the result is multiplied by this factor, set -1 to subtract the field miscAccelerations miscAccelerationsType  factor double the result is multiplied by this factor solarflux double solar flux constant in 1 AU [W/m**2] eclipse eclipseType  factor double the result is multiplied by this factor, set -1 to subtract the field inputfileReflectivity filename  inputfileEmissivity filename  solarflux double solar flux constant in 1 AU [W/m**2] factor double the result is multiplied by this factor, set -1 to subtract the field', 'display_text': 'This class gives the non conservative forces acting on satellites.  <h2 id=\"relativisticEffect\">Relativistic effect</h2><p> The relativistic effect to the acceleration of an artificial Earth satellite according to IERS2010 conventions.</p><p>The macro model and the attitude of the satellite is not needed.  <h2 id=\"RadiationPressure\">RadiationPressure</h2><p> This class computes acceleration acting on a satellite caused by Solar and Earth radiation pressure and thermal radiation.</p><p>Solar radiation pressure: The solar constant at 1 AU can be set via <strong class=\"groops-config-element\">solarFlux</strong>. The <strong class=\"groops-config-element\">factorSolarRadation</strong> can be used to scale the computed acceleration of the direct solar radiation.</p><p>Earth radiation pressure: Input are a time series of gridded albedo values (unitless) as <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileAlbedoTimeSeries</a> and a time series of gridded longwave flux (W/m$^2$) as <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileLongwaveFluxTimeSeries</a>. Both files are optional and if not specified, the respective effect on the acceleration is not computed. The <strong class=\"groops-config-element\">factorEarthRadation</strong> can be used to scale the computed acceleration of the earth radiation.</p><p>The thermal radiation (TRP) of the satellite itself is either computed as direct re-emission or based on the actual temperature of the satellite surfaces, depending on the setings of the <a class=\"groops-file\" href=\"fileFormat_satelliteModel.html\">satellite macro model</a>. The second one uses a transient temperature model with a temporal differential equation which disallows parallel computing. The <strong class=\"groops-config-element\">factorThermalRadiation</strong> can be used to scale the computed acceleration of the TRP.</p><p>The algorithms are described in:</p><p>Woeske et. al. (2019), GRACE accelerometer calibration by high precision non-gravitational force modeling, Advances in Space Research, <a href=\"https://doi.org/10.1016/j.asr.2018.10.025\" target=\"_blank\">https://doi.org/10.1016/j.asr.2018.10.025</a>.  <h2 id=\"atmosphericDrag\">AtmosphericDrag</h2><p> Atmospheric drag model. Algorithm for the atmospheric drag modelling is based on the free molecule flow theory by Sentman 1961. An analytical expression of this treatise is given in Moe and Moe 2005.</p><p>Sentman L. (1961), Free molecule flow theory and its application to the determination of aerodynamic forces, Technical report.</p><p>Moe K., Moe M. M. (2005), Gas-surface interactions and satellite drag coefficients, Planetary and Space Science 53(8), 793-801, doi:10.1016/j.pss.2005.03.005.</p><p>Optional determination steps: Turn temperature on or off. In the first case, the model mentioned above is applied, which estimates variable drag and lift coefficients - in the latter case a constant drag coefficient can be specified.</p><p>Turn wind on/off: It enables the usage of the Horizontal Wind Model 2014 to add additional thermospheric winds in the calculation process.  <h2 id=\"atmosphericDragFromDensityFile\">AtmosphericDragFromDensityFile</h2><p> Atmospheric drag computed from thermospheric density along the orbit (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileDensity</a>, MISCVALUE). The <a class=\"groops-class\" href=\"thermosphereType.html\">thermosphere</a> is used to to compute temperature and wind. For further details see <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">atmosphericDrag</a>.  <h2 id=\"antennaThrust\">Antenna thrust</h2><p> The thrust (acceleration) in the opposite direction the antenna is facing which is generated by satellite antenna broadcasts. The thrust is defined in the satellite macro model.  <h2 id=\"fromParametrization\">FromParametrization</h2><p> Reads a solution vector from file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a> which may be computed by a least squares adjustment (e.g. by <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>). The coefficients of the vector are interpreted from position <strong class=\"groops-config-element\">indexStart</strong> (counting from zero) with help of <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrization</a>. If the solution file contains solution of several right hand sides you can choose one with number <strong class=\"groops-config-element\">rightSide</strong> (counting from zero).</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"group\">Group</h2><p> Groups a set of <a class=\"groops-class\" href=\"miscAccelerationsType.html\">miscAccelerations</a> and has no further effect itself.  <h2 id=\"solarRadiationPressure\">SolarRadiationPressure</h2><p> DEPRECATED since 2022-12-19. Use radiationPressure instead.  <h2 id=\"albedo\">Albedo</h2><p> DEPRECATED since 2022-12-19. Use radiationPressure instead.'},\n'noiseGeneratorType': { 'name': 'noiseGeneratorType', 'key': 'noiseGeneratorType', 'description': 'This class implements the generation of different types of noise. It provides a generic interface that can be implemented by different types of generators. The characteristics of the generated noise is determined by the generators. See the appropriate documentation for more information.     The noise is Gaussian with a standard deviation  sigma . The noise is computed via a pseudo random sequence with a start value given by  initRandom . The same value always yields the same sequence. Be careful in  parallel  mode as all nodes generates the same pseudo random sequence. If this value is set to zero a real random value is used as starting value.     This generator creates noise defined by a one sided PSD. The  psd  is an expression controlled by the variable \\'freq\\'. To determine the frequency  sampling  must be given.     Generated noise     is filtered by a    .     This generator creates noise that conforms to a power law relationship, where the power of the noise at a frequency is proportional to  , with a typically between -2 and 2.', 'config_table': 'sigma double standard deviation initRandom uint start value for pseudo random sequence, 0: real random noise noiseGeneratorType Basis noise psd expression one sided PSD (variable: freq [Hz]) [unit^2/Hz] sampling double to determine frequency [seconds] filter digitalFilterType digital filter noise noiseGeneratorType Basis noise warmupEpochCount uint number of additional epochs at before start and after end overSamplingFactor uint noise with multiple higher sampling -> filter -> decimate noise noiseGeneratorType Basis noise alpha double Exponent of the power law relationship 1/f^alpha', 'display_text': 'This class implements the generation of different types of noise. It provides a generic interface that can be implemented by different types of generators. The characteristics of the generated noise is determined by the generators. See the appropriate documentation for more information.  <h2>White</h2><p> The noise is Gaussian with a standard deviation <strong class=\"groops-config-element\">sigma</strong>. The noise is computed via a pseudo random sequence with a start value given by <strong class=\"groops-config-element\">initRandom</strong>. The same value always yields the same sequence. Be careful in <a class=\"groops-ref\" href=\"general.parallelization.html\">parallel</a> mode as all nodes generates the same pseudo random sequence. If this value is set to zero a real random value is used as starting value.  <h2>ExpressionPSD</h2><p> This generator creates noise defined by a one sided PSD. The <strong class=\"groops-config-element\">psd</strong> is an expression controlled by the variable \\'freq\\'. To determine the frequency <strong class=\"groops-config-element\">sampling</strong> must be given.  <h2>Filter</h2><p> Generated noise <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noise</a> is filtered by a <a class=\"groops-class\" href=\"digitalFilterType.html\">filter</a>.  <h2>PowerLaw</h2><p> This generator creates noise that conforms to a power law relationship, where the power of the noise at a frequency is proportional to $1/f^\\\\alpha$, with a typically between -2 and 2.'},\n'normalEquationType': { 'name': 'normalEquationType', 'key': 'normalEquationType', 'description': 'This class provides a system of normal equations. This total system is the weighted sum of individual normals.  The normals do not need to have the same dimension. The dimension of the total combined system is chosen to cover all individual systems. For each normal a  startIndex  is required which indicates the position of the first unknown of the individual normal within the combined parameter vector. The   of the relative weights are defined by  aprioriSigma  in a first step. If an apriori solution     is given or the normals are solved iteratively the weights are determined by means of variance compoment estimation (VCE), see  NormalsSolverVCE :  where   is the number of observations. The square sum of the residuals is calculated by  The system of normal equations can be solved with several right hand sides at once. But only one right hand side, which can be selected with the index  rightHandSide  (counting from zero), can be used to compute the variance factors. The combined normal   and the solution   are taken from the previous iteration step. In case of     the algorithm is a little bit different as described below.     This class acculumates normal equations from observation equations. The class     computes the linearized and decorrelated equation system for each arc  :  The arc depending parameters   are eliminated and the system of normal equations is acculumated according to      This class acculumates normal equations from observation equations. The class     computes the linearized and decorrelated equation system for each arc  :  The arc depending parameters   are eliminated and the system of normal equations is acculumated according to  The variance   of each individual arc is determined by  where   is the number of observations. If an apriori solution is not given at the first iteration step a zero vector is assumed.     Reads a system of normal equations from file     as generated by e.g.  NormalsBuild .     Set up a system of normal equations  where   is a diagonal matrix whose elements are given as a vector by     and   is the right hand side towards which will be regularized. It can be given by    . The diagonal matrix can be generated with  NormalsRegularizationBorders ,  NormalsRegularizationSphericalHarmonics , or  MatrixCalculate . If   is not given a unit matrix is assumed. The right hand side   may be generated with  Gravityfield2SphericalHarmonicsVector . If   is not given a zero vector is assumed.    Generalized regularization which is represented by the observation equation   There are no requirements for partial covariance matrices   except for them being symmetric. The accumulated covariance matrix   must be positive definite however. The variance components   are estimated during the adjustment process and are assumed to be positive. All     must be of same size and must match the dimension of     (if provided, otherwise a zero vector of appropriate dimensions is created). The parameter  aprioriSigma  determines the initial variance factor for the partial covariance matrices. Either one   can be supplied or one for each  . The regularization matrix can be applied to a subset of parameters by adjusting  startIndex .', 'config_table': 'observation observationType  aprioriSigma double  startIndex uint add this normals at index of total matrix (counting from 0) inputfileArcList filename to accelerate computation observation observationType  startIndex uint add this normals at index of total matrix (counting from 0) inputfileArcList filename to accelerate computation inputfileNormalEquation filename  aprioriSigma double  startIndex uint add this normals at index of total matrix (counting from 0) inputfileDiagonalMatrix filename Vector with the diagonal elements of the weight matrix inputfileBias filename Matrix with right hand sides aprioriSigma double  startIndex uint regularization of parameters starts at this index (counting from 0) inputfilePartialCovarianceMatrix filename symmetric matrix (sum of all matrices must be positive definite) inputfileBiasMatrix filename bias vector (default: zero vector) aprioriSigma double apriori sigmas for initial iteration (default: 1.0) startIndex uint regularization of parameters starts at this index (counting from 0)', 'display_text': 'This class provides a system of normal equations. This total system is the weighted sum of individual normals. \\\\[  \\\\M N_{total} =  \\\\sum_{k=1} \\\\frac{1}{\\\\sigma_k^2}\\\\M N_k  \\\\qquad\\\\text{and}\\\\qquad \\\\M n_{total} = \\\\sum_{k=1} \\\\frac{1}{\\\\sigma_k^2} \\\\M n_k. \\\\]The normals do not need to have the same dimension. The dimension of the total combined system is chosen to cover all individual systems. For each normal a <strong class=\"groops-config-element\">startIndex</strong> is required which indicates the position of the first unknown of the individual normal within the combined parameter vector.</p><p>The $\\\\sigma_k$ of the relative weights are defined by <strong class=\"groops-config-element\">aprioriSigma</strong> in a first step. If an apriori solution <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileApproxSolution</a> is given or the normals are solved iteratively the weights are determined by means of variance compoment estimation (VCE), see <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>: \\\\[ \\\\sigma_k^2 = \\\\frac{\\\\M e_k^T\\\\M P\\\\M e_k} {n_k-\\\\frac{1}{\\\\sigma_k^2}\\\\text{trace}\\\\left(\\\\M N_k\\\\M N_{total}^{-1}\\\\right)}, \\\\]where $n_k$ is the number of observations. The square sum of the residuals is calculated by \\\\[ \\\\M e_k^T\\\\M P\\\\M e_k = \\\\M x^T\\\\M N_k\\\\M x - 2\\\\M n_k^T\\\\M x + \\\\M l_k^T\\\\M P_k\\\\M l_k. \\\\]The system of normal equations can be solved with several right hand sides at once. But only one right hand side, which can be selected with the index <strong class=\"groops-config-element\">rightHandSide</strong> (counting from zero), can be used to compute the variance factors. The combined normal $\\\\M N_{total}$ and the solution $\\\\M x$ are taken from the previous iteration step. In case of <a class=\"groops-class\" href=\"normalEquationType.html#designVCE\">DesignVCE</a> the algorithm is a little bit different as described below.  <h2 id=\"design\">Design</h2><p> This class acculumates normal equations from observation equations. The class <a class=\"groops-class\" href=\"observationType.html\">observation</a> computes the linearized and decorrelated equation system for each arc $i$: \\\\[ \\\\M l_i  = \\\\M A_i \\\\M x + \\\\M B_i \\\\M y_i + \\\\M e_i. \\\\]The arc depending parameters $\\\\M y_i$ are eliminated and the system of normal equations is acculumated according to \\\\[  \\\\M N = \\\\sum_{i=1}^m \\\\M A_i^T  \\\\M A_i  \\\\qquad\\\\text{and}\\\\qquad \\\\M n = \\\\sum_{i=1}^m \\\\M A_i^T \\\\M l_i. \\\\] <h2 id=\"designVCE\">DesignVCE</h2><p> This class acculumates normal equations from observation equations. The class <a class=\"groops-class\" href=\"observationType.html\">observation</a> computes the linearized and decorrelated equation system for each arc $i$: \\\\[ \\\\M l_i  = \\\\M A_i \\\\M x + \\\\M B_i \\\\M y_i + \\\\M e_i. \\\\]The arc depending parameters $\\\\M y_i$ are eliminated and the system of normal equations is acculumated according to \\\\[  \\\\M N =  \\\\sum_{i=1} \\\\frac{1}{\\\\sigma_i^2}\\\\M A_i^T  \\\\M A_i  \\\\qquad\\\\text{and}\\\\qquad \\\\M n = \\\\sum_{i=1} \\\\frac{1}{\\\\sigma_i^2} \\\\M A_i^T \\\\M l_i. \\\\]The variance $\\\\sigma_i^2$ of each individual arc is determined by \\\\[ \\\\sigma_i^2 = \\\\frac{(\\\\M l_i-\\\\M A_i\\\\M x)^T(\\\\M l_i-\\\\M A_i\\\\M x)} {n_i-\\\\frac{1}{\\\\sigma_i^2}\\\\text{trace}\\\\left(\\\\M A_i^T  \\\\M A_i\\\\M N_{total}^{-1}\\\\right)}, \\\\]where $n_i$ is the number of observations. If an apriori solution is not given at the first iteration step a zero vector is assumed.  <h2 id=\"file\">File</h2><p> Reads a system of normal equations from file <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a> as generated by e.g. <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>.  <h2 id=\"regularization\">Regularization</h2><p> Set up a system of normal equations \\\\[ \\\\M N = \\\\M R \\\\qquad\\\\text{and}\\\\qquad \\\\M n = \\\\M R \\\\M b, \\\\]where $\\\\M R$ is a diagonal matrix whose elements are given as a vector by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDiagonalMatrix</a> and $\\\\M b$ is the right hand side towards which will be regularized. It can be given by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileBiasVector</a>. The diagonal matrix can be generated with <a class=\"groops-program\" href=\"NormalsRegularizationBorders.html\">NormalsRegularizationBorders</a>, <a class=\"groops-program\" href=\"NormalsRegularizationSphericalHarmonics.html\">NormalsRegularizationSphericalHarmonics</a>, or <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>. If $\\\\M R$ is not given a unit matrix is assumed. The right hand side $\\\\M b$ may be generated with <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a>. If $\\\\M b$ is not given a zero vector is assumed.  <h2>RegularizationGeneralized</h2><p></p><p>Generalized regularization which is represented by the observation equation \\\\[ \\\\mathbf{x}_0 = \\\\mathbf{I} \\\\mathbf{x} + \\\\mathbf{v}, \\\\mathbf{v} \\\\sim \\\\mathcal{N}(0, \\\\sum_k \\\\sigma^2_k \\\\mathbf{V}_k). \\\\] There are no requirements for partial covariance matrices $\\\\mathbf{V}_k$ except for them being symmetric. The accumulated covariance matrix $\\\\sum_k \\\\sigma^2_k \\\\mathbf{V}_k$ must be positive definite however. The variance components $\\\\sigma^2_k$ are estimated during the adjustment process and are assumed to be positive. All <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePartialCovarianceMatrix</a> must be of same size and must match the dimension of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileBiasMatrix</a> (if provided, otherwise a zero vector of appropriate dimensions is created).</p><p>The parameter <strong class=\"groops-config-element\">aprioriSigma</strong> determines the initial variance factor for the partial covariance matrices. Either one $\\\\sigma_0$ can be supplied or one for each $\\\\mathbf{V}_k$.</p><p>The regularization matrix can be applied to a subset of parameters by adjusting <strong class=\"groops-config-element\">startIndex</strong>.'},\n'observationType': { 'name': 'observationType', 'key': 'observationType', 'description': 'This class sets up the observation equations in linearized Gauss-Markov model  The observations are divided into short data blocks which can be computed independently and so easily can be parallelized. Usually these data blocks are short arcs of a satellite\\'s orbit. In most cases the unknown parameter vector contains coefficients of a gravity field parametrization given by    . Additional parameters like instrument calibration parameters are appended at the end of the vector  . It is possible to give several observation vectors in one model. The observations within each arc are decorrelated in the following way: In a first step a Cholesky decomposition of the covariance matrix is performed  where   is an upper regular triangular matrix. In a second step the transformation  gives an estimation from decorrelated observations with equal variance  Usually the arc dependent parameters are eliminated in the next step and not mentioned for the parameter names in the following.     The observation equations for precise orbit data (POD) are formulated as variational equations. It is based on  inputfileVariational  calculated with  PreprocessingVariationalEquation . Necessary integrations are performed by integrating a moving interpolation polynomial of degree  integrationDegree . The kinematic positions as pseudo observations are taken from  rightHandSide  and should not be given equally spaced in time. The observation equations are interpolated to these times by a moving polynomial of degree  interpolationDegree . The accuracy or the full covariance matrix of the precise orbit data is provided in     and can be estimated with  PreprocessingPod . accelerateComputation : In the event that the sampling of the kinematic orbit is much higher than the sampling of the variational equations (e.g. 1 second vs. 5 seconds) the accumulation of the observation equations can be accelerated by transforming the observation equations  where   describes the interpolation of the sampling of the variational design matrix   to the sampling of the observations   with more rows than columns. The QR decomposition  can be used to transform the observation equations  As the zero lines should not be considered, the computational time for the accumulation is reduced. This option is not meaningful for evaluating the residuals such as in  PreprocessingPod . The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  &lt;satellite>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;satellite>:arc&lt;no>.position0.x:: ,  &lt;satellite>:arc&lt;no>.position0.y:: ,  &lt;satellite>:arc&lt;no>.position0.z:: .  &lt;satellite>:arc&lt;no>.velocity0.x:: ,  &lt;satellite>:arc&lt;no>.velocity0.y:: ,  &lt;satellite>:arc&lt;no>.velocity0.z:: .       The observation equations for precise orbit data (POD) of short arcs are given by  with the integral kernel  and the normalized time  The kinematic positions   as pseudo observations are taken from    . From these positions the influence of the reference forces   is subtracted which are computed with the background models in    . The integral is solved by the integration of a moving interpolation polynomial of degree  integrationDegree . The boundary values   and   (satellite\\'s state vector) are estimated per arc and are usually directly eliminated if  keepSatelliteStates  is not set. The unknown gravity field   parametrized by     is not evaluated at the observed positions but at the orbit given by    . The same is true for the reference forces. The linearized effect of the gravity field change by the position adjustment is taken into account by  gradientfield . This may be a low order field up to a spherical harmonics degree of   or  . The    ,    , and     must be synchronous and must be given with a constant sampling and without any gaps in each short arc (see  InstrumentSynchronize ). The kinematic positions   should not given equally spaced in time but must be divided into the same arcs as the other instrument data. The observation equations are interpolated to this time by a polynomial interpolation with degree  interpolationDegree . The accuracy or the full covariance matrix of the precise orbit data is provided in     and can be estimated with  PreprocessingPod . For  accelerateComputation  see    . The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  &lt;satellite>:&lt;parametrizationAcceleration>:*:* ,   and for each arc if  keepSatelliteStates  is set    &lt;satellite>:arc&lt;no>.position.start.x:: ,  &lt;satellite>:arc&lt;no>.position.start.y:: ,  &lt;satellite>:arc&lt;no>.position.start.z:: .  &lt;satellite>:arc&lt;no>.position.end.x:: ,  &lt;satellite>:arc&lt;no>.position.end.y:: ,  &lt;satellite>:arc&lt;no>.position.end.z:: .       The observation equations for precise orbit data (POD) are given by  where the accelerations of the satellite   are derived from the kinematic positions in    . The orbit differentation is performed by a moving polynomial interpolation or approximation with degree  interpolationDegree  and number of used epochs  numberOfEpochs . The reference forces   are computed with the background models in    . All instrument data    ,    , and     must be synchronous and be given with a constant sampling without any gaps in each short arc (see  InstrumentSynchronize ). The unknown gravity field   parametrized by     is not evaluated at the observed positions but at the orbit given by    . The same is true for the reference forces. This orbit may be a more accurate dynamical orbit but in most cases the kinematic orbit provides good results. The accuracy or the full covariance matrix of the precise orbit data is provided in     and can be estimated with  PreprocessingPod . The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  &lt;satellite>:&lt;parametrizationAcceleration>:*:* .       The observation equations for precise orbit data (POD) are given by  where the velocities of the satellite   are derived from the kinematic positions in     and the Earth\\'s rotation vector   is modeled within    . The orbit differentiation is performed by a polynomial interpolation with degree  interpolationDegree . The integrals are solved by a polynomial interpolation with degree  integrationDegree . The reference forces   are computed with the background models in    . All instrument data    ,    , and     must be synchronous and be given with a constant sampling without any gaps in each short arc (see  InstrumentSynchronize ). The unknown gravity potential   parametrized by     is not evaluated at the observed positions but at the orbit given by    . The same is true for the reference forces. This orbit may be a more accurate dynamical orbit but in most cases the kinematic orbit provides good results. An unknown energy bias   per arc is parametrized by     and should be a constant in theory but temporal changes might help to absorb other unmodelled effects. The accuracy or the full covariance matrix of the precise orbit data is provided in     and can be estimated with  PreprocessingPod . The following parameters with  parameter names  are set up:  *:&lt;parametrizationGravity>:*:* .     Like     (see there for details) but with two satellites and additional satellite-to-satellite (SST) observations. If multiple     are given, all data are added together. So corrections in extra files like the light time correction can easily be added. Empirical parameters for the SST observations can be set up with    . The accuracy or the full covariance matrix of SST is provided in    . The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  &lt;satellite1>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite1>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;satellite1>:arc&lt;no>.position0.x:: ,  &lt;satellite1>:arc&lt;no>.position0.y:: ,  &lt;satellite1>:arc&lt;no>.position0.z:: .  &lt;satellite1>:arc&lt;no>.velocity0.x:: ,  &lt;satellite1>:arc&lt;no>.velocity0.y:: ,  &lt;satellite1>:arc&lt;no>.velocity0.z:: .  &lt;satellite2>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite2>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;satellite2>:arc&lt;no>.position0.x:: ,  &lt;satellite2>:arc&lt;no>.position0.y:: ,  &lt;satellite2>:arc&lt;no>.position0.z:: .  &lt;satellite2>:arc&lt;no>.velocity0.x:: ,  &lt;satellite2>:arc&lt;no>.velocity0.y:: ,  &lt;satellite2>:arc&lt;no>.velocity0.z:: .  &lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking>:*:* .       Like     (see there for details) but with two satellites and additional satellite-to-satellite (SST) observations. If multiple     are given all data are added together. So corrections in extra files like the light time correction can easily be added. Empirical parameters for the SST observations can be set up with    . The accuracy or the full covariance matrix of SST is provided in    . The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  &lt;satellite1>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite2>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking>:*:* ,   and for each arc if  keepSatelliteStates  is set    &lt;satellite1>:arc&lt;no>.position.start.x:: ,  &lt;satellite1>:arc&lt;no>.position.start.y:: ,  &lt;satellite1>:arc&lt;no>.position.start.z:: .  &lt;satellite1>:arc&lt;no>.position.end.x:: ,  &lt;satellite1>:arc&lt;no>.position.end.y:: ,  &lt;satellite1>:arc&lt;no>.position.end.z:: .  &lt;satellite2>:arc&lt;no>.position.start.x:: ,  &lt;satellite2>:arc&lt;no>.position.start.y:: ,  &lt;satellite2>:arc&lt;no>.position.start.z:: .  &lt;satellite2>:arc&lt;no>.position.end.x:: ,  &lt;satellite2>:arc&lt;no>.position.end.y:: ,  &lt;satellite2>:arc&lt;no>.position.end.z:: .       Like     (see there for details) but with two simultaneous satellite-to-satellite (SST) observations. This class reads two SST observation files (    and    ). Empirical parameters for the SST observations can be set up independently for both SST observation types with     and    . Both SST observation types are reduced by the same background models and the same impact of accelerometer measurements. The covariance matrix of the reduced observations should not consider the instrument noise only (   ) but must take the cross correlations     into account. The covariance matrix of the reduced observations is given by   The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  &lt;satellite1>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite1>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;satellite1>:arc&lt;no>.position0.x:: ,  &lt;satellite1>:arc&lt;no>.position0.y:: ,  &lt;satellite1>:arc&lt;no>.position0.z:: .  &lt;satellite1>:arc&lt;no>.velocity0.x:: ,  &lt;satellite1>:arc&lt;no>.velocity0.y:: ,  &lt;satellite1>:arc&lt;no>.velocity0.z:: .  &lt;satellite2>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite2>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;satellite2>:arc&lt;no>.position0.x:: ,  &lt;satellite2>:arc&lt;no>.position0.y:: ,  &lt;satellite2>:arc&lt;no>.position0.z:: .  &lt;satellite2>:arc&lt;no>.velocity0.x:: ,  &lt;satellite2>:arc&lt;no>.velocity0.y:: ,  &lt;satellite2>:arc&lt;no>.velocity0.z:: .  &lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking1>:*:* .  &lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking2>:*:* .       Observation equations for satellite gravity gradiometry (SGG)  From the     observations precomputed     together with other background models are reduced, all given in    . All instrument data    ,    , and     must be synchronous and be diveded into each short arcs (see  InstrumentSynchronize ). Additional to the     an (temporal changing) bias for each gradiometer component and arc can be estimated with    . The accuracy or the full covariance matrix of the gradiometer is provided in  covarianceSgg  and can be estimated with  PreprocessingGradiometer . The following parameters with  parameter names  are set up:  *:&lt;parametrizationGravity>:*:* .     The gravity field is estimated from point wise measurements. The gravity field parametrization is given by    . There is no need to have the data regular distributed or given on a sphere or ellipsoid. The type of the gridded data (e.g gravity anomalies or geoid heights) must be set with    . A     can be reduced beforehand. The observations at given positions are calculated from    . The input columns are enumerated by  data0 ,  data1 ,  , see  dataVariables . The observations can be divided into small blocks for parallelization. With  blockingSize  set the maximum count of observations in each block. The following parameters with  parameter names  are set up:  *:&lt;parametrizationGravity>:*:* .     The gravity field parametrized by     is estimated from deflections of the vertical measurements. A     can be reduced beforehand. The observations   in north direction and   in east direction at given positions are calculated from    . The input columns are enumerated by  data0 ,  data1 ,  , see  dataVariables . The ellipsoid parameters  R  and  inverseFlattening  are used to define the local normal direction. The observations can be divided into small blocks for parallelization. With  blockingSize  set the maximum count of observations in each block. The following parameters with  parameter names  are set up:  *:&lt;parametrizationGravity>:*:* .     Observation equations for displacements of a list of stations due to the effect of time variable loading masses. The displacement   of a station is calculated according to  where   is the normal gravity, the load Love and Shida numbers   are given by     and the load Love numbers   are given by    . The   are the spherical harmonics expansion of degree   of the full time variable gravitational potential (potential of the loading mass + deformation potential) parametrized by    . Additional parameters can be setup to estimate the realization of the reference frame of the station coordinates ( estimateTranslation ,  estimateRotation , and  estimateScale ). The observations at stations coordinates are calculated from    . The input columns are enumerated by  data0 ,  data1 ,  , see  dataVariables . The ellipsoid parameters  R  and  inverseFlattening  are used to define the local frame (north, east, up). The following parameters with  parameter names  are set up:    *:&lt;parametrizationGravity>:*:* ,  *:translation.x:*:* ,  *:translation.y:*:* ,  *:translation.z:*:* ,  *:scale:*:* ,  *:rotation.x:*:* ,  *:rotation.y:*:* ,  *:rotation.z:*:* .  See also  Gravityfield2DisplacementTimeSeries . Reference: Rietbroek (2014): Retrieval of Sea Level and Surface Loading Variations from Geodetic Observations and Model Simulations: an Integrated Approach, Bonn, 2014. - Dissertation,  https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460', 'config_table': 'rightHandSide sequence input for observation vectors inputfileOrbit filename kinematic positions as observations inputfileVariational filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration parametrizationAccelerationType orbit force parameters integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n accelerateComputation boolean acceleration of computation by transforming the observations covariancePod covariancePodType covariance matrix of kinematic orbits inputfileSatelliteModel filename satellite macro model rightHandSide podRightSideType input for the reduced observation vector inputfileOrbit filename used to evaluate the observation equations, not used as observations inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  gradientfield gravityfieldType low order field to estimate the change of the gravity by position adjustement parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration parametrizationAccelerationType orbit force parameters keepSatelliteStates boolean set boundary values of each arc global integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n accelerateComputation boolean acceleration of computation by transforming the observations covariancePod covariancePodType covariance matrix of kinematic orbits inputfileSatelliteModel filename satellite macro model rightHandSide podRightSideType input for the reduced observation vector inputfileOrbit filename used to evaluate the observation equations, not used as observations inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration parametrizationAccelerationType orbit force parameters interpolationDegree uint orbit differentation  by polynomial approximation of degree n numberOfEpochs uint number of used Epochs for polynom computation covariancePod covariancePodType covariance matrix of kinematic orbits inputfileSatelliteModel filename satellite macro model rightHandSide podRightSideType input for the reduced observation vector inputfileOrbit filename used to evaluate the observation equations, not used as observations inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization (potential) parametrizationBias parametrizationTemporalType unknown total energy per arc interpolationDegree uint orbit differentiation  by polynomial approximation of degree n integrationDegree uint integration of forces by polynomial approximation of degree n covariancePod covariancePodType covariance matrix of kinematic orbits rightHandSide sequence input for observation vectors inputfileSatelliteTracking filename ranging observations and corrections inputfileOrbit1 filename kinematic positions of satellite A as observations inputfileOrbit2 filename kinematic positions of satellite B as observations sstType choice  range   rangeRate   none   inputfileVariational1 filename approximate position and integrated state matrix inputfileVariational2 filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst parametrizationSatelliteTrackingType satellite tracking parameter integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n covarianceSst covarianceSstType covariance matrix of satellite to satellite tracking observations covariancePod1 covariancePodType covariance matrix of kinematic orbits (satellite 1) covariancePod2 covariancePodType covariance matrix of kinematic orbits (satellite 2) inputfileSatelliteModel1 filename satellite macro model inputfileSatelliteModel2 filename satellite macro model rightHandSide sstRightSideType input for the reduced observation vector sstType choice  range   rangeRate   rangeAcceleration   none   inputfileOrbit1 filename used to evaluate the observation equations, not used as observations inputfileOrbit2 filename used to evaluate the observation equations, not used as observations inputfileStarCamera1 filename  inputfileStarCamera2 filename  earthRotation earthRotationType  ephemerides ephemeridesType  gradientfield gravityfieldType low order field to estimate the change of the gravity by position adjustement parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst parametrizationSatelliteTrackingType satellite tracking parameter keepSatelliteStates boolean set boundary values of each arc global integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n covarianceSst covarianceSstType covariance matrix of satellite to satellite tracking observations covariancePod1 covariancePodType covariance matrix of kinematic orbits (satellite 1) covariancePod2 covariancePodType covariance matrix of kinematic orbits (satellite 2) rightHandSide sequence input for observation vectors inputfileSatelliteTracking1 filename ranging observations and corrections inputfileSatelliteTracking2 filename ranging observations and corrections inputfileOrbit1 filename kinematic positions of satellite A as observations inputfileOrbit2 filename kinematic positions of satellite B as observations sstType choice  range   rangeRate   none   inputfileVariational1 filename approximate position and integrated state matrix inputfileVariational2 filename approximate position and integrated state matrix ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType gravity field parametrization parametrizationAcceleration1 parametrizationAccelerationType orbit1 force parameters parametrizationAcceleration2 parametrizationAccelerationType orbit2 force parameters parametrizationSst1 parametrizationSatelliteTrackingType satellite tracking parameter for first ranging observations parametrizationSst2 parametrizationSatelliteTrackingType satellite tracking parameter for second ranging observations integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint orbit interpolation by polynomial approximation of degree n covarianceSst1 covarianceSstType covariance matrix of first satellite to satellite tracking observations covarianceSst2 covarianceSstType covariance matrix of second satellite to satellite tracking observations covarianceAcc covarianceSstType common covariance matrix of reduced satellite to satellite tracking observations covariancePod1 covariancePodType covariance matrix of kinematic orbits (satellite 1) covariancePod2 covariancePodType covariance matrix of kinematic orbits (satellite 2) rightHandSide sggRightSideType input for the observation vector inputfileOrbit filename  inputfileStarCamera filename  earthRotation earthRotationType  ephemerides ephemeridesType  parametrizationGravity parametrizationGravityType  parametrizationBias parametrizationTemporalType per arc useXX boolean  useYY boolean  useZZ boolean  useXY boolean  useXZ boolean  useYZ boolean  covarianceSgg sequence  sigma double general variance factor inputfileSigmasPerArc filename different accuaries for each arc (multplicated with sigma) inputfileCovarianceFunction filename covariance function in time rightHandSide sequence input for observation vectors inputfileGriddedData filename  observation expression [SI units] sigma expression accuracy, 1/sigma used as weighting referencefield gravityfieldType  kernel kernelType type of observations parametrizationGravity parametrizationGravityType  time time for reference field and parametrization blockingSize uint segementation of the obervations if designmatrix can\\'t be build at once rightHandSide sequence input for observation vectors inputfileGriddedData filename  observationXi expression North-South Deflections of the Vertical [rad] observationEta expression East-West Deflections of the Vertical  [rad] sigmaXi expression accuracy, 1/sigma used as weighting sigmaEta expression accuracy, 1/sigma used as weighting referencefield gravityfieldType  parametrizationGravity parametrizationGravityType  time time for reference field and parametrization R double reference radius for ellipsoid inverseFlattening double reference flattening for ellipsoid, 0: sphere blockingSize uint segementation of the obervations if designmatrix can\\'t be build at once rightHandSide sequence input for observation vectors inputfileGriddedData filename station positions with displacement data observationNorth expression displacement [m] observationEast expression displacement [m] observationUp expression displacement [m] sigmaNorth expression accuracy, 1/sigma used as weighting sigmaEast expression accuracy, 1/sigma used as weighting sigmaUp expression accuracy, 1/sigma used as weighting inGlobalFrame boolean obs/sigmas given in global x,y,z frame instead of north,east,up referencefield gravityfieldType  time time for reference field and parametrization parametrizationGravity parametrizationGravityType of loading (+defo) potential estimateTranslation boolean coordinate center estimateScale boolean scale factor of position estimateRotation boolean rotation inputfileDeformationLoadLoveNumber filename  inputfilePotentialLoadLoveNumber filename if full potential is given and not only loading potential R double reference radius for ellipsoid inverseFlattening double reference flattening for ellipsoid, 0: sphere', 'display_text': 'This class sets up the observation equations in linearized Gauss-Markov model \\\\[\\\\label{gmm} \\\\M l  = \\\\M A \\\\M x + \\\\M e\\\\qquad\\\\text{and}\\\\qquad\\\\mathcal{C}(\\\\M e) = \\\\sigma^2\\\\M P^{-1}. \\\\]The observations are divided into short data blocks which can be computed independently and so easily can be parallelized. Usually these data blocks are short arcs of a satellite\\'s orbit. In most cases the unknown parameter vector contains coefficients of a gravity field parametrization given by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>. Additional parameters like instrument calibration parameters are appended at the end of the vector $\\\\M x$. It is possible to give several observation vectors in one model.</p><p>The observations within each arc are decorrelated in the following way: In a first step a Cholesky decomposition of the covariance matrix is performed \\\\[ \\\\M P^{-1} = \\\\M W^T\\\\M W, \\\\]where $\\\\M W$ is an upper regular triangular matrix. In a second step the transformation \\\\[\\\\label{dekorrelierung} \\\\bar{\\\\M A} = \\\\M W^{-T}\\\\M A\\\\qquad\\\\text{and}\\\\qquad \\\\bar{\\\\M l} = \\\\M W^{-T}\\\\M l \\\\]gives an estimation from decorrelated observations with equal variance \\\\[\\\\label{normal.GMM} \\\\bar{\\\\M l} = \\\\bar{\\\\M A} \\\\M x + \\\\bar{\\\\M e} \\\\qquad\\\\text{and}\\\\qquad \\\\mathcal{C}(\\\\bar{\\\\M e})= \\\\sigma^2 \\\\M I. \\\\]Usually the arc dependent parameters are eliminated in the next step and not mentioned for the parameter names in the following.  <h2 id=\"podVariational\">PodVariational</h2><p> The observation equations for precise orbit data (POD) are formulated as variational equations. It is based on <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> calculated with <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>. Necessary integrations are performed by integrating a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>.</p><p>The kinematic positions as pseudo observations are taken from <strong class=\"groops-config-element\">rightHandSide</strong> and should not be given equally spaced in time. The observation equations are interpolated to these times by a moving polynomial of degree <strong class=\"groops-config-element\">interpolationDegree</strong>.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p><strong class=\"groops-config-element\">accelerateComputation</strong>: In the event that the sampling of the kinematic orbit is much higher than the sampling of the variational equations (e.g. 1 second vs. 5 seconds) the accumulation of the observation equations can be accelerated by transforming the observation equations \\\\[   \\\\M l = \\\\M J \\\\M A \\\\M x + \\\\M e, \\\\]where $\\\\M J$ describes the interpolation of the sampling of the variational design matrix $\\\\M A$ to the sampling of the observations $\\\\M l$ with more rows than columns. The QR decomposition \\\\[   \\\\M J = \\\\begin{pmatrix} \\\\M Q_1 & \\\\M Q_2 \\\\end{pmatrix}          \\\\begin{pmatrix} \\\\M R \\\\\\\\ \\\\M 0 \\\\end{pmatrix}. \\\\]can be used to transform the observation equations \\\\[   \\\\begin{pmatrix} \\\\M Q_1^T \\\\M l \\\\\\\\ \\\\M Q_2^T \\\\M l \\\\end{pmatrix} =   \\\\begin{pmatrix} \\\\M Q_1^T \\\\M R \\\\\\\\ \\\\M 0 \\\\end{pmatrix} \\\\M A \\\\M x +   \\\\begin{pmatrix} \\\\M Q_1^T \\\\M e \\\\\\\\ \\\\M Q_2^T \\\\M e \\\\end{pmatrix}. \\\\]As the zero lines should not be considered, the computational time for the accumulation is reduced. This option is not meaningful for evaluating the residuals such as in <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;satellite>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.velocity0.z::</code>. </li></ul>   <h2 id=\"podIntegral\">PodIntegral</h2><p> The observation equations for precise orbit data (POD) of short arcs are given by \\\\[   {\\\\M r}_\\\\epsilon(\\\\tau) = {\\\\M r}_A(1-\\\\tau) + {\\\\M r}_B\\\\tau - T^2\\\\int_0^1 K(\\\\tau,\\\\tau\\')   \\\\left(\\\\M f_0(\\\\tau\\')+\\\\nabla V(\\\\tau\\')\\\\right)\\\\,d\\\\tau\\' \\\\]with the integral kernel \\\\[   K(\\\\tau,\\\\tau\\') = \\\\begin{cases} \\\\tau\\'(1-\\\\tau) & \\\\text{for }\\\\tau\\'\\\\le\\\\tau \\\\\\\\   \\\\tau(1-\\\\tau\\') & \\\\text{for }\\\\tau\\'>\\\\tau \\\\end{cases}, \\\\]and the normalized time \\\\[   \\\\tau = \\\\frac{t-t_A}{T}\\\\qquad\\\\text{with}\\\\qquad T=t_B-t_A. \\\\]The kinematic positions ${\\\\M r}_\\\\epsilon(\\\\tau)$ as pseudo observations are taken from <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>. From these positions the influence of the reference forces $\\\\M f_0(\\\\tau)$ is subtracted which are computed with the background models in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>. The integral is solved by the integration of a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>. The boundary values ${\\\\M r}_A$ and ${\\\\M r}_B$ (satellite\\'s state vector) are estimated per arc and are usually directly eliminated if <strong class=\"groops-config-element\">keepSatelliteStates</strong> is not set.</p><p>The unknown gravity field $\\\\nabla V(\\\\M r, t)$ parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a> is not evaluated at the observed positions but at the orbit given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. The same is true for the reference forces. The linearized effect of the gravity field change by the position adjustment is taken into account by <strong class=\"groops-config-element\">gradientfield</strong>. This may be a low order field up to a spherical harmonics degree of $n=2$ or $n=3$.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> must be synchronous and must be given with a constant sampling and without any gaps in each short arc (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>). The kinematic positions ${\\\\M r}_\\\\epsilon(\\\\tau)$ should not given equally spaced in time but must be divided into the same arcs as the other instrument data. The observation equations are interpolated to this time by a polynomial interpolation with degree <strong class=\"groops-config-element\">interpolationDegree</strong>.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>For <strong class=\"groops-config-element\">accelerateComputation</strong> see <a class=\"groops-class\" href=\"observationType.html#podVariational\">observation:podVariational</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>, </li></ul>  and for each arc if <strong class=\"groops-config-element\">keepSatelliteStates</strong> is set <ul>  <li><code>&lt;satellite>:arc&lt;no>.position.start.x::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position.start.y::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position.start.z::</code>. </li><li> <code>&lt;satellite>:arc&lt;no>.position.end.x::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position.end.y::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position.end.z::</code>. </li></ul>   <h2 id=\"podAcceleration\">PodAcceleration</h2><p> The observation equations for precise orbit data (POD) are given by \\\\[ \\\\ddot{\\\\M r}(t) - \\\\M g_0(t) = \\\\nabla V(\\\\M r, t), \\\\]where the accelerations of the satellite $\\\\ddot{\\\\M r}(t)$ are derived from the kinematic positions in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>. The orbit differentation is performed by a moving polynomial interpolation or approximation with degree <strong class=\"groops-config-element\">interpolationDegree</strong> and number of used epochs <strong class=\"groops-config-element\">numberOfEpochs</strong>. The reference forces $\\\\M g_0(t)$ are computed with the background models in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>.</p><p>All instrument data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> must be synchronous and be given with a constant sampling without any gaps in each short arc (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>The unknown gravity field $\\\\nabla V(\\\\M r, t)$ parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a> is not evaluated at the observed positions but at the orbit given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. The same is true for the reference forces. This orbit may be a more accurate dynamical orbit but in most cases the kinematic orbit provides good results.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>. </li></ul>   <h2 id=\"podEnergy\">PodEnergy</h2><p> The observation equations for precise orbit data (POD) are given by \\\\[   \\\\frac{1}{2}\\\\dot{\\\\M r}^2   -\\\\dot{\\\\M r} \\\\cdot (\\\\M\\\\Omega\\\\times\\\\M r)   +\\\\int_{t_0}^t(\\\\dot{\\\\M\\\\Omega}\\\\times\\\\M r)\\\\cdot \\\\dot{\\\\M r}\\\\,dt   - \\\\int_{t_0}^t \\\\M g_0 \\\\cdot\\\\dot{\\\\M r}\\'\\\\,dt   = V + E. \\\\]where the velocities of the satellite $\\\\dot{\\\\M r}(t)$ are derived from the kinematic positions in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a> and the Earth\\'s rotation vector $\\\\M\\\\Omega(t)$ is modeled within <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>. The orbit differentiation is performed by a polynomial interpolation with degree <strong class=\"groops-config-element\">interpolationDegree</strong>. The integrals are solved by a polynomial interpolation with degree <strong class=\"groops-config-element\">integrationDegree</strong>. The reference forces $\\\\M g_0(t)$ are computed with the background models in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>.</p><p>All instrument data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> must be synchronous and be given with a constant sampling without any gaps in each short arc (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>The unknown gravity potential $V(\\\\M r)$ parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a> is not evaluated at the observed positions but at the orbit given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>. The same is true for the reference forces. This orbit may be a more accurate dynamical orbit but in most cases the kinematic orbit provides good results.</p><p>An unknown energy bias $E$ per arc is parametrized by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationBias</a> and should be a constant in theory but temporal changes might help to absorb other unmodelled effects.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in <a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <code>*:&lt;parametrizationGravity>:*:*</code>.  <h2 id=\"sstVariational\">SstVariational</h2><p> Like <a class=\"groops-class\" href=\"observationType.html#podVariational\">observation:podVariational</a> (see there for details) but with two satellites and additional satellite-to-satellite (SST) observations.</p><p>If multiple <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a> are given, all data are added together. So corrections in extra files like the light time correction can easily be added. Empirical parameters for the SST observations can be set up with <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>. The accuracy or the full covariance matrix of SST is provided in <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>&lt;satellite1>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;satellite1>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.velocity0.z::</code>. </li><li> <code>&lt;satellite2>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;satellite2>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.velocity0.z::</code>. </li><li> <code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking>:*:*</code>. </li></ul>   <h2 id=\"sstIntegral\">SstIntegral</h2><p> Like <a class=\"groops-class\" href=\"observationType.html#podIntegral\">observation:podIntegral</a> (see there for details) but with two satellites and additional satellite-to-satellite (SST) observations.</p><p>If multiple <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a> are given all data are added together. So corrections in extra files like the light time correction can easily be added. Empirical parameters for the SST observations can be set up with <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>. The accuracy or the full covariance matrix of SST is provided in <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>&lt;satellite1>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite2>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking>:*:*</code>, </li></ul>  and for each arc if <strong class=\"groops-config-element\">keepSatelliteStates</strong> is set <ul>  <li><code>&lt;satellite1>:arc&lt;no>.position.start.x::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position.start.y::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position.start.z::</code>. </li><li> <code>&lt;satellite1>:arc&lt;no>.position.end.x::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position.end.y::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position.end.z::</code>. </li><li> <code>&lt;satellite2>:arc&lt;no>.position.start.x::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position.start.y::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position.start.z::</code>. </li><li> <code>&lt;satellite2>:arc&lt;no>.position.end.x::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position.end.y::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position.end.z::</code>. </li></ul>   <h2 id=\"dualSstVariational\">DualSstVariational</h2><p> Like <a class=\"groops-class\" href=\"observationType.html#sstVariational\">observation:sstVariational</a> (see there for details) but with two simultaneous satellite-to-satellite (SST) observations.</p><p>This class reads two SST observation files (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking1</a> and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking2</a>). Empirical parameters for the SST observations can be set up independently for both SST observation types with <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst1</a> and <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst2</a>.</p><p>Both SST observation types are reduced by the same background models and the same impact of accelerometer measurements. The covariance matrix of the reduced observations should not consider the instrument noise only (<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst1/2</a>) but must take the cross correlations <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceAcc</a> into account. The covariance matrix of the reduced observations is given by \\\\[   \\\\M\\\\Sigma(\\\\begin{bmatrix} \\\\Delta l_{SST1} \\\\\\\\ \\\\Delta l_{SST2} \\\\end{bmatrix})   = \\\\begin{bmatrix} \\\\M\\\\Sigma_{SST1} + \\\\M\\\\Sigma_{ACC} & \\\\M\\\\Sigma_{ACC} \\\\\\\\                    \\\\M\\\\Sigma_{ACC} & \\\\M\\\\Sigma_{SST2} + \\\\M\\\\Sigma_{ACC}     \\\\end{bmatrix}. \\\\] The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>&lt;satellite1>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;satellite1>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;satellite1>:arc&lt;no>.velocity0.z::</code>. </li><li> <code>&lt;satellite2>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;satellite2>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;satellite2>:arc&lt;no>.velocity0.z::</code>. </li><li> <code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking1>:*:*</code>. </li><li> <code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking2>:*:*</code>. </li></ul>   <h2 id=\"gradiometer\">Gradiometer</h2><p> Observation equations for satellite gravity gradiometry (SGG) \\\\[   \\\\nabla\\\\nabla V(\\\\M r) =   \\\\begin{pmatrix}     \\\\frac{\\\\partial^2 V}{\\\\partial x^2}         & \\\\frac{\\\\partial^2 V}{\\\\partial x\\\\partial y} & \\\\frac{\\\\partial^2 V}{\\\\partial x\\\\partial z} \\\\\\\\     \\\\frac{\\\\partial^2 V}{\\\\partial y\\\\partial x} & \\\\frac{\\\\partial^2 V}{\\\\partial y^2}         & \\\\frac{\\\\partial^2 V}{\\\\partial y\\\\partial z} \\\\\\\\     \\\\frac{\\\\partial^2 V}{\\\\partial z\\\\partial x} & \\\\frac{\\\\partial^2 V}{\\\\partial z\\\\partial y} & \\\\frac{\\\\partial^2 V}{\\\\partial z^2}   \\\\end{pmatrix}. \\\\]From the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileGradiometer</a> observations precomputed <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileReferenceGradiometer</a> together with other background models are reduced, all given in <a class=\"groops-class\" href=\"sggRightSideType.html\">rightHandSide</a>.</p><p>All instrument data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileGradiometer</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> must be synchronous and be diveded into each short arcs (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>Additional to the <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a> an (temporal changing) bias for each gradiometer component and arc can be estimated with <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationBias</a>.</p><p>The accuracy or the full covariance matrix of the gradiometer is provided in <strong class=\"groops-config-element\">covarianceSgg</strong> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingGradiometer.html\">PreprocessingGradiometer</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <code>*:&lt;parametrizationGravity>:*:*</code>.  <h2 id=\"terrestrial\">Terrestrial</h2><p> The gravity field is estimated from point wise measurements. The gravity field parametrization is given by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>. There is no need to have the data regular distributed or given on a sphere or ellipsoid. The type of the gridded data (e.g gravity anomalies or geoid heights) must be set with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. A <a class=\"groops-class\" href=\"gravityfieldType.html\">referencefield</a> can be reduced beforehand.</p><p>The observations at given positions are calculated from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>. The input columns are enumerated by <code>data0</code>, <code>data1</code>, , see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The observations can be divided into small blocks for parallelization. With <strong class=\"groops-config-element\">blockingSize</strong> set the maximum count of observations in each block.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <code>*:&lt;parametrizationGravity>:*:*</code>.  <h2 id=\"deflections\">Deflections</h2><p> The gravity field parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a> is estimated from deflections of the vertical measurements. A <a class=\"groops-class\" href=\"gravityfieldType.html\">referencefield</a> can be reduced beforehand.</p><p>The observations $\\\\xi$ in north direction and $\\\\eta$ in east direction at given positions are calculated from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>. The input columns are enumerated by <code>data0</code>, <code>data1</code>, , see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are used to define the local normal direction.</p><p>The observations can be divided into small blocks for parallelization. With <strong class=\"groops-config-element\">blockingSize</strong> set the maximum count of observations in each block.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <code>*:&lt;parametrizationGravity>:*:*</code>.  <h2 id=\"stationLoading\">StationLoading</h2><p> Observation equations for displacements of a list of stations due to the effect of time variable loading masses. The displacement $\\\\M u$ of a station is calculated according to \\\\[ \\\\M u(\\\\M r) = \\\\frac{1}{\\\\gamma}\\\\sum_{n=0}^\\\\infty \\\\left[\\\\frac{h_n}{1+k_n}V_n(\\\\M r)\\\\,\\\\M e_{up} + R\\\\frac{l_n}{1+k_n}\\\\left(  \\\\frac{\\\\partial V_n(\\\\M r)}{\\\\partial \\\\M e_{north}}\\\\M e_{north} +\\\\frac{\\\\partial V_n(\\\\M r)}{\\\\partial \\\\M e_{east}} \\\\M e_{east}\\\\right)\\\\right], \\\\]where $\\\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDeformationLoadLoveNumber</a> and the load Love numbers $k_n$ are given by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePotentialLoadLoveNumber</a>. The $V_n$ are the spherical harmonics expansion of degree $n$ of the full time variable gravitational potential (potential of the loading mass + deformation potential) parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>. Additional parameters can be setup to estimate the realization of the reference frame of the station coordinates (<strong class=\"groops-config-element\">estimateTranslation</strong>, <strong class=\"groops-config-element\">estimateRotation</strong>, and <strong class=\"groops-config-element\">estimateScale</strong>).</p><p>The observations at stations coordinates are calculated from <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>. The input columns are enumerated by <code>data0</code>, <code>data1</code>, , see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are used to define the local frame (north, east, up).</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up: <ul>  <li><code>*:&lt;parametrizationGravity>:*:*</code>, </li><li> <code>*:translation.x:*:*</code>, </li><li> <code>*:translation.y:*:*</code>, </li><li> <code>*:translation.z:*:*</code>, </li><li> <code>*:scale:*:*</code>, </li><li> <code>*:rotation.x:*:*</code>, </li><li> <code>*:rotation.y:*:*</code>, </li><li> <code>*:rotation.z:*:*</code>. </li></ul> </p><p>See also <a class=\"groops-program\" href=\"Gravityfield2DisplacementTimeSeries.html\">Gravityfield2DisplacementTimeSeries</a>.</p><p>Reference: Rietbroek (2014): Retrieval of Sea Level and Surface Loading Variations from Geodetic Observations and Model Simulations: an Integrated Approach, Bonn, 2014. - Dissertation, <a href=\"https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460\" target=\"_blank\">https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460</a>'},\n'orbitPropagatorType': { 'name': 'orbitPropagatorType', 'key': 'orbitPropagatorType', 'description': 'Implements the propagation of a satellite orbit under the influence of     as used in  SimulateOrbit  (dynamic orbits from numerical orbit integration).     This class implements Euler\\'s method to propagate a satellite orbit under the influence of    . Satellite is assumed to be oriented along-track.     This class implements the classical Runge-Kutta 4 method of orbit propagation for satellite orbit under the influence of    . No step-width control or other advanced features are implemented. Satellite is assumed to be oriented along-track. See: Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits     This class implements the Adams-Moulton class of predictor-corrector orbit propagators for a satellite orbit under the influence of     using an implicit Adams-Bashforth corrector. The coefficients for the propagator are derived using the equations given in section 4.2.3 of [1]. Satellite is assumed to be oriented along-track. [1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits     This class implements the Stoermer-Cowell class of predictor-corrector orbit propagators for a satellite orbit under the influence of    . The coefficients for the Stoermer predictor and Cowell corrector are derived using the equations given in section 4.2.6 of [1]. Stoermer-Cowell is a double integration algorithm, yielding positions directly from accelertions. It does not produce velocities. The velocities are derived using Adams-type propagators as suggested in [2]. Satellite is assumed to be oriented along-track. [1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits [2] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”     This class implements the Gauss-Jackson multi-step predictor-corrector method to propagate a satellite orbit under the influence of    . Satellite is assumed to be oriented along-track. Implementation is based on [1]. [1] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”     This class implements an integration Polynomial method to propagate a satellite orbit under the influence of    . Satellite is assumed to be oriented along-track. Implementation is based on code by Torsten Mayer-Gürr.     Reads an orbit from file. If the needed epochs are not given an exception is thrown.', 'config_table': 'order uint Order of the Adams-Bashforth type propagator. applyMoultonCorrector boolean Corrector step after Adams-Bashforth predcition. warmup orbitPropagatorType  order uint Order of the Stoermer-Cowell type propagator. warmup orbitPropagatorType  order uint of Gauss-Jackson method. warmup orbitPropagatorType  correctorIterations uint Maximum number of iterations to run the corrector step for. epsilon double Convergence criteria for position, velocity, and acceleration tests. degree uint polynomial degree to integrate accelerations shift int shift polynomial in future (predicted accelerations) epsilon double [m] max. position change to recompute forces warmup orbitPropagatorType to compute epochs before start epoch corrector boolean apply corrector iteration if position change is larger than epsilon inputfileOrbit filename epoch at timeStart is not used margin double [seconds] to find identical times recomputeForces boolean', 'display_text': 'Implements the propagation of a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">forces</a> as used in <a class=\"groops-program\" href=\"SimulateOrbit.html\">SimulateOrbit</a> (dynamic orbits from numerical orbit integration).  <h2>Euler</h2><p> This class implements Euler\\'s method to propagate a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. Satellite is assumed to be oriented along-track.  <h2>RungeKutta4</h2><p> This class implements the classical Runge-Kutta 4 method of orbit propagation for satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. No step-width control or other advanced features are implemented. Satellite is assumed to be oriented along-track. See: Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits  <h2>AdamsBashforthMoulton</h2><p> This class implements the Adams-Moulton class of predictor-corrector orbit propagators for a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a> using an implicit Adams-Bashforth corrector. The coefficients for the propagator are derived using the equations given in section 4.2.3 of [1]. Satellite is assumed to be oriented along-track. [1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits  <h2>StoermerCowell</h2><p> This class implements the Stoermer-Cowell class of predictor-corrector orbit propagators for a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. The coefficients for the Stoermer predictor and Cowell corrector are derived using the equations given in section 4.2.6 of [1]. Stoermer-Cowell is a double integration algorithm, yielding positions directly from accelertions. It does not produce velocities. The velocities are derived using Adams-type propagators as suggested in [2]. Satellite is assumed to be oriented along-track. [1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits [2] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”  <h2>GaussJackson</h2><p> This class implements the Gauss-Jackson multi-step predictor-corrector method to propagate a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. Satellite is assumed to be oriented along-track. Implementation is based on [1]. [1] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”  <h2 id=\"Polynomial\">Polynomial</h2><p> This class implements an integration Polynomial method to propagate a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. Satellite is assumed to be oriented along-track. Implementation is based on code by Torsten Mayer-Gürr.  <h2>File</h2><p> Reads an orbit from file. If the needed epochs are not given an exception is thrown.'},\n'parameterNamesType': { 'name': 'parameterNamesType', 'key': 'parameterNamesType', 'description': 'Generates a list of parameter names. All parameters are appended.     The parameter is given explicitly by four parts:    object: Object this parameter refers to, e.g.  graceA ,  G023 ,  earth ,  type: Type of this parameter, e.g.  accBias ,  position.x ,  temporal: Temporal representation of this parameter, e.g.  trend ,  polynomial.degree1 ,  interval: Interval/epoch this parameter represents, e.g.  2017-01-01_00-00-00_2017-01-02_00-00-00 ,  2018-01-01_00-00-00 .       Read parameter names from  file .     Parameter names of gravity    . An additional  object  name can be included in the parameter names.     Parameter names of satellite acceleration    . Arc related parameters are appended if an     is provided which defines the arc structure. An additional  object  name can be included in the parameter names.     Parameter names of satellite tracking    . An additional  object  name can be included in the parameter names.     Parameter names from temporal parametrization. It is possible to setup the temporal parameters for each    .     Parameter names of GNSS antenna center variation    . An additional  object  name (antenna name) can be included in the parameter names. It is possible to setup the parameters for each    .     Parameter names used in    .     Replaces parts of    s. The star \" * \" left this part untouched.     Select a subset of    s using    .     Removes all duplicate names (keep first) from    .', 'config_table': 'object string object this parameter refers to, e.g. graceA, G023, earth type string type of this parameter, e.g. accBias, position.x temporal string temporal representation of this parameter, e.g. trend, polynomial.degree1 interval string interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00 inputfileParameterNames filename file with parameter names object string object these parameters refers to, e.g. earth parametrization parametrizationGravityType  object string object these parameters refers to, e.g. graceA, G023 parameterization parametrizationAccelerationType  inputfileInstrument filename defines the arc structure for arc related parameters object string object these parameters refers to, e.g. grace1.grace2 parameterization parametrizationSatelliteTrackingType  parameterNameBase parameterNamesType  parametrizationTemporal parametrizationTemporalType  object string antenna name parametrization parametrizationGnssAntennaType  gnssType gnssType e.g. C1CG** observation observationType  parameterName parameterNamesType  object string *: left this part untouched, object type string *: left this part untouched, type temporal string *: left this part untouched, temporal representation interval string *: left this part untouched, interval/epoch parameterName parameterNamesType  parameterSelection parameterSelectorType parameter order/selection parameterName parameterNamesType', 'display_text': 'Generates a list of parameter names. All parameters are appended.  <h2>Name</h2><p> The parameter is given explicitly by four parts: <ol>  <li>object: Object this parameter refers to, e.g. <code>graceA</code>, <code>G023</code>, <code>earth</code>, </li><li> type: Type of this parameter, e.g. <code>accBias</code>, <code>position.x</code>, </li><li> temporal: Temporal representation of this parameter, e.g. <code>trend</code>, <code>polynomial.degree1</code>, </li><li> interval: Interval/epoch this parameter represents, e.g. <code>2017-01-01_00-00-00_2017-01-02_00-00-00</code>, <code>2018-01-01_00-00-00</code>. </li></ol>   <h2>File</h2><p> Read parameter names from <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">file</a>.  <h2>Gravity</h2><p> Parameter names of gravity <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrization</a>. An additional <strong class=\"groops-config-element\">object</strong> name can be included in the parameter names.  <h2>Acceleration</h2><p> Parameter names of satellite acceleration <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrization</a>. Arc related parameters are appended if an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> is provided which defines the arc structure. An additional <strong class=\"groops-config-element\">object</strong> name can be included in the parameter names.  <h2>SatelliteTracking</h2><p> Parameter names of satellite tracking <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrization</a>. An additional <strong class=\"groops-config-element\">object</strong> name can be included in the parameter names.  <h2>Temporal</h2><p> Parameter names from temporal parametrization. It is possible to setup the temporal parameters for each <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterNameBase</a>.  <h2>GnssAntenna</h2><p> Parameter names of GNSS antenna center variation <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">parametrization</a>. An additional <strong class=\"groops-config-element\">object</strong> name (antenna name) can be included in the parameter names. It is possible to setup the parameters for each <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>.  <h2>Observation</h2><p> Parameter names used in <a class=\"groops-class\" href=\"observationType.html\">observation equations</a>.  <h2>Rename</h2><p> Replaces parts of <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>s. The star \"<code>*</code>\" left this part untouched.  <h2>Selection</h2><p> Select a subset of <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>s using <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>.  <h2>WithoutDuplicates</h2><p> Removes all duplicate names (keep first) from <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>.'},\n'parameterSelectorType': { 'name': 'parameterSelectorType', 'key': 'parameterSelectorType', 'description': 'This class provides an index vector from selected parameters, which can be used e.g. to reorder a normal equation matrix. The size of the index vector determines the size of the new matrix. Entries are the indices of the selected parameters in the provided parameter list or NULLINDEX for zero/new parameters.     Parameter index vector from name. Name matching supports wildcards * for any number of characters and ? for exactly one character. Does not add zero/empty parameters if there are no matches.     Parameter index vector from list of parameter names.     Parameter index vector from range.     Parameter index vector from matrix.     Expand parameter index vector by adding zero parameters.     Groups a set of    s and has no further effect itself.     Parameter index vector from a complement of other parameter selector(s).', 'config_table': 'object string object this parameter refers to, e.g. graceA, G023, earth (wildcards: * and ?) type string type of this parameter, e.g. accBias, position.x (wildcards: * and ?) temporal string temporal representation of this parameter, e.g. trend, polynomial.degree1 (wildcards: * and ?) interval string interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00 (wildcards: * and ?) parameterName parameterNamesType  start expression start at this index (variables: length) count expression count of parameters, default: all parameters to the end (variables: length) inputfileMatrix filename index in old parameter list or -1 for new parameter column expression use this column (counting from 0, variables: columns) startRow expression start at this row (counting from 0, variables: rows) countRows expression use these many rows (default: use all, variables: rows) count expression count of zero parameters (variables: length) parameterSelection parameterSelectorType parameter order/selection parameterSelection parameterSelectorType parameter order/selection', 'display_text': 'This class provides an index vector from selected parameters, which can be used e.g. to reorder a normal equation matrix. The size of the index vector determines the size of the new matrix. Entries are the indices of the selected parameters in the provided parameter list or NULLINDEX for zero/new parameters.  <h2 id=\"wildcard\">Wildcard</h2><p> Parameter index vector from name. Name matching supports wildcards * for any number of characters and ? for exactly one character. Does not add zero/empty parameters if there are no matches.  <h2>Names</h2><p> Parameter index vector from list of parameter names.  <h2>Range</h2><p> Parameter index vector from range.  <h2>Matrix</h2><p> Parameter index vector from matrix.  <h2>Zeros</h2><p> Expand parameter index vector by adding zero parameters.  <h2 id=\"group\">Group</h2><p> Groups a set of <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>s and has no further effect itself.  <h2 id=\"complement\">Complement</h2><p> Parameter index vector from a complement of other parameter selector(s).'},\n'parametrizationAccelerationType': { 'name': 'parametrizationAccelerationType', 'key': 'parametrizationAccelerationType', 'description': 'This class defines parameters of satellite accelerations. It will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.     Oscillation once, twice, ... per revolution in Satellite Reference Frame (SRF) with the argument of latitude as input angle.  If the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead. Paramters are estimated in  . The  parameter names  are    *:perRevolution.cos(&lt;order>*u).x::&lt;interval> ,  *:perRevolution.cos(&lt;order>*u).y::&lt;interval> ,  *:perRevolution.cos(&lt;order>*u).z::&lt;interval> ,  *:perRevolution.sin(&lt;order>*u).x::&lt;interval> ,  *:perRevolution.sin(&lt;order>*u).y::&lt;interval> ,  *:perRevolution.sin(&lt;order>*u).z::&lt;interval> .       Temporal changing accelerometer bias per axis in   in Satellite Reference Frame (SRF). If the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead. The  parameter names  are    *:accBias.x:*:* ,  *:accBias.y:*:* ,  *:accBias.z:*:* .       Accelerometer scale factor per axis. The  parameter names  are    *:accScale.x:&lt;temporal>:&lt;interval> ,  *:accScale.y:&lt;temporal>:&lt;interval> ,  *:accScale.z:&lt;temporal>:&lt;interval> ,  *:accScaleCross.xy:&lt;temporal>:&lt;interval> ,  *:accScaleCross.xz:&lt;temporal>:&lt;interval> ,  *:accScaleCross.yz:&lt;temporal>:&lt;interval> ,  *:accScaleRotation.xy:&lt;temporal>:&lt;interval> ,  *:accScaleRotation.xz:&lt;temporal>:&lt;interval> ,  *:accScaleRotation.yz:&lt;temporal>:&lt;interval> .  This parametrization needs the attitude of the satellite.     GNSS solar radiation pressure model. Paramters are estimated in  . The  parameter names  are    *:solarRadiationPressure.ECOM.D0:*:* ,  *:solarRadiationPressure.ECOM.DC2:*:* ,  *:solarRadiationPressure.ECOM.DS2:*:* ,  *:solarRadiationPressure.ECOM.DC4:*:* ,  *:solarRadiationPressure.ECOM.DS4:*:* ,  *:solarRadiationPressure.ECOM.Y0:*:* ,  *:solarRadiationPressure.ECOM.B0:*:* ,  *:solarRadiationPressure.ECOM.BC1:*:* ,  *:solarRadiationPressure.ECOM.BS1:*:* ,  *:solarRadiationPressure.ECOM.BC3:*:* ,  *:solarRadiationPressure.ECOM.BS3:*:* .  This parametrization needs the attitude of the satellite.     Estimate the thermospheric density along the orbit using a satllite macro model. An optional thermospheric model can be used to compute temperature and wind. The temperature is used to estimate variable drag and lift coefficients, otherwise a constant drag coefficient is used. The density is estimated in  . The  parameter names  are  *:density:&lt;temporal>:&lt;interval> . This parametrization needs the macro model and the attitude of the satellite.     Estimate a scale factor for a given model. The  parameter names  are  *:modelScale:&lt;temporal>:&lt;interval> .', 'config_table': 'order uint once, twice, ... estimateX boolean along estimateY boolean cross estimateZ boolean radial interval timeSeriesType setup new parameters each interval perArc boolean  estimateX boolean along estimateY boolean cross estimateZ boolean radial temporal parametrizationTemporalType  perArc boolean  inputfileAccelerometer filename  estimateX boolean along estimateY boolean cross estimateZ boolean radial estimateCrossTalk boolean non-orthognality of axes estimateRotation boolean misalignment temporal parametrizationTemporalType  perArc boolean  estimateD0 boolean constant term along D-axis (sat-sun vector) estimateD2 boolean 2-per-rev terms along D-axis estimateD4 boolean 4-per-rev terms along D-axis estimateY0 boolean constant term along Y-axis (solar panel axis) estimateB0 boolean constant term along B-axis (cross product D x Y) estimateB1 boolean 1-per-rev terms along B-axis estimateB3 boolean 3-per-rev terms along B-axis perArc boolean  eclipse eclipseType  thermosphere thermosphereType for wind and temperature earthRotation double [rad/s] considerTemperature boolean compute drag and lift, otherwise simple drag coefficient is used considerWind boolean  temporalDensity parametrizationTemporalType parameters along orbit perArc boolean  miscAccelerations miscAccelerationsType  temporal parametrizationTemporalType  perArc boolean', 'display_text': 'This class defines parameters of satellite accelerations. It will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.  <h2 id=\"perRevolution\">PerRevolution</h2><p> Oscillation once, twice, ... per revolution in Satellite Reference Frame (SRF) with the argument of latitude as input angle.  If the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead. Paramters are estimated in $[nm/s^2=10^{-9}\\\\,m/s^2]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:perRevolution.cos(&lt;order>*u).x::&lt;interval></code>, </li><li> <code>*:perRevolution.cos(&lt;order>*u).y::&lt;interval></code>, </li><li> <code>*:perRevolution.cos(&lt;order>*u).z::&lt;interval></code>, </li><li> <code>*:perRevolution.sin(&lt;order>*u).x::&lt;interval></code>, </li><li> <code>*:perRevolution.sin(&lt;order>*u).y::&lt;interval></code>, </li><li> <code>*:perRevolution.sin(&lt;order>*u).z::&lt;interval></code>. </li></ul>   <h2 id=\"accBias\">AccBias</h2><p> Temporal changing accelerometer bias per axis in $[m/s^2]$ in Satellite Reference Frame (SRF). If the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:accBias.x:*:*</code>, </li><li> <code>*:accBias.y:*:*</code>, </li><li> <code>*:accBias.z:*:*</code>. </li></ul>   <h2 id=\"accelerometerScaleFactors\">AccelerometerScaleFactors</h2><p> Accelerometer scale factor per axis.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:accScale.x:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScale.y:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScale.z:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScaleCross.xy:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScaleCross.xz:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScaleCross.yz:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScaleRotation.xy:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScaleRotation.xz:&lt;temporal>:&lt;interval></code>, </li><li> <code>*:accScaleRotation.yz:&lt;temporal>:&lt;interval></code>. </li></ul> </p><p>This parametrization needs the attitude of the satellite.  <h2 id=\"gnssSolarRadiation\">GnssSolarRadiation</h2><p> GNSS solar radiation pressure model. Paramters are estimated in $[nm/s^2=10^{-9}\\\\,m/s^2]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:solarRadiationPressure.ECOM.D0:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.DC2:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.DS2:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.DC4:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.DS4:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.Y0:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.B0:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.BC1:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.BS1:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.BC3:*:*</code>, </li><li> <code>*:solarRadiationPressure.ECOM.BS3:*:*</code>. </li></ul> </p><p>This parametrization needs the attitude of the satellite.  <h2 id=\"thermosphericDensity\">ThermosphericDensity</h2><p> Estimate the thermospheric density along the orbit using a satllite macro model. An optional thermospheric model can be used to compute temperature and wind. The temperature is used to estimate variable drag and lift coefficients, otherwise a constant drag coefficient is used. The density is estimated in $[kg/m^3]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:density:&lt;temporal>:&lt;interval></code>.</p><p>This parametrization needs the macro model and the attitude of the satellite.  <h2 id=\"modelScale\">ModelScale</h2><p> Estimate a scale factor for a given model. The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:modelScale:&lt;temporal>:&lt;interval></code>.'},\n'parametrizationGnssAntennaType': { 'name': 'parametrizationGnssAntennaType', 'key': 'parametrizationGnssAntennaType', 'description': 'Parametrization of antenna center variations. It will be used to set up the design matrix in a least squares adjustment. Usually the parametrization is setup separately for different    . If multiple parametrizations are given the parameters are sequently appended in the design matrix and parameter vector.     Antenna center or, if setup for a specific    , phase/code center offset (e.g.  *1*G  for GPS L1 phase center offset) in  . The  parameter names  are    *:antennaCenter.x:*:* ,  *:antennaCenter.y:*:* ,  *:antennaCenter.z:*:* .       Parametrization of antenna center variations in   in terms of spherical harmonics. As usually only data above the horizon are observed only the even spherical harmonics (degree/order   even), which are symmetric to the equator, are setup. The total count of parameters is   and the  parameter names  are    *:antennaCenterVariations.sphericalHarmonics.c_&lt;degree>_&lt;order>:*:* ,  *:antennaCenterVariations.sphericalHarmonics.s_&lt;degree>_&lt;order>:*:* .      Parametrization of antenna center variations with radial basis functions  where   in   the coefficients which has to be estimated and   are the basis functions   The  parameter names  are  *:antennaCenterVariations.radialBasis.&lt;index>.&lt;total count>:*:* .', 'config_table': 'estimateX boolean  estimateY boolean  estimateZ boolean  minDegree uint min degree maxDegree uint max degree grid gridType nodal points of shannon kernels minDegree uint min degree of shannon kernel maxDegree uint max degree of shannon kernel', 'display_text': 'Parametrization of antenna center variations. It will be used to set up the design matrix in a least squares adjustment. Usually the parametrization is setup separately for different <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>.</p><p>If multiple parametrizations are given the parameters are sequently appended in the design matrix and parameter vector.  <h2 id=\"center\">Center</h2><p> Antenna center or, if setup for a specific <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>, phase/code center offset (e.g. <code>*1*G</code> for GPS L1 phase center offset) in $[m]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:antennaCenter.x:*:*</code>, </li><li> <code>*:antennaCenter.y:*:*</code>, </li><li> <code>*:antennaCenter.z:*:*</code>. </li></ul>   <h2>SphericalHarmonics</h2><p> Parametrization of antenna center variations in $[m]$ in terms of spherical harmonics. As usually only data above the horizon are observed only the even spherical harmonics (degree/order $m+n$ even), which are symmetric to the equator, are setup.</p><p>The total count of parameters is $((n_{max}+1)(n_{max}+2)-n_{min}(n_{min}+1)/2$ and the <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:antennaCenterVariations.sphericalHarmonics.c_&lt;degree>_&lt;order>:*:*</code>, </li><li> <code>*:antennaCenterVariations.sphericalHarmonics.s_&lt;degree>_&lt;order>:*:*</code>. </li></ul> </p><p> <h2>RadialBasis</h2><p> Parametrization of antenna center variations with radial basis functions \\\\[   ACV(\\\\M x(A, E)) = \\\\sum_i a_i \\\\Phi(\\\\M x\\\\cdot\\\\M x_i) \\\\]where $a_i$ in $[m]$ the coefficients which has to be estimated and $\\\\Phi$ are the basis functions \\\\[   \\\\Phi(\\\\cos\\\\psi) = \\\\sum_n \\\\sqrt{2n+1}P_n(\\\\cos\\\\psi). \\\\] The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:antennaCenterVariations.radialBasis.&lt;index>.&lt;total count>:*:*</code>.</p><p>'},\n'parametrizationGravityType': { 'name': 'parametrizationGravityType', 'key': 'parametrizationGravityType', 'description': 'This class gives a parametrization of the time depending gravity field. Together with the class     it will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.     The potential   is parametrized by a expansion of (fully normalized) spherical harmonics  You can set the range of degree   with  minDegree  and  maxDegree . The sorting sequence of the potential coefficients in the parameter vector can be defined by    . The total count of parameters is   and the  parameter names  are    *:sphericalHarmonics.c_&lt;degree>_&lt;order>:*:* ,  *:sphericalHarmonics.s_&lt;degree>_&lt;order>:*:* .       The potential   is represented by a sum of space localizing basis functions  where   the coefficients which has to be estimated and   are the basis functions given by isotropic radial     functions  The basis functions are located on a grid   given by    . This class can also be used to estimate point masses if     is set to density. The  parameter names  are  *:radialBasis.&lt;index>.&lt;total count>:*:* .     The time variable potential is given by  wehre   is the spatial parametrization of the gravity field and can be choosen with    . The parametrization in time domain   is selected by    . The total parameter count is the parameter count of     times the parameter count of    .     Parametrization of the gravity field on the basis of a linear transformation of a source parametrization. The linear transformation changes the original solution space represented by     from  to  through the linear transformation  . It follows that the rows of the matrix   in  inputfileTransformationMatrix  coincides with the number of parameters in    . The new parameter count is given by the number of columns in   and may be smaller, equal or larger than the original parameter count. The  parameter names  are  *:transformedParameter.&lt;index>.&lt;total count>:*:* .     This class is used to estimate the earthquake oscillation function parameters, i.e.  ,  , and  . The results describes the variation in the gravitational potential field caused by large earthquakes.  with   and   . In this equation,   is the attenuation factor,   is the overtone factor,   is degree,   is order, and   is time after earthquake in second. The  parameter names  are    *:earthquakeParameter.c_&lt;degree>_&lt;order>_A:*:* ,  *:earthquakeParameter.s_&lt;degree>_&lt;order>_A:*:* ,  *:earthquakeParameter.c_&lt;degree>_&lt;order>_W:*:* ,  *:earthquakeParameter.s_&lt;degree>_&lt;order>_W:*:* ,  *:earthquakeParameter.c_&lt;degree>_&lt;order>_P:*:* ,  *:earthquakeParameter.s_&lt;degree>_&lt;order>_P:*:* .', 'config_table': 'minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme kernel kernelType shape of the radial basis function grid gridType nodal point distribution parametrizationGravity parametrizationGravityType  parametrizationTemporal parametrizationTemporalType  parametrizationGravitySource parametrizationGravityType  inputfileTransformationMatrix filename transformation matrix from target to source parametrization (rows of this matrix must coincide with the parameter count of the source parametrization) inputInitialCoefficient filename initial values for oscillation parameters time0 time the time earthquake happened minDegree uint  maxDegree uint  GM double Geocentric gravitational constant R double reference radius numbering sphericalHarmonicsNumberingType numbering scheme', 'display_text': 'This class gives a parametrization of the time depending gravity field. Together with the class <a class=\"groops-class\" href=\"observationType.html\">oberservation</a> it will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.  <h2 id=\"sphericalHarmonics\">SphericalHarmonics</h2><p> The potential $V$ is parametrized by a expansion of (fully normalized) spherical harmonics \\\\[ V(\\\\lambda,\\\\vartheta,r) = \\\\frac{GM}{R}\\\\sum_{n=0}^\\\\infty \\\\sum_{m=0}^n \\\\left(\\\\frac{R}{r}\\\\right)^{n+1}   \\\\left(c_{nm} C_{nm}(\\\\lambda,\\\\vartheta) + s_{nm} S_{nm}(\\\\lambda,\\\\vartheta)\\\\right). \\\\]You can set the range of degree $n$ with <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong>. The sorting sequence of the potential coefficients in the parameter vector can be defined by <a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.</p><p>The total count of parameters is $(n_{max}+1)^2-n_{min}^2$ and the <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:sphericalHarmonics.c_&lt;degree>_&lt;order>:*:*</code>, </li><li> <code>*:sphericalHarmonics.s_&lt;degree>_&lt;order>:*:*</code>. </li></ul>   <h2 id=\"radialBasis\">RadialBasis</h2><p> The potential $V$ is represented by a sum of space localizing basis functions \\\\[   V(\\\\M x) = \\\\sum_i a_i \\\\Phi(\\\\M x, \\\\M x_i) \\\\]where $a_i$ the coefficients which has to be estimated and $\\\\Phi$ are the basis functions given by isotropic radial <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> functions \\\\[   \\\\Phi(\\\\cos\\\\psi,r,R) = \\\\sum_n \\\\left(\\\\frac{R}{r}\\\\right)^{n+1} k_n\\\\sqrt{2n+1}\\\\bar{P}_n(\\\\cos\\\\psi). \\\\]The basis functions are located on a grid $\\\\M x_i$ given by <a class=\"groops-class\" href=\"gridType.html\">grid</a>. This class can also be used to estimate point masses if <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is set to density.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:radialBasis.&lt;index>.&lt;total count>:*:*</code>.  <h2>Temporal</h2><p> The time variable potential is given by \\\\[   V(\\\\M x,t) = \\\\sum_i V_i(\\\\M x)\\\\Psi_i(t), \\\\]wehre $V_i(\\\\M x)$ is the spatial parametrization of the gravity field and can be choosen with <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>. The parametrization in time domain $\\\\Psi_i(t)$ is selected by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>. The total parameter count is the parameter count of <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a> times the parameter count of <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.  <h2>LinearTransformation</h2><p> Parametrization of the gravity field on the basis of a linear transformation of a source parametrization. The linear transformation changes the original solution space represented by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">pararametrizationGravitySource</a> from \\\\[   \\\\mathbf{l} = \\\\mathbf{A}\\\\mathbf{x} + \\\\mathbf{e} \\\\]to \\\\[   \\\\mathbf{l} = \\\\mathbf{A}\\\\mathbf{F}\\\\mathbf{y} + \\\\mathbf{e} \\\\]through the linear transformation $\\\\mathbf{x}=\\\\mathbf{F}\\\\mathbf{y}$. It follows that the rows of the matrix $\\\\mathbf{F}$ in <a class=\"groops-file\" href=\"fileFormat_matrix.html\">inputfileTransformationMatrix</a> coincides with the number of parameters in <a class=\"groops-class\" href=\"parametrizationGravityType.html\">pararametrizationGravitySource</a>. The new parameter count is given by the number of columns in $\\\\mathbf{F}$ and may be smaller, equal or larger than the original parameter count.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:transformedParameter.&lt;index>.&lt;total count>:*:*</code>.  <h2>EarthquakeOscillation</h2><p> This class is used to estimate the earthquake oscillation function parameters, i.e. $C_{nlm}$, $\\\\omega_{nlm}$, and $P_{nlm}$. The results describes the variation in the gravitational potential field caused by large earthquakes. \\\\[ C_{lm}(\\\\M t) = \\\\sum_{n=0}^NC_{nlm}(1-\\\\cos(\\\\omega_{nlm}d\\\\M t)\\\\exp(P_{nlm}\\\\omega_{nlm}d\\\\M t)), \\\\]with $\\\\omega_{nlm}=\\\\frac{2\\\\pi}{T_{nlm}}$ and $P_{nlm}=\\\\frac{-1}{2Q_{nlm}}$ . In this equation, $Q_{nlm}$ is the attenuation factor, $n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time after earthquake in second.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>*:earthquakeParameter.c_&lt;degree>_&lt;order>_A:*:*</code>, </li><li> <code>*:earthquakeParameter.s_&lt;degree>_&lt;order>_A:*:*</code>, </li><li> <code>*:earthquakeParameter.c_&lt;degree>_&lt;order>_W:*:*</code>, </li><li> <code>*:earthquakeParameter.s_&lt;degree>_&lt;order>_W:*:*</code>, </li><li> <code>*:earthquakeParameter.c_&lt;degree>_&lt;order>_P:*:*</code>, </li><li> <code>*:earthquakeParameter.s_&lt;degree>_&lt;order>_P:*:*</code>. </li></ul>'},\n'parametrizationSatelliteTrackingType': { 'name': 'parametrizationSatelliteTrackingType', 'key': 'parametrizationSatelliteTrackingType', 'description': 'This class defines parameters of Satellite-to-Satellite tracking observations. It will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.     Estimate the KBR antenna phase centre (APC) coordinates in   for each spacecraft in satellite reference frame (SRF) as constant per axis. The observation equations are computed by taking the derivative of the antenna offset correction equation w.r.t. the KBR APC coordinates. The  parameter names  are    satellite1.satellite2:sstAntennaCenter1.x:*:* ,  satellite1.satellite2:sstAntennaCenter1.y:*:* ,  satellite1.satellite2:sstAntennaCenter1.z:*:* ,  satellite1.satellite2:sstAntennaCenter2.x:*:* ,  satellite1.satellite2:sstAntennaCenter2.y:*:* ,  satellite1.satellite2:sstAntennaCenter2.z:*:* .       Estimate bias for SST observations in   or  ]. The temporal variation is defined by    . The  parameter names  are  satellite1.satellite2:sstBias:&lt;temporal>:&lt;interval> .     Estimate scale factor for SST observations with respect to reference SST data    . The temporal variation is defined by    . The  parameter names  are  satellite1.satellite2:sstScale:&lt;temporal>:&lt;interval> .     Estimate time shift in seconds in SST observations, with defined temporal variation by    . The design matrix is computed by taking the derivative of the ranging data w.r.t. time. The  parameter names  are  satellite1.satellite2:sstTimeBias:&lt;temporal>:&lt;interval> .     Estimate scale factors for deterministic signal models from satellite tracking instrument file    , see  EnsembleAveragingScaleModel . Amplitude variation of model waveforms is defined by    . The  parameter names  are  satellite1.satellite2:scaleModel:&lt;temporal>:&lt;interval> .     Estimate deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. These events can be time-indexed beforehand using satellite position and orientation, see  GraceSstSpecialEvents . The shape of this short-period waveform is nearly constant within one month and can be approximated by a polynomial. The amplitude variation of the waveform can also be taken into account by    . The  parameter names  are  satellite1.satellite2:&lt;type>.legendrePolynomial.n&lt;degree>:&lt;temporal>:&lt;interval> .', 'config_table': 'estimate1X boolean along (satellite 1) estimate1Y boolean cross (satellite 1) estimate1Z boolean nadir (satellite 1) estimate2X boolean along (satellite 2) estimate2Y boolean cross (satellite 2) estimate2Z boolean nadir (satellite 2) interpolationDegree uint differentiation by polynomial approximation of degree n temporal parametrizationTemporalType  perArc boolean  inputfileSatelliteTracking filename  temporal parametrizationTemporalType  perArc boolean  polynomialDegree uint polynomial degree temporal parametrizationTemporalType  perArc boolean  inputfileSatelliteTracking filename  temporal parametrizationTemporalType  perArc boolean  inputfileEvents filename instrument with GRACE events type choice  eclipse1   eclipse2   starCameraBox1   starCameraBox2   starCameraBox3   starCameraBox4   starCameraBox5   starCameraBox6   marginLeft double margin size (on both sides) [seconds] marginRight double margin size (on both sides) [seconds] minNumberOfEvents uint min. number of events to setup parameters polynomialDegree uint polynomial degree temporal parametrizationTemporalType', 'display_text': 'This class defines parameters of Satellite-to-Satellite tracking observations. It will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.  <h2 id=\"antennaCenter\">AntennaCenter</h2><p> Estimate the KBR antenna phase centre (APC) coordinates in $[m]$ for each spacecraft in satellite reference frame (SRF) as constant per axis. The observation equations are computed by taking the derivative of the antenna offset correction equation w.r.t. the KBR APC coordinates.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>satellite1.satellite2:sstAntennaCenter1.x:*:*</code>, </li><li> <code>satellite1.satellite2:sstAntennaCenter1.y:*:*</code>, </li><li> <code>satellite1.satellite2:sstAntennaCenter1.z:*:*</code>, </li><li> <code>satellite1.satellite2:sstAntennaCenter2.x:*:*</code>, </li><li> <code>satellite1.satellite2:sstAntennaCenter2.y:*:*</code>, </li><li> <code>satellite1.satellite2:sstAntennaCenter2.z:*:*</code>. </li></ul>   <h2 id=\"bias\">Bias</h2><p> Estimate bias for SST observations in $[m]$ or $[m/s$]. The temporal variation is defined by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:sstBias:&lt;temporal>:&lt;interval></code>.  <h2 id=\"scale\">Scale</h2><p> Estimate scale factor for SST observations with respect to reference SST data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>. The temporal variation is defined by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:sstScale:&lt;temporal>:&lt;interval></code>.  <h2 id=\"timeBias\">TimeBias</h2><p> Estimate time shift in seconds in SST observations, with defined temporal variation by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>. The design matrix is computed by taking the derivative of the ranging data w.r.t. time.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:sstTimeBias:&lt;temporal>:&lt;interval></code>.  <h2 id=\"scaleModel\">ScaleModel</h2><p> Estimate scale factors for deterministic signal models from satellite tracking instrument file <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>, see <a class=\"groops-program\" href=\"EnsembleAveragingScaleModel.html\">EnsembleAveragingScaleModel</a>. Amplitude variation of model waveforms is defined by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:scaleModel:&lt;temporal>:&lt;interval></code>.  <h2 id=\"specialEffect\">SpecialEffect</h2><p> Estimate deterministic signals in the GRACE K-Band measurements caused by Sun intrusions into the star camera baffles of GRACE-A and eclipse transits of the satellites. These events can be time-indexed beforehand using satellite position and orientation, see <a class=\"groops-program\" href=\"GraceSstSpecialEvents.html\">GraceSstSpecialEvents</a>. The shape of this short-period waveform is nearly constant within one month and can be approximated by a polynomial. The amplitude variation of the waveform can also be taken into account by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:&lt;type>.legendrePolynomial.n&lt;degree>:&lt;temporal>:&lt;interval></code>.'},\n'parametrizationTemporalType': { 'name': 'parametrizationTemporalType', 'key': 'parametrizationTemporalType', 'description': 'This class gives a parametrization of time depending parameters (gravity field, positions, ...). It will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended. Useally time intervals are defined half open meaning the last time belongs not to the interval. This behaviour can be changed for the last interval with  includeLastTime .     Represents a parameter being constant in time in each  interval . The  parameter names  are  *:*:*:&lt;interval> .     A time variable function is given by a linear trend  with   is  timeStart  and   is  timeStep  in days. A constant term is not included and must added separately. The  parameter name  is  *:*:trend.&lt;timeStep(days)>*(t-&lt;timeStart>):* .     A time variable function is given by  with the (spatial) coefficients   as parameters and the temporal basis functions  . Basis splines are defined as polynomials of degree   in intervals between nodal points in time  , for details see  basis splines . The parameters are ordered timewise. First all parameters of   then   and so on. The total parameter count in each  interval  is  , where   is the count of time points from     in each interval and   is the  degree . The  parameter names  are  *:*:spline.n&lt;degree>:&lt;interval of each spline> .     A time variable function is represented by Legendre polynomials in each  interval . The time is normed to   in each interval. The total parameter count is  , where   is the polynmial degree and   the number of intervals with the  parameter names   *:*:legendrePolynomial.n&lt;degree>:&lt;interval> .     A time variable function is given by a oscillation  with  ,   is  timeStart  and   is  timePeriod  in days. The  parameter names  are  *:*:oscillation.cos(2*pi/&lt;period(days)>*(t-&lt;timeStart>)):*  and  *:*:oscillation.sin(2*pi/&lt;period(days)>*(t-&lt;timeStart>)):* .     A time variable function is given by a fourier expansion  with the normalized time  and   is  timeStart ,   is  timeEnd  in each  interval  and   is the  fourierDegree . The total parameter count is  , where   is the number of intervals. The parameters are sorted in following order:   with the  parameter names   *:*:fourier.cos(&lt;m>*x):&lt;interval>  and  *:*:fourier.sin(&lt;m>*x):&lt;interval> .     The time variable function is given by a fourier expansion  where   are the arguments of the tide constituents    where   are the Doodson\\'s fundamental arguments ( ) and   are the Doodson multipliers for the term at frequency  . The multipliers must be given by     coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2). The major constituents given by     can be used to interpolate minor tidal constituents using the file    . This file can be created with  DoodsonHarmonicsCalculateAdmittance . The total parameter count is   with   the number of doodson frequencies. The parameters are sorted in following order:   with the  parameter names   *:*:doodson.cos(&lt;doodsonName>):*  and  *:*:doodson.sin(&lt;doodsonName>):* .', 'config_table': 'interval timeSeriesType  includeLastTime boolean  timeStart time reference time timeStep time  degree uint degree of splines timeSeries timeSeriesType nodal points in time domain intervals timeSeriesType  includeLastTime boolean  polynomialDegree uint polynomial degree interval timeSeriesType intervals of polynomials includeLastTime boolean  period time [day] time0 time reference time fourierDegree uint  interval timeSeriesType intervals of fourier series includeLastTime boolean  doodson doodson code number (e.g. 255.555) or darwin name (e.g. M2) inputfileAdmittance filename interpolation of minor constituents', 'display_text': 'This class gives a parametrization of time depending parameters (gravity field, positions, ...). It will be used to set up the design matrix in a least squares adjustment. If multiple parametrizations are given the coefficients in the parameter vector are sequently appended.</p><p>Useally time intervals are defined half open meaning the last time belongs not to the interval. This behaviour can be changed for the last interval with <strong class=\"groops-config-element\">includeLastTime</strong>.  <h2 id=\"constant\">Constant</h2><p> Represents a parameter being constant in time in each <strong class=\"groops-config-element\">interval</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:*:*:&lt;interval></code>.  <h2 id=\"trend\">Trend</h2><p> A time variable function is given by a linear trend \\\\[ f(x,t) = \\\\frac{1}{T}(t-t_0) \\\\cdot f_t(x), \\\\]with $t_0$ is <strong class=\"groops-config-element\">timeStart</strong> and $T$ is <strong class=\"groops-config-element\">timeStep</strong> in days. A constant term is not included and must added separately.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter name</a> is <code>*:*:trend.&lt;timeStep(days)>*(t-&lt;timeStart>):*</code>.  <h2 id=\"splines\">Splines</h2><p> A time variable function is given by \\\\[ f(x,t) =  \\\\sum_i f_i(x)\\\\Psi_i(t), \\\\]with the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions $\\\\Psi_i(t)$. Basis splines are defined as polynomials of degree $n$ in intervals between nodal points in time $t_i$, for details see <a class=\"groops-ref\" href=\"fundamentals.basisSplines.html\">basis splines</a>.</p><p>The parameters are ordered timewise. First all parameters of $f_{i=1}(x)$ then $f_{i=2}(x)$ and so on. The total parameter count in each <strong class=\"groops-config-element\">interval</strong> is $N=N_t+n-1$, where $N_t$ is the count of time points from <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> in each interval and $n$ is the <strong class=\"groops-config-element\">degree</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:*:spline.n&lt;degree>:&lt;interval of each spline></code>.  <h2>Polynomial</h2><p> A time variable function is represented by Legendre polynomials in each <strong class=\"groops-config-element\">interval</strong>. The time is normed to $[-1,1)$ in each interval.</p><p>The total parameter count is $(N+1)M$, where $N$ is the polynmial degree and $M$ the number of intervals with the <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> <code>*:*:legendrePolynomial.n&lt;degree>:&lt;interval></code>.  <h2>Oscillation</h2><p> A time variable function is given by a oscillation \\\\[ f(x,t) = f^c(\\\\M x)\\\\cos(\\\\omega_i(t)) + f^s(\\\\M x)\\\\sin(\\\\omega_i(t)) \\\\]with $\\\\omega_i=\\\\frac{2\\\\pi}{T_i}(t-t_0)$, $t_0$ is <strong class=\"groops-config-element\">timeStart</strong> and $T$ is <strong class=\"groops-config-element\">timePeriod</strong> in days.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:*:oscillation.cos(2*pi/&lt;period(days)>*(t-&lt;timeStart>)):*</code> and <code>*:*:oscillation.sin(2*pi/&lt;period(days)>*(t-&lt;timeStart>)):*</code>.  <h2>Fourier</h2><p> A time variable function is given by a fourier expansion \\\\[ f(x,t) = \\\\sum_{m=1}^M f_m^c(\\\\M x)\\\\cos(2\\\\pi m \\\\tau) + f_m^s(\\\\M x)\\\\sin(2\\\\pi m \\\\tau) \\\\]with the normalized time \\\\[ \\\\tau = \\\\frac{t-t_A}{t_B-t_A}, \\\\]and $t_A$ is <strong class=\"groops-config-element\">timeStart</strong>, $t_B$ is <strong class=\"groops-config-element\">timeEnd</strong> in each <strong class=\"groops-config-element\">interval</strong> and $M$ is the <strong class=\"groops-config-element\">fourierDegree</strong>.</p><p>The total parameter count is $2MN$, where $N$ is the number of intervals. The parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\\\ldots$ with the <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> <code>*:*:fourier.cos(&lt;m>*x):&lt;interval></code> and <code>*:*:fourier.sin(&lt;m>*x):&lt;interval></code>.  <h2>DoodsonHarmonic</h2><p> The time variable function is given by a fourier expansion \\\\[   f(x,t) = \\\\sum_{i} f_i^c(x)\\\\cos(\\\\Theta_i(t)) + f_i^s(x)\\\\sin(\\\\Theta_i(t)), \\\\]where $\\\\Theta_i(t)$ are the arguments of the tide constituents $i$ \\\\[   \\\\Theta_i(t) = \\\\sum_{k=1}^6 n_i^k\\\\beta_k(t), \\\\]where $\\\\beta_k(t)$ are the Doodson\\'s fundamental arguments ($\\\\tau,s,h,p,N\\',p_s$) and $n_i^k$ are the Doodson multipliers for the term at frequency $i$. The multipliers must be given by <a class=\"groops-class\" href=\"doodson.html\">doodson</a> coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2).</p><p>The major constituents given by <a class=\"groops-class\" href=\"doodson.html\">doodson</a> can be used to interpolate minor tidal constituents using the file <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>. This file can be created with <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a>.</p><p>The total parameter count is $2N$ with $N$ the number of doodson frequencies. The parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\\\ldots$ with the <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> <code>*:*:doodson.cos(&lt;doodsonName>):*</code> and <code>*:*:doodson.sin(&lt;doodsonName>):*</code>.'},\n'planetType': { 'name': 'planetType', 'key': 'planetType', 'description': 'Defines the planet to compute the    .', 'config_table': 'planetType choice planet earth   sun   moon   mercury   venus   mars   jupiter   saturn   uranus   neptune   pluto   solarBaryCenter   earthMoonBaryCenter', 'display_text': 'Defines the planet to compute the <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemeris</a>.'},\n'platformSelectorType': { 'name': 'platformSelectorType', 'key': 'platformSelectorType', 'description': 'Select a list of platforms (stations, satellites, ...). In a first step all platforms are selected if first selector  exclude s platforms otherwise all platforms excluded. When every selector from top to bottom selects or deselects (with  exclude ) the matching platforms. See also  GnssProcessing  or  SlrProcessing .     Select all platforms.     Select all receivers/transmitters which match the  name ,  markerName , and  markerNumber .     Select receivers/transmitters from each row of    . Additional columns in a row represent alternatives if previous names are not available (e.g. without observation file).     Select all platforms which has the specified equipment in the processed time interval.     Deselects all selected receivers/transmitters of    .', 'config_table': 'name string wildcards: * and ? markerName string wildcards: * and ?, from platform markerNumber string wildcards: * and ?, from platform exclude boolean deselect matching platforms inputfileStringTable filename list of names with alternatives exclude boolean deselect first matching platforms name string wildcards: * and ? serial string wildcards: * and ? equipmentType choice equipment type all  all types gnssAntenna sequence antennas radome string wildcards: * and ? gnssReceiver sequence receivers version string wildcards: * and ? slrStation  SLR station slrRetroReflector  laser retroreflector satelliteIdentifier sequence satellite identifier cospar string wildcards: * and ? norad string wildcards: * and ? sic string wildcards: * and ? sp3 string wildcards: * and ? other  other types exclude boolean deselect matching platforms selector platformSelectorType', 'display_text': 'Select a list of platforms (stations, satellites, ...). In a first step all platforms are selected if first selector <strong class=\"groops-config-element\">exclude</strong>s platforms otherwise all platforms excluded. When every selector from top to bottom selects or deselects (with <strong class=\"groops-config-element\">exclude</strong>) the matching platforms.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> or <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.  <h2 id=\"all\">All</h2><p> Select all platforms.  <h2 id=\"wildcard\">Wildcard</h2><p> Select all receivers/transmitters which match the <strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">markerName</strong>, and <strong class=\"groops-config-element\">markerNumber</strong>.  <h2 id=\"file\">File</h2><p> Select receivers/transmitters from each row of <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStringTable</a>. Additional columns in a row represent alternatives if previous names are not available (e.g. without observation file).  <h2 id=\"equipment\">Equipment</h2><p> Select all platforms which has the specified equipment in the processed time interval.  <h2 id=\"exclude\">Exclude</h2><p> Deselects all selected receivers/transmitters of <a class=\"groops-class\" href=\"platformSelectorType.html\">selector</a>.'},\n'plotAxisType': { 'name': 'plotAxisType', 'key': 'plotAxisType', 'description': 'Defines the style of the axes of  PlotGraph .     General axis for arbitrary input data.     The input data are interpreted as MJD (modified Julian date). The unit of the tick spacings should be appenend to the number and can be any of    Y (year, plot with 4 digits)  y (year, plot with 2 digits)  O (month, plot using  FORMAT_DATE_MAP )  o (month, plot with 2 digits)  U (ISO week, plot using  FORMAT_DATE_MAP )  u (ISO week, plot using 2 digits)  r (Gregorian week, 7-day stride from start of week  TIME_WEEK_START )  K (ISO weekday, plot name of day)  D (date, plot using  FORMAT_DATE_MAP )  d (day, plot day of month 0-31 or year 1-366, via  FORMAT_DATE_MAP )  R (day, same as d, aligned with  TIME_WEEK_START )  H (hour, plot using  FORMAT_CLOCK_MAP )  h (hour, plot with 2 digits)  M (minute, plot using  FORMAT_CLOCK_MAP )  m (minute, plot with 2 digits)  S (second, plot using  FORMAT_CLOCK_MAP )  s (second, plot with 2 digits).  A secondary time axis can be added to specify larger intervals (e.g dates of hourly data). Examples: Settings for Fig.  :  majorTickSpacing = 6H , secondary:  majorTickSpacing = 1D .  Settings for Fig.  :  majorTickSpacing = 2d , secondary:  majorTickSpacing = 1O ,  options = FORMAT_DATE_MAP=\"o yyyy\" .  Settings for Fig.  :  majorTickSpacing = 1o , secondary:  majorTickSpacing = 1Y ,  options = FORMAT_DATE_MAP=\"mm\" .      Axis with string labels. The coordinate system is based on the label indices (e.g. 0, 1, 2).', 'config_table': 'min double The minimum value of the axis. If no value is given, the minimum scale value is set automatically. max double The maximum value of the axis. If no value is given, the maximum scale value is set automatically. majorTickSpacing double The boundary annotation. minorTickSpacing double The spacing of the frame tick intervals. gridLineSpacing double The spacing of the grid line intervals gridLine plotLineType The style of the grid lines. unit string Naming unit to append to the axis values. label string The description of the axis. logarithmic boolean If set to \\'yes\\', a logarithmic scale is used for the axis. color plotColorType Setting the color of the axis bars and labels. changeDirection boolean If set to \\'yes\\', the directions right/up are changed to left/down. min time The minimum value of the time axis. If no value is given, the minimum scale value is set automatically. max time The maximum value of the time axis. If no value is given, the maximum scale value is set automatically. majorTickSpacing string Y: year, o: month minorTickSpacing string D: date, d: day gridLineSpacing string H: clock, h: hour, m: minute, s: second secondary sequence secondary time axis majorTickSpacing string Y: year, o: month minorTickSpacing string D: date, d: day gridLineSpacing string H: clock, h: hour, m: minute, s: second color plotColorType color of axis bars and labels gridLine plotLineType The style of the grid lines. changeDirection boolean right->left / up->down options string adjust date format labels string tick labels (ticks are placed at their index. e.g. 0, 1, ..., 5) min expression minimum value of the axis max expression maximum values of the axis majorTickSpacing expression The boundary annotation. minorTickSpacing expression The spacing of the frame tick intervals. gridLineSpacing expression The spacing of the grid line intervals gridLine plotLineType The style of the grid lines. color plotColorType set the color of the axis and labels orthogonalLabels boolean labels are oriented orthogonal to axis changeDirection boolean If set to \\'yes\\', the directions right/up are changed to left/down.', 'display_text': 'Defines the style of the axes of <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.  <h2>Standard</h2><p> General axis for arbitrary input data.  <h2>Time</h2><p> The input data are interpreted as MJD (modified Julian date). The unit of the tick spacings should be appenend to the number and can be any of <ul>  <li>Y (year, plot with 4 digits) </li><li> y (year, plot with 2 digits) </li><li> O (month, plot using <code>FORMAT_DATE_MAP</code>) </li><li> o (month, plot with 2 digits) </li><li> U (ISO week, plot using <code>FORMAT_DATE_MAP</code>) </li><li> u (ISO week, plot using 2 digits) </li><li> r (Gregorian week, 7-day stride from start of week <code>TIME_WEEK_START</code>) </li><li> K (ISO weekday, plot name of day) </li><li> D (date, plot using <code>FORMAT_DATE_MAP</code>) </li><li> d (day, plot day of month 0-31 or year 1-366, via <code>FORMAT_DATE_MAP</code>) </li><li> R (day, same as d, aligned with <code>TIME_WEEK_START</code>) </li><li> H (hour, plot using <code>FORMAT_CLOCK_MAP</code>) </li><li> h (hour, plot with 2 digits) </li><li> M (minute, plot using <code>FORMAT_CLOCK_MAP</code>) </li><li> m (minute, plot with 2 digits) </li><li> S (second, plot using <code>FORMAT_CLOCK_MAP</code>) </li><li> s (second, plot with 2 digits). </li></ul> </p><p>A secondary time axis can be added to specify larger intervals (e.g dates of hourly data).</p><p>Examples: Settings for Fig. <a href=\"plotAxisType.html#plotAxisTime1\">plotAxisType:plotAxisTime1</a>: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>6H</code>, secondary: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1D</code>. </p><p>Settings for Fig. <a href=\"plotAxisType.html#plotAxisTime2\">plotAxisType:plotAxisTime2</a>: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>2d</code>, secondary: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1O</code>, <strong class=\"groops-config-element\">options</strong>=<code>FORMAT_DATE_MAP=\"o yyyy\"</code>. </p><p>Settings for Fig. <a href=\"plotAxisType.html#plotAxisTime3\">plotAxisType:plotAxisTime3</a>: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1o</code>, secondary: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1Y</code>, <strong class=\"groops-config-element\">options</strong>=<code>FORMAT_DATE_MAP=\"mm\"</code>. </p><p> <h2>Labeled</h2><p> Axis with string labels. The coordinate system is based on the label indices (e.g. 0, 1, 2).'},\n'plotColorType': { 'name': 'plotColorType', 'key': 'plotColorType', 'description': 'Selects a color. Used in  PlotDegreeAmplitudes ,  PlotGraph ,  PlotMap ,  PlotMatrix ,  PlotSphericalHarmonicsTriangle .', 'config_table': 'plotColorType choice color black   red   blue   green   orange   darkred   yellow   lightgreen   gray   rgb sequence  red uint 0..255 green uint 0..255 blue uint 0..255 grayscale sequence  value uint 0..255 namedColor sequence  colorName string name after GMT definition cycler sequence  index uint pick color based on index expression inputfileColorList filename list of colors as defined by GMT', 'display_text': 'Selects a color. Used in <a class=\"groops-program\" href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a>, <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>, <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.</p><p>'},\n'plotColorbarType': { 'name': 'plotColorbarType', 'key': 'plotColorbarType', 'description': 'A colorbar as used in  PlotMap ,  PlotMatrix ,  PlotSphericalHarmonicsTriangle .', 'config_table': 'plotColorbarType sequence  min double  max double  annotation double boundary annotation unit string appended to axis values label string description of the axis logarithmic boolean use logarithmic scale triangleLeft boolean  triangleRight boolean  illuminate boolean illuminate vertical boolean plot vertical color bar on the right length double length of colorbar in percent margin double between colorbar and figure [cm] colorTable string name of the color bar reverse boolean reverse direction showColorbar boolean', 'display_text': 'A colorbar as used in <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.'},\n'plotGraphLayerType': { 'name': 'plotGraphLayerType', 'key': 'plotGraphLayerType', 'description': 'Defines the content of an xy-plot of  PlotGraph . Multiple layers are are plotted sequentially. With  plotOnSecondAxis  the alternative y-axis on the right hand side can be selected if provided.     Draws a     and/or points (   ) of xy data. The standard  dataVariables  are available to select the data columns of    . If no     of the     is given a     is required and the color is determined by  valueZ . Additionally a vertical error bar can be plotted at each data point with size  valueErrorBar . See  Gravityfield2AreaMeanTimeSeries  for an example plot.     Draws a symmetrical envelope around  valueY  as function of  valueX  using deviations  valueErrors . The standard  dataVariables  are available to select the data columns of    . The data line itself is not plotted but must be added as extra    .     Creates a bar plot with vertical or  horizontal  bars out of the given x- and y-values. The standard  dataVariables  are available to select the data columns of    . The bars ranges from  valueBase  (can be also an expression) to the  valueY . If no     is given a     is required and the color is determined by  valueZ . See  Instrument2Histogram  for an example plot.     Creates a regular grid of yxz values. The standard  dataVariables  are available to select the data columns of    . Empty grid cells are not plotted. Cells with more than one value will be set to the mean value. The grid spacing is determined by the median spacing of the input data or set by  incrementX/Y . See  Orbit2ArgumentOfLatitude  for an example plot.     Plots a rectangle to highlight an area.     Writes a  text  at  originX  and  originY  position in the graph. With  clip  the text is cutted at the boundaries of the plotting area.     Plot degree amplitudes of potential coefficients computed by  Gravityfield2DegreeAmplitudes  or  PotentialCoefficients2DegreeAmplitudes . The standard  dataVariables  are available to select the data columns of    . It plots a solid line for the  valueSignal  and a dotted line for the  valueError  per default.     Plot degree amplitudes from a    . The coefficients can be converted to different functionals with    . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly. It plots a solid line for the degree amplitude (signal) and a dotted line for the formal errors per default. This is a simplified version of    .', 'config_table': 'inputfileMatrix filename each line contains x,y valueX expression expression for x-values (input columns are named data0, data1, ...) valueY expression expression for y-values (input columns are named data0, data1, ...) valueZ expression expression for the colorbar valueErrorBar expression expression for error bars (input columns are named data0, data1, ...) description string text of the legend line plotLineType  symbol plotSymbolType  plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). inputfileMatrix filename each line contains x,y valueX expression expression for x-values (input columns are named data0, data1, ...) valueY expression expression for y-values (input columns are named data0, data1, ...) valueErrors expression expression for error values description string text of the legend fillColor plotColorType fill color of the envelope edgeLine plotLineType edge line style of the envelope plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). inputfileMatrix filename each line contains x,y valueX expression expression for x-values (input columns are named data0, data1, ...) valueY expression expression for y-values (input columns are named data0, data1, ...) valueZ expression expression for the colorbar valueBase expression base value of bars (default: minimum y-value) width expression width of bars (default: minimum x-gap) horizontal boolean draw horizontal bars instead of vertical description string text of the legend color plotColorType  edgeLine plotLineType line plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). inputfileMatrix filename each line contains x,y,z valueX expression expression for x-values (input columns are named data0, data1, ...) valueY expression expression for y-values (input columns are named data0, data1, ...) valueZ expression expression for the colorbar incrementX double the grid spacing incrementY double the grid spacing plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). minX double empty: left maxX double empty: right minY double empty: bottom maxY double empty: top description string text of the legend edgeLine plotLineType  fillColor plotColorType  plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). text string  originX double  originY double  offsetX double [cm] x-offset from origin offsetY double [cm] y-offset from origin alignment string L, C, R (left, center, right) and T, M, B (top, middle, bottom) fontSize double [pt] fontColor plotColorType  clip boolean clip at boundaries plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). inputfileMatrix filename degree amplitudes valueDegree expression expression for x-values (degrees) (input columns are named data0, data1, ...) valueSignal expression expression for y-values (signal) (input columns are named data0, data1, ...) valueErrors expression expression for y-values (formal errors) description string text of the legend lineSignal plotLineType  lineErrors plotLineType  plotOnSecondAxis boolean draw dataset on a second Y-axis (if available). gravityfield gravityfieldType  kernel kernelType  type choice type of variances rms  degree amplitudes (square root of degree variances) accumulation  cumulate variances over degrees median  median of absolute values per degree time time at this time the gravity field will be evaluated minDegree uint  maxDegree uint  description string text of the legend lineSignal plotLineType  lineErrors plotLineType  plotOnSecondAxis boolean draw dataset on a second Y-axis (if available).', 'display_text': 'Defines the content of an xy-plot of <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>. Multiple layers are are plotted sequentially. With <strong class=\"groops-config-element\">plotOnSecondAxis</strong> the alternative y-axis on the right hand side can be selected if provided.  <h2 id=\"linesAndPoints\">LinesAndPoints</h2><p> Draws a <a class=\"groops-class\" href=\"plotLineType.html\">line</a> and/or points (<a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a>) of xy data. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>. If no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> of the <a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a> is given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a> is required and the color is determined by <strong class=\"groops-config-element\">valueZ</strong>. Additionally a vertical error bar can be plotted at each data point with size <strong class=\"groops-config-element\">valueErrorBar</strong>.</p><p>See <a class=\"groops-program\" href=\"Gravityfield2AreaMeanTimeSeries.html\">Gravityfield2AreaMeanTimeSeries</a> for an example plot.  <h2>ErrorEnvelope</h2><p> Draws a symmetrical envelope around <strong class=\"groops-config-element\">valueY</strong> as function of <strong class=\"groops-config-element\">valueX</strong> using deviations <strong class=\"groops-config-element\">valueErrors</strong>. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>. The data line itself is not plotted but must be added as extra <a class=\"groops-class\" href=\"plotGraphLayerType.html#linesAndPoints\">layer:linesAndPoints</a>.  <h2>Bars</h2><p> Creates a bar plot with vertical or <strong class=\"groops-config-element\">horizontal</strong> bars out of the given x- and y-values. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>. The bars ranges from <strong class=\"groops-config-element\">valueBase</strong> (can be also an expression) to the <strong class=\"groops-config-element\">valueY</strong>. If no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> is given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a> is required and the color is determined by <strong class=\"groops-config-element\">valueZ</strong>.</p><p>See <a class=\"groops-program\" href=\"Instrument2Histogram.html\">Instrument2Histogram</a> for an example plot.  <h2>Gridded</h2><p> Creates a regular grid of yxz values. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>. Empty grid cells are not plotted. Cells with more than one value will be set to the mean value. The grid spacing is determined by the median spacing of the input data or set by <strong class=\"groops-config-element\">incrementX/Y</strong>.</p><p>See <a class=\"groops-program\" href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a> for an example plot.  <h2>Rectangle</h2><p> Plots a rectangle to highlight an area.  <h2>Text</h2><p> Writes a <strong class=\"groops-config-element\">text</strong> at <strong class=\"groops-config-element\">originX</strong> and <strong class=\"groops-config-element\">originY</strong> position in the graph. With <strong class=\"groops-config-element\">clip</strong> the text is cutted at the boundaries of the plotting area.  <h2 id=\"degreeAmplitudes\">DegreeAmplitudes</h2><p> Plot degree amplitudes of potential coefficients computed by <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a> or <a class=\"groops-program\" href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a>. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>. It plots a solid line for the <strong class=\"groops-config-element\">valueSignal</strong> and a dotted line for the <strong class=\"groops-config-element\">valueError</strong> per default.  <h2 id=\"degreeAmplitudesSimple\">DegreeAmplitudesSimple</h2><p> Plot degree amplitudes from a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>. The coefficients can be converted to different functionals with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. It plots a solid line for the degree amplitude (signal) and a dotted line for the formal errors per default.</p><p>This is a simplified version of <a class=\"groops-class\" href=\"plotGraphLayerType.html#degreeAmplitudes\">layer:degreeAmplitudes</a>.'},\n'plotLegendType': { 'name': 'plotLegendType', 'key': 'plotLegendType', 'description': 'Plot a legend of the descriptions provided in     in  PlotGraph .', 'config_table': 'plotLegendType sequence  width double legend width [cm] height double legend height [cm] (default: estimated) positionX double legend x-position in normalized (0-1) coordinates. positionY double legend y-position in normalized (0-1) coordinates. anchorPoint string Two character combination of L, C, R (for left, center, or right) and T, M, B for top, middle, or bottom. e.g., TL for top left columns uint number of columns in legend textColor plotColorType color of the legend text fillColor plotColorType fill color of the legend box edgeLine plotLineType style of the legend box edge', 'display_text': 'Plot a legend of the descriptions provided in <a class=\"groops-class\" href=\"plotGraphLayerType.html\">plotGraphLayer</a> in <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.'},\n'plotLineType': { 'name': 'plotLineType', 'key': 'plotLineType', 'description': 'Defines the line style to be plotted.     Draws a solid line.     Draws a dashed line.     Draws a dotted line.     Draws a custom line. The line  style  code is described in  https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes .', 'config_table': 'width double line width [p] color plotColorType  width double line width [p] color plotColorType  width double line width [p] color plotColorType    style string line style code width double line width [p] color plotColorType', 'display_text': 'Defines the line style to be plotted.  <h2>Solid</h2><p> Draws a solid line.  <h2>Dashed</h2><p> Draws a dashed line.  <h2>Dotted</h2><p> Draws a dotted line.  <h2>Custom</h2><p> Draws a custom line. The line <strong class=\"groops-config-element\">style</strong> code is described in <a href=\"https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes</a>.'},\n'plotMapLayerType': { 'name': 'plotMapLayerType', 'key': 'plotMapLayerType', 'description': 'Defines the content of a map of  PlotMap . Multiple layers are are plotted sequentially.     Creates a regular grid of xyz values. The standard  dataVariables  are available to select the data column of    . Empty grid cells are not plotted. Cells with more than one value will be set to the mean value. The grid spacing can be determined automatically for regular rectangular grids otherwise it must be set with  increment . To get a better display together with some projections the grid should be internally  resample d to higher resolution. It is assumed that the points of     represents centers of grid cells. This assumption can be changed with  gridlineRegistered  (e.g. if the data starts at the north pole).     Draws points (   ) and/or    s between the points. If no     of the     is given a     is required and the color is determined by the  value  expression. The standard  dataVariables  are available to select the data column of    .     Draws an arrow for each point in    . The arrows are defined by the expressions  valueNorth/East . The standard  dataVariables  are available to select the correspondent data columns of    . The  scale  factor converts the input units to cm in the plot. If no     is given a     is required and the color is determined by the  value  expression. With  scaleArrow  a reference arrow as legend can be plotted inside or outside the map.     Draws a    . If     is not set and a  value  is given the fill color is taken from a    .     Plots coastlines. GMT provides them in different  resolution s. Features with an area smaller than  minArea  in   will not be plotted.     Plots rivers and lakes. GMT provides different classes ( https://docs.generic-mapping-tools.org/latest/coast.html ).     Plots national boundaries. GMT provides them in different  resolution s.     An image of the Earth\\'s surface as seen from outer space - the image is known as  blue marble . The directory of  inputfileChannels  contains several files in different resolutions representing the Earth\\'s surface each month throughout a year.      Writes a  text  at  originLongitude  and  originLatitude  position in the map. With  clip  the text is cutted at the boundaries of the plotting area.', 'config_table': 'inputfileGriddedData filename  value expression expression to compute values (input columns are named data0, data1, ...) increment angle the grid spacing [degrees] illuminate boolean illuminate grid resample sequence  intermediateDpi double oversample grid for a smoother visual effect interpolationMethod choice interpolation method for oversampling bspline  B-Spline interpolation bicubic  bicubic interpolation bilinear  bilinear interpolation nearest  nearest neighbour interpolation threshold double A threshold of 1.0 requires all (4 or 16) nodes involved in interpolation to be non-NaN. 0.5 will interpolate about half way from a non-NaN value; 0.1 will go about 90% of the way. gridlineRegistered boolean treat input as point values instead of cell means inputfileGriddedData filename  value expression expression to compute color (input columns are named data0, data1, ...) symbol plotSymbolType  line plotLineType style of connecting lines drawLineAsGreatCircle boolean draw connecting lines as great circles (otherwise, a straight line is drawn instead) inputfileGriddedData filename grid file with north and east values for arrows valueNorth expression expression to compute north values (input columns are named data0, data1, ...) valueEast expression expression to compute east values (input columns are named data0, data1, ...) value expression expression to compute arrow color (input columns are named data0, data1, ...) scale double [cm per input unit] length scale factor penSize double [pt] width of arrow shaft headSize double [pt] size of arrow head, 0: no head, negative: reverse head color plotColorType empty: from value scaleArrow sequence draw an arrow for scale reference originX double [0-1] 0: left, 1: right originY double [0-1] 0: bottom, 1: top length double in same unit as valueNorth and valueEast unit string displayed unit text (e.g. 1 cm) label string description of the arrows inputfilePolygon filename  line plotLineType style of border lines fillColor plotColorType polygon fill color (no fill color: determine from value if given, else: no fill) value double value to compute fill color from a colorbar (ignored if a fillColor is given) drawLineAsGreatCircle boolean draw connecting lines as great circles (otherwise, a straight line is drawn instead) resolution choice  crude   low   medium   high   full   line plotLineType line style for coastlines landColor plotColorType fill land area oceanColor plotColorType fill ocean area minArea uint [km^2] features with a smaller area than this are dropped class choice  riversCanalsLakes   riversCanals   permanentRiversLakes   permanentRivers   intermittentRivers   canals   singleClass sequence  class uint 0-10. See GMT documentation line plotLineType  resolution choice  crude   low   medium   high   full   line plotLineType  inputfileImage filename Blue Marble image file brightness double brightness of bitmap [-1, 1] illuminate sequence add hillshade based on topography inputfileTopography filename GMT grid file containing topography. azimuth angle direction of lighting source [deg] elevation angle direction of lighting source [deg] ambient double ambient lighting diffuse double diffuse lighting specular double specular reflection shine double surface shine amplitude double scale gradient by factor text string  originLongitude angle [deg] originLatitude angle [deg] offsetX double [cm] x-offset from origin offsetY double [cm] y-offset from origin alignment string L, C, R (left, center, right) and T, M, B (top, middle, bottom) fontSize double  fontColor plotColorType  clip boolean clip at boundaries', 'display_text': 'Defines the content of a map of <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>. Multiple layers are are plotted sequentially.  <h2>GriddedData</h2><p> Creates a regular grid of xyz values. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data column of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>. Empty grid cells are not plotted. Cells with more than one value will be set to the mean value. The grid spacing can be determined automatically for regular rectangular grids otherwise it must be set with <strong class=\"groops-config-element\">increment</strong>. To get a better display together with some projections the grid should be internally <strong class=\"groops-config-element\">resample</strong>d to higher resolution. It is assumed that the points of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> represents centers of grid cells. This assumption can be changed with <strong class=\"groops-config-element\">gridlineRegistered</strong> (e.g. if the data starts at the north pole).  <h2 id=\"points\">Points</h2><p> Draws points (<a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a>) and/or <a class=\"groops-class\" href=\"plotLineType.html\">line</a>s between the points. If no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> of the <a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a> is given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a> is required and the color is determined by the <strong class=\"groops-config-element\">value</strong> expression. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the data column of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.  <h2>Arrows</h2><p> Draws an arrow for each point in <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>. The arrows are defined by the expressions <strong class=\"groops-config-element\">valueNorth/East</strong>. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select the correspondent data columns of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>. The <strong class=\"groops-config-element\">scale</strong> factor converts the input units to cm in the plot. If no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> is given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a> is required and the color is determined by the <strong class=\"groops-config-element\">value</strong> expression. With <strong class=\"groops-config-element\">scaleArrow</strong> a reference arrow as legend can be plotted inside or outside the map.  <h2>Polygon</h2><p> Draws a <a class=\"groops-class\" href=\"fileFormat_polygon.html\">inputfilePolygon</a>. If <a class=\"groops-class\" href=\"plotColorType.html\">fillColor</a> is not set and a <strong class=\"groops-config-element\">value</strong> is given the fill color is taken from a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a>.  <h2>Coast</h2><p> Plots coastlines. GMT provides them in different <strong class=\"groops-config-element\">resolution</strong>s. Features with an area smaller than <strong class=\"groops-config-element\">minArea</strong> in $km^2$ will not be plotted.  <h2>Rivers</h2><p> Plots rivers and lakes. GMT provides different classes (<a href=\"https://docs.generic-mapping-tools.org/latest/coast.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/coast.html</a>).  <h2>PoliticalBoundary</h2><p> Plots national boundaries. GMT provides them in different <strong class=\"groops-config-element\">resolution</strong>s.  <h2>BlueMarble</h2><p> An image of the Earth\\'s surface as seen from outer space - the image is known as <em>blue marble</em>. The directory of <strong class=\"groops-config-element\">inputfileChannels</strong> contains several files in different resolutions representing the Earth\\'s surface each month throughout a year.</p><p>  <h2>Text</h2><p> Writes a <strong class=\"groops-config-element\">text</strong> at <strong class=\"groops-config-element\">originLongitude</strong> and <strong class=\"groops-config-element\">originLatitude</strong> position in the map. With <strong class=\"groops-config-element\">clip</strong> the text is cutted at the boundaries of the plotting area.'},\n'plotMapProjectionType': { 'name': 'plotMapProjectionType', 'key': 'plotMapProjectionType', 'description': 'Selects the underlying projection of  PlotMap .     The Robinson projection, presented by Arthur H. Robinson in 1963, is a modified cylindrical projection that is neither conformal nor equal-area. Central meridian and all parallels are straight lines; other meridians are curved. It uses lookup tables rather than analytic expressions to make the world map look right.     The orthographic azimuthal projection is a perspective projection from infinite distance. It is therefore often used to give the appearance of a globe viewed from space.     The orthographic azimuthal projection is a perspective projection from infinite distance. It is therefore often used to give the appearance of a globe viewed from space.     Stereographic projection around given central point.     Skyplot used to plot azimuth/elevation data as generated by  GnssAntennaDefinition2Skyplot  or  GnssResiduals2Skyplot .     A particular subset of the transverse Mercator is the Universal Transverse Mercator (UTM) which was adopted by the US Army for large-scale military maps. Here, the globe is divided into 60 zones between 84 S and 84 N, most of which are 6  wide. Each of these UTM zones have their unique central meridian.     This conic projection was designed by Lambert (1772) and has been used extensively for mapping of regions with predominantly east-west orientation.     Linear mapping of longitude/latitude to x/y (Plate Caree).     This pseudo-cylindrical, equal-area projection was developed by Mollweide in 1805. Parallels are unequally spaced straight lines with the meridians being equally spaced elliptical arcs. The scale is only true along latitudes 40 44\\' north and south. The projection is used mainly for global maps showing data distributions.', 'config_table': 'centralMeridian angle central meridian [degree] lambdaCenter angle central point [degree] phiCenter angle central point [degree] lambdaCenter angle longitude of central point in degrees phiCenter angle latitude of central point in degrees altitude double [km] azimuth angle to the east of north of view [degrees] tilt angle upward tilt of the plane of projection, if negative, then the view is centered on the horizon [degrees] viewpointTwist angle clockwise twist of the viewpoint [degrees] viewpointWidth angle width of the viewpoint [degrees] viewpointHeight angle height of the viewpoint [degrees] lambdaCenter angle longitude of central point in degrees phiCenter angle latitude of central point in degrees zone string UTM zone code (e.g. 33N) lambda0 angle longitude of projection center [deg] phi0 angle latitude of projection centert [deg] phi1 angle latitude of first standard parallel [deg] phi2 angle latitude of first standard parallel [deg] centralMeridian angle central meridian [degree]', 'display_text': 'Selects the underlying projection of <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.  <h2>Robinson</h2><p> The Robinson projection, presented by Arthur H. Robinson in 1963, is a modified cylindrical projection that is neither conformal nor equal-area. Central meridian and all parallels are straight lines; other meridians are curved. It uses lookup tables rather than analytic expressions to make the world map look right.  <h2>Orthographic</h2><p> The orthographic azimuthal projection is a perspective projection from infinite distance. It is therefore often used to give the appearance of a globe viewed from space.  <h2>Perspective sphere</h2><p> The orthographic azimuthal projection is a perspective projection from infinite distance. It is therefore often used to give the appearance of a globe viewed from space.  <h2>Polar</h2><p> Stereographic projection around given central point.  <h2>Skyplot</h2><p> Skyplot used to plot azimuth/elevation data as generated by <a class=\"groops-program\" href=\"GnssAntennaDefinition2Skyplot.html\">GnssAntennaDefinition2Skyplot</a> or <a class=\"groops-program\" href=\"GnssResiduals2Skyplot.html\">GnssResiduals2Skyplot</a>.  <h2>UTM</h2><p> A particular subset of the transverse Mercator is the Universal Transverse Mercator (UTM) which was adopted by the US Army for large-scale military maps. Here, the globe is divided into 60 zones between 84$^{o}$S and 84$^{o}$N, most of which are 6$^{o}$ wide. Each of these UTM zones have their unique central meridian.  <h2>Lambert</h2><p> This conic projection was designed by Lambert (1772) and has been used extensively for mapping of regions with predominantly east-west orientation.  <h2>Linear</h2><p> Linear mapping of longitude/latitude to x/y (Plate Caree).  <h2>Mollweide</h2><p> This pseudo-cylindrical, equal-area projection was developed by Mollweide in 1805. Parallels are unequally spaced straight lines with the meridians being equally spaced elliptical arcs. The scale is only true along latitudes 40$^{o}$44\\' north and south. The projection is used mainly for global maps showing data distributions.'},\n'plotSymbolType': { 'name': 'plotSymbolType', 'key': 'plotSymbolType', 'description': 'Plots a symbol as used e.g. in     or    .', 'config_table': 'plotSymbolType choice symbol circle sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean  star sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean  cross sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean  square sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean  triangle sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean  diamond sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean  dash sequence  color plotColorType empty: determined from value size double size of symbol [point] blackContour boolean', 'display_text': 'Plots a symbol as used e.g. in <a class=\"groops-class\" href=\"plotGraphLayerType.html#linesAndPoints\">plotGraphLayer:linesAndPoints</a> or <a class=\"groops-class\" href=\"plotMapLayerType.html#points\">plotMapLayer:points</a>.'},\n'podRightSideType': { 'name': 'podRightSideType', 'key': 'podRightSideType', 'description': 'Observation vector for precise orbit data (POD) of     equations in a least squares adjustment. The observations are reduced by the effect of     and     (observed minus computed).', 'config_table': 'podRightSideType sequence  inputfileOrbit filename kinematic positions of satellite as observations inputfileAccelerometer filename non-gravitational forces in satellite reference frame forces forcesType', 'display_text': 'Observation vector for precise orbit data (POD) of <a class=\"groops-class\" href=\"observationType.html\">observation</a> equations in a least squares adjustment. The observations are reduced by the effect of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> and <a class=\"groops-class\" href=\"forcesType.html\">forces</a> (observed minus computed).'},\n'sggRightSideType': { 'name': 'sggRightSideType', 'key': 'sggRightSideType', 'description': 'Observation vector for gradiometer data (satellite gravity gradiometry, SGG) of     equations in a least squares adjustment. The observations are reduced by an    , the effect of    , and     (observed minus computed). The reference gradiometer data can be precomputed with  SimulateGradiometer .', 'config_table': 'sggRightSideType sequence  inputfileGradiometer filename observed gravity gradients inputfileReferenceGradiometer filename precomputed gradients at orbit positions referencefield gravityfieldType  tides tidesType', 'display_text': 'Observation vector for gradiometer data (satellite gravity gradiometry, SGG) of <a class=\"groops-class\" href=\"observationType.html\">observation</a> equations in a least squares adjustment. The observations are reduced by an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileReferenceGradiometer</a>, the effect of <a class=\"groops-class\" href=\"gravityfieldType.html\">referencefield</a>, and <a class=\"groops-class\" href=\"tidesType.html\">tides</a> (observed minus computed).</p><p>The reference gradiometer data can be precomputed with <a class=\"groops-program\" href=\"SimulateGradiometer.html\">SimulateGradiometer</a>.'},\n'slrParametrizationType': { 'name': 'slrParametrizationType', 'key': 'slrParametrizationType', 'description': 'This class defines the models and parameters of the linearized observation equations for normal points (see  SlrProcessing )  where the left side is the observation vector minus the effects computed from the a priori models. After each least squares adjustment (see    ) the a priori parameters are updated  The vector   can be written with    . Any  outputfiles  defined in the parametrizations are written with    . Each parametrization (and possible constraint equations) has a  name  which enables activating/deactivating the estimation of subsets of   with    . The a priori model   is unaffected and is always reduced. The model for the one way range observations between station   and reflector   can be described as   See also  SlrProcessing .     A priori tropospheric correction is handled by a     model (e.g. Mendes and Pavlis). Additional parameters in   for zenith delay can be set up via    . These parameters can be soft-constrained using     to avoid an unsolvable system of normal equations in case of data gaps. The  parameter names  are  &lt;station>:troposphere:&lt;temporal>:&lt;interval> .     The estimation of (reduced) dynamic orbits is formulated as variational equations. It is based on     calculated with  PreprocessingVariationalEquation . Necessary integrations are performed by integrating a moving interpolation polynomial of degree  integrationDegree . The     must include at least those parameters that were estimated in  PreprocessingVariationalEquationOrbitFit . Additional     parameters can be set up to reduce orbit mismodeling. The parameters and  parameter names  are divided into global    &lt;satellite>:&lt;parametrizationAcceleration>:*:* ,  &lt;satellite>:stochasticPulse.x::&lt;time> ,  &lt;satellite>:stochasticPulse.y::&lt;time> ,  &lt;satellite>:stochasticPulse.z::&lt;time> ,   and arc related parameters    &lt;satellite>:arc&lt;no>.&lt;parametrizationAcceleration>:*:* ,  &lt;satellite>:arc&lt;no>.position0.x:: ,  &lt;satellite>:arc&lt;no>.position0.y:: ,  &lt;satellite>:arc&lt;no>.position0.z:: .  &lt;satellite>:arc&lt;no>.velocity0.x:: ,  &lt;satellite>:arc&lt;no>.velocity0.y:: ,  &lt;satellite>:arc&lt;no>.velocity0.z:: .       Estimates a (time depending) gravity field together with at least one    . The parametrization of the gravity field can be set with    . The  parameter names  are  gravityfield:&lt;parametrization>:*:* .     Estimates a static position for all     in the terrestrial frame. No-net constraints can be applied for a subset of stations,    , with a standard deviation of  noNetTranslationSigma  and  noNetRotationSigma  and  noNetScaleSigma  and  noNetScaleSigma . If the template     is provided the constraints are applied relatively to these positions. Only stations with an existing position file are considered. Without     the constraints are applied towards the apriori values from    . As a single corrupted station position can disturb the no-net conditions, the rotation/translation parameters are estimated in a  robust least squares adjustment  beforehand. The computed weight matrix is used to downweight corrupted stations in the constraint equations. In case you want to align to an ITRF/ILRS reference frame, precise coordinates can be generated with  Sinex2StationPositions . The  parameter names  are    &lt;station>:position.x:: ,  &lt;station>:position.y:: ,  &lt;station>:position.z:: .       Earth rotation parameters (ERPs) can be estimated by defining  estimatePole  ( ,  ) and  estimateUT1  ( ). Estimating length of day (LOD) with the sign according to IGS conventions requires a negative value in    . Constraints on the defined parameters can be added via    . An example would be to set up     so the   parameter is included in the normal equation system . Since   cannot be determined by SLR, a hard constraint to its a priori value can then be added. The  parameter names  are    earth:polarMotion.xp:&lt;temporal>:&lt;interval> ,  earth:polarMotion.yp:&lt;temporal>:&lt;interval> ,  earth:UT1:&lt;temporal>:&lt;interval> ,  earth:nutation.X:&lt;temporal>:&lt;interval> ,  earth:nutation.>:&lt;temporal>:&lt;interval> .       A priori station range bias value for all    . The   provides the mean range biases  , but these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive satellites and not for active ones. Use  SlrSinexDataHandling2Files  to convert the range biases from   to  instrument file .     Estimates a constant station range bias in   for    . The  parameter names  are  &lt;station>:rangeBias:: .     A priori satellite range bias value for    .     Estimates a constant satellite range bias in   for    . The  parameter names  a  &lt;satellite>:rangeBias:: .     A priori station-satellite range bias value between all     -     pairs. For standard   processing this class should be setup twice. Once for the model from José Rodríguez (see  SlrComModel2RangeBiasStationSatellite ) and additionally for biases from the   converted with  SlrSinexDataHandling2Files .     Estimates the station-satellite range bias in   between all     -     pairs. The  parameter names  are  &lt;station>.&lt;satellite>:rangeBias:: .     A priori time bias value for all    . The   provides the mean time biases  , but these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive satellites and not for active ones. Use  SlrSinexDataHandling2Files  to convert the time biases from   to  instrument file .     Estimates a     time bias in   for    . The  parameter names  are  &lt;station>:timeBias:&lt;temporal>:&lt;interval> .     Add a pseudo observation equation (constraint) for each selected      where   is the  bias  and   is the a priori value of the parameter if  relativeToApriori  is not set. The standard deviation  sigma  is used to weight the observation equations.     Groups a set of parameters. This class can be used to structure complex parametrizations and has no further effect itself.', 'config_table': 'name string used for parameter selection selectStations platformSelectorType  outputfileTroposphere filename columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient troposphere troposphereType a priori troposphere model troposphereEstimation parametrizationTemporalType [m] parametrization of zenith delays name string used for parameter selection selectSatellites platformSelectorType  outputfileOrbit filename variable {satellite} available outputfileParameters filename variable {satellite} available inputfileVariational filename variable {satellite} available stochasticPulse timeSeriesType [mu/s] parametrization of stochastic pulses parametrizationAcceleration parametrizationAccelerationType orbit force parameters ephemerides ephemeridesType  integrationDegree uint integration of forces by polynomial approximation of degree n interpolationDegree uint for orbit interpolation and velocity calculation name string used for parameter selection parametrization parametrizationGravityType  name string used for parameter selection selectStations platformSelectorType  outputfileGriddedPosition filename delta north east up for all stations outputfilePosition filename variable {station} available, full estimated coordinates (in TRF) nameConstraint string used for parameter selection selectNoNetStations platformSelectorType  inputfileNoNetPositions filename variable {station} available, precise coordinates used for no-net constraints (in TRF) noNetTranslationSigma double (0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates noNetRotationSigma double (0 = unconstrained) sigma [m] at Earth\\'s surface for no-net rotation constraint on station coordinates noNetScaleSigma double (0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates huber double stations > huber*sigma0 are downweighted in no-net constraint huberPower double stations > huber: sigma=(e/huber)^huberPower*sigma0 name string used for parameter selection outputfileEOP filename EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S) estimatePole parametrizationTemporalType xp, yp [mas] estimateUT1 parametrizationTemporalType rotation angle [ms] estimateNutation parametrizationTemporalType dX, dY [mas] selectStations platformSelectorType  inputfileRangeBias filename variable {station} available name string used for parameter selection selectStations platformSelectorType  outputfileRangeBias filename variable {station} available selectSatellites platformSelectorType  inputfileRangeBias filename variable {satellite} available name string used for parameter selection selectSatellites platformSelectorType  outputfileRangeBias filename variable {satellite} available selectStations platformSelectorType  selectSatellites platformSelectorType  inputfileRangeBias filename variable {station} and {satellite} available name string used for parameter selection selectStations platformSelectorType  selectSatellites platformSelectorType  outputfileRangeBias filename variable {station} and {satellite} available selectStations platformSelectorType  inputfileTimeBias filename variable {station} available name string used for parameter selection selectStations platformSelectorType  estimateTimeBias parametrizationTemporalType [ms] name string  parameters parameterSelectorType parameter to constrain sigma double sigma of the constraint (same unit as parameter) bias double constrain all selected parameters towards this value relativeToApriori boolean constrain only dx and not full x=dx+x0 parametrization slrParametrizationType', 'display_text': 'This class defines the models and parameters of the linearized observation equations for normal points (see <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>) \\\\[\\\\label{slrParametrizationType:model}   \\\\M l - \\\\M f(\\\\M x_0) = \\\\left.\\\\frac{\\\\partial \\\\M f(\\\\M x)}{\\\\partial \\\\M x}\\\\right|_{\\\\M x_0} \\\\Delta\\\\M x + \\\\M\\\\epsilon, \\\\]where the left side is the observation vector minus the effects computed from the a priori models. After each least squares adjustment (see <a class=\"groops-class\" href=\"slrProcessingStepType.html#estimate\">SlrProcessing:processingStep:estimate</a>) the a priori parameters are updated \\\\[\\\\label{slrParametrizationType:update}   \\\\M x_0 := \\\\M x_0 + \\\\Delta\\\\hat{\\\\M x}. \\\\]The vector $\\\\M x_0$ can be written with <a class=\"groops-class\" href=\"slrProcessingStepType.html#writeAprioriSolution\">SlrProcessing:processingStep:writeAprioriSolution</a>. Any <strong class=\"groops-config-element\">outputfiles</strong> defined in the parametrizations are written with <a class=\"groops-class\" href=\"slrProcessingStepType.html#writeResults\">SlrProcessing:processingStep:writeResults</a>.</p><p>Each parametrization (and possible constraint equations) has a <strong class=\"groops-config-element\">name</strong> which enables activating/deactivating the estimation of subsets of $\\\\Delta\\\\M x$ with <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">SlrProcessing:processingStep:selectParametrizations</a>. The a priori model $\\\\M f(\\\\M x_0)$ is unaffected and is always reduced.</p><p>The model for the one way range observations between station $s$ and reflector $r$ can be described as \\\\[\\\\label{slrParametrizationType:slrFullModel} \\\\begin{split}   f_s^r(\\\\M x) &= \\\\frac{1}{2}\\\\left(\\\\left\\\\lVert \\\\M r^r(t_{bounce})-\\\\M r_s(t_{trans}) \\\\right\\\\rVert                           + \\\\left\\\\lVert \\\\M r_s(t_{recv})-\\\\M r^r(t_{bounce}) \\\\right\\\\rVert\\\\right)  \\\\\\\\               &+ \\\\text{troposphere}(t,\\\\M r_{ss}^r)                + \\\\text{bias}^r + \\\\text{bias}_s + \\\\text{bias}_s^r + \\\\text{other}(\\\\ldots) + \\\\epsilon_r^s \\\\end{split} \\\\] See also <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.  <h2 id=\"troposphere\">Troposphere</h2><p> A priori tropospheric correction is handled by a <a class=\"groops-class\" href=\"troposphereType.html\">troposphere</a> model (e.g. Mendes and Pavlis). Additional parameters in $[m]$ for zenith delay can be set up via <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">troposphereEstimation</a>. These parameters can be soft-constrained using <a class=\"groops-class\" href=\"slrParametrizationType.html#constraints\">parametrization:constraints</a> to avoid an unsolvable system of normal equations in case of data gaps.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>:troposphere:&lt;temporal>:&lt;interval></code>.  <h2 id=\"dynamicOrbits\">DynamicOrbits</h2><p> The estimation of (reduced) dynamic orbits is formulated as variational equations. It is based on <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> calculated with <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>. Necessary integrations are performed by integrating a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>. The <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> must include at least those parameters that were estimated in <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>. Additional <a class=\"groops-class\" href=\"timeSeriesType.html\">stochasticPulse</a> parameters can be set up to reduce orbit mismodeling.</p><p>The parameters and <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are divided into global <ul>  <li><code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite>:stochasticPulse.x::&lt;time></code>, </li><li> <code>&lt;satellite>:stochasticPulse.y::&lt;time></code>, </li><li> <code>&lt;satellite>:stochasticPulse.z::&lt;time></code>, </li></ul>  and arc related parameters <ul>  <li><code>&lt;satellite>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position0.x::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position0.y::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.position0.z::</code>. </li><li> <code>&lt;satellite>:arc&lt;no>.velocity0.x::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.velocity0.y::</code>, </li><li> <code>&lt;satellite>:arc&lt;no>.velocity0.z::</code>. </li></ul>   <h2 id=\"gravityField\">GravityField</h2><p> Estimates a (time depending) gravity field together with at least one <a class=\"groops-class\" href=\"slrParametrizationType.html#dynamicOrbits\">parametrization:dynamicOrbits</a>. The parametrization of the gravity field can be set with <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrization</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>gravityfield:&lt;parametrization>:*:*</code>.  <h2 id=\"staticPositions\">StaticPositions</h2><p> Estimates a static position for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a> in the terrestrial frame.</p><p>No-net constraints can be applied for a subset of stations, <a class=\"groops-class\" href=\"platformSelectorType.html\">selectNoNetReceivers</a>, with a standard deviation of <strong class=\"groops-config-element\">noNetTranslationSigma</strong> and <strong class=\"groops-config-element\">noNetRotationSigma</strong> and <strong class=\"groops-config-element\">noNetScaleSigma</strong> and <strong class=\"groops-config-element\">noNetScaleSigma</strong>. If the template <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a> is provided the constraints are applied relatively to these positions. Only stations with an existing position file are considered. Without <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a> the constraints are applied towards the apriori values from <a class=\"groops-class\" href=\"slrStationGeneratorType.html\">SlrProcessing:station</a>. As a single corrupted station position can disturb the no-net conditions, the rotation/translation parameters are estimated in a <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a> beforehand. The computed weight matrix is used to downweight corrupted stations in the constraint equations.</p><p>In case you want to align to an ITRF/ILRS reference frame, precise coordinates can be generated with <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>&lt;station>:position.x::</code>, </li><li> <code>&lt;station>:position.y::</code>, </li><li> <code>&lt;station>:position.z::</code>. </li></ul>   <h2 id=\"earthRotation\">EarthRotation</h2><p> Earth rotation parameters (ERPs) can be estimated by defining <strong class=\"groops-config-element\">estimatePole</strong> ($x_p$, $y_p$) and <strong class=\"groops-config-element\">estimateUT1</strong> ($dUT1, LOD$).</p><p>Estimating length of day (LOD) with the sign according to IGS conventions requires a negative value in <a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">parametrizationTemporal:trend:timeStep</a>.</p><p>Constraints on the defined parameters can be added via <a class=\"groops-class\" href=\"slrParametrizationType.html#constraints\">parametrization:constraints</a>. An example would be to set up <a class=\"groops-class\" href=\"parametrizationTemporalType.html#constant\">estimateUT1:constant</a> so the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be determined by SLR, a hard constraint to its a priori value can then be added.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <ul>  <li><code>earth:polarMotion.xp:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:polarMotion.yp:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:UT1:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:nutation.X:&lt;temporal>:&lt;interval></code>, </li><li> <code>earth:nutation.>:&lt;temporal>:&lt;interval></code>. </li></ul>   <h2 id=\"rangeBiasStationApriori\">RangeBiasStationApriori</h2><p> A priori station range bias value for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>. The <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> provides the mean range biases <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a>, but these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive satellites and not for active ones. Use <a class=\"groops-program\" href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a> to convert the range biases from <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a> to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.  <h2 id=\"rangeBiasStation\">RangeBiasStation</h2><p> Estimates a constant station range bias in $[m]$ for <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>:rangeBias::</code>.  <h2 id=\"rangeBiasSatelliteApriori\">RangeBiasSatelliteApriori</h2><p> A priori satellite range bias value for <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a>.  <h2 id=\"rangeBiasSatellite\">RangeBiasSatellite</h2><p> Estimates a constant satellite range bias in $[m]$ for <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> a <code>&lt;satellite>:rangeBias::</code>.  <h2 id=\"rangeBiasStationSatelliteApriori\">RangeBiasStationSatelliteApriori</h2><p> A priori station-satellite range bias value between all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a> - <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a> pairs.</p><p>For standard <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> processing this class should be setup twice. Once for the model from José Rodríguez (see <a class=\"groops-program\" href=\"SlrComModel2RangeBiasStationSatellite.html\">SlrComModel2RangeBiasStationSatellite</a>) and additionally for biases from the <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a> converted with <a class=\"groops-program\" href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a>.  <h2 id=\"rangeBiasStationSatellite\">RangeBiasStationSatellite</h2><p> Estimates the station-satellite range bias in $[m]$ between all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a> - <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a> pairs.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>.&lt;satellite>:rangeBias::</code>.  <h2 id=\"timeBiasApriori\">TimeBiasApriori</h2><p> A priori time bias value for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>. The <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> provides the mean time biases <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a>, but these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive satellites and not for active ones. Use <a class=\"groops-program\" href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a> to convert the time biases from <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a> to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.  <h2 id=\"timeBias\">TimeBias</h2><p> Estimates a <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">temporal changing</a> time bias in $[ms]$ for <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>:timeBias:&lt;temporal>:&lt;interval></code>.  <h2 id=\"constraints\">Constraints</h2><p> Add a pseudo observation equation (constraint) for each selected <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameters</a> \\\\[   b-x_0 = 1 \\\\cdot dx + \\\\epsilon, \\\\]where $b$ is the <strong class=\"groops-config-element\">bias</strong> and $x_0$ is the a priori value of the parameter if <strong class=\"groops-config-element\">relativeToApriori</strong> is not set. The standard deviation <strong class=\"groops-config-element\">sigma</strong> is used to weight the observation equations.  <h2 id=\"group\">Group</h2><p> Groups a set of parameters. This class can be used to structure complex parametrizations and has no further effect itself.'},\n'slrProcessingStepType': { 'name': 'slrProcessingStepType', 'key': 'slrProcessingStepType', 'description': 'Processing step in  SlrProcessing . Processing steps enable a dynamic definition of the consecutive steps performed during any kind of SLR processing. The most common steps are    , which performs an iterative least squares adjustment, and    , which writes all output files defined in  SlrProcessing  and is usually the last step. Some steps such as     and     affect all subsequent steps. In case these steps are used within a     step, they only affect the steps within this level.     Iterative non-linear least squares adjustment. In every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters. The estimated parameters serve as a priori values in the next iteration and the following processing steps. Iterates until either every single parameter update (converted to an influence in meter) is below a  convergenceThreshold  or  maxIterationCount  is reached. With  computeResiduals  the observation equations are computed again after each update to compute the observation residuals. The overall standard deviation of a single observation used for the weighting is composed of several factors  where the   is given by    :accuracy. The other factors are estimated iteratively from the residuals. With  computeWeights  a standardized variance   for each residual   is computed  taking the redundancy   into account. If   is above a threshold  huber  the observation gets a higher standard deviation used for weighting according to  similar to  robust least squares adjustment . With  adjustSigma0  an individual variance factor can be computed for each station separately      In this step all  outputfiles  defined in     are written. It considers the settings of     and    . It is usually the last processing step, but can also be used at other points in the processing in combination with  suffix  to write intermediate results.     Accumulates the normal equations matrix and writes it. If     is set only the selected parameters are written to the normal equations and all other parameters are eliminated beforehand (implicitly solved). The solution of the normals would results in   (see    ). To write the appropriate apriori vector   use    .     Writes the current apriori vector   (see    ). If     is set only the selected parameters are written.     Writes the  observation residuals  for all    . For for each station-satellite pair a file is written. The file name is interpreted as a template with the variables  {station}  and  {satellite}  being replaced by the station name.     Writes a  list  of stations (stations) which are used in the last step and selected by    .     Writes a  list  of satellites which are used in the last step and selected by    .     Print residual statistics.     station   sigma redundancy obsCount outlier   ----------------------------------------------   1874       0.52   0.86      22      1 (4.55     1889       1.20   0.98     186      5 (2.69     1890       0.63   0.77      14      1 (7.14     1891       0.49   0.50       6      0 (0.00     7237       1.08   0.95     236     14 (5.93     7394       0.36   0.88      26      0 (0.00     7811       0.38   0.41       5      0 (0.00     7819       1.21   0.94     120      1 (0.83     7821       0.69   0.95     202      3 (1.49     7827       0.40   0.85      29      1 (3.45     7839       0.52   0.93     143     10 (6.99     7840       0.15   0.80      16      0 (0.00     7841       0.26   0.90      56      1 (1.79     7941       0.55   0.92     277      5 (1.81     8834       0.66   0.88     101      1 (0.99     ----------------------------------------------   satellite sigma redundancy obsCount outlier   ----------------------------------------------   lageos1    1.04   0.94     722     24 (3.32     lageos2    0.91   0.95     590     11 (1.86     etalon1    1.19   0.78      57      2 (3.51     etalon2    1.10   0.81      70      6 (8.57     ----------------------------------------------       Enable/disable parameter groups and constraint groups for subsequent steps, e.g.     or    . The  name  and  nameConstraint  of these groups are defined in    . Prior models or previously estimated parameters used as new apriori   values are unaffected and they are always reduced from the observations. This means all unselected parameters are kept fixed to their last result.     This step can be used to process only a subset of satellites in subsequent processing steps.     This step can be used to process only a subset of stations in subsequent processing steps.     Perform these processing steps. This step can be used to structure complex processing flows. The     processing steps defined within a group only affect the steps within this group.', 'config_table': 'computeResiduals boolean  adjustSigma0 boolean adjust sigma0 by scale factor (per station) computeWeights boolean downweight outliers huber double residuals > huber*sigma0 are downweighted huberPower double residuals > huber: sigma=(e/huber)^huberPower*sigma0 convergenceThreshold double [m] stop iteration once full convergence is reached maxIterationCount uint maximum number of iterations suffix string appended to every output file name (e.g. orbit.G01.suffix.dat) outputfileNormalEquations filename normals remainingParameters parameterSelectorType parameter order/selection of output normal equations constraintsOnly boolean write only normals of constraints without observations defaultNormalsBlockSize uint block size for distributing the normal equations, 0: one block, empty: original block size outputfileAprioriSolution filename a priori parameters outputfileParameterNames filename parameter names remainingParameters parameterSelectorType parameter order/selection of output normal equations selectStations platformSelectorType subset of used stations selectSatellites platformSelectorType subset of used satellites outputfileResiduals filename variable {station} available selectStations platformSelectorType subset of used stations outputfileUsedStationList filename ascii file with names of used stations selectSatellites platformSelectorType subset of used satellites outputfileUsedSatelliteList filename ascii file with names parametrization choice  enable sequence  name string wildcards: * and ? disable sequence  name string wildcards: * and ? selectSatellites platformSelectorType  selectStations platformSelectorType  processingStep slrProcessingStepType steps are processed consecutively', 'display_text': 'Processing step in <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.</p><p>Processing steps enable a dynamic definition of the consecutive steps performed during any kind of SLR processing. The most common steps are <a class=\"groops-class\" href=\"slrProcessingStepType.html#estimate\">estimate</a>, which performs an iterative least squares adjustment, and <a class=\"groops-class\" href=\"slrProcessingStepType.html#writeResults\">writeResults</a>, which writes all output files defined in <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a> and is usually the last step. Some steps such as <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">selectParametrizations</a> and <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectStations\">selectStations</a> affect all subsequent steps. In case these steps are used within a <a class=\"groops-class\" href=\"slrProcessingStepType.html#group\">group</a> step, they only affect the steps within this level.  <h2 id=\"estimate\">Estimate</h2><p> Iterative non-linear least squares adjustment. In every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters. The estimated parameters serve as a priori values in the next iteration and the following processing steps. Iterates until either every single parameter update (converted to an influence in meter) is below a <strong class=\"groops-config-element\">convergenceThreshold</strong> or <strong class=\"groops-config-element\">maxIterationCount</strong> is reached.</p><p>With <strong class=\"groops-config-element\">computeResiduals</strong> the observation equations are computed again after each update to compute the observation residuals.</p><p>The overall standard deviation of a single observation used for the weighting is composed of several factors \\\\[   \\\\hat{\\\\sigma}_i = \\\\hat{\\\\sigma}_i^{huber} \\\\hat{\\\\sigma}^{stat} \\\\sigma_{apriori}^{stat}, \\\\]where the $\\\\sigma_{apriori}^{stat}$ is given by <a class=\"groops-class\" href=\"slrStationGeneratorType.html\">station</a>:accuracy. The other factors are estimated iteratively from the residuals.</p><p>With <strong class=\"groops-config-element\">computeWeights</strong> a standardized variance $\\\\hat{s}_i^2$ for each residual $\\\\hat{\\\\epsilon}_i$ is computed \\\\[   \\\\hat{s}_i^2 = \\\\frac{1}{\\\\hat{\\\\sigma}^{stat} \\\\sigma_{apriori}^{stat}}\\\\frac{\\\\hat{\\\\epsilon}_i^2}{r_i}   \\\\qquad\\\\text{with}\\\\qquad   r_i = \\\\left(\\\\M A\\\\left(\\\\M A^T\\\\M A\\\\right)^{-1}\\\\M A^T\\\\right)_{ii} \\\\]taking the redundancy $r_i$ into account. If $\\\\hat{s}_i$ is above a threshold <strong class=\"groops-config-element\">huber</strong> the observation gets a higher standard deviation used for weighting according to \\\\[   \\\\hat{\\\\sigma}_i^{huber} =   \\\\left\\\\{ \\\\begin{array}{ll}     1                              & s < huber,\\\\\\\\     (\\\\hat{s}_i/huber)^{huberPower} & s \\\\ge huber   \\\\end{array} \\\\right., \\\\]similar to <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>With <strong class=\"groops-config-element\">adjustSigma0</strong> an individual variance factor can be computed for each station separately \\\\[   \\\\hat{\\\\sigma}^{stat} = \\\\sqrt{\\\\frac{\\\\hat{\\\\M\\\\epsilon}^T\\\\M P\\\\hat{\\\\M\\\\epsilon}}{r}}. \\\\] <h2 id=\"writeResults\">WriteResults</h2><p> In this step all <strong class=\"groops-config-element\">outputfiles</strong> defined in <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a> are written. It considers the settings of <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">processingStep:selectParametrizations</a> and <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectStations\">processingStep:selectStations</a>.</p><p>It is usually the last processing step, but can also be used at other points in the processing in combination with <strong class=\"groops-config-element\">suffix</strong> to write intermediate results.  <h2 id=\"writeNormalEquations\">WriteNormalEquations</h2><p> Accumulates the normal equations matrix and writes it. If <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a> is set only the selected parameters are written to the normal equations and all other parameters are eliminated beforehand (implicitly solved).</p><p>The solution of the normals would results in $\\\\Delta\\\\M x$ (see <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>). To write the appropriate apriori vector $\\\\M x_0$ use <a class=\"groops-class\" href=\"slrProcessingStepType.html#writeAprioriSolution\">processingStep:writeAprioriSolution</a>.  <h2 id=\"writeAprioriSolution\">WriteAprioriSolution</h2><p> Writes the current apriori vector $\\\\M x_0$ (see <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>). If <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a> is set only the selected parameters are written.  <h2 id=\"writeResiduals\">WriteResiduals</h2><p> Writes the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">observation residuals</a> for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>. For for each station-satellite pair a file is written. The file name is interpreted as a template with the variables <code>{station}</code> and <code>{satellite}</code> being replaced by the station name.  <h2 id=\"writeUsedStationList\">WriteUsedStationList</h2><p> Writes a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of stations (stations) which are used in the last step and selected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.  <h2 id=\"writeUsedSatelliteList\">WriteUsedSatelliteList</h2><p> Writes a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of satellites which are used in the last step and selected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a>.  <h2 id=\"printResidualStatistics\">PrintResidualStatistics</h2><p> Print residual statistics. <pre>   station   sigma redundancy obsCount outlier   ----------------------------------------------   1874       0.52   0.86      22      1 (4.55    1889       1.20   0.98     186      5 (2.69    1890       0.63   0.77      14      1 (7.14    1891       0.49   0.50       6      0 (0.00    7237       1.08   0.95     236     14 (5.93    7394       0.36   0.88      26      0 (0.00    7811       0.38   0.41       5      0 (0.00    7819       1.21   0.94     120      1 (0.83    7821       0.69   0.95     202      3 (1.49    7827       0.40   0.85      29      1 (3.45    7839       0.52   0.93     143     10 (6.99    7840       0.15   0.80      16      0 (0.00    7841       0.26   0.90      56      1 (1.79    7941       0.55   0.92     277      5 (1.81    8834       0.66   0.88     101      1 (0.99    ----------------------------------------------   satellite sigma redundancy obsCount outlier   ----------------------------------------------   lageos1    1.04   0.94     722     24 (3.32    lageos2    0.91   0.95     590     11 (1.86    etalon1    1.19   0.78      57      2 (3.51    etalon2    1.10   0.81      70      6 (8.57    ---------------------------------------------- </pre>  <h2 id=\"selectParametrizations\">SelectParametrizations</h2><p> Enable/disable parameter groups and constraint groups for subsequent steps, e.g. <a class=\"groops-class\" href=\"slrProcessingStepType.html#estimate\">processingStep:estimate</a> or <a class=\"groops-class\" href=\"slrProcessingStepType.html#writeResults\">processingStep:writeResults</a>. The <strong class=\"groops-config-element\">name</strong> and <strong class=\"groops-config-element\">nameConstraint</strong> of these groups are defined in <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>. Prior models or previously estimated parameters used as new apriori $\\\\M x_0$ values are unaffected and they are always reduced from the observations. This means all unselected parameters are kept fixed to their last result.  <h2 id=\"selectSatellites\">SelectSatellites</h2><p> This step can be used to process only a subset of satellites in subsequent processing steps.  <h2 id=\"selectStations\">SelectStations</h2><p> This step can be used to process only a subset of stations in subsequent processing steps.  <h2 id=\"group\">Group</h2><p> Perform these processing steps. This step can be used to structure complex processing flows. The <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">select..</a> processing steps defined within a group only affect the steps within this group.'},\n'slrSatelliteGeneratorType': { 'name': 'slrSatelliteGeneratorType', 'key': 'slrSatelliteGeneratorType', 'description': 'Definition and basic information of SLR satellites. See also  SlrProcessing .     A list of satellite names must be provided via    . The other input files are read for each satellite, where the file name is interpreted as a template with the variable  {satellite}  being replaced by the satellite name from list. The     contains information about laser retro-reflector, optical reference point, retro-reflector orientation, range corrections and center of mass. It can be created via  PlatformCreate . If     ist not provided an orbit reference frame (along, cross, nearly nadir) is assumed.', 'config_table': 'inputfileSatelliteList filename ascii file with satellite names, used to loop variable {satellite} inputfileSatelliteInfo filename variable {satellite} available inputfileOrbit filename variable {satellite} available inputfileAttitude filename variable {satellite} available interpolationDegree uint for orbit interpolation and velocity calculation', 'display_text': 'Definition and basic information of SLR satellites.</p><p>See also <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.  <h2 id=\"satellites\">Satellites</h2><p> A list of satellite names must be provided via <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileSatelliteList</a>. The other input files are read for each satellite, where the file name is interpreted as a template with the variable <code>{satellite}</code> being replaced by the satellite name from list. The <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileSatelliteInfo</a> contains information about laser retro-reflector, optical reference point, retro-reflector orientation, range corrections and center of mass. It can be created via <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>. If <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a> ist not provided an orbit reference frame (along, cross, nearly nadir) is assumed.'},\n'slrStationGeneratorType': { 'name': 'slrStationGeneratorType', 'key': 'slrStationGeneratorType', 'description': 'Definition and basic information of SLR ground stations. See also  SlrProcessing .     A list of station names must be provided via    . It defines the variable  {station}  for the station specific input files. The     contains metadata information like station number, station name and approximate station postion in terrestrial reference frame (TRF) considering the station eccentricities. They can be created via  SinexEccentricties2SlrPlatform  or  PlatformCreate . The     are separate files for each  {station} - {satellite}  pair. They can be converted from CRD format via  Crd2NormalPoints , CSTG format via  Cstg2NormalPoints  and MERIT II format via  Merit2NormalPoints  and  Merit2FullRate . The apriori observation weighting is defined by the expression  accuracy  in  . The following variables are defined for each observation from the    :  {residual} ,  {accuracy} ,  {redundancy} ,  {laserWavelength} ,  {azimut} ,  {elevation} . Observations with non-positive accuracies are removed. This can be used for a rough outlier removal by an expression such as  accuracy  =  if(abs(residual)>30, NAN, accuracy) . The effects of loading and tidal deformation on station positions can be corrected for via     and    , respectively. Tidal deformations typically include:        : Earth tidal deformations (IERS conventions)      : ocean tidal deformations         (e.g. fes2014b n720,  minDegree = 1 )      : atmospheric tidal deformation         (e.g. AOD1B RL06,  minDegree = 1 )      : pole tidal deformations (IERS conventions)      : ocean pole tidal deformations (IERS conventions)', 'config_table': 'inputfileStationList filename ascii file with station names inputfileStationInfo filename station metadata inputfileStationPosition filename station position disableStationWithoutPosition boolean drop stations without apriori position inputfileObservations filename variable {station} {satellite} available accuracy expression [m] used for weighting, variables: {residual}, {accuracy}, {redundancy}, {laserWavelength}, {azimut}, {elevation} loadingDisplacement gravityfieldType loading deformation tidalDisplacement tidesType tidal deformation ephemerides ephemeridesType for tidal deformation inputfileDeformationLoadLoveNumber filename  inputfilePotentialLoadLoveNumber filename if full potential is given and not only loading potential elevationCutOff angle [degree] ignore observations below cutoff interpolationDegree uint for position interpolation', 'display_text': 'Definition and basic information of SLR ground stations.</p><p>See also <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.  <h2 id=\"stations\">Stations</h2><p> A list of station names must be provided via <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileStationList</a>. It defines the variable <code>{station}</code> for the station specific input files. The <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> contains metadata information like station number, station name and approximate station postion in terrestrial reference frame (TRF) considering the station eccentricities. They can be created via <a class=\"groops-program\" href=\"SinexEccentricties2SlrPlatform.html\">SinexEccentricties2SlrPlatform</a> or <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a> are separate files for each <code>{station}</code>-<code>{satellite}</code> pair. They can be converted from CRD format via <a class=\"groops-program\" href=\"Crd2NormalPoints.html\">Crd2NormalPoints</a>, CSTG format via <a class=\"groops-program\" href=\"Cstg2NormalPoints.html\">Cstg2NormalPoints</a> and MERIT II format via <a class=\"groops-program\" href=\"Merit2NormalPoints.html\">Merit2NormalPoints</a> and <a class=\"groops-program\" href=\"Merit2FullRate.html\">Merit2FullRate</a>.</p><p>The apriori observation weighting is defined by the expression <strong class=\"groops-config-element\">accuracy</strong> in $[m]$. The following variables are defined for each observation from the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: <code>{residual}</code>, <code>{accuracy}</code>, <code>{redundancy}</code>, <code>{laserWavelength}</code>, <code>{azimut}</code>, <code>{elevation}</code>. Observations with non-positive accuracies are removed. This can be used for a rough outlier removal by an expression such as <strong class=\"groops-config-element\">accuracy</strong> = <code>if(abs(residual)>30, NAN, accuracy)</code>.</p><p>The effects of loading and tidal deformation on station positions can be corrected for via <a class=\"groops-class\" href=\"gravityfieldType.html\">loadingDisplacement</a> and <a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>, respectively. Tidal deformations typically include: <ul>    <li><a class=\"groops-class\" href=\"tidesType.html#earthTide\">earthTide</a>: Earth tidal deformations (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: ocean tidal deformations         (e.g. fes2014b_n720, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: atmospheric tidal deformation         (e.g. AOD1B RL06, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#poleTide\">poleTide</a>: pole tidal deformations (IERS conventions)   </li><li> <a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">poleOceanTide</a>: ocean pole tidal deformations (IERS conventions) </li></ul>'},\n'sphericalHarmonicsFilterType': { 'name': 'sphericalHarmonicsFilterType', 'key': 'sphericalHarmonicsFilterType', 'description': 'Filtering of a spherical harmonics expansion.     Orderwise filtering with the DDK filter by Kusche et al. 2009.     Filtering the spherical harmonics expansion with a Gaussian filter.  radius  gives the filter radius on the Earth surface in km.     Filtering the spherical harmonics expansion with a matrix filter.', 'config_table': 'level uint DDK filter level (1, 2, 3, ..., 8) inputfileNormalEquation filename  radius double filter radius [km] inputfileMatrix filename  minDegree uint of matrix maxDegree uint of matrix numbering sphericalHarmonicsNumberingType numbering scheme of the matrix', 'display_text': 'Filtering of a spherical harmonics expansion.  <h2>DDK</h2><p> Orderwise filtering with the DDK filter by Kusche et al. 2009.  <h2>Gauss</h2><p> Filtering the spherical harmonics expansion with a Gaussian filter. <strong class=\"groops-config-element\">radius</strong> gives the filter radius on the Earth surface in km.  <h2>Matrix</h2><p> Filtering the spherical harmonics expansion with a matrix filter.'},\n'sphericalHarmonicsNumberingType': { 'name': 'sphericalHarmonicsNumberingType', 'key': 'sphericalHarmonicsNumberingType', 'description': 'This class organizes the numbering scheme of spherical harmonics coefficients in a parameter vector (e.g  Gravityfield2SphericalHarmonicsVector  and the design matrix of    .     Numbering degree by degree:       Numbering order by order:       Numbering order by order with cnm, snm non-alternating:       Numbering as specified in the chosen file. The     is a matrix with the first column indicating cnm/snm with 0 or 1. The second and third column specify degree and order.', 'config_table': 'inputfile filename', 'display_text': 'This class organizes the numbering scheme of spherical harmonics coefficients in a parameter vector (e.g <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a> and the design matrix of <a class=\"groops-class\" href=\"parametrizationGravityType.html#sphericalHarmonics\">parametrizationGravity:sphericalHarmoncis</a>.  <h2>Degree</h2><p> Numbering degree by degree: \\\\[ c20, c21, s21, c22, s22, c30, c31, s31, c32, s32,\\\\ldots \\\\]  <h2>Order</h2><p> Numbering order by order: \\\\[ c20, c30, c40, \\\\ldots, c21, s21, c31, s31, \\\\ldots, c22, s22 \\\\]  <h2>OrderNonAlternating</h2><p> Numbering order by order with cnm, snm non-alternating: \\\\[ c20, c30, c40, \\\\ldots, c21, c31, c41, \\\\ldots, s21, s31, s41, \\\\]  <h2>File</h2><p> Numbering as specified in the chosen file. The <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfile</a> is a matrix with the first column indicating cnm/snm with 0 or 1. The second and third column specify degree and order.'},\n'sstRightSideType': { 'name': 'sstRightSideType', 'key': 'sstRightSideType', 'description': 'Observation vector for GRACE like data (satellite-tracking and precise orbit data (POD)) of     equations in a least squares adjustment. The observations are reduced by the effect of     and     (observed minus computed).', 'config_table': 'sstRightSideType sequence  inputfileSatelliteTracking filename ranging observations and corrections inputfileOrbit1 filename kinematic positions of satellite A as observations inputfileOrbit2 filename kinematic positions of satellite B as observations inputfileAccelerometer1 filename non-gravitational forces in satellite reference frame A inputfileAccelerometer2 filename non-gravitational forces in satellite reference frame B forces forcesType', 'display_text': 'Observation vector for GRACE like data (satellite-tracking and precise orbit data (POD)) of <a class=\"groops-class\" href=\"observationType.html\">observation</a> equations in a least squares adjustment. The observations are reduced by the effect of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> and <a class=\"groops-class\" href=\"forcesType.html\">forces</a> (observed minus computed).'},\n'thermosphereType': { 'name': 'thermosphereType', 'key': 'thermosphereType', 'description': 'This class provides functions for calculating the density, temperature and velocity in the thermosphere. The wind is computed by HWM14 model if  hwm14DataDirectory  is provided. A quiet thermosphere is assumed if  inputfileMagnetic3hAp  is not given.     Thermosphere parameters from the JB2008 model: Bowman, B. R., Tobiska, W. K., Marcos, F. A., Huang, C. Y., Lin, C. S., Burke, W. J. (2008). A new empirical thermospheric density model JB2008 using new solar and geomagnetic indices.  In AIAA/AAS Astrodynamics Specialist Conference and Exhibit.  https://doi.org/10.2514/6.2008-6438      Thermosphere parameters from the NRLMSIS2 model: Emmert J.D, D.P.Drob, J.M. Picone, et al. (2020), NRLMSIS 2.0: A whole-atmosphere empirical model of temperature and neutral species densities. Earth and Space Science, Volume 8, 3  https://doi.org/10.1029/2020EA001321', 'config_table': 'inputfileSolfsmy filename solar indices inputfileDtc filename  inputfileMagnetic3hAp filename indicies for wind model hwm14DataDirectory filename directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin inputfileMsis filename input NRLMSIS 2.0 inputfileModelParameters filename path to msis20.parm file inputfileMagnetic3hAp filename indicies for wind model hwm14DataDirectory filename directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin', 'display_text': 'This class provides functions for calculating the density, temperature and velocity in the thermosphere. The wind is computed by HWM14 model if <strong class=\"groops-config-element\">hwm14DataDirectory</strong> is provided. A quiet thermosphere is assumed if <strong class=\"groops-config-element\">inputfileMagnetic3hAp</strong> is not given.  <h2>JB2008</h2><p> Thermosphere parameters from the JB2008 model:</p><p>Bowman, B. R., Tobiska, W. K., Marcos, F. A., Huang, C. Y., Lin, C. S., Burke, W. J. (2008). A new empirical thermospheric density model JB2008 using new solar and geomagnetic indices.  In AIAA/AAS Astrodynamics Specialist Conference and Exhibit. <a href=\"https://doi.org/10.2514/6.2008-6438\" target=\"_blank\">https://doi.org/10.2514/6.2008-6438</a>  <h2>NRLMSIS2</h2><p> Thermosphere parameters from the NRLMSIS2 model:</p><p>Emmert J.D, D.P.Drob, J.M. Picone, et al. (2020), NRLMSIS 2.0: A whole-atmosphere empirical model of temperature and neutral species densities. Earth and Space Science, Volume 8, 3 <a href=\"https://doi.org/10.1029/2020EA001321\" target=\"_blank\">https://doi.org/10.1029/2020EA001321</a>'},\n'tidesType': { 'name': 'tidesType', 'key': 'tidesType', 'description': 'This class computes functionals of the time depending tide potential, e.g potential, acceleration or gravity gradients. If several instances of the class are given the results are summed up. Before summation every single result is multiplicated by a  factor . To get the difference between two ocean tide models you must choose one factor by 1 and the other by -1. To get the mean of two models just set each factor to 0.5.     This class computes the tide generating potential (TGP) of sun, moon and planets (Mercury, Venus, Mars, Jupiter, Saturn). It takes into account the flattening of the Earth (At the moment only at the acceleration level). The computed result is multiplied with  factor .     This class computes the earth tide according to the IERS2003 conventions. The values of solid Earth tide external potential Love numbers and the frequency dependent corrections of these values are given in the file    . The effect of the permanent tide is removed if  includePermanentTide  is set to false. The computed result is multiplied with  factor .     The potential coefficients of the solid Earth pole tide according to the IERS2003 conventions are given by  with   is the  scale ,   is the  outPhase  and   are the wobble variables in seconds of arc. They are related to the polar motion variables   according to  The mean pole   is approximated by a polynomial read from    . The displacment is calculated with  where   is the  horizontalDisplacement  and   is the  verticalDisplacement . The computed result is multiplied with  factor .     The ocean pole tide is generated by the centrifugal effect of polar motion on the oceans. The potential coefficients of this effect is given by IERS2003 conventions are given by  where the coefficients are read from file    ,   is given by  gammaReal  and  gammaImaginary  and   are the wobble variables in radians. They are related to the polar motion variables   according to  The mean pole   is approximated by a polynomial read from    . The computed result is multiplied with  factor .     The time variable potential of ocean tides is given by a fourier expansion  where   and   are spherical harmonics expansions and are read from the file    . If set the expansion is limited in the range between  minDegree  and  maxDegree  inclusivly.   are the arguments of the tide constituents  :  where   are the Doodson\\'s fundamental arguments ( ) and   are the Doodson multipliers for the term at frequency  . The major constituents given by     can be used to interpolate minor tidal constituents using the file    . This file can be created with  DoodsonHarmonicsCalculateAdmittance . After the interpolation step a selection of the computed constituents can be choosen by    . Only these constiuents are considered for the results. If no     is set all constituents will be used. The constituents can be coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2). The computed result is multiplied with  factor .     Computes the centrifugal potential in a rotating system  The current rotation vector   is computed from the     provided by the calling program. The computed result is multiplied with  factor . Be careful, the centrifugal potential is not harmonic. Convolution with a harmonic kernel (e.g. to compute gravity anomalies) is not meaningful.     This class computes the solid moon tide according to the IERS2010 conventions. The values of solid Moon tide external potential Love numbers are given and there are no frequency dependent corrections of these values. The computed result is multiplied with  factor .     Groups a set of     and has no further effect itself.', 'config_table': 'useMoon boolean TGP of moon useSun boolean TGP of sun usePlanets boolean TGP of planets useEarth boolean TGP of Earth c20Earth double J2 flattening of the Earth factor double the result is multiplied by this factor, set -1 to subtract the field inputfileEarthtide filename  includePermanentTide boolean results in FALSE: zero tide, TRUE: tide free gravity field factor double the result is multiplied by this factor, set -1 to subtract the field scale double  outPhase double  inputfileMeanPole filename  horizontalDisplacement double [m] verticalDisplacement double [m] factor double the result is multiplied by this factor, set -1 to subtract the field inputfileOceanPole filename  minDegree uint  maxDegree uint  gammaReal double  gammaImaginary double  inputfileMeanPole filename  factor double the result is multiplied by this factor, set -1 to subtract the field inputfileTides filename  inputfileAdmittance filename interpolation of minor constituents selectDoodson doodson consider only these constituents, code number (e.g. 255.555) or darwin name (e.g. M2) minDegree uint  maxDegree uint  nodeCorr uint nodal corrections: 0-no corr, 1-IHO, 2-Schureman factor double the result is multiplied by this factor, set -1 to subtract the field factor double the result is multiplied by this factor, set -1 to subtract the field k20 double  k30 double  factor double the result is multiplied by this factor, set -1 to subtract the field tides tidesType  factor double the result is multiplied by this factor', 'display_text': 'This class computes functionals of the time depending tide potential, e.g potential, acceleration or gravity gradients.</p><p>If several instances of the class are given the results are summed up. Before summation every single result is multiplicated by a <strong class=\"groops-config-element\">factor</strong>. To get the difference between two ocean tide models you must choose one factor by 1 and the other by -1. To get the mean of two models just set each factor to 0.5.  <h2 id=\"astronomicalTide\">AstronomicalTide</h2><p> This class computes the tide generating potential (TGP) of sun, moon and planets (Mercury, Venus, Mars, Jupiter, Saturn). It takes into account the flattening of the Earth (At the moment only at the acceleration level).</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"earthTide\">EarthTide</h2><p> This class computes the earth tide according to the IERS2003 conventions. The values of solid Earth tide external potential Love numbers and the frequency dependent corrections of these values are given in the file <a class=\"groops-class\" href=\"fileFormat_earthTide.html\">inputfileEarthtide</a>. The effect of the permanent tide is removed if <strong class=\"groops-config-element\">includePermanentTide</strong> is set to false.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"poleTide\">PoleTide</h2><p> The potential coefficients of the solid Earth pole tide according to the IERS2003 conventions are given by \\\\[ \\\\begin{split} \\\\Delta c_{21} &= s\\\\cdot(m_1 + o\\\\cdot m_2), \\\\\\\\ \\\\Delta s_{21} &= s\\\\cdot(m_2 - o\\\\cdot m_1), \\\\end{split} \\\\]with $s$ is the <strong class=\"groops-config-element\">scale</strong>, $o$ is the <strong class=\"groops-config-element\">outPhase</strong> and $(m_1,m_2)$ are the wobble variables in seconds of arc. They are related to the polar motion variables $(x_p,y_p)$ according to \\\\[ \\\\begin{split} m_1 &=  (x_p - \\\\bar{x}_p), \\\\\\\\ m_2 &= -(y_p - \\\\bar{y}_p), \\\\end{split} \\\\]The mean pole $(\\\\bar{x}_p, \\\\bar{y}_p)$ is approximated by a polynomial read from <a class=\"groops-class\" href=\"fileFormat_meanPolarMotion.html\">inputfileMeanPole</a>.</p><p>The displacment is calculated with \\\\[ \\\\begin{split} S_r          &= -v\\\\sin2\\\\vartheta(m_1\\\\cos\\\\lambda+m_2\\\\sin\\\\lambda),\\\\\\\\ S_\\\\vartheta &= -h\\\\cos2\\\\vartheta(m_1\\\\cos\\\\lambda+m_2\\\\sin\\\\lambda),\\\\\\\\ S_\\\\lambda   &=  h\\\\cos\\\\vartheta(m_1\\\\sin\\\\lambda-m_2\\\\cos\\\\lambda), \\\\end{split} \\\\]where $h$ is the <strong class=\"groops-config-element\">horizontalDisplacement</strong> and $v$ is the <strong class=\"groops-config-element\">verticalDisplacement</strong>.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"oceanPoleTide\">OceanPoleTide</h2><p> The ocean pole tide is generated by the centrifugal effect of polar motion on the oceans. The potential coefficients of this effect is given by IERS2003 conventions are given by \\\\[ \\\\begin{Bmatrix} \\\\Delta c_{nm}  \\\\\\\\ \\\\Delta s_{nm} \\\\end{Bmatrix}= \\\\begin{Bmatrix} c_{nm}^R  \\\\\\\\ s_{nm}^R \\\\end{Bmatrix} (m_1\\\\gamma^R+m_2\\\\gamma^I)+ \\\\begin{Bmatrix} c_{nm}^I  \\\\\\\\ s_{nm}^I \\\\end{Bmatrix} (m_2\\\\gamma^R-m_1\\\\gamma^I) \\\\]where the coefficients are read from file <a class=\"groops-class\" href=\"fileFormat_oceanPoleTide.html\">inputfileOceanPole</a>, $\\\\gamma=\\\\gamma^R+i\\\\gamma^I$ is given by <strong class=\"groops-config-element\">gammaReal</strong> and <strong class=\"groops-config-element\">gammaImaginary</strong> and $(m_1,m_2)$ are the wobble variables in radians. They are related to the polar motion variables $(x_p,y_p)$ according to \\\\[ \\\\begin{split} m_1 &=  (x_p - \\\\bar{x}_p), \\\\\\\\ m_2 &= -(y_p - \\\\bar{y}_p), \\\\end{split} \\\\]The mean pole $(\\\\bar{x}_p, \\\\bar{y}_p)$ is approximated by a polynomial read from <a class=\"groops-class\" href=\"fileFormat_meanPolarMotion.html\">inputfileMeanPole</a>.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"doodsonHarmonicTide\">DoodsonHarmonicTide</h2><p> The time variable potential of ocean tides is given by a fourier expansion \\\\[ V(\\\\M x,t) = \\\\sum_{f} V_f^c(\\\\M x)\\\\cos(\\\\Theta_f(t)) + V_f^s(\\\\M x)\\\\sin(\\\\Theta_f(t)), \\\\]where $V_f^c(\\\\M x)$ and $V_f^s(\\\\M x)$ are spherical harmonics expansions and are read from the file <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonic</a>. If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. $\\\\Theta_f(t)$ are the arguments of the tide constituents $f$: \\\\[ \\\\Theta_f(t) = \\\\sum_{i=1}^6 n_f^i\\\\beta_i(t), \\\\]where $\\\\beta_i(t)$ are the Doodson\\'s fundamental arguments ($\\\\tau,s,h,p,N\\',p_s$) and $n_f^i$ are the Doodson multipliers for the term at frequency $f$.</p><p>The major constituents given by <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonic</a> can be used to interpolate minor tidal constituents using the file <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>. This file can be created with <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a>.</p><p>After the interpolation step a selection of the computed constituents can be choosen by <a class=\"groops-class\" href=\"doodson.html\">selectDoodson</a>. Only these constiuents are considered for the results. If no <a class=\"groops-class\" href=\"doodson.html\">selectDoodson</a> is set all constituents will be used. The constituents can be coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2).</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"centrifugal\">Centrifugal</h2><p> Computes the centrifugal potential in a rotating system \\\\[ V(\\\\M r, t) = \\\\frac{1}{2} (\\\\M\\\\omega(t)\\\\times\\\\M r)^2. \\\\]The current rotation vector $\\\\M\\\\omega(t)$ is computed from the <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a> provided by the calling program. The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.</p><p>Be careful, the centrifugal potential is not harmonic. Convolution with a harmonic kernel (e.g. to compute gravity anomalies) is not meaningful.  <h2>SolidMoonTide</h2><p> This class computes the solid moon tide according to the IERS2010 conventions. The values of solid Moon tide external potential Love numbers are given and there are no frequency dependent corrections of these values. The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.  <h2 id=\"group\">Group</h2><p> Groups a set of <a class=\"groops-class\" href=\"tidesType.html\">tides</a> and has no further effect itself.'},\n'timeSeriesType': { 'name': 'timeSeriesType', 'key': 'timeSeriesType', 'description': 'This class generates a series of points in time. The series is always sorted in ascending order. Depending of the application the series is interpreted as list of points or as intervals between the points.      Generates a time series with uniform sampling. The first point in time will be  timeStart . The last generated point in time will be less or equal  timeEnd . The time step between generated points in time is given by  sampling .     Generates a time series with uniform sampling between  timeStart  and  timeEnd .  intervallCount  gives the count of intervals. This class generates count+1 points in time inclusive  timeStart  and  timeEnd .     The points of the time series are given explicitly with  time .     If  useMonthMiddle  is set, time points are generated at mid of each month inclusively the  monthStart  in  yearStart  and  monthEnd  in  yearEnd . Otherwise times are given at the first of each month and a time point after the last month.     If  useYearMiddle  is set, time points are generated at mid of each year inclusively  yearStart  and  yearEnd . Otherwise times are given at the first of each year and a time point after the last year.     Generates a time series with monthly sampling. The first point in time will be  timeStart  and the following points are generated for each month at the same day and time in month. The last generated point in time will be less or equal  timeEnd .     Generates a time series with yearly sampling. The first point in time will be  timeStart  and the following points are generated for each year at the same day and time in year. The last generated point in time will be less or equal  timeEnd .     Read a time series (epochs) from an  instrument file . The time series can be restricted to the interval starting from  timeStart  and before  timeEnd .     Reconstruct a time series from an  instrument file . The time series is the first epoch of each arc plus one time step beyond the last epoch of the last arc (using median sampling).     Reads an  orbit file  and create a time stamp for each ascending equator crossing. The time series can be restricted to the interval starting from  timeStart  and before  timeEnd .     In a first step a     is generated. In a second step all times are removed which are in range before or after  excludeMargin  seconds of the times given by    .     Only times for which the     is met are included in the time series. The  variableLoopTime  is set to every time and the     is evaluated.     Interpolates  nodeInterpolation  count points between the given     uniformly.', 'config_table': 'timeStart time first point in time timeEnd time last point in time will be less or equal timeEnd sampling time time step between points in time timeStart time 1st point of the time series timeEnd time last point of the time series intervalCount uint count of intervals, count+1 points in time will generated time time explicit list of points in time monthStart uint  yearStart uint  monthEnd uint  yearEnd uint  useMonthMiddle boolean time points are mid of months, otherwise the 1st of each month + a time point behind the last month yearStart uint  yearEnd uint  useYearMiddle boolean time points are mid of years, otherwise the 1st of each year + a time point behind the last year timeStart time first point in time timeEnd time last point in time will be less or equal timeEnd timeStart time first point in time timeEnd time last point in time will be less or equal timeEnd inputfileInstrument filename  timeStart time inclusive, i.e. exclude eochs before this epoch timeEnd time exclusive, i.e. only epochs before this time are used inputfileInstrument filename Must be regular. Time series is first epoch of each arc plus one time step extrapolated from last epoch of last arc. inputfileOrbit filename  timeStart time exclude eochs before this epoch timeEnd time only epochs before this time are used timeSeries timeSeriesType time series to be created timeSeriesExclude timeSeriesType exclude this time points from time series (within margin) excludeMargin double on both sides [seconds] timeSeries timeSeriesType only times for which condition is met will be included variableLoopTime string variable with time of each loop condition conditionType test for each time timeSeries timeSeriesType time series to be created nodeInterpolation uint interpolates count points in each time interval given by the time series', 'display_text': 'This class generates a series of points in time. The series is always sorted in ascending order. Depending of the application the series is interpreted as list of points or as intervals between the points.</p><p>  <h2 id=\"uniformSampling\">UniformSampling</h2><p> Generates a time series with uniform sampling. The first point in time will be <strong class=\"groops-config-element\">timeStart</strong>. The last generated point in time will be less or equal <strong class=\"groops-config-element\">timeEnd</strong>. The time step between generated points in time is given by <strong class=\"groops-config-element\">sampling</strong>.  <h2>UniformInterval</h2><p> Generates a time series with uniform sampling between <strong class=\"groops-config-element\">timeStart</strong> and <strong class=\"groops-config-element\">timeEnd</strong>. <strong class=\"groops-config-element\">intervallCount</strong> gives the count of intervals. This class generates count+1 points in time inclusive <strong class=\"groops-config-element\">timeStart</strong> and <strong class=\"groops-config-element\">timeEnd</strong>.  <h2 id=\"irregular\">Irregular</h2><p> The points of the time series are given explicitly with <strong class=\"groops-config-element\">time</strong>.  <h2>Monthly</h2><p> If <strong class=\"groops-config-element\">useMonthMiddle</strong> is set, time points are generated at mid of each month inclusively the <strong class=\"groops-config-element\">monthStart</strong> in <strong class=\"groops-config-element\">yearStart</strong> and <strong class=\"groops-config-element\">monthEnd</strong> in <strong class=\"groops-config-element\">yearEnd</strong>. Otherwise times are given at the first of each month and a time point after the last month.  <h2>Yearly</h2><p> If <strong class=\"groops-config-element\">useYearMiddle</strong> is set, time points are generated at mid of each year inclusively <strong class=\"groops-config-element\">yearStart</strong> and <strong class=\"groops-config-element\">yearEnd</strong>. Otherwise times are given at the first of each year and a time point after the last year.  <h2>EveryMonth</h2><p> Generates a time series with monthly sampling. The first point in time will be <strong class=\"groops-config-element\">timeStart</strong> and the following points are generated for each month at the same day and time in month. The last generated point in time will be less or equal <strong class=\"groops-config-element\">timeEnd</strong>.  <h2>EveryYear</h2><p> Generates a time series with yearly sampling. The first point in time will be <strong class=\"groops-config-element\">timeStart</strong> and the following points are generated for each year at the same day and time in year. The last generated point in time will be less or equal <strong class=\"groops-config-element\">timeEnd</strong>.  <h2 id=\"instrument\">Instrument</h2><p> Read a time series (epochs) from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The time series can be restricted to the interval starting from <strong class=\"groops-config-element\">timeStart</strong> and before <strong class=\"groops-config-element\">timeEnd</strong>.  <h2>InstrumentArcIntervals</h2><p> Reconstruct a time series from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>. The time series is the first epoch of each arc plus one time step beyond the last epoch of the last arc (using median sampling).  <h2>Revolution</h2><p> Reads an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit file</a> and create a time stamp for each ascending equator crossing. The time series can be restricted to the interval starting from <strong class=\"groops-config-element\">timeStart</strong> and before <strong class=\"groops-config-element\">timeEnd</strong>.  <h2>Exclude</h2><p> In a first step a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is generated. In a second step all times are removed which are in range before or after <strong class=\"groops-config-element\">excludeMargin</strong> seconds of the times given by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeriesExclude</a>.  <h2>Conditional</h2><p> Only times for which the <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is met are included in the time series. The <strong class=\"groops-config-element\">variableLoopTime</strong> is set to every time and the <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is evaluated.  <h2>Interpolate</h2><p> Interpolates <strong class=\"groops-config-element\">nodeInterpolation</strong> count points between the given <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> uniformly.'},\n'troposphereType': { 'name': 'troposphereType', 'key': 'troposphereType', 'description': 'This class provides functions for calculating and estimating the signal delay in the dry and wet atmosphere.    Tropospheric delays based on the Vienna Mapping Functions 3 (VMF3) model (Landskron and Boehm 2017, DOI:  ). Hydrostatic and wet mapping function coefficients ( ,  ) and zenith delays (ZHD, ZWD) have to be provided via    . This file can contain either station-specific data (see  ViennaMappingFunctionStation2File ) or data on a regular global grid (see  ViennaMappingFunctionGrid2File ). In the second case mapping coefficients and zenith delays are interpolated to the requested coordinates. This includes a height correction that requires approximate meteorological data provided via    .    Tropospheric delays based on the Global Pressure and Temperature 3 (GPT3) model (Landskron and Boehm 2017, DOI:  ). It is an empirical model derived from the Vienna Mapping Functions 3 (VMF3, see    ) and thus does not require additional mapping coefficients and zenith delay values.    Tropospheric delays based on the Mendes-Pavlis model that employs meteorological data. (Mendes et al. (2002),   and Mendes and Pavlis (2004),  ) The meteorological data have to be provided via    . This file contains the temperature, air pressure and humidity and must be first generated using the programs  Crd2NormalPoints ,  Cstg2NormalPoints ,  Merit2NormalPoints  or  Merit2FullRate .', 'config_table': 'inputfileVmfCoefficients filename ah, aw, zhd, zwd coefficients inputfileGpt filename gridded GPT data aHeight double parameter a (height correction) bHeight double parameter b (height correction) cHeight double parameter c (height correction) inputfileGpt filename gridded GPT data aHeight double parameter a (height correction) bHeight double parameter b (height correction) cHeight double parameter c (height correction) inputfileStationMeteorology filename', 'display_text': 'This class provides functions for calculating and estimating the signal delay in the dry and wet atmosphere.  <h2 id=\"viennaMapping\">ViennaMapping</h2><p></p><p>Tropospheric delays based on the Vienna Mapping Functions 3 (VMF3) model (Landskron and Boehm 2017, DOI: <a href=\"https://doi.org/10.1007/s00190-017-1066-2\">10.1007/s00190-017-1066-2</a>).</p><p>Hydrostatic and wet mapping function coefficients ($a_h$, $a_w$) and zenith delays (ZHD, ZWD) have to be provided via <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileVmfCoefficients</a>. This file can contain either station-specific data (see <a class=\"groops-program\" href=\"ViennaMappingFunctionStation2File.html\">ViennaMappingFunctionStation2File</a>) or data on a regular global grid (see <a class=\"groops-program\" href=\"ViennaMappingFunctionGrid2File.html\">ViennaMappingFunctionGrid2File</a>). In the second case mapping coefficients and zenith delays are interpolated to the requested coordinates. This includes a height correction that requires approximate meteorological data provided via <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGpt</a>.  <h2 id=\"gpt\">GPT</h2><p></p><p>Tropospheric delays based on the Global Pressure and Temperature 3 (GPT3) model (Landskron and Boehm 2017, DOI: <a href=\"https://doi.org/10.1007/s00190-017-1066-2\">10.1007/s00190-017-1066-2</a>).</p><p>It is an empirical model derived from the Vienna Mapping Functions 3 (VMF3, see <a class=\"groops-class\" href=\"troposphereType.html#viennaMapping\">viennaMapping</a>) and thus does not require additional mapping coefficients and zenith delay values.  <h2 id=\"mendesAndPavlis\">MendesAndPavlis</h2><p></p><p>Tropospheric delays based on the Mendes-Pavlis model that employs meteorological data. (Mendes et al. (2002), <a href=\"https://doi.org/10.1029/2001GL014394\">10.1029/2001GL014394</a> and Mendes and Pavlis (2004), <a href=\"https://doi.org/10.1029/2004GL020308\">110.1029/2004GL020308</a>)</p><p>The meteorological data have to be provided via <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStationMeteorology</a>. This file contains the temperature, air pressure and humidity and must be first generated using the programs <a class=\"groops-program\" href=\"Crd2NormalPoints.html\">Crd2NormalPoints</a>, <a class=\"groops-program\" href=\"Cstg2NormalPoints.html\">Cstg2NormalPoints</a>, <a class=\"groops-program\" href=\"Merit2NormalPoints.html\">Merit2NormalPoints</a> or <a class=\"groops-program\" href=\"Merit2FullRate.html\">Merit2FullRate</a>.'},\n'general.fileFormat': { 'name': 'general.fileFormat', 'key': 'general.fileFormat', 'description': 'All GROOPS files are written either in XML, JSON, binary, or ASCII format depending on the filename extension.    .xml : XML format  .json : JSON format  .dat : binary format  .txt  and all other extensions: ASCII format  With an additional extension of \\' .gz \\' files are directly compressed and uncompressed. It is also possible to directly uncompress and read (but not write)  \\'d files (\\' .Z \\'). Comments are allowed in ASCII files and all the text starting from the character \\' # \\' to the end of the line is ignored. The program  FileConvert  can be used to convert between the different formats. This program is also useful to get some general information of files in binary format. The following special file types are used in GROOPS:', 'config_table': '', 'display_text': 'All GROOPS files are written either in XML, JSON, binary, or ASCII format depending on the filename extension. <ul>  <li><code>.xml</code>: XML format </li><li> <code>.json</code>: JSON format </li><li> <code>.dat</code>: binary format </li><li> <code>.txt</code> and all other extensions: ASCII format </li></ul> </p><p>With an additional extension of \\'<code>.gz</code>\\' files are directly compressed and uncompressed. It is also possible to directly uncompress and read (but not write) <a href=\"https://en.wikipedia.org/wiki/Compress\">Unix compress</a>\\'d files (\\'<code>.Z</code>\\').</p><p>Comments are allowed in ASCII files and all the text starting from the character \\'<code>#</code>\\' to the end of the line is ignored.</p><p>The program <a class=\"groops-program\" href=\"FileConvert.html\">FileConvert</a> can be used to convert between the different formats. This program is also useful to get some general information of files in binary format.</p><p>The following special file types are used in GROOPS:'},\n'fileFormat_admittance': { 'name': 'Admittance', 'key': 'fileFormat_admittance', 'description': 'Interpolation matrix to create ocean minor tides from modeled major tides. The file can be created with  DoodsonHarmonicsCalculateAdmittance  and used e.g. in   Interpolation matrix to create ocean minor tides from modeled major tides. The file can be created with  . See  DoodsonHarmonicsCalculateAdmittance .', 'config_table': '', 'display_text': 'Interpolation matrix to create ocean minor tides from modeled major tides. The file can be created with <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a> and used e.g. in <a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>.</p><p>See <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a>.'},\n'fileFormat_arcList': { 'name': 'ArcList', 'key': 'fileFormat_arcList', 'description': 'With the  InstrumentSynchronize  an  instrument file  can be divided into time intervals and within the intervals into arcs. This file provides the information about the mapping of arcs to time intervals. This file can be used for the variational equation approach or  KalmanBuildNormals .  groops arclist version=20200123          32  # number of times # time [MJD]               first arc # ==================================  58909.000000000000000000          0  58910.000000000000000000          8  58911.000000000000000000         17  58912.000000000000000000         25  58913.000000000000000000         29  58914.000000000000000000         37  58915.000000000000000000         45  58916.000000000000000000         53  58917.000000000000000000         61  58918.000000000000000000         69  58919.000000000000000000         78  58920.000000000000000000         86  58921.000000000000000000         95  58922.000000000000000000        103  58923.000000000000000000        112  58924.000000000000000000        120  58925.000000000000000000        128  58926.000000000000000000        136  58927.000000000000000000        144  58928.000000000000000000        153  58929.000000000000000000        161  58930.000000000000000000        169  58931.000000000000000000        177  58932.000000000000000000        185  58933.000000000000000000        193  58934.000000000000000000        201  58935.000000000000000000        210  58936.000000000000000000        218  58937.000000000000000000        226  58938.000000000000000000        234  58939.000000000000000000        242  58940.000000000000000000        250', 'config_table': '', 'display_text': 'With the <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a> an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> can be divided into time intervals and within the intervals into arcs. This file provides the information about the mapping of arcs to time intervals.</p><p>This file can be used for the variational equation approach or <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>.</p><p><pre> groops arclist version=20200123          32  # number of times # time [MJD]               first arc # ==================================  58909.000000000000000000          0  58910.000000000000000000          8  58911.000000000000000000         17  58912.000000000000000000         25  58913.000000000000000000         29  58914.000000000000000000         37  58915.000000000000000000         45  58916.000000000000000000         53  58917.000000000000000000         61  58918.000000000000000000         69  58919.000000000000000000         78  58920.000000000000000000         86  58921.000000000000000000         95  58922.000000000000000000        103  58923.000000000000000000        112  58924.000000000000000000        120  58925.000000000000000000        128  58926.000000000000000000        136  58927.000000000000000000        144  58928.000000000000000000        153  58929.000000000000000000        161  58930.000000000000000000        169  58931.000000000000000000        177  58932.000000000000000000        185  58933.000000000000000000        193  58934.000000000000000000        201  58935.000000000000000000        210  58936.000000000000000000        218  58937.000000000000000000        226  58938.000000000000000000        234  58939.000000000000000000        242  58940.000000000000000000        250 </pre>'},\n'fileFormat_doodsonEarthOrientationParameter': { 'name': 'DoodsonEarthOrientationParameter', 'key': 'fileFormat_doodsonEarthOrientationParameter', 'description': 'Corrections for Earth orientation parameters (EOP) ( ) as cos/sin oscillations for a list of doodson tidal frequencies.  groops doodsonEarthOrientationParameter version=20200123         11 # number of constituents # dood.   xpCos [arcsec]            xpSin [arcsec]            ypCos [arcsec]            ypSin [arcsec]            ut1Cos [sec]              ut1Sin [sec]              lodCos [sec]              lodSin [sec]             name # ===========================================================================================================================================================================================================================  155.645  2.399999999999999786e-07  1.799999999999999971e-07  1.799999999999999971e-07 -2.399999999999999786e-07 -2.000000000000000042e-08  2.000000000000000042e-08 -1.499999999999999932e-07 -1.400000000000000095e-07 \"\"  155.655 -8.220000000000000920e-06 -6.280000000000000012e-06 -6.280000000000000012e-06  8.220000000000000920e-06  7.899999999999999537e-07 -8.599999999999999187e-07  5.219999999999999150e-06  4.829999999999999496e-06 m1  155.665 -1.649999999999999872e-06 -1.260000000000000007e-06 -1.260000000000000007e-06  1.649999999999999872e-06  1.600000000000000033e-07 -1.700000000000000135e-07  1.049999999999999900e-06  9.700000000000000302e-07 \"\"  157.455 -1.539999999999999867e-06 -1.199999999999999946e-06 -1.199999999999999946e-06  1.539999999999999867e-06  1.499999999999999932e-07 -1.600000000000000033e-07  9.799999999999999345e-07  8.899999999999999491e-07 chi1  157.465 -3.400000000000000270e-07 -2.599999999999999988e-07 -2.599999999999999988e-07  3.400000000000000270e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.099999999999999746e-07  1.999999999999999909e-07 \"\"  161.557  9.999999999999999547e-08  8.000000000000000167e-08  8.000000000000000167e-08 -9.999999999999999547e-08 -1.000000000000000021e-08  1.000000000000000021e-08 -7.000000000000000477e-08 -4.999999999999999774e-08 \"\"  162.556  2.549999999999999726e-06  2.019999999999999718e-06  2.019999999999999718e-06 -2.549999999999999726e-06 -2.099999999999999746e-07  2.899999999999999763e-07 -1.799999999999999919e-06 -1.289999999999999931e-06 pi1  163.545 -4.899999999999999672e-07 -3.799999999999999616e-07 -3.799999999999999616e-07  4.899999999999999672e-07  4.000000000000000084e-08 -5.999999999999999464e-08  3.499999999999999842e-07  2.399999999999999786e-07 \"\"  163.555  4.272999999999999238e-05  3.010999999999999801e-05  3.010999999999999801e-05 -4.272999999999999238e-05 -3.079999999999999734e-06  5.219999999999999150e-06 -3.270999999999999684e-05 -1.929999999999999817e-05 p1  164.554 -3.599999999999999943e-07 -2.800000000000000191e-07 -2.800000000000000191e-07  3.599999999999999943e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.700000000000000090e-07  1.700000000000000135e-07 \"\"  164.556 -1.029999999999999879e-06 -7.999999999999999638e-07 -7.999999999999999638e-07  1.029999999999999879e-06  8.000000000000000167e-08 -1.199999999999999893e-07  7.599999999999999233e-07  4.899999999999999672e-07 \"\"', 'config_table': '', 'display_text': 'Corrections for Earth orientation parameters (EOP) ($x_p, y_p, UT1, LOD$) as cos/sin oscillations for a list of doodson tidal frequencies.</p><p><pre> groops doodsonEarthOrientationParameter version=20200123         11 # number of constituents # dood.   xpCos [arcsec]            xpSin [arcsec]            ypCos [arcsec]            ypSin [arcsec]            ut1Cos [sec]              ut1Sin [sec]              lodCos [sec]              lodSin [sec]             name # ===========================================================================================================================================================================================================================  155.645  2.399999999999999786e-07  1.799999999999999971e-07  1.799999999999999971e-07 -2.399999999999999786e-07 -2.000000000000000042e-08  2.000000000000000042e-08 -1.499999999999999932e-07 -1.400000000000000095e-07 \"\"  155.655 -8.220000000000000920e-06 -6.280000000000000012e-06 -6.280000000000000012e-06  8.220000000000000920e-06  7.899999999999999537e-07 -8.599999999999999187e-07  5.219999999999999150e-06  4.829999999999999496e-06 m1  155.665 -1.649999999999999872e-06 -1.260000000000000007e-06 -1.260000000000000007e-06  1.649999999999999872e-06  1.600000000000000033e-07 -1.700000000000000135e-07  1.049999999999999900e-06  9.700000000000000302e-07 \"\"  157.455 -1.539999999999999867e-06 -1.199999999999999946e-06 -1.199999999999999946e-06  1.539999999999999867e-06  1.499999999999999932e-07 -1.600000000000000033e-07  9.799999999999999345e-07  8.899999999999999491e-07 chi1  157.465 -3.400000000000000270e-07 -2.599999999999999988e-07 -2.599999999999999988e-07  3.400000000000000270e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.099999999999999746e-07  1.999999999999999909e-07 \"\"  161.557  9.999999999999999547e-08  8.000000000000000167e-08  8.000000000000000167e-08 -9.999999999999999547e-08 -1.000000000000000021e-08  1.000000000000000021e-08 -7.000000000000000477e-08 -4.999999999999999774e-08 \"\"  162.556  2.549999999999999726e-06  2.019999999999999718e-06  2.019999999999999718e-06 -2.549999999999999726e-06 -2.099999999999999746e-07  2.899999999999999763e-07 -1.799999999999999919e-06 -1.289999999999999931e-06 pi1  163.545 -4.899999999999999672e-07 -3.799999999999999616e-07 -3.799999999999999616e-07  4.899999999999999672e-07  4.000000000000000084e-08 -5.999999999999999464e-08  3.499999999999999842e-07  2.399999999999999786e-07 \"\"  163.555  4.272999999999999238e-05  3.010999999999999801e-05  3.010999999999999801e-05 -4.272999999999999238e-05 -3.079999999999999734e-06  5.219999999999999150e-06 -3.270999999999999684e-05 -1.929999999999999817e-05 p1  164.554 -3.599999999999999943e-07 -2.800000000000000191e-07 -2.800000000000000191e-07  3.599999999999999943e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.700000000000000090e-07  1.700000000000000135e-07 \"\"  164.556 -1.029999999999999879e-06 -7.999999999999999638e-07 -7.999999999999999638e-07  1.029999999999999879e-06  8.000000000000000167e-08 -1.199999999999999893e-07  7.599999999999999233e-07  4.899999999999999672e-07 \"\" </pre>'},\n'fileFormat_doodsonHarmonic': { 'name': 'DoodsonHarmonic', 'key': 'fileFormat_doodsonHarmonic', 'description': 'Ocean tides are represented as time variable gravitational potential and is given by a fourier expansion  where   and   are spherical harmonics. The   are the arguments of the tide constituents  :  where   are the Doodson\\'s fundamental arguments ( ) and   are the Doodson multipliers for the term at frequency  . To extract the potential coefficients of   and   for each frequency   use  DoodsonHarmonics2PotentialCoefficients . See also  PotentialCoefficients2DoodsonHarmonics .', 'config_table': '', 'display_text': 'Ocean tides are represented as time variable gravitational potential and is given by a fourier expansion \\\\[ V(\\\\M x,t) = \\\\sum_{f} V_f^c(\\\\M x)\\\\cos(\\\\Theta_f(t)) + V_f^s(\\\\M x)\\\\sin(\\\\Theta_f(t)), \\\\]where $V_f^c(\\\\M x)$ and $V_f^s(\\\\M x)$ are spherical harmonics. The $\\\\Theta_f(t)$ are the arguments of the tide constituents $f$: \\\\[ \\\\Theta_f(t) = \\\\sum_{i=1}^6 n_f^i\\\\beta_i(t), \\\\]where $\\\\beta_i(t)$ are the Doodson\\'s fundamental arguments ($\\\\tau,s,h,p,N\\',p_s$) and $n_f^i$ are the Doodson multipliers for the term at frequency $f$.</p><p>To extract the potential coefficients of $V_f^c$ and $V_f^s$ for each frequency $f$ use <a class=\"groops-program\" href=\"DoodsonHarmonics2PotentialCoefficients.html\">DoodsonHarmonics2PotentialCoefficients</a>.</p><p>See also <a class=\"groops-program\" href=\"PotentialCoefficients2DoodsonHarmonics.html\">PotentialCoefficients2DoodsonHarmonics</a>.'},\n'fileFormat_earthOrientationParameter': { 'name': 'EarthOrientationParameter', 'key': 'fileFormat_earthOrientationParameter', 'description': 'Earth Orientation Parameter (EOP) as provided by the International Earth Rotation and Reference Systems Service (IERS) (e.g  EOP 14 C04 (IAU2000A) ). See  IersC04IAU2000EarthOrientationParameter ,  IersRapidIAU2000EarthOrientationParameter .  groops earthOrientationParameter version=20200123        9641 # number of epochs # UTC [MJD]                 xp [arcsec]               yp [arcsec]               deltUT [sec]              LOD [sec]                 dX [arcsec]               dY [arcsec] # ====================================================================================================================================================================================   5.894700000000000000e+04  5.690599999999999825e-02  4.099130000000000273e-01 -2.316246000000000138e-01  1.636400000000000094e-03 -2.900000000000000017e-05  5.800000000000000034e-05   5.894800000000000000e+04  5.771400000000000141e-02  4.110159999999999925e-01 -2.332083000000000073e-01  1.520099999999999923e-03 -6.000000000000000152e-05  2.199999999999999943e-05   5.894900000000000000e+04  5.813000000000000111e-02  4.120099999999999874e-01 -2.346157000000000104e-01  1.293099999999999935e-03 -7.200000000000000182e-05  3.199999999999999855e-05   5.895000000000000000e+04  5.854100000000000276e-02  4.129849999999999910e-01 -2.357567999999999886e-01  9.872999999999999832e-04 -7.600000000000000418e-05  5.899999999999999754e-05   5.895100000000000000e+04  5.908599999999999963e-02  4.139869999999999939e-01 -2.366149999999999920e-01  7.075000000000000126e-04 -8.000000000000000654e-05  8.600000000000000331e-05   5.895200000000000000e+04  5.976900000000000268e-02  4.154180000000000095e-01 -2.372105999999999937e-01  4.798000000000000073e-04 -8.399999999999999535e-05  1.129999999999999955e-04   5.895300000000000000e+04  6.095400000000000124e-02  4.167310000000000181e-01 -2.375994999999999913e-01  3.118999999999999919e-04 -8.700000000000000051e-05  1.399999999999999877e-04   5.895400000000000000e+04  6.210199999999999748e-02  4.180929999999999924e-01 -2.378588000000000091e-01  1.710000000000000094e-04 -9.100000000000000287e-05  1.669999999999999935e-04   5.895500000000000000e+04  6.290999999999999370e-02  4.196619999999999795e-01 -2.380454999999999932e-01  1.719000000000000042e-04 -6.000000000000000152e-06  8.100000000000000375e-05   5.895600000000000000e+04  6.385599999999999610e-02  4.214060000000000028e-01 -2.382557999999999898e-01  2.683000000000000163e-04  1.029999999999999964e-04 -3.600000000000000091e-05   5.895700000000000000e+04  6.455500000000000127e-02  4.229890000000000039e-01 -2.385857000000000117e-01  4.040000000000000080e-04  1.019999999999999992e-04 -2.000000000000000164e-05   5.895800000000000000e+04  6.440300000000000191e-02  4.242549999999999932e-01 -2.390210000000000112e-01  4.910999999999999567e-04  5.899999999999999754e-05  4.399999999999999886e-05', 'config_table': '', 'display_text': 'Earth Orientation Parameter (EOP) as provided by the International Earth Rotation and Reference Systems Service (IERS) (e.g <code>EOP 14 C04 (IAU2000A)</code>).</p><p>See <a class=\"groops-program\" href=\"IersC04IAU2000EarthOrientationParameter.html\">IersC04IAU2000EarthOrientationParameter</a>, <a class=\"groops-program\" href=\"IersRapidIAU2000EarthOrientationParameter.html\">IersRapidIAU2000EarthOrientationParameter</a>.</p><p><pre> groops earthOrientationParameter version=20200123        9641 # number of epochs # UTC [MJD]                 xp [arcsec]               yp [arcsec]               deltUT [sec]              LOD [sec]                 dX [arcsec]               dY [arcsec] # ====================================================================================================================================================================================   5.894700000000000000e+04  5.690599999999999825e-02  4.099130000000000273e-01 -2.316246000000000138e-01  1.636400000000000094e-03 -2.900000000000000017e-05  5.800000000000000034e-05   5.894800000000000000e+04  5.771400000000000141e-02  4.110159999999999925e-01 -2.332083000000000073e-01  1.520099999999999923e-03 -6.000000000000000152e-05  2.199999999999999943e-05   5.894900000000000000e+04  5.813000000000000111e-02  4.120099999999999874e-01 -2.346157000000000104e-01  1.293099999999999935e-03 -7.200000000000000182e-05  3.199999999999999855e-05   5.895000000000000000e+04  5.854100000000000276e-02  4.129849999999999910e-01 -2.357567999999999886e-01  9.872999999999999832e-04 -7.600000000000000418e-05  5.899999999999999754e-05   5.895100000000000000e+04  5.908599999999999963e-02  4.139869999999999939e-01 -2.366149999999999920e-01  7.075000000000000126e-04 -8.000000000000000654e-05  8.600000000000000331e-05   5.895200000000000000e+04  5.976900000000000268e-02  4.154180000000000095e-01 -2.372105999999999937e-01  4.798000000000000073e-04 -8.399999999999999535e-05  1.129999999999999955e-04   5.895300000000000000e+04  6.095400000000000124e-02  4.167310000000000181e-01 -2.375994999999999913e-01  3.118999999999999919e-04 -8.700000000000000051e-05  1.399999999999999877e-04   5.895400000000000000e+04  6.210199999999999748e-02  4.180929999999999924e-01 -2.378588000000000091e-01  1.710000000000000094e-04 -9.100000000000000287e-05  1.669999999999999935e-04   5.895500000000000000e+04  6.290999999999999370e-02  4.196619999999999795e-01 -2.380454999999999932e-01  1.719000000000000042e-04 -6.000000000000000152e-06  8.100000000000000375e-05   5.895600000000000000e+04  6.385599999999999610e-02  4.214060000000000028e-01 -2.382557999999999898e-01  2.683000000000000163e-04  1.029999999999999964e-04 -3.600000000000000091e-05   5.895700000000000000e+04  6.455500000000000127e-02  4.229890000000000039e-01 -2.385857000000000117e-01  4.040000000000000080e-04  1.019999999999999992e-04 -2.000000000000000164e-05   5.895800000000000000e+04  6.440300000000000191e-02  4.242549999999999932e-01 -2.390210000000000112e-01  4.910999999999999567e-04  5.899999999999999754e-05  4.399999999999999886e-05 </pre>'},\n'fileFormat_earthTide': { 'name': 'EarthTide', 'key': 'fileFormat_earthTide', 'description': 'Containing the Love numbers together with frequency corrections to compute the gravitational potential and the geometric displacements due to solid Earth tides. It is used by   Containing the Love numbers together with frequency corrections to compute the gravitational potential and the geometric displacements due to solid Earth tides. It is used by  .', 'config_table': '', 'display_text': 'Containing the Love numbers together with frequency corrections to compute the gravitational potential and the geometric displacements due to solid Earth tides. It is used by <a class=\"groops-class\" href=\"tidesType.html\">tides</a>.'},\n'fileFormat_ephemerides': { 'name': 'Ephemerides', 'key': 'fileFormat_ephemerides', 'description': 'Ephemerides of sun, moon, and planets stored as coefficients of Chebyshev polynomials. Used in   Ephemerides of sun, moon, and planets stored as coefficients of Chebyshev polynomials. Used in  . See also  JplAscii2Ephemerides .', 'config_table': '', 'display_text': 'Ephemerides of sun, moon, and planets stored as coefficients of Chebyshev polynomials. Used in <a class=\"groops-class\" href=\"ephemeridesType.html#jpl\">Ephemerides:jpl</a>.</p><p>See also <a class=\"groops-program\" href=\"JplAscii2Ephemerides.html\">JplAscii2Ephemerides</a>.'},\n'fileFormat_gnssAntennaDefinition': { 'name': 'GnssAntennaDefinition', 'key': 'fileFormat_gnssAntennaDefinition', 'description': 'Contains a list of GNSS antennas which are identified by its name (type), serial, and radome. Each antenna consists of antenna center offsets (ACO) and antenna center variations (ACV) for different signal   Contains a list of GNSS antennas which are identified by its name (type), serial, and radome. Each antenna consists of antenna center offsets (ACO) and antenna center variations (ACV) for different signal   (code and phase). The ACV values for each type are stored in an elevation and azimuth dependent grid.     See also  GnssAntennaDefinitionCreate ,  GnssAntex2AntennaDefinition .  &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"antennaDefinition\" version=\"20190429\">     &lt;antennaCount>65&lt;/antennaCount>     ...     &lt;antenna>         &lt;name>BLOCK IIIA&lt;/name>         &lt;serial>G074&lt;/serial>         &lt;radome>2018-109A&lt;/radome>         &lt;comment>PCO provided by the Aerospace Corporation, PV from estimations by ESA/CODE&lt;/comment>         &lt;pattern>             &lt;count>3&lt;/count>             &lt;cell>                 &lt;type>*1*G**&lt;/type>                 &lt;offset>                     &lt;x>-1.23333333333333e-03&lt;/x>                     &lt;y>4.33333333333333e-04&lt;/y>                     &lt;z>3.15200000000000e-01&lt;/z>                 &lt;/offset>                 &lt;dZenit>1.00000000000000e+00&lt;/dZenit>                 &lt;pattern>                     &lt;type>0&lt;/type>                     &lt;rows>1&lt;/rows>                     &lt;columns>18&lt;/columns>                     &lt;cell row=\"0\" col=\"0\">1.39000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"1\">1.28000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"2\">1.02000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"3\">5.80000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"4\">1.10000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"5\">-4.50000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"6\">-9.70000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"7\">-1.28000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"8\">-1.34000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"9\">-1.18000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"10\">-8.90000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"11\">-4.50000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"12\">1.20000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"13\">7.20000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"14\">1.33000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"15\">1.33000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"16\">1.33000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"17\">1.33000000000000e-02&lt;/cell>                 &lt;/pattern>             &lt;/cell>             ...         &lt;/pattern>     &lt;/antenna> &lt;/groops>', 'config_table': '', 'display_text': 'Contains a list of GNSS antennas which are identified by its name (type), serial, and radome. Each antenna consists of antenna center offsets (ACO) and antenna center variations (ACV) for different signal <a class=\"groops-class\" href=\"gnssType.html\">types</a> (code and phase). The ACV values for each type are stored in an elevation and azimuth dependent grid.</p><p>  </p><p>See also <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>, <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.</p><p></p><p><pre> &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"antennaDefinition\" version=\"20190429\">     &lt;antennaCount>65&lt;/antennaCount>     ...     &lt;antenna>         &lt;name>BLOCK IIIA&lt;/name>         &lt;serial>G074&lt;/serial>         &lt;radome>2018-109A&lt;/radome>         &lt;comment>PCO provided by the Aerospace Corporation, PV from estimations by ESA/CODE&lt;/comment>         &lt;pattern>             &lt;count>3&lt;/count>             &lt;cell>                 &lt;type>*1*G**&lt;/type>                 &lt;offset>                     &lt;x>-1.23333333333333e-03&lt;/x>                     &lt;y>4.33333333333333e-04&lt;/y>                     &lt;z>3.15200000000000e-01&lt;/z>                 &lt;/offset>                 &lt;dZenit>1.00000000000000e+00&lt;/dZenit>                 &lt;pattern>                     &lt;type>0&lt;/type>                     &lt;rows>1&lt;/rows>                     &lt;columns>18&lt;/columns>                     &lt;cell row=\"0\" col=\"0\">1.39000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"1\">1.28000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"2\">1.02000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"3\">5.80000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"4\">1.10000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"5\">-4.50000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"6\">-9.70000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"7\">-1.28000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"8\">-1.34000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"9\">-1.18000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"10\">-8.90000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"11\">-4.50000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"12\">1.20000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"13\">7.20000000000000e-03&lt;/cell>                     &lt;cell row=\"0\" col=\"14\">1.33000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"15\">1.33000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"16\">1.33000000000000e-02&lt;/cell>                     &lt;cell row=\"0\" col=\"17\">1.33000000000000e-02&lt;/cell>                 &lt;/pattern>             &lt;/cell>             ...         &lt;/pattern>     &lt;/antenna> &lt;/groops> </pre>'},\n'fileFormat_gnssReceiverDefinition': { 'name': 'GnssReceiverDefinition', 'key': 'fileFormat_gnssReceiverDefinition', 'description': 'Contains a list of GNSS receivers which are identified by its name, serial, and version. Defines for each receiver a list of signal   Contains a list of GNSS receivers which are identified by its name, serial, and version. Defines for each receiver a list of signal   which can be observed. Can also be used for GNSS transmitters to define a list of transmitted signal types. For GLONASS satellites the frequency number can be stored in the  version  field. See  GnssReceiverDefinitionCreate .  &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"receiverDefinition\" version=\"20190429\">     &lt;receiverCount>112&lt;/receiverCount>     &lt;receiver>         &lt;name>GLONASS&lt;/name>         &lt;serial>R779&lt;/serial>         &lt;version>2&lt;/version>         &lt;comment/>         &lt;types>             &lt;count>4&lt;/count>             &lt;cell>*1CR**J&lt;/cell>             &lt;cell>*1PR**J&lt;/cell>             &lt;cell>*2CR**J&lt;/cell>             &lt;cell>*2PR**J&lt;/cell>         &lt;/types>     &lt;/receiver>     ...     &lt;receiver>         &lt;name>GLONASS-K1&lt;/name>         &lt;serial>R802&lt;/serial>         &lt;version>7&lt;/version>         &lt;comment/>         &lt;types>             &lt;count>10&lt;/count>             &lt;cell>*1CR**O&lt;/cell>             &lt;cell>*1PR**O&lt;/cell>             &lt;cell>*2CR**O&lt;/cell>             &lt;cell>*2PR**O&lt;/cell>             &lt;cell>*3IR**&lt;/cell>             &lt;cell>*3QR**&lt;/cell>             &lt;cell>*4AR**&lt;/cell>             &lt;cell>*4BR**&lt;/cell>             &lt;cell>*6AR**&lt;/cell>             &lt;cell>*6BR**&lt;/cell>         &lt;/types>     &lt;/receiver> &lt;/groops>', 'config_table': '', 'display_text': 'Contains a list of GNSS receivers which are identified by its name, serial, and version. Defines for each receiver a list of signal <a class=\"groops-class\" href=\"gnssType.html\">types</a> which can be observed. Can also be used for GNSS transmitters to define a list of transmitted signal types. For GLONASS satellites the frequency number can be stored in the <em>version</em> field.</p><p>See <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a>.</p><p><pre> &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"receiverDefinition\" version=\"20190429\">     &lt;receiverCount>112&lt;/receiverCount>     &lt;receiver>         &lt;name>GLONASS&lt;/name>         &lt;serial>R779&lt;/serial>         &lt;version>2&lt;/version>         &lt;comment/>         &lt;types>             &lt;count>4&lt;/count>             &lt;cell>*1CR**J&lt;/cell>             &lt;cell>*1PR**J&lt;/cell>             &lt;cell>*2CR**J&lt;/cell>             &lt;cell>*2PR**J&lt;/cell>         &lt;/types>     &lt;/receiver>     ...     &lt;receiver>         &lt;name>GLONASS-K1&lt;/name>         &lt;serial>R802&lt;/serial>         &lt;version>7&lt;/version>         &lt;comment/>         &lt;types>             &lt;count>10&lt;/count>             &lt;cell>*1CR**O&lt;/cell>             &lt;cell>*1PR**O&lt;/cell>             &lt;cell>*2CR**O&lt;/cell>             &lt;cell>*2PR**O&lt;/cell>             &lt;cell>*3IR**&lt;/cell>             &lt;cell>*3QR**&lt;/cell>             &lt;cell>*4AR**&lt;/cell>             &lt;cell>*4BR**&lt;/cell>             &lt;cell>*6AR**&lt;/cell>             &lt;cell>*6BR**&lt;/cell>         &lt;/types>     &lt;/receiver> &lt;/groops> </pre>'},\n'fileFormat_gnssSignalBias': { 'name': 'GnssSignalBias', 'key': 'fileFormat_gnssSignalBias', 'description': 'Signal biases of GNSS transmitters or receivers for different   Signal biases of GNSS transmitters or receivers for different  .  groops gnssSignalBias version=20200123           5 # number of signals # type   bias [m] # ===============================  C1CG06 -1.752461109688110974e-01  C1WG06  4.005884595055994590e-02  C2WG06  6.597469378913034532e-02  L1*G06 -2.736169875580296909e-02  L2*G06  3.422596762686257871e-02   See also  GnssProcessing ,  GnssSimulateReceiver ,  GnssSignalBias2Matrix ,  GnssSignalBias2SinexBias .', 'config_table': '', 'display_text': 'Signal biases of GNSS transmitters or receivers for different <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>.</p><p><pre> groops gnssSignalBias version=20200123           5 # number of signals # type   bias [m] # ===============================  C1CG06 -1.752461109688110974e-01  C1WG06  4.005884595055994590e-02  C2WG06  6.597469378913034532e-02  L1*G06 -2.736169875580296909e-02  L2*G06  3.422596762686257871e-02  </pre></p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>, <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>, <a class=\"groops-program\" href=\"GnssSignalBias2Matrix.html\">GnssSignalBias2Matrix</a>, <a class=\"groops-program\" href=\"GnssSignalBias2SinexBias.html\">GnssSignalBias2SinexBias</a>.'},\n'fileFormat_griddedData': { 'name': 'GriddedData', 'key': 'fileFormat_griddedData', 'description': 'List of arbitrarily distributed points defined by geographic coordinates and ellipsoidal height. Each point can also have an associated area (projected on the unit sphere with a total area of  ). This file format supports multiple values per point (called  data0 ,  data1  and so on). For regular gridded data and binary format ( *.dat ) a more efficient storage scheme is used. See also:  GriddedDataCreate .  groops griddedData version=20200123  1  2  6.378137000000000000e+06  6.356752314140356146e+06 72 # hasArea, data columns, ellipoid a, ellipoid b, data rows # longitude [deg]           latitude [deg]            height [m]                unit areas [-]             data0                     data1 # ===========================================================================================================================================================  -1.650000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.350000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.050000000000000142e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -7.500000000000001421e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -4.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.499999999999997691e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   4.499999999999997868e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   7.499999999999997158e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.049999999999999574e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.349999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.649999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.650000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00  -1.350000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00', 'config_table': '', 'display_text': 'List of arbitrarily distributed points defined by geographic coordinates and ellipsoidal height. Each point can also have an associated area (projected on the unit sphere with a total area of $4\\\\pi$). This file format supports multiple values per point (called <code>data0</code>, <code>data1</code> and so on).</p><p>For regular gridded data and binary format (<code>*.dat</code>) a more efficient storage scheme is used.</p><p>See also: <a class=\"groops-program\" href=\"GriddedDataCreate.html\">GriddedDataCreate</a>.</p><p><pre> groops griddedData version=20200123  1  2  6.378137000000000000e+06  6.356752314140356146e+06 72 # hasArea, data columns, ellipoid a, ellipoid b, data rows # longitude [deg]           latitude [deg]            height [m]                unit areas [-]             data0                     data1 # ===========================================================================================================================================================  -1.650000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.350000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.050000000000000142e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -7.500000000000001421e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -4.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.499999999999997691e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   4.499999999999997868e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   7.499999999999997158e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.049999999999999574e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.349999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00   1.649999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00  -1.650000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00  -1.350000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00 </pre></p><p>'},\n'fileFormat_griddedDataTimeSeries': { 'name': 'GriddedDataTimeSeries', 'key': 'fileFormat_griddedDataTimeSeries', 'description': 'Time series of data for arbitrarily distributed points defined by geographic coordinates and ellipsoidal height. The data can be temporal interpolated by  basis splines . The file format consists of a  griddedData , a time series, and for each spatial point and spline node pair multiple values called  data0 ,  data1 ,  . A GriddedDataTimeSeries can be generated from individual  griddedData  with the program  GriddedData2GriddedDataTimeSeries . Vice-versa, a GriddedDataTimeSeries can be evaluated at a specific time stamp to obtain a  griddedData  with  GriddedDataTimeSeries2GriddedData .', 'config_table': '', 'display_text': 'Time series of data for arbitrarily distributed points defined by geographic coordinates and ellipsoidal height. The data can be temporal interpolated by <a class=\"groops-ref\" href=\"fundamentals.basisSplines.html\">basis splines</a>. The file format consists of a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData</a>, a time series, and for each spatial point and spline node pair multiple values called <code>data0</code>, <code>data1</code>, .</p><p>A GriddedDataTimeSeries can be generated from individual <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData</a> with the program <a class=\"groops-program\" href=\"GriddedData2GriddedDataTimeSeries.html\">GriddedData2GriddedDataTimeSeries</a>. Vice-versa, a GriddedDataTimeSeries can be evaluated at a specific time stamp to obtain a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData</a> with <a class=\"groops-program\" href=\"GriddedDataTimeSeries2GriddedData.html\">GriddedDataTimeSeries2GriddedData</a>.'},\n'fileFormat_instrument': { 'name': 'Instrument', 'key': 'fileFormat_instrument', 'description': 'This template file format can store different observations in a epoch wise manner. Each epoch consists of a time and additional data, e.g orbits, accelerometer data, star camera quaternions (see   This template file format can store different observations in a epoch wise manner. Each epoch consists of a time and additional data, e.g orbits, accelerometer data, star camera quaternions (see  ). The time series can be divided in several arcs (see  InstrumentSynchronize ). Also a  matrix  file is allowed as one single arc. The first column must contain times [MJD]. Without any extra column the instrument type is INSTRUMENTTIME, with one additional column the type is MISCVALUE, and for more columns the type MISCVALUES is used.  groops instrument version=20200123 # SATELLITETRACKING          -9         60  # instrument type, number of arcs # Time [MJD]               data0: range [m]          data1: range-rate [m/s]   data2: range-acc [m/s^2] # =====================================================================================================          12 # number of epochs of 1. arc  54588.000000000000000000 -5.074649470097549492e+05  5.755440207134928654e-01  1.877605261528093308e-03  54588.000057870370255841 -5.074620458130163024e+05  5.849357691551860805e-01  1.878948916234051596e-03  54588.000115740740966430 -5.074590976427756250e+05  5.943331739937073310e-01  1.879937220634776869e-03  54588.000173611111222272 -5.074561024756557308e+05  6.037340169611068452e-01  1.880370529387525701e-03  54588.000231481481478113 -5.074530602992626373e+05  6.131368121270999172e-01  1.880680632122925426e-03  54588.000289351851733954 -5.074499711071007187e+05  6.225398878861636565e-01  1.880495369480403561e-03  54588.000347222222444543 -5.074468349029610981e+05  6.319414138081351773e-01  1.880073731783055927e-03  54588.000405092592700385 -5.074436516971451929e+05  6.413404243585696385e-01  1.879464843086203459e-03  54588.000462962962956226 -5.074404215058300761e+05  6.507353310092597320e-01  1.878578987216372124e-03  54588.000520833333212067 -5.074371443491023383e+05  6.601267978060636477e-01  1.877878184949659246e-03  54588.000578703703922656 -5.074338202460713219e+05  6.695136489207137442e-01  1.876962042758626532e-03  54588.000636574074178498 -5.074304492190054734e+05  6.788964444122400632e-01  1.876091925462087043e-03          12 # number of epochs of 2. arc  54588.000694444444434339 -5.074270312892858055e+05  6.882748400534359767e-01  1.875376456928801432e-03  54588.000752314814690180 -5.074235664742725785e+05  6.976508178537534910e-01  1.874929898412159559e-03  54588.000810185185400769 -5.074200547868391732e+05  7.070236200716006891e-01  1.874312324351668077e-03  54588.000868055555656611 -5.074164962409950094e+05  7.163943828291452487e-01  1.873924188388115340e-03  54588.000925925925912452 -5.074128908454515622e+05  7.257639682023964145e-01  1.874025826380292404e-03  54588.000983796296168293 -5.074092386012640782e+05  7.351333608427884636e-01  1.873680487441316657e-03  54588.001041666666878882 -5.074055395130896359e+05  7.445020815182646912e-01  1.873849502509668122e-03  54588.001099537037134724 -5.074017935789784533e+05  7.538716732272922050e-01  1.873971633320137753e-03  54588.001157407407390565 -5.073980007962241652e+05  7.632414098560330595e-01  1.873984767500571974e-03  54588.001215277777646406 -5.073941611626467784e+05  7.726123093411200182e-01  1.874295246964456478e-03  54588.001273148148356995 -5.073902746728868224e+05  7.819835205798950639e-01  1.874226146744964808e-03  54588.001331018518612836 -5.073863413272026228e+05  7.913547196412918927e-01  1.874173804634685515e-03', 'config_table': '', 'display_text': 'This template file format can store different observations in a epoch wise manner. Each epoch consists of a time and additional data, e.g orbits, accelerometer data, star camera quaternions (see <a class=\"groops-class\" href=\"instrumentTypeType.html\">InstrumentType</a>). The time series can be divided in several arcs (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>Also a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file is allowed as one single arc. The first column must contain times [MJD]. Without any extra column the instrument type is INSTRUMENTTIME, with one additional column the type is MISCVALUE, and for more columns the type MISCVALUES is used.</p><p><pre> groops instrument version=20200123 # SATELLITETRACKING          -9         60  # instrument type, number of arcs # Time [MJD]               data0: range [m]          data1: range-rate [m/s]   data2: range-acc [m/s^2] # =====================================================================================================          12 # number of epochs of 1. arc  54588.000000000000000000 -5.074649470097549492e+05  5.755440207134928654e-01  1.877605261528093308e-03  54588.000057870370255841 -5.074620458130163024e+05  5.849357691551860805e-01  1.878948916234051596e-03  54588.000115740740966430 -5.074590976427756250e+05  5.943331739937073310e-01  1.879937220634776869e-03  54588.000173611111222272 -5.074561024756557308e+05  6.037340169611068452e-01  1.880370529387525701e-03  54588.000231481481478113 -5.074530602992626373e+05  6.131368121270999172e-01  1.880680632122925426e-03  54588.000289351851733954 -5.074499711071007187e+05  6.225398878861636565e-01  1.880495369480403561e-03  54588.000347222222444543 -5.074468349029610981e+05  6.319414138081351773e-01  1.880073731783055927e-03  54588.000405092592700385 -5.074436516971451929e+05  6.413404243585696385e-01  1.879464843086203459e-03  54588.000462962962956226 -5.074404215058300761e+05  6.507353310092597320e-01  1.878578987216372124e-03  54588.000520833333212067 -5.074371443491023383e+05  6.601267978060636477e-01  1.877878184949659246e-03  54588.000578703703922656 -5.074338202460713219e+05  6.695136489207137442e-01  1.876962042758626532e-03  54588.000636574074178498 -5.074304492190054734e+05  6.788964444122400632e-01  1.876091925462087043e-03          12 # number of epochs of 2. arc  54588.000694444444434339 -5.074270312892858055e+05  6.882748400534359767e-01  1.875376456928801432e-03  54588.000752314814690180 -5.074235664742725785e+05  6.976508178537534910e-01  1.874929898412159559e-03  54588.000810185185400769 -5.074200547868391732e+05  7.070236200716006891e-01  1.874312324351668077e-03  54588.000868055555656611 -5.074164962409950094e+05  7.163943828291452487e-01  1.873924188388115340e-03  54588.000925925925912452 -5.074128908454515622e+05  7.257639682023964145e-01  1.874025826380292404e-03  54588.000983796296168293 -5.074092386012640782e+05  7.351333608427884636e-01  1.873680487441316657e-03  54588.001041666666878882 -5.074055395130896359e+05  7.445020815182646912e-01  1.873849502509668122e-03  54588.001099537037134724 -5.074017935789784533e+05  7.538716732272922050e-01  1.873971633320137753e-03  54588.001157407407390565 -5.073980007962241652e+05  7.632414098560330595e-01  1.873984767500571974e-03  54588.001215277777646406 -5.073941611626467784e+05  7.726123093411200182e-01  1.874295246964456478e-03  54588.001273148148356995 -5.073902746728868224e+05  7.819835205798950639e-01  1.874226146744964808e-03  54588.001331018518612836 -5.073863413272026228e+05  7.913547196412918927e-01  1.874173804634685515e-03 </pre>'},\n'fileFormat_matrix': { 'name': 'Matrix', 'key': 'fileFormat_matrix', 'description': 'Stores matrices and vectors. Only one triangle is written for symmetric or triangular matrices. The header (the matrix definition) is optional. Therefore a pure text with only numbers in columns are also allowed. This simplifies the handling of external data. Instead of a matrix file also an  instrument  file is allowed. The first column is the time [MJD], the other columns depends on the instrument type.  groops matrix version=20200123 LowerSymmetricMatrix( 4 x 4 )   1.000000000000000000e+00   0.000000000000000000e+00  1.000000000000000000e+00   0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00   0.000000000000000000e+00  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00', 'config_table': '', 'display_text': 'Stores matrices and vectors. Only one triangle is written for symmetric or triangular matrices.</p><p>The header (the matrix definition) is optional. Therefore a pure text with only numbers in columns are also allowed. This simplifies the handling of external data.</p><p>Instead of a matrix file also an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument</a> file is allowed. The first column is the time [MJD], the other columns depends on the instrument type.</p><p><pre> groops matrix version=20200123 LowerSymmetricMatrix( 4 x 4 )   1.000000000000000000e+00   0.000000000000000000e+00  1.000000000000000000e+00   0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00   0.000000000000000000e+00  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00 </pre></p><p>'},\n'fileFormat_meanPolarMotion': { 'name': 'MeanPolarMotion', 'key': 'fileFormat_meanPolarMotion', 'description': 'The mean pole of the Earth rotation is represented by a polynomial in a time interval.  &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"meanPolarMotion\" version=\"20200123\">   &lt;meanPolarMotion>     &lt;intervalCount>2&lt;/intervalCount>     &lt;interval>       &lt;timeStart>42778.0000000000000000&lt;/timeStart>       &lt;degree>3&lt;/degree>       &lt;xp>5.59741000000000e-02&lt;/xp>       &lt;xp>1.82430000000000e-03&lt;/xp>       &lt;xp>1.84130000000000e-04&lt;/xp>       &lt;xp>7.02400000000000e-06&lt;/xp>       &lt;yp>3.46346000000000e-01&lt;/yp>       &lt;yp>1.78960000000000e-03&lt;/yp>       &lt;yp>-1.07290000000000e-04&lt;/yp>       &lt;yp>-9.08000000000000e-07&lt;/yp>     &lt;/interval>     &lt;interval>       &lt;timeStart>55197.0000000000000000&lt;/timeStart>       &lt;degree>1&lt;/degree>       &lt;xp>2.35130000000000e-02&lt;/xp>       &lt;xp>7.61410000000000e-03&lt;/xp>       &lt;yp>3.58891000000000e-01&lt;/yp>       &lt;yp>-6.28700000000000e-04&lt;/yp>     &lt;/interval>   &lt;/meanPolarMotion> &lt;/groops>', 'config_table': '', 'display_text': 'The mean pole of the Earth rotation is represented by a polynomial in a time interval.</p><p><pre> &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"meanPolarMotion\" version=\"20200123\">   &lt;meanPolarMotion>     &lt;intervalCount>2&lt;/intervalCount>     &lt;interval>       &lt;timeStart>42778.0000000000000000&lt;/timeStart>       &lt;degree>3&lt;/degree>       &lt;xp>5.59741000000000e-02&lt;/xp>       &lt;xp>1.82430000000000e-03&lt;/xp>       &lt;xp>1.84130000000000e-04&lt;/xp>       &lt;xp>7.02400000000000e-06&lt;/xp>       &lt;yp>3.46346000000000e-01&lt;/yp>       &lt;yp>1.78960000000000e-03&lt;/yp>       &lt;yp>-1.07290000000000e-04&lt;/yp>       &lt;yp>-9.08000000000000e-07&lt;/yp>     &lt;/interval>     &lt;interval>       &lt;timeStart>55197.0000000000000000&lt;/timeStart>       &lt;degree>1&lt;/degree>       &lt;xp>2.35130000000000e-02&lt;/xp>       &lt;xp>7.61410000000000e-03&lt;/xp>       &lt;yp>3.58891000000000e-01&lt;/yp>       &lt;yp>-6.28700000000000e-04&lt;/yp>     &lt;/interval>   &lt;/meanPolarMotion> &lt;/groops> </pre>'},\n'fileFormat_normalEquation': { 'name': 'NormalEquation', 'key': 'fileFormat_normalEquation', 'description': 'Stores a  system of normal equations    This file format consists of multiple files. The file name  normals.dat.gz  corresponds to the following files:    normals.dat.gz  or  normals.00.00.dat.gz  ...  normals.0n.0n.dat.gz :       the normal matrix   as  matrix ,  normals.rightHandSide.dat.gz :       the right hand side(s)   as  matrix ,  normals.parameterNames.txt :  parameter names ,  normals.info.xml :      u.a. containing the number of observations and the quadratic sum of (reduced) observations  .   A large normal matrix may be splitted into blocks and stored in multiple files. The block row/column number is indicated in the file name. Only the upper blocks of the sysmmetric matrix are considered. Matrix in blocks can be distributed on muliple nodes in parallel mode to efficiently use distributed memory.', 'config_table': '', 'display_text': 'Stores a <a class=\"groops-ref\" href=\"normalEquationType.html\">system of normal equations</a> \\\\[   \\\\M N \\\\hat{\\\\M x} = \\\\M n. \\\\] This file format consists of multiple files. The file name <code>normals.dat.gz</code> corresponds to the following files: <ul>  <li><code>normals.dat.gz</code> or <code>normals.00.00.dat.gz</code> ... <code>normals.0n.0n.dat.gz</code>:       the normal matrix $\\\\M N$ as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>, </li><li> <code>normals.rightHandSide.dat.gz</code>:       the right hand side(s) $\\\\M n$ as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>, </li><li> <code>normals.parameterNames.txt</code>: <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a>, </li><li> <code>normals.info.xml</code>:      u.a. containing the number of observations and the quadratic sum of (reduced) observations $\\\\M l^T\\\\M P\\\\M l$. </li></ul>  A large normal matrix may be splitted into blocks and stored in multiple files. The block row/column number is indicated in the file name. Only the upper blocks of the sysmmetric matrix are considered. Matrix in blocks can be distributed on muliple nodes in parallel mode to efficiently use distributed memory.'},\n'fileFormat_oceanPoleTide': { 'name': 'OceanPoleTide', 'key': 'fileFormat_oceanPoleTide', 'description': 'Describes the reaction of the ocean mass to the change of the centrifugal potential (polar wobble) in terms spherical harmonics. See also  Iers2OceanPoleTide .', 'config_table': '', 'display_text': 'Describes the reaction of the ocean mass to the change of the centrifugal potential (polar wobble) in terms spherical harmonics.</p><p>See also <a class=\"groops-program\" href=\"Iers2OceanPoleTide.html\">Iers2OceanPoleTide</a>.'},\n'fileFormat_parameterName': { 'name': 'ParameterName', 'key': 'fileFormat_parameterName', 'description': 'Name of parameters of a system of  normal equations  or  solution vector . A parameter name is a string  &lt;object>:&lt;type>:&lt;temporal>:&lt;interval>  containg four parts divided by  :     object: Object this parameter refers to, e.g.  graceA ,  G023 ,  earth ,  type: Type of this parameter, e.g.  accBias ,  position.x ,  temporal: Temporal representation of this parameter, e.g.  trend ,  polynomial.degree1 ,  interval: Interval/epoch this parameter represents, e.g.  2017-01-01_00-00-00_2017-01-02_00-00-00 ,  2018-01-01_00-00-00 .   In the documentation a star ( * ) in the name means this part is untouched and useally set by other classes. Times are written as  yyyy-mm-dd_hh-mm-ss  and intervals (if not empty) as  &lt;timeStart>_&lt;timeEnd> . See  ParameterNamesCreate .  groops parameterName version=20200123 # object:type:temporal:interval # =============================       10080 # number of parameters  karr:position.x::2018-06-01_00-00-00_2018-06-02_00-00-00  karr:position.y::2018-06-01_00-00-00_2018-06-02_00-00-00  karr:position.z::2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_02-00-00  karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_04-00-00  karr:troposphereWet:spline.n1:2018-06-01_02-00-00_2018-06-01_06-00-00  karr:troposphereWet:spline.n1:2018-06-01_04-00-00_2018-06-01_08-00-00  karr:troposphereWet:spline.n1:2018-06-01_06-00-00_2018-06-01_10-00-00  karr:troposphereWet:spline.n1:2018-06-01_08-00-00_2018-06-01_12-00-00  karr:troposphereWet:spline.n1:2018-06-01_10-00-00_2018-06-01_14-00-00  karr:troposphereWet:spline.n1:2018-06-01_12-00-00_2018-06-01_16-00-00  karr:troposphereWet:spline.n1:2018-06-01_14-00-00_2018-06-01_18-00-00  karr:troposphereWet:spline.n1:2018-06-01_16-00-00_2018-06-01_20-00-00  karr:troposphereWet:spline.n1:2018-06-01_18-00-00_2018-06-01_22-00-00  karr:troposphereWet:spline.n1:2018-06-01_20-00-00_2018-06-02_00-00-00  karr:troposphereWet:spline.n1:2018-06-01_22-00-00_2018-06-02_00-00-00  karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:signalBias01(+1.00L1CG**)::  karr:signalBias02(+1.00L2WG**)::  karr:signalBias03(+1.00L2XG**)::  G01:solarRadiationPressure.ECOM.D0::  G01:solarRadiationPressure.ECOM.DC2::  G01:solarRadiationPressure.ECOM.DS2::  G01:solarRadiationPressure.ECOM.Y0::  G01:solarRadiationPressure.ECOM.B0::  G01:solarRadiationPressure.ECOM.BC1::  G01:solarRadiationPressure.ECOM.BS1::  G01:stochasticPulse.x::2018-06-01_12-00-00  G01:stochasticPulse.y::2018-06-01_12-00-00  G01:stochasticPulse.z::2018-06-01_12-00-00  G01:arc0.position0.x::  G01:arc0.position0.y::  G01:arc0.position0.z::  G01:arc0.velocity0.x::  G01:arc0.velocity0.y::  G01:arc0.velocity0.z::  G01:signalBias01(-1.00C1CG01)::  G01:signalBias02(+1.00L1*G01)::  G01:signalBias03(+1.00L2*G01)::', 'config_table': '', 'display_text': 'Name of parameters of a system of <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> or <a class=\"groops-file\" href=\"fileFormat_matrix.html\">solution vector</a>.</p><p>A parameter name is a string <code>&lt;object>:&lt;type>:&lt;temporal>:&lt;interval></code> containg four parts divided by <code>:</code> <ol>  <li>object: Object this parameter refers to, e.g. <code>graceA</code>, <code>G023</code>, <code>earth</code>, </li><li> type: Type of this parameter, e.g. <code>accBias</code>, <code>position.x</code>, </li><li> temporal: Temporal representation of this parameter, e.g. <code>trend</code>, <code>polynomial.degree1</code>, </li><li> interval: Interval/epoch this parameter represents, e.g. <code>2017-01-01_00-00-00_2017-01-02_00-00-00</code>, <code>2018-01-01_00-00-00</code>. </li></ol>  In the documentation a star (<code>*</code>) in the name means this part is untouched and useally set by other classes. Times are written as <code>yyyy-mm-dd_hh-mm-ss</code> and intervals (if not empty) as <code>&lt;timeStart>_&lt;timeEnd></code>.</p><p>See <a class=\"groops-program\" href=\"ParameterNamesCreate.html\">ParameterNamesCreate</a>.</p><p><pre> groops parameterName version=20200123 # object:type:temporal:interval # =============================       10080 # number of parameters  karr:position.x::2018-06-01_00-00-00_2018-06-02_00-00-00  karr:position.y::2018-06-01_00-00-00_2018-06-02_00-00-00  karr:position.z::2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_02-00-00  karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_04-00-00  karr:troposphereWet:spline.n1:2018-06-01_02-00-00_2018-06-01_06-00-00  karr:troposphereWet:spline.n1:2018-06-01_04-00-00_2018-06-01_08-00-00  karr:troposphereWet:spline.n1:2018-06-01_06-00-00_2018-06-01_10-00-00  karr:troposphereWet:spline.n1:2018-06-01_08-00-00_2018-06-01_12-00-00  karr:troposphereWet:spline.n1:2018-06-01_10-00-00_2018-06-01_14-00-00  karr:troposphereWet:spline.n1:2018-06-01_12-00-00_2018-06-01_16-00-00  karr:troposphereWet:spline.n1:2018-06-01_14-00-00_2018-06-01_18-00-00  karr:troposphereWet:spline.n1:2018-06-01_16-00-00_2018-06-01_20-00-00  karr:troposphereWet:spline.n1:2018-06-01_18-00-00_2018-06-01_22-00-00  karr:troposphereWet:spline.n1:2018-06-01_20-00-00_2018-06-02_00-00-00  karr:troposphereWet:spline.n1:2018-06-01_22-00-00_2018-06-02_00-00-00  karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00  karr:signalBias01(+1.00L1CG**)::  karr:signalBias02(+1.00L2WG**)::  karr:signalBias03(+1.00L2XG**)::  G01:solarRadiationPressure.ECOM.D0::  G01:solarRadiationPressure.ECOM.DC2::  G01:solarRadiationPressure.ECOM.DS2::  G01:solarRadiationPressure.ECOM.Y0::  G01:solarRadiationPressure.ECOM.B0::  G01:solarRadiationPressure.ECOM.BC1::  G01:solarRadiationPressure.ECOM.BS1::  G01:stochasticPulse.x::2018-06-01_12-00-00  G01:stochasticPulse.y::2018-06-01_12-00-00  G01:stochasticPulse.z::2018-06-01_12-00-00  G01:arc0.position0.x::  G01:arc0.position0.y::  G01:arc0.position0.z::  G01:arc0.velocity0.x::  G01:arc0.velocity0.y::  G01:arc0.velocity0.z::  G01:signalBias01(-1.00C1CG01)::  G01:signalBias02(+1.00L1*G01)::  G01:signalBias03(+1.00L2*G01):: </pre>'},\n'fileFormat_platform': { 'name': 'Platform', 'key': 'fileFormat_platform', 'description': 'Defines a platform with a local coordinate frame equipped with instruments. The platform might be a reference station, a low Earth satellite, or a transmitting GNSS satellite and is referenced by a marker name and number. The reference point (marker or center of mass (CoM)) can change in time relative to the local frame. Each equipped instrument is described at least by the following information    name  serial number  coordinates in the local frame  a time interval in which the instrument was active  the orientation for antennas and reflectors.  For GNSS satellites the platform defines the PRN. The different assigned SVNs are defined by the transmitting antennas. Platforms for GNSS stations can be created from station log files with  GnssStationLog2Platform . Platforms for GNSS satellites can be created from an ANTEX file with  GnssAntex2AntennaDefinition . See also  PlatformCreate .', 'config_table': '', 'display_text': 'Defines a platform with a local coordinate frame equipped with instruments. The platform might be a reference station, a low Earth satellite, or a transmitting GNSS satellite and is referenced by a marker name and number. The reference point (marker or center of mass (CoM)) can change in time relative to the local frame.</p><p>Each equipped instrument is described at least by the following information <ul>  <li>name </li><li> serial number </li><li> coordinates in the local frame </li><li> a time interval in which the instrument was active </li><li> the orientation for antennas and reflectors. </li></ul> </p><p>For GNSS satellites the platform defines the PRN. The different assigned SVNs are defined by the transmitting antennas.</p><p>Platforms for GNSS stations can be created from station log files with <a class=\"groops-program\" href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a>. Platforms for GNSS satellites can be created from an ANTEX file with <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.</p><p>See also <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.</p><p>'},\n'fileFormat_polygon': { 'name': 'Polygon', 'key': 'fileFormat_polygon', 'description': 'List of longitude and latitudes to describe borders, e.g. river basins or continents. It is used in   List of longitude and latitudes to describe borders, e.g. river basins or continents. It is used in  .  groops polygon version=20200123           2  # number of polygons           6  # number of points (1. polygon) # longitude [deg]           latitude [deg] # ==================================================  -1.598200000000000216e+02  2.203000000000000114e+01  -1.596200000000000045e+02  2.189999999999999858e+01  -1.593799999999999955e+02  2.189999999999999858e+01  -1.593000000000000114e+02  2.221999999999999886e+01  -1.595800000000000125e+02  2.221999999999999886e+01  -1.598200000000000216e+02  2.203000000000000114e+01           5  # number of points (2. polygon) # longitude [deg]           latitude [deg] # ==================================================  -7.900000000000000000e+01  2.669999999999999929e+01  -7.870000000000000284e+01  2.650000000000000000e+01  -7.823000000000000398e+01  2.667000000000000171e+01  -7.793000000000000682e+01  2.667000000000000171e+01  -7.779999999999999716e+01  2.646999999999999886e+01', 'config_table': '', 'display_text': 'List of longitude and latitudes to describe borders, e.g. river basins or continents. It is used in <a class=\"groops-class\" href=\"borderType.html#polygon\">border:polygon</a>.</p><p><pre> groops polygon version=20200123           2  # number of polygons           6  # number of points (1. polygon) # longitude [deg]           latitude [deg] # ==================================================  -1.598200000000000216e+02  2.203000000000000114e+01  -1.596200000000000045e+02  2.189999999999999858e+01  -1.593799999999999955e+02  2.189999999999999858e+01  -1.593000000000000114e+02  2.221999999999999886e+01  -1.595800000000000125e+02  2.221999999999999886e+01  -1.598200000000000216e+02  2.203000000000000114e+01           5  # number of points (2. polygon) # longitude [deg]           latitude [deg] # ==================================================  -7.900000000000000000e+01  2.669999999999999929e+01  -7.870000000000000284e+01  2.650000000000000000e+01  -7.823000000000000398e+01  2.667000000000000171e+01  -7.793000000000000682e+01  2.667000000000000171e+01  -7.779999999999999716e+01  2.646999999999999886e+01 </pre></p><p>'},\n'fileFormat_potentialCoefficients': { 'name': 'PotentialCoefficients', 'key': 'fileFormat_potentialCoefficients', 'description': 'The standard  .gfc  format as defined by the ICGEM is used in ASCII the format. Only the static part is used and temporal variations (e.g. trend) are ignored. To write additional information and temporal variations use  PotentialCoefficients2Icgem .', 'config_table': '', 'display_text': 'The standard <code>.gfc</code> format as defined by the ICGEM is used in ASCII the format. Only the static part is used and temporal variations (e.g. trend) are ignored. To write additional information and temporal variations use <a class=\"groops-program\" href=\"PotentialCoefficients2Icgem.html\">PotentialCoefficients2Icgem</a>.'},\n'fileFormat_satelliteModel': { 'name': 'SatelliteModel', 'key': 'fileFormat_satelliteModel', 'description': 'Properties of a satellite to model non-conservative forces (e.g.   Properties of a satellite to model non-conservative forces (e.g.  ). The file may contain surface properties, mass, drag coefficients, and antenna thrust values. See  SatelliteModelCreate  and  SinexMetadata2SatelliteModel .  &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"satelliteModel\" version=\"20190429\">    &lt;satelliteCount>1&lt;/satelliteCount>    &lt;satellite>        &lt;satelliteName>GALILEO-2&lt;/satelliteName>        &lt;mass>7.00000000000000e+02&lt;/mass>        &lt;coefficientDrag>0.00000000000000e+00&lt;/coefficientDrag>        &lt;surfaceCount>15&lt;/surfaceCount>        &lt;surface>            &lt;type>0&lt;/type>            &lt;normal>                &lt;x>-1.00000000000000e+00&lt;/x>                &lt;y>0.00000000000000e+00&lt;/y>                &lt;z>0.00000000000000e+00&lt;/z>            &lt;/normal>            &lt;area>4.40000000000000e-01&lt;/area>            &lt;reflexionVisible>0.00000000000000e+00&lt;/reflexionVisible>            &lt;diffusionVisible>7.00000000000000e-02&lt;/diffusionVisible>            &lt;absorptionVisible>9.30000000000000e-01&lt;/absorptionVisible>            &lt;reflexionInfrared>1.00000000000000e-01&lt;/reflexionInfrared>            &lt;diffusionInfrared>1.00000000000000e-01&lt;/diffusionInfrared>            &lt;absorptionInfrared>8.00000000000000e-01&lt;/absorptionInfrared>            &lt;hasThermalReemission>1&lt;/hasThermalReemission>        &lt;/surface>        ...        &lt;modulCount>2&lt;/modulCount>        &lt;modul>            &lt;type>1&lt;/type>            &lt;rotationAxis>                &lt;x>0.00000000000000e+00&lt;/x>                &lt;y>1.00000000000000e+00&lt;/y>                &lt;z>0.00000000000000e+00&lt;/z>            &lt;/rotationAxis>            &lt;normal>                &lt;x>0.00000000000000e+00&lt;/x>                &lt;y>0.00000000000000e+00&lt;/y>                &lt;z>1.00000000000000e+00&lt;/z>            &lt;/normal>            &lt;surface>                &lt;count>4&lt;/count>                &lt;cell>11&lt;/cell>                &lt;cell>12&lt;/cell>                &lt;cell>13&lt;/cell>                &lt;cell>14&lt;/cell>            &lt;/surface>        &lt;/modul>        &lt;modul>            &lt;type>2&lt;/type>            &lt;antennaThrust>                &lt;x>0.00000000000000e+00&lt;/x>                &lt;y>0.00000000000000e+00&lt;/y>                &lt;z>2.65000000000000e+02&lt;/z>            &lt;/antennaThrust>        &lt;/modul>    &lt;/satellite> &lt;/groops>', 'config_table': '', 'display_text': 'Properties of a satellite to model non-conservative forces (e.g. <a class=\"groops-class\" href=\"miscAccelerationsType.html\">miscAccelerations</a>). The file may contain surface properties, mass, drag coefficients, and antenna thrust values.</p><p>See <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a> and <a class=\"groops-program\" href=\"SinexMetadata2SatelliteModel.html\">SinexMetadata2SatelliteModel</a>.</p><p><pre> &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?> &lt;groops type=\"satelliteModel\" version=\"20190429\">    &lt;satelliteCount>1&lt;/satelliteCount>    &lt;satellite>        &lt;satelliteName>GALILEO-2&lt;/satelliteName>        &lt;mass>7.00000000000000e+02&lt;/mass>        &lt;coefficientDrag>0.00000000000000e+00&lt;/coefficientDrag>        &lt;surfaceCount>15&lt;/surfaceCount>        &lt;surface>            &lt;type>0&lt;/type>            &lt;normal>                &lt;x>-1.00000000000000e+00&lt;/x>                &lt;y>0.00000000000000e+00&lt;/y>                &lt;z>0.00000000000000e+00&lt;/z>            &lt;/normal>            &lt;area>4.40000000000000e-01&lt;/area>            &lt;reflexionVisible>0.00000000000000e+00&lt;/reflexionVisible>            &lt;diffusionVisible>7.00000000000000e-02&lt;/diffusionVisible>            &lt;absorptionVisible>9.30000000000000e-01&lt;/absorptionVisible>            &lt;reflexionInfrared>1.00000000000000e-01&lt;/reflexionInfrared>            &lt;diffusionInfrared>1.00000000000000e-01&lt;/diffusionInfrared>            &lt;absorptionInfrared>8.00000000000000e-01&lt;/absorptionInfrared>            &lt;hasThermalReemission>1&lt;/hasThermalReemission>        &lt;/surface>        ...        &lt;modulCount>2&lt;/modulCount>        &lt;modul>            &lt;type>1&lt;/type>            &lt;rotationAxis>                &lt;x>0.00000000000000e+00&lt;/x>                &lt;y>1.00000000000000e+00&lt;/y>                &lt;z>0.00000000000000e+00&lt;/z>            &lt;/rotationAxis>            &lt;normal>                &lt;x>0.00000000000000e+00&lt;/x>                &lt;y>0.00000000000000e+00&lt;/y>                &lt;z>1.00000000000000e+00&lt;/z>            &lt;/normal>            &lt;surface>                &lt;count>4&lt;/count>                &lt;cell>11&lt;/cell>                &lt;cell>12&lt;/cell>                &lt;cell>13&lt;/cell>                &lt;cell>14&lt;/cell>            &lt;/surface>        &lt;/modul>        &lt;modul>            &lt;type>2&lt;/type>            &lt;antennaThrust>                &lt;x>0.00000000000000e+00&lt;/x>                &lt;y>0.00000000000000e+00&lt;/y>                &lt;z>2.65000000000000e+02&lt;/z>            &lt;/antennaThrust>        &lt;/modul>    &lt;/satellite> &lt;/groops> </pre>'},\n'fileFormat_stringList': { 'name': 'StringList', 'key': 'fileFormat_stringList', 'description': 'White space separated list of strings. Comments are allowed and all the text from the character \\' # \\' to the end of the line is ignored. Strings containing white spaces or the \\' # \\' character must be set in quotes (\\' \"\" \\').  # IGSR3 stations abmf abpo ade1 adis ajac albh algo alic alrt amc2 aoml areq arev artu asc1', 'config_table': '', 'display_text': 'White space separated list of strings. Comments are allowed and all the text from the character \\'<code>#</code>\\' to the end of the line is ignored. Strings containing white spaces or the \\'<code>#</code>\\' character must be set in quotes (\\'<code>\"\"</code>\\').</p><p><pre> # IGSR3 stations abmf abpo ade1 adis ajac albh algo alic alrt amc2 aoml areq arev artu asc1 </pre>'},\n'fileFormat_stringTable': { 'name': 'StringTable', 'key': 'fileFormat_stringTable', 'description': 'White space separated table of strings in row and columns. Additional columns in a row may represent alternatives, e.g. for core stations in a GNSS network. Comments are allowed and all the text from the character \\' # \\' to the end of the line is ignored. Strings containing white spaces or the \\' # \\' character must be set in quotes  (\\' \"\" \\').  # core network with alternative stations artu mdvj mdvo nril asc1 sthl bahr bhr1 yibl nama chat chti auck chpi braz ufpr savo ckis nium coco xmis dgar dgav cro1 scub abmf lmmf aoml daej taej suwn osn1 darw kat1 tow2 alic dav1 maw1 drao albh will holb nano fair whit glps guat gode godz usno usn3 goug', 'config_table': '', 'display_text': 'White space separated table of strings in row and columns. Additional columns in a row may represent alternatives, e.g. for core stations in a GNSS network. Comments are allowed and all the text from the character \\'<code>#</code>\\' to the end of the line is ignored. Strings containing white spaces or the \\'<code>#</code>\\' character must be set in quotes  (\\'<code>\"\"</code>\\').</p><p><pre> # core network with alternative stations artu mdvj mdvo nril asc1 sthl bahr bhr1 yibl nama chat chti auck chpi braz ufpr savo ckis nium coco xmis dgar dgav cro1 scub abmf lmmf aoml daej taej suwn osn1 darw kat1 tow2 alic dav1 maw1 drao albh will holb nano fair whit glps guat gode godz usno usn3 goug </pre>'},\n'fileFormat_tideGeneratingPotential': { 'name': 'TideGeneratingPotential', 'key': 'fileFormat_tideGeneratingPotential', 'description': 'groops tideGeneratingPotential version=20200123        7160 # Degree    Dood.    cos                       sin                      name # ==========================================================================           3 055.556  0.000000000000000000e+00 -6.569000000000000125e-07 \"\"           3 055.635  0.000000000000000000e+00 -2.842000000000000170e-07 \"\"           3 055.561  0.000000000000000000e+00 -6.360000000000000040e-08 \"\"           2 055.563 -3.122600001000726621e-06  0.000000000000000000e+00 \"\"           2 055.565  7.719644799947265879e-02  0.000000000000000000e+00 om1           3 055.645  0.000000000000000000e+00  2.921429999971616515e-05 \"\"           2 055.573  1.975999999999999959e-07  0.000000000000000000e+00 \"\"           2 055.575 -7.535264999889109729e-04  0.000000000000000000e+00 om2', 'config_table': '', 'display_text': '<pre> groops tideGeneratingPotential version=20200123        7160 # Degree    Dood.    cos                       sin                      name # ==========================================================================           3 055.556  0.000000000000000000e+00 -6.569000000000000125e-07 \"\"           3 055.635  0.000000000000000000e+00 -2.842000000000000170e-07 \"\"           3 055.561  0.000000000000000000e+00 -6.360000000000000040e-08 \"\"           2 055.563 -3.122600001000726621e-06  0.000000000000000000e+00 \"\"           2 055.565  7.719644799947265879e-02  0.000000000000000000e+00 om1           3 055.645  0.000000000000000000e+00  2.921429999971616515e-05 \"\"           2 055.573  1.975999999999999959e-07  0.000000000000000000e+00 \"\"           2 055.575 -7.535264999889109729e-04  0.000000000000000000e+00 om2 </pre></p><p>'},\n'fileFormat_timeSplinesCovariance': { 'name': 'TimeSplinesCovariance', 'key': 'fileFormat_timeSplinesCovariance', 'description': 'Stores covariance information for  TimeSplinesGravityField . It can be the variances of the potential coefficients or the full covariance matrix for each temporal nodal point.', 'config_table': '', 'display_text': 'Stores covariance information for <a class=\"groops-file\" href=\"fileFormat_timeSplinesGravityField.html\">TimeSplinesGravityField</a>. It can be the variances of the potential coefficients or the full covariance matrix for each temporal nodal point.'},\n'fileFormat_timeSplinesGravityField': { 'name': 'TimeSplinesGravityField', 'key': 'fileFormat_timeSplinesGravityField', 'description': 'Temporal changing gravity field, parametrized as spherical harmonics in the spatial domain and parametrized as basis splines in the time domain (see  basis splines ). It is evaluated with   Temporal changing gravity field, parametrized as spherical harmonics in the spatial domain and parametrized as basis splines in the time domain (see  . See also:  Gravityfield2TimeSplines ,  PotentialCoefficients2BlockMeanTimeSplines .', 'config_table': '', 'display_text': 'Temporal changing gravity field, parametrized as spherical harmonics in the spatial domain and parametrized as basis splines in the time domain (see <a class=\"groops-ref\" href=\"fundamentals.basisSplines.html\">basis splines</a>). It is evaluated with <a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>.</p><p>See also: <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>, <a class=\"groops-program\" href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a>.'},\n'fileFormat_variationalEquation': { 'name': 'VariationalEquation', 'key': 'fileFormat_variationalEquation', 'description': 'Arcs with reference orbit and state transition matrices. The file contains a reference orbit (position and velocity), the derivatives of the orbit with respect to the satellite state vector for each arc, transformations (rotations) between the satellite, celestial, and terrestrial frame and a satellite macro model (see  SatelliteModel ). The reference orbit can be extracted with  Variational2OrbitAndStarCamera . See also:  PreprocessingVariationalEquation .', 'config_table': '', 'display_text': 'Arcs with reference orbit and state transition matrices.</p><p>The file contains a reference orbit (position and velocity), the derivatives of the orbit with respect to the satellite state vector for each arc, transformations (rotations) between the satellite, celestial, and terrestrial frame and a satellite macro model (see <a class=\"groops-file\" href=\"fileFormat_satelliteModel.html\">SatelliteModel</a>).</p><p>The reference orbit can be extracted with <a class=\"groops-program\" href=\"Variational2OrbitAndStarCamera.html\">Variational2OrbitAndStarCamera</a>.</p><p>See also: <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.</p><p>'},\n};\n"
  },
  {
    "path": "docs/html/doodson.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - doodson</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"doodson\">Doodson</h1><p>\nThis is a string which describes a tidal frequency either coded as Doodson number\nor using Darwin´s name, e.g. <code>255.555</code> or <code>M2</code>.</p><p>The following names are defined:\n<ul>\n\n<li><code>055.565</code>: <code>om1</code>  </li><li>\n<code>055.575</code>: <code>om2</code>     </li><li>\n<code>056.554</code>: <code>sa</code>\n</li><li>\n<code>056.555</code>: <code>sa</code>   </li><li>\n<code>057.555</code>: <code>ssa</code>     </li><li>\n<code>058.554</code>: <code>sta</code>\n</li><li>\n<code>063.655</code>: <code>msm</code>  </li><li>\n<code>065.455</code>: <code>mm</code>      </li><li>\n<code>073.555</code>: <code>msf</code>\n</li><li>\n<code>075.555</code>: <code>mf</code>   </li><li>\n<code>083.655</code>: <code>mstm</code>    </li><li>\n<code>085.455</code>: <code>mtm</code>\n</li><li>\n<code>093.555</code>: <code>msq</code>  </li><li>\n<code>093.555</code>: <code>msqm</code>    </li><li>\n<code>125.755</code>: <code>2q1</code>\n</li><li>\n<code>127.555</code>: <code>sig1</code> </li><li>\n<code>127.555</code>: <code>sigma1</code>  </li><li>\n<code>135.655</code>: <code>q1</code>\n</li><li>\n<code>137.455</code>: <code>ro1</code>  </li><li>\n<code>137.455</code>: <code>rho1</code>    </li><li>\n<code>145.555</code>: <code>o1</code>\n</li><li>\n<code>147.555</code>: <code>tau1</code> </li><li>\n<code>155.655</code>: <code>m1</code>      </li><li>\n<code>157.455</code>: <code>chi1</code>\n</li><li>\n<code>162.556</code>: <code>pi1</code>  </li><li>\n<code>163.555</code>: <code>p1</code>      </li><li>\n<code>164.555</code>: <code>s1</code>\n</li><li>\n<code>165.555</code>: <code>k1</code>   </li><li>\n<code>166.554</code>: <code>psi1</code>    </li><li>\n<code>167.555</code>: <code>fi1</code>\n</li><li>\n<code>167.555</code>: <code>phi1</code> </li><li>\n<code>173.655</code>: <code>the1</code>    </li><li>\n<code>173.655</code>: <code>theta1</code>\n</li><li>\n<code>175.455</code>: <code>j1</code>   </li><li>\n<code>183.555</code>: <code>so1</code>     </li><li>\n<code>185.555</code>: <code>oo1</code>\n</li><li>\n<code>195.455</code>: <code>v1</code>   </li><li>\n<code>225.855</code>: <code>3n2</code>     </li><li>\n<code>227.655</code>: <code>eps2</code>\n</li><li>\n<code>235.755</code>: <code>2n2</code>  </li><li>\n<code>237.555</code>: <code>mu2</code>     </li><li>\n<code>237.555</code>: <code>mi2</code>\n</li><li>\n<code>245.655</code>: <code>n2</code>   </li><li>\n<code>247.455</code>: <code>nu2</code>     </li><li>\n<code>247.455</code>: <code>ni2</code>\n</li><li>\n<code>253.755</code>: <code>gam2</code> </li><li>\n<code>254.556</code>: <code>alf2</code>    </li><li>\n<code>255.555</code>: <code>m2</code>\n</li><li>\n<code>256.554</code>: <code>bet2</code> </li><li>\n<code>257.555</code>: <code>dlt2</code>    </li><li>\n<code>263.655</code>: <code>la2</code>\n</li><li>\n<code>263.655</code>: <code>lmb2</code> </li><li>\n<code>263.655</code>: <code>lambda2</code> </li><li>\n<code>265.455</code>: <code>l2</code>\n</li><li>\n<code>271.557</code>: <code>2t2</code>  </li><li>\n<code>272.556</code>: <code>t2</code>      </li><li>\n<code>273.555</code>: <code>s2</code>\n</li><li>\n<code>274.554</code>: <code>r2</code>   </li><li>\n<code>275.555</code>: <code>k2</code>      </li><li>\n<code>283.655</code>: <code>ksi2</code>\n</li><li>\n<code>285.455</code>: <code>eta2</code> </li><li>\n<code>355.555</code>: <code>m3</code>      </li><li>\n<code>381.555</code>: <code>t3</code>\n</li><li>\n<code>382.555</code>: <code>s3</code>   </li><li>\n<code>383.555</code>: <code>r3</code>      </li><li>\n<code>435.755</code>: <code>n4</code>\n</li><li>\n<code>445.655</code>: <code>mn4</code>  </li><li>\n<code>455.555</code>: <code>m4</code>      </li><li>\n<code>473.555</code>: <code>ms4</code>\n</li><li>\n<code>491.555</code>: <code>s4</code>   </li><li>\n<code>655.555</code>: <code>m6</code>      </li><li>\n<code>855.555</code>: <code>m8</code>\n</li></ul>\n\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/earthRotationType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - earthRotationType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"earthRotationType\">EarthRotation</h1><p>\nThis class realize the transformation between a terestrial\nreference frame (TRF) and a celestial reference frame (CRF).\n</p>\n\n<h2 id=\"file\">File</h2><p>\nThis class realize the transformation by interpolation from file.\nThis file can be created with <a class=\"groops-program\" href=\"EarthOrientationParameterTimeSeries.html\">EarthOrientationParameterTimeSeries</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for polynomial interpolation</td></tr>\n</table>\n\n<h2>Iers2010</h2><p>\nThis class realize the transformation according to the IERS2010 conventions\ngiven by the <em>International Earth Rotation and Reference Systems Service</em> (IERS).\nA file with the earth orientation parameter is needed (<a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">inputfileEOP</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">truncatedNutation</div></div></td><td>boolean</td><td>use truncated nutation model (IAU2006B)</td></tr>\n</table>\n\n<h2 id=\"iers2010b\">Iers2010b</h2><p>\nThis class realize the transformation according to the IERS2010 conventions\ngiven by the <em>International Earth Rotation and Reference Systems Service</em> (IERS).\nA file with the earth orientation parameter is needed (<a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">inputfileEOP</a>).\nIncludes additional high-frequency EOP models (<a class=\"groops-class\" href=\"fileFormat_doodsonEarthOrientationParameter.html\">inputfileDoodsonEOP</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileDoodsonEOP</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>Iers2003</h2><p>\nThis class realize the transformation according to IERS2003 conventions\ngiven by the <em>International Earth Rotation and Reference Systems Service</em> (IERS).\nA file with the earth orientation parameter is needed (<a class=\"groops-class\" href=\"fileFormat_earthOrientationParameter.html\">inputfileEOP</a>).</p><p>The following subroutines are used:\n<ul>\n\n<li>BPN2000.f,\n</li><li>\nERA2000.f,\n</li><li>\npmsdnut.f,\n</li><li>\nPOM2000.f,\n</li><li>\nSP2000.f,\n</li><li>\nT2C2000.f,\n</li><li>\nXYS2000A.f\n</li></ul>\n\nfrom <a href=\"ftp://maia.usno.navy.mil/conv2000/chapter5/\" target=\"_blank\">ftp://maia.usno.navy.mil/conv2000/chapter5/</a> and\n<ul>\n\n<li>orthoeop.f\n</li></ul>\n\nfrom <a href=\"ftp://maia.usno.navy.mil/conv2000/chapter8/\" target=\"_blank\">ftp://maia.usno.navy.mil/conv2000/chapter8/</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileEOP</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>Iers1996</h2><p>\nVery old.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileEOP</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNutation</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>Gmst</h2><p>\nThe transformation is realized as rotation about the z-axis.\nThe angle ist given by the Greenwich Mean Siderial Time (GMST).\n<pre>\n  Double Tu0 = (timeUTC.mjdInt()-51544.5)/36525.0;</p><p>  Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))\n               + (8640184.812866/(24*60*60))*Tu0\n               + (0.093104/(24*60*60))*Tu0*Tu0\n               + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;\n  Double r = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;\n  GMST = fmod(2*PI*(GMST0 + r * timeUTC.mjdMod()), 2*PI);\n</pre>\n</p>\n\n<h2>Earth Rotation Angle (ERA)</h2><p>\nThe transformation is realized as rotation about the z-axis.\nThe angle ist given by the Earth Rotation Angle (ERA) as\n<pre>\n  const Time T = timeUT1-mjd2time(J2000);\n  ERA = fmod(2*PI*(0.7790572732640 + T.mjdMod() + 0.00273781191135448*T.mjd()), 2*PI);\n</pre>\n</p>\n\n<h2>Z-Axis</h2><p>\nThe transformation is realized as rotation about the z-axis.\nYou must specify the angle (<strong class=\"groops-config-element\">initialAngle</strong>) at <strong class=\"groops-config-element\">time0</strong> and\nthe angular velocity (<strong class=\"groops-config-element\">angularVelocity</strong>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">initialAngle</div></div></td><td>double</td><td>Angle at time0 [rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">angularVelocity</div></div></td><td>double</td><td>[rad/s]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time0</div></div></td><td>time</td><td></td></tr>\n</table>\n\n<h2>StarCamera</h2><p>\nThis class reads quaternions from an instrument file and interpolates to the given time stamp.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>degree of interpolation polynomial</td></tr>\n</table>\n\n<h2>MoonRotation</h2><p>\nThis class realizes the transformation between the moon-fixed system\n(Principal Axis System (PA) or Mean Earth System (ME))\nand the ICRS according to the JPL ephemeris file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileEphemerides</div></div></td><td>filename</td><td>librations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">moonfixedSystem</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">PA</div></div></td><td></td><td>Principal Axis System</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ME</div></div></td><td></td><td>Mean Earth System</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/eclipseType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - eclipseType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"eclipseType\">Eclipse</h1><p>\nShadowing of satellites by moon and Earth provided as factor\nbetween $[0,1]$ with 0: full shadow and 1: full sun light.\n</p>\n\n<h2>Conical</h2><p>\n<figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/eclipseConical.png\" alt=\"eclipseConical\"><figcaption class=\"center\">Figure: Modelling umbra and penumbra.</figcaption></figure>\n</p>\n\n<h2>SOLAARS</h2><p>\nEarth’s penumbra modeling with Solar radiation pressure with\nOblateness and Lower Atmospheric Absorption, Refraction, and Scattering (SOLAARS).\nSee Robertson, Robbie. (2015),\nHighly Physical Solar Radiation Pressure Modeling During Penumbra Transitions (pp. 67-75).\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/ephemeridesType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ephemeridesType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"ephemeridesType\">Ephemerides</h1><p>\nEphemerides of Sun, Moon and planets.\nThe coordinate system is defined as center of <a class=\"groops-class\" href=\"planetType.html\">origin</a>.\n</p>\n\n<h1 id=\"jpl\">JPL</h1><p>\nUsing <code>DExxx</code> ephemerides from NASA Jet Propulsion Laboratory (JPL).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileEphemerides</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">origin</div></div></td><td><a href=\"planetType.html\">planet</a></td><td>center of coordinate system</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_admittance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Admittance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Admittance (file format)</h1><p>\n\nInterpolation matrix to create ocean minor tides from modeled major tides.\nThe file can be created with <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a> and used e.g. in\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>.</p><p>See <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_arcList.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ArcList</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ArcList (file format)</h1><p>\n\nWith the <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a> an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a> can\nbe divided into time intervals and within the intervals into arcs.\nThis file provides the information about the mapping of arcs to time intervals.</p><p>This file can be used for the variational equation approach or <a class=\"groops-program\" href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a>.</p><p><pre>\ngroops arclist version=20200123\n         32  # number of times\n# time [MJD]               first arc\n# ==================================\n 58909.000000000000000000          0\n 58910.000000000000000000          8\n 58911.000000000000000000         17\n 58912.000000000000000000         25\n 58913.000000000000000000         29\n 58914.000000000000000000         37\n 58915.000000000000000000         45\n 58916.000000000000000000         53\n 58917.000000000000000000         61\n 58918.000000000000000000         69\n 58919.000000000000000000         78\n 58920.000000000000000000         86\n 58921.000000000000000000         95\n 58922.000000000000000000        103\n 58923.000000000000000000        112\n 58924.000000000000000000        120\n 58925.000000000000000000        128\n 58926.000000000000000000        136\n 58927.000000000000000000        144\n 58928.000000000000000000        153\n 58929.000000000000000000        161\n 58930.000000000000000000        169\n 58931.000000000000000000        177\n 58932.000000000000000000        185\n 58933.000000000000000000        193\n 58934.000000000000000000        201\n 58935.000000000000000000        210\n 58936.000000000000000000        218\n 58937.000000000000000000        226\n 58938.000000000000000000        234\n 58939.000000000000000000        242\n 58940.000000000000000000        250\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_doodsonEarthOrientationParameter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonEarthOrientationParameter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonEarthOrientationParameter (file format)</h1><p>\n\nCorrections for Earth orientation parameters (EOP) ($x_p, y_p, UT1, LOD$)\nas cos/sin oscillations for a list of doodson tidal frequencies.</p><p><pre>\ngroops doodsonEarthOrientationParameter version=20200123\n        11 # number of constituents\n# dood.   xpCos [arcsec]            xpSin [arcsec]            ypCos [arcsec]            ypSin [arcsec]            ut1Cos [sec]              ut1Sin [sec]              lodCos [sec]              lodSin [sec]             name\n# ===========================================================================================================================================================================================================================\n 155.645  2.399999999999999786e-07  1.799999999999999971e-07  1.799999999999999971e-07 -2.399999999999999786e-07 -2.000000000000000042e-08  2.000000000000000042e-08 -1.499999999999999932e-07 -1.400000000000000095e-07 \"\"\n 155.655 -8.220000000000000920e-06 -6.280000000000000012e-06 -6.280000000000000012e-06  8.220000000000000920e-06  7.899999999999999537e-07 -8.599999999999999187e-07  5.219999999999999150e-06  4.829999999999999496e-06 m1\n 155.665 -1.649999999999999872e-06 -1.260000000000000007e-06 -1.260000000000000007e-06  1.649999999999999872e-06  1.600000000000000033e-07 -1.700000000000000135e-07  1.049999999999999900e-06  9.700000000000000302e-07 \"\"\n 157.455 -1.539999999999999867e-06 -1.199999999999999946e-06 -1.199999999999999946e-06  1.539999999999999867e-06  1.499999999999999932e-07 -1.600000000000000033e-07  9.799999999999999345e-07  8.899999999999999491e-07 chi1\n 157.465 -3.400000000000000270e-07 -2.599999999999999988e-07 -2.599999999999999988e-07  3.400000000000000270e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.099999999999999746e-07  1.999999999999999909e-07 \"\"\n 161.557  9.999999999999999547e-08  8.000000000000000167e-08  8.000000000000000167e-08 -9.999999999999999547e-08 -1.000000000000000021e-08  1.000000000000000021e-08 -7.000000000000000477e-08 -4.999999999999999774e-08 \"\"\n 162.556  2.549999999999999726e-06  2.019999999999999718e-06  2.019999999999999718e-06 -2.549999999999999726e-06 -2.099999999999999746e-07  2.899999999999999763e-07 -1.799999999999999919e-06 -1.289999999999999931e-06 pi1\n 163.545 -4.899999999999999672e-07 -3.799999999999999616e-07 -3.799999999999999616e-07  4.899999999999999672e-07  4.000000000000000084e-08 -5.999999999999999464e-08  3.499999999999999842e-07  2.399999999999999786e-07 \"\"\n 163.555  4.272999999999999238e-05  3.010999999999999801e-05  3.010999999999999801e-05 -4.272999999999999238e-05 -3.079999999999999734e-06  5.219999999999999150e-06 -3.270999999999999684e-05 -1.929999999999999817e-05 p1\n 164.554 -3.599999999999999943e-07 -2.800000000000000191e-07 -2.800000000000000191e-07  3.599999999999999943e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.700000000000000090e-07  1.700000000000000135e-07 \"\"\n 164.556 -1.029999999999999879e-06 -7.999999999999999638e-07 -7.999999999999999638e-07  1.029999999999999879e-06  8.000000000000000167e-08 -1.199999999999999893e-07  7.599999999999999233e-07  4.899999999999999672e-07 \"\"\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_doodsonHarmonic.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - DoodsonHarmonic</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>DoodsonHarmonic (file format)</h1><p>\n\nOcean tides are represented as time variable gravitational potential\nand is given by a fourier expansion\n\\[\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\Theta_f(t)) + V_f^s(\\M x)\\sin(\\Theta_f(t)),\n\\]where $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics.\nThe $\\Theta_f(t)$ are the arguments of the tide constituents $f$:\n\\[\n\\Theta_f(t) = \\sum_{i=1}^6 n_f^i\\beta_i(t),\n\\]where $\\beta_i(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$) and $n_f^i$\nare the Doodson multipliers for the term at frequency $f$.</p><p>To extract the potential coefficients of $V_f^c$ and $V_f^s$\nfor each frequency $f$ use <a class=\"groops-program\" href=\"DoodsonHarmonics2PotentialCoefficients.html\">DoodsonHarmonics2PotentialCoefficients</a>.</p><p>See also <a class=\"groops-program\" href=\"PotentialCoefficients2DoodsonHarmonics.html\">PotentialCoefficients2DoodsonHarmonics</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_earthOrientationParameter.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - EarthOrientationParameter</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>EarthOrientationParameter (file format)</h1><p>\n\nEarth Orientation Parameter (EOP) as provided by the International Earth Rotation and Reference Systems Service (IERS) (e.g <code>EOP 14 C04 (IAU2000A)</code>).</p><p>See <a class=\"groops-program\" href=\"IersC04IAU2000EarthOrientationParameter.html\">IersC04IAU2000EarthOrientationParameter</a>, <a class=\"groops-program\" href=\"IersRapidIAU2000EarthOrientationParameter.html\">IersRapidIAU2000EarthOrientationParameter</a>.</p><p><pre>\ngroops earthOrientationParameter version=20200123\n       9641 # number of epochs\n# UTC [MJD]                 xp [arcsec]               yp [arcsec]               deltUT [sec]              LOD [sec]                 dX [arcsec]               dY [arcsec]\n# ====================================================================================================================================================================================\n  5.894700000000000000e+04  5.690599999999999825e-02  4.099130000000000273e-01 -2.316246000000000138e-01  1.636400000000000094e-03 -2.900000000000000017e-05  5.800000000000000034e-05\n  5.894800000000000000e+04  5.771400000000000141e-02  4.110159999999999925e-01 -2.332083000000000073e-01  1.520099999999999923e-03 -6.000000000000000152e-05  2.199999999999999943e-05\n  5.894900000000000000e+04  5.813000000000000111e-02  4.120099999999999874e-01 -2.346157000000000104e-01  1.293099999999999935e-03 -7.200000000000000182e-05  3.199999999999999855e-05\n  5.895000000000000000e+04  5.854100000000000276e-02  4.129849999999999910e-01 -2.357567999999999886e-01  9.872999999999999832e-04 -7.600000000000000418e-05  5.899999999999999754e-05\n  5.895100000000000000e+04  5.908599999999999963e-02  4.139869999999999939e-01 -2.366149999999999920e-01  7.075000000000000126e-04 -8.000000000000000654e-05  8.600000000000000331e-05\n  5.895200000000000000e+04  5.976900000000000268e-02  4.154180000000000095e-01 -2.372105999999999937e-01  4.798000000000000073e-04 -8.399999999999999535e-05  1.129999999999999955e-04\n  5.895300000000000000e+04  6.095400000000000124e-02  4.167310000000000181e-01 -2.375994999999999913e-01  3.118999999999999919e-04 -8.700000000000000051e-05  1.399999999999999877e-04\n  5.895400000000000000e+04  6.210199999999999748e-02  4.180929999999999924e-01 -2.378588000000000091e-01  1.710000000000000094e-04 -9.100000000000000287e-05  1.669999999999999935e-04\n  5.895500000000000000e+04  6.290999999999999370e-02  4.196619999999999795e-01 -2.380454999999999932e-01  1.719000000000000042e-04 -6.000000000000000152e-06  8.100000000000000375e-05\n  5.895600000000000000e+04  6.385599999999999610e-02  4.214060000000000028e-01 -2.382557999999999898e-01  2.683000000000000163e-04  1.029999999999999964e-04 -3.600000000000000091e-05\n  5.895700000000000000e+04  6.455500000000000127e-02  4.229890000000000039e-01 -2.385857000000000117e-01  4.040000000000000080e-04  1.019999999999999992e-04 -2.000000000000000164e-05\n  5.895800000000000000e+04  6.440300000000000191e-02  4.242549999999999932e-01 -2.390210000000000112e-01  4.910999999999999567e-04  5.899999999999999754e-05  4.399999999999999886e-05\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_earthTide.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - EarthTide</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>EarthTide (file format)</h1><p>\n\nContaining the Love numbers together with frequency corrections to compute\nthe gravitational potential and the geometric displacements due to solid Earth tides.\nIt is used by <a class=\"groops-class\" href=\"tidesType.html\">tides</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_ephemerides.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Ephemerides</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Ephemerides (file format)</h1><p>\n\nEphemerides of sun, moon, and planets stored as coefficients of Chebyshev polynomials.\nUsed in <a class=\"groops-class\" href=\"ephemeridesType.html#jpl\">Ephemerides:jpl</a>.</p><p>See also <a class=\"groops-program\" href=\"JplAscii2Ephemerides.html\">JplAscii2Ephemerides</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_gnssAntennaDefinition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssAntennaDefinition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssAntennaDefinition (file format)</h1><p>\n\nContains a list of GNSS antennas which are identified by its\nname (type), serial, and radome. Each antenna consists of\nantenna center offsets (ACO) and antenna center variations (ACV)\nfor different signal <a class=\"groops-class\" href=\"gnssType.html\">types</a> (code and phase).\nThe ACV values for each type are stored in an elevation and azimuth dependent grid.</p><p>\n\n</p><p>See also <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>, <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.</p><p><figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/fileFormatGnssAntennaDefinition.png\" alt=\"fileFormatGnssAntennaDefinition\"><figcaption class=\"center\">Figure: Antenna center variations of ASH701945D\\_M for two frequencies of GPS and GLONASS</figcaption></figure></p><p><pre>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;groops type=\"antennaDefinition\" version=\"20190429\">\n    &lt;antennaCount>65&lt;/antennaCount>\n    ...\n    &lt;antenna>\n        &lt;name>BLOCK IIIA&lt;/name>\n        &lt;serial>G074&lt;/serial>\n        &lt;radome>2018-109A&lt;/radome>\n        &lt;comment>PCO provided by the Aerospace Corporation, PV from estimations by ESA/CODE&lt;/comment>\n        &lt;pattern>\n            &lt;count>3&lt;/count>\n            &lt;cell>\n                &lt;type>*1*G**&lt;/type>\n                &lt;offset>\n                    &lt;x>-1.23333333333333e-03&lt;/x>\n                    &lt;y>4.33333333333333e-04&lt;/y>\n                    &lt;z>3.15200000000000e-01&lt;/z>\n                &lt;/offset>\n                &lt;dZenit>1.00000000000000e+00&lt;/dZenit>\n                &lt;pattern>\n                    &lt;type>0&lt;/type>\n                    &lt;rows>1&lt;/rows>\n                    &lt;columns>18&lt;/columns>\n                    &lt;cell row=\"0\" col=\"0\">1.39000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"1\">1.28000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"2\">1.02000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"3\">5.80000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"4\">1.10000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"5\">-4.50000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"6\">-9.70000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"7\">-1.28000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"8\">-1.34000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"9\">-1.18000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"10\">-8.90000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"11\">-4.50000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"12\">1.20000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"13\">7.20000000000000e-03&lt;/cell>\n                    &lt;cell row=\"0\" col=\"14\">1.33000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"15\">1.33000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"16\">1.33000000000000e-02&lt;/cell>\n                    &lt;cell row=\"0\" col=\"17\">1.33000000000000e-02&lt;/cell>\n                &lt;/pattern>\n            &lt;/cell>\n            ...\n        &lt;/pattern>\n    &lt;/antenna>\n&lt;/groops>\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_gnssReceiverDefinition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssReceiverDefinition</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssReceiverDefinition (file format)</h1><p>\n\nContains a list of GNSS receivers which are identified by its\nname, serial, and version. Defines for each receiver a list of\nsignal <a class=\"groops-class\" href=\"gnssType.html\">types</a> which can be observed.\nCan also be used for GNSS transmitters to define a list of\ntransmitted signal types. For GLONASS satellites the frequency\nnumber can be stored in the <em>version</em> field.</p><p>See <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a>.</p><p><pre>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;groops type=\"receiverDefinition\" version=\"20190429\">\n    &lt;receiverCount>112&lt;/receiverCount>\n    &lt;receiver>\n        &lt;name>GLONASS&lt;/name>\n        &lt;serial>R779&lt;/serial>\n        &lt;version>2&lt;/version>\n        &lt;comment/>\n        &lt;types>\n            &lt;count>4&lt;/count>\n            &lt;cell>*1CR**J&lt;/cell>\n            &lt;cell>*1PR**J&lt;/cell>\n            &lt;cell>*2CR**J&lt;/cell>\n            &lt;cell>*2PR**J&lt;/cell>\n        &lt;/types>\n    &lt;/receiver>\n    ...\n    &lt;receiver>\n        &lt;name>GLONASS-K1&lt;/name>\n        &lt;serial>R802&lt;/serial>\n        &lt;version>7&lt;/version>\n        &lt;comment/>\n        &lt;types>\n            &lt;count>10&lt;/count>\n            &lt;cell>*1CR**O&lt;/cell>\n            &lt;cell>*1PR**O&lt;/cell>\n            &lt;cell>*2CR**O&lt;/cell>\n            &lt;cell>*2PR**O&lt;/cell>\n            &lt;cell>*3IR**&lt;/cell>\n            &lt;cell>*3QR**&lt;/cell>\n            &lt;cell>*4AR**&lt;/cell>\n            &lt;cell>*4BR**&lt;/cell>\n            &lt;cell>*6AR**&lt;/cell>\n            &lt;cell>*6BR**&lt;/cell>\n        &lt;/types>\n    &lt;/receiver>\n&lt;/groops>\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_gnssSignalBias.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GnssSignalBias</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GnssSignalBias (file format)</h1><p>\n\nSignal biases of GNSS transmitters or receivers for different <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>.</p><p><pre>\ngroops gnssSignalBias version=20200123\n          5 # number of signals\n# type   bias [m]\n# ===============================\n C1CG06 -1.752461109688110974e-01\n C1WG06  4.005884595055994590e-02\n C2WG06  6.597469378913034532e-02\n L1*G06 -2.736169875580296909e-02\n L2*G06  3.422596762686257871e-02\n </pre></p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>, <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>, <a class=\"groops-program\" href=\"GnssSignalBias2Matrix.html\">GnssSignalBias2Matrix</a>, <a class=\"groops-program\" href=\"GnssSignalBias2SinexBias.html\">GnssSignalBias2SinexBias</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_griddedData.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedData</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedData (file format)</h1><p>\n\nList of arbitrarily distributed points defined by geographic coordinates and ellipsoidal\nheight. Each point can also have an associated area\n(projected on the unit sphere with a total area of $4\\pi$).\nThis file format supports multiple values per point (called <code>data0</code>, <code>data1</code> and so on).</p><p>For regular gridded data and binary format (<code>*.dat</code>) a more efficient storage scheme is used.</p><p>See also: <a class=\"groops-program\" href=\"GriddedDataCreate.html\">GriddedDataCreate</a>.</p><p><pre>\ngroops griddedData version=20200123\n 1  2  6.378137000000000000e+06  6.356752314140356146e+06 72 # hasArea, data columns, ellipoid a, ellipoid b, data rows\n# longitude [deg]           latitude [deg]            height [m]                unit areas [-]             data0                     data1\n# ===========================================================================================================================================================\n -1.650000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.350000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.050000000000000142e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -7.500000000000001421e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -4.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.499999999999997691e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  4.499999999999997868e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  7.499999999999997158e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.049999999999999574e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.349999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.649999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.650000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00\n -1.350000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00\n</pre></p><p></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_griddedDataTimeSeries.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - GriddedDataTimeSeries</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GriddedDataTimeSeries (file format)</h1><p>\n\nTime series of data for arbitrarily distributed points defined by geographic coordinates and ellipsoidal\nheight. The data can be temporal interpolated by <a class=\"groops-ref\" href=\"fundamentals.basisSplines.html\">basis splines</a>.\nThe file format consists of a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData</a>, a time series, and\nfor each spatial point and spline node pair multiple values called <code>data0</code>, <code>data1</code>, &hellip; .</p><p>A GriddedDataTimeSeries can be generated from individual <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData</a> with the program\n<a class=\"groops-program\" href=\"GriddedData2GriddedDataTimeSeries.html\">GriddedData2GriddedDataTimeSeries</a>. Vice-versa, a GriddedDataTimeSeries can be evaluated at a\nspecific time stamp to obtain a <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">griddedData</a> with <a class=\"groops-program\" href=\"GriddedDataTimeSeries2GriddedData.html\">GriddedDataTimeSeries2GriddedData</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_instrument.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Instrument</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Instrument (file format)</h1><p>\n\nThis template file format can store different observations in a epoch wise manner. Each epoch consists of a time and\nadditional data, e.g orbits, accelerometer data, star camera quaternions (see <a class=\"groops-class\" href=\"instrumentTypeType.html\">InstrumentType</a>).\nThe time series can be divided in several arcs (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>Also a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a> file is allowed as one single arc. The first column must contain times [MJD]. Without any extra column\nthe instrument type is INSTRUMENTTIME, with one additional column the type is MISCVALUE, and for more columns the type\nMISCVALUES is used.</p><p><pre>\ngroops instrument version=20200123\n# SATELLITETRACKING\n         -9         60  # instrument type, number of arcs\n# Time [MJD]               data0: range [m]          data1: range-rate [m/s]   data2: range-acc [m/s^2]\n# =====================================================================================================\n         12 # number of epochs of 1. arc\n 54588.000000000000000000 -5.074649470097549492e+05  5.755440207134928654e-01  1.877605261528093308e-03\n 54588.000057870370255841 -5.074620458130163024e+05  5.849357691551860805e-01  1.878948916234051596e-03\n 54588.000115740740966430 -5.074590976427756250e+05  5.943331739937073310e-01  1.879937220634776869e-03\n 54588.000173611111222272 -5.074561024756557308e+05  6.037340169611068452e-01  1.880370529387525701e-03\n 54588.000231481481478113 -5.074530602992626373e+05  6.131368121270999172e-01  1.880680632122925426e-03\n 54588.000289351851733954 -5.074499711071007187e+05  6.225398878861636565e-01  1.880495369480403561e-03\n 54588.000347222222444543 -5.074468349029610981e+05  6.319414138081351773e-01  1.880073731783055927e-03\n 54588.000405092592700385 -5.074436516971451929e+05  6.413404243585696385e-01  1.879464843086203459e-03\n 54588.000462962962956226 -5.074404215058300761e+05  6.507353310092597320e-01  1.878578987216372124e-03\n 54588.000520833333212067 -5.074371443491023383e+05  6.601267978060636477e-01  1.877878184949659246e-03\n 54588.000578703703922656 -5.074338202460713219e+05  6.695136489207137442e-01  1.876962042758626532e-03\n 54588.000636574074178498 -5.074304492190054734e+05  6.788964444122400632e-01  1.876091925462087043e-03\n         12 # number of epochs of 2. arc\n 54588.000694444444434339 -5.074270312892858055e+05  6.882748400534359767e-01  1.875376456928801432e-03\n 54588.000752314814690180 -5.074235664742725785e+05  6.976508178537534910e-01  1.874929898412159559e-03\n 54588.000810185185400769 -5.074200547868391732e+05  7.070236200716006891e-01  1.874312324351668077e-03\n 54588.000868055555656611 -5.074164962409950094e+05  7.163943828291452487e-01  1.873924188388115340e-03\n 54588.000925925925912452 -5.074128908454515622e+05  7.257639682023964145e-01  1.874025826380292404e-03\n 54588.000983796296168293 -5.074092386012640782e+05  7.351333608427884636e-01  1.873680487441316657e-03\n 54588.001041666666878882 -5.074055395130896359e+05  7.445020815182646912e-01  1.873849502509668122e-03\n 54588.001099537037134724 -5.074017935789784533e+05  7.538716732272922050e-01  1.873971633320137753e-03\n 54588.001157407407390565 -5.073980007962241652e+05  7.632414098560330595e-01  1.873984767500571974e-03\n 54588.001215277777646406 -5.073941611626467784e+05  7.726123093411200182e-01  1.874295246964456478e-03\n 54588.001273148148356995 -5.073902746728868224e+05  7.819835205798950639e-01  1.874226146744964808e-03\n 54588.001331018518612836 -5.073863413272026228e+05  7.913547196412918927e-01  1.874173804634685515e-03\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_matrix.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Matrix</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Matrix (file format)</h1><p>\n\nStores matrices and vectors. Only one triangle is written for symmetric or triangular matrices.</p><p>The header (the matrix definition) is optional.\nTherefore a pure text with only numbers in columns are also allowed.\nThis simplifies the handling of external data.</p><p>Instead of a matrix file also an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument</a> file is allowed.\nThe first column is the time [MJD], the other columns depends on the instrument type.</p><p><pre>\ngroops matrix version=20200123\nLowerSymmetricMatrix( 4 x 4 )\n  1.000000000000000000e+00\n  0.000000000000000000e+00  1.000000000000000000e+00\n  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00\n  0.000000000000000000e+00  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00\n</pre></p><p></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_meanPolarMotion.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - MeanPolarMotion</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>MeanPolarMotion (file format)</h1><p>\n\nThe mean pole of the Earth rotation is represented by a polynomial in a time interval.</p><p><pre>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;groops type=\"meanPolarMotion\" version=\"20200123\">\n  &lt;meanPolarMotion>\n    &lt;intervalCount>2&lt;/intervalCount>\n    &lt;interval>\n      &lt;timeStart>42778.0000000000000000&lt;/timeStart>\n      &lt;degree>3&lt;/degree>\n      &lt;xp>5.59741000000000e-02&lt;/xp>\n      &lt;xp>1.82430000000000e-03&lt;/xp>\n      &lt;xp>1.84130000000000e-04&lt;/xp>\n      &lt;xp>7.02400000000000e-06&lt;/xp>\n      &lt;yp>3.46346000000000e-01&lt;/yp>\n      &lt;yp>1.78960000000000e-03&lt;/yp>\n      &lt;yp>-1.07290000000000e-04&lt;/yp>\n      &lt;yp>-9.08000000000000e-07&lt;/yp>\n    &lt;/interval>\n    &lt;interval>\n      &lt;timeStart>55197.0000000000000000&lt;/timeStart>\n      &lt;degree>1&lt;/degree>\n      &lt;xp>2.35130000000000e-02&lt;/xp>\n      &lt;xp>7.61410000000000e-03&lt;/xp>\n      &lt;yp>3.58891000000000e-01&lt;/yp>\n      &lt;yp>-6.28700000000000e-04&lt;/yp>\n    &lt;/interval>\n  &lt;/meanPolarMotion>\n&lt;/groops>\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_normalEquation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - NormalEquation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>NormalEquation (file format)</h1><p>\n\nStores a <a class=\"groops-ref\" href=\"normalEquationType.html\">system of normal equations</a>\n\\[\n  \\M N \\hat{\\M x} = \\M n.\n\\]\nThis file format consists of multiple files.\nThe file name <code>normals.dat.gz</code> corresponds to the following files:\n<ul>\n\n<li><code>normals.dat.gz</code> or <code>normals.00.00.dat.gz</code> ... <code>normals.0n.0n.dat.gz</code>:\n      the normal matrix $\\M N$ as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>,\n</li><li>\n<code>normals.rightHandSide.dat.gz</code>:\n      the right hand side(s) $\\M n$ as <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>,\n</li><li>\n<code>normals.parameterNames.txt</code>: <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a>,\n</li><li>\n<code>normals.info.xml</code>:\n     u.a. containing the number of observations and the quadratic sum of (reduced) observations $\\M l^T\\M P\\M l$.\n</li></ul>\n\nA large normal matrix may be splitted into blocks and stored in multiple files.\nThe block row/column number is indicated in the file name.\nOnly the upper blocks of the sysmmetric matrix are considered.\nMatrix in blocks can be distributed on muliple nodes in parallel mode to efficiently use distributed memory.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_oceanPoleTide.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - OceanPoleTide</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>OceanPoleTide (file format)</h1><p>\n\nDescribes the reaction of the ocean mass to the change\nof the centrifugal potential (polar wobble) in terms spherical harmonics.</p><p>See also <a class=\"groops-program\" href=\"Iers2OceanPoleTide.html\">Iers2OceanPoleTide</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_parameterName.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - ParameterName</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>ParameterName (file format)</h1><p>\n\nName of parameters of a system of <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a> or <a class=\"groops-file\" href=\"fileFormat_matrix.html\">solution vector</a>.</p><p>A parameter name is a string <code>&lt;object>:&lt;type>:&lt;temporal>:&lt;interval></code> containg four parts divided by <code>:</code>\n<ol>\n\n<li>object: Object this parameter refers to, e.g. <code>graceA</code>, <code>G023</code>, <code>earth</code>, &hellip; </li><li>\ntype: Type of this parameter, e.g. <code>accBias</code>, <code>position.x</code>, &hellip; </li><li>\ntemporal: Temporal representation of this parameter, e.g. <code>trend</code>, <code>polynomial.degree1</code>, &hellip; </li><li>\ninterval: Interval/epoch this parameter represents, e.g. <code>2017-01-01_00-00-00_2017-01-02_00-00-00</code>, <code>2018-01-01_00-00-00</code>.\n</li></ol>\n\nIn the documentation a star (<code>*</code>) in the name means this part is untouched and useally set by other classes.\nTimes are written as <code>yyyy-mm-dd_hh-mm-ss</code> and intervals (if not empty) as <code>&lt;timeStart>_&lt;timeEnd></code>.</p><p>See <a class=\"groops-program\" href=\"ParameterNamesCreate.html\">ParameterNamesCreate</a>.</p><p><pre>\ngroops parameterName version=20200123\n# object:type:temporal:interval\n# =============================\n      10080 # number of parameters\n karr:position.x::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:position.y::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:position.z::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_02-00-00\n karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_04-00-00\n karr:troposphereWet:spline.n1:2018-06-01_02-00-00_2018-06-01_06-00-00\n karr:troposphereWet:spline.n1:2018-06-01_04-00-00_2018-06-01_08-00-00\n karr:troposphereWet:spline.n1:2018-06-01_06-00-00_2018-06-01_10-00-00\n karr:troposphereWet:spline.n1:2018-06-01_08-00-00_2018-06-01_12-00-00\n karr:troposphereWet:spline.n1:2018-06-01_10-00-00_2018-06-01_14-00-00\n karr:troposphereWet:spline.n1:2018-06-01_12-00-00_2018-06-01_16-00-00\n karr:troposphereWet:spline.n1:2018-06-01_14-00-00_2018-06-01_18-00-00\n karr:troposphereWet:spline.n1:2018-06-01_16-00-00_2018-06-01_20-00-00\n karr:troposphereWet:spline.n1:2018-06-01_18-00-00_2018-06-01_22-00-00\n karr:troposphereWet:spline.n1:2018-06-01_20-00-00_2018-06-02_00-00-00\n karr:troposphereWet:spline.n1:2018-06-01_22-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:signalBias01(+1.00L1CG**)::\n karr:signalBias02(+1.00L2WG**)::\n karr:signalBias03(+1.00L2XG**)::\n G01:solarRadiationPressure.ECOM.D0::\n G01:solarRadiationPressure.ECOM.DC2::\n G01:solarRadiationPressure.ECOM.DS2::\n G01:solarRadiationPressure.ECOM.Y0::\n G01:solarRadiationPressure.ECOM.B0::\n G01:solarRadiationPressure.ECOM.BC1::\n G01:solarRadiationPressure.ECOM.BS1::\n G01:stochasticPulse.x::2018-06-01_12-00-00\n G01:stochasticPulse.y::2018-06-01_12-00-00\n G01:stochasticPulse.z::2018-06-01_12-00-00\n G01:arc0.position0.x::\n G01:arc0.position0.y::\n G01:arc0.position0.z::\n G01:arc0.velocity0.x::\n G01:arc0.velocity0.y::\n G01:arc0.velocity0.z::\n G01:signalBias01(-1.00C1CG01)::\n G01:signalBias02(+1.00L1*G01)::\n G01:signalBias03(+1.00L2*G01)::\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_platform.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Platform</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Platform (file format)</h1><p>\n\nDefines a platform with a local coordinate frame equipped with instruments.\nThe platform might be a reference station, a low Earth satellite,\nor a transmitting GNSS satellite and is referenced by a marker name and number.\nThe reference point (marker or center of mass (CoM)) can change in time\nrelative to the local frame.</p><p>Each equipped instrument is described at least by the following information\n<ul>\n\n<li>name\n</li><li>\nserial number\n</li><li>\ncoordinates in the local frame\n</li><li>\na time interval in which the instrument was active\n</li><li>\nthe orientation for antennas and reflectors.\n</li></ul>\n</p><p>For GNSS satellites the platform defines the PRN. The different assigned SVNs\nare defined by the transmitting antennas.</p><p>Platforms for GNSS stations can be created from station log files with\n<a class=\"groops-program\" href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a>. Platforms for GNSS satellites\ncan be created from an ANTEX file with <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a>.</p><p>See also <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/fileFormatPlatform.png\" alt=\"fileFormatPlatform\"><figcaption class=\"center\">Figure: Platform for stations, LEOs, and GNSS satellites.</figcaption></figure>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_polygon.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Polygon</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Polygon (file format)</h1><p>\n\nList of longitude and latitudes to describe borders, e.g. river basins or continents.\nIt is used in <a class=\"groops-class\" href=\"borderType.html#polygon\">border:polygon</a>.</p><p><pre>\ngroops polygon version=20200123\n          2  # number of polygons\n          6  # number of points (1. polygon)\n# longitude [deg]           latitude [deg]\n# ==================================================\n -1.598200000000000216e+02  2.203000000000000114e+01\n -1.596200000000000045e+02  2.189999999999999858e+01\n -1.593799999999999955e+02  2.189999999999999858e+01\n -1.593000000000000114e+02  2.221999999999999886e+01\n -1.595800000000000125e+02  2.221999999999999886e+01\n -1.598200000000000216e+02  2.203000000000000114e+01\n          5  # number of points (2. polygon)\n# longitude [deg]           latitude [deg]\n# ==================================================\n -7.900000000000000000e+01  2.669999999999999929e+01\n -7.870000000000000284e+01  2.650000000000000000e+01\n -7.823000000000000398e+01  2.667000000000000171e+01\n -7.793000000000000682e+01  2.667000000000000171e+01\n -7.779999999999999716e+01  2.646999999999999886e+01\n</pre></p><p></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_potentialCoefficients.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - PotentialCoefficients</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>PotentialCoefficients (file format)</h1><p>\n\nThe standard <code>.gfc</code> format as defined by the ICGEM is used in ASCII the format.\nOnly the static part is used and temporal variations (e.g. trend) are ignored.\nTo write additional information and temporal variations use <a class=\"groops-program\" href=\"PotentialCoefficients2Icgem.html\">PotentialCoefficients2Icgem</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_satelliteModel.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - SatelliteModel</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>SatelliteModel (file format)</h1><p>\n\nProperties of a satellite to model non-conservative forces (e.g. <a class=\"groops-class\" href=\"miscAccelerationsType.html\">miscAccelerations</a>).\nThe file may contain surface properties, mass, drag coefficients, and antenna thrust values.</p><p>See <a class=\"groops-program\" href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a> and <a class=\"groops-program\" href=\"SinexMetadata2SatelliteModel.html\">SinexMetadata2SatelliteModel</a>.</p><p><pre>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;groops type=\"satelliteModel\" version=\"20190429\">\n   &lt;satelliteCount>1&lt;/satelliteCount>\n   &lt;satellite>\n       &lt;satelliteName>GALILEO-2&lt;/satelliteName>\n       &lt;mass>7.00000000000000e+02&lt;/mass>\n       &lt;coefficientDrag>0.00000000000000e+00&lt;/coefficientDrag>\n       &lt;surfaceCount>15&lt;/surfaceCount>\n       &lt;surface>\n           &lt;type>0&lt;/type>\n           &lt;normal>\n               &lt;x>-1.00000000000000e+00&lt;/x>\n               &lt;y>0.00000000000000e+00&lt;/y>\n               &lt;z>0.00000000000000e+00&lt;/z>\n           &lt;/normal>\n           &lt;area>4.40000000000000e-01&lt;/area>\n           &lt;reflexionVisible>0.00000000000000e+00&lt;/reflexionVisible>\n           &lt;diffusionVisible>7.00000000000000e-02&lt;/diffusionVisible>\n           &lt;absorptionVisible>9.30000000000000e-01&lt;/absorptionVisible>\n           &lt;reflexionInfrared>1.00000000000000e-01&lt;/reflexionInfrared>\n           &lt;diffusionInfrared>1.00000000000000e-01&lt;/diffusionInfrared>\n           &lt;absorptionInfrared>8.00000000000000e-01&lt;/absorptionInfrared>\n           &lt;hasThermalReemission>1&lt;/hasThermalReemission>\n       &lt;/surface>\n       ...\n       &lt;modulCount>2&lt;/modulCount>\n       &lt;modul>\n           &lt;type>1&lt;/type>\n           &lt;rotationAxis>\n               &lt;x>0.00000000000000e+00&lt;/x>\n               &lt;y>1.00000000000000e+00&lt;/y>\n               &lt;z>0.00000000000000e+00&lt;/z>\n           &lt;/rotationAxis>\n           &lt;normal>\n               &lt;x>0.00000000000000e+00&lt;/x>\n               &lt;y>0.00000000000000e+00&lt;/y>\n               &lt;z>1.00000000000000e+00&lt;/z>\n           &lt;/normal>\n           &lt;surface>\n               &lt;count>4&lt;/count>\n               &lt;cell>11&lt;/cell>\n               &lt;cell>12&lt;/cell>\n               &lt;cell>13&lt;/cell>\n               &lt;cell>14&lt;/cell>\n           &lt;/surface>\n       &lt;/modul>\n       &lt;modul>\n           &lt;type>2&lt;/type>\n           &lt;antennaThrust>\n               &lt;x>0.00000000000000e+00&lt;/x>\n               &lt;y>0.00000000000000e+00&lt;/y>\n               &lt;z>2.65000000000000e+02&lt;/z>\n           &lt;/antennaThrust>\n       &lt;/modul>\n   &lt;/satellite>\n&lt;/groops>\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_stringList.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - StringList</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>StringList (file format)</h1><p>\n\nWhite space separated list of strings.\nComments are allowed and all the text from the character '<code>#</code>' to the end of the line is ignored.\nStrings containing white spaces or the '<code>#</code>' character must be set in quotes ('<code>\"\"</code>').</p><p><pre>\n# IGSR3 stations\nabmf\nabpo\nade1\nadis\najac\nalbh\nalgo\nalic\nalrt\namc2\naoml\nareq\narev\nartu\nasc1\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_stringTable.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - StringTable</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>StringTable (file format)</h1><p>\n\nWhite space separated table of strings in row and columns.\nAdditional columns in a row may represent alternatives, e.g. for core stations in a GNSS network.\nComments are allowed and all the text from the character '<code>#</code>' to the end of the line is ignored.\nStrings containing white spaces or the '<code>#</code>' character must be set in quotes  ('<code>\"\"</code>').</p><p><pre>\n# core network with alternative stations\nartu mdvj mdvo nril\nasc1 sthl\nbahr bhr1 yibl nama\nchat chti auck\nchpi braz ufpr savo\nckis nium\ncoco xmis dgar dgav\ncro1 scub abmf lmmf aoml\ndaej taej suwn osn1\ndarw kat1 tow2 alic\ndav1 maw1\ndrao albh will holb nano\nfair whit\nglps guat\ngode godz usno usn3\ngoug\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_tideGeneratingPotential.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TideGeneratingPotential</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TideGeneratingPotential (file format)</h1><p>\n<pre>\ngroops tideGeneratingPotential version=20200123\n       7160\n# Degree    Dood.    cos                       sin                      name\n# ==========================================================================\n          3 055.556  0.000000000000000000e+00 -6.569000000000000125e-07 \"\"\n          3 055.635  0.000000000000000000e+00 -2.842000000000000170e-07 \"\"\n          3 055.561  0.000000000000000000e+00 -6.360000000000000040e-08 \"\"\n          2 055.563 -3.122600001000726621e-06  0.000000000000000000e+00 \"\"\n          2 055.565  7.719644799947265879e-02  0.000000000000000000e+00 om1\n          3 055.645  0.000000000000000000e+00  2.921429999971616515e-05 \"\"\n          2 055.573  1.975999999999999959e-07  0.000000000000000000e+00 \"\"\n          2 055.575 -7.535264999889109729e-04  0.000000000000000000e+00 om2\n</pre></p><p></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_timeSplinesCovariance.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TimeSplinesCovariance</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TimeSplinesCovariance (file format)</h1><p>\n\nStores covariance information for <a class=\"groops-file\" href=\"fileFormat_timeSplinesGravityField.html\">TimeSplinesGravityField</a>.\nIt can be the variances of the potential coefficients or the full covariance matrix for each\ntemporal nodal point.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_timeSplinesGravityField.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - TimeSplinesGravityField</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>TimeSplinesGravityField (file format)</h1><p>\n\nTemporal changing gravity field, parametrized as spherical harmonics in the spatial domain and\nparametrized as basis splines in the time domain (see <a class=\"groops-ref\" href=\"fundamentals.basisSplines.html\">basis splines</a>).\nIt is evaluated with <a class=\"groops-class\" href=\"gravityfieldType.html#timeSplines\">gravityfield:timeSplines</a>.</p><p>See also: <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a>, <a class=\"groops-program\" href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fileFormat_variationalEquation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - VariationalEquation</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>VariationalEquation (file format)</h1><p>\n\nArcs with reference orbit and state transition matrices.</p><p>The file contains a reference orbit (position and velocity),\nthe derivatives of the orbit with respect to the satellite state vector for each arc,\ntransformations (rotations) between the satellite, celestial, and terrestrial frame\nand a satellite macro model (see <a class=\"groops-file\" href=\"fileFormat_satelliteModel.html\">SatelliteModel</a>).</p><p>The reference orbit can be extracted with <a class=\"groops-program\" href=\"Variational2OrbitAndStarCamera.html\">Variational2OrbitAndStarCamera</a>.</p><p>See also: <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.</p><p></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/forcesType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - forcesType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"forcesType\">Forces</h1><p>\nThis class provides the forces acting on a satellite.\nThis encompasses <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>, <a class=\"groops-class\" href=\"tidesType.html\">tides</a>\nand <a class=\"groops-class\" href=\"miscAccelerationsType.html\">miscAccelerations</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">forcesType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">tides</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">miscAccelerations</div></div></td><td><a href=\"miscAccelerationsType.html\">miscAccelerations</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fundamentals.autoregressiveModel.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Autoregressive model</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"fundamentals.autoregressiveModel\">Autoregressive Models</h1><p>\nA multivariate (or vector) autoregressive model is one possible representation of a random process.\nIt specifies, that the output at epoch $t$ depends on the $p$ previous epochs, where $p$ is denoted process order,\nplus a stochastic term.\nIn the following, finite order vector autoregressive - VAR($p$) in short - models as implemented in GROOPS will be described.</p><p><h2>Definition</h2><p></p><p>A finite order VAR($p$) model is defined as\n\\[\n  \\mathbf{y}_e(t_i) = \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{w}(t_i),\n  \\hspace{5pt} \\mathbf{w}(t_i) \\sim \\mathcal{N}(0, \\mathbf{\\Sigma}^{(p)}_\\mathbf{w}),\n\\]where $\\mathbf{y}_e(t_i)$ are realizations of a random vector process\nSubtracting the right hand side and substituting the stochastic term $-\\mathbf{w}(t_i)$ with the residual $\\mathbf{v}(t_i)$ gives us\n\\[\n  \\mathbf{0}  = \\mathbf{y}_e(t_i) - \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{v}(t_i)\n\\]which can be used as pseudo-observation equations in the determination of the parameters $\\mathbf{y}_e(t_i)$.\nIn matrix notation this reads\n\\[\n  0 =\n  \\begin{bmatrix}\n    \\mathbf{I} & -\\mathbf{\\Phi}^{(p)}_1 & \\cdots & -\\mathbf{\\Phi}^{(p)}_p \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{y}_e(t_i) \\\\\n    \\mathbf{y}_e(t_{i-1}) \\\\\n    \\vdots \\\\\n    \\mathbf{y}_e(t_{i-p}) \\\\\n  \\end{bmatrix}\n  + \\mathbf{v}(t_i).\n\\]After rearranging the vectors $\\mathbf{x}_t$ to have ascending time stamps\n\\[\n  0 =\n  \\begin{bmatrix}\n    -\\mathbf{\\Phi}^{(p)}_p & \\cdots & -\\mathbf{\\Phi}^{(p)}_1 & \\mathbf{I} \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{y}_e(t_{i-p}) \\\\\n    \\vdots \\\\\n    \\mathbf{y}_e(t_{i-1}) \\\\\n    \\mathbf{y}_e(t_i) \\\\\n  \\end{bmatrix}\n  + \\mathbf{v}(t_i)\n\\]For practical purposes, the residuals above are further decorrelated using the\ninverse square root of the white noise covariance matrix, leading to\n\\[\n  \\bar{\\mathbf{v}}(t_i) = \\underbrace{\\mathbf{\\Sigma}^{(p)^{-\\frac{1}{2}}}_\\mathbf{w}}_{=\\mathbf{W}}\\mathbf{v}(t_i), \\hspace{25pt}  \\bar{\\mathbf{v}}(t_i) \\sim \\mathcal{N}(0, \\mathbf{I}).\n\\]The used square root is in principle arbitrary, but should satisfy $\\mathbf{W}^T\\mathbf{W} = \\mathbf{\\Sigma}^{(p)}_\\mathbf{w} $.\nThis means that both eigendecomposition based roots and Cholesky factors can be used.\nAfter the applying the matrix from the left, we arrive at the observation equations\n\\[\n  0 =\n  \\begin{bmatrix}\n    -\\mathbf{W}\\mathbf{\\Phi}^{(p)}_p & \\cdots & -\\mathbf{W}\\mathbf{\\Phi}^{(p)}_1 & \\mathbf{W} \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{y}_e(t_{i-p}) \\\\\n    \\vdots \\\\\n    \\mathbf{y}_e(t_{i-1}) \\\\\n    \\mathbf{y}_e(t_i) \\\\\n  \\end{bmatrix}\n  + \\bar{\\mathbf{v}}(t_i)\n\\]which yields fully decorrelated residuals.\nCurrenty, VAR($p$) models are saved to a single  file which contains this matrix.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fundamentals.basisSplines.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Basis splines</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"fundamentals.basisSplines\">Basis splines</h1><p>\nA time variable function is given by\n\\[\nf(x,t) =  \\sum_i f_i(x)\\Psi_i(t),\n\\]with the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions $\\Psi_i(t)$.\nBasis splines are defined as polynomials of degree $n$ in intervals between nodal points in time $t_i$:\n<ul>\n\n<li>Block mean values ($n=0$)\n\\[\n  \\Psi_i(t) = \\begin{cases}\n  1 & \\text{if } t\\in[t_i,t_{i+1}), \\\\\n  0 & \\text{otherwise}\n\\end{cases}\n\\]</li><li>\nLinear splines ($n=1$)\n\\[\n  \\Psi_i(t) = \\begin{cases}\n    \\tau_{i-1}  & \\text{if } t_{i-1} \\le t \\le t_i, \\\\\n  1-\\tau_i      & \\text{if } t_{i}   \\le t \\le t_{i+1}, \\\\\n  0 & \\text{otherwise}.\n\\end{cases}\n\\]</li><li>\nQuadratic splines ($n=2$)\n\\[\n  \\Psi_i(t) = \\begin{cases}\n  \\frac{1}{2}\\tau^2_{i-1}                           & \\text{if } t_{i-1} \\le t \\le t_i, \\\\\n            -\\tau^2_{i}   +\\tau_{i}   +\\frac{1}{2}  & \\text{if } t_{i}   \\le t \\le t_{i+1}, \\\\\n  \\frac{1}{2}\\tau^2_{i+1} -\\tau_{i+1} +\\frac{1}{2}  & \\text{if } t_{i+1} \\le t \\le t_{i+2}, \\\\\n  0 & \\text{otherwise}.\n\\end{cases}\n\\]</li><li>\nCubic splines ($n=3$)\n\\[\n  \\Psi_i(t) = \\begin{cases}\n   \\frac{1}{6}\\tau^3_{i-2}                                                               & \\text{if } t_{i-2} \\le t \\le t_{i-1}, \\\\\n  -\\frac{3}{6}\\tau^3_{i-1} +\\frac{3}{6}\\tau^2_{i-1} +\\frac{3}{6}\\tau_{i-1} +\\frac{1}{6}  & \\text{if } t_{i-1} \\le t \\le t_i,     \\\\\n   \\frac{3}{6}\\tau^3_{i}   -           \\tau^2_{i}   +\\frac{4}{6}                         & \\text{if } t_{i}   \\le t \\le t_{i+1}, \\\\\n  -\\frac{1}{6}\\tau^3_{i+1} +\\frac{3}{6}\\tau^2_{i+1} -\\frac{3}{6}\\tau_{i+1} +\\frac{1}{6}  & \\text{if } t_{i+1} \\le t \\le t_{i+2}, \\\\\n  0 & \\text{otherwise}.\n\\end{cases}\n\\]</li></ul>\n\nwhere $\\tau$ is the normlized time in each time interval\n\\[\n  \\tau_i = \\frac{t-t_i}{t_{i+1}-t_i}.\n\\]The total number of coefficients $f_i(x)$ is $N=N_t+n-1$,\nwhere $N_t$ is the count of nodal time points $t_i$ and $n$ is the degree.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/basissplines.png\" alt=\"basissplines\"><figcaption class=\"center\">Figure: Basis splines for different degrees with nodal points every 6 hours.</figcaption></figure>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/fundamentals.robustLeastSquares.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Robust least squares adjustment</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"fundamentals.robustLeastSquares\">Robust least squares adjustment</h1><p>\nThe robust least squares adjustment used in GROOPS is based on a modified Huber\nestimator. It downweights observations with large otuliers iteratively.</p><p>The algorithm starts with a first solution with equal weights $\\M P =\\M I$\n\\[\n  \\hat{\\M x} = (\\M A^T\\M P\\M A)^{-1}\\M A^T\\M P\\M l.\n\\]The solution is used to compute the residuals\n\\[\n  \\hat{e}_i = \\left(\\M l - \\M A \\hat{\\M x}\\right)_i\n\\]and the redundancies of all observations\n\\[\n  r_i = \\left(\\M I - \\M A(\\M A^T\\M P\\M A)^{-1}\\M A^T\\M P\\right)_{ii}.\n\\]For observations with large residuals a new standard deviation is assigned\n\\[\n  \\sigma_i =\n  \\begin{cases}\n    1                                     & \\text{for } \\left|\\frac{\\hat{e}_i}{r_i}\\right| \\le h\\cdot\\hat{\\sigma} \\\\\n    \\left|\\frac{\\hat{e}_i}{r_ih}\\right|^p & \\text{for } \\left|\\frac{\\hat{e}_i}{r_i}\\right| > h\\cdot\\hat{\\sigma},\n  \\end{cases}\n\\]where $h$ is <strong class=\"groops-config-element\">huber</strong>, $p$ is <strong class=\"groops-config-element\">huberPower</strong>, and $\\hat{\\sigma}^2$ a robust overall variance factor\ncomputed from all residuals.\nThe estimation is repeated <strong class=\"groops-config-element\">huberMaxIteration</strong> times with a new weight matrix\n\\[\n  \\M P = \\text{diag}\\left(\\frac{1}{\\sigma_1^2}, \\frac{1}{\\sigma_2^2}, \\ldots, \\frac{1}{\\sigma_n^2}\\right)\n\\] or until convergence is reached.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.configFiles.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Config files</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.configFiles\">Config files</h1><p>\nGROOPS is controlled by XML configuration files. One or more configuration files\nmust be passed as arguments to GROOPS:\n<pre>\n  groops config1.xml config2.xml [...]\n</pre>\nThese files can be created with the graphical user interface program <code>groopsGui</code>\nin a convenient way (see section <a class=\"groops-ref\" href=\"general.gui.html\">GUI</a>).\nA complete formal (computer readable) description of a configuration file\nin the form of an XSD schema file can be created with the command\n<pre>\n  groops --xsd groops.xsd\n</pre></p><p>A configuration file consists of a list of <a class=\"groops-ref\" href=\"programType.html\">programs</a>\nthat are executed in sequential order. Each program comes with its own config options\nand they work independently without any internal communication between programs.\nData flow between programs is realized via files. An <strong class=\"groops-config-element\">outputfile</strong> of one program can serve as\nan <strong class=\"groops-config-element\">inputfile</strong> for the next program.\nMost programs are deliberately kept small and focused on a specific task. This modularity combined with the\ngeneral purpose design of many programs enables the creation of complex workflows with little effort.\nIncluding <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">loops and conditions</a> in a config file provides even more flexibility.</p><p>Individual programs (and also other optional config elements) can be disabled\nand are ignored during execution. Mandatory config elements are indicated by a star (<code>*</code>).\nEmpty optional elements are ignored or a meaningful default value is assumed.</p><p>The elements of a configuration file can be one of the following basic data types:\n<ul>\n\n<li><code>int</code>: integer number\n</li><li>\n<code>uint</code>: unsigned integer number\n</li><li>\n<code>double</code>: floating point number\n</li><li>\n<code>angle</code>: given in degree\n</li><li>\n<code>time</code>: given in modified Julian date (MJD)\n</li><li>\n<code>boolean</code>: 0: false, 1: true\n</li><li>\n<code>string</code>: text\n</li><li>\n<code>filename</code>: absolute path to a file or path relative to the working directory\n</li><li>\n<code>expression</code>: numerical expression evaluated during execution\n</li><li>\n<code>doodson</code>: Doodson number or Darwin's name of a tidal frequency\n</li><li>\n<code>gnssType</code>: GNSS observation type according to the RINEX 3 definition\n</li></ul>\n\nThe first 5 data types also allow numerical expressions as input in addition to pure numbers.\nIn addition to these basic types, there are a large number of complex data types called classes,\nwhich are described in section <a class=\"groops-ref\" href=\"classes.html\">Classes</a>.</p><p><h2 id=\"variables\">Variables</h2><p>\nIn addition to programs, a config file can also include elements called variables.\nThese elements are comparable to read-only variables in programming and can be referenced from any program and config element.\nThis can be done by either linking an element directly to a variable or\nby using the name as a variable in an expression of an input field (see section <a class=\"groops-ref\" href=\"general.parser.html\">Parsers and variables</a>).\nWhile elements can only be directly linked to variables of the same type, this also supports complex data types\nsuch as <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>. Thus it is possible to, for example, define a reference gravity field once\nin the global section and use it multiple times in different programs.</p><p>Variables can be declared anywhere in the configuration file. Variables in locations other than the global section\nhave a local scope and hide global variables or variables from a hierarchy level above. They are valid after\ndeclaration until the end of the hierarchy level is reached or a new variable with the same name is declared.</p><p>Variables are not evaluated directly when they are declared, but only later when they are used in a config element.\nThis means, for example, that a variable <code>satelliteFile</code> with <code>data/swarm_orbit_{loopTime:%D}.dat</code>\ncan be declared in the global section without the variable <code>loopTime</code> having to be known at this time.</p><p>One special variable is <code>groopsDataDir</code>, which is used as a variable in most default\nfile paths throughout many GROOPS programs. Since this variable is going to be needed in\nmost config files, it is recommended to define it in a template file that is used when creating\nnew config files in the GUI. See section <a class=\"groops-ref\" href=\"general.gui.html\">Graphical User Interface (GUI)</a>\nfor details on how to set up a template file.</p><p>In addition, the variables <code>groopsConfigFile</code> and <code>workingDir</code> are set automatically.</p><p>Global variables can be manipulated when running a config file by passing the argument <code>--global &lt;name>=&lt;value></code>.\nFor example, running the command\n<pre>\n  groops --global timeStart=58849 --global satellite=swarm config.xml\n</pre>\nruns the config file <code>config.xml</code> but replaces the values of the global variable <code>timeStart</code>\nand <code>satellite</code> with <code>58849</code> and <code>swarm</code>, respectively. If a global variable passed as\nan argument does not already exist in the config file, it will be added with the type <code>string</code>.\nOnly the basic data types listed above are supported. This feature can be useful when running GROOPS\nfrom the command line or from an external script file.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.constants.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Constants and the setting file</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.constants\">Constants and the settings file</h1><p>\nGROOPS uses some built-in constants like <code>DEFAULT_GM</code> or the definition\nof leap seconds, which are defined in  <code>source/base/constants.cpp</code>.</p><p>A complete list of the constants can be written to an XML file with:\n<pre>\n  groops --write-settings &lt;groopsDefaults.xml>\n</pre></p><p>The built-in constants can be overwritten by a <code>groopsDefaults.xml</code> file\nin the working directory or by explicitly passing the file as an argument at execution:\n<pre>\n  groops --settings &lt;groopsDefaults.xml> &lt;config.xml>\n</pre></p><p>It might also be useful to adjust the default values in the schema file used by the <a class=\"groops-ref\" href=\"general.gui.html\">GUI</a>:\n<pre>\n  groops --settings &lt;groopsDefaults.xml> --xsd &lt;groops.xsd>\n</pre></p><p>Example file:\n<pre>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;groops>\n  &lt;LIGHT_VELOCITY>299792458&lt;/LIGHT_VELOCITY>\n  &lt;DEFAULT_GM>3.986004415e+14&lt;/DEFAULT_GM>\n  &lt;DEFAULT_R>6378136.3&lt;/DEFAULT_R>\n  &lt;GRS80_a>6378137.0&lt;/GRS80_a>\n  &lt;GRS80_f>298.2572221010&lt;/GRS80_f>\n  &lt;GRAVITATIONALCONSTANT>6.6730e-11&lt;/GRAVITATIONALCONSTANT>\n  &lt;R_Earth>6.37813630000000e+06&lt;/R_Earth>\n  &lt;R_Moon>1.73800000000000e+06&lt;/R_Moon>\n  &lt;GM_Earth>3.98600441500000e+14&lt;/GM_Earth>\n  &lt;GM_Sun>1.32712442076000e+20&lt;/GM_Sun>\n  &lt;GM_Moon>4.90280105600000e+12&lt;/GM_Moon>\n  &lt;GM_MERCURY>2.20320808280762e+13&lt;/GM_MERCURY>\n  &lt;GM_VENUS>3.24858603864143e+14&lt;/GM_VENUS>\n  &lt;GM_MARS>4.28283149222192e+13&lt;/GM_MARS>\n  &lt;GM_JUPITER>1.26712769822770e+17&lt;/GM_JUPITER>\n  &lt;GM_SATURN>3.79406266494906e+16&lt;/GM_SATURN>\n  &lt;TIME_EPSILON>1.0e-05&lt;/TIME_EPSILON>\n  &lt;DELTA_TAI_GPS>19&lt;/DELTA_TAI_GPS>\n  &lt;DELTA_TT_GPS>51.184&lt;/DELTA_TT_GPS>\n  &lt;J2000>51544.5&lt;/J2000>\n  &lt;leapSecond>\n    &lt;MJD>57754&lt;/MJD>\n    &lt;DELTA_UTC_GPS>-18&lt;/DELTA_UTC_GPS>\n  &lt;/leapSecond>\n  &lt;leapSecond>\n    &lt;MJD>57204&lt;/MJD>\n    &lt;DELTA_UTC_GPS>-17&lt;/DELTA_UTC_GPS>\n  &lt;/leapSecond>\n  &lt;leapSecond>\n    &lt;MJD>56109&lt;/MJD>\n    &lt;DELTA_UTC_GPS>-16&lt;/DELTA_UTC_GPS>\n  &lt;/leapSecond></p><p>  ...</p><p>  &lt;leapSecond>\n    &lt;MJD>41317&lt;/MJD>\n    &lt;DELTA_UTC_GPS>9&lt;/DELTA_UTC_GPS>\n  &lt;/leapSecond>\n  &lt;leapSecond>\n    &lt;MJD>0&lt;/MJD>\n    &lt;DELTA_UTC_GPS>10&lt;/DELTA_UTC_GPS>\n  &lt;/leapSecond>\n&lt;/groops>\n</pre>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.fileFormat.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - File Formats</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.fileFormat\">File formats</h1><p>\nAll GROOPS files are written either in XML, JSON, binary, or ASCII format depending on the filename extension.\n<ul>\n\n<li><code>.xml</code>: XML format\n</li><li>\n<code>.json</code>: JSON format\n</li><li>\n<code>.dat</code>: binary format\n</li><li>\n<code>.txt</code> and all other extensions: ASCII format\n</li></ul>\n</p><p>With an additional extension of '<code>.gz</code>' files are directly compressed and uncompressed. It is also possible to directly uncompress and read (but not write) <a href=\"https://en.wikipedia.org/wiki/Compress\">Unix compress</a>'d files ('<code>.Z</code>').</p><p>Comments are allowed in ASCII files and all the text starting from the character '<code>#</code>' to the end of the line is ignored.</p><p>The program <a class=\"groops-program\" href=\"FileConvert.html\">FileConvert</a> can be used to convert between the different formats. This program is also useful to get\nsome general information of files in binary format.</p><p>The following special file types are used in GROOPS:\n</p>\n<p><ul>\n<li><a href=\"fileFormat_admittance.html\">Admittance</a></li>\n<li><a href=\"fileFormat_arcList.html\">ArcList</a></li>\n<li><a href=\"fileFormat_doodsonEarthOrientationParameter.html\">DoodsonEarthOrientationParameter</a></li>\n<li><a href=\"fileFormat_doodsonHarmonic.html\">DoodsonHarmonic</a></li>\n<li><a href=\"fileFormat_earthOrientationParameter.html\">EarthOrientationParameter</a></li>\n<li><a href=\"fileFormat_earthTide.html\">EarthTide</a></li>\n<li><a href=\"fileFormat_ephemerides.html\">Ephemerides</a></li>\n<li><a href=\"fileFormat_gnssAntennaDefinition.html\">GnssAntennaDefinition</a></li>\n<li><a href=\"fileFormat_gnssReceiverDefinition.html\">GnssReceiverDefinition</a></li>\n<li><a href=\"fileFormat_gnssSignalBias.html\">GnssSignalBias</a></li>\n<li><a href=\"fileFormat_griddedData.html\">GriddedData</a></li>\n<li><a href=\"fileFormat_griddedDataTimeSeries.html\">GriddedDataTimeSeries</a></li>\n<li><a href=\"fileFormat_instrument.html\">Instrument</a></li>\n<li><a href=\"fileFormat_matrix.html\">Matrix</a></li>\n<li><a href=\"fileFormat_meanPolarMotion.html\">MeanPolarMotion</a></li>\n<li><a href=\"fileFormat_normalEquation.html\">NormalEquation</a></li>\n<li><a href=\"fileFormat_oceanPoleTide.html\">OceanPoleTide</a></li>\n<li><a href=\"fileFormat_parameterName.html\">ParameterName</a></li>\n<li><a href=\"fileFormat_platform.html\">Platform</a></li>\n<li><a href=\"fileFormat_polygon.html\">Polygon</a></li>\n<li><a href=\"fileFormat_potentialCoefficients.html\">PotentialCoefficients</a></li>\n<li><a href=\"fileFormat_satelliteModel.html\">SatelliteModel</a></li>\n<li><a href=\"fileFormat_stringList.html\">StringList</a></li>\n<li><a href=\"fileFormat_stringTable.html\">StringTable</a></li>\n<li><a href=\"fileFormat_tideGeneratingPotential.html\">TideGeneratingPotential</a></li>\n<li><a href=\"fileFormat_timeSplinesCovariance.html\">TimeSplinesCovariance</a></li>\n<li><a href=\"fileFormat_timeSplinesGravityField.html\">TimeSplinesGravityField</a></li>\n<li><a href=\"fileFormat_variationalEquation.html\">VariationalEquation</a></li>\n</ul></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.gui.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Graphical User Interface (GUI)</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.gui\">Graphical User Interface (GUI)</h1><p></p><p>The graphical user interface program <code>groopsGui</code> enables the convenient creation of GROOPS config files.\nIt uses the <a href=\"https://qt.io\">Qt5 framework</a> for cross-platform support.</p><p><figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/gui_overview.png\" alt=\"gui_overview\"><figcaption class=\"center\">Figure: Overview of the GUI (components mentioned below marked in red)</figcaption></figure></p><p><h2>Settings and first-time setup</h2><p></p><p>The GUI depends on an XSD schema file containing the complete formal (computer readable) description of a GROOPS config file.\nThis schema file can be created with the command:\n<pre>\n  groops --xsd &lt;groopsDir>/groops.xsd\n</pre>\nAt least one schema file has to be set via\nthe menu <code>Settings - Default Paths and Files</code>. Setting more than one schema files enables the <em>schema selector</em> in the toolbar.\nThe selected schema will be used when (re-)opening or creating a config file.\nThis feature is useful when working with different versions of GROOPS at the same time.</p><p>It is possible to set a <em>template file</em> via the menu <code>Settings - Default Paths and Files</code>. This can be any GROOPS config file.\nWhenever a new config file is created via the GUI, all global elements and programs defined in the template file are automatically created in the new config file.\nIt is highly recommended to create a template file containing at least the global element <code>groopsDataDir</code> of type <code>filename</code>.\nThis element is used as a <a class=\"groops-ref\" href=\"general.parser.html\">variable</a> in most default file paths throughout many GROOPS programs.\nThus, setting the path to the base directory containing all GROOPS data once in the template file, for example as\n<strong class=\"groops-config-element\">groopsDataDir</strong>=<code>/home/&lt;user>/groops/data</code>, is the most convenient way to handle default paths in GROOPS.\nThe template file can also contain other often-used global elements, for example <code>tmpDir</code> or  <code>timeStart</code> and  <code>timeEnd</code>.</p><p>A <em>working directory</em> can be set via <code>Settings - Default Paths and Files</code>.\nThis directory is used as the default directory in the save dialog of new config files.</p><p>The GUI offers the option to open the GROOPS documentation for a selected program. To use this feature,\nthe GROOPS documentation must be generated (if not already present) with the command:\n<pre>\n  groops --doc &lt;groopsDir>/docs/\n</pre>\nIn the menu <code>Settings - Default Paths and Files</code> the path to the HTML version of the documentation must be set (i.e. <code>&lt;groopsDir>/docs/html</code>).\nSelecting any program and pressing <code>F1</code> opens the documentation for this program in an external browser.\nPressing <code>F1</code> without having any program selected opens the main page of the GROOPS documentation.</p><p>Executing a config file from the GUI requires the setup of a run command in the menu <code>Settings - Commands</code>.\nIt is recommended for this command to open a new terminal in which GROOPS is executed with the config file given as an argument.\nThe placeholders <code>%w</code> and <code>%f</code> are replaced by the directory and file name of the selected config file, respectively.\nMultiple commands can be set up, with the option to choose one of them in the run dialog.</p><p>Example commands:\n<ul>\n\n\t<li>Windows: <code>cd /d %w && groops.exe %f</code>\n\t</li><li>\nLinux (KDE): <code>konsole --workdir %w -e bash -ic \"groops %f; bash\"</code>\n\t</li><li>\nLinux (GNOME): <code>gnome-terminal --working-directory=%w -x bash -ic \"groops %f; bash\"</code>\n\t</li><li>\nWindows, MPI with 4 processes: <code>cd /d %w && mpiexec -n 4 groopsMPI.exe %f</code>\n\t</li><li>\nLinux (KDE), MPI with 4 processes: <code>konsole --workdir %w -e bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"</code>\n\t</li><li>\nLinux (GNOME), MPI with 4 processes: <code>gnome-terminal --working-directory=%w -x bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"</code>\n</li></ul>\n</p><p><h2>Basic features</h2><p></p><p>Most basic features used to manipulate a config element are accessible via the context menu,\nfor example attributing <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">loops and conditions</a> or setting an element global.\nGlobal elements automatically appear in the dropdown value list of config elements of the same type.\nSelecting a global element from the dropdown list as a value links this config element to the global element.\nIn case the global element is removed, all linked elements' values are replaced by the value of the deleted global element.</p><p>The sidebar features three widgets:\n<ul>\n\n\t<li><code>Open Files</code>: An overview of all open config files (select to change current tree)\n\t</li><li>\n<code>Program List</code>: A list of all programs defined in the schema of the active tree (filterable, supports drag and drop to tree, double click appends program)\n\t</li><li>\n<code>Undo Stack</code>: Tracks all changes in a config file (select to change state of tree)\n</li></ul>\n</p><p>In case the names of programs or config elements change over time, the GUI offers a rename feature to update outdated config files.\nThe changes must be documented in the schema using GROOPS' rename feature. Affected elements will be marked with an icon and\nthe context menu item <code>Update name</code> will be available to change the element to the new name defined in the schema.</p><p><h2>Additional keyboard shortcuts</h2><p></p><p><ul>\n\n\t<li>Tree navigation:\n\t<ul>\n\n\t\t</li><li>\n<code>Enter</code>: Switch focus from tree to input field of selected row\n\t\t</li><li>\n<code>Escape</code>: Switch focus from input field back to tree\n\t\t</li><li>\n<code>Tab</code>: Next sibling element (or next sibling of parent if there is no next sibling, or next child otherwise)\n\t\t</li><li>\n<code>Shift+Tab</code>: Previous sibling element (or parent if there is no previous sibling)\n\t\t</li><li>\n<code>Ctrl+Tab</code>: Next tab/tree\n\t\t</li><li>\n<code>Ctrl+Shift+Tab</code>: Previous tab/tree\n\t\t</li><li>\n<code>Ctrl+Space</code>: Interact with the element (e.g. filename/program: open dialog; time: switch focus between input fields)\n\t\t</li><li>\n<code>Ctrl+Up/Down</code>: Next/previous sibling element\n\t\t</li><li>\n<code>Ctrl+Left/Right</code>: Fold/expand (complex) element\n\t</li></ul>\n\n\t<li>Tree manipulation:\n\t<ul>\n\n\t\t</li><li>\n<code>Ctrl+Shift+Up/Down</code>: Move unbounded list element (e.g. program, layer) up/down\n\t</li></ul>\n\n\t<li>Drag and Drop of tabs to other programs (i.e. text editors) or other GUI windows:\n\t<ul>\n\n\t\t</li><li>\n<code>Drag</code>: Copy tab (= keep in source window)\n\t\t</li><li>\n<code>Shift+Drag</code>: Move tab (= remove from source window)\n\t</li></ul>\n\n\t<li>Drag and Drop GROOPS config file(s) into GUI:\n\t<ul>\n\n\t\t</li><li>\n<code>Drag</code>: Open file(s) in new tab(s)\n\t\t</li><li>\n<code>Shift+Drag</code>: Open file in current tab (replaces current tab, only works with a single file)\n\t</li></ul>\n\n</ul>\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.loopsAndConditions.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Loops and conditions</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.loopsAndConditions\">Loops and conditions</h1><p>\nThe program flow within a config file can be controlled by the classes <a class=\"groops-class\" href=\"loopType.html\">loop</a>\nand <a class=\"groops-class\" href=\"conditionType.html\">condition</a>. The easiest way to access these classes is with the programs\n<a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> and <a class=\"groops-program\" href=\"IfPrograms.html\">IfPrograms</a>.</p><p>The programs defined in <a class=\"groops-program\" href=\"IfPrograms.html\">IfPrograms</a> are only executed if the defined\n<a class=\"groops-class\" href=\"conditionType.html\">condition</a> is met. A typical example is to check whether a file that\nshould have been created in previous programs actually exists. Further options are string comparisons and\nchecking the result of a numerical expression or the return value of an external command.</p><p>With <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> it is possible to repeat the programs defined inside within a loop.\nThe class <a class=\"groops-class\" href=\"loopType.html\">loop</a> creates a sequence to loop over and defines <a class=\"groops-ref\" href=\"general.parser.html\">variables</a>\nthat contain the index and element for the current iteration.</p><p>The <a class=\"groops-class\" href=\"loopType.html\">loop</a> and <a class=\"groops-class\" href=\"conditionType.html\">condition</a> can also be attributed to single\nconfig elements (including programs). Config elements with an assigned loop are repeated, with the loop variables\nbeing evaluated for each element. If a <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is attributed to a config element\nin addition to a loop, each element within the loop is only created if the condition is met. Conditions can also\nbe attributed to optional elements without an associated loop.\nIf the condition is not met, the optional element will be treated as if it was not provided.</p><p>Example: A program needs all files in a download directory as input.\nAll the <strong class=\"groops-config-element\">inputfile</strong>s can be selected manually of course, but it is much easier to assign\na loop variable with <strong class=\"groops-config-element\">inputfile</strong>=<code>{loopFile}</code> and attribute a\n<a class=\"groops-class\" href=\"loopType.html#directoryListing\">loop:directoryListing</a>.\nThe loop lists the content of the download directory and assigns each file name to the\n<strong class=\"groops-config-element\">variableLoopFile</strong>=<code>loopFile</code>.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.parallelization.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Parallelization</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.parallelization\">Parallelization</h1><p>\nIf GROOPS is compiled with the\n<a href=\"https://en.wikipedia.org/wiki/Message_Passing_Interface\">Message Passing Interface</a> (MPI),\nmost GROOPS <a class=\"groops-ref\" href=\"programType.html\">programs</a> can be run in parallel on multiple processor cores.\nProcessing on computer clusters with distributed memory is also supported.</p><p>Many loops are parallelized by computing each loop step at a different core.\nUsually the first node distributes the work load, assigns loop steps to different cores,\nand is not participating on the actual loop computation. This means running\nGROOPS with only two nodes has no advantages in almost all cases.\nNon-parallel parts and <a class=\"groops-ref\" href=\"programType.html\">programs</a> without parallel support\nare executed at the first node only.</p><p>Large systems of <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equations</a>, which are divided into blocks,\nare distributed over the nodes to reduce the memory consumption on each single node.</p><p>As all nodes may read and write files (at least reading the <a class=\"groops-ref\" href=\"general.configFiles.html\">config files</a>)\nthe required part of the file system must be available on all participating computers.\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/general.parser.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Parser</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1 id=\"general.parser\">Parsers and variables</h1><p>\nThe XML configuration file is evaluated by two parsers. In a first step a text parser is applied.\nIn the second step mathematical expressions are resolved to a number.\nVariables (see section <a class=\"groops-ref\" href=\"general.configFiles.html#variables\">variables</a>) can be referenced via their\nname directly for the expression parser or in the form <code>{name}</code> for the text parser.</p><p><h2 id=\"expression\">Mathematical expression parser</h2><p>\nIn all input fields that accept numbers (int, uint, double, angle, time) numerical\nexpressions are also allowed. Declared variables can be accessed via their name. The following\noperations and functions are defined:\n<ul>\n\n<li>Constants:    <code>pi()</code>, <code>rho()=180/pi()</code>, <code>nan()</code>, <code>c()</code>: light velocity,\n                    <code>G()</code>: gravitational constant, <code>GM()</code>: gravitational constant of the Earth, <code>R()</code>: reference radius of the Earth\n</li><li>\nMathematical: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>^</code>\n</li><li>\nComparison:   <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&lt;=</code>, <code>></code>, <code>>=</code>, result is 1 or 0\n</li><li>\nLogical:      not <code>!</code>, and <code>&&</code>, <code>||</code>, or <code>isnan(x)</code>, result is 1 or 0\n</li><li>\nFunctions:    <code>sqrt(x)</code>, <code>exp(x)</code>,\n                    <code>sin(x)</code>,  <code>cos(x)</code>, <code>tan(x)</code>,\n                    <code>asin(x)</code>,  <code>acos(x)</code>,  <code>atan(x)</code>,\n                    <code>abs(x)</code>,  <code>round(x)</code>,  <code>ceil(x)</code>,  <code>floor(x)</code>,\n                    <code>deg2rad(x)</code>, <code>rad2deg(x)</code>\n</li><li>\nFunctions with 2 arguments: <code>atan2(y,x)</code>, <code>min(x,y)</code>, <code>max(x,y)</code>, <code>mod(x,y)</code>\n</li><li>\nTime functions: <code>now()</code>: local time in MJD, <code>date2mjd(year, month, day)</code>, <code>gps2utc(mjd)</code>, <code>utc2gps(mjd)</code>, <code>dayofyear(mjd)</code>, <code>decimalyear(mjd)</code>\n</li><li>\nCondition: <code>if(c,x,y)</code>: If the first argument is true (not 0), the second argument is evaluated, otherwise the third.\n</li></ul>\n</p><p>\n<h2 id=\"text\">Text parser</h2><p>\nBefore the mathematical expression parser evaluates the expression, a simple text parser is applied.\nThe text parser is used for all input fields (also file names). It scans the text for terms like\n<code>{variable}</code> and replaces it by the text content of the <code>variable</code>.\nA literal '<code>{</code>' character must be escaped with '<code>#{</code>'.</p><p>The text parser allows regex replacements in the form <code>{text/regex/replace}</code>.\nAll matches of <code>regex</code> in the <code>text</code> are replaced by <code>replace</code>.\nPossible <code>{variables}</code> in the three parts are evaluated beforehand.\nCapturing groups <code>()</code> can be accessed by <code>$1</code>, <code>$2</code>,\n&hellip; in the replacement (<code>$0</code> is the complete match). Additional escape sequences are:\n<ul>\n\n<li><code>\\l</code> lowercase next char,\n</li><li>\n<code>\\u</code> uppercase next char,\n</li><li>\n<code>\\L</code> lowercase until <code>\\E</code>,\n</li><li>\n<code>\\U</code> uppercase until <code>\\E</code>,\n</li><li>\n<code>\\Q</code> quote (disable) pattern metacharacters until <code>\\E</code>,\n</li><li>\n<code>\\E</code> end either case modification or quoted section.\n</li></ul>\n</p><p>Examples:\n<ul>\n\n<li><code>{{variable}/test/text}</code> replaces all occurrences of <code>test</code> by <code>text</code>.\n</li><li>\n<code>{TEXT/.+/\\L$0}</code> converts text to lower case.\n</li><li>\n<code>{012345/.#{2}(.#{3}).*/$1}</code> extracts the substring at index 2 and length 3 resulting in <code>234</code>.\n      Note the escaping <code>#{</code>.\n</li></ul>\n</p><p>The text parser also evaluates terms in the form <code>{expression:format}</code> and replaces it by a formatted\noutput. In order not to get confused with the regex replacements, the '<code>/</code>' character must be escaped\nwith '<code>#/</code>' in the expression. The <code>format</code> contains the text to be written as output.\nIt can contain embedded format specifiers that are replaced by the value of the expression and formatted\nas requested (also multiple times). In the following, the resulting formatted output is given in the\nbrackets for an expression with the example value of 57493.8:\n<ul>\n\n<li><code>%i</code>: Integer [57494]\n</li><li>\n<code>%f</code>: Decimal floating point [57493.800000]\n</li><li>\n<code>%e</code>: Scientific notation [5.749380e+04]\n</li><li>\n<code>%g</code>: Use the shortest representation: <code>%e</code> or <code>%f</code> [57493.8]\n</li><li>\n<code>%c</code>: Interpret number as ASCII character\n</li><li>\n<code>%%</code>: Write a single literal <code>%</code> character\n</li></ul>\n\nThe following specifiers interpret the value of the expression as MJD (modified Julian date):\n<ul>\n\n<li><code>%y</code>: Four digit year [2016]\n</li><li>\n<code>%Y</code>: Two digit year [16]\n</li><li>\n<code>%m</code>: Month [04]\n</li><li>\n<code>%d</code>: Day of month [15]\n</li><li>\n<code>%H</code>: Hour [19]\n</li><li>\n<code>%M</code>: Minute [12]\n</li><li>\n<code>%S</code>: Second [00]\n</li><li>\n<code>%D</code>: Date (same as <code>%y-%m-%d</code>) [2016-04-15]\n</li><li>\n<code>%T</code>: Time (same as <code>%H-%M-%S</code>) [19-12-00]\n</li><li>\n<code>%W</code>: GPS week [1892]\n</li><li>\n<code>%w</code>: Day of GPS week (0..6) [5]\n</li><li>\n<code>%O</code>: Day of year (1..366)\n</li></ul>\n\nThe format can be specified further with <code>%[width][.precision]specifier</code>,\nwhere <code>[width]</code> is the minimum number of characters to be printed.\nIf the value to be printed is shorter than this number, the result is padded with blank spaces\n(or zeros if <code>[width]</code> starts with a zero).\nThe <code>[.precision]</code> defines the number of digits after the period (for <code>%g</code> the number of\nsignificant digits instead).</p><p>Example:\nTwo variables <strong class=\"groops-config-element\">time</strong>=<code>57493+19/24+12/1440</code> and <strong class=\"groops-config-element\">satellite</strong>=<code>swarm</code> are\nset in the global section. The <strong class=\"groops-config-element\">inputfile</strong>=<code>data/{time:%y}/{satellite}_{time:%D}.dat</code>\nis expanded to <code>\"data/2016/swarm_2016-04-15.dat\"</code>.</p><p>Example:\nThe variable <strong class=\"groops-config-element\">x</strong>=<code>3+5</code> is set in the global section.\nThe expression <strong class=\"groops-config-element\">number</strong>=<code>2*x</code> is evaluated by the expression parser to <code>=16</code>.\nIn contrast if we use brackets like in <strong class=\"groops-config-element\">number</strong>=<code>2*{x}</code> the expression is first evaluated\nby the text parser to <code>\"2*3+5\"</code> and the expression parser now gives the result <code>=11</code>.</p><p>\n<h2 id=\"dataVariables\">Variables for data</h2><p>\nSome programs (e.g. <a class=\"groops-program\" href=\"FunctionsCalculate.html\">FunctionsCalculate</a>, <a class=\"groops-program\" href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a>,\n<a class=\"groops-program\" href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a>, or the plot programs)\nread data (<a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>) or <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a>\nand evaluate input/output expressions for each data row.\nFor these kind of expressions additional variables are automatically defined for each data column\n(<code>X</code> stands for the data column number: $0\\ldots n$):\n<ul>\n\n<li><code>index</code>: the row number, starting with zero\n</li><li>\n<code>dataX</code>: the value itself\n</li><li>\n<code>dataXcount</code>: number of rows\n</li><li>\n<code>dataXmin</code>\n</li><li>\n<code>dataXmax</code>\n</li><li>\n<code>dataXsum</code>\n</li><li>\n<code>dataXmean</code>\n</li><li>\n<code>dataXrms</code>: root mean square\n</li><li>\n<code>dataXstd</code>: standard deviation\n</li><li>\n<code>dataXmedian</code>\n</li><li>\n<code>dataXmad</code>: median absolute deviation\n</li><li>\n<code>dataXstep</code>: the minimal difference between two neighboring data points in the column\n</li></ul>\n\nFor <a class=\"groops-file\" href=\"fileFormat_griddedData.html\">gridded data</a> input the following variables are additionally defined for each data point:\n<ul>\n\n<li><code>longitude</code> in degrees\n</li><li>\n<code>latitude</code> in degrees\n</li><li>\n<code>height</code> in meters\n</li><li>\n<code>cartesianX</code> coordinate in meters\n</li><li>\n<code>cartesianY</code> coordinate in meters\n</li><li>\n<code>cartesianZ</code> coordinate in meters\n</li><li>\n<code>area</code> of the unit sphere\n</li><li>\n<code>dataXwmean</code>: area-weighted mean\n</li><li>\n<code>dataXwrms</code>: area-weighted root mean square\n</li><li>\n<code>dataXwstd</code>: area-weighted standard deviation\n</li></ul>\n</p><p></p>\n\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gnssAntennaDefintionListType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gnssAntennaDefintionListType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gnssAntennaDefintionListType\">GnssAntennaDefintionList</h1><p>\nProvides a list of GnssAntennaDefinitions as used in <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.\n</p>\n\n<h2>New</h2><p>\nCreates a new antenna.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">pattern</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>pattern matching of observation types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">offsetX</div></div></td><td>double</td><td>[m] antenna center offset</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">offsetY</div></div></td><td>double</td><td>[m] antenna center offset</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">offsetZ</div></div></td><td>double</td><td>[m] antenna center offset</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">deltaAzimuth</div></div></td><td>angle</td><td>[degree] step size</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">deltaZenith</div></div></td><td>angle</td><td>[degree] step size</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">maxZenith</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">values</div></div></td><td>expression</td><td>[m] expression (zenith, azimuth: variables)</td></tr>\n</table>\n\n<h2>FromFile</h2><p>\nSelect all or the first antenna from an <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a>\nwhich matches the wildcards.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">onlyFirstMatch</div></div></td><td>boolean</td><td>otherwise all machting antennas included</td></tr>\n</table>\n\n<h2>FromStationInfo</h2><p>\nSelect all antennas from an <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a>\nwhich are used by a station within a defined time interval.\nWith <strong class=\"groops-config-element\">specializeAntenna</strong> an individual antenna is created for each different serial number\nusing the general type specific values from file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>only antennas used in this time interval</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td>only antennas used in this time interval</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">specializeAntenna</div></div></td><td>boolean</td><td>e.g. separate different serial numbers from stationInfo</td></tr>\n</table>\n\n<h2>Resample</h2><p>\nThe azimuth and elevation dependent antenna center variations (patterns) of all <strong class=\"groops-config-element\">antenna</strong>s\nare resampled to a new resolution.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaAzimuth</div></div></td><td>angle</td><td>[degree] step size, empty: no change</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaZenith</div></div></td><td>angle</td><td>[degree] step size, empty: no change</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxZenith</div></div></td><td>angle</td><td>[degree], empty: no change</td></tr>\n</table>\n\n<h2>Transform</h2><p>\nThis class can be used to separate general antenna patterns for different <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>s.\nIf the <strong class=\"groops-config-element\">antenna</strong>s contain only one pattern for all GPS observations on the L1 frequency (<code>*1*G**</code>),\nthe <strong class=\"groops-config-element\">patternTypes</strong>=<code>C1*G**</code> and <code>L1*G**</code> create two patterns with the <code>*1*G**</code> patterm as template.\nThe first matching pattern in the <strong class=\"groops-config-element\">antenna</strong> is used as template.\nAlso new <strong class=\"groops-config-element\">additionalPattern</strong> can be added (e.g. for <code>*5*G**</code>).\nWith <strong class=\"groops-config-element\">addExistingPatterns</strong> all already existing patterns that don't match completely to any of the above are added.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">patternTypes</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>gnssType for each pattern (first match is used)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">additionalPattern</div></div></td><td>sequence</td><td>additional new patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>pattern matching of observation types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">offsetX</div></div></td><td>double</td><td>[m] antenna center offset</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">offsetY</div></div></td><td>double</td><td>[m] antenna center offset</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">offsetZ</div></div></td><td>double</td><td>[m] antenna center offset</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">deltaAzimuth</div></div></td><td>angle</td><td>[degree] step size</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">deltaZenith</div></div></td><td>angle</td><td>[degree] step size</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">maxZenith</div></div></td><td>angle</td><td>[degree]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">values</div></div></td><td>expression</td><td>[m] expression (zenith, azimuth: variables)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">addExistingPatterns</div></div></td><td>boolean</td><td>add existing patterns that don't match completely any of the above</td></tr>\n</table>\n\n<h2>Rename</h2><p>\nReplaces parts of the descrption of <strong class=\"groops-config-element\">antenna</strong>s.\nThe star \"<code>*</code>\" left this part untouched.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>*: left this part untouched</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td>*: left this part untouched</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td>*: left this part untouched</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">comment</div></div></td><td>string</td><td>*: left this part untouched</td></tr>\n</table>\n\n<h2>SetZero</h2><p>\nThe antenna center variations (patterns) or offsets\nof all <strong class=\"groops-config-element\">antenna</strong>s are set to zero.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">patternTypes</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>only matching patterns, default: all</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">zeroOffset</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">zeroPattern</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2>RemoveCenterMean</h2><p>\nThe antenna offset and antenna variations (patterns) are inseparable parts of the\nantenna model. With <strong class=\"groops-config-element\">removeOffset</strong> an estimated offset is removed from\nall selected patterns and added to the offset. With <strong class=\"groops-config-element\">removeMean</strong> an estimated\nconstant is removed additionally as it cannot be seperated from signal biases.\nThe mean and offset are defined as discretized (<strong class=\"groops-config-element\">deltaAzimuth</strong>,\n<strong class=\"groops-config-element\">dZenith</strong>) integral of the spherical cap from zenith down to <strong class=\"groops-config-element\">maxZenith</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antenna</div></div></td><td><a href=\"gnssAntennaDefintionListType.html\">gnssAntennaDefintionList</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">patternTypes</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>only matching patterns, default: all</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">removeMean</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">removeOffset</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaAzimuth</div></div></td><td>angle</td><td>[degree] sampling of pattern to estimate center/constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">deltaZenith</div></div></td><td>angle</td><td>[degree] sampling of pattern to estimate center/constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxZenith</div></div></td><td>angle</td><td>[degree] sampling of pattern to estimate center/constant</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gnssParametrizationType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gnssParametrizationType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gnssParametrizationType\">GnssParametrization</h1><p>\nThis class defines the models and parameters of the linearized observation equations\nfor all phase and code measurements (see <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>)\n\\[\\label{gnssParametrizationType:model}\n  \\M l - \\M f(\\M x_0) = \\left.\\frac{\\partial \\M f(\\M x)}{\\partial \\M x}\\right|_{\\M x_0} \\Delta\\M x + \\M\\epsilon,\n\\]where the left side is the observation vector minus the effects computed from the a priori models.\nAfter each least squares adjustment\n(see <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">GnssProcessing:processingStep:estimate</a>)\nthe a priori parameters are updated\n\\[\\label{gnssParametrizationType:update}\n  \\M x_0 := \\M x_0 + \\Delta\\hat{\\M x}.\n\\]The vector $\\M x_0$ can be written with\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeAprioriSolution\">GnssProcessing:processingStep:writeAprioriSolution</a>.\nAny <strong class=\"groops-config-element\">outputfiles</strong> defined in the parametrizations are written with\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">GnssProcessing:processingStep:writeResults</a>.</p><p>Each parametrization (and possible constraint equations) has a <strong class=\"groops-config-element\">name</strong> which enables\nactivating/deactivating the estimation of subsets of $\\Delta\\M x$ with\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">GnssProcessing:processingStep:selectParametrizations</a>.\nThe a priori model $\\M f(\\M x_0)$ is unaffected and is always reduced.</p><p>The model for the different observation types can be described as\n\\[\\label{gnssParametrizationType:gnssFullModel}\n\\begin{split}\n  f[\\tau\\nu a]_r^s(\\M x) &= \\text{geometry}(\\M r_r^s) + \\text{clock}^s(t) + \\text{clock}_r(t) \\\\\n               &+ \\text{ionosphere}([\\tau\\nu],t,\\M r_r^s) + \\text{troposphere}(t,\\M r_r^s) \\\\\n               &+ \\text{antenna}[\\tau\\nu a]^s  + \\text{antenna}[\\tau\\nu a]_r \\\\\n               &+ \\text{bias}[\\tau\\nu a]^s + \\text{bias}[\\tau\\nu a]_r\n               + \\lambda[L\\nu] N[L\\nu a]_r^s + \\text{other}(\\ldots) + \\epsilon[\\tau\\nu a]_r^s\n\\end{split}\n\\]The notation $[\\tau\\nu a]_r^s$ describes the\nattribution to a signal type $\\tau$ (i.e., C or L), frequency $\\nu$,\nsignal attribute $a$ (e.g., C, W, Q, X), transmitting satellite $s$, and observing receiver $r$.\nIt follows the <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>,\nsee <a class=\"groops-ref\" href=\"gnssType.html\">GnssType</a>.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.\n</p>\n\n<h2 id=\"ionosphereSTEC\">IonosphereSTEC</h2><p>\nThe influence of the ionosphere is modelled by a STEC parameter (slant total electron content)\nin terms of $[TECU]$ between each transmitter and receiver at each epoch. These parameters are pre-eliminated\nfrom the observation equations before accumulating the normal equations.\nThis is similar to using the ionosphere-free linear combination as observations\nbut only one STEC parameter is needed for an arbitrary number of observation types.</p><p>The influence on the code and phase observation is modeled as\n\\[\\label{gnssParametrizationType:IonosphereSTEC:STEC}\n\\begin{split}\n\\text{ionosphere}([C\\nu], STEC) &=  \\frac{40.3}{f_{\\nu}^2}STEC + \\frac{7525\\M b^T\\M k}{f_{\\nu}^3}STEC +  \\frac{r}{f_{\\nu}^4}STEC^2 \\\\\n\\text{ionosphere}([L\\nu], STEC) &= -\\frac{40.3}{f_{\\nu}^2}STEC - \\frac{7525\\M b^T\\M k}{2f_{\\nu}^3}STEC - \\frac{r}{3f_{\\nu}^4}STEC^2 + \\text{bending}(E)STEC^2\n\\end{split}\n\\]The second order term depends on the <a class=\"groops-class\" href=\"magnetosphereType.html\">magnetosphere</a> $\\M b$\nand the direction of the signal $\\M k$.</p><p>If further information about the ionosphere is available\n(in the form of a prior model or as additional parametrizations\nsuch as <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">parametrization:ionosphereMap</a> or\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">parametrization:ionosphereVTEC</a>) the STEC\nparameters describe local and short–term scintillations. The STEC parameters are estimated\nas additions to the model and it is advised to constrain them towards zero\nwith a standard deviation of <strong class=\"groops-config-element\">sigmaSTEC</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">apply2ndOrderCorrection</div></div></td><td>boolean</td><td>apply ionospheric correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">apply3rdOrderCorrection</div></div></td><td>boolean</td><td>apply ionospheric correction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">applyBendingCorrection</div></div></td><td>boolean</td><td>apply ionospheric correction</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">magnetosphere</div></div></td><td><a href=\"magnetosphereType.html\">magnetosphere</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaSTEC</div></div></td><td>expression</td><td>expr. for sigma [TECU] for STEC constraint, variable E (elevation) available</td></tr>\n</table>\n\n<h2 id=\"ionosphereVTEC\">IonosphereVTEC</h2><p>\nThe influence of the ionosphere is modelled by a VTEC parameter (vertical total electron content)\nin terms of $[TECU]$ for every selected receiver at each epoch. Optionally, VTEC gradients in the\nNorth (x) and East (y) direction can be estimated via <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">gradient</a>.\nThe slant TEC is computed based on the VTEC and the optional North and East gradients $\\Delta V_x$ and $\\Delta V_y$\nusing the elevation-dependent Modified Single-Layer Model (MSLM) mapping function\n\\[\\label{gnssParametrizationType:IonosphereVTEC:STEC}\n  STEC = \\frac{VTEC + \\cos(A) \\Delta V_x + \\sin(A) \\Delta V_y}{\\cos z'}\n  \\qquad\\text{with}\\qquad\n  \\sin z'= \\left(\\frac{R}{R+H}\\right)\\sin\\left(\\alpha(\\pi/2-E)\\right)\n\\]inserted into eq. \\eqref{gnssParametrizationType:IonosphereSTEC:STEC},\nwhere $A$ is the azimuth angle and $E$ is the elevation angle.</p><p>The result is written as a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">times series file</a> at epochs with observations\ndepending on <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">GnssProcessing:processingStep:selectEpochs</a>.</p><p>This class provides a simplified model of the ionosphere for single receivers\nand enables the separation of the TEC and signal biases, meaning\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a> becomes estimable.\nLocal and short-term scintillations should be considered by adding loosely constrained\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">parametrization:ionosphereSTEC</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>&lt;station>:VTEC::&lt;time></code>,\n</li><li>\n<code>&lt;station>:VTECGradient.x:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>&lt;station>:VTECGradient.y:&lt;temporal>:&lt;interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileVTEC</div></div></td><td>filename</td><td>variable {station} available, columns: MJD, VTEC, north gradient, east gradient</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mapR</div></div></td><td>double</td><td>constant of MSLM mapping function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mapH</div></div></td><td>double</td><td>constant of MSLM mapping function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mapAlpha</div></div></td><td>double</td><td>constant of MSLM mapping function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gradient</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>parametrization of north and east gradients</td></tr>\n</table>\n\n<h2 id=\"ionosphereMap\">IonosphereMap</h2><p>\nApriori VTEC maps can be removed from the observations with\n<a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a>\n(e.g. from <a class=\"groops-program\" href=\"GnssIonex2GriddedDataTimeSeries.html\">GnssIonex2GriddedDataTimeSeries</a>).</p><p>The ionosphere is parametrized in terms of $[TECU]$ in a single layer sphere with\n<strong class=\"groops-config-element\">radiusIonosphericLayer</strong> as a <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">temporal</a>ly\nchanging (e.g. hourly linear splines) spherical harmonics expansion\n\\[\n  VTEC(\\lambda,\\theta,t) = \\sum_{n=0}^{n_{max}} \\sum_{m=0}^n c_{nm}(t)C_{nm}(\\lambda,\\theta)+s_{nm}(t)S_{nm}(\\lambda,\\theta)\n\\]up to <strong class=\"groops-config-element\">maxDegree</strong>=<code>15</code> in a solar-geomagentic frame defined\nby <a class=\"groops-class\" href=\"magnetosphereType.html\">magnetosphere</a>. The VTEC values are mapped to STEC values\nin the observation equations via eq. \\eqref{gnssParametrizationType:IonosphereVTEC:STEC}.</p><p>The estimated VTEC inclusive the apriori <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileGriddedDataTimeSeries</a>\ncan be written to <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">outputfileGriddedDataTimeSeries</a>\nevaluated at <a class=\"groops-class\" href=\"gridType.html\">outputGrid</a> and <a class=\"groops-class\" href=\"timeSeriesType.html\">outputTimeSeries</a>.</p><p>Local and short-term scintillations should be considered by adding constrained\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">parametrization:ionosphereSTEC</a>.\nTo account for signal biases add\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>VTEC:sphericalHarmonics.c_&lt;degree>_&lt;order>:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>VTEC:sphericalHarmonics.s_&lt;degree>_&lt;order>:&lt;temporal>:&lt;interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td>single layer VTEC [TECU]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outputGrid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">outputTimeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileGriddedDataTimeSeries</div></div></td><td>filename</td><td>single layer VTEC [TECU]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>spherical harmonics parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>temporal evolution of VTEC values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radiusIonosphericLayer</div></div></td><td>double</td><td>[m] radius of ionospheric single layer</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mapR</div></div></td><td>double</td><td>[m] constant of MSLM mapping function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mapH</div></div></td><td>double</td><td>[m] constant of MSLM mapping function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">mapAlpha</div></div></td><td>double</td><td>constant of MSLM mapping function</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">magnetosphere</div></div></td><td><a href=\"magnetosphereType.html\">magnetosphere</a></td><td></td></tr>\n</table>\n\n<h2 id=\"clocks\">Clocks</h2><p>\nClock errors are estimated epoch-wise for each <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a>.\nNo clock errors are estimated if no valid observations are available (e.g. data gaps in the observations).</p><p>If all transmitters and receivers are selected by <strong class=\"groops-config-element\">selectTransmitters</strong> and <strong class=\"groops-config-element\">selectReceivers</strong> respectively,\nthese parameters will be lineary dependent which would lead to a rank deficiency in the normal equation\nmatrix. To circumvent this issue, the estimation requires an additional zero-mean constraint added in each epoch.\nThis is realized with an additional observation equation\n\\[\n  0 = \\frac{1}{n_i + n_k} (\\sum_i \\Delta t^{s_i} + \\sum_k \\Delta t_{r_k})\n\\]summed over all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/ReceiversZeroMean</a>\nwith a standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:clock::&lt;time></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClockTransmitter</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClockReceiver</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmittersZeroMean</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceiversZeroMean</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaZeroMeanConstraint</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks</td></tr>\n</table>\n\n<h2 id=\"clocksModel\">ClocksModel</h2><p>\nThis parametrization is an alternative to <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">parametrization:clocks</a>.\nClock errors are estimated epoch-wise for each <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a>\nand, opposed to <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">parametrization:clocks</a>, are also estimated for epochs\nthat have no valid observations available (e.g. data gaps).</p><p>The clock error of an epoch can be predicted by the clock error\nof the preceding epoch and an unknown clock drift\n\\[\n  \\Delta t_{i+1} = \\Delta t_{i} + t_{drift} dt + \\epsilon_i.\n\\]This equation is applied as an additional constraint equation in each epoch\n\\[\n  0 = \\Delta t_{i+1} - \\Delta t_{i} - t_{drift} dt + \\epsilon_i.\n\\]The variance $\\sigma^2(\\epsilon)$ is estimated iteratively by variance component estimation (VCE).\nClock jumps are treated as outliers and are automatically downweighted as described in\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">GnssProcessing:processingStep:estimate</a>.</p><p>The absolute initial clock error and clock drift cannot be determined if all receiver\nand transmitter clocks are estimated together due to their linear dependency.\nThis linear dependency would lead to a rank deficiency in the normal equation matrix in the same\nmanner as described in <a class=\"groops-class\" href=\"gnssParametrizationType.html#clocks\">parametrization:clocks</a>.\nTo circumvent this issue, an additional zero-mean constraint is added in each epoch\nas observation equation\n\\[\n  0 = \\frac{1}{n_i + n_k} (\\sum_i \\Delta t^{s_i} + \\sum_k \\Delta t_{r_k})\n\\]summed over all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/ReceiversZeroMean</a>.\nThis should be a loose constraint with a relatively large standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:clock::&lt;time></code>\nand <code>&lt;station or prn>:clockDrift::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClockTransmitter</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileClockReceiver</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>clock jumps > huber*sigma0 are downweighted</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>clock jumps > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmittersZeroMean</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>use these transmitters for zero-mean constraint</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceiversZeroMean</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>use these receivers for zero-mean constraint</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaZeroMeanConstraint</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks</td></tr>\n</table>\n\n<h2 id=\"signalBiases\">SignalBiases</h2><p>\nEach code and phase observation (e.g <code>C1C</code> or <code>L2W</code>) contains a bias at transmitter/receiver level\n\\[\n  [\\tau\\nu a]_r^s(t) = \\dots + \\text{bias}[\\tau\\nu a]^s + \\text{bias}[\\tau\\nu a]_r + \\dots\n\\]This class provides the apriori model $\\M f(\\M x_0)$ of eq. \\eqref{gnssParametrizationType:model} only.</p><p>The <a class=\"groops-class\" href=\"fileFormat_gnssSignalBias.html\">inputfileSignalBiasTransmitter/Receiver</a> are read\nfor each transmitter and receiver. Those file names are interpreted as a template with\nthe variable <code>{prn}</code> or <code>{station}</code> being replaced by transmitter PRNs or receiver station names, respectively.\n(Infos regarding the variables <code>{prn}</code> and <code>{station}</code> can be found in\n<a class=\"groops-class\" href=\"gnssTransmitterGeneratorType.html\">gnssTransmitterGeneratorType</a> and\n<a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">gnssReceiverGeneratorType</a> respectively). Those files can\nbe converted with <a class=\"groops-program\" href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a>.</p><p>The estimation of the biases is complex due to different linear dependencies, which\nresult in rank deficiencies in the system of normal equations.\nFor simplification the parametrization for $\\Delta\\M x$ has been split into:\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#codeBiases\">parametrization:codeBiases</a>,\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a>, and\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ambiguities\">parametrization:ambiguities</a> (including phase biases).\nThe file handling on the other hand still remains within this class. Any prior\nvalues for the transmitter/receiver biases are read with the respective <strong class=\"groops-config-element\">inputfileSignalBiasTransmitter/Receiver</strong>.\nAll biases for a transmitter/receiver are accumulated and written to the respective <strong class=\"groops-config-element\">outputfileSignalBiasTransmitter/Receiver</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSignalBiasTransmitter</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileSignalBiasReceiver</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSignalBiasTransmitter</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSignalBiasReceiver</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n</table>\n\n<h2 id=\"ambiguities\">Ambiguities</h2><p>\nSets up an ambiguity parameter for each track and phase observation type.\n\\[\n  [L\\nu a]_r^s(t) = \\dots + \\text{bias}[L\\nu a]^s + \\text{bias}[L\\nu a]_r + \\lambda[L\\nu] N[L\\nu a]_r^s\n\\]As the phase observations contain a float bias at transmitter/receiver level, not all ambiguities\nare resolvable to integer values. The number of resolvable ambiguities can be increased with\nknown phase biases read from file via <a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.\nIn this case, <a class=\"groops-class\" href=\"platformSelectorType.html\">estimateTransmitter/ReceiverPhaseBias</a> should\nnot be used for the corresponding transmitters and receivers.</p><p>In case of GLONASS, the phase biases at receiver level differ between different frequency channels\n(frequency division multiple access, FDMA) and for each channel an extra float phase bias is estimated.\nWith <strong class=\"groops-config-element\">linearGlonassBias</strong> a linear relationship between bias and frequency channel is assumed,\nwhich reduces the number of float bias parameters and increases the number of resolvable integer ambiguities.</p><p>The integer ambiguities can be resolved and fixed in\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">GnssProcessing:processingStep:resolveAmbiguities</a>.\nResolved integer ambiguities are not estimated as unknown parameters in\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html\">gnssProcessingStepType:estimate</a> anymore\nand are removed from the system of normal equations.</p><p>The estimated phase biases can be written to files in\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>&lt;station>:phaseBias(&lt;gnssType>)::</code>,\n</li><li>\n<code>&lt;prn>:phaseBias(&lt;gnssType>)::</code>,\n</li><li>\n<code>&lt;station>.&lt;prn>:ambiguity&lt;index>of&lt;count>(&lt;GnssTypes>)::&lt;track interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimateTransmitterPhaseBias</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimateReceiverPhaseBias</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">linearGlonassBias</div></div></td><td>boolean</td><td>bias depends linear on frequency channel number</td></tr>\n</table>\n\n<h2 id=\"codeBiases\">CodeBiases</h2><p>\nEach code observation (e.g <code>C1C</code> or <code>C2W</code>) contains a bias at transmitter/receiver level\n\\[\n  [C\\nu a]_r^s(t) = \\dots + \\text{bias}[C\\nu a]^s + \\text{bias}[C\\nu a]_r + \\dots\n\\]The code biases cannot be estimated together with clock errors and ionospheric delays in an absolute sense\nas rank deficiencies will occur in the system of normal equations. Therefore, the biases are not initialized and set up\nas parameters directly but only estimable linear combinations are parametrized.</p><p>The basic idea is to set up simplified normal equations with the biases,\nclock and STEC parameters of one single receiver or transmitter,\neliminate clock and STEC parameters and perform an eigen value decomposition\nof the normal equation matrix\n\\[\n  \\M N = \\M Q \\M\\Lambda \\M Q^T.\n\\]Instead of estimating the original bias parameter $\\M x$ a transformed set $\\bar{\\M x}$\nis introduced:\n\\[\n  \\bar{\\M x} = \\M Q^T \\M x.\n\\]The new parameters corresponding to eigen values $\\lambda>0$ are estimable,\nthe others are left out (set to zero). The behavior can be controlled by explicitly setting up to two bias types\nwith <a class=\"groops-class\" href=\"gnssType.html\">typesClockDatum</a> for each transmitter to zero. These then define the ionosphere-free clock datum\nof the transmitter. The missing linear combinations,\nwhich depend on the STEC parameters, can be added with\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#tecBiases\">parametrization:tecBiases</a>.</p><p>Additional rank deficiencies may also occur when biases of transmitters and receivers are estimated together.\nThe minimum norm nullspace (also via eigen value decomposition)\nis formulated as zero constraint equations and added with a standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>In case of GLONASS the code biases at receiver level can differ between different frequency channels\n(frequency division multiple access, FDMA) and for each channel an extra code bias is estimated.\nWith <strong class=\"groops-config-element\">linearGlonassBias</strong> a linear relationship between bias and frequency channel is assumed,\nwhich reduces the number of bias parameters.</p><p>The estimated biases can be written to files in\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:codeBias0&lt;index>&lt;combi of gnssTypes>::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">linearGlonassBias</div></div></td><td>boolean</td><td>bias depends linear on frequency channel number</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">typesClockDatum</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>first two matching types define the ionosphere free transmitter clock (e.g. C1WG, C2WG)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaZeroMeanConstraint</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for null space constraint</td></tr>\n</table>\n\n<h2 id=\"tecBiases\">TecBiases</h2><p>\nEach code observation (e.g <code>C1C</code> or <code>C2W</code>) contains a bias at transmitter/receiver level\n\\[\n  [C\\nu a]_r^s(t) = \\dots + \\text{bias}[C\\nu a]^s + \\text{bias}[C\\nu a]_r + \\ldots\n\\]This parametrization represents the linear combination of signal biases\nwhich completely depend on the STEC parameters. Ignoring these bias combinations would result\nin a biased STEC estimation (all other parameters are nearly unaffected).\nTo determine this part of the signal biases\nthe <a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereSTEC\">parametrization:ionosphereSTEC</a> should be constrained.\nFurthermore, additional information about the ionosphere is required from\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereVTEC\">parametrization:ionosphereVTEC</a> or\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#ionosphereMap\">parametrization:ionosphereMap</a>.</p><p>Rank deficiencies due to the signal bias parameters may occur if biases of\ntransmitters and receivers are estimated together.\nThe minimum norm nullspace is formulated as zero constraint equations and added with\na standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The accumulated estimated result can be written to files in\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station or prn>:tecBias0&lt;index>&lt;combi of gnssTypes>::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">linearGlonassBias</div></div></td><td>boolean</td><td>phase or code biases depend linear on frequency channel number</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaZeroMeanConstraint</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for null space constraint</td></tr>\n</table>\n\n<h2 id=\"temporalBias\">TemporalBias</h2><p>\nThis parametrization resolves the issue of some phase observations suffering from time-variable biases.\nSuch a phenomenon has been found to affect GPS block IIF satellites on the L5 phase measurements\n(see Montenbruck et al. 2011, DOI: <a href=\"https://doi.org/10.1007/s10291-011-0232-x\">10.1007/s10291-011-0232-x</a>).</p><p>For these time-variable biases an appropriate temporal representation has to be defined in\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.\nFor example, time-variable biases for GPS block IIF L5 phase observations (<a class=\"groops-class\" href=\"gnssType.html\">type</a>=<code>L5*G</code>)\ncan be represented by a cubic spline with a nodal distance of one hour.</p><p>The result is written as a <a class=\"groops-file\" href=\"fileFormat_instrument.html\">times series file</a> at the processing sampling\nor the sampling set by <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">GnssProcessing:processingStep:selectEpochs</a>).</p><p>This parametrization should be set up in addition to the constant\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#signalBiases\">parametrization:signalBiases</a>.\nDepending on the temporal representation a temporal zero-mean constraint is needed\nto separate this parametrization from the constant component. The constraint equations are added with\na standard deviation of <strong class=\"groops-config-element\">sigmaZeroMeanConstraint</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<code>&lt;prn>:signalBias.&lt;gnssType>:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileBiasTimeSeries</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileBiasTimeSeries</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaZeroMeanConstraint</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for temporal zero-mean constraint</td></tr>\n</table>\n\n<h2 id=\"staticPositions\">StaticPositions</h2><p>\nEstimates a static position for all\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a> in the terrestrial frame.</p><p>No-net constraints can be applied for a subset of stations,\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectNoNetReceivers</a>, with a\nstandard deviation of <strong class=\"groops-config-element\">noNetTranslationSigma</strong> and <strong class=\"groops-config-element\">noNetRotationSigma</strong> and <strong class=\"groops-config-element\">noNetScaleSigma</strong>.\nIf the template <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a> is provided\nthe constraints are applied relatively to these positions. Only stations with an existing position file\nare considered. Without <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a>\nthe constraints are applied towards the apriori values from\n<a class=\"groops-class\" href=\"gnssReceiverGeneratorType.html\">GnssProcessing:receiver</a>.\nAs a single corrupted station position can disturb the no-net conditions,\nthe rotation/translation parameters are estimated in a\n<a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>\nbeforehand. The computed weight matrix is used to downweight corrupted stations\nin the constraint equations.</p><p>In case you want to align to an ITRF/IGS reference frame, precise coordinates can be\ngenerated with <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>&lt;station>:position.x::</code>,\n</li><li>\n<code>&lt;station>:position.y::</code>,\n</li><li>\n<code>&lt;station>:position.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGriddedPosition</div></div></td><td>filename</td><td>delta north east up for all stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePosition</div></div></td><td>filename</td><td>variable {station} available, full estimated coordinates (in TRF)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectNoNetReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileNoNetPositions</div></div></td><td>filename</td><td>variable {station} available, precise coordinates used for no-net constraints (in TRF)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">noNetTranslationSigma</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">noNetRotationSigma</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] at Earth's surface for no-net rotation constraint on station coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">noNetScaleSigma</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>stations > huber*sigma0 are downweighted in no-net constraint</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>stations > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n</table>\n\n<h2 id=\"kinematicPositions\">KinematicPositions</h2><p>\nEstimates the epoch-wise <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfilePositions</a>\nin an Earth-fixed frame (or in case of LEO satellites in an intertial frame).</p><p>The $3\\times3$ epoch wise <a class=\"groops-class\" href=\"fileFormat_instrument.html\">outputfileCovarianceEpoch</a>\nare computed within\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#computeCovarianceMatrix\">GnssProcessing:processingStep:computeCovarianceMatrix</a></p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>&lt;station>:position.x::&lt;time></code>,\n</li><li>\n<code>&lt;station>:position.y::&lt;time></code>,\n</li><li>\n<code>&lt;station>:position.z::&lt;time></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePositions</div></div></td><td>filename</td><td>variable {station} available, estimated kinematic positions/orbit</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileCovarianceEpoch</div></div></td><td>filename</td><td>variable {station} available, 3x3 epoch covariances</td></tr>\n</table>\n\n<h2 id=\"leoDynamicOrbits\">LeoDynamicOrbits</h2><p>\nThe estimation of (reduced) dynamic orbits is formulated as variational equations.\nIt is based on <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> calculated with <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>.\nThe <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> must include at least those\nparameters that were estimated in <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>.\nAdditional <a class=\"groops-class\" href=\"timeSeriesType.html\">stochasticPulse</a> parameters can be set up to reduce orbit mismodeling.\nIf not enough epochs with observations are available (<strong class=\"groops-config-element\">minEstimableEpochsRatio</strong>) the LEO satellite is disabled.</p><p>The parameters and <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are divided into global\n<ul>\n\n<li><code>&lt;station>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;station>:stochasticPulse.x::&lt;time></code>,\n</li><li>\n<code>&lt;station>:stochasticPulse.y::&lt;time></code>,\n</li><li>\n<code>&lt;station>:stochasticPulse.z::&lt;time></code>,\n</li></ul>\n\nand arc related parameters\n<ul>\n\n<li><code>&lt;station>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;station>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;station>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;station>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;station>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;station>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;station>:arc&lt;no>.velocity0.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameters</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stochasticPulse</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>[mu/s] parametrization of stochastic pulses</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minEstimableEpochsRatio</div></div></td><td>double</td><td>drop satellites with lower ratio of estimable epochs to total epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for orbit interpolation and velocity calculation</td></tr>\n</table>\n\n<h2 id=\"transmitterDynamicOrbits\">TransmitterDynamicOrbits</h2><p>\nSame as <a class=\"groops-class\" href=\"gnssParametrizationType.html#leoDynamicOrbits\">leoDynamicOrbits</a> but\nfor transmitting GNSS satellites.\nFor more details see <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#orbitIntegration\">orbit integration</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameters</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stochasticPulse</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>[mu/s] parametrization of stochastic pulses</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minEstimableEpochsRatio</div></div></td><td>double</td><td>drop satellites with lower ratio of estimable epochs to total epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for orbit interpolation and velocity calculation</td></tr>\n</table>\n\n<h2 id=\"troposphere\">Troposphere</h2><p>\nA priori tropospheric correction is handled by a <a class=\"groops-class\" href=\"troposphereType.html\">troposphere</a> model (e.g. Vienna Mapping Functions 3).\nAdditional parameters in $[m]$ for zenith wet delay and gradients can be set up via\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">troposphereWetEstimation</a> (usually 2-hourly linear splines)\nand <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">troposphereGradientEstimation</a> (usually a daily trend).\nThese parameters can be soft-constrained using\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">parametrization:constraints</a>\nto avoid an unsolvable system of normal equations in case of data gaps.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>&lt;station>:troposphereWet:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>&lt;station>:troposphereGradient.x:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>&lt;station>:troposphereGradient.y:&lt;temporal>:&lt;interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTroposphere</div></div></td><td>filename</td><td>columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">troposphere</div></div></td><td><a href=\"troposphereType.html\">troposphere</a></td><td>a priori troposphere model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">troposphereWetEstimation</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>[m] parametrization of zenith wet delays</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">troposphereGradientEstimation</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>[degree] parametrization of north and east gradients</td></tr>\n</table>\n\n<h2 id=\"earthRotation\">EarthRotation</h2><p>\nEarth rotation parameters (ERPs) can be estimated by defining\n<strong class=\"groops-config-element\">estimatePole</strong> ($x_p$, $y_p\\, [mas]$) and <strong class=\"groops-config-element\">estimateUT1</strong> ($dUT1\\, [ms], LOD$).</p><p>Estimating length of day (LOD) with the sign according to IGS conventions requires a negative\nvalue in <a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">parametrizationTemporal:trend:timeStep</a>.</p><p>Constraints on the defined parameters can be added via\n<a class=\"groops-class\" href=\"gnssParametrizationType.html#constraints\">parametrization:constraints</a>.\nAn example would be to set up <a class=\"groops-class\" href=\"parametrizationTemporalType.html#constant\">estimateUT1:constant</a>\nso the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be\ndetermined by GNSS, a hard constraint to its a priori value can then be added.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>earth:polarMotion.xp:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:polarMotion.yp:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:UT1:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:nutation.X:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:nutation.Y:&lt;temporal>:&lt;interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileEOP</div></div></td><td>filename</td><td>EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimatePole</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>xp, yp [mas]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimateUT1</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>rotation angle [ms]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimateNutation</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>dX, dY [mas]</td></tr>\n</table>\n\n<h2 id=\"receiverAntennas\">ReceiverAntennas</h2><p>\nThis class is for parametrization the antenna for their antenna center offsets (ACO) and\nantenna center variations (ACV) by <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">antennaCenterVariations</a>.\nThe receivers to be estimated can be selected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a>.</p><p>The amount of patterns to be estimated is configurable with a list of <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a>.\nFor each added <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a> a set of parameters will be evaluated. The observations\nwill be assigned to the first <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a> that matches their own.\nE.g. having the patterns: <code>***G</code> and <code>L1*</code> would lead to all GPS observations be assigned\nto the observation equations of the first pattern. The pattern type <code>L1*</code> would then consist\nof all other GNSS L1 phase observations. <strong class=\"groops-config-element\">addNonMatchingTypes</strong> will, if activated, create automatically patterns\nfor <a class=\"groops-class\" href=\"gnssType.html\">observations</a> that are not selected within the list <a class=\"groops-class\" href=\"gnssType.html\">patternTypes</a>.\nFurthermore, it is possible to group same antenna build types from different receivers by <strong class=\"groops-config-element\">groupAntennas</strong>.\nThe grouping by same antenna build ignores antenna serial numbers.</p><p>To estimate the antenna variation parameters, a longer period of observations might be necessary\nfor accurate estimations. Hence one should use this parametrization by\naccumulating normal equations from several epochs.\nThis can be accomplished as the last steps in the <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processing steps</a>\n by adding <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">ReceiverAntennas</a>\nto current selected parameters with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">GnssProcessing:processingStep:selectParametrizations</a>\nand write the normal equation matrix with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeNormalEquations\">GnssProcessing:processingStep:writeNormalEquations</a>.\nThe written normal equations can then be accumulated with <a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a> and solved by <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>.\nFurther, one should apply constraints to the normal equations by <a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a> since the estimation\n of ACO and ACV can lead to rank deficiencies in the normal equation matrix.\nLast the solved normal equation can be parsed to a <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a>\n with the program <a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>.</p><p>As example referring to the cookbook <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a>,\none could add additionally <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">receiverAntennas</a> as parametrization.\nSince the estimations are done on a daily basis for each receiver we add an additional\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a> which\ndisables <code>parameter.receiverAntenna</code>. After all stations are processed together with all parameters, one\nadds <code>parameter.receiverAntenna</code> with <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>\n to the current selected parametrizations.\nThe last <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingStep</a> is <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeNormalEquations\">GnssProcessing:processingStep:writeNormalEquations</a>\nto write the daily normal equations including the parametrization <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">receiverAntennas</a> into files.\nThese normal equation files are then processed with the programs:</p><p><ul>\n\n  <li><a class=\"groops-program\" href=\"NormalsAccumulate.html\">NormalsAccumulate</a>: accumulates normal equations.\n  </li><li>\n<a class=\"groops-program\" href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a>: apply constraint to the normal equations.\n  </li><li>\n<a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>: solves the normal equations.\n  </li><li>\n<a class=\"groops-program\" href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a>: writes the solution into a <a class=\"groops-file\" href=\"fileFormat_gnssAntennaDefinition.html\">antenna definition file</a>\n</li></ul>\n</p><p>Note that the apriori value $\\M x_0$ for this parametrization is always zero and never updated\naccording to eq. \\eqref{gnssParametrizationType:update}.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<code>&lt;antennaName>:&lt;antennaCenterVariations>.&lt;gnssType>::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antennaCenterVariations</div></div></td><td><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></td><td>estimate antenna center variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">patternTypes</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>gnssType for each pattern (first match is used)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">addNonMatchingTypes</div></div></td><td>boolean</td><td>add patterns for additional observed gnssTypes that don't match any of the above</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">groupAntennas</div></div></td><td>boolean</td><td>common ACVs for same antenna build types (ignores antenna serial number)</td></tr>\n</table>\n\n<h2 id=\"transmitterAntennas\">TransmitterAntennas</h2><p>\nSame as <a class=\"groops-class\" href=\"gnssParametrizationType.html#receiverAntennas\">receiverAntennas</a> but\nfor transmitting antennas (GNSS satellites).</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<code>&lt;antennaName>:&lt;antennaCenterVariations>.&lt;gnssType>::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">antennaCenterVariations</div></div></td><td><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></td><td>estimate antenna center variations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">patternTypes</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>gnssType for each pattern (first match is used)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">addNonMatchingTypes</div></div></td><td>boolean</td><td>add patterns for additional observed gnssTypes that don't match any of the above</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">groupAntennas</div></div></td><td>boolean</td><td>common ACVs for same antenna build types (ignores antenna serial number)</td></tr>\n</table>\n\n<h2 id=\"constraints\">Constraints</h2><p>\nAdd a pseudo observation equation (constraint)\nfor each selected <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameters</a>\n\\[\n  b-x_0 = 1 \\cdot dx + \\epsilon,\n\\]where $b$ is the <strong class=\"groops-config-element\">bias</strong> and $x_0$ is the a priori value of the parameter\nif <strong class=\"groops-config-element\">relativeToApriori</strong> is not set.\nThe standard deviation <strong class=\"groops-config-element\">sigma</strong> is used to weight the observation equations.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter to constrain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sigma</div></div></td><td>double</td><td>sigma of the constraint (same unit as parameter)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">bias</div></div></td><td>double</td><td>constrain all selected parameters towards this value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">relativeToApriori</div></div></td><td>boolean</td><td>constrain only dx and not full x=dx+x0</td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nGroups a set of parameters. This class can be used to structure complex parametrizations\nand has no further effect itself.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"gnssParametrizationType.html\">gnssParametrization</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gnssProcessingStepType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gnssProcessingStepType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gnssProcessingStepType\">GnssProcessingStep</h1><p>\nProcessing step in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.</p><p>Processing steps enable a dynamic definition of the consecutive steps performed during any kind of GNSS processing.\nThe most common steps are <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">estimate</a>, which performs an iterative least\nsquares adjustment, and <a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">writeResults</a>, which writes all output files\ndefined in <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> and is usually the last step.\nSome steps such as <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">selectParametrizations</a>,\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">selectEpochs</a>,\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">selectNormalsBlockStructure</a>, and\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a> affect all subsequent steps.\nIn case these steps are used within a <a class=\"groops-class\" href=\"gnssProcessingStepType.html#group\">group</a> or\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">forEachReceiverSeparately</a> step,\nthey only affect the steps within this level.</p><p>For usage examples see cookbooks on <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#processing\">GNSS satellite orbit determination and network analysis</a>\nor <a class=\"groops-ref\" href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a>.\n</p>\n\n<h2 id=\"estimate\">Estimate</h2><p>\nIterative non-linear least squares adjustment.\nIn every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters.\nThe estimated parameters serve as a priori values in the next iteration and the following processing steps.\nIterates until either every single parameter update (converted to an influence in meters)\nis below a <strong class=\"groops-config-element\">convergenceThreshold</strong> or <strong class=\"groops-config-element\">maxIterationCount</strong> is reached.</p><p>With <strong class=\"groops-config-element\">computeResiduals</strong> the observation equations are computed\nagain after each update to compute the observation residuals.</p><p>The overall standard deviation of a single observation used for the weighting\nis composed of several factors\n\\[\n  \\hat{\\sigma}_i = \\hat{\\sigma}_i^{huber} \\hat{\\sigma}_{[\\tau\\nu a]}^{recv} \\sigma_{[\\tau\\nu a]}^{recv}(E,A),\n\\]where $[\\tau\\nu a]$ is the signal type, the azimuth and elevation dependent $\\sigma_{[\\tau\\nu a]}^{recv}(E,A)$ is given by\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">receiver:inputfileAccuracyDefinition</a> and the other factors are\nestimated iteratively from the residuals.</p><p>With <strong class=\"groops-config-element\">computeWeights</strong> a standardized variance $\\hat{s}_i^2$\nfor each residual $\\hat{\\epsilon}_i$ is computed\n\\[\n  \\hat{s}_i^2 = \\frac{1}{\\hat{\\sigma}_{[\\tau\\nu a]}^{recv} \\sigma_{[\\tau\\nu a]}^{recv}(E,A)}\\frac{\\hat{\\epsilon}_i^2}{r_i}\n  \\qquad\\text{with}\\qquad\n  r_i = \\left(\\M A\\left(\\M A^T\\M A\\right)^{-1}\\M A^T\\right)_{ii}\n\\]taking the redundancy $r_i$ into account. If $\\hat{s}_i$ is above a threshold <strong class=\"groops-config-element\">huber</strong>\nthe observation gets a higher standard deviation used for weighting according to\n\\[\n  \\hat{\\sigma}_i^{huber} =\n  \\left\\{ \\begin{array}{ll}\n    1                              & s < huber,\\\\\n    (\\hat{s}_i/huber)^{huberPower} & s \\ge huber\n  \\end{array} \\right.,\n\\]similar to <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>With <strong class=\"groops-config-element\">adjustSigma0</strong> individual variance factors can be computed\nfor each station and all phases of a system and each code observation <a class=\"groops-ref\" href=\"gnssType.html\">type</a>\n(e.g. for each <code>L**G</code>, <code>L**E</code>, <code>C1CG</code>, <code>C2WG</code>, <code>C1CE</code>, &hellip; )\nseparately\n\\[\n  \\hat{\\sigma}_{[\\tau\\nu a]}^{recv} = \\sqrt{\\frac{\\hat{\\M\\epsilon}^T\\M P\\hat{\\M\\epsilon}}{r}}.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeResiduals</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">adjustSigma0</div></div></td><td>boolean</td><td>adjust sigma0 by scale factor (per receiver and type)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeWeights</div></div></td><td>boolean</td><td>downweight outliers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>residuals > huber*sigma0 are downweighted</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>residuals > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">convergenceThreshold</div></div></td><td>double</td><td>[m] stop iteration once full convergence is reached</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxIterationCount</div></div></td><td>uint</td><td>maximum number of iterations</td></tr>\n</table>\n\n<h2 id=\"resolveAmbiguities\">ResolveAmbiguities</h2><p>\nPerforms a least squares adjustment like <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a>\nbut with additional integer phase ambiguity resolution.\nAfter this step all resolved ambiguities are removed from the normal equation system.\nOnly ambiguities involving <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a> are resolved.\nIf <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters/Receivers</a> is not set, all usable transmitters and/or \nreceivers are selected for ambiguity resolution.</p><p>Integer ambiguity resolution is performed based on the least squares ambiguity decorrelation adjustment\n(LAMBDA) method (Teunissen 1995, DOI <a href=\"https://doi.org/10.1007/BF00863419\">10.1007/BF00863419</a>), specifically\nthe modified algorithm (MLAMBDA) by Chang et al. (2005, DOI <a href=\"https://doi.org/10.1007/s00190-005-0004-x\">10.1007/s00190-005-0004-x</a>).\nFirst the covariance matrix of the integer ambiguity parameters is computed by eliminating all but those parameters\nfrom the full normal equation matrix and inverting it. Then, a Z-transformation is performed as described by\nChang et al. (2005) to decorrelate the ambiguity parameters without losing their integer nature.</p><p>The search process follows MLAMBDA and uses integer minimization of the weighted sum of squared residuals.\nIt is computationally infeasible to search a hyper-ellipsoid with a dimension of ten thousand or more.\nInstead, a blocked search algorithm is performed by moving a window with a length of, for example,\n<strong class=\"groops-config-element\">searchBlockSize</strong>=<code>200</code> parameters over the decorrelated ambiguities, starting from the most accurate.\nIn each step, the window is moved by half of its length and the overlapping parts are compared to each other.\nIf all fixed ambiguities in the overlap agree, the algorithm continues.\nOtherwise, both windows are combined and the search is repeated using the combined window, again comparing with the overlapping\npart of the preceding window. If not all solutions could be checked for a block after <strong class=\"groops-config-element\">maxSearchSteps</strong>,\nthe selected <strong class=\"groops-config-element\">incompleteAction</strong> is performed.\nIf the algorithm reaches ambiguities with a standard deviation higher than <strong class=\"groops-config-element\">sigmaMaxResolve</strong>,\nambiguity resolution stops and the remaining ambiguities are left as float values.\nOtherwise, all ambiguity parameters are fixed to integer values.</p><p>In contrast to an integer least squares solution over the full ambiguity vector, it is not guaranteed that the resulting solution\nis optimal in the sense of minimal variance with given covariance.\nThis trade-off is necessary to cope with large numbers of ambiguities.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAmbiguities</div></div></td><td>filename</td><td>resolved ambiguities</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>only resolve ambiguities with these participating transmitters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>only resolve ambiguities with these participating receivers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaMaxResolve</div></div></td><td>double</td><td>max. allowed std. dev. of ambiguity to resolve [cycles]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">searchBlockSize</div></div></td><td>uint</td><td>block size for blocked integer search</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxSearchSteps</div></div></td><td>uint</td><td>max. steps of integer search for each block</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">incompleteAction</div></div></td><td>choice</td><td>if not all solutions tested after maxSearchSteps</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">stop</div></div></td><td></td><td>stop searching, ambiguities remain float in this block</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">resolve</div></div></td><td></td><td>use best integer solution found so far</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">shrinkBlockSize</div></div></td><td></td><td>try again with half block size</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">throwException</div></div></td><td></td><td>stop and throw an exception</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeResiduals</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">adjustSigma0</div></div></td><td>boolean</td><td>adjust sigma0 by scale factor (per receiver and type)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeWeights</div></div></td><td>boolean</td><td>downweight outliers</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>residuals > huber*sigma0 are downweighted</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>residuals > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n</table>\n\n<h2 id=\"computeCovarianceMatrix\">ComputeCovarianceMatrix</h2><p>\nAccumulates the normal equations and computes the covariance matrix as inverse of the normal matrix.\nIt is not the full inverse but only the elements which are set in the normal matrix\n(see  <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectNormalsBlockStructure\">gnssProcessingStep:selectNormalsBlockStructure</a>)\nare computed. The matrix is passed to the <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>.\nOnly used in <a class=\"groops-class\" href=\"gnssParametrizationType.html#kinematicPositions\">parametrizations:kinematicPositions</a>\nto get the epoch-wise covariance information at the moment.\n</p>\n\n<h2 id=\"writeResults\">WriteResults</h2><p>\nIn this step all <strong class=\"groops-config-element\">outputfiles</strong> defined in <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>\nare written. It considers the settings of\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">processingStep:selectParametrizations</a>,\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">processingStep:selectEpochs</a>, and\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">processingStep:selectReceivers</a>.</p><p>It is usually the last processing step, but can also be used at other points in the\nprocessing in combination with <strong class=\"groops-config-element\">suffix</strong> to write intermediate results, for example\nbefore <a class=\"groops-class\" href=\"gnssProcessingStepType.html#resolveAmbiguities\">gnssProcessingStep:resolveAmbiguities</a> to\noutput the float solution.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">suffix</div></div></td><td>string</td><td>appended to every output file name (e.g. orbit.G01.suffix.dat)</td></tr>\n</table>\n\n<h2 id=\"writeNormalEquations\">WriteNormalEquations</h2><p>\nAccumulates the normal equations matrix and writes it.\nIf <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a>\nis set only the selected parameters are written to the normal equations\nand all other parameters are eliminated beforehand (implicitly solved).</p><p>The solution of the normals would result in $\\Delta\\M x$\n(see <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>). To write the\nappropriate apriori vector $\\M x_0$ use\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeAprioriSolution\">processingStep:writeAprioriSolution</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquations</div></div></td><td>filename</td><td>normals</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">remainingParameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of output normal equations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">constraintsOnly</div></div></td><td>boolean</td><td>write only normals of constraints without observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultNormalsBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block, empty: original block size</td></tr>\n</table>\n\n<h2 id=\"writeAprioriSolution\">WriteAprioriSolution</h2><p>\nWrites the current apriori vector $\\M x_0$\n(see <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>).\nIf <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a>\nis set only the selected parameters are written.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAprioriSolution</div></div></td><td>filename</td><td>a priori parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterNames</div></div></td><td>filename</td><td>parameter names</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">remainingParameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of output normal equations</td></tr>\n</table>\n\n<h2 id=\"writeResiduals\">WriteResiduals</h2><p>\nWrites the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">observation residuals</a> for all\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a>.\nFor each station a file is written. The file name is interpreted as\na template with the variable <code>{station}</code> being replaced by the station name.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileResiduals</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n</table>\n\n<h2 id=\"writeUsedStationList\">WriteUsedStationList</h2><p>\nWrites a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of receivers (stations) which are used in the last step and\nselected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileUsedStationList</div></div></td><td>filename</td><td>ascii file with names of used stations</td></tr>\n</table>\n\n<h2 id=\"writeUsedTransmitterList\">WriteUsedTransmitterList</h2><p>\nWrites a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of transmitters which are used in the last step and\nselected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectTransmitters</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used transmitters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileUsedTransmitterList</div></div></td><td>filename</td><td>ascii file with PRNs</td></tr>\n</table>\n\n<h2 id=\"printResidualStatistics\">PrintResidualStatistics</h2><p>\nPrint residual statistics.\n<pre>\n  areq: C1CG**: factor =  0.64, sigma0 = 1.00, count =  2748, outliers =    48 (1.75 %)\n  areq: C1WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    43 (1.56 %)\n  areq: C2WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    59 (2.15 %)\n  areq: C5XG**: factor =  0.46, sigma0 = 1.00, count =  1279, outliers =    23 (1.80 %)\n  areq: L1CG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 %)\n  areq: L1WG**: factor =  0.86, sigma0 = 1.02, count =  2748, outliers =    40 (1.46 %)\n  areq: L2WG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 %)\n  areq: L5XG**: factor =  0.86, sigma0 = 1.30, count =  1279, outliers =    14 (1.09 %)\n  areq: C1PR**: factor =  0.48, sigma0 = 1.00, count =  1713, outliers =    53 (3.09 %)\n  areq: C2PR**: factor =  0.55, sigma0 = 1.00, count =  1713, outliers =    51 (2.98 %)\n  areq: L1PR**: factor =  0.85, sigma0 = 1.09, count =  1713, outliers =    29 (1.69 %)\n  areq: L2PR**: factor =  0.85, sigma0 = 0.88, count =  1713, outliers =    29 (1.69 %)\n  areq: C1XE**: factor =  0.44, sigma0 = 1.00, count =  1264, outliers =    21 (1.66 %)\n  areq: C5XE**: factor =  0.33, sigma0 = 1.00, count =  1264, outliers =    27 (2.14 %)\n  areq: C7XE**: factor =  0.28, sigma0 = 1.00, count =  1264, outliers =    41 (3.24 %)\n  areq: L1XE**: factor =  0.82, sigma0 = 1.14, count =  1264, outliers =    15 (1.19 %)\n  areq: L5XE**: factor =  0.82, sigma0 = 0.84, count =  1264, outliers =    15 (1.19 %)\n  areq: L7XE**: factor =  0.82, sigma0 = 0.94, count =  1264, outliers =    15 (1.19 %)\n  badg: C1CG**: factor =  1.25, sigma0 = 1.00, count =  2564, outliers =    47 (1.83 %)\n  ...\n</pre>\n</p>\n\n<h2 id=\"selectParametrizations\">SelectParametrizations</h2><p>\nEnable/disable parameter groups and constraint groups for subsequent steps,\ne.g. <a class=\"groops-class\" href=\"gnssProcessingStepType.html#estimate\">processingStep:estimate</a> or\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#writeResults\">processingStep:writeResults</a>.\nThe <strong class=\"groops-config-element\">name</strong> and <strong class=\"groops-config-element\">nameConstraint</strong> of these groups\nare defined in <a class=\"groops-class\" href=\"gnssParametrizationType.html\">parametrizations</a>.\nPrior models or previously estimated parameters used as new apriori $\\M x_0$ values are unaffected\nand they are always reduced from the observations. This means all unselected parameters are kept fixed\nto their last result.</p><p>An example would be to process at a 5-minute sampling using\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectEpochs\">processingStep:selectEpochs</a>\nand then at the end to densify the clock parameters to the full 30-second observation sampling\nwhile keeping all other parameters fixed\n(<strong class=\"groops-config-element\">disable</strong>=<code>*</code>, <strong class=\"groops-config-element\">enable</strong>=<code>*.clock*</code>, <strong class=\"groops-config-element\">enable</strong>=<code>parameter.STEC</code>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">enable</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">name</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">disable</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">name</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n</table>\n\n<h2 id=\"selectEpochs\">SelectEpochs</h2><p>\nSelect epochs for subsequent steps. This step can be used to reduce the processing sampling\nwhile keeping the original observation sampling for all preprocessing steps (e.g. outlier and cycle slip detection).\nAnother example is to process at a 5-minute sampling by setting <strong class=\"groops-config-element\">nthEpoch</strong>=<code>10</code> and then\nat the end to densify only the clock parameters to the full 30-second observation sampling by\nsetting <strong class=\"groops-config-element\">nthEpoch</strong>=<code>1</code> while keeping all other parameters fixed\nwith <a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectParametrizations\">processingStep:selectParametrizations</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">nthEpoch</div></div></td><td>uint</td><td>use only every nth epoch in all subsequent processing steps</td></tr>\n</table>\n\n<h2 id=\"selectNormalsBlockStructure\">SelectNormalsBlockStructure</h2><p>\nSelect block structure of sparse normal equations for subsequent steps.</p><p>This step can be used to define the structure of the different parts of the normal equation system,\nwhich can have a major impact on computing performance and memory consumption depending on the processing setup.</p><p><figure><img class=\"figure\" style=\"width:40%;\" src=\"../figures/gnss_normals_structure.png\" alt=\"gnss_normals_structure\"><figcaption class=\"center\">Figure: Structure of normal equations in GNSS processing</figcaption></figure></p><p>The normal equation system is divided into three parts for epoch, interval, and ambiguity parameters.\nThe epoch part is subdivided further into one subpart per epoch. Each part is divided into blocks and only non-zero\nblocks are stored in memory to reduce memory consumption and to prevent unnecessary matrix computations.\n<strong class=\"groops-config-element\">defaultBlockSizeEpoch</strong>, <strong class=\"groops-config-element\">defaultBlockSizeInterval</strong>, and <strong class=\"groops-config-element\">defaultBlockSizeAmbiguity</strong> control\nthe size of the blocks within each part of the normal equations. <strong class=\"groops-config-element\">defaultBlockReceiverCount</strong> can be set to group\na number of receivers into one block within the epoch and interval parts.</p><p>If <strong class=\"groops-config-element\">keepEpochNormalsInMemory</strong>=<code>no</code> epoch blocks are eliminated after they are set up to reduce the number\nof parameters in the normal equation system. <strong class=\"groops-config-element\">defaultBlockCountReduction</strong> controls after how many epoch blocks\nan elimination step is performed. For larger processing setups or high sampling rates epoch block elimination is recommended\nas the large number of clock parameters require a lot of memory.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockSizeEpoch</div></div></td><td>uint</td><td>block size of epoch parameters, 0: one block</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockSizeInterval</div></div></td><td>uint</td><td>block size of interval parameters, 0: one block</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockSizeAmbiguity</div></div></td><td>uint</td><td>block size of ambiguity parameters, 0: one block</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockReceiverCount</div></div></td><td>uint</td><td>number of receivers to group into one block for epoch and interval</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultBlockCountReduction</div></div></td><td>uint</td><td>minimum number of blocks for epoch reduction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">keepEpochNormalsInMemory</div></div></td><td>boolean</td><td>speeds up processing but uses much more memory</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">accumulateEpochObservations</div></div></td><td>boolean</td><td>set up all observations per epoch and receiver at once</td></tr>\n</table>\n\n<h2 id=\"selectReceivers\">SelectReceivers</h2><p>\nThis step can be used to process only a subset of stations in subsequent processing steps.\nThe most common use is to start the processing with a well-distributed network of core stations as seen in\n<a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#processing\">GNSS satellite orbit determination and network analysis</a>.\nTo later process all other stations individually, use the processing step\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#forEachReceiverSeparately\">processingStep:forEachReceiverSeparately</a>\nand select all stations excluding the core stations in that step.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n</table>\n\n<h2 id=\"forEachReceiverSeparately\">ForEachReceiverSeparately</h2><p>\nPerform these processing steps for each <a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a> separately.\nAll non-receiver-related parameters parameters are disabled in these processing steps.</p><p>This step can be used for individual precise point positioning (PPP) of all stations.\nDuring <a class=\"groops-ref\" href=\"cookbook.gnssNetwork.html#processing\">GNSS satellite orbit determination and network analysis</a> this step is used after the\ninitial processing of the core network to process all other stations individually. In that case provide the same station list as\n<a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileExcludeStationList</a> in this step that was used as <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileStationList</a> in the\n<a class=\"groops-class\" href=\"gnssProcessingStepType.html#selectReceivers\">selectReceivers</a> step where the core network was selected.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectReceivers</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableReceiver</div></div></td><td>string</td><td>variable is set for each receiver</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">processingStep</div></div></td><td><a href=\"gnssProcessingStepType.html\">gnssProcessingStep</a></td><td>steps are processed consecutively</td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nPerform these processing steps. This step can be used to structure complex processing flows.\nThe <a class=\"groops-class\" href=\"gnssProcessingStepType.html\">processingStep</a>s that affect the following steps\n(those beginning with Select) only have an effect until the end of the group.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">processingStep</div></div></td><td><a href=\"gnssProcessingStepType.html\">gnssProcessingStep</a></td><td>steps are processed consecutively</td></tr>\n</table>\n\n<h2 id=\"disableTransmitterShadowEpochs\">DisableTransmitterShadowEpochs</h2><p>\nDisable transmitter epochs during eclipse.\nWith proper attitude modeling (see <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a>) this is usually not necessary.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectTransmitters</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">disableShadowEpochs</div></div></td><td>boolean</td><td>disable epochs if satellite is in Earth's/Moon's shadow</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">disablePostShadowRecoveryEpochs</div></div></td><td>boolean</td><td>disable epochs if satellite is in post-shadow recovery maneuver for GPS block IIA</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td>eclipse model used to determine if a satellite is in Earth's shadow</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gnssReceiverGeneratorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gnssReceiverGeneratorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gnssReceiverGeneratorType\">GnssReceiverGenerator</h1><p>\nDefinition and basic information of GNSS receivers.</p><p>Most of the input files are provided in GROOPS file formats at\n<a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a> (marked with <b>*</b> below).\nThese files are regularly updated.\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a><b>*</b>:\n        Antenna and receiver information, antenna reference point offsets, antenna orientations.\n        Created via <a class=\"groops-program\" href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a> or <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a><b>*</b>:\n        Antenna center offsets and variations.\n        Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a>:\n        Observed signal types (optional).\n        Created via <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a> in case you want to define which signal\n        types a receiver model can observe.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a><b>*</b>:\n        Elevation and azimuth dependent accuracy.\n        Created via <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservation</a>:\n        Converted from RINEX observation files via <a class=\"groops-program\" href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a>.\n</li></ul>\n</p><p>It is possible to limit the observation types to be used in the processing by a list of <a class=\"groops-class\" href=\"gnssType.html\">useType</a>\nand any observation types not defined within the list are ignored and discarded.\nSimilarly observations defined in the list of <a class=\"groops-class\" href=\"gnssType.html\">ignoreType</a> are ignored and discarded.\nThe codes used follow the <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>.</p><p>Each receiver goes through a <strong class=\"groops-config-element\">preprocessing</strong> step individually, where observation outliers are removed or downweighted,\ncontinuous tracks of phase observations are defined for ambiguity parametrization, cycle slips are detected, and receivers are\ndisabled if they do not fulfill certain requirements. The preprocessing step consists of an initial PPP estimation done by\n<a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a> and checks whether the position error\nof the solutions exceeds <strong class=\"groops-config-element\">codeMaxPositionDiff</strong>. If the error exceeds the threshold the receiver will be discarded.\nThe preprocessing also sets initial clock error values and removes tracks that stay below a certain elevation mask (<strong class=\"groops-config-element\">elevationTrackMinimum</strong>).</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> and <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>.\n</p>\n\n<h2 id=\"stationNetwork\">StationNetwork</h2><p>\nA network of GNSS ground stations is defined via <a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStationList</a>.\nEach line can contain more than one station. The first station in each line for which <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>\nexists and contains enough observations is used for the processing.\nAll input files except <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>,\n<a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a>, and\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAccuracyDefinition</a> are read for each station.\nThe file name is interpreted as a template with the variable <code>{station}</code> being replaced by the station name.</p><p>The effects of loading and tidal deformation on station positions can be corrected for\nvia <a class=\"groops-class\" href=\"gravityfieldType.html\">loadingDisplacement</a> and\n<a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>, respectively.\nTidal deformations typically include:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"tidesType.html#earthTide\">earthTide</a>: Earth tidal deformations (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: ocean tidal deformations\n        (e.g. fes2014b_n720, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: atmospheric tidal deformation\n        (e.g. AOD1B RL06, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#poleTide\">poleTide</a>: pole tidal deformations (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">poleOceanTide</a>: ocean pole tidal deformations (IERS conventions)\n</li></ul>\n</p><p></p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationList</div></div></td><td>filename</td><td>ascii file with station names</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxStationCount</div></div></td><td>uint</td><td>maximum number of stations to be used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>variable {station} available. station metadata (antennas, receivers, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>antenna center offsets and variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">noAntennaPatternFound</div></div></td><td>choice</td><td>what should happen if no antenna pattern is found for an observation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ignoreObservation</div></div></td><td></td><td>ignore observation if no matching pattern is found</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">useNearestFrequency</div></div></td><td></td><td>use pattern of nearest frequency if no matching pattern is found</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">throwException</div></div></td><td></td><td>throw exception if no matching pattern is found</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileReceiverDefinition</div></div></td><td>filename</td><td>observed signal types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccuracyDefinition</div></div></td><td>filename</td><td>elevation and azimuth dependent accuracy</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStationPosition</div></div></td><td>filename</td><td>variable {station} available.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">disableStationWithoutPosition</div></div></td><td>boolean</td><td>drop stations without apriori position</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileClock</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileObservations</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">loadingDisplacement</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>loading deformation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">tidalDisplacement</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td>tidal deformation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td>for tidal deformation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDeformationLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfilePotentialLoadLoveNumber</div></div></td><td>filename</td><td>if full potential is given and not only loading potential</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">useType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>only use observations that match any of these patterns</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">ignoreType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>ignore observations that match any of these patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">elevationCutOff</div></div></td><td>angle</td><td>[degree] ignore observations below cutoff</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">elevationTrackMinimum</div></div></td><td>angle</td><td>[degree] ignore tracks that never exceed minimum elevation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minObsCountPerTrack</div></div></td><td>uint</td><td>tracks with less number of epochs with observations are dropped</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minEstimableEpochsRatio</div></div></td><td>double</td><td>[0,1] drop stations with lower ratio of estimable epochs to total epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">preprocessing</div></div></td><td>sequence</td><td>settings for preprocessing of observations/stations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">printStatistics</div></div></td><td>boolean</td><td>print preprocesssing statistics for all receivers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>residuals > huber*sigma0 are downweighted</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>residuals > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">codeMaxPositionDiff</div></div></td><td>double</td><td>[m] max. allowed position error by PPP code only clock error estimation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">denoisingLambda</div></div></td><td>double</td><td>regularization parameter for total variation denoising used in cylce slip detection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">tecWindowSize</div></div></td><td>uint</td><td>(0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">tecSigmaFactor</div></div></td><td>double</td><td>factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileTrackBefore</div></div></td><td>filename</td><td>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileTrackAfter</div></div></td><td>filename</td><td>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection</td></tr>\n</table>\n\n<h2 id=\"lowEarthOrbiter\">LowEarthOrbiter</h2><p>\nA single low-Earth orbiting (LEO) satellite with an onboard GNSS receiver.\nAn apriori orbit is needed as <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nAttitude data must be provided via <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>.\nIf no attitude data is available from the satellite operator,\nthe star camera data can be simulated by using <a class=\"groops-program\" href=\"SimulateStarCamera.html\">SimulateStarCamera</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>satellite metadata (antenna, receiver, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefinition</div></div></td><td>filename</td><td>antenna center offsets and variations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">noAntennaPatternFound</div></div></td><td>choice</td><td>what should happen if no antenna pattern is found for an observation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ignoreObservation</div></div></td><td></td><td>ignore observation if no matching pattern is found</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">useNearestFrequency</div></div></td><td></td><td>use pattern of nearest frequency if no matching pattern is found</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">throwException</div></div></td><td></td><td>throw exception if no matching pattern is found</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileReceiverDefinition</div></div></td><td>filename</td><td>observed signal types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccuracyDefinition</div></div></td><td>filename</td><td>elevation and azimut dependent accuracy</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileObservations</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>approximate positions</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td>satellite attitude</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaFactorPhase</div></div></td><td>expression</td><td>PHASE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sigmaFactorCode</div></div></td><td>expression</td><td>CODE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">supportsIntegerAmbiguities</div></div></td><td>boolean</td><td>receiver tracks full cycle integer ambiguities</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">wavelengthFactor</div></div></td><td>double</td><td>factor to account for half-wavelength observations (collected by codeless squaring techniques)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">useType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>only use observations that match any of these patterns</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">ignoreType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>ignore observations that match any of these patterns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">elevationCutOff</div></div></td><td>angle</td><td>[degree] ignore observations below cutoff</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minObsCountPerTrack</div></div></td><td>uint</td><td>tracks with less number of epochs with observations are dropped</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">preprocessing</div></div></td><td>sequence</td><td>settings for preprocessing of observations/stations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">printStatistics</div></div></td><td>boolean</td><td>print preprocesssing statistics for all receivers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>residuals > huber*sigma0 are downweighted</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>residuals > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">codeMaxPositionDiff</div></div></td><td>double</td><td>[m] max. allowed position error by PPP code only clock error estimation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">denoisingLambda</div></div></td><td>double</td><td>regularization parameter for total variation denoising used in cylce slip detection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">tecWindowSize</div></div></td><td>uint</td><td>(0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">tecSigmaFactor</div></div></td><td>double</td><td>factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileTrackBefore</div></div></td><td>filename</td><td>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">outputfileTrackAfter</div></div></td><td>filename</td><td>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gnssTransmitterGeneratorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gnssTransmitterGeneratorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gnssTransmitterGeneratorType\">GnssTransmitterGenerator</h1><p>\nDefinition and basic information of GNSS transmitters.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> and <a class=\"groops-program\" href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a>.\n</p>\n\n<h2 id=\"gnss\">GNSS</h2><p>\nA list of satellite PRNs (i.e for GPS: G01, G02, G03, ...) must be provided via\n<a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileTransmitterList</a>. Satellite system codes follow the\n<a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>, see <a class=\"groops-ref\" href=\"gnssType.html\">GnssType</a>.\nAll input files except <a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a>,\nand <a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileReceiverDefinition</a> are read for each satellite.\nThe file name is interpreted as a template with the variable <code>{prn}</code> being replaced by the satellite PRN.</p><p>Metadata input files (marked with <b>*</b> below) are provided in GROOPS file formats at\n<a href=\"https://ftp.tugraz.at/pub/ITSG/groops\" target=\"_blank\">https://ftp.tugraz.at/pub/ITSG/groops</a>. These files are regularly updated.\n<ul>\n\n  <li><a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileTransmitterInfo</a><b>*</b>:\n        PRN-SVN mapping, antenna offsets and orientations.\n        Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssAntennaDefinition.html\">inputfileAntennaDefinition</a><b>*</b>:\n        Antenna center variations.\n        Created via <a class=\"groops-program\" href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a> or <a class=\"groops-program\" href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_gnssReceiverDefinition.html\">inputfileSignalDefintion</a><b>*</b>:\n        Transmitted signal types.\n        Created via <a class=\"groops-program\" href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a> in case you want to define which signal\n        types a satellite transmits.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClockFrequencyScale</a><b>*</b>:\n        Scale factor of transmitted signals due to frequency offset/clock drift.\n        Can be dreived from broadcast clocks drifts.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>: Converted via <a class=\"groops-program\" href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a> or\n        output of <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a>:\n        Rotation from body frame to CRF. Created via <a class=\"groops-program\" href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a> or converted via <a class=\"groops-program\" href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a>.\n  </li><li>\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileClock</a>:\n        Converted via <a class=\"groops-program\" href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a> or <a class=\"groops-program\" href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a> or\n        output of <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileTransmitterList</div></div></td><td>filename</td><td>ascii file with transmitter PRNs, used to loop variable {prn}</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTransmitterInfo</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAntennaDefintion</div></div></td><td>filename</td><td>phase centers and variations (ANTEX like)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">noAntennaPatternFound</div></div></td><td>choice</td><td>what should happen is no antenna pattern is found for an observation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ignoreObservation</div></div></td><td></td><td>ignore observation if no matching pattern is found</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">useNearestFrequency</div></div></td><td></td><td>use pattern of nearest frequency if no matching pattern is found</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">throwException</div></div></td><td></td><td>throw exception if no matching pattern is found</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSignalDefintion</div></div></td><td>filename</td><td>transmitted signal types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileClockFrequencyScale</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAttitude</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileClock</div></div></td><td>filename</td><td>variable {prn} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolateClock</div></div></td><td>boolean</td><td>linear interpolation of missing epochs</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for orbit interpolation and velocity calculation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gnssType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gnssType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gnssType\">GnssType</h1><p>\nA GnssType string consists of six parts (type, frequency, attribute, system, PRN, frequency number)\nrepresented by seven characters.\n<ul>\n\n<li>The first three characters (representing type, frequency, and attribute) correspond to the observation codes of the\n      <a href=\"https://files.igs.org/pub/data/format/rinex305.pdf\">RINEX 3 definition</a>.\n</li><li>\nThe satellite system character also follows the RINEX 3 definition:\n      <ul>\n\n        </li><li>\n<code>G</code> = GPS\n        </li><li>\n<code>R</code> = GLONASS\n        </li><li>\n<code>E</code> = Galileo\n        </li><li>\n<code>C</code> = BeiDou\n        </li><li>\n<code>S</code> = SBAS\n        </li><li>\n<code>J</code> = QZSS\n        </li><li>\n<code>I</code> = IRNSS\n      </li></ul>\n\n<li>PRN is a two-digit number identifying a satellite.\n</li><li>\nFrequency number is only used for GLONASS, where the range -7 to 14 is represented by letters starting with A.\n</li></ul>\n</p><p>Each part of a GnssType string can be replaced by a wildcard '<code>*</code>', enabling the use of these strings as patterns,\nfor example to select a subset of observations (e.g. <code>C**G**</code> matches all GPS code/range observations).\nTrailing wildcards are optional, meaning <code>L1*R</code> is automatically expanded to <code>L1*R***</code>.\nFor some RINEX 2 types (e.g. Galileo L5) the RINEX 3 attribute is unknown/undefined and can be replaced by <code>?</code>,\nfor example <code>L5?E01</code>.</p><p>Examples:\n<ul>\n\n<li><code>C1CG23</code> = code/range observation, L1 frequency, derived from C/A code, GPS, PRN 23\n</li><li>\n<code>L2PR05B</code> = phase observation, G2 frequency, derived from P code, GLONASS, PRN 05, frequency number -6\n</li><li>\n<code>*5*E**</code> = all observation types, E5a frequency, all attributes, Galileo, all PRNs\n</li></ul>\n\n</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gravityfieldType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gravityfieldType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gravityfieldType\">Gravityfield</h1><p>\nThis class computes functionals of the time depending gravity field,\ne.g potential, gravity anomalies or gravity gradients.</p><p>If several instances of the class are given the results are summed up.\nBefore summation every single result is multiplicated by a <strong class=\"groops-config-element\">factor</strong>.\nTo subtract a normal field like GRS80 from a potential\nto get the disturbance potential you must choose one factor by 1\nand the other by -1. To get the mean of two fields just set each factor to 0.5.</p><p>Some of the instances gives also information about the accuracy.\nThe variance of the result (sum) is computed by means of variance propagation.\n</p>\n\n<h2 id=\"potentialCoefficients\">PotentialCoefficients</h2><p>\nReads coefficients of a spherical harmonics expansion from file.\nThe potential is given by\n\\[\nV(\\lambda,\\vartheta,r) = \\frac{GM}{R}\\sum_{n=0}^\\infty \\sum_{m=0}^n \\left(\\frac{R}{r}\\right)^{n+1}\n  \\left(c_{nm} C_{nm}(\\lambda,\\vartheta) + s_{nm} S_{nm}(\\lambda,\\vartheta)\\right).\n\\]If set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The computed result\nis multiplied with <strong class=\"groops-config-element\">factor</strong>. If <strong class=\"groops-config-element\">setSigmasToZero</strong> is true\nthe variances are set to zero. This option is only important for variance propagation\nand does not change the result of the gravity field functionals.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">setSigmasToZero</div></div></td><td>boolean</td><td>set variances to zero, should be used by adding back reference fields</td></tr>\n</table>\n\n<h2>PotentialCoefficientsInterior</h2><p>\nReads coefficients of a spherical harmonics expansion (for inner space) from file.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\nIf <strong class=\"groops-config-element\">setSigmasToZero</strong> is true the variances are set to zero.\nThis option is only important for error propagation\nand does not change the result of the gravity field functionals.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePotentialCoefficients</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">setSigmasToZero</div></div></td><td>boolean</td><td>set variances to zero, should be used by adding back reference fields</td></tr>\n</table>\n\n<h2 id=\"fromParametrization\">FromParametrization</h2><p>\nReads a solution vector from file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a>\nwhich may be computed by a least squares adjustment (e.g. by <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>).\nThe coefficients of the vector are interpreted from position <strong class=\"groops-config-element\">indexStart</strong>\n(counting from zero) with help of <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.\nIf the solution file contains solution of several right hand sides you can choose\none with number <strong class=\"groops-config-element\">rightSide</strong> (counting from zero).\nYou can also read a vector from file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSigmax</a>\ncontaining the accuracies of the coefficients.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSolution</div></div></td><td>filename</td><td>solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSigmax</div></div></td><td>filename</td><td>standards deviations or covariance matrix of the solution</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">indexStart</div></div></td><td>uint</td><td>position in the solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rightSide</div></div></td><td>uint</td><td>if solution contains several right hand sides, select one</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"timeSplines\">TimeSplines</h2><p>\nRead a time variable gravity field from file\n<a class=\"groops-class\" href=\"fileFormat_timeSplinesGravityField.html\">inputfileTimeSplinesGravityfield</a>\nrepresented by a spherical harmonics expansion in the spatial domain and spline functions\nin the time domain. If set the expansion is limited in the range between\n<strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.</p><p>This file can be created for example by <a class=\"groops-program\" href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a> or\n<a class=\"groops-program\" href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a>.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTimeSplinesGravityfield</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileTimeSplinesCovariance</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"trend\">Trend</h2><p>\nThe given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is interpreted\nas trend function and the result is computed at time $t$ as follows\n\\[\nV(\\M x,t) = \\frac{t-t_0}{\\Delta t}V(\\M x),\n\\]with $t_0$ is <strong class=\"groops-config-element\">timeStart</strong> and $\\Delta t$ is <strong class=\"groops-config-element\">timeStep</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>this field is multiplicated by (time-time0)/timeStep</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>reference time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStep</div></div></td><td>time</td><td></td></tr>\n</table>\n\n<h2 id=\"oscillation\">Oscillation</h2><p>\nThe given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is interpreted\nas oscillation function and the result is computed at time $t$ as follows\n\\[\nV(\\M x,t) = \\cos(\\omega)V_{cos}(\\M x)+\\sin(\\omega)V_{sin}(\\M x),\n\\]with $\\omega=\\frac{2\\pi}{T}(t-t_0)$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfieldCos</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>multiplicated by cos(2pi/T(time-time0))</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfieldSin</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>multiplicated by sin(2pi/T(time-time0))</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time0</div></div></td><td>time</td><td>reference time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">period</div></div></td><td>time</td><td>[day]</td></tr>\n</table>\n\n<h2>InInterval</h2><p>\nA <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is only evaluated in the interval between\n<strong class=\"groops-config-element\">timeStart</strong> inclusively and <strong class=\"groops-config-element\">timeEnd</strong> exclusively.\nOutside the interval the result is zero.</p><p>This class is useful to get a time series of monthly mean GRACE gravity field solutions.\nIn each month another file of potentialCoefficients is valid.\nThis can easily be created with <a class=\"groops-class\" href=\"loopType.html\">loop</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>first point in time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeEnd</div></div></td><td>time</td><td>last point in time will be less or equal timeEnd</td></tr>\n</table>\n\n<h2 id=\"tides\">Tides</h2><p>\nTreat <a class=\"groops-class\" href=\"tidesType.html\">tides</a> as gravitational forces.\nThe tides need a realization of <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>\nto transform between the CRF and TRF and to compute rotational deformation\nfrom polar motion.\nIt also needs <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemerides</a> from Sun, moon, and planets.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">tides</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n</table>\n\n<h2 id=\"topography\">Topography</h2><p>\nThe gravity is integrated from a topographic mass distribution.\nFor each grid point in <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGridRectangular</a> a prisma with\n<strong class=\"groops-config-element\">density</strong> is assumed. The horizontal extension is computed from the grid spacing\nand the vertical extension is given by <strong class=\"groops-config-element\">radialLowerBound</strong>\nand <strong class=\"groops-config-element\">radialUpperBound</strong> above ellipsoid. All values are expressions and computed\nfor each point with given data in the grid file. The standard variables for grids\nare available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>Example: The grid file contains the orthometric height of the topography in the first\ncolumn, the geoid height in the second and the mean density of each prism in the third\ncolumn. In this case the following settings should be used:\n<ul>\n\n<li><strong class=\"groops-config-element\">radialUpperBound</strong> = <code>data0+data1</code>,\n</li><li>\n<strong class=\"groops-config-element\">radialLowerBound</strong> = <code>data1</code>,\n</li><li>\n<strong class=\"groops-config-element\">density</strong> = <code>data2</code>.\n</li></ul>\n</p><p>As the prim computation is time consuming a maximum distance around the evaluation point\ncan defined with <strong class=\"groops-config-element\">distancePrism</strong>. Afterwards a simplified radial line\n(the prism mass is concentrated to a line in the center) is used up to\na distance of <strong class=\"groops-config-element\">distanceLine</strong>. At last the prim is approximated by a point mass\nin the center up to a distance <strong class=\"groops-config-element\">distanceMax</strong> (if set). Prisms nearby the evaluation\npoint can be excluded with <strong class=\"groops-config-element\">distanceMin</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGridRectangular</div></div></td><td>filename</td><td>Digital Terrain Model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">density</div></div></td><td>expression</td><td>expression [kg/m**3]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radialUpperBound</div></div></td><td>expression</td><td>expression (variables 'height', 'data', 'L', 'B' and, 'area' are taken from the gridded data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">radialLowerBound</div></div></td><td>expression</td><td>expression (variables 'height', 'data', 'L', 'B' and, 'area' are taken from the gridded data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">distanceMin</div></div></td><td>double</td><td>[km] min. influence distance (ignore near zone)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">distancePrism</div></div></td><td>double</td><td>[km] max. distance for prism formular</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">distanceLine</div></div></td><td>double</td><td>[km] max. distance for radial integration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">distanceMax</div></div></td><td>double</td><td>[km] max. influence distance (ignore far zone)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2>EarthquakeOscillation</h2><p>\nThe given <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> is interpreted as an oscillation function\nin the gravitational potential field, caused by large earthquakes.\nThe result is computed at time $t$ as follows:\n\\[\nC_{lm}(\\M t) = \\sum_{n=0}^NC_{nlm}(1-\\cos(\\omega)\\exp(\\frac{-\\omega}{2Q_{nlm}})),\n\\]with $\\omega=\\frac{2\\pi}{T_{nlm}}(t-t_0)$. In this equation, $Q_{nlm}$ is the attenuation factor,\n$n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time in second.\n$T_{nlm}$ and $Q_{nlm}$ are computed with the elastic Earth model or observed from the long\nperiod record of superconducting gravimeter measurements after the earthquakes.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputCoefficientMatrix</div></div></td><td>filename</td><td>oscillation model parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time0</div></div></td><td>time</td><td>the time earthquake happened</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n</table>\n\n<h2>Filter</h2><p>\nConvert <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> to spherical harmonics\nand <a class=\"groops-class\" href=\"sphericalHarmonicsFilterType.html\">filter</a> the coefficients.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">filter</div></div></td><td><a href=\"sphericalHarmonicsFilterType.html\">sphericalHarmonicsFilter</a></td><td></td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nGroups a set of <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a> and has no further effect itself.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/gridType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - gridType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"gridType\">Grid</h1><p>\nThis class generates a set of grid points. In a first step, the grid\nis always generated globally, with <a class=\"groops-class\" href=\"borderType.html\">border</a> a regional\nsubset of points can be extracted from the global grid. The parameters\n<strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> define the shape of the ellipsoid\non which the grid is generated. In case <strong class=\"groops-config-element\">inverseFlattening</strong> is\nchosen as zero, a sphere is used. With <strong class=\"groops-config-element\">height</strong> the distance of\nthe points above the ellipsoid can be defined. In addition to the location\nof the points, weights are assigned to each of the points. These weights\ncan be regarded as the surface element associated with each grid point.\n</p>\n\n<h2>Geograph</h2><p>\nThe geographical grid is an equal-angular point distribution with points\nlocated along meridians and along circles of latitude. <strong class=\"groops-config-element\">deltaLambda</strong>\ndenotes the angular difference between adjacent points along meridians and\n<strong class=\"groops-config-element\">deltaPhi</strong> describes the angular difference between adjacent points\nalong circles of latitude. The point setting results as follows:\n\\[\n\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 0\\leq i< \\frac{360^\\circ}{\\Delta\\lambda},\n\\]\\[\n\\varphi_j=-90^\\circ+\\frac{\\Delta\\varphi}{2}+j\\cdot\\Delta\\varphi\\qquad\\mbox{with}\\qquad 0\\leq j<\\frac{180^\\circ}{\\Delta\\varphi}.\n\\]The number of grid points can be determined by\n\\[\nI=\\frac{360^\\circ}{\\Delta\\lambda}\\cdot\\frac{180^\\circ}{\\Delta\\varphi}.\n\\]The weights are calculated according to\n\\[\nw_i=\\int\\limits_{\\lambda_i-\\frac{\\Delta\\lambda}{2}}^{\\lambda_i+\\frac{\\Delta\\lambda}{2}}\\int\\limits_{\\vartheta_i-\\frac{\\Delta\\vartheta}{2}}^{\\vartheta_i+\\frac{\\Delta\\vartheta}{2}}=2\\cdot\\Delta\\lambda\\sin(\\Delta\\vartheta)\\sin(\\vartheta_i).\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">deltaLambda</div></div></td><td>angle</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">deltaPhi</div></div></td><td>angle</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>ellipsoidal height expression (variables 'height', 'L', 'B')</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>TriangleVertex</h2><p>\nThe zeroth level of densification\ncoincides with the 12 icosahedron vertices, as displayed in the upper left part\nof Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a>. Then, depending on the envisaged densification,\neach triangle edge is divided into $n$ parts, illustrated in the upper right\npart of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a>. The new nodes on the edges are then connected\nby arcs of great circles parallel to the triangle edges. The intersections of\neach three corresponding parallel lines become nodes of the densified grid as well.\nAs in case of a spherical triangle those three connecting lines do not exactly\nintersect in one point, the center of the resulting triangle is used as location\nfor the new node (lower left part of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a>). The lower right\nside of Fig. <a href=\"fig.html#triangle_grid\">fig:triangle_grid</a> finally shows the densified triangle vertex\ngrid for a level of $n=3$. The number of grid points in dependence of the chosen\nlevel of densification can be calculated by\n\\[\\label{eq:numberVertex}\nI=10\\cdot(n+1)^2+2.\n\\]\n<figure><img class=\"figure\" style=\"width:60%;\" src=\"../figures/icogrid.png\" alt=\"icogrid\"><figcaption class=\"center\">Figure: TriangleVertex grid.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">level</div></div></td><td>uint</td><td>division of icosahedron, point count = 10*(n+1)**2+2</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>TriangleCenter</h2><p>\nThe points of the zeroth level are located at the centers of the icosahedron triangles.\nTo achieve a finer grid, each of the triangles is divided into four smaller triangles by\nconnecting the midpoints of the triangle edges. The refined grid points are again located\nat the center of the triangles. Subsequently, the triangles can be further densified up to\nthe desired level of densification $n$, which is defined by <strong class=\"groops-config-element\">level</strong>.</p><p>The number of global grid points for a certain level can be determined by\n\\[\\label{eq:numberCenter}\nI=20\\cdot 4^n.\n\\]Thus the quantity of grid points depends exponentially on the level $n$, as with\nevery additional level the number of grid points quadruplicates.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">level</div></div></td><td>uint</td><td>division of icosahedron, point count = 5*4**(n+1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>Gauss</h2><p>\n The grid features equiangular spacing along circles of latitude with\n <strong class=\"groops-config-element\">parallelsCount</strong> defining the number $L$ of the parallels.\n\\[\n\\Delta\\lambda=\\frac{\\pi}{L}\\qquad\\Rightarrow\\qquad\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 0\\leq i< 2L.\n\\]Along the meridians the points are located at $L$ parallels at\nthe $L$ zeros $\\vartheta_j$ of the Legendre polynomial of degree $L$,\n\\[\nP_L(\\cos\\vartheta_j)=0.\n\\]Consequently, the number of grid points sums up to\n\\[\nI=2\\cdot L^2.\n\\]The weights can be calculated according to\n\\[\nw_i(L)=\\Delta\\lambda\\frac{2}{(1-t_i^2)(P'_{L}(\\cos(\\vartheta _i)))^2},\\label{weights}\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">parallelsCount</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>Reuter</h2><p>\nThe Reuter grid features equi-distant spacing along the meridians determined\nby the control parameter $\\gamma$ according to\n\\[\n\\Delta\\vartheta=\\frac{\\pi}{\\gamma}\\qquad\\Rightarrow\\vartheta_j=j\\Delta\\vartheta,\\qquad\\mbox{with}\\qquad 1\\leq j\\leq \\gamma-1.\n\\]Thus $\\gamma+1$ denotes the number of points per meridian, as the two poles\nare included in the point distribution as well. Along the circles of latitude,\nthe number of grid points decreases with increasing latitude in order to achieve\nan evenly distributed point pattern. This number is chosen, so that the points\nalong each circle of latitude have the same spherical distance as two adjacent\nlatitudes. The resulting relationship is given by\n\\[\\label{eq:sphericalDistance}\n\\Delta\\vartheta=\\arccos\\left( \\cos^2\\vartheta_j+\\sin^2\\vartheta_j\\cos\\Delta\\lambda_j\\right).\n\\]The left hand side of this equation is the spherical distance between adjacent\nlatitudes, the right hand side stands for the spherical distance between two points\nwith the same polar distance $\\vartheta_j$ and a longitudinal difference of\n$\\Delta\\lambda_i$. This longitudinal distance can be adjusted depending on\n$\\vartheta_j$ to fulfill Eq. \\eqref{eq:sphericalDistance}. The resulting\nformula for $\\Delta\\lambda_i$ is\n\\[\\label{eq:deltaLambdai}\n\\Delta\\lambda_j=\\arccos\\left( \\frac{\\sin\\Delta\\vartheta -\\cos^2\\vartheta_j}{\\sin^2\\vartheta_j}\\right).\n\\]The number of points $\\gamma_j$ for each circle of latitude can then be determined by\n\\[\\label{eq:gammai}\n\\gamma_j=\\left[ \\frac{2\\pi}{\\Delta\\lambda_j}\\right] .\n\\]Here the Gauss bracket $[x]$ specifies the largest integer equal to or less than $x$.\nThe longitudes are subsequently determined by\n\\[\n\\lambda_{ij}=\\frac{\\Delta\\lambda_j}{2}+i\\cdot(2\\pi/\\gamma_j),\\qquad\\mbox{with}\\qquad 0\\leq i< \\gamma_j.\n\\]The number of grid points can be estimated by\n\\[\\label{eq:numberReuter}\nI=\\leq 2+\\frac{4}{\\pi}\\gamma^2,\n\\]The $\\leq$ results from the fact that the $\\gamma_j$ are restricted to integer values.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">gamma</div></div></td><td>uint</td><td>number of parallels</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>ellipsoidal height</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>Corput</h2><p>\nThis kind of grid distributes an arbitrarily chosen number of $I$ points\n(defined by <strong class=\"groops-config-element\">globalPointsCount</strong>) following a recursive, quasi random sequence.\nIn longitudinal direction the pattern follows\n\\[\n\\Delta\\lambda=\\frac{2\\pi}{I}\\qquad\\Rightarrow\\qquad\\frac{\\Delta\\lambda}{2}+\\lambda_i=i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 1\\leq i\\leq I.\n\\]This implies that every grid point features a unique longitude, with equi-angular\nlongitudinal differences.</p><p>The polar distance in the form $t_i=\\cos\\vartheta_i$ for each point is determined\nby the following recursive sequence:\n<ul>\n\n<li>Starting from an interval $t\\in[-1,1]$.\n</li><li>\nIf $I=1$, then the midpoint of the interval is returned as result of\nthe sequence, and the sequence is terminated.\n</li><li>\nIf the number of points is uneven, the  midpoint is included into the list of $t_i$.\n</li><li>\nSubsequently, the interval is bisected into an upper and lower half,\n       and the sequence is called for both halves.\n</li><li>\n$t$ from upper and lower half are alternately sorted into the list of $t_i$.\n</li><li>\nThe polar distances are calculated by\n\\[\n\\vartheta_i=\\arccos\\, t_i.\n\\]</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">globalPointsCount</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>ellipsoidal height</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>Driscoll</h2><p>\nThe Driscoll-Healy grid, has equiangular spacing along the meridians as well\nas along the circles of latitude. In longitudinal direction (along the parallels),\nthese angular differences for a given <strong class=\"groops-config-element\">dimension</strong> $L$ coincide with those\ndescribed for the corresponding geographical grid and Gauss grid. Along the meridians,\nthe size of the latitudinal differences is half the size compared to the geographical\ngrid. This results in the following point pattern,\n\\[\n\\begin{split}\n\\Delta\\lambda=\\frac{\\pi}{L}\\qquad&\\Rightarrow\\qquad\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad&\\mbox{with}\\qquad 0\\leq i< 2L, \\\\\n\\Delta\\vartheta=\\frac{\\pi}{2L}\\qquad&\\Rightarrow\\qquad\\vartheta_j=j\\cdot\\Delta\\vartheta\\qquad&\\mbox{with}\\qquad 1\\leq j\\leq 2L.\n\\end{split}\n\\]Consequently, the number of grid points is\n\\[\nI=4\\cdot L^2.\n\\]The weights are given by\n\\[\nw_i=\\Delta\\lambda\\frac{4}{2L}\\sin(\\vartheta_i)\\sum_{l=0}^{L-1}\\frac{\\sin\\left[ (2l+1)\\;\\vartheta_i\\right] }{2l+1}.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">dimension</div></div></td><td>uint</td><td>number of parallels = 2*dimension</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>ellipsoidal height</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n<h2>SinglePoint</h2><p>\nCreates one single point.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">L</div></div></td><td>angle</td><td>longitude</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">B</div></div></td><td>angle</td><td>latitude</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>ellipsoidal height</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">area</div></div></td><td>double</td><td>associated area element on unit sphere</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>major axsis of the ellipsoid/sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>flattening of the ellipsoid, 0: sphere</td></tr>\n</table>\n\n<h2>SinglePointCartesian</h2><p>\nCreates one single point.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">x</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">y</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">z</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">area</div></div></td><td>double</td><td>associated area element on unit sphere</td></tr>\n</table>\n\n<h2 id=\"file\">File</h2><p>\nIn this class grid is read from a file, which is given by <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGrid</a>.\nA corresponding file can be generated with <a class=\"groops-program\" href=\"GriddedDataCreate.html\">GriddedDataCreate</a> or with <a class=\"groops-program\" href=\"Matrix2GriddedData.html\">Matrix2GriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGrid</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">border</div></div></td><td><a href=\"borderType.html\">border</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Overview</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>GROOPS Documentation and Cookbook</h1>\n<p>GROOPS is a software toolkit for gravity field recovery, GNSS processing, and statistical analysis of time series and spatial data.\nIt is licensed under GPLv3 and hosted at <a target=\"_blank\" href=\"https://github.com/groops-devs/groops\">GitHub</a>.</p>\n<p>GROOPS depends on data files such as Earth rotation, Love numbers, and GNSS meta information.\nAn initial data set that is regularly updated is available on our FTP server,\n<a target=\"_blank\" href=\"https://ftp.tugraz.at/pub/ITSG/groops\">https://ftp.tugraz.at/pub/ITSG/groops</a>.\nYou can choose between downloading the data directory or a single\n<a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data.zip\">data.zip</a> with the same content.</p>\n<p>Additional tutorial videos are available at our <a target=\"_blank\" href=\"https://www.youtube.com/channel/UCzUirVN2JuEKZwdM9dIqllg/videos\">YouTube channel</a>.\nQuestions about the usage of GROOPS can be posted in the\n<a target=\"_blank\" href=\"https://github.com/groops-devs/groops/discussions\">Discussions</a>.</p>\n<div class=\"container\">\n<div class=\"row\">\n  <div class=\"col-sm top-buffer\">\n        <h5 class=\"card-title\">General Information</h5>\n          <p class=\"card-text\">File formats and basic concepts for using GROOPS and its GUI.</p>\n        <ul class=\"list-group list-group-flush\">\n          <li><a href=\"general.configFiles.html\">Config files</a></li>\n          <li><a href=\"general.parser.html\">Parser</a></li>\n          <li><a href=\"general.loopsAndConditions.html\">Loops and conditions</a></li>\n          <li><a href=\"general.constants.html\">Constants and the setting file</a></li>\n          <li><a href=\"general.parallelization.html\">Parallelization</a></li>\n          <li><a href=\"general.gui.html\">Graphical User Interface (GUI)</a></li>\n          <li><a href=\"general.fileFormat.html\">File formats</a></li>\n        </ul>\n  </div>\n  <div class=\"col-sm top-buffer\">\n        <h5 class=\"card-title\">Mathematic Fundamentals</h5>\n          <p class=\"card-text\">Description of methods used throughout GROOPS.</p>\n        <ul class=\"list-group list-group-flush\">\n          <li><a href=\"fundamentals.robustLeastSquares.html\">Robust least squares adjustment</a></li>\n          <li><a href=\"fundamentals.basisSplines.html\">Basis splines</a></li>\n          <li><a href=\"fundamentals.autoregressiveModel.html\">Autoregressive models</a></li>\n        </ul>\n  </div>\n</div>\n<div class=\"row\">\n  <div class=\"col-sm top-buffer\">\n        <h5 class=\"card-title\">Cookbook</h5>\n          <p class=\"card-text\">Recipes to explore the GROOPS feature set.</p>\n        <ul class=\"list-group list-group-flush\">\n          <li><a href=\"cookbook.instrument.html\">Instrument data handling</a></li>\n          <li><a href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a></li>\n          <li><a href=\"cookbook.gnssPpp.html\">GNSS precise point positioning (PPP)</a></li>\n          <li><a href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a></li>\n          <li><a href=\"cookbook.gravityFieldPod.html\">Gravity field determination from POD data</a></li>\n          <li><a href=\"cookbook.gravityFieldGrace.html\">GRACE gravity field recovery</a></li>\n          <li><a href=\"cookbook.regionalGeoid.html\">Regional geoid determination</a></li>\n        </ul>\n  </div>\n  <div class=\"col-sm top-buffer\">\n        <h5 class=\"card-title\">Program/Class Reference</h5>\n        <p class=\"card-text\">Reference and documentation for all programs and classes in GROOPS.</p>\n        <ul class=\"list-group list-group-flush\">\n          <li><a href=\"programType.html\">List of programs</a></li>\n          <li><a href=\"classes.html\">List of classes</a></li>\n        </ul>\n  </div>\n</div>\n</div>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/instrumentTypeType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - instrumentTypeType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"instrumentTypeType\">InstrumentType</h1><p>\nDefines the type of an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">instrumentTypeType</div></div></td><td>choice</td><td>instrument type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">INSTRUMENTTIME</div></div></td><td></td><td>time without data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MISCVALUE</div></div></td><td></td><td>single value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MISCVALUES</div></div></td><td></td><td>multiple values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">VECTOR3D</div></div></td><td></td><td>x, y, z</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">COVARIANCE3D</div></div></td><td></td><td>xx, yy, zz, xy, xz, yz</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ORBIT</div></div></td><td></td><td>position [m], velocity [m/s], acceleration [m/s^2] (each x, y, z)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">STARCAMERA</div></div></td><td></td><td>quaternions (q0, qx, qy, qz)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ACCELEROMETER</div></div></td><td></td><td>x, y, z [m/s^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">SATELLITETRACKING</div></div></td><td></td><td>range [m], range rate [m/s], range acceleration [m/s^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">GRADIOMETER</div></div></td><td></td><td>xx, yy, zz, xy, xz, yz [1/s^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">GNSSRECEIVER</div></div></td><td></td><td>GNSS phase/code observations [m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">OBSERVATIONSIGMA</div></div></td><td></td><td>accuracy</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">SATELLITELASERRANGING</div></div></td><td></td><td>range [m], accuracy [m], redundancy, window [s], wavelength [m], azimuth [rad], elevation [rad]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">METEOROLOGICAL</div></div></td><td></td><td>temperature [K], pressure [Pa], humidity [%], windSpeed [m/s], radiation [W/m^2], precip. [mm/d]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MASS</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">THRUSTER</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">MAGNETOMETER</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">ACCHOUSEKEEPING</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/interpolatorTimeSeriesType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - interpolatorTimeSeriesType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"interpolatorTimeSeriesType\">InterpolatorTimeSeries</h1><p>\nThis class resamples data of a times series to new poins in time.\n</p>\n\n<h2>Polynomial</h2><p>\nPolynomial prediction using a moving polynomial of <strong class=\"groops-config-element\">polynomialDegree</strong>.\nThe optimal polynomial is chosen based on the centricity of the data points around the resampling\npoint and the distance to all polynomial data points. All polynomial data points must be within\n<strong class=\"groops-config-element\">maxDataPointRange</strong>. Resampling points within <strong class=\"groops-config-element\">maxExtrapolationDistance</strong> of the\npolynomial will be extrapolated. The elements <strong class=\"groops-config-element\">maxDataPointRange</strong> and <strong class=\"groops-config-element\">maxExtrapolationDistance</strong>\nare given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/instrumentResample_polynomial.png\" alt=\"instrumentResample_polynomial\"><figcaption class=\"center\">Figure: Example of polynomial prediction when resampling from 5 to 1 minute sampling</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>degree of the moving polynomial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDataPointRange</div></div></td><td>double</td><td>[seconds] all degree+1 data points must be within this range for a valid polynomial</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxExtrapolationDistance</div></div></td><td>double</td><td>[seconds] resampling points within this range of the polynomial will be extrapolated</td></tr>\n</table>\n\n<h2>Least squares polynomial fit</h2><p>\nA polynomial of <strong class=\"groops-config-element\">polynomialDegree</strong> is estimated using all data points within\n<strong class=\"groops-config-element\">maxDataPointDistance</strong> of the resampling point. This polynomial is then used\nto predict the resampling point. A resampling point will be extrapolated if there are\nonly data points before/after as long as the closest one is within <strong class=\"groops-config-element\">maxExtrapolationDistance</strong>.\nThe elements <strong class=\"groops-config-element\">maxDataPointDistance</strong> and <strong class=\"groops-config-element\">maxExtrapolationDistance</strong> are given\nin the unit of seconds. If negative values are used, the unit is relative to the median input sampling.</p><p><figure><img class=\"figure\" style=\"width:50%;\" src=\"../figures/instrumentResample_leastSquares.png\" alt=\"instrumentResample_leastSquares\"><figcaption class=\"center\">Figure: Example of least squares polynomial fit when resampling from 5 to 1 minute sampling</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>degree of the estimated polynomial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDataPointDistance</div></div></td><td>double</td><td>[seconds] all data points within this distance around the resampling point will be used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxExtrapolationDistance</div></div></td><td>double</td><td>[seconds] resampling points within this range of the polynomial will be extrapolated</td></tr>\n</table>\n\n<h2>Fill gaps with least squares polynomial fit</h2><p>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">polynomialDegree</div></div></td><td>uint</td><td>degree of the estimated polynomial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDataGap</div></div></td><td>double</td><td>[seconds] max data gap to interpolate</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDataSpan</div></div></td><td>double</td><td>[seconds] time span on each side used for least squares fit</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>[seconds] margin for identical times</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/kernelType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - kernelType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"kernelType\">Kernel</h1><p>\nKernel defines harmonic isotropic integral kernels $K$.\n\\[\nT(P) = \\frac{1}{4\\pi}\\int_\\Omega K(P,Q)\\cdot f(Q)\\,d\\Omega(Q),\n\\]where $T$ is the (disturbance)potential and $f$ is a functional on the spherical surface $\\Omega$.\nThe Kernel can be exapanded into a series of (fully normalized) legendre polynomials\n\\[\\label{eq.kernel}\nK(\\cos\\psi,r,R) = \\sum_n \\left(\\frac{R}{r}\\right)^{n+1}\nk_n\\sqrt{2n+1}\\bar{P}_n(\\cos\\psi).\n\\]On the one hand the kernel defines the type of the functionals $f$ that are measured\nor have to be computed, e.g. gravity anomalies given by the Stokes-kernel.\nOn the other hand the kernel functions can be used as basis functions to represent\nthe gravity field, e.g. as spline functions or wavelets.\n</p>\n\n<h2 id=\"geoidHeight\">GeoidHeight</h2><p>\nThe geoid height is defined by Bruns formula\n\\[\nN = \\frac{1}{\\gamma}T\n\\]with $T$ the disturbance potential and the normal gravity\n\\[\\label{normalgravity}\n\\gamma  = \\gamma_0 - 0.30877\\cdot 10^{-5}/s^2(1-0.00142\\sin^2(B))h\n\\]and\n\\[\n\\gamma_0 = 9.780327\\,m/s^2(1+0.0053024\\sin^2(B)-0.0000058\\sin^2(2B))\n\\]where $h$ is the ellipsoidal height in meter and $B$ the longitude.</p><p>The kernel is given by\n\\[\nK(\\cos\\psi,r,R) = \\gamma\\frac{R(r^2-R^2)}{l^3},\n\\]and the coefficients in \\eqref{eq.kernel} are\n\\[\nk_n = \\gamma.\n\\]</p>\n\n<h2>Anomalies</h2><p>\nGravity anomalies in linearized form are defined by\n\\[\n\\Delta g = -\\frac{\\partial T}{\\partial r}-\\frac{2}{r}T.\n\\]The Stokes kernel is given by\n\\[\nK(\\cos\\psi,r,R) = \\frac{2R^2}{l}-3\\frac{Rl}{r^2}-\\frac{R^2}{r^2}\\cos\\psi\n\\left(5+3\\ln\\frac{l+r-R\\cos\\psi}{2r}\\right),\n\\]and the coefficients in \\eqref{eq.kernel} are\n\\[\nk_n = \\frac{R}{n-1}.\n\\]</p>\n\n<h2 id=\"disturbance\">Disturbance</h2><p>\nGravity disturbances in linearized form are defined by\n\\[\n\\delta g = -\\frac{dT}{dr}.\n\\]The Hotine kernel is given by\n\\[\nK(\\cos\\psi,r,R) = \\frac{2R^2}{l}-R\\ln\\frac{l+R-r\\cos\\psi}{r(1-\\cos\\psi)},\n\\]and the coefficients in \\eqref{eq.kernel} are\n\\[\nk_n = \\frac{R}{n+1}.\n\\]</p>\n\n<h2>Potential</h2><p>\nThe Abel-Poisson kernel is given by\n\\[\nK(\\cos\\psi,r,R) = \\frac{R(r^2-R^2)}{l^3},\n\\]and the coefficients in \\eqref{eq.kernel} are\n\\[\nk_n = 1.\n\\]</p>\n\n<h2>Density</h2><p>\nThis kernel defines a point mass or mass on a single layer ($1/l$-kernel)\ntaking the effect of the loading into account.</p><p>The coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\[\nk_n = 4\\pi G R\\frac{1+k_n'}{2n+1},\n\\]where $G$ is the gravitational constant and $k_n'$ are the load Love numbers.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileLoadingLoveNumber</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2 id=\"waterHeight\">WaterHeight</h2><p>\nHeight of equivalent water columns taking the effect of the loading into account.</p><p>The coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\[\nk_n = 4\\pi G \\rho R\\frac{1+k_n'}{2n+1},\n\\]where $G$ is the gravitational constant, $\\rho$ is the <strong class=\"groops-config-element\">density</strong> of water\nand $k_n'$ are the load Love numbers.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">density</div></div></td><td>double</td><td>[kg/m**3]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileLoadingLoveNumber</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>BottomPressure</h2><p>\nOcean bottom pressure caused by water and atmosphere masses columns taking the effect of the loading into account.</p><p>The coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\[\nk_n = \\frac{4\\pi G R }{\\gamma}\\frac{1+k_n'}{2n+1},\n\\]where $G$ is the gravitational constant, $\\gamma$ is the normal gravity and $k_n'$ are the load Love numbers.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileLoadingLoveNumber</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>Deformation</h2><p>\nComputes the radial deformation caused by loading.</p><p>The coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\[\nk_n = \\gamma\\frac{1+k_n'}{h_n'},\n\\]where $\\gamma$ is the normal gravity defined in \\eqref{normalgravity},\n$h_n'$ and $k_n'$ are the load Love numbers and the load deformation Love numbers.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDeformationLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfilePotentialLoadLoveNumber</div></div></td><td>filename</td><td>if full potential is given and not only loading potential</td></tr>\n</table>\n\n<h2>RadialGradient</h2><p>\nThis kernel defines the second radial derivative of the (disturbance) potential.\n\\[\nT_{rr} = \\frac{\\partial^2 T}{\\partial r^2}.\n\\]The coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\[\nk_n = \\frac{r^2}{(n+1)(n+2)}.\n\\]</p>\n\n<h2 id=\"coefficients\">Coefficients</h2><p>\nThe kernel is defined by the coefficients $k_n$ given by file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileCoefficients</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>FilterGauss</h2><p>\nAnother <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is smoothed by a gauss filter\nwhich is defined by\n\\[\nF(\\cos\\psi) = \\frac{b\\cdot e^{-b(1-\\cos\\psi)}}{1-e^{-2b}}\n\\]with $b = \\frac{ln(2)}{1-\\cos(r/R)}$ where $r$ is the given\nsmoothing <strong class=\"groops-config-element\">radius</strong> in km and $R=6378.1366$ km is the\nEarth radius.\nThe coefficients $k_n$ of the <strong class=\"groops-config-element\">kernel</strong> are multiplicated by\n\\[\nf_n = \\frac{1}{2n+1} \\int_{-1}^1 F(t)\\cdot \\bar{P}_n(t)\\,dt.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">radius</div></div></td><td>double</td><td>filter radius [km]</td></tr>\n</table>\n\n<h2>BlackmanLowpass</h2><p>\nAnother <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is smoothed by a Blackman low-pass filter. The filter is\ndefined through the beginning and end of the transition from pass-band to stop-band. This\ntransition band is specified by <strong class=\"groops-config-element\">startDegreeTransition</strong> ($n_1$) and <strong class=\"groops-config-element\">stopDegreeTransition</strong> ($n_2$).</p><p>The coefficients of this kernel are defined as\n\\[\n\\begin{cases}\n1 & \\text{for } n < n_1 \\\\\nA_n^2 & \\text{for } n_1\\leq n \\leq n_2 \\\\\n0 & \\text{for } n > n_2 \\\\\n\\end{cases}\n\\]with\n\\[\nA_n = 0.42 + 0.5\\cos(\\pi \\frac{n-n_1}{n_2-n_1}) + 0.08 \\cos(2\\pi\\frac{n-n_1}{n_2-n_1}).\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">startDegreeTransition</div></div></td><td>uint</td><td>minimum degree in transition band</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">stopDegreeTransition</div></div></td><td>uint</td><td>maximum degree in transition band</td></tr>\n</table>\n\n<h2>Truncation</h2><p>\nAnother <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is truncated before <strong class=\"groops-config-element\">minDegree</strong> and after <strong class=\"groops-config-element\">maxDegree</strong>.\nThe coefficients of this kernel are defined as\n\\[\n  k_n =\n  \\begin{cases}\n  1 & \\text{for } n_{\\text{minDegree}} \\leq n \\leq n_{\\text{maxDegree}}\\\\\n  0 & \\text{else.} \\\\\n  \\end{cases}\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td>truncate before minDegree</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>truncate after maxDegree</td></tr>\n</table>\n\n<h2>SelenoidHeight</h2><p>\nThe selenoid height is defined by Bruns formula\n\\[\nN = \\frac{1}{\\gamma}T\n\\]with $T$ the disturbance potential and the normal gravity $\\gamma=\\frac{GM}{R^2}$ of the moon.</p><p>The kernel is given by\n\\[\nK(\\cos\\psi,r,R) = \\gamma\\frac{R(r^2-R^2)}{l^3},\n\\]and the coefficients in \\eqref{eq.kernel} are\n\\[\nk_n = \\gamma.\n\\]</p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/loopType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - loopType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"loopType\">Loop</h1><p>\nGenerates a sequence with variables to loop over.\nThe variable names can be set with <strong class=\"groops-config-element\">variableLoop...</strong> and\nthe current values are assigned to the variables for each loop step.</p><p>With <a class=\"groops-class\" href=\"conditionType.html\">condition</a> only a subset of loop steps are performed.\nThe <strong class=\"groops-config-element\">variableLoopIndex</strong> and <strong class=\"groops-config-element\">variableLoopCount</strong> are not affected by the condition.\nThe result would therefore be the same as using <a class=\"groops-program\" href=\"LoopPrograms.html\">LoopPrograms</a> with a nested <a class=\"groops-program\" href=\"IfPrograms.html\">IfPrograms</a>.</p><p>See <a class=\"groops-ref\" href=\"general.loopsAndConditions.html\">Loop and conditions</a> for usage.\n</p>\n\n<h2 id=\"timeSeries\">TimeSeries</h2><p>\nLoop over points in time.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>loop is called for every point in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTime</div></div></td><td>string</td><td>variable with time of each loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"timeIntervals\">TimeIntervals</h2><p>\nLoop over the intervals between points in time.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeIntervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>loop is called for every interval</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTimeStart</div></div></td><td>string</td><td>variable with starting time of each interval</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTimeEnd</div></div></td><td>string</td><td>variable with ending time of each interval</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"stringList\">StringList</h2><p>\nLoop over list of strings.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">string</div></div></td><td>string</td><td>explicit list of strings</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopString</div></div></td><td>string</td><td>name of the variable to be replaced</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"stringTable\">StringTable</h2><p>\nLoop over <strong class=\"groops-config-element\">row</strong>s of a table containing strings.\nEach row must have the same number of cells.\nFor each column an extra <strong class=\"groops-config-element\">variableLoopString</strong> can be defined.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">row</div></div></td><td>sequence</td><td>rows of a table</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">cell</div></div></td><td>string</td><td>list of columns in a row</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">transpose</div></div></td><td>boolean</td><td>loop over columns instead of rows</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">variableLoopString</div></div></td><td>string</td><td>1. variable name for the 1. column, next variable name for the 2. column, ... </td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"fileStringList\">FileStringList</h2><p>\nLoop over list of strings from <a class=\"groops-file\" href=\"fileFormat_stringList.html\">files</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>string list file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopString</div></div></td><td>string</td><td>name of the variable to be replaced</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"fileStringTable\">FileStringTable</h2><p>\nLoop over rows of a <a class=\"groops-file\" href=\"fileFormat_stringTable.html\">table</a> containing strings.\nEach row must have the same number of columns.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>string table file with multiple columns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">transpose</div></div></td><td>boolean</td><td>loop over columns instead of rows</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">variableLoopString</div></div></td><td>string</td><td>1. variable name for the 1. column, next variable name for the 2. column, ... </td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"fileTextLines\">FileTextLines</h2><p>\nLoop over lines of a text file.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfile</div></div></td><td>filename</td><td>simple text file with lines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>start at element startIndex (counting from 0)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">count</div></div></td><td>uint</td><td>use number of loops only (default: use all)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopLine</div></div></td><td>string</td><td>name of the variable to be replaced</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"matrix\">Matrix</h2><p>\nLoop over rows of a <a class=\"groops-file\" href=\"fileFormat_matrix.html\">matrix</a>. To define the loop variables the standard\ndata variables of the matrix are available, see <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">transpose</div></div></td><td>boolean</td><td>effectively loop over columns</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startRow</div></div></td><td>expression</td><td>start at this row (variable: rows)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countRows</div></div></td><td>expression</td><td>use this many rows (variable: rows)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">variableLoop</div></div></td><td>expression</td><td>define a variable by name = expression (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"numberSequence\">NumberSequence</h2><p>\nLoop over sequence of numbers.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rangeStart</div></div></td><td>double</td><td>start of range</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rangeEnd</div></div></td><td>double</td><td>end of range (inclusive)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sampling</div></div></td><td>double</td><td>sampling</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopNumber</div></div></td><td>string</td><td>name of the variable to be replaced</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"directoryListing\">DirectoryListing</h2><p>\nLoop over files of a directory.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">directory</div></div></td><td>filename</td><td>directory</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">pattern</div></div></td><td>string</td><td>wildcard pattern</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">isRegularExpression</div></div></td><td>boolean</td><td>pattern is a regular expression</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopFile</div></div></td><td>string</td><td>name of the variable to be replaced</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"commandOutput\">CommandOutput</h2><p>\nLoop over lines of command output.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">command</div></div></td><td>filename</td><td>each output line becomes a loop iteration</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">silently</div></div></td><td>boolean</td><td>without showing the output.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopString</div></div></td><td>string</td><td>name of the variable to be replaced</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"platformEquipment\">PlatformEquipment</h2><p>\nLoop over specific equipment of a <a class=\"groops-file\" href=\"fileFormat_platform.html\">platform file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePlatform</div></div></td><td>filename</td><td>platform info file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">equipmentType</div></div></td><td>choice</td><td>equipment type to loop over</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">all</div></div></td><td></td><td>loop over all types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gnssAntenna</div></div></td><td></td><td>loop over antennas</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gnssReceiver</div></div></td><td></td><td>loop over receivers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">slrStation</div></div></td><td></td><td>loop over SLR stations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">slrRetroReflector</div></div></td><td></td><td>loop over laser retroreflectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">satelliteIdentifier</div></div></td><td></td><td>loop over satellite identifiers</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">other</div></div></td><td></td><td>loop over other types</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopName</div></div></td><td>string</td><td>variable with name</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopSerial</div></div></td><td>string</td><td>variable with serial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopInfo</div></div></td><td>string</td><td>variable with radome (antenna) or version (receiver)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTimeStart</div></div></td><td>string</td><td>variable with start time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTimeEnd</div></div></td><td>string</td><td>variable with end time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopPositionX</div></div></td><td>string</td><td>variable with position x</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopPositionY</div></div></td><td>string</td><td>variable with position y</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopPositionY</div></div></td><td>string</td><td>variable with position z</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"loop\">Loop</h2><p>\nLoop over nested loops. First <strong class=\"groops-config-element\">loop</strong> is outermost loop, every subsequent <strong class=\"groops-config-element\">loop</strong> is one level below the previous <strong class=\"groops-config-element\">loop</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">loop</div></div></td><td><a href=\"loopType.html\">loop</a></td><td>subloop</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2 id=\"sortAndRemoveDuplicates\">SortAndRemoveDuplicates</h2><p>\nPerform the <a class=\"groops-class\" href=\"loopType.html\">loop</a> in the alphabetically\norder defined by the evaluated <strong class=\"groops-config-element\">sortString</strong> for each loop step.\nSo the string must contain loop variables. If <strong class=\"groops-config-element\">sortString</strong>\nis empty, no sorting will take place.</p><p>Example: The <strong class=\"groops-config-element\">sortString</strong>=<code>{loopTime:%m}</code> of a time series\nsorts the times in ascending order by month.</p><p>The same principle is used to remove duplicates. If different loop steps\nevaluates <strong class=\"groops-config-element\">removeDuplicatesString</strong> to the same string,\nonly the first loop step is executed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">loop</div></div></td><td><a href=\"loopType.html\">loop</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">sortString</div></div></td><td>string</td><td>use {loopVariables}, sort alphabetically</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">descending</div></div></td><td>boolean</td><td>sorting descending instead of ascending</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">removeDuplicatesString</div></div></td><td>string</td><td>use {loopVariables}, remove duplicates (order is preserved)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2>ManualTable</h2><p>\nDEPRECATED since 2025-09-27. Use LoopStringTable instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">table</div></div></td><td>choice</td><td>define table by rows/columns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rowWise</div></div></td><td>sequence</td><td>define table by rows</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">row</div></div></td><td>sequence</td><td>define table by rows</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">cell</div></div></td><td>string</td><td>explicit list of cells in row/column</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">columnWise</div></div></td><td>sequence</td><td>define table by columns</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">column</div></div></td><td>sequence</td><td>define table by columns</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-3\"><div class=\"h-100 config mustset-unbounded\">cell</div></div></td><td>string</td><td>explicit list of cells in row/column</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">variableLoopString</div></div></td><td>string</td><td>1. variable name for the 1. column, next variable name for the 2. column, ... </td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n<h2>FileGnssStationInfo</h2><p>\nDEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGnssStationInfo</div></div></td><td>filename</td><td>station/transmitter info file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">infoType</div></div></td><td>choice</td><td>info to loop over</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">antenna</div></div></td><td></td><td>loop over antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">receiver</div></div></td><td></td><td>loop over receivers</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopName</div></div></td><td>string</td><td>variable with antenna/receiver name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopSerial</div></div></td><td>string</td><td>variable with antenna/receiver serial</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopInfo</div></div></td><td>string</td><td>variable with radome (antenna) or version (receiver)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTimeStart</div></div></td><td>string</td><td>variable with antenna/receiver start time</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTimeEnd</div></div></td><td>string</td><td>variable with antenna/receiver end time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopIndex</div></div></td><td>string</td><td>variable with index of current iteration (starts with zero)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopCount</div></div></td><td>string</td><td>variable with total number of iterations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>check before each loop step</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/magnetosphereType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - magnetosphereType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"magnetosphereType\">Magnetosphere</h1><p>\nThis class provides functions of the magnetic field of the Earth.\n</p>\n\n<h2>IGRF</h2><p>\nInternational Geomagnetic Reference Field.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileMagneticNorthPole</div></div></td><td>filename</td><td>time series of north pole</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/matrixGeneratorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - matrixGeneratorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"matrixGeneratorType\">MatrixGenerator</h1><p>\nThis class provides a matrix used e.g. by <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.\nIf multiple matrices are given the resulting matrix is the sum all\nand the size is exandeded to fit all matrices. Before the computation of each submatrix\nthe variables <code>rowsBefore</code> and <code>columnsBefore</code> with current size of the overall matrix\nare set. As all matrices can be manipulated before, complex matrix operations are possible.\n</p>\n\n<h2>File</h2><p>\nMatrix from <a class=\"groops-file\" href=\"fileFormat_matrix.html\">file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n</table>\n\n<h2>Normals file</h2><p>\nMatrix from a <a class=\"groops-file\" href=\"fileFormat_normalEquation.html\">normal equation file</a>. The symmetric normal matrix,\nthe right hand side vector, the lPl vector, or the observation count $(1\\times1)$ can be selected.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">normalMatrix</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">lPl</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationCount</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n</table>\n\n<h2>Expression</h2><p>\nMatrix filled by an expression. For each element of the new matrix the variables\n<code>row</code> and <code>column</code> are set and the expression <strong class=\"groops-config-element\">element</strong> is evaluated.</p><p>Excample: The <strong class=\"groops-config-element\">element</strong>=<code>if(row==column,1,0)</code> generates an identity matrix.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rows</div></div></td><td>expression</td><td>(variables: rowsBefore, columnsBefore)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">columns</div></div></td><td>expression</td><td>(variables: rowsBefore, columnsBefore)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">element</div></div></td><td>expression</td><td>for each element of matrix (variables: row, column, rows, columns, rowsBefore, columnsBefore)</td></tr>\n</table>\n\n<h2>Element manipulation</h2><p>\nThe elements of a matrix are replaced an expression.\nFor each element of the matrix the variables <code>data</code>, <code>row</code>, <code>column</code>\nare set and the expression <strong class=\"groops-config-element\">element</strong> is evaluated and replaces the element.\nAdditionally the standard data variables are available (assigned each row),\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">element</div></div></td><td>expression</td><td>for each element of matrix (variables: data, row, column, rows, columns, rowsBefore, columnsBefore)</td></tr>\n</table>\n\n<h2>ElementWiseOperation</h2><p>\nGiven two matrices $\\mathbf{A}$ and $\\mathbf{B}$ this class computes $c_{ij} = f(a_{ij}, b_{ij})$,\nwhere $f$ is an expression (for example <code>data0*data1</code>).\nFor each element of the matrix the variables <code>data0</code>, <code>data1</code>, <code>row</code>, <code>column</code>\nare set and the expression <strong class=\"groops-config-element\">element</strong> is evaluated.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix1</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix2</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">expression</div></div></td><td>expression</td><td>for each element of matrix (variables: data0, data1, row, column, rows, columns, rowsBefore, columnsBefore)</td></tr>\n</table>\n\n<h2>Append</h2><p>\nAppend matrix to the right (first row) or bottom (first column).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">side</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">right</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">bottom</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">diagonal</div></div></td><td></td><td></td></tr>\n</table>\n\n<h2>Shift</h2><p>\nShift start row and start column of a matrix.\nIn other words: zero lines and columns are inserted at the beginning of the matrix.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startRow</div></div></td><td>expression</td><td>start row (variables: rowsBefore, columnsBefore, rows, columns)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startColumn</div></div></td><td>expression</td><td>start column (variables: rowsBefore, columnsBefore, rows, columns)</td></tr>\n</table>\n\n<h2>Slice</h2><p>\nSlice of a matrix.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startRow</div></div></td><td>expression</td><td>start row of matrix (variables: rowsBefore, columnsBefore, rows, columns)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startColumn</div></div></td><td>expression</td><td>start column of matrix (variables: rowsBefore, columnsBefore, rows, columns)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rows</div></div></td><td>expression</td><td>0: until end (variables: rowsBefore, columnsBefore, rows, columns)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">columns</div></div></td><td>expression</td><td>0: until end (variables: rowsBefore, columnsBefore, rows, columns)</td></tr>\n</table>\n\n<h2>Reshape</h2><p>\nMatrix reshaped columnwise to new row and columns.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rows</div></div></td><td>expression</td><td>0: auto-determine rows, (variables: rowsBefore, columnsBefore)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">columns</div></div></td><td>expression</td><td>0: auto-determine columns (variables: rowsBefore, columnsBefore)</td></tr>\n</table>\n\n<h2 id=\"reorder\">Reorder</h2><p>\nReorder rows or columns of a matrix by an index vectors.\nThe index vector can be created with <a class=\"groops-program\" href=\"ParameterSelection2IndexVector.html\">ParameterSelection2IndexVector</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileIndexVectorRow</div></div></td><td>filename</td><td>index in input matrix or -1 for new parameter.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileIndexVectorColumn</div></div></td><td>filename</td><td>index in input matrix or -1 for new parameter.</td></tr>\n</table>\n\n<h2>Sort</h2><p>\nSort matrix by <strong class=\"groops-config-element\">column</strong> in ascending order by default or in <strong class=\"groops-config-element\">descending</strong> order.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">column</div></div></td><td>uint</td><td>sort by column, top = highest priority</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">descending</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2>Transpose</h2><p>\nTransposed of a matrix $\\M A^T$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n</table>\n\n<h2>Multiplication</h2><p>\nMultiplication of matrices.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix1</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix2</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n</table>\n\n<h2>Inverse</h2><p>\nInverse of a matrix $\\M A^{-1}$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">pseudoInverse</div></div></td><td>boolean</td><td>compute pseudo inverse instead of regular one</td></tr>\n</table>\n\n<h2>Cholesky</h2><p>\nUpper triangular natrix of the cholesky decomposition of a symmetric matrix $\\M A=\\M W^T\\M W$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n</table>\n\n<h2>RankKUpdate</h2><p>\nSymmetric matrix from rank k update: $\\M A^T\\M A$.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td></td></tr>\n</table>\n\n<h2>EigenValues</h2><p>\nComputes the eigenvalues of a square matrix and gives a vector of eigenvalues for symmetric matrices\nor a matrix with 2 columns with real and imaginary parts in general case.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">eigenVectors</div></div></td><td>boolean</td><td>return eigen vectors instead of eigen values</td></tr>\n</table>\n\n<h2>Diagonal</h2><p>\nExtract the diagonal or subdiagnoal ($n\\times 1$ vector) of a matrix.\nThe zero <strong class=\"groops-config-element\">diagonal</strong> means the main diagonal, a positive value the superdiagonal,\nand a negative the subdiagonal.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">diagonal</div></div></td><td>int</td><td>zero: main diagonal, positive: superdiagonal, negative: subdiagonal</td></tr>\n</table>\n\n<h2>FromDiagonal</h2><p>\nGenerate a matrix from a diagonal vector.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td>(nx1) or (1xn) diagonal vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">diagonal</div></div></td><td>int</td><td>zero: main diagonal, positive: superdiagonal, negative: subdiagonal</td></tr>\n</table>\n\n<h2>Set type</h2><p>\nSet type (matrix, matrixSymmetricUpper, matrixSymmetricLower, matrixTriangularUpper, matrixTriangularLower)\nof a matrix. If the type is not matrix, the matrix must be quadratic. Symmetric matrices are filled symmetric\nand for triangular matrix the other triangle is set to zero.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">matrix</div></div></td><td><a href=\"matrixGeneratorType.html\">matrixGenerator</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">matrix</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">matrixSymmetricUpper</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">matrixSymmetricLower</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">matrixTriangularUpper</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">matrixTriangularLower</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/miscAccelerationsType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - miscAccelerationsType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"miscAccelerationsType\">MiscAccelerations</h1><p>\nThis class gives the non conservative forces acting on satellites.\n</p>\n\n<h2 id=\"relativisticEffect\">Relativistic effect</h2><p>\nThe relativistic effect to the acceleration of an artificial Earth satellite\naccording to IERS2010 conventions.</p><p>The macro model and the attitude of the satellite is not needed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">beta</div></div></td><td>double</td><td>PPN (parameterized post-Newtonian) parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gamma</div></div></td><td>double</td><td>PPN (parameterized post-Newtonian) parameter</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">J</div></div></td><td>double</td><td>Earth’s angular momentum per unit mass [m**2/s]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\n\n<h2 id=\"RadiationPressure\">RadiationPressure</h2><p>\nThis class computes acceleration acting on a satellite caused by Solar and Earth radiation pressure\nand thermal radiation.</p><p>Solar radiation pressure: The solar constant at 1 AU can be set via <strong class=\"groops-config-element\">solarFlux</strong>.\nThe <strong class=\"groops-config-element\">factorSolarRadation</strong> can be used to scale the computed acceleration of the direct solar radiation.</p><p>Earth radiation pressure:\nInput are a time series of gridded albedo values (unitless) as <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileAlbedoTimeSeries</a>\nand a time series of gridded longwave flux (W/m$^2$) as <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileLongwaveFluxTimeSeries</a>.\nBoth files are optional and if not specified, the respective effect on the acceleration is not computed.\nThe <strong class=\"groops-config-element\">factorEarthRadation</strong> can be used to scale the computed acceleration of the earth radiation.</p><p>The thermal radiation (TRP) of the satellite itself is either computed as direct re-emission or\nbased on the actual temperature of the satellite surfaces, depending on the setings of the\n<a class=\"groops-file\" href=\"fileFormat_satelliteModel.html\">satellite macro model</a>. The second one uses a transient temperature model\nwith a temporal differential equation which disallows parallel computing.\nThe <strong class=\"groops-config-element\">factorThermalRadiation</strong> can be used to scale the computed acceleration of the TRP.</p><p>The algorithms are described in:</p><p>Woeske et. al. (2019), GRACE accelerometer calibration by high precision non-gravitational force modeling,\nAdvances in Space Research, <a href=\"https://doi.org/10.1016/j.asr.2018.10.025\" target=\"_blank\">https://doi.org/10.1016/j.asr.2018.10.025</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">solarflux</div></div></td><td>double</td><td>solar flux constant in 1 AU [W/m^2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAlbedoTimeSeries</div></div></td><td>filename</td><td>GriddedDataTimeSeries of albedo values (unitless)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileLongwaveFluxTimeSeries</div></div></td><td>filename</td><td>GriddedDataTimeSeries of longwave flux values [W/m^2]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factorSolarRadation</div></div></td><td>double</td><td>Solar radiation pressure is multiplied by this factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factorEarthRadation</div></div></td><td>double</td><td>Earth radiation preussure is multiplied by this factor</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factorThermalRadiation</div></div></td><td>double</td><td>Thermal (re-)radiation is multiplied by this factor</td></tr>\n</table>\n\n<h2 id=\"atmosphericDrag\">AtmosphericDrag</h2><p>\nAtmospheric drag model.\nAlgorithm for the atmospheric drag modelling is based on the free molecule flow\ntheory by Sentman 1961. An analytical expression of this treatise is given in\nMoe and Moe 2005.</p><p>Sentman L. (1961), Free molecule flow theory and its application to the determination\nof aerodynamic forces, Technical report.</p><p>Moe K., Moe M. M. (2005), Gas-surface interactions and satellite drag coefficients,\nPlanetary and Space Science 53(8), 793-801, doi:10.1016/j.pss.2005.03.005.</p><p>Optional determination steps:\nTurn temperature on or off.\nIn the first case, the model mentioned above is applied, which estimates variable drag\nand lift coefficients - in the latter case a constant drag coefficient can be specified.</p><p>Turn wind on/off:\nIt enables the usage of the Horizontal Wind Model 2014 to add additional thermospheric\nwinds in the calculation process.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">thermosphere</div></div></td><td><a href=\"thermosphereType.html\">thermosphere</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td>double</td><td>[rad/s]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerTemperature</div></div></td><td>boolean</td><td>compute drag and lift, otherwise simple drag coefficient is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerWind</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\n\n<h2 id=\"atmosphericDragFromDensityFile\">AtmosphericDragFromDensityFile</h2><p>\nAtmospheric drag computed from thermospheric density along the orbit\n(<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileDensity</a>, MISCVALUE). The <a class=\"groops-class\" href=\"thermosphereType.html\">thermosphere</a>\nis used to to compute temperature and wind.\nFor further details see <a class=\"groops-class\" href=\"miscAccelerationsType.html#atmosphericDrag\">atmosphericDrag</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDensity</div></div></td><td>filename</td><td>density along orbit, MISCVALUE (kg/m^3)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">thermosphere</div></div></td><td><a href=\"thermosphereType.html\">thermosphere</a></td><td>used to compute temperature and wind</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td>double</td><td>[rad/s]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerTemperature</div></div></td><td>boolean</td><td>compute drag and lift, otherwise simple drag coefficient is used</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerWind</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\n\n<h2 id=\"antennaThrust\">Antenna thrust</h2><p>\nThe thrust (acceleration) in the opposite direction the antenna is facing\nwhich is generated by satellite antenna broadcasts.\nThe thrust is defined in the satellite macro model.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\n\n<h2 id=\"fromParametrization\">FromParametrization</h2><p>\nReads a solution vector from file <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileSolution</a>\nwhich may be computed by a least squares adjustment (e.g. by <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>).\nThe coefficients of the vector are interpreted from position <strong class=\"groops-config-element\">indexStart</strong>\n(counting from zero) with help of <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrization</a>.\nIf the solution file contains solution of several right hand sides you can choose\none with number <strong class=\"groops-config-element\">rightSide</strong> (counting from zero).</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSolution</div></div></td><td>filename</td><td>solution vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">indexStart</div></div></td><td>uint</td><td>position in the solution vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">rightSide</div></div></td><td>uint</td><td>if solution contains several right hand sides, select one</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nGroups a set of <a class=\"groops-class\" href=\"miscAccelerationsType.html\">miscAccelerations</a> and has no further effect itself.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">miscAccelerations</div></div></td><td><a href=\"miscAccelerationsType.html\">miscAccelerations</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\n\n<h2 id=\"solarRadiationPressure\">SolarRadiationPressure</h2><p>\nDEPRECATED since 2022-12-19. Use radiationPressure instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">solarflux</div></div></td><td>double</td><td>solar flux constant in 1 AU [W/m**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"albedo\">Albedo</h2><p>\nDEPRECATED since 2022-12-19. Use radiationPressure instead.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileReflectivity</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileEmissivity</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">solarflux</div></div></td><td>double</td><td>solar flux constant in 1 AU [W/m**2]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/noiseGeneratorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - noiseGeneratorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"noiseGeneratorType\">NoiseGenerator</h1><p>\nThis class implements the generation of different types of noise.\nIt provides a generic interface that can be implemented by different\ntypes of generators. The characteristics of the generated noise\nis determined by the generators. See the appropriate documentation\nfor more information.\n</p>\n\n<h2>White</h2><p>\nThe noise is Gaussian with a standard deviation <strong class=\"groops-config-element\">sigma</strong>.\nThe noise is computed via a pseudo random sequence with a start value given\nby <strong class=\"groops-config-element\">initRandom</strong>. The same value always yields the same sequence.\nBe careful in <a class=\"groops-ref\" href=\"general.parallelization.html\">parallel</a> mode\nas all nodes generates the same pseudo random sequence.\nIf this value is set to zero a real random value is used as starting value.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sigma</div></div></td><td>double</td><td>standard deviation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">initRandom</div></div></td><td>uint</td><td>start value for pseudo random sequence, 0: real random</td></tr>\n</table>\n\n<h2>ExpressionPSD</h2><p>\nThis generator creates noise defined by a one sided PSD.\nThe <strong class=\"groops-config-element\">psd</strong> is an expression controlled by the variable 'freq'.\nTo determine the frequency <strong class=\"groops-config-element\">sampling</strong> must be given.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>Basis noise</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">psd</div></div></td><td>expression</td><td>one sided PSD (variable: freq [Hz]) [unit^2/Hz]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sampling</div></div></td><td>double</td><td>to determine frequency [seconds]</td></tr>\n</table>\n\n<h2>Filter</h2><p>\nGenerated noise <a class=\"groops-class\" href=\"noiseGeneratorType.html\">noise</a> is\nfiltered by a <a class=\"groops-class\" href=\"digitalFilterType.html\">filter</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">filter</div></div></td><td><a href=\"digitalFilterType.html\">digitalFilter</a></td><td>digital filter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>Basis noise</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">warmupEpochCount</div></div></td><td>uint</td><td>number of additional epochs at before start and after end</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">overSamplingFactor</div></div></td><td>uint</td><td>noise with multiple higher sampling -> filter -> decimate</td></tr>\n</table>\n\n<h2>PowerLaw</h2><p>\nThis generator creates noise that conforms to a power law relationship, where the power\nof the noise at a frequency is proportional to $1/f^\\alpha$, with a typically between -2 and 2.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">noise</div></div></td><td><a href=\"noiseGeneratorType.html\">noiseGenerator</a></td><td>Basis noise</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">alpha</div></div></td><td>double</td><td>Exponent of the power law relationship 1/f^alpha</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/normalEquationType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - normalEquationType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"normalEquationType\">NormalEquation</h1><p>\nThis class provides a system of normal equations.\nThis total system is the weighted sum of individual normals.\n\\[\n \\M N_{total} =  \\sum_{k=1} \\frac{1}{\\sigma_k^2}\\M N_k\n \\qquad\\text{and}\\qquad\n\\M n_{total} = \\sum_{k=1} \\frac{1}{\\sigma_k^2} \\M n_k.\n\\]The normals do not need to have the same dimension. The dimension\nof the total combined system is chosen to cover all individual systems.\nFor each normal a <strong class=\"groops-config-element\">startIndex</strong> is required which indicates\nthe position of the first unknown of the individual normal within the\ncombined parameter vector.</p><p>The $\\sigma_k$ of the relative weights are defined by <strong class=\"groops-config-element\">aprioriSigma</strong>\nin a first step. If an apriori solution <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileApproxSolution</a> is\ngiven or the normals are solved iteratively the weights are determined by means\nof variance compoment estimation (VCE), see <a class=\"groops-program\" href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a>:\n\\[\n\\sigma_k^2 =\n\\frac{\\M e_k^T\\M P\\M e_k}\n{n_k-\\frac{1}{\\sigma_k^2}\\text{trace}\\left(\\M N_k\\M N_{total}^{-1}\\right)},\n\\]where $n_k$ is the number of observations. The square sum of the residuals\nis calculated by\n\\[\n\\M e_k^T\\M P\\M e_k = \\M x^T\\M N_k\\M x - 2\\M n_k^T\\M x + \\M l_k^T\\M P_k\\M l_k.\n\\]The system of normal equations can be solved with several right hand sides at once. But\nonly one right hand side, which can be selected with the index <strong class=\"groops-config-element\">rightHandSide</strong>\n(counting from zero), can be used to compute the variance factors.\nThe combined normal $\\M N_{total}$ and the solution $\\M x$ are taken from the previous\niteration step. In case of <a class=\"groops-class\" href=\"normalEquationType.html#designVCE\">DesignVCE</a> the algorithm\nis a little bit different as described below.\n</p>\n\n<h2 id=\"design\">Design</h2><p>\nThis class acculumates normal equations from observation equations.\nThe class <a class=\"groops-class\" href=\"observationType.html\">observation</a> computes\nthe linearized and decorrelated equation system for each arc $i$:\n\\[\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i.\n\\]The arc depending parameters $\\M y_i$ are eliminated and the system of normal\nequations is acculumated according to\n\\[\n \\M N = \\sum_{i=1}^m \\M A_i^T  \\M A_i\n \\qquad\\text{and}\\qquad\n\\M n = \\sum_{i=1}^m \\M A_i^T \\M l_i.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td><a href=\"observationType.html\">observation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">aprioriSigma</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>add this normals at index of total matrix (counting from 0)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileArcList</div></div></td><td>filename</td><td>to accelerate computation</td></tr>\n</table>\n\n<h2 id=\"designVCE\">DesignVCE</h2><p>\nThis class acculumates normal equations from observation equations.\nThe class <a class=\"groops-class\" href=\"observationType.html\">observation</a> computes\nthe linearized and decorrelated equation system for each arc $i$:\n\\[\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i.\n\\]The arc depending parameters $\\M y_i$ are eliminated and the system of normal\nequations is acculumated according to\n\\[\n \\M N =  \\sum_{i=1} \\frac{1}{\\sigma_i^2}\\M A_i^T  \\M A_i\n \\qquad\\text{and}\\qquad\n\\M n = \\sum_{i=1} \\frac{1}{\\sigma_i^2} \\M A_i^T \\M l_i.\n\\]The variance $\\sigma_i^2$ of each individual arc is determined by\n\\[\n\\sigma_i^2 =\n\\frac{(\\M l_i-\\M A_i\\M x)^T(\\M l_i-\\M A_i\\M x)}\n{n_i-\\frac{1}{\\sigma_i^2}\\text{trace}\\left(\\M A_i^T  \\M A_i\\M N_{total}^{-1}\\right)},\n\\]where $n_i$ is the number of observations. If an apriori solution is not given at the first\niteration step a zero vector is assumed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td><a href=\"observationType.html\">observation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>add this normals at index of total matrix (counting from 0)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileArcList</div></div></td><td>filename</td><td>to accelerate computation</td></tr>\n</table>\n\n<h2 id=\"file\">File</h2><p>\nReads a system of normal equations from file <a class=\"groops-class\" href=\"fileFormat_normalEquation.html\">inputfileNormalEquation</a>\nas generated by e.g. <a class=\"groops-program\" href=\"NormalsBuild.html\">NormalsBuild</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">aprioriSigma</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>add this normals at index of total matrix (counting from 0)</td></tr>\n</table>\n\n<h2 id=\"regularization\">Regularization</h2><p>\nSet up a system of normal equations\n\\[\n\\M N = \\M R\n\\qquad\\text{and}\\qquad\n\\M n = \\M R \\M b,\n\\]where $\\M R$ is a diagonal matrix whose elements are given as a vector by\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDiagonalMatrix</a> and $\\M b$ is the right hand side towards which will\nbe regularized. It can be given by <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileBiasVector</a>.\nThe diagonal matrix can be generated with <a class=\"groops-program\" href=\"NormalsRegularizationBorders.html\">NormalsRegularizationBorders</a>,\n<a class=\"groops-program\" href=\"NormalsRegularizationSphericalHarmonics.html\">NormalsRegularizationSphericalHarmonics</a>, or <a class=\"groops-program\" href=\"MatrixCalculate.html\">MatrixCalculate</a>.\nIf $\\M R$ is not given a unit matrix is assumed.\nThe right hand side $\\M b$ may be generated with <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a>.\nIf $\\M b$ is not given a zero vector is assumed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileDiagonalMatrix</div></div></td><td>filename</td><td>Vector with the diagonal elements of the weight matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileBias</div></div></td><td>filename</td><td>Matrix with right hand sides</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">aprioriSigma</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>regularization of parameters starts at this index (counting from 0)</td></tr>\n</table>\n\n<h2>RegularizationGeneralized</h2><p></p><p>Generalized regularization which is represented by the observation equation\n\\[\n\\mathbf{x}_0 = \\mathbf{I} \\mathbf{x} + \\mathbf{v}, \\mathbf{v} \\sim \\mathcal{N}(0, \\sum_k \\sigma^2_k \\mathbf{V}_k).\n\\]\nThere are no requirements for partial covariance matrices $\\mathbf{V}_k$ except for them being symmetric.\nThe accumulated covariance matrix $\\sum_k \\sigma^2_k \\mathbf{V}_k$ must be positive definite however.\nThe variance components $\\sigma^2_k$ are estimated during the adjustment process and are assumed to be positive.\nAll <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePartialCovarianceMatrix</a> must be of same size\nand must match the dimension of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileBiasMatrix</a>\n(if provided, otherwise a zero vector of appropriate dimensions is created).</p><p>The parameter <strong class=\"groops-config-element\">aprioriSigma</strong> determines the initial variance factor for the partial covariance matrices. Either one $\\sigma_0$ can be\nsupplied or one for each $\\mathbf{V}_k$.</p><p>The regularization matrix can be applied to a subset of parameters by adjusting <strong class=\"groops-config-element\">startIndex</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfilePartialCovarianceMatrix</div></div></td><td>filename</td><td>symmetric matrix (sum of all matrices must be positive definite)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileBiasMatrix</div></div></td><td>filename</td><td>bias vector (default: zero vector)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">aprioriSigma</div></div></td><td>double</td><td>apriori sigmas for initial iteration (default: 1.0)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startIndex</div></div></td><td>uint</td><td>regularization of parameters starts at this index (counting from 0)</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/observationType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - observationType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"observationType\">Observation</h1><p>\nThis class sets up the observation equations in linearized Gauss-Markov model\n\\[\\label{gmm}\n\\M l  = \\M A \\M x + \\M e\\qquad\\text{and}\\qquad\\mathcal{C}(\\M e) = \\sigma^2\\M P^{-1}.\n\\]The observations are divided into short data blocks which can be computed independently\nand so easily can be parallelized. Usually these data blocks are short arcs of a\nsatellite's orbit. In most cases the unknown parameter vector contains coefficients\nof a gravity field parametrization given by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.\nAdditional parameters like instrument calibration parameters are appended at the\nend of the vector $\\M x$.\nIt is possible to give several observation vectors in one model.</p><p>The observations within each arc are decorrelated in the following way:\nIn a first step a Cholesky decomposition of the covariance matrix is performed\n\\[\n\\M P^{-1} = \\M W^T\\M W,\n\\]where $\\M W$ is an upper regular triangular matrix.\nIn a second step the transformation\n\\[\\label{dekorrelierung}\n\\bar{\\M A} = \\M W^{-T}\\M A\\qquad\\text{and}\\qquad \\bar{\\M l} = \\M W^{-T}\\M l\n\\]gives an estimation from decorrelated observations with equal variance\n\\[\\label{normal.GMM}\n\\bar{\\M l} = \\bar{\\M A} \\M x + \\bar{\\M e}\n\\qquad\\text{and}\\qquad\n\\mathcal{C}(\\bar{\\M e})= \\sigma^2 \\M I.\n\\]Usually the arc dependent parameters are eliminated in the next step\nand not mentioned for the parameter names in the following.\n</p>\n\n<h2 id=\"podVariational\">PodVariational</h2><p>\nThe observation equations for precise orbit data (POD) are formulated as variational equations.\nIt is based on <a class=\"groops-file\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> calculated with <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>.</p><p>The kinematic positions as pseudo observations are taken from\n<strong class=\"groops-config-element\">rightHandSide</strong> and should not be given equally spaced in time. The observation\nequations are interpolated to these times by a moving polynomial of degree <strong class=\"groops-config-element\">interpolationDegree</strong>.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in\n<a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p><strong class=\"groops-config-element\">accelerateComputation</strong>: In the event that the sampling of the kinematic orbit is much higher than the sampling\nof the variational equations (e.g. 1 second vs. 5 seconds) the accumulation of the observation equations\ncan be accelerated by transforming the observation equations\n\\[\n  \\M l = \\M J \\M A \\M x + \\M e,\n\\]where $\\M J$ describes the interpolation of the sampling of the variational design matrix $\\M A$\nto the sampling of the observations $\\M l$ with more rows than columns. The QR decomposition\n\\[\n  \\M J = \\begin{pmatrix} \\M Q_1 & \\M Q_2 \\end{pmatrix}\n         \\begin{pmatrix} \\M R \\\\ \\M 0 \\end{pmatrix}.\n\\]can be used to transform the observation equations\n\\[\n  \\begin{pmatrix} \\M Q_1^T \\M l \\\\ \\M Q_2^T \\M l \\end{pmatrix} =\n  \\begin{pmatrix} \\M Q_1^T \\M R \\\\ \\M 0 \\end{pmatrix} \\M A \\M x +\n  \\begin{pmatrix} \\M Q_1^T \\M e \\\\ \\M Q_2^T \\M e \\end{pmatrix}.\n\\]As the zero lines should not be considered, the computational time for the accumulation is reduced.\nThis option is not meaningful for evaluating the residuals such as in <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.velocity0.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>kinematic positions as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">accelerateComputation</div></div></td><td>boolean</td><td>acceleration of computation by transforming the observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">covariancePod</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits</td></tr>\n</table>\n\n<h2 id=\"podIntegral\">PodIntegral</h2><p>\nThe observation equations for precise orbit data (POD) of short arcs are given by\n\\[\n  {\\M r}_\\epsilon(\\tau) = {\\M r}_A(1-\\tau) + {\\M r}_B\\tau - T^2\\int_0^1 K(\\tau,\\tau')\n  \\left(\\M f_0(\\tau')+\\nabla V(\\tau')\\right)\\,d\\tau'\n\\]with the integral kernel\n\\[\n  K(\\tau,\\tau') = \\begin{cases} \\tau'(1-\\tau) & \\text{for }\\tau'\\le\\tau \\\\\n  \\tau(1-\\tau') & \\text{for }\\tau'>\\tau \\end{cases},\n\\]and the normalized time\n\\[\n  \\tau = \\frac{t-t_A}{T}\\qquad\\text{with}\\qquad T=t_B-t_A.\n\\]The kinematic positions ${\\M r}_\\epsilon(\\tau)$ as pseudo observations are taken from\n<a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>. From these positions the influence of the reference forces $\\M f_0(\\tau)$\nis subtracted which are computed with the background models in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>.\nThe integral is solved by the integration of a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>.\nThe boundary values ${\\M r}_A$ and ${\\M r}_B$ (satellite's state vector) are estimated per arc\nand are usually directly eliminated if <strong class=\"groops-config-element\">keepSatelliteStates</strong> is not set.</p><p>The unknown gravity field $\\nabla V(\\M r, t)$ parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>\nis not evaluated at the observed positions but at the orbit given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nThe same is true for the reference forces. The linearized effect of the gravity field change by the position\nadjustment is taken into account by <strong class=\"groops-config-element\">gradientfield</strong>. This may be a low order field up to a\nspherical harmonics degree of $n=2$ or $n=3$.</p><p>The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a>\nmust be synchronous and must be given with a constant sampling and without any gaps in each short arc\n(see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).\nThe kinematic positions ${\\M r}_\\epsilon(\\tau)$ should not given equally spaced in time\nbut must be divided into the same arcs as the other instrument data.\nThe observation equations are interpolated to this time by a polynomial interpolation\nwith degree <strong class=\"groops-config-element\">interpolationDegree</strong>.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in\n<a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>For <strong class=\"groops-config-element\">accelerateComputation</strong> see <a class=\"groops-class\" href=\"observationType.html#podVariational\">observation:podVariational</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>,\n</li></ul>\n\nand for each arc if <strong class=\"groops-config-element\">keepSatelliteStates</strong> is set\n<ul>\n\n<li><code>&lt;satellite>:arc&lt;no>.position.start.x::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position.start.y::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position.start.z::</code>.\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position.end.x::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position.end.y::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position.end.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"podRightSideType.html\">podRightSide</a></td><td>input for the reduced observation vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gradientfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>low order field to estimate the change of the gravity by position adjustement</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">keepSatelliteStates</div></div></td><td>boolean</td><td>set boundary values of each arc global</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">accelerateComputation</div></div></td><td>boolean</td><td>acceleration of computation by transforming the observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">covariancePod</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits</td></tr>\n</table>\n\n<h2 id=\"podAcceleration\">PodAcceleration</h2><p>\nThe observation equations for precise orbit data (POD) are given by\n\\[\n\\ddot{\\M r}(t) - \\M g_0(t) = \\nabla V(\\M r, t),\n\\]where the accelerations of the satellite $\\ddot{\\M r}(t)$ are derived from the kinematic positions\nin <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>. The orbit differentation is performed by a moving\npolynomial interpolation or approximation with degree <strong class=\"groops-config-element\">interpolationDegree</strong>\nand number of used epochs <strong class=\"groops-config-element\">numberOfEpochs</strong>. The reference forces $\\M g_0(t)$ are computed\nwith the background models in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>.</p><p>All instrument data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>,\nand <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> must be synchronous and be given\nwith a constant sampling without any gaps in each short arc (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>The unknown gravity field $\\nabla V(\\M r, t)$ parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>\nis not evaluated at the observed positions but at the orbit given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nThe same is true for the reference forces. This orbit may be a more accurate dynamical orbit but\nin most cases the kinematic orbit provides good results.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in\n<a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"podRightSideType.html\">podRightSide</a></td><td>input for the reduced observation vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit differentation  by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">numberOfEpochs</div></div></td><td>uint</td><td>number of used Epochs for polynom computation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">covariancePod</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits</td></tr>\n</table>\n\n<h2 id=\"podEnergy\">PodEnergy</h2><p>\nThe observation equations for precise orbit data (POD) are given by\n\\[\n  \\frac{1}{2}\\dot{\\M r}^2\n  -\\dot{\\M r} \\cdot (\\M\\Omega\\times\\M r)\n  +\\int_{t_0}^t(\\dot{\\M\\Omega}\\times\\M r)\\cdot \\dot{\\M r}\\,dt\n  - \\int_{t_0}^t \\M g_0 \\cdot\\dot{\\M r}'\\,dt\n  = V + E.\n\\]where the velocities of the satellite $\\dot{\\M r}(t)$ are derived from\nthe kinematic positions in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a> and the Earth's rotation vector $\\M\\Omega(t)$ is modeled\nwithin <a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>. The orbit differentiation is\nperformed by a polynomial interpolation with degree <strong class=\"groops-config-element\">interpolationDegree</strong>.\nThe integrals are solved by a polynomial interpolation with degree <strong class=\"groops-config-element\">integrationDegree</strong>.\nThe reference forces $\\M g_0(t)$ are computed with the background models in <a class=\"groops-class\" href=\"podRightSideType.html\">rightHandSide</a>.</p><p>All instrument data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a>, and <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a>\nmust be synchronous and be given with a constant sampling without any gaps in each short arc\n(see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>The unknown gravity potential $V(\\M r)$ parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>\nis not evaluated at the observed positions but at the orbit given by <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>.\nThe same is true for the reference forces. This orbit may be a more accurate dynamical orbit but\nin most cases the kinematic orbit provides good results.</p><p>An unknown energy bias $E$ per arc is parametrized by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationBias</a>\nand should be a constant in theory but temporal changes might help to absorb other unmodelled effects.</p><p>The accuracy or the full covariance matrix of the precise orbit data is provided in\n<a class=\"groops-class\" href=\"covariancePodType.html\">covariancePod</a> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingPod.html\">PreprocessingPod</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<code>*:&lt;parametrizationGravity>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"podRightSideType.html\">podRightSide</a></td><td>input for the reduced observation vector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization (potential)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationBias</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>unknown total energy per arc</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit differentiation  by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">covariancePod</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits</td></tr>\n</table>\n\n<h2 id=\"sstVariational\">SstVariational</h2><p>\nLike <a class=\"groops-class\" href=\"observationType.html#podVariational\">observation:podVariational</a> (see there for details)\nbut with two satellites and additional satellite-to-satellite (SST) observations.</p><p>If multiple <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a> are given,\nall data are added together. So corrections in extra files like the light time correction\ncan easily be added. Empirical parameters for the SST observations can be set up with\n<a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>.\nThe accuracy or the full covariance matrix of SST is provided in\n<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.velocity0.z::</code>.\n</li><li>\n<code>&lt;satellite2>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.velocity0.z::</code>.\n</li><li>\n<code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking>:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit1</div></div></td><td>filename</td><td>kinematic positions of satellite A as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit2</div></div></td><td>filename</td><td>kinematic positions of satellite B as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational1</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational2</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationSst</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst</div></div></td><td><a href=\"covarianceSstType.html\">covarianceSst</a></td><td>covariance matrix of satellite to satellite tracking observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod1</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod2</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 2)</td></tr>\n</table>\n\n<h2 id=\"sstIntegral\">SstIntegral</h2><p>\nLike <a class=\"groops-class\" href=\"observationType.html#podIntegral\">observation:podIntegral</a> (see there for details)\nbut with two satellites and additional satellite-to-satellite (SST) observations.</p><p>If multiple <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a> are given\nall data are added together. So corrections in extra files like the light time correction\ncan easily be added. Empirical parameters for the SST observations can be set up with\n<a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst</a>.\nThe accuracy or the full covariance matrix of SST is provided in\n<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite2>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking>:*:*</code>,\n</li></ul>\n\nand for each arc if <strong class=\"groops-config-element\">keepSatelliteStates</strong> is set\n<ul>\n\n<li><code>&lt;satellite1>:arc&lt;no>.position.start.x::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position.start.y::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position.start.z::</code>.\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position.end.x::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position.end.y::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position.end.z::</code>.\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position.start.x::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position.start.y::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position.start.z::</code>.\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position.end.x::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position.end.y::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position.end.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel1</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileSatelliteModel2</div></div></td><td>filename</td><td>satellite macro model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"sstRightSideType.html\">sstRightSide</a></td><td>input for the reduced observation vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeAcceleration</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit1</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit2</div></div></td><td>filename</td><td>used to evaluate the observation equations, not used as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera1</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera2</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gradientfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>low order field to estimate the change of the gravity by position adjustement</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationSst</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">keepSatelliteStates</div></div></td><td>boolean</td><td>set boundary values of each arc global</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst</div></div></td><td><a href=\"covarianceSstType.html\">covarianceSst</a></td><td>covariance matrix of satellite to satellite tracking observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod1</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 1)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod2</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 2)</td></tr>\n</table>\n\n<h2 id=\"dualSstVariational\">DualSstVariational</h2><p>\nLike <a class=\"groops-class\" href=\"observationType.html#sstVariational\">observation:sstVariational</a> (see there for details)\nbut with two simultaneous satellite-to-satellite (SST) observations.</p><p>This class reads two SST observation files (<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking1</a> and\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking2</a>).\nEmpirical parameters for the SST observations can be set up independently for both SST observation\ntypes with <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst1</a> and\n<a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrizationSst2</a>.</p><p>Both SST observation types are reduced by the same background models and the same impact\nof accelerometer measurements. The covariance matrix of the reduced observations should not consider\nthe instrument noise only (<a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceSst1/2</a>) but must\ntake the cross correlations <a class=\"groops-class\" href=\"covarianceSstType.html\">covarianceAcc</a> into account.\nThe covariance matrix of the reduced observations is given by\n\\[\n  \\M\\Sigma(\\begin{bmatrix} \\Delta l_{SST1} \\\\ \\Delta l_{SST2} \\end{bmatrix})\n  = \\begin{bmatrix} \\M\\Sigma_{SST1} + \\M\\Sigma_{ACC} & \\M\\Sigma_{ACC} \\\\\n                   \\M\\Sigma_{ACC} & \\M\\Sigma_{SST2} + \\M\\Sigma_{ACC}\n    \\end{bmatrix}.\n\\]\nThe following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;satellite1>:arc&lt;no>.velocity0.z::</code>.\n</li><li>\n<code>&lt;satellite2>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;satellite2>:arc&lt;no>.velocity0.z::</code>.\n</li><li>\n<code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking1>:*:*</code>.\n</li><li>\n<code>&lt;satellite1>.&lt;satellite2>:&lt;parametrizationSatelliteTracking2>:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking1</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteTracking2</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit1</div></div></td><td>filename</td><td>kinematic positions of satellite A as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit2</div></div></td><td>filename</td><td>kinematic positions of satellite B as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sstType</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">range</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rangeRate</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">none</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational1</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational2</div></div></td><td>filename</td><td>approximate position and integrated state matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>gravity field parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration1</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit1 force parameters</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration2</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit2 force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationSst1</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter for first ranging observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationSst2</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td>satellite tracking parameter for second ranging observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>orbit interpolation by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst1</div></div></td><td><a href=\"covarianceSstType.html\">covarianceSst</a></td><td>covariance matrix of first satellite to satellite tracking observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSst2</div></div></td><td><a href=\"covarianceSstType.html\">covarianceSst</a></td><td>covariance matrix of second satellite to satellite tracking observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">covarianceAcc</div></div></td><td><a href=\"covarianceSstType.html\">covarianceSst</a></td><td>common covariance matrix of reduced satellite to satellite tracking observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod1</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covariancePod2</div></div></td><td><a href=\"covariancePodType.html\">covariancePod</a></td><td>covariance matrix of kinematic orbits (satellite 2)</td></tr>\n</table>\n\n<h2 id=\"gradiometer\">Gradiometer</h2><p>\nObservation equations for satellite gravity gradiometry (SGG)\n\\[\n  \\nabla\\nabla V(\\M r) =\n  \\begin{pmatrix}\n    \\frac{\\partial^2 V}{\\partial x^2}         & \\frac{\\partial^2 V}{\\partial x\\partial y} & \\frac{\\partial^2 V}{\\partial x\\partial z} \\\\\n    \\frac{\\partial^2 V}{\\partial y\\partial x} & \\frac{\\partial^2 V}{\\partial y^2}         & \\frac{\\partial^2 V}{\\partial y\\partial z} \\\\\n    \\frac{\\partial^2 V}{\\partial z\\partial x} & \\frac{\\partial^2 V}{\\partial z\\partial y} & \\frac{\\partial^2 V}{\\partial z^2}\n  \\end{pmatrix}.\n\\]From the <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileGradiometer</a> observations precomputed <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileReferenceGradiometer</a>\ntogether with other background models are reduced, all given in <a class=\"groops-class\" href=\"sggRightSideType.html\">rightHandSide</a>.</p><p>All instrument data <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileGradiometer</a>, <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileOrbit</a>,\nand <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStarCamera</a> must be synchronous and be diveded\ninto each short arcs (see <a class=\"groops-program\" href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a>).</p><p>Additional to the <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>\nan (temporal changing) bias for each gradiometer component and arc can be estimated with\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationBias</a>.</p><p>The accuracy or the full covariance matrix of the gradiometer is provided in\n<strong class=\"groops-config-element\">covarianceSgg</strong> and can be estimated with <a class=\"groops-program\" href=\"PreprocessingGradiometer.html\">PreprocessingGradiometer</a>.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<code>*:&lt;parametrizationGravity>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">rightHandSide</div></div></td><td><a href=\"sggRightSideType.html\">sggRightSide</a></td><td>input for the observation vector</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStarCamera</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">earthRotation</div></div></td><td><a href=\"earthRotationType.html\">earthRotation</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationBias</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>per arc</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useXX</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useYY</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useZZ</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useXY</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useXZ</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useYZ</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">covarianceSgg</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>double</td><td>general variance factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileSigmasPerArc</div></div></td><td>filename</td><td>different accuaries for each arc (multplicated with sigma)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileCovarianceFunction</div></div></td><td>filename</td><td>covariance function in time</td></tr>\n</table>\n\n<h2 id=\"terrestrial\">Terrestrial</h2><p>\nThe gravity field is estimated from point wise measurements.\nThe gravity field parametrization is given by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.\nThere is no need to have the data regular distributed or given on a sphere or ellipsoid.\nThe type of the gridded data (e.g gravity anomalies or geoid heights)\nmust be set with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nA <a class=\"groops-class\" href=\"gravityfieldType.html\">referencefield</a> can be reduced beforehand.</p><p>The observations at given positions are calculated from\n<a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\nThe input columns are enumerated by <code>data0</code>, <code>data1</code>, &hellip; ,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The observations can be divided into small blocks for parallelization.\nWith <strong class=\"groops-config-element\">blockingSize</strong> set the maximum count of observations in each block.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<code>*:&lt;parametrizationGravity>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observation</div></div></td><td>expression</td><td>[SI units]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigma</div></div></td><td>expression</td><td>accuracy, 1/sigma used as weighting</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">referencefield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>type of observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>for reference field and parametrization</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">blockingSize</div></div></td><td>uint</td><td>segementation of the obervations if designmatrix can't be build at once</td></tr>\n</table>\n\n<h2 id=\"deflections\">Deflections</h2><p>\nThe gravity field parametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>\nis estimated from deflections of the vertical measurements.\nA <a class=\"groops-class\" href=\"gravityfieldType.html\">referencefield</a> can be reduced beforehand.</p><p>The observations $\\xi$ in north direction and $\\eta$ in east direction\nat given positions are calculated from\n<a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\nThe input columns are enumerated by <code>data0</code>, <code>data1</code>, &hellip; ,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are used\nto define the local normal direction.</p><p>The observations can be divided into small blocks for parallelization.\nWith <strong class=\"groops-config-element\">blockingSize</strong> set the maximum count of observations in each block.</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<code>*:&lt;parametrizationGravity>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationXi</div></div></td><td>expression</td><td>North-South Deflections of the Vertical [rad]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationEta</div></div></td><td>expression</td><td>East-West Deflections of the Vertical  [rad]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigmaXi</div></div></td><td>expression</td><td>accuracy, 1/sigma used as weighting</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigmaEta</div></div></td><td>expression</td><td>accuracy, 1/sigma used as weighting</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">referencefield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>for reference field and parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoid</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoid, 0: sphere</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">blockingSize</div></div></td><td>uint</td><td>segementation of the obervations if designmatrix can't be build at once</td></tr>\n</table>\n\n<h2 id=\"stationLoading\">StationLoading</h2><p>\nObservation equations for displacements of a list of stations\ndue to the effect of time variable loading masses. The displacement $\\M u$ of a station is calculated according to\n\\[\n\\M u(\\M r) = \\frac{1}{\\gamma}\\sum_{n=0}^\\infty \\left[\\frac{h_n}{1+k_n}V_n(\\M r)\\,\\M e_{up}\n+ R\\frac{l_n}{1+k_n}\\left(\n \\frac{\\partial V_n(\\M r)}{\\partial \\M e_{north}}\\M e_{north}\n+\\frac{\\partial V_n(\\M r)}{\\partial \\M e_{east}} \\M e_{east}\\right)\\right],\n\\]where $\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileDeformationLoadLoveNumber</a> and the load Love numbers $k_n$ are given by\n<a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfilePotentialLoadLoveNumber</a>.\nThe $V_n$ are the spherical harmonics expansion of degree $n$ of the full time variable\ngravitational potential (potential of the loading mass + deformation potential)\nparametrized by <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.\nAdditional parameters can be setup to estimate the realization of the reference frame\nof the station coordinates (<strong class=\"groops-config-element\">estimateTranslation</strong>,\n<strong class=\"groops-config-element\">estimateRotation</strong>, and <strong class=\"groops-config-element\">estimateScale</strong>).</p><p>The observations at stations coordinates are calculated from\n<a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\nThe input columns are enumerated by <code>data0</code>, <code>data1</code>, &hellip; ,\nsee <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>.</p><p>The ellipsoid parameters <strong class=\"groops-config-element\">R</strong> and <strong class=\"groops-config-element\">inverseFlattening</strong> are used\nto define the local frame (north, east, up).</p><p>The following parameters with <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are set up:\n<ul>\n\n<li><code>*:&lt;parametrizationGravity>:*:*</code>,\n</li><li>\n<code>*:translation.x:*:*</code>,\n</li><li>\n<code>*:translation.y:*:*</code>,\n</li><li>\n<code>*:translation.z:*:*</code>,\n</li><li>\n<code>*:scale:*:*</code>,\n</li><li>\n<code>*:rotation.x:*:*</code>,\n</li><li>\n<code>*:rotation.y:*:*</code>,\n</li><li>\n<code>*:rotation.z:*:*</code>.\n</li></ul>\n</p><p>See also <a class=\"groops-program\" href=\"Gravityfield2DisplacementTimeSeries.html\">Gravityfield2DisplacementTimeSeries</a>.</p><p>Reference:\nRietbroek (2014): Retrieval of Sea Level and Surface Loading Variations from Geodetic Observations\nand Model Simulations: an Integrated Approach, Bonn, 2014. - Dissertation,\n<a href=\"https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460\" target=\"_blank\">https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">rightHandSide</div></div></td><td>sequence</td><td>input for observation vectors</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>station positions with displacement data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationNorth</div></div></td><td>expression</td><td>displacement [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationEast</div></div></td><td>expression</td><td>displacement [m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">observationUp</div></div></td><td>expression</td><td>displacement [m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigmaNorth</div></div></td><td>expression</td><td>accuracy, 1/sigma used as weighting</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigmaEast</div></div></td><td>expression</td><td>accuracy, 1/sigma used as weighting</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">sigmaUp</div></div></td><td>expression</td><td>accuracy, 1/sigma used as weighting</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inGlobalFrame</div></div></td><td>boolean</td><td>obs/sigmas given in global x,y,z frame instead of north,east,up</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">referencefield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>for reference field and parametrization</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td>of loading (+defo) potential</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateTranslation</div></div></td><td>boolean</td><td>coordinate center</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateScale</div></div></td><td>boolean</td><td>scale factor of position</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateRotation</div></div></td><td>boolean</td><td>rotation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDeformationLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfilePotentialLoadLoveNumber</div></div></td><td>filename</td><td>if full potential is given and not only loading potential</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius for ellipsoid</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inverseFlattening</div></div></td><td>double</td><td>reference flattening for ellipsoid, 0: sphere</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/orbitPropagatorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - orbitPropagatorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"orbitPropagatorType\">OrbitPropagator</h1><p>\nImplements the propagation of a satellite orbit under\nthe influence of <a class=\"groops-class\" href=\"forcesType.html\">forces</a> as\nused in <a class=\"groops-program\" href=\"SimulateOrbit.html\">SimulateOrbit</a>\n(dynamic orbits from numerical orbit integration).\n</p>\n\n<h2>Euler</h2><p>\nThis class implements Euler's method to propagate a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>.\nSatellite is assumed to be oriented along-track.\n</p>\n\n<h2>RungeKutta4</h2><p>\nThis class implements the classical Runge-Kutta 4 method of orbit propagation\nfor satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>.\nNo step-width control or other advanced features are implemented.\nSatellite is assumed to be oriented along-track.\nSee: Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n</p>\n\n<h2>AdamsBashforthMoulton</h2><p>\nThis class implements the Adams-Moulton class of predictor-corrector orbit propagators\nfor a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a> using an implicit\nAdams-Bashforth corrector. The coefficients for the propagator are derived using the equations\ngiven in section 4.2.3 of [1]. Satellite is assumed to be oriented along-track.\n[1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td>Order of the Adams-Bashforth type propagator.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">applyMoultonCorrector</div></div></td><td>boolean</td><td>Corrector step after Adams-Bashforth predcition.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">warmup</div></div></td><td><a href=\"orbitPropagatorType.html\">orbitPropagator</a></td><td></td></tr>\n</table>\n\n<h2>StoermerCowell</h2><p>\nThis class implements the Stoermer-Cowell class of predictor-corrector orbit propagators for a satellite orbit\nunder the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. The coefficients for the Stoermer predictor and Cowell corrector\nare derived using the equations given in section 4.2.6 of [1]. Stoermer-Cowell is a double integration algorithm,\nyielding positions directly from accelertions. It does not produce velocities. The velocities are derived using\nAdams-type propagators as suggested in [2]. Satellite is assumed to be oriented along-track.\n[1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n[2] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td>Order of the Stoermer-Cowell type propagator.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">warmup</div></div></td><td><a href=\"orbitPropagatorType.html\">orbitPropagator</a></td><td></td></tr>\n</table>\n\n<h2>GaussJackson</h2><p>\nThis class implements the Gauss-Jackson multi-step predictor-corrector method to\npropagate a satellite orbit under the influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>.\nSatellite is assumed to be oriented along-track. Implementation is based on [1].\n[1] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td>of Gauss-Jackson method.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">warmup</div></div></td><td><a href=\"orbitPropagatorType.html\">orbitPropagator</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">correctorIterations</div></div></td><td>uint</td><td>Maximum number of iterations to run the corrector step for.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">epsilon</div></div></td><td>double</td><td>Convergence criteria for position, velocity, and acceleration tests.</td></tr>\n</table>\n\n<h2 id=\"Polynomial\">Polynomial</h2><p>\nThis class implements an integration Polynomial method to propagate a satellite orbit under\nthe influence of <a class=\"groops-class\" href=\"forcesType.html\">Forces</a>. Satellite is assumed to be oriented along-track.\nImplementation is based on code by Torsten Mayer-Gürr.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">degree</div></div></td><td>uint</td><td>polynomial degree to integrate accelerations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">shift</div></div></td><td>int</td><td>shift polynomial in future (predicted accelerations)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">epsilon</div></div></td><td>double</td><td>[m] max. position change to recompute forces</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">warmup</div></div></td><td><a href=\"orbitPropagatorType.html\">orbitPropagator</a></td><td>to compute epochs before start epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">corrector</div></div></td><td>boolean</td><td>apply corrector iteration if position change is larger than epsilon</td></tr>\n</table>\n\n<h2>File</h2><p>\nReads an orbit from file. If the needed epochs are not given an exception is thrown.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>epoch at timeStart is not used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">margin</div></div></td><td>double</td><td>[seconds] to find identical times</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">recomputeForces</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parameterNamesType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parameterNamesType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parameterNamesType\">ParameterNames</h1><p>\nGenerates a list of parameter names. All parameters are appended.\n</p>\n\n<h2>Name</h2><p>\nThe parameter is given explicitly by four parts:\n<ol>\n\n<li>object: Object this parameter refers to, e.g. <code>graceA</code>, <code>G023</code>, <code>earth</code>, &hellip; </li><li>\ntype: Type of this parameter, e.g. <code>accBias</code>, <code>position.x</code>, &hellip; </li><li>\ntemporal: Temporal representation of this parameter, e.g. <code>trend</code>, <code>polynomial.degree1</code>, &hellip; </li><li>\ninterval: Interval/epoch this parameter represents, e.g. <code>2017-01-01_00-00-00_2017-01-02_00-00-00</code>, <code>2018-01-01_00-00-00</code>.\n</li></ol>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>object this parameter refers to, e.g. graceA, G023, earth</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">type</div></div></td><td>string</td><td>type of this parameter, e.g. accBias, position.x</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">temporal</div></div></td><td>string</td><td>temporal representation of this parameter, e.g. trend, polynomial.degree1</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interval</div></div></td><td>string</td><td>interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00</td></tr>\n</table>\n\n<h2>File</h2><p>\nRead parameter names from <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileParameterNames</div></div></td><td>filename</td><td>file with parameter names</td></tr>\n</table>\n\n<h2>Gravity</h2><p>\nParameter names of gravity <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrization</a>.\nAn additional <strong class=\"groops-config-element\">object</strong> name can be included in the parameter names.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>object these parameters refers to, e.g. earth</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n</table>\n\n<h2>Acceleration</h2><p>\nParameter names of satellite acceleration <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrization</a>.\nArc related parameters are appended if an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileInstrument</a> is provided which\ndefines the arc structure.\nAn additional <strong class=\"groops-config-element\">object</strong> name can be included in the parameter names.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>object these parameters refers to, e.g. graceA, G023</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterization</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileInstrument</div></div></td><td>filename</td><td>defines the arc structure for arc related parameters</td></tr>\n</table>\n\n<h2>SatelliteTracking</h2><p>\nParameter names of satellite tracking <a class=\"groops-class\" href=\"parametrizationSatelliteTrackingType.html\">parametrization</a>.\nAn additional <strong class=\"groops-config-element\">object</strong> name can be included in the parameter names.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>object these parameters refers to, e.g. grace1.grace2</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterization</div></div></td><td><a href=\"parametrizationSatelliteTrackingType.html\">parametrizationSatelliteTracking</a></td><td></td></tr>\n</table>\n\n<h2>Temporal</h2><p>\nParameter names from temporal parametrization.\nIt is possible to setup the temporal parameters for each <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterNameBase</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parameterNameBase</div></div></td><td><a href=\"parameterNamesType.html\">parameterNames</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n</table>\n\n<h2>GnssAntenna</h2><p>\nParameter names of GNSS antenna center variation <a class=\"groops-class\" href=\"parametrizationGnssAntennaType.html\">parametrization</a>.\nAn additional <strong class=\"groops-config-element\">object</strong> name (antenna name) can be included in the parameter names.\nIt is possible to setup the parameters for each <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>antenna name</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"parametrizationGnssAntennaType.html\">parametrizationGnssAntenna</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">gnssType</div></div></td><td><a href=\"gnssType.html\">gnssType</a></td><td>e.g. C1CG**</td></tr>\n</table>\n\n<h2>Observation</h2><p>\nParameter names used in <a class=\"groops-class\" href=\"observationType.html\">observation equations</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">observation</div></div></td><td><a href=\"observationType.html\">observation</a></td><td></td></tr>\n</table>\n\n<h2>Rename</h2><p>\nReplaces parts of <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>s.\nThe star \"<code>*</code>\" left this part untouched.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterName</div></div></td><td><a href=\"parameterNamesType.html\">parameterNames</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>*: left this part untouched, object</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">type</div></div></td><td>string</td><td>*: left this part untouched, type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">temporal</div></div></td><td>string</td><td>*: left this part untouched, temporal representation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interval</div></div></td><td>string</td><td>*: left this part untouched, interval/epoch</td></tr>\n</table>\n\n<h2>Selection</h2><p>\nSelect a subset of <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>s\nusing <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterName</div></div></td><td><a href=\"parameterNamesType.html\">parameterNames</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection</td></tr>\n</table>\n\n<h2>WithoutDuplicates</h2><p>\nRemoves all duplicate names (keep first) from <a class=\"groops-class\" href=\"parameterNamesType.html\">parameterName</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterName</div></div></td><td><a href=\"parameterNamesType.html\">parameterNames</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parameterSelectorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parameterSelectorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parameterSelectorType\">ParameterSelector</h1><p>\nThis class provides an index vector from selected parameters,\nwhich can be used e.g. to reorder a normal equation matrix.\nThe size of the index vector determines the size of the new matrix.\nEntries are the indices of the selected parameters in the provided\nparameter list or NULLINDEX for zero/new parameters.\n</p>\n\n<h2 id=\"wildcard\">Wildcard</h2><p>\nParameter index vector from name. Name matching supports wildcards * for any number of characters and ? for exactly one character.\nDoes not add zero/empty parameters if there are no matches.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">object</div></div></td><td>string</td><td>object this parameter refers to, e.g. graceA, G023, earth (wildcards: * and ?)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">type</div></div></td><td>string</td><td>type of this parameter, e.g. accBias, position.x (wildcards: * and ?)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">temporal</div></div></td><td>string</td><td>temporal representation of this parameter, e.g. trend, polynomial.degree1 (wildcards: * and ?)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interval</div></div></td><td>string</td><td>interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00 (wildcards: * and ?)</td></tr>\n</table>\n\n<h2>Names</h2><p>\nParameter index vector from list of parameter names.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterName</div></div></td><td><a href=\"parameterNamesType.html\">parameterNames</a></td><td></td></tr>\n</table>\n\n<h2>Range</h2><p>\nParameter index vector from range.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">start</div></div></td><td>expression</td><td>start at this index (variables: length)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">count</div></div></td><td>expression</td><td>count of parameters, default: all parameters to the end (variables: length)</td></tr>\n</table>\n\n<h2>Matrix</h2><p>\nParameter index vector from matrix.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>index in old parameter list or -1 for new parameter</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">column</div></div></td><td>expression</td><td>use this column (counting from 0, variables: columns)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">startRow</div></div></td><td>expression</td><td>start at this row (counting from 0, variables: rows)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">countRows</div></div></td><td>expression</td><td>use these many rows (default: use all, variables: rows)</td></tr>\n</table>\n\n<h2>Zeros</h2><p>\nExpand parameter index vector by adding zero parameters.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">count</div></div></td><td>expression</td><td>count of zero parameters (variables: length)</td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nGroups a set of <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameterSelection</a>s and has no further effect itself.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection</td></tr>\n</table>\n\n<h2 id=\"complement\">Complement</h2><p>\nParameter index vector from a complement of other parameter selector(s).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameterSelection</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parametrizationAccelerationType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parametrizationAccelerationType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parametrizationAccelerationType\">ParametrizationAcceleration</h1><p>\nThis class defines parameters of satellite accelerations.\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n</p>\n\n<h2 id=\"perRevolution\">PerRevolution</h2><p>\nOscillation once, twice, ... per revolution in Satellite Reference Frame (SRF)\nwith the argument of latitude as input angle.  If the attitude of the satellite\nis not provided the Celestial Reference Frame (CRF) is used instead.\nParamters are estimated in $[nm/s^2=10^{-9}\\,m/s^2]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:perRevolution.cos(&lt;order>*u).x::&lt;interval></code>,\n</li><li>\n<code>*:perRevolution.cos(&lt;order>*u).y::&lt;interval></code>,\n</li><li>\n<code>*:perRevolution.cos(&lt;order>*u).z::&lt;interval></code>,\n</li><li>\n<code>*:perRevolution.sin(&lt;order>*u).x::&lt;interval></code>,\n</li><li>\n<code>*:perRevolution.sin(&lt;order>*u).y::&lt;interval></code>,\n</li><li>\n<code>*:perRevolution.sin(&lt;order>*u).z::&lt;interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">order</div></div></td><td>uint</td><td>once, twice, ...</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateX</div></div></td><td>boolean</td><td>along</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateY</div></div></td><td>boolean</td><td>cross</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateZ</div></div></td><td>boolean</td><td>radial</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">interval</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>setup new parameters each interval</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"accBias\">AccBias</h2><p>\nTemporal changing accelerometer bias per axis in $[m/s^2]$ in Satellite Reference Frame (SRF).\nIf the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:accBias.x:*:*</code>,\n</li><li>\n<code>*:accBias.y:*:*</code>,\n</li><li>\n<code>*:accBias.z:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateX</div></div></td><td>boolean</td><td>along</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateY</div></div></td><td>boolean</td><td>cross</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateZ</div></div></td><td>boolean</td><td>radial</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"accelerometerScaleFactors\">AccelerometerScaleFactors</h2><p>\nAccelerometer scale factor per axis.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:accScale.x:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScale.y:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScale.z:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScaleCross.xy:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScaleCross.xz:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScaleCross.yz:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScaleRotation.xy:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScaleRotation.xz:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>*:accScaleRotation.yz:&lt;temporal>:&lt;interval></code>.\n</li></ul>\n</p><p>This parametrization needs the attitude of the satellite.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileAccelerometer</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateX</div></div></td><td>boolean</td><td>along</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateY</div></div></td><td>boolean</td><td>cross</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateZ</div></div></td><td>boolean</td><td>radial</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateCrossTalk</div></div></td><td>boolean</td><td>non-orthognality of axes</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateRotation</div></div></td><td>boolean</td><td>misalignment</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"gnssSolarRadiation\">GnssSolarRadiation</h2><p>\nGNSS solar radiation pressure model. Paramters are estimated in $[nm/s^2=10^{-9}\\,m/s^2]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:solarRadiationPressure.ECOM.D0:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.DC2:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.DS2:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.DC4:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.DS4:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.Y0:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.B0:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.BC1:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.BS1:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.BC3:*:*</code>,\n</li><li>\n<code>*:solarRadiationPressure.ECOM.BS3:*:*</code>.\n</li></ul>\n</p><p>This parametrization needs the attitude of the satellite.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateD0</div></div></td><td>boolean</td><td>constant term along D-axis (sat-sun vector)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateD2</div></div></td><td>boolean</td><td>2-per-rev terms along D-axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateD4</div></div></td><td>boolean</td><td>4-per-rev terms along D-axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateY0</div></div></td><td>boolean</td><td>constant term along Y-axis (solar panel axis)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateB0</div></div></td><td>boolean</td><td>constant term along B-axis (cross product D x Y)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateB1</div></div></td><td>boolean</td><td>1-per-rev terms along B-axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateB3</div></div></td><td>boolean</td><td>3-per-rev terms along B-axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">eclipse</div></div></td><td><a href=\"eclipseType.html\">eclipse</a></td><td></td></tr>\n</table>\n\n<h2 id=\"thermosphericDensity\">ThermosphericDensity</h2><p>\nEstimate the thermospheric density along the orbit using a satllite macro model.\nAn optional thermospheric model can be used to compute temperature and wind.\nThe temperature is used to estimate variable drag and lift coefficients, otherwise a constant drag coefficient is used.\nThe density is estimated in $[kg/m^3]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:density:&lt;temporal>:&lt;interval></code>.</p><p>This parametrization needs the macro model and the attitude of the satellite.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">thermosphere</div></div></td><td><a href=\"thermosphereType.html\">thermosphere</a></td><td>for wind and temperature</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">earthRotation</div></div></td><td>double</td><td>[rad/s]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerTemperature</div></div></td><td>boolean</td><td>compute drag and lift, otherwise simple drag coefficient is used</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">considerWind</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporalDensity</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>parameters along orbit</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"modelScale\">ModelScale</h2><p>\nEstimate a scale factor for a given model.\nThe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:modelScale:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">miscAccelerations</div></div></td><td><a href=\"miscAccelerationsType.html\">miscAccelerations</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parametrizationGnssAntennaType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parametrizationGnssAntennaType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parametrizationGnssAntennaType\">ParametrizationGnssAntenna</h1><p>\nParametrization of antenna center variations. It will be used to set up the design matrix in a least squares adjustment.\nUsually the parametrization is setup separately for different <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>.</p><p>If multiple parametrizations are given the parameters are sequently appended in the design matrix and parameter vector.\n</p>\n\n<h2 id=\"center\">Center</h2><p>\nAntenna center or, if setup for a specific <a class=\"groops-class\" href=\"gnssType.html\">gnssType</a>,\nphase/code center offset (e.g. <code>*1*G</code> for GPS L1 phase center offset) in $[m]$.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:antennaCenter.x:*:*</code>,\n</li><li>\n<code>*:antennaCenter.y:*:*</code>,\n</li><li>\n<code>*:antennaCenter.z:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateX</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateY</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimateZ</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2>SphericalHarmonics</h2><p>\nParametrization of antenna center variations in $[m]$ in terms of spherical harmonics.\nAs usually only data above the horizon are observed only the even spherical harmonics\n(degree/order $m+n$ even), which are symmetric to the equator, are setup.</p><p>The total count of parameters is $((n_{max}+1)(n_{max}+2)-n_{min}(n_{min}+1)/2$ and\nthe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:antennaCenterVariations.sphericalHarmonics.c_&lt;degree>_&lt;order>:*:*</code>,\n</li><li>\n<code>*:antennaCenterVariations.sphericalHarmonics.s_&lt;degree>_&lt;order>:*:*</code>.\n</li></ul>\n</p><p></p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td>min degree</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>max degree</td></tr>\n</table>\n\n<h2>RadialBasis</h2><p>\nParametrization of antenna center variations with radial basis functions\n\\[\n  ACV(\\M x(A, E)) = \\sum_i a_i \\Phi(\\M x\\cdot\\M x_i)\n\\]where $a_i$ in $[m]$ the coefficients which has to be estimated and $\\Phi$ are the basis\nfunctions\n\\[\n  \\Phi(\\cos\\psi) = \\sum_n \\sqrt{2n+1}P_n(\\cos\\psi).\n\\]\nThe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<code>*:antennaCenterVariations.radialBasis.&lt;index>.&lt;total count>:*:*</code>.</p><p><figure><img class=\"figure\" style=\"width:40%;\" src=\"../figures/parametrizationGnssAntennaRadialBasis.png\" alt=\"parametrizationGnssAntennaRadialBasis\"><figcaption class=\"center\">Figure: Nodal points of the basis functions\nusing a Reuter grid for transmitting satellites (view angle of 18 deg). The red line indicates the view angle of 14 deg of ground stations.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td>nodal points of shannon kernels</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td>min degree of shannon kernel</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>max degree of shannon kernel</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parametrizationGravityType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parametrizationGravityType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parametrizationGravityType\">ParametrizationGravity</h1><p>\nThis class gives a parametrization of the time depending gravity field.\nTogether with the class <a class=\"groops-class\" href=\"observationType.html\">oberservation</a> it will be used\nto set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n</p>\n\n<h2 id=\"sphericalHarmonics\">SphericalHarmonics</h2><p>\nThe potential $V$ is parametrized by a expansion of (fully normalized) spherical harmonics\n\\[\nV(\\lambda,\\vartheta,r) = \\frac{GM}{R}\\sum_{n=0}^\\infty \\sum_{m=0}^n \\left(\\frac{R}{r}\\right)^{n+1}\n  \\left(c_{nm} C_{nm}(\\lambda,\\vartheta) + s_{nm} S_{nm}(\\lambda,\\vartheta)\\right).\n\\]You can set the range of degree $n$ with <strong class=\"groops-config-element\">minDegree</strong> and <strong class=\"groops-config-element\">maxDegree</strong>.\nThe sorting sequence of the potential coefficients in the parameter vector can be defined by\n<a class=\"groops-class\" href=\"sphericalHarmonicsNumberingType.html\">numbering</a>.</p><p>The total count of parameters is $(n_{max}+1)^2-n_{min}^2$ and\nthe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:sphericalHarmonics.c_&lt;degree>_&lt;order>:*:*</code>,\n</li><li>\n<code>*:sphericalHarmonics.s_&lt;degree>_&lt;order>:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme</td></tr>\n</table>\n\n<h2 id=\"radialBasis\">RadialBasis</h2><p>\nThe potential $V$ is represented by a sum of space localizing basis functions\n\\[\n  V(\\M x) = \\sum_i a_i \\Phi(\\M x, \\M x_i)\n\\]where $a_i$ the coefficients which has to be estimated and $\\Phi$ are the basis\nfunctions given by isotropic radial <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> functions\n\\[\n  \\Phi(\\cos\\psi,r,R) = \\sum_n \\left(\\frac{R}{r}\\right)^{n+1} k_n\\sqrt{2n+1}\\bar{P}_n(\\cos\\psi).\n\\]The basis functions are located on a grid $\\M x_i$ given by <a class=\"groops-class\" href=\"gridType.html\">grid</a>.\nThis class can also be used to estimate point masses if <a class=\"groops-class\" href=\"kernelType.html\">kernel</a> is set to density.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:radialBasis.&lt;index>.&lt;total count>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td>shape of the radial basis function</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">grid</div></div></td><td><a href=\"gridType.html\">grid</a></td><td>nodal point distribution</td></tr>\n</table>\n\n<h2>Temporal</h2><p>\nThe time variable potential is given by\n\\[\n  V(\\M x,t) = \\sum_i V_i(\\M x)\\Psi_i(t),\n\\]wehre $V_i(\\M x)$ is the spatial parametrization of the gravity field\nand can be choosen with <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.\nThe parametrization in time domain $\\Psi_i(t)$ is selected by\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.\nThe total parameter count is the parameter count of <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>\ntimes the parameter count of <a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrizationGravity</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravity</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationTemporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n</table>\n\n<h2>LinearTransformation</h2><p>\nParametrization of the gravity field on the basis of a linear transformation of a source parametrization.\nThe linear transformation changes the original solution space represented by\n<a class=\"groops-class\" href=\"parametrizationGravityType.html\">pararametrizationGravitySource</a> from\n\\[\n  \\mathbf{l} = \\mathbf{A}\\mathbf{x} + \\mathbf{e}\n\\]to\n\\[\n  \\mathbf{l} = \\mathbf{A}\\mathbf{F}\\mathbf{y} + \\mathbf{e}\n\\]through the linear transformation $\\mathbf{x}=\\mathbf{F}\\mathbf{y}$.\nIt follows that the rows of the matrix $\\mathbf{F}$ in <a class=\"groops-file\" href=\"fileFormat_matrix.html\">inputfileTransformationMatrix</a> coincides with\nthe number of parameters in <a class=\"groops-class\" href=\"parametrizationGravityType.html\">pararametrizationGravitySource</a>.\nThe new parameter count is given by the number of columns in $\\mathbf{F}$ and may be smaller, equal or larger\nthan the original parameter count.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:transformedParameter.&lt;index>.&lt;total count>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrizationGravitySource</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTransformationMatrix</div></div></td><td>filename</td><td>transformation matrix from target to source parametrization (rows of this matrix must coincide with the parameter count of the source parametrization)</td></tr>\n</table>\n\n<h2>EarthquakeOscillation</h2><p>\nThis class is used to estimate the earthquake oscillation function parameters,\ni.e. $C_{nlm}$, $\\omega_{nlm}$, and $P_{nlm}$.\nThe results describes the variation in the gravitational potential field caused by large earthquakes.\n\\[\nC_{lm}(\\M t) = \\sum_{n=0}^NC_{nlm}(1-\\cos(\\omega_{nlm}d\\M t)\\exp(P_{nlm}\\omega_{nlm}d\\M t)),\n\\]with $\\omega_{nlm}=\\frac{2\\pi}{T_{nlm}}$ and $P_{nlm}=\\frac{-1}{2Q_{nlm}}$ . In this equation, $Q_{nlm}$ is the attenuation factor,\n$n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time after earthquake in second.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>*:earthquakeParameter.c_&lt;degree>_&lt;order>_A:*:*</code>,\n</li><li>\n<code>*:earthquakeParameter.s_&lt;degree>_&lt;order>_A:*:*</code>,\n</li><li>\n<code>*:earthquakeParameter.c_&lt;degree>_&lt;order>_W:*:*</code>,\n</li><li>\n<code>*:earthquakeParameter.s_&lt;degree>_&lt;order>_W:*:*</code>,\n</li><li>\n<code>*:earthquakeParameter.c_&lt;degree>_&lt;order>_P:*:*</code>,\n</li><li>\n<code>*:earthquakeParameter.s_&lt;degree>_&lt;order>_P:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputInitialCoefficient</div></div></td><td>filename</td><td>initial values for oscillation parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time0</div></div></td><td>time</td><td>the time earthquake happened</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">GM</div></div></td><td>double</td><td>Geocentric gravitational constant</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">R</div></div></td><td>double</td><td>reference radius</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parametrizationSatelliteTrackingType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parametrizationSatelliteTrackingType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parametrizationSatelliteTrackingType\">ParametrizationSatelliteTracking</h1><p>\nThis class defines parameters of Satellite-to-Satellite tracking observations.\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n</p>\n\n<h2 id=\"antennaCenter\">AntennaCenter</h2><p>\nEstimate the KBR antenna phase centre (APC) coordinates in $[m]$ for each spacecraft in satellite reference frame (SRF)\nas constant per axis. The observation equations are computed by taking the derivative\nof the antenna offset correction equation w.r.t. the KBR APC coordinates.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>satellite1.satellite2:sstAntennaCenter1.x:*:*</code>,\n</li><li>\n<code>satellite1.satellite2:sstAntennaCenter1.y:*:*</code>,\n</li><li>\n<code>satellite1.satellite2:sstAntennaCenter1.z:*:*</code>,\n</li><li>\n<code>satellite1.satellite2:sstAntennaCenter2.x:*:*</code>,\n</li><li>\n<code>satellite1.satellite2:sstAntennaCenter2.y:*:*</code>,\n</li><li>\n<code>satellite1.satellite2:sstAntennaCenter2.z:*:*</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimate1X</div></div></td><td>boolean</td><td>along (satellite 1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimate1Y</div></div></td><td>boolean</td><td>cross (satellite 1)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimate1Z</div></div></td><td>boolean</td><td>nadir (satellite 1)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimate2X</div></div></td><td>boolean</td><td>along (satellite 2)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimate2Y</div></div></td><td>boolean</td><td>cross (satellite 2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">estimate2Z</div></div></td><td>boolean</td><td>nadir (satellite 2)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>differentiation by polynomial approximation of degree n</td></tr>\n</table>\n\n<h2 id=\"bias\">Bias</h2><p>\nEstimate bias for SST observations in $[m]$ or $[m/s$]. The temporal variation is defined by\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:sstBias:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"scale\">Scale</h2><p>\nEstimate scale factor for SST observations with respect to reference SST data\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>.\nThe temporal variation is defined by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:sstScale:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteTracking</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"timeBias\">TimeBias</h2><p>\nEstimate time shift in seconds in SST observations, with defined temporal variation\nby <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.\nThe design matrix is computed by taking the derivative of the ranging data w.r.t. time.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:sstTimeBias:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>polynomial degree</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"scaleModel\">ScaleModel</h2><p>\nEstimate scale factors for deterministic signal models from satellite tracking instrument file <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileSatelliteTracking</a>, see <a class=\"groops-program\" href=\"EnsembleAveragingScaleModel.html\">EnsembleAveragingScaleModel</a>.\nAmplitude variation of model waveforms is defined by <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:scaleModel:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteTracking</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">perArc</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"specialEffect\">SpecialEffect</h2><p>\nEstimate deterministic signals in the GRACE K-Band measurements caused by Sun intrusions\ninto the star camera baffles of GRACE-A and eclipse transits of the satellites.\nThese events can be time-indexed beforehand using satellite position and orientation,\nsee <a class=\"groops-program\" href=\"GraceSstSpecialEvents.html\">GraceSstSpecialEvents</a>. The shape of this short-period waveform is nearly\nconstant within one month and can be approximated by a polynomial.\nThe amplitude variation of the waveform can also be taken into account\nby <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">parametrizationTemporal</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>satellite1.satellite2:&lt;type>.legendrePolynomial.n&lt;degree>:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileEvents</div></div></td><td>filename</td><td>instrument with GRACE events</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">eclipse1</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">eclipse2</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">starCameraBox1</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">starCameraBox2</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">starCameraBox3</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">starCameraBox4</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">starCameraBox5</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">starCameraBox6</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">marginLeft</div></div></td><td>double</td><td>margin size (on both sides) [seconds]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">marginRight</div></div></td><td>double</td><td>margin size (on both sides) [seconds]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minNumberOfEvents</div></div></td><td>uint</td><td>min. number of events to setup parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>polynomial degree</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">temporal</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/parametrizationTemporalType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - parametrizationTemporalType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"parametrizationTemporalType\">ParametrizationTemporal</h1><p>\nThis class gives a parametrization of time depending parameters (gravity field, positions, ...).\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.</p><p>Useally time intervals are defined half open meaning the last time belongs not to the interval.\nThis behaviour can be changed for the last interval with <strong class=\"groops-config-element\">includeLastTime</strong>.\n</p>\n\n<h2 id=\"constant\">Constant</h2><p>\nRepresents a parameter being constant in time in each <strong class=\"groops-config-element\">interval</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:*:*:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">interval</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">includeLastTime</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2 id=\"trend\">Trend</h2><p>\nA time variable function is given by a linear trend\n\\[\nf(x,t) = \\frac{1}{T}(t-t_0) \\cdot f_t(x),\n\\]with $t_0$ is <strong class=\"groops-config-element\">timeStart</strong> and $T$ is <strong class=\"groops-config-element\">timeStep</strong> in days.\nA constant term is not included and must added separately.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter name</a> is <code>*:*:trend.&lt;timeStep(days)>*(t-&lt;timeStart>):*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>reference time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStep</div></div></td><td>time</td><td></td></tr>\n</table>\n\n<h2 id=\"splines\">Splines</h2><p>\nA time variable function is given by\n\\[\nf(x,t) =  \\sum_i f_i(x)\\Psi_i(t),\n\\]with the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions $\\Psi_i(t)$.\nBasis splines are defined as polynomials of degree $n$ in intervals between nodal points in time $t_i$,\nfor details see <a class=\"groops-ref\" href=\"fundamentals.basisSplines.html\">basis splines</a>.</p><p>The parameters are ordered timewise. First all parameters of $f_{i=1}(x)$ then\n$f_{i=2}(x)$ and so on. The total parameter count in each <strong class=\"groops-config-element\">interval</strong> is $N=N_t+n-1$,\nwhere $N_t$ is the count of time points from <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> in each interval and $n$\nis the <strong class=\"groops-config-element\">degree</strong>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:*:spline.n&lt;degree>:&lt;interval of each spline></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">degree</div></div></td><td>uint</td><td>degree of splines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>nodal points in time domain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">intervals</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">includeLastTime</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2>Polynomial</h2><p>\nA time variable function is represented by Legendre polynomials in each <strong class=\"groops-config-element\">interval</strong>.\nThe time is normed to $[-1,1)$ in each interval.</p><p>The total parameter count is $(N+1)M$,\nwhere $N$ is the polynmial degree and $M$ the number of intervals with\nthe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> <code>*:*:legendrePolynomial.n&lt;degree>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">polynomialDegree</div></div></td><td>uint</td><td>polynomial degree</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">interval</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>intervals of polynomials</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">includeLastTime</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2>Oscillation</h2><p>\nA time variable function is given by a oscillation\n\\[\nf(x,t) = f^c(\\M x)\\cos(\\omega_i(t)) + f^s(\\M x)\\sin(\\omega_i(t))\n\\]with $\\omega_i=\\frac{2\\pi}{T_i}(t-t_0)$,\n$t_0$ is <strong class=\"groops-config-element\">timeStart</strong> and $T$ is <strong class=\"groops-config-element\">timePeriod</strong> in days.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>*:*:oscillation.cos(2*pi/&lt;period(days)>*(t-&lt;timeStart>)):*</code>\nand <code>*:*:oscillation.sin(2*pi/&lt;period(days)>*(t-&lt;timeStart>)):*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">period</div></div></td><td>time</td><td>[day]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">time0</div></div></td><td>time</td><td>reference time</td></tr>\n</table>\n\n<h2>Fourier</h2><p>\nA time variable function is given by a fourier expansion\n\\[\nf(x,t) = \\sum_{m=1}^M f_m^c(\\M x)\\cos(2\\pi m \\tau) + f_m^s(\\M x)\\sin(2\\pi m \\tau)\n\\]with the normalized time\n\\[\n\\tau = \\frac{t-t_A}{t_B-t_A},\n\\]and $t_A$ is <strong class=\"groops-config-element\">timeStart</strong>, $t_B$ is <strong class=\"groops-config-element\">timeEnd</strong> in each <strong class=\"groops-config-element\">interval</strong>\nand $M$ is the <strong class=\"groops-config-element\">fourierDegree</strong>.</p><p>The total parameter count is $2MN$, where $N$ is the number of intervals.\nThe parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\ldots$ with\nthe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> <code>*:*:fourier.cos(&lt;m>*x):&lt;interval></code> and <code>*:*:fourier.sin(&lt;m>*x):&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">fourierDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">interval</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>intervals of fourier series</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">includeLastTime</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n<h2>DoodsonHarmonic</h2><p>\nThe time variable function is given by a fourier expansion\n\\[\n  f(x,t) = \\sum_{i} f_i^c(x)\\cos(\\Theta_i(t)) + f_i^s(x)\\sin(\\Theta_i(t)),\n\\]where $\\Theta_i(t)$ are the arguments of the tide constituents $i$\n\\[\n  \\Theta_i(t) = \\sum_{k=1}^6 n_i^k\\beta_k(t),\n\\]where $\\beta_k(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$) and $n_i^k$\nare the Doodson multipliers for the term at frequency $i$.\nThe multipliers must be given by <a class=\"groops-class\" href=\"doodson.html\">doodson</a> coded as Doodson number\n(e.g. 255.555) or as names intoduced by Darwin (e.g. M2).</p><p>The major constituents given by <a class=\"groops-class\" href=\"doodson.html\">doodson</a> can be used to interpolate minor tidal constituents\nusing the file <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>. This file can be created with\n<a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a>.</p><p>The total parameter count is $2N$ with $N$ the number of doodson frequencies.\nThe parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\ldots$ with\nthe <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> <code>*:*:doodson.cos(&lt;doodsonName>):*</code> and <code>*:*:doodson.sin(&lt;doodsonName>):*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">doodson</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td>code number (e.g. 255.555) or darwin name (e.g. M2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAdmittance</div></div></td><td>filename</td><td>interpolation of minor constituents</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/planetType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - planetType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"planetType\">Planet</h1><p>\nDefines the planet to compute the <a class=\"groops-class\" href=\"ephemeridesType.html\">ephemeris</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">planetType</div></div></td><td>choice</td><td>planet</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">earth</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">sun</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">moon</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">mercury</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">venus</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">mars</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">jupiter</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">saturn</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">uranus</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">neptune</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">pluto</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">solarBaryCenter</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">earthMoonBaryCenter</div></div></td><td></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/platformSelectorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - platformSelectorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"platformSelectorType\">PlatformSelector</h1><p>\nSelect a list of platforms (stations, satellites, ...).\nIn a first step all platforms are selected if first selector <strong class=\"groops-config-element\">exclude</strong>s platforms\notherwise all platforms excluded. When every selector from top to bottom selects or deselects\n(with <strong class=\"groops-config-element\">exclude</strong>) the matching platforms.</p><p>See also <a class=\"groops-program\" href=\"GnssProcessing.html\">GnssProcessing</a> or <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.\n</p>\n\n<h2 id=\"all\">All</h2><p>\nSelect all platforms.\n</p>\n\n<h2 id=\"wildcard\">Wildcard</h2><p>\nSelect all receivers/transmitters which match the\n<strong class=\"groops-config-element\">name</strong>, <strong class=\"groops-config-element\">markerName</strong>, and <strong class=\"groops-config-element\">markerNumber</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">markerName</div></div></td><td>string</td><td>wildcards: * and ?, from platform</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">markerNumber</div></div></td><td>string</td><td>wildcards: * and ?, from platform</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exclude</div></div></td><td>boolean</td><td>deselect matching platforms</td></tr>\n</table>\n\n<h2 id=\"file\">File</h2><p>\nSelect receivers/transmitters from each row of\n<a class=\"groops-class\" href=\"fileFormat_stringTable.html\">inputfileStringTable</a>.\nAdditional columns in a row represent alternatives\nif previous names are not available (e.g. without observation file).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStringTable</div></div></td><td>filename</td><td>list of names with alternatives</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exclude</div></div></td><td>boolean</td><td>deselect first matching platforms</td></tr>\n</table>\n\n<h2 id=\"equipment\">Equipment</h2><p>\nSelect all platforms which has the specified equipment in the processed time interval.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">serial</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">equipmentType</div></div></td><td>choice</td><td>equipment type</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">all</div></div></td><td></td><td>all types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gnssAntenna</div></div></td><td>sequence</td><td>antennas</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">radome</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gnssReceiver</div></div></td><td>sequence</td><td>receivers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">version</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">slrStation</div></div></td><td></td><td>SLR station</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">slrRetroReflector</div></div></td><td></td><td>laser retroreflector</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">satelliteIdentifier</div></div></td><td>sequence</td><td>satellite identifier</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">cospar</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">norad</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sic</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">sp3</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">other</div></div></td><td></td><td>other types</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">exclude</div></div></td><td>boolean</td><td>deselect matching platforms</td></tr>\n</table>\n\n<h2 id=\"exclude\">Exclude</h2><p>\nDeselects all selected receivers/transmitters of\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selector</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selector</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotAxisType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotAxisType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotAxisType\">PlotAxis</h1><p>\nDefines the style of the axes of <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n</p>\n\n<h2>Standard</h2><p>\nGeneral axis for arbitrary input data.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">min</div></div></td><td>double</td><td>The minimum value of the axis. If no value is given, the minimum scale value is set automatically.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">max</div></div></td><td>double</td><td>The maximum value of the axis. If no value is given, the maximum scale value is set automatically.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacing</div></div></td><td>double</td><td>The boundary annotation.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacing</div></div></td><td>double</td><td>The spacing of the frame tick intervals.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacing</div></div></td><td>double</td><td>The spacing of the grid line intervals</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>The style of the grid lines.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">unit</div></div></td><td>string</td><td>Naming unit to append to the axis values.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">label</div></div></td><td>string</td><td>The description of the axis.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">logarithmic</div></div></td><td>boolean</td><td>If set to 'yes', a logarithmic scale is used for the axis.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>Setting the color of the axis bars and labels.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">changeDirection</div></div></td><td>boolean</td><td>If set to 'yes', the directions right/up are changed to left/down.</td></tr>\n</table>\n\n<h2>Time</h2><p>\nThe input data are interpreted as MJD (modified Julian date).\nThe unit of the tick spacings should be appenend to the number and can be any of\n<ul>\n\n<li>Y (year, plot with 4 digits)\n</li><li>\ny (year, plot with 2 digits)\n</li><li>\nO (month, plot using <code>FORMAT_DATE_MAP</code>)\n</li><li>\no (month, plot with 2 digits)\n</li><li>\nU (ISO week, plot using <code>FORMAT_DATE_MAP</code>)\n</li><li>\nu (ISO week, plot using 2 digits)\n</li><li>\nr (Gregorian week, 7-day stride from start of week <code>TIME_WEEK_START</code>)\n</li><li>\nK (ISO weekday, plot name of day)\n</li><li>\nD (date, plot using <code>FORMAT_DATE_MAP</code>)\n</li><li>\nd (day, plot day of month 0-31 or year 1-366, via <code>FORMAT_DATE_MAP</code>)\n</li><li>\nR (day, same as d, aligned with <code>TIME_WEEK_START</code>)\n</li><li>\nH (hour, plot using <code>FORMAT_CLOCK_MAP</code>)\n</li><li>\nh (hour, plot with 2 digits)\n</li><li>\nM (minute, plot using <code>FORMAT_CLOCK_MAP</code>)\n</li><li>\nm (minute, plot with 2 digits)\n</li><li>\nS (second, plot using <code>FORMAT_CLOCK_MAP</code>)\n</li><li>\ns (second, plot with 2 digits).\n</li></ul>\n</p><p>A secondary time axis can be added to specify larger intervals (e.g dates of hourly data).</p><p>Examples: Settings for Fig. <a href=\"plotAxisType.html#plotAxisTime1\">plotAxisType:plotAxisTime1</a>: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>6H</code>, secondary: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1D</code>.\n<figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/plotAxisTime1.png\" alt=\"plotAxisTime1\"><figcaption class=\"center\">Figure: Time axis for daily data.</figcaption></figure></p><p>Settings for Fig. <a href=\"plotAxisType.html#plotAxisTime2\">plotAxisType:plotAxisTime2</a>: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>2d</code>, secondary: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1O</code>, <strong class=\"groops-config-element\">options</strong>=<code>FORMAT_DATE_MAP=\"o yyyy\"</code>.\n<figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/plotAxisTime2.png\" alt=\"plotAxisTime2\"><figcaption class=\"center\">Figure: Time axis for monthly data.</figcaption></figure></p><p>Settings for Fig. <a href=\"plotAxisType.html#plotAxisTime3\">plotAxisType:plotAxisTime3</a>: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1o</code>, secondary: <strong class=\"groops-config-element\">majorTickSpacing</strong>=<code>1Y</code>, <strong class=\"groops-config-element\">options</strong>=<code>FORMAT_DATE_MAP=\"mm\"</code>.\n<figure><img class=\"figure\" style=\"width:100%;\" src=\"../figures/plotAxisTime3.png\" alt=\"plotAxisTime3\"><figcaption class=\"center\">Figure: Time axis for yearly data.</figcaption></figure></p><p></p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">min</div></div></td><td>time</td><td>The minimum value of the time axis. If no value is given, the minimum scale value is set automatically.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">max</div></div></td><td>time</td><td>The maximum value of the time axis. If no value is given, the maximum scale value is set automatically.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacing</div></div></td><td>string</td><td>Y: year, o: month</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacing</div></div></td><td>string</td><td>D: date, d: day</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacing</div></div></td><td>string</td><td>H: clock, h: hour, m: minute, s: second</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">secondary</div></div></td><td>sequence</td><td>secondary time axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">majorTickSpacing</div></div></td><td>string</td><td>Y: year, o: month</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">minorTickSpacing</div></div></td><td>string</td><td>D: date, d: day</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">gridLineSpacing</div></div></td><td>string</td><td>H: clock, h: hour, m: minute, s: second</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>color of axis bars and labels</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>The style of the grid lines.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">changeDirection</div></div></td><td>boolean</td><td>right->left / up->down</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">options</div></div></td><td>string</td><td>adjust date format</td></tr>\n</table>\n\n<h2>Labeled</h2><p>\nAxis with string labels. The coordinate system is based on the label indices (e.g. 0, 1, 2).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">labels</div></div></td><td>string</td><td>tick labels (ticks are placed at their index. e.g. 0, 1, ..., 5)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">min</div></div></td><td>expression</td><td>minimum value of the axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">max</div></div></td><td>expression</td><td>maximum values of the axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">majorTickSpacing</div></div></td><td>expression</td><td>The boundary annotation.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minorTickSpacing</div></div></td><td>expression</td><td>The spacing of the frame tick intervals.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLineSpacing</div></div></td><td>expression</td><td>The spacing of the grid line intervals</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>The style of the grid lines.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>set the color of the axis and labels</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">orthogonalLabels</div></div></td><td>boolean</td><td>labels are oriented orthogonal to axis</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">changeDirection</div></div></td><td>boolean</td><td>If set to 'yes', the directions right/up are changed to left/down.</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotColorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotColorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotColorType\">PlotColor</h1><p>\nSelects a color.\nUsed in <a class=\"groops-program\" href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a>, <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>, <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>,\n<a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.</p><p></p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">plotColorType</div></div></td><td>choice</td><td>color</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">black</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">red</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">blue</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">green</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">orange</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">darkred</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">yellow</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">lightgreen</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">gray</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rgb</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">red</div></div></td><td>uint</td><td>0..255</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">green</div></div></td><td>uint</td><td>0..255</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">blue</div></div></td><td>uint</td><td>0..255</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">grayscale</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">value</div></div></td><td>uint</td><td>0..255</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">namedColor</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">colorName</div></div></td><td>string</td><td>name after GMT definition</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">cycler</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">index</div></div></td><td>uint</td><td>pick color based on index expression</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">inputfileColorList</div></div></td><td>filename</td><td>list of colors as defined by GMT</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotColorbarType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotColorbarType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotColorbarType\">PlotColorbar</h1><p>\nA colorbar as used in <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>, <a class=\"groops-program\" href=\"PlotMatrix.html\">PlotMatrix</a>, <a class=\"groops-program\" href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">plotColorbarType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">min</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">max</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">annotation</div></div></td><td>double</td><td>boundary annotation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">unit</div></div></td><td>string</td><td>appended to axis values</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">label</div></div></td><td>string</td><td>description of the axis</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">logarithmic</div></div></td><td>boolean</td><td>use logarithmic scale</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">triangleLeft</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">triangleRight</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">illuminate</div></div></td><td>boolean</td><td>illuminate</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">vertical</div></div></td><td>boolean</td><td>plot vertical color bar on the right</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">length</div></div></td><td>double</td><td>length of colorbar in percent</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">margin</div></div></td><td>double</td><td>between colorbar and figure [cm]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">colorTable</div></div></td><td>string</td><td>name of the color bar</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">reverse</div></div></td><td>boolean</td><td>reverse direction</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">showColorbar</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotGraphLayerType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotGraphLayerType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotGraphLayerType\">PlotGraphLayer</h1><p>\nDefines the content of an xy-plot of <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\nMultiple layers are are plotted sequentially. With <strong class=\"groops-config-element\">plotOnSecondAxis</strong>\nthe alternative y-axis on the right hand side can be selected if provided.\n</p>\n\n<h2 id=\"linesAndPoints\">LinesAndPoints</h2><p>\nDraws a <a class=\"groops-class\" href=\"plotLineType.html\">line</a> and/or points (<a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a>)\nof xy data. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>.\nIf no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> of the <a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a>\nis given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a>\nis required and the color is determined by <strong class=\"groops-config-element\">valueZ</strong>.\nAdditionally a vertical error bar can be plotted at each data point with\nsize <strong class=\"groops-config-element\">valueErrorBar</strong>.</p><p>See <a class=\"groops-program\" href=\"Gravityfield2AreaMeanTimeSeries.html\">Gravityfield2AreaMeanTimeSeries</a> for an example plot.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>each line contains x,y</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueX</div></div></td><td>expression</td><td>expression for x-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueY</div></div></td><td>expression</td><td>expression for y-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueZ</div></div></td><td>expression</td><td>expression for the colorbar</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueErrorBar</div></div></td><td>expression</td><td>expression for error bars (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>text of the legend</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">line</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">symbol</div></div></td><td><a href=\"plotSymbolType.html\">plotSymbol</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2>ErrorEnvelope</h2><p>\nDraws a symmetrical envelope around <strong class=\"groops-config-element\">valueY</strong> as function of <strong class=\"groops-config-element\">valueX</strong>\nusing deviations <strong class=\"groops-config-element\">valueErrors</strong>.\nThe standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>.\nThe data line itself is not plotted but must be added as extra\n<a class=\"groops-class\" href=\"plotGraphLayerType.html#linesAndPoints\">layer:linesAndPoints</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>each line contains x,y</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueX</div></div></td><td>expression</td><td>expression for x-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueY</div></div></td><td>expression</td><td>expression for y-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueErrors</div></div></td><td>expression</td><td>expression for error values</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>text of the legend</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fillColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>fill color of the envelope</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">edgeLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>edge line style of the envelope</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2>Bars</h2><p>\nCreates a bar plot with vertical or <strong class=\"groops-config-element\">horizontal</strong> bars out of the given\nx- and y-values. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>.\nThe bars ranges from <strong class=\"groops-config-element\">valueBase</strong> (can be also an expression) to the <strong class=\"groops-config-element\">valueY</strong>.\nIf no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> is given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a>\nis required and the color is determined by <strong class=\"groops-config-element\">valueZ</strong>.</p><p>See <a class=\"groops-program\" href=\"Instrument2Histogram.html\">Instrument2Histogram</a> for an example plot.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>each line contains x,y</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueX</div></div></td><td>expression</td><td>expression for x-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueY</div></div></td><td>expression</td><td>expression for y-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueZ</div></div></td><td>expression</td><td>expression for the colorbar</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueBase</div></div></td><td>expression</td><td>base value of bars (default: minimum y-value)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">width</div></div></td><td>expression</td><td>width of bars (default: minimum x-gap)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">horizontal</div></div></td><td>boolean</td><td>draw horizontal bars instead of vertical</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>text of the legend</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">edgeLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>line</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2>Gridded</h2><p>\nCreates a regular grid of yxz values. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>.\nEmpty grid cells are not plotted. Cells with more than one value will be set to the mean value.\nThe grid spacing is determined by the median spacing of the input data or set by <strong class=\"groops-config-element\">incrementX/Y</strong>.</p><p>See <a class=\"groops-program\" href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a> for an example plot.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>each line contains x,y,z</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueX</div></div></td><td>expression</td><td>expression for x-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueY</div></div></td><td>expression</td><td>expression for y-values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueZ</div></div></td><td>expression</td><td>expression for the colorbar</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">incrementX</div></div></td><td>double</td><td>the grid spacing</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">incrementY</div></div></td><td>double</td><td>the grid spacing</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2>Rectangle</h2><p>\nPlots a rectangle to highlight an area.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minX</div></div></td><td>double</td><td>empty: left</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxX</div></div></td><td>double</td><td>empty: right</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minY</div></div></td><td>double</td><td>empty: bottom</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxY</div></div></td><td>double</td><td>empty: top</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>text of the legend</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">edgeLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fillColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2>Text</h2><p>\nWrites a <strong class=\"groops-config-element\">text</strong> at <strong class=\"groops-config-element\">originX</strong> and <strong class=\"groops-config-element\">originY</strong> position in the graph.\nWith <strong class=\"groops-config-element\">clip</strong> the text is cutted at the boundaries of the plotting area.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">text</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">originX</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">originY</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">offsetX</div></div></td><td>double</td><td>[cm] x-offset from origin</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">offsetY</div></div></td><td>double</td><td>[cm] y-offset from origin</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">alignment</div></div></td><td>string</td><td>L, C, R (left, center, right) and T, M, B (top, middle, bottom)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fontSize</div></div></td><td>double</td><td>[pt]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">fontColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">clip</div></div></td><td>boolean</td><td>clip at boundaries</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2 id=\"degreeAmplitudes\">DegreeAmplitudes</h2><p>\nPlot degree amplitudes of potential coefficients computed by <a class=\"groops-program\" href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a>\nor <a class=\"groops-program\" href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a>.\nThe standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a> are available to select\nthe data columns of <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfileMatrix</a>. It plots a solid line for the\n<strong class=\"groops-config-element\">valueSignal</strong> and a dotted line for the <strong class=\"groops-config-element\">valueError</strong> per default.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td>degree amplitudes</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueDegree</div></div></td><td>expression</td><td>expression for x-values (degrees) (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueSignal</div></div></td><td>expression</td><td>expression for y-values (signal) (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">valueErrors</div></div></td><td>expression</td><td>expression for y-values (formal errors)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>text of the legend</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lineSignal</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lineErrors</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n<h2 id=\"degreeAmplitudesSimple\">DegreeAmplitudesSimple</h2><p>\nPlot degree amplitudes from a <a class=\"groops-class\" href=\"gravityfieldType.html\">gravityfield</a>.\nThe coefficients can be converted to different functionals with <a class=\"groops-class\" href=\"kernelType.html\">kernel</a>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly. It plots a solid line for the degree amplitude (signal)\nand a dotted line for the formal errors per default.</p><p>This is a simplified version of\n<a class=\"groops-class\" href=\"plotGraphLayerType.html#degreeAmplitudes\">layer:degreeAmplitudes</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">gravityfield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">kernel</div></div></td><td><a href=\"kernelType.html\">kernel</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">type</div></div></td><td>choice</td><td>type of variances</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">rms</div></div></td><td></td><td>degree amplitudes (square root of degree variances)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">accumulation</div></div></td><td></td><td>cumulate variances over degrees</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">median</div></div></td><td></td><td>median of absolute values per degree</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">time</div></div></td><td>time</td><td>at this time the gravity field will be evaluated</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">description</div></div></td><td>string</td><td>text of the legend</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lineSignal</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lineErrors</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">plotOnSecondAxis</div></div></td><td>boolean</td><td>draw dataset on a second Y-axis (if available).</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotLegendType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotLegendType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotLegendType\">PlotLegend</h1><p>\nPlot a legend of the descriptions provided in\n<a class=\"groops-class\" href=\"plotGraphLayerType.html\">plotGraphLayer</a> in <a class=\"groops-program\" href=\"PlotGraph.html\">PlotGraph</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">plotLegendType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>legend width [cm]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">height</div></div></td><td>double</td><td>legend height [cm] (default: estimated)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">positionX</div></div></td><td>double</td><td>legend x-position in normalized (0-1) coordinates.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">positionY</div></div></td><td>double</td><td>legend y-position in normalized (0-1) coordinates.</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">anchorPoint</div></div></td><td>string</td><td>Two character combination of L, C, R (for left, center, or right) and T, M, B for top, middle, or bottom. e.g., TL for top left</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">columns</div></div></td><td>uint</td><td>number of columns in legend</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">textColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>color of the legend text</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">fillColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>fill color of the legend box</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">edgeLine</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>style of the legend box edge</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotLineType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotLineType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotLineType\">PlotLine</h1><p>\nDefines the line style to be plotted.\n</p>\n\n<h2>Solid</h2><p>\nDraws a solid line.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>line width [p]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n</table>\n\n<h2>Dashed</h2><p>\nDraws a dashed line.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>line width [p]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n</table>\n\n<h2>Dotted</h2><p>\nDraws a dotted line.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>line width [p]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>  </td></tr>\n</table>\n\n<h2>Custom</h2><p>\nDraws a custom line. The line <strong class=\"groops-config-element\">style</strong> code is described in\n<a href=\"https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">style</div></div></td><td>string</td><td>line style code</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">width</div></div></td><td>double</td><td>line width [p]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotMapLayerType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotMapLayerType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotMapLayerType\">PlotMapLayer</h1><p>\nDefines the content of a map of <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>. Multiple layers are are plotted sequentially.\n</p>\n\n<h2>GriddedData</h2><p>\nCreates a regular grid of xyz values. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data column of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\nEmpty grid cells are not plotted. Cells with more than one value will be set to the mean value.\nThe grid spacing can be determined automatically for regular rectangular grids otherwise\nit must be set with <strong class=\"groops-config-element\">increment</strong>. To get a better display together with some projections\nthe grid should be internally <strong class=\"groops-config-element\">resample</strong>d to higher resolution.\nIt is assumed that the points of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a> represents centers of grid cells.\nThis assumption can be changed with <strong class=\"groops-config-element\">gridlineRegistered</strong> (e.g. if the data starts at the north pole).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">value</div></div></td><td>expression</td><td>expression to compute values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">increment</div></div></td><td>angle</td><td>the grid spacing [degrees]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">illuminate</div></div></td><td>boolean</td><td>illuminate grid</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">resample</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">intermediateDpi</div></div></td><td>double</td><td>oversample grid for a smoother visual effect</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">interpolationMethod</div></div></td><td>choice</td><td>interpolation method for oversampling</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">bspline</div></div></td><td></td><td>B-Spline interpolation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">bicubic</div></div></td><td></td><td>bicubic interpolation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">bilinear</div></div></td><td></td><td>bilinear interpolation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset\">nearest</div></div></td><td></td><td>nearest neighbour interpolation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">threshold</div></div></td><td>double</td><td>A threshold of 1.0 requires all (4 or 16) nodes involved in interpolation to be non-NaN. 0.5 will interpolate about half way from a non-NaN value; 0.1 will go about 90% of the way.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gridlineRegistered</div></div></td><td>boolean</td><td>treat input as point values instead of cell means</td></tr>\n</table>\n\n<h2 id=\"points\">Points</h2><p>\nDraws points (<a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a>) and/or <a class=\"groops-class\" href=\"plotLineType.html\">line</a>s\nbetween the points. If no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> of the <a class=\"groops-class\" href=\"plotSymbolType.html\">symbol</a>\nis given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a> is required and the color is determined\nby the <strong class=\"groops-config-element\">value</strong> expression. The standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the data column of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">value</div></div></td><td>expression</td><td>expression to compute color (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">symbol</div></div></td><td><a href=\"plotSymbolType.html\">plotSymbol</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">line</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>style of connecting lines</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">drawLineAsGreatCircle</div></div></td><td>boolean</td><td>draw connecting lines as great circles (otherwise, a straight line is drawn instead)</td></tr>\n</table>\n\n<h2>Arrows</h2><p>\nDraws an arrow for each point in <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\nThe arrows are defined by the expressions <strong class=\"groops-config-element\">valueNorth/East</strong>.\nThe standard <a class=\"groops-ref\" href=\"general.parser.html#dataVariables\">dataVariables</a>\nare available to select the correspondent data columns of <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGriddedData</a>.\nThe <strong class=\"groops-config-element\">scale</strong> factor converts the input units to cm in the plot.\nIf no <a class=\"groops-class\" href=\"plotColorType.html\">color</a> is given a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a> is required\nand the color is determined by the <strong class=\"groops-config-element\">value</strong> expression.\nWith <strong class=\"groops-config-element\">scaleArrow</strong> a reference arrow as legend can be plotted inside or outside the map.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGriddedData</div></div></td><td>filename</td><td>grid file with north and east values for arrows</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueNorth</div></div></td><td>expression</td><td>expression to compute north values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">valueEast</div></div></td><td>expression</td><td>expression to compute east values (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">value</div></div></td><td>expression</td><td>expression to compute arrow color (input columns are named data0, data1, ...)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">scale</div></div></td><td>double</td><td>[cm per input unit] length scale factor</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">penSize</div></div></td><td>double</td><td>[pt] width of arrow shaft</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">headSize</div></div></td><td>double</td><td>[pt] size of arrow head, 0: no head, negative: reverse head</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: from value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">scaleArrow</div></div></td><td>sequence</td><td>draw an arrow for scale reference</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">originX</div></div></td><td>double</td><td>[0-1] 0: left, 1: right</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">originY</div></div></td><td>double</td><td>[0-1] 0: bottom, 1: top</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">length</div></div></td><td>double</td><td>in same unit as valueNorth and valueEast</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">unit</div></div></td><td>string</td><td>displayed unit text (e.g. 1 cm)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">label</div></div></td><td>string</td><td>description of the arrows</td></tr>\n</table>\n\n<h2>Polygon</h2><p>\nDraws a <a class=\"groops-class\" href=\"fileFormat_polygon.html\">inputfilePolygon</a>.\nIf <a class=\"groops-class\" href=\"plotColorType.html\">fillColor</a> is not set and a <strong class=\"groops-config-element\">value</strong>\nis given the fill color is taken from a <a class=\"groops-class\" href=\"plotColorbarType.html\">colorbar</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfilePolygon</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">line</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>style of border lines</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fillColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>polygon fill color (no fill color: determine from value if given, else: no fill)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">value</div></div></td><td>double</td><td>value to compute fill color from a colorbar (ignored if a fillColor is given)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">drawLineAsGreatCircle</div></div></td><td>boolean</td><td>draw connecting lines as great circles (otherwise, a straight line is drawn instead)</td></tr>\n</table>\n\n<h2>Coast</h2><p>\nPlots coastlines. GMT provides them in different <strong class=\"groops-config-element\">resolution</strong>s.\nFeatures with an area smaller than <strong class=\"groops-config-element\">minArea</strong> in $km^2$ will not be plotted.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">resolution</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">crude</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">low</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">medium</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">high</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">full</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">line</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td>line style for coastlines</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">landColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>fill land area</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">oceanColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>fill ocean area</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minArea</div></div></td><td>uint</td><td>[km^2] features with a smaller area than this are dropped</td></tr>\n</table>\n\n<h2>Rivers</h2><p>\nPlots rivers and lakes. GMT provides different classes\n(<a href=\"https://docs.generic-mapping-tools.org/latest/coast.html\" target=\"_blank\">https://docs.generic-mapping-tools.org/latest/coast.html</a>).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">class</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">riversCanalsLakes</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">riversCanals</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">permanentRiversLakes</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">permanentRivers</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">intermittentRivers</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">canals</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">singleClass</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">class</div></div></td><td>uint</td><td>0-10. See GMT documentation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">line</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n</table>\n\n<h2>PoliticalBoundary</h2><p>\nPlots national boundaries. GMT provides them in different <strong class=\"groops-config-element\">resolution</strong>s.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">resolution</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">crude</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">low</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">medium</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">high</div></div></td><td></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">full</div></div></td><td></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">line</div></div></td><td><a href=\"plotLineType.html\">plotLine</a></td><td></td></tr>\n</table>\n\n<h2>BlueMarble</h2><p>\nAn image of the Earth's surface as seen from outer space -\nthe image is known as <em>blue marble</em>. The directory of <strong class=\"groops-config-element\">inputfileChannels</strong>\ncontains several files in different resolutions representing the Earth's surface each\nmonth throughout a year.</p><p><figure><img class=\"figure\" style=\"width:80%;\" src=\"../figures/blueMarble.png\" alt=\"blueMarble\"><figcaption class=\"center\">Figure: The blue marble.</figcaption></figure>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileImage</div></div></td><td>filename</td><td>Blue Marble image file</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">brightness</div></div></td><td>double</td><td>brightness of bitmap [-1, 1]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">illuminate</div></div></td><td>sequence</td><td>add hillshade based on topography</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileTopography</div></div></td><td>filename</td><td>GMT grid file containing topography.</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">azimuth</div></div></td><td>angle</td><td>direction of lighting source [deg]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">elevation</div></div></td><td>angle</td><td>direction of lighting source [deg]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">ambient</div></div></td><td>double</td><td>ambient lighting</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">diffuse</div></div></td><td>double</td><td>diffuse lighting</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">specular</div></div></td><td>double</td><td>specular reflection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">shine</div></div></td><td>double</td><td>surface shine</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">amplitude</div></div></td><td>double</td><td>scale gradient by factor</td></tr>\n</table>\n\n<h2>Text</h2><p>\nWrites a <strong class=\"groops-config-element\">text</strong> at <strong class=\"groops-config-element\">originLongitude</strong> and <strong class=\"groops-config-element\">originLatitude</strong> position in the map.\nWith <strong class=\"groops-config-element\">clip</strong> the text is cutted at the boundaries of the plotting area.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">text</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">originLongitude</div></div></td><td>angle</td><td>[deg]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">originLatitude</div></div></td><td>angle</td><td>[deg]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">offsetX</div></div></td><td>double</td><td>[cm] x-offset from origin</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">offsetY</div></div></td><td>double</td><td>[cm] y-offset from origin</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">alignment</div></div></td><td>string</td><td>L, C, R (left, center, right) and T, M, B (top, middle, bottom)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">fontSize</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">fontColor</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">clip</div></div></td><td>boolean</td><td>clip at boundaries</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotMapProjectionType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotMapProjectionType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotMapProjectionType\">PlotMapProjection</h1><p>\nSelects the underlying projection of <a class=\"groops-program\" href=\"PlotMap.html\">PlotMap</a>.\n</p>\n\n<h2>Robinson</h2><p>\nThe Robinson projection, presented by Arthur H. Robinson in 1963,\nis a modified cylindrical projection that is neither conformal nor equal-area.\nCentral meridian and all parallels are straight lines; other meridians are curved.\nIt uses lookup tables rather than analytic expressions to make the world map look right.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">centralMeridian</div></div></td><td>angle</td><td>central meridian [degree]</td></tr>\n</table>\n\n<h2>Orthographic</h2><p>\nThe orthographic azimuthal projection is a perspective projection from infinite distance.\nIt is therefore often used to give the appearance of a globe viewed from space.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lambdaCenter</div></div></td><td>angle</td><td>central point [degree]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">phiCenter</div></div></td><td>angle</td><td>central point [degree]</td></tr>\n</table>\n\n<h2>Perspective sphere</h2><p>\nThe orthographic azimuthal projection is a perspective projection from infinite distance.\nIt is therefore often used to give the appearance of a globe viewed from space.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lambdaCenter</div></div></td><td>angle</td><td>longitude of central point in degrees</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">phiCenter</div></div></td><td>angle</td><td>latitude of central point in degrees</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">altitude</div></div></td><td>double</td><td>[km]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">azimuth</div></div></td><td>angle</td><td>to the east of north of view [degrees]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">tilt</div></div></td><td>angle</td><td>upward tilt of the plane of projection, if negative, then the view is centered on the horizon [degrees]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">viewpointTwist</div></div></td><td>angle</td><td>clockwise twist of the viewpoint [degrees]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">viewpointWidth</div></div></td><td>angle</td><td>width of the viewpoint [degrees]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">viewpointHeight</div></div></td><td>angle</td><td>height of the viewpoint [degrees]</td></tr>\n</table>\n\n<h2>Polar</h2><p>\nStereographic projection around given central point.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">lambdaCenter</div></div></td><td>angle</td><td>longitude of central point in degrees</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">phiCenter</div></div></td><td>angle</td><td>latitude of central point in degrees</td></tr>\n</table>\n\n<h2>Skyplot</h2><p>\nSkyplot used to plot azimuth/elevation data as generated by\n<a class=\"groops-program\" href=\"GnssAntennaDefinition2Skyplot.html\">GnssAntennaDefinition2Skyplot</a> or <a class=\"groops-program\" href=\"GnssResiduals2Skyplot.html\">GnssResiduals2Skyplot</a>.\n</p>\n\n<h2>UTM</h2><p>\nA particular subset of the transverse Mercator is the Universal Transverse Mercator (UTM)\nwhich was adopted by the US Army for large-scale military maps.\nHere, the globe is divided into 60 zones between 84$^{o}$S and 84$^{o}$N, most of which are 6$^{o}$ wide.\nEach of these UTM zones have their unique central meridian.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">zone</div></div></td><td>string</td><td>UTM zone code (e.g. 33N)</td></tr>\n</table>\n\n<h2>Lambert</h2><p>\nThis conic projection was designed by Lambert (1772) and has been used extensively for mapping of regions with predominantly east-west orientation.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">lambda0</div></div></td><td>angle</td><td>longitude of projection center [deg]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">phi0</div></div></td><td>angle</td><td>latitude of projection centert [deg]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">phi1</div></div></td><td>angle</td><td>latitude of first standard parallel [deg]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">phi2</div></div></td><td>angle</td><td>latitude of first standard parallel [deg]</td></tr>\n</table>\n\n<h2>Linear</h2><p>\nLinear mapping of longitude/latitude to x/y (Plate Caree).\n</p>\n\n<h2>Mollweide</h2><p>\nThis pseudo-cylindrical, equal-area projection was developed by Mollweide in 1805. Parallels are unequally spaced straight\nlines with the meridians being equally spaced elliptical arcs. The scale is only true along latitudes 40$^{o}$44' north and south.\nThe projection is used mainly for global maps showing data distributions.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">centralMeridian</div></div></td><td>angle</td><td>central meridian [degree]</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/plotSymbolType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - plotSymbolType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"plotSymbolType\">PlotSymbol</h1><p>\nPlots a symbol as used e.g. in <a class=\"groops-class\" href=\"plotGraphLayerType.html#linesAndPoints\">plotGraphLayer:linesAndPoints</a>\nor <a class=\"groops-class\" href=\"plotMapLayerType.html#points\">plotMapLayer:points</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">plotSymbolType</div></div></td><td>choice</td><td>symbol</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">circle</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">star</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">cross</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">square</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">triangle</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">diamond</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">dash</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">color</div></div></td><td><a href=\"plotColorType.html\">plotColor</a></td><td>empty: determined from value</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">size</div></div></td><td>double</td><td>size of symbol [point]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config optional\">blackContour</div></div></td><td>boolean</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/podRightSideType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - podRightSideType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"podRightSideType\">PodRightSide</h1><p>\nObservation vector for precise orbit data (POD) of <a class=\"groops-class\" href=\"observationType.html\">observation</a>\nequations in a least squares adjustment. The observations are reduced by the effect of\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a> and <a class=\"groops-class\" href=\"forcesType.html\">forces</a>\n(observed minus computed).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">podRightSideType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>kinematic positions of satellite as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileAccelerometer</div></div></td><td>filename</td><td>non-gravitational forces in satellite reference frame</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">forces</div></div></td><td><a href=\"forcesType.html\">forces</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/programType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Programs</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Programs</h1>\n<p>This reference manual details programs included in GROOPS, describing what they are and what they do.\n      For usage examples see the cookbook in the <a href=\"index.html\">documentation overview</a>.</p>\n<h2>Covariance</h2>\n<p><ul>\n<li><a href=\"AutoregressiveModel2CovarianceMatrix.html\">AutoregressiveModel2CovarianceMatrix</a></li>\n<li><a href=\"CovarianceFunction2DigitalFilter.html\">CovarianceFunction2DigitalFilter</a></li>\n<li><a href=\"CovarianceFunction2PowerSpectralDensity.html\">CovarianceFunction2PowerSpectralDensity</a></li>\n<li><a href=\"CovarianceMatrix2AutoregressiveModel.html\">CovarianceMatrix2AutoregressiveModel</a></li>\n<li><a href=\"CovarianceMatrix2Correlation.html\">CovarianceMatrix2Correlation</a></li>\n<li><a href=\"PowerSpectralDensity2CovarianceFunction.html\">PowerSpectralDensity2CovarianceFunction</a></li>\n</ul></p>\n<h2>DoodsonHarmonics</h2>\n<p><ul>\n<li><a href=\"DoodsonAdmittanceInterpolation.html\">DoodsonAdmittanceInterpolation</a></li>\n<li><a href=\"DoodsonAdmittanceTimeSeries.html\">DoodsonAdmittanceTimeSeries</a></li>\n<li><a href=\"DoodsonArguments2TimeSeries.html\">DoodsonArguments2TimeSeries</a></li>\n<li><a href=\"DoodsonHarmonics2GriddedAmplitudeAndPhase.html\">DoodsonHarmonics2GriddedAmplitudeAndPhase</a></li>\n<li><a href=\"DoodsonHarmonics2PotentialCoefficients.html\">DoodsonHarmonics2PotentialCoefficients</a></li>\n<li><a href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a></li>\n<li><a href=\"DoodsonHarmonicsChangePartialTides.html\">DoodsonHarmonicsChangePartialTides</a></li>\n<li><a href=\"ModelEquilibriumTide.html\">ModelEquilibriumTide</a></li>\n<li><a href=\"PotentialCoefficients2DoodsonHarmonics.html\">PotentialCoefficients2DoodsonHarmonics</a></li>\n</ul></p>\n<h2>Gnss</h2>\n<p><ul>\n<li><a href=\"GnssAntennaDefinition2ParameterVector.html\">GnssAntennaDefinition2ParameterVector</a></li>\n<li><a href=\"GnssAntennaDefinition2Skyplot.html\">GnssAntennaDefinition2Skyplot</a></li>\n<li><a href=\"GnssAntennaDefinitionCreate.html\">GnssAntennaDefinitionCreate</a></li>\n<li><a href=\"GnssAntennaNormalsConstraint.html\">GnssAntennaNormalsConstraint</a></li>\n<li><a href=\"GnssAttitudeInfoCreate.html\">GnssAttitudeInfoCreate</a></li>\n<li><a href=\"GnssBiasClockAlignment.html\">GnssBiasClockAlignment</a></li>\n<li><a href=\"GnssEstimateClockShift.html\">GnssEstimateClockShift</a></li>\n<li><a href=\"GnssGlonassFrequencyNumberUpdate.html\">GnssGlonassFrequencyNumberUpdate</a></li>\n<li><a href=\"GnssProcessing.html\">GnssProcessing</a></li>\n<li><a href=\"GnssReceiverDefinitionCreate.html\">GnssReceiverDefinitionCreate</a></li>\n<li><a href=\"GnssResiduals2AccuracyDefinition.html\">GnssResiduals2AccuracyDefinition</a></li>\n<li><a href=\"GnssResiduals2Skyplot.html\">GnssResiduals2Skyplot</a></li>\n<li><a href=\"GnssResiduals2TransmitterAccuracyDefinition.html\">GnssResiduals2TransmitterAccuracyDefinition</a></li>\n<li><a href=\"GnssSignalBias2Matrix.html\">GnssSignalBias2Matrix</a></li>\n<li><a href=\"GnssSimulateReceiver.html\">GnssSimulateReceiver</a></li>\n<li><a href=\"InstrumentGnssReceiver2TimeSeries.html\">InstrumentGnssReceiver2TimeSeries</a></li>\n<li><a href=\"ParameterVector2GnssAntennaDefinition.html\">ParameterVector2GnssAntennaDefinition</a></li>\n</ul></p>\n<h2>Grace</h2>\n<p><ul>\n<li><a href=\"EnsembleAveragingScaleModel.html\">EnsembleAveragingScaleModel</a></li>\n<li><a href=\"GraceAntennaCenterCorrectionArcCovariance.html\">GraceAntennaCenterCorrectionArcCovariance</a></li>\n<li><a href=\"GraceOrbit2TransplantTimeOffset.html\">GraceOrbit2TransplantTimeOffset</a></li>\n<li><a href=\"GraceSstResidualAnalysis.html\">GraceSstResidualAnalysis</a></li>\n<li><a href=\"GraceSstScaleModel.html\">GraceSstScaleModel</a></li>\n<li><a href=\"GraceSstSpecialEvents.html\">GraceSstSpecialEvents</a></li>\n<li><a href=\"GraceThrusterResponse2Accelerometer.html\">GraceThrusterResponse2Accelerometer</a></li>\n<li><a href=\"InstrumentSatelliteTrackingAntennaCenterCorrection.html\">InstrumentSatelliteTrackingAntennaCenterCorrection</a></li>\n<li><a href=\"InstrumentStarCameraAngularAccelerometerFusion.html\">InstrumentStarCameraAngularAccelerometerFusion</a></li>\n</ul></p>\n<h2>Gravityfield</h2>\n<p><ul>\n<li><a href=\"Gravityfield2AbsoluteGravity.html\">Gravityfield2AbsoluteGravity</a></li>\n<li><a href=\"Gravityfield2AreaMeanTimeSeries.html\">Gravityfield2AreaMeanTimeSeries</a></li>\n<li><a href=\"Gravityfield2Deflections.html\">Gravityfield2Deflections</a></li>\n<li><a href=\"Gravityfield2DegreeAmplitudes.html\">Gravityfield2DegreeAmplitudes</a></li>\n<li><a href=\"Gravityfield2DegreeAmplitudesPlotGrid.html\">Gravityfield2DegreeAmplitudesPlotGrid</a></li>\n<li><a href=\"Gravityfield2DisplacementTimeSeries.html\">Gravityfield2DisplacementTimeSeries</a></li>\n<li><a href=\"Gravityfield2EmpiricalCovariance.html\">Gravityfield2EmpiricalCovariance</a></li>\n<li><a href=\"Gravityfield2Gradients.html\">Gravityfield2Gradients</a></li>\n<li><a href=\"Gravityfield2GravityVector.html\">Gravityfield2GravityVector</a></li>\n<li><a href=\"Gravityfield2GridCovarianceMatrix.html\">Gravityfield2GridCovarianceMatrix</a></li>\n<li><a href=\"Gravityfield2GriddedData.html\">Gravityfield2GriddedData</a></li>\n<li><a href=\"Gravityfield2GriddedDataTimeSeries.html\">Gravityfield2GriddedDataTimeSeries</a></li>\n<li><a href=\"Gravityfield2PotentialCoefficients.html\">Gravityfield2PotentialCoefficients</a></li>\n<li><a href=\"Gravityfield2PotentialCoefficientsTimeSeries.html\">Gravityfield2PotentialCoefficientsTimeSeries</a></li>\n<li><a href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a></li>\n<li><a href=\"Gravityfield2TimeSplines.html\">Gravityfield2TimeSplines</a></li>\n<li><a href=\"Gravityfield2TrendPotentialCoefficients.html\">Gravityfield2TrendPotentialCoefficients</a></li>\n<li><a href=\"GravityfieldCovariancesPropagation2GriddedData.html\">GravityfieldCovariancesPropagation2GriddedData</a></li>\n<li><a href=\"GravityfieldReplacePotentialCoefficients.html\">GravityfieldReplacePotentialCoefficients</a></li>\n<li><a href=\"GravityfieldVariancesPropagation2GriddedData.html\">GravityfieldVariancesPropagation2GriddedData</a></li>\n</ul></p>\n<h2>Grid</h2>\n<p><ul>\n<li><a href=\"GriddedData2AreaMeanTimeSeries.html\">GriddedData2AreaMeanTimeSeries</a></li>\n<li><a href=\"GriddedData2GriddedDataStatistics.html\">GriddedData2GriddedDataStatistics</a></li>\n<li><a href=\"GriddedData2GriddedDataTimeSeries.html\">GriddedData2GriddedDataTimeSeries</a></li>\n<li><a href=\"GriddedData2Matrix.html\">GriddedData2Matrix</a></li>\n<li><a href=\"GriddedData2PotentialCoefficients.html\">GriddedData2PotentialCoefficients</a></li>\n<li><a href=\"GriddedData2SphericalDistance.html\">GriddedData2SphericalDistance</a></li>\n<li><a href=\"GriddedData2TimeSeries.html\">GriddedData2TimeSeries</a></li>\n<li><a href=\"GriddedDataCalculate.html\">GriddedDataCalculate</a></li>\n<li><a href=\"GriddedDataConcatenate.html\">GriddedDataConcatenate</a></li>\n<li><a href=\"GriddedDataCreate.html\">GriddedDataCreate</a></li>\n<li><a href=\"GriddedDataInterpolate.html\">GriddedDataInterpolate</a></li>\n<li><a href=\"GriddedDataReduceSampling.html\">GriddedDataReduceSampling</a></li>\n<li><a href=\"GriddedDataTimeSeries2GriddedData.html\">GriddedDataTimeSeries2GriddedData</a></li>\n<li><a href=\"GriddedDataTimeSeries2PotentialCoefficients.html\">GriddedDataTimeSeries2PotentialCoefficients</a></li>\n<li><a href=\"GriddedTopography2AtmospherePotentialCoefficients.html\">GriddedTopography2AtmospherePotentialCoefficients</a></li>\n<li><a href=\"GriddedTopography2PotentialCoefficients.html\">GriddedTopography2PotentialCoefficients</a></li>\n<li><a href=\"GriddedTopographyEllipsoidal2Radial.html\">GriddedTopographyEllipsoidal2Radial</a></li>\n<li><a href=\"Matrix2GriddedData.html\">Matrix2GriddedData</a></li>\n<li><a href=\"MatrixRectangular2GriddedData.html\">MatrixRectangular2GriddedData</a></li>\n<li><a href=\"TimeSeries2GriddedData.html\">TimeSeries2GriddedData</a></li>\n</ul></p>\n<h2>Instrument</h2>\n<p><ul>\n<li><a href=\"Instrument2AllanVariance.html\">Instrument2AllanVariance</a></li>\n<li><a href=\"Instrument2CovarianceFunctionVCE.html\">Instrument2CovarianceFunctionVCE</a></li>\n<li><a href=\"Instrument2CrossCorrelationFunction.html\">Instrument2CrossCorrelationFunction</a></li>\n<li><a href=\"Instrument2Histogram.html\">Instrument2Histogram</a></li>\n<li><a href=\"Instrument2PowerSpectralDensity.html\">Instrument2PowerSpectralDensity</a></li>\n<li><a href=\"Instrument2RmsPlotGrid.html\">Instrument2RmsPlotGrid</a></li>\n<li><a href=\"Instrument2Scaleogram.html\">Instrument2Scaleogram</a></li>\n<li><a href=\"Instrument2SpectralCoherence.html\">Instrument2SpectralCoherence</a></li>\n<li><a href=\"Instrument2Spectrogram.html\">Instrument2Spectrogram</a></li>\n<li><a href=\"InstrumentAccelerometer2ThermosphericDensity.html\">InstrumentAccelerometer2ThermosphericDensity</a></li>\n<li><a href=\"InstrumentAccelerometerApplyEstimatedParameters.html\">InstrumentAccelerometerApplyEstimatedParameters</a></li>\n<li><a href=\"InstrumentAccelerometerEstimateBiasScale.html\">InstrumentAccelerometerEstimateBiasScale</a></li>\n<li><a href=\"InstrumentAccelerometerEstimateParameters.html\">InstrumentAccelerometerEstimateParameters</a></li>\n<li><a href=\"InstrumentApplyTimeOffset.html\">InstrumentApplyTimeOffset</a></li>\n<li><a href=\"InstrumentArcCalculate.html\">InstrumentArcCalculate</a></li>\n<li><a href=\"InstrumentArcCrossStatistics.html\">InstrumentArcCrossStatistics</a></li>\n<li><a href=\"InstrumentArcStatistics.html\">InstrumentArcStatistics</a></li>\n<li><a href=\"InstrumentConcatenate.html\">InstrumentConcatenate</a></li>\n<li><a href=\"InstrumentCovarianceCheck.html\">InstrumentCovarianceCheck</a></li>\n<li><a href=\"InstrumentDetrend.html\">InstrumentDetrend</a></li>\n<li><a href=\"InstrumentEarthRotation.html\">InstrumentEarthRotation</a></li>\n<li><a href=\"InstrumentEstimateEmpiricalCovariance.html\">InstrumentEstimateEmpiricalCovariance</a></li>\n<li><a href=\"InstrumentEstimateHelmertTransformation.html\">InstrumentEstimateHelmertTransformation</a></li>\n<li><a href=\"InstrumentFilter.html\">InstrumentFilter</a></li>\n<li><a href=\"InstrumentInsertNAN.html\">InstrumentInsertNAN</a></li>\n<li><a href=\"InstrumentMultiplyAdd.html\">InstrumentMultiplyAdd</a></li>\n<li><a href=\"InstrumentReduceSampling.html\">InstrumentReduceSampling</a></li>\n<li><a href=\"InstrumentRemoveEpochsByCriteria.html\">InstrumentRemoveEpochsByCriteria</a></li>\n<li><a href=\"InstrumentRemoveEpochsByTimes.html\">InstrumentRemoveEpochsByTimes</a></li>\n<li><a href=\"InstrumentRemoveEpochsThruster.html\">InstrumentRemoveEpochsThruster</a></li>\n<li><a href=\"InstrumentResample.html\">InstrumentResample</a></li>\n<li><a href=\"InstrumentRotate.html\">InstrumentRotate</a></li>\n<li><a href=\"InstrumentSetType.html\">InstrumentSetType</a></li>\n<li><a href=\"InstrumentStarCamera2AccAngularRate.html\">InstrumentStarCamera2AccAngularRate</a></li>\n<li><a href=\"InstrumentStarCamera2RollPitchYaw.html\">InstrumentStarCamera2RollPitchYaw</a></li>\n<li><a href=\"InstrumentStarCamera2RotaryMatrix.html\">InstrumentStarCamera2RotaryMatrix</a></li>\n<li><a href=\"InstrumentStarCameraMultiply.html\">InstrumentStarCameraMultiply</a></li>\n<li><a href=\"InstrumentStatisticsTimeSeries.html\">InstrumentStatisticsTimeSeries</a></li>\n<li><a href=\"InstrumentSynchronize.html\">InstrumentSynchronize</a></li>\n<li><a href=\"InstrumentWaveletDecomposition.html\">InstrumentWaveletDecomposition</a></li>\n<li><a href=\"LocalLevelFrame2StarCamera.html\">LocalLevelFrame2StarCamera</a></li>\n</ul></p>\n<h2>KalmanFilter</h2>\n<p><ul>\n<li><a href=\"KalmanBuildNormals.html\">KalmanBuildNormals</a></li>\n<li><a href=\"KalmanFilter.html\">KalmanFilter</a></li>\n<li><a href=\"KalmanSmoother.html\">KalmanSmoother</a></li>\n<li><a href=\"KalmanSmootherLeastSquares.html\">KalmanSmootherLeastSquares</a></li>\n</ul></p>\n<h2>Misc</h2>\n<p><ul>\n<li><a href=\"DigitalFilter2FrequencyResponse.html\">DigitalFilter2FrequencyResponse</a></li>\n<li><a href=\"DigitalFilter2ImpulseResponse.html\">DigitalFilter2ImpulseResponse</a></li>\n<li><a href=\"EarthOrientationParameterTimeSeries.html\">EarthOrientationParameterTimeSeries</a></li>\n<li><a href=\"EarthRotaryVectorTimeSeries.html\">EarthRotaryVectorTimeSeries</a></li>\n<li><a href=\"EclipseFactor2GriddedData.html\">EclipseFactor2GriddedData</a></li>\n<li><a href=\"FilterMatrixWindowedPotentialCoefficients.html\">FilterMatrixWindowedPotentialCoefficients</a></li>\n<li><a href=\"FunctionsCalculate.html\">FunctionsCalculate</a></li>\n<li><a href=\"Grs2PotentialCoefficients.html\">Grs2PotentialCoefficients</a></li>\n<li><a href=\"Kaula2SigmaPotentialCoefficients.html\">Kaula2SigmaPotentialCoefficients</a></li>\n<li><a href=\"Kernel2Coefficients.html\">Kernel2Coefficients</a></li>\n<li><a href=\"Kernel2SigmaPotentialCoefficients.html\">Kernel2SigmaPotentialCoefficients</a></li>\n<li><a href=\"KernelEvaluate.html\">KernelEvaluate</a></li>\n<li><a href=\"MagneticField2GriddedData.html\">MagneticField2GriddedData</a></li>\n<li><a href=\"MatrixCalculate.html\">MatrixCalculate</a></li>\n<li><a href=\"ObservationEquations2Files.html\">ObservationEquations2Files</a></li>\n<li><a href=\"PlatformCreate.html\">PlatformCreate</a></li>\n<li><a href=\"PotentialCoefficients2BlockMeanTimeSplines.html\">PotentialCoefficients2BlockMeanTimeSplines</a></li>\n<li><a href=\"PotentialCoefficients2DegreeAmplitudes.html\">PotentialCoefficients2DegreeAmplitudes</a></li>\n<li><a href=\"RadialBasisSplines2KernelCoefficients.html\">RadialBasisSplines2KernelCoefficients</a></li>\n<li><a href=\"SatelliteModelCreate.html\">SatelliteModelCreate</a></li>\n<li><a href=\"SynthesisSphericalHarmonicsMatrix.html\">SynthesisSphericalHarmonicsMatrix</a></li>\n<li><a href=\"TemporalRepresentation2TimeSeries.html\">TemporalRepresentation2TimeSeries</a></li>\n<li><a href=\"ThermosphericState2GriddedData.html\">ThermosphericState2GriddedData</a></li>\n<li><a href=\"TimeSeries2PotentialCoefficients.html\">TimeSeries2PotentialCoefficients</a></li>\n<li><a href=\"TimeSeriesCreate.html\">TimeSeriesCreate</a></li>\n<li><a href=\"Variational2OrbitAndStarCamera.html\">Variational2OrbitAndStarCamera</a></li>\n</ul></p>\n<h2>NormalEquation</h2>\n<p><ul>\n<li><a href=\"NormalsAccumulate.html\">NormalsAccumulate</a></li>\n<li><a href=\"NormalsBuild.html\">NormalsBuild</a></li>\n<li><a href=\"NormalsBuildShortTimeStaticLongTime.html\">NormalsBuildShortTimeStaticLongTime</a></li>\n<li><a href=\"NormalsCreate.html\">NormalsCreate</a></li>\n<li><a href=\"NormalsEliminate.html\">NormalsEliminate</a></li>\n<li><a href=\"NormalsMultiplyAdd.html\">NormalsMultiplyAdd</a></li>\n<li><a href=\"NormalsRegularizationBorders.html\">NormalsRegularizationBorders</a></li>\n<li><a href=\"NormalsRegularizationSphericalHarmonics.html\">NormalsRegularizationSphericalHarmonics</a></li>\n<li><a href=\"NormalsReorder.html\">NormalsReorder</a></li>\n<li><a href=\"NormalsReorderAndAccumulate.html\">NormalsReorderAndAccumulate</a></li>\n<li><a href=\"NormalsScale.html\">NormalsScale</a></li>\n<li><a href=\"NormalsSolverVCE.html\">NormalsSolverVCE</a></li>\n<li><a href=\"NormalsTemporalCombination.html\">NormalsTemporalCombination</a></li>\n<li><a href=\"ParameterNamesCreate.html\">ParameterNamesCreate</a></li>\n<li><a href=\"ParameterSelection2IndexVector.html\">ParameterSelection2IndexVector</a></li>\n</ul></p>\n<h2>Orbit</h2>\n<p><ul>\n<li><a href=\"Orbit2ArgumentOfLatitude.html\">Orbit2ArgumentOfLatitude</a></li>\n<li><a href=\"Orbit2BetaPrimeAngle.html\">Orbit2BetaPrimeAngle</a></li>\n<li><a href=\"Orbit2EarthFixedOrbit.html\">Orbit2EarthFixedOrbit</a></li>\n<li><a href=\"Orbit2EclipseFactor.html\">Orbit2EclipseFactor</a></li>\n<li><a href=\"Orbit2Groundtracks.html\">Orbit2Groundtracks</a></li>\n<li><a href=\"Orbit2Kepler.html\">Orbit2Kepler</a></li>\n<li><a href=\"Orbit2MagneticField.html\">Orbit2MagneticField</a></li>\n<li><a href=\"Orbit2ThermosphericState.html\">Orbit2ThermosphericState</a></li>\n<li><a href=\"OrbitAddVelocityAndAcceleration.html\">OrbitAddVelocityAndAcceleration</a></li>\n<li><a href=\"PlanetOrbit.html\">PlanetOrbit</a></li>\n</ul></p>\n<h2>Plot</h2>\n<p><ul>\n<li><a href=\"PlotDegreeAmplitudes.html\">PlotDegreeAmplitudes</a></li>\n<li><a href=\"PlotGraph.html\">PlotGraph</a></li>\n<li><a href=\"PlotMap.html\">PlotMap</a></li>\n<li><a href=\"PlotMatrix.html\">PlotMatrix</a></li>\n<li><a href=\"PlotSphericalHarmonicsTriangle.html\">PlotSphericalHarmonicsTriangle</a></li>\n</ul></p>\n<h2>Preprocessing</h2>\n<p><ul>\n<li><a href=\"PreprocessingDualSst.html\">PreprocessingDualSst</a></li>\n<li><a href=\"PreprocessingGradiometer.html\">PreprocessingGradiometer</a></li>\n<li><a href=\"PreprocessingPod.html\">PreprocessingPod</a></li>\n<li><a href=\"PreprocessingSst.html\">PreprocessingSst</a></li>\n<li><a href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a></li>\n<li><a href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a></li>\n<li><a href=\"PreprocessingVariationalEquationSstFit.html\">PreprocessingVariationalEquationSstFit</a></li>\n</ul></p>\n<h2>Simulation</h2>\n<p><ul>\n<li><a href=\"NoiseAccelerometer.html\">NoiseAccelerometer</a></li>\n<li><a href=\"NoiseGriddedData.html\">NoiseGriddedData</a></li>\n<li><a href=\"NoiseInstrument.html\">NoiseInstrument</a></li>\n<li><a href=\"NoiseNormalsSolution.html\">NoiseNormalsSolution</a></li>\n<li><a href=\"NoiseOrbit.html\">NoiseOrbit</a></li>\n<li><a href=\"NoiseSatelliteTracking.html\">NoiseSatelliteTracking</a></li>\n<li><a href=\"NoiseStarCamera.html\">NoiseStarCamera</a></li>\n<li><a href=\"NoiseTimeSeries.html\">NoiseTimeSeries</a></li>\n<li><a href=\"SimulateAccelerometer.html\">SimulateAccelerometer</a></li>\n<li><a href=\"SimulateAccelerometerCoMOffset.html\">SimulateAccelerometerCoMOffset</a></li>\n<li><a href=\"SimulateGradiometer.html\">SimulateGradiometer</a></li>\n<li><a href=\"SimulateKeplerOrbit.html\">SimulateKeplerOrbit</a></li>\n<li><a href=\"SimulateOrbit.html\">SimulateOrbit</a></li>\n<li><a href=\"SimulateSatelliteTracking.html\">SimulateSatelliteTracking</a></li>\n<li><a href=\"SimulateStarCamera.html\">SimulateStarCamera</a></li>\n<li><a href=\"SimulateStarCameraGnss.html\">SimulateStarCameraGnss</a></li>\n<li><a href=\"SimulateStarCameraGrace.html\">SimulateStarCameraGrace</a></li>\n<li><a href=\"SimulateStarCameraSentinel1.html\">SimulateStarCameraSentinel1</a></li>\n<li><a href=\"SimulateStarCameraTerrasar.html\">SimulateStarCameraTerrasar</a></li>\n</ul></p>\n<h2>Slr</h2>\n<p><ul>\n<li><a href=\"SlrProcessing.html\">SlrProcessing</a></li>\n</ul></p>\n<h2>System</h2>\n<p><ul>\n<li><a href=\"FileConvert.html\">FileConvert</a></li>\n<li><a href=\"FileCreateDirectories.html\">FileCreateDirectories</a></li>\n<li><a href=\"FileMove.html\">FileMove</a></li>\n<li><a href=\"FileRemove.html\">FileRemove</a></li>\n<li><a href=\"FileTextCreate.html\">FileTextCreate</a></li>\n<li><a href=\"GroupPrograms.html\">GroupPrograms</a></li>\n<li><a href=\"IfPrograms.html\">IfPrograms</a></li>\n<li><a href=\"LoopPrograms.html\">LoopPrograms</a></li>\n<li><a href=\"RunCommand.html\">RunCommand</a></li>\n</ul></p>\n<h2>Conversion</h2>\n<p><ul>\n<li><a href=\"Accelerometer2GraceL1b.html\">Accelerometer2GraceL1b</a></li>\n<li><a href=\"BerneseKinematic2Orbit.html\">BerneseKinematic2Orbit</a></li>\n<li><a href=\"Champ2AccStar.html\">Champ2AccStar</a></li>\n<li><a href=\"Champ2Orbit.html\">Champ2Orbit</a></li>\n<li><a href=\"Cosmic2OrbitStar.html\">Cosmic2OrbitStar</a></li>\n<li><a href=\"Cpf2Orbit.html\">Cpf2Orbit</a></li>\n<li><a href=\"Crd2NormalPoints.html\">Crd2NormalPoints</a></li>\n<li><a href=\"Cstg2NormalPoints.html\">Cstg2NormalPoints</a></li>\n<li><a href=\"DoodsonAdmittance2SupplementaryFiles.html\">DoodsonAdmittance2SupplementaryFiles</a></li>\n<li><a href=\"DoodsonHarmonics2IersPotential.html\">DoodsonHarmonics2IersPotential</a></li>\n<li><a href=\"DoodsonHarmonics2IersWaterHeight.html\">DoodsonHarmonics2IersWaterHeight</a></li>\n<li><a href=\"GnssAntex2AntennaDefinition.html\">GnssAntex2AntennaDefinition</a></li>\n<li><a href=\"GnssClock2ClockRinex.html\">GnssClock2ClockRinex</a></li>\n<li><a href=\"GnssClockRinex2InstrumentClock.html\">GnssClockRinex2InstrumentClock</a></li>\n<li><a href=\"GnssEop2IgsErp.html\">GnssEop2IgsErp</a></li>\n<li><a href=\"GnssGriddedDataTimeSeries2Ionex.html\">GnssGriddedDataTimeSeries2Ionex</a></li>\n<li><a href=\"GnssIonex2GriddedDataTimeSeries.html\">GnssIonex2GriddedDataTimeSeries</a></li>\n<li><a href=\"GnssNormals2Sinex.html\">GnssNormals2Sinex</a></li>\n<li><a href=\"GnssOrbex2StarCamera.html\">GnssOrbex2StarCamera</a></li>\n<li><a href=\"GnssReceiver2RinexObservation.html\">GnssReceiver2RinexObservation</a></li>\n<li><a href=\"GnssRinexNavigation2OrbitClock.html\">GnssRinexNavigation2OrbitClock</a></li>\n<li><a href=\"GnssSignalBias2SinexBias.html\">GnssSignalBias2SinexBias</a></li>\n<li><a href=\"GnssSinexBias2SignalBias.html\">GnssSinexBias2SignalBias</a></li>\n<li><a href=\"GnssStationLog2Platform.html\">GnssStationLog2Platform</a></li>\n<li><a href=\"GnssTroposphere2TropoSinex.html\">GnssTroposphere2TropoSinex</a></li>\n<li><a href=\"GoceXml2Gradiometer.html\">GoceXml2Gradiometer</a></li>\n<li><a href=\"GoceXml2Orbit.html\">GoceXml2Orbit</a></li>\n<li><a href=\"GoceXml2StarCamera.html\">GoceXml2StarCamera</a></li>\n<li><a href=\"GoceXmlEggNom1b.html\">GoceXmlEggNom1b</a></li>\n<li><a href=\"Grace2PotentialCoefficients.html\">Grace2PotentialCoefficients</a></li>\n<li><a href=\"GraceAccelerometer2L1bAscii.html\">GraceAccelerometer2L1bAscii</a></li>\n<li><a href=\"GraceAod2DoodsonHarmonics.html\">GraceAod2DoodsonHarmonics</a></li>\n<li><a href=\"GraceAod2TimeSplines.html\">GraceAod2TimeSplines</a></li>\n<li><a href=\"GraceCoefficients2BlockMeanTimeSplines.html\">GraceCoefficients2BlockMeanTimeSplines</a></li>\n<li><a href=\"GraceL1a2Accelerometer.html\">GraceL1a2Accelerometer</a></li>\n<li><a href=\"GraceL1a2SatelliteTracking.html\">GraceL1a2SatelliteTracking</a></li>\n<li><a href=\"GraceL1a2StarCamera.html\">GraceL1a2StarCamera</a></li>\n<li><a href=\"GraceL1a2Temperature.html\">GraceL1a2Temperature</a></li>\n<li><a href=\"GraceL1b2AccHousekeeping.html\">GraceL1b2AccHousekeeping</a></li>\n<li><a href=\"GraceL1b2Accelerometer.html\">GraceL1b2Accelerometer</a></li>\n<li><a href=\"GraceL1b2ClockOffset.html\">GraceL1b2ClockOffset</a></li>\n<li><a href=\"GraceL1b2GnssReceiver.html\">GraceL1b2GnssReceiver</a></li>\n<li><a href=\"GraceL1b2Magnetometer.html\">GraceL1b2Magnetometer</a></li>\n<li><a href=\"GraceL1b2Mass.html\">GraceL1b2Mass</a></li>\n<li><a href=\"GraceL1b2Orbit.html\">GraceL1b2Orbit</a></li>\n<li><a href=\"GraceL1b2SatelliteTracking.html\">GraceL1b2SatelliteTracking</a></li>\n<li><a href=\"GraceL1b2StarCamera.html\">GraceL1b2StarCamera</a></li>\n<li><a href=\"GraceL1b2StarCameraCovariance.html\">GraceL1b2StarCameraCovariance</a></li>\n<li><a href=\"GraceL1b2SteeringMirror.html\">GraceL1b2SteeringMirror</a></li>\n<li><a href=\"GraceL1b2Thruster.html\">GraceL1b2Thruster</a></li>\n<li><a href=\"GraceL1b2TimeOffset.html\">GraceL1b2TimeOffset</a></li>\n<li><a href=\"GraceL1b2Uso.html\">GraceL1b2Uso</a></li>\n<li><a href=\"GraceL1b2Vector.html\">GraceL1b2Vector</a></li>\n<li><a href=\"GraceSequenceOfEvents.html\">GraceSequenceOfEvents</a></li>\n<li><a href=\"GrailCdr2Orbit.html\">GrailCdr2Orbit</a></li>\n<li><a href=\"GrailCdr2SatelliteTracking.html\">GrailCdr2SatelliteTracking</a></li>\n<li><a href=\"GrailCdr2StarCamera.html\">GrailCdr2StarCamera</a></li>\n<li><a href=\"GriddedData2NetCdf.html\">GriddedData2NetCdf</a></li>\n<li><a href=\"GriddedDataTimeSeries2NetCdf.html\">GriddedDataTimeSeries2NetCdf</a></li>\n<li><a href=\"GroopsAscii2Orbit.html\">GroopsAscii2Orbit</a></li>\n<li><a href=\"Hw2TideGeneratingPotential.html\">Hw2TideGeneratingPotential</a></li>\n<li><a href=\"Icgem2PotentialCoefficients.html\">Icgem2PotentialCoefficients</a></li>\n<li><a href=\"Iers2OceanPoleTide.html\">Iers2OceanPoleTide</a></li>\n<li><a href=\"IersC04IAU2000EarthOrientationParameter.html\">IersC04IAU2000EarthOrientationParameter</a></li>\n<li><a href=\"IersHighFrequentEop2DoodsonEop.html\">IersHighFrequentEop2DoodsonEop</a></li>\n<li><a href=\"IersPotential2DoodsonHarmonics.html\">IersPotential2DoodsonHarmonics</a></li>\n<li><a href=\"IersRapidIAU2000EarthOrientationParameter.html\">IersRapidIAU2000EarthOrientationParameter</a></li>\n<li><a href=\"IersWaterHeight2DoodsonHarmonics.html\">IersWaterHeight2DoodsonHarmonics</a></li>\n<li><a href=\"Igs2EarthOrientationParameter.html\">Igs2EarthOrientationParameter</a></li>\n<li><a href=\"Jason2Starcamera.html\">Jason2Starcamera</a></li>\n<li><a href=\"JplAscii2Ephemerides.html\">JplAscii2Ephemerides</a></li>\n<li><a href=\"Merit2FullRate.html\">Merit2FullRate</a></li>\n<li><a href=\"Merit2NormalPoints.html\">Merit2NormalPoints</a></li>\n<li><a href=\"NetCdf2GriddedData.html\">NetCdf2GriddedData</a></li>\n<li><a href=\"NetCdf2GriddedDataTimeSeries.html\">NetCdf2GriddedDataTimeSeries</a></li>\n<li><a href=\"NetCdfInfo.html\">NetCdfInfo</a></li>\n<li><a href=\"NormalsSphericalHarmonics2Sinex.html\">NormalsSphericalHarmonics2Sinex</a></li>\n<li><a href=\"OceanTidesDTU2GriddedData.html\">OceanTidesDTU2GriddedData</a></li>\n<li><a href=\"Orbit2Cpf.html\">Orbit2Cpf</a></li>\n<li><a href=\"Orbit2GraceL1b.html\">Orbit2GraceL1b</a></li>\n<li><a href=\"Orbit2GroopsAscii.html\">Orbit2GroopsAscii</a></li>\n<li><a href=\"Orbit2Sp3Format.html\">Orbit2Sp3Format</a></li>\n<li><a href=\"PotentialCoefficients2Icgem.html\">PotentialCoefficients2Icgem</a></li>\n<li><a href=\"PsmslOceanBottomPressure2TimeSeries.html\">PsmslOceanBottomPressure2TimeSeries</a></li>\n<li><a href=\"RinexObservation2GnssReceiver.html\">RinexObservation2GnssReceiver</a></li>\n<li><a href=\"Sacc2Orbit.html\">Sacc2Orbit</a></li>\n<li><a href=\"SatelliteTracking2GraceL1b.html\">SatelliteTracking2GraceL1b</a></li>\n<li><a href=\"Sentinel2StarCamera.html\">Sentinel2StarCamera</a></li>\n<li><a href=\"SentinelXml2Orbit.html\">SentinelXml2Orbit</a></li>\n<li><a href=\"Sinex2Normals.html\">Sinex2Normals</a></li>\n<li><a href=\"Sinex2StationDiscontinuities.html\">Sinex2StationDiscontinuities</a></li>\n<li><a href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a></li>\n<li><a href=\"SinexEccentricties2SlrPlatform.html\">SinexEccentricties2SlrPlatform</a></li>\n<li><a href=\"SinexMetadata2GlonassFrequencyNumber.html\">SinexMetadata2GlonassFrequencyNumber</a></li>\n<li><a href=\"SinexMetadata2SatelliteModel.html\">SinexMetadata2SatelliteModel</a></li>\n<li><a href=\"SlrComModel2RangeBiasStationSatellite.html\">SlrComModel2RangeBiasStationSatellite</a></li>\n<li><a href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a></li>\n<li><a href=\"Sp3Format2Orbit.html\">Sp3Format2Orbit</a></li>\n<li><a href=\"StarCamera2GraceL1b.html\">StarCamera2GraceL1b</a></li>\n<li><a href=\"StarCamera2Orbex.html\">StarCamera2Orbex</a></li>\n<li><a href=\"Swarm2Starcamera.html\">Swarm2Starcamera</a></li>\n<li><a href=\"TerraSarTandem2Orbit.html\">TerraSarTandem2Orbit</a></li>\n<li><a href=\"TerraSarTandem2StarCamera.html\">TerraSarTandem2StarCamera</a></li>\n<li><a href=\"Tle2Orbit.html\">Tle2Orbit</a></li>\n<li><a href=\"ViennaMappingFunctionGrid2File.html\">ViennaMappingFunctionGrid2File</a></li>\n<li><a href=\"ViennaMappingFunctionStation2File.html\">ViennaMappingFunctionStation2File</a></li>\n</ul></p>\n<h2>Deprecated</h2>\n<p><ul>\n<li><a href=\"GnssAttitude2Orbex.html\">GnssAttitude2Orbex</a></li>\n<li><a href=\"GnssPrn2SvnBlockVariables.html\">GnssPrn2SvnBlockVariables</a></li>\n<li><a href=\"GnssStationInfoCreate.html\">GnssStationInfoCreate</a></li>\n<li><a href=\"GridRectangular2NetCdf.html\">GridRectangular2NetCdf</a></li>\n<li><a href=\"NetCdf2GridRectangular.html\">NetCdf2GridRectangular</a></li>\n<li><a href=\"Sinex2StationPosition.html\">Sinex2StationPosition</a></li>\n<li><a href=\"Sinex2StationPostSeismicDeformation.html\">Sinex2StationPostSeismicDeformation</a></li>\n</ul></p>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/search.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - Search</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            <h1>Search</h1>\n<p id=\"search-meta-info\"></p>\n<div id=\"searchResults\"></div>\n<script type=\"text/javascript\" src=\"documentationSearchIndex.js\"></script>\n<script type=\"text/javascript\" src=\"static/searchtools.js\"></script>\n<script>window.onload = startSearch();</script>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/sggRightSideType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - sggRightSideType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"sggRightSideType\">SggRightSide</h1><p>\nObservation vector for gradiometer data (satellite gravity gradiometry, SGG)\nof <a class=\"groops-class\" href=\"observationType.html\">observation</a> equations in a least squares adjustment.\nThe observations are reduced by an <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileReferenceGradiometer</a>,\nthe effect of <a class=\"groops-class\" href=\"gravityfieldType.html\">referencefield</a>, and <a class=\"groops-class\" href=\"tidesType.html\">tides</a>\n(observed minus computed).</p><p>The reference gradiometer data can be precomputed with <a class=\"groops-program\" href=\"SimulateGradiometer.html\">SimulateGradiometer</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sggRightSideType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">inputfileGradiometer</div></div></td><td>filename</td><td>observed gravity gradients</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileReferenceGradiometer</div></div></td><td>filename</td><td>precomputed gradients at orbit positions</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">referencefield</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">tides</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/slrParametrizationType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - slrParametrizationType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"slrParametrizationType\">SlrParametrization</h1><p>\nThis class defines the models and parameters of the linearized observation equations\nfor normal points (see <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>)\n\\[\\label{slrParametrizationType:model}\n  \\M l - \\M f(\\M x_0) = \\left.\\frac{\\partial \\M f(\\M x)}{\\partial \\M x}\\right|_{\\M x_0} \\Delta\\M x + \\M\\epsilon,\n\\]where the left side is the observation vector minus the effects computed from the a priori models.\nAfter each least squares adjustment\n(see <a class=\"groops-class\" href=\"slrProcessingStepType.html#estimate\">SlrProcessing:processingStep:estimate</a>)\nthe a priori parameters are updated\n\\[\\label{slrParametrizationType:update}\n  \\M x_0 := \\M x_0 + \\Delta\\hat{\\M x}.\n\\]The vector $\\M x_0$ can be written with\n<a class=\"groops-class\" href=\"slrProcessingStepType.html#writeAprioriSolution\">SlrProcessing:processingStep:writeAprioriSolution</a>.\nAny <strong class=\"groops-config-element\">outputfiles</strong> defined in the parametrizations are written with\n<a class=\"groops-class\" href=\"slrProcessingStepType.html#writeResults\">SlrProcessing:processingStep:writeResults</a>.</p><p>Each parametrization (and possible constraint equations) has a <strong class=\"groops-config-element\">name</strong> which enables\nactivating/deactivating the estimation of subsets of $\\Delta\\M x$ with\n<a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">SlrProcessing:processingStep:selectParametrizations</a>.\nThe a priori model $\\M f(\\M x_0)$ is unaffected and is always reduced.</p><p>The model for the one way range observations between station $s$ and reflector $r$\ncan be described as\n\\[\\label{slrParametrizationType:slrFullModel}\n\\begin{split}\n  f_s^r(\\M x) &= \\frac{1}{2}\\left(\\left\\lVert \\M r^r(t_{bounce})-\\M r_s(t_{trans}) \\right\\rVert\n                          + \\left\\lVert \\M r_s(t_{recv})-\\M r^r(t_{bounce}) \\right\\rVert\\right)  \\\\\n              &+ \\text{troposphere}(t,\\M r_{ss}^r)\n               + \\text{bias}^r + \\text{bias}_s + \\text{bias}_s^r + \\text{other}(\\ldots) + \\epsilon_r^s\n\\end{split}\n\\]\nSee also <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.\n</p>\n\n<h2 id=\"troposphere\">Troposphere</h2><p>\nA priori tropospheric correction is handled by a <a class=\"groops-class\" href=\"troposphereType.html\">troposphere</a> model (e.g. Mendes and Pavlis).\nAdditional parameters in $[m]$ for zenith delay can be set up via\n<a class=\"groops-class\" href=\"parametrizationTemporalType.html\">troposphereEstimation</a>.\nThese parameters can be soft-constrained using\n<a class=\"groops-class\" href=\"slrParametrizationType.html#constraints\">parametrization:constraints</a>\nto avoid an unsolvable system of normal equations in case of data gaps.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>:troposphere:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileTroposphere</div></div></td><td>filename</td><td>columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">troposphere</div></div></td><td><a href=\"troposphereType.html\">troposphere</a></td><td>a priori troposphere model</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">troposphereEstimation</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>[m] parametrization of zenith delays</td></tr>\n</table>\n\n<h2 id=\"dynamicOrbits\">DynamicOrbits</h2><p>\nThe estimation of (reduced) dynamic orbits is formulated as variational equations.\nIt is based on <a class=\"groops-class\" href=\"fileFormat_variationalEquation.html\">inputfileVariational</a> calculated with <a class=\"groops-program\" href=\"PreprocessingVariationalEquation.html\">PreprocessingVariationalEquation</a>.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree <strong class=\"groops-config-element\">integrationDegree</strong>.\nThe <a class=\"groops-class\" href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a> must include at least those\nparameters that were estimated in <a class=\"groops-program\" href=\"PreprocessingVariationalEquationOrbitFit.html\">PreprocessingVariationalEquationOrbitFit</a>.\nAdditional <a class=\"groops-class\" href=\"timeSeriesType.html\">stochasticPulse</a> parameters can be set up to reduce orbit mismodeling.</p><p>The parameters and <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are divided into global\n<ul>\n\n<li><code>&lt;satellite>:&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:stochasticPulse.x::&lt;time></code>,\n</li><li>\n<code>&lt;satellite>:stochasticPulse.y::&lt;time></code>,\n</li><li>\n<code>&lt;satellite>:stochasticPulse.z::&lt;time></code>,\n</li></ul>\n\nand arc related parameters\n<ul>\n\n<li><code>&lt;satellite>:arc&lt;no>.&lt;parametrizationAcceleration>:*:*</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position0.x::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position0.y::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.position0.z::</code>.\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.velocity0.x::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.velocity0.y::</code>,\n</li><li>\n<code>&lt;satellite>:arc&lt;no>.velocity0.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileOrbit</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameters</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileVariational</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">stochasticPulse</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>[mu/s] parametrization of stochastic pulses</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">parametrizationAcceleration</div></div></td><td><a href=\"parametrizationAccelerationType.html\">parametrizationAcceleration</a></td><td>orbit force parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">integrationDegree</div></div></td><td>uint</td><td>integration of forces by polynomial approximation of degree n</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for orbit interpolation and velocity calculation</td></tr>\n</table>\n\n<h2 id=\"gravityField\">GravityField</h2><p>\nEstimates a (time depending) gravity field together with at least one\n<a class=\"groops-class\" href=\"slrParametrizationType.html#dynamicOrbits\">parametrization:dynamicOrbits</a>.\nThe parametrization of the gravity field can be set with\n<a class=\"groops-class\" href=\"parametrizationGravityType.html\">parametrization</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>gravityfield:&lt;parametrization>:*:*</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"parametrizationGravityType.html\">parametrizationGravity</a></td><td></td></tr>\n</table>\n\n<h2 id=\"staticPositions\">StaticPositions</h2><p>\nEstimates a static position for all\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectReceivers</a> in the terrestrial frame.</p><p>No-net constraints can be applied for a subset of stations,\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectNoNetReceivers</a>, with a\nstandard deviation of <strong class=\"groops-config-element\">noNetTranslationSigma</strong> and <strong class=\"groops-config-element\">noNetRotationSigma</strong> and <strong class=\"groops-config-element\">noNetScaleSigma</strong> and <strong class=\"groops-config-element\">noNetScaleSigma</strong>.\nIf the template <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a> is provided\nthe constraints are applied relatively to these positions. Only stations with an existing position file\nare considered. Without <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileNoNetPositions</a>\nthe constraints are applied towards the apriori values from\n<a class=\"groops-class\" href=\"slrStationGeneratorType.html\">SlrProcessing:station</a>.\nAs a single corrupted station position can disturb the no-net conditions,\nthe rotation/translation parameters are estimated in a\n<a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>\nbeforehand. The computed weight matrix is used to downweight corrupted stations\nin the constraint equations.</p><p>In case you want to align to an ITRF/ILRS reference frame, precise coordinates can be\ngenerated with <a class=\"groops-program\" href=\"Sinex2StationPositions.html\">Sinex2StationPositions</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>&lt;station>:position.x::</code>,\n</li><li>\n<code>&lt;station>:position.y::</code>,\n</li><li>\n<code>&lt;station>:position.z::</code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileGriddedPosition</div></div></td><td>filename</td><td>delta north east up for all stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfilePosition</div></div></td><td>filename</td><td>variable {station} available, full estimated coordinates (in TRF)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nameConstraint</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectNoNetStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileNoNetPositions</div></div></td><td>filename</td><td>variable {station} available, precise coordinates used for no-net constraints (in TRF)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">noNetTranslationSigma</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">noNetRotationSigma</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] at Earth's surface for no-net rotation constraint on station coordinates</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">noNetScaleSigma</div></div></td><td>double</td><td>(0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>stations > huber*sigma0 are downweighted in no-net constraint</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>stations > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n</table>\n\n<h2 id=\"earthRotation\">EarthRotation</h2><p>\nEarth rotation parameters (ERPs) can be estimated by defining\n<strong class=\"groops-config-element\">estimatePole</strong> ($x_p$, $y_p$) and <strong class=\"groops-config-element\">estimateUT1</strong> ($dUT1, LOD$).</p><p>Estimating length of day (LOD) with the sign according to IGS conventions requires a negative\nvalue in <a class=\"groops-class\" href=\"parametrizationTemporalType.html#trend\">parametrizationTemporal:trend:timeStep</a>.</p><p>Constraints on the defined parameters can be added via\n<a class=\"groops-class\" href=\"slrParametrizationType.html#constraints\">parametrization:constraints</a>.\nAn example would be to set up <a class=\"groops-class\" href=\"parametrizationTemporalType.html#constant\">estimateUT1:constant</a>\nso the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be\ndetermined by SLR, a hard constraint to its a priori value can then be added.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are\n<ul>\n\n<li><code>earth:polarMotion.xp:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:polarMotion.yp:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:UT1:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:nutation.X:&lt;temporal>:&lt;interval></code>,\n</li><li>\n<code>earth:nutation.>:&lt;temporal>:&lt;interval></code>.\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileEOP</div></div></td><td>filename</td><td>EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimatePole</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>xp, yp [mas]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimateUT1</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>rotation angle [ms]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">estimateNutation</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>dX, dY [mas]</td></tr>\n</table>\n\n<h2 id=\"rangeBiasStationApriori\">RangeBiasStationApriori</h2><p>\nA priori station range bias value for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.\nThe <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> provides the mean range biases <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a>,\nbut these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive\nsatellites and not for active ones.\nUse <a class=\"groops-program\" href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a> to convert the range biases from\n<a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a> to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileRangeBias</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n</table>\n\n<h2 id=\"rangeBiasStation\">RangeBiasStation</h2><p>\nEstimates a constant station range bias in $[m]$ for\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>:rangeBias::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileRangeBias</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n</table>\n\n<h2 id=\"rangeBiasSatelliteApriori\">RangeBiasSatelliteApriori</h2><p>\nA priori satellite range bias value for <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileRangeBias</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n</table>\n\n<h2 id=\"rangeBiasSatellite\">RangeBiasSatellite</h2><p>\nEstimates a constant satellite range bias in $[m]$ for\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> a <code>&lt;satellite>:rangeBias::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileRangeBias</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n</table>\n\n<h2 id=\"rangeBiasStationSatelliteApriori\">RangeBiasStationSatelliteApriori</h2><p>\nA priori station-satellite range bias value between all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a> -\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a> pairs.</p><p>For standard <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> processing this class should be setup twice.\nOnce for the model from José Rodríguez (see <a class=\"groops-program\" href=\"SlrComModel2RangeBiasStationSatellite.html\">SlrComModel2RangeBiasStationSatellite</a>) and additionally for\nbiases from the <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a> converted with <a class=\"groops-program\" href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileRangeBias</div></div></td><td>filename</td><td>variable {station} and {satellite} available</td></tr>\n</table>\n\n<h2 id=\"rangeBiasStationSatellite\">RangeBiasStationSatellite</h2><p>\nEstimates the station-satellite range bias in $[m]$ between all\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a> -\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a> pairs.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>.&lt;satellite>:rangeBias::</code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileRangeBias</div></div></td><td>filename</td><td>variable {station} and {satellite} available</td></tr>\n</table>\n\n<h2 id=\"timeBiasApriori\">TimeBiasApriori</h2><p>\nA priori time bias value for all <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.\nThe <a href=\"https://ilrs.gsfc.nasa.gov/\">ILRS</a> provides the mean time biases <a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a>,\nbut these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive\nsatellites and not for active ones.\nUse <a class=\"groops-program\" href=\"SlrSinexDataHandling2Files.html\">SlrSinexDataHandling2Files</a> to convert the time biases from\n<a href=\"https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html\">ILRS Data Handling File</a> to <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTimeBias</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n</table>\n\n<h2 id=\"timeBias\">TimeBias</h2><p>\nEstimates a <a class=\"groops-class\" href=\"parametrizationTemporalType.html\">temporal changing</a>\ntime bias in $[ms]$ for <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.</p><p>The <a class=\"groops-file\" href=\"fileFormat_parameterName.html\">parameter names</a> are <code>&lt;station>:timeBias:&lt;temporal>:&lt;interval></code>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td>used for parameter selection</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">estimateTimeBias</div></div></td><td><a href=\"parametrizationTemporalType.html\">parametrizationTemporal</a></td><td>[ms]</td></tr>\n</table>\n\n<h2 id=\"constraints\">Constraints</h2><p>\nAdd a pseudo observation equation (constraint)\nfor each selected <a class=\"groops-class\" href=\"parameterSelectorType.html\">parameters</a>\n\\[\n  b-x_0 = 1 \\cdot dx + \\epsilon,\n\\]where $b$ is the <strong class=\"groops-config-element\">bias</strong> and $x_0$ is the a priori value of the parameter\nif <strong class=\"groops-config-element\">relativeToApriori</strong> is not set.\nThe standard deviation <strong class=\"groops-config-element\">sigma</strong> is used to weight the observation equations.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">name</div></div></td><td>string</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter to constrain</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sigma</div></div></td><td>double</td><td>sigma of the constraint (same unit as parameter)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">bias</div></div></td><td>double</td><td>constrain all selected parameters towards this value</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">relativeToApriori</div></div></td><td>boolean</td><td>constrain only dx and not full x=dx+x0</td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nGroups a set of parameters. This class can be used to structure complex parametrizations\nand has no further effect itself.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td><a href=\"slrParametrizationType.html\">slrParametrization</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/slrProcessingStepType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - slrProcessingStepType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"slrProcessingStepType\">SlrProcessingStep</h1><p>\nProcessing step in <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.</p><p>Processing steps enable a dynamic definition of the consecutive steps performed during any kind of SLR processing.\nThe most common steps are <a class=\"groops-class\" href=\"slrProcessingStepType.html#estimate\">estimate</a>, which performs an iterative least\nsquares adjustment, and <a class=\"groops-class\" href=\"slrProcessingStepType.html#writeResults\">writeResults</a>, which writes all output files\ndefined in <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a> and is usually the last step.\nSome steps such as <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">selectParametrizations</a>\nand <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectStations\">selectStations</a> affect all subsequent steps.\nIn case these steps are used within a <a class=\"groops-class\" href=\"slrProcessingStepType.html#group\">group</a> step,\nthey only affect the steps within this level.\n</p>\n\n<h2 id=\"estimate\">Estimate</h2><p>\nIterative non-linear least squares adjustment.\nIn every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters.\nThe estimated parameters serve as a priori values in the next iteration and the following processing steps.\nIterates until either every single parameter update (converted to an influence in meter)\nis below a <strong class=\"groops-config-element\">convergenceThreshold</strong> or <strong class=\"groops-config-element\">maxIterationCount</strong> is reached.</p><p>With <strong class=\"groops-config-element\">computeResiduals</strong> the observation equations are computed\nagain after each update to compute the observation residuals.</p><p>The overall standard deviation of a single observation used for the weighting\nis composed of several factors\n\\[\n  \\hat{\\sigma}_i = \\hat{\\sigma}_i^{huber} \\hat{\\sigma}^{stat} \\sigma_{apriori}^{stat},\n\\]where the $\\sigma_{apriori}^{stat}$ is given by <a class=\"groops-class\" href=\"slrStationGeneratorType.html\">station</a>:accuracy.\nThe other factors are estimated iteratively from the residuals.</p><p>With <strong class=\"groops-config-element\">computeWeights</strong> a standardized variance $\\hat{s}_i^2$\nfor each residual $\\hat{\\epsilon}_i$ is computed\n\\[\n  \\hat{s}_i^2 = \\frac{1}{\\hat{\\sigma}^{stat} \\sigma_{apriori}^{stat}}\\frac{\\hat{\\epsilon}_i^2}{r_i}\n  \\qquad\\text{with}\\qquad\n  r_i = \\left(\\M A\\left(\\M A^T\\M A\\right)^{-1}\\M A^T\\right)_{ii}\n\\]taking the redundancy $r_i$ into account. If $\\hat{s}_i$ is above a threshold <strong class=\"groops-config-element\">huber</strong>\nthe observation gets a higher standard deviation used for weighting according to\n\\[\n  \\hat{\\sigma}_i^{huber} =\n  \\left\\{ \\begin{array}{ll}\n    1                              & s < huber,\\\\\n    (\\hat{s}_i/huber)^{huberPower} & s \\ge huber\n  \\end{array} \\right.,\n\\]similar to <a class=\"groops-ref\" href=\"fundamentals.robustLeastSquares.html\">robust least squares adjustment</a>.</p><p>With <strong class=\"groops-config-element\">adjustSigma0</strong> an individual variance factor can be computed for each station separately\n\\[\n  \\hat{\\sigma}^{stat} = \\sqrt{\\frac{\\hat{\\M\\epsilon}^T\\M P\\hat{\\M\\epsilon}}{r}}.\n\\]</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeResiduals</div></div></td><td>boolean</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">adjustSigma0</div></div></td><td>boolean</td><td>adjust sigma0 by scale factor (per station)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">computeWeights</div></div></td><td>boolean</td><td>downweight outliers</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huber</div></div></td><td>double</td><td>residuals > huber*sigma0 are downweighted</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">huberPower</div></div></td><td>double</td><td>residuals > huber: sigma=(e/huber)^huberPower*sigma0</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">convergenceThreshold</div></div></td><td>double</td><td>[m] stop iteration once full convergence is reached</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxIterationCount</div></div></td><td>uint</td><td>maximum number of iterations</td></tr>\n</table>\n\n<h2 id=\"writeResults\">WriteResults</h2><p>\nIn this step all <strong class=\"groops-config-element\">outputfiles</strong> defined in <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>\nare written. It considers the settings of\n<a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">processingStep:selectParametrizations</a>\nand <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectStations\">processingStep:selectStations</a>.</p><p>It is usually the last processing step, but can also be used at other points in the\nprocessing in combination with <strong class=\"groops-config-element\">suffix</strong> to write intermediate results.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">suffix</div></div></td><td>string</td><td>appended to every output file name (e.g. orbit.G01.suffix.dat)</td></tr>\n</table>\n\n<h2 id=\"writeNormalEquations\">WriteNormalEquations</h2><p>\nAccumulates the normal equations matrix and writes it.\nIf <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a>\nis set only the selected parameters are written to the normal equations\nand all other parameters are eliminated beforehand (implicitly solved).</p><p>The solution of the normals would results in $\\Delta\\M x$\n(see <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>). To write the\nappropriate apriori vector $\\M x_0$ use\n<a class=\"groops-class\" href=\"slrProcessingStepType.html#writeAprioriSolution\">processingStep:writeAprioriSolution</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileNormalEquations</div></div></td><td>filename</td><td>normals</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">remainingParameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of output normal equations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">constraintsOnly</div></div></td><td>boolean</td><td>write only normals of constraints without observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">defaultNormalsBlockSize</div></div></td><td>uint</td><td>block size for distributing the normal equations, 0: one block, empty: original block size</td></tr>\n</table>\n\n<h2 id=\"writeAprioriSolution\">WriteAprioriSolution</h2><p>\nWrites the current apriori vector $\\M x_0$\n(see <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>).\nIf <a class=\"groops-class\" href=\"parameterSelectorType.html\">remainingParameters</a>\nis set only the selected parameters are written.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileAprioriSolution</div></div></td><td>filename</td><td>a priori parameters</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outputfileParameterNames</div></div></td><td>filename</td><td>parameter names</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">remainingParameters</div></div></td><td><a href=\"parameterSelectorType.html\">parameterSelector</a></td><td>parameter order/selection of output normal equations</td></tr>\n</table>\n\n<h2 id=\"writeResiduals\">WriteResiduals</h2><p>\nWrites the <a class=\"groops-file\" href=\"fileFormat_instrument.html\">observation residuals</a> for all\n<a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>. For for each station-satellite\npair a file is written. The file name is interpreted as a template with\nthe variables <code>{station}</code> and <code>{satellite}</code> being replaced by the station name.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used satellites</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileResiduals</div></div></td><td>filename</td><td>variable {station} available</td></tr>\n</table>\n\n<h2 id=\"writeUsedStationList\">WriteUsedStationList</h2><p>\nWrites a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of stations (stations) which are used in the last step and\nselected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectStations</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used stations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileUsedStationList</div></div></td><td>filename</td><td>ascii file with names of used stations</td></tr>\n</table>\n\n<h2 id=\"writeUsedSatelliteList\">WriteUsedSatelliteList</h2><p>\nWrites a <a class=\"groops-file\" href=\"fileFormat_stringList.html\">list</a> of satellites which are used in the last step and\nselected by <a class=\"groops-class\" href=\"platformSelectorType.html\">selectSatellites</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td>subset of used satellites</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">outputfileUsedSatelliteList</div></div></td><td>filename</td><td>ascii file with names</td></tr>\n</table>\n\n<h2 id=\"printResidualStatistics\">PrintResidualStatistics</h2><p>\nPrint residual statistics.\n<pre>\n  station   sigma redundancy obsCount outlier\n  ----------------------------------------------\n  1874       0.52   0.86      22      1 (4.55 \n  1889       1.20   0.98     186      5 (2.69 \n  1890       0.63   0.77      14      1 (7.14 \n  1891       0.49   0.50       6      0 (0.00 \n  7237       1.08   0.95     236     14 (5.93 \n  7394       0.36   0.88      26      0 (0.00 \n  7811       0.38   0.41       5      0 (0.00 \n  7819       1.21   0.94     120      1 (0.83 \n  7821       0.69   0.95     202      3 (1.49 \n  7827       0.40   0.85      29      1 (3.45 \n  7839       0.52   0.93     143     10 (6.99 \n  7840       0.15   0.80      16      0 (0.00 \n  7841       0.26   0.90      56      1 (1.79 \n  7941       0.55   0.92     277      5 (1.81 \n  8834       0.66   0.88     101      1 (0.99 \n  ----------------------------------------------\n  satellite sigma redundancy obsCount outlier\n  ----------------------------------------------\n  lageos1    1.04   0.94     722     24 (3.32 \n  lageos2    0.91   0.95     590     11 (1.86 \n  etalon1    1.19   0.78      57      2 (3.51 \n  etalon2    1.10   0.81      70      6 (8.57 \n  ----------------------------------------------\n</pre>\n</p>\n\n<h2 id=\"selectParametrizations\">SelectParametrizations</h2><p>\nEnable/disable parameter groups and constraint groups for subsequent steps,\ne.g. <a class=\"groops-class\" href=\"slrProcessingStepType.html#estimate\">processingStep:estimate</a> or\n<a class=\"groops-class\" href=\"slrProcessingStepType.html#writeResults\">processingStep:writeResults</a>.\nThe <strong class=\"groops-config-element\">name</strong> and <strong class=\"groops-config-element\">nameConstraint</strong> of these groups\nare defined in <a class=\"groops-class\" href=\"slrParametrizationType.html\">parametrizations</a>.\nPrior models or previously estimated parameters used as new apriori $\\M x_0$ values are unaffected\nand they are always reduced from the observations. This means all unselected parameters are kept fixed\nto their last result.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">parametrization</div></div></td><td>choice</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">enable</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">name</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">disable</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-2\"><div class=\"h-100 config mustset-unbounded\">name</div></div></td><td>string</td><td>wildcards: * and ?</td></tr>\n</table>\n\n<h2 id=\"selectSatellites\">SelectSatellites</h2><p>\nThis step can be used to process only a subset of satellites in subsequent processing steps.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectSatellites</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n</table>\n\n<h2 id=\"selectStations\">SelectStations</h2><p>\nThis step can be used to process only a subset of stations in subsequent processing steps.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">selectStations</div></div></td><td><a href=\"platformSelectorType.html\">platformSelector</a></td><td></td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nPerform these processing steps. This step can be used to structure complex processing flows.\nThe <a class=\"groops-class\" href=\"slrProcessingStepType.html#selectParametrizations\">select..</a> processing steps\ndefined within a group only affect the steps within this group.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">processingStep</div></div></td><td><a href=\"slrProcessingStepType.html\">slrProcessingStep</a></td><td>steps are processed consecutively</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/slrSatelliteGeneratorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - slrSatelliteGeneratorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"slrSatelliteGeneratorType\">SlrSatelliteGenerator</h1><p>\nDefinition and basic information of SLR satellites.</p><p>See also <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.\n</p>\n\n<h2 id=\"satellites\">Satellites</h2><p>\nA list of satellite names must be provided via <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileSatelliteList</a>.\nThe other input files are read for each satellite, where the file name is interpreted as a template\nwith the variable <code>{satellite}</code> being replaced by the satellite name from list.\nThe <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileSatelliteInfo</a> contains information about laser retro-reflector,\noptical reference point, retro-reflector orientation, range corrections and center of mass.\nIt can be created via <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>.\nIf <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAttitude</a> ist not provided an orbit reference frame\n(along, cross, nearly nadir) is assumed.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileSatelliteList</div></div></td><td>filename</td><td>ascii file with satellite names, used to loop variable {satellite}</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSatelliteInfo</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAttitude</div></div></td><td>filename</td><td>variable {satellite} available</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for orbit interpolation and velocity calculation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/slrStationGeneratorType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - slrStationGeneratorType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"slrStationGeneratorType\">SlrStationGenerator</h1><p>\nDefinition and basic information of SLR ground stations.</p><p>See also <a class=\"groops-program\" href=\"SlrProcessing.html\">SlrProcessing</a>.\n</p>\n\n<h2 id=\"stations\">Stations</h2><p>\nA list of station names must be provided via <a class=\"groops-class\" href=\"fileFormat_stringList.html\">inputfileStationList</a>.\nIt defines the variable <code>{station}</code> for the station specific input files.\nThe <a class=\"groops-class\" href=\"fileFormat_platform.html\">inputfileStationInfo</a> contains metadata information like station number,\nstation name and approximate station postion in terrestrial reference frame (TRF)\nconsidering the station eccentricities. They can be created via <a class=\"groops-program\" href=\"SinexEccentricties2SlrPlatform.html\">SinexEccentricties2SlrPlatform</a>\nor <a class=\"groops-program\" href=\"PlatformCreate.html\">PlatformCreate</a>. The <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a> are separate files\nfor each <code>{station}</code>-<code>{satellite}</code> pair. They can be converted from CRD\nformat via <a class=\"groops-program\" href=\"Crd2NormalPoints.html\">Crd2NormalPoints</a>, CSTG format via <a class=\"groops-program\" href=\"Cstg2NormalPoints.html\">Cstg2NormalPoints</a>\nand MERIT II format via <a class=\"groops-program\" href=\"Merit2NormalPoints.html\">Merit2NormalPoints</a> and <a class=\"groops-program\" href=\"Merit2FullRate.html\">Merit2FullRate</a>.</p><p>The apriori observation weighting is defined by the expression <strong class=\"groops-config-element\">accuracy</strong> in $[m]$.\nThe following variables are defined for each observation from the\n<a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileObservations</a>: <code>{residual}</code>, <code>{accuracy}</code>,\n<code>{redundancy}</code>, <code>{laserWavelength}</code>, <code>{azimut}</code>, <code>{elevation}</code>.\nObservations with non-positive accuracies are removed.\nThis can be used for a rough outlier removal by an expression such as\n<strong class=\"groops-config-element\">accuracy</strong> = <code>if(abs(residual)>30, NAN, accuracy)</code>.</p><p>The effects of loading and tidal deformation on station positions can be corrected for\nvia <a class=\"groops-class\" href=\"gravityfieldType.html\">loadingDisplacement</a> and\n<a class=\"groops-class\" href=\"tidesType.html\">tidalDisplacement</a>, respectively.\nTidal deformations typically include:\n<ul>\n\n  <li><a class=\"groops-class\" href=\"tidesType.html#earthTide\">earthTide</a>: Earth tidal deformations (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: ocean tidal deformations\n        (e.g. fes2014b_n720, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#doodsonHarmonicTide\">doodsonHarmonicTide</a>: atmospheric tidal deformation\n        (e.g. AOD1B RL06, <strong class=\"groops-config-element\">minDegree</strong>=<code>1</code>)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#poleTide\">poleTide</a>: pole tidal deformations (IERS conventions)\n  </li><li>\n<a class=\"groops-class\" href=\"tidesType.html#oceanPoleTide\">poleOceanTide</a>: ocean pole tidal deformations (IERS conventions)\n</li></ul>\n\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationList</div></div></td><td>filename</td><td>ascii file with station names</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationInfo</div></div></td><td>filename</td><td>station metadata</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileStationPosition</div></div></td><td>filename</td><td>station position</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">disableStationWithoutPosition</div></div></td><td>boolean</td><td>drop stations without apriori position</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileObservations</div></div></td><td>filename</td><td>variable {station} {satellite} available</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">accuracy</div></div></td><td>expression</td><td>[m] used for weighting, variables: {residual}, {accuracy}, {redundancy}, {laserWavelength}, {azimut}, {elevation}</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">loadingDisplacement</div></div></td><td><a href=\"gravityfieldType.html\">gravityfield</a></td><td>loading deformation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">tidalDisplacement</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td>tidal deformation</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">ephemerides</div></div></td><td><a href=\"ephemeridesType.html\">ephemerides</a></td><td>for tidal deformation</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDeformationLoadLoveNumber</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfilePotentialLoadLoveNumber</div></div></td><td>filename</td><td>if full potential is given and not only loading potential</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">elevationCutOff</div></div></td><td>angle</td><td>[degree] ignore observations below cutoff</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">interpolationDegree</div></div></td><td>uint</td><td>for position interpolation</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/sphericalHarmonicsFilterType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - sphericalHarmonicsFilterType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"sphericalHarmonicsFilterType\">SphericalHarmonicsFilter</h1><p>\nFiltering of a spherical harmonics expansion.\n</p>\n\n<h2>DDK</h2><p>\nOrderwise filtering with the DDK filter by Kusche et al. 2009.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">level</div></div></td><td>uint</td><td>DDK filter level (1, 2, 3, ..., 8)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileNormalEquation</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n<h2>Gauss</h2><p>\nFiltering the spherical harmonics expansion with a Gaussian filter.\n<strong class=\"groops-config-element\">radius</strong> gives the filter radius on the Earth surface in km.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">radius</div></div></td><td>double</td><td>filter radius [km]</td></tr>\n</table>\n\n<h2>Matrix</h2><p>\nFiltering the spherical harmonics expansion with a matrix filter.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMatrix</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">minDegree</div></div></td><td>uint</td><td>of matrix</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">maxDegree</div></div></td><td>uint</td><td>of matrix</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">numbering</div></div></td><td><a href=\"sphericalHarmonicsNumberingType.html\">sphericalHarmonicsNumbering</a></td><td>numbering scheme of the matrix</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/sphericalHarmonicsNumberingType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - sphericalHarmonicsNumberingType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"sphericalHarmonicsNumberingType\">SphericalHarmonicsNumbering</h1><p>\nThis class organizes the numbering scheme of spherical harmonics coefficients\nin a parameter vector (e.g <a class=\"groops-program\" href=\"Gravityfield2SphericalHarmonicsVector.html\">Gravityfield2SphericalHarmonicsVector</a> and the design matrix of\n<a class=\"groops-class\" href=\"parametrizationGravityType.html#sphericalHarmonics\">parametrizationGravity:sphericalHarmoncis</a>.\n</p>\n\n<h2>Degree</h2><p>\nNumbering degree by degree:\n\\[ c20, c21, s21, c22, s22, c30, c31, s31, c32, s32,\\ldots \\]\n</p>\n\n<h2>Order</h2><p>\nNumbering order by order:\n\\[ c20, c30, c40, \\ldots, c21, s21, c31, s31, \\ldots, c22, s22 \\]\n</p>\n\n<h2>OrderNonAlternating</h2><p>\nNumbering order by order with cnm, snm non-alternating:\n\\[ c20, c30, c40, \\ldots, c21, c31, c41, \\ldots, s21, s31, s41, \\]\n</p>\n\n<h2>File</h2><p>\nNumbering as specified in the chosen file.\nThe <a class=\"groops-class\" href=\"fileFormat_matrix.html\">inputfile</a> is a matrix with the first column indicating cnm/snm with 0 or 1.\nThe second and third column specify degree and order.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfile</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/sstRightSideType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - sstRightSideType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"sstRightSideType\">SstRightSide</h1><p>\nObservation vector for GRACE like data (satellite-tracking and precise orbit data (POD))\nof <a class=\"groops-class\" href=\"observationType.html\">observation</a> equations in a least squares adjustment.\nThe observations are reduced by the effect of <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileAccelerometer</a>\nand <a class=\"groops-class\" href=\"forcesType.html\">forces</a> (observed minus computed).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sstRightSideType</div></div></td><td>sequence</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional-unbounded\">inputfileSatelliteTracking</div></div></td><td>filename</td><td>ranging observations and corrections</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit1</div></div></td><td>filename</td><td>kinematic positions of satellite A as observations</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileOrbit2</div></div></td><td>filename</td><td>kinematic positions of satellite B as observations</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileAccelerometer1</div></div></td><td>filename</td><td>non-gravitational forces in satellite reference frame A</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config optional\">inputfileAccelerometer2</div></div></td><td>filename</td><td>non-gravitational forces in satellite reference frame B</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-1\"><div class=\"h-100 config mustset\">forces</div></div></td><td><a href=\"forcesType.html\">forces</a></td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/static/groops.css",
    "content": "/* -- general alignment ---------------------------------------------------- */\n\n.center {\n   text-align: center;\n}\n\n.top-buffer {\n    margin-top: 1.0em;\n}\n\n.list-group {\n    list-style-position: inside;\n}\n\n/* -- icon styles ---------------------------------------------------- */\n\nimg.figure {\n    display: block;\n    margin-left: auto;\n    margin-right: auto;\n}\n\nimg.groopsIcon {\n  height: 1.2em;\n  vertical-align: middle;\n}\n\nimg.logo {\n    height: 1.5em;\n    vertical-align: middle;\n  }\n\n/* -- table styles ---------------------------------------------------- */\n\ndiv.config {\n    background-size: 1.2em;\n    background-position: center left;\n    background-repeat: no-repeat;\n    padding-left: 1.5em;\n}\n\ndiv.optional {\n    background-image: url(\"element.svg\");\n}\n\ndiv.mustset {\n    background-image: url(\"element-mustset.svg\");\n}\n\ndiv.mustset-unbounded {\n    background-image: url(\"element-mustset-unbounded.svg\");\n}\n\ndiv.optional-unbounded {\n    background-image: url(\"element-unbounded.svg\");\n}\n\ndiv.config-tree {\n    background-image: url(\"connector.svg\");\n    background-repeat: no-repeat;\n}\n\ndiv.depth-0 {\n    background: none;\n    padding-left: 0.0em;\n}\n\ndiv.depth-1 {\n    padding-left: 1.6em;\n    background-position: center left 0.1em;\n}\n\ndiv.depth-2 {\n    padding-left: 3.2em;\n    background-position: center left 1.7em;\n}\n\ndiv.depth-3 {\n    padding-left: 4.8em;\n    background-position: center left 3.3em;\n}\n\ndiv.depth-4 {\n    padding-left: 6.4em;\n    background-position: center left 4.9em;\n}\n\ndiv.depth-5 {\n    padding-left: 8.0em;\n    background-position: center left 6.5em;\n}\n\ntd {\n    padding: 3px !important;\n}\n\n/* -- inline icons ---------------------------------------------------- */\n\n.groops-program\n{\n   background-image: url(\"program.svg\");\n   background-repeat: no-repeat;\n   background-position: center left;\n   background-size: 1.0em;\n   padding-left: 1.2em;\n   font-weight: bold;\n}\n\n.groops-class\n{\n   background-image: url(\"element.svg\");\n   background-repeat: no-repeat;\n   background-position: center left;\n   background-size: 1.0em;\n   padding-left: 1.2em;\n   font-weight: bold;\n}\n\n.groops-config-element\n{\n   background-image: url(\"element.svg\");\n   background-repeat: no-repeat;\n   background-position: center left;\n   background-size: 1.0em;\n   padding-left: 1.2em;\n   font-weight: bold;\n}\n\n.groops-file\n{\n   background-image: url(\"file.svg\");\n   background-repeat: no-repeat;\n   background-position: center left;\n   background-size: 1.0em;\n   padding-left: 1.1em;\n   font-weight: bold;\n}\n\n.groops-ref\n{\n}\n\n/* -- search box ---------------------------------------------------- */\n\ndiv.faded {\n    height: 5em;\n    overflow-y: hidden;\n}\n\ndiv.faded:after {\n  content  : \"\";\n  position : absolute;\n  z-index  : 1;\n  bottom   : 0;\n  left     : 0;\n  pointer-events   : none;\n  background-image : linear-gradient(to bottom,\n                    rgba(255,255,255, 0),\n                    rgba(255,255,255, 1) 90%);\n  width    : 100%;\n  height   : 3em;\n}\n\ndiv.search-result {\n    min-height: 5em;\n}\n\n/* -- end ------------------------------------------------------------- */\n"
  },
  {
    "path": "docs/html/static/searchtools.js",
    "content": "/** Global variables */\n\nvar idx = lunr(function () {\n              this.ref('key')\n              this.field('name')\n              this.field('display_text')\n              this.field('description')\n              this.field('config_table')\n              this.metadataWhitelist = ['position']\n\n              for(var i in documents)\n                this.add(documents[i]);\n            })\n\nvar wrapThreshold = 6  /** number of search results per page */\nvar paginationCount = 5  /** number of (maximum) pagination links */\n\nvar activePageIndex = 0  /** index of currently viewed search result page */\nvar currentPaginationLinks;  /** array of currently available page links in pagination list */\nvar resultRangePerPage;  /** array containing the intervals of search results per page (ctd. blockIndex) */\n\n/** Functions for search result presentation */\n\n/**\n * Show/hide search result boxes\n *\n * @param oldIndex page index of results to hide\n * @param newIndex page index of results to show\n */\nfunction toggleSearchResults(oldIndex, newIndex) {\n\n    var resultList = document.getElementById(\"searchResults\");\n    for(var k = resultRangePerPage[oldIndex]; k<resultRangePerPage[oldIndex+1]; k++)\n        resultList.childNodes[k].style.display = \"none\";\n\n    for(var k = resultRangePerPage[newIndex]; k<resultRangePerPage[newIndex+1]; k++)\n        resultList.childNodes[k].style.display = \"\";\n}\n\n/**\n * Navigation of search results with pagination buttons.\n * Shows/hides search result boxes and updates links and meta-data\n *\n * @param resultRangePerPage  array containing the intervals of search results per page (ctd. blockIndex)\n * @param pageIndex index of page to be displayed\n */\nfunction searchResultNavigation(resultRangePerPage, pageIndex) {\n\n    var newPageIndex = Math.min(resultRangePerPage.length-2, Math.max(0, pageIndex))  // make sure we are in the correct range\n    if(newPageIndex == activePageIndex)  // short curcuit if the same page is requested\n        return;\n\n    toggleSearchResults(activePageIndex, newPageIndex)  // hide/show the requested search results\n\n    var currentCenter = currentPaginationLinks[Math.floor(currentPaginationLinks.length/2)]  // center of current pagination bar\n    var shift = newPageIndex - currentCenter  // new center is requested page\n\n    if( (currentPaginationLinks[currentPaginationLinks.length-1]+shift)>(resultRangePerPage.length-2) || (currentPaginationLinks[0]+shift)<0 )  // if the shift would put outside bounds, ignore\n        shift = 0\n\n    for(i in currentPaginationLinks)  // update pagination link numbers\n        currentPaginationLinks[i] += shift\n\n    activePageIndex = newPageIndex  // update HTML elements\n    updatePaginationLinks(currentPaginationLinks, activePageIndex)\n}\n\n/**\n * Update HTML elements of pagination buttons\n *\n * @param paginationLinks  array of page indices currently in pagination list\n * @param newIndex index of page to be displayed\n */\nfunction updatePaginationLinks(paginationLinks, newIndex) {\n\n    var paginationSpan = document.getElementById(\"pagination-page-number\")\n    paginationSpan.innerHTML = (newIndex+1)\n\n    for(var k = 0; k<paginationLinks.length; k++)\n    {\n        var item = document.getElementById(\"pagination-link-\"+k)\n        item.setAttribute(\"onclick\", \"searchResultNavigation(resultRangePerPage, \"+paginationLinks[k]+\");\")\n        item.innerHTML = '<span class=\"'+(paginationLinks[k] == newIndex ? 'text-warning' :'text-primary')+' page-link\">'+(paginationLinks[k]+1)+'</a>'\n    }\n\n}\n\n/**\n * Emphasize text based on search result position\n *\n * @param position array of search result position in text\n * @param text text to be changed\n */\nfunction highlightResult(position, text) {\n\n    var highlight = '<em class=\"text-warning\">' + text.slice(position[0], position[0]+position[1]+1) + '</em>'\n    return text.slice(0, position[0]) + highlight + text.slice(position[0]+position[1]+1, text.length)\n}\n\n/**\n * Function to expand a search result box on button click\n *\n * @param hiddedId id of box to be expanded\n */\nfunction expandSearchBox(hiddenId)\n{\n    var searchBox = document.getElementById(hiddenId)\n    searchBox.classList.toggle(\"faded\")\n}\n\n/**\n * Parse search terms for URL. This function generates the query which is passed to the search module\n *\n * @param rawInput URL POST token\n */\nfunction parseSearchTerms(rawInput)\n{\n    var tokens = rawInput.split('+')\n\n    var searchString = tokens[0]\n    for(var i = 1; i<tokens.length; i++)\n        searchString += ' '+tokens[i]\n\n    for(var i = 0; i<tokens.length; i++)\n        searchString += '  name:*'+tokens[i]+'*'\n\n    return searchString\n}\n\n/** Mustache templates for reoccurring HTML elements */\n\n/** HTML template for a search result box */\nvar templateSearchResult = '<div class=\"card border-light mb-3\" style=\"{{style}}\"><div class=\"card-header\">' +\n                           '<a href=\"{{key}}.html\">{{name}}</a>' +\n                           '<span class=\"badge badge-primary float-right\" onclick=\"expandSearchBox(\\'search:{{name}}\\');\">+</span></div>' +\n                           '<div id=\"search:{{name}}\" class=\"card-body search-result faded\"><p>{{{content}}}</p></div></div>'\n\n/** HTML template for the pagination links */\nvar templatePagination = '<ul class=\"pagination\">'+\n                         '<li class=\"page-item\" onclick=\"searchResultNavigation(resultRangePerPage, activePageIndex-1);\"><span class=\"text-primary page-link\">&laquo;</span></li>'+\n                         '{{#pages}}<li class=\"page-item\" id=\"pagination-link-{{.}}\">{{.}}</li>{{/pages}}'+\n                         '<li class=\"page-item\" onclick=\"searchResultNavigation(resultRangePerPage, activePageIndex+1);\"><span class=\"text-primary page-link\">&raquo;</span></li>'+\n                         '</ul>'\n\n/** Search result generation */\n\n/**\n * This function should be called when the search page is loaded. It parses the POST data from the URL and queries the\n * search index. The results are dynamically displayed as (potentially) hidden cards.\n */\nfunction startSearch() {\n\n    var rawSearchString = window.location.search.substr(1).split('=')[1]\n\n    var metaInfo = document.getElementById(\"search-meta-info\")\n    var list = document.getElementById(\"searchResults\")\n    while(list.firstChild) {\n        list.removeChild(list.firstChild);\n    }\n\n    if(rawSearchString == '')  // short circuit on empty search\n    {\n        metaInfo.innerHTML = 'Empty search.';\n        return;\n    }\n\n    var searchQuery = parseSearchTerms(rawSearchString)  // create query from user input and search index\n    var results = idx.search(searchQuery);\n\n    if(results.length == 0)  // short circuit on no results\n    {\n        metaInfo.innerHTML = 'Your search - <b>\"'+rawSearchString+'\"</b> - did not return any results.'\n        return;\n    }\n\n    resultRangePerPage = [0]\n    while(resultRangePerPage[resultRangePerPage.length-1]<results.length)\n        resultRangePerPage.push(Math.min(resultRangePerPage[resultRangePerPage.length-1]+wrapThreshold, results.length))\n\n    metaInfo.innerHTML = 'Page <span id=\"pagination-page-number\">1</span> of '+(resultRangePerPage.length-1)+' ('+results.length+' results).'\n\n    for(i in results)\n    {\n        var metadata = results[i].matchData.metadata;\n        var positions =  {'name': [], 'description': [], 'display_text': [], 'config_table': []}\n        for(j in metadata)\n            for(k in metadata[j])\n               positions[k] = positions[k].concat(metadata[j][k].position);\n\n        var fullText = documents[results[i].ref].display_text\n\n        var data = {'name': documents[results[i].ref].name, 'key': results[i].ref,'content':  fullText/*documents[results[i].ref].description*/, 'style': (i>=wrapThreshold) ? 'display: none;' : ''}\n        var renderedSearchResult = Mustache.render(templateSearchResult, data)\n\n        list.insertAdjacentHTML('beforeend', renderedSearchResult)\n    }\n\n    currentPaginationLinks = Array.apply(null, {length: Math.min(paginationCount, resultRangePerPage.length-1)}).map(Number.call, Number)\n    var data = {'pages': currentPaginationLinks}\n    var renderedPagination = Mustache.render(templatePagination, data)\n\n    document.getElementById(\"content\").insertAdjacentHTML('beforeend', renderedPagination)\n\n    activePageIndex = 0\n    updatePaginationLinks(currentPaginationLinks, activePageIndex)\n }\n"
  },
  {
    "path": "docs/html/static/template.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - [[[title]]]</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            [[[content]]]\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/thermosphereType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - thermosphereType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"thermosphereType\">Thermosphere</h1><p>\nThis class provides functions for calculating the density, temperature and velocity\nin the thermosphere.\nThe wind is computed by HWM14 model if <strong class=\"groops-config-element\">hwm14DataDirectory</strong> is provided.\nA quiet thermosphere is assumed if <strong class=\"groops-config-element\">inputfileMagnetic3hAp</strong> is not given.\n</p>\n\n<h2>JB2008</h2><p>\nThermosphere parameters from the JB2008 model:</p><p>Bowman, B. R., Tobiska, W. K., Marcos, F. A., Huang, C. Y., Lin, C. S., Burke, W. J. (2008).\nA new empirical thermospheric density model JB2008 using new solar and geomagnetic indices.\n In AIAA/AAS Astrodynamics Specialist Conference and Exhibit. <a href=\"https://doi.org/10.2514/6.2008-6438\" target=\"_blank\">https://doi.org/10.2514/6.2008-6438</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileSolfsmy</div></div></td><td>filename</td><td>solar indices</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileDtc</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileMagnetic3hAp</div></div></td><td>filename</td><td>indicies for wind model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">hwm14DataDirectory</div></div></td><td>filename</td><td>directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin</td></tr>\n</table>\n\n<h2>NRLMSIS2</h2><p>\nThermosphere parameters from the NRLMSIS2 model:</p><p>Emmert J.D, D.P.Drob, J.M. Picone, et al. (2020), NRLMSIS 2.0: A whole-atmosphere empirical\nmodel of temperature and neutral species densities. Earth and Space Science, Volume 8, 3\n<a href=\"https://doi.org/10.1029/2020EA001321\" target=\"_blank\">https://doi.org/10.1029/2020EA001321</a>\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMsis</div></div></td><td>filename</td><td>input NRLMSIS 2.0</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileModelParameters</div></div></td><td>filename</td><td>path to msis20.parm file</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileMagnetic3hAp</div></div></td><td>filename</td><td>indicies for wind model</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">hwm14DataDirectory</div></div></td><td>filename</td><td>directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/tidesType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - tidesType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"tidesType\">Tides</h1><p>\nThis class computes functionals of the time depending tide potential,\ne.g potential, acceleration or gravity gradients.</p><p>If several instances of the class are given the results are summed up.\nBefore summation every single result is multiplicated by a <strong class=\"groops-config-element\">factor</strong>.\nTo get the difference between two ocean tide models you must choose one factor by 1\nand the other by -1. To get the mean of two models just set each factor to 0.5.\n</p>\n\n<h2 id=\"astronomicalTide\">AstronomicalTide</h2><p>\nThis class computes the tide generating potential (TGP) of sun, moon\nand planets (Mercury, Venus, Mars, Jupiter, Saturn).\nIt takes into account the flattening of the Earth (At the moment only at the acceleration level).</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useMoon</div></div></td><td>boolean</td><td>TGP of moon</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useSun</div></div></td><td>boolean</td><td>TGP of sun</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">usePlanets</div></div></td><td>boolean</td><td>TGP of planets</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useEarth</div></div></td><td>boolean</td><td>TGP of Earth</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">c20Earth</div></div></td><td>double</td><td>J2 flattening of the Earth</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"earthTide\">EarthTide</h2><p>\nThis class computes the earth tide according to the IERS2003 conventions.\nThe values of solid Earth tide external potential Love numbers and\nthe frequency dependent corrections of these values are given in the file\n<a class=\"groops-class\" href=\"fileFormat_earthTide.html\">inputfileEarthtide</a>. The effect of the permanent tide is removed if\n<strong class=\"groops-config-element\">includePermanentTide</strong> is set to false.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileEarthtide</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">includePermanentTide</div></div></td><td>boolean</td><td>results in FALSE: zero tide, TRUE: tide free gravity field</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"poleTide\">PoleTide</h2><p>\nThe potential coefficients of the solid Earth pole tide according to the\nIERS2003 conventions are given by\n\\[\n\\begin{split}\n\\Delta c_{21} &= s\\cdot(m_1 + o\\cdot m_2), \\\\\n\\Delta s_{21} &= s\\cdot(m_2 - o\\cdot m_1),\n\\end{split}\n\\]with $s$ is the <strong class=\"groops-config-element\">scale</strong>, $o$ is the <strong class=\"groops-config-element\">outPhase</strong> and\n$(m_1,m_2)$ are the wobble variables in seconds of arc.\nThey are related to the polar motion variables $(x_p,y_p)$ according to\n\\[\n\\begin{split}\nm_1 &=  (x_p - \\bar{x}_p), \\\\\nm_2 &= -(y_p - \\bar{y}_p),\n\\end{split}\n\\]The mean pole $(\\bar{x}_p, \\bar{y}_p)$ is approximated by a polynomial\nread from <a class=\"groops-class\" href=\"fileFormat_meanPolarMotion.html\">inputfileMeanPole</a>.</p><p>The displacment is calculated with\n\\[\n\\begin{split}\nS_r          &= -v\\sin2\\vartheta(m_1\\cos\\lambda+m_2\\sin\\lambda),\\\\\nS_\\vartheta &= -h\\cos2\\vartheta(m_1\\cos\\lambda+m_2\\sin\\lambda),\\\\\nS_\\lambda   &=  h\\cos\\vartheta(m_1\\sin\\lambda-m_2\\cos\\lambda),\n\\end{split}\n\\]where $h$ is the <strong class=\"groops-config-element\">horizontalDisplacement</strong>\nand $v$ is the <strong class=\"groops-config-element\">verticalDisplacement</strong>.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">scale</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">outPhase</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMeanPole</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">horizontalDisplacement</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">verticalDisplacement</div></div></td><td>double</td><td>[m]</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"oceanPoleTide\">OceanPoleTide</h2><p>\nThe ocean pole tide is generated by the centrifugal effect of polar motion on the oceans.\nThe potential coefficients of this effect is given by\nIERS2003 conventions are given by\n\\[\n\\begin{Bmatrix}\n\\Delta c_{nm}  \\\\\n\\Delta s_{nm}\n\\end{Bmatrix}=\n\\begin{Bmatrix}\nc_{nm}^R  \\\\\ns_{nm}^R\n\\end{Bmatrix}\n(m_1\\gamma^R+m_2\\gamma^I)+\n\\begin{Bmatrix}\nc_{nm}^I  \\\\\ns_{nm}^I\n\\end{Bmatrix}\n(m_2\\gamma^R-m_1\\gamma^I)\n\\]where the coefficients are read from file <a class=\"groops-class\" href=\"fileFormat_oceanPoleTide.html\">inputfileOceanPole</a>,\n$\\gamma=\\gamma^R+i\\gamma^I$ is given by <strong class=\"groops-config-element\">gammaReal</strong> and\n<strong class=\"groops-config-element\">gammaImaginary</strong> and $(m_1,m_2)$ are the wobble variables in radians.\nThey are related to the polar motion variables $(x_p,y_p)$ according to\n\\[\n\\begin{split}\nm_1 &=  (x_p - \\bar{x}_p), \\\\\nm_2 &= -(y_p - \\bar{y}_p),\n\\end{split}\n\\]The mean pole $(\\bar{x}_p, \\bar{y}_p)$ is approximated by a polynomial\nread from <a class=\"groops-class\" href=\"fileFormat_meanPolarMotion.html\">inputfileMeanPole</a>.</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOceanPole</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gammaReal</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">gammaImaginary</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileMeanPole</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"doodsonHarmonicTide\">DoodsonHarmonicTide</h2><p>\nThe time variable potential of ocean tides is given by a fourier expansion\n\\[\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\Theta_f(t)) + V_f^s(\\M x)\\sin(\\Theta_f(t)),\n\\]where $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics expansions and are\nread from the file <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonic</a>.\nIf set the expansion is limited in the range between <strong class=\"groops-config-element\">minDegree</strong>\nand <strong class=\"groops-config-element\">maxDegree</strong> inclusivly.\n$\\Theta_f(t)$ are the arguments of the tide constituents $f$:\n\\[\n\\Theta_f(t) = \\sum_{i=1}^6 n_f^i\\beta_i(t),\n\\]where $\\beta_i(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$)\nand $n_f^i$ are the Doodson multipliers for the term at frequency $f$.</p><p>The major constituents given by <a class=\"groops-class\" href=\"fileFormat_doodsonHarmonic.html\">inputfileDoodsonHarmonic</a> can be used to\ninterpolate minor tidal constituents using the file <a class=\"groops-class\" href=\"fileFormat_admittance.html\">inputfileAdmittance</a>.\nThis file can be created with <a class=\"groops-program\" href=\"DoodsonHarmonicsCalculateAdmittance.html\">DoodsonHarmonicsCalculateAdmittance</a>.</p><p>After the interpolation step a selection of the computed constituents can be\nchoosen by <a class=\"groops-class\" href=\"doodson.html\">selectDoodson</a>. Only these constiuents are considered for the results.\nIf no <a class=\"groops-class\" href=\"doodson.html\">selectDoodson</a> is set all constituents will be used. The constituents can\nbe coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2).</p><p>The computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileTides</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">inputfileAdmittance</div></div></td><td>filename</td><td>interpolation of minor constituents</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">selectDoodson</div></div></td><td><a href=\"doodson.html\">doodson</a></td><td>consider only these constituents, code number (e.g. 255.555) or darwin name (e.g. M2)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">minDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">maxDegree</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">nodeCorr</div></div></td><td>uint</td><td>nodal corrections: 0-no corr, 1-IHO, 2-Schureman</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"centrifugal\">Centrifugal</h2><p>\nComputes the centrifugal potential in a rotating system\n\\[\nV(\\M r, t) = \\frac{1}{2} (\\M\\omega(t)\\times\\M r)^2.\n\\]The current rotation vector $\\M\\omega(t)$ is computed from the\n<a class=\"groops-class\" href=\"earthRotationType.html\">earthRotation</a>\nprovided by the calling program.\nThe computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.</p><p>Be careful, the centrifugal potential is not harmonic.\nConvolution with a harmonic kernel (e.g. to compute gravity\nanomalies) is not meaningful.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2>SolidMoonTide</h2><p>\nThis class computes the solid moon tide according to the IERS2010 conventions.\nThe values of solid Moon tide external potential Love numbers are given and\nthere are no frequency dependent corrections of these values.\nThe computed result is multiplied with <strong class=\"groops-config-element\">factor</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">k20</div></div></td><td>double</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">k30</div></div></td><td>double</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor, set -1 to subtract the field</td></tr>\n</table>\n\n<h2 id=\"group\">Group</h2><p>\nGroups a set of <a class=\"groops-class\" href=\"tidesType.html\">tides</a> and has no further effect itself.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional-unbounded\">tides</div></div></td><td><a href=\"tidesType.html\">tides</a></td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">factor</div></div></td><td>double</td><td>the result is multiplied by this factor</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/timeSeriesType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - timeSeriesType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"timeSeriesType\">TimeSeries</h1><p>\nThis class generates a series of points in time. The series is always sorted in ascending order.\nDepending of the application the series is interpreted as list of points or as intervals between the points.</p><p><figure><img class=\"figure\" style=\"width:40%;\" src=\"../figures/timeSeriesIntervals.png\" alt=\"timeSeriesIntervals\"><figcaption class=\"center\">Figure: List of points $t_i$ vs. intervals $T_i$.</figcaption></figure>\n</p>\n\n<h2 id=\"uniformSampling\">UniformSampling</h2><p>\nGenerates a time series with uniform sampling. The first point in time will be <strong class=\"groops-config-element\">timeStart</strong>.\nThe last generated point in time will be less or equal <strong class=\"groops-config-element\">timeEnd</strong>.\nThe time step between generated points in time is given by <strong class=\"groops-config-element\">sampling</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>first point in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeEnd</div></div></td><td>time</td><td>last point in time will be less or equal timeEnd</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">sampling</div></div></td><td>time</td><td>time step between points in time</td></tr>\n</table>\n\n<h2>UniformInterval</h2><p>\nGenerates a time series with uniform sampling between <strong class=\"groops-config-element\">timeStart</strong> and <strong class=\"groops-config-element\">timeEnd</strong>.\n<strong class=\"groops-config-element\">intervallCount</strong> gives the count of intervals. This class generates count+1 points in time\ninclusive <strong class=\"groops-config-element\">timeStart</strong> and <strong class=\"groops-config-element\">timeEnd</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>1st point of the time series</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeEnd</div></div></td><td>time</td><td>last point of the time series</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">intervalCount</div></div></td><td>uint</td><td>count of intervals, count+1 points in time will generated</td></tr>\n</table>\n\n<h2 id=\"irregular\">Irregular</h2><p>\nThe points of the time series are given explicitly with <strong class=\"groops-config-element\">time</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">time</div></div></td><td>time</td><td>explicit list of points in time</td></tr>\n</table>\n\n<h2>Monthly</h2><p>\nIf <strong class=\"groops-config-element\">useMonthMiddle</strong> is set, time points are generated at mid of each month inclusively\nthe <strong class=\"groops-config-element\">monthStart</strong> in <strong class=\"groops-config-element\">yearStart</strong> and <strong class=\"groops-config-element\">monthEnd</strong> in <strong class=\"groops-config-element\">yearEnd</strong>.\nOtherwise times are given at the first of each month and a time point after the last month.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">monthStart</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">yearStart</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">monthEnd</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">yearEnd</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useMonthMiddle</div></div></td><td>boolean</td><td>time points are mid of months, otherwise the 1st of each month + a time point behind the last month</td></tr>\n</table>\n\n<h2>Yearly</h2><p>\nIf <strong class=\"groops-config-element\">useYearMiddle</strong> is set, time points are generated at mid of each year inclusively <strong class=\"groops-config-element\">yearStart</strong>\nand <strong class=\"groops-config-element\">yearEnd</strong>. Otherwise times are given at the first of each year and a time point after the last year.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">yearStart</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">yearEnd</div></div></td><td>uint</td><td></td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">useYearMiddle</div></div></td><td>boolean</td><td>time points are mid of years, otherwise the 1st of each year + a time point behind the last year</td></tr>\n</table>\n\n<h2>EveryMonth</h2><p>\nGenerates a time series with monthly sampling. The first point in time will be <strong class=\"groops-config-element\">timeStart</strong> and the following\npoints are generated for each month at the same day and time in month.\nThe last generated point in time will be less or equal <strong class=\"groops-config-element\">timeEnd</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>first point in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeEnd</div></div></td><td>time</td><td>last point in time will be less or equal timeEnd</td></tr>\n</table>\n\n<h2>EveryYear</h2><p>\nGenerates a time series with yearly sampling. The first point in time will be <strong class=\"groops-config-element\">timeStart</strong> and the following\npoints are generated for each year at the same day and time in year.\nThe last generated point in time will be less or equal <strong class=\"groops-config-element\">timeEnd</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeStart</div></div></td><td>time</td><td>first point in time</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">timeEnd</div></div></td><td>time</td><td>last point in time will be less or equal timeEnd</td></tr>\n</table>\n\n<h2 id=\"instrument\">Instrument</h2><p>\nRead a time series (epochs) from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\nThe time series can be restricted to the interval\nstarting from <strong class=\"groops-config-element\">timeStart</strong> and before <strong class=\"groops-config-element\">timeEnd</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>inclusive, i.e. exclude eochs before this epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td>exclusive, i.e. only epochs before this time are used</td></tr>\n</table>\n\n<h2>InstrumentArcIntervals</h2><p>\nReconstruct a time series from an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">instrument file</a>.\nThe time series is the first epoch of each arc plus one time step beyond the last\nepoch of the last arc (using median sampling).\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileInstrument</div></div></td><td>filename</td><td>Must be regular. Time series is first epoch of each arc plus one time step extrapolated from last epoch of last arc.</td></tr>\n</table>\n\n<h2>Revolution</h2><p>\nReads an <a class=\"groops-file\" href=\"fileFormat_instrument.html\">orbit file</a> and create a time stamp for each ascending equator crossing.\nThe time series can be restricted to the interval\nstarting from <strong class=\"groops-config-element\">timeStart</strong> and before <strong class=\"groops-config-element\">timeEnd</strong>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileOrbit</div></div></td><td>filename</td><td></td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeStart</div></div></td><td>time</td><td>exclude eochs before this epoch</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">timeEnd</div></div></td><td>time</td><td>only epochs before this time are used</td></tr>\n</table>\n\n<h2>Exclude</h2><p>\nIn a first step a <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> is generated.\nIn a second step all times are removed which are in range before or after <strong class=\"groops-config-element\">excludeMargin</strong> seconds\nof the times given by <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeriesExclude</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>time series to be created</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeriesExclude</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>exclude this time points from time series (within margin)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">excludeMargin</div></div></td><td>double</td><td>on both sides [seconds]</td></tr>\n</table>\n\n<h2>Conditional</h2><p>\nOnly times for which the <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is met are included in the time series.\nThe <strong class=\"groops-config-element\">variableLoopTime</strong> is set to every time and the <a class=\"groops-class\" href=\"conditionType.html\">condition</a> is evaluated.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>only times for which condition is met will be included</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">variableLoopTime</div></div></td><td>string</td><td>variable with time of each loop</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">condition</div></div></td><td><a href=\"conditionType.html\">condition</a></td><td>test for each time</td></tr>\n</table>\n\n<h2>Interpolate</h2><p>\nInterpolates <strong class=\"groops-config-element\">nodeInterpolation</strong> count points between\nthe given <a class=\"groops-class\" href=\"timeSeriesType.html\">timeSeries</a> uniformly.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">timeSeries</div></div></td><td><a href=\"timeSeriesType.html\">timeSeries</a></td><td>time series to be created</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">nodeInterpolation</div></div></td><td>uint</td><td>interpolates count points in each time interval given by the time series</td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/html/troposphereType.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>GROOPS - troposphereType</title>\n\n    <!-- JQuery and Popper -->\n    <script src=\"https://code.jquery.com/jquery-3.4.1.slim.min.js\" integrity=\"sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js\" integrity=\"sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo\" crossorigin=\"anonymous\"></script>\n\n    <!-- Bootstrap -->\n    <!-- https://getbootstrap.com/docs/4.1/examples/ -->\n    <script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js\" integrity=\"sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6\" crossorigin=\"anonymous\"></script>\n    <link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\" integrity=\"sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh\" crossorigin=\"anonymous\">\n\n    <!-- Mathjax -->\n    <script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({tex2jax: {inlineMath: [ ['$','$'] ],\n                                  displayMath: [ [\"\\\\[\",\"\\\\]\"] ],\n                                  processEscapes: true},\n                        TeX:     {Macros: {M: [\"{\\\\mathbf #1}\",1]},\n                                  equationNumbers: {autoNumber: \"all\"}  }});\n    </script>\n    <script async src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.7/MathJax.js?config=TeX-AMS_CHTML\" integrity=\"sha384-e/4/LvThKH1gwzXhdbY2AsjR3rm7LHWyhIG5C0jiRfn8AN2eTN5ILeztWw0H9jmN\" crossorigin=\"anonymous\"></script>\n\n    <!-- lunr -->\n    <script src=\"https://cdn.jsdelivr.net/npm/lunr@2.3.8/lunr.min.js\" integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\" crossorigin=\"anonymous\"></script>\n\n    <!-- Mustache -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mustache@4.0.1/mustache.min.js\" integrity=\"sha384-0PLEZVBpOQ+Kqw3anJWSNWvRxpEFt02tSpBvyRsA4WcvX/OTldWdXxGLVLvh954H\" crossorigin=\"anonymous\"></script>\n\n    <!-- GROOPS Stylesheet -->\n    <link rel=\"stylesheet\" href=\"static/groops.css\"/>\n\n    <!-- icon -->\n    <link rel=\"icon\" href=\"static/groops_icon.png\">\n\n</head>\n<body>\n    <header>\n        <nav class=\"navbar navbar-expand-lg navbar-dark bg-dark\">\n            <div class=\"container\">\n              <a class=\"navbar-brand\" href=\"index.html\"><img class=\"logo\" src=\"static/groops_white.svg\"></a>\n              <div class=\"collapse navbar-collapse\" id=\"mainNavbar\">\n                <ul class=\"navbar-nav mr-auto\">\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"programType.html\">Programs</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"classes.html\">Classes</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.parser.html\">Parser</a>\n                  </li>\n                  <li class=\"nav-item\">\n                    <a class=\"nav-link\" href=\"general.fileFormat.html\">File Formats</a>\n                  </li>\n                </ul>\n              </div>\n                <form class=\"form-inline my-2 my-lg-0\" action=\"search.html\" id=\"searchTools\">\n                  <input class=\"form-control mr-sm-2\" placeholder=\"Search\" name=\"searchTerms\" method=\"GET\" value=\"\" type=\"text\" id=\"searchBox\">\n                  <button class=\"btn btn-secondary my-2 my-sm-0\" type=\"submit\" id=\"searchButton\">Search</button>\n                </form>\n              <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#mainNavbar\" aria-controls=\"mainNavbar\" aria-expanded=\"false\" aria-label=\"Toggle navigation\" style=\"\">\n                <span class=\"navbar-toggler-icon\"></span>\n              </button>\n            </div>\n        </nav>\n    </header>\n    <main class=\"container px-0 pt-2 top-buffer\">\n        <div id=\"content\" class=\"container\">\n            \n<h1 id=\"troposphereType\">Troposphere</h1><p>\nThis class provides functions for calculating and estimating\nthe signal delay in the dry and wet atmosphere.\n</p>\n\n<h2 id=\"viennaMapping\">ViennaMapping</h2><p></p><p>Tropospheric delays based on the Vienna Mapping Functions 3 (VMF3) model\n(Landskron and Boehm 2017, DOI: <a href=\"https://doi.org/10.1007/s00190-017-1066-2\">10.1007/s00190-017-1066-2</a>).</p><p>Hydrostatic and wet mapping function coefficients ($a_h$, $a_w$) and zenith delays (ZHD, ZWD) have to be provided\nvia <a class=\"groops-class\" href=\"fileFormat_griddedDataTimeSeries.html\">inputfileVmfCoefficients</a>. This file can contain either station-specific data\n(see <a class=\"groops-program\" href=\"ViennaMappingFunctionStation2File.html\">ViennaMappingFunctionStation2File</a>) or data on a regular global grid\n(see <a class=\"groops-program\" href=\"ViennaMappingFunctionGrid2File.html\">ViennaMappingFunctionGrid2File</a>). In the second case mapping coefficients and zenith delays are\ninterpolated to the requested coordinates. This includes a height correction that requires approximate meteorological\ndata provided via <a class=\"groops-class\" href=\"fileFormat_griddedData.html\">inputfileGpt</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset-unbounded\">inputfileVmfCoefficients</div></div></td><td>filename</td><td>ah, aw, zhd, zwd coefficients</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGpt</div></div></td><td>filename</td><td>gridded GPT data</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">aHeight</div></div></td><td>double</td><td>parameter a (height correction)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">bHeight</div></div></td><td>double</td><td>parameter b (height correction)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">cHeight</div></div></td><td>double</td><td>parameter c (height correction)</td></tr>\n</table>\n\n<h2 id=\"gpt\">GPT</h2><p></p><p>Tropospheric delays based on the Global Pressure and Temperature 3 (GPT3) model\n(Landskron and Boehm 2017, DOI: <a href=\"https://doi.org/10.1007/s00190-017-1066-2\">10.1007/s00190-017-1066-2</a>).</p><p>It is an empirical model derived from the Vienna Mapping Functions 3\n(VMF3, see <a class=\"groops-class\" href=\"troposphereType.html#viennaMapping\">viennaMapping</a>) and thus does not require\nadditional mapping coefficients and zenith delay values.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileGpt</div></div></td><td>filename</td><td>gridded GPT data</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">aHeight</div></div></td><td>double</td><td>parameter a (height correction)</td></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">bHeight</div></div></td><td>double</td><td>parameter b (height correction)</td></tr>\n<tr class=\"\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config optional\">cHeight</div></div></td><td>double</td><td>parameter c (height correction)</td></tr>\n</table>\n\n<h2 id=\"mendesAndPavlis\">MendesAndPavlis</h2><p></p><p>Tropospheric delays based on the Mendes-Pavlis model that employs meteorological data.\n(Mendes et al. (2002), <a href=\"https://doi.org/10.1029/2001GL014394\">10.1029/2001GL014394</a> and\nMendes and Pavlis (2004), <a href=\"https://doi.org/10.1029/2004GL020308\">110.1029/2004GL020308</a>)</p><p>The meteorological data have to be provided via <a class=\"groops-class\" href=\"fileFormat_instrument.html\">inputfileStationMeteorology</a>.\nThis file contains the temperature, air pressure and humidity and must be first generated using the\nprograms <a class=\"groops-program\" href=\"Crd2NormalPoints.html\">Crd2NormalPoints</a>, <a class=\"groops-program\" href=\"Cstg2NormalPoints.html\">Cstg2NormalPoints</a>, <a class=\"groops-program\" href=\"Merit2NormalPoints.html\">Merit2NormalPoints</a> or <a class=\"groops-program\" href=\"Merit2FullRate.html\">Merit2FullRate</a>.\n</p>\n<table class=\"table table-hover\">\n<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>\n<tr class=\"table-light\"><td class=\"m-0\"><div class=\"h-100 config-tree depth-0\"><div class=\"h-100 config mustset\">inputfileStationMeteorology</div></div></td><td>filename</td><td></td></tr>\n</table>\n\n        </div>\n    </main>\n</body>\n</html>\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <!-- This code is licensed under GNU GPL v3 -->\n    <!-- You are allowed to freely copy, distribute and use this code, but removing author credit is strictly prohibited -->\n    <!-- Generated by http://insider.zone/tools/client-side-url-redirect-generator/ -->\n\n    <!-- REDIRECTING STARTS -->\n    <link rel=\"canonical\" href=\"html/index.html\"/>\n    <noscript>\n        <meta http-equiv=\"refresh\" content=\"0;URL=html/index.html\">\n    </noscript>\n    <!--[if lt IE 9]><script type=\"text/javascript\">var IE_fix=true;</script><![endif]-->\n    <script type=\"text/javascript\">\n        var url = \"html/index.html\";\n        if(typeof IE_fix != \"undefined\") // IE8 and lower fix to pass the http referer\n        {\n            document.write(\"redirecting...\"); // Don't remove this line or appendChild() will fail because it is called before document.onload to make the redirect as fast as possible. Nobody will see this text, it is only a tech fix.\n            var referLink = document.createElement(\"a\");\n            referLink.href = url;\n            document.body.appendChild(referLink);\n            referLink.click();\n        }\n        else { window.location.replace(url); } // All other browsers\n    </script>\n    <!-- Credit goes to http://insider.zone/ -->\n    <!-- REDIRECTING ENDS -->\n  </head>\n  <body>\n    <a href=\"html/index.html\">link to documentation</a>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/latex/.gitignore",
    "content": "# dynamic content\n# ---------------\ndocumentation.*\n!documentation.tex\n!documentation.pdf\n*.log\n"
  },
  {
    "path": "docs/latex/classes.auto.tex",
    "content": "% auto generated by GROOPS\n\n\\section{AutoregressiveModelSequence}\\label{autoregressiveModelSequenceType}\nRepresents a sequence of multivariate autoregressive (AR) models with increasing order $p$.\nThe AR models should be stored as \\file{matrix file}{matrix} in the \\reference{GROOPS definition of\nAR models}{fundamentals.autoregressiveModel}.\nThe required AR models can be computed with \\program{CovarianceMatrix2AutoregressiveModel},\nand passed to this class through\n\\config{inputfileAutoregressiveModel} in increasing order.\n\nThe main purpose of AutoregressiveModelSequence is to use AR models of the form\n\\begin{equation}\n  \\label{eq:ar-model}\n  \\mathbf{y}_e(t_i) = \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{w}(t_i),\n  \\hspace{5pt} \\mathbf{w}(t_i) \\sim \\mathcal{N}(0, \\mathbf{\\Sigma}^{(p)}_\\mathbf{w}),\n\\end{equation}\nto create pseudo-observation equations\n\\begin{equation}\n  \\label{eq:pseudo-observations-transformed}\n  0 = \\bar{\\mathbf{\\Phi}} \\Delta\\mathbf{y} + \\bar{\\mathbf{w}}, \\hspace{5pt} \\bar{\\mathbf{w}} \\sim\n  \\mathcal{N}(0, \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}}),\n\\end{equation}\nwith\n\\begin{equation}\n  \\label{eq:pseudo-observations-ar}\n  \\bar{\\mathbf{\\Phi}} =\n  \\begin{bmatrix}\n    \\mathbf{I} & & & & & \\\\\n    -\\mathbf{\\Phi}^{(1)}_1 & \\mathbf{I} & & & &  \\\\\n    -\\mathbf{\\Phi}^{(2)}_2 & -\\mathbf{\\Phi}^{(2)}_1 & \\mathbf{I} & & & \\\\\n    -\\mathbf{\\Phi}^{(3)}_3 & -\\mathbf{\\Phi}^ {(3)}_2 & -\\mathbf{\\Phi}^ {(3)}_1 & \\mathbf{I} & &  \\\\\n    & -\\mathbf{\\Phi}^{(3)}_3 & -\\mathbf{\\Phi}^ {(3)}_2 & -\\mathbf{\\Phi}^ {(3)}_1 & \\mathbf{I} &  \\\\\n    & & \\ddots & \\ddots & \\ddots & \\ddots  \\\\\n  \\end{bmatrix},\n  \\hspace{15pt}\n  \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}} =\n  \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}} =\n  \\begin{bmatrix}\n    \\mathbf{\\Sigma}^{(0)}_{\\mathbf{w}} & & & & & \\\\\n    & \\mathbf{\\Sigma}^{(1)}_{\\mathbf{w}} & & & & \\\\\n    & & \\mathbf{\\Sigma}^{(2)}_{\\mathbf{w}} & & & \\\\\n    & & & \\mathbf{\\Sigma}^{(3)}_{\\mathbf{w}} & & \\\\\n    & & & & \\mathbf{\\Sigma}^{(3)}_{\\mathbf{w}} &  \\\\\n    & & & & & \\ddots \\\\\n  \\end{bmatrix}.\n\\end{equation}\nused to constrain high-frequency temporal gravity field variations (see\n\\program{KalmanSmootherLeastSquares}, \\program{NormalsBuildShortTimeStaticLongTime},\n\\program{PreprocessingSst}).\n\nThe corresponding normal equation coefficient matrix is given by\n\\begin{equation}\n  \\label{eq:ar-normals}\n  \\bar{\\mathbf{\\Phi}}^T\\bar{\\mathbf{\\Sigma}}^{-1}_{\\bar{\\mathbf{w}}}\\bar{\\mathbf{\\Phi}}\n\\end{equation}\nand if all AR models are estimated from the same sample its inverse is a block-Toeplitz covariance matrix\n\\begin{equation}\n  (\\mathbf{\\Sigma}_{\\mathbf{y}_m})_{ij} =\n  \\begin{cases}\n \\mathbf{\\Sigma}(|j-i|) & \\text{for } i \\leq j \\\\\n \\mathbf{\\Sigma}(|j-i|))^T & \\text{otherwise}\n \\end{cases},\n\\end{equation}\nwhich can be computed using \\program{AutoregressiveModel2CovarianceMatrix}.\n\nA detailed description with applications can be found in:\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). \\url{https://doi.org/10.1007/s00190-019-01314-1}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~autoregressiveModelSequenceType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileAutoregressiveModel & \\hfuzz=500pt filename & \\hfuzz=500pt matrix file containing an AR model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma0 & \\hfuzz=500pt double & \\hfuzz=500pt a-priori sigma for white noise covariance\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Border}\\label{borderType}\nWith this class you can select one or more region on the surface of the Earth.\nIn every instance of Border you can choose whether the specific region is excluded\nfrom the overall result with the switch \\config{exclude}.\nTo determine whether a specific point will be used furthermore the following algorithm will be applied:\nIn a first step all points are selected if first border excludes points otherwise all points excluded.\nWhen every point will be tested for each instance of border from top to bottom.\nIf the point is not in the selected region nothing happens.\nOtherwise it will included or excluded depending on the switch \\config{exclude}.\n\nFirst Example: The border excludes all continental areas.\nThe result are points on the oceans only.\n\nSecond Example: First border describes the continent north america. The next borders\nexcludes the great lakes and the last border describes Washington island.\nIn this configuration points are selected if they are inside north america\nbut not in the area of the great lakes. But if the point is on Washington island\nit will be included again.\n\n\n\\subsection{Rectangle}\nThe region is restricted along lines of geographical coordinates.\n\\config{minPhi} and \\config{maxPhi} describe the lower and the upper bound of the region.\n\\config{minLambda} and \\config{maxLambda} define the left and right bound.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minLambda & \\hfuzz=500pt angle & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxLambda & \\hfuzz=500pt angle & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minPhi & \\hfuzz=500pt angle & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxPhi & \\hfuzz=500pt angle & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exclude & \\hfuzz=500pt boolean & \\hfuzz=500pt dismiss points inside\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Cap}\nThe region is defined by a spherical cap with the center given in geographical coordinates\nlongitude (\\config{lambdaCenter}) and latitude (\\config{phiCenter}).\nThe radius of the cap is given as aperture angle \\config{psi}.\n\n\\fig{!hb}{0.4}{borderCap}{fig:borderCap}{spherical cap}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~lambdaCenter & \\hfuzz=500pt angle & \\hfuzz=500pt longitude of the center of the cap\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~phiCenter & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of the center of the cap\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~psi & \\hfuzz=500pt angle & \\hfuzz=500pt aperture angle (radius)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exclude & \\hfuzz=500pt boolean & \\hfuzz=500pt dismiss points inside\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Polygon}\\label{borderType:polygon}\nThe region is defined by \\configFile{inputfilePolygon}{polygon}\ncontaining one or more polygons given in longitude and latitude.\nAn additional \\config{buffer} around the polygon can be defined.\nUse a negative value to shrink the polygon area.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePolygon & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~buffer & \\hfuzz=500pt double & \\hfuzz=500pt buffer around polygon [km], \\$<\\$0: inside\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exclude & \\hfuzz=500pt boolean & \\hfuzz=500pt dismiss points inside\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Condition}\\label{conditionType}\nTest for conditions. See \\reference{Loop and conditions}{general.loopsAndConditions} for usage.\n\n\n\\subsection{FileExist}\nCheck for a file or directory existing.\nSupports wildcards * for any number of characters and ? for exactly one character.\nFiles smaller than \\config{minSize} are treated as non-existent.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~file & \\hfuzz=500pt filename & \\hfuzz=500pt supports wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minimumSize & \\hfuzz=500pt uint & \\hfuzz=500pt minimum file size in byte.\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Command}\nExecute command and check success.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~command & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~silently & \\hfuzz=500pt boolean & \\hfuzz=500pt without showing the output.\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Expression}\\label{conditionType:expression}\nEvaluate expression.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~expression & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Matrix}\nEvaluate elements of a \\configClass{matrix}{matrixGeneratorType} based on an expression.\nIf \\config{all}=\\verb|yes|, all elements of the matrix must evaluate to true\nfor the condition to be fulfilled, otherwise any element evaluating to true is sufficient.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt expression is evaluated for each element of resulting matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~expression & \\hfuzz=500pt expression & \\hfuzz=500pt (variable: data) evaluated for each element\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~all & \\hfuzz=500pt boolean & \\hfuzz=500pt all (=yes)/any (=no) elements must evaluate to true\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{MatrixEmpty}\nEvaluate if \\file{matrix}{matrix} (or \\file{instrument}{instrument}) file is empty/has zero size.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StringContainsPattern}\nDetermines if there is a match between a \\config{pattern} and some subsequence in a \\config{string}.\nSupports wildcards * for any number of characters and ? for exactly one character.\nIf \\config{isRegularExpression} is set, \\config{pattern} is interpreted as a\nregular expression instead. In any case, the \\reference{text parser}{general.parser:text}\nis applied beforehand.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~string & \\hfuzz=500pt filename & \\hfuzz=500pt should contain a \\{variable\\}\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~pattern & \\hfuzz=500pt filename & \\hfuzz=500pt supports wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~isRegularExpression & \\hfuzz=500pt boolean & \\hfuzz=500pt pattern is  a regular expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~caseSensitive & \\hfuzz=500pt boolean & \\hfuzz=500pt treat lower and upper case as distinct\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StringMatchPattern}\nDetermines if a \\config{pattern} matches the entire \\config{string}.\nSupports wildcards * for any number of characters and ? for exactly one character.\nIf \\config{isRegularExpression} is set, \\config{pattern} is interpreted as a\nregular expression instead. In any case, the \\reference{text parser}{general.parser:text}\nis applied beforehand.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~string & \\hfuzz=500pt filename & \\hfuzz=500pt should contain a \\{variable\\}\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~pattern & \\hfuzz=500pt filename & \\hfuzz=500pt supports wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~isRegularExpression & \\hfuzz=500pt boolean & \\hfuzz=500pt pattern is  a regular expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~caseSensitive & \\hfuzz=500pt boolean & \\hfuzz=500pt treat lower and upper case as distinct\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{And}\nAll conditions must be met (with short-circuit evaluation).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Or}\nOne of the conditions must be met (with short-circuit evaluation).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Not}\nThe result of the condition is inverted.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{CovariancePod}\\label{covariancePodType}\nProvides arc-wise covariance matrices for precise orbit data.\nTemporal correlations are modeled in the orbit system (along, cross, radial).\nThe \\configFile{inputfileCovarianceFunction}{matrix} provides temporal covariance functions for each axis.\nFrom the diagonal matrix for each time step\n\\begin{equation}\n  Cov_{3\\times3}(t) = \\text{diag}(cov_x(t), cov_y(t), cov_z(t))\n\\end{equation}\nthe Toeplitz covariance matrix for an arc is constructed\n\\begin{equation}\n  \\M C = \\begin{pmatrix}\n    Cov(t_0) & Cov(t_1) & \\cdots   &          &        &        \\\\\n    Cov(t_1) & Cov(t_0) & Cov(t_1) & \\cdots   &        &        \\\\\n    \\cdots   & Cov(t_1) & Cov(t_0) & Cov(t_1) & \\cdots &        \\\\\n             & \\cdots   & \\ddots   & \\ddots   & \\ddots & \\cdots \\\\\n  \\end{pmatrix}\n\\end{equation}\n\nThe epoch-wise $3\\times3$ covariance matrices given by \\configFile{inputfileCovariancePodEpoch}{instrument}\nare eigenvalue-decomposed\n\\begin{equation}\n  \\M C_{3\\times3}(t_i) = \\M Q \\M\\Lambda \\M Q^T,\n\\end{equation}\nwhere $\\M Q$ is an orthogonal matrix and $\\M\\Lambda$ diagonal.\nThis is used to split the covariances matrices\n\\begin{equation}\n  \\M C_{3\\times3}(t_i) = \\M D(t_i) \\M D(t_i)^T = (\\M Q \\M\\Lambda^{1/2} \\M Q^T)(\\M Q \\M\\Lambda^{1/2} \\M Q^T)^T,\n\\end{equation}\nand to compose a block diagonal matrix for an arc\n\\begin{equation}\n  \\M D = \\text{diag}(\\M D(t_1), \\M D(t_2), \\ldots, \\M D(t_2)).\n\\end{equation}\n\nThe complete covariance matrix of an arc is given by\n\\begin{equation}\n  \\M C_{arc} = \\sigma_0^2 \\sigma_{arc}^2 \\M D \\M C \\M D^T +\n  \\text{diag}(\\sigma_1^2\\M I_{3\\times3}, \\sigma_2^2\\M I_{3\\times3}, \\ldots, \\sigma_n^2\\M I_{3\\times3})\n\\end{equation}\nwhere \\config{sigma}~$\\sigma_0$ is an overall factor\nand the arc specific factors $\\sigma_{arc}$ can be provided with \\configFile{inputfileSigmasPerArc}{matrix}.\nThe last matrix can be used to downweight outliers in single epochs and will be added if\n\\configFile{inputfileSigmasPerEpoch}{instrument} is provided.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePodType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt general variance factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt different accuracies for each arc (multiplied with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt different accuracies for each epoch (added)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt covariances in time for along, cross, and radial direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch-wise covariances\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{CovarianceSst}\\label{covarianceSstType}\nProvides arc-wise covariance matrices for satellite-to-satellite observations (SST).\nThe \\configFile{inputfileCovarianceFunction}{matrix} provides a temporal covariance function.\nFrom it the Toeplitz covariance matrix is constructed\n\\begin{equation}\n  \\M C = \\begin{pmatrix}\n    cov(t_0) & cov(t_1) & \\cdots   &          &        &        \\\\\n    cov(t_1) & cov(t_0) & cov(t_1) & \\cdots   &        &        \\\\\n    \\cdots   & cov(t_1) & cov(t_0) & cov(t_1) & \\cdots &        \\\\\n             & \\cdots   & \\ddots   & \\ddots   & \\ddots & \\cdots \\\\\n  \\end{pmatrix} \\\\\n\\end{equation}\n\nThe complete covariance matrix of an arc is given by\n\\begin{equation}\n  \\M C_{arc} = \\sigma_0^2 \\sigma_{arc}^2 \\M C + \\sigma_{S,arc}^2 \\M S_{arc}+ \\text{diag}(\\sigma_1^2, \\sigma_2^2, \\ldots, \\sigma_n^2)\n\\end{equation}\nwhere \\config{sigma}~$\\sigma_0$ is an overall factor and the arc specific factors $\\sigma_{arc}$\ncan be provided with \\configFile{inputfileSigmasPerArc}{matrix}.\nThe second term describes general covariance matrices for each arc\n\\configFile{inputfileCovarianceMatrixArc}{matrix} together with the factors $\\sigma_{S,arc}$ from \\config{sigmasCovarianceMatrixArc}.\nThe last matrix can be used to downweight outliers in single epochs and will be added if\n\\configFile{inputfileSigmasPerEpoch}{instrument} is provided.\n\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSstType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt general variance factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt different accuaries for each arc (multplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt different accuaries for each epoch (added)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt one matrix file per arc. Use \\{arcNo\\} as template\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigmasCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt vector with one sigma for each covarianceMatrixArc\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{DigitalFilter}\\label{digitalFilterType}\nDigital filter implementation for the filtering of equally spaced time series. This class implements the filter equations as\n\\begin{equation}\\label{digitalFilterType:arma}\n  \\sum_{l=0}^Q a_l y_{n-l} = \\sum_{k=-p_0}^{P-p_0-1} b_k x_{n-k}, \\hspace{25pt} a_0 = 1,\n\\end{equation}\nwhere $Q$ is the autoregressive (AR) order and $P$ is the moving average (MA) order. Note that the MA part can also be non-causal.\nThe characteristics of a filter cascade can be computed by the programs \\program{DigitalFilter2FrequencyResponse} and \\program{DigitalFilter2ImpulseResponse}.\nTo apply a filter cascade to a time series (or an instrument file ) use \\program{InstrumentFilter}.\nEach filter can be applyed in forward and backward direction by setting \\config{backwardDirection}.\nIf the same filter is applied in both directions, the combined filter has zero phase and the squared magnitude response.\nSetting \\config{inFrequencyDomain} to true applies the transfer function of the filter to the DFT of the input and synthesizes the result, i.e.:\n\\begin{equation}\n  y_n = \\mathcal{F}^{-1}\\{H\\cdot\\mathcal{F}\\{x_n\\}\\}.\n\\end{equation}\nThis is equivalent to setting \\config{padType} to \\config{periodic}.\n\nTo reduce warmup effects, the input time series can be padded by choosing a \\config{padType}:\n\\begin{itemize}\n\\item \\config{none}: no padding is applied\n\\item \\config{zero}: zeros are appended at the beginning and end of the input time series\n\\item \\config{constant}: the beginning of the input time series is padded with the first value, the end is padded with the last value\n\\item \\config{periodic}: periodic continuation of the input time series (i.,e. the beginning is padded with the last epochs and the end is padded with the first epochs)\n\\item \\config{symmetric}: beginning and end are reflected around the first and last epoch respectively\n\\end{itemize}\n\n\n\\subsection{MovingAverage}\nMoving average (boxcar) filter. For odd lengths, this filter is symmetric and has therefore no phase shift. For even lengths, a phase shift of half a cycle is introduced.\n\n\\[\n  y_n = \\sum_{k=-\\lfloor\\frac{P}{2}\\rfloor}^{\\lfloor\\frac{P}{2}\\rfloor} \\frac{1}{P}x_{n-k}\n\\]\n\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~length & \\hfuzz=500pt uint & \\hfuzz=500pt number of epochs in averaging operator\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Median}\nMoving median filter of length $n$. The filter output at epoch $k$ is the median of the set start at $k-n/2$ to $k+n/2$.\nThe filter length $n$ should be uneven to avoid a phase shift.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~length & \\hfuzz=500pt uint & \\hfuzz=500pt length of the moving window [epochs]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Derivative}\nSymmetric MA filter for numerical differentiation using polynomial approximation. The input time series is approximated by a moving polynomial of degree \\config{polynomialDegree}, by solving\n\\begin{equation}\n  \\begin{bmatrix} x(t_k+\\tau_0) \\\\ \\vdots \\\\ x(t_k+\\tau_M) \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  1      & \\tau_0 & \\tau_0^2 & \\cdots & \\tau_0^M \\\\\n  \\vdots & \\vdots & \\vdots   &        & \\vdots   \\\\\n  1      & \\tau_M & \\tau_M^2 & \\cdots & \\tau_M^M \\\\\n  \\end{bmatrix}%^{-1}\n  \\begin{bmatrix}\n  a_0 \\\\ \\vdots \\\\ a_M\n  \\end{bmatrix}\n  \\qquad\\text{with}\\quad\n  \\tau_j =  (j-M/2)\\cdot \\Delta t,\n\\end{equation}\nfor each time step $t_k$ ($\\Delta t$ is the \\config{sampling} of the time series).\nThe filter coefficients for the $k$-th derivative are obtained by taking the appropriate row of the inverse coefficient matrix $\\mathbf{W}$:\n\\begin{equation}\n  b_n = \\prod_{i=0}^{k-1} (k-i) \\mathbf{w}_{2,:}.\n\\end{equation}\nThe \\config{polynomialDegree} should be even if no phase shift should be introduced.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of approximation polynomial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~derivative & \\hfuzz=500pt uint & \\hfuzz=500pt take kth derivative\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt assumed time step between points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Integral}\nNumerical integration using polynomial approximation.\nThe input time series is approximated by a moving polynomial of degree \\config{polynomialDegree}\nby solving\n\\begin{equation}\n  \\begin{bmatrix} x(t_k+\\tau_0) \\\\ \\vdots \\\\ x(t_k+\\tau_M) \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  1      & \\tau_0 & \\tau_0^2 & \\cdots & \\tau_0^M \\\\\n  \\vdots & \\vdots & \\vdots   &        & \\vdots   \\\\\n  1      & \\tau_M & \\tau_M^2 & \\cdots & \\tau_M^M \\\\\n  \\end{bmatrix}%^{-1}\n  \\begin{bmatrix}\n  a_0 \\\\ \\vdots \\\\ a_M\n  \\end{bmatrix}\n  \\qquad\\text{with}\\quad\n  \\tau_j =  (j-M/2)\\cdot \\Delta t,\n\\end{equation}\nfor each time step $t_k$ ($\\Delta t$ is the \\config{sampling} of the time series).\nThe numerical integral for each time step $t_k$ is approximated by the center interval of the estimated polynomial.\n\n\\fig{!hb}{0.7}{DigitalFilter_integral}{fig:DigitalFilterIntegral}{Numerical integration by polynomial approximation.}\n\n\\config{polynomialDegree} should be even to avoid a phase shift.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of approximation polynomial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt assumed time step between points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Correlation}\nCorrelation ($\\rho$) of \\config{corr} is introduced into the time series:\n\\begin{equation}\n  y_n = \\rho\\cdot y_{n-1} + \\sqrt{1-\\rho^2}x_n.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~correlation & \\hfuzz=500pt double & \\hfuzz=500pt correlation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~backwardDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in backward direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{GraceLowpass}\nLow pass and differentation filter as used for GRACE KBR and ACC data in the Level1A processing.\n\n\\fig{!hb}{0.8}{DigitalFilter_graceLowpass}{fig:DigitalFilterGraceLowpass}{Amplitude response of the low pass filter used in the L1A processing.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rawDataRate & \\hfuzz=500pt double & \\hfuzz=500pt sampling frequency in Hz (fs).\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~convolutionNumber & \\hfuzz=500pt uint & \\hfuzz=500pt number of self convolutions of the filter kernel\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fitInterval & \\hfuzz=500pt double & \\hfuzz=500pt length of the filter kernel [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lowPassBandwith & \\hfuzz=500pt double & \\hfuzz=500pt target low pass bandwidth\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~normFrequency & \\hfuzz=500pt double & \\hfuzz=500pt norm filter at this frequency [Hz] (default: GRACE dominant (J2) signal frequency)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~reduceQuadraticFit & \\hfuzz=500pt boolean & \\hfuzz=500pt remove-\\$>\\$filter-\\$>\\$restore quadratic fit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~derivative & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~derivative1st & \\hfuzz=500pt  & \\hfuzz=500pt range rate\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~derivative2nd & \\hfuzz=500pt  & \\hfuzz=500pt range acceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Butterworth}\nDigital implementation of the Butterworth filter. The design of the filter is done by modifying the analog (continuous time) transfer function, which is\nthen transformed into the digital domain by using the bilinear transform. The filter coefficients are then determined by a least squares adjustment in time domain.\n\nThe \\config{filterType} can be \\config{lowpass}, \\config{highpass}, where one cutoff frequency has to be specified, and \\config{bandpass} and \\config{bandstop} where to cutoff frequencies have to be specified.\nCutoff frequencies must be given as normalized frequency $w_n = f/f_{\\text{nyq}}$. For a cutoff frequency of 30~mHz for a time series sampled with 5~seconds gives a normalized frequency of $0.03/0.1 = 0.3$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt filter order\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt filter type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~lowpass & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Wn & \\hfuzz=500pt double & \\hfuzz=500pt normalized cutoff frequency (f\\_c / f\\_nyq)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~highpass & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Wn & \\hfuzz=500pt double & \\hfuzz=500pt normalized cutoff frequency (f\\_c / f\\_nyq)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~bandpass & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Wn1 & \\hfuzz=500pt double & \\hfuzz=500pt lower normalized cutoff frequency (f\\_c / f\\_nyq)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Wn2 & \\hfuzz=500pt double & \\hfuzz=500pt upper normalized cutoff frequency (f\\_c / f\\_nyq)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~bandstop & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Wn1 & \\hfuzz=500pt double & \\hfuzz=500pt lower normalized cutoff frequency (f\\_c / f\\_nyq)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Wn2 & \\hfuzz=500pt double & \\hfuzz=500pt upper normalized cutoff frequency (f\\_c / f\\_nyq)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~backwardDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in backward direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{File}\nRead filter coefficients of \\eqref{digitalFilterType:arma} from a coefficient file.\nOne column might define the index $n$\nof the coefficients $a_n$ and $b_n$ in the other columns.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with filter coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~index & \\hfuzz=500pt expression & \\hfuzz=500pt index of coefficients (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~bn & \\hfuzz=500pt expression & \\hfuzz=500pt MA coefficients (moving average) (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~an & \\hfuzz=500pt expression & \\hfuzz=500pt AR coefficients (autoregressive) (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~backwardDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in backward direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Wavelet}\nFilter representation of a wavelet.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileWavelet & \\hfuzz=500pt filename & \\hfuzz=500pt wavelet coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt filter type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~lowpass & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~highpass & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~level & \\hfuzz=500pt uint & \\hfuzz=500pt compute filter for specific decomposition level\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~backwardDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in backward direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Notch}\nImplemented after Christian Siemes' dissertation, page 106.\n\n\\fig{!hb}{0.6}{DigitalFilter_notch}{fig:DigitalFilterNotch}{Amplitude response of a notch filter of order three with default settings.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~notchFrequency & \\hfuzz=500pt double & \\hfuzz=500pt normalized notch frequency w\\_n = (f\\_n/f\\_nyq)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~bandWidth & \\hfuzz=500pt double & \\hfuzz=500pt bandwidth at -3db. Quality factor of filter Q = w\\_n/bw\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~backwardDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in backward direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Decorrelation}\nMoving average decorrelation filter based on eigendecomposition of a Toeplitz covariance matrix.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function of time series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TimeLag}\nLag operator in digital filter representation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~lag & \\hfuzz=500pt int & \\hfuzz=500pt lag epochs: 1 (lag); -1 (lead)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inFrequencyDomain & \\hfuzz=500pt boolean & \\hfuzz=500pt apply filter in frequency domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~padType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt no padding is applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero & \\hfuzz=500pt  & \\hfuzz=500pt zero padding\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt  & \\hfuzz=500pt pad using first and last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~periodic & \\hfuzz=500pt  & \\hfuzz=500pt periodic continuation of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~symmetric & \\hfuzz=500pt  & \\hfuzz=500pt symmetric continuation around the matrix edges\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ReduceFilterOutput}\nRemoves the filtered signal from the input, i.e. the input is passed\nthrough a \\configClass{digitalFilter}{digitalFilterType} with a frequency response of $1-H(f)$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~filter & \\hfuzz=500pt \\hyperref[digitalFilterType]{digitalFilter} & \\hfuzz=500pt remove filter output from input signal\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Doodson}\\label{doodson}\nThis is a string which describes a tidal frequency either coded as Doodson number\nor using Darwin´s name, e.g. \\verb|255.555| or \\verb|M2|.\n\nThe following names are defined:\n\\begin{itemize}\n\\item \\verb|055.565|: \\verb|om1|  \\item \\verb|055.575|: \\verb|om2|     \\item \\verb|056.554|: \\verb|sa|\n\\item \\verb|056.555|: \\verb|sa|   \\item \\verb|057.555|: \\verb|ssa|     \\item \\verb|058.554|: \\verb|sta|\n\\item \\verb|063.655|: \\verb|msm|  \\item \\verb|065.455|: \\verb|mm|      \\item \\verb|073.555|: \\verb|msf|\n\\item \\verb|075.555|: \\verb|mf|   \\item \\verb|083.655|: \\verb|mstm|    \\item \\verb|085.455|: \\verb|mtm|\n\\item \\verb|093.555|: \\verb|msq|  \\item \\verb|093.555|: \\verb|msqm|    \\item \\verb|125.755|: \\verb|2q1|\n\\item \\verb|127.555|: \\verb|sig1| \\item \\verb|127.555|: \\verb|sigma1|  \\item \\verb|135.655|: \\verb|q1|\n\\item \\verb|137.455|: \\verb|ro1|  \\item \\verb|137.455|: \\verb|rho1|    \\item \\verb|145.555|: \\verb|o1|\n\\item \\verb|147.555|: \\verb|tau1| \\item \\verb|155.655|: \\verb|m1|      \\item \\verb|157.455|: \\verb|chi1|\n\\item \\verb|162.556|: \\verb|pi1|  \\item \\verb|163.555|: \\verb|p1|      \\item \\verb|164.555|: \\verb|s1|\n\\item \\verb|165.555|: \\verb|k1|   \\item \\verb|166.554|: \\verb|psi1|    \\item \\verb|167.555|: \\verb|fi1|\n\\item \\verb|167.555|: \\verb|phi1| \\item \\verb|173.655|: \\verb|the1|    \\item \\verb|173.655|: \\verb|theta1|\n\\item \\verb|175.455|: \\verb|j1|   \\item \\verb|183.555|: \\verb|so1|     \\item \\verb|185.555|: \\verb|oo1|\n\\item \\verb|195.455|: \\verb|v1|   \\item \\verb|225.855|: \\verb|3n2|     \\item \\verb|227.655|: \\verb|eps2|\n\\item \\verb|235.755|: \\verb|2n2|  \\item \\verb|237.555|: \\verb|mu2|     \\item \\verb|237.555|: \\verb|mi2|\n\\item \\verb|245.655|: \\verb|n2|   \\item \\verb|247.455|: \\verb|nu2|     \\item \\verb|247.455|: \\verb|ni2|\n\\item \\verb|253.755|: \\verb|gam2| \\item \\verb|254.556|: \\verb|alf2|    \\item \\verb|255.555|: \\verb|m2|\n\\item \\verb|256.554|: \\verb|bet2| \\item \\verb|257.555|: \\verb|dlt2|    \\item \\verb|263.655|: \\verb|la2|\n\\item \\verb|263.655|: \\verb|lmb2| \\item \\verb|263.655|: \\verb|lambda2| \\item \\verb|265.455|: \\verb|l2|\n\\item \\verb|271.557|: \\verb|2t2|  \\item \\verb|272.556|: \\verb|t2|      \\item \\verb|273.555|: \\verb|s2|\n\\item \\verb|274.554|: \\verb|r2|   \\item \\verb|275.555|: \\verb|k2|      \\item \\verb|283.655|: \\verb|ksi2|\n\\item \\verb|285.455|: \\verb|eta2| \\item \\verb|355.555|: \\verb|m3|      \\item \\verb|381.555|: \\verb|t3|\n\\item \\verb|382.555|: \\verb|s3|   \\item \\verb|383.555|: \\verb|r3|      \\item \\verb|435.755|: \\verb|n4|\n\\item \\verb|445.655|: \\verb|mn4|  \\item \\verb|455.555|: \\verb|m4|      \\item \\verb|473.555|: \\verb|ms4|\n\\item \\verb|491.555|: \\verb|s4|   \\item \\verb|655.555|: \\verb|m6|      \\item \\verb|855.555|: \\verb|m8|\n\\end{itemize}\n\n\\clearpage\n%==================================\n\n\\section{EarthRotation}\\label{earthRotationType}\nThis class realize the transformation between a terestrial\nreference frame (TRF) and a celestial reference frame (CRF).\n\n\n\\subsection{File}\\label{earthRotationType:file}\nThis class realize the transformation by interpolation from file.\nThis file can be created with \\program{EarthOrientationParameterTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for polynomial interpolation\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Iers2010}\nThis class realize the transformation according to the IERS2010 conventions\ngiven by the \\emph{International Earth Rotation and Reference Systems Service} (IERS).\nA file with the earth orientation parameter is needed (\\configFile{inputfileEOP}{earthOrientationParameter}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~truncatedNutation & \\hfuzz=500pt boolean & \\hfuzz=500pt use truncated nutation model (IAU2006B)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Iers2010b}\\label{earthRotationType:iers2010b}\nThis class realize the transformation according to the IERS2010 conventions\ngiven by the \\emph{International Earth Rotation and Reference Systems Service} (IERS).\nA file with the earth orientation parameter is needed (\\configFile{inputfileEOP}{earthOrientationParameter}).\nIncludes additional high-frequency EOP models (\\configFile{inputfileDoodsonEOP}{doodsonEarthOrientationParameter}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileDoodsonEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Iers2003}\nThis class realize the transformation according to IERS2003 conventions\ngiven by the \\emph{International Earth Rotation and Reference Systems Service} (IERS).\nA file with the earth orientation parameter is needed (\\configFile{inputfileEOP}{earthOrientationParameter}).\n\nThe following subroutines are used:\n\\begin{itemize}\n\\item BPN2000.f,\n\\item ERA2000.f,\n\\item pmsdnut.f,\n\\item POM2000.f,\n\\item SP2000.f,\n\\item T2C2000.f,\n\\item XYS2000A.f\n\\end{itemize}\nfrom \\url{ftp://maia.usno.navy.mil/conv2000/chapter5/} and\n\\begin{itemize}\n\\item orthoeop.f\n\\end{itemize}\nfrom \\url{ftp://maia.usno.navy.mil/conv2000/chapter8/}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Iers1996}\nVery old.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNutation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Gmst}\nThe transformation is realized as rotation about the z-axis.\nThe angle ist given by the Greenwich Mean Siderial Time (GMST).\n\\begin{verbatim}\n  Double Tu0 = (timeUTC.mjdInt()-51544.5)/36525.0;\n\n  Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))\n               + (8640184.812866/(24*60*60))*Tu0\n               + (0.093104/(24*60*60))*Tu0*Tu0\n               + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;\n  Double r = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;\n  GMST = fmod(2*PI*(GMST0 + r * timeUTC.mjdMod()), 2*PI);\n\\end{verbatim}\n\n\n\\subsection{Earth Rotation Angle (ERA)}\nThe transformation is realized as rotation about the z-axis.\nThe angle ist given by the Earth Rotation Angle (ERA) as\n\\begin{verbatim}\n  const Time T = timeUT1-mjd2time(J2000);\n  ERA = fmod(2*PI*(0.7790572732640 + T.mjdMod() + 0.00273781191135448*T.mjd()), 2*PI);\n\\end{verbatim}\n\n\n\\subsection{Z-Axis}\nThe transformation is realized as rotation about the z-axis.\nYou must specify the angle (\\config{initialAngle}) at \\config{time0} and\nthe angular velocity (\\config{angularVelocity}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~initialAngle & \\hfuzz=500pt double & \\hfuzz=500pt Angle at time0 [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~angularVelocity & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time0 & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StarCamera}\nThis class reads quaternions from an instrument file and interpolates to the given time stamp.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of interpolation polynomial\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{MoonRotation}\nThis class realizes the transformation between the moon-fixed system\n(Principal Axis System (PA) or Mean Earth System (ME))\nand the ICRS according to the JPL ephemeris file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileEphemerides & \\hfuzz=500pt filename & \\hfuzz=500pt librations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~moonfixedSystem & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~PA & \\hfuzz=500pt  & \\hfuzz=500pt Principal Axis System\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ME & \\hfuzz=500pt  & \\hfuzz=500pt Mean Earth System\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Eclipse}\\label{eclipseType}\nShadowing of satellites by moon and Earth provided as factor\nbetween $[0,1]$ with 0: full shadow and 1: full sun light.\n\n\n\\subsection{Conical}\n\\fig{!hb}{0.8}{eclipseConical}{fig:eclipseConical}{Modelling umbra and penumbra.}\n\n\n\\subsection{SOLAARS}\nEarth’s penumbra modeling with Solar radiation pressure with\nOblateness and Lower Atmospheric Absorption, Refraction, and Scattering (SOLAARS).\nSee Robertson, Robbie. (2015),\nHighly Physical Solar Radiation Pressure Modeling During Penumbra Transitions (pp. 67-75).\n\n\\clearpage\n%==================================\n\n\\section{Ephemerides}\\label{ephemeridesType}\nEphemerides of Sun, Moon and planets.\nThe coordinate system is defined as center of \\configClass{origin}{planetType}.\n\n\n\\section{JPL}\\label{ephemeridesType:jpl}\nUsing \\verb|DExxx| ephemerides from NASA Jet Propulsion Laboratory (JPL).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileEphemerides & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~origin & \\hfuzz=500pt \\hyperref[planetType]{planet} & \\hfuzz=500pt center of coordinate system\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Forces}\\label{forcesType}\nThis class provides the forces acting on a satellite.\nThis encompasses \\configClass{gravityfield}{gravityfieldType}, \\configClass{tides}{tidesType}\nand \\configClass{miscAccelerations}{miscAccelerationsType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~forcesType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~tides & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~miscAccelerations & \\hfuzz=500pt \\hyperref[miscAccelerationsType]{miscAccelerations} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{GnssAntennaDefintionList}\\label{gnssAntennaDefintionListType}\nProvides a list of GnssAntennaDefinitions as used in \\program{GnssAntennaDefinitionCreate}.\n\n\n\\subsection{New}\nCreates a new antenna.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~pattern & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt pattern matching of observation types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~offsetX & \\hfuzz=500pt double & \\hfuzz=500pt [m] antenna center offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~offsetY & \\hfuzz=500pt double & \\hfuzz=500pt [m] antenna center offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~offsetZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] antenna center offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~deltaAzimuth & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] step size\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~deltaZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] step size\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~maxZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~values & \\hfuzz=500pt expression & \\hfuzz=500pt [m] expression (zenith, azimuth: variables)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FromFile}\nSelect all or the first antenna from an \\file{antenna definition file}{gnssAntennaDefinition}\nwhich matches the wildcards.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~onlyFirstMatch & \\hfuzz=500pt boolean & \\hfuzz=500pt otherwise all machting antennas included\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FromStationInfo}\nSelect all antennas from an \\file{antenna definition file}{gnssAntennaDefinition}\nwhich are used by a station within a defined time interval.\nWith \\config{specializeAntenna} an individual antenna is created for each different serial number\nusing the general type specific values from file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt only antennas used in this time interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt only antennas used in this time interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~specializeAntenna & \\hfuzz=500pt boolean & \\hfuzz=500pt e.g. separate different serial numbers from stationInfo\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Resample}\nThe azimuth and elevation dependent antenna center variations (patterns) of all \\config{antenna}s\nare resampled to a new resolution.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt \\hyperref[gnssAntennaDefintionListType]{gnssAntennaDefintionList} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaAzimuth & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] step size, empty: no change\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] step size, empty: no change\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree], empty: no change\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Transform}\nThis class can be used to separate general antenna patterns for different \\configClass{gnssType}{gnssType}s.\nIf the \\config{antenna}s contain only one pattern for all GPS observations on the L1 frequency (\\verb|*1*G**|),\nthe \\config{patternTypes}=\\verb|C1*G**| and \\verb|L1*G**| create two patterns with the \\verb|*1*G**| patterm as template.\nThe first matching pattern in the \\config{antenna} is used as template.\nAlso new \\config{additionalPattern} can be added (e.g. for \\verb|*5*G**|).\nWith \\config{addExistingPatterns} all already existing patterns that don't match completely to any of the above are added.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt \\hyperref[gnssAntennaDefintionListType]{gnssAntennaDefintionList} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~patternTypes & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt gnssType for each pattern (first match is used)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~additionalPattern & \\hfuzz=500pt sequence & \\hfuzz=500pt additional new patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt pattern matching of observation types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~offsetX & \\hfuzz=500pt double & \\hfuzz=500pt [m] antenna center offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~offsetY & \\hfuzz=500pt double & \\hfuzz=500pt [m] antenna center offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~offsetZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] antenna center offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~deltaAzimuth & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] step size\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~deltaZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] step size\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~maxZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~values & \\hfuzz=500pt expression & \\hfuzz=500pt [m] expression (zenith, azimuth: variables)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~addExistingPatterns & \\hfuzz=500pt boolean & \\hfuzz=500pt add existing patterns that don't match completely any of the above\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Rename}\nReplaces parts of the descrption of \\config{antenna}s.\nThe star \"\\verb|*|\" left this part untouched.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt \\hyperref[gnssAntennaDefintionListType]{gnssAntennaDefintionList} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SetZero}\nThe antenna center variations (patterns) or offsets\nof all \\config{antenna}s are set to zero.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt \\hyperref[gnssAntennaDefintionListType]{gnssAntennaDefintionList} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~patternTypes & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt only matching patterns, default: all\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~zeroOffset & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~zeroPattern & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RemoveCenterMean}\nThe antenna offset and antenna variations (patterns) are inseparable parts of the\nantenna model. With \\config{removeOffset} an estimated offset is removed from\nall selected patterns and added to the offset. With \\config{removeMean} an estimated\nconstant is removed additionally as it cannot be seperated from signal biases.\nThe mean and offset are defined as discretized (\\config{deltaAzimuth},\n\\config{dZenith}) integral of the spherical cap from zenith down to \\config{maxZenith}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt \\hyperref[gnssAntennaDefintionListType]{gnssAntennaDefintionList} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~patternTypes & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt only matching patterns, default: all\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~removeOffset & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaAzimuth & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] sampling of pattern to estimate center/constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] sampling of pattern to estimate center/constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] sampling of pattern to estimate center/constant\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{GnssParametrization}\\label{gnssParametrizationType}\nThis class defines the models and parameters of the linearized observation equations\nfor all phase and code measurements (see \\program{GnssProcessing})\n\\begin{equation}\\label{gnssParametrizationType:model}\n  \\M l - \\M f(\\M x_0) = \\left.\\frac{\\partial \\M f(\\M x)}{\\partial \\M x}\\right|_{\\M x_0} \\Delta\\M x + \\M\\epsilon,\n\\end{equation}\nwhere the left side is the observation vector minus the effects computed from the a priori models.\nAfter each least squares adjustment\n(see \\configClass{GnssProcessing:processingStep:estimate}{gnssProcessingStepType:estimate})\nthe a priori parameters are updated\n\\begin{equation}\\label{gnssParametrizationType:update}\n  \\M x_0 := \\M x_0 + \\Delta\\hat{\\M x}.\n\\end{equation}\nThe vector $\\M x_0$ can be written with\n\\configClass{GnssProcessing:processingStep:writeAprioriSolution}{gnssProcessingStepType:writeAprioriSolution}.\nAny \\config{outputfiles} defined in the parametrizations are written with\n\\configClass{GnssProcessing:processingStep:writeResults}{gnssProcessingStepType:writeResults}.\n\nEach parametrization (and possible constraint equations) has a \\config{name} which enables\nactivating/deactivating the estimation of subsets of $\\Delta\\M x$ with\n\\configClass{GnssProcessing:processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations}.\nThe a priori model $\\M f(\\M x_0)$ is unaffected and is always reduced.\n\nThe model for the different observation types can be described as\n\\begin{equation}\\label{gnssParametrizationType:gnssFullModel}\n\\begin{split}\n  f[\\tau\\nu a]_r^s(\\M x) &= \\text{geometry}(\\M r_r^s) + \\text{clock}^s(t) + \\text{clock}_r(t) \\\\\n               &+ \\text{ionosphere}([\\tau\\nu],t,\\M r_r^s) + \\text{troposphere}(t,\\M r_r^s) \\\\\n               &+ \\text{antenna}[\\tau\\nu a]^s  + \\text{antenna}[\\tau\\nu a]_r \\\\\n               &+ \\text{bias}[\\tau\\nu a]^s + \\text{bias}[\\tau\\nu a]_r\n               + \\lambda[L\\nu] N[L\\nu a]_r^s + \\text{other}(\\ldots) + \\epsilon[\\tau\\nu a]_r^s\n\\end{split}\n\\end{equation}\nThe notation $[\\tau\\nu a]_r^s$ describes the\nattribution to a signal type $\\tau$ (i.e., C or L), frequency $\\nu$,\nsignal attribute $a$ (e.g., C, W, Q, X), transmitting satellite $s$, and observing receiver $r$.\nIt follows the \\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition},\nsee \\reference{GnssType}{gnssType}.\n\nSee also \\program{GnssProcessing}.\n\n\n\\subsection{IonosphereSTEC}\\label{gnssParametrizationType:ionosphereSTEC}\nThe influence of the ionosphere is modelled by a STEC parameter (slant total electron content)\nin terms of $[TECU]$ between each transmitter and receiver at each epoch. These parameters are pre-eliminated\nfrom the observation equations before accumulating the normal equations.\nThis is similar to using the ionosphere-free linear combination as observations\nbut only one STEC parameter is needed for an arbitrary number of observation types.\n\nThe influence on the code and phase observation is modeled as\n\\begin{equation}\\label{gnssParametrizationType:IonosphereSTEC:STEC}\n\\begin{split}\n\\text{ionosphere}([C\\nu], STEC) &=  \\frac{40.3}{f_{\\nu}^2}STEC + \\frac{7525\\M b^T\\M k}{f_{\\nu}^3}STEC +  \\frac{r}{f_{\\nu}^4}STEC^2 \\\\\n\\text{ionosphere}([L\\nu], STEC) &= -\\frac{40.3}{f_{\\nu}^2}STEC - \\frac{7525\\M b^T\\M k}{2f_{\\nu}^3}STEC - \\frac{r}{3f_{\\nu}^4}STEC^2 + \\text{bending}(E)STEC^2\n\\end{split}\n\\end{equation}\nThe second order term depends on the \\configClass{magnetosphere}{magnetosphereType} $\\M b$\nand the direction of the signal $\\M k$.\n\nIf further information about the ionosphere is available\n(in the form of a prior model or as additional parametrizations\nsuch as \\configClass{parametrization:ionosphereMap}{gnssParametrizationType:ionosphereMap} or\n\\configClass{parametrization:ionosphereVTEC}{gnssParametrizationType:ionosphereVTEC}) the STEC\nparameters describe local and short–term scintillations. The STEC parameters are estimated\nas additions to the model and it is advised to constrain them towards zero\nwith a standard deviation of \\config{sigmaSTEC}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~apply2ndOrderCorrection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply ionospheric correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~apply3rdOrderCorrection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply ionospheric correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~applyBendingCorrection & \\hfuzz=500pt boolean & \\hfuzz=500pt apply ionospheric correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~magnetosphere & \\hfuzz=500pt \\hyperref[magnetosphereType]{magnetosphere} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaSTEC & \\hfuzz=500pt expression & \\hfuzz=500pt expr. for sigma [TECU] for STEC constraint, variable E (elevation) available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{IonosphereVTEC}\\label{gnssParametrizationType:ionosphereVTEC}\nThe influence of the ionosphere is modelled by a VTEC parameter (vertical total electron content)\nin terms of $[TECU]$ for every selected receiver at each epoch. Optionally, VTEC gradients in the\nNorth (x) and East (y) direction can be estimated via \\configClass{gradient}{parametrizationTemporalType}.\nThe slant TEC is computed based on the VTEC and the optional North and East gradients $\\Delta V_x$ and $\\Delta V_y$\nusing the elevation-dependent Modified Single-Layer Model (MSLM) mapping function\n\\begin{equation}\\label{gnssParametrizationType:IonosphereVTEC:STEC}\n  STEC = \\frac{VTEC + \\cos(A) \\Delta V_x + \\sin(A) \\Delta V_y}{\\cos z'}\n  \\qquad\\text{with}\\qquad\n  \\sin z'= \\left(\\frac{R}{R+H}\\right)\\sin\\left(\\alpha(\\pi/2-E)\\right)\n\\end{equation}\ninserted into eq.~\\eqref{gnssParametrizationType:IonosphereSTEC:STEC},\nwhere $A$ is the azimuth angle and $E$ is the elevation angle.\n\nThe result is written as a \\file{times series file}{instrument} at epochs with observations\ndepending on \\configClass{GnssProcessing:processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}.\n\nThis class provides a simplified model of the ionosphere for single receivers\nand enables the separation of the TEC and signal biases, meaning\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases} becomes estimable.\nLocal and short-term scintillations should be considered by adding loosely constrained\n\\configClass{parametrization:ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:VTEC::<time>|,\n\\item \\verb|<station>:VTECGradient.x:<temporal>:<interval>|,\n\\item \\verb|<station>:VTECGradient.y:<temporal>:<interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileVTEC & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, columns: MJD, VTEC, north gradient, east gradient\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mapR & \\hfuzz=500pt double & \\hfuzz=500pt constant of MSLM mapping function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mapH & \\hfuzz=500pt double & \\hfuzz=500pt constant of MSLM mapping function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mapAlpha & \\hfuzz=500pt double & \\hfuzz=500pt constant of MSLM mapping function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gradient & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt parametrization of north and east gradients\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{IonosphereMap}\\label{gnssParametrizationType:ionosphereMap}\nApriori VTEC maps can be removed from the observations with\n\\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\n(e.g. from \\program{GnssIonex2GriddedDataTimeSeries}).\n\nThe ionosphere is parametrized in terms of $[TECU]$ in a single layer sphere with\n\\config{radiusIonosphericLayer} as a \\configClass{temporal}{parametrizationTemporalType}ly\nchanging (e.g. hourly linear splines) spherical harmonics expansion\n\\begin{equation}\n  VTEC(\\lambda,\\theta,t) = \\sum_{n=0}^{n_{max}} \\sum_{m=0}^n c_{nm}(t)C_{nm}(\\lambda,\\theta)+s_{nm}(t)S_{nm}(\\lambda,\\theta)\n\\end{equation}\nup to \\config{maxDegree}=\\verb|15| in a solar-geomagentic frame defined\nby \\configClass{magnetosphere}{magnetosphereType}. The VTEC values are mapped to STEC values\nin the observation equations via eq.~\\eqref{gnssParametrizationType:IonosphereVTEC:STEC}.\n\nThe estimated VTEC inclusive the apriori \\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\ncan be written to \\configFile{outputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nevaluated at \\configClass{outputGrid}{gridType} and \\configClass{outputTimeSeries}{timeSeriesType}.\n\nLocal and short-term scintillations should be considered by adding constrained\n\\configClass{parametrization:ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}.\nTo account for signal biases add\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|VTEC:sphericalHarmonics.c_<degree>_<order>:<temporal>:<interval>|,\n\\item \\verb|VTEC:sphericalHarmonics.s_<degree>_<order>:<temporal>:<interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt single layer VTEC [TECU]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outputGrid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outputTimeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt single layer VTEC [TECU]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt spherical harmonics parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt temporal evolution of VTEC values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radiusIonosphericLayer & \\hfuzz=500pt double & \\hfuzz=500pt [m] radius of ionospheric single layer\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mapR & \\hfuzz=500pt double & \\hfuzz=500pt [m] constant of MSLM mapping function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mapH & \\hfuzz=500pt double & \\hfuzz=500pt [m] constant of MSLM mapping function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mapAlpha & \\hfuzz=500pt double & \\hfuzz=500pt constant of MSLM mapping function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~magnetosphere & \\hfuzz=500pt \\hyperref[magnetosphereType]{magnetosphere} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Clocks}\\label{gnssParametrizationType:clocks}\nClock errors are estimated epoch-wise for each \\configClass{selectTransmitters/Receivers}{platformSelectorType}.\nNo clock errors are estimated if no valid observations are available (e.g. data gaps in the observations).\n\nIf all transmitters and receivers are selected by \\config{selectTransmitters} and \\config{selectReceivers} respectively,\nthese parameters will be lineary dependent which would lead to a rank deficiency in the normal equation\nmatrix. To circumvent this issue, the estimation requires an additional zero-mean constraint added in each epoch.\nThis is realized with an additional observation equation\n\\begin{equation}\n  0 = \\frac{1}{n_i + n_k} (\\sum_i \\Delta t^{s_i} + \\sum_k \\Delta t_{r_k})\n\\end{equation}\nsummed over all \\configClass{selectTransmitters/ReceiversZeroMean}{platformSelectorType}\nwith a standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:clock::<time>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClockTransmitter & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClockReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmittersZeroMean & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceiversZeroMean & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaZeroMeanConstraint & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ClocksModel}\\label{gnssParametrizationType:clocksModel}\nThis parametrization is an alternative to \\configClass{parametrization:clocks}{gnssParametrizationType:clocks}.\nClock errors are estimated epoch-wise for each \\configClass{selectTransmitters/Receivers}{platformSelectorType}\nand, opposed to \\configClass{parametrization:clocks}{gnssParametrizationType:clocks}, are also estimated for epochs\nthat have no valid observations available (e.g. data gaps).\n\nThe clock error of an epoch can be predicted by the clock error\nof the preceding epoch and an unknown clock drift\n\\begin{equation}\n  \\Delta t_{i+1} = \\Delta t_{i} + t_{drift} dt + \\epsilon_i.\n\\end{equation}\nThis equation is applied as an additional constraint equation in each epoch\n\\begin{equation}\n  0 = \\Delta t_{i+1} - \\Delta t_{i} - t_{drift} dt + \\epsilon_i.\n\\end{equation}\nThe variance $\\sigma^2(\\epsilon)$ is estimated iteratively by variance component estimation (VCE).\nClock jumps are treated as outliers and are automatically downweighted as described in\n\\configClass{GnssProcessing:processingStep:estimate}{gnssProcessingStepType:estimate}.\n\nThe absolute initial clock error and clock drift cannot be determined if all receiver\nand transmitter clocks are estimated together due to their linear dependency.\nThis linear dependency would lead to a rank deficiency in the normal equation matrix in the same\nmanner as described in \\configClass{parametrization:clocks}{gnssParametrizationType:clocks}.\nTo circumvent this issue, an additional zero-mean constraint is added in each epoch\nas observation equation\n\\begin{equation}\n  0 = \\frac{1}{n_i + n_k} (\\sum_i \\Delta t^{s_i} + \\sum_k \\Delta t_{r_k})\n\\end{equation}\nsummed over all \\configClass{selectTransmitters/ReceiversZeroMean}{platformSelectorType}.\nThis should be a loose constraint with a relatively large standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:clock::<time>|\nand \\verb|<station or prn>:clockDrift::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClockTransmitter & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClockReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt clock jumps \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt clock jumps \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmittersZeroMean & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt use these transmitters for zero-mean constraint\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceiversZeroMean & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt use these receivers for zero-mean constraint\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaZeroMeanConstraint & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SignalBiases}\\label{gnssParametrizationType:signalBiases}\nEach code and phase observation (e.g \\verb|C1C| or \\verb|L2W|) contains a bias at transmitter/receiver level\n\\begin{equation}\n  [\\tau\\nu a]_r^s(t) = \\dots + \\text{bias}[\\tau\\nu a]^s + \\text{bias}[\\tau\\nu a]_r + \\dots\n\\end{equation}\nThis class provides the apriori model $\\M f(\\M x_0)$ of eq. \\eqref{gnssParametrizationType:model} only.\n\nThe \\configFile{inputfileSignalBiasTransmitter/Receiver}{gnssSignalBias} are read\nfor each transmitter and receiver. Those file names are interpreted as a template with\nthe variable \\verb|{prn}| or \\verb|{station}| being replaced by transmitter PRNs or receiver station names, respectively.\n(Infos regarding the variables \\verb|{prn}| and \\verb|{station}| can be found in\n\\configClass{gnssTransmitterGeneratorType}{gnssTransmitterGeneratorType} and\n\\configClass{gnssReceiverGeneratorType}{gnssReceiverGeneratorType} respectively). Those files can\nbe converted with \\program{GnssSinexBias2SignalBias}.\n\nThe estimation of the biases is complex due to different linear dependencies, which\nresult in rank deficiencies in the system of normal equations.\nFor simplification the parametrization for $\\Delta\\M x$ has been split into:\n\\configClass{parametrization:codeBiases}{gnssParametrizationType:codeBiases},\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases}, and\n\\configClass{parametrization:ambiguities}{gnssParametrizationType:ambiguities} (including phase biases).\nThe file handling on the other hand still remains within this class. Any prior\nvalues for the transmitter/receiver biases are read with the respective \\config{inputfileSignalBiasTransmitter/Receiver}.\nAll biases for a transmitter/receiver are accumulated and written to the respective \\config{outputfileSignalBiasTransmitter/Receiver}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSignalBiasTransmitter & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSignalBiasReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSignalBiasTransmitter & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSignalBiasReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Ambiguities}\\label{gnssParametrizationType:ambiguities}\nSets up an ambiguity parameter for each track and phase observation type.\n\\begin{equation}\n  [L\\nu a]_r^s(t) = \\dots + \\text{bias}[L\\nu a]^s + \\text{bias}[L\\nu a]_r + \\lambda[L\\nu] N[L\\nu a]_r^s\n\\end{equation}\nAs the phase observations contain a float bias at transmitter/receiver level, not all ambiguities\nare resolvable to integer values. The number of resolvable ambiguities can be increased with\nknown phase biases read from file via \\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\nIn this case, \\configClass{estimateTransmitter/ReceiverPhaseBias}{platformSelectorType} should\nnot be used for the corresponding transmitters and receivers.\n\nIn case of GLONASS, the phase biases at receiver level differ between different frequency channels\n(frequency division multiple access, FDMA) and for each channel an extra float phase bias is estimated.\nWith \\config{linearGlonassBias} a linear relationship between bias and frequency channel is assumed,\nwhich reduces the number of float bias parameters and increases the number of resolvable integer ambiguities.\n\nThe integer ambiguities can be resolved and fixed in\n\\configClass{GnssProcessing:processingStep:resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}.\nResolved integer ambiguities are not estimated as unknown parameters in\n\\configClass{gnssProcessingStepType:estimate}{gnssProcessingStepType} anymore\nand are removed from the system of normal equations.\n\nThe estimated phase biases can be written to files in\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:phaseBias(<gnssType>)::|,\n\\item \\verb|<prn>:phaseBias(<gnssType>)::|,\n\\item \\verb|<station>.<prn>:ambiguity<index>of<count>(<GnssTypes>)::<track interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimateTransmitterPhaseBias & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimateReceiverPhaseBias & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~linearGlonassBias & \\hfuzz=500pt boolean & \\hfuzz=500pt bias depends linear on frequency channel number\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{CodeBiases}\\label{gnssParametrizationType:codeBiases}\nEach code observation (e.g \\verb|C1C| or \\verb|C2W|) contains a bias at transmitter/receiver level\n\\begin{equation}\n  [C\\nu a]_r^s(t) = \\dots + \\text{bias}[C\\nu a]^s + \\text{bias}[C\\nu a]_r + \\dots\n\\end{equation}\nThe code biases cannot be estimated together with clock errors and ionospheric delays in an absolute sense\nas rank deficiencies will occur in the system of normal equations. Therefore, the biases are not initialized and set up\nas parameters directly but only estimable linear combinations are parametrized.\n\nThe basic idea is to set up simplified normal equations with the biases,\nclock and STEC parameters of one single receiver or transmitter,\neliminate clock and STEC parameters and perform an eigen value decomposition\nof the normal equation matrix\n\\begin{equation}\n  \\M N = \\M Q \\M\\Lambda \\M Q^T.\n\\end{equation}\nInstead of estimating the original bias parameter $\\M x$ a transformed set $\\bar{\\M x}$\nis introduced:\n\\begin{equation}\n  \\bar{\\M x} = \\M Q^T \\M x.\n\\end{equation}\nThe new parameters corresponding to eigen values $\\lambda>0$ are estimable,\nthe others are left out (set to zero). The behavior can be controlled by explicitly setting up to two bias types\nwith \\configClass{typesClockDatum}{gnssType} for each transmitter to zero. These then define the ionosphere-free clock datum\nof the transmitter. The missing linear combinations,\nwhich depend on the STEC parameters, can be added with\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases}.\n\nAdditional rank deficiencies may also occur when biases of transmitters and receivers are estimated together.\nThe minimum norm nullspace (also via eigen value decomposition)\nis formulated as zero constraint equations and added with a standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nIn case of GLONASS the code biases at receiver level can differ between different frequency channels\n(frequency division multiple access, FDMA) and for each channel an extra code bias is estimated.\nWith \\config{linearGlonassBias} a linear relationship between bias and frequency channel is assumed,\nwhich reduces the number of bias parameters.\n\nThe estimated biases can be written to files in\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:codeBias0<index><combi of gnssTypes>::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~linearGlonassBias & \\hfuzz=500pt boolean & \\hfuzz=500pt bias depends linear on frequency channel number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~typesClockDatum & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt first two matching types define the ionosphere free transmitter clock (e.g. C1WG, C2WG)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaZeroMeanConstraint & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for null space constraint\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TecBiases}\\label{gnssParametrizationType:tecBiases}\nEach code observation (e.g \\verb|C1C| or \\verb|C2W|) contains a bias at transmitter/receiver level\n\\begin{equation}\n  [C\\nu a]_r^s(t) = \\dots + \\text{bias}[C\\nu a]^s + \\text{bias}[C\\nu a]_r + \\ldots\n\\end{equation}\nThis parametrization represents the linear combination of signal biases\nwhich completely depend on the STEC parameters. Ignoring these bias combinations would result\nin a biased STEC estimation (all other parameters are nearly unaffected).\nTo determine this part of the signal biases\nthe \\configClass{parametrization:ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC} should be constrained.\nFurthermore, additional information about the ionosphere is required from\n\\configClass{parametrization:ionosphereVTEC}{gnssParametrizationType:ionosphereVTEC} or\n\\configClass{parametrization:ionosphereMap}{gnssParametrizationType:ionosphereMap}.\n\nRank deficiencies due to the signal bias parameters may occur if biases of\ntransmitters and receivers are estimated together.\nThe minimum norm nullspace is formulated as zero constraint equations and added with\na standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe accumulated estimated result can be written to files in\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:tecBias0<index><combi of gnssTypes>::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~linearGlonassBias & \\hfuzz=500pt boolean & \\hfuzz=500pt phase or code biases depend linear on frequency channel number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaZeroMeanConstraint & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for null space constraint\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TemporalBias}\\label{gnssParametrizationType:temporalBias}\nThis parametrization resolves the issue of some phase observations suffering from time-variable biases.\nSuch a phenomenon has been found to affect GPS block IIF satellites on the L5 phase measurements\n(see Montenbruck et al. 2011, DOI: \\href{https://doi.org/10.1007/s10291-011-0232-x}{10.1007/s10291-011-0232-x}).\n\nFor these time-variable biases an appropriate temporal representation has to be defined in\n\\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nFor example, time-variable biases for GPS block IIF L5 phase observations (\\configClass{type}{gnssType}=\\verb|L5*G|)\ncan be represented by a cubic spline with a nodal distance of one hour.\n\nThe result is written as a \\file{times series file}{instrument} at the processing sampling\nor the sampling set by \\configClass{GnssProcessing:processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}).\n\nThis parametrization should be set up in addition to the constant\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\nDepending on the temporal representation a temporal zero-mean constraint is needed\nto separate this parametrization from the constant component. The constraint equations are added with\na standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe \\file{parameter names}{parameterName} are\n\\verb|<prn>:signalBias.<gnssType>:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileBiasTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileBiasTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaZeroMeanConstraint & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for temporal zero-mean constraint\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StaticPositions}\\label{gnssParametrizationType:staticPositions}\nEstimates a static position for all\n\\configClass{selectReceivers}{platformSelectorType} in the terrestrial frame.\n\nNo-net constraints can be applied for a subset of stations,\n\\configClass{selectNoNetReceivers}{platformSelectorType}, with a\nstandard deviation of \\config{noNetTranslationSigma} and \\config{noNetRotationSigma} and \\config{noNetScaleSigma}.\nIf the template \\configFile{inputfileNoNetPositions}{stringList} is provided\nthe constraints are applied relatively to these positions. Only stations with an existing position file\nare considered. Without \\configFile{inputfileNoNetPositions}{stringList}\nthe constraints are applied towards the apriori values from\n\\configClass{GnssProcessing:receiver}{gnssReceiverGeneratorType}.\nAs a single corrupted station position can disturb the no-net conditions,\nthe rotation/translation parameters are estimated in a\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}\nbeforehand. The computed weight matrix is used to downweight corrupted stations\nin the constraint equations.\n\nIn case you want to align to an ITRF/IGS reference frame, precise coordinates can be\ngenerated with \\program{Sinex2StationPositions}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:position.x::|,\n\\item \\verb|<station>:position.y::|,\n\\item \\verb|<station>:position.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGriddedPosition & \\hfuzz=500pt filename & \\hfuzz=500pt delta north east up for all stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePosition & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, full estimated coordinates (in TRF)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectNoNetReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileNoNetPositions & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, precise coordinates used for no-net constraints (in TRF)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~noNetTranslationSigma & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~noNetRotationSigma & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] at Earth's surface for no-net rotation constraint on station coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~noNetScaleSigma & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt stations \\$>\\$ huber*sigma0 are downweighted in no-net constraint\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt stations \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{KinematicPositions}\\label{gnssParametrizationType:kinematicPositions}\nEstimates the epoch-wise \\configFile{outputfilePositions}{instrument}\nin an Earth-fixed frame (or in case of LEO satellites in an intertial frame).\n\nThe $3\\times3$ epoch wise \\configFile{outputfileCovarianceEpoch}{instrument}\nare computed within\n\\configClass{GnssProcessing:processingStep:computeCovarianceMatrix}{gnssProcessingStepType:computeCovarianceMatrix}\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:position.x::<time>|,\n\\item \\verb|<station>:position.y::<time>|,\n\\item \\verb|<station>:position.z::<time>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePositions & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, estimated kinematic positions/orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, 3x3 epoch covariances\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{LeoDynamicOrbits}\\label{gnssParametrizationType:leoDynamicOrbits}\nThe estimation of (reduced) dynamic orbits is formulated as variational equations.\nIt is based on \\configFile{inputfileVariational}{variationalEquation} calculated with \\program{PreprocessingVariationalEquation}.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree \\config{integrationDegree}.\nThe \\configClass{parametrizationAcceleration}{parametrizationAccelerationType} must include at least those\nparameters that were estimated in \\program{PreprocessingVariationalEquationOrbitFit}.\nAdditional \\configClass{stochasticPulse}{timeSeriesType} parameters can be set up to reduce orbit mismodeling.\nIf not enough epochs with observations are available (\\config{minEstimableEpochsRatio}) the LEO satellite is disabled.\n\nThe parameters and \\file{parameter names}{parameterName} are divided into global\n\\begin{itemize}\n\\item \\verb|<station>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<station>:stochasticPulse.x::<time>|,\n\\item \\verb|<station>:stochasticPulse.y::<time>|,\n\\item \\verb|<station>:stochasticPulse.z::<time>|,\n\\end{itemize}\nand arc related parameters\n\\begin{itemize}\n\\item \\verb|<station>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<station>:arc<no>.position0.x::|,\n\\item \\verb|<station>:arc<no>.position0.y::|,\n\\item \\verb|<station>:arc<no>.position0.z::|.\n\\item \\verb|<station>:arc<no>.velocity0.x::|,\n\\item \\verb|<station>:arc<no>.velocity0.y::|,\n\\item \\verb|<station>:arc<no>.velocity0.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameters & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stochasticPulse & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt [mu/s] parametrization of stochastic pulses\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minEstimableEpochsRatio & \\hfuzz=500pt double & \\hfuzz=500pt drop satellites with lower ratio of estimable epochs to total epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for orbit interpolation and velocity calculation\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TransmitterDynamicOrbits}\\label{gnssParametrizationType:transmitterDynamicOrbits}\nSame as \\configClass{leoDynamicOrbits}{gnssParametrizationType:leoDynamicOrbits} but\nfor transmitting GNSS satellites.\nFor more details see \\reference{orbit integration}{cookbook.gnssNetwork:orbitIntegration}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameters & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stochasticPulse & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt [mu/s] parametrization of stochastic pulses\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minEstimableEpochsRatio & \\hfuzz=500pt double & \\hfuzz=500pt drop satellites with lower ratio of estimable epochs to total epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for orbit interpolation and velocity calculation\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Troposphere}\\label{gnssParametrizationType:troposphere}\nA priori tropospheric correction is handled by a \\configClass{troposphere}{troposphereType} model (e.g. Vienna Mapping Functions 3).\nAdditional parameters in $[m]$ for zenith wet delay and gradients can be set up via\n\\configClass{troposphereWetEstimation}{parametrizationTemporalType} (usually 2-hourly linear splines)\nand \\configClass{troposphereGradientEstimation}{parametrizationTemporalType} (usually a daily trend).\nThese parameters can be soft-constrained using\n\\configClass{parametrization:constraints}{gnssParametrizationType:constraints}\nto avoid an unsolvable system of normal equations in case of data gaps.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:troposphereWet:<temporal>:<interval>|,\n\\item \\verb|<station>:troposphereGradient.x:<temporal>:<interval>|,\n\\item \\verb|<station>:troposphereGradient.y:<temporal>:<interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTroposphere & \\hfuzz=500pt filename & \\hfuzz=500pt columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~troposphere & \\hfuzz=500pt \\hyperref[troposphereType]{troposphere} & \\hfuzz=500pt a priori troposphere model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~troposphereWetEstimation & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt [m] parametrization of zenith wet delays\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~troposphereGradientEstimation & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt [degree] parametrization of north and east gradients\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EarthRotation}\\label{gnssParametrizationType:earthRotation}\nEarth rotation parameters (ERPs) can be estimated by defining\n\\config{estimatePole} ($x_p$, $y_p\\, [mas]$) and \\config{estimateUT1} ($dUT1\\, [ms], LOD$).\n\nEstimating length of day (LOD) with the sign according to IGS conventions requires a negative\nvalue in \\configClass{parametrizationTemporal:trend:timeStep}{parametrizationTemporalType:trend}.\n\nConstraints on the defined parameters can be added via\n\\configClass{parametrization:constraints}{gnssParametrizationType:constraints}.\nAn example would be to set up \\configClass{estimateUT1:constant}{parametrizationTemporalType:constant}\nso the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be\ndetermined by GNSS, a hard constraint to its a priori value can then be added.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|earth:polarMotion.xp:<temporal>:<interval>|,\n\\item \\verb|earth:polarMotion.yp:<temporal>:<interval>|,\n\\item \\verb|earth:UT1:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.X:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.Y:<temporal>:<interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimatePole & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt xp, yp [mas]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimateUT1 & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt rotation angle [ms]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimateNutation & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt dX, dY [mas]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ReceiverAntennas}\\label{gnssParametrizationType:receiverAntennas}\nThis class is for parametrization the antenna for their antenna center offsets (ACO) and\nantenna center variations (ACV) by \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}.\nThe receivers to be estimated can be selected by \\configClass{selectReceivers}{platformSelectorType}.\n\nThe amount of patterns to be estimated is configurable with a list of \\configClass{patternTypes}{gnssType}.\nFor each added \\configClass{patternTypes}{gnssType} a set of parameters will be evaluated. The observations\nwill be assigned to the first \\configClass{patternTypes}{gnssType} that matches their own.\nE.g. having the patterns: \\verb|***G| and \\verb|L1*| would lead to all GPS observations be assigned\nto the observation equations of the first pattern. The pattern type \\verb|L1*| would then consist\nof all other GNSS L1 phase observations. \\config{addNonMatchingTypes} will, if activated, create automatically patterns\nfor \\configClass{observations}{gnssType} that are not selected within the list \\configClass{patternTypes}{gnssType}.\nFurthermore, it is possible to group same antenna build types from different receivers by \\config{groupAntennas}.\nThe grouping by same antenna build ignores antenna serial numbers.\n\nTo estimate the antenna variation parameters, a longer period of observations might be necessary\nfor accurate estimations. Hence one should use this parametrization by\naccumulating normal equations from several epochs.\nThis can be accomplished as the last steps in the \\configClass{processing steps}{gnssProcessingStepType}\n by adding \\configClass{ReceiverAntennas}{gnssParametrizationType:receiverAntennas}\nto current selected parameters with \\configClass{GnssProcessing:processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations}\nand write the normal equation matrix with \\configClass{GnssProcessing:processingStep:writeNormalEquations}{gnssProcessingStepType:writeNormalEquations}.\nThe written normal equations can then be accumulated with \\program{NormalsAccumulate} and solved by \\program{NormalsSolverVCE}.\nFurther, one should apply constraints to the normal equations by \\program{GnssAntennaNormalsConstraint} since the estimation\n of ACO and ACV can lead to rank deficiencies in the normal equation matrix.\nLast the solved normal equation can be parsed to a \\file{antenna definition file}{gnssAntennaDefinition}\n with the program \\program{ParameterVector2GnssAntennaDefinition}.\n\nAs example referring to the cookbook \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork},\none could add additionally \\configClass{receiverAntennas}{gnssParametrizationType:receiverAntennas} as parametrization.\nSince the estimations are done on a daily basis for each receiver we add an additional\n\\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations} which\ndisables \\verb|parameter.receiverAntenna|. After all stations are processed together with all parameters, one\nadds \\verb|parameter.receiverAntenna| with \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}\n to the current selected parametrizations.\nThe last \\configClass{processingStep}{gnssProcessingStepType} is \\configClass{GnssProcessing:processingStep:writeNormalEquations}{gnssProcessingStepType:writeNormalEquations}\nto write the daily normal equations including the parametrization \\configClass{receiverAntennas}{gnssParametrizationType:receiverAntennas} into files.\nThese normal equation files are then processed with the programs:\n\n\\begin{itemize}\n  \\item \\program{NormalsAccumulate}: accumulates normal equations.\n  \\item \\program{GnssAntennaNormalsConstraint}: apply constraint to the normal equations.\n  \\item \\program{NormalsSolverVCE}: solves the normal equations.\n  \\item \\program{ParameterVector2GnssAntennaDefinition}: writes the solution into a \\file{antenna definition file}{gnssAntennaDefinition}\n\\end{itemize}\n\nNote that the apriori value $\\M x_0$ for this parametrization is always zero and never updated\naccording to eq.~\\eqref{gnssParametrizationType:update}.\n\nThe \\file{parameter names}{parameterName} are\n\\verb|<antennaName>:<antennaCenterVariations>.<gnssType>::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antennaCenterVariations & \\hfuzz=500pt \\hyperref[parametrizationGnssAntennaType]{parametrizationGnssAntenna} & \\hfuzz=500pt estimate antenna center variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~patternTypes & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt gnssType for each pattern (first match is used)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~addNonMatchingTypes & \\hfuzz=500pt boolean & \\hfuzz=500pt add patterns for additional observed gnssTypes that don't match any of the above\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~groupAntennas & \\hfuzz=500pt boolean & \\hfuzz=500pt common ACVs for same antenna build types (ignores antenna serial number)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TransmitterAntennas}\\label{gnssParametrizationType:transmitterAntennas}\nSame as \\configClass{receiverAntennas}{gnssParametrizationType:receiverAntennas} but\nfor transmitting antennas (GNSS satellites).\n\nThe \\file{parameter names}{parameterName} are\n\\verb|<antennaName>:<antennaCenterVariations>.<gnssType>::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antennaCenterVariations & \\hfuzz=500pt \\hyperref[parametrizationGnssAntennaType]{parametrizationGnssAntenna} & \\hfuzz=500pt estimate antenna center variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~patternTypes & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt gnssType for each pattern (first match is used)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~addNonMatchingTypes & \\hfuzz=500pt boolean & \\hfuzz=500pt add patterns for additional observed gnssTypes that don't match any of the above\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~groupAntennas & \\hfuzz=500pt boolean & \\hfuzz=500pt common ACVs for same antenna build types (ignores antenna serial number)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Constraints}\\label{gnssParametrizationType:constraints}\nAdd a pseudo observation equation (constraint)\nfor each selected \\configClass{parameters}{parameterSelectorType}\n\\begin{equation}\n  b-x_0 = 1 \\cdot dx + \\epsilon,\n\\end{equation}\nwhere $b$ is the \\config{bias} and $x_0$ is the a priori value of the parameter\nif \\config{relativeToApriori} is not set.\nThe standard deviation \\config{sigma} is used to weight the observation equations.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter to constrain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt sigma of the constraint (same unit as parameter)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~bias & \\hfuzz=500pt double & \\hfuzz=500pt constrain all selected parameters towards this value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~relativeToApriori & \\hfuzz=500pt boolean & \\hfuzz=500pt constrain only dx and not full x=dx+x0\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{gnssParametrizationType:group}\nGroups a set of parameters. This class can be used to structure complex parametrizations\nand has no further effect itself.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[gnssParametrizationType]{gnssParametrization} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{GnssProcessingStep}\\label{gnssProcessingStepType}\nProcessing step in \\program{GnssProcessing}.\n\nProcessing steps enable a dynamic definition of the consecutive steps performed during any kind of GNSS processing.\nThe most common steps are \\configClass{estimate}{gnssProcessingStepType:estimate}, which performs an iterative least\nsquares adjustment, and \\configClass{writeResults}{gnssProcessingStepType:writeResults}, which writes all output files\ndefined in \\program{GnssProcessing} and is usually the last step.\nSome steps such as \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations},\n\\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs},\n\\configClass{selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure}, and\n\\configClass{selectReceivers}{gnssProcessingStepType:selectReceivers} affect all subsequent steps.\nIn case these steps are used within a \\configClass{group}{gnssProcessingStepType:group} or\n\\configClass{forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately} step,\nthey only affect the steps within this level.\n\nFor usage examples see cookbooks on \\reference{GNSS satellite orbit determination and network analysis}{cookbook.gnssNetwork:processing}\nor \\reference{Kinematic orbit determination of LEO satellites}{cookbook.kinematicOrbit}.\n\n\n\\subsection{Estimate}\\label{gnssProcessingStepType:estimate}\nIterative non-linear least squares adjustment.\nIn every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters.\nThe estimated parameters serve as a priori values in the next iteration and the following processing steps.\nIterates until either every single parameter update (converted to an influence in meters)\nis below a \\config{convergenceThreshold} or \\config{maxIterationCount} is reached.\n\nWith \\config{computeResiduals} the observation equations are computed\nagain after each update to compute the observation residuals.\n\nThe overall standard deviation of a single observation used for the weighting\nis composed of several factors\n\\begin{equation}\n  \\hat{\\sigma}_i = \\hat{\\sigma}_i^{huber} \\hat{\\sigma}_{[\\tau\\nu a]}^{recv} \\sigma_{[\\tau\\nu a]}^{recv}(E,A),\n\\end{equation}\nwhere $[\\tau\\nu a]$ is the signal type, the azimuth and elevation dependent $\\sigma_{[\\tau\\nu a]}^{recv}(E,A)$ is given by\n\\configFile{receiver:inputfileAccuracyDefinition}{gnssAntennaDefinition} and the other factors are\nestimated iteratively from the residuals.\n\nWith \\config{computeWeights} a standardized variance $\\hat{s}_i^2$\nfor each residual $\\hat{\\epsilon}_i$ is computed\n\\begin{equation}\n  \\hat{s}_i^2 = \\frac{1}{\\hat{\\sigma}_{[\\tau\\nu a]}^{recv} \\sigma_{[\\tau\\nu a]}^{recv}(E,A)}\\frac{\\hat{\\epsilon}_i^2}{r_i}\n  \\qquad\\text{with}\\qquad\n  r_i = \\left(\\M A\\left(\\M A^T\\M A\\right)^{-1}\\M A^T\\right)_{ii}\n\\end{equation}\ntaking the redundancy $r_i$ into account. If $\\hat{s}_i$ is above a threshold \\config{huber}\nthe observation gets a higher standard deviation used for weighting according to\n\\begin{equation}\n  \\hat{\\sigma}_i^{huber} =\n  \\left\\{ \\begin{array}{ll}\n    1                              & s < huber,\\\\\n    (\\hat{s}_i/huber)^{huberPower} & s \\ge huber\n  \\end{array} \\right.,\n\\end{equation}\nsimilar to \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\nWith \\config{adjustSigma0} individual variance factors can be computed\nfor each station and all phases of a system and each code observation \\reference{type}{gnssType}\n(e.g. for each \\verb|L**G|, \\verb|L**E|, \\verb|C1CG|, \\verb|C2WG|, \\verb|C1CE|, \\ldots)\nseparately\n\\begin{equation}\n  \\hat{\\sigma}_{[\\tau\\nu a]}^{recv} = \\sqrt{\\frac{\\hat{\\M\\epsilon}^T\\M P\\hat{\\M\\epsilon}}{r}}.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeResiduals & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~adjustSigma0 & \\hfuzz=500pt boolean & \\hfuzz=500pt adjust sigma0 by scale factor (per receiver and type)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeWeights & \\hfuzz=500pt boolean & \\hfuzz=500pt downweight outliers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~convergenceThreshold & \\hfuzz=500pt double & \\hfuzz=500pt [m] stop iteration once full convergence is reached\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxIterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt maximum number of iterations\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ResolveAmbiguities}\\label{gnssProcessingStepType:resolveAmbiguities}\nPerforms a least squares adjustment like \\configClass{processingStep:estimate}{gnssProcessingStepType:estimate}\nbut with additional integer phase ambiguity resolution.\nAfter this step all resolved ambiguities are removed from the normal equation system.\nOnly ambiguities involving \\configClass{selectTransmitters/Receivers}{platformSelectorType} are resolved.\nIf \\configClass{selectTransmitters/Receivers}{platformSelectorType} is not set, all usable transmitters and/or \nreceivers are selected for ambiguity resolution.\n\nInteger ambiguity resolution is performed based on the least squares ambiguity decorrelation adjustment\n(LAMBDA) method (Teunissen 1995, DOI \\href{https://doi.org/10.1007/BF00863419}{10.1007/BF00863419}), specifically\nthe modified algorithm (MLAMBDA) by Chang et al. (2005, DOI \\href{https://doi.org/10.1007/s00190-005-0004-x}{10.1007/s00190-005-0004-x}).\nFirst the covariance matrix of the integer ambiguity parameters is computed by eliminating all but those parameters\nfrom the full normal equation matrix and inverting it. Then, a Z-transformation is performed as described by\nChang et al. (2005) to decorrelate the ambiguity parameters without losing their integer nature.\n\nThe search process follows MLAMBDA and uses integer minimization of the weighted sum of squared residuals.\nIt is computationally infeasible to search a hyper-ellipsoid with a dimension of ten thousand or more.\nInstead, a blocked search algorithm is performed by moving a window with a length of, for example,\n\\config{searchBlockSize}=\\verb|200| parameters over the decorrelated ambiguities, starting from the most accurate.\nIn each step, the window is moved by half of its length and the overlapping parts are compared to each other.\nIf all fixed ambiguities in the overlap agree, the algorithm continues.\nOtherwise, both windows are combined and the search is repeated using the combined window, again comparing with the overlapping\npart of the preceding window. If not all solutions could be checked for a block after \\config{maxSearchSteps},\nthe selected \\config{incompleteAction} is performed.\nIf the algorithm reaches ambiguities with a standard deviation higher than \\config{sigmaMaxResolve},\nambiguity resolution stops and the remaining ambiguities are left as float values.\nOtherwise, all ambiguity parameters are fixed to integer values.\n\nIn contrast to an integer least squares solution over the full ambiguity vector, it is not guaranteed that the resulting solution\nis optimal in the sense of minimal variance with given covariance.\nThis trade-off is necessary to cope with large numbers of ambiguities.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAmbiguities & \\hfuzz=500pt filename & \\hfuzz=500pt resolved ambiguities\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt only resolve ambiguities with these participating transmitters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt only resolve ambiguities with these participating receivers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaMaxResolve & \\hfuzz=500pt double & \\hfuzz=500pt max. allowed std. dev. of ambiguity to resolve [cycles]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~searchBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for blocked integer search\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxSearchSteps & \\hfuzz=500pt uint & \\hfuzz=500pt max. steps of integer search for each block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~incompleteAction & \\hfuzz=500pt choice & \\hfuzz=500pt if not all solutions tested after maxSearchSteps\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~stop & \\hfuzz=500pt  & \\hfuzz=500pt stop searching, ambiguities remain float in this block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~resolve & \\hfuzz=500pt  & \\hfuzz=500pt use best integer solution found so far\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~shrinkBlockSize & \\hfuzz=500pt  & \\hfuzz=500pt try again with half block size\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~throwException & \\hfuzz=500pt  & \\hfuzz=500pt stop and throw an exception\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeResiduals & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~adjustSigma0 & \\hfuzz=500pt boolean & \\hfuzz=500pt adjust sigma0 by scale factor (per receiver and type)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeWeights & \\hfuzz=500pt boolean & \\hfuzz=500pt downweight outliers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ComputeCovarianceMatrix}\\label{gnssProcessingStepType:computeCovarianceMatrix}\nAccumulates the normal equations and computes the covariance matrix as inverse of the normal matrix.\nIt is not the full inverse but only the elements which are set in the normal matrix\n(see  \\configClass{gnssProcessingStep:selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure})\nare computed. The matrix is passed to the \\configClass{parametrizations}{gnssParametrizationType}.\nOnly used in \\configClass{parametrizations:kinematicPositions}{gnssParametrizationType:kinematicPositions}\nto get the epoch-wise covariance information at the moment.\n\n\n\\subsection{WriteResults}\\label{gnssProcessingStepType:writeResults}\nIn this step all \\config{outputfiles} defined in \\configClass{parametrizations}{gnssParametrizationType}\nare written. It considers the settings of\n\\configClass{processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations},\n\\configClass{processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}, and\n\\configClass{processingStep:selectReceivers}{gnssProcessingStepType:selectReceivers}.\n\nIt is usually the last processing step, but can also be used at other points in the\nprocessing in combination with \\config{suffix} to write intermediate results, for example\nbefore \\configClass{gnssProcessingStep:resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities} to\noutput the float solution.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~suffix & \\hfuzz=500pt string & \\hfuzz=500pt appended to every output file name (e.g. orbit.G01.suffix.dat)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteNormalEquations}\\label{gnssProcessingStepType:writeNormalEquations}\nAccumulates the normal equations matrix and writes it.\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written to the normal equations\nand all other parameters are eliminated beforehand (implicitly solved).\n\nThe solution of the normals would result in $\\Delta\\M x$\n(see \\configClass{parametrizations}{gnssParametrizationType}). To write the\nappropriate apriori vector $\\M x_0$ use\n\\configClass{processingStep:writeAprioriSolution}{gnssProcessingStepType:writeAprioriSolution}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquations & \\hfuzz=500pt filename & \\hfuzz=500pt normals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~remainingParameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of output normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~constraintsOnly & \\hfuzz=500pt boolean & \\hfuzz=500pt write only normals of constraints without observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultNormalsBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block, empty: original block size\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteAprioriSolution}\\label{gnssProcessingStepType:writeAprioriSolution}\nWrites the current apriori vector $\\M x_0$\n(see \\configClass{parametrizations}{gnssParametrizationType}).\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAprioriSolution & \\hfuzz=500pt filename & \\hfuzz=500pt a priori parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt parameter names\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~remainingParameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of output normal equations\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteResiduals}\\label{gnssProcessingStepType:writeResiduals}\nWrites the \\file{observation residuals}{instrument} for all\n\\configClass{selectReceivers}{platformSelectorType}.\nFor each station a file is written. The file name is interpreted as\na template with the variable \\verb|{station}| being replaced by the station name.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteUsedStationList}\\label{gnssProcessingStepType:writeUsedStationList}\nWrites a \\file{list}{stringList} of receivers (stations) which are used in the last step and\nselected by \\configClass{selectReceivers}{platformSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileUsedStationList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with names of used stations\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteUsedTransmitterList}\\label{gnssProcessingStepType:writeUsedTransmitterList}\nWrites a \\file{list}{stringList} of transmitters which are used in the last step and\nselected by \\configClass{selectTransmitters}{platformSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used transmitters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileUsedTransmitterList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with PRNs\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PrintResidualStatistics}\\label{gnssProcessingStepType:printResidualStatistics}\nPrint residual statistics.\n\\begin{verbatim}\n  areq: C1CG**: factor =  0.64, sigma0 = 1.00, count =  2748, outliers =    48 (1.75 \\%)\n  areq: C1WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    43 (1.56 \\%)\n  areq: C2WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    59 (2.15 \\%)\n  areq: C5XG**: factor =  0.46, sigma0 = 1.00, count =  1279, outliers =    23 (1.80 \\%)\n  areq: L1CG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 \\%)\n  areq: L1WG**: factor =  0.86, sigma0 = 1.02, count =  2748, outliers =    40 (1.46 \\%)\n  areq: L2WG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 \\%)\n  areq: L5XG**: factor =  0.86, sigma0 = 1.30, count =  1279, outliers =    14 (1.09 \\%)\n  areq: C1PR**: factor =  0.48, sigma0 = 1.00, count =  1713, outliers =    53 (3.09 \\%)\n  areq: C2PR**: factor =  0.55, sigma0 = 1.00, count =  1713, outliers =    51 (2.98 \\%)\n  areq: L1PR**: factor =  0.85, sigma0 = 1.09, count =  1713, outliers =    29 (1.69 \\%)\n  areq: L2PR**: factor =  0.85, sigma0 = 0.88, count =  1713, outliers =    29 (1.69 \\%)\n  areq: C1XE**: factor =  0.44, sigma0 = 1.00, count =  1264, outliers =    21 (1.66 \\%)\n  areq: C5XE**: factor =  0.33, sigma0 = 1.00, count =  1264, outliers =    27 (2.14 \\%)\n  areq: C7XE**: factor =  0.28, sigma0 = 1.00, count =  1264, outliers =    41 (3.24 \\%)\n  areq: L1XE**: factor =  0.82, sigma0 = 1.14, count =  1264, outliers =    15 (1.19 \\%)\n  areq: L5XE**: factor =  0.82, sigma0 = 0.84, count =  1264, outliers =    15 (1.19 \\%)\n  areq: L7XE**: factor =  0.82, sigma0 = 0.94, count =  1264, outliers =    15 (1.19 \\%)\n  badg: C1CG**: factor =  1.25, sigma0 = 1.00, count =  2564, outliers =    47 (1.83 \\%)\n  ...\n\\end{verbatim}\n\n\n\\subsection{SelectParametrizations}\\label{gnssProcessingStepType:selectParametrizations}\nEnable/disable parameter groups and constraint groups for subsequent steps,\ne.g. \\configClass{processingStep:estimate}{gnssProcessingStepType:estimate} or\n\\configClass{processingStep:writeResults}{gnssProcessingStepType:writeResults}.\nThe \\config{name} and \\config{nameConstraint} of these groups\nare defined in \\configClass{parametrizations}{gnssParametrizationType}.\nPrior models or previously estimated parameters used as new apriori $\\M x_0$ values are unaffected\nand they are always reduced from the observations. This means all unselected parameters are kept fixed\nto their last result.\n\nAn example would be to process at a 5-minute sampling using\n\\configClass{processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}\nand then at the end to densify the clock parameters to the full 30-second observation sampling\nwhile keeping all other parameters fixed\n(\\config{disable}=\\verb|*|, \\config{enable}=\\verb|*.clock*|, \\config{enable}=\\verb|parameter.STEC|).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~enable & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~disable & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SelectEpochs}\\label{gnssProcessingStepType:selectEpochs}\nSelect epochs for subsequent steps. This step can be used to reduce the processing sampling\nwhile keeping the original observation sampling for all preprocessing steps (e.g. outlier and cycle slip detection).\nAnother example is to process at a 5-minute sampling by setting \\config{nthEpoch}=\\verb|10| and then\nat the end to densify only the clock parameters to the full 30-second observation sampling by\nsetting \\config{nthEpoch}=\\verb|1| while keeping all other parameters fixed\nwith \\configClass{processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~nthEpoch & \\hfuzz=500pt uint & \\hfuzz=500pt use only every nth epoch in all subsequent processing steps\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SelectNormalsBlockStructure}\\label{gnssProcessingStepType:selectNormalsBlockStructure}\nSelect block structure of sparse normal equations for subsequent steps.\n\nThis step can be used to define the structure of the different parts of the normal equation system,\nwhich can have a major impact on computing performance and memory consumption depending on the processing setup.\n\n\\fig{!hb}{0.4}{gnss_normals_structure}{fig:gnss_normals_structure}{Structure of normal equations in GNSS processing}\n\nThe normal equation system is divided into three parts for epoch, interval, and ambiguity parameters.\nThe epoch part is subdivided further into one subpart per epoch. Each part is divided into blocks and only non-zero\nblocks are stored in memory to reduce memory consumption and to prevent unnecessary matrix computations.\n\\config{defaultBlockSizeEpoch}, \\config{defaultBlockSizeInterval}, and \\config{defaultBlockSizeAmbiguity} control\nthe size of the blocks within each part of the normal equations. \\config{defaultBlockReceiverCount} can be set to group\na number of receivers into one block within the epoch and interval parts.\n\nIf \\config{keepEpochNormalsInMemory}=\\verb|no| epoch blocks are eliminated after they are set up to reduce the number\nof parameters in the normal equation system. \\config{defaultBlockCountReduction} controls after how many epoch blocks\nan elimination step is performed. For larger processing setups or high sampling rates epoch block elimination is recommended\nas the large number of clock parameters require a lot of memory.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockSizeEpoch & \\hfuzz=500pt uint & \\hfuzz=500pt block size of epoch parameters, 0: one block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockSizeInterval & \\hfuzz=500pt uint & \\hfuzz=500pt block size of interval parameters, 0: one block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockSizeAmbiguity & \\hfuzz=500pt uint & \\hfuzz=500pt block size of ambiguity parameters, 0: one block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockReceiverCount & \\hfuzz=500pt uint & \\hfuzz=500pt number of receivers to group into one block for epoch and interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockCountReduction & \\hfuzz=500pt uint & \\hfuzz=500pt minimum number of blocks for epoch reduction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~keepEpochNormalsInMemory & \\hfuzz=500pt boolean & \\hfuzz=500pt speeds up processing but uses much more memory\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~accumulateEpochObservations & \\hfuzz=500pt boolean & \\hfuzz=500pt set up all observations per epoch and receiver at once\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SelectReceivers}\\label{gnssProcessingStepType:selectReceivers}\nThis step can be used to process only a subset of stations in subsequent processing steps.\nThe most common use is to start the processing with a well-distributed network of core stations as seen in\n\\reference{GNSS satellite orbit determination and network analysis}{cookbook.gnssNetwork:processing}.\nTo later process all other stations individually, use the processing step\n\\configClass{processingStep:forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately}\nand select all stations excluding the core stations in that step.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ForEachReceiverSeparately}\\label{gnssProcessingStepType:forEachReceiverSeparately}\nPerform these processing steps for each \\configClass{selectReceivers}{platformSelectorType} separately.\nAll non-receiver-related parameters parameters are disabled in these processing steps.\n\nThis step can be used for individual precise point positioning (PPP) of all stations.\nDuring \\reference{GNSS satellite orbit determination and network analysis}{cookbook.gnssNetwork:processing} this step is used after the\ninitial processing of the core network to process all other stations individually. In that case provide the same station list as\n\\configFile{inputfileExcludeStationList}{stringList} in this step that was used as \\configFile{inputfileStationList}{stringList} in the\n\\configClass{selectReceivers}{gnssProcessingStepType:selectReceivers} step where the core network was selected.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectReceivers & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableReceiver & \\hfuzz=500pt string & \\hfuzz=500pt variable is set for each receiver\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~processingStep & \\hfuzz=500pt \\hyperref[gnssProcessingStepType]{gnssProcessingStep} & \\hfuzz=500pt steps are processed consecutively\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{gnssProcessingStepType:group}\nPerform these processing steps. This step can be used to structure complex processing flows.\nThe \\configClass{processingStep}{gnssProcessingStepType}s that affect the following steps\n(those beginning with Select) only have an effect until the end of the group.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~processingStep & \\hfuzz=500pt \\hyperref[gnssProcessingStepType]{gnssProcessingStep} & \\hfuzz=500pt steps are processed consecutively\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DisableTransmitterShadowEpochs}\\label{gnssProcessingStepType:disableTransmitterShadowEpochs}\nDisable transmitter epochs during eclipse.\nWith proper attitude modeling (see \\program{SimulateStarCameraGnss}) this is usually not necessary.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectTransmitters & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~disableShadowEpochs & \\hfuzz=500pt boolean & \\hfuzz=500pt disable epochs if satellite is in Earth's/Moon's shadow\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~disablePostShadowRecoveryEpochs & \\hfuzz=500pt boolean & \\hfuzz=500pt disable epochs if satellite is in post-shadow recovery maneuver for GPS block IIA\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt eclipse model used to determine if a satellite is in Earth's shadow\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{GnssReceiverGenerator}\\label{gnssReceiverGeneratorType}\nDefinition and basic information of GNSS receivers.\n\nMost of the input files are provided in GROOPS file formats at\n\\url{https://ftp.tugraz.at/pub/ITSG/groops} (marked with \\textbf{*} below).\nThese files are regularly updated.\n\\begin{itemize}\n  \\item \\configFile{inputfileStationInfo}{platform}\\textbf{*}:\n        Antenna and receiver information, antenna reference point offsets, antenna orientations.\n        Created via \\program{GnssStationLog2Platform} or \\program{PlatformCreate}.\n  \\item \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\\textbf{*}:\n        Antenna center offsets and variations.\n        Created via \\program{GnssAntex2AntennaDefinition} or \\program{GnssAntennaDefinitionCreate}.\n  \\item \\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition}:\n        Observed signal types (optional).\n        Created via \\program{GnssReceiverDefinitionCreate} in case you want to define which signal\n        types a receiver model can observe.\n  \\item \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition}\\textbf{*}:\n        Elevation and azimuth dependent accuracy.\n        Created via \\program{GnssAntennaDefinitionCreate}.\n  \\item \\configFile{inputfileObservation}{instrument}:\n        Converted from RINEX observation files via \\program{RinexObservation2GnssReceiver}.\n\\end{itemize}\n\nIt is possible to limit the observation types to be used in the processing by a list of \\configClass{useType}{gnssType}\nand any observation types not defined within the list are ignored and discarded.\nSimilarly observations defined in the list of \\configClass{ignoreType}{gnssType} are ignored and discarded.\nThe codes used follow the \\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition}.\n\nEach receiver goes through a \\config{preprocessing} step individually, where observation outliers are removed or downweighted,\ncontinuous tracks of phase observations are defined for ambiguity parametrization, cycle slips are detected, and receivers are\ndisabled if they do not fulfill certain requirements. The preprocessing step consists of an initial PPP estimation done by\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares} and checks whether the position error\nof the solutions exceeds \\config{codeMaxPositionDiff}. If the error exceeds the threshold the receiver will be discarded.\nThe preprocessing also sets initial clock error values and removes tracks that stay below a certain elevation mask (\\config{elevationTrackMinimum}).\n\nSee also \\program{GnssProcessing} and \\program{GnssSimulateReceiver}.\n\n\n\\subsection{StationNetwork}\\label{gnssReceiverGeneratorType:stationNetwork}\nA network of GNSS ground stations is defined via \\configFile{inputfileStationList}{stringTable}.\nEach line can contain more than one station. The first station in each line for which \\configFile{inputfileObservations}{instrument}\nexists and contains enough observations is used for the processing.\nAll input files except \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition},\n\\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition}, and\n\\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} are read for each station.\nThe file name is interpreted as a template with the variable \\verb|{station}| being replaced by the station name.\n\nThe effects of loading and tidal deformation on station positions can be corrected for\nvia \\configClass{loadingDisplacement}{gravityfieldType} and\n\\configClass{tidalDisplacement}{tidesType}, respectively.\nTidal deformations typically include:\n\\begin{itemize}\n  \\item \\configClass{earthTide}{tidesType:earthTide}: Earth tidal deformations (IERS conventions)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tidal deformations\n        (e.g. fes2014b\\_n720, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: atmospheric tidal deformation\n        (e.g. AOD1B RL06, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{poleTide}{tidesType:poleTide}: pole tidal deformations (IERS conventions)\n  \\item \\configClass{poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tidal deformations (IERS conventions)\n\\end{itemize}\n\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with station names\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxStationCount & \\hfuzz=500pt uint & \\hfuzz=500pt maximum number of stations to be used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available. station metadata (antennas, receivers, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt antenna center offsets and variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~noAntennaPatternFound & \\hfuzz=500pt choice & \\hfuzz=500pt what should happen if no antenna pattern is found for an observation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ignoreObservation & \\hfuzz=500pt  & \\hfuzz=500pt ignore observation if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~useNearestFrequency & \\hfuzz=500pt  & \\hfuzz=500pt use pattern of nearest frequency if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~throwException & \\hfuzz=500pt  & \\hfuzz=500pt throw exception if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileReceiverDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt observed signal types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccuracyDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt elevation and azimuth dependent accuracy\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStationPosition & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~disableStationWithoutPosition & \\hfuzz=500pt boolean & \\hfuzz=500pt drop stations without apriori position\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileObservations & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~loadingDisplacement & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt loading deformation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~tidalDisplacement & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt tidal deformation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt for tidal deformation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDeformationLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfilePotentialLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt if full potential is given and not only loading potential\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~useType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt only use observations that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~ignoreType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt ignore observations that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~elevationCutOff & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] ignore observations below cutoff\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~elevationTrackMinimum & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] ignore tracks that never exceed minimum elevation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minObsCountPerTrack & \\hfuzz=500pt uint & \\hfuzz=500pt tracks with less number of epochs with observations are dropped\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minEstimableEpochsRatio & \\hfuzz=500pt double & \\hfuzz=500pt [0,1] drop stations with lower ratio of estimable epochs to total epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~preprocessing & \\hfuzz=500pt sequence & \\hfuzz=500pt settings for preprocessing of observations/stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~printStatistics & \\hfuzz=500pt boolean & \\hfuzz=500pt print preprocesssing statistics for all receivers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~codeMaxPositionDiff & \\hfuzz=500pt double & \\hfuzz=500pt [m] max. allowed position error by PPP code only clock error estimation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~denoisingLambda & \\hfuzz=500pt double & \\hfuzz=500pt regularization parameter for total variation denoising used in cylce slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~tecWindowSize & \\hfuzz=500pt uint & \\hfuzz=500pt (0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~tecSigmaFactor & \\hfuzz=500pt double & \\hfuzz=500pt factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileTrackBefore & \\hfuzz=500pt filename & \\hfuzz=500pt variables \\{station\\}, \\{prn\\}, \\{trackTimeStart\\}, \\{trackTimeEnd\\}, \\{types\\}, TEC and MW-like combinations in cycles for each track before cycle slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileTrackAfter & \\hfuzz=500pt filename & \\hfuzz=500pt variables \\{station\\}, \\{prn\\}, \\{trackTimeStart\\}, \\{trackTimeEnd\\}, \\{types\\}, TEC and MW-like combinations in cycles for each track after cycle slip detection\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{LowEarthOrbiter}\\label{gnssReceiverGeneratorType:lowEarthOrbiter}\nA single low-Earth orbiting (LEO) satellite with an onboard GNSS receiver.\nAn apriori orbit is needed as \\configFile{inputfileOrbit}{instrument}.\nAttitude data must be provided via \\configFile{inputfileStarCamera}{instrument}.\nIf no attitude data is available from the satellite operator,\nthe star camera data can be simulated by using \\program{SimulateStarCamera}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt satellite metadata (antenna, receiver, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt antenna center offsets and variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~noAntennaPatternFound & \\hfuzz=500pt choice & \\hfuzz=500pt what should happen if no antenna pattern is found for an observation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ignoreObservation & \\hfuzz=500pt  & \\hfuzz=500pt ignore observation if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~useNearestFrequency & \\hfuzz=500pt  & \\hfuzz=500pt use pattern of nearest frequency if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~throwException & \\hfuzz=500pt  & \\hfuzz=500pt throw exception if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileReceiverDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt observed signal types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccuracyDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt elevation and azimut dependent accuracy\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileObservations & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt approximate positions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt satellite attitude\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaFactorPhase & \\hfuzz=500pt expression & \\hfuzz=500pt PHASE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaFactorCode & \\hfuzz=500pt expression & \\hfuzz=500pt CODE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~supportsIntegerAmbiguities & \\hfuzz=500pt boolean & \\hfuzz=500pt receiver tracks full cycle integer ambiguities\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~wavelengthFactor & \\hfuzz=500pt double & \\hfuzz=500pt factor to account for half-wavelength observations (collected by codeless squaring techniques)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~useType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt only use observations that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~ignoreType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt ignore observations that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~elevationCutOff & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] ignore observations below cutoff\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minObsCountPerTrack & \\hfuzz=500pt uint & \\hfuzz=500pt tracks with less number of epochs with observations are dropped\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~preprocessing & \\hfuzz=500pt sequence & \\hfuzz=500pt settings for preprocessing of observations/stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~printStatistics & \\hfuzz=500pt boolean & \\hfuzz=500pt print preprocesssing statistics for all receivers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~codeMaxPositionDiff & \\hfuzz=500pt double & \\hfuzz=500pt [m] max. allowed position error by PPP code only clock error estimation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~denoisingLambda & \\hfuzz=500pt double & \\hfuzz=500pt regularization parameter for total variation denoising used in cylce slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~tecWindowSize & \\hfuzz=500pt uint & \\hfuzz=500pt (0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~tecSigmaFactor & \\hfuzz=500pt double & \\hfuzz=500pt factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileTrackBefore & \\hfuzz=500pt filename & \\hfuzz=500pt variables \\{station\\}, \\{prn\\}, \\{trackTimeStart\\}, \\{trackTimeEnd\\}, \\{types\\}, TEC and MW-like combinations in cycles for each track before cycle slip detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileTrackAfter & \\hfuzz=500pt filename & \\hfuzz=500pt variables \\{station\\}, \\{prn\\}, \\{trackTimeStart\\}, \\{trackTimeEnd\\}, \\{types\\}, TEC and MW-like combinations in cycles for each track after cycle slip detection\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{GnssTransmitterGenerator}\\label{gnssTransmitterGeneratorType}\nDefinition and basic information of GNSS transmitters.\n\nSee also \\program{GnssProcessing} and \\program{GnssSimulateReceiver}.\n\n\n\\subsection{GNSS}\\label{gnssTransmitterGeneratorType:gnss}\nA list of satellite PRNs (i.e for GPS: G01, G02, G03, ...) must be provided via\n\\configFile{inputfileTransmitterList}{stringList}. Satellite system codes follow the\n\\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition}, see \\reference{GnssType}{gnssType}.\nAll input files except \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition},\nand \\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition} are read for each satellite.\nThe file name is interpreted as a template with the variable \\verb|{prn}| being replaced by the satellite PRN.\n\nMetadata input files (marked with \\textbf{*} below) are provided in GROOPS file formats at\n\\url{https://ftp.tugraz.at/pub/ITSG/groops}. These files are regularly updated.\n\\begin{itemize}\n  \\item \\configFile{inputfileTransmitterInfo}{platform}\\textbf{*}:\n        PRN-SVN mapping, antenna offsets and orientations.\n        Created via \\program{GnssAntex2AntennaDefinition} or \\program{PlatformCreate}.\n  \\item \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\\textbf{*}:\n        Antenna center variations.\n        Created via \\program{GnssAntex2AntennaDefinition} or \\program{GnssAntennaDefinitionCreate}.\n  \\item \\configFile{inputfileSignalDefintion}{gnssReceiverDefinition}\\textbf{*}:\n        Transmitted signal types.\n        Created via \\program{GnssReceiverDefinitionCreate} in case you want to define which signal\n        types a satellite transmits.\n  \\item \\configFile{inputfileClockFrequencyScale}{instrument}\\textbf{*}:\n        Scale factor of transmitted signals due to frequency offset/clock drift.\n        Can be dreived from broadcast clocks drifts.\n  \\item \\configFile{inputfileOrbit}{instrument}: Converted via \\program{Sp3Format2Orbit} or\n        output of \\program{GnssProcessing}.\n  \\item \\configFile{inputfileAttitude}{instrument}:\n        Rotation from body frame to CRF. Created via \\program{SimulateStarCameraGnss} or converted via \\program{GnssOrbex2StarCamera}.\n  \\item \\configFile{inputfileClock}{instrument}:\n        Converted via \\program{GnssClockRinex2InstrumentClock} or \\program{GnssRinexNavigation2OrbitClock} or\n        output of \\program{GnssProcessing}.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileTransmitterList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with transmitter PRNs, used to loop variable \\{prn\\}\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefintion & \\hfuzz=500pt filename & \\hfuzz=500pt phase centers and variations (ANTEX like)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~noAntennaPatternFound & \\hfuzz=500pt choice & \\hfuzz=500pt what should happen is no antenna pattern is found for an observation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ignoreObservation & \\hfuzz=500pt  & \\hfuzz=500pt ignore observation if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~useNearestFrequency & \\hfuzz=500pt  & \\hfuzz=500pt use pattern of nearest frequency if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~throwException & \\hfuzz=500pt  & \\hfuzz=500pt throw exception if no matching pattern is found\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSignalDefintion & \\hfuzz=500pt filename & \\hfuzz=500pt transmitted signal types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileClockFrequencyScale & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAttitude & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{prn\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolateClock & \\hfuzz=500pt boolean & \\hfuzz=500pt linear interpolation of missing epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for orbit interpolation and velocity calculation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{GnssType}\\label{gnssType}\nA GnssType string consists of six parts (type, frequency, attribute, system, PRN, frequency number)\nrepresented by seven characters.\n\\begin{itemize}\n\\item The first three characters (representing type, frequency, and attribute) correspond to the observation codes of the\n      \\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition}.\n\\item The satellite system character also follows the RINEX 3 definition:\n      \\begin{itemize}\n        \\item \\verb|G| = GPS\n        \\item \\verb|R| = GLONASS\n        \\item \\verb|E| = Galileo\n        \\item \\verb|C| = BeiDou\n        \\item \\verb|S| = SBAS\n        \\item \\verb|J| = QZSS\n        \\item \\verb|I| = IRNSS\n      \\end{itemize}\n\\item PRN is a two-digit number identifying a satellite.\n\\item Frequency number is only used for GLONASS, where the range -7 to 14 is represented by letters starting with A.\n\\end{itemize}\n\nEach part of a GnssType string can be replaced by a wildcard '\\verb|*|', enabling the use of these strings as patterns,\nfor example to select a subset of observations (e.g. \\verb|C**G**| matches all GPS code/range observations).\nTrailing wildcards are optional, meaning \\verb|L1*R| is automatically expanded to \\verb|L1*R***|.\nFor some RINEX 2 types (e.g. Galileo L5) the RINEX 3 attribute is unknown/undefined and can be replaced by \\verb|?|,\nfor example \\verb|L5?E01|.\n\nExamples:\n\\begin{itemize}\n\\item \\verb|C1CG23| = code/range observation, L1 frequency, derived from C/A code, GPS, PRN 23\n\\item \\verb|L2PR05B| = phase observation, G2 frequency, derived from P code, GLONASS, PRN 05, frequency number -6\n\\item \\verb|*5*E**| = all observation types, E5a frequency, all attributes, Galileo, all PRNs\n\\end{itemize}\n\n\\clearpage\n%==================================\n\n\\section{Gravityfield}\\label{gravityfieldType}\nThis class computes functionals of the time depending gravity field,\ne.g potential, gravity anomalies or gravity gradients.\n\nIf several instances of the class are given the results are summed up.\nBefore summation every single result is multiplicated by a \\config{factor}.\nTo subtract a normal field like GRS80 from a potential\nto get the disturbance potential you must choose one factor by 1\nand the other by -1. To get the mean of two fields just set each factor to 0.5.\n\nSome of the instances gives also information about the accuracy.\nThe variance of the result (sum) is computed by means of variance propagation.\n\n\n\\subsection{PotentialCoefficients}\\label{gravityfieldType:potentialCoefficients}\nReads coefficients of a spherical harmonics expansion from file.\nThe potential is given by\n\\begin{equation}\nV(\\lambda,\\vartheta,r) = \\frac{GM}{R}\\sum_{n=0}^\\infty \\sum_{m=0}^n \\left(\\frac{R}{r}\\right)^{n+1}\n  \\left(c_{nm} C_{nm}(\\lambda,\\vartheta) + s_{nm} S_{nm}(\\lambda,\\vartheta)\\right).\n\\end{equation}\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The computed result\nis multiplied with \\config{factor}. If \\config{setSigmasToZero} is true\nthe variances are set to zero. This option is only important for variance propagation\nand does not change the result of the gravity field functionals.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~setSigmasToZero & \\hfuzz=500pt boolean & \\hfuzz=500pt set variances to zero, should be used by adding back reference fields\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PotentialCoefficientsInterior}\nReads coefficients of a spherical harmonics expansion (for inner space) from file.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The computed result is multiplied with \\config{factor}.\nIf \\config{setSigmasToZero} is true the variances are set to zero.\nThis option is only important for error propagation\nand does not change the result of the gravity field functionals.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~setSigmasToZero & \\hfuzz=500pt boolean & \\hfuzz=500pt set variances to zero, should be used by adding back reference fields\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FromParametrization}\\label{gravityfieldType:fromParametrization}\nReads a solution vector from file \\configFile{inputfileSolution}{matrix}\nwhich may be computed by a least squares adjustment (e.g. by \\program{NormalsSolverVCE}).\nThe coefficients of the vector are interpreted from position \\config{indexStart}\n(counting from zero) with help of \\configClass{parametrizationGravity}{parametrizationGravityType}.\nIf the solution file contains solution of several right hand sides you can choose\none with number \\config{rightSide} (counting from zero).\nYou can also read a vector from file \\configFile{inputfileSigmax}{matrix}\ncontaining the accuracies of the coefficients.\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standards deviations or covariance matrix of the solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~indexStart & \\hfuzz=500pt uint & \\hfuzz=500pt position in the solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rightSide & \\hfuzz=500pt uint & \\hfuzz=500pt if solution contains several right hand sides, select one\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TimeSplines}\\label{gravityfieldType:timeSplines}\nRead a time variable gravity field from file\n\\configFile{inputfileTimeSplinesGravityfield}{timeSplinesGravityField}\nrepresented by a spherical harmonics expansion in the spatial domain and spline functions\nin the time domain. If set the expansion is limited in the range between\n\\config{minDegree} and \\config{maxDegree} inclusivly.\n\nThis file can be created for example by \\program{Gravityfield2TimeSplines} or\n\\program{PotentialCoefficients2BlockMeanTimeSplines}.\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTimeSplinesGravityfield & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileTimeSplinesCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Trend}\\label{gravityfieldType:trend}\nThe given \\configClass{gravityfield}{gravityfieldType} is interpreted\nas trend function and the result is computed at time $t$ as follows\n\\begin{equation}\nV(\\M x,t) = \\frac{t-t_0}{\\Delta t}V(\\M x),\n\\end{equation}\nwith $t_0$ is \\config{timeStart} and $\\Delta t$ is \\config{timeStep}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt this field is multiplicated by (time-time0)/timeStep\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt reference time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStep & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Oscillation}\\label{gravityfieldType:oscillation}\nThe given \\configClass{gravityfield}{gravityfieldType} is interpreted\nas oscillation function and the result is computed at time $t$ as follows\n\\begin{equation}\nV(\\M x,t) = \\cos(\\omega)V_{cos}(\\M x)+\\sin(\\omega)V_{sin}(\\M x),\n\\end{equation}\nwith $\\omega=\\frac{2\\pi}{T}(t-t_0)$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfieldCos & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt multiplicated by cos(2pi/T(time-time0))\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfieldSin & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt multiplicated by sin(2pi/T(time-time0))\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time0 & \\hfuzz=500pt time & \\hfuzz=500pt reference time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~period & \\hfuzz=500pt time & \\hfuzz=500pt [day]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{InInterval}\nA \\configClass{gravityfield}{gravityfieldType} is only evaluated in the interval between\n\\config{timeStart} inclusively and \\config{timeEnd} exclusively.\nOutside the interval the result is zero.\n\nThis class is useful to get a time series of monthly mean GRACE gravity field solutions.\nIn each month another file of potentialCoefficients is valid.\nThis can easily be created with \\configClass{loop}{loopType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt first point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt last point in time will be less or equal timeEnd\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Tides}\\label{gravityfieldType:tides}\nTreat \\configClass{tides}{tidesType} as gravitational forces.\nThe tides need a realization of \\configClass{earthRotation}{earthRotationType}\nto transform between the CRF and TRF and to compute rotational deformation\nfrom polar motion.\nIt also needs \\configClass{ephemerides}{ephemeridesType} from Sun, moon, and planets.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~tides & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Topography}\\label{gravityfieldType:topography}\nThe gravity is integrated from a topographic mass distribution.\nFor each grid point in \\configFile{inputfileGridRectangular}{griddedData} a prisma with\n\\config{density} is assumed. The horizontal extension is computed from the grid spacing\nand the vertical extension is given by \\config{radialLowerBound}\nand \\config{radialUpperBound} above ellipsoid. All values are expressions and computed\nfor each point with given data in the grid file. The standard variables for grids\nare available, see~\\reference{dataVariables}{general.parser:dataVariables}.\n\nExample: The grid file contains the orthometric height of the topography in the first\ncolumn, the geoid height in the second and the mean density of each prism in the third\ncolumn. In this case the following settings should be used:\n\\begin{itemize}\n\\item \\config{radialUpperBound} = \\verb|data0+data1|,\n\\item \\config{radialLowerBound} = \\verb|data1|,\n\\item \\config{density} = \\verb|data2|.\n\\end{itemize}\n\nAs the prim computation is time consuming a maximum distance around the evaluation point\ncan defined with \\config{distancePrism}. Afterwards a simplified radial line\n(the prism mass is concentrated to a line in the center) is used up to\na distance of \\config{distanceLine}. At last the prim is approximated by a point mass\nin the center up to a distance \\config{distanceMax} (if set). Prisms nearby the evaluation\npoint can be excluded with \\config{distanceMin}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGridRectangular & \\hfuzz=500pt filename & \\hfuzz=500pt Digital Terrain Model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~density & \\hfuzz=500pt expression & \\hfuzz=500pt expression [kg/m**3]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radialUpperBound & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables 'height', 'data', 'L', 'B' and, 'area' are taken from the gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radialLowerBound & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables 'height', 'data', 'L', 'B' and, 'area' are taken from the gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~distanceMin & \\hfuzz=500pt double & \\hfuzz=500pt [km] min. influence distance (ignore near zone)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~distancePrism & \\hfuzz=500pt double & \\hfuzz=500pt [km] max. distance for prism formular\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~distanceLine & \\hfuzz=500pt double & \\hfuzz=500pt [km] max. distance for radial integration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~distanceMax & \\hfuzz=500pt double & \\hfuzz=500pt [km] max. influence distance (ignore far zone)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EarthquakeOscillation}\nThe given \\configClass{gravityfield}{gravityfieldType} is interpreted as an oscillation function\nin the gravitational potential field, caused by large earthquakes.\nThe result is computed at time $t$ as follows:\n\\begin{equation}\nC_{lm}(\\M t) = \\sum_{n=0}^NC_{nlm}(1-\\cos(\\omega)\\exp(\\frac{-\\omega}{2Q_{nlm}})),\n\\end{equation}\nwith $\\omega=\\frac{2\\pi}{T_{nlm}}(t-t_0)$. In this equation, $Q_{nlm}$ is the attenuation factor,\n$n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time in second.\n$T_{nlm}$ and $Q_{nlm}$ are computed with the elastic Earth model or observed from the long\nperiod record of superconducting gravimeter measurements after the earthquakes.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputCoefficientMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt oscillation model parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time0 & \\hfuzz=500pt time & \\hfuzz=500pt the time earthquake happened\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Filter}\nConvert \\configClass{gravityfield}{gravityfieldType} to spherical harmonics\nand \\configClass{filter}{sphericalHarmonicsFilterType} the coefficients.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~filter & \\hfuzz=500pt \\hyperref[sphericalHarmonicsFilterType]{sphericalHarmonicsFilter} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{gravityfieldType:group}\nGroups a set of \\configClass{gravityfield}{gravityfieldType} and has no further effect itself.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Grid}\\label{gridType}\nThis class generates a set of grid points. In a first step, the grid\nis always generated globally, with \\configClass{border}{borderType} a regional\nsubset of points can be extracted from the global grid. The parameters\n\\config{R} and \\config{inverseFlattening} define the shape of the ellipsoid\non which the grid is generated. In case \\config{inverseFlattening} is\nchosen as zero, a sphere is used. With \\config{height} the distance of\nthe points above the ellipsoid can be defined. In addition to the location\nof the points, weights are assigned to each of the points. These weights\ncan be regarded as the surface element associated with each grid point.\n\n\n\\subsection{Geograph}\nThe geographical grid is an equal-angular point distribution with points\nlocated along meridians and along circles of latitude. \\config{deltaLambda}\ndenotes the angular difference between adjacent points along meridians and\n\\config{deltaPhi} describes the angular difference between adjacent points\nalong circles of latitude. The point setting results as follows:\n\\begin{equation}\n\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 0\\leq i< \\frac{360^\\circ}{\\Delta\\lambda},\n\\end{equation}\n\\begin{equation}\n\\varphi_j=-90^\\circ+\\frac{\\Delta\\varphi}{2}+j\\cdot\\Delta\\varphi\\qquad\\mbox{with}\\qquad 0\\leq j<\\frac{180^\\circ}{\\Delta\\varphi}.\n\\end{equation}\nThe number of grid points can be determined by\n\\begin{equation}\nI=\\frac{360^\\circ}{\\Delta\\lambda}\\cdot\\frac{180^\\circ}{\\Delta\\varphi}.\n\\end{equation}\nThe weights are calculated according to\n\\begin{equation}\nw_i=\\int\\limits_{\\lambda_i-\\frac{\\Delta\\lambda}{2}}^{\\lambda_i+\\frac{\\Delta\\lambda}{2}}\\int\\limits_{\\vartheta_i-\\frac{\\Delta\\vartheta}{2}}^{\\vartheta_i+\\frac{\\Delta\\vartheta}{2}}=2\\cdot\\Delta\\lambda\\sin(\\Delta\\vartheta)\\sin(\\vartheta_i).\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~deltaLambda & \\hfuzz=500pt angle & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~deltaPhi & \\hfuzz=500pt angle & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt ellipsoidal height expression (variables 'height', 'L', 'B')\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TriangleVertex}\nThe zeroth level of densification\ncoincides with the 12 icosahedron vertices, as displayed in the upper left part\nof Fig.~\\ref{fig:triangle_grid}. Then, depending on the envisaged densification,\neach triangle edge is divided into $n$ parts, illustrated in the upper right\npart of Fig.~\\ref{fig:triangle_grid}. The new nodes on the edges are then connected\nby arcs of great circles parallel to the triangle edges. The intersections of\neach three corresponding parallel lines become nodes of the densified grid as well.\nAs in case of a spherical triangle those three connecting lines do not exactly\nintersect in one point, the center of the resulting triangle is used as location\nfor the new node (lower left part of Fig.~\\ref{fig:triangle_grid}). The lower right\nside of Fig.~\\ref{fig:triangle_grid} finally shows the densified triangle vertex\ngrid for a level of $n=3$. The number of grid points in dependence of the chosen\nlevel of densification can be calculated by\n\\begin{equation}\\label{eq:numberVertex}\nI=10\\cdot(n+1)^2+2.\n\\end{equation}\n\n\\fig{!hb}{0.6}{icogrid}{fig:triangle_grid}{TriangleVertex grid.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~level & \\hfuzz=500pt uint & \\hfuzz=500pt division of icosahedron, point count = 10*(n+1)**2+2\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TriangleCenter}\nThe points of the zeroth level are located at the centers of the icosahedron triangles.\nTo achieve a finer grid, each of the triangles is divided into four smaller triangles by\nconnecting the midpoints of the triangle edges. The refined grid points are again located\nat the center of the triangles. Subsequently, the triangles can be further densified up to\nthe desired level of densification $n$, which is defined by \\config{level}.\n\nThe number of global grid points for a certain level can be determined by\n\\begin{equation}\\label{eq:numberCenter}\nI=20\\cdot 4^n.\n\\end{equation}\nThus the quantity of grid points depends exponentially on the level $n$, as with\nevery additional level the number of grid points quadruplicates.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~level & \\hfuzz=500pt uint & \\hfuzz=500pt division of icosahedron, point count = 5*4**(n+1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Gauss}\n The grid features equiangular spacing along circles of latitude with\n \\config{parallelsCount} defining the number $L$ of the parallels.\n\\begin{equation}\n\\Delta\\lambda=\\frac{\\pi}{L}\\qquad\\Rightarrow\\qquad\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 0\\leq i< 2L.\n\\end{equation}\nAlong the meridians the points are located at $L$ parallels at\nthe $L$ zeros $\\vartheta_j$ of the Legendre polynomial of degree~$L$,\n\\begin{equation}\nP_L(\\cos\\vartheta_j)=0.\n\\end{equation}\nConsequently, the number of grid points sums up to\n\\begin{equation}\nI=2\\cdot L^2.\n\\end{equation}\nThe weights can be calculated according to\n\\begin{equation}\nw_i(L)=\\Delta\\lambda\\frac{2}{(1-t_i^2)(P'_{L}(\\cos(\\vartheta _i)))^2},\\label{weights}\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~parallelsCount & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Reuter}\nThe Reuter grid features equi-distant spacing along the meridians determined\nby the control parameter~$\\gamma$ according to\n\\begin{equation}\n\\Delta\\vartheta=\\frac{\\pi}{\\gamma}\\qquad\\Rightarrow\\vartheta_j=j\\Delta\\vartheta,\\qquad\\mbox{with}\\qquad 1\\leq j\\leq \\gamma-1.\n\\end{equation}\nThus $\\gamma+1$ denotes the number of points per meridian, as the two poles\nare included in the point distribution as well. Along the circles of latitude,\nthe number of grid points decreases with increasing latitude in order to achieve\nan evenly distributed point pattern. This number is chosen, so that the points\nalong each circle of latitude have the same spherical distance as two adjacent\nlatitudes. The resulting relationship is given by\n\\begin{equation}\\label{eq:sphericalDistance}\n\\Delta\\vartheta=\\arccos\\left( \\cos^2\\vartheta_j+\\sin^2\\vartheta_j\\cos\\Delta\\lambda_j\\right).\n\\end{equation}\nThe left hand side of this equation is the spherical distance between adjacent\nlatitudes, the right hand side stands for the spherical distance between two points\nwith the same polar distance $\\vartheta_j$ and a longitudinal difference of\n$\\Delta\\lambda_i$. This longitudinal distance can be adjusted depending on\n$\\vartheta_j$ to fulfill Eq.~\\eqref{eq:sphericalDistance}. The resulting\nformula for $\\Delta\\lambda_i$ is\n\\begin{equation}\\label{eq:deltaLambdai}\n\\Delta\\lambda_j=\\arccos\\left( \\frac{\\sin\\Delta\\vartheta -\\cos^2\\vartheta_j}{\\sin^2\\vartheta_j}\\right).\n\\end{equation}\nThe number of points~$\\gamma_j$ for each circle of latitude can then be determined by\n\\begin{equation}\\label{eq:gammai}\n\\gamma_j=\\left[ \\frac{2\\pi}{\\Delta\\lambda_j}\\right] .\n\\end{equation}\nHere the Gauss bracket $[x]$ specifies the largest integer equal to or less than $x$.\nThe longitudes are subsequently determined by\n\\begin{equation}\n\\lambda_{ij}=\\frac{\\Delta\\lambda_j}{2}+i\\cdot(2\\pi/\\gamma_j),\\qquad\\mbox{with}\\qquad 0\\leq i< \\gamma_j.\n\\end{equation}\nThe number of grid points can be estimated by\n\\begin{equation}\\label{eq:numberReuter}\nI=\\leq 2+\\frac{4}{\\pi}\\gamma^2,\n\\end{equation}\nThe $\\leq$ results from the fact that the $\\gamma_j$ are restricted to integer values.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~gamma & \\hfuzz=500pt uint & \\hfuzz=500pt number of parallels\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt ellipsoidal height\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Corput}\nThis kind of grid distributes an arbitrarily chosen number of $I$ points\n(defined by \\config{globalPointsCount}) following a recursive, quasi random sequence.\nIn longitudinal direction the pattern follows\n\\begin{equation}\n\\Delta\\lambda=\\frac{2\\pi}{I}\\qquad\\Rightarrow\\qquad\\frac{\\Delta\\lambda}{2}+\\lambda_i=i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 1\\leq i\\leq I.\n\\end{equation}\nThis implies that every grid point features a unique longitude, with equi-angular\nlongitudinal differences.\n\nThe polar distance in the form $t_i=\\cos\\vartheta_i$ for each point is determined\nby the following recursive sequence:\n\\begin{itemize}\n\\item Starting from an interval $t\\in[-1,1]$.\n\\item If $I=1$, then the midpoint of the interval is returned as result of\nthe sequence, and the sequence is terminated.\n\\item If the number of points is uneven, the  midpoint is included into the list of $t_i$.\n\\item Subsequently, the interval is bisected into an upper and lower half,\n       and the sequence is called for both halves.\n\\item $t$ from upper and lower half are alternately sorted into the list of $t_i$.\n\\item The polar distances are calculated by\n\\begin{equation}\n\\vartheta_i=\\arccos\\, t_i.\n\\end{equation}\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~globalPointsCount & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt ellipsoidal height\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Driscoll}\nThe Driscoll-Healy grid, has equiangular spacing along the meridians as well\nas along the circles of latitude. In longitudinal direction (along the parallels),\nthese angular differences for a given \\config{dimension} $L$ coincide with those\ndescribed for the corresponding geographical grid and Gauss grid. Along the meridians,\nthe size of the latitudinal differences is half the size compared to the geographical\ngrid. This results in the following point pattern,\n\\begin{equation}\n\\begin{split}\n\\Delta\\lambda=\\frac{\\pi}{L}\\qquad&\\Rightarrow\\qquad\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad&\\mbox{with}\\qquad 0\\leq i< 2L, \\\\\n\\Delta\\vartheta=\\frac{\\pi}{2L}\\qquad&\\Rightarrow\\qquad\\vartheta_j=j\\cdot\\Delta\\vartheta\\qquad&\\mbox{with}\\qquad 1\\leq j\\leq 2L.\n\\end{split}\n\\end{equation}\nConsequently, the number of grid points is\n\\begin{equation}\nI=4\\cdot L^2.\n\\end{equation}\nThe weights are given by\n\\begin{equation}\nw_i=\\Delta\\lambda\\frac{4}{2L}\\sin(\\vartheta_i)\\sum_{l=0}^{L-1}\\frac{\\sin\\left[ (2l+1)\\;\\vartheta_i\\right] }{2l+1}.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~dimension & \\hfuzz=500pt uint & \\hfuzz=500pt number of parallels = 2*dimension\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt ellipsoidal height\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SinglePoint}\nCreates one single point.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~L & \\hfuzz=500pt angle & \\hfuzz=500pt longitude\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~B & \\hfuzz=500pt angle & \\hfuzz=500pt latitude\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt ellipsoidal height\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~area & \\hfuzz=500pt double & \\hfuzz=500pt associated area element on unit sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt major axsis of the ellipsoid/sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt flattening of the ellipsoid, 0: sphere\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SinglePointCartesian}\nCreates one single point.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~x & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~y & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~z & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~area & \\hfuzz=500pt double & \\hfuzz=500pt associated area element on unit sphere\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{File}\\label{gridType:file}\nIn this class grid is read from a file, which is given by \\configFile{inputfileGrid}{griddedData}.\nA corresponding file can be generated with \\program{GriddedDataCreate} or with \\program{Matrix2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGrid & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{InstrumentType}\\label{instrumentTypeType}\nDefines the type of an \\file{instrument file}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~instrumentTypeType & \\hfuzz=500pt choice & \\hfuzz=500pt instrument type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~INSTRUMENTTIME & \\hfuzz=500pt  & \\hfuzz=500pt time without data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MISCVALUE & \\hfuzz=500pt  & \\hfuzz=500pt single value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MISCVALUES & \\hfuzz=500pt  & \\hfuzz=500pt multiple values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~VECTOR3D & \\hfuzz=500pt  & \\hfuzz=500pt x, y, z\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~COVARIANCE3D & \\hfuzz=500pt  & \\hfuzz=500pt xx, yy, zz, xy, xz, yz\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ORBIT & \\hfuzz=500pt  & \\hfuzz=500pt position [m], velocity [m/s], acceleration [m/s\\textasciicircum{}2] (each x, y, z)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~STARCAMERA & \\hfuzz=500pt  & \\hfuzz=500pt quaternions (q0, qx, qy, qz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ACCELEROMETER & \\hfuzz=500pt  & \\hfuzz=500pt x, y, z [m/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~SATELLITETRACKING & \\hfuzz=500pt  & \\hfuzz=500pt range [m], range rate [m/s], range acceleration [m/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~GRADIOMETER & \\hfuzz=500pt  & \\hfuzz=500pt xx, yy, zz, xy, xz, yz [1/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~GNSSRECEIVER & \\hfuzz=500pt  & \\hfuzz=500pt GNSS phase/code observations [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~OBSERVATIONSIGMA & \\hfuzz=500pt  & \\hfuzz=500pt accuracy\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~SATELLITELASERRANGING & \\hfuzz=500pt  & \\hfuzz=500pt range [m], accuracy [m], redundancy, window [s], wavelength [m], azimuth [rad], elevation [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~METEOROLOGICAL & \\hfuzz=500pt  & \\hfuzz=500pt temperature [K], pressure [Pa], humidity [\\%], windSpeed [m/s], radiation [W/m\\textasciicircum{}2], precip. [mm/d]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MASS & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~THRUSTER & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MAGNETOMETER & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ACCHOUSEKEEPING & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{InterpolatorTimeSeries}\\label{interpolatorTimeSeriesType}\nThis class resamples data of a times series to new poins in time.\n\n\n\\subsection{Polynomial}\nPolynomial prediction using a moving polynomial of \\config{polynomialDegree}.\nThe optimal polynomial is chosen based on the centricity of the data points around the resampling\npoint and the distance to all polynomial data points. All polynomial data points must be within\n\\config{maxDataPointRange}. Resampling points within \\config{maxExtrapolationDistance} of the\npolynomial will be extrapolated. The elements \\config{maxDataPointRange} and \\config{maxExtrapolationDistance}\nare given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.\n\n\\fig{!hb}{0.5}{instrumentResample_polynomial}{fig:instrumentResample_polynomial}{Example of polynomial prediction when resampling from 5 to 1 minute sampling}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of the moving polynomial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDataPointRange & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] all degree+1 data points must be within this range for a valid polynomial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxExtrapolationDistance & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] resampling points within this range of the polynomial will be extrapolated\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Least squares polynomial fit}\nA polynomial of \\config{polynomialDegree} is estimated using all data points within\n\\config{maxDataPointDistance} of the resampling point. This polynomial is then used\nto predict the resampling point. A resampling point will be extrapolated if there are\nonly data points before/after as long as the closest one is within \\config{maxExtrapolationDistance}.\nThe elements \\config{maxDataPointDistance} and \\config{maxExtrapolationDistance} are given\nin the unit of seconds. If negative values are used, the unit is relative to the median input sampling.\n\n\\fig{!hb}{0.5}{instrumentResample_leastSquares}{fig:instrumentResample_leastSquares}{Example of least squares polynomial fit when resampling from 5 to 1 minute sampling}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of the estimated polynomial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDataPointDistance & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] all data points within this distance around the resampling point will be used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxExtrapolationDistance & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] resampling points within this range of the polynomial will be extrapolated\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Fill gaps with least squares polynomial fit}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of the estimated polynomial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDataGap & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] max data gap to interpolate\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDataSpan & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] time span on each side used for least squares fit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] margin for identical times\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Kernel}\\label{kernelType}\nKernel defines harmonic isotropic integral kernels $K$.\n\\begin{equation}\nT(P) = \\frac{1}{4\\pi}\\int_\\Omega K(P,Q)\\cdot f(Q)\\,d\\Omega(Q),\n\\end{equation}\nwhere $T$ is the (disturbance)potential and $f$ is a functional on the spherical surface~$\\Omega$.\nThe Kernel can be exapanded into a series of (fully normalized) legendre polynomials\n\\begin{equation}\\label{eq.kernel}\nK(\\cos\\psi,r,R) = \\sum_n \\left(\\frac{R}{r}\\right)^{n+1}\nk_n\\sqrt{2n+1}\\bar{P}_n(\\cos\\psi).\n\\end{equation}\nOn the one hand the kernel defines the type of the functionals~$f$ that are measured\nor have to be computed, e.g. gravity anomalies given by the Stokes-kernel.\nOn the other hand the kernel functions can be used as basis functions to represent\nthe gravity field, e.g. as spline functions or wavelets.\n\n\n\\subsection{GeoidHeight}\\label{kernelType:geoidHeight}\nThe geoid height is defined by Bruns formula\n\\begin{equation}\nN = \\frac{1}{\\gamma}T\n\\end{equation}\nwith $T$ the disturbance potential and the normal gravity\n\\begin{equation}\\label{normalgravity}\n\\gamma  = \\gamma_0 - 0.30877\\cdot 10^{-5}/s^2(1-0.00142\\sin^2(B))h\n\\end{equation}\nand\n\\begin{equation}\n\\gamma_0 = 9.780327\\,m/s^2(1+0.0053024\\sin^2(B)-0.0000058\\sin^2(2B))\n\\end{equation}\nwhere $h$ is the ellipsoidal height in meter and $B$ the longitude.\n\nThe kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\gamma\\frac{R(r^2-R^2)}{l^3},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\gamma.\n\\end{equation}\n\n\n\\subsection{Anomalies}\nGravity anomalies in linearized form are defined by\n\\begin{equation}\n\\Delta g = -\\frac{\\partial T}{\\partial r}-\\frac{2}{r}T.\n\\end{equation}\nThe Stokes kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\frac{2R^2}{l}-3\\frac{Rl}{r^2}-\\frac{R^2}{r^2}\\cos\\psi\n\\left(5+3\\ln\\frac{l+r-R\\cos\\psi}{2r}\\right),\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{R}{n-1}.\n\\end{equation}\n\n\n\\subsection{Disturbance}\\label{kernelType:disturbance}\nGravity disturbances in linearized form are defined by\n\\begin{equation}\n\\delta g = -\\frac{dT}{dr}.\n\\end{equation}\nThe Hotine kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\frac{2R^2}{l}-R\\ln\\frac{l+R-r\\cos\\psi}{r(1-\\cos\\psi)},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{R}{n+1}.\n\\end{equation}\n\n\n\\subsection{Potential}\nThe Abel-Poisson kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\frac{R(r^2-R^2)}{l^3},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = 1.\n\\end{equation}\n\n\n\\subsection{Density}\nThis kernel defines a point mass or mass on a single layer ($1/l$-kernel)\ntaking the effect of the loading into account.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = 4\\pi G R\\frac{1+k_n'}{2n+1},\n\\end{equation}\nwhere $G$ is the gravitational constant and $k_n'$ are the load Love numbers.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileLoadingLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WaterHeight}\\label{kernelType:waterHeight}\nHeight of equivalent water columns taking the effect of the loading into account.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = 4\\pi G \\rho R\\frac{1+k_n'}{2n+1},\n\\end{equation}\nwhere $G$ is the gravitational constant, $\\rho$ is the \\config{density} of water\nand $k_n'$ are the load Love numbers.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~density & \\hfuzz=500pt double & \\hfuzz=500pt [kg/m**3]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileLoadingLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{BottomPressure}\nOcean bottom pressure caused by water and atmosphere masses columns taking the effect of the loading into account.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{4\\pi G R }{\\gamma}\\frac{1+k_n'}{2n+1},\n\\end{equation}\nwhere $G$ is the gravitational constant, $\\gamma$ is the normal gravity and $k_n'$ are the load Love numbers.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileLoadingLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Deformation}\nComputes the radial deformation caused by loading.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\gamma\\frac{1+k_n'}{h_n'},\n\\end{equation}\nwhere $\\gamma$ is the normal gravity defined in \\eqref{normalgravity},\n$h_n'$ and $k_n'$ are the load Love numbers and the load deformation Love numbers.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDeformationLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfilePotentialLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt if full potential is given and not only loading potential\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RadialGradient}\nThis kernel defines the second radial derivative of the (disturbance) potential.\n\\begin{equation}\nT_{rr} = \\frac{\\partial^2 T}{\\partial r^2}.\n\\end{equation}\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{r^2}{(n+1)(n+2)}.\n\\end{equation}\n\n\n\\subsection{Coefficients}\\label{kernelType:coefficients}\nThe kernel is defined by the coefficients $k_n$ given by file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FilterGauss}\nAnother \\configClass{kernel}{kernelType} is smoothed by a gauss filter\nwhich is defined by\n\\begin{equation}\nF(\\cos\\psi) = \\frac{b\\cdot e^{-b(1-\\cos\\psi)}}{1-e^{-2b}}\n\\end{equation}\nwith $b = \\frac{ln(2)}{1-\\cos(r/R)}$ where $r$ is the given\nsmoothing \\config{radius} in km and $R=6378.1366$~km is the\nEarth radius.\nThe coefficients~$k_n$ of the \\config{kernel} are multiplicated by\n\\begin{equation}\nf_n = \\frac{1}{2n+1} \\int_{-1}^1 F(t)\\cdot \\bar{P}_n(t)\\,dt.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~radius & \\hfuzz=500pt double & \\hfuzz=500pt filter radius [km]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{BlackmanLowpass}\nAnother \\configClass{kernel}{kernelType} is smoothed by a Blackman low-pass filter. The filter is\ndefined through the beginning and end of the transition from pass-band to stop-band. This\ntransition band is specified by \\config{startDegreeTransition} ($n_1$) and \\config{stopDegreeTransition} ($n_2$).\n\nThe coefficients of this kernel are defined as\n\\begin{equation}\n\\begin{cases}\n1 & \\text{for } n < n_1 \\\\\nA_n^2 & \\text{for } n_1\\leq n \\leq n_2 \\\\\n0 & \\text{for } n > n_2 \\\\\n\\end{cases}\n\\end{equation}\nwith\n\\begin{equation}\nA_n = 0.42 + 0.5\\cos(\\pi \\frac{n-n_1}{n_2-n_1}) + 0.08 \\cos(2\\pi\\frac{n-n_1}{n_2-n_1}).\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~startDegreeTransition & \\hfuzz=500pt uint & \\hfuzz=500pt minimum degree in transition band\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~stopDegreeTransition & \\hfuzz=500pt uint & \\hfuzz=500pt maximum degree in transition band\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Truncation}\nAnother \\configClass{kernel}{kernelType} is truncated before \\config{minDegree} and after \\config{maxDegree}.\nThe coefficients of this kernel are defined as\n\\begin{equation}\n  k_n =\n  \\begin{cases}\n  1 & \\text{for } n_{\\text{minDegree}} \\leq n \\leq n_{\\text{maxDegree}}\\\\\n  0 & \\text{else.} \\\\\n  \\end{cases}\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt truncate before minDegree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt truncate after maxDegree\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SelenoidHeight}\nThe selenoid height is defined by Bruns formula\n\\begin{equation}\nN = \\frac{1}{\\gamma}T\n\\end{equation}\nwith $T$ the disturbance potential and the normal gravity $\\gamma=\\frac{GM}{R^2}$ of the moon.\n\nThe kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\gamma\\frac{R(r^2-R^2)}{l^3},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\gamma.\n\\end{equation}\n\n\\clearpage\n%==================================\n\n\\section{Loop}\\label{loopType}\nGenerates a sequence with variables to loop over.\nThe variable names can be set with \\config{variableLoop...} and\nthe current values are assigned to the variables for each loop step.\n\nWith \\configClass{condition}{conditionType} only a subset of loop steps are performed.\nThe \\config{variableLoopIndex} and \\config{variableLoopCount} are not affected by the condition.\nThe result would therefore be the same as using \\program{LoopPrograms} with a nested \\program{IfPrograms}.\n\nSee \\reference{Loop and conditions}{general.loopsAndConditions} for usage.\n\n\n\\subsection{TimeSeries}\\label{loopType:timeSeries}\nLoop over points in time.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt loop is called for every point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTime & \\hfuzz=500pt string & \\hfuzz=500pt variable with time of each loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TimeIntervals}\\label{loopType:timeIntervals}\nLoop over the intervals between points in time.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeIntervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt loop is called for every interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTimeStart & \\hfuzz=500pt string & \\hfuzz=500pt variable with starting time of each interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTimeEnd & \\hfuzz=500pt string & \\hfuzz=500pt variable with ending time of each interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StringList}\\label{loopType:stringList}\nLoop over list of strings.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~string & \\hfuzz=500pt string & \\hfuzz=500pt explicit list of strings\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopString & \\hfuzz=500pt string & \\hfuzz=500pt name of the variable to be replaced\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StringTable}\\label{loopType:stringTable}\nLoop over \\config{row}s of a table containing strings.\nEach row must have the same number of cells.\nFor each column an extra \\config{variableLoopString} can be defined.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~row & \\hfuzz=500pt sequence & \\hfuzz=500pt rows of a table\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~cell & \\hfuzz=500pt string & \\hfuzz=500pt list of columns in a row\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~transpose & \\hfuzz=500pt boolean & \\hfuzz=500pt loop over columns instead of rows\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~variableLoopString & \\hfuzz=500pt string & \\hfuzz=500pt 1. variable name for the 1. column, next variable name for the 2. column, ... \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FileStringList}\\label{loopType:fileStringList}\nLoop over list of strings from \\file{files}{stringList}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt string list file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopString & \\hfuzz=500pt string & \\hfuzz=500pt name of the variable to be replaced\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FileStringTable}\\label{loopType:fileStringTable}\nLoop over rows of a \\file{table}{stringTable} containing strings.\nEach row must have the same number of columns.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt string table file with multiple columns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~transpose & \\hfuzz=500pt boolean & \\hfuzz=500pt loop over columns instead of rows\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~variableLoopString & \\hfuzz=500pt string & \\hfuzz=500pt 1. variable name for the 1. column, next variable name for the 2. column, ... \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FileTextLines}\\label{loopType:fileTextLines}\nLoop over lines of a text file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt simple text file with lines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt start at element startIndex (counting from 0)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~count & \\hfuzz=500pt uint & \\hfuzz=500pt use number of loops only (default: use all)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopLine & \\hfuzz=500pt string & \\hfuzz=500pt name of the variable to be replaced\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Matrix}\\label{loopType:matrix}\nLoop over rows of a \\file{matrix}{matrix}. To define the loop variables the standard\ndata variables of the matrix are available, see~\\reference{dataVariables}{general.parser:dataVariables}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~transpose & \\hfuzz=500pt boolean & \\hfuzz=500pt effectively loop over columns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startRow & \\hfuzz=500pt expression & \\hfuzz=500pt start at this row (variable: rows)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countRows & \\hfuzz=500pt expression & \\hfuzz=500pt use this many rows (variable: rows)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~variableLoop & \\hfuzz=500pt expression & \\hfuzz=500pt define a variable by name = expression (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{NumberSequence}\\label{loopType:numberSequence}\nLoop over sequence of numbers.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rangeStart & \\hfuzz=500pt double & \\hfuzz=500pt start of range\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rangeEnd & \\hfuzz=500pt double & \\hfuzz=500pt end of range (inclusive)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt sampling\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopNumber & \\hfuzz=500pt string & \\hfuzz=500pt name of the variable to be replaced\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DirectoryListing}\\label{loopType:directoryListing}\nLoop over files of a directory.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~directory & \\hfuzz=500pt filename & \\hfuzz=500pt directory\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~pattern & \\hfuzz=500pt string & \\hfuzz=500pt wildcard pattern\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~isRegularExpression & \\hfuzz=500pt boolean & \\hfuzz=500pt pattern is a regular expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopFile & \\hfuzz=500pt string & \\hfuzz=500pt name of the variable to be replaced\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{CommandOutput}\\label{loopType:commandOutput}\nLoop over lines of command output.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~command & \\hfuzz=500pt filename & \\hfuzz=500pt each output line becomes a loop iteration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~silently & \\hfuzz=500pt boolean & \\hfuzz=500pt without showing the output.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopString & \\hfuzz=500pt string & \\hfuzz=500pt name of the variable to be replaced\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PlatformEquipment}\\label{loopType:platformEquipment}\nLoop over specific equipment of a \\file{platform file}{platform}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePlatform & \\hfuzz=500pt filename & \\hfuzz=500pt platform info file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~equipmentType & \\hfuzz=500pt choice & \\hfuzz=500pt equipment type to loop over\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~all & \\hfuzz=500pt  & \\hfuzz=500pt loop over all types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gnssAntenna & \\hfuzz=500pt  & \\hfuzz=500pt loop over antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gnssReceiver & \\hfuzz=500pt  & \\hfuzz=500pt loop over receivers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~slrStation & \\hfuzz=500pt  & \\hfuzz=500pt loop over SLR stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~slrRetroReflector & \\hfuzz=500pt  & \\hfuzz=500pt loop over laser retroreflectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~satelliteIdentifier & \\hfuzz=500pt  & \\hfuzz=500pt loop over satellite identifiers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~other & \\hfuzz=500pt  & \\hfuzz=500pt loop over other types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopName & \\hfuzz=500pt string & \\hfuzz=500pt variable with name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopSerial & \\hfuzz=500pt string & \\hfuzz=500pt variable with serial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopInfo & \\hfuzz=500pt string & \\hfuzz=500pt variable with radome (antenna) or version (receiver)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTimeStart & \\hfuzz=500pt string & \\hfuzz=500pt variable with start time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTimeEnd & \\hfuzz=500pt string & \\hfuzz=500pt variable with end time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopPositionX & \\hfuzz=500pt string & \\hfuzz=500pt variable with position x\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopPositionY & \\hfuzz=500pt string & \\hfuzz=500pt variable with position y\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopPositionY & \\hfuzz=500pt string & \\hfuzz=500pt variable with position z\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Loop}\\label{loopType:loop}\nLoop over nested loops. First \\config{loop} is outermost loop, every subsequent \\config{loop} is one level below the previous \\config{loop}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~loop & \\hfuzz=500pt \\hyperref[loopType]{loop} & \\hfuzz=500pt subloop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SortAndRemoveDuplicates}\\label{loopType:sortAndRemoveDuplicates}\nPerform the \\configClass{loop}{loopType} in the alphabetically\norder defined by the evaluated \\config{sortString} for each loop step.\nSo the string must contain loop variables. If \\config{sortString}\nis empty, no sorting will take place.\n\nExample: The \\config{sortString}=\\verb|{loopTime:%m}| of a time series\nsorts the times in ascending order by month.\n\nThe same principle is used to remove duplicates. If different loop steps\nevaluates \\config{removeDuplicatesString} to the same string,\nonly the first loop step is executed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~loop & \\hfuzz=500pt \\hyperref[loopType]{loop} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sortString & \\hfuzz=500pt string & \\hfuzz=500pt use \\{loopVariables\\}, sort alphabetically\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~descending & \\hfuzz=500pt boolean & \\hfuzz=500pt sorting descending instead of ascending\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeDuplicatesString & \\hfuzz=500pt string & \\hfuzz=500pt use \\{loopVariables\\}, remove duplicates (order is preserved)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ManualTable}\nDEPRECATED since 2025-09-27. Use LoopStringTable instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~table & \\hfuzz=500pt choice & \\hfuzz=500pt define table by rows/columns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rowWise & \\hfuzz=500pt sequence & \\hfuzz=500pt define table by rows\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~row & \\hfuzz=500pt sequence & \\hfuzz=500pt define table by rows\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~cell & \\hfuzz=500pt string & \\hfuzz=500pt explicit list of cells in row/column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~columnWise & \\hfuzz=500pt sequence & \\hfuzz=500pt define table by columns\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~column & \\hfuzz=500pt sequence & \\hfuzz=500pt define table by columns\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~cell & \\hfuzz=500pt string & \\hfuzz=500pt explicit list of cells in row/column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~variableLoopString & \\hfuzz=500pt string & \\hfuzz=500pt 1. variable name for the 1. column, next variable name for the 2. column, ... \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FileGnssStationInfo}\nDEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGnssStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt station/transmitter info file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~infoType & \\hfuzz=500pt choice & \\hfuzz=500pt info to loop over\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~antenna & \\hfuzz=500pt  & \\hfuzz=500pt loop over antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~receiver & \\hfuzz=500pt  & \\hfuzz=500pt loop over receivers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopName & \\hfuzz=500pt string & \\hfuzz=500pt variable with antenna/receiver name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopSerial & \\hfuzz=500pt string & \\hfuzz=500pt variable with antenna/receiver serial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopInfo & \\hfuzz=500pt string & \\hfuzz=500pt variable with radome (antenna) or version (receiver)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTimeStart & \\hfuzz=500pt string & \\hfuzz=500pt variable with antenna/receiver start time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTimeEnd & \\hfuzz=500pt string & \\hfuzz=500pt variable with antenna/receiver end time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current iteration (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt check before each loop step\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Magnetosphere}\\label{magnetosphereType}\nThis class provides functions of the magnetic field of the Earth.\n\n\n\\subsection{IGRF}\nInternational Geomagnetic Reference Field.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileMagneticNorthPole & \\hfuzz=500pt filename & \\hfuzz=500pt time series of north pole\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{MatrixGenerator}\\label{matrixGeneratorType}\nThis class provides a matrix used e.g. by \\program{MatrixCalculate}.\nIf multiple matrices are given the resulting matrix is the sum all\nand the size is exandeded to fit all matrices. Before the computation of each submatrix\nthe variables \\verb|rowsBefore| and \\verb|columnsBefore| with current size of the overall matrix\nare set. As all matrices can be manipulated before, complex matrix operations are possible.\n\n\n\\subsection{File}\nMatrix from \\file{file}{matrix}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Normals file}\nMatrix from a \\file{normal equation file}{normalEquation}. The symmetric normal matrix,\nthe right hand side vector, the lPl vector, or the observation count $(1\\times1)$ can be selected.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~normalMatrix & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~lPl & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationCount & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Expression}\nMatrix filled by an expression. For each element of the new matrix the variables\n\\verb|row| and \\verb|column| are set and the expression \\config{element} is evaluated.\n\nExcample: The \\config{element}=\\verb|if(row==column,1,0)| generates an identity matrix.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rows & \\hfuzz=500pt expression & \\hfuzz=500pt (variables: rowsBefore, columnsBefore)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~columns & \\hfuzz=500pt expression & \\hfuzz=500pt (variables: rowsBefore, columnsBefore)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~element & \\hfuzz=500pt expression & \\hfuzz=500pt for each element of matrix (variables: row, column, rows, columns, rowsBefore, columnsBefore)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Element manipulation}\nThe elements of a matrix are replaced an expression.\nFor each element of the matrix the variables \\verb|data|, \\verb|row|, \\verb|column|\nare set and the expression \\config{element} is evaluated and replaces the element.\nAdditionally the standard data variables are available (assigned each row),\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~element & \\hfuzz=500pt expression & \\hfuzz=500pt for each element of matrix (variables: data, row, column, rows, columns, rowsBefore, columnsBefore)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ElementWiseOperation}\nGiven two matrices $\\mathbf{A}$ and $\\mathbf{B}$ this class computes $c_{ij} = f(a_{ij}, b_{ij})$,\nwhere $f$ is an expression (for example \\verb|data0*data1|).\nFor each element of the matrix the variables \\verb|data0|, \\verb|data1|, \\verb|row|, \\verb|column|\nare set and the expression \\config{element} is evaluated.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix1 & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix2 & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~expression & \\hfuzz=500pt expression & \\hfuzz=500pt for each element of matrix (variables: data0, data1, row, column, rows, columns, rowsBefore, columnsBefore)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Append}\nAppend matrix to the right (first row) or bottom (first column).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~side & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~right & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~bottom & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~diagonal & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Shift}\nShift start row and start column of a matrix.\nIn other words: zero lines and columns are inserted at the beginning of the matrix.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startRow & \\hfuzz=500pt expression & \\hfuzz=500pt start row (variables: rowsBefore, columnsBefore, rows, columns)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startColumn & \\hfuzz=500pt expression & \\hfuzz=500pt start column (variables: rowsBefore, columnsBefore, rows, columns)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Slice}\nSlice of a matrix.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startRow & \\hfuzz=500pt expression & \\hfuzz=500pt start row of matrix (variables: rowsBefore, columnsBefore, rows, columns)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startColumn & \\hfuzz=500pt expression & \\hfuzz=500pt start column of matrix (variables: rowsBefore, columnsBefore, rows, columns)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rows & \\hfuzz=500pt expression & \\hfuzz=500pt 0: until end (variables: rowsBefore, columnsBefore, rows, columns)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~columns & \\hfuzz=500pt expression & \\hfuzz=500pt 0: until end (variables: rowsBefore, columnsBefore, rows, columns)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Reshape}\nMatrix reshaped columnwise to new row and columns.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rows & \\hfuzz=500pt expression & \\hfuzz=500pt 0: auto-determine rows, (variables: rowsBefore, columnsBefore)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~columns & \\hfuzz=500pt expression & \\hfuzz=500pt 0: auto-determine columns (variables: rowsBefore, columnsBefore)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Reorder}\\label{matrixGeneratorType:reorder}\nReorder rows or columns of a matrix by an index vectors.\nThe index vector can be created with \\program{ParameterSelection2IndexVector}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileIndexVectorRow & \\hfuzz=500pt filename & \\hfuzz=500pt index in input matrix or -1 for new parameter.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileIndexVectorColumn & \\hfuzz=500pt filename & \\hfuzz=500pt index in input matrix or -1 for new parameter.\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Sort}\nSort matrix by \\config{column} in ascending order by default or in \\config{descending} order.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~column & \\hfuzz=500pt uint & \\hfuzz=500pt sort by column, top = highest priority\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~descending & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Transpose}\nTransposed of a matrix $\\M A^T$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Multiplication}\nMultiplication of matrices.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix1 & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix2 & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Inverse}\nInverse of a matrix $\\M A^{-1}$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~pseudoInverse & \\hfuzz=500pt boolean & \\hfuzz=500pt compute pseudo inverse instead of regular one\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Cholesky}\nUpper triangular natrix of the cholesky decomposition of a symmetric matrix $\\M A=\\M W^T\\M W$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RankKUpdate}\nSymmetric matrix from rank k update: $\\M A^T\\M A$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EigenValues}\nComputes the eigenvalues of a square matrix and gives a vector of eigenvalues for symmetric matrices\nor a matrix with 2 columns with real and imaginary parts in general case.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~eigenVectors & \\hfuzz=500pt boolean & \\hfuzz=500pt return eigen vectors instead of eigen values\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Diagonal}\nExtract the diagonal or subdiagnoal ($n\\times 1$ vector) of a matrix.\nThe zero \\config{diagonal} means the main diagonal, a positive value the superdiagonal,\nand a negative the subdiagonal.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~diagonal & \\hfuzz=500pt int & \\hfuzz=500pt zero: main diagonal, positive: superdiagonal, negative: subdiagonal\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FromDiagonal}\nGenerate a matrix from a diagonal vector.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt (nx1) or (1xn) diagonal vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~diagonal & \\hfuzz=500pt int & \\hfuzz=500pt zero: main diagonal, positive: superdiagonal, negative: subdiagonal\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Set type}\nSet type (matrix, matrixSymmetricUpper, matrixSymmetricLower, matrixTriangularUpper, matrixTriangularLower)\nof a matrix. If the type is not matrix, the matrix must be quadratic. Symmetric matrices are filled symmetric\nand for triangular matrix the other triangle is set to zero.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~matrix & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~matrixSymmetricUpper & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~matrixSymmetricLower & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~matrixTriangularUpper & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~matrixTriangularLower & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{MiscAccelerations}\\label{miscAccelerationsType}\nThis class gives the non conservative forces acting on satellites.\n\n\n\\subsection{Relativistic effect}\\label{miscAccelerationsType:relativisticEffect}\nThe relativistic effect to the acceleration of an artificial Earth satellite\naccording to IERS2010 conventions.\n\nThe macro model and the attitude of the satellite is not needed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~beta & \\hfuzz=500pt double & \\hfuzz=500pt PPN (parameterized post-Newtonian) parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gamma & \\hfuzz=500pt double & \\hfuzz=500pt PPN (parameterized post-Newtonian) parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~J & \\hfuzz=500pt double & \\hfuzz=500pt Earth’s angular momentum per unit mass [m**2/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RadiationPressure}\\label{miscAccelerationsType:RadiationPressure}\nThis class computes acceleration acting on a satellite caused by Solar and Earth radiation pressure\nand thermal radiation.\n\nSolar radiation pressure: The solar constant at 1~AU can be set via \\config{solarFlux}.\nThe \\config{factorSolarRadation} can be used to scale the computed acceleration of the direct solar radiation.\n\nEarth radiation pressure:\nInput are a time series of gridded albedo values (unitless) as \\configFile{inputfileAlbedoTimeSeries}{griddedDataTimeSeries}\nand a time series of gridded longwave flux (W/m$^2$) as \\configFile{inputfileLongwaveFluxTimeSeries}{griddedDataTimeSeries}.\nBoth files are optional and if not specified, the respective effect on the acceleration is not computed.\nThe \\config{factorEarthRadation} can be used to scale the computed acceleration of the earth radiation.\n\nThe thermal radiation (TRP) of the satellite itself is either computed as direct re-emission or\nbased on the actual temperature of the satellite surfaces, depending on the setings of the\n\\file{satellite macro model}{satelliteModel}. The second one uses a transient temperature model\nwith a temporal differential equation which disallows parallel computing.\nThe \\config{factorThermalRadiation} can be used to scale the computed acceleration of the TRP.\n\nThe algorithms are described in:\n\nWoeske et. al. (2019), GRACE accelerometer calibration by high precision non-gravitational force modeling,\nAdvances in Space Research, \\url{https://doi.org/10.1016/j.asr.2018.10.025}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~solarflux & \\hfuzz=500pt double & \\hfuzz=500pt solar flux constant in 1 AU [W/m\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAlbedoTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt GriddedDataTimeSeries of albedo values (unitless)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileLongwaveFluxTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt GriddedDataTimeSeries of longwave flux values [W/m\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factorSolarRadation & \\hfuzz=500pt double & \\hfuzz=500pt Solar radiation pressure is multiplied by this factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factorEarthRadation & \\hfuzz=500pt double & \\hfuzz=500pt Earth radiation preussure is multiplied by this factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factorThermalRadiation & \\hfuzz=500pt double & \\hfuzz=500pt Thermal (re-)radiation is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{AtmosphericDrag}\\label{miscAccelerationsType:atmosphericDrag}\nAtmospheric drag model.\nAlgorithm for the atmospheric drag modelling is based on the free molecule flow\ntheory by Sentman 1961. An analytical expression of this treatise is given in\nMoe and Moe 2005.\n\nSentman L. (1961), Free molecule flow theory and its application to the determination\nof aerodynamic forces, Technical report.\n\nMoe K., Moe M. M. (2005), Gas-surface interactions and satellite drag coefficients,\nPlanetary and Space Science 53(8), 793-801, doi:10.1016/j.pss.2005.03.005.\n\nOptional determination steps:\nTurn temperature on or off.\nIn the first case, the model mentioned above is applied, which estimates variable drag\nand lift coefficients - in the latter case a constant drag coefficient can be specified.\n\nTurn wind on/off:\nIt enables the usage of the Horizontal Wind Model 2014 to add additional thermospheric\nwinds in the calculation process.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~thermosphere & \\hfuzz=500pt \\hyperref[thermosphereType]{thermosphere} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerTemperature & \\hfuzz=500pt boolean & \\hfuzz=500pt compute drag and lift, otherwise simple drag coefficient is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerWind & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{AtmosphericDragFromDensityFile}\\label{miscAccelerationsType:atmosphericDragFromDensityFile}\nAtmospheric drag computed from thermospheric density along the orbit\n(\\configFile{inputfileDensity}{instrument}, MISCVALUE). The \\configClass{thermosphere}{thermosphereType}\nis used to to compute temperature and wind.\nFor further details see \\configClass{atmosphericDrag}{miscAccelerationsType:atmosphericDrag}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDensity & \\hfuzz=500pt filename & \\hfuzz=500pt density along orbit, MISCVALUE (kg/m\\textasciicircum{}3)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~thermosphere & \\hfuzz=500pt \\hyperref[thermosphereType]{thermosphere} & \\hfuzz=500pt used to compute temperature and wind\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerTemperature & \\hfuzz=500pt boolean & \\hfuzz=500pt compute drag and lift, otherwise simple drag coefficient is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerWind & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Antenna thrust}\\label{miscAccelerationsType:antennaThrust}\nThe thrust (acceleration) in the opposite direction the antenna is facing\nwhich is generated by satellite antenna broadcasts.\nThe thrust is defined in the satellite macro model.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{FromParametrization}\\label{miscAccelerationsType:fromParametrization}\nReads a solution vector from file \\configFile{inputfileSolution}{matrix}\nwhich may be computed by a least squares adjustment (e.g. by \\program{NormalsSolverVCE}).\nThe coefficients of the vector are interpreted from position \\config{indexStart}\n(counting from zero) with help of \\configClass{parametrization}{parametrizationAccelerationType}.\nIf the solution file contains solution of several right hand sides you can choose\none with number \\config{rightSide} (counting from zero).\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~indexStart & \\hfuzz=500pt uint & \\hfuzz=500pt position in the solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rightSide & \\hfuzz=500pt uint & \\hfuzz=500pt if solution contains several right hand sides, select one\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{miscAccelerationsType:group}\nGroups a set of \\configClass{miscAccelerations}{miscAccelerationsType} and has no further effect itself.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~miscAccelerations & \\hfuzz=500pt \\hyperref[miscAccelerationsType]{miscAccelerations} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SolarRadiationPressure}\\label{miscAccelerationsType:solarRadiationPressure}\nDEPRECATED since 2022-12-19. Use radiationPressure instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~solarflux & \\hfuzz=500pt double & \\hfuzz=500pt solar flux constant in 1 AU [W/m**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Albedo}\\label{miscAccelerationsType:albedo}\nDEPRECATED since 2022-12-19. Use radiationPressure instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileReflectivity & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileEmissivity & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~solarflux & \\hfuzz=500pt double & \\hfuzz=500pt solar flux constant in 1 AU [W/m**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{NoiseGenerator}\\label{noiseGeneratorType}\nThis class implements the generation of different types of noise.\nIt provides a generic interface that can be implemented by different\ntypes of generators. The characteristics of the generated noise\nis determined by the generators. See the appropriate documentation\nfor more information.\n\n\n\\subsection{White}\nThe noise is Gaussian with a standard deviation \\config{sigma}.\nThe noise is computed via a pseudo random sequence with a start value given\nby \\config{initRandom}. The same value always yields the same sequence.\nBe careful in \\reference{parallel}{general.parallelization} mode\nas all nodes generates the same pseudo random sequence.\nIf this value is set to zero a real random value is used as starting value.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt standard deviation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~initRandom & \\hfuzz=500pt uint & \\hfuzz=500pt start value for pseudo random sequence, 0: real random\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ExpressionPSD}\nThis generator creates noise defined by a one sided PSD.\nThe \\config{psd} is an expression controlled by the variable 'freq'.\nTo determine the frequency \\config{sampling} must be given.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt Basis noise\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~psd & \\hfuzz=500pt expression & \\hfuzz=500pt one sided PSD (variable: freq [Hz]) [unit\\textasciicircum{}2/Hz]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt to determine frequency [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Filter}\nGenerated noise \\configClass{noise}{noiseGeneratorType} is\nfiltered by a \\configClass{filter}{digitalFilterType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~filter & \\hfuzz=500pt \\hyperref[digitalFilterType]{digitalFilter} & \\hfuzz=500pt digital filter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt Basis noise\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~warmupEpochCount & \\hfuzz=500pt uint & \\hfuzz=500pt number of additional epochs at before start and after end\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~overSamplingFactor & \\hfuzz=500pt uint & \\hfuzz=500pt noise with multiple higher sampling -\\$>\\$ filter -\\$>\\$ decimate\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PowerLaw}\nThis generator creates noise that conforms to a power law relationship, where the power\nof the noise at a frequency is proportional to $1/f^\\alpha$, with a typically between -2 and 2.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt Basis noise\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~alpha & \\hfuzz=500pt double & \\hfuzz=500pt Exponent of the power law relationship 1/f\\textasciicircum{}alpha\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{NormalEquation}\\label{normalEquationType}\nThis class provides a system of normal equations.\nThis total system is the weighted sum of individual normals.\n\\begin{equation}\n \\M N_{total} =  \\sum_{k=1} \\frac{1}{\\sigma_k^2}\\M N_k\n \\qquad\\text{and}\\qquad\n\\M n_{total} = \\sum_{k=1} \\frac{1}{\\sigma_k^2} \\M n_k.\n\\end{equation}\nThe normals do not need to have the same dimension. The dimension\nof the total combined system is chosen to cover all individual systems.\nFor each normal a \\config{startIndex} is required which indicates\nthe position of the first unknown of the individual normal within the\ncombined parameter vector.\n\nThe $\\sigma_k$ of the relative weights are defined by \\config{aprioriSigma}\nin a first step. If an apriori solution \\configFile{inputfileApproxSolution}{matrix} is\ngiven or the normals are solved iteratively the weights are determined by means\nof variance compoment estimation (VCE), see \\program{NormalsSolverVCE}:\n\\begin{equation}\n\\sigma_k^2 =\n\\frac{\\M e_k^T\\M P\\M e_k}\n{n_k-\\frac{1}{\\sigma_k^2}\\text{trace}\\left(\\M N_k\\M N_{total}^{-1}\\right)},\n\\end{equation}\nwhere $n_k$ is the number of observations. The square sum of the residuals\nis calculated by\n\\begin{equation}\n\\M e_k^T\\M P\\M e_k = \\M x^T\\M N_k\\M x - 2\\M n_k^T\\M x + \\M l_k^T\\M P_k\\M l_k.\n\\end{equation}\nThe system of normal equations can be solved with several right hand sides at once. But\nonly one right hand side, which can be selected with the index \\config{rightHandSide}\n(counting from zero), can be used to compute the variance factors.\nThe combined normal $\\M N_{total}$ and the solution $\\M x$ are taken from the previous\niteration step. In case of \\configClass{DesignVCE}{normalEquationType:designVCE} the algorithm\nis a little bit different as described below.\n\n\n\\subsection{Design}\\label{normalEquationType:design}\nThis class acculumates normal equations from observation equations.\nThe class \\configClass{observation}{observationType} computes\nthe linearized and decorrelated equation system for each arc $i$:\n\\begin{equation}\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i.\n\\end{equation}\nThe arc depending parameters~$\\M y_i$ are eliminated and the system of normal\nequations is acculumated according to\n\\begin{equation}\n \\M N = \\sum_{i=1}^m \\M A_i^T  \\M A_i\n \\qquad\\text{and}\\qquad\n\\M n = \\sum_{i=1}^m \\M A_i^T \\M l_i.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt \\hyperref[observationType]{observation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~aprioriSigma & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt add this normals at index of total matrix (counting from 0)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt to accelerate computation\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DesignVCE}\\label{normalEquationType:designVCE}\nThis class acculumates normal equations from observation equations.\nThe class \\configClass{observation}{observationType} computes\nthe linearized and decorrelated equation system for each arc $i$:\n\\begin{equation}\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i.\n\\end{equation}\nThe arc depending parameters~$\\M y_i$ are eliminated and the system of normal\nequations is acculumated according to\n\\begin{equation}\n \\M N =  \\sum_{i=1} \\frac{1}{\\sigma_i^2}\\M A_i^T  \\M A_i\n \\qquad\\text{and}\\qquad\n\\M n = \\sum_{i=1} \\frac{1}{\\sigma_i^2} \\M A_i^T \\M l_i.\n\\end{equation}\nThe variance $\\sigma_i^2$ of each individual arc is determined by\n\\begin{equation}\n\\sigma_i^2 =\n\\frac{(\\M l_i-\\M A_i\\M x)^T(\\M l_i-\\M A_i\\M x)}\n{n_i-\\frac{1}{\\sigma_i^2}\\text{trace}\\left(\\M A_i^T  \\M A_i\\M N_{total}^{-1}\\right)},\n\\end{equation}\nwhere $n_i$ is the number of observations. If an apriori solution is not given at the first\niteration step a zero vector is assumed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt \\hyperref[observationType]{observation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt add this normals at index of total matrix (counting from 0)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt to accelerate computation\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{File}\\label{normalEquationType:file}\nReads a system of normal equations from file \\configFile{inputfileNormalEquation}{normalEquation}\nas generated by e.g. \\program{NormalsBuild}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~aprioriSigma & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt add this normals at index of total matrix (counting from 0)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Regularization}\\label{normalEquationType:regularization}\nSet up a system of normal equations\n\\begin{equation}\n\\M N = \\M R\n\\qquad\\text{and}\\qquad\n\\M n = \\M R \\M b,\n\\end{equation}\nwhere $\\M R$ is a diagonal matrix whose elements are given as a vector by\n\\configFile{inputfileDiagonalMatrix}{matrix} and $\\M b$ is the right hand side towards which will\nbe regularized. It can be given by \\configFile{inputfileBiasVector}{matrix}.\nThe diagonal matrix can be generated with \\program{NormalsRegularizationBorders},\n\\program{NormalsRegularizationSphericalHarmonics}, or \\program{MatrixCalculate}.\nIf $\\M R$ is not given a unit matrix is assumed.\nThe right hand side $\\M b$ may be generated with \\program{Gravityfield2SphericalHarmonicsVector}.\nIf $\\M b$ is not given a zero vector is assumed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileDiagonalMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt Vector with the diagonal elements of the weight matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileBias & \\hfuzz=500pt filename & \\hfuzz=500pt Matrix with right hand sides\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~aprioriSigma & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt regularization of parameters starts at this index (counting from 0)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RegularizationGeneralized}\n\nGeneralized regularization which is represented by the observation equation\n\\begin{equation}\n\\mathbf{x}_0 = \\mathbf{I} \\mathbf{x} + \\mathbf{v}, \\mathbf{v} \\sim \\mathcal{N}(0, \\sum_k \\sigma^2_k \\mathbf{V}_k).\n\\end{equation}\n\nThere are no requirements for partial covariance matrices $\\mathbf{V}_k$ except for them being symmetric.\nThe accumulated covariance matrix $\\sum_k \\sigma^2_k \\mathbf{V}_k$ must be positive definite however.\nThe variance components $\\sigma^2_k$ are estimated during the adjustment process and are assumed to be positive.\nAll \\configFile{inputfilePartialCovarianceMatrix}{matrix} must be of same size\nand must match the dimension of \\configFile{inputfileBiasMatrix}{matrix}\n(if provided, otherwise a zero vector of appropriate dimensions is created).\n\nThe parameter \\config{aprioriSigma} determines the initial variance factor for the partial covariance matrices. Either one $\\sigma_0$ can be\nsupplied or one for each $\\mathbf{V}_k$.\n\nThe regularization matrix can be applied to a subset of parameters by adjusting \\config{startIndex}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfilePartialCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt symmetric matrix (sum of all matrices must be positive definite)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileBiasMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt bias vector (default: zero vector)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~aprioriSigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori sigmas for initial iteration (default: 1.0)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt regularization of parameters starts at this index (counting from 0)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Observation}\\label{observationType}\nThis class sets up the observation equations in linearized Gauss-Markov model\n\\begin{equation}\\label{gmm}\n\\M l  = \\M A \\M x + \\M e\\qquad\\text{and}\\qquad\\mathcal{C}(\\M e) = \\sigma^2\\M P^{-1}.\n\\end{equation}\nThe observations are divided into short data blocks which can be computed independently\nand so easily can be parallelized. Usually these data blocks are short arcs of a\nsatellite's orbit. In most cases the unknown parameter vector contains coefficients\nof a gravity field parametrization given by \\configClass{parametrizationGravity}{parametrizationGravityType}.\nAdditional parameters like instrument calibration parameters are appended at the\nend of the vector~$\\M x$.\nIt is possible to give several observation vectors in one model.\n\nThe observations within each arc are decorrelated in the following way:\nIn a first step a Cholesky decomposition of the covariance matrix is performed\n\\begin{equation}\n\\M P^{-1} = \\M W^T\\M W,\n\\end{equation}\nwhere $\\M W$ is an upper regular triangular matrix.\nIn a second step the transformation\n\\begin{equation}\\label{dekorrelierung}\n\\bar{\\M A} = \\M W^{-T}\\M A\\qquad\\text{and}\\qquad \\bar{\\M l} = \\M W^{-T}\\M l\n\\end{equation}\ngives an estimation from decorrelated observations with equal variance\n\\begin{equation}\\label{normal.GMM}\n\\bar{\\M l} = \\bar{\\M A} \\M x + \\bar{\\M e}\n\\qquad\\text{and}\\qquad\n\\mathcal{C}(\\bar{\\M e})= \\sigma^2 \\M I.\n\\end{equation}\nUsually the arc dependent parameters are eliminated in the next step\nand not mentioned for the parameter names in the following.\n\n\n\\subsection{PodVariational}\\label{observationType:podVariational}\nThe observation equations for precise orbit data (POD) are formulated as variational equations.\nIt is based on \\file{inputfileVariational}{variationalEquation} calculated with \\program{PreprocessingVariationalEquation}.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree \\config{integrationDegree}.\n\nThe kinematic positions as pseudo observations are taken from\n\\config{rightHandSide} and should not be given equally spaced in time. The observation\nequations are interpolated to these times by a moving polynomial of degree \\config{interpolationDegree}.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\n\\config{accelerateComputation}: In the event that the sampling of the kinematic orbit is much higher than the sampling\nof the variational equations (e.g. 1 second vs. 5 seconds) the accumulation of the observation equations\ncan be accelerated by transforming the observation equations\n\\begin{equation}\n  \\M l = \\M J \\M A \\M x + \\M e,\n\\end{equation}\nwhere $\\M J$ describes the interpolation of the sampling of the variational design matrix~$\\M A$\nto the sampling of the observations $\\M l$ with more rows than columns. The QR decomposition\n\\begin{equation}\n  \\M J = \\begin{pmatrix} \\M Q_1 & \\M Q_2 \\end{pmatrix}\n         \\begin{pmatrix} \\M R \\\\ \\M 0 \\end{pmatrix}.\n\\end{equation}\ncan be used to transform the observation equations\n\\begin{equation}\n  \\begin{pmatrix} \\M Q_1^T \\M l \\\\ \\M Q_2^T \\M l \\end{pmatrix} =\n  \\begin{pmatrix} \\M Q_1^T \\M R \\\\ \\M 0 \\end{pmatrix} \\M A \\M x +\n  \\begin{pmatrix} \\M Q_1^T \\M e \\\\ \\M Q_2^T \\M e \\end{pmatrix}.\n\\end{equation}\nAs the zero lines should not be considered, the computational time for the accumulation is reduced.\nThis option is not meaningful for evaluating the residuals such as in \\program{PreprocessingPod}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:arc<no>.position0.x::|,\n\\item \\verb|<satellite>:arc<no>.position0.y::|,\n\\item \\verb|<satellite>:arc<no>.position0.z::|.\n\\item \\verb|<satellite>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~accelerateComputation & \\hfuzz=500pt boolean & \\hfuzz=500pt acceleration of computation by transforming the observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~covariancePod & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PodIntegral}\\label{observationType:podIntegral}\nThe observation equations for precise orbit data (POD) of short arcs are given by\n\\begin{equation}\n  {\\M r}_\\epsilon(\\tau) = {\\M r}_A(1-\\tau) + {\\M r}_B\\tau - T^2\\int_0^1 K(\\tau,\\tau')\n  \\left(\\M f_0(\\tau')+\\nabla V(\\tau')\\right)\\,d\\tau'\n\\end{equation}\nwith the integral kernel\n\\begin{equation}\n  K(\\tau,\\tau') = \\begin{cases} \\tau'(1-\\tau) & \\text{for }\\tau'\\le\\tau \\\\\n  \\tau(1-\\tau') & \\text{for }\\tau'>\\tau \\end{cases},\n\\end{equation}\nand the normalized time\n\\begin{equation}\n  \\tau = \\frac{t-t_A}{T}\\qquad\\text{with}\\qquad T=t_B-t_A.\n\\end{equation}\nThe kinematic positions~${\\M r}_\\epsilon(\\tau)$ as pseudo observations are taken from\n\\configClass{rightHandSide}{podRightSideType}. From these positions the influence of the reference forces $\\M f_0(\\tau)$\nis subtracted which are computed with the background models in \\configClass{rightHandSide}{podRightSideType}.\nThe integral is solved by the integration of a moving interpolation polynomial of degree \\config{integrationDegree}.\nThe boundary values ${\\M r}_A$ and ${\\M r}_B$ (satellite's state vector) are estimated per arc\nand are usually directly eliminated if \\config{keepSatelliteStates} is not set.\n\nThe unknown gravity field $\\nabla V(\\M r, t)$ parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis not evaluated at the observed positions but at the orbit given by \\configFile{inputfileOrbit}{instrument}.\nThe same is true for the reference forces. The linearized effect of the gravity field change by the position\nadjustment is taken into account by \\config{gradientfield}. This may be a low order field up to a\nspherical harmonics degree of $n=2$ or $n=3$.\n\nThe \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument}, and \\configFile{inputfileAccelerometer}{instrument}\nmust be synchronous and must be given with a constant sampling and without any gaps in each short arc\n(see \\program{InstrumentSynchronize}).\nThe kinematic positions~${\\M r}_\\epsilon(\\tau)$ should not given equally spaced in time\nbut must be divided into the same arcs as the other instrument data.\nThe observation equations are interpolated to this time by a polynomial interpolation\nwith degree \\config{interpolationDegree}.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\nFor \\config{accelerateComputation} see \\configClass{observation:podVariational}{observationType:podVariational}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|,\n\\end{itemize}\nand for each arc if \\config{keepSatelliteStates} is set\n\\begin{itemize}\n\\item \\verb|<satellite>:arc<no>.position.start.x::|,\n\\item \\verb|<satellite>:arc<no>.position.start.y::|,\n\\item \\verb|<satellite>:arc<no>.position.start.z::|.\n\\item \\verb|<satellite>:arc<no>.position.end.x::|,\n\\item \\verb|<satellite>:arc<no>.position.end.y::|,\n\\item \\verb|<satellite>:arc<no>.position.end.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[podRightSideType]{podRightSide} & \\hfuzz=500pt input for the reduced observation vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gradientfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt low order field to estimate the change of the gravity by position adjustement\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~keepSatelliteStates & \\hfuzz=500pt boolean & \\hfuzz=500pt set boundary values of each arc global\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~accelerateComputation & \\hfuzz=500pt boolean & \\hfuzz=500pt acceleration of computation by transforming the observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~covariancePod & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PodAcceleration}\\label{observationType:podAcceleration}\nThe observation equations for precise orbit data (POD) are given by\n\\begin{equation}\n\\ddot{\\M r}(t) - \\M g_0(t) = \\nabla V(\\M r, t),\n\\end{equation}\nwhere the accelerations of the satellite $\\ddot{\\M r}(t)$ are derived from the kinematic positions\nin \\configClass{rightHandSide}{podRightSideType}. The orbit differentation is performed by a moving\npolynomial interpolation or approximation with degree \\config{interpolationDegree}\nand number of used epochs \\config{numberOfEpochs}. The reference forces $\\M g_0(t)$ are computed\nwith the background models in \\configClass{rightHandSide}{podRightSideType}.\n\nAll instrument data \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument},\nand \\configFile{inputfileAccelerometer}{instrument} must be synchronous and be given\nwith a constant sampling without any gaps in each short arc (see \\program{InstrumentSynchronize}).\n\nThe unknown gravity field $\\nabla V(\\M r, t)$ parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis not evaluated at the observed positions but at the orbit given by \\configFile{inputfileOrbit}{instrument}.\nThe same is true for the reference forces. This orbit may be a more accurate dynamical orbit but\nin most cases the kinematic orbit provides good results.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[podRightSideType]{podRightSide} & \\hfuzz=500pt input for the reduced observation vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit differentation  by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~numberOfEpochs & \\hfuzz=500pt uint & \\hfuzz=500pt number of used Epochs for polynom computation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~covariancePod & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PodEnergy}\\label{observationType:podEnergy}\nThe observation equations for precise orbit data (POD) are given by\n\\begin{equation}\n  \\frac{1}{2}\\dot{\\M r}^2\n  -\\dot{\\M r} \\cdot (\\M\\Omega\\times\\M r)\n  +\\int_{t_0}^t(\\dot{\\M\\Omega}\\times\\M r)\\cdot \\dot{\\M r}\\,dt\n  - \\int_{t_0}^t \\M g_0 \\cdot\\dot{\\M r}'\\,dt\n  = V + E.\n\\end{equation}\nwhere the velocities of the satellite $\\dot{\\M r}(t)$ are derived from\nthe kinematic positions in \\configClass{rightHandSide}{podRightSideType} and the Earth's rotation vector~$\\M\\Omega(t)$ is modeled\nwithin \\configClass{earthRotation}{earthRotationType}. The orbit differentiation is\nperformed by a polynomial interpolation with degree \\config{interpolationDegree}.\nThe integrals are solved by a polynomial interpolation with degree \\config{integrationDegree}.\nThe reference forces $\\M g_0(t)$ are computed with the background models in \\configClass{rightHandSide}{podRightSideType}.\n\nAll instrument data \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument}, and \\configFile{inputfileAccelerometer}{instrument}\nmust be synchronous and be given with a constant sampling without any gaps in each short arc\n(see \\program{InstrumentSynchronize}).\n\nThe unknown gravity potential $V(\\M r)$ parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis not evaluated at the observed positions but at the orbit given by \\configFile{inputfileOrbit}{instrument}.\nThe same is true for the reference forces. This orbit may be a more accurate dynamical orbit but\nin most cases the kinematic orbit provides good results.\n\nAn unknown energy bias~$E$ per arc is parametrized by \\configClass{parametrizationBias}{parametrizationTemporalType}\nand should be a constant in theory but temporal changes might help to absorb other unmodelled effects.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[podRightSideType]{podRightSide} & \\hfuzz=500pt input for the reduced observation vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization (potential)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationBias & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt unknown total energy per arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit differentiation  by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~covariancePod & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SstVariational}\\label{observationType:sstVariational}\nLike \\configClass{observation:podVariational}{observationType:podVariational} (see there for details)\nbut with two satellites and additional satellite-to-satellite (SST) observations.\n\nIf multiple \\configFile{inputfileSatelliteTracking}{instrument} are given,\nall data are added together. So corrections in extra files like the light time correction\ncan easily be added. Empirical parameters for the SST observations can be set up with\n\\configClass{parametrizationSst}{parametrizationSatelliteTrackingType}.\nThe accuracy or the full covariance matrix of SST is provided in\n\\configClass{covarianceSst}{covarianceSstType}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite1>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.position0.x::|,\n\\item \\verb|<satellite1>:arc<no>.position0.y::|,\n\\item \\verb|<satellite1>:arc<no>.position0.z::|.\n\\item \\verb|<satellite1>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite2>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.position0.x::|,\n\\item \\verb|<satellite2>:arc<no>.position0.y::|,\n\\item \\verb|<satellite2>:arc<no>.position0.z::|.\n\\item \\verb|<satellite2>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking>:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite A as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite B as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational1 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational2 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst & \\hfuzz=500pt \\hyperref[covarianceSstType]{covarianceSst} & \\hfuzz=500pt covariance matrix of satellite to satellite tracking observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod1 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod2 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 2)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SstIntegral}\\label{observationType:sstIntegral}\nLike \\configClass{observation:podIntegral}{observationType:podIntegral} (see there for details)\nbut with two satellites and additional satellite-to-satellite (SST) observations.\n\nIf multiple \\configFile{inputfileSatelliteTracking}{instrument} are given\nall data are added together. So corrections in extra files like the light time correction\ncan easily be added. Empirical parameters for the SST observations can be set up with\n\\configClass{parametrizationSst}{parametrizationSatelliteTrackingType}.\nThe accuracy or the full covariance matrix of SST is provided in\n\\configClass{covarianceSst}{covarianceSstType}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite1>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking>:*:*|,\n\\end{itemize}\nand for each arc if \\config{keepSatelliteStates} is set\n\\begin{itemize}\n\\item \\verb|<satellite1>:arc<no>.position.start.x::|,\n\\item \\verb|<satellite1>:arc<no>.position.start.y::|,\n\\item \\verb|<satellite1>:arc<no>.position.start.z::|.\n\\item \\verb|<satellite1>:arc<no>.position.end.x::|,\n\\item \\verb|<satellite1>:arc<no>.position.end.y::|,\n\\item \\verb|<satellite1>:arc<no>.position.end.z::|.\n\\item \\verb|<satellite2>:arc<no>.position.start.x::|,\n\\item \\verb|<satellite2>:arc<no>.position.start.y::|,\n\\item \\verb|<satellite2>:arc<no>.position.start.z::|.\n\\item \\verb|<satellite2>:arc<no>.position.end.x::|,\n\\item \\verb|<satellite2>:arc<no>.position.end.y::|,\n\\item \\verb|<satellite2>:arc<no>.position.end.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel1 & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel2 & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[sstRightSideType]{sstRightSide} & \\hfuzz=500pt input for the reduced observation vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeAcceleration & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gradientfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt low order field to estimate the change of the gravity by position adjustement\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~keepSatelliteStates & \\hfuzz=500pt boolean & \\hfuzz=500pt set boundary values of each arc global\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst & \\hfuzz=500pt \\hyperref[covarianceSstType]{covarianceSst} & \\hfuzz=500pt covariance matrix of satellite to satellite tracking observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod1 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod2 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 2)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DualSstVariational}\\label{observationType:dualSstVariational}\nLike \\configClass{observation:sstVariational}{observationType:sstVariational} (see there for details)\nbut with two simultaneous satellite-to-satellite (SST) observations.\n\nThis class reads two SST observation files (\\configFile{inputfileSatelliteTracking1}{instrument} and\n\\configFile{inputfileSatelliteTracking2}{instrument}).\nEmpirical parameters for the SST observations can be set up independently for both SST observation\ntypes with \\configClass{parametrizationSst1}{parametrizationSatelliteTrackingType} and\n\\configClass{parametrizationSst2}{parametrizationSatelliteTrackingType}.\n\nBoth SST observation types are reduced by the same background models and the same impact\nof accelerometer measurements. The covariance matrix of the reduced observations should not consider\nthe instrument noise only (\\configClass{covarianceSst1/2}{covarianceSstType}) but must\ntake the cross correlations \\configClass{covarianceAcc}{covarianceSstType} into account.\nThe covariance matrix of the reduced observations is given by\n\\begin{equation}\n  \\M\\Sigma(\\begin{bmatrix} \\Delta l_{SST1} \\\\ \\Delta l_{SST2} \\end{bmatrix})\n  = \\begin{bmatrix} \\M\\Sigma_{SST1} + \\M\\Sigma_{ACC} & \\M\\Sigma_{ACC} \\\\\n                   \\M\\Sigma_{ACC} & \\M\\Sigma_{SST2} + \\M\\Sigma_{ACC}\n    \\end{bmatrix}.\n\\end{equation}\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite1>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.position0.x::|,\n\\item \\verb|<satellite1>:arc<no>.position0.y::|,\n\\item \\verb|<satellite1>:arc<no>.position0.z::|.\n\\item \\verb|<satellite1>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite2>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.position0.x::|,\n\\item \\verb|<satellite2>:arc<no>.position0.y::|,\n\\item \\verb|<satellite2>:arc<no>.position0.z::|.\n\\item \\verb|<satellite2>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking1>:*:*|.\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking2>:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking1 & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking2 & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite A as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite B as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational1 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational2 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst1 & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter for first ranging observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst2 & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter for second ranging observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst1 & \\hfuzz=500pt \\hyperref[covarianceSstType]{covarianceSst} & \\hfuzz=500pt covariance matrix of first satellite to satellite tracking observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst2 & \\hfuzz=500pt \\hyperref[covarianceSstType]{covarianceSst} & \\hfuzz=500pt covariance matrix of second satellite to satellite tracking observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~covarianceAcc & \\hfuzz=500pt \\hyperref[covarianceSstType]{covarianceSst} & \\hfuzz=500pt common covariance matrix of reduced satellite to satellite tracking observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod1 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod2 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 2)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Gradiometer}\\label{observationType:gradiometer}\nObservation equations for satellite gravity gradiometry (SGG)\n\\begin{equation}\n  \\nabla\\nabla V(\\M r) =\n  \\begin{pmatrix}\n    \\frac{\\partial^2 V}{\\partial x^2}         & \\frac{\\partial^2 V}{\\partial x\\partial y} & \\frac{\\partial^2 V}{\\partial x\\partial z} \\\\\n    \\frac{\\partial^2 V}{\\partial y\\partial x} & \\frac{\\partial^2 V}{\\partial y^2}         & \\frac{\\partial^2 V}{\\partial y\\partial z} \\\\\n    \\frac{\\partial^2 V}{\\partial z\\partial x} & \\frac{\\partial^2 V}{\\partial z\\partial y} & \\frac{\\partial^2 V}{\\partial z^2}\n  \\end{pmatrix}.\n\\end{equation}\nFrom the \\configFile{inputfileGradiometer}{instrument} observations precomputed \\configFile{inputfileReferenceGradiometer}{instrument}\ntogether with other background models are reduced, all given in \\configClass{rightHandSide}{sggRightSideType}.\n\nAll instrument data \\configFile{inputfileGradiometer}{instrument}, \\configFile{inputfileOrbit}{instrument},\nand \\configFile{inputfileStarCamera}{instrument} must be synchronous and be diveded\ninto each short arcs (see \\program{InstrumentSynchronize}).\n\nAdditional to the \\configClass{parametrizationGravity}{parametrizationGravityType}\nan (temporal changing) bias for each gradiometer component and arc can be estimated with\n\\configClass{parametrizationBias}{parametrizationTemporalType}.\n\nThe accuracy or the full covariance matrix of the gradiometer is provided in\n\\config{covarianceSgg} and can be estimated with \\program{PreprocessingGradiometer}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[sggRightSideType]{sggRightSide} & \\hfuzz=500pt input for the observation vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationBias & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt per arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useXX & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useYY & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useZZ & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useXY & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useXZ & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useYZ & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSgg & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt general variance factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt different accuaries for each arc (multplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function in time\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Terrestrial}\\label{observationType:terrestrial}\nThe gravity field is estimated from point wise measurements.\nThe gravity field parametrization is given by \\configClass{parametrizationGravity}{parametrizationGravityType}.\nThere is no need to have the data regular distributed or given on a sphere or ellipsoid.\nThe type of the gridded data (e.g gravity anomalies or geoid heights)\nmust be set with \\configClass{kernel}{kernelType}.\nA \\configClass{referencefield}{gravityfieldType} can be reduced beforehand.\n\nThe observations at given positions are calculated from\n\\configFile{inputfileGriddedData}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe observations can be divided into small blocks for parallelization.\nWith \\config{blockingSize} set the maximum count of observations in each block.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt expression & \\hfuzz=500pt [SI units]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt expression & \\hfuzz=500pt accuracy, 1/sigma used as weighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~referencefield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt type of observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt for reference field and parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~blockingSize & \\hfuzz=500pt uint & \\hfuzz=500pt segementation of the obervations if designmatrix can't be build at once\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Deflections}\\label{observationType:deflections}\nThe gravity field parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis estimated from deflections of the vertical measurements.\nA \\configClass{referencefield}{gravityfieldType} can be reduced beforehand.\n\nThe observations $\\xi$ in north direction and $\\eta$ in east direction\nat given positions are calculated from\n\\configFile{inputfileGriddedData}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe ellipsoid parameters \\config{R} and \\config{inverseFlattening} are used\nto define the local normal direction.\n\nThe observations can be divided into small blocks for parallelization.\nWith \\config{blockingSize} set the maximum count of observations in each block.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationXi & \\hfuzz=500pt expression & \\hfuzz=500pt North-South Deflections of the Vertical [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationEta & \\hfuzz=500pt expression & \\hfuzz=500pt East-West Deflections of the Vertical  [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigmaXi & \\hfuzz=500pt expression & \\hfuzz=500pt accuracy, 1/sigma used as weighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigmaEta & \\hfuzz=500pt expression & \\hfuzz=500pt accuracy, 1/sigma used as weighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~referencefield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt for reference field and parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoid, 0: sphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~blockingSize & \\hfuzz=500pt uint & \\hfuzz=500pt segementation of the obervations if designmatrix can't be build at once\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StationLoading}\\label{observationType:stationLoading}\nObservation equations for displacements of a list of stations\ndue to the effect of time variable loading masses. The displacement~$\\M u$ of a station is calculated according to\n\\begin{equation}\n\\M u(\\M r) = \\frac{1}{\\gamma}\\sum_{n=0}^\\infty \\left[\\frac{h_n}{1+k_n}V_n(\\M r)\\,\\M e_{up}\n+ R\\frac{l_n}{1+k_n}\\left(\n \\frac{\\partial V_n(\\M r)}{\\partial \\M e_{north}}\\M e_{north}\n+\\frac{\\partial V_n(\\M r)}{\\partial \\M e_{east}} \\M e_{east}\\right)\\right],\n\\end{equation}\nwhere $\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by\n\\configFile{inputfileDeformationLoadLoveNumber}{matrix} and the load Love numbers $k_n$ are given by\n\\configFile{inputfilePotentialLoadLoveNumber}{matrix}.\nThe $V_n$ are the spherical harmonics expansion of degree $n$ of the full time variable\ngravitational potential (potential of the loading mass + deformation potential)\nparametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}.\nAdditional parameters can be setup to estimate the realization of the reference frame\nof the station coordinates (\\config{estimateTranslation},\n\\config{estimateRotation}, and \\config{estimateScale}).\n\nThe observations at stations coordinates are calculated from\n\\configFile{inputfileGriddedData}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe ellipsoid parameters \\config{R} and \\config{inverseFlattening} are used\nto define the local frame (north, east, up).\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|*:translation.x:*:*|,\n\\item \\verb|*:translation.y:*:*|,\n\\item \\verb|*:translation.z:*:*|,\n\\item \\verb|*:scale:*:*|,\n\\item \\verb|*:rotation.x:*:*|,\n\\item \\verb|*:rotation.y:*:*|,\n\\item \\verb|*:rotation.z:*:*|.\n\\end{itemize}\n\nSee also \\program{Gravityfield2DisplacementTimeSeries}.\n\nReference:\nRietbroek (2014): Retrieval of Sea Level and Surface Loading Variations from Geodetic Observations\nand Model Simulations: an Integrated Approach, Bonn, 2014. - Dissertation,\n\\url{https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt station positions with displacement data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationNorth & \\hfuzz=500pt expression & \\hfuzz=500pt displacement [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationEast & \\hfuzz=500pt expression & \\hfuzz=500pt displacement [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationUp & \\hfuzz=500pt expression & \\hfuzz=500pt displacement [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigmaNorth & \\hfuzz=500pt expression & \\hfuzz=500pt accuracy, 1/sigma used as weighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigmaEast & \\hfuzz=500pt expression & \\hfuzz=500pt accuracy, 1/sigma used as weighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigmaUp & \\hfuzz=500pt expression & \\hfuzz=500pt accuracy, 1/sigma used as weighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inGlobalFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt obs/sigmas given in global x,y,z frame instead of north,east,up\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~referencefield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt for reference field and parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt of loading (+defo) potential\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateTranslation & \\hfuzz=500pt boolean & \\hfuzz=500pt coordinate center\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateScale & \\hfuzz=500pt boolean & \\hfuzz=500pt scale factor of position\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateRotation & \\hfuzz=500pt boolean & \\hfuzz=500pt rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDeformationLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfilePotentialLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt if full potential is given and not only loading potential\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoid, 0: sphere\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{OrbitPropagator}\\label{orbitPropagatorType}\nImplements the propagation of a satellite orbit under\nthe influence of \\configClass{forces}{forcesType} as\nused in \\program{SimulateOrbit}\n(dynamic orbits from numerical orbit integration).\n\n\n\\subsection{Euler}\nThis class implements Euler's method to propagate a satellite orbit under the influence of \\configClass{Forces}{forcesType}.\nSatellite is assumed to be oriented along-track.\n\n\n\\subsection{RungeKutta4}\nThis class implements the classical Runge-Kutta 4 method of orbit propagation\nfor satellite orbit under the influence of \\configClass{Forces}{forcesType}.\nNo step-width control or other advanced features are implemented.\nSatellite is assumed to be oriented along-track.\nSee: Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n\n\n\\subsection{AdamsBashforthMoulton}\nThis class implements the Adams-Moulton class of predictor-corrector orbit propagators\nfor a satellite orbit under the influence of \\configClass{Forces}{forcesType} using an implicit\nAdams-Bashforth corrector. The coefficients for the propagator are derived using the equations\ngiven in section 4.2.3 of [1]. Satellite is assumed to be oriented along-track.\n[1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt Order of the Adams-Bashforth type propagator.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~applyMoultonCorrector & \\hfuzz=500pt boolean & \\hfuzz=500pt Corrector step after Adams-Bashforth predcition.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~warmup & \\hfuzz=500pt \\hyperref[orbitPropagatorType]{orbitPropagator} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StoermerCowell}\nThis class implements the Stoermer-Cowell class of predictor-corrector orbit propagators for a satellite orbit\nunder the influence of \\configClass{Forces}{forcesType}. The coefficients for the Stoermer predictor and Cowell corrector\nare derived using the equations given in section 4.2.6 of [1]. Stoermer-Cowell is a double integration algorithm,\nyielding positions directly from accelertions. It does not produce velocities. The velocities are derived using\nAdams-type propagators as suggested in [2]. Satellite is assumed to be oriented along-track.\n[1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n[2] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt Order of the Stoermer-Cowell type propagator.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~warmup & \\hfuzz=500pt \\hyperref[orbitPropagatorType]{orbitPropagator} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{GaussJackson}\nThis class implements the Gauss-Jackson multi-step predictor-corrector method to\npropagate a satellite orbit under the influence of \\configClass{Forces}{forcesType}.\nSatellite is assumed to be oriented along-track. Implementation is based on [1].\n[1] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt of Gauss-Jackson method.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~warmup & \\hfuzz=500pt \\hyperref[orbitPropagatorType]{orbitPropagator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~correctorIterations & \\hfuzz=500pt uint & \\hfuzz=500pt Maximum number of iterations to run the corrector step for.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~epsilon & \\hfuzz=500pt double & \\hfuzz=500pt Convergence criteria for position, velocity, and acceleration tests.\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Polynomial}\\label{orbitPropagatorType:Polynomial}\nThis class implements an integration Polynomial method to propagate a satellite orbit under\nthe influence of \\configClass{Forces}{forcesType}. Satellite is assumed to be oriented along-track.\nImplementation is based on code by Torsten Mayer-Gürr.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~degree & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree to integrate accelerations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~shift & \\hfuzz=500pt int & \\hfuzz=500pt shift polynomial in future (predicted accelerations)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~epsilon & \\hfuzz=500pt double & \\hfuzz=500pt [m] max. position change to recompute forces\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~warmup & \\hfuzz=500pt \\hyperref[orbitPropagatorType]{orbitPropagator} & \\hfuzz=500pt to compute epochs before start epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~corrector & \\hfuzz=500pt boolean & \\hfuzz=500pt apply corrector iteration if position change is larger than epsilon\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{File}\nReads an orbit from file. If the needed epochs are not given an exception is thrown.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt epoch at timeStart is not used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] to find identical times\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~recomputeForces & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParameterNames}\\label{parameterNamesType}\nGenerates a list of parameter names. All parameters are appended.\n\n\n\\subsection{Name}\nThe parameter is given explicitly by four parts:\n\\begin{enumerate}\n\\item object: Object this parameter refers to, e.g. \\verb|graceA|, \\verb|G023|, \\verb|earth|, \\ldots\n\\item type: Type of this parameter, e.g. \\verb|accBias|, \\verb|position.x|, \\ldots\n\\item temporal: Temporal representation of this parameter, e.g. \\verb|trend|, \\verb|polynomial.degree1|, \\ldots\n\\item interval: Interval/epoch this parameter represents, e.g. \\verb|2017-01-01_00-00-00_2017-01-02_00-00-00|, \\verb|2018-01-01_00-00-00|.\n\\end{enumerate}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt object this parameter refers to, e.g. graceA, G023, earth\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~type & \\hfuzz=500pt string & \\hfuzz=500pt type of this parameter, e.g. accBias, position.x\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~temporal & \\hfuzz=500pt string & \\hfuzz=500pt temporal representation of this parameter, e.g. trend, polynomial.degree1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interval & \\hfuzz=500pt string & \\hfuzz=500pt interval/epoch this parameter refers to, e.g. 2017-01-01\\_00-00-00\\_2017-01-02\\_00-00-00, 2008-01-01\\_00-00-00\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{File}\nRead parameter names from \\file{file}{parameterName}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt file with parameter names\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Gravity}\nParameter names of gravity \\configClass{parametrization}{parametrizationGravityType}.\nAn additional \\config{object} name can be included in the parameter names.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt object these parameters refers to, e.g. earth\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Acceleration}\nParameter names of satellite acceleration \\configClass{parametrization}{parametrizationAccelerationType}.\nArc related parameters are appended if an \\configFile{inputfileInstrument}{instrument} is provided which\ndefines the arc structure.\nAn additional \\config{object} name can be included in the parameter names.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt object these parameters refers to, e.g. graceA, G023\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterization & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt defines the arc structure for arc related parameters\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SatelliteTracking}\nParameter names of satellite tracking \\configClass{parametrization}{parametrizationSatelliteTrackingType}.\nAn additional \\config{object} name can be included in the parameter names.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt object these parameters refers to, e.g. grace1.grace2\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterization & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Temporal}\nParameter names from temporal parametrization.\nIt is possible to setup the temporal parameters for each \\configClass{parameterNameBase}{parameterNamesType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameterNameBase & \\hfuzz=500pt \\hyperref[parameterNamesType]{parameterNames} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{GnssAntenna}\nParameter names of GNSS antenna center variation \\configClass{parametrization}{parametrizationGnssAntennaType}.\nAn additional \\config{object} name (antenna name) can be included in the parameter names.\nIt is possible to setup the parameters for each \\configClass{gnssType}{gnssType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt antenna name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[parametrizationGnssAntennaType]{parametrizationGnssAntenna} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gnssType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt e.g. C1CG**\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Observation}\nParameter names used in \\configClass{observation equations}{observationType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt \\hyperref[observationType]{observation} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Rename}\nReplaces parts of \\configClass{parameterName}{parameterNamesType}s.\nThe star \"\\verb|*|\" left this part untouched.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterName & \\hfuzz=500pt \\hyperref[parameterNamesType]{parameterNames} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched, object\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~type & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched, type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~temporal & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched, temporal representation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interval & \\hfuzz=500pt string & \\hfuzz=500pt *: left this part untouched, interval/epoch\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Selection}\nSelect a subset of \\configClass{parameterName}{parameterNamesType}s\nusing \\configClass{parameterSelection}{parameterSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterName & \\hfuzz=500pt \\hyperref[parameterNamesType]{parameterNames} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WithoutDuplicates}\nRemoves all duplicate names (keep first) from \\configClass{parameterName}{parameterNamesType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterName & \\hfuzz=500pt \\hyperref[parameterNamesType]{parameterNames} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParameterSelector}\\label{parameterSelectorType}\nThis class provides an index vector from selected parameters,\nwhich can be used e.g. to reorder a normal equation matrix.\nThe size of the index vector determines the size of the new matrix.\nEntries are the indices of the selected parameters in the provided\nparameter list or NULLINDEX for zero/new parameters.\n\n\n\\subsection{Wildcard}\\label{parameterSelectorType:wildcard}\nParameter index vector from name. Name matching supports wildcards * for any number of characters and ? for exactly one character.\nDoes not add zero/empty parameters if there are no matches.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~object & \\hfuzz=500pt string & \\hfuzz=500pt object this parameter refers to, e.g. graceA, G023, earth (wildcards: * and ?)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~type & \\hfuzz=500pt string & \\hfuzz=500pt type of this parameter, e.g. accBias, position.x (wildcards: * and ?)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~temporal & \\hfuzz=500pt string & \\hfuzz=500pt temporal representation of this parameter, e.g. trend, polynomial.degree1 (wildcards: * and ?)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interval & \\hfuzz=500pt string & \\hfuzz=500pt interval/epoch this parameter refers to, e.g. 2017-01-01\\_00-00-00\\_2017-01-02\\_00-00-00, 2008-01-01\\_00-00-00 (wildcards: * and ?)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Names}\nParameter index vector from list of parameter names.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterName & \\hfuzz=500pt \\hyperref[parameterNamesType]{parameterNames} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Range}\nParameter index vector from range.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~start & \\hfuzz=500pt expression & \\hfuzz=500pt start at this index (variables: length)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~count & \\hfuzz=500pt expression & \\hfuzz=500pt count of parameters, default: all parameters to the end (variables: length)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Matrix}\nParameter index vector from matrix.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt index in old parameter list or -1 for new parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~column & \\hfuzz=500pt expression & \\hfuzz=500pt use this column (counting from 0, variables: columns)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startRow & \\hfuzz=500pt expression & \\hfuzz=500pt start at this row (counting from 0, variables: rows)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countRows & \\hfuzz=500pt expression & \\hfuzz=500pt use these many rows (default: use all, variables: rows)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Zeros}\nExpand parameter index vector by adding zero parameters.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~count & \\hfuzz=500pt expression & \\hfuzz=500pt count of zero parameters (variables: length)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{parameterSelectorType:group}\nGroups a set of \\configClass{parameterSelection}{parameterSelectorType}s and has no further effect itself.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Complement}\\label{parameterSelectorType:complement}\nParameter index vector from a complement of other parameter selector(s).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParametrizationAcceleration}\\label{parametrizationAccelerationType}\nThis class defines parameters of satellite accelerations.\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n\n\n\\subsection{PerRevolution}\\label{parametrizationAccelerationType:perRevolution}\nOscillation once, twice, ... per revolution in Satellite Reference Frame (SRF)\nwith the argument of latitude as input angle.  If the attitude of the satellite\nis not provided the Celestial Reference Frame (CRF) is used instead.\nParamters are estimated in $[nm/s^2=10^{-9}\\,m/s^2]$.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:perRevolution.cos(<order>*u).x::<interval>|,\n\\item \\verb|*:perRevolution.cos(<order>*u).y::<interval>|,\n\\item \\verb|*:perRevolution.cos(<order>*u).z::<interval>|,\n\\item \\verb|*:perRevolution.sin(<order>*u).x::<interval>|,\n\\item \\verb|*:perRevolution.sin(<order>*u).y::<interval>|,\n\\item \\verb|*:perRevolution.sin(<order>*u).z::<interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt once, twice, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateX & \\hfuzz=500pt boolean & \\hfuzz=500pt along\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateY & \\hfuzz=500pt boolean & \\hfuzz=500pt cross\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateZ & \\hfuzz=500pt boolean & \\hfuzz=500pt radial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~interval & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt setup new parameters each interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{AccBias}\\label{parametrizationAccelerationType:accBias}\nTemporal changing accelerometer bias per axis in $[m/s^2]$ in Satellite Reference Frame (SRF).\nIf the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:accBias.x:*:*|,\n\\item \\verb|*:accBias.y:*:*|,\n\\item \\verb|*:accBias.z:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateX & \\hfuzz=500pt boolean & \\hfuzz=500pt along\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateY & \\hfuzz=500pt boolean & \\hfuzz=500pt cross\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateZ & \\hfuzz=500pt boolean & \\hfuzz=500pt radial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{AccelerometerScaleFactors}\\label{parametrizationAccelerationType:accelerometerScaleFactors}\nAccelerometer scale factor per axis.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:accScale.x:<temporal>:<interval>|,\n\\item \\verb|*:accScale.y:<temporal>:<interval>|,\n\\item \\verb|*:accScale.z:<temporal>:<interval>|,\n\\item \\verb|*:accScaleCross.xy:<temporal>:<interval>|,\n\\item \\verb|*:accScaleCross.xz:<temporal>:<interval>|,\n\\item \\verb|*:accScaleCross.yz:<temporal>:<interval>|,\n\\item \\verb|*:accScaleRotation.xy:<temporal>:<interval>|,\n\\item \\verb|*:accScaleRotation.xz:<temporal>:<interval>|,\n\\item \\verb|*:accScaleRotation.yz:<temporal>:<interval>|.\n\\end{itemize}\n\nThis parametrization needs the attitude of the satellite.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateX & \\hfuzz=500pt boolean & \\hfuzz=500pt along\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateY & \\hfuzz=500pt boolean & \\hfuzz=500pt cross\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateZ & \\hfuzz=500pt boolean & \\hfuzz=500pt radial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateCrossTalk & \\hfuzz=500pt boolean & \\hfuzz=500pt non-orthognality of axes\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateRotation & \\hfuzz=500pt boolean & \\hfuzz=500pt misalignment\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{GnssSolarRadiation}\\label{parametrizationAccelerationType:gnssSolarRadiation}\nGNSS solar radiation pressure model. Paramters are estimated in $[nm/s^2=10^{-9}\\,m/s^2]$.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:solarRadiationPressure.ECOM.D0:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DC2:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DS2:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DC4:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DS4:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.Y0:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.B0:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BC1:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BS1:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BC3:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BS3:*:*|.\n\\end{itemize}\n\nThis parametrization needs the attitude of the satellite.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateD0 & \\hfuzz=500pt boolean & \\hfuzz=500pt constant term along D-axis (sat-sun vector)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateD2 & \\hfuzz=500pt boolean & \\hfuzz=500pt 2-per-rev terms along D-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateD4 & \\hfuzz=500pt boolean & \\hfuzz=500pt 4-per-rev terms along D-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateY0 & \\hfuzz=500pt boolean & \\hfuzz=500pt constant term along Y-axis (solar panel axis)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateB0 & \\hfuzz=500pt boolean & \\hfuzz=500pt constant term along B-axis (cross product D x Y)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateB1 & \\hfuzz=500pt boolean & \\hfuzz=500pt 1-per-rev terms along B-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateB3 & \\hfuzz=500pt boolean & \\hfuzz=500pt 3-per-rev terms along B-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ThermosphericDensity}\\label{parametrizationAccelerationType:thermosphericDensity}\nEstimate the thermospheric density along the orbit using a satllite macro model.\nAn optional thermospheric model can be used to compute temperature and wind.\nThe temperature is used to estimate variable drag and lift coefficients, otherwise a constant drag coefficient is used.\nThe density is estimated in $[kg/m^3]$.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:density:<temporal>:<interval>|.\n\nThis parametrization needs the macro model and the attitude of the satellite.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~thermosphere & \\hfuzz=500pt \\hyperref[thermosphereType]{thermosphere} & \\hfuzz=500pt for wind and temperature\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerTemperature & \\hfuzz=500pt boolean & \\hfuzz=500pt compute drag and lift, otherwise simple drag coefficient is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerWind & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporalDensity & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt parameters along orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ModelScale}\\label{parametrizationAccelerationType:modelScale}\nEstimate a scale factor for a given model.\nThe \\file{parameter names}{parameterName} are \\verb|*:modelScale:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~miscAccelerations & \\hfuzz=500pt \\hyperref[miscAccelerationsType]{miscAccelerations} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParametrizationGnssAntenna}\\label{parametrizationGnssAntennaType}\nParametrization of antenna center variations. It will be used to set up the design matrix in a least squares adjustment.\nUsually the parametrization is setup separately for different \\configClass{gnssType}{gnssType}.\n\nIf multiple parametrizations are given the parameters are sequently appended in the design matrix and parameter vector.\n\n\n\\subsection{Center}\\label{parametrizationGnssAntennaType:center}\nAntenna center or, if setup for a specific \\configClass{gnssType}{gnssType},\nphase/code center offset (e.g. \\verb|*1*G| for GPS L1 phase center offset) in $[m]$.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:antennaCenter.x:*:*|,\n\\item \\verb|*:antennaCenter.y:*:*|,\n\\item \\verb|*:antennaCenter.z:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateX & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateY & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateZ & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SphericalHarmonics}\nParametrization of antenna center variations in $[m]$ in terms of spherical harmonics.\nAs usually only data above the horizon are observed only the even spherical harmonics\n(degree/order $m+n$ even), which are symmetric to the equator, are setup.\n\nThe total count of parameters is $((n_{max}+1)(n_{max}+2)-n_{min}(n_{min}+1)/2$ and\nthe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:antennaCenterVariations.sphericalHarmonics.c_<degree>_<order>:*:*|,\n\\item \\verb|*:antennaCenterVariations.sphericalHarmonics.s_<degree>_<order>:*:*|.\n\\end{itemize}\n\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt min degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt max degree\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RadialBasis}\nParametrization of antenna center variations with radial basis functions\n\\begin{equation}\n  ACV(\\M x(A, E)) = \\sum_i a_i \\Phi(\\M x\\cdot\\M x_i)\n\\end{equation}\nwhere $a_i$ in $[m]$ the coefficients which has to be estimated and $\\Phi$ are the basis\nfunctions\n\\begin{equation}\n  \\Phi(\\cos\\psi) = \\sum_n \\sqrt{2n+1}P_n(\\cos\\psi).\n\\end{equation}\n\nThe \\file{parameter names}{parameterName} are\n\\verb|*:antennaCenterVariations.radialBasis.<index>.<total count>:*:*|.\n\n\\fig{!hb}{0.4}{parametrizationGnssAntennaRadialBasis}{fig:parametrizationGnssAntennaRadialBasis}{Nodal points of the basis functions\nusing a Reuter grid for transmitting satellites (view angle of 18 deg). The red line indicates the view angle of 14 deg of ground stations.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt nodal points of shannon kernels\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt min degree of shannon kernel\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt max degree of shannon kernel\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParametrizationGravity}\\label{parametrizationGravityType}\nThis class gives a parametrization of the time depending gravity field.\nTogether with the class \\configClass{oberservation}{observationType} it will be used\nto set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n\n\n\\subsection{SphericalHarmonics}\\label{parametrizationGravityType:sphericalHarmonics}\nThe potential~$V$ is parametrized by a expansion of (fully normalized) spherical harmonics\n\\begin{equation}\nV(\\lambda,\\vartheta,r) = \\frac{GM}{R}\\sum_{n=0}^\\infty \\sum_{m=0}^n \\left(\\frac{R}{r}\\right)^{n+1}\n  \\left(c_{nm} C_{nm}(\\lambda,\\vartheta) + s_{nm} S_{nm}(\\lambda,\\vartheta)\\right).\n\\end{equation}\nYou can set the range of degree~$n$ with \\config{minDegree} and \\config{maxDegree}.\nThe sorting sequence of the potential coefficients in the parameter vector can be defined by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}.\n\nThe total count of parameters is $(n_{max}+1)^2-n_{min}^2$ and\nthe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:sphericalHarmonics.c_<degree>_<order>:*:*|,\n\\item \\verb|*:sphericalHarmonics.s_<degree>_<order>:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RadialBasis}\\label{parametrizationGravityType:radialBasis}\nThe potential~$V$ is represented by a sum of space localizing basis functions\n\\begin{equation}\n  V(\\M x) = \\sum_i a_i \\Phi(\\M x, \\M x_i)\n\\end{equation}\nwhere $a_i$ the coefficients which has to be estimated and $\\Phi$ are the basis\nfunctions given by isotropic radial \\configClass{kernel}{kernelType} functions\n\\begin{equation}\n  \\Phi(\\cos\\psi,r,R) = \\sum_n \\left(\\frac{R}{r}\\right)^{n+1} k_n\\sqrt{2n+1}\\bar{P}_n(\\cos\\psi).\n\\end{equation}\nThe basis functions are located on a grid~$\\M x_i$ given by \\configClass{grid}{gridType}.\nThis class can also be used to estimate point masses if \\configClass{kernel}{kernelType} is set to density.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:radialBasis.<index>.<total count>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt shape of the radial basis function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt nodal point distribution\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Temporal}\nThe time variable potential is given by\n\\begin{equation}\n  V(\\M x,t) = \\sum_i V_i(\\M x)\\Psi_i(t),\n\\end{equation}\nwehre $V_i(\\M x)$ is the spatial parametrization of the gravity field\nand can be choosen with \\configClass{parametrizationGravity}{parametrizationGravityType}.\nThe parametrization in time domain $\\Psi_i(t)$ is selected by\n\\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nThe total parameter count is the parameter count of \\configClass{parametrizationTemporal}{parametrizationTemporalType}\ntimes the parameter count of \\configClass{parametrizationGravity}{parametrizationGravityType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{LinearTransformation}\nParametrization of the gravity field on the basis of a linear transformation of a source parametrization.\nThe linear transformation changes the original solution space represented by\n\\configClass{pararametrizationGravitySource}{parametrizationGravityType} from\n\\begin{equation}\n  \\mathbf{l} = \\mathbf{A}\\mathbf{x} + \\mathbf{e}\n\\end{equation}\nto\n\\begin{equation}\n  \\mathbf{l} = \\mathbf{A}\\mathbf{F}\\mathbf{y} + \\mathbf{e}\n\\end{equation}\nthrough the linear transformation $\\mathbf{x}=\\mathbf{F}\\mathbf{y}$.\nIt follows that the rows of the matrix $\\mathbf{F}$ in \\file{inputfileTransformationMatrix}{matrix} coincides with\nthe number of parameters in \\configClass{pararametrizationGravitySource}{parametrizationGravityType}.\nThe new parameter count is given by the number of columns in $\\mathbf{F}$ and may be smaller, equal or larger\nthan the original parameter count.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:transformedParameter.<index>.<total count>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationGravitySource & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransformationMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt transformation matrix from target to source parametrization (rows of this matrix must coincide with the parameter count of the source parametrization)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EarthquakeOscillation}\nThis class is used to estimate the earthquake oscillation function parameters,\ni.e. $C_{nlm}$, $\\omega_{nlm}$, and $P_{nlm}$.\nThe results describes the variation in the gravitational potential field caused by large earthquakes.\n\\begin{equation}\nC_{lm}(\\M t) = \\sum_{n=0}^NC_{nlm}(1-\\cos(\\omega_{nlm}d\\M t)\\exp(P_{nlm}\\omega_{nlm}d\\M t)),\n\\end{equation}\nwith $\\omega_{nlm}=\\frac{2\\pi}{T_{nlm}}$ and $P_{nlm}=\\frac{-1}{2Q_{nlm}}$ . In this equation, $Q_{nlm}$ is the attenuation factor,\n$n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time after earthquake in second.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:earthquakeParameter.c_<degree>_<order>_A:*:*|,\n\\item \\verb|*:earthquakeParameter.s_<degree>_<order>_A:*:*|,\n\\item \\verb|*:earthquakeParameter.c_<degree>_<order>_W:*:*|,\n\\item \\verb|*:earthquakeParameter.s_<degree>_<order>_W:*:*|,\n\\item \\verb|*:earthquakeParameter.c_<degree>_<order>_P:*:*|,\n\\item \\verb|*:earthquakeParameter.s_<degree>_<order>_P:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputInitialCoefficient & \\hfuzz=500pt filename & \\hfuzz=500pt initial values for oscillation parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time0 & \\hfuzz=500pt time & \\hfuzz=500pt the time earthquake happened\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParametrizationSatelliteTracking}\\label{parametrizationSatelliteTrackingType}\nThis class defines parameters of Satellite-to-Satellite tracking observations.\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n\n\n\\subsection{AntennaCenter}\\label{parametrizationSatelliteTrackingType:antennaCenter}\nEstimate the KBR antenna phase centre (APC) coordinates in $[m]$ for each spacecraft in satellite reference frame (SRF)\nas constant per axis. The observation equations are computed by taking the derivative\nof the antenna offset correction equation w.r.t. the KBR APC coordinates.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|satellite1.satellite2:sstAntennaCenter1.x:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter1.y:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter1.z:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter2.x:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter2.y:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter2.z:*:*|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimate1X & \\hfuzz=500pt boolean & \\hfuzz=500pt along (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimate1Y & \\hfuzz=500pt boolean & \\hfuzz=500pt cross (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimate1Z & \\hfuzz=500pt boolean & \\hfuzz=500pt nadir (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimate2X & \\hfuzz=500pt boolean & \\hfuzz=500pt along (satellite 2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimate2Y & \\hfuzz=500pt boolean & \\hfuzz=500pt cross (satellite 2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimate2Z & \\hfuzz=500pt boolean & \\hfuzz=500pt nadir (satellite 2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt differentiation by polynomial approximation of degree n\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Bias}\\label{parametrizationSatelliteTrackingType:bias}\nEstimate bias for SST observations in $[m]$ or $[m/s$]. The temporal variation is defined by\n\\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:sstBias:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Scale}\\label{parametrizationSatelliteTrackingType:scale}\nEstimate scale factor for SST observations with respect to reference SST data\n\\configFile{inputfileSatelliteTracking}{instrument}.\nThe temporal variation is defined by \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:sstScale:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TimeBias}\\label{parametrizationSatelliteTrackingType:timeBias}\nEstimate time shift in seconds in SST observations, with defined temporal variation\nby \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nThe design matrix is computed by taking the derivative of the ranging data w.r.t. time.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:sstTimeBias:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ScaleModel}\\label{parametrizationSatelliteTrackingType:scaleModel}\nEstimate scale factors for deterministic signal models from satellite tracking instrument file \\configFile{inputfileSatelliteTracking}{instrument}, see \\program{EnsembleAveragingScaleModel}.\nAmplitude variation of model waveforms is defined by \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:scaleModel:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perArc & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SpecialEffect}\\label{parametrizationSatelliteTrackingType:specialEffect}\nEstimate deterministic signals in the GRACE K-Band measurements caused by Sun intrusions\ninto the star camera baffles of GRACE-A and eclipse transits of the satellites.\nThese events can be time-indexed beforehand using satellite position and orientation,\nsee \\program{GraceSstSpecialEvents}. The shape of this short-period waveform is nearly\nconstant within one month and can be approximated by a polynomial.\nThe amplitude variation of the waveform can also be taken into account\nby \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:<type>.legendrePolynomial.n<degree>:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileEvents & \\hfuzz=500pt filename & \\hfuzz=500pt instrument with GRACE events\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~eclipse1 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~eclipse2 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~starCameraBox1 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~starCameraBox2 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~starCameraBox3 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~starCameraBox4 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~starCameraBox5 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~starCameraBox6 & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~marginLeft & \\hfuzz=500pt double & \\hfuzz=500pt margin size (on both sides) [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~marginRight & \\hfuzz=500pt double & \\hfuzz=500pt margin size (on both sides) [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minNumberOfEvents & \\hfuzz=500pt uint & \\hfuzz=500pt min. number of events to setup parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{ParametrizationTemporal}\\label{parametrizationTemporalType}\nThis class gives a parametrization of time depending parameters (gravity field, positions, ...).\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n\nUseally time intervals are defined half open meaning the last time belongs not to the interval.\nThis behaviour can be changed for the last interval with \\config{includeLastTime}.\n\n\n\\subsection{Constant}\\label{parametrizationTemporalType:constant}\nRepresents a parameter being constant in time in each \\config{interval}.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:*:*:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~interval & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~includeLastTime & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Trend}\\label{parametrizationTemporalType:trend}\nA time variable function is given by a linear trend\n\\begin{equation}\nf(x,t) = \\frac{1}{T}(t-t_0) \\cdot f_t(x),\n\\end{equation}\nwith $t_0$ is \\config{timeStart} and $T$ is \\config{timeStep} in days.\nA constant term is not included and must added separately.\n\nThe \\file{parameter name}{parameterName} is \\verb|*:*:trend.<timeStep(days)>*(t-<timeStart>):*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt reference time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStep & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Splines}\\label{parametrizationTemporalType:splines}\nA time variable function is given by\n\\begin{equation}\nf(x,t) =  \\sum_i f_i(x)\\Psi_i(t),\n\\end{equation}\nwith the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions~$\\Psi_i(t)$.\nBasis splines are defined as polynomials of degree~$n$ in intervals between nodal points in time $t_i$,\nfor details see~\\reference{basis splines}{fundamentals.basisSplines}.\n\nThe parameters are ordered timewise. First all parameters of $f_{i=1}(x)$ then\n$f_{i=2}(x)$ and so on. The total parameter count in each \\config{interval} is $N=N_t+n-1$,\nwhere $N_t$ is the count of time points from \\configClass{timeSeries}{timeSeriesType} in each interval and $n$\nis the \\config{degree}.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:*:spline.n<degree>:<interval of each spline>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~degree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of splines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt nodal points in time domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~intervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~includeLastTime & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Polynomial}\nA time variable function is represented by Legendre polynomials in each \\config{interval}.\nThe time is normed to $[-1,1)$ in each interval.\n\nThe total parameter count is $(N+1)M$,\nwhere $N$ is the polynmial degree and $M$ the number of intervals with\nthe \\file{parameter names}{parameterName} \\verb|*:*:legendrePolynomial.n<degree>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~interval & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt intervals of polynomials\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~includeLastTime & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Oscillation}\nA time variable function is given by a oscillation\n\\begin{equation}\nf(x,t) = f^c(\\M x)\\cos(\\omega_i(t)) + f^s(\\M x)\\sin(\\omega_i(t))\n\\end{equation}\nwith $\\omega_i=\\frac{2\\pi}{T_i}(t-t_0)$,\n$t_0$ is \\config{timeStart} and $T$ is \\config{timePeriod} in days.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:*:oscillation.cos(2*pi/<period(days)>*(t-<timeStart>)):*|\nand \\verb|*:*:oscillation.sin(2*pi/<period(days)>*(t-<timeStart>)):*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~period & \\hfuzz=500pt time & \\hfuzz=500pt [day]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time0 & \\hfuzz=500pt time & \\hfuzz=500pt reference time\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Fourier}\nA time variable function is given by a fourier expansion\n\\begin{equation}\nf(x,t) = \\sum_{m=1}^M f_m^c(\\M x)\\cos(2\\pi m \\tau) + f_m^s(\\M x)\\sin(2\\pi m \\tau)\n\\end{equation}\nwith the normalized time\n\\begin{equation}\n\\tau = \\frac{t-t_A}{t_B-t_A},\n\\end{equation}\nand $t_A$ is \\config{timeStart}, $t_B$ is \\config{timeEnd} in each \\config{interval}\nand $M$ is the \\config{fourierDegree}.\n\nThe total parameter count is $2MN$, where $N$ is the number of intervals.\nThe parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\ldots$ with\nthe \\file{parameter names}{parameterName} \\verb|*:*:fourier.cos(<m>*x):<interval>| and \\verb|*:*:fourier.sin(<m>*x):<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~fourierDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~interval & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt intervals of fourier series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~includeLastTime & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DoodsonHarmonic}\nThe time variable function is given by a fourier expansion\n\\begin{equation}\n  f(x,t) = \\sum_{i} f_i^c(x)\\cos(\\Theta_i(t)) + f_i^s(x)\\sin(\\Theta_i(t)),\n\\end{equation}\nwhere $\\Theta_i(t)$ are the arguments of the tide constituents $i$\n\\begin{equation}\n  \\Theta_i(t) = \\sum_{k=1}^6 n_i^k\\beta_k(t),\n\\end{equation}\nwhere $\\beta_k(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$) and $n_i^k$\nare the Doodson multipliers for the term at frequency~$i$.\nThe multipliers must be given by \\configClass{doodson}{doodson} coded as Doodson number\n(e.g. 255.555) or as names intoduced by Darwin (e.g. M2).\n\nThe major constituents given by \\configClass{doodson}{doodson} can be used to interpolate minor tidal constituents\nusing the file \\configFile{inputfileAdmittance}{admittance}. This file can be created with\n\\program{DoodsonHarmonicsCalculateAdmittance}.\n\nThe total parameter count is $2N$ with $N$ the number of doodson frequencies.\nThe parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\ldots$ with\nthe \\file{parameter names}{parameterName} \\verb|*:*:doodson.cos(<doodsonName>):*| and \\verb|*:*:doodson.sin(<doodsonName>):*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~doodson & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt code number (e.g. 255.555) or darwin name (e.g. M2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt interpolation of minor constituents\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Planet}\\label{planetType}\nDefines the planet to compute the \\configClass{ephemeris}{ephemeridesType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~planetType & \\hfuzz=500pt choice & \\hfuzz=500pt planet\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~earth & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sun & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~moon & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~mercury & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~venus & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~mars & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~jupiter & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~saturn & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~uranus & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~neptune & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~pluto & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~solarBaryCenter & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~earthMoonBaryCenter & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlatformSelector}\\label{platformSelectorType}\nSelect a list of platforms (stations, satellites, ...).\nIn a first step all platforms are selected if first selector \\config{exclude}s platforms\notherwise all platforms excluded. When every selector from top to bottom selects or deselects\n(with \\config{exclude}) the matching platforms.\n\nSee also \\program{GnssProcessing} or \\program{SlrProcessing}.\n\n\n\\subsection{All}\\label{platformSelectorType:all}\nSelect all platforms.\n\n\n\\subsection{Wildcard}\\label{platformSelectorType:wildcard}\nSelect all receivers/transmitters which match the\n\\config{name}, \\config{markerName}, and \\config{markerNumber}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~markerName & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?, from platform\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~markerNumber & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?, from platform\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exclude & \\hfuzz=500pt boolean & \\hfuzz=500pt deselect matching platforms\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{File}\\label{platformSelectorType:file}\nSelect receivers/transmitters from each row of\n\\configFile{inputfileStringTable}{stringTable}.\nAdditional columns in a row represent alternatives\nif previous names are not available (e.g. without observation file).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStringTable & \\hfuzz=500pt filename & \\hfuzz=500pt list of names with alternatives\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exclude & \\hfuzz=500pt boolean & \\hfuzz=500pt deselect first matching platforms\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Equipment}\\label{platformSelectorType:equipment}\nSelect all platforms which has the specified equipment in the processed time interval.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~equipmentType & \\hfuzz=500pt choice & \\hfuzz=500pt equipment type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~all & \\hfuzz=500pt  & \\hfuzz=500pt all types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gnssAntenna & \\hfuzz=500pt sequence & \\hfuzz=500pt antennas\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gnssReceiver & \\hfuzz=500pt sequence & \\hfuzz=500pt receivers\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~version & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~slrStation & \\hfuzz=500pt  & \\hfuzz=500pt SLR station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~slrRetroReflector & \\hfuzz=500pt  & \\hfuzz=500pt laser retroreflector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~satelliteIdentifier & \\hfuzz=500pt sequence & \\hfuzz=500pt satellite identifier\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~cospar & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~norad & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sic & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sp3 & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~other & \\hfuzz=500pt  & \\hfuzz=500pt other types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exclude & \\hfuzz=500pt boolean & \\hfuzz=500pt deselect matching platforms\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Exclude}\\label{platformSelectorType:exclude}\nDeselects all selected receivers/transmitters of\n\\configClass{selector}{platformSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selector & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotAxis}\\label{plotAxisType}\nDefines the style of the axes of \\program{PlotGraph}.\n\n\n\\subsection{Standard}\nGeneral axis for arbitrary input data.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~min & \\hfuzz=500pt double & \\hfuzz=500pt The minimum value of the axis. If no value is given, the minimum scale value is set automatically.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~max & \\hfuzz=500pt double & \\hfuzz=500pt The maximum value of the axis. If no value is given, the maximum scale value is set automatically.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacing & \\hfuzz=500pt double & \\hfuzz=500pt The boundary annotation.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacing & \\hfuzz=500pt double & \\hfuzz=500pt The spacing of the frame tick intervals.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacing & \\hfuzz=500pt double & \\hfuzz=500pt The spacing of the grid line intervals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt The style of the grid lines.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~unit & \\hfuzz=500pt string & \\hfuzz=500pt Naming unit to append to the axis values.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~label & \\hfuzz=500pt string & \\hfuzz=500pt The description of the axis.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~logarithmic & \\hfuzz=500pt boolean & \\hfuzz=500pt If set to 'yes', a logarithmic scale is used for the axis.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt Setting the color of the axis bars and labels.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~changeDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt If set to 'yes', the directions right/up are changed to left/down.\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Time}\nThe input data are interpreted as MJD (modified Julian date).\nThe unit of the tick spacings should be appenend to the number and can be any of\n\\begin{itemize}\n\\item Y (year, plot with 4 digits)\n\\item y (year, plot with 2 digits)\n\\item O (month, plot using \\verb|FORMAT_DATE_MAP|)\n\\item o (month, plot with 2 digits)\n\\item U (ISO week, plot using \\verb|FORMAT_DATE_MAP|)\n\\item u (ISO week, plot using 2 digits)\n\\item r (Gregorian week, 7-day stride from start of week \\verb|TIME_WEEK_START|)\n\\item K (ISO weekday, plot name of day)\n\\item D (date, plot using \\verb|FORMAT_DATE_MAP|)\n\\item d (day, plot day of month 0-31 or year 1-366, via \\verb|FORMAT_DATE_MAP|)\n\\item R (day, same as d, aligned with \\verb|TIME_WEEK_START|)\n\\item H (hour, plot using \\verb|FORMAT_CLOCK_MAP|)\n\\item h (hour, plot with 2 digits)\n\\item M (minute, plot using \\verb|FORMAT_CLOCK_MAP|)\n\\item m (minute, plot with 2 digits)\n\\item S (second, plot using \\verb|FORMAT_CLOCK_MAP|)\n\\item s (second, plot with 2 digits).\n\\end{itemize}\n\nA secondary time axis can be added to specify larger intervals (e.g dates of hourly data).\n\nExamples: Settings for Fig.~\\ref{plotAxisType:plotAxisTime1}: \\config{majorTickSpacing}=\\verb|6H|, secondary: \\config{majorTickSpacing}=\\verb|1D|.\n\\fig{!hb}{1.0}{plotAxisTime1}{plotAxisType:plotAxisTime1}{Time axis for daily data.}\n\nSettings for Fig.~\\ref{plotAxisType:plotAxisTime2}: \\config{majorTickSpacing}=\\verb|2d|, secondary: \\config{majorTickSpacing}=\\verb|1O|, \\config{options}=\\verb|FORMAT_DATE_MAP=\"o yyyy\"|.\n\\fig{!hb}{1.0}{plotAxisTime2}{plotAxisType:plotAxisTime2}{Time axis for monthly data.}\n\nSettings for Fig.~\\ref{plotAxisType:plotAxisTime3}: \\config{majorTickSpacing}=\\verb|1o|, secondary: \\config{majorTickSpacing}=\\verb|1Y|, \\config{options}=\\verb|FORMAT_DATE_MAP=\"mm\"|.\n\\fig{!hb}{1.0}{plotAxisTime3}{plotAxisType:plotAxisTime3}{Time axis for yearly data.}\n\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~min & \\hfuzz=500pt time & \\hfuzz=500pt The minimum value of the time axis. If no value is given, the minimum scale value is set automatically.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~max & \\hfuzz=500pt time & \\hfuzz=500pt The maximum value of the time axis. If no value is given, the maximum scale value is set automatically.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacing & \\hfuzz=500pt string & \\hfuzz=500pt Y: year, o: month\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacing & \\hfuzz=500pt string & \\hfuzz=500pt D: date, d: day\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacing & \\hfuzz=500pt string & \\hfuzz=500pt H: clock, h: hour, m: minute, s: second\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~secondary & \\hfuzz=500pt sequence & \\hfuzz=500pt secondary time axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~majorTickSpacing & \\hfuzz=500pt string & \\hfuzz=500pt Y: year, o: month\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~minorTickSpacing & \\hfuzz=500pt string & \\hfuzz=500pt D: date, d: day\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~gridLineSpacing & \\hfuzz=500pt string & \\hfuzz=500pt H: clock, h: hour, m: minute, s: second\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt color of axis bars and labels\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt The style of the grid lines.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~changeDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt right-\\$>\\$left / up-\\$>\\$down\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~options & \\hfuzz=500pt string & \\hfuzz=500pt adjust date format\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Labeled}\nAxis with string labels. The coordinate system is based on the label indices (e.g. 0, 1, 2).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~labels & \\hfuzz=500pt string & \\hfuzz=500pt tick labels (ticks are placed at their index. e.g. 0, 1, ..., 5)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~min & \\hfuzz=500pt expression & \\hfuzz=500pt minimum value of the axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~max & \\hfuzz=500pt expression & \\hfuzz=500pt maximum values of the axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacing & \\hfuzz=500pt expression & \\hfuzz=500pt The boundary annotation.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacing & \\hfuzz=500pt expression & \\hfuzz=500pt The spacing of the frame tick intervals.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacing & \\hfuzz=500pt expression & \\hfuzz=500pt The spacing of the grid line intervals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt The style of the grid lines.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt set the color of the axis and labels\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~orthogonalLabels & \\hfuzz=500pt boolean & \\hfuzz=500pt labels are oriented orthogonal to axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~changeDirection & \\hfuzz=500pt boolean & \\hfuzz=500pt If set to 'yes', the directions right/up are changed to left/down.\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotColor}\\label{plotColorType}\nSelects a color.\nUsed in \\program{PlotDegreeAmplitudes}, \\program{PlotGraph}, \\program{PlotMap},\n\\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~plotColorType & \\hfuzz=500pt choice & \\hfuzz=500pt color\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~black & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~red & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~blue & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~green & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~orange & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~darkred & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~yellow & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~lightgreen & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gray & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rgb & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~red & \\hfuzz=500pt uint & \\hfuzz=500pt 0..255\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~green & \\hfuzz=500pt uint & \\hfuzz=500pt 0..255\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~blue & \\hfuzz=500pt uint & \\hfuzz=500pt 0..255\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~grayscale & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt uint & \\hfuzz=500pt 0..255\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~namedColor & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~colorName & \\hfuzz=500pt string & \\hfuzz=500pt name after GMT definition\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~cycler & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~index & \\hfuzz=500pt uint & \\hfuzz=500pt pick color based on index expression\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileColorList & \\hfuzz=500pt filename & \\hfuzz=500pt list of colors as defined by GMT\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotColorbar}\\label{plotColorbarType}\nA colorbar as used in \\program{PlotMap}, \\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~plotColorbarType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~min & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~max & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~annotation & \\hfuzz=500pt double & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~unit & \\hfuzz=500pt string & \\hfuzz=500pt appended to axis values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~label & \\hfuzz=500pt string & \\hfuzz=500pt description of the axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~logarithmic & \\hfuzz=500pt boolean & \\hfuzz=500pt use logarithmic scale\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~triangleLeft & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~triangleRight & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~illuminate & \\hfuzz=500pt boolean & \\hfuzz=500pt illuminate\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~vertical & \\hfuzz=500pt boolean & \\hfuzz=500pt plot vertical color bar on the right\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~length & \\hfuzz=500pt double & \\hfuzz=500pt length of colorbar in percent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt between colorbar and figure [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~colorTable & \\hfuzz=500pt string & \\hfuzz=500pt name of the color bar\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~reverse & \\hfuzz=500pt boolean & \\hfuzz=500pt reverse direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~showColorbar & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotGraphLayer}\\label{plotGraphLayerType}\nDefines the content of an xy-plot of \\program{PlotGraph}.\nMultiple layers are are plotted sequentially. With \\config{plotOnSecondAxis}\nthe alternative y-axis on the right hand side can be selected if provided.\n\n\n\\subsection{LinesAndPoints}\\label{plotGraphLayerType:linesAndPoints}\nDraws a \\configClass{line}{plotLineType} and/or points (\\configClass{symbol}{plotSymbolType})\nof xy data. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nIf no \\configClass{color}{plotColorType} of the \\configClass{symbol}{plotSymbolType}\nis given a \\configClass{colorbar}{plotColorbarType}\nis required and the color is determined by \\config{valueZ}.\nAdditionally a vertical error bar can be plotted at each data point with\nsize \\config{valueErrorBar}.\n\nSee \\program{Gravityfield2AreaMeanTimeSeries} for an example plot.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt each line contains x,y\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueX & \\hfuzz=500pt expression & \\hfuzz=500pt expression for x-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueY & \\hfuzz=500pt expression & \\hfuzz=500pt expression for y-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueZ & \\hfuzz=500pt expression & \\hfuzz=500pt expression for the colorbar\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueErrorBar & \\hfuzz=500pt expression & \\hfuzz=500pt expression for error bars (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt text of the legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~line & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~symbol & \\hfuzz=500pt \\hyperref[plotSymbolType]{plotSymbol} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{ErrorEnvelope}\nDraws a symmetrical envelope around \\config{valueY} as function of \\config{valueX}\nusing deviations \\config{valueErrors}.\nThe standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nThe data line itself is not plotted but must be added as extra\n\\configClass{layer:linesAndPoints}{plotGraphLayerType:linesAndPoints}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt each line contains x,y\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueX & \\hfuzz=500pt expression & \\hfuzz=500pt expression for x-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueY & \\hfuzz=500pt expression & \\hfuzz=500pt expression for y-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueErrors & \\hfuzz=500pt expression & \\hfuzz=500pt expression for error values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt text of the legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fillColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt fill color of the envelope\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~edgeLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt edge line style of the envelope\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Bars}\nCreates a bar plot with vertical or \\config{horizontal} bars out of the given\nx- and y-values. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nThe bars ranges from \\config{valueBase} (can be also an expression) to the \\config{valueY}.\nIf no \\configClass{color}{plotColorType} is given a \\configClass{colorbar}{plotColorbarType}\nis required and the color is determined by \\config{valueZ}.\n\nSee \\program{Instrument2Histogram} for an example plot.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt each line contains x,y\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueX & \\hfuzz=500pt expression & \\hfuzz=500pt expression for x-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueY & \\hfuzz=500pt expression & \\hfuzz=500pt expression for y-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueZ & \\hfuzz=500pt expression & \\hfuzz=500pt expression for the colorbar\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueBase & \\hfuzz=500pt expression & \\hfuzz=500pt base value of bars (default: minimum y-value)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt expression & \\hfuzz=500pt width of bars (default: minimum x-gap)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~horizontal & \\hfuzz=500pt boolean & \\hfuzz=500pt draw horizontal bars instead of vertical\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt text of the legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~edgeLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt line\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Gridded}\nCreates a regular grid of yxz values. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nEmpty grid cells are not plotted. Cells with more than one value will be set to the mean value.\nThe grid spacing is determined by the median spacing of the input data or set by \\config{incrementX/Y}.\n\nSee \\program{Orbit2ArgumentOfLatitude} for an example plot.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt each line contains x,y,z\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueX & \\hfuzz=500pt expression & \\hfuzz=500pt expression for x-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueY & \\hfuzz=500pt expression & \\hfuzz=500pt expression for y-values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueZ & \\hfuzz=500pt expression & \\hfuzz=500pt expression for the colorbar\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~incrementX & \\hfuzz=500pt double & \\hfuzz=500pt the grid spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~incrementY & \\hfuzz=500pt double & \\hfuzz=500pt the grid spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Rectangle}\nPlots a rectangle to highlight an area.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minX & \\hfuzz=500pt double & \\hfuzz=500pt empty: left\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxX & \\hfuzz=500pt double & \\hfuzz=500pt empty: right\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minY & \\hfuzz=500pt double & \\hfuzz=500pt empty: bottom\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxY & \\hfuzz=500pt double & \\hfuzz=500pt empty: top\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt text of the legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~edgeLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fillColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Text}\nWrites a \\config{text} at \\config{originX} and \\config{originY} position in the graph.\nWith \\config{clip} the text is cutted at the boundaries of the plotting area.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~originX & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~originY & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~offsetX & \\hfuzz=500pt double & \\hfuzz=500pt [cm] x-offset from origin\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~offsetY & \\hfuzz=500pt double & \\hfuzz=500pt [cm] y-offset from origin\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~alignment & \\hfuzz=500pt string & \\hfuzz=500pt L, C, R (left, center, right) and T, M, B (top, middle, bottom)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fontSize & \\hfuzz=500pt double & \\hfuzz=500pt [pt]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~fontColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~clip & \\hfuzz=500pt boolean & \\hfuzz=500pt clip at boundaries\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DegreeAmplitudes}\\label{plotGraphLayerType:degreeAmplitudes}\nPlot degree amplitudes of potential coefficients computed by \\program{Gravityfield2DegreeAmplitudes}\nor \\program{PotentialCoefficients2DegreeAmplitudes}.\nThe standard \\reference{dataVariables}{general.parser:dataVariables} are available to select\nthe data columns of \\configFile{inputfileMatrix}{matrix}. It plots a solid line for the\n\\config{valueSignal} and a dotted line for the \\config{valueError} per default.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt degree amplitudes\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueDegree & \\hfuzz=500pt expression & \\hfuzz=500pt expression for x-values (degrees) (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueSignal & \\hfuzz=500pt expression & \\hfuzz=500pt expression for y-values (signal) (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~valueErrors & \\hfuzz=500pt expression & \\hfuzz=500pt expression for y-values (formal errors)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt text of the legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lineSignal & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lineErrors & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DegreeAmplitudesSimple}\\label{plotGraphLayerType:degreeAmplitudesSimple}\nPlot degree amplitudes from a \\configClass{gravityfield}{gravityfieldType}.\nThe coefficients can be converted to different functionals with \\configClass{kernel}{kernelType}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. It plots a solid line for the degree amplitude (signal)\nand a dotted line for the formal errors per default.\n\nThis is a simplified version of\n\\configClass{layer:degreeAmplitudes}{plotGraphLayerType:degreeAmplitudes}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt type of variances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rms & \\hfuzz=500pt  & \\hfuzz=500pt degree amplitudes (square root of degree variances)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~accumulation & \\hfuzz=500pt  & \\hfuzz=500pt cumulate variances over degrees\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~median & \\hfuzz=500pt  & \\hfuzz=500pt median of absolute values per degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt text of the legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lineSignal & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lineErrors & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~plotOnSecondAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt draw dataset on a second Y-axis (if available).\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotLegend}\\label{plotLegendType}\nPlot a legend of the descriptions provided in\n\\configClass{plotGraphLayer}{plotGraphLayerType} in \\program{PlotGraph}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~plotLegendType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt legend width [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt legend height [cm] (default: estimated)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionX & \\hfuzz=500pt double & \\hfuzz=500pt legend x-position in normalized (0-1) coordinates.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionY & \\hfuzz=500pt double & \\hfuzz=500pt legend y-position in normalized (0-1) coordinates.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~anchorPoint & \\hfuzz=500pt string & \\hfuzz=500pt Two character combination of L, C, R (for left, center, or right) and T, M, B for top, middle, or bottom. e.g., TL for top left\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~columns & \\hfuzz=500pt uint & \\hfuzz=500pt number of columns in legend\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~textColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt color of the legend text\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~fillColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt fill color of the legend box\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~edgeLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt style of the legend box edge\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotLine}\\label{plotLineType}\nDefines the line style to be plotted.\n\n\n\\subsection{Solid}\nDraws a solid line.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt line width [p]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Dashed}\nDraws a dashed line.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt line width [p]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Dotted}\nDraws a dotted line.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt line width [p]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt   \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Custom}\nDraws a custom line. The line \\config{style} code is described in\n\\url{https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~style & \\hfuzz=500pt string & \\hfuzz=500pt line style code\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt line width [p]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotMapLayer}\\label{plotMapLayerType}\nDefines the content of a map of \\program{PlotMap}. Multiple layers are are plotted sequentially.\n\n\n\\subsection{GriddedData}\nCreates a regular grid of xyz values. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data column of \\configFile{inputfileGriddedData}{griddedData}.\nEmpty grid cells are not plotted. Cells with more than one value will be set to the mean value.\nThe grid spacing can be determined automatically for regular rectangular grids otherwise\nit must be set with \\config{increment}. To get a better display together with some projections\nthe grid should be internally \\config{resample}d to higher resolution.\nIt is assumed that the points of \\configFile{inputfileGriddedData}{griddedData} represents centers of grid cells.\nThis assumption can be changed with \\config{gridlineRegistered} (e.g. if the data starts at the north pole).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~increment & \\hfuzz=500pt angle & \\hfuzz=500pt the grid spacing [degrees]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~illuminate & \\hfuzz=500pt boolean & \\hfuzz=500pt illuminate grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~resample & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~intermediateDpi & \\hfuzz=500pt double & \\hfuzz=500pt oversample grid for a smoother visual effect\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~interpolationMethod & \\hfuzz=500pt choice & \\hfuzz=500pt interpolation method for oversampling\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~bspline & \\hfuzz=500pt  & \\hfuzz=500pt B-Spline interpolation\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~bicubic & \\hfuzz=500pt  & \\hfuzz=500pt bicubic interpolation\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~bilinear & \\hfuzz=500pt  & \\hfuzz=500pt bilinear interpolation\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~nearest & \\hfuzz=500pt  & \\hfuzz=500pt nearest neighbour interpolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~threshold & \\hfuzz=500pt double & \\hfuzz=500pt A threshold of 1.0 requires all (4 or 16) nodes involved in interpolation to be non-NaN. 0.5 will interpolate about half way from a non-NaN value; 0.1 will go about 90\\% of the way.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridlineRegistered & \\hfuzz=500pt boolean & \\hfuzz=500pt treat input as point values instead of cell means\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Points}\\label{plotMapLayerType:points}\nDraws points (\\configClass{symbol}{plotSymbolType}) and/or \\configClass{line}{plotLineType}s\nbetween the points. If no \\configClass{color}{plotColorType} of the \\configClass{symbol}{plotSymbolType}\nis given a \\configClass{colorbar}{plotColorbarType} is required and the color is determined\nby the \\config{value} expression. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data column of \\configFile{inputfileGriddedData}{griddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute color (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~symbol & \\hfuzz=500pt \\hyperref[plotSymbolType]{plotSymbol} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~line & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt style of connecting lines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~drawLineAsGreatCircle & \\hfuzz=500pt boolean & \\hfuzz=500pt draw connecting lines as great circles (otherwise, a straight line is drawn instead)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Arrows}\nDraws an arrow for each point in \\configFile{inputfileGriddedData}{griddedData}.\nThe arrows are defined by the expressions \\config{valueNorth/East}.\nThe standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the correspondent data columns of \\configFile{inputfileGriddedData}{griddedData}.\nThe \\config{scale} factor converts the input units to cm in the plot.\nIf no \\configClass{color}{plotColorType} is given a \\configClass{colorbar}{plotColorbarType} is required\nand the color is determined by the \\config{value} expression.\nWith \\config{scaleArrow} a reference arrow as legend can be plotted inside or outside the map.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt grid file with north and east values for arrows\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueNorth & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute north values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~valueEast & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute east values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute arrow color (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~scale & \\hfuzz=500pt double & \\hfuzz=500pt [cm per input unit] length scale factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~penSize & \\hfuzz=500pt double & \\hfuzz=500pt [pt] width of arrow shaft\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~headSize & \\hfuzz=500pt double & \\hfuzz=500pt [pt] size of arrow head, 0: no head, negative: reverse head\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: from value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~scaleArrow & \\hfuzz=500pt sequence & \\hfuzz=500pt draw an arrow for scale reference\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~originX & \\hfuzz=500pt double & \\hfuzz=500pt [0-1] 0: left, 1: right\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~originY & \\hfuzz=500pt double & \\hfuzz=500pt [0-1] 0: bottom, 1: top\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~length & \\hfuzz=500pt double & \\hfuzz=500pt in same unit as valueNorth and valueEast\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~unit & \\hfuzz=500pt string & \\hfuzz=500pt displayed unit text (e.g. 1 cm)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~label & \\hfuzz=500pt string & \\hfuzz=500pt description of the arrows\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Polygon}\nDraws a \\configFile{inputfilePolygon}{polygon}.\nIf \\configClass{fillColor}{plotColorType} is not set and a \\config{value}\nis given the fill color is taken from a \\configClass{colorbar}{plotColorbarType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePolygon & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~line & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt style of border lines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fillColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt polygon fill color (no fill color: determine from value if given, else: no fill)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt value to compute fill color from a colorbar (ignored if a fillColor is given)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~drawLineAsGreatCircle & \\hfuzz=500pt boolean & \\hfuzz=500pt draw connecting lines as great circles (otherwise, a straight line is drawn instead)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Coast}\nPlots coastlines. GMT provides them in different \\config{resolution}s.\nFeatures with an area smaller than \\config{minArea} in $km^2$ will not be plotted.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~resolution & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~crude & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~low & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~medium & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~high & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~full & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~line & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt line style for coastlines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~landColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt fill land area\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~oceanColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt fill ocean area\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minArea & \\hfuzz=500pt uint & \\hfuzz=500pt [km\\textasciicircum{}2] features with a smaller area than this are dropped\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Rivers}\nPlots rivers and lakes. GMT provides different classes\n(\\url{https://docs.generic-mapping-tools.org/latest/coast.html}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~class & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~riversCanalsLakes & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~riversCanals & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~permanentRiversLakes & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~permanentRivers & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~intermittentRivers & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~canals & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~singleClass & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~class & \\hfuzz=500pt uint & \\hfuzz=500pt 0-10. See GMT documentation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~line & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PoliticalBoundary}\nPlots national boundaries. GMT provides them in different \\config{resolution}s.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~resolution & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~crude & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~low & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~medium & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~high & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~full & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~line & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{BlueMarble}\nAn image of the Earth's surface as seen from outer space -\nthe image is known as \\emph{blue marble}. The directory of \\config{inputfileChannels}\ncontains several files in different resolutions representing the Earth's surface each\nmonth throughout a year.\n\n\\fig{!hb}{0.8}{blueMarble}{fig:blueMarbleMap}{The blue marble.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileImage & \\hfuzz=500pt filename & \\hfuzz=500pt Blue Marble image file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~brightness & \\hfuzz=500pt double & \\hfuzz=500pt brightness of bitmap [-1, 1]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~illuminate & \\hfuzz=500pt sequence & \\hfuzz=500pt add hillshade based on topography\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTopography & \\hfuzz=500pt filename & \\hfuzz=500pt GMT grid file containing topography.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~azimuth & \\hfuzz=500pt angle & \\hfuzz=500pt direction of lighting source [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~elevation & \\hfuzz=500pt angle & \\hfuzz=500pt direction of lighting source [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~ambient & \\hfuzz=500pt double & \\hfuzz=500pt ambient lighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~diffuse & \\hfuzz=500pt double & \\hfuzz=500pt diffuse lighting\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~specular & \\hfuzz=500pt double & \\hfuzz=500pt specular reflection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~shine & \\hfuzz=500pt double & \\hfuzz=500pt surface shine\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~amplitude & \\hfuzz=500pt double & \\hfuzz=500pt scale gradient by factor\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Text}\nWrites a \\config{text} at \\config{originLongitude} and \\config{originLatitude} position in the map.\nWith \\config{clip} the text is cutted at the boundaries of the plotting area.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~originLongitude & \\hfuzz=500pt angle & \\hfuzz=500pt [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~originLatitude & \\hfuzz=500pt angle & \\hfuzz=500pt [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~offsetX & \\hfuzz=500pt double & \\hfuzz=500pt [cm] x-offset from origin\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~offsetY & \\hfuzz=500pt double & \\hfuzz=500pt [cm] y-offset from origin\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~alignment & \\hfuzz=500pt string & \\hfuzz=500pt L, C, R (left, center, right) and T, M, B (top, middle, bottom)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fontSize & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~fontColor & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~clip & \\hfuzz=500pt boolean & \\hfuzz=500pt clip at boundaries\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotMapProjection}\\label{plotMapProjectionType}\nSelects the underlying projection of \\program{PlotMap}.\n\n\n\\subsection{Robinson}\nThe Robinson projection, presented by Arthur H. Robinson in 1963,\nis a modified cylindrical projection that is neither conformal nor equal-area.\nCentral meridian and all parallels are straight lines; other meridians are curved.\nIt uses lookup tables rather than analytic expressions to make the world map look right.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~centralMeridian & \\hfuzz=500pt angle & \\hfuzz=500pt central meridian [degree]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Orthographic}\nThe orthographic azimuthal projection is a perspective projection from infinite distance.\nIt is therefore often used to give the appearance of a globe viewed from space.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lambdaCenter & \\hfuzz=500pt angle & \\hfuzz=500pt central point [degree]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~phiCenter & \\hfuzz=500pt angle & \\hfuzz=500pt central point [degree]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Perspective sphere}\nThe orthographic azimuthal projection is a perspective projection from infinite distance.\nIt is therefore often used to give the appearance of a globe viewed from space.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lambdaCenter & \\hfuzz=500pt angle & \\hfuzz=500pt longitude of central point in degrees\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~phiCenter & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of central point in degrees\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~altitude & \\hfuzz=500pt double & \\hfuzz=500pt [km]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~azimuth & \\hfuzz=500pt angle & \\hfuzz=500pt to the east of north of view [degrees]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~tilt & \\hfuzz=500pt angle & \\hfuzz=500pt upward tilt of the plane of projection, if negative, then the view is centered on the horizon [degrees]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~viewpointTwist & \\hfuzz=500pt angle & \\hfuzz=500pt clockwise twist of the viewpoint [degrees]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~viewpointWidth & \\hfuzz=500pt angle & \\hfuzz=500pt width of the viewpoint [degrees]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~viewpointHeight & \\hfuzz=500pt angle & \\hfuzz=500pt height of the viewpoint [degrees]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Polar}\nStereographic projection around given central point.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lambdaCenter & \\hfuzz=500pt angle & \\hfuzz=500pt longitude of central point in degrees\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~phiCenter & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of central point in degrees\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Skyplot}\nSkyplot used to plot azimuth/elevation data as generated by\n\\program{GnssAntennaDefinition2Skyplot} or \\program{GnssResiduals2Skyplot}.\n\n\n\\subsection{UTM}\nA particular subset of the transverse Mercator is the Universal Transverse Mercator (UTM)\nwhich was adopted by the US Army for large-scale military maps.\nHere, the globe is divided into 60 zones between 84$^{o}$S and 84$^{o}$N, most of which are 6$^{o}$ wide.\nEach of these UTM zones have their unique central meridian.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~zone & \\hfuzz=500pt string & \\hfuzz=500pt UTM zone code (e.g. 33N)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Lambert}\nThis conic projection was designed by Lambert (1772) and has been used extensively for mapping of regions with predominantly east-west orientation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~lambda0 & \\hfuzz=500pt angle & \\hfuzz=500pt longitude of projection center [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~phi0 & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of projection centert [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~phi1 & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of first standard parallel [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~phi2 & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of first standard parallel [deg]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Linear}\nLinear mapping of longitude/latitude to x/y (Plate Caree).\n\n\n\\subsection{Mollweide}\nThis pseudo-cylindrical, equal-area projection was developed by Mollweide in 1805. Parallels are unequally spaced straight\nlines with the meridians being equally spaced elliptical arcs. The scale is only true along latitudes 40$^{o}$44' north and south.\nThe projection is used mainly for global maps showing data distributions.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~centralMeridian & \\hfuzz=500pt angle & \\hfuzz=500pt central meridian [degree]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PlotSymbol}\\label{plotSymbolType}\nPlots a symbol as used e.g. in \\configClass{plotGraphLayer:linesAndPoints}{plotGraphLayerType:linesAndPoints}\nor \\configClass{plotMapLayer:points}{plotMapLayerType:points}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~plotSymbolType & \\hfuzz=500pt choice & \\hfuzz=500pt symbol\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~circle & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~star & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~cross & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~square & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~triangle & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~diamond & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dash & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~color & \\hfuzz=500pt \\hyperref[plotColorType]{plotColor} & \\hfuzz=500pt empty: determined from value\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~size & \\hfuzz=500pt double & \\hfuzz=500pt size of symbol [point]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~blackContour & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{PodRightSide}\\label{podRightSideType}\nObservation vector for precise orbit data (POD) of \\configClass{observation}{observationType}\nequations in a least squares adjustment. The observations are reduced by the effect of\n\\configFile{inputfileAccelerometer}{instrument} and \\configClass{forces}{forcesType}\n(observed minus computed).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~podRightSideType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt non-gravitational forces in satellite reference frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~forces & \\hfuzz=500pt \\hyperref[forcesType]{forces} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SggRightSide}\\label{sggRightSideType}\nObservation vector for gradiometer data (satellite gravity gradiometry, SGG)\nof \\configClass{observation}{observationType} equations in a least squares adjustment.\nThe observations are reduced by an \\configFile{inputfileReferenceGradiometer}{instrument},\nthe effect of \\configClass{referencefield}{gravityfieldType}, and \\configClass{tides}{tidesType}\n(observed minus computed).\n\nThe reference gradiometer data can be precomputed with \\program{SimulateGradiometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sggRightSideType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGradiometer & \\hfuzz=500pt filename & \\hfuzz=500pt observed gravity gradients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileReferenceGradiometer & \\hfuzz=500pt filename & \\hfuzz=500pt precomputed gradients at orbit positions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~referencefield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~tides & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SlrParametrization}\\label{slrParametrizationType}\nThis class defines the models and parameters of the linearized observation equations\nfor normal points (see \\program{SlrProcessing})\n\\begin{equation}\\label{slrParametrizationType:model}\n  \\M l - \\M f(\\M x_0) = \\left.\\frac{\\partial \\M f(\\M x)}{\\partial \\M x}\\right|_{\\M x_0} \\Delta\\M x + \\M\\epsilon,\n\\end{equation}\nwhere the left side is the observation vector minus the effects computed from the a priori models.\nAfter each least squares adjustment\n(see \\configClass{SlrProcessing:processingStep:estimate}{slrProcessingStepType:estimate})\nthe a priori parameters are updated\n\\begin{equation}\\label{slrParametrizationType:update}\n  \\M x_0 := \\M x_0 + \\Delta\\hat{\\M x}.\n\\end{equation}\nThe vector $\\M x_0$ can be written with\n\\configClass{SlrProcessing:processingStep:writeAprioriSolution}{slrProcessingStepType:writeAprioriSolution}.\nAny \\config{outputfiles} defined in the parametrizations are written with\n\\configClass{SlrProcessing:processingStep:writeResults}{slrProcessingStepType:writeResults}.\n\nEach parametrization (and possible constraint equations) has a \\config{name} which enables\nactivating/deactivating the estimation of subsets of $\\Delta\\M x$ with\n\\configClass{SlrProcessing:processingStep:selectParametrizations}{slrProcessingStepType:selectParametrizations}.\nThe a priori model $\\M f(\\M x_0)$ is unaffected and is always reduced.\n\nThe model for the one way range observations between station $s$ and reflector $r$\ncan be described as\n\\begin{equation}\\label{slrParametrizationType:slrFullModel}\n\\begin{split}\n  f_s^r(\\M x) &= \\frac{1}{2}\\left(\\left\\lVert \\M r^r(t_{bounce})-\\M r_s(t_{trans}) \\right\\rVert\n                          + \\left\\lVert \\M r_s(t_{recv})-\\M r^r(t_{bounce}) \\right\\rVert\\right)  \\\\\n              &+ \\text{troposphere}(t,\\M r_{ss}^r)\n               + \\text{bias}^r + \\text{bias}_s + \\text{bias}_s^r + \\text{other}(\\ldots) + \\epsilon_r^s\n\\end{split}\n\\end{equation}\n\nSee also \\program{SlrProcessing}.\n\n\n\\subsection{Troposphere}\\label{slrParametrizationType:troposphere}\nA priori tropospheric correction is handled by a \\configClass{troposphere}{troposphereType} model (e.g. Mendes and Pavlis).\nAdditional parameters in $[m]$ for zenith delay can be set up via\n\\configClass{troposphereEstimation}{parametrizationTemporalType}.\nThese parameters can be soft-constrained using\n\\configClass{parametrization:constraints}{slrParametrizationType:constraints}\nto avoid an unsolvable system of normal equations in case of data gaps.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>:troposphere:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTroposphere & \\hfuzz=500pt filename & \\hfuzz=500pt columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~troposphere & \\hfuzz=500pt \\hyperref[troposphereType]{troposphere} & \\hfuzz=500pt a priori troposphere model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~troposphereEstimation & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt [m] parametrization of zenith delays\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DynamicOrbits}\\label{slrParametrizationType:dynamicOrbits}\nThe estimation of (reduced) dynamic orbits is formulated as variational equations.\nIt is based on \\configFile{inputfileVariational}{variationalEquation} calculated with \\program{PreprocessingVariationalEquation}.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree \\config{integrationDegree}.\nThe \\configClass{parametrizationAcceleration}{parametrizationAccelerationType} must include at least those\nparameters that were estimated in \\program{PreprocessingVariationalEquationOrbitFit}.\nAdditional \\configClass{stochasticPulse}{timeSeriesType} parameters can be set up to reduce orbit mismodeling.\n\nThe parameters and \\file{parameter names}{parameterName} are divided into global\n\\begin{itemize}\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:stochasticPulse.x::<time>|,\n\\item \\verb|<satellite>:stochasticPulse.y::<time>|,\n\\item \\verb|<satellite>:stochasticPulse.z::<time>|,\n\\end{itemize}\nand arc related parameters\n\\begin{itemize}\n\\item \\verb|<satellite>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:arc<no>.position0.x::|,\n\\item \\verb|<satellite>:arc<no>.position0.y::|,\n\\item \\verb|<satellite>:arc<no>.position0.z::|.\n\\item \\verb|<satellite>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameters & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stochasticPulse & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt [mu/s] parametrization of stochastic pulses\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for orbit interpolation and velocity calculation\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{GravityField}\\label{slrParametrizationType:gravityField}\nEstimates a (time depending) gravity field together with at least one\n\\configClass{parametrization:dynamicOrbits}{slrParametrizationType:dynamicOrbits}.\nThe parametrization of the gravity field can be set with\n\\configClass{parametrization}{parametrizationGravityType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|gravityfield:<parametrization>:*:*|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{StaticPositions}\\label{slrParametrizationType:staticPositions}\nEstimates a static position for all\n\\configClass{selectReceivers}{platformSelectorType} in the terrestrial frame.\n\nNo-net constraints can be applied for a subset of stations,\n\\configClass{selectNoNetReceivers}{platformSelectorType}, with a\nstandard deviation of \\config{noNetTranslationSigma} and \\config{noNetRotationSigma} and \\config{noNetScaleSigma} and \\config{noNetScaleSigma}.\nIf the template \\configFile{inputfileNoNetPositions}{stringList} is provided\nthe constraints are applied relatively to these positions. Only stations with an existing position file\nare considered. Without \\configFile{inputfileNoNetPositions}{stringList}\nthe constraints are applied towards the apriori values from\n\\configClass{SlrProcessing:station}{slrStationGeneratorType}.\nAs a single corrupted station position can disturb the no-net conditions,\nthe rotation/translation parameters are estimated in a\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}\nbeforehand. The computed weight matrix is used to downweight corrupted stations\nin the constraint equations.\n\nIn case you want to align to an ITRF/ILRS reference frame, precise coordinates can be\ngenerated with \\program{Sinex2StationPositions}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:position.x::|,\n\\item \\verb|<station>:position.y::|,\n\\item \\verb|<station>:position.z::|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGriddedPosition & \\hfuzz=500pt filename & \\hfuzz=500pt delta north east up for all stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePosition & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, full estimated coordinates (in TRF)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nameConstraint & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectNoNetStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileNoNetPositions & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, precise coordinates used for no-net constraints (in TRF)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~noNetTranslationSigma & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~noNetRotationSigma & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] at Earth's surface for no-net rotation constraint on station coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~noNetScaleSigma & \\hfuzz=500pt double & \\hfuzz=500pt (0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt stations \\$>\\$ huber*sigma0 are downweighted in no-net constraint\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt stations \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EarthRotation}\\label{slrParametrizationType:earthRotation}\nEarth rotation parameters (ERPs) can be estimated by defining\n\\config{estimatePole} ($x_p$, $y_p$) and \\config{estimateUT1} ($dUT1, LOD$).\n\nEstimating length of day (LOD) with the sign according to IGS conventions requires a negative\nvalue in \\configClass{parametrizationTemporal:trend:timeStep}{parametrizationTemporalType:trend}.\n\nConstraints on the defined parameters can be added via\n\\configClass{parametrization:constraints}{slrParametrizationType:constraints}.\nAn example would be to set up \\configClass{estimateUT1:constant}{parametrizationTemporalType:constant}\nso the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be\ndetermined by SLR, a hard constraint to its a priori value can then be added.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|earth:polarMotion.xp:<temporal>:<interval>|,\n\\item \\verb|earth:polarMotion.yp:<temporal>:<interval>|,\n\\item \\verb|earth:UT1:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.X:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.>:<temporal>:<interval>|.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimatePole & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt xp, yp [mas]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimateUT1 & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt rotation angle [ms]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~estimateNutation & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt dX, dY [mas]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RangeBiasStationApriori}\\label{slrParametrizationType:rangeBiasStationApriori}\nA priori station range bias value for all \\configClass{selectStations}{platformSelectorType}.\nThe \\href{https://ilrs.gsfc.nasa.gov/}{ILRS} provides the mean range biases \\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File},\nbut these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive\nsatellites and not for active ones.\nUse \\program{SlrSinexDataHandling2Files} to convert the range biases from\n\\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File} to \\file{instrument file}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RangeBiasStation}\\label{slrParametrizationType:rangeBiasStation}\nEstimates a constant station range bias in $[m]$ for\n\\configClass{selectStations}{platformSelectorType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>:rangeBias::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RangeBiasSatelliteApriori}\\label{slrParametrizationType:rangeBiasSatelliteApriori}\nA priori satellite range bias value for \\configClass{selectSatellites}{platformSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RangeBiasSatellite}\\label{slrParametrizationType:rangeBiasSatellite}\nEstimates a constant satellite range bias in $[m]$ for\n\\configClass{selectSatellites}{platformSelectorType}.\n\nThe \\file{parameter names}{parameterName} a \\verb|<satellite>:rangeBias::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RangeBiasStationSatelliteApriori}\\label{slrParametrizationType:rangeBiasStationSatelliteApriori}\nA priori station-satellite range bias value between all \\configClass{selectStations}{platformSelectorType} -\n\\configClass{selectSatellites}{platformSelectorType} pairs.\n\nFor standard \\href{https://ilrs.gsfc.nasa.gov/}{ILRS} processing this class should be setup twice.\nOnce for the model from José Rodríguez (see \\program{SlrComModel2RangeBiasStationSatellite}) and additionally for\nbiases from the \\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File} converted with \\program{SlrSinexDataHandling2Files}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} and \\{satellite\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{RangeBiasStationSatellite}\\label{slrParametrizationType:rangeBiasStationSatellite}\nEstimates the station-satellite range bias in $[m]$ between all\n\\configClass{selectStations}{platformSelectorType} -\n\\configClass{selectSatellites}{platformSelectorType} pairs.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>.<satellite>:rangeBias::|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} and \\{satellite\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TimeBiasApriori}\\label{slrParametrizationType:timeBiasApriori}\nA priori time bias value for all \\configClass{selectStations}{platformSelectorType}.\nThe \\href{https://ilrs.gsfc.nasa.gov/}{ILRS} provides the mean time biases \\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File},\nbut these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive\nsatellites and not for active ones.\nUse \\program{SlrSinexDataHandling2Files} to convert the time biases from\n\\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File} to \\file{instrument file}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTimeBias & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{TimeBias}\\label{slrParametrizationType:timeBias}\nEstimates a \\configClass{temporal changing}{parametrizationTemporalType}\ntime bias in $[ms]$ for \\configClass{selectStations}{platformSelectorType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>:timeBias:<temporal>:<interval>|.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt used for parameter selection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~estimateTimeBias & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt [ms]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Constraints}\\label{slrParametrizationType:constraints}\nAdd a pseudo observation equation (constraint)\nfor each selected \\configClass{parameters}{parameterSelectorType}\n\\begin{equation}\n  b-x_0 = 1 \\cdot dx + \\epsilon,\n\\end{equation}\nwhere $b$ is the \\config{bias} and $x_0$ is the a priori value of the parameter\nif \\config{relativeToApriori} is not set.\nThe standard deviation \\config{sigma} is used to weight the observation equations.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter to constrain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt sigma of the constraint (same unit as parameter)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~bias & \\hfuzz=500pt double & \\hfuzz=500pt constrain all selected parameters towards this value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~relativeToApriori & \\hfuzz=500pt boolean & \\hfuzz=500pt constrain only dx and not full x=dx+x0\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{slrParametrizationType:group}\nGroups a set of parameters. This class can be used to structure complex parametrizations\nand has no further effect itself.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[slrParametrizationType]{slrParametrization} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SlrProcessingStep}\\label{slrProcessingStepType}\nProcessing step in \\program{SlrProcessing}.\n\nProcessing steps enable a dynamic definition of the consecutive steps performed during any kind of SLR processing.\nThe most common steps are \\configClass{estimate}{slrProcessingStepType:estimate}, which performs an iterative least\nsquares adjustment, and \\configClass{writeResults}{slrProcessingStepType:writeResults}, which writes all output files\ndefined in \\program{SlrProcessing} and is usually the last step.\nSome steps such as \\configClass{selectParametrizations}{slrProcessingStepType:selectParametrizations}\nand \\configClass{selectStations}{slrProcessingStepType:selectStations} affect all subsequent steps.\nIn case these steps are used within a \\configClass{group}{slrProcessingStepType:group} step,\nthey only affect the steps within this level.\n\n\n\\subsection{Estimate}\\label{slrProcessingStepType:estimate}\nIterative non-linear least squares adjustment.\nIn every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters.\nThe estimated parameters serve as a priori values in the next iteration and the following processing steps.\nIterates until either every single parameter update (converted to an influence in meter)\nis below a \\config{convergenceThreshold} or \\config{maxIterationCount} is reached.\n\nWith \\config{computeResiduals} the observation equations are computed\nagain after each update to compute the observation residuals.\n\nThe overall standard deviation of a single observation used for the weighting\nis composed of several factors\n\\begin{equation}\n  \\hat{\\sigma}_i = \\hat{\\sigma}_i^{huber} \\hat{\\sigma}^{stat} \\sigma_{apriori}^{stat},\n\\end{equation} where the $\\sigma_{apriori}^{stat}$ is given by \\configClass{station}{slrStationGeneratorType}:accuracy.\nThe other factors are estimated iteratively from the residuals.\n\nWith \\config{computeWeights} a standardized variance $\\hat{s}_i^2$\nfor each residual $\\hat{\\epsilon}_i$ is computed\n\\begin{equation}\n  \\hat{s}_i^2 = \\frac{1}{\\hat{\\sigma}^{stat} \\sigma_{apriori}^{stat}}\\frac{\\hat{\\epsilon}_i^2}{r_i}\n  \\qquad\\text{with}\\qquad\n  r_i = \\left(\\M A\\left(\\M A^T\\M A\\right)^{-1}\\M A^T\\right)_{ii}\n\\end{equation}\ntaking the redundancy $r_i$ into account. If $\\hat{s}_i$ is above a threshold \\config{huber}\nthe observation gets a higher standard deviation used for weighting according to\n\\begin{equation}\n  \\hat{\\sigma}_i^{huber} =\n  \\left\\{ \\begin{array}{ll}\n    1                              & s < huber,\\\\\n    (\\hat{s}_i/huber)^{huberPower} & s \\ge huber\n  \\end{array} \\right.,\n\\end{equation}\nsimilar to \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\nWith \\config{adjustSigma0} an individual variance factor can be computed for each station separately\n\\begin{equation}\n  \\hat{\\sigma}^{stat} = \\sqrt{\\frac{\\hat{\\M\\epsilon}^T\\M P\\hat{\\M\\epsilon}}{r}}.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeResiduals & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~adjustSigma0 & \\hfuzz=500pt boolean & \\hfuzz=500pt adjust sigma0 by scale factor (per station)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeWeights & \\hfuzz=500pt boolean & \\hfuzz=500pt downweight outliers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}huberPower*sigma0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~convergenceThreshold & \\hfuzz=500pt double & \\hfuzz=500pt [m] stop iteration once full convergence is reached\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxIterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt maximum number of iterations\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteResults}\\label{slrProcessingStepType:writeResults}\nIn this step all \\config{outputfiles} defined in \\configClass{parametrizations}{slrParametrizationType}\nare written. It considers the settings of\n\\configClass{processingStep:selectParametrizations}{slrProcessingStepType:selectParametrizations}\nand \\configClass{processingStep:selectStations}{slrProcessingStepType:selectStations}.\n\nIt is usually the last processing step, but can also be used at other points in the\nprocessing in combination with \\config{suffix} to write intermediate results.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~suffix & \\hfuzz=500pt string & \\hfuzz=500pt appended to every output file name (e.g. orbit.G01.suffix.dat)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteNormalEquations}\\label{slrProcessingStepType:writeNormalEquations}\nAccumulates the normal equations matrix and writes it.\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written to the normal equations\nand all other parameters are eliminated beforehand (implicitly solved).\n\nThe solution of the normals would results in $\\Delta\\M x$\n(see \\configClass{parametrizations}{slrParametrizationType}). To write the\nappropriate apriori vector $\\M x_0$ use\n\\configClass{processingStep:writeAprioriSolution}{slrProcessingStepType:writeAprioriSolution}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquations & \\hfuzz=500pt filename & \\hfuzz=500pt normals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~remainingParameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of output normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~constraintsOnly & \\hfuzz=500pt boolean & \\hfuzz=500pt write only normals of constraints without observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultNormalsBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block, empty: original block size\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteAprioriSolution}\\label{slrProcessingStepType:writeAprioriSolution}\nWrites the current apriori vector $\\M x_0$\n(see \\configClass{parametrizations}{slrParametrizationType}).\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAprioriSolution & \\hfuzz=500pt filename & \\hfuzz=500pt a priori parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt parameter names\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~remainingParameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of output normal equations\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteResiduals}\\label{slrProcessingStepType:writeResiduals}\nWrites the \\file{observation residuals}{instrument} for all\n\\configClass{selectStations}{platformSelectorType}. For for each station-satellite\npair a file is written. The file name is interpreted as a template with\nthe variables \\verb|{station}| and \\verb|{satellite}| being replaced by the station name.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used satellites\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteUsedStationList}\\label{slrProcessingStepType:writeUsedStationList}\nWrites a \\file{list}{stringList} of stations (stations) which are used in the last step and\nselected by \\configClass{selectStations}{platformSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileUsedStationList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with names of used stations\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{WriteUsedSatelliteList}\\label{slrProcessingStepType:writeUsedSatelliteList}\nWrites a \\file{list}{stringList} of satellites which are used in the last step and\nselected by \\configClass{selectSatellites}{platformSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt subset of used satellites\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileUsedSatelliteList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with names\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PrintResidualStatistics}\\label{slrProcessingStepType:printResidualStatistics}\nPrint residual statistics.\n\\begin{verbatim}\n  station   sigma redundancy obsCount outlier\n  ----------------------------------------------\n  1874       0.52   0.86      22      1 (4.55 %)\n  1889       1.20   0.98     186      5 (2.69 %)\n  1890       0.63   0.77      14      1 (7.14 %)\n  1891       0.49   0.50       6      0 (0.00 %)\n  7237       1.08   0.95     236     14 (5.93 %)\n  7394       0.36   0.88      26      0 (0.00 %)\n  7811       0.38   0.41       5      0 (0.00 %)\n  7819       1.21   0.94     120      1 (0.83 %)\n  7821       0.69   0.95     202      3 (1.49 %)\n  7827       0.40   0.85      29      1 (3.45 %)\n  7839       0.52   0.93     143     10 (6.99 %)\n  7840       0.15   0.80      16      0 (0.00 %)\n  7841       0.26   0.90      56      1 (1.79 %)\n  7941       0.55   0.92     277      5 (1.81 %)\n  8834       0.66   0.88     101      1 (0.99 %)\n  ----------------------------------------------\n  satellite sigma redundancy obsCount outlier\n  ----------------------------------------------\n  lageos1    1.04   0.94     722     24 (3.32 %)\n  lageos2    0.91   0.95     590     11 (1.86 %)\n  etalon1    1.19   0.78      57      2 (3.51 %)\n  etalon2    1.10   0.81      70      6 (8.57 %)\n  ----------------------------------------------\n\\end{verbatim}\n\n\n\\subsection{SelectParametrizations}\\label{slrProcessingStepType:selectParametrizations}\nEnable/disable parameter groups and constraint groups for subsequent steps,\ne.g. \\configClass{processingStep:estimate}{slrProcessingStepType:estimate} or\n\\configClass{processingStep:writeResults}{slrProcessingStepType:writeResults}.\nThe \\config{name} and \\config{nameConstraint} of these groups\nare defined in \\configClass{parametrizations}{slrParametrizationType}.\nPrior models or previously estimated parameters used as new apriori $\\M x_0$ values are unaffected\nand they are always reduced from the observations. This means all unselected parameters are kept fixed\nto their last result.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~enable & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~disable & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt wildcards: * and ?\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SelectSatellites}\\label{slrProcessingStepType:selectSatellites}\nThis step can be used to process only a subset of satellites in subsequent processing steps.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectSatellites & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SelectStations}\\label{slrProcessingStepType:selectStations}\nThis step can be used to process only a subset of stations in subsequent processing steps.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~selectStations & \\hfuzz=500pt \\hyperref[platformSelectorType]{platformSelector} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{slrProcessingStepType:group}\nPerform these processing steps. This step can be used to structure complex processing flows.\nThe \\configClass{select..}{slrProcessingStepType:selectParametrizations} processing steps\ndefined within a group only affect the steps within this group.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~processingStep & \\hfuzz=500pt \\hyperref[slrProcessingStepType]{slrProcessingStep} & \\hfuzz=500pt steps are processed consecutively\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SlrSatelliteGenerator}\\label{slrSatelliteGeneratorType}\nDefinition and basic information of SLR satellites.\n\nSee also \\program{SlrProcessing}.\n\n\n\\subsection{Satellites}\\label{slrSatelliteGeneratorType:satellites}\nA list of satellite names must be provided via \\configFile{inputfileSatelliteList}{stringList}.\nThe other input files are read for each satellite, where the file name is interpreted as a template\nwith the variable \\verb|{satellite}| being replaced by the satellite name from list.\nThe \\configFile{inputfileSatelliteInfo}{platform} contains information about laser retro-reflector,\noptical reference point, retro-reflector orientation, range corrections and center of mass.\nIt can be created via \\program{PlatformCreate}.\nIf \\configFile{inputfileAttitude}{instrument} ist not provided an orbit reference frame\n(along, cross, nearly nadir) is assumed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with satellite names, used to loop variable \\{satellite\\}\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteInfo & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAttitude & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for orbit interpolation and velocity calculation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SlrStationGenerator}\\label{slrStationGeneratorType}\nDefinition and basic information of SLR ground stations.\n\nSee also \\program{SlrProcessing}.\n\n\n\\subsection{Stations}\\label{slrStationGeneratorType:stations}\nA list of station names must be provided via \\configFile{inputfileStationList}{stringList}.\nIt defines the variable \\verb|{station}| for the station specific input files.\nThe \\configFile{inputfileStationInfo}{platform} contains metadata information like station number,\nstation name and approximate station postion in terrestrial reference frame (TRF)\nconsidering the station eccentricities. They can be created via \\program{SinexEccentricties2SlrPlatform}\nor \\program{PlatformCreate}. The \\configFile{inputfileObservations}{instrument} are separate files\nfor each \\verb|{station}|-\\verb|{satellite}| pair. They can be converted from CRD\nformat via \\program{Crd2NormalPoints}, CSTG format via \\program{Cstg2NormalPoints}\nand MERIT II format via \\program{Merit2NormalPoints} and \\program{Merit2FullRate}.\n\nThe apriori observation weighting is defined by the expression \\config{accuracy} in $[m]$.\nThe following variables are defined for each observation from the\n\\configFile{inputfileObservations}{instrument}: \\verb|{residual}|, \\verb|{accuracy}|,\n\\verb|{redundancy}|, \\verb|{laserWavelength}|, \\verb|{azimut}|, \\verb|{elevation}|.\nObservations with non-positive accuracies are removed.\nThis can be used for a rough outlier removal by an expression such as\n\\config{accuracy} = \\verb|if(abs(residual)>30, NAN, accuracy)|.\n\nThe effects of loading and tidal deformation on station positions can be corrected for\nvia \\configClass{loadingDisplacement}{gravityfieldType} and\n\\configClass{tidalDisplacement}{tidesType}, respectively.\nTidal deformations typically include:\n\\begin{itemize}\n  \\item \\configClass{earthTide}{tidesType:earthTide}: Earth tidal deformations (IERS conventions)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tidal deformations\n        (e.g. fes2014b\\_n720, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: atmospheric tidal deformation\n        (e.g. AOD1B RL06, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{poleTide}{tidesType:poleTide}: pole tidal deformations (IERS conventions)\n  \\item \\configClass{poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tidal deformations (IERS conventions)\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationList & \\hfuzz=500pt filename & \\hfuzz=500pt ascii file with station names\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt station metadata\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStationPosition & \\hfuzz=500pt filename & \\hfuzz=500pt station position\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~disableStationWithoutPosition & \\hfuzz=500pt boolean & \\hfuzz=500pt drop stations without apriori position\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileObservations & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} \\{satellite\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~accuracy & \\hfuzz=500pt expression & \\hfuzz=500pt [m] used for weighting, variables: \\{residual\\}, \\{accuracy\\}, \\{redundancy\\}, \\{laserWavelength\\}, \\{azimut\\}, \\{elevation\\}\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~loadingDisplacement & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt loading deformation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~tidalDisplacement & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt tidal deformation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt for tidal deformation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDeformationLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfilePotentialLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt if full potential is given and not only loading potential\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~elevationCutOff & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] ignore observations below cutoff\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for position interpolation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SphericalHarmonicsFilter}\\label{sphericalHarmonicsFilterType}\nFiltering of a spherical harmonics expansion.\n\n\n\\subsection{DDK}\nOrderwise filtering with the DDK filter by Kusche et al. 2009.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~level & \\hfuzz=500pt uint & \\hfuzz=500pt DDK filter level (1, 2, 3, ..., 8)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Gauss}\nFiltering the spherical harmonics expansion with a Gaussian filter.\n\\config{radius} gives the filter radius on the Earth surface in km.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~radius & \\hfuzz=500pt double & \\hfuzz=500pt filter radius [km]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Matrix}\nFiltering the spherical harmonics expansion with a matrix filter.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt of matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme of the matrix\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SphericalHarmonicsNumbering}\\label{sphericalHarmonicsNumberingType}\nThis class organizes the numbering scheme of spherical harmonics coefficients\nin a parameter vector (e.g \\program{Gravityfield2SphericalHarmonicsVector} and the design matrix of\n\\configClass{parametrizationGravity:sphericalHarmoncis}{parametrizationGravityType:sphericalHarmonics}.\n\n\n\\subsection{Degree}\nNumbering degree by degree:\n\\[ c20, c21, s21, c22, s22, c30, c31, s31, c32, s32,\\ldots \\]\n\n\n\\subsection{Order}\nNumbering order by order:\n\\[ c20, c30, c40, \\ldots, c21, s21, c31, s31, \\ldots, c22, s22 \\]\n\n\n\\subsection{OrderNonAlternating}\nNumbering order by order with cnm, snm non-alternating:\n\\[ c20, c30, c40, \\ldots, c21, c31, c41, \\ldots, s21, s31, s41, \\]\n\n\n\\subsection{File}\nNumbering as specified in the chosen file.\nThe \\configFile{inputfile}{matrix} is a matrix with the first column indicating cnm/snm with 0 or 1.\nThe second and third column specify degree and order.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{SstRightSide}\\label{sstRightSideType}\nObservation vector for GRACE like data (satellite-tracking and precise orbit data (POD))\nof \\configClass{observation}{observationType} equations in a least squares adjustment.\nThe observations are reduced by the effect of \\configFile{inputfileAccelerometer}{instrument}\nand \\configClass{forces}{forcesType} (observed minus computed).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sstRightSideType & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite A as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite B as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileAccelerometer1 & \\hfuzz=500pt filename & \\hfuzz=500pt non-gravitational forces in satellite reference frame A\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileAccelerometer2 & \\hfuzz=500pt filename & \\hfuzz=500pt non-gravitational forces in satellite reference frame B\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~forces & \\hfuzz=500pt \\hyperref[forcesType]{forces} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Thermosphere}\\label{thermosphereType}\nThis class provides functions for calculating the density, temperature and velocity\nin the thermosphere.\nThe wind is computed by HWM14 model if \\config{hwm14DataDirectory} is provided.\nA quiet thermosphere is assumed if \\config{inputfileMagnetic3hAp} is not given.\n\n\n\\subsection{JB2008}\nThermosphere parameters from the JB2008 model:\n\nBowman, B. R., Tobiska, W. K., Marcos, F. A., Huang, C. Y., Lin, C. S., Burke, W. J. (2008).\nA new empirical thermospheric density model JB2008 using new solar and geomagnetic indices.\n In AIAA/AAS Astrodynamics Specialist Conference and Exhibit. \\url{https://doi.org/10.2514/6.2008-6438}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSolfsmy & \\hfuzz=500pt filename & \\hfuzz=500pt solar indices\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDtc & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileMagnetic3hAp & \\hfuzz=500pt filename & \\hfuzz=500pt indicies for wind model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~hwm14DataDirectory & \\hfuzz=500pt filename & \\hfuzz=500pt directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{NRLMSIS2}\nThermosphere parameters from the NRLMSIS2 model:\n\nEmmert J.D, D.P.Drob, J.M. Picone, et al. (2020), NRLMSIS 2.0: A whole-atmosphere empirical\nmodel of temperature and neutral species densities. Earth and Space Science, Volume 8, 3\n\\url{https://doi.org/10.1029/2020EA001321}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMsis & \\hfuzz=500pt filename & \\hfuzz=500pt input NRLMSIS 2.0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileModelParameters & \\hfuzz=500pt filename & \\hfuzz=500pt path to msis20.parm file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileMagnetic3hAp & \\hfuzz=500pt filename & \\hfuzz=500pt indicies for wind model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~hwm14DataDirectory & \\hfuzz=500pt filename & \\hfuzz=500pt directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Tides}\\label{tidesType}\nThis class computes functionals of the time depending tide potential,\ne.g potential, acceleration or gravity gradients.\n\nIf several instances of the class are given the results are summed up.\nBefore summation every single result is multiplicated by a \\config{factor}.\nTo get the difference between two ocean tide models you must choose one factor by 1\nand the other by -1. To get the mean of two models just set each factor to 0.5.\n\n\n\\subsection{AstronomicalTide}\\label{tidesType:astronomicalTide}\nThis class computes the tide generating potential (TGP) of sun, moon\nand planets (Mercury, Venus, Mars, Jupiter, Saturn).\nIt takes into account the flattening of the Earth (At the moment only at the acceleration level).\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useMoon & \\hfuzz=500pt boolean & \\hfuzz=500pt TGP of moon\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useSun & \\hfuzz=500pt boolean & \\hfuzz=500pt TGP of sun\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~usePlanets & \\hfuzz=500pt boolean & \\hfuzz=500pt TGP of planets\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useEarth & \\hfuzz=500pt boolean & \\hfuzz=500pt TGP of Earth\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~c20Earth & \\hfuzz=500pt double & \\hfuzz=500pt J2 flattening of the Earth\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EarthTide}\\label{tidesType:earthTide}\nThis class computes the earth tide according to the IERS2003 conventions.\nThe values of solid Earth tide external potential Love numbers and\nthe frequency dependent corrections of these values are given in the file\n\\configFile{inputfileEarthtide}{earthTide}. The effect of the permanent tide is removed if\n\\config{includePermanentTide} is set to false.\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileEarthtide & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~includePermanentTide & \\hfuzz=500pt boolean & \\hfuzz=500pt results in FALSE: zero tide, TRUE: tide free gravity field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{PoleTide}\\label{tidesType:poleTide}\nThe potential coefficients of the solid Earth pole tide according to the\nIERS2003 conventions are given by\n\\begin{equation}\n\\begin{split}\n\\Delta c_{21} &= s\\cdot(m_1 + o\\cdot m_2), \\\\\n\\Delta s_{21} &= s\\cdot(m_2 - o\\cdot m_1),\n\\end{split}\n\\end{equation}\nwith $s$ is the \\config{scale}, $o$ is the \\config{outPhase} and\n$(m_1,m_2)$ are the wobble variables in seconds of arc.\nThey are related to the polar motion variables $(x_p,y_p)$ according to\n\\begin{equation}\n\\begin{split}\nm_1 &=  (x_p - \\bar{x}_p), \\\\\nm_2 &= -(y_p - \\bar{y}_p),\n\\end{split}\n\\end{equation}\nThe mean pole $(\\bar{x}_p, \\bar{y}_p)$ is approximated by a polynomial\nread from \\configFile{inputfileMeanPole}{meanPolarMotion}.\n\nThe displacment is calculated with\n\\begin{equation}\n\\begin{split}\nS_r          &= -v\\sin2\\vartheta(m_1\\cos\\lambda+m_2\\sin\\lambda),\\\\\nS_\\vartheta &= -h\\cos2\\vartheta(m_1\\cos\\lambda+m_2\\sin\\lambda),\\\\\nS_\\lambda   &=  h\\cos\\vartheta(m_1\\sin\\lambda-m_2\\cos\\lambda),\n\\end{split}\n\\end{equation}\nwhere $h$ is the \\config{horizontalDisplacement}\nand $v$ is the \\config{verticalDisplacement}.\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~scale & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outPhase & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMeanPole & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~horizontalDisplacement & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~verticalDisplacement & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{OceanPoleTide}\\label{tidesType:oceanPoleTide}\nThe ocean pole tide is generated by the centrifugal effect of polar motion on the oceans.\nThe potential coefficients of this effect is given by\nIERS2003 conventions are given by\n\\begin{equation}\n\\begin{Bmatrix}\n\\Delta c_{nm}  \\\\\n\\Delta s_{nm}\n\\end{Bmatrix}=\n\\begin{Bmatrix}\nc_{nm}^R  \\\\\ns_{nm}^R\n\\end{Bmatrix}\n(m_1\\gamma^R+m_2\\gamma^I)+\n\\begin{Bmatrix}\nc_{nm}^I  \\\\\ns_{nm}^I\n\\end{Bmatrix}\n(m_2\\gamma^R-m_1\\gamma^I)\n\\end{equation}\nwhere the coefficients are read from file \\configFile{inputfileOceanPole}{oceanPoleTide},\n$\\gamma=\\gamma^R+i\\gamma^I$ is given by \\config{gammaReal} and\n\\config{gammaImaginary} and $(m_1,m_2)$ are the wobble variables in radians.\nThey are related to the polar motion variables $(x_p,y_p)$ according to\n\\begin{equation}\n\\begin{split}\nm_1 &=  (x_p - \\bar{x}_p), \\\\\nm_2 &= -(y_p - \\bar{y}_p),\n\\end{split}\n\\end{equation}\nThe mean pole $(\\bar{x}_p, \\bar{y}_p)$ is approximated by a polynomial\nread from \\configFile{inputfileMeanPole}{meanPolarMotion}.\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOceanPole & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gammaReal & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gammaImaginary & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMeanPole & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{DoodsonHarmonicTide}\\label{tidesType:doodsonHarmonicTide}\nThe time variable potential of ocean tides is given by a fourier expansion\n\\begin{equation}\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\Theta_f(t)) + V_f^s(\\M x)\\sin(\\Theta_f(t)),\n\\end{equation}\nwhere $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics expansions and are\nread from the file \\configFile{inputfileDoodsonHarmonic}{doodsonHarmonic}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\n$\\Theta_f(t)$ are the arguments of the tide constituents~$f$:\n\\begin{equation}\n\\Theta_f(t) = \\sum_{i=1}^6 n_f^i\\beta_i(t),\n\\end{equation}\nwhere $\\beta_i(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$)\nand $n_f^i$ are the Doodson multipliers for the term at frequency~$f$.\n\nThe major constituents given by \\configFile{inputfileDoodsonHarmonic}{doodsonHarmonic} can be used to\ninterpolate minor tidal constituents using the file \\configFile{inputfileAdmittance}{admittance}.\nThis file can be created with \\program{DoodsonHarmonicsCalculateAdmittance}.\n\nAfter the interpolation step a selection of the computed constituents can be\nchoosen by \\configClass{selectDoodson}{doodson}. Only these constiuents are considered for the results.\nIf no \\configClass{selectDoodson}{doodson} is set all constituents will be used. The constituents can\nbe coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2).\n\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTides & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt interpolation of minor constituents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~selectDoodson & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt consider only these constituents, code number (e.g. 255.555) or darwin name (e.g. M2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nodeCorr & \\hfuzz=500pt uint & \\hfuzz=500pt nodal corrections: 0-no corr, 1-IHO, 2-Schureman\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Centrifugal}\\label{tidesType:centrifugal}\nComputes the centrifugal potential in a rotating system\n\\begin{equation}\nV(\\M r, t) = \\frac{1}{2} (\\M\\omega(t)\\times\\M r)^2.\n\\end{equation}\nThe current rotation vector $\\M\\omega(t)$ is computed from the\n\\configClass{earthRotation}{earthRotationType}\nprovided by the calling program.\nThe computed result is multiplied with \\config{factor}.\n\nBe careful, the centrifugal potential is not harmonic.\nConvolution with a harmonic kernel (e.g. to compute gravity\nanomalies) is not meaningful.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{SolidMoonTide}\nThis class computes the solid moon tide according to the IERS2010 conventions.\nThe values of solid Moon tide external potential Love numbers are given and\nthere are no frequency dependent corrections of these values.\nThe computed result is multiplied with \\config{factor}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~k20 & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~k30 & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Group}\\label{tidesType:group}\nGroups a set of \\configClass{tides}{tidesType} and has no further effect itself.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~tides & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{TimeSeries}\\label{timeSeriesType}\nThis class generates a series of points in time. The series is always sorted in ascending order.\nDepending of the application the series is interpreted as list of points or as intervals between the points.\n\n\\fig{!hb}{0.4}{timeSeriesIntervals}{fig:timeSeriesIntervals}{List of points $t_i$ vs. intervals $T_i$.}\n\n\n\\subsection{UniformSampling}\\label{timeSeriesType:uniformSampling}\nGenerates a time series with uniform sampling. The first point in time will be \\config{timeStart}.\nThe last generated point in time will be less or equal \\config{timeEnd}.\nThe time step between generated points in time is given by \\config{sampling}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt first point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt last point in time will be less or equal timeEnd\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sampling & \\hfuzz=500pt time & \\hfuzz=500pt time step between points in time\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{UniformInterval}\nGenerates a time series with uniform sampling between \\config{timeStart} and \\config{timeEnd}.\n\\config{intervallCount} gives the count of intervals. This class generates count+1 points in time\ninclusive \\config{timeStart} and \\config{timeEnd}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt 1st point of the time series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt last point of the time series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~intervalCount & \\hfuzz=500pt uint & \\hfuzz=500pt count of intervals, count+1 points in time will generated\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Irregular}\\label{timeSeriesType:irregular}\nThe points of the time series are given explicitly with \\config{time}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt explicit list of points in time\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Monthly}\nIf \\config{useMonthMiddle} is set, time points are generated at mid of each month inclusively\nthe \\config{monthStart} in \\config{yearStart} and \\config{monthEnd} in \\config{yearEnd}.\nOtherwise times are given at the first of each month and a time point after the last month.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~monthStart & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~yearStart & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~monthEnd & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~yearEnd & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useMonthMiddle & \\hfuzz=500pt boolean & \\hfuzz=500pt time points are mid of months, otherwise the 1st of each month + a time point behind the last month\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Yearly}\nIf \\config{useYearMiddle} is set, time points are generated at mid of each year inclusively \\config{yearStart}\nand \\config{yearEnd}. Otherwise times are given at the first of each year and a time point after the last year.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~yearStart & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~yearEnd & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useYearMiddle & \\hfuzz=500pt boolean & \\hfuzz=500pt time points are mid of years, otherwise the 1st of each year + a time point behind the last year\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EveryMonth}\nGenerates a time series with monthly sampling. The first point in time will be \\config{timeStart} and the following\npoints are generated for each month at the same day and time in month.\nThe last generated point in time will be less or equal \\config{timeEnd}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt first point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt last point in time will be less or equal timeEnd\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{EveryYear}\nGenerates a time series with yearly sampling. The first point in time will be \\config{timeStart} and the following\npoints are generated for each year at the same day and time in year.\nThe last generated point in time will be less or equal \\config{timeEnd}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt first point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt last point in time will be less or equal timeEnd\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Instrument}\\label{timeSeriesType:instrument}\nRead a time series (epochs) from an \\file{instrument file}{instrument}.\nThe time series can be restricted to the interval\nstarting from \\config{timeStart} and before \\config{timeEnd}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt inclusive, i.e. exclude eochs before this epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt exclusive, i.e. only epochs before this time are used\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{InstrumentArcIntervals}\nReconstruct a time series from an \\file{instrument file}{instrument}.\nThe time series is the first epoch of each arc plus one time step beyond the last\nepoch of the last arc (using median sampling).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt Must be regular. Time series is first epoch of each arc plus one time step extrapolated from last epoch of last arc.\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Revolution}\nReads an \\file{orbit file}{instrument} and create a time stamp for each ascending equator crossing.\nThe time series can be restricted to the interval\nstarting from \\config{timeStart} and before \\config{timeEnd}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt exclude eochs before this epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt only epochs before this time are used\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Exclude}\nIn a first step a \\configClass{timeSeries}{timeSeriesType} is generated.\nIn a second step all times are removed which are in range before or after \\config{excludeMargin} seconds\nof the times given by \\configClass{timeSeriesExclude}{timeSeriesType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt time series to be created\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeriesExclude & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt exclude this time points from time series (within margin)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~excludeMargin & \\hfuzz=500pt double & \\hfuzz=500pt on both sides [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Conditional}\nOnly times for which the \\configClass{condition}{conditionType} is met are included in the time series.\nThe \\config{variableLoopTime} is set to every time and the \\configClass{condition}{conditionType} is evaluated.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt only times for which condition is met will be included\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTime & \\hfuzz=500pt string & \\hfuzz=500pt variable with time of each loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt test for each time\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{Interpolate}\nInterpolates \\config{nodeInterpolation} count points between\nthe given \\configClass{timeSeries}{timeSeriesType} uniformly.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt time series to be created\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~nodeInterpolation & \\hfuzz=500pt uint & \\hfuzz=500pt interpolates count points in each time interval given by the time series\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\n\\section{Troposphere}\\label{troposphereType}\nThis class provides functions for calculating and estimating\nthe signal delay in the dry and wet atmosphere.\n\n\n\\subsection{ViennaMapping}\\label{troposphereType:viennaMapping}\n\nTropospheric delays based on the Vienna Mapping Functions 3 (VMF3) model\n(Landskron and Boehm 2017, DOI: \\href{https://doi.org/10.1007/s00190-017-1066-2}{10.1007/s00190-017-1066-2}).\n\nHydrostatic and wet mapping function coefficients ($a_h$, $a_w$) and zenith delays (ZHD, ZWD) have to be provided\nvia \\configFile{inputfileVmfCoefficients}{griddedDataTimeSeries}. This file can contain either station-specific data\n(see \\program{ViennaMappingFunctionStation2File}) or data on a regular global grid\n(see \\program{ViennaMappingFunctionGrid2File}). In the second case mapping coefficients and zenith delays are\ninterpolated to the requested coordinates. This includes a height correction that requires approximate meteorological\ndata provided via \\configFile{inputfileGpt}{griddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileVmfCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt ah, aw, zhd, zwd coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGpt & \\hfuzz=500pt filename & \\hfuzz=500pt gridded GPT data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~aHeight & \\hfuzz=500pt double & \\hfuzz=500pt parameter a (height correction)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~bHeight & \\hfuzz=500pt double & \\hfuzz=500pt parameter b (height correction)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~cHeight & \\hfuzz=500pt double & \\hfuzz=500pt parameter c (height correction)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{GPT}\\label{troposphereType:gpt}\n\nTropospheric delays based on the Global Pressure and Temperature 3 (GPT3) model\n(Landskron and Boehm 2017, DOI: \\href{https://doi.org/10.1007/s00190-017-1066-2}{10.1007/s00190-017-1066-2}).\n\nIt is an empirical model derived from the Vienna Mapping Functions 3\n(VMF3, see \\configClass{viennaMapping}{troposphereType:viennaMapping}) and thus does not require\nadditional mapping coefficients and zenith delay values.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGpt & \\hfuzz=500pt filename & \\hfuzz=500pt gridded GPT data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~aHeight & \\hfuzz=500pt double & \\hfuzz=500pt parameter a (height correction)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~bHeight & \\hfuzz=500pt double & \\hfuzz=500pt parameter b (height correction)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~cHeight & \\hfuzz=500pt double & \\hfuzz=500pt parameter c (height correction)\\\\\n\\hline\n\\end{tabularx}\n\n\n\\subsection{MendesAndPavlis}\\label{troposphereType:mendesAndPavlis}\n\nTropospheric delays based on the Mendes-Pavlis model that employs meteorological data.\n(Mendes et al. (2002), \\href{https://doi.org/10.1029/2001GL014394}{10.1029/2001GL014394} and\nMendes and Pavlis (2004), \\href{https://doi.org/10.1029/2004GL020308}{110.1029/2004GL020308})\n\nThe meteorological data have to be provided via \\configFile{inputfileStationMeteorology}{instrument}.\nThis file contains the temperature, air pressure and humidity and must be first generated using the\nprograms \\program{Crd2NormalPoints}, \\program{Cstg2NormalPoints}, \\program{Merit2NormalPoints} or \\program{Merit2FullRate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationMeteorology & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n"
  },
  {
    "path": "docs/latex/cookbook.gnssNetwork.tex",
    "content": "\\section{GNSS satellite orbit determination and station network analysis}\\label{cookbook.gnssNetwork}\nThis cookbook chapter describes an example of global GNSS processing as done by analysis centers of the\nInternational GNSS Service (IGS). Resulting products usually comprise:\n\\begin{itemize}\n  \\item Satellite orbits, clocks, and signal biases\n  \\item Station positions, clocks, signal biases, and troposphere estimates\n  \\item Earth orientation parameters\n\\end{itemize}\n\nScientific details about the underlying processing approach and the applied parametrizations, models, and corrections\ncan be found in a doctoral thesis available under DOI \\href{https://doi.org/10.3217/978-3-85125-885-1}{10.3217/978-3-85125-885-1}.\n\nAn example scenario for this task is available at \\url{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip}.\nIt includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at \\url{https://ftp.tugraz.at/pub/ITSG/groops} (data folder or zipped archive).\nThe scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.\n\n\\emph{Note: Global GNSS processing can become very computationally intensive. Depending on the number of satellites\nand stations, the observation and processing sampling, and parametrizations it can quickly exceed the capabilities\nof a normal desktop computer and may require computer clusters or number crunchers (see section}\n\\reference{Parallelization}{general.parallelization}\\emph{).}\n\n\\subsection{Data preparation}\\label{cookbook.gnssNetwork:metadata}\nMost of the required metadata files are provided in GROOPS file formats at \\url{https://ftp.tugraz.at/pub/ITSG/groops}.\nThese files are regularly updated.\n\nData that has to be gathered from other sources comprises:\n\\begin{itemize}\n  \\item \\textbf{Receiver observations}: GNSS measurements converted from RINEX format (see \\program{RinexObservation2GnssReceiver}).\n  \\item \\textbf{Approximate orbits}: broadcast or precise orbits in CRF for orbit integration (see \\program{GnssRinexNavigation2OrbitClock} or \\program{Sp3Format2Orbit}).\n  \\item \\textbf{Approximate clocks}: broadcast or precise clocks (see \\program{GnssRinexNavigation2OrbitClock} or \\program{GnssClockRinex2InstrumentClock})\n\\end{itemize}\nReceiver observations, broadcast ephemerides, and precise satellite orbits and clocks can be downloaded from the\n\\href{https://igs.org/data-products-overview/}{IGS Data Centers}.\nGPS, GLONASS, and Galileo orbits and clocks for the period 1994-2020 are also available as part of\n\\href{https://doi.org/10.3217/dataset-4528-0723-0867}{Graz University of Technology's contribution to IGS repro3}.\n\nThe \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip}{example scenario} includes a small set of this data.\nThe script \\verb|010groopsConvert.xml| can be used to convert these external formats into GROOPS formats.\n\nPrepare a \\file{station list file}{stringTable} that contains the stations to be processed.\nEach line can contain more than one station. The first station in each line that has data available is used for the processing.\nIf your network contains more than 60-70 stations, it is recommended to start processing with a core network (see \\reference{Advanced}{cookbook.gnssNetwork:advanced}).\nIn this case, define an additional \\file{core station list file}{stringTable} that can also have multiple stations per line.\n\n\\subsection{Preprocessing: Orbit integration}\\label{cookbook.gnssNetwork:orbitIntegration}\nNumerical integration of the satellite orbits is the first step in global GNSS processing.\nDynamic orbits are integrated based on \\configClass{force models}{forcesType} and then fitted to the approximate orbits\nby estimating their initial state and additional empirical parameters for solar radiation pressure to improve the orbit fit.\nThe resulting \\file{variational equations}{variationalEquation} file contains the integrated orbit, derivatives\nwith respect to the satellite state vector, attitude, Earth rotation and satellite model.\n\nOrbit preprocessing is covered by the script \\verb|020groopsGnssPreprocessing.xml| in the \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip}{example scenario}.\n\nIt is recommended to perform the steps below in a \\reference{loop}{general.loopsAndConditions} over all\nsatellites/PRNs using \\program{LoopPrograms}. To get the relation between \\verb|{prn}| and \\verb|{svn}| setup\nan additional \\configClass{loop:platformEquipment}{loopType:platformEquipment} inside\n\\configClass{loop:loop}{loopType:loop} with\n\\begin{itemize}\n  \\item \\configFile{inputfilePlatform}{platform}: the old \\config{inputfileTransmitterInfo}\n  \\item \\config{equipmentType}         = \\verb|gnssAntenna|\n  \\item \\config{variableLoopName}      = \\verb|block|\n  \\item \\config{variableLoopSerial}    = \\verb|svn|\n  \\item \\config{variableLoopTimeStart} = \\verb|svnTimeStart|\n  \\item \\config{variableLoopTimeEnd}   = \\verb|svnTimeEnd|\n  \\item \\configClass{condition:expression}{conditionType:expression}\n  \\begin{itemize}\n    \\item \\config{expression} = \\verb|(svnTimeStart <= loopTime) && (loopTime < svnTimeEnd)|\n  \\end{itemize}\n\\end{itemize}\nThis second loop should perform only one step. The following programs are looped over all \\verb|{prn}|:\n\\begin{itemize}\n  \\item \\program{InstrumentResample}: resample approximate orbits from \\reference{data preparation}{cookbook.gnssPpp:metadata} to target sampling (e.g., 1 minute) by defining a \\configClass{timeSeries}{timeSeriesType} based on a \\config{method:polynomial} (\\config{polynomialDegree}=\\verb|7|, \\config{maxDataPointRange}=\\verb|7200|, \\config{maxExtrapolationDistance}=\\verb|900|).\n  \\item \\program{OrbitAddVelocityAndAcceleration}: add velocity via running polynomial (\\config{polynomialDegree}=\\verb|2|) derivation (needed for attitude computation)\n  \\item \\program{SimulateStarCameraGnss}\n  \\item \\program{PreprocessingVariationalEquation}:\n        \\begin{itemize}\n          \\item \\configFile{inputfileSatelliteModel}{satelliteModel}=\\verb|{groopsDataDir}/gnss/transmitter/satelliteModel/satelliteModel_boxWing.{svn}.xml|\n          \\item \\configFile{inputfileOrbit}{instrument}: the resampled approximate orbit from \\program{InstrumentResample}\n          \\item \\configFile{inputfileStarCamera}{instrument}: the attitude file from \\program{SimulateStarCameraGnss}\n          \\item \\config{forces}: see below\n          \\item \\configClass{gradientfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}: a static gravity field (e.g. GOCO06s) with \\config{maxDegree}=\\verb|4|.\n        \\end{itemize}\n  \\item \\program{PreprocessingVariationalEquationOrbitFit}: fit the integrated orbit (\\configFile{inputfileVariational}{variationalEquation}) to the approximate orbit (\\configFile{inputfileOrbit}{instrument}) by least squares adjustment.\n        Add \\configClass{parametrizationAcceleration:gnssSolarRadiation}{parametrizationAccelerationType:gnssSolarRadiation}\n        and select the \\href{https://doi.org/10.1007/s00190-015-0814-4}{ECOM2} parameters to be estimated.\n\\end{itemize}\n\nForce models usually include:\n\\begin{itemize}\n  \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n        static gravity field (e.g. GOCO06s)\n  \\item \\configClass{gravityfield:trend}{gravityfieldType:trend}\n  \\begin{itemize}\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n          trend component of time-variable gravity field (e.g. GOCO06s)\n  \\end{itemize}\n  \\item \\configClass{gravityfield:oscillation}{gravityfieldType:oscillation}\n  \\begin{itemize}\n    \\item \\configClass{gravityfieldCos:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n          annual cosine component of time-variable gravity field (e.g. GOCO06s)\n    \\item \\configClass{gravityfieldSin:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n          annual sine component of time-variable gravity field (e.g. GOCO06s)\n  \\end{itemize}\n  \\item \\configClass{tides:astronomicalTide}{tidesType:astronomicalTide}: astronomical tides (e.g. based on JPL ephemeris)\n  \\item \\configClass{tides:earthTide}{tidesType:earthTide}: Earth tide (IERS conventions)\n  \\item \\configClass{tides:doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tides (e.g. FES 2014b)\n  \\item \\configClass{tides:poleTide}{tidesType:poleTide}: pole tides (IERS conventions)\n  \\item \\configClass{tides:poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tides (IERS conventions)\n  \\item \\configClass{miscAccelerations:solarRadiationPressure}{miscAccelerationsType:solarRadiationPressure}:\n        solar radiation pressure (box-wing model)\n  \\item \\configClass{miscAccelerations:albedo}{miscAccelerationsType:albedo}: Earth radiation pressure (albedo model)\n  \\item \\configClass{miscAccelerations:antennaThrust}{miscAccelerationsType:antennaThrust}:\n        antenna thrust (e.g. from IGS metadata SINEX file)\n  \\item \\configClass{miscAccelerations:relativisticEffect}{miscAccelerationsType:relativisticEffect}:\n        relativistic effects (IERS conventions)\n\\end{itemize}\nFor the spherical harmonics expansions a \\config{maxDegree}=\\verb|60| is more than enough.\n\nThe result of the preprocessing should be a \\file{variational equations file}{variationalEquation},\na \\file{reduced dynamic orbit file}{instrument} from \\program{PreprocessingVariationalEquationOrbitFit}\nand an \\file{attitude file}{instrument} from \\program{SimulateStarCameraGnss} for each satellite.\n\n\\subsection{GNSS processing}\\label{cookbook.gnssNetwork:processing}\nThe script \\verb|030groopsGnssProcessing.xml| in the \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssNetwork.zip}{example scenario}\nimplements the following steps and settings.\n\nThese are the settings for \\program{GnssProcessing}. If not otherwise stated use the default values.\n\nThe first step is setting the processing sampling, in this example it is 30~seconds.\nThe processing interval usually is a single 24-hour day, therefore define\n\\configClass{timeSeries:uniformSampling}{timeSeriesType:uniformSampling} with \\config{timeStart}=\\verb|<mjd>|,\n\\config{timeEnd}=\\verb|<mjd>+1|, \\config{sampling}=\\verb|30/86400| (processing sampling).\n\nAdd the appropriate \\configClass{transmitters:gnss}{gnssTransmitterGeneratorType:gnss} (e.g. GPS, GLONASS, and Galileo)\nand provide the required files:\n\\begin{itemize}\n  \\item \\configFile{inputfileOrbit}{instrument} from \\reference{preprocessing}{cookbook.gnssNetwork:orbitIntegration}\n  \\item \\configFile{inputfileAttitude}{instrument} from \\reference{preprocessing}{cookbook.gnssNetwork:orbitIntegration}\n  \\item \\configFile{inputfileClock}{instrument} from \\reference{data preparation}{cookbook.gnssPpp:metadata}\n\\end{itemize}\n\nThe following settings are needed in \\configClass{receiver:stationNetwork}{gnssReceiverGeneratorType:stationNetwork}:\n\\begin{itemize}\n   \\item \\configFile{inputfileStationList}{stringTable}: list of all stations to be processed\n   \\item \\configFile{inputfileObservations}{instrument}: The converted RINEX observation files.\n   \\item \\configClass{tidalDisplacement}{tidesType}: Use the settings described in \\reference{receiver:stationNetwork}{gnssReceiverGeneratorType:stationNetwork}.\n   \\item \\configClass{excludeType}{gnssType}: Signals you might want to exclude are \\verb|C*?G| (old unknown GPS code observations), \\verb|*3*R| (GLONASS G3 freq.), \\verb|*6*E| (Galileo E6 freq.).\n\\end{itemize}\n\nAdd the following \\configClass{parametrizations}{gnssParametrizationType}\nand define the \\config{outputfiles} you are interested in inside each of them:\n\\begin{itemize}\n  \\item \\configClass{ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}: add a constraint of \\config{sigmaSTEC}=\\verb|40|\n  \\item \\configClass{ionosphereMap}{gnssParametrizationType:ionosphereMap}: add \\configClass{temporal:splines}{parametrizationTemporalType:splines}\n        with linear (\\config{degree}=\\verb|1|) 2-hourly splines\n  \\item \\configClass{clocks}{gnssParametrizationType:clocks}: optionally change \\configClass{selectTransmitterZeroMeans}{platformSelectorType} to \\configClass{wildcard}{platformSelectorType:wildcard} with \\config{name}=\\verb|G*| to align clocks to mean over GPS (instead of all) satellites\n  \\item \\configClass{signalBiases}{gnssParametrizationType:signalBiases}\n  \\item \\configClass{ambiguities}{gnssParametrizationType:ambiguities}\n  \\item \\configClass{codeBiases}{gnssParametrizationType:codeBiases}\n  \\item \\configClass{tecBiases}{gnssParametrizationType:tecBiases}\n  \\item \\configClass{temporalBias}{gnssParametrizationType:temporalBias}: time-variable GPS L5 phase bias with \\configClass{type}{gnssType}=\\verb|L5*G|\n        and \\configClass{parametrizationTemporal:splines}{parametrizationTemporalType:splines} with degree 3 and hourly nodes.\n  \\item \\configClass{staticPositions}{gnssParametrizationType:staticPositions}\n  \\item \\configClass{troposphere}{gnssParametrizationType:troposphere}: select \\configClass{troposphere:viennaMapping}{troposphereType:viennaMapping}\n        with the appropriate vmf3grid file. Add \\configClass{troposphereWetEstimation:splines}{parametrizationTemporalType:splines}\n        with linear (\\config{degree}=\\verb|1|) 2-hourly splines\n        and \\configClass{troposphereGradientEstimation:splines}{parametrizationTemporalType:splines} with linear daily splines.\n  \\item \\configClass{transmitterDynamicOrbit}{gnssParametrizationType:transmitterDynamicOrbits}:\n        provide \\configFile{inputfileVariational}{variationalEquation}=\\verb|preprocessing/variational.{prn}.dat|\n        from the preprocessing step.\n        Add \\configClass{parametrizationAcceleration:gnssSolarRadiation}{parametrizationAccelerationType:gnssSolarRadiation} and\n        \\configClass{stochasticPulse:irregular}{timeSeriesType:irregular} parameter at center of day to further improve orbit fit.\n  \\item \\configClass{earthRotation}{gnssParametrizationType:earthRotation}\n        \\begin{itemize}\n          \\item \\configClass{estimatePole:constant}{parametrizationTemporalType:constant}: polar motion\n          \\item \\configClass{estimatePole:trend}{parametrizationTemporalType:trend} polar motion rate\n                (at center of day with \\config{timeStep}=\\verb|1|)\n          \\item \\configClass{estimateUT1:trend}{parametrizationTemporalType:trend}: length of day (at center of day with\n                \\config{timeStep}=\\verb|-1| to match IGS sign convention)\n        \\end{itemize}\n    \\item \\configClass{constraints}{gnssParametrizationType:constraints}: loose constraint on GPS L5 phase biases,\n        \\configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\\verb|signalBias.L5*|, \\config{sigma}=\\verb|5| meters, and \\config{relativeToApriori}=\\verb|yes|\n    \\item \\configClass{constraints}{gnssParametrizationType:constraints}: loose constraint troposphere estimates,\n        \\configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\\verb|troposphere*|, \\config{sigma}=\\verb|5| meters, and \\config{relativeToApriori}=\\verb|yes|\n    \\item \\configClass{constraints}{gnssParametrizationType:constraints}: constraint on stochastic pulses,\n        \\configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\\verb|stochasticPulse*|, \\config{sigma}=\\verb|0.1| micrometers/second.\n\\end{itemize}\n\nFinally, define the \\configClass{processingSteps}{gnssProcessingStepType}.\nThis can be overwhelming at first, but offers a lot of flexibility.\nThe example script uses a 5-minute processing sampling with subsequent clock densification to 30 seconds.\n\n\\begin{itemize}\n      \\item \\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \\config{nthEpoch}=\\verb|10| to reduce sampling to 5 minutes.\n      \\item \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:\n            disable \\verb|constraint.STEC|, \\verb|*VTEC|, \\verb|*.tecBiases| as the ionosphere parameters are estimated in the final steps only.\n      \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|6|\n      \\item \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}\n      \\item \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:\n            enable \\verb|*| (all) parameters\n      \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|4|: final iterations (with 5-minute sampling) and ionosphere parameters\n      \\item \\configClass{group}{gnssProcessingStepType:group}: clock densification to 30-second sampling\n      \\begin{itemize}\n            \\item \\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \\config{nthEpoch}=\\verb|1| to set full 30-second sampling\n            \\item \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:\n            disable \\verb|*| (all) parameters and reenable \\verb|*.clock*| and \\verb|*.STEC| parameters\n            \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|6|\n            \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}: with \\config{suffix}=\\verb|30s| to write 30-second clock files\n      \\end{itemize}\n      \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}: write the final results\n\\end{itemize}\n\nWith some additional steps, the full 30-second sampling can be used to estimate all parameters (not only the clocks).\nThese steps are disabled in the example script, as they require at least 16~GB of system memory.\nIn this case, it is not necessary to separately write the 30-second clock files as listed above.\n\n\\begin{itemize}\n      \\item \\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \\config{nthEpoch}=\\verb|1| to set full 30-second sampling\n      \\item \\configClass{selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure}: As the system of normal\n      equations can be very large, the memory consumption might be reduced with \\config{keepEpochNormalsinMemory}=\\verb|no|.\n      In this case the epoch parameters are directly eliminated during the accumulation and reconstructed in the solving step.\n      This might lead to longer computation times.\n      \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|2|: final iterations with full sampling\n\\end{itemize}\n\n\\subsection{Advanced: Processing large station networks}\\label{cookbook.gnssNetwork:advanced}\n\nProcessing large station networks requires some additional steps to keep the computational load to a reasonable degree.\nThe general processing strategy is to first process a well-distributed subset of stations (i.e. a core network)\nto get good estimates of all satellite parameters, which then enables integer ambiguity resolution (IAR). Once\nthe ambiguities of the core network are resolved and stable estimates for satellite phase biases are available, all\nother (non-core) stations can be processed individually (including IAR) while keeping the satellite parameters fixed.\nAt last, all stations can be processed together with all satellite parameters and ionosphere parameters.\n\nLet's start with the \\configClass{processingSteps}{gnssProcessingStepType} of the core network:\n\\begin{itemize}\n      \\item \\configClass{selectReceivers}{gnssProcessingStepType:selectReceivers} with \\configClass{selectReceivers:file}{platformSelectorType:file}\n      using the core network station list file from \\reference{data preparation}{cookbook.gnssPpp:metadata} as \\configFile{inputfileStringTable}{stringTable}.\n      \\item \\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \\config{nthEpoch}=\\verb|10| to reduce sampling to 5 minutes.\n      \\item \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:\n            disable \\verb|constraint.STEC|, \\verb|*VTEC|, \\verb|*.tecBiases| as the ionosphere parameters are estimated in the final steps only.\n      \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|6|\n      \\item \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}\n      \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|4|: final iterations (with 5-minute sampling)\n\\end{itemize}\n\nNow all other (non-core) stations can be processed separately:\n\\begin{itemize}\n      \\item \\configClass{forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately}:\n            with \\configClass{selectReceivers:file}{platformSelectorType:file} inside \\configClass{selectReceivers:exclude}{platformSelectorType:exclude}\n            using the station list from the core network above to process all non-core stations individually with fixed transmitter parameters\n      \\begin{itemize}\n      \\item \\configClass{processingStep:estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|6|\n      \\item \\configClass{processingStep:resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}\n      \\item \\configClass{processingStep:estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|4|\n      \\end{itemize}\n\\end{itemize}\n\nNext all stations are processed together with all parameters:\n\\begin{itemize}\n      \\item \\configClass{selectReceivers}{gnssProcessingStepType:selectReceivers}: with \\configClass{selectReceivers:all}{platformSelectorType:all}\n      \\item \\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \\config{nthEpoch}=\\verb|1| to set full 30-second sampling\n      \\item \\configClass{group}{gnssProcessingStepType:group}: clock densification to 30-second sampling\n      \\begin{itemize}\n            \\item \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:\n            disable \\verb|*| (all) parameters and reenable \\verb|*.clock*| and \\verb|*.STEC| parameters\n            \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|6|\n      \\end{itemize}\n      \\item \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}: enable \\verb|*| (all) parameters.\n      \\item \\configClass{selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure}: with \\config{keepEpochNormalsinMemory}=\\verb|no|\n      \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|4|: final iterations with full sampling and all parameters\n      \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}: write the final results\n\\end{itemize}\n\n% =============================================================\n"
  },
  {
    "path": "docs/latex/cookbook.gnssPpp.tex",
    "content": "\\section{GNSS precise point positioning (PPP)}\\label{cookbook.gnssPpp}\nThis cookbook chapter describes an example of GNSS precise point positioning (PPP) for a ground station using GPS, GLONASS, and Galileo.\nFor information on how to generate the GNSS products (orbits, clocks, signal biases, etc.) required for PPP,\nsee the cookbook \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork}.\n\nScientific details about the underlying processing approach and the applied parametrizations, models, and corrections\ncan be found in a doctoral thesis available under DOI \\href{https://doi.org/10.3217/978-3-85125-885-1}{10.3217/978-3-85125-885-1}.\n\nAn example scenario for this task is available at \\url{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip}.\nIt includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at \\url{https://ftp.tugraz.at/pub/ITSG/groops} (data folder or zipped archive).\nThe scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.\n\n\\subsection{Data preparation}\\label{cookbook.gnssPpp:metadata}\nMost of the required metadata files are provided in GROOPS file formats at \\url{https://ftp.tugraz.at/pub/ITSG/groops}.\nThese files are regularly updated.\n\nData that has to be gathered from other sources comprises:\n\\begin{itemize}\n  \\item \\textbf{Receiver observations}: GNSS measurements converted from RINEX format (see \\program{RinexObservation2GnssReceiver})\n  \\item \\textbf{Precise orbits}: precise orbits in CRF for orbit integration (see \\program{Sp3Format2Orbit})\n  \\item \\textbf{Precise clocks}: precise clocks (see \\program{GnssClockRinex2InstrumentClock})\n  \\item \\textbf{Attitude}: rotation from body frame to CRF (see \\program{SimulateStarCameraGnss} or \\program{GnssOrbex2StarCamera})\n  \\item \\textbf{Signal biases}: code (and phase) biases (see \\program{GnssSinexBias2SignalBias})\n\\end{itemize}\nReceiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the\n\\href{https://igs.org/data-products-overview/}{IGS Data Centers}.\nGPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of\n\\href{https://doi.org/10.3217/dataset-4528-0723-0867}{Graz University of Technology's contribution to IGS repro3}.\n\nThe \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip}{example scenario} includes a small set of this data.\nThe script \\verb|010groopsConvert.xml| can be used to convert these external formats into GROOPS formats.\n\nPrepare a \\file{station list file}{stringList} that contains the stations (one per line) to be processed.\n\n\\subsection{Processing of a ground station}\\label{cookbook.gnssPpp:processing}\nThe script \\verb|02groopsGnssProcessing.xml| in the \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGnssPPP.zip}{example scenario}\nimplements the following steps and settings.\n\nThese are the settings for \\program{GnssProcessing}. If not otherwise stated use the default values.\n\nThe first step is setting the processing sampling, in this example it is 30~seconds.\nThe processing interval usually is a single 24-hour day,\n\\configClass{timeSeries:uniformSampling}{timeSeriesType:uniformSampling} with \\config{timeStart}=\\verb|<mjd>|,\n\\config{timeEnd}=\\verb|<mjd>+1|, \\config{sampling}=\\verb|30/86400| (processing sampling).\n\nAdd the appropriate \\configClass{transmitters:gnss}{gnssTransmitterGeneratorType:gnss} (e.g. GPS, GLONASS, and Galileo)\nand provide the required files (from \\reference{Data preparation}{cookbook.gnssPpp:metadata}):\n\\begin{itemize}\n  \\item \\configFile{inputfileOrbit}{instrument}\n  \\item \\configFile{inputfileAttitude}{instrument}\n  \\item \\configFile{inputfileClock}{instrument}\n\\end{itemize}\n\nThe following settings are needed in \\configClass{receiver:stationNetwork}{gnssReceiverGeneratorType:stationNetwork}:\n\\begin{itemize}\n   \\item \\configFile{inputfileStationList}{stringList}: list of all stations to be processed\n   \\item \\configFile{inputfileObservations}{instrument}: The converted RINEX observation file.\n   \\item \\configClass{tidalDisplacement}{tidesType}: Use the settings described in \\reference{receiver:stationNetwork}{gnssReceiverGeneratorType:stationNetwork}.\n   \\item \\configClass{useType}{gnssType}: We recommend to explicitly specify the signals to be processed\n            and to make sure that at least transmitter code biases are provided for each of them, e.g. \\verb|C1CG|,\n            \\verb|C1WG|, \\verb|C2WG|, \\verb|L1*G|, \\verb|L2*G|, ...).\n   \\item \\configClass{excludeType}{gnssType}: Signals you might want to exclude are \\verb|L5*G| (GPS L5 phase due to time-variable bias on block IIF satellites), \\verb|*3*R| (GLONASS G3 freq.), \\verb|*6*E| (Galileo E6 freq.)\n\\end{itemize}\n\nAdd the following \\configClass{parametrizations}{gnssParametrizationType}\nand define the \\config{outputfiles} you are interested in inside each of them:\n\\begin{itemize}\n  \\item \\configClass{ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}: add a constraint of \\config{sigmaSTEC}=\\verb|40|\n  \\item \\configClass{ionosphereVTEC}{gnssParametrizationType:ionosphereVTEC}\n  \\item \\configClass{clocks}{gnssParametrizationType:clocks}: delete \\configClass{selectTransmitters}{platformSelectorType}\n  \\item \\configClass{signalBiases}{gnssParametrizationType:signalBiases}: provide \\configFile{inputfileSignalBiasTransmitter}{gnssSignalBias} from\n        \\reference{Data preparation}{cookbook.gnssPpp:metadata}.\n  \\item \\configClass{ambiguities}{gnssParametrizationType:ambiguities}: if precise transmitter phase biases are available you can delete \\configClass{estimateTransmitterPhaseBiases}{platformSelectorType}\n  \\item \\configClass{codeBiases}{gnssParametrizationType:codeBiases}: delete \\configClass{selectTransmitters}{platformSelectorType}, set \\config{sigmaZeroMeanConstraint}=\\verb|0|\n  \\item \\configClass{tecBiases}{gnssParametrizationType:tecBiases}: delete \\configClass{selectTransmitters}{platformSelectorType}, set \\config{sigmaZeroMeanConstraint}=\\verb|0|\n  \\item \\configClass{kinematicPositions}{gnssParametrizationType:kinematicPositions}\n  \\item \\configClass{troposphere}{gnssParametrizationType:troposphere}: select \\configClass{troposphere:viennaMapping}{troposphereType:viennaMapping}\n        with the appropriate vmf3grid file. Add \\configClass{troposphereWetEstimation:splines}{parametrizationTemporalType:splines}\n        with linear (\\config{degree}=\\verb|1|) 2-hourly splines\n        and \\configClass{troposphereGradientEstimation:splines}{parametrizationTemporalType:splines} with linear daily splines.\n  \\item \\configClass{constraints}{gnssParametrizationType:constraints}: loose constraint troposphere estimates,\n        \\configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\\verb|troposphere*|, \\config{sigma}=\\verb|5|, and \\config{relativeToApriori}=\\verb|yes|\n\\end{itemize}\n\nAdd the following \\configClass{processingSteps}{gnssProcessingStepType}:\n\\begin{itemize}\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|8|\n  \\item \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|2|\n  \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}\n\\end{itemize}\n\nWhen processing multiple stations at the same time, moving \\configClass{estimate}{gnssProcessingStepType:estimate}\nand \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities} into the processing step\n\\configClass{forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately} sets up and solves\nthe normal equations independently for each station.\n\n% =============================================================\n"
  },
  {
    "path": "docs/latex/cookbook.gravityFieldGrace.tex",
    "content": "\\section{GRACE gravity field recovery}\\label{cookbook.gravityFieldGrace}\nThis cookbook chapter describes an example of estimating a gravity field solution using GRACE observation\ndata. For the respective month a set of spherical harmonic coefficients up to a maximum degree is determined.\nAn example scenario for this task can be found at\n\\url{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioGraceGravityfieldRecovery.zip}\nincluding the required GROOPS scripts and data sets for the gravity field recovery process.\nThe provided scenario consists of a slightly simplified example as compared to the operational one.\nThe background models are provided at \\url{https://ftp.tugraz.at/pub/ITSG/groops/data/}.\n\n\n\\subsection{Background models}\\label{cookbook.gravityFieldGrace:backgroundModels}\nThe following background models were used during the data processing:\n\\begin{itemize}\n  \\item \\textbf{Earth rotation}: \\href{https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html}{IERS 2010} % IERS 2010\n  \\item \\textbf{Moon, sun and planets ephemerides}: \\href{https://ipnpr.jpl.nasa.gov/progress_report/42-196/196C.pdf}{JPL DE432} %JPL DE432\n  \\item \\textbf{Earth tide}: \\href{https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html}{IERS 2010} % IERS 2010\n  \\item \\textbf{Ocean tide}: \\href{https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes/description-fes2014.html}{FES2014b} % FES2014b\n  \\item \\textbf{Pole tide}: \\href{https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html}{IERS 2010} % IERS 2010\n  \\item \\textbf{Ocean pole tide}: \\href{https://doi.org/10.1029/2001JC001224}{Desai 2004} % Desai 2004 (IERS 2010)\n  \\item \\textbf{Atmospheric tides}: \\href{https://doi.org/10.1029/2022MS003193}{TiME22} % TiME22\n  \\item \\textbf{Atmosphere and Ocean Dealiasing}: \\href{https://doi.org/10.1093/gji/ggx302}{AOD1B RL06} % AOD1B RL06\n  \\item \\textbf{Sub-monthly continental hydrology}: \\href{https://doi.org/10.2312/GFZ.b103-08095}{LSDM (ESMGFZ)} % LSDM (ESMGFZ)\n  \\item \\textbf{Relativistic corrections}: \\href{https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html}{IERS 2010} % IERS 2010\n\\end{itemize}\nThese models were reduced during the analysis process and are not present in the solution.\nThe \\href{https://doi.org/10.5194/essd-13-99-2021}{GOCO06s}\nmodel was used as the static gravity field as well as for the trend component and annual oscillation.\nIn the script \\verb|000groopsBackgroundModels.xml| a monthly mean of the GOCO06s including the time-variable components is determined\nin form of time splines using \\program{Gravityfield2TimeSplines}. This model is later added back to the final gravity solution.\n\n\\subsection{Instrument data preparation}\\label{cookbook.gravityFieldGrace:metadata}\nThe ITSG gravity field solutions are computed from the official GRACE L1B \\href{https://doi.org/10.5067/GRJPL-L1B03}{JPL (2018)}\nand GRACE-FO L1B \\href{https://doi.org/10.5067/GFL1B-ASJ04}{JPL (2019)} observation data. The data sets for this example are provided\nin GROOPS file format in the scenario folder.\n\nThe satellite-to-satellite-tracking (SST) data consists of:\n\\begin{itemize}\n  \\item \\textbf{K-band range rates}\n  \\item \\textbf{Light time correction}\n  \\item \\textbf{Antenna offset corrections}\n\\end{itemize}\n\nAdditional observation data required for the processing comprises:\n\\begin{itemize}\n  \\item \\textbf{Star camera observations}\n  \\item \\textbf{Accelerometer data}\n  \\item \\textbf{Approximate orbits} % \\textbf{Initial dynamic orbits}\n  \\item \\textbf{Thruster data}\n\\end{itemize}\n\nThe determination of\n\\begin{itemize}\n  \\item \\textbf{Kinematic orbits}\n  \\item \\textbf{3x3 epoch covariances}\n\\end{itemize}\nis depicted in \\reference{Kinematic orbit determination of LEO satellites}{cookbook.kinematicOrbit}.\nThese data sets are also provided in the scenario folder.\n\nData preparation is handled in the script \\verb|010groopsInstruments.xml|. The approximate orbits (initial dynamic orbits)\nof the satellites, the star camera observations, the accelerometer data and the thruster data are resampled with a 5s sampling\nand small gaps in the data are filled using \\program{InstrumentResample}. Gross outliers are removed using \\program{InstrumentRemoveEpochsByCriteria}\nand the data is synchronized using  \\program{InstrumentSynchronize}.\n\nThe approximate orbits are later used as a priori information for the dynamic orbit integration.\nIn addition to the observed orientation of the spacecrafts (star camera observations),\nthe nominal orientation is computed using \\program{SimulateStarCameraGrace}. The difference between\nobserved and simulated orientation is determined using \\program{InstrumentStarCameraMultiply}\nand is employed in the outlier detection.\n\nThe accelerometer data is initially calibrated by estimating a bias using\n\\program{InstrumentAccelerometerEstimateBiasScale} with respect to simulated data created\nwith \\program{SimulateAccelerometer}. For simulating accelerometer data a satellite model\nimplying the satellite's mass and surfaces is required. Such a model can be created with\n\\program{SatelliteModelCreate}. Models for the GRACE and GRACE-FO satellites are also provided\nat \\url{https://ftp.tugraz.at/pub/ITSG/groops/data/satelliteModel/}. Non-gravitational forces\ncomprising atmospheric drag, solar radiation pressure and albedo have to be modeled when simulating\nthe accelerometer data. The acceleration bias parameters are determined as degree 3 time splines\nwith 6h nodes. When determining these parameters the thruster events are excluded from the estimation.\n\nThe SST observations, the light time corrections and the antenna center corrections are synchronized\nwith a 5s sampling together with simulated SST data created with \\program{SimulateSatelliteTracking}.\nSimulated data is used for the outlier detection of the original SST observations.\n\nThe sampling of the kinematic orbits is reduced to 60s using \\program{InstrumentReduceSampling} and\nan outlier detection is performed using the approximate dynamic orbits.\n\nThe approximate orbits, the star camera observations and the accelerometer data are divided into 24h arcs\n(variational arcs). The kinematic orbits, its 3x3 epoch covariances, KBR observations,\nlight time corrections, antenna center corrections and star camera observations are divided into 3h arcs\nper day (short arcs). Additionally the approximate orbits and the star camera observations are also\nsynchronized to short arcs.\n\nFurther information on instrument data preparation can be found in\n\\reference{Instrument data handling}{cookbook.instrument}.\n\n\\subsection{Variational equations}\\label{cookbook.gravityFieldGrace:variational}\nIn this processing step dynamic orbits are computed for a complete 24h orbit arc by integrating\nthe forces acting on the GRACE/GRACE-FO satellites. Additionally, the state transition matrix is set up.\nThe dynamic orbits are then fitted to kinematic orbits and SST observations in a least squares adjustment\nby co-estimating additional accelerometer calibration parameters together with the initial state vector.\nThe newly estimated parameters are then used to re-estimate the dynamic orbits and setting up the new\nstate transition matrix.\n\nThe script \\verb|020groopsVariational.xml| in the scenario folder implements the required processing steps.\nTime splines from a time-variable gravity field are estimated using \\program{Gravityfield2TimeSplines}.\nIn this step the static gravity field (GOCO06s) is combined with the following time-variable components:\n\\begin{itemize}\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n    static gravity field\n    \\item \\configClass{gravityfield:trend}{gravityfieldType:trend}\n    \\begin{itemize}\n        \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n      trend component of gravity field\n    \\end{itemize}\n    \\item \\configClass{gravityfield:oscillation}{gravityfieldType:oscillation}\n    \\begin{itemize}\n        \\item \\configClass{gravityfieldCos:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n      annual cosine component of gravity field\n        \\item \\configClass{gravityfieldSin:potentialCoefficients}{gravityfieldType:potentialCoefficients}:\n      annual sine component of gravity field\n    \\end{itemize}\n    \\item \\configClass{gravityfield:timeSplines}{gravityfieldType:timeSplines}: atmosphere and ocean dealiasing (AOD1B RL06)\n    \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tides (FES2014b)\n    \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: atmospheric tides (TiME22)\n    \\item \\configClass{tides:poleTide}{tidesType:poleTide}: pole tides (IERS 2010)\n    \\item \\configClass{tides:poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tides (IERS 2010)\n\\end{itemize}\n\\config{maxDegree}=\\verb|220| and \\config{sampling}=\\verb|10/1440| is sufficient.\n\nIn \\program{PreprocessingVariationalEquation} the \\file{variational equations}{variationalEquation}\ncomprising the integrated orbit together with the state transition matrix are stored in\n\\configFile{outputfileVariational}{variationalEquation}.\n\nThis program has to be executed for both GRACE or GRACE-FO satellites and it is recommended\nto use \\program{LoopPrograms}.\n\\begin{itemize}\n    \\item \\configFile{inputfileSatelliteModel}{satelliteModel}: satellite model from \\verb|020groopsInstruments.xml|\n    \\item \\configFile{inputfileOrbit}{instrument}: the approximate orbits from \\verb|020groopsInstruments.xml|\n    \\item \\configFile{inputfileStarCamera}{instrument}: the attitude file from \\verb|020groopsInstruments.xml|\n    \\item \\configFile{inputfileAccelerometer}{instrument}: the accelerometer data from\n    \\verb|020groopsInstruments.xml|\n    \\item \\config{forces}: see below\n    \\item \\configClass{ephemerides}{ephemeridesType}: JPL DE432\n    \\item \\configClass{gradientfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}: a static gravity field (GOCO06s) with \\config{maxDegree}=\\verb|10| is more than sufficient.\n\\end{itemize}\n\nThe \\configClass{force models}{forcesType} include:\n\\begin{itemize}\n  \\item \\configClass{gravityfield:timeSplines}{gravityfieldType:timeSplines}:\n        the previously estimated time-variable gravity field\n  \\item \\configClass{tides:astronomicalTide}{tidesType:astronomicalTide}: astronomical tides (based on JPL DE432 ephemerides)\n  \\item \\configClass{tides:earthTide}{tidesType:earthTide}: Earth tide (IERS conventions)\n  \\item \\configClass{miscAccelerations:relativisticEffect}{miscAccelerationsType:relativisticEffect}:\n        relativistic effects (IERS conventions)\n\\end{itemize}\n\nIn \\program{PreprocessingVariationalEquationOrbitFit} the integrated orbit\n(\\configFile{inputfileVariational}{variationalEquation}) is fitted to the kinematic orbit\n(\\configFile{inputfileOrbit}{instrument}) by least squares adjustment. The additional accelerometer\ncalibration parameters can be defined by\n\\begin{itemize}\n  \\item \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}: accelerometer scale factor (once per day)\n  \\item \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}: accelerometer bias (time spline with 6h nodes)\n\\end{itemize}\n\nThe observation equations (parameter sensitivity matrix) are computed by integration of the variational\nequations (\\configFile{inputfileVariational}{variationalEquation}) using a polynomial with\n\\config{integrationDegree}=\\verb|7|. \\program{PreprocessingVariationalEquationOrbitFit} has to be\nexecuted per satellite.\n\n\\program{PreprocessingVariationalEquationSstFit} fits two dynamic orbits\n\\configFile{inputfileVariational1/2}{variationalEquation} to the SST observations and the kinematic orbits.\n\\begin{itemize}\n    \\item \\config{rightHandSide}: input for observation vectors\n        \\begin{itemize}\n            \\item \\configFile{inputfileSatelliteTracking}{instrument}: K-band range rate observations\n            \\item \\configFile{inputfileSatelliteTracking}{instrument}: light time correction\n            \\item \\configFile{inputfileSatelliteTracking}{instrument}: antenna offset corrections\n            \\item \\configFile{inputfileOrbit1}{instrument}: kinematic orbit of satellite 1\n            \\item \\configFile{inputfileOrbit2}{instrument}: kinematic orbit of satellite 2\n        \\end{itemize}\n    \\item \\config{sstType}: rangeRate\n    \\item \\configFile{inputfileVariational1}{variationalEquation}: dynamic orbit and integrated state matrix of satellite 1\n    \\item \\configFile{inputfileVariational2}{variationalEquation}: dynamic orbit and integrated state matrix of satellite 2\n    \\item \\configClass{parametrizationAcceleration1}{parametrizationAccelerationType}: same as in In \\program{PreprocessingVariationalEquationOrbitFit}\n    \\item \\configClass{parametrizationAcceleration2}{parametrizationAccelerationType}: same as in In \\program{PreprocessingVariationalEquationOrbitFit}\n    \\item \\config{integrationDegree}: \\verb|7|\n    \\item \\config{interpolationDegree}: \\verb|7|\n    \\item \\configClass{covarianceSst}{covarianceSstType}\n        \\begin{itemize}\n            \\item \\config{sigma}: \\verb|1|\n        \\end{itemize}\n    \\item \\configClass{covariancePod1}{covariancePodType}\n        \\begin{itemize}\n            \\item \\config{sigma}: 1\n            \\item \\configFile{inputfileCovariancePodEpoch}{instrument}: 3x3 epoch covariances\n        \\end{itemize}\n    \\item \\configClass{covariancePod2}{covariancePodType}\n        \\begin{itemize}\n            \\item \\config{sigma}: 1\n            \\item \\configFile{inputfileCovariancePodEpoch}{instrument}: 3x3 epoch covariances\n        \\end{itemize}\n\\end{itemize}\nThe estimated accelerometer calibration parameters from \\program{PreprocessingVariationalEquationOrbitFit}\nand \\program{PreprocessingVariationalEquationSstFit} are determined as corrections and stored\nin \\configFile{outputfileSolution}{matrix}. Both correction estimates have to be summed up using\n\\program{FunctionsCalculate}.\n\nThe dynamic orbit and the resulting accelerometer calibration parameters are now used to re-integrate\nthe orbit once more using \\program{PreprocessingVariationalEquation} and introducing\n\\configClass{parametrizationAcceleration}{parametrizationAccelerationType} as \\config{estimatedParameters}.\nThis step usually ensures convergence. If the maximum orbit difference is still not sufficient this step\ncan be repeated again.\n\n\\subsection{Preprocessing}\\label{cookbook.gravityFieldGrace:preprocessing}\nThe script \\verb|030groopsPreprocessing.xml| implements the following steps and settings.\nThe program \\program{PreprocessingSst} processes SST observations and kinematic orbit data, and\nperforms a complete least squares adjustment for gravity field determination by computing\nthe observations equations. It also allows for an iterative refinement of the stochastic model\nof the observations along with arc-wise variance factors through variance component estimation (VCE).\nForce model parameters (gravitational potential coefficients and accelerometer calibration parameters)\nare computed by integrating the parameter sensitivity matrix from the variational equations.\nParameters describing effects due to the SST observation system and geometry (KBR antenna phase\ncenter variations) are computed using the dynamic orbits as a Taylor point.\nShort time gravity variations can be co-estimated together with the monthly mean gravity field.\nThe autoregressive model sequence constraining the short time parameters is provided in the data folder.\nIt is precomputed from hydrology and nontidal atmospheric and ocean background models.\nSee \\href{https://doi.org/10.1007/s00190-019-01314-1}{Kvas 2019} for more information about\nthis co-estimation.\n\n\\begin{itemize}\n    \\item \\configClass{observation}{observationType}: sstVariational\n        \\begin{itemize}\n            \\item \\config{rightHandSide}:\n            \\begin{itemize}\n                \\item \\configFile{inputfileSatelliteTracking}{instrument}: KBR range rates\n                \\item \\configFile{inputfileSatelliteTracking}{instrument}: light time correction\n                \\item \\configFile{inputfileSatelliteTracking}{instrument}: antenna offset corrections\n                \\item \\configFile{inputfileOrbit1}{instrument}: kinematic orbit of satellite 1\n                \\item \\configFile{inputfileOrbit2}{instrument}: kinematic orbit of satellite 2\n            \\end{itemize}\n            \\item \\config{sstType}: rangeRate\n            \\item \\configFile{inputfileVariational1}{variationalEquation}: dynamic orbit and integrated state matrix of satellite 1\n            \\item \\configFile{inputfileVariational2}{variationalEquation}: dynamic orbit and integrated state matrix of satellite 2\n            \\item \\configClass{ephemerides}{ephemeridesType}: JPL DE432\n            \\item \\configClass{parametrizationGravity}{parametrizationGravityType}: spherical harmonics from \\config{minDegree}=\\verb|2| to \\config{maxDegree}=\\verb|60|\n            \\item \\configClass{parametrizationGravity}{parametrizationGravityType}: high frequency parametrization\n            \\item \\configClass{parametrizationAcceleration1}{parametrizationAccelerationType}: same as in In \\program{PreprocessingVariationalEquationOrbitFit}\n            \\item \\configClass{parametrizationAcceleration2}{parametrizationAccelerationType}: same as in In \\program{PreprocessingVariationalEquationOrbitFit}\n            \\item \\configClass{parametrizationSst}{parametrizationSatelliteTrackingType}: antenna phase center variations (y and z for both satellites)\n            \\item \\config{integrationDegree}: 7\n            \\item \\config{interpolationDegree}: 7\n        \\end{itemize}\n    \\item \\configClass{covarianceSst}{covarianceSstType}\n        \\begin{itemize}\n            \\item \\config{sigma}: \\verb|1e-7|\n            \\item \\config{sampling}: 5 [seconds]\n        \\end{itemize}\n    \\item \\configClass{covariancePod1/2}{covariancePodType}\n        \\begin{itemize}\n            \\item \\config{sigma}:  \\verb|2|\n            \\item \\configFile{inputfileCovariancePodEpoch}{instrument}: 3x3 epoch covariances\n            \\item \\config{sampling}: 60 [seconds]\n        \\end{itemize}\n    \\item \\config{estimateShortTimeVariations}\n        \\begin{itemize}\n            \\item \\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType}: AR models\n            \\item \\configClass{parameterSelection}{parameterSelectorType}: names\n                \\begin{itemize}\n                    \\item \\configClass{parameterName}{parameterNamesType}: parametrizationGravity\n                    \\begin{itemize}\n                        \\item \\configClass{parametrization}{parametrizationGravityType}: high frequency parametrization\n                    \\end{itemize}\n                \\end{itemize}\n        \\end{itemize}\n\\end{itemize}\n\n\\program{ParameterSelection2IndexVector} and \\program{MatrixCalculate} with\n\\configClass{matrix:reorder}{matrixGeneratorType:reorder} can be used to extract the desired\nspherical harmonic coefficients from \\configFile{outputfileSolution}{matrix} and the respective\nstandard deviations from \\configFile{outputfileSigmax}{matrix} up to a certain degree.\n\nIn the program \\program{Gravityfield2PotentialCoefficients} the estimated spherical harmonics\ncoefficients are read with\n\\configClass{gravityfield:fromParametrization}{gravityfieldType:fromParametrization}.\nThe monthly mean gravity field can be added back by additionally selecting the time splines created\nin \\verb|000groopsBackgroundModels.xml| using\n\\configClass{gravityfield:timeSplines}{gravityfieldType:timeSplines}. The preprocessing solution\nis saved as a \\file{spherical harmonics file}{potentialCoefficients}.\n\n\\subsection{Setting up normal equations}\\label{cookbook.gravityFieldGrace:monthlyNormals}\nNormal equations are set up in the script \\verb|040groopsMonthlyNormals120.xml| using\nthe program \\program{NormalsBuildShortTimeStaticLongTime}. The time intervals which the normal\nequations are divided into are defined in \\configFile{inputfileArcList}{arcList}.\nThe normal equations are based on \\configClass{observation}{observationType} including the SST data,\nthe kinematic orbits and the variational equations. The parametrization of the gravity field can\nbe set with \\configClass{observation:parametrizationGravity}{parametrizationGravityType}\n(e.g. spherical harmonics up to degree and order 120). Accelerometer calibration parameters\nand KBR antenna phase center variations can be parameterized using\n\\configClass{parametrizationAcceleration}{parametrizationAccelerationType} and\n\\configClass{parametrizationSst}{parametrizationSatelliteTrackingType}.\nWith \\config{estimateShortTimeVariations} short time variations of the gravity\nfield can be co-estimated. The parameters selected by\n\\configClass{parameterSelection}{parameterSelectorType} (e.g. linear splines with 6h nodes) are\nconstrained by an \\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType}.\nAdditional temporal variations (e.g. trend and annual oscillation) could be estimated with\n\\config{estimateLongTimeVariations}.\n\n\\subsection{Solving normal equations}\\label{cookbook.gravityFieldGrace:monhtlySolve}\nThe desired spherical harmonic coefficients are determined in the script \\verb|050groopsMonthlySolve.xml|.\n\\program{NormalsSolverVCE} accumulates \\configClass{normalEquation}{normalEquationType} and solves\nthe total combined system. Variance component estimation is used to determine the relative weighting\nof the individual normals, i.e. the arc-wise variances. The previously computed stochastic model of\nthe observations remains unchanged. The estimated parameter vector (\\configFile{outputfileSolution}{matrix}),\nthe estimated accuracies (\\configFile{outputfileSigmax}{matrix}) and the full covariance matrix\n(\\configFile{outputfileCovariance}{matrix}) can be saved.\nUsing \\program{Gravityfield2PotentialCoefficients} the final solution can be saved as\na \\file{spherical harmonics file}{potentialCoefficients} by adding back the monthly mean gravity\nfield to the estimated spherical harmonic coefficients.\n\n% =============================================================\n"
  },
  {
    "path": "docs/latex/cookbook.gravityFieldPod.tex",
    "content": "\\section{Gravity field determination from precise orbit data (POD)}\\label{cookbook.gravityFieldPod}\n\nThis cookbook chapter describes exemplarily the steps for determining the monthly gravity variations from precise orbit data (POD).\n\n\\subsection{Step 1: Preperation of data}\n\nFollowing data have to be prepared monthly with an adequate sampling, e.g. 10 s using\n\\program{InstrumentConcatenate}:\n\\begin{itemize}\n  \\item Precise (kinematic) orbit data\n  \\item 3x3 covariance matrices data\n  \\item Initial orbit data used for precise orbit determination\n  \\item Star camera data\n  \\item Accelerometer data\n\\end{itemize}\nReduced sampling can be achieved by \\program{InstrumentReduceSampling}. If the satellite mission does not provide any required\naccelerometer data, these data can be generated via \\program{SimulateAccelerometer}.\n\nFor satellite missions with less knowledge about the acting forces, it makes sense to consider more than one state vector within an orbit revolution.\nOtherwise the accuracy of the estimated parameters will decrease. This implies that shorter arcs are necessary. The assignment of the kinematic orbit\ndata as well as the 3x3 covariance matrices data to the arcs can be done with \\program{InstrumentSynchronize}.\n\n\\subsection{Step 2: Conversion of the background gravity field}\n\\program{Gravityfield2SphericalHarmonicsVector} converts the static respectively background gravity field into spherical harmonics.\n\n\\subsection{Step 3: Preprocessing POD}\nFor determining the accuracies and weights of the kinematic orbits it is sufficient to make a least-square estimation with only certain parameters, due\nto the fact that some parameters do not influence the estimation of the accuracies and weights.\nThis estimation is done with \\program{PreprocessingPod}. Additionally, this program determines the temporal correlation of the kinematic orbit positions\nx, y and z. If short arcs are used the setting \\configClass{observation:podIntegral}{observationType:podIntegral} shall be used. This setting\nconsiders the frictional forces by means of a macro model as well as the conservative and non-conservative forces.\n\n\\subsection{Step 4: Solving of normal equations system}\n\\program{NormalsSolverVCE} sets up the observation equations and summarized them to a normal equations system. The subsequent least-square estimation delivers\nthe parameters surcharges.\n\n\\subsection{Step 5: Determination of the estimated gravity field parameters}\nThe estimated parameters result from the re-addition of the background field, which is done in \\program{MatrixCalculate}.\n\n\\subsection{Step 6: Conversion of the gravity field parameters}\n\\program{Gravityfield2PotentialCoefficients} converts the gravity field parameters into spherical harmonics.\n\n% =============================================================\n"
  },
  {
    "path": "docs/latex/cookbook.instrument.tex",
    "content": "\\section{Instrument data handling}\\label{cookbook.instrument}\n\nGROOPS provides functions and programs to read/write, preprocess, analyze and visualize uniformly and non-uniformly sampled instrument data.\nThis includes tools for filter design and analysis, re-sampling, smoothing, detrending, and power spectrum estimation.\nThis tutorial goes through exemplary steps for data handling procedures.\n\n\\subsection{Reading data}\n\n\\begin{itemize}\n\\item GROOPS is able to read and convert relevant data from various LEO and GNSS satellites. Instrument files need to be converted into the respective GROOPS format using conversion programs.Depending on the content of the input file, the data is stored with a specific \\configClass{instrument type}{instrumentTypeType}. User also has the option to change the type later on with \\program{InstrumentSetType}.\n\n\\item Multiple files can be concatenated to one file using \\program{InstrumentConcatenate}. Using this program, it is also possible to sort the epochs, remove the duplicates and NaN values.\n\\item \\emph{Example: Concatenating instrument files}\n  \\begin{itemize}\n  \\item Create three successively daily sinusoidal signals with \\program{TimeSeriesCreate} and set their type to MISCVALUE with \\program{InstrumentSetType}. In this example, each data set has an overlap of 1 hour with their following dataset.\n  \\item Merge all datasets to one single file with \\program{InstrumentConcatenate}.\n  \\fig{!ht}{0.8}{instrumentDataHandeling_concatenating}{fig:instrumentDataHandeling_concatenating}{Example 1: Concatenating instrument files into one dataset.}\n  \\end{itemize}\n \\item Many measurements involve data collected asynchronously by multiple sensors with different sampling. Use \\program{InstrumentSynchronize} for a continuous harmonization of the data over time or segmentation of the data into arcs.\n\\end{itemize}\n\n\\subsection{Preprocessing}\nReal-world data is often incomplete, inconsistent, and/or lacking in certain behaviors or trends, and is likely to contain many errors. Data preprocessing is a proven method of resolving such issues. Following steps are usually required to be taken:\n\n\\begin{itemize}\n\\item Gross outlier removal:\n  \\begin{itemize}\n  \\item Create reference values to compare the input data with. Depending on the instrument type, this can be done by simulation programs such as \\program{SimulateAccelerometer} or \\program{SimulateStarCamera}. If no reference data is available, the outlier detection is based on the data itself. If needed, synchronize the reference data file and the input data with \\program{InstrumentSynchronize}.\n\n  \\item In case of star camera data, compute the differences between the input data and the reference data with \\program{InstrumentStarCameraMultiply}.\n\n  \\item Set a threshold for outlier detection in \\program{InstrumentRemoveEpochsByCriteria}. The threshold is defined empirically according to the accuracy characteristics of each data products. If the differences exceed a predefined threshold, the corresponding epochs are removed. An arbitrary margin can be defined to additionally remove epochs before and after the identified outliers. It is also possible to remove epochs at specific times using \\program{InstrumentRemoveEpochsByTimes}.\n  \\item Missing epochs can be filled by reference data with \\program{InstrumentConcatenate}.\n  \\item It is also possible to interpolate the missing epochs with \\program{InstrumentResample}.\n  \\item \\emph{Example: Removing outliers in a synthetic data.}\n  \\begin{itemize}\n  \\item Create a sinusoidal signal with an amplitude of 1.0 using \\program{TimeSeriesCreate} and set its type to MISCVALUE with \\program{InstrumentSetType}.\n  \\item Add zero-mean, white Gaussian noise with a standard deviation of 0.1 with \\program{NoiseInstrument}. Interpret this data as a real measurement file.\n  \\item Set the threshold criteria to 0.2 in \\program{InstrumentRemoveEpochsByCriteria} and remove the outliers and their nearest epochs in 20 second interval.\n  \\item Fill the data gaps with \\program{InstrumentResample}.\n  \\fig{!ht}{0.8}{instrumentDataHandeling_outlierRemoval}{fig:instrumentDataHandeling_outlierRemoval}{Example 2: Removing gross outliers.}\n  \\end{itemize}\n  \\end{itemize}\n\n\n\\item Downsampling:\n  \\begin{itemize}\n  \\item If the sampling is irregular use \\program{InstrumentResample} to make the sampling equidistant.\n  \\item Use \\program{InstrumentSynchronize} to divide the data at gaps into arcs.\n  \\item Apply a lowpass filter (e.g. Butterworth) with the Nyquist frequency of the target sampling as cutoff with \\program{InstrumentFilter}. Apply the filter in both directions to avoid phase shifts.\n  \\item Use \\program{InstrumentReduceSampling} to down-sample the data.\n  \\end{itemize}\n\n\\item Calibration:\n  \\begin{itemize}\n  \\item For a general instrument file, \\program{InstrumentDetrend} subtracts offsets or linear/nonlinear trends from the input data. This can be achieved also with \\program{FunctionsCalculate} or \\program{InstrumentArcCalculate} by applying determined calibration factors or solving a least-square adjustment.\n  \\item For accelerometer data, \\program{InstrumentAccelerometerEstimateBiasScale} is designed to estimate and subtract complex biases or scales with respect to simulated accelerometer data. If a thruster file is given, the corresponding epochs are eliminated during estimation process.\n  \\item \\emph{Example: GRACE-C accelerometer calibration}\n  \\begin{itemize}\n  \\item For one particular date, read and convert Level-1B GRACE-C orbit, star camera, accelerometer, and thruster data with \\program{GraceL1b2Orbit}, \\program{GraceL1b2StarCamera}, \\program{GraceL1b2Accelerometer}, and \\program{GraceL1b2Thruster} respectively. It is also required to read the macro-model data of the satellite using the related information in the official document and convert it to GROOPS format with \\program{SatelliteModelCreate}.\n  \\item Use \\program{SimulateAccelerometer} to generate simulated accelerations due to non-gravitational force models including: \\configClass{miscAccelerations:atmosphericDrag}{miscAccelerationsType:atmosphericDrag}, \\configClass{miscAccelerations:solarRadiationPressure}{miscAccelerationsType:solarRadiationPressure}, and \\configClass{miscAccelerations:albedo}{miscAccelerationsType:albedo}.\n  \\item Calibrate the real measurements with a daily constant accelerometer bias by choosing a constant parameter per axis in \\configClass{parametrizationAcceleration:accBias}{parametrizationAccelerationType:accBias}.\n  \\fig{!ht}{0.8}{instrumentDataHandeling_calibration}{fig:instrumentDataHandeling_calibration}{Example 3: Calibrating GRACE-C ACT1B data.}\n  \\end{itemize}\n  \\end{itemize}\n\\end{itemize}\n\n\\subsection{Statistical analysis}\n\\begin{itemize}\n\\item \\program{InstrumentStatisticsTimeSeries} returns statistics for one or more instrument files. \\program{InstrumentArcCalculate} is also able to generate a \\config{statistics} file with one mid epoch per arc.\n\\end{itemize}\n\n\\subsection{Spectral analysis}\nSpectral analysis studies the frequency spectrum contained in discrete, uniformly sampled data. The Fourier transform is a tool that reveals frequency components of a signal by representing it in frequency space. The Power Spectral Density (PSD) is a measurement of the energy at each frequency.\n\n\\begin{itemize}\n\\item If the sampling is irregular use \\program{InstrumentResample} to make the sampling equidistant.\n\\item Use \\program{Instrument2PowerSpectralDensity} to compute PSD.\n\\item If covariance function of a dataset is available, use \\program{CovarianceFunction2PowerSpectralDensity}.\n\\item \\emph{Example: Spectral analysis of a synthetic signal.}\n  \\begin{itemize}\n  \\item Create a sinusoidal signal with an amplitude of 1.0 using \\program{TimeSeriesCreate} and set its type to MISCVALUE with \\program{InstrumentSetType}. Interpret this data as a simulation data file.\n  \\item Add zero-mean, white Gaussian noise with a standard deviation of 0.1 with \\program{NoiseInstrument}. Interpret this data as a real measurement file.\n  \\item Compute PSD of the simulated and measurement data and represent the results with \\program{PlotGraph}.\n  \\fig{!ht}{0.8}{instrumentDataHandeling_psd}{fig:instrumentDataHandeling_psd}{Example 4: Spectral analysis of a synthetic signal.}\n  \\end{itemize}\n\\end{itemize}\n\n\\subsection{Data visualization}\n\\begin{itemize}\n\\item Argument of latitude plot\nPlotting instrument data as a function of satellite position in orbit and time reveals features related to the orbit geometry or environmental conditions. For circular orbits, the position of  satellite can be specified by the argument of latitude.\n\\begin{itemize}\n\\item Synchronize the instrument data file with the related orbit data using \\program{InstrumentSynchronize}.\n\\item Use \\program{Orbit2ArgumentOfLatitude} to compute argument of latitude at each epoch.\n\\item Plot the instrument data versus argument of latitude and time with \\program{PlotGraph}.\n\\item \\emph{Example: Argument of latitude representation of GRACE-C eclipse factors}\n  \\begin{itemize}\n  \\item Compute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using \\program{Orbit2EclipseFactor}.\n  \\item Synchronize the eclipse factor data file with the related orbit data using \\program{InstrumentSynchronize}.\n  \\item Use \\program{Orbit2ArgumentOfLatitude} to compute argument of latitude at each epoch and visualize the results with \\program{PlotGraph}.\n  \\fig{!ht}{0.8}{instrumentDataHandeling_aol}{fig:instrumentDataHandeling_aol}{Example 5: GRACE-C eclipse factors represented in argument of latitude plot.}\n  \\end{itemize}\n\\end{itemize}\n\n\\item Ground-track plot\nPlotting instrument data with respect to the satellite ground track is useful to identify any features of geophysical origin in the data.\n\\begin{itemize}\n\\item Synchronize the instrument data file with the related orbit data using \\program{InstrumentSynchronize}.\n\\item Use \\program{Orbit2Groundtracks} to map instrument data to satellite ground-track.\n\\item Visualize the output with \\program{PlotMap}.\n\\item \\emph{Example 6: Ground-track representation of GRACE-C eclipse factors}\n  \\begin{itemize}\n  \\item Compute eclipse factors at each epoch of GRACE-C orbit at an arbitrary time using \\program{Orbit2EclipseFactor}.\n  \\item Synchronize the eclipse factor data file with the related orbit data using \\program{InstrumentSynchronize}.\n  \\item Use \\program{Orbit2Groundtracks} to generate the gridded data. Each grid value represents the mean value of eclipse factor over the instrument time period (1 month).  visualize the results with \\program{PlotMap}.\n  \\end{itemize}\n  \\fig{!ht}{0.8}{instrumentDataHandeling_groundTrack}{fig:instrumentDataHandeling_groundTrack}{Example 6: GRACE-C eclipse factors represented in ground-track plot.}\n\\end{itemize}\n\n\\end{itemize}\n%% =============================================================\n"
  },
  {
    "path": "docs/latex/cookbook.kinematicOrbit.tex",
    "content": "\\section{Kinematic orbit determination of LEO satellites}\\label{cookbook.kinematicOrbit}\nThis cookbook chapter describes exemplarily the steps for determining kinematic orbits of low-Earth orbit (LEO) satellites.\n\nAn example scenario for this task is available at \\url{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip}.\nIt includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at \\url{https://ftp.tugraz.at/pub/ITSG/groops} (data folder or zipped archive).\nThe scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.\n\n\\subsection{Prepare GNSS satellite data}\\label{cookbook.kinematicOrbit:gnssMetadata}\nMost of the required metadata files are provided in GROOPS file formats at \\url{https://ftp.tugraz.at/pub/ITSG/groops}.\nThese files are regularly updated.\n\nData that has to be gathered from other sources comprises:\n\\begin{itemize}\n  \\item \\textbf{Receiver observations}: GNSS measurements converted from RINEX format (see \\program{RinexObservation2GnssReceiver})\n  \\item \\textbf{Precise orbits}: precise orbits in CRF for orbit integration (see \\program{Sp3Format2Orbit})\n  \\item \\textbf{Precise clocks}: precise clocks (see \\program{GnssClockRinex2InstrumentClock})\n  \\item \\textbf{Attitude}: rotation from body frame to CRF (see \\program{SimulateStarCameraGnss} or \\program{GnssOrbex2StarCamera})\n  \\item \\textbf{Signal biases}: code (and phase) biases (see \\program{GnssSinexBias2SignalBias})\n\\end{itemize}\nReceiver observations, precise satellite orbits and clocks, and possibly attitude and signal biases can be downloaded from the\n\\href{https://igs.org/data-products-overview/}{IGS Data Centers}.\nGPS, GLONASS, and Galileo orbits, clocks, attitude, and signal biases for the period 1994-2020 are also available as part of\n\\href{https://doi.org/10.3217/dataset-4528-0723-0867}{Graz University of Technology's contribution to IGS repro3}.\n\nThe \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip}{example scenario} includes a small set of this data.\nThe script \\verb|010groopsConvert.xml| can be used to convert these external formats into GROOPS formats.\n\n\\subsection{Prepare LEO metadata}\\label{cookbook.kinematicOrbit:leoMetadata}\nMetadata for several LEO missions is availabe at \\url{https://ftp.tugraz.at/pub/ITSG/groops/data/gnss/receiverLowEarthOrbiter}.\n\nIf you want to process another mission, you can create the necessary files with these steps:\n\\begin{itemize}\n  \\item For creating the \\file{GnssSatelliteInfo file}{platform} use \\program{PlatformCreate}. Note that the rotation from the\n  satellite reference frame into the antenna reference frame, as well as the change of the center of mass due to fuel consumption, has to be considered here.\n  \\item The \\file{GnssReceiverDefinition file}{gnssReceiverDefinition} can be created by using \\program{GnssReceiverDefinitionCreate}. Here you can specify which GNSS signal types the receiver observes.\n  \\item For creating the \\file{GnssAntennaDefinition file}{gnssAntennaDefinition}\\ use \\program{GnssAntennaDefinitionCreate}. Here you can define phase center offsets for the antenna.\n  \\item For determining the elevation dependent accuracies the program \\program{GnssAntennaDefinitionCreate} is used again.\n  \\begin{itemize}\n    \\item \\config{antenna}: set to new\n    \\item Set the \\config{pattern}s for code (\\config{type}=\\verb|C**|) and phase\n    (\\config{type}=\\verb|L**|). The standard deviation is expressed e.g. with \\config{values}=\\verb|0.001/cos(2*PI/180*zenith)|.\n  \\end{itemize}\n\\end{itemize}\n\n\\subsection{Prepare LEO data}\\label{cookbook.kinematicOrbit:leoData}\nThe \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip}{example scenario} includes a small set of this data for the GRACE-FO mission.\nThe script \\verb|020groopsConvertGracefo.xml| can be used to convert these external formats into GROOPS formats.\n\nThe data preparation steps are:\n\\begin{itemize}\n  \\item Conversion of the approximate orbit and star camera data into GROOPS format using a conversion program.\n  \\item If no attitude data is given the star camera data can be simulated by using \\program{SimulateStarCamera} or \\program{SimulateStarCameraSentinel1}.\n  \\item The GNSS observation data (given in RINEX format) can be converted with \\program{RinexObservation2GnssReceiver}.\n  \\item Suitable programs to get daily data are \\program{InstrumentConcatenate} and \\program{InstrumentSynchronize}.\n  \\item For interpolating the orbit and star camera data to GNSS receiver epochs use \\program{InstrumentResample} and provide the converted RINEX observation file as input for\n  \\configClass{timeSeries:instrument}{timeSeriesType:instrument}.\n  \\item For synchronizing these data use \\program{InstrumentSynchronize}.\n\\end{itemize}\nDetailed description of instrument data handling can be found in \\reference{Instrument data handling}{cookbook.instrument}.\n\n\\subsection{Estimate kinematic orbits}\\label{cookbook.kinematicOrbit:processing}\nThe script \\verb|03groopsGnssProcessing.xml| in the \\href{https://ftp.tugraz.at/pub/ITSG/groops/scenario/scenarioLeoKinematicOrbit.zip}{example scenario}\nimplements the following steps and settings.\n\nThese are the settings for \\program{GnssProcessing}. If not otherwise stated use the default values.\n\nAs we have only one receiver the processing sampling can be directly taken from the observation file:\n\\configClass{timeSeries:instrument}{timeSeriesType:instrument}.\n\nAdd the appropriate \\configClass{transmitters:gnss}{gnssTransmitterGeneratorType:gnss} (e.g. GPS)\nand provide the required files (from \\reference{Prepare GNSS satellite data}{cookbook.kinematicOrbit:gnssMetadata}):\n\\begin{itemize}\n  \\item \\configFile{inputfileOrbit}{instrument}\n  \\item \\configFile{inputfileAttitude}{instrument}\n  \\item \\configFile{inputfileClock}{instrument}\n\\end{itemize}\n\nThe following files (from \\reference{Prepare LEO metadata}{cookbook.kinematicOrbit:leoMetadata} and \\reference{Prepare LEO data}{cookbook.kinematicOrbit:leoData}) and settings are needed in \\configClass{receiver:lowEarthOrbiter}{gnssReceiverGeneratorType:lowEarthOrbiter}:\n\\begin{itemize}\n   \\item \\configFile{inputfileStationInfo}{platform}: The satellite info file.\n   \\item \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\n   \\item \\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition}\n   \\item \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition}\n   \\item \\configFile{inputfileObservations}{instrument}: The converted RINEX observation file.\n   \\item \\configFile{inputfileOrbit}{instrument}: The approximate orbit.\n   \\item \\configFile{inputfileStarCamera}{instrument}: The convered or simulated attitude.\n   \\item \\configClass{useType}{gnssType}: We recommend to explicitly specify the signals to be processed\n            and to make sure that at least transmitter code biases are provided for each of them, e.g. \\verb|C1CG|,\n            \\verb|C1WG|, \\verb|C2WG|, \\verb|L1*G|, \\verb|L2*G|, ...).\n\\end{itemize}\n\nAdd the following \\configClass{parametrizations}{gnssParametrizationType}\nand define the \\config{outputfiles} within you are interested in:\n\\begin{itemize}\n  \\item \\configClass{ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}: add a constraint of \\config{sigmaSTEC}=\\verb|40|\n  \\item \\configClass{ionosphereVTEC}{gnssParametrizationType:ionosphereVTEC}:\n        set \\config{mapR}=\\verb|6371e3+450e3| to satellite height and ionosphere height \\config{mapH}=\\verb|50e3| above.\n  \\item \\configClass{clocks}{gnssParametrizationType:clocks}: delete \\configClass{selectTransmitters}{platformSelectorType}\n  \\item \\configClass{signalBiases}{gnssParametrizationType:signalBiases}: provide \\configFile{inputfileSignalBiasTransmitter}{gnssSignalBias} created with \\program{GnssSinexBias2SignalBias}\n  \\item \\configClass{ambiguities}{gnssParametrizationType:ambiguities}: if precise transmitter phase biases are available you can delete \\configClass{estimateTransmitterPhaseBiases}{platformSelectorType}\n  \\item \\configClass{codeBiases}{gnssParametrizationType:codeBiases}: delete \\configClass{selectTransmitters}{platformSelectorType}, set \\config{sigmaZeroMeanConstraint}=\\verb|0|\n  \\item \\configClass{tecBiases}{gnssParametrizationType:tecBiases}: delete \\configClass{selectTransmitters}{platformSelectorType}, set \\config{sigmaZeroMeanConstraint}=\\verb|0|\n  \\item \\configClass{kinematicPositions}{gnssParametrizationType:kinematicPositions}\n\\end{itemize}\n\nAdd the following \\configClass{processingSteps}{gnssProcessingStepType}:\n\\begin{itemize}\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|8|\n  \\item \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: with \\config{maxIterationCount}=\\verb|2|\n  \\item \\configClass{computeCovarianceMatrix}{gnssProcessingStepType:computeCovarianceMatrix}\n  \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}\n\\end{itemize}\n\n% =============================================================\n"
  },
  {
    "path": "docs/latex/cookbook.regionalGeoid.tex",
    "content": "\\section{Regional geoid determination}\\label{cookbook.regionalGeoid}\nThis shows the exemplary computation of a regional geoid using terrestrial gravimetric observations\nin combination with a global satellite model such as GOCO06s. The geoid is estimated in a least squares adjustment with\na parametrization using radial basis functions. A detailed desciption of the method is given in\nChristian Pock (2017), Consistent Combination of Satellite and Terrestrial Gravity Field Observations in Regional Geoid Modeling.\nDissertation TU Graz.\n\n\n\\subsection{Gravimetric data}\nHere it is assumed that the measured absolute gravity data is given at points in ellipsoidal coordinates.\nThe observed values should be converted to SI units~$m/s^2$.\n\\begin{itemize}\n  \\item \\program{Matrix2GriddedData} to convert data from text file in tabular form.\n\\end{itemize}\n\n\\fig{!ht}{0.5}{regionalGeoidGravimetricData}{fig:regionalGeoidGravimetricData}{Distribution of gravimetric observations}\n\n\\subsection{Topography}\nA high resolution topography model is needed to reduce the observations.\nAs the model heights are usually given in physical heights a reference geoid is needed to compute the correct ellipsoidal height.\n\\begin{itemize}\n  \\item \\program{NetCdf2GridRectangular} convert into groops format.\n  \\item \\program{Gravityfield2GriddedData}: Compute geoid heights using the GOCO06s model with\n  \\begin{itemize}\n    \\item \\configClass{grid:file}{gridType:file} The topography grid\n    \\item \\configClass{kernel:geoidHeight}{kernelType:geoidHeight}\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients} the GOCO06s model\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\n    Subtract (\\config{factor}=-1) GRS680 normal field.\n  \\end{itemize}\n  \\item \\program{GriddedDataCalculate}: Generate a new combined griddedData file\n        with the orthometric height (\\verb|data0|) and the geoid height (\\verb|data1|).\n  \\item \\program{GriddedTopography2PotentialCoefficients}: Compute the gravitational potential in terms\n        of spherical harmonics up to a maximum degree of the global satellite model.\n        This is the part of the topography, which is already included in the global satellite model.\n        The integration boundaries are \\config{radialUpperBound}=\\verb|data0+data1|\n        and \\config{radialLowerBound}=\\verb|data1|.\n\\end{itemize}\n\n\\fig{!ht}{1.0}{regionalGeoidTopography}{fig:regionalGeoidTopography}{Topography and geoid heights}\n\n\\subsection{Reduce}\nCalculate approximate reference gravity to reduce it from the observations.\n\\begin{itemize}\n  \\item \\program{Gravityfield2AbsoluteGravity}\n  \\begin{itemize}\n    \\item \\configClass{grid:File}{gridType:file} at observation positions\n    \\item \\configClass{gravityfield:tides}{gravityfieldType:tides} Centrifugal potential\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients} full GOCO06s model\n    \\item \\configClass{gravityfield:topography}{gravityfieldType:topography}\n          (\\config{radialUpperBound}=\\verb|data0+data1|, \\config{radialLowerBound}=\\verb|data1|)\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\n          Subtract (\\config{factor}=-1) the potential part of the topography already included in the GOCO06s model.\n  \\end{itemize}\n  \\item \\program{GriddedDataCalculate} to calculate observed minus computed.\n  \\item Large outliers can be removed in \\program{GriddedDataCalculate} with \\config{removalCriteria}.\n\\end{itemize}\n\n\\fig{!hb}{0.5}{regionalGeoidObserved-computed}{fig:regionalGeoidObserved-computed}{Gravity disturbances: observed minus computed}\n\n\n\\subsection{Radial Basis Functions (RBF)}\nThe residual gravity is parametrized in terms of Radial Basis Functions\n\\configClass{parametrizationGravity:radialBasis}{parametrizationGravityType:radialBasis}.\nThe basis functions should be distributed on a regular \\configClass{grid}{gridType} covering\na somewhat larger area than the observations, see \\configClass{border}{borderType}.\nThe shape of the functions \\configClass{kernel:coefficients}{kernelType:coefficients} should reflect\nthe signal content of reduced observations and are defined by the coefficients.\n\\begin{itemize}\n  \\item \\program{RadialBasisSplines2KernelCoefficients}\n  \\begin{itemize}\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients} accuracies of GOCO06s model\n    \\item \\config{maxDegree}=7000. Complemented by Kaula's rule of thumb\n  \\end{itemize}\n\\end{itemize}\nThe maximum degree should correspond to the spatial resolution.\nRule of thumb: the number of spherical harmonic coefficients $(\\text{maxDegree}+1)^2$ should roughly agree\nto the number of grid points if they would cover the complete Earth.\n\n\\fig{!hb}{0.5}{regionalGeoidDegreeAmplitudes}{fig:regionalGeoidDegreeAmplitudes}{Degree amplitudes for the shape of the radial basis functions}\n\n\\subsection{Compute: Estimate parameters in a least squares adjustment}\nSetup the observation equations and accumulate the system of normal equations.\n\\begin{itemize}\n\\item \\program{NormalsBuild}\n  \\begin{itemize}\n    \\item \\configClass{normalEquation:design}{normalEquationType:design} with\n          \\configClass{observation:terrestrial}{observationType:terrestrial}\n    \\begin{itemize}\n      \\item \\configClass{kernel:disturbance}{kernelType:disturbance}\n      \\item \\configClass{parametrizationGravity:radialBasis}{parametrizationGravityType:radialBasis}\n            with \\configClass{kernel:coefficients}{kernelType:coefficients}\n    \\end{itemize}\n  \\end{itemize}\n\\item \\program{NormalsSolverVCE}\n  \\begin{itemize}\n    \\item \\configClass{normalEquation:file}{normalEquationType:file} from \\program{NormalsBuild}\n    \\item \\configClass{normalEquation:regularization}{normalEquationType:regularization}\n           towards zero means regularization towards the GOCO06s, which is reduced from the data.\n  \\end{itemize}\n\\end{itemize}\n\n\\subsection{Restore: Calculate the geoid solution}\nEvaluate the estimated parameters and add back the reduced reference models.\n\\begin{itemize}\n  \\item \\program{Gravityfield2GriddedData}: Compute approximate geoid heights using the GOCO06s model with\n  \\begin{itemize}\n    \\item \\configClass{grid}{gridType} select a grid with target resolution at elliposid\n    \\item \\configClass{kernel:geoidHeight}{kernelType:geoidHeight}\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients} GOCO06s model\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\n    Subtract (\\config{factor}=-1) GRS80 normal field.\n  \\end{itemize}\n  \\item \\program{GriddedDataCalculate}: Move points from ellipsoid to geoid with \\config{height}=\\verb|data0|\n  \\item \\program{Gravityfield2GriddedData}\n  \\begin{itemize}\n    \\item \\configClass{grid:file}{gridType:file} from above.\n    \\item \\configClass{kernel:geoidHeight}{kernelType:geoidHeight}\n    \\item \\configClass{gravityfield:fromParametrization}{gravityfieldType:fromParametrization}\n          The solution vector~$\\M x$ together with the RBF parametrization\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients} GOCO06s model\n    \\item \\configClass{gravityfield:topography}{gravityfieldType:topography}\n          (\\config{radialUpperBound}=\\verb|data0+data1|, \\config{radialLowerBound}=\\verb|data1|)\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\n          Subtract (\\config{factor}=-1) the potential part of the topography already included in the GOCO06s model.\n    \\item \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\n          Subtract (\\config{factor}=-1) GRS80 normal field.\n    \\item \\config{convertToHarmonics}=\\verb|no|, otherwise the RBF are converted to harmonics up to degree 7000.\n  \\end{itemize}\n  \\item \\program{GriddedDataCalculate}: Set \\config{height}=0 of the computed geoid grid.\n  \\item \\program{GridRectangular2NetCdf}\n\\end{itemize}\n\n\\fig{!hb}{0.6}{regionalGeoidGeoid}{fig:regionalGeoidGeoid}{Estimated geoid}\n\n\n% =============================================================\n"
  },
  {
    "path": "docs/latex/documentation.tex",
    "content": "\\documentclass[10pt,twoside,titlepage]{report}\n\\usepackage[utf8x]{inputenc}\n\\usepackage[fleqn]{amsmath}\n\\usepackage{array}\n\\usepackage{varwidth}\n\\usepackage{ltablex}\n\\usepackage{vmargin}\n\\usepackage{fancyhdr}\n\\usepackage[pdftex]{graphicx}\n\\usepackage[pdftex,pagebackref=true,unicode]{hyperref}\n\\pdfcompresslevel=9\n\\hypersetup{colorlinks=true,linkcolor=[rgb]{0.01176,0.38039,0.67058},urlcolor=[rgb]{0.01176,0.38039,0.67058}}\n\n% Style\n% -----\n\\parindent0mm\n\\parskip2ex plus1ex minus1ex\n\\frenchspacing\n\\sloppy\n\\setcounter{secnumdepth}{3}\n\\setcounter{tocdepth}{1}\n\\setpapersize{A4}\n\\setmarginsrb{2.5cm}{1cm}{2cm}{2cm}{8mm}{15mm}{5mm}{15mm}\n\n\\pagestyle{fancy}\n\\addtolength{\\headwidth}{0.7cm}\n\\renewcommand{\\chaptermark}[1]{\\markboth{\\slshape\\thechapter.\\ #1}{}}\n\\renewcommand{\\sectionmark}[1]{\\markright{\\slshape\\thesection.\\ #1}}\n\\fancyhead[L,R]{\\slshape\\thepage}\n\\fancyhead[LO]{\\slshape\\nouppercase{\\rightmark}}\n\\fancyhead[RE]{\\slshape\\nouppercase{\\leftmark}}\n\\cfoot{}\n\n\\fancypagestyle{plain}{%\n\\pagestyle{fancy}\n\\fancyhead[RO]{\\slshape\\thepage}\n\\fancyhead[LE]{\\slshape\\thepage}\n\\fancyhead[LO]{}\n\\fancyhead[RE]{}\n}\n\n% Config table style\n% ------------------\n\\newcolumntype{N}{>{\\begin{varwidth}{6cm}}l<{\\end{varwidth}}} % Name column (with max. width of 6cm)\n\\newcolumntype{T}{l}                                          % Type column\n\\newcolumntype{A}{X}                                          % Annotation column\n\n% Commands\n% --------\n\\newcommand{\\config}[1]{\\protect\\includegraphics[width=0.9em]{element.pdf}\\,\\textbf{#1}}\n\\newcommand{\\configClass}[2]{\\protect\\includegraphics[width=0.9em]{element.pdf}\\,\\hyperref[#2]{\\textbf{#1}}}\n\\newcommand{\\configFile}[2]{\\protect\\includegraphics[width=0.9em]{element.pdf}\\,\\hyperref[general.fileFormat:#2]{\\textbf{#1}}}\n\\newcommand{\\program}[1]{\\protect\\includegraphics[width=0.9em]{program.pdf}\\,\\hyperref[#1]{\\textbf{#1}}}\n\\newcommand{\\file}[2]{\\protect\\includegraphics[height=1.7ex]{file.pdf}\\,\\hyperref[general.fileFormat:#2]{#1}}\n\\newcommand{\\reference}[2]{\\hyperref[#2]{#1~(\\ref{#2})}}\n\\newcommand{\\M}[1]{\\mathbf{#1}}\n\n% \\fig{position}{width as fraction of textwidth}{filename}{label}{caption}\n% ------------------------------------------------------------------------\n\\newcommand{\\fig}[5]{%\n\\begin{figure}[#1]%\n\\centering%\n\\includegraphics*[width=#2\\textwidth]{#3}%\n\\caption{#5}\\label{#4}%\n\\end{figure}%\n}\n\n%=========================================\n\n\\begin{document}\n\\hfuzz=5000pt\n\\vfuzz=5000pt\n\\hbadness=10000\n\\vbadness=10000\n\n\\graphicspath{{../figures/}}\n\n%---------------------------- title page ------------------------------------\n\\thispagestyle{empty}\n\\begin{center}\n\\vspace*{6cm}\n\\begin{figure}[!h]\n\\centering\n\\includegraphics*[width=0.75\\textwidth]{groops_banner}\n\\end{figure}\n\\vspace*{0.2cm}\n{\\huge\\sf Gravity Recovery Object Oriented Programming System} \\\\\n\\vspace*{2cm}\n{\\huge\\sf Documentation} \\\\\n\\vspace*{2cm}\n{\\Large\\sf GitHub repository: \\url{https://github.com/groops-devs/groops}}\n\\end{center}\n\n\\newpage\n\\clearpage{\\pagestyle{empty}} %\\cleardoublepage}%\n%\\pagenumbering{Roman}\n\\tableofcontents%\n\\clearpage{\\pagestyle{empty}\\cleardoublepage\\clearpage}\n\n\\chapter{General information}\nThe Gravity Recovery Object Oriented Programming System (GROOPS) is a software toolkit written in C++\nthat enables the user to perform core geodetic tasks.\nKey features of the software include gravity field recovery from satellite and terrestrial data,\nthe determination of satellite orbits from global navigation satellite system (GNSS) measurements,\nand the processing of GNSS constellations and ground station networks. Most tasks and algorithms are\n(optionally) parallelized through the Message Passing Interface (MPI), thus the software enables\na smooth transition from single-CPU desktop computers to large distributed\ncomputing environments for resource intensive tasks.\n\nParts of GROOPS originate from developments in the Astronomical, Physical and Mathematical Geodesy Group\nat the University of Bonn, Germany. Since 2010 it is developed and maintained at Graz University of Technology, Austria.\nIt is licensed under GPLv3 and hosted at GitHub, \\url{https://github.com/groops-devs/groops}.\n\nIf you use data sets computed with GROOPS in a publication or publish the data itself, please cite our reference paper:\\\\\nMayer-Guerr, T., Behzadpour, S., Eicker, A., Ellmer, M., Koch, B., Krauss, S., Pock, C., Rieser, D., Strasser, S., Suesser-Rechberger,\nB., Zehentner, N., Kvas, A. (2021). GROOPS: A software toolkit for gravity field recovery and GNSS processing.\nComputers and Geosciences, 104864. \\url{https://doi.org/10.1016/j.cageo.2021.104864}.\n\nGROOPS depends on data files such as Earth rotation, Love numbers, and GNSS meta information.\nAn initial data set that is regularly updated is available on our FTP server,\n\\url{https://ftp.tugraz.at/pub/ITSG/groops}. You can choose between downloading the data directory\nor a single \\href{https://ftp.tugraz.at/pub/ITSG/groops/data.zip}{data.zip} with the same content.\n\n\\input{general.configFiles}\n\\clearpage\n\\input{general.parser}\n\\clearpage\n\\input{general.loopsAndConditions}\n\\clearpage\n\\input{general.constants}\n\\clearpage\n\\input{general.parallelization}\n\\clearpage\n\\input{general.gui}\n\\clearpage\n\\input{general.fileFormat}\n\\input{general.fileFormat.auto}\n\\clearpage\n\n\\chapter{Mathematical fundamentals}\nThis chapter describes the methods and mathematical fundamentals used throughout GROOPS.\n\\input{fundamentals.robustLeastSquares}\n\\clearpage\n\\input{fundamentals.basisSplines}\n\\clearpage\n\\input{fundamentals.autoregressiveModel}\n\n\\chapter{Cookbook}\\label{general.cookbook}\nThis chapter presents recipes to explore the GROOPS feature set.\n\\input{cookbook.instrument}\n\\clearpage\n\\input{cookbook.gnssNetwork}\n\\clearpage\n\\input{cookbook.gnssPpp}\n\\clearpage\n\\input{cookbook.kinematicOrbit}\n\\clearpage\n\\input{cookbook.gravityFieldPod}\n\\clearpage\n\\input{cookbook.gravityFieldGrace}\n\\clearpage\n\\input{cookbook.regionalGeoid}\n\n\\chapter{Programs}\\label{programType}\nThis chapter details programs included in GROOPS, describing what they are and what they do. For usage examples see the cookbook in Chapter~\\ref{general.cookbook}.\n\\input{programs.auto}\n\n\\chapter{Classes}\\label{classes}\nThis chapter details classes included in GROOPS, describing what they are and what they do. For usage examples see the cookbook in Chapter~\\ref{general.cookbook}.\n\\input{classes.auto}\n\n\\end{document}\n"
  },
  {
    "path": "docs/latex/fundamentals.autoregressiveModel.tex",
    "content": "\\section{Autoregressive Models}\\label{fundamentals.autoregressiveModel}\nA multivariate (or vector) autoregressive model is one possible representation of a random process.\nIt specifies, that the output at epoch $t$ depends on the $p$ previous epochs, where $p$ is denoted process order,\nplus a stochastic term.\nIn the following, finite order vector autoregressive - VAR($p$) in short - models as implemented in GROOPS will be described.\n\n\\subsection{Definition}\n\nA finite order VAR($p$) model is defined as\n\\begin{equation}\n  \\mathbf{y}_e(t_i) = \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{w}(t_i),\n  \\hspace{5pt} \\mathbf{w}(t_i) \\sim \\mathcal{N}(0, \\mathbf{\\Sigma}^{(p)}_\\mathbf{w}),\n\\end{equation}\nwhere $\\mathbf{y}_e(t_i)$ are realizations of a random vector process\nSubtracting the right hand side and substituting the stochastic term $-\\mathbf{w}(t_i)$ with the residual $\\mathbf{v}(t_i)$ gives us\n\\begin{equation}\n  \\mathbf{0}  = \\mathbf{y}_e(t_i) - \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{v}(t_i)\n\\end{equation}\nwhich can be used as pseudo-observation equations in the determination of the parameters $\\mathbf{y}_e(t_i)$.\nIn matrix notation this reads\n\\begin{equation}\n  0 =\n  \\begin{bmatrix}\n    \\mathbf{I} & -\\mathbf{\\Phi}^{(p)}_1 & \\cdots & -\\mathbf{\\Phi}^{(p)}_p \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{y}_e(t_i) \\\\\n    \\mathbf{y}_e(t_{i-1}) \\\\\n    \\vdots \\\\\n    \\mathbf{y}_e(t_{i-p}) \\\\\n  \\end{bmatrix}\n  + \\mathbf{v}(t_i).\n\\end{equation}\nAfter rearranging the vectors $\\mathbf{x}_t$ to have ascending time stamps\n\\begin{equation}\n  0 =\n  \\begin{bmatrix}\n    -\\mathbf{\\Phi}^{(p)}_p & \\cdots & -\\mathbf{\\Phi}^{(p)}_1 & \\mathbf{I} \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{y}_e(t_{i-p}) \\\\\n    \\vdots \\\\\n    \\mathbf{y}_e(t_{i-1}) \\\\\n    \\mathbf{y}_e(t_i) \\\\\n  \\end{bmatrix}\n  + \\mathbf{v}(t_i)\n\\end{equation}\nFor practical purposes, the residuals above are further decorrelated using the\ninverse square root of the white noise covariance matrix, leading to\n\\begin{equation}\n  \\bar{\\mathbf{v}}(t_i) = \\underbrace{\\mathbf{\\Sigma}^{(p)^{-\\frac{1}{2}}}_\\mathbf{w}}_{=\\mathbf{W}}\\mathbf{v}(t_i), \\hspace{25pt}  \\bar{\\mathbf{v}}(t_i) \\sim \\mathcal{N}(0, \\mathbf{I}).\n\\end{equation}\nThe used square root is in principle arbitrary, but should satisfy $\\mathbf{W}^T\\mathbf{W} = \\mathbf{\\Sigma}^{(p)}_\\mathbf{w} $.\nThis means that both eigendecomposition based roots and Cholesky factors can be used.\nAfter the applying the matrix from the left, we arrive at the observation equations\n\\begin{equation}\n  0 =\n  \\begin{bmatrix}\n    -\\mathbf{W}\\mathbf{\\Phi}^{(p)}_p & \\cdots & -\\mathbf{W}\\mathbf{\\Phi}^{(p)}_1 & \\mathbf{W} \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{y}_e(t_{i-p}) \\\\\n    \\vdots \\\\\n    \\mathbf{y}_e(t_{i-1}) \\\\\n    \\mathbf{y}_e(t_i) \\\\\n  \\end{bmatrix}\n  + \\bar{\\mathbf{v}}(t_i)\n\\end{equation}\nwhich yields fully decorrelated residuals.\nCurrenty, VAR($p$) models are saved to a single  file which contains this matrix.\n"
  },
  {
    "path": "docs/latex/fundamentals.basisSplines.tex",
    "content": "\\section{Basis splines}\\label{fundamentals.basisSplines}\nA time variable function is given by\n\\begin{equation}\nf(x,t) =  \\sum_i f_i(x)\\Psi_i(t),\n\\end{equation}\nwith the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions~$\\Psi_i(t)$.\nBasis splines are defined as polynomials of degree~$n$ in intervals between nodal points in time $t_i$:\n\\begin{itemize}\n\\item Block mean values ($n=0$)\n\\begin{equation}\n  \\Psi_i(t) = \\begin{cases}\n  1 & \\text{if } t\\in[t_i,t_{i+1}), \\\\\n  0 & \\text{otherwise}\n\\end{cases}\n\\end{equation}\n\\item Linear splines ($n=1$)\n\\begin{equation}\n  \\Psi_i(t) = \\begin{cases}\n    \\tau_{i-1}  & \\text{if } t_{i-1} \\le t \\le t_i, \\\\\n  1-\\tau_i      & \\text{if } t_{i}   \\le t \\le t_{i+1}, \\\\\n  0 & \\text{otherwise}.\n\\end{cases}\n\\end{equation}\n\\item Quadratic splines ($n=2$)\n\\begin{equation}\n  \\Psi_i(t) = \\begin{cases}\n  \\frac{1}{2}\\tau^2_{i-1}                           & \\text{if } t_{i-1} \\le t \\le t_i, \\\\\n            -\\tau^2_{i}   +\\tau_{i}   +\\frac{1}{2}  & \\text{if } t_{i}   \\le t \\le t_{i+1}, \\\\\n  \\frac{1}{2}\\tau^2_{i+1} -\\tau_{i+1} +\\frac{1}{2}  & \\text{if } t_{i+1} \\le t \\le t_{i+2}, \\\\\n  0 & \\text{otherwise}.\n\\end{cases}\n\\end{equation}\n\\item Cubic splines ($n=3$)\n\\begin{equation}\n  \\Psi_i(t) = \\begin{cases}\n   \\frac{1}{6}\\tau^3_{i-2}                                                               & \\text{if } t_{i-2} \\le t \\le t_{i-1}, \\\\\n  -\\frac{3}{6}\\tau^3_{i-1} +\\frac{3}{6}\\tau^2_{i-1} +\\frac{3}{6}\\tau_{i-1} +\\frac{1}{6}  & \\text{if } t_{i-1} \\le t \\le t_i,     \\\\\n   \\frac{3}{6}\\tau^3_{i}   -           \\tau^2_{i}   +\\frac{4}{6}                         & \\text{if } t_{i}   \\le t \\le t_{i+1}, \\\\\n  -\\frac{1}{6}\\tau^3_{i+1} +\\frac{3}{6}\\tau^2_{i+1} -\\frac{3}{6}\\tau_{i+1} +\\frac{1}{6}  & \\text{if } t_{i+1} \\le t \\le t_{i+2}, \\\\\n  0 & \\text{otherwise}.\n\\end{cases}\n\\end{equation}\n\\end{itemize}\nwhere $\\tau$ is the normlized time in each time interval\n\\begin{equation}\n  \\tau_i = \\frac{t-t_i}{t_{i+1}-t_i}.\n\\end{equation}\nThe total number of coefficients $f_i(x)$ is $N=N_t+n-1$,\nwhere $N_t$ is the count of nodal time points~$t_i$ and $n$ is the degree.\n\n\\fig{!hb}{0.8}{basissplines}{fig:basissplines}{Basis splines for different degrees with nodal points every 6 hours.}\n"
  },
  {
    "path": "docs/latex/fundamentals.robustLeastSquares.tex",
    "content": "\\section{Robust least squares adjustment}\\label{fundamentals.robustLeastSquares}\nThe robust least squares adjustment used in GROOPS is based on a modified Huber\nestimator. It downweights observations with large otuliers iteratively.\n\nThe algorithm starts with a first solution with equal weights $\\M P =\\M I$\n\\begin{equation}\n  \\hat{\\M x} = (\\M A^T\\M P\\M A)^{-1}\\M A^T\\M P\\M l.\n\\end{equation}\nThe solution is used to compute the residuals\n\\begin{equation}\n  \\hat{e}_i = \\left(\\M l - \\M A \\hat{\\M x}\\right)_i\n\\end{equation}\nand the redundancies of all observations\n\\begin{equation}\n  r_i = \\left(\\M I - \\M A(\\M A^T\\M P\\M A)^{-1}\\M A^T\\M P\\right)_{ii}.\n\\end{equation}\nFor observations with large residuals a new standard deviation is assigned\n\\begin{equation}\n  \\sigma_i =\n  \\begin{cases}\n    1                                     & \\text{for } \\left|\\frac{\\hat{e}_i}{r_i}\\right| \\le h\\cdot\\hat{\\sigma} \\\\\n    \\left|\\frac{\\hat{e}_i}{r_ih}\\right|^p & \\text{for } \\left|\\frac{\\hat{e}_i}{r_i}\\right| > h\\cdot\\hat{\\sigma},\n  \\end{cases}\n\\end{equation}\nwhere $h$ is \\config{huber}, $p$ is \\config{huberPower}, and $\\hat{\\sigma}^2$ a robust overall variance factor\ncomputed from all residuals.\nThe estimation is repeated \\config{huberMaxIteration} times with a new weight matrix\n\\begin{equation}\n  \\M P = \\text{diag}\\left(\\frac{1}{\\sigma_1^2}, \\frac{1}{\\sigma_2^2}, \\ldots, \\frac{1}{\\sigma_n^2}\\right)\n\\end{equation}\n or until convergence is reached.\n"
  },
  {
    "path": "docs/latex/general.configFiles.tex",
    "content": "\\section{Config files}\\label{general.configFiles}\nGROOPS is controlled by XML configuration files. One or more configuration files\nmust be passed as arguments to GROOPS:\n\\begin{verbatim}\n  groops config1.xml config2.xml [...]\n\\end{verbatim}\nThese files can be created with the graphical user interface program \\verb|groopsGui|\nin a convenient way (see section~\\reference{GUI}{general.gui}).\nA complete formal (computer readable) description of a configuration file\nin the form of an XSD schema file can be created with the command\n\\begin{verbatim}\n  groops --xsd groops.xsd\n\\end{verbatim}\n\nA configuration file consists of a list of \\reference{programs}{programType}\nthat are executed in sequential order. Each program comes with its own config options\nand they work independently without any internal communication between programs.\nData flow between programs is realized via files. An \\config{outputfile} of one program can serve as\nan \\config{inputfile} for the next program.\nMost programs are deliberately kept small and focused on a specific task. This modularity combined with the\ngeneral purpose design of many programs enables the creation of complex workflows with little effort.\nIncluding \\reference{loops and conditions}{general.loopsAndConditions} in a config file provides even more flexibility.\n\nIndividual programs (and also other optional config elements) can be disabled\nand are ignored during execution. Mandatory config elements are indicated by a star (\\verb|*|).\nEmpty optional elements are ignored or a meaningful default value is assumed.\n\nThe elements of a configuration file can be one of the following basic data types:\n\\begin{itemize}\n\\item \\verb|int|: integer number\n\\item \\verb|uint|: unsigned integer number\n\\item \\verb|double|: floating point number\n\\item \\verb|angle|: given in degree\n\\item \\verb|time|: given in modified Julian date (MJD)\n\\item \\verb|boolean|: 0: false, 1: true\n\\item \\verb|string|: text\n\\item \\verb|filename|: absolute path to a file or path relative to the working directory\n\\item \\verb|expression|: numerical expression evaluated during execution\n\\item \\verb|doodson|: Doodson number or Darwin's name of a tidal frequency\n\\item \\verb|gnssType|: GNSS observation type according to the RINEX 3 definition\n\\end{itemize}\nThe first 5 data types also allow numerical expressions as input in addition to pure numbers.\nIn addition to these basic types, there are a large number of complex data types called classes,\nwhich are described in section~\\reference{Classes}{classes}.\n\n\\subsection{Variables}\\label{general.configFiles:variables}\nIn addition to programs, a config file can also include elements called variables.\nThese elements are comparable to read-only variables in programming and can be referenced from any program and config element.\nThis can be done by either linking an element directly to a variable or\nby using the name as a variable in an expression of an input field (see section~\\reference{Parsers and variables}{general.parser}).\nWhile elements can only be directly linked to variables of the same type, this also supports complex data types\nsuch as \\configClass{gravityfield}{gravityfieldType}. Thus it is possible to, for example, define a reference gravity field once\nin the global section and use it multiple times in different programs.\n\nVariables can be declared anywhere in the configuration file. Variables in locations other than the global section\nhave a local scope and hide global variables or variables from a hierarchy level above. They are valid after\ndeclaration until the end of the hierarchy level is reached or a new variable with the same name is declared.\n\nVariables are not evaluated directly when they are declared, but only later when they are used in a config element.\nThis means, for example, that a variable \\verb|satelliteFile| with \\verb|data/swarm_orbit_{loopTime:%D}.dat|\ncan be declared in the global section without the variable \\verb|loopTime| having to be known at this time.\n\nOne special variable is \\verb|groopsDataDir|, which is used as a variable in most default\nfile paths throughout many GROOPS programs. Since this variable is going to be needed in\nmost config files, it is recommended to define it in a template file that is used when creating\nnew config files in the GUI. See section~\\reference{Graphical User Interface (GUI)}{general.gui}\nfor details on how to set up a template file.\n\nIn addition, the variables \\verb|groopsConfigFile| and \\verb|workingDir| are set automatically.\n\nGlobal variables can be manipulated when running a config file by passing the argument \\verb|--global <name>=<value>|.\nFor example, running the command\n\\begin{verbatim}\n  groops --global timeStart=58849 --global satellite=swarm config.xml\n\\end{verbatim}\nruns the config file \\verb|config.xml| but replaces the values of the global variable \\verb|timeStart|\nand \\verb|satellite| with \\verb|58849| and \\verb|swarm|, respectively. If a global variable passed as\nan argument does not already exist in the config file, it will be added with the type \\verb|string|.\nOnly the basic data types listed above are supported. This feature can be useful when running GROOPS\nfrom the command line or from an external script file.\n"
  },
  {
    "path": "docs/latex/general.constants.tex",
    "content": "\\section{Constants and the settings file}\\label{general.constants}\nGROOPS uses some built-in constants like \\verb|DEFAULT_GM| or the definition\nof leap seconds, which are defined in  \\verb|source/base/constants.cpp|.\n\nA complete list of the constants can be written to an XML file with:\n\\begin{verbatim}\n  groops --write-settings <groopsDefaults.xml>\n\\end{verbatim}\n\nThe built-in constants can be overwritten by a \\verb|groopsDefaults.xml| file\nin the working directory or by explicitly passing the file as an argument at execution:\n\\begin{verbatim}\n  groops --settings <groopsDefaults.xml> <config.xml>\n\\end{verbatim}\n\nIt might also be useful to adjust the default values in the schema file used by the \\reference{GUI}{general.gui}:\n\\begin{verbatim}\n  groops --settings <groopsDefaults.xml> --xsd <groops.xsd>\n\\end{verbatim}\n\nExample file:\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops>\n  <LIGHT_VELOCITY>299792458</LIGHT_VELOCITY>\n  <DEFAULT_GM>3.986004415e+14</DEFAULT_GM>\n  <DEFAULT_R>6378136.3</DEFAULT_R>\n  <GRS80_a>6378137.0</GRS80_a>\n  <GRS80_f>298.2572221010</GRS80_f>\n  <GRAVITATIONALCONSTANT>6.6730e-11</GRAVITATIONALCONSTANT>\n  <R_Earth>6.37813630000000e+06</R_Earth>\n  <R_Moon>1.73800000000000e+06</R_Moon>\n  <GM_Earth>3.98600441500000e+14</GM_Earth>\n  <GM_Sun>1.32712442076000e+20</GM_Sun>\n  <GM_Moon>4.90280105600000e+12</GM_Moon>\n  <GM_MERCURY>2.20320808280762e+13</GM_MERCURY>\n  <GM_VENUS>3.24858603864143e+14</GM_VENUS>\n  <GM_MARS>4.28283149222192e+13</GM_MARS>\n  <GM_JUPITER>1.26712769822770e+17</GM_JUPITER>\n  <GM_SATURN>3.79406266494906e+16</GM_SATURN>\n  <TIME_EPSILON>1.0e-05</TIME_EPSILON>\n  <DELTA_TAI_GPS>19</DELTA_TAI_GPS>\n  <DELTA_TT_GPS>51.184</DELTA_TT_GPS>\n  <J2000>51544.5</J2000>\n  <leapSecond>\n    <MJD>57754</MJD>\n    <DELTA_UTC_GPS>-18</DELTA_UTC_GPS>\n  </leapSecond>\n  <leapSecond>\n    <MJD>57204</MJD>\n    <DELTA_UTC_GPS>-17</DELTA_UTC_GPS>\n  </leapSecond>\n  <leapSecond>\n    <MJD>56109</MJD>\n    <DELTA_UTC_GPS>-16</DELTA_UTC_GPS>\n  </leapSecond>\n\n  ...\n\n  <leapSecond>\n    <MJD>41317</MJD>\n    <DELTA_UTC_GPS>9</DELTA_UTC_GPS>\n  </leapSecond>\n  <leapSecond>\n    <MJD>0</MJD>\n    <DELTA_UTC_GPS>10</DELTA_UTC_GPS>\n  </leapSecond>\n</groops>\n\\end{verbatim}\n"
  },
  {
    "path": "docs/latex/general.fileFormat.auto.tex",
    "content": "% auto generated by GROOPS\n\\subsection{Admittance}\\label{general.fileFormat:admittance}\nInterpolation matrix to create ocean minor tides from modeled major tides.\nThe file can be created with \\program{DoodsonHarmonicsCalculateAdmittance} and used e.g. in\n\\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}.\n\nSee \\program{DoodsonHarmonicsCalculateAdmittance}.\n\n\n%==================================\n\\subsection{ArcList}\\label{general.fileFormat:arcList}\nWith the \\program{InstrumentSynchronize} an \\file{instrument file}{instrument} can\nbe divided into time intervals and within the intervals into arcs.\nThis file provides the information about the mapping of arcs to time intervals.\n\nThis file can be used for the variational equation approach or \\program{KalmanBuildNormals}.\n\n\\begin{verbatim}\ngroops arclist version=20200123\n         32  # number of times\n# time [MJD]               first arc\n# ==================================\n 58909.000000000000000000          0\n 58910.000000000000000000          8\n 58911.000000000000000000         17\n 58912.000000000000000000         25\n 58913.000000000000000000         29\n 58914.000000000000000000         37\n 58915.000000000000000000         45\n 58916.000000000000000000         53\n 58917.000000000000000000         61\n 58918.000000000000000000         69\n 58919.000000000000000000         78\n 58920.000000000000000000         86\n 58921.000000000000000000         95\n 58922.000000000000000000        103\n 58923.000000000000000000        112\n 58924.000000000000000000        120\n 58925.000000000000000000        128\n 58926.000000000000000000        136\n 58927.000000000000000000        144\n 58928.000000000000000000        153\n 58929.000000000000000000        161\n 58930.000000000000000000        169\n 58931.000000000000000000        177\n 58932.000000000000000000        185\n 58933.000000000000000000        193\n 58934.000000000000000000        201\n 58935.000000000000000000        210\n 58936.000000000000000000        218\n 58937.000000000000000000        226\n 58938.000000000000000000        234\n 58939.000000000000000000        242\n 58940.000000000000000000        250\n\\end{verbatim}\n\n\n%==================================\n\\subsection{DoodsonEarthOrientationParameter}\\label{general.fileFormat:doodsonEarthOrientationParameter}\nCorrections for Earth orientation parameters (EOP) ($x_p, y_p, UT1, LOD$)\nas cos/sin oscillations for a list of doodson tidal frequencies.\n\n\\begin{verbatim}\ngroops doodsonEarthOrientationParameter version=20200123\n        11 # number of constituents\n# dood.   xpCos [arcsec]            xpSin [arcsec]            ypCos [arcsec]            ypSin [arcsec]            ut1Cos [sec]              ut1Sin [sec]              lodCos [sec]              lodSin [sec]             name\n# ===========================================================================================================================================================================================================================\n 155.645  2.399999999999999786e-07  1.799999999999999971e-07  1.799999999999999971e-07 -2.399999999999999786e-07 -2.000000000000000042e-08  2.000000000000000042e-08 -1.499999999999999932e-07 -1.400000000000000095e-07 \"\"\n 155.655 -8.220000000000000920e-06 -6.280000000000000012e-06 -6.280000000000000012e-06  8.220000000000000920e-06  7.899999999999999537e-07 -8.599999999999999187e-07  5.219999999999999150e-06  4.829999999999999496e-06 m1\n 155.665 -1.649999999999999872e-06 -1.260000000000000007e-06 -1.260000000000000007e-06  1.649999999999999872e-06  1.600000000000000033e-07 -1.700000000000000135e-07  1.049999999999999900e-06  9.700000000000000302e-07 \"\"\n 157.455 -1.539999999999999867e-06 -1.199999999999999946e-06 -1.199999999999999946e-06  1.539999999999999867e-06  1.499999999999999932e-07 -1.600000000000000033e-07  9.799999999999999345e-07  8.899999999999999491e-07 chi1\n 157.465 -3.400000000000000270e-07 -2.599999999999999988e-07 -2.599999999999999988e-07  3.400000000000000270e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.099999999999999746e-07  1.999999999999999909e-07 \"\"\n 161.557  9.999999999999999547e-08  8.000000000000000167e-08  8.000000000000000167e-08 -9.999999999999999547e-08 -1.000000000000000021e-08  1.000000000000000021e-08 -7.000000000000000477e-08 -4.999999999999999774e-08 \"\"\n 162.556  2.549999999999999726e-06  2.019999999999999718e-06  2.019999999999999718e-06 -2.549999999999999726e-06 -2.099999999999999746e-07  2.899999999999999763e-07 -1.799999999999999919e-06 -1.289999999999999931e-06 pi1\n 163.545 -4.899999999999999672e-07 -3.799999999999999616e-07 -3.799999999999999616e-07  4.899999999999999672e-07  4.000000000000000084e-08 -5.999999999999999464e-08  3.499999999999999842e-07  2.399999999999999786e-07 \"\"\n 163.555  4.272999999999999238e-05  3.010999999999999801e-05  3.010999999999999801e-05 -4.272999999999999238e-05 -3.079999999999999734e-06  5.219999999999999150e-06 -3.270999999999999684e-05 -1.929999999999999817e-05 p1\n 164.554 -3.599999999999999943e-07 -2.800000000000000191e-07 -2.800000000000000191e-07  3.599999999999999943e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.700000000000000090e-07  1.700000000000000135e-07 \"\"\n 164.556 -1.029999999999999879e-06 -7.999999999999999638e-07 -7.999999999999999638e-07  1.029999999999999879e-06  8.000000000000000167e-08 -1.199999999999999893e-07  7.599999999999999233e-07  4.899999999999999672e-07 \"\"\n\\end{verbatim}\n\n\n%==================================\n\\subsection{DoodsonHarmonic}\\label{general.fileFormat:doodsonHarmonic}\nOcean tides are represented as time variable gravitational potential\nand is given by a fourier expansion\n\\begin{equation}\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\Theta_f(t)) + V_f^s(\\M x)\\sin(\\Theta_f(t)),\n\\end{equation}\nwhere $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics.\nThe $\\Theta_f(t)$ are the arguments of the tide constituents $f$:\n\\begin{equation}\n\\Theta_f(t) = \\sum_{i=1}^6 n_f^i\\beta_i(t),\n\\end{equation}\nwhere $\\beta_i(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$) and $n_f^i$\nare the Doodson multipliers for the term at frequency~$f$.\n\nTo extract the potential coefficients of $V_f^c$ and $V_f^s$\nfor each frequency $f$ use \\program{DoodsonHarmonics2PotentialCoefficients}.\n\nSee also \\program{PotentialCoefficients2DoodsonHarmonics}.\n\n\n%==================================\n\\subsection{EarthOrientationParameter}\\label{general.fileFormat:earthOrientationParameter}\nEarth Orientation Parameter (EOP) as provided by the International Earth Rotation and Reference Systems Service (IERS) (e.g \\verb|EOP 14 C04 (IAU2000A)|).\n\nSee \\program{IersC04IAU2000EarthOrientationParameter}, \\program{IersRapidIAU2000EarthOrientationParameter}.\n\n\\begin{verbatim}\ngroops earthOrientationParameter version=20200123\n       9641 # number of epochs\n# UTC [MJD]                 xp [arcsec]               yp [arcsec]               deltUT [sec]              LOD [sec]                 dX [arcsec]               dY [arcsec]\n# ====================================================================================================================================================================================\n  5.894700000000000000e+04  5.690599999999999825e-02  4.099130000000000273e-01 -2.316246000000000138e-01  1.636400000000000094e-03 -2.900000000000000017e-05  5.800000000000000034e-05\n  5.894800000000000000e+04  5.771400000000000141e-02  4.110159999999999925e-01 -2.332083000000000073e-01  1.520099999999999923e-03 -6.000000000000000152e-05  2.199999999999999943e-05\n  5.894900000000000000e+04  5.813000000000000111e-02  4.120099999999999874e-01 -2.346157000000000104e-01  1.293099999999999935e-03 -7.200000000000000182e-05  3.199999999999999855e-05\n  5.895000000000000000e+04  5.854100000000000276e-02  4.129849999999999910e-01 -2.357567999999999886e-01  9.872999999999999832e-04 -7.600000000000000418e-05  5.899999999999999754e-05\n  5.895100000000000000e+04  5.908599999999999963e-02  4.139869999999999939e-01 -2.366149999999999920e-01  7.075000000000000126e-04 -8.000000000000000654e-05  8.600000000000000331e-05\n  5.895200000000000000e+04  5.976900000000000268e-02  4.154180000000000095e-01 -2.372105999999999937e-01  4.798000000000000073e-04 -8.399999999999999535e-05  1.129999999999999955e-04\n  5.895300000000000000e+04  6.095400000000000124e-02  4.167310000000000181e-01 -2.375994999999999913e-01  3.118999999999999919e-04 -8.700000000000000051e-05  1.399999999999999877e-04\n  5.895400000000000000e+04  6.210199999999999748e-02  4.180929999999999924e-01 -2.378588000000000091e-01  1.710000000000000094e-04 -9.100000000000000287e-05  1.669999999999999935e-04\n  5.895500000000000000e+04  6.290999999999999370e-02  4.196619999999999795e-01 -2.380454999999999932e-01  1.719000000000000042e-04 -6.000000000000000152e-06  8.100000000000000375e-05\n  5.895600000000000000e+04  6.385599999999999610e-02  4.214060000000000028e-01 -2.382557999999999898e-01  2.683000000000000163e-04  1.029999999999999964e-04 -3.600000000000000091e-05\n  5.895700000000000000e+04  6.455500000000000127e-02  4.229890000000000039e-01 -2.385857000000000117e-01  4.040000000000000080e-04  1.019999999999999992e-04 -2.000000000000000164e-05\n  5.895800000000000000e+04  6.440300000000000191e-02  4.242549999999999932e-01 -2.390210000000000112e-01  4.910999999999999567e-04  5.899999999999999754e-05  4.399999999999999886e-05\n\\end{verbatim}\n\n\n%==================================\n\\subsection{EarthTide}\\label{general.fileFormat:earthTide}\nContaining the Love numbers together with frequency corrections to compute\nthe gravitational potential and the geometric displacements due to solid Earth tides.\nIt is used by \\configClass{tides}{tidesType}.\n\n\n%==================================\n\\subsection{Ephemerides}\\label{general.fileFormat:ephemerides}\nEphemerides of sun, moon, and planets stored as coefficients of Chebyshev polynomials.\nUsed in \\configClass{Ephemerides:jpl}{ephemeridesType:jpl}.\n\nSee also \\program{JplAscii2Ephemerides}.\n\n\n%==================================\n\\subsection{GnssAntennaDefinition}\\label{general.fileFormat:gnssAntennaDefinition}\nContains a list of GNSS antennas which are identified by its\nname (type), serial, and radome. Each antenna consists of\nantenna center offsets (ACO) and antenna center variations (ACV)\nfor different signal \\configClass{types}{gnssType} (code and phase).\nThe ACV values for each type are stored in an elevation and azimuth dependent grid.\n\n%New \\config{antenna} with \\config{pattern}s for code (\\config{type}=\\verb|C**|) and phase\n%(\\config{type}=\\verb|L**|).\n%The standard deviation is expressed e.g. with \\config{values}=\\verb|0.001/cos(2*PI/180*zenith)|.\n\nSee also \\program{GnssAntennaDefinitionCreate}, \\program{GnssAntex2AntennaDefinition}.\n\n\\fig{!hb}{1.0}{fileFormatGnssAntennaDefinition}{fig:fileFormatGnssAntennaDefinition}{Antenna center variations of ASH701945D\\_M for two frequencies of GPS and GLONASS}\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"antennaDefinition\" version=\"20190429\">\n    <antennaCount>65</antennaCount>\n    ...\n    <antenna>\n        <name>BLOCK IIIA</name>\n        <serial>G074</serial>\n        <radome>2018-109A</radome>\n        <comment>PCO provided by the Aerospace Corporation, PV from estimations by ESA/CODE</comment>\n        <pattern>\n            <count>3</count>\n            <cell>\n                <type>*1*G**</type>\n                <offset>\n                    <x>-1.23333333333333e-03</x>\n                    <y>4.33333333333333e-04</y>\n                    <z>3.15200000000000e-01</z>\n                </offset>\n                <dZenit>1.00000000000000e+00</dZenit>\n                <pattern>\n                    <type>0</type>\n                    <rows>1</rows>\n                    <columns>18</columns>\n                    <cell row=\"0\" col=\"0\">1.39000000000000e-02</cell>\n                    <cell row=\"0\" col=\"1\">1.28000000000000e-02</cell>\n                    <cell row=\"0\" col=\"2\">1.02000000000000e-02</cell>\n                    <cell row=\"0\" col=\"3\">5.80000000000000e-03</cell>\n                    <cell row=\"0\" col=\"4\">1.10000000000000e-03</cell>\n                    <cell row=\"0\" col=\"5\">-4.50000000000000e-03</cell>\n                    <cell row=\"0\" col=\"6\">-9.70000000000000e-03</cell>\n                    <cell row=\"0\" col=\"7\">-1.28000000000000e-02</cell>\n                    <cell row=\"0\" col=\"8\">-1.34000000000000e-02</cell>\n                    <cell row=\"0\" col=\"9\">-1.18000000000000e-02</cell>\n                    <cell row=\"0\" col=\"10\">-8.90000000000000e-03</cell>\n                    <cell row=\"0\" col=\"11\">-4.50000000000000e-03</cell>\n                    <cell row=\"0\" col=\"12\">1.20000000000000e-03</cell>\n                    <cell row=\"0\" col=\"13\">7.20000000000000e-03</cell>\n                    <cell row=\"0\" col=\"14\">1.33000000000000e-02</cell>\n                    <cell row=\"0\" col=\"15\">1.33000000000000e-02</cell>\n                    <cell row=\"0\" col=\"16\">1.33000000000000e-02</cell>\n                    <cell row=\"0\" col=\"17\">1.33000000000000e-02</cell>\n                </pattern>\n            </cell>\n            ...\n        </pattern>\n    </antenna>\n</groops>\n\\end{verbatim}\n\n\n%==================================\n\\subsection{GnssReceiverDefinition}\\label{general.fileFormat:gnssReceiverDefinition}\nContains a list of GNSS receivers which are identified by its\nname, serial, and version. Defines for each receiver a list of\nsignal \\configClass{types}{gnssType} which can be observed.\nCan also be used for GNSS transmitters to define a list of\ntransmitted signal types. For GLONASS satellites the frequency\nnumber can be stored in the \\emph{version} field.\n\nSee \\program{GnssReceiverDefinitionCreate}.\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"receiverDefinition\" version=\"20190429\">\n    <receiverCount>112</receiverCount>\n    <receiver>\n        <name>GLONASS</name>\n        <serial>R779</serial>\n        <version>2</version>\n        <comment/>\n        <types>\n            <count>4</count>\n            <cell>*1CR**J</cell>\n            <cell>*1PR**J</cell>\n            <cell>*2CR**J</cell>\n            <cell>*2PR**J</cell>\n        </types>\n    </receiver>\n    ...\n    <receiver>\n        <name>GLONASS-K1</name>\n        <serial>R802</serial>\n        <version>7</version>\n        <comment/>\n        <types>\n            <count>10</count>\n            <cell>*1CR**O</cell>\n            <cell>*1PR**O</cell>\n            <cell>*2CR**O</cell>\n            <cell>*2PR**O</cell>\n            <cell>*3IR**</cell>\n            <cell>*3QR**</cell>\n            <cell>*4AR**</cell>\n            <cell>*4BR**</cell>\n            <cell>*6AR**</cell>\n            <cell>*6BR**</cell>\n        </types>\n    </receiver>\n</groops>\n\\end{verbatim}\n\n\n%==================================\n\\subsection{GnssSignalBias}\\label{general.fileFormat:gnssSignalBias}\nSignal biases of GNSS transmitters or receivers for different \\configClass{gnssType}{gnssType}.\n\n\\begin{verbatim}\ngroops gnssSignalBias version=20200123\n          5 # number of signals\n# type   bias [m]\n# ===============================\n C1CG06 -1.752461109688110974e-01\n C1WG06  4.005884595055994590e-02\n C2WG06  6.597469378913034532e-02\n L1*G06 -2.736169875580296909e-02\n L2*G06  3.422596762686257871e-02\n \\end{verbatim}\n\nSee also \\program{GnssProcessing}, \\program{GnssSimulateReceiver}, \\program{GnssSignalBias2Matrix}, \\program{GnssSignalBias2SinexBias}.\n\n\n%==================================\n\\subsection{GriddedData}\\label{general.fileFormat:griddedData}\nList of arbitrarily distributed points defined by geographic coordinates and ellipsoidal\nheight. Each point can also have an associated area\n(projected on the unit sphere with a total area of $4\\pi$).\nThis file format supports multiple values per point (called \\verb|data0|, \\verb|data1| and so on).\n\nFor regular gridded data and binary format (\\verb|*.dat|) a more efficient storage scheme is used.\n\nSee also: \\program{GriddedDataCreate}.\n\n\\begin{verbatim}\ngroops griddedData version=20200123\n 1  2  6.378137000000000000e+06  6.356752314140356146e+06 72 # hasArea, data columns, ellipoid a, ellipoid b, data rows\n# longitude [deg]           latitude [deg]            height [m]                unit areas [-]             data0                     data1\n# ===========================================================================================================================================================\n -1.650000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.350000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.050000000000000142e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -7.500000000000001421e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -4.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.499999999999997691e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  4.499999999999997868e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  7.499999999999997158e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.049999999999999574e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.349999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.649999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.650000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00\n -1.350000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00\n\\end{verbatim}\n\n\n\n%==================================\n\\subsection{GriddedDataTimeSeries}\\label{general.fileFormat:griddedDataTimeSeries}\nTime series of data for arbitrarily distributed points defined by geographic coordinates and ellipsoidal\nheight. The data can be temporal interpolated by \\reference{basis splines}{fundamentals.basisSplines}.\nThe file format consists of a \\file{griddedData}{griddedData}, a time series, and\nfor each spatial point and spline node pair multiple values called \\verb|data0|, \\verb|data1|, \\ldots.\n\nA GriddedDataTimeSeries can be generated from individual \\file{griddedData}{griddedData} with the program\n\\program{GriddedData2GriddedDataTimeSeries}. Vice-versa, a GriddedDataTimeSeries can be evaluated at a\nspecific time stamp to obtain a \\file{griddedData}{griddedData} with \\program{GriddedDataTimeSeries2GriddedData}.\n\n\n%==================================\n\\subsection{Instrument}\\label{general.fileFormat:instrument}\nThis template file format can store different observations in a epoch wise manner. Each epoch consists of a time and\nadditional data, e.g orbits, accelerometer data, star camera quaternions (see \\configClass{InstrumentType}{instrumentTypeType}).\nThe time series can be divided in several arcs (see \\program{InstrumentSynchronize}).\n\nAlso a \\file{matrix}{matrix} file is allowed as one single arc. The first column must contain times [MJD]. Without any extra column\nthe instrument type is INSTRUMENTTIME, with one additional column the type is MISCVALUE, and for more columns the type\nMISCVALUES is used.\n\n\\begin{verbatim}\ngroops instrument version=20200123\n# SATELLITETRACKING\n         -9         60  # instrument type, number of arcs\n# Time [MJD]               data0: range [m]          data1: range-rate [m/s]   data2: range-acc [m/s^2]\n# =====================================================================================================\n         12 # number of epochs of 1. arc\n 54588.000000000000000000 -5.074649470097549492e+05  5.755440207134928654e-01  1.877605261528093308e-03\n 54588.000057870370255841 -5.074620458130163024e+05  5.849357691551860805e-01  1.878948916234051596e-03\n 54588.000115740740966430 -5.074590976427756250e+05  5.943331739937073310e-01  1.879937220634776869e-03\n 54588.000173611111222272 -5.074561024756557308e+05  6.037340169611068452e-01  1.880370529387525701e-03\n 54588.000231481481478113 -5.074530602992626373e+05  6.131368121270999172e-01  1.880680632122925426e-03\n 54588.000289351851733954 -5.074499711071007187e+05  6.225398878861636565e-01  1.880495369480403561e-03\n 54588.000347222222444543 -5.074468349029610981e+05  6.319414138081351773e-01  1.880073731783055927e-03\n 54588.000405092592700385 -5.074436516971451929e+05  6.413404243585696385e-01  1.879464843086203459e-03\n 54588.000462962962956226 -5.074404215058300761e+05  6.507353310092597320e-01  1.878578987216372124e-03\n 54588.000520833333212067 -5.074371443491023383e+05  6.601267978060636477e-01  1.877878184949659246e-03\n 54588.000578703703922656 -5.074338202460713219e+05  6.695136489207137442e-01  1.876962042758626532e-03\n 54588.000636574074178498 -5.074304492190054734e+05  6.788964444122400632e-01  1.876091925462087043e-03\n         12 # number of epochs of 2. arc\n 54588.000694444444434339 -5.074270312892858055e+05  6.882748400534359767e-01  1.875376456928801432e-03\n 54588.000752314814690180 -5.074235664742725785e+05  6.976508178537534910e-01  1.874929898412159559e-03\n 54588.000810185185400769 -5.074200547868391732e+05  7.070236200716006891e-01  1.874312324351668077e-03\n 54588.000868055555656611 -5.074164962409950094e+05  7.163943828291452487e-01  1.873924188388115340e-03\n 54588.000925925925912452 -5.074128908454515622e+05  7.257639682023964145e-01  1.874025826380292404e-03\n 54588.000983796296168293 -5.074092386012640782e+05  7.351333608427884636e-01  1.873680487441316657e-03\n 54588.001041666666878882 -5.074055395130896359e+05  7.445020815182646912e-01  1.873849502509668122e-03\n 54588.001099537037134724 -5.074017935789784533e+05  7.538716732272922050e-01  1.873971633320137753e-03\n 54588.001157407407390565 -5.073980007962241652e+05  7.632414098560330595e-01  1.873984767500571974e-03\n 54588.001215277777646406 -5.073941611626467784e+05  7.726123093411200182e-01  1.874295246964456478e-03\n 54588.001273148148356995 -5.073902746728868224e+05  7.819835205798950639e-01  1.874226146744964808e-03\n 54588.001331018518612836 -5.073863413272026228e+05  7.913547196412918927e-01  1.874173804634685515e-03\n\\end{verbatim}\n\n\n%==================================\n\\subsection{Matrix}\\label{general.fileFormat:matrix}\nStores matrices and vectors. Only one triangle is written for symmetric or triangular matrices.\n\nThe header (the matrix definition) is optional.\nTherefore a pure text with only numbers in columns are also allowed.\nThis simplifies the handling of external data.\n\nInstead of a matrix file also an \\file{instrument}{instrument} file is allowed.\nThe first column is the time [MJD], the other columns depends on the instrument type.\n\n\\begin{verbatim}\ngroops matrix version=20200123\nLowerSymmetricMatrix( 4 x 4 )\n  1.000000000000000000e+00\n  0.000000000000000000e+00  1.000000000000000000e+00\n  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00\n  0.000000000000000000e+00  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00\n\\end{verbatim}\n\n\n\n%==================================\n\\subsection{MeanPolarMotion}\\label{general.fileFormat:meanPolarMotion}\nThe mean pole of the Earth rotation is represented by a polynomial in a time interval.\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"meanPolarMotion\" version=\"20200123\">\n  <meanPolarMotion>\n    <intervalCount>2</intervalCount>\n    <interval>\n      <timeStart>42778.0000000000000000</timeStart>\n      <degree>3</degree>\n      <xp>5.59741000000000e-02</xp>\n      <xp>1.82430000000000e-03</xp>\n      <xp>1.84130000000000e-04</xp>\n      <xp>7.02400000000000e-06</xp>\n      <yp>3.46346000000000e-01</yp>\n      <yp>1.78960000000000e-03</yp>\n      <yp>-1.07290000000000e-04</yp>\n      <yp>-9.08000000000000e-07</yp>\n    </interval>\n    <interval>\n      <timeStart>55197.0000000000000000</timeStart>\n      <degree>1</degree>\n      <xp>2.35130000000000e-02</xp>\n      <xp>7.61410000000000e-03</xp>\n      <yp>3.58891000000000e-01</yp>\n      <yp>-6.28700000000000e-04</yp>\n    </interval>\n  </meanPolarMotion>\n</groops>\n\\end{verbatim}\n\n\n%==================================\n\\subsection{NormalEquation}\\label{general.fileFormat:normalEquation}\nStores a \\reference{system of normal equations}{normalEquationType}\n\\begin{equation}\n  \\M N \\hat{\\M x} = \\M n.\n\\end{equation}.\nThis file format consists of multiple files.\nThe file name \\verb|normals.dat.gz| corresponds to the following files:\n\\begin{itemize}\n\\item \\verb|normals.dat.gz| or \\verb|normals.00.00.dat.gz| ... \\verb|normals.0n.0n.dat.gz|:\n      the normal matrix $\\M N$ as \\file{matrix}{matrix},\n\\item \\verb|normals.rightHandSide.dat.gz|:\n      the right hand side(s) $\\M n$ as \\file{matrix}{matrix},\n\\item \\verb|normals.parameterNames.txt|: \\file{parameter names}{parameterName},\n\\item \\verb|normals.info.xml|:\n\\     u.a. containing the number of observations and the quadratic sum of (reduced) observations $\\M l^T\\M P\\M l$.\n\\end{itemize}\nA large normal matrix may be splitted into blocks and stored in multiple files.\nThe block row/column number is indicated in the file name.\nOnly the upper blocks of the sysmmetric matrix are considered.\nMatrix in blocks can be distributed on muliple nodes in parallel mode to efficiently use distributed memory.\n\n\n%==================================\n\\subsection{OceanPoleTide}\\label{general.fileFormat:oceanPoleTide}\nDescribes the reaction of the ocean mass to the change\nof the centrifugal potential (polar wobble) in terms spherical harmonics.\n\nSee also \\program{Iers2OceanPoleTide}.\n\n\n%==================================\n\\subsection{ParameterName}\\label{general.fileFormat:parameterName}\nName of parameters of a system of \\file{normal equations}{normalEquation} or \\file{solution vector}{matrix}.\n\nA parameter name is a string \\verb|<object>:<type>:<temporal>:<interval>| containg four parts divided by \\verb|:|\n\\begin{enumerate}\n\\item object: Object this parameter refers to, e.g. \\verb|graceA|, \\verb|G023|, \\verb|earth|, \\ldots\n\\item type: Type of this parameter, e.g. \\verb|accBias|, \\verb|position.x|, \\ldots\n\\item temporal: Temporal representation of this parameter, e.g. \\verb|trend|, \\verb|polynomial.degree1|, \\ldots\n\\item interval: Interval/epoch this parameter represents, e.g. \\verb|2017-01-01_00-00-00_2017-01-02_00-00-00|, \\verb|2018-01-01_00-00-00|.\n\\end{enumerate}\nIn the documentation a star (\\verb|*|) in the name means this part is untouched and useally set by other classes.\nTimes are written as \\verb|yyyy-mm-dd_hh-mm-ss| and intervals (if not empty) as \\verb|<timeStart>_<timeEnd>|.\n\nSee \\program{ParameterNamesCreate}.\n\n\\begin{verbatim}\ngroops parameterName version=20200123\n# object:type:temporal:interval\n# =============================\n      10080 # number of parameters\n karr:position.x::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:position.y::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:position.z::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_02-00-00\n karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_04-00-00\n karr:troposphereWet:spline.n1:2018-06-01_02-00-00_2018-06-01_06-00-00\n karr:troposphereWet:spline.n1:2018-06-01_04-00-00_2018-06-01_08-00-00\n karr:troposphereWet:spline.n1:2018-06-01_06-00-00_2018-06-01_10-00-00\n karr:troposphereWet:spline.n1:2018-06-01_08-00-00_2018-06-01_12-00-00\n karr:troposphereWet:spline.n1:2018-06-01_10-00-00_2018-06-01_14-00-00\n karr:troposphereWet:spline.n1:2018-06-01_12-00-00_2018-06-01_16-00-00\n karr:troposphereWet:spline.n1:2018-06-01_14-00-00_2018-06-01_18-00-00\n karr:troposphereWet:spline.n1:2018-06-01_16-00-00_2018-06-01_20-00-00\n karr:troposphereWet:spline.n1:2018-06-01_18-00-00_2018-06-01_22-00-00\n karr:troposphereWet:spline.n1:2018-06-01_20-00-00_2018-06-02_00-00-00\n karr:troposphereWet:spline.n1:2018-06-01_22-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:signalBias01(+1.00L1CG**)::\n karr:signalBias02(+1.00L2WG**)::\n karr:signalBias03(+1.00L2XG**)::\n G01:solarRadiationPressure.ECOM.D0::\n G01:solarRadiationPressure.ECOM.DC2::\n G01:solarRadiationPressure.ECOM.DS2::\n G01:solarRadiationPressure.ECOM.Y0::\n G01:solarRadiationPressure.ECOM.B0::\n G01:solarRadiationPressure.ECOM.BC1::\n G01:solarRadiationPressure.ECOM.BS1::\n G01:stochasticPulse.x::2018-06-01_12-00-00\n G01:stochasticPulse.y::2018-06-01_12-00-00\n G01:stochasticPulse.z::2018-06-01_12-00-00\n G01:arc0.position0.x::\n G01:arc0.position0.y::\n G01:arc0.position0.z::\n G01:arc0.velocity0.x::\n G01:arc0.velocity0.y::\n G01:arc0.velocity0.z::\n G01:signalBias01(-1.00C1CG01)::\n G01:signalBias02(+1.00L1*G01)::\n G01:signalBias03(+1.00L2*G01)::\n\\end{verbatim}\n\n\n%==================================\n\\subsection{Platform}\\label{general.fileFormat:platform}\nDefines a platform with a local coordinate frame equipped with instruments.\nThe platform might be a reference station, a low Earth satellite,\nor a transmitting GNSS satellite and is referenced by a marker name and number.\nThe reference point (marker or center of mass (CoM)) can change in time\nrelative to the local frame.\n\nEach equipped instrument is described at least by the following information\n\\begin{itemize}\n\\item name\n\\item serial number\n\\item coordinates in the local frame\n\\item a time interval in which the instrument was active\n\\item the orientation for antennas and reflectors.\n\\end{itemize}\n\nFor GNSS satellites the platform defines the PRN. The different assigned SVNs\nare defined by the transmitting antennas.\n\nPlatforms for GNSS stations can be created from station log files with\n\\program{GnssStationLog2Platform}. Platforms for GNSS satellites\ncan be created from an ANTEX file with \\program{GnssAntex2AntennaDefinition}.\n\nSee also \\program{PlatformCreate}.\n\n\\fig{!hb}{0.8}{fileFormatPlatform}{fig:fileFormatPlatform}{Platform for stations, LEOs, and GNSS satellites.}\n\n\n%==================================\n\\subsection{Polygon}\\label{general.fileFormat:polygon}\nList of longitude and latitudes to describe borders, e.g. river basins or continents.\nIt is used in \\configClass{border:polygon}{borderType:polygon}.\n\n\\begin{verbatim}\ngroops polygon version=20200123\n          2  # number of polygons\n          6  # number of points (1. polygon)\n# longitude [deg]           latitude [deg]\n# ==================================================\n -1.598200000000000216e+02  2.203000000000000114e+01\n -1.596200000000000045e+02  2.189999999999999858e+01\n -1.593799999999999955e+02  2.189999999999999858e+01\n -1.593000000000000114e+02  2.221999999999999886e+01\n -1.595800000000000125e+02  2.221999999999999886e+01\n -1.598200000000000216e+02  2.203000000000000114e+01\n          5  # number of points (2. polygon)\n# longitude [deg]           latitude [deg]\n# ==================================================\n -7.900000000000000000e+01  2.669999999999999929e+01\n -7.870000000000000284e+01  2.650000000000000000e+01\n -7.823000000000000398e+01  2.667000000000000171e+01\n -7.793000000000000682e+01  2.667000000000000171e+01\n -7.779999999999999716e+01  2.646999999999999886e+01\n\\end{verbatim}\n\n\n\n%==================================\n\\subsection{PotentialCoefficients}\\label{general.fileFormat:potentialCoefficients}\nThe standard \\verb|.gfc| format as defined by the ICGEM is used in ASCII the format.\nOnly the static part is used and temporal variations (e.g. trend) are ignored.\nTo write additional information and temporal variations use \\program{PotentialCoefficients2Icgem}.\n\n\n%==================================\n\\subsection{SatelliteModel}\\label{general.fileFormat:satelliteModel}\nProperties of a satellite to model non-conservative forces (e.g. \\configClass{miscAccelerations}{miscAccelerationsType}).\nThe file may contain surface properties, mass, drag coefficients, and antenna thrust values.\n\nSee \\program{SatelliteModelCreate} and \\program{SinexMetadata2SatelliteModel}.\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"satelliteModel\" version=\"20190429\">\n   <satelliteCount>1</satelliteCount>\n   <satellite>\n       <satelliteName>GALILEO-2</satelliteName>\n       <mass>7.00000000000000e+02</mass>\n       <coefficientDrag>0.00000000000000e+00</coefficientDrag>\n       <surfaceCount>15</surfaceCount>\n       <surface>\n           <type>0</type>\n           <normal>\n               <x>-1.00000000000000e+00</x>\n               <y>0.00000000000000e+00</y>\n               <z>0.00000000000000e+00</z>\n           </normal>\n           <area>4.40000000000000e-01</area>\n           <reflexionVisible>0.00000000000000e+00</reflexionVisible>\n           <diffusionVisible>7.00000000000000e-02</diffusionVisible>\n           <absorptionVisible>9.30000000000000e-01</absorptionVisible>\n           <reflexionInfrared>1.00000000000000e-01</reflexionInfrared>\n           <diffusionInfrared>1.00000000000000e-01</diffusionInfrared>\n           <absorptionInfrared>8.00000000000000e-01</absorptionInfrared>\n           <hasThermalReemission>1</hasThermalReemission>\n       </surface>\n       ...\n       <modulCount>2</modulCount>\n       <modul>\n           <type>1</type>\n           <rotationAxis>\n               <x>0.00000000000000e+00</x>\n               <y>1.00000000000000e+00</y>\n               <z>0.00000000000000e+00</z>\n           </rotationAxis>\n           <normal>\n               <x>0.00000000000000e+00</x>\n               <y>0.00000000000000e+00</y>\n               <z>1.00000000000000e+00</z>\n           </normal>\n           <surface>\n               <count>4</count>\n               <cell>11</cell>\n               <cell>12</cell>\n               <cell>13</cell>\n               <cell>14</cell>\n           </surface>\n       </modul>\n       <modul>\n           <type>2</type>\n           <antennaThrust>\n               <x>0.00000000000000e+00</x>\n               <y>0.00000000000000e+00</y>\n               <z>2.65000000000000e+02</z>\n           </antennaThrust>\n       </modul>\n   </satellite>\n</groops>\n\\end{verbatim}\n\n\n%==================================\n\\subsection{StringList}\\label{general.fileFormat:stringList}\nWhite space separated list of strings.\nComments are allowed and all the text from the character '\\verb|#|' to the end of the line is ignored.\nStrings containing white spaces or the '\\verb|#|' character must be set in quotes ('\\verb|\"\"|').\n\n\\begin{verbatim}\n# IGSR3 stations\nabmf\nabpo\nade1\nadis\najac\nalbh\nalgo\nalic\nalrt\namc2\naoml\nareq\narev\nartu\nasc1\n\\end{verbatim}\n\n\n%==================================\n\\subsection{StringTable}\\label{general.fileFormat:stringTable}\nWhite space separated table of strings in row and columns.\nAdditional columns in a row may represent alternatives, e.g. for core stations in a GNSS network.\nComments are allowed and all the text from the character '\\verb|#|' to the end of the line is ignored.\nStrings containing white spaces or the '\\verb|#|' character must be set in quotes  ('\\verb|\"\"|').\n\n\\begin{verbatim}\n# core network with alternative stations\nartu mdvj mdvo nril\nasc1 sthl\nbahr bhr1 yibl nama\nchat chti auck\nchpi braz ufpr savo\nckis nium\ncoco xmis dgar dgav\ncro1 scub abmf lmmf aoml\ndaej taej suwn osn1\ndarw kat1 tow2 alic\ndav1 maw1\ndrao albh will holb nano\nfair whit\nglps guat\ngode godz usno usn3\ngoug\n\\end{verbatim}\n\n\n%==================================\n\\subsection{TideGeneratingPotential}\\label{general.fileFormat:tideGeneratingPotential}\n\n\\begin{verbatim}\ngroops tideGeneratingPotential version=20200123\n       7160\n# Degree    Dood.    cos                       sin                      name\n# ==========================================================================\n          3 055.556  0.000000000000000000e+00 -6.569000000000000125e-07 \"\"\n          3 055.635  0.000000000000000000e+00 -2.842000000000000170e-07 \"\"\n          3 055.561  0.000000000000000000e+00 -6.360000000000000040e-08 \"\"\n          2 055.563 -3.122600001000726621e-06  0.000000000000000000e+00 \"\"\n          2 055.565  7.719644799947265879e-02  0.000000000000000000e+00 om1\n          3 055.645  0.000000000000000000e+00  2.921429999971616515e-05 \"\"\n          2 055.573  1.975999999999999959e-07  0.000000000000000000e+00 \"\"\n          2 055.575 -7.535264999889109729e-04  0.000000000000000000e+00 om2\n\\end{verbatim}\n\n\n\n%==================================\n\\subsection{TimeSplinesCovariance}\\label{general.fileFormat:timeSplinesCovariance}\nStores covariance information for \\file{TimeSplinesGravityField}{timeSplinesGravityField}.\nIt can be the variances of the potential coefficients or the full covariance matrix for each\ntemporal nodal point.\n\n\n%==================================\n\\subsection{TimeSplinesGravityField}\\label{general.fileFormat:timeSplinesGravityField}\nTemporal changing gravity field, parametrized as spherical harmonics in the spatial domain and\nparametrized as basis splines in the time domain (see~\\reference{basis splines}{fundamentals.basisSplines}).\nIt is evaluated with \\configClass{gravityfield:timeSplines}{gravityfieldType:timeSplines}.\n\nSee also: \\program{Gravityfield2TimeSplines}, \\program{PotentialCoefficients2BlockMeanTimeSplines}.\n\n\n%==================================\n\\subsection{VariationalEquation}\\label{general.fileFormat:variationalEquation}\nArcs with reference orbit and state transition matrices.\n\nThe file contains a reference orbit (position and velocity),\nthe derivatives of the orbit with respect to the satellite state vector for each arc,\ntransformations (rotations) between the satellite, celestial, and terrestrial frame\nand a satellite macro model (see \\file{SatelliteModel}{satelliteModel}).\n\nThe reference orbit can be extracted with \\program{Variational2OrbitAndStarCamera}.\n\nSee also: \\program{PreprocessingVariationalEquation}.\n\n\n\n%==================================\n"
  },
  {
    "path": "docs/latex/general.fileFormat.tex",
    "content": "\\section{File formats}\\label{general.fileFormat}\nAll GROOPS files are written either in XML, JSON, binary, or ASCII format depending on the filename extension.\n\\begin{itemize}\n\\item \\verb|.xml|: XML format\n\\item \\verb|.json|: JSON format\n\\item \\verb|.dat|: binary format\n\\item \\verb|.txt| and all other extensions: ASCII format\n\\end{itemize}\n\nWith an additional extension of '\\verb|.gz|' files are directly compressed and uncompressed. It is also possible to directly uncompress and read (but not write) \\href{https://en.wikipedia.org/wiki/Compress}{Unix compress}'d files ('\\verb|.Z|').\n\nComments are allowed in ASCII files and all the text starting from the character '\\verb|#|' to the end of the line is ignored.\n\nThe program \\program{FileConvert} can be used to convert between the different formats. This program is also useful to get\nsome general information of files in binary format.\n\nThe following special file types are used in GROOPS:\n"
  },
  {
    "path": "docs/latex/general.gui.tex",
    "content": "\\section{Graphical User Interface (GUI)}\\label{general.gui}\n\nThe graphical user interface program \\verb|groopsGui| enables the convenient creation of GROOPS config files.\nIt uses the \\href{https://qt.io}{Qt5 framework} for cross-platform support.\n\n\\fig{!ht}{1.0}{gui_overview}{fig:gui_overview}{Overview of the GUI (components mentioned below marked in red)}\n\n\\subsection{Settings and first-time setup}\n\nThe GUI depends on an XSD schema file containing the complete formal (computer readable) description of a GROOPS config file.\nThis schema file can be created with the command:\n\\begin{verbatim}\n  groops --xsd <groopsDir>/groops.xsd\n\\end{verbatim}\nAt least one schema file has to be set via\nthe menu \\verb|Settings - Default Paths and Files|. Setting more than one schema files enables the \\emph{schema selector} in the toolbar.\nThe selected schema will be used when (re-)opening or creating a config file.\nThis feature is useful when working with different versions of GROOPS at the same time.\n\nIt is possible to set a \\emph{template file} via the menu \\verb|Settings - Default Paths and Files|. This can be any GROOPS config file.\nWhenever a new config file is created via the GUI, all global elements and programs defined in the template file are automatically created in the new config file.\nIt is highly recommended to create a template file containing at least the global element \\verb|groopsDataDir| of type \\verb|filename|.\nThis element is used as a \\reference{variable}{general.parser} in most default file paths throughout many GROOPS programs.\nThus, setting the path to the base directory containing all GROOPS data once in the template file, for example as\n\\config{groopsDataDir}=\\verb|/home/<user>/groops/data|, is the most convenient way to handle default paths in GROOPS.\nThe template file can also contain other often-used global elements, for example \\verb|tmpDir| or  \\verb|timeStart| and  \\verb|timeEnd|.\n\nA \\emph{working directory} can be set via \\verb|Settings - Default Paths and Files|.\nThis directory is used as the default directory in the save dialog of new config files.\n\nThe GUI offers the option to open the GROOPS documentation for a selected program. To use this feature,\nthe GROOPS documentation must be generated (if not already present) with the command:\n\\begin{verbatim}\n  groops --doc <groopsDir>/docs/\n\\end{verbatim}\nIn the menu \\verb|Settings - Default Paths and Files| the path to the HTML version of the documentation must be set (i.e. \\verb|<groopsDir>/docs/html|).\nSelecting any program and pressing \\verb|F1| opens the documentation for this program in an external browser.\nPressing \\verb|F1| without having any program selected opens the main page of the GROOPS documentation.\n\nExecuting a config file from the GUI requires the setup of a run command in the menu \\verb|Settings - Commands|.\nIt is recommended for this command to open a new terminal in which GROOPS is executed with the config file given as an argument.\nThe placeholders \\verb|%w| and \\verb|%f| are replaced by the directory and file name of the selected config file, respectively.\nMultiple commands can be set up, with the option to choose one of them in the run dialog.\n\nExample commands:\n\\begin{itemize}\n\t\\item Windows: \\verb|cd /d %w && groops.exe %f|\n\t\\item Linux (KDE): \\verb|konsole --workdir %w -e bash -ic \"groops %f; bash\"|\n\t\\item Linux (GNOME): \\verb|gnome-terminal --working-directory=%w -x bash -ic \"groops %f; bash\"|\n\t\\item Windows, MPI with 4 processes: \\verb|cd /d %w && mpiexec -n 4 groopsMPI.exe %f|\n\t\\item Linux (KDE), MPI with 4 processes: \\verb|konsole --workdir %w -e bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"|\n\t\\item Linux (GNOME), MPI with 4 processes: \\verb|gnome-terminal --working-directory=%w -x bash -ic \"mpiexec -n 4 groopsMPI %f; bash\"|\n\\end{itemize}\n\n\\subsection{Basic features}\n\nMost basic features used to manipulate a config element are accessible via the context menu,\nfor example attributing \\reference{loops and conditions}{general.loopsAndConditions} or setting an element global.\nGlobal elements automatically appear in the dropdown value list of config elements of the same type.\nSelecting a global element from the dropdown list as a value links this config element to the global element.\nIn case the global element is removed, all linked elements' values are replaced by the value of the deleted global element.\n\nThe sidebar features three widgets:\n\\begin{itemize}\n\t\\item \\verb|Open Files|: An overview of all open config files (select to change current tree)\n\t\\item \\verb|Program List|: A list of all programs defined in the schema of the active tree (filterable, supports drag and drop to tree, double click appends program)\n\t\\item \\verb|Undo Stack|: Tracks all changes in a config file (select to change state of tree)\n\\end{itemize}\n\nIn case the names of programs or config elements change over time, the GUI offers a rename feature to update outdated config files.\nThe changes must be documented in the schema using GROOPS' rename feature. Affected elements will be marked with an icon and\nthe context menu item \\verb|Update name| will be available to change the element to the new name defined in the schema.\n\n\\subsection{Additional keyboard shortcuts}\n\n\\begin{itemize}\n\t\\item Tree navigation:\n\t\\begin{itemize}\n\t\t\\item \\verb|Enter|: Switch focus from tree to input field of selected row\n\t\t\\item \\verb|Escape|: Switch focus from input field back to tree\n\t\t\\item \\verb|Tab|: Next sibling element (or next sibling of parent if there is no next sibling, or next child otherwise)\n\t\t\\item \\verb|Shift+Tab|: Previous sibling element (or parent if there is no previous sibling)\n\t\t\\item \\verb|Ctrl+Tab|: Next tab/tree\n\t\t\\item \\verb|Ctrl+Shift+Tab|: Previous tab/tree\n\t\t\\item \\verb|Ctrl+Space|: Interact with the element (e.g. filename/program: open dialog; time: switch focus between input fields)\n\t\t\\item \\verb|Ctrl+Up/Down|: Next/previous sibling element\n\t\t\\item \\verb|Ctrl+Left/Right|: Fold/expand (complex) element\n\t\\end{itemize}\n\t\\item Tree manipulation:\n\t\\begin{itemize}\n\t\t\\item \\verb|Ctrl+Shift+Up/Down|: Move unbounded list element (e.g. program, layer) up/down\n\t\\end{itemize}\n\t\\item Drag and Drop of tabs to other programs (i.e. text editors) or other GUI windows:\n\t\\begin{itemize}\n\t\t\\item \\verb|Drag|: Copy tab (= keep in source window)\n\t\t\\item \\verb|Shift+Drag|: Move tab (= remove from source window)\n\t\\end{itemize}\n\t\\item Drag and Drop GROOPS config file(s) into GUI:\n\t\\begin{itemize}\n\t\t\\item \\verb|Drag|: Open file(s) in new tab(s)\n\t\t\\item \\verb|Shift+Drag|: Open file in current tab (replaces current tab, only works with a single file)\n\t\\end{itemize}\n\\end{itemize}\n"
  },
  {
    "path": "docs/latex/general.loopsAndConditions.tex",
    "content": "\\section{Loops and conditions}\\label{general.loopsAndConditions}\nThe program flow within a config file can be controlled by the classes \\configClass{loop}{loopType}\nand \\configClass{condition}{conditionType}. The easiest way to access these classes is with the programs\n\\program{LoopPrograms} and \\program{IfPrograms}.\n\nThe programs defined in \\program{IfPrograms} are only executed if the defined\n\\configClass{condition}{conditionType} is met. A typical example is to check whether a file that\nshould have been created in previous programs actually exists. Further options are string comparisons and\nchecking the result of a numerical expression or the return value of an external command.\n\nWith \\program{LoopPrograms} it is possible to repeat the programs defined inside within a loop.\nThe class \\configClass{loop}{loopType} creates a sequence to loop over and defines \\reference{variables}{general.parser}\nthat contain the index and element for the current iteration.\n\nThe \\configClass{loop}{loopType} and \\configClass{condition}{conditionType} can also be attributed to single\nconfig elements (including programs). Config elements with an assigned loop are repeated, with the loop variables\nbeing evaluated for each element. If a \\configClass{condition}{conditionType} is attributed to a config element\nin addition to a loop, each element within the loop is only created if the condition is met. Conditions can also\nbe attributed to optional elements without an associated loop.\nIf the condition is not met, the optional element will be treated as if it was not provided.\n\nExample: A program needs all files in a download directory as input.\nAll the \\config{inputfile}s can be selected manually of course, but it is much easier to assign\na loop variable with \\config{inputfile}=\\verb|{loopFile}| and attribute a\n\\configClass{loop:directoryListing}{loopType:directoryListing}.\nThe loop lists the content of the download directory and assigns each file name to the\n\\config{variableLoopFile}=\\verb|loopFile|.\n"
  },
  {
    "path": "docs/latex/general.parallelization.tex",
    "content": "\\section{Parallelization}\\label{general.parallelization}\nIf GROOPS is compiled with the\n\\href{https://en.wikipedia.org/wiki/Message_Passing_Interface}{Message Passing Interface} (MPI),\nmost GROOPS \\reference{programs}{programType} can be run in parallel on multiple processor cores.\nProcessing on computer clusters with distributed memory is also supported.\n\nMany loops are parallelized by computing each loop step at a different core.\nUsually the first node distributes the work load, assigns loop steps to different cores,\nand is not participating on the actual loop computation. This means running\nGROOPS with only two nodes has no advantages in almost all cases.\nNon-parallel parts and \\reference{programs}{programType} without parallel support\nare executed at the first node only.\n\nLarge systems of \\file{normal equations}{normalEquation}, which are divided into blocks,\nare distributed over the nodes to reduce the memory consumption on each single node.\n\nAs all nodes may read and write files (at least reading the \\reference{config files}{general.configFiles})\nthe required part of the file system must be available on all participating computers.\n"
  },
  {
    "path": "docs/latex/general.parser.auto.tex",
    "content": "% auto generated by GROOPS\n\n\\subsection{Mathematical expression parser}\\label{general.parser:expression}\nIn all input fields that accept numbers (int, uint, double, angle, time) numerical\nexpressions are also allowed. Declared variables can be accessed via their name. The following\noperations and functions are defined:\n\\begin{itemize}\n\\item Constants:    \\verb|pi()|, \\verb|rho()=180/pi()|, \\verb|nan()|, \\verb|c()|: light velocity,\n                    \\verb|G()|: gravitational constant, \\verb|GM()|: gravitational constant of the Earth, \\verb|R()|: reference radius of the Earth\n\\item Mathematical: \\verb|+|, \\verb|-|, \\verb|*|, \\verb|/|, \\verb|^|\n\\item Comparison:   \\verb|==|, \\verb|!=|, \\verb|<|, \\verb|<=|, \\verb|>|, \\verb|>=|, result is 1 or 0\n\\item Logical:      not \\verb|!|, and \\verb|&&|, \\verb'||', or \\verb|isnan(x)|, result is 1 or 0\n\\item Functions:    \\verb|sqrt(x)|, \\verb|exp(x)|,\n                    \\verb|sin(x)|,  \\verb|cos(x)|, \\verb|tan(x)|,\n                    \\verb|asin(x)|,  \\verb|acos(x)|,  \\verb|atan(x)|,\n                    \\verb|abs(x)|,  \\verb|round(x)|,  \\verb|ceil(x)|,  \\verb|floor(x)|,\n                    \\verb|deg2rad(x)|, \\verb|rad2deg(x)|\n\\item Functions with 2 arguments: \\verb|atan2(y,x)|, \\verb|min(x,y)|, \\verb|max(x,y)|, \\verb|mod(x,y)|\n\\item Time functions: \\verb|now()|: local time in MJD, \\verb|date2mjd(year, month, day)|, \\verb|gps2utc(mjd)|, \\verb|utc2gps(mjd)|, \\verb|dayofyear(mjd)|, \\verb|decimalyear(mjd)|\n\\item Condition: \\verb|if(c,x,y)|: If the first argument is true (not 0), the second argument is evaluated, otherwise the third.\n\\end{itemize}\n\n\n\\subsection{Text parser}\\label{general.parser:text}\nBefore the mathematical expression parser evaluates the expression, a simple text parser is applied.\nThe text parser is used for all input fields (also file names). It scans the text for terms like\n\\verb|{variable}| and replaces it by the text content of the \\verb|variable|.\nA literal '\\verb|{|' character must be escaped with '\\verb|#{|'.\n\nThe text parser allows regex replacements in the form \\verb|{text/regex/replace}|.\nAll matches of \\verb|regex| in the \\verb|text| are replaced by \\verb|replace|.\nPossible \\verb|{variables}| in the three parts are evaluated beforehand.\nCapturing groups \\verb|()| can be accessed by \\verb|$1|, \\verb|$2|,\n\\ldots in the replacement (\\verb|$0| is the complete match). Additional escape sequences are:\n\\begin{itemize}\n\\item \\verb|\\l| lowercase next char,\n\\item \\verb|\\u| uppercase next char,\n\\item \\verb|\\L| lowercase until \\verb|\\E|,\n\\item \\verb|\\U| uppercase until \\verb|\\E|,\n\\item \\verb|\\Q| quote (disable) pattern metacharacters until \\verb|\\E|,\n\\item \\verb|\\E| end either case modification or quoted section.\n\\end{itemize}\n\nExamples:\n\\begin{itemize}\n\\item \\verb|{{variable}/test/text}| replaces all occurrences of \\verb|test| by \\verb|text|.\n\\item \\verb|{TEXT/.+/\\L$0}| converts text to lower case.\n\\item \\verb|{012345/.#{2}(.#{3}).*/$1}| extracts the substring at index 2 and length 3 resulting in \\verb|234|.\n      Note the escaping \\verb|#{|.\n\\end{itemize}\n\nThe text parser also evaluates terms in the form \\verb|{expression:format}| and replaces it by a formatted\noutput. In order not to get confused with the regex replacements, the '\\verb|/|' character must be escaped\nwith '\\verb|#/|' in the expression. The \\verb|format| contains the text to be written as output.\nIt can contain embedded format specifiers that are replaced by the value of the expression and formatted\nas requested (also multiple times). In the following, the resulting formatted output is given in the\nbrackets for an expression with the example value of 57493.8:\n\\begin{itemize}\n\\item \\verb|%i|: Integer [57494]\n\\item \\verb|%f|: Decimal floating point [57493.800000]\n\\item \\verb|%e|: Scientific notation [5.749380e+04]\n\\item \\verb|%g|: Use the shortest representation: \\verb|%e| or \\verb|%f| [57493.8]\n\\item \\verb|%c|: Interpret number as ASCII character\n\\item \\verb|%%|: Write a single literal \\verb|%| character\n\\end{itemize}\nThe following specifiers interpret the value of the expression as MJD (modified Julian date):\n\\begin{itemize}\n\\item \\verb|%y|: Four digit year [2016]\n\\item \\verb|%Y|: Two digit year [16]\n\\item \\verb|%m|: Month [04]\n\\item \\verb|%d|: Day of month [15]\n\\item \\verb|%H|: Hour [19]\n\\item \\verb|%M|: Minute [12]\n\\item \\verb|%S|: Second [00]\n\\item \\verb|%D|: Date (same as \\verb|%y-%m-%d|) [2016-04-15]\n\\item \\verb|%T|: Time (same as \\verb|%H-%M-%S|) [19-12-00]\n\\item \\verb|%W|: GPS week [1892]\n\\item \\verb|%w|: Day of GPS week (0..6) [5]\n\\item \\verb|%O|: Day of year (1..366)\n\\end{itemize}\nThe format can be specified further with \\verb|%[width][.precision]specifier|,\nwhere \\verb|[width]| is the minimum number of characters to be printed.\nIf the value to be printed is shorter than this number, the result is padded with blank spaces\n(or zeros if \\verb|[width]| starts with a zero).\nThe \\verb|[.precision]| defines the number of digits after the period (for \\verb|%g| the number of\nsignificant digits instead).\n\nExample:\nTwo variables \\config{time}=\\verb|57493+19/24+12/1440| and \\config{satellite}=\\verb|swarm| are\nset in the global section. The \\config{inputfile}=\\verb|data/{time:%y}/{satellite}_{time:%D}.dat|\nis expanded to \\verb|\"data/2016/swarm_2016-04-15.dat\"|.\n\nExample:\nThe variable \\config{x}=\\verb|3+5| is set in the global section.\nThe expression \\config{number}=\\verb|2*x| is evaluated by the expression parser to \\verb|=16|.\nIn contrast if we use brackets like in \\config{number}=\\verb|2*{x}| the expression is first evaluated\nby the text parser to \\verb|\"2*3+5\"| and the expression parser now gives the result \\verb|=11|.\n\n\n\\subsection{Variables for data}\\label{general.parser:dataVariables}\nSome programs (e.g. \\program{FunctionsCalculate}, \\program{InstrumentArcCalculate},\n\\program{GriddedDataCalculate}, or the plot programs)\nread data (\\file{matrix}{matrix}) or \\file{gridded data}{griddedData}\nand evaluate input/output expressions for each data row.\nFor these kind of expressions additional variables are automatically defined for each data column\n(\\verb|X| stands for the data column number: $0\\ldots n$):\n\\begin{itemize}\n\\item \\verb|index|: the row number, starting with zero\n\\item \\verb|dataX|: the value itself\n\\item \\verb|dataXcount|: number of rows\n\\item \\verb|dataXmin|\n\\item \\verb|dataXmax|\n\\item \\verb|dataXsum|\n\\item \\verb|dataXmean|\n\\item \\verb|dataXrms|: root mean square\n\\item \\verb|dataXstd|: standard deviation\n\\item \\verb|dataXmedian|\n\\item \\verb|dataXmad|: median absolute deviation\n\\item \\verb|dataXstep|: the minimal difference between two neighboring data points in the column\n\\end{itemize}\nFor \\file{gridded data}{griddedData} input the following variables are additionally defined for each data point:\n\\begin{itemize}\n\\item \\verb|longitude| in degrees\n\\item \\verb|latitude| in degrees\n\\item \\verb|height| in meters\n\\item \\verb|cartesianX| coordinate in meters\n\\item \\verb|cartesianY| coordinate in meters\n\\item \\verb|cartesianZ| coordinate in meters\n\\item \\verb|area| of the unit sphere\n\\item \\verb|dataXwmean|: area-weighted mean\n\\item \\verb|dataXwrms|: area-weighted root mean square\n\\item \\verb|dataXwstd|: area-weighted standard deviation\n\\end{itemize}\n\n"
  },
  {
    "path": "docs/latex/general.parser.tex",
    "content": "\\section{Parsers and variables}\\label{general.parser}\nThe XML configuration file is evaluated by two parsers. In a first step a text parser is applied.\nIn the second step mathematical expressions are resolved to a number.\nVariables (see section~\\reference{variables}{general.configFiles:variables}) can be referenced via their\nname directly for the expression parser or in the form \\verb|{name}| for the text parser.\n\n\\input{general.parser.auto}\n"
  },
  {
    "path": "docs/latex/programs.auto.tex",
    "content": "% auto generated by GROOPS\n\\section{Programs: Covariance}\n\\subsection{AutoregressiveModel2CovarianceMatrix}\\label{AutoregressiveModel2CovarianceMatrix}\nThis program computes the covariance structure of a random process represented by an AR model sequence.\nThe covariance matrix is determined by accumulating the normal equations of all AR models in \\config{autoregressiveModelSequence}\nand inverting the combined normal equation matrix.\nFor each output file in \\configFile{outputfileCovarianceMatrix}{matrix},\nthe covariance matrix of appropriate time lag is saved (the first file contains the auto-covariance,\nsecond file cross covariance and so on). The matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\Sigma(t-h, t)$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfileCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt covariance matrix for each lag\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~autoregressiveModelSequence & \\hfuzz=500pt \\hyperref[autoregressiveModelSequenceType]{autoregressiveModelSequence} & \\hfuzz=500pt AR model sequence\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{CovarianceFunction2DigitalFilter}\\label{CovarianceFunction2DigitalFilter}\nComputes digital filter coefficients for a \\configClass{digital filter}{digitalFilterType} of given degree and\norder. The filter coefficients are computed by fitting them to an approximated\nimpulse response represented by the cholesky factor of the covariance matrix.\n\nThe parameter \\config{warmup} determines from which element of the cholesky matrix the\ncoefficients (default: half the covariance length) are fitted.\n\nPer default, the program computes filter coefficients which generate colored noise\nwhen applied to a white noise sequence. When \\config{decorrelationFilter} is set,\na decorrelation filter is computed which yields white noise when applied to colored noise.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileFilter & \\hfuzz=500pt filename & \\hfuzz=500pt filter coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt first column: time steps, following columns: covariance functions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~column & \\hfuzz=500pt uint & \\hfuzz=500pt Column with covariance function to be fitted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~warmup & \\hfuzz=500pt uint & \\hfuzz=500pt number of samples until diagonal of Cholesky factor is flat (default: half covariance length)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~numeratorDegree & \\hfuzz=500pt uint & \\hfuzz=500pt Maximum degree of numerator polynomial (MA constituent)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~denominatorDegree & \\hfuzz=500pt uint & \\hfuzz=500pt Maximum degree of denominator polynomial (AR constitutent)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~decorrelationFilter & \\hfuzz=500pt boolean & \\hfuzz=500pt compute a decorrelation filter\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{CovarianceFunction2PowerSpectralDensity}\\label{CovarianceFunction2PowerSpectralDensity}\nOne sided Power Spectral Density (PSD) from a covariance function. The first column of \\configFile{inputfileCovarianceFunction}{matrix}\nshould contain the time lag in seconds.\nMultiple covariance functions (in the following column)s are supported.\nThe output is a \\file{matrix}{matrix} with first column contains the frequency $[Hz]$ and the other columns the PSD $[unit^2/Hz]$.\n\nConversion between covariance function $c_j$ and PSD $p_k$ is performed by discrete cosine transformation:\n\\begin{equation}\np_k = 2\\Delta t\\left(c_0 + c_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 c_j \\cos(\\pi jk/(n-1))\\right).\n\\end{equation}\n\nSee also \\program{PowerSpectralDensity2CovarianceFunction}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePSD & \\hfuzz=500pt filename & \\hfuzz=500pt first column: frequency [Hz], other columns PSD [unit\\textasciicircum{}2/Hz]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt first column: time steps, following columns: covariance functions\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{CovarianceMatrix2AutoregressiveModel}\\label{CovarianceMatrix2AutoregressiveModel}\nThis program computes a VAR(p) model from empirical covariance matrices.\nThe \\configFile{inputfileCovarianceMatrix}{matrix} represent the covariance structure of the process:\nthe first file should contain the auto-covariance, the second the cross-covariance of lag one,\nthe next cross-covariance of lag two and so on.\n\nCross-covariance matrices $\\Sigma_{\\Delta_k}$ are defined as the cross-covariance between epoch $t-k$ and $t$.\nIf the process realizations $x_{t}$ are arrange by ascending time stamps\n($\\{\\dots, x_{t-2}, x_{t-1}, x_{t}, x_{t+1}, x_{t+2},\\dots\\}$),\nthe covariance structure of the (stationary) process is therefore given by\n\\begin{equation}\n\\begin{bmatrix}\n\\Sigma & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\cdots \\\\\n\\Sigma_{\\Delta_1}^T & \\Sigma & \\Sigma_{\\Delta_1} &  \\cdots \\\\\n\\Sigma_{\\Delta_2}^T & \\Sigma_{\\Delta_1}^T & \\Sigma & \\cdots \\\\\n\\vdots & \\vdots & \\vdots & \\ddots \\\\\n\\end{bmatrix}.\n\\end{equation}\n\nThe estimate AR model is saved as single matrix \\config{outputfileAutoregressiveModel} according to the GROOPS AR model conventions.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAutoregressiveModel & \\hfuzz=500pt filename & \\hfuzz=500pt coefficients and white noise covariance of AR(p) model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt file name of covariance matrix\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{CovarianceMatrix2Correlation}\\label{CovarianceMatrix2Correlation}\nThis program computes the pearson correlation coefficient\n\\begin{equation}\n  \\rho_{ij} = \\frac{\\sigma_{ij}}{\\sigma_i \\sigma_j}\n\\end{equation}\nfrom a given covariance matrix stored in \\configFile{inputfileCovarianceMatrix}{matrix}.\nThe result is stored in \\configFile{outputfileCorrelationMatrix}{matrix}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCorrelationMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt correlation matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt covariance matrix\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PowerSpectralDensity2CovarianceFunction}\\label{PowerSpectralDensity2CovarianceFunction}\nCovariance function from Power Spectral Density (PSD).\nThe \\configFile{inputfilePSD}{matrix} contains in the first column the frequency $[Hz]$, followed by (possibly multiple) PSDs $[unit^2/Hz]$.\nThe output is a \\file{matrix}{matrix}, the first column containing time lag $[s]$ and the other columns the covariance functions $[unit^2]$.\nConversion between PSD $p_j$ and covariance function $c_k$ is performed by discrete cosine transformation:\n\\begin{equation}\nc_k = \\frac{1}{4\\Delta t (n-1)}\\left(p_0 + p_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 p_j \\cos(\\pi jk/(n-1))\\right).\n\\end{equation}\n\nSee also \\program{CovarianceFunction2PowerSpectralDensity}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt first column: time steps [seconds], following columns: covariance functions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePSD & \\hfuzz=500pt filename & \\hfuzz=500pt first column: frequency [Hz], following columns PSD [unit\\textasciicircum{}2/Hz]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: DoodsonHarmonics}\n\\subsection{DoodsonAdmittanceInterpolation}\\label{DoodsonAdmittanceInterpolation}\nTo visualize the interpolation of the minor tides.\nThe output is a \\file{matrix}{matrix} with the first column containing the tidal frequency,\nthe second column is the tide generating amplitude (from \\configFile{inputfileTideGeneratingPotential}{tideGeneratingPotential}), and the following\ncolumns the contribution of the major tides to the this tidal frequency as defined in in \\configFile{inputfileAdmittance}{admittance}.\n\n\\fig{!hb}{0.8}{doodsonAdmittanceInterpolation}{fig:doodsonAdmittanceInterpolation}{Linear interpolation of minor tides in the diurnal band.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt interpolation of minor constituents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonAdmittanceTimeSeries}\\label{DoodsonAdmittanceTimeSeries}\nTo visualize the interpolation of the minor tides it computes cosine multipliers of all major tides.\nWithout admittance this would be a simple cos oscillation.\nThe \\config{outputfileTimeSeries} is an \\file{instrument file}{instrument} (MISCVALUES) containining the cos of all the major tides.\n\n\\fig{!hb}{0.8}{doodsonAdmittanceTimeSeries}{fig:doodsonAdmittanceTimeSeries}{Cosine of the Mf tidal frequency with modulation from the interpolated minor tides.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES (cos of major tides, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt cos/sin multipliers of the major tides\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonArguments2TimeSeries}\\label{DoodsonArguments2TimeSeries}\nTime series of doodson/fundamental arguments.\nThe \\configFile{outputfileTimeSeries}{instrument} contains the six Doodson arguments,\nfollowed by the five fundamental arguments in radians.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt each epoch: 6 doodson args, 5 fundamental args [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonHarmonics2GriddedAmplitudeAndPhase}\\label{DoodsonHarmonics2GriddedAmplitudeAndPhase}\nThis program reads a \\configFile{inputfileDoodsonHarmonics}{doodsonHarmonic} and evaluates a single tidal\nconstituent selected by \\config{dooddson} (Doodson number or Darwin´s name, e.g. 255.555 or M2).\nThis program computes the amplitude and phase from the cos and sin coefficients on\na given \\configClass{grid}{gridType}. The type of functional (e.g gravity anomalies or geoid heights)\ncan be choosen with \\configClass{kernel}{kernelType}.\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nTo visualize the results use \\program{PlotMap}.\n\n\\fig{!hb}{1.}{doodsonHarmonics2GriddedAmplitudeAndPhase}{fig:doodsonHarmonics2GriddedAmplitudeAndPhase}{M2 amplitude and phase of FES2014b.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGrid & \\hfuzz=500pt filename & \\hfuzz=500pt ampl, phase [-pi,pi], cos, sin\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~doodson & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt tidal constituent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~filter & \\hfuzz=500pt \\hyperref[sphericalHarmonicsFilterType]{sphericalHarmonicsFilter} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the values on grid are multiplied by this factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{DoodsonHarmonics2PotentialCoefficients}\\label{DoodsonHarmonics2PotentialCoefficients}\nThe \\configFile{inputfileDoodsonHarmonics}{doodsonHarmonic} contains a Fourier series of a time variable\ngravitational potential at specific tidal frequencies (tides)\n\\begin{equation}\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\theta_f(t)) + V_f^s(\\M x)\\sin(\\theta_f(t)),\n\\end{equation}\nwhere $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics expansions.\nIf set the expansions are limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThe \\configFile{outputfilePotentialCoefficients}{potentialCoefficients} is not a single file but a series of files.\nFor each spherical harmonics expansion $V_f^c(\\M x)$ and $V_f^s(\\M x)$ a separate file is created\nwhere the variables \\config{variableLoopName}, \\config{variableLoopDoodson}, \\config{variableLoopCosSin} are set accordingly.\nThe file name should contain these variables, e.g. \\verb|coeff.{name}.{doodson}.{cossin}.gfc|.\n\nIf \\config{applyXi} the Doodson-Warburg phase correction (see IERS conventions) is applied to the cos/sin\npotentialCoefficients before.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopName & \\hfuzz=500pt string & \\hfuzz=500pt variable with darwins's name of each constituent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopDoodson & \\hfuzz=500pt string & \\hfuzz=500pt variable with doodson code of each constituent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCosSin & \\hfuzz=500pt string & \\hfuzz=500pt variable with 'cos' or 'sin' of each constituent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of each constituent (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of constituents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt to compute Xi phase correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~applyXi & \\hfuzz=500pt boolean & \\hfuzz=500pt apply Doodson-Warburg phase correction (see IERS conventions)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonHarmonicsCalculateAdmittance}\\label{DoodsonHarmonicsCalculateAdmittance}\nComputes the admittance function to interpolate minor tides from\ntides given in \\configFile{inputfileDoodsonHarmonics}{doodsonHarmonic}\nusing \\configFile{inputfileTideGeneratingPotential}{tideGeneratingPotential}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt TGP\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~threshold & \\hfuzz=500pt double & \\hfuzz=500pt [m\\textasciicircum{}2/s\\textasciicircum{}2] only interpolate tides with TGP greater than threshold\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~degreeInterpolation & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree for interpolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~degreeExtrapolation & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree for extrapolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~excludeDoodsonForInterpolation & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt major tides not used for interpolation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonHarmonicsChangePartialTides}\\label{DoodsonHarmonicsChangePartialTides}\nReads a file \\configFile{inputfileDoodsonHarmonic}{doodsonHarmonic} and write it to\n\\configFile{outputfileDoodsonHarmonics}{doodsonHarmonic}. If set the spherical harmonics\nexpansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusivly.\nThe \\configClass{useDoodson}{doodson} and \\configClass{ignoreDoodson}{doodson} can be used\nto filter the partial types that will be exported.\nAdditional partial tides can be interpolated using the file \\configFile{inputfileAdmittance}{admittance}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt interpolation of minor constituents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~useDoodson & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt use only these partial tides (additional tides will be interpolated)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~ignoreDoodson & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt ignore these partial tides\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ModelEquilibriumTide}\\label{ModelEquilibriumTide}\nComputes the equilibrium ocean tide of the long periodic \\config{tideGeneratingPotential}.\nThe spherical harmonics expansion up to \\config{maxDegree} with \\config{GM} and \\config{R}\nis estimated using a least squares adjustment.\n\nThe \\configFile{inputfileDensityGrid}{griddedData} must be a global regular grid with the\nvertically averaged seawater density over the ocean and zero over land.\n\nIt takes iteratively self attraction and loading into account using the Love numbers\n\\configFile{inputfilePotentialLoadLoveNumber}{matrix} and\n\\configFile{inputfileDeformationLoadLoveNumber}{matrix}.\n\nAdditionally the effects of the solid Earth tide are considered,\nboth the gravitational (Love numbers \\config{k20}, \\config{k20plus})\nand the geometrical (Love numbers \\config{h20,0}, \\config{h20,2}) effect.\n\nSee also \\program{PotentialCoefficients2DoodsonHarmonics}.\n\n\\fig{!hb}{0.8}{modelEquilibriumTide}{fig:modelEquilibriumTide}{Equilibrium tide of SA constituent}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt includes the loading\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDensityGrid & \\hfuzz=500pt filename & \\hfuzz=500pt [kg/m\\textasciicircum{}3] density of sea water, zero over land\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~tideGeneratingPotential & \\hfuzz=500pt double & \\hfuzz=500pt [m\\textasciicircum{}2/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~k20 & \\hfuzz=500pt double & \\hfuzz=500pt earth tide love number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~k20plus & \\hfuzz=500pt double & \\hfuzz=500pt earth tide love number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~h20\\_0 & \\hfuzz=500pt double & \\hfuzz=500pt earth tide love number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~h20\\_2 & \\hfuzz=500pt double & \\hfuzz=500pt earth tide love number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePotentialLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDeformationLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PotentialCoefficients2DoodsonHarmonics}\\label{PotentialCoefficients2DoodsonHarmonics}\nCreate a \\file{DoodsonHarmonic file}{doodsonHarmonic} from a list of\ncos/sin \\file{potentialCoefficients}{potentialCoefficients} for given \\config{doodson}\n(Doodson number or Darwin´s name, e.g. 255.555 or M2) tidal constituents.\nIf \\config{applyXi} the Doodson-Warburg phase correction (see IERS conventions) is applied before.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt to compute Xi phase correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~constituent & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~doodson & \\hfuzz=500pt \\hyperref[doodson]{doodson} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCosPotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinPotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~applyXi & \\hfuzz=500pt boolean & \\hfuzz=500pt apply Doodson-Warburg phase correction (see IERS conventions)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Gnss}\n\\subsection{GnssAntennaDefinition2ParameterVector}\\label{GnssAntennaDefinition2ParameterVector}\nEstimates parameters of a parametrization of \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType},\nwhich represents all antennas from \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\nmatching the wildcard patterns of \\config{name}, \\config{serial}, \\config{radome}.\n\nThe provided values at the area weighted grid points of the pattern of each gnssType are used as pseudo-observations.\nA subset of patterns can be selected with \\configClass{types}{gnssType}.\n\nThe \\file{GnssAntennaDefinition file}{gnssAntennaDefinition} can be modified to the demands before with\n\\program{GnssAntennaDefinitionCreate}.\n\nSee also \\program{ParameterVector2GnssAntennaDefinition}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antennaCenterVariations & \\hfuzz=500pt \\hyperref[parametrizationGnssAntennaType]{parametrizationGnssAntenna} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~types & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt if not set, all types in the file are used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~zeroNaN & \\hfuzz=500pt boolean & \\hfuzz=500pt treat NaN values as zero, otherwise values are ignored\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssAntennaDefinition2Skyplot}\\label{GnssAntennaDefinition2Skyplot}\nProduce a \\file{skyplot}{griddedData} of antenna center variations\nwhich can be plotted with \\program{PlotMap}.\n\nThe first antenna from \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\nmatching the wildcard patterns of \\config{name}, \\config{serial}, \\config{radome} is used.\n\nFor each antenna pattern (gnssType) a separate data column is computed.\nA subset of patterns can be selected with \\configClass{types}{gnssType}.\n\nAzimuth and elevation are written as ellipsoidal longitude and latitude in a \\file{griddedData file}{griddedData}.\nThe choosen ellipsoid parameters \\config{R} and \\config{inverseFlattening} are arbitrary but should be the same\nas in \\configClass{grid}{gridType} and \\program{PlotMap}.\n\n\\fig{!hb}{1.0}{fileFormatGnssAntennaDefinition}{fig:gnssAntennaDefinition2Skyplot}{Antenna Center Variations of ASH701945D\\_M for two frequencies of GPS and GLONASS}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt data column for each gnssType\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~types & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt if not set, all types in the file are used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssAntennaDefinitionCreate}\\label{GnssAntennaDefinitionCreate}\nCreate a \\file{GNSS antenna definition file}{gnssAntennaDefinition} (Antenna Center Variations, ACV) consisting of multiple antennas.\nThe antennas can be created from scratch or can be selected from existing files.\nThis program can also be used to modify existing files.\n\nFurthermore it can be used to create accuracy definition files containing azimuth and elevation dependent accuracy values for antennas.\nTo create an accuracy pattern for phase observations with \\verb|1 mm| accuracy at zenith and no azimuth dependency, define a\npattern with \\config{type}=\\verb|L|, \\config{values}=\\verb|0.001/cos(zenith/rho)|.\n\nThe antennas in \\configFile{outputfileAntennaDefinition}{gnssAntennaDefinition}\nare sorted by names and duplicates are removed (first one is kept).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt \\hyperref[gnssAntennaDefintionListType]{gnssAntennaDefintionList} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssAntennaNormalsConstraint}\\label{GnssAntennaNormalsConstraint}\nApply constraints to \\file{normal equations}{normalEquation}\ncontaining \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}.\nUsually the antenna center variations are estimated together with other parameters\nlike station coordinates, signal biases and slant TEC in \\program{GnssProcessing}.\nThis results in a rank deficient matrix as not all parameters can be separated.\nThe deficient can be solved by adding pseudo observation equations as constraints.\n\nTo separate antenna center variations and signal biases\napply \\config{constraint:mean} for each GNSS \\configClass{type}{gnssType}.\nThe observation equation for the integral mean of antenna center variations (ACV)\nin all azimuth~$A$ and elevation~$E$ dependent directions\n\\begin{equation}\n  0 = \\iint ACV(A,E)\\, d\\Phi \\approx \\sum_i ACV(A_i,E_i)\\, \\Delta\\Phi_i\n\\end{equation}\nis approximated by a grid defined by\n\\config{deltaAzimuth}, \\config{deltaZenith}, and \\config{maxZenith}.\n\nTo separate from station coordinates use \\config{constraint:centerMean}\nand from slant TEC parameters use \\config{constraint:TEC}.\n\nThe constraints are applied separately to all antennas matching\nthe wildcard patterns of \\config{name}, \\config{serial}, \\config{radome}.\n\nSee also \\program{ParameterVector2GnssAntennaDefinition}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt with applied constraints\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~constraint & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~center & \\hfuzz=500pt sequence & \\hfuzz=500pt zero center (x,y,z) of a single pattern\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt applied for each matching types\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~applyWeight & \\hfuzz=500pt boolean & \\hfuzz=500pt from normal equations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~centerMean & \\hfuzz=500pt sequence & \\hfuzz=500pt zero center (x,y,z) as (weighted) mean of all patterns\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~applyWeight & \\hfuzz=500pt boolean & \\hfuzz=500pt from normal equations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constant & \\hfuzz=500pt sequence & \\hfuzz=500pt zero constant (mean of all directions) of a single pattern\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt applied for each matching types\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~applyWeight & \\hfuzz=500pt boolean & \\hfuzz=500pt from normal equations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~constantMean & \\hfuzz=500pt sequence & \\hfuzz=500pt zero constant (mean of all directions) as (weighted) mean of all patterns\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~applyWeight & \\hfuzz=500pt boolean & \\hfuzz=500pt from normal equations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~TEC & \\hfuzz=500pt sequence & \\hfuzz=500pt zero TEC computed as (weighetd) least squares from all types\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt applied for combination of matching types\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~applyWeight & \\hfuzz=500pt boolean & \\hfuzz=500pt from normal equations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt [TECU]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antennaCenterVariations & \\hfuzz=500pt \\hyperref[parametrizationGnssAntennaType]{parametrizationGnssAntenna} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~antennaName & \\hfuzz=500pt string & \\hfuzz=500pt apply constraints to all machting antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~antennaSerial & \\hfuzz=500pt string & \\hfuzz=500pt apply constraints to all machting antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~antennaRadome & \\hfuzz=500pt string & \\hfuzz=500pt apply constraints to all machting antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaAzimuth & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] sampling of pattern to estimate center/constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] sampling of pattern to estimate center/constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxZenith & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] sampling of pattern to estimate center/constant\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssAttitudeInfoCreate}\\label{GnssAttitudeInfoCreate}\nCreates attitude info file (\\file{Instrument(MISCVALUES)}{instrument})\nused by \\program{SimulateStarCameraGnss}. One or more \\config{attitudeInfo}s can be specified.\nThey are valid from \\config{timeStart} until the start of the subsequent \\config{attitudeInfo}.\n\\config{maxManeuverTime} is used by \\program{SimulateStarCameraGnss} to look\nfor ongoing orbit maneuvers before/after the given orbit that might affect the attitude at\nthe beginning or end of a given orbit.\n\n\\fig{!hb}{0.9}{gnssAttitudeModes}{fig:gnssAttitudeModes2}{Overview of attitude modes used by GNSS satellites}\n\nHere is a list of GNSS satellite types for which the attitude behavior is known and their\nrespective attitude modes and required parameters:\n\\begin{itemize}\n\\item \\textbf{GPS-II/IIA} [1]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: shadowMaxYawSteeringAndRecovery\n  \\item \\config{noonMode}: catchUpYawSteering\n  \\item \\config{maxYawRate}: 0.12~deg/s\n  \\item \\config{yawBias}: 0.5~deg\n  \\item \\config{maxManeuverTime}: 2~h\n\\end{itemize}\n\\item \\textbf{GPS-IIR/IIR-M} [1]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: catchUpYawSteering\n  \\item \\config{noonMode}: catchUpYawSteering\n  \\item \\config{maxYawRate}: 0.2~deg/s\n  \\item \\config{maxManeuverTime}: 30~min\n\\end{itemize}\n\\item \\textbf{GPS-IIF} [2]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: shadowConstantYawSteering\n  \\item \\config{noonMode}: catchUpYawSteering\n  \\item \\config{maxYawRate}: 0.11~deg/s\n  \\item \\config{yawBias}: -0.7~deg\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\item \\textbf{GLO-M} [3]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: shadowMaxYawSteeringAndStop\n  \\item \\config{noonMode}: centeredMaxYawSteering\n  \\item \\config{maxYawRate}: 0.25~deg/s\n  \\item \\config{noonBetaThreshold}: 2~deg\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\item \\textbf{GAL-1} [4]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering1\n  \\item \\config{noonMode}: smoothedYawSteering1\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\item \\textbf{GAL-2} [4]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering2\n  \\item \\config{noonMode}: smoothedYawSteering2\n  \\item \\config{midnightBetaThreshold}: 4.1~deg\n  \\item \\config{noonBetaThreshold}: 4.1~deg\n  \\item \\config{activationThreshold}: 10~deg\n  \\item \\config{maxManeuverTime}: 5656~s\n\\end{itemize}\n\\item \\textbf{BDS-2G/3G} [5, 6]\n\\begin{itemize}\n  \\item \\config{defaultMode}: orbitNormal\n  \\item \\config{midnightMode}: orbitNormal\n  \\item \\config{noonMode}: orbitNormal\n\\end{itemize}\n\\item \\textbf{BDS-2I} [5]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: betaDependentOrbitNormal\n  \\item \\config{noonMode}: betaDependentOrbitNormal\n  \\item \\config{maxYawRate}: 0.085~deg/s\n  \\item \\config{midnightBetaThreshold}: 4~deg\n  \\item \\config{noonBetaThreshold}: 4~deg\n  \\item \\config{activationThreshold}: 5~deg\n  \\item \\config{maxManeuverTime}: 24~h\n\\end{itemize}\n\\item \\textbf{BDS-2M} [5]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: betaDependentOrbitNormal\n  \\item \\config{noonMode}: betaDependentOrbitNormal\n  \\item \\config{maxYawRate}: 0.159~deg/s\n  \\item \\config{midnightBetaThreshold}: 4~deg\n  \\item \\config{noonBetaThreshold}: 4~deg\n  \\item \\config{activationThreshold}: 5~deg\n  \\item \\config{maxManeuverTime}: 13~h\n\\end{itemize}\n\\item \\textbf{BDS-3I/3SI} [6]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering2\n  \\item \\config{noonMode}: smoothedYawSteering2\n  \\item \\config{midnightBetaThreshold}: 3~deg\n  \\item \\config{noonBetaThreshold}: 3~deg\n  \\item \\config{activationThreshold}: 6~deg\n  \\item \\config{maxManeuverTime}: 5740~s\n\\end{itemize}\n\\item \\textbf{BDS-3M/3SM} [6]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering2\n  \\item \\config{noonMode}: smoothedYawSteering2\n  \\item \\config{midnightBetaThreshold}: 3~deg\n  \\item \\config{noonBetaThreshold}: 3~deg\n  \\item \\config{activationThreshold}: 6~deg\n  \\item \\config{maxManeuverTime}: 3090~s\n\\end{itemize}\n\\item \\textbf{QZS-1} [7]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: betaDependentOrbitNormal\n  \\item \\config{noonMode}: betaDependentOrbitNormal\n  \\item \\config{maxYawRate}: 0.01~deg/s\n  \\item \\config{yawBias}: 180~deg\n  \\item \\config{midnightBetaThreshold}: 20~deg\n  \\item \\config{noonBetaThreshold}: 20~deg\n  \\item \\config{activationThreshold}: 18.5~deg\n  \\item \\config{maxManeuverTime}: 24~h\n\\end{itemize}\n\\item \\textbf{QZS-2G} [7]\n\\begin{itemize}\n  \\item \\config{defaultMode}: orbitNormal\n  \\item \\config{midnightMode}: orbitNormal\n  \\item \\config{noonMode}: orbitNormal\n  \\item \\config{yawBias}: 180~deg\n\\end{itemize}\n\\item \\textbf{QZS-2I} [7]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: centeredMaxYawSteering\n  \\item \\config{noonMode}: centeredMaxYawSteering\n  \\item \\config{maxYawRate}: 0.055~deg/s\n  \\item \\config{midnightBetaThreshold}: 5~deg\n  \\item \\config{noonBetaThreshold}: 5~deg\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\end{itemize}\n\nSome specific satellites may deviate in their attitude behavior or parameters\n(e.g. G013-G040, R713, C005, C015, C017, J001).\n\nReferences for the attitude behavior information:\n\\begin{enumerate}\n\\item \\href{https://doi.org/10.1007/s10291-008-0092-1}{Kouba (2009)}\n\\item \\href{https://doi.org/10.1007/s10291-016-0562-9}{Kuang et al. (2017)}\n\\item \\href{https://doi.org/10.1016/j.asr.2010.09.007}{Dilssner et al. (2011)}\n\\item \\url{https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3}\n\\item \\href{https://doi.org/10.1007/s10291-018-0783-1}{Wang et al. (2018)}\n\\item \\href{https://doi.org/10.1017/S0373463318000103}{Li et al. (2018)}\n\\item \\url{https://qzss.go.jp/en/technical/qzssinfo/index.html}\n\\end{enumerate}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAttitudeInfo & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~attitudeInfo & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~defaultMode & \\hfuzz=500pt choice & \\hfuzz=500pt default attitude mode\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~nominalYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~orbitNormal & \\hfuzz=500pt  & \\hfuzz=500pt keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~midnightMode & \\hfuzz=500pt choice & \\hfuzz=500pt attitude mode for maneuvers around orbit midnight\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~nominalYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~orbitNormal & \\hfuzz=500pt  & \\hfuzz=500pt keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~catchUpYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~shadowMaxYawSteeringAndRecovery & \\hfuzz=500pt  & \\hfuzz=500pt yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~shadowMaxYawSteeringAndStop & \\hfuzz=500pt  & \\hfuzz=500pt yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached, then stop (e.g. GLO-M (midnight))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~shadowConstantYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~centeredMaxYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~smoothedYawSteering1 & \\hfuzz=500pt  & \\hfuzz=500pt yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~smoothedYawSteering2 & \\hfuzz=500pt  & \\hfuzz=500pt yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~betaDependentOrbitNormal & \\hfuzz=500pt  & \\hfuzz=500pt switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~noonMode & \\hfuzz=500pt choice & \\hfuzz=500pt attitude mode for maneuvers around orbit noon\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~nominalYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~orbitNormal & \\hfuzz=500pt  & \\hfuzz=500pt keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~catchUpYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~centeredMaxYawSteering & \\hfuzz=500pt  & \\hfuzz=500pt yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~smoothedYawSteering1 & \\hfuzz=500pt  & \\hfuzz=500pt yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~smoothedYawSteering2 & \\hfuzz=500pt  & \\hfuzz=500pt yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~betaDependentOrbitNormal & \\hfuzz=500pt  & \\hfuzz=500pt switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~maxYawRate & \\hfuzz=500pt double & \\hfuzz=500pt [degree/s] maximum yaw rate of the satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~yawBias & \\hfuzz=500pt double & \\hfuzz=500pt [degree] yaw bias applied in satellite attitude control system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~midnightBetaThreshold & \\hfuzz=500pt double & \\hfuzz=500pt [degree] limit midnight maneuver to this absolute angle of the Sun above/below the satellite orbital plane\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~noonBetaThreshold & \\hfuzz=500pt double & \\hfuzz=500pt [degree] limit noon maneuver to this absolute angle of the Sun above/below the satellite orbital plane\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~activationThreshold & \\hfuzz=500pt double & \\hfuzz=500pt [degree] limit maneuver to this yaw/Earth-spacecraft-Sun angle (depending on mode)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~maxManeuverTime & \\hfuzz=500pt double & \\hfuzz=500pt [s] maximum duration of maneuver or maximum maneuver lookup time before/after orbit start/end\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssBiasClockAlignment}\\label{GnssBiasClockAlignment}\nThis program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks).\nEach 'group' of \\config{transmitter}s, usually a system like GPS or Galileo, is aligned individually by a constant shift over all transmitters.\nIf \\config{alignClocksByFreqNo} is set, GLONASS transmitters will be divided by frequency number into groups of nominally two transmitters.\nThe offset between clocks and reference clocks will be shifted into receiver code biases, if \\config{receiver} is provided.\"\n\nBy setting \\config{alignFreqNoBiasesAtReceiver} and providing \\config{receiver}, this program can further align GLONASS transmitter signal\nbiases so that the differences between frequency number-dependent receiver signal biases are minimal, which helps if PPP users don't set\nup individual signal biases per frequency number at the receiver. Alignment is done by computing signal bias residuals to the mean over all\nfrequency numbers of a signal type at each receiver and then computing the means over all receivers for each frequency number and shifting\nthose from the receiver signal biases to the transmitter signal biases. Internal consistency of the biases is not affected by this.\n\nIf you only want to align GLONASS frequency numbers, provide the same clocks in\n\\configFile{inputfileClock}{instrument} and \\configFile{inputfileReferenceClock}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~transmitter & \\hfuzz=500pt sequence & \\hfuzz=500pt one element per satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt aligned clock instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt (GLONASS only) aligned signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt clock instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileReferenceClock & \\hfuzz=500pt filename & \\hfuzz=500pt reference clock instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt (GLONASS only) signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt transmitter platform file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~receiver & \\hfuzz=500pt sequence & \\hfuzz=500pt one element per station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt aligned signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~alignClocksByFreqNo & \\hfuzz=500pt boolean & \\hfuzz=500pt align clocks for each GLONASS frequency number separately\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~alignFreqNoBiasesAtReceiver & \\hfuzz=500pt boolean & \\hfuzz=500pt align frequency number-dependent code biases for each receiver\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssEstimateClockShift}\\label{GnssEstimateClockShift}\nThis program estimates an epoch-wise clock shift in a constellation of GNSS satellites.\nEach separate \\config{data} represents a satellite... (e.g. 32 GPS satellites).\nThe shift to reference clocks can be estimated by providing \\configFile{inputfileInstrumentRef}{instrument}.\nClock shifts are estimated for each epoch given by \\configClass{timeSeries}{timeSeriesType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileShiftTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, clock shift\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~data & \\hfuzz=500pt sequence & \\hfuzz=500pt e.g. satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt corrected clocks\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileInstrumentDiff & \\hfuzz=500pt filename & \\hfuzz=500pt clock difference after correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt input clocks\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileInstrumentRef & \\hfuzz=500pt filename & \\hfuzz=500pt reference clocks (subtracted from input clocks)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt clock epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt [s] margin for time comparison\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssGlonassFrequencyNumberUpdate}\\label{GnssGlonassFrequencyNumberUpdate}\nUpdate/set GLONASS frequency number in \\configFile{inputfileTransmitterInfo}{platform} files.\nThe \\configFile{inputfilePrn2FrequencyNumber}{matrix} can be generated with\n\\program{SinexMetadata2GlonassFrequencyNumber}.\n\nSee also \\program{GnssAntex2AntennaDefinition}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt templated for PRN list (variableNamePrn)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt templated for PRN list (variableNamePrn)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePrn2FrequencyNumber & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~prn & \\hfuzz=500pt string & \\hfuzz=500pt PRN (e.g. R01) for transmitter info files\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableNamePrn & \\hfuzz=500pt string & \\hfuzz=500pt variable name for PRN in transmitter info files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssProcessing}\\label{GnssProcessing}\nThis program processes GNSS observations. It calculates the linearized observation equations,\naccumulates them into a system of normal equations and solves it.\n\nThe primary use cases of this program are:\n\\begin{itemize}\n  \\item \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork}\n  \\item \\reference{Kinematic orbit determination of LEO satellites}{cookbook.kinematicOrbit}\n  \\item \\reference{GNSS precise point positioning (PPP)}{cookbook.gnssPpp}\n\\end{itemize}\n\nThe observation epochs are defined by \\configClass{timeSeries}{timeSeriesType}\nand only observations at these epochs (within a \\config{timeMargin}) are considered.\n\nTo calculate observation equations from the tracks, the model parameters or unknown parameters need to be\ndefined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined\n\\configClass{parametrization}{gnssParametrizationType}.\nSome of the \\configClass{parametrization}{gnssParametrizationType} also include a priori models.\n\nLastly it is required to define the process flow of the gnssProcessing. This is accomplished\nwith a list of \\configClass{processingSteps}{gnssProcessingStepType}.\nEach step is processed consecutively. Some steps allow the selection of parameters, epochs,\nor the normal equation structure, which affects all subsequent steps.\nA minimal example consists of following steps:\n\\begin{itemize}\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: iterative float solution with outlier downeighting\n  \\item \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}:\n        fix ambiguities to integer and remove them from the normals\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: few iteration for final outlier downweighting\n  \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}:\n        write the output files defined in \\configClass{parametrization}{gnssParametrizationType}\n\\end{itemize}\n\nIf the program is run on multiple processes the \\configClass{receiver}{gnssReceiverGeneratorType}s\n(stations or LEO satellites) are distributed over the processes.\n\nSee also \\program{GnssSimulateReceiver}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt defines observation epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeMargin & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] margin to consider two times identical\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~transmitter & \\hfuzz=500pt \\hyperref[gnssTransmitterGeneratorType]{gnssTransmitterGenerator} & \\hfuzz=500pt constellation of GNSS satellites\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~receiver & \\hfuzz=500pt \\hyperref[gnssReceiverGeneratorType]{gnssReceiverGenerator} & \\hfuzz=500pt ground station network or LEO satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt apriori earth rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[gnssParametrizationType]{gnssParametrization} & \\hfuzz=500pt models and parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~processingStep & \\hfuzz=500pt \\hyperref[gnssProcessingStepType]{gnssProcessingStep} & \\hfuzz=500pt steps are processed consecutively\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GnssReceiverDefinitionCreate}\\label{GnssReceiverDefinitionCreate}\nCreate a \\file{GNSS receiver definition file}{gnssReceiverDefinition}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGnssReceiverDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~receiverDefinition & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~version & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~gnssType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssResiduals2AccuracyDefinition}\\label{GnssResiduals2AccuracyDefinition}\nCompute antenna accuracies from observation \\configFile{inputfileResiduals}{instrument}.\nThe \\configFile{inputfileStationInfo}{platform} is needed to assign\nthe residuals to the equipped antenna at observation times.\n\nThe \\configFile{outputfileAccuracyDefinition}{gnssAntennaDefinition} contains\nat first step the same accuracy information for all antennas as the input file.\nOnly the azimuth~$A$ and elevation~$E$ dependent grid points of the patterns\nwhere enough residuals are available ($>$ \\config{minRedundancy})\nare replaced by estimated accuracy\n\\begin{equation}\n \\sigma(A,E) = \\sqrt{\\frac{\\sum_i e_i^2(A,E)}{\\sum_i r_i(A,E)}},\n\\end{equation}\nwhere $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the\ncorresponding redundancies (number of observations minus the contribution to\nthe estimated parameters).\n\nThe \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} can be modified\nto the demands before with \\program{GnssAntennaDefinitionCreate}\n(e.g. with \\config{antenna:resample}).\n\nTo verify the results the \\configFile{outputfileAntennaMean}{gnssAntennaDefinition}\nand the accumulated \\configFile{outputfileAntennaRedundancy}{gnssAntennaDefinition}\nof the computed pattern grid points can be written.\n\nExample: Analysis of TerraSAR-X residuals of one month shows that low elevation\nGPS satellites are not tracked by the onboard receiver. An estimation of accuracies\nfor these directions is not possible from the residuals and the apriori accuracies\nare left untouched. The other directions show very low phase noise hardly elevation\nand azimuth dependent for L2W. A nearly zero mean indicates the use of adequate antennca\ncenter variations in the processing.\n\n\\fig{!hb}{0.8}{gnssResiduals2AccuracyDefinition}{fig:gnssResiduals2AccuracyDefinition}{L2W accuracies of TerraSAR-X determined from residuals of one month}\n\nSee also \\program{GnssResiduals2TransmitterAccuracyDefinition}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAccuracyDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt elevation and azimuth dependent accuracy\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntennaMean & \\hfuzz=500pt filename & \\hfuzz=500pt weighted mean of the residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntennaRedundancy & \\hfuzz=500pt filename & \\hfuzz=500pt redundancy of adjustment\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccuracyDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt apriori accuracies\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt to assign residuals to antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~isTransmitter & \\hfuzz=500pt boolean & \\hfuzz=500pt stationInfo is of a transmitter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~thresholdOutlier & \\hfuzz=500pt double & \\hfuzz=500pt ignore residuals with sigma/sigma0 greater than threshold\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minRedundancy & \\hfuzz=500pt double & \\hfuzz=500pt min number of residuals. to estimate sigma\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt GNSS receiver residuals\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssResiduals2Skyplot}\\label{GnssResiduals2Skyplot}\nWrite GNSS residuals together with azimuth and elevation to be plotted with \\program{PlotMap}.\nAzimuth and elevation are written as ellipsoidal longitude and latitude in a \\file{griddedData file}{griddedData}.\nThe choosen ellipsoid parameters \\config{R} and \\config{inverseFlattening} are arbitrary but should be the same\nas in \\program{PlotMap}. If with \\configClass{typeTransmitter}{gnssType} (e.g. '\\verb|***G18|')\na single transmitter is selected the azimuth and elevation are computed from the transmitter point of view.\n\nFor each GNSS \\configClass{type}{gnssType} an extra data column is created.\n\nA \\file{GNSS residual file}{instrument} includes additional information\nbesides the residuals, which can also be selected with \\configClass{type}{gnssType}\n\\begin{itemize}\n\\item \\verb|A1*|, \\verb|E1*|: azimuth and elevation at receiver\n\\item \\verb|A2*|, \\verb|E2*|: azimuth and elevation at transmitter\n\\item \\verb|I**|: Estimated slant total electron content (STEC)\n\\end{itemize}\n\nFurthermore these files may include for each residual \\configClass{type}{gnssType}\ninformation about the redundancy and the accuracy relation $\\sigma/\\sigma_0$\nof the estimated $\\sigma$ versus the apriori $\\sigma_0$ from the least squares adjustment.\nThe 3 values (residuals, redundancy, $\\sigma/\\sigma_0$) are coded with the same type.\nTo get access to all values the corresponding type must be repeated in \\configClass{type}{gnssType}.\n\n\\fig{!hb}{0.5}{gnssResiduals2Skyplot}{fig:gnssResiduals2Skyplot}{GPS C2W residuals of GRAZ station at 2012-01-01}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~typeTransmitter & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt choose transmitter view, e.g. '***G18'\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt GNSS receiver residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssResiduals2TransmitterAccuracyDefinition}\\label{GnssResiduals2TransmitterAccuracyDefinition}\nCompute antenna accuracies from observation \\configFile{inputfileResiduals}{instrument}.\nThe \\configFile{inputfileTransmitterInfo}{platform} is needed to assign\nthe residuals to the equipped antenna at observation times.\n\nThe \\configFile{outputfileAccuracyDefinition}{gnssAntennaDefinition} contains\nat first step the same accuracy information for all antennas as the input file.\nOnly the azimuth~$A$ and elevation~$E$ dependent grid points of the patterns\nwhere enough residuals are available ($>$ \\config{minRedundancy})\nare replaced by estimated accuracy\n\\begin{equation}\n \\sigma(A,E) = \\sqrt{\\frac{\\sum_i e_i^2(A,E)}{\\sum_i r_i(A,E)}},\n\\end{equation}\nwhere $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the\ncorresponding redundancies (number of observations minus the contribution to\nthe estimated parameters).\n\nThe \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} can be modified\nto the demands before with \\program{GnssAntennaDefinitionCreate}\n(e.g. with \\config{antenna:resample}).\n\nTo verify the results the \\configFile{outputfileAntennaMean}{gnssAntennaDefinition}\nand the accumulated \\configFile{outputfileAntennaRedundancy}{gnssAntennaDefinition}\nof the computed pattern grid points can be written.\n\nSee also \\program{GnssResiduals2AccuracyDefinition}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAccuracyDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt elevation and azimuth dependent accuracy\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntennaMean & \\hfuzz=500pt filename & \\hfuzz=500pt weighted mean of the residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntennaRedundancy & \\hfuzz=500pt filename & \\hfuzz=500pt redundancy of adjustment\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccuracyDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt apriori accuracies\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt to assign residuals to antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minRedundancy & \\hfuzz=500pt double & \\hfuzz=500pt min number of residuals. to estimate sigma\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt GNSS receiver residuals\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssSignalBias2Matrix}\\label{GnssSignalBias2Matrix}\nComputes signal biases for a given list of \\configClass{types}{gnssType}.\nIf the type list is empty, all types contained in \\configFile{inputfileSignalBias}{gnssSignalBias} are used.\nThe resulting \\configFile{outputfileMatrix}{matrix} contains a vector with an entry for each type.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTypes & \\hfuzz=500pt filename & \\hfuzz=500pt ASCII list of types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~types & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt if not set, all types in the file are used\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssSimulateReceiver}\\label{GnssSimulateReceiver}\nThis program simulates observations from receivers to GNSS satellites.\nThese simulated observations can then be used in \\program{GnssProcessing}, for example to conduct closed-loop simulations.\n\nOne or more GNSS constellations must be defined via \\configClass{transmitter}{gnssTransmitterGeneratorType}.\nReceivers such as ground station networks or Low Earth Orbit (LEO) satellites can be defined via \\configClass{receiver}{gnssReceiverGeneratorType}.\n\nIf multiple receivers defined an \\configFile{outputfileGnssReceiver}{instrument} and \\configFile{outputfileClock}{instrument}\nare written for each single receiver with the \\reference{variable}{general.parser} \\verb|{station}| being replaced by the receiver name.\n\nA list of simulated observation types can be defined via \\configClass{observationType}{gnssType}. Noise can be added to both observations and clock errors\nvia \\configClass{noiseObervation}{noiseGeneratorType} and \\configClass{noiseClockReceiver}{noiseGeneratorType}, respectively. Observation noise is\ninterpreted as a factor that is multiplied to the accuracy derived from the accuracy pattern of the respective observation type\n(see \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} in \\configClass{receiver}{gnssReceiverGeneratorType}).\n\nThe \\configClass{parametrization}{gnssParametrizationType} are used to simulate a priori models (e.g. troposphere, signal biases).\nParameter settings and outputfiles are ignored.\n\nIf the program is run on multiple processes the \\configClass{receiver}{gnssReceiverGeneratorType}s\n(stations or LEO satellites) are distributed over the processes.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGnssReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, simulated observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available, simulated receiver clock errors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt defines observation epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeMargin & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] margin to consider two times identical\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~transmitter & \\hfuzz=500pt \\hyperref[gnssTransmitterGeneratorType]{gnssTransmitterGenerator} & \\hfuzz=500pt constellation of GNSS satellites\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~receiver & \\hfuzz=500pt \\hyperref[gnssReceiverGeneratorType]{gnssReceiverGenerator} & \\hfuzz=500pt ground station network or LEO satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt apriori earth rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[gnssParametrizationType]{gnssParametrization} & \\hfuzz=500pt models and parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~observationType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt simulated observation types\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseObservation & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [-] noise is multiplied with type accuracy pattern of receiver\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseClockReceiver & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m] noise added to the simulated receiver clock\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentGnssReceiver2TimeSeries}\\label{InstrumentGnssReceiver2TimeSeries}\nConvert selected GNSS observations or residuals into a simpler time series format.\nThe \\config{outputfileTimeSeries} is an \\file{instrument file}{instrument} (MISCVALUES).\nFor each epoch the first data column contains the PRN, the second the satellite system,\nfollowed by a column for each GNSS \\configClass{type}{gnssType}.\nAs normally more than one GNSS transmitter is tracked per epoch, the output file\nhas several lines per observed epoch (epochs with the same time, one for each transmitter).\n\nThe second data column of the output contains a number representating the system\n\\begin{itemize}\n\\item 71: 'G', GPS\n\\item 82: 'R', GLONASS\n\\item 69: 'E', GALILEO\n\\item 67: 'C', BDS\n\\item 83: 'S', SBAS\n\\item 74: 'J', QZSS\n\\item 73: 'I', IRNSS .\n\\end{itemize}\n\nA \\file{GNSS residual file}{instrument} includes additional information\nbesides the residuals, which can also be selected with \\configClass{type}{gnssType}\n\\begin{itemize}\n\\item \\verb|A1*|, \\verb|E1*|: azimuth and elevation at receiver\n\\item \\verb|A2*|, \\verb|E2*|: azimuth and elevation at transmitter\n\\item \\verb|I**|: Estimated slant total electron content (STEC)\n\\end{itemize}\n\nFurthermore these files may include for each residual \\configClass{type}{gnssType}\ninformation about the redundancy and the accuracy relation $\\sigma/\\sigma_0$\nof the estimated $\\sigma$ versus the apriori $\\sigma_0$ from the least squares adjustment.\nThe three values (residuals, redundancy, $\\sigma/\\sigma_0$) are coded with the same type.\nTo get access to all values the corresponding type must be repeated in \\configClass{type}{gnssType}.\n\nExample: Selected GPS phase residuals (\\configClass{type}{gnssType}='\\verb|L1*G|' and \\configClass{type}{gnssType}='\\verb|L2*G|').\nPlotted with \\program{PlotGraph} with two \\configClass{layer:linesAndPoints}{plotGraphLayerType}\n(\\config{valueX}='\\verb|data0|',  \\config{valueY}='\\verb|100*data3+data1|' and \\config{valueY}='\\verb|100*data4+data1|' respectively).\n\\fig{!hb}{0.8}{instrumentGnssReceiver2TimeSeries}{fig:instrumentGnssReceiver2TimeSeries}{GPS residuals in cm, shifted by PRN}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt Instrument (MISCVALUES): prn, system, values for each type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGnssReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt GNSS receiver observations or residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ParameterVector2GnssAntennaDefinition}\\label{ParameterVector2GnssAntennaDefinition}\nUpdates an \\file{GnssAntennaDefinition file}{gnssAntennaDefinition} with estimated parameters which belongs\nto the parametrization \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}.\nThe \\configFile{outfileAntennaDefinition}{gnssAntennaDefinition} contains all antennas\nfrom \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}.\nThe antenna center variations representend by the \\configFile{inputfileSolution}{matrix} are added\nto the matching antennas.\n\nThe \\file{GnssAntennaDefinition file}{gnssAntennaDefinition} can be modified to the demands before with\n\\program{GnssAntennaDefinitionCreate}.\n\nThe following steps are used to estimate antenna center variations:\n\\begin{itemize}\n\\item \\program{GnssAntennaDefinitionCreate} or \\program{GnssAntex2AntennaDefinition}\n\\item \\program{GnssProcessing} with \\config{inputfileAntennaDefinition} as apriori\n      and writing \\file{normal equations}{normalEquation} with\n      parametrization of \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}\n\\item \\program{NormalsEliminate}: eliminate all other than antenna parameters\n\\item \\program{NormalsAccumulate}: accumulate normals over a sufficient long period\n\\item \\program{GnssAntennaNormalsConstraint}: constrain unsolvable parameter linear combinations\n\\item \\program{NormalsSolverVCE}: estimate the parameter vector\n\\item \\program{ParameterVector2GnssAntennaDefinition}: update \\config{inputfileAntennaDefinition}\n\\end{itemize}\n\nSee also \\program{ParameterVector2GnssAntennaDefinition}, \\program{GnssAntennaNormalsConstraint}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt all apriori antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt apriori antennas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antennaCenterVariations & \\hfuzz=500pt \\hyperref[parametrizationGnssAntennaType]{parametrizationGnssAntenna} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Grace}\n\\subsection{EnsembleAveragingScaleModel}\\label{EnsembleAveragingScaleModel}\nThis programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits from residuals.\nThe ensemble averaging method is used to characterize the average properties of signal shapes across all transit events.\nEach shape is assigned to one arc of 3 hours (default). This can be modefied by enabling \\config{averagingInterval}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileScaleModel & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGrace1EclipseFactor & \\hfuzz=500pt filename & \\hfuzz=500pt GRACE-A eclipse factors computed with integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGrace2EclipseFactor & \\hfuzz=500pt filename & \\hfuzz=500pt GRACE-B eclipse factors computed with integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGraceResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt SST Residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeMargin & \\hfuzz=500pt uint & \\hfuzz=500pt epochs before eclipse mode\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~waveLength & \\hfuzz=500pt uint & \\hfuzz=500pt length of the sample wave\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~averagingInterval & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~nearestNeighborNumber & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceAntennaCenterCorrectionArcCovariance}\\label{GraceAntennaCenterCorrectionArcCovariance}\nThis program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC)\nfrom the orientation covariance matrices provided in Level-1B products via variance propagation.\nBy using the output \\configFile{outputfileSatelliteTrackingCovariance}{matrix} in \\program{PreprocessingSst},\nnoise model distinguishes between the stationary noise of ranging observations and the non­stationary AOC noise.\n\nThe covariances are derived from the partial derivative of the AOC w.r.t. the roll/pitch/yaw rotations\nand star camera covariances \\configFile{inputfileScaCovariance1}{matrix} and \\configFile{inputfileScaCovariance2}{matrix}.\n\nThe covariances for the range-rates and range-acceleration are computed by differentiating\nan interpolation polynomial of degree \\config{interpolationDegree}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSatelliteTrackingCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt corrections for range, range-rate, and range-accelerations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeAcceleration & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileScaCovariance1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileScaCovariance2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaAccelerometerX & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaAccelerometerY & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaAccelerometerZ & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~antennaCenters & \\hfuzz=500pt choice & \\hfuzz=500pt KBR antenna phase center\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1X & \\hfuzz=500pt double & \\hfuzz=500pt x-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1Y & \\hfuzz=500pt double & \\hfuzz=500pt y-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1Z & \\hfuzz=500pt double & \\hfuzz=500pt z-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2X & \\hfuzz=500pt double & \\hfuzz=500pt x-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2Y & \\hfuzz=500pt double & \\hfuzz=500pt y-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2Z & \\hfuzz=500pt double & \\hfuzz=500pt z-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~file & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputAntennaCenters & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt differentiation by polynomial approximation of degree n\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GraceOrbit2TransplantTimeOffset}\\label{GraceOrbit2TransplantTimeOffset}\nThis program computes the time shift between two co-orbiting satellites based on dynamic orbit data.\nWhen applied to data of the first satellite, the computed time shift virtually shifts data of first satellite into the location of the second satellite.\nNote that \\config{inputfileOrbit1} and \\config{inputfileOrbit2} need velocity and acceleration data, which\ncan be computed with \\program{OrbitAddVelocityAndAcceleration}.\nThe program tries to find a minimum of the objective function\n\\begin{equation}\n  f(\\Delta t) = \\| r_1(t) - r_2(t + \\Delta t) \\|^2,\n\\end{equation}\nby applying Newton's method to the first derivative, thus iteratively computing\n\\begin{equation}\n  \\Delta t_{k+1} = \\Delta t_k + \\frac{f'(\\Delta t_k)}{f''(\\Delta t_k)}.\n\\end{equation}\nThis iteration is stopped when the difference between to consecutive time shift values falls below \\config{threshold} or\n\\config{maximumIterations} is reached. An \\config{initialGuess} of the time shift can speed up convergence.\n\nSee also \\program{OrbitAddVelocityAndAcceleration} and \\program{InstrumentApplyTimeOffset}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeOffset & \\hfuzz=500pt filename & \\hfuzz=500pt estimated time offset in seconds (MISCVALUE)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt orbit data of satellite 1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt orbit data of satellite 2\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree for the interpolation of position, velocity and acceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~initialGuess & \\hfuzz=500pt double & \\hfuzz=500pt initial guess for the time shift [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maximumIterations & \\hfuzz=500pt uint & \\hfuzz=500pt maximum number of iterations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~threshold & \\hfuzz=500pt double & \\hfuzz=500pt when the maximum difference between two iterations is below this value, stop [seconds]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GraceSstResidualAnalysis}\\label{GraceSstResidualAnalysis}\nThis program applies the Multi-Resolution Analysis (MRA) using\nDiscrete Wavelet Transform (DWT) to the monthly GRACE SST post-fit residuals.\nFirst, the residuals are transferred into wavelet domain by applying an 8 level\nDaubechies wavelet transform (default).\nIn the next step, detail coefficients are merged into three major groups\ndue to their approximate frequency subbands:\n\\begin{itemize}\n\\item Low scale details, corresponding to the frequency band above 10 mHz;\n\\item Intermediate scale details, corresponding to the approximate frequency\n      range above 3 mHz up to 10 mHz;\n\\item High scale details, corresponding to the approximate frequency range\nabove 0.5 mHz up to 10 mHz.\n\\end{itemize}\nIn the last step, each group is reconstructed back into time domain.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrumentHighScale & \\hfuzz=500pt filename & \\hfuzz=500pt High scale details\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrumentMidScale & \\hfuzz=500pt filename & \\hfuzz=500pt Intermediate scale details\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrumentLowScale & \\hfuzz=500pt filename & \\hfuzz=500pt Low scale details\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt GRACE SST Residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileWavelet & \\hfuzz=500pt filename & \\hfuzz=500pt wavelet coefficients\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceSstScaleModel}\\label{GraceSstScaleModel}\nThis programs estimate satellite-to-satellite-tracking (SST) deterministic signals\ndue to eclipse transits and low-SNR values from post-fit residuals.\nThe low-SNR effects are estimated by directly using the residual values.\nThe ensemble averaging method is used to characterize the average properties of eclipse transit signal shapes across all transit events.\nEach shape is assigned to one arc of 3 hours (default). This can be modefied by enabling \\config{averagingInterval}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGraceResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt SST Residuals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeMargin & \\hfuzz=500pt uint & \\hfuzz=500pt epochs before instrumental events\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~waveLength & \\hfuzz=500pt uint & \\hfuzz=500pt length of the sample wave\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateEclipseTransitScale & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfileScaleModel & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGrace1EclipseFactor & \\hfuzz=500pt filename & \\hfuzz=500pt GRACE-A eclipse factors computed with integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGrace2EclipseFactor & \\hfuzz=500pt filename & \\hfuzz=500pt GRACE-B eclipse factors computed with integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~averagingInterval & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~nearestNeighborNumber & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateLowSnrScale & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfileScaleModel & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGraceSstSNR & \\hfuzz=500pt filename & \\hfuzz=500pt GRACE SNR values\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceSstSpecialEvents}\\label{GraceSstSpecialEvents}\nTime-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions\ninto the star camera baffles of GRACE-A and eclipse transits of the satellites.\nThe events are determined by satellites' position (\\configFile{inputfileOrbit1/2}{instrument})\nand orientation (\\configFile{inputfileStarCamera1/2}{instrument}). Each type of event is represented\nby its mid-interval point per orbit revolution and is reported in \\configFile{outputfileEvents}{instrument}.\n\nThe waveform of each event is nearly constant within one month and can be approximated by a polynomial.\nFor the purpose of gravity field recovery, each waveform is parameterized by a polynomial and the coefficients\nof this polynomial are estimated as additional instrument calibration parameters in a common adjustment\nwith all other instrument, satellite, and gravity field parameters,\nsee \\configClass{parametrizationSatelliteTracking:specialEffect}{parametrizationSatelliteTrackingType:specialEffect}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEvents & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileIntervals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~marginLeft & \\hfuzz=500pt double & \\hfuzz=500pt margin size (on both sides) [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~marginRight & \\hfuzz=500pt double & \\hfuzz=500pt margin size (on both sides) [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceThrusterResponse2Accelerometer}\\label{GraceThrusterResponse2Accelerometer}\nAdd modeled thruster responses to accelerometer data.\nThe epochs and durations are given in the \\configFile{inputfileThruster}{instrument} (THRUSTER).\n\nThe \\configFile{inputfileThrusterResponse}{matrix} is a $(6\\times 3)$ matrix with\nthe linear accelerations in the SRF ($x, y, z$) in one line per pair:\n\\begin{enumerate}\n\\item Negative Yaw,\n\\item Positive Pitch,\n\\item Positive Yaw,\n\\item Negative Pitch,\n\\item Negative Roll,\n\\item Positive Roll.\n\\end{enumerate}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileThruster & \\hfuzz=500pt filename & \\hfuzz=500pt THRUSTER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileThrusterResponse & \\hfuzz=500pt filename & \\hfuzz=500pt thruster model (matrix with one line per pair)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentSatelliteTrackingAntennaCenterCorrection}\\label{InstrumentSatelliteTrackingAntennaCenterCorrection}\nThis program computes the correction due to offset of the antenna center relative the center of mass.\nThe offsets $\\M c_A$ and $\\M c_B$ in \\configFile{inputfileAntennaCenters}{matrix} are given in the satellite\nreference frame. These offsets are rotated into the the inertial frame with $\\M D_A$ and $\\M D_B$ from\n\\configFile{inputfileStarCamera}{instrument} and projected onto the line of sight (LOS)\n\\begin{equation}\n  \\rho_{AOC} = \\M e_{AB}\\cdot(\\M D_A\\,\\M c_A - \\M D_B\\,\\M c_B),\n\\end{equation}\nwith the unit vector in line of sight direction\n\\begin{equation}\n  \\M e_{AB} = \\frac{\\M r_B - \\M r_A}{\\left\\lVert{\\M r_B - \\M r_A}\\right\\rVert}.\n\\end{equation}\nThe corrections for the range-rates and range-acceleration are computed by differentiating\nan interpolation polynomial of degree \\config{interpolationDegree}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt corrections for range, range-rate, and range-accelerations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~antennaCenters & \\hfuzz=500pt choice & \\hfuzz=500pt KBR antenna phase center\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1X & \\hfuzz=500pt double & \\hfuzz=500pt x-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1Y & \\hfuzz=500pt double & \\hfuzz=500pt y-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1Z & \\hfuzz=500pt double & \\hfuzz=500pt z-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2X & \\hfuzz=500pt double & \\hfuzz=500pt x-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2Y & \\hfuzz=500pt double & \\hfuzz=500pt y-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2Z & \\hfuzz=500pt double & \\hfuzz=500pt z-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~file & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputAntennaCenters & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt differentiation by polynomial approximation of degree n\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentStarCameraAngularAccelerometerFusion}\\label{InstrumentStarCameraAngularAccelerometerFusion}\nThis program estimates the satellites orientation from star camera data\n\\configFile{inputfileStarCamera}{instrument} and angular accelerometer data\n\\configFile{inputfileAngularAcc}{instrument}. The combination of both observation types\nis achieved in a least square adjustment. The optimal weighting between the two different\nobservation groups is achieved by means of VCE in combination with a robust estimator.\nThe system of linearized observation equations within the sensor fusion approach can be formulated as:\n\\begin{equation}\n  \\begin{bmatrix}\n  \\M l_{ACC1B}\\\\\n  \\M l_{SCA1B}\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  \\M A_{ACC1B} & \\M B_{ACC1B}\\\\\n  \\M A_{SCA1B} & \\M 0\n  \\end{bmatrix}\n  \\begin{bmatrix}\n  \\M q\\\\\n  \\M b\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  \\frac{\\partial \\dot{\\boldsymbol{\\omega}}}{\\partial \\M q} & \\frac{\\partial \\dot{\\boldsymbol{\\omega}}}{\\partial \\M b}\\\\\n  \\M I & \\M 0\n  \\end{bmatrix}\n  \\begin{bmatrix}\n  \\M q\\\\\n  \\M b\n  \\end{bmatrix}\n\\end{equation}\nwith\n\\begin{equation}\\begin{split}\n  \\M l_{ACC1B}  &= \\dot{\\boldsymbol{\\omega}}_{ACC1B} - \\dot{\\boldsymbol{\\omega}}_{0}, \\\\\n  \\M l_{SCA1B}  &= \\M q_{SCA1B} - \\M q_{0}, \\\\\n  \\M q_{Fusion} &= \\M q + \\M q_{0}.\n\\end{split}\\end{equation}\nThe reference values $\\M q_{0}$ and $\\dot{\\boldsymbol{\\omega}}_{0}$ are derived\nfrom \\configFile{inputfileStarCameraReference}{instrument}. In the course of the estimation,\nthe accelerometer data is calibrated, by setting a bias factor $\\M b$ with \\config{accBias}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt combined quaternions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt epoch-wise covariance matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt full arc-wise covariance matrix per arc. arc number is appended to filename\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileEpochSigmaStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt from vce and outlier detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileEpochSigmaAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt from vce and outlier detection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularAcc & \\hfuzz=500pt filename & \\hfuzz=500pt angular acceleration observations (bias removed)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameter (one column for each arc)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCameraReference & \\hfuzz=500pt filename & \\hfuzz=500pt quaternions as taylor point\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt star camera observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCameraCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt star camera observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAngularAcc & \\hfuzz=500pt filename & \\hfuzz=500pt angular acceleration observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~correctAccNonQuadratic & \\hfuzz=500pt boolean & \\hfuzz=500pt apply correction (non-square proof mass)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~accBias & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt accelerometer bias per interval and axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~accScale & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt accelerometer scale per interval and axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaStarcamera & \\hfuzz=500pt double & \\hfuzz=500pt [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaAccelerometerX & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaAccelerometerY & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaAccelerometerZ & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateSigmaScaPerAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt separate variance factor for roll, pitch, yaw, instead of one common factor.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateSigmaAccPerAxis & \\hfuzz=500pt boolean & \\hfuzz=500pt separate variance factor for each accelerometer axis, instead of one common factor.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber*sigma0 are downweighted\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt residuals \\$>\\$ huber: sigma=(e/huber)\\textasciicircum{}power*sigma0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt non linear equation solved iteratively\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: Gravityfield}\n\\subsection{Gravityfield2AbsoluteGravity}\\label{Gravityfield2AbsoluteGravity}\nThis program computes the absolute value of gravity $\\left\\lVert{\\M g}\\right\\rVert$\nof a \\configClass{gravityfield}{gravityfieldType} on a given \\configClass{grid}{gridType}.\nThe result is multiplicated with \\config{factor}.\nTo get the full gravity vector in a terrestrial frame add\nthe centrifugal part, see \\configClass{gravityfield:tides:centrifugal}{tidesType:centrifugal}.\n\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\nIt is intended to compute gravity anomalies from absolute gravity observations.\nTo visualize the results use \\program{PlotMap}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2AreaMeanTimeSeries}\\label{Gravityfield2AreaMeanTimeSeries}\nThis program computes a time series of time variable\n\\configClass{gravityfield}{gravityfieldType} functionals averaged over a given area,\ne.g. equivalent water heights in the amazon basin.  The type of functional\n(e.g gravity anomalies or geoid heights) can be choosen with \\configClass{kernel}{kernelType}.\nThe average is performed at each time step by a weigthed average over all \\configClass{grid}{gridType}\npoints where the weight is the associated area at each point. If \\config{removeMean} is set\nthe temporal mean is removed from the time series. To speed up the computation\nthe gravity field can be converted to spherical harmonics before the computation\nwith \\config{convertToHarmonics}.\n\nAdditionally the root mean square of the values in the area at each time step\ncan is computed if \\config{compueRms} is set.\n\nAdditionally the accuracy of the value at each time step can be computed if \\config{compueSigma} is set.\n\nThe \\configFile{outputfileTimeSeries}{instrument} is an instrument file with one, two, or three data columns.\nFirst data column contains the computed functionals and the following columns contain the RMS and the accuracies (optionally).\n\nTo visualize the results use \\program{PlotGraph}.\n\n\\fig{!hb}{0.8}{gravityfield2AreaMeanTimeSeries}{fig:gravityfield2AreaMeanTimeSeries}{Amazon basin: Area mean values of ITSG-Grace2016 monthly solutions with error bars from computed sigma.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~convertToHarmonics & \\hfuzz=500pt boolean & \\hfuzz=500pt gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~multiplyWithArea & \\hfuzz=500pt boolean & \\hfuzz=500pt multiply time series with total area (useful for mass estimates)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt remove the temporal mean of the series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeRms & \\hfuzz=500pt boolean & \\hfuzz=500pt additional rms each time step\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeSigma & \\hfuzz=500pt boolean & \\hfuzz=500pt additional error bars at each time step\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2Deflections}\\label{Gravityfield2Deflections}\nThis program computes the deflections of the vertical $\\xi$ in north direction\nand $\\eta$ in east direction in radian\naccording to\n\\begin{equation}\n\\xi = g_x/\\gamma \\qquad\\text{and}\\qquad \\eta=g_y/\\gamma,\n\\end{equation}\nwhere $\\M g=\\nabla V$ is the gravity vector from \\configClass{gravityfield}{gravityfieldType} in\nthe local ellipsoidal system (north, east, up) and $\\gamma$ is the normal gravity at that point.\n\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt xi (north), eta (east) [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2DegreeAmplitudes}\\label{Gravityfield2DegreeAmplitudes}\nThis program computes degree amplitudes from a \\configClass{gravityfield}{gravityfieldType}\nand saves them to a \\file{matrix}{matrix} file with three columns: the degree, the degree amplitude, and the formal errors.\n\nThe coefficients can be converted to different functionals with \\configClass{kernel}{kernelType}.\nThe gravity field can be evaluated at different altitudes by specifying \\config{evaluationRadius}.\nPolar regions can be excluded by setting \\config{polarGap}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nSee also \\program{PotentialCoefficients2DegreeAmplitudes}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt three column matrix with degree, signal amplitude, formal error\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt type of variances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rms & \\hfuzz=500pt  & \\hfuzz=500pt degree amplitudes (square root of degree variances)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~accumulation & \\hfuzz=500pt  & \\hfuzz=500pt cumulate variances over degrees\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~median & \\hfuzz=500pt  & \\hfuzz=500pt median of absolute values per degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~evaluationRadius & \\hfuzz=500pt double & \\hfuzz=500pt evaluate the gravity field at this radius (default: evaluate at surface\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~polarGap & \\hfuzz=500pt angle & \\hfuzz=500pt exclude polar regions (aperture angle in degrees)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2DegreeAmplitudesPlotGrid}\\label{Gravityfield2DegreeAmplitudesPlotGrid}\nThis program computes a \\configClass{timeSeries}{timeSeriesType}\nof a time variable \\configClass{gravityfield}{gravityfieldType} and saves it as degree amplitudes.\nThe expansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusivly\n\\begin{equation}\n  \\sigma_n = \\frac{GM}{R}\\left(\\frac{R}{r}\\right)^{n+1}k_n\\sqrt{\\sum_{m=0}^n c_{nm}^2+s_{nm}^2}.\n\\end{equation}\n\nThe \\configFile{outputfileTimeSeries}{matrix} is a matrix with\nevery row containing the time, degree, degree amplitude, and the formal error.\n\nTo visualize the results use \\program{PlotGraph}).\n\nSee also \\program{Gravityfield2DegreeAmplitudes}.\n\n\\fig{!hb}{0.5}{gravityfield2DegreeAmplitudesPlotGrid}{fig:gravityfield2DegreeAmplitudesPlotGrid}{Degree amplitudes of monthly ITSG-Grace2016 solutions relative to GOCO05s.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt each row: mjd, degree, amplitude, formal error\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~evaluationRadius & \\hfuzz=500pt double & \\hfuzz=500pt evaluate the gravity field at this radius (default: evaluate at surface\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~polarGap & \\hfuzz=500pt angle & \\hfuzz=500pt exclude polar regions (aperture angle in degrees)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt minimal degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt maximal degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2DisplacementTimeSeries}\\label{Gravityfield2DisplacementTimeSeries}\nThis program computes a time series of displacements of a list of stations (\\configClass{grid}{gridType})\ndue to the effect of time variable loading masses. The displacement~$\\M u$ of a station is calculated according to\n\\begin{equation}\\label{eq:displacement}\n\\M u(\\M r) = \\frac{1}{\\gamma}\\sum_{n=0}^\\infty \\left[\\frac{h_n}{1+k_n}V_n(\\M r)\\,\\M e_{up}\n+ R\\frac{l_n}{1+k_n}\\left(\n \\frac{\\partial V_n(\\M r)}{\\partial \\M e_{north}}\\M e_{north}\n+\\frac{\\partial V_n(\\M r)}{\\partial \\M e_{east}} \\M e_{east}\\right)\\right],\n\\end{equation}\nwhere $\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by\n\\configFile{inputfileDeformationLoadLoveNumber}{matrix} and the load Love numbers $k_n$ are given by\n\\configFile{inputfilePotentialLoadLoveNumber}{matrix}. The $V_n$ are the spherical harmonics expansion of\nthe full time variable gravitational potential (potential of the loading mass + deformation potential):\n\\begin{equation}\nV(\\M r) = \\sum_{n=0}^\\infty V_n(\\M r).\n\\end{equation}\nDeformations due to Earth tide and due to polar tides are computed using the IERS conventions.\nEq.~\\eqref{eq:displacement} is not used in these cases.\n\nThe \\config{outputfileTimeSeries} is an \\file{instrument file}{instrument}, MISCVALUES.\nThe data columns contain the deformation of each station in $x,y,z$ in a global terrestrial\nreference frame or alternatively in a local elliposidal frame (north, east, up)\nif \\config{localReferenceFrame} is set.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt x,y,z [m] per station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt station list\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~tides & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDeformationLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfilePotentialLoadLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt if full potential is given and not only loading potential\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt remove the temporal mean of each coordinate\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~localReferenceFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt local left handed reference frame (north, east, up)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2EmpiricalCovariance}\\label{Gravityfield2EmpiricalCovariance}\nThis program estimates an spatial and temporal covariance matrix from\na time series of gravity fields.\n\nFirstly for every time step $t_i$\na spherical harmonics vector $\\M x_i$ from the time variable gravity field\nis generated. The coefficients of the spherical harmonics expansion are\nin the sequence given by \\configClass{numbering}{sphericalHarmonicsNumberingType}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The coefficients are related to the\nreference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nIn the next step the empirical covariance matrix is estimated according to\n\\begin{equation}\n\\M\\Sigma(\\Delta i)_{full} = \\frac{1}{N}\\sum_{i=1}^N \\M x_i \\M x_{i+\\Delta i}^T,\n\\end{equation}\nwhere $\\Delta i$ is given by \\config{differenceStep}.\n\nFrom the diagonal elements of $\\M\\Sigma(\\Delta i)$ the isotropic accuracies\nare computed\n\\begin{equation}\n\\sigma_n^2 = \\frac{1}{2n+1}\\sum_{m=0}^n \\sigma_{cnm}^2+\\sigma_{snm}^2,\n\\end{equation}\nand a diagonal matrix is constructed $\\Sigma_{iso} = \\text{diag}(\\sigma_2^2,\\ldots,\\sigma_N^2)$.\nThe result is computed:\n\\begin{equation}\n\\M\\Sigma(\\Delta i) = \\alpha_{full}\\M\\Sigma(\\Delta i)_{full}+\\alpha_{iso}\\M\\Sigma(\\Delta i)_{iso}.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme for solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt sampling of the gravityfield\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~differenceStep & \\hfuzz=500pt uint & \\hfuzz=500pt choose dt for: x,i(t) - x,j(t+dt)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factorFullMatrixPart & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factorIsotropicPart & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~intervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2Gradients}\\label{Gravityfield2Gradients}\nThis program computes gravity gradients from \\configClass{gravityfield}{gravityfieldType}\non a \\configClass{grid}{gridType} in a global terrestrial reference frame\nor alternatively in a local elliposidal frame (north, east, up) if \\config{localReferenceFrame} is set.\nIn \\configFile{outputfileGriddedData}{griddedData} the values $[Vxx, Vyy, Vzz, Vxy, Vxz, Vyz]$\nwill be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt Vxx Vyy Vzz Vxy Vxz Vyz\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~localReferenceFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt local left handed reference frame (north, east, up)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2GravityVector}\\label{Gravityfield2GravityVector}\nThis program computes gravity vectors from \\configClass{gravityfield}{gravityfieldType}\non a \\configClass{grid}{gridType} in a global terrestrial reference frame\nor alternatively in a local elliposidal frame (north, east, up) if \\config{localReferenceFrame} is set.\nIn \\configFile{outputfileGriddedData}{griddedData} the values $[gx, gy, gz]$\nwill be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt gx, gy, gz\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~localReferenceFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt local left handed reference frame (north, east, up)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2GridCovarianceMatrix}\\label{Gravityfield2GridCovarianceMatrix}\nThis program propagates the covariance matrix of a \\configClass{gravityfield}{gravityfieldType}\nevaluated at \\config{time} to a \\configClass{grid}{gridType}. The full variance-covariance matrix is computed\nand written to a \\file{matrix file}{matrix}:\n\\begin{equation}\n\\mathbf{\\Sigma}_\\mathbf{y} = \\mathbf{F}\\mathbf{\\Sigma}_\\mathbf{x}\\mathbf{F}^T\n\\end{equation}\nThe \\configClass{kernel}{kernelType} determines the quantity of the grid values, for example,\n\\configClass{kernel:waterHeight}{kernelType:waterHeight}.\n\nSee also \\program{GravityfieldCovariancesPropagation2GriddedData}, \\program{GravityfieldVariancesPropagation2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt symmetric grid covariance matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2GriddedData}\\label{Gravityfield2GriddedData}\nThis program computes values of a \\configClass{gravityfield}{gravityfieldType} on a given \\configClass{grid}{gridType}.\nThe type of value (e.g gravity anomalies or geoid heights) can be choosen with \\configClass{kernel}{kernelType}.\nIf a time is given the gravity field will be evaluated at this point of time otherwise only the static part will be used.\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nTo speed up the computation the gravity field can be converted to spherical harmonics before the computation\nwith \\config{convertToHarmonics}.\n\nTo visualize the results use \\program{PlotMap}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~convertToHarmonics & \\hfuzz=500pt boolean & \\hfuzz=500pt gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2GriddedDataTimeSeries}\\label{Gravityfield2GriddedDataTimeSeries}\nThis program computes values of a \\configClass{gravityfield}{gravityfieldType} on a given \\configClass{grid}{gridType}\nfor each time step of \\configClass{timeSeries}{timeSeriesType}.\nThe type of value (e.g gravity anomalies or geoid heights) can be choosen with \\configClass{kernel}{kernelType}.\nTo speed up the computation the gravity field can be converted to spherical harmonics before the computation\nwith \\config{convertToHarmonics}.\nThe \\configFile{outputfileTimeSeries}{instrument} is an instrument (MISCVALUES) file with a data column\nfor each grid point per epoch.\n\nThis program enables the use of all instrument programs like \\program{InstrumentFilter},\n\\program{InstrumentArcStatistics} or \\program{InstrumentDetrend} to analyze and manipulate time series of gridded data.\n\nSee also \\program{TimeSeries2GriddedData}, \\program{Gravityfield2GriddedData}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt each epoch: data of grid points (MISCVALUES)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~convertToHarmonics & \\hfuzz=500pt boolean & \\hfuzz=500pt gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Gravityfield2PotentialCoefficients}\\label{Gravityfield2PotentialCoefficients}\nThis program evaluates a time variable \\configClass{gravityfield}{gravityfieldType}\nat a given \\config{time} and saves it as a \\file{spherical harmonics file}{potentialCoefficients}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2PotentialCoefficientsTimeSeries}\\label{Gravityfield2PotentialCoefficientsTimeSeries}\nThis program computes a \\configClass{timeSeries}{timeSeriesType}\nof a time variable \\configClass{gravityfield}{gravityfieldType}\nand converts to coefficients of a spherical harmonics expansion.\nThe expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThe \\configFile{outputfileTimeSeries}{instrument} contains the potential coefficients\nas data columns for each epoch in the sequence given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (MISCVALUES)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2SphericalHarmonicsVector}\\label{Gravityfield2SphericalHarmonicsVector}\nThis program evaluates a time variable \\configClass{gravityfield}{gravityfieldType} at a given \\config{time}\nand saves a \\file{vector}{matrix} with the coefficients of a spherical harmonics expansion in the sequence given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}.\nIf set the expansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusively.\nThe coefficients are related to the reference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nThis coefficients vector can be used as a approximate solution, see \\program{NormalsMultiplyAdd},\nor as pseudo oberservations for regularization,\nsee \\configClass{normalEquation:regularization}{normalEquationType:regularization}.\n\nFor back transformation use \\program{Gravityfield2PotentialCoefficients}\nwith \\configClass{gravityfield:fromParametrization}{gravityfieldType:fromParametrization}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileVector & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startIndex & \\hfuzz=500pt uint & \\hfuzz=500pt start index to put the coefficients in the solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme for solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useSigma & \\hfuzz=500pt boolean & \\hfuzz=500pt use formal errors instead of coefficients\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2TimeSplines}\\label{Gravityfield2TimeSplines}\nThis program estimates splines in time domain from a time variable gravity field\nand writes \\configFile{outputfileTimeSplines}{timeSplinesGravityField}.\nThe \\configClass{gravityfield}{gravityfieldType} is sampled at \\configClass{sampling}{timeSeriesType}, converted to potential coefficients\nin the range between \\config{minDegree} and \\config{maxDegree} inclusively.\nThe time series of spherical harmonics can be temporal filtered with \\configClass{temporalFilter}{digitalFilterType}.\n\nIn the next step temporal splines with \\config{splineDegree} and nodal points given\nat \\configClass{splineTimeSeries}{timeSeriesType} are adjusted to the time series in a least squares sense.\nThis is very fast for block means (splineDegree = 0) but for other splines a large systems of equations\nmust be solved. In the adjustment process the time series of gravity fields can be interpreted as samples\nat the given times or as continuous function with linear behaviour between sampled points (\\config{linearInterpolation}).\n\nTo combine a series of potential coefficients to a spline file with block means (splineDegree = 0)\nuse the fast \\program{PotentialCoefficients2BlockMeanTimeSplines} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSplines & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~temporalFilter & \\hfuzz=500pt \\hyperref[digitalFilterType]{digitalFilter} & \\hfuzz=500pt filter sampled gravity field in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~sampling & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt gravity field is sampled at these times\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt remove the temporal mean of the series before estimating the splines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~linearInterpolation & \\hfuzz=500pt boolean & \\hfuzz=500pt assume linear behavior between sampled points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~splineDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of splines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~splineTimeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt nodal points of splines in time domain\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Gravityfield2TrendPotentialCoefficients}\\label{Gravityfield2TrendPotentialCoefficients}\nThis program estimates \\configClass{parametrizationTemporal}{parametrizationTemporalType}\n(e.g. mean, trend, annual) from a time variable gravity field.\n\nIn a first step a time variable \\configClass{gravityfield}{gravityfieldType}\nis sampled at \\configClass{timeSeries}{timeSeriesType}\nand converted to coefficients of a spherical harmonics expansion.\nThe expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusively.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThese coefficients serves as observations of\na \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares} to estimate\n\\configClass{parametrizationTemporal}{parametrizationTemporalType} parameters.\nFor each temporal parameter an\n\\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\nis generated.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt for each temporal parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberMaxIteration & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for robust estimation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GravityfieldCovariancesPropagation2GriddedData}\\label{GravityfieldCovariancesPropagation2GriddedData}\nThis program computes the covariance between a source point given\nby longitude/latitude (\\config{L}, \\config{B}) and the points of a \\configClass{grid}{gridType}\nin terms of the functional given by \\configClass{kernel}{kernelType} from the variance-covariance\nmatrix of a \\configClass{gravityfield}{gravityfieldType} evaluated at \\config{time}.\n\nIf \\config{computeCorrelation} is set, the program returns the correlation according to\n\\begin{equation}\nr_{ij} = \\frac{\\sigma_{ij}}{\\sigma_i \\sigma_j}\n\\end{equation}\nin the range of [-1, 1] instead of the covariance.\n\nSee also \\program{Gravityfield2GridCovarianceMatrix}, \\program{GravityfieldVariancesPropagation2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt gridded data file containing the covariance betwenn source point and grid points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt functional\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~L & \\hfuzz=500pt angle & \\hfuzz=500pt longitude of variance point\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~B & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of variance point\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt ellipsoidal height of source point\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeCorrelation & \\hfuzz=500pt boolean & \\hfuzz=500pt compute correlations instead of covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GravityfieldReplacePotentialCoefficients}\\label{GravityfieldReplacePotentialCoefficients}\nReplaces single potential coefficients in a gravity field.\nBoth \\configClass{gravityfield}{gravityfieldType}\nand \\configClass{gravityfieldReplacement}{gravityfieldType} are evaluated\nat \\config{time} and converted to spherical harmonic coefficients.\nSingle \\config{coefficients} are then replaced in \\configClass{gravityfield}{gravityfieldType}\nby the values from \\configClass{gravityfieldReplacement}{gravityfieldType}\nand the result is written to \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\nfrom \\config{minDegree} to \\config{maxDegree},\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt single coefficients are replaced by the other gravityfield\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfieldReplacement & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt contains the coefficients for replacement\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~coefficients & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~cnm & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~degree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~snm & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~degree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~order & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GravityfieldVariancesPropagation2GriddedData}\\label{GravityfieldVariancesPropagation2GriddedData}\nThis program propagates variance-covariance matrix of a \\configClass{gravityfield}{gravityfieldType}\nevaluated at \\config{time} to the points of a \\configClass{grid}{gridType} in terms of the functional\ngiven by \\configClass{kernel}{kernelType}.\nThe resulting \\file{outputfileGriddedData}{griddedData} contains the standard deviations of the grid\npoints.\n\nSee also \\program{Gravityfield2GridCovarianceMatrix}, \\program{GravityfieldCovariancesPropagation2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviation at each grid point\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt functional\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: Grid}\n\\subsection{GriddedData2AreaMeanTimeSeries}\\label{GriddedData2AreaMeanTimeSeries}\nThis program computes a time series of area mean values\nin a basin represented by \\configClass{border}{borderType} from a sequence of grid files.\nIf a file is not found, the epoch is skipped. Per default\nthe weighted average of all points in the given border is computed where the points are weighted by their area element.\n\nIf \\config{computeMean} is set, the time average of each grid points is subtracted before the computation.\nIf \\config{multiplyWithArea} is set, the weighted average is multiplied with the total basin area.\nThis is useful for computing the total mass in the basin.\n\nThe \\configFile{outputfileTimeSeries}{instrument} is an instrument file, where the first columns are the\nmean value each data column in the grid files, followed by the the weighted RMS\nfor each data column in the grid files if \\config{computeRms} is set.\nIf the number of data columns differs between the grid files, the remaining columns are padded with zeros.\n\nSee also \\program{Gravityfield2AreaMeanTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~multiplyWithArea & \\hfuzz=500pt boolean & \\hfuzz=500pt multiply time series with total area (useful for mass estimates)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt remove the temporal mean of the series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeRms & \\hfuzz=500pt boolean & \\hfuzz=500pt additional rms each time step\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedData2GriddedDataStatistics}\\label{GriddedData2GriddedDataStatistics}\nThis program assigns values \\configFile{inputfileGriddedData}{griddedData} to the nearest points\nof a new \\configClass{grid}{gridType}. If some of the new points are not filled in with data\n\\config{emptyValue} is used instead. If multiple points of the input fall on the same node\nthe result can be selected with \\config{statistics} (e.g. mean, root mean square, min, max, \\ldots).\nIt also is possible to simply count the number of data points that were assigned to each point.\n\nBe aware in case borders are given within \\configClass{grid}{gridType}, the \\configFile{outputfileGriddedData}{griddedData} will have points excluded before the assignement of old points to the new points.\nThe data from \\configFile{inputfileGriddedData}{griddedData} will not be limited by the given borders! See \\reference{GriddedDataConcatenate}{GriddedDataConcatenate} to limit the\n\\configFile{inputfileGriddedData}{griddedData} to given borders.\n\n\\fig{!hb}{0.8}{griddedData2GriddedDataStatistics}{fig:griddedData2GriddedDataStatistics}{Assignement of irregular distributed data to grid.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~statistic & \\hfuzz=500pt choice & \\hfuzz=500pt statistic used if multiple values fall on the same cell\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~mean & \\hfuzz=500pt  & \\hfuzz=500pt mean\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~wmean & \\hfuzz=500pt  & \\hfuzz=500pt area weighted mean\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rms & \\hfuzz=500pt  & \\hfuzz=500pt root mean square\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~wrms & \\hfuzz=500pt  & \\hfuzz=500pt area weighted root mean square\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~std & \\hfuzz=500pt  & \\hfuzz=500pt standard deviation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~wstd & \\hfuzz=500pt  & \\hfuzz=500pt area weighted standard deviation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sum & \\hfuzz=500pt  & \\hfuzz=500pt sum\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~min & \\hfuzz=500pt  & \\hfuzz=500pt minimum value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~max & \\hfuzz=500pt  & \\hfuzz=500pt maximum value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~count & \\hfuzz=500pt  & \\hfuzz=500pt number of values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~first & \\hfuzz=500pt  & \\hfuzz=500pt first value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~last & \\hfuzz=500pt  & \\hfuzz=500pt last value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~emptyValue & \\hfuzz=500pt double & \\hfuzz=500pt value for nodes without data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedData2GriddedDataTimeSeries}\\label{GriddedData2GriddedDataTimeSeries}\nWrite a series of \\configFile{inputfileGriddedData}{griddedData}\nwith the corresponding \\configClass{timeSeries}{timeSeriesType}\nas a single \\file{gridded data time series file}{griddedDataTimeSeries}.\nThe \\config{splineDegree} defines the possible temporal interpolation of data in the output file.\nFor a file with spline degree 0 (temporal block means) the time intervals\nin which the grids are valid are defined between adjacent points in time.\nTherefore one more point in time is needed than the number of input grid files for degree 0.\n\nSee also \\program{GriddedDataTimeSeries2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt file count must agree with number of times+splineDegre-1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~splineDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of splines\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedData2Matrix}\\label{GriddedData2Matrix}\nThis program converts \\configFile{inputfileGriddedData}{griddedData}\nto \\configFile{outputfileMatrix}{matrix} with data columns.\nThe grid is expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nThe content of the output matrix can be controlled by \\config{outColumn} expressions\napplied to every grid point. The common data variables for grids are available,\nsee \\reference{dataVariables}{general.parser:dataVariables}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt point list as matrix with longitude and latitude values in columns and possible additional columns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outColumn & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables: longitude, latitude, height, area, data0, data1, ...)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedData2PotentialCoefficients}\\label{GriddedData2PotentialCoefficients}\nThis program estimate potential coefficients from \\configFile{inputfileGriddedData}{griddedData}\ngravity field functionals. It used a simple quadrature formular\n\\begin{equation}\n  c_{nm} = \\frac{1}{4\\pi}\\frac{R}{GM} \\sum_i f_i \\left(\\frac{r_i}{R}\\right)^{n+1} k_n C_{nm}(\\lambda_i,\\vartheta_i)\\,\\Delta\\Phi_i\n\\end{equation}\nor a \\config{leastSquares} adjustment with block diagonal normal matrix (order by order).\nFor the latter one the data must be regular distributed.\n\nThe \\config{value}s $f_i$ and the \\config{weight}s $\\Delta\\Phi_i$ are expressions\nusing the common data variables for grids, see \\reference{dataVariables}{general.parser:dataVariables}.\nMultiple \\configFile{outputfilePotentialCoefficients}{potentialCoefficients} can be estimated in one step.\nFor each an indivdual \\config{value} must be specified.\nThe type of the gridded data (e.g gravity anomalies or geoid heights)\nmust be set with \\configClass{kernel}{kernelType} $k_n$.\n\nThe expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusively. The coefficients are related\nto the reference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nFor irregular distributed data and using the full variance covariance matrix use\n\\program{NormalsSolverVCE} together with \\configClass{oberservation:terrestrial}{observationType:terrestrial}\nand \\configClass{parametrizationGravity:sphericalHarmonics}{parametrizationGravityType:sphericalHarmonics}.\n\nSee also \\program{GriddedDataTimeSeries2PotentialCoefficients}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt one file for each value expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~weight & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt data type of input values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~leastSquares & \\hfuzz=500pt boolean & \\hfuzz=500pt false: quadrature formular, true: least squares adjustment order by order\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GriddedData2SphericalDistance}\\label{GriddedData2SphericalDistance}\nCompute the spherical distance on the unit sphere in radians between all point pairs of two grids.\nThe spherical distance is computed by\n\\begin{equation}\n  \\psi_{12} = \\arccos(\\M n_1 \\cdot \\M n_2),\n\\end{equation}\nwhere $\\M n_i$ is the (normalized) position. This implies that all points are projected onto the unit sphere.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt matrix containing the spherical distance between all point pairs [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid1 & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid2 & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedData2TimeSeries}\\label{GriddedData2TimeSeries}\nWrite a series of \\configFile{inputfileGriddedData}{griddedData} with the corresponding\n\\configClass{timeSeries}{timeSeriesType} as a single time series file\n(\\file{instrument}{instrument}, MISCVALUES).\n\nIf \\config{groupDataByPoints} is true the \\config{outputfileTimeSeries} starts\nfor each epoch with all data (\\verb|data0|, \\verb|data1|\\ldots) for the first point,\nfollowed by all data of the second point and so on.\nIf \\config{groupDataByPoints} is false, the file starts with \\verb|data0|\nfor all points, followed by all \\verb|data1| and so on.\n\nThis enables the use of all instrument programs like \\program{InstrumentFilter} or\n\\program{InstrumentDetrend} to analyze and manipulate time series of gridded data.\n\nSee also \\program{TimeSeries2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt each epoch: multiple data for points (MISCVALUES)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt file count must agree with number of times\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~groupDataByPoints & \\hfuzz=500pt boolean & \\hfuzz=500pt multiple data are given point by point, otherwise: data0 for all points, followed by all data1\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataCalculate}\\label{GriddedDataCalculate}\nThis program manipulates \\file{grid files}{griddedData} with data in columns similar to\n\\program{FunctionsCalculate}, see there for more details.\nIf several \\config{inputfile}s are given the data columns are copied side by side.\nAll \\config{inputfile}s must contain the same grid points.\nThe columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots.\n\nThe content of \\configFile{outputfileGriddedData}{griddedData} is controlled by \\config{outColumn}.\nThe algorithm to compute the output is as follows:\nThe expressions in \\config{outColumn} are evaluated once for each grid point of the input.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values\nfrom the input columns before.\nAdditional variables are available, e.g. \\verb|index|, \\verb|data0rms|,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nFor a simplified handling \\config{constant}s can be defined by \\verb|name=value|.\nIt is also possible to estimate \\config{parameter}s in a least squares adjustment.\nThe \\config{leastSquares} serves as template for observation equations for every point.\nThe expression \\config{leastSquares} is evaluated for each grid point.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nIn the next step the parameters are estimated in order to minimize the expressions in \\config{leastSquares}\nin the sense of least squares.\n\nAfterwards grid points are removed if one of the \\config{removalCriteria} expressions\nfor this grid point evaluates true (not zero).\n\nAn extra \\configFile{statistics:outputfile}{matrix} can be generated with one row of data.\nFor the computation of the \\config{outColumn} values\nall~\\reference{dataVariables}{general.parser:dataVariables} are available\n(e.g. \\verb|data3mean|, \\verb|data4std|) inclusively the \\config{constant}s and\nestimated \\config{parameter}s but without the \\verb|data0|,~\\verb|data1|,~\\ldots itself.\nThe variables and the numbering of the columns refers to the \\configFile{outputfileGriddedData}{griddedData}.\n\nSee also \\program{FunctionsCalculate}, \\program{InstrumentArcCalculate}, \\program{MatrixCalculate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~constant & \\hfuzz=500pt expression & \\hfuzz=500pt define a constant by name=value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameter & \\hfuzz=500pt expression & \\hfuzz=500pt define a parameter by name[=value]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~leastSquares & \\hfuzz=500pt expression & \\hfuzz=500pt try to minimize the expression by adjustment of the parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~removalCriteria & \\hfuzz=500pt expression & \\hfuzz=500pt points are removed if one criterion evaluates true. data0 is the first data field.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~longitude & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~latitude & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~height & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~area & \\hfuzz=500pt expression & \\hfuzz=500pt expression: e.g. deltaL * 2.0 * sin(deltaB/2.0) * cos(latitude/rho)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeArea & \\hfuzz=500pt boolean & \\hfuzz=500pt automatically area computation of rectangular grids (overwrite area)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~statistics & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with one row, columns are user defined\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outColumn & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute statistics columns, data* are the outputColumns\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataConcatenate}\\label{GriddedDataConcatenate}\nThis program concatenate grid from several \\configFile{inputfileGriddedData}{griddedData}\nand write it to a new \\configFile{outputfileGriddedData}{griddedData}.\nInput files must have the same number of data columns.\nIf \\config{sort} is enabled, the points are sorted by latitudes starting from north/west to south east.\nIdentical points (within a \\config{margin}) can be removed with \\config{removeDuplicates}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sortPoints & \\hfuzz=500pt boolean & \\hfuzz=500pt sort from north/west to south east\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeDuplicates & \\hfuzz=500pt choice & \\hfuzz=500pt remove duplicate points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~keepFirst & \\hfuzz=500pt sequence & \\hfuzz=500pt keep first point, remove all other identicals\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin distance for identical points [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~keepLast & \\hfuzz=500pt sequence & \\hfuzz=500pt keep last point, remove all other identicals\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin distance for identical points [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataCreate}\\label{GriddedDataCreate}\nThis program creates a \\configClass{grid}{gridType} and writes it to \\configFile{outputfileGrid}{griddedData}.\nThe grid is expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nExtra \\config{value} columns can be appended using expressions\nwith the common \\reference{data variables}{general.parser:dataVariables} for gridded data.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGrid & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables as 'longitude', 'height', 'area' are taken from the gridded data)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataInterpolate}\\label{GriddedDataInterpolate}\nInterpolate values of a regular rectangular \\configFile{inputfileGriddedData}{griddedData}\nto new points given by \\configClass{grid}{gridType} and write as \\configFile{outputfileGriddedData}{griddedData}.\nOnly longitude and latitude of points are considered; the height is ignored for interpolation.\n\n(Only nearest neighbor method is implemented at the moment.)\n\n\\fig{!hb}{0.8}{griddedDataInterpolate}{fig:griddedDataInterpolate}{Interpolation of point data from rectangular gridded data.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt must be rectangular\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~method & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~nearestNeighbor & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataReduceSampling}\\label{GriddedDataReduceSampling}\nGenerate coarse grid by computing area weighted mean values.\nThe number of points is decimated by averaging integer multiplies of grid points\n(\\config{multiplierLongitude}, \\config{multiplierLatitude}).\n\nif \\config{volumeConserving} is set, data are interpreted as heights above ellipsoid\nand the tesseroid volume\n\\begin{equation}\n  V=\\int_r^{r+H}\\int_{\\varphi_1}^{\\varphi_2}\\int_{\\lambda_1}^{\\lambda_2} r^2\\cos\\varphi\\,d\\varphi\\,d\\lambda\\,dr\n\\end{equation}\nis conserved, where $r$ is the radius of the ellipsoid at grid center and\n$(\\varphi_1-\\varphi_2)\\times(\\lambda_1-\\lambda_2)$ are the grid cell boundaries.\nThis is meaninful for Digital Elevation Models (DEM).\n\nThe fine grid can be written, where the first coarse grid values (data0) are additionally appended.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCoarseGridRectangular & \\hfuzz=500pt filename & \\hfuzz=500pt coarse grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileFineGridRectangular & \\hfuzz=500pt filename & \\hfuzz=500pt fine grid with additional coarse grid values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileFineGridRectangular & \\hfuzz=500pt filename & \\hfuzz=500pt Digital Terrain Model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~multiplierLongitude & \\hfuzz=500pt uint & \\hfuzz=500pt Generalizing factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~multiplierLatitude & \\hfuzz=500pt uint & \\hfuzz=500pt Generalizing factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~volumeConserving & \\hfuzz=500pt boolean & \\hfuzz=500pt data are interpreted as heights above ellipsoid\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataTimeSeries2GriddedData}\\label{GriddedDataTimeSeries2GriddedData}\nRead a \\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nand write for each epoch a \\file{gridded data file}{griddedData} where\nthe \\config{variableLoopTime} and \\config{variableLoopIndex} are expanded for\neach point of the given \\configClass{timeSeries}{timeSeriesType}\nto create the file name for this epoch (see \\reference{text parser}{general.parser:text}).\n\nIf \\configClass{timeSeries}{timeSeriesType} is not set\nthe temporal nodal points from the inputfile are used.\n\nSee also \\program{GriddedData2GriddedDataTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilesGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTime & \\hfuzz=500pt string & \\hfuzz=500pt variable with time of each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current epoch (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt otherwise times from inputfile are used\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataTimeSeries2PotentialCoefficients}\\label{GriddedDataTimeSeries2PotentialCoefficients}\nThis program estimate potential coefficients from\n\\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nin the same way as \\program{GriddedData2PotentialCoefficients}\nbut not only for one grid but for each epoch of\n\\configClass{timeSeries}{timeSeriesType} of if not set\nfor the temporal nodal points from the inputfile.\nThe \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\n(one for each \\config{value}) are written for each epoch with the expansion\nof \\config{variableLoopTime} and \\config{variableLoopIndex}\n(see \\reference{text parser}{general.parser:text}).\n\nSee also \\program{GriddedData2PotentialCoefficients}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfilesPotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTime & \\hfuzz=500pt string & \\hfuzz=500pt variable with time of each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current epoch (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt otherwise times from inputfile are used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables: longitude, latitude, height, area, data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~weight & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute values (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt kernel in which the grid values are given\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for potential coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~leastSquares & \\hfuzz=500pt boolean & \\hfuzz=500pt false: quadrature formular, true: least squares adjustment order by order\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GriddedTopography2AtmospherePotentialCoefficients}\\label{GriddedTopography2AtmospherePotentialCoefficients}\nEstimate interior and exterior potential coefficients for atmosphere above digital terrain models.\nCoefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.\nThe density of the atmosphere is assumed to be (Sjöberg, 1998)\n\\begin{equation}\n\\rho_0\\left(\\frac{R}{R+h}\\right)^\\nu,\n\\end{equation}\nwhere $R$ is the radial distance of the ellipsoid at each point, $h$ the radial height above the ellipsoid,\n$\\rho_0$ is \\config{densitySeaLevel} and \\config{nu} $\\nu$ is a constant factor. The density is integrated\nfrom \\config{radialLowerBound} and \\config{upperAtmosphericBoundary} above the ellipsoid.\nThe \\config{radialLowerBound} is typically the topography and can be computed as expression at every point\nfrom \\configFile{inputfileGriddedData}{griddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePotentialCoefficientsExterior & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePotentialCoefficientsInterior & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt Digital Terrain Model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~densitySeaLevel & \\hfuzz=500pt double & \\hfuzz=500pt [kg/m**3]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ny & \\hfuzz=500pt double & \\hfuzz=500pt Constant for Atmosphere\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radialLowerBound & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~upperAtmosphericBoundary & \\hfuzz=500pt double & \\hfuzz=500pt constant upper bound [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor, set -1 to subtract the field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GriddedTopography2PotentialCoefficients}\\label{GriddedTopography2PotentialCoefficients}\nEstimate potential coefficients from digital terrain models.\nCoefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePotentialCoefficientsInterior & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt Digital Terrain Model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~density & \\hfuzz=500pt expression & \\hfuzz=500pt expression [kg/m\\textasciicircum{}3]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radialUpperBound & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~radialLowerBound & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GriddedTopographyEllipsoidal2Radial}\\label{GriddedTopographyEllipsoidal2Radial}\nInterpolate digital terrain models from ellipoidal heights to radial heights.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt Digital Terrain Model\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Matrix2GriddedData}\\label{Matrix2GriddedData}\nThis program reads a \\file{matrix file}{matrix} with data in columns\nand convert into \\file{gridded data}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~points & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ellipsoidal & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~longitude & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~latitude & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~height & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~cartesian & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~x & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~y & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~z & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~area & \\hfuzz=500pt expression & \\hfuzz=500pt expression (e.g. deltaL*2*sin(deltaB/2)*cos(data1/RHO))\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sortPoints & \\hfuzz=500pt boolean & \\hfuzz=500pt sort from north/west to south east\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeArea & \\hfuzz=500pt boolean & \\hfuzz=500pt the area can be computed automatically for rectangular grids\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{MatrixRectangular2GriddedData}\\label{MatrixRectangular2GriddedData}\nRead gridded data (matrix).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rowMajor & \\hfuzz=500pt boolean & \\hfuzz=500pt true: data is ordered row by row, false: columnwise\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~startLongitude & \\hfuzz=500pt angle & \\hfuzz=500pt longitude of upper left corner of the grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~startLatitude & \\hfuzz=500pt angle & \\hfuzz=500pt latitude of upper left corner of the grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~deltaLongitude & \\hfuzz=500pt angle & \\hfuzz=500pt sampling, negative for east to west data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~deltaLatitude & \\hfuzz=500pt angle & \\hfuzz=500pt sampling, negative for south to north data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{TimeSeries2GriddedData}\\label{TimeSeries2GriddedData}\nInterpret the data columns of \\configFile{inputfileTimeSeries}{instrument}\nas data points of a corresponding \\configClass{grid}{gridType}.\n\nFor each epoch a \\file{gridded data file}{griddedData} is written where\nthe \\config{variableLoopTime} and \\config{variableLoopIndex} are expanded for\neach point of the given time series to create the file name for this epoch\n(see \\reference{text parser}{general.parser:text}).\n\nThe number of input data columns must be a multiple of the number $n$ of grid points.\nIf \\config{isGroupedDataByPoint} is true the \\configFile{inputfileTimeSeries}{instrument} starts\nwith all data (\\verb|data0|, \\verb|data1|\\ldots) for the first point, followed by all data of the second point and so on.\nIf \\config{isGroupedDataByPoint} is false, the file starts with \\verb|data0| for all points, followed by all \\verb|data1| and so on.\n\nSee also \\program{GriddedData2TimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilesGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTime & \\hfuzz=500pt string & \\hfuzz=500pt variable with time of each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current epoch (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt each epoch: multiple data for points (MISCVALUES)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt corresponding grid points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~isDataGroupedByPoint & \\hfuzz=500pt boolean & \\hfuzz=500pt multiple data are given point by point, otherwise: first data0 for all points, followed by all data1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Instrument}\n\\subsection{Instrument2AllanVariance}\\label{Instrument2AllanVariance}\nThis program computes the overlapping Allan variance from an\n\\configFile{inputfileInstrument}{instrument}.\nThe estimate is averaged over all arcs (arcs are assumed to contain no data gaps).\n\nThe overlapping Allan variance is defined as\n\\begin{equation}\n  \\sigma^2(m\\tau_0) = \\frac{1}{2(m\\tau_0)^2(N-2m)} \\sum_{n=1}^{N-2m}(x_{n+2m}-2x_{n+m}+x_n)^2,\n\\end{equation}\nwhere $m\\tau_0$ is the averaging interval defined by the median sampling $\\tau_0$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAllanVariance & \\hfuzz=500pt filename & \\hfuzz=500pt column 0: averaging interval [seconds], column 1-(n-1): Allan variance for each data column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Instrument2CovarianceFunctionVCE}\\label{Instrument2CovarianceFunctionVCE}\nThis estimates a covariance function of \\configFile{inputfileInstrument}{instrument}\nfor all selected columns with \\config{startDataFields} and \\config{countDataFields}.\nThe estimation is performed robustly via variance component estimation.\nBad arcs are downweigthed and the accuracies can be written with \\configFile{outputfileSigmasPerArc}{matrix}.\nThe length of the covariance functions are determined by the longest arc.\nAdditionaly the data can be detrended with \\configClass{parameter}{parametrizationTemporalType}\nand \\configClass{parameterPerArc}{parametrizationTemporalType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameter vector (global part only)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameter & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt data is reduced by temporal representation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameterPerArc & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt data is reduced by temporal representation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt number of iterations for the estimation\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Instrument2CrossCorrelationFunction}\\label{Instrument2CrossCorrelationFunction}\nThis program computes the cross correlation between all corresponding data columns\nin two \\file{instrument files}{instrument}. The instrument files must be synchronized (\\program{InstrumentSynchronize}).\nThe \\configFile{outputfileCorrelation}{matrix} is a matrix with the first column containing the time lag followed by\ncross-correlation function for each data column. The maximum lag is defined by the maximum arc length.\n\nThe correlation is based on the unbiased estimate of the cross-covariance between data columns $x$ and $y$,\n\\begin{equation}\n  \\sigma_{xy}(h) = \\frac{1}{N}\\sum_{k=1} x_{k+h} y_k,\n\\end{equation}\nwhich is averaged over all arcs. From this estimate, the correlation for each lag is then computed via\n\\begin{equation}\n  r_{xy}(h) = \\frac{\\sigma_{xy}(h)}{\\sigma_x(0)\\sigma_y(0)},\n\\end{equation}\nwhich is the ratio between the biased estimates of the cross-covariance at lag $h$ and the auto-covariance of the individual data columns.\n\nFor instrument with data gaps, lag bins without any data are set to NAN.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCorrelation & \\hfuzz=500pt filename & \\hfuzz=500pt column 1: time lag, column 2..n cross-correlation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrumentReference & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Instrument2Histogram}\\label{Instrument2Histogram}\nThis program computes the arc-wise histogram from an \\file{instrument file}{instrument}.\nThe output is a \\file{matrix}{matrix} with the first column containing the lower bound of each bin.\nThe other columns contain the histograms for each arc.\n\n\\fig{!hb}{0.8}{instrument2Histogram}{fig:instrument2Histogram}{GRACE range-rate residuals of one month (one arc) divided into 50 bins.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt column 1: lower bin bound; columns 2 to N: histogram of each arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~selectDataField & \\hfuzz=500pt uint & \\hfuzz=500pt select channel for histogram computation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~binCount & \\hfuzz=500pt uint & \\hfuzz=500pt (default: Freedman-Diaconis' choice, maximum of all channels)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~lowerBound & \\hfuzz=500pt expression & \\hfuzz=500pt lower bound for bins (default: global minimum, data values outside are ignored)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~upperBound & \\hfuzz=500pt expression & \\hfuzz=500pt upper bound for bins (default: global maximum, data values outside are ignored)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~relative & \\hfuzz=500pt boolean & \\hfuzz=500pt output relative frequencies\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~cumulative & \\hfuzz=500pt boolean & \\hfuzz=500pt accumulate frequencies\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Instrument2PowerSpectralDensity}\\label{Instrument2PowerSpectralDensity}\nThis program computes the power spectral density (PSD) for all data fields in an \\file{instrument file}{instrument}.\nThe PSD is computed using Lomb's method. For each arc and each frequency $f$, a sinusoid is fit to the data\n\\begin{equation}\n  l_i = a \\cos(2\\pi f t_i) + b \\sin(2\\pi f t_i) + e_i\n\\end{equation}\n\nThe PSD for this frequency is then computed by forming the square sum of adjusted observations:\n\\begin{equation}\n  P(f) = \\sum_i \\hat{l}^2_i.\n\\end{equation}\n\nThe resulting PSD is the average over all arcs. For regularly sampled time series,\nthis method yields the same results as FFT based PSD estimates.\n\nA regular frequency grid based on the longest arc and the median sampling is computed.\nThe maximum number of epochs per arc is determined by\n\\begin{equation}\n  N = \\frac{t_{\\text{end}} - t_{\\text{start}}}{\\Delta t_{\\text{median}} } + 1,\n\\end{equation}\nthe Nyquist frequency is given by\n\\begin{equation}\n  f_{\\text{nyq}} = \\frac{1}{2\\Delta t_{\\text{median}}}.\n\\end{equation}\n\nIf it is suspected that \\configFile{inputfileInstrument}{instrument} contains secular variations,\nthe input should be detrended using \\program{InstrumentDetrend}.\n\nSee also \\program{Instrument2CovarianceFunctionVCE},\n\\program{CovarianceFunction2PowerSpectralDensity}, \\program{PowerSpectralDensity2CovarianceFunction}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePSD & \\hfuzz=500pt filename & \\hfuzz=500pt estimated PSD: column 0: frequency vector, column 1-(n-1): PSD estimate for each channel\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Instrument2RmsPlotGrid}\\label{Instrument2RmsPlotGrid}\nThis program computes an RMS plot grid from one or more \\configFile{inputfileInstrument}{instrument}\ncontaining 3D data (e.g. orbits or station positions), which can then be plotted as gridded data in \\program{PlotGraph}.\nThe RMS is computed from the difference between \\configFile{inputfileInstrument}{instrument} and\n\\configFile{inputfileInstrumentReference}{instrument}.\nAll instrument files must be synchronized (see \\program{InstrumentSynchronize}).\n\nEach separate \\configFile{inputfileInstrument}{instrument} represents an entry (e.g. a satellite or station)\nin the resulting grid. Therefore, providing, for example, 32 orbit files of GPS satellites\nresults in a grid with columns: mjd, id (0-31), rms.\n\nThe first three data columns of the instrument data are considered for computation of the RMS values.\nThe \\config{factor} can be set to, for example, sqrt(3) to get 3D instead of 1D RMS values.\n\nIf \\configClass{timeIntervals}{timeSeriesType} are provided, each \\configFile{inputfileInstrument}{instrument}\nand \\configFile{inputfileInstrumentReference}{instrument} serves as a template with variable \\verb|loopTime|.\nThis allows concatenation of instrument files, for example to create a month-long RMS plot grid from daily GPS\norbit files (see below).\n\nHelmert parameters between the two frames can be estimated each epoch optionally if\n\\config{estimateShift}, \\config{estimateScale}, or \\config{estimateRotation} are set.\nIt uses a \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\n\\fig{!hb}{0.8}{instrument2RmsPlotGrid}{fig:instrument2RmsPlotGrid}{Comparison of estimated GPS orbits with IGS final solution.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileRmsPlotGrid & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, id, rms\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileHelmertTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, tx, ty, tz, scale, rx, ry, rz\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt one file per satellite/station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileInstrumentReference & \\hfuzz=500pt filename & \\hfuzz=500pt one file per satellite/station, same order as above\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeIntervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt for \\{loopTime\\} variable in inputfile\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt e.g. sqrt(3) for 3D RMS\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateShift & \\hfuzz=500pt boolean & \\hfuzz=500pt coordinate center every epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateScale & \\hfuzz=500pt boolean & \\hfuzz=500pt scale factor of position every epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateRotation & \\hfuzz=500pt boolean & \\hfuzz=500pt rotation every epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberMaxIteration & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for robust estimation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Instrument2Scaleogram}\\label{Instrument2Scaleogram}\nThis program computes the wavelet transform of a time series up to a \\config{maxLevel}.\nThe scalogram is written to a matrix which can be plotted by using a gridded layer in \\program{PlotGraph}.\nIndividual detail levels can be written to matrix files by setting \\configFile{outputfileLevels}{matrix}.\nThe data column to be decomposed must be set by \\config{selectDataField}.\n\nThe wavelet transform is implemented as a filter bank, so care should be taken when the input contains data gaps.\nLow/highpass wavelet filters are applied in forward and backward direction, input is padded symmetric.\nSee \\configClass{digitalFilter}{digitalFilterType} for details.\n\n\\fig{!hb}{0.8}{instrument2Scaleogram}{fig:Instrument2Scaleogram}{GRACE range-rate residuals of one month.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileScaleogram & \\hfuzz=500pt filename & \\hfuzz=500pt matrix columns: mjd, level, value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileLevels & \\hfuzz=500pt filename & \\hfuzz=500pt use loopLevel as variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileWavelet & \\hfuzz=500pt filename & \\hfuzz=500pt wavelet coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~selectDataField & \\hfuzz=500pt uint & \\hfuzz=500pt data column to transform\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxLevel & \\hfuzz=500pt uint & \\hfuzz=500pt maximum level of decomposition (default: full)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Instrument2SpectralCoherence}\\label{Instrument2SpectralCoherence}\nThis program computes the spectral coherence between two \\file{instrument files}{instrument}.\n\nThe (magnitude-squared) coherence is defined as\n\\begin{equation}\n  C_{xy}(f) = \\frac{|P_{xy}(f)|^2}{P_{xx}(f)P_{yy}(f)}\n\\end{equation}\nand is a measure in the range [0, 1] for the similarity of the signals $x$ and $y$ in frequency domain.\n$P_{xy}$ is the cross-spectral density between $x$ and $y$ and $P_{xx}$, $P_{yy}$ are auto-spectral densities.\nAuto- and cross-spectral densities are computed using Lomb's method (see \\program{Instrument2PowerSpectralDensity} for details).\n\nThe resulting PSD is the average over all arcs. For regularly sampled time series,\nthis method yields the same results as FFT based PSD estimates.\n\nA regular frequency grid based on the longest arc and the median sampling is computed.\nThe maximum number of epochs per arc is determined by\n\\begin{equation}\n  N = \\frac{t_{\\text{end}} - t_{\\text{start}}}{\\Delta t_{\\text{median}} } + 1,\n\\end{equation}\nthe Nyquist frequency is given by\n\\begin{equation}\n  f_{\\text{nyq}} = \\frac{1}{2\\Delta t_{\\text{median}}}.\n\\end{equation}\n\nIf it is suspected that \\configFile{inputfileInstrument}{instrument} contains secular variations,\nthe input should be detrended using \\program{InstrumentDetrend}.\n\nThe \\configFile{outputfileCoherence}{matrix} contains a matrix with the frequency vector as first column,\nthe coherence for each instrument channel is saved in the following columns.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCoherence & \\hfuzz=500pt filename & \\hfuzz=500pt column 1: frequency, column 2-n coherence\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrumentReference & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Instrument2Spectrogram}\\label{Instrument2Spectrogram}\nThis program applies the Short Time Fourier Transform (STFT) to selected data columns\nof \\configFile{inputfileInstrument}{instrument} and computes the spectrogram.\nThe STFT is computed at centered \\configClass{timeSeries}{timeSeriesType} with\nan (possible overlapping) rectangular window with \\config{windowLength} seconds.\nData gaps are zero padded within the window.\n\nThe \\configFile{outputfileSpectrogram}{matrix} is a matrix with each row the time (MJD),\nthe frequency $[Hz]$, and the amplitudes $[unit/\\sqrt{Hz}]$ for the selected data columns.\nIt can be plotted with \\program{PlotGraph}.\n\n\\fig{!hb}{0.8}{instrument2Spectrogram}{fig:instrument2Spectrogram}{GRACE range-rate residuals of one month (window of 6 hours).}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSpectrogram & \\hfuzz=500pt filename & \\hfuzz=500pt mjd, freq, ampl0, ampl1, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt center of SFFT window\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~windowLength & \\hfuzz=500pt double & \\hfuzz=500pt [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all)\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentAccelerometer2ThermosphericDensity}\\label{InstrumentAccelerometer2ThermosphericDensity}\nThis program estimates neutral mass densities along the satellite trajectory based on \\file{accelerometer data}{instrument}.\nIn order to determine the neutral mass density the accelerometer input should only reflect the accelerations due to drag\n(e.g. \\configClass{miscAccelerations:atmosphericDrag}{miscAccelerationsType:atmosphericDrag}).\nThus, influences from solar and Earth radiation pressure must be reduced beforehand.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDensity & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE (kg/m\\textasciicircum{}3)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~satelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt add non-gravitational forces in satellite reference frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~thermosphere & \\hfuzz=500pt \\hyperref[thermosphereType]{thermosphere} & \\hfuzz=500pt used to compute temperature and wind\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerTemperature & \\hfuzz=500pt boolean & \\hfuzz=500pt compute drag and lift, otherwise simple drag coefficient is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~considerWind & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentAccelerometerApplyEstimatedParameters}\\label{InstrumentAccelerometerApplyEstimatedParameters}\nThis program evaluates estimated satellite parameters and writes the result to an accelerometer file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt add non-gravitational forces in satellite reference frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameter & \\hfuzz=500pt filename & \\hfuzz=500pt estimated orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~indexStart & \\hfuzz=500pt int & \\hfuzz=500pt position in the solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rightSide & \\hfuzz=500pt int & \\hfuzz=500pt if solution contains several right hand sides, select one\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt the result is multiplied by this factor\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentAccelerometerEstimateBiasScale}\\label{InstrumentAccelerometerEstimateBiasScale}\nThis program calibrates \\configFile{inputfileAccelerometer}{instrument} with respect to\nsimulated accelerometer data, see \\program{SimulateAccelerometer}.\nThe parameters \\configFile{outputfileSolution}{matrix}\nof \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}\nare estimated and the effect is reduced to calibrate the \\file{accelerometer data}{instrument}.\n\nIf \\configFile{inputfileThruster}{instrument} is given, the corresponding epochs\n(within \\config{marginThruster}) are not used for the parameter estimation,\nbut the accelerometer epochs are still calibrated afterwards.\nAn arbitrary instrument file is allowed here.\n\nThe \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument},\n\\configClass{earthRotation}{earthRotationType}, \\configClass{ephemerides}{ephemeridesType},\nand \\configFile{satelliteModel}{satelliteModel} are only needed for some special parametrizations.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometerSim & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileThruster & \\hfuzz=500pt filename & \\hfuzz=500pt remove thruster events\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~marginThruster & \\hfuzz=500pt double & \\hfuzz=500pt margin size (on both sides) [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentAccelerometerEstimateParameters}\\label{InstrumentAccelerometerEstimateParameters}\nThis program estimates calibration parameters for acceleration data given given an optional reference acceleration.\nSpecifically, the program solves the equation\n\\begin{equation}\n  \\mathbf{a} - \\mathbf{a}_\\text{ref} = \\mathbf{f}(\\mathbf{x}) + \\mathbf{e}\n\\end{equation}\nfor the unknown parameters $\\mathbf{x}$, where $\\mathbf{a}$ is given in \\configFile{inputfileAccelerometer}{instrument} and\n$\\mathbf{a}_\\text{ref}$ is given in  \\configFile{inputfileAccelerometerReference}{instrument}.\nThe parametrization of $\\mathbf{x}$ can be set via \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}.\nOptionally, the empirical covariance functions for the accelerations $\\mathbf{a}$ can be estimated by enabling \\config{estimateCovarianceFunctions}.\n\nThe estimated parameters are written to the file \\configFile{outputfileSolution}{matrix} and can be used by\n\\program{InstrumentAccelerometerApplyEstimatedParameters} to calibrate accelerometer measurements.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt values for estimated parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt names of the estimated parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateArcSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileArcSigmas & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateEpochSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileEpochSigmas & \\hfuzz=500pt filename & \\hfuzz=500pt estimated epoch-wise sigmas\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateCovarianceFunctions & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions for x, y, z direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAccelerometerReference & \\hfuzz=500pt filename & \\hfuzz=500pt if not given, reference acceleration is assumed zero\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model (may be needed by parametrizationAcceleration)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaX & \\hfuzz=500pt double & \\hfuzz=500pt apriori accuracy in x-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaY & \\hfuzz=500pt double & \\hfuzz=500pt apriori accuracy in y-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigmaZ & \\hfuzz=500pt double & \\hfuzz=500pt apriori accuracy in z-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt iteration count for determining the covariance function\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentApplyTimeOffset}\\label{InstrumentApplyTimeOffset}\nThis program applies a \\configFile{inputfileTimeOffset}{instrument} (MISCVALUE)\nto an \\configFile{inputfileInstrument}{instrument}.\nThe time offsets in seconds are multiplicated with a \\config{factor}.\nThe instrument files must be synchronized (see \\program{InstrumentSynchronize}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTimeOffset & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE with time offset in seconds\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt applied to time offset\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentArcCalculate}\\label{InstrumentArcCalculate}\nThis program manipulates the data columns every arc of an \\file{instrument file}{instrument} similar to\n\\program{FunctionsCalculate}, see there for more details.\nIf several \\configFile{inputfileInstrument}{instrument}s are given the data columns are copied side by side.\nFor this the instrument files must be synchronized (see \\program{InstrumentSynchronize}). For the data\ncolumns the standard data variables are available, see~\\reference{dataVariables}{general.parser:dataVariables}.\nFor the time column (MJD) a variable \\verb|epoch| (together with \\verb|epochmean|, \\verb|epochmin|, \\ldots)\nis defined additionally.\n\nThe content of \\configFile{outputfileInstrument}{instrument} is controlled by \\config{outColumn}.\nThe number of \\config{outColumn} must agree with the selected \\configClass{outType}{instrumentTypeType}.\nThe algorithm to compute the output is as follows:\nThe expressions in \\config{outColumn} are evaluated once for each epoch of the input.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nIf no \\config{outColumn} are specified all input columns are used instead directly.\nThe \\configClass{instrument type}{instrumentTypeType} can be specified with \\config{outType} and must be agree with the number of columns.\n\nAn extra \\config{statistics} file can be generated with one mid epoch per arc. For the computation of the \\config{outColumn} values\nall~\\reference{dataVariables}{general.parser:dataVariables} are available (e.g. \\verb|epochmin|, \\verb|data0mean|, \\verb|data1std|, \\ldots)\ninclusively the \\config{constant}s and estimated \\config{parameter}s but without the \\verb|data0|,~\\verb|data1|,~\\ldots itself.\nThe variables and the numbering of the columns refers to the \\configFile{outputfileInstrument}{instrument}.\n\nSee also \\program{FunctionsCalculate}, \\program{MatrixCalculate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data columns are appended to the right\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~constant & \\hfuzz=500pt expression & \\hfuzz=500pt define a constant by name=value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameter & \\hfuzz=500pt expression & \\hfuzz=500pt define a parameter by name[=value]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~leastSquares & \\hfuzz=500pt expression & \\hfuzz=500pt try to minimize the expression by adjustment of the parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~removalCriteria & \\hfuzz=500pt expression & \\hfuzz=500pt row is removed if one criterion evaluates true.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outType & \\hfuzz=500pt \\hyperref[instrumentTypeType]{instrumentType} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outColumn & \\hfuzz=500pt expression & \\hfuzz=500pt expression of output columns, extra 'epoch' variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~statistics & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file with mid epoch per arc, data columns are user defined\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outColumn & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute statistics columns, data* are from outColumn\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentArcCrossStatistics}\\label{InstrumentArcCrossStatistics}\nComputes statistics of selected data columns between two \\file{instrument files}{instrument} arc wise.\nThe \\configFile{outputfileStatisticsTimeSeries}{instrument} contains for every arc one (mid) epoch\nwith statistics column(s). Possible statistics are\n\\begin{itemize}\n  \\item Correlation\n  \\begin{equation}\n    \\rho = \\frac{\\sum_i x_i y_i}{\\sqrt{(\\sum_i x_i^2) (\\sum_i y_i^2})},\n  \\end{equation}\n  \\item Error RMS\n  \\begin{equation}\n    rms = \\sqrt{\\frac{1}{N}\\sum_i (x_i-y_i)^2},\n  \\end{equation}\n  \\item Nash-Sutcliffe coefficient (NSC)\n  \\begin{equation}\n    nsc = 1- \\frac{\\sum_i (x_i-y_i)^2}{\\sum_i (y_i-\\bar{y})^2}.\n  \\end{equation}\n\\end{itemize}\nWith \\config{removeArcMean} the mean of each data column of each arc is reduced before.\n\nWith \\config{perColumn} separate statistics for each selected data column are computed,\notherwise an overall value is computed.\n\nSee also \\program{InstrumentArcStatistics}, \\program{InstrumentStatisticsTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStatisticsTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt statistics column(s) per arc, MISCVALUES\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrumentReference & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~statistics & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~correlation & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~errorRMS & \\hfuzz=500pt  & \\hfuzz=500pt rms of differences\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~nashSutcliffe & \\hfuzz=500pt  & \\hfuzz=500pt with respect to reference field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeArcMean & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perColumn & \\hfuzz=500pt boolean & \\hfuzz=500pt compute statistic per column\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentArcStatistics}\\label{InstrumentArcStatistics}\nComputes statistics of selected data columns of \\configFile{inputfileInstrument}{instrument} arc wise.\nThe \\configFile{outputfileStatisticsTimeSeries}{instrument} contains for every arc one (mid) epoch\nwith statistics column(s). Possible statistics are root mean square, standard deviation,\nmean, median, min, and max.\n\nWith \\config{perColumn} separate statistics for each selected data column are computed,\notherwise an overall value is computed.\n\nSee also \\program{InstrumentArcCrossStatistics}, \\program{InstrumentStatisticsTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStatisticsTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, statistics column(s) per instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~statistics & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rootMeanSquare & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~standardDeviation & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~mean & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~median & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~min & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~max & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~epochCount & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perColumn & \\hfuzz=500pt boolean & \\hfuzz=500pt compute statistic per column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ignoreNan & \\hfuzz=500pt boolean & \\hfuzz=500pt ignore NaN values in input\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentConcatenate}\\label{InstrumentConcatenate}\nThis program concatenate the arcs from several \\file{instrument files}{instrument}\nand write it to a new \\file{file}{instrument}. Input files must be of the same type.\nThe arcs are merged to one arc even though there is a gap inbetween.\nTo split the data into arcs use \\program{InstrumentSynchronize}.\nThree options are available: \\config{sort}, \\config{removeDuplicates} and \\config{checkForNaNs}.\nIf \\config{sort} is enabled, the program reads all files, no matter if they are sorted correctly in time, and\nthen sorts the epochs. If \\config{removeDuplicates} is enabled, the program checks the whole data set\nfor epochs that are contained twice. And if \\config{checkForNaNs} is enabled the data set is checked for\ninvalid epochs containing NaNs.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sort & \\hfuzz=500pt boolean & \\hfuzz=500pt sort epochs with increasing time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeDuplicates & \\hfuzz=500pt choice & \\hfuzz=500pt remove duplicate epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~keepFirst & \\hfuzz=500pt sequence & \\hfuzz=500pt keep first epoch with the same time stamp, remove all others\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin for identical times [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~keepLast & \\hfuzz=500pt sequence & \\hfuzz=500pt keep last epoch with the same time stamp, remove all others\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin for identical times [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~checkForNaNs & \\hfuzz=500pt boolean & \\hfuzz=500pt remove epochs with NaN values in one of the data fields\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentCovarianceCheck}\\label{InstrumentCovarianceCheck}\nThis program checks \\configFile{inputfileCovariance3d}{instrument}\n3x3 covariance matrices if they are invertible or not and removes the invalid epochs.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCovariance3d & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCovariance3d & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentDetrend}\\label{InstrumentDetrend}\nReduces \\configClass{parametrizationTemporal}{parametrizationTemporalType} (e.g. const, trend, polynomial)\nper arc from selected data columns of \\configFile{inputfileInstrument}{instrument}\nusing a robust \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\nThe \\configFile{outputfileTimeSeriesArcParameters}{instrument} contains for every arc one (mid) epoch\nwith the estimated parameters. The order is: first all data (\\verb|data0|, \\verb|data1|, \\ldots)\nof first temporal parameter, followed by all data of the second temporal parameter and so on.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt detrended instrument time series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTimeSeriesArcParameters & \\hfuzz=500pt filename & \\hfuzz=500pt time series of estimated parameters per arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt per arc, data is reduced by temporal representation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberMaxIteration & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for robust estimation\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentEarthRotation}\\label{InstrumentEarthRotation}\nPrecompute Earth rotation matrix from celestial to terrestrial frame\nand save as \\file{StarCamera file}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation from CRF to TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentEstimateEmpiricalCovariance}\\label{InstrumentEstimateEmpiricalCovariance}\nThis program estimates the empirical auto- and cross-covariance of selected data columns per arc\nof \\configFile{inputfileInstrument}{instrument}.\nThe maximum computed lag is determined by the number of \\configFile{outputfileCovarianceMatrix}{matrix} specified\n(for a single output file only the auto-covariance is determined, for two output files auto- and cross-covariance is computed and so on).\n\nStationarity is assumed for the input time series, which means the temporal covariance matrix has Toeplitz structure.\n\\begin{equation}\n\\begin{bmatrix}\n\\Sigma & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\Sigma_{\\Delta_3} & \\Sigma_{\\Delta_4} \\\\\n       & \\Sigma            & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\Sigma_{\\Delta_3} \\\\\n       &                   & \\Sigma            & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} \\\\\n       &                   &                   & \\Sigma            & \\Sigma_{\\Delta_1} \\\\\n       &                   &                   &                   & \\Sigma            \\\\\n\\end{bmatrix}\n\\end{equation}\n\nThe matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\Sigma(t-h, t)$.\n\nTo get a reliable estimate, \\program{InstrumentDetrend} should be called first.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfileCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentEstimateHelmertTransformation}\\label{InstrumentEstimateHelmertTransformation}\nThis program estimates a 3D Helmert transformation between two networks\n(frame realizations, e.g. GNSS satellite or station network).\nEach separate \\config{data} represents a satellite/station/\\ldots (e.g. 32 GPS satellites).\nThe instrument data (x,y,z position) considered can be set with \\config{startData}.\nThe Helmert parameters are set up according to \\configClass{parametrizationTemporal}{parametrizationTemporalType}\nfor each \\configClass{timeIntervals}{timeSeriesType} and are estimated using a\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileHelmertTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, Tx,Ty,Tz,s,Rx,Ry,Rz according to temporal parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~data & \\hfuzz=500pt sequence & \\hfuzz=500pt e.g. satellite, station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt transformed positions as instrument type Vector3d\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileInstrumentDiff & \\hfuzz=500pt filename & \\hfuzz=500pt position difference as instrument type Vector3d\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrumentReference & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start index of position (x,y,z) columns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeIntervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt parameters are estimated per interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt temporal parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateShift & \\hfuzz=500pt boolean & \\hfuzz=500pt coordinate center\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateScale & \\hfuzz=500pt boolean & \\hfuzz=500pt scale factor of position\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateRotation & \\hfuzz=500pt boolean & \\hfuzz=500pt rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huber & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberPower & \\hfuzz=500pt double & \\hfuzz=500pt for robust least squares\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~huberMaxIteration & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for robust estimation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentFilter}\\label{InstrumentFilter}\nThis program filter selected data columns of \\configFile{inputfileInstrument}{instrument}\nwith \\configClass{digitalFilter}{digitalFilterType} arc wise.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~digitalFilter & \\hfuzz=500pt \\hyperref[digitalFilterType]{digitalFilter} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentInsertNAN}\\label{InstrumentInsertNAN}\nThis program inserts NAN epochs into \\configFile{inputfileInstrument}{instrument} files,\neither at specific \\configClass{times}{timeSeriesType} or where gaps in the instrument are detected.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~times & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt Insert NAN at specific times.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~atGaps & \\hfuzz=500pt boolean & \\hfuzz=500pt Insert NAN where epochs are more than 1.5 times the median sampling apart.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~atArcEnds & \\hfuzz=500pt boolean & \\hfuzz=500pt Insert one epoch with data NAN at arc ends\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentMultiplyAdd}\\label{InstrumentMultiplyAdd}\nThis program multiply \\file{instrument data}{instrument} with a factor and add them together.\nAfterwards the mean of each arc and data column can be removed with \\config{removeArcMean}.\nThe instrument files must be synchronized (\\program{InstrumentSynchronize}).\n\nSee also \\program{InstrumentArcCalculate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~instrument & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeArcMean & \\hfuzz=500pt boolean & \\hfuzz=500pt remove mean value of each arc\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentReduceSampling}\\label{InstrumentReduceSampling}\nThis program reduce the sampling of a instrument file. Only epochs with a time stamp\nwith a division by \\config{sampling} without remainder are kept (inside \\config{margin}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt new sampling in seconds\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin around the new sampling in seconds\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~relative2FirstEpoch & \\hfuzz=500pt boolean & \\hfuzz=500pt compute sampling relative to time of first epoch\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentRemoveEpochsByCriteria}\\label{InstrumentRemoveEpochsByCriteria}\nThis program removes epochs from \\configFile{inputfileInstrument}{instrument}\nby evaluating a set of \\config{removalCriteria} expressions. For the data\ncolumns the standard data variables are available,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe instrument data can be reduced by data from \\configFile{inputfileInstrumentReference}{instrument}\nprior to evaluation of the expressions.\n\nTo reduce the data by its median, use an expression like \\verb|data1-data1mean|.\nTo remove epochs that deviate by more than 3 sigma use \\verb|abs(data1)>3*data1std|\nor \\verb|abs(data0-data0median)>3*1.4826*data0mad|.\n\nAll arcs in the input instrument file are concatenated, meaning expressions\nlike \\verb|data1mean| refer to the complete dataset. The removed epochs can be saved\nin a separate \\configFile{outputfileInstrumentRemovedEpochs}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt all data is stored in one arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrumentRemovedEpochs & \\hfuzz=500pt filename & \\hfuzz=500pt all data is stored in one arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt arcs are concatenated for processing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileInstrumentReference & \\hfuzz=500pt filename & \\hfuzz=500pt if given, the reference data is reduced prior to the expressions being evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~removalCriteria & \\hfuzz=500pt expression & \\hfuzz=500pt epochs are removed if one criterion evaluates true. data0 is the first data field.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt remove data around identified epochs (on both sides) [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentRemoveEpochsByTimes}\\label{InstrumentRemoveEpochsByTimes}\nThis program compares an \\file{instrument file}{instrument} with a\n\\configClass{time series}{timeSeriesType}.\nEpochs contained within the time series (including a defined margin)\nare removed from the instrument file. The margin is added on\nboth sides of the epochs. The arcs of the instrument file are\nconcatenated to one arc. The removed epochs can be saved\nin a separate instrument file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt all epochs are concatenated in one arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrumentRemovedEpochs & \\hfuzz=500pt filename & \\hfuzz=500pt all epochs are concatenated in one arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timePoints & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin size (on both sides) [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentRemoveEpochsThruster}\\label{InstrumentRemoveEpochsThruster}\nThis program remove epochs from an \\file{instrument file}{instrument}.\nThe epochs are defined by a \\file{thruster file}{instrument}\nplus a defined margin before and after the thruster firings.\nThe arcs of the instrument file are concatenated to one arc.\nThe removed epochs can be saved in a separate instrument file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt all epochs are concatenated in one arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileInstrumentRemovedEpochs & \\hfuzz=500pt filename & \\hfuzz=500pt all epochs are concatenated in one arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileThruster & \\hfuzz=500pt filename & \\hfuzz=500pt THRUSTER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~marginBefore & \\hfuzz=500pt double & \\hfuzz=500pt margin before start of firing [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~marginAfter & \\hfuzz=500pt double & \\hfuzz=500pt margin after end of firing [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentResample}\\label{InstrumentResample}\nThis program resamples \\file{instrument data}{instrument} to a given\n\\configClass{timeSeries}{timeSeriesType} using a resampling\n\\configClass{method}{interpolatorTimeSeriesType}.\n\nThis program can also be used to reduce the sampling of an instrument file,\nbut a better way to reduce the sampling of noisy data with regular sampling\nis to use a low pass filter first with \\program{InstrumentFilter} and then thin\nout the data with \\program{InstrumentReduceSampling}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~method & \\hfuzz=500pt \\hyperref[interpolatorTimeSeriesType]{interpolatorTimeSeries} & \\hfuzz=500pt resampling method\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt resampled points in time\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentRotate}\\label{InstrumentRotate}\nThis program rotates \\file{instrument data}{instrument} into a new reference frame\n(using \\configFile{inputfileStarCamera}{instrument}).\nThe rotation is usually done from satellite frame into inertial frame.\n\nTo apply Earth rotation to orbits use \\program{Orbit2EarthFixedOrbit}\nFor other instrument data use \\program{InstrumentEarthRotation} before.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseRotate & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentSetType}\\label{InstrumentSetType}\nConvert \\file{instrument data}{instrument} into instrument data with new \\configClass{type}{instrumentTypeType}.\nThe selected number of data columns must agree with the \\configClass{type}{instrumentTypeType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~type & \\hfuzz=500pt \\hyperref[instrumentTypeType]{instrumentType} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentStarCamera2AccAngularRate}\\label{InstrumentStarCamera2AccAngularRate}\nThis program derivate from a time series of quaternions\na series of angular rates and angular accelerations.\nThe derivatives are computed by a polynomial interpolation\nwith \\config{interpolationDegree} of the quaternions.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularRate & \\hfuzz=500pt filename & \\hfuzz=500pt [rad/s], VECTOR3D\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularAcc & \\hfuzz=500pt filename & \\hfuzz=500pt [rad/s**2], VECTOR3D\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt derivation by polynomial interpolation of degree n\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentStarCamera2RollPitchYaw}\\label{InstrumentStarCamera2RollPitchYaw}\nCompute roll, pitch, yaw angles from \\configFile{inputfileStarCamera}{instrument} data.\nOptional the angles are computed relative\nto a \\configFile{inputfileStarCameraReference}{instrument}.\n\nSee also \\program{SimulateStarCamera}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt roll, pitch, yaw [rad], VECTOR3D\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCameraReference & \\hfuzz=500pt filename & \\hfuzz=500pt nominal orientation\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentStarCamera2RotaryMatrix}\\label{InstrumentStarCamera2RotaryMatrix}\nWrite \\configFile{inputfileStarCamera}{instrument} rotations\nas \\configFile{outputfileInstrument}{instrument} rotary matrices\n(for each epoch $xx, xy, xz, yx, yy, yz, zx, zy, zz$).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt xx, xy, xz, yx, yy, yz, zx, zy, zz (MISCVALUES)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{InstrumentStarCameraMultiply}\\label{InstrumentStarCameraMultiply}\nThis program applies several rotations given by \\configFile{inputfileStarCamera}{instrument}.\nThe resulting rotation is written as \\configFile{outputfileStarCamera}{instrument}.\nAll instrument files must be synchronized (\\program{InstrumentSynchronize}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~instrument & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inverse & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentStatisticsTimeSeries}\\label{InstrumentStatisticsTimeSeries}\nThis program computes a time series of statistics for one or more instrument files.\nPossible statistics are root mean square, standard deviation, mean, median, min, and max.\nThe columns of the output time series are defined either as one per \\configFile{inputfileInstrument}{instrument}\nor, if \\config{perColumn} is true, statistics are computed per column for each file.\nProviding e.g. 32 orbit files of GPS satellites results in a time series matrix\nwith columns: mjd, statisticsG01, statisticsG02, ..., statisticsG32.\nIf \\config{intervals} are provided, the input data is split into these intervals\nand one statistic is computed per interval. Otherwise, overall statistics are computed.\nThe instrument data considered for computation of the component-wise statistics\ncan be set with \\config{startDataFields} and \\config{countDataFields}.\nThe \\config{factor} can be set to e.g. sqrt(3) to get 3D instead of 1D RMS values.\n\nSee also \\program{InstrumentArcStatistics}, \\program{InstrumentArcCrossStatistics}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStatisticsTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, statistics column(s) per instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~statistics & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rootMeanSquare & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~standardDeviation & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~mean & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~median & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sum & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~min & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~max & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~epochCount & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~perColumn & \\hfuzz=500pt boolean & \\hfuzz=500pt compute statistic per column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ignoreNan & \\hfuzz=500pt boolean & \\hfuzz=500pt ignore NaN values in statistic computation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~intervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt intervals for statistics computation (one statistic per interval)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt e.g. sqrt(3) for 3D RMS\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentSynchronize}\\label{InstrumentSynchronize}\nThis program reads several \\file{instrument files}{instrument} and synchronize the data.\nEvery epoch with some missing data will be deleted so the remaining epochs\nhave data from every instrument.\n\nIn a second step the epochs are divided into arcs with maximal epochs\n(or \\config{maxArcLen}) without having a gap inside an arc.\nA Gap is defined by a time step with at least \\config{minGap} seconds\nbetween consecutive epochs or if not set the 1.5 of the median sampling.\nArc with an epoch count less than \\config{minArcLen} will be rejected.\n\nA specific region can be selected with \\configClass{border}{borderType}.\nIn this case one of the instrument data must be an orbit.\n\nIf \\configClass{timeIntervals}{timeSeriesType} is given the data are also divided into time bins.\nThe assignment of arcs to the bins can be saved in \\configFile{outputfileArcList}{arcList}.\nThis file can be used for the variational equation approach or \\program{KalmanBuildNormals}.\n\nInstrument files from \\config{irregularData} are not synchronized but\ndivided into the same number of arcs within the same time intervals.\nData outside the defined arcs will be deleted.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~data & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt margin for identical times [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minGap & \\hfuzz=500pt double & \\hfuzz=500pt minimal time to define a gap and to begin a new arc, 0: no dividing [seconds], if not set 1.5*median sampling is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minArcLength & \\hfuzz=500pt uint & \\hfuzz=500pt minimal number of epochs of an arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxArcLength & \\hfuzz=500pt uint & \\hfuzz=500pt maximal number of epochs of an arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~arcType & \\hfuzz=500pt choice & \\hfuzz=500pt all arcs or only ascending or descending arcs are selected\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ascending & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~descending & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt only data in a specific region is selected\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeIntervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt divide data into time bins\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt arc and time bin mapping\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~irregularData & \\hfuzz=500pt sequence & \\hfuzz=500pt instrument files with irregular sampling\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~minArcLength & \\hfuzz=500pt uint & \\hfuzz=500pt minimal number of epochs in an arc\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{InstrumentWaveletDecomposition}\\label{InstrumentWaveletDecomposition}\nThis program performs a multilevel one-dimensional wavelet analysis on one \\config{selectDataField}\ndata column of \\configFile{inputfileInstrument}{instrument}.\nThe \\configFile{outputfileInstrument}{instrument} contains the decomposed levels in time domain ${a_J,d_J,...,d_1}$\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES, decomposed levels in time domain a\\_J,d\\_J,...,d\\_1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~selectDataField & \\hfuzz=500pt uint & \\hfuzz=500pt select a data column for decomposition\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileWavelet & \\hfuzz=500pt filename & \\hfuzz=500pt wavelet coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~level & \\hfuzz=500pt uint & \\hfuzz=500pt level of decomposition\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{LocalLevelFrame2StarCamera}\\label{LocalLevelFrame2StarCamera}\nCompute rotation (\\file{StarCamera file}{instrument}) from local level frame (ellipsoidal north, east, down)\nto TRF for positions given in \\configFile{inputfileInstrument}{instrument} (first 3 data columns).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation matrix from local level frame (ellipsoidal north, east, down) to TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt origin of local level frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~constantOriginPerArc & \\hfuzz=500pt boolean & \\hfuzz=500pt use constant origin for all epochs of an arc (median position)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: KalmanFilter}\n\\subsection{KalmanBuildNormals}\\label{KalmanBuildNormals}\nThis program sets up normal equations based on \\configClass{observation}{observationType}\nfor short-term gravity field variations.\nIt computes the normal equations based on the intervals $i \\in \\{1, ..., N\\}$ given in the \\configFile{arcList}{arcList}.\nIt sets up the least squares adjustment\n\\begin{equation}\n    \\begin{bmatrix}\n    \\mathbf{l}_1 \\\\\n    \\mathbf{l}_2 \\\\\n    \\vdots \\\\\n    \\mathbf{l}_N \\\\\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n    \\mathbf{A}_1  &  & & \\\\\n    & \\mathbf{A}_2  & &\\\\\n    &  & \\ddots & \\\\\n    & & & \\mathbf{A}_N \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{x}^{(1)} \\\\\n    \\mathbf{x}^{(2)} \\\\\n    \\vdots \\\\\n    \\mathbf{x}^{(N)} \\\\\n  \\end{bmatrix}\n  +\n  \\begin{bmatrix}\n    \\mathbf{e}_1 \\\\\n    \\mathbf{e}_2 \\\\\n    \\vdots \\\\\n    \\mathbf{e}_N \\\\\n  \\end{bmatrix},\n\\end{equation}\nand subsequently computes the normal equations $\\mathbf{N}_i, \\mathbf{n}_i$ for each interval.\nIf \\config{eliminateNonGravityParameters} is true, all non-gravity parameters are eliminated before the normals\nare written to \\configFile{outputfileNormalEquation}{normalEquation}.\nFor each time interval in \\config{arcList} a single \\file{normal equation file}{normalEquation} is written.\n\nThis program computes the input normals for \\program{KalmanFilter} and \\program{KalmanSmootherLeastSquares}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt outputfile for normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt \\hyperref[observationType]{observation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt list to correspond points of time to arc numbers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~eliminateNonGravityParameters & \\hfuzz=500pt boolean & \\hfuzz=500pt eliminate additional parameters from normals, 0: all parameter are saved\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{KalmanFilter}\\label{KalmanFilter}\nThe program computes time variable gravity fields using the Kalman filter approach of\n\nKurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012).\nImproved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.\n\\url{https://doi.org/10.1016/j.jog.2012.02.006}.\n\nThe updated state $\\mathbf{x}_t^+$ is determined by solving the least squares adjustment\n\\begin{equation}\n\\mathbf{l}_t = \\mathbf{A}_t \\mathbf{x}_t + \\mathbf{e}_t \\hspace{25pt} \\mathbf{e}_t \\sim \\mathcal{N}(0, \\mathbf{R}_t)\\\\\n\\mathbf{B} \\mathbf{x}^+_{t-1} = \\mathbf{I} \\mathbf{x}_t + \\mathbf{v}_t\\hspace{25pt} \\mathbf{v} \\sim \\mathcal{N}(0,\\mathbf{Q} + \\mathbf{B} \\mathbf{P}^+_{t-1}\\mathbf{B}^T).\n\\end{equation}\nIn normal equation form this can be written as\n\\begin{equation}\n\\hat{\\mathbf{x}}_t = \\mathbf{x}^+_t = (\\mathbf{N}_t + \\mathbf{P}^{-^{-1}}_t)^{-1}(\\mathbf{n}_t + \\mathbf{P}^{-^{-1}}_t \\mathbf{x}^-_t),\n\\end{equation}\nwhere $\\mathbf{x}_t^- = \\mathbf{B} \\mathbf{x}^+_{t-1}$ and $\\mathbf{P}_t^{-} = \\mathbf{Q} + \\mathbf{B} \\mathbf{P}^+_{t-1}\\mathbf{B}^T$\nare the predicted state and its covariance matrix.\n\nThe process dynamic $\\mathbf{B}, \\mathbf{Q}$ is represented as an \\reference{autoregressive model}{fundamentals.autoregressiveModel},\nand passed to the program through \\configFile{inputfileAutoregressiveModel}{matrix}.\nThe sequence of normal equations $\\mathbf{N}_t, \\mathbf{n}_t$ are given as list of \\configFile{inputfileNormalEquations}{normalEquation},\nwhich can be generated using \\configClass{loops}{loopType}.\nIn the same way, the \\file{matrix files}{matrix} for \\config{outputfileUpdatedState} and \\config{inputfileUpdatedStateCovariance}\ncan also be specified using \\configClass{loops}{loopType}.\n\nIf no \\configFile{inputfileInitialState}{matrix} is set, a zero vector with appropriate dimensions is used.\nThe \\configFile{inputfileInitialStateCovarianceMatrix}{matrix} however must be given.\n\nSee also \\program{KalmanBuildNormals}, \\program{KalmanSmoother}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfileUpdatedState & \\hfuzz=500pt filename & \\hfuzz=500pt estimated state x+ (nx1-matrix)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outputfileUpdatedStateCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt estimated state' s covariance matrix Cov(x+)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileNormalEquations & \\hfuzz=500pt filename & \\hfuzz=500pt normal equations input file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileInitialState & \\hfuzz=500pt filename & \\hfuzz=500pt initial state x0\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInitialStateCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt initial state's covariance matrix Cov(x0)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAutoregressiveModel & \\hfuzz=500pt filename & \\hfuzz=500pt file name of autoregressive model\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{KalmanSmoother}\\label{KalmanSmoother}\nApply the Rauch-Tung-Striebel smoother to a gravity field time series computed by \\program{KalmanFilter}.\nThis is the implementation of the approach presented in\n\nKurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012).\nImproved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.\n\\url{https://doi.org/10.1016/j.jog.2012.02.006}.\n\nThe result has zero phase and the squared magnitude response of \\configFile{inputfileAutoregressiveModel}{matrix}\n(see \\reference{autoregressiveModel}{fundamentals.autoregressiveModel} for details).\n\\configFile{inputfileUpdatedState}{matrix} and \\configFile{inputfileUpdatedStateCovariance}{matrix}\nare the output of a \\program{KalmanFilter} forward sweep.\nThe matrix files for\\configFile{outputfileUpdatedState}{matrix}, \\configFile{inputfileUpdatedState}{matrix}\nand \\configFile{inputfileUpdatedStateCovariance}{matrix} can also be specified using \\configClass{loops}{loopType}.\n\nSee also \\program{KalmanBuildNormals}, \\program{KalmanFilter} and \\program{KalmanSmootherLeastSquares}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfileState & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameters (nx1-matrix)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outputfileStateCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameters' covariance matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileUpdatedState & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileUpdatedStateCovarianceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAutoregressiveModel & \\hfuzz=500pt filename & \\hfuzz=500pt file name of autoregressive model\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{KalmanSmootherLeastSquares}\\label{KalmanSmootherLeastSquares}\nThis program estimates temporal gravity field variations with a constraint least squares adjustment.\nPrior information is introduced by means of a \\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType}\nwhich represent a stationary random process (see the \\reference{autoregressive model description}{fundamentals.autoregressiveModel}) for details.\n\nThe output files for the estimated gravity field (\\configFile{outputfileSolution}{matrix}), the\ncorresponding standard deviations (\\configFile{outputfileSigmax}{matrix}) and the full covariance matrix\n(\\configFile{outputfileCovariance}{matrix}) can be specified using \\configClass{loops}{loopType}.\nSimilarly, the \\configFile{inputfileNormalEquations}{normalEquation}\ncan also be specified using \\configClass{loops}{loopType}.\n\nSee also \\program{KalmanBuildNormals}, \\program{KalmanFilter} and\\program{KalmanSmoother}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt file name of solution vector (use time tags)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt file name of sigma vector (use time tags)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt file name of full covariance matrix (use time tags)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileNormalEquations & \\hfuzz=500pt filename & \\hfuzz=500pt input normal equations (loopTime will be expanded)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~autoregressiveModelSequence & \\hfuzz=500pt \\hyperref[autoregressiveModelSequenceType]{autoregressiveModelSequence} & \\hfuzz=500pt file containing AR model for spatiotemporal constraint\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: Misc}\n\\subsection{DigitalFilter2FrequencyResponse}\\label{DigitalFilter2FrequencyResponse}\nCompute amplitude-, phase-, group delay and frequency response of a \\configClass{digitalFilter}{digitalFilterType} cascade.\nThe \\configFile{outputfileResponse}{matrix} is a matrix with following columns:\nfreq $[Hz]$, ampl, phase $[rad]$, group delay $[-]$, real, imag.\n\nWhen \\config{unwrapPhase} is set to true, $2\\pi$ jumps of the phase response are removed before writing the output to file.\n\nThe response of the filter cascade is given by the product of each individual frequency response:\n\\begin{equation}\n  H(f) = \\prod_f H_j(f).\n\\end{equation}\nAmplitude and phase response are computed from the frequency response via\n\\begin{equation}\n  A(f) = |H(f)| \\hspace{5pt}\\text{and}\\hspace{5pt} \\Phi(f) = \\arctan \\frac{\\mathcal{I}(H(f))}{\\mathcal{R}(H(f))}.\n\\end{equation}\nThe group delay is computed by numerically differentiating the phase response\n\\begin{equation}\n  \\tau_g(f_k) = \\frac{1}{2} \\left[\\frac{\\Phi(f_k) - \\Phi(f_{k-1})}{2\\pi(f_k-f_{k-1})} + \\frac{\\Phi(f_{k+1}) - \\Phi(f_{k})}{2\\pi(f_{k+1}-f_{k})}\\right] \\approx \\frac{d\\Phi}{df}\\frac{df}{d\\omega}.\n\\end{equation}\nThe frequency vector for a \\config{length} $N$ and a \\config{sampling} $\\Delta t$ is given by\n\\begin{equation}\n  f_k = \\frac{k}{N \\Delta t}, \\hspace{15pt} k \\in \\{0, \\dots, \\left\\lfloor\\frac{N+2}{2}\\right\\rfloor-1\\}.\n\\end{equation}\n\nSee also \\program{DigitalFilter2ImpulseResponse}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileResponse & \\hfuzz=500pt filename & \\hfuzz=500pt columns: freq [Hz], ampl, phase [rad], group delay [-], real, imag\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~digitalFilter & \\hfuzz=500pt \\hyperref[digitalFilterType]{digitalFilter} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~length & \\hfuzz=500pt uint & \\hfuzz=500pt length of the data series in time domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt sampling to determine frequency [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~skipZeroFrequency & \\hfuzz=500pt boolean & \\hfuzz=500pt omit zero frequency when writing to file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~unwrapPhase & \\hfuzz=500pt boolean & \\hfuzz=500pt unwrap phase response\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DigitalFilter2ImpulseResponse}\\label{DigitalFilter2ImpulseResponse}\nImpulse response of a \\configClass{digitalFilter}{digitalFilterType} cascade.\nThe impulse response is computed by filtering a sequence with \\config{length} samples and a unit impulse at index \\config{pulseLag}.\n\nThe \\configFile{outputfileResponse}{matrix} is a matrix with the time stamp (zero at \\config{pulseLag})\nin the first column and the impulse response $h_k$ in the second column.\n\nSee also \\program{DigitalFilter2FrequencyResponse}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileResponse & \\hfuzz=500pt filename & \\hfuzz=500pt columns: time [seconds], response\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~digitalFilter & \\hfuzz=500pt \\hyperref[digitalFilterType]{digitalFilter} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~length & \\hfuzz=500pt uint & \\hfuzz=500pt length of the impulse response\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~pulseLag & \\hfuzz=500pt uint & \\hfuzz=500pt start of the pulse in the data series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds]\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{EarthOrientationParameterTimeSeries}\\label{EarthOrientationParameterTimeSeries}\nComputes a \\configClass{timeSeries}{timeSeriesType} (GPS time) of Earth Orientation Parameter (EOP).\nThe \\file{instrument file}{instrument} (MISCVALUES) contains the elements at each epoch in the following order:\n\\begin{itemize}\n\\item $x_p$ [rad]\n\\item $y_p$ [rad]\n\\item $s_p$ [rad]\n\\item $UT1-UTC$ [seconds]\n\\item length of day (LOD) [seconds]\n\\item $X$ [rad]\n\\item $Y$ [rad]\n\\item $S$ [rad]\n\\end{itemize}\nThe values are in situ values with all corrections and models applied. The time series can be used to\nprecompute Earth rotation with a low temporal resolution (e.g. 10 min) and reuse the file in\n\\configClass{earthRotation:file}{earthRotationType:file} to interpolate the data to the needed epochs\n(e.g. to rotate orbit data). As some Earth rotation models are quite slow this can accelerate the computation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt each row: mjd(GPS), xp, yp, sp, dUT1, LOD, X, Y, S\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{EarthRotaryVectorTimeSeries}\\label{EarthRotaryVectorTimeSeries}\nComputes a \\configFile{outputfileTimeSeries}{instrument} of Earth's rotary axis\nand its temporal derivative at \\configClass{timeSeries}{timeSeriesType} (GPS time).\nThe \\file{instrument file}{instrument} (MISCVALUES) contains the elements at each epoch in the following order:\n\\begin{itemize}\n\\item $\\omega_x [rad/s]$\n\\item $\\omega_y [rad/s]$\n\\item $\\omega_z [rad/s]$\n\\item $\\dot{\\omega}_x [rad/s^2]$\n\\item $\\dot{\\omega}_y [rad/s^2]$\n\\item $\\dot{\\omega}_z [rad/s^2]$.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt wx, wy, wz [rad], dwx, dwy, dwz [rad/s\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inTRF & \\hfuzz=500pt boolean & \\hfuzz=500pt terrestrial reference frame, otherwise celestial\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{EclipseFactor2GriddedData}\\label{EclipseFactor2GriddedData}\nThis program converts the output of a \\configClass{eclipse}{eclipseType} model on a given\n\\configClass{grid}{gridType}. The time for the evaluation can be specified in \\config{time}.\nThe values will be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R}\nand \\config{inverseFlattening}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt eclipse factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{FilterMatrixWindowedPotentialCoefficients}\\label{FilterMatrixWindowedPotentialCoefficients}\nCreate a spherical harmonic window matrix. The window matrix $\\mathbf{W}$ is generated in space domain through\nspherical harmonic synthesis and analysis matrices.\nThe resulting linear operator can be written as\n\\begin{equation}\n\\mathbf{W} = \\mathbf{K} \\mathbf{A} \\mathbf{\\Omega} \\mathbf{S} \\mathbf{K}^{-1}.\n\\end{equation}\nHere, $\\mathbf{K}$ is a diagonal matrix with the \\configClass{kernel}{kernelType} coefficients on the main diagonal,\n$\\mathbf{S}$ is the spherical harmonic synthesis matrix, $\\mathbf{\\Omega}$ is defined by the values in\n\\file{inputfileGriddedData}{griddedData} and the\nexpression \\config{value}, $\\mathbf{A}$ is the spherical harmonic analysis matrix.\nThe resulting window matrix is written to a \\file{matrix}{matrix} file.\n\nThe spherical harmonic degree range, and coefficient numbering are defined by\n\\config{minDegree}, \\config{maxDegree}, and \\configClass{numbering}{sphericalHarmonicsNumberingType}.\n\nNote that a proper window function $\\mathbf{\\Omega}$ should contain values in the range [0, 1].\nThe window function $\\mathbf{\\Omega}$ can feature a smooth transition between 0 and 1 to avoid ringing effects.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileWindowMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt gridded data which defines the window function in space domain\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute the window function (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt kernel for windowing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme for solution vector\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{FunctionsCalculate}\\label{FunctionsCalculate}\nThis program manipulates \\file{matrix files}{matrix} with data in columns.\nIf several \\config{inputfile}s are given the data columns are copied side by side.\nAll \\config{inputfile}s must contain the same number of rows.\nThe columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots.\n\nThe content of \\configFile{outputfile}{matrix} is controlled by \\config{outColumn}.\nThe algorithm to compute the output is as follows:\nThe expressions in \\config{outColumn} are evaluated once for each row of the input.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nAdditional variables are available, e.g. \\verb|index|, \\verb|data0rms|, see~\\reference{dataVariables}{general.parser:dataVariables}.\nIf no \\config{outColumn} are specified all input columns are used instead directly.\n\nFor a simplified handling \\config{constant}s can be defined by \\verb|name=value|, e.g. \\verb|annual=365.25|.\nIt is also possible to estimate \\config{parameter}s in a least squares adjustment.\nThe \\config{leastSquares} serves as template for observation equations for every row.\nThe expression \\config{leastSquares} is evaluated for each row in the \\config{inputfile}.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nIn the next step the parameters are estimated in order to minimize the expressions in \\config{leastSquares}\nin the sense of least squares.\n\nAfterwards complete rows are removed if one of the \\config{removalCriteria} expressions for this row evaluates true (not zero).\n\nAn extra \\config{statistics} file can be generated with one row of data. For the computation of the \\config{outColumn} values\nall~\\reference{dataVariables}{general.parser:dataVariables} are available (e.g. \\verb|data3mean|, \\verb|data4std|)\ninclusively the \\config{constant}s and estimated \\config{parameter}s but without the \\verb|data0|,~\\verb|data1|,~\\ldots itself.\nThe variables and the numbering of the columns refers to the \\configFile{outputfile}{matrix}.\n\nFirst example: To calculate the mean of two values at each row set \\config{outColumn} to \\verb|0.5*(data1+data0)|.\n\nSecond example: An input file contain a column with times and a column with values.\nTo remove a trend from the values define the \\config{parameter}s \\verb|trend| and \\verb|bias|.\nThe observation equation in \\config{leastSquares} is \\verb|data1 - (trend*data0+bias)|.\nFor output you can define the following columns for example:\n\\begin{itemize}\n\\item \\config{outColumn}=\\verb|data0|: points in time.\n\\item \\config{outColumn}=\\verb|data1|: the values itself.\n\\item \\config{outColumn}=\\verb|trend*data0+bias|: the linear fit.\n\\item \\config{outColumn}=\\verb|data1-trend*data0-bias|: the residuals.\n\\end{itemize}\nThe extra statistics file could contain in this case:\n\\begin{itemize}\n\\item \\config{outColumn}=\\verb|data0max-data0min|: time span.\n\\item \\config{outColumn}=\\verb|bias|: estimated parameter.\n\\item \\config{outColumn}=\\verb|trend|: estimated parameter.\n\\item \\config{outColumn}=\\verb|data3rms|: root mean square of the residuals.\n\\end{itemize}\n\nSee also \\program{InstrumentArcCalculate}, \\program{GriddedDataCalculate}, \\program{MatrixCalculate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~constant & \\hfuzz=500pt expression & \\hfuzz=500pt define a constant by name=value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameter & \\hfuzz=500pt expression & \\hfuzz=500pt define a parameter by name[=value]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~leastSquares & \\hfuzz=500pt expression & \\hfuzz=500pt try to minimize the expression by adjustment of the parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~removalCriteria & \\hfuzz=500pt expression & \\hfuzz=500pt row is removed if one criterion evaluates true.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~outColumn & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute output columns (input columns are named data0, data1, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~statistics & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with one row, columns are user defined\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~outColumn & \\hfuzz=500pt expression & \\hfuzz=500pt expression to compute statistics columns, data* are the outputColumns\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Grs2PotentialCoefficients}\\label{Grs2PotentialCoefficients}\nThis program creates potential coefficients from the defining constants\nof a Geodetic Reference System (GRS). The potential coeffiencts excludes the centrifugal part.\nThe form of the reference ellipsoid is either determined by the dynamical form factor \\config{J2},\nor the geometric \\config{inverseFlattening}. One of those form parameters must be specified.\n\nThe default values create the GRS80.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~omega & \\hfuzz=500pt double & \\hfuzz=500pt Angular velocity of rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~J2 & \\hfuzz=500pt double & \\hfuzz=500pt Dynamical form factor\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt Geometric inverse flattening of reference ellipsoid (0: sphere, ignored when J2 is set)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Kaula2SigmaPotentialCoefficients}\\label{Kaula2SigmaPotentialCoefficients}\nCreate signal standard deviations of potential coefficients according Kaula's rule of thumb\n\\begin{equation}\n  \\sigma_n = \\frac{f}{n^p},\n\\end{equation}\nwith the degree $n$, the \\config{factor} $f$, and the \\config{power} $p$.\n\nThe standard deviations are written as formal errors of\n \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~power & \\hfuzz=500pt double & \\hfuzz=500pt sigma = factor/degree\\textasciicircum{}power\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt sigma = factor/degree\\textasciicircum{}power\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Kernel2Coefficients}\\label{Kernel2Coefficients}\nThis program computes and returns the coefficients and inverse coefficients of a \\configClass{kernel}{kernelType}\nfrom from \\config{minDegree} to \\config{maxDegree} at a given \\config{height}.\n\nThe main purpose is for visualization with \\program{PlotGraph}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with columns degree, coefficients and inverse coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt minimum degree of returned coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegre & \\hfuzz=500pt uint & \\hfuzz=500pt compute coefficients up to maxDegree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt evaluate kernel at R+height [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Kernel2SigmaPotentialCoefficients}\\label{Kernel2SigmaPotentialCoefficients}\nCreate variances of spherical harmonics by convolution a kernel with white noise,\ne.g. to display filter coefficients of a Gaussian filter.\nThe coefficients are written as formal errors of \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{KernelEvaluate}\\label{KernelEvaluate}\nCompute \\configClass{kernel}{kernelType} values for distant angles.\nThe main purpose is for visualization with \\program{PlotGraph}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with first column the angle [degree], second the kernel value\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minAngle & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxAngle & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt evaluate at R+height [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{MagneticField2GriddedData}\\label{MagneticField2GriddedData}\nComputes x, y, z of the magentic field vector.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt x, y, z [Tesla = kg/A/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~magnetosphere & \\hfuzz=500pt \\hyperref[magnetosphereType]{magnetosphere} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~localReferenceFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt local left handed reference frame (north, east, up)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{MatrixCalculate}\\label{MatrixCalculate}\nThis program creates a \\file{matrix}{matrix} from multiple matrices.\nAll \\configClass{matrices}{matrixGeneratorType} are summed up. The size of the resulting matrix is exandeded to fit all matrices.\nThe class \\configClass{matrixGenerator}{matrixGeneratorType} allows complex matrix operations before.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~matrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ObservationEquations2Files}\\label{ObservationEquations2Files}\nThis program computes the linearized and decorrelated equation system for each arc $i$:\n\\begin{equation}\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i\n\\end{equation}\nusing class \\configClass{observation}{observationType} and writes $\\M A_i$, $\\M B_i$ and $\\M l_i$ as \\file{matrix}{matrix} files.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileObservationVector & \\hfuzz=500pt filename & \\hfuzz=500pt one file for each arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileDesignMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt one file for each arc, without arc related parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileDesignMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt one file for each arc, arc related parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableArc & \\hfuzz=500pt string & \\hfuzz=500pt variable with arc number\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt without arc related parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt \\hyperref[observationType]{observation} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PlatformCreate}\\label{PlatformCreate}\nCreate a \\file{Platform file}{platform} from scratch by defining attributes such as\n\\config{markerName}, \\config{markerNumber}, \\config{comment}, \\config{approxPosition},\n\\config{equipment}.\n\nSee also \\program{GnssAntex2AntennaDefinition} and \\program{GnssStationLog2Platform}.\n\n\\fig{!hb}{0.8}{fileFormatPlatform}{fig:platformCreate}{Platform for stations, LEOs, and GNSS satellites.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePlatform & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~markerName & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~markerNumber & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approxPositionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] in TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approxPositionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] in TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approxPositionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] in TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~equipment & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gnssAntenna & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] ARP in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] ARP in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] ARP in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationX & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to left-handed antenna system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationY & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to left-handed antenna system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationZ & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to left-handed antenna system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipX & \\hfuzz=500pt boolean & \\hfuzz=500pt flip x-axis (after rotation)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipY & \\hfuzz=500pt boolean & \\hfuzz=500pt flip y-axis (after rotation)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipZ & \\hfuzz=500pt boolean & \\hfuzz=500pt flip z-axis (after rotation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~gnssReceiver & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~version & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~laserRetroReflector & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt e.g. GFZ, ITE, IPIE\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] optial reference point RP in satellite system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] optial reference point RP in satellite system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] optial reference point RP in satellite system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationX & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to LRR system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationY & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to LRR system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationZ & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to LRR system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipX & \\hfuzz=500pt boolean & \\hfuzz=500pt flip x-axis (after rotation)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipY & \\hfuzz=500pt boolean & \\hfuzz=500pt flip y-axis (after rotation)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipZ & \\hfuzz=500pt boolean & \\hfuzz=500pt flip z-axis (after rotation)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~range & \\hfuzz=500pt double & \\hfuzz=500pt [m] range bias (only without range matrix)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileRangeMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt [m] (azimuth(0..360) x zenith(0..dZenit*rows)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~dZenit & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] increment of range matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~geodeticSatellite & \\hfuzz=500pt sequence & \\hfuzz=500pt e.g. LAGEOS\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt double & \\hfuzz=500pt [m] standard center-of-mass correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~slrStation & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt CDP SOD 8-digit No.\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt IERS DOMES\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] eccentricity in north\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] eccentricity in east\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] eccentricity in up\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~satelliteIdentifier & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~cospar & \\hfuzz=500pt string & \\hfuzz=500pt Satellite COSPAR ID\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~norad & \\hfuzz=500pt string & \\hfuzz=500pt Satellite Catalog (NORAD) Number\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sic & \\hfuzz=500pt string & \\hfuzz=500pt SIC Code\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sp3 & \\hfuzz=500pt string & \\hfuzz=500pt SP3\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~other & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~positionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~referencePoint & \\hfuzz=500pt sequence & \\hfuzz=500pt e.g. center of mass in satellite frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~xStart & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~yStart & \\hfuzz=500pt double & \\hfuzz=500pt linear motion between start and end\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zStart & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~xEnd & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~yEnd & \\hfuzz=500pt double & \\hfuzz=500pt linear motion between start and end\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zEnd & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PotentialCoefficients2BlockMeanTimeSplines}\\label{PotentialCoefficients2BlockMeanTimeSplines}\nThis program is a simplified version of \\program{Gravityfield2TimeSplines}.\nIt reads a series of potential coefficient files (\\configFile{inputfilePotentialCoefficients}{potentialCoefficients})\nand creates a time splines file with spline degree 0 (temporal block means) or degree 1 (linear splines).\nThe time intervals in which the potential coefficients are valid are defined between adjacent\npoints in time given by \\config{splineTimeSeries}. Therefore one more point in time is needed\nthan the number of potential coefficient files for degree 0.\n\nThe coefficients can be filtered with \\configClass{filter}{sphericalHarmonicsFilterType}.\nIf set the expansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nThis program is useful e.g. to combine monthly GRACE solutions to one file.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSplines & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTimeSplinesCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt only the variances are saved\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~filter & \\hfuzz=500pt \\hyperref[sphericalHarmonicsFilterType]{sphericalHarmonicsFilter} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeMean & \\hfuzz=500pt boolean & \\hfuzz=500pt remove the temporal mean of the series before estimating the splines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolate & \\hfuzz=500pt boolean & \\hfuzz=500pt interpolate missing files\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~splineTimeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt input files must be between points in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~splineDegree & \\hfuzz=500pt uint & \\hfuzz=500pt degree of splines\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PotentialCoefficients2DegreeAmplitudes}\\label{PotentialCoefficients2DegreeAmplitudes}\nThis program computes degree amplitudes from\n\\file{potentialCoefficients files}{potentialCoefficients}\nand saves them to a \\file{matrix}{matrix} file.\n\nThe coefficients can be filtered with \\configClass{filter}{sphericalHarmonicsFilterType} and converted\nto different functionals with \\configClass{kernel}{kernelType}. The gravity field can be evaluated at\ndifferent altitudes by specifying \\config{evaluationRadius}. Polar regions can be excluded\nby setting \\config{polarGap}. If set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThe \\configFile{outputfileMatrix}{matrix} contains in the first 3 columns the degree, the degree amplitude, and\nthe formal errors. For each additional \\configFile{inputfilePotentialCoefficients}{potentialCoefficients} three columns\nare appended: the degree amplitude, the formal errors, and the difference to the first file.\n\nFor example the data columns for 4 \\configFile{inputfilePotentialCoefficients}{potentialCoefficients} are\n\\begin{itemize}\n\\item degree=\\verb|data0|\n\\item PotentialCoefficients0: signal=\\verb|data1|, error=\\verb|data2|,\n\\item PotentialCoefficients1: signal=\\verb|data3|, error=\\verb|data4|,  difference=\\verb|data5|,\n\\item PotentialCoefficients2: signal=\\verb|data6|, error=\\verb|data7|,  difference=\\verb|data8|,\n\\item PotentialCoefficients3: signal=\\verb|data9|, error=\\verb|data10|, difference=\\verb|data11|.\n\\end{itemize}\n\nSee also \\program{Gravityfield2DegreeAmplitudes}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt matrix with degree, signal amplitude, formal error, differences\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~filter & \\hfuzz=500pt \\hyperref[sphericalHarmonicsFilterType]{sphericalHarmonicsFilter} & \\hfuzz=500pt filter the coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt type of variances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rms & \\hfuzz=500pt  & \\hfuzz=500pt degree amplitudes (square root of degree variances)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~accumulation & \\hfuzz=500pt  & \\hfuzz=500pt cumulate variances over degrees\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~evaluationRadius & \\hfuzz=500pt double & \\hfuzz=500pt evaluate the gravity field at this radius (default: evaluate at surface\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~polarGap & \\hfuzz=500pt angle & \\hfuzz=500pt exclude polar regions (aperture angle in degrees)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{RadialBasisSplines2KernelCoefficients}\\label{RadialBasisSplines2KernelCoefficients}\nThis program calculates the coefficients $k_n$ of a \\configClass{kernel:coefficients}{kernelType:coefficients} according to\n\\begin{equation}\n  k_n = \\frac{GM}{4\\pi R}\\frac{\\sigma_n}{\\sqrt{2n+1}}.\n\\end{equation}\nfrom a given \\configClass{gravityfield}{gravityfieldType},\nwith \\config{R} and \\config{GM} describing the reference radius and the geocentric constant, respectively.\nThe $\\sigma_n$\nstand for the gravity field accuracies (from degree \\config{minDegree} to \\config{maxDegree}), if they are given.\nIf no accuracies are provided, the $\\sigma_n$\nrepresent the square root of the degree variances of the gravity field.\nIf \\config{maxDegree} exceeds the maximum degree given by \\configClass{gravityfield}{gravityfieldType},\nthe higher degrees are complemented by Kaula's rule\nThe output of the coefficients is given in the file  \\configFile{outputfileCoefficients}{matrix}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~kaulaPower & \\hfuzz=500pt double & \\hfuzz=500pt sigma = kaulaFactor/degree\\textasciicircum{}kaulaPower\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~kaulaFactor & \\hfuzz=500pt double & \\hfuzz=500pt sigma = kaulaFactor/degree\\textasciicircum{}kaulaPower\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SatelliteModelCreate}\\label{SatelliteModelCreate}\nThis program creates a satellite macro model for the estimation of non-gravitational accelerations acting on a satellite.\nMandatory input values are the \\config{satelliteName}, \\config{mass}, \\config{coefficientDrag} and information\nabout the satellite \\config{surfaces}. For low Earth orbiting satellites, like GRACE for instance, a good guess\nfor the drag coefficient could be 2.3. Apart from that, it is latter on possible to estimate a more precise variable drag coefficient\n(e.g. \\configClass{miscAccelerations:atmosphericDrag}{miscAccelerationsType:atmosphericDrag}), which will override this initial guess.\nConcerning the satellite surfaces an external file must be imported which must contain information about each single\n satellite plate in terms of plate \\config{area}, the associated plate normal and re-radiation properties\n(reflexion, diffusion and absorption) properties in the visible and IR part. Examplarily, a description of\nthe macro model for GRACE can be found under:\n\\url{https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf}\nAdditionally, it is possible to add further information like antennaThrust, solar panel, temporal mass changes and\nmassInstrument using the modules option.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~satellite & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~satelliteName & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~mass & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~coefficientDrag & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~surfaces & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt each line must contain one surface element\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt expression & \\hfuzz=500pt 0: plate, 1: sphere, 2: cylinder\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~area & \\hfuzz=500pt expression & \\hfuzz=500pt [m\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~normalX & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~normalY & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~normalZ & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~reflexionVisible & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~diffusionVisible & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~absorptionVisible & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~reflexionInfrared & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~diffusionInfrared & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~absorptionInfrared & \\hfuzz=500pt expression & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~specificHeatCapacity & \\hfuzz=500pt expression & \\hfuzz=500pt 0: no thermal radiation, -1: direct reemission [Ws/K/m\\textasciicircum{}2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~module & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~antennaThrust & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~thrustX & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~thrustY & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~thrustZ & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~solarPanel & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationAxisX & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationAxisY & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationAxisZ & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~normalX & \\hfuzz=500pt double & \\hfuzz=500pt Direction to sun\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~normalY & \\hfuzz=500pt double & \\hfuzz=500pt Direction to sun\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~normalZ & \\hfuzz=500pt double & \\hfuzz=500pt Direction to sun\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~indexSurface & \\hfuzz=500pt uint & \\hfuzz=500pt index of solar panel surfaces\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~massChange & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~mass & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~massInstrument & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SynthesisSphericalHarmonicsMatrix}\\label{SynthesisSphericalHarmonicsMatrix}\nThis program builds a linear operator matrix for spherical harmonic analysis or synthesis based on\nthe points defined in \\configClass{grid}{gridType}. Depending on the chosen\n\\config{type} (synthesis, quadrature, or leastSquares), the resulting matrix can be used to:\n\\begin{itemize}\n  \\item \\textbf{synthesis}: Map spherical harmonic coefficients to values on a grid,\n  \\item \\textbf{quadrature}: Integrate grid-based functionals into spherical harmonic coefficients by\n        a simple quadrature formula,\n  \\item \\textbf{leastSquares}: Estimate coefficients from grid data via a least squares approach.\n\\end{itemize}\n\nhe spherical harmonic degree range is constrained by\n\\config{minDegree} and \\config{maxDegree}, and the ordering of the coefficients is given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}. The reference gravitational\nconstant is \\config{GM}, and the reference radius is \\config{R}.\n\nThe computed matrix is written to \\configFile{outputfileMatrix}{matrix} with dimensions\n(number of grid points)~$\\times$~(number of spherical harmonic coefficients). For\n\\config{type} = \\emph{leastSquares}, the program applies a QR-based pseudo-inverse so that the\noutput matrix can directly form the normal-equation building blocks for a blockwise\nleast-squares solution in spherical harmonic space.\n\nSee also \\program{Gravityfield2GriddedData}, \\program{GriddedData2PotentialCoefficients},\n\\program{Gravityfield2SphericalHarmonicsVector}, and \\program{MatrixCalculate} for additional\ntools to convert between grids and spherical harmonics.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme of sh coefficients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~synthesis & \\hfuzz=500pt  & \\hfuzz=500pt synthesize spherical harmonics on a grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~quadrature & \\hfuzz=500pt  & \\hfuzz=500pt calculate spherical harmonics from grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~leastSquares & \\hfuzz=500pt  & \\hfuzz=500pt estimated spherical harmonics from grid\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{TemporalRepresentation2TimeSeries}\\label{TemporalRepresentation2TimeSeries}\nThis program computes the design matrix of temporal representation at a given time series.\nThe output matrix contains the time steps in MJD in the first column, the other columns contain the design matrix.\nThe intention of this program is to visualize the parametrization together with \\program{PlotGraph}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt Time (MJD) in first column, design matrix follows\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~temporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ThermosphericState2GriddedData}\\label{ThermosphericState2GriddedData}\nThis program converts the output (neutral mass density,temperature) of an empirical thermosphere model (e.g. JB2008) on a given \\configClass{grid}{gridType}.\nAdditionally, also the thermospheric winds estimated by using the horizontal wind model HWM 2014 can be assessed.\nThe time for the evaluation can be specified in \\config{time}. The values will be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\\fig{!hb}{1.0}{thermosphericState2GriddedData}{fig:thermosphericState2GriddedData}{JB2008 model in 300 km height at 2003-07-01 12:00.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt density [kg/m**3], temperature [K], wind (x, y, z) [m/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~thermosphere & \\hfuzz=500pt \\hyperref[thermosphereType]{thermosphere} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~localReferenceFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt wind in local north, east, up, otherwise global terrestrial\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{TimeSeries2PotentialCoefficients}\\label{TimeSeries2PotentialCoefficients}\nInterpret the data columns of \\configFile{inputfileTimeSeries}{instrument}\nas potential coefficients. The sequence of coefficients is given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType} starting from data column \\config{startDataFields}.\n\nFor each epoch a \\configFile{outputfilesPotentialCoefficients}{potentialCoefficients}\nis written where the \\config{variableLoopTime} and \\config{variableLoopIndex} are expanded for\neach point of the given time series to create the file name for this epoch,\nsee \\reference{text parser}{general.parser:text}.\n\nSee also \\program{Gravityfield2PotentialCoefficientsTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilesPotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopTime & \\hfuzz=500pt string & \\hfuzz=500pt variable with time of each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopIndex & \\hfuzz=500pt string & \\hfuzz=500pt variable with index of current epoch (starts with zero)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopCount & \\hfuzz=500pt string & \\hfuzz=500pt variable with total number of epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt each epoch: multiple data for points (MISCVALUES)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt first data column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt minimal degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt maximal degree\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{TimeSeriesCreate}\\label{TimeSeriesCreate}\nThis program generates an \\file{instrument file}{instrument},\ncontaining a time series.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt time series to be created\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~data & \\hfuzz=500pt expression & \\hfuzz=500pt expression of output columns, extra 'epoch' variable\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Variational2OrbitAndStarCamera}\\label{Variational2OrbitAndStarCamera}\nExtracts the reference \\configFile{outputfileOrbit}{instrument}, \\configFile{outputfileStarCamera}{instrument},\nand \\configFile{outputfileEarthRotation}{instrument} from \\configFile{inputfileVariational}{variationalEquation}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt output orbit (instrument) file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt output satellite attidude as star camera (instrument) file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileEarthRotation & \\hfuzz=500pt filename & \\hfuzz=500pt output Earth rotation as star camera (instrument) file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt input variational file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: NormalEquation}\n\\subsection{NormalsAccumulate}\\label{NormalsAccumulate}\nThis program accumulates normal equations and writes the total combined system to\n\\configFile{outputfileNormalequation}{normalEquation}.\nThe \\configFile{inputfileNormalEquation}{normalEquation}s must have all the same size and the same block structure.\n\nThis program is the simplified and fast version of the more general program \\program{NormalsBuild}.\nFor input normals with different parameters, see \\program{NormalsReorderAndAccumulate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NormalsBuild}\\label{NormalsBuild}\nThis program accumulates \\configClass{normalEquation}{normalEquationType}s and\nwrites the total combined system to \\configFile{outputfileNormalequation}{normalEquation}.\nFor a detailed description of the used algorithm see \\configClass{normalEquation}{normalEquationType}.\nLarge normal equation systems can be divided into blocks with \\config{normalsBlockSize}.\n\nA simplifed and fast version of this program is \\program{NormalsAccumulate}.\nFor input normals with different parameters see \\program{NormalsReorderAndAccumulate}.\nTo solve the system of normal equations use \\program{NormalsSolverVCE}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~normalEquation & \\hfuzz=500pt \\hyperref[normalEquationType]{normalEquation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~normalsBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsBuildShortTimeStaticLongTime}\\label{NormalsBuildShortTimeStaticLongTime}\nThis program sets up normal equations based on \\configClass{observation}{observationType}.\nAdditionally short time and long time variations can be parametrized based on the static parameters\nin \\configClass{observation}{observationType} in an efficient way. The observation equations\nare divided into time intervals $i \\in \\{1, ..., N\\}$ (e.g. daily) as defined in\n\\configFile{inputfileArcList}{arcList}.\n\nWith \\config{estimateLongTimeVariations} additional temporal variations can be co-estimated\nfor a subset of the parameters selected by \\configClass{parameterSelection}{parameterSelectorType}.\nThese parameters might be spherical harmonic coefficients with a limited maximum degree.\nThe temporal variations are represented by base functions $\\Phi_k(t_i)$ (e.g. trend and annual oscillation)\ngiven by \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nThe temporal base functions are evaluated at the mid time~$t_i$ of each interval~$i$, multiplicated\nwith the design matrix $\\M A_i$ of the selected parameters, and the design matrix is extended\naccordingly.\n\n\\fig{!hb}{0.8}{normalsBuildShortTimeStaticLongTime}{fig:normalsBuildShortTimeStaticLongTime}{Schema of the extended design matrix.}\n\nWith \\config{estimateShortTimeVariations} short time variations of the gravity field can be co-estimated.\nTheir purpose is to mitigate temporal aliasing.\nThe short time parameters selected by \\configClass{parameterSelection}{parameterSelectorType}\n(e.g. daily constant or linear splines every 6 hour) are constrained by an\n\\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType}. If only a static parameter\nset is selected the coressponding part of the design matrix is copied and modeled as a constant value\nper interval in \\configFile{inputfileArcList}{arcList} additionally so the corresponding temporal factor can be expressed as\n\\begin{equation}\n  \\Phi_i(t)  =\n  \\begin{cases}\n    1 &\\text{if} \\hspace{5pt} t \\in [t_i, t_{i+1}) \\\\\n    0 & \\text{otherwise}\n  \\end{cases}.\n\\end{equation}\n\nBefore writing the normal equations to \\configFile{outputfileNormalEquation}{normalEquation}\nshort time gravity and satellite specific parameters can be eliminated with \\config{eliminateParameter}.\n\nExample: For the computation of the mean gravity field ITSG-Grace2018s with additional trend and annual signal\nthe normal equations are computed month by month and accumulated afterwards (see \\program{NormalsAccumulate}).\nThe observations were divided into daily intervals with \\configFile{inputfileArcList}{arcList}.\nThe static gravity field has been parametrized as spherical harmonics\nup to degree $n=200$ in \\configClass{observation:parametrizationGravity}{parametrizationGravityType}.\nThe trend and annual signals defined by\n\\configClass{estimateLongTimeVariations:parametrizationTemporal}{parametrizationTemporalType}\nwere estimated for selected parameters up to degree $n=120$.\nTo mitigate temporal aliasing daily gravity fields up to degree $n=40$ were setup and constrained\nwith an \\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType} up to order three.\n\nA detailed description of the approach is given in:\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). \\url{https://doi.org/10.1007/s00190-019-01314-1}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt outputfile for normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt \\hyperref[observationType]{observation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateShortTimeVariations & \\hfuzz=500pt sequence & \\hfuzz=500pt co-estimate short time gravity field variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~autoregressiveModelSequence & \\hfuzz=500pt \\hyperref[autoregressiveModelSequenceType]{autoregressiveModelSequence} & \\hfuzz=500pt AR model sequence for constraining short time gravity variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameters describing the short time gravity field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateLongTimeVariations & \\hfuzz=500pt sequence & \\hfuzz=500pt co-estimate long time gravity field variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt parametrization of time variations (trend, annual, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameters describing the long time gravity field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt list to correspond points of time to arc numbers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~eliminateParameter & \\hfuzz=500pt boolean & \\hfuzz=500pt eliminate short time and state parameter\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsCreate}\\label{NormalsCreate}\nCreate \\file{normal equations}{normalEquation}\nfrom calculated matrices (\\configClass{matrixGenerator}{matrixGeneratorType}).\n\nThe \\configFile{inputfileParameterNames}{parameterName} can be created with \\program{ParameterNamesCreate}.\n\nThe \\configClass{normalMatrix}{matrixGeneratorType} must be symmetric.\nThe \\configClass{rightHandSide}{matrixGeneratorType} must have the same number of rows\nand can contain multiple columns for multiple solutions.\n\nThe Vector $\\M l^T\\M P\\M l$ is the quadratic sum of observations for each column of the right hand side.\nIt is used to determine the aposteriori accuracy\n\\begin{equation}\n\\hat{\\sigma}^2 = \\frac{\\hat{\\M e}^T\\M P\\hat{\\M e}}{n-m} = \\frac{\\M l^T\\M P\\M l - \\M n^T\\hat{\\M x}}{n-m}.\n\\end{equation}\nIf the vector is not given, it is automatically determined by assuming $\\hat{\\sigma}^2=1$.\n\nThe number of observations~$n$ is given by the expression \\config{observationCount}.\nThe variable \\verb|observationCount| can be used, if it is set by a normal equation file\n\\configFile{inputfileNormalEquationObsCount}{normalEquation}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~normalMatrix & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~lPl & \\hfuzz=500pt \\hyperref[matrixGeneratorType]{matrixGenerator} & \\hfuzz=500pt vector with size of rhs columns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileNormalEquationObsCount & \\hfuzz=500pt filename & \\hfuzz=500pt sets the variable observationCount\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observationCount & \\hfuzz=500pt expression & \\hfuzz=500pt (variables: rows, columns (rhs), observationCount)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NormalsEliminate}\\label{NormalsEliminate}\nThis program eliminates parameters from a system of \\configFile{inputfileNormalEquation}{normalEquation}s.\nTo just remove (cutting out) parameters use \\program{NormalsReorder}.\n\nThe \\configClass{remainingParameters}{parameterSelectorType} allows the selection\nof parameters that will remain, all others will be eliminated. The order of remaining parameters\ncan be modified via the parameter selection. Block size of the output normal matrix can be adjusted with\n\\config{outBlockSize}. If it is set to zero, the \\configFile{outputfileNormalEquation}{normalEquation}\nis written to a single block file.\n\nFor example the normal equations are divided into two groups of\nparameters $\\hat{\\M x}_1$ and $\\hat{\\M x}_2$ according to\n\\begin{equation}\n\\begin{pmatrix}\n  \\M N_{11} & \\M N_{12} \\\\\n  \\M N_{21} & \\M N_{22}\n\\end{pmatrix}\n\\begin{pmatrix} \\hat{\\M x}_1 \\\\ \\hat{\\M x}_2 \\end{pmatrix}\n=\n\\begin{pmatrix}\n  \\M n_1 \\\\\n  \\M n_2\n\\end{pmatrix}.\n\\end{equation}\nand $\\hat{\\M x}_2$ shall be eliminated, the reduced system of normal equations is given by\n\\begin{equation}\n\\bar{\\M N}\\hat{\\M x} = \\bar{\\M n}\n\\qquad\\text{with}\\qquad\n\\bar{\\M N}=\\M N_{11}-\\M N_{12}\\M N_{22}^{-1}\\M N_{12}^T\n\\qquad\\text{and}\\qquad\\bar{\\M n} =  \\M n_1 - \\M N_{12}\\M N_{22}^{-1}\\M n_2.\n\\end{equation}\n\nSee also \\program{NormalsReorder}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~remainingParameters & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of output normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsMultiplyAdd}\\label{NormalsMultiplyAdd}\nThis program modifies \\configFile{inputfileNormalEquation}{normalEquation} in a way\nthat $\\bar{\\M x}$ is estimated instead of $\\M x$.\n\\begin{equation}\n \\bar{\\M x} := \\M x + \\alpha\\, \\M x_0,\n\\end{equation}\nwhere $\\M x_0$ is \\configFile{inputfileParameter}{matrix} and $\\alpha$ is \\config{factor}.\nThis can be used to re-add reduced reference fields before a combined estimation\nat normal equation level.\nTherefore the right hand side of the normal equations is modified by\n\\begin{equation}\n \\bar{\\M n} := \\M n + \\alpha\\,\\M N\\M x_0,\n\\end{equation}\nand the quadratic sum of observations by\n\\begin{equation}\n \\bar{\\M l^T\\M P\\M l} := \\M l^T\\M P\\M l + \\alpha^2\\,\\M x_0^T\\M N\\M x_0 + 2\\alpha\\,\\M x_0^T\\M n\n\\end{equation}\n\nAs the normal matrix itself is not modified, rewriting of the matrix can be disabled by setting\n\\config{writeNormalMatrix} to false.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameter & \\hfuzz=500pt filename & \\hfuzz=500pt x\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt alpha\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~writeNormalMatrix & \\hfuzz=500pt boolean & \\hfuzz=500pt write full coefficient matrix, right hand sides and info files\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsRegularizationBorders}\\label{NormalsRegularizationBorders}\nThis program sets up two regularization matrices for two different regional areas.\nFor a given set of points defined by \\configClass{grid}{gridType} it is evaluated, whether each point\n(corresponding to an unknown parameter of a respective parameterization by space localizing basis functions)\nis inside or outside a certain area given by \\configClass{border}{borderType}.\nEach regularization matrix is a diagonal matrix, one of them features a one if the\npoint is inside, and a zero if the point lies outside the area. The other matrix features\na zero if the point is inside, and a one if the point lies outside the area\nThis results in two regularization matrices with\n\\begin{equation}\n\\M R_1+\\M R_2=\\M I.\n\\end{equation}\nThe two matrices are provided as vectors of the diagonal\nin the output files \\configFile{outputfileOutside}{matrix} and \\configFile{outputfileInside}{matrix}.\nThe regularization matrices are then used by \\configClass{normalEquation:regularization}{normalEquationType:regularization}.\nAs an example, the two different areas could be oceanic regions on the one hand and continental areas on the other hand.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInside & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOutside & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~grid & \\hfuzz=500pt \\hyperref[gridType]{grid} & \\hfuzz=500pt nodal point distribution of parameters, e.g harmonics splines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~border & \\hfuzz=500pt \\hyperref[borderType]{border} & \\hfuzz=500pt regularization areas, e.g land and ocean\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates for border\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates for border, 0: spherical coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NormalsRegularizationSphericalHarmonics}\\label{NormalsRegularizationSphericalHarmonics}\nDiagonal regularization matrix from gravity field accuracies,\nif not given from signal (cnm,snm), if not given from kaulas rule.\nThe inverse accuracies $1/\\sigma_n^2$ are used as weights in the regularization matrix.\nThe diagonal is saved as Vector.\n\nThe corresponding pseudo observations can be computed with \\program{Gravityfield2SphericalHarmonicsVector}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDiagonalmatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minRegularizationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxRegularizationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~numbering & \\hfuzz=500pt \\hyperref[sphericalHarmonicsNumberingType]{sphericalHarmonicsNumbering} & \\hfuzz=500pt numbering scheme for regul matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~makeIsotropic & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~kaulaPower & \\hfuzz=500pt double & \\hfuzz=500pt sigma = kaulaFactor*degree**kaulaPower\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~kaulaFactor & \\hfuzz=500pt double & \\hfuzz=500pt sigma = kaulaFactor*degree**kaulaPower\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NormalsReorder}\\label{NormalsReorder}\nReorder \\configFile{inputfileNormalEquation}{normalEquation} by selecting parameters in a specific order.\nThe \\configClass{parameterSelection}{parameterSelectorType} also allows one to change dimension of the normal equations,\neither by cutting parameters or by inserting zero rows/columns for additional parameters.\nWithout \\configClass{parameterSelection}{parameterSelectorType} the order of parameters remains the same.\nAdditionally the block sizes of the files can be adjusted. If \\config{outBlockSize} is set to zero,\nthe normal matrix is written to a single block file, which is needed by some programs.\n\nTo eliminate parameters without changing the result of the other parameters use \\program{NormalsEliminate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of output normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsReorderAndAccumulate}\\label{NormalsReorderAndAccumulate}\nThis program accumulates \\configFile{inputfileNormalEquation}{normalEquation}s with respect\nto the parameter names and writes the total combined system to \\configFile{outputfileNormalequation}{normalEquation}.\n\nThe combined normal equation is extended to include all parameter names uniquely from all input normals.\nThe input normals are sorted so that parameters with the same name are accumulated.\nThis requires that the names in each normal equation are unique.\n\nThe output can be written as multiple small block files with \\config{outBlockSize},\nor as single block with \\config{outBlockSize}=0,\nor blocked with respect to the first part of the parameter names (object), if \\config{outBlockSize} left empty.\n\nSee also \\program{NormalsBuild} and \\program{NormalsAccumulate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block, empty: blocking by objects\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsScale}\\label{NormalsScale}\nScales rows and columns of a system of \\configFile{inputfileNormalEquation}{normalEquation}\ngiven by a diagonal matrix \\configFile{inputfileFactorVector}{matrix} $\\M S$\n\\begin{equation}\n  \\bar{\\M N} := \\M S \\M N \\M S \\qquad\\text{and}\\qquad \\bar{\\M n} := \\M S \\M n.\n\\end{equation}\nThe estimated solution is now\n\\begin{equation}\n  \\bar{\\M x} := \\M S^{-1} \\M x.\n\\end{equation}\nThis is effectively the same as rescaling columns of the design matrix.\nThis program is useful when combining normal equations from different sources,\nfor example in case the units of certain parameters don't match.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileFactorVector & \\hfuzz=500pt filename & \\hfuzz=500pt Vector containing the factors\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsSolverVCE}\\label{NormalsSolverVCE}\nThis program accumulates \\configClass{normalEquation}{normalEquationType}\nand solves the total combined system.\nThe relative weigthing between the individual normals is determined iteratively\nby means of variance component estimation (VCE). For a detailed description\nof the used algorithm see \\configClass{normalEquation}{normalEquationType}.\n\nBesides the estimated parameter vector (\\configFile{outputfileSolution}{matrix}) the\nestimated accuracies (\\configFile{outputfileSigmax}{matrix}) and the full covariance matrix\n(\\configFile{outputfileCovariance}{matrix}) can be saved. Also the combined normal system\ncan be written to \\configFile{outputfileNormalEquation}{normalEquation}.\n\nThe \\configFile{outputfileContribution}{matrix} is a matrix with rows for each estimated\nparameter and columns for each \\configClass{normalEquation}{normalEquationType}\nand indicates the contribution of the individual normals to the estimated parameters.\nEach row sum up to one.\n\nSee also \\program{NormalsBuild}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt full covariance matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileContribution & \\hfuzz=500pt filename & \\hfuzz=500pt contribution of normal system components to the solution vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileVarianceFactors & \\hfuzz=500pt filename & \\hfuzz=500pt estimated variance factors as vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt the combined normal equation system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~normalEquation & \\hfuzz=500pt \\hyperref[normalEquationType]{normalEquation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileApproxSolution & \\hfuzz=500pt filename & \\hfuzz=500pt to accelerate convergence\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rightHandSideNumberVCE & \\hfuzz=500pt uint & \\hfuzz=500pt the right hand side number for estimation of variance factors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~normalsBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size for distributing the normal equations, 0: one block\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxIterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt maximum number of iterations for variance component estimation\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NormalsTemporalCombination}\\label{NormalsTemporalCombination}\nThis program reads a times series of \\configFile{inputfileNormalequation}{normalEquation}\nwith asscociated \\configClass{timeSeries}{timeSeriesType} and setup a new combined normal equation system.\nFor each parameter a \\configClass{parametrizationTemporal}{parametrizationTemporalType} is used.\n\nIt can be used to estimate trend and annual spherical harmonic coefficients from monthly GRACE normal equations.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt normal equations for each point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt times of each normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationTemporal & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{ParameterNamesCreate}\\label{ParameterNamesCreate}\nGenerate a \\configFile{outputfileParameterNames}{parameterName} by \\configClass{parameterName}{parameterNamesType}.\nThis file can be used in \\program{NormalsCreate} or in the class \\configClass{parameterSelector}{parameterSelectorType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt output parameter names file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterName & \\hfuzz=500pt \\hyperref[parameterNamesType]{parameterNames} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ParameterSelection2IndexVector}\\label{ParameterSelection2IndexVector}\nGenerate index vector from parameter selection in \\file{matrix format}{matrix}.\nThis vector can be used in \\program{MatrixCalculate}\nwith \\configClass{matrix:reorder}{matrixGeneratorType:reorder}\nto reorder arbitrary vectors and matrices similar to \\program{NormalsReorder}.\n\nThe \\configClass{parameterSelection}{parameterSelectorType} allows reordering and dimension changes,\neither by cutting parameters or by inserting additional parameters.\n\\configFile{outputfileIndexVector}{matrix} contains indices of parameters in\n\\configFile{inputfileParameterNames}{parameterName} or -1 for newly added parameters.\n\\configFile{outputfileParameterNames}{parameterName} contains the selected parameter names.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileIndexVector & \\hfuzz=500pt filename & \\hfuzz=500pt indices of source parameters in target normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt output parameter names file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt parameter names file of source normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameter order/selection of target normal equations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Orbit}\n\\subsection{Orbit2ArgumentOfLatitude}\\label{Orbit2ArgumentOfLatitude}\nThis program computes the argument of latitude of an \\file{orbit}{instrument}\nand writes it as \\file{instrument file}{instrument} (MISCVALUE(S)).\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n\n\\fig{!hb}{0.8}{instrumentOrbit2ArgumentOfLatitude}{fig:instrumentOrbit2ArgumentOfLatitude}{Derivation filtered GRACE range-rate residuals.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileArgOfLatitude & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (MISCVALUE(S): argLat, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data are appended\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Orbit2BetaPrimeAngle}\\label{Orbit2BetaPrimeAngle}\nThis program computes the beta prime angle (between the orbital plane and earth-sun direction)\nand writes it as MISCVALUE(S) \\file{instrument file}{instrument}. The angle is calculated w.r.t the sun (per default),\nbut can be changed.\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileBetaAngle & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (MISCVALUE(S): beta', ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data are appended\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~planet & \\hfuzz=500pt \\hyperref[planetType]{planet} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Orbit2EarthFixedOrbit}\\label{Orbit2EarthFixedOrbit}\nNormally the orbits in GROOPS are given in the celestial reference frame (CRF) with the\norigin in the center of mass (CoM). This program rotates the orbit with\n\\configClass{earthRotation}{earthRotationType} from CRF to the TRF.\n\nTo additionally tranform into the center of solid Earth (CE) frame (or center of Figure (CF)),\na correction can be applied by providing degree one coefficients of a\n\\configClass{gravityfield}{gravityfieldType} (e.g. ocean tides).\n\nIf \\config{celestial2terrestrial} is set to no, the inverse transformation is applied.\n\nSee also \\program{InstrumentRotate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt transformation from CRF to TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt degree 1 fluid mantle for CM2CE correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~celestial2terrestrial & \\hfuzz=500pt boolean & \\hfuzz=500pt yes: crf-\\$>\\$trf, no: trf-\\$>\\$crf\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Orbit2EclipseFactor}\\label{Orbit2EclipseFactor}\nThis program generates an \\file{instrument file}{instrument} (MISCVALUE(S)) containing the eclipse factor for a given set of orbit.\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEclipseFactor & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (MISCVALUE(S): eclipse, ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data are appended\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Orbit2Groundtracks}\\label{Orbit2Groundtracks}\nThis program write \\file{satellites positions}{instrument} as \\file{gridded data}{griddedData}\n(\\config{outputfileTrackGriddedData}) in a terrestrial reference frame. The points are expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and\n\\config{inverseFlattening}. The orbit data are given in the celestial frame so \\configClass{earthRotation}{earthRotationType}\nis needed to transform the data into the terrestrial frame.\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each point.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt positions as gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt values at grid points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt transformation from CRF to TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Orbit2Kepler}\\label{Orbit2Kepler}\nThis program computes the osculating Keplerian elements from position and velocity\nof a given \\configFile{inputfileOrbit}{instrument}.\nThe \\configFile{inputfileOrbit}{instrument} must contain positions and velocities (see \\program{OrbitAddVelocityAndAcceleration}).\n\nThe \\config{outputfileKepler} is an \\file{instrument file}{instrument} (MISCVALUES)\nwith the Keplerian elements at each epoch in the following order\n\\begin{itemize}\n\\item Ascending Node $\\Omega$ [degree]\n\\item Inclination $i$ [degree]\n\\item Argument of perigee $\\omega$ [degree]\n\\item major axis $a$ [m]\n\\item eccentricity $e$\n\\item mean anomaly $M$ [degree]\n\\item transit time of perigee $\\tau$ [mjd]\n\\end{itemize}\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileKepler & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (MISCVALUES: Omega, i, omega [degree], a [m], e, M [degree], tau [mjd], ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt position and velocity at each epoch define the kepler orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data is appended\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Orbit2MagneticField}\\label{Orbit2MagneticField}\nThis program computes the magentic field vector($x, y, z$ $[Tesla = kg/A/s^2]$ in CRF))\nalong an \\file{orbit}{instrument} and writes it as \\file{instrument file}{instrument} (MISCVALUES).\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as data columns to each epoch.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMagneticField & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (x,y,z in CRF [Tesla = kg/A/s\\textasciicircum{}2]), ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data are appended to output file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~magnetosphere & \\hfuzz=500pt \\hyperref[magnetosphereType]{magnetosphere} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{Orbit2ThermosphericState}\\label{Orbit2ThermosphericState}\nThis program computes the thermosperic state (density, temperature, wind (x,y,z in CRF))\nbased on emprical models along an \\file{orbit}{instrument}\nand writes it as \\file{instrument file}{instrument} (MISCVALUES).\nThe wind is given in an celestial reference frame (CRF).\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileThermosphericState & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file (MISCVALUES: density, temperature, wind (x,y,z in CRF), ...)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt data are appended to output file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~thermosphere & \\hfuzz=500pt \\hyperref[thermosphereType]{thermosphere} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{OrbitAddVelocityAndAcceleration}\\label{OrbitAddVelocityAndAcceleration}\nThis program computes velocities and accelerations from a given \\file{orbit}{instrument}\nby differentiating a moving polynomial.\nThe values are saved in one output file which then contains orbit, velocity and acceleration.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~polynomialDegree & \\hfuzz=500pt uint & \\hfuzz=500pt Polynomial degree, must be even!\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PlanetOrbit}\\label{PlanetOrbit}\nCreates an \\file{orbit file}{instrument} of sun, moon, or planets.\nThe orbit is given in the celestial reference frame (CRF)\nor alternatively in the terrestrial reference frame (TRF)\nif \\configClass{earthRotation}{earthRotationType} is provided.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~planet & \\hfuzz=500pt \\hyperref[planetType]{planet} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt transform orbits into TRF\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Plot}\n\\subsection{PlotDegreeAmplitudes}\\label{PlotDegreeAmplitudes}\nPlot degree amplitudes of potential coefficients computed by \\program{Gravityfield2DegreeAmplitudes}\nor \\program{PotentialCoefficients2DegreeAmplitudes} using the GMT Generic Mapping Tools\n(\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\nThis is a convenience program with meaningful default values. The same plots can be generated with the more general \\program{PlotGraph}.\n\n\\fig{!hb}{0.8}{plotDegreeAmplitudes}{fig:plotDegreeAmplitudes}{Comparison of GRACE solutions (2008-06) with GOCO06s.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt *.png, *.jpg, *.eps, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~title & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~layer & \\hfuzz=500pt \\hyperref[plotGraphLayerType]{plotGraphLayer} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacingDegree & \\hfuzz=500pt double & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacingDegree & \\hfuzz=500pt double & \\hfuzz=500pt frame tick spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacingDegree & \\hfuzz=500pt double & \\hfuzz=500pt gridline spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~labelDegree & \\hfuzz=500pt string & \\hfuzz=500pt description of the x-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~logarithmicDegree & \\hfuzz=500pt boolean & \\hfuzz=500pt use logarithmic scale for the x-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minY & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxY & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacingY & \\hfuzz=500pt double & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacingY & \\hfuzz=500pt double & \\hfuzz=500pt frame tick spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacingY & \\hfuzz=500pt double & \\hfuzz=500pt gridline spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~unitY & \\hfuzz=500pt string & \\hfuzz=500pt appended to axis values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~labelY & \\hfuzz=500pt string & \\hfuzz=500pt description of the y-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~logarithmicY & \\hfuzz=500pt boolean & \\hfuzz=500pt use logarithmic scale for the y-axis\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt The style of the grid lines.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~legend & \\hfuzz=500pt \\hyperref[plotLegendType]{plotLegend} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~options & \\hfuzz=500pt sequence & \\hfuzz=500pt further options...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~titleFontSize & \\hfuzz=500pt uint & \\hfuzz=500pt in pt\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~marginTitle & \\hfuzz=500pt double & \\hfuzz=500pt between title and figure [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~drawGridOnTop & \\hfuzz=500pt boolean & \\hfuzz=500pt grid lines above all other lines/points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~options & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~transparent & \\hfuzz=500pt boolean & \\hfuzz=500pt make background transparent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~dpi & \\hfuzz=500pt uint & \\hfuzz=500pt use this resolution when rasterizing postscript file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~removeFiles & \\hfuzz=500pt boolean & \\hfuzz=500pt remove .gmt and script files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PlotGraph}\\label{PlotGraph}\nGenerates a two dimensional xy plot using the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThe plotting area is defined by the two axes \\configClass{axisX/Y}{plotAxisType}. An alternative \\configClass{axisY2}{plotAxisType}\non the right hand side can be added. The content of the graph itself is defined\nby one or more \\configClass{layer}{plotGraphLayerType}s.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\nSee also: \\program{PlotDegreeAmplitudes}, \\program{PlotMap}, \\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt *.png, *.jpg, *.eps, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~title & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~layer & \\hfuzz=500pt \\hyperref[plotGraphLayerType]{plotGraphLayer} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~axisX & \\hfuzz=500pt \\hyperref[plotAxisType]{plotAxis} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~axisY & \\hfuzz=500pt \\hyperref[plotAxisType]{plotAxis} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~axisY2 & \\hfuzz=500pt \\hyperref[plotAxisType]{plotAxis} & \\hfuzz=500pt Second y-axis on right hand side\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~colorbar & \\hfuzz=500pt \\hyperref[plotColorbarType]{plotColorbar} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~legend & \\hfuzz=500pt \\hyperref[plotLegendType]{plotLegend} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~options & \\hfuzz=500pt sequence & \\hfuzz=500pt further options...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~titleFontSize & \\hfuzz=500pt uint & \\hfuzz=500pt in pt\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~marginTitle & \\hfuzz=500pt double & \\hfuzz=500pt between title and figure [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~drawGridOnTop & \\hfuzz=500pt boolean & \\hfuzz=500pt grid lines above all other lines/points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~options & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~transparent & \\hfuzz=500pt boolean & \\hfuzz=500pt make background transparent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~dpi & \\hfuzz=500pt uint & \\hfuzz=500pt use this resolution when rasterizing postscript file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~removeFiles & \\hfuzz=500pt boolean & \\hfuzz=500pt remove .gmt and script files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PlotMap}\\label{PlotMap}\nGenerates a map using the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThe base map is defined by a \\configClass{projection}{plotMapProjectionType} of an ellipsoid (\\config{R}, \\config{inverseFlattening}).\nThe content of the map itself is defined by one or more \\configClass{layer}{plotMapLayerType}s.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\nSee also: \\program{PlotDegreeAmplitudes}, \\program{PlotGraph}, \\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n\n\\fig{!hb}{0.8}{plotMap}{fig:plotMap}{A Robinson projection with griddedData (geoid), coast, polygon (amazon), and points (IGS stations) layer.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt *.png, *.jpg, *.eps, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~title & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~statisticInfos & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~layer & \\hfuzz=500pt \\hyperref[plotMapLayerType]{plotMapLayer} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates on output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minLambda & \\hfuzz=500pt angle & \\hfuzz=500pt min. longitude (default: compute from input data)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxLambda & \\hfuzz=500pt angle & \\hfuzz=500pt max. longitude (default: compute from input data)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minPhi & \\hfuzz=500pt angle & \\hfuzz=500pt min. latitude (default: compute from input data)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxPhi & \\hfuzz=500pt angle & \\hfuzz=500pt max. latitude (default: compute from input data)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacing & \\hfuzz=500pt angle & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacing & \\hfuzz=500pt angle & \\hfuzz=500pt frame tick spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacing & \\hfuzz=500pt angle & \\hfuzz=500pt gridline spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~colorbar & \\hfuzz=500pt \\hyperref[plotColorbarType]{plotColorbar} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~projection & \\hfuzz=500pt \\hyperref[plotMapProjectionType]{plotMapProjection} & \\hfuzz=500pt map projection\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~options & \\hfuzz=500pt sequence & \\hfuzz=500pt further options...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~titleFontSize & \\hfuzz=500pt uint & \\hfuzz=500pt in pt\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~marginTitle & \\hfuzz=500pt double & \\hfuzz=500pt between title and figure [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~drawGridOnTop & \\hfuzz=500pt boolean & \\hfuzz=500pt grid lines above all other lines/points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~options & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~transparent & \\hfuzz=500pt boolean & \\hfuzz=500pt make background transparent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~dpi & \\hfuzz=500pt uint & \\hfuzz=500pt use this resolution when rasterizing postscript file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~removeFiles & \\hfuzz=500pt boolean & \\hfuzz=500pt remove .gmt and script files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PlotMatrix}\\label{PlotMatrix}\nPlot the coefficients of a \\configFile{inputfileMatrix}{matrix}\nusing the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\n\\fig{!hb}{0.6}{plotMatrix}{fig:plotMatrix}{Upper left part of the DDK filter matrix.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt *.png, *.jpg, *.eps, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~title & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minColumn & \\hfuzz=500pt uint & \\hfuzz=500pt minimum column index to plot\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxColumn & \\hfuzz=500pt uint & \\hfuzz=500pt maximum column index to plot\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacingX & \\hfuzz=500pt double & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacingX & \\hfuzz=500pt double & \\hfuzz=500pt frame tick spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacingX & \\hfuzz=500pt double & \\hfuzz=500pt gridline spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minRow & \\hfuzz=500pt uint & \\hfuzz=500pt minimum row index to plot\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxRow & \\hfuzz=500pt uint & \\hfuzz=500pt maximum row index to plot\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacingY & \\hfuzz=500pt double & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacingY & \\hfuzz=500pt double & \\hfuzz=500pt frame tick spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacingY & \\hfuzz=500pt double & \\hfuzz=500pt gridline spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt The style of the grid lines.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~colorbar & \\hfuzz=500pt \\hyperref[plotColorbarType]{plotColorbar} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~options & \\hfuzz=500pt sequence & \\hfuzz=500pt further options...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~titleFontSize & \\hfuzz=500pt uint & \\hfuzz=500pt in pt\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~marginTitle & \\hfuzz=500pt double & \\hfuzz=500pt between title and figure [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~drawGridOnTop & \\hfuzz=500pt boolean & \\hfuzz=500pt grid lines above all other lines/points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~options & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~transparent & \\hfuzz=500pt boolean & \\hfuzz=500pt make background transparent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~dpi & \\hfuzz=500pt uint & \\hfuzz=500pt use this resolution when rasterizing postscript file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~removeFiles & \\hfuzz=500pt boolean & \\hfuzz=500pt remove .gmt and script files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PlotSphericalHarmonicsTriangle}\\label{PlotSphericalHarmonicsTriangle}\nPlot the potential coefficients of a spherical harmonic expansion\nusing the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThis program plots the formal errors (sigmas).\nIf \\configClass{gravityfield}{gravityfieldType} provides no sigmas\ne.g. with \\config{setSigmasToZero} in \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\nthe coefficients itself are plotted instead.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\n\\fig{!hb}{0.8}{plotSphericalHarmonicsTriangle}{fig:plotSphericalHarmonicsTriangle}{Formal errors of GOCO06s.}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt *.png, *.jpg, *.eps, ...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~title & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt use sigmas, if not given use signal (cnm,snm)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt at this time the gravity field will be evaluated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~majorTickSpacing & \\hfuzz=500pt double & \\hfuzz=500pt boundary annotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minorTickSpacing & \\hfuzz=500pt double & \\hfuzz=500pt frame tick spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLineSpacing & \\hfuzz=500pt double & \\hfuzz=500pt gridline spacing\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gridLine & \\hfuzz=500pt \\hyperref[plotLineType]{plotLine} & \\hfuzz=500pt The style of the grid lines.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~colorbar & \\hfuzz=500pt \\hyperref[plotColorbarType]{plotColorbar} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~options & \\hfuzz=500pt sequence & \\hfuzz=500pt further options...\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~width & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~height & \\hfuzz=500pt double & \\hfuzz=500pt in cm\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~titleFontSize & \\hfuzz=500pt uint & \\hfuzz=500pt in pt\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~marginTitle & \\hfuzz=500pt double & \\hfuzz=500pt between title and figure [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~drawGridOnTop & \\hfuzz=500pt boolean & \\hfuzz=500pt grid lines above all other lines/points\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~options & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~transparent & \\hfuzz=500pt boolean & \\hfuzz=500pt make background transparent\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~dpi & \\hfuzz=500pt uint & \\hfuzz=500pt use this resolution when rasterizing postscript file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~removeFiles & \\hfuzz=500pt boolean & \\hfuzz=500pt remove .gmt and script files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Preprocessing}\n\\subsection{PreprocessingDualSst}\\label{PreprocessingDualSst}\nThis programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration.\nFour different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites.\nThis program works similar to \\program{PreprocessingSst}, see there for details. Here only the settings explained,\nwhich are different.\n\nBoth SST observation types are reduced by the same background models and the same impact\nof accelerometer measurements. The covariance matrix of the reduced observations should not consider\nthe the instrument noise only (\\configClass{covarianceSst1/2}{covarianceSstType}) but must\ntake the cross correlations \\configClass{covarianceAcc}{covarianceSstType} into account.\nThe covariance matrix of the reduced observations is given by\n\\begin{equation}\n  \\M\\Sigma(\\begin{bmatrix} \\Delta l_{SST1} \\\\ \\Delta l_{SST2} \\end{bmatrix})\n  = \\begin{bmatrix} \\M\\Sigma_{SST1} + \\M\\Sigma_{ACC} & \\M\\Sigma_{ACC} \\\\\n                   \\M\\Sigma_{ACC} & \\M\\Sigma_{SST2} + \\M\\Sigma_{ACC}\n    \\end{bmatrix}.\n\\end{equation}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameter vector (static part only)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterName & \\hfuzz=500pt filename & \\hfuzz=500pt estimated signal parameters (index is appended)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateArcSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcSst1 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (SST1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcSst2 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (SST2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcAcc & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (ACC)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcPod1 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (POD1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcPod2 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (POD2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateEpochSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochSst1 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (SST1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochSst2 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (SST2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochAcc & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (ACC)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochPod1 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (POD1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochPod2 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (POD2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateCovarianceFunctions & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionSst1 & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionSst2 & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionAcc & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionPod1 & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions for along, cross, radial direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionPod2 & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions for along, cross, radial direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeResiduals & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSst1Residuals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSst2Residuals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileAccResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfilePod1Residuals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfilePod2Residuals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt choice & \\hfuzz=500pt obervation equations (Sst)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dualSstVariational & \\hfuzz=500pt sequence & \\hfuzz=500pt two SST observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking1 & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking2 & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite A as observations\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite B as observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational1 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational2 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst1 & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter for first ranging observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst2 & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter for second ranging observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst1 & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Must be given per sst arc with correct dimensions.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Vector with one sigma for each \\$<\\$inputfileCovarianceMatrixArc\\$>\\$\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst2 & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Must be given per sst arc with correct dimensions.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Vector with one sigma for each \\$<\\$inputfileCovarianceMatrixArc\\$>\\$\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceAcc & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Must be given per sst arc with correct dimensions.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Vector with one sigma for each \\$<\\$inputfileCovarianceMatrixArc\\$>\\$\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod1 & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod2 & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateShortTimeVariations & \\hfuzz=500pt sequence & \\hfuzz=500pt co-estimate short time gravity field variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~estimateSigma & \\hfuzz=500pt boolean & \\hfuzz=500pt estimate standard deviation via VCE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~autoregressiveModelSequence & \\hfuzz=500pt \\hyperref[autoregressiveModelSequenceType]{autoregressiveModelSequence} & \\hfuzz=500pt AR model sequence for constraining short time gravity variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameters describing the short time gravity field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~downweightPod & \\hfuzz=500pt double & \\hfuzz=500pt downweight factor for POD\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt list to correspond points of time to arc numbers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for the estimation of calibration parameter and error PSD\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableNameIterations & \\hfuzz=500pt string & \\hfuzz=500pt All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size of static normal equation blocks\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PreprocessingGradiometer}\\label{PreprocessingGradiometer}\nThis program estimates empirical covariance functions of the gradiometer instrument noise and determine arc wise variances to\ndownweight arcs with outliers. This program works similar to \\program{PreprocessingPod}, see there for details.\nHere only the settings explained, which are different.\n\n...\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSggResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[sggRightSideType]{sggRightSide} & \\hfuzz=500pt input for the observation vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationBias & \\hfuzz=500pt \\hyperref[parametrizationTemporalType]{parametrizationTemporal} & \\hfuzz=500pt per arc\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSgg & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~covarianceLength & \\hfuzz=500pt uint & \\hfuzz=500pt counts observation epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt for the estimation of calibration parameter and error PSD\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PreprocessingPod}\\label{PreprocessingPod}\nThis program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to\ndownweight arcs with outliers.\n\nA complete least squares adjustment for gravity field determination is performed by computing the \\config{observation}\nequations, see \\configClass{observation:podIntegral}{observationType:podIntegral} or\n\\configClass{observation:podVariational}{observationType:podVariational} for details. The normal equations\nare accumulated and solved to \\configFile{outputfileSolution}{matrix} together with the estimated accuracies\n\\configFile{outputfileSigmax}{matrix}. The estimated residuals~$\\hat{\\M e}=\\M l-\\M A\\hat{\\M x}$ can be computed with\n\\config{computeResiduals}.\n\nFor each component (along, cross, radial) of the kinematic orbit positions a noise covariance function is estimated\n\\begin{equation}\n  \\text{cov}(\\Delta t_i) = \\sum_{n=0}^{N-1} a_n^2 \\cos\\left(\\frac{\\pi}{T} n\\Delta t_i\\right).\n\\end{equation}\nThe covariance matrix is composed of the sum of matrices $F_n$ and unknown variance factors\n\\begin{equation}\n  \\M\\Sigma = a_1^2\\M F_1 + a_2^2 \\M F_2 + \\cdots + a_N^2\\M F_N,\n\\end{equation}\nwith the cosine transformation matrices\n\\begin{equation}\n  \\M F_n = \\left(\\cos\\left(\\frac{\\pi}{T} n(t_i-t_k)\\right)\\right)_{ik}.\n\\end{equation}\n\nAn additional variance factor can be computed (\\config{estimateArcSigmas}) for each arc~$k$  according to\n\\begin{equation}\n  \\hat{\\sigma}_k^2 = \\frac{\\hat{\\M e}_k^T\\M\\Sigma^{-1}\\hat{\\M e}_k}{r_k},\n\\end{equation}\nwhere $r_k$ is the redundancy. This variance factor should be around one for normally behaving arcs\nas the noise characteristics are already considered by the covariance matrix but bad arcs get a much larger variance.\nBy applying this factor bad arcs or arcs with large outliers are downweighted.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameter vector (static part only)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterName & \\hfuzz=500pt filename & \\hfuzz=500pt names of estimated parameters (static part only)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateArcSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcPod & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (POD2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateCovarianceFunctions & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionPod & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions for along, cross, radial direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeResiduals & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfilePodResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt choice & \\hfuzz=500pt obervation equations (POD)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~podIntegral & \\hfuzz=500pt sequence & \\hfuzz=500pt precise orbit data (integral approach)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[podRightSideType]{podRightSide} & \\hfuzz=500pt input for the reduced observation vector\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~gradientfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt low order field to estimate the change of the gravity by position adjustement\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~keepSatelliteStates & \\hfuzz=500pt boolean & \\hfuzz=500pt set boundary values of each arc global\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~accelerateComputation & \\hfuzz=500pt boolean & \\hfuzz=500pt acceleration of computation by transforming the observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~podVariational & \\hfuzz=500pt sequence & \\hfuzz=500pt precise orbit data (variational equations)\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions as observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~accelerateComputation & \\hfuzz=500pt boolean & \\hfuzz=500pt acceleration of computation by transforming the observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuracies for each arc (multiplied with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt list to correspond points of time to arc numbers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~adjustmentThreshold & \\hfuzz=500pt double & \\hfuzz=500pt Adjustment factor threshold: Iteration will be stopped once both SST and POD adjustment factors are under this threshold\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for the estimation of calibration parameters and error PSD\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PreprocessingSst}\\label{PreprocessingSst}\nThis program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration.\nThree different observation groups are considered separately: SST and POD1/POD2 for the two satellites.\nThis program works similar to \\program{PreprocessingPod}, see there for details. Here only deviations\nin the settings are explained.\n\nPrecise orbit data (POD) often contains systematic errors in addition to stochastic noise. In this case the\nvariance component estimation fails and assigns too much weight to the POD data. Therefore an additional\n\\config{downweightPod} factor can be applied to the standard deviation of POD for the next least squares adjustment\nin the iteration. This factor should also applied as \\config{sigma} in \\configClass{observation}{observationType}\nfor computation of the final solution e.g. with \\program{NormalsSolverVCE}.\n\nShort time variations of the gravity field can be co-estimated together with the static/monthly\nmean gravity field. The short time parameters must also be set in \\configClass{observation:parametrizationGravity}{parametrizationGravityType} and\ncan then be selected by \\configClass{estimateShortTimeVariations:parameterSelection}{parameterSelectorType}.\nIf these parameters are not time variable, for example when a range of static parameters is selected,\nthey are set up as constant for each time interval defined in \\config{inputfileArcList}. The parameters are constrained by an\n\\configClass{estimateShortTimeVariations:autoregressiveModelSequence}{autoregressiveModelSequenceType}. The weight of\nthe constrain equations in terms of the standard deviation can be estimated by means of\nVariance Component Estimation (VCE) if \\config{estimateShortTimeVariations:estimateSigma} is set.\nThe mathematical background of this co-estimation can be found in:\n\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). \\url{https://doi.org/10.1007/s00190-019-01314-1}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt estimated parameter vector (static part only)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileParameterName & \\hfuzz=500pt filename & \\hfuzz=500pt estimated signal parameters (index is appended)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateArcSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcSst & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (SST)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcPod1 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (POD1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerArcPod2 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each arc (POD2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateEpochSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochSst & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (SST)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochPod1 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (POD1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasPerEpochPod2 & \\hfuzz=500pt filename & \\hfuzz=500pt accuracies of each epoch (POD2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateCovarianceFunctions & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionSst & \\hfuzz=500pt filename & \\hfuzz=500pt covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionPod1 & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions for along, cross, radial direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunctionPod2 & \\hfuzz=500pt filename & \\hfuzz=500pt covariance functions for along, cross, radial direction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateSstArcCovarianceSigmas & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSigmasCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt one variance factor per matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~computeResiduals & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfileSstResiduals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfilePod1Residuals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~outputfilePod2Residuals & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~observation & \\hfuzz=500pt choice & \\hfuzz=500pt obervation equations (Sst)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sstIntegral & \\hfuzz=500pt sequence & \\hfuzz=500pt integral approach\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel1 & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel2 & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~rightHandSide & \\hfuzz=500pt \\hyperref[sstRightSideType]{sstRightSide} & \\hfuzz=500pt input for the reduced observation vector\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeAcceleration & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt used to evaluate the observation equations, not used as observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~gradientfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt low order field to estimate the change of the gravity by position adjustement\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~keepSatelliteStates & \\hfuzz=500pt boolean & \\hfuzz=500pt set boundary values of each arc global\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sstVariational & \\hfuzz=500pt sequence & \\hfuzz=500pt variational equations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite A as observations\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite B as observations\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational1 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational2 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Must be given per sst arc with correct dimensions.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasCovarianceMatrixArc & \\hfuzz=500pt filename & \\hfuzz=500pt Vector with one sigma for each \\$<\\$inputfileCovarianceMatrixArc\\$>\\$\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod1 & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod2 & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sigma & \\hfuzz=500pt double & \\hfuzz=500pt apriori factor of covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerArc & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each arc (multiplicated with sigma)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmasPerEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt apriori different accuaries for each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt approximate covariances in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] sampling of the covariance function\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimateShortTimeVariations & \\hfuzz=500pt sequence & \\hfuzz=500pt co-estimate short time gravity field variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~estimateSigma & \\hfuzz=500pt boolean & \\hfuzz=500pt estimate standard deviation via VCE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~autoregressiveModelSequence & \\hfuzz=500pt \\hyperref[autoregressiveModelSequenceType]{autoregressiveModelSequence} & \\hfuzz=500pt AR model sequence for constraining short time gravity variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parameterSelection & \\hfuzz=500pt \\hyperref[parameterSelectorType]{parameterSelector} & \\hfuzz=500pt parameters describing the short time gravity field\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~downweightPod & \\hfuzz=500pt double & \\hfuzz=500pt downweight factor for POD\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileArcList & \\hfuzz=500pt filename & \\hfuzz=500pt list to correspond points of time to arc numbers\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt (maximum) number of iterations for the estimation of calibration parameter and error PSD\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableNameIterations & \\hfuzz=500pt string & \\hfuzz=500pt All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~defaultBlockSize & \\hfuzz=500pt uint & \\hfuzz=500pt block size of static normal equation blocks\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PreprocessingVariationalEquation}\\label{PreprocessingVariationalEquation}\nThis program integrates an orbit dynamically using the given forces and set up the state transition matrix\nfor each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using\nthe variational equation approach. The variational equations are computed arc-wise as defined by \\configFile{inputfileOrbit}{instrument}.\nThis means for each arc new initial state parameters are set up.\n\nIn a first step the \\configClass{forces}{forcesType} acting on the satellite are evaluated at the apriori positions given\nby \\configFile{inputfileOrbit}{instrument}. Non-conservative forces like solar radiation pressure need the orientation of the\nsatellite (\\configFile{inputfileStarCamera}{instrument}) and additionally, a satellite macro model (\\config{satelliteModel})\nwith the surface properties. Furthermore \\configFile{inputfileAccelerometer}{instrument} observations are also considered.\n\nIn a second step the accelerations are integrated twice to a dynamic orbit using a moving polynomial with the degree\n\\config{integrationDegree}. The orbit is corrected to be self-consistent. This means the forces should be evaluated\nat the new integrated positions instead of the apriori ones. This correction is computed in a linear approximation\nusing the gradient of the forces with respect to the positions (\\config{gradientfield}). As this term is small generally\nonly the largest force components have to be considered. A low degree spherical harmonic expansion of the static gravity\nfield (about up to degree 5) is sufficient in almost all cases. In this step also the state transition matrix (the partial\nderivatives of the current state, position and velocity) with respect to the initial state is computed.\nThe integrated orbit together with the state transitions are stored in \\configFile{outputfileVariational}{variationalEquation},\nthe integrated orbit only in \\configFile{outputfileOrbit}{instrument}.\n\nTo improve the numerical stability a reference ellipse can be reduced beforehand using Enke's method (\\config{useEnke}).\nMathematically the result is the same, but as the large central term is removed before and restored\nafterwards more digits are available for the computation.\n\nThe integrated orbit should be fitted to observations afterwards by the programs\n\\program{PreprocessingVariationalEquationOrbitFit} and/or \\program{PreprocessingVariationalEquationSstFit}.\nThey apply a least squares adjustment by estimating some satellite parameters (e.g. an accelerometer bias).\nIf the fitted orbit is too far away from the original \\configFile{inputfileOrbit}{instrument} the linearization may not be\naccurate enough. In this case \\program{PreprocessingVariationalEquation} should be run again with the fitted orbit\nas \\configFile{inputfileOrbit}{instrument} and introducing the \\config{estimatedParameters} as additional forces.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position, used to evaluate the force\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation from body frame to CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt non-gravitational forces in satellite reference frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~forces & \\hfuzz=500pt \\hyperref[forcesType]{forces} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~estimatedParameters & \\hfuzz=500pt sequence & \\hfuzz=500pt satellite parameters e.g. from orbit fit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameter & \\hfuzz=500pt filename & \\hfuzz=500pt estimated orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~gradientfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt low order field to estimate the change of the gravity by position adjustement\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useEnke & \\hfuzz=500pt sequence & \\hfuzz=500pt integrate differential forces to an elliptical reference trajectory\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt geocentric gravitational constant used for elliptical reference orbit\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PreprocessingVariationalEquationOrbitFit}\\label{PreprocessingVariationalEquationOrbitFit}\nThis program fits an \\configFile{inputfileVariational}{variationalEquation} to an observed \\configFile{inputfileOrbit}{instrument} by estimating parameters\nin a least squares adjustment. Additional to the initial satellite state for each arc, these parameters can be\n\\configClass{parametrizationGravity}{parametrizationGravityType}, satellite \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}\nand stochastic pulses (velocity jumps) at given times, \\configClass{stochasticPulse}{timeSeriesType}. The estimated parameters can be stored with\n\\configFile{outputfileSolution}{matrix} and an extra file with the parameter names is created. The fitted orbit is written\nas new reference in \\configFile{outputfileVariational}{variationalEquation} and additionally in \\configFile{outputfileOrbit}{instrument}.\n\nThe observed orbit positions (\\configFile{inputfileOrbit}{instrument}) together with the epoch-wise covariance matrix\n(\\configFile{inputfileCovariancePodEpoch}{instrument}) must be split in the same arcs as the variational equations but not\nnecessarily uniformly distributed (use irregularData in \\program{InstrumentSynchronize}). An iterative downweighting of\noutliers is performed by M-Huber method.\n\nThe observation equations (parameter sensitivity matrix) are computed by integration of the variational equations\n(\\configFile{inputfileVariational}{variationalEquation}) using a polynomial with \\config{integrationDegree} and interpolated to the\nobservation epochs using a polynomial with \\config{interpolationDegree}.\n\nAll parameters used here must be reestimated in the full least squares adjustment\nfor the gravity field determination to get a solution which is not biased towards the reference field.\nThe solutions of additional estimations are relative (deltas) as the parameters are already used as Taylor point\nin the reference orbit.\n\nSee also \\program{PreprocessingVariationalEquation}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt estimated calibration and state parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileCovariancePodEpoch & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch wise covariances\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt may be needed by parametrizationAcceleration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stochasticPulse & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt for the estimation of calibration parameter and error PSD\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{PreprocessingVariationalEquationSstFit}\\label{PreprocessingVariationalEquationSstFit}\nThis program fits two \\configFile{inputfileVariational1/2}{variationalEquation} to satellite-to-satellite-tracking (SST) and orbit\nobservations in a GRACE like configuration. It works similar to \\program{PreprocessingVariationalEquationOrbitFit},\nsee there for details.\n\nAs the relative weighting of the observation types is important complex description of the covariances can be set with\n\\configClass{covarianceSst}{covarianceSstType}, \\configClass{covariancePod1}{covariancePodType}, \\configClass{covariancePod2}{covariancePodType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileVariational1 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileVariational2 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt integrated orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution1 & \\hfuzz=500pt filename & \\hfuzz=500pt estimated calibration and state parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution2 & \\hfuzz=500pt filename & \\hfuzz=500pt estimated calibration and state parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~rightHandSide & \\hfuzz=500pt sequence & \\hfuzz=500pt input for observation vectors\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt ranging observations and corrections\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite A as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt kinematic positions of satellite B as observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sstType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~range & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~rangeRate & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~none & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational1 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVariational2 & \\hfuzz=500pt filename & \\hfuzz=500pt approximate position and integrated state matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationGravity & \\hfuzz=500pt \\hyperref[parametrizationGravityType]{parametrizationGravity} & \\hfuzz=500pt gravity field parametrization\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration1 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit1 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationAcceleration2 & \\hfuzz=500pt \\hyperref[parametrizationAccelerationType]{parametrizationAcceleration} & \\hfuzz=500pt orbit2 force parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~parametrizationSst & \\hfuzz=500pt \\hyperref[parametrizationSatelliteTrackingType]{parametrizationSatelliteTracking} & \\hfuzz=500pt satellite tracking parameter\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~integrationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt integration of forces by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt orbit interpolation by polynomial approximation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covarianceSst & \\hfuzz=500pt \\hyperref[covarianceSstType]{covarianceSst} & \\hfuzz=500pt covariance matrix of satellite to satellite tracking observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod1 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 1)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~covariancePod2 & \\hfuzz=500pt \\hyperref[covariancePodType]{covariancePod} & \\hfuzz=500pt covariance matrix of kinematic orbits (satellite 2)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~iterationCount & \\hfuzz=500pt uint & \\hfuzz=500pt for the estimation of calibration parameter and error PSD\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: Simulation}\n\\subsection{NoiseAccelerometer}\\label{NoiseAccelerometer}\nThis program adds noise and biases to simulated \\file{accelerometer data}{instrument}\ngenerated by \\program{SimulateAccelerometer}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~biasAlong & \\hfuzz=500pt double & \\hfuzz=500pt [m/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~biasCross & \\hfuzz=500pt double & \\hfuzz=500pt [m/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~biasRadial & \\hfuzz=500pt double & \\hfuzz=500pt [m/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseAlong & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseCross & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m/s**2]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseRadial & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m/s**2]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NoiseGriddedData}\\label{NoiseGriddedData}\nThis program adds noise to \\file{gridded data data}{griddedData}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NoiseInstrument}\\label{NoiseInstrument}\nThis program adds noise to \\file{instrument data}{instrument}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~startDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt start\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~countDataFields & \\hfuzz=500pt uint & \\hfuzz=500pt number of data fields (default: all after start)\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NoiseNormalsSolution}\\label{NoiseNormalsSolution}\nThe inverse of the normal matrix of \\configFile{inputfileNormalEquation}{normalEquation}\nrepresents the covariance matrix of the estimated parameters. This program generates a noise vector with\n\\begin{equation}\n\\M\\Sigma(\\M e) = \\M N^{-1},\n\\end{equation}\nif generated input noise is standard white noise.\n\nThe noise vector is computed with\n\\begin{equation}\n\\M e = \\M W^{-T} \\M z,\n\\end{equation}\nwhere $\\M z$ is the generated \\configClass{noise}{noiseGeneratorType} and\n$\\M W$ is the cholesky upper triangle matrix of the normal matrix $\\M N=\\M W^T\\M W$.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNoise & \\hfuzz=500pt filename & \\hfuzz=500pt generated noise as matrix: parameterCount x sampleCount\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormalEquation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampleCount & \\hfuzz=500pt uint & \\hfuzz=500pt number of samples to be generated\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useEigenvalueDecomposition & \\hfuzz=500pt boolean & \\hfuzz=500pt use eigenvalue decomposition\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NoiseOrbit}\\label{NoiseOrbit}\nThis program adds noise to simulated \\file{satellite}{instrument}'s positions\nand velocities generated by \\program{SimulateOrbit} (along, cross, radial).\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise options.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noisePosition & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt along, cross, radial [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseVelocity & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt along, cross, radial [m/s]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NoiseSatelliteTracking}\\label{NoiseSatelliteTracking}\nThis program adds noise to simulated satellite tracking data generated by \\program{SimulateSatelliteTracking}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseRange & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseRangeRate & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~noiseRangeAcceleration & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [m/s\\textasciicircum{}2]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NoiseStarCamera}\\label{NoiseStarCamera}\nThis program adds noise to rotation observations. The noise is computed via a pseudo random sequence.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise options.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noiseRoll & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noisePitch & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [rad]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noiseYaw & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt [rad]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{NoiseTimeSeries}\\label{NoiseTimeSeries}\nThis program generates \\configFile{outputfileNoise}{instrument} with the requested characteristics.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise options.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNoise & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovarianceFunction & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~noise & \\hfuzz=500pt \\hyperref[noiseGeneratorType]{noiseGenerator} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~columns & \\hfuzz=500pt uint & \\hfuzz=500pt number of noise series (columns)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SimulateAccelerometer}\\label{SimulateAccelerometer}\nThis program simulate \\file{accelerometer data}{instrument}. The orientation of the accelerometer\nis given by \\configFile{inputfileStarCamera}{instrument} otherwise the celestial reference frame (CRF) is used.\nFor computation of non-conservative forces a \\configFile{satelliteModel}{satelliteModel} is needed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~forces & \\hfuzz=500pt \\hyperref[forcesType]{forces} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{SimulateAccelerometerCoMOffset}\\label{SimulateAccelerometerCoMOffset}\nThis program generates an \\file{accelerometer file}{instrument} containing perturbing accelerations\ndue to a given center of mass (CoM) offset. This includes centrifugal effects,\nEuler forces and the effect of gravity gradients.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt effect of offset\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~applyAngularRate & \\hfuzz=500pt boolean & \\hfuzz=500pt compute effect of centrifugal forces\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~applyAngularAccelerations & \\hfuzz=500pt boolean & \\hfuzz=500pt compute effect of Euler forces\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gradientfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt low order field to estimate the change of the gravity by position adjustement\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt derivation of quaternions by polynomial interpolation of degree n\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~CoMOffsetX & \\hfuzz=500pt double & \\hfuzz=500pt offset [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~CoMOffsetY & \\hfuzz=500pt double & \\hfuzz=500pt offset [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~CoMOffsetZ & \\hfuzz=500pt double & \\hfuzz=500pt offset [m]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{SimulateGradiometer}\\label{SimulateGradiometer}\nThis program simulates error free \\file{gradiometer data}{instrument} along a satellite's orbit.\nThe orientation of the full tensor gradiometer is given by \\configFile{inputfileStarCamera}{instrument}\notherwise the celestial reference frame (CRF) is used.\nThe gravity gradients are given by \\configClass{gravityfield}{gravityfieldType} and\n\\configClass{tides}{tidesType}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGradiometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~tides & \\hfuzz=500pt \\hyperref[tidesType]{tides} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{SimulateKeplerOrbit}\\label{SimulateKeplerOrbit}\nThis program simulates a Keplerian \\file{orbit}{instrument} at a given \\config{timeSeries}\nstarting from the given \\config{integrationConstants}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~integrationConstants & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~kepler & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~majorAxis & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~eccentricity & \\hfuzz=500pt double & \\hfuzz=500pt [-]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inclination & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ascendingNode & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~argumentOfPerigee & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~meanAnomaly & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt integration constants are valid at this epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionAndVelocity & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~position0x & \\hfuzz=500pt double & \\hfuzz=500pt [m] in CRF\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~position0y & \\hfuzz=500pt double & \\hfuzz=500pt [m] in CRF\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~position0z & \\hfuzz=500pt double & \\hfuzz=500pt [m] in CRF\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~velocity0x & \\hfuzz=500pt double & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~velocity0y & \\hfuzz=500pt double & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~velocity0z & \\hfuzz=500pt double & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt integration constants are valid at this epoch\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SimulateOrbit}\\label{SimulateOrbit}\nThis program integrates an \\file{orbit}{instrument} from a given force function (dynamic orbit).\nThe force functions are given by \\configClass{forces}{forcesType}.\nFor computation of non-conservative forces a \\file{satelliteModel}{satelliteModel} is needed.\nThe integration method must be selected with \\configClass{propagator}{orbitPropagatorType}.\nBecause the orbit data are calculated in the celestial reference frame (CRF) you need\n\\configClass{earthRotation}{earthRotationType} to transform the force function\nfrom the terrestrial reference frame (TRF).\nThe integration start and end time, as well as the sampling, are derived from\nthe \\config{timeSeries} option. It is possible to integrate the arc in \\config{reverse},\nwhere the initial conditions are assumed to be met at the end time of the \\config{timeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt orbit file to be written.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt satellite macro model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt time points for simulated orbit epochs.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~integrationConstants & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~kepler & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~majorAxis & \\hfuzz=500pt double & \\hfuzz=500pt [m]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~eccentricity & \\hfuzz=500pt double & \\hfuzz=500pt [-]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inclination & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ascendingNode & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~argumentOfPerigee & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~meanAnomaly & \\hfuzz=500pt angle & \\hfuzz=500pt [degree]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionAndVelocity & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~position0x & \\hfuzz=500pt double & \\hfuzz=500pt [m] in CRF\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~position0y & \\hfuzz=500pt double & \\hfuzz=500pt [m] in CRF\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~position0z & \\hfuzz=500pt double & \\hfuzz=500pt [m] in CRF\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~velocity0x & \\hfuzz=500pt double & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~velocity0y & \\hfuzz=500pt double & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~velocity0z & \\hfuzz=500pt double & \\hfuzz=500pt [m/s]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~file & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt only epoch at timeStart is used\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~margin & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] used when finding initial epoch in orbitFile\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~propagator & \\hfuzz=500pt \\hyperref[orbitPropagatorType]{orbitPropagator} & \\hfuzz=500pt orbit propagation method.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~forces & \\hfuzz=500pt \\hyperref[forcesType]{forces} & \\hfuzz=500pt considered in orbit propagation.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~reverse & \\hfuzz=500pt boolean & \\hfuzz=500pt start integration at last epoch in timeSeries, going backward in time.\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SimulateSatelliteTracking}\\label{SimulateSatelliteTracking}\nThis program simulates \\file{tracking data}{instrument} (range, range-rate, range-accelerations)\nbetween 2 satellites. The range is given by\n\\begin{equation}\n\\rho(t) = \\left\\lVert{\\M r_B(t) - \\M r_A(t)}\\right\\rVert = \\M e_{AB}(t)\\cdot\\M r_{AB}(t),\n\\end{equation}\nwith $\\M r_{AB} = \\M r_B - \\M r_A$ and the unit vector in line of sight (LOS) direction\n\\begin{equation}\\label{sst.los}\n\\M e_{AB} = \\frac{\\M r_{AB}}{\\left\\lVert{\\M r_{AB}}\\right\\rVert}=\\frac{\\M r_{AB}}{\\rho}.\n\\end{equation}\nRange-rates~$\\dot{\\rho}$ and range accelrations~$\\ddot{\\rho}$ are obtained by differentation\n\\begin{equation}\\label{obsRangeRate}\n\\dot{\\rho}  = \\M e_{AB}\\cdot\\dot{\\M r}_{AB} + \\dot{\\M e}_{AB}\\cdot\\M r_{AB}\n            = \\M e_{AB}\\cdot\\dot{\\M r}_{AB},\n\\end{equation}\n\\begin{equation}\\label{obsRangeAccl}\n\\begin{split}\n\\ddot{\\rho} &= \\M e_{AB}\\cdot\\ddot{\\M r}_{AB} +\\dot{\\M e}_{AB}\\cdot\\dot{\\M r}_{AB}\n            = \\M e_{AB}\\cdot\\ddot{\\M r}_{AB} +\n   \\frac{1}{\\rho}\\left(\\dot{\\M r}_{AB}^2-\\dot{\\rho}^2\\right). \\\\\n\\end{split}\n\\end{equation}\nwith the derivative of the unit vector\n\\begin{equation}\n\\dot{\\M e}_{AB}=\\frac{d}{dt}\\left(\\frac{\\M r_{AB}}{\\rho}\\right)\n=\\frac{\\dot{\\M r}_{AB}}{\\rho}-\\frac{\\dot{\\rho}\\cdot\\M r_{AB}}{\\rho^2}\n=\\frac{1}{\\rho}\\left({\\dot{\\M r}_{AB}-\\dot{\\rho}\\cdot\\M e_{AB}}\\right).\n\\end{equation}\nThe \\configFile{inputfileOrbit}{instrument}s must contain positions, velocities, and acceleration\n(see \\program{OrbitAddVelocityAndAcceleration}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{SimulateStarCamera}\\label{SimulateStarCamera}\nThis program simulates \\file{star camera}{instrument} measurements at each satellite's position.\nThe satellite's orientation follows a local orbit frame with the x-axis in along track (along velocity),\ny-axis is cross track (normal to position and velocity vector) and z-axis pointing nadir (negative position vector).\nAs for non circular orbit the position and velocity are not exact normal, the default is the x-axis to be exact\nalong velocity and the z-axis forms a right hand system (not exact nadir) or with \\config{nadirPointing} the z-axis\nis exact nadir and x-axis approximates along.\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation from satellite to inertial frame (x: along, y: cross, z: nadir)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt position and velocity defines the orientation of the satellite at each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~nadirPointing & \\hfuzz=500pt boolean & \\hfuzz=500pt false: exact along and nearly nadir, true: nearly along and exact nadir\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{SimulateStarCameraGnss}\\label{SimulateStarCameraGnss}\nThis program simulates \\file{star camera}{instrument} measurements at each satellite position\nof \\configFile{inputfileOrbit}{instrument}.\nThe resulting rotation matrices rotate from body frame to inertial frame. The body frame refers\nto the IGS-specific (not the manufacturer-specific) body frame, as described by\n\\href{https://doi.org/10.1016/j.asr.2015.06.019}{Montenbruck et al. (2015)}.\nThe \\configFile{inputfileOrbit}{instrument} must contain velocities\n(use \\program{OrbitAddVelocityAndAcceleration} if needed).\n\nInformation about the attitude mode(s) used by the GNSS satellite may be provided via\n\\configFile{inputfileAttitudeInfo}{instrument}. This file can be created with\n\\program{GnssAttitudeInfoCreate}. It contains one or more time-dependent entries,\neach defining the default attitude mode, the attitude modes used around orbit noon and\nmidnight, and some parameters required by the various modes.\nIf no \\configFile{inputfileAttitudeInfo}{instrument} is selected, the program defaults\nto a nominal yaw-steering attitude model.\nA sufficiently high \\config{modelingResolution} ensures that the attitude behavior is modeled properly\nat all times.\n\nThe attitude behavior is defined by the respective mode. Here is a list of the supported\nmodes with a brief explanation and references:\n\\begin{itemize}\n\\item \\textbf{nominalYawSteering}:\n      Yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) [1]\n\\item \\textbf{orbitNormal}:\n      Keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) [1]\n\\item \\textbf{catchUpYawSteering}:\n      Yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) [2, 3]\n\\item \\textbf{shadowMaxYawSteeringAndRecovery}:\n      Yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight)) [2]\n\\item \\textbf{shadowMaxYawSteeringAndStop}:\n      Yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached,\n      then stop (e.g. GLO-M (midnight)) [4]\n\\item \\textbf{shadowConstantYawSteering}:\n      Yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight)) [3]\n\\item \\textbf{centeredMaxYawSteering}:\n      Yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) [4, 8]\n\\item \\textbf{smoothedYawSteering1}:\n      Yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) [5]\n\\item \\textbf{smoothedYawSteering2}:\n      Yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) [5, 6]\n\\item \\textbf{betaDependentOrbitNormal}:\n      Switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) [7, 8]\n\\end{itemize}\n\n\\fig{!hb}{0.9}{gnssAttitudeModes}{fig:gnssAttitudeModes1}{Overview of attitude modes used by GNSS satellites}\n\nSee \\program{GnssAttitudeInfoCreate} for more details on which satellite uses which attitude modes\nand the required parameters for each mode.\n\nReferences for the attitude modes:\n\\begin{enumerate}\n\\item \\href{https://doi.org/10.1016/j.asr.2015.06.019}{Montenbruck et al. (2015)}\n\\item \\href{https://doi.org/10.1007/s10291-008-0092-1}{Kouba (2009)}\n\\item \\href{https://doi.org/10.1007/s10291-016-0562-9}{Kuang et al. (2017)}\n\\item \\href{https://doi.org/10.1016/j.asr.2010.09.007}{Dilssner et al. (2011)}\n\\item \\url{https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3}\n\\item \\href{https://doi.org/10.1007/s10291-018-0783-1}{Wang et al. (2018)}\n\\item \\href{https://doi.org/10.1017/S0373463318000103}{Li et al. (2018)}\n\\item \\url{https://qzss.go.jp/en/technical/qzssinfo/index.html}\n\\end{enumerate}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation from body frame to CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt attitude is modeled based on this orbit\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAttitudeInfo & \\hfuzz=500pt filename & \\hfuzz=500pt attitude modes used by the satellite and respective parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt polynomial degree for orbit interpolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~modelingResolution & \\hfuzz=500pt double & \\hfuzz=500pt [s] resolution for attitude model evaluation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ephemerides & \\hfuzz=500pt \\hyperref[ephemeridesType]{ephemerides} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~eclipse & \\hfuzz=500pt \\hyperref[eclipseType]{eclipse} & \\hfuzz=500pt model to determine if satellite is in Earth's shadow\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SimulateStarCameraGrace}\\label{SimulateStarCameraGrace}\nSimulates \\file{star camera data}{instrument} of the two GRACE satellites.\n\\begin{itemize}\n\\item x: the antenna center pointing to the other satellite.\n\\item y: normal to line of sight and the radial direction.\n\\item z: forms a right handed system.\n\\end{itemize}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit1 & \\hfuzz=500pt filename & \\hfuzz=500pt position define the orientation of the satellite at each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit2 & \\hfuzz=500pt filename & \\hfuzz=500pt position define the orientation of the satellite at each epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~antennaCenters & \\hfuzz=500pt choice & \\hfuzz=500pt KBR antenna phase center\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1X & \\hfuzz=500pt double & \\hfuzz=500pt x-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1Y & \\hfuzz=500pt double & \\hfuzz=500pt y-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center1Z & \\hfuzz=500pt double & \\hfuzz=500pt z-coordinate of antenna position in SRF [m] for GRACEA\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2X & \\hfuzz=500pt double & \\hfuzz=500pt x-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2Y & \\hfuzz=500pt double & \\hfuzz=500pt y-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~center2Z & \\hfuzz=500pt double & \\hfuzz=500pt z-coordinate of antenna position in SRF [m] for GRACEB\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~file & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputAntennaCenters & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SimulateStarCameraSentinel1}\\label{SimulateStarCameraSentinel1}\nThis program simulates \\file{star camera}{instrument} measurements at each satellite's position for the Sentinel 1A satellite.\nThe \\configFile{inputfileOrbit}{instrument} must contain positions and velocities (see \\program{OrbitAddVelocityAndAcceleration}).\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt position and velocity defines the orientation of the satellite at each epoch\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{SimulateStarCameraTerrasar}\\label{SimulateStarCameraTerrasar}\nThis program simulates \\configFile{outputfileStarCamera}{instrument} measurements at each satellite's position for the Terrasar satellite.\nThe \\configFile{inputfileOrbit}{instrument} must contain positions and velocities (see \\program{OrbitAddVelocityAndAcceleration}).\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n\nH. Fiedler, E. Boerner, J. Mittermayer and G. Krieger,\nTotal zero Doppler Steering-a new method for minimizing the Doppler centroid,\nin IEEE Geoscience and Remote Sensing Letters, vol. 2, no. 2, pp. 141-145, April 2005, \\url{https://www.doi.org/10.1109/LGRS.2005.844591}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation from satellite to inertial frame (x: along, y: cross, z: nadir)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt position and velocity defines the orientation of the satellite at each epoch\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: Slr}\n\\subsection{SlrProcessing}\\label{SlrProcessing}\nThis program processes SLR normal point or full rate observations. It calculates the linearized observation equations,\naccumulates them into a system of normal equations and solves it.\n\nTo calculate observation equations from the passes, the model parameters or unknown parameters need to be\ndefined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined\n\\configClass{parametrization}{slrParametrizationType}.\nSome of the \\configClass{parametrization}{slrParametrizationType} also include a priori models.\n\nLastly it is required to define the process flow of the SLR processing. This is accomplished\nwith a list of \\configClass{processingSteps}{slrProcessingStepType}.\nEach step is processed consecutively. Some steps allow the selection of parameters, station, or satellites,\nwhich affects all subsequent steps.\n\nThe \\configClass{timeSeries}{timeSeriesType} is used to precompute Earth rotation and station displacements\nwith a uniform sampling. In a second step these values are interpolated to the observation epochs.\nA sampling of about 10 minutes should be adequate.\n\nIt should be noted that GROOPS uses GPS time format, but normal point/full rate data files and CPF files, provided by ILRS data centers\nare given in UTC time format.\n%See also \\program{SlrSimulation}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt defines station movements and earth rotation epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~satellite & \\hfuzz=500pt \\hyperref[slrSatelliteGeneratorType]{slrSatelliteGenerator} & \\hfuzz=500pt satellites\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~station & \\hfuzz=500pt \\hyperref[slrStationGeneratorType]{slrStationGenerator} & \\hfuzz=500pt ground station network\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt apriori earth rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~parametrization & \\hfuzz=500pt \\hyperref[slrParametrizationType]{slrParametrization} & \\hfuzz=500pt models and parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~processingStep & \\hfuzz=500pt \\hyperref[slrProcessingStepType]{slrProcessingStep} & \\hfuzz=500pt steps are processed consecutively\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: System}\n\\subsection{FileConvert}\\label{FileConvert}\nConverts GROOPS file between different file formats (ASCII, XML, JSON, binary),\nsee \\reference{file formats}{general.fileFormat} for details.\nWith an additional extension of '.gz' files are directly compressed and uncompressed.\nIt prints also some information about the content.\nTherefore it can be used to get an idea about the content of binary files.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{FileCreateDirectories}\\label{FileCreateDirectories}\nCreates the directory and parent directories as needed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~directory & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{FileMove}\\label{FileMove}\nMove/rename file or directory. If the \\config{outputfile} is an existing directory\nthe \\config{inputfile} is moved into it.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt target name or directory for the move/rename\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{FileRemove}\\label{FileRemove}\nRemove files or directories.\nDeletes also the content recursivley if one of \\config{files} is a directory.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~files & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{FileTextCreate}\\label{FileTextCreate}\nCreate text \\config{outputfile} containing \\config{line}s.\nThis program can be a powerful tool,\nif the \\config{line} is repeated with a \\configClass{loop}{loopType}\ntogether with the \\reference{text parser}{general.parser:text}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~line & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GroupPrograms}\\label{GroupPrograms}\nRuns \\config{program}s in a group, which can be used to structure a config file.\nIf \\config{catchErrors} is enabled and an error occurs, the remaining \\config{program}s\nare skipped and execution continues with \\config{errorProgram}s, in case any are defined.\nOtherwise an exception is thrown.\n\nThe \\config{silently} option disables the screen ouput of the \\config{program}s.\nWith \\config{outputfileLog} a log file is written for this group additional to a global log file.\nThis might be helpful within \\program{LoopPrograms} with parallel iterations.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileLog & \\hfuzz=500pt filename & \\hfuzz=500pt additional log file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~silently & \\hfuzz=500pt boolean & \\hfuzz=500pt without showing the output.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~program & \\hfuzz=500pt programType & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~catchErrors & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~errorProgram & \\hfuzz=500pt programType & \\hfuzz=500pt executed if an error occured\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{IfPrograms}\\label{IfPrograms}\nRuns a list of \\config{program}s if a \\configClass{condition}{conditionType} is met.\nOtherwise \\config{elseProgram}s are executed.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~condition & \\hfuzz=500pt \\hyperref[conditionType]{condition} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~program & \\hfuzz=500pt programType & \\hfuzz=500pt executed if condition evaluates to true\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~elseProgram & \\hfuzz=500pt programType & \\hfuzz=500pt executed if condition evaluates to false\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{LoopPrograms}\\label{LoopPrograms}\nThis program runs a list of programs in a \\configClass{loop}{loopType}.\n\nIf \\config{continueAfterError}=\\verb|yes| and an error occurs, the remaining programs in the current iteration\nare skipped and the loop continues with the next iteration. Otherwise an exception is thrown.\n\nIf this program is executed on multiple processing nodes, the iterations can be computed in parallel,\nsee \\reference{parallelization}{general.parallelization}. The first process serves as load balancer\nand the other processes are assigned to iterations according to \\config{processCountPerIteration}.\nFor example, running a loop containing three iterations on 13 processes with \\config{processCountPerIteration}=\\verb|4|,\nruns the three iterations in parallel, with each iteration being assigned four processes.\nWith \\config{parallelLog}=\\verb|yes| all processes write output to screen and the log file.\nAs the output can be quite confusing in this case, running \\program{GroupPrograms} with an extra \\config{outputfileLog}\nfor each iteration (use the loop variables for the name of the log files) might be helpful.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~loop & \\hfuzz=500pt \\hyperref[loopType]{loop} & \\hfuzz=500pt subprograms are called for every iteration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~continueAfterError & \\hfuzz=500pt boolean & \\hfuzz=500pt continue with next iteration after error, otherwise throw exception\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~processCountPerIteration & \\hfuzz=500pt uint & \\hfuzz=500pt 0: use all processes for each iteration\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~parallelLog & \\hfuzz=500pt boolean & \\hfuzz=500pt write to screen/log file from all processing nodes in parallelized loops\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~program & \\hfuzz=500pt programType & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{RunCommand}\\label{RunCommand}\nExecute system \\config{command}s. If \\config{executeParallel} is set and\nmultiple \\config{command}s are given they are executed in parallel at\ndistributed nodes, otherwise they are executed consecutively at master node only.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~command & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~silently & \\hfuzz=500pt boolean & \\hfuzz=500pt without showing the output.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~continueAfterError & \\hfuzz=500pt boolean & \\hfuzz=500pt continue with next command after error, otherwise throw exception\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~executeParallel & \\hfuzz=500pt boolean & \\hfuzz=500pt execute several commands in parallel\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\section{Programs: Conversion}\n\\subsection{Accelerometer2GraceL1b}\\label{Accelerometer2GraceL1b}\nThis program converts accelerometer data from the \\file{instrument file (ACCELEROMETER)}{instrument}\nformat into GRACE SDS format.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, \\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt ACT1B\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileHeader & \\hfuzz=500pt filename & \\hfuzz=500pt YAML Header, \\{epochmin\\}, \\{epochmax\\}, \\{epochcount\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAngularAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileFlags & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(qualflg, acl\\_res.x, acl\\_res.y, acl\\_res.z)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~satelliteId & \\hfuzz=500pt string & \\hfuzz=500pt A, B, C or D\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{BerneseKinematic2Orbit}\\label{BerneseKinematic2Orbit}\nRead kinematic orbits in Bernese format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt from TRF to CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Champ2AccStar}\\label{Champ2AccStar}\nThis program reads in CHAMP accelerometer and star camera data given in the special CHAMP format.\nIn case of CHAMP accelerometer and star camera data is both stored in one file.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularAcceleration & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Champ2Orbit}\\label{Champ2Orbit}\nThis program reads in CHAMP precise science orbits in the special CHORB format.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Cosmic2OrbitStar}\\label{Cosmic2OrbitStar}\nThis program reads in cosmic orbit and star camera data given in the CHAMP format.\nIn case of cosmic orbit and star camera data is stored in one file.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Cpf2Orbit}\\label{Cpf2Orbit}\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html}{CPF file}\nand writes an \\file{instrument file (ORBIT)}{instrument}.\n\nThe time format of the CPF file is UTC.\nThe coordinate system used in the CPF format is usually represented in TRF.\nIf \\configClass{earthRotation}{earthRotationType} is provided the data are transformed\nfrom terrestrial (TRF) to celestial reference frame (CRF).\n\nSee also \\program{Orbit2Cpf}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt SLR CPF file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Crd2NormalPoints}\\label{Crd2NormalPoints}\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/formats/crd.html}{CRD file}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding normal point data like range, accuracy, redundancy, wavelength and window size.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalPoints & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMeteorological & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSlrData & \\hfuzz=500pt filename & \\hfuzz=500pt SLR CRD files\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Cstg2NormalPoints}\\label{Cstg2NormalPoints}\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html}{CSTG file} provided by the \\href{https://ilrs.gsfc.nasa.gov/}{ILRS}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding normal point data like range, accuracy, redundancy, wavelength and window size.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalPoints & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMeteorological & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSlrData & \\hfuzz=500pt filename & \\hfuzz=500pt SLR CSTG file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonAdmittance2SupplementaryFiles}\\label{DoodsonAdmittance2SupplementaryFiles}\nThe publication of an ocean tide model includes not only the atlas\nin the form of spherical harmonics coefficients,\nbut also the matrix of Doodson multipliers (\\config{outputfileDoodsonMatrix})\nand the \\config{outputfileAdmittanceMatrix}.\n\nThe \\config{outputfileMajorTideList} contains the \\config{fileNames}\nfor each contituent.\nThe required information is taken from the\n\\configFile{inputfileAdmittance}{admittance}.\n\nSee also \\program{DoodsonHarmonics2PotentialCoefficients}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileMajorTideList & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~fileNames & \\hfuzz=500pt filename & \\hfuzz=500pt template for fileList, variables: doodson, name, cossin\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileDoodsonMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAdmittanceMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAdmittance & \\hfuzz=500pt filename & \\hfuzz=500pt interpolation of minor constituents\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonHarmonics2IersPotential}\\label{DoodsonHarmonics2IersPotential}\nConvert doodson harmonics to IERS conventions according to FES2004.\ncf. \\url{ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt according to IERS2010, chapter 6.3.2, footnote 7\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDoodsonHarmoncis & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~header & \\hfuzz=500pt string & \\hfuzz=500pt info for output header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{DoodsonHarmonics2IersWaterHeight}\\label{DoodsonHarmonics2IersWaterHeight}\nConvert doodson harmonics to IERS conventions according to FES2004.\ncf. \\url{ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt according to IERS2010, chapter 6.3.2, footnote 7\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDoodsonHarmoncis & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt to compute Xi phase correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~header & \\hfuzz=500pt string & \\hfuzz=500pt info for output header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt data type of output values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt e.g. from [m] to [cm]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssAntex2AntennaDefinition}\\label{GnssAntex2AntennaDefinition}\nConverts metadata and antenna definitions from the \\href{https://files.igs.org/pub/data/format/antex14.txt}{IGS ANTEX format}.\nto \\configFile{antennaDefinition}{gnssAntennaDefinition}, \\configFile{transmitterInfo}{platform}, and\n\\configFile{transmitterList}{stringList} files for the respective GNSS and for the list of ground station antennas.\n\nThe \\file{transmitterInfo}{platform} files for GLONASS satellites should then be updated using \\program{GnssGlonassFrequencyNumberUpdate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntennaDefinitionStation & \\hfuzz=500pt filename & \\hfuzz=500pt antenna center variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntennaDefinitionTransmitter & \\hfuzz=500pt filename & \\hfuzz=500pt antenna center variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt PRN is appended to file name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterListGps & \\hfuzz=500pt filename & \\hfuzz=500pt list of PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterListGlonass & \\hfuzz=500pt filename & \\hfuzz=500pt list of PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterListGalileo & \\hfuzz=500pt filename & \\hfuzz=500pt list of PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterListBeiDou & \\hfuzz=500pt filename & \\hfuzz=500pt list of PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterListQzss & \\hfuzz=500pt filename & \\hfuzz=500pt list of PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTransmitterListIrnss & \\hfuzz=500pt filename & \\hfuzz=500pt list of PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt ignore older antenna definitions\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~createZeroModel & \\hfuzz=500pt boolean & \\hfuzz=500pt create empty antenna patterns\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssClock2ClockRinex}\\label{GnssClock2ClockRinex}\nConverts GNSS clocks from GROOPS format to \\href{https://files.igs.org/pub/data/format/rinex_clock304.txt}{IGS clock RINEX format}.\nClocks can be provided via \\config{satelliteData} and/or \\config{stationData}.\nObserved signal types are inferred from \\configFile{inputfileSignalBias}{gnssSignalBias}.\nSatellites/stations used as clock references can be provided via \\config{referenceClock}.\n\nSee IGS clock RINEX format description for further details on header information.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileClockRinex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~satelliteData & \\hfuzz=500pt sequence & \\hfuzz=500pt one element per satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt clock instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt PRN (e.g. G23)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationData & \\hfuzz=500pt sequence & \\hfuzz=500pt one element per station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt clock instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePosition & \\hfuzz=500pt filename & \\hfuzz=500pt station position file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt station info file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt station name (e.g. wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comment in header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~program & \\hfuzz=500pt string & \\hfuzz=500pt name of program (for first line)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~institution & \\hfuzz=500pt string & \\hfuzz=500pt name of agency (for first line)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~analysisCenter & \\hfuzz=500pt string & \\hfuzz=500pt name of analysis center\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~differentialCodeBias & \\hfuzz=500pt string & \\hfuzz=500pt program and source for applied differential code bias\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~phaseCenterVariations & \\hfuzz=500pt string & \\hfuzz=500pt program and source for applied phase center variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~referenceClock & \\hfuzz=500pt string & \\hfuzz=500pt identifier of reference satellite/station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~referenceFrame & \\hfuzz=500pt string & \\hfuzz=500pt terrestrial reference frame for the stations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssClockRinex2InstrumentClock}\\label{GnssClockRinex2InstrumentClock}\nThis program converts clocks from the \\href{https://files.igs.org/pub/data/format/rinex_clock304.txt}{IGS clock RINEX format},\nwhich contains the clocks of all satellites and stations in a single file,\ninto an \\file{instrument file (MISCVALUE)}{instrument} for each \\config{identifier}\n(satellite and/or station).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt identifier is appended to each file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileClockRinex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt satellite or station identifier, e.g. G23 or alic\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~intervals & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minEpochsPerInterval & \\hfuzz=500pt uint & \\hfuzz=500pt minimum number of epochs in an interval\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssEop2IgsErp}\\label{GnssEop2IgsErp}\nWrite GNSS Earth orientation parameters to \\href{https://files.igs.org/pub/data/format/erp.txt}{IGS ERP file format}.\n\nRequires polar motion, polar motion rate, dUT1 and LOD parameters in the solution\nvector \\configFile{inputfileSolution}{matrix} and their sigmas in \\configFile{inputfileSigmax}{matrix}.\nSolution usually comes out of \\program{GnssProcessing}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileIgsErp & \\hfuzz=500pt filename & \\hfuzz=500pt IGS ERP file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~epoch & \\hfuzz=500pt sequence & \\hfuzz=500pt e.g. daily solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileParameterNames & \\hfuzz=500pt filename & \\hfuzz=500pt parameter names\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~inputfileTransmitterList & \\hfuzz=500pt filename & \\hfuzz=500pt transmitter PRNs used in solution (used for transmitter count)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileStationList & \\hfuzz=500pt filename & \\hfuzz=500pt stations used in solution (used for station count)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt reference time for epoch\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssGriddedDataTimeSeries2Ionex}\\label{GnssGriddedDataTimeSeries2Ionex}\nConverts TEC maps from GROOPS \\file{gridded data time series}{griddedDataTimeSeries} format\nto IGS \\href{https://files.igs.org/pub/data/format/ionex1.pdf}{IONEX file format}.\n\nCurrently only supports 2D TEC maps.\n\nSee also \\program{GnssIonex2GriddedDataTimeSeries}, \\configClass{IonosphereMap}{gnssParametrizationType:ionosphereMap}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileIonex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt must contain regular grid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression (e.g. data column)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt (empty = use input file time series)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~program & \\hfuzz=500pt string & \\hfuzz=500pt name of program (for first line)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~institution & \\hfuzz=500pt string & \\hfuzz=500pt name of agency (for first line)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt description in header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comment in header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~mappingFunction & \\hfuzz=500pt string & \\hfuzz=500pt see IONEX documentation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~elevationCutoff & \\hfuzz=500pt double & \\hfuzz=500pt see IONEX documentation (0 if unknown)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~observablesUsed & \\hfuzz=500pt string & \\hfuzz=500pt see IONEX documentation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~exponent & \\hfuzz=500pt int & \\hfuzz=500pt factor 10\\textasciicircum{}exponent is applied to all values\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssIonex2GriddedDataTimeSeries}\\label{GnssIonex2GriddedDataTimeSeries}\nConverts TEC maps from IGS \\href{https://files.igs.org/pub/data/format/ionex1.pdf}{IONEX file format}\nto GROOPS \\file{gridded data time series}{griddedDataTimeSeries} format.\n\nCurrently only supports 2D TEC maps.\n\nSee also \\program{GnssGriddedDataTimeSeries2Ionex}, \\configClass{IonosphereMap}{gnssParametrizationType:ionosphereMap}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileIonex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssNormals2Sinex}\\label{GnssNormals2Sinex}\nWrite GNSS data/metadata and \\file{normal equations}{normalEquation} to\n\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}.\n\nNormal equations usually come from \\program{GnssProcessing}\n(e.g. from \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork}).\nMetadata input files include \\configFile{stationInfo/transmitterInfo}{platform}, \\configFile{antennaDefinition}{gnssAntennaDefinition},\nand \\configFile{stationList/transmitterList}{stringList}, see \\program{GnssAntex2AntennaDefinition}.\n\nSee also \\program{Sinex2Normals} and \\program{NormalsSphericalHarmonics2Sinex}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSinexNormals & \\hfuzz=500pt filename & \\hfuzz=500pt full SINEX file including normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSinexCoordinates & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file without normal equations (station coordinates file)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormals & \\hfuzz=500pt filename & \\hfuzz=500pt normal equation matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileApriori & \\hfuzz=500pt filename & \\hfuzz=500pt apriori parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAprioriSigma & \\hfuzz=500pt filename & \\hfuzz=500pt constraint sigmas for apriori parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAprioriMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt normal equation matrix of applied constraints\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~transmitterConstellation & \\hfuzz=500pt sequence & \\hfuzz=500pt transmitter constellation metadata\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransmitterList & \\hfuzz=500pt filename & \\hfuzz=500pt transmitter PRNs used in solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt transmitter info file template\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt transmitter phase centers and variations (ANTEX)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~variablePrn & \\hfuzz=500pt string & \\hfuzz=500pt loop variable for PRNs from transmitter list\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~stations & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationList & \\hfuzz=500pt filename & \\hfuzz=500pt stations contained in normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt station info file template\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt station phase centers and variations (ANTEX)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~variableStationName & \\hfuzz=500pt string & \\hfuzz=500pt loop variable for station names from station list\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationTimeStart & \\hfuzz=500pt time & \\hfuzz=500pt start time for which solution has observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~observationTimeEnd & \\hfuzz=500pt time & \\hfuzz=500pt end time for which solution has observations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt reference time for parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] observation sampling\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~antennaCalibrationModel & \\hfuzz=500pt string & \\hfuzz=500pt e.g. IGS14\\_WWWW (WWWW = ANTEX release GPS week)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sinexHeader & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~agencyCode & \\hfuzz=500pt string & \\hfuzz=500pt identify the agency providing the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt start time of the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt end time of the data \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~observationCode & \\hfuzz=500pt string & \\hfuzz=500pt technique used to generate the SINEX solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~constraintCode & \\hfuzz=500pt string & \\hfuzz=500pt 0: tight constraint, 1: siginficant constraint, 2: unconstrained\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~solutionContent & \\hfuzz=500pt string & \\hfuzz=500pt solution types contained in the SINEX solution (S O E T C A)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt organizitions gathering/alerting the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~contact & \\hfuzz=500pt string & \\hfuzz=500pt Address of the relevant contact. e-mail\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~output & \\hfuzz=500pt string & \\hfuzz=500pt Description of the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~input & \\hfuzz=500pt string & \\hfuzz=500pt Brief description of the input used to generate this solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~software & \\hfuzz=500pt string & \\hfuzz=500pt Software used to generate the file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~hardware & \\hfuzz=500pt string & \\hfuzz=500pt Computer hardware on which above software was run\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileComment & \\hfuzz=500pt filename & \\hfuzz=500pt comments in the comment block from a file (truncated at 80 characters)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comments in the comment block\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssOrbex2StarCamera}\\label{GnssOrbex2StarCamera}\nConverts GNSS satellite attitude from \\href{http://acc.igs.org/misc/proposal_orbex_april2019.pdf}{ORBEX file format}\n(quaternions) to \\file{instrument file (STARCAMERA)}{instrument}.\nThe resulting star camera files contain the rotation from satellite body frame to TRF, or to CRF in case\n\\configClass{earthRotation}{earthRotationType} is provided.\n\nSee also \\program{GnssAttitude2Orbex}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt rotation from body frame to TRF/CRF, identifier is appended to each file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt (empty = all) satellite identifier, e.g. G23 or E05\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotation from TRF to CRF\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssReceiver2RinexObservation}\\label{GnssReceiver2RinexObservation}\nConverts a \\configFile{inputfileGnssReceiver}{instrument} into a\n\\href{https://files.igs.org/pub/data/format/rinex_4.00.pdf}{RINEX} observation file.\nThe \\configFile{inputfileStationInfo}{platform} contains the antenna\nand receiver information for the RINEX header.\nThe \\configClass{useType}{gnssType} and \\configClass{ignoreType}{gnssType} can be used to filter\nthe observation types that will be exported.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileRinexObservation & \\hfuzz=500pt filename & \\hfuzz=500pt RINEX observation file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGnssReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt GNSS instrument file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt antenna and receiver info\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt write comments at begin of header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~observer & \\hfuzz=500pt string & \\hfuzz=500pt header information\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~angency & \\hfuzz=500pt string & \\hfuzz=500pt header information\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~useType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt only use observations that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~ignoreType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt ignore observations that match any of these patterns\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssRinexNavigation2OrbitClock}\\label{GnssRinexNavigation2OrbitClock}\nEvaluates orbit and clock parameters from \\href{https://files.igs.org/pub/data/format/rinex_4.00.pdf}{RINEX} (version 2, 3, and 4)\nnavigation file \\config{inputfileRinex} at epochs given by \\configClass{timeSeries}{timeSeriesType} and writes them to\n\\configFile{outputfileOrbit}{instrument} and \\configFile{outputfileClock}{instrument}, respectively.\n\nOrbits are rotated from TRF (as broadcasted) to CRF via \\configClass{earthRotation}{earthRotationType},\nbut system-specific TRFs (WGS84, PZ-90, etc.) are not aligned to a common TRF.\n\nFurthermore, option is available to remove any satellite ephemeris data that has their satellite flag set to unhealthy.\n\nSee also \\program{OrbitAddVelocityAndAcceleration}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt PRN is appended to file name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt PRN is appended to file name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileRinex & \\hfuzz=500pt filename & \\hfuzz=500pt RINEX navigation file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt orbit and clock evaluation epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt for rotation from TRF to CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~useType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt (e.g. ***G12) only use satellites with PRN that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~ignoreType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt (e.g. ***R**) ignore satellites PRN that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~removeUnhealthySatellites & \\hfuzz=500pt boolean & \\hfuzz=500pt Remove satellite ephemeris that have their sat flags set to unhealthy\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssSignalBias2SinexBias}\\label{GnssSignalBias2SinexBias}\nConvert \\file{GNSS signal biases}{gnssSignalBias} from GROOPS format to \\href{https://files.igs.org/pub/data/format/sinex_bias_100.pdf}{IGS SINEX Bias format}.\nBiases can be provided via \\config{transmitterBiases} and/or \\config{receiverBiases}.\nPhase biases without attribute (e.g. \\verb|L1*|) are automatically expanded so each code\nbias has a corresponding phase bias\n(Example: \\verb|C1C|, \\verb|C1W|, \\verb|L1*| are converted to \\verb|C1C|, \\verb|C1W|, \\verb|L1C|, \\verb|L1W|).\n\nTime-variable biases (e.g. GPS L5 satellite phase bias) can be provided via \\config{timeVariableBias}.\nTheir time span will be based on the provided epochs ($t \\pm \\Delta t / 2$).\nThe slope of the bias can be optionally provided in the second data column.\n\nIf GLONASS receiver biases depend on frequency number, those must be defined in \\configFile{inputfileTransmitterInfo}{platform}\nto get the correct PRN/SVN assignment to the biases.\n\nSee IGS SINEX Bias format description for further details on header information.\n\nSee also \\program{GnssSinexBias2SignalBias} and \\program{GnssBiasClockAlignment}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSinexBias & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileTransmitterInfo & \\hfuzz=500pt filename & \\hfuzz=500pt one file per satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~transmitterBiases & \\hfuzz=500pt sequence & \\hfuzz=500pt one element per satellite\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~timeVariableBias & \\hfuzz=500pt sequence & \\hfuzz=500pt one entry per time variable bias type\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, bias [m], (biasSlope [m/s])\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt bias type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt PRN or station name (e.g. G23 or wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~receiverBiases & \\hfuzz=500pt sequence & \\hfuzz=500pt one element per station\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt signal bias file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~timeVariableBias & \\hfuzz=500pt sequence & \\hfuzz=500pt one entry per time variable bias type\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt columns: mjd, bias [m], (biasSlope [m/s])\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~type & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt bias type\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt PRN or station name (e.g. G23 or wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~agencyCode & \\hfuzz=500pt string & \\hfuzz=500pt identify the agency providing the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~fileAgencyCode & \\hfuzz=500pt string & \\hfuzz=500pt identify the agency creating the file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt start time of the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt end time of the data \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~biasMode & \\hfuzz=500pt choice & \\hfuzz=500pt absolute or relative bias estimates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~absolute & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~relative & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~observationSampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~intervalLength & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] interval for bias parameter representation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~determinationMethod & \\hfuzz=500pt string & \\hfuzz=500pt determination method used to generate the bias results (see SINEX Bias format description)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~receiverClockReferenceGnss & \\hfuzz=500pt string & \\hfuzz=500pt (G, R, E, C) reference GNSS used for receiver clock estimation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~satelliteClockReferenceObservables & \\hfuzz=500pt string & \\hfuzz=500pt one per system, reference code observable on first and second frequency (RINEX3 format)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt organization gathering/altering the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~contact & \\hfuzz=500pt string & \\hfuzz=500pt contact name and/or email address\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~input & \\hfuzz=500pt string & \\hfuzz=500pt brief description of the input used to generate this solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~output & \\hfuzz=500pt string & \\hfuzz=500pt description of the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~software & \\hfuzz=500pt string & \\hfuzz=500pt software used to generate the file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~hardware & \\hfuzz=500pt string & \\hfuzz=500pt computer hardware on which above software was run\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comments in the comment block\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssSinexBias2SignalBias}\\label{GnssSinexBias2SignalBias}\nConverts GNSS signal biases from \\href{https://files.igs.org/pub/data/format/sinex_bias_100.pdf}{IGS SINEX Bias format}\nto \\file{GnssSignalBias format}{gnssSignalBias}.\n\nOnly satellite observable-specific signal biases (OSB) are supported at the moment.\nIf multiple entries exist for the same bias, the weighted average (based on time span) of all entries is used.\nTime-variable biases are not supported at the moment.\n\nSee also \\program{GnssSignalBias2SinexBias}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSignalBias & \\hfuzz=500pt filename & \\hfuzz=500pt identifier is appended to file name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinexBias & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileGlonassSignalDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt GLONASS frequency number mapping\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt (empty = all) satellite PRN, e.g. G23 or E05\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssStationLog2Platform}\\label{GnssStationLog2Platform}\nConverts \\href{https://files.igs.org/pub/station/general/blank.log}{IGS station log format} or\n\\href{https://files.igs.org/pub/station/general/blank_v2.0.log}{IGS station log format v2.0} to \\configFile{outputfileStationPlatform}{platform}.\n\nIf \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition} is provided, station log data is cross-checked with the given antenna definitions.\nCross-checking station log data with a \\href{https://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX file} is\npossible with \\program{CheckStationsPlatformsWithSinex}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStationPlatform & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationLog & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt used to check antennas\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssTroposphere2TropoSinex}\\label{GnssTroposphere2TropoSinex}\nConvert GNSS troposphere data from GROOPS format as estimated by \\program{GnssProcessing}\nto \\href{https://files.igs.org/pub/data/format/sinex_tro_v2.00.pdf}{IGS SINEX TRO} format.\n\nFor each station folling files are needed:\n\\begin{itemize}\n  \\item \\configFile{inputfileStationInfo}{platform},\n  \\item \\configFile{inputfileTroposphereData}{instrument}(MISVALUES),\n  \\item optional standard deviations with \\configFile{inputfileTroposphereSigmas}{instrument}(MISVALUES),\n  \\item \\configFile{inputfilePosition}{instrument}(VECTOR3D).\n\\end{itemize}\nThe \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition} contains antenna center offsets and variations\nof all used antennas. Created via \\program{GnssAntex2AntennaDefinition} or \\program{GnssAntennaDefinitionCreate}.\n\nFor considering the geoid height use \\configFile{inputfileGriddedGeoidHeight}{griddedData}\nas it might be computed by \\program{Gravityfield2GriddedData}.\nThe height closest to the station's position is used in each case.\n\nSee also \\program{GnssProcessing}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTropoSinex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~station & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt platform file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTroposphereData & \\hfuzz=500pt filename & \\hfuzz=500pt Troposphere data estimates (columns: mjd, trodry, trowet, tgndry, tgnwet, tgedry, tgewet)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileTroposphereSigmas & \\hfuzz=500pt filename & \\hfuzz=500pt Troposphere data sigmas (columns: mjd, sigma\\_trowet, sigma\\_tgnwet, sigma\\_tgewet)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfilePosition & \\hfuzz=500pt filename & \\hfuzz=500pt Precise station position (columns: mjd, x, y, z [m in TRF])\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAntennaDefinition & \\hfuzz=500pt filename & \\hfuzz=500pt station phase centers and variations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileGriddedGeoidHeight & \\hfuzz=500pt filename & \\hfuzz=500pt value closest to the station's position is used in each case\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~dataSamplingInterval & \\hfuzz=500pt double & \\hfuzz=500pt [sec] GNSS data sampling rate\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~tropoSamplingInterval & \\hfuzz=500pt double & \\hfuzz=500pt [sec] Tropospheric parameter sampling interval\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~tropoModelingMethod & \\hfuzz=500pt string & \\hfuzz=500pt Tropospheric estimation method: Filter, Smoother, Least Squares, Piece-Wise Linear Interpolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~aPrioriTropoModel & \\hfuzz=500pt string & \\hfuzz=500pt A priori tropospheric model used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~tropoMappingFunction & \\hfuzz=500pt string & \\hfuzz=500pt Name of mapping function used for hydrostatic and wet delay\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gradientMappingFunction & \\hfuzz=500pt string & \\hfuzz=500pt Name of mapping function used for gradients\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~metDataSource & \\hfuzz=500pt string & \\hfuzz=500pt source of surface meteorological observations used (see format desc.)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~observationWeighting & \\hfuzz=500pt string & \\hfuzz=500pt observation weighting model applied\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~elevationCutoff & \\hfuzz=500pt double & \\hfuzz=500pt [deg]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~gnssSystems & \\hfuzz=500pt string & \\hfuzz=500pt G=GPS, R=GLONASS, E=Galileo, C=BeiDou\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeSystem & \\hfuzz=500pt string & \\hfuzz=500pt G (GPS) or UTC\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~oceanTideModel & \\hfuzz=500pt string & \\hfuzz=500pt Name of applied Ocean tide loading model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~atmosphericTideModel & \\hfuzz=500pt string & \\hfuzz=500pt Name of applied Atmospheric tide loading model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~geoidModel & \\hfuzz=500pt string & \\hfuzz=500pt Geoid model name for undulation values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~systemCode & \\hfuzz=500pt string & \\hfuzz=500pt Terrestrial reference system code\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~remark & \\hfuzz=500pt string & \\hfuzz=500pt Remark used to identify the origin of the coordinates (AC acronym)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~antennaCalibrationModel & \\hfuzz=500pt string & \\hfuzz=500pt e.g. IGS20\\_WWWW (WWWW = ANTEX release GPS week)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sinexTroHeader & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~agencyCode & \\hfuzz=500pt string & \\hfuzz=500pt Identify the agency providing the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt Start time of the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt End time of the data \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~observationCode & \\hfuzz=500pt string & \\hfuzz=500pt Technique used to generate the SINEX solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~solutionContents & \\hfuzz=500pt string & \\hfuzz=500pt Marker name if single station, MIX if multiple stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt Organizitions gathering/alerting the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~output & \\hfuzz=500pt string & \\hfuzz=500pt Description of the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~contact & \\hfuzz=500pt string & \\hfuzz=500pt Address of the relevant contact e-mail\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~software & \\hfuzz=500pt string & \\hfuzz=500pt Software used to generate the file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~hardware & \\hfuzz=500pt string & \\hfuzz=500pt Computer hardware on which above software was run\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~input & \\hfuzz=500pt string & \\hfuzz=500pt Brief description of the input used to generate this solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~versionNumber & \\hfuzz=500pt string & \\hfuzz=500pt Unique identifier of the product, same as in file name, e.g. 000\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileComment & \\hfuzz=500pt filename & \\hfuzz=500pt comments in the comment block from a file (truncated at 80 characters per line)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comments in the comment block\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GoceXml2Gradiometer}\\label{GoceXml2Gradiometer}\nRead ESA XML GOCE Data.\nThe \\config{outputfileGradiometer} is written as \\file{instrument file (GRADIOMETER)}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGradiometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GoceXml2Orbit}\\label{GoceXml2Orbit}\nRead ESA XML GOCE Data.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotation from TRF to CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GoceXml2StarCamera}\\label{GoceXml2StarCamera}\nRead ESA XML GOCE Data.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GoceXmlEggNom1b}\\label{GoceXmlEggNom1b}\nRead ESA XML GOCE Data.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGradiometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularRate & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularAcc & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Grace2PotentialCoefficients}\\label{Grace2PotentialCoefficients}\nThis program converts potential coefficients from the GRACE SDS format\ninto \\file{potential coefficients file}{potentialCoefficients}.\nThe program supports file formats for RL04 to RL06.\n\nWithin the program, the variables \\verb|epochStart|, \\verb|epochEnd| and \\verb|epochMid|\nare populated with the corresponding time-stamps in the file.\nThese can be used in to \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\nto auto-generate the file name.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt variables: epochStart, epochEnd, epochMid\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceAccelerometer2L1bAscii}\\label{GraceAccelerometer2L1bAscii}\nConvert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAscii & \\hfuzz=500pt filename & \\hfuzz=500pt ASCII outputfile\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt GROOPS acceleromter file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~satelliteIdentifier & \\hfuzz=500pt string & \\hfuzz=500pt satellite identifier (A or B for GRACE, C or D for GRACE-FO)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~globalAttributes & \\hfuzz=500pt string & \\hfuzz=500pt additional attributes as 'key: value' pairs\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceAod2DoodsonHarmonics}\\label{GraceAod2DoodsonHarmonics}\nThis program converts the atmospheric and ocean tidal products (AOD1B)\nfrom the GRACE SDS format into \\configFile{outputfileDoodsonHarmonics}{doodsonHarmonic}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDoodsonHarmonics & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt to compute Xi phase correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceAod2TimeSplines}\\label{GraceAod2TimeSplines}\nThis program converts the atmospheric and ocean de-aliasing product (AOD1B)\nfrom the GRACE SDS format into \\file{time spline files}{timeSplinesGravityField}.\nMultiple \\config{inputfile}s must be given in the correct time order.\nA linear method is assumed for the interpolation between the given points in time.\n\nThe GRACE SDS format is described in \"AOD1B Product Description Document\"\ngiven at \\url{http://podaac.jpl.nasa.gov/grace/documentation.html}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileDealiasing & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAtmosphere & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOcean & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileBottomPressure & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileMisc & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceCoefficients2BlockMeanTimeSplines}\\label{GraceCoefficients2BlockMeanTimeSplines}\nThis program converts potential coefficients from the GRACE SDS RL06 format\ninto \\configFile{outputfileTimeSplines}{timeSplinesGravityField}.\n\nThe \\configFile{outputfileTimeSeries}{instrument} contains the mid points\nof non-empty intervals and \\configFile{outputfileTimeIntervals}{instrument}\ncontains the monthly interval boundaries from first to last solution.\n\nThe output will always be monthly block means. If the SDS solutions do vary or overlap,\nthe nearest solution in terms of reference epoch is used.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSplines & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTimeSplinesCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt only the variances are saved\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt mid points of non-empty intervals\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTimeIntervals & \\hfuzz=500pt filename & \\hfuzz=500pt monthly interval boundaries from first to last solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1a2Accelerometer}\\label{GraceL1a2Accelerometer}\nThis program converts Level-1A accelerometer data (ACC1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in \\verb|GRACEiolib.h| given at\n\\url{http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz}.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER in SRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER in SRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt ACC1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1a2SatelliteTracking}\\label{GraceL1a2SatelliteTracking}\nThis program converts Level-1A satellite tracking data (KBR1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in \\verb|GRACEiolib.h| given at\n\\url{http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz}.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(ant\\_id, K\\_phase, Ka\\_phase, K\\_SNR, Ka\\_SNR)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt KBR1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1a2StarCamera}\\label{GraceL1a2StarCamera}\nThis program converts orientation data measured by the star cameras\nfrom the GRACE Level-1A format (SCA1A) to the GROOPS instrument file format.\nFor further information see \\program{GraceL1a2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera1 & \\hfuzz=500pt filename & \\hfuzz=500pt STARCAMERA1A, head 1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera2 & \\hfuzz=500pt filename & \\hfuzz=500pt STARCAMERA1A, head 2\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt SCA1A, !GRACE-FO is not working!\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1a2Temperature}\\label{GraceL1a2Temperature}\nThis program converts Level-1A temperature measurments (HRT1B or HRT1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in GRACE given at \\url{http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz}.\nMultiple \\config{inputfile}s must be given in the correct time order.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTemperature & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt HRT1B or HRT1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2AccHousekeeping}\\label{GraceL1b2AccHousekeeping}\nThis program converts ACC housekeeping data (AHK1B or AHK1A) from the GRACE SDS format into \\file{instrument file (ACCHOUSEKEEPING)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileAccHousekeeping & \\hfuzz=500pt filename & \\hfuzz=500pt ACCHOUSEKEEPING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt AHK1B or AHK1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Accelerometer}\\label{GraceL1b2Accelerometer}\nThis program converts accelerometer data (ACC1B or ACT1B) from the GRACE SDS format into \\file{instrument file (ACCELEROMETER)}{instrument}.\n\nMultiple \\config{inputfile}s must be given in the correct time order.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n\nThe GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\"\ngiven at \\url{https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAngularAccelerometer & \\hfuzz=500pt filename & \\hfuzz=500pt ACCELEROMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileFlags & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(qualflg, acl\\_res.x, acl\\_res.y, acl\\_res.z)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt ACC1B or ACT1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2ClockOffset}\\label{GraceL1b2ClockOffset}\nThis program converts clock data (CLK1B or LLK1B) from the GRACE SDS format into \\file{instrument file (MISCVALUE)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt CLK1B or LLK1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2GnssReceiver}\\label{GraceL1b2GnssReceiver}\nThis program converts GPS receiver data (phase and pseudo range) data\nfrom the GRACE SDS format (GPS1B or GPS1A) into \\file{instrument file (GNSSRECEIVER)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGnssReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt GNSSRECEIVER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt GPS1B or GPS1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Magnetometer}\\label{GraceL1b2Magnetometer}\nThis program converts magnetometer data (MAG1B or MAG1A) from the GRACE SDS format into \\file{instrument file (MAGNETOMETER)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMagnetometer & \\hfuzz=500pt filename & \\hfuzz=500pt MAGNETOMETER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt MAG1B or MAG1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Mass}\\label{GraceL1b2Mass}\nThis program converts mass data (MAS1B or MAS1A) from the GRACE SDS format into \\file{instrument file (MASS)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMass & \\hfuzz=500pt filename & \\hfuzz=500pt MASS\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt MAS1B or MAS1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Orbit}\\label{GraceL1b2Orbit}\nThis program converts the reduced dynamical orbit\nfrom the GRACE/GRACE-FO SDS format (GNV1B, GNI1B) into \\file{instrument file (ORBIT)}{instrument}.\n\nWhen GNV1B is used, the orbit can be rotated from the terrestrial reference frame (TRF) transformed into the celestial reference frame (CRF) by\nspecifying \\configClass{earthRotation}{earthRotationType}.\n\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt to rotate GNV1B into CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt GNV1B/GNI1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2SatelliteTracking}\\label{GraceL1b2SatelliteTracking}\nThis program converts low-low satellite data measured by the K-band ranging system\nfrom the GRACE SDS format (KBR1B or LRI1B) into \\file{instrument file (SATELLITETRACKING)}{instrument}.\nThe \\config{inputfile}s contain also corrections to antenna offsets\nand the so called light time correction. The corrections can be stored in additional files\nin the same format as the observations.\nIf a phase break is found an artificial gap is created.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt SATELLITETRACKING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntCentr & \\hfuzz=500pt filename & \\hfuzz=500pt SATELLITETRACKING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileLighttime & \\hfuzz=500pt filename & \\hfuzz=500pt SATELLITETRACKING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSNR & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(K\\_A\\_SNR, Ka\\_A\\_SNR, K\\_B\\_SNR, Ka\\_B\\_SNR, qualflg)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileIonoCorr & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt KBR1B or LRI1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2StarCamera}\\label{GraceL1b2StarCamera}\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GRACE SDS format (SCA1B) into \\file{instrument file (STARCAMERA)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCameraFlags & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(sca\\_id, qual\\_rss, qualflg)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt SCA1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2StarCameraCovariance}\\label{GraceL1b2StarCameraCovariance}\nThis program computes star camera covariance matrices (\\file{instrument file, COVARIANE3D}{instrument})\nfor a GRACE satellite under consideration of the active camera heads and an a priori variance factor.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCameraCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCameraFlags & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSequenceOfEventsQSA & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~sigma0 & \\hfuzz=500pt double & \\hfuzz=500pt [seconds of arc]\\\\\n\\hline\n\\end{tabularx}\n\nThis program is \\reference{parallelized}{general.parallelization}.\n\\clearpage\n%==================================\n\\subsection{GraceL1b2SteeringMirror}\\label{GraceL1b2SteeringMirror}\nThis program converts GRACE-FO Steering Mirror output (LSM1B) to an \\file{instrument file (STARCAMERA)}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt LSM1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Thruster}\\label{GraceL1b2Thruster}\nThis program converts thruster data (THR1B or THR1A) from the GRACE SDS format into \\file{instrument file (THRUSTER)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileThruster & \\hfuzz=500pt filename & \\hfuzz=500pt THRUSTER\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt THR1B or THR1A\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2TimeOffset}\\label{GraceL1b2TimeOffset}\nThis program converts time data (TIM1A or TIM1B) from the GRACE SDS format into \\file{instrument file (MISCVALUE)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTime & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~fractionalScale & \\hfuzz=500pt double & \\hfuzz=500pt 1e-6 for GRACE, 1e-9 for GRACE-FO\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt TIM1A or TIM1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Uso}\\label{GraceL1b2Uso}\nThis program converts clock data (USO1B) from the GRACE SDS format into \\file{instrument file (MISCVALUES)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileUso & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(uso\\_freq, K\\_freq, Ka\\_freq)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt USO1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceL1b2Vector}\\label{GraceL1b2Vector}\nThis program reads vector orientation data (positions of instruments in the satellite frame) from the GRACE SDS format\n(VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B).\nThe \\configFile{outputfileVector}{matrix} is a $(3n\\times1)$ matrix containing $(x,y,z)$ for each record.\nThe GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\"\ngiven at \\url{http://podaac.jpl.nasa.gov/grace/documentation.html}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileVector & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GraceSequenceOfEvents}\\label{GraceSequenceOfEvents}\nThis program converts the GRACE SOE (sequence of events) file/format into \\file{instrument file (MISCVALUES)}{instrument}.\nThe GRACE SOE format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" and \"TN-03\\_SOE\\_format.txt\"\ngiven at \\url{http://podaac.jpl.nasa.gov/grace/documentation.html}.\nThe output is one arc of satellite data which can include data gaps.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGraceA & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileGraceB & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt SoE file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~events & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ACCT & \\hfuzz=500pt sequence & \\hfuzz=500pt DSHL HeaterDisconnect\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~mode & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~Heater & \\hfuzz=500pt  & \\hfuzz=500pt DSHL HeaterDisconnect\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~SetPoint & \\hfuzz=500pt  & \\hfuzz=500pt temperature set point\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~AOCS & \\hfuzz=500pt sequence & \\hfuzz=500pt coarse pointing mode or attitude hold mode\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~mode & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~CPM & \\hfuzz=500pt  & \\hfuzz=500pt coarse pointing mode\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~AHM & \\hfuzz=500pt  & \\hfuzz=500pt attitude hold mode\\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~SM & \\hfuzz=500pt  & \\hfuzz=500pt science mode\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ACCR & \\hfuzz=500pt  & \\hfuzz=500pt ACCR\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~CMCAL & \\hfuzz=500pt sequence & \\hfuzz=500pt CoM calibration maneuver\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] create events between start and end of maneuver\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~KBRCAL & \\hfuzz=500pt sequence & \\hfuzz=500pt KBR calibration maneuver\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~sampling & \\hfuzz=500pt double & \\hfuzz=500pt [seconds] create events between start and end of maneuver\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~VCM & \\hfuzz=500pt  & \\hfuzz=500pt CoM coordinates in SRF (m)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~VKB & \\hfuzz=500pt  & \\hfuzz=500pt KBR phase center coordinates in SRF (m)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~ICUVP & \\hfuzz=500pt  & \\hfuzz=500pt ICUVP\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~IPU & \\hfuzz=500pt  & \\hfuzz=500pt IPU\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~IPUR & \\hfuzz=500pt  & \\hfuzz=500pt IPUR\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~KAMI & \\hfuzz=500pt  & \\hfuzz=500pt KAMI: time tag offset to Ka-phase meas.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~KMI & \\hfuzz=500pt  & \\hfuzz=500pt K\\_MI: time tag offset to K-phase meas.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~KTOFF & \\hfuzz=500pt  & \\hfuzz=500pt KTOFF: time tag offset to KBR meas.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MANV & \\hfuzz=500pt  & \\hfuzz=500pt MANV\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MTE1 & \\hfuzz=500pt  & \\hfuzz=500pt MTE1\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~MTE2 & \\hfuzz=500pt  & \\hfuzz=500pt MTE2\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~OCC & \\hfuzz=500pt  & \\hfuzz=500pt OCC\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~QSA & \\hfuzz=500pt  & \\hfuzz=500pt SCA to SRF frame rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~QKS & \\hfuzz=500pt  & \\hfuzz=500pt SCA to KBR frame rotation\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GrailCdr2Orbit}\\label{GrailCdr2Orbit}\nThis program converts the orbit from the GRAIL SDS format into  \\file{instrument file (ORBIT)}{instrument}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GrailCdr2SatelliteTracking}\\label{GrailCdr2SatelliteTracking}\nThis program converts low-low satellite data measured by the K-band ranging system\nfrom the GRAIL format into \\file{instrument file (SATELLITETRACKING)}{instrument}.\nThe \\config{inputfile}s contain also corrections for antenna offsets\nand the so called light time correction.\nThe corrections can be stored in additional files in the same format as the observations.\nIf a phase break is found an artificial gap is created.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileAntCentr & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileLighttime & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTemperature & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approximateTimeBias & \\hfuzz=500pt double & \\hfuzz=500pt [seconds]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GrailCdr2StarCamera}\\label{GrailCdr2StarCamera}\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GRAIL SDS format into \\file{instrument file (STARCAMERA)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedData2NetCdf}\\label{GriddedData2NetCdf}\nThis program converts a \\configFile{inputfileGriddedData}{griddedData}\nto a COARDS compliant NetCDF file. The output data can be defined with \\config{dataVariable}.\nYou should add at least the attributes \\verb|units|, \\verb|long_name|, and maybe \\verb|_FillValue|\nto the variables. For the \\config{dataVariable:value} the standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileGriddedData}{griddedData}.\n\nSee also \\program{NetCdfInfo}, \\program{GriddedDataTimeSeries2NetCdf}, \\program{NetCdf2GriddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt file name of NetCDF output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt input grid sequence\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~dataVariable & \\hfuzz=500pt sequence & \\hfuzz=500pt metadata for data variables\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt netCDF variable name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~value & \\hfuzz=500pt expression & \\hfuzz=500pt expression (variables 'height', 'data', 'longitude', 'latitude' and, 'area' are taken from the gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~attribute & \\hfuzz=500pt choice & \\hfuzz=500pt netCDF attributes\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~globalAttribute & \\hfuzz=500pt choice & \\hfuzz=500pt additional meta data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GriddedDataTimeSeries2NetCdf}\\label{GriddedDataTimeSeries2NetCdf}\nRead a \\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nand converts it to a COARDS compliant NetCDF file.\n\nThe output data can be defined with \\config{dataVariable}.\nYou should add at least the attributes \\verb|units|, \\verb|long_name|, and maybe \\verb|_FillValue|\nto the variables. The \\config{dataVariable:inputColumn} selects the data from the input file.\n\nIf \\configClass{timeSeries}{timeSeriesType} is not set\nthe temporal nodal points from the inputfile are used.\n\nSee also \\program{NetCdfInfo}, \\program{GriddedData2NetCdf}, \\program{NetCdf2GriddedDataTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt file name of NetCDF output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt otherwise times from inputfile are used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~dataVariable & \\hfuzz=500pt sequence & \\hfuzz=500pt metadata for data variables\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt netCDF variable name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputColumn & \\hfuzz=500pt uint & \\hfuzz=500pt input data column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~attribute & \\hfuzz=500pt choice & \\hfuzz=500pt netCDF attributes\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~globalAttribute & \\hfuzz=500pt choice & \\hfuzz=500pt additional meta data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GroopsAscii2Orbit}\\label{GroopsAscii2Orbit}\nRead Orbits given in groops kinematic orbit ASCII format with covariance information.\n\nSee also \\program{Orbit2GroopsAscii}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Hw2TideGeneratingPotential}\\label{Hw2TideGeneratingPotential}\nWrite \\file{tide generating potential}{tideGeneratingPotential}\nfrom Hartmann and Wenzel 1995 file, \\url{https://doi.org/10.1029/95GL03324}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~headerLines & \\hfuzz=500pt uint & \\hfuzz=500pt skip number of header lines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~referenceTime & \\hfuzz=500pt time & \\hfuzz=500pt reference time\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Icgem2PotentialCoefficients}\\label{Icgem2PotentialCoefficients}\nRead spherical harmonics in ICGEM format (\\url{http://icgem.gfz-potsdam.de/}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStaticCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt static potential coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTrendCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt trend potential coefficients in GROOPS gfc format.  Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOscillationCosine & \\hfuzz=500pt filename & \\hfuzz=500pt oscillation cosine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileOscillationSine & \\hfuzz=500pt filename & \\hfuzz=500pt oscillation sine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileIntervals & \\hfuzz=500pt filename & \\hfuzz=500pt two column ASCII file with all intervals found (only sensible for icgem2.0). The base name will be extended with .static, .trend, .annualCos, and .annualSin.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileIcgem & \\hfuzz=500pt filename & \\hfuzz=500pt ICGEM GFC file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useFormalErrors & \\hfuzz=500pt boolean & \\hfuzz=500pt use formal errors if both formal and calibrated errors are given\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Iers2OceanPoleTide}\\label{Iers2OceanPoleTide}\nRead ocean pole tide model according to IERS conventions\nand convert into \\file{oceanPoleTide file}{oceanPoleTide}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOceanPole & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileLoadingLoveNumber & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt Reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~Omega & \\hfuzz=500pt double & \\hfuzz=500pt [rad/s] earth rotation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~rho & \\hfuzz=500pt double & \\hfuzz=500pt [kg/m**3] density of sea water\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~G & \\hfuzz=500pt double & \\hfuzz=500pt [m**3/(kg*s**2)] gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~g & \\hfuzz=500pt double & \\hfuzz=500pt [m/s**2] gravity\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{IersC04IAU2000EarthOrientationParameter}\\label{IersC04IAU2000EarthOrientationParameter}\nRead a IERS Earth orientation data C04 (IAU2000A) file\nand write it as \\configFile{outputfileEOP}{earthOrientationParameter}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{IersHighFrequentEop2DoodsonEop}\\label{IersHighFrequentEop2DoodsonEop}\nRead Diurnal and Subdiurnal Earth Orientation variations according to updated IERS 2010 conventions\nand write them as \\configFile{outputfileDoodsonEOP}{doodsonEarthOrientationParameter}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDoodsonEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{IersPotential2DoodsonHarmonics}\\label{IersPotential2DoodsonHarmonics}\nRead ocean tide file in IERS format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDoodsonHarmoncis & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~headerLines & \\hfuzz=500pt uint & \\hfuzz=500pt skip number of header lines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{IersRapidIAU2000EarthOrientationParameter}\\label{IersRapidIAU2000EarthOrientationParameter}\nRead a IERS Earth orientation rapid data and prediction file (IAU2000)\nand write it as \\configFile{outputfileEOP}{earthOrientationParameter}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{IersWaterHeight2DoodsonHarmonics}\\label{IersWaterHeight2DoodsonHarmonics}\nRead ocean tide file in IERS format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileDoodsonHarmoncis & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~headerLines & \\hfuzz=500pt uint & \\hfuzz=500pt skip number of header lines\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTideGeneratingPotential & \\hfuzz=500pt filename & \\hfuzz=500pt to compute Xi phase correction\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~kernel & \\hfuzz=500pt \\hyperref[kernelType]{kernel} & \\hfuzz=500pt data type of input values\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~factor & \\hfuzz=500pt double & \\hfuzz=500pt to convert in SI units\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Igs2EarthOrientationParameter}\\label{Igs2EarthOrientationParameter}\nRead Rapid Earth Orientation Parameter from IGS daily file\nand write it as \\configFile{outputfileEOP}{earthOrientationParameter}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEOP & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Jason2Starcamera}\\label{Jason2Starcamera}\nThis program reads in Jason star camera data given in a special  format.\nFiles available at: \\url{cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/}.\nA description of the format can be found under:\n\\url{ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~jasonNumber & \\hfuzz=500pt uint & \\hfuzz=500pt Jason number (different file format), 1 for Sentinel\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{JplAscii2Ephemerides}\\label{JplAscii2Ephemerides}\nRead JPL DExxx (ASCII) ephemerides.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileEphemerides & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileHeader & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Merit2FullRate}\\label{Merit2FullRate}\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html}{MERIT II file}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding full rate data like range, accuracy, wavelength, azimuth and elevation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalPoints & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMeteorological & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSlrData & \\hfuzz=500pt filename & \\hfuzz=500pt SLR MERIT II file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Merit2NormalPoints}\\label{Merit2NormalPoints}\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html}{MERIT II file}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding normal point data like range, accuracy, redundancy, wavelength, window size, azimuth and elevation.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNormalPoints & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMeteorological & \\hfuzz=500pt filename & \\hfuzz=500pt variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSlrData & \\hfuzz=500pt filename & \\hfuzz=500pt SLR MERIT II file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NetCdf2GriddedData}\\label{NetCdf2GriddedData}\nThis program converts a COARDS compliant NetCDF file into an\n\\configFile{outputfileGriddedData}{griddedData}.\nIf no specific input \\config{variableNameData} are selected all suitable data are used.\n\nIf the NETCDF file contains a time axis (\\config{variableNameData}) an specific epoch\ncan be selected with \\config{time}. The nearest epoch in file is used.\n\nSee also \\program{NetCdfInfo}, \\program{GriddedData2NetCdf}, \\program{NetCdf2GriddedDataTimeSeries}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameLongitude & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameLatitude & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableNameTime & \\hfuzz=500pt string & \\hfuzz=500pt if with time axis: name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~variableNameData & \\hfuzz=500pt string & \\hfuzz=500pt data variables, otherwise all suitable data are used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt if with time axis: nearest epoch is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NetCdf2GriddedDataTimeSeries}\\label{NetCdf2GriddedDataTimeSeries}\nThis program converts a COARDS compliant NetCDF file into\n\\configFile{outputfileGriddedDataTimeSeries}{griddedDataTimeSeries}.\nIf no specific input \\config{variableNameData} are selected all suitable data are used.\n\nSee also \\program{NetCdfInfo}, \\program{NetCdf2GriddedData}, \\program{GriddedDataTimeSeries2NetCdf}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedDataTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameLongitude & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameLatitude & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameTime & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~variableNameData & \\hfuzz=500pt string & \\hfuzz=500pt data variables, otherwise all suitable data are used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NetCdfInfo}\\label{NetCdfInfo}\nPrint content information of a NetCDF file like\ndimensions, variables and attributes.\n\nSee also \\program{NetCdf2GriddedData}, \\program{NetCdf2GriddedDataTimeSeries},\n\\program{GriddedData2NetCdf}, \\program{GriddedDataTimeSeries2NetCdf}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NormalsSphericalHarmonics2Sinex}\\label{NormalsSphericalHarmonics2Sinex}\nWrite potential coefficients and \\file{normal equations}{normalEquation} to\n\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}.\n\nSee also \\program{Sinex2Normals} and \\program{GnssNormals2Sinex}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSinex & \\hfuzz=500pt filename & \\hfuzz=500pt solutions in SINEX format\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNormals & \\hfuzz=500pt filename & \\hfuzz=500pt normal equation matrix\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSigmax & \\hfuzz=500pt filename & \\hfuzz=500pt standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileApriori & \\hfuzz=500pt filename & \\hfuzz=500pt apriori parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAprioriMatrix & \\hfuzz=500pt filename & \\hfuzz=500pt normal equation matrix of applied constraints\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt reference time for parameters\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~sinexHeader & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~agencyCode & \\hfuzz=500pt string & \\hfuzz=500pt identify the agency providing the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt start time of the data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt end time of the data \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~observationCode & \\hfuzz=500pt string & \\hfuzz=500pt technique used to generate the SINEX solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~constraintCode & \\hfuzz=500pt string & \\hfuzz=500pt 0: tight constraint, 1: siginficant constraint, 2: unconstrained\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~solutionContent & \\hfuzz=500pt string & \\hfuzz=500pt solution types contained in the SINEX solution (S O E T C A)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt organizitions gathering/alerting the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~contact & \\hfuzz=500pt string & \\hfuzz=500pt Address of the relevant contact. e-mail\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~output & \\hfuzz=500pt string & \\hfuzz=500pt Description of the file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~input & \\hfuzz=500pt string & \\hfuzz=500pt Brief description of the input used to generate this solution\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~software & \\hfuzz=500pt string & \\hfuzz=500pt Software used to generate the file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~hardware & \\hfuzz=500pt string & \\hfuzz=500pt Computer hardware on which above software was run\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileComment & \\hfuzz=500pt filename & \\hfuzz=500pt comments in the comment block from a file (truncated at 80 characters)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comments in the comment block\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{OceanTidesDTU2GriddedData}\\label{OceanTidesDTU2GriddedData}\nConvert DTU ocean tide grids to griddedData (amplitude, phase).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGriddedData & \\hfuzz=500pt filename & \\hfuzz=500pt data0=amplitude, data1=phase\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Orbit2Cpf}\\label{Orbit2Cpf}\nWrites groops orbits to \\href{https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html}{CPF file}.\n\nThe coordinate system used in the CPF format is usually presented in ITRF.\nThe required time format for the input orbit file is GPS.\nThe time format of the output CPF file is given in UTC.\n\nSee also \\program{Cpf2Orbit}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteInfo & \\hfuzz=500pt filename & \\hfuzz=500pt Platform File\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~versionNumber & \\hfuzz=500pt uint & \\hfuzz=500pt Version number of production day with zero leading fill, e.g. 01\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~targetClass & \\hfuzz=500pt uint & \\hfuzz=500pt set 1 for passive retroreflector, set 0 for no retroreflector (includes debris)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Orbit2GraceL1b}\\label{Orbit2GraceL1b}\nThis program converts an \\file{instrument file (ORBIT)}{instrument} specified in the celestial reference frame (CRF)\nto the GRACE/GRACE-FO SDS format (GNV1B, GNI1B). If \\configClass{earthRotation}{earthRotationType} is provided,\nthe orbit is rotated into the terrestrial reference frame as required for the GNV1B product; otherwise,\na GNI1B product is written.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, \\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2Orbit}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt GNV1B/GNI1B\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileHeader & \\hfuzz=500pt filename & \\hfuzz=500pt YAML Header, \\{epochmin\\}, \\{epochmax\\}, \\{epochcount\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~satelliteId & \\hfuzz=500pt string & \\hfuzz=500pt A, B, C or D\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotation into Earth fixed frame\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Orbit2GroopsAscii}\\label{Orbit2GroopsAscii}\nConvert groops orbits and corresponding covariance information to ASCII format.\nThe format is used to publish TUG orbits. It contains a two line header\nwith a short description of the orbit defined in \\config{firstLine}.\nThe orbit is rotated to the Earth fixed frame (TRF) with \\configClass{earthRotation}{earthRotationType} and given as one line per epoch.\nThe epoch lines contained time [MJD GPS time], position x, y and z [m], and the epoch covariance xx, yy, zz, xy, xz and yz [$m^2$].\n\nSee also \\program{GroopsAscii2Orbit}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~firstLine & \\hfuzz=500pt string & \\hfuzz=500pt Text for first line\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Orbit2Sp3Format}\\label{Orbit2Sp3Format}\nWrites orbits to \\href{https://files.igs.org/pub/data/format/sp3d.pdf}{SP3 format}.\n\nSP3 orbits are usually given in the terrestrial reference frame (TRF), so providing \\configClass{earthRotation}{earthRotationType}\nautomatically rotates the orbits from the celestial reference frame (CRF) to the TRF.\nSince SP3 orbits often use the center of Earth as a reference, a correction from center of mass to center\nof Earth can be applied to the orbits by providing \\configClass{gravityfield}{gravityfieldType} (e.g. ocean tides).\n\nSee also \\program{Sp3Format2Orbit}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~satellite & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~inputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt 3 characters (e.g. GNSS PRN: G01)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~orbitAccuracy & \\hfuzz=500pt double & \\hfuzz=500pt [m] used for accuracy codes in header (0 = unknown)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotate data into Earth-fixed frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comment lines (77 char max)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~firstLine & \\hfuzz=500pt string & \\hfuzz=500pt Text for first line e.g:  u+U  IGb14 KIN ITSG\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~writeVelocity & \\hfuzz=500pt boolean & \\hfuzz=500pt write velocity in addition to position\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~useSp3kFormat & \\hfuzz=500pt boolean & \\hfuzz=500pt use the extended sp3k format\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PotentialCoefficients2Icgem}\\label{PotentialCoefficients2Icgem}\nWrite spherical harmonics in ICGEM format.\nGROOPS uses this format as default but this program enables\nthe possibility to include comments and set the modelname.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfilePotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileTrend & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~oscillation & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileCosPotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinPotentialCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~period & \\hfuzz=500pt string & \\hfuzz=500pt period of oscillation [year]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt comment in header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileComment & \\hfuzz=500pt filename & \\hfuzz=500pt file containing comments for header\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~modelname & \\hfuzz=500pt string & \\hfuzz=500pt name of the model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~tideSystem & \\hfuzz=500pt choice & \\hfuzz=500pt tide system of model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zero\\_tide & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~tide\\_free & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~minDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~maxDegree & \\hfuzz=500pt uint & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~GM & \\hfuzz=500pt double & \\hfuzz=500pt Geocentric gravitational constant\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~time & \\hfuzz=500pt time & \\hfuzz=500pt reference time\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{PsmslOceanBottomPressure2TimeSeries}\\label{PsmslOceanBottomPressure2TimeSeries}\nThis programs reads ocean bottom pressure time series from the Permanent Service for Mean Sea Level (PSMSL).\n\nIn addition to the OBP measurements, the recorder position can be written to a \\file{grid file}{griddedData}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileTimeSeries & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfilePosition & \\hfuzz=500pt filename & \\hfuzz=500pt recorder position as gridded data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~isDaily & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~ignoreBadData & \\hfuzz=500pt boolean & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{RinexObservation2GnssReceiver}\\label{RinexObservation2GnssReceiver}\nConverts \\href{https://files.igs.org/pub/data/format/rinex_4.00.pdf}{RINEX} (version 2, 3, and 4) and\n\\href{https://terras.gsi.go.jp/ja/crx2rnx.html}{Compact RINEX} observation files to\n\\configFile{outputfileGnssReceiver}{instrument}.\n\nIn case of \\href{https://files.igs.org/pub/data/format/rinex211.txt}{RINEX v2.x} observation files\ncontaining GLONASS satellites, a mapping from PRN to frequency number must be provided via\n\\configFile{inputfileMatrixPrn2FrequencyNumber}{matrix}, see \\program{SinexMetadata2GlonassFrequencyNumber}.\nRINEX v3+ observation files already contain this information.\n\n\\configClass{useType}{gnssType} and \\configClass{ignoreType}{gnssType} can be used to filter\nthe observation types that will be exported.\n\nIf \\configFile{inputfileStationInfo}{platform} is set, RINEX antenna and receiver info\nwill be cross-checked with the provided file and warnings are raised in case of differences.\n\nA list of semi-codeless GPS receivers (observing C2D instead of C2W) can be provided via\n\\configFile{inputfileSemiCodelessReceivers}{stringList} with one receiver name per line.\nObservation types will be automatically corrected for these receivers.\n\nSome LEO satellites use special RINEX observation types, either from the unofficial RINEX v2.20\nor custom ones. These can be provided via \\configFile{inputfileSpecialObservationTypes}{stringTable}.\nThe file must  must contain a table with two columns, the first being the special type,\nand the second being the equivalent RINEX v3 type.\n\n%Example for RINEX v2.20:\n\n%\\begin{tabular}{ll}\n%LA & L1C \\\\\n%L1 & L1W \\\\\n%L2 & L2W \\\\\n%SA & S1C \\\\\n%S1 & S1W \\\\\n%S2 & S2W \\\\\n%\\end{tabular}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGnssReceiver & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileRinexObservation & \\hfuzz=500pt filename & \\hfuzz=500pt RINEX or Compact RINEX observation files\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileMatrixPrn2FrequencyNumber & \\hfuzz=500pt filename & \\hfuzz=500pt (required for RINEX v2 files containing GLONASS observations), matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt used to determine semi-codeless receivers and to cross-check antenna and receiver info\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSemiCodelessReceivers & \\hfuzz=500pt filename & \\hfuzz=500pt list with one receiver name per line\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSpecialObservationTypes & \\hfuzz=500pt filename & \\hfuzz=500pt table mapping special observation types to RINEX 3 types, e.g.: LA L1C\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~useType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt only use observations that match any of these patterns\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~ignoreType & \\hfuzz=500pt \\hyperref[gnssType]{gnssType} & \\hfuzz=500pt ignore observations that match any of these patterns\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sacc2Orbit}\\label{Sacc2Orbit}\nThis program reads in SACC orbit data.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SatelliteTracking2GraceL1b}\\label{SatelliteTracking2GraceL1b}\nThis program converts low-low satellite tracking data (KBR or LRI) from\nthe GROOPS format \\file{instrument file (SATELLITETRACKING)}{instrument}\nto the GRACE SDS format (KBR1B or LRI1B).\nIt reads the satellite tracking data and optionally corrections\n(antenna offsets and light time corrections) and flags into one \\config{outputfile}.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, \\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2SatelliteTracking}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt KBR1B or LRI1B\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileHeader & \\hfuzz=500pt filename & \\hfuzz=500pt YAML Header, \\{epochmin\\}, \\{epochmax\\}, \\{epochcount\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteTracking & \\hfuzz=500pt filename & \\hfuzz=500pt SATELLITETRACKING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileIonoCorr & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileLighttime & \\hfuzz=500pt filename & \\hfuzz=500pt SATELLITETRACKING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileAntCentr & \\hfuzz=500pt filename & \\hfuzz=500pt SATELLITETRACKING\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSNR & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(K\\_A\\_SNR, Ka\\_A\\_SNR, K\\_B\\_SNR, Ka\\_B\\_SNR, qualflg)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sentinel2StarCamera}\\label{Sentinel2StarCamera}\nThis program reads in Sentinel-1/2/3 star camera data given in the special format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SentinelXml2Orbit}\\label{SentinelXml2Orbit}\nRead Sentinel orbits from XML format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sinex2Normals}\\label{Sinex2Normals}\nConvert normal equations from \\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}\nto \\file{normal equations}{normalEquation}.\n\nSee also \\program{GnssNormals2Sinex} and \\program{NormalsSphericalHarmonics2Sinex}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileNormals & \\hfuzz=500pt filename & \\hfuzz=500pt N, n: unconstrained normal equations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileNormalsConstraint & \\hfuzz=500pt filename & \\hfuzz=500pt N0, n0: normal equations of applied constraints\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolution & \\hfuzz=500pt filename & \\hfuzz=500pt x: parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileSolutionApriori & \\hfuzz=500pt filename & \\hfuzz=500pt x0: a priori parameter vector\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputFileSinex & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sinex2StationDiscontinuities}\\label{Sinex2StationDiscontinuities}\nConvert station discontinuities from\n\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}\n(e.g. ITRF20) to \\configFile{outputfileInstrument}{instrument} (MISCVALUE).\nA value of 1 means position discontinuity, a value of 2 means velocity discontinuity.\nStart and end epochs with value 0 are added in addition to the discontinuities from\nSINEX to define continuity interval borders.\n\nSee also \\program{Sinex2StationPosition} and \\program{Sinex2StationPostSeismicDeformation}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt loop variable is replaced with station name (e.g. wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileDiscontinuities & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX (e.g. ITRF20) station discontinuities\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopStation & \\hfuzz=500pt string & \\hfuzz=500pt variable name for station loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt only export these stations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sinex2StationPositions}\\label{Sinex2StationPositions}\nExtracts station positions from \\config{inputfileSinexSolution}\n(\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format description})\nand writes an \\configFile{outputfileInstrument}{instrument} of type VECTOR3D\nfor each station.  Positions will be computed at \\configClass{timeSeries}{timeSeriesType} based on position and velocity\nof each provided interval in the SINEX file.\nWith \\config{inputfileSinexDiscontinuities} the bounds of these time spans are adjusted to the exact epochs of discontinuities.\nThe \\config{inputfileSinexPostSeismicDeformations} adds the ITRF post-seismic deformation model to the affected stations.\nThe \\config{inputfileSinexFrequencies} adds annual and semi-annual frequencies.\n\nIf \\config{extrapolateBackward} or \\config{extrapolateForward} are provided, positions will also be computed for epochs\nbefore the first interval/after the last interval, based on the position and velocity of the first/last interval.\nPosition extrapolation will stop at the first discontinuity before the first interval/after the last interval.\n\nStations can be limited via \\config{stationName}, otherwise all stations in \\config{inputfileSinexSolution} will be used.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt loop variable is replaced with station name (e.g. wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopStation & \\hfuzz=500pt string & \\hfuzz=500pt variable name for station loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinexSolution & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSinexDiscontinuities & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSinexPostSeismicDeformations & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSinexFrequencies & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file (XYZ or ENU)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt compute positions for these epochs based on velocity\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~extrapolateForward & \\hfuzz=500pt boolean & \\hfuzz=500pt also compute positions for epochs after last interval defined in SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~extrapolateBackward & \\hfuzz=500pt boolean & \\hfuzz=500pt also compute positions for epochs before first interval defined in SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt convert only these stations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SinexEccentricties2SlrPlatform}\\label{SinexEccentricties2SlrPlatform}\nReads metadata like station name, station number, approximate station position and station eccentricities\nfrom \\href{https://ilrs.gsfc.nasa.gov/network/site_procedures/eccentricity.html}{Station Eccentricities Sinex File}\n(une version) and write them to the \\configFile{outputfileStationInfo}{platform} for each station.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt loop variable is replaced with station name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopStation & \\hfuzz=500pt string & \\hfuzz=500pt variable name for station loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinex & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file (.snx or .ssc)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt convert only these stations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SinexMetadata2GlonassFrequencyNumber}\\label{SinexMetadata2GlonassFrequencyNumber}\nCreate \\configFile{outputfileMatrixPrn2FrequencyNumber}{matrix} matrix\nfrom \\href{https://www.igs.org/mgex/metadata/#metadata}{IGS SINEX metadata format}\nwith the columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber.\n\nSee also \\program{GnssGlonassFrequencyNumberUpdate}, \\program{GnssAntex2AntennaDefinition},\n\\program{RinexObservation2GnssReceiver}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileMatrixPrn2FrequencyNumber & \\hfuzz=500pt filename & \\hfuzz=500pt GROOPS matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinexMetadata & \\hfuzz=500pt filename & \\hfuzz=500pt IGS SINEX metadata file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SinexMetadata2SatelliteModel}\\label{SinexMetadata2SatelliteModel}\nCreate \\configFile{outputfileSatelliteModel}{satelliteModel} from \\href{https://www.igs.org/mgex/metadata/#metadata}{IGS SINEX metadata format}.\n\nIf \\configFile{inputfileSatelliteModel}{satelliteModel} is provided it is used as a basis and values are updated from the metadata file.\n\nSee also \\program{SatelliteModelCreate}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinexMetadata & \\hfuzz=500pt filename & \\hfuzz=500pt IGS SINEX metadata file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteModel & \\hfuzz=500pt filename & \\hfuzz=500pt base satellite model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~svn & \\hfuzz=500pt string & \\hfuzz=500pt e.g. G040, R736, E204, C211\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SlrComModel2RangeBiasStationSatellite}\\label{SlrComModel2RangeBiasStationSatellite}\nConverts the tables of CoM corrections of José Rodríguez\n(\\url{https://icts-yebes.oan.es/slr/com_models/models/}) into station/satellite\nspecific \\configFile{outputfileRangeBias}{instrument}. Only the deviations to the default value in\n\\configFile{inputfileSatelliteInfo}{platform} are written. This program must be called for every\nprovided satellite. The range bias values can be used in\n\\configClass{parametrization:rangeBiasStationSatelliteApriori}{slrParametrizationType:rangeBiasStationSatelliteApriori}\nin \\program {SlrProcessing}.\n\nReference:\nRodriguez J., Otsubo T., Appleby G. Upgraded Modelling for the\nDetermination of Centre of Mass Corrections of Geodetic SLR\nSatellites: Impact on Key Parameters of the Terrestrial Reference\nFrame. Journal of Geodesy, 2019. doi: 10.1007/s00190-019-01315-0\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileRangeBias & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE, variable \\{station\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSatelliteInfo & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt from Rodriguez model\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopStation & \\hfuzz=500pt string & \\hfuzz=500pt variable name for station loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt convert only these stations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{SlrSinexDataHandling2Files}\\label{SlrSinexDataHandling2Files}\nConverts SLR range and time bias from \\verb|ILRS_Data_Handling_File_xxxx.xx.xx.snx| provided at\n\\url{https://cddis.nasa.gov/archive/slr/products/resource/}. The range and time bias values can be used in\n\\configClass{parametrization:rangeBiasXxxApriori}{slrParametrizationType:rangeBiasStationApriori}\nin \\program {SlrProcessing}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileRangeBiasStation & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileRangeBiasStationSatellite & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUE [m]\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileTimeBias & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(bias [s], drift [s/d])\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopStation & \\hfuzz=500pt string & \\hfuzz=500pt variable name for station loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopSatellite & \\hfuzz=500pt string & \\hfuzz=500pt variable name for satellite loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinex & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file (.snx)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileSatelliteId & \\hfuzz=500pt filename & \\hfuzz=500pt table SP3 and satellite name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt convert only these stations\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sp3Format2Orbit}\\label{Sp3Format2Orbit}\nRead orbits from \\href{https://files.igs.org/pub/data/format/sp3d.pdf}{SP3 format}\nand write an \\file{instrument file (ORBIT)}{instrument}.\nThe additional \\config{outputfileClock} is an \\file{instrument file (MISCVALUE)}{instrument}\nand \\config{outputfileCovariance} is an \\file{instrument file (COVARIANCE3D)}{instrument}.\n\nWith \\config{satelliteIdentifier} a single satellite can be selected if the \\config{inputfile}s\ncontain more than one satellites. If \\config{satelliteIdentifier} is empty the first satellite is taken.\nAll satellites can be selected with \\config{satelliteIdentifier}=\\verb|<all>|.\nIn this case the identifier is appended to each output file.\n\nIf \\configClass{earthRotation}{earthRotationType} is provided the data are transformed\nfrom terrestrial (TRF) to celestial reference frame (CRF).\nSince SP3 orbits often use the center of Earth as a reference, a correction from center\nof Earth to center of mass can be applied to the orbits by providing \\configClass{gravityfield}{gravityfieldType} (e.g. ocean tides).\n\nSee also \\program{Orbit2Sp3Format}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileClock & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileCovariance & \\hfuzz=500pt filename & \\hfuzz=500pt 3x3 epoch covariance\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~satelliteIdentifier & \\hfuzz=500pt string & \\hfuzz=500pt e.g. L09 for GRACE A, empty: take first satellite, \\$<\\$all\\$>\\$: identifier is appended to each file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotation from TRF to CRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~gravityfield & \\hfuzz=500pt \\hyperref[gravityfieldType]{gravityfield} & \\hfuzz=500pt degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt orbits in SP3 format\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{StarCamera2GraceL1b}\\label{StarCamera2GraceL1b}\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GROOPS format \\file{instrument file (STARCAMERA)}{instrument} to the GRACE SDS format (SCA1B).\n\nIt reads one \\config{inputfileStarCamera} and optionally one\n\\config{inputfileStarCameraFlags} containing \\file{MISCVALUES}{instrument}(sca\\_id, qual\\_rss, qualflg),\nand writes one SDS output file.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, |\\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2StarCamera}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfile & \\hfuzz=500pt filename & \\hfuzz=500pt SCA1B\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileHeader & \\hfuzz=500pt filename & \\hfuzz=500pt YAML Header, \\{epochmin\\}, \\{epochmax\\}, \\{epochcount\\} available\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt STARCAMERA\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileStarCameraFlags & \\hfuzz=500pt filename & \\hfuzz=500pt MISCVALUES(sca\\_id, qual\\_rss, qualflg)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~satelliteId & \\hfuzz=500pt string & \\hfuzz=500pt A, B, C or D\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{StarCamera2Orbex}\\label{StarCamera2Orbex}\nConverts satellite attitude from \\file{instrument file (STARCAMERA)}{instrument} to\n\\href{http://acc.igs.org/misc/ORBEX009.pdf}{ORBEX file format} (quaternions).\n\nIf \\configClass{earthRotation}{earthRotationType} is provided, the output file contains quaternions\nfor rotation from TRF to satellite body frame (IGS/ORBEX convention),\notherwise the rotation is from CRF to satellite body frame.\n\nSee also \\program{GnssOrbex2StarCamera}, \\program{SimulateStarCameraGnss}.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbex & \\hfuzz=500pt filename & \\hfuzz=500pt ORBEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~satellite & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~identifier & \\hfuzz=500pt string & \\hfuzz=500pt string identifier (e.g. GNSS PRN: G01)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt e.g. BLOCK IIR-B, GRACE\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotate data into Earth-fixed frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt resample to these epochs (otherwise input file epochs are used)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for attitude and Earth rotation interpolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt description of file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~createdBy & \\hfuzz=500pt string & \\hfuzz=500pt name of agency\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputData & \\hfuzz=500pt string & \\hfuzz=500pt description of input data (see ORBEX description)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~contact & \\hfuzz=500pt string & \\hfuzz=500pt email address\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~referenceFrame & \\hfuzz=500pt string & \\hfuzz=500pt reference frame used in file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Swarm2Starcamera}\\label{Swarm2Starcamera}\nThis program reads SWARM star camera data given in the cdf format\nand before converted to an ascii file using the program \\verb|cdfexport|\nprovided by the Goddard Space Flight Center (\\url{http://cdf.gsfc.nasa.gov/}).\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{TerraSarTandem2Orbit}\\label{TerraSarTandem2Orbit}\nThis program reads in TerraSar-X or Tandem-X orbits in the special CHORB format and takes the appropriate\ntime frame as stated in the document header.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt orbits in CHORB format\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{TerraSarTandem2StarCamera}\\label{TerraSarTandem2StarCamera}\nThis program reads in TerraSar-X or Tandem-X star camera data given in the special format.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStarCamera & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Tle2Orbit}\\label{Tle2Orbit}\nThis program computes the \\configFile{outputfileOrbit}{instrument}\nfrom two-line elements (TLE/3LE)\nas can be found at e.g. \\url{http://celestrak.org/NORAD/elements/}.\nThe first satellite in the input file that matches the wildcard of \\config{satelliteName} is used.\nIf more records with exactly the same name are found, the one with the closest reference epoch\nis used for each point in the \\configClass{timeSeries}{timeSeriesType}.\n\nThe program uses the Simplified General Perturbation (SGP) model. More information can\nbe found in the Revisiting Spacetrack Report 3 by Vallado et al. 2006.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbit & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileTLE & \\hfuzz=500pt filename & \\hfuzz=500pt two line elements (TLE/3LE)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~satelliteName & \\hfuzz=500pt string & \\hfuzz=500pt first name of wildcard match is used\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt output orbit at these times\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotation to CRF\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ViennaMappingFunctionGrid2File}\\label{ViennaMappingFunctionGrid2File}\nThis program converts the gridded time series of the Vienna Mapping Functions (VMF) into\nthe \\file{GROOPS file format}{griddedDataTimeSeries}.\n\nGridded VMF data is available at: \\url{https://vmf.geo.tuwien.ac.at/trop_products/GRID/}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileVmfCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfile & \\hfuzz=500pt filename & \\hfuzz=500pt files must be given for each point in time\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt times of input files\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaLambda & \\hfuzz=500pt angle & \\hfuzz=500pt [deg] sampling in longitude\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~deltaPhi & \\hfuzz=500pt angle & \\hfuzz=500pt [deg] sampling in latitude\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~isCellRegistered & \\hfuzz=500pt boolean & \\hfuzz=500pt grid points represent cells (VMF3), not grid corners (VMF1)\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{ViennaMappingFunctionStation2File}\\label{ViennaMappingFunctionStation2File}\nConverts Vienna Mapping Functions (VMF) station time series into \\file{GROOPS file format}{griddedDataTimeSeries}.\n\nStation-wise VMF data for GNSS is available at: \\url{https://vmf.geo.tuwien.ac.at/trop_products/GNSS/}\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~outputfileVmfCoefficients & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileStation & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileVmf & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\section{Programs: Deprecated}\n\\subsection{GnssAttitude2Orbex}\\label{GnssAttitude2Orbex}\nDEPRECATED since 2024-11-30. Please use \\program{StarCamera2Orbex} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileOrbex & \\hfuzz=500pt filename & \\hfuzz=500pt ORBEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileTransmitterList & \\hfuzz=500pt filename & \\hfuzz=500pt ASCII list with transmitter PRNs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileAttitude & \\hfuzz=500pt filename & \\hfuzz=500pt instrument file containing attitude\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variablePrn & \\hfuzz=500pt string & \\hfuzz=500pt loop variable for PRNs from transmitter list\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt resample to these epochs (otherwise input file epochs are used)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~earthRotation & \\hfuzz=500pt \\hyperref[earthRotationType]{earthRotation} & \\hfuzz=500pt rotate data into Earth-fixed frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~interpolationDegree & \\hfuzz=500pt uint & \\hfuzz=500pt for attitude and Earth rotation interpolation\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~description & \\hfuzz=500pt string & \\hfuzz=500pt description of file contents\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~createdBy & \\hfuzz=500pt string & \\hfuzz=500pt name of agency\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputData & \\hfuzz=500pt string & \\hfuzz=500pt description of input data (see ORBEX description)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~contact & \\hfuzz=500pt string & \\hfuzz=500pt email address\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~referenceFrame & \\hfuzz=500pt string & \\hfuzz=500pt reference frame used in file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GnssPrn2SvnBlockVariables}\\label{GnssPrn2SvnBlockVariables}\nDEPRECATED since 2024-02-12. This program no longer works!\n\nSetup up a \\configClass{loop:platformEquipment}{loopType:platformEquipment} instead with\n\\begin{itemize}\n  \\item \\configFile{inputfilePlatform}{platform}: the old \\config{inputfileTransmitterInfo}\n  \\item \\config{equipmentType}         = \\verb|gnssAntenna|\n  \\item \\config{variableLoopName}      = \\verb|block|\n  \\item \\config{variableLoopSerial}    = \\verb|svn|\n  \\item \\config{variableLoopTimeStart} = \\verb|svnTimeStart|\n  \\item \\config{variableLoopTimeEnd}   = \\verb|svnTimeEnd|\n  \\item \\configClass{condition:expression}{conditionType:expression}\n  \\begin{itemize}\n    \\item \\config{expression} = \\verb|(svnTimeStart <= time) && (time < svnTimeEnd)|\n  \\end{itemize}\n\\end{itemize}\nAttribute this loop to programs, which uses the variables.\n\n\\clearpage\n%==================================\n\\subsection{GnssStationInfoCreate}\\label{GnssStationInfoCreate}\nDEPRECATED since 2024-12-02. Please use \\program{PlatformCreate} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileStationInfo & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~markerName & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~markerNumber & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approxPositionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] in TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approxPositionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] in TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~approxPositionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] in TRF\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~antenna & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~radome & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionX & \\hfuzz=500pt double & \\hfuzz=500pt [m] ARP in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionY & \\hfuzz=500pt double & \\hfuzz=500pt [m] ARP in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~positionZ & \\hfuzz=500pt double & \\hfuzz=500pt [m] ARP in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationX & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to left-handed antenna system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationY & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to left-handed antenna system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~rotationZ & \\hfuzz=500pt angle & \\hfuzz=500pt [degree] from local/vehicle to left-handed antenna system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipX & \\hfuzz=500pt boolean & \\hfuzz=500pt flip x-axis (after rotation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipY & \\hfuzz=500pt boolean & \\hfuzz=500pt flip y-axis (after rotation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~flipZ & \\hfuzz=500pt boolean & \\hfuzz=500pt flip z-axis (after rotation)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~receiver & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~serial & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~version & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~referencePoint & \\hfuzz=500pt sequence & \\hfuzz=500pt e.g. center of mass in satellite frame\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~comment & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~xStart & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~yStart & \\hfuzz=500pt double & \\hfuzz=500pt linear motion between start and end\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zStart & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~xEnd & \\hfuzz=500pt double & \\hfuzz=500pt [m] in north, east, up or vehicle system\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~yEnd & \\hfuzz=500pt double & \\hfuzz=500pt linear motion between start and end\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~zEnd & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeStart & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~timeEnd & \\hfuzz=500pt time & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{GridRectangular2NetCdf}\\label{GridRectangular2NetCdf}\nDEPRECATED since 2023-07-06. Please use \\program{GriddedData2NetCdf} or \\program{GriddedDataTimeSeries2NetCdf} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt file name of NetCDF output\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~inputfileGridRectangular & \\hfuzz=500pt filename & \\hfuzz=500pt input grid sequence\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~times & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt values for time axis (COARDS specification)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~dataVariable & \\hfuzz=500pt sequence & \\hfuzz=500pt metadata for data variables\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element.pdf}~selectDataField & \\hfuzz=500pt uint & \\hfuzz=500pt input data column\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt netCDF variable name\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-unbounded.pdf}~attribute & \\hfuzz=500pt choice & \\hfuzz=500pt netCDF attributes\\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~globalAttribute & \\hfuzz=500pt choice & \\hfuzz=500pt additional meta data\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~text & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~value & \\hfuzz=500pt sequence & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~name & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~value & \\hfuzz=500pt double & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~dataType & \\hfuzz=500pt choice & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~double & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~float & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\quad\\quad\\includegraphics[width=1em]{connector.pdf}\\includegraphics[width=1em]{element-mustset.pdf}~int & \\hfuzz=500pt  & \\hfuzz=500pt \\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{NetCdf2GridRectangular}\\label{NetCdf2GridRectangular}\nDEPRECATED since 2023-07-06. Please use \\program{NetCdf2GriddedData} or \\program{NetCdf2GriddedDataTimeSeries} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileGridRectangular & \\hfuzz=500pt filename & \\hfuzz=500pt One grid for each epoch in the NetCDF file is written. Use loopTimeVariable as template.\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~loopTimeVariable & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileNetCdf & \\hfuzz=500pt filename & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameLongitude & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~variableNameLatitude & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableNameTime & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable (leave blank for static grids)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~variableNameData & \\hfuzz=500pt string & \\hfuzz=500pt name of NetCDF variable\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~R & \\hfuzz=500pt double & \\hfuzz=500pt reference radius for ellipsoidal coordinates\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inverseFlattening & \\hfuzz=500pt double & \\hfuzz=500pt reference flattening for ellipsoidal coordinates\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sinex2StationPosition}\\label{Sinex2StationPosition}\nDEPRECATED since 2023-02-16. Please use \\program{Sinex2StationPositions} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt loop variable is replaced with station name (e.g. wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinex & \\hfuzz=500pt filename & \\hfuzz=500pt SINEX file (.snx or .ssc)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~inputfileDiscontinuities & \\hfuzz=500pt filename & \\hfuzz=500pt discontinuities file per station; loop variable is replaced with station name (e.g. wtzz)\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~variableLoopStation & \\hfuzz=500pt string & \\hfuzz=500pt variable name for station loop\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt convert only these stations\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt compute positions for these epochs based on velocity\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~extrapolateForward & \\hfuzz=500pt boolean & \\hfuzz=500pt also compute positions for epochs after last interval defined in SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~extrapolateBackward & \\hfuzz=500pt boolean & \\hfuzz=500pt also compute positions for epochs before first interval defined in SINEX file\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n\\subsection{Sinex2StationPostSeismicDeformation}\\label{Sinex2StationPostSeismicDeformation}\nDEPRECATED since 2023-02-16. Please use \\program{Sinex2StationPositions} instead.\n\n\n\\keepXColumns\n\\begin{tabularx}{\\textwidth}{N T A}\n\\hline\nName & Type & Annotation\\\\\n\\hline\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~outputfileInstrument & \\hfuzz=500pt filename & \\hfuzz=500pt deformation time series\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~inputfileSinex & \\hfuzz=500pt filename & \\hfuzz=500pt ITRF post-seismic deformation SINEX file\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~timeSeries & \\hfuzz=500pt \\hyperref[timeSeriesType]{timeSeries} & \\hfuzz=500pt compute deformation for these epochs\\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element-mustset.pdf}~stationName & \\hfuzz=500pt string & \\hfuzz=500pt \\\\\n\\hfuzz=500pt\\includegraphics[width=1em]{element.pdf}~localLevelFrame & \\hfuzz=500pt boolean & \\hfuzz=500pt output in North, East, Up local-level frame\\\\\n\\hline\n\\end{tabularx}\n\n\\clearpage\n%==================================\n"
  },
  {
    "path": "docs/makeDocumentation.sh",
    "content": "#!/bin/bash\n../bin/groops --doc .\n\necho \"make Latex\"\ncd latex\npdflatex -interaction=nonstopmode documentation.tex >/dev/null\npdflatex -interaction=nonstopmode documentation.tex >/dev/null\npdflatex -interaction=nonstopmode documentation.tex | grep -a1 -e \"^!\" -e \"Warning\"\ncd ..\nmv latex/documentation.pdf .\n\necho \"make source code docu (doxygen)\"\ncd source\ndoxygen Doxyfile >/dev/null\ncd ..\n"
  },
  {
    "path": "docs/source/.gitignore",
    "content": "*\n!Doxyfile\n!.gitignore\n"
  },
  {
    "path": "docs/source/Doxyfile",
    "content": "# Doxyfile 1.10.0\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n#\n# Note:\n#\n# Use doxygen to compare the used configuration file with the template\n# configuration file:\n# doxygen -x [configFile]\n# Use doxygen to compare the used configuration file with the template\n# configuration file without replacing the environment variables or CMake type\n# replacement variables:\n# doxygen -x_noenv [configFile]\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the configuration\n# file that follow. The default is UTF-8 which is also the encoding used for all\n# text before the first occurrence of this tag. Doxygen uses libiconv (or the\n# iconv built into libc) for the transcoding. See\n# https://www.gnu.org/software/libiconv/ for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = GROOPS\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         =\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"Gravity Recovery Object Oriented Programming System\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           =\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = .\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096\n# sub-directories (in 2 levels) under the output directory of each output format\n# and will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to\n# control the number of sub-directories.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# Controls the number of sub-directories that will be created when\n# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every\n# level increment doubles the number of directories, resulting in 4096\n# directories at level 8 which is the default and also the maximum value. The\n# sub-directories are organized in 2 levels, the first level always has a fixed\n# number of 16 directories.\n# Minimum value: 0, maximum value: 8, default value: 8.\n# This tag requires that the tag CREATE_SUBDIRS is set to YES.\n\nCREATE_SUBDIRS_LEVEL   = 8\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,\n# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English\n# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,\n# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with\n# English messages), Korean, Korean-en (Korean with English messages), Latvian,\n# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,\n# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,\n# Swedish, Turkish, Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = YES\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = YES\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = YES\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        = ../../source\n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    = ../../source\n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = YES\n\n# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line\n# such as\n# /***************\n# as being the beginning of a Javadoc-style comment \"banner\". If set to NO, the\n# Javadoc-style will behave just like regular comments and it will not be\n# interpreted by doxygen.\n# The default value is: NO.\n\nJAVADOC_BANNER         = NO\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = YES\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = YES\n\n# By default Python docstrings are displayed as preformatted text and doxygen's\n# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the\n# doxygen's special commands can be used and the contents of the docstring\n# documentation blocks is shown as doxygen documentation.\n# The default value is: YES.\n\nPYTHON_DOCSTRING       = YES\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 5\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:^^\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". Note that you cannot put \\n's in the value part of an alias\n# to insert newlines (in the resulting output). You can put ^^ in the value part\n# of an alias to insert a newline as if a physical newline was in the original\n# file. When you need a literal { or } or , in the value part of an alias you\n# have to escape them by means of a backslash (\\), this can lead to conflicts\n# with the commands \\{ and \\} for these it is advised to use the version @{ and\n# @} or use a double escape (\\\\{ and \\\\})\n\nALIASES                =\n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice\n# sources only. Doxygen will then generate output that is more tailored for that\n# language. For instance, namespaces will be presented as modules, types will be\n# separated into more groups, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_SLICE  = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,\n# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,\n# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:\n# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser\n# tries to guess whether the code is fixed or free formatted code, this is the\n# default for Fortran type files). For instance to make doxygen treat .inc files\n# as Fortran files (default is PHP), and .f files as C (default is Fortran),\n# use: inc=Fortran f=C.\n#\n# Note: For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen. When specifying no_extension you should add\n# * to the FILE_PATTERNS.\n#\n# Note see also the list of default file extension mappings.\n\nEXTENSION_MAPPING      =\n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See https://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up\n# to that level are automatically included in the table of contents, even if\n# they do not have an id attribute.\n# Note: This feature currently applies only to Markdown headings.\n# Minimum value: 0, maximum value: 99, default value: 5.\n# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.\n\nTOC_INCLUDE_HEADINGS   = 5\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = NO\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = NO\n\n# If one adds a struct or class to a group and this option is enabled, then also\n# any nested class or struct is added to the same group. By default this option\n# is disabled and one has to add nested compounds explicitly via \\ingroup.\n# The default value is: NO.\n\nGROUP_NESTED_COMPOUNDS = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 0\n\n# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use\n# during processing. When set to 0 doxygen will based this on the number of\n# cores available in the system. You can set it explicitly to a value larger\n# than 0 to get more control over the balance between CPU load and processing\n# speed. At this moment only the input processing can be done using multiple\n# threads. Since this is still an experimental feature the default is set to 1,\n# which effectively disables parallel processing. Please report any issues you\n# encounter. Generating dot graphs in parallel is controlled by the\n# DOT_NUM_THREADS setting.\n# Minimum value: 0, maximum value: 32, default value: 1.\n\nNUM_PROC_THREADS       = 1\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = NO\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual\n# methods of a class will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIV_VIRTUAL   = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = NO\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. If set to YES, local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO, only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If this flag is set to YES, the name of an unnamed parameter in a declaration\n# will be determined by the corresponding definition. By default unnamed\n# parameters remain unnamed in the output.\n# The default value is: YES.\n\nRESOLVE_UNNAMED_PARAMS = YES\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = NO\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO, these classes will be included in the various overviews. This option\n# will also hide undocumented C++ concepts if enabled. This option has no effect\n# if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# declarations. If set to NO, these declarations will be included in the\n# documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO, these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# With the correct setting of option CASE_SENSE_NAMES doxygen will better be\n# able to match the capabilities of the underlying filesystem. In case the\n# filesystem is case sensitive (i.e. it supports files in the same directory\n# whose names only differ in casing), the option must be set to YES to properly\n# deal with such files in case they appear in the input. For filesystems that\n# are not case sensitive the option should be set to NO to properly deal with\n# output files written for symbols that only differ in casing, such as for two\n# classes, one named CLASS and the other named Class, and to also support\n# references to files without having to specify the exact matching casing. On\n# Windows (including Cygwin) and MacOS, users should typically set this option\n# to NO, whereas on Linux or other Unix flavors it should typically be set to\n# YES.\n# Possible values are: SYSTEM, NO and YES.\n# The default value is: SYSTEM.\n\nCASE_SENSE_NAMES       = NO\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES, the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will\n# append additional text to a page's title, such as Class Reference. If set to\n# YES the compound reference will be hidden.\n# The default value is: NO.\n\nHIDE_COMPOUND_REFERENCE= NO\n\n# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class\n# will show which file needs to be included to use the class.\n# The default value is: YES.\n\nSHOW_HEADERFILE        = YES\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = NO\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = NO\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = NO\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo\n# list. This list is created by putting \\todo commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test\n# list. This list is created by putting \\test commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       =\n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES, the\n# list will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    =\n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file. See also section \"Changing the\n# layout of pages\" for information.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            =\n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. See also \\cite for info how to create references.\n\nCITE_BIB_FILES         =\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = YES\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = NO\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as documenting some parameters in\n# a documented function twice, or documenting parameters that don't exist or\n# using markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete\n# function parameter documentation. If set to NO, doxygen will accept that some\n# parameters have no documentation without warning.\n# The default value is: YES.\n\nWARN_IF_INCOMPLETE_DOC = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO, doxygen will only warn about wrong parameter\n# documentation, but not about the absence of documentation. If EXTRACT_ALL is\n# set to YES then this flag will automatically be disabled. See also\n# WARN_IF_INCOMPLETE_DOC\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = NO\n\n# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about\n# undocumented enumeration values. If set to NO, doxygen will accept\n# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: NO.\n\nWARN_IF_UNDOC_ENUM_VAL = NO\n\n# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when\n# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS\n# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but\n# at the end of the doxygen process doxygen will return with a non-zero status.\n# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves\n# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not\n# write the warning messages in between other messages but write them at the end\n# of a run, in case a WARN_LOGFILE is defined the warning messages will be\n# besides being in the defined file also be shown at the end of a run, unless\n# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case\n# the behavior will remain as with the setting FAIL_ON_WARNINGS.\n# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.\n# The default value is: NO.\n\nWARN_AS_ERROR          = NO\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# See also: WARN_LINE_FORMAT\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# In the $text part of the WARN_FORMAT command it is possible that a reference\n# to a more specific place is given. To make it easier to jump to this place\n# (outside of doxygen) the user can define a custom \"cut\" / \"paste\" string.\n# Example:\n# WARN_LINE_FORMAT = \"'vi $file +$line'\"\n# See also: WARN_FORMAT\n# The default value is: at line $line of file $file.\n\nWARN_LINE_FORMAT       = \"at line $line of file $file\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr). In case the file specified cannot be opened for writing the\n# warning and error messages are written to standard error. When as file - is\n# specified the warning and error messages are written to standard output\n# (stdout).\n\nWARN_LOGFILE           =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = ../../source/\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see:\n# https://www.gnu.org/software/libiconv/) for the list of possible encodings.\n# See also: INPUT_FILE_ENCODING\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify\n# character encoding on a per file pattern basis. Doxygen will compare the file\n# name with each pattern and apply the encoding instead of the default\n# INPUT_ENCODING) if there is a match. The character encodings are a list of the\n# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding\n# \"INPUT_ENCODING\" for further information on supported encodings.\n\nINPUT_FILE_ENCODING    =\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# read by doxygen.\n#\n# Note the list of default checked file patterns might differ from the list of\n# default file extension mappings.\n#\n# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm,\n# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl,\n# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d,\n# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to\n# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,\n# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.\n\nFILE_PATTERNS          = *.c \\\n                         *.cc \\\n                         *.cxx \\\n                         *.cpp \\\n                         *.c++ \\\n                         *.d \\\n                         *.java \\\n                         *.ii \\\n                         *.ixx \\\n                         *.ipp \\\n                         *.i++ \\\n                         *.inl \\\n                         *.h \\\n                         *.hh \\\n                         *.hxx \\\n                         *.hpp \\\n                         *.h++ \\\n                         *.idl \\\n                         *.odl \\\n                         *.cs \\\n                         *.php \\\n                         *.php3 \\\n                         *.inc \\\n                         *.m \\\n                         *.mm \\\n                         *.dox \\\n                         *.py \\\n                         *.for \\\n                         *.vhd \\\n                         *.vhdl\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                =\n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       = *.new \\\n                         *.old \\\n                         *.new/* \\\n                         *.old/*\n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# ANamespace::AClass, ANamespace::*Test\n\nEXCLUDE_SYMBOLS        =\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           =\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       = *\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             =\n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n#\n# Note that doxygen will use the data processed and written to standard output\n# for further processing, therefore nothing else, like debug statements or used\n# commands (so in case of a Windows batch file always use @echo OFF), should be\n# written to standard output.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nINPUT_FILTER           =\n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nFILTER_PATTERNS        =\n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = NO\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS =\n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE =\n\n# The Fortran standard specifies that for fixed formatted Fortran code all\n# characters from position 72 are to be considered as comment. A common\n# extension is to allow longer lines before the automatic comment starts. The\n# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can\n# be processed before the automatic comment starts.\n# Minimum value: 7, maximum value: 10000, default value: 72.\n\nFORTRAN_COMMENT_AFTER  = 72\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = YES\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# multi-line macros, enums or list initialized variables directly into the\n# documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# entity all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = NO\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = NO\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see https://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)\n# that should be ignored while generating the index headers. The IGNORE_PREFIX\n# tag works for classes, function and member names. The entity will be placed in\n# the alphabetical list under the first letter of the entity name that remains\n# after removing the prefix.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            =\n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            =\n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        =\n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# cascading style sheets that are included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefore more robust against future updates.\n# Doxygen will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# Note: Since the styling of scrollbars can currently not be overruled in\n# Webkit/Chromium, the styling will be left out of the default doxygen.css if\n# one or more extra stylesheets have been specified. So if scrollbar\n# customization is desired it has to be added explicitly. For an example see the\n# documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  =\n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       =\n\n# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output\n# should be rendered with a dark or light theme.\n# Possible values are: LIGHT always generate light mode output, DARK always\n# generate dark mode output, AUTO_LIGHT automatically set the mode according to\n# the user preference, use light mode if no preference is set (the default),\n# AUTO_DARK automatically set the mode according to the user preference, use\n# dark mode if no preference is set and TOGGLE allow to user to switch between\n# light and dark mode via a button.\n# The default value is: AUTO_LIGHT.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE        = AUTO_LIGHT\n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the style sheet and background images according to\n# this color. Hue is specified as an angle on a color-wheel, see\n# https://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 220\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use gray-scales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 100\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 80\n\n# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML\n# documentation will contain a main index with vertical navigation menus that\n# are dynamically created via JavaScript. If disabled, the navigation index will\n# consists of multiple levels of tabs that are statically embedded in every HTML\n# page. Disable this option to support browsers that do not have JavaScript,\n# like the Qt help browser.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_MENUS     = YES\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = NO\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see:\n# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To\n# create a documentation set, doxygen will generate a Makefile in the HTML\n# output directory. Running make will produce the docset in that directory and\n# running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy\n# genXcode/_index.html for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\n\n# This tag determines the URL of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDURL         =\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.doxygen.Project\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = Publisher\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# on Windows. In the beginning of 2021 Microsoft took the original page, with\n# a.o. the download links, offline the HTML help workshop was already many years\n# in maintenance mode). You can download the HTML help workshop from the web\n# archives at Installation executable (see:\n# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo\n# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               =\n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler (hhc.exe). If non-empty,\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           =\n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated\n# (YES) or that it should be included in the main .chm file (NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     =\n\n# The BINARY_TOC flag controls whether a binary table of contents is generated\n# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               =\n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   =\n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  =\n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  =\n\n# The QHG_LOCATION tag can be used to specify the location (absolute path\n# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to\n# run qhelpgenerator on the generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           =\n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = NO\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = org.doxygen.Project\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine tune the look of the index (see \"Fine-tuning the output\"). As an\n# example, the default style sheet generated by doxygen has an example that\n# shows how to put an image at the root of the tree instead of the PROJECT_NAME.\n# Since the tree basically has the same information as the tab index, you could\n# consider setting DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = NO\n\n# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the\n# FULL_SIDEBAR option determines if the side bar is limited to only the treeview\n# area (value NO) or if it should extend to the full height of the window (value\n# YES). Setting this to YES gives a layout similar to\n# https://docs.readthedocs.io with more room for contents, but less room for the\n# project logo, title, and description. If either GENERATE_TREEVIEW or\n# DISABLE_INDEX is set to NO, this option has no effect.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFULL_SIDEBAR           = NO\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 4\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email\n# addresses.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nOBFUSCATE_EMAILS       = YES\n\n# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg\n# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see\n# https://inkscape.org) to generate formulas as SVG images instead of PNGs for\n# the HTML output. These images will generally look nicer at scaled resolutions.\n# Possible values are: png (the default) and svg (looks nicer but requires the\n# pdf2svg or inkscape tool).\n# The default value is: png.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FORMULA_FORMAT    = png\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# The FORMULA_MACROFILE can contain LaTeX \\newcommand and \\renewcommand commands\n# to create new LaTeX commands to be used in formulas as building blocks. See\n# the section \"Including formulas\" for details.\n\nFORMULA_MACROFILE      =\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# https://www.mathjax.org) which uses client side JavaScript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.\n# Note that the different versions of MathJax have different requirements with\n# regards to the different settings, so it is possible that also other MathJax\n# settings have to be changed when switching between the different MathJax\n# versions.\n# Possible values are: MathJax_2 and MathJax_3.\n# The default value is: MathJax_2.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_VERSION        = MathJax_2\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. For more details about the output format see MathJax\n# version 2 (see:\n# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3\n# (see:\n# http://docs.mathjax.org/en/latest/web/components/output.html).\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility. This is the name for Mathjax version 2, for MathJax version 3\n# this will be translated into chtml), NativeMML (i.e. MathML. Only supported\n# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This\n# is the name for Mathjax version 3, for MathJax version 2 this will be\n# translated into HTML-CSS) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from https://www.mathjax.org before deployment. The default value is:\n# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2\n# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = http://www.mathjax.org/mathjax\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# for MathJax version 2 (see\n# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# For example for MathJax version 3 (see\n# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):\n# MATHJAX_EXTENSIONS = ams\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     =\n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see:\n# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       =\n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using JavaScript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = NO\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see:\n# https://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see:\n# https://xapian.org/). See the section \"External Indexing and Searching\" for\n# details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       =\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     =\n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when not enabling USE_PDFLATEX the default is latex when enabling\n# USE_PDFLATEX the default is pdflatex and when in the later case latex is\n# chosen this is overwritten by pdflatex. For specific output languages the\n# default can have been set differently, this depends on the implementation of\n# the output language.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# Note: This tag is used in the Makefile / make.bat.\n# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file\n# (.tex).\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to\n# generate index for LaTeX. In case there is no backslash (\\) as first character\n# it will be automatically added in the LaTeX code.\n# Note: This tag is used in the generated output file (.tex).\n# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.\n# The default value is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_MAKEINDEX_CMD    = makeindex\n\n# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = a4\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. The package can be specified just\n# by its name or with the correct syntax as to be used with the LaTeX\n# \\usepackage command. To get the times font for instance you can specify :\n# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}\n# To use the option intlimits with the amsmath package you can specify:\n# EXTRA_PACKAGES=[intlimits]{amsmath}\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         =\n\n# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for\n# the generated LaTeX document. The header should contain everything until the\n# first chapter. If it is left blank doxygen will generate a standard header. It\n# is highly recommended to start with a default header using\n# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty\n# and then modify the file new_header.tex. See also section \"Doxygen usage\" for\n# information on how to generate the default header that doxygen normally uses.\n#\n# Note: Only use a user-defined header if you know what you are doing!\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. The following\n# commands have a special meaning inside the header (and footer): For a\n# description of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           =\n\n# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for\n# the generated LaTeX document. The footer should contain everything after the\n# last chapter. If it is left blank doxygen will generate a standard footer. See\n# LATEX_HEADER for more information on how to generate a default footer and what\n# special commands can be used inside the footer. See also section \"Doxygen\n# usage\" for information on how to generate the default footer that doxygen\n# normally uses. Note: Only use a user-defined footer if you know what you are\n# doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           =\n\n# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# LaTeX style sheets that are included after the standard style sheets created\n# by doxygen. Using this option one can overrule certain style aspects. Doxygen\n# will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_STYLESHEET =\n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      =\n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as\n# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX\n# files. Set this option to YES, to get a higher quality PDF documentation.\n#\n# See also section LATEX_CMD_NAME for selecting the engine.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error.\n# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch\n# mode nothing is printed on the terminal, errors are scrolled as if <return> is\n# hit at every error; missing files that TeX tries to input or request from\n# keyboard input (\\read on a not open input stream) cause the job to abort,\n# NON_STOP In nonstop mode the diagnostic message will appear on the terminal,\n# but there is no possibility of user interaction just like in batch mode,\n# SCROLL In scroll mode, TeX will stop only for missing files to input or if\n# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at\n# each error, asking for user intervention.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = NO\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# https://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)\n# path from which the emoji images will be read. If a relative path is entered,\n# it will be relative to the LATEX_OUTPUT directory. If left blank the\n# LATEX_OUTPUT directory will be used.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EMOJI_DIRECTORY  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's\n# configuration file, i.e. a series of assignments. You only have to provide\n# replacements, missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    =\n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's configuration file. A template extensions file can be\n# generated using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             =\n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include\n# namespace members in file scope as well, matching the HTML output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_NS_MEMB_FILE_SCOPE = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an\n# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures\n# the structure of the code including all documentation. Note that this feature\n# is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO, the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = NO\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of\n# RECURSIVE has no effect here.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           = ../../source/\n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  =\n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             =\n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      =\n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               =\n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       =\n\n# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces\n# will be listed in the class and namespace index. If set to NO, only the\n# inherited external classes will be listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed\n# in the topic index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to diagram generator tools\n#---------------------------------------------------------------------------\n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = NO\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of\n# subgraphs. When you want a differently looking font in the dot files that\n# doxygen generates you can specify fontname, fontcolor and fontsize attributes.\n# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,\n# Edge and Graph Attributes specification</a> You need to make sure dot is able\n# to find the font, which can be done by putting it in a standard location or by\n# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the\n# directory containing the font. Default graphviz fontsize is 14.\n# The default value is: fontname=Helvetica,fontsize=10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_COMMON_ATTR        = \"fontname=Helvetica,fontsize=10\"\n\n# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can\n# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a\n# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about\n# arrows shapes.</a>\n# The default value is: labelfontname=Helvetica,labelfontsize=10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_EDGE_ATTR          = \"labelfontname=Helvetica,labelfontsize=10\"\n\n# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes\n# around nodes set 'shape=plain' or 'shape=plaintext' <a\n# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>\n# The default value is: shape=box,height=0.2,width=0.4.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NODE_ATTR          = \"shape=box,height=0.2,width=0.4\"\n\n# You can set the path where dot can find font specified with fontname in\n# DOT_COMMON_ATTR and others dot attributes.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           =\n\n# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will\n# generate a graph for each documented class showing the direct and indirect\n# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and\n# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case\n# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the\n# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used.\n# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance\n# relations will be shown as texts / links. Explicit enabling an inheritance\n# graph or choosing a different representation for an inheritance graph of a\n# specific class, can be accomplished by means of the command \\inheritancegraph.\n# Disabling an inheritance graph can be accomplished by means of the command\n# \\hideinheritancegraph.\n# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN.\n# The default value is: YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes. Explicit enabling a collaboration graph,\n# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the\n# command \\collaborationgraph. Disabling a collaboration graph can be\n# accomplished by means of the command \\hidecollaborationgraph.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies. Explicit enabling a group\n# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means\n# of the command \\groupgraph. Disabling a directory graph can be accomplished by\n# means of the command \\hidegroupgraph. See also the chapter Grouping in the\n# manual.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag UML_LOOK is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and\n# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS\n# tag is set to YES, doxygen will add type and arguments for attributes and\n# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen\n# will not generate fields with class member information in the UML graphs. The\n# class diagrams will look similar to the default class diagrams but using UML\n# notation for the relationships.\n# Possible values are: NO, YES and NONE.\n# The default value is: NO.\n# This tag requires that the tag UML_LOOK is set to YES.\n\nDOT_UML_DETAILS        = NO\n\n# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters\n# to display on a single line. If the actual line length exceeds this threshold\n# significantly it will be wrapped across multiple lines. Some heuristics are\n# applied to avoid ugly line breaks.\n# Minimum value: 0, maximum value: 1000, default value: 17.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_WRAP_THRESHOLD     = 17\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = NO\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO,\n# can be accomplished by means of the command \\includegraph. Disabling an\n# include graph can be accomplished by means of the command \\hideincludegraph.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set\n# to NO, can be accomplished by means of the command \\includedbygraph. Disabling\n# an included by graph can be accomplished by means of the command\n# \\hideincludedbygraph.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command. Disabling a call graph can be\n# accomplished by means of the command \\hidecallgraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command. Disabling a caller graph can be\n# accomplished by means of the command \\hidecallergraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = YES\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories. Explicit enabling a directory graph, when\n# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command\n# \\directorygraph. Disabling a directory graph can be accomplished by means of\n# the command \\hidedirectorygraph.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels\n# of child directories generated in directory dependency graphs by dot.\n# Minimum value: 1, maximum value: 25, default value: 1.\n# This tag requires that the tag DIRECTORY_GRAPH is set to YES.\n\nDIR_GRAPH_MAX_DEPTH    = 1\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot. For an explanation of the image formats see the section\n# output formats in the documentation of the dot tool (Graphviz (see:\n# https://www.graphviz.org/)).\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,\n# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and\n# png:gdiplus:gdiplus.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = png\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               =\n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           =\n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               =\n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           =\n\n# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the\n# path where java can find the plantuml.jar file or to the filename of jar file\n# to be used. If left blank, it is assumed PlantUML is not used or called during\n# a preprocessing step. Doxygen will generate a warning when it encounters a\n# \\startuml command in this case and will not generate output for the diagram.\n\nPLANTUML_JAR_PATH      =\n\n# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a\n# configuration file for plantuml.\n\nPLANTUML_CFG_FILE      =\n\n# When using plantuml, the specified paths are searched for files specified by\n# the !include statement in a plantuml block.\n\nPLANTUML_INCLUDE_PATH  =\n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 50\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = NO\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal\n# graphical representation for inheritance and collaboration diagrams is used.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate\n# files that are used to generate the various graphs.\n#\n# Note: This setting is not only used for dot files but also for msc temporary\n# files.\n# The default value is: YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "groops.xsd",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n\t<xs:simpleType name=\"int\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"uint\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"double\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"angle\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"boolean\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"time\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"doodson\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"string\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"filename\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"expression\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:simpleType name=\"gnssType\">\n\t\t<xs:restriction base=\"xs:string\"/>\n\t</xs:simpleType>\n\t<xs:complexType name=\"autoregressiveModelSequenceType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"inputfileAutoregressiveModel\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>matrix file containing an AR model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sigma0\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>a-priori sigma for white noise covariance</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"borderType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>borders of geographical areas</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"rectangle\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>along lines of geographical coordinates</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"minLambda\" type=\"angle\"/>\n\t\t\t\t\t\t<xs:element name=\"maxLambda\" type=\"angle\"/>\n\t\t\t\t\t\t<xs:element name=\"minPhi\" type=\"angle\"/>\n\t\t\t\t\t\t<xs:element name=\"maxPhi\" type=\"angle\"/>\n\t\t\t\t\t\t<xs:element name=\"exclude\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>dismiss points inside</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"cap\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>spherical cap</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"lambdaCenter\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude of the center of the cap</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phiCenter\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of the center of the cap</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"psi\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>aperture angle (radius)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"exclude\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>dismiss points inside</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"polygon\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>polygon from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfilePolygon\" type=\"filename\" default=\"{groopsDataDir}/border/\"/>\n\t\t\t\t\t\t<xs:element name=\"buffer\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>buffer around polygon [km], &lt;0: inside</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"exclude\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>dismiss points inside</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"conditionType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"fileExist\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"file\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>supports wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minimumSize\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum file size in byte.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"command\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"command\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"silently\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>without showing the output.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"expression\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"expression\" type=\"expression\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"matrix\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression is evaluated for each element of resulting matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"expression\" type=\"expression\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(variable: data) evaluated for each element</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"all\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all (=yes)/any (=no) elements must evaluate to true</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"matrixEmpty\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"stringContainsPattern\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"string\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>should contain a {variable}</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"pattern\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>supports wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"isRegularExpression\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>pattern is  a regular expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"caseSensitive\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>treat lower and upper case as distinct</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"stringMatchPattern\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"string\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>should contain a {variable}</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"pattern\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>supports wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"isRegularExpression\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>pattern is  a regular expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"caseSensitive\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>treat lower and upper case as distinct</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"and\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"or\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"not\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"covariancePodType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>general variance factor</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>different accuracies for each arc (multiplied with sigma)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>different accuracies for each epoch (added)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>covariances in time for along, cross, and radial direction</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>3x3 epoch-wise covariances</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"covarianceSstType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>general variance factor</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>different accuaries for each arc (multplicated with sigma)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>different accuaries for each epoch (added)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>covariance function in time</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>one matrix file per arc. Use {arcNo} as template</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sigmasCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>vector with one sigma for each covarianceMatrixArc</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"digitalFilterType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>create digital filter</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"movingAverage\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>moving average (boxcar) filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"length\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of epochs in averaging operator</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"movingMedian\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>moving median filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"length\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>length of the moving window [epochs]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"derivative\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>differentiation by polynomial approximation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of approximation polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"derivative\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>take kth derivative</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>assumed time step between points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"integral\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>integration by polynomial approximation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of approximation polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>assumed time step between points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"correlation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>correlation by simple coefficient</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"correlation\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>correlation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"backwardDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in backward direction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"graceLowpass\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GRACE low pass filter (self convolving kernel)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rawDataRate\" type=\"double\" default=\"10.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sampling frequency in Hz (fs).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"convolutionNumber\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of self convolutions of the filter kernel</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fitInterval\" type=\"double\" minOccurs=\"0\" default=\"70.7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>length of the filter kernel [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"lowPassBandwith\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>target low pass bandwidth</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"normFrequency\" type=\"double\" minOccurs=\"0\" default=\"0.37e-3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>norm filter at this frequency [Hz] (default: GRACE dominant (J2) signal frequency)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"reduceQuadraticFit\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove-&gt;filter-&gt;restore quadratic fit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"derivative\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"derivative1st\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>range rate</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"derivative2nd\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>range acceleration</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"butterworth\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>fixed order digital Butterworth filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter order</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter type</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"lowpass\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Wn\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>normalized cutoff frequency (f_c / f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"highpass\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Wn\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>normalized cutoff frequency (f_c / f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"bandpass\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Wn1\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>lower normalized cutoff frequency (f_c / f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Wn2\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>upper normalized cutoff frequency (f_c / f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"bandstop\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Wn1\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>lower normalized cutoff frequency (f_c / f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Wn2\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>upper normalized cutoff frequency (f_c / f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"backwardDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in backward direction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read ARMA filter from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix with filter coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"index\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>index of coefficients (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"bn\" type=\"expression\" minOccurs=\"0\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MA coefficients (moving average) (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"an\" type=\"expression\" minOccurs=\"0\" default=\"data2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>AR coefficients (autoregressive) (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"backwardDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in backward direction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"wavelet\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>filter representation of wavelet</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileWavelet\" type=\"filename\" default=\"{groopsDataDir}/wavelets/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wavelet coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter type</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"lowpass\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"highpass\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"level\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute filter for specific decomposition level</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"backwardDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in backward direction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"notch\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>notch filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"notchFrequency\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normalized notch frequency w_n = (f_n/f_nyq)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"bandWidth\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>bandwidth at -3db. Quality factor of filter Q = w_n/bw</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"backwardDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in backward direction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"decorrelation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>decorrelation filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance function of time series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"lag\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>lag/lead filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"lag\" type=\"int\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>lag epochs: 1 (lag); -1 (lead)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inFrequencyDomain\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply filter in frequency domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"padType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>no padding is applied</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero padding</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pad using first and last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"periodic\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>periodic continuation of matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"symmetric\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>symmetric continuation around the matrix edges</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"reduceFilterOutput\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>remove filter output from input signal</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"filter\" type=\"digitalFilterType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove filter output from input signal</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"earthRotationType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>transformation from CRF to TRF</xs:documentation>\n\t\t\t<xs:appinfo>rename: itrf2010 = iers2010</xs:appinfo>\n\t\t\t<xs:appinfo>rename: itrf2010b = iers2010b</xs:appinfo>\n\t\t\t<xs:appinfo>rename: itrf2003 = iers2003</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>interpolated values from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEOP\" type=\"filename\" default=\"{groopsDataDir}/earthRotation/timeSeries_EOP_rapid_IAU2000_desai.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for polynomial interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"iers2010\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>IERS conventions 2010</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEOP\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/earthRotation/EOP_20C04_IAU2000.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"truncatedNutation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use truncated nutation model (IAU2006B)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"iers2010b\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>IERS conventions 2010 with HF EOP model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEOP\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/earthRotation/EOP_20C04_IAU2000.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonEOP\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/earthRotation/doodsonEOP_desai_jgrb51665-sup-0002-ds01.txt\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"iers2003\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>IERS conventions 2003</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEOP\" type=\"filename\" default=\"{groopsDataDir}/earthRotation/EOP_20C04_IAU2000.txt\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"itrf1996\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>IERS conventions 1996</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEOP\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNutation\" type=\"filename\" default=\"{groopsDataDir}/earthRotation/nutationIAU1980.xml\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gmst\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>z-Axis rotation with gmst</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"era\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>z-Axis rotation with earth rotation angle (ERA)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"zAxis\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>z-Axis rotation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"initialAngle\" type=\"double\" default=\"5.133658456\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Angle at time0 [rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"angularVelocity\" type=\"double\" default=\"7.29211585531e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time0\" type=\"time\" default=\"51740.5\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"starCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>earth rotation from instrument file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of interpolation polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"moonRotation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Libration angles (Moon)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEphemerides\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/tides/ephemerides_JPL_DE432.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>librations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"moonfixedSystem\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"PA\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Principal Axis System</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ME\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Mean Earth System</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"eclipseType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>Shadowing of satellites by moon and Earth</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"conical\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Umbra and penumbra shadow model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SOLAARS\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Penumbra with Oblateness and Lower Atmospheric Absorption, Refraction, and Scattering</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"ephemeridesType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>ephemerides of Sun, Moon and planets</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"jpl\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEphemerides\" type=\"filename\" default=\"{groopsDataDir}/tides/ephemerides_JPL_DE432.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"origin\" type=\"planetType\" minOccurs=\"0\" default=\"earth\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>center of coordinate system</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"forcesType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t<xs:element name=\"tides\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t<xs:element name=\"miscAccelerations\" type=\"miscAccelerationsType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"gnssAntennaDefintionListType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"new\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"pattern\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pattern matching of observation types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"offsetX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] antenna center offset</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"offsetY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] antenna center offset</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"offsetZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] antenna center offset</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"deltaAzimuth\" type=\"angle\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] step size</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"deltaZenith\" type=\"angle\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] step size</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"maxZenith\" type=\"angle\" minOccurs=\"0\" default=\"90\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"values\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] expression (zenith, azimuth: variables)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fromFile\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"onlyFirstMatch\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>otherwise all machting antennas included</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fromStationInfo\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only antennas used in this time interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only antennas used in this time interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"specializeAntenna\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. separate different serial numbers from stationInfo</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"resample\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"antenna\" type=\"gnssAntennaDefintionListType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"deltaAzimuth\" type=\"angle\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] step size, empty: no change</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaZenith\" type=\"angle\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] step size, empty: no change</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxZenith\" type=\"angle\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree], empty: no change</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"transform\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"antenna\" type=\"gnssAntennaDefintionListType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"patternTypes\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gnssType for each pattern (first match is used)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"additionalPattern\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional new patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>pattern matching of observation types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"offsetX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] antenna center offset</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"offsetY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] antenna center offset</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"offsetZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] antenna center offset</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"deltaAzimuth\" type=\"angle\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] step size</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"deltaZenith\" type=\"angle\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] step size</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"maxZenith\" type=\"angle\" minOccurs=\"0\" default=\"90\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"values\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] expression (zenith, azimuth: variables)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"addExistingPatterns\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add existing patterns that don&apos;t match completely any of the above</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rename\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"antenna\" type=\"gnssAntennaDefintionListType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"setZero\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"antenna\" type=\"gnssAntennaDefintionListType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"patternTypes\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only matching patterns, default: all</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"zeroOffset\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"zeroPattern\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"removeCenterMean\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"antenna\" type=\"gnssAntennaDefintionListType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"patternTypes\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only matching patterns, default: all</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"removeOffset\" type=\"boolean\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"deltaAzimuth\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] sampling of pattern to estimate center/constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaZenith\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] sampling of pattern to estimate center/constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxZenith\" type=\"angle\" minOccurs=\"0\" default=\"90\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] sampling of pattern to estimate center/constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"gnssParametrizationType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>parametrization of GNSS observations</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"ionosphereSTEC\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>ionospheric slant delays</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.STEC\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"apply2ndOrderCorrection\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply ionospheric correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"apply3rdOrderCorrection\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply ionospheric correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"applyBendingCorrection\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply ionospheric correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"magnetosphere\" type=\"magnetosphereType\"/>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraint.STEC\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaSTEC\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expr. for sigma [TECU] for STEC constraint, variable E (elevation) available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ionosphereVTEC\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>ionospheric verical delays</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.VTEC\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileVTEC\" type=\"filename\" minOccurs=\"0\" default=\"output/vtec_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, columns: MJD, VTEC, north gradient, east gradient</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mapR\" type=\"double\" minOccurs=\"0\" default=\"6371e3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant of MSLM mapping function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mapH\" type=\"double\" minOccurs=\"0\" default=\"506.7e3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant of MSLM mapping function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mapAlpha\" type=\"double\" minOccurs=\"0\" default=\"0.9782\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant of MSLM mapping function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gradient\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parametrization of north and east gradients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ionosphereMap\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>ionospheric verical delays</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.mapVTEC\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedDataTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>single layer VTEC [TECU]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputGrid\" type=\"gridType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"{&quot;geograph&quot;:{&quot;deltaLambda&quot;:&quot;5&quot;,&quot;deltaPhi&quot;:&quot;2.5&quot;,&quot;height&quot;:&quot;450e3&quot;,&quot;R&quot;:&quot;6371e3&quot;,&quot;inverseFlattening&quot;:0}}\"/>\n\t\t\t\t\t\t<xs:element name=\"outputTimeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"{&quot;uniformSampling&quot;:{&quot;sampling&quot;:&quot;2/24&quot;}}\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedDataTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>single layer VTEC [TECU]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" default=\"15\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>spherical harmonics parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>temporal evolution of VTEC values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radiusIonosphericLayer\" type=\"double\" minOccurs=\"0\" default=\"6371e3+450e3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] radius of ionospheric single layer</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mapR\" type=\"double\" minOccurs=\"0\" default=\"6371e3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] constant of MSLM mapping function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mapH\" type=\"double\" minOccurs=\"0\" default=\"506.7e3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] constant of MSLM mapping function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mapAlpha\" type=\"double\" minOccurs=\"0\" default=\"0.9782\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant of MSLM mapping function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"magnetosphere\" type=\"magnetosphereType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"clocks\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>clock errors</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.clocks\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileClockTransmitter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileClockReceiver\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraintEpoch.clocks\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmittersZeroMean\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceiversZeroMean\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"sigmaZeroMeanConstraint\" type=\"double\" minOccurs=\"0\" default=\"0.0001\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"clocksModel\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>clock errors with AR1 process model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.clocks\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileClockTransmitter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileClockReceiver\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>clock jumps &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>clock jumps &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraintEpoch.clocksModel\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmittersZeroMean\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use these transmitters for zero-mean constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceiversZeroMean\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use these receivers for zero-mean constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaZeroMeanConstraint\" type=\"double\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"signalBiases\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>apriori values of signal biases (code/phase)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.signalBiases\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileSignalBiasTransmitter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSignalBiasReceiver\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSignalBiasTransmitter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSignalBiasReceiver\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ambiguities\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>integer and float ambiguities</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.ambiguities\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateTransmitterPhaseBias\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"estimateReceiverPhaseBias\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"linearGlonassBias\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>bias depends linear on frequency channel number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"codeBiases\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>biases of code signals</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.codeBiases\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"linearGlonassBias\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>bias depends linear on frequency channel number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"typesClockDatum\" type=\"gnssType\" minOccurs=\"0\" default=\"[&quot;C1WG&quot;, &quot;C2WG&quot;, &quot;C1CE&quot;, &quot;C5QE&quot;, &quot;C1PR&quot;, &quot;C2PR&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first two matching types define the ionosphere free transmitter clock (e.g. C1WG, C2WG)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraint.codeBiases\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaZeroMeanConstraint\" type=\"double\" minOccurs=\"0\" default=\"0.0001\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for null space constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"tecBiases\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>biases of signals which changes the estimated TEC</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.tecBiases\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"linearGlonassBias\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>phase or code biases depend linear on frequency channel number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraint.tecBiases\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaZeroMeanConstraint\" type=\"double\" minOccurs=\"0\" default=\"0.0001\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for null space constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"temporalBias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>temporal changing signal bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.temporalBias\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileBiasTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileBiasTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\" default=\"L5*G\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraint.temporalBias\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaZeroMeanConstraint\" type=\"double\" minOccurs=\"0\" default=\"0.0001\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for temporal zero-mean constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"staticPositions\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>static positions with no-net constraints</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.staticPositions\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedPosition\" type=\"filename\" minOccurs=\"0\" default=\"output/gridPosition_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>delta north east up for all stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfilePosition\" type=\"filename\" minOccurs=\"0\" default=\"output/stationPosition_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, full estimated coordinates (in TRF)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraint.staticPositions\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectNoNetReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNoNetPositions\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/receiverStation/position/igs/igs20/stationPosition.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, precise coordinates used for no-net constraints (in TRF)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noNetTranslationSigma\" type=\"double\" minOccurs=\"0\" default=\"0.01\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noNetRotationSigma\" type=\"double\" minOccurs=\"0\" default=\"0.001\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] at Earth&apos;s surface for no-net rotation constraint on station coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noNetScaleSigma\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>stations &gt; huber*sigma0 are downweighted in no-net constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>stations &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"kinematicPositions\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>position each epoch</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.kinematicPositions\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfilePositions\" type=\"filename\" minOccurs=\"0\" default=\"output/positions_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, estimated kinematic positions/orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceEpoch\" type=\"filename\" minOccurs=\"0\" default=\"output/covariance3x3Epoch_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, 3x3 epoch covariances</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"leoDynamicOrbits\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>LEO orbits by variational equations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.dynamicOrbits\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameters\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\" default=\"variational_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stochasticPulse\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[mu/s] parametrization of stochastic pulses</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"minEstimableEpochsRatio\" type=\"double\" minOccurs=\"0\" default=\"0.75\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>drop satellites with lower ratio of estimable epochs to total epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for orbit interpolation and velocity calculation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"transmitterDynamicOrbits\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GNSS satellite orbits by variational equations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.transmitterDynamicOrbits\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameters\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\" default=\"variational_{loopTime:%D}.{prn}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stochasticPulse\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[mu/s] parametrization of stochastic pulses</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"minEstimableEpochsRatio\" type=\"double\" minOccurs=\"0\" default=\"0.75\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>drop satellites with lower ratio of estimable epochs to total epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for orbit interpolation and velocity calculation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"troposphere\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>tropospheric delays</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.troposphere\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileTroposphere\" type=\"filename\" minOccurs=\"0\" default=\"output/troposphere_{loopTime:%D}.{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"troposphere\" type=\"troposphereType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>a priori troposphere model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"troposphereWetEstimation\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] parametrization of zenith wet delays</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"troposphereGradientEstimation\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] parametrization of north and east gradients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"earthRotation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Earth rotation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.earthRotation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileEOP\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimatePole\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>xp, yp [mas]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateUT1\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation angle [ms]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateNutation\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>dX, dY [mas]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"receiverAntennas\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>antenna center variations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.receiverAntenna\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"antennaCenterVariations\" type=\"parametrizationGnssAntennaType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimate antenna center variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"patternTypes\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gnssType for each pattern (first match is used)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"addNonMatchingTypes\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add patterns for additional observed gnssTypes that don&apos;t match any of the above</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"groupAntennas\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>common ACVs for same antenna build types (ignores antenna serial number)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"transmitterAntennas\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>antenna center variations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.transmitterAntenna\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"antennaCenterVariations\" type=\"parametrizationGnssAntennaType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimate antenna center variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"patternTypes\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gnssType for each pattern (first match is used)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"addNonMatchingTypes\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add patterns for additional observed gnssTypes that don&apos;t match any of the above</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"groupAntennas\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>common ACVs for same antenna build types (ignores antenna serial number)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"constraints\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parameter constraints</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"constraint.name\"/>\n\t\t\t\t\t\t<xs:element name=\"parameters\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter to constrain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma of the constraint (same unit as parameter)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"bias\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constrain all selected parameters towards this value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"relativeToApriori\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constrain only dx and not full x=dx+x0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>grouping parametrizations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"gnssParametrizationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"gnssProcessingStepType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"estimate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>least squares adjustment</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"computeResiduals\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"adjustSigma0\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>adjust sigma0 by scale factor (per receiver and type)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeWeights\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>downweight outliers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"convergenceThreshold\" type=\"double\" minOccurs=\"0\" default=\"0.01\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] stop iteration once full convergence is reached</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxIterationCount\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"resolveAmbiguities\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>resolve integer ambiguities</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAmbiguities\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>resolved ambiguities</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[{&quot;all&quot;:{}}]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only resolve ambiguities with these participating transmitters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[{&quot;all&quot;:{}}]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only resolve ambiguities with these participating receivers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaMaxResolve\" type=\"double\" minOccurs=\"0\" default=\"0.2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>max. allowed std. dev. of ambiguity to resolve [cycles]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"searchBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"200\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for blocked integer search</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxSearchSteps\" type=\"uint\" minOccurs=\"0\" default=\"200000000\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>max. steps of integer search for each block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"incompleteAction\" default=\"shrinkBlockSize\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if not all solutions tested after maxSearchSteps</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"stop\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>stop searching, ambiguities remain float in this block</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"resolve\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use best integer solution found so far</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"shrinkBlockSize\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>try again with half block size</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"throwException\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>stop and throw an exception</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeResiduals\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"adjustSigma0\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>adjust sigma0 by scale factor (per receiver and type)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeWeights\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>downweight outliers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"computeCovarianceMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute covariance matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeResults\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write all estimated parameters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"suffix\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>appended to every output file name (e.g. orbit.G01.suffix.dat)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeNormalEquations\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write unconstrained and constraint normal equations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquations\" type=\"filename\" default=\"output/normals_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"remainingParameters\" type=\"parameterSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of output normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"constraintsOnly\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>write only normals of constraints without observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultNormalsBlockSize\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block, empty: original block size</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeAprioriSolution\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write apriori solution vector</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAprioriSolution\" type=\"filename\" minOccurs=\"0\" default=\"output/x0_{loopTime:%D}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>a priori parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\" minOccurs=\"0\" default=\"output/parameterNames_{loopTime:%D}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter names</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"remainingParameters\" type=\"parameterSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of output normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeResiduals\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write observation residuals</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileResiduals\" type=\"filename\" default=\"output/residuals_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeUsedStationList\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write used stations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileUsedStationList\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with names of used stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeUsedTransmitterList\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write used transmitters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used transmitters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileUsedTransmitterList\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"printResidualStatistics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>print residual statistics</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectParametrizations\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select parametrizations for all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"enable\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"*\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"disable\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"*\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectEpochs\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select epochs to be used in all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"nthEpoch\" type=\"uint\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use only every nth epoch in all subsequent processing steps</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectNormalsBlockStructure\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select block structure of the distributed normal equation matrix for all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockSizeEpoch\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size of epoch parameters, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockSizeInterval\" type=\"uint\" minOccurs=\"0\" default=\"64\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size of interval parameters, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockSizeAmbiguity\" type=\"uint\" minOccurs=\"0\" default=\"64\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size of ambiguity parameters, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockReceiverCount\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of receivers to group into one block for epoch and interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockCountReduction\" type=\"uint\" minOccurs=\"0\" default=\"32\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum number of blocks for epoch reduction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"keepEpochNormalsInMemory\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>speeds up processing but uses much more memory</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"accumulateEpochObservations\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set up all observations per epoch and receiver at once</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectReceivers\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>use this subset of stations in all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"forEachReceiverSeparately\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>process receiver by receiver, transmitter parameters disabled</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectReceivers\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"variableReceiver\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable is set for each receiver</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"processingStep\" type=\"gnssProcessingStepType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>steps are processed consecutively</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>group processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"processingStep\" type=\"gnssProcessingStepType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>steps are processed consecutively</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"disableTransmitterShadowEpochs\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>disable transmitter epochs in eclipse</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectTransmitters\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"disableShadowEpochs\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>disable epochs if satellite is in Earth&apos;s/Moon&apos;s shadow</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"disablePostShadowRecoveryEpochs\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>disable epochs if satellite is in post-shadow recovery maneuver for GPS block IIA</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>eclipse model used to determine if a satellite is in Earth&apos;s shadow</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"gnssReceiverGeneratorType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"stationNetwork\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationList\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with station names</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxStationCount\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum number of stations to be used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/stationInfo/igs/stationInfo.{station}.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available. station metadata (antennas, receivers, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>antenna center offsets and variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noAntennaPatternFound\" default=\"ignoreObservation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>what should happen if no antenna pattern is found for an observation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ignoreObservation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ignore observation if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"useNearestFrequency\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use pattern of nearest frequency if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"throwException\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>throw exception if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileReceiverDefinition\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>observed signal types</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccuracyDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/accuracyDefinition/accuracyDefinition.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>elevation and azimuth dependent accuracy</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationPosition\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/receiverStation/position/igs/igs20/stationPosition.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"disableStationWithoutPosition\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>drop stations without apriori position</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileClock\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileObservations\" type=\"filename\" minOccurs=\"0\" default=\"gnssReceiver_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"loadingDisplacement\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loading deformation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tidalDisplacement\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tidal deformation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for tidal deformation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDeformationLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialLoadLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if full potential is given and not only loading potential</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only use observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elevationCutOff\" type=\"angle\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] ignore observations below cutoff</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elevationTrackMinimum\" type=\"angle\" minOccurs=\"0\" default=\"15\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] ignore tracks that never exceed minimum elevation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minObsCountPerTrack\" type=\"uint\" minOccurs=\"0\" default=\"60\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tracks with less number of epochs with observations are dropped</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minEstimableEpochsRatio\" type=\"double\" minOccurs=\"0\" default=\"0.75\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[0,1] drop stations with lower ratio of estimable epochs to total epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"preprocessing\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>settings for preprocessing of observations/stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"printStatistics\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>print preprocesssing statistics for all receivers</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"codeMaxPositionDiff\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] max. allowed position error by PPP code only clock error estimation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"denoisingLambda\" type=\"double\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>regularization parameter for total variation denoising used in cylce slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"tecWindowSize\" type=\"uint\" minOccurs=\"0\" default=\"15\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>(0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"tecSigmaFactor\" type=\"double\" minOccurs=\"0\" default=\"3.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileTrackBefore\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileTrackAfter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"lowEarthOrbiter\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite metadata (antenna, receiver, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>antenna center offsets and variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noAntennaPatternFound\" default=\"ignoreObservation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>what should happen if no antenna pattern is found for an observation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ignoreObservation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ignore observation if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"useNearestFrequency\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use pattern of nearest frequency if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"throwException\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>throw exception if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileReceiverDefinition\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>observed signal types</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccuracyDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>elevation and azimut dependent accuracy</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileObservations\" type=\"filename\" minOccurs=\"0\" default=\"gnssReceiver_{loopTime:%D}.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate positions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite attitude</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaFactorPhase\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PHASE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaFactorCode\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>CODE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"supportsIntegerAmbiguities\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>receiver tracks full cycle integer ambiguities</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"wavelengthFactor\" type=\"double\" minOccurs=\"0\" default=\"1.\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>factor to account for half-wavelength observations (collected by codeless squaring techniques)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only use observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elevationCutOff\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] ignore observations below cutoff</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minObsCountPerTrack\" type=\"uint\" minOccurs=\"0\" default=\"20\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tracks with less number of epochs with observations are dropped</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"preprocessing\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>settings for preprocessing of observations/stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"printStatistics\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>print preprocesssing statistics for all receivers</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"codeMaxPositionDiff\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] max. allowed position error by PPP code only clock error estimation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"denoisingLambda\" type=\"double\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>regularization parameter for total variation denoising used in cylce slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"tecWindowSize\" type=\"uint\" minOccurs=\"0\" default=\"15\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>(0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"tecSigmaFactor\" type=\"double\" minOccurs=\"0\" default=\"3.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileTrackBefore\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileTrackAfter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"gnssTransmitterGeneratorType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"GNSS\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterList\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/transmitterList.gps.txt\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with transmitter PRNs, used to loop variable {prn}</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefintion\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>phase centers and variations (ANTEX like)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noAntennaPatternFound\" default=\"useNearestFrequency\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>what should happen is no antenna pattern is found for an observation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ignoreObservation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ignore observation if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"useNearestFrequency\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use pattern of nearest frequency if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"throwException\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>throw exception if no matching pattern is found</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSignalDefintion\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/transmitter/signalDefinition/signalDefinition.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>transmitted signal types</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileClockFrequencyScale\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\" default=\"orbit_{loopTime:%D}.{prn}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAttitude\" type=\"filename\" default=\"attitude_{loopTime:%D}.{prn}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileClock\" type=\"filename\" default=\"clock_{loopTime:%D}.{prn}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {prn} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolateClock\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>linear interpolation of missing epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for orbit interpolation and velocity calculation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"gravityfieldType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>functions of the gravity field</xs:documentation>\n\t\t\t<xs:appinfo>rename: fromRepresentation = fromParametrization</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"potentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>file with potential coefficients</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialCoefficients\" type=\"filename\" default=\"{groopsDataDir}/potential/\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"setSigmasToZero\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set variances to zero, should be used by adding back reference fields</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"potentialCoefficientsInterior\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>file with potential coefficients</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialCoefficients\" type=\"filename\" default=\"{groopsDataDir}/potential/\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"setSigmasToZero\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set variances to zero, should be used by adding back reference fields</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fromParametrization\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>from a solution vector with given parametrization</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrization</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSolution\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standards deviations or covariance matrix of the solution</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"indexStart\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position in the solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightSide\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if solution contains several right hand sides, select one</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"timeSplines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>file with splines in time domain</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileTimeSplinesGravityfield\" type=\"filename\" default=\"{groopsDataDir}/\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTimeSplinesCovariance\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"trend\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravityfield as trend</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>this field is multiplicated by (time-time0)/timeStep</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" default=\"51544.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeStep\" type=\"time\" default=\"365.25\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"oscillation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravityfield as oscillation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gravityfieldCos\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>multiplicated by cos(2pi/T(time-time0))</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfieldSin\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>multiplicated by sin(2pi/T(time-time0))</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time0\" type=\"time\" default=\"51544.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"period\" type=\"time\" default=\"365.25\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[day]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inInterval\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravityfields only valid in specific time interval</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>last point in time will be less or equal timeEnd</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"tides\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravityfield from tide models</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"tides\" type=\"tidesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"topography\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravityfield from topographic masses</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGridRectangular\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Digital Terrain Model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"density\" type=\"expression\" minOccurs=\"0\" default=\"2670\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression [kg/m**3]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radialUpperBound\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables &apos;height&apos;, &apos;data&apos;, &apos;L&apos;, &apos;B&apos; and, &apos;area&apos; are taken from the gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radialLowerBound\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables &apos;height&apos;, &apos;data&apos;, &apos;L&apos;, &apos;B&apos; and, &apos;area&apos; are taken from the gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"distanceMin\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[km] min. influence distance (ignore near zone)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"distancePrism\" type=\"double\" minOccurs=\"0\" default=\"15\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[km] max. distance for prism formular</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"distanceLine\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[km] max. distance for radial integration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"distanceMax\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[km] max. influence distance (ignore far zone)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"earthquakeOscillation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravityfield from earthquake oscillation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputCoefficientMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>oscillation model parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time0\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the time earthquake happened</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"filter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>filtered spherical harmonics</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"filter\" type=\"sphericalHarmonicsFilterType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>group gravityfields</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"gridType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>point distributions on the sphere/ellipsoid</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"geograph\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>along lines of geographical coordinates</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"deltaLambda\" type=\"angle\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"deltaPhi\" type=\"angle\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ellipsoidal height expression (variables &apos;height&apos;, &apos;L&apos;, &apos;B&apos;)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"triangleVertex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>triangle grid (vertcies)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"level\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>division of icosahedron, point count = 10*(n+1)**2+2</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"triangleCenter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>triangle grid (center points)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"level\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>division of icosahedron, point count = 5*4**(n+1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gauss\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gauss-legendre grid</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parallelsCount\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"reuter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>reuter grid</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gamma\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of parallels</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ellipsoidal height</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"corput\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>pseudo random distribution</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"globalPointsCount\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ellipsoidal height</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"driscoll\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>driscoll-healy grid</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"dimension\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of parallels = 2*dimension</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ellipsoidal height</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"singlePoint\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>one single point</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"L\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"B\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0.\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ellipsoidal height</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"area\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>associated area element on unit sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major axsis of the ellipsoid/sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>flattening of the ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"singlePointCartesian\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>one single point</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"x\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"y\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"z\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"area\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>associated area element on unit sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read points (with values) from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGrid\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"instrumentTypeType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>instrument type</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"INSTRUMENTTIME\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time without data</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"MISCVALUE\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>single value</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"MISCVALUES\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>multiple values</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"VECTOR3D\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>x, y, z</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"COVARIANCE3D\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>xx, yy, zz, xy, xz, yz</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ORBIT\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>position [m], velocity [m/s], acceleration [m/s^2] (each x, y, z)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"STARCAMERA\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>quaternions (q0, qx, qy, qz)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ACCELEROMETER\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>x, y, z [m/s^2]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SATELLITETRACKING\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>range [m], range rate [m/s], range acceleration [m/s^2]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GRADIOMETER\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>xx, yy, zz, xy, xz, yz [1/s^2]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GNSSRECEIVER\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GNSS phase/code observations [m]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"OBSERVATIONSIGMA\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accuracy</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SATELLITELASERRANGING\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>range [m], accuracy [m], redundancy, window [s], wavelength [m], azimuth [rad], elevation [rad]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"METEOROLOGICAL\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>temperature [K], pressure [Pa], humidity [%], windSpeed [m/s], radiation [W/m^2], precip. [mm/d]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"MASS\"/>\n\t\t\t<xs:element name=\"THRUSTER\"/>\n\t\t\t<xs:element name=\"MAGNETOMETER\"/>\n\t\t\t<xs:element name=\"ACCHOUSEKEEPING\"/>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"interpolatorTimeSeriesType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>resampling method</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"polynomial\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>polynomial prediction</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of the moving polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDataPointRange\" type=\"double\" default=\"-(3+1.1)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] all degree+1 data points must be within this range for a valid polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxExtrapolationDistance\" type=\"double\" minOccurs=\"0\" default=\"-1.1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] resampling points within this range of the polynomial will be extrapolated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"leastSquaresPolynomialFit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>least squares polynomial fit</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of the estimated polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDataPointDistance\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] all data points within this distance around the resampling point will be used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxExtrapolationDistance\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] resampling points within this range of the polynomial will be extrapolated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fillGapsLeastSquaresPolynomialFit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>least squares polynomial fit</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of the estimated polynomial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDataGap\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] max data gap to interpolate</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDataSpan\" type=\"double\" minOccurs=\"0\" default=\"20\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] time span on each side used for least squares fit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] margin for identical times</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"kernelType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>harmonic and isotropic integral kernels</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"geoidHeight\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>geoid = potential/normalgravity</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"anomalies\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravity anomalies, Stokes kernel</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"disturbance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravity disturbance, Hotine kernel</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"potential\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Abel-Poisson kernel</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"density\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>mass on a single layer (1/l kernel)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileLoadingLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"waterHeight\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>equivalent water columns, accounts the loading</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"density\" type=\"double\" default=\"1025\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[kg/m**3]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileLoadingLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"bottomPressure\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>ocean bottom pressure in Pascal, accounts for loading</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileLoadingLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"deformation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>radial deformation by loading</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileDeformationLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialLoadLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if full potential is given and not only loading potential</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"radialGradient\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>radial gravity gradient</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"coefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>construct kernel by a legendre-polynomial expansion</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileCoefficients\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"filterGauss\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>smoothing by a gauss filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"radius\" type=\"double\" default=\"500\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter radius [km]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"blackmanLowPass\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Blackman low-pass filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"startDegreeTransition\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum degree in transition band</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stopDegreeTransition\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum degree in transition band</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"truncation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>truncate kernel at specific degree</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>truncate before minDegree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>truncate after maxDegree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selenoidHeight\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>selenoid = potential/normalgravity</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"loopType\">\n\t\t<xs:annotation>\n\t\t\t<xs:appinfo>rename: temporal = timeIntervals</xs:appinfo>\n\t\t\t<xs:appinfo>rename: manualList = stringList</xs:appinfo>\n\t\t\t<xs:appinfo>rename: fileAscii = fileStringList</xs:appinfo>\n\t\t\t<xs:appinfo>rename: fileAsciiTable = fileStringTable</xs:appinfo>\n\t\t\t<xs:appinfo>rename: fileLines = fileTextLines</xs:appinfo>\n\t\t\t<xs:appinfo>rename: uniformSampling = numberSequence</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"timeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over points in time</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop is called for every point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTime\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with time of each loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"timeIntervals\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over time intervals</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeIntervals\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop is called for every interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTimeStart\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with starting time of each interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTimeEnd\" type=\"string\" minOccurs=\"0\" default=\"loopTimeEnd\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with ending time of each interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"stringList\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over list of strings</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"string\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>explicit list of strings</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopString\" type=\"string\" minOccurs=\"0\" default=\"loopString\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the variable to be replaced</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"stringTable\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over table of strings</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"row\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rows of a table</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"cell\" type=\"string\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>list of columns in a row</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"transpose\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop over columns instead of rows</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopString\" type=\"string\" default=\"loopString\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>1. variable name for the 1. column, next variable name for the 2. column, ... </xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fileStringList\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over list of strings from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>string list file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopString\" type=\"string\" minOccurs=\"0\" default=\"loopString\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the variable to be replaced</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fileStringTable\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over of a table containing strings</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>string table file with multiple columns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"transpose\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop over columns instead of rows</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopString\" type=\"string\" default=\"loopString\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>1. variable name for the 1. column, next variable name for the 2. column, ... </xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fileTextLines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over of lines of a text file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>simple text file with lines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start at element startIndex (counting from 0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"count\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use number of loops only (default: use all)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopLine\" type=\"string\" minOccurs=\"0\" default=\"loopLine\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the variable to be replaced</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"matrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over rows of a matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"transpose\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>effectively loop over columns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startRow\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start at this row (variable: rows)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countRows\" type=\"expression\" minOccurs=\"0\" default=\"rows\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use this many rows (variable: rows)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoop\" type=\"expression\" default=\"loopNumber=data0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a variable by name = expression (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"numberSequence\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over sequence of numbers</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rangeStart\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start of range</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rangeEnd\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>end of range (inclusive)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sampling</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopNumber\" type=\"string\" minOccurs=\"0\" default=\"loopNumber\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the variable to be replaced</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"directoryListing\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over files of a directory</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"directory\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>directory</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"pattern\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wildcard pattern</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"isRegularExpression\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>pattern is a regular expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopFile\" type=\"string\" minOccurs=\"0\" default=\"loopFile\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the variable to be replaced</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"commandOutput\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over lines of command output</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"command\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each output line becomes a loop iteration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"silently\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>without showing the output.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopString\" type=\"string\" minOccurs=\"0\" default=\"loopCommand\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the variable to be replaced</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"platformEquipment\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over equipment of a platform file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfilePlatform\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>platform info file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"equipmentType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>equipment type to loop over</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"all\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over all types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssAntenna\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over antennas</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssReceiver\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over receivers</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"slrStation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over SLR stations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"slrRetroReflector\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over laser retroreflectors</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"satelliteIdentifier\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over satellite identifiers</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"other\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over other types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopName\" type=\"string\" minOccurs=\"0\" default=\"loopName\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopSerial\" type=\"string\" minOccurs=\"0\" default=\"loopSerial\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with serial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopInfo\" type=\"string\" minOccurs=\"0\" default=\"loopInfo\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with radome (antenna) or version (receiver)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTimeStart\" type=\"string\" minOccurs=\"0\" default=\"loopTimeStart\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with start time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTimeEnd\" type=\"string\" minOccurs=\"0\" default=\"loopTimeEnd\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with end time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopPositionX\" type=\"string\" minOccurs=\"0\" default=\"loopPositionX\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with position x</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopPositionY\" type=\"string\" minOccurs=\"0\" default=\"loopPositionY\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with position y</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopPositionY\" type=\"string\" minOccurs=\"0\" default=\"loopPositionZ\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with position z</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"loop\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loop over loops</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"loop\" type=\"loopType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subloop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sortAndRemoveDuplicates\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sort loops</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"loop\" type=\"loopType\"/>\n\t\t\t\t\t\t<xs:element name=\"sortString\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use {loopVariables}, sort alphabetically</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"descending\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sorting descending instead of ascending</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeDuplicatesString\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use {loopVariables}, remove duplicates (order is preserved)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"manualTable\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2025-09-27. Use stringTable instead</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"table\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define table by rows/columns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rowWise\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>define table by rows</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"row\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>define table by rows</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"cell\" type=\"string\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>explicit list of cells in row/column</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"columnWise\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>define table by columns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"column\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>define table by columns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"cell\" type=\"string\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>explicit list of cells in row/column</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopString\" type=\"string\" default=\"loopString\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>1. variable name for the 1. column, next variable name for the 2. column, ... </xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fileGnssStationInfo\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2022-11-11. Use platformEquipment instead</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGnssStationInfo\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>station/transmitter info file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"infoType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>info to loop over</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"antenna\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over antennas</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"receiver\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop over receivers</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopName\" type=\"string\" minOccurs=\"0\" default=\"loopName\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with antenna/receiver name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopSerial\" type=\"string\" minOccurs=\"0\" default=\"loopSerial\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with antenna/receiver serial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopInfo\" type=\"string\" minOccurs=\"0\" default=\"loopInfo\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with radome (antenna) or version (receiver)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTimeStart\" type=\"string\" minOccurs=\"0\" default=\"loopTimeStart\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with antenna/receiver start time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTimeEnd\" type=\"string\" minOccurs=\"0\" default=\"loopTimeEnd\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with antenna/receiver end time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current iteration (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>check before each loop step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"magnetosphereType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>magentic field of the Earth</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"igrf\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>International Geomagnetic Reference Field</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMagneticNorthPole\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/magnetosphere/magneticNorthPole.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time series of north pole</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"matrixGeneratorType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>matrix calculation</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"normalsFile\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>from normal equation file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"normalMatrix\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rightHandSide\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"lPl\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationCount\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"expression\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>matrix filled by an expression</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rows\" type=\"expression\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(variables: rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"columns\" type=\"expression\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(variables: rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"element\" type=\"expression\" default=\"if(row==column,1,0)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each element of matrix (variables: row, column, rows, columns, rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"elementManipulation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>elements of a matrix are manipulated by an expression</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"element\" type=\"expression\" default=\"data\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each element of matrix (variables: data, row, column, rows, columns, rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"elementWiseOperation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>element wise operation of two matrices</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix1\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"matrix2\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"expression\" type=\"expression\" minOccurs=\"0\" default=\"data0*data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each element of matrix (variables: data0, data1, row, column, rows, columns, rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"append\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>append matrix to right or bottom</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"side\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"right\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"bottom\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"diagonal\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"shift\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>shift start row and/or start column</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"startRow\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start row (variables: rowsBefore, columnsBefore, rows, columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startColumn\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start column (variables: rowsBefore, columnsBefore, rows, columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"slice\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>slice of a matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"startRow\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start row of matrix (variables: rowsBefore, columnsBefore, rows, columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startColumn\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start column of matrix (variables: rowsBefore, columnsBefore, rows, columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rows\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0: until end (variables: rowsBefore, columnsBefore, rows, columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"columns\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0: until end (variables: rowsBefore, columnsBefore, rows, columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"reshape\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>matrix reshaped columnwise to new row and columns</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"rows\" type=\"expression\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0: auto-determine rows, (variables: rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"columns\" type=\"expression\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0: auto-determine columns (variables: rowsBefore, columnsBefore)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"reorder\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>reorder matrix with index vectors</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: rowIndex = inputfileIndexVectorRow</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: columnIndex = inputfileIndexVectorColumn</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileIndexVectorRow\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>index in input matrix or -1 for new parameter.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileIndexVectorColumn\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>index in input matrix or -1 for new parameter.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sort\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sort matrix by column</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"column\" type=\"uint\" default=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sort by column, top = highest priority</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"descending\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"transpose\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>transposed of a matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"multiplication\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>multiplication of matrices</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix1\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"matrix2\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inverse\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>inverse/pseudoinverse</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"pseudoInverse\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute pseudo inverse instead of regular one</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"cholesky\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>cholesky decomposition</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rankKUpdate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>rank k update (A^T*A)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"eigenValues\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>eigen values</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"eigenVectors\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>return eigen vectors instead of eigen values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"diagonal\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>diagonal of matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"diagonal\" type=\"int\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>zero: main diagonal, positive: superdiagonal, negative: subdiagonal</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fromDiagonal\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create matrix from diagonal vector</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(nx1) or (1xn) diagonal vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"diagonal\" type=\"int\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>zero: main diagonal, positive: superdiagonal, negative: subdiagonal</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"setType\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>set type of a matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"matrix\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"matrixSymmetricUpper\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"matrixSymmetricLower\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"matrixTriangularUpper\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"matrixTriangularLower\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"miscAccelerationsType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>non conservative forces acting on satellites</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"relativisticEffect\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Relativistic effect (IERS2010)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"beta\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PPN (parameterized post-Newtonian) parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gamma\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PPN (parameterized post-Newtonian) parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"J\" type=\"double\" minOccurs=\"0\" default=\"9.8e8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Earth’s angular momentum per unit mass [m**2/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"radiationPressure\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Solar and Earh radiation pressure model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"solarflux\" type=\"double\" minOccurs=\"0\" default=\"1367\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solar flux constant in 1 AU [W/m^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAlbedoTimeSeries\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/earthRadiationPressure/CERES_SYN1deg_albedo_climatology.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GriddedDataTimeSeries of albedo values (unitless)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileLongwaveFluxTimeSeries\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/earthRadiationPressure/CERES_SYN1deg_longwaveFlux_climatology.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GriddedDataTimeSeries of longwave flux values [W/m^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factorSolarRadation\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Solar radiation pressure is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factorEarthRadation\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Earth radiation preussure is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factorThermalRadiation\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Thermal (re-)radiation is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"atmosphericDrag\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>atmospheric drag</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"thermosphere\" type=\"thermosphereType\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"double\" minOccurs=\"0\" default=\"7.29211585531e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerTemperature\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute drag and lift, otherwise simple drag coefficient is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerWind\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"antennaThrust\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>antenna thrust</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"atmosphericDragFromDensityFile\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>atmospheric drag (from density along orbit)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileDensity\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>density along orbit, MISCVALUE (kg/m^3)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"thermosphere\" type=\"thermosphereType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to compute temperature and wind</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"double\" minOccurs=\"0\" default=\"7.29211585531e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerTemperature\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute drag and lift, otherwise simple drag coefficient is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerWind\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fromParametrization\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>from a solution vector with given parametrization</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"parametrizationAccelerationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSolution\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"indexStart\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position in the solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightSide\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if solution contains several right hand sides, select one</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>group misc accelerations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"miscAccelerations\" type=\"miscAccelerationsType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"solarRadiationPressure\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2022-12-19. Use radiationPressure instead.</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"solarflux\" type=\"double\" minOccurs=\"0\" default=\"1367\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solar flux constant in 1 AU [W/m**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"albedo\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2022-12-19. Use radiationPressure instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileEmissity = inputfileEmissivity</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileReflectivity\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/albedo/earth_ceres_reflectivity_grid2.5.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileEmissivity\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/albedo/earth_ceres_emissivity_grid2.5.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"solarflux\" type=\"double\" minOccurs=\"0\" default=\"1367\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solar flux constant in 1 AU [W/m**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"noiseGeneratorType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>generate different types of noise</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"white\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>white noise</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"initRandom\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start value for pseudo random sequence, 0: real random</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"expressionPSD\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>defined by one sided PSD</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Basis noise</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"psd\" type=\"expression\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one sided PSD (variable: freq [Hz]) [unit^2/Hz]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to determine frequency [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"filter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>noise conforms to psd of filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"filter\" type=\"digitalFilterType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>digital filter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Basis noise</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"warmupEpochCount\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of additional epochs at before start and after end</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"overSamplingFactor\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>noise with multiple higher sampling -&gt; filter -&gt; decimate</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"powerLaw\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>noise follows power law relationship (f^alpha)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Basis noise</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"alpha\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Exponent of the power law relationship 1/f^alpha</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"normalEquationType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>system of normal equations</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"design\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>from observation equations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: arcList = inputfileArcList</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"observation\" type=\"observationType\"/>\n\t\t\t\t\t\t<xs:element name=\"aprioriSigma\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add this normals at index of total matrix (counting from 0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to accelerate computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"designVCE\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>from observation equations with variance component estimation per arc</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: arcList = inputfileArcList</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"observation\" type=\"observationType\"/>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add this normals at index of total matrix (counting from 0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to accelerate computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read normal equations from file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"aprioriSigma\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add this normals at index of total matrix (counting from 0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"regularization\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>diagonal matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileDiagonalMatrix\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Vector with the diagonal elements of the weight matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileBias\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Matrix with right hand sides</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"aprioriSigma\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>regularization of parameters starts at this index (counting from 0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"regularizationGeneralized\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>regularization with a sum of partial covariance matrices</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfilePartialCovarianceMatrix\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>symmetric matrix (sum of all matrices must be positive definite)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileBiasMatrix\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>bias vector (default: zero vector)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"aprioriSigma\" type=\"double\" default=\"1.0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori sigmas for initial iteration (default: 1.0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>regularization of parameters starts at this index (counting from 0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"observationType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>obervation equations for least squares adjustment</xs:documentation>\n\t\t\t<xs:appinfo>rename: satelliteTracking = sstIntegral</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"podVariational\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>precise orbit data (variational equations)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"accelerateComputation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>acceleration of computation by transforming the observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod\" type=\"covariancePodType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"podIntegral\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>precise orbit data (integral approach)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"podRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for the reduced observation vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"gradientfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>low order field to estimate the change of the gravity by position adjustement</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"keepSatelliteStates\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set boundary values of each arc global</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"accelerateComputation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>acceleration of computation by transforming the observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod\" type=\"covariancePodType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"podAcceleration\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>precise orbit data (acceleration approach)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"podRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for the reduced observation vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit differentation  by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numberOfEpochs\" type=\"uint\" minOccurs=\"0\" default=\"9\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of used Epochs for polynom computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod\" type=\"covariancePodType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"podEnergy\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>precise orbit data (energy approach)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"podRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for the reduced observation vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization (potential)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationBias\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>unknown total energy per arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit differentiation  by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod\" type=\"covariancePodType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sstVariational\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sst data and pod</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter1 = parametrizationAcceleration1</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter2 = parametrizationAcceleration2</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameterSst = parametrizationSst</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite A as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite B as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationSst\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst\" type=\"covarianceSstType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of satellite to satellite tracking observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod1\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod2\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sstIntegral\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sst data and pod</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel1 = inputfileSatelliteModel1</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel2 = inputfileSatelliteModel2</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter1 = parametrizationAcceleration1</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter2 = parametrizationAcceleration2</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameterSst = parametrizationSst</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel1\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel2\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"sstRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for the reduced observation vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeAcceleration\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"gradientfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>low order field to estimate the change of the gravity by position adjustement</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationSst\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"keepSatelliteStates\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set boundary values of each arc global</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst\" type=\"covarianceSstType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of satellite to satellite tracking observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod1\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod2\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"dualSstVariational\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>dual sst data and pod</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking1\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking2\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite A as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite B as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationSst1\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter for first ranging observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationSst2\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter for second ranging observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst1\" type=\"covarianceSstType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of first satellite to satellite tracking observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst2\" type=\"covarianceSstType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of second satellite to satellite tracking observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceAcc\" type=\"covarianceSstType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>common covariance matrix of reduced satellite to satellite tracking observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod1\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod2\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gradiometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GOCE gradiometry</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"sggRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for the observation vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationBias\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>per arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useXX\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"useYY\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"useZZ\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"useXY\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"useXZ\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"useYZ\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"covarianceSgg\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>general variance factor</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>different accuaries for each arc (multplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance function in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"terrestrial\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>e.g. gravity anomalies, GPS/levelling</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observation\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[SI units]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"expression\" minOccurs=\"0\" default=\"sqrt(4*PI/area)\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracy, 1/sigma used as weighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"referencefield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>type of observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for reference field and parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blockingSize\" type=\"uint\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>segementation of the obervations if designmatrix can&apos;t be build at once</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"deflections\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>e.g. Deflections of the vertical</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationXi\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>North-South Deflections of the Vertical [rad]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationEta\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>East-West Deflections of the Vertical  [rad]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigmaXi\" type=\"expression\" minOccurs=\"0\" default=\"sqrt(4*PI/area)\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracy, 1/sigma used as weighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigmaEta\" type=\"expression\" minOccurs=\"0\" default=\"sqrt(4*PI/area)\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracy, 1/sigma used as weighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"referencefield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for reference field and parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blockingSize\" type=\"uint\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>segementation of the obervations if designmatrix can&apos;t be build at once</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"stationLoading\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Loading from station observations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>station positions with displacement data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationNorth\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>displacement [m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationEast\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>displacement [m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationUp\" type=\"expression\" default=\"data2\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>displacement [m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigmaNorth\" type=\"expression\" minOccurs=\"0\" default=\"data3\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracy, 1/sigma used as weighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigmaEast\" type=\"expression\" minOccurs=\"0\" default=\"data4\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracy, 1/sigma used as weighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigmaUp\" type=\"expression\" minOccurs=\"0\" default=\"data5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracy, 1/sigma used as weighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inGlobalFrame\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>obs/sigmas given in global x,y,z frame instead of north,east,up</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"referencefield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for reference field and parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>of loading (+defo) potential</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateTranslation\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>coordinate center</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateScale\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>scale factor of position</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateRotation\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDeformationLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialLoadLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if full potential is given and not only loading potential</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoid, 0: sphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"orbitPropagatorType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>algorithm for integration</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"euler\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Euler step method</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rungeKutta4\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>The classical Runge-Kutta 4 method</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"adamsBashforthMoulton\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Adams-Bashforth-Moulton class of predictor-corrector method</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\" default=\"4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Order of the Adams-Bashforth type propagator.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"applyMoultonCorrector\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Corrector step after Adams-Bashforth predcition.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"warmup\" type=\"orbitPropagatorType\" default=\"rungeKutta4\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"stoermerCowell\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Stoermer-Cowell predictor-corrector method</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\" default=\"4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Order of the Stoermer-Cowell type propagator.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"warmup\" type=\"orbitPropagatorType\" default=\"rungeKutta4\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gaussJackson\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Gauss-Jackson method</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>of Gauss-Jackson method.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"warmup\" type=\"orbitPropagatorType\" default=\"rungeKutta4\"/>\n\t\t\t\t\t\t<xs:element name=\"correctorIterations\" type=\"uint\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Maximum number of iterations to run the corrector step for.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"epsilon\" type=\"double\" minOccurs=\"0\" default=\"1e-15\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Convergence criteria for position, velocity, and acceleration tests.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"polynomial\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Integration Polynomial method using prediction only</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"degree\" type=\"uint\" default=\"9\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree to integrate accelerations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"shift\" type=\"int\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>shift polynomial in future (predicted accelerations)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"epsilon\" type=\"double\" default=\"1e-6\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] max. position change to recompute forces</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"warmup\" type=\"orbitPropagatorType\" default=\"rungeKutta4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to compute epochs before start epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"corrector\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply corrector iteration if position change is larger than epsilon</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read orbit from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>epoch at timeStart is not used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] to find identical times</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"recomputeForces\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parameterNamesType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>generate a list of parameter names</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"name\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>object this parameter refers to, e.g. graceA, G023, earth</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>type of this parameter, e.g. accBias, position.x</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>temporal representation of this parameter, e.g. trend, polynomial.degree1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileParameterNames\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file with parameter names</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"parametrizationGravity\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parametrization of gravity field</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>object these parameters refers to, e.g. earth</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"parametrizationAcceleration\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parametrization of orbit forces</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>object these parameters refers to, e.g. graceA, G023</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameterization\" type=\"parametrizationAccelerationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>defines the arc structure for arc related parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"parametrizationSatelliteTracking\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>satellite tracking parametrization</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>object these parameters refers to, e.g. grace1.grace2</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameterization\" type=\"parametrizationSatelliteTrackingType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"parametrizationTemporal\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>temporal parametrization</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterNameBase\" type=\"parameterNamesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"parametrizationGnssAntenna\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parametrization of GNSS antenna center variations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>antenna name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"parametrizationGnssAntennaType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"gnssType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. C1CG**</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"observation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parameters of oberservation equations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"observation\" type=\"observationType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rename\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>rename parts</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterName\" type=\"parameterNamesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched, object</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched, type</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched, temporal representation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*: left this part untouched, interval/epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selection\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterName\" type=\"parameterNamesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"withoutDuplicates\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterName\" type=\"parameterNamesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parameterSelectorType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>selected parameters</xs:documentation>\n\t\t\t<xs:appinfo>rename: name = wildcard</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"wildcard\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parameter name matching</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"object\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>object this parameter refers to, e.g. graceA, G023, earth (wildcards: * and ?)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>type of this parameter, e.g. accBias, position.x (wildcards: * and ?)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>temporal representation of this parameter, e.g. trend, polynomial.degree1 (wildcards: * and ?)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00 (wildcards: * and ?)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"names\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>manual list of parameter names</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterName\" type=\"parameterNamesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"range\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>range of parameters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"start\" type=\"expression\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start at this index (variables: length)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"count\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>count of parameters, default: all parameters to the end (variables: length)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"matrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>matrix containing parameter indexes</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>index in old parameter list or -1 for new parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"column\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use this column (counting from 0, variables: columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startRow\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start at this row (counting from 0, variables: rows)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countRows\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use these many rows (default: use all, variables: rows)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"zeros\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>additional zero parameters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"count\" type=\"expression\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>count of zero parameters (variables: length)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>groups a set of parameter selectors.</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"complement\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>all parameters except those selected</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parametrizationAccelerationType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"perRevolution\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>oscillation per revoultion</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>once, twice, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateX\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateY\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>cross</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateZ\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>radial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>setup new parameters each interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"accBias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accelerometer bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"estimateX\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateY\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>cross</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateZ\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>radial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"accelerometerScaleFactors\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accelerometer scale factors</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"estimateX\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateY\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>cross</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateZ\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>radial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateCrossTalk\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>non-orthognality of axes</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateRotation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>misalignment</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gnssSolarRadiation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GNSS solar radiation pressure model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"estimateD0\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant term along D-axis (sat-sun vector)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateD2\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>2-per-rev terms along D-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateD4\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>4-per-rev terms along D-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateY0\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant term along Y-axis (solar panel axis)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateB0\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant term along B-axis (cross product D x Y)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateB1\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>1-per-rev terms along B-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateB3\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>3-per-rev terms along B-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"thermosphericDensity\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>thermospheric density along the orbit</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"thermosphere\" type=\"thermosphereType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for wind and temperature</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"double\" minOccurs=\"0\" default=\"7.29211585531e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerTemperature\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute drag and lift, otherwise simple drag coefficient is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerWind\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"temporalDensity\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameters along orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"modelScale\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>model scale factor.</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"miscAccelerations\" type=\"miscAccelerationsType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parametrizationGnssAntennaType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>antenna center variations</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"center\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"estimateX\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"estimateY\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"estimateZ\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"sphericalHarmonics\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>max degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"radialBasis\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nodal points of shannon kernels</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min degree of shannon kernel</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>max degree of shannon kernel</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parametrizationGravityType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>parametrization of the gravity field</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"sphericalHarmonics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>potential coefficients!</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"radialBasis\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>harmonic radial basis functions</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>shape of the radial basis function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nodal point distribution</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"temporal\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time variable gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: temporal = parametrizationTemporal</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"linearTransformation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>linear transformation of a original parameters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravitySource\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransformationMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>transformation matrix from target to source parametrization (rows of this matrix must coincide with the parameter count of the source parametrization)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"earthquakeOscillation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>earthquake oscillation parameters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputInitialCoefficient\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>initial values for oscillation parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time0\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the time earthquake happened</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parametrizationSatelliteTrackingType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>SST parameters</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"antennaCenter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>antenna center</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"estimate1X\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimate1Y\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>cross (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimate1Z\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nadir (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimate2X\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimate2Y\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>cross (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimate2Z\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nadir (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>differentiation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"bias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>SST bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"scale\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>SST scale</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"timeBias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>SST time bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"scaleModel\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>scale factors for model from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"perArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"specialEffect\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>special effects from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEvents\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument with GRACE events</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"eclipse1\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"eclipse2\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"starCameraBox1\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"starCameraBox2\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"starCameraBox3\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"starCameraBox4\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"starCameraBox5\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"starCameraBox6\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"marginLeft\" type=\"double\" default=\"20\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin size (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"marginRight\" type=\"double\" default=\"20\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin size (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minNumberOfEvents\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min. number of events to setup parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"parametrizationTemporalType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>Parametrization of temporal variations</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"constant\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Constant in time</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"includeLastTime\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"trend\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Linear trend</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" default=\"51544.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeStep\" type=\"time\" default=\"365.25\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"splines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Splines</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"degree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nodal points in time domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"intervals\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"includeLastTime\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"polynomial\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Polynomial</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>intervals of polynomials</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"includeLastTime\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"oscillation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Oscillations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"period\" type=\"time\" default=\"365.25\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[day]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time0\" type=\"time\" default=\"51544.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fourier\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Fourier series</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"fourierDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"interval\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>intervals of fourier series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"includeLastTime\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"doodsonHarmonic\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Tidal variations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"doodson\" type=\"doodson\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>code number (e.g. 255.555) or darwin name (e.g. M2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAdmittance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolation of minor constituents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"planetType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>planet</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"earth\"/>\n\t\t\t<xs:element name=\"sun\"/>\n\t\t\t<xs:element name=\"moon\"/>\n\t\t\t<xs:element name=\"mercury\"/>\n\t\t\t<xs:element name=\"venus\"/>\n\t\t\t<xs:element name=\"mars\"/>\n\t\t\t<xs:element name=\"jupiter\"/>\n\t\t\t<xs:element name=\"saturn\"/>\n\t\t\t<xs:element name=\"uranus\"/>\n\t\t\t<xs:element name=\"neptune\"/>\n\t\t\t<xs:element name=\"pluto\"/>\n\t\t\t<xs:element name=\"solarBaryCenter\"/>\n\t\t\t<xs:element name=\"earthMoonBaryCenter\"/>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"platformSelectorType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>selected platforms (stations, satellites, ...)</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"all\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>all available platforms</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"wildcard\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select by name and number</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"markerName\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?, from platform</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"markerNumber\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?, from platform</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"exclude\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>deselect matching platforms</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select from file (with alternatives)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStringTable\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of names with alternatives</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"exclude\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>deselect first matching platforms</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"equipment\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select by equipment</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"equipmentType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>equipment type</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"all\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>all types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssAntenna\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>antennas</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssReceiver\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>receivers</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"version\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"slrStation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>SLR station</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"slrRetroReflector\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>laser retroreflector</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"satelliteIdentifier\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite identifier</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"cospar\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"norad\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sic\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sp3\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"other\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>other types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"exclude\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>deselect matching platforms</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"exclude\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>deselect from selection</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selector\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotAxisType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>axis limits, labels and annotation</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"standard\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>generic x/y axis</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: annotation = majorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frame = minorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: grid = gridLineSpacing</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"min\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The minimum value of the axis. If no value is given, the minimum scale value is set automatically.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"max\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The maximum value of the axis. If no value is given, the maximum scale value is set automatically.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacing\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The boundary annotation.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacing\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The spacing of the frame tick intervals.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacing\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The spacing of the grid line intervals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLine\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;:&quot;0.25&quot;, &quot;color&quot;:&quot;gray&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The style of the grid lines.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"unit\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Naming unit to append to the axis values.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"label\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The description of the axis.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"logarithmic\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>If set to &apos;yes&apos;, a logarithmic scale is used for the axis.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Setting the color of the axis bars and labels.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"changeDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>If set to &apos;yes&apos;, the directions right/up are changed to left/down.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"time\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>intepret x-values as MJD</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: annotation = majorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frame = minorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: grid = gridLineSpacing</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"min\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The minimum value of the time axis. If no value is given, the minimum scale value is set automatically.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"max\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The maximum value of the time axis. If no value is given, the maximum scale value is set automatically.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacing\" type=\"string\" minOccurs=\"0\" default=\"2o\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Y: year, o: month</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacing\" type=\"string\" minOccurs=\"0\" default=\"1o\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>D: date, d: day</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacing\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>H: clock, h: hour, m: minute, s: second</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"secondary\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>secondary time axis</xs:documentation>\n\t\t\t\t\t\t\t\t<xs:appinfo>rename: annotation = majorTickSpacing</xs:appinfo>\n\t\t\t\t\t\t\t\t<xs:appinfo>rename: frame = minorTickSpacing</xs:appinfo>\n\t\t\t\t\t\t\t\t<xs:appinfo>rename: grid = gridLineSpacing</xs:appinfo>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"majorTickSpacing\" type=\"string\" minOccurs=\"0\" default=\"1Y\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Y: year, o: month</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"minorTickSpacing\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>D: date, d: day</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gridLineSpacing\" type=\"string\" minOccurs=\"0\" default=\"1Y\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>H: clock, h: hour, m: minute, s: second</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>color of axis bars and labels</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLine\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;:&quot;0.25&quot;, &quot;color&quot;:&quot;gray&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The style of the grid lines.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"changeDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>right-&gt;left / up-&gt;down</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"options\" type=\"string\" minOccurs=\"0\" default=\"[&quot;FORMAT_DATE_MAP=yyyy-mm-dd&quot;, &quot;FORMAT_CLOCK_MAP=hh:mm&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>adjust date format</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"labeled\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>major ticks with string labels</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"labels\" type=\"string\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tick labels (ticks are placed at their index. e.g. 0, 1, ..., 5)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"min\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum value of the axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"max\" type=\"expression\" minOccurs=\"0\" default=\"labelCount-1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum values of the axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacing\" type=\"expression\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The boundary annotation.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacing\" type=\"expression\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The spacing of the frame tick intervals.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacing\" type=\"expression\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The spacing of the grid line intervals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLine\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;:&quot;0.25&quot;, &quot;color&quot;:&quot;gray&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The style of the grid lines.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set the color of the axis and labels</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"orthogonalLabels\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>labels are oriented orthogonal to axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"changeDirection\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>If set to &apos;yes&apos;, the directions right/up are changed to left/down.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotColorType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>color</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"black\"/>\n\t\t\t<xs:element name=\"red\"/>\n\t\t\t<xs:element name=\"blue\"/>\n\t\t\t<xs:element name=\"green\"/>\n\t\t\t<xs:element name=\"orange\"/>\n\t\t\t<xs:element name=\"darkred\"/>\n\t\t\t<xs:element name=\"yellow\"/>\n\t\t\t<xs:element name=\"lightgreen\"/>\n\t\t\t<xs:element name=\"gray\"/>\n\t\t\t<xs:element name=\"rgb\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"red\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0..255</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"green\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0..255</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blue\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0..255</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"grayscale\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0..255</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"namedColor\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"colorName\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name after GMT definition</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"cycler\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"index\" type=\"uint\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>pick color based on index expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileColorList\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/plot/colors.conf\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of colors as defined by GMT</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotColorbarType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"min\" type=\"double\" minOccurs=\"0\"/>\n\t\t\t<xs:element name=\"max\" type=\"double\" minOccurs=\"0\"/>\n\t\t\t<xs:element name=\"annotation\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"unit\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>appended to axis values</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"label\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>description of the axis</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"logarithmic\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>use logarithmic scale</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"triangleLeft\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t<xs:element name=\"triangleRight\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t<xs:element name=\"illuminate\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>illuminate</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"vertical\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>plot vertical color bar on the right</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"length\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>length of colorbar in percent</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"0.4\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>between colorbar and figure [cm]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"colorTable\" type=\"string\" minOccurs=\"0\" default=\"haxby\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>name of the color bar</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"reverse\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>reverse direction</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"showColorbar\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotGraphLayerType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>lines, points and polygons</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"linesAndPoints\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>line/points</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each line contains x,y</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueX\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for x-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueY\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for y-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueZ\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for the colorbar</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueErrorBar\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for error bars (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>text of the legend</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"plotLineType\" minOccurs=\"0\" default=\"solid\"/>\n\t\t\t\t\t\t<xs:element name=\"symbol\" type=\"plotSymbolType\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"errorEnvelope\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>error envelope for line plots</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each line contains x,y</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueX\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for x-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueY\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for y-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueErrors\" type=\"expression\" default=\"data2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for error values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>text of the legend</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fillColor\" type=\"plotColorType\" minOccurs=\"0\" default=\"gray\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>fill color of the envelope</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"edgeLine\" type=\"plotLineType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>edge line style of the envelope</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"bars\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>bar graph</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each line contains x,y</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueX\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for x-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueY\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for y-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueZ\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for the colorbar</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueBase\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>base value of bars (default: minimum y-value)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"width\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>width of bars (default: minimum x-gap)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"horizontal\" type=\"boolean\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw horizontal bars instead of vertical</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>text of the legend</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\"/>\n\t\t\t\t\t\t<xs:element name=\"edgeLine\" type=\"plotLineType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gridded\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>mesh data</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each line contains x,y,z</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueX\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for x-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueY\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for y-values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueZ\" type=\"expression\" default=\"data2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for the colorbar</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"incrementX\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the grid spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"incrementY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the grid spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rectangle\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>draw rectangle</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"minX\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: left</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxX\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: right</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: bottom</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: top</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>text of the legend</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"edgeLine\" type=\"plotLineType\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"fillColor\" type=\"plotColorType\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"text\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>text</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"text\" type=\"string\"/>\n\t\t\t\t\t\t<xs:element name=\"originX\" type=\"double\"/>\n\t\t\t\t\t\t<xs:element name=\"originY\" type=\"double\"/>\n\t\t\t\t\t\t<xs:element name=\"offsetX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[cm] x-offset from origin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"offsetY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[cm] y-offset from origin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"alignment\" type=\"string\" minOccurs=\"0\" default=\"BL\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>L, C, R (left, center, right) and T, M, B (top, middle, bottom)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fontSize\" type=\"double\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[pt]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fontColor\" type=\"plotColorType\"/>\n\t\t\t\t\t\t<xs:element name=\"clip\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>clip at boundaries</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"degreeAmplitudes\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>degree amplitudes of a gravity field</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree amplitudes</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueDegree\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for x-values (degrees) (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueSignal\" type=\"expression\" minOccurs=\"0\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for y-values (signal) (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueErrors\" type=\"expression\" minOccurs=\"0\" default=\"data2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression for y-values (formal errors)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>text of the legend</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"lineSignal\" type=\"plotLineType\" minOccurs=\"0\" default=\"solid\"/>\n\t\t\t\t\t\t<xs:element name=\"lineErrors\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;custom&quot;: {&quot;style&quot;:&quot;5_2:0&quot;}}\"/>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"degreeAmplitudesSimple\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>degree amplitudes of a gravity field</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>type of variances</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rms\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>degree amplitudes (square root of degree variances)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"accumulation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>cumulate variances over degrees</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"median\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>median of absolute values per degree</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>text of the legend</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"lineSignal\" type=\"plotLineType\" minOccurs=\"0\" default=\"solid\"/>\n\t\t\t\t\t\t<xs:element name=\"lineErrors\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;custom&quot;: {&quot;style&quot;:&quot;5_2:0&quot;}}\"/>\n\t\t\t\t\t\t<xs:element name=\"plotOnSecondAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw dataset on a second Y-axis (if available).</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotLegendType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>legend width [cm]</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>legend height [cm] (default: estimated)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"positionX\" type=\"double\" minOccurs=\"0\" default=\"1.05\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>legend x-position in normalized (0-1) coordinates.</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"positionY\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>legend y-position in normalized (0-1) coordinates.</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"anchorPoint\" type=\"string\" minOccurs=\"0\" default=\"TL\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Two character combination of L, C, R (for left, center, or right) and T, M, B for top, middle, or bottom. e.g., TL for top left</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"columns\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>number of columns in legend</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"textColor\" type=\"plotColorType\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>color of the legend text</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"fillColor\" type=\"plotColorType\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>fill color of the legend box</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"edgeLine\" type=\"plotLineType\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>style of the legend box edge</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotLineType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>line style</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"solid\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>solid line</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line width [p]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"dashed\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>dashed line</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line width [p]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"dotted\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>dotted line</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line width [p]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>  </xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"custom\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>custom line (e.g. dash-dot)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"style\" type=\"string\" default=\".-\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line style code</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line width [p]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotMapLayerType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>plot layers</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"griddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>data with regular sampling</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"increment\" type=\"angle\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the grid spacing [degrees]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"illuminate\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>illuminate grid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"resample\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"intermediateDpi\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>oversample grid for a smoother visual effect</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"interpolationMethod\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>interpolation method for oversampling</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"bspline\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>B-Spline interpolation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"bicubic\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>bicubic interpolation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"bilinear\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>bilinear interpolation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"nearest\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>nearest neighbour interpolation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"threshold\" type=\"double\" minOccurs=\"0\" default=\"0.5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>A threshold of 1.0 requires all (4 or 16) nodes involved in interpolation to be non-NaN. 0.5 will interpolate about half way from a non-NaN value; 0.1 will go about 90% of the way.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridlineRegistered\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>treat input as point values instead of cell means</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"points\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>colored points</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute color (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"symbol\" type=\"plotSymbolType\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"plotLineType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>style of connecting lines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"drawLineAsGreatCircle\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw connecting lines as great circles (otherwise, a straight line is drawn instead)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"arrows\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>colored arrows</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>grid file with north and east values for arrows</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueNorth\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute north values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"valueEast\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute east values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute arrow color (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"scale\" type=\"double\" minOccurs=\"0\" default=\"50\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[cm per input unit] length scale factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"penSize\" type=\"double\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[pt] width of arrow shaft</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"headSize\" type=\"double\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[pt] size of arrow head, 0: no head, negative: reverse head</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"scaleArrow\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw an arrow for scale reference</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"originX\" type=\"double\" default=\"0.055\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[0-1] 0: left, 1: right</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"originY\" type=\"double\" default=\"0.065\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[0-1] 0: bottom, 1: top</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"length\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in same unit as valueNorth and valueEast</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"unit\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>displayed unit text (e.g. 1 cm)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"label\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>description of the arrows</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"polygon\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>boundaries</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfilePolygon\" type=\"filename\" default=\"{groopsDataDir}/border/\"/>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"plotLineType\" minOccurs=\"0\" default=\"solid\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>style of border lines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fillColor\" type=\"plotColorType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polygon fill color (no fill color: determine from value if given, else: no fill)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>value to compute fill color from a colorbar (ignored if a fillColor is given)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"drawLineAsGreatCircle\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>draw connecting lines as great circles (otherwise, a straight line is drawn instead)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"coast\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>coast lines, ...</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"resolution\" default=\"medium\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"crude\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"low\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"medium\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"high\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"full\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;: &quot;1&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>line style for coastlines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"landColor\" type=\"plotColorType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>fill land area</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"oceanColor\" type=\"plotColorType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>fill ocean area</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minArea\" type=\"uint\" minOccurs=\"0\" default=\"5000\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[km^2] features with a smaller area than this are dropped</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rivers\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>major rivers</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"class\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"riversCanalsLakes\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"riversCanals\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"permanentRiversLakes\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"permanentRivers\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"intermittentRivers\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"canals\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"singleClass\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"class\" type=\"uint\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>0-10. See GMT documentation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"plotLineType\" default=\"{&quot;solid&quot;: {&quot;width&quot;: &quot;1&quot;}}\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"politicalBoundary\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>political boundaries</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"resolution\" default=\"medium\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"crude\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"low\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"medium\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"high\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"full\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"plotLineType\" default=\"{&quot;solid&quot;: {&quot;width&quot;: &quot;0.25&quot;}}\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"blueMarble\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>blue marble</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileImage\" type=\"filename\" default=\"{groopsDataDir}/plot/bluemarble/1800x900/bluemarble.05.jpg\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Blue Marble image file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"brightness\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>brightness of bitmap [-1, 1]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"illuminate\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add hillshade based on topography</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTopography\" type=\"filename\" default=\"{groopsDataDir}/plot/bluemarble/1800x900/bluemarble.topography.grd\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>GMT grid file containing topography.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"azimuth\" type=\"angle\" minOccurs=\"0\" default=\"315\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>direction of lighting source [deg]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"elevation\" type=\"angle\" minOccurs=\"0\" default=\"45\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>direction of lighting source [deg]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ambient\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ambient lighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"diffuse\" type=\"double\" minOccurs=\"0\" default=\"0.6\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>diffuse lighting</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"specular\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>specular reflection</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"shine\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>surface shine</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"amplitude\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>scale gradient by factor</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"text\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>text</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"text\" type=\"string\"/>\n\t\t\t\t\t\t<xs:element name=\"originLongitude\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"originLatitude\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"offsetX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[cm] x-offset from origin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"offsetY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[cm] y-offset from origin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"alignment\" type=\"string\" minOccurs=\"0\" default=\"LB\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>L, C, R (left, center, right) and T, M, B (top, middle, bottom)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fontSize\" type=\"double\" minOccurs=\"0\" default=\"10\"/>\n\t\t\t\t\t\t<xs:element name=\"fontColor\" type=\"plotColorType\"/>\n\t\t\t\t\t\t<xs:element name=\"clip\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>clip at boundaries</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotMapProjectionType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>plot layers</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"robinson\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>robinson projection</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"centralMeridian\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>central meridian [degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"orthographic\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>orthographic projection</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"lambdaCenter\" type=\"angle\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>central point [degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phiCenter\" type=\"angle\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>central point [degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"perspective\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>perspective sphere</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"lambdaCenter\" type=\"angle\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude of central point in degrees</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phiCenter\" type=\"angle\" minOccurs=\"0\" default=\"40\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of central point in degrees</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"altitude\" type=\"double\" minOccurs=\"0\" default=\"1500\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[km]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"azimuth\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to the east of north of view [degrees]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tilt\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>upward tilt of the plane of projection, if negative, then the view is centered on the horizon [degrees]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"viewpointTwist\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>clockwise twist of the viewpoint [degrees]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"viewpointWidth\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>width of the viewpoint [degrees]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"viewpointHeight\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>height of the viewpoint [degrees]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"polar\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>polar stereographic</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"lambdaCenter\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude of central point in degrees</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phiCenter\" type=\"angle\" minOccurs=\"0\" default=\"-90\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of central point in degrees</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"skyplot\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>skyplot</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"linear\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>linear (plate carree) projection</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Utm\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>UTM projection</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"zone\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>UTM zone code (e.g. 33N)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"lambert\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>lambert conformal conic</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"lambda0\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude of projection center [deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phi0\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of projection centert [deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phi1\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of first standard parallel [deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phi2\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of first standard parallel [deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"mollweide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>mollweide projection </xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"centralMeridian\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>central meridian [degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"plotSymbolType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>symbol</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"circle\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"star\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"cross\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"square\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"triangle\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"diamond\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"dash\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"color\" type=\"plotColorType\" minOccurs=\"0\" default=\"black\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>empty: determined from value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"size\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>size of symbol [point]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"blackContour\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"podRightSideType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>kinematic positions of satellite as observations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>non-gravitational forces in satellite reference frame</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"forces\" type=\"forcesType\"/>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"sggRightSideType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"inputfileGradiometer\" type=\"filename\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>observed gravity gradients</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileReferenceGradiometer\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>precomputed gradients at orbit positions</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"referencefield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t<xs:element name=\"tides\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"slrParametrizationType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>parametrization of SLR observations</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"troposphere\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>tropospheric delays</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.troposphere\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileTroposphere\" type=\"filename\" minOccurs=\"0\" default=\"output/troposphere_{loopTime:%D}.{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"troposphere\" type=\"troposphereType\" default=\"{&quot;mendesAndPavlis&quot;:{}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>a priori troposphere model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"troposphereEstimation\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] parametrization of zenith delays</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"dynamicOrbits\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>satellite orbits by variational equations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.dynamicOrbits\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameters\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\" default=\"variational_{loopTime:%D}.{satellite}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stochasticPulse\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[mu/s] parametrization of stochastic pulses</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for orbit interpolation and velocity calculation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gravityField\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>gravity field of the Earth</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.gravityField\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"parametrizationGravityType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"staticPositions\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>static positions with no-net constraints</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.staticPositions\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedPosition\" type=\"filename\" minOccurs=\"0\" default=\"output/gridPosition_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>delta north east up for all stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfilePosition\" type=\"filename\" minOccurs=\"0\" default=\"output/stationPosition_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, full estimated coordinates (in TRF)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nameConstraint\" type=\"string\" minOccurs=\"0\" default=\"constraint.staticPositions\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectNoNetStations\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNoNetPositions\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/slr/stations/position/slrf2020_CM/stationPosition.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, precise coordinates used for no-net constraints (in TRF)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noNetTranslationSigma\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noNetRotationSigma\" type=\"double\" minOccurs=\"0\" default=\"0.001\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] at Earth&apos;s surface for no-net rotation constraint on station coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noNetScaleSigma\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>stations &gt; huber*sigma0 are downweighted in no-net constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>stations &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"earthRotation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Earth rotation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.earthRotation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileEOP\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimatePole\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>xp, yp [mas]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateUT1\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation angle [ms]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateNutation\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>dX, dY [mas]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rangeBiasStationApriori\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>apriori range bias from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileRangeBias\" type=\"filename\" default=\"{groopsDataDir}/slr/stations/rangeBias/rangeBias.{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rangeBiasStation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>range bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.rangeBiasStation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileRangeBias\" type=\"filename\" default=\"rangeBias_{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rangeBiasSatelliteApriori\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>apriori range bias from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileRangeBias\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rangeBiasSatellite\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>range bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.rangeBiasSatellite\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileRangeBias\" type=\"filename\" default=\"rangeBias_{satellite}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rangeBiasStationSatelliteApriori\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>apriori range bias from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileRangeBias\" type=\"filename\" default=\"{groopsDataDir}/slr/rangeBiasStationSatellite/modelRodriguez/rangeBias.{station}.{satellite}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} and {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"rangeBiasStationSatellite\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>range bias</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.rangeBiasSatellite\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileRangeBias\" type=\"filename\" default=\"rangeBias_{station}_{satellite}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} and {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"timeBiasApriori\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>apriori time bias at station from file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTimeBias\" type=\"filename\" default=\"{groopsDataDir}/slr/stations/timeBias/timeBias.{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"timeBias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time bias at station</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"parameter.timeBias\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used for parameter selection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\" default=\"[&quot;all&quot;]\"/>\n\t\t\t\t\t\t<xs:element name=\"estimateTimeBias\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[ms]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"constraints\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>parameter constraints</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"constraint.name\"/>\n\t\t\t\t\t\t<xs:element name=\"parameters\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter to constrain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma of the constraint (same unit as parameter)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"bias\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constrain all selected parameters towards this value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"relativeToApriori\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constrain only dx and not full x=dx+x0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>grouping parametrizations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"slrParametrizationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"slrProcessingStepType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"estimate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>least squares adjustment</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"computeResiduals\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"adjustSigma0\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>adjust sigma0 by scale factor (per station)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeWeights\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>downweight outliers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber: sigma=(e/huber)^huberPower*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"convergenceThreshold\" type=\"double\" minOccurs=\"0\" default=\"0.01\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] stop iteration once full convergence is reached</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxIterationCount\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeResults\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write all estimated parameters</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"suffix\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>appended to every output file name (e.g. orbit.G01.suffix.dat)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeNormalEquations\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write unconstrained and constraint normal equations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquations\" type=\"filename\" default=\"output/normals_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"remainingParameters\" type=\"parameterSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of output normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"constraintsOnly\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>write only normals of constraints without observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultNormalsBlockSize\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block, empty: original block size</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeAprioriSolution\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write apriori solution vector</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAprioriSolution\" type=\"filename\" minOccurs=\"0\" default=\"output/x0_{loopTime:%D}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>a priori parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\" minOccurs=\"0\" default=\"output/parameterNames_{loopTime:%D}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter names</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"remainingParameters\" type=\"parameterSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of output normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeResiduals\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write observation residuals</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used satellites</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileResiduals\" type=\"filename\" default=\"output/residuals_{loopTime:%D}.{station}.{satellite}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeUsedStationList\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write used stations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileUsedStationList\" type=\"filename\" default=\"output/stationList.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with names of used stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"writeUsedSatelliteList\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write used satellites</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subset of used satellites</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileUsedSatelliteList\" type=\"filename\" default=\"output/satelliteList.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with names</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"printResidualStatistics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>print residual statistics</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectParametrizations\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>select parametrizations for all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"enable\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"*\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"disable\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"*\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>wildcards: * and ?</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectSatellites\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>use this subset of satellites in all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectSatellites\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"selectStations\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>use this subset of stations in all subsequent processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"selectStations\" type=\"platformSelectorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>group processing steps</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"processingStep\" type=\"slrProcessingStepType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>steps are processed consecutively</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"slrSatelliteGeneratorType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"satellites\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteList\" type=\"filename\" default=\"{groopsDataDir}/slr/satellites/satelliteList.txt\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with satellite names, used to loop variable {satellite}</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteInfo\" type=\"filename\" default=\"{groopsDataDir}/slr/satellites/satelliteInfo/satelliteInfo.{satellite}.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\" default=\"{satellite}_orbit_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAttitude\" type=\"filename\" minOccurs=\"0\" default=\"{satellite}_attitude_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for orbit interpolation and velocity calculation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"slrStationGeneratorType\">\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"stations\">\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationList\" type=\"filename\" default=\"{groopsDataDir}/slr/stations/stationList.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ascii file with station names</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" default=\"{groopsDataDir}/slr/stations/stationInfo/stationInfo.{station}.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>station metadata</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationPosition\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/slr/stations/position/slrf2020_CM/stationPosition.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>station position</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"disableStationWithoutPosition\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>drop stations without apriori position</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileObservations\" type=\"filename\" minOccurs=\"0\" default=\"normalPoints_{satellite}_{station}_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} {satellite} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"accuracy\" type=\"expression\" default=\"if(abs(residual)&gt;30, NAN, accuracy)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] used for weighting, variables: {residual}, {accuracy}, {redundancy}, {laserWavelength}, {azimut}, {elevation}</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"loadingDisplacement\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loading deformation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tidalDisplacement\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tidal deformation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for tidal deformation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDeformationLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialLoadLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if full potential is given and not only loading potential</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elevationCutOff\" type=\"angle\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] ignore observations below cutoff</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for position interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"sphericalHarmonicsFilterType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>filtering of spherical harmonics</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"filterDdk\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>smoothing by a DDK filter</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"level\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>DDK filter level (1, 2, 3, ..., 8)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\" default=\"{groopsDataDir}/sphericalHarmonicsFilter/DDK/normalsKuscheGfzBlock_n2-120_orderwiseNonAlternating.dat.gz\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"filterGauss\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>smoothing by a isotropic gaussian filter</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"radius\" type=\"double\" default=\"500\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter radius [km]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"filterMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>smoothing by a filter matrix</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>of matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>of matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme of the matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"sphericalHarmonicsNumberingType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>Numbering schema of spherical harmonics coefficients</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"degreewise\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sort degree by degree</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"orderwise\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sort order by order</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"orderwiseNonAlternating\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sort order by order with cnm, snm non-alternating</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"file\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>sort as specified in the chosen file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"sstRightSideType\">\n\t\t<xs:sequence>\n\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>kinematic positions of satellite A as observations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>kinematic positions of satellite B as observations</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileAccelerometer1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>non-gravitational forces in satellite reference frame A</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"inputfileAccelerometer2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>non-gravitational forces in satellite reference frame B</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"forces\" type=\"forcesType\"/>\n\t\t</xs:sequence>\n\t</xs:complexType>\n\t<xs:complexType name=\"thermosphereType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>density, temperature and velocity</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"jb2008\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Jacchia-Bowman 2008 Empirical Thermospheric Density Model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileSolfsmy\" type=\"filename\" default=\"{groopsDataDir}/thermosphere/jb2008/SOLFSMY.TXT\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solar indices</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDtc\" type=\"filename\" default=\"{groopsDataDir}/thermosphere/jb2008/DTCFILE.TXT\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileMagnetic3hAp\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/thermosphere/hwm14/apActivity.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>indicies for wind model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"hwm14DataDirectory\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/thermosphere/hwm14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"nrlmsis2\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>NRLMSIS 2.0 Empirical Thermospheric Density Model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileMsis\" type=\"filename\" default=\"{groopsDataDir}/thermosphere/nrlmsis2/inputMSIS.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input NRLMSIS 2.0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileModelParameters\" type=\"filename\" default=\"{groopsDataDir}/thermosphere/nrlmsis2/msis20.parm\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>path to msis20.parm file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileMagnetic3hAp\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/thermosphere/hwm14/apActivity.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>indicies for wind model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"hwm14DataDirectory\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/thermosphere/hwm14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"tidesType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>tidal forces</xs:documentation>\n\t\t\t<xs:appinfo>rename: poleTide2010 = poleTide</xs:appinfo>\n\t\t\t<xs:appinfo>rename: poleOceanTide2010 = oceanPoleTide</xs:appinfo>\n\t\t\t<xs:appinfo>rename: moonTide = solidMoonTide</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"astronomicalTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>direct tides from sun, moon and planets</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"useMoon\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>TGP of moon</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useSun\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>TGP of sun</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"usePlanets\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>TGP of planets</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useEarth\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>TGP of Earth</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"c20Earth\" type=\"double\" minOccurs=\"0\" default=\"-4.84166854896119e-04\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>J2 flattening of the Earth</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"earthTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>solid earth tides</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileEarthtide\" type=\"filename\" default=\"{groopsDataDir}/tides/earthAnelastic2003.xml\"/>\n\t\t\t\t\t\t<xs:element name=\"includePermanentTide\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>results in FALSE: zero tide, TRUE: tide free gravity field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"doodsonHarmonicTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>tides with harmonic representation, e.g. ocean tides</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileOcean = inputfileTides</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileTides\" type=\"filename\" default=\"{groopsDataDir}/tides/oceanTide_fes2022_n180_version20241110.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAdmittance\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/tides/oceanTide_fes2022_admittance_linear_linear.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolation of minor constituents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectDoodson\" type=\"doodson\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>consider only these constituents, code number (e.g. 255.555) or darwin name (e.g. M2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"nodeCorr\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nodal corrections: 0-no corr, 1-IHO, 2-Schureman</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"poleTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>centrifugal effect of polar motion</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"scale\" type=\"double\" minOccurs=\"0\" default=\"1.333e-9\"/>\n\t\t\t\t\t\t<xs:element name=\"outPhase\" type=\"double\" minOccurs=\"0\" default=\"0.0115\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileMeanPole\" type=\"filename\" default=\"{groopsDataDir}/tides/secularPole2018.xml\"/>\n\t\t\t\t\t\t<xs:element name=\"horizontalDisplacement\" type=\"double\" minOccurs=\"0\" default=\"0.009\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"verticalDisplacement\" type=\"double\" minOccurs=\"0\" default=\"0.033\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"oceanPoleTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>The ocean pole tide is generated by the centrifugal effect of polar motion on the oceans</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileOceanPole\" type=\"filename\" default=\"{groopsDataDir}/tides/oceanPoleTide_desai2004.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"gammaReal\" type=\"double\" minOccurs=\"0\" default=\"0.6870\"/>\n\t\t\t\t\t\t<xs:element name=\"gammaImaginary\" type=\"double\" minOccurs=\"0\" default=\"0.0036\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileMeanPole\" type=\"filename\" default=\"{groopsDataDir}/tides/secularPole2018.xml\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"centrifugal\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Current centrifugal force from Earth rotation</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"solidMoonTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>solid moon tides (at moon)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"k20\" type=\"double\" minOccurs=\"0\" default=\"0.0213\"/>\n\t\t\t\t\t\t<xs:element name=\"k30\" type=\"double\" minOccurs=\"0\" default=\"0.0\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"group\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>group tides</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"tides\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"timeSeriesType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>Generates time series</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"uniformSampling\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>uniform series with given sampling</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>last point in time will be less or equal timeEnd</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time step between points in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"uniformInterval\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>uniform series with given interval count</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>1st point of the time series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>last point of the time series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"intervalCount\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>count of intervals, count+1 points in time will generated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"irregular\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>every single point in time is given</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>explicit list of points in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"monthly\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series based on months</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"monthStart\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"yearStart\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"monthEnd\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"yearEnd\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"useMonthMiddle\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time points are mid of months, otherwise the 1st of each month + a time point behind the last month</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"yearly\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series based on years</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"yearStart\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"yearEnd\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"useYearMiddle\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time points are mid of years, otherwise the 1st of each year + a time point behind the last year</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"everyMonth\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series based on months</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>last point in time will be less or equal timeEnd</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"everyYear\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series based on years</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>last point in time will be less or equal timeEnd</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"instrument\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read time series from an instrument file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>inclusive, i.e. exclude eochs before this epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>exclusive, i.e. only epochs before this time are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"instrumentArcIntervals\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>try to reproduce arc interval time series from an instrument file</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Must be regular. Time series is first epoch of each arc plus one time step extrapolated from last epoch of last arc.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"revolutions\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create time series from orbit file (revolutions)</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>exclude eochs before this epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only epochs before this time are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"exclude\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>exclude times from a given time series</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time series to be created</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeriesExclude\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>exclude this time points from time series (within margin)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"excludeMargin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>on both sides [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"conditional\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series based depending on conditions</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only times for which condition is met will be included</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTime\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with time of each loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>test for each time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"interpolate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>interpolate between created times</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time series to be created</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nodeInterpolation\" type=\"uint\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolates count points in each time interval given by the time series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"troposphereType\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>signal delay in the atmosphere</xs:documentation>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"viennaMapping\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Vienna Mapping Function</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileVmfCoefficients\" type=\"filename\" default=\"{groopsDataDir}/troposphere/\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ah, aw, zhd, zwd coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGpt\" type=\"filename\" default=\"{groopsDataDir}/troposphere/gpt3_grid1deg.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridded GPT data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"aHeight\" type=\"double\" minOccurs=\"0\" default=\"2.53e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter a (height correction)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"bHeight\" type=\"double\" minOccurs=\"0\" default=\"5.49e-3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter b (height correction)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"cHeight\" type=\"double\" minOccurs=\"0\" default=\"1.14e-3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter c (height correction)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"gpt\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GPT empirical troposphere model</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGpt\" type=\"filename\" default=\"{groopsDataDir}/troposphere/gpt3_grid1deg.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridded GPT data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"aHeight\" type=\"double\" minOccurs=\"0\" default=\"2.53e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter a (height correction)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"bHeight\" type=\"double\" minOccurs=\"0\" default=\"5.49e-3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter b (height correction)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"cHeight\" type=\"double\" minOccurs=\"0\" default=\"1.14e-3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter c (height correction)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"mendesAndPavlis\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>SLR troposphere model by Mendes and Pavlis, 2004</xs:documentation>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationMeteorology\" type=\"filename\" default=\"meteorology_{loopTime:%y}.{station}.dat\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:complexType name=\"programType\">\n\t\t<xs:annotation>\n\t\t\t<xs:appinfo>rename: CovarianceFunction2PSD = CovarianceFunction2PowerSpectralDensity</xs:appinfo>\n\t\t\t<xs:appinfo>rename: CovariancePsd2CovarianceFunction = PowerSpectralDensity2CovarianceFunction</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssAntennaDefinition2Representation = GnssAntennaDefinition2ParameterVector</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssAntennaDefinition2GriddedData = GnssAntennaDefinition2Skyplot</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssAntennaRepresentationConstraint = GnssAntennaNormalsConstraint</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssResiduals2AntennaDefinition = GnssResiduals2AccuracyDefinition</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssResiduals2GriddedData = GnssResiduals2Skyplot</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssRepresentation2AntennaDefinition = ParameterVector2GnssAntennaDefinition</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Gravityfield2DegreeAmplitudeTimeSeries = Gravityfield2DegreeAmplitudesPlotGrid</xs:appinfo>\n\t\t\t<xs:appinfo>rename: DisplacementTimeSeries = Gravityfield2DisplacementTimeSeries</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GravityfieldReplaceC20 = GravityfieldReplacePotentialCoefficients</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Grid2Matrix = GriddedData2Matrix</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Grid2File = GriddedDataCreate</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GridMatrix2GriddedData = Matrix2GriddedData</xs:appinfo>\n\t\t\t<xs:appinfo>rename: AsciiMatrix2GridRectangular = MatrixRectangular2GriddedData</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputeAllanVariance = Instrument2AllanVariance</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputeCorrelation = Instrument2CrossCorrelationFunction</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputeHistogram = Instrument2Histogram</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputePSD = Instrument2PowerSpectralDensity</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputePsd = Instrument2PowerSpectralDensity</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputeScaleogram = Instrument2Scaleogram</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputeSpectralCoherence = Instrument2SpectralCoherence</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentComputeSpectrogram = Instrument2Spectrogram</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentAccelerometerEstimatedParameter = InstrumentAccelerometerApplyEstimatedParameters</xs:appinfo>\n\t\t\t<xs:appinfo>rename: ArcConcatenate = InstrumentConcatenate</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentMatrix2Instrument = InstrumentSetType</xs:appinfo>\n\t\t\t<xs:appinfo>rename: ArcSynchronize = InstrumentSynchronize</xs:appinfo>\n\t\t\t<xs:appinfo>rename: SimulateLocalLevelFrame = LocalLevelFrame2StarCamera</xs:appinfo>\n\t\t\t<xs:appinfo>rename: KernelComputeCoefficients = Kernel2Coefficients</xs:appinfo>\n\t\t\t<xs:appinfo>rename: KernelDegreeVariances = RadialBasisSplines2KernelCoefficients</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentCreateTimeSeries = TimeSeriesCreate</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Variational2Orbit = Variational2OrbitAndStarCamera</xs:appinfo>\n\t\t\t<xs:appinfo>rename: KalmanStaticTemporalNormals = NormalsBuildShortTimeStaticLongTime</xs:appinfo>\n\t\t\t<xs:appinfo>rename: NormalsParameterSelection2IndexVector = ParameterSelection2IndexVector</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentOrbit2ArgumentOfLatitude = Orbit2ArgumentOfLatitude</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentOrbit2BetaPrimeAngle = Orbit2BetaPrimeAngle</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentOrbit2EclipseFactor = Orbit2EclipseFactor</xs:appinfo>\n\t\t\t<xs:appinfo>rename: ArcGroundtracks = Orbit2Groundtracks</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentOrbit2ThermosphericState = Orbit2ThermosphericState</xs:appinfo>\n\t\t\t<xs:appinfo>rename: InstrumentOrbit2VelocityAcceleration = OrbitAddVelocityAndAcceleration</xs:appinfo>\n\t\t\t<xs:appinfo>rename: NormalsSimulateNoise = NoiseNormalsSolution</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GroupProgramme = GroupPrograms</xs:appinfo>\n\t\t\t<xs:appinfo>rename: IfProgramme = IfPrograms</xs:appinfo>\n\t\t\t<xs:appinfo>rename: LoopProgramme = LoopPrograms</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Admittance2Iers = DoodsonAdmittance2SupplementaryFiles</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GraceCsrAod2DoodsonHarmonics = GraceAod2DoodsonHarmonics</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Eop2003file = IersC04IAU2000EarthOrientationParameter</xs:appinfo>\n\t\t\t<xs:appinfo>rename: IersRapidEop2Earthrotation = IersRapidIAU2000EarthOrientationParameter</xs:appinfo>\n\t\t\t<xs:appinfo>rename: IGS2EarthRotation = Igs2EarthOrientationParameter</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Igs2InstrumentClock = GnssClockRinex2InstrumentClock</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssStationLog2StationInfo = GnssStationLog2Platform</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Tsxtdx2Orbit = Tsxtdx2Starcamera</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Tsxtdx2Starcamera = TerraSarTandem2StarCamera</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Kinematic2Orbit = BerneseKinematic2Orbit</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GraceCsrAod2TimeSplines = GraceAod2TimeSplines</xs:appinfo>\n\t\t\t<xs:appinfo>rename: AsciiKinematic2OrbitCovariance = GroopsAscii2Orbit</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Orbit2Ascii = Orbit2GroopsAscii</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Orbit2Sp3 = Orbit2Sp3Format</xs:appinfo>\n\t\t\t<xs:appinfo>rename: ReadOceanBottomPressurePSMSL = PsmslOceanBottomPressure2TimeSeries</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Sp3file2Orbit = Sp3Format2Orbit</xs:appinfo>\n\t\t\t<xs:appinfo>rename: Igs2Orbit = Sp3Format2Orbit</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssCreateStationInfo = GnssStationInfoCreate</xs:appinfo>\n\t\t\t<xs:appinfo>rename: GnssSinex2StationPosition = Sinex2StationPosition</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:choice>\n\t\t\t<xs:element name=\"AutoregressiveModel2CovarianceMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute the covariance structure of a sequence of VAR(0) to VAR(p) models</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceMatrix\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix for each lag</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"autoregressiveModelSequence\" type=\"autoregressiveModelSequenceType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>AR model sequence</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"CovarianceFunction2DigitalFilter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Digital filter coefficients from covariance function.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileFilter\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovariance\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first column: time steps, following columns: covariance functions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"column\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Column with covariance function to be fitted</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"warmup\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of samples until diagonal of Cholesky factor is flat (default: half covariance length)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numeratorDegree\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Maximum degree of numerator polynomial (MA constituent)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"denominatorDegree\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Maximum degree of denominator polynomial (AR constitutent)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"decorrelationFilter\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute a decorrelation filter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"CovarianceFunction2PowerSpectralDensity\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Power Spectral Density (PSD) from covariance functions.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePSD\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first column: frequency [Hz], other columns PSD [unit^2/Hz]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first column: time steps, following columns: covariance functions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"CovarianceMatrix2AutoregressiveModel\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute a VAR(p) model from covariance matrices</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAutoregressiveModel\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>coefficients and white noise covariance of AR(p) model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceMatrix\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of covariance matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"CovarianceMatrix2Correlation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute the correlation matrix from a covariance matrix</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCorrelationMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>correlation matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PowerSpectralDensity2CovarianceFunction\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Covariance functions from Power Spectral Density (PSD).</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunction\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first column: time steps [seconds], following columns: covariance functions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfilePSD\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first column: frequency [Hz], following columns PSD [unit^2/Hz]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonAdmittanceInterpolation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>visualize the interpolation of the minor tides.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAdmittance\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolation of minor constituents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonAdmittanceTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>cos/sin multipliers of the major tides.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES (cos of major tides, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAdmittance\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>cos/sin multipliers of the major tides</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonArguments2TimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>doodson/fundamental arguments.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each epoch: 6 doodson args, 5 fundamental args [rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonHarmonics2GriddedAmplitudeAndPhase\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>amplitude and phase of a harmonic tidal constituent on a grid.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGrid\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ampl, phase [-pi,pi], cos, sin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonHarmonics\" type=\"filename\" default=\"{groopsDataDir}/tides/\"/>\n\t\t\t\t\t\t<xs:element name=\"doodson\" type=\"doodson\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tidal constituent</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"filter\" type=\"sphericalHarmonicsFilterType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the values on grid are multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonHarmonics2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write a lot of files with potential coefficients from harmonic tide model.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\" default=\"coeff_{doodson}_{name}_{cossin}.gfc\"/>\n\t\t\t\t\t\t<xs:element name=\"variableLoopName\" type=\"string\" minOccurs=\"0\" default=\"name\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with darwins&apos;s name of each constituent</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopDoodson\" type=\"string\" minOccurs=\"0\" default=\"doodson\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with doodson code of each constituent</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCosSin\" type=\"string\" minOccurs=\"0\" default=\"cossin\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with &apos;cos&apos; or &apos;sin&apos; of each constituent</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of each constituent (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of constituents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonHarmonics\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/tides/generatingTide_HW95.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to compute Xi phase correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"applyXi\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply Doodson-Warburg phase correction (see IERS conventions)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonHarmonicsCalculateAdmittance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>computes the admittance function from TGP</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAdmittance\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonHarmonics\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/tides/generatingTide_HW95.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>TGP</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"threshold\" type=\"double\" minOccurs=\"0\" default=\"1e-4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m^2/s^2] only interpolate tides with TGP greater than threshold</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"degreeInterpolation\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree for interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"degreeExtrapolation\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree for extrapolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"excludeDoodsonForInterpolation\" type=\"doodson\" minOccurs=\"0\" default=\"[&quot;164.554&quot;, &quot;164.555&quot;, &quot;164.556&quot;, &quot;164.566&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>major tides not used for interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonHarmonicsChangePartialTides\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>change partial tides in doodsonHarmonics file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonHarmonics\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonHarmonics\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAdmittance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolation of minor constituents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useDoodson\" type=\"doodson\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use only these partial tides (additional tides will be interpolated)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreDoodson\" type=\"doodson\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore these partial tides</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ModelEquilibriumTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>equilibrium tide, taking the effect of loading and self attraction into account.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>includes the loading</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\" default=\"120\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDensityGrid\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[kg/m^3] density of sea water, zero over land</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tideGeneratingPotential\" type=\"double\" default=\"-0.0856534056\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m^2/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"k20\" type=\"double\" minOccurs=\"0\" default=\"0.30190\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>earth tide love number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"k20plus\" type=\"double\" minOccurs=\"0\" default=\"-0.00089\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>earth tide love number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"h20_0\" type=\"double\" minOccurs=\"0\" default=\"0.6078\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>earth tide love number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"h20_2\" type=\"double\" minOccurs=\"0\" default=\"-0.0006\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>earth tide love number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileDeformationLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/deformationLoveNumbers_CE_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"5\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PotentialCoefficients2DoodsonHarmonics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>doodsonHarmonic file from cos/sin potentialCoefficients.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonHarmonics\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/tides/generatingTide_HW95.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to compute Xi phase correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"constituent\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"doodson\" type=\"doodson\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCosPotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSinPotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"applyXi\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply Doodson-Warburg phase correction (see IERS conventions)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAntennaDefinition2ParameterVector\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate parameters of an antenna parametrization to fit an antenna definition</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"antennaCenterVariations\" type=\"parametrizationGnssAntennaType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"types\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if not set, all types in the file are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"zeroNaN\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>treat NaN values as zero, otherwise values are ignored</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAntennaDefinition2Skyplot\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create gridded data from Antenna definition.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data column for each gnssType</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\" default=\"*\"/>\n\t\t\t\t\t\t<xs:element name=\"types\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if not set, all types in the file are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAntennaDefinitionCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create GNSS antenna definition file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaDefinition\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"antenna\" type=\"gnssAntennaDefintionListType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAntennaNormalsConstraint\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Apply constraints to normals of antenna parametrization</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>with applied constraints</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"constraint\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"center\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero center (x,y,z) of a single pattern</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>applied for each matching types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"applyWeight\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>from normal equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"centerMean\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero center (x,y,z) as (weighted) mean of all patterns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"applyWeight\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>from normal equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constant\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero constant (mean of all directions) of a single pattern</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>applied for each matching types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"applyWeight\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>from normal equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constantMean\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero constant (mean of all directions) as (weighted) mean of all patterns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"applyWeight\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>from normal equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"TEC\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>zero TEC computed as (weighetd) least squares from all types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>applied for combination of matching types</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"applyWeight\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>from normal equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1e-4\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[TECU]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaCenterVariations\" type=\"parametrizationGnssAntennaType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"antennaName\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply constraints to all machting antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaSerial\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply constraints to all machting antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaRadome\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply constraints to all machting antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaAzimuth\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] sampling of pattern to estimate center/constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaZenith\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] sampling of pattern to estimate center/constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxZenith\" type=\"angle\" minOccurs=\"0\" default=\"90\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree] sampling of pattern to estimate center/constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAttitudeInfoCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Creates attitude info file used by SimulateStarCameraGnss.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAttitudeInfo\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"attitudeInfo\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"defaultMode\" default=\"nominalYawSteering\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>default attitude mode</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"nominalYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"orbitNormal\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"midnightMode\" default=\"nominalYawSteering\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>attitude mode for maneuvers around orbit midnight</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"nominalYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"orbitNormal\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"catchUpYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"shadowMaxYawSteeringAndRecovery\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"shadowMaxYawSteeringAndStop\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached, then stop (e.g. GLO-M (midnight))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"shadowConstantYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"centeredMaxYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"smoothedYawSteering1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"smoothedYawSteering2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"betaDependentOrbitNormal\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"noonMode\" default=\"nominalYawSteering\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>attitude mode for maneuvers around orbit noon</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"nominalYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"orbitNormal\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"catchUpYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"centeredMaxYawSteering\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"smoothedYawSteering1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"smoothedYawSteering2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"betaDependentOrbitNormal\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"maxYawRate\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree/s] maximum yaw rate of the satellite</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"yawBias\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] yaw bias applied in satellite attitude control system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"midnightBetaThreshold\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] limit midnight maneuver to this absolute angle of the Sun above/below the satellite orbital plane</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"noonBetaThreshold\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] limit noon maneuver to this absolute angle of the Sun above/below the satellite orbital plane</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"activationThreshold\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] limit maneuver to this yaw/Earth-spacecraft-Sun angle (depending on mode)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"maxManeuverTime\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[s] maximum duration of maneuver or maximum maneuver lookup time before/after orbit start/end</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssBiasClockAlignment\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Align GNSS transmitter clocks to reference clocks and adjust related receiver signal biases as well as GLONASS transmitter biases.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"transmitter\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one element per satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileClock\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>aligned clock instrument file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSignalBias\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>(GLONASS only) aligned signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileClock\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>clock instrument file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileReferenceClock\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>reference clock instrument file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>(GLONASS only) signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>transmitter platform file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"receiver\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one element per station</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>aligned signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"alignClocksByFreqNo\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>align clocks for each GLONASS frequency number separately</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"alignFreqNoBiasesAtReceiver\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>align frequency number-dependent code biases for each receiver</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssEstimateClockShift\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate clock shift for a constellation of satellites.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileShiftTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, clock shift</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"data\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>corrected clocks</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentDiff\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>clock difference after correction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input clocks</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentRef\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>reference clocks (subtracted from input clocks)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>clock epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[s] margin for time comparison</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssGlonassFrequencyNumberUpdate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Update/set GLONASS frequency number in transmitter info files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterInfo\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>templated for PRN list (variableNamePrn)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterInfo\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>templated for PRN list (variableNamePrn)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfilePrn2FrequencyNumber\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/glonassPrnSvn2FrequencyNumber.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"prn\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PRN (e.g. R01) for transmitter info files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNamePrn\" type=\"string\" minOccurs=\"0\" default=\"prn\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for PRN in transmitter info files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssProcessing\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GNSS/LEO satellite orbit determination, station network analysis, PPP</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>defines observation epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeMargin\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] margin to consider two times identical</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"transmitter\" type=\"gnssTransmitterGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constellation of GNSS satellites</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"receiver\" type=\"gnssReceiverGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ground station network or LEO satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori earth rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"gnssParametrizationType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>models and parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"processingStep\" type=\"gnssProcessingStepType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>steps are processed consecutively</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssReceiverDefinitionCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create GNSS receiver definition file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGnssReceiverDefinition\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"receiverDefinition\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"version\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssResiduals2AccuracyDefinition\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute accuracy definition from observation residuals</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileAntennaDefinition = outputfileAntennaMean</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccuracyDefinition\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>elevation and azimuth dependent accuracy</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaMean\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>weighted mean of the residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaRedundancy\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>redundancy of adjustment</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccuracyDefinition\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori accuracies</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to assign residuals to antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"isTransmitter\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>stationInfo is of a transmitter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"thresholdOutlier\" type=\"double\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore residuals with sigma/sigma0 greater than threshold</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minRedundancy\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min number of residuals. to estimate sigma</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileResiduals\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNSS receiver residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssResiduals2Skyplot\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert residuals into griddedData format for plotting</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"typeTransmitter\" type=\"gnssType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>choose transmitter view, e.g. &apos;***G18&apos;</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileResiduals\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNSS receiver residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssResiduals2TransmitterAccuracyDefinition\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute accuracy definition from observation residuals</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccuracyDefinition\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>elevation and azimuth dependent accuracy</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaMean\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>weighted mean of the residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaRedundancy\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>redundancy of adjustment</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccuracyDefinition\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori accuracies</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterInfo\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to assign residuals to antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minRedundancy\" type=\"double\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min number of residuals. to estimate sigma</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileResiduals\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNSS receiver residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssSignalBias2Matrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Computes signal biases for a given type list</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileTypes\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ASCII list of types</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"types\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if not set, all types in the file are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssSimulateReceiver\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GNSS receiver simulation</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGnssReceiver\" type=\"filename\" default=\"gnssReceiver_{loopTime:%D}.{station}.dat.gz\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, simulated observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileClock\" type=\"filename\" minOccurs=\"0\" default=\"clock_{loopTime:%D}.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available, simulated receiver clock errors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>defines observation epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeMargin\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] margin to consider two times identical</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"transmitter\" type=\"gnssTransmitterGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constellation of GNSS satellites</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"receiver\" type=\"gnssReceiverGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ground station network or LEO satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori earth rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"gnssParametrizationType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[&quot;troposphere&quot;]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>models and parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observationType\" type=\"gnssType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>simulated observation types</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseObservation\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[-] noise is multiplied with type accuracy pattern of receiver</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseClockReceiver\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] noise added to the simulated receiver clock</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentGnssReceiver2TimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert gnssReceiver file into instrument(MISCVLAUES) file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Residuals</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Instrument (MISCVALUES): prn, system, values for each type</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGnssReceiver\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNSS receiver observations or residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ParameterVector2GnssAntennaDefinition\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Update antenna definition from parametrization</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outfileAntennaDefinition\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all apriori antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaCenterVariations\" type=\"parametrizationGnssAntennaType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSolution\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileParameterNames\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"EnsembleAveragingScaleModel\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Ensamble Averaging of eclipse transit signals</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileScaleModel\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGrace1EclipseFactor\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GRACE-A eclipse factors computed with integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGrace2EclipseFactor\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GRACE-B eclipse factors computed with integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGraceResiduals\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SST Residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeMargin\" type=\"uint\" default=\"25\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>epochs before eclipse mode</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"waveLength\" type=\"uint\" default=\"60\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>length of the sample wave</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"averagingInterval\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"nearestNeighborNumber\" type=\"uint\" minOccurs=\"0\" default=\"24\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceAntennaCenterCorrectionArcCovariance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute antenna center correction from orbit configuration</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTrackingCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>corrections for range, range-rate, and range-accelerations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeAcceleration\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileScaCovariance1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileScaCovariance2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"sigmaAccelerometerX\" type=\"double\" minOccurs=\"0\" default=\"10e-7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaAccelerometerY\" type=\"double\" minOccurs=\"0\" default=\"2e-7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaAccelerometerZ\" type=\"double\" minOccurs=\"0\" default=\"2e-7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaCenters\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>KBR antenna phase center</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1X\" type=\"double\" minOccurs=\"0\" default=\"1.4451172588\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>x-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1Y\" type=\"double\" minOccurs=\"0\" default=\"-0.0004233040\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>y-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1Z\" type=\"double\" minOccurs=\"0\" default=\"0.0022786600\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>z-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2X\" type=\"double\" minOccurs=\"0\" default=\"1.4443870350\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>x-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2Y\" type=\"double\" minOccurs=\"0\" default=\"0.0005761203\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>y-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2Z\" type=\"double\" minOccurs=\"0\" default=\"0.0033040887\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>z-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"file\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputAntennaCenters\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>differentiation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceOrbit2TransplantTimeOffset\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute the time shift between two co-orbiting satellites from their orbit data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeOffset\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated time offset in seconds (MISCVALUE)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit data of satellite 1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit data of satellite 2</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree for the interpolation of position, velocity and acceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"initialGuess\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>initial guess for the time shift [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maximumIterations\" type=\"uint\" minOccurs=\"0\" default=\"50\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum number of iterations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"threshold\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>when the maximum difference between two iterations is below this value, stop [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceSstResidualAnalysis\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Multiresolution analysis of GRACE SST residuals.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentHighScale\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>High scale details</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentMidScale\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Intermediate scale details</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentLowScale\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Low scale details</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GRACE SST Residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileWavelet\" type=\"filename\" default=\"{groopsDataDir}/wavelets/db20.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wavelet coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceSstScaleModel\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Ensamble Averaging of eclipse transit signals</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileGraceResiduals\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SST Residuals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeMargin\" type=\"uint\" default=\"25\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>epochs before instrumental events</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"waveLength\" type=\"uint\" default=\"60\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>length of the sample wave</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateEclipseTransitScale\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileScaleModel\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileGrace1EclipseFactor\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>GRACE-A eclipse factors computed with integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileGrace2EclipseFactor\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>GRACE-B eclipse factors computed with integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"averagingInterval\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"nearestNeighborNumber\" type=\"uint\" minOccurs=\"0\" default=\"24\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateLowSnrScale\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileScaleModel\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileGraceSstSNR\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>GRACE SNR values</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceSstSpecialEvents\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Detect GRACE events (eclipse, sun intrusion into star camera box).</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEvents\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileIntervals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\"/>\n\t\t\t\t\t\t<xs:element name=\"marginLeft\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin size (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"marginRight\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin size (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceThrusterResponse2Accelerometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Add modeled thruster responses to accelerometer</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileThruster\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>THRUSTER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileThrusterResponse\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>thruster model (matrix with one line per pair)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentSatelliteTrackingAntennaCenterCorrection\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute antenna center correction from orbit configuration</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTracking\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>corrections for range, range-rate, and range-accelerations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"antennaCenters\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>KBR antenna phase center</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1X\" type=\"double\" minOccurs=\"0\" default=\"1.4451172588\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>x-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1Y\" type=\"double\" minOccurs=\"0\" default=\"-0.0004233040\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>y-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1Z\" type=\"double\" minOccurs=\"0\" default=\"0.0022786600\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>z-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2X\" type=\"double\" minOccurs=\"0\" default=\"1.4443870350\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>x-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2Y\" type=\"double\" minOccurs=\"0\" default=\"0.0005761203\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>y-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2Z\" type=\"double\" minOccurs=\"0\" default=\"0.0033040887\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>z-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"file\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputAntennaCenters\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>differentiation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentStarCameraAngularAccelerometerFusion\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>estimation of the satellites orientation from star camera and angular accelerometer data.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>combined quaternions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>epoch-wise covariance matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceMatrix\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>full arc-wise covariance matrix per arc. arc number is appended to filename</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileEpochSigmaStarCamera\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>from vce and outlier detection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileEpochSigmaAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>from vce and outlier detection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularAcc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>angular acceleration observations (bias removed)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameter (one column for each arc)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCameraReference\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>quaternions as taylor point</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>star camera observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCameraCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>star camera observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAngularAcc\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>angular acceleration observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"correctAccNonQuadratic\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apply correction (non-square proof mass)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"accBias\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>accelerometer bias per interval and axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"accScale\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>accelerometer scale per interval and axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaStarcamera\" type=\"double\" minOccurs=\"0\" default=\"1.\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaAccelerometerX\" type=\"double\" minOccurs=\"0\" default=\"10e-7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaAccelerometerY\" type=\"double\" minOccurs=\"0\" default=\"2e-7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaAccelerometerZ\" type=\"double\" minOccurs=\"0\" default=\"2e-7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateSigmaScaPerAxis\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>separate variance factor for roll, pitch, yaw, instead of one common factor.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateSigmaAccPerAxis\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>separate variance factor for each accelerometer axis, instead of one common factor.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber*sigma0 are downweighted</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>residuals &gt; huber: sigma=(e/huber)^power*sigma0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"15\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>non linear equation solved iteratively</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2AbsoluteGravity\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Absolute gravity values on a grid.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2AreaMeanTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>generates a time series as mean values over an area from a time variable gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"convertToHarmonics\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"multiplyWithArea\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>multiply time series with total area (useful for mass estimates)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove the temporal mean of the series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeRms\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional rms each time step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeSigma\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional error bars at each time step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2Deflections\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Deflections of the vertical - based on gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>xi (north), eta (east) [rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2DegreeAmplitudes\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>computes degree amplitudes of a gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>three column matrix with degree, signal amplitude, formal error</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>type of variances</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rms\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>degree amplitudes (square root of degree variances)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"accumulation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>cumulate variances over degrees</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"median\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>median of absolute values per degree</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"evaluationRadius\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>evaluate the gravity field at this radius (default: evaluate at surface</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"polarGap\" type=\"angle\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>exclude polar regions (aperture angle in degrees)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2DegreeAmplitudesPlotGrid\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Time series of degree amplitudes from a time variable gravityfield.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each row: mjd, degree, amplitude, formal error</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"evaluationRadius\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>evaluate the gravity field at this radius (default: evaluate at surface</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"polarGap\" type=\"angle\" minOccurs=\"0\" default=\"0.\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>exclude polar regions (aperture angle in degrees)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimal degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximal degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2DisplacementTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>generates a time series of station displacements</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>x,y,z [m] per station</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>station list</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"tides\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileDeformationLoadLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialLoadLoveNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if full potential is given and not only loading potential</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove the temporal mean of each coordinate</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"localReferenceFrame\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>local left handed reference frame (north, east, up)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2EmpiricalCovariance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate a empircal covariance function from time series</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme for solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sampling of the gravityfield</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"differenceStep\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>choose dt for: x,i(t) - x,j(t+dt)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factorFullMatrixPart\" type=\"double\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"factorIsotropicPart\" type=\"double\" minOccurs=\"0\" default=\"0.1\"/>\n\t\t\t\t\t\t<xs:element name=\"intervals\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2Gradients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Gradients from gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Vxx Vyy Vzz Vxy Vxz Vyz</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"localReferenceFrame\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>local left handed reference frame (north, east, up)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2GravityVector\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Gravity vector from gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gx, gy, gz</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"localReferenceFrame\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>local left handed reference frame (north, east, up)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2GridCovarianceMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Covariance matrix of values of a gravity field on a grid.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>symmetric grid covariance matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>values of a gravity field on a grid.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"convertToHarmonics\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2GriddedDataTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series of gridded gravity fields.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each epoch: data of grid points (MISCVALUES)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"convertToHarmonics\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>writes a gravity field to a file with potential coefficients</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2PotentialCoefficientsTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>time series of potential coefficients</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (MISCVALUES)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2SphericalHarmonicsVector\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>converts a gravity field to a solution vector with potential coeffcients</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVector\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"startIndex\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start index to put the coefficients in the solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme for solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useSigma\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use formal errors instead of coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2TimeSplines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate splines in time domain from a time variable gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSplines</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSplines\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"temporalFilter\" type=\"digitalFilterType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter sampled gravity field in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field is sampled at these times</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove the temporal mean of the series before estimating the splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"linearInterpolation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>assume linear behavior between sampled points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"splineDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"splineTimeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nodal points of splines in time domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Gravityfield2TrendPotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>estimate temporal parametrization (e.g. trend, annual)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each temporal parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberMaxIteration\" type=\"uint\" minOccurs=\"0\" default=\"15\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for robust estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GravityfieldCovariancesPropagation2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>covariances of values of a gravity field on a grid</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridded data file containing the covariance betwenn source point and grid points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>functional</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"L\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude of variance point</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"B\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of variance point</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ellipsoidal height of source point</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeCorrelation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute correlations instead of covariances</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GravityfieldReplacePotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Replace single potential coefficients in a gravity field</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>single coefficients are replaced by the other gravityfield</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfieldReplacement\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>contains the coefficients for replacement</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"coefficients\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"cnm\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"degree\" type=\"uint\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"snm\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"degree\" type=\"uint\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"order\" type=\"uint\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GravityfieldVariancesPropagation2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>standard deviations of values of a gravity field on a grid</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviation at each grid point</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>functional</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2AreaMeanTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>generates a time series as mean values over an area from a list of grid files</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"multiplyWithArea\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>multiply time series with total area (useful for mass estimates)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove the temporal mean of the series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeRms\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional rms each time step</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2GriddedDataStatistics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Assign gridded data to grid points</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"statistic\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>statistic used if multiple values fall on the same cell</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"mean\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>mean</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"wmean\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>area weighted mean</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rms\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>root mean square</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"wrms\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>area weighted root mean square</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"std\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>standard deviation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"wstd\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>area weighted standard deviation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sum\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>sum</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"min\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>minimum value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"max\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>maximum value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"count\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>number of values</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"first\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>first value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"last\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>last value</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"emptyValue\" type=\"double\" minOccurs=\"0\" default=\"nan()\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>value for nodes without data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2GriddedDataTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write time series of gridded data as gridded data time series file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedDataTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file count must agree with number of times+splineDegre-1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"splineDegree\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2Matrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write grid to matrix file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>point list as matrix with longitude and latitude values in columns and possible additional columns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outColumn\" type=\"expression\" minOccurs=\"0\" default=\"[&quot;longitude&quot;, &quot;latitude&quot;, &quot;height&quot;, &quot;data0&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables: longitude, latitude, height, area, data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate potential coefficients from gridded gravity field functionals</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file for each value expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" default=\"data0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"weight\" type=\"expression\" default=\"area\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data type of input values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"leastSquares\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>false: quadrature formular, true: least squares adjustment order by order</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2SphericalDistance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>spherical distance between all point pairs of two grids.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix containing the spherical distance between all point pairs [rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid1\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"grid2\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2TimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write time series of gridded data as time series file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each epoch: multiple data for points (MISCVALUES)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file count must agree with number of times</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"groupDataByPoints\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>multiple data are given point by point, otherwise: data0 for all points, followed by all data1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataCalculate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Calculate values of gridded data.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"constant\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a constant by name=value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameter\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a parameter by name[=value]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"leastSquares\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>try to minimize the expression by adjustment of the parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removalCriteria\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>points are removed if one criterion evaluates true. data0 is the first data field.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"longitude\" type=\"expression\" default=\"longitude\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"latitude\" type=\"expression\" default=\"latitude\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"expression\" default=\"height\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"area\" type=\"expression\" minOccurs=\"0\" default=\"area\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression: e.g. deltaL * 2.0 * sin(deltaB/2.0) * cos(latitude/rho)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" minOccurs=\"0\" default=\"[&quot;data0&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeArea\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>automatically area computation of rectangular grids (overwrite area)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"statistics\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>matrix with one row, columns are user defined</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outColumn\" type=\"expression\" default=\"data0rms\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression to compute statistics columns, data* are the outputColumns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataConcatenate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Concatenate gridded data from several files</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"sortPoints\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sort from north/west to south east</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeDuplicates\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove duplicate points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"keepFirst\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep first point, remove all other identicals</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>margin distance for identical points [m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"keepLast\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep last point, remove all other identicals</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>margin distance for identical points [m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create a grid an write it to file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGrid\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" minOccurs=\"0\" default=\"0.0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables as &apos;longitude&apos;, &apos;height&apos;, &apos;area&apos; are taken from the gridded data)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataInterpolate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Interpolate values of rectangular grids to new points</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>must be rectangular</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"method\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"nearestNeighbor\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataReduceSampling\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Generate coarse grid by computing mean values</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCoarseGridRectangular\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>coarse grid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileFineGridRectangular\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>fine grid with additional coarse grid values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileFineGridRectangular\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Digital Terrain Model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"multiplierLongitude\" type=\"uint\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Generalizing factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"multiplierLatitude\" type=\"uint\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Generalizing factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"volumeConserving\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data are interpreted as heights above ellipsoid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataTimeSeries2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write a griddedDataTimeSeries as griddedData for each epoch</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilesGriddedData\" type=\"filename\" default=\"grid_{loopTime:%y-%m}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTime\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with time of each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current epoch (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedDataTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>otherwise times from inputfile are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataTimeSeries2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert a griddedDataTimeSeries to a sequence of PotentialCoefficients files</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilesPotentialCoefficients\" type=\"filename\" default=\"coeff_{loopTime:%D}.gfc\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTime\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with time of each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current epoch (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedDataTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>otherwise times from inputfile are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" default=\"data0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables: longitude, latitude, height, area, data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"weight\" type=\"expression\" default=\"area\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute values (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>kernel in which the grid values are given</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for potential coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"leastSquares\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>false: quadrature formular, true: least squares adjustment order by order</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedTopography2AtmospherePotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate interoir and exterior atmospheric potential coefficients above digital terrain models</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficientsExterior\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficientsInterior\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Digital Terrain Model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"densitySeaLevel\" type=\"double\" minOccurs=\"0\" default=\"1.225\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[kg/m**3]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ny\" type=\"double\" minOccurs=\"0\" default=\"680\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Constant for Atmosphere</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radialLowerBound\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables &apos;L&apos;, &apos;B&apos;, &apos;height&apos;, &apos;data&apos;, and &apos;area&apos; are taken from the gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"upperAtmosphericBoundary\" type=\"double\" minOccurs=\"0\" default=\"11000\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constant upper bound [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor, set -1 to subtract the field</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedTopography2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate potential coefficients from digital terrain models</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficientsInterior\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Digital Terrain Model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"density\" type=\"expression\" minOccurs=\"0\" default=\"2670\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression [kg/m^3]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radialUpperBound\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables &apos;L&apos;, &apos;B&apos;, &apos;height&apos;, &apos;data&apos;, and &apos;area&apos; are taken from the gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"radialLowerBound\" type=\"expression\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (variables &apos;L&apos;, &apos;B&apos;, &apos;height&apos;, &apos;data&apos;, and &apos;area&apos; are taken from the gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedTopographyEllipsoidal2Radial\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Interpolate digital terrain models from ellipoidal heights to radial heights</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Digital Terrain Model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Matrix2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read gridded data from matrix</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"points\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ellipsoidal\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"longitude\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"latitude\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"height\" type=\"expression\" default=\"data2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"cartesian\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"x\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"y\" type=\"expression\" default=\"data1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"z\" type=\"expression\" default=\"data2\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"area\" type=\"expression\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (e.g. deltaL*2*sin(deltaB/2)*cos(data1/RHO))</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" minOccurs=\"0\" default=\"[&quot;data3&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sortPoints\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sort from north/west to south east</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeArea\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the area can be computed automatically for rectangular grids</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"MatrixRectangular2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read gridded data (matrix)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"rowMajor\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>true: data is ordered row by row, false: columnwise</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startLongitude\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>longitude of upper left corner of the grid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startLatitude\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>latitude of upper left corner of the grid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaLongitude\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sampling, negative for east to west data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaLatitude\" type=\"angle\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sampling, negative for south to north data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"TimeSeries2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write time series as gridded data for each epoch</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilesGriddedData\" type=\"filename\" default=\"grid_{loopTime:%y-%m}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTime\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with time of each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current epoch (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each epoch: multiple data for points (MISCVALUES)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>corresponding grid points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"isDataGroupedByPoint\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>multiple data are given point by point, otherwise: first data0 for all points, followed by all data1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2AllanVariance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute Allan variance from instrument files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAllanVariance\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>column 0: averaging interval [seconds], column 1-(n-1): Allan variance for each data column</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2CovarianceFunctionVCE\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Covariance functions via variance component estimation</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunction\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance functions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileResiduals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameter vector (global part only)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameter\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data is reduced by temporal representation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameterPerArc\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data is reduced by temporal representation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of iterations for the estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2CrossCorrelationFunction\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Empirical computation of the correlation between two instrument files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCorrelation\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>column 1: time lag, column 2..n cross-correlation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentReference\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2Histogram\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute a histogram from an instrument file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>column 1: lower bin bound; columns 2 to N: histogram of each arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"selectDataField\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>select channel for histogram computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"binCount\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(default: Freedman-Diaconis&apos; choice, maximum of all channels)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"lowerBound\" type=\"expression\" minOccurs=\"0\" default=\"dataMin\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>lower bound for bins (default: global minimum, data values outside are ignored)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"upperBound\" type=\"expression\" minOccurs=\"0\" default=\"dataMax\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>upper bound for bins (default: global maximum, data values outside are ignored)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"relative\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output relative frequencies</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"cumulative\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>accumulate frequencies</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2PowerSpectralDensity\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute PSD from instrument files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePSD\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated PSD: column 0: frequency vector, column 1-(n-1): PSD estimate for each channel</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2RmsPlotGrid\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute RMS plot grid from instrument file(s) containing 3D data (e.g. orbits, station positions).</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: intervals = timeIntervals</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileRmsPlotGrid\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, id, rms</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileHelmertTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, tx, ty, tz, scale, rx, ry, rz</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file per satellite/station</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentReference\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file per satellite/station, same order as above</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeIntervals\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for {loopTime} variable in inputfile</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. sqrt(3) for 3D RMS</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateShift\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>coordinate center every epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateScale\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>scale factor of position every epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateRotation\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation every epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberMaxIteration\" type=\"uint\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for robust estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2Scaleogram\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute scalogram and detail levels of an instrument file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileScaleogram\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix columns: mjd, level, value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileLevels\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use loopLevel as variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileWavelet\" type=\"filename\" default=\"{groopsDataDir}/wavelets/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wavelet coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"selectDataField\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data column to transform</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxLevel\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum level of decomposition (default: full)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2SpectralCoherence\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Empirical computation of the spectral coherence between two instrument files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCoherence\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>column 1: frequency, column 2-n coherence</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentReference\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Instrument2Spectrogram\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>spectrogram using Short Time Fourier Transform</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSpectrogram\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>mjd, freq, ampl0, ampl1, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>center of SFFT window</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"windowLength\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentAccelerometer2ThermosphericDensity\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate neutral density from accelerometer data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDensity\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE (kg/m^3)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add non-gravitational forces in satellite reference frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"thermosphere\" type=\"thermosphereType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to compute temperature and wind</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerTemperature\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute drag and lift, otherwise simple drag coefficient is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"considerWind\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentAccelerometerApplyEstimatedParameters\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>apply estimated acceleration parameters to an accelerometer file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>add non-gravitational forces in satellite reference frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileParameter\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"indexStart\" type=\"int\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position in the solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightSide\" type=\"int\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if solution contains several right hand sides, select one</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the result is multiplied by this factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentAccelerometerEstimateBiasScale\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>estimate accelerometer bias and scale.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometerSim\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileThruster\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove thruster events</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"marginThruster\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin size (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentAccelerometerEstimateParameters\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>estimate accelerometer parameters.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>values for estimated parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>names of the estimated parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateArcSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileArcSigmas\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateEpochSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileEpochSigmas\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>estimated epoch-wise sigmas</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateCovarianceFunctions\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance functions for x, y, z direction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometerReference\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if not given, reference acceleration is assumed zero</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model (may be needed by parametrizationAcceleration)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"sigmaX\" type=\"double\" minOccurs=\"0\" default=\"1e-9\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori accuracy in x-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaY\" type=\"double\" minOccurs=\"0\" default=\"10e-9\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori accuracy in y-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sigmaZ\" type=\"double\" minOccurs=\"0\" default=\"1e-9\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori accuracy in z-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>iteration count for determining the covariance function</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentApplyTimeOffset\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Apply a time offset to an instrument file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTimeOffset\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE with time offset in seconds</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>applied to time offset</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentArcCalculate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Instrument data calculation arc wise.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data columns are appended to the right</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"constant\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a constant by name=value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameter\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a parameter by name[=value]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"leastSquares\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>try to minimize the expression by adjustment of the parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removalCriteria\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>row is removed if one criterion evaluates true.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outType\" type=\"instrumentTypeType\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outColumn\" type=\"expression\" minOccurs=\"0\" default=\"[&quot;data0&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression of output columns, extra &apos;epoch&apos; variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"statistics\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>instrument file with mid epoch per arc, data columns are user defined</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outColumn\" type=\"expression\" default=\"data0rms\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression to compute statistics columns, data* are from outColumn</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentArcCrossStatistics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute RMS of an instrument time series or differences</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStatisticsTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>statistics column(s) per arc, MISCVALUES</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentReference\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"statistics\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"correlation\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"errorRMS\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>rms of differences</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"nashSutcliffe\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>with respect to reference field</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeArcMean\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"perColumn\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute statistic per column</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentArcStatistics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute statistics for arcs of instrument data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStatisticsTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, statistics column(s) per instrument file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"statistics\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rootMeanSquare\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"standardDeviation\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"mean\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"median\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"min\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"max\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"epochCount\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"perColumn\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute statistic per column</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreNan\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore NaN values in input</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentConcatenate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>concatenate arcs from several files</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"sort\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sort epochs with increasing time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeDuplicates\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove duplicate epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"keepFirst\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep first epoch with the same time stamp, remove all others</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>margin for identical times [seconds]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"keepLast\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>keep last epoch with the same time stamp, remove all others</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>margin for identical times [seconds]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"checkForNaNs\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove epochs with NaN values in one of the data fields</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentCovarianceCheck\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Remove non invertible covariance matrices</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance3d\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovariance3d\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentDetrend\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Reduces temporal parametrization (e.g. trend, polynomial) per arc from instrument file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: temporalRepresentation = parametrizationTemporal</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>detrended instrument time series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeriesArcParameters\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time series of estimated parameters per arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>per arc, data is reduced by temporal representation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberMaxIteration\" type=\"uint\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for robust estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentEarthRotation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Precompute Earth rotation matrix (CRF -&gt; TRF) and save as StarCamera file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from CRF to TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentEstimateEmpiricalCovariance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate the empirical covariance matrix of an instrument file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceMatrix\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentEstimateHelmertTransformation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute RMS time series from instrument file(s).</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: temporalRepresentation = parametrizationTemporal</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: intervals = timeIntervals</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileHelmertTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, Tx,Ty,Tz,s,Rx,Ry,Rz according to temporal parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"data\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. satellite, station</xs:documentation>\n\t\t\t\t\t\t\t\t<xs:appinfo>rename: startData = startDataFields</xs:appinfo>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>transformed positions as instrument type Vector3d</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentDiff\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>position difference as instrument type Vector3d</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentReference\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>start index of position (x,y,z) columns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeIntervals\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameters are estimated per interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>temporal parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateShift\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>coordinate center</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateScale\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>scale factor of position</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateRotation\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huber\" type=\"double\" minOccurs=\"0\" default=\"2.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberPower\" type=\"double\" minOccurs=\"0\" default=\"1.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for robust least squares</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"huberMaxIteration\" type=\"uint\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for robust estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentFilter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>filter any instrument file arc wise</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"digitalFilter\" type=\"digitalFilterType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentInsertNAN\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Insert epochs with data NAN into instrument files</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"times\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Insert NAN at specific times.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"atGaps\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Insert NAN where epochs are more than 1.5 times the median sampling apart.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"atArcEnds\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Insert one epoch with data NAN at arc ends</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentMultiplyAdd\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Multiply instrument data with a factor and add them together</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"instrument\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeArcMean\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove mean value of each arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentReduceSampling\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>reduce sampling of instrument data.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>new sampling in seconds</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin around the new sampling in seconds</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"relative2FirstEpoch\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute sampling relative to time of first epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentRemoveEpochsByCriteria\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Remove epochs which criteria defined through expressions</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all data is stored in one arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentRemovedEpochs\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all data is stored in one arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>arcs are concatenated for processing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrumentReference\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if given, the reference data is reduced prior to the expressions being evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removalCriteria\" type=\"expression\" default=\"abs(data0-data0median) &gt; 3*1.4826*data0mad\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>epochs are removed if one criterion evaluates true. data0 is the first data field.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove data around identified epochs (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentRemoveEpochsByTimes\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Remove epochs from instrument data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all epochs are concatenated in one arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentRemovedEpochs\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all epochs are concatenated in one arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timePoints\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin size (on both sides) [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentRemoveEpochsThruster\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Remove epochs from instrument data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all epochs are concatenated in one arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrumentRemovedEpochs\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all epochs are concatenated in one arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileThruster\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>THRUSTER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"marginBefore\" type=\"double\" minOccurs=\"0\" default=\"0.1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin before start of firing [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"marginAfter\" type=\"double\" minOccurs=\"0\" default=\"0.7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin after end of firing [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentResample\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Resample data to given time series</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"method\" type=\"interpolatorTimeSeriesType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>resampling method</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>resampled points in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentRotate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Rotate instrument data into a new reference frame</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inverseRotate\" type=\"boolean\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentSetType\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Reinterpret data columns of instrument file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileTimeSeries = inputfileInstrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"type\" type=\"instrumentTypeType\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentStarCamera2AccAngularRate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>derivation of angular rates from rotations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularRate\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s], VECTOR3D</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularAcc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s**2], VECTOR3D</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>derivation by polynomial interpolation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentStarCamera2RollPitchYaw\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute roll, pitch, yaw angles</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>roll, pitch, yaw [rad], VECTOR3D</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCameraReference\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nominal orientation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentStarCamera2RotaryMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute rotary matrix</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>xx, xy, xz, yx, yy, yz, zx, zy, zz (MISCVALUES)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentStarCameraMultiply\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Mutiply instrument data with a factor and add them together</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"instrument\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inverse\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentStatisticsTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute time series of statistics for intervals of instrument data.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Statistics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStatisticsTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, statistics column(s) per instrument file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"statistics\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rootMeanSquare\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"standardDeviation\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"mean\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"median\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sum\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"min\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"max\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"epochCount\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"perColumn\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute statistic per column</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreNan\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore NaN values in statistic computation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"intervals\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>intervals for statistics computation (one statistic per interval)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. sqrt(3) for 3D RMS</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentSynchronize\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Synchronize instrument data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"data\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>margin for identical times [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minGap\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimal time to define a gap and to begin a new arc, 0: no dividing [seconds], if not set 1.5*median sampling is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minArcLength\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimal number of epochs of an arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxArcLength\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximal number of epochs of an arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"arcType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>all arcs or only ascending or descending arcs are selected</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ascending\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"descending\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only data in a specific region is selected</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeIntervals\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>divide data into time bins</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileArcList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>arc and time bin mapping</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"irregularData\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument files with irregular sampling</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"minArcLength\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>minimal number of epochs in an arc</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"InstrumentWaveletDecomposition\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Wavelet decomposition of an instrument file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES, decomposed levels in time domain a_J,d_J,...,d_1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"selectDataField\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>select a data column for decomposition</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileWavelet\" type=\"filename\" default=\"{groopsDataDir}/wavelets/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wavelet coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"level\" type=\"uint\" default=\"4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>level of decomposition</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"LocalLevelFrame2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Rotation from local level frame (ellipsoidal north, east, down) to TRF.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation matrix from local level frame (ellipsoidal north, east, down) to TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>origin of local level frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"constantOriginPerArc\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use constant origin for all epochs of an arc (median position)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"KalmanBuildNormals\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accumulate normals for sub monthly data sets.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: arcList = inputfileArcList</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: KalmanFilter</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\" default=\"normals/normals_{loopTime:%D}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>outputfile for normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observation\" type=\"observationType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list to correspond points of time to arc numbers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"eliminateNonGravityParameters\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>eliminate additional parameters from normals, 0: all parameter are saved</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"KalmanFilter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Computes time variable gravity fields using Kalman filter approach</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: KalmanFilter</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileUpdatedState\" type=\"filename\" default=\"kalman/updatedState/x_{loopTime:%D}.txt\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated state x+ (nx1-matrix)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileUpdatedStateCovarianceMatrix\" type=\"filename\" minOccurs=\"0\" default=\"kalman/updatedStateCovariance/covariance_{loopTime:%D}.dat\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated state&apos; s covariance matrix Cov(x+)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquations\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normal equations input file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInitialState\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>initial state x0</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInitialStateCovarianceMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>initial state&apos;s covariance matrix Cov(x0)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAutoregressiveModel\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of autoregressive model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"KalmanSmoother\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Computes time variable gravity fields using Kalman smoother approach</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: KalmanFilter</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileState\" type=\"filename\" default=\"kalman/smoothedState/x_{loopTime:%D}.txt\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameters (nx1-matrix)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileStateCovarianceMatrix\" type=\"filename\" minOccurs=\"0\" default=\"kalman/smoothedStateCovariance/covariance_{loopTime:%D}.dat\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameters&apos; covariance matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileUpdatedState\" type=\"filename\" default=\"kalman/updatedState/x_{loopTime:%D}.txt\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileUpdatedStateCovarianceMatrix\" type=\"filename\" default=\"kalman/updatedStateCovariance/covariance_{loopTime:%D}.dat\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAutoregressiveModel\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of autoregressive model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"KalmanSmootherLeastSquares\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Smoothed time variable gravity field by least squares adjustment</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: KalmanFilter</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" default=\"kalman/smoothedState/x_{loopTime:%D}.txt\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of solution vector (use time tags)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmax\" type=\"filename\" minOccurs=\"0\" default=\"kalman/smoothedStateSigma/sigmax_{loopTime:%D}.txt\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of sigma vector (use time tags)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance\" type=\"filename\" minOccurs=\"0\" default=\"kalman/smoothedStateCovariance/covariance_{loopTime:%D}.dat\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of full covariance matrix (use time tags)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquations\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input normal equations (loopTime will be expanded)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"autoregressiveModelSequence\" type=\"autoregressiveModelSequenceType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file containing AR model for spatiotemporal constraint</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DigitalFilter2FrequencyResponse\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>amplitude and phase response of a filter cascade</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileResponse\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: freq [Hz], ampl, phase [rad], group delay [-], real, imag</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"digitalFilter\" type=\"digitalFilterType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"length\" type=\"uint\" minOccurs=\"0\" default=\"512\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>length of the data series in time domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sampling to determine frequency [seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"skipZeroFrequency\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>omit zero frequency when writing to file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"unwrapPhase\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>unwrap phase response</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DigitalFilter2ImpulseResponse\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>impulse response of a filter cascade</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileResponse\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>columns: time [seconds], response</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"digitalFilter\" type=\"digitalFilterType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"length\" type=\"uint\" minOccurs=\"0\" default=\"201\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>length of the impulse response</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"pulseLag\" type=\"uint\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start of the pulse in the data series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"EarthOrientationParameterTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Time series of EOP</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEOP\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each row: mjd(GPS), xp, yp, sp, dUT1, LOD, X, Y, S</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"EarthRotaryVectorTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Time series of Earth&apos;s rotary axis</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wx, wy, wz [rad], dwx, dwy, dwz [rad/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inTRF\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>terrestrial reference frame, otherwise celestial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"EclipseFactor2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>eclipse factor on a grid.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>eclipse factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FilterMatrixWindowedPotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create a spherical harmonic window matrix.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileWindowMatrix\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridded data which defines the window function in space domain</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute the window function (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>kernel for windowing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme for solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FunctionsCalculate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Functions Calulate</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"constant\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a constant by name=value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameter\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>define a parameter by name[=value]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"leastSquares\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>try to minimize the expression by adjustment of the parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removalCriteria\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>row is removed if one criterion evaluates true.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outColumn\" type=\"expression\" minOccurs=\"0\" default=\"[&quot;data0&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression to compute output columns (input columns are named data0, data1, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"statistics\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>matrix with one row, columns are user defined</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outColumn\" type=\"expression\" default=\"data0rms\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression to compute statistics columns, data* are the outputColumns</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Grs2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>spherical harmonics from Geodetic Reference System (GRS)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" default=\"10\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986005e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"omega\" type=\"double\" minOccurs=\"0\" default=\"7292115e-11\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Angular velocity of rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"J2\" type=\"double\" minOccurs=\"0\" default=\"108263e-8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Dynamical form factor</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geometric inverse flattening of reference ellipsoid (0: sphere, ignored when J2 is set)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Kaula2SigmaPotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create variances according kaulas rule of thumb</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"power\" type=\"double\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma = factor/degree^power</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma = factor/degree^power</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Kernel2Coefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute kernel coefficients</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix with columns degree, coefficients and inverse coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum degree of returned coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegre\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute coefficients up to maxDegree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>evaluate kernel at R+height [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Kernel2SigmaPotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create variances of spherical harmonics by convolution a kernel with white noise</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"KernelEvaluate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute kernel values for distant angles</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix with first column the angle [degree], second the kernel value</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"minAngle\" type=\"angle\" minOccurs=\"0\" default=\"-180\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxAngle\" type=\"angle\" minOccurs=\"0\" default=\"180\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>evaluate at R+height [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"MagneticField2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>magentic field vector</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>x, y, z [Tesla = kg/A/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"magnetosphere\" type=\"magnetosphereType\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\" default=\"51544.5\"/>\n\t\t\t\t\t\t<xs:element name=\"localReferenceFrame\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>local left handed reference frame (north, east, up)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"MatrixCalculate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Matrix manipulation</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"matrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ObservationEquations2Files\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write the design matrix and observation vector</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileObservationVector\" type=\"filename\" minOccurs=\"0\" default=\"l_{arc:%03i}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file for each arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileDesignMatrix\" type=\"filename\" minOccurs=\"0\" default=\"A_{arc:%03i}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file for each arc, without arc related parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileDesignMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file for each arc, arc related parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableArc\" type=\"string\" minOccurs=\"0\" default=\"arc\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with arc number</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\" minOccurs=\"0\" default=\"parameterNames.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>without arc related parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observation\" type=\"observationType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlatformCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create a platform file equipped with instruments</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePlatform\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"markerName\" type=\"string\"/>\n\t\t\t\t\t\t<xs:element name=\"markerNumber\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"approxPositionX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] in TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"approxPositionY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] in TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"approxPositionZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] in TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"equipment\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssAntenna\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionX\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] ARP in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionY\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] ARP in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionZ\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] ARP in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationX\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to left-handed antenna system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationY\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to left-handed antenna system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationZ\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to left-handed antenna system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"flipX\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip x-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"flipY\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip y-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"flipZ\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip z-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"gnssReceiver\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"version\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"laserRetroReflector\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>e.g. GFZ, ITE, IPIE</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionX\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] optial reference point RP in satellite system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionY\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] optial reference point RP in satellite system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionZ\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] optial reference point RP in satellite system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationX\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to LRR system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationY\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to LRR system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationZ\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to LRR system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"flipX\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip x-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"flipY\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip y-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"flipZ\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip z-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"range\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] range bias (only without range matrix)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileRangeMatrix\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] (azimuth(0..360) x zenith(0..dZenit*rows)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dZenit\" type=\"angle\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] increment of range matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"geodeticSatellite\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>e.g. LAGEOS</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"range\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] standard center-of-mass correction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"slrStation\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>CDP SOD 8-digit No.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>IERS DOMES</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] eccentricity in north</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] eccentricity in east</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] eccentricity in up</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"satelliteIdentifier\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"cospar\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Satellite COSPAR ID</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"norad\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Satellite Catalog (NORAD) Number</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sic\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>SIC Code</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sp3\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>SP3</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"other\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"positionZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referencePoint\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. center of mass in satellite frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"xStart\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"yStart\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>linear motion between start and end</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zStart\" type=\"double\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"xEnd\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"yEnd\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>linear motion between start and end</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zEnd\" type=\"double\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PotentialCoefficients2BlockMeanTimeSplines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write monthly potential coeffcients into one time spline file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSplines</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSplines\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSplinesCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only the variances are saved</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialCoefficients\" type=\"filename\" default=\"{groopsDataDir}/potential/\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"filter\" type=\"sphericalHarmonicsFilterType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeMean\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>remove the temporal mean of the series before estimating the splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolate\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolate missing files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"splineTimeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input files must be between points in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"splineDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree of splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PotentialCoefficients2DegreeAmplitudes\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>degree amplitudes of potential coefficients</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>matrix with degree, signal amplitude, formal error, differences</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialCoefficients\" type=\"filename\" default=\"{groopsDataDir}/potential/\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\" default=\"geoidHeight\"/>\n\t\t\t\t\t\t<xs:element name=\"filter\" type=\"sphericalHarmonicsFilterType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>filter the coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>type of variances</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rms\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>degree amplitudes (square root of degree variances)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"accumulation\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>cumulate variances over degrees</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"evaluationRadius\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>evaluate the gravity field at this radius (default: evaluate at surface</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"polarGap\" type=\"angle\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>exclude polar regions (aperture angle in degrees)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"RadialBasisSplines2KernelCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Kernel/Covariance-function from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kaulaPower\" type=\"double\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma = kaulaFactor/degree^kaulaPower</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kaulaFactor\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma = kaulaFactor/degree^kaulaPower</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SatelliteModelCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create satellite macro model.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteModel\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"satellite\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:appinfo>rename: modul = module</xs:appinfo>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"satelliteName\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"mass\" type=\"double\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"coefficientDrag\" type=\"double\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"surfaces\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>each line must contain one surface element</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"expression\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>0: plate, 1: sphere, 2: cylinder</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"area\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m^2]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"normalX\" type=\"expression\" default=\"data1\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"normalY\" type=\"expression\" default=\"data2\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"normalZ\" type=\"expression\" default=\"data3\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"reflexionVisible\" type=\"expression\" default=\"data4\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"diffusionVisible\" type=\"expression\" default=\"data5\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"absorptionVisible\" type=\"expression\" default=\"data6\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"reflexionInfrared\" type=\"expression\" default=\"data7\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"diffusionInfrared\" type=\"expression\" default=\"data8\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"absorptionInfrared\" type=\"expression\" default=\"data9\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"specificHeatCapacity\" type=\"expression\" default=\"data10\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>0: no thermal radiation, -1: direct reemission [Ws/K/m^2]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"module\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"antennaThrust\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"thrustX\" type=\"double\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"thrustY\" type=\"double\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"thrustZ\" type=\"double\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"solarPanel\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationAxisX\" type=\"double\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationAxisY\" type=\"double\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationAxisZ\" type=\"double\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"normalX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Direction to sun</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"normalY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Direction to sun</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"normalZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Direction to sun</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"indexSurface\" type=\"uint\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>index of solar panel surfaces</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"massChange\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"mass\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"massInstrument\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SynthesisSphericalHarmonicsMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>matrix for synthesizing spherical harmonics on a grid</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme of sh coefficients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"type\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"synthesis\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>synthesize spherical harmonics on a grid</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"quadrature\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>calculate spherical harmonics from grid</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"leastSquares\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>estimated spherical harmonics from grid</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"TemporalRepresentation2TimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Design matrix of temporal representation.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrix\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Time (MJD) in first column, design matrix follows</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"temporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ThermosphericState2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>thermospheric state values</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>density [kg/m**3], temperature [K], wind (x, y, z) [m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"thermosphere\" type=\"thermosphereType\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\"/>\n\t\t\t\t\t\t<xs:element name=\"localReferenceFrame\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>wind in local north, east, up, otherwise global terrestrial</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"TimeSeries2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write time series as potential coefficients for each epoch.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilesPotentialCoefficients\" type=\"filename\" default=\"coeff_{loopTime:%y-%m}.gfc\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopTime\" type=\"string\" minOccurs=\"0\" default=\"loopTime\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with time of each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopIndex\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with index of current epoch (starts with zero)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopCount\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable with total number of epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>each epoch: multiple data for points (MISCVALUES)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first data column</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimal degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximal degree</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"TimeSeriesCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create a time series</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileFile = outputfileTimeSeries</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time series to be created</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"data\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression of output columns, extra &apos;epoch&apos; variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Variational2OrbitAndStarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Extracts orbit and star camera data from variational file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputFileOrbit = outputfileOrbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputFileVariational = inputfileVariational</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Misc</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: VariationalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output orbit (instrument) file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output satellite attidude as star camera (instrument) file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileEarthRotation\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output Earth rotation as star camera (instrument) file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input variational file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsAccumulate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accumulate normal equations and write to file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsBuild\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accumulate normal equations and write it to file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: normalequation = normalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"normalEquation\" type=\"normalEquationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"normalsBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsBuildShortTimeStaticLongTime\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Normal equations with static, short time, and long time gravity field parameters</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: arcList = inputfileArcList</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>outputfile for normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observation\" type=\"observationType\"/>\n\t\t\t\t\t\t<xs:element name=\"estimateShortTimeVariations\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>co-estimate short time gravity field variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"autoregressiveModelSequence\" type=\"autoregressiveModelSequenceType\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>AR model sequence for constraining short time gravity variations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parameters describing the short time gravity field</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateLongTimeVariations\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>co-estimate long time gravity field variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parametrization of time variations (trend, annual, ...)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parameters describing the long time gravity field</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list to correspond points of time to arc numbers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"eliminateParameter\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>eliminate short time and state parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>create normal equations from calculated matrices</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequationObsCount = inputfileNormalEquationObsCount</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileParameterNames\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"normalMatrix\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"matrixGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"lPl\" type=\"matrixGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>vector with size of rhs columns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquationObsCount\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sets the variable observationCount</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observationCount\" type=\"expression\" default=\"observationCount\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(variables: rows, columns (rhs), observationCount)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsEliminate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Eliminate parameters from a system of normal equations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"remainingParameters\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of output normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsMultiplyAdd\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>n += alpha*N*x</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileParameter\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>x</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>alpha</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"writeNormalMatrix\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>write full coefficient matrix, right hand sides and info files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsRegularizationBorders\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Two regularization matrices for inside und outside of Border</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInside\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileOutside\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"grid\" type=\"gridType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>nodal point distribution of parameters, e.g harmonics splines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"border\" type=\"borderType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>regularization areas, e.g land and ocean</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates for border</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates for border, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsRegularizationSphericalHarmonics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>diagonal regularization matrix from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDiagonalmatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minRegularizationDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxRegularizationDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" default=\"2\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"numbering\" type=\"sphericalHarmonicsNumberingType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>numbering scheme for regul matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"makeIsotropic\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"kaulaPower\" type=\"double\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma = kaulaFactor*degree**kaulaPower</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kaulaFactor\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>sigma = kaulaFactor*degree**kaulaPower</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsReorder\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Reorder normal equations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of output normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsReorderAndAccumulate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>accumulate normal equations and write to file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"outBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block, empty: blocking by objects</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsScale\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Scales rows and columns of a normal equation system</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileFactorVector\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Vector containing the factors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsSolverVCE\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>solve normal equations (relative weighting by variance component estimation (VCE))</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: normalequation = normalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>full covariance matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileContribution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>contribution of normal system components to the solution vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileVarianceFactors\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated variance factors as vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the combined normal equation system</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"normalEquation\" type=\"normalEquationType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileApproxSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to accelerate convergence</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightHandSideNumberVCE\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>the right hand side number for estimation of variance factors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"normalsBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size for distributing the normal equations, 0: one block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxIterationCount\" type=\"uint\" minOccurs=\"0\" default=\"20\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum number of iterations for variance component estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsTemporalCombination\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>normal equations of trend, annual from a time series of normal equations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileNormalequation = outputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: temporalRepresentation = parametrizationTemporal</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normal equations for each point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>times of each normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationTemporal\" type=\"parametrizationTemporalType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ParameterNamesCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Generate a parameter names file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output parameter names file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameterName\" type=\"parameterNamesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ParameterSelection2IndexVector\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Generate index vector from parameter selection.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileIndexVector\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>indices of source parameters in target normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterNames\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output parameter names file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileParameterNames\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter names file of source normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter order/selection of target normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2ArgumentOfLatitude\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Argument of latitude.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileArgOfLatitude\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (MISCVALUE(S): argLat, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data are appended</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2BetaPrimeAngle\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Beta prime angle</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileBetaAngle\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (MISCVALUE(S): beta&apos;, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data are appended</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"planet\" type=\"planetType\" minOccurs=\"0\" default=\"sun\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2EarthFixedOrbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>rotate an orbit into a rotation earth fixed frame</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>transformation from CRF to TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[{&quot;tides&quot;: {&quot;tides&quot;: {&quot;doodsonHarmonicTide&quot;: {&quot;minDegree&quot;:1, &quot;maxDegree&quot;:1}}}}]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree 1 fluid mantle for CM2CE correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"celestial2terrestrial\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>yes: crf-&gt;trf, no: trf-&gt;crf</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2EclipseFactor\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create instrument file containing eclipse factors.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEclipseFactor\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (MISCVALUE(S): eclipse, ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data are appended</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2Groundtracks\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>groundtracks of a satellite as gridded data.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>positions as gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>values at grid points</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>transformation from CRF to TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2Kepler\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>keplerian elements from orbit position and velocity at each epoch</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileKepler\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (MISCVALUES: Omega, i, omega [degree], a [m], e, M [degree], tau [mjd], ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position and velocity at each epoch define the kepler orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data is appended</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2MagneticField\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Thermospheric state along orbit.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMagneticField\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (x,y,z in CRF [Tesla = kg/A/s^2]), ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data are appended to output file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"magnetosphere\" type=\"magnetosphereType\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2ThermosphericState\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Thermospheric state along orbit.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileThermosphericState\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file (MISCVALUES: density, temperature, wind (x,y,z in CRF), ...)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data are appended to output file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"thermosphere\" type=\"thermosphereType\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"OrbitAddVelocityAndAcceleration\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Compute velocities and accelerations from a given orbit</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"polynomialDegree\" type=\"uint\" minOccurs=\"0\" default=\"8\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Polynomial degree, must be even!</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlanetOrbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>orbits of sun, moon and, planets</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"planet\" type=\"planetType\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>transform orbits into TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlotDegreeAmplitudes\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Plot Degree Amplitudes</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: annotationDegree = majorTickSpacingDegree</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frameDegree = minorTickSpacingDegree</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: gridDegree = gridLineSpacingDegree</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: annotationY = majorTickSpacingY</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frameY = minorTickSpacingY</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: gridY = gridLineSpacingY</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gravityfield</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*.png, *.jpg, *.eps, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"title\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"layer\" type=\"plotGraphLayerType\" default=\"degreeAmplitudesSimple\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacingDegree\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacingDegree\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>frame tick spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacingDegree\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridline spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"labelDegree\" type=\"string\" minOccurs=\"0\" default=\"[degree]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of the x-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"logarithmicDegree\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use logarithmic scale for the x-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minY\" type=\"double\" minOccurs=\"0\" default=\"1e-6\"/>\n\t\t\t\t\t\t<xs:element name=\"maxY\" type=\"double\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacingY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacingY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>frame tick spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacingY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridline spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"unitY\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>appended to axis values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"labelY\" type=\"string\" minOccurs=\"0\" default=\"geoid height [m]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of the y-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"logarithmicY\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use logarithmic scale for the y-axis</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLine\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;:&quot;0.25&quot;, &quot;color&quot;:&quot;gray&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The style of the grid lines.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"legend\" type=\"plotLegendType\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"options\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>further options...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"titleFontSize\" type=\"uint\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in pt</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"marginTitle\" type=\"double\" minOccurs=\"0\" default=\"0.4\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>between title and figure [cm]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"drawGridOnTop\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>grid lines above all other lines/points</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"options\" type=\"string\" minOccurs=\"0\" default=\"[&quot;FONT_ANNOT_PRIMARY=10p&quot;, &quot;MAP_ANNOT_OFFSET_PRIMARY=0.1c&quot;, &quot;FONT_LABEL=10p&quot;, &quot;MAP_LABEL_OFFSET=0.1c&quot;, &quot;FONT_ANNOT_SECONDARY=10p&quot;]\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"transparent\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>make background transparent</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dpi\" type=\"uint\" minOccurs=\"0\" default=\"300\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use this resolution when rasterizing postscript file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"removeFiles\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>remove .gmt and script files</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlotGraph\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Plot functions (x,y)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*.png, *.jpg, *.eps, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"title\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"layer\" type=\"plotGraphLayerType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"axisX\" type=\"plotAxisType\"/>\n\t\t\t\t\t\t<xs:element name=\"axisY\" type=\"plotAxisType\"/>\n\t\t\t\t\t\t<xs:element name=\"axisY2\" type=\"plotAxisType\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Second y-axis on right hand side</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"colorbar\" type=\"plotColorbarType\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"legend\" type=\"plotLegendType\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"options\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>further options...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"titleFontSize\" type=\"uint\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in pt</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"marginTitle\" type=\"double\" minOccurs=\"0\" default=\"0.4\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>between title and figure [cm]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"drawGridOnTop\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>grid lines above all other lines/points</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"options\" type=\"string\" minOccurs=\"0\" default=\"[&quot;FONT_ANNOT_PRIMARY=10p&quot;, &quot;MAP_ANNOT_OFFSET_PRIMARY=0.1c&quot;, &quot;FONT_LABEL=10p&quot;, &quot;MAP_LABEL_OFFSET=0.1c&quot;, &quot;FONT_ANNOT_SECONDARY=10p&quot;, &quot;TIME_SYSTEM=MJD&quot;]\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"transparent\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>make background transparent</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dpi\" type=\"uint\" minOccurs=\"0\" default=\"300\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use this resolution when rasterizing postscript file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"removeFiles\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>remove .gmt and script files</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlotMap\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Plot maps</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: annotation = majorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frame = minorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: grid = gridLineSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*.png, *.jpg, *.eps, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"title\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"statisticInfos\" type=\"boolean\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"layer\" type=\"plotMapLayerType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates on output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minLambda\" type=\"angle\" minOccurs=\"0\" default=\"-180\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min. longitude (default: compute from input data)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxLambda\" type=\"angle\" minOccurs=\"0\" default=\"180\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>max. longitude (default: compute from input data)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minPhi\" type=\"angle\" minOccurs=\"0\" default=\"-90\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>min. latitude (default: compute from input data)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxPhi\" type=\"angle\" minOccurs=\"0\" default=\"90\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>max. latitude (default: compute from input data)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacing\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacing\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>frame tick spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacing\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridline spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"colorbar\" type=\"plotColorbarType\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"projection\" type=\"plotMapProjectionType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>map projection</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"options\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>further options...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"titleFontSize\" type=\"uint\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in pt</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"marginTitle\" type=\"double\" minOccurs=\"0\" default=\"0.4\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>between title and figure [cm]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"drawGridOnTop\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>grid lines above all other lines/points</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"options\" type=\"string\" minOccurs=\"0\" default=\"[&quot;FONT_ANNOT_PRIMARY=10p&quot;, &quot;MAP_ANNOT_OFFSET_PRIMARY=0.1c&quot;, &quot;FONT_LABEL=10p&quot;, &quot;MAP_LABEL_OFFSET=0.1c&quot;, &quot;FONT_ANNOT_SECONDARY=10p&quot;]\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"transparent\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>make background transparent</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dpi\" type=\"uint\" minOccurs=\"0\" default=\"300\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use this resolution when rasterizing postscript file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"removeFiles\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>remove .gmt and script files</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlotMatrix\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Plot coefficients of a Matrix.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: annotationX = majorTickSpacingX</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frameX = minorTickSpacingX</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: gridX = gridLineSpacingX</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: annotationY = majorTickSpacingY</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frameY = minorTickSpacingY</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: gridY = gridLineSpacingY</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*.png, *.jpg, *.eps, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"title\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrix\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"minColumn\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum column index to plot</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxColumn\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum column index to plot</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacingX\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacingX\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>frame tick spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacingX\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridline spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minRow\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum row index to plot</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"maxRow\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>maximum row index to plot</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacingY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacingY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>frame tick spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacingY\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridline spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLine\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;:&quot;0.25&quot;, &quot;color&quot;:&quot;gray&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The style of the grid lines.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"colorbar\" type=\"plotColorbarType\"/>\n\t\t\t\t\t\t<xs:element name=\"options\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>further options...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"titleFontSize\" type=\"uint\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in pt</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"marginTitle\" type=\"double\" minOccurs=\"0\" default=\"0.4\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>between title and figure [cm]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"drawGridOnTop\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>grid lines above all other lines/points</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"options\" type=\"string\" minOccurs=\"0\" default=\"[&quot;FONT_ANNOT_PRIMARY=10p&quot;, &quot;MAP_ANNOT_OFFSET_PRIMARY=0.1c&quot;, &quot;FONT_LABEL=10p&quot;, &quot;MAP_LABEL_OFFSET=0.1c&quot;, &quot;FONT_ANNOT_SECONDARY=10p&quot;]\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"transparent\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>make background transparent</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dpi\" type=\"uint\" minOccurs=\"0\" default=\"300\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use this resolution when rasterizing postscript file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"removeFiles\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>remove .gmt and script files</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PlotSphericalHarmonicsTriangle\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Plot triangle of potential coefficients</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: annotation = majorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: frame = minorTickSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: grid = gridLineSpacing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Plot</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>*.png, *.jpg, *.eps, ...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"title\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use sigmas, if not given use signal (cnm,snm)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>at this time the gravity field will be evaluated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"majorTickSpacing\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>boundary annotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minorTickSpacing\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>frame tick spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLineSpacing\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gridline spacing</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gridLine\" type=\"plotLineType\" minOccurs=\"0\" default=\"{&quot;solid&quot;: {&quot;width&quot;:&quot;0.25&quot;, &quot;color&quot;:&quot;gray&quot;}}\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>The style of the grid lines.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"colorbar\" type=\"plotColorbarType\" default=\"{&quot;logarithmic&quot;:&quot;1&quot;}\"/>\n\t\t\t\t\t\t<xs:element name=\"options\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>further options...</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"width\" type=\"double\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"height\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in cm</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"titleFontSize\" type=\"uint\" minOccurs=\"0\" default=\"12\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>in pt</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"marginTitle\" type=\"double\" minOccurs=\"0\" default=\"0.4\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>between title and figure [cm]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"drawGridOnTop\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>grid lines above all other lines/points</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"options\" type=\"string\" minOccurs=\"0\" default=\"[&quot;FONT_ANNOT_PRIMARY=10p&quot;, &quot;MAP_ANNOT_OFFSET_PRIMARY=0.1c&quot;, &quot;FONT_LABEL=10p&quot;, &quot;MAP_LABEL_OFFSET=0.1c&quot;, &quot;FONT_ANNOT_SECONDARY=10p&quot;]\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"transparent\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>make background transparent</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dpi\" type=\"uint\" minOccurs=\"0\" default=\"300\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>use this resolution when rasterizing postscript file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"removeFiles\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>remove .gmt and script files</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingDualSst\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate covariance function / arc weights.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Residuals</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: KalmanFilter</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameter vector (static part only)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterName\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated signal parameters (index is appended)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateArcSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcSst1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (SST1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcSst2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (SST2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcAcc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (ACC)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcPod1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (POD1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcPod2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (POD2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateEpochSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochSst1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (SST1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochSst2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (SST2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochAcc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (ACC)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochPod1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (POD1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochPod2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (POD2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateCovarianceFunctions\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionSst1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionSst2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionAcc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionPod1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance functions for along, cross, radial direction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionPod2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance functions for along, cross, radial direction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeResiduals\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSst1Residuals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSst2Residuals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileAccResiduals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfilePod1Residuals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfilePod2Residuals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>obervation equations (Sst)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dualSstVariational\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>two SST observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking1\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking2\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite A as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite B as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileVariational1\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileVariational2\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationSst1\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter for first ranging observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationSst2\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter for second ranging observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst1\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Must be given per sst arc with correct dimensions.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Vector with one sigma for each &lt;inputfileCovarianceMatrixArc&gt;</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst2\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Must be given per sst arc with correct dimensions.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Vector with one sigma for each &lt;inputfileCovarianceMatrixArc&gt;</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceAcc\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Must be given per sst arc with correct dimensions.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Vector with one sigma for each &lt;inputfileCovarianceMatrixArc&gt;</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod1\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch covariances</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod2\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch covariances</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateShortTimeVariations\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>co-estimate short time gravity field variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"estimateSigma\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>estimate standard deviation via VCE</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"autoregressiveModelSequence\" type=\"autoregressiveModelSequenceType\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>AR model sequence for constraining short time gravity variations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parameters describing the short time gravity field</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"downweightPod\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>downweight factor for POD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list to correspond points of time to arc numbers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for the estimation of calibration parameter and error PSD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameIterations\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size of static normal equation blocks</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingGradiometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate covariance function / arc weights.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSggResiduals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"sggRightSideType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for the observation vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationBias\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>per arc</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSgg\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"covarianceLength\" type=\"uint\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>counts observation epochs</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for the estimation of calibration parameter and error PSD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingPod\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate covariance function / arc weights.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: arcList = inputfileArcList</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Residuals</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameter vector (static part only)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterName\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>names of estimated parameters (static part only)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateArcSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcPod\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (POD2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateCovarianceFunctions\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionPod\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance functions for along, cross, radial direction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeResiduals\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfilePodResiduals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>obervation equations (POD)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"podIntegral\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>precise orbit data (integral approach)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"podRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input for the reduced observation vector</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"gradientfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>low order field to estimate the change of the gravity by position adjustement</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"keepSatelliteStates\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>set boundary values of each arc global</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"accelerateComputation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>acceleration of computation by transforming the observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"podVariational\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>precise orbit data (variational equations)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"accelerateComputation\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>acceleration of computation by transforming the observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuracies for each arc (multiplied with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch covariances</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list to correspond points of time to arc numbers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"adjustmentThreshold\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Adjustment factor threshold: Iteration will be stopped once both SST and POD adjustment factors are under this threshold</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for the estimation of calibration parameters and error PSD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingSst\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Estimate covariance function / arc weights.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Residuals</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: KalmanFilter</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated parameter vector (static part only)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileParameterName\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated signal parameters (index is appended)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateArcSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcSst\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (SST)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcPod1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (POD1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerArcPod2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each arc (POD2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateEpochSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochSst\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (SST)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochPod1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (POD1)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasPerEpochPod2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>accuracies of each epoch (POD2)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateCovarianceFunctions\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionSst\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionPod1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance functions for along, cross, radial direction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunctionPod2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>covariance functions for along, cross, radial direction</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateSstArcCovarianceSigmas\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSigmasCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>one variance factor per matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"computeResiduals\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfileSstResiduals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfilePod1Residuals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"outputfilePod2Residuals\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observation\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>obervation equations (Sst)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sstIntegral\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integral approach</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: satelliteModel1 = inputfileSatelliteModel1</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: satelliteModel2 = inputfileSatelliteModel2</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter1 = parametrizationAcceleration1</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter2 = parametrizationAcceleration2</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameterSst = parametrizationSst</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel1\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel2\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rightHandSide\" type=\"sstRightSideType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input for the reduced observation vector</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeAcceleration\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>used to evaluate the observation equations, not used as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera1\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera2\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"gradientfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>low order field to estimate the change of the gravity by position adjustement</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationSst\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"keepSatelliteStates\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>set boundary values of each arc global</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sstVariational\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>variational equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter1 = parametrizationAcceleration1</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter2 = parametrizationAcceleration2</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameterSst = parametrizationSst</xs:appinfo>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite A as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite B as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileVariational1\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileVariational2\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationSst\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Must be given per sst arc with correct dimensions.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasCovarianceMatrixArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Vector with one sigma for each &lt;inputfileCovarianceMatrixArc&gt;</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod1\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch covariances</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod2\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sigma\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori factor of covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerArc\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each arc (multiplicated with sigma)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmasPerEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>apriori different accuaries for each epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>approximate covariances in time</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch covariances</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] sampling of the covariance function</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"estimateShortTimeVariations\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>co-estimate short time gravity field variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"estimateSigma\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>estimate standard deviation via VCE</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"autoregressiveModelSequence\" type=\"autoregressiveModelSequenceType\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>AR model sequence for constraining short time gravity variations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"parameterSelection\" type=\"parameterSelectorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parameters describing the short time gravity field</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"downweightPod\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>downweight factor for POD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileArcList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list to correspond points of time to arc numbers</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(maximum) number of iterations for the estimation of calibration parameter and error PSD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameIterations\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"defaultBlockSize\" type=\"uint\" minOccurs=\"0\" default=\"2048\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>block size of static normal equation blocks</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingVariationalEquation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Integrate Variational Equations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: VariationalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVariational\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position, used to evaluate the force</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from body frame to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>non-gravitational forces in satellite reference frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"forces\" type=\"forcesType\"/>\n\t\t\t\t\t\t<xs:element name=\"estimatedParameters\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite parameters e.g. from orbit fit</xs:documentation>\n\t\t\t\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileParameter\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>estimated orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"gradientfield\" type=\"gravityfieldType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>low order field to estimate the change of the gravity by position adjustement</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useEnke\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integrate differential forces to an elliptical reference trajectory</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>geocentric gravitational constant used for elliptical reference orbit</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingVariationalEquationOrbitFit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>fit variational equations to orbit observations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter = parametrizationAcceleration</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: VariationalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVariational\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated calibration and state parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite as observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovariancePodEpoch\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch wise covariances</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>may be needed by parametrizationAcceleration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stochasticPulse\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for the estimation of calibration parameter and error PSD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PreprocessingVariationalEquationSstFit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>fit variational equations to sst/orbit observations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: representation = parametrizationGravity</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter1 = parametrizationAcceleration1</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameter2 = parametrizationAcceleration2</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parameterSst = parametrizationSst</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Preprocessing</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: VariationalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVariational1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileVariational2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integrated orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated calibration and state parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>estimated calibration and state parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rightHandSide\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input for observation vectors</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ranging observations and corrections</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite A as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>kinematic positions of satellite B as observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sstType\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"range\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rangeRate\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"none\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileVariational2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>approximate position and integrated state matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"parametrizationGravity\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>gravity field parametrization</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration1\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit1 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationAcceleration2\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit2 force parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrizationSst\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite tracking parameter</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>integration of forces by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit interpolation by polynomial approximation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covarianceSst\" type=\"covarianceSstType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of satellite to satellite tracking observations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod1\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"covariancePod2\" type=\"covariancePodType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>covariance matrix of kinematic orbits (satellite 2)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"iterationCount\" type=\"uint\" minOccurs=\"0\" default=\"10\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for the estimation of calibration parameter and error PSD</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseAccelerometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>add noise and bias to accelerometer data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"biasAlong\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"biasCross\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"biasRadial\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseAlong\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseCross\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseRadial\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseGriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>add noise to gridded data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseInstrument\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>add noise to instrument data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileInstrument\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"startDataFields\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"countDataFields\" type=\"uint\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of data fields (default: all after start)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseNormalsSolution\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create a correlated error vector from a system of normal equations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileNormalequation = inputfileNormalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNoise\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>generated noise as matrix: parameterCount x sampleCount</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormalEquation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"sampleCount\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of samples to be generated</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useEigenvalueDecomposition\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use eigenvalue decomposition</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseOrbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>add noise to orbit positions and velocities</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"noisePosition\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along, cross, radial [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseVelocity\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>along, cross, radial [m/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseSatelliteTracking\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>generate noise and add the result to satellite tracking data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTracking\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"noiseRange\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseRangeRate\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseRangeAcceleration\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s^2]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseStarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>add noise to rotation observations</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"noiseRoll\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noisePitch\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"noiseYaw\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NoiseTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>generate random noise</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Noise</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSeries</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNoise\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovarianceFunction\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"noise\" type=\"noiseGeneratorType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"columns\" type=\"uint\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>number of noise series (columns)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateAccelerometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>simulate accelerometer data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"forces\" type=\"forcesType\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateAccelerometerCoMOffset\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create accelerations due to CoM offset.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>effect of offset</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"applyAngularRate\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute effect of centrifugal forces</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"applyAngularAccelerations\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute effect of Euler forces</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gradientfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>low order field to estimate the change of the gravity by position adjustement</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>derivation of quaternions by polynomial interpolation of degree n</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"CoMOffsetX\" type=\"double\" default=\"50e-6\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>offset [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"CoMOffsetY\" type=\"double\" default=\"50e-6\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>offset [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"CoMOffsetZ\" type=\"double\" default=\"50e-6\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>offset [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateGradiometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>simulate error free gradiometer data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGradiometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"tides\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateKeplerOrbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>compute Keplerian orbit</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationConstants\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"kepler\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"majorAxis\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"eccentricity\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[-]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inclination\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ascendingNode\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"argumentOfPerigee\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"meanAnomaly\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration constants are valid at this epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"positionAndVelocity\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"position0x\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in CRF</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"position0y\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in CRF</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"position0z\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in CRF</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"velocity0x\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"velocity0y\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"velocity0z\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>integration constants are valid at this epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateOrbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>pure dynamical orbit integration</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: satelliteModel = inputfileSatelliteModel</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit file to be written.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/satelliteModel/\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite macro model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>time points for simulated orbit epochs.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"integrationConstants\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"kepler\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"majorAxis\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"eccentricity\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[-]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inclination\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"ascendingNode\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"argumentOfPerigee\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"meanAnomaly\" type=\"angle\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"positionAndVelocity\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"position0x\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in CRF</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"position0y\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in CRF</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"position0z\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in CRF</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"velocity0x\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"velocity0y\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"velocity0z\" type=\"double\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m/s]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"file\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>only epoch at timeStart is used</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"margin\" type=\"double\" minOccurs=\"0\" default=\"1e-5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] used when finding initial epoch in orbitFile</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"propagator\" type=\"orbitPropagatorType\" default=\"polynomial\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit propagation method.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\" minOccurs=\"0\" default=\"jpl\"/>\n\t\t\t\t\t\t<xs:element name=\"forces\" type=\"forcesType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>considered in orbit propagation.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"reverse\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start integration at last epoch in timeSeries, going backward in time.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateSatelliteTracking\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>simulate tracking data (range, range-rate, range-accelerations) between 2 satellites</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTracking\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateStarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Rotation from satellite (x: along, y: cross, z: nadir) to inertial frame.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from satellite to inertial frame (x: along, y: cross, z: nadir)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position and velocity defines the orientation of the satellite at each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"nadirPointing\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>false: exact along and nearly nadir, true: nearly along and exact nadir</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateStarCameraGnss\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Simulates star camera data for a GNSS satellite based on an attitude model.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from body frame to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>attitude is modeled based on this orbit</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAttitudeInfo\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/transmitter/attitudeInfo/attitudeInfo.{svn}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>attitude modes used by the satellite and respective parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" minOccurs=\"0\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>polynomial degree for orbit interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"modelingResolution\" type=\"double\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[s] resolution for attitude model evaluation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ephemerides\" type=\"ephemeridesType\"/>\n\t\t\t\t\t\t<xs:element name=\"eclipse\" type=\"eclipseType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>model to determine if satellite is in Earth&apos;s shadow</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateStarCameraGrace\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Simulates the orientation of the two GRACE satellites.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera1\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera2\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position define the orientation of the satellite at each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position define the orientation of the satellite at each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaCenters\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>KBR antenna phase center</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1X\" type=\"double\" minOccurs=\"0\" default=\"1.4451172588\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>x-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1Y\" type=\"double\" minOccurs=\"0\" default=\"-0.0004233040\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>y-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center1Z\" type=\"double\" minOccurs=\"0\" default=\"0.0022786600\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>z-coordinate of antenna position in SRF [m] for GRACEA</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2X\" type=\"double\" minOccurs=\"0\" default=\"1.4443870350\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>x-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2Y\" type=\"double\" minOccurs=\"0\" default=\"0.0005761203\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>y-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"center2Z\" type=\"double\" minOccurs=\"0\" default=\"0.0033040887\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>z-coordinate of antenna position in SRF [m] for GRACEB</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"file\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputAntennaCenters\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateStarCameraSentinel1\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>simulate star camera data for Sentinel 1</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position and velocity defines the orientation of the satellite at each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SimulateStarCameraTerrasar\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>simulate star camera data for Terrasar</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Simulation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from satellite to inertial frame (x: along, y: cross, z: nadir)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>position and velocity defines the orientation of the satellite at each epoch</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SlrProcessing\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Satellite Laser Ranging (SLR) processing</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>defines station movements and earth rotation epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satellite\" type=\"slrSatelliteGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellites</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"station\" type=\"slrStationGeneratorType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ground station network</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori earth rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parametrization\" type=\"slrParametrizationType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>models and parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"processingStep\" type=\"slrProcessingStepType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>steps are processed consecutively</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FileConvert\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts GROOPS file between different file formats (ASCII, XML, JSON, binary).</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputFile = outputfile</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: inputFile = inputfile</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: VariationalEquation</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSplines</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FileCreateDirectories\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Creates the directory and parent directories as needed.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"directory\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FileMove\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Move/rename file or directory.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>target name or directory for the move/rename</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FileRemove\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Remove files or directories.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"files\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"FileTextCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create text file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"line\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GroupPrograms\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Runs programs in group and can catch errors.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: programme = program</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileLog\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional log file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"silently\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>without showing the output.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"program\" type=\"programType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"catchErrors\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"errorProgram\" type=\"programType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>executed if an error occured</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"IfPrograms\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Runs programs if condition is met.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: programme = program</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"condition\" type=\"conditionType\"/>\n\t\t\t\t\t\t<xs:element name=\"program\" type=\"programType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>executed if condition evaluates to true</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elseProgram\" type=\"programType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>executed if condition evaluates to false</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"LoopPrograms\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Runs programs multiple times.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: programme = program</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: parallelLoops = processCountPerLoopStep</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>rename: processCountPerLoopStep = processCountPerIteration</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"loop\" type=\"loopType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>subprograms are called for every iteration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"continueAfterError\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>continue with next iteration after error, otherwise throw exception</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"processCountPerIteration\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>0: use all processes for each iteration</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"parallelLog\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>write to screen/log file from all processing nodes in parallelized loops</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"program\" type=\"programType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"RunCommand\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Execute system commands</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: System</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"command\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"silently\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>without showing the output.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"continueAfterError\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>continue with next command after error, otherwise throw exception</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"executeParallel\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>execute several commands in parallel</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Accelerometer2GraceL1b\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>convert GROOPS ACC data into SDS L1B data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACT1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileHeader\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>YAML Header, {epochmin}, {epochmax}, {epochcount} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAngularAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileFlags\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteId\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>A, B, C or D</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"BerneseKinematic2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read kinematic orbits in Bernese format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>from TRF to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Champ2AccStar\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read CHAMP accelerometer and star camera data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularAcceleration\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Champ2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read champ PSO orbits from the special CHORB format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Cosmic2OrbitStar\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read COSMIC orbit and star camera data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Cpf2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read orbit from SLR prediction (CPF) format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" default=\"output/orbit_{satellite}_{loopNumberEphVersion:%03i}{loopNumberVersion:%02i}_{loopSource}_{loopTime:%D}.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SLR CPF file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Crd2NormalPoints\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read SLR data from CRD format for a given satellite</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalPoints\" type=\"filename\" default=\"output/normalsPoints_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileMeteorological\" type=\"filename\" default=\"output/meteorological_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSlrData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SLR CRD files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Cstg2NormalPoints\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read SLR data from CSTG format for a given satellite</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalPoints\" type=\"filename\" default=\"output/normalsPoints_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileMeteorological\" type=\"filename\" default=\"output/meteorological_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSlrData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SLR CSTG file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonAdmittance2SupplementaryFiles\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write ascii doodson and admittance matrix</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMajorTideList\" type=\"filename\" minOccurs=\"0\" default=\"fileList.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"fileNames\" type=\"filename\" minOccurs=\"0\" default=\"model_{doodson}_{name}_{cossin}.gfc\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>template for fileList, variables: doodson, name, cossin</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonMatrix\" type=\"filename\" minOccurs=\"0\" default=\"doodson.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAdmittanceMatrix\" type=\"filename\" minOccurs=\"0\" default=\"admittance.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAdmittance\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>interpolation of minor constituents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonHarmonics2IersPotential\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>convert doodson harmonics file to IERS</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>according to IERS2010, chapter 6.3.2, footnote 7</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonHarmoncis\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"header\" type=\"string\" default=\"[&quot;Coefficients to compute variations in normalized Stokes coefficients (unit = 10^-11)&quot;, &quot;Ocean tide model: FES2014b up to (100,100) in cm&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>info for output header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"1e11\"/>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"DoodsonHarmonics2IersWaterHeight\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>convert doodson harmonics file to IERS</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>according to IERS2010, chapter 6.3.2, footnote 7</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDoodsonHarmoncis\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" default=\"{groopsDataDir}/tides/generatingTide_HW95.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to compute Xi phase correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"header\" type=\"string\" default=\"Ocean tide model: FES2014b up to (100,100) in cm\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>info for output header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\" default=\"waterHeight\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data type of output values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"100\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. from [m] to [cm]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAntex2AntennaDefinition\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts IGS ANTEX file to GNSS metadata and antenna definition files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaDefinitionStation\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>antenna center variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntennaDefinitionTransmitter\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>antenna center variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterInfo\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PRN is appended to file name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterListGps\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterListGlonass\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterListGalileo\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterListBeiDou\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterListQzss\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTransmitterListIrnss\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list of PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntex\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore older antenna definitions</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"createZeroModel\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>create empty antenna patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssClock2ClockRinex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts GNSS clocks from GROOPS format to IGS clock RINEX format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileClockRinex\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"satelliteData\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one element per satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileClock\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>clock instrument file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>PRN (e.g. G23)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationData\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one element per station</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileClock\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>clock instrument file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfilePosition\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>station position file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>station info file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>station name (e.g. wtzz)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>comment in header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"program\" type=\"string\" default=\"GROOPS\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of program (for first line)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"institution\" type=\"string\" default=\"TUG (TU Graz)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of agency (for first line)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"analysisCenter\" type=\"string\" default=\"TUG  Graz University of Technology (TU Graz), Austria\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of analysis center</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"differentialCodeBias\" type=\"string\" minOccurs=\"0\" default=\"GROOPS            OSB co-estimated in LSA (see bias file)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>program and source for applied differential code bias</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"phaseCenterVariations\" type=\"string\" default=\"GROOPS            igs20.atx @ files.igs.org \">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>program and source for applied phase center variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referenceClock\" type=\"string\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>identifier of reference satellite/station</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referenceFrame\" type=\"string\" default=\"IGb14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>terrestrial reference frame for the stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssClockRinex2InstrumentClock\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert GNSS clock RINEX files to single value instrument files for satellites or stations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: inputfileIgsClock = inputfileClockRinex</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>identifier is appended to each file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileClockRinex\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite or station identifier, e.g. G23 or alic</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"intervals\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"minEpochsPerInterval\" type=\"uint\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>minimum number of epochs in an interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssEop2IgsErp\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write GNSS Earth orientation parameters to IGS ERP file format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileIgsErp\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>IGS ERP file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"epoch\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. daily solution</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSolution\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parameter vector</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileParameterNames\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>parameter names</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterList\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>transmitter PRNs used in solution (used for transmitter count)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStationList\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>stations used in solution (used for station count)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>reference time for epoch</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssGriddedDataTimeSeries2Ionex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts TEC maps from GROOPS GriddedDataTimeSeries format to IGS IONEX file format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSplines</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileIonex\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedDataTimeSeries\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>must contain regular grid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" default=\"data0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>expression (e.g. data column)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(empty = use input file time series)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"program\" type=\"string\" default=\"GROOPS\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of program (for first line)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"institution\" type=\"string\" default=\"TUG (TU Graz)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of agency (for first line)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description in header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" default=\"[&quot;TEC values in 0.1 TECU, 9999 if no value available&quot;]\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>comment in header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"mappingFunction\" type=\"string\" minOccurs=\"0\" default=\"MSLM\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>see IONEX documentation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elevationCutoff\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>see IONEX documentation (0 if unknown)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observablesUsed\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>see IONEX documentation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"exponent\" type=\"int\" minOccurs=\"0\" default=\"-1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>factor 10^exponent is applied to all values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssIonex2GriddedDataTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts TEC maps from IGS IONEX file format to GROOPS GriddedDataTimeSeries format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSplines</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedDataTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileIonex\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssNormals2Sinex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write GNSS data/metadata and normal equations to SINEX format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSinexNormals\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>full SINEX file including normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSinexCoordinates\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file without normal equations (station coordinates file)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormals\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normal equation matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileApriori\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAprioriSigma\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>constraint sigmas for apriori parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAprioriMatrix\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normal equation matrix of applied constraints</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"transmitterConstellation\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>transmitter constellation metadata</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterList\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>transmitter PRNs used in solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>transmitter info file template</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>transmitter phase centers and variations (ANTEX)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"variablePrn\" type=\"string\" minOccurs=\"0\" default=\"prn\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop variable for PRNs from transmitter list</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stations\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStationList\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>stations contained in normal equations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/stationInfo/igs/stationInfo.{station}.xml\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>station info file template</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>station phase centers and variations (ANTEX)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"variableStationName\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>loop variable for station names from station list</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationTimeStart\" type=\"time\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>start time for which solution has observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationTimeEnd\" type=\"time\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>end time for which solution has observations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time for parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] observation sampling</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaCalibrationModel\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. IGS14_WWWW (WWWW = ANTEX release GPS week)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sinexHeader\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"agencyCode\" type=\"string\" minOccurs=\"0\" default=\"TUG\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>identify the agency providing the data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>start time of the data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>end time of the data </xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationCode\" type=\"string\" minOccurs=\"0\" default=\"C\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>technique used to generate the SINEX solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constraintCode\" type=\"string\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>0: tight constraint, 1: siginficant constraint, 2: unconstrained</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"solutionContent\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>solution types contained in the SINEX solution (S O E T C A)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>organizitions gathering/alerting the file contents</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"contact\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Address of the relevant contact. e-mail</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"output\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Description of the file contents</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"input\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Brief description of the input used to generate this solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"software\" type=\"string\" minOccurs=\"0\" default=\"GROOPS (https://github.com/groops-devs/groops)\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Software used to generate the file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"hardware\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Computer hardware on which above software was run</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileComment\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block from a file (truncated at 80 characters)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssOrbex2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts satellite attitude from ORBEX to StarCamera format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from body frame to TRF/CRF, identifier is appended to each file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbex\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(empty = all) satellite identifier, e.g. G23 or E05</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from TRF to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssReceiver2RinexObservation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts GnssReceiver Instrument file to RINEX.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileRinexObservation\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>RINEX observation file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGnssReceiver\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNSS instrument file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>antenna and receiver info</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>write comments at begin of header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observer\" type=\"string\" minOccurs=\"0\" default=\"TUG\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>header information</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"angency\" type=\"string\" minOccurs=\"0\" default=\"TUG\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>header information</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only use observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssRinexNavigation2OrbitClock\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert RINEX navigation file (e.g. broadcast ephemeris) to orbit and clock files.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PRN is appended to file name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileClock\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>PRN is appended to file name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileRinex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>RINEX navigation file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbit and clock evaluation epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for rotation from TRF to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(e.g. ***G12) only use satellites with PRN that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(e.g. ***R**) ignore satellites PRN that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"removeUnhealthySatellites\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Remove satellite ephemeris that have their sat flags set to unhealthy</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssSignalBias2SinexBias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert GNSS signal biases from GROOPS format to IGS SINEX Bias format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSinexBias\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one file per satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"transmitterBiases\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one element per satellite</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeVariableBias\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>one entry per time variable bias type</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, bias [m], (biasSlope [m/s])</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>bias type</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>PRN or station name (e.g. G23 or wtzz)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"receiverBiases\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one element per station</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>signal bias file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeVariableBias\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>one entry per time variable bias type</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>columns: mjd, bias [m], (biasSlope [m/s])</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"type\" type=\"gnssType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>bias type</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>PRN or station name (e.g. G23 or wtzz)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"agencyCode\" type=\"string\" default=\"TUG\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>identify the agency providing the data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fileAgencyCode\" type=\"string\" default=\"TUG\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>identify the agency creating the file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>start time of the data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>end time of the data </xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"biasMode\" default=\"absolute\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>absolute or relative bias estimates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"absolute\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"relative\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observationSampling\" type=\"double\" minOccurs=\"0\" default=\"30\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"intervalLength\" type=\"double\" minOccurs=\"0\" default=\"86400\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds] interval for bias parameter representation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"determinationMethod\" type=\"string\" minOccurs=\"0\" default=\"CO-ESTIMATED_IN_LSA\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>determination method used to generate the bias results (see SINEX Bias format description)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"receiverClockReferenceGnss\" type=\"string\" minOccurs=\"0\" default=\"G\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(G, R, E, C) reference GNSS used for receiver clock estimation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteClockReferenceObservables\" type=\"string\" minOccurs=\"0\" default=\"G  C1W  C2W\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>one per system, reference code observable on first and second frequency (RINEX3 format)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\" default=\"Graz University of Technology, Austria (TUG/TU Graz)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>organization gathering/altering the file contents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"contact\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>contact name and/or email address</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"input\" type=\"string\" minOccurs=\"0\" default=\"GNSS observations from the IGS station network\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>brief description of the input used to generate this solution</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"output\" type=\"string\" minOccurs=\"0\" default=\"Estimated signal biases from GNSS processing\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of the file contents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"software\" type=\"string\" minOccurs=\"0\" default=\"GROOPS (https://github.com/groops-devs/groops)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>software used to generate the file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"hardware\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>computer hardware on which above software was run</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssSinexBias2SignalBias\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts GNSS signal biases from SINEX Bias format to GnssSignalBias format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSignalBias\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>identifier is appended to file name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexBias\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileGlonassSignalDefinition\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/transmitter/signalDefinition/signalDefinition.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GLONASS frequency number mapping</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(empty = all) satellite PRN, e.g. G23 or E05</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssStationLog2Platform\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>GNSS analysis</xs:documentation>\n\t\t\t\t\t<xs:appinfo>rename: outputfileStationInfo = outputfileStationPlatform</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStationPlatform\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationLog\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to check antennas</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssTroposphere2TropoSinex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert GNSS troposphere data from GROOPS format to SINEX_TRO format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTropoSinex\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"station\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/stationInfo/stationInfo.{station}.xml\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>platform file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTroposphereData\" type=\"filename\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Troposphere data estimates (columns: mjd, trodry, trowet, tgndry, tgnwet, tgedry, tgewet)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileTroposphereSigmas\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Troposphere data sigmas (columns: mjd, sigma_trowet, sigma_tgnwet, sigma_tgewet)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfilePosition\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Precise station position (columns: mjd, x, y, z [m in TRF])</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntennaDefinition\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>station phase centers and variations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedGeoidHeight\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>value closest to the station&apos;s position is used in each case</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"dataSamplingInterval\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[sec] GNSS data sampling rate</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tropoSamplingInterval\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[sec] Tropospheric parameter sampling interval</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tropoModelingMethod\" type=\"string\" minOccurs=\"0\" default=\"Least Squares\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Tropospheric estimation method: Filter, Smoother, Least Squares, Piece-Wise Linear Interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"aPrioriTropoModel\" type=\"string\" minOccurs=\"0\" default=\"VMF3 Operational 1x1° gridded + gradients (V3GR)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>A priori tropospheric model used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tropoMappingFunction\" type=\"string\" minOccurs=\"0\" default=\"Vienna Mapping Functions 3 (VMF3)\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Name of mapping function used for hydrostatic and wet delay</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gradientMappingFunction\" type=\"string\" minOccurs=\"0\" default=\"Chen &amp; Herring (1997), C_dry=0.0031, C_wet=0.0007\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Name of mapping function used for gradients</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"metDataSource\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>source of surface meteorological observations used (see format desc.)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"observationWeighting\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>observation weighting model applied</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"elevationCutoff\" type=\"double\" minOccurs=\"0\" default=\"5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[deg]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gnssSystems\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>G=GPS, R=GLONASS, E=Galileo, C=BeiDou</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSystem\" type=\"string\" minOccurs=\"0\" default=\"G\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>G (GPS) or UTC</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"oceanTideModel\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Name of applied Ocean tide loading model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"atmosphericTideModel\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Name of applied Atmospheric tide loading model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"geoidModel\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geoid model name for undulation values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"systemCode\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Terrestrial reference system code</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"remark\" type=\"string\" minOccurs=\"0\" default=\"TUG\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Remark used to identify the origin of the coordinates (AC acronym)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antennaCalibrationModel\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. IGS20_WWWW (WWWW = ANTEX release GPS week)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sinexTroHeader\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"agencyCode\" type=\"string\" minOccurs=\"0\" default=\"TUG\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Identify the agency providing the data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Start time of the data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>End time of the data </xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationCode\" type=\"string\" minOccurs=\"0\" default=\"P\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Technique used to generate the SINEX solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"solutionContents\" type=\"string\" minOccurs=\"0\" default=\"MIX\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Marker name if single station, MIX if multiple stations</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Organizitions gathering/alerting the file contents</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"output\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Description of the file contents</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"contact\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Address of the relevant contact e-mail</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"software\" type=\"string\" minOccurs=\"0\" default=\"GROOPS (https://github.com/groops-devs/groops)\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Software used to generate the file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"hardware\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Computer hardware on which above software was run</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"input\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Brief description of the input used to generate this solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"versionNumber\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Unique identifier of the product, same as in file name, e.g. 000</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileComment\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block from a file (truncated at 80 characters per line)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GoceXml2Gradiometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read ESA XML GOCE Data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGradiometer\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GoceXml2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read ESA XML GOCE Data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from TRF to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GoceXml2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read ESA XML GOCE Data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GoceXmlEggNom1b\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read ESA XML GOCE Data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGradiometer\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularRate\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularAcc\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Grace2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfilePotentialCoefficients\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variables: epochStart, epochEnd, epochMid</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceAccelerometer2L1bAscii\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAscii\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ASCII outputfile</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAccelerometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GROOPS acceleromter file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteIdentifier\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>satellite identifier (A or B for GRACE, C or D for GRACE-FO)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"globalAttributes\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional attributes as &apos;key: value&apos; pairs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceAod2DoodsonHarmonics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert AOD1B tides into DoodsonHarmonics.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonHarmonics\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" default=\"{groopsDataDir}/tides/generatingTide_HW95.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to compute Xi phase correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceAod2TimeSplines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>convert AOD1B dealiasing data into linear splines</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: TimeSplines</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDealiasing\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAtmosphere\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileOcean\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileBottomPressure\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileMisc\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceCoefficients2BlockMeanTimeSplines\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSplines\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSplinesCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only the variances are saved</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>mid points of non-empty intervals</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeIntervals\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>monthly interval boundaries from first to last solution</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1a2Accelerometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1A data (ACC1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER in SRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER in SRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACC1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1a2SatelliteTracking\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1A data (KBR1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTracking\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(ant_id, K_phase, Ka_phase, K_SNR, Ka_SNR)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>KBR1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1a2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1A data (SCA1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera1\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>STARCAMERA1A, head 1</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera2\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>STARCAMERA1A, head 2</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SCA1A, !GRACE-FO is not working!</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1a2Temperature\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1A data (HRT1B or HRT1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTemperature\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>HRT1B or HRT1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2AccHousekeeping\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (AHK1B or AHK1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccHousekeeping\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCHOUSEKEEPING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>AHK1B or AHK1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Accelerometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (ACC1B or ACT1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAngularAccelerometer\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACCELEROMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileFlags\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ACC1B or ACT1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2ClockOffset\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (CLK1B or LLK1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileClock\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>CLK1B or LLK1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2GnssReceiver\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (GPS1B or GPS1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGnssReceiver\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNSSRECEIVER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GPS1B or GPS1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Magnetometer\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (MAG1B or MAG1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMagnetometer\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MAGNETOMETER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MAG1B or MAG1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Mass\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (MAS1B or MAS1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMass\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MASS</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MAS1B or MAS1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE/GRACE-FO L1B data (GNV1B, GNI1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to rotate GNV1B into CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNV1B/GNI1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2SatelliteTracking\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (KBR1B or LRI1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTracking\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SATELLITETRACKING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntCentr\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SATELLITETRACKING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileLighttime\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SATELLITETRACKING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSNR\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileIonoCorr\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>KBR1B or LRI1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (SCA1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCameraFlags\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(sca_id, qual_rss, qualflg)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SCA1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2StarCameraCovariance\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Covariance matrix from star camera flags</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCameraCovariance\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCameraFlags\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSequenceOfEventsQSA\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"sigma0\" type=\"double\" minOccurs=\"0\" default=\"6\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds of arc]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2SteeringMirror\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (LSM1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>LSM1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Thruster\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (THR1B or THR1A)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileThruster\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>THRUSTER</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>THR1B or THR1A</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2TimeOffset\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (TIM1A or TIM1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTime\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"fractionalScale\" type=\"double\" default=\"1e-6\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>1e-6 for GRACE, 1e-9 for GRACE-FO</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>TIM1A or TIM1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Uso\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (USO1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileUso\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(uso_freq, K_freq, Ka_freq)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>USO1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceL1b2Vector\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE L1B data (VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Matrix</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVector\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GraceSequenceOfEvents\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GRACE SOE file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGraceA\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileGraceB\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" default=\"{groopsDataDir}/grace/TN-01_SOE.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SoE file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"events\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ACCT\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>DSHL HeaterDisconnect</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"mode\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"Heater\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>DSHL HeaterDisconnect</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"SetPoint\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>temperature set point</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"AOCS\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>coarse pointing mode or attitude hold mode</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"mode\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"CPM\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>coarse pointing mode</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"AHM\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>attitude hold mode</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"SM\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>science mode</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ACCR\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ACCR</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"CMCAL\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>CoM calibration maneuver</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] create events between start and end of maneuver</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"KBRCAL\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>KBR calibration maneuver</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"sampling\" type=\"double\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[seconds] create events between start and end of maneuver</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"VCM\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>CoM coordinates in SRF (m)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"VKB\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>KBR phase center coordinates in SRF (m)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"ICUVP\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>ICUVP</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"IPU\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>IPU</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"IPUR\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>IPUR</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"KAMI\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>KAMI: time tag offset to Ka-phase meas.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"KMI\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>K_MI: time tag offset to K-phase meas.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"KTOFF\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>KTOFF: time tag offset to KBR meas.</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"MANV\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>MANV</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"MTE1\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>MTE1</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"MTE2\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>MTE2</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"OCC\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>OCC</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"QSA\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>SCA to SRF frame rotation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"QKS\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>SCA to KBR frame rotation</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GrailCdr2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read CDR GRAIL data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GrailCdr2SatelliteTracking\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read CDR GRAIL data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteTracking\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileAntCentr\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileLighttime\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileTemperature\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"approximateTimeBias\" type=\"double\" minOccurs=\"0\" default=\"0.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[seconds]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GrailCdr2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read CDR GRAIL data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedData2NetCdf\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert gridded data to a netCDF file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNetCdf\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of NetCDF output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input grid sequence</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"dataVariable\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>metadata for data variables</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>netCDF variable name</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"expression\" minOccurs=\"0\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>expression (variables &apos;height&apos;, &apos;data&apos;, &apos;longitude&apos;, &apos;latitude&apos; and, &apos;area&apos; are taken from the gridded data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"attribute\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>netCDF attributes</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"text\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"globalAttribute\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional meta data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"text\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GriddedDataTimeSeries2NetCdf\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts a griddedDataTimeSeries file to a netCDF file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNetCdf\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of NetCDF output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGriddedDataTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>otherwise times from inputfile are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"dataVariable\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>metadata for data variables</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>netCDF variable name</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputColumn\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input data column</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"attribute\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>netCDF attributes</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"text\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"globalAttribute\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional meta data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"text\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GroopsAscii2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read Orbits given in groosp kinematic ASCII format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Hw2TideGeneratingPotential\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read tide generating potential from Hartmann and Wenzel 1995</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTideGeneratingPotential\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" default=\"hw95.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"headerLines\" type=\"uint\" minOccurs=\"0\" default=\"205\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>skip number of header lines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referenceTime\" type=\"time\" minOccurs=\"0\" default=\"51544.5\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Icgem2PotentialCoefficients\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read spherical harmonics in ICGEM format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStaticCoefficients\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>static potential coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTrendCoefficients\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>trend potential coefficients in GROOPS gfc format.  Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileOscillationCosine\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>oscillation cosine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileOscillationSine\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>oscillation sine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileIntervals\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>two column ASCII file with all intervals found (only sensible for icgem2.0). The base name will be extended with .static, .trend, .annualCos, and .annualSin.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileIcgem\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ICGEM GFC file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useFormalErrors\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use formal errors if both formal and calibrated errors are given</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Iers2OceanPoleTide\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read ocean pole tide model</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOceanPole\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileLoadingLoveNumber\" type=\"filename\" default=\"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"Omega\" type=\"double\" minOccurs=\"0\" default=\"7.292115e-05\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[rad/s] earth rotation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"rho\" type=\"double\" minOccurs=\"0\" default=\"1025\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[kg/m**3] density of sea water</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"G\" type=\"double\" minOccurs=\"0\" default=\"6.673e-11\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m**3/(kg*s**2)] gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"g\" type=\"double\" minOccurs=\"0\" default=\"9.7803278\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m/s**2] gravity</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"IersC04IAU2000EarthOrientationParameter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read Earth Orientation Parameter</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEOP\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"IersHighFrequentEop2DoodsonEop\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read Diurnal and Subdiurnal Earth Orientation variations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonEOP\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"IersPotential2DoodsonHarmonics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read ocean tide file in IERS format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonHarmoncis\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"headerLines\" type=\"uint\" default=\"4\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>skip number of header lines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"IersRapidIAU2000EarthOrientationParameter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read Earth Orientation Parameter</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEOP\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"IersWaterHeight2DoodsonHarmonics\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read ocean tide file in IERS format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: DoodsonHarmonics</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileDoodsonHarmoncis\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"headerLines\" type=\"uint\" default=\"3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>skip number of header lines</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTideGeneratingPotential\" type=\"filename\" default=\"{groopsDataDir}/tides/generatingTide_HW95.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to compute Xi phase correction</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"kernel\" type=\"kernelType\" default=\"waterHeight\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data type of input values</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"factor\" type=\"double\" minOccurs=\"0\" default=\"0.01\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>to convert in SI units</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Igs2EarthOrientationParameter\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Earth Orientation Parameter from IGS daily file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEOP\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Jason2Starcamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read Jason star camera data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"jasonNumber\" type=\"uint\" default=\"2\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Jason number (different file format), 1 for Sentinel</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"JplAscii2Ephemerides\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>JPL DExxx (ASCII) ephemerides</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileEphemerides\" type=\"filename\" default=\"JPL_DE432.dat\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileHeader\" type=\"filename\" default=\"header.432_571\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileData\" type=\"filename\" default=\"ascp01950.432\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Merit2FullRate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read SLR data (full-rate) from merit format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalPoints\" type=\"filename\" default=\"output/normalsPoints_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileMeteorological\" type=\"filename\" default=\"output/meteorological_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSlrData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SLR MERIT II file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Merit2NormalPoints\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Read SLR data (normal points) from merit format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalPoints\" type=\"filename\" default=\"output/normalsPoints_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileMeteorological\" type=\"filename\" default=\"output/meteorological_{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSlrData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SLR MERIT II file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NetCdf2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert COARDS compliant grids to gridded data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNetCdf\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"variableNameLongitude\" type=\"string\" default=\"lon\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameLatitude\" type=\"string\" default=\"lat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameTime\" type=\"string\" minOccurs=\"0\" default=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if with time axis: name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameData\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data variables, otherwise all suitable data are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>if with time axis: nearest epoch is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NetCdf2GriddedDataTimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert a NetCDF file to a GriddedDataTimeSeries file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grid</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedDataTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNetCdf\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"variableNameLongitude\" type=\"string\" default=\"lon\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameLatitude\" type=\"string\" default=\"lat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameTime\" type=\"string\" default=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameData\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data variables, otherwise all suitable data are used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NetCdfInfo\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Content information of a NetCDF file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"inputfileNetCdf\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NormalsSphericalHarmonics2Sinex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write potential coefficients and normal equations to SINEX format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSinex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>solutions in SINEX format</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileNormals\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normal equation matrix</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSigmax\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileApriori\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>apriori parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAprioriMatrix\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>normal equation matrix of applied constraints</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time for parameters</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"sinexHeader\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"agencyCode\" type=\"string\" minOccurs=\"0\" default=\"TUG\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>identify the agency providing the data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>start time of the data</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>end time of the data </xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"observationCode\" type=\"string\" minOccurs=\"0\" default=\"C\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>technique used to generate the SINEX solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"constraintCode\" type=\"string\" minOccurs=\"0\" default=\"2\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>0: tight constraint, 1: siginficant constraint, 2: unconstrained</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"solutionContent\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>solution types contained in the SINEX solution (S O E T C A)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>organizitions gathering/alerting the file contents</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"contact\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Address of the relevant contact. e-mail</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"output\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Description of the file contents</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"input\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Brief description of the input used to generate this solution</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"software\" type=\"string\" minOccurs=\"0\" default=\"GROOPS (https://github.com/groops-devs/groops)\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Software used to generate the file</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"hardware\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>Computer hardware on which above software was run</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileComment\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block from a file (truncated at 80 characters)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>comments in the comment block</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"OceanTidesDTU2GriddedData\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert DTU ocean tide grids to griddedData (amplitude, phase)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGriddedData\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>data0=amplitude, data1=phase</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.257\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2Cpf\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write orbit positions to CPF</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\" default=\"{target}_cpf_{fileDate}_{ephVerNum}{ver}.tug\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteInfo\" type=\"filename\" default=\"{groopsDataDir}/slr/satellite/satelliteInfo/satelliteInfo.{satellite}.xml\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Platform File</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"versionNumber\" type=\"uint\" minOccurs=\"0\" default=\"01\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Version number of production day with zero leading fill, e.g. 01</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"targetClass\" type=\"uint\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>set 1 for passive retroreflector, set 0 for no retroreflector (includes debris)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2GraceL1b\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>convert GROOPS L1B data to SDS data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GNV1B/GNI1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileHeader\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>YAML Header, {epochmin}, {epochmax}, {epochcount} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"satelliteId\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>A, B, C or D</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation into Earth fixed frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2GroopsAscii\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write orbit positions to TUG ASCII format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileCovariance\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"firstLine\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Text for first line</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Orbit2Sp3Format\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Write orbits (position, velocity, covariance) to SP3 format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"satellite\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileClock\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCovariance\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>3 characters (e.g. GNSS PRN: G01)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"orbitAccuracy\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] used for accuracy codes in header (0 = unknown)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotate data into Earth-fixed frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[{&quot;tides&quot;: {&quot;tides&quot;: {&quot;doodsonHarmonicTide&quot;: {&quot;minDegree&quot;:1, &quot;maxDegree&quot;:1}}}}]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>comment lines (77 char max)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"firstLine\" type=\"string\" minOccurs=\"0\" default=\"RAW   IGb14 FIT  TUG\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Text for first line e.g:  u+U  IGb14 KIN ITSG</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"writeVelocity\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>write velocity in addition to position</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useSp3kFormat\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>use the extended sp3k format</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PotentialCoefficients2Icgem\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>write spherical harmonics in ICGEM format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: PotentialCoefficients</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfilePotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTrend\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"oscillation\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileCosPotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileSinPotentialCoefficients\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"period\" type=\"string\" default=\"1.0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>period of oscillation [year]</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>comment in header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileComment\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file containing comments for header</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"modelname\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of the model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"tideSystem\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>tide system of model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zero_tide\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"tide_free\"/>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"minDegree\" type=\"uint\" minOccurs=\"0\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"maxDegree\" type=\"uint\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"GM\" type=\"double\" minOccurs=\"0\" default=\"3.986004415e+14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>Geocentric gravitational constant</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378136.3\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"PsmslOceanBottomPressure2TimeSeries\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read ocean bottom pressure (OBP) time series in the PSMSL file format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeSeries\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfilePosition\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>recorder position as gridded data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"isDaily\" type=\"boolean\" default=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"ignoreBadData\" type=\"boolean\" default=\"1\"/>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\"/>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\"/>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"RinexObservation2GnssReceiver\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts RINEX or Compact RINEX files to GROOPS GnssReceiver Instrument file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGnssReceiver\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileRinexObservation\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>RINEX or Compact RINEX observation files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileMatrixPrn2FrequencyNumber\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/transmitter/glonassPrnSvn2FrequencyNumber.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>(required for RINEX v2 files containing GLONASS observations), matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>used to determine semi-codeless receivers and to cross-check antenna and receiver info</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSemiCodelessReceivers\" type=\"filename\" minOccurs=\"0\" default=\"{groopsDataDir}/gnss/receiverStation/semiCodelessReceivers.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>list with one receiver name per line</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSpecialObservationTypes\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>table mapping special observation types to RINEX 3 types, e.g.: LA L1C</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"useType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only use observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"ignoreType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ignore observations that match any of these patterns</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sacc2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read SACC orbit data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SatelliteTracking2GraceL1b\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read GROOPS L1B data (KBR1B or LRI1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>KBR1B or LRI1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileHeader\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>YAML Header, {epochmin}, {epochmax}, {epochcount} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteTracking\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SATELLITETRACKING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileIonoCorr\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileLighttime\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SATELLITETRACKING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAntCentr\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SATELLITETRACKING</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSNR\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sentinel2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read Sentinel-1/2/3 star camera data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SentinelXml2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read XML Sentinel Data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sinex2Normals\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert SINEX to GROOPS normal equations.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: NormalEquation</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormals\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>N, n: unconstrained normal equations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileNormalsConstraint\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>N0, n0: normal equations of applied constraints</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolution\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>x: parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileSolutionApriori\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>x0: a priori parameter vector</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputFileSinex\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sinex2StationDiscontinuities\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert station discontinuities from SINEX (e.g. ITRF20) to InstrumentMiscValue.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop variable is replaced with station name (e.g. wtzz)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDiscontinuities\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX (e.g. ITRF20) station discontinuities</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopStation\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for station loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>only export these stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sinex2StationPositions\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert station positions from SINEX to InstrumentVector3d.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\" default=\"stationPosition.{station}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop variable is replaced with station name (e.g. wtzz)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopStation\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for station loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexSolution\" type=\"filename\" default=\"ITRF2020-IGS-TRF.SSC\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexDiscontinuities\" type=\"filename\" minOccurs=\"0\" default=\"ITRF2020-soln-gnss.snx\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexPostSeismicDeformations\" type=\"filename\" minOccurs=\"0\" default=\"ITRF2020-psd-gnss.snx\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexFrequencies\" type=\"filename\" minOccurs=\"0\" default=\"ITRF2020-Frequencies-XYZ-CF.snx\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file (XYZ or ENU)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute positions for these epochs based on velocity</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"extrapolateForward\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>also compute positions for epochs after last interval defined in SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"extrapolateBackward\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>also compute positions for epochs before first interval defined in SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>convert only these stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SinexEccentricties2SlrPlatform\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Platform file from SINEX eccentricties.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStationInfo\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop variable is replaced with station name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopStation\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for station loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file (.snx or .ssc)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>convert only these stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SinexMetadata2GlonassFrequencyNumber\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create glonassPrnSvn2FrequencyNumber matrix from IGS SINEX metadata file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileMatrixPrn2FrequencyNumber\" type=\"filename\" default=\"{groopsDataDir}/gnss/transmitter/glonassPrnSvn2FrequencyNumber.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>GROOPS matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexMetadata\" type=\"filename\" default=\"igs_satellite_metadata.snx\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>IGS SINEX metadata file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SinexMetadata2SatelliteModel\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Create satellite model from IGS SINEX metadata file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Gnss</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileSatelliteModel\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinexMetadata\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>IGS SINEX metadata file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteModel\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>base satellite model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"svn\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. G040, R736, E204, C211</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SlrComModel2RangeBiasStationSatellite\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read CoM model</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileRangeBias\" type=\"filename\" default=\"rangeBias.{station}.{satellite}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE, variable {station} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteInfo\" type=\"filename\" default=\"{groopsDataDir}/slr/satellites/satelliteInfo/satelliteInfo.{satellite}.xml\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" default=\"com/com_&lt;aji|et1|la2|las|lg1|lg2|str&gt;.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>from Rodriguez model</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopStation\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for station loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>convert only these stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"SlrSinexDataHandling2Files\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Convert SLR SINEX data handling file</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Slr</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileRangeBiasStation\" type=\"filename\" minOccurs=\"0\" default=\"rangeBias.{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileRangeBiasStationSatellite\" type=\"filename\" minOccurs=\"0\" default=\"rangeBias.{station}.{satellite}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUE [m]</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"outputfileTimeBias\" type=\"filename\" minOccurs=\"0\" default=\"timeBias.{station}.txt\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(bias [s], drift [s/d])</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopStation\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for station loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopSatellite\" type=\"string\" minOccurs=\"0\" default=\"satellite\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for satellite loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinex\" type=\"filename\" default=\"ILRS_Data_Handling_File.snx\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file (.snx)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSatelliteId\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>table SP3 and satellite name</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>convert only these stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sp3Format2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read orbits from SP3 format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Covariance</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileClock\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"outputfileCovariance\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>3x3 epoch covariance</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteIdentifier\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. L09 for GRACE A, empty: take first satellite, &lt;all&gt;: identifier is appended to each file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation from TRF to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"gravityfield\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\" default=\"[{&quot;tides&quot;: {&quot;tides&quot;: {&quot;doodsonHarmonicTide&quot;: {&quot;minDegree&quot;:1, &quot;maxDegree&quot;:1}}}}]\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbits in SP3 format</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"StarCamera2GraceL1b\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>convert GROOPS L1B data to SDS data (SCA1B)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Grace</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfile\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SCA1B</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileHeader\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>YAML Header, {epochmin}, {epochmax}, {epochcount} available</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>STARCAMERA</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileStarCameraFlags\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>MISCVALUES(sca_id, qual_rss, qualflg)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteId\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>A, B, C or D</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"StarCamera2Orbex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>Converts satellite attitude from StarCamera to ORBEX format.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ORBEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satellite\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"inputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"identifier\" type=\"string\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>string identifier (e.g. GNSS PRN: G01)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\" minOccurs=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>e.g. BLOCK IIR-B, GRACE</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotate data into Earth-fixed frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>resample to these epochs (otherwise input file epochs are used)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for attitude and Earth rotation interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of file contents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"createdBy\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of agency</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputData\" type=\"string\" default=\"p\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of input data (see ORBEX description)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"contact\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>email address</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referenceFrame\" type=\"string\" default=\"IGS20\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference frame used in file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Swarm2Starcamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read SWARM star camera data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"TerraSarTandem2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read TerraSar-X or Tandem-X orbits from the special CHORB format</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Orbit</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>orbits in CHORB format</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"TerraSarTandem2StarCamera\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>read TerraSar-X or Tandem-X star camera data</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStarCamera\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Tle2Orbit\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>orbit from Two Line Elements (TLE/3LE)</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t\t<xs:appinfo>tag: Instrument</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbit\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileTLE\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>two line elements (TLE/3LE)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"satelliteName\" type=\"string\" minOccurs=\"0\" default=\"*\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>first name of wildcard match is used</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output orbit at these times</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotation to CRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ViennaMappingFunctionGrid2File\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>converts VMF grid time series to one file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVmfCoefficients\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfile\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>files must be given for each point in time</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>times of input files</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaLambda\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[deg] sampling in longitude</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"deltaPhi\" type=\"angle\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[deg] sampling in latitude</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"isCellRegistered\" type=\"boolean\" minOccurs=\"0\" default=\"1\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>grid points represent cells (VMF3), not grid corners (VMF1)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"ViennaMappingFunctionStation2File\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>converts VMF station time series to one file.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Conversion</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileVmfCoefficients\" type=\"filename\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStationInfo\" type=\"filename\" default=\"{groopsDataDir}/gnss/receiverStation/stationInfo/igs/stationInfo.{station}.xml\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileStation\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileVmf\" type=\"filename\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssAttitude2Orbex\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2024-11-30. Please use StarCamera2Orbex instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileOrbex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ORBEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileTransmitterList\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ASCII list with transmitter PRNs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileAttitude\" type=\"filename\" default=\"attitude.{prn}.dat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>instrument file containing attitude</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variablePrn\" type=\"string\" minOccurs=\"0\" default=\"prn\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop variable for PRNs from transmitter list</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>resample to these epochs (otherwise input file epochs are used)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"earthRotation\" type=\"earthRotationType\" minOccurs=\"0\" default=\"file\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>rotate data into Earth-fixed frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"interpolationDegree\" type=\"uint\" default=\"7\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>for attitude and Earth rotation interpolation</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"description\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of file contents</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"createdBy\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of agency</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputData\" type=\"string\" default=\"p\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>description of input data (see ORBEX description)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"contact\" type=\"string\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>email address</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referenceFrame\" type=\"string\" default=\"IGb14\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference frame used in file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssPrn2SvnBlockVariables\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2024-02-12. This program no longer works! See documentation for help.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GnssStationInfoCreate\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2024-12-02. Please use PlatformCreate instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileStationInfo\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"markerName\" type=\"string\"/>\n\t\t\t\t\t\t<xs:element name=\"markerNumber\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t<xs:element name=\"approxPositionX\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] in TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"approxPositionY\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] in TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"approxPositionZ\" type=\"double\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>[m] in TRF</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"antenna\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"radome\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"positionX\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] ARP in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"positionY\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] ARP in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"positionZ\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] ARP in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationX\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to left-handed antenna system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationY\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to left-handed antenna system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"rotationZ\" type=\"angle\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[degree] from local/vehicle to left-handed antenna system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"flipX\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip x-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"flipY\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip y-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"flipZ\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>flip z-axis (after rotation)</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"receiver\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"serial\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"version\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"referencePoint\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>e.g. center of mass in satellite frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"comment\" type=\"string\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"xStart\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"yStart\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>linear motion between start and end</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zStart\" type=\"double\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"xEnd\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>[m] in north, east, up or vehicle system</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"yEnd\" type=\"double\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>linear motion between start and end</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"zEnd\" type=\"double\" default=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeStart\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"timeEnd\" type=\"time\" minOccurs=\"0\"/>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"GridRectangular2NetCdf\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2023-07-06. Please use GriddedData2NetCdf or GriddedDataTimeSeries2NetCdf instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileNetCdf\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>file name of NetCDF output</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileGridRectangular\" type=\"filename\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>input grid sequence</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"times\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>values for time axis (COARDS specification)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"dataVariable\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>metadata for data variables</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"selectDataField\" type=\"uint\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>input data column</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\" default=\"data0\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>netCDF variable name</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"attribute\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t\t\t\t<xs:documentation>netCDF attributes</xs:documentation>\n\t\t\t\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"text\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"globalAttribute\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>additional meta data</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"text\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t<xs:element name=\"value\">\n\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"name\" type=\"string\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"value\" type=\"double\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"dataType\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"double\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"float\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<xs:element name=\"int\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t\t\t</xs:choice>\n\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"NetCdf2GridRectangular\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2023-07-06. Please use NetCdf2GriddedData or NetCdf2GriddedDataTimeSeries instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileGridRectangular\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>One grid for each epoch in the NetCDF file is written. Use loopTimeVariable as template.</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"loopTimeVariable\" type=\"string\" default=\"loopTime\"/>\n\t\t\t\t\t\t<xs:element name=\"inputfileNetCdf\" type=\"filename\"/>\n\t\t\t\t\t\t<xs:element name=\"variableNameLongitude\" type=\"string\" default=\"lon\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameLatitude\" type=\"string\" default=\"lat\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameTime\" type=\"string\" minOccurs=\"0\" default=\"time\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable (leave blank for static grids)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableNameData\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>name of NetCDF variable</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"R\" type=\"double\" minOccurs=\"0\" default=\"6378137.0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference radius for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inverseFlattening\" type=\"double\" minOccurs=\"0\" default=\"298.2572221010\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>reference flattening for ellipsoidal coordinates</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sinex2StationPosition\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>loop variable is replaced with station name (e.g. wtzz)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>SINEX file (.snx or .ssc)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileDiscontinuities\" type=\"filename\" minOccurs=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>discontinuities file per station; loop variable is replaced with station name (e.g. wtzz)</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"variableLoopStation\" type=\"string\" minOccurs=\"0\" default=\"station\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>variable name for station loop</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>convert only these stations</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute positions for these epochs based on velocity</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"extrapolateForward\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>also compute positions for epochs after last interval defined in SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"extrapolateBackward\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>also compute positions for epochs before first interval defined in SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t\t<xs:element name=\"Sinex2StationPostSeismicDeformation\">\n\t\t\t\t<xs:annotation>\n\t\t\t\t\t<xs:documentation>DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.</xs:documentation>\n\t\t\t\t\t<xs:appinfo>tag: Deprecated</xs:appinfo>\n\t\t\t\t</xs:annotation>\n\t\t\t\t<xs:complexType>\n\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t<xs:element name=\"outputfileInstrument\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>deformation time series</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"inputfileSinex\" type=\"filename\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>ITRF post-seismic deformation SINEX file</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"timeSeries\" type=\"timeSeriesType\" maxOccurs=\"unbounded\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>compute deformation for these epochs</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t<xs:element name=\"stationName\" type=\"string\"/>\n\t\t\t\t\t\t<xs:element name=\"localLevelFrame\" type=\"boolean\" minOccurs=\"0\" default=\"0\">\n\t\t\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t\t\t<xs:documentation>output in North, East, Up local-level frame</xs:documentation>\n\t\t\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t</xs:sequence>\n\t\t\t\t</xs:complexType>\n\t\t\t</xs:element>\n\t\t</xs:choice>\n\t</xs:complexType>\n\t<xs:element name=\"groops\">\n\t\t<xs:annotation>\n\t\t\t<xs:documentation>GROOPS (Gravity Recovery Object Oriented Programming System)</xs:documentation>\n\t\t\t<xs:appinfo>rename: programme = program</xs:appinfo>\n\t\t</xs:annotation>\n\t\t<xs:complexType>\n\t\t\t<xs:sequence>\n\t\t\t\t<xs:element name=\"global\">\n\t\t\t\t\t<xs:annotation>\n\t\t\t\t\t\t<xs:documentation>global settings</xs:documentation>\n\t\t\t\t\t\t<xs:appinfo>rename: normalequationType = normalEquationType</xs:appinfo>\n\t\t\t\t\t\t<xs:appinfo>rename: gnssAntennaRepresentationType = parametrizationGnssAntennaType</xs:appinfo>\n\t\t\t\t\t\t<xs:appinfo>rename: parameterSatelliteType = parametrizationAccelerationType</xs:appinfo>\n\t\t\t\t\t\t<xs:appinfo>rename: representationType = parametrizationGravityType</xs:appinfo>\n\t\t\t\t\t\t<xs:appinfo>rename: parameterSatelliteTrackingType = parametrizationSatelliteTrackingType</xs:appinfo>\n\t\t\t\t\t\t<xs:appinfo>rename: temporalRepresentationType = parametrizationTemporalType</xs:appinfo>\n\t\t\t\t\t</xs:annotation>\n\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t<xs:element name=\"int\" type=\"int\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"uint\" type=\"uint\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"double\" type=\"double\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"angle\" type=\"angle\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"boolean\" type=\"boolean\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"time\" type=\"time\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"doodson\" type=\"doodson\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"string\" type=\"string\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"filename\" type=\"filename\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"expression\" type=\"expression\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gnssType\" type=\"gnssType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"autoregressiveModelSequenceType\" type=\"autoregressiveModelSequenceType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"borderType\" type=\"borderType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"conditionType\" type=\"conditionType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"covariancePodType\" type=\"covariancePodType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"covarianceSstType\" type=\"covarianceSstType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"digitalFilterType\" type=\"digitalFilterType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"earthRotationType\" type=\"earthRotationType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"eclipseType\" type=\"eclipseType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"ephemeridesType\" type=\"ephemeridesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"forcesType\" type=\"forcesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gnssAntennaDefintionListType\" type=\"gnssAntennaDefintionListType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gnssParametrizationType\" type=\"gnssParametrizationType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gnssProcessingStepType\" type=\"gnssProcessingStepType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gnssReceiverGeneratorType\" type=\"gnssReceiverGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gnssTransmitterGeneratorType\" type=\"gnssTransmitterGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gravityfieldType\" type=\"gravityfieldType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"gridType\" type=\"gridType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"instrumentTypeType\" type=\"instrumentTypeType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"interpolatorTimeSeriesType\" type=\"interpolatorTimeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"kernelType\" type=\"kernelType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"loopType\" type=\"loopType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"magnetosphereType\" type=\"magnetosphereType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"matrixGeneratorType\" type=\"matrixGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"miscAccelerationsType\" type=\"miscAccelerationsType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"noiseGeneratorType\" type=\"noiseGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"normalEquationType\" type=\"normalEquationType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"observationType\" type=\"observationType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"orbitPropagatorType\" type=\"orbitPropagatorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parameterNamesType\" type=\"parameterNamesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parameterSelectorType\" type=\"parameterSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parametrizationAccelerationType\" type=\"parametrizationAccelerationType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parametrizationGnssAntennaType\" type=\"parametrizationGnssAntennaType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parametrizationGravityType\" type=\"parametrizationGravityType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parametrizationSatelliteTrackingType\" type=\"parametrizationSatelliteTrackingType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"parametrizationTemporalType\" type=\"parametrizationTemporalType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"planetType\" type=\"planetType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"platformSelectorType\" type=\"platformSelectorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotAxisType\" type=\"plotAxisType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotColorType\" type=\"plotColorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotColorbarType\" type=\"plotColorbarType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotGraphLayerType\" type=\"plotGraphLayerType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotLegendType\" type=\"plotLegendType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotLineType\" type=\"plotLineType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotMapLayerType\" type=\"plotMapLayerType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotMapProjectionType\" type=\"plotMapProjectionType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"plotSymbolType\" type=\"plotSymbolType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"podRightSideType\" type=\"podRightSideType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"sggRightSideType\" type=\"sggRightSideType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"slrParametrizationType\" type=\"slrParametrizationType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"slrProcessingStepType\" type=\"slrProcessingStepType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"slrSatelliteGeneratorType\" type=\"slrSatelliteGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"slrStationGeneratorType\" type=\"slrStationGeneratorType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"sphericalHarmonicsFilterType\" type=\"sphericalHarmonicsFilterType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"sphericalHarmonicsNumberingType\" type=\"sphericalHarmonicsNumberingType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"sstRightSideType\" type=\"sstRightSideType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"thermosphereType\" type=\"thermosphereType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"tidesType\" type=\"tidesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"timeSeriesType\" type=\"timeSeriesType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t\t<xs:element name=\"troposphereType\" type=\"troposphereType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t</xs:complexType>\n\t\t\t\t</xs:element>\n\t\t\t\t<xs:element name=\"program\" type=\"programType\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n\t\t\t</xs:sequence>\n\t\t</xs:complexType>\n\t</xs:element>\n</xs:schema>\n"
  },
  {
    "path": "gui/.gitignore",
    "content": "# dynamic content\n# ---------------\n/build\ngroopsGui.pro.user*\nMakefile\n.qmake.stash\n"
  },
  {
    "path": "gui/addVariableDialog/addVariableDialog.cpp",
    "content": "/***********************************************/\n/**\n* @file addVariableDialog.cpp\n*\n* @brief Dialog to add variables.\n*\n* @author Sebastian Strasser\n* @date 2016-10-17\n*/\n/***********************************************/\n\n#include <QPushButton>\n#include <QScreen>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"addVariableDialog.h\"\n#include \"ui_addVariableDialog.h\"\n\n/***********************************************/\n\nAddVariableDialog::AddVariableDialog(Tree *tree, const QString &type, const QString &label, bool disablePlace, bool disableCreateLink, QWidget *parent)\n  : QDialog(parent), sourceType(type), disableCreateLink(disableCreateLink), ui(new Ui::AddVariableDialog)\n{\n  try\n  {\n    ui->setupUi(this);\n\n    QSize screenSize = QGuiApplication::primaryScreen()->size();\n    setMinimumSize(screenSize.width()/5, screenSize.height()/10);\n    resize(minimumSizeHint());\n\n    // fill combo box with types\n    for(auto xsdElement : tree->xsdElements())\n      ui->comboBoxType->addItem(xsdElement->type);\n    if(ui->comboBoxType->count() < 1)\n      throw(Exception(\"no global element types found in schema\"));\n    ui->comboBoxType->setCurrentText(type);\n\n    bool fromTemplate = !label.isEmpty() && (ui->comboBoxType->currentText() == type);\n\n    if(fromTemplate)\n      ui->lineEditName->setText(label);\n    // only allow variable names with letters and numbers\n    QRegularExpressionValidator *validator = new QRegularExpressionValidator(QRegularExpression(\"[a-zA-Z]([a-zA-Z0-9])*\"), this);\n    ui->lineEditName->setValidator(validator);\n\n\n    ui->radioButtonGlobal->setEnabled(!disablePlace);\n    ui->radioButtonLocal->setEnabled(!disablePlace);\n\n    ui->checkBoxCreateLink->setEnabled(!disableCreateLink && fromTemplate);\n    ui->checkBoxCreateLink->setChecked(!disableCreateLink && fromTemplate);\n\n    // disable Ok button if line edit is empty\n    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!this->label().isEmpty());\n\n    ui->lineEditName->setFocus();\n\n    // signal-slot connections\n    connect(ui->lineEditName, SIGNAL(textEdited(const QString &)), this, SLOT(nameEdited(const QString &)));\n    connect(ui->comboBoxType, SIGNAL(currentIndexChanged(int)),    this, SLOT(typeChanged(int)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nAddVariableDialog::~AddVariableDialog()\n{\n  delete ui;\n}\n\n/***********************************************/\n\nvoid AddVariableDialog::nameEdited(const QString &label)\n{\n  try\n  {\n    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!label.isEmpty());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n\n/***********************************************/\n\nvoid AddVariableDialog::typeChanged(int /*index*/)\n{\n  try\n  {\n    if(ui->comboBoxType->currentText() == sourceType)\n      ui->checkBoxCreateLink->setEnabled(!disableCreateLink);\n    else\n    {\n      ui->checkBoxCreateLink->setEnabled(false);\n      ui->checkBoxCreateLink->setChecked(false);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n\n/***********************************************/\n\nQString AddVariableDialog::label() const\n{\n  return ui->lineEditName->text();\n}\n\n/***********************************************/\n\nQString AddVariableDialog::type() const\n{\n  return ui->comboBoxType->currentText();\n}\n\n/***********************************************/\n\nBool AddVariableDialog::inGlobal() const\n{\n  return ui->radioButtonGlobal->isEnabled() && ui->radioButtonGlobal->isChecked();\n}\n\n/***********************************************/\n\nBool AddVariableDialog::setLink() const\n{\n  return ui->checkBoxCreateLink->isChecked();\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "gui/addVariableDialog/addVariableDialog.h",
    "content": "/***********************************************/\n/**\n* @file addVariableDialog.h\n*\n* @brief Dialog to add variables.\n*\n* @author Sebastian Strasser\n* @date 2016-10-17\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__ADDVARIABLELDIALOG__\n#define __GROOPSGUI__ADDVARIABLELDIALOG__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementGlobal.h\"\n#include <QDialog>\n#include <QRegularExpression>\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class AddVariableDialog;\n}\n\nclass Tree;\nclass TreeElement;\nclass TreeElementGlobal;\n\n/***** CLASS ***********************************/\n\nclass AddVariableDialog : public QDialog\n{\n  Q_OBJECT\n\n  QString sourceType;\n  bool    disableCreateLink;\n\npublic:\n  AddVariableDialog(Tree *tree, const QString &type, const QString &label, bool disablePlace, bool disableCreateLink, QWidget *parent=nullptr);\n ~AddVariableDialog();\n\n  QString type()     const;\n  QString label()    const;\n  Bool    inGlobal() const;\n  Bool    setLink()  const;\n\nprivate slots:\n  void nameEdited(const QString &label);\n  void typeChanged(int index);\n\nprivate:\n  Ui::AddVariableDialog *ui;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/addVariableDialog/addVariableDialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>AddVariableDialog</class>\n <widget class=\"QDialog\" name=\"AddVariableDialog\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>400</width>\n    <height>172</height>\n   </rect>\n  </property>\n  <property name=\"sizePolicy\">\n   <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Fixed\">\n    <horstretch>0</horstretch>\n    <verstretch>0</verstretch>\n   </sizepolicy>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>400</width>\n    <height>160</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Add variable - GROOPS</string>\n  </property>\n  <layout class=\"QGridLayout\" name=\"gridLayout_2\">\n   <item row=\"4\" column=\"0\">\n    <widget class=\"QDialogButtonBox\" name=\"buttonBox\">\n     <property name=\"orientation\">\n      <enum>Qt::Horizontal</enum>\n     </property>\n     <property name=\"standardButtons\">\n      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>\n     </property>\n    </widget>\n   </item>\n   <item row=\"0\" column=\"0\">\n    <layout class=\"QGridLayout\" name=\"gridLayout\">\n     <item row=\"1\" column=\"0\">\n      <widget class=\"QLabel\" name=\"labelType\">\n       <property name=\"text\">\n        <string>Type</string>\n       </property>\n      </widget>\n     </item>\n     <item row=\"0\" column=\"4\">\n      <widget class=\"QLineEdit\" name=\"lineEditName\">\n       <property name=\"sizePolicy\">\n        <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Fixed\">\n         <horstretch>0</horstretch>\n         <verstretch>0</verstretch>\n        </sizepolicy>\n       </property>\n      </widget>\n     </item>\n     <item row=\"2\" column=\"0\">\n      <widget class=\"QLabel\" name=\"labelPlace\">\n       <property name=\"text\">\n        <string>Place</string>\n       </property>\n      </widget>\n     </item>\n     <item row=\"1\" column=\"4\">\n      <widget class=\"QComboBox\" name=\"comboBoxType\">\n       <property name=\"sizePolicy\">\n        <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Fixed\">\n         <horstretch>0</horstretch>\n         <verstretch>0</verstretch>\n        </sizepolicy>\n       </property>\n       <property name=\"maxVisibleItems\">\n        <number>20</number>\n       </property>\n      </widget>\n     </item>\n     <item row=\"2\" column=\"4\">\n      <layout class=\"QHBoxLayout\" name=\"horizontalLayout\">\n       <item>\n        <widget class=\"QRadioButton\" name=\"radioButtonGlobal\">\n         <property name=\"text\">\n          <string>global section</string>\n         </property>\n         <property name=\"checked\">\n          <bool>true</bool>\n         </property>\n        </widget>\n       </item>\n       <item>\n        <widget class=\"QRadioButton\" name=\"radioButtonLocal\">\n         <property name=\"text\">\n          <string>local</string>\n         </property>\n         <property name=\"checked\">\n          <bool>false</bool>\n         </property>\n        </widget>\n       </item>\n       <item>\n        <spacer name=\"horizontalSpacer\">\n         <property name=\"orientation\">\n          <enum>Qt::Horizontal</enum>\n         </property>\n         <property name=\"sizeHint\" stdset=\"0\">\n          <size>\n           <width>40</width>\n           <height>20</height>\n          </size>\n         </property>\n        </spacer>\n       </item>\n      </layout>\n     </item>\n     <item row=\"0\" column=\"0\">\n      <widget class=\"QLabel\" name=\"labelName\">\n       <property name=\"text\">\n        <string>Name</string>\n       </property>\n      </widget>\n     </item>\n     <item row=\"3\" column=\"4\">\n      <widget class=\"QCheckBox\" name=\"checkBoxCreateLink\">\n       <property name=\"text\">\n        <string>create link</string>\n       </property>\n       <property name=\"checked\">\n        <bool>true</bool>\n       </property>\n      </widget>\n     </item>\n    </layout>\n   </item>\n  </layout>\n </widget>\n <resources/>\n <connections>\n  <connection>\n   <sender>buttonBox</sender>\n   <signal>accepted()</signal>\n   <receiver>AddVariableDialog</receiver>\n   <slot>accept()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>248</x>\n     <y>254</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>157</x>\n     <y>274</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonBox</sender>\n   <signal>rejected()</signal>\n   <receiver>AddVariableDialog</receiver>\n   <slot>reject()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>316</x>\n     <y>260</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>286</x>\n     <y>274</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n</ui>\n"
  },
  {
    "path": "gui/base/importGroops.h",
    "content": "/***********************************************/\n/**\n* @file importGroops.h\n*\n* @brief Imports basic headers from GROOPS.\n*\n* @author Sebastian Strasser\n* @date 2020-02-05\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__IMPORTGROOPS__\n#define __GROOPSGUI__IMPORTGROOPS__\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/time.h\"\n#include \"parser/expressionParser.h\"\n#include \"parser/stringParser.h\"\n\n#endif /* __GROOPSGUI__IMPORTGROOPS__ */\n"
  },
  {
    "path": "gui/base/schema.cpp",
    "content": "/***********************************************/\n/**\n* @file schema.cpp\n*\n* @brief XSD (XML schema) tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include <QTextStream>\n#include <QFile>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n#include \"schema.h\"\n\n/***********************************************/\n\nXsdElementPtr XsdComplex::getXsdElement(QString name) const\n{\n  try\n  {\n    auto iter = std::find_if(elements.begin(), elements.end(), [&](XsdElementPtr element) {return element->names.contains(name);});\n    if(iter == elements.end())\n      return nullptr;\n    return *iter;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool Schema::readFile(QString fileName)\n{\n  try\n  {\n    complexType.clear();\n    rootElement = nullptr;\n    if(fileName.isEmpty())\n      return false;\n\n    QFile file(fileName);\n    if(!file.open(QFile::ReadOnly | QFile::Text))\n      return false;\n    QString errorMessage;\n    XmlNodePtr xmlNode = XmlNode::read(&file, errorMessage);\n    if(!xmlNode)\n      return false;\n\n    // read ComplexTypes\n    UInt count = xmlNode->getChildCount(QString(\"xs:complexType\"));\n    for(UInt i=0; i<count; i++)\n      complexType.push_back(readElement(xmlNode->getChild(QString(\"xs:complexType\")), {}, true));\n    // read elements\n    rootElement = readElement(xmlNode->getChild(QString(\"xs:element\")), {}, false);\n\n    setComplexPointer(rootElement); // set recursively pointer to the complex types\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    complexType.clear();\n    rootElement = nullptr;\n    return false;\n  }\n}\n\n/***********************************************/\n\nXsdElementPtr Schema::readElement(XmlNodePtr xmlNode, const std::map<QString, QString> &renames, bool isComplexType)\n{\n  try\n  {\n    if(!xmlNode)\n      throw(Exception(\"xs:element is null\"));\n\n    XsdElementPtr element(new XsdElement());\n    element->complex = nullptr;\n\n    // read name\n    XmlAttrPtr attr = xmlNode->getAttribute(\"name\");\n    if(!attr)\n      throw(Exception(\"xs:element without name\"));\n    element->names = QStringList(attr->text);\n    // renames\n    auto findRename = [&](const QString name){return std::find_if(renames.begin(), renames.end(), [&](auto pair){return pair.second == name;});};\n    auto iterRenames = findRename(element->names.back());\n    while(iterRenames != renames.end())\n    {\n      element->names.push_back(iterRenames->first);\n      iterRenames = findRename(element->names.back());\n    }\n\n    // annotation, tags, and renames\n    std::map<QString, QString> childRenames;\n    XmlNodePtr child = xmlNode->getChild(\"xs:annotation\");\n    if(child)\n    {\n      XmlNodePtr doc = child->getChild(\"xs:documentation\");\n      if(doc)\n        element->annotation = doc->getText();\n\n      for(XmlNodePtr info = child->getChild(\"xs:appinfo\"); info; info = child->getChild(\"xs:appinfo\"))\n      {\n        if(info->getText().startsWith(\"rename:\")) // format: \"rename: oldName = newName\"\n        {\n          QStringList splits = info->getText().split(\" \", Qt::SkipEmptyParts);\n          childRenames[splits[1]] = splits[3];\n        }\n        else if(info->getText().startsWith(\"tag:\"))\n          element->tags.append(info->getText().split(\" \", Qt::SkipEmptyParts)[1]);\n      }\n    }\n\n    // attributes\n    QString minOccurs, maxOccurs;\n    readAttribute (xmlNode, \"type\",      element->type);\n    readAttribute (xmlNode, \"default\",   element->defaultValue);\n    readAttribute (xmlNode, \"minOccurs\", minOccurs);\n    readAttribute (xmlNode, \"maxOccurs\", maxOccurs);\n    element->optional  = (minOccurs == \"0\");\n    element->unbounded = (maxOccurs == \"unbounded\");\n\n    XmlNodePtr xmlNode2;\n    if(isComplexType)\n      xmlNode2 = xmlNode;\n    else\n      xmlNode2 = xmlNode->getChild(\"xs:complexType\");\n    if(xmlNode2)\n    {\n      element->complex = readComplex(xmlNode2, childRenames);\n      if(element->type.isEmpty()) // create unique identifier\n      {\n        QTextStream ss(&element->type);\n        ss<<element->complex->type<<\"Start-\";\n        for(auto child : element->complex->elements)\n          ss<<child->type<<\"-\";\n        ss<<element->complex->type<<\"End\";\n      }\n    }\n\n    return element;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXsdComplexPtr Schema::readComplex(XmlNodePtr xmlNode, const std::map<QString, QString> &renames)\n{\n  try\n  {\n    XsdComplexPtr complex(new XsdComplex());\n    complex->isReady = false;\n\n    complex->type = \"sequence\";\n    XmlNodePtr xmlNode2 = xmlNode->getChild(\"xs:sequence\");\n    if(!xmlNode2)\n    {\n      xmlNode2 = xmlNode->getChild(\"xs:choice\");\n      complex->type = \"choice\";\n    }\n    if(!xmlNode2)\n      throw(Exception(\"xs:complex must contain xs:sequence or xs:choice\"));\n\n     // read children\n    UInt count = xmlNode2->getChildCount(\"xs:element\");\n    if(!count)\n      throw(Exception(\"xs:sequence/xs::choice must contain xs:element\"));\n    complex->elements.resize(count);\n    for(UInt i=0; i<count; i++)\n      complex->elements.at(i) = readElement(xmlNode2->getChild(\"xs:element\"), renames, false);\n\n    return complex;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Schema::setComplexPointer(XsdElementPtr element)\n{\n  try\n  {\n    if(!element->complex)\n    {\n      auto iter = std::find_if(complexType.begin(), complexType.end(), [&](const auto &child) {return child->names.front() == element->type;});\n      if(iter != complexType.end())\n        element->complex = (*iter)->complex;\n    }\n\n    if((element->complex) && (!element->complex->isReady))\n    {\n      element->complex->isReady = true;\n      for(auto &child : element->complex->elements)\n        setComplexPointer(child);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "gui/base/schema.h",
    "content": "/***********************************************/\n/**\n* @file schema.h\n*\n* @brief XSD (XML schema) tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__SCHEMA__\n#define __GROOPSGUI__SCHEMA__\n\n#include <QStringList>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n\n/***** TYPES ***********************************/\n\nclass   XsdElement;\nclass   XsdComplex;\ntypedef std::shared_ptr<XsdElement> XsdElementPtr;\ntypedef std::shared_ptr<XsdComplex> XsdComplexPtr;\n\n/***** CLASS ***********************************/\n\nclass XsdElement\n{\npublic:\n  XsdElement() : optional(true), unbounded(false), complex(nullptr) {}\n\n  QStringList   names; // with possible renames\n  QString       type;\n  QString       annotation;\n  QString       defaultValue;\n  QStringList   tags;\n  bool          optional;\n  bool          unbounded;\n  XsdComplexPtr complex;\n};\n\n/***** CLASS ***********************************/\n\nclass XsdComplex\n{\npublic:\n  XsdComplex() : isReady(false) {}\n\n  QString                    type;    // \"choice\" or \"sequence\"\n  std::vector<XsdElementPtr> elements;\n  bool                       isReady; // internal: complex pointer is set for all children?\n\n  /** @brief Return type for @p name from schema considering renames, or nullptr if not found. */\n  XsdElementPtr getXsdElement(QString name) const;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief XSD (XML schema) tree. */\nclass Schema\n{\n  XsdElementPtr readElement(XmlNodePtr xmlNode, const std::map<QString, QString> &renames, bool isComplexType);\n  XsdComplexPtr readComplex(XmlNodePtr xmlNode, const std::map<QString, QString> &renames);\n  void          setComplexPointer(XsdElementPtr element);\n\npublic:\n  std::vector<XsdElementPtr> complexType;\n  XsdElementPtr rootElement;\n\n  /** @brief reads a GROOPS XML schema.\n  * @return is a valid GROOPS XML schema. */\n  bool readFile(QString fileName);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/base/xml.cpp",
    "content": "/***********************************************/\n/**\n* @file xml.cpp\n*\n* @brief Nodes of an XML tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2004-11-14\n*/\n/***********************************************/\n\n#include <QDebug>\n#include <QString>\n#include <QTextStream>\n#include <QXmlStreamReader>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n\n/***********************************************/\n\nUInt XmlNode::getChildCount(const QStringList &names)\n{\n  return std::count_if(children.begin(), children.end(), [&names](auto child) {return names.contains(child->getName());});\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::getChild(const QStringList &names)\n{\n  auto iter = std::find_if(children.begin(), children.end(), [&names](auto child) {return names.contains(child->getName());});\n  if(iter == children.end())\n    return XmlNodePtr();\n  XmlNodePtr ptr = *iter;\n  children.erase(iter);\n  return ptr;\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::getNextChild()\n{\n  XmlNodePtr ptr(nullptr);\n  if(!children.empty())\n  {\n    ptr = children.front();\n    children.pop_front();\n  }\n  return ptr;\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::peekNextChild()\n{\n  if(!children.empty())\n    return children.front();\n  return nullptr;\n}\n\n/***********************************************/\n\nXmlAttrPtr XmlNode::getAttribute(const QString &name)\n{\n  auto iter = std::find_if(attribute.begin(), attribute.end(), [&name](auto attr) {return attr->name == name;});\n  if(iter == attribute.end())\n    return XmlAttrPtr();\n  XmlAttrPtr ptr = *iter;\n  attribute.erase(iter);\n  return ptr;\n}\n\n/***********************************************/\n\nXmlAttrPtr XmlNode::findAttribute(const QString &name)\n{\n  auto iter = std::find_if(attribute.begin(), attribute.end(), [&name](auto attr) {return attr->name == name;});\n  if(iter == attribute.end())\n    return XmlAttrPtr();\n  return *iter;\n}\n\n/***********************************************/\n/***********************************************/\n\nXmlNodePtr XmlNode::parse(QXmlStreamReader &reader, QString &errorMessage)\n{\n  try\n  {\n    // header\n    auto type = reader.readNext();\n    if(type != QXmlStreamReader::StartDocument)\n    {\n      errorMessage = \"XML header expected\";\n      return nullptr;\n    }\n\n    XmlNodePtr             root;\n    std::stack<XmlNodePtr> stack;\n    for(;;)\n    {\n      auto type = reader.readNext();\n      if(type == QXmlStreamReader::EndDocument)\n        break;\n\n      if(type == QXmlStreamReader::Invalid)\n      {\n        errorMessage = QString(\"XML parser error (row=%1, col=%2):\\n%3\").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString());\n        return nullptr;\n      }\n\n      if(type == QXmlStreamReader::Comment)\n      {\n        XmlNodePtr xmlNode = XmlNode::create(\"COMMENT\");\n        xmlNode->text += reader.text().toString();\n        if(!stack.empty())\n          stack.top()->addChild(xmlNode);\n      }\n\n      if(type == QXmlStreamReader::StartElement)\n      {\n        XmlNodePtr xmlNode = XmlNode::create(reader.qualifiedName().toString());\n        if(stack.empty())\n          root = xmlNode;\n\n        for(auto &attribute : reader.attributes())\n        {\n          XmlAttrPtr attr(new XmlAttribute());\n          attr->name = attribute.name().toString();\n          attr->text = attribute.value().toString();\n          xmlNode->addAttribute(attr);\n        }\n\n        if(!stack.empty())\n          stack.top()->addChild(xmlNode);\n        stack.push(xmlNode);\n      } // if(StartElement)\n\n      if(type == QXmlStreamReader::Characters)\n      {\n        if(!reader.isWhitespace())\n          stack.top()->text += reader.text().toString();\n      }\n\n      if(type == QXmlStreamReader::EndElement)\n      {\n        XmlNodePtr xmlNode = stack.top();\n        if(xmlNode->name != reader.qualifiedName().toString())\n        {\n          errorMessage = QString(\"XML parser error: (row=%1, col=%2):\\nunexpected end element\").arg(reader.lineNumber()).arg(reader.columnNumber());\n          return nullptr;\n        }\n        stack.pop();\n      }  // if(EndElement)\n    } // for(;;)\n\n    return root;\n  }\n  catch(std::exception &e)\n  {\n    errorMessage = QString(\"XML parser error: critical error\");\n    return nullptr;\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::read(const QByteArray &data, QString &errorMessage)\n{\n  QXmlStreamReader reader(data);\n  return parse(reader, errorMessage);\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::read(QIODevice *device, QString &errorMessage)\n{\n  QXmlStreamReader reader(device);\n  return parse(reader, errorMessage);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid XmlNode::writeFile(const QString &fileName, const XmlNodePtr &root)\n{\n  try\n  {\n    QFile file(fileName);\n    if(file.open(QFile::WriteOnly | QFile::Truncate))\n    {\n      QTextStream stream(&file);\n      write(stream, root, false);\n    }\n    else\n      throw(Exception(\"cannot open file\"));\n  }\n  catch(std::exception &e)\n  {\n    throw(Exception(_GROOPS_ERRORLINE+\" filename='\"+fileName.toStdString()+\"'\\n\"+e.what()));\n  }\n}\n\n/***********************************************/\n\nvoid XmlNode::write(QTextStream &stream, const XmlNodePtr &root, bool writeCommentsAsElements)\n{\n  try\n  {\n    stream<<\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" ?>\\n\";\n    root->write(stream, 0, writeCommentsAsElements);\n  }\n  catch(std::exception &e)\n  {\n    throw(Exception(std::string(\"In XmlNode::write:\\n\")+e.what()));\n  }\n}\n\n/***********************************************/\n\nvoid XmlNode::write(QTextStream &stream, UInt depth, bool writeCommentsAsElements)\n{\n  auto sanitizeXML = [](const QString &in)\n  {\n    if(in.isEmpty())\n      return QString();\n    std::vector<QString> chars = {\"&\", \">\", \"<\", \"\\\"\", \"'\"};\n    std::vector<QString> replacements = {\"&amp;\", \"&gt;\", \"&lt;\", \"&quot;\", \"&apos;\"};\n    QString out(in);\n    for(UInt k=0; k<chars.size(); k++)\n      out = out.replace(chars.at(k), replacements.at(k));\n    return out;\n  };\n\n  // special node -> translate to XML comment\n  if(!writeCommentsAsElements && (getName() == \"COMMENT\"))\n  {\n    stream<<QString(depth, '\\t')<<\"<!--\"<<sanitizeXML(getText())<<\"-->\\n\";\n    return;\n  }\n\n  // start tag\n  stream<<QString(depth, '\\t')<<\"<\"<<getName();\n\n  // attribute\n  for(auto attr : attribute)\n    stream<<\" \"<<attr->name<<\"=\\\"\"<<sanitizeXML(attr->text)<<\"\\\"\";\n\n  // short form?\n  if(getText().isEmpty() && children.empty())\n  {\n    stream<<\"/>\\n\";\n    return;\n  }\n  stream<<\">\"<<sanitizeXML(getText());\n\n  // children\n  if(!children.empty())\n  {\n    stream<<\"\\n\";\n    for(auto child : children)\n      child->write(stream, depth+1, writeCommentsAsElements);\n    stream<<QString(depth, '\\t');\n  }\n\n  // end tag\n  stream<<\"</\"<<getName()<<\">\\n\";\n}\n\n/***********************************************/\n/***********************************************/\n\nXmlAttrPtr readAttribute(const XmlNodePtr &node, const QString &name, QString &var)\n{\n  try\n  {\n    XmlAttrPtr attr = node->getAttribute(name);\n    if(attr)\n      var = attr->text;\n    return attr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXmlAttrPtr writeAttribute(const XmlNodePtr &node, const QString &name, const QString &var)\n{\n  XmlAttrPtr attr = XmlAttrPtr(new XmlAttribute(name, var));\n  node->addAttribute(attr);\n  return attr;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/base/xml.h",
    "content": "/***********************************************/\n/**\n* @file xml.h\n*\n* @brief Nodes of an XML tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2004-11-14\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__XML__\n#define __GROOPSGUI__XML__\n\n#include <QString>\n#include <QStringList>\n#include <QFile>\n#include <sstream>\n#include \"base/importGroops.h\"\n\n/***** TYPES ***********************************/\n\nclass   QXmlStreamReader;\nclass   QTextStream;\nclass   XmlAttribute;\nclass   XmlNode;\ntypedef std::shared_ptr<XmlNode>      XmlNodePtr;\ntypedef std::shared_ptr<XmlAttribute> XmlAttrPtr;\n\n/***** CLASS ***********************************/\n\n/**\n* @brief Attribues of an XML node.\n* @see XmlNode\n*/\nclass XmlAttribute\n{\npublic:\n  /** @brief Name of the attribute. */\n  QString name;\n\n  /** @brief Content/text of the attribute. */\n  QString text;\n\n  XmlAttribute() {}\n  XmlAttribute(QString _name, QString _text) : name(_name), text(_text) {}\n};\n\n/***** CLASS ***********************************/\n\n/**\n* @brief Node of an XML tree.\n*\n* A node can only have one(!) text part that comes before any children.\n* Nodes are removed from the node tree while reading, so each node can only be read once.\n* Memory is managed via std::shared_prt, so it does not have to be freed manually.\n*/\nclass XmlNode\n{\n  QString           name;\n  QString           text;\n  std::list<XmlNodePtr> children;\n  std::list<XmlAttrPtr> attribute;\n\n  static XmlNodePtr parse(QXmlStreamReader &reader, QString &errorMessage);\n  void write(QTextStream &stream, UInt depth, bool writeCommentsAsElements);\n\npublic:\n  XmlNode(const QString &name) {this->name = name;}\n  XmlNode(const XmlNode &node) = delete;\n  XmlNode &operator=(const XmlNode &node) = delete;\n\n  /** @brief Returns the name of the node. */\n  const QString &getName() const {return name;}\n\n  /** @brief Sets the name of the node. */\n  void setName(const QString &name) {this->name = name;}\n\n  /** @brief Returns the text/content of the node. */\n  const QString &getText() const {return text;}\n\n  /** @brief Sets the text/content of the node. */\n  void setText(const QString &text) {this->text = text;}\n\n  /** @brief Returns TRUE of node has children, FALSE otherwise. */\n  bool hasChildren() const {return !children.empty();}\n\n  /** @brief Returns number of children with name @p name.  */\n  UInt getChildCount(const QStringList &names);\n  UInt getChildCount(const QString &name) {return getChildCount(QStringList(name));}\n\n  /** @brief Returns the first child with name @p name.\n  * The child is removed from the node tree.\n  * Returns a nullptr if child does not exist.  */\n  XmlNodePtr getChild(const QStringList &names);\n  XmlNodePtr getChild(const QString &name) {return getChild(QStringList({name}));}\n\n  /** @brief Adds a child to the node.\n  * A node must not be added to the node tree multiple times. */\n  void addChild(const XmlNodePtr &child, bool front=false) {if(front) children.push_front(child); else children.push_back(child);}\n\n  /** @brief Returns the next child.\n  * The child is removed from the node tree.\n  * Returns a nullptr if child does not exist. */\n  XmlNodePtr getNextChild();\n\n  /** @brief Returns the next child.\n  * Returns a nullptr if child does not exist. */\n  XmlNodePtr peekNextChild();\n\n  /** @brief Returns the attribute with name @p name.\n  * Returns a nullptr if attribute does not exist. */\n  XmlAttrPtr getAttribute(const QString &name);\n\n  /** @brief Returns the attribute with name @p name.\n  * Returns a nullptr if attribute does not exist. */\n  XmlAttrPtr findAttribute(const QString &name);\n\n  /** @brief Adds a new attribute to the node. */\n  void addAttribute(const XmlAttrPtr &attr) {if(attr) attribute.push_back(attr);}\n\n  /** @brief Creates a new node with name @p name. */\n  static XmlNodePtr create(const QString &name) {return std::make_shared<XmlNode>(name);}\n\n  /** @brief Reads an XML tree from stream.\n  * @param name File name.\n  * @return Root of the XML tree. */\n  static XmlNodePtr read(const QByteArray &data, QString &errorMessage);\n\n  /** @brief Reads an XML tree from stream.\n  * @param name File name.\n  * @return Root of the XML tree. */\n  static XmlNodePtr read(QIODevice *device, QString &errorMessage);\n\n  /** Writes an XML tree into a @p stream.\n  * @param stream Output stream.\n  * @param root Root of the XML tree. */\n  static void write(QTextStream &stream, const XmlNodePtr &root, bool writeCommentsAsElements=false);\n\n  /** Writes an XML tree into a file.\n  * @param name File name.\n  * @param root Root of the XML tree. */\n  static void writeFile(const QString &name, const XmlNodePtr &root);\n};\n\n/***** FUNCTIONS ***********************************/\n\nXmlAttrPtr readAttribute (const XmlNodePtr &node, const QString &name, QString &var);\nXmlAttrPtr writeAttribute(const XmlNodePtr &node, const QString &name, const QString &var);\n\n/***********************************************/\n\n#endif /* __GROOPSGUI__XML__ */\n"
  },
  {
    "path": "gui/executeDialog/executeDialog.cpp",
    "content": "/***********************************************/\n/**\n* @file executeDialog.cpp\n*\n* @brief Execute dialog.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-13\n*\n*/\n/***********************************************/\n\n#include \"ui_executeDialog.h\"\n#include <QFileDialog>\n#include <QSettings>\n#include <QList>\n#include <QCheckBox>\n#include <QScreen>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"settingsDialog/settingsCommandDialog.h\"\n#include \"executeDialog.h\"\n\n/***********************************************/\n\nExecuteDialog::ExecuteDialog(Tree *tree, QWidget *parent)\n  : QDialog(parent), ui(new Ui::ExecuteDialog)\n{\n  try\n  {\n    ui->setupUi(this);\n    this->tree = tree;\n\n    // restore size of window\n    // ----------------------\n    setMinimumSize(QGuiApplication::primaryScreen()->size()/4);\n    QRect parentRect(parentWidget()->mapToGlobal(QPoint(0, 0)), parentWidget()->size());\n    resize(settings.value(\"executeDialog/size\", minimumSizeHint()).toSize());\n    move(settings.value(\"executeDialog/position\", QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), parentRect).topLeft()).toPoint());\n\n    // init table\n    // ----------\n    QStringList headerLable;\n    ui->tableWidget->setHeaderLabels(headerLable << \"Program\" << \"Comment\");\n    ui->tableWidget->setColumnWidth(0, settings.value(\"executeDialog/columnWidth\", 350).toInt());\n    ui->tableWidget->setAlternatingRowColors(true);\n    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);\n\n    // set rectangular icon size\n    // -------------------------\n    QCheckBox *checkBox = new QCheckBox(this);\n    int height = checkBox->sizeHint().height();\n    ui->tableWidget->setIconSize(QSize(2*height, height));\n    delete checkBox;\n\n    // fill list\n    // ---------\n    addChildren(ui->tableWidget->invisibleRootItem(), tree->rootElement);\n\n    QStringList labelList, commandList;\n    SettingsCommandDialog::readCommandList(labelList, commandList);\n\n    ui->comboBoxCommand->addItems( labelList );\n    ui->comboBoxCommand->setCurrentIndex( settings.value(\"execute/commandIndex\", int(0)).toInt() );\n    ui->checkBoxLogFile->setChecked( settings.value(\"execute/useLogFile\", bool(false)).toBool() );\n    ui->editorLogfile->setText( settings.value(\"execute/logFile\", QString(\"groops.log\")).toString() );\n    ui->editorLogfile->setEnabled( ui->checkBoxLogFile->isChecked() );\n    ui->buttonBrowseLogfile->setEnabled( ui->checkBoxLogFile->isChecked() );\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nExecuteDialog::~ExecuteDialog()\n{\n  delete ui;\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::editCommand()\n{\n  try\n  {\n    settings.setValue(\"execute/commandIndex\", ui->comboBoxCommand->currentIndex());\n\n    SettingsCommandDialog dialog(this);\n    dialog.exec();\n\n    ui->comboBoxCommand->clear();\n    ui->comboBoxCommand->addItems( settings.value(\"execute/commandLabels\").toStringList() );\n    ui->comboBoxCommand->setCurrentIndex( settings.value(\"execute/commandIndex\", int(0)).toInt() );\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::toggleLogfile()\n{\n  try\n  {\n    ui->editorLogfile->setEnabled( ui->checkBoxLogFile->isChecked() );\n    ui->buttonBrowseLogfile->setEnabled( ui->checkBoxLogFile->isChecked() );\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::browseLogfile()\n{\n  try\n  {\n    QString name = tree->addWorkingDirectory(ui->editorLogfile->text());\n    name = QFileDialog::getSaveFileName(this, tr(\"Choose logfile - GROOPS\"),\n                                        name, \"\", nullptr, QFileDialog::DontConfirmOverwrite);\n    if(!name.isEmpty())\n      ui->editorLogfile->setText(tree->stripWorkingDirectory(name));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::clickedAll()\n{\n  try\n  {\n    for(int i=0; i<itemList.size(); i++)\n      if(!itemList[i]->parent()) // only top level items\n        itemList[i]->setCheckState(0, Qt::Checked);\n    ui->tableWidget->update();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/*******************************************************************************/\n\nvoid ExecuteDialog::clickedNone()\n{\n  try\n  {\n    for(int i=0; i<itemList.size(); i++)\n      if(!itemList[i]->parent()) // only top level items\n        itemList[i]->setCheckState(0, Qt::Unchecked);\n    ui->tableWidget->update();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::clickedApply()\n{\n  try\n  {\n    for(int i=0; i<programList.size(); i++)\n      programList[i]->setDisabled( (itemList[i]->checkState(0)==Qt::Unchecked) );\n    tree->fileSave();\n\n    settings.setValue(\"execute/useLogFile\",   ui->checkBoxLogFile->isChecked());\n    settings.setValue(\"execute/logFile\",      ui->editorLogfile->text());\n    settings.setValue(\"execute/commandIndex\", ui->comboBoxCommand->currentIndex());\n\n    settings.setValue(\"executeDialog/position\",    pos());\n    settings.setValue(\"executeDialog/size\",        size());\n    settings.setValue(\"executeDialog/columnWidth\", ui->tableWidget->columnWidth(0));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::clickedStdBox(QAbstractButton *button)\n{\n  try\n  {\n    switch(ui->stdButtonBox->standardButton(button))\n    {\n      case QDialogButtonBox::Ok:\n        clickedApply();\n        accept();\n        break;\n      case QDialogButtonBox::Apply:\n        clickedApply();\n        break;\n      case QDialogButtonBox::Cancel:\n        reject();\n        break;\n      default:\n        qWarning(\"Unknown button clicked\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::changeEvent(QEvent *e)\n{\n  QDialog::changeEvent(e);\n  switch(e->type())\n  {\n    case QEvent::LanguageChange:\n      ui->retranslateUi(this);\n      break;\n    default:\n      break;\n  }\n}\n\n/***********************************************/\n\nvoid ExecuteDialog::addChildren(QTreeWidgetItem *parentItem, TreeElement *parentElement)\n{\n  try\n  {\n    TreeElementComplex *parent = dynamic_cast<TreeElementComplex*>(parentElement);\n\n    for(auto &element : parent->children())\n      if(dynamic_cast<TreeElementProgram*>(element))\n      {\n        QTreeWidgetItem *item = new QTreeWidgetItem();\n        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);\n        item->setIcon(0, QIcon(\":/icons/scalable/program.svg\"));\n        item->setText(0, element->selectedValue());\n        item->setText(1, element->comment());\n        item->setCheckState(0, (element->disabled()) ? Qt::Unchecked : Qt::Checked);\n        itemList.push_back(item);\n        programList.push_back(element);\n        parentItem->addChild(item);\n\n        // recursively add children\n        addChildren(item, element);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/executeDialog/executeDialog.h",
    "content": "/***********************************************/\n/**\n* @file executeDialog.h\n*\n* @brief Execute dialog.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-13\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__EXECUTEDIALOG__\n#define __GROOPSGUI__EXECUTEDIALOG__\n\n#include <QDialog>\n#include <QList>\n#include <QSettings>\n#include \"base/importGroops.h\"\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class ExecuteDialog;\n}\n\nclass QTreeWidgetItem;\nclass QAbstractButton;\nclass Tree;\nclass TreeElement;\n\n/***** CLASS ***********************************/\n\nclass ExecuteDialog : public QDialog\n{\n  Q_OBJECT\n\n  Ui::ExecuteDialog      *ui;\n  QSettings               settings;\n  Tree                   *tree;\n  QList<TreeElement*>     programList;\n  QList<QTreeWidgetItem*> itemList;\n\npublic:\n  ExecuteDialog(Tree *tree, QWidget *parent=nullptr);\n ~ExecuteDialog();\n\npublic slots:\n  void editCommand();\n  void toggleLogfile();\n  void browseLogfile();\n  void clickedAll();\n  void clickedNone();\n  void clickedApply();\n  void clickedStdBox(QAbstractButton *button);\n\nprotected:\n  void changeEvent(QEvent *e);\n\nprivate:\n  void addChildren(QTreeWidgetItem *parentItem, TreeElement *parentElement);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/executeDialog/executeDialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>ExecuteDialog</class>\n <widget class=\"QDialog\" name=\"ExecuteDialog\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>700</width>\n    <height>300</height>\n   </rect>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>500</width>\n    <height>300</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Execute - GROOPS</string>\n  </property>\n  <property name=\"sizeGripEnabled\">\n   <bool>true</bool>\n  </property>\n  <layout class=\"QVBoxLayout\" name=\"verticalLayout\" stretch=\"0,0,0\">\n   <item>\n    <widget class=\"QTreeWidget\" name=\"tableWidget\">\n     <column>\n      <property name=\"text\">\n       <string notr=\"true\">1</string>\n      </property>\n     </column>\n    </widget>\n   </item>\n   <item>\n    <widget class=\"QGroupBox\" name=\"groupBox\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Fixed\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"title\">\n      <string/>\n     </property>\n     <layout class=\"QGridLayout\" name=\"gridLayout\" columnstretch=\"0,1,0,0\">\n      <item row=\"0\" column=\"0\">\n       <widget class=\"QLabel\" name=\"label\">\n        <property name=\"text\">\n         <string>Command line:</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"1\">\n       <widget class=\"QComboBox\" name=\"comboBoxCommand\">\n        <property name=\"sizePolicy\">\n         <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Fixed\">\n          <horstretch>0</horstretch>\n          <verstretch>0</verstretch>\n         </sizepolicy>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"3\">\n       <widget class=\"QPushButton\" name=\"buttonEditCommand\">\n        <property name=\"icon\">\n         <iconset resource=\"../resources/icons.qrc\">\n          <normaloff>:/icons/scalable/settings.svg</normaloff>:/icons/scalable/settings.svg</iconset>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"0\">\n       <widget class=\"QCheckBox\" name=\"checkBoxLogFile\">\n        <property name=\"text\">\n         <string>Use &amp;logfile</string>\n        </property>\n        <property name=\"checked\">\n         <bool>true</bool>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"1\" colspan=\"2\">\n       <widget class=\"QLineEdit\" name=\"editorLogfile\">\n        <property name=\"text\">\n         <string>groops.log</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"3\">\n       <widget class=\"QPushButton\" name=\"buttonBrowseLogfile\">\n        <property name=\"icon\">\n         <iconset resource=\"../resources/icons.qrc\">\n          <normaloff>:/icons/scalable/document-open.svg</normaloff>:/icons/scalable/document-open.svg</iconset>\n        </property>\n       </widget>\n      </item>\n     </layout>\n    </widget>\n   </item>\n   <item>\n    <layout class=\"QHBoxLayout\" name=\"horizontalLayout\">\n     <item>\n      <widget class=\"QPushButton\" name=\"buttonAll\">\n       <property name=\"text\">\n        <string>&amp;All</string>\n       </property>\n      </widget>\n     </item>\n     <item>\n      <widget class=\"QPushButton\" name=\"buttonNone\">\n       <property name=\"text\">\n        <string>&amp;None</string>\n       </property>\n      </widget>\n     </item>\n     <item>\n      <spacer name=\"horizontalSpacer\">\n       <property name=\"orientation\">\n        <enum>Qt::Horizontal</enum>\n       </property>\n       <property name=\"sizeHint\" stdset=\"0\">\n        <size>\n         <width>0</width>\n         <height>0</height>\n        </size>\n       </property>\n      </spacer>\n     </item>\n     <item>\n      <widget class=\"QDialogButtonBox\" name=\"stdButtonBox\">\n       <property name=\"orientation\">\n        <enum>Qt::Horizontal</enum>\n       </property>\n       <property name=\"standardButtons\">\n        <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>\n       </property>\n      </widget>\n     </item>\n    </layout>\n   </item>\n  </layout>\n </widget>\n <resources>\n  <include location=\"../resources/icons.qrc\"/>\n </resources>\n <connections>\n  <connection>\n   <sender>stdButtonBox</sender>\n   <signal>clicked(QAbstractButton*)</signal>\n   <receiver>ExecuteDialog</receiver>\n   <slot>clickedStdBox(QAbstractButton*)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonAll</sender>\n   <signal>clicked()</signal>\n   <receiver>ExecuteDialog</receiver>\n   <slot>clickedAll()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonNone</sender>\n   <signal>clicked()</signal>\n   <receiver>ExecuteDialog</receiver>\n   <slot>clickedNone()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonEditCommand</sender>\n   <signal>clicked()</signal>\n   <receiver>ExecuteDialog</receiver>\n   <slot>editCommand()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>checkBoxLogFile</sender>\n   <signal>toggled(bool)</signal>\n   <receiver>ExecuteDialog</receiver>\n   <slot>toggleLogfile()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonBrowseLogfile</sender>\n   <signal>clicked()</signal>\n   <receiver>ExecuteDialog</receiver>\n   <slot>browseLogfile()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n <slots>\n  <slot>clickedStdBox(QAbstractButton*)</slot>\n  <slot>clickedAll()</slot>\n  <slot>clickedNone()</slot>\n  <slot>toggleLogfile()</slot>\n  <slot>browseLogfile()</slot>\n  <slot>editCommand()</slot>\n </slots>\n</ui>\n"
  },
  {
    "path": "gui/findReplaceDock/findReplaceDock.cpp",
    "content": "/***********************************************/\n/**\n* @file findReplaceDock.cpp\n*\n* @brief Find/replace dock.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2013-10-30\n*/\n/***********************************************/\n\n#include <QtWidgets>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeItem.h\"\n#include \"mainWindow/mainWindow.h\"\n#include \"findReplaceDock.h\"\n#include \"ui_findReplaceDock.h\"\n\n/***********************************************/\n\nFindReplaceDock::FindReplaceDock(MainWindow *parent) : QDockWidget(parent), ui(new Ui::FindReplaceDock)\n{\n  try\n  {\n    mainWindow = parent;\n    ui->setupUi(this);\n    ui->labelMessage->setText(\"\");\n\n    resize(settings.value(\"findReplaceDock/size\", size()).toSize());\n\n    connect(ui->editFind, SIGNAL(textEdited(const QString &)), this, SLOT(editFindTextChanged(const QString &)));\n    connect(ui->checkBoxSearchType, &QCheckBox::stateChanged, this, &FindReplaceDock::searchTypeChanged);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nFindReplaceDock::~FindReplaceDock()\n{\n  settings.setValue(\"findReplaceDock/size\", size());\n  delete ui;\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::setFocusOnFind()\n{\n  try\n  {\n    ui->editFind->selectAll();\n    ui->editFind->setFocus();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::setFindText(QString text)\n{\n  try\n  {\n    ui->editFind->setText(text);\n    editFindTextChanged(text);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nQString FindReplaceDock::getFindText() const\n{\n  try\n  {\n    return ui->editFind->text();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n\n/***********************************************/\n/***********************************************/\n\nvoid FindReplaceDock::editFindTextChanged(const QString &text)\n{\n  try\n  {\n    bool enable = !text.isEmpty();\n    bool searchType = ui->checkBoxSearchType->isChecked();\n    ui->buttonNext->setEnabled(enable);\n    ui->buttonPrevious->setEnabled(enable);\n    ui->buttonReplace->setEnabled(enable && !searchType);\n    ui->buttonReplaceAll->setEnabled(enable && !searchType);\n    ui->labelMessage->setText(\"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::searchTypeChanged()\n{\n  try\n  {\n    bool enable = !ui->editFind->text().isEmpty();\n    bool searchType = ui->checkBoxSearchType->isChecked();\n    ui->editReplace->setEnabled(!searchType);\n    ui->buttonReplace->setEnabled(enable && !searchType);\n    ui->buttonReplaceAll->setEnabled(enable && !searchType);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n\n/***********************************************/\n/***********************************************/\n\nvoid FindReplaceDock::clickedNext()\n{\n  findNext(TRUE/*forwards*/);\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::clickedPrevious()\n{\n  findNext(FALSE/*forwards*/);\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::clickedReplace()\n{\n  try\n  {\n    Tree *tree = mainWindow->getCurrentTree();\n    if(!tree)\n      return;\n    TreeItem *treeItem = tree->selectedItem();\n    int start, length;\n    treeItem->selection(start, length);\n    QString text = treeItem->treeElement()->selectedValue();\n    if((start >= 0) && (length > 0) && (getExpression().match(text.mid(start, length)).capturedLength() == length))\n    {\n      text.replace(start, length, ui->editReplace->text());\n      if(text == treeItem->treeElement()->selectedValue()) // no change?\n        return;\n      treeItem->treeElement()->changeSelectedValue(text);\n      treeItem->setSelection(start, 0);\n    }\n    clickedNext();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::clickedReplaceAll()\n{\n  try\n  {\n    QRegularExpression regExp = getExpression();\n    QString replaceStr = ui->editReplace->text();\n\n    Tree *tree = mainWindow->getCurrentTree();\n    if(!tree)\n      return;\n\n    int count = 0;\n    for(QTreeWidgetItemIterator itemIter(tree->rootElement->item(), QTreeWidgetItemIterator::All); *itemIter; itemIter++)\n    {\n      TreeElement *treeElement = dynamic_cast<TreeItem*>(*itemIter)->treeElement();\n      if(treeElement->isEditable())\n      {\n        QString text = treeElement->selectedValue();\n        text.replace(regExp, replaceStr);\n        if(text != treeElement->selectedValue()) // change?\n        {\n          treeElement->changeSelectedValue(text);\n          count++;\n        }\n      }\n    }\n\n    if(count)\n      ui->labelMessage->setText(QString(\"%1 matches replaced.\").arg(count));\n    else\n      messageNotFound();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::findNext(bool forwards)\n{\n  try\n  {\n    QRegularExpression regExp = getExpression();\n    bool searchType = ui->checkBoxSearchType->isChecked();\n\n    Tree *tree = mainWindow->getCurrentTree();\n    if(!tree)\n      return;\n    TreeItem *treeItemStart = tree->selectedItem();\n    if(!treeItemStart)\n      treeItemStart = tree->rootElement->item();\n\n    QTreeWidgetItemIterator itemIter(treeItemStart, QTreeWidgetItemIterator::All);\n    if(searchType)\n      (forwards) ? itemIter++ : itemIter--; // start with next item to prevent lock\n\n    bool wrap = false;\n    for(;;)\n    {\n      if(!*itemIter) // last element? -> wrap search\n      {\n        if(wrap) // only once\n          break;\n        wrap = true;\n        if(forwards)\n          itemIter = QTreeWidgetItemIterator(tree->rootElement->item(), QTreeWidgetItemIterator::All);\n        else // find last item\n          for(QTreeWidgetItemIterator i(treeItemStart, QTreeWidgetItemIterator::All); *i; i++)\n            itemIter = i;\n      }\n\n      TreeItem *treeItem = dynamic_cast<TreeItem*>(*itemIter);\n      if(treeItem && treeItem->treeElement())\n      {\n        auto treeElement = treeItem->treeElement();\n        if(searchType)\n        {\n          if(regExp.match(treeElement->name(), 0).hasMatch())\n          {\n            tree->setSelectedItem(treeItem);\n            return;\n          }\n        } // search value\n        else if(treeElement->isEditable() && !treeElement->isLinked() && treeElement->selectedValue().size())\n        {\n          int start, length, startMatch = -1;\n          treeItem->selection(start, length);\n          QRegularExpressionMatch match;\n          if(forwards)\n            startMatch = treeElement->selectedValue().indexOf(regExp, std::max(start, 0)+length, &match);\n          else if(start != 0)\n            startMatch = treeElement->selectedValue().lastIndexOf(regExp, ((start>0) ? start : treeElement->selectedValue().size())-1, &match);\n          if(startMatch >= 0)\n          {\n            tree->setSelectedItem(treeItem);\n            treeItem->setSelection(startMatch, match.capturedLength());\n            ui->labelMessage->setText(\"\");\n            return;\n          }\n        } // if(searchValue)\n      } // if(treeItem)\n\n      // next item\n      (forwards) ? itemIter++ : itemIter--;\n    } // for(;;)\n\n    messageNotFound();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid FindReplaceDock::messageNotFound()\n{\n  ui->labelMessage->setText(QString(\"No matches found.\"));\n  QApplication::beep();\n}\n\n/***********************************************/\n\nQRegularExpression FindReplaceDock::getExpression()\n{\n  try\n  {\n    QString pattern = ui->editFind->text();\n    if(!ui->checkBoxRegExp->checkState())\n      pattern.replace(QRegularExpression(R\"(([\\.\\*\\?\\+\\/\\^\\$\\|\\(\\)\\[\\]\\{\\}\\\\]))\"), R\"(\\\\1)\");\n    QRegularExpression regExp(pattern);\n    if(ui->checkBoxMatchCase->checkState())\n      regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);\n    return regExp;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid FindReplaceDock::closeEvent(QCloseEvent *e)\n{\n  try\n  {\n    hide();\n    e->ignore();\n    //e->accept();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid FindReplaceDock::changeEvent(QEvent *e)\n{\n  QDockWidget::changeEvent(e);\n  switch(e->type())\n  {\n    case QEvent::LanguageChange:\n      ui->retranslateUi(this);\n      break;\n    default:\n      break;\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/findReplaceDock/findReplaceDock.h",
    "content": "/***********************************************/\n/**\n* @file findReplaceDock.h\n*\n* @brief Find/replace dock.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2013-10-30\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__FINDREPLACEDOCK__\n#define __GROOPSGUI__FINDREPLACEDOCK__\n\n#include <QDockWidget>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElementComplex.h\"\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class FindReplaceDock;\n}\n\nclass MainWindow;\n\n/***** CLASS ***********************************/\n\nclass FindReplaceDock : public QDockWidget\n{\n  Q_OBJECT\n\n  Ui::FindReplaceDock *ui;\n  MainWindow          *mainWindow;\n  Tree                *tree;\n  QSettings            settings;\n\n  void    messageNotFound();\n  QRegularExpression getExpression();\n  void    findNext(bool forwards);\n\npublic:\n  FindReplaceDock(MainWindow *parent);\n ~FindReplaceDock();\n\n  void setFocusOnFind();\n  void setFindText(QString text);\n  QString getFindText() const;\n\npublic slots:\n  void clickedNext();\n  void clickedPrevious();\n  void clickedReplace();\n  void clickedReplaceAll();\n  void editFindTextChanged(const QString &text);\n  void searchTypeChanged();\n\nprotected:\n  void closeEvent(QCloseEvent *e);\n  void changeEvent(QEvent *e);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/findReplaceDock/findReplaceDock.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>FindReplaceDock</class>\n <widget class=\"QDockWidget\" name=\"FindReplaceDock\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>429</width>\n    <height>110</height>\n   </rect>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Find/Replace</string>\n  </property>\n  <widget class=\"QWidget\" name=\"gridLayoutWidget\">\n   <layout class=\"QVBoxLayout\" name=\"verticalLayout\">\n    <property name=\"spacing\">\n     <number>6</number>\n    </property>\n    <property name=\"topMargin\">\n     <number>6</number>\n    </property>\n    <property name=\"bottomMargin\">\n     <number>6</number>\n    </property>\n    <item>\n     <layout class=\"QGridLayout\" name=\"gridLayout\">\n      <property name=\"spacing\">\n       <number>6</number>\n      </property>\n      <item row=\"0\" column=\"0\">\n       <widget class=\"QLabel\" name=\"labelFind\">\n        <property name=\"text\">\n         <string>Find:</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"1\">\n       <widget class=\"QLineEdit\" name=\"editFind\"/>\n      </item>\n      <item row=\"0\" column=\"2\">\n       <widget class=\"QPushButton\" name=\"buttonNext\">\n        <property name=\"enabled\">\n         <bool>false</bool>\n        </property>\n        <property name=\"text\">\n         <string>Next</string>\n        </property>\n        <property name=\"icon\">\n         <iconset resource=\"../resources/icons.qrc\">\n          <normaloff>:/icons/scalable/down.svg</normaloff>:/icons/scalable/down.svg</iconset>\n        </property>\n        <property name=\"shortcut\">\n         <string>F3</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"0\" column=\"3\">\n       <widget class=\"QPushButton\" name=\"buttonPrevious\">\n        <property name=\"enabled\">\n         <bool>false</bool>\n        </property>\n        <property name=\"text\">\n         <string>Previous</string>\n        </property>\n        <property name=\"icon\">\n         <iconset resource=\"../resources/icons.qrc\">\n          <normaloff>:/icons/scalable/up.svg</normaloff>:/icons/scalable/up.svg</iconset>\n        </property>\n        <property name=\"shortcut\">\n         <string>Shift+F3</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"0\">\n       <widget class=\"QLabel\" name=\"labelReplace\">\n        <property name=\"text\">\n         <string>Replace:</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"1\">\n       <widget class=\"QLineEdit\" name=\"editReplace\"/>\n      </item>\n      <item row=\"1\" column=\"2\">\n       <widget class=\"QPushButton\" name=\"buttonReplace\">\n        <property name=\"enabled\">\n         <bool>false</bool>\n        </property>\n        <property name=\"text\">\n         <string>Replace</string>\n        </property>\n       </widget>\n      </item>\n      <item row=\"1\" column=\"3\">\n       <widget class=\"QPushButton\" name=\"buttonReplaceAll\">\n        <property name=\"enabled\">\n         <bool>false</bool>\n        </property>\n        <property name=\"text\">\n         <string>Replace all</string>\n        </property>\n       </widget>\n      </item>\n     </layout>\n    </item>\n    <item>\n     <layout class=\"QHBoxLayout\" name=\"horizontalLayout\" stretch=\"1,0,0,0\">\n      <item>\n       <widget class=\"QLabel\" name=\"labelMessage\">\n        <property name=\"text\">\n         <string>Message</string>\n        </property>\n       </widget>\n      </item>\n      <item>\n       <widget class=\"QCheckBox\" name=\"checkBoxSearchType\">\n        <property name=\"toolTip\">\n         <string>Search in element type instead of value.</string>\n        </property>\n        <property name=\"text\">\n         <string>Search Type</string>\n        </property>\n        <property name=\"checked\">\n         <bool>false</bool>\n        </property>\n       </widget>\n      </item>\n      <item>\n       <widget class=\"QCheckBox\" name=\"checkBoxRegExp\">\n        <property name=\"text\">\n         <string>Interpret as RegExp</string>\n        </property>\n        <property name=\"checked\">\n         <bool>false</bool>\n        </property>\n       </widget>\n      </item>\n      <item>\n       <widget class=\"QCheckBox\" name=\"checkBoxMatchCase\">\n        <property name=\"text\">\n         <string>Match Case</string>\n        </property>\n        <property name=\"checked\">\n         <bool>false</bool>\n        </property>\n       </widget>\n      </item>\n     </layout>\n    </item>\n   </layout>\n  </widget>\n </widget>\n <resources>\n  <include location=\"../resources/icons.qrc\"/>\n </resources>\n <connections>\n  <connection>\n   <sender>buttonNext</sender>\n   <signal>clicked()</signal>\n   <receiver>FindReplaceDock</receiver>\n   <slot>clickedNext()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonPrevious</sender>\n   <signal>clicked()</signal>\n   <receiver>FindReplaceDock</receiver>\n   <slot>clickedPrevious()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonReplace</sender>\n   <signal>clicked()</signal>\n   <receiver>FindReplaceDock</receiver>\n   <slot>clickedReplace()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonReplaceAll</sender>\n   <signal>clicked()</signal>\n   <receiver>FindReplaceDock</receiver>\n   <slot>clickedReplaceAll()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n <slots>\n  <slot>clickedNext()</slot>\n  <slot>clickedPrevious()</slot>\n  <slot>clickedReplace()</slot>\n  <slot>clickedReplaceAll()</slot>\n </slots>\n</ui>\n"
  },
  {
    "path": "gui/groopsGui.pro",
    "content": "#-------------------------------------------------\n#\n# Project created by QtCreator 2011-02-19T14:42:42\n#\n#-------------------------------------------------\n\n!defined(GROOPS_DIR, var) {\n  GROOPS_DIR = ../\n}\n\n!defined(OBJ_DIR, var) {\n  OBJ_DIR=build\n}\n\n!defined(DESTDIR, var) {\n  DESTDIR=$$GROOPS_DIR/bin\n}\n\n!defined(TARGET, var) {\n  TARGET=groopsGui\n}\n\nQT += xml\nQT += widgets\n\nCONFIG += c++14\n\nwin32:RC_ICONS += resources/groops.ico\n\nTEMPLATE = app\n\nINCLUDEPATH += $$GROOPS_DIR/source\n\nOBJECTS_DIR=$$OBJ_DIR\nMOC_DIR=$$OBJ_DIR\nUI_DIR=$$OBJ_DIR\nRCC_DIR=$$OBJ_DIR\n\nSOURCES += main.cpp \\\n           base/xml.cpp \\\n           base/schema.cpp \\\n           tree/tree.cpp \\\n           tree/treeItem.cpp \\\n           tree/treeElement.cpp \\\n           tree/treeElementSimple.cpp \\\n           tree/treeElementBool.cpp \\\n           tree/treeElementFileName.cpp \\\n           tree/treeElementTime.cpp \\\n           tree/treeElementComplex.cpp \\\n           tree/treeElementSequence.cpp \\\n           tree/treeElementChoice.cpp \\\n           tree/treeElementAdd.cpp \\\n           tree/treeElementGlobal.cpp \\\n           tree/treeElementProgram.cpp \\\n           tree/treeElementComment.cpp \\\n           tree/treeElementUnknown.cpp \\\n           executeDialog/executeDialog.cpp \\\n           findReplaceDock/findReplaceDock.cpp \\\n           programDialog/programDialog.cpp \\\n           settingsDialog/settingsCommandDialog.cpp \\\n           settingsDialog/settingsPathDialog.cpp \\\n           mainWindow/tabs.cpp \\\n           mainWindow/mainWindow.cpp \\\n           mainWindow/sideBar.cpp \\\n           addVariableDialog/addVariableDialog.cpp \\\n           mainWindow/schemaSelector.cpp \\\n           $$GROOPS_DIR/source/parser/expressionParser.cpp \\\n           $$GROOPS_DIR/source/parser/stringParser.cpp \\\n           $$GROOPS_DIR/source/base/format.cpp \\\n           $$GROOPS_DIR/source/base/time.cpp \\\n           $$GROOPS_DIR/source/base/constants.cpp \\\n\nHEADERS  += \\\n            base/xml.h \\\n            base/schema.h \\\n            tree/tree.h \\\n            tree/treeItem.h \\\n            tree/treeElement.h \\\n            tree/treeElementSimple.h \\\n            tree/treeElementBool.h \\\n            tree/treeElementFileName.h \\\n            tree/treeElementTime.h \\\n            tree/treeElementComplex.h \\\n            tree/treeElementSequence.h \\\n            tree/treeElementChoice.h \\\n            tree/treeElementAdd.h \\\n            tree/treeElementGlobal.h \\\n            tree/treeElementProgram.h \\\n            tree/treeElementLoopCondition.h \\\n            tree/treeElementComment.h \\\n            tree/treeElementUnknown.h \\\n            executeDialog/executeDialog.h \\\n            findReplaceDock/findReplaceDock.h \\\n            programDialog/programDialog.h \\\n            settingsDialog/settingsCommandDialog.h \\\n            settingsDialog/settingsPathDialog.h \\\n            mainWindow/tabs.h \\\n            mainWindow/mainWindow.h \\\n            mainWindow/sideBar.h \\\n            addVariableDialog/addVariableDialog.h \\\n            mainWindow/schemaSelector.h \\\n            base/importGroops.h \\\n            $$GROOPS_DIR/source/parser/expressionParser.h \\\n            $$GROOPS_DIR/source/parser/stringParser.h \\\n            $$GROOPS_DIR/source/base/format.h \\\n            $$GROOPS_DIR/source/base/exception.h \\\n            $$GROOPS_DIR/source/base/importStd.h \\\n            $$GROOPS_DIR/source/base/time.h \\\n            $$GROOPS_DIR/source/base/portable.h \\\n            $$GROOPS_DIR/source/base/constants.h \\\n\nFORMS += mainWindow/mainWindow.ui \\\n         executeDialog/executeDialog.ui \\\n         settingsDialog/settingsCommandDialog.ui \\\n         findReplaceDock/findReplaceDock.ui \\\n         programDialog/programDialog.ui \\\n         settingsDialog/settingsPathDialog.ui \\\n         addVariableDialog/addVariableDialog.ui \\\n         mainWindow/schemaSelector.ui \\\n\nRESOURCES += resources/icons.qrc\n"
  },
  {
    "path": "gui/main.cpp",
    "content": "/***********************************************/\n/**\n* @file main.cpp\n*\n* @brief Main.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2011-07-12\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QtWidgets>\n#include <QApplication>\n#include <QMessageBox>\n#include <QFileInfo>\n#include <QMainWindow>\n#include <QSettings>\n#include \"base/importGroops.h\"\n#include \"base/schema.h\"\n#include \"settingsDialog/settingsPathDialog.h\"\n#include \"mainWindow/mainWindow.h\"\n\n/***********************************************/\n\nclass MyApplication : public QApplication\n{\npublic:\n  MyApplication(int &argc, char **argv) : QApplication(argc, argv) {}\n\n  virtual bool notify(QObject *receiver, QEvent *event);\n};\n\n/***********************************************/\n\nbool MyApplication::notify(QObject *receiver, QEvent *event)\n{\n  try\n  {\n    return QApplication::notify(receiver, event);\n  }\n  catch(std::exception &e)\n  {\n    qWarning(\"%s\", e.what());\n    QMessageBox::critical(nullptr, \"GROOPS\", QString(\"****** Error ******\\n\")+e.what());\n  }\n  catch(...)\n  {\n    qWarning(\"Unknown ERROR\");\n    QMessageBox::critical(nullptr, \"GROOPS\", \"Unknown ERROR\");\n  }\n  return false;\n}\n\n/***********************************************/\n\nint main(int argc, char *argv[])\n{\n  try\n  {\n    MyApplication app(argc, argv);\n    app.connect( &app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()) );\n\n    QCoreApplication::setApplicationName(\"groopsGui\");\n    QCoreApplication::setOrganizationName(\"groops-devs\");\n    QApplication::setFont(QApplication::font(\"QMenu\"));\n\n    QCommandLineParser parser;\n    std::stringstream ss;\n    ss<<\"Graphical User Interface for GROOPS (Gravity Recovery Object Oriented Programming System)\"<<std::endl<<std::endl;\n    ss<<\"Written by: Torsten Mayer-Guerr, Wolfgang Mayer-Guerr, Sebastian Strasser\"<<std::endl;\n    ss<<\"GitHub repository: https://github.com/groops-devs/groops\"<<std::endl;\n    ss<<\"(Compiled: \"<<__DATE__<<\" \"<<__TIME__<<\")\";\n    parser.setApplicationDescription(QString::fromStdString(ss.str()));\n    parser.addHelpOption();\n    parser.addOptions(\n    {\n      {{\"c\", \"clean\"},  \"Do not open files from last session at startup.\"},\n      {{\"f\", \"file\"},   \"Open <file> at startup.\", \"file\"},\n      {{\"s\", \"schema\"}, \"Set XML schema <file> at startup.\", \"file\"}\n    });\n    parser.process(app); // Handle command line options\n\n    MainWindow window;\n    window.show();\n\n    QSettings settings;\n    QString fileNameSchema = settings.value(\"files/schemaFile\").toString();\n\n    // Set XML schema if passed as argument\n    // ------------------------------------\n    if(parser.isSet(\"schema\"))\n    {\n      QFileInfo fileFromArg(parser.value(\"schema\"));\n      Schema schema;\n      if(fileFromArg.isFile() && schema.readFile(fileFromArg.absoluteFilePath()))\n      {\n        fileNameSchema = fileFromArg.absoluteFilePath();\n        settings.setValue(\"files/schemaFile\", fileNameSchema);\n        QStringList schemaFiles = settings.value(\"files/schemaFiles\").toStringList();\n        if(!schemaFiles.contains(fileNameSchema))\n        {\n          schemaFiles.append(fileNameSchema);\n          schemaFiles.sort();\n          settings.setValue(\"files/schemaFiles\", schemaFiles);\n        }\n      }\n      else\n        QMessageBox::critical(&window, \"GROOPS\", QString(\"File '%1' passed as argument seems not to be a valid XSD schema\").arg(fileFromArg.absoluteFilePath()));\n    }\n\n    // check schema\n    // ------------\n    if(fileNameSchema.isEmpty())\n    {\n      QMessageBox::information(&window , \"GROOPS\", \"GROOPS seems not to be configured yet. You should set at least the XSD schema file.\");\n      SettingsPathDialog dialog(&window);\n      if(!dialog.exec())\n      {\n        window.close();\n        return 0;\n      }\n    }\n\n    // Open the files from the previous session (from settings)\n    // --------------------------------------------------------\n    bool isOpen = false;\n    if(!parser.isSet(\"clean\"))\n      for(const auto &fileName : settings.value(\"openFiles\").toStringList())\n        if(QFileInfo::exists(fileName))\n          isOpen = window.fileOpen(QFileInfo(fileName).absoluteFilePath()) || isOpen;\n\n    // Open files from command line arguments\n    // --------------------------------------\n    for(const auto &fileName : parser.values(\"file\"))\n      if(QFileInfo::exists(fileName))\n        isOpen = window.fileOpen(QFileInfo(fileName).absoluteFilePath()) || isOpen;\n\n    if(!isOpen)\n      window.fileNew();\n\n    return app.exec();\n  }\n  catch(std::exception &e)\n  {\n    qWarning(\"%s\", e.what());\n    QMessageBox::critical(nullptr, \"GROOPS\", QString(\"****** Error ******\\n\")+e.what());\n  }\n  catch(...)\n  {\n    qWarning(\"Unknown ERROR\");\n    QMessageBox::critical(nullptr, \"GROOPS\", \"Unknown ERROR\");\n  }\n\n  return 0;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/mainWindow/mainWindow.cpp",
    "content": "/***********************************************/\n/**\n* @file mainWindow.cpp\n*\n* @brief The main window.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2011-09-02\n*\n*/\n/***********************************************/\n\n#include \"ui_mainWindow.h\"\n#include <QtDebug>\n#include <QDesktopServices>\n#include <QtWidgets>\n#include <QFontDialog>\n#include <QUndoGroup>\n#include <QUndoView>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"findReplaceDock/findReplaceDock.h\"\n#include \"programDialog/programDialog.h\"\n#include \"settingsDialog/settingsCommandDialog.h\"\n#include \"settingsDialog/settingsPathDialog.h\"\n#include \"mainWindow/schemaSelector.h\"\n#include \"mainWindow/sideBar.h\"\n#include \"mainWindow/tabs.h\"\n#include \"mainWindow.h\"\n\n/***********************************************/\n\nMainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)\n{\n  try\n  {\n    ui->setupUi(this);\n    ui->statusBar->setHidden(true);\n    tabEnvironment = nullptr;\n    undoView  = nullptr;\n    undoGroup = new QUndoGroup(this);\n\n    // Undo/Redo actions\n    // -----------------\n    QAction *editUndoAction = undoGroup->createUndoAction(this, tr(\"&Undo\"));\n    editUndoAction->setShortcuts(QKeySequence::Undo);\n    editUndoAction->setIcon(QIcon(\":/icons/scalable/edit-undo.svg\"));\n    ui->menuEdit->insertAction(ui->editCutAction, editUndoAction);\n    ui->mainToolBar->addSeparator();\n    ui->mainToolBar->addAction(editUndoAction);\n\n    QAction *editRedoAction = undoGroup->createRedoAction(this, tr(\"&Redo\"));\n    editRedoAction->setShortcuts(QKeySequence::Redo);\n    editRedoAction->setIcon(QIcon(\":/icons/scalable/edit-redo.svg\"));\n    ui->menuEdit->insertAction(ui->editCutAction, editRedoAction);\n    ui->mainToolBar->addAction(editRedoAction);\n    ui->menuEdit->insertSeparator(ui->editCutAction);\n\n    schemaSelector = new SchemaSelector(ui->mainToolBar);\n    schemaSelector->setAction(ui->mainToolBar->addWidget(schemaSelector));\n\n    // signal slot connections\n    // -----------------------\n    connect(ui->fileNewAction,         SIGNAL(triggered(bool)), this, SLOT(fileNew()));\n    connect(ui->fileOpenAction,        SIGNAL(triggered(bool)), this, SLOT(fileOpen()));\n    connect(ui->fileReOpenAction,      SIGNAL(triggered(bool)), this, SLOT(fileReOpen()));\n    connect(ui->fileCloseAction,       SIGNAL(triggered(bool)), this, SLOT(fileClose()));\n    connect(ui->fileCloseOtherAction,  SIGNAL(triggered(bool)), this, SLOT(fileCloseOther()));\n    connect(ui->fileExitAction,        SIGNAL(triggered(bool)), this, SLOT(fileExit()));\n    connect(ui->editFindReplaceAction, SIGNAL(triggered(bool)), this, SLOT(editFindReplace()));\n    connect(ui->settingsCommandAction, SIGNAL(triggered(bool)), this, SLOT(settingsCommand()));\n    connect(ui->settingsPathAction,    SIGNAL(triggered(bool)), this, SLOT(settingsPath()));\n    connect(ui->settingsFontAction,    SIGNAL(triggered(bool)), this, SLOT(settingsFont()));\n    connect(ui->helpAboutAction,       SIGNAL(triggered(bool)), this, SLOT(helpAbout()));\n\n    // additional keyboard shortcuts\n    // -----------------------------\n    ui->editFindReplaceAction->setShortcuts({tr(\"Ctrl+F\"), tr(\"Ctrl+H\")});\n    ui->editRemoveAction->setShortcuts({tr(\"Del\"), tr(\"Ctrl+-\")});\n\n    // restore window\n    // --------------\n    setMinimumSize(QGuiApplication::primaryScreen()->size()/3);\n    if(settings.contains(\"mainWindow/geometry\"))\n      restoreGeometry(settings.value(\"mainWindow/geometry\").toByteArray());\n    else\n    {\n      resize(minimumSizeHint());\n      move(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), QGuiApplication::primaryScreen()->geometry()).topLeft());\n    }\n    restoreState(settings.value(\"mainWindow/state\").toByteArray());\n/*    QApplication::setFont(settings.value(\"misc/font\", QApplication::font()).toString());*/\n// qWarning()<<settings.value(\"misc/font\", QApplication::font()).toString();\n\n    // fill 'Open Recent' menu\n    // ------------------------------------\n    QStringList recentFileList = settings.value(\"recentFiles\").toStringList();\n    menuFileLastOpened = new QMenu(this);\n    ui->fileOpenRecentAction->setEnabled(recentFileList.size()>0);\n    connect(menuFileLastOpened,   SIGNAL(triggered(QAction*)), this, SLOT(fileLastOpened(QAction *)));\n    for(int i=0; i<recentFileList.size(); i++)\n      menuFileLastOpened->addAction(recentFileList[i])->setData(recentFileList[i]);\n    ui->fileOpenRecentAction->setMenu(menuFileLastOpened);\n\n    // ShowDescriptions status\n    // -----------------------\n    ui->helpShowDescriptionsAction->setCheckable(true);\n    ui->helpShowResultsAction->setCheckable(true);\n\n    // ActionList\n    // ----------\n    ActionList actionList;\n    actionList.fileNewAction               = ui->fileNewAction;\n    actionList.fileOpenAction              = ui->fileOpenAction;\n    actionList.fileReOpenAction            = ui->fileReOpenAction;\n    actionList.fileShowInManagerAction     = ui->fileShowInManagerAction;\n    actionList.fileCloseAction             = ui->fileCloseAction;\n    actionList.fileCloseOtherAction        = ui->fileCloseOtherAction;\n    actionList.fileSaveAction              = ui->fileSaveAction;\n    actionList.fileSaveAsAction            = ui->fileSaveAsAction;\n    actionList.fileRunAction               = ui->fileRunAction;\n    actionList.editCutAction               = ui->editCutAction;\n    actionList.editCopyAction              = ui->editCopyAction;\n    actionList.editPasteAction             = ui->editPasteAction;\n    actionList.editPasteOverwriteAction    = ui->editPasteOverwriteAction;\n    actionList.editAddAction               = ui->editAddAction;\n    actionList.editRemoveAction            = ui->editRemoveAction;\n    actionList.editAddVariableAction       = ui->editAddVariableAction;\n    actionList.editSetLoopAction           = ui->editSetLoopAction;\n    actionList.editSetConditionAction      = ui->editSetConditionAction;\n    actionList.editEnabledAction           = ui->editEnabledAction;\n    actionList.editEnableAllAction         = ui->editEnableAllAction;\n    actionList.editDisableAllAction        = ui->editDisableAllAction;\n    actionList.editRenameAction            = ui->editRenameAction;\n    actionList.editUpdateNameAction        = ui->editUpdateNameAction;\n    actionList.editAddCommentAction        = ui->editAddCommentAction;\n    actionList.editCollapseAllAction       = ui->editCollapseAllAction;\n    actionList.editOpenExternallyAction    = ui->editOpenExternallyAction;\n    actionList.settingsPathAction          = ui->settingsPathAction;\n    actionList.helpShowDescriptionsAction  = ui->helpShowDescriptionsAction;\n    actionList.helpShowResultsAction       = ui->helpShowResultsAction;\n    actionList.helpOpenDocumentationAction = ui->helpOpenDocumentationAction;\n\n    // TabEnvironment\n    // --------------\n    show();\n    tabEnvironment = new TabEnvironment(this, &actionList, undoGroup);\n    connect(tabEnvironment, SIGNAL(fileChanged(const QString&, const QString&, bool)), this, SLOT(fileChanged(const QString&, const QString&, bool)));\n\n    // Side bar and side bar widgets\n    // -----------------------------\n    // Open Files widget\n    OpenFilesTreeWidget *openFilesTreeWidget = new OpenFilesTreeWidget(tabEnvironment, actionList);\n\n    // Undo Stack widget\n    undoView = new QUndoView(undoGroup);\n    undoView->setAlternatingRowColors(true);\n\n    // Program List widget\n    programListWidget = new ProgramListWidget();\n\n    // Add widgets to side bar\n    sideBar = new SideBar(this);\n    sideBar->addSideBarWidget(\"Open Files\",   openFilesTreeWidget);\n    sideBar->addSideBarWidget(\"Program List\", programListWidget);\n    sideBar->addSideBarWidget(\"Undo Stack\",   undoView);\n\n    // Basic layout\n    // ------------\n    // Horizontal splitter (side bar widgets | tab environment)\n    QSplitter *splitter = new QSplitter;\n    splitter->setOrientation(Qt::Horizontal);\n    splitter->addWidget(sideBar->stackedWidget());\n    splitter->addWidget(tabEnvironment);\n    splitter->setChildrenCollapsible(false);\n    splitter->setStretchFactor(0, 0);\n    splitter->setStretchFactor(1, 1);\n    splitter->setSizes({sideBar->lastWidth()});\n    connect(splitter, SIGNAL(splitterMoved(int, int)), sideBar, SLOT(widthChanged(int, int)));\n\n    // Set layout (side bar | splitter)\n    QHBoxLayout *layout = new QHBoxLayout;\n    layout->addWidget(sideBar);\n    layout->addWidget(splitter);\n    layout->setAlignment(sideBar, Qt::AlignTop);\n    layout->setContentsMargins(0,0,0,0);\n    layout->setSpacing(0);\n\n    // Set layout as central widget\n    QWidget *window = new QWidget;\n    window->setLayout(layout);\n    setCentralWidget(window);\n    tabEnvironment->setFocus();\n\n    // Find/Replace Dock\n    // -----------------\n    findReplaceDock = new FindReplaceDock(this);\n    findReplaceDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);\n    addDockWidget(Qt::BottomDockWidgetArea, findReplaceDock);\n    findReplaceDock->hide();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nMainWindow::~MainWindow()\n{\n  delete ui;\n  delete undoView;\n}\n\n/***********************************************/\n\nTree *MainWindow::getCurrentTree() const\n{\n  return tabEnvironment->currentTree();\n}\n\n/***********************************************/\n\nbool MainWindow::fileNew()                            {return tabEnvironment->fileNew();}\nbool MainWindow::fileOpen(const QString &fileName)    {return tabEnvironment->fileOpen(fileName);}\nbool MainWindow::fileReOpen()                         {return tabEnvironment->fileReOpen();}\nvoid MainWindow::fileLastOpened(QAction *whichAction) {tabEnvironment->fileOpen(whichAction->data().toString());}\nbool MainWindow::fileClose()                          {return tabEnvironment->fileClose();}\nvoid MainWindow::fileCloseOther()                     {tabEnvironment->fileCloseOther();}\nvoid MainWindow::fileExit()                           {close();}\n\n/***********************************************/\n\nvoid MainWindow::editFindReplace()\n{\n  QString oldFindText = findReplaceDock->getFindText();\n\n  auto widget = QApplication::focusWidget();\n  QLineEdit *lineEdit = dynamic_cast<QLineEdit*>(widget);\n  if(!lineEdit && dynamic_cast<QComboBox*>(widget))\n    lineEdit = dynamic_cast<QComboBox*>(widget)->lineEdit();\n  if(lineEdit && !lineEdit->selectedText().isEmpty())\n    findReplaceDock->setFindText(lineEdit->selectedText());\n\n  if(!findReplaceDock->isVisible())\n    findReplaceDock->setVisible(true);\n  else if(findReplaceDock->getFindText() == oldFindText)\n    findReplaceDock->setVisible(false);\n\n  if(findReplaceDock->isVisible())\n    findReplaceDock->setFocusOnFind();\n}\n\n/***********************************************/\n\nvoid MainWindow::settingsCommand()\n{\n  SettingsCommandDialog dialog(this);\n  dialog.exec();\n}\n\n/***********************************************/\n\nvoid MainWindow::settingsPath()\n{\n  SettingsPathDialog dialog(this);\n  if(dialog.exec() == QDialog::Accepted)\n    schemaSelector->updateList();\n}\n\n/***********************************************/\n\nvoid MainWindow::settingsFont()\n{\n  bool ok;\n  QFont font = QFontDialog::getFont(&ok, QApplication::font());\n  if(!ok)\n    return;\n  settings.setValue(\"misc/font\", font);\n  QApplication::setFont(font);\n}\n\n/***********************************************/\n\nvoid MainWindow::helpAbout()\n{\n  QMessageBox::about(this, tr(\"About GROOPS GUI\"),\n                     tr(\"<h2>GROOPS Graphical User Interface</h2>\"\n                        \"<p>Gravity Recovery Object Oriented Programming System\"\n                        \"<p>Torsten Mayer-G&uuml;rr\"\n                        \"<br>Wolfgang Mayer-G&uuml;rr\"\n                        \"<br>Sebastian Strasser\"\n                        \"<p>GitHub repository: <a href=\\\"https://github.com/groops-devs/groops\\\">https://github.com/groops-devs/groops</a></p>\"\n                        \"<p>This GUI application uses the <a href=\\\"https://www.qt.io\\\">Qt framework</a> and Google's <a href=\\\"https://github.com/google/material-design-icons\\\">Material design icons</a>.</p>\"));\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MainWindow::fileChanged(const QString &caption, const QString &fileName, bool isClean)\n{\n  try\n  {\n    Tree *tree = tabEnvironment->currentTree();\n    if(tree == nullptr)\n      return;\n\n    // adapt window title\n    // ------------------\n    QString capt = caption;\n    if(!isClean)\n      capt += tr(\" [changed]\");\n    capt += tr(\" - GROOPS\");\n    this->setWindowTitle(capt);\n\n    // update Program List widget with programs from current schema\n    // ----------------------------------------------------------------\n    disconnect(programListWidget, SIGNAL(addProgram(const QString &)), nullptr, nullptr);\n    programListWidget->init(tree);\n    connect(programListWidget, SIGNAL(addProgram(const QString &)), tree, SLOT(addProgram(const QString &)));\n\n    schemaSelector->setCurrentTreeSchema(tree->fileNameSchema());\n\n    // update recentFiles list\n    // -----------------------\n    if(!fileName.isEmpty() && isClean) // !isClean cannot be a new file\n    {\n      QStringList fileNames = settings.value(\"recentFiles\").toStringList();\n      fileNames.removeOne(fileName); // is the name in the list? -> remove\n      fileNames.prepend(fileName);\n      while(fileNames.size() > 10)   // Maximum of 10 entries\n        fileNames.removeLast();\n      settings.setValue(\"recentFiles\", fileNames);\n\n      // update 'recently openend files' menu\n      // ------------------------------------\n      menuFileLastOpened->clear();\n      for(auto &fileName : fileNames)\n        menuFileLastOpened->addAction(fileName)->setData(fileName);\n      menuFileLastOpened->setEnabled(fileNames.size());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid MainWindow::closeEvent(QCloseEvent *e)\n{\n  try\n  {\n    if(!tabEnvironment || tabEnvironment->okToAbandon())\n    {\n      settings.setValue(\"mainWindow/geometry\", saveGeometry());\n      settings.setValue(\"mainWindow/state\",    saveState());\n      e->accept();\n    }\n    else\n      e->ignore();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid MainWindow::changeEvent(QEvent *e)\n{\n  QMainWindow::changeEvent(e);\n  switch(e->type())\n  {\n    case QEvent::LanguageChange:\n      ui->retranslateUi(this);\n      break;\n    default:\n      break;\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/mainWindow/mainWindow.h",
    "content": "/***********************************************/\n/**\n* @file mainWindow.h\n*\n* @brief The main window.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2011-09-02\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__MAINWINDOW_\n#define __GROOPSGUI__MAINWINDOW_\n\n#include <QMainWindow>\n#include <QSettings>\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class MainWindow;\n}\n\nclass QMenu;\nclass QUndoGroup;\nclass QUndoView;\nclass TabEnvironment;\nclass FindReplaceDock;\nclass Tree;\nclass SideBar;\nclass ProgramListWidget;\nclass SchemaSelector;\n\n/***** CLASS ***********************************/\n\nclass MainWindow : public QMainWindow\n{\n  Q_OBJECT\n\n  Ui::MainWindow    *ui;\n  QSettings          settings;\n  QMenu             *menuFileLastOpened;\n  QUndoGroup        *undoGroup;\n  QUndoView         *undoView;\n  TabEnvironment    *tabEnvironment;\n  FindReplaceDock   *findReplaceDock;\n  SideBar           *sideBar;\n  ProgramListWidget *programListWidget;\n  SchemaSelector    *schemaSelector;\n\npublic:\n  MainWindow(QWidget *parent=nullptr);\n ~MainWindow();\n\n  Tree *getCurrentTree() const;\n\npublic slots:\n  bool fileNew();\n  bool fileOpen(const QString &fileName=QString());\n  bool fileReOpen();\n  bool fileClose();\n  void fileCloseOther();\n  void fileExit();\n  void fileLastOpened(QAction *whichAction);\n  void editFindReplace();\n  void settingsCommand();\n  void settingsPath();\n  void settingsFont();\n  void helpAbout();\n  void fileChanged(const QString &caption, const QString &fileName, bool isClean);\n\nprotected:\n  void closeEvent(QCloseEvent *e);\n  void changeEvent(QEvent *e);\n};\n\n/***** CLASS ***********************************/\n\nclass ActionList\n{\npublic:\n  QAction *fileNewAction;\n  QAction *fileOpenAction;\n  QAction *fileReOpenAction;\n  QAction *fileOpenRecentAction;\n  QAction *fileShowInManagerAction;\n  QAction *fileSaveAction;\n  QAction *fileSaveAsAction;\n  QAction *fileRunAction;\n  QAction *fileCloseAction;\n  QAction *fileCloseOtherAction;\n  QAction *editCutAction;\n  QAction *editCopyAction;\n  QAction *editPasteAction;\n  QAction *editPasteOverwriteAction;\n  QAction *editAddAction;\n  QAction *editRemoveAction;\n  QAction *editAddVariableAction;\n  QAction *editSetLoopAction;\n  QAction *editSetConditionAction;\n  QAction *editEnabledAction;\n  QAction *editEnableAllAction;\n  QAction *editDisableAllAction;\n  QAction *editRenameAction;\n  QAction *editUpdateNameAction;\n  QAction *editAddCommentAction;\n  QAction *editCollapseAllAction;\n  QAction *editOpenExternallyAction;\n  QAction *settingsPathAction;\n  QAction *helpShowDescriptionsAction;\n  QAction *helpShowResultsAction;\n  QAction *helpOpenDocumentationAction;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/mainWindow/mainWindow.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>MainWindow</class>\n <widget class=\"QMainWindow\" name=\"MainWindow\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>800</width>\n    <height>600</height>\n   </rect>\n  </property>\n  <property name=\"windowTitle\">\n   <string>GROOPS</string>\n  </property>\n  <property name=\"windowIcon\">\n   <iconset resource=\"../resources/icons.qrc\">\n    <normaloff>:/icons/scalable/groops.svg</normaloff>:/icons/scalable/groops.svg</iconset>\n  </property>\n  <widget class=\"QWidget\" name=\"centralWidget\"/>\n  <widget class=\"QMenuBar\" name=\"menuBar\">\n   <property name=\"geometry\">\n    <rect>\n     <x>0</x>\n     <y>0</y>\n     <width>800</width>\n     <height>20</height>\n    </rect>\n   </property>\n   <widget class=\"QMenu\" name=\"menuFile\">\n    <property name=\"title\">\n     <string>&amp;File</string>\n    </property>\n    <addaction name=\"fileNewAction\"/>\n    <addaction name=\"fileOpenAction\"/>\n    <addaction name=\"fileReOpenAction\"/>\n    <addaction name=\"fileOpenRecentAction\"/>\n    <addaction name=\"fileShowInManagerAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"fileSaveAction\"/>\n    <addaction name=\"fileSaveAsAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"fileRunAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"fileCloseAction\"/>\n    <addaction name=\"fileCloseOtherAction\"/>\n    <addaction name=\"fileExitAction\"/>\n   </widget>\n   <widget class=\"QMenu\" name=\"menuEdit\">\n    <property name=\"title\">\n     <string>&amp;Edit</string>\n    </property>\n    <addaction name=\"editCutAction\"/>\n    <addaction name=\"editCopyAction\"/>\n    <addaction name=\"editPasteAction\"/>\n    <addaction name=\"editPasteOverwriteAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"editFindReplaceAction\"/>\n    <addaction name=\"editCollapseAllAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"editEnabledAction\"/>\n    <addaction name=\"editEnableAllAction\"/>\n    <addaction name=\"editDisableAllAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"editAddAction\"/>\n    <addaction name=\"editRemoveAction\"/>\n    <addaction name=\"editAddVariableAction\"/>\n    <addaction name=\"editAddCommentAction\"/>\n    <addaction name=\"editSetLoopAction\"/>\n    <addaction name=\"editSetConditionAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"editRenameAction\"/>\n    <addaction name=\"editUpdateNameAction\"/>\n    <addaction name=\"editOpenExternallyAction\"/>\n   </widget>\n   <widget class=\"QMenu\" name=\"menuSettings\">\n    <property name=\"title\">\n     <string>&amp;Settings</string>\n    </property>\n    <addaction name=\"settingsCommandAction\"/>\n    <addaction name=\"settingsPathAction\"/>\n    <addaction name=\"settingsFontAction\"/>\n   </widget>\n   <widget class=\"QMenu\" name=\"menuHelp\">\n    <property name=\"title\">\n     <string>&amp;Help</string>\n    </property>\n    <addaction name=\"helpShowDescriptionsAction\"/>\n    <addaction name=\"helpShowResultsAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"helpOpenDocumentationAction\"/>\n    <addaction name=\"separator\"/>\n    <addaction name=\"helpAboutAction\"/>\n   </widget>\n   <addaction name=\"menuFile\"/>\n   <addaction name=\"menuEdit\"/>\n   <addaction name=\"menuSettings\"/>\n   <addaction name=\"menuHelp\"/>\n  </widget>\n  <widget class=\"QToolBar\" name=\"mainToolBar\">\n   <property name=\"sizePolicy\">\n    <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n     <horstretch>0</horstretch>\n     <verstretch>0</verstretch>\n    </sizepolicy>\n   </property>\n   <attribute name=\"toolBarArea\">\n    <enum>TopToolBarArea</enum>\n   </attribute>\n   <attribute name=\"toolBarBreak\">\n    <bool>false</bool>\n   </attribute>\n   <addaction name=\"fileNewAction\"/>\n   <addaction name=\"fileOpenAction\"/>\n   <addaction name=\"fileSaveAction\"/>\n   <addaction name=\"fileSaveAsAction\"/>\n   <addaction name=\"separator\"/>\n   <addaction name=\"fileRunAction\"/>\n   <addaction name=\"separator\"/>\n   <addaction name=\"editEnableAllAction\"/>\n   <addaction name=\"editDisableAllAction\"/>\n   <addaction name=\"editCollapseAllAction\"/>\n  </widget>\n  <widget class=\"QStatusBar\" name=\"statusBar\"/>\n  <action name=\"fileNewAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/document-new.svg</normaloff>:/icons/scalable/document-new.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>New</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+N</string>\n   </property>\n  </action>\n  <action name=\"fileOpenAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/document-open.svg</normaloff>:/icons/scalable/document-open.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Open ...</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+O</string>\n   </property>\n  </action>\n  <action name=\"fileOpenRecentAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/document-open-recent.svg</normaloff>:/icons/scalable/document-open-recent.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Open Recent</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Open Recent</string>\n   </property>\n  </action>\n  <action name=\"fileSaveAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/document-save.svg</normaloff>:/icons/scalable/document-save.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Save</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+S</string>\n   </property>\n  </action>\n  <action name=\"fileSaveAsAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/document-save-as.svg</normaloff>:/icons/scalable/document-save-as.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Save As ...</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Save As</string>\n   </property>\n  </action>\n  <action name=\"fileReOpenAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/view-refresh.svg</normaloff>:/icons/scalable/view-refresh.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Reopen</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>F5</string>\n   </property>\n  </action>\n  <action name=\"fileRunAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/run.svg</normaloff>:/icons/scalable/run.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Run ...</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+R</string>\n   </property>\n  </action>\n  <action name=\"fileCloseAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-delete.svg</normaloff>:/icons/scalable/edit-delete.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Close File</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+W</string>\n   </property>\n  </action>\n  <action name=\"fileExitAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/application-exit.svg</normaloff>:/icons/scalable/application-exit.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Quit</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+Q</string>\n   </property>\n  </action>\n  <action name=\"editCutAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-cut.svg</normaloff>:/icons/scalable/edit-cut.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Cut</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+X</string>\n   </property>\n  </action>\n  <action name=\"editCopyAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-copy.svg</normaloff>:/icons/scalable/edit-copy.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Copy</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+C</string>\n   </property>\n  </action>\n  <action name=\"editPasteAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-paste.svg</normaloff>:/icons/scalable/edit-paste.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Paste</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+V</string>\n   </property>\n  </action>\n  <action name=\"editPasteOverwriteAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-paste.svg</normaloff>:/icons/scalable/edit-paste.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Paste (Overwrite)</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+Shift+V</string>\n   </property>\n  </action>\n  <action name=\"editFindReplaceAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-find-replace.svg</normaloff>:/icons/scalable/edit-find-replace.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Find/Replace</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+F</string>\n   </property>\n  </action>\n  <action name=\"editAddAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-add.svg</normaloff>:/icons/scalable/edit-add.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Add</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl++</string>\n   </property>\n  </action>\n  <action name=\"editRemoveAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-delete.svg</normaloff>:/icons/scalable/edit-delete.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Delete ...</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Del</string>\n   </property>\n  </action>\n  <action name=\"editAddVariableAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/link.svg</normaloff>:/icons/scalable/link.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Add Variable ...</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Add Variable</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+G</string>\n   </property>\n  </action>\n  <action name=\"editEnabledAction\">\n   <property name=\"checkable\">\n    <bool>true</bool>\n   </property>\n   <property name=\"checked\">\n    <bool>true</bool>\n   </property>\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"text\">\n    <string>Enabled</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+E</string>\n   </property>\n  </action>\n  <action name=\"editAddCommentAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/element-comment.svg</normaloff>:/icons/scalable/element-comment.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Add Comment</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>F4</string>\n   </property>\n  </action>\n  <action name=\"settingsCommandAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/settings.svg</normaloff>:/icons/scalable/settings.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Commands ...</string>\n   </property>\n  </action>\n  <action name=\"settingsPathAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/settings.svg</normaloff>:/icons/scalable/settings.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Default Paths and Files ...</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Default Paths and Files</string>\n   </property>\n  </action>\n  <action name=\"settingsFontAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/settings.svg</normaloff>:/icons/scalable/settings.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Font</string>\n   </property>\n   <property name=\"visible\">\n    <bool>false</bool>\n   </property>\n  </action>\n  <action name=\"helpShowDescriptionsAction\">\n   <property name=\"checkable\">\n    <bool>true</bool>\n   </property>\n   <property name=\"checked\">\n    <bool>true</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/help-contents.svg</normaloff>:/icons/scalable/help-contents.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Show Descriptions</string>\n   </property>\n  </action>\n  <action name=\"helpShowResultsAction\">\n   <property name=\"checkable\">\n    <bool>true</bool>\n   </property>\n   <property name=\"checked\">\n    <bool>true</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/help-contents.svg</normaloff>:/icons/scalable/help-contents.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Show Results of Links/Expressions</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Show Results of Links/Expressions</string>\n   </property>\n  </action>\n  <action name=\"helpAboutAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/help-about.svg</normaloff>:/icons/scalable/help-about.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>About ...</string>\n   </property>\n  </action>\n  <action name=\"editRenameAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-rename.svg</normaloff>:/icons/scalable/edit-rename.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Rename ...</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>F2</string>\n   </property>\n  </action>\n  <action name=\"editSetLoopAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/loop-set.svg</normaloff>:/icons/scalable/loop-set.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Set Loop</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Set Loop</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+L</string>\n   </property>\n  </action>\n  <action name=\"editEnableAllAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-enable.svg</normaloff>:/icons/scalable/edit-enable.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Enable All</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Enable All Top-Level Programs</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+Shift+E</string>\n   </property>\n  </action>\n  <action name=\"editDisableAllAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-disable.svg</normaloff>:/icons/scalable/edit-disable.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Disable All</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Disable All Top-Level Programs</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+Shift+D</string>\n   </property>\n  </action>\n  <action name=\"editCollapseAllAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/document-collapse.svg</normaloff>:/icons/scalable/document-collapse.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Collapse All</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Collapse All Elements</string>\n   </property>\n  </action>\n  <action name=\"helpOpenDocumentationAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/help-contents.svg</normaloff>:/icons/scalable/help-contents.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Open Documentation</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Open Documentation in External Browser</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>F1</string>\n   </property>\n  </action>\n  <action name=\"editSetConditionAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/condition-set.svg</normaloff>:/icons/scalable/condition-set.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Set Condition</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Set Condition</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+K</string>\n   </property>\n  </action>\n  <action name=\"fileCloseOtherAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-delete.svg</normaloff>:/icons/scalable/edit-delete.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Close Other Files</string>\n   </property>\n   <property name=\"shortcut\">\n    <string>Ctrl+Shift+W</string>\n   </property>\n  </action>\n  <action name=\"editOpenExternallyAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/open-externally.svg</normaloff>:/icons/scalable/open-externally.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Open Externally</string>\n   </property>\n  </action>\n  <action name=\"fileShowInManagerAction\">\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/open-externally.svg</normaloff>:/icons/scalable/open-externally.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Show in File Manager</string>\n   </property>\n  </action>\n  <action name=\"editUpdateNameAction\">\n   <property name=\"enabled\">\n    <bool>false</bool>\n   </property>\n   <property name=\"icon\">\n    <iconset resource=\"../resources/icons.qrc\">\n     <normaloff>:/icons/scalable/edit-rename.svg</normaloff>:/icons/scalable/edit-rename.svg</iconset>\n   </property>\n   <property name=\"text\">\n    <string>Update Name</string>\n   </property>\n   <property name=\"toolTip\">\n    <string>Update name in case the element has been renamed in the schema</string>\n   </property>\n  </action>\n </widget>\n <layoutdefault spacing=\"6\" margin=\"11\"/>\n <resources>\n  <include location=\"../resources/icons.qrc\"/>\n </resources>\n <connections/>\n</ui>\n"
  },
  {
    "path": "gui/mainWindow/schemaSelector.cpp",
    "content": "/***********************************************/\n/**\n* @file schemaSelector.h\n*\n* @brief Schema selector.\n*\n* @author Sebastian Strasser\n* @date 2017-06-17\n*/\n/***********************************************/\n\n#include \"schemaSelector.h\"\n#include \"ui_schemaSelector.h\"\n\n/***********************************************/\n\nSchemaSelector::SchemaSelector(QWidget *parent) : QWidget(parent), ui(new Ui::SchemaSelector)\n{\n  ui->setupUi(this);\n  action = nullptr;\n\n  ui->icon->hide();\n  int iconSize = parentWidget()->minimumSizeHint().height()*7/10;\n  ui->icon->setMaximumSize(iconSize, iconSize);\n  ui->icon->resize(ui->icon->maximumSize());\n\n  updateList();\n\n  connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectionChanged()));\n}\n\n/***********************************************/\n\nSchemaSelector::~SchemaSelector()\n{\n  delete ui;\n}\n\n/***********************************************/\n\nvoid SchemaSelector::setAction(QAction *action)\n{\n  this->action = action;\n  if(action != nullptr)\n    action->setVisible(ui->comboBox->count() > 1);\n}\n\n/***********************************************/\n\nvoid SchemaSelector::setCurrentTreeSchema(QString schemaFile)\n{\n  currentTreeSchema = schemaFile;\n  ui->icon->setVisible(schemaFile != ui->comboBox->currentText());\n}\n\n/***********************************************/\n\nvoid SchemaSelector::updateList()\n{\n  QString     schemaFile  = settings.value(\"files/schemaFile\").toString();\n  QStringList schemaFiles = settings.value(\"files/schemaFiles\").toStringList();\n  ui->comboBox->blockSignals(true);\n  ui->comboBox->clear();\n  if(schemaFiles.size())\n    ui->comboBox->addItems(schemaFiles);\n  else\n    ui->comboBox->addItem(schemaFile);\n  int index = ui->comboBox->findText(schemaFile);\n  ui->comboBox->setCurrentIndex(index >= 0 ? index : 0);\n  ui->comboBox->blockSignals(false);\n\n  if(schemaFile != ui->comboBox->currentText())\n    selectionChanged();\n\n  ui->icon->setVisible(currentTreeSchema != ui->comboBox->currentText());\n\n  // setVisible() has to be called on QAction when QWidget is added to QMenuBar\n  if(action != nullptr)\n    action->setVisible(ui->comboBox->count() > 1);\n}\n\n/***********************************************/\n\nvoid SchemaSelector::selectionChanged()\n{\n  settings.setValue(\"files/schemaFile\", ui->comboBox->currentText());\n  ui->icon->setVisible(currentTreeSchema != ui->comboBox->currentText());\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/mainWindow/schemaSelector.h",
    "content": "/***********************************************/\n/**\n* @file schemaSelector.h\n*\n* @brief Schema selector.\n*\n* @author Sebastian Strasser\n* @date 2017-06-17\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__SCHEMASELECTOR_H__\n#define __GROOPSGUI__SCHEMASELECTOR_H__\n\n#include <QAction>\n#include <QSettings>\n#include <QWidget>\n\n/***** CLASS ***********************************/\n\nnamespace Ui {\nclass SchemaSelector;\n}\n\nclass SchemaSelector : public QWidget\n{\n  Q_OBJECT\n\npublic:\n  explicit SchemaSelector(QWidget *parent);\n ~SchemaSelector();\n  void setAction(QAction *action);\n  void setCurrentTreeSchema(QString schemaFile);\n\npublic slots:\n  void updateList();\n  void selectionChanged();\n\nprivate:\n  Ui::SchemaSelector *ui;\n  QSettings           settings;\n  QAction            *action;\n  QString             currentTreeSchema;\n};\n\n/***********************************************/\n\n#endif // __GROOPSGUI__SCHEMASELECTOR_H__\n"
  },
  {
    "path": "gui/mainWindow/schemaSelector.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>SchemaSelector</class>\n <widget class=\"QWidget\" name=\"SchemaSelector\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>400</width>\n    <height>30</height>\n   </rect>\n  </property>\n  <property name=\"sizePolicy\">\n   <sizepolicy hsizetype=\"Fixed\" vsizetype=\"Minimum\">\n    <horstretch>0</horstretch>\n    <verstretch>0</verstretch>\n   </sizepolicy>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>0</width>\n    <height>0</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Form</string>\n  </property>\n  <layout class=\"QGridLayout\" name=\"gridLayout\">\n   <property name=\"topMargin\">\n    <number>0</number>\n   </property>\n   <property name=\"bottomMargin\">\n    <number>0</number>\n   </property>\n   <property name=\"verticalSpacing\">\n    <number>0</number>\n   </property>\n   <item row=\"0\" column=\"1\">\n    <widget class=\"QComboBox\" name=\"comboBox\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Fixed\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"sizeAdjustPolicy\">\n      <enum>QComboBox::AdjustToContents</enum>\n     </property>\n    </widget>\n   </item>\n   <item row=\"0\" column=\"0\">\n    <widget class=\"QLabel\" name=\"label\">\n     <property name=\"text\">\n      <string>Schema:</string>\n     </property>\n    </widget>\n   </item>\n   <item row=\"0\" column=\"2\">\n    <widget class=\"QLabel\" name=\"icon\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"minimumSize\">\n      <size>\n       <width>16</width>\n       <height>16</height>\n      </size>\n     </property>\n     <property name=\"toolTip\">\n      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selected schema differs from the schema the current file was opened with. Reload file to apply selected schema.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\n     </property>\n     <property name=\"text\">\n      <string/>\n     </property>\n     <property name=\"pixmap\">\n      <pixmap resource=\"../resources/icons.qrc\">:/icons/scalable/warning.svg</pixmap>\n     </property>\n     <property name=\"scaledContents\">\n      <bool>true</bool>\n     </property>\n    </widget>\n   </item>\n  </layout>\n </widget>\n <resources>\n  <include location=\"../resources/icons.qrc\"/>\n </resources>\n <connections/>\n</ui>\n"
  },
  {
    "path": "gui/mainWindow/sideBar.cpp",
    "content": "/***********************************************/\n/**\n* @file sideBar.h\n*\n* @brief Side bar and all of its components.\n*\n* @author Sebastian Strasser\n* @date 2017-06-17\n*/\n/***********************************************/\n\n#include \"sideBar.h\"\n#include \"tree/tree.h\"\n#include <QDebug>\n#include <QDesktopServices>\n#include <QFileInfo>\n#include <QPainter>\n#include <QStyleOption>\n#include <QMenu>\n#include <QHeaderView>\n#include <QUrl>\n#include <QMimeData>\n\n/***********************************************/\n\nSideBar::SideBar(QWidget *parent) : QWidget(parent)\n{\n  try\n  {\n    layout = new QVBoxLayout(this);\n    layout->setAlignment(this, Qt::AlignTop);\n    layout->setSpacing(0);\n    layout->setContentsMargins(0,0,0,0);\n\n    _stackedWidget = new QStackedWidget(this);\n    _stackedWidget->setHidden(settings.value(\"sideBar/isHidden\", false).toBool());\n    _lastWidth = settings.value(\"sideBar/width\", parentWidget()->width()/5).toInt();\n\n    buttonGroup.setExclusive(false);\n    connect(&buttonGroup, &QButtonGroup::idClicked, this, &SideBar::buttonClicked);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nSideBar::~SideBar()\n{\n  settings.setValue(\"sideBar/width\",    lastWidth());\n  settings.setValue(\"sideBar/isHidden\", stackedWidget()->isHidden());\n}\n\n/***********************************************/\n\nvoid SideBar::addSideBarWidget(const QString &buttonLabel, QWidget *widget)\n{\n  // add push button\n  PushButtonVertical *button = new PushButtonVertical(buttonLabel, this);\n  button->setMaximumWidth(button->minimumSizeHint().height()); // orientation = Qt::Vertical;\n  button->setFlat(true);\n  button->setCheckable(true);\n  button->setChecked(false);\n  buttonGroup.addButton(button, _stackedWidget->count());\n  layout->addWidget(button);\n\n  _stackedWidget->addWidget(widget);\n\n  buttonGroup.button(0)->setChecked(!_stackedWidget->isHidden());\n  _stackedWidget->setCurrentIndex(0);\n}\n\n/***********************************************/\n\nvoid SideBar::buttonClicked(int id)\n{\n  // deselect all others\n  for(int i=0; i<_stackedWidget->count(); i++)\n    if(i != id)\n      buttonGroup.button(i)->setChecked(false);\n\n  _stackedWidget->setVisible(buttonGroup.button(id)->isChecked());\n  if(buttonGroup.button(id)->isChecked())\n    _stackedWidget->setCurrentIndex(id);\n}\n\n/***********************************************/\n\nvoid SideBar::widthChanged(int width, int /*index*/)\n{\n  if(!_stackedWidget->isHidden())\n    _lastWidth = width;\n}\n\n/***********************************************/\n\nvoid PushButtonVertical::paintEvent(QPaintEvent */*event*/)\n{\n  // support focus/hover styles\n  QStyleOptionButton options;\n  options.initFrom(this);\n  options.icon     = icon();\n  options.iconSize = iconSize();\n  if(isFlat())                                    options.features |= QStyleOptionButton::Flat;\n  if(menu())                                      options.features |= QStyleOptionButton::HasMenu;\n  if(autoDefault() || isDefault())                options.features |= QStyleOptionButton::AutoDefaultButton;\n  if(isDefault())                                 options.features |= QStyleOptionButton::DefaultButton;\n  if(isDown() || (menu() && menu()->isVisible())) options.state    |= QStyle::State_Sunken;\n  if(isChecked())                                 options.state    |= QStyle::State_On;\n  if(!isFlat() && !isDown())                      options.state    |= QStyle::State_Raised;\n\n  QPainter painter(this);\n  style()->drawControl(QStyle::CE_PushButton, &options, &painter, this);\n\n  // text render hint\n  painter.setRenderHints(QPainter::TextAntialiasing);\n  painter.rotate(-90);\n  painter.drawText(QRect(0, 0, -height(), width()), Qt::AlignHCenter | Qt::AlignVCenter, QPushButton::text());\n}\n\n/***********************************************/\n\nOpenFilesTreeWidget::OpenFilesTreeWidget(TabEnvironment *tabEnvironment, ActionList &actionList) : actionList(actionList), tabEnvironment(tabEnvironment)\n{\n  setColumnCount(1);\n  header()->close();\n  setSortingEnabled(true);\n  sortByColumn(0, Qt::AscendingOrder);\n  viewport()->setAcceptDrops(true); // internal & external drag\n  populateTree();\n\n  connect(tabEnvironment, SIGNAL(fileChanged(const QString&, const QString&, bool)), this, SLOT(fileChanged(const QString&, const QString&, bool)));\n  connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));\n  connect(this, SIGNAL(fileSelectionChanged(int)), tabEnvironment, SLOT(tabChanged(int)));\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::populateTree()\n{\n  // remember collapsed status of folders\n  QStringList collapsedFolders;\n  for(auto it = QTreeWidgetItemIterator(this); *it; it++)\n    if(((*it)->data(0, Qt::UserRole).toString() == \"folder\") && !(*it)->isExpanded())\n      collapsedFolders.push_back((*it)->toolTip(0));\n\n  clear(); // clear tree\n\n  // populate tree with opened files\n  TreeWidgetItem *topLevelItem = nullptr;\n  for(auto &tree : tabEnvironment->trees())\n    if(!tree->fileName().isEmpty())\n    {\n      QStringList splitFileName = tree->fileName().split(\"/\");\n\n      // add root folder as top level item if treeWidget doesn't already have it\n      if(findItems(splitFileName[0], Qt::MatchFixedString|Qt::MatchCaseSensitive).isEmpty())\n      {\n        topLevelItem = new TreeWidgetItem;\n        topLevelItem->setText(0, splitFileName[0]);\n        topLevelItem->setIcon(0, QIcon(\":/icons/scalable/folder.svg\"));\n        addTopLevelItem(topLevelItem);\n      }\n\n      QTreeWidgetItem *parentItem = topLevelItem;\n\n      // iterate through non-root directories (file name comes after)\n      for(int i=1; i<splitFileName.size()-1; i++)\n      {\n        // iterate through children of parentItem to see if this directory exists\n        bool thisDirectoryExists = false;\n        for(int k=0; k<parentItem->childCount(); k++)\n          if(splitFileName[i] == parentItem->child(k)->text(0))\n          {\n            thisDirectoryExists = true;\n            parentItem = parentItem->child(k);\n            break;\n          }\n\n        if(!thisDirectoryExists)\n        {\n          parentItem = new TreeWidgetItem(parentItem);\n          parentItem->setText(0, splitFileName[i].toUtf8());\n          QStringList fileName;\n          for(int k=0; k<=i; k++)\n            fileName<<splitFileName[k];\n          parentItem->setToolTip(0, fileName.join(\"/\").toUtf8());\n          parentItem->setData(0, Qt::UserRole, QVariant(QString(\"folder\")));\n          parentItem->setIcon(0, QIcon(\":/icons/scalable/folder.svg\"));\n          parentItem->setFlags(Qt::ItemIsEnabled);\n        }\n      }\n\n      QTreeWidgetItem *childItem = new TreeWidgetItem(parentItem);\n      childItem->setText(0,    tree->caption());\n      childItem->setToolTip(0, tree->fileName());\n      childItem->setData(0, Qt::UserRole, QVariant(QString(\"file\")));\n      childItem->setIcon(0, tree->isClean() ? QIcon(\":/icons/scalable/text-xml.svg\") : QIcon(\":/icons/scalable/document-save.svg\"));\n    }\n\n  // reduce branches to a maximum of one folder above the first file\n  auto it = QTreeWidgetItemIterator(this);\n  while(*it)\n  {\n    if(((*it)->data(0, Qt::UserRole).toString() == \"folder\") && ((*it)->childCount() == 1) &&\n       ((*it)->child(0)->data(0, Qt::UserRole).toString() == \"folder\"))\n    {\n      QTreeWidgetItem *child = (*it)->takeChild(0);\n      if((*it)->parent())\n        (*it)->parent()->addChild(child);\n      else\n        addTopLevelItem(child);\n      it = QTreeWidgetItemIterator(this);\n    }\n    else\n      ++it;\n  }\n\n  // delete branches that don't contain any files\n  it = QTreeWidgetItemIterator(this);\n  while(*it)\n  {\n    if((*it)->data(0, Qt::UserRole).toString() == \"folder\" && !hasFileChild((*it)))\n    {\n      delete (*it);\n      it = QTreeWidgetItemIterator(this);\n    }\n    else\n      ++it;\n  }\n\n  // if only one top level item is left and it has no files as direct children, remove it and make children top level items\n  while(topLevelItemCount() == 1)\n  {\n    QTreeWidgetItem *topLevelItem = this->topLevelItem(0);\n    int directFileChildren = 0;\n    for(int i=0; i<topLevelItem->childCount(); i++)\n      if(topLevelItem->child(i)->data(0, Qt::UserRole).toString() == \"file\")\n        directFileChildren++;\n    if(directFileChildren > 0)\n      break;\n    this->insertTopLevelItems(topLevelItemCount(), topLevelItem->takeChildren());\n    delete topLevelItem;\n  }\n\n  // restore expanded/collapsed status of folders\n  expandAll();\n  for(auto it=QTreeWidgetItemIterator(this); *it; it++)\n    if(((*it)->data(0, Qt::UserRole).toString() == \"folder\") && collapsedFolders.contains((*it)->toolTip(0)))\n      (*it)->setExpanded(false);\n\n  // add newly created files (without associated XML file) to top level\n  for(auto &tree : tabEnvironment->trees())\n    if(tree->fileName().isEmpty())\n    {\n      QTreeWidgetItem *item = new TreeWidgetItem();\n      item->setText(0, tree->caption());\n      // item->setToolTip(0, tree->caption());\n      item->setData(0, Qt::UserRole, QVariant(QString(\"file\")));\n      item->setIcon(0, tree->isClean() ? QIcon(\":/icons/scalable/text-xml.svg\") : QIcon(\":/icons/scalable/document-save.svg\"));\n      insertTopLevelItem(topLevelItemCount(), item);\n    }\n}\n\n/***********************************************/\n\nbool OpenFilesTreeWidget::hasFileChild(const QTreeWidgetItem *item) const\n{\n  for(int i=0; i<item->childCount(); i++)\n    if((item->child(i)->data(0, Qt::UserRole).toString() == \"file\") || hasFileChild(item->child(i)))\n      return true;\n  return false;\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem */*previous*/)\n{\n  for(auto &tree : tabEnvironment->trees())\n    if((tree != tabEnvironment->currentTree()) && (current->text(0) == tree->caption()) && (current->toolTip(0) == tree->fileName()))\n    {\n      disconnect(tabEnvironment, SIGNAL(fileChanged(const QString&, const QString&, bool)), this, SLOT(fileChanged(const QString&, const QString&, bool)));\n      tabEnvironment->setCurrentTree(tree);\n      connect(tabEnvironment, SIGNAL(fileChanged(const QString&, const QString&, bool)), this, SLOT(fileChanged(const QString&, const QString&, bool)));\n      break;\n    }\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::fileChanged(const QString &caption, const QString &fileName, bool /*isClean*/)\n{\n  this->blockSignals(true);\n  populateTree();\n  for(auto it=QTreeWidgetItemIterator(this); *it; it++)\n    if(((*it)->text(0) == caption) && ((*it)->toolTip(0) == fileName))\n      this->setCurrentItem(*it);\n  this->blockSignals(false);\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::mousePressEvent(QMouseEvent *event)\n{\n  QTreeWidgetItem *item = itemAt(event->pos());\n  if(item && item->data(0, Qt::UserRole).toString() == \"folder\")\n    item->setExpanded(!item->isExpanded());\n  else\n    QTreeWidget::mousePressEvent(event);\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::contextMenuEvent(QContextMenuEvent *e)\n{\n  QTreeWidgetItem *item = itemAt(e->pos());\n  if(!item || item->data(0, Qt::UserRole).toString() == \"folder\")\n    return;\n  setCurrentItem(item);\n\n  QMenu *contextMenu = new QMenu(this);\n  contextMenu->addAction(actionList.fileNewAction);\n  contextMenu->addAction(actionList.fileOpenAction);\n  contextMenu->addAction(actionList.fileReOpenAction);\n  contextMenu->addAction(actionList.fileShowInManagerAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(actionList.fileSaveAction);\n  contextMenu->addAction(actionList.fileSaveAsAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(actionList.fileRunAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(actionList.fileCloseAction);\n  contextMenu->addAction(actionList.fileCloseOtherAction);\n  contextMenu->exec(e->globalPos());\n  delete contextMenu;\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::dragEnterEvent(QDragEnterEvent *event)\n{\n  if(event->mimeData()->hasUrls()) // file names?\n    event->acceptProposedAction();\n  else\n    event->ignore();\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::dragMoveEvent(QDragMoveEvent *event)\n{\n  if(event->mimeData()->hasUrls()) // file names?\n    event->acceptProposedAction();\n  else\n    event->ignore();\n}\n\n/***********************************************/\n\nvoid OpenFilesTreeWidget::dropEvent(QDropEvent *event)\n{\n  if(event->mimeData()->hasUrls())  // file names?\n  {\n    for(auto &url : event->mimeData()->urls())\n      tabEnvironment->fileOpen(url.toLocalFile());\n    event->acceptProposedAction();\n  }\n}\n\n/***********************************************/\n\nbool TreeWidgetItem::operator<(const QTreeWidgetItem &other) const\n{\n  if((this->data(0, Qt::UserRole).toString() == \"file\") && (other.data(0, Qt::UserRole).toString() == \"folder\"))\n    return false;\n  else if((this->data(0, Qt::UserRole).toString() == \"folder\") && (other.data(0, Qt::UserRole).toString() == \"file\"))\n    return true;\n  else\n    return QTreeWidgetItem::operator<(other);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/mainWindow/sideBar.h",
    "content": "/***********************************************/\n/**\n* @file sideBar.h\n*\n* @brief Side bar and all of its components.\n*\n* @author Sebastian Strasser\n* @date 2017-06-17\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__SIDEBAR__\n#define __GROOPSGUI__SIDEBAR__\n\n#include <QStackedWidget>\n#include <QPushButton>\n#include <QButtonGroup>\n#include <QPaintEvent>\n#include <QVBoxLayout>\n#include <QTreeWidget>\n#include \"base/importGroops.h\"\n#include \"mainWindow/tabs.h\"\n#include \"mainWindow/mainWindow.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Side bar containing the buttons to switch side bar widgets, but not the side bar widgets themselves. */\nclass SideBar : public QWidget\n{\n  Q_OBJECT\n\n  QStackedWidget       *_stackedWidget;\n  QButtonGroup          buttonGroup;\n  QVBoxLayout          *layout;\n  QSettings             settings;\n  int                   _lastWidth;\n\npublic:\n  SideBar(QWidget *parent);\n ~SideBar();\n\n  /** @brief Adds a @a button to the side bar and a @a widget to the side bar widgets stack. */\n  void addSideBarWidget(const QString &buttonLabel, QWidget *widget);\n\n  /** @brief Returns a pointer to the side bar widgets stack. */\n  QStackedWidget *stackedWidget() const {return _stackedWidget;}\n\n  /** @brief Returns the last set width of the widget. */\n  int lastWidth() {return _lastWidth;}\n\npublic slots:\n  /** @brief Updates the side bar selection and shows/hides the side bar widget. */\n  void buttonClicked(int id);\n\n  /** @brief Set last width of the widget, used for saving settings. */\n  void widthChanged(int width, int index);\n};\n\n/***********************************************/\n\n/** @brief PushButton that allows for vertical orientation. */\nclass PushButtonVertical : public QPushButton\n{\n  Q_OBJECT\n\npublic:\n  PushButtonVertical(QString text, QWidget *parent=nullptr) : QPushButton(text, parent) {};\n\n  QSize minimumSizeHint() const override {return QPushButton::minimumSizeHint().transposed();}\n  QSize sizeHint() const override  {return QPushButton::sizeHint().transposed();}\n\nprotected:\n  void  paintEvent(QPaintEvent *event) override; // Reimplemented to support vertical orientation.\n};\n\n/***********************************************/\n\n/** @brief \"Open Files\" side bar widget with intelligent tree structure. */\nclass OpenFilesTreeWidget : public QTreeWidget\n{\n  Q_OBJECT\n\n  ActionList      actionList;\n  TabEnvironment *tabEnvironment;\n\npublic:\n  /** @brief Initializes the widget and populates the tree with items from the @a tabEnvironment. */\n  OpenFilesTreeWidget(TabEnvironment *tabEnvironment, ActionList &actionList);\n\n  /** @brief Populates the tree with items from the tabEnvironment. */\n  void populateTree();\n\n  /** @brief Recursively check if an @a item has a \"file\" as child, grandchild, ...\n   *  @return True if a \"file\" is found. */\n  bool hasFileChild(const QTreeWidgetItem *item) const;\n\npublic slots:\n  /** @brief Emits @a fileSelectionChanged(int) signal if another item is selected in the tree. */\n  void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);\n\n  /** @brief Updates the tree if anything changes (file opened/changed/closed/...). */\n  void fileChanged(const QString &caption, const QString &fileName, bool isClean);\n\nprotected:\n  /** @brief Catch clicks on \"folders\" to collapse/expand them instead of selecting them. */\n  void mousePressEvent(QMouseEvent *event);\n\n  /** @brief Create context menu if a file is right-clicked. */\n  void contextMenuEvent(QContextMenuEvent *e);\n\n  void dragEnterEvent (QDragEnterEvent *event);\n  void dragMoveEvent  (QDragMoveEvent  *event);\n  void dropEvent      (QDropEvent      *event);\n\nsignals:\n  /** @brief This signal is emitted if another file is selected in the tree. */\n  void fileSelectionChanged(int index);\n};\n\n/***********************************************/\n\n/** @brief TreeWidgetItem that sorts \"folders\" above \"files\". */\nclass TreeWidgetItem : public QTreeWidgetItem\n{\npublic:\n  TreeWidgetItem(QTreeWidgetItem *parent=nullptr) : QTreeWidgetItem(parent) {}\n  virtual bool operator<(const QTreeWidgetItem &other) const;\n};\n\n/***********************************************/\n\n#endif // __GROOPSGUI__SIDEBAR__\n"
  },
  {
    "path": "gui/mainWindow/tabs.cpp",
    "content": "/***********************************************/\n/**\n* @file tabs.cpp\n*\n* @brief Tab environment.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2011-07-16\n*/\n/***********************************************/\n\n#include <QApplication>\n#include <QSettings>\n#include <QTabWidget>\n#include <QMenu>\n#include <QContextMenuEvent>\n#include <QHeaderView>\n#include <QPushButton>\n#include <QLabel>\n#include <QVBoxLayout>\n#include <QUrl>\n#include <QUndoGroup>\n#include <QDrag>\n#include <QProcess>\n#include <QDebug>\n#include <QFileDialog>\n#include <QMimeData>\n#include <QDesktopServices>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"mainWindow/mainWindow.h\"\n#include \"tabs.h\"\n\n/***********************************************/\n\nTabEnvironment::TabEnvironment(QWidget *parent, ActionList *actionList, QUndoGroup *undoGroup) : QTabWidget(parent)\n{\n  try\n  {\n    TabBar *tabBar = new TabBar(this);\n    setTabBar(tabBar);\n    setMovable(true);\n    setTabsClosable(true);\n    setDocumentMode(true);\n    this->actionList     = *actionList;\n    this->undoGroup      = undoGroup;\n    this->newFileCounter = 0;\n    this->isFullyLoaded  = false;\n\n    QPushButton *addButton = new QPushButton(QIcon(\":/icons/scalable/document-new.svg\"), \"\");\n    addButton->setFlat(true);\n    addButton->resize(tabBar->contentsRect().height(), tabBar->contentsRect().height());\n    addButton->setIconSize(addButton->contentsRect().size()*0.9);\n    setCornerWidget(addButton, Qt::TopRightCorner);\n\n    connect(addButton, SIGNAL(clicked()),              this, SLOT(fileNew()));\n    connect(this,      SIGNAL(currentChanged(int)),    this, SLOT(tabChanged(int)));\n    connect(this,      SIGNAL(tabCloseRequested(int)), this, SLOT(tabClose(int)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTabEnvironment::~TabEnvironment()\n{\n  Tree *tree = currentTree();\n  if(tree)\n  {\n    const Double width = this->width();\n    settings.setValue(\"tree/relativeColumnWidth0\", tree->columnWidth(0)/width);\n    settings.setValue(\"tree/relativeColumnWidth1\", tree->columnWidth(1)/width);\n    settings.setValue(\"tree/relativeColumnWidth2\", tree->columnWidth(2)/width);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nTree *TabEnvironment::currentTree() const\n{\n  return dynamic_cast<Tree*>(currentWidget());\n}\n\n/***********************************************/\n\nvoid TabEnvironment::setCurrentTree(Tree *tree)\n{\n  setCurrentWidget(tree);\n}\n\n/***********************************************/\n\nQVector<Tree*> TabEnvironment::trees() const\n{\n  QVector<Tree*> trees(count());\n  for(int i=0; i<count(); i++)\n    trees[i] = dynamic_cast<Tree*>(widget(i));\n  return trees;\n}\n\n/***********************************************/\n\nTree *TabEnvironment::treeAt(int index) const\n{\n  return dynamic_cast<Tree*>(widget(index));\n}\n\n/***********************************************/\n/***********************************************/\n\nbool TabEnvironment::newTab(const QString &fileName)\n{\n  try\n  {\n    Tree *tree = new Tree(nullptr, &actionList, this);\n\n    bool ok = false;\n    if(fileName.isEmpty())\n      ok = tree->fileNew(QString(\"new%1\").arg(++newFileCounter));\n    else\n      ok = tree->fileOpen(fileName);\n    if(!ok)\n    {\n      delete tree;\n      return false;\n    }\n\n    // copy sections sizes from current tree\n    if(currentTree())\n    {\n      tree->setColumnWidth(0, currentTree()->columnWidth(0));\n      tree->setColumnWidth(1, currentTree()->columnWidth(1));\n      tree->setColumnWidth(2, currentTree()->columnWidth(2));\n    }\n\n    undoGroup->addStack(tree->undoStack);\n    connect(tree, SIGNAL(fileChanged(const QString&, const QString&, bool)), this, SLOT(treeFileChanged(const QString&, const QString&, bool)));\n    connect(tree, SIGNAL(sectionResized(int, int, int)), this, SLOT(treeSectionResized(int, int, int)));\n    setCurrentIndex(insertTab(currentIndex()+1, tree, tree->caption()));\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TabEnvironment::fileOpen(const QString &fileName)\n{\n  try\n  {\n    // no file name -> open file selector\n    if(fileName.isEmpty())\n    {\n      QString defaultName;\n      if(currentTree())\n        defaultName = QFileInfo(currentTree()->fileName()).absolutePath();\n      if(defaultName.isEmpty())\n        defaultName = settings.value(\"files/workingDirectory\", QString(\"../scenario\")).toString();\n      QStringList fileNames = QFileDialog::getOpenFileNames(this, tr(\"Open File - GROOPS\"), defaultName, tr(\"XML files (*.xml)\"));\n      for(auto fileName : fileNames)\n        if(!fileName.isEmpty() && !fileOpen(fileName))\n          return false;\n      return !fileNames.isEmpty();\n    }\n\n    // file is already opened? -> select tab and reOpen\n    for(int i=0; i<count(); i++)\n      if(treeAt(i)->fileName() == QFileInfo(fileName).absoluteFilePath())\n      {\n        setCurrentIndex(i);\n        return fileReOpen();\n      }\n\n    // current tab is new and unchanged -> overwrite\n    if(currentTree() && currentTree()->fileName().isEmpty() && currentTree()->isClean())\n      return currentTree()->fileOpen(fileName);\n\n    // new tab\n    return newTab(fileName);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TabEnvironment::fileReOpen()\n{\n  return currentTree() ? currentTree()->fileOpen(currentTree()->fileName()) : false;\n}\n\n/***********************************************/\n\nbool TabEnvironment::fileClose()\n{\n  try\n  {\n    Tree *tree = currentTree();\n    if(!tree || !tree->okToAbandon())\n      return false;\n    int index = currentIndex();\n    if(count()==1)\n      fileNew();\n    removeTab(index);\n    undoGroup->removeStack(tree->undoStack);\n    tree->deleteLater();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TabEnvironment::fileCloseOther()\n{\n  try\n  {\n    Tree *remainingTree = currentTree();\n    if(remainingTree)\n      for(int i=count(); i-->0;)\n      {\n        setCurrentIndex(i);\n        if(currentTree() != remainingTree)\n          fileClose();\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TabEnvironment::okToAbandon()\n{\n  QStringList fileList;\n  for(int i=0; i<count(); i++)\n  {\n    setCurrentIndex(i);\n    if(!treeAt(i)->fileName().isEmpty())\n      fileList<<treeAt(i)->fileName();\n    if(!treeAt(i)->okToAbandon())\n      return false;\n  }\n\n  settings.setValue(\"openFiles\", fileList);\n  return true;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TabEnvironment::showEvent(QShowEvent *event)\n{\n  if(!isFullyLoaded)\n    for(Tree *tree : trees())\n    {\n      tree->setColumnWidth(0, static_cast<int>(std::round(settings.value(\"tree/relativeColumnWidth0\", 0.2).toDouble()*width())));\n      tree->setColumnWidth(1, static_cast<int>(std::round(settings.value(\"tree/relativeColumnWidth1\", 0.4).toDouble()*width())));\n      tree->setColumnWidth(2, static_cast<int>(std::round(settings.value(\"tree/relativeColumnWidth2\", 0.2).toDouble()*width())));\n    }\n  isFullyLoaded = true;\n  QTabWidget::showEvent(event);\n}\n\n/***********************************************/\n\nvoid TabEnvironment::resizeEvent(QResizeEvent *event)\n{\n  Tree *tree = currentTree();\n  if(tree && (event->oldSize().width() > 0))\n  {\n    const Double scale = 1.*event->size().width()/event->oldSize().width();\n    tree->setColumnWidth(0, static_cast<int>(std::round(scale*tree->columnWidth(0))));\n    tree->setColumnWidth(1, static_cast<int>(std::round(scale*tree->columnWidth(1))));\n    tree->setColumnWidth(2, static_cast<int>(std::round(scale*tree->columnWidth(2))));\n  }\n  QTabWidget::resizeEvent(event);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TabEnvironment::treeSectionResized(int logicalIndex, int /*oldSize*/, int newSize)\n{\n  if(logicalIndex > 2)\n    return;\n  for(Tree *tree : trees())\n  {\n    tree->blockSignals(true);\n    tree->setColumnWidth(logicalIndex, newSize);\n    tree->blockSignals(false);\n  }\n}\n\n/***********************************************/\n\nvoid TabEnvironment::treeFileChanged(const QString &/*caption*/, const QString &/*fileName*/, bool /*isClean*/)\n{\n  for(int i=0; i<count(); i++)\n  {\n    setTabToolTip(i, treeAt(i)->fileName());\n    setTabText   (i, treeAt(i)->caption());\n    setTabIcon   (i, treeAt(i)->isClean() ? QIcon() : QIcon(\":/icons/scalable/document-save.svg\"));\n  }\n\n  if(currentTree())\n    emit fileChanged(currentTree()->caption(), currentTree()->fileName(), currentTree()->isClean());\n}\n\n/***********************************************/\n\nvoid TabEnvironment::tabClose(int index)\n{\n  // deselect all other tabs\n  for(int i=0; i<count(); i++)\n    if(i != index)\n      treeAt(i)->setSelectedItem(nullptr);\n  setCurrentIndex(index);\n  fileClose();\n}\n\n/***********************************************/\n\nvoid TabEnvironment::tabChanged(int index)\n{\n  if(tabBar()->currentIndex() != index)\n    tabBar()->setCurrentIndex(index);\n\n  // deselect all other tabs\n  for(int i=0; i<count(); i++)\n    if(i != index)\n      treeAt(i)->setCurrent(false);\n\n  if(currentTree())\n  {\n    currentTree()->setCurrent(true);\n    undoGroup->setActiveStack(currentTree()->undoStack);\n    emit fileChanged(currentTree()->caption(), currentTree()->fileName(), currentTree()->isClean());\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nTabBar::TabBar(TabEnvironment *tabEnvironment) : QTabBar(tabEnvironment), tabEnvironment(tabEnvironment)\n{\n  setAcceptDrops(true);\n}\n\n/***********************************************/\n\nvoid TabBar::mouseDoubleClickEvent(QMouseEvent */*e*/)\n{\n  tabEnvironment->fileNew();\n}\n\n/***********************************************/\n\nvoid TabBar::contextMenuEvent(QContextMenuEvent *e)\n{\n  int index = tabAt(e->pos());\n  if(index < 0)\n    return;\n  tabEnvironment->setCurrentIndex(index);\n\n  QMenu *contextMenu = new QMenu(this);\n  contextMenu->addAction(tabEnvironment->actionList.fileNewAction);\n  contextMenu->addAction(tabEnvironment->actionList.fileOpenAction);\n  contextMenu->addAction(tabEnvironment->actionList.fileReOpenAction);\n  contextMenu->addAction(tabEnvironment->actionList.fileShowInManagerAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(tabEnvironment->actionList.fileSaveAction);\n  contextMenu->addAction(tabEnvironment->actionList.fileSaveAsAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(tabEnvironment->actionList.fileRunAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(tabEnvironment->actionList.editEnableAllAction);\n  contextMenu->addAction(tabEnvironment->actionList.editDisableAllAction);\n  contextMenu->addAction(tabEnvironment->actionList.editCollapseAllAction);\n  contextMenu->addSeparator();\n  contextMenu->addAction(tabEnvironment->actionList.fileCloseAction);\n  contextMenu->addAction(tabEnvironment->actionList.fileCloseOtherAction);\n  contextMenu->exec(e->globalPos());\n  delete contextMenu;\n}\n\n/***********************************************/\n\nvoid TabBar::dragEnterEvent(QDragEnterEvent *event)\n{\n  try\n  {\n    // file names?\n    if(event->mimeData()->hasUrls())\n      event->acceptProposedAction();\n    else\n      QTabBar::dragEnterEvent(event);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TabBar::dragMoveEvent(QDragMoveEvent *event)\n{\n  try\n  {\n    if(this->geometry().contains(event->pos()))\n    {\n      // hacky way to abort QDrag (may not work on Windows)\n      QKeyEvent esc(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);\n      QApplication::sendEvent(this, &esc);\n      return;\n    }\n\n    // file names?\n    if(event->mimeData()->hasUrls())\n      event->acceptProposedAction();\n    else\n      QTabBar::dragMoveEvent(event);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TabBar::dropEvent(QDropEvent *event)\n{\n  if(event->mimeData()->hasUrls()) // file names?\n  {\n    for(auto &url : event->mimeData()->urls())\n      tabEnvironment->fileOpen(url.toLocalFile());\n    event->acceptProposedAction();\n  }\n  else\n    QTabBar::dropEvent(event);\n}\n\n/***********************************************/\n\nvoid TabBar::mousePressEvent(QMouseEvent *event)\n{\n  if(event->button() == Qt::LeftButton)\n    dragStartPosition = event->pos();\n  QTabBar::mousePressEvent(event);\n}\n\n/***********************************************/\n\nvoid TabBar::mouseMoveEvent(QMouseEvent *event)\n{\n  if(!(event->buttons() & Qt::LeftButton))\n    return;\n\n  // if cursor is within TabBar, call original event handler\n  if(this->geometry().contains(event->pos()))\n  {\n    QTabBar::mouseMoveEvent(event);\n    return;\n  }\n\n  if((event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance())\n    return;\n\n  int index = tabAt(dragStartPosition);\n  if(index < 0)\n    return;\n\n  // Tab is dragged outside of TabBar\n  // --------------------------------\n  tabEnvironment->setCurrentIndex(index);\n  Tree *tree = tabEnvironment->currentTree();\n  if(!tree)\n    return;\n\n  QDrag *drag = new QDrag(this);\n  QMimeData *mimeData = new QMimeData;\n\n  // add file to MIME data\n  QList<QUrl> urls;\n  if(!tree->fileName().isEmpty())\n    urls.push_back(QUrl::fromLocalFile(tree->fileName()));\n  mimeData->setUrls(urls);\n  drag->setMimeData(mimeData);\n\n  // add small picture to mouse cursor\n  QPixmap pixmap(tree->size());\n  tree->render(&pixmap);\n  drag->setPixmap(pixmap.scaled(200,200, Qt::KeepAspectRatio));\n  drag->setHotSpot(QPoint(-20,-20));\n\n  Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction);\n\n  if(dropAction != Qt::IgnoreAction)\n  {\n    QWidget *target = qobject_cast<QWidget*>(drag->target());\n\n    if(target && !tree->fileName().isEmpty())\n    {\n      QProcess *process = new QProcess(this);\n      QString program = QFileInfo(QCoreApplication::applicationFilePath()).fileName();\n      process->startDetached(program, {\"-c\", \"-f\", tree->fileName()});\n    }\n\n    // TabBar refresh after drag requires mouse button release\n    QMouseEvent click(QEvent::MouseButtonRelease, dragStartPosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);\n    QApplication::sendEvent(this, &click);\n\n    // close tab if file is moved (Shift+Drag)\n    Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();\n    if(modifiers == Qt::ShiftModifier)\n      tabEnvironment->fileClose();\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/mainWindow/tabs.h",
    "content": "/***********************************************/\n/**\n* @file tabs.h\n*\n* @brief Tab environment.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2011-07-16\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TABS__\n#define __GROOPSGUI__TABS__\n\n#include <QTabWidget>\n#include <QTabBar>\n#include <QFrame>\n#include <QLabel>\n#include <QSettings>\n#include \"base/importGroops.h\"\n#include \"mainWindow/mainWindow.h\"\n\n/***** TYPES ***********************************/\n\nclass Tree;\n\n/***** CLASS ***********************************/\n\nclass TabEnvironment : public QTabWidget\n{\n  Q_OBJECT\n\n  ActionList  actionList;\n  QSettings   settings;\n  QUndoGroup *undoGroup;\n  int         newFileCounter;\n  bool        isFullyLoaded;\n\n  friend class TabBar;\n\npublic:\n  TabEnvironment(QWidget *parent, ActionList *actionList, QUndoGroup *undoGroup);\n ~TabEnvironment();\n\n  /** @brief Get the current selected tree. */\n  Tree *currentTree() const;\n\n  /** @brief Makes tree the current tree. */\n  void setCurrentTree(Tree *tree);\n\n  /** @brief List of all trees. */\n  QVector<Tree*> trees() const;\n\nprivate:\n  Tree *treeAt(int index) const;\n\n  /** @brief Creates a new tab.\n  * Opens file if @a fileName is given.\n  * @return success? */\n  bool newTab(const QString &fileName);\n\npublic slots:\n  /** @brief Creates a new empty tab.\n  * @return success? */\n  bool fileNew() {return newTab(QString());}\n\n  /** @brief Open the file with @a fileName.\n  * If @a fileName is empty a file selector is opened.\n  * The user is asked to save the old file before if necessary.\n  * @return success? */\n  bool fileOpen(const QString &fileName = QString());\n\n  /** @brief Reload the file.\n  * The user is asked to save the file before if necessary.\n  * @return success? */\n  bool fileReOpen();\n\n  /** @brief Close the current tab.\n  * The user is asked to save the file before if necessary.\n  * @return success? */\n  bool fileClose();\n\n  /** @brief Close all but the current tab.\n  * The user is asked to save the other files before if necessary. */\n  void fileCloseOther();\n\n  /** @brief Is it allowed to close the file?\n  * The user is asked to save the file before if necessary.\n  * @return allowed */\n  bool okToAbandon();\n\nsignals:\n  /** @brief This signal is emitted when tab is changed.\n  * @param caption fileName without path or something like 'newX'.\n  * @param fileName the current file (empty if file is new)\n  * @param isClean no unsaved changes */\n  void fileChanged(const QString &caption, const QString &fileName, bool isClean);\n\nprotected:\n  void showEvent(QShowEvent *event) override;\n  void resizeEvent(QResizeEvent *event) override;\n\nprivate slots:\n  void treeSectionResized(int logicalIndex, int /*oldSize*/, int newSize);\n  void treeFileChanged(const QString &/*caption*/, const QString &/*fileName*/, bool /*isClean*/);\n  void tabClose(int index);\n  void tabChanged(int index);\n};\n\n/***********************************************/\n\n// new tabBar implementation to implement context menu and double click\nclass TabBar : public QTabBar\n{\n  Q_OBJECT\n\npublic:\n  TabBar(TabEnvironment *tabEnvironment);\n\npublic slots:\n  void contextMenuEvent(QContextMenuEvent *e);\n  void mouseDoubleClickEvent(QMouseEvent *e);\n\nprivate:\n  TabEnvironment *tabEnvironment;\n  QPoint dragStartPosition;\n\n  void dragEnterEvent(QDragEnterEvent *event);\n  void dragMoveEvent(QDragMoveEvent *event);\n  void dropEvent(QDropEvent *event);\n  void mousePressEvent(QMouseEvent *event);\n  void mouseMoveEvent(QMouseEvent *event);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/programDialog/programDialog.cpp",
    "content": "/***********************************************/\n/**\n* @file programDialog.cpp\n*\n* @brief Program List Widget and Dialog.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2015-05-15\n*/\n/***********************************************/\n\n#include <QSettings>\n#include <QTreeWidget>\n#include <QTreeWidgetItem>\n#include <QList>\n#include <QLabel>\n#include <QDragEnterEvent>\n#include <QMimeData>\n#include <QDrag>\n#include <QDialogButtonBox>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"programDialog.h\"\n#include \"ui_programDialog.h\"\n\n/***********************************************/\n\nProgramListWidget::ProgramListWidget(QWidget *parent) : QWidget(parent)\n{\n  try\n  {\n    treeWidget               = new TreeWidget(this);\n    lineEdit                 = new QLineEdit(this);\n    QLabel      *label       = new QLabel(\"Filter:\", this);\n    QGridLayout *gridLayout  = new QGridLayout(this);\n\n    gridLayout->addWidget(treeWidget, 0, 0, 1, 2);\n    gridLayout->addWidget(label,      1, 0);\n    gridLayout->addWidget(lineEdit,   1, 1);\n    gridLayout->setContentsMargins(0, 0, 0, gridLayout->spacing());\n\n    // init table\n    // ----------\n    QStringList headerLabel;\n    treeWidget->setHeaderLabels(headerLabel << \"Program\" << \"Comment\" << \"Tags\");\n    treeWidget->hideColumn(2);\n    treeWidget->setColumnWidth(0, settings.value(\"programListWidget/columnWidth\", 200).toInt());\n    treeWidget->setAlternatingRowColors(true);\n    treeWidget->setRootIsDecorated(false);\n    treeWidget->setItemsExpandable(false);\n    treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);\n    treeWidget->setDragEnabled(true);\n    treeWidget->setAcceptDrops(false);\n    treeWidget->setDragDropMode(QAbstractItemView::DragOnly);\n\n    connect(treeWidget, SIGNAL(itemSelectionChanged()),               this, SLOT(itemSelectionChanged()));\n    connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(itemActivated(QTreeWidgetItem*, int)));\n    connect(lineEdit,   SIGNAL(textEdited(QString)),                  this, SLOT(filterChanged(QString)));\n\n    lineEdit->setFocus();\n\n    lineEdit->installEventFilter(this);\n    treeWidget->installEventFilter(this);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nProgramListWidget::ProgramListWidget(Tree *tree, int indexSelected, QWidget *parent) : ProgramListWidget(parent)\n{\n  init(tree, indexSelected);\n}\n\n/***********************************************/\n\nProgramListWidget::~ProgramListWidget()\n{\n  settings.setValue(\"programListWidget/columnWidth\", columnWidth());\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::init(Tree *tree, int indexSelected)\n{\n  try\n  {\n    this->tree = tree;\n\n    // clear list\n    treeWidget->clear();\n\n    // fill list\n    programList = tree->programList();\n    QTreeWidgetItem *selectedItem = nullptr;\n    for(int i=0; i<programList.size(); i++)\n    {\n      QTreeWidgetItem *item = new QTreeWidgetItem();\n      item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);\n      item->setIcon(0, QIcon(\":/icons/scalable/program.svg\"));\n      item->setText(0, programList.at(i)->names.front());\n      item->setText(1, programList.at(i)->annotation);\n      item->setText(2, programList.at(i)->tags.join(\", \"));\n\n      if(!programList.at(i)->tags.size()) // old schema without tags\n        programList.at(i)->tags.push_back(\"Untagged\");\n      QList<QTreeWidgetItem*> tagItems = treeWidget->findItems(programList.at(i)->tags.at(0), Qt::MatchExactly, 0);\n      QTreeWidgetItem *tagItem;\n      if(tagItems.size())\n        tagItem = tagItems.at(0);\n      else\n      {\n        tagItem = new QTreeWidgetItem();\n        tagItem->setText(0, programList.at(i)->tags.at(0));\n        treeWidget->addTopLevelItem(tagItem);\n      }\n      tagItem->addChild(item);\n\n      if(static_cast<int>(i) == indexSelected)\n        selectedItem = item;\n    }\n\n    if(selectedItem)\n    {\n      selectedItem->setSelected(true);\n      treeWidget->setCurrentItem(selectedItem);\n    }\n\n    treeWidget->expandAll();\n\n    filterChanged(lineEdit->text());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::setColumnWidth(int width)\n{\n  treeWidget->setColumnWidth(0, width);\n}\n\n/***********************************************/\n\nint ProgramListWidget::selectedIndex()\n{\n  return treeWidget->getItemIndex(treeWidget->currentItem());\n}\n\n/***********************************************/\n\nbool ProgramListWidget::eventFilter(QObject *obj, QEvent *event)\n{\n  try\n  {\n    if(event->type() == QEvent::KeyPress)\n    {\n      QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);\n      const bool isFilterKey = (!keyEvent->text().isEmpty() || keyEvent->key() == Qt::Key_Left   || keyEvent->key() == Qt::Key_Right\n                                                            || keyEvent->key() == Qt::Key_Delete || keyEvent->key() == Qt::Key_Backspace);\n      if(obj != treeWidget && !isFilterKey)\n      {\n        treeWidget->setFocus();\n        return QApplication::sendEvent(treeWidget, keyEvent);\n      }\n      else if(obj != lineEdit && isFilterKey)\n      {\n        lineEdit->setFocus();\n        return QApplication::sendEvent(lineEdit, keyEvent);\n      }\n    }\n\n    return QWidget::eventFilter(obj, event);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::itemActivated(QTreeWidgetItem *item, int /*column*/)\n{\n  try\n  {\n    if(!item || item->childCount() || item->isHidden())\n      return;\n    emit programSelected(treeWidget->getItemIndex(item));\n    emit addProgram(programList.at(treeWidget->getItemIndex(item))->names.front());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::filterChanged(QString text)\n{\n  try\n  {\n    QStringList filterStrings = text.split(\" \");\n    if(!filterStrings.size())\n      return;\n\n    // find items containing the first filter string\n    QList<QTreeWidgetItem*> itemsFound;\n    itemsFound.append(treeWidget->findItems(filterStrings.at(0), Qt::MatchContains | Qt::MatchRecursive, 0));\n    itemsFound.append(treeWidget->findItems(filterStrings.at(0), Qt::MatchContains | Qt::MatchRecursive, 1));\n    itemsFound.append(treeWidget->findItems(filterStrings.at(0), Qt::MatchContains | Qt::MatchRecursive, 2));\n    itemsFound = QSet<QTreeWidgetItem*>(itemsFound.begin(), itemsFound.end()).values();\n\n    // remove items that don't contain further filter strings\n    for(int i=1; i<filterStrings.size(); i++)\n      for(int j=itemsFound.size(); j-->0;)\n        if(!itemsFound.at(j)->text(0).contains(filterStrings.at(i), Qt::CaseInsensitive) && !itemsFound.at(j)->text(1).contains(filterStrings.at(i), Qt::CaseInsensitive))\n          itemsFound.removeAt(j);\n\n    // hide all items\n    for(QTreeWidgetItemIterator it(treeWidget); *it; it++)\n      (*it)->setHidden(true);\n\n    // show found items\n    for(int i=0; i<itemsFound.size(); i++)\n    {\n      itemsFound.at(i)->setHidden(false);\n      if(itemsFound.at(i)->parent())\n        itemsFound.at(i)->parent()->setHidden(false);\n    }\n\n    itemSelectionChanged();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::itemSelectionChanged()\n{\n  try\n  {\n    QTreeWidgetItem *item = treeWidget->currentItem();\n    emit selectionChanged(item && !item->childCount() && !item->isHidden());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nint ProgramListWidget::TreeWidget::getItemIndex(QTreeWidgetItem *item)\n{\n  try\n  {\n    if(!item)\n      return -1;\n    QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::NoChildren); // tag items excluded\n    for(int index=0; *it; index++, it++)\n      if(*it == item)\n        return index;\n    return -1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::TreeWidget::mousePressEvent(QMouseEvent *event)\n{\n  try\n  {\n    if(event->button() == Qt::LeftButton)\n      dragStartPosition = event->pos();\n    QTreeWidget::mousePressEvent(event);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid ProgramListWidget::TreeWidget::mouseMoveEvent(QMouseEvent *event)\n{\n  try\n  {\n    // use original event handler if it is not a movement with pressed left mouse button starting over an item\n    QTreeWidgetItem *item = itemAt(event->pos());\n    if((!(event->buttons() & Qt::LeftButton)) || ((event->pos()-dragStartPosition).manhattanLength() < QApplication::startDragDistance()) ||\n       !item || (item && item->childCount()))\n    {\n      QTreeWidget::mouseMoveEvent(event);\n      return;\n    }\n\n    // create xml data\n    QString xmlData;\n    int index = getItemIndex(item);\n    if(index >= 0 && index < static_cast<int>(programListWidget->programList.size()))\n    {\n      TreeElement *element = TreeElementProgram::newTreeElement(programListWidget->tree, nullptr, programListWidget->programList.at(index), \"\", XmlNodePtr(nullptr), true/*fillWithDefaults*/);\n      XmlNodePtr xmlNode = XmlNodePtr(new XmlNode(\"program\"));\n      writeAttribute(xmlNode, \"xsdType\", \"programType\");\n      xmlNode->addChild(element->createXmlTree());\n\n      QTextStream stream(&xmlData, QIODevice::WriteOnly);\n      XmlNode::write(stream, xmlNode);\n    }\n\n    // create mime data\n    QMimeData *mimeData = new QMimeData;\n    mimeData->setData(\"application/x-groops\", xmlData.toUtf8());\n    if(mimeData == nullptr)\n    {\n      QTreeWidget::mouseMoveEvent(event);\n      return;\n    }\n\n    // perform drag\n    QDrag *drag = new QDrag(viewport());\n    drag->setMimeData(mimeData);\n    drag->exec(Qt::MoveAction|Qt::CopyAction);\n\n    event->accept();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nProgramDialog::ProgramDialog(TreeElementProgram *treeElement, QWidget *parent) : QDialog(parent), ui(new Ui::ProgramDialog)\n{\n  try\n  {\n    ui->setupUi(this);\n    this->treeElement = treeElement;\n\n    // restore size of window\n    // ----------------------\n    QRect parentRect(parentWidget()->mapToGlobal(QPoint(0, 0)), parentWidget()->size());\n    resize(settings.value(\"programDialog/size\", size()).toSize());\n    move(settings.value(\"programDialog/position\", QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), parentRect).topLeft()).toPoint());\n\n    programListWidget = new ProgramListWidget(treeElement->tree, treeElement->selectedIndex(), this);\n    programListWidget->setColumnWidth(settings.value(\"programDialog/columnWidth\", 350).toInt());\n    ui->verticalLayout->addWidget(programListWidget);\n\n    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);\n    ui->verticalLayout->addWidget(buttonBox);\n\n    connect(programListWidget, SIGNAL(selectionChanged(bool)), buttonBox->button(QDialogButtonBox::Ok), SLOT(setEnabled(bool)));\n    connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);\n    connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);\n    connect(programListWidget, SIGNAL(programSelected(int)), this, SLOT(programSelected(int)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nProgramDialog::~ProgramDialog()\n{\n  settings.setValue(\"programDialog/position\",    pos());\n  settings.setValue(\"programDialog/size\",        size());\n  settings.setValue(\"programDialog/columnWidth\", programListWidget->columnWidth());\n\n  delete ui;\n}\n\n/***********************************************/\n\nvoid ProgramDialog::programSelected(int index)\n{\n  treeElement->changeSelectedIndex(index);\n  QDialog::accept();\n}\n\n/***********************************************/\n\nvoid ProgramDialog::accept()\n{\n  int index = programListWidget->selectedIndex();\n  if(index >= 0)\n    programSelected(index);\n}\n\n\n/***********************************************/\n\nvoid ProgramDialog::changeEvent(QEvent *e)\n{\n  QDialog::changeEvent(e);\n  switch(e->type())\n  {\n    case QEvent::LanguageChange:\n      ui->retranslateUi(this);\n      break;\n    default:\n      break;\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/programDialog/programDialog.h",
    "content": "/***********************************************/\n/**\n* @file programDialog.h\n*\n* @brief Program List Widget and Dialog.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2015-05-15\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__PROGRAMDIALOG__\n#define __GROOPSGUI__PROGRAMDIALOG__\n\n#include <QWidget>\n#include <QDialog>\n#include <QList>\n#include <QTreeWidget>\n#include <QLineEdit>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class ProgramDialog;\n}\n\nclass TreeElementProgram;\n\n/***** CLASS ***********************************/\n\nclass ProgramListWidget : public QWidget\n{\n  Q_OBJECT\n\n  // ----------------------------------\n  class TreeWidget : public QTreeWidget\n  {\n    ProgramListWidget *programListWidget;\n    QPoint             dragStartPosition;\n\n    void mousePressEvent(QMouseEvent *event);\n    void mouseMoveEvent (QMouseEvent *event);\n\n  public:\n    TreeWidget(ProgramListWidget *parent) : QTreeWidget(parent), programListWidget(parent) {}\n\n    int getItemIndex(QTreeWidgetItem *item);\n  };\n  friend class TreeWidget;\n  // ----------------------------------\n\n  QSettings            settings;\n  TreeWidget          *treeWidget;\n  QLineEdit           *lineEdit;\n  QList<XsdElementPtr> programList;\n  Tree                *tree;\n\npublic:\n  ProgramListWidget(QWidget *parent=nullptr);\n  ProgramListWidget(Tree *tree, int indexSelected=0, QWidget *parent=nullptr);\n ~ProgramListWidget();\n\n  void init(Tree *tree, int indexSelected=0);\n  int  columnWidth() const {return treeWidget ? treeWidget->columnWidth(0) : 350;}\n  void setColumnWidth(int width);\n  int  selectedIndex();\n  int  programCount() {return programList.size();}\n\nprotected:\n  bool eventFilter(QObject *obj, QEvent *event);\n\nsignals:\n  void addProgram(const QString &name);\n  void programSelected(int index);\n  void selectionChanged(bool isProgramSelected);\n\npublic slots:\n  void itemActivated(QTreeWidgetItem *item, int column);\n  void filterChanged(QString text);\n  void itemSelectionChanged();\n};\n\n/***********************************************/\n\nclass ProgramDialog : public QDialog\n{\n  Q_OBJECT\n\n  Ui::ProgramDialog  *ui;\n  QSettings           settings;\n  TreeElementProgram *treeElement;\n  ProgramListWidget  *programListWidget;\n\npublic:\n  ProgramDialog(TreeElementProgram *treeElement, QWidget *parent=nullptr);\n ~ProgramDialog();\n\npublic slots:\n  void programSelected(int index);\n  void accept();\n\nprotected:\n  void changeEvent(QEvent *e);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/programDialog/programDialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>ProgramDialog</class>\n <widget class=\"QDialog\" name=\"ProgramDialog\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>700</width>\n    <height>500</height>\n   </rect>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>500</width>\n    <height>300</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Programs - GROOPS</string>\n  </property>\n  <property name=\"sizeGripEnabled\">\n   <bool>true</bool>\n  </property>\n  <layout class=\"QVBoxLayout\" name=\"verticalLayout\"/>\n </widget>\n <resources/>\n <connections/>\n <slots>\n  <slot>itemActivated(QTreeWidgetItem *, int)</slot>\n </slots>\n</ui>\n"
  },
  {
    "path": "gui/resources/LICENSE_Apache2",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "gui/resources/README.md",
    "content": "## Icons used in GROOPS GUI\n\nWe list external icons contained in the GROOPS repository with references and licenses here.\n\n### Google's Material design icons\n\n* Reference: https://github.com/google/material-design-icons\n* Files: `scalable/*` except `groops.svg`\n* License: [Apache License 2.0](https://github.com/groops-devs/groops/blob/main/gui/resources/LICENSE_Apache2)\n* Modifications:\n  * All icons have been recolored.\n  * `document-save-as.svg`: A pen has been added.\n  * `element-mustset.svg`, `element-mustset-unbounded.svg`, `element-mustset-unbounded-disabled.svg`: A star has been added.\n"
  },
  {
    "path": "gui/resources/icons.qrc",
    "content": "<RCC>\n    <qresource prefix=\"/icons\">\n        <file>scalable/application-exit.svg</file>\n        <file>scalable/document-collapse.svg</file>\n        <file>scalable/document-new.svg</file>\n        <file>scalable/document-open-recent.svg</file>\n        <file>scalable/document-open.svg</file>\n        <file>scalable/document-save-as.svg</file>\n        <file>scalable/document-save.svg</file>\n        <file>scalable/edit-add.svg</file>\n        <file>scalable/edit-copy.svg</file>\n        <file>scalable/edit-cut.svg</file>\n        <file>scalable/edit-delete.svg</file>\n        <file>scalable/edit-disable.svg</file>\n        <file>scalable/edit-enable.svg</file>\n        <file>scalable/edit-find-replace.svg</file>\n        <file>scalable/edit-paste.svg</file>\n        <file>scalable/edit-redo.svg</file>\n        <file>scalable/edit-undo.svg</file>\n        <file>scalable/help-about.svg</file>\n        <file>scalable/help-contents.svg</file>\n        <file>scalable/link.svg</file>\n        <file>scalable/link-broken.svg</file>\n        <file>scalable/link-disabled.svg</file>\n        <file>scalable/loop-remove.svg</file>\n        <file>scalable/loop-set.svg</file>\n        <file>scalable/run.svg</file>\n        <file>scalable/settings.svg</file>\n        <file>scalable/view-refresh.svg</file>\n        <file>scalable/warning.svg</file>\n        <file>scalable/element-comment.svg</file>\n        <file>scalable/element-unbounded.svg</file>\n        <file>scalable/element.svg</file>\n        <file>scalable/element-mustset.svg</file>\n        <file>scalable/element-mustset-unbounded.svg</file>\n        <file>scalable/element-disabled.svg</file>\n        <file>scalable/element-unbounded-disabled.svg</file>\n        <file>scalable/element-unknown-disabled.svg</file>\n        <file>scalable/element-unknown.svg</file>\n        <file>scalable/program-disabled.svg</file>\n        <file>scalable/program.svg</file>\n        <file>scalable/down.svg</file>\n        <file>scalable/up.svg</file>\n        <file>scalable/edit-comment.svg</file>\n        <file>scalable/edit-rename.svg</file>\n        <file>scalable/text-xml.svg</file>\n        <file>scalable/folder.svg</file>\n        <file>scalable/element-mustset-unbounded-disabled.svg</file>\n        <file>scalable/condition-remove.svg</file>\n        <file>scalable/condition-set.svg</file>\n        <file>scalable/groops.svg</file>\n        <file>scalable/ignore.svg</file>\n        <file>scalable/open-externally.svg</file>\n    </qresource>\n</RCC>\n"
  },
  {
    "path": "gui/settingsDialog/settingsCommandDialog.cpp",
    "content": "/***********************************************/\n/**\n* @file settingsCommandDialog.h\n*\n* @brief Dialog to set up commands.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-13\n*/\n/***********************************************/\n\n#include \"ui_settingsCommandDialog.h\"\n#include <QtDebug>\n#include <QSettings>\n#include <QList>\n#include <QAbstractButton>\n#include <QDropEvent>\n#include <QScreen>\n#include \"base/importGroops.h\"\n#include \"settingsCommandDialog.h\"\n\n/***********************************************/\n\nSettingsCommandDialog::SettingsCommandDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsCommandDialog)\n{\n  try\n  {\n    ui->setupUi(this);\n\n    // restore size of window\n    // ----------------------\n    setMinimumSize(QGuiApplication::primaryScreen()->size()/4);\n    QRect parentRect(parentWidget()->mapToGlobal(QPoint(0, 0)), parentWidget()->size());\n    resize(settings.value(\"settingsCommandDialog/size\", minimumSizeHint()).toSize());\n    move(settings.value(\"settingsCommandDialog/position\", QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), parentRect).topLeft()).toPoint());\n\n    // commands\n    // --------\n    QStringList labelList, commandList;\n    readCommandList(labelList, commandList);\n    int commandIndex = settings.value(\"execute/commandIndex\", int(0)).toInt();\n\n    // init table\n    // ----------\n    QStringList headerLable;\n    ui->table->setColumnCount(2);\n    ui->table->setRowCount(labelList.size()+1);\n    ui->table->horizontalHeader()->setStretchLastSection(true);\n    ui->table->setColumnWidth(0, settings.value(\"settingsCommandDialog/columnWidth\", int(200)).toInt());\n    ui->table->setHorizontalHeaderLabels(headerLable << \"Label\" << \"Command\");\n    ui->table->setSelectionMode(QAbstractItemView::SingleSelection);\n    ui->table->setSelectionBehavior(QAbstractItemView::SelectRows);\n\n    for(int i=0; i<labelList.size();i++)\n      insertItem(i, labelList[i], commandList[i]);\n    insertItem(labelList.size(), \"\", \"\");\n    ui->table->setCurrentCell(commandIndex, 1);\n\n    connect(ui->table,        SIGNAL(cellChanged(int, int)),     this, SLOT(tableCellChanged(int, int)));\n    connect(ui->stdButtonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(clickedStdBox(QAbstractButton*)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nSettingsCommandDialog::~SettingsCommandDialog()\n{\n  delete ui;\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::readCommandList(QStringList &labelList, QStringList &commandList)\n{\n  try\n  {\n    QSettings settings;\n    labelList    = settings.value(\"execute/commandLabels\").toStringList();\n    commandList  = settings.value(\"execute/commands\").toStringList();\n    if(labelList.size() != commandList.size())\n      throw(Exception(\"size mismatch between command labels and commands\"));\n    if(labelList.isEmpty())\n    {\n      labelList<<\"groops (Windows)\";                 commandList<<\"cd /d %w && groops.exe %f\";\n      labelList<<\"groops (KDE)\";                     commandList<<\"konsole --workdir %w -e bash -ic \\\"groops %f; bash\\\"\";\n      labelList<<\"groops (GNOME)\";                   commandList<<\"gnome-terminal --working-directory=%w -x bash -ic \\\"groops %f; bash\\\"\";\n      labelList<<\"groopsMPI (Windows, 4 processes)\"; commandList<<\"cd /d %w && mpiexec /genv OMP_NUM_THREADS 1 -n 4 groopsMPI.exe %f\";\n      labelList<<\"groopsMPI (KDE, 4 processes)\";     commandList<<\"konsole --workdir %w -e bash -ic \\\"OMP_NUM_THREADS=1 mpiexec -x OMP_NUM_THREADS -n 4 groopsMPI %f; bash\\\"\";\n      labelList<<\"groopsMPI (GNOME, 4 processes)\";   commandList<<\"gnome-terminal --working-directory=%w -x bash -ic \\\"OMP_NUM_THREADS=1 mpiexec -x OMP_NUM_THREADS -n 4 groopsMPI %f; bash\\\"\";\n      settings.setValue(\"execute/commandLabels\", labelList);\n      settings.setValue(\"execute/commands\",      commandList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::insertItem(int row, const QString &label, const QString &command)\n{\n  try\n  {\n    QTableWidgetItem *item1 = new QTableWidgetItem(label);\n    QTableWidgetItem *item2 = new QTableWidgetItem(command);\n    item1->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);\n    item2->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);\n    ui->table->setItem(row, 0, item1);\n    ui->table->setItem(row, 1, item2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::clickedUp()\n{\n  try\n  {\n    int index = ui->table->currentRow();\n    if((index<1) || (index >= ui->table->rowCount()-1))\n      return;\n\n    QString label, command;\n    if(ui->table->item(index, 0)) label   = ui->table->item(index, 0)->text();\n    if(ui->table->item(index, 1)) command = ui->table->item(index, 1)->text();\n\n    ui->table->removeRow(index);\n    ui->table->insertRow(index-1);\n    insertItem(index-1, label, command);\n    ui->table->setCurrentCell(index-1, 1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::clickedDown()\n{\n  try\n  {\n    int index = ui->table->currentRow();\n    if((index<0) || (index >= ui->table->rowCount()-2))\n      return;\n\n    QString label, command;\n    if(ui->table->item(index, 0)) label   = ui->table->item(index, 0)->text();\n    if(ui->table->item(index, 1)) command = ui->table->item(index, 1)->text();\n\n    ui->table->removeRow(index);\n    ui->table->insertRow(index+1);\n    insertItem(index+1, label, command);\n    ui->table->setCurrentCell(index+1, 1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::clickedApply()\n{\n  try\n  {\n    QStringList labelList, commandList;\n    for(int i=0; i<ui->table->rowCount()-1; i++)\n    {\n      QString label, command;\n      if(ui->table->item(i, 0)) label   = ui->table->item(i, 0)->text();\n      if(ui->table->item(i, 1)) command = ui->table->item(i, 1)->text();\n\n      if((!label.isEmpty()) || (!command.isEmpty()))\n      {\n        labelList.append(label);\n        commandList.append(command);\n      }\n      else\n        ui->table->removeRow(i--);\n    }\n    int commandIndex = ui->table->currentRow();\n\n    settings.setValue(\"execute/commandLabels\",             labelList);\n    settings.setValue(\"execute/commands\",                  commandList);\n    settings.setValue(\"execute/commandIndex\",              commandIndex);\n    settings.setValue(\"settingsCommandDialog/position\",    pos());\n    settings.setValue(\"settingsCommandDialog/size\",        size());\n    settings.setValue(\"settingsCommandDialog/columnWidth\", ui->table->columnWidth(0));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::clickedStdBox(QAbstractButton *button)\n{\n  try\n  {\n    switch(ui->stdButtonBox->standardButton(button))\n    {\n      case QDialogButtonBox::Ok:\n        clickedApply();\n        accept();\n        break;\n      case QDialogButtonBox::Apply:\n        clickedApply();\n        break;\n      case QDialogButtonBox::Cancel:\n        reject();\n        break;\n      default:\n        qWarning(\"Unknown button clicked\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::tableCellChanged(int /*row*/, int /*column*/)\n{\n  try\n  {\n    QString label, command;\n    int rows  = ui->table->rowCount();\n    if(ui->table->item(rows-1, 0)) label   = ui->table->item(rows-1, 0)->text();\n    if(ui->table->item(rows-1, 1)) command = ui->table->item(rows-1, 1)->text();\n\n    if((!label.isEmpty()) || (!command.isEmpty()))\n    {\n      ui->table->insertRow(rows);\n      insertItem(rows, \"\", \"\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsCommandDialog::changeEvent(QEvent *e)\n{\n  QDialog::changeEvent(e);\n  switch(e->type())\n  {\n    case QEvent::LanguageChange:\n      ui->retranslateUi(this);\n      break;\n    default:\n      break;\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/settingsDialog/settingsCommandDialog.h",
    "content": "/***********************************************/\n/**\n* @file settingsCommandDialog.h\n*\n* @brief Dialog to set up commands.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-13\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__SETTINGSCOMMANDDIALOG__\n#define __GROOPSGUI__SETTINGSCOMMANDDIALOG__\n\n#include <QDialog>\n#include <QSettings>\n#include \"base/importGroops.h\"\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class SettingsCommandDialog;\n}\n\nclass QAbstractButton;\n\n/***** CLASS ***********************************/\n\nclass SettingsCommandDialog : public QDialog\n{\n  Q_OBJECT\n\n  Ui::SettingsCommandDialog *ui;\n  QSettings                  settings;\n\n  void insertItem(int row, const QString &label, const QString &command);\n\npublic:\n  SettingsCommandDialog(QWidget *parent=nullptr);\n ~SettingsCommandDialog();\n\n static void readCommandList(QStringList &lableList, QStringList &commandList);\n\npublic slots:\n  void clickedUp();\n  void clickedDown();\n  void clickedApply();\n  void clickedStdBox(QAbstractButton *button);\n\nprivate slots:\n  void tableCellChanged(int row, int column);\n\nprotected:\n  void changeEvent(QEvent *e);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/settingsDialog/settingsCommandDialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>SettingsCommandDialog</class>\n <widget class=\"QDialog\" name=\"SettingsCommandDialog\">\n  <property name=\"windowModality\">\n   <enum>Qt::ApplicationModal</enum>\n  </property>\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>700</width>\n    <height>300</height>\n   </rect>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>500</width>\n    <height>300</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Commands - GROOPS</string>\n  </property>\n  <property name=\"sizeGripEnabled\">\n   <bool>true</bool>\n  </property>\n  <layout class=\"QVBoxLayout\" name=\"verticalLayout\">\n   <item>\n    <widget class=\"QTableWidget\" name=\"table\">\n     <property name=\"contextMenuPolicy\">\n      <enum>Qt::ActionsContextMenu</enum>\n     </property>\n     <property name=\"selectionMode\">\n      <enum>QAbstractItemView::SingleSelection</enum>\n     </property>\n     <property name=\"selectionBehavior\">\n      <enum>QAbstractItemView::SelectRows</enum>\n     </property>\n     <attribute name=\"horizontalHeaderStretchLastSection\">\n      <bool>true</bool>\n     </attribute>\n    </widget>\n   </item>\n   <item>\n    <layout class=\"QHBoxLayout\" name=\"horizontalLayout\">\n     <item>\n      <widget class=\"QPushButton\" name=\"upButton\">\n       <property name=\"text\">\n        <string>&amp;Up</string>\n       </property>\n       <property name=\"icon\">\n        <iconset resource=\"../resources/icons.qrc\">\n         <normaloff>:/icons/scalable/up.svg</normaloff>:/icons/scalable/up.svg</iconset>\n       </property>\n      </widget>\n     </item>\n     <item>\n      <widget class=\"QPushButton\" name=\"downButton\">\n       <property name=\"text\">\n        <string>Down</string>\n       </property>\n       <property name=\"icon\">\n        <iconset resource=\"../resources/icons.qrc\">\n         <normaloff>:/icons/scalable/down.svg</normaloff>:/icons/scalable/down.svg</iconset>\n       </property>\n      </widget>\n     </item>\n     <item>\n      <spacer name=\"horizontalSpacer\">\n       <property name=\"orientation\">\n        <enum>Qt::Horizontal</enum>\n       </property>\n       <property name=\"sizeHint\" stdset=\"0\">\n        <size>\n         <width>0</width>\n         <height>0</height>\n        </size>\n       </property>\n      </spacer>\n     </item>\n     <item>\n      <widget class=\"QDialogButtonBox\" name=\"stdButtonBox\">\n       <property name=\"orientation\">\n        <enum>Qt::Horizontal</enum>\n       </property>\n       <property name=\"standardButtons\">\n        <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>\n       </property>\n      </widget>\n     </item>\n    </layout>\n   </item>\n  </layout>\n </widget>\n <resources>\n  <include location=\"../resources/icons.qrc\"/>\n </resources>\n <connections>\n  <connection>\n   <sender>stdButtonBox</sender>\n   <signal>clicked(QAbstractButton*)</signal>\n   <receiver>SettingsCommandDialog</receiver>\n   <slot>clickedStdBox(QAbstractButton*)</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>upButton</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsCommandDialog</receiver>\n   <slot>clickedUp()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>downButton</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsCommandDialog</receiver>\n   <slot>clickedDown()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n <slots>\n  <slot>clickedUp()</slot>\n  <slot>clickedDown()</slot>\n  <slot>clickedApply()</slot>\n  <slot>clickedStdBox(QAbstractButton*)</slot>\n </slots>\n</ui>\n"
  },
  {
    "path": "gui/settingsDialog/settingsPathDialog.cpp",
    "content": "/***********************************************/\n/**\n* @file settingsPathDialog.cpp\n*\n* @brief Dialog to set up default paths and files.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-13\n*/\n/***********************************************/\n\n#include \"ui_settingsPathDialog.h\"\n#include <QtDebug>\n#include <QSettings>\n#include <QFileDialog>\n#include <QMessageBox>\n#include <QSysInfo>\n#include <QScreen>\n#include \"base/importGroops.h\"\n#include \"base/schema.h\"\n#include \"settingsPathDialog.h\"\n\n/***********************************************/\n\nSettingsPathDialog::SettingsPathDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsPathDialog)\n{\n  try\n  {\n    ui->setupUi(this);\n\n    // restore size of window\n    // ----------------------\n    setMinimumSize(QGuiApplication::primaryScreen()->size()/4);\n    QRect parentRect(parentWidget()->mapToGlobal(QPoint(0, 0)), parentWidget()->size());\n    resize(settings.value(\"settingsPathDialog/size\", minimumSizeHint()).toSize());\n    move(settings.value(\"settingsPathDialog/position\", QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), parentRect).topLeft()).toPoint());\n\n    connect(ui->listSchema->model(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(schemaListChanged()));\n    connect(ui->listSchema->model(), SIGNAL(rowsRemoved (QModelIndex,int,int)), this, SLOT(schemaListChanged()));\n\n    const QString baseDir(QSysInfo::productType() == \"windows\" ? \"C:\" : QDir::homePath());\n    const QString schemaFile = settings.value(\"files/schemaFile\", QFileInfo(baseDir+\"/groops/groops.xsd\").absoluteFilePath()).toString();\n    ui->listSchema->addItems(settings.value(\"files/schemaFiles\", QStringList(schemaFile)).toStringList());\n    ui->editTemplateFile->setText(settings.value(\"files/templateFile\").toString());\n    ui->editWorkingDir->setText(settings.value(\"files/workingDirectory\", QDir(baseDir+\"/groops/scenario\").absolutePath()).toString());\n    ui->editDocumentationDir->setText(settings.value(\"files/documentationDirectory\", QDir(baseDir+\"/groops/docs/html\").absolutePath()).toString());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nSettingsPathDialog::~SettingsPathDialog()\n{\n  delete ui;\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::schemaListChanged()\n{\n   ui->buttonSchemaChange->setEnabled(ui->listSchema->count() > 0);\n   ui->buttonSchemaRemove->setEnabled(ui->listSchema->count() > 1);\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedSchemaChange()\n{\n  QListWidgetItem *item = ui->listSchema->currentItem();\n  if(!item)\n    return;\n\n  QString name = QFileDialog::getOpenFileName(this, tr(\"Change Schema File - GROOPS\"),\n                                              item->text(), tr(\"XML Schema files (*.xsd)\"));\n  if(!name.isEmpty() && !ui->listSchema->findItems(name, Qt::MatchFixedString|Qt::MatchCaseSensitive).size())\n  {\n    // validate XSD schema file\n    Schema schema;\n    if(!schema.readFile(name))\n    {\n      QMessageBox::StandardButton button =\n        QMessageBox::critical(this , tr(\"Change Schema File - GROOPS\"),\n                              tr(\"File '%1' seems not to be a valid XSD schema. Try another file?\").arg(name),\n                              QMessageBox::Ok | QMessageBox::Cancel);\n      if(button == QMessageBox::Ok)\n        clickedSchemaChange();\n      return;\n    }\n\n    item->setText(name);\n    ui->listSchema->sortItems();\n    item->setSelected(true);\n  }\n}\n\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedSchemaAdd()\n{\n  QString name = QFileDialog::getOpenFileName(this, tr(\"Add Schema File - GROOPS\"),\n                                              ui->listSchema->currentItem() ? ui->listSchema->currentItem()->text() : \"groops.xsd\", tr(\"XML Schema files (*.xsd)\"));\n  if(!name.isEmpty() && !ui->listSchema->findItems(name, Qt::MatchFixedString|Qt::MatchCaseSensitive).size())\n  {\n    // validate XSD schema file\n    Schema schema;\n    if(!schema.readFile(name))\n    {\n      QMessageBox::StandardButton button =\n        QMessageBox::critical(this , tr(\"Add Schema File - GROOPS\"),\n                              tr(\"File '%1' seems not to be a valid XSD schema. Try another file?\").arg(name),\n                              QMessageBox::Ok | QMessageBox::Cancel);\n      if(button == QMessageBox::Ok)\n        clickedSchemaAdd();\n      return;\n    }\n\n    ui->listSchema->addItem(name);\n    ui->listSchema->sortItems();\n    ui->listSchema->findItems(name, Qt::MatchFixedString|Qt::MatchCaseSensitive).at(0)->setSelected(true);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedSchemaRemove()\n{\n  qDeleteAll(ui->listSchema->selectedItems());\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedTemplateFile()\n{\n  QString name = QFileDialog::getOpenFileName(this, tr(\"Choose System Directory - GROOPS\"), ui->editTemplateFile->text(), tr(\"XML files (*.xml)\"));\n  if(!name.isEmpty())\n    ui->editTemplateFile->setText(name);\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedWorkingDir()\n{\n  QString name = QFileDialog::getExistingDirectory(this, tr(\"Choose Working Directory - GROOPS\"), ui->editWorkingDir->text());\n  if(!name.isEmpty())\n    ui->editWorkingDir->setText(name);\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedDocumentationDir()\n{\n  QString name = QFileDialog::getExistingDirectory(this, tr(\"Choose Documentation Directory - GROOPS\"), ui->editDocumentationDir->text());\n  if(!name.isEmpty())\n    ui->editDocumentationDir->setText(name);\n}\n\n\n/***********************************************/\n\nvoid SettingsPathDialog::clickedOk()\n{\n  try\n  {\n    QStringList schemaFiles;\n    for(int i=0; i<ui->listSchema->count(); i++)\n      schemaFiles.append(ui->listSchema->item(i)->text());\n    if(!schemaFiles.size())\n    {\n      QMessageBox::warning(this , tr(\"Path Settings - GROOPS\"), tr(\"No XML Schema Files specified. At least one schema is required.\"), QMessageBox::Ok);\n      return;\n    }\n\n    settings.setValue(\"files/schemaFile\",             schemaFiles.at(0));\n    settings.setValue(\"files/schemaFiles\",            schemaFiles);\n    settings.setValue(\"files/templateFile\",           ui->editTemplateFile->text());\n    settings.setValue(\"files/workingDirectory\",       ui->editWorkingDir->text());\n    settings.setValue(\"files/documentationDirectory\", ui->editDocumentationDir->text());\n    settings.setValue(\"settingsPathDialog/position\",  pos());\n    settings.setValue(\"settingsPathDialog/size\",      size());\n    accept();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid SettingsPathDialog::changeEvent(QEvent *e)\n{\n  QDialog::changeEvent(e);\n  switch(e->type())\n  {\n    case QEvent::LanguageChange:\n      ui->retranslateUi(this);\n      break;\n    default:\n      break;\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/settingsDialog/settingsPathDialog.h",
    "content": "/***********************************************/\n/**\n* @file settingsPathDialog.h\n*\n* @brief Dialog to set up default paths and files.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-13\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__SETTINGSPATHDIALOG__\n#define __GROOPSGUI__SETTINGSPATHDIALOG__\n\n#include <QDialog>\n#include <QSettings>\n#include \"base/importGroops.h\"\n\n/***** TYPES ***********************************/\n\nnamespace Ui\n{\n  class SettingsPathDialog;\n}\n\n/***** CLASS ***********************************/\n\nclass SettingsPathDialog : public QDialog\n{\n  Q_OBJECT\n\n  Ui::SettingsPathDialog *ui;\n  QSettings               settings;\n\npublic:\n  SettingsPathDialog(QWidget *parent=nullptr);\n ~SettingsPathDialog();\n\npublic slots:\n  void clickedSchemaChange();\n  void clickedSchemaAdd();\n  void clickedSchemaRemove();\n  void clickedTemplateFile();\n  void clickedWorkingDir();\n  void clickedDocumentationDir();\n  void clickedOk();\n  void schemaListChanged();\n\nprotected:\n  void changeEvent(QEvent *e);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/settingsDialog/settingsPathDialog.ui",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ui version=\"4.0\">\n <class>SettingsPathDialog</class>\n <widget class=\"QDialog\" name=\"SettingsPathDialog\">\n  <property name=\"geometry\">\n   <rect>\n    <x>0</x>\n    <y>0</y>\n    <width>600</width>\n    <height>300</height>\n   </rect>\n  </property>\n  <property name=\"minimumSize\">\n   <size>\n    <width>600</width>\n    <height>300</height>\n   </size>\n  </property>\n  <property name=\"windowTitle\">\n   <string>Default paths and files - GROOPS</string>\n  </property>\n  <property name=\"sizeGripEnabled\">\n   <bool>true</bool>\n  </property>\n  <layout class=\"QGridLayout\" name=\"gridLayout\" rowstretch=\"0,0,0,1,0,0,0,0\">\n   <item row=\"0\" column=\"0\">\n    <widget class=\"QLabel\" name=\"labelSchema\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"text\">\n      <string>XML Schema Files:</string>\n     </property>\n    </widget>\n   </item>\n   <item row=\"0\" column=\"1\" rowspan=\"4\">\n    <widget class=\"QListWidget\" name=\"listSchema\">\n     <property name=\"minimumSize\">\n      <size>\n       <width>0</width>\n       <height>50</height>\n      </size>\n     </property>\n    </widget>\n   </item>\n   <item row=\"0\" column=\"2\">\n    <widget class=\"QPushButton\" name=\"buttonSchemaChange\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"toolTip\">\n      <string>Change schema file</string>\n     </property>\n     <property name=\"icon\">\n      <iconset resource=\"../resources/icons.qrc\">\n       <normaloff>:/icons/scalable/document-open.svg</normaloff>:/icons/scalable/document-open.svg</iconset>\n     </property>\n    </widget>\n   </item>\n   <item row=\"1\" column=\"2\">\n    <widget class=\"QPushButton\" name=\"buttonSchemaAdd\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"toolTip\">\n      <string>Add schema file</string>\n     </property>\n     <property name=\"icon\">\n      <iconset resource=\"../resources/icons.qrc\">\n       <normaloff>:/icons/scalable/edit-add.svg</normaloff>:/icons/scalable/edit-add.svg</iconset>\n     </property>\n    </widget>\n   </item>\n   <item row=\"2\" column=\"2\">\n    <widget class=\"QPushButton\" name=\"buttonSchemaRemove\">\n     <property name=\"enabled\">\n      <bool>false</bool>\n     </property>\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"toolTip\">\n      <string>Remove schema file</string>\n     </property>\n     <property name=\"icon\">\n      <iconset resource=\"../resources/icons.qrc\">\n       <normaloff>:/icons/scalable/edit-delete.svg</normaloff>:/icons/scalable/edit-delete.svg</iconset>\n     </property>\n    </widget>\n   </item>\n   <item row=\"4\" column=\"0\">\n    <widget class=\"QLabel\" name=\"labelTemplate\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"text\">\n      <string>Template File:</string>\n     </property>\n    </widget>\n   </item>\n   <item row=\"4\" column=\"1\">\n    <widget class=\"QLineEdit\" name=\"editTemplateFile\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n    </widget>\n   </item>\n   <item row=\"4\" column=\"2\">\n    <widget class=\"QPushButton\" name=\"buttonTemplateFile\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"icon\">\n      <iconset resource=\"../resources/icons.qrc\">\n       <normaloff>:/icons/scalable/document-open.svg</normaloff>:/icons/scalable/document-open.svg</iconset>\n     </property>\n    </widget>\n   </item>\n   <item row=\"5\" column=\"0\">\n    <widget class=\"QLabel\" name=\"labelWorkingDir\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"text\">\n      <string>Working Directory:</string>\n     </property>\n    </widget>\n   </item>\n   <item row=\"5\" column=\"1\">\n    <widget class=\"QLineEdit\" name=\"editWorkingDir\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n    </widget>\n   </item>\n   <item row=\"5\" column=\"2\">\n    <widget class=\"QPushButton\" name=\"buttonWorkingDir\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"icon\">\n      <iconset resource=\"../resources/icons.qrc\">\n       <normaloff>:/icons/scalable/document-open.svg</normaloff>:/icons/scalable/document-open.svg</iconset>\n     </property>\n    </widget>\n   </item>\n   <item row=\"6\" column=\"0\">\n    <widget class=\"QLabel\" name=\"labelDocumentationDir\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"text\">\n      <string>Documentation Directory:</string>\n     </property>\n    </widget>\n   </item>\n   <item row=\"6\" column=\"1\">\n    <widget class=\"QLineEdit\" name=\"editDocumentationDir\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n    </widget>\n   </item>\n   <item row=\"6\" column=\"2\">\n    <widget class=\"QPushButton\" name=\"buttonDocumentationDir\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Minimum\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"icon\">\n      <iconset resource=\"../resources/icons.qrc\">\n       <normaloff>:/icons/scalable/document-open.svg</normaloff>:/icons/scalable/document-open.svg</iconset>\n     </property>\n    </widget>\n   </item>\n   <item row=\"7\" column=\"0\" colspan=\"2\">\n    <widget class=\"QDialogButtonBox\" name=\"buttonBox\">\n     <property name=\"sizePolicy\">\n      <sizepolicy hsizetype=\"Expanding\" vsizetype=\"Minimum\">\n       <horstretch>0</horstretch>\n       <verstretch>0</verstretch>\n      </sizepolicy>\n     </property>\n     <property name=\"orientation\">\n      <enum>Qt::Horizontal</enum>\n     </property>\n     <property name=\"standardButtons\">\n      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>\n     </property>\n    </widget>\n   </item>\n  </layout>\n </widget>\n <resources>\n  <include location=\"../resources/icons.qrc\"/>\n </resources>\n <connections>\n  <connection>\n   <sender>buttonTemplateFile</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedTemplateFile()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>590</x>\n     <y>200</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonWorkingDir</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedWorkingDir()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>590</x>\n     <y>230</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonBox</sender>\n   <signal>accepted()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedOk()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>38</x>\n     <y>290</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonBox</sender>\n   <signal>rejected()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>reject()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>38</x>\n     <y>290</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonSchemaChange</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedSchemaChange()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>20</x>\n     <y>20</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonSchemaAdd</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedSchemaAdd()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>590</x>\n     <y>62</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>299</x>\n     <y>89</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonSchemaRemove</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedSchemaRemove()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>590</x>\n     <y>92</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>299</x>\n     <y>89</y>\n    </hint>\n   </hints>\n  </connection>\n  <connection>\n   <sender>buttonDocumentationDir</sender>\n   <signal>clicked()</signal>\n   <receiver>SettingsPathDialog</receiver>\n   <slot>clickedDocumentationDir()</slot>\n   <hints>\n    <hint type=\"sourcelabel\">\n     <x>590</x>\n     <y>260</y>\n    </hint>\n    <hint type=\"destinationlabel\">\n     <x>350</x>\n     <y>122</y>\n    </hint>\n   </hints>\n  </connection>\n </connections>\n <slots>\n  <slot>clickedOk()</slot>\n  <slot>clickedWorkingDir()</slot>\n  <slot>clickedSchemaChange()</slot>\n  <slot>clickedSchemaAdd()</slot>\n  <slot>clickedSchemaRemove()</slot>\n  <slot>clickedTemplateFile()</slot>\n  <slot>clickedDocumentationDir()</slot>\n </slots>\n</ui>\n"
  },
  {
    "path": "gui/tree/tree.cpp",
    "content": "/***********************************************/\n/**\n* @file tree.cpp\n*\n* @brief Editable tree from XML schema.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QMimeData>\n#include <QDrag>\n#include <QSettings>\n#include <QTreeWidget>\n#include <QHeaderView>\n#include <QClipboard>\n#include <QProcess>\n#include <QApplication>\n#include <QMessageBox>\n#include <QFileDialog>\n#include <QInputDialog>\n#include <QMenu>\n#include <QComboBox>\n#include <QContextMenuEvent>\n#include <QTextStream>\n#include <QUrl>\n#include <QDesktopServices>\n#include <QVBoxLayout>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n#include \"base/schema.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementFileName.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"tree/treeElementLoopCondition.h\"\n#include \"tree/treeElementComment.h\"\n#include \"tree/treeElementUnknown.h\"\n#include \"addVariableDialog/addVariableDialog.h\"\n#include \"executeDialog/executeDialog.h\"\n#include \"settingsDialog/settingsPathDialog.h\"\n#include \"tree/tree.h\"\n#ifdef _WIN32\n#undef  NOMINMAX\n#define NOMINMAX 1\n#include \"windows.h\"\n#endif\n\n/***********************************************/\n/***********************************************/\n\nTree::Tree(QWidget *parent, ActionList *actionList, TabEnvironment *tabEnvironment) : QWidget(parent)\n{\n  try\n  {\n    this->_isClean      = true;\n    this->_selectedItem = nullptr;\n    this->rootElement   = nullptr;\n    this->elementGlobal = nullptr;\n    this->fileWatcher   = nullptr;\n    this->undoStack     = new QUndoStack(this);\n    this->_isCurrent    = true;\n\n    // Layout\n    // ======\n    auto createBar = [this](const QIcon &icon, QLabel *label, const std::vector<QPushButton*> &buttons)\n    {\n      QLabel *iconLabel = new QLabel(this);\n      iconLabel->setPixmap(icon.pixmap(24,24));\n      QHBoxLayout *layoutBar = new QHBoxLayout(this);\n      layoutBar->addWidget(iconLabel);\n      layoutBar->addWidget(label, 1);\n      for(QPushButton *button : buttons)\n        layoutBar->addWidget(button);\n      layoutBar->setContentsMargins(3, 3, 3, 3);\n      auto frame = new QFrame(this);\n      frame->setFrameStyle(QFrame::Box);\n      frame->setLayout(layoutBar);\n      frame->setVisible(false);\n      const QString highlightColor = frame->palette().highlight().color().name().right(6);\n      frame->setStyleSheet(\".QFrame { color: #\"+highlightColor+\"; background-color: #4d\"+highlightColor+\" }\");\n      return frame;\n    };\n\n    // Bar handling external file changes\n    // ----------------------------------\n    {\n      QPushButton *buttonReopen = new QPushButton(QIcon(\":/icons/scalable/view-refresh.svg\"), \"Reopen\", this);\n      QPushButton *buttonIgnore = new QPushButton(QIcon(\":/icons/scalable/ignore.svg\"), \"Ignore\", this);\n      barFileExternallyChanged = createBar(QIcon(\":/icons/scalable/warning.svg\"), new QLabel(\"File was modified externally. Reopen?\", this), {buttonReopen, buttonIgnore});\n      connect(buttonReopen, SIGNAL(clicked()), this, SLOT(barFileExternallyChangedReopen()));\n      connect(buttonIgnore, SIGNAL(clicked()), this, SLOT(barClickedIgnore()));\n    }\n\n    // Bar handling broken links\n    // -------------------------\n    {\n      QPushButton *buttonShowAll   = new QPushButton(QIcon(\":/icons/scalable/edit-find-replace.svg\"), \"Show all\", this);\n      QPushButton *buttonIgnore    = new QPushButton(QIcon(\":/icons/scalable/ignore.svg\"), \"Ignore\", this);\n      labelBrokenLinks = new QLabel(this);\n      barBrokenLinks = createBar(QIcon(\":/icons/scalable/warning.svg\"), labelBrokenLinks, {buttonShowAll, buttonIgnore});\n      connect(buttonShowAll, SIGNAL(clicked()), this, SLOT(barBrokenLinksExpand()));\n      connect(buttonIgnore,  SIGNAL(clicked()), this, SLOT(barClickedIgnore()));\n    }\n\n    // Bar handling unknown elements\n    // -----------------------------\n    {\n      QPushButton *buttonShowAll   = new QPushButton(QIcon(\":/icons/scalable/edit-find-replace.svg\"), \"Show all\", this);\n      QPushButton *buttonRemoveAll = new QPushButton(QIcon(\":/icons/scalable/edit-delete.svg\"), \"Remove all\", this);\n      QPushButton *buttonIgnore    = new QPushButton(QIcon(\":/icons/scalable/ignore.svg\"), \"Ignore\", this);\n      buttonRemoveAll->setMinimumWidth(95);\n      labelUnknownElements = new QLabel(this);\n      barUnknownElements = createBar(QIcon(\":/icons/scalable/help-about.svg\"), labelUnknownElements, {buttonShowAll, buttonRemoveAll, buttonIgnore});\n      connect(buttonShowAll,   SIGNAL(clicked()), this, SLOT(barUnknownElementsExpand()));\n      connect(buttonRemoveAll, SIGNAL(clicked()), this, SLOT(barUnknownElementsRemoveAll()));\n      connect(buttonIgnore,    SIGNAL(clicked()), this, SLOT(barClickedIgnore()));\n    }\n\n    // Bar handling schema renamed elements\n    // ------------------------------------\n    {\n      QPushButton *buttonShowAll   = new QPushButton(QIcon(\":/icons/scalable/edit-find-replace.svg\"), \"Show all\", this);\n      QPushButton *buttonUpdateAll = new QPushButton(QIcon(\":/icons/scalable/edit-rename.svg\"), \"Update all\", this);\n      QPushButton *buttonIgnore    = new QPushButton(QIcon(\":/icons/scalable/ignore.svg\"), \"Ignore\", this);\n      buttonUpdateAll->setMinimumWidth(95);\n      labelSchemaRenamedElements = new QLabel(this);\n      barSchemaRenamedElements = createBar(QIcon(\":/icons/scalable/help-about.svg\"), labelSchemaRenamedElements, {buttonShowAll, buttonUpdateAll, buttonIgnore});\n      connect(buttonShowAll,   SIGNAL(clicked()), this, SLOT(barSchemaRenamedElementsExpand()));\n      connect(buttonUpdateAll, SIGNAL(clicked()), this, SLOT(barSchemaRenamedElementsUpdateAll()));\n      connect(buttonIgnore,    SIGNAL(clicked()), this, SLOT(barClickedIgnore()));\n    }\n\n    // Bar handling deprecated elements\n    // --------------------------------\n    {\n      QPushButton *buttonShowAll   = new QPushButton(QIcon(\":/icons/scalable/edit-find-replace.svg\"), \"Show all\", this);\n      QPushButton *buttonIgnore    = new QPushButton(QIcon(\":/icons/scalable/ignore.svg\"), \"Ignore\", this);\n      labelDeprecatedElements = new QLabel(this);\n      barDeprecatedElements = createBar(QIcon(\":/icons/scalable/help-about.svg\"), labelDeprecatedElements, {buttonShowAll, buttonIgnore});\n      connect(buttonShowAll, SIGNAL(clicked()), this, SLOT(barDeprecatedElementsExpand()));\n      connect(buttonIgnore,  SIGNAL(clicked()), this, SLOT(barClickedIgnore()));\n    }\n\n    this->treeWidget = new TreeWidget(this, tabEnvironment);\n\n    QVBoxLayout *layout = new QVBoxLayout();\n    layout->setSpacing(3);\n    layout->setContentsMargins(0, 3, 0, 0);\n    layout->addWidget(barFileExternallyChanged);\n    layout->addWidget(barBrokenLinks);\n    layout->addWidget(barUnknownElements);\n    layout->addWidget(barSchemaRenamedElements);\n    layout->addWidget(barDeprecatedElements);\n    layout->addWidget(treeWidget, 1);\n    setLayout(layout);\n\n    // QTreeWidget events\n    // ------------------\n    connect(QApplication::clipboard(),              SIGNAL(dataChanged()),                                          this, SLOT(treeClipboardDataChanged()));\n    connect(qobject_cast<QTreeWidget*>(treeWidget), SIGNAL(customContextMenuRequested(const QPoint &)),             this, SLOT(treeContextMenuRequested (const QPoint&)));\n    connect(qobject_cast<QTreeWidget*>(treeWidget), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(treeCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));\n    connect(qobject_cast<QTreeWidget*>(treeWidget), SIGNAL(itemSelectionChanged()),                                 this, SLOT(treeItemSelectionChanged()));\n    connect(qobject_cast<QTreeWidget*>(treeWidget), SIGNAL(itemClicked       (QTreeWidgetItem*, int)),              this, SLOT(treeItemClicked       (QTreeWidgetItem*, int)));\n    connect(qobject_cast<QTreeWidget*>(treeWidget), SIGNAL(itemDoubleClicked (QTreeWidgetItem*, int)),              this, SLOT(treeItemDoubleClicked (QTreeWidgetItem*, int)));\n    connect(treeWidget->header(), SIGNAL(sectionResized(int, int, int)), this, SIGNAL(sectionResized(int, int, int)));\n\n    // connection to actions\n    // ---------------------\n    this->actionList = *actionList;\n    connect(this->actionList.fileSaveAction,              SIGNAL(triggered(bool)), this, SLOT(fileSave()));\n    connect(this->actionList.fileSaveAsAction,            SIGNAL(triggered(bool)), this, SLOT(fileSaveAs()));\n    connect(this->actionList.fileRunAction,               SIGNAL(triggered(bool)), this, SLOT(fileRun()));\n    connect(this->actionList.fileShowInManagerAction,     SIGNAL(triggered(bool)), this, SLOT(fileShowInManager()));\n    connect(this->actionList.editCutAction,               SIGNAL(triggered(bool)), this, SLOT(editCut()));\n    connect(this->actionList.editCopyAction,              SIGNAL(triggered(bool)), this, SLOT(editCopy()));\n    connect(this->actionList.editPasteAction,             SIGNAL(triggered(bool)), this, SLOT(editPaste()));\n    connect(this->actionList.editPasteOverwriteAction,    SIGNAL(triggered(bool)), this, SLOT(editPasteOverwrite()));\n    connect(this->actionList.editAddAction,               SIGNAL(triggered(bool)), this, SLOT(editAdd()));\n    connect(this->actionList.editRemoveAction,            SIGNAL(triggered(bool)), this, SLOT(editRemove()));\n    connect(this->actionList.editAddVariableAction,       SIGNAL(triggered(bool)), this, SLOT(editAddVariable()));\n    connect(this->actionList.editSetLoopAction,           SIGNAL(triggered(bool)), this, SLOT(editSetLoop()));\n    connect(this->actionList.editSetConditionAction,      SIGNAL(triggered(bool)), this, SLOT(editSetCondition()));\n    connect(this->actionList.editEnabledAction,           SIGNAL(triggered(bool)), this, SLOT(editEnabled(bool)));\n    connect(this->actionList.editEnableAllAction,         SIGNAL(triggered(bool)), this, SLOT(editEnableAll()));\n    connect(this->actionList.editDisableAllAction,        SIGNAL(triggered(bool)), this, SLOT(editDisableAll()));\n    connect(this->actionList.editRenameAction,            SIGNAL(triggered(bool)), this, SLOT(editRename()));\n    connect(this->actionList.editUpdateNameAction,        SIGNAL(triggered(bool)), this, SLOT(editUpdateName()));\n    connect(this->actionList.editAddCommentAction,        SIGNAL(triggered(bool)), this, SLOT(editAddComment()));\n    connect(this->actionList.editCollapseAllAction,       SIGNAL(triggered(bool)), this, SLOT(editCollapseAll()));\n    connect(this->actionList.editOpenExternallyAction,    SIGNAL(triggered(bool)), this, SLOT(editOpenExternally()));\n    connect(this->actionList.helpShowDescriptionsAction,  SIGNAL(triggered(bool)), this, SLOT(helpShowDescriptions(bool)));\n    connect(this->actionList.helpShowResultsAction,       SIGNAL(triggered(bool)), this, SLOT(helpShowResults(bool)));\n    connect(this->actionList.helpOpenDocumentationAction, SIGNAL(triggered(bool)), this, SLOT(helpOpenDocumentation()));\n\n    actionList->helpShowDescriptionsAction->setChecked(settings.value(\"misc/showDescriptions\", true).toBool());\n    actionList->helpShowResultsAction->setChecked(settings.value(\"misc/showResults\", true).toBool());\n    helpShowDescriptions(actionList->helpShowDescriptionsAction->isChecked());\n    helpShowResults(actionList->helpShowResultsAction->isChecked());\n\n    // track state of file via undoStack\n    connect(undoStack,  SIGNAL(cleanChanged(bool)), this, SLOT(undoStackCleanChanged(bool)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTree::~Tree()\n{\n  clearTree();\n}\n\n/***********************************************/\n\nvoid Tree::clearTree()\n{\n  try\n  {\n    fileWatcherClear();\n    setSelectedItem(nullptr);\n    _isClean = true;\n    undoStack->clear();\n    brokenLinkCount = unknownCount = renamedCount = deprecatedCount = 0;\n    barFileExternallyChanged->setHidden(true);\n    barUnknownElements->setHidden(true);\n    barSchemaRenamedElements->setHidden(true);\n    barDeprecatedElements->setHidden(true);\n\n    if(rootElement)\n      rootElement->removeItem();\n    delete rootElement;\n    rootElement   = nullptr;\n    elementGlobal = nullptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool Tree::readSchema()\n{\n  try\n  {\n    Schema        schema;\n    XsdComplexPtr xsdGlobal;\n\n    QString fileNameSchema = settings.value(\"files/schemaFile\").toString();\n    if(schema.readFile(fileNameSchema) && schema.rootElement && schema.rootElement->complex)\n    {\n      auto xsdGlobalSequence = schema.rootElement->complex->getXsdElement(\"global\");\n      if(xsdGlobalSequence && xsdGlobalSequence->complex)\n        xsdGlobal = xsdGlobalSequence->complex;\n      if(xsdGlobal)\n      {\n        xsdElementLoop      = xsdGlobal->getXsdElement(\"loopType\");\n        xsdElementCondition = xsdGlobal->getXsdElement(\"conditionType\");\n      }\n    }\n    if(!xsdGlobal || !xsdElementLoop || !xsdElementCondition)\n    {\n      QMessageBox::critical(this , tr(\"GROOPS\"), tr(\"File '%1' seems not to be a valid XSD schema\").arg(fileNameSchema));\n      return false;\n    }\n\n    _fileNameSchema = fileNameSchema;\n    _schema         = schema;\n    _xsdGlobal      = xsdGlobal;\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Tree::setCurrent(bool isCurrent)\n{\n  if(!isCurrent)\n    setSelectedItem(nullptr);\n  _isCurrent = isCurrent;\n}\n\n/***********************************************/\n\nvoid Tree::setSelectedItem(TreeItem *item)\n{\n  try\n  {\n    if(item == _selectedItem)\n      return;\n\n    // old item lost selection\n    if(_selectedItem)\n      _selectedItem->lostCurrent();\n\n    // new item gets selection\n    _selectedItem = item;\n    if(_selectedItem)\n    {\n      _selectedItem->becomeCurrent();\n      updateActions();\n    }\n\n    if(_selectedItem != treeWidget->currentItem())\n      treeWidget->setCurrentItem(item);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTreeElement *Tree::selectedElement() const\n{\n  return _selectedItem ? _selectedItem->treeElement() : nullptr;\n}\n\n/***********************************************/\n/***********************************************/\n\nQString Tree::addWorkingDirectory(const QString &filename) const\n{\n  try\n  {\n    QFileInfo file(filename);\n    QString s = file.filePath();\n    if(file.isRelative())\n      file.setFile(workingDirectory, s);\n    return file.absoluteFilePath();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nQString Tree::stripWorkingDirectory(const QString &filename) const\n{\n  try\n  {\n    QString path = workingDirectory.absolutePath();\n    if(path.isEmpty())\n      return filename;\n    QFileInfo file(filename);\n    if(file.isRelative())\n      return filename;\n    QString s = file.absoluteFilePath();\n    path += QString(\"/\");\n    if(s.startsWith(path))\n      s.remove(0, path.length());\n\n    return QDir::toNativeSeparators(s);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool Tree::okToAbandon()\n{\n  try\n  {\n    if(isClean())\n      return true;\n\n    auto button = QMessageBox::question(this , tr(\"Close File - GROOPS\"), tr(\"File '%1' was changed.\\nDo you want to save the file?\").arg(caption()),\n                                        QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);\n    if(button == QMessageBox::Save)\n      return fileSave();\n    return (button == QMessageBox::Discard);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool Tree::fileNew(const QString &caption)\n{\n  try\n  {\n    if(!okToAbandon())\n      return false;\n    if(!readSchema())\n      return false;\n\n    // try to open template file, clear tree if not\n    blockSignals(true); // do not emit fileChanged\n    QString templateFile = settings.value(\"files/templateFile\").toString();\n    if(!QFileInfo(templateFile).isFile() || !fileOpen(templateFile))\n    {\n      clearTree();\n      rootElement = dynamic_cast<TreeElementComplex*>(TreeElement::newTreeElement(this, nullptr, _schema.rootElement, \"\", XmlNodePtr(nullptr), true/*fillWithDefaults*/));\n      TreeItem *item = rootElement->createItem(nullptr, nullptr);\n      if(item)\n        item->setExpanded(true);\n    }\n    blockSignals(false);\n\n    _caption  = caption;\n    _fileName = QString();\n    workingDirectory.setPath(settings.value(\"files/workingDirectory\").toString());\n    emit fileChanged(caption, fileName(), isClean());\n\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool Tree::fileOpen(QString fileName)\n{\n  try\n  {\n    if(!okToAbandon())\n      return false;\n\n    if(fileName.isEmpty())\n      fileName = _fileName; // try to reopen\n    if(fileName.isEmpty())\n      fileNew(caption());\n\n    if(!readSchema())\n      return false;\n\n    // read xml file\n    // -------------\n    QFile file(fileName);\n    if(!file.open(QFile::ReadOnly | QFile::Text))\n    {\n      QMessageBox::critical(this , tr(\"Open file - GROOPS\"), tr(\"Cannot open file '%1'.\").arg(fileName));\n      return false;\n    }\n    QString errorMessage;\n    XmlNodePtr xmlNode = XmlNode::read(&file, errorMessage);\n    if(!xmlNode)\n    {\n      QMessageBox::critical(this , tr(\"Open file - GROOPS\"), errorMessage);\n      return false;\n    }\n\n    // seems to be all ok\n    // ------------------\n    _caption          = QFileInfo(fileName).fileName();\n    _fileName         = fileName;\n    workingDirectory  = QFileInfo(fileName).dir();\n    emit fileChanged(caption(), fileName, isClean());\n    fileWatcherCreate();\n\n    clearTree();\n    TreeElement *element = TreeElement::newTreeElement(this, nullptr, _schema.rootElement, \"\", xmlNode, false/*fillWithDefaults*/);\n    rootElement = dynamic_cast<TreeElementComplex*>(element); // set rootElement after complete initialization\n    VariableListPtr varList = std::make_shared<const VariableList>();\n    QMap<QString, QString> labelTypes;\n    rootElement->updateParserResults(varList, false);\n    rootElement->updateLinks(labelTypes);\n    rootElement->createItem(nullptr, nullptr)->setExpanded(true);\n    treeChanged();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nconst std::vector<XsdElementPtr> &Tree::xsdElements() const\n{\n  return _xsdGlobal->elements;\n}\n\n/***********************************************/\n\nXsdElementPtr Tree::xsdElement(const QString &type) const\n{\n  return _xsdGlobal->getXsdElement(type);\n}\n\n/***********************************************/\n\nQList<XsdElementPtr> Tree::programList() const\n{\n  QList<XsdElementPtr> programList;\n  for(auto element : _schema.complexType)\n    if(element->names.front() == \"programmeType\" || element->names.front() == \"programType\")\n      for(auto program : element->complex->elements)\n        programList.push_back(program);\n  return programList;\n}\n\n/***********************************************/\n\nvoid Tree::addProgram(const QString &name)\n{\n  try\n  {\n    for(auto &targetElement : rootElement->children())\n      if(dynamic_cast<TreeElementAdd*>(targetElement) && (targetElement->type() == \"programType\"))\n      {\n        undoStack->beginMacro(\"add program \"+name);\n        TreeElement *elementProgram = rootElement->addChild(targetElement, \"programType\", \"\", XmlNodePtr(nullptr));\n        elementProgram->changeSelectedIndex(elementProgram->findValueIndex(name));\n        undoStack->endMacro();\n        break;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Tree::fileWatcherCreate()\n{\n  try\n  {\n    fileWatcherClear();\n    if(fileName().isEmpty())\n      return;\n    fileWatcher = new QFileSystemWatcher(this);\n    fileWatcher->addPath(fileName());\n    connect(fileWatcher, &QFileSystemWatcher::fileChanged, this, &Tree::fileWatcherChangedExternally);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::fileWatcherClear()\n{\n  if(fileWatcher)\n  {\n    disconnect(fileWatcher, &QFileSystemWatcher::fileChanged, this, &Tree::fileWatcherChangedExternally);\n    fileWatcher->deleteLater();\n    fileWatcher = nullptr;\n  }\n}\n\n/***********************************************/\n\nvoid Tree::fileWatcherChangedExternally()\n{\n  barFileExternallyChanged->setVisible(true);\n}\n\n/***********************************************/\n/***********************************************/\n\n// mime data <-> XML of the element\n// --------------------------------\nstatic const char *mimeFormatString = \"application/x-groops\"; //\"text/plain\";\n\nstatic QMimeData *createMimeData(const TreeElement *element)\n{\n  try\n  {\n    if(element->type().isEmpty())\n      return nullptr;\n    XmlNodePtr xmlNode = element->createXmlTree(true/*createRootEvenIfEmpty*/);\n    if(!xmlNode)\n      return nullptr;\n    writeAttribute(xmlNode, \"xsdType\", element->type());\n\n    // create xml text\n    QString xmlData;\n    QTextStream stream(&xmlData, QIODevice::WriteOnly);\n    XmlNode::write(stream, xmlNode, true/*writeCommentsAsElements*/);\n\n    // create mime data\n    QMimeData *mimeData = new QMimeData;\n    mimeData->setData(mimeFormatString, xmlData.toUtf8());\n    return mimeData;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nstatic bool fromMimeData(const QMimeData *mimeData, XmlNodePtr &xmlNode, QString &type, QString &label)\n{\n  try\n  {\n    if(!mimeData->hasFormat(mimeFormatString))\n      return false;\n    // create xmlData from MIME data\n    QString errorMessage;\n    xmlNode = XmlNode::read(mimeData->data(mimeFormatString), errorMessage);\n    if(!xmlNode)\n      return false;\n    readAttribute(xmlNode, \"xsdType\", type);\n    readAttribute(xmlNode, \"label\",   label);\n    if(!label.isEmpty())\n      writeAttribute(xmlNode, \"label\", label);\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Tree::updateActions()\n{\n  try\n  {\n    if(!selectedElement())\n      return;\n    TreeElement        *element       = selectedElement();\n    TreeElementComplex *parentElement = element->parentElement;\n\n    // test content of clipboard\n    QString    type, label;\n    XmlNodePtr xmlNode;\n    bool isClipboard = fromMimeData(QApplication::clipboard()->mimeData(), xmlNode, type, label);\n    bool canCopy = !element->type().isEmpty() && element->createXmlTree(true);\n\n    actionList.fileShowInManagerAction    ->setEnabled(!fileName().isEmpty() );\n    actionList.editCutAction              ->setEnabled(canCopy && ((parentElement && parentElement->canRemoveChild(element)) || dynamic_cast<TreeElementLoopCondition*>(element)));\n    actionList.editCopyAction             ->setEnabled(canCopy);\n    actionList.editPasteAction            ->setEnabled(isClipboard && (parentElement && parentElement->canAddChild(element, type, label)));\n    actionList.editPasteOverwriteAction   ->setEnabled(isClipboard && element->canOverwrite(type));\n    actionList.editAddAction              ->setEnabled(parentElement && parentElement->canAddChild(element, element->type(), element->label()));\n    actionList.editRemoveAction           ->setEnabled((parentElement && parentElement->canRemoveChild(element)) || dynamic_cast<TreeElementLoopCondition*>(element));\n    actionList.editAddVariableAction      ->setEnabled(parentElement || dynamic_cast<TreeElementLoopCondition*>(element));\n    actionList.editSetLoopAction          ->setEnabled(element->canSetLoop());\n    actionList.editSetConditionAction     ->setEnabled(element->canSetCondition());\n    actionList.editEnabledAction          ->setEnabled(element->canDisabled());\n    actionList.editEnabledAction          ->setChecked(!element->disabled());\n    actionList.editEnableAllAction        ->setEnabled(true);\n    actionList.editDisableAllAction       ->setEnabled(true);\n    actionList.editRenameAction           ->setEnabled(element->canRename());\n    actionList.editUpdateNameAction       ->setEnabled(element->canUpdateName());\n    actionList.editAddCommentAction       ->setEnabled(parentElement && parentElement->canAddChild(element, \"COMMENT\", \"\"));\n    actionList.editCollapseAllAction      ->setEnabled(true);\n    TreeElementFileName *fileNameElement = dynamic_cast<TreeElementFileName*>(element);\n    actionList.editOpenExternallyAction   ->setEnabled(fileNameElement && QFileInfo(addWorkingDirectory(fileNameElement->selectedResult())).isFile());\n    actionList.helpOpenDocumentationAction->setEnabled(true);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/**** slots ************************************/\n/***********************************************/\n\nbool Tree::fileSave()\n{\n  try\n  {\n    if(!isCurrent())\n      return false;\n\n    if(_fileName.isEmpty())\n      return fileSaveAs();\n\n    fileWatcherClear();\n    XmlNodePtr xmlNode = rootElement->createXmlTree();\n    XmlNode::writeFile(fileName(), xmlNode);\n    undoStack->setClean();\n    fileWatcherCreate();\n    emit fileChanged(caption(), fileName(), isClean());\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool Tree::fileSaveAs()\n{\n  try\n  {\n    if(!isCurrent())\n      return false;\n\n    // Open file selector\n    QString name = _fileName;\n    if(name.isEmpty())\n      name = settings.value(\"files/workingDirectory\").toString(); // selecttor starts in default working directory\n    name = QFileDialog::getSaveFileName(this, tr(\"Save file - GROOPS\"), name, tr(\"XML files (*.xml)\"));\n    if(name.isEmpty())\n      return false;\n    if(!name.endsWith(\".xml\"))\n      name += \".xml\";\n\n    _fileName         = name;\n    _caption          = QFileInfo(name).fileName();\n    workingDirectory  = QFileInfo(name).dir();\n\n    return fileSave();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::fileRun()\n{\n  try\n  {\n    if(!isCurrent())\n      return;\n\n    // file must be saved first\n    // ------------------------\n    if(!isClean() || fileName().isEmpty())\n    {\n      QMessageBox::StandardButton button =\n      QMessageBox::warning(this , tr(\"Run file - GROOPS\"),\n                           tr(\"File '%1' was changed.\\nYou have to save it first.\").arg(caption()),\n                           QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Save);\n      if(button != QMessageBox::Save)\n        return;\n      if(!fileSave())\n        return;\n    }\n\n    // execute dialog\n    // --------------\n    ExecuteDialog dialog(this, this);\n    if(!dialog.exec())\n      return;\n\n    // create execute command\n    // ----------------------\n    QStringList commandList  = settings.value(\"execute/commands\").toStringList();\n    int         commandIndex = settings.value(\"execute/commandIndex\", int(0)).toInt();\n    if((commandIndex<0)||(commandIndex>=commandList.size()))\n      return;\n    QString command = commandList[commandIndex];\n    if(command.isEmpty())\n      return;\n\n    QString optionString;\n    // append log file option?\n    if(settings.value(\"execute/useLogFile\", bool(false)).toBool())\n      optionString += \" -l \"+settings.value(\"execute/logFile\", QString(\"groops.log\")).toString()+\" \";\n    optionString += fileName();\n\n    command.replace(\"%f\", optionString);\n    command.replace(\"%w\", workingDirectory.absolutePath());\n\n    qWarning()<<\"run command:\"<<command;\n\n    // execute command\n    // ---------------\n#ifdef _WIN32\n    // https://stackoverflow.com/questions/42051405/qprocess-with-cmd-command-does-not-result-in-command-line-window\n    class DetachableProcess : public QProcess\n    {\n    public:\n      DetachableProcess(QObject *parent=0) : QProcess(parent) {}\n      void detach()\n      {\n        waitForStarted();\n        setProcessState(QProcess::NotRunning);\n      }\n    };\n\n    DetachableProcess process;\n    process.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args)\n    {args->flags |= CREATE_NEW_CONSOLE;\n      args->startupInfo->dwFlags &=~ STARTF_USESTDHANDLES;});\n    process.start(QString(\"cmd.exe\"), QStringList({\"/k\", command}));\n    process.detach();\n#else\n    QProcess::startDetached(command);\n#endif\n\n    return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::fileShowInManager()\n{\n  if(isCurrent() && !fileName().isEmpty())\n    QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(fileName()).absoluteDir().path()));\n}\n\n/***********************************************/\n\nvoid Tree::editCut()\n{\n  try\n  {\n    if(!selectedElement())\n      return;\n    QMimeData *mimeData = createMimeData(selectedElement());\n    if(!mimeData)\n      return;\n\n    if(dynamic_cast<TreeElementLoopCondition*>(selectedElement()))\n      dynamic_cast<TreeElementLoopCondition*>(selectedElement())->affectedElement->removeLoopOrCondition(selectedElement());\n    else if(selectedElement()->parentElement && selectedElement()->parentElement->canRemoveChild(selectedElement()))\n      selectedElement()->parentElement->removeChild(selectedElement());\n    else\n    {\n      delete mimeData;\n      return;\n    }\n\n    QApplication::clipboard()->setMimeData(mimeData);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editCopy()\n{\n  try\n  {\n    if(!selectedElement())\n      return;\n    // copy to clipboard\n    QMimeData *mimeData = createMimeData(selectedElement());\n    if(mimeData)\n      QApplication::clipboard()->setMimeData(mimeData);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editPaste()\n{\n  try\n  {\n    if(!selectedElement() || !selectedElement()->parentElement)\n      return;\n    // paste from clipboard\n    QString    type, label;\n    XmlNodePtr xmlNode;\n    if(fromMimeData(QApplication::clipboard()->mimeData(), xmlNode, type, label))\n      selectedElement()->parentElement->addChild(selectedElement(), type, label, xmlNode);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editPasteOverwrite()\n{\n  try\n  {\n    if(!selectedElement())\n      return;\n    // paste from clipboard\n    QString    type, label;\n    XmlNodePtr xmlNode;\n    if(!fromMimeData(QApplication::clipboard()->mimeData(), xmlNode, type, label))\n      return;\n    selectedElement()->overwrite(type, xmlNode);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editAdd()\n{\n  try\n  {\n    TreeElement *element = selectedElement();\n    if(!element || !element->parentElement)\n      return;\n    element->parentElement->addChild(element, element->type(), element->label(), element->createXmlTree(true/*createRootEvenIfEmpty*/));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editRemove()\n{\n  try\n  {\n    if(!selectedElement())\n      return;\n\n    if(QMessageBox::question(this , tr(\"Remove element - GROOPS\"), tr(\"Do you really want to remove this element?\"),\n                             QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) != QMessageBox::Ok)\n      return;\n\n    if(dynamic_cast<TreeElementLoopCondition*>(selectedElement()))\n      dynamic_cast<TreeElementLoopCondition*>(selectedElement())->affectedElement->removeLoopOrCondition(selectedElement());\n    else if(selectedElement()->parentElement && selectedElement()->parentElement->canRemoveChild(selectedElement()))\n      selectedElement()->parentElement->removeChild(selectedElement());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editAddVariable()\n{\n  try\n  {\n    TreeElement *element = selectedElement();\n    if(!element)\n      return;\n\n    AddVariableDialog dialog(this, element->type(), element->name(),\n                             dynamic_cast<TreeElementGlobal*>(element->parentElement)/*disablePlace*/,\n                             dynamic_cast<TreeElementAdd*>(element)/*disableCreateLink*/, this);\n    if(!dialog.exec())\n      return;\n\n    XmlNodePtr xmlNode;\n    if(element->type() == dialog.type())\n      xmlNode = element->createXmlTree(false/*createRootEvenIfEmpty*/);\n    if(xmlNode)\n    {\n      xmlNode->setName(element->type());\n      // remove loop, condition, ...\n      QString loopLabel, conditionLabel, tmp;\n      readAttribute(xmlNode, \"label\",     tmp);\n      readAttribute(xmlNode, \"disabled\",  tmp);\n      readAttribute(xmlNode, \"loop\",      loopLabel);\n      readAttribute(xmlNode, \"condition\", conditionLabel);\n      if(loopLabel      == \"_localLoop_\")      xmlNode->getChild(\"loopType\");\n      if(conditionLabel == \"_localCondition_\") xmlNode->getChild(\"conditionType\");\n      writeAttribute(xmlNode, \"label\", dialog.label());\n    }\n\n    TreeElement *targetElement = element;\n    if(dialog.inGlobal())\n      targetElement = elementGlobal->children().back();\n    else if(dynamic_cast<TreeElementLoopCondition*>(element))\n      targetElement = dynamic_cast<TreeElementLoopCondition*>(element)->affectedElement;\n    if(!targetElement->parentElement)\n      return;\n\n    undoStack->beginMacro(\"add variable \"+dialog.label());\n    if(!targetElement->parentElement->addChild(targetElement, dialog.type(), dialog.label(), xmlNode))\n    {\n      // abort/end macro and overwrite it with empty command\n      undoStack->endMacro();\n      undoStack->undo();\n      undoStack->push(new QUndoCommand);\n      undoStack->undo();\n      return;\n    }\n\n    // element will be linked\n    if(dialog.setLink())\n      element->changeSelectedLink(dialog.label());\n\n    undoStack->endMacro();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editSetLoop()\n{\n  try\n  {\n    if(selectedElement() && selectedElement()->canSetLoop())\n      selectedElement()->setLoop();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editSetCondition()\n{\n  try\n  {\n    if(selectedElement() && selectedElement()->canSetCondition())\n      selectedElement()->setCondition();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editEnabled(bool checked)\n{\n  try\n  {\n    if(selectedElement())\n      selectedElement()->setDisabled(!checked);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editEnableAll()\n{\n  try\n  {\n    if(!isCurrent())\n      return;\n\n    undoStack->beginMacro(\"enable all programs\");\n    for(auto &element : rootElement->children())\n      if(element->disabled() && dynamic_cast<TreeElementProgram*>(element))\n        element->setDisabled(false);\n    undoStack->endMacro();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editDisableAll()\n{\n  try\n  {\n    if(!isCurrent())\n      return;\n\n    undoStack->beginMacro(\"disable all programs\");\n    for(auto &element : rootElement->children())\n      if(!element->disabled() && dynamic_cast<TreeElementProgram*>(element))\n        element->setDisabled(true);\n    undoStack->endMacro();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editRename()\n{\n  try\n  {\n    if(!selectedElement() || !selectedElement()->canRename())\n      return;\n\n    bool ok = true;\n    QString label = QInputDialog::getText(this, tr(\"Rename variable - GROOPS\"), tr(\"Name of variable:\"), QLineEdit::Normal, selectedElement()->label(), &ok);\n\n    // check if its a valid label\n    QStringList existingNames;\n    if(dynamic_cast<TreeElementGlobal*>(selectedElement()->parentElement))\n      for(auto child : selectedElement()->parentElement->children())\n        if(!child->label().isEmpty())\n          existingNames.push_back(child->label());\n    QRegularExpression regex(\"^[a-zA-Z]([a-zA-Z0-9])*$\");\n    while(ok && (label != selectedElement()->label()) && (label.isEmpty() || existingNames.contains(label) || !regex.match(label).hasMatch()))\n      label = QInputDialog::getText(this, tr(\"Rename variable - GROOPS\"), tr(\"Name already exists or is invalid (only letters and digits allowed)!\\nChoose another name:\"), QLineEdit::Normal, label, &ok);\n    if(!ok)\n      return;\n\n    selectedElement()->rename(label);\n    if(selectedElement()->parentElement)\n      selectedElement()->parentElement->updateLinksInScope();\n    updateActions();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editUpdateName()\n{\n  try\n  {\n    if(!selectedElement() || !selectedElement()->canUpdateName())\n      return;\n    selectedElement()->updateName();\n    updateActions();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editAddComment()\n{\n  try\n  {\n    TreeElement *element = selectedElement();\n    if(!element || !element->parentElement)\n      return;\n    element->parentElement->addChild(element, \"COMMENT\", \"\", nullptr);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editCollapseAll()\n{\n  try\n  {\n    if(!isCurrent())\n      return;\n    treeWidget->collapseAll();\n    treeWidget->expand(treeWidget->model()->index(0,0));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::editOpenExternally()\n{\n  try\n  {\n    if(selectedElement())\n      QDesktopServices::openUrl(QUrl::fromLocalFile(addWorkingDirectory(selectedElement()->selectedResult())));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::helpShowDescriptions(bool state)\n{\n  settings.setValue(\"misc/showDescriptions\", state);\n  treeWidget->setColumnHidden(2, !state);\n  if(!treeWidget->isColumnHidden(2))\n    treeWidget->setColumnWidth(2, std::max(treeWidget->columnWidth(2), 100));\n}\n\n/***********************************************/\n\nvoid Tree::helpShowResults(bool state)\n{\n  settings.setValue(\"misc/showResults\", state);\n  _showResults = state;\n  if(rootElement)\n    rootElement->createItem(nullptr, nullptr);\n}\n\n/***********************************************/\n\nvoid Tree::helpOpenDocumentation()\n{\n  try\n  {\n    if(!isCurrent())\n      return;\n\n    QString path     = settings.value(\"files/documentationDirectory\").toString()+\"/\";\n    QString fileName = \"index.html\";\n    TreeElement *element = selectedElement();\n    if(element)\n    {\n      fileName = (dynamic_cast<TreeElementProgram*>(element) ? element->selectedValue() : element->type())+\".html\";\n      if(!QFileInfo::exists(path+fileName))\n        fileName = \"index.html\";\n    }\n    if(QFileInfo::exists(path+fileName))\n      QDesktopServices::openUrl(QUrl::fromLocalFile(path+fileName));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nint Tree::columnWidth(int column) const\n{\n  return treeWidget->columnWidth(column);\n}\n\n/***********************************************/\n\nvoid Tree::setColumnWidth(int column, int width)\n{\n  treeWidget->setColumnWidth(column, width);\n}\n\n/***********************************************/\n/**** Event-Handler ****************************/\n/***********************************************/\n\nstatic void countBrokenLinksUnknownsRenamesAndDeprecated(const TreeElement *element, int &brokenLinkCount, int &unknownCount, int &renamedCount, int &deprecatedCount)\n{\n  try\n  {\n    if(!element || element->disabled())\n      return;\n\n    if(element->isBrokenLinked())\n      brokenLinkCount++;\n    if(dynamic_cast<const TreeElementUnknown*>(element) || element->isSelectionUnknown(element->selectedIndex()))\n      unknownCount++;\n    if(element->isRenamedInSchema() || element->isSelectionRenamedInSchema(element->selectedIndex()))\n      renamedCount++;\n    if(element->isDeprecated() || element->isSelectionDeprecated(element->selectedIndex()))\n      deprecatedCount++;\n\n    // check loop, condition, children\n    countBrokenLinksUnknownsRenamesAndDeprecated(element->loop,      brokenLinkCount, unknownCount, renamedCount, deprecatedCount);\n    countBrokenLinksUnknownsRenamesAndDeprecated(element->condition, brokenLinkCount, unknownCount, renamedCount, deprecatedCount);\n    if(dynamic_cast<const TreeElementComplex*>(element))\n      for(const auto &child : dynamic_cast<const TreeElementComplex*>(element)->children())\n        countBrokenLinksUnknownsRenamesAndDeprecated(child, brokenLinkCount, unknownCount, renamedCount, deprecatedCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::treeChanged()\n{\n  try\n  {\n    if(!rootElement)\n      return;\n    int brokenLinkCountOld = brokenLinkCount;\n    int unknownCountOld    = unknownCount;\n    int renamedCountOld    = renamedCount;\n    int deprecatedCountOld = deprecatedCount;\n    brokenLinkCount = unknownCount = renamedCount = deprecatedCount = 0;\n    countBrokenLinksUnknownsRenamesAndDeprecated(rootElement, brokenLinkCount, unknownCount, renamedCount, deprecatedCount);\n    if(!brokenLinkCount || (brokenLinkCount > brokenLinkCountOld))\n      barBrokenLinks->setVisible(brokenLinkCount);\n    if(!unknownCount || (unknownCount > unknownCountOld))\n      barUnknownElements->setVisible(unknownCount);\n    if(!renamedCount || (renamedCount > renamedCountOld))\n      barSchemaRenamedElements->setVisible(renamedCount);\n    if(!deprecatedCount || (deprecatedCount > deprecatedCountOld))\n      barDeprecatedElements->setVisible(deprecatedCount);\n    labelBrokenLinks->setText(QString(\"File contains %1 broken links.\").arg(brokenLinkCount));\n    labelUnknownElements->setText(QString(\"File contains %1 unknown elements.\").arg(unknownCount));\n    labelSchemaRenamedElements->setText(QString(\"File contains %1 elements that were renamed in the schema.\").arg(renamedCount));\n    labelDeprecatedElements->setText(QString(\"File contains %1 deprecated elements.\").arg(deprecatedCount));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::undoStackCleanChanged(bool clean)\n{\n  try\n  {\n    _isClean = clean;\n    updateActions();\n    emit fileChanged(caption(), fileName(), isClean());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Tree::treeClipboardDataChanged()\n{\n  updateActions();\n}\n\n/***********************************************/\n\nvoid Tree::treeContextMenuRequested(const QPoint &pos)\n{\n  try\n  {\n    TreeItem *item = dynamic_cast<TreeItem*>(treeWidget->itemAt(pos));\n    if(!item)\n      return;\n    setSelectedItem(item);\n\n    QMenu *contextMenu = new QMenu(this);\n    contextMenu->addAction(actionList.helpOpenDocumentationAction);\n    contextMenu->addSeparator();\n    contextMenu->addAction(actionList.editCutAction);\n    contextMenu->addAction(actionList.editCopyAction);\n    contextMenu->addAction(actionList.editPasteAction);\n    contextMenu->addAction(actionList.editPasteOverwriteAction);\n    contextMenu->addSeparator();\n    contextMenu->addAction(actionList.editEnabledAction);\n    contextMenu->addSeparator();\n    contextMenu->addAction(actionList.editAddAction);\n    contextMenu->addAction(actionList.editRemoveAction);\n    contextMenu->addAction(actionList.editAddVariableAction);\n    contextMenu->addAction(actionList.editAddCommentAction);\n    contextMenu->addAction(actionList.editSetLoopAction);\n    contextMenu->addAction(actionList.editSetConditionAction);\n    contextMenu->addSeparator();\n    contextMenu->addAction(actionList.editRenameAction);\n    contextMenu->addAction(actionList.editOpenExternallyAction);\n    contextMenu->exec(QWidget::mapToGlobal(pos));\n    delete contextMenu;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::treeCurrentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem */*previous*/)\n{\n  try\n  {\n    setSelectedItem(dynamic_cast<TreeItem*>(current));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n\n/***********************************************/\n\nvoid Tree::treeItemSelectionChanged()\n{\n  // catch edge case where clicked item changes because editor is removed from item above and therefore vertical position changes\n  const QSignalBlocker blocker(treeWidget);\n  for(QTreeWidgetItem *item : treeWidget->selectedItems())\n    item->setSelected(item == selectedItem());\n  if(selectedItem())\n    selectedItem()->setSelected(true);\n}\n\n/***********************************************/\n\nvoid Tree::treeItemClicked(QTreeWidgetItem *item, int column)\n{\n  try\n  {\n    if(column != 1) // value column?\n      return;\n    if(item != _selectedItem)\n      setSelectedItem(dynamic_cast<TreeItem*>(item));\n    _selectedItem->setFocus();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::treeItemDoubleClicked(QTreeWidgetItem *item, int column)\n{\n  try\n  {\n    if(column != 3) // comment column?\n      return;\n    if(item != _selectedItem)\n      setSelectedItem(dynamic_cast<TreeItem*>(item));\n    if(_selectedItem->treeElement()->canComment())\n      _selectedItem->editComment();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Tree::barFileExternallyChangedReopen()\n{\n  if(fileOpen(fileName()))\n    barFileExternallyChanged->setHidden(true);\n}\n\n/***********************************************/\n\nvoid Tree::barBrokenLinksExpand()\n{\n  // recursive call\n  std::function<bool(TreeElement*)> expand = [&expand](TreeElement *element)\n  {\n    if(!element->item() || element->disabled())\n      return false;\n    bool expandChild = FALSE;\n    if(dynamic_cast<TreeElementComplex*>(element))\n      for(auto &child : dynamic_cast<TreeElementComplex*>(element)->children())\n        expandChild = expand(child) || expandChild;\n    expandChild = (element->loop      && expand(element->loop))      || expandChild;\n    expandChild = (element->condition && expand(element->condition)) || expandChild;\n    if(expandChild)\n    {\n      element->item()->setExpanded(true);\n      return true;\n    }\n    return element->isBrokenLinked();\n  };\n\n  expand(rootElement);\n}\n\n/***********************************************/\n\nvoid Tree::barUnknownElementsExpand()\n{\n  // recursive call\n  std::function<bool(TreeElement*)> expand = [&expand](TreeElement *element)\n  {\n    if(!element->item())\n      return false;\n    bool expandChild = FALSE;\n    if(dynamic_cast<TreeElementComplex*>(element))\n      for(auto &child : dynamic_cast<TreeElementComplex*>(element)->children())\n        expandChild = expand(child) || expandChild;\n    expandChild = (element->loop      && expand(element->loop))      || expandChild;\n    expandChild = (element->condition && expand(element->condition)) || expandChild;\n    if(expandChild)\n    {\n      element->item()->setExpanded(true);\n      return true;\n    }\n    return (dynamic_cast<TreeElementUnknown*>(element) || element->isSelectionUnknown(element->selectedIndex()));\n  };\n\n  expand(rootElement);\n}\n\n/***********************************************/\n\nvoid Tree::barUnknownElementsRemoveAll()\n{\n  try\n  {\n    if(QMessageBox::question(this , tr(\"Remove all unknown elements - GROOPS\"),\n                             tr(\"Do you really want to remove all unknown elements?\\n\\nNotice: This will not affect unknown choices or programs.\"),\n                             QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) != QMessageBox::Ok)\n      return;\n\n    // recursive call\n    std::function<void(TreeElement*)> removeUnknown = [&removeUnknown](TreeElement *element)\n    {\n      if(dynamic_cast<TreeElementUnknown*>(element) && element->parentElement)\n        element->parentElement->removeChild(element);\n      else\n      {\n        if(dynamic_cast<TreeElementComplex*>(element))\n          for(UInt i=dynamic_cast<TreeElementComplex*>(element)->children().size(); i-->0;)\n            removeUnknown(dynamic_cast<TreeElementComplex*>(element)->children().at(i));\n        if(element->loop)\n          for(UInt i=element->loop->children().size(); i-->0;)\n            removeUnknown(element->loop->children().at(i));\n        if(element->condition)\n          for(UInt i=element->condition->children().size(); i-->0;)\n            removeUnknown(element->condition->children().at(i));\n      }\n    };\n\n    removeUnknown(rootElement);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid Tree::barSchemaRenamedElementsExpand()\n{\n  // recursive call\n  std::function<bool(TreeElement*)> expand = [&expand](TreeElement *element)\n  {\n    if(!element->item())\n      return false;\n    bool expandChild = FALSE;\n    if(dynamic_cast<TreeElementComplex*>(element))\n      for(auto &child : dynamic_cast<TreeElementComplex*>(element)->children())\n        expandChild = expand(child) || expandChild;\n    expandChild = (element->loop      && expand(element->loop))      || expandChild;\n    expandChild = (element->condition && expand(element->condition)) || expandChild;\n    if(expandChild)\n    {\n      element->item()->setExpanded(true);\n      return true;\n    }\n    return (element->isRenamedInSchema() || element->isSelectionRenamedInSchema(element->selectedIndex()));\n  };\n\n  expand(rootElement);\n}\n\n/***********************************************/\n\nvoid Tree::barSchemaRenamedElementsUpdateAll()\n{\n  // recursive call\n  std::function<void(TreeElement*)> updateName = [&updateName](TreeElement *element)\n  {\n    if(element->canUpdateName())\n      element->updateName();\n    if(element->loop)      updateName(element->loop);\n    if(element->condition) updateName(element->condition);\n    if(dynamic_cast<TreeElementComplex*>(element))\n      for(auto &child : dynamic_cast<TreeElementComplex*>(element)->children())\n        updateName(child);\n  };\n\n  updateName(rootElement);\n}\n\n/***********************************************/\n\nvoid Tree::barDeprecatedElementsExpand()\n{\n  // recursive call\n  std::function<bool(TreeElement*)> expand = [&expand](TreeElement *element)\n  {\n    if(!element->item() || element->disabled())\n      return false;\n    bool expandChild = FALSE;\n    if(dynamic_cast<TreeElementComplex*>(element))\n      for(auto &child : dynamic_cast<TreeElementComplex*>(element)->children())\n        expandChild = expand(child) || expandChild;\n    expandChild = (element->loop      && expand(element->loop))      || expandChild;\n    expandChild = (element->condition && expand(element->condition)) || expandChild;\n    if(expandChild)\n    {\n      element->item()->setExpanded(true);\n      return true;\n    }\n    return element->isDeprecated() || element->isSelectionDeprecated(element->selectedIndex());\n  };\n\n  expand(rootElement);\n}\n\n/***********************************************/\n\nvoid Tree::barClickedIgnore()\n{\n  QFrame *bar = dynamic_cast<QFrame*>(sender()->parent());\n  if(bar)\n    bar->setHidden(true);\n}\n\n/***********************************************/\n/**** TreeWidget *******************************/\n/***********************************************/\n\nTreeWidget::TreeWidget(Tree *tree, TabEnvironment *tabEnvironment)\n  : QTreeWidget(tree), tree(tree), tabEnvironment(tabEnvironment), dragElement(nullptr)\n{\n  try\n  {\n    setlocale(LC_NUMERIC, \"en_US.UTF-8\"); // force . as decimal separator (QLocale behavior is strange)\n\n    // init QTreeWidget\n    // ----------------\n    QStringList headerLabel;\n    setHeaderLabels(headerLabel<<tr(\"Type\")<<tr(\"Value\")<<tr(\"Description\")<<tr(\"Comment\"));\n    setAlternatingRowColors(true);\n    setRootIsDecorated(false);\n    setItemsExpandable(true);\n    setSortingEnabled(false);\n    setContextMenuPolicy(Qt::CustomContextMenu);\n    setSelectionMode(QAbstractItemView::SingleSelection);\n    header()->setStretchLastSection(true);\n    header()->setSectionsMovable(false);\n    viewport()->setAcceptDrops(true); // internal & external drag\n\n    // set rectangular icon size\n    // -------------------------\n    QLabel *label = new QLabel(this);\n    int height = label->sizeHint().height();\n    setIconSize(QSize(2*height, height));\n    delete label;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeWidget::eventFilter(QObject *obj, QEvent *event)\n{\n  Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();\n\n  if(event->type() == QEvent::KeyPress)\n  {\n    QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);\n    if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab  ||\n      (modifiers == Qt::ControlModifier && keyEvent->key() == Qt::Key_Space))\n    {\n      keyPressEvent(keyEvent);\n      return true;\n    }\n  }\n\n  if(event->type() == QEvent::Wheel && modifiers != Qt::ControlModifier)\n  {\n    QComboBox *combo = qobject_cast<QComboBox*>(obj);\n    if(combo && !combo->hasFocus())\n      return true;\n  }\n\n  // standard event processing\n  return QObject::eventFilter(obj, event);\n}\n\n/***********************************************/\n\n// Key events\n// ----------\nvoid TreeWidget::keyPressEvent(QKeyEvent *event)\n{\n  try\n  {\n    Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();\n    QModelIndex index = currentIndex();\n    QModelIndex newIndex;\n    const int columnEditor = 1;\n\n    auto setNewIndex = [&] ()\n    {\n      if(newIndex.isValid())\n      {\n        setCurrentIndex(newIndex);\n        TreeItem *item = dynamic_cast<TreeItem*>(currentItem());\n        if(item)\n          item->setFocus();\n      }\n    };\n\n    // Enter: Switch focus from tree to input field of selected row\n    if(event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)\n    {\n      newIndex = index.sibling(index.row(), columnEditor);\n      setNewIndex();\n    }\n\n    // Escape: Switch focus from input field back to tree\n    else if(event->key() == Qt::Key_Escape)\n      setFocus();\n\n    // Ctrl+Space: Interact with the element (fileName/program: open dialog, time: switch focus)\n    else if(modifiers.testFlag(Qt::ControlModifier) && event->key() == Qt::Key_Space)\n    {\n      TreeItem *item = dynamic_cast<TreeItem*>(currentItem());\n      if(item)\n        item->treeElement()->interact();\n    }\n\n    // Ctrl+Tab: Next tab\n    else if(event->matches(QKeySequence::NextChild))\n      tabEnvironment->setCurrentIndex((tabEnvironment->currentIndex()+1) % tabEnvironment->count());\n    // Ctrl+Shift+Tab: Previous tab\n    else if(event->matches(QKeySequence::PreviousChild))\n      tabEnvironment->setCurrentIndex((tabEnvironment->currentIndex()-1+tabEnvironment->count()) % tabEnvironment->count());\n\n    // Tab: Next sibling element (or next sibling of parent if there is no next sibling, or next child otherwise)\n    else if(event->key() == Qt::Key_Tab && !event->matches(QKeySequence::NextChild))\n    {\n      if(index.column() != columnEditor)\n        newIndex = index.sibling(index.row(), columnEditor);\n      else\n      {\n        newIndex = index.sibling(index.row()+1, columnEditor);\n        if(!newIndex.isValid())\n        {\n          newIndex = index.parent().sibling(index.parent().row()+1, columnEditor);\n          if(!newIndex.isValid())\n            newIndex = model()->index(0, columnEditor, index);\n        }\n      }\n      setNewIndex();\n    }\n\n    // Shift+Tab: Previous sibling element (or parent if there is no previous sibling)\n    else if(event->key() == Qt::Key_Backtab && !event->matches(QKeySequence::PreviousChild))\n    {\n      if(index.row() == 0)\n        newIndex = index.parent().sibling(index.parent().row(), 1);\n      else\n        newIndex = index.sibling(index.row()-1, 1);\n      setNewIndex();\n    }\n\n    // Ctrl+Shift+Up/Down: Move element\n    else if(modifiers.testFlag(Qt::ControlModifier) && modifiers.testFlag(Qt::ShiftModifier) && (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down))\n    {\n      TreeItem *item = dynamic_cast<TreeItem*>(currentItem());\n      if(item && item->treeElement()->parentElement)\n      {\n        TreeElement *element = item->treeElement();\n        auto children = element->parentElement->children();\n        auto iter = std::find(children.begin(), children.end(), element);\n        if((event->key() == Qt::Key_Up) && (iter != children.begin()))\n          element->parentElement->moveChild(*(--iter), element);\n        else if((event->key() == Qt::Key_Down) && (++iter != children.end()) && (++iter != children.end()))\n          element->parentElement->moveChild(*iter, element);\n      }\n    }\n\n    // other key\n    else\n      QTreeWidget::keyPressEvent(event);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Drag & Drop events\n// ------------------\nvoid TreeWidget::mousePressEvent(QMouseEvent *event)\n{\n  try\n  {\n    if(event->button() == Qt::LeftButton)\n      dragStartPosition = event->pos();\n    QTreeWidget::mousePressEvent(event); // the orginal event handler\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeWidget::mouseMoveEvent(QMouseEvent *event)\n{\n  try\n  {\n    // is there a movement with pressed left button?\n    if((!(event->buttons() & Qt::LeftButton)) ||\n       ((event->pos()-dragStartPosition).manhattanLength() < QApplication::startDragDistance()))\n    {\n      QTreeWidget::mouseMoveEvent(event);  // the orginal event handler\n      return;\n    }\n\n    // is position not over an item?\n    TreeItem *item = dynamic_cast<TreeItem*>(itemAt(dragStartPosition));\n    if(!item || !item->treeElement()->parentElement)\n    {\n      QTreeWidget::mouseMoveEvent(event);  // the orginal event handler\n      return;\n    }\n\n    // start drag\n    // ----------\n    QMimeData *mimeData = createMimeData(item->treeElement());\n    if(!mimeData)\n    {\n      QTreeWidget::mouseMoveEvent(event);  // the orginal event handler\n      return;\n    }\n\n    // perform drag\n    dragElement = item->treeElement();\n    QDrag *drag = new QDrag(this);\n    drag->setMimeData(mimeData);\n    Qt::DropAction result;\n    if(dragElement->parentElement->canRemoveChild(dragElement))\n      result = drag->exec(Qt::MoveAction|Qt::CopyAction, Qt::MoveAction);\n    else\n      result = drag->exec(Qt::CopyAction);\n\n    // delete element from source if its moved\n    if(dragElement && (result == Qt::MoveAction))\n      dragElement->parentElement->removeChild(dragElement);\n    dragElement = nullptr;\n\n    event->accept();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeWidget::dragEnterEvent(QDragEnterEvent *event)\n{\n  try\n  {\n    // file names?\n    if(event->mimeData()->hasUrls())\n    {\n      event->acceptProposedAction();\n      return;\n    }\n\n    if(event->mimeData()->hasFormat(mimeFormatString))\n      event->acceptProposedAction();\n    else\n      event->ignore();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeWidget::dragMoveEvent(QDragMoveEvent *event)\n{\n  try\n  {\n    // file names?\n    if(event->mimeData()->hasUrls())\n    {\n      event->acceptProposedAction();\n      return;\n    }\n\n    // is position over an item?\n    TreeItem *item = dynamic_cast<TreeItem*>(itemAt(event->pos()));\n    XmlNodePtr xmlNode;\n    QString    type, label;\n    if(item && fromMimeData(event->mimeData(), xmlNode, type, label) &&\n       item->treeElement()->parentElement && item->treeElement()->parentElement->canAddChild(item->treeElement(), type, label) &&\n       !((event->proposedAction() == Qt::CopyAction) && !(event->keyboardModifiers() & Qt::ControlModifier)))\n    {\n      // check if element tried to move into itself or its children\n      if(dragElement && (event->source() == this) && (event->possibleActions() & Qt::MoveAction))\n      {\n        for(auto parent = item->treeElement(); parent; parent = parent->parentElement)\n          if(parent == dragElement)\n          {\n            event->ignore();\n            return;\n          }\n      }\n\n      event->acceptProposedAction();\n      return;\n    }\n\n    event->ignore();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeWidget::dropEvent(QDropEvent *event)\n{\n  try\n  {\n    // file names?\n    if(event->mimeData()->hasUrls())\n    {\n      QList<QUrl> urls = event->mimeData()->urls();\n      if((urls.size() == 1) && (event->keyboardModifiers() == Qt::ShiftModifier))\n        tree->fileOpen(urls.at(0).toLocalFile()); // replace current tab\n      else\n        for(int i=0; i<urls.size(); i++)\n          tabEnvironment->fileOpen(urls.at(i).toLocalFile());\n      event->acceptProposedAction();\n      return;\n    }\n\n    // is position over an item?\n    TreeItem *item = dynamic_cast<TreeItem*>(itemAt(event->pos()));\n    XmlNodePtr xmlNode;\n    QString    type, label;\n    if(item && item->treeElement()->parentElement && fromMimeData(event->mimeData(), xmlNode, type, label))\n    {\n      TreeElement *targetElement = item->treeElement();\n      // can directly moved?\n      if(dragElement && (event->source() == this) && (event->dropAction() & Qt::MoveAction))\n      {\n        // check if element tried to move into itself or its children\n        for(auto parent = targetElement; parent; parent = parent->parentElement)\n          if(parent == dragElement)\n          {\n            event->ignore();\n            return;\n          }\n\n        // move within same unbounded list\n        // if(targetElement->parentElement->canMoveChild(targetElement, dragElement))\n        // {\n        //   targetElement->parentElement->moveChild(targetElement, dragElement);\n        //   dragElement = nullptr;\n        //   event->acceptProposedAction();\n        //   return;\n        // }\n\n        tree->undoStack->beginMacro(\"move \"+dragElement->name());\n        dragElement->parentElement->removeChild(dragElement);\n        if(!targetElement->parentElement->addChild(targetElement, type, label, xmlNode))\n        {\n          // abort/end macro and overwrite it with empty command\n          tree->undoStack->endMacro();\n          tree->undoStack->undo();\n          tree->undoStack->push(new QUndoCommand);\n          tree->undoStack->undo();\n          event->ignore();\n          return;\n        }\n        tree->undoStack->endMacro();\n        dragElement = nullptr;\n        event->acceptProposedAction();\n        return;\n      }\n\n      // copy or external source\n      if(targetElement->parentElement->addChild(targetElement, type, label, xmlNode))\n      {\n        event->acceptProposedAction();\n        return;\n      }\n    }\n    event->ignore();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/tree.h",
    "content": "/***********************************************/\n/**\n* @file tree.h\n*\n* @brief Editable tree from XML schema.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREE__\n#define __GROOPSGUI__TREE__\n\n#include <QSettings>\n#include <QTreeWidget>\n#include <QAction>\n#include <QDir>\n#include <QUndoStack>\n#include <QFileSystemWatcher>\n#include \"base/importGroops.h\"\n#include \"base/schema.h\"\n#include \"mainWindow/mainWindow.h\"\n#include \"mainWindow/tabs.h\"\n\n/***** TYPES ***********************************/\n\nclass TreeItem;\nclass TreeElement;\nclass TreeElementGlobal;\nclass TreeElementComplex;\nclass TreeWidget;\n\n/***** CLASS ***********************************/\n\nclass Tree: public QWidget\n{\n  Q_OBJECT\n\n  QSettings      settings;\n  ActionList     actionList;\n  bool           _showResults;\n  bool           _isCurrent;\n  TreeItem      *_selectedItem;\n  Schema         _schema;\n  XsdComplexPtr  _xsdGlobal;\n  QString        _fileNameSchema;\n  bool           _isClean;         // file is unchanged\n  QString        _caption;         // fileName without path or something like 'newX'.\n  QString        _fileName;        // absolute path\n  QDir           workingDirectory;\n\n  void clearTree();\n  bool readSchema();\n\n  friend class TreeItem;\n\npublic:\n  Tree(QWidget *parent, ActionList *actionList, TabEnvironment *tabEnvironment);\n  virtual ~Tree();\n\n  // public variables\n  QUndoStack         *undoStack;\n  TreeElementComplex *rootElement;\n  TreeElementGlobal  *elementGlobal; // set by TreeElementGlobal\n  XsdElementPtr       xsdElementLoop;\n  XsdElementPtr       xsdElementCondition;\n\n  /** @brief Is the tree selected?\n  * Tree reacts in actions (like saveAs).  */\n  bool isCurrent() {return _isCurrent;}\n\n  /** @brief Sets the tree selected. */\n  void setCurrent(bool isCurrent);\n\n  /** @brief Sets the current TreeElement/TreeItem.\n  * Creates the editor elements.\n  * Updates the action list. */\n  void setSelectedItem(TreeItem *item);\n\n  /** @brief Gets the current TreeItem. */\n  TreeItem *selectedItem() const {return _selectedItem;}\n\n  /** @brief Gets the current TreeElement. */\n  TreeElement *selectedElement() const;\n\n  /** @brief Are results of links and expressions are shown?. */\n  bool showResults() const {return _showResults;}\n\n  /** @brief fileName without path or something like 'newX'. */\n  QString caption() const {return _caption;}\n\n  /** @brief the current fileName with absolute path. */\n  QString fileName() const {return _fileName;}\n\n  QString fileNameSchema() const {return _fileNameSchema;}\n\n  /** @brief makes the fileName absolute. */\n  QString addWorkingDirectory(const QString &fileName) const;\n\n  /** @brief makes the fileName relative to the working directory if possible. */\n  QString stripWorkingDirectory(const QString &fileName) const;\n\n  /** @brief Does the current file have no unsaved changes? */\n  bool isClean() const {return _isClean;}\n\n  /** @brief Is it allowed to close the file?\n  * The user is asked to save the file before if necessary.\n  * @return allowed */\n  bool okToAbandon();\n\n  /** @brief Creates a new empty tree.\n  * The user is asked to save the old file before if necessary.\n  * @return success? */\n  bool fileNew(const QString &caption);\n\n  /** @brief Open the file with @a fileName.\n  * If @a fileName is empty try to reload the current file.\n  * The user is asked to save the old file before if necessary.\n  * @return success? */\n  bool fileOpen(QString fileName);\n\nsignals:\n  /** @brief This signal is emitted when the file or status is changed.\n  * @param caption fileName without path or something like 'newX'.\n  * @param fileName the current file (empty if file is new)\n  * @param isClean no unsaved changes */\n  void fileChanged(const QString &caption, const QString &fileName, bool isClean);\n\npublic:\n  const std::vector<XsdElementPtr> &xsdElements() const;\n  XsdElementPtr xsdElement(const QString &type) const;\n  QList<XsdElementPtr> programList() const;\n\npublic slots:\n  void addProgram(const QString &name);\n\n  // check state of file on disk\n  // ---------------------------\nprivate:\n  QFileSystemWatcher *fileWatcher;\n\n  void fileWatcherCreate();\n  void fileWatcherClear();\n\nprivate slots:\n  void fileWatcherChangedExternally();\n\nprivate:\n  // enabling/disabling actions depending on the selected item\n  void updateActions();\n\npublic slots:\n  bool fileSave();\n  bool fileSaveAs();\n  void fileRun();\n  void fileShowInManager();\n  void editCut();\n  void editCopy();\n  void editPaste();\n  void editPasteOverwrite();\n  void editAdd();\n  void editRemove();\n  void editAddVariable();\n  void editSetLoop();\n  void editSetCondition();\n  void editEnabled(bool checked);\n  void editEnableAll();\n  void editDisableAll();\n  void editRename();\n  void editUpdateName();\n  void editAddComment();\n  void editCollapseAll();\n  void editOpenExternally();\n  void helpShowDescriptions(bool);\n  void helpShowResults(bool);\n  void helpOpenDocumentation();\n\n  // ========================================================\n\n  // Layout\n  // ------\n  int  columnWidth(int column) const;\n  void setColumnWidth(int column, int width);\n\nsignals:\n  void sectionResized(int logicalIndex, int oldSize, int newSize);\n\nprivate:\n  QFrame     *barFileExternallyChanged;\n  QFrame     *barBrokenLinks;\n  QFrame     *barUnknownElements;\n  QFrame     *barSchemaRenamedElements;\n  QFrame     *barDeprecatedElements;\n  QLabel     *labelBrokenLinks;\n  QLabel     *labelUnknownElements;\n  QLabel     *labelSchemaRenamedElements;\n  QLabel     *labelDeprecatedElements;\n  int         brokenLinkCount, unknownCount, renamedCount, deprecatedCount;\n  TreeWidget *treeWidget;\n\npublic:\n  void treeChanged();   // slot: called by TreeElements whenever unknowns or renamed could be changed\n\nprivate slots:\n  void undoStackCleanChanged(bool clean);\n  void treeClipboardDataChanged();\n  void treeContextMenuRequested(const QPoint &pos);\n  void treeCurrentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);\n  void treeItemSelectionChanged();\n  void treeItemClicked       (QTreeWidgetItem *item, int column);\n  void treeItemDoubleClicked (QTreeWidgetItem *item, int column);\n  void barFileExternallyChangedReopen();\n  void barBrokenLinksExpand();\n  void barUnknownElementsExpand();\n  void barUnknownElementsRemoveAll();\n  void barSchemaRenamedElementsExpand();\n  void barSchemaRenamedElementsUpdateAll();\n  void barDeprecatedElementsExpand();\n  void barClickedIgnore();\n};\n\n/***********************************************/\n\nclass TreeWidget: public QTreeWidget\n{\n  Q_OBJECT\n\n  Tree           *tree;\n  TabEnvironment *tabEnvironment;\n  QPoint          dragStartPosition;\n  TreeElement    *dragElement;\n\npublic:\n  TreeWidget(Tree *tree, TabEnvironment *tabEnvironment);\n  virtual ~TreeWidget() {}\n\nprotected:\n  bool eventFilter(QObject *obj, QEvent *event) override;\n  bool focusNextPrevChild(bool /*next*/) override {return false;}\n  void keyPressEvent  (QKeyEvent       *event) override;\n  void mousePressEvent(QMouseEvent     *event) override;\n  void mouseMoveEvent (QMouseEvent     *event) override;\n  void dragEnterEvent (QDragEnterEvent *event) override;\n  void dragMoveEvent  (QDragMoveEvent  *event) override;\n  void dropEvent      (QDropEvent      *event) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPSGUI__TREE__ */\n"
  },
  {
    "path": "gui/tree/treeElement.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElement.cpp\n*\n* @brief Node of the tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QComboBox>\n#include <QLineEdit>\n#include <QHeaderView>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n#include \"base/schema.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementSequence.h\"\n#include \"tree/treeElementChoice.h\"\n#include \"tree/treeElementSimple.h\"\n#include \"tree/treeElementBool.h\"\n#include \"tree/treeElementFileName.h\"\n#include \"tree/treeElementTime.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"tree/treeElementLoopCondition.h\"\n#include \"tree/treeElement.h\"\n\n/***********************************************/\n\nTreeElement::UndoCommand::UndoCommand(TreeElement *_treeElement, const QString &name)\n  : QUndoCommand(name+\" \"+_treeElement->name()+\" \"+_treeElement->selectedValue()),\n    treeElement(_treeElement),\n    tree(_treeElement->tree) {}\n\n/***********************************************/\n/***********************************************/\n\nTreeElement *TreeElement::newTreeElement(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement, const QString &defaultOverride,\n                                         XmlNodePtr xmlNode, bool fillWithDefaults)\n{\n  try\n  {\n    if(xsdElement->complex)\n    {\n      if((xsdElement->complex->type==\"sequence\") && xsdElement->names.contains(\"global\"))\n        return new TreeElementGlobal(tree, parentElement, xsdElement, xmlNode);\n      if((xsdElement->type==\"programType\") || (xsdElement->type== \"programmeType\"))\n        return new TreeElementProgram(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n      if(xsdElement->complex->type==\"sequence\")\n        return new TreeElementSequence(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n      if(xsdElement->complex->type==\"choice\")\n        return new TreeElementChoice(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n      throw(Exception(\"unknown complex element\"));\n    }\n\n    if(xsdElement->type==\"boolean\")\n      return new TreeElementBool(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n    if(xsdElement->type==\"filename\")\n      return new TreeElementFileName(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n    if(xsdElement->type==\"time\")\n      return new TreeElementTime(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n    return new TreeElementSimple(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nTreeElement::TreeElement(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement, const QString &defaultOverride, XmlNodePtr xmlNode)\n{\n  try\n  {\n    this->tree             = tree;\n    this->parentElement    = parentElement;\n    this->xsdElement       = xsdElement;\n    if(xsdElement)\n      this->defaultValue = QString (xsdElement->defaultValue);\n    if(!defaultOverride.isEmpty())\n      this->defaultValue   = defaultOverride;\n    this->_selectedIndex   = -1;\n    this->_brokenLinkIndex = -1;\n    this->_valueCount      = 0;\n    this->_pushComment     = false;\n    this->loop             = nullptr;\n    this->condition        = nullptr;\n    this->_disabled        = false;\n    this->_elementAdd      = nullptr;\n    this->_item            = nullptr;\n    this->comboBox         = nullptr;\n\n    if(xsdElement)\n      _name = _schemaName = xsdElement->names.front();\n\n    // evaluation of the XML nodes\n    // ---------------------------\n    if(xmlNode)\n    {\n      _name = xmlNode->getName();\n\n      QString loopLabel;\n      readAttribute(xmlNode, \"loop\", loopLabel);\n      if(!loopLabel.isEmpty())\n      {\n        XmlNodePtr xmlLoop;\n        if(loopLabel == \"_localLoop_\")\n          xmlLoop = xmlNode->getChild(\"loopType\");\n        else\n        {\n          xmlLoop = XmlNode::create(\"loopType\");\n          writeAttribute(xmlLoop, \"link\", loopLabel);\n        }\n        loop = new TreeElementLoopCondition(tree, this, tree->xsdElementLoop, xmlLoop);\n      }\n\n      QString conditionLabel;\n      readAttribute(xmlNode, \"condition\", conditionLabel);\n      if(!conditionLabel.isEmpty())\n      {\n        XmlNodePtr xmlCondition;\n        if(conditionLabel == \"_localCondition_\")\n          xmlCondition = xmlNode->getChild(\"conditionType\");\n        else\n        {\n          xmlCondition = XmlNode::create(\"conditionType\");\n          writeAttribute(xmlCondition, \"link\", conditionLabel);\n        }\n        condition = new TreeElementLoopCondition(tree, this, tree->xsdElementCondition, xmlCondition);\n      }\n\n      readAttribute(xmlNode, \"label\",   _label);\n      readAttribute(xmlNode, \"comment\", _comment);\n      XmlAttrPtr attr = xmlNode->getAttribute(\"disabled\");\n      if(attr && (attr->text == \"1\"))\n        _disabled = true;\n\n      // is this a link?\n      QString link;\n      readAttribute(xmlNode, \"link\", link);\n      if(!link.isEmpty())\n      {\n        _valueList.insert(_valueCount, link);\n        _selectedIndex = _valueCount;\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTreeElement::~TreeElement()\n{\n  removeItem();\n  delete loop;\n  delete condition;\n  setElementAdd(nullptr);\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElement::createXmlBaseNode() const\n{\n  try\n  {\n    XmlNodePtr xmlNode = XmlNode::create(xmlName());\n    if(!label().isEmpty())     writeAttribute(xmlNode, \"label\",     label());\n    if(disabled())             writeAttribute(xmlNode, \"disabled\",  \"1\");\n    if(isLinked())             writeAttribute(xmlNode, \"link\",      selectedValue());\n\n    if(loop)\n    {\n      if(loop->isLinked())\n        writeAttribute(xmlNode, \"loop\", loop->selectedValue());\n      else\n      {\n        writeAttribute(xmlNode, \"loop\", \"_localLoop_\");\n        XmlNodePtr xmlLoop = loop->createXmlTree(true);\n        xmlNode->addChild(xmlLoop);\n      }\n    }\n\n    if(condition)\n    {\n      if(condition->isLinked())\n        writeAttribute(xmlNode, \"condition\", condition->selectedValue());\n      else\n      {\n        writeAttribute(xmlNode, \"condition\", \"_localCondition_\");\n        XmlNodePtr xmlCondition = condition->createXmlTree(true);\n        xmlNode->addChild(xmlCondition);\n      }\n    }\n\n    if(!comment().isEmpty())\n      writeAttribute(xmlNode, \"comment\",   comment());\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nint TreeElement::findValueIndex(const QString &value) const\n{\n  try\n  {\n    for(int i=0; i<_valueCount; i++)\n      if(value == _valueList[i])\n        return i;\n    return -1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nint TreeElement::findLinkIndex(const QString &value) const\n{\n  try\n  {\n    for(int i=_valueCount; i<_valueList.size(); i++)\n      if(value == _valueList[i])\n        return i;\n    return -1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nclass TreeElement::UndoCommandChangeSelectedIndex : public TreeElement::UndoCommand\n{\n  int index;\npublic:\n  UndoCommandChangeSelectedIndex(TreeElement *treeElement, int index) : UndoCommand(treeElement, \"change\"), index(index)\n      {setText(\"change \"+treeElement->name()+\" from \"+treeElement->selectedValue()+\" to \"+treeElement->_valueList[index]);}\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandChangeSelectedIndex::redo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n\n    int indexOld = treeElement->selectedIndex();\n    treeElement->setSelectedIndex(index);\n    index = indexOld;\n    tree->treeChanged();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::changeSelectedIndex(int index)\n{\n  try\n  {\n    if((index<0) || (index>=_valueList.size()))\n      throw(Exception(\"index out of range\"));\n    if(index == _selectedIndex)\n      return;\n    tree->undoStack->push(new UndoCommandChangeSelectedIndex(this, index));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::changeSelectedValue(const QString &value)\n{\n  changeSelectedIndex(insertNewValue(value, true/*prepend*/));\n}\n\n/***********************************************/\n\nvoid TreeElement::changeSelectedLink(const QString &link)\n{\n  try\n  {\n    int selectedIndex = findLinkIndex(link);\n    if(selectedIndex < 0)\n    {\n      selectedIndex = _valueList.size();\n      _valueList.push_back(link);\n      if(comboBox)\n        comboBox->insertItem(comboBox->count(), QIcon(\":/icons/scalable/link.svg\"), link);\n    }\n    changeSelectedIndex(selectedIndex);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElement::setSelectedIndex(int index)\n{\n  try\n  {\n    if((index < 0) || (index >= _valueList.size()))\n      throw(Exception(\"index out of range\"));\n\n    if(index == _selectedIndex)\n      return;\n    _selectedIndex = index;\n\n    // send auto comment\n    if(_pushComment && parentElement)\n      parentElement->setAutoComment(selectedValue());\n\n    if(item())\n      item()->updateValue();\n\n    if(comboBox)\n    {\n      comboBox->setCurrentIndex(_selectedIndex);\n      comboBoxSetToolTip();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nint TreeElement::insertNewValue(const QString &value, bool prepend)\n{\n  try\n  {\n    // is the value already in the list?\n    int index = findValueIndex(value);\n    if(index >= 0)\n      return index;\n\n    if(value.isEmpty())\n      prepend = true;\n\n    // insert at index;\n    index = (prepend) ? 0 : _valueCount;\n    if((index == 0) && (_valueCount > 0) && _valueList[0].isEmpty())\n      index++;\n    _valueList.insert(index, value);\n    _valueCount++;\n    if(_selectedIndex >= index)\n      _selectedIndex++;\n    if(_brokenLinkIndex >= index)\n      _brokenLinkIndex++;\n\n    // update comboBox\n    if(comboBox)\n      comboBox->insertItem(index, value);\n\n    // empty values only allowed at the beginning\n    for(int i=1; i<_valueList.size(); i++)\n      if(_valueList[i].isEmpty())\n      {\n        if(_selectedIndex >= i)\n          _selectedIndex--;\n        if(_brokenLinkIndex >= i)\n          _brokenLinkIndex--;\n        _valueList.removeAt(i);\n        _valueCount--;\n        if(comboBox)\n          comboBox->removeItem(i);\n        i--;\n      }\n\n    if(comboBox && (comboBox->count() != _valueList.size()))\n      throw(Exception(\"comboBox not consistent\"));\n\n    return index;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nVariableListPtr TreeElement::updateParserResults(VariableListPtr varList, Bool /*addVariableInReturn*/)\n{\n  if(loop)      loop->updateParserResults(varList, false);\n  if(condition) condition->updateParserResults(varList, false);\n  return varList;\n}\n\n/***********************************************/\n\nQString TreeElement::getLinkType(const QString &type)\n{\n  static const QStringList numberList({\"int\", \"uint\", \"double\", \"angle\", \"boolean\", \"time\", \"expression\"});\n  static const QStringList stringList({\"string\", \"filename\", \"gnssType\", \"doodson\"});\n  if(numberList.contains(type)) return QString(\"number_\");\n  if(stringList.contains(type)) return QString(\"string_\");\n  return type;\n}\n\n/***********************************************/\n\nvoid TreeElement::updateLinks(QMap<QString, QString> &labelTypes)\n{\n  try\n  {\n    if(loop)      {auto labelTypesLocal = labelTypes; loop->updateLinks(labelTypesLocal);}\n    if(condition) {auto labelTypesLocal = labelTypes; condition->updateLinks(labelTypesLocal);}\n\n    QString linkType = getLinkType(type());\n    if(!label().isEmpty() && !disabled())\n      labelTypes[label()] = linkType;\n\n    // find all links\n    QStringList linkList;\n    for(auto iter = labelTypes.keyValueBegin(); iter != labelTypes.keyValueEnd(); iter++)\n      if((iter->first != label()) && (iter->second == linkType)) // should not linked to self\n        linkList.push_back(iter->first);\n    linkList.sort();\n\n    QString selectedLink;\n    if(isLinked())\n      selectedLink = selectedValue();\n\n    // remove all links and refill\n    while(_valueList.size() > _valueCount)\n      _valueList.removeAt(_valueCount);\n    _valueList<<linkList;\n    if(comboBox)\n    {\n      while(comboBox->count() > _valueCount)\n        comboBox->removeItem(_valueCount);\n      for(const QString &link : linkList)\n        comboBox->insertItem(comboBox->count(), QIcon(\":/icons/scalable/link.svg\"), link);\n    }\n\n    // restore selected link\n    _brokenLinkIndex = -1;\n    if(!selectedLink.isEmpty())\n    {\n      int selectedIndex = findLinkIndex(selectedLink);\n      if(selectedIndex < 0) // broken link\n      {\n        selectedIndex = _valueList.size();\n        _brokenLinkIndex = selectedIndex;\n        _valueList.push_back(selectedLink);\n        if(comboBox)\n          comboBox->insertItem(comboBox->count(), QIcon(\":/icons/scalable/link-broken.svg\"), selectedLink);\n      }\n      setSelectedIndex(selectedIndex);\n      if(comboBox && (comboBox->currentIndex() != selectedIndex))\n      {\n        comboBox->setCurrentIndex(selectedIndex);\n        comboBoxSetToolTip();\n      }\n\n      if(item())\n        item()->updateValue();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n\n/***********************************************/\n/***********************************************/\n\nbool TreeElement::renamedLink(const QString &oldLabel, const QString &newLabel)\n{\n  try\n  {\n    // Is this a new variable with same name (hide scope of renamed)\n    if(label() == oldLabel)\n      return false;\n\n    if(loop)      loop->renamedLink(oldLabel, newLabel);\n    if(condition) condition->renamedLink(oldLabel, newLabel);\n\n    // is this link in the list?\n    int index = findLinkIndex(oldLabel);\n    if(index < 0)\n      return true;\n\n    // replace label\n    _valueList.replace(index, newLabel);\n    if(item())\n      item()->updateValue();\n    if(comboBox && (index < comboBox->count()))\n      comboBox->setItemText(index, newLabel);\n\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElement::UndoCommandSetComment : public TreeElement::UndoCommand\n{\n  QString text;\n\npublic:\n  UndoCommandSetComment(TreeElement *treeElement, const QString &_text)\n    : UndoCommand(treeElement, \"comment\"),\n      text(_text) {}\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandSetComment::redo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n    std::swap(treeElement->_comment, text);\n    if(treeElement->item())\n      treeElement->item()->updateComment();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::setComment(const QString &text)\n{\n  try\n  {\n    if(_comment != text) // is something changed?\n      tree->undoStack->push(new UndoCommandSetComment(this, text));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElement::setAutoComment(const QString &text)\n{\n  try\n  {\n    if((_comment == _autoComment) || (_comment == text))\n      _comment = QString();\n    _autoComment = text;\n    if(item())\n      item()->updateComment();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::setPushAutoComments(bool on)\n{\n  try\n  {\n    _pushComment = on;\n    if(_pushComment && parentElement)\n      parentElement->setAutoComment(selectedValue());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nbool TreeElement::baseOverwrite(XmlNodePtr xmlNode, bool contentOnly)\n{\n  if(!contentOnly)\n  {\n    QString loopLabel, conditionLabel, comment;\n    readAttribute(xmlNode, \"loop\",      loopLabel);\n    readAttribute(xmlNode, \"condition\", conditionLabel);\n    readAttribute(xmlNode, \"comment\",   comment);\n    setComment(comment);\n\n    if(!loopLabel.isEmpty())\n    {\n      XmlNodePtr xmlLoop;\n      if(loopLabel == \"_localLoop_\")\n        xmlLoop = xmlNode->getChild(\"loopType\");\n      else\n      {\n        xmlLoop = XmlNode::create(\"loopType\");\n        writeAttribute(xmlLoop, \"link\", loopLabel);\n      }\n      if(canSetLoop())\n        loop = new TreeElementLoopCondition(tree, this, tree->xsdElementLoop, xmlLoop);\n    }\n\n    if(!conditionLabel.isEmpty())\n    {\n      XmlNodePtr xmlCondition;\n      if(conditionLabel == \"_localCondition_\")\n        xmlCondition = xmlNode->getChild(\"conditionType\");\n      else\n      {\n        xmlCondition = XmlNode::create(\"conditionType\");\n        writeAttribute(xmlCondition, \"link\", conditionLabel);\n      }\n      if(canSetCondition())\n        condition = new TreeElementLoopCondition(tree, this, tree->xsdElementCondition, xmlCondition);\n    }\n  }\n\n  QString link;\n  readAttribute(xmlNode, \"link\", link);\n  if(!link.isEmpty())\n    changeSelectedLink(link);\n  return link.isEmpty();\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElement::UndoCommandSetLoop : public TreeElement::UndoCommand\n{\n  TreeElementLoopCondition *loop;\n\npublic:\n  UndoCommandSetLoop(TreeElement *treeElement, TreeElementLoopCondition *loop)\n    : UndoCommand(treeElement, (loop ? \"set loop for\" : \"remove loop from\")),\n      loop(loop) {}\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandSetLoop::redo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n\n    std::swap(loop, treeElement->loop);\n\n    if(treeElement->loop && treeElement->parentElement)\n    {\n      treeElement->parentElement->updateParserResultsInScope();\n      treeElement->parentElement->updateLinksInScope();\n      tree->treeChanged();\n    }\n\n    if(treeElement->item())\n    {\n      if(treeElement->loop)\n      {\n        treeElement->loop->createItem(treeElement->item(), nullptr/*after*/);\n        tree->setSelectedItem(treeElement->loop->item());\n      }\n      else\n        loop->removeItem();\n\n      treeElement->item()->updateIcon();\n      treeElement->item()->updateName();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElement::canSetLoop() const\n{\n  if(loop || !label().isEmpty())\n    return false;\n  return unbounded();\n}\n\n/***********************************************/\n\nvoid TreeElement::setLoop()\n{\n  try\n  {\n    if(canSetLoop())\n      tree->undoStack->push(new UndoCommandSetLoop(this, new TreeElementLoopCondition(tree, this, tree->xsdElementLoop, nullptr)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElement::UndoCommandSetCondition : public TreeElement::UndoCommand\n{\n  TreeElementLoopCondition *condition;\n\npublic:\n  UndoCommandSetCondition(TreeElement *treeElement, TreeElementLoopCondition *condition)\n    : UndoCommand(treeElement, (condition ?  \"set condition for\" : \"remove condition from\")),\n      condition(condition) {}\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandSetCondition::redo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n\n    std::swap(condition, treeElement->condition);\n\n    if(treeElement->condition && treeElement->parentElement)\n    {\n      treeElement->parentElement->updateParserResultsInScope();\n      treeElement->parentElement->updateLinksInScope();\n      tree->treeChanged();\n    }\n\n    if(treeElement->item())\n    {\n      if(treeElement->condition)\n      {\n        treeElement->condition->createItem(treeElement->item(), (treeElement->loop ? treeElement->loop->item() : nullptr)/*after*/);\n        tree->setSelectedItem(treeElement->condition->item());\n      }\n      else\n        condition->removeItem();\n\n      treeElement->item()->updateIcon();\n      treeElement->item()->updateName();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElement::canSetCondition() const\n{\n  if(condition || !label().isEmpty())\n    return false;\n  return optional() || unbounded();\n}\n\n/***********************************************/\n\nvoid TreeElement::setCondition()\n{\n  try\n  {\n    if(canSetCondition())\n      tree->undoStack->push(new UndoCommandSetCondition(this, new TreeElementLoopCondition(tree, this, tree->xsdElementCondition, nullptr)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::removeLoopOrCondition(TreeElement *element)\n{\n  try\n  {\n    if(element == loop)\n      tree->undoStack->push(new UndoCommandSetLoop(this, nullptr));\n    if(element == condition)\n      tree->undoStack->push(new UndoCommandSetCondition(this, nullptr));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElement::UndoCommandSetEnabled : public TreeElement::UndoCommand\n{\n  bool disabled;\n\npublic:\n  UndoCommandSetEnabled(TreeElement *treeElement, bool disabled)\n  : UndoCommand(treeElement, (disabled ? \"disable\" : \"enable\")),\n  disabled(disabled) {}\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandSetEnabled::redo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n\n    std::swap(disabled, treeElement->_disabled);\n\n    if(!treeElement->label().isEmpty() && treeElement->parentElement)\n    {\n      treeElement->parentElement->updateParserResultsInScope();\n      treeElement->parentElement->updateLinksInScope();\n    }\n\n    if(treeElement->item())\n      treeElement->item()->updateIcon();\n\n    tree->treeChanged();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElement::canDisabled() const\n{\n  if(disabled())\n    return true;  // a disabled element can always be enabled\n  return unbounded() || optional();\n}\n\n/***********************************************/\n\nvoid TreeElement::setDisabled(bool disabled)\n{\n  try\n  {\n    if((disabled != _disabled) && canDisabled())\n      tree->undoStack->push(new UndoCommandSetEnabled(this, disabled));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElement::UndoCommandRename : public TreeElement::UndoCommand\n{\n  QString label;\n\npublic:\n  UndoCommandRename(TreeElement *treeElement, QString label)\n  : UndoCommand(treeElement, \"rename\"), label(label)\n  {\n    setText(\"rename \"+treeElement->name()+\" to \"+label);\n  }\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandRename::redo()\n{\n  try\n  {\n    std::swap(label, treeElement->_label);\n\n    // renames links in other elements\n    auto parent = treeElement->parentElement;\n    if(parent)\n    {\n      const QVector<TreeElement*> &children = parent->children();\n      bool stopped = false;\n      for(int i=children.indexOf(treeElement)+1; i<children.size(); i++)\n        if(!children.at(i)->renamedLink(label, treeElement->_label))\n          {stopped = true; break;}\n\n      // variables in global section are globally valid -> repeat with parent of global\n      if(!stopped && dynamic_cast<TreeElementGlobal*>(parent) && parent->parentElement)\n      {\n        parent = parent->parentElement; // parent of global -> groops\n        const QVector<TreeElement*> &children = parent->children();\n        for(int i=children.indexOf(treeElement->parentElement)+1; i<children.size(); i++) // start after global\n          if(!children.at(i)->renamedLink(label, treeElement->_label))\n            break;\n      }\n\n      parent->updateParserResultsInScope();\n      parent->updateLinksInScope();\n      tree->treeChanged();\n    }\n\n    if(treeElement->item())\n    {\n      tree->setSelectedItem(treeElement->item());\n      treeElement->item()->updateName();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElement::canRename() const\n{\n  return !label().isEmpty();\n}\n\n/***********************************************/\n\nbool TreeElement::rename(const QString &label)\n{\n  try\n  {\n    if(!canRename() || label.isEmpty() || (label == this->label()))\n      return false;\n    tree->undoStack->push(new UndoCommandRename(this, label));\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElement::UndoCommandUpdateName::redo()\n{\n  try\n  {\n    if(!name.isEmpty())\n      std::swap(name,  treeElement->_name);\n    if(!value.isEmpty())\n      std::swap(value, treeElement->_valueList[treeElement->selectedIndex()]);\n\n    if(treeElement->item())\n    {\n      tree->setSelectedItem(treeElement->item());\n      treeElement->item()->lostCurrent();\n      treeElement->item()->updateName();\n      treeElement->item()->updateIcon();\n      treeElement->item()->updateValue();\n      treeElement->item()->becomeCurrent(); // rebuild comboBox\n    }\n\n    tree->treeChanged();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElement::canUpdateName() const\n{\n  return isRenamedInSchema();\n}\n\n/***********************************************/\n\nvoid TreeElement::updateName()\n{\n  try\n  {\n    if(TreeElement::canUpdateName())\n      tree->undoStack->push(new UndoCommandUpdateName(this, QString()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElement::setElementAdd(TreeElementAdd *elementAdd)\n{\n  try\n  {\n    if(_elementAdd)\n      _elementAdd->unboundedCount--;\n    _elementAdd = elementAdd;\n    if(_elementAdd)\n      _elementAdd->unboundedCount++;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nTreeItem *TreeElement::createItem(TreeItem *parent, TreeItem *after)\n{\n  try\n  {\n    if(!_item)\n      _item = TreeItem::newTreeItem(this, parent, after);\n    else\n    {\n      _item->updateIcon();\n      _item->updateValue();\n      _item->updateComment();\n    }\n\n    if(loop)      loop->createItem(_item, nullptr/*after*/);\n    if(condition) condition->createItem(_item, (loop ? loop->item() : nullptr)/*after*/);\n\n    return _item;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::removeItem()\n{\n  try\n  {\n    if(!_item)\n      return;\n    if(loop)      loop->removeItem();\n    if(condition) condition->removeItem();\n    auto parentItem = dynamic_cast<QTreeWidgetItem*>(_item)->parent();\n    if(parentItem)\n      parentItem->removeChild(_item);\n    delete _item;\n    _item = nullptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nQComboBox *TreeElement::createComboBox(bool isEditable)\n{\n  try\n  {\n    // is there a choice?\n    if(!isEditable && (_valueList.size() <= 1))\n      return nullptr;\n\n    comboBox = new QComboBox(tree);\n    comboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));\n    comboBox->setEditable(isEditable);\n    comboBox->setCompleter(nullptr);\n    comboBox->setInsertPolicy(QComboBox::NoInsert);\n    comboBox->installEventFilter(tree);\n    comboBox->setFocusPolicy(Qt::StrongFocus);\n\n    // fill comboBox\n    for(int i=0; i<_valueCount; i++)\n      comboBox->insertItem(comboBox->count(), _valueList[i]);\n    for(int i=_valueCount; i<_valueList.size(); i++)\n      comboBox->insertItem(comboBox->count(), ((i == _brokenLinkIndex) ? QIcon(\":/icons/scalable/link-broken.svg\") : QIcon(\":/icons/scalable/link.svg\")), _valueList[i]);\n    comboBox->setCurrentIndex(_selectedIndex);\n\n    connect(comboBox, SIGNAL(activated(int)), this, SLOT(comboBoxActivated(int)));\n    if(comboBox->lineEdit())\n    {\n      connect(comboBox->lineEdit(), SIGNAL(textEdited(const QString &)), this, SLOT(comboBoxTextEdited(const QString &)));\n      connect(tree, SIGNAL(sectionResized(int, int, int)), this, SLOT(columnResized(int, int, int)));\n    }\n\n    return comboBox;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::comboBoxSetToolTip()\n{\n  try\n  {\n    if(!comboBox || !comboBox->lineEdit())\n      return;\n\n    QLineEdit *lineEdit = comboBox->lineEdit();\n    if(lineEdit->width() < QFontMetrics(lineEdit->font()).boundingRect(lineEdit->text()).width()+7)\n      lineEdit->setToolTip(lineEdit->text());\n    else\n      lineEdit->setToolTip(\"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::comboBoxActivated(int index)\n{\n  try\n  {\n    changeSelectedIndex(index);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElement::UndoCommandEdit::redo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n    treeElement->setSelectedIndex(treeElement->insertNewValue(newValue, true/*prepend*/));\n    tree->treeChanged();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::UndoCommandEdit::undo()\n{\n  try\n  {\n    if(treeElement->item())\n      tree->setSelectedItem(treeElement->item());\n\n    if(isLink)\n      treeElement->setSelectedIndex(treeElement->findLinkIndex(oldValue));\n    else\n      treeElement->setSelectedIndex(treeElement->insertNewValue(oldValue, true/*prepend*/));\n    tree->treeChanged();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElement::UndoCommandEdit::mergeWith(const QUndoCommand *command)\n{\n  try\n  {\n    const UndoCommandEdit *newCommand = dynamic_cast<const UndoCommandEdit*>(command);\n    if(treeElement != newCommand->treeElement)\n      return false;\n\n    // remove old text\n    if(isCreated && (newCommand->newValue != newValue))\n    {\n      int index = treeElement->findValueIndex(newValue);\n      if(index>=0)\n      {\n        treeElement->_valueList.removeAt(index);\n        treeElement->_valueCount--;\n        if(treeElement->_selectedIndex >= index)\n          treeElement->_selectedIndex--;\n        if(treeElement->_brokenLinkIndex >= index)\n          treeElement->_brokenLinkIndex--;\n\n        // update comboBox\n        auto comboBox = treeElement->comboBox;\n        if(comboBox)\n        {\n          int cursorPosition = comboBox->lineEdit()->cursorPosition();\n          comboBox->removeItem(index);\n          comboBox->lineEdit()->setCursorPosition(cursorPosition);\n\n          if(comboBox->count() != treeElement->_valueList.size())\n            throw(Exception(\"comboBox not consistent\"));\n          if(comboBox->currentIndex() != treeElement->_selectedIndex)\n            comboBox->setCurrentIndex(treeElement->_selectedIndex);\n        }\n      }\n    }\n\n    newValue  = newCommand->newValue;\n    isCreated = newCommand->isCreated;\n    setText(\"edit \"+treeElement->name()+\": \"+newValue);\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::comboBoxTextEdited(const QString &text)\n{\n  try\n  {\n    if(isLinked() || (text != selectedValue()))\n      tree->undoStack->push(new UndoCommandEdit(this, text));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElement::columnResized(int column, int /*oldSize*/, int /*newSize*/)\n{\n  try\n  {\n    if((column == 1) && comboBox && comboBox->lineEdit())\n      comboBoxSetToolTip();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElement.h",
    "content": "/***********************************************/\n/**\n* @file treeElement.h\n*\n* @brief Node of the tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENT__\n#define __GROOPSGUI__TREEELEMENT__\n\n#include <QtDebug>\n#include <QPointer>\n#include <QList>\n#include <QStringList>\n#include <QComboBox>\n#include <QUndoCommand>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n#include \"base/schema.h\"\n\n/***** TYPES ***********************************/\n\nclass  Tree;\nclass  TreeElement;\nclass  TreeElementComplex;\nclass  TreeElementProgram;\nclass  TreeElementAdd;\nclass  TreeElementLoopCondition;\nclass  TreeItem;\nclass  QComboBox;\n\ntypedef std::shared_ptr<const VariableList> VariableListPtr;\n\n/***** CLASS ***********************************/\n\nclass TreeElement : public QObject\n{\n  Q_OBJECT\n\nprotected:\n  class UndoCommand : public QUndoCommand\n  {\n  protected:\n    TreeElement *treeElement;\n    Tree        *tree;\n\n  public:\n    UndoCommand(TreeElement *treeElement, const QString &name);\n    virtual ~UndoCommand() {}\n  };\n\nprivate:\n  QString _name, _schemaName, _label;\n\npublic:\n  TreeElement(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement, const QString &defaultOverride, XmlNodePtr xmlNode);\n  virtual ~TreeElement();\n\n  /** @brief Tree of TreeElements from XSD-Schema. *\n  * recursively called for all children. */\n  static TreeElement *newTreeElement(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                                     const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults);\n\n  Tree               *tree;\n  TreeElementComplex *parentElement;\n  XsdElementPtr       xsdElement;\n  QString             defaultValue;\n\n  virtual QString name()              const {return (_label.isEmpty()) ? _name : _label;}\n  virtual QString xmlName()           const {return _name;}\n  virtual QString label()             const {return _label;}\n  virtual QString annotation()        const {return (xsdElement) ? QString (xsdElement->annotation) : QString();}\n  virtual QString type()              const {return (xsdElement) ? QString (xsdElement->type)       : QString();}\n  virtual bool    optional()          const {return (xsdElement) ? xsdElement->optional  : true;}\n  virtual bool    unbounded()         const {return (xsdElement) ? xsdElement->unbounded : false;}\n  virtual bool    isRenamedInSchema() const {return (xmlName() != _schemaName);}\n  virtual bool    isDeprecated()      const {return annotation().startsWith(\"DEPRECATED\");}\n\n  /** @brief Is the selection without coresponding schema? (choice only) */\n  virtual bool isSelectionUnknown(int /*index*/) const  {return false;}\n\n  /** @brief Is the selection renamed (new name in the schema)? (choice only)  */\n  virtual bool isSelectionRenamedInSchema(int /*index*/) const {return false;}\n\n  /** @brief Is the selection deprecated? (choice only) */\n  virtual bool isSelectionDeprecated(int /*index*/) const  {return false;}\n\n  // ========================================================\n\npublic:\n  /** @brief Generate XML-tree.\n  * recursively called for all children. */\n  virtual XmlNodePtr createXmlTree(bool createRootEvenIfEmpty=false) const = 0;\n\nprotected:\n  /** @brief basis of a XML node (starting tag).\n  * sets the attributes (\"label\", \"comment\", \"link\", ...). */\n  XmlNodePtr createXmlBaseNode() const;\n\n  // ========================================================\n\n  // Management of the content\n  // -------------------------\nprotected:\n  int         _selectedIndex;\n  int         _valueCount;        // _selectedIndex >= _valueCount is a link\n  int         _brokenLinkIndex;\n  QStringList _valueList;         // History or Choices\n\n  class UndoCommandChangeSelectedIndex;\n  friend class UndoCommandChangeSelectedIndex;\n\npublic:\n  /** @brief Can values be edited?. */\n  virtual bool isEditable() const {return false;}\n\n  /** @brief the selected index. */\n  int selectedIndex() const {return _selectedIndex;}\n\n  /** @brief the selected value. */\n  const QString &selectedValue() const {return _valueList[_selectedIndex];}\n\n  /** @brief the selected value as result of parser. */\n  virtual QString selectedResult() const {return QString();}\n\n  /** @brief is the selected value a link? */\n  bool isLinked() const {return _selectedIndex >= _valueCount;}\n\n  /** @brief is the selected value a broken link? */\n  bool isBrokenLinked() const {return _selectedIndex == _brokenLinkIndex;}\n\n  /** @brief find index of a value.\n  * returns -1 if not found. */\n  int findValueIndex(const QString &value) const;\n\n  /** @brief find index of a link.\n  * returns -1 if not found. */\n  int findLinkIndex(const QString &value) const;\n\n  /** @brief changes the current index.\n  * - calls setSelectedIndex\n  * Is undoable. */\n  void changeSelectedIndex(int index);\n\n  /** @brief changes the current index.\n  * - calls changeSelectedIndex\n  * Is undoable. */\n  void changeSelectedValue(const QString &value);\n\n  /** @brief changes the current index.\n  * - calls changeSelectedIndex\n  * Is undoable. */\n  void changeSelectedLink(const QString &link);\n\nprotected:\n  /** @brief changes the current index.\n  * if selected index is changed:\n  * - create auto comment\n  * - update item and comboBox\n  * - call tree->setChanged() */\n  virtual void setSelectedIndex(int index);\n\n  /** @brief insert a new value into the valueList.\n  * the selectedIndex/selectedValue is not changed.\n  * @return the index of the new value */\n  int insertNewValue(const QString &value, bool prepend=false);\n\n  // Inform about changes in variables\n  // ---------------------------------\npublic:\n  /** @brief inform this element about a renamed link.\n   * recursively called for all children.\n   * @return next element can also be renamed. */\n  virtual bool renamedLink(const QString &oldLabel, const QString &newLabel);\n\nprotected:\n  /** @brief inform this element about changed variables.\n  * recursively called for all children.\n  * If this element is a variable and @a addVariableInReturn an updated varList is returned. */\n  virtual VariableListPtr updateParserResults(VariableListPtr varList, Bool addVariableInReturn);\n\n  static QString getLinkType(const QString &type);\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children. */\n  virtual void updateLinks(QMap<QString, QString> &labelTypes);\n\n  friend class TreeElementComplex;\n  friend class TreeElementGlobal;\n  friend class TreeElementLoopCondition;\n\n  // ========================================================\n\n  // Overwrite\n  // ---------\nprotected:\n  /** @brief Copy loop, conditions, comments and links from @a xmlNode.\n  * Is undoable.\n  * if @a contentOnly loop,conditions and comments are not copied.\n  * @return is not link -> do more */\n  bool baseOverwrite(XmlNodePtr xmlNode, bool contentOnly=false);\n\npublic:\n  /** @brief Is it possible to overweite the element? */\n  virtual bool canOverwrite(const QString &/*type*/) {return false;}\n\n  /** @brief Copy the content of @a xmlNode into this.\n  * Is undoable.\n  * @return success */\n  virtual bool overwrite(const QString &/*type*/, XmlNodePtr /*xmlNode*/, bool /*contentOnly*/=false) {return false;}\n\n  // ========================================================\n\n  // Set/remove loop for elements\n  // ----------------------------\nprivate:\n  class UndoCommandSetLoop;\n  friend class UndoCommandSetLoop;\n\npublic:\n  TreeElementLoopCondition *loop;\n\n  /** @brief Is it possible to set a loop for the element?\n  * Loops can only be set for unbounded elements, but not for the add element or global elements. */\n  virtual bool canSetLoop() const;\n\n  /** @brief Set loop for element.\n  * Is undoable. */\n  void setLoop();\n\n  // ========================================================\n\n  // Set/remove conditions for elements\n  // ----------------------------------\nprivate:\n  class UndoCommandSetCondition;\n  friend class UndoCommandSetCondition;\n\npublic:\n  TreeElementLoopCondition *condition;\n\n  /** @brief Is it possible to set a condition for the element?\n  * Conditions can only be set for unbounded elements, but not for the add element or global elements. */\n  virtual bool canSetCondition() const;\n\n  /** @brief Set condition for element.\n  * Is undoable. */\n  void setCondition();\n\n  /** @brief Remove loop/condition for element.\n  * Is undoable. */\n  void removeLoopOrCondition(TreeElement *element);\n\n  // ========================================================\n\n  // Enable/Diable elements\n  // ----------------------\nprivate:\n  bool _disabled;\n\n  class UndoCommandSetEnabled;\n  friend class UndoCommandSetEnabled;\n\npublic:\n  /** @brief Is the element disabled? */\n  bool disabled() const {return _disabled;}\n\n  /** @brief Is it possible to disable the element?\n   * optional or unbounded elements can be disabled. */\n  virtual bool canDisabled() const;\n\n  /** @brief disable/enable the element.\n   * Is undoable. */\n  void setDisabled(bool disabled=true);\n\n  // ========================================================\n\n  // Rename elements\n  // ---------------\nprivate:\n  class UndoCommandRename;\n  friend class UndoCommandRename;\n\npublic:\n  /** @brief Is it possible to rename the element? */\n  virtual bool canRename() const;\n\n  /** @brief Rename the element.\n  * Is undoable.\n  * All elements informed by @a renamedLink() and @a updateParserResults(). */\n  virtual bool rename(const QString &label);\n\n  // ========================================================\n\n  // Update name of elements in case of schema changes\n  // -------------------------------------------------\nprotected:\n  class UndoCommandUpdateName : public UndoCommand\n  {\n    QString name, value;\n\n  public:\n    UndoCommandUpdateName(TreeElement *treeElement, const QString &value)\n    : UndoCommand(treeElement, \"update name\"), name(treeElement->_schemaName), value(value) {}\n\n    void redo();\n    void undo() {redo();}\n  };\n  friend class UndoCommandUpdateName;\n\npublic:\n  /** @brief Is it possible to update name of the element?\n  * Only elements with name changes in the schema can be updated. */\n  virtual bool canUpdateName() const;\n\n  /** @brief Update name of the element.\n  * Is undoable. */\n  virtual void updateName();\n\n  // ========================================================\n\n  // comments\n  // --------\nprivate:\n  QString _comment;\n  QString _autoComment;\n  bool    _pushComment;\n\n  class UndoCommandSetComment;\n  friend class UndoCommandSetComment;\n\n  // @brief Receive a new auto-comment.\n  // auto-comment is send by setSelectedValue() to the parent.\n  void setAutoComment(const QString &text);\n\npublic:\n  /** @brief comment of this element. */\n  const QString &comment() const {return (_comment.isEmpty()) ? _autoComment : _comment;}\n\n  /** @brief Can element be commented. */\n  virtual bool canComment() const {return true;}\n\n  /** @brief sets a new comment.\n  * - item->setText() is called\n  * Is undoable. */\n  void setComment(const QString &text);\n\n  /** @brief Should this element send its value as auto-comment to the parent element?\n  * Auto-comment is send by setSelectedValue() to the parent.\n  * An Auto-comment never overwrites a real comment. */\n  void setPushAutoComments(bool on=true);\n\n  // ========================================================\n\n  // Unbounded lists (managed in the add-element)\n  // --------------------------------------------\nprivate:\n  TreeElementAdd *_elementAdd;\n\npublic:\n  /** @brief Add this element to an unbounded list.\n  * Must only be used in TreeElementComplex.\n  * Adjust the element counter in addElement. */\n  void setElementAdd(TreeElementAdd *elementAdd);\n\n  /** @brief If this is unbounded() returns the add element.\n  * the add element contains the counter of elements in the unbounded list.\n  * Overwritten by ElementAdd. */\n  virtual TreeElementAdd *elementAdd() const {return _elementAdd;}\n\n  // ========================================================\n\n  // TreeItem: visual element (one line in the tree widget)\n  // ------------------------------------------------------\nprivate:\n  TreeItem *_item;\n\npublic:\n  /** @brief pointer to visual element. */\n  TreeItem *item() const {return _item;}\n\n  /** @brief create visual element. */\n  virtual TreeItem *createItem(TreeItem *parent, TreeItem *after);\n\n  /** @brief remove visual element. */\n  virtual void removeItem();\n\nprivate:\n  QPointer<QComboBox> comboBox;\n  void comboBoxSetToolTip();\n\nprotected:\n  class UndoCommandEdit : public UndoCommand\n  {\n    bool    isCreated, isLink;\n    QString newValue, oldValue;\n\n  public:\n    UndoCommandEdit(TreeElement *treeElement, const QString &text)\n    : UndoCommand(treeElement, \"edit\"), isCreated(treeElement->findValueIndex(text)<0), isLink(treeElement->isLinked()),\n      newValue(text), oldValue(treeElement->selectedValue())\n      {setText(\"edit \"+treeElement->name()+\": \"+text);}\n\n    int  id() const {return 999;}\n    void redo();\n    void undo();\n    bool mergeWith(const QUndoCommand *command);\n  };\n  friend class UndoCommandEdit;\n\n  /** @brief create a combo box.\n  * The combo box is filled with values and links.\n  * Connections are set. */\n  QComboBox *createComboBox(bool isEditable);\n\npublic:\n  /** @brief Create the editor element.\n  * Is called from item when the it gets the focus.\n  * The editor is deleted by the caller. */\n  virtual QWidget *createEditor() {return nullptr;}\n\n  /** @brief Interacts with the element (open dialog, ...).\n  * Used by TreeElementFileName, TreeElementProgram, and TreeElementTime. */\n  virtual void interact() {}\n\n  /** @brief event handler called by item when it gets selected.\n  * Used by TreeElementChoice. */\n  virtual void startSelected()  {}\n\n  /** @brief event handler called by item when it losts the selection.\n  * Used by TreeElementChoice. */\n  virtual void stopSelected() {}\n\npublic slots:\n  void comboBoxActivated(int index);\n  void comboBoxTextEdited(const QString &text);\n  void columnResized(int column, int oldSize, int newSize);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementAdd.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementAdd.cpp\n*\n* @brief The add element for unbounded elements.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#include <QPushButton>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"addVariableDialog/addVariableDialog.h\"\n\n/***********************************************/\n\nTreeElementAdd::TreeElementAdd(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                               const QString &defaultOverride, bool visible)\n  : TreeElement(tree, parentElement, xsdElement, defaultOverride, XmlNodePtr(nullptr)), unboundedCount(0), visible(visible)\n{\n  try\n  {\n    insertNewValue(\"...\", false);\n    setSelectedIndex(0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nTreeItem *TreeElementAdd::createItem(TreeItem *parent, TreeItem *after)\n{\n  try\n  {\n    if(!visible)\n      return nullptr;\n    return TreeElement::createItem(parent, after);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nQWidget *TreeElementAdd::createEditor()\n{\n  try\n  {\n    // create Pushbutton\n    QPushButton *pushButton = new QPushButton(QIcon(\":/icons/scalable/edit-add.svg\"), tr(\"&Add\"), tree);\n    pushButton->setDefault(true);\n\n    // signals and slots connections\n    connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));\n\n    return pushButton;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementAdd::pushButtonClicked()\n{\n  try\n  {\n    if(dynamic_cast<TreeElementGlobal*>(parentElement))\n      parentElement->addChild(this, \"\", \"\", XmlNodePtr(nullptr));\n    else\n      parentElement->addChild(this, type(), \"\", XmlNodePtr(nullptr));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementAdd.h",
    "content": "/***********************************************/\n/**\n* @file treeElementAdd.h\n*\n* @brief The add element for unbounded elements.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTADD__\n#define __GROOPSGUI__TREEELEMENTADD__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElement.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementAdd : public TreeElement\n{\n  Q_OBJECT\n\npublic:\n  UInt unboundedCount;\n  bool visible;\n\npublic:\n  TreeElementAdd(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                 const QString &defaultOverride, bool visible=true);\n\n  bool optional()          const override {return false;}\n  bool unbounded()         const override {return true;}\n  bool isRenamedInSchema() const override {return false;}\n  bool isDeprecated()      const override {return false;}\n\n  /** @brief Generate XML-tree. *\n  * the add button will not be saved. */\n  XmlNodePtr createXmlTree(bool /*createRootEvenIfEmpty*/) const override {return XmlNodePtr(nullptr);}\n\n  /** @brief returns the add element.\n  * @return this */\n  TreeElementAdd *elementAdd() const override {return const_cast<TreeElementAdd*>(this);}\n\n  bool canSetLoop()      const override {return false;}\n  bool canSetCondition() const override {return false;}\n  bool canDisabled()     const override {return false;}\n  bool canComment()      const override {return false;}\n\n  /** @brief creates visual element (if visible). */\n  TreeItem *createItem(TreeItem *parent, TreeItem *after) override;\n\n  /** @brief creates a push button. */\n  QWidget *createEditor() override;\n\n  /** @brief Adds element. */\n  void interact() override {pushButtonClicked();}\n\npublic slots:\n  void pushButtonClicked();\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementBool.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementBool.cpp\n*\n* @brief Element with true or false.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementBool.h\"\n\n/***********************************************/\n\nTreeElementBool::TreeElementBool(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                                 const QString &defaultOverride, XmlNodePtr xmlNode, bool /*fillWithDefaults*/)\n  : TreeElement(tree, parentElement, xsdElement, defaultOverride, xmlNode)\n{\n  try\n  {\n    insertNewValue(\"no\",  false);\n    insertNewValue(\"yes\", false);\n\n    int index=0;\n    if(xmlNode)\n    {\n      if(xmlNode->getText()==\"1\")\n        index=1;\n      else if(!isLinked() && xmlNode->getText()!=\"0\")\n        throw(Exception(\"xml node doesn't match with schema\"));\n    }\n    else if(defaultValue==\"1\")\n      index=1;\n\n    setSelectedIndex(isLinked() ? selectedIndex() : index);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementBool::createXmlTree(bool /*createRootEvenIfEmpty*/) const\n{\n  try\n  {\n    XmlNodePtr xmlNode = TreeElement::createXmlBaseNode();\n    if(!isLinked())\n      xmlNode->setText(selectedValue()==\"yes\" ? \"1\" : \"0\");\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementBool::overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly)\n{\n  try\n  {\n    if(!canOverwrite(type) || !xmlNode)\n      return false;\n\n    tree->undoStack->beginMacro(\"overwrite \"+name());\n    if(baseOverwrite(xmlNode, contentOnly))\n      changeSelectedIndex(xmlNode->getText() == \"1\");\n    tree->undoStack->endMacro();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementBool.h",
    "content": "/***********************************************/\n/**\n* @file treeElementBool.h\n*\n* @brief Element with true or false.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTBOOL__\n#define __GROOPSGUI__TREEELEMENTBOOL__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementSimple.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementBool : public TreeElement\n{\n  Q_OBJECT\n\npublic:\n  TreeElementBool(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                  const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults);\n\n  /** @brief Values cannot be edited. */\n  bool isEditable() const override {return false;}\n\n  /** @brief Generate XML-tree. */\n  XmlNodePtr createXmlTree(bool /*createRootEvenIfEmpty*/) const override;\n\n  /** @brief Is it possible to overweite the element? */\n  bool canOverwrite(const QString &type) override {return (this->type() == type);}\n\n  /** @brief Copy the content of @a xmlNode into this.\n  * Is undoable.\n  * @return success */\n  bool overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly=false) override;\n\n  /** @brief creates an uneditable combo box. */\n  QWidget *createEditor() override {return createComboBox(false);}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementChoice.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementChoice.cpp\n*\n* @brief Choice element with children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QComboBox>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementChoice.h\"\n\n/***********************************************/\n\nTreeElementChoice::TreeElementChoice(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement, const QString &defaultOverride,\n                                     XmlNodePtr xmlNode, bool fillWithDefaults, bool recieveAutoComments)\n  : TreeElementComplex(tree, parentElement, xsdElement, defaultOverride, xmlNode, recieveAutoComments)\n{\n  try\n  {\n    if(optional() && !unbounded())\n    {\n      addChoice(\"<none>\", XsdElementPtr(nullptr), QJsonObject());\n      schemaNameList.push_back(\"<none>\");\n      annotationList.push_back(\"\");\n    }\n\n    // create children list from XSD schema\n    for(auto &xsdElement : xsdElement->complex->elements)\n    {\n      addChoice(xsdElement->names.front(), xsdElement, defaultObject.value(xsdElement->names.front()).toObject());\n      schemaNameList.push_back(xsdElement->names.front());\n      annotationList.push_back(xsdElement->annotation);\n    }\n\n    int index = 0;\n    if(isLinked())\n      index = selectedIndex();\n    else if(xmlNode) // values from XML\n    {\n      XmlNodePtr xmlNode2 = xmlNode->getNextChild();\n      if(!xmlNode2)\n        throw(Exception(xmlNode->getName().toStdString()+\": xml node doesn't match with schema\"));\n      XsdElementPtr xsdChoice = xsdElement->complex->getXsdElement(xmlNode2->getName()); // find also renamed\n      if(xsdChoice)\n        index = findValueIndex(xsdChoice->names.front());\n      else // unkown element\n      {\n        index = addChoice(xmlNode2->getName(), XsdElementPtr(nullptr), QJsonObject());\n        schemaNameList.push_back(\"[unknown]\");\n        annotationList.push_back(\"\");\n      }\n      _valueList[index] = xmlNode2->getName(); // if renamed\n      createChildrenElements(index, xmlNode2);\n    }\n    else if(fillWithDefaults && !defaultObject.isEmpty()) // from default\n      index = std::max(findValueIndex(defaultObject.begin().key()), 0);\n\n    TreeElementComplex::setSelectedIndex(index);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementChoice::isSelectionRenamedInSchema(int index) const\n{\n  return (index < schemaNameList.size()) && (_valueList[index] != schemaNameList[index]) && (schemaNameList[index] != \"[unknown]\");\n}\n\n/***********************************************/\n\nbool TreeElementChoice::isSelectionUnknown(int index) const\n{\n  return (index < schemaNameList.size()) && (schemaNameList[index] == \"[unknown]\");\n}\n\n/***********************************************/\n\nbool TreeElementChoice::isSelectionDeprecated(int index) const\n{\n  return (index < annotationList.size()) && (annotationList[index].startsWith(\"DEPRECATED\"));\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementChoice::createXmlTree(bool /*createRootEvenIfEmpty*/) const\n{\n  try\n  {\n    if(selectedValue()==\"<none>\")\n      return XmlNodePtr(nullptr);\n    XmlNodePtr xmlNode = createXmlBaseNode();\n    if(isLinked())\n      return xmlNode;\n    XmlNodePtr xmlNodeChoice = XmlNode::create(selectedValue());\n    xmlNode->addChild(xmlNodeChoice);\n    createXmlChildren(xmlNodeChoice);\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementChoice::setSelectedIndex(int index)\n{\n  try\n  {\n    TreeElementComplex::setSelectedIndex(index);\n\n    if(item())\n    {\n      if(item() == tree->selectedItem())\n        item()->updateAnnotation((index < annotationList.size()) ? annotationList[index] : QString());\n      else\n        item()->updateAnnotation(annotation());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementChoice::overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly)\n{\n  try\n  {\n    if(!canOverwrite(type))\n      return false;\n\n    if(!xmlNode && optional() && !unbounded()) // <none>\n    {\n      tree->undoStack->beginMacro(\"overwrite \"+name());\n      changeSelectedIndex(0);\n      tree->undoStack->endMacro();\n      return true;\n    }\n\n    if(!xmlNode || !xmlNode->hasChildren())\n      return false;\n\n    tree->undoStack->beginMacro(\"overwrite \"+name());\n    if(baseOverwrite(xmlNode, contentOnly))\n    {\n      XmlNodePtr xmlNode2 = xmlNode->getNextChild();\n      int index = findValueIndex(xmlNode2->getName());\n      if(index < 0) // possible renamed\n      {\n        XsdElementPtr xsdChoice = xsdElement->complex->getXsdElement(xmlNode2->getName()); // find also renamed\n        if(xsdChoice)\n          for(auto &name : xsdChoice->names)\n          {\n            index = findValueIndex(name);\n            if(index >= 0)\n              break;\n          }\n      }\n      if(index < 0) // unknown element\n      {\n        index = addChoice(xmlNode2->getName(), XsdElementPtr(nullptr), QJsonObject());\n        schemaNameList.push_back(xmlNode2->getName());\n        annotationList.push_back(\"\");\n      }\n      changeSelectedIndex(index);\n      overwriteChildren(xmlNode2);\n    }\n    tree->undoStack->endMacro();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nbool TreeElementChoice::canUpdateName() const\n{\n  return TreeElementComplex::canUpdateName() || isSelectionRenamedInSchema(selectedIndex());\n}\n\n/***********************************************/\n\nvoid TreeElementChoice::updateName()\n{\n  if(canUpdateName())\n    tree->undoStack->push(new UndoCommandUpdateName(this, isSelectionRenamedInSchema(selectedIndex()) ? schemaNameList[selectedIndex()] : QString()));\n}\n\n/***********************************************/\n/***********************************************/\n\nQWidget *TreeElementChoice::createEditor()\n{\n  try\n  {\n    QComboBox *comboBox = createComboBox(false);\n    if(!comboBox)\n      return comboBox;\n    for(int i=0; i<comboBox->count(); i++)\n    {\n      if(isSelectionRenamedInSchema(i))\n        comboBox->setItemIcon(i, QIcon(\":/icons/scalable/edit-rename.svg\"));\n      else if(isSelectionUnknown(i))\n        comboBox->setItemIcon(i, QIcon(\":/icons/scalable/element-unknown.svg\"));\n      else if(isSelectionDeprecated(i))\n        comboBox->setItemIcon(i, QIcon(\":/icons/scalable/warning.svg\"));\n    }\n    connect(comboBox, SIGNAL(highlighted(int)), this, SLOT(comboBoxHighlighted(int)));\n\n    return comboBox;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementChoice::comboBoxHighlighted(int index)\n{\n  if(item())\n    item()->updateAnnotation((index < annotationList.size()) ? annotationList[index] : QString());\n}\n\n/***********************************************/\n\nvoid TreeElementChoice::startSelected()\n{\n  if(item())\n    item()->updateAnnotation((selectedIndex() < annotationList.size()) ? annotationList[selectedIndex()] : QString());\n}\n\n/***********************************************/\n\n\nvoid TreeElementChoice::stopSelected()\n{\n  if(item())\n    item()->updateAnnotation(annotation());\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementChoice.h",
    "content": "/***********************************************/\n/**\n* @file treeElementChoice.h\n*\n* @brief Choice element with children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTCHOICE__\n#define __GROOPSGUI__TREEELEMENTCHOICE__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementComplex.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementChoice : public TreeElementComplex\n{\n  Q_OBJECT\n\n  QStringList schemaNameList;\n  QStringList annotationList;\n\npublic:\n  TreeElementChoice(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement, const QString &defaultOverride,\n                    XmlNodePtr xmlNode, bool fillWithDefaults, bool recieveAutoComments=false);\n\n  /** @brief Is the selection without coresponding schema? */\n  bool isSelectionUnknown(int index) const override;\n\n  /** @brief Is the selection renamed (new name in the schema)? */\n  bool isSelectionRenamedInSchema(int index) const override;\n\n  /** @brief Is the selection deprecated? */\n  bool isSelectionDeprecated(int index) const override;\n\n  /** @brief Generate XML-tree.\n  * recursively called for all children. */\n  XmlNodePtr createXmlTree(bool /*createRootEvenIfEmpty*/) const override;\n\n  /** @brief changes the current index.\n  * calls TreeElemenComplex::selectIndex\n  * updates annotation */\n  void setSelectedIndex(int index) override;\n\n  /** @brief Is it possible to overweite the element? */\n  bool canOverwrite(const QString &type) override {return (this->type() == type);}\n\n  /** @brief Copy the content of @a xmlNode into this.\n  * Is undoable.\n  * @return success */\n  bool overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly=false) override;\n\n  // ========================================================\n\n  // Update name of elements in case of schema changes\n  // -------------------------------------------------\n  /** @brief Is it possible to update name of the element?\n  * Only elements with name changes in the schema can be updated. */\n  bool canUpdateName() const override;\n\n  /** @brief Update name of the element.\n  * Is undoable. */\n  void updateName() override;\n\n  // ========================================================\n\n  /** @brief creates an uneditable combo box. */\n  QWidget *createEditor() override;\n\n  /** @brief event handler called by item when it gets selected. */\n  void startSelected() override;\n\n  /** @brief event handler called by item when it losts the selection. */\n  void stopSelected() override;\n\nprotected slots:\n  void comboBoxHighlighted(int index);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementComment.cpp",
    "content": "/***********************************************/\n/**\n * @file treeElementComment.cpp\n *\n * @brief Comment element.\n *\n * @author Torsten Mayer-Guerr\n * @date 2023-06-21\n */\n/***********************************************/\n\n#include <QtDebug>\n#include <QTextEdit>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElementComment.h\"\n\n/***********************************************/\n\nTreeElementComment::TreeElementComment(Tree *tree, TreeElementComplex *parentElement, const QString &text)\n  : TreeElement(tree, parentElement, nullptr, QString(), nullptr)\n{\n  try\n  {\n    insertNewValue(text, false);\n    setSelectedIndex(0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementComment::createXmlTree(bool createRootEvenIfEmpty) const\n{\n  try\n  {\n    if(selectedValue().isEmpty() && !createRootEvenIfEmpty)\n       return XmlNodePtr(nullptr);\n    XmlNodePtr xmlNode = XmlNode::create(\"COMMENT\");\n    xmlNode->setText(selectedValue());\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComment::setSelectedIndex(int index)\n{\n  TreeElement::setSelectedIndex(index);\n  if(textEditor && (selectedValue() != textEditor->toPlainText()))\n    textEditor->setPlainText(selectedValue());\n}\n\n/***********************************************/\n\nbool TreeElementComment::overwrite(const QString &type, XmlNodePtr xmlNode, bool /*contentOnly*/)\n{\n  try\n  {\n    if(!canOverwrite(type) || !xmlNode)\n      return false;\n\n    tree->undoStack->beginMacro(\"overwrite \"+name());\n    changeSelectedValue(xmlNode->getText());\n    tree->undoStack->endMacro();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nQWidget *TreeElementComment::createEditor()\n{\n  try\n  {\n    textEditor = new QTextEdit(tree);\n    textEditor->setContentsMargins(0,0,0,0);\n    textEditor->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));\n    textEditor->setWordWrapMode(QTextOption::NoWrap);\n    textEditor->setTabChangesFocus(true);\n    textEditor->setTextInteractionFlags(Qt::TextEditorInteraction);\n    textEditor->setUndoRedoEnabled(false); // own implementation\n    textEditor->setFocusPolicy(Qt::StrongFocus);\n    textEditor->installEventFilter(tree);\n    textEditor->setPlainText(selectedValue());\n\n    QFontMetrics fontMetrics(textEditor->document()->defaultFont());\n    textEditor->setFixedHeight(fontMetrics.size(0, textEditor->toPlainText()+\"\\n\\nextraline\").height() + 2*textEditor->frameWidth());\n\n    connect(textEditor, SIGNAL(textChanged()), this, SLOT(textEditorTextChanged()));\n    return textEditor;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComment::textEditorTextChanged()\n{\n  try\n  {\n    if(isLinked() || (textEditor->toPlainText() != selectedValue()))\n      tree->undoStack->push(new UndoCommandEdit(this, textEditor->toPlainText()));\n\n    // adjust size\n    QFontMetrics fontMetrics(textEditor->document()->defaultFont());\n    textEditor->setFixedHeight(fontMetrics.size(0, textEditor->toPlainText()+\"\\n\\nextraline\").height() + 2*textEditor->frameWidth());\n    if(item())\n      item()->setSizeHint(1, textEditor->size());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementComment.h",
    "content": "/***********************************************/\n/**\n* @file treeElementComment.h\n*\n* @brief Comment element.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-06-21\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTCOMMENT__\n#define __GROOPSGUI__TREEELEMENTCOMMENT__\n\n#include <QPointer>\n#include \"base/importGroops.h\"\n#include \"tree/treeElement.h\"\n\n/***** TYPES ***********************************/\n\nclass QTextEdit;\n\n/***** CLASS ***********************************/\n\nclass TreeElementComment : public TreeElement\n{\n  Q_OBJECT\n\n  QPointer<QTextEdit> textEditor;\n\npublic:\n  TreeElementComment(Tree *tree, TreeElementComplex *parentElement, const QString &text);\n ~TreeElementComment() {}\n\n  QString name()              const override {return \"comment\";}\n  QString xmlName()           const override {return \"COMMENT\";}\n  QString label()             const override {return QString();}\n  QString type()              const override {return \"COMMENT\";}\n  bool    optional()          const override {return true;}\n  bool    unbounded()         const override {return true;}\n  bool    isRenamedInSchema() const override {return false;}\n  bool    isDeprecated()      const override {return false;}\n\n  /** @brief Generate XML-tree. */\n  XmlNodePtr createXmlTree(bool createRootEvenIfEmpty) const override;\n\n  /** @brief Values can be edited. */\n  bool isEditable() const override {return true;}\n\n  /** @brief Updates editor. */\n  void setSelectedIndex(int index) override;\n\n   /** @brief Is it possible to overweite the element? */\n  bool canOverwrite(const QString &type) override {return (this->type() == type);}\n\n  /** @brief Copy the content of @a xmlNode into this.\n  * Is undoable.\n  * @return success */\n  bool overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly=false) override;\n\n  bool canSetLoop()      const override {return false;}\n  bool canSetCondition() const override {return false;}\n  bool canDisabled()     const override {return false;}\n  bool canComment()      const override {return false;}\n\n  /** @brief creates an editable combo box. */\n  QWidget *createEditor() override;\n\nprivate slots:\n  void textEditorTextChanged();\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementComplex.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementComplex.cpp\n*\n* @brief Abstract element with children (sequence or choice).\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QJsonDocument>\n#include <QJsonObject>\n#include <QJsonArray>\n#include \"base/importGroops.h\"\n#include \"base/xml.h\"\n#include \"base/schema.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"tree/treeElementLoopCondition.h\"\n#include \"tree/treeElementComment.h\"\n#include \"tree/treeElementUnknown.h\"\n#include \"tree/treeElementComplex.h\"\n\n/***********************************************/\n\nTreeElementComplex::TreeElementComplex(Tree *tree, TreeElementComplex *parentElement,\n                                       XsdElementPtr xsdElement, const QString &defaultOverride,\n                                       XmlNodePtr xmlNode, bool recieveAutoComments)\n                   : TreeElement(tree, parentElement, xsdElement, defaultOverride, xmlNode),\n                     recieveAutoComments(recieveAutoComments),\n                     initializedVariables(false)\n{\n  // convert default string to QJsonObject\n  if(!defaultValue.isEmpty())\n  {\n    QJsonDocument doc = QJsonDocument::fromJson(defaultValue.toUtf8());\n    if(!doc.isNull() && doc.isObject())\n      defaultObject = doc.object();\n    else\n      defaultObject = QJsonDocument::fromJson(QString(\"{\\\"\"+defaultValue+\"\\\" : {}}\").toUtf8()).object();\n  }\n}\n\n/***********************************************/\n\nTreeElementComplex::~TreeElementComplex()\n{\n  for(auto &childdrenAtIndex : children_)\n    for(auto &child : childdrenAtIndex)\n      delete child;\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::createXmlChildren(XmlNodePtr xmlNode, bool createRootEvenIfEmpty) const\n{\n  try\n  {\n    XmlNodePtr xmlChild;\n    if(xmlNode && !isLinked())\n      for(auto &child : children_[selectedIndex()])\n        if((xmlChild = child->createXmlTree(createRootEvenIfEmpty)))\n        {\n          // write _local loops and conditions before element\n          XmlAttrPtr attr = xmlChild->findAttribute(\"loop\");\n          if(attr && (attr->text == \"_localLoop_\"))\n            xmlNode->addChild(xmlChild->getChild(\"loopType\"));\n\n          attr = xmlChild->findAttribute(\"condition\");\n          if(attr && (attr->text == \"_localCondition_\"))\n            xmlNode->addChild(xmlChild->getChild(\"conditionType\"));\n\n          xmlNode->addChild(xmlChild);\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nint TreeElementComplex::addChoice(const QString &value, XsdElementPtr xsdComplex, const QJsonObject &defaultObject)\n{\n  try\n  {\n    int index = insertNewValue(value, false);\n    if(index != xsdElementList.size())\n      throw(Exception(\"lists not consistent\"));\n    xsdElementList.push_back(xsdComplex);\n    overrideDefaultObjects.push_back(defaultObject);\n    children_.push_back(QVector<TreeElement*>());\n    return index;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::createChildrenElements(int index, XmlNodePtr xmlNode)\n{\n  try\n  {\n    if((index < 0) || (index >= xsdElementList.size()))\n      return;\n\n    // children already created?\n    if(children_[index].size())\n    {\n      if(xmlNode)\n        throw(Exception(\"cannot create\"));\n      childSetPushAutoComments(true, index); // set autocomment for the first element\n      return;\n    }\n\n    auto defaultStr = [](const QJsonValue &defaultValue) -> QString\n    {\n      switch(defaultValue.type())\n      {\n        case QJsonValue::String: return defaultValue.toString();\n        case QJsonValue::Bool:   return (defaultValue.toBool() ? \"1\" : \"0\");\n        case QJsonValue::Double: return QString::number(defaultValue.toDouble());\n        case QJsonValue::Object: if(!defaultValue.toObject().isEmpty()) return QJsonDocument(defaultValue.toObject()).toJson(QJsonDocument::Compact); break;\n        case QJsonValue::Array:  if(!defaultValue.toArray().isEmpty())  return QJsonDocument(defaultValue.toArray()).toJson(QJsonDocument::Compact);  break;\n        default: break;\n      }\n      return QString();\n    };\n\n    // lambda function to add comments & variables inbetween\n    // -----------------------------------------------------\n    auto insertCommentsAndVariables = [&]()\n    {\n      if(!xmlNode)\n        return;\n      XmlNodePtr xmlChild;\n      XmlAttrPtr attrLabel;\n      std::list<XmlNodePtr> xmlLocals;\n      for(;;)\n      {\n        if(!(xmlChild = xmlNode->peekNextChild()))\n          break;\n        if(xmlChild->getName() == \"COMMENT\")\n          children_[index].push_back(new TreeElementComment(tree, this, xmlNode->getNextChild()->getText()));\n        else if((attrLabel = xmlChild->findAttribute(\"label\")))\n        {\n          xmlChild = xmlNode->getNextChild(); // remove node\n          if(attrLabel->text.startsWith(\"_local\"))\n            xmlLocals.push_front(xmlChild); // _local variables (loops/conditions) are added to next element\n          else\n          {\n            if(xmlLocals.size())\n              throw(Exception(\"variables cannot have loops or conditions\"));\n            children_[index].push_back(TreeElement::newTreeElement(tree, this, tree->xsdElement(xmlChild->getName()), \"\", xmlChild, false/*fillWithDefaults*/));\n          }\n        }\n        else\n          break;\n      }\n      // add _local variables to next xml element\n      if(xmlChild && xmlLocals.size())\n        for(auto &xmlLocal : xmlLocals)\n          xmlChild->addChild(xmlLocal, true);\n    };\n    // -------------------------------------------------\n\n    if(xsdElementList[index] && xsdElementList[index]->complex)\n    {\n      auto xsdComplex = xsdElementList[index]->complex;\n      if(xsdComplex->type != \"sequence\")\n        throw(Exception(\"complex must be sequence\"));\n\n      for(auto &xsdElement : xsdComplex->elements)\n      {\n        QJsonValue overrideDefaultValue = overrideDefaultObjects[index].value(xsdElement->names.front());\n\n        // lambda function to add new tree element as child\n        // -------------------------------------------------\n        auto addNewChildElement = [&](TreeElementAdd *elementAdd, const QJsonValue &defaultValue)\n        {\n          insertCommentsAndVariables();\n          XmlNodePtr xmlChild;\n          if(xmlNode)\n            xmlChild = xmlNode->getChild(xsdElement->names);\n\n          TreeElement *treeElement;\n          try\n          {\n            treeElement = TreeElement::newTreeElement(tree, this, xsdElement, defaultStr(defaultValue), xmlChild, !xmlNode/*fillWithDefaults*/);\n          }\n          catch(std::exception &/*e*/)\n          {\n            // add empty element from schema and add xmlNode as an unknown element afterwards\n            treeElement = TreeElement::newTreeElement(tree, this, xsdElement, \"\", nullptr, !xmlNode/*fillWithDefaults*/);\n            xmlNode->addChild(xmlChild);\n          }\n          treeElement->setElementAdd(elementAdd);\n          children_[index].push_back(treeElement);\n        };\n        // -------------------------------------------------\n\n        if(!xsdElement->unbounded)\n          addNewChildElement(nullptr, overrideDefaultValue);\n        else\n        {\n          if((overrideDefaultValue.isUndefined() || overrideDefaultValue.isNull()) && xsdElement->defaultValue.startsWith(\"[\"))\n            overrideDefaultValue = QJsonDocument::fromJson(xsdElement->defaultValue.toUtf8()).array(); // catch arrays in default\n\n          // the add element\n          TreeElementAdd *elementAdd = new TreeElementAdd(tree, this, xsdElement, defaultStr(defaultValue));\n          if(xmlNode)\n          {\n            UInt childCount = xmlNode->getChildCount(xsdElement->names);\n            for(UInt i=0; i<childCount; i++)\n              addNewChildElement(elementAdd, overrideDefaultValue);\n          }\n          else if(overrideDefaultValue.isArray()) // create multiple elements from default array\n          {\n            for(const auto &arrayElement : overrideDefaultValue.toArray())\n              addNewChildElement(elementAdd, arrayElement);\n          }\n          else if(!xsdElement->optional) // not optional -> create at least one element\n            addNewChildElement(elementAdd, overrideDefaultValue);\n\n          children_[index].push_back(elementAdd);\n        } // if(unbounded)\n      } // for(xsdElements)\n    } // if(xsdComplex)\n\n    insertCommentsAndVariables();\n\n    // are there unknown XML nodes?\n    if(xmlNode && xmlNode->hasChildren())\n      while(xmlNode->hasChildren())\n        children_[index].push_back(new TreeElementUnknown(tree, this, xmlNode->getNextChild()));\n\n    // invisible add element to be able to remove links and comments at end of list\n    children_[index].push_back(new TreeElementAdd(tree, this, nullptr, \"\", false/*visible*/));\n\n    updateParserResultsInScope();\n    updateLinksInScope();\n    childSetPushAutoComments(true, index); // set autocomment for the first element\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::setSelectedIndex(int index)\n{\n  try\n  {\n    TreeElement::setSelectedIndex(index);\n\n    removeChildrenItems();\n    if(isLinked())\n      return;\n\n    createChildrenElements(index, XmlNodePtr(nullptr));\n\n    // create items\n    if(item())\n    {\n      createChildrenItems();\n      item()->setExpanded(true);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElementComplex::updateParserResultsInScope()\n{\n  try\n  {\n    if(!initializedVariables)\n      return;\n    auto varList = this->varList; // without added local variables\n    for(auto &child : children_[selectedIndex()])\n      varList = child->updateParserResults(varList, true);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nVariableListPtr TreeElementComplex::updateParserResults(VariableListPtr varList, Bool /*addVariableInReturn*/)\n{\n  try\n  {\n    this->varList = varList;\n    initializedVariables = true;\n    TreeElement::updateParserResults(varList, false);\n    for(auto &childdrenAtIndex : children_)\n    {\n      auto varListLocal = this->varList; // without added local variables\n      for(auto &child : childdrenAtIndex)\n        varListLocal = child->updateParserResults(varListLocal, true);\n    }\n    return varList;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::updateLinksInScope()\n{\n  try\n  {\n    if(!initializedVariables)\n      return;\n    auto labelTypesLocal = this->labelTypes; // without added local variables\n    for(auto &child : children_[selectedIndex()])\n      child->updateLinks(labelTypesLocal);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::updateLinks(QMap<QString, QString> &labelTypes)\n{\n  try\n  {\n    this->labelTypes = labelTypes;\n    initializedVariables = true;\n    TreeElement::updateLinks(labelTypes);\n    for(auto &childdrenAtIndex : children_)\n    {\n      auto labelTypesLocal = this->labelTypes; // without added local variables\n      for(auto &child : childdrenAtIndex)\n        child->updateLinks(labelTypesLocal);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementComplex::renamedLink(const QString &oldLabel, const QString &newLabel)\n{\n  try\n  {\n    if(!TreeElement::renamedLink(oldLabel, newLabel))\n      return false;\n    labelTypes[newLabel] = labelTypes.value(oldLabel);\n    if(oldLabel != newLabel)\n      labelTypes.remove(oldLabel);\n    for(auto &childdrenAtIndex : children_)\n      for(auto &child : childdrenAtIndex)\n        if(!child->renamedLink(oldLabel, newLabel))\n          break;\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElementComplex::UndoCommandOverwriteChildren : public TreeElement::UndoCommand\n{\n  TreeElementComplex *treeElement;\n  XmlNodePtr          xmlNode;\n\npublic:\n  UndoCommandOverwriteChildren(TreeElementComplex *treeElement, XmlNodePtr xmlNode)\n    : UndoCommand(treeElement, \"overwrite\"), treeElement(treeElement), xmlNode(xmlNode) {}\n ~UndoCommandOverwriteChildren() {}\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElementComplex::UndoCommandOverwriteChildren::redo()\n{\n  try\n  {\n    XmlNodePtr xmlNodeOld = XmlNode::create(\"parent\");\n    treeElement->createXmlChildren(xmlNodeOld);\n\n    treeElement->removeChildrenItems();\n    for(auto &child : treeElement->children_[treeElement->selectedIndex()])\n      delete child;\n    treeElement->children_[treeElement->selectedIndex()].clear();\n\n    treeElement->createChildrenElements(treeElement->selectedIndex(), xmlNode);\n    treeElement->createChildrenItems();\n    tree->treeChanged();\n\n    xmlNode = xmlNodeOld;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::overwriteChildren(XmlNodePtr xmlNode)\n{\n  tree->undoStack->push(new UndoCommandOverwriteChildren(this, xmlNode));\n}\n\n/***********************************************/\n/***********************************************/\n\nTreeElement *TreeElementComplex::skipCommentElements(TreeElement *targetElement, int index) const\n{\n  if(index < 0)\n    index = selectedIndex();\n  auto end  = children_[index].end();\n  auto iter = std::find(children_[index].begin(), end, targetElement);\n  while((iter != end) && (((*iter)->type() == \"COMMENT\") || !(*iter)->label().isEmpty())) // skip comment elements inbetween\n    iter++;\n  return (iter != end) ? *iter : nullptr;\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::childSetPushAutoComments(bool on, int index)\n{\n  if(index < 0)\n    index = selectedIndex();\n  if(!children_[index].size())\n    return;\n  TreeElement *child = skipCommentElements(children_[index][0], index);\n  if(child)\n    child->setPushAutoComments(on && recieveAutoComments);\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::UndoCommandRemoveAddChild::redo()\n{\n  try\n  {\n    // disable auto comment of the first element (temporary)\n    parent->childSetPushAutoComments(false);\n\n    auto &children = parent->children_[parent->selectedIndex()];\n    if(toAdd) // add child\n    {\n      // find element in the list and insert\n      int index = std::distance(children.begin(), std::find(children.begin(), children.end(), targetElement));\n      children.insert(index, treeElement);\n      treeElement->setElementAdd(addElement); // insert into the unbounded list\n\n      // set visible and get the focus\n      if(parent->item())\n      {\n        // find precursor item\n        TreeItem *afterItem = nullptr;\n        if(parent->loop      && parent->loop->item())      afterItem = parent->loop->item();\n        if(parent->condition && parent->condition->item()) afterItem = parent->condition->item();\n        for(int i=0; (i<children.size()) && (children[i] != treeElement); i++)\n          if(children[i]->item())\n            afterItem = children[i]->item();\n        tree->setSelectedItem(treeElement->createItem(parent->item(), afterItem));\n      }\n    }\n    else // remove child\n    {\n      // find element in the list & remove\n      int index = std::distance(children.begin(), std::find(children.begin(), children.end(), treeElement));\n      children.remove(index);\n      addElement = treeElement->elementAdd();\n      treeElement->setElementAdd(nullptr);\n      treeElement->removeItem();\n\n      if(targetElement->item())\n        tree->setSelectedItem(targetElement->item());\n    }\n\n    parent->updateParserResultsInScope();\n    parent->updateLinksInScope();\n\n    // enable auto comment of the first element\n    parent->childSetPushAutoComments(true);\n\n    tree->treeChanged();\n\n    toAdd = !toAdd;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementComplex::canAddChild(TreeElement *targetElement, const QString &type, const QString &label) const\n{\n  try\n  {\n    if(!targetElement || (targetElement->parentElement != this))\n      throw(Exception(\"invalid call\"));\n    if(type.isEmpty())\n      return false;\n    if(type == \"COMMENT\")\n      return true;\n    if(!label.isEmpty())\n      return (tree->xsdElement(type) != nullptr);\n    targetElement = skipCommentElements(targetElement);\n    return (targetElement->type() == type) && targetElement->unbounded();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementComplex::canRemoveChild(TreeElement *element) const\n{\n  try\n  {\n    if(!element)\n      return false;\n    if(element->parentElement != this)\n      throw(Exception(\"try to remove an external child\"));\n    if(dynamic_cast<TreeElementAdd*>(element))\n      return false;\n    return element->unbounded() && (element->optional() || (element->elementAdd() && element->elementAdd()->unboundedCount > 1));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTreeElement *TreeElementComplex::addChild(TreeElement *targetElement, const QString &type, const QString &label, XmlNodePtr xmlNode)\n{\n  try\n  {\n    if(!canAddChild(targetElement, type, label))\n      return nullptr;\n\n    TreeElement *newElement;\n    if(type == \"COMMENT\")\n    {\n      newElement = new TreeElementComment(tree, this, xmlNode ? xmlNode->getText() : QString());\n    }\n    else if(!label.isEmpty())\n    {\n      newElement = TreeElement::newTreeElement(tree, this, tree->xsdElement(type), \"\", xmlNode, !xmlNode/*fillWithDefaults*/);\n      newElement->_name  = newElement->_schemaName;\n      newElement->_label = label;\n    }\n    else\n    {\n      TreeElement *targetElement2 = skipCommentElements(targetElement);\n      newElement = TreeElement::newTreeElement(tree, this, targetElement2->xsdElement, targetElement2->defaultValue, xmlNode, !xmlNode/*fillWithDefaults*/);\n      newElement->_name  = newElement->_schemaName;\n      newElement->_label = \"\";\n      newElement->setElementAdd(targetElement2->elementAdd());\n    }\n\n    tree->undoStack->push(new UndoCommandRemoveAddChild(newElement, targetElement, this, true/*isAdd*/));\n    return newElement;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementComplex::removeChild(TreeElement *element)\n{\n  try\n  {\n    if(!canRemoveChild(element))\n      return false;\n\n    // find element in the list\n    auto &children = children_[selectedIndex()];\n    int index = std::distance(children.begin(), std::find(children.begin(), children.end(), element));\n    if(index+1 >= children_[selectedIndex()].size())\n      throw(Exception(\"element not in the list or add element is missing\"));\n\n    tree->undoStack->push(new UndoCommandRemoveAddChild(element, children[index+1], this, false/*isAdd*/));\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass TreeElementComplex::UndoCommandMoveChild : public TreeElement::UndoCommand\n{\n  TreeElement *targetElement;\n\npublic:\n  UndoCommandMoveChild(TreeElement *treeElement, TreeElement *targetElement)\n  : UndoCommand(treeElement, \"move\"), targetElement(targetElement) {}\n  ~UndoCommandMoveChild() {}\n\n  void redo();\n  void undo() {redo();}\n};\n\n/***********************************************/\n\nvoid TreeElementComplex::UndoCommandMoveChild::redo()\n{\n  try\n  {\n    TreeElementComplex *parent = treeElement->parentElement;\n    parent->childSetPushAutoComments(false); // disable auto comment of the first element (temporary)\n    treeElement->removeItem();\n\n    // find element in the list & remove\n    auto &children = parent->children_[parent->selectedIndex()];\n    int index = std::distance(children.begin(), std::find(children.begin(), children.end(), treeElement));\n    TreeElement *targetElementOld = children.at(index+1);\n    children.remove(index);\n    index = std::distance(children.begin(), std::find(children.begin(), children.end(), targetElement));\n    children.insert(index, treeElement);\n    targetElement = targetElementOld;\n\n    parent->updateParserResultsInScope();\n    parent->updateLinksInScope();\n    parent->childSetPushAutoComments(true); // enable auto comment of the first element\n    tree->treeChanged();\n\n    // set visible and get the focus\n    // -----------------------------\n    if(parent->item())\n    {\n      // find precursor item\n      TreeItem *after = nullptr;\n      if(parent->loop      && parent->loop->item())      after = parent->loop->item();\n      if(parent->condition && parent->condition->item()) after = parent->condition->item();\n      for(int i=0; i<children.size(); i++)\n      {\n        if(children[i] == treeElement)\n          break;\n        if(children[i]->item())\n          after = children[i]->item();\n      }\n      tree->setSelectedItem(treeElement->createItem(parent->item(), after));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementComplex::canMoveChild(TreeElement *targetElement, TreeElement *element) const\n{\n  if((targetElement == element) || (element->parentElement != this) || (targetElement->parentElement != this))\n    return false;\n  if(dynamic_cast<TreeElementAdd*>(element))\n    return false;\n  if(dynamic_cast<TreeElementComment*>(element))\n    return true;\n  if(!element->label().isEmpty())\n    return true;\n  return element->elementAdd() && (element->elementAdd() == skipCommentElements(targetElement)->elementAdd());\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::moveChild(TreeElement *targetElement, TreeElement *element)\n{\n  try\n  {\n    if(canMoveChild(targetElement, element))\n      tree->undoStack->push(new UndoCommandMoveChild(element, targetElement));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElementComplex::createChildrenItems()\n{\n  try\n  {\n    TreeItem *after = (item()->childCount()) ? dynamic_cast<TreeItem*>(item()->child(item()->childCount()-1)) : nullptr;\n    if(item() && !isLinked())\n      for(auto &childElement : children_[selectedIndex()])\n      {\n        TreeItem *child = childElement->createItem(item(), after);\n        if(child)\n          after = child;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::removeChildrenItems()\n{\n  try\n  {\n    if(item())\n      item()->setExpanded(false); // hide all children\n\n    for(auto &childdrenAtIndex : children_)\n      for(auto &child : childdrenAtIndex)\n        child->removeItem();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTreeItem *TreeElementComplex::createItem(TreeItem *parent, TreeItem *after)\n{\n  try\n  {\n    TreeItem *item = TreeElement::createItem(parent, after);\n    createChildrenItems();\n    return item;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementComplex::removeItem()\n{\n  try\n  {\n    removeChildrenItems();\n    TreeElement::removeItem();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementComplex.h",
    "content": "/***********************************************/\n/**\n* @file treeElementComplex.h\n*\n* @brief Abstract element with children (sequence or choice).\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTCOMPLEX__\n#define __GROOPSGUI__TREEELEMENTCOMPLEX__\n\n#include <QJsonObject>\n#include \"base/importGroops.h\"\n#include \"tree/treeElement.h\"\n\n/***** TYPES ***********************************/\n\nclass TreeElementAdd;\n\n/***** CLASS ***********************************/\n\nclass TreeElementComplex : public TreeElement\n{\n  friend class TreeElementGlobal;\n\n  QVector<QVector<TreeElement*>> children_;              // list of children for each choice\n  QVector<XsdElementPtr>         xsdElementList;         // xsd for each choice\n  QVector<QJsonObject>           overrideDefaultObjects; // defaultValue for each choice\n  bool                           recieveAutoComments;\n\nprotected:\n  QJsonObject defaultObject;\n\npublic:\n  TreeElementComplex(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement, const QString &defaultOverride,\n                     XmlNodePtr xmlNode, bool recieveAutoComments=false);\n ~TreeElementComplex();\n\nprotected:\n  /** @brief add XML-nodes of the children to @a xmlNode. */\n  void createXmlChildren(XmlNodePtr xmlNode, bool createRootEvenIfEmpty=false) const;\n\n  // init the children lists\n  // -----------------------\n  /** @brief append a additional choice/sequence. */\n  int addChoice(const QString &value, XsdElementPtr xsdComplex, const QJsonObject &overrideDefaultObject);\n\n  /** @brief create elements for a choice with @a index. */\n  void createChildrenElements(int index, XmlNodePtr xmlNode);\n\n  /** @brief changes the current index.\n  * calls TreeElement::selectIndex\n  * creates the children elemens and items.\n  * if an @a index is choosen without children all items are removed.\n  * Set items expanded. */\n  void setSelectedIndex(int index) override;\n\n  // ========================================================\n\npublic:\n  const QVector<TreeElement*> &children() const {static QVector<TreeElement*> empty; return isLinked() ? empty : children_[selectedIndex()];}\n\n  // ========================================================\n\n  // Inform about changes in variables\n  // ---------------------------------\nprivate:\n  bool                   initializedVariables;\n  VariableListPtr        varList;\n  QMap<QString, QString> labelTypes;\n\npublic:\n  /** @brief must be called if a variable is changed within this scope. */\n  virtual void updateParserResultsInScope();\n\n  /** @brief must be called if a variable is added/removed/renamed within this scope.\n   * recursively called for all children. */\n  virtual void updateLinksInScope();\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children. Returns the input @a varList. */\n  VariableListPtr updateParserResults(VariableListPtr varList, Bool /*addVariableInReturn*/) override;\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children. */\n  void updateLinks(QMap<QString, QString> &labelTypes) override;\n\n  /** @brief must be called if a variable is renamed.\n   * recursively called for all children.\n   * @return next element can also be renamed. */\n  bool renamedLink(const QString &oldLabel, const QString &newLabel) override;\n\n  // ========================================================\n\n  // Overwrite content\n  // -----------------\nprivate:\n  class UndoCommandOverwriteChildren;\n  friend class UndoCommandOverwriteChildren;\n\npublic:\n  /** @brief copy the children of @a xmlNode into selected choice.\n  * Is undoable. */\n  void overwriteChildren(XmlNodePtr xmlNode);\n\n  // ========================================================\n\nprivate:\n  TreeElement *skipCommentElements(TreeElement *targetElement, int index=-1) const;\n  void childSetPushAutoComments(bool on, int index=-1);\n\n  // Add/Remove elements\n  // -------------------\nprotected:\n  class UndoCommandRemoveAddChild : public TreeElement::UndoCommand\n  {\n    bool                toAdd;\n    TreeElementComplex *parent;\n    TreeElement        *targetElement;\n    TreeElementAdd     *addElement;\n\n  public:\n    UndoCommandRemoveAddChild(TreeElement *newElement, TreeElement *targetElement, TreeElementComplex *parent, bool isAdd)\n      : UndoCommand(newElement, (isAdd ? \"add\" : \"remove\")), toAdd(isAdd), parent(parent), targetElement(targetElement), addElement(newElement->elementAdd()) {}\n   ~UndoCommandRemoveAddChild() {if(toAdd) delete treeElement;}\n\n    void redo();\n    void undo() {redo();}\n  };\n  friend class UndoCommandRemoveAddChild;\n\npublic:\n  /** @brief Is it possible to insert an element with @a type before @a targetElement? */\n  virtual bool canAddChild(TreeElement *targetElement, const QString &type, const QString &label) const;\n\n  /** @brief Is it possible to remove this element from tree? */\n  virtual bool canRemoveChild(TreeElement *element) const;\n\n  /** @brief add child before/after @a targetElement.\n  * Is undoable.\n  * the new element is selected.\n  * @return successfully created element */\n  virtual TreeElement *addChild(TreeElement *targetElement, const QString &type, const QString &label, XmlNodePtr xmlNode);\n\n  /** @brief remove child @a element.\n  * Is undoable.\n  * if successful the element is deleted.\n  * @return success */\n  virtual bool removeChild(TreeElement *element);\n\n  // ========================================================\n\n  // move elements\n  // --------------\nprivate:\n  class UndoCommandMoveChild;\n  friend class UndoCommandMoveChild;\n\npublic:\n  /** @brief Is it possible to move an element before @a targetElement?\n  * Only possible within the same unbounded list. */\n  virtual bool canMoveChild(TreeElement *targetElement, TreeElement *element) const;\n\n  /** @brief move child before @a targetElement.\n  * Is undoable. */\n  virtual void moveChild(TreeElement *targetElement, TreeElement *element);\n\n  // ========================================================\n\n  // TreeItem: visual element (one line in the tree widget)\n  // ------------------------------------------------------\nprivate:\n  void createChildrenItems();\n  void removeChildrenItems();\n\npublic:\n  /** @brief create visual element.\n  * Recursively for all children. */\n  TreeItem *createItem(TreeItem *parent, TreeItem *after) override;\n\n  /** @brief remove visual element.\n  * Recursively for all children. */\n  void removeItem() override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPSGUI__TREEELEMENTCOMPLEX__ */\n"
  },
  {
    "path": "gui/tree/treeElementFileName.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementFileName.cpp\n*\n* @brief Element with file selector.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QHBoxLayout>\n#include <QPushButton>\n#include <QFileDialog>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementFileName.h\"\n\n/***********************************************/\n\nTreeElementFileName::TreeElementFileName(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                                         const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults)\n  : TreeElementSimple(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults)\n{\n}\n\n/***********************************************/\n\nQWidget *TreeElementFileName::createEditor()\n{\n  try\n  {\n    // create layout\n    QWidget *layoutWidget = new QWidget(tree);\n    QHBoxLayout *layout   = new QHBoxLayout(layoutWidget);\n    layout->setContentsMargins(0, 0, 0, 0);\n\n    // create ComboBox\n    QComboBox *comboBox = createComboBox(true);\n    layout->addWidget(comboBox);\n    layoutWidget->setFocusProxy(comboBox);\n\n    // create FileSelector Button\n    openFileButton = new QPushButton(layoutWidget);\n    openFileButton->setIcon(QIcon(\":/icons/scalable/document-open.svg\"));\n    layout->addWidget(openFileButton);\n    // signals and slots connections\n    connect(openFileButton, SIGNAL(clicked()), this, SLOT(openFileClicked()));\n\n    return layoutWidget;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementFileName::interact()\n{\n  openFileClicked();\n}\n\n/***********************************************/\n\nvoid TreeElementFileName::openFileClicked()\n{\n  try\n  {\n    // if directory doesn't exist, repeatedly go up one directory until it exists\n    QFileInfo startFile(tree->addWorkingDirectory(selectedResult()));\n    while(!startFile.isFile() && !startFile.absoluteDir().exists() && !startFile.absoluteDir().isRoot())\n    {\n      QString dir = startFile.absolutePath();\n      dir.truncate(dir.lastIndexOf(\"/\")+1);\n      startFile = QFileInfo(dir + startFile.fileName());\n    }\n\n    // lambda to replace beginning part of path with global variable\n    auto replaceByVariable = [&](QString path, QString &variable, QString &parsedVariable)\n    {\n      for(int i=_valueCount; i<_valueList.size(); i++) // all possible links\n      {\n        QString parsed = parseExpression(\"{\"+_valueList.at(i)+\"}\", *varList);\n        if(path.startsWith(parsed) && (parsed.size() > parsedVariable.size()))\n        {\n          variable = \"{\"+_valueList.at(i)+\"}\";\n          parsedVariable = parsed;\n        }\n      }\n    };\n\n    // possible to add several elements?\n    if(elementAdd())\n    {\n      QStringList files = QFileDialog::getOpenFileNames(openFileButton, name(), startFile.absoluteFilePath());\n      if(files.size()==0)\n        return;\n\n      QString lastFile = tree->stripWorkingDirectory(files.last());\n      QString variable;\n      QString parsedVariable;\n      replaceByVariable(lastFile, variable, parsedVariable);\n\n      for(int i=0; i<files.size()-1; i++)\n      {\n        XmlNodePtr xmlNode = createXmlTree(true);\n        if(!(xmlNode && parentElement))\n          continue;\n        xmlNode->setText(variable+tree->stripWorkingDirectory(files[i]).mid(parsedVariable.size()));\n        parentElement->addChild(this, type(), \"\", xmlNode);\n      }\n      changeSelectedValue(variable+lastFile.mid(parsedVariable.size()));\n    }\n    else\n    {\n      // File Selector Dialog\n      QString selectedPath = QFileDialog::getSaveFileName(openFileButton, name(), startFile.absoluteFilePath(), \"\", nullptr, QFileDialog::DontConfirmOverwrite);\n      if(!selectedPath.isEmpty())\n      {\n        selectedPath = tree->stripWorkingDirectory(selectedPath);\n        QString variable;\n        QString parsedVariable;\n        replaceByVariable(selectedPath, variable, parsedVariable);\n        changeSelectedValue(variable+selectedPath.mid(parsedVariable.size()));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementFileName.h",
    "content": "/***********************************************/\n/**\n* @file treeElementFileName.h\n*\n* @brief Element with file selector.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTFILENAME__\n#define __GROOPSGUI__TREEELEMENTFILENAME__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementSimple.h\"\n\n/***** TYPES ***********************************/\n\nclass QPushButton;\n\n/***** CLASS ***********************************/\n\nclass TreeElementFileName : public TreeElementSimple\n{\n  Q_OBJECT\n\n  VariableListPtr varList;\n\npublic:\n  TreeElementFileName(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                      const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults);\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children.\n  * If this element is a variable and @a addVariableInReturn an updated varList is returned. */\n  VariableListPtr updateParserResults(VariableListPtr varList, Bool addVariableInReturn) override {this->varList = varList; return TreeElementSimple::updateParserResults(varList, addVariableInReturn);}\n\n  /** @brief creates an editable combo box with additional file selector. */\n  QWidget *createEditor() override;\n\n  /** @brief Opens file selector dialog. */\n  void interact() override;\n\nprivate:\n  QPointer<QPushButton> openFileButton;\n\nprivate slots:\n  void openFileClicked();\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementGlobal.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementGlobal.cpp\n*\n* @brief The global element.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-07-10\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QInputDialog>\n#include \"addVariableDialog/addVariableDialog.h\"\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementSimple.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementComment.h\"\n#include \"tree/treeElementUnknown.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElementGlobal.h\"\n\n/***********************************************/\n\nTreeElementGlobal::TreeElementGlobal(Tree *tree, TreeElementComplex *parentElement,\n                                     XsdElementPtr xsdElement, XmlNodePtr xmlNode)\n  : TreeElementComplex(tree, parentElement, xsdElement, \"\", xmlNode, false/*recieveAutoComments*/)\n{\n  try\n  {\n    if(isLinked())\n      throw(Exception(\"global cannot be linked\"));\n\n    tree->elementGlobal = this;\n\n    addChoice(\"\", nullptr/*xsdElement*/, QJsonObject());\n    if(xmlNode)\n      createChildrenElements(0, xmlNode);     // add children\n    // the add element\n    children_[0].push_back(new TreeElementAdd(tree, this, xsdElement, \"\", true/*visible*/));\n    setSelectedIndex(0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTreeElementGlobal::~TreeElementGlobal()\n{\n  tree->elementGlobal = nullptr;\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementGlobal::createXmlTree(bool /*createRootEvenIfEmpty*/) const\n{\n  try\n  {\n    XmlNodePtr xmlNode = createXmlBaseNode();\n    if(!isLinked())\n      createXmlChildren(xmlNode, true/*createRootEvenIfEmpty*/);\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid TreeElementGlobal::updateParserResultsInScope()\n{\n  try\n  {\n    if(parentElement)\n      parentElement->updateParserResultsInScope(); // global variables are valid globally\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nVariableListPtr TreeElementGlobal::updateParserResults(VariableListPtr varListOld, Bool /*addVariableInReturn*/)\n{\n  try\n  {\n    varList = std::make_shared<const VariableList>(*varListOld); // make copy\n    // as the order is irrelevant -> add all variables before\n    for(auto child : children())\n      if(!child->label().isEmpty() && !child->disabled())\n        std::const_pointer_cast<VariableList>(varList)->setVariable(child->label().toStdString(), (child->isLinked() ? \"{\"+child->selectedValue()+\"}\" : child->selectedValue()).toStdString());\n    for(auto child : children_[selectedIndex()])\n      child->updateParserResults(varList, false);\n    return varList;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementGlobal::updateLinksInScope()\n{\n  try\n  {\n    if(parentElement)\n      parentElement->updateLinksInScope(); // global variables are valid globally\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementGlobal::updateLinks(QMap<QString, QString> &labelTypes)\n{\n  try\n  {\n    // as the order is irrelevant -> add all links before\n    for(auto child : children())\n      if(!child->label().isEmpty() && !child->disabled())\n        labelTypes[child->label()] = getLinkType(child->type());\n    this->labelTypes = labelTypes;\n    for(auto child : children_[selectedIndex()])\n      child->updateLinks(labelTypes);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nbool TreeElementGlobal::canAddChild(TreeElement */*targetElement*/, const QString &type, const QString &/*label*/) const\n{\n  return type.isEmpty() || (type == \"COMMENT\") || tree->xsdElement(type);\n}\n\n/***********************************************/\n\nTreeElement *TreeElementGlobal::addChild(TreeElement *targetElement, const QString &type, const QString &label, XmlNodePtr xmlNode)\n{\n  try\n  {\n    if(!canAddChild(targetElement, type, label))\n      return nullptr;\n\n    if(type == \"COMMENT\")\n      return TreeElementComplex::addChild(targetElement, type, \"\", xmlNode);\n\n    QString newLabel = label;\n    QString newType  = type;\n    if(newType.isEmpty())\n    {\n      AddVariableDialog dialog(tree, \"\", \"\", true/*disablePlace*/, dynamic_cast<TreeElementAdd*>(targetElement)/*disableCreateLink*/, tree);\n      if(!dialog.exec())\n        return nullptr;\n      newLabel = dialog.label();\n      newType  = dialog.type();\n    }\n\n    // check label\n    if(newLabel.isEmpty())\n    {\n      if(xmlNode)\n        newLabel = xmlNode->getName(); // default name\n      bool ok = true;\n      newLabel = QInputDialog::getText(tree, tr(\"Add global element - GROOPS\"), tr(\"Name of global element:\"), QLineEdit::Normal, newLabel, &ok);\n      if(!ok)\n        return nullptr;\n    }\n\n    // check label\n    QStringList existingNames;\n    for(auto child : children())\n      if(!child->label().isEmpty())\n        existingNames.push_back(child->label());\n    QRegularExpression regex(\"^[a-zA-Z]([a-zA-Z0-9])*$\");\n    bool ok = true;\n    while(ok && (newLabel.isEmpty() || existingNames.contains(newLabel) || !regex.match(newLabel).hasMatch()))\n      newLabel = QInputDialog::getText(tree, tr(\"Add global element - GROOPS\"), tr(\"Name already exists or is invalid (only letters and digits allowed)!\\nChoose another name:\"), QLineEdit::Normal, newLabel, &ok);\n    if(!ok)\n      return nullptr;\n\n    if(xmlNode)\n    {\n      xmlNode->setName(newType);\n      // remove loop, condition, ...\n      QString loopLabel, conditionLabel, tmp;\n      readAttribute(xmlNode, \"label\",     tmp);\n      readAttribute(xmlNode, \"disabled\",  tmp);\n      readAttribute(xmlNode, \"loop\",      loopLabel);\n      readAttribute(xmlNode, \"condition\", conditionLabel);\n      if(loopLabel      == \"_localLoop_\")      xmlNode->getChild(\"loopType\");\n      if(conditionLabel == \"_localCondition_\") xmlNode->getChild(\"conditionType\");\n      writeAttribute(xmlNode, \"label\", newLabel);\n    }\n\n    return TreeElementComplex::addChild(targetElement, newType, newLabel, xmlNode);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementGlobal.h",
    "content": "/***********************************************/\n/**\n* @file treeElementGlobal.h\n*\n* @brief The global element.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-07-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTGLOBAL__\n#define __GROOPSGUI__TREEELEMENTGLOBAL__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementComplex.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementGlobal : public TreeElementComplex\n{\n  Q_OBJECT\n\npublic:\n  TreeElementGlobal(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                    XmlNodePtr xmlNode);\n ~TreeElementGlobal();\n\n  /** @brief Generate XML-tree.\n  * recursively called for all children. */\n  XmlNodePtr createXmlTree(bool /*createRootEvenIfEmpty*/) const override;\n\n  // Inform about changes in variables\n  // ---------------------------------\n  /** @brief must be called if a variable is changed within this scope. */\n  void updateParserResultsInScope() override;\n\n  /** @brief must be called if a variable is added/removed/renamed within this scope.\n   * recursively called for all children. */\n  void updateLinksInScope() override;\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children.\n  * Returns a new varList containing the global variables. */\n  VariableListPtr updateParserResults(VariableListPtr varList, Bool /*addVariableInReturn*/) override;\n\n  /** @brief inform this element about changed variables.\n   * recursively called for all children. */\n  void updateLinks(QMap<QString, QString> &labelTypes) override;\n\n  // Add/Remove elements\n  // -------------------\n  /** @brief Is it possible to insert an element with @a type before @a targetElement?\n  * New elements can be added directly to the global section. */\n  bool canAddChild(TreeElement *targetElement, const QString &type, const QString &label) const override;\n\n  /** @brief add child before @a targetElement.\n  * Is undoable. the new element is selected.\n  * @return success */\n  TreeElement *addChild(TreeElement *targetElement, const QString &type, const QString &label, XmlNodePtr xmlNode) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPSGUI__TREEELEMENTGLOBAL__ */\n"
  },
  {
    "path": "gui/tree/treeElementLoopCondition.h",
    "content": "/***********************************************/\n/**\n* @file treeElementLoopCondition.h\n*\n* @brief Loop or condition of an element.\n*\n* @author Torsten Mayer-Guerr\n* @date 2024-01-22\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTLOOPCONDITION__\n#define __GROOPSGUI__TREEELEMENTLOOPCONDITION__\n\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElementChoice.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementLoopCondition : public TreeElementChoice\n{\n  Q_OBJECT\n\n  QString _name, _label;\n\npublic:\n  TreeElementLoopCondition(Tree *tree, TreeElement *affectedElement, XsdElementPtr xsdElement, XmlNodePtr xmlNode)\n    : TreeElementChoice(tree, nullptr, xsdElement, \"\", xmlNode, !xmlNode, false), affectedElement(affectedElement)\n    {\n      _name  = (xsdElement == tree->xsdElementLoop) ? \"loop\" : \"condition\";\n      _label = (xsdElement == tree->xsdElementLoop) ? \"_localLoop_\" : \"_localCondition_\";\n    }\n\n  TreeElement *affectedElement;\n\n  QString name()         const override {return _name;}\n  QString label()        const override {return _label;}\n  bool optional()        const override {return true;}\n  bool unbounded()       const override {return false;}\n  bool canSetLoop()      const override {return false;}\n  bool canSetCondition() const override {return false;}\n  bool canDisabled()     const override {return false;}\n  bool canRename()       const override {return false;}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementProgram.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementProgram.cpp\n*\n* @brief Program element with children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"programDialog/programDialog.h\"\n#include \"tree/treeElementProgram.h\"\n\n/***********************************************/\n\nQWidget *TreeElementProgram::createEditor()\n{\n  try\n  {\n    // create program selection button\n    openButton = new QPushButton(tree);\n    openButton->setText(selectedValue());\n    openButton->setStyleSheet(\"Text-align:left; padding: 2px; padding-left: 4px\");\n    openButton->setDefault(true);\n    if(isSelectionRenamedInSchema(selectedIndex()))\n      openButton->setIcon(QIcon(\":/icons/scalable/edit-rename.svg\"));\n    else if(isSelectionDeprecated(selectedIndex()))\n      openButton->setIcon(QIcon(\":/icons/scalable/warning.svg\"));\n    else if(isSelectionUnknown(selectedIndex()))\n      openButton->setIcon(QIcon(\":/icons/scalable/element-unknown.svg\"));\n\n    // signals and slots connections\n    connect(openButton, SIGNAL(clicked()), this, SLOT(openClicked()));\n\n    return openButton;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementProgram::interact()\n{\n  openClicked();\n}\n\n/***********************************************/\n\nvoid TreeElementProgram::setSelectedIndex(int index)\n{\n  TreeElementChoice::setSelectedIndex(index);\n  if(openButton)\n  {\n    if(isSelectionRenamedInSchema(selectedIndex()))\n      openButton->setIcon(QIcon(\":/icons/scalable/edit-rename.svg\"));\n    else if(isSelectionDeprecated(selectedIndex()))\n      openButton->setIcon(QIcon(\":/icons/scalable/warning.svg\"));\n    else if(isSelectionUnknown(selectedIndex()))\n      openButton->setIcon(QIcon(\":/icons/scalable/element-unknown.svg\"));\n    else\n      openButton->setIcon(QIcon());\n    openButton->setText(selectedValue());\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementProgram::openClicked()\n{\n  try\n  {\n    ProgramDialog dialog(this, tree);\n    dialog.exec();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "gui/tree/treeElementProgram.h",
    "content": "/***********************************************/\n/**\n* @file treeElementProgram.h\n*\n* @brief Program element with children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTPROGRAM__\n#define __GROOPSGUI__TREEELEMENTPROGRAM__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementChoice.h\"\n#include <QPushButton>\n\n/***** CLASS ***********************************/\n\nclass TreeElementProgram : public TreeElementChoice\n{\n  Q_OBJECT\n\n  QPushButton *openButton;\n\npublic:\n  TreeElementProgram(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                       const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults)\n    : TreeElementChoice(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults, true/*recieveAutoComments*/) {}\n\n  /** @brief creates an uneditable combo box with addtional selector. */\n  QWidget *createEditor() override;\n\n  /** @brief Opens program selector dialog. */\n  void interact() override;\n\nprotected:\n  /** @brief changes the current index.\n  * if selected index is changed:\n  * - update button text\n  * - call TreeElementChoice::setSelectedIndex() */\n  void setSelectedIndex(int index) override;\n\nprivate slots:\n  void openClicked();\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementSequence.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementSequence.cpp\n*\n* @brief Element with children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementSequence.h\"\n\n/***********************************************/\n\nTreeElementSequence::TreeElementSequence(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                                         const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults)\n  : TreeElementComplex(tree, parentElement, xsdElement, defaultOverride, xmlNode)\n{\n  try\n  {\n    int index = 0;\n    if(optional() && !unbounded())\n    {\n      index = addChoice(\"<none>\",    XsdElementPtr(nullptr), QJsonObject());\n      index = addChoice(\"<enabled>\", xsdElement,             defaultObject);\n      if(!xmlNode || isLinked())\n        index = (fillWithDefaults && !defaultObject.isEmpty()) ? 1 : 0;\n    }\n    else\n      index = addChoice(\"\", xsdElement, defaultObject);\n\n    if(xmlNode && !isLinked())\n      createChildrenElements(index, xmlNode);\n    setSelectedIndex(isLinked() ? selectedIndex() : index);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementSequence::createXmlTree(bool /*createRootEvenIfEmpty*/) const\n{\n  try\n  {\n    if(selectedValue()==\"<none>\")\n      return XmlNodePtr(nullptr);\n    XmlNodePtr xmlNode = createXmlBaseNode();\n    if(!isLinked())\n      createXmlChildren(xmlNode);\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nbool TreeElementSequence::overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly)\n{\n  try\n  {\n    if(!canOverwrite(type))\n      return false;\n\n    if(!xmlNode && optional() && !unbounded()) // <none>\n    {\n      tree->undoStack->beginMacro(\"overwrite \"+name());\n      changeSelectedIndex(0);\n      tree->undoStack->endMacro();\n      return true;\n    }\n\n    if(!xmlNode)\n      return false;\n\n    tree->undoStack->beginMacro(\"overwrite \"+name());\n    if(baseOverwrite(xmlNode, contentOnly))\n    {\n      changeSelectedIndex((optional() && !unbounded()) ? 1 : 0); // change to <enabled>\n      overwriteChildren(xmlNode);\n    }\n    tree->undoStack->endMacro();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementSequence.h",
    "content": "/***********************************************/\n/**\n* @file treeElementSequence.h\n*\n* @brief Element with children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTSEQUENCE__\n#define __GROOPSGUI__TREEELEMENTSEQUENCE__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementComplex.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementSequence : public TreeElementComplex\n{\npublic:\n  TreeElementSequence(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                      const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults);\n\n  /** @brief Generate XML-tree.\n  * recursively called for all children. */\n  XmlNodePtr createXmlTree(bool /*createRootEvenIfEmpty*/) const override;\n\n  /** @brief Is it possible to overweite the element? */\n  bool canOverwrite(const QString &type) override {return (this->type() == type) && parentElement;}\n\n  /** @brief Copy the content of @a xmlNode into this.\n  * Is undoable.\n  * @return success */\n  bool overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly=false) override;\n\n  /** @brief creates an uneditable combo box. */\n  QWidget *createEditor() override {return createComboBox(false);}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementSimple.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementSimple.cpp\n*\n* @brief Element without children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QJsonDocument>\n#include <QJsonArray>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeItem.h\"\n#include \"tree/treeElementSimple.h\"\n\n/***********************************************/\n\nTreeElementSimple::TreeElementSimple(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                                     const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults)\n  : TreeElement(tree, parentElement, xsdElement, defaultOverride, xmlNode)\n{\n  try\n  {\n    if(!isLinked())\n    {\n      if(xmlNode && xmlNode->hasChildren())\n        throw(Exception(\"xml node doesn't match with schema\"));\n      else if(xmlNode && !xmlNode->getText().isEmpty())\n        insertNewValue(xmlNode->getText(), false);\n      else if(!fillWithDefaults || defaultValue.isEmpty())\n        insertNewValue(\"\", false);\n    }\n    if(!defaultValue.isEmpty())\n    {\n      // catch arrays in default\n      QJsonArray defaultArray = QJsonDocument::fromJson(defaultValue.toUtf8()).array();\n      if(!defaultArray.isEmpty())\n        defaultValue = defaultArray.last().toString();\n      insertNewValue(defaultValue, false);\n    }\n\n    setSelectedIndex(isLinked() ? selectedIndex() : 0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementSimple::createXmlTree(bool createRootEvenIfEmpty) const\n{\n  try\n  {\n    if(label().isEmpty() && selectedValue().isEmpty() && !createRootEvenIfEmpty)\n       return XmlNodePtr(nullptr);\n    XmlNodePtr xmlNode = TreeElement::createXmlBaseNode();\n    if(!isLinked())\n      xmlNode->setText(selectedValue());\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementSimple::setSelectedIndex(int index)\n{\n  try\n  {\n    TreeElement::setSelectedIndex(index);\n    if(parentElement)\n      parentElement->updateParserResultsInScope();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nVariableListPtr TreeElementSimple::updateParserResults(VariableListPtr varList, Bool addVariableInReturn)\n{\n  TreeElement::updateParserResults(varList, false);\n\n  QString resultNew = parseExpression((isLinked()) ? \"{\"+selectedValue()+\"}\" : selectedValue(), *varList);\n  if(resultNew != result)\n  {\n    result = resultNew;\n    if(item())\n      item()->updateValue();\n  }\n\n  if(!addVariableInReturn || label().isEmpty() || disabled()) // is not variable?\n    return varList;\n\n  // variable -> add to list\n  auto varListNew = std::make_shared<VariableList>(*varList); // make copy\n  varListNew->setVariable(label().toStdString(), (isLinked() ? \"{\"+selectedValue()+\"}\" : selectedValue()).toStdString());\n  return std::const_pointer_cast<const VariableList>(varListNew);\n}\n\n/***********************************************/\n\nQString TreeElementSimple::parseExpression(const QString &text, const VariableList &varList) const\n{\n  QString result = text;\n  try\n  {\n    bool resolved = true;\n    result = QString::fromStdString(StringParser::parse(name().toStdString(), text.toStdString(), varList, resolved));\n    if(resolved && QStringList({\"bool\", \"int\", \"uint\", \"double\", \"angle\", \"time\", \"expression\"}).contains(type())) // only numerical values\n    {\n      Double d = ExpressionVariable::parse(result.toStdString(), varList);\n      result.setNum(d, 'f', 7).remove(QRegularExpression(\"0+$\")).remove(QRegularExpression(\"\\\\.$\")); // %.7f with trailing zeros removed\n    }\n  }\n  catch(std::exception &/*e*/)\n  {\n  }\n  return result;\n}\n\n\n/***********************************************/\n\nbool TreeElementSimple::overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly)\n{\n  try\n  {\n    if(!canOverwrite(type) || !xmlNode)\n      return false;\n\n    tree->undoStack->beginMacro(\"overwrite \"+name());\n    if(baseOverwrite(xmlNode, contentOnly))\n      changeSelectedValue(xmlNode->getText());\n    tree->undoStack->endMacro();\n    return true;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementSimple.h",
    "content": "/***********************************************/\n/**\n* @file treeElementSimple.h\n*\n* @brief Element without children.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTSIMPLE__\n#define __GROOPSGUI__TREEELEMENTSIMPLE__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElement.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementSimple : public TreeElement\n{\n  Q_OBJECT\n\n  QString result; // parsed value\n\npublic:\n  TreeElementSimple(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                    const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults);\n\n  /** @brief Generate XML-tree. */\n  XmlNodePtr createXmlTree(bool createRootEvenIfEmpty) const override;\n\n  /** @brief Values can be edited. */\n  bool isEditable() const override {return true;}\n\n  /** @brief the selected value as result of parser. */\n  QString selectedResult() const override {return result;}\n\n  /** @brief changes the current index.\n  * calls TreeElement::selectIndex\n  * Updates the parsed result. */\n  void setSelectedIndex(int index) override;\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children.\n  * If this element is a variable and @a addVariableInReturn an updated varList is returned. */\n  VariableListPtr updateParserResults(VariableListPtr varList, Bool addVariableInReturn) override;\n\nprotected:\n  virtual QString parseExpression(const QString &text, const VariableList &varList) const;\n\npublic:\n  /** @brief Is it possible to overweite the element? */\n  bool canOverwrite(const QString &type) override {return (this->type() == type);}\n\n  /** @brief Copy the content of @a xmlNode into this.\n  * Is undoable.\n  * @return success */\n  bool overwrite(const QString &type, XmlNodePtr xmlNode, bool contentOnly=false) override;\n\n  /** @brief creates an editable combo box. */\n  QWidget *createEditor() override {return createComboBox(true);}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementTime.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementTime.cpp\n*\n* @brief Element with date/time editor.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QHBoxLayout>\n#include <QComboBox>\n#include <QDateTimeEdit>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementSimple.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementTime.h\"\n\n/***********************************************/\n\nvoid TreeElementTime::setSelectedIndex(int index)\n{\n  try\n  {\n    TreeElementSimple::setSelectedIndex(index); // updates also mjd\n\n    if(dateTimeEdit && !changeNotDateTime) // avoid infinite recursion\n    {\n      changeNotComboBox = true;\n      dateTimeEdit->setDateTime(mjd2date(mjd));\n      changeNotComboBox = false;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nQWidget *TreeElementTime::createEditor()\n{\n  try\n  {\n    changeNotComboBox = changeNotDateTime = false;\n\n    // create layout\n    QWidget *layoutWidget = new QWidget(tree);\n    QHBoxLayout *layout   = new QHBoxLayout(layoutWidget);\n    layout->setContentsMargins(0, 0, 0, 0);\n\n    // create ComboBox\n    comboBox = createComboBox(true);\n    layout->addWidget(comboBox);\n    layoutWidget->setFocusProxy(comboBox);\n    connect(comboBox, SIGNAL(editTextChanged(const QString &)), this, SLOT(comboBoxEditTextChanged(const QString &)));\n\n    // create DateTime-Editor\n    dateTimeEdit = new QDateTimeEdit();\n    dateTimeEdit-> setDisplayFormat(\"yyyy-MM-dd hh:mm:ss\");\n    dateTimeEdit->setMinimumDateTime(QDate(1858, 11, 17).startOfDay()); // (mjd = 0)\n    dateTimeEdit->setDateTime(mjd2date(mjd));\n    layout->addWidget(dateTimeEdit);\n    connect(dateTimeEdit, SIGNAL(dateTimeChanged(const QDateTime &)), this, SLOT(dateTimeChanged(const QDateTime &)));\n\n    return layoutWidget;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementTime::interact()\n{\n  if(!dateTimeEdit->hasFocus())\n    dateTimeEdit->setFocus();\n  else\n    comboBox->setFocus();\n}\n\n/***********************************************/\n\nvoid TreeElementTime::comboBoxEditTextChanged(const QString &text)\n{\n  try\n  {\n    if(dateTimeEdit && !changeNotDateTime) // avoid infinite recursion\n    {\n      mjd = 0;\n      if(tree->elementGlobal)\n      {\n        try\n        {\n          bool resolved = true;\n          auto result = StringParser::parse(name().toStdString(), text.toStdString(), *varList, resolved);\n          if(resolved)\n            mjd = ExpressionVariable::parse(result, *varList);\n        }\n        catch(std::exception &/*e*/)\n        {} // if not a number use mjd = 0\n      }\n\n      changeNotComboBox = true;\n      dateTimeEdit->setDateTime(mjd2date(mjd));\n      changeNotComboBox = false;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeElementTime::dateTimeChanged(const QDateTime &dateTime)\n{\n  try\n  {\n    if(comboBox && !changeNotComboBox) // avoid infinite recursion\n    {\n      changeNotDateTime = true;\n      QString text = date2mjd(dateTime);\n      comboBox->setEditText(text);\n      comboBoxTextEdited(text);\n      changeNotDateTime = false;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nQString TreeElementTime::date2mjd(const QDateTime &dateTime) const\n{\n  try\n  {\n    int Y   = dateTime.date().year();\n    int M   = dateTime.date().month();\n    int D   = dateTime.date().day();\n    int mjd = (1461 * (Y + 4800 + (M - 14)/12))/4 +(367 * (M - 2 - 12 * ((M - 14)/12)))/12 - (3 * ((Y + 4900 + (M - 14)/12)/100))/4 + D - 32075-2400001;\n\n    int    hour = dateTime.time().hour();\n    int    min  = dateTime.time().minute();\n    double sec  = dateTime.time().second(); //+dateTime.time().msec()/1000.;\n\n    QString     string;\n    QTextStream stream(&string);\n    bool        set=false;\n    if(mjd!=0)  {stream<<mjd; set=true;}\n    if(hour!=0) {stream<<((set)?\"+\":\"\")<<hour<<\"/24\";   set=true;}\n    if(min!=0)  {stream<<((set)?\"+\":\"\")<<min<<\"/1440\";  set=true;}\n    if(sec!=0.) {stream<<((set)?\"+\":\"\")<<sec<<\"/86400\"; set=true;}\n    return string;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nQDateTime TreeElementTime::mjd2date(Double mjd) const\n{\n  try\n  {\n    Time time = mjd2time(mjd);\n    UInt year, month, day, hour, minute;\n    Double second;\n    time.date(year, month, day, hour, minute, second);\n\n    QDateTime dateTime(QDate(year, month, day), QTime(hour, minute, second));\n    if(std::round(second - dateTime.time().second()) > 0)\n      dateTime = dateTime.addSecs(1);\n    return dateTime;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nQString TreeElementTime::parseExpression(const QString &text, const VariableList &varList) const\n{\n  mjd = 0;\n  QString result = text;\n  try\n  {\n    bool resolved = true;\n    result = QString::fromStdString(StringParser::parse(name().toStdString(), text.toStdString(), varList, resolved));\n    if(result.isEmpty() || !resolved)\n      return result;\n    mjd = ExpressionVariable::parse(result.toStdString(), varList);\n    result.setNum(mjd, 'f', 7).remove(QRegularExpression(\"0+$\")).remove(QRegularExpression(\"\\\\.$\")); // %.7f with trailing zeros removed\n    if(mjd == 0)\n      return result;\n\n    // is a date?\n    if(mjd > 1000)\n    {\n      QString dateString = mjd2date(mjd).toString(\"yyyy-MM-dd hh:mm:ss\");\n      if(dateString.endsWith(\" 00:00:00\"))\n        dateString.truncate(dateString.lastIndexOf(\" 00:00:00\"));\n      return dateString.trimmed();\n    }\n\n    // time span\n    QDateTime dateTime = mjd2date(std::fabs(mjd));\n    if(dateTime.time() == QTime(0,0,0))\n      return result;\n    QString dateString;\n    if(mjd < 0)\n      dateString += \"-\";\n    if(std::floor(std::abs(mjd)))\n      dateString += QString::number(static_cast<int>(std::floor(std::abs(mjd))))+\"d \"; // days\n    dateString += dateTime.toString(\"hh:mm:ss\");\n    if(result != text)\n      dateString += \" (\"+result+\")\";\n    return dateString;\n  }\n  catch(std::exception &/*e*/)\n  {\n  }\n\n  return result;\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementTime.h",
    "content": "/***********************************************/\n/**\n* @file treeElementSimple.h\n*\n* @brief Element with date/time editor.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-06-10\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTTIME__\n#define __GROOPSGUI__TREEELEMENTTIME__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementSimple.h\"\n\n/***** TYPES ***********************************/\n\nclass QComboBox;\nclass QDateTimeEdit;\nclass QDateTime;\n\n/***** CLASS ***********************************/\n\nclass TreeElementTime : public TreeElementSimple\n{\n  Q_OBJECT\n\n  VariableListPtr varList;\n\npublic:\n  TreeElementTime(Tree *tree, TreeElementComplex *parentElement, XsdElementPtr xsdElement,\n                  const QString &defaultOverride, XmlNodePtr xmlNode, bool fillWithDefaults)\n    : TreeElementSimple(tree, parentElement, xsdElement, defaultOverride, xmlNode, fillWithDefaults), mjd(0.) {}\n\n  /** @brief changes the current index.\n   * calls TreeElementSimple::selectIndex\n  * Updates the timeEditor. */\n  void setSelectedIndex(int index) override;\n\n  /** @brief inform this element about changed variables.\n  * recursively called for all children.\n  * If this element is a variable and @a addVariableInReturn an updated varList is returned. */\n  VariableListPtr updateParserResults(VariableListPtr varList, Bool addVariableInReturn) override {this->varList = varList; return TreeElementSimple::updateParserResults(varList, addVariableInReturn);}\n\n  /** @brief creates an editable combo box + dateTimeEdit. */\n  QWidget *createEditor() override;\n\n  /** @brief Switches focus between comboBox and dateTimeEdit. */\n  void interact() override;\n\nprivate:\n  mutable Double          mjd; // updated by parseExpression\n  QPointer<QComboBox>     comboBox;\n  QPointer<QDateTimeEdit> dateTimeEdit;\n  bool changeNotComboBox, changeNotDateTime;\n\n  QString   date2mjd(const QDateTime &dateTime) const;\n  QDateTime mjd2date(Double mjd) const;\n\n  QString parseExpression(const QString &text, const VariableList &varList) const override;\n\nprivate slots:\n  void comboBoxEditTextChanged(const QString &text);\n  void dateTimeChanged(const QDateTime &dateTime);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "gui/tree/treeElementUnknown.cpp",
    "content": "/***********************************************/\n/**\n* @file treeElementUnknown.cpp\n*\n* @brief Unknown element without XML schema entry.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementUnknown.h\"\n\n/***********************************************/\n\nTreeElementUnknown::TreeElementUnknown(Tree *tree, TreeElementComplex *parentElement, XmlNodePtr xmlNode)\n  : TreeElementComplex(tree, parentElement, XsdElementPtr(nullptr), \"\", xmlNode)\n{\n  try\n  {\n    if(!xmlNode)\n      throw(Exception(\"no XML given\"));\n\n    _isEditable = !(xmlNode->hasChildren());\n    addChoice(xmlNode->getText(), XsdElementPtr(nullptr), QJsonObject());\n    createChildrenElements(0, xmlNode);\n    setSelectedIndex(isLinked() ? selectedIndex() : 0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr TreeElementUnknown::createXmlTree(bool /*createRootEvenIfEmpty*/) const\n{\n  try\n  {\n    XmlNodePtr xmlNode = TreeElement::createXmlBaseNode();\n    if(!isLinked())\n      xmlNode->setText(selectedValue());\n    createXmlChildren(xmlNode, true/*createRootEvenIfEmpty*/);\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeElementUnknown.h",
    "content": "/***********************************************/\n/**\n* @file treeElementUnknown.h\n*\n* @brief Enknown element without XML schema entry.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEELEMENTUNKNOWN__\n#define __GROOPSGUI__TREEELEMENTUNKNOWN__\n\n#include \"base/importGroops.h\"\n#include \"tree/treeElementComplex.h\"\n\n/***** CLASS ***********************************/\n\nclass TreeElementUnknown : public TreeElementComplex\n{\n  Q_OBJECT\n\n  bool _isEditable;\n\npublic:\n  TreeElementUnknown(Tree *tree, TreeElementComplex *parentElement, XmlNodePtr xmlNode);\n\n  bool optional()          const override {return true;}\n  bool unbounded()         const override {return true;}\n  bool isRenamedInSchema() const override {return false;}\n  bool canSetLoop()        const override {return false;}\n  bool canSetCondition()   const override {return false;}\n  bool isDeprecated()      const override {return false;}\n\n  /** @brief Values can be edited. */\n  bool isEditable() const override {return _isEditable;}\n\n  /** @brief Generate XML-tree.\n  * recursivly called for all children. */\n  XmlNodePtr createXmlTree(bool /*createRootEvenIfEmpty*/) const override;\n\n  /** @brief creates an editable combo box. */\n  QWidget *createEditor() override {return createComboBox(_isEditable);}\n};\n\n/***********************************************/\n\n#endif /* __GROOPSGUI__TREEELEMENTSEQUENCE__ */\n"
  },
  {
    "path": "gui/tree/treeItem.cpp",
    "content": "/***********************************************/\n/**\n* @file treeItem.cpp\n*\n* @brief Visible representation of an element as an item in the tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#include <QtDebug>\n#include <QLineEdit>\n#include <QPainter>\n#include \"base/importGroops.h\"\n#include \"tree/tree.h\"\n#include \"tree/treeElement.h\"\n#include \"tree/treeElementAdd.h\"\n#include \"tree/treeElementComplex.h\"\n#include \"tree/treeElementGlobal.h\"\n#include \"tree/treeElementProgram.h\"\n#include \"tree/treeElementLoopCondition.h\"\n#include \"tree/treeElementComment.h\"\n#include \"tree/treeElementUnknown.h\"\n#include \"tree/treeItem.h\"\n\n/***********************************************/\n/***********************************************/\n\nTreeItem *TreeItem::newTreeItem(TreeElement *treeElement, TreeItem *parent, TreeItem *after)\n{\n  try\n  {\n    if(!treeElement)\n      throw(Exception(\"TreeElement==nullptr\"));\n    TreeItem *item = nullptr;\n    if(!parent)\n      item = new TreeItem(treeElement, treeElement->tree->treeWidget);\n    else if(after)\n      item = new TreeItem(treeElement, parent, after);\n    else\n      item = new TreeItem(treeElement, parent);\n\n    item->setFocus();\n\n    return item;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::init(TreeElement *treeElement)\n{\n  try\n  {\n    this->valueEditor   = nullptr;\n    this->_treeElement  = treeElement;\n    this->commentEditor = nullptr;\n\n    if(dynamic_cast<TreeElementComment*>(treeElement))\n      icon = iconDisabled = QIcon(\":/icons/scalable/element-comment.svg\");\n    else if(dynamic_cast<TreeElementLoopCondition*>(treeElement) && (treeElement->type() == \"loopType\"))\n      icon = iconDisabled = QIcon(\":/icons/scalable/loop-set.svg\");\n    else if(dynamic_cast<TreeElementLoopCondition*>(treeElement) && (treeElement->type() == \"conditionType\"))\n      icon = iconDisabled = QIcon(\":/icons/scalable/condition-set.svg\");\n    else if(!treeElement->label().isEmpty())\n    {\n      icon         = QIcon(\":/icons/scalable/link.svg\");\n      iconDisabled = QIcon(\":/icons/scalable/link-disabled.svg\");\n    }\n    else if(dynamic_cast<TreeElementProgram*>(treeElement))\n    {\n      icon         = QIcon(\":/icons/scalable/program.svg\");\n      iconDisabled = QIcon(\":/icons/scalable/program-disabled.svg\");\n    }\n    else if(dynamic_cast<TreeElementAdd*>(treeElement))\n      icon = iconDisabled = QIcon(\":/icons/scalable/element-unbounded.svg\");\n    else if(dynamic_cast<TreeElementUnknown*>(treeElement))\n    {\n      icon         = QIcon(\":/icons/scalable/element-unknown.svg\");\n      iconDisabled = QIcon(\":/icons/scalable/element-unknown-disabled.svg\");\n    }\n    else if(!treeElement->optional() && !treeElement->unbounded())\n      icon = iconDisabled = QIcon(\":/icons/scalable/element-mustset.svg\");\n    else if ((treeElement->optional()) && !treeElement->unbounded())\n    {\n      icon         = QIcon(\":/icons/scalable/element.svg\");\n      iconDisabled = QIcon(\":/icons/scalable/element-disabled.svg\");\n    }\n    else if(!treeElement->optional() && treeElement->unbounded())\n    {\n      icon         = QIcon(\":/icons/scalable/element-mustset-unbounded.svg\");\n      iconDisabled = QIcon(\":/icons/scalable/element-mustset-unbounded-disabled.svg\");\n    }\n    else if(treeElement->optional() && treeElement->unbounded())\n    {\n      icon         = QIcon(\":/icons/scalable/element-unbounded.svg\");\n      iconDisabled = QIcon(\":/icons/scalable/element-unbounded-disabled.svg\");\n    }\n\n    updateIcon();\n    updateName();\n    updateValue();\n    updateAnnotation(treeElement->annotation());\n    updateComment();\n\n    setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nTreeItem::~TreeItem()\n{\n  lostCurrent();\n}\n\n/***********************************************/\n\nQVariant TreeItem::data(int column, int role) const\n{\n  if(role == Qt::ToolTipRole)\n  {\n    QFontMetrics fm(font(column));\n    if(treeWidget()->columnWidth(column) < fm.boundingRect(text(column)).width()+7)\n      return QVariant(text(column).replace(\" [=\", \"\\n[=\"));\n  }\n\n  return QTreeWidgetItem::data(column, role);\n}\n\n/***********************************************/\n\nvoid TreeItem::updateIcon()\n{\n  QIcon baseIcon = (treeElement()->disabled()) ? iconDisabled : icon;\n\n  if(treeElement()->isRenamedInSchema()) // add renamed icon to base icon\n  {\n    int iconHeight = treeWidget()->iconSize().height();\n    QIcon renamedIcon(\":/icons/scalable/edit-rename.svg\");\n    QPixmap pixmap(2*iconHeight, iconHeight);\n    pixmap.fill(QColor(0,0,0,0));\n    QPainter painter(&pixmap);\n    painter.drawPixmap(0, 0, baseIcon.pixmap(iconHeight));\n    painter.drawPixmap(iconHeight+2, 0, renamedIcon.pixmap(iconHeight));\n    setIcon(0, pixmap);\n  }\n  else\n    setIcon(0, baseIcon);\n}\n\n/***********************************************/\n\nvoid TreeItem::updateName()\n{\n  QString text = treeElement()->name();\n  if(treeElement()->loop)      text += \" [loop]\";\n  if(treeElement()->condition) text += \" [condition]\";\n  setText(0, text);\n}\n\n/***********************************************/\n\nvoid TreeItem::updateValue()\n{\n  if(valueEditor)\n    return;\n\n  QString text   = treeElement()->selectedValue();\n  QString result = treeElement()->selectedResult();\n  if(treeElement()->tree->showResults() && !result.isEmpty() && (result != text) && (result != \"{\"+text+\"}\"))\n    text += \"   [=\"+result+\"]\";\n  setText(1, text);\n  QIcon icon;\n  if(treeElement()->isBrokenLinked())\n    icon = QIcon(\":/icons/scalable/link-broken.svg\");\n  else if(treeElement()->isLinked())\n    icon = QIcon(\":/icons/scalable/link.svg\");\n  else if(dynamic_cast<TreeElementChoice*>(treeElement()) && dynamic_cast<TreeElementChoice*>(treeElement())->isSelectionRenamedInSchema(treeElement()->selectedIndex()))\n    icon = QIcon(\":/icons/scalable/edit-rename.svg\");\n  else if(dynamic_cast<TreeElementChoice*>(treeElement()) && dynamic_cast<TreeElementChoice*>(treeElement())->isSelectionUnknown(treeElement()->selectedIndex()))\n    icon = QIcon(\":/icons/scalable/element-unknown.svg\");\n  else if(dynamic_cast<TreeElementChoice*>(treeElement()) && dynamic_cast<TreeElementChoice*>(treeElement())->isSelectionDeprecated(treeElement()->selectedIndex()))\n    icon = QIcon(\":/icons/scalable/warning.svg\");\n  setIcon(1, icon);\n}\n\n/***********************************************/\n\nvoid TreeItem::updateAnnotation(const QString &text)\n{\n  setText(2, text);\n}\n\n/***********************************************/\n\nvoid TreeItem::updateComment()\n{\n  if(commentEditor)\n    return;\n  setText(3, treeElement()->comment());\n}\n\n/***********************************************/\n\nvoid TreeItem::becomeCurrent()\n{\n  try\n  {\n    treeWidget()->scrollToItem(this, QAbstractItemView::EnsureVisible);\n\n    if(!valueEditor)\n      valueEditor = treeElement()->createEditor();\n\n    if(valueEditor)\n    {\n      // clear cell\n      setText(1, \"\");\n      setIcon(1, QIcon());\n      // init widget\n      treeWidget()->setItemWidget(this, 1, valueEditor);\n      // treeElement()->tree->update();\n    }\n\n    treeElement()->startSelected();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::lostCurrent()\n{\n  try\n  {\n    treeElement()->stopSelected();\n\n    if(valueEditor)\n    {\n      treeWidget()->removeItemWidget(this, 1);\n      valueEditor = nullptr;\n      updateValue();\n      setSizeHint(1, QSize());\n      // treeElement()->tree->update();\n    }\n    if(commentEditor)\n    {\n      treeWidget()->removeItemWidget(this, 3);\n      delete commentEditor;\n      commentEditor = nullptr;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::setFocus()\n{\n  try\n  {\n    if(valueEditor)\n      valueEditor->setFocus();\n    else\n      treeWidget()->setFocus();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::setSelection(int start, int length)\n{\n  try\n  {\n    if(!valueEditor || start < 0)\n      return;\n\n    QLineEdit *lineEdit = valueEditor->findChild<QLineEdit*>();\n    if(lineEdit)\n      lineEdit->setSelection(start, length);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::selection(int &start, int &length) const\n{\n  try\n  {\n    start = -1;\n    length = 0;\n    if(!valueEditor)\n      return;\n\n    QLineEdit *lineEdit = valueEditor->findChild<QLineEdit*>();\n    if(lineEdit)\n    {\n      start = lineEdit->selectionStart() >= 0 ? lineEdit->selectionStart() : lineEdit->cursorPosition();\n      length = lineEdit->selectedText().size();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::editComment()\n{\n  try\n  {\n    if(!treeElement()->canComment())\n      return;\n    setText(3, \"\");\n    commentEditor = new QLineEdit(treeElement()->comment());\n    connect(commentEditor, SIGNAL(editingFinished()), this, SLOT(editCommentFinished()));\n    treeWidget()->setItemWidget(this, 3, commentEditor);\n    commentEditor->setFocus();\n    commentEditor->selectAll();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid TreeItem::editCommentFinished()\n{\n  try\n  {\n    if(!commentEditor)\n      return;\n    treeElement()->setComment(commentEditor->text());\n    treeWidget()->removeItemWidget(this, 3);\n    commentEditor->deleteLater();\n    commentEditor = nullptr;\n    updateComment();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "gui/tree/treeItem.h",
    "content": "/***********************************************/\n/**\n* @file treeItem.h\n*\n* @brief Visible representation of an element as an item in the tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2006-10-07\n*/\n/***********************************************/\n\n#ifndef __GROOPSGUI__TREEITEM__\n#define __GROOPSGUI__TREEITEM__\n\n#include <QTreeWidgetItem>\n#include <QPointer>\n#include \"base/importGroops.h\"\n\n/***** TYPES ***********************************/\n\nclass  TreeElement;\nclass  QLineEdit;\n\n/***** CLASS ***********************************/\n\nclass TreeItem : public QObject, public QTreeWidgetItem\n{\n  Q_OBJECT\n\n  TreeElement      *_treeElement;\n  QIcon              icon, iconDisabled;\n  QPointer<QWidget>  valueEditor;\n  QLineEdit         *commentEditor;\n\n  void init(TreeElement *treeElement);\n\n  TreeItem(TreeElement *treeElement, QTreeWidget *parent)                : QTreeWidgetItem(parent)        {init(treeElement);}\n  TreeItem(TreeElement *treeElement, TreeItem  *parent)                  : QTreeWidgetItem()              {parent->insertChild(0,this); init(treeElement);}\n  TreeItem(TreeElement *treeElement, TreeItem  *parent, TreeItem *after) : QTreeWidgetItem(parent, after) {init(treeElement);}\n\n  // adjust tooltip text\n  QVariant data(int column, int role) const override;\n\npublic:\n  virtual ~TreeItem();\n\n  /** @brief Append a new item to the tree.\n  * If parent==nullptr the element will be appended to root. */\n  static TreeItem *newTreeItem(TreeElement *treeElement, TreeItem *parent=nullptr, TreeItem *after=nullptr);\n\n  /** @brief The corresponding tree element. */\n  TreeElement *treeElement() const {return _treeElement;}\n\n  void updateIcon();\n  void updateName();\n  void updateValue();\n  void updateAnnotation(const QString &text);\n  void updateComment();\n\n  void becomeCurrent();\n  void lostCurrent();\n\n  void setFocus();\n\n  // for and search/replace\n  void setSelection(int start, int length);\n  void selection(int &start, int &length) const;\n\n  void editComment();\n\npublic slots:\n  void editCommentFinished();\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/.gitignore",
    "content": "# miscellaneous\n# -------------\n/build\n/Makefile\n"
  },
  {
    "path": "source/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10)\n\nproject(GROOPS LANGUAGES CXX Fortran)\n\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_Fortran_FLAGS \"-std=legacy\")\ninclude_directories(${PROJECT_SOURCE_DIR})\ninclude(sourcesCXX.txt)\ninclude(sourcesF77.txt)\ninclude(sourcesF90.txt)\nadd_library(groopscore OBJECT ${SOURCES})\n\n# =========================================\n\n# Libraries\n# ---------\n# stdc++fs  required C++14 std::experimental::filesystem or C++17 std::filesystem\n# EXPAT     required Stream-oriented XML parser library (https://libexpat.github.io/)\n# BLAS      required Basic Linear Algebra Subprograms (http://www.netlib.org/blas/)\n# LAPACK    required Linear Algebra PACKage (http://www.netlib.org/lapack/)\n# ERFA      optional Essential Routines for Fundamental Astronomy (https://github.com/liberfa)\n# Z         optional File compression (https://www.zlib.net)\n# NETCDF    optional Network Common Data Form (https://www.unidata.ucar.edu/software/netcdf/)\n\n# External Source Files\n# ---------------------\n# HWM14     Horizontal Wind Model 2014 (https://map.nrl.navy.mil/map/pub/nrl/HWM/HWM14/)\n# NRLMSIS   NRLMSIS 2.0 thermospheric model (https://map.nrl.navy.mil/map/pub/nrl/NRLMSIS/NRLMSIS2.0/)\n# JB2008    JB2008 thermospheric model (http://sol.spacenvironment.net/jb2008/)\n# IGRF      International Geomagnetic Reference Field (https://doi.org/10.1186/s40623-015-0228-9)\n# IERS      International Earth Rotation and Reference Systems Service (IERS) Conventions software collection (https://iers-conventions.obspm.fr/)\n\nfind_package(BLAS   REQUIRED)\nfind_package(LAPACK REQUIRED)\nfind_package(EXPAT  REQUIRED)\ninclude_directories(${EXPAT_INCLUDE_DIRS})\n\nset(BASE_LIBRARIES ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} ${EXPAT_LIBRARIES} stdc++fs)\n\nfind_library(LIB_ERFA erfa)\nif(LIB_ERFA AND ((NOT ${DISABLE_ERFA}) OR (NOT DEFINED DISABLE_ERFA)))\n  find_path(ERFA_INCLUDE_DIR NAMES erfa.h)\n  include_directories(${ERFA_INCLUDE_DIR})\n  set(BASE_LIBRARIES ${BASE_LIBRARIES} ${LIB_ERFA})\nelse()\n  add_definitions(-DGROOPS_DISABLE_ERFA)\n  message(WARNING \"ERFA library *NOT* found (https://github.com/liberfa). GROOPS is not able to compute Earth rotation based on IERS EOP files.\")\nendif()\n\nfind_library(LIB_Z z)\nif(LIB_Z AND ((NOT ${DISABLE_Z}) OR (NOT DEFINED DISABLE_Z)))\n  find_path(ZLIB_INCLUDE_DIR NAMES zlib.h)\n  include_directories(${ZLIB_INCLUDE_DIR})\n  set(BASE_LIBRARIES ${BASE_LIBRARIES} ${LIB_Z})\nelse()\n  add_definitions(-DGROOPS_DISABLE_Z)\n  message(WARNING \"Z library *NOT* found (https://www.zlib.net). GROOPS is not able to read/write compressed *.gz files.\")\nendif()\n\nfind_library(LIB_NETCDF netcdf)\nif(LIB_NETCDF AND ((NOT ${DISABLE_NETCDF}) OR (NOT DEFINED DISABLE_NETCDF)))\n  find_path(NETCDF_INCLUDE_DIR NAMES netcdf.h)\n  include_directories(${NETCDF_INCLUDE_DIR})\n  set(BASE_LIBRARIES ${BASE_LIBRARIES} ${LIB_NETCDF})\nelse()\n  add_definitions(-DGROOPS_DISABLE_NETCDF)\n  message(WARNING \"netCDF library *NOT* found (https://www.unidata.ucar.edu/software/netcdf). GROOPS is not able to convert netCDF *.grd files.\")\nendif()\n\nif(${DISABLE_HWM14})\n  message(WARNING \"HWM14 wind model will *NOT* be compiled.\")\n  add_definitions(-DGROOPS_DISABLE_HWM14)\nendif()\n\nif(${DISABLE_NRLMSIS})\n  message(WARNING \"NRLMSIS thermospheric model will *NOT* be compiled.\")\n  add_definitions(-DGROOPS_DISABLE_NRLMSIS)\nendif()\n\nif(${DISABLE_JB2008})\n  message(WARNING \"JB2008 thermospheric model will *NOT* be compiled.\")\n  add_definitions(-DGROOPS_DISABLE_JB2008)\nendif()\n\nif(${DISABLE_IGRF})\n  message(WARNING \"IGRF magnetic field model will *NOT* be compiled.\")\n  add_definitions(-DGROOPS_DISABLE_IGRF)\nendif()\n\nif(${DISABLE_IERS})\n  message(WARNING \"IERS software routines will *NOT* be compiled.\")\n  add_definitions(-DGROOPS_DISABLE_IERS)\nendif()\n\n# =========================================\n\nadd_executable(groops ${PROJECT_SOURCE_DIR}/parallel/parallelSingle.cpp $<TARGET_OBJECTS:groopscore>)\ntarget_link_libraries(groops ${BASE_LIBRARIES})\n\ninstall(TARGETS groops DESTINATION bin)\n\n# =========================================\n\nfind_package(MPI COMPONENTS CXX)\nif(MPI_FOUND)\n  include_directories(${MPI_CXX_INCLUDE_PATH})\n  add_executable(groopsMPI ${PROJECT_SOURCE_DIR}/parallel/parallelCluster.cpp $<TARGET_OBJECTS:groopscore>)\n\n  target_link_libraries(groopsMPI ${BASE_LIBRARIES} ${MPI_CXX_LIBRARIES})\n  if(MPI_COMPILE_FLAGS)\n    set_target_properties(groopsMPI PROPERTIES COMPILE_FLAGS \"${MPI_CXX_COMPILE_FLAGS}\")\n  endif()\n  if(MPI_LINK_FLAGS)\n    set_target_properties(groopsMPI PROPERTIES LINK_FLAGS \"${MPI_CXX_LINK_FLAGS}\")\n  endif()\n  install(TARGETS groopsMPI DESTINATION bin)\nelse()\n  message(WARNING \"A GROOPS executable for MPI parallel computing will *NOT* be created.\")\nendif()\n\n# =========================================\n"
  },
  {
    "path": "source/base/angle.h",
    "content": "/***********************************************/\n/**\n* @file angle.h\n*\n* @brief Angle in radians.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-31-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ANGLE__\n#define __GROOPS_ANGLE__\n\n#include \"base/importStd.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Angle in radians.\n* @ingroup vector3dGroup\n* It's only used to distinguish between doubles and angles in input/output.\n* Angle is converted from/to degrees in input/output. */\nclass Angle\n{\n  Double value;\n\npublic:\n  explicit Angle(Double x=0.) : value(x) {}   //!< Default constructor\n\n  Angle &operator=(Double x) {value=x; return *this;} //!< Assignment.\n\n  operator Double() const {return value;} //!< Cast to Double.\n\n  Angle &operator*= (Double c)       {value *= c;       return *this;}\n  Angle &operator+= (const Angle &x) {value += x.value; return *this;}\n  Angle &operator-= (const Angle &x) {value -= x.value; return *this;}\n};\n\n/***********************************************/\n\ninline Angle operator- (const Angle &t)                   {return Angle(t)  *= -1;}\ninline Angle operator+ (const Angle &t1, const Angle &t2) {return Angle(t1) += t2;}\ninline Angle operator- (const Angle &t1, const Angle &t2) {return Angle(t1) -= t2;}\ninline Angle operator* (Double c, const Angle &t)         {return Angle(t)  *=c;}\ninline Angle operator* (const Angle &t, Double c)         {return Angle(t)  *=c;}\n\n/*************************************************/\n\n#endif\n"
  },
  {
    "path": "source/base/basisSplines.h",
    "content": "/***********************************************/\n/**\n* @file basisSplines.h\n*\n* @brief Basis Splines.\n*\n* @author Beate Klinger\n* @date 2015-05-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BASISSPLINES__\n#define __GROOPS_BASISSPLINES__\n\n#include \"base/importStd.h\"\n#include \"matrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Basis Splines.\n* @ingroup base */\nnamespace BasisSplines\n{\n  /** @brief Basis Splines.\n  * @param t in [0,1).\n  * @param degree spline degree.\n  * @return vector(degree+1) with splines coefficients. */\n  inline Vector compute(Double t, UInt degree);\n}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ninline Vector BasisSplines::compute(Double t, UInt degree)\n{\n  Vector b(degree+1);\n  b(0) = 1.;\n  for(UInt n=1; n<=degree; n++)\n  {\n    b(n) = t/n * b(n-1);\n    for(UInt i=n; i-->1;)\n      b(i) = (t+n-i)/n * b(i-1) - (t-i-1)/n * b(i);\n    b(0) *= (1-t)/n;\n  }\n\n  return b;\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/base/constants.cpp",
    "content": "/***********************************************/\n/**\n* @file constants.cpp\n*\n* @brief Define constants.\n*\n* Constants are only valid after call of main().\n* New constants must be set in inputOutput/settings.cpp.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n#include \"base/constants.h\"\n\n/***** CONSTANTS *******************************/\n\nDouble LIGHT_VELOCITY;\n\n/***** DEFAULTS ********************************/\n\nDouble DEFAULT_GRS80_a;\nDouble DEFAULT_GRS80_f;\nDouble DEFAULT_GM;\nDouble DEFAULT_R;\nstd::string STRING_DEFAULT_GRS80_a;\nstd::string STRING_DEFAULT_GRS80_f;\nstd::string STRING_DEFAULT_GM;\nstd::string STRING_DEFAULT_R;\n\n/***** CONSTANTS for Planets and Tides *********/\n\nDouble GRAVITATIONALCONSTANT;\nDouble R_Earth;\nDouble R_Moon;\nDouble GM_Earth;\nDouble GM_Sun;\nDouble GM_Moon;\nDouble GM_MERCURY;\nDouble GM_VENUS;\nDouble GM_MARS;\nDouble GM_JUPITER;\nDouble GM_SATURN;\n\n/***** TIME SHIFTS *****************************/\n\nDouble TIME_EPSILON;\nDouble DELTA_TAI_GPS;\nDouble DELTA_TT_GPS;\nDouble J2000;\nstd::string STRING_J2000;\n\nstd::vector<Int>    MJD_UTC_GPS;\nstd::vector<Double> DELTA_UTC_GPS;\n\n/***** CLASS ***********************************/\n\n// class for constants initialization,\n// will be initialized before main()\nclass InitConstants\n{\npublic:\n  InitConstants();\n};\n\nstatic InitConstants initConstants;\n\n/***********************************************/\n\nInitConstants::InitConstants()\n{\n  try\n  {\n    LIGHT_VELOCITY = 299792458.0;\n\n    STRING_DEFAULT_GRS80_a = \"6378137.0\";\n    STRING_DEFAULT_GRS80_f = \"298.2572221010\";\n    STRING_DEFAULT_GM      = \"3.986004415e+14\";\n    STRING_DEFAULT_R       = \"6378136.3\";\n\n    DEFAULT_GM      = std::atof(STRING_DEFAULT_GM.c_str());\n    DEFAULT_R       = std::atof(STRING_DEFAULT_R.c_str());\n    DEFAULT_GRS80_a = std::atof(STRING_DEFAULT_GRS80_a.c_str());\n    DEFAULT_GRS80_f = std::atof(STRING_DEFAULT_GRS80_f.c_str());\n\n    GRAVITATIONALCONSTANT = 6.673e-11;\n    R_Earth    = DEFAULT_R;\n    R_Moon     = 1738000;\n    GM_Earth   = DEFAULT_GM;\n    GM_Sun     = 1.32712442076e20;\n    GM_Moon    = 0.49028010560e13; //GM_Earth/81.30056;\n    GM_MERCURY = GM_Sun/6023600.0;\n    GM_VENUS   = GM_Sun/408523.71;\n    GM_MARS    = GM_Sun/3098708.0;\n    GM_JUPITER = GM_Sun/1047.3486;\n    GM_SATURN  = GM_Sun/3497.898;\n\n    TIME_EPSILON  = 1e-5;\n    DELTA_TAI_GPS = 19.0;\n    DELTA_TT_GPS  = 51.184;\n    STRING_J2000  = \"51544.5\";\n    J2000         = std::atof(STRING_J2000.c_str());\n\n    MJD_UTC_GPS.push_back(date2time(2017, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-18);\n    MJD_UTC_GPS.push_back(date2time(2015, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-17);\n    MJD_UTC_GPS.push_back(date2time(2012, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-16);\n    MJD_UTC_GPS.push_back(date2time(2009, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-15);\n    MJD_UTC_GPS.push_back(date2time(2006, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-14);\n    MJD_UTC_GPS.push_back(date2time(1999, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-13);\n    MJD_UTC_GPS.push_back(date2time(1997, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-12);\n    MJD_UTC_GPS.push_back(date2time(1996, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-11);\n    MJD_UTC_GPS.push_back(date2time(1994, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-10);\n    MJD_UTC_GPS.push_back(date2time(1993, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-9);\n    MJD_UTC_GPS.push_back(date2time(1992, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-8);\n    MJD_UTC_GPS.push_back(date2time(1991, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-7);\n    MJD_UTC_GPS.push_back(date2time(1990, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-6);\n    MJD_UTC_GPS.push_back(date2time(1988, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(-5);\n    MJD_UTC_GPS.push_back(date2time(1985, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-4);\n    MJD_UTC_GPS.push_back(date2time(1983, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-3);\n    MJD_UTC_GPS.push_back(date2time(1982, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-2);\n    MJD_UTC_GPS.push_back(date2time(1981, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(-1);\n    MJD_UTC_GPS.push_back(date2time(1980, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(0);\n    MJD_UTC_GPS.push_back(date2time(1979, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(1);\n    MJD_UTC_GPS.push_back(date2time(1978, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(2);\n    MJD_UTC_GPS.push_back(date2time(1977, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(3);\n    MJD_UTC_GPS.push_back(date2time(1976, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(4);\n    MJD_UTC_GPS.push_back(date2time(1975, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(5);\n    MJD_UTC_GPS.push_back(date2time(1974, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(6);\n    MJD_UTC_GPS.push_back(date2time(1973, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(7);\n    MJD_UTC_GPS.push_back(date2time(1972, 7, 1).mjdInt());  DELTA_UTC_GPS.push_back(8);\n    MJD_UTC_GPS.push_back(date2time(1972, 1, 1).mjdInt());  DELTA_UTC_GPS.push_back(9);\n    MJD_UTC_GPS.push_back(0);                               DELTA_UTC_GPS.push_back(10);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/constants.h",
    "content": "/***********************************************/\n/**\n* @file constants.h\n*\n* @brief define constants.\n*\n* Constants are only valid after call of main().\n* New constants must be set in inputOutput/settings.cpp.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONSTANTS__\n#define __GROOPS_CONSTANTS__\n\n#include \"base/importStd.h\"\n\n/**\n* @defgroup constants Constants\n* @brief General constants used in groops.\n* @ingroup base\n* Constants can be overwritten with groopsDefaults.xml file on input. */\n// @{\n\n/***** CONST ***********************************/\n\nconstexpr Double PI             = 3.141592653589793238462643383279502884; //!< 3.1415.\nconstexpr Double RAD2DEG        = 180.0/PI;           //!< Conversion radian -> degree\nconstexpr Double DEG2RAD        = PI/180.0;           //!< Conversion degree -> radian.\nconstexpr UInt   MAX_UINT       = 4294967295U;        //!< max. representable integer number.\nconstexpr UInt   INFINITYDEGREE = MAX_UINT;           //!< infinity polynomial/harmonics degree.\nconstexpr UInt   NULLINDEX      = MAX_UINT;           //!< undefined index.\nconstexpr Double NAN_EXPR       = std::numeric_limits<Double>::has_quiet_NaN ? std::numeric_limits<Double>::quiet_NaN() : NAN; //!< not a number symbol\n\n[[deprecated(\"Use RAD2DEG instead (or 1/RHO -> RAD2DEG\")]] constexpr Double RHO = RAD2DEG;\n\nextern Double LIGHT_VELOCITY;  //!< speed of light [m/s].\n\n/***** DEFAULTS ********************************/\n\nextern std::string STRING_DEFAULT_GM;       //!< Gravitational constant of the Earth (EGM96).\nextern std::string STRING_DEFAULT_R;        //!< Reference radius (EGM96).\nextern std::string STRING_DEFAULT_GRS80_a;  //!< Semi major axis of Earth's ellipsoid.\nextern std::string STRING_DEFAULT_GRS80_f;  //!< inverse flattening of Earth's ellipsoid.\n\nextern Double DEFAULT_GM;      //!< Gravitational constant of the Earth (EGM96).\nextern Double DEFAULT_R;       //!< Reference radius (EGM96).\nextern Double DEFAULT_GRS80_a; //!< Semi major axis of Earth's ellipsoid.\nextern Double DEFAULT_GRS80_f; //!< inverse flattening of Earth's ellipsoid.\n\n/***** CONSTANTS for Planets and Tides *********/\n\nextern Double GRAVITATIONALCONSTANT; //!< Gravitational constant 6.673e-11.\nextern Double R_Earth;               //!< Earth radius (Used in Planets).\nextern Double R_Moon;                //!< Moon radius.\nextern Double GM_Earth;              //!< Gravitational constant of the Earth (Used in Planets).\nextern Double GM_Sun;                //!< Gravitational constant of the sun (Used in Planets).\nextern Double GM_Moon;               //!< Gravitational constant of the moon (Used in Planets).\nextern Double GM_MERCURY;            //!< Gravitational constant of mercury (Used in Planets).\nextern Double GM_VENUS;              //!< Gravitational constant of venus (Used in Planets).\nextern Double GM_MARS;               //!< Gravitational constant of mars (Used in Planets).\nextern Double GM_JUPITER;            //!< Gravitational constant of jupiter (Used in Planets).\nextern Double GM_SATURN;             //!< Gravitational constant of saturn (Used in Planets).\n\n/***** Ionosphere ******************************/\n\nnamespace Ionosphere\n{\n  constexpr Double e0 =  8.854187817e-12;              //!< Permittivity of free space [F/m].\n  constexpr Double me =  9.1093835611e-31;             //!< Electron mass [kg]\n  constexpr Double E  = -1.602176634e-19;              //!< Electron charge [C]\n  constexpr Double Ap =  1e16*(E*E/(4*PI*PI*e0*me))/2; //!< 40.3e16 in [TECU -> m]\n}\n\n/***** TIME SHIFTS *****************************/\n\nextern Double      TIME_EPSILON;   //!< Margin to consider two times identical [seconds].\nextern Double      DELTA_TAI_GPS;  //!< Seconds to be added to GPS time to get TAI.\nextern Double      DELTA_TT_GPS;   //!< Seconds to be added to GPS time to get TT.\nextern Double      J2000;          //!< J2000 in mjd\nextern std::string STRING_J2000;   //!< J2000 in mjd\n\nextern std::vector<Int>    MJD_UTC_GPS;   //!< Time of new introduced leap second.\nextern std::vector<Double> DELTA_UTC_GPS; //!< Leap seconds.\n\n// @} group constants\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/base/doodson.cpp",
    "content": "/***********************************************/\n/**\n* @file doodson.cpp\n*\n* @brief Doodson arguments and multipliers.\n*\n* @author Torsten Mayer-Guerr\n* @author Daniel Rieser\n* @date 2005-07-15\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/matrix.h\"\n#include \"base/time.h\"\n#include \"base/planets.h\"\n#include \"base/doodson.h\"\n\n/***********************************************/\n\nstruct DoodsonName\n{\n  const char *code;\n  const char *name;\n};\nstatic const DoodsonName doodsonName[] = {\n      // long periodic          // xi = PI/2 * std::remainder(j,4)\n      {\"055.565\", \"om1\"    },   // j=2\n      {\"055.575\", \"om2\"    },   // j=0\n      {\"056.554\", \"sa\"     },   // j=0\n      {\"056.555\", \"sa\"     },   // j=0\n      {\"057.555\", \"ssa\"    },   // j=0\n      {\"058.554\", \"sta\"    },   // j=0\n      {\"063.655\", \"msm\"    },   // j=0\n      {\"065.455\", \"mm\"     },   // j=0\n      {\"065.555\", \"d3mm\"   },   // j=3 (degree 3)\n      {\"073.555\", \"msf\"    },   // j=0\n      {\"075.555\", \"mf\"     },   // j=0\n      {\"083.655\", \"mstm\"   },   // j=0\n      {\"085.455\", \"mtm\"    },   // j=0\n      {\"093.555\", \"msq\"    },   // j=0\n      {\"093.555\", \"msqm\"   },   // j=0 alternative name\n      // diurnal\n      {\"125.755\", \"2q1\"    },   // j=3\n      {\"127.555\", \"sig1\"   },   // j=3\n      {\"127.555\", \"sigma1\" },   // j=3 alternative name\n      {\"135.555\", \"d3q1\"   },   // j=2 (degree 3)\n      {\"135.655\", \"q1\"     },   // j=3\n      {\"137.455\", \"rho1\"   },   // j=3\n      {\"137.455\", \"ro1\"    },   // j=3 alternative name\n      {\"145.555\", \"o1\"     },   // j=3\n      {\"145.655\", \"d3o1\"   },   // j=2\n      {\"147.555\", \"tau1\"   },   // j=1\n      {\"155.555\", \"d3m1\"   },   // j=2 (degree 3)\n      {\"155.655\", \"m1\"     },   // j=1\n      {\"157.455\", \"chi1\"   },   // j=1\n      {\"162.556\", \"pi1\"    },   // j=3\n      {\"163.555\", \"p1\"     },   // j=3\n      {\"164.555\", \"s1\"     },   // j=2\n      {\"164.556\", \"s1(tgp)\"},   // j=1\n      {\"165.555\", \"k1\"     },   // j=1\n      {\"166.554\", \"psi1\"   },   // j=1\n      {\"167.555\", \"phi1\"   },   // j=1\n      {\"167.555\", \"fi1\"    },   // j=1 alternative name\n      {\"173.655\", \"theta1\" },   // j=1\n      {\"173.655\", \"tet1\"   },   // j=1 alternative name\n      {\"173.655\", \"the1\"   },   // j=1 alternative name\n      {\"175.455\", \"j1\"     },   // j=1\n      {\"175.555\", \"d3j1\"   },   // j=2 (degree 3)\n      {\"183.555\", \"so1\"    },   // j=1\n      {\"185.555\", \"oo1\"    },   // j=1\n      {\"195.455\", \"v1\"     },   // j=1\n      // semidiurnal\n      {\"225.855\", \"3n2\"    },   // j=0\n      {\"227.655\", \"eps2\"   },   // j=0\n      {\"235.655\", \"d32n2\"  },   // j=1 (degree 3)\n      {\"235.755\", \"2n2\"    },   // j=0\n      {\"237.555\", \"mu2\"    },   // j=0\n      {\"237.555\", \"mi2\"    },   // j=0 alternative name\n      {\"245.555\", \"d3n2\"   },   // j=1 (degree 3)\n      {\"245.655\", \"n2\"     },   // j=0\n      {\"247.455\", \"nu2\"    },   // j=0\n      {\"247.455\", \"ni2\"    },   // j=0 alternative name\n      {\"253.755\", \"gamma2\" },   // j=2\n      {\"253.755\", \"gam2\"   },   // j=2 alternative name\n      {\"254.556\", \"alpha2\" },   // j=2\n      {\"254.556\", \"alf2\"   },   // j=2 alternative name\n      {\"255.555\", \"m2\"     },   // j=0\n      {\"255.655\", \"d3m2\"   },   // j=3 (degree 3)\n      {\"256.554\", \"beta2\"  },   // j=0\n      {\"256.554\", \"bet2\"   },   // j=0 alternative name\n      {\"257.555\", \"delta2\" },   // j=0\n      {\"257.555\", \"dlt2\"   },   // j=0 alternative name\n      {\"263.655\", \"la2\"    },   // j=2\n      {\"263.655\", \"lambda2\"},   // j=2 alternative name\n      {\"263.655\", \"lmb2\"   },   // j=2 alternative name\n      {\"265.455\", \"l2\"     },   // j=2\n      {\"265.555\", \"d3l2\"   },   // j=3 (degree 3)\n      {\"271.557\", \"2t2\"    },   // j=0\n      {\"272.556\", \"t2\"     },   // j=0\n      {\"273.555\", \"s2\"     },   // j=0\n      {\"273.555\", \"s2\"     },   // j=0\n      {\"274.554\", \"r2\"     },   // j=2\n      {\"275.555\", \"k2\"     },   // j=0\n      {\"283.655\", \"ksi2\"   },   // j=0\n      {\"285.455\", \"eta2\"   },   // j=0\n      // terdiurnal\n      {\"345.655\", \"d3mn3\"  },   // j=2 (degree 3)\n      {\"355.555\", \"d3m3\"   },   // j=2 (degree 3)\n      {\"375.555\", \"d3mk3\"  },   // j=2 (degree 3)\n      {\"381.555\", \"t3\"     },   // j=0 nonlinear\n      {\"382.555\", \"s3\"     },   // j=2 (degree 3)\n      {\"383.555\", \"r3\"     },   // j=0 nonlinear\n      // nonlinear\n      {\"435.755\", \"n4\"     },   // j=0\n      {\"445.655\", \"mn4\"    },   // j=0\n      {\"455.555\", \"m4\"     },   // j=0\n      {\"473.555\", \"ms4\"    },   // j=0\n      {\"491.555\", \"s4\"     },   // j=0\n      {\"5a0.555\", \"s5\"     },   // j=0\n      {\"655.555\", \"m6\"     },   // j=0\n      {\"6bz.555\", \"s6\"     },   // j=0\n      {\"855.555\", \"m8\"     },   // j=0\n      {nullptr,   nullptr  }};\n\n/***** CLASS ***********************************/\n\nDoodson::Doodson(const std::vector<Int> &v)\n{\n  try\n  {\n    d = {};\n    for(UInt i=0; i<std::min(v.size(), UInt(6)); i++)\n      d[i] = v.at(i);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDoodson::Doodson(const std::string &str)\n{\n  try\n  {\n    // convert to upper case\n    std::string str2 = str;\n    std::transform(str2.begin(), str2.end(), str2.begin(), ::tolower);\n    // find a name?\n    for(UInt i=0; doodsonName[i].name!=nullptr; i++)\n      if(str2 == doodsonName[i].name)\n      {\n        str2 = doodsonName[i].code;\n        break;\n      }\n\n    auto doodNumber = [](char c)\n    {\n      if(std::isdigit(c))          return static_cast<Int>(c-'0');\n      if(('a' <= c) && (c <= 'm')) return static_cast<Int>(c-'a')+10;\n      if(('n' <= c) && (c <= 'z')) return static_cast<Int>(c-'n')-13;\n      throw(Exception(\"unknown character: \"s+c));\n    };\n\n    d[0] = doodNumber(str2.at(0));\n    d[1] = doodNumber(str2.at(1));\n    d[2] = doodNumber(str2.at(2));\n    if(str2.at(3) != '.') throw(Exception(\"dot expected\"));\n    d[3] = doodNumber(str2.at(4));\n    d[4] = doodNumber(str2.at(5));\n    d[5] = doodNumber(str2.at(6));\n    for(UInt i=1; i<6; i++)\n      d[i] -= 5;\n\n    if(str2 != code())\n      throw(Exception(\"something strange: '\"+str2+\"' != \"+code()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"not a Doodson name or number: '\"+str+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nstd::string Doodson::code() const\n{\n  std::stringstream ss;\n\n  auto doodNumber = [](Int d)\n  {\n    if(d < 0) return static_cast<char>('n'+(d+13));\n    if(d > 9) return static_cast<char>('a'+(d-10));\n    return static_cast<char>('0'+d);\n  };\n\n  ss<<doodNumber(d[0]);\n  ss<<doodNumber(d[1]+5);\n  ss<<doodNumber(d[2]+5);\n  ss<<\".\";\n  ss<<doodNumber(d[3]+5);\n  ss<<doodNumber(d[4]+5);\n  ss<<doodNumber(d[5]+5);\n  return ss.str();\n}\n\n/***********************************************/\n\nstd::string Doodson::name() const\n{\n  std::string c = code();\n  for(UInt i=0; doodsonName[i].name!=nullptr; i++)\n    if(c == doodsonName[i].code)\n      return doodsonName[i].name;\n  return code();\n}\n\n/***********************************************/\n\nDouble Doodson::thetaf(const Time &timeGPS) const\n{\n  Vector a = arguments(timeGPS);\n  return a(0)*d[0]+a(1)*d[1]+a(2)*d[2]+a(3)*d[3]+a(4)*d[4]+a(5)*d[5];\n}\n\n/***********************************************/\n\nDouble Doodson::frequency(Time timeGPS) const\n{\n  Vector f(6);\n  Double t = timeGPS2JC(timeGPS)/10.; // centuries\n\n  f(0) = (127037328.88553056 + (2* 0.17696111 + (3*-0.00183140 + 4* 0.00008824*t)*t)*t) * DEG2RAD;\n  f(1) = (  4812678.81195750 + (2*-0.14663889 + (3* 0.00185140 + 4*-0.00015355*t)*t)*t) * DEG2RAD;\n  f(2) = (   360007.69748806 + (2* 0.03032222 + (3* 0.00002000 + 4*-0.00006532*t)*t)*t) * DEG2RAD;\n  f(3) = (    40690.13635250 + (2*-1.03217222 + (3*-0.01249168 + 4* 0.00052655*t)*t)*t) * DEG2RAD;\n  f(4) = (    19341.36261972 + (2*-0.20756111 + (3*-0.00213942 + 4* 0.00016501*t)*t)*t) * DEG2RAD;\n  f(5) = (       17.19457667 + (2* 0.04568889 + (3*-0.00001776 + 4*-0.00003323*t)*t)*t) * DEG2RAD;\n\n  return (f(0)*d[0]+f(1)*d[1]+f(2)*d[2]+f(3)*d[3]+f(4)*d[4]+f(5)*d[5])/365250.;\n}\n\n/***********************************************/\n\nVector Doodson::arguments(const Time &timeGPS)\n{\n  Vector a(6);\n  const Vector f = Planets::fundamentals(timeGPS);\n  a(1) = f(2)+f(4);\n  a(2) = f(2)+f(4)-f(3);\n  a(3) = f(2)+f(4)-f(0);\n  a(4) = -f(4);\n  a(5) = f(2)+f(4)-f(3)-f(1);\n  a(0) = Planets::gmst(timeGPS2UTC(timeGPS)) + PI - a(1);\n  return a;\n}\n\n/***********************************************/\n\nMatrix Doodson::matrix(const std::vector<Doodson> &doodson)\n{\n  Matrix A(doodson.size(),6);\n  for(UInt i=0; i<doodson.size(); i++)\n  {\n    A(i,0) = doodson.at(i).d[0];\n    A(i,1) = doodson.at(i).d[1];\n    A(i,2) = doodson.at(i).d[2];\n    A(i,3) = doodson.at(i).d[3];\n    A(i,4) = doodson.at(i).d[4];\n    A(i,5) = doodson.at(i).d[5];\n  }\n  return A;\n}\n\n/***********************************************/\n\nMatrix Doodson::nodeCorr(const std::vector<Doodson> &doodson, const Time &timeGPS, const UInt &nCorr)\n{\n  try\n  {\n    Vector f = arguments(timeGPS);    //Doodson arguments\n    Matrix fu(doodson.size(),2);      //nodal factor and phase corrections\n\n    for(UInt i=0; i<6;i++) // bring f between 0-2PI\n    {\n      f[i] = fmod(f[i], 2.*PI);\n      if(f[i] < 0)\n        f[i] += 2.*PI;\n    };\n\n    Double N = -f(4)+2.0*PI;  // longitude of moon's ascending node in the range of 0 to +2pi\n    Double p = f(3);          // longitude of moon's perigee\n\n    //according to IHO\n    if (nCorr==1)\n    {\n      for(UInt i=0; i<doodson.size(); i++)\n      {\n        //compute nodal factors and phases for constituents given in 'doodson'\n        if (doodson.at(i).code() == \"065.455\" || doodson.at(i).code() == \"085.455\") //Mm or Mtm\n        {\n          fu(i,0) = 1.0 - 0.1311*cos(N) + 0.0538*cos(2.0*p) + 0.0505*cos(2.0*p-N); //factor\n          fu(i,1) = 0;                                                       //phase\n        }\n        else if (doodson.at(i).code() == \"075.555\") //Mf\n        {\n          fu(i,0) = 1.084 + 0.415*cos(N) + 0.039*cos(2.0*N);\n          fu(i,1) = (-23.7*sin(N) + 2.7*sin(2*N) - 0.4*sin(3.0*N))*DEG2RAD;\n        }\n        else if (doodson.at(i).code() == \"093.555\") //MSQ\n        {\n          fu(i,0) = 1.0007 - 0.0373*cos(N) + 0.0002*cos(2.0*N);\n          fu(i,1) = (2.14*sin(N))*DEG2RAD;\n        }\n        else if (doodson.at(i).code() == \"145.555\" || doodson.at(i).code() == \"135.655\" ) //O1 or Q1\n        {\n          fu(i,0) = 1.0176 + 0.1871*cos(N) - 0.0147*cos(2*N);\n          fu(i,1) = (10.80*sin(N) - 1.34*sin(2.0*N) + 0.19*sin(3.0*N))*DEG2RAD;\n        }\n        else if (doodson.at(i).code() == \"165.555\")  //K1\n        {\n          fu(i,0) = 1.0060 + 0.1150*cos(N) - 0.0088*cos(2.0*N) + 0.0006*cos(3.0*N);\n          fu(i,1) = (-8.86*sin(N)+0.68*sin(2.0*N)-0.07*sin(3.0*N))*DEG2RAD;\n        }\n        else if (doodson.at(i).code() == \"255.555\" || doodson.at(i).code() == \"245.655\" || doodson.at(i).code() == \"235.755\") //M2 or N2 or 2N2\n        {\n          fu(i,0) = 1.0007 - 0.0373*cos(N) + 0.0002*cos(2.0*N);\n          fu(i,1) = (-2.14*sin(N))*DEG2RAD;\n        }\n        else if (doodson.at(i).code() == \"275.555\") //K2\n        {\n          fu(i,0) = 1.0246 + 0.2863*cos(N) + 0.0083*cos(2.0*N) - 0.0015*cos(3.0*N);\n          fu(i,1) = (-17.74*sin(N) + 0.68*sin(2.0*N) - 0.04*sin(3.0*N))*DEG2RAD;\n        }\n        else if (doodson.at(i).code() == \"455.555\") //M4 (=2 x M2)\n        {\n          fu(i,0) = pow(1.0007 - 0.0373*cos(N) + 0.0002*cos(2.0*N),2);\n          fu(i,1) = 2.0*(-2.14*sin(N))*DEG2RAD;\n        }\n        else  //for all other constituents\n        {\n          fu(i,0) = 1.0;\n          fu(i,1) = 0.0;\n        }\n      } //end for\n\n      return fu;\n    } // if(nCorr==1)\n\n    // according to Schureman\n    if(nCorr==2)\n    {\n      Double i         = (5.0 + 8.0/60.0 + 43.3546/3600.0)*DEG2RAD;              // inclination of moon's orbit to ecliptic\n      Double omega     = (23.0 + 27.0/60.0 + 8.26/3600.0)*DEG2RAD;               // obliquity of the ecliptic at epoch 1/1/1900\n      Double I         = acos(cos(omega)*cos(i) - sin(omega)*sin(i)*cos(N));     // I... inclination of moon's orbit to celestial equator\n      Double nu        = asin(sin(i) * sin(N) / sin(I));                         // nu\n      Double nu_s      = atan(sin(2.0*I)*sin(nu)/(sin(2*I)*cos(nu)+0.3347));     // nu', Schureman f 224\n      Double nu_2s     = atan(pow(sin(I),2)*sin(2.0*nu)/(pow(sin(I),2)*cos(2.0*nu)+0.0727))/2.0; // nü'', Schureman f 232\n      Double omega_cap = acos(cos(N)*cos(nu)+sin(N)*sin(nu)*cos(omega));         // capital omega\n      Double xi = 0.0;\n      if(N>PI)\n        xi = N + omega_cap -2.0*PI;\n      else\n        xi = N - omega_cap;\n\n      for(UInt k=0; k<doodson.size(); k++)\n      {\n        //compute nodal factors and phases for constituents given in 'doodson'\n        if (doodson.at(k).code() == \"065.455\" || doodson.at(k).code() == \"085.455\") //Mm or Mtm\n        {\n          fu(k,0) = (2.0/3.0 - pow(sin(I),2))/0.5021; //factor\n          fu(k,1) = 0.0;                                                       //phase\n        }\n        else if (doodson.at(k).code() == \"075.555\") //Mf\n        {\n          fu(k,0) = pow(sin(I),2)/0.1578;\n          fu(k,1) = -2.0*xi;\n        }\n        else if (doodson.at(k).code() == \"093.555\") //MSQ\n        {\n          fu(k,0) = pow(sin(I),2)/0.1578;\n          fu(k,1) = -2.0*xi;\n        }\n        else if (doodson.at(k).code() == \"145.555\" || doodson.at(k).code() == \"135.655\" ) //O1 or Q1\n        {\n          fu(k,0) = sin(I)*pow(cos(I/2.0),2)/0.38;\n          fu(k,1) = 2.0*xi-nu;\n        }\n        else if (doodson.at(k).code() == \"165.555\")  //K1\n        {\n          fu(k,0) = pow(0.8965*pow(sin(2.0*I),2)+0.6001*sin(2.0*I)*cos(nu)+0.1006,0.5);\n          fu(k,1) = -nu_s;\n        }\n        else if (doodson.at(k).code() == \"255.555\" || doodson.at(k).code() == \"245.655\" || doodson.at(k).code() == \"235.755\") //M2 or N2 or 2N2\n        {\n          fu(k,0) = pow(cos(I/2.0),4)/0.9154;\n          fu(k,1) = 2.0*xi-2.0*nu;\n        }\n        else if (doodson.at(k).code() == \"275.555\") //K2\n        {\n          fu(k,0) = pow(19.0444*pow(sin(I),4)+2.7702*pow(sin(I),2)*cos(2.0*nu)+0.0981,0.5);\n          fu(k,1) = -2.0*nu_2s;\n        }\n        else if (doodson.at(k).code() == \"455.555\") //M4 (=2 x M2)\n        {\n          fu(k,0) = pow(cos(I/2.0),4)/0.9154 * pow(cos(I/2.0),4)/0.9154;\n          fu(k,1) = 2.0*(2.0*xi-2.0*nu);\n        }\n        else  // for all other constituents\n        {\n          fu(k,0)=1.0;\n          fu(k,1)=0.0;\n        }\n      } //end for\n\n      return fu;\n    } // if(nCorr==2)\n\n    // no nodal corrections\n    for(UInt i=0; i<doodson.size(); i++)\n    {\n      fu(i,0)=1.0;\n      fu(i,1)=0.0;\n    }\n    return fu;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/doodson.h",
    "content": "/***********************************************/\n/**\n* @file doodson.h\n*\n* @brief Doodson arguments and multipliers.\n*\n* @author Torsten Mayer-Guerr\n* @author Daniel Rieser\n* @date 2005-07-15\n*/\n/***********************************************/\n\n\n#ifndef __GROOPS_DOODSON__\n#define __GROOPS_DOODSON__\n\n// Latex documentation\n#ifdef DOCSTRING_Doodson\nstatic const char *docstringDoodson = R\"(\n\\section{Doodson}\\label{doodson}\nThis is a string which describes a tidal frequency either coded as Doodson number\nor using Darwin´s name, e.g. \\verb|255.555| or \\verb|M2|.\n\nThe following names are defined:\n\\begin{itemize}\n\\item \\verb|055.565|: \\verb|om1|  \\item \\verb|055.575|: \\verb|om2|     \\item \\verb|056.554|: \\verb|sa|\n\\item \\verb|056.555|: \\verb|sa|   \\item \\verb|057.555|: \\verb|ssa|     \\item \\verb|058.554|: \\verb|sta|\n\\item \\verb|063.655|: \\verb|msm|  \\item \\verb|065.455|: \\verb|mm|      \\item \\verb|073.555|: \\verb|msf|\n\\item \\verb|075.555|: \\verb|mf|   \\item \\verb|083.655|: \\verb|mstm|    \\item \\verb|085.455|: \\verb|mtm|\n\\item \\verb|093.555|: \\verb|msq|  \\item \\verb|093.555|: \\verb|msqm|    \\item \\verb|125.755|: \\verb|2q1|\n\\item \\verb|127.555|: \\verb|sig1| \\item \\verb|127.555|: \\verb|sigma1|  \\item \\verb|135.655|: \\verb|q1|\n\\item \\verb|137.455|: \\verb|ro1|  \\item \\verb|137.455|: \\verb|rho1|    \\item \\verb|145.555|: \\verb|o1|\n\\item \\verb|147.555|: \\verb|tau1| \\item \\verb|155.655|: \\verb|m1|      \\item \\verb|157.455|: \\verb|chi1|\n\\item \\verb|162.556|: \\verb|pi1|  \\item \\verb|163.555|: \\verb|p1|      \\item \\verb|164.555|: \\verb|s1|\n\\item \\verb|165.555|: \\verb|k1|   \\item \\verb|166.554|: \\verb|psi1|    \\item \\verb|167.555|: \\verb|fi1|\n\\item \\verb|167.555|: \\verb|phi1| \\item \\verb|173.655|: \\verb|the1|    \\item \\verb|173.655|: \\verb|theta1|\n\\item \\verb|175.455|: \\verb|j1|   \\item \\verb|183.555|: \\verb|so1|     \\item \\verb|185.555|: \\verb|oo1|\n\\item \\verb|195.455|: \\verb|v1|   \\item \\verb|225.855|: \\verb|3n2|     \\item \\verb|227.655|: \\verb|eps2|\n\\item \\verb|235.755|: \\verb|2n2|  \\item \\verb|237.555|: \\verb|mu2|     \\item \\verb|237.555|: \\verb|mi2|\n\\item \\verb|245.655|: \\verb|n2|   \\item \\verb|247.455|: \\verb|nu2|     \\item \\verb|247.455|: \\verb|ni2|\n\\item \\verb|253.755|: \\verb|gam2| \\item \\verb|254.556|: \\verb|alf2|    \\item \\verb|255.555|: \\verb|m2|\n\\item \\verb|256.554|: \\verb|bet2| \\item \\verb|257.555|: \\verb|dlt2|    \\item \\verb|263.655|: \\verb|la2|\n\\item \\verb|263.655|: \\verb|lmb2| \\item \\verb|263.655|: \\verb|lambda2| \\item \\verb|265.455|: \\verb|l2|\n\\item \\verb|271.557|: \\verb|2t2|  \\item \\verb|272.556|: \\verb|t2|      \\item \\verb|273.555|: \\verb|s2|\n\\item \\verb|274.554|: \\verb|r2|   \\item \\verb|275.555|: \\verb|k2|      \\item \\verb|283.655|: \\verb|ksi2|\n\\item \\verb|285.455|: \\verb|eta2| \\item \\verb|355.555|: \\verb|m3|      \\item \\verb|381.555|: \\verb|t3|\n\\item \\verb|382.555|: \\verb|s3|   \\item \\verb|383.555|: \\verb|r3|      \\item \\verb|435.755|: \\verb|n4|\n\\item \\verb|445.655|: \\verb|mn4|  \\item \\verb|455.555|: \\verb|m4|      \\item \\verb|473.555|: \\verb|ms4|\n\\item \\verb|491.555|: \\verb|s4|   \\item \\verb|655.555|: \\verb|m6|      \\item \\verb|855.555|: \\verb|m8|\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/matrix.h\"\n#include \"base/time.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Doodson arguments.\n* @ingroup base */\nclass Doodson\n{\npublic:\n  /** @brief Multipliers. */\n  std::array<Int, 6> d;\n\n  /** @brief Default constructor. */\n  Doodson() {d[0]=d[1]=d[2]=d[3]=d[4]=d[5]=0;}\n\n  /** @brief Constructor with std::vector of multipliers. */\n  explicit Doodson(const std::vector<Int> &v);\n\n  /** @brief Constructor from Doodsoncode or Name.\n  * You can give e.g. \"255.555\" or \"M2\". */\n  explicit Doodson(const std::string &str);\n\n  /** @brief Doodsoncode.\n  * Coded by n1(n2+5)(n3+5).(n4+5)(n5+5)(n6+5).\n  * Example: 255.555 for M2 Tide. */\n  std::string code() const;\n\n  /** @brief Name of tide.\n  * If tide has no name the code is given instead.\n  * Example: M2 for 255.555. */\n  std::string name() const;\n\n  /** @brief Angle of this constituent at time @a timeGPS. */\n  Double thetaf(const Time &timeGPS) const;\n\n  /** @brief Frequency of this constituent.\n  * In rad/day. calling without given time J2000 is assumed. */\n  Double frequency(Time timeGPS = mjd2time(J2000)) const;\n\n  /** @brief Doodson arguments at time @a timeGPS. */\n  static Vector arguments(const Time &timeGPS);\n\n  /** @brief matrix of doodson multipliers.\n  * To get a vector of angles of the constituents at time @a timeGPS call\n  * @code\n  * Matrix A      = Doodson::matrix(doodsonList);\n  * Vector thetaf = A * Doodson::arguments(timeGPS);\n  * @endcode */\n  static Matrix matrix(const std::vector<Doodson> &doodson);\n\n  /** @brief matrix with nodal corrections for constituents in &doodson at time @a timeGPS.\n  * Following the specifications of IHO, HSSC Tidal and Water Level Working Group.\n  * Corrections are implemented for Mm,Mtm,Mf,MSq,O1,Q1,K1,K2,M2,N2,2N2,M4.\n  * For all others factor = 1 and phase correction = 0.\n  *\n  * Return of fu with:\n  * fu(:,0) = node factors.\n  * fu(:,1) = phase corrections (in radians). */\n  static Matrix nodeCorr(const std::vector<Doodson> &doodson, const Time &timeGPS, const UInt &nCorr);\n\n  /** @brief Implementation of Comparable (comparison of frequency). */\n  Bool operator== (const Doodson &dood) const {return d == dood.d;}\n  /** @brief Implementation of Comparable (comparison of frequency). */\n  Bool operator!= (const Doodson &dood) const {return d != dood.d;}\n  /** @brief Implementation of Comparable (comparison of frequency). */\n  Bool operator<  (const Doodson &dood) const {return frequency() <  dood.frequency();}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_DOODSON__ */\n"
  },
  {
    "path": "source/base/ellipsoid.cpp",
    "content": "/***********************************************/\n/**\n* @file ellipsoid.cpp\n*\n* @brief Transformation of ellipsoidial coordinates.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-25\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/ellipsoid.h\"\n\n/***********************************************/\n\nvoid Ellipsoid::operator()(const Vector3d &point, Angle &L, Angle &B, Double &h) const\n{\n  if(point.quadsum() == 0.)\n    throw(Exception(\"In Ellipsoid:\\n0 Vector\"));\n\n  const Double e2  = sqrt((_a/_b-1)*(_a/_b+1));\n  const Double z   = point.z();\n  const Double rho = std::sqrt(point.x()*point.x()+point.y()*point.y());\n\n  // start values\n  L = (rho != 0.) ? point.lambda() : Angle(0);\n  B = Angle(std::atan2(z*(1+e2*e2), rho));\n  h = 0.0;\n\n  // Iteration\n  Double h1, B1;\n  UInt   count = 0;\n  do\n  {\n    h1 = h;\n    B1 = B;\n    const Double N = _a*(_a/(_b*std::sqrt(1+std::pow(e2*std::cos(B), 2))));\n    h = (std::fabs(B) < (60*DEG2RAD)) ? (rho/std::cos(B) - N) : (z/std::sin(B) - N/(1+e2*e2));\n    B = Angle(std::atan2(z*(1+e2*e2), rho*(1+e2*e2*h/(N+h))));\n  }\n  while(((std::fabs(h-h1) > 1e-6) || (std::fabs(B-B1) > 1e-10)) && (count++ < 1000));\n}\n\n/***********************************************/\n\nconst Vector3d Ellipsoid::operator()(Angle L, Angle B, Double h) const\n{\n  Double e2 = std::sqrt((_a/_b-1)*(_a/_b+1));\n  Double N  = _a*(_a/(_b*std::sqrt(1+std::pow(e2*std::cos(B), 2))));\n\n  return Vector3d((N+h) * std::cos(B) * std::cos(L),\n                  (N+h) * std::cos(B) * std::sin(L),\n                  (N/(1+e2*e2)+h)* std::sin(B));\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/ellipsoid.h",
    "content": "/***********************************************/\n/**\n* @file ellipsoid.h\n*\n* @brief Transformation of ellipsoidial coordinates.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ELLIPSOID__\n#define __GROOPS_ELLIPSOID__\n\n#include \"base/importStd.h\"\n#include \"base/angle.h\"\n#include \"base/vector3d.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Transformation of ellipsoidial coordinates.\n* @ingroup vector3dGroup */\nclass Ellipsoid\n{\n  Double _a,_b;\n\npublic:\n  /** @brief Ellipsoid from semi major axis and inverse flatenning.\n  * if f=0, a sphere is assumed. */\n  Ellipsoid(Double a=DEFAULT_GRS80_a, Double f=DEFAULT_GRS80_f) : _a(a), _b((f != 0.) ? (a*(1-1/f)) : a) {}\n\n  /** @brief Computes ellipsoidal coordinates from @a point.\n  * @param point point\n  * @param[out] L longitude (-PI,PI]\n  * @param[out] B latitude [-PI,PI]\n  * @param[out] h height [m]\n  */\n  void operator()(const Vector3d &point, Angle &L, Angle &B, Double &h) const;\n\n  /** @brief Transformation ellipsoidal coordinates in @a Vector3d.\n  * @param L longitude (-PI,PI]\n  * @param B latitude [-PI/2,PI/2]\n  * @param h height [m]\n  */\n  const Vector3d operator()(Angle L, Angle B, Double h) const;\n\n  /// Semi major axis.\n  Double a() const {return _a;}\n\n  /// Semi minor axis.\n  Double b() const {return _b;}\n\n  /// Numerical  excentricity.\n  Double e() const {return sqrt(_a*_a-_b*_b)/_a;}\n\n  /// Flattening.\n  Double f() const {return (_a-_b)/_a;}\n};\n\n/*************************************************/\n\n#endif\n"
  },
  {
    "path": "source/base/equinoctial.cpp",
    "content": "/***********************************************/\n/**\n* @file equinoctial.cpp\n*\n* @brief Equinoctial elements and orbits.\n*\n* @author Matthias Ellmer\n* @date 2015-06-10\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/vector3d.h\"\n#include \"base/time.h\"\n#include \"base/kepler.h\"\n#include \"base/equinoctial.h\"\n\n/***********************************************/\n\nEquinoctial::Equinoctial() :\n  GM(DEFAULT_GM),\n  a(0),\n  h(0),\n  k(0),\n  p(0),\n  q(0),\n  l0(0),\n  tau()\n{\n}\n\n/***********************************************/\n\nEquinoctial::Equinoctial(Double a, Double h, Double k, Double p, Double q, Double l0, const Time &tau, Double GM) :\n  GM(GM),\n  a(a),\n  h(h),\n  k(k),\n  p(p),\n  q(q),\n  l0(l0),\n  tau(tau)\n{\n}\n\n/***********************************************/\n\nEquinoctial::Equinoctial(const Kepler &kepler) :\n  GM(kepler.GM),\n  a(kepler.a),\n  h(kepler.e*std::sin(kepler.omega + kepler.Omega)),\n  k(kepler.e*std::cos(kepler.omega + kepler.Omega)),\n  p(tan(kepler.i / 2) *std::sin(kepler.Omega)),\n  q(tan(kepler.i / 2) *std::cos(kepler.Omega)),\n  l0(kepler.meanAnomaly(kepler.tau) + kepler.omega + kepler.Omega),\n  tau(kepler.tau)\n{\n}\n\n/***********************************************/\n\nEquinoctial::Equinoctial(const Time &epoch, const Vector3d &position, const Vector3d &velocity, Double _GM) :\n  Equinoctial(epoch, epoch, position, velocity, _GM)\n{\n}\n\n/***********************************************/\n\nEquinoctial::Equinoctial(const Time &epoch, const Time &time, const Vector3d &position, const Vector3d &velocity, Double _GM) :\n  GM(_GM),\n  tau(epoch)\n{\n  try\n  {\n    // Semi-major axis\n    a = 1 / (2 / position.norm() - velocity.norm() * velocity.norm() / GM);\n\n    // First orthonormal basis vector in equinoctial reference frame\n    Vector3d f, g, w;\n    w = crossProduct(position, velocity) * (1 / crossProduct(position, velocity).norm());\n\n    // Elements p and q\n    p =  w.x() / (1 + w.z());\n    q = -w.y() / (1 + w.z());\n\n    // Remaining basis vectors using p and q\n    orthonormals(f, g);\n\n    // Ecccentricity vector\n    Vector3d e_ = -position * (1 / position.norm()) + crossProduct(velocity, crossProduct(position, velocity)) * (1 / GM);\n\n    // Elements h and k\n    h = inner(e_, g);\n    k = inner(e_, f);\n\n    // Position in equinoctial frame\n    Double X = inner(position, f);\n    Double Y = inner(position, g);\n\n    // Eccentric longitude\n    Double b = 1 / (1 + std::sqrt(1 - h * h - k * k));\n    Double sinF = h + ((1 - h * h * b) * Y - h * k * b * X) / (a * std::sqrt(1 - h * h - k * k));\n    Double cosF = k + ((1 - k * k * b) * X - h * k * b * Y) / (a * std::sqrt(1 - h * h - k * k));\n    Double    F = atan2(sinF, cosF);\n\n    // Mean longitude\n    LongDouble lambda = F + h * std::cos(F) - k * std::sin(F);\n\n    // The easy method with no LongDoubles would be\n    //   l0 = lambda - n * (time - epoch).seconds();\n    // See Equinoctial::meanLongitude() for reasoning.\n\n    // Refrence mean longitude at epoch\n    LongDouble thisGM = GM;\n    LongDouble a3 = std::pow(a,3);\n    LongDouble n = std::sqrt(thisGM / a3);\n    LongDouble l0_Int = (time.mjdInt()-epoch.mjdInt()) * (24*60*60);\n    LongDouble l0_Mod = (time.mjdMod()-epoch.mjdMod()) * (24*60*60);\n\n    l0 = lambda - n * l0_Int - n * l0_Mod;\n\n    // correct domain\n    const LongDouble lpi = 3.14159265358979323846264338328L;\n    l0 = std::fmod(l0, 2*lpi);\n    if (l0 < 0)\n      l0 += 2 * lpi;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nLongDouble Equinoctial::meanLongitude(const Time &time) const\n{\n  try\n  {\n    // See comment in constructor. Again, this would be the easy method:\n    //     LongDouble lambda = l0 + (time - tau).seconds() * std::sqrt(GM / (a * a * a));\n    //     Double lambda = l0 + ((time - tau).seconds()/a) * std::sqrt(GM / a );\n    LongDouble thisGM = GM;\n    LongDouble a3 = std::pow(a,3);\n    LongDouble n = std::sqrt(thisGM / a3);\n    LongDouble l0_Int = (time.mjdInt()-tau.mjdInt()) * (24*60*60);\n    LongDouble l0_Mod = (time.mjdMod()-tau.mjdMod()) * (24*60*60);\n\n    LongDouble lambda = l0 + n * l0_Int + n * l0_Mod;\n\n    const LongDouble lpi = 3.14159265358979323846264338328L;\n    lambda = std::fmod(lambda, 2*lpi);\n    if (lambda < 0)\n      lambda += 2 * lpi;\n\n    return lambda;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Equinoctial::eccentricLongitude(const Time &time) const\n{\n  try\n  {\n    LongDouble lambda = meanLongitude(time);\n    LongDouble F = lambda;\n    LongDouble F_old;\n    LongDouble eps = 1e-18;\n\n    // Newton-Raphson method\n    UInt iter = 0;\n    do\n    {\n      F_old = F;\n      F = F - (F - k * std::sin(F) + h * std::cos(F) - lambda) / (1 - k * std::cos(F) - h * std::sin(F));\n    }\n    while ((std::fabs(F - F_old) > eps) && (iter++ < 100));\n\n\n    return static_cast<Double>(F);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Equinoctial::trueLongitude(const Time &time) const\n{\n  try\n  {\n    Double beta = 1 / (1 + std::sqrt(1 - h * h - k * k)); // Supplementary quantity\n    Double F    = eccentricLongitude(time);\n    Double sinL = ((1 - k * k * beta) * std::sin(F) + h * k * beta * std::cos(F) - h) / (1 - h * std::sin(F) - k * std::cos(F));\n    Double cosL = ((1 - h * h * beta) * std::cos(F) + h * k * beta * std::sin(F) - k) / (1 - h * std::sin(F) - k * std::cos(F));\n\n    return atan2(sinL, cosL);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Equinoctial::meanAnomaly(const Time &time) const\n{\n  try\n  {\n    Double sinXi = h / std::sqrt(h * h + k * k);\n    Double cosXi = k / std::sqrt(h * h + k * k);\n    return static_cast<Double>(meanLongitude(time)) - std::atan2(sinXi, cosXi);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Equinoctial::orthonormals(Vector3d &f, Vector3d &g) const\n{\n  try\n  {\n    Vector3d w;\n    orthonormals(f, g, w);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nvoid Equinoctial::orthonormals(Vector3d &f, Vector3d &g, Vector3d &w) const\n{\n  try\n  {\n    Double alpha = 1 / (1 + p * p + q * q);\n    f = alpha * Vector3d(1 - p * p + q * q, 2 * p * q, -2 * p);\n    g = alpha * Vector3d(2 * p * q, 1 + p * p - q * q, 2 * q);\n    w = alpha * Vector3d(2 * p, -2 * q, 1 - p * p - q * q);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Equinoctial::stateTransitionMatrix(const Time &time)\n{\n  try\n  {\n    // Prerequisites\n\n    Vector3d f, g, w;\n    orthonormals(f, g, w);\n\n    Vector3d inPlanePosition, inPlaneVelocity;\n    inPlaneOrbit(time, inPlanePosition, inPlaneVelocity);\n    Double X  = inPlanePosition.x();\n    Double Y  = inPlanePosition.y();\n    Double XD = inPlaneVelocity.x();\n    Double YD = inPlaneVelocity.y();\n\n    Vector3d position, velocity;\n    orbit(time, position, velocity);\n\n    // Supplementary quantities\n    Double A = std::sqrt(GM * a);\n    Double B = std::sqrt(1 - h * h - k * k);\n    Double C = 1 + p * p + q * q;\n\n    Double F =  eccentricLongitude(time);\n\n    Double n = std::sqrt(GM / (a * a * a));\n    Double r = a * (1 - h * std::sin(F) - k * std::cos(F)); //inPlanePosition.norm();\n\n    // Partial derivatives\n    Double dXdh = -k * XD / (n * (1. + B)) + a * Y * YD / (A * B);\n    Double dYdh = -k * YD / (n * (1. + B)) - a * X * YD / (A * B) - a;\n    Double dXdk =  h * XD / (n * (1. + B)) + a * Y * XD / (A * B) - a;\n    Double dYdk =  h * YD / (n * (1. + B)) - a * X * XD / (A * B);\n\n    Double dXDdh =  a * YD * YD / (A * B) + (A / (r * r * r)) * (a * k * X / (1 + B) - Y * Y / B);\n    Double dYDdh = -a * XD * YD / (A * B) + (A / (r * r * r)) * (a * k * Y / (1 + B) + X * Y / B);\n    Double dXDdk =  a * XD * YD / (A * B) - (A / (r * r * r)) * (a * h * X / (1 + B) + X * Y / B);\n    Double dYDdk = -a * XD * XD / (A * B) - (A / (r * r * r)) * (a * h * Y / (1 + B) - X * X / B);\n\n    // State transition matrix\n    // Chapter 2.1.6 -- Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” DTIC Document.\n    // Broucke, R. A., and P. J. Cefola. 1972. “On the Equinoctial Orbit Elements.” Celestial Mechanics 5 (3): 303–10. doi:10.1007/BF01228432.\n    // TAKE CARE as the derivatives dr/da and drd/da are wrong in Danielson. Check Broucke for these.\n\n    // Order is dr/da dr/dh dr/dk dr/dp dr/dq dr/dlambda\n    // Position derivatives\n    Matrix Phi(6, 6);\n\n    {\n      // dr/da\n      Vector3d tmp = (1./a) * (position - velocity * 1.5 * (time -tau).seconds());\n      Phi(0, 0) = tmp.x();\n      Phi(1, 0) = tmp.y();\n      Phi(2, 0) = tmp.z();\n    }\n    {\n      // dr/dh\n      Vector3d tmp = dXdh * f + dYdh * g;\n      Phi(0, 1) = tmp.x();\n      Phi(1, 1) = tmp.y();\n      Phi(2, 1) = tmp.z();\n    }\n    {\n      // dr/dk\n      Vector3d tmp = dXdk * f + dYdk * g;\n      Phi(0, 2) = tmp.x();\n      Phi(1, 2) = tmp.y();\n      Phi(2, 2) = tmp.z();\n    }\n    {\n      // dr/dp\n      Vector3d tmp = 2.* (q * (Y * f - X * g) - X * w) / C;\n      Phi(0, 3) = tmp.x();\n      Phi(1, 3) = tmp.y();\n      Phi(2, 3) = tmp.z();\n    }\n    {\n      // dr/dq\n      Vector3d tmp = 2.* (p * (X * g - Y * f) + Y * w) / C;\n      Phi(0, 4) = tmp.x();\n      Phi(1, 4) = tmp.y();\n      Phi(2, 4) = tmp.z();\n    }\n    {\n      // dr/dlambda\n      Vector3d tmp = velocity * (1./n);\n      Phi(0, 5) = tmp.x();\n      Phi(1, 5) = tmp.y();\n      Phi(2, 5) = tmp.z();\n    }\n\n    // Velocity derivatives\n    {\n      // drd/da\n      Vector3d tmp = - (1./(2*a)) * (velocity - position * 3 * GM * (time -tau).seconds() / (r*r*r) );\n      Phi(3, 0) = tmp.x();\n      Phi(4, 0) = tmp.y();\n      Phi(5, 0) = tmp.z();\n    }\n    {\n      // drd/dh\n      Vector3d tmp = dXDdh * f + dYDdh * g;\n      Phi(3, 1) = tmp.x();\n      Phi(4, 1) = tmp.y();\n      Phi(5, 1) = tmp.z();\n    }\n    {\n      // drd/dk\n      Vector3d tmp = dXDdk * f + dYDdk * g;\n      Phi(3, 2) = tmp.x();\n      Phi(4, 2) = tmp.y();\n      Phi(5, 2) = tmp.z();\n    }\n    {\n      // drd/dp\n      Vector3d tmp = 2.* (q * (YD * f - XD * g) - XD * w) / C;\n      Phi(3, 3) = tmp.x();\n      Phi(4, 3) = tmp.y();\n      Phi(5, 3) = tmp.z();\n    }\n    {\n      // drd/dq\n      Vector3d tmp = 2.* (p * (XD * g - YD * f) + YD * w) / C;\n      Phi(3, 4) = tmp.x();\n      Phi(4, 4) = tmp.y();\n      Phi(5, 4) = tmp.z();\n    }\n    {\n      // drd/dlambda\n      Vector3d tmp = - n * std::pow(a / r, 3) * position;\n      Phi(3, 5) = tmp.x();\n      Phi(4, 5) = tmp.y();\n      Phi(5, 5) = tmp.z();\n    }\n\n    return Phi;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nconst Vector3d Equinoctial::position(const Time &time) const\n{\n  try\n  {\n    Vector3d position, velocity;\n    orbit(time, position, velocity);\n    return position;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Equinoctial::orbit(const Time &time, Vector3d &position, Vector3d &velocity) const\n{\n  try\n  {\n    Vector3d acceleration;\n    orbit(time, position, velocity, acceleration);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Equinoctial::orbit(const Time &time, Vector3d &position, Vector3d &velocity, Vector3d &acceleration) const\n{\n  try\n  {\n    Vector3d inPlanePosition, inPlaneVelocity;\n    inPlaneOrbit(time, inPlanePosition, inPlaneVelocity);\n\n    Vector3d of, og;\n    orthonormals(of, og);\n\n    position = inPlanePosition.x() * of + inPlanePosition.y() * og;\n    velocity = inPlaneVelocity.x() * of + inPlaneVelocity.y() * og;\n    acceleration = -GM / (std::pow(position.norm(), 3)) * position;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Equinoctial::inPlaneOrbit(const Time &time, Vector3d &position, Vector3d &velocity) const\n{\n  try\n  {\n    Vector3d acceleration;\n    inPlaneOrbit(time, position, velocity, acceleration);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Equinoctial::inPlaneOrbit(const Time &time, Vector3d &position, Vector3d &velocity, Vector3d &acceleration) const\n{\n  try\n  {\n    Double F = eccentricLongitude(time);\n\n    Double beta = 1 / (1 + std::sqrt(1 - h * h - k * k)); // Supplementary quantity\n    Double r    = a * (1 - h * std::sin(F) - k * std::cos(F)); // Radius\n\n    // Coordinates and velocities in orbital plane\n    position.x() = a * ((1 - h * h * beta) * std::cos(F) + h * k * beta * std::sin(F) - k);\n    position.y() = a * ((1 - k * k * beta) * std::sin(F) + h * k * beta * std::cos(F) - h);\n    position.z() = 0;\n\n    velocity.x() = std::sqrt(GM * a) / r * ( h * k * beta * std::cos(F) - (1 - h * h * beta) * std::sin(F));\n    velocity.y() = std::sqrt(GM * a) / r * (-h * k * beta * std::sin(F) + (1 - k * k * beta) * std::cos(F));\n    velocity.z() = 0;\n\n    acceleration = -GM / (r * r * r) * position;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/equinoctial.h",
    "content": "/***********************************************/\n/**\n* @file equinoctial.h\n*\n* @brief Equinoctial elements and orbits.\n*\n* @author Matthias Ellmer\n* @date 2015-06-10\n*\n* @see Broucke, R. A., and P. J. Cefola. 1972. “On the Equinoctial Orbit Elements.” Celestial Mechanics 5 (3): 303–10. doi:10.1007/BF01228432.\n* @see Broucke, R. A. 1970. “On the Matrizant of the Two-Body Problem.” Astronomy and Astrophysics 6 (June): 173–82.\n* @see Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits. Springer-Verlag Berlin Heidelberg New York. Chapter 2.2.5, pp. 30-32\n* @see Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” DTIC Document.\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EQUINOCTIAL__\n#define __GROOPS_EQUINOCTIAL__\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n#include \"base/vector3d.h\"\n\nclass Kepler;\n\n/***** CLASS ***********************************/\n\n/** @brief Equinoctial orbits.\n* @ingroup base */\nclass Equinoctial\n{\npublic:\n  Double GM;      //!< Specific gravitational constant\n  Double a;       //!< a                     | Semi-major axis\n  Double h;       //!< e sin(omega + Omega)\n  Double k;       //!< e cos(omega + Omega)\n  Double p;       //!< tan(i/2) + sin(Omega)\n  Double q;       //!< tan(i/2) + cos(Omega)\n  LongDouble l0;  //!< M0 + omega + Omega    | Mean longitude at t = tau\n  Time   tau;     //!<                       | Time of perigee\n\n  /// Default constructor.\n  Equinoctial();\n\n  /** @brief Constructor with equinoctial elements\n  * @param a    Semi-major axis\n  * @param h\n  * @param k\n  * @param p\n  * @param q\n  * @param l0   Mean longitude at time of perigee\n  * @param tau  Time of perigee\n  * @param GM   Specific gravitational constant */\n Equinoctial(Double a, Double h, Double k, Double p, Double q, Double l0, const Time &tau, Double GM = DEFAULT_GM);\n\n  /** @brief Equinoctial from Kepler orbit\n  * @param kepler Kepler object */\n  explicit Equinoctial(const Kepler &kepler);\n\n  /** @brief Constructor with state vector at initial time @a epoch.\n  * @param epoch    Reference epoch. Position and velocity are given at this epoch. The motion will be parametrized with respect to this epoch.\n  * @param position Initial position\n  * @param velocity Initial velocity\n  * @param GM   Specific gravitational constant */\n  explicit Equinoctial(const Time &epoch, const Vector3d &position, const Vector3d &velocity, Double GM=DEFAULT_GM);\n\n  /** @brief Constructor with state vector at arbitrary time @a time.\n  * @param epoch    Reference epoch. The motion will be parametrized with respect to this epoch.\n  * @param time     Time of position and velocity\n  * @param position Initial position\n  * @param velocity Initial velocity\n  * @param GM   Specific gravitational constant\n  * @see Chapter 2.1.5 Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” */\n  explicit Equinoctial(const Time &epoch, const Time &time, const Vector3d &position, const Vector3d &velocity, Double GM=DEFAULT_GM);\n\n  /** @brief Mean longitude @a lambda at @a time\n  * @param time Time of mean longitude\n  * @see Eq. 14.a, Broucke, R. A., and P. J. Cefola. 1972. “On the Equinoctial Orbit Elements.” Celestial Mechanics 5 (3): 303–10. doi:10.1007/BF01228432.\n  * We use a LongDouble for numerical reasons. Roundoff in time differences can lead to discrepancies in\n  * computation of different orbits. We use LongDouble for the mean Longitude to get around this. Needs to be considered here\n  * and in constructor from position and velocity. */\n  LongDouble meanLongitude(const Time &time) const;\n\n  /** @brief Eccentric longitude @a F at @a time through Newton's method\n  * @param time Eccentric longitude at this time\n  * @see Eq. 14.b, Broucke, R. A., and P. J. Cefola. 1972. “On the Equinoctial Orbit Elements.” Celestial Mechanics 5 (3): 303–10. doi:10.1007/BF01228432.\n  */\n  Double eccentricLongitude(const Time &time) const;\n\n  /** @brief True longitude @a L at @a time\n  * @param time True longitude at this time\n  * @see Eq. 14.c, Broucke, R. A., and P. J. Cefola. 1972. “On the Equinoctial Orbit Elements.” Celestial Mechanics 5 (3): 303–10. doi:10.1007/BF01228432.\n  * @see Chapter 2.1.4 Eq 5, Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” DTIC Document */\n  Double trueLongitude(const Time &time) const;\n\n  /** @brief Mean anomaly @a M at @a time\n  * @param time Time of mean anomaly\n  * @see Chapter 2.1.3 Eq 2, Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” DTIC Document */\n  Double meanAnomaly(const Time &time) const;\n\n  /** @brief Orthonormal vectors defining the orbital plane system\n  * @param[out] F perigee direction\n  * @param[out] G corresponding to true anomaly 90°\n  * @param[out] H completing the system\n  * @see Eq. 2.71 ff in Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits. Springer-Verlag Berlin Heidelberg New York. */\n  void orthonormals(Vector3d &F, Vector3d &G, Vector3d &H) const;\n\n  /** @brief In-plane orthonormal vectors\n  * @param[out] F perigee direction\n  * @param[out] G corresponding to true anomaly 90°\n  * @see Eq. 2.71 ff in Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits. Springer-Verlag Berlin Heidelberg New York. */\n  void orthonormals(Vector3d &F, Vector3d &G) const;\n\n  /** @brief State transition matrix and inverse at @a time.\n  * @param      time   Evaluation time\n  * @returns           State transition matrix. The rows contain the partial derivatives of position and velocity with regard to equinoctial elements.\n  * @see Chapter 2.1.6 and 2.1.7 -- Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” DTIC Document. */\n  Matrix stateTransitionMatrix(const Time &time);\n\n  /** @brief Position at @a time.\n  * @param time time\n  * @returns position at @a time */\n  const Vector3d position(const Time &time) const;\n\n  /** @brief Position and velocity at @a time.\n  * @param time time\n  * @param[out] position position at @a time\n  * @param[out] velocity velocity at @a time */\n  void orbit(const Time &time, Vector3d &position, Vector3d &velocity) const;\n\n  /** @brief Position, velocity, and acceleration at @a time.\n  * @param time time\n  * @param[out] position position at @a time\n  * @param[out] velocity velocity at @a time\n  * @param[out] acceleration acceleration at @a time\n  * @see Eq. 2.71 in Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits. Springer-Verlag Berlin Heidelberg New York. */\n  void orbit(const Time &time, Vector3d &position, Vector3d &velocity, Vector3d &acceleration) const;\n\n  /** @brief Position and velocity in orbital plane at @a time\n  * @param time time\n  * @param[out] position position at @a time\n  * @param[out] velocity velocity at @a time\n  * @see Eq. 2.71 in Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits. Springer-Verlag Berlin Heidelberg New York. */\n  void inPlaneOrbit(const Time &time, Vector3d &position, Vector3d &velocity) const;\n\n  /** @brief Position, velocity, and acceleration in orbital plane at @a time\n  * @param time time\n  * @param[out] position position at @a time\n  * @param[out] velocity velocity at @a time\n  * @param[out] acceleration acceleration at @a time\n  * @see Eq. 2.71 in Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits. Springer-Verlag Berlin Heidelberg New York. */\n  void inPlaneOrbit(const Time &time, Vector3d &position, Vector3d &velocity, Vector3d &acceleration) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_KEPLER__ */\n"
  },
  {
    "path": "source/base/exception.h",
    "content": "/***********************************************/\n/**\n* @file exception.h\n*\n* @brief Exception handling.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-06-16\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EXCEPTION__\n#define __GROOPS_EXCEPTION__\n\n#include <exception>\n#include <string>\n\n/***** CLASS ***********************************/\n\n/** @brief Exception handling.\n* @ingroup base */\nclass Exception : public std::exception\n{\n  std::string message;\n\npublic:\n  /** @brief Exception handling.\n  * @param msg Error message */\n  Exception(const std::string &msg) noexcept : message(msg) {}\n\n  /** @brief Error message.\n  * Returns a C-style character string\n  * describing the general cause of the current error. */\n  const char *what() const noexcept {return message.c_str();}\n};\n\n/***********************************************/\n\n#define _GROOPS_QUOTEME_(x) #x\n#define _GROOPS_QUOTEME(x) _GROOPS_QUOTEME_(x)\n#define _GROOPS_ERRORLINE (std::string(\"in \")+__FILE__+\":\"+_GROOPS_QUOTEME(__LINE__)+\" (\"+__func__+\")\")\n\n/** @brief Rethrow an error message.\n* Prepend the calling function and source file.\n* Is to be used in the form:\n* @code\n* void func()\n* {\n*   try\n*   {\n*   }\n*   catch(std::exception &e)\n*   {\n*     GROOPS_RETHROW(e)\n*   }\n* }\n* @endcode\n* @ingroup base */\n#define GROOPS_RETHROW(e) throw(Exception(_GROOPS_ERRORLINE+\"\\n\"+e.what()));\n\n/** @brief Rethrow an error message with extra function text.\n* @see GROOPS_RETHROW\n* @ingroup base */\n#define GROOPS_RETHROW_EXTRA(text, e) throw(Exception(_GROOPS_ERRORLINE+\": \"+text+\"\\n\"+e.what()));\n\n/***********************************************/\n\n#endif /* __GROOPS_Exception__ */\n"
  },
  {
    "path": "source/base/format.cpp",
    "content": "/***********************************************/\n/**\n* @file format.cpp\n*\n* @brief Format of numbers.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2016-07-15\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n#include \"base/format.h\"\n#include <regex>\n\n/***** FUNCTIONS *******************************/\n\nstd::string operator%(LongDouble value, const std::string &format)\n{\n  try\n  {\n    UInt   year=0, month=0, day=0, hour=0, min=0;\n    Double sec=0;\n    Int    secondPrecision = -1;\n\n    // parse format string -> calculate new result string\n    std::string result;\n    std::string::size_type posFormat = 0;\n    for(;;)\n    {\n      if(posFormat >= format.size())\n        break;\n      std::string::size_type posFormatOld = posFormat;\n      posFormat = format.find('%', posFormatOld);\n      result += format.substr(posFormatOld, posFormat-posFormatOld);\n      if(posFormat == std::string::npos)\n        break;\n      posFormat++;\n      if(posFormat>=format.size())\n        throw(Exception(\"expecting qualifier after '%'\"));\n\n      // parse %[flags][width][.precision]specifier format\n      std::stringstream ss;\n      auto c = format.at(posFormat++);\n\n      Bool hasSubSpecifiers = FALSE;\n      // [flags]\n      for(;;)\n      {\n        if(c=='0')      ss.fill('0');\n        else if(c==' ') ss.fill(' ');\n        else if(c=='-') ss.setf(std::ios_base::left, std::ios_base::adjustfield);\n        else if(c=='#') throw(Exception(\"'#' not supported\"));\n        else if(c=='+') throw(Exception(\"'+' not supported\"));\n        else break;\n        c = format.at(posFormat++);\n        hasSubSpecifiers = TRUE;\n      }\n\n      // [width]\n      if(std::isdigit(c))\n      {\n        const char *ptr1 = format.c_str()+posFormat-1;\n        char *ptr2;\n        ss.width(std::strtol(ptr1, &ptr2, 10));\n        posFormat += ptr2-ptr1-1;\n        c = format.at(posFormat++);\n        hasSubSpecifiers = TRUE;\n      }\n\n      // [.precision]\n      if(c=='.')\n      {\n        const char *ptr1 = format.c_str()+posFormat;\n        char *ptr2;\n        ss.precision(std::strtol(ptr1, &ptr2, 10));\n        posFormat += ptr2-ptr1;\n        c = format.at(posFormat++);\n        hasSubSpecifiers = TRUE;\n      }\n\n      // specifier\n      switch(c)\n      {\n        case '%':\n        {\n          ss<<'%';\n          break;\n        }\n        case 'c': // character\n        {\n          ss<<static_cast<char>(std::round(value));\n          break;\n        }\n        case 'i': // integer\n        {\n          ss<<static_cast<long int>(std::round(value));\n          break;\n        }\n        case 'f':  // float\n        case 'e':\n        case 'g':\n        {\n          if(c=='e') ss.setf(std::ios::scientific, std::ios::floatfield);\n          if(c=='f') ss.setf(std::ios::fixed,      std::ios::floatfield);\n          ss<<value;\n          break;\n        }\n        case 'O': // day of year\n        {\n          ss<<mjd2time(value).dayOfYear();\n          break;\n        }\n        case 'W':\n        {\n          ss<<static_cast<int>(std::floor(value)-44244)/7; //GPS week\n          break;\n        }\n        case 'w':\n        {\n          ss<<static_cast<int>(std::floor(value)-44244)%7; // GPS day of week\n          break;\n        }\n\n        // date/time preparation\n        case 'y': case 'm': case 'd':\n        case 'H': case 'M': case 'S':\n        case 'D': case 'T': case 'Y':\n        {\n          // check (once) if complete format string contains %S with precision (e.g. %.2S), find maximum precision of any %S, and round time accordingly\n          if(secondPrecision == -1)\n          {\n            secondPrecision = 0;\n            static const std::regex regexPattern(\"%[[\\\\d #+\\\\-]*\\\\.(\\\\d+)[S]\");\n            std::sregex_iterator next(format.begin(), format.end(), regexPattern);\n            std::sregex_iterator end;\n            while(next != end)\n            {\n              std::smatch match = *next;\n              secondPrecision = std::max(std::atoi(match[1].str().c_str()), secondPrecision);\n              next++;\n            }\n\n            // round seconds to precision considering rollovers\n            mjd2time(value).date(year, month, day, hour, min, sec);\n            sec = std::round(sec*std::pow(10., secondPrecision))/std::pow(10., secondPrecision) + std::pow(10., -(secondPrecision+1));\n            date2time(year, month, day, hour, min, sec).date(year, month, day, hour, min, sec);\n          }\n\n          if(c=='y')      {ss<<std::setw(4)<<std::setfill('0')<<year;}\n          else if(c=='m') {ss<<std::setw(2)<<std::setfill('0')<<month;}\n          else if(c=='d') {ss<<std::setw(2)<<std::setfill('0')<<day;}\n          else if(c=='H') {ss<<std::setw(2)<<std::setfill('0')<<hour;}\n          else if(c=='M') {ss<<std::setw(2)<<std::setfill('0')<<min;}\n          else if(c=='S')\n          {\n            if(hasSubSpecifiers)\n            {\n              ss.setf(std::ios::fixed, std::ios::floatfield);\n              ss<<sec;\n            }\n            else\n              ss<<std::setw(2)<<std::setfill('0')<<std::round(sec);\n          }\n          else if(c=='D') {ss<<std::setw(4)<<std::setfill('0')<<year<<\"-\"<<std::setw(2)<<std::setfill('0')<<month<<\"-\"<<std::setw(2)<<std::setfill('0')<<day;}\n          else if(c=='T') {ss<<std::setw(2)<<std::setfill('0')<<hour<<\"-\"<<std::setw(2)<<std::setfill('0')<<min<<\"-\"<<std::setw(2)<<std::setfill('0')<<std::round(sec);}\n          else if(c=='Y') {ss<<std::setw(2)<<std::setfill('0')<<year%100;}; // two digit year\n          break;\n        }\n\n        default:\n          throw(Exception(std::string(\"unknown formater '%\")+c+\"'\"));\n      } // switch\n      result += ss.str();\n    } // for(;;)\n\n    return result;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/*************************************************/\n\nstd::string operator%(const Time &x, const std::string &format)\n{\n  LongDouble value = x.mjdMod();\n  value += x.mjdInt();\n  return value%format;\n}\n\n/*************************************************/\n"
  },
  {
    "path": "source/base/format.h",
    "content": "/***********************************************/\n/**\n* @file format.h\n*\n* @brief Format of numbers.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2016-07-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FORMAT__\n#define __GROOPS_FORMAT__\n\n#include \"base/importStd.h\"\n\nusing namespace std::literals::string_literals;\n\n/***** FUNCTIONS *******************************/\n\n/** @brief format numbers for output.\n* @ingroup base\n* The number @a x is replaced by the @a format string. The format contains the text to be written\n* to output It can contain embedded format specifiers that are replaced by the number\n* and formatted as requested (also multiple times).\n* In the following an example output is given in the brackets for the example value of 57493.8:\n* - %i: integer [57494]\n* - %f: Decimal floating point [57493.800000]\n* - %e: Scientific notation [5.749380e+04]\n* - %g: Use the shortest representation: %e or %f [57493.8]\n* - %c: interpret number as ASCII character.\n* - %%: write a single %.\n*\n* The following specifiers interpret the value as MJD (modified julian date):\n* - %y: four digit year [2016]\n* - %Y: two digit year [16]\n* - %m: month [04]\n* - %d: day of month [15]\n* - %H: Hour [19]\n* - %M: Minute [12]\n* - %S: Second [00 or custom floating point format, e.g. %04.1S = 00.0]\n* - %D: Date (same as %y-%m-%d) [2016-04-15]\n* - %T: Time (same as %H-%M-%S) [19-12-00]\n* - %W: GPS week [1892]\n* - %w: Day of GPS week (0..6) [5]\n* - %O: Day of year (1..366)\n* ẂARNING: Using multiple %S and/or %T specifiers with different precisions in the same format string\n*          can lead to incorrect rounding (60 sec) since the maximum precision is used for rounding!\n*\n* The output can be specified further with %[width][.precision]specifier,\n* there [width] is the minimum number of characters to be printed. If the value to be printed\n* is shorter than this number, the result is padded with blank spaces (or zeros if [width] starts\n* with a zero). The [.precision] defines the number of digits after the period (for %g the number\n* of significant digits instead).\n*\n* Example 51544.5 % \"%D_T%T\"s -> '2000-01-01_T12-00-00'. */\nstd::string operator%(LongDouble x, const std::string &format);\n\ninline std::string operator%(Double x, const std::string &format) {return static_cast<LongDouble>(x)%format;}\ninline std::string operator%(UInt   x, const std::string &format) {return static_cast<LongDouble>(x)%format;}\ninline std::string operator%(Int    x, const std::string &format) {return static_cast<LongDouble>(x)%format;}\n\nclass Time;\n/** @copydoc operator%(LongDouble, const std::string &) */\nstd::string operator%(const Time &x, const std::string &format);\n\n/*************************************************/\n\n#endif\n"
  },
  {
    "path": "source/base/fourier.cpp",
    "content": "/***********************************************/\n/**\n* @file fourier.cpp\n*\n* @brief FFT-functions.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2004-10-25\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/fourier.h\"\n\n/***********************************************/\n\nstatic inline void butterfly2(std::complex<Double> *f, const std::vector<std::complex<Double>> &twiddles, UInt step, UInt m)\n{\n  for(UInt i=0; i<m; i++)\n  {\n    const auto t = f[i+m] * twiddles[i*step];\n    f[i+m]  = f[i]-t;\n    f[i]   += t;\n  }\n}\n\n/***********************************************/\n\nstatic inline void butterfly3(std::complex<Double> *f, const std::vector<std::complex<Double>> &twiddles, UInt step, UInt m)\n{\n  const Double epi3 = twiddles[step*m].imag();\n  for(UInt i=0; i<m; i++)\n  {\n    const auto t1 = f[i+  m] * twiddles[  i*step];\n    const auto t2 = f[i+2*m] * twiddles[2*i*step];\n    const auto t3 = t1 + t2;\n    const auto t0 = std::complex<Double>(-epi3*(t1.imag()-t2.imag()), epi3*(t1.real()-t2.real()));\n    f[i+m]    = f[i] - 0.5*t3;\n    f[i+2*m]  = f[i+m] - t0;\n    f[i]     += t3;\n    f[i+m]   += t0;\n  }\n}\n\n/***********************************************/\n\nstatic inline void butterfly4(std::complex<Double> *f, const std::vector<std::complex<Double>> &twiddles, UInt step, UInt m, Bool inverse)\n{\n  for(UInt i=0; i<m; i++)\n  {\n    const auto t0 = f[i+  m] * twiddles[  i*step];\n    const auto t1 = f[i+2*m] * twiddles[2*i*step];\n    const auto t2 = f[i+3*m] * twiddles[3*i*step];\n    const auto t3 = t0   + t2;\n    const auto t4 = f[i] - t1;\n    const auto t5 = std::complex<Double>(+t0.imag()-t2.imag(), -t0.real()+t2.real()) * ((inverse) ? -1. : 1.);\n    f[i]    += t1;\n    f[i+2*m] = f[i] - t3;\n    f[i]    += t3;\n    f[i+m]   = t4 + t5;\n    f[i+3*m] = t4 - t5;\n  }\n}\n\n/***********************************************/\n\nstatic inline void butterfly5(std::complex<Double> *f, const std::vector<std::complex<Double>> &twiddles, UInt step, UInt m)\n{\n  const std::complex<Double> ya = twiddles[step*m];\n  const std::complex<Double> yb = twiddles[step*2*m];\n  for(UInt i=0; i<m; i++)\n  {\n    const auto t0  = f[i+1*m] * twiddles[  i*step];\n    const auto t1  = f[i+2*m] * twiddles[2*i*step];\n    const auto t2  = f[i+3*m] * twiddles[3*i*step];\n    const auto t3  = f[i+4*m] * twiddles[4*i*step];\n    const auto t4  = t0 + t3;\n    const auto t5  = t1 + t2;\n    const auto t6  = t1 - t2;\n    const auto t7  = t0 - t3;\n    const auto t8  = f[i] + t4 * ya.real() + t5 * yb.real();\n    const auto t9  = f[i] + t4 * yb.real() + t5 * ya.real();\n    const auto t10 = std::complex<Double>(+t7.imag(), -t7.real()) * ya.imag() + std::complex<Double>(t6.imag(), -t6.real()) * yb.imag();\n    const auto t11 = std::complex<Double>(-t7.imag(), +t7.real()) * yb.imag() + std::complex<Double>(t6.imag(), -t6.real()) * ya.imag();\n    f[i]     += t4 + t5;\n    f[i+1*m]  = t8 - t10;\n    f[i+2*m]  = t9 + t11;\n    f[i+3*m]  = t9 - t11;\n    f[i+4*m]  = t8 + t10;\n  }\n}\n\n/***********************************************/\n\n// perform the butterfly for one stage of a mixed radix FFT.\nstatic inline void butterfly(std::complex<Double> *f, const std::vector<std::complex<Double>> &twiddles, UInt step, UInt m, UInt p)\n{\n  std::vector<std::complex<Double>> t(p);\n  for(UInt u=0; u<m; u++)\n  {\n    for(UInt i=0; i<p; i++)\n      t[i] = f[i*m+u];\n    for(UInt i=0; i<p; i++)\n    {\n      f[i*m+u] = t[0];\n      for(UInt k=1; k<p; k++)\n        f[i*m+u] += t[k] * twiddles[(k*step*(i*m+u))%twiddles.size()];\n    }\n  }\n}\n\n/***********************************************/\n\nstatic inline std::vector<UInt> computeRadix(UInt n)\n{\n  std::vector<UInt> factors;\n  UInt p = 4; // factor out powers of 4, powers of 2, then any remaining primes\n  do\n  {\n    while(n % p)\n    {\n      if(p == 4)      p  = 2;\n      else if(p == 2) p  = 3;\n      else            p += 2;\n    }\n    n /= p;\n    factors.push_back(p);\n    factors.push_back(n);\n  }\n  while(n > 1);\n\n  return factors;\n}\n\n/***********************************************/\n\n// recursive call: DFT of size m*p performed by doing p instances of smaller DFTs of size m, each one takes a decimated version of the input\nstatic inline void recursiveFft(Bool inverse, std::complex<Double> *f, const std::complex<Double> *input, const UInt *factors, const std::vector<std::complex<Double>> &twiddles, UInt step)\n{\n  const UInt p = *(factors++); // the radix\n  const UInt m = *(factors++); // stage's fft length/p\n\n  if(m>1)\n  {\n    for(UInt i=0; i<p; i++)\n      recursiveFft(inverse, f+(i*m), input+(i*step), factors, twiddles, p*step);\n  }\n  else\n    for(UInt i=0; i<p; i++)\n      f[i] = input[i*step];\n\n  // recombine the p smaller DFTs\n  switch(p)\n  {\n    case 2:  butterfly2(f, twiddles, step, m);          break;\n    case 3:  butterfly3(f, twiddles, step, m);          break;\n    case 4:  butterfly4(f, twiddles, step, m, inverse); break;\n    case 5:  butterfly5(f, twiddles, step, m);          break;\n    default: butterfly (f, twiddles, step, m, p);       break;\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<std::complex<Double>> Fourier::fft(const Vector &data)\n{\n  try\n  {\n    const UInt count = data.rows();\n\n    std::vector<std::complex<Double>> input(count);\n    for(UInt i=0; i<count; i++)\n      input[i] = data(i);\n\n    // compute twiddle factors\n    std::vector<std::complex<Double>> twiddles(count);\n    for(UInt i=0; i<twiddles.size(); i++)\n      twiddles[i] = std::exp(std::complex<Double>(0, -2*PI*i/count));\n\n    std::vector<std::complex<Double>> F(twiddles.size());\n    std::vector<UInt> factors = computeRadix(twiddles.size());\n    recursiveFft(FALSE/*inverse*/, F.data(), input.data(), factors.data(), twiddles, 1);\n    F.resize((count+2)/2);\n    return F;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Fourier::synthesis(const std::vector<std::complex<Double>> &F, Bool countEven)\n{\n  try\n  {\n    const UInt count = 2*F.size() - (countEven ? 2 : 1);\n\n    // extent input symmetric\n    std::vector<std::complex<Double>> F2(count);\n    F2[0] = F[0];\n    for(UInt i=1; i<F.size(); i++)\n    {\n      F2[i]       = F[i];\n      F2[count-i] = std::conj(F[i]);\n    }\n\n    // compute twiddle factors\n    std::vector<std::complex<Double>> twiddles(count);\n    for(UInt i=0; i<twiddles.size(); i++)\n      twiddles[i] = std::exp(std::complex<Double>(0, 2*PI*i/count));\n\n    std::vector<std::complex<Double>> F3(twiddles.size());\n    std::vector<UInt> factors = computeRadix(twiddles.size());\n    recursiveFft(TRUE/*inverse*/, F3.data(), F2.data(), factors.data(), twiddles, 1);\n\n    Vector data(count);\n    for(UInt i=0; i<F3.size(); i++)\n      data(i) = (1./count)*F3[i].real();\n    return data;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Fourier::frequencies(UInt count, Double dt)\n{\n  Vector frequencies((count+2)/2);\n  for(UInt k=0; k<(count+2)/2; k++)\n    frequencies(k) = static_cast<Double>(k)/(count*dt);\n  return frequencies;\n}\n\n/***********************************************/\n\nvoid Fourier::complex2AmplitudePhase(const std::vector<std::complex<Double>> &F, Vector &amplitude, Vector &phase)\n{\n  amplitude = Vector(F.size());\n  phase     = Vector(F.size());\n  for(UInt k = 0; k<F.size(); k++)\n  {\n    phase(k)     = std::atan2(F.at(k).imag(), F.at(k).real());\n    amplitude(k) = std::abs(F.at(k));\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic void cosTransformation(Vector &x)\n{\n  const UInt n = x.rows();\n  if(n<2)\n    return;\n\n  Double c = x(0)-x(n-1);\n  x(0) += x(n-1);\n  for(UInt i=1; i<n/2; i++)\n  {\n    c += 2*std::cos(PI*i/(n-1)) * (x(i)-x(n-1-i));\n    const Double t1 = (x(i)+x(n-1-i));\n    const Double t2 = (x(i)-x(n-1-i)) * 2 * std::sin(PI*i/(n-1));\n    x(i)     = t1 - t2;\n    x(n-1-i) = t1 + t2;\n  }\n  if(n%2)\n    x(n/2) *= 2;\n\n  const auto F = Fourier::fft(x.row(0, n-1));\n\n  x(0) = F[0].real();\n  x(1) = c;\n  for(UInt i=1; i<n/2; i++)\n  {\n    x(2*i+0) = F[i].real();\n    x(2*i+1) = x(2*i-1) - F[i].imag();\n  }\n  if(n%2)\n    x(n-1) = F.back().real();\n}\n\n/***********************************************/\n\nVector Fourier::covariance2psd(const Vector &cov, Double dt)\n{\n  try\n  {\n    Vector psd = 2*dt*cov; // one sided PSD\n    cosTransformation(psd);\n    return psd;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Fourier::psd2covariance(const Vector &psd, Double dt)\n{\n  try\n  {\n    Vector cov = 0.25/(dt*(psd.rows()-1))*psd; // from  one sided PSD\n    cosTransformation(cov);\n    return cov;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/fourier.h",
    "content": "/***********************************************/\n/**\n* @file fourier.h\n*\n* @brief FFT-functions.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2004-10-25\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FOURIER__\n#define __GROOPS_FOURIER__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/***** CLASS ***********************************/\n\n/**\n* @brief FFT-functions.\n* @ingroup base\n*/\nnamespace Fourier\n{\n/***** Complex FFT *****************************/\n\n  /** @brief Forward fourier transform of a real periodic sequence.\n  * A data sequence with @f$j=0\\ldots n-1@f$ elements is transformed with\n  * @f[ y_k = \\sum_{j=0}^{n-1} x_j e^{-2\\pi jk/n}, @f]\n  * where @f$k = 0 \\ldots [n/2]@f$.\n  * This transform is normalized since a call of fft followed by a call of synthesis gives the original result.\n  * @param data data series\n  * @return complex representation of the fourier transform */\n  std::vector<std::complex<Double>> fft(const Vector &data);\n\n  /** @brief Backward transform of complex fourier coefficients.\n  *\n  * If @a countEven=FALSE the size of the output data is @f$n=2m-1@f$ and computed by\n  * @f[ x_j = \\frac{1}{n} \\sum_{k=-(m-1)}^{m-1} y_{|k|} e^{2\\pi jk/n}, @f]\n  * where @f$m@f$ is the number of complex fourier coefficients.\n  *\n  * If @a countEven=TRUE the size of the output data is @f$n=2m-2@f$ and computed by\n  * @f[ x_j = \\frac{1}{n} \\sum_{k=-(m-2)}^{m-2} y_{|k|} e^{2\\pi jk/n} + \\frac{1}{n} (-1)^j re(y_{m-1}). @f]\n  * The imaginary part of the last coefficient is ignored.\n  *\n  * @param F complex fourier coefficients\n  * @param countEven size of output vector is even\n  * @return data series */\n  Vector synthesis(const std::vector<std::complex<Double>> &F, Bool countEven);\n\n  /** @brief Frequency computation.\n  * This function creates a frequency vector of half the length of an input\n  * data vector. The output vector contains frequencies measured in cycles per time.\n  * @param count length of input sequence\n  * @param dt sampling interval\n  * @return frequency vector */\n  Vector frequencies(UInt count, Double dt);\n\n  /** @brief Convert complex FFT coefficients to amplitude and phase.\n  * @param F complex fourier coefficients\n  * @param[out] amplitude amplitude spectrum\n  * @param[out] phase phase spectrum */\n  void complex2AmplitudePhase(const std::vector<std::complex<Double>> &F, Vector &amplitude, Vector &phase);\n\n  /***** Covariance transformation ***************/\n\n  /** @brief Computes the one sided PSD from a given covariance function.\n  * A covariance function @f$c@f$with @f$j=0\\ldots n-1@f$ elements is transformed to a one sided PSD\n  * by the cosine transformation\n  * @f[ psd_k = 2dt\\left(c_0 + c_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 c_j \\cos(\\pi jk/(n-1))\\right). @f]\n  * The PSD of white noise with a variance of @f$\\sigma^2@f$ is constant for all frequencies\n  * with the power @f$A=2\\delta t\\sigma^2@f$.\n  * @param cov covariance function\n  * @param dt sampling interval\n  * @return psd */\n  Vector covariance2psd(const Vector &cov, Double dt);\n\n  /** @brief Computes the covariance function from a one sided PSD.\n  * A one sided PSD @f$p@f$ with @f$j=0\\ldots n-1@f$ elements is transformed into a covariance function\n  * by the cosine transformation\n  * @f[ c_k = \\frac{1}{4dt(n-1)}\\left(p_0 + p_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 p_j \\cos(\\pi jk/(n-1))\\right). @f]\n  * The variance of a PSD with constant power @f$A@f$ for all frequencies (white noise)\n  * is @f$\\sigma^2=cov(0)=\\frac{A}{2\\delta t}@f$ .\n  * @param psd power spectral density (PSD)\n  * @param dt sampling interval\n  * @return covariance function */\n  Vector psd2covariance(const Vector &psd, Double dt);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_FOURIER__ */\n"
  },
  {
    "path": "source/base/gnssType.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssType.cpp\n*\n* @brief GNSS observation types.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-04-30\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/gnssType.h\"\n\n/***********************************************/\n\n// Bit masks\nconst GnssType GnssType::PRN        = GnssType(static_cast<UInt64>(0xff));       // satellite identification number (PRN, SBAS-100, ...)\nconst GnssType GnssType::SYSTEM     = GnssType(static_cast<UInt64>(0x0f) << 8);  // satellite system (GPS, GLONASS, ...)\nconst GnssType GnssType::FREQUENCY  = GnssType(static_cast<UInt64>(0x0f) << 12); // frequency\nconst GnssType GnssType::TYPE       = GnssType(static_cast<UInt64>(0xff) << 16); // phase, range, doppler, ...\nconst GnssType GnssType::ATTRIBUTE  = GnssType(static_cast<UInt64>(0x7f) << 24); // attribute\nconst GnssType GnssType::FREQ_NO    = GnssType(static_cast<UInt64>(0xff) << 32); // GLONASS frequency number\nconst GnssType GnssType::ALL        = GnssType::TYPE + GnssType::FREQUENCY + GnssType::ATTRIBUTE + GnssType::SYSTEM + GnssType::PRN + GnssType::FREQ_NO;\nconst GnssType GnssType::NOPRN      = GnssType::TYPE + GnssType::FREQUENCY + GnssType::ATTRIBUTE + GnssType::SYSTEM                 + GnssType::FREQ_NO;\n// system\nconst GnssType GnssType::GPS       = GnssType(static_cast<UInt64>(1) << 8);\nconst GnssType GnssType::GLONASS   = GnssType(static_cast<UInt64>(2) << 8);\nconst GnssType GnssType::SBAS      = GnssType(static_cast<UInt64>(3) << 8);\nconst GnssType GnssType::BDS       = GnssType(static_cast<UInt64>(4) << 8);\nconst GnssType GnssType::GALILEO   = GnssType(static_cast<UInt64>(5) << 8);\nconst GnssType GnssType::QZSS      = GnssType(static_cast<UInt64>(6) << 8);\nconst GnssType GnssType::IRNSS     = GnssType(static_cast<UInt64>(7) << 8);\n// frequency\nconst GnssType GnssType::L1        = GnssType(static_cast<UInt64>(1) << 12); // GPS\nconst GnssType GnssType::L2        = GnssType(static_cast<UInt64>(2) << 12);\nconst GnssType GnssType::L5        = GnssType(static_cast<UInt64>(5) << 12);\nconst GnssType GnssType::E1        = GnssType(static_cast<UInt64>(1) << 12); // GALILEO\nconst GnssType GnssType::E5a       = GnssType(static_cast<UInt64>(5) << 12);\nconst GnssType GnssType::E5b       = GnssType(static_cast<UInt64>(7) << 12);\nconst GnssType GnssType::E5        = GnssType(static_cast<UInt64>(8) << 12);\nconst GnssType GnssType::E6        = GnssType(static_cast<UInt64>(6) << 12);\nconst GnssType GnssType::G1        = GnssType(static_cast<UInt64>(1) << 12); // GLONASS\nconst GnssType GnssType::G1a       = GnssType(static_cast<UInt64>(4) << 12);\nconst GnssType GnssType::G2        = GnssType(static_cast<UInt64>(2) << 12);\nconst GnssType GnssType::G2a       = GnssType(static_cast<UInt64>(6) << 12);\nconst GnssType GnssType::G3        = GnssType(static_cast<UInt64>(3) << 12);\nconst GnssType GnssType::B1        = GnssType(static_cast<UInt64>(2) << 12); // BDS\nconst GnssType GnssType::B1C       = GnssType(static_cast<UInt64>(1) << 12);\nconst GnssType GnssType::B2a       = GnssType(static_cast<UInt64>(5) << 12);\nconst GnssType GnssType::B2b       = GnssType(static_cast<UInt64>(7) << 12);\nconst GnssType GnssType::B2        = GnssType(static_cast<UInt64>(8) << 12);\nconst GnssType GnssType::B3        = GnssType(static_cast<UInt64>(6) << 12);\nconst GnssType GnssType::L6        = GnssType(static_cast<UInt64>(6) << 12); // QZSS\nconst GnssType GnssType::S9        = GnssType(static_cast<UInt64>(9) << 12); // IRNSS S\n// observation type\nconst GnssType GnssType::RANGE     = GnssType(static_cast<UInt64>(1) << 16);\nconst GnssType GnssType::PHASE     = GnssType(static_cast<UInt64>(2) << 16);\nconst GnssType GnssType::DOPPLER   = GnssType(static_cast<UInt64>(3) << 16);\nconst GnssType GnssType::SNR       = GnssType(static_cast<UInt64>(4) << 16);\nconst GnssType GnssType::IONODELAY = GnssType(static_cast<UInt64>(5) << 16);\nconst GnssType GnssType::AZIMUT    = GnssType(static_cast<UInt64>(6) << 16);\nconst GnssType GnssType::ELEVATION = GnssType(static_cast<UInt64>(7) << 16);\nconst GnssType GnssType::ROTI      = GnssType(static_cast<UInt64>(8) << 16);  // Rate of Tec Index\nconst GnssType GnssType::IONOINDEX = GnssType(static_cast<UInt64>(9) << 16);  // Ionospheric index (sigma_phi)\nconst GnssType GnssType::CHANNEL   = GnssType(static_cast<UInt64>(10)<< 16);\n// attributes\nconst GnssType GnssType::C         = GnssType(static_cast<UInt64>(1) << 24);  // C/A - Code\nconst GnssType GnssType::W         = GnssType(static_cast<UInt64>(2) << 24);  // P Z-tracking and similar (AS on)\nconst GnssType GnssType::D         = GnssType(static_cast<UInt64>(3) << 24);  // L1(C/A)+(P2-P1) (semi-codeless)\nconst GnssType GnssType::X         = GnssType(static_cast<UInt64>(4) << 24);\nconst GnssType GnssType::S         = GnssType(static_cast<UInt64>(5) << 24);\nconst GnssType GnssType::L         = GnssType(static_cast<UInt64>(6) << 24);\nconst GnssType GnssType::I         = GnssType(static_cast<UInt64>(7) << 24);\nconst GnssType GnssType::Q         = GnssType(static_cast<UInt64>(8) << 24);\nconst GnssType GnssType::A         = GnssType(static_cast<UInt64>(9) << 24);\nconst GnssType GnssType::B         = GnssType(static_cast<UInt64>(10) << 24);\nconst GnssType GnssType::Z         = GnssType(static_cast<UInt64>(11) << 24);\nconst GnssType GnssType::P         = GnssType(static_cast<UInt64>(12) << 24);\nconst GnssType GnssType::Y         = GnssType(static_cast<UInt64>(13) << 24);\nconst GnssType GnssType::M         = GnssType(static_cast<UInt64>(14) << 24);\nconst GnssType GnssType::E         = GnssType(static_cast<UInt64>(15) << 24);\nconst GnssType GnssType::UNKNOWN_ATTRIBUTE = GnssType(static_cast<UInt64>(99) << 24);\n\n// some codes\nconst GnssType GnssType::C1CG      = GnssType::RANGE + GnssType::L1  + GnssType::C + GnssType::GPS;\nconst GnssType GnssType::C1SG      = GnssType::RANGE + GnssType::L1  + GnssType::S + GnssType::GPS;\nconst GnssType GnssType::C1LG      = GnssType::RANGE + GnssType::L1  + GnssType::L + GnssType::GPS;\nconst GnssType GnssType::C1XG      = GnssType::RANGE + GnssType::L1  + GnssType::X + GnssType::GPS;\nconst GnssType GnssType::C1WG      = GnssType::RANGE + GnssType::L1  + GnssType::W + GnssType::GPS;\nconst GnssType GnssType::C2CG      = GnssType::RANGE + GnssType::L2  + GnssType::C + GnssType::GPS;\nconst GnssType GnssType::C2DG      = GnssType::RANGE + GnssType::L2  + GnssType::D + GnssType::GPS;\nconst GnssType GnssType::C2SG      = GnssType::RANGE + GnssType::L2  + GnssType::S + GnssType::GPS;\nconst GnssType GnssType::C2LG      = GnssType::RANGE + GnssType::L2  + GnssType::L + GnssType::GPS;\nconst GnssType GnssType::C2XG      = GnssType::RANGE + GnssType::L2  + GnssType::X + GnssType::GPS;\nconst GnssType GnssType::C2WG      = GnssType::RANGE + GnssType::L2  + GnssType::W + GnssType::GPS;\nconst GnssType GnssType::C2UG      = GnssType::RANGE + GnssType::L2  + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GPS;\nconst GnssType GnssType::C5IG      = GnssType::RANGE + GnssType::L5  + GnssType::I + GnssType::GPS;\nconst GnssType GnssType::C5QG      = GnssType::RANGE + GnssType::L5  + GnssType::Q + GnssType::GPS;\nconst GnssType GnssType::C5XG      = GnssType::RANGE + GnssType::L5  + GnssType::X + GnssType::GPS;\nconst GnssType GnssType::C5UG      = GnssType::RANGE + GnssType::L5  + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GPS;\nconst GnssType GnssType::L1_G      = GnssType::PHASE + GnssType::L1                + GnssType::GPS;\nconst GnssType GnssType::L2_G      = GnssType::PHASE + GnssType::L2                + GnssType::GPS;\nconst GnssType GnssType::L5_G      = GnssType::PHASE + GnssType::L5                + GnssType::GPS;\n\nconst GnssType GnssType::C1CR      = GnssType::RANGE + GnssType::G1  + GnssType::C + GnssType::GLONASS;\nconst GnssType GnssType::C1PR      = GnssType::RANGE + GnssType::G1  + GnssType::P + GnssType::GLONASS;\nconst GnssType GnssType::C4AR      = GnssType::RANGE + GnssType::G1a + GnssType::A + GnssType::GLONASS;\nconst GnssType GnssType::C4BR      = GnssType::RANGE + GnssType::G1a + GnssType::B + GnssType::GLONASS;\nconst GnssType GnssType::C4XR      = GnssType::RANGE + GnssType::G1a + GnssType::X + GnssType::GLONASS;\nconst GnssType GnssType::C2CR      = GnssType::RANGE + GnssType::G2  + GnssType::C + GnssType::GLONASS;\nconst GnssType GnssType::C2PR      = GnssType::RANGE + GnssType::G2  + GnssType::P + GnssType::GLONASS;\nconst GnssType GnssType::C6AR      = GnssType::RANGE + GnssType::G2a + GnssType::A + GnssType::GLONASS;\nconst GnssType GnssType::C6BR      = GnssType::RANGE + GnssType::G2a + GnssType::B + GnssType::GLONASS;\nconst GnssType GnssType::C6XR      = GnssType::RANGE + GnssType::G2a + GnssType::X + GnssType::GLONASS;\nconst GnssType GnssType::C3IR      = GnssType::RANGE + GnssType::G3  + GnssType::I + GnssType::GLONASS;\nconst GnssType GnssType::C3QR      = GnssType::RANGE + GnssType::G3  + GnssType::Q + GnssType::GLONASS;\nconst GnssType GnssType::C3XR      = GnssType::RANGE + GnssType::G3  + GnssType::X + GnssType::GLONASS;\nconst GnssType GnssType::L1_R      = GnssType::PHASE + GnssType::G1                + GnssType::GLONASS;\nconst GnssType GnssType::L4_R      = GnssType::PHASE + GnssType::G1a               + GnssType::GLONASS;\nconst GnssType GnssType::L2_R      = GnssType::PHASE + GnssType::G2                + GnssType::GLONASS;\nconst GnssType GnssType::L6_R      = GnssType::PHASE + GnssType::G2a               + GnssType::GLONASS;\nconst GnssType GnssType::L3_R      = GnssType::PHASE + GnssType::G3                + GnssType::GLONASS;\n\nconst GnssType GnssType::C1AE      = GnssType::RANGE + GnssType::E1  + GnssType::A + GnssType::GALILEO;\nconst GnssType GnssType::C1BE      = GnssType::RANGE + GnssType::E1  + GnssType::B + GnssType::GALILEO;\nconst GnssType GnssType::C1CE      = GnssType::RANGE + GnssType::E1  + GnssType::C + GnssType::GALILEO;\nconst GnssType GnssType::C1XE      = GnssType::RANGE + GnssType::E1  + GnssType::X + GnssType::GALILEO;\nconst GnssType GnssType::C1ZE      = GnssType::RANGE + GnssType::E1  + GnssType::Z + GnssType::GALILEO;\nconst GnssType GnssType::C1UE      = GnssType::RANGE + GnssType::E1  + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GALILEO;\nconst GnssType GnssType::C5IE      = GnssType::RANGE + GnssType::E5a + GnssType::I + GnssType::GALILEO;\nconst GnssType GnssType::C5QE      = GnssType::RANGE + GnssType::E5a + GnssType::Q + GnssType::GALILEO;\nconst GnssType GnssType::C5XE      = GnssType::RANGE + GnssType::E5a + GnssType::X + GnssType::GALILEO;\nconst GnssType GnssType::C5UE      = GnssType::RANGE + GnssType::E5a + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GALILEO;\nconst GnssType GnssType::C7IE      = GnssType::RANGE + GnssType::E5b + GnssType::I + GnssType::GALILEO;\nconst GnssType GnssType::C7QE      = GnssType::RANGE + GnssType::E5b + GnssType::Q + GnssType::GALILEO;\nconst GnssType GnssType::C7XE      = GnssType::RANGE + GnssType::E5b + GnssType::X + GnssType::GALILEO;\nconst GnssType GnssType::C7UE      = GnssType::RANGE + GnssType::E5b + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GALILEO;\nconst GnssType GnssType::C8IE      = GnssType::RANGE + GnssType::E5  + GnssType::I + GnssType::GALILEO;\nconst GnssType GnssType::C8QE      = GnssType::RANGE + GnssType::E5  + GnssType::Q + GnssType::GALILEO;\nconst GnssType GnssType::C8XE      = GnssType::RANGE + GnssType::E5  + GnssType::X + GnssType::GALILEO;\nconst GnssType GnssType::C8UE      = GnssType::RANGE + GnssType::E5  + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GALILEO;\nconst GnssType GnssType::C6AE      = GnssType::RANGE + GnssType::E6  + GnssType::A + GnssType::GALILEO;\nconst GnssType GnssType::C6BE      = GnssType::RANGE + GnssType::E6  + GnssType::B + GnssType::GALILEO;\nconst GnssType GnssType::C6CE      = GnssType::RANGE + GnssType::E6  + GnssType::C + GnssType::GALILEO;\nconst GnssType GnssType::C6XE      = GnssType::RANGE + GnssType::E6  + GnssType::X + GnssType::GALILEO;\nconst GnssType GnssType::C6ZE      = GnssType::RANGE + GnssType::E6  + GnssType::Z + GnssType::GALILEO;\nconst GnssType GnssType::C6UE      = GnssType::RANGE + GnssType::E6  + GnssType::UNKNOWN_ATTRIBUTE + GnssType::GALILEO;\nconst GnssType GnssType::L1_E      = GnssType::PHASE + GnssType::E1                + GnssType::GALILEO;\nconst GnssType GnssType::L5_E      = GnssType::PHASE + GnssType::E5a               + GnssType::GALILEO;\nconst GnssType GnssType::L7_E      = GnssType::PHASE + GnssType::E5b               + GnssType::GALILEO;\nconst GnssType GnssType::L8_E      = GnssType::PHASE + GnssType::E5                + GnssType::GALILEO;\nconst GnssType GnssType::L6_E      = GnssType::PHASE + GnssType::E6                + GnssType::GALILEO;\n\nconst GnssType GnssType::C2IC      = GnssType::RANGE + GnssType::B1  + GnssType::I + GnssType::BDS;\nconst GnssType GnssType::C2QC      = GnssType::RANGE + GnssType::B1  + GnssType::Q + GnssType::BDS;\nconst GnssType GnssType::C2XC      = GnssType::RANGE + GnssType::B1  + GnssType::X + GnssType::BDS;\nconst GnssType GnssType::C1DC      = GnssType::RANGE + GnssType::B1C + GnssType::D + GnssType::BDS;\nconst GnssType GnssType::C1PC      = GnssType::RANGE + GnssType::B1C + GnssType::P + GnssType::BDS;\nconst GnssType GnssType::C1XC      = GnssType::RANGE + GnssType::B1C + GnssType::X + GnssType::BDS;\nconst GnssType GnssType::C1SC      = GnssType::RANGE + GnssType::B1C + GnssType::S + GnssType::BDS;\nconst GnssType GnssType::C1LC      = GnssType::RANGE + GnssType::B1C + GnssType::L + GnssType::BDS;\nconst GnssType GnssType::C1ZC      = GnssType::RANGE + GnssType::B1C + GnssType::Z + GnssType::BDS;\nconst GnssType GnssType::C5DC      = GnssType::RANGE + GnssType::B2a + GnssType::D + GnssType::BDS;\nconst GnssType GnssType::C5PC      = GnssType::RANGE + GnssType::B2a + GnssType::P + GnssType::BDS;\nconst GnssType GnssType::C5XC      = GnssType::RANGE + GnssType::B2a + GnssType::X + GnssType::BDS;\nconst GnssType GnssType::C7IC      = GnssType::RANGE + GnssType::B2b + GnssType::I + GnssType::BDS;\nconst GnssType GnssType::C7QC      = GnssType::RANGE + GnssType::B2b + GnssType::Q + GnssType::BDS;\nconst GnssType GnssType::C7XC      = GnssType::RANGE + GnssType::B2b + GnssType::X + GnssType::BDS;\nconst GnssType GnssType::C7DC      = GnssType::RANGE + GnssType::B2b + GnssType::D + GnssType::BDS;\nconst GnssType GnssType::C7PC      = GnssType::RANGE + GnssType::B2b + GnssType::P + GnssType::BDS;\nconst GnssType GnssType::C7ZC      = GnssType::RANGE + GnssType::B2b + GnssType::Z + GnssType::BDS;\nconst GnssType GnssType::C8DC      = GnssType::RANGE + GnssType::B2  + GnssType::D + GnssType::BDS;\nconst GnssType GnssType::C8PC      = GnssType::RANGE + GnssType::B2  + GnssType::P + GnssType::BDS;\nconst GnssType GnssType::C8XC      = GnssType::RANGE + GnssType::B2  + GnssType::X + GnssType::BDS;\nconst GnssType GnssType::C6IC      = GnssType::RANGE + GnssType::B3  + GnssType::I + GnssType::BDS;\nconst GnssType GnssType::C6QC      = GnssType::RANGE + GnssType::B3  + GnssType::Q + GnssType::BDS;\nconst GnssType GnssType::C6XC      = GnssType::RANGE + GnssType::B3  + GnssType::X + GnssType::BDS;\nconst GnssType GnssType::C6DC      = GnssType::RANGE + GnssType::B3  + GnssType::D + GnssType::BDS;\nconst GnssType GnssType::C6PC      = GnssType::RANGE + GnssType::B3  + GnssType::P + GnssType::BDS;\nconst GnssType GnssType::C6ZC      = GnssType::RANGE + GnssType::B3  + GnssType::Z + GnssType::BDS;\nconst GnssType GnssType::L2_C      = GnssType::PHASE + GnssType::B1                + GnssType::BDS;\nconst GnssType GnssType::L1_C      = GnssType::PHASE + GnssType::B1C               + GnssType::BDS;\nconst GnssType GnssType::L5_C      = GnssType::PHASE + GnssType::B2a               + GnssType::BDS;\nconst GnssType GnssType::L7_C      = GnssType::PHASE + GnssType::B2b               + GnssType::BDS;\nconst GnssType GnssType::L8_C      = GnssType::PHASE + GnssType::B2                + GnssType::BDS;\nconst GnssType GnssType::L6_C      = GnssType::PHASE + GnssType::B3                + GnssType::BDS;\n\nconst GnssType GnssType::C1CJ      = GnssType::RANGE + GnssType::L1  + GnssType::C + GnssType::QZSS;\nconst GnssType GnssType::C1EJ      = GnssType::RANGE + GnssType::L1  + GnssType::E + GnssType::QZSS;\nconst GnssType GnssType::C1SJ      = GnssType::RANGE + GnssType::L1  + GnssType::S + GnssType::QZSS;\nconst GnssType GnssType::C1LJ      = GnssType::RANGE + GnssType::L1  + GnssType::L + GnssType::QZSS;\nconst GnssType GnssType::C1XJ      = GnssType::RANGE + GnssType::L1  + GnssType::X + GnssType::QZSS;\nconst GnssType GnssType::C1ZJ      = GnssType::RANGE + GnssType::L1  + GnssType::Z + GnssType::QZSS;\nconst GnssType GnssType::C1BJ      = GnssType::RANGE + GnssType::L1  + GnssType::B + GnssType::QZSS;\nconst GnssType GnssType::C2SJ      = GnssType::RANGE + GnssType::L2  + GnssType::S + GnssType::QZSS;\nconst GnssType GnssType::C2LJ      = GnssType::RANGE + GnssType::L2  + GnssType::L + GnssType::QZSS;\nconst GnssType GnssType::C2XJ      = GnssType::RANGE + GnssType::L2  + GnssType::X + GnssType::QZSS;\nconst GnssType GnssType::C5IJ      = GnssType::RANGE + GnssType::L5  + GnssType::I + GnssType::QZSS;\nconst GnssType GnssType::C5QJ      = GnssType::RANGE + GnssType::L5  + GnssType::Q + GnssType::QZSS;\nconst GnssType GnssType::C5XJ      = GnssType::RANGE + GnssType::L5  + GnssType::X + GnssType::QZSS;\nconst GnssType GnssType::C5DJ      = GnssType::RANGE + GnssType::L5  + GnssType::D + GnssType::QZSS;\nconst GnssType GnssType::C5PJ      = GnssType::RANGE + GnssType::L5  + GnssType::P + GnssType::QZSS;\nconst GnssType GnssType::C5ZJ      = GnssType::RANGE + GnssType::L5  + GnssType::Z + GnssType::QZSS;\nconst GnssType GnssType::C6SJ      = GnssType::RANGE + GnssType::L6  + GnssType::S + GnssType::QZSS;\nconst GnssType GnssType::C6LJ      = GnssType::RANGE + GnssType::L6  + GnssType::L + GnssType::QZSS;\nconst GnssType GnssType::C6XJ      = GnssType::RANGE + GnssType::L6  + GnssType::X + GnssType::QZSS;\nconst GnssType GnssType::C6EJ      = GnssType::RANGE + GnssType::L6  + GnssType::E + GnssType::QZSS;\nconst GnssType GnssType::C6ZJ      = GnssType::RANGE + GnssType::L6  + GnssType::Z + GnssType::QZSS;\nconst GnssType GnssType::L1_J      = GnssType::PHASE + GnssType::L1                + GnssType::QZSS;\nconst GnssType GnssType::L2_J      = GnssType::PHASE + GnssType::L2                + GnssType::QZSS;\nconst GnssType GnssType::L5_J      = GnssType::PHASE + GnssType::L5                + GnssType::QZSS;\nconst GnssType GnssType::L6_J      = GnssType::PHASE + GnssType::L6                + GnssType::QZSS;\n\n/***********************************************/\n\nGnssType::GnssType(const std::string &str)\n{\n  try\n  {\n    type = 0;\n    if(str.size()<=0)\n      return;\n\n    switch(str.at(0))\n    {\n      case 'C': type += RANGE.type;     break;\n      case 'L': type += PHASE.type;     break;\n      case 'D': type += DOPPLER.type;   break;\n      case 'S': type += SNR.type;       break;\n      case 'A': type += AZIMUT.type;    break;\n      case 'E': type += ELEVATION.type; break;\n      case 'I': type += IONODELAY.type; break;\n      case 'X': type += CHANNEL.type;   break;\n      case 'R': type += ROTI.type;      break;\n      case 'P': type += IONOINDEX.type; break;\n      case '*': break;\n      default:\n        throw(Exception(\"Unknown GnssType string: \"+str));\n    }\n    if(str.size()<=1)\n      return;\n\n    switch(str.at(1))\n    {\n      case '1': type += L1.type;   break;\n      case '2': type += L2.type;   break;\n      case '3': type += G3.type;   break;\n      case '4': type += G1a.type;  break;\n      case '5': type += L5.type;   break;\n      case '6': type += E6.type;   break;\n      case '7': type += E5b.type;  break;\n      case '8': type += E5.type;   break;\n      case '9': type += S9.type;   break;\n      case '*': break;\n      default:\n        throw(Exception(\"Unknown GnssType string: \"+str));\n    }\n    if(str.size()<=2)\n      return;\n\n    switch(str.at(2))\n    {\n      case 'C': type += C.type; break;\n      case 'W': type += W.type; break;\n      case 'D': type += D.type; break;\n      case 'X': type += X.type; break;\n      case 'S': type += S.type; break;\n      case 'L': type += L.type; break;\n      case 'I': type += I.type; break;\n      case 'Q': type += Q.type; break;\n      case 'A': type += A.type; break;\n      case 'B': type += B.type; break;\n      case 'Z': type += Z.type; break;\n      case 'P': type += P.type; break;\n      case 'Y': type += Y.type; break;\n      case 'M': type += M.type; break;\n      case 'E': type += E.type; break;\n      case '?': type += UNKNOWN_ATTRIBUTE.type; break;\n      case '*': break;\n      default:\n        throw(Exception(\"Unknown GnssType string: \"+str));\n    }\n    if(str.size()<=3)\n      return;\n\n    switch(str.at(3))\n    {\n      case 'G': type += GPS.type;     break;\n      case 'R': type += GLONASS.type; break;\n      case 'E': type += GALILEO.type; break;\n      case 'C': type += BDS.type;     break;\n      case 'S': type += SBAS.type;    break;\n      case 'J': type += QZSS.type;    break;\n      case 'I': type += IRNSS.type;   break;\n      case '*': break;\n      default:\n        throw(Exception(\"Unknown GnssType string: \"+str));\n    }\n    if(str.size()<=4)\n      return;\n\n    if(str.at(4)!='*')\n    {\n      UInt prn;\n      std::stringstream ss(str.substr(4,2));\n      ss>>prn;\n      type += prn;\n    }\n\n    // GLONASS frequency number\n    if(str.size()>6 && 'A'<=str.at(6) && str.at(6)<='Z')\n      setFrequencyNumber(str.at(6)-'A'-7);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string GnssType::str() const\n{\n  try\n  {\n    std::stringstream ss;\n\n    if     ((type & TYPE.type) == RANGE.type)     ss<<'C';\n    else if((type & TYPE.type) == PHASE.type)     ss<<'L';\n    else if((type & TYPE.type) == DOPPLER.type)   ss<<'D';\n    else if((type & TYPE.type) == SNR.type)       ss<<'S';\n    else if((type & TYPE.type) == AZIMUT.type)    ss<<'A';\n    else if((type & TYPE.type) == ELEVATION.type) ss<<'E';\n    else if((type & TYPE.type) == IONODELAY.type) ss<<'I';\n    else if((type & TYPE.type) == CHANNEL.type)   ss<<'X';\n    else if((type & TYPE.type) == ROTI.type)      ss<<'R';\n    else if((type & TYPE.type) == IONOINDEX.type) ss<<'P';\n    else if((type & TYPE.type) == 0)              ss<<'*';\n    else ss<<'?';\n\n\n    if     ((type & FREQUENCY.type) == L1.type)   ss<<'1';\n    else if((type & FREQUENCY.type) == L2.type)   ss<<'2';\n    else if((type & FREQUENCY.type) == L5.type)   ss<<'5';\n    else if((type & FREQUENCY.type) == E5b.type)  ss<<'7';\n    else if((type & FREQUENCY.type) == E5.type)   ss<<'8';\n    else if((type & FREQUENCY.type) == E6.type)   ss<<'6';\n    else if((type & FREQUENCY.type) == G3.type)   ss<<'3';\n    else if((type & FREQUENCY.type) == G1a.type)  ss<<'4';\n    else if((type & FREQUENCY.type) == S9.type)   ss<<'9';\n    else if((type & FREQUENCY.type) == 0)         ss<<'*';\n    else ss<<'?';\n\n    if     ((type & ATTRIBUTE.type) == C.type) ss<<'C';\n    else if((type & ATTRIBUTE.type) == W.type) ss<<'W';\n    else if((type & ATTRIBUTE.type) == D.type) ss<<'D';\n    else if((type & ATTRIBUTE.type) == X.type) ss<<'X';\n    else if((type & ATTRIBUTE.type) == S.type) ss<<'S';\n    else if((type & ATTRIBUTE.type) == L.type) ss<<'L';\n    else if((type & ATTRIBUTE.type) == I.type) ss<<'I';\n    else if((type & ATTRIBUTE.type) == Q.type) ss<<'Q';\n    else if((type & ATTRIBUTE.type) == A.type) ss<<'A';\n    else if((type & ATTRIBUTE.type) == B.type) ss<<'B';\n    else if((type & ATTRIBUTE.type) == Z.type) ss<<'Z';\n    else if((type & ATTRIBUTE.type) == P.type) ss<<'P';\n    else if((type & ATTRIBUTE.type) == Y.type) ss<<'Y';\n    else if((type & ATTRIBUTE.type) == M.type) ss<<'M';\n    else if((type & ATTRIBUTE.type) == E.type) ss<<'E';\n    else if((type & ATTRIBUTE.type) == UNKNOWN_ATTRIBUTE.type) ss<<'?';\n    else if((type & ATTRIBUTE.type) == 0)      ss<<'*';\n    else ss<<'?';\n\n    if     ((type & SYSTEM.type) == GPS.type)     ss<<'G';\n    else if((type & SYSTEM.type) == GLONASS.type) ss<<'R';\n    else if((type & SYSTEM.type) == GALILEO.type) ss<<'E';\n    else if((type & SYSTEM.type) == BDS.type)     ss<<'C';\n    else if((type & SYSTEM.type) == SBAS.type)    ss<<'S';\n    else if((type & SYSTEM.type) == QZSS.type)    ss<<'J';\n    else if((type & SYSTEM.type) == IRNSS.type)   ss<<'I';\n    else if((type & SYSTEM.type) == 0)            ss<<'*';\n    else ss<<'?';\n\n    if((type & PRN.type) == 0)\n      ss<<\"**\";\n    else\n      ss<<prn()%\"%02i\"s;\n\n    if(frequencyNumber() != 9999)\n      ss<<static_cast<Char>(frequencyNumber()+7+'A');\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nDouble GnssType::frequency() const\n{\n  try\n  {\n    if((*this==GPS) || (*this==SBAS) || (*this==GALILEO) || (*this==QZSS) || (*this==IRNSS))\n    {\n      if     (*this == L1)  return 1575.42e6;\n      else if(*this == L2)  return 1227.60e6;\n      else if(*this == L5)  return 1176.45e6;\n      else if(*this == E5b) return 1207.140e6;\n      else if(*this == E5)  return 1191.795e6;\n      else if(*this == E6)  return 1278.75e6;\n      else if(*this == S9)  return 2492.028e6;\n    }\n    else if(*this==GLONASS)\n    {\n      if((*this == G1 || *this == G2) && frequencyNumber() == 9999)\n        throw(Exception(str()+\": GLONASS frequency number not set\"));\n      if     (*this == G1)  return 1602e6 + frequencyNumber()*9e6/16;\n      else if(*this == G1a) return 1600.995e6;\n      else if(*this == G2)  return 1246e6 + frequencyNumber()*7e6/16;\n      else if(*this == G2a) return 1248.06e6;\n      else if(*this == G3)  return 1202.025e6;\n    }\n    else if(*this==BDS)\n    {\n      if     (*this == B1C)  return 1575.42e6;\n      else if(*this == B1)   return 1561.098e6;\n      else if(*this == B2)   return 1191.795e6;\n      else if(*this == B2a)  return 1176.45e6;\n      else if(*this == B2b)  return 1207.14e6;\n      else if(*this == B3)   return 1268.52e6;\n    }\n    throw(Exception(str()+\": frequency unknown\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssType::wavelength() const\n{\n  return LIGHT_VELOCITY/frequency();\n}\n\n/***********************************************/\n\nInt GnssType::frequencyNumber() const\n{\n  if(!(type & FREQ_NO.type))\n    return 9999;\n  return static_cast<Int>((type & FREQ_NO.type)>>32)-8;\n}\n\n/***********************************************/\n\nvoid GnssType::setFrequencyNumber(Int number)\n{\n  type &= ~FREQ_NO.type;\n  if((-7 <= number) && (number <= 255-8))\n    type += (static_cast<UInt64>(number+8)<<32) & FREQ_NO.type;\n}\n\n/***********************************************/\n\nDouble GnssType::ionosphericFactor() const\n{\n  try\n  {\n    if(*this == GnssType::PHASE)\n      return -Ionosphere::Ap/std::pow(frequency(), 2);\n    if(*this == GnssType::RANGE)\n      return +Ionosphere::Ap/std::pow(frequency(), 2);\n    throw(Exception(\"only defined for PHASE and RANGE\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssType::isInList(const std::vector<GnssType> &types) const\n{\n  return (index(types, *this) != NULLINDEX);\n}\n\n/***********************************************/\n\nBool GnssType::isInList(const std::vector<GnssType> &types, UInt &idx) const\n{\n  idx = index(types, *this);\n  return (idx != NULLINDEX);\n}\n\n/***********************************************/\n\nUInt GnssType::index(const std::vector<GnssType> &types, GnssType type)\n{\n  for(UInt i=0; i<types.size(); i++)\n    if(type == types.at(i))\n      return i;\n  return NULLINDEX;\n}\n\n/***********************************************/\n\nBool GnssType::allEqual(const std::vector<GnssType> &types1, const std::vector<GnssType> &types2, GnssType mask)\n{\n  try\n  {\n    if(types1.size() != types2.size())\n      return FALSE;\n    for(UInt i=0; i<types1.size(); i++)\n      if(index(types2, types1.at(i) & mask) == NULLINDEX)\n        return FALSE;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<GnssType> GnssType::replaceCompositeSignals(const std::vector<GnssType> &typesIn)\n{\n  try\n  {\n    std::vector<GnssType> types;\n\n    for(GnssType t : typesIn)\n      if((t == GnssType::PHASE) || (t == GnssType::RANGE)) // only phase and code signals are transmitted (what about doppler?)\n      {\n        GnssType prn = t & GnssType::PRN;\n        if(t == GnssType::PHASE)\n          types.push_back( t & ~GnssType::ATTRIBUTE );\n        else if(t == GnssType::C2DG) {types.push_back(GnssType::C1CG + prn); types.push_back(GnssType::C1WG + prn); types.push_back(GnssType::C2WG + prn);}\n        else if(t == GnssType::C1XG) {types.push_back(GnssType::C1SG + prn); types.push_back(GnssType::C1LG + prn);}\n        else if(t == GnssType::C2XG) {types.push_back(GnssType::C2SG + prn); types.push_back(GnssType::C2LG + prn);}\n        else if(t == GnssType::C5XG) {types.push_back(GnssType::C5IG + prn); types.push_back(GnssType::C5QG + prn);}\n\n        else if(t == GnssType::C4XR) {types.push_back(GnssType::C4AR + prn); types.push_back(GnssType::C4BR + prn);}\n        else if(t == GnssType::C6XR) {types.push_back(GnssType::C6AR + prn); types.push_back(GnssType::C6BR + prn);}\n        else if(t == GnssType::C3XR) {types.push_back(GnssType::C3IR + prn); types.push_back(GnssType::C3QR + prn);}\n\n        else if(t == GnssType::C1XE) {types.push_back(GnssType::C1BE + prn); types.push_back(GnssType::C1CE + prn);}\n        else if(t == GnssType::C1ZE) {types.push_back(GnssType::C1AE + prn); types.push_back(GnssType::C1BE + prn); types.push_back(GnssType::C1CE + prn);}\n        else if(t == GnssType::C5XE) {types.push_back(GnssType::C5IE + prn); types.push_back(GnssType::C5QE + prn);}\n        else if(t == GnssType::C7XE) {types.push_back(GnssType::C7IE + prn); types.push_back(GnssType::C7QE + prn);}\n        else if(t == GnssType::C8XE) {types.push_back(GnssType::C8IE + prn); types.push_back(GnssType::C8QE + prn);}\n        else if(t == GnssType::C6XE) {types.push_back(GnssType::C6BE + prn); types.push_back(GnssType::C6CE + prn);}\n        else if(t == GnssType::C6ZE) {types.push_back(GnssType::C6AE + prn); types.push_back(GnssType::C6BE + prn); types.push_back(GnssType::C6CE + prn);}\n\n        else if(t == GnssType::C2XC) {types.push_back(GnssType::C2IC + prn); types.push_back(GnssType::C2QC + prn);}\n        else if(t == GnssType::C1XC) {types.push_back(GnssType::C1DC + prn); types.push_back(GnssType::C1PC + prn);}\n        else if(t == GnssType::C1ZC) {types.push_back(GnssType::C1SC + prn); types.push_back(GnssType::C1LC + prn);}\n        else if(t == GnssType::C5XC) {types.push_back(GnssType::C5DC + prn); types.push_back(GnssType::C5PC + prn);}\n        else if(t == GnssType::C7XC) {types.push_back(GnssType::C7IC + prn); types.push_back(GnssType::C7QC + prn);}\n        else if(t == GnssType::C7ZC) {types.push_back(GnssType::C7DC + prn); types.push_back(GnssType::C7PC + prn);}\n        else if(t == GnssType::C8XC) {types.push_back(GnssType::C8DC + prn); types.push_back(GnssType::C8PC + prn);}\n        else if(t == GnssType::C6XC) {types.push_back(GnssType::C6IC + prn); types.push_back(GnssType::C6QC + prn);}\n        else if(t == GnssType::C6ZC) {types.push_back(GnssType::C6DC + prn); types.push_back(GnssType::C6PC + prn);}\n\n        else if(t == GnssType::C1XJ) {types.push_back(GnssType::C1SJ + prn); types.push_back(GnssType::C1LJ + prn);}\n        else if(t == GnssType::C2XJ) {types.push_back(GnssType::C2SJ + prn); types.push_back(GnssType::C2LJ + prn);}\n        else if(t == GnssType::C5XJ) {types.push_back(GnssType::C5IJ + prn); types.push_back(GnssType::C5QJ + prn);}\n        else if(t == GnssType::C5ZJ) {types.push_back(GnssType::C5DJ + prn); types.push_back(GnssType::C5PJ + prn);}\n        else if(t == GnssType::C6XJ) {types.push_back(GnssType::C6SJ + prn); types.push_back(GnssType::C6LJ + prn);}\n        else if(t == GnssType::C6ZJ) {types.push_back(GnssType::C6SJ + prn); types.push_back(GnssType::C6EJ + prn);}\n\n        // unknown attributes\n        else if(t == GnssType::C2UG) {types.push_back(GnssType::C2SG + prn); types.push_back(GnssType::C2LG + prn);}\n        else if(t == GnssType::C5UG) {types.push_back(GnssType::C5IG + prn); types.push_back(GnssType::C5QG + prn);}\n        else if(t == GnssType::C1UE) {types.push_back(GnssType::C1BE + prn); types.push_back(GnssType::C1CE + prn);}\n        else if(t == GnssType::C5UE) {types.push_back(GnssType::C5IE + prn); types.push_back(GnssType::C5QE + prn);}\n        else if(t == GnssType::C7UE) {types.push_back(GnssType::C7IE + prn); types.push_back(GnssType::C7QE + prn);}\n        else if(t == GnssType::C8UE) {types.push_back(GnssType::C8IE + prn); types.push_back(GnssType::C8QE + prn);}\n        else if(t == GnssType::C6UE) {types.push_back(GnssType::C6BE + prn); types.push_back(GnssType::C6CE + prn);}\n        else\n          types.push_back(t);\n      }\n\n    std::sort(types.begin(), types.end());\n    types.erase(std::unique(types.begin(), types.end()), types.end()); // remove duplicates\n    return types;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssType::hasWildcard(GnssType mask) const\n{\n  return ((mask.type & TYPE.type)      && !(type & TYPE.type))      ||\n         ((mask.type & FREQUENCY.type) && !(type & FREQUENCY.type)) ||\n         ((mask.type & ATTRIBUTE.type) && !(type & ATTRIBUTE.type)) ||\n         ((mask.type & SYSTEM.type)    && !(type & SYSTEM.type))    ||\n         ((mask.type & PRN.type)       && !(type & PRN.type))       ||\n         ((mask.type & FREQ_NO.type)   && !(type & FREQ_NO.type));\n}\n\n/***********************************************/\n\nGnssType &GnssType::operator+=(const GnssType &t)\n{\n  try\n  {\n    if(((type & TYPE.type)      && (t.type & TYPE.type)      && (type & TYPE.type)       != (t.type & TYPE.type))       ||\n       ((type & FREQUENCY.type) && (t.type & FREQUENCY.type) && ((type & FREQUENCY.type) != (t.type & FREQUENCY.type))) ||\n       ((type & SYSTEM.type)    && (t.type & SYSTEM.type)    && ((type & SYSTEM.type)    != (t.type & SYSTEM.type)))    ||\n       ((type & ATTRIBUTE.type) && (t.type & ATTRIBUTE.type) && ((type & ATTRIBUTE.type) != (t.type & ATTRIBUTE.type))) ||\n       ((type & PRN.type)       && (t.type & PRN.type)       && ((type & PRN.type)       != (t.type & PRN.type)))       ||\n       ((type & FREQ_NO.type)   && (t.type & FREQ_NO.type)   && ((type & FREQ_NO.type)   != (t.type & FREQ_NO.type))))\n      throw(Exception(\"Incompatible addition: \"+str()+\" + \"+t.str()));\n\n    type |= t.type;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssType &GnssType::operator&=(const GnssType &t)\n{\n  type &= t.type;\n  return *this;\n}\n\n/***********************************************/\n\nGnssType GnssType::operator~() const\n{\n  return GnssType(~type);\n}\n\n/***********************************************/\n\nBool GnssType::operator==(const GnssType &t) const\n{\n  if(type == t.type) return TRUE;\n  if((type & SYSTEM.type)    && (t.type & SYSTEM.type)    && ((type & SYSTEM.type)    != (t.type & SYSTEM.type)))    return FALSE;\n  if((type & FREQUENCY.type) && (t.type & FREQUENCY.type) && ((type & FREQUENCY.type) != (t.type & FREQUENCY.type))) return FALSE;\n  if((type & TYPE.type)      && (t.type & TYPE.type)      && ((type & TYPE.type)      != (t.type & TYPE.type)))      return FALSE;\n  if((type & ATTRIBUTE.type) && (t.type & ATTRIBUTE.type) && ((type & ATTRIBUTE.type) != (t.type & ATTRIBUTE.type))) return FALSE;\n  if((type & PRN.type)       && (t.type & PRN.type)       && ((type & PRN.type)       != (t.type & PRN.type)))       return FALSE;\n  if((type & FREQ_NO.type)   && (t.type & FREQ_NO.type)   && ((type & FREQ_NO.type)   != (t.type & FREQ_NO.type)))   return FALSE;\n  return TRUE;\n}\n\n/***********************************************/\n\nBool GnssType::operator<(const GnssType &t) const\n{\n  if((type & SYSTEM.type)    != (t.type & SYSTEM.type))    return ((t.type & SYSTEM.type)    == 0) || (((type & SYSTEM.type)    != 0) && ((type & SYSTEM.type)    < (t.type & SYSTEM.type)));\n  if((type & TYPE.type)      != (t.type & TYPE.type))      return ((t.type & TYPE.type)      == 0) || (((type & TYPE.type)      != 0) && ((type & TYPE.type)      < (t.type & TYPE.type)));\n  if((type & FREQUENCY.type) != (t.type & FREQUENCY.type)) return ((t.type & FREQUENCY.type) == 0) || (((type & FREQUENCY.type) != 0) && ((type & FREQUENCY.type) < (t.type & FREQUENCY.type)));\n  if((type & ATTRIBUTE.type) != (t.type & ATTRIBUTE.type)) return ((t.type & ATTRIBUTE.type) == 0) || (((type & ATTRIBUTE.type) != 0) && ((type & ATTRIBUTE.type) < (t.type & ATTRIBUTE.type)));\n  if((type & PRN.type)       != (t.type & PRN.type))       return ((t.type & PRN.type)       == 0) || (((type & PRN.type)       != 0) && ((type & PRN.type)       < (t.type & PRN.type)));\n  if((type & FREQ_NO.type)   != (t.type & FREQ_NO.type))   return ((t.type & FREQ_NO.type)   == 0) || (((type & FREQ_NO.type)   != 0) && ((type & FREQ_NO.type)   < (t.type & FREQ_NO.type)));\n  return FALSE;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/gnssType.h",
    "content": "/***********************************************/\n/**\n* @file gnssType.h\n*\n* @brief Defines a GNSS observation type according to the RINEX 3 definition.\n*\n* Due to the strict weak ordering requirement, wildcard matching is not supported for e.g. sets or maps.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-04-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSTYPE__\n#define __GROOPS_GNSSTYPE__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssType\nstatic const char *docstringGnssType = R\"(\n\\section{GnssType}\\label{gnssType}\nA GnssType string consists of six parts (type, frequency, attribute, system, PRN, frequency number)\nrepresented by seven characters.\n\\begin{itemize}\n\\item The first three characters (representing type, frequency, and attribute) correspond to the observation codes of the\n      \\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition}.\n\\item The satellite system character also follows the RINEX 3 definition:\n      \\begin{itemize}\n        \\item \\verb|G| = GPS\n        \\item \\verb|R| = GLONASS\n        \\item \\verb|E| = Galileo\n        \\item \\verb|C| = BeiDou\n        \\item \\verb|S| = SBAS\n        \\item \\verb|J| = QZSS\n        \\item \\verb|I| = IRNSS\n      \\end{itemize}\n\\item PRN is a two-digit number identifying a satellite.\n\\item Frequency number is only used for GLONASS, where the range -7 to 14 is represented by letters starting with A.\n\\end{itemize}\n\nEach part of a GnssType string can be replaced by a wildcard '\\verb|*|', enabling the use of these strings as patterns,\nfor example to select a subset of observations (e.g. \\verb|C**G**| matches all GPS code/range observations).\nTrailing wildcards are optional, meaning \\verb|L1*R| is automatically expanded to \\verb|L1*R***|.\nFor some RINEX 2 types (e.g. Galileo L5) the RINEX 3 attribute is unknown/undefined and can be replaced by \\verb|?|,\nfor example \\verb|L5?E01|.\n\nExamples:\n\\begin{itemize}\n\\item \\verb|C1CG23| = code/range observation, L1 frequency, derived from C/A code, GPS, PRN 23\n\\item \\verb|L2PR05B| = phase observation, G2 frequency, derived from P code, GLONASS, PRN 05, frequency number -6\n\\item \\verb|*5*E**| = all observation types, E5a frequency, all attributes, Galileo, all PRNs\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/importStd.h\"\n\n/***** CLASS ***********************************/\n\n/**\n* @brief Defines a GNSS observation type according to the RINEX 3 definition.\n* @ingroup base\n*\n* Due to the strict weak ordering requirement, wildcard matching is not supported for e.g. sets or maps. */\nclass GnssType\n{\npublic:\n  /// Bit masks\n  static const GnssType PRN;        ///< satellite identification number (PRN, SBAS-100, ...)\n  static const GnssType SYSTEM;     ///< satellite system (GPS, GLONASS, ...)\n  static const GnssType FREQUENCY;  ///< frequency\n  static const GnssType TYPE;       ///< phase, range, doppler, ...\n  static const GnssType ATTRIBUTE;  ///< attribute\n  static const GnssType FREQ_NO;    ///< GLONASS frequency number\n  static const GnssType ALL;        ///< = TYPE + FREQUENCY + ATTRIBUTE + SYSTEM + PRN + GLO_FREQ_NO\n  static const GnssType NOPRN;      ///< = TYPE + FREQUENCY + ATTRIBUTE + SYSTEM       + GLO_FREQ_NO\n  /// system\n  static const GnssType GPS;\n  static const GnssType GLONASS;\n  static const GnssType GALILEO;\n  static const GnssType BDS;\n  static const GnssType SBAS;\n  static const GnssType QZSS;\n  static const GnssType IRNSS;\n  /// frequency\n  static const GnssType L1;   ///< GPS\n  static const GnssType L2;\n  static const GnssType L5;\n  static const GnssType E1;   ///< GALILEO\n  static const GnssType E5a;\n  static const GnssType E5b;\n  static const GnssType E5;\n  static const GnssType E6;\n  static const GnssType G1;   ///< GLONASS\n  static const GnssType G1a;\n  static const GnssType G2;\n  static const GnssType G2a;\n  static const GnssType G3;\n  static const GnssType B1;   ///< BDS\n  static const GnssType B1C;\n  static const GnssType B2a;\n  static const GnssType B2b;\n  static const GnssType B2;\n  static const GnssType B3;\n  static const GnssType L6;   ///< QZSS\n  static const GnssType S9;   ///< IRNSS S\n  /// observation type\n  static const GnssType RANGE;\n  static const GnssType PHASE;\n  static const GnssType DOPPLER;\n  static const GnssType SNR;\n  static const GnssType IONODELAY;\n  static const GnssType CHANNEL;\n  static const GnssType AZIMUT;     ///< FREQUENCY L1: receiver, L2: transmitter\n  static const GnssType ELEVATION;  ///< FREQUENCY L1: receiver, L2: transmitter\n  static const GnssType ROTI;       ///< Rate of Tec Index\n  static const GnssType IONOINDEX;  ///< Ionospheric index (sigma_phi)\n  /// attributes\n  static const GnssType C;          ///< C/A - Code\n  static const GnssType W;          ///< P Z-tracking and similar (AS on)\n  static const GnssType D;          ///< L1(C/A)+(P2-P1) (semi-codeless)\n  static const GnssType X;\n  static const GnssType S;\n  static const GnssType L;\n  static const GnssType I;\n  static const GnssType Q;\n  static const GnssType A;\n  static const GnssType B;\n  static const GnssType Z;\n  static const GnssType P;         ///< military P (AS off) - Code\n  static const GnssType Y;         ///< military\n  static const GnssType M;         ///< military\n  static const GnssType E;\n  static const GnssType UNKNOWN_ATTRIBUTE;\n\n  static const GnssType C1CG;\n  static const GnssType C1SG;\n  static const GnssType C1LG;\n  static const GnssType C1XG;\n  static const GnssType C1WG;\n  static const GnssType C2CG;\n  static const GnssType C2DG;\n  static const GnssType C2SG;\n  static const GnssType C2LG;\n  static const GnssType C2XG;\n  static const GnssType C2WG;\n  static const GnssType C2UG;      ///< unknown attribute (RINEX 2)\n  static const GnssType C5IG;\n  static const GnssType C5QG;\n  static const GnssType C5XG;\n  static const GnssType C5UG;      ///< unknown attribute (RINEX 2)\n  static const GnssType L1_G;\n  static const GnssType L2_G;\n  static const GnssType L5_G;\n\n  static const GnssType C1CR;\n  static const GnssType C1PR;\n  static const GnssType C4AR;\n  static const GnssType C4BR;\n  static const GnssType C4XR;\n  static const GnssType C2CR;\n  static const GnssType C2PR;\n  static const GnssType C6AR;\n  static const GnssType C6BR;\n  static const GnssType C6XR;\n  static const GnssType C3IR;\n  static const GnssType C3QR;\n  static const GnssType C3XR;\n  static const GnssType L1_R;\n  static const GnssType L4_R;\n  static const GnssType L2_R;\n  static const GnssType L6_R;\n  static const GnssType L3_R;\n\n  static const GnssType C1AE;\n  static const GnssType C1BE;\n  static const GnssType C1CE;\n  static const GnssType C1XE;\n  static const GnssType C1ZE;\n  static const GnssType C1UE;      ///< unknown attribute (RINEX 2)\n  static const GnssType C5IE;\n  static const GnssType C5QE;\n  static const GnssType C5XE;\n  static const GnssType C5UE;      ///< unknown attribute (RINEX 2)\n  static const GnssType C7IE;\n  static const GnssType C7QE;\n  static const GnssType C7XE;\n  static const GnssType C7UE;      ///< unknown attribute (RINEX 2)\n  static const GnssType C8IE;\n  static const GnssType C8QE;\n  static const GnssType C8XE;\n  static const GnssType C8UE;      ///< unknown attribute (RINEX 2)\n  static const GnssType C6AE;\n  static const GnssType C6BE;\n  static const GnssType C6CE;\n  static const GnssType C6XE;\n  static const GnssType C6ZE;\n  static const GnssType C6UE;      ///< unknown attribute (RINEX 2)\n  static const GnssType L1_E;\n  static const GnssType L5_E;\n  static const GnssType L7_E;\n  static const GnssType L8_E;\n  static const GnssType L6_E;\n\n  static const GnssType C2IC;\n  static const GnssType C2QC;\n  static const GnssType C2XC;\n  static const GnssType C1DC;\n  static const GnssType C1PC;\n  static const GnssType C1XC;\n  static const GnssType C1SC;\n  static const GnssType C1LC;\n  static const GnssType C1ZC;\n  static const GnssType C5DC;\n  static const GnssType C5PC;\n  static const GnssType C5XC;\n  static const GnssType C7IC;\n  static const GnssType C7QC;\n  static const GnssType C7XC;\n  static const GnssType C7DC;\n  static const GnssType C7PC;\n  static const GnssType C7ZC;\n  static const GnssType C8DC;\n  static const GnssType C8PC;\n  static const GnssType C8XC;\n  static const GnssType C6IC;\n  static const GnssType C6QC;\n  static const GnssType C6XC;\n  static const GnssType C6DC;\n  static const GnssType C6PC;\n  static const GnssType C6ZC;\n  static const GnssType L2_C;\n  static const GnssType L1_C;\n  static const GnssType L5_C;\n  static const GnssType L7_C;\n  static const GnssType L8_C;\n  static const GnssType L6_C;\n\n  static const GnssType C1CJ;\n  static const GnssType C1EJ;\n  static const GnssType C1SJ;\n  static const GnssType C1LJ;\n  static const GnssType C1XJ;\n  static const GnssType C1ZJ;\n  static const GnssType C1BJ;\n  static const GnssType C2SJ;\n  static const GnssType C2LJ;\n  static const GnssType C2XJ;\n  static const GnssType C5IJ;\n  static const GnssType C5QJ;\n  static const GnssType C5XJ;\n  static const GnssType C5DJ;\n  static const GnssType C5PJ;\n  static const GnssType C5ZJ;\n  static const GnssType C6SJ;\n  static const GnssType C6LJ;\n  static const GnssType C6XJ;\n  static const GnssType C6EJ;\n  static const GnssType C6ZJ;\n  static const GnssType L1_J;\n  static const GnssType L2_J;\n  static const GnssType L5_J;\n  static const GnssType L6_J;\n\n  UInt64 type;\n\n  constexpr GnssType() : type(0) {}\n  constexpr explicit GnssType(UInt64 t) : type(t) {}\n  constexpr GnssType(const GnssType &t) : type(t.type) {}\n  explicit GnssType(const std::string &str);\n  GnssType &operator=(const GnssType &t) {type = t.type; return *this;}\n\n  Double      frequency() const;\n  Double      wavelength() const;\n  std::string str() const;\n  std::string prnStr() const {return str().substr(3,3);}\n  UInt        prn() const    {return type & PRN.type;}\n  Int         frequencyNumber() const; ///< GLONASS frequency number (9999 if not set).\n  void        setFrequencyNumber(Int number);\n\n  /** @brief First order STEC influence [m/TECU]. */\n  Double ionosphericFactor() const;\n\n  /** @brief Returns TRUE if calling instance is in the given list. */\n  Bool isInList(const std::vector<GnssType> &types) const;\n\n  /** @brief Returns TRUE if calling instance is in the given list.\n  * Returns the @p index of types vector. If not found NULLINDEX is returned.*/\n  Bool isInList(const std::vector<GnssType> &types, UInt &index) const;\n\n  /** @brief Returns the index of types vector. If not found NULLINDEX is returned. */\n  static UInt index(const std::vector<GnssType> &types, GnssType type);\n\n  /** @brief Returns true if both vectors are of the same size and contain only the same types, independent of sorting. */\n  static Bool allEqual(const std::vector<GnssType> &types1, const std::vector<GnssType> &types2, GnssType mask=GnssType::ALL);\n\n  /** @brief Replaces observed (composed) types by original transmitted types.\n  * Codes replaced e.g. C2DG = C1CG - C1WG + C2CW.\n  * Phase types returned without tracking attribute and all other observations are removed. */\n  static std::vector<GnssType> replaceCompositeSignals(const std::vector<GnssType> &types);\n\n  /** @brief Returns true if a wildcard (*) is used in the parts given by @a mask. */\n  Bool hasWildcard(GnssType mask=GnssType::ALL) const;\n\n  GnssType &operator+=(const GnssType &t);\n  GnssType &operator&=(const GnssType &t);\n  GnssType  operator+ (const GnssType &t) const {GnssType t1(*this); t1+=t; return t1;}\n  GnssType  operator& (const GnssType &t) const {GnssType t1(*this); t1&=t; return t1;}\n  GnssType  operator~ () const;\n\n  /** @brief Returns true if all parts are either the same or match a wildcard. */\n  Bool operator==(const GnssType &t) const;\n\n  /** @brief Returns true if @a this is smaller than @a other or @a other is a wildcard. When used for sorting, wildcards are at the end. */\n  Bool operator< (const GnssType &t) const;\n\n  /** @brief Returns true if any part is neither the same nor matches a wildcard. */\n  Bool operator!=(const GnssType &t) const { return !(*this==t); }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/base/griddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData.cpp\n*\n* @brief Gridded values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"griddedData.h\"\n\n/***********************************************/\n\nvoid GriddedData::init(const GriddedDataRectangular &grid)\n{\n  try\n  {\n    if(!grid.isValid())\n      throw(Exception(\"GriddedDataRectangular is not valid\"));\n\n    std::vector<Double> radius, dLambda, dPhi;\n    std::vector<Angle>  lambda, phi;\n    grid.geocentric(lambda, phi, radius);\n    grid.areaElements(dLambda, dPhi);\n\n    std::vector<Double> cosL(lambda.size()), sinL(lambda.size());\n    for(UInt k=0; k<lambda.size(); k++)\n    {\n      cosL[k] = std::cos(lambda[k]);\n      sinL[k] = std::sin(lambda[k]);\n    }\n\n    ellipsoid = grid.ellipsoid;\n    points.resize(phi.size()*lambda.size());\n    areas.resize(phi.size()*lambda.size());\n    for(UInt i=0; i<phi.size(); i++)\n    {\n      const Double cosPhi = std::cos(phi[i]);\n      const Double sinPhi = std::sin(phi[i]);\n      for(UInt k=0; k<lambda.size(); k++)\n      {\n        points[i*lambda.size()+k] = Vector3d(radius[i]*cosPhi*cosL[k], radius[i]*cosPhi*sinL[k], radius[i]*sinPhi);\n        areas [i*lambda.size()+k] = dLambda[k]*dPhi[i];\n      }\n    }\n\n    // values\n    values.resize(grid.values.size());\n    for(UInt idx=0; idx<values.size(); idx++)\n    {\n      values.at(idx).resize(phi.size()*lambda.size());\n      for(UInt i=0; i<phi.size(); i++)\n        for(UInt k=0; k<lambda.size(); k++)\n          values[idx][i*lambda.size()+k] = grid.values[idx](i,k);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GriddedData::sort()\n{\n  try\n  {\n    std::vector<UInt> index(points.size());\n    std::iota(index.begin(), index.end(), 0);\n    std::stable_sort(index.begin(), index.end(), [&](UInt i, UInt k)\n                     {return (std::fabs(points.at(i).theta()-points.at(k).theta()) < 1e-10) ? // same latitude?\n                             (points.at(i).lambda() < points.at(k).lambda()) :                // sort longitudes\n                             (points.at(i).theta()  < points.at(k).theta());});               // sort latitudes\n\n    // TODO: check regional over date boundary\n\n    auto tmpPoints = points;\n    for(UInt i=0; i<tmpPoints.size(); i++)\n      points.at(i) = tmpPoints.at(index.at(i));\n\n    auto tmpAreas = areas;\n    for(UInt i=0; i<tmpAreas.size(); i++)\n      areas.at(i) = tmpAreas.at(index.at(i));\n\n    for(UInt k=0; k<values.size(); k++)\n    {\n      auto tmpValues = values.at(k);\n      for(UInt i=0; i<tmpValues.size(); i++)\n        values.at(k).at(i) = tmpValues.at(index.at(i));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GriddedData::isRectangle(std::vector<Angle> &lambda, std::vector<Angle> &phi, std::vector<Double> &radius) const\n{\n  try\n  {\n    if(!points.size())\n      return FALSE;\n\n    const Angle  phi1 = points.front().phi();\n    const Double r1   = points.front().r();\n    const Double eps  = 1e-10 * r1;\n\n    // first row\n    lambda.clear();\n    for(UInt i=0; (i<points.size()) && (std::fabs(points.at(i).r()-r1) < eps) && (std::fabs(points.at(i).phi()-phi1) < 1e-10); i++)\n      lambda.push_back(points.at(i).lambda());\n\n    if(points.size() % lambda.size())\n      return FALSE;\n\n    // check points\n    phi.clear();\n    radius.clear();\n    for(UInt i=0; i*lambda.size()<points.size(); i++)\n    {\n      phi.push_back(points.at(i*lambda.size()).phi());\n      radius.push_back(points.at(i*lambda.size()).r());\n      for(UInt k=0; k<lambda.size(); k++)\n        if((points.at(i*lambda.size()+k)-polar(lambda.at(k), phi.at(i), radius.at(i))).r() > eps)\n          return FALSE;\n    }\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GriddedData::computeArea()\n{\n  try\n  {\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius;\n    if(!isRectangle(lambda, phi, radius))\n      return FALSE;\n\n    std::vector<Double> dx(lambda.size(), 2*PI);\n    if(lambda.size() > 1)\n    {\n      dx.front() = std::fabs(std::remainder(lambda.at(1)-lambda.at(0), 2*PI));\n      for(UInt k=1; k<lambda.size()-1; k++)\n        dx.at(k) = 0.5*std::fabs(std::remainder(lambda.at(k+1)-lambda.at(k-1), 2*PI));\n      dx.back() = std::fabs(std::remainder(lambda.at(lambda.size()-1)-lambda.at(lambda.size()-2), 2*PI));\n    }\n\n    // TODO: boundaries should be between ellipsoidal latitudes and not between geocentric phis\n    // integral cos(phi) dPhi\n    std::vector<Double> dy(phi.size(), 2.);\n    if(phi.size() > 1)\n    {\n      dy.front() = std::fabs(std::sin(std::min(std::max(static_cast<Double>(phi.front()+0.5*(phi.at(1)-phi.at(0))), -PI), PI))-\n                             std::sin(std::min(std::max(static_cast<Double>(phi.front()-0.5*(phi.at(1)-phi.at(0))), -PI), PI)));\n      for(UInt i=1; i<phi.size()-1; i++)\n        dy.at(i) = std::fabs(std::sin(0.5*(phi.at(i+1)+phi.at(i)))-std::sin(0.5*(phi.at(i)+phi.at(i-1))));\n      dy.back() = std::fabs(std::sin(std::min(std::max(static_cast<Double>(phi.back()+0.5*(phi.at(phi.size()-1)-phi.at(phi.size()-2))), -PI), PI))-\n                            std::sin(std::min(std::max(static_cast<Double>(phi.back()-0.5*(phi.at(phi.size()-1)-phi.at(phi.size()-2))), -PI), PI)));\n    }\n\n    areas.resize(points.size());\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=0; k<lambda.size(); k++)\n        areas.at(i*lambda.size()+k) = dx.at(k)*dy.at(i);\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GriddedData::isValid() const\n{\n  try\n  {\n    if(areas.size() && (areas.size() != points.size()))\n      return FALSE;\n    for(UInt idx=0; idx<values.size(); idx++)\n      if(values.at(idx).size() != points.size())\n        return FALSE;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nBool GriddedDataRectangular::init(const GriddedData &grid)\n{\n  try\n  {\n    if(!grid.isValid())\n      return FALSE;\n\n    std::vector<Double> radius;\n    std::vector<Angle>  lambda;\n    std::vector<Angle>  phi;\n    if(!grid.isRectangle(lambda, phi, radius))\n      return FALSE;\n\n    ellipsoid  = grid.ellipsoid;\n    longitudes = lambda;\n    latitudes.resize(phi.size());\n    heights.resize(phi.size());\n    Angle longitude;\n    for(UInt i=0; i<phi.size(); i++)\n      ellipsoid(polar(Angle(0), phi.at(i), radius.at(i)), longitude, latitudes.at(i), heights.at(i));\n\n    values.resize( grid.values.size() );\n    for(UInt idx=0; idx<values.size(); idx++)\n    {\n      values.at(idx) = Matrix(phi.size(), lambda.size());\n      for(UInt i=0; i<phi.size(); i++)\n        for(UInt k=0; k<lambda.size(); k++)\n          values.at(idx)(i,k) = grid.values.at(idx).at(i*lambda.size()+k);\n    }\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GriddedDataRectangular::geocentric(std::vector<Angle> &lambda, std::vector<Angle> &phi, std::vector<Double> &radius) const\n{\n  try\n  {\n    lambda = longitudes;\n    phi.resize(latitudes.size());\n    radius.resize(heights.size());\n    for(UInt i=0; i<phi.size(); i++)\n    {\n      const Vector3d points = ellipsoid(Angle(0), latitudes.at(i), heights.at(i));\n      phi.at(i)    = points.phi();\n      radius.at(i) = points.r();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GriddedDataRectangular::cellBorders(std::vector<Double> &lambda, std::vector<Double> &phi) const\n{\n  try\n  {\n    lambda.clear();\n    if(longitudes.size() > 1)\n    {\n      lambda.resize(longitudes.size()+1);\n      lambda.front() = std::remainder(longitudes.front() - 0.5*std::remainder(longitudes.at(1)-longitudes.at(0), 2*PI), 2*PI);\n      for(UInt k=0; k<longitudes.size()-1; k++)\n        lambda.at(k+1) = std::remainder(longitudes.at(k) + 0.5*std::remainder(longitudes.at(k+1)-longitudes.at(k), 2*PI), 2*PI);\n      lambda.back() = std::remainder(longitudes.back() + 0.5*std::remainder(longitudes.at(longitudes.size()-1)-longitudes.at(longitudes.size()-2), 2*PI), 2*PI);\n    }\n    else if(longitudes.size() == 1)\n      lambda = {std::remainder(longitudes.front()-PI, 2*PI), std::remainder(longitudes.front()+PI, 2*PI)};\n\n    phi.clear();\n    if(latitudes.size() > 1)\n    {\n      phi.resize(latitudes.size()+1);\n      phi.front() = std::min(std::max(static_cast<Double>(latitudes.front()-0.5*(latitudes.at(1)-latitudes.at(0))), -PI), PI);\n      for(UInt i=0; i<latitudes.size()-1; i++)\n        phi.at(i+1) = 0.5 * (latitudes.at(i) + latitudes.at(i+1));\n      phi.back() = std::min(std::max(static_cast<Double>(latitudes.back()+0.5*(latitudes.at(latitudes.size()-1)-latitudes.at(latitudes.size()-2))), -PI), PI);\n    }\n    else if(latitudes.size() == 1)\n      phi = {PI/2, -PI/2};\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GriddedDataRectangular::areaElements(std::vector<Double> &dLambda, std::vector<Double> &dPhi) const\n{\n  try\n  {\n    std::vector<Double> lambda, phi;\n    cellBorders(lambda, phi);\n    for(UInt i=0; i<phi.size(); i++)\n      phi.at(i) = ellipsoid(Angle(0.), Angle(phi.at(i)), 0.).phi();  // geocentric\n\n    dLambda.resize(longitudes.size());\n    for(UInt k=0; k<dLambda.size(); k++)\n      dLambda.at(k) = std::fabs(std::remainder(lambda.at(k+1)-lambda.at(k), 2*PI));\n    if(longitudes.size() == 1)\n      dLambda.front() = 2*PI;\n\n    dPhi.resize(latitudes.size());\n    for(UInt i=0; i<dPhi.size(); i++)\n      dPhi.at(i) = std::fabs(std::sin(phi.at(i+1))-std::sin(phi.at(i))); // area = integral cos(phi) dPhi\n\n    // total area\n    return std::accumulate(dLambda.begin(), dLambda.end(), 0.) * std::accumulate(dPhi.begin(), dPhi.end(), 0.);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GriddedDataRectangular::isValid() const\n{\n  try\n  {\n    if(heights.size() != latitudes.size())\n      return FALSE;\n    for(UInt idx=0; idx<values.size(); idx++)\n      if((values.at(idx).rows() != latitudes.size()) || (values.at(idx).columns() != longitudes.size()))\n        return FALSE;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/griddedData.h",
    "content": "/***********************************************/\n/**\n* @file griddedData.h\n*\n* @brief Gridded values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDDEDDATA__\n#define __GROOPS_GRIDDEDDATA__\n\n#include \"base/importStd.h\"\n#include \"base/vector3d.h\"\n#include \"base/ellipsoid.h\"\n\n/** @addtogroup base */\n/// @{\n\nclass GriddedDataRectangular;\n\n/***** CLASS ***********************************/\n\n/** @brief Point list with (multiple) data. */\nclass GriddedData\n{\npublic:\n  Ellipsoid                        ellipsoid; //!< Ellipsoid for conversion to ellipsoidal coordinates\n  std::vector<Vector3d>            points;    //!< List of points\n  std::vector<Double>              areas;     //!< Area element (projected to unit sphere).\n  std::vector<std::vector<Double>> values;    //!< data.at(dataIdx).at(pointIdx)\n\n  /// Default constructor.\n  GriddedData() = default;\n\n  /// Constructor with points, area elements, and multiple values for each point.\n  GriddedData(const Ellipsoid &ellip, const std::vector<Vector3d> &_points, const std::vector<Double> &_areas, const std::vector<std::vector<Double>> &_values) : ellipsoid(ellip), points(_points), areas(_areas), values(_values) {}\n\n  /// Constructor from GriddedDataRectangular.\n  GriddedData(const GriddedDataRectangular &grid) {init(grid);}\n\n  /// Create from GriddedDataRectangular.\n  void init(const GriddedDataRectangular &grid);\n\n  /** @brief Sort points geographically (North/West->South/East). */\n  void sort();\n\n  /** @brief Define points a rectangular grid?\n  * if function returns FALSE, @a lambda, @a phi, @a radius contain garbage.\n  * if function returns TRUE, points are in same order as:\n  @code\n  UInt idx = 0;\n  for(UInt i=0; i<phi.size(); i++)\n    for(UInt k=0; k<lambda.size(); k++)\n      points.at(idx++) == polar(lambda.at(k), phi.at(i), r.at(i));\n  @endcode */\n  Bool isRectangle(std::vector<Angle> &lambda, std::vector<Angle> &phi, std::vector<Double> &radius) const;\n\n  /** @brief Automatically area computation of rectangular grids (overwrite areas). */\n  Bool computeArea();\n\n  /** @brief Is GriddedData valid?\n  * Test dimensions of vectors. */\n  Bool isValid() const;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Rectangular grid with (multiple) data. */\nclass GriddedDataRectangular\n{\npublic:\n  Ellipsoid           ellipsoid;  //!< Ellipsoid for conversion to ellipsoidal coordinates\n  std::vector<Angle>  longitudes; //!< Longitude (columns)\n  std::vector<Angle>  latitudes;  //!< Latitude (rows)\n  std::vector<Double> heights;    //!< Elliposoidal height (rows)\n  std::vector<Matrix> values;     //!< Multiple values at each point.\n\n  /// Create from GriddedData.\n  Bool init(const GriddedData &grid);\n\n  /** @brief Conversion from ellipsoidal to geocentric spherical polar coordinates. */\n  void geocentric(std::vector<Angle> &lambda, std::vector<Angle> &phi, std::vector<Double> &radius) const;\n\n  /** @brief borders of grid cell (i,k): (lat(i) - lat(i+1)) x (lon(k) - lon(k+1)). */\n  void cellBorders(std::vector<Double> &longitudes, std::vector<Double> &latitudes) const;\n\n  /** @brief Area elements projected on the unit sphere.\n  * area(i,k) = dPhi(i)*dLambda(k).\n  * @return total area (4pi for global grids). */\n  Double areaElements(std::vector<Double> &dLambda, std::vector<Double> &dPhi) const;\n\n  /** @brief Is GriddedDataRectangular valid?\n  * Test dimensions of vectors. */\n  Bool isValid() const;\n};\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/base/import.h",
    "content": "/***********************************************/\n/**\n* @file import.h\n*\n* @brief Import of common standard headers.\n*\n* @author Torsten Mayer-Guerr\n* @date 1998-04-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_IMPORT__\n#define __GROOPS_IMPORT__\n\n#include \"importStd.h\"\n#include \"constants.h\"\n#include \"matrix.h\"\n#include \"time.h\"\n#include \"angle.h\"\n#include \"vector3d.h\"\n#include \"tensor3d.h\"\n#include \"rotary3d.h\"\n#include \"transform3d.h\"\n#include \"ellipsoid.h\"\n\n/***********************************************/\n\n#endif /* __GROOPS_IMPORT__ */\n\n"
  },
  {
    "path": "source/base/importStd.h",
    "content": "/***********************************************/\n/**\n* @file importStd.h\n*\n* @brief Import of common standard headers.\n*\n* @author Torsten Mayer-Guerr\n* @date 1998-04-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_IMPORTSTD__\n#define __GROOPS_IMPORTSTD__\n\n#include <array>\n#include <cmath>\n#include <limits>\n#include <string>\n#include <memory>\n#include <iostream>\n#include <sstream>\n#include <fstream>\n#include <iomanip>\n#include <vector>\n#include <list>\n#include <set>\n#include <stack>\n#include <functional>\n#include <algorithm>\n#include <numeric>\n#include <complex>\n\n#include \"portable.h\"\n#include \"exception.h\"\n#include \"format.h\"\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n\n"
  },
  {
    "path": "source/base/kepler.cpp",
    "content": "/***********************************************/\n/**\n* @file kepler.cpp\n*\n* @brief Keplerian elements and orbits.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-09-12\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/vector3d.h\"\n#include \"base/time.h\"\n#include \"base/kepler.h\"\n#include \"base/equinoctial.h\"\n\n/***********************************************/\n\nKepler::Kepler() :\n  GM(DEFAULT_GM),\n  Omega(0),\n  i(0),\n  omega(0),\n  a(0),\n  e(0),\n  tau()\n{\n}\n\n/***********************************************/\n\nKepler::Kepler(Double _Omega, Double _i, Double _omega, Double _a, Double _e, const Time &_tau, Double _GM) :\n  GM(_GM),\n  Omega(_Omega),\n  i( _i),\n  omega(_omega),\n  a(_a),\n  e(_e),\n  tau(_tau)\n{\n}\n\n/***********************************************/\n\nKepler::Kepler(const Time &time, Double _Omega, Double _i, Double _omega, Double _a, Double _e, Double _M, Double _GM) :\n  GM(_GM),\n  Omega(_Omega),\n  i( _i),\n  omega(_omega),\n  a(_a),\n  e(_e),\n  tau(time - seconds2time(_M*sqrt(a*a*a/GM)))\n{\n}\n\n/***********************************************/\n\nKepler::Kepler(const Equinoctial &equinoctial) :\n  GM(equinoctial.GM),\n  a(equinoctial.a),\n  tau(equinoctial.tau)\n{\n  e = sqrt(equinoctial.h*equinoctial.h+equinoctial.k*equinoctial.k);\n  i = 2*atan(sqrt(equinoctial.p*equinoctial.p+equinoctial.q*equinoctial.q));\n\n  const Double sinOmega  = equinoctial.p/sqrt(equinoctial.p*equinoctial.p+equinoctial.q*equinoctial.q);\n  const Double cosOmega  = equinoctial.q/sqrt(equinoctial.p*equinoctial.p+equinoctial.q*equinoctial.q);\n  Omega = atan2(sinOmega,cosOmega);\n\n  const Double sinXi = equinoctial.h / sqrt(equinoctial.h*equinoctial.h+equinoctial.k*equinoctial.k);\n  const Double cosXi = equinoctial.k / sqrt(equinoctial.h*equinoctial.h+equinoctial.k*equinoctial.k);\n  const Double xi    = atan2(sinXi,cosXi);\n  const Double M     = static_cast<Double>(equinoctial.l0) - xi;\n\n  omega = xi - Omega; //equinoctial.l0 - Omega;\n  tau   = tau - seconds2time(M*sqrt(a*a*a/GM));\n\n  if(Omega<0) Omega += 2*PI;\n  if(omega<0) omega += 2*PI;\n  if(i<0)     i     += 2*PI;\n}\n\n/***********************************************/\n\nKepler::Kepler(const Time &time, const Vector3d &position, const Vector3d &velocity, Double _GM) : GM(_GM)\n{\n  const Double   r = position.r();\n  const Vector3d C = crossProduct(position, velocity);\n\n  i     = atan2(sqrt(C.x()*C.x()+C.y()*C.y()), C.z());\n  Omega = atan2(C.x(), -C.y());\n\n  // major semi axis\n  a = 1/(2/position.r()-inner(velocity,velocity)/GM);\n\n  // excentricity\n  const Double p = inner(C,C)/GM;\n  e  = sqrt((a-p)/a);\n\n  // true anomaly\n  const Double v = atan2(p*inner(position,velocity)/C.r(), p-r);\n\n  // oribt system\n  const Vector3d P = (e+cos(v))/p * position - r*sin(v)/C.r() * velocity;\n  const Vector3d Q = sin(v)/p     * position + r*cos(v)/C.r() * velocity;\n  const Vector3d K = Vector3d(cos(Omega), sin(Omega), 0);\n\n  // argument of perigee\n  omega = atan2(-inner(K,Q), inner(K,P));\n\n  // excentric anomaly\n  Double E = atan2(inner(position,Q)/(a*sqrt(1-e*e)), inner(position,P)/a+e);\n\n  // positive angles\n  if(i<0)     i     += 2*PI;\n  if(Omega<0) Omega += 2*PI;\n  if(omega<0) omega += 2*PI;\n  if(E<0)     E     += 2*PI;\n\n  // time of perigee\n  const Double M = E - e*sin(E);\n  tau = time - seconds2time(M*sqrt(a*a*a/GM));\n}\n\n/***********************************************/\n\nDouble Kepler::meanAnomaly(const Time &time) const\n{\n  Double M = (time-tau).seconds()*sqrt(GM/(a*a*a));\n  if(M<0) M += 2*PI;\n  return M;\n}\n\n/***********************************************/\n\nDouble Kepler::trueAnomaly(const Time &time) const\n{\n  Double M = meanAnomaly(time);\n\n  // excentric anomaly\n  Double E = M;\n  Double E_old;\n  Double eps = 1e-12;\n\n  UInt iter = 0;\n  do\n  {\n    E_old = E;\n    E = M + e*sin(E);\n  }\n  while((fabs(E-E_old)>eps)&&(iter++<100));\n\n  return atan2(sqrt(1-e*e)*sin(E), cos(E)-e);\n}\n\n/***********************************************/\n\nconst Vector3d Kepler::position(const Time &time) const\n{\n  Vector3d position, velocity;\n  orbit(time, position, velocity);\n  return position;\n}\n\n/***********************************************/\n\nvoid Kepler::orbit(const Time &time, Vector3d &position, Vector3d &velocity) const\n{\n  Vector3d acceleration;\n  orbit(time, position, velocity, acceleration);\n}\n\n/***********************************************/\n\nvoid Kepler::orbit(const Time &time, Vector3d &position, Vector3d &velocity, Vector3d &acceleration) const\n{\n  Double v = trueAnomaly(time);\n\n  // distance and angular momentum\n  Double p = a*(1-e*e);\n  Double r = p/(1+e*cos(v));\n  Double C = sqrt(GM*p);\n\n  // orbital system\n  Vector3d P(cos(Omega)*cos(omega)-sin(Omega)*sin(omega)*cos(i),\n             sin(Omega)*cos(omega)+cos(Omega)*sin(omega)*cos(i),\n             sin(omega)*sin(i));\n\n  Vector3d Q(-cos(Omega)*sin(omega)-sin(Omega)*cos(omega)*cos(i),\n             -sin(Omega)*sin(omega)+cos(Omega)*cos(omega)*cos(i),\n             cos(omega)*sin(i));\n\n\n  // position and velocity\n  position     = (r*cos(v))    * P + (r*sin(v))       * Q;\n  velocity     = (-C/p*sin(v)) * P + (C*(cos(v)+e)/p) * Q;\n  acceleration = -GM/pow(position.r(),3) * position;\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/base/kepler.h",
    "content": "/***********************************************/\n/**\n* @file kepler.h\n*\n* @brief Keplerian elements and orbits.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-09-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KEPLER__\n#define __GROOPS_KEPLER__\n\n#include \"base/importStd.h\"\n#include \"base/vector3d.h\"\n#include \"base/time.h\"\n\nclass Equinoctial;\n\n/***** CLASS ***********************************/\n\n/** @brief Keplerian orbits.\n* @ingroup base */\nclass Kepler\n{\npublic:\n  Double GM;    //!< Specific gravitational constant\n  Double Omega; //!< ascending node\n  Double i;     //!< inclination\n  Double omega; //!< argument of perigee\n  Double a;     //!< major semi axis\n  Double e;     //!< excentricity\n  Time   tau;   //!< time of perigee\n\n  /// Default constructor.\n  Kepler();\n\n  /** @brief Constructor with keplerian elements.\n  * @param Omega ascending node\n  * @param i     inclination\n  * @param omega argument of perigee\n  * @param a     major semi axis\n  * @param e     excentricity\n  * @param tau   time of perigee\n  * @param GM    specific gravitational constant */\n  Kepler(Double Omega, Double i, Double omega, Double a, Double e, const Time &tau, Double GM=DEFAULT_GM);\n\n  /** @brief Constructor with keplerian elements.\n  * @param time  time of mean anomaly\n  * @param Omega ascending node\n  * @param i     inclination\n  * @param omega argument of perigee\n  * @param a     major semi axis\n  * @param e     excentricity\n  * @param M     mean anomaly\n  * @param GM    specific gravitational constant */\n  Kepler(const Time &time, Double Omega, Double i, Double omega, Double a, Double e, Double M, Double GM=DEFAULT_GM);\n\n  /** @brief Constructor with initial state vector.\n  * @param time Start time\n  * @param position Start position\n  * @param velocity Start velocity\n  * @param GM   Specific gravitational constant */\n  Kepler(const Time &time, const Vector3d &position, const Vector3d &velocity, Double GM=DEFAULT_GM);\n\n  /** @brief Kepler from Equinoctial orbit\n  * @param equinoctial Equinoctial object\n  * @see Chapter 2.1.3 Danielson, Donald A., Christopher Patrick Sagovac, Beny Neta, and Leo W. Early. 1995. “Semianalytic Satellite Theory.” */\n  explicit Kepler(const Equinoctial &equinoctial);\n\n  /// Mean anomaly at @a time.\n  Double meanAnomaly(const Time &time) const;\n\n  /// True anomaly at @a time.\n  Double trueAnomaly(const Time &time) const;\n\n  /// Position at @a time.\n  const Vector3d position(const Time &time) const;\n\n  /** @brief Position and velocity at @a time.\n  * @param time time\n  * @param[out] position position at @a time\n  * @param[out] velocity velocity at @a time */\n  void orbit(const Time &time, Vector3d &position, Vector3d &velocity) const;\n\n  /** @brief Position, velocity, and acceleration at @a time.\n  * @param time time\n  * @param[out] position position at @a time\n  * @param[out] velocity velocity at @a time\n  * @param[out] acceleration acceleration at @a time */\n  void orbit(const Time &time, Vector3d &position, Vector3d &velocity, Vector3d &acceleration) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_KEPLER__ */\n"
  },
  {
    "path": "source/base/legendreFunction.cpp",
    "content": "/***********************************************/\n/**\n* @file legendreFunction.cpp\n*\n* @brief Associated Legendre functions.\n* (fully normalized).\n*\n* @author Torsten Mayer-Guerr\n* @author Annette Eicker\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"legendreFunction.h\"\n\n/***** VARIABLES *******************************/\n\nMatrix LegendreFunction::factor1;\nMatrix LegendreFunction::factor2;\nMatrix LegendreFunction::factor1Integral;\nMatrix LegendreFunction::factor2Integral;\nVector LegendreFunction::factorSmall; //integration for small thetas\n\n/***********************************************/\n\nvoid LegendreFunction::computeFactors(UInt degree)\n{\n  // Enough factors already computed?\n  if(factor1.rows()>degree)\n    return;\n\n  factor1 = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  factor2 = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  // factors for recursion P[n-1][n-1] -> P[n][n]\n  if(degree>0) factor1(1,1) = std::sqrt(3.0);\n  for(UInt n=2; n<=degree; n++)\n    factor1(n,n) = std::sqrt((2.*n+1)/(2.*n));\n\n  // factors for recursion P[m][n-1] and P[m][n-2] -> P[m][n]\n  for(UInt m=0; m<degree; m++)\n    for(UInt n=m+1; n<=degree; n++)\n    {\n      Double f = (2.*n+1)/((n+m)*(n-m));\n      factor1(n,m) =  std::sqrt(f*(2.*n-1));\n      factor2(n,m) = -std::sqrt(f*(n-m-1.)*(n+m-1.)/(2.*n-3));\n    }\n}\n\n/***********************************************/\n\nvoid LegendreFunction::computeFactorsIntegral(UInt degree)\n{\n  // Enough factors already computed?\n  if(factor1Integral.rows()>degree)\n    return;\n\n  factor1Integral = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  factor2Integral = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  // factors for recursion P[n-1][n-2] and int_P[n-2][n-2] -> P[n][n]\n  for(UInt n=2; n<=degree; n++)\n  {\n    factor1Integral(n,n) =  1./(2.*n+2.)*std::sqrt((2.*n+1.)/(n*(n-1.)));\n    factor2Integral(n,n) =  1./(2.*n+2.)*std::sqrt(n*(2.*n+1.)*(2.*n-1.)/(n-1.));\n  }\n\n  // factors for recursion P[n-1][m] and int_P[n-2][m] -> P[n][m]\n  for(UInt m=0; m<degree; m++)\n    for(UInt n=m+1; n<=degree; n++)\n    {\n      factor1Integral(n,m) = -1.0/(n+1.)*std::sqrt((2.*n+1.)*(2.*n-1.)/((n-m)*(n+m)));\n      factor2Integral(n,m) = (n-2.)/(n+1.)*std::sqrt((2.*n+1.)*(n+m-1.)*(n-m-1.)/((2.*n-3.)*(n+m)*(n-m)));\n    }\n\n  // factors for Hmain diagonal for small thetas\n  factorSmall = Vector(degree+1);\n\n  for(UInt n=3; n<=degree; n++)\n  {\n    factorSmall(n)=1.0;\n    for(UInt k=5; k<=(2*n-1); k+=2)\n      factorSmall(n) *= k/(k+1.);\n    factorSmall(n) = std::sqrt(factorSmall(n)*(2*n+1));\n  }\n}\n\n/***********************************************/\n\nconst Matrix LegendreFunction::compute(Double t, UInt degree)\n{\n  computeFactors(degree);\n\n  Matrix Fkt(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  Fkt(0,0) = 1e280; // dirty trick: to account for small numbers in very high degrees.\n\n  // recursion P[n-1][n-1] -> P[n][n] (main diagonals)\n  for(UInt n=1; n<=degree; n++)\n    Fkt(n,n) = factor1(n,n) *std::sqrt(1-t*t)* Fkt(n-1, n-1);\n\n  // recursion P[m][n-1] and P[m][n-2] -> P[m][n]\n  // secondary diagonal m=n-1\n  for(UInt n=1; n<=degree; n++)\n    Fkt(n,n-1) = factor1(n,n-1) * t * Fkt(n-1,n-1);\n\n  // all other functions\n  for(UInt m=0; m<(degree-1); m++)\n    for(UInt n=m+2; n<=degree; n++)\n      Fkt(n,m) = factor1(n,m)*t*Fkt(n-1,m) + factor2(n,m)*Fkt(n-2,m);\n\n  return 1e-280 * Fkt; // dirty trick: to account for small numbers in very high degrees.\n}\n\n/***********************************************/\n\nconst Matrix LegendreFunction::integral(Double t1, Double t2, UInt degree)\n{\n  computeFactorsIntegral(degree);\n\n  Matrix intP(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  Double qt1    = t1*t1;\n  Double qt2    = t2*t2;\n  Double y1     = std::sqrt(1-qt1);\n  Double y2     = std::sqrt(1-qt2);\n  Double qy1    = 1-qt1;\n  Double qy2    = 1-qt2;\n  Double theta1 = acos(t1);\n  Double theta2 = acos(t2);\n\n  Matrix P1 = LegendreFunction::compute(t1, degree);\n  Matrix P2 = LegendreFunction::compute(t2, degree);\n\n  intP(0,0) = t2-t1;\n  intP(1,1) = std::sqrt(3.0)/2.0  * (t2*y2-theta2-t1*y1+theta1);\n  intP(2,2) = std::sqrt(5.0/12.0) * (3*t2-std::pow(t2, 3)-3*t1+std::pow(t1, 3));\n\n  // recursion P[n-1][n-2] and int_P[n-2][n-2] -> int_P[n][n]\n\n  // recursions are instable for small theta\n  if(theta1<=10.0*DEG2RAD && theta2<=10.0*DEG2RAD)\n  {\n    for(UInt n=3; n<=degree; n++)\n    {\n      Double x1  = 0.0;\n      Double x2  = 0.0;\n      Double fak = 1.0;\n\n      for(UInt k=0; k<=20; k++)\n      {\n        for(UInt i=1; i<=k; i++)\n          fak *= (2.*i-1.)/(2.*i);\n\n        x1 += fak*std::pow(y1, 2*k)/(n+2+2*k);\n        x2 += fak*std::pow(y2, 2*k)/(n+2+2*k);\n      }\n\n      intP(n,n) = -factorSmall(n)*(std::pow(y2, n+2)*x2 - std::pow(y1, n+2)*x1);\n    }\n  }\n  else // for large thetas\n  {\n    for(UInt n=3; n<=degree; n++)\n      intP(n,n) = factor1Integral(n,n) * (qy2*P2(n-1,n-2)-qy1*P1(n-1,n-2)) + factor2Integral(n,n) * intP(n-2,n-2);\n  }\n\n  // recursion P[n-1][m] and int_P[n-2][m] -> int_P[n][m]\n  for(UInt m=0; m<degree; m++)\n  {\n    intP(m+1,m) = factor1Integral(m+1,m) * (qy2*P2(m,m)-qy1*P1(m,m));\n    for(UInt n=m+2; n<=degree; n++)\n      intP(n,m) = factor1Integral(n,m) * (qy2*P2(n-1,m)-qy1*P1(n-1,m))\n                + factor2Integral(n,m) * intP(n-2,m);\n  }\n\n  return intP;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/legendreFunction.h",
    "content": "/***********************************************/\n/**\n* @file legendreFunction.h\n*\n* @brief Associated Legendre functions.\n* (fully normalized).\n*\n* @author Torsten Mayer-Guerr\n* @author Annette Eicker\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __LEGEDNREFUNCTION__\n#define __LEGEDNREFUNCTION__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Associated Legendre functions.\n* @ingroup base\n* fully normalized. */\nclass LegendreFunction\n{\n  static Matrix factor1, factor2;\n  static Matrix factor1Integral, factor2Integral;\n  static Vector factorSmall;\n\n  static void computeFactors(UInt degree);\n  static void computeFactorsIntegral(UInt degree);\n\npublic:\n  /** @brief Legendre functions.\n  * (fully normalized).\n  * @f[ P_n^m(t) \\textnormal{ with } t=\\cos(\\psi),\\quad n,m=0\\ldots\\textnormal{degree} @f]\n  * @return lower triangular matrix with dimension @a degree+1.\n  */\n  static const Matrix compute(Double t, UInt degree);\n\n  /** @brief integral over Legendre functions.\n  * (fully normalized).\n  * @f[ I_n^m = \\int_{t_1}^{t_2} P_n^m(t)\\,dt \\textnormal{ with } t=\\cos(\\psi),\\quad n,m=0\\ldots\\textnormal{degree} @f]\n  * @return lower triangular matrix with dimension @a degree+1.\n  */\n  static const Matrix integral(Double t1, Double t2, UInt degree);\n}; // end LegendreFunction\n\n/***********************************************/\n\n#endif /* __LEGENDREFUNCTION__ */\n\n\n\n"
  },
  {
    "path": "source/base/legendrePolynomial.cpp",
    "content": "/***********************************************/\n/**\n* @file legendrePolynomial.cpp\n*\n* @brief Legendre polynomials.\n*\n* fully normalized.\n*\n* @author Torsten Mayer-Guerr\n* @author Annette Eicker\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/legendrePolynomial.h\"\n\n/***** VARIABLES ********************************/\n\n// factors for the recursion\nVector LegendrePolynomial::factor1,            LegendrePolynomial::factor2;\nVector LegendrePolynomial::factor1Derivate,    LegendrePolynomial::factor2Derivate;\nVector LegendrePolynomial::factor1Derivate2nd, LegendrePolynomial::factor2Derivate2nd;\nVector LegendrePolynomial::factor1Integral,    LegendrePolynomial::factor2Integral;\n\n/***********************************************/\n\nvoid LegendrePolynomial::computeFactors(UInt degree)\n{\n  // Enough factors already computed?\n  if(factor1.rows()>degree)\n    return;\n\n  factor1 = Vector(degree+1);\n  factor2 = Vector(degree+1);\n\n  factor1(0) = 1.0;\n  factor2(0) = sqrt(3.0);\n\n  for(UInt n=2; n<=degree; n++)\n  {\n    factor1(n) = sqrt(2.*n+1)*sqrt(2.*n-1.)/n;\n    factor2(n) = -(n-1.)*sqrt(2.*n+1.)/sqrt(2.*n-3.)/n;\n  }\n}\n\n/***********************************************/\n\nvoid LegendrePolynomial::computeFactorsDerivate(UInt degree)\n{\n  // Enough factors already computed?\n  if(factor1Derivate.rows()>degree)\n    return;\n\n  factor1Derivate = Vector(degree+1);\n  factor2Derivate = Vector(degree+1);\n\n  factor1Derivate(0) = sqrt(3.);\n  factor2Derivate(0) = 3.*sqrt(5.);\n\n  for(UInt n=2; n<=degree; n++)\n  {\n    factor1Derivate(n) = sqrt(2.*n+1.)*sqrt(2.*n-1.)/(n-1.);\n    factor2Derivate(n) = -sqrt(2.*n+1.)*n/sqrt(2.*n-3.)/(n-1.);\n  }\n}\n\n/***********************************************/\n\nvoid LegendrePolynomial::computeFactorsDerivate2nd(UInt degree)\n{\n  // Enough factors already computed?\n  if(factor1Derivate2nd.rows()>degree)\n    return;\n\n  factor1Derivate2nd = Vector(degree+1);\n  factor2Derivate2nd = Vector(degree+1);\n\n  factor1Derivate2nd(0) =  3. * sqrt(5.);\n  factor2Derivate2nd(0) = 15. * sqrt(7.);\n\n  for(UInt n=3; n<=degree; n++)\n  {\n    factor1Derivate2nd(n) = sqrt(2.*n+1.)*sqrt(2.*n-1.)/(n-2.);\n    factor2Derivate2nd(n) = -(n+1.)*sqrt(2.*n+1.)/sqrt(2.*n-3.)/(n-2.);\n  }\n}\n\n/***********************************************/\n\nvoid LegendrePolynomial::computeFactorsIntegral(UInt degree)\n{\n  // Enough factors already computed?\n  if(factor1Integral.rows()>degree)\n    return;\n\n  factor1Integral = Vector(degree+1);\n  factor2Integral = Vector(degree+1);\n\n  for(UInt n=1; n<=degree; n++)\n  {\n    factor1Integral(n) = -1./sqrt((2.*n+1.)*(2.*n+3.));\n    factor2Integral(n) =  1./sqrt((2.*n+1.)*(2.*n-1.));\n  }\n}\n\n/***********************************************/\n\nconst Vector LegendrePolynomial::compute(Double t, UInt degree)\n{\n  computeFactors(degree);\n\n  Vector P(degree+1);\n  P(0) = 1.0;\n\n  if(degree>=1) P(1) = sqrt(3.)*t;\n\n  for(UInt n=2; n<=degree; n++)\n    P(n) = factor1(n)*t*P(n-1) + factor2(n)*P(n-2);\n\n  return P;\n}\n\n/***********************************************/\n\nconst Vector LegendrePolynomial::derivative(Double t, UInt degree)\n{\n  computeFactorsDerivate(degree);\n\n  Vector P(degree+1);\n  if(degree>=1) P(1) = sqrt(3.);\n\n  for(UInt n=2; n<=degree; n++)\n    P(n) = factor1Derivate(n)*t*P(n-1) + factor2Derivate(n)*P(n-2);\n\n  return P;\n}\n\n/***********************************************/\n\nconst Vector LegendrePolynomial::derivative2nd(Double t, UInt degree)\n{\n  computeFactorsDerivate2nd(degree);\n\n  Vector P(degree+1);\n  if(degree>=2) P(2) = 3.*sqrt(5.);\n\n  for(UInt n=3; n<=degree; n++)\n    P(n) = factor1Derivate2nd(n)*t*P(n-1) + factor2Derivate2nd(n)*P(n-2);\n\n  return P;\n}\n\n/***********************************************/\n\nconst Vector LegendrePolynomial::integral(Double t, UInt degree)\n{\n  computeFactorsIntegral(degree);\n\n  Vector R(degree+1);\n  Vector P = compute(t,degree);\n\n  R(0)=1-t;\n  for(UInt n=1; n<=degree-1; n++)\n    R(n) = factor1Integral(n)*P(n+1) + factor2Integral(n)*P(n-1);\n\n  return R;\n}\n\n/***********************************************/\n\nDouble LegendrePolynomial::sum(Double t, const Vector &koeff, UInt degree)\n{\n  computeFactors(degree);\n\n  // pointer arithemtic to be as fast as possible\n  const Double *aptr = factor1.field()+degree;\n  const Double *bptr = factor2.field()+degree;\n  const Double *kptr = koeff.field()+degree;\n  const Double *stop = koeff.field();\n\n  Double u;\n  Double u2 = *(kptr--);\n  Double u1 = *(aptr--) * t * u2 + *(kptr--);\n\n  while(kptr!=stop)\n  {\n    u  = *(aptr--) * t * u1 + *(bptr--) * u2 + *(kptr--);\n    u2 = u1;\n    u1 = u;\n  }\n\n  return *kptr  + *bptr * u2 + u1 * sqrt(3.) * t;\n}\n\n/***********************************************/\n\nDouble LegendrePolynomial::sumDerivative(Double t, const Vector &koeff, UInt degree)\n{\n  computeFactorsDerivate(degree);\n\n  // pointer arithemtic to be as fast as possible\n  const Double *aptr = factor1Derivate.field()+degree;\n  const Double *bptr = factor2Derivate.field()+degree;\n  const Double *kptr = koeff.field()+degree;\n  const Double *stop = koeff.field()+1;\n\n  Double u;\n  Double u2 = *(kptr--);\n  Double u1 = *(aptr--) * t * u2 + *(kptr--);\n\n  while(kptr!=stop)\n  {\n    u  = *(aptr--) * t * u1 + *(bptr--) * u2 + *(kptr--);\n    u2 = u1;\n    u1 = u;\n  }\n\n  return (*kptr  + *bptr * u2) * sqrt(3.) + u1 * (3.*sqrt(5.)) * t;\n}\n\n/***********************************************/\n\nDouble LegendrePolynomial::sumDerivative2nd(Double t, const Vector &koeff, UInt degree)\n{\n  computeFactorsDerivate2nd(degree);\n\n  // pointer arithemtic to be as fast as possible\n  const Double *aptr = factor1Derivate2nd.field()+degree;\n  const Double *bptr = factor2Derivate2nd.field()+degree;\n  const Double *kptr = koeff.field()+degree;\n  const Double *stop = koeff.field()+2;\n\n  Double u;\n  Double u2 = *(kptr--);\n  Double u1 = *(aptr--) * t * u2 + *(kptr--);\n\n  while(kptr!=stop)\n  {\n    u  = *(aptr--) * t * u1 + *(bptr--) * u2 + *(kptr--);\n    u2 = u1;\n    u1 = u;\n  }\n\n  return (*kptr  + *bptr * u2) * (3.*sqrt(5.)) + u1 * (15.*sqrt(7.)) * t;\n}\n\n/***********************************************/\n\nvoid LegendrePolynomial::zeros(UInt degree, Vector &zeros, Vector &weights)\n{\n  zeros   = Vector(degree);\n  weights = Vector(degree);\n\n  Double pf=0, pd=1;\n  for(UInt k=0; k<(degree+1)/2; k++)\n  {\n    Double x = std::cos(PI*(4*(k+1)-1)/(4*degree+2));\n    Double x0;\n    do\n    {\n      x0 = x;\n      Double f0 = 1.;\n      Double f1 = x;\n      for(UInt n=2; n<=degree; n++)\n      {\n        pf = (2-1./n)*x*f1-(1-1./n)*f0;\n        pd = n*(x*pf-f1)/(x*x-1);\n        f0 = f1;\n        f1 = pf;\n      }\n      x -= pf/pd;\n    }\n    while(std::fabs(x-x0) > std::fabs(x)*1e-15);\n\n    zeros(k)            =  x;\n    zeros(degree-1-k)   = -x;\n    weights(k)          = 2./((1.-x*x)*pd*pd);\n    weights(degree-1-k) = weights(k);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/legendrePolynomial.h",
    "content": "/***********************************************/\n/**\n* @file legendrePolynomial.h\n*\n* @brief Legendre polynomials.\n* fully normalized.\n*\n* @author Torsten Mayer-Guerr\n* @author Annette Eicker\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LEGEDNREPOLYNOMIAL__\n#define __GROOPS_LEGEDNREPOLYNOMIAL__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Legendre polynomials.\n* @ingroup base\n* fully normalized.\n*/\nclass LegendrePolynomial\n{\n  static Vector factor1,            factor2;\n  static Vector factor1Derivate,    factor2Derivate;\n  static Vector factor1Derivate2nd, factor2Derivate2nd;\n  static Vector factor1Integral,    factor2Integral;\n\n  static void computeFactors(UInt degree);\n  static void computeFactorsDerivate(UInt degree);\n  static void computeFactorsDerivate2nd(UInt degree);\n  static void computeFactorsIntegral(UInt degree);\n\npublic:\n  /** @brief  Legendre polynomials.\n  * (fully normalized).\n  * @f[ P_n(t) \\textnormal{ with } t=\\cos(\\psi),\\quad n=0\\ldots\\textnormal{degree} @f]\n  * @return vector with size @a degree+1. */\n  static const Vector compute(Double t, UInt degree);\n\n  /** @brief Derivative of Legendre polynomials.\n  * (fully normalized).\n  * @f[ P'_n(t) \\textnormal{ with } t=\\cos(\\psi),\\quad n=0\\ldots\\textnormal{degree} @f]\n  * @return vector with size @a degree+1. */\n  static const Vector derivative(Double t, UInt degree);\n\n  /** @brief 2nd derivative of Legendre polynomials.\n  * (fully normalized).\n  * @f[ P''_n(t) \\textnormal{ with } t=\\cos(\\psi),\\quad n=0\\ldots\\textnormal{degree} @f]\n  * @return vector with size @a degree+1. */\n  static const Vector derivative2nd(Double t, UInt degree);\n\n  /** @brief Integral over Legendre polynomials.\n  * For a spherical cap (from 1 to t=cos(psi)).\n  * (fully normalized).\n  * @f[ \\int_t^1 P_n(t)\\,dt \\textnormal{ with } t=\\cos(\\psi),\\quad n=0\\ldots\\textnormal{degree} @f]\n  * @return vector with size @a degree+1. */\n  static const Vector integral(Double t, UInt degree);\n\n  /** @brief Sum of Legendre polynomials.\n  * (fully normalized).\n  * Clenshaw Algorithm.\n  * @f[ \\sum_{n=0}^N k_n P_n(t) \\textnormal{ with } t=\\cos(\\psi) @f]\n  * @param t aperture angle \\f$\\cos(\\psi)\\f$.\n  * @param coeff coefficients \\f$k_n\\f$\n  * @param degree degree \\f$N\\f$ */\n  static Double sum(Double t, const Vector &coeff, UInt degree);\n\n  /** @brief Sum of the derivative of Legendre polynomials.\n  * (fully normalized).\n  * Clenshaw Algorithm.\n  * @f[ \\sum_{n=0}^N k_n P'_n(t) \\textnormal{ with } t=\\cos(\\psi) @f]\n  * @param t aperture angle \\f$\\cos(\\psi)\\f$.\n  * @param coeff coefficients \\f$k_n\\f$\n  * @param degree degree \\f$N\\f$\n  */\n  static Double sumDerivative(Double t, const Vector &coeff, UInt degree);\n\n  /** @brief Sum of the 2nd derivative of Legendre polynomials.\n  * (fully normalized).\n  * Clenshaw Algorithm.\n  * @f[ \\sum_{n=0}^N k_n P''_n(t) \\textnormal{ with } t=\\cos(\\psi) @f]\n  * @param t aperture angle \\f$\\cos(\\psi)\\f$.\n  * @param coeff coefficients \\f$k_n\\f$\n  * @param degree degree \\f$N\\f$ */\n  static Double sumDerivative2nd(Double t, const Vector &coeff, UInt degree);\n\n  /** @brief Zero crossing sof Legendre polynomials.\n  * The weights for Gauss-Legendre Integration are computed additionally.\n  * @param degree degree \\f$N\\f$\n  * @param[out] zeros zero crossings in a vector of size @a degree\n  * @param[out] weights weights in a vector of size @a degree */\n  static void zeros(UInt degree, Vector &zeros, Vector &weights);\n}; // end LegendrePolynomial\n\n\n/***********************************************/\n\n#endif /* __GROOPS_LEGENDREPOLYNOMIAL__ */\n\n\n\n"
  },
  {
    "path": "source/base/matrix.cpp",
    "content": "/***********************************************/\n/**\n* @file matrix.cpp\n*\n* @brief matrix computations.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @author Sebastian Strasser\n* @date 2001-06-16\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"external/lapack/blas.h\"\n#include \"external/lapack/lapack.h\"\n#include \"base/matrix.h\"\n\n/***********************************************/\n/***** MatrixBase ******************************/\n/***********************************************/\n\nMatrixBase::MatrixBase(UInt size, Bool fill, Double value) : _size(size)\n{\n  try\n  {\n    ptr = std::shared_ptr<Double[]>(new Double[_size]);\n    if(fill)\n      std::fill_n(ptr.get(), _size, value);\n\n    // since c++20\n    // if(fill)\n    //   ptr = std::make_shared<Double[]>(_size, value);\n    // else\n    //   ptr = std::make_shared_for_overwrite<Double[]>(_size);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***** const_MatrixSlice ***********************/\n/***********************************************/\n\nconst_MatrixSlice::const_MatrixSlice(UInt rows, UInt columns, Matrix::Type type, Matrix::Uplo uplo, Bool fill, Double value) :\n  _rows(rows),\n  _columns(columns),\n  _start(0),\n  _ld(rows),\n  _type(type),\n  _uplo(uplo),\n  _rowMajorOrder(FALSE)\n{\n  if(size())\n    base = std::make_shared<MatrixBase>(size(), fill, value);\n}\n\n/***********************************************/\n\nconst_MatrixSlice const_MatrixSlice::slice(UInt startRow, UInt startColumn, UInt height, UInt width) const\n{\n  try\n  {\n    if((height==0) || (width==0))\n      return Matrix(height, width);\n    if((startRow+height>rows()) || (startColumn+width>columns()))\n      throw(Exception(\"Dimension error: (\"+rows()%\"%i x \"s+columns()%\"%i).slice(\"s+startRow%\"%i, \"s+startColumn%\"%i, \"s+height%\"%i, \"s+width%\"%i)\"s));\n\n    const_MatrixSlice x(*this);\n    x._rows    = height;\n    x._columns = width;\n    x._start  += (x._rowMajorOrder) ? (startColumn + startRow*_ld) : (startRow + startColumn*_ld);\n    if((startRow!=startColumn) || (height!=width))\n      x._type = GENERAL;\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***** MatrixSlice *****************************/\n/***********************************************/\n\nMatrixSlice MatrixSlice::slice(UInt startRow, UInt startColumn, UInt height, UInt width) const\n{\n  try\n  {\n    if((height==0) || (width==0))\n      return Matrix(height, width);\n    if((startRow+height>rows()) || (startColumn+width>columns()))\n      throw(Exception(\"Dimension error: (\"+rows()%\"%i x \"s+columns()%\"%i).slice(\"s+startRow%\"%i, \"s+startColumn%\"%i, \"s+height%\"%i, \"s+width%\"%i)\"s));\n\n    MatrixSlice x(*this);\n    x._rows    = height;\n    x._columns = width;\n    x._start  += (x._rowMajorOrder) ? (startColumn + startRow*_ld) : (startRow + startColumn*_ld);\n    if((startRow!=startColumn) || (height!=width))\n      x._type = GENERAL;\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nconst MatrixSlice &MatrixSlice::fill(Double f) const\n{\n  if(!size())\n    return *this;\n  if(_rowMajorOrder)\n    for(UInt i=0; i<_rows; i++)\n      std::fill_n(base->field()+(_start+i*_ld), _columns, f);\n  else\n    for(UInt i=0; i<_columns; i++)\n      std::fill_n(base->field()+(_start+i*_ld), _rows, f);\n  return *this;\n}\n\n/***********************************************/\n\nMatrixSliceRef MatrixSlice::operator+= (const const_MatrixSlice &x) const\n{\n  try\n  {\n    axpy(1., x, *this);\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSliceRef MatrixSlice::operator-= (const const_MatrixSlice &x) const\n{\n  try\n  {\n    axpy(-1., x, *this);\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSliceRef MatrixSlice::operator += (Double c) const\n{\n  for(UInt i=0; i<rows(); i++)\n    for(UInt j=0; j<columns(); j++)\n      (*this)(i,j) += c;\n  return *this;\n}\n\n/***********************************************/\n\nMatrixSliceRef MatrixSlice::operator -= (Double c) const\n{\n  return (*this += -c);\n}\n\n/***********************************************/\n\nMatrixSliceRef MatrixSlice::operator *= (Double c) const\n{\n  if(!size())\n    return *this;\n  const UInt rows    = (_rowMajorOrder) ? _columns : _rows;\n  const UInt columns = (_rowMajorOrder) ? _rows : _columns;\n  if(rows == _ld)\n    blas_dscal(static_cast<F77Int>(rows*columns), c, field(), 1);\n  else\n    for(UInt i=0; i<columns; i++)\n      blas_dscal(static_cast<F77Int>(rows), c, field()+i*_ld, 1);\n  return *this;\n}\n\n/***********************************************/\n\nMatrixSliceRef MatrixSlice::operator /= (Double c) const\n{\n  return (*this *= 1./c);\n}\n\n/***********************************************/\n/***** Matrix **********************************/\n/***********************************************/\n\nvoid Matrix::assignment(Bool movePossible)\n{\n  try\n  {\n    if(!base)\n      return;\n    if(_rowMajorOrder || (_ld != _rows) || (_start != 0))\n    {\n      // shrink memeory if needed\n      auto baseNew = std::make_shared<MatrixBase>(_rows*_columns, FALSE, 0.);\n      if(!_rowMajorOrder)\n        lapack_dlacpy(_rows, _columns, const_field(), ld(), baseNew->field(), _rows);\n      else\n        for(UInt i=0; i<_columns; i++)\n          blas_dcopy(static_cast<F77Int>(_rows), const_field()+i, static_cast<F77Int>(ld()), baseNew->field()+i*_rows, 1);\n      base           = std::move(baseNew);\n      _start         = 0;\n      _ld            = _rows;\n      _rowMajorOrder = FALSE;\n    }\n    else if(!movePossible || (base.use_count() > 1))\n    {\n      auto baseNew = std::make_shared<MatrixBase>(*base);\n      base = std::move(baseNew);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix::Matrix(const Matrix &x)            : MatrixSlice(x)            {assignment();}\nMatrix::Matrix(const const_MatrixSlice &x) : MatrixSlice(x)            {assignment();}\nMatrix::Matrix(Matrix &&x)                 : MatrixSlice(std::move(x)) {assignment(TRUE);}\nMatrix::Matrix(const_MatrixSlice &&x)      : MatrixSlice(std::move(x)) {assignment(TRUE);}\n\n/***********************************************/\n\nMatrix::Matrix(std::initializer_list<std::initializer_list<Double>> list) : MatrixSlice(list.size(), (list.size() ? list.begin()->size() : 0), GENERAL, UPPER, FALSE, 0.)\n{\n  try\n  {\n    for(const auto &l : list)\n      if(l.size() != columns())\n        throw(Exception(\"All rows of matrix must have same number of columns when constructing from vectors. Expected \"+columns()%\"%i columns but got \"s+l.size()%\"%i.\"s));\n\n    for(UInt i=0; i<rows(); i++)\n      for(UInt k=0; k<columns(); k++)\n        (*this)(i, k) = *((list.begin()+i)->begin()+k);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix &Matrix::operator=(const const_MatrixSlice &x)\n{\n  _rows          = x._rows;\n  _columns       = x._columns;\n  _start         = x._start;\n  _ld            = x._ld;\n  _type          = x._type;\n  _uplo          = x._uplo;\n  _rowMajorOrder = x._rowMajorOrder;\n  base           = x.base;\n  assignment();\n  return *this;\n}\n\n/***********************************************/\n\nMatrix &Matrix::operator=(const Matrix &x)\n{\n  return operator=(static_cast<const const_MatrixSlice &>(x));\n}\n\n/***********************************************/\n\nMatrix &Matrix::operator=(const_MatrixSlice &&x)\n{\n  _rows          = x._rows;\n  _columns       = x._columns;\n  _start         = x._start;\n  _ld            = x._ld;\n  _type          = x._type;\n  _uplo          = x._uplo;\n  _rowMajorOrder = x._rowMajorOrder;\n  base           = std::move(x.base);\n  assignment(TRUE);\n  return *this;\n}\n\n/***********************************************/\n\nMatrix &Matrix::operator=(Matrix &&x)\n{\n  return operator=(std::move(static_cast<const_MatrixSlice &>(x)));\n}\n\n/***********************************************/\n/***** Vector **********************************/\n/***********************************************/\n\nVector::Vector(const const_MatrixSlice &x) : Matrix(x)\n{\n  try\n  {\n    if(columns() > 1)\n      throw(Exception(\"Matrix assignment to Vector with more than 1 column\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector::Vector(const_MatrixSlice &&x) : Matrix(std::move(x))\n{\n  try\n  {\n    if(columns() > 1)\n      throw(Exception(\"Matrix assignment to Vector with more than 1 column\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector::Vector(std::initializer_list<Double> list) : Matrix(list.size(), 1, Matrix::NOFILL)\n{\n  try\n  {\n    for(UInt i=0; i<list.size(); i++)\n      (*this)(i) = *(list.begin()+i);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector::Vector(const std::vector<Double> &x) : Matrix(x.size(), 1, Matrix::NOFILL)\n{\n  try\n  {\n    for(UInt i=0; i<x.size(); i++)\n      (*this)(i) = x[i];\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector &Vector::operator=(const const_MatrixSlice &x)\n{\n  try\n  {\n    if(x.columns() > 1)\n      throw(Exception(\"Matrix assignment to Vector with more than 1 column\"));\n    Matrix::operator=(x);\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector &Vector::operator=(const_MatrixSlice &&x)\n{\n  try\n  {\n    if(x.columns() > 1)\n      throw(Exception(\"Matrix assignment to Vector with more than 1 column\"));\n    Matrix::operator=(std::move(x));\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector::operator std::vector<Double> () const\n{\n  try\n  {\n    std::vector<Double> x(rows());\n    for(UInt i=0; i<x.size(); i++)\n      x[i] = operator()(i);\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***** FUNCTIONS *******************************/\n/***********************************************/\n\nMatrix identityMatrix(UInt size, Matrix::Type type)\n{\n  Matrix I(size, type);\n  for(UInt i=0; i<size; i++)\n    I(i,i) = 1.0;\n  return I;\n}\n\n/***********************************************/\n\nvoid fillSymmetric(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.getType()!=Matrix::SYMMETRIC)\n      throw(Exception(\"Matrix must be SYMMETRIC\"));\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n\n    if(A.isUpper())\n      for(UInt i=0; i<A.rows(); i++)\n        copy(A.slice(i, i+1, 1, A.columns()-i-1).trans(), A.slice(i+1, i, A.rows()-i-1, 1));\n    else\n      for(UInt i=0; i<A.columns(); i++)\n        copy(A.slice(i+1, i, A.rows()-i-1, 1).trans(), A.slice(i, i+1, 1, A.columns()-i-1));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid zeroUnusedTriangle(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.getType()!=Matrix::TRIANGULAR)\n      throw(Exception(\"Matrix must be TRIANGULAR\"));\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n\n    if(A.isUpper()) // set lower triangle to zero\n      for(UInt k=0; k<A.columns()-1; k++)\n        A.slice(k+1, k, A.rows()-k-1, 1).setNull();\n    else  // set upper triangle to zero\n      for(UInt k=1; k<A.columns(); k++)\n        A.slice(k, k+1, 1, A.columns()-k-1).setNull();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n//***********************************************/\n\nvoid copy(const_MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if((A.size()==0) && (B.size()==0))\n      return;\n    if((A.rows()!=B.rows()) || (A.columns()!=B.columns()))\n      throw(Exception(\"Dimension error: (\"+A.rows()%\"%i x \"s+A.columns()%\"%i) and (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s));\n\n    const UInt rows    = (B.isRowMajorOrder()) ? B.columns() : B.rows();\n    const UInt columns = (B.isRowMajorOrder()) ? B.rows() : B.columns();\n    if(A.isRowMajorOrder() == B.isRowMajorOrder())\n      lapack_dlacpy(rows, columns, A.const_field(),A.ld(), B.field(),B.ld());\n    else\n      for(UInt i=0; i<columns; i++)\n        blas_dcopy(static_cast<F77Int>(rows), A.const_field()+i, static_cast<F77Int>(A.ld()), B.field()+i*B.ld(), 1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid swap(MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if((A.size()==0) && (B.size()==0))\n      return;\n    if((A.rows()!=B.rows()) || (A.columns()!=B.columns()))\n      throw(Exception(\"Dimension error: (\"+A.rows()%\"%i x \"s+A.columns()%\"%i) and (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s));\n\n    const UInt ldA  = (A.isRowMajorOrder()) ? 1 : A.ld();\n    const UInt incA = (A.isRowMajorOrder()) ? A.ld() : 1;\n    const UInt ldB  = (B.isRowMajorOrder()) ? 1 : B.ld();\n    const UInt incB = (B.isRowMajorOrder()) ? B.ld() : 1;\n    if(A.rows()>=A.columns())\n      for(UInt i=0; i<A.columns(); i++)\n        blas_dswap(static_cast<F77Int>(A.rows()), A.const_field()+i*ldA, static_cast<F77Int>(incA), B.field()+i*ldB, static_cast<F77Int>(incB));\n    else\n      for(UInt i=0; i<A.rows(); i++)\n        blas_dswap(static_cast<F77Int>(A.columns()), A.const_field()+i*incA, static_cast<F77Int>(ldA), B.field()+i*incB, static_cast<F77Int>(ldB));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n//***********************************************/\n\nvoid reshape(const_MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if(A.size() != B.size())\n      throw(Exception(\"Dimension error: (\"+A.rows()%\"%i x \"s+A.columns()%\"%i) can't be reshaped to (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s));\n    if(A.size()==0)\n      return;\n\n    if(A.rows() == B.rows())\n      copy(A, B);\n    else\n      for(UInt i=0; i<A.size(); i++)\n        B(i%B.rows(), i/B.rows()) = A(i%A.rows(), i/A.rows());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n//***********************************************/\n\nMatrix reshape(const_MatrixSliceRef A, UInt rows, UInt columns)\n{\n  try\n  {\n    if(!rows && !columns)\n      throw(Exception(\"Only one dimension can be automatically determined.\"));\n    Matrix B(rows ? rows : A.size()/columns, columns ? columns : A.size()/rows);\n    reshape(A, B);\n    return B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\nMatrix reorder(const_MatrixSliceRef A, const std::vector<UInt> &rowIndex)\n{\n  try\n  {\n    Matrix B(rowIndex.size(), A.columns(), Matrix::NOFILL);\n    for(UInt i=0; i<B.rows(); i++)\n      if(rowIndex[i] != NULLINDEX)\n        copy(A.row(rowIndex.at(i)), B.row(i));\n      else\n        B.row(i).setNull();\n    return B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool isStrictlyZero(const_MatrixSliceRef A)\n{\n  try\n  {\n    for(UInt c = 0; c<A.columns(); c++)\n      for(UInt r = 0; r<A.rows(); r++)\n        if(A(r, c) != 0.0)\n          return FALSE;\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n\n}\n\n/***********************************************/\n\nDouble inner(const_MatrixSliceRef A, const_MatrixSliceRef B)\n{\n  try\n  {\n    if((A.size()==0) && (B.size()==0))\n      return 0.;\n    if((A.rows()!=B.rows()) || (A.columns()!=B.columns()))\n      throw(Exception(\"Dimension error: (\"+A.rows()%\"%i x \"s+A.columns()%\"%i)  and (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s));\n\n    const UInt rows    = (B.isRowMajorOrder()) ? B.columns() : B.rows();\n    const UInt columns = (B.isRowMajorOrder()) ? B.rows() : B.columns();\n    const Double *ptr1 = A.const_field();\n    const Double *ptr2 = B.const_field();\n    Double sum  = 0;\n\n    if(A.isRowMajorOrder() == B.isRowMajorOrder())\n      for(UInt i=0; i<columns; i++)\n        sum += blas_ddot(static_cast<F77Int>(rows), ptr1+i*A.ld(), 1, ptr2+i*B.ld(), 1);\n    else\n      for(UInt i=0; i<columns; i++)\n        sum += blas_ddot(static_cast<F77Int>(rows), ptr1+i, static_cast<F77Int>(A.ld()), ptr2+i*B.ld(), 1);\n    return sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble sum(const_MatrixSliceRef A)\n{\n  try\n  {\n    Double sum = 0;\n    for(UInt i=0; i<A.rows(); i++)\n      for(UInt k=0; k<A.columns(); k++)\n        sum += A(i,k);\n    return sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble trace(const_MatrixSliceRef A)\n{\n  try\n  {\n    if(A.rows() != A.columns())\n      throw(Exception(\"Dimension error: A(\"+A.rows()%\"%i x \"s+A.columns()%\"%i) Matrix must be square!\"s));\n\n    Double tr = 0;\n    for(UInt i=0; i<A.rows(); i++)\n      tr += A(i,i);\n    return tr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble determinant(const_MatrixSliceRef A)\n{\n  Double sign = 0.0;\n  Double logdet = logdeterminant(A, sign);\n\n  return sign * std::exp(logdet);\n}\n\n/***********************************************/\n\nDouble logdeterminant(const_MatrixSliceRef A, Double& sign)\n{\n  try\n  {\n    if(A.rows() != A.columns())\n      throw(Exception(\"Determinant is only defined for square matrices: A(\"+A.rows()%\"%i x \"s+A.columns()%\"%i).\"s));\n\n    sign = 0.0;\n    Double logdet = -std::numeric_limits<Double>::infinity();\n\n    if(A.getType() == Matrix::TRIANGULAR)\n    {\n      UInt countNegative = 0;\n      logdet = 0.0;\n\n      // eigenvalues of a triangular matrix are its diagonal elements\n      for(UInt k = 0; k<A.rows(); k++)\n      {\n        logdet += std::log(std::abs(A(k, k)));\n        if(A(k, k)<0)\n          countNegative++;\n      }\n      sign = (countNegative % 2) == 0 ? 1.0 : -1.0;\n    }\n    else // GENERAL and SYMMETRIC matrices from QR decomposition: det(A) = det(Q)*det(R) = det(R)*(-1)^s\n    {\n      Matrix R = A; // copy for decomposition\n      if(R.getType() == Matrix::SYMMETRIC)\n      {\n        fillSymmetric(R);\n        R.setType(Matrix::GENERAL);\n      }\n\n      Vector tau = QR_decomposition(R); // A = QR\n      Double signR = 0.0;\n      logdet = logdeterminant(R, signR); // recursive call for det(R)\n      UInt houseHolderCount = R.columns()-1; // det(Q) depends on number of reflectors: number of columns-1\n\n      sign = (houseHolderCount % 2) == 0 ? signR : -signR;  // flip sign if necessary\n    }\n\n    return logdet;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble maxabs(const_MatrixSliceRef A)\n{\n  Double d = 0;\n  for(UInt i=0; i<A.rows(); i++)\n    for(UInt k=0; k<A.columns(); k++)\n      d = std::max(d, std::fabs(A(i,k)));\n  return A.size() ? d : NAN_EXPR;\n}\n\n/***********************************************/\n\nDouble min(const_MatrixSliceRef A)\n{\n  Double d = std::numeric_limits<double>::max();\n  for(UInt i=0; i<A.rows(); i++)\n    for(UInt k=0; k<A.columns(); k++)\n      d = std::min(d, A(i,k));\n  return A.size() ? d : NAN_EXPR;\n}\n\n/***********************************************/\n\nDouble max(const_MatrixSliceRef A)\n{\n  Double d = std::numeric_limits<double>::min();\n  for(UInt i=0; i<A.rows(); i++)\n    for(UInt k=0; k<A.columns(); k++)\n      d = std::max(d, A(i,k));\n  return A.size() ? d : NAN_EXPR;\n}\n\n/***********************************************/\n\nDouble median(const_MatrixSliceRef A)\n{\n  try\n  {\n    if(!A.size())\n      return NAN_EXPR;\n    std::vector<Double> data = flatten(A);\n    std::partial_sort(data.begin(), data.begin()+data.size()/2+1, data.end());\n    return (data.size()%2) ? data.at(data.size()/2) : (0.5*(data.at(data.size()/2-1)+data.at(data.size()/2)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble medianAbsoluteDeviation(const_MatrixSliceRef A)\n{\n  try\n  {\n    if(!A.size())\n      return NAN_EXPR;\n    // median\n    std::vector<Double> data = flatten(A);\n    std::partial_sort(data.begin(), data.begin()+data.size()/2+1, data.end());\n    const Double median = (data.size()%2) ? data.at(data.size()/2) : (0.5*(data.at(data.size()/2-1)+data.at(data.size()/2)));\n    // absolute deviation\n    std::for_each(data.begin(), data.end(), [&](auto &x) {x = std::abs(x-median);});\n    std::partial_sort(data.begin(), data.begin()+data.size()/2+1, data.end());\n    return (data.size()%2) ? data.at(data.size()/2) : (0.5*(data.at(data.size()/2-1)+data.at(data.size()/2)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid axpy(Double c, const_MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if((A.size()==0) && (B.size()==0))\n      return;\n    if((A.rows()!=B.rows()) || (A.columns()!=B.columns()))\n      throw(Exception(\"Dimension error: (\"+A.rows()%\"%i x \"s+A.columns()%\"%i)  and (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s));\n\n    const UInt rows    = (B.isRowMajorOrder()) ? B.columns() : B.rows();\n    const UInt columns = (B.isRowMajorOrder()) ? B.rows() : B.columns();\n    const Double *ptr1 = A.const_field();\n          Double *ptr2 = B.field();\n\n    if(A.isRowMajorOrder() == B.isRowMajorOrder())\n      for(UInt i=0; i<columns; i++)\n        blas_daxpy(static_cast<F77Int>(rows), c, ptr1+i*A.ld(), 1, ptr2+i*B.ld(), 1);\n    else\n      for(UInt i=0; i<columns; i++)\n        blas_daxpy(static_cast<F77Int>(rows), c, ptr1+i, static_cast<F77Int>(A.ld()), ptr2+i*B.ld(), 1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Matrix-Matrix multiplication: C += c * A * B.\nvoid matMult(Double c, const_MatrixSliceRef A, const_MatrixSliceRef B, MatrixSliceRef C)\n{\n  try\n  {\n    if((A.columns()!=B.rows())||(A.rows()!=C.rows())||(B.columns()!=C.columns()))\n      throw(Exception(\"Dimension error\"));\n    if(C.size()==0)\n      return;\n    if(C.getType()!=Matrix::GENERAL)\n      throw(Exception(\"Matrix C must be GENERAL\"));\n\n    if((A.getType()==Matrix::TRIANGULAR) && (B.getType()==Matrix::GENERAL))\n    {\n      Matrix B2 = B;\n      triangularMult(c,A,B2);\n      axpy(1., B2, C);\n      return;\n    }\n\n    if((A.getType()==Matrix::GENERAL) && (B.getType()==Matrix::TRIANGULAR))\n    {\n      Matrix A2 = A;\n      triangularMult(c, B.trans(), A2.trans());\n      axpy(1., A2, C);\n      return;\n    }\n\n    if((A.getType()==Matrix::SYMMETRIC) && (B.getType()==Matrix::GENERAL) && (C.isRowMajorOrder() == B.isRowMajorOrder()))\n    {\n      const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n      if(!C.isRowMajorOrder())\n        blas_dsymm(TRUE, isUpper, static_cast<F77Int>(C.rows()), static_cast<F77Int>(C.columns()),\n                   c, A.const_field(), static_cast<F77Int>(A.ld()), B.const_field(), static_cast<F77Int>(B.ld()), 1.0, C.field(), static_cast<F77Int>(C.ld()));\n      else\n        blas_dsymm(FALSE, isUpper, static_cast<F77Int>(C.columns()), static_cast<F77Int>(C.rows()),\n                   c, A.const_field(), static_cast<F77Int>(A.ld()), B.const_field(), static_cast<F77Int>(B.ld()), 1.0, C.field(), static_cast<F77Int>(C.ld()));\n      return;\n    }\n\n    if((A.getType()==Matrix::GENERAL) && (B.getType()==Matrix::SYMMETRIC) && (C.isRowMajorOrder() == A.isRowMajorOrder()))\n    {\n      const Bool isUpper = (B.isRowMajorOrder()) ? (!B.isUpper()) : B.isUpper();\n      if(!C.isRowMajorOrder())\n        blas_dsymm(FALSE, isUpper, static_cast<F77Int>(C.rows()), static_cast<F77Int>(C.columns()),\n                   c, B.const_field(), static_cast<F77Int>(B.ld()), A.const_field(), static_cast<F77Int>(A.ld()), 1.0, C.field(), static_cast<F77Int>(C.ld()));\n      else\n        blas_dsymm(TRUE, isUpper, static_cast<F77Int>(C.columns()), static_cast<F77Int>(C.rows()),\n                   c, B.const_field(), static_cast<F77Int>(B.ld()), A.const_field(), static_cast<F77Int>(A.ld()), 1.0, C.field(), static_cast<F77Int>(C.ld()));\n      return;\n    }\n\n    if((A.getType()!=Matrix::GENERAL) || (B.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Combination of Matrix types not implemented\"));\n\n    if(!C.isRowMajorOrder())\n      blas_dgemm(A.isRowMajorOrder(), B.isRowMajorOrder(), static_cast<F77Int>(C.rows()), static_cast<F77Int>(C.columns()), static_cast<F77Int>(A.columns()),\n                 c, A.const_field(), static_cast<F77Int>(A.ld()), B.const_field(), static_cast<F77Int>(B.ld()), 1.0, C.field(), static_cast<F77Int>(C.ld()));\n    else\n      blas_dgemm(!B.isRowMajorOrder(), !A.isRowMajorOrder(), static_cast<F77Int>(C.columns()), static_cast<F77Int>(C.rows()), static_cast<F77Int>(A.columns()),\n                 c, B.const_field(), static_cast<F77Int>(B.ld()), A.const_field(), static_cast<F77Int>(A.ld()), 1.0, C.field(), static_cast<F77Int>(C.ld()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"C(\"s+C.rows()%\"%i x \"s+C.columns()%\"%i) = A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i) * B(\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid rankKUpdate(Double c, const_MatrixSliceRef A, MatrixSliceRef N)\n{\n  try\n  {\n    if((N.rows()!=N.columns())||(A.columns()!=N.rows()))\n      throw(Exception(\"Dimension error\"));\n    if((N.size()==0) || (A.size()==0))\n      return;\n    if((N.getType()!=Matrix::SYMMETRIC)||(A.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Matrix A must be GENERAL and Matrix N must be SYMMETRIC\"));\n\n    const Bool isUpper = (N.isRowMajorOrder()) ? (!N.isUpper()) : N.isUpper();\n    blas_dsyrk(isUpper, !A.isRowMajorOrder(), static_cast<F77Int>(N.rows()), static_cast<F77Int>(A.rows()),\n               c, A.const_field(), static_cast<F77Int>(A.ld()), 1.0, N.field(), static_cast<F77Int>(N.ld()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"N = A'A mit A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i) and N = (\"s+N.rows()%\"%i x \"s+N.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid rank2KUpdate(Double c, const_MatrixSliceRef A, const_MatrixSliceRef B, MatrixSliceRef N)\n{\n  try\n  {\n    if((N.rows()!=N.columns())||(A.columns()!=N.rows())||(B.columns()!=N.rows()))\n      throw(Exception(\"Dimension error\"));\n    if(N.size()==0)\n      return;\n    if((N.getType()!=Matrix::SYMMETRIC)||(A.getType()!=Matrix::GENERAL)||(B.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Matrix A and B must be GENERAL and Matrix N must be SYMMETRIC\"));\n    if(A.isRowMajorOrder() != B.isRowMajorOrder())\n      throw(Exception(\"not possible\"));\n\n    const Bool isUpper = (N.isRowMajorOrder()) ? (!N.isUpper()) : N.isUpper();\n    blas_dsyr2k(isUpper, !A.isRowMajorOrder(), static_cast<F77Int>(N.rows()), static_cast<F77Int>(A.rows()),\n                c, A.const_field(), static_cast<F77Int>(A.ld()), B.const_field(), static_cast<F77Int>(B.ld()), 1.0, N.field(), static_cast<F77Int>(N.ld()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"N = A'B+B'A mit A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i), B = (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i), N = (\"s+N.rows()%\"%i x \"s+N.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid inverse(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.size()==0)\n      return;\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n\n    Int info = 0;\n    if(A.getType()==Matrix::TRIANGULAR)\n    {\n      const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n      info = lapack_dtrtri(isUpper, A.rows(),A.field(),A.ld());\n    }\n    else if(A.getType()==Matrix::SYMMETRIC)\n    {\n      cholesky(A);\n      const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n      info = lapack_dpotri(isUpper, A.rows(),A.field(),A.ld());\n      const_cast<MatrixSlice&>(A).setType(Matrix::SYMMETRIC);\n    }\n    else\n    {\n      Int *ipiv = new Int[A.rows()];\n      info = lapack_dgetrf(A.rows(),A.columns(), A.field(),A.ld(),ipiv);\n      if(info==0)\n        info = lapack_dgetri(A.rows(),A.field(),A.ld(),ipiv);\n      delete[] ipiv;\n    }\n\n    if(info!=0)\n      throw(Exception(\"can not compute inverse, error = \"+info%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nVector eigenValueDecomposition(MatrixSliceRef A, Bool computeEigenVectors)\n{\n  try\n  {\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n    if(A.getType()!=Matrix::SYMMETRIC)\n      throw(Exception(\"Matrix must be SYMMETRIC\"));\n\n    Vector eigen(A.rows());\n    const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    const Int info = lapack_dsyev(computeEigenVectors, isUpper, A.rows(),A.field(),A.ld(), eigen.field());\n    const_cast<MatrixSlice&>(A).setType(Matrix::GENERAL);\n    if(info!=0)\n      throw(Exception(\"cannot compute eigen values, error = \"+info%\"%i\"s));\n    return eigen;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix eigenValueDecomposition(MatrixSliceRef A, Matrix &VL, Matrix &VR, Bool computeEigenVectors)\n{\n  try\n  {\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n    if(A.getType()!=Matrix::GENERAL)\n      throw(Exception(\"Matrix must be GENERAL\"));\n\n    Matrix eigenValues(A.rows(), 2, Matrix::NOFILL);\n    Int    info;\n    if(computeEigenVectors)\n    {\n      VL = Matrix(A.rows(), A.rows(), Matrix::NOFILL);\n      VR = Matrix(A.rows(), A.rows(), Matrix::NOFILL);\n      info = lapack_dgeev(TRUE, TRUE, A.rows(), A.field(), A.ld(),   // Input matrix field\n                          &eigenValues(0,0), &eigenValues(0,1),      // Real and complex eigenvalue vectors\n                          VL.field(), VL.ld(), VR.field(), VR.ld()); // Left and right eigenvectors\n    }\n    else\n    {\n      info = lapack_dgeev(FALSE, FALSE, A.rows(), A.field(), A.ld(), // Input matrix field\n                          &eigenValues(0,0), &eigenValues(0,1),      // Real and complex eigenvalue vectors\n                          nullptr, 1, nullptr, 1);\n    }\n\n    if(info!=0)\n      throw(Exception(\"cannot compute eigen values, error = \"+info%\"%i\"s));\n    return eigenValues;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nVector singularValueDecomposition(MatrixSliceRef A, Matrix &U, Matrix &Vt, Bool computeSingularVectors)\n{\n  try\n  {\n    if(A.isRowMajorOrder())\n      throw(Exception(\"Matrix must not be transposed\"));\n\n    const UInt m = A.rows();\n    const UInt n = A.columns();\n    const UInt s = std::min(m,n);\n    Vector singular(s);\n    Int    info;\n    if(computeSingularVectors)\n    {\n      U  = Matrix(m, s, Matrix::NOFILL);\n      Vt = Matrix(s, n, Matrix::NOFILL);\n      info = lapack_dgesdd(TRUE, m, n, A.field(), A.ld(), singular.field(), U.field(), U.ld(), Vt.field(), Vt.ld());\n    }\n    else\n      info = lapack_dgesdd(FALSE, m, n, A.field(), A.ld(), singular.field(), nullptr, 1, nullptr, 1);\n\n    if(info!=0)\n      throw(Exception(\"cannot compute singular values, error = \"+info%\"%i\"s));\n    return singular;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix pseudoInverse(const_MatrixSliceRef A, Double rcond)\n{\n  try\n  {\n    // symmetric positive semidefinite\n    if(A.getType() == Matrix::SYMMETRIC)\n    {\n      Matrix U = A; // copy contents of A\n      Vector s = eigenValueDecomposition(U);\n\n      const Double maxS = maxabs(s);\n      for(UInt k=0; k<s.rows(); k++)\n        U.column(k) *= (s(k) >= (rcond*maxS)) ? 1./sqrt(s(k)) : 0.;\n\n      Matrix Inv(A.rows(), Matrix::SYMMETRIC);\n      rankKUpdate(1., U.trans(), Inv);\n      return Inv;\n    }\n\n    // general inverse\n    Matrix U, Vt;\n    Vector s = singularValueDecomposition(Matrix(A), U, Vt);\n\n    const Double maxS = maxabs(s);\n    for(UInt k=0; k<s.rows(); k++)\n      U.column(k) *= (std::fabs(s(k)) >= (rcond*maxS)) ? 1./s(k) : 0.;\n\n    return Vt.trans() * U.trans();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix matrixSquareRoot(const_MatrixSliceRef A, Double rcond)\n{\n  try\n  {\n    if(A.getType() != Matrix::SYMMETRIC)\n      throw(Exception(\"Input matrix must be SYMMETRIC.\"));\n\n    Matrix Q = A; // copy contents of A\n    Matrix U, Vt;\n    Vector e = singularValueDecomposition(Q, U, Vt, TRUE);\n\n    const Double maxE = maxabs(e);\n    for(UInt k=0; k<e.rows(); k++)\n    {\n      if(e(k) < -(rcond*maxE))\n        throw(Exception(\"Input matrix must be positive semidefinite\"));\n      U.column(k) *= (e(k) >= (rcond*maxE)) ? std::sqrt(e(k)) : 0.;\n    }\n\n    return U*Vt; // Q*sqrt(E)*Q.trans()\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix matrixSquareRootInverse(const_MatrixSliceRef A, Double rcond)\n{\n  try\n  {\n    if(A.getType() != Matrix::SYMMETRIC)\n      throw(Exception(\"Input matrix must be SYMMETRIC.\"));\n\n    Matrix Q = A; // copy contents of A\n    Matrix U, Vt;\n    Vector e = singularValueDecomposition(Q, U, Vt, TRUE);\n\n    const Double maxE = maxabs(e);\n    for(UInt k=0; k<e.rows(); k++)\n    {\n      if(e(k) < -(rcond*maxE))\n        throw(Exception(\"Input matrix must be positive semidefinite\"));\n      U.column(k) *= (e(k) >= (rcond*maxE)) ? 1.0/std::sqrt(e(k)) : 0.;\n    }\n\n    return U*Vt; // Q*E^(-0.5)*Q.trans()\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix kron(const_MatrixSliceRef A, const_MatrixSlice B)\n{\n  try\n  {\n    Matrix C(A.rows()*B.rows(), A.columns()*B.columns());\n    for(UInt i=0; i<A.rows(); i++)\n      for(UInt k=0; k<A.columns(); k++)\n        axpy(A(i, k), B, C.slice(i*B.rows(), k*B.columns(), B.rows(), B.columns()));\n    return C;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix toeplitz(const Vector &a)\n{\n  try\n  {\n    Matrix A(a.rows(), Matrix::SYMMETRIC);\n    for(UInt i=0; i<A.columns(); i++)\n      copy(a.row(0, a.rows()-i).trans(), A.slice(i, i, 1, A.rows()-i));\n    fillSymmetric(A);\n    return A;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid solveInPlace(MatrixSliceRef N, MatrixSliceRef B)\n{\n  try\n  {\n    if(N.rows()!=N.columns()||(N.columns()!=B.rows()))\n      throw(Exception(\"Dimension error\"));\n    if(B.size()==0)\n      return;\n    if(B.getType()!=Matrix::GENERAL)\n      throw(Exception(\"Matrix B must be GENERAL\"));\n\n    if(N.getType()==Matrix::TRIANGULAR)\n    {\n      triangularSolve(1.0, N, B);\n    }\n    else if(N.getType()==Matrix::SYMMETRIC)\n    {\n      cholesky(N);\n      triangularSolve(1.0, N.trans(), B);\n      triangularSolve(1.0, N, B);\n    }\n    else if(N.getType()==Matrix::GENERAL)\n    {\n      if(N.isRowMajorOrder() || B.isRowMajorOrder())\n        throw(Exception(\"Matricies must not be transposed, if N == GENERAL\"));\n      Int *ipiv = new Int[N.rows()];\n      const Int info = lapack_dgesv(B.rows(),B.columns(), N.field(),N.ld(), ipiv, B.field(),B.ld());\n      delete[] ipiv;\n      if(info!=0)\n        throw(Exception(\"cannot solve system, error = \"+info%\"%i\"s));\n    }\n    else\n      throw(Exception(\"Matrix Type not implemented\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"B := N(\"s+N.rows()%\"%i x \"s+N.columns()%\"%i)^-1 * B = (\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix leastSquares(MatrixSliceRef A, MatrixSliceRef l)\n{\n  try\n  {\n    if((A.getType()!=Matrix::GENERAL)||(l.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Matrix A and l must be GENERAL\"));\n    if((A.rows()<A.columns())||(A.rows()!=l.rows()))\n      throw(Exception(\"Dimension error\"));\n    if(l.isRowMajorOrder())\n      throw(Exception(\"l must not be transposed\"));\n\n    Vector tau = QR_decomposition(A);\n    QTransMult(A, tau, l);\n    Matrix x = l.row(0, tau.rows());\n    triangularSolve(1., A.row(0, tau.rows()), x);\n    l.row(0, tau.rows()).setNull();\n    QMult(A, tau, l);\n\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"min[ A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)*x - l(\"s+l.rows()%\"%i x \"s+l.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceLeastSquaresFit(const_MatrixSliceRef A, MatrixSliceRef l)\n{\n  try\n  {\n    if((A.getType()!=Matrix::GENERAL)||(l.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Matrix A and l must be GENERAL\"));\n    if((A.rows()<A.columns())||(A.rows()!=l.rows()))\n      throw(Exception(\"Dimension error\"));\n\n    Matrix B = A;\n    Vector tau = QR_decomposition(B);\n    QTransMult(B, tau, l);\n    l.row(0,tau.rows()).setNull();\n    QMult(B, tau, l);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"min[ A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)*x - l(\"s+l.rows()%\"%i x \"s+l.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid eliminationParameter(MatrixSliceRef B, const std::vector<std::reference_wrapper<Matrix>> &listA)\n{\n  try\n  {\n    const Vector tau = QR_decomposition(B);\n    for(Matrix &A : listA)\n    {\n      if(A.rows() != B.rows())\n        throw(Exception(\"Dimension error: B(\"s+B.rows()%\"%i x \"s+B.columns()%\"%i), A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s));\n      QTransMult(B, tau, A);\n      A = A.row(B.columns(), A.rows()-B.columns());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Triangular matrix\n// -----------------\nvoid cholesky(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.getType()!=Matrix::SYMMETRIC)\n      throw(Exception(\"Matrix must be SYMMETRIC\"));\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n\n    const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    const Int info = lapack_dpotrf(isUpper, A.rows(), A.field(),A.ld());\n    const_cast<MatrixSlice&>(A).setType(Matrix::TRIANGULAR, Matrix::UPPER);\n    if(isUpper)\n      const_cast<MatrixSlice&>(A)._rowMajorOrder = FALSE;\n    else\n      const_cast<MatrixSlice&>(A)._rowMajorOrder = TRUE;\n    if(info!=0)\n      throw(Exception(\"cannot compute decomposition, error = \"+info%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"W'W = A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<UInt> choleskyPivoting(MatrixSliceRef A, UInt &rank, Double tolerance)\n{\n  try\n  {\n    if(A.getType()!=Matrix::SYMMETRIC)\n      throw(Exception(\"Matrix must be SYMMETRIC\"));\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n\n    F77Int *ipiv = new F77Int[A.rows()];\n    F77Int  irank;\n    const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    const Int info = lapack_dpstrf(isUpper, A.rows(), A.field(), A.ld(), ipiv, irank, tolerance);\n    const_cast<MatrixSlice&>(A).setType(Matrix::TRIANGULAR, Matrix::UPPER);\n    if(isUpper)\n      const_cast<MatrixSlice&>(A)._rowMajorOrder = FALSE;\n    else\n      const_cast<MatrixSlice&>(A)._rowMajorOrder = TRUE;\n\n    if(info<0)\n      throw(Exception(\"cannot compute decomposition, error = \"+info%\"%i\"s));\n\n    rank = irank;\n    std::vector<UInt> piv(A.rows());\n    for(UInt i=0; i<piv.size(); i++)\n      piv[i] = static_cast<UInt>(ipiv[i]-1);\n    delete[] ipiv;\n    return piv;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"W'W = A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid cholesky2Inverse(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n    if(A.size()==0)\n      return;\n    if(A.getType()!=Matrix::TRIANGULAR)\n      throw(Exception(\"Matrix must be TRIANGULAR\"));\n\n    const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    const Int info = lapack_dpotri(isUpper, A.rows(),A.field(),A.ld());\n    const_cast<MatrixSlice&>(A).setType(Matrix::SYMMETRIC);\n    if(info!=0)\n      throw(Exception(\"can not compute inverse, error = \"+info%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid choleskyProduct(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.rows()!=A.columns())\n      throw(Exception(\"Dimension error\"));\n    if(A.getType()!=Matrix::TRIANGULAR)\n      throw(Exception(\"Matrix must be TRIANGULAR\"));\n    if(A.size()==0)\n      return;\n\n    const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    const Int info = lapack_dlauum(isUpper, A.rows(), A.field(),A.ld());\n    const_cast<MatrixSlice&>(A).setType(Matrix::SYMMETRIC);\n    if(info!=0)\n      throw(Exception(\"cannot compute W'W, error = \"+info%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid triangularMult(Double c, const_MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if((A.getType()!=Matrix::TRIANGULAR)||(B.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Matrix A must be TRIANGULAR and Matrix B must be GENERAL\"));\n    if((A.rows()!=A.columns())||(A.columns()!=B.rows()))\n      throw(Exception(\"Dimension error\"));\n\n    Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    if(!B.isRowMajorOrder())\n      blas_dtrmm(TRUE,  isUpper, A.isRowMajorOrder(), FALSE, static_cast<F77Int>(B.rows()), static_cast<F77Int>(B.columns()),\n                 c, A.const_field(), static_cast<F77Int>(A.ld()), B.field(), static_cast<F77Int>(B.ld()));\n    else\n      blas_dtrmm(FALSE, isUpper, !A.isRowMajorOrder(), FALSE, static_cast<F77Int>(B.columns()), static_cast<F77Int>(B.rows()),\n                 c, A.const_field(), static_cast<F77Int>(A.ld()), B.field(), static_cast<F77Int>(B.ld()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"B = A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i) * B(\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid triangularSolve(Double c, const_MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if((A.getType()!=Matrix::TRIANGULAR)||(B.getType()!=Matrix::GENERAL))\n      throw(Exception(\"Matrix A must be TRIANGULAR and Matrix B must be GENERAL\"));\n    if((A.rows()!=A.columns())||(A.columns()!=B.rows()))\n      throw(Exception(\"Dimension error\"));\n\n    const Bool isUpper = (A.isRowMajorOrder()) ? (!A.isUpper()) : A.isUpper();\n    if(!B.isRowMajorOrder())\n      blas_dtrsm(TRUE,  isUpper,  A.isRowMajorOrder(), FALSE, static_cast<F77Int>(B.rows()), static_cast<F77Int>(B.columns()),\n                c, A.const_field(), static_cast<F77Int>(A.ld()), B.field(), static_cast<F77Int>(B.ld()));\n    else\n      blas_dtrsm(FALSE, isUpper, !A.isRowMajorOrder(), FALSE, static_cast<F77Int>(B.columns()), static_cast<F77Int>(B.rows()),\n                 c, A.const_field(), static_cast<F77Int>(A.ld()), B.field(), static_cast<F77Int>(B.ld()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"B = A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)^-1 * B(\"s+B.rows()%\"%i x \"s+B.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVector QR_decomposition(MatrixSliceRef A)\n{\n  try\n  {\n    if(A.isRowMajorOrder())\n      throw(Exception(\"A.trans not implemented\"));\n\n    Vector tau (A.columns());\n    const Int info = lapack_dgeqrf(A.rows(), A.columns(), A.field(), A.ld(), tau.field());\n    if(info!=0)\n      throw(Exception(\"can not compute QR decomposition, error = \"+info%\"%i\"s));\n    const_cast<MatrixSlice&>(A).setType(Matrix::TRIANGULAR, Matrix::UPPER);\n    return tau;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid QMult(const_MatrixSliceRef B, const Vector &tau, MatrixSliceRef A)\n{\n  try\n  {\n    if((B.rows()!=A.rows())||(tau.rows()!=B.columns()))\n      throw(Exception(\"Dimension error\"));\n    if(A.getType()!=Matrix::GENERAL)\n      throw(Exception(\"Matrix A must be GENERAL\"));\n\n    if(!A.isRowMajorOrder())\n      lapack_dormqr(TRUE, FALSE, A.rows(),A.columns(),B.columns(), B.const_field(),B.ld(),tau.field(), A.field(),A.ld());\n    else\n      lapack_dormqr(FALSE, TRUE, A.columns(),A.rows(),B.columns(), B.const_field(),B.ld(),tau.field(), A.field(),A.ld());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Q(\"s+B.rows()%\"%i x \"s+B.columns()%\"%i) * A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid QTransMult(const_MatrixSliceRef B, const Vector &tau, MatrixSliceRef A)\n{\n  try\n  {\n    if((B.rows()!=A.rows())||(tau.rows()!=B.columns()))\n      throw(Exception(\"Dimension error\"));\n    if(A.getType()!=Matrix::GENERAL)\n      throw(Exception(\"Matrix C must be GENERAL\"));\n\n    if(!A.isRowMajorOrder())\n      lapack_dormqr(TRUE, TRUE, A.rows(),A.columns(),B.columns(), B.const_field(),B.ld(),tau.const_field(), A.field(),A.ld());\n    else\n      lapack_dormqr(FALSE, FALSE, A.columns(),A.rows(),B.columns(), B.const_field(),B.ld(),tau.const_field(), A.field(),A.ld());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Q(\"s+B.rows()%\"%i x \"s+B.columns()%\"%i) * A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n\n/***********************************************/\n\nvoid generateQ(MatrixSliceRef A, const Vector &tau)\n{\n  try\n  {\n    const Int info = lapack_dorgqr(A.rows(), A.columns(), tau.rows(), A.field(), A.ld(), tau.const_field());\n    if(info!=0)\n      throw(Exception(\"can not compute Q matrix, error = \"+info%\"%i\"s));\n    const_cast<MatrixSlice&>(A).setType(Matrix::GENERAL);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"A = (\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s, e)\n  }\n}\n"
  },
  {
    "path": "source/base/matrix.h",
    "content": "/***********************************************/\n/**\n* @file matrix.h\n*\n* @brief matrix computations.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @author Sebastian Strasser\n* @date 2001-06-16\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIX__\n#define __GROOPS_MATRIX__\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n\n/** @defgroup matrixGroup Matrix and Vector\n* @brief User friendly Classes for BLAS (Basic Linear Algebra Subroutines) and LAPACK (Linear Algebra Package).\n* @ingroup base */\n/// @{\n\n/***** DEFINES *********************************/\n\nclass MatrixBase;\nclass const_MatrixSlice;\nclass MatrixSlice;\nclass Matrix;\nclass Vector;\n\ntypedef const const_MatrixSlice &const_MatrixSliceRef; //!< reason is given in @ref const_MatrixSlice\ntypedef const MatrixSlice       &MatrixSliceRef;       //!< reason is given in @ref MatrixSlice\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n/** @brief Readonly view of a slice of a Matrix.\n* This is a reference to a memory area of a Matrix. It is intentend to be used as parameter of a function,\n* which operates on parts or all elements of the matrix without changing the size of the matrix.\n* Examples are copy, matMult or inverse. To store a matrix in a variable use the class Matrix instead.\n*\n* The class MatrixSlice itself should be a const reference in a function parameter definition.\n* Thus the function accepts temporally created const_MatrixSlice or Matrix as parameter.\n* As the following definition is a little bit confusing:\n* @code void f(const const_MatrixSlice &x); @endcode\n* a shortcut is defined with the same meaning:\n* @code void f(const_MatrixSliceRef x); @endcode */\nclass const_MatrixSlice\n{\npublic:\n  /// Matrix types\n  enum Type {GENERAL, SYMMETRIC, TRIANGULAR};\n\n  /** @brief upper or lower triangle.\n  * For SYMMETRIC or TRIANGULAR matrices.\n  * The other triangular is not accessed. */\n  enum Uplo {UPPER, LOWER};\n\n  const_MatrixSlice()                          = delete;  //!< Disallow default constructor.\n  const_MatrixSlice(const const_MatrixSlice &) = default; //!< Copy constructor.\n  const_MatrixSlice(const_MatrixSlice &&)      = default; //!< Move constructor.\n  const_MatrixSlice &operator=(const const_MatrixSlice &) = delete; //!< Disallow copying.\n\n  UInt rows()    const {return _rows;}          //!< row count.\n  UInt columns() const {return _columns;}       //!< column count.\n  UInt size()    const {return _rows*_columns;} //!< size = rows*columns.\n\n  inline Double operator () (UInt row, UInt column) const; /// matrix element.\n\n  /** @brief Transposed matrix.\n  * The transpose points to the same memory. */\n  inline const_MatrixSlice trans() const;\n\n  /** @brief Readonly reference to a submatrix.\n  * The same memory is used. No memory is copied. */\n  const_MatrixSlice slice(UInt startRow, UInt startColumn, UInt height, UInt width) const;\n\n  /** @brief Readonly reference to one or more columns.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  inline const_MatrixSlice column(UInt column, UInt len=1) const {return slice(0,column,rows(),len);}\n\n  /** @brief Readonly reference to one or more rows.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  inline const_MatrixSlice row(UInt row, UInt len=1) const {return slice(row,0,len,columns());}\n\n  /** @brief Typ der Matrix.\n  * GENERAL, SYMMETRIC, TRIANGLUAR. */\n  Type getType() const {return _type;}\n\n  /** @brief Which triangle is used?\n  * For @a getType()==GENERAL the result is meaningless.\n  * If TRUE the upper triangle is used, the lower otherwise. */\n  Bool isUpper() const {return _uplo==UPPER;}\n\n  /** @brief Pointer to the memory.\n  * Access to the element `A(row,column)` with\n  * `ptr = (A.isRowMajorOrder()) ? (A.field() + (column + row*A.ld())) : (A.field() + (row + column*A.ld()));` */\n  inline const Double *const_field() const;\n\n  /** @brief Leading Dimension.\n  * Number of elements needed to reach the next column or row,\n  * depending whether `!isRowMajorOrder()` or `isRowMajorOrder()`.\n  * @see field() */\n  UInt ld() const {return _ld;}\n\n  /** @brief Transposed view of the matrix?\n  * If `isRowMajorOrder()==TRUE` the matrix is stored rowwise, columnwise otherwise.\n  * @see field() */\n  Bool isRowMajorOrder() const {return _rowMajorOrder;}\n\n  inline Matrix operator+(Double c)                   const;\n  inline Matrix operator-(Double c)                   const;\n  inline Matrix operator*(Double c)                   const;\n  inline Matrix operator/(Double c)                   const;\n  inline Matrix operator-()                           const;\n  inline Matrix operator+(const const_MatrixSlice &x) const;\n  inline Matrix operator-(const const_MatrixSlice &x) const;\n\nprotected:\n  UInt _rows,  _columns;\n  UInt _start, _ld;\n  Type _type;\n  Uplo _uplo;\n  Bool _rowMajorOrder;\n  std::shared_ptr<MatrixBase> base;\n\n  const_MatrixSlice(UInt rows, UInt columns, const_MatrixSlice::Type type, const_MatrixSlice::Uplo uplo, Bool fill, Double value);\n\n  friend class MatrixSlice;\n  friend class Matrix;\n  friend class Vector;\n  friend void  cholesky(MatrixSliceRef A);\n  friend std::vector<UInt> choleskyPivoting(MatrixSliceRef A, UInt& rank, Double tolerance);\n}; // class MatrixSlice\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n/** @brief Writable view of a slice of a Matrix.\n* This is a reference to a memory area of a Matrix. It is intentend to be used as parameter of a function,\n* which operates on parts or all elements of the matrix without changing the size of the matrix.\n* Examples are copy, matMult or inverse. To store a matrix in a variable use the class Matrix instead.\n*\n* The class MatrixSlice itself should be a const reference in a function parameter definition,\n* although the memory is still changeable (the elements). Thus the function accepts temporally created\n* MatrixSlice or Matrix as parameter. As the following definition is confusing:\n* @code void f(const MatrixSlice &x); // the elements of x are still writable @endcode\n* a shortcut is defined with the same meaning:\n* @code void f(MatrixSliceRef x); @endcode */\nclass MatrixSlice : public const_MatrixSlice\n{\npublic:\n  MatrixSlice() = delete;                                                 //!< Disallow default constructor.\n  MatrixSlice(const MatrixSlice &) = default;                             //!< Copy constructor.\n  MatrixSlice(const const_MatrixSlice &x) : const_MatrixSlice(x) {}       //!< Copy constructor.\n  MatrixSlice(MatrixSlice &&) = default;                                  //!< Move constructor.\n  MatrixSlice(const_MatrixSlice &&x) : const_MatrixSlice(std::move(x)) {} //!< Move constructor.\n  MatrixSlice &operator=(MatrixSlice &) = delete;                         //!< Disallow copying\n\n  /// writable matrix element.\n  inline Double &operator () (UInt row, UInt column) const;\n\n  /** @brief Transposed matrix.\n  * The transpose points to the same memory. */\n  inline MatrixSlice trans() const;\n\n  /** @brief Writable reference to a submatrix.\n  * The same memory is used. No memory is copied. */\n  MatrixSlice slice(UInt startRow, UInt startColumn, UInt height, UInt width) const;\n\n  /** @brief Writable reference to one or more columns.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  MatrixSlice column(UInt column, UInt len=1) const {return slice(0,column,rows(),len);}\n\n  /** @brief Writable reference to one or more rows.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  MatrixSlice row(UInt row, UInt len=1) const {return slice(row,0,len,columns());}\n\n  /** @brief Set type of the matrix.\n  * @param type GENERAL, SYMMETRIC, TRIANGLUAR. */\n  void setType(Type type) {_type=type;}\n\n  /** @brief Set type of the matrix.\n  * @param type GENERAL, SYMMETRIC, TRIANGULAR.\n  * @param uplo if type is not GENERAL, only the UPPER or LOWER part of the matrix is used. */\n  void setType(Type type, Uplo uplo) {_type=type; _uplo=uplo;}\n\n  /** @brief Pointer to the memory.\n  * Access to the element `A(row,column)` with\n  * `ptr = (A.isRowMajorOrder()) ? (A.field() + (column + row*A.ld())) : (A.field() + (row + column*A.ld()));` */\n  inline Double *field() const;\n\n  /// fill all matrix elements.\n  const MatrixSlice &fill(Double f) const;\n\n  /// reset all matrix elements.\n  const MatrixSlice &setNull() const {return fill(0);}\n\n  const MatrixSlice &operator+=(const const_MatrixSlice &x) const;\n  const MatrixSlice &operator-=(const const_MatrixSlice &x) const;\n  const MatrixSlice &operator+=(Double c) const;\n  const MatrixSlice &operator-=(Double c) const;\n  const MatrixSlice &operator*=(Double c) const;\n  const MatrixSlice &operator/=(Double c) const;\n\nprotected:\n  MatrixSlice(UInt rows, UInt columns, MatrixSlice::Type type, MatrixSlice::Uplo uplo, Bool fill, Double value) : const_MatrixSlice(rows, columns, type, uplo, fill, value) {}\n}; // class MatrixSlice\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n/** @brief Matrix representation.\n* With smart memmory management. The memory is only copied if needed (copy on write, late copy).\n* For parameter references use MatrixSlice or const_MatrixSlice. */\nclass Matrix : public MatrixSlice\n{\npublic:\n  /// to mark uninitialzed elements.\n  enum Fill {NOFILL};\n\n  /// Default Constructor.\n  Matrix() : MatrixSlice(0, 0, GENERAL, UPPER, FALSE, 0.) {}\n\n  /// Default Constructor.\n  explicit Matrix(UInt rows, UInt columns, Double fill=0.) : MatrixSlice(rows, columns, GENERAL, UPPER, TRUE, fill) {}\n\n  /// Constructor with uninitialzed elements.\n  explicit Matrix(UInt rows, UInt columns, Fill /*fill*/) : MatrixSlice(rows, columns, GENERAL, UPPER, FALSE, 0.) {}\n\n  /** @brief Constructor for quadratic matrices.\n  * @param rows Number of rows and columns.\n  * @param type GENERAL, SYMMETRIC, TRIANGULAR\n  * @param uplo Only the UPPER or LOWER part of the matrix is used */\n  Matrix(UInt rows, Type type, Uplo uplo=Matrix::UPPER) : MatrixSlice(rows, rows, type, uplo, TRUE, 0.) {}\n\n  Matrix(const Matrix &x);                                           //!< Copy Constructor.\n  Matrix(const const_MatrixSlice &x);                                //!< Copy Constructor.\n  Matrix(Matrix &&x);                                                //!< Move Constructor.\n  Matrix(const_MatrixSlice &&x);                                     //!< Move Constructor.\n  Matrix(std::initializer_list<std::initializer_list<Double>> list); //!< List Constructor.\n  Matrix &operator=(const Matrix &x);                                //!< Assignment.\n  Matrix &operator=(const const_MatrixSlice &x);                     //!< Assignment.\n  Matrix &operator=(Matrix &&x);                                     //!< Move Assignment.\n  Matrix &operator=(const_MatrixSlice &&x);                          //!< Move Assignment.\n\n  /// matrix element.\n  Double operator()(UInt row, UInt column) const {return const_MatrixSlice::operator()(row,column);}\n\n  /// writable matrix element.\n  Double &operator()(UInt row, UInt column) {return MatrixSlice::operator()(row,column);}\n\n  /** @brief Readonly transposed matrix.\n  * The transpose points to the same memory. */\n  const const_MatrixSlice trans() const {return const_MatrixSlice::trans();}\n\n  /** @brief Writable transposed matrix.\n  * The transpose points to the same memory. */\n  MatrixSlice trans() {return MatrixSlice::trans();}\n\n  /** @brief Readonly reference to a submatrix.\n  * The same memory is used. No memory is copied. */\n  const_MatrixSlice slice(UInt startRow, UInt startColumn, UInt height, UInt width) const {return const_MatrixSlice::slice(startRow, startColumn, height, width);}\n\n  /** @brief Writable reference to a submatrix.\n  * The same memory is used. No memory is copied. */\n  MatrixSlice slice(UInt startRow, UInt startColumn, UInt height, UInt width) {return MatrixSlice::slice(startRow, startColumn, height, width);}\n\n  /** @brief Readonly reference to one or more columns.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  const_MatrixSlice column(UInt column, UInt len=1) const {return slice(0,column,rows(),len);}\n\n  /** @brief Writable reference to one or more columns.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  MatrixSlice column(UInt column, UInt len=1) {return slice(0,column,rows(),len);}\n\n  /** @brief Readonly reference to one or more rows.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  const_MatrixSlice row(UInt row, UInt len=1) const {return slice(row,0,len,columns());}\n\n  /** @brief Writable reference to one or more rows.\n  * The same memory is used. No memory is copied.\n  * @relates slice */\n  MatrixSlice row(UInt row, UInt len=1) {return slice(row,0,len,columns());}\n\nprivate:\n  void assignment(Bool movePossible=FALSE);\n};\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n/** @brief Vector representation.\n* A Vector is a Matrix with only one column. */\nclass Vector : public Matrix\n{\npublic:\n  /// Default Constructor (vector with zeros).\n  explicit Vector(UInt rows=0, Double fill=0.) : Matrix(rows, 1, fill) {}\n\n  Vector(const Vector &) = default;              //!< Copy Constructor.\n  Vector(const const_MatrixSlice &x);            //!< Copy Constructor.\n  Vector(Vector &&) = default;                   //!< Move Constructor.\n  Vector(const_MatrixSlice &&x);                 //!< Move Constructor.\n  Vector(std::initializer_list<Double> list);    //!< List Constructor.\n  Vector(const std::vector<Double> &x);          //!< Cast operator.\n  Vector &operator=(const Vector &) = default;   //!< Assignment.\n  Vector &operator=(const const_MatrixSlice &x); //!< Assignment.\n  Vector &operator=(Vector &&) = default;        //!< Move Assignment.\n  Vector &operator=(const_MatrixSlice &&x);      //!< Move Assignment.\n\n  inline Double operator()(UInt row) const {return const_MatrixSlice::operator()(row,0);} //!< vector element.\n  inline Double operator[](UInt row) const {return const_MatrixSlice::operator()(row,0);} //!< vector element.\n  inline Double at(UInt row)         const {return const_MatrixSlice::operator()(row,0);} //!< vector element.\n\n  inline Double &operator()(UInt row) {return MatrixSlice::operator()(row,0);} //!< writable vector element.\n  inline Double &operator[](UInt row) {return MatrixSlice::operator()(row,0);} //!< writable vector element.\n  inline Double &at(UInt row)         {return MatrixSlice::operator()(row,0);} //!< writable vector element.\n\n  /** @brief Writable reference to a submatrix.\n  * The same memory is used. No memory is copied. */\n  inline const_MatrixSlice slice(UInt startRow, UInt len) const {return const_MatrixSlice::slice(startRow,0,len,columns());}\n\n  /** @brief Writable reference to a submatrix.\n  * The same memory is used. No memory is copied. */\n  inline MatrixSlice slice(UInt startRow, UInt len) {return MatrixSlice::slice(startRow,0,len,columns());}\n\n  /// Cast operator to std::vector.\n  operator std::vector<Double> () const;\n}; // class Vector\n\n/***********************************************/\n/***** FUNCTIONS *******************************/\n/***********************************************/\n\n/** @brief Element-wise scalar matrix addition.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Matrix operator+(Double c, const_MatrixSliceRef A) {return A+c;}\n\n/** @brief Element-wise scalar matrix subtraction.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Matrix operator-(Double c, const_MatrixSliceRef A);\n\n/** @brief Element-wise scalar matrix multiplication.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Matrix operator*(Double c, const_MatrixSliceRef A) {return A*c;}\n\n/** @brief Element-wise scalar matrix division.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Matrix operator/(Double c, const_MatrixSliceRef A);\n\n/** @brief Matrix matrix multiplication.\n* The @a type of matrices are considered. */\ninline Matrix operator*(const_MatrixSliceRef A, const_MatrixSliceRef B);\n\n/** @brief identity matrix. */\nMatrix identityMatrix(UInt size, Matrix::Type=Matrix::GENERAL);\n\n/** @brief Fill the not used triangle, the result is symmetric.\n* A must be quadratic. */\nvoid fillSymmetric(MatrixSliceRef A);\n\n/** @brief Fill unused triangle with zeros.\n* A must be quadratic and triangular, otherwise an exception is thrown. */\nvoid zeroUnusedTriangle(MatrixSliceRef A);\n\n/** @brief Copy the content of Matrix @a A in Matrix @a B.\n* @warning Undefined for overlapping memory.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nvoid copy(const_MatrixSliceRef A, MatrixSliceRef B);\n\n/** @brief Swap the content of Matrix @a A and Matrix @a B.\n* @warning Undefined for overlapping memory.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nvoid swap(MatrixSliceRef A, MatrixSliceRef B);\n\n/** @brief Reshape the content of Matrix @a A into Matrix @a B.\n* Reshaping is done by column-wise order.\n* @warning Undefined for overlapping memory.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nvoid reshape(const_MatrixSliceRef A, MatrixSliceRef B);\n\n/** @brief Return a reshaped copy of Matrix @a A with new dimensions (@a rows x @a columns).\n* Reshaping is done by column-wise order. Either @a rows or @a columns can be set to zero\n* to auto-determine the dimension based on the provided one.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nMatrix reshape(const_MatrixSliceRef A, UInt rows, UInt columns);\n\n/** @brief Return a reordered copy of Matrix @a A.\n* The parameter @a rowIndex contains the indices of the input matrix rows in the reordered matrix.\n* Indices with NULLINDEX are inserted as zero elements into the new matrix.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nMatrix reorder(const_MatrixSliceRef A, const std::vector<UInt> &rowIndex);\n\n/** @brief Return the columns of the matrix as column vector.\n* The columns of the matrix are copied into the resulting vector.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Vector flatten(const_MatrixSliceRef A) {return reshape(A, A.size(), 1);}\n\n/** @brief Return whether the matrix is contains only strict zeros.\n* (operation is always applied to both triangles). */\nBool isStrictlyZero(const_MatrixSliceRef A);\n\n/** @brief Scalar product.\n* Sum of elementwise products.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble inner(const_MatrixSliceRef A, const_MatrixSliceRef B);\n\n/** @brief Sum of matrix elements. Returns 0 if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble sum(const_MatrixSliceRef A);\n\n/** @brief Mean of matrix elements. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Double mean(const_MatrixSliceRef A) {return A.size() ? sum(A)/A.size() : NAN_EXPR;}\n\n/** @brief Square sum of matrix elements. Returns 0 if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Double quadsum(const_MatrixSliceRef A) {return inner(A,A);}\n\n/** @brief Square root of squared sum of matrix elements. Returns 0 if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Double norm(const_MatrixSliceRef A) {return sqrt(quadsum(A));}\n\n/** @brief Root mean square (RMS) of matrix elements. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Double rootMeanSquare(const_MatrixSliceRef A) {return A.size() ? std::sqrt(quadsum(A)/A.size()) : NAN_EXPR;}\n\n/** @brief Standard deviation of matrix elements. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\ninline Double standardDeviation(const_MatrixSliceRef A) {return A.size()>1 ? std::sqrt((quadsum(A)-std::pow(sum(A),2)/A.size())/(A.size()-1)) : NAN_EXPR;}\n\n/** @brief Trace of matrix. Returns 0 if @p A is empty. */\nDouble trace(const_MatrixSliceRef A);\n\n/** @brief Matrix determinant. For non-triangular matrices, the determinant is computed from the QR factorization of a copy of @p A. */\nDouble determinant(const_MatrixSliceRef A);\n\n/** @brief Logarithm of matrix determinant and its sign. For non-triangular matrices, the determinant is computed from the QR factorization of a copy of @p A. */\nDouble logdeterminant(const_MatrixSliceRef A, Double &sign);\n\n/** @brief Maximum absolute element of matrix. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble maxabs(const_MatrixSliceRef A);\n\n/** @brief Minimum element of matrix. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble min(const_MatrixSliceRef A);\n\n/** @brief Maximum element of matrix. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble max(const_MatrixSliceRef A);\n\n/** @brief Median element of matrix. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble median(const_MatrixSliceRef A);\n\n/** @brief Median Absolute Deviation (MAD) of matrix elements. Returns NAN if @p A is empty.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nDouble medianAbsoluteDeviation(const_MatrixSliceRef A);\n\n/** @brief axpy: B += c * A.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles). */\nvoid axpy(Double c, const_MatrixSliceRef A, MatrixSliceRef B);\n\n/** @brief Matrix matrix multiplication: C += c * A * B.\n* The @a type of matrices are considered. */\nvoid matMult(Double c, const_MatrixSliceRef A, const_MatrixSliceRef B, MatrixSliceRef C);\n\n/** @brief rank k update (accumulate normal equations).\n* @a N must be SYMMETRIC.\n* @f[ N += c \\cdot (A^TA) @f] */\nvoid rankKUpdate(Double c, const_MatrixSliceRef A, MatrixSliceRef N);\n\n/** @brief rank 2k update.\n* @a N must be SYMMETRIC.\n* @f[ N += c \\cdot (A^TB+B^TA) @f] */\nvoid rank2KUpdate(Double c, const_MatrixSliceRef A, const_MatrixSliceRef B, MatrixSliceRef N);\n\n/** @brief Inverte a matrix. */\nvoid inverse(MatrixSliceRef A);\n\n/** @brief Eigen value decomposition.\n* @f[ N = Q\\Lambda Q^T @f]\n* @param[in,out]  A input: symmetric Matrix, output matrix of eigen vectors\n* @param computeEigenVectors if true eigen vectors are stored in A\n* @return eigen values in ascending order */\nVector eigenValueDecomposition(MatrixSliceRef A, Bool computeEigenVectors=TRUE);\n\n/** @brief Eigen value decomposition.\n* @param[in]  A input: general N-by-N nonsymmetric Matrix\n* @param[out] VL N-by-N, left eigenvectors of A, one per column\n* @param[out] VR N-by-N, right eigenvectors of A, one per column\n* @param computeEigenVectors if true VL and VR are computed, untouched otherwise\n* @return eigen values in ascending order (first column: real part, second column: imaginary part) */\nMatrix eigenValueDecomposition(MatrixSliceRef A, Matrix &VL, Matrix &VR, Bool computeEigenVectors=TRUE);\n\n/** @brief singular value decomposition (SVD).\n* A = U*diag(S)*Vt.\n* @param[in,out]  A input: (n x m) Matrix, output: content is destroyed.\n* @param[out] U the left singular vectors (n x s)\n* @param[out] Vt the right singular vectors (s x n) with s=min(n,m)\n* @param computeSingularVectors if true U and Vt are computed, untouched otherwise\n* @return singular values in descending order */\nVector singularValueDecomposition(MatrixSliceRef A, Matrix &U, Matrix &Vt, Bool computeSingularVectors=TRUE);\n\n/** @brief pseudo inverse of matrix A using SVD/EVD.\n* @param[in] A input: Matrix content is copied to temporary matrix\n* @param[in] rcond singular values with an absolute value smaller than max(S)*rcond are assumed to be zero\n* @return Moore-Penrose inverse of A */\nMatrix pseudoInverse(const_MatrixSliceRef A, Double rcond = 1e-15);\n\n/** @brief matrix square root of a positive semi-definite matrix which fulfills B*B = A and B^T*B = A.\n* @param[in] A input: Matrix content is copied to temporary matrix\n* @param[in] rcond Eigenvalues with an absolute value smaller than max(S)*rcond are assumed to be zero\n* @return matrix square root of A */\nMatrix matrixSquareRoot(const_MatrixSliceRef A, Double rcond = 1e-15);\n\n/** @brief inverse of matrix square root of a positive semi-definite matrix which fulfills B*B = inv(A) and B^T*B = inv(A).\n* @param[in] A input: Matrix content is copied to temporary matrix\n* @param[in] rcond Eigenvalues with an absolute value smaller than max(S)*rcond are assumed to be zero\n* @return matrix square root of A */\nMatrix matrixSquareRootInverse(const_MatrixSliceRef A, Double rcond = 1e-15);\n\n/** @brief kron computes the kronecker product of A and B.\n* The @a type of matrix is @b not considered\n* (operation is always applied to both triangles).\n* @return C matrix containing the kronecker product for the matrices */\nMatrix kron(const_MatrixSliceRef A, const_MatrixSlice B);\n\n/** @brief toeplitz computes a toeplitz matrix out of a given vector.\n* @param a (n x 1) vector which is going to be toeplitz\n* @return (n x n) matrix toeplitzed */\nMatrix toeplitz(const Vector &a);\n\n/***********************************************/\n\n/** @brief Solve system of equations for mutliple right hand sides.\n* @f[ B := N^{-1} B @f]\n* - if @a N is GENERAL content is destroyed.\n* - if @a N is SYMMETRIC content will be replaced by the cholesky decomposition N=W'W.\n* - if @a N is TRIANGULAR content is unchanged. */\nvoid solveInPlace(MatrixSliceRef N, MatrixSliceRef B);\n\n/** @brief Solve system of equations for mutliple right hand sides.\n* @f[ B := N^{-1} B @f]\n* - if @a N is GENERAL content is destroyed.\n* - if @a N is SYMMETRIC content will be replaced by the cholesky decomposition N=W'W.\n* - if @a N is TRIANGULAR content is unchanged. */\nMatrix solve(MatrixSliceRef N, const_MatrixSliceRef B);\n\n/** @brief Least squares adjustment with multiple right hand sides.\n* Using QR decomposition. Content of A will be destroyed. Residuals are returned in l.\n* @f[ x = (A^TA)^{-1}A^T l @f] */\nMatrix leastSquares(MatrixSliceRef A, MatrixSliceRef l);\n\n/** @brief Observations l reduced by least suqares fit.\n* Using QR decomposition.\n* @f[ l := (I-A*(A^TA)^{-1}A^T) l @f] */\nvoid reduceLeastSquaresFit(const_MatrixSliceRef A, MatrixSliceRef l);\n\n/** @brief Eliminate additional parameters from observation equations.\n* Additional parameters are defined by the desigmatrix @a B.\n* Using @a B=QR decomposition.\n* \\f[ \\bar{A}^T \\bar{A} = A^T (I - B (B^T B)^{-1} B^T) A \\f] */\nvoid eliminationParameter(MatrixSliceRef B, const std::vector<std::reference_wrapper<Matrix>> &listA);\n\n/** @brief Eliminate additional parameters from observation equations.\n* Additional parameters are defined by the desigmatrix @a B.\n* Using QR decomposition.\n* \\f[ \\bar{A}^T \\bar{A} = A^T (I - B (B^T B)^{-1} B^T) A \\f]\n* \\f[ \\bar{A}^T \\bar{l} = A^T (I - B (B^T B)^{-1} B^T) l \\f] */\ninline void eliminationParameter(MatrixSliceRef B, Matrix &A, Matrix &l) {eliminationParameter(B, {A, l});}\n\n/***********************************************/\n\n/** @brief Cholesky decomposition of a SYMMETRIC matrix.\n* @param[in,out] A Input: positive definite matrix, Output: upper triangular matrix W (@f$ A = W^TW @f$). */\nvoid cholesky(MatrixSliceRef A);\n\n/** @brief Cholesky decomposition with pivoting of a SYMMETRIC matrix.\n* @param[in,out] A Input: positive semidefinite matrix, Output: upper triangular matrix W (@f$ P^TAP = W^TW @f$).\n* @param[out] rank Estimated rank of the matrix.\n* @param tolerance The algorithm terminates at the (K-1)st step if the pivot <= tolerance.\n* @return pivoting vector (@f$ P(piv[i],i)=1 @f$) */\nstd::vector<UInt> choleskyPivoting(MatrixSliceRef A, UInt &rank, Double tolerance=-1);\n\n/** @brief Inverte a matrix, if the cholesky decomposition of the matrix is given. */\nvoid cholesky2Inverse(MatrixSliceRef W);\n\n/** @brief Computes the product WW'. */\nvoid choleskyProduct(MatrixSliceRef W);\n\n/** @brief Triangular matrix - matrix multiplication: C := c * W * C.\n* W must be a TRIANGULAR matrix. */\nvoid triangularMult(Double c, const_MatrixSliceRef W, MatrixSliceRef C);\n\n/** @brief Inverse triangular matrix - matrix multiplication: C := c * W^-1 * C.\n* W must be a TRIANGULAR matrix. */\nvoid triangularSolve(Double c, const_MatrixSliceRef W, MatrixSliceRef C);\n\n/***********************************************/\n\n/** @brief QR decomposition.\n* Computes a QR factorization of a real M-by-N matrix A.\n* The matrix Q is represented as a product of elementary reflectors\n* Q = H(0) H(1) . . . H(k), where k = min(m,n)-1.\n* Each H(i) has the form H(i) = I - tau(i) * v(i) * v(i)'\n* where tau is a real scalar, and v is stored on exit in A(i+1:m,i).\n* @param[in,out] A On exit, the elements on and above the diagonal of the array contain\n* the min(M,N)-by-N upper trapezoidal matrix R (R is upper triangular if m >= n);\n* the elements below the diagonal, with the vector tau, represent the orthogonal\n* matrix Q as a product of min(m,n) elementary reflectors.\n* @return  tau: The scalar factors of the elementary reflectors. */\nVector QR_decomposition(MatrixSliceRef A);\n\n/** @brief Q Multiplication.\n* Computes A := Q*A.\n* The matrix Q is represented as a product of elementary reflectors\n* Q = H(0) H(1) . . . H(k), where k = min(m,n)-1.\n* Each H(i) has the form H(i) = I - tau(i) * v(i) * v(i)'\n* where tau is a real scalar, and v is stored in B(i+1:m,i).\n* @see QR_decomposition */\nvoid QMult(const_MatrixSliceRef B, const Vector &tau, MatrixSliceRef A);\n\n/** @brief Q' Multiplication.\n* Computes A := Q'*A.\n* The matrix Q is represented as a product of elementary reflectors\n* Q = H(0) H(1) . . . H(k), where k = min(m,n)-1.\n* Each H(i) has the form H(i) = I - tau(i) * v(i) * v(i)'\n* where tau is a real scalar, and v is stored in B(i+1:m,i).\n* @see QR_decomposition */\nvoid QTransMult(const_MatrixSliceRef B, const Vector &tau, MatrixSliceRef A);\n\n/** @brief Generate Q matrix.\n* Generates  real matrix Q with orthonormal columns,\n* The matrix Q is represented at input as a product of elementary reflectors\n* Q = H(0) H(1) . . . H(k), where k = min(m,n)-1.\n* Each H(i) has the form H(i) = I - tau(i) * v(i) * v(i)'\n* where tau is a real scalar, and v is stored in A(i+1:m,i).\n* @see QR_decomposition */\nvoid generateQ(MatrixSliceRef A, const Vector &tau);\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n/** @brief Internal class.\n* Used for memory management of matrices.\n* Memory is only copied, if needed (copy on write).\n* This means multiple matrices share the same memory,\n* as long as the elements are not changed. */\nclass MatrixBase\n{\npublic:\n  MatrixBase(UInt size, Bool fill, Double value);  //!< Constructor\n  MatrixBase(const MatrixBase &) = default;        //!< Copy Constructor.\n\n  /// Readonly access to field.\n  inline const Double *const_field() const {return ptr.get();}\n\n  /** Writable access to field.\n  * Maybe memory must be copied. */\n  inline Double *field();\n\nprivate:\n  std::shared_ptr<Double[]> ptr;\n  UInt _size;\n};\n\n/// @} group matrix\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ninline Double *MatrixBase::field()\n{\n  if(ptr.use_count()>1) // not threat save\n  {\n    auto ptr2 = std::shared_ptr<Double[]>(new Double[_size]);\n    // auto ptr2 = std::make_shared_for_overwrite<Double[]>(_size); // since c++20\n    std::copy_n(ptr.get(), _size, ptr2.get());\n    ptr = std::move(ptr2);\n  }\n  return ptr.get();\n}\n\n/***********************************************/\n\ninline Matrix const_MatrixSlice::operator+(Double c)                   const {return Matrix(*this) +=  c;}\ninline Matrix const_MatrixSlice::operator-(Double c)                   const {return Matrix(*this) -=  c;}\ninline Matrix const_MatrixSlice::operator*(Double c)                   const {return Matrix(*this) *=  c;}\ninline Matrix const_MatrixSlice::operator/(Double c)                   const {return Matrix(*this) /=  c;}\ninline Matrix const_MatrixSlice::operator-()                           const {return Matrix(*this) *= -1;}\ninline Matrix const_MatrixSlice::operator+(const const_MatrixSlice &x) const {return Matrix(*this) +=  x;}\ninline Matrix const_MatrixSlice::operator-(const const_MatrixSlice &x) const {return Matrix(*this) -=  x;}\n\n/***********************************************/\n\ninline const Double *const_MatrixSlice::const_field() const\n{\n  if(!base)\n    throw(Exception(\"const_MatrixSlice.field: Null-Pointer\"));\n  return base->const_field()+_start;\n}\n\n/***********************************************/\n\ninline Double *MatrixSlice::field() const\n{\n  if(!base)\n    throw(Exception(\"MatrixSlice.field: Null-Pointer\"));\n  return base->field()+_start;\n}\n\n/***********************************************/\n\n// readonly\ninline Double const_MatrixSlice::operator () (UInt row, UInt  column) const\n{\n  if((row>=rows()) || (column>=columns()))\n    throw(Exception(\"Access to matrix element (\"s+row%\"%i x \"s+column%\"%i) out of range, matrix size (\"s+rows()%\"%i x \"s+columns()%\"%i)\"s));\n  return *(base->const_field() + (_start + (_rowMajorOrder ? (column+row*_ld) : (row+column*_ld))));\n}\n\n/***********************************************/\n\n// writable\ninline Double &MatrixSlice::operator () (UInt row, UInt  column)  const\n{\n  if((row>=rows()) || (column>=columns()))\n    throw(Exception(\"Access to matrix element (\"s+row%\"%i x \"s+column%\"%i) out of range, matrix size (\"s+rows()%\"%i x \"s+columns()%\"%i)\"s));\n  return *(base->field() + (_start + (_rowMajorOrder ? (column+row*_ld) : (row+column*_ld))));\n}\n\n/***********************************************/\n\ninline const_MatrixSlice const_MatrixSlice::trans() const\n{\n  const_MatrixSlice x(*this);\n  x._rows          = _columns;\n  x._columns       = _rows;\n  x._uplo          = (_uplo==UPPER) ? LOWER : UPPER;\n  x._rowMajorOrder = !_rowMajorOrder;\n  return x;\n}\n\n/***********************************************/\n\ninline MatrixSlice MatrixSlice::trans() const\n{\n  MatrixSlice x(*this);\n  x._rows          = _columns;\n  x._columns       = _rows;\n  x._uplo          = (_uplo==UPPER) ? LOWER : UPPER;\n  x._rowMajorOrder = !_rowMajorOrder;\n  return x;\n}\n\n/***********************************************/\n\ninline Matrix operator- (Double c, const_MatrixSliceRef A)\n{\n  Matrix C(A);\n  for(UInt i=0; i<C.rows(); i++)\n    for(UInt j=0; j<C.columns(); j++)\n      C(i,j) = c-C(i,j);\n  return C;\n}\n\n/***********************************************/\n\ninline Matrix operator/ (Double c, const_MatrixSliceRef A)\n{\n  Matrix C(A);\n  for(UInt i=0; i<C.rows(); i++)\n    for(UInt j=0; j<C.columns(); j++)\n      C(i,j) = c/C(i,j);\n  return C;\n}\n\n/***********************************************/\n\ninline Matrix operator* (const_MatrixSliceRef A, const_MatrixSliceRef B)\n{\n  Matrix C(A.rows(),B.columns());\n  matMult(1.0, A, B, C);\n  return C;\n}\n\n//***********************************************/\n\ninline Matrix solve(MatrixSliceRef N, const_MatrixSliceRef B)\n{\n  Matrix X = B;\n  solveInPlace(N,X);\n  return X;\n}\n\n//***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/base/parameterName.cpp",
    "content": "/***********************************************/\n/**\n* @file parameterName.cpp\n*\n* @brief Parameter name representation.\n*\n* @author Sebastian Strasser\n* @date 2017-05-23\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/string.h\"\n#include \"base/parameterName.h\"\n\n/***********************************************/\n\nParameterName::ParameterName(const std::string &object, const std::string &type, const std::string &temporal, const Time &timeStart, const Time &timeEnd)\n  : object(object), type(type), temporal(temporal)\n{\n  try\n  {\n    if(timeStart != Time())\n    {\n      std::stringstream ss;\n      ss<<timeStart.dateTimeStr();\n      if(timeEnd != Time())\n        ss<<\"_\"<<timeEnd.dateTimeStr();\n      interval = ss.str();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParameterName::ParameterName(const std::string &object, const std::string &type, const std::string &temporal, const std::string &interval)\n  : object(object), type(type), temporal(temporal), interval(interval)\n{\n}\n\n/***********************************************/\n\nParameterName ParameterName::fromStr(const std::string &str)\n{\n  try\n  {\n    std::vector<std::string> parts = String::split(str, sep);\n\n    ParameterName parameterName;\n    if(parts.size() > 0) parameterName.object   = parts.at(0);\n    if(parts.size() > 1) parameterName.type     = parts.at(1);\n    if(parts.size() > 2) parameterName.temporal = parts.at(2);\n    if(parts.size() > 3) parameterName.interval = parts.at(3);\n    if(parts.size() > 4) throw(Exception(\"Parameter name contains more than four parts: \"+str));\n\n    return parameterName;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParameterName::combine(const ParameterName &name)\n{\n  try\n  {\n    if(!fuzzyMatch(name))\n      return FALSE;\n\n    if(object.empty())   object   = name.object;\n    if(type.empty())     type     = name.type;\n    if(interval.empty()) interval = name.interval;\n    if(temporal.empty()) temporal = name.temporal;\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParameterName::fuzzyMatch(const ParameterName &other) const\n{\n  try\n  {\n    return (object   == other.object   || object.empty()   || other.object.empty())   &&\n           (type     == other.type     || type.empty()     || other.type.empty())     &&\n           (interval == other.interval || interval.empty() || other.interval.empty()) &&\n           (temporal == other.temporal || temporal.empty() || other.temporal.empty());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParameterName::operator==(const ParameterName &other) const\n{\n  try\n  {\n    return (object == other.object) && (type == other.type ) && (interval == other.interval ) && (temporal == other.temporal);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParameterName::operator<(const ParameterName &other) const\n{\n  try\n  {\n    Int compareObject = object.compare(other.object);\n    if(compareObject < 0) return TRUE;\n    if(compareObject > 0) return FALSE;\n\n    Int compareType = type.compare(other.type);\n    if(compareType < 0) return TRUE;\n    if(compareType > 0) return FALSE;\n\n    Int compareInterval = interval.compare(other.interval);\n    if(compareInterval < 0) return TRUE;\n    if(compareInterval > 0) return FALSE;\n\n    Int compareTemporal = temporal.compare(other.temporal);\n    if(compareTemporal < 0) return TRUE;\n\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/parameterName.h",
    "content": "/***********************************************/\n/**\n* @file parameterName.h\n*\n* @brief Parameter name representation.\n*\n* @author Sebastian Strasser\n* @date 2017-05-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAME__\n#define __GROOPS_PARAMETERNAME__\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n\n/***** CLASS ***********************************/\n\n/**\n* @brief Parameter name representation.\n* @ingroup base */\nclass ParameterName\n{\npublic:\n  std::string object;    //!< Object this parameter refers to, e.g. graceA, G023, earth, ...\n  std::string type;      //!< Type of this parameter, e.g. accBias, position.x, ...\n  std::string temporal;  //!< Temporal representation of this parameter, e.g. trend, polynomial.degree1, ...\n  std::string interval;  //!< Interval/epoch this parameter represents, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2018-01-01_00-00-00\n\n  /** @brief Constructor. All parameters are optional.\n  * @param object    Object this parameter refers to, e.g. graceA, G023, earth, ...\n  * @param type      Type of this parameter, e.g. accBias, position.x, ...\n  * @param temporal  Temporal representation of this parameter, e.g. trend, polynomial.degree1, ...\n  * @param timeStart Start of interval or point in time which this parameter represents\n  * @param timeEnd   End of interval which this parameter represents  */\n  ParameterName(const std::string &object=\"\", const std::string &type=\"\", const std::string &temporal=\"\", const Time &timeStart=Time(), const Time &timeEnd=Time());\n\n  /** @brief Constructor.\n  * @param object   Object this parameter refers to, e.g. graceA, G023, earth, ...\n  * @param type     Type of this parameter, e.g. accBias, position.x, ...\n  * @param temporal Temporal representation of this parameter, e.g. trend, polynomial.degree1, ...\n  * @param interval Interval/epoch this parameter represents, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2018-01-01_00-00-00 */\n  ParameterName(const std::string &object, const std::string &type, const std::string &temporal, const std::string &interval);\n\n  /** @brief Returns the separator between parts of the parameter name. */\n  static constexpr Char sep = ':';\n\n  /** @brief Returns ParameterName object built from a single string @p str separated by a separator @p sep. */\n  static ParameterName fromStr(const std::string &str);\n\n  /** @brief Returns string representation of the ParameterName with parts separated by separator @p sep. */\n  std::string str() const { return object + sep + type + sep + temporal + sep + interval; }\n\n  /** @brief Fill empty parts of this parameter with parts from @p name. Returns FALSE if parameter names cannot be combined, TRUE otherwise. */\n  Bool combine(const ParameterName &name);\n\n  /** @brief Returns TRUE if the parameter name is empty, FALSE otherwise. */\n  Bool empty() const { return (object.empty() && type.empty() && interval.empty() && temporal.empty()); }\n\n  /** @brief Returns TRUE if parameter names match. Empty parts always match with non-empty parts. */\n  Bool fuzzyMatch(const ParameterName &other) const;\n\n  /** @brief Returns TRUE if parameter names match exactly. */\n  Bool operator==(const ParameterName &other) const;\n\n  /** @brief Returns TRUE if parameter names do not match exactly. */\n  Bool operator!=(const ParameterName &other) const { return !(*this == other); }\n\n  /** @brief Sort operator. */\n  Bool operator<(const ParameterName &other) const;\n};\n\n/***********************************************/\n\n#endif\n\n"
  },
  {
    "path": "source/base/planets.cpp",
    "content": "/***********************************************/\n/**\n* @file planets.cpp\n*\n* @brief Planet and Earth fundamentals.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-04-26\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/time.h\"\n#include \"base/vector3d.h\"\n#include \"base/transform3d.h\"\n#include \"base/ellipsoid.h\"\n#include \"base/planets.h\"\n\n/************************************************/\n\n// Reference: The Astronomical Almanac, page C24.\nVector3d Planets::positionSun(const Time &timeGPS)\n{\n  const Double t = (timeGPS2TT(timeGPS)-mjd2time(J2000)).mjd();\n  // mean anomaly\n  const Double g = DEG2RAD * (357.528 + 0.9856003*t);\n  // solar ecliptic longitude\n  const Double lambda = DEG2RAD * (280.464 + 0.9856090*t + 1.915*std::sin(g) + 0.02*std::sin(2*g));\n  // obliquity of the ecliptic\n  const Double eps = DEG2RAD * (23.439 - 0.0000004*t);\n  // distance\n  const Double r = 149597870700 * (1.000142 - 0.01671*std::cos(g) - 0.00014*std::cos(2*g));\n  // position\n  return Vector3d(r*std::cos(lambda), r*std::sin(lambda)*std::cos(eps), r*std::sin(lambda)*std::sin(eps));\n}\n\n/************************************************/\n\n// Fundamental Arguments of nutation theory\n// from IERS Conventions 2003\nVector Planets::fundamentals(const Time &timeGPS)\n{\n  const Double T = timeGPS2JC(timeGPS);\n  Vector F(5);\n  F(0) = DEG2RAD/3600*( 485868.249036+T*(1717915923.2178+T*( 31.8792+T*( 0.051635+T*(-0.00024470)))));\n  F(1) = DEG2RAD/3600*(1287104.793048+T*( 129596581.0481+T*( -0.5532+T*( 0.000136+T*(-0.00001149)))));\n  F(2) = DEG2RAD/3600*( 335779.526232+T*(1739527262.8478+T*(-12.7512+T*(-0.001037+T*( 0.00000417)))));\n  F(3) = DEG2RAD/3600*(1072260.703692+T*(1602961601.2090+T*( -6.3706+T*( 0.006593+T*(-0.00003169)))));\n  F(4) = DEG2RAD/3600*( 450160.398036+T*( - 6962890.5431+T*(  7.4722+T*( 0.007702+T*(-0.00005939)))));\n  return F;\n}\n\n/************************************************/\n\nDouble Planets::gmst(const Time &timeUT1)\n{\n  Double Tu0 = (timeUT1.mjdInt()-51544.5)/36525.0;\n\n  Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))\n               + (8640184.812866/(24*60*60))*Tu0\n               + (0.093104/(24*60*60))*Tu0*Tu0\n               + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;\n  Double r     = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;\n  return fmod(2*PI*(GMST0 + r * timeUT1.mjdMod()), 2*PI);\n}\n\n/************************************************/\n\nDouble Planets::ERA(const Time &timeUT1)\n{\n  const Time T = timeUT1-mjd2time(J2000);\n  return fmod(2*PI*(0.7790572732640 + T.mjdMod() + 0.00273781191135448*T.mjd()), 2*PI);\n}\n\n/************************************************/\n\nRotary3d Planets::celestial2TerrestrialFrame(const Time &timeGPS)\n{\n  return rotaryZ(Angle(Planets::gmst(timeGPS2UTC(timeGPS))));\n}\n\n/***********************************************/\n\nDouble Planets::normalGravity(const Vector3d &p)\n{\n  const Double ga = 9.7803267715;\n  const Double gb = 9.8321863685;\n  const Double m  = 0.00344978600308;\n  const Double f  = DEFAULT_GRS80_f;\n  const Double a  = DEFAULT_GRS80_a;\n  const Double b  = a*(1-1/f);\n\n  Ellipsoid ellipsoid(DEFAULT_GRS80_a, DEFAULT_GRS80_f);\n  Angle  L,B;\n  Double h;\n  ellipsoid(p, L,B,h);\n\n  const Double cos2 = std::pow(std::cos(B),2);\n  const Double sin2 = std::pow(std::sin(B),2);\n  const Double gamma0 = (a*ga*cos2+b*gb*sin2)/std::sqrt(a*a*cos2+b*b*sin2);\n  return gamma0 -2*ga/a*(1+1/f+m+(-3/f+5*m/2)*sin2)*h+3*ga/a/a*h*h;\n}\n\n/************************************************/\n"
  },
  {
    "path": "source/base/planets.h",
    "content": "/***********************************************/\n/**\n* @file planets.h\n*\n* @brief Planet and Earth fundamentals.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-04-26\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLANETS__\n#define __GROOPS_PLANETS__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/time.h\"\n#include \"base/vector3d.h\"\n#include \"base/rotary3d.h\"\n\nclass FileName;\n\n/***** CLASS ***********************************/\n\n/** @brief planet and Earth fundamentals.\n* @ingroup base */\nnamespace Planets\n{\n  /** @brief Fundamental arguments of nutation theory.\n  * -  F(0) = l  = Mean Anomaly of the Moon\n  * -  F(1) = l' = Mean Anomaly of the Sun\n  * -  F(2) = L-Omega\n  * -  F(3) = D = Mean Elongation of the Moon from Sun\n  * -  F(4) = Omega = Mean Longitude of the Ascening Node of the Moon */\n  Vector fundamentals(const Time &timeGPS);\n\n  /** @brief Position of sun in celestial frame.\n  * Reference:  The Astronomical Almanac, page C24.\n  * Accurate to 0.01 degrees between the years 1950 through 2050. */\n  Vector3d positionSun(const Time &timeGPS);\n\n  /** @brief Greenwich Mean Sideral Time.\n  * roation angle (CRF -> TRF) [rad]. */\n  Double gmst(const Time &timeUT1);\n\n  /** @brief Earth rotation angle.\n  * roation angle (CRF -> TRF) [rad]. */\n  Double ERA(const Time &timeUT1);\n\n  /** @brief Approximate Earth rotation.\n  * Without Earth rotation parameter (EOP). */\n  Rotary3d celestial2TerrestrialFrame(const Time &timeGPS);\n\n  /** @brief Gravity of the Earth.\n  * Normal Gravity Formula (Geodetic Reference System 1980). */\n  Double normalGravity(const Vector3d &p);\n} // end Planets\n\n/***********************************************/\n\n#endif /* __GROOPS_PLANET__ */\n"
  },
  {
    "path": "source/base/polynomial.cpp",
    "content": "/***********************************************/\n/**\n* @file polynomial.cpp\n*\n* @brief Interpolation by polynomial.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-05-27\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/polynomial.h\"\n\n/***********************************************/\n\nvoid Polynomial::init(const std::vector<Time> &times, UInt degree, Bool throwException,\n                      Bool leastSquares, Double range, Double extrapolation, Double margin)\n{\n  try\n  {\n    this->times          = times;\n    this->degree         = degree;\n    this->throwException = throwException;\n    this->isLeastSquares = leastSquares;\n    this->sampling       = medianSampling(times).seconds();\n    this->range          = range * ((range < 0) ? -sampling : 1.);\n    this->extrapolation  = extrapolation * ((extrapolation < 0) ? -sampling : 1.);\n    this->margin         = margin;\n\n    if(times.size() < degree+1)\n      throw(Exception(\"Not enough data points (\"+times.size()%\"%i) to interpolate with polynomial degree \"s+degree%\"%i\"s));\n    if(std::adjacent_find(times.begin(), times.end(), [margin](const Time &t1, const Time &t2){return (t2-t1).seconds() <= margin;}) != times.end())\n      throw(Exception(\"Input time series is unordered or contains duplicates\"));\n\n    std::vector<Bool> isConstInterval(times.size()-1);\n    for(UInt i=0; i<isConstInterval.size(); i++)\n      isConstInterval.at(i) = (std::fabs((times.at(i+1)-times.at(i)).seconds()-sampling) < margin);\n\n    isPrecomputed.clear();\n    isPrecomputed.resize(times.size()-degree, TRUE);\n    if(degree > 0)\n      for(UInt i=0; i<isPrecomputed.size(); i++)\n        isPrecomputed.at(i) = !std::any_of(isConstInterval.begin()+i, isConstInterval.begin()+(i+degree), [](Bool b){return !b;});\n\n    // precomputed polynomial interpolation matrix\n    W = Matrix(degree+1, degree+1);\n    for(UInt i=0; i<W.rows(); i++)\n    {\n      W(0,i) = 1.0;\n      for(UInt n=1; n<W.columns(); n++)\n        W(n,i) = (i-degree/2.) * W(n-1,i);\n    }\n    inverse(W);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Polynomial::interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch, UInt derivative, Bool adjoint) const\n{\n  try\n  {\n    if(!derivative && !isLeastSquares && (timesNew == times)) // need interpolation?\n      return A;\n\n    Matrix B(rowsPerEpoch*(adjoint ? times.size() : timesNew.size()), A.columns());\n    auto searchStart = times.begin();\n    for(UInt i=0; i<timesNew.size(); i++)\n    {\n      // find interval\n      // -------------\n      UInt idx   = NULLINDEX;\n      UInt count = degree+1;\n      if(!isLeastSquares)\n      {\n        searchStart = std::lower_bound(searchStart, times.end(), timesNew.at(i));            // first epoch greater or equal than interpolation point\n        const UInt idxFirstRight = static_cast<UInt>(std::distance(times.begin(), searchStart));\n\n        // same time? -> no interpolation needed\n        if(!adjoint && !derivative && (idxFirstRight < times.size()) && (std::fabs((*searchStart-timesNew.at(i)).seconds()) <= margin))\n        {\n          copy(A.row(rowsPerEpoch*idxFirstRight, rowsPerEpoch), B.row(rowsPerEpoch*i, rowsPerEpoch));\n          continue;\n        }\n\n        // interpolation possible?\n        UInt   optimalCentricity = MAX_UINT; // primary metric   (number of points left and right)\n        Double optimalDistance   = 1e99;    // secondary metric\n        for(UInt k=std::max(idxFirstRight, count)-count; k<=std::min(idxFirstRight, times.size()-count); k++)\n        {\n          const Double dt1 = (times.at(k)-timesNew.at(i)).seconds();\n          const Double dt2 = (times.at(k+degree)-timesNew.at(i)).seconds();\n          if((dt2-dt1 <= range)  && (dt2 >= -extrapolation) && (dt1 <= extrapolation))\n          {\n            const UInt centricity = std::max(idxFirstRight-k, k+count-idxFirstRight); // max(number of points left and right)\n            if(centricity > optimalCentricity)\n              break; // there won't be any better polynomial to the right of the current optimal anymore if centricity is increasing\n            if((centricity < optimalCentricity) || (std::max(std::fabs(dt1), std::fabs(dt2)) < optimalDistance))\n            {\n              idx               = k;\n              optimalCentricity = centricity;\n              optimalDistance   = std::max(std::fabs(dt1), std::fabs(dt2));\n            }\n          }\n        }\n      }\n      else // least squares\n      {\n        auto searchEnd = std::upper_bound(searchStart, times.end(), timesNew.at(i)+seconds2time(range)); // first epoch outside search interval\n        searchStart    = std::lower_bound(searchStart, searchEnd,   timesNew.at(i)-seconds2time(range)); // first epoch greater or equal than search interval\n        idx   = std::distance(times.begin(), searchStart);\n        count = static_cast<UInt>(std::distance(searchStart, searchEnd));\n        if((count < degree+1) || ((times.at(idx) - timesNew.at(i)).seconds() > extrapolation) || // all points are after newTime and we are too far away\n                                 ((timesNew.at(i) - times.at(idx+count-1)).seconds() > extrapolation))   // all points are before newTime and we are too far away\n          idx = NULLINDEX;\n      }\n\n      // check if we are allowed to predict\n      // ----------------------------------\n      if(idx == NULLINDEX)\n      {\n        if(throwException || adjoint)\n          throw(Exception(\"cannot interpolate at \"+timesNew.at(i).dateTimeStr()));\n        B.row(i*rowsPerEpoch, rowsPerEpoch).fill(NAN_EXPR);\n        continue;\n      }\n\n      // compute interpolation coefficients\n      // ----------------------------------\n      Vector coeff;\n      if(!isLeastSquares && isPrecomputed.at(idx))\n      {\n        const Double tau = (timesNew.at(i)-times.at(idx)).seconds()/sampling - degree/2.;\n        coeff = Vector(W.rows());\n        Double t = 1.0;\n        for(UInt n=derivative; n<=degree; n++)\n        {\n          Double d = 1.0;\n          for(UInt k=0; k<derivative; k++)\n            d *= (n-k)/sampling;\n          axpy(d*t, W.column(n), coeff);\n          t *= tau;\n        }\n      }\n      else\n      {\n        // polynomial matrix\n        Matrix P(count, degree+1, Matrix::NOFILL);\n        for(UInt k=0; k<count; k++)\n        {\n          const Double factor = (timesNew.at(i)-times.at(idx+k)).seconds()/sampling;\n          P(k,0) = 1.0;\n          for(UInt n=1; n<=degree; n++)\n            P(k,n) = factor * P(k,n-1);\n        }\n\n        coeff = Vector(count);\n        coeff(derivative) = 1.;\n        for(UInt n=1; n<=derivative; n++)\n          coeff(derivative) *= n/sampling;\n        if(P.rows() > P.columns()) // solve with QR-decomposition\n        {\n          const Vector tau = QR_decomposition(P);\n          triangularSolve(1., P.row(0, P.columns()).trans(), coeff.row(0, P.columns())); // R^(-T)*coeff\n          QMult(P, tau, coeff);                                                          // coeff := Q*R^(-T)*coeff\n        }\n        else\n        {\n          solveInPlace(Matrix(P.trans()), coeff);\n        }\n      }\n\n      // interpolate\n      // -----------\n      if(!adjoint)\n      {\n        if(rowsPerEpoch == 1)\n          matMult(1., coeff.trans(), A.row(idx, coeff.rows()), B.row(i, rowsPerEpoch));\n        else\n          for(UInt k=0; k<coeff.rows(); k++)\n            axpy(coeff(k), A.row(rowsPerEpoch*(idx+k), rowsPerEpoch), B.row(rowsPerEpoch*i, rowsPerEpoch));\n      }\n      else\n      {\n        if(rowsPerEpoch == 1)\n          matMult(1., coeff, A.row(i, rowsPerEpoch), B.row(idx, coeff.rows()));\n        else\n          for(UInt k=0; k<coeff.rows(); k++)\n            axpy(coeff(k), A.row(rowsPerEpoch*i, rowsPerEpoch), B.row(rowsPerEpoch*(idx+k), rowsPerEpoch));\n      }\n    }\n\n    return B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/polynomial.h",
    "content": "/***********************************************/\n/**\n* @file polynomial.h\n*\n* @brief Interpolation/derivation by polynomial.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-05-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INTERPOLATION__\n#define __GROOPS_INTERPOLATION__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/time.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolation/derivation by polynomial.\n* @ingroup base */\nclass Polynomial\n{\n  Bool              throwException;\n  UInt              degree;\n  std::vector<Time> times;\n  Double            sampling, margin;\n  Bool              isLeastSquares;\n  Double            range, extrapolation;\n  std::vector<Bool> isPrecomputed;\n  Matrix            W;\n\npublic:\n  /// Constructor\n  Polynomial() {}\n\n  /** @brief Constructor.\n  * @see init(const std::vector<Time> &, UInt, Bool). */\n  Polynomial(const std::vector<Time> &times, UInt degree, Bool throwException=TRUE) {init(times, degree, throwException);}\n\n  /** @brief Constructor.\n  * @see init(const std::vector<Time> &, UInt, Bool, Bool, Double, Double, Double). */\n  Polynomial(const std::vector<Time> &times, UInt degree, Bool throwException, Bool leastSquares,\n             Double range, Double extrapolation, Double margin=1e-5) {init(times, degree, throwException, leastSquares, range, extrapolation, margin);}\n\n  /** @brief Initialize the interpolator.\n  * @param times epochs of the input data.\n  * @param degree of the polynomial.\n  * @param throwException otherwise the non-interpolated values filled with NaN.\n  * @param leastSquares use least squares fit polynomial instead of interpolation polynomial.\n  * @param range interpolation is only allowed if all nodal points are within this interval or\n  *              in case of least squares fit use all points within [t-range, t+range)\n  *              (given in [seconds] or if negative given in the input median sampling).\n  * @param extrapolation data will be extrapolated only if the nearest nodal point is less than this distance away\n  *              (given in [seconds] or if negative given in the input median sampling).\n  * @param margin to accelerate the interpolation check input times for equidistant sampling within margin [seconds].  */\n  void init(const std::vector<Time> &times, UInt degree, Bool throwException, Bool leastSquares,\n            Double range, Double extrapolation, Double margin=1e-5);\n\n  /** @brief Simplified initialization.\n  * Initialized with @a leastSquares=FALSE, @p range=-(degree+1.1), and @p Double extrapolation=-1.1\n  * (Allow inter/extrapolation of one missing epoch).\n  * @see init(const std::vector<Time> &, UInt, Bool, Bool, Double, Double, Double). */\n  void init(const std::vector<Time> &times, UInt degree, Bool throwException=TRUE) {init(times, degree, throwException, FALSE/*leastSquares*/, -(degree+1.1), -1.1, 1e-5);}\n\n  /** @brief Interpolate a matrix to new epochs.\n  * @param timesNew output epochs of the returned matrix.\n  * @param A input data of time series\n  * @param rowsPerEpoch e.g. for @a A with positions (x,y,z) per epoch in separated rows.\n  * @param derivative compute the kth derivative.\n  * @param adjoint Apply the adjoint (transpose) operator (rows of A relates to timesNew, ouput rows relates to times).\n  * @return Interpolated matrix with timesNew.size()*rowsPerEpoch rows. */\n  Matrix interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch, UInt derivative, Bool adjoint=FALSE) const;\n\n  /** @brief Interpolate a matrix to new epochs.\n  * @see interpolate(const std::vector<Time> &, const_MatrixSliceRef, UInt, UInt) */\n  Matrix interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch=1) const {return interpolate(timesNew, A, rowsPerEpoch, 0);}\n\n  /** @brief Compute derivatives of a time series.\n  * @see interpolate(const std::vector<Time> &, const_MatrixSliceRef, UInt, UInt) */\n  Matrix derivative(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch=1) const {return interpolate(timesNew, A, rowsPerEpoch, 1);}\n\n  /** @brief Compute 2nd derivatives of a time series.\n  * @see interpolate(const std::vector<Time> &, const_MatrixSliceRef, UInt, UInt) */\n  Matrix derivative2nd(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch=1) const {return interpolate(timesNew, A, rowsPerEpoch, 2);}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_POLYNOMIAL__ */\n"
  },
  {
    "path": "source/base/portable.h",
    "content": "/***********************************************/\n/**\n* @file portable.h\n*\n* @brief Define standard types.\n*\n* This is important to account for different systems.\n* e.g. 'int' have sometimes 16 Bit or 32 Bit size.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PORTABLE__\n#define __GROOPS_PORTABLE__\n\n#include <cstdint>\n\n/***** DEFINES *********************************/\n\n/// Disable external libraries\n// #define GROOPS_DISABLE_ERFA     // compile without ERFA library\n// #define GROOPS_DISABLE_Z        // compile without Z library\n// #define GROOPS_DISABLE_NETCDF   // compile without NETCDF library\n\n/// Disable external sources\n// #define GROOPS_DISABLE_NRLMSIS    // do not use external/nrlmsis2 sources\n// #define GROOPS_DISABLE_JB2008     // do not use external/jb2008 sources\n// #define GROOPS_DISABLE_HWM14      // do not use external/hwm14 sources\n// #define GROOPS_DISABLE_IGRF       // do not use external/igrf sources\n// #define GROOPS_DISABLE_IERS       // do not use external/iers sources\n\n/***** TYPES ***********************************/\n\n/** @brief Standard types.\n* This is important to account for different systems.\n* e.g. 'int' have sometimes 16 Bit or 32 Bit size.\n*/\n//@{\ntypedef float             Float;\ntypedef double            Double;\ntypedef long double       LongDouble;\ntypedef int               Int;\ntypedef std::int32_t      Int32;\ntypedef std::int64_t      Int64;\ntypedef std::size_t       UInt;\ntypedef std::uint16_t     UInt16;\ntypedef std::uint32_t     UInt32;\ntypedef std::uint64_t     UInt64;\ntypedef char              Byte;\ntypedef bool              Bool;\ntypedef char              Char;\n//@}\n\n/***** CONST ***********************************/\n\n#ifndef TRUE\nconstexpr Bool FALSE = false; //!< boolean true\nconstexpr Bool TRUE  = true;  //!< boolean false\n#endif\n\n/***********************************************/\n\n#endif /* __GROOPS_PORTAB__ */\n"
  },
  {
    "path": "source/base/rotary3d.cpp",
    "content": "/***********************************************/\n/**\n* @file rotary3d.cpp\n*\n* @brief Rotations in 3d space.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/ellipsoid.h\"\n#include \"base/vector3d.h\"\n#include \"base/tensor3d.h\"\n#include \"base/transform3d.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/rotary3d.h\"\n\n/***********************************************/\n\n// rotary from 3x3 matrix or quaterions\nRotary3d::Rotary3d(const_MatrixSliceRef q)\n{\n  try\n  {\n    if((q.rows()==3) && (q.columns()==3)) // (3x3) rotary matrix\n    {\n      if( q(0,0)*q(1,1)*q(2,2)+q(0,1)*q(1,2)*q(2,0)+q(0,2)*q(1,0)*q(2,1)\n         -q(2,0)*q(1,1)*q(0,2)-q(2,1)*q(1,2)*q(0,0)-q(2,2)*q(1,0)*q(0,1) < 0)\n        throw(Exception(\"rotary matrix contains reflection\"));\n\n      field[0][0] = q(0,0);\n      field[0][1] = q(0,1);\n      field[0][2] = q(0,2);\n      field[1][0] = q(1,0);\n      field[1][1] = q(1,1);\n      field[1][2] = q(1,2);\n      field[2][0] = q(2,0);\n      field[2][1] = q(2,1);\n      field[2][2] = q(2,2);\n    }\n    else if((q.rows()==4) && (q.columns()==1)) // (4x1) quaternion vector\n    {\n      field[0][0] = q(1,0)*q(1,0)-q(2,0)*q(2,0)-q(3,0)*q(3,0)+q(0,0)*q(0,0);\n      field[0][1] = 2*(q(1,0)*q(2,0)-q(3,0)*q(0,0));\n      field[0][2] = 2*(q(1,0)*q(3,0)+q(2,0)*q(0,0));\n      field[1][0] = 2*(q(1,0)*q(2,0)+q(3,0)*q(0,0));\n      field[1][1] = q(2,0)*q(2,0)-q(1,0)*q(1,0)-q(3,0)*q(3,0)+q(0,0)*q(0,0);\n      field[1][2] = 2*(q(2,0)*q(3,0)-q(1,0)*q(0,0));\n      field[2][0] = 2*(q(1,0)*q(3,0)-q(2,0)*q(0,0));\n      field[2][1] = 2*(q(2,0)*q(3,0)+q(1,0)*q(0,0));\n      field[2][2] = q(3,0)*q(3,0)-q(2,0)*q(2,0)-q(1,0)*q(1,0)+q(0,0)*q(0,0);\n    }\n    else\n      throw(Exception(\"matrix is not quaternion nor rotary matrix\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d::Rotary3d(Vector3d x, Vector3d y)\n{\n  // Orthonormalize\n  x.normalize();\n  Vector3d z = normalize(crossProduct(x,y));\n  y = crossProduct(z,x);\n\n  field[0][0] = x.x(); field[0][1] = y.x(); field[0][2] = z.x();\n  field[1][0] = x.y(); field[1][1] = y.y(); field[1][2] = z.y();\n  field[2][0] = x.z(); field[2][1] = y.z(); field[2][2] = z.z();\n}\n\n/***********************************************/\n\nVector Rotary3d::quaternion() const\n{\n  Vector q(4);\n  if( field[0][0] + field[1][1] + field[2][2] > 0.)\n  {\n    Double t = 1. + field[0][0] + field[1][1] + field[2][2];\n    Double s = 0.5/sqrt(t);\n    q(0) = s*t;\n    q(3) = (field[1][0] - field[0][1]) * s;\n    q(2) = (field[0][2] - field[2][0]) * s;\n    q(1) = (field[2][1] - field[1][2]) * s;\n  }\n  else if((field[0][0] > field[1][1]) && (field[0][0] > field[2][2]))\n  {\n    Double t = 1. + field[0][0] - field[1][1] - field[2][2];\n    Double s = 0.5/sqrt(t);\n    q(1) = s*t;\n    q(2) = (field[1][0] + field[0][1]) * s;\n    q(3) = (field[0][2] + field[2][0]) * s;\n    q(0) = (field[2][1] - field[1][2]) * s;\n  }\n  else if(field[1][1] > field[2][2])\n  {\n    Double t = 1. - field[0][0] + field[1][1] - field[2][2];\n    Double s = 0.5/sqrt(t);\n    q(2) = s*t;\n    q(1) = (field[1][0] + field[0][1]) * s;\n    q(0) = (field[0][2] - field[2][0]) * s;\n    q(3) = (field[2][1] + field[1][2]) * s;\n  }\n  else\n  {\n    Double t = 1. - field[0][0] - field[1][1] + field[2][2];\n    Double s = 0.5/sqrt(t);\n    q(3) = s*t;\n    q(0) = (field[1][0] - field[0][1]) * s;\n    q(1) = (field[0][2] + field[2][0]) * s;\n    q(2) = (field[2][1] + field[1][2]) * s;\n  }\n  return q;\n}\n\n/***********************************************/\n\nVector3d Rotary3d::rotate(const Vector3d &v) const\n{\n  Vector3d erg;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      erg.field[i] += field[i][k] * v.field[k];\n  return erg;\n}\n\nVector3d Rotary3d::transform(const Vector3d &v) const {return rotate(v);}\n\n/***********************************************/\n\nVector3d Rotary3d::inverseRotate(const Vector3d &v) const\n{\n  Vector3d erg;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      erg.field[i] += field[k][i] * v.field[k];\n  return erg;\n}\n\nVector3d Rotary3d::inverseTransform(const Vector3d &v) const {return inverseRotate(v);}\n\n/***********************************************/\n\nTensor3d Rotary3d::rotate(const Tensor3d &t) const\n{\n  auto rot = [&](UInt i, UInt k)\n  {\n    return  field[i][0]*field[k][0] * t.xx()\n         +  field[i][1]*field[k][1] * t.yy()\n         +  field[i][2]*field[k][2] * t.zz()\n         + (field[i][0]*field[k][1] + field[i][1]*field[k][0]) * t.xy()\n         + (field[i][0]*field[k][2] + field[i][2]*field[k][0]) * t.xz()\n         + (field[i][1]*field[k][2] + field[i][2]*field[k][1]) * t.yz();\n  };\n\n  Tensor3d t2;\n  t2.xx() = rot(0, 0);\n  t2.yy() = rot(1, 1);\n  t2.zz() = rot(2, 2);\n  t2.xy() = rot(0, 1);\n  t2.xz() = rot(0, 2);\n  t2.yz() = rot(1, 2);\n  return t2;\n}\n\nTensor3d Rotary3d::transform(const Tensor3d &t) const {return rotate(t);}\n\n/***********************************************/\n\nTensor3d Rotary3d::inverseRotate(const Tensor3d &t) const\n{\n  auto rot = [&](UInt i, UInt k)\n  {\n    return  field[0][i]*field[0][k] * t.xx()\n         +  field[1][i]*field[1][k] * t.yy()\n         +  field[2][i]*field[2][k] * t.zz()\n         + (field[0][i]*field[1][k] + field[1][i]*field[0][k]) * t.xy()\n         + (field[0][i]*field[2][k] + field[2][i]*field[0][k]) * t.xz()\n         + (field[1][i]*field[2][k] + field[2][i]*field[1][k]) * t.yz();\n  };\n\n  Tensor3d t2;\n  t2.xx() = rot(0, 0);\n  t2.yy() = rot(1, 1);\n  t2.zz() = rot(2, 2);\n  t2.xy() = rot(0, 1);\n  t2.xz() = rot(0, 2);\n  t2.yz() = rot(1, 2);\n  return t2;\n}\n\nTensor3d Rotary3d::inverseTransform(const Tensor3d &t) const {return inverseRotate(t);}\n\n/***********************************************/\n\nSphericalHarmonics Rotary3d::rotate(const SphericalHarmonics &harm) const\n{\n  return harm.rotate(*this);\n}\n\n/***********************************************/\n\nSphericalHarmonics Rotary3d::inverseRotate(const SphericalHarmonics &harm) const\n{\n  return harm.rotate(inverse(*this));\n}\n\n/***********************************************/\n\nRotary3d &Rotary3d::operator*= (const Rotary3d &b)\n{\n  *this = *this * b;\n  return *this;\n}\n\n/***********************************************/\n\nRotary3d Rotary3d::operator* (const Rotary3d &b) const\n{\n  Rotary3d erg;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n    {\n      erg.field[i][k] = 0.0;\n      for(UInt l=0; l<3; l++)\n        erg.field[i][k] += field[i][l] * b.field[l][k];\n    }\n  return erg;\n}\n\n/***********************************************/\n\nTransform3d Rotary3d::operator*(const Transform3d &b) const\n{\n  Transform3d erg;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n    {\n      erg.field[i][k] = 0.0;\n      for(UInt l=0; l<3; l++)\n        erg.field[i][k] += field[i][l] * b.field[l][k];\n    }\n  return erg;\n}\n\n/***********************************************/\n\nvoid Rotary3d::euler(Angle &alpha, Angle &beta, Angle &gamma) const\n{\n  beta  = atan2(sqrt(field[2][0]*field[2][0]+field[2][1]*field[2][1]), field[2][2]);\n  if(beta == 0.)\n  {\n    alpha = atan2(field[0][1], field[0][0]);\n    gamma = 0;\n    return;\n  }\n  alpha = atan2(field[2][0], -field[2][1]);\n  gamma = atan2(field[0][2],  field[1][2]);\n}\n\n/***********************************************/\n\nvoid Rotary3d::cardan(Angle &roll, Angle &pitch, Angle &yaw) const\n{\n  roll  = -atan2( field[2][1], field[2][2]);\n  pitch = -atan2(-field[2][0], sqrt(field[2][1]*field[2][1]+field[2][2]*field[2][2]));\n  yaw   = -atan2( field[1][0], field[0][0]);\n}\n\n/***********************************************/\n/***********************************************/\n\nRotary3d rotaryX(Angle angle)\n{\n  const Double c = cos(angle);\n  const Double s = sin(angle);\n  Rotary3d rot;\n  rot.field[1][1] =  c; rot.field[1][2] = s;\n  rot.field[2][1] = -s; rot.field[2][2] = c;\n  return rot;\n}\n\n/***********************************************/\n\nRotary3d rotaryY(Angle angle)\n{\n  const Double c = cos(angle);\n  const Double s = sin(angle);\n  Rotary3d rot;\n  rot.field[0][0] = c; rot.field[0][2] = -s;\n  rot.field[2][0] = s; rot.field[2][2] =  c;\n  return rot;\n}\n\n/***********************************************/\n\nRotary3d rotaryZ(Angle angle)\n{\n  const Double c = cos(angle);\n  const Double s = sin(angle);\n  Rotary3d rot;\n  rot.field[0][0] =  c; rot.field[0][1] = s;\n  rot.field[1][0] = -s; rot.field[1][1] = c;\n  return rot;\n}\n\n/***********************************************/\n\nRotary3d inverse(const Rotary3d &b)\n{\n  Rotary3d rot;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      rot.field[i][k] = b.field[k][i];\n  return rot;\n}\n\n/***********************************************/\n\nRotary3d localNorthEastDown(const Vector3d &point)\n{\n  const Vector3d z = normalize(-point);                           // down\n  const Vector3d y = normalize(crossProduct(z, Vector3d(0,0,1))); // east\n  const Vector3d x = normalize(crossProduct(y, z));               // north\n  Rotary3d rot;\n  rot.field[0][0] = x.x(); rot.field[0][1] = y.x(); rot.field[0][2] = z.x();\n  rot.field[1][0] = x.y(); rot.field[1][1] = y.y(); rot.field[1][2] = z.y();\n  rot.field[2][0] = x.z(); rot.field[2][1] = y.z(); rot.field[2][2] = z.z();\n  return rot;\n}\n\n/***********************************************/\n\nRotary3d localNorthEastDown(const Vector3d &point, const Ellipsoid &ellipsoid)\n{\n  Angle  L, B;\n  Double h;\n  ellipsoid(point, L, B, h);\n  return localNorthEastDown(polar(L, B, 1.));\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/base/rotary3d.h",
    "content": "/***********************************************/\n/**\n* @file rotary3d.h\n*\n* @brief Rotations in 3d space.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ROTARY3D__\n#define __GROOPS_ROTARY3D__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/** @addtogroup vector3dGroup */\n/// @{\n\nclass Angle;\nclass Vector3d;\nclass Tensor3d;\nclass Transform3d;\nclass Ellipsoid;\nclass SphericalHarmonics;\n\n/***** CLASS ***********************************/\n\n/** @brief Rotations in 3d space.\n* Rotation of @a Vector3d and @a Tensor3d. */\nclass Rotary3d\n{\n  std::array<std::array<Double,3>,3> field;\n\npublic:\n  Rotary3d() : field{{{1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}}} {} //!< Default constructor (Unitary matrix).\n\n  /// Contructor from std::array.\n  Rotary3d(const std::array<std::array<Double,3>,3> &x) : field(x) {}\n\n  /// Contructor from quaternions (q0, qx, qy, qz) or rotary matrix (3x3).\n  explicit Rotary3d(const_MatrixSliceRef q);\n\n  /** @brief Rotation of a local system.\n  * Rotational matrix from local system (defined by the given axis x,y,z)\n  * to the global system. The axis will be normalized and orthogonalized before.\n  * The z-axis is defined orthogonal to x and y.\n  * Zhe y-axis is defined orthogonal to the new z-axis and x. */\n  Rotary3d(Vector3d x, Vector3d y);\n\n  /// Quaternions (q0, qx, qy, qz).\n  Vector quaternion() const;\n\n  /// Cast to Matrix.\n  Matrix matrix() const;\n\n  /** @brief Rotate a vector.\n  * \\f[ y = D \\cdot v \\f]. */\n  Vector3d rotate(const Vector3d &v) const;\n  /** @copydoc rotate */\n  Vector3d transform(const Vector3d &v) const;\n\n  /** @brief Inverse rotation of a vector.\n  * \\f[ y = D^T \\cdot v \\f]. */\n  Vector3d inverseRotate(const Vector3d &v) const;\n  /** @copydoc inverseRotate */\n  Vector3d inverseTransform(const Vector3d &v) const;\n\n  /** @brief Rotate a tensor.\n  * Both sides of the dyadic product are rotated.\n  * \\f[ y = D \\cdot t \\cdot D^T \\f]. */\n  Tensor3d rotate(const Tensor3d &t) const;\n  /** @copydoc rotate */\n  Tensor3d transform(const Tensor3d &t) const;\n\n  /** @brief Inverse rotation a tensor.\n  * Both sides of the dyadic product are rotated.\n  * \\f[ y = D^T \\cdot t \\cdot D \\f]. */\n  Tensor3d inverseRotate(const Tensor3d &t) const;\n  /** @copydoc inverseRotate */\n  Tensor3d inverseTransform(const Tensor3d &t) const;\n\n  /** @brief Rotate spherical harmonic coefficients. */\n  SphericalHarmonics rotate(const SphericalHarmonics &harm) const;\n\n  /** @brief Inverse of spherical harmonic coefficients. */\n  SphericalHarmonics inverseRotate(const SphericalHarmonics &harm) const;\n\n  /** @brief Return Euler angles.\n  * @code rotary = rotaryZ(gamma)*rotaryX(beta)*rotaryZ(alpha); @endcode */\n  void euler(Angle &alpha, Angle &beta, Angle &gamma) const;\n\n  /** @brief Return Euler angles.\n  * @code rotary = rotaryZ(yaw)*rotaryY(pitch)*rotaryX(roll); @endcode */\n  void cardan(Angle &roll, Angle &pitch, Angle &yaw) const;\n\n  Rotary3d    &operator*=(Rotary3d const &b);\n  Rotary3d     operator* (Rotary3d const &b) const;\n  Transform3d  operator* (Transform3d const &b) const;\n\n  friend class Transform3d;\n  friend Rotary3d rotaryX(Angle angle);\n  friend Rotary3d rotaryY(Angle angle);\n  friend Rotary3d rotaryZ(Angle angle);\n  friend Rotary3d inverse(const Rotary3d &b);\n  friend Rotary3d localNorthEastDown(const Vector3d &point);\n};\n\n/***********************************************/\n\n/** @brief Rotation about x-axis.\n* @param angle in [rad].\n* \\f[ D=\\left(\\begin{array}{ccc}\n      1 & 0          & 0          \\\\\n      0 & \\cos\\alpha & \\sin\\alpha \\\\\n      0 &-\\sin\\alpha & \\cos\\alpha\n      \\end{array}\\right) \\f] */\nRotary3d rotaryX(Angle angle);\n\n/** @brief Rotation about y-axis.\n* @param angle in [rad].\n* \\f[ D=\\left(\\begin{array}{ccc}\n      \\cos\\alpha & 0 &-\\sin\\alpha \\\\\n      0          & 1 & 0          \\\\\n      \\sin\\alpha & 0 & \\cos\\alpha\n      \\end{array}\\right) \\f] */\nRotary3d rotaryY(Angle angle);\n\n/** @brief Rotation about z-axis.\n* @param angle in [rad].\n* \\f[ D=\\left(\\begin{array}{ccc}\n      \\cos\\alpha & \\sin\\alpha & 0 \\\\\n     -\\sin\\alpha & \\cos\\alpha & 0 \\\\\n      0          & 0          & 1\n      \\end{array}\\right) \\f] */\nRotary3d rotaryZ(Angle angle);\n\n/** @brief Rotary3d of inverse rotation.\n* Transposed matrix. */\nRotary3d inverse(const Rotary3d &b);\n\n/** @brief Rotational matrix from local system (north, east, down) to the global system (coordinate system of point). */\n//[[deprecated]]\nRotary3d localNorthEastDown(const Vector3d &point);\n\n/** @brief Rotational matrix from local system (north, east, down) to the global system (coordinate system of point).\n* Converts @p point to ellipsoidal coordinates beforehand. */\n//[[deprecated]]\nRotary3d localNorthEastDown(const Vector3d &point, const Ellipsoid &ellipsoid);\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ninline Matrix Rotary3d::matrix() const\n{\n  Matrix R(3, 3, Matrix::NOFILL);\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      R(i,k) = field[i][k];\n  return R;\n}\n\n/*************************************************/\n\n#endif /* __GROOPS_VECTOR3D__ */\n\n\n"
  },
  {
    "path": "source/base/sphericalHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonics.cpp\n*\n* @brief Spherical harmonics and functions of the gravity field.\n*\n* (4Pi normalized).\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/tensor3d.h\"\n#include \"base/rotary3d.h\"\n#include \"base/sphericalHarmonics.h\"\n\n/***********************************************/\n\nMatrix SphericalHarmonics::factor1;\nMatrix SphericalHarmonics::factor2;\n\n/***********************************************/\n\nvoid SphericalHarmonics::computeFactors(UInt degree)\n{\n  // Enough factors?\n  if(factor1.rows()>degree)\n    return;\n\n  factor1 = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  factor2 = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  // factors for the recursion P[n-1][n-1] -> P[n][n]\n  if(degree>0) factor1(1,1) = std::sqrt(3.);\n  for(UInt n=2; n<=degree; n++)\n    factor1(n,n) =  std::sqrt((2.*n+1.)/(2.*n));\n\n  // factors for the recursion P[m][n-1] and P[m][n-2] -> P[m][n]\n  for(UInt m=0; m<degree; m++)\n    for(UInt n=m+1; n<=degree; n++)\n    {\n      Double f = (2.*n+1.)/static_cast<Double>((n+m)*(n-m));\n      factor1(n,m) =  std::sqrt(f*(2.*n-1.));\n      factor2(n,m) = -std::sqrt(f*(n-m-1.)*(n+m-1.)/(2.*n-3.));\n    }\n}\n\n/***********************************************/\n\n// Basis functions Ynm (Cnm and Snm)\nvoid SphericalHarmonics::CnmSnm(const Vector3d &point, UInt degree, Matrix &Cnm, Matrix &Snm, Bool interior)\n{\n  computeFactors(degree);\n\n  Cnm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Snm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  Double rr, x, y, z;\n  if(!interior)\n  {\n    rr = pow(1/point.r(),2);\n    x  = point.x() * rr;\n    y  = point.y() * rr;\n    z  = point.z() * rr;\n    Cnm(0,0) = 1e280/point.r(); // dirty trick: to account for small numbers in very high degrees.\n  }\n  else\n  {\n    rr = pow(point.r(),2);\n    x  = point.x();\n    y  = point.y();\n    z  = point.z();\n    Cnm(0,0) = 1e280; // dirty trick: to account for small numbers in very high degrees.\n  }\n\n  // Recursion diagonal\n  // C(n-1,n-1) -> C(n,n)\n  for(UInt n=1; n<=degree; n++)\n  {\n    Cnm(n,n) = factor1(n,n) * (x * Cnm(n-1,n-1) - y * Snm(n-1,n-1));\n    Snm(n,n) = factor1(n,n) * (y * Cnm(n-1,n-1) + x * Snm(n-1,n-1));\n  }\n\n  // Recursion secondary diagonal\n  // C(n-1,n-1) -> C(n,n-1)\n  for(UInt n=1; n<=degree; n++)\n  {\n    Cnm(n,n-1) = factor1(n,n-1) * z * Cnm(n-1,n-1);\n    Snm(n,n-1) = factor1(n,n-1) * z * Snm(n-1,n-1);\n  }\n\n  // Recursion others\n  // C(n-1,m),C(n-1,m) -> C(n,m)\n  if(degree>1)\n  {\n    for(UInt m=0; m<(degree-1); m++)\n    {\n      Double *c  = &Cnm(m+2,m),     *s  = &Snm(m+2,m);\n      Double *f1 = &factor1(m+2,m), *f2 = &factor2(m+2,m);\n\n      for(UInt n=m+2; n<=degree; n++)\n      {\n        *c = *f1 * z * c[-1] + *f2 * rr * c[-2];\n        *s = *f1 * z * s[-1] + *f2 * rr * s[-2];\n        c++; s++; f1++; f2++;\n      }\n    }\n  }\n\n  Cnm *= 1e-280; // dirty trick: to account for small numbers in very high degrees.\n  Snm *= 1e-280;\n}\n\n/***********************************************/\n\nMatrix SphericalHarmonics::Pnm(Angle theta, Double _r, UInt degree, Bool interior)\n{\n  computeFactors(degree);\n\n  Matrix Pnm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  Double r;\n  if(!interior)\n  {\n    r = 1/_r;\n    Pnm(0,0) = 1e280*r; // dirty trick: to account for small numbers in very high degrees.\n  }\n  else\n  {\n    r = _r;\n    Pnm(0,0) = 1e280; // dirty trick: to account for small numbers in very high degrees.\n  }\n  const Double rr = pow(r,2);\n  const Double x  = sin(theta) * r;\n  const Double z  = cos(theta) * r;\n\n  // Recursion diagonal\n  // C(n-1,n-1) -> C(n,n)\n  for(UInt n=1; n<=degree; n++)\n    Pnm(n,n) = factor1(n,n) * (x * Pnm(n-1,n-1));\n\n  // Recursion secondary diagonal\n  // C(n-1,n-1) -> C(n,n-1)\n  for(UInt n=1; n<=degree; n++)\n    Pnm(n,n-1) = factor1(n,n-1) * z * Pnm(n-1,n-1);\n\n  // Recursion others\n  // C(n-1,m),C(n-1,m) -> C(n,m)\n  if(degree>1)\n  {\n    for(UInt m=0; m<(degree-1); m++)\n    {\n      Double *c  = &Pnm(m+2,m);\n      Double *f1 = &factor1(m+2,m);\n      Double *f2 = &factor2(m+2,m);\n\n      for(UInt n=m+2; n<=degree; n++)\n      {\n        *c = *f1 * z * c[-1] + *f2 * rr * c[-2];\n        c++; f1++; f2++;\n      }\n    }\n  }\n\n  Pnm *= 1e-280; // dirty trick: to account for small numbers in very high degrees.\n  return Pnm;\n}\n\n/***********************************************/\n\nSphericalHarmonics::SphericalHarmonics(Bool interior) :\n  _GM(DEFAULT_GM),\n  _R(DEFAULT_R),\n  _maxDegree(0),\n  _cnm(_maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER),\n  _snm(_maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER),\n  _interior(interior)\n{\n}\n\n/***********************************************/\n\nSphericalHarmonics::SphericalHarmonics(Double GM, Double R, const const_MatrixSlice &cnm, const const_MatrixSlice &snm, Bool interior) :\n    _GM(GM),\n    _R(R),\n    _maxDegree(cnm.rows()-1),\n    _cnm(cnm),\n    _snm(snm),\n    _interior(interior)\n{\n  try\n  {\n    if(cnm.rows()!=snm.rows())\n      throw(Exception(\"Dimensions of potential coefficients do not agree\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics::SphericalHarmonics(Double GM, Double R, const const_MatrixSlice &cnm, const const_MatrixSlice &snm, const const_MatrixSlice &sigma2cnm, const const_MatrixSlice &sigma2snm, Bool interior) :\n    _GM(GM),\n    _R(R),\n    _maxDegree(cnm.rows()-1),\n    _cnm(cnm),\n    _snm(snm),\n    _sigma2cnm(sigma2cnm),\n    _sigma2snm(sigma2snm),\n    _interior(interior)\n{\n  try\n  {\n    if((cnm.rows() != snm.rows()) ||\n       ((sigma2cnm.size() || sigma2snm.size()) && ((cnm.rows() != sigma2cnm.rows()) || (snm.rows() != sigma2snm.rows()))))\n      throw(Exception(\"Dimensions of potential coefficients do not agree\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics SphericalHarmonics::get(UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  if(GM <= 0) GM = _GM;\n  if(R  <= 0) R  = _R;\n  if(maxDegree == INFINITYDEGREE)\n    maxDegree = _maxDegree;\n\n  // Quick return possible?\n  if((GM == _GM) && (R == _R) && (minDegree == 0) && (maxDegree == _maxDegree))\n    return SphericalHarmonics(GM, R, _cnm, _snm, _sigma2cnm, _sigma2snm, _interior);\n\n  const UInt maxd = std::min(maxDegree, _maxDegree);\n  if(minDegree > maxd)\n    return SphericalHarmonics(GM, R, Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER), Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER), _interior);\n\n  Matrix cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  copy(_cnm.slice(minDegree, 0, maxd-minDegree+1, maxd+1), cnm.slice(minDegree, 0, maxd-minDegree+1, maxd+1));\n  copy(_snm.slice(minDegree, 0, maxd-minDegree+1, maxd+1), snm.slice(minDegree, 0, maxd-minDegree+1, maxd+1));\n\n  Matrix sigma2cnm, sigma2snm;\n  if(_sigma2cnm.size())\n  {\n    sigma2cnm = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    sigma2snm = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    copy(_sigma2cnm.slice(minDegree,0,maxd-minDegree+1,maxd+1), sigma2cnm.slice(minDegree,0,maxd-minDegree+1,maxd+1));\n    copy(_sigma2snm.slice(minDegree,0,maxd-minDegree+1,maxd+1), sigma2snm.slice(minDegree,0,maxd-minDegree+1,maxd+1));\n  }\n\n  // adjust factors\n  if(R != _R)\n  {\n    Double factor = (_interior) ? (_GM/GM*pow(R/_R, minDegree+1)) : (_GM/GM*pow(_R/R, minDegree));\n    for(UInt n=minDegree; n<=maxd; n++)\n    {\n      cnm.slice(n, 0, 1, n+1) *= factor;\n      snm.slice(n, 0, 1, n+1) *= factor;\n      if(sigma2cnm.size()) sigma2cnm.slice(n, 0, 1, n+1) *= factor*factor;\n      if(sigma2snm.size()) sigma2snm.slice(n, 0, 1, n+1) *= factor*factor;\n      factor *= ((_interior) ? R/_R : _R/R);\n    }\n  }\n  else if(GM != _GM)\n  {\n    const Double factor = _GM/GM;\n    cnm *= factor;\n    snm *= factor;\n    if(sigma2cnm.size()) sigma2cnm *= factor*factor;\n    if(sigma2snm.size()) sigma2snm *= factor*factor;\n  }\n\n  return SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm, _interior);\n}\n\n/***********************************************/\n\n// Based on\n// \"On a Fortran procedure for rotating spherical-harmonic coefficients\"\n// R. H. Gooding, C. A. Wagner, DOI 10.1007/s10569-010-9293-3\nSphericalHarmonics SphericalHarmonics::rotate(const Rotary3d &rotary) const\n{\n  try\n  {\n    Angle alpha, beta, gamma;\n    rotary.euler(alpha, beta, gamma); // rotary = rotaryZ(gamma)*rotaryX(beta)*rotaryZ(alpha);\n\n    Double s = sin(0.5*beta);\n    Double c = cos(0.5*beta);\n    if(s*s<0.5) // consistency for I/2 is set up\n      s = std::sqrt((1.-c)*(1.+c)); // xImod from 2*asin(s)*radian if wanted\n    else\n      c = std::sqrt((1.-s)*(1.+s)); // xImod from 2*acos(c)*radian if wanted\n\n    // initialize d-matrix degree 1/2 (Risbo comment)\n    Matrix d(2,2);\n    d(0,0) =  c;\n    d(0,1) =  s;\n    d(1,0) = -s;\n    d(1,1) =  c;\n\n    // MAIN LOOP: combination of Risbo (for key d-file) & Gooding (for rotation)\n    Matrix cnmRot(_maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snmRot(_maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    cnmRot(0,0) = _cnm(0,0);\n    for(UInt j=2; j<=2*_maxDegree; j++)\n    {\n      // recursion in two directions from d to dd (Risbo comment)\n      Matrix dd(j+1, j+1);\n      for(UInt i=0; i<j; i++)\n        for(UInt k=0; k<j; k++)\n        {\n          dd(i,  k)   += std::sqrt((j-i)*(j-k))/j * c * d(i,k);\n          dd(i+1,k)   -= std::sqrt((i+1)*(j-k))/j * s * d(i,k);\n          dd(i,  k+1) += std::sqrt((j-i)*(k+1))/j * s * d(i,k);\n          dd(i+1,k+1) += std::sqrt((i+1)*(k+1))/j * c * d(i,k);\n        }\n      d = dd;\n\n      // do the rotation (Gooding), ignoring half-integer degrees\n      if((j%2)==0)\n      {\n        const UInt n = j/2;\n        for(UInt k=0; k<=n; k++)\n          for(UInt m=0; m<=n; m++)\n          {\n            const Double dplus  = d(n+k, n+m) * ((m==0) ? std::sqrt(0.5) : 1.) * ((k==0) ? std::sqrt(0.5) : 1.);\n            const Double dminus = d(n+k, n-m) * ((m==0) ? std::sqrt(0.5) : 1.) * ((k==0) ? std::sqrt(0.5) : 1.) * (((m%2)==1) ? -1. : 1.);\n            const Double cm     = std::cos(m*(alpha-PI/2));\n            const Double sm     = std::sin(m*(alpha-PI/2));\n            const Double ck     = std::cos(k*(-gamma-PI/2));\n            const Double sk     = std::sin(k*(-gamma-PI/2));\n            cnmRot(n,k) += (ck*cm*(dplus+dminus)+sk*sm*(dplus-dminus)) * _cnm(n,m) + (ck*sm*(dplus+dminus)-sk*cm*(dplus-dminus)) * _snm(n,m);\n            snmRot(n,k) += (sk*cm*(dplus+dminus)-ck*sm*(dplus-dminus)) * _cnm(n,m) + (sk*sm*(dplus+dminus)+ck*cm*(dplus-dminus)) * _snm(n,m);\n          }\n      }\n    } // for(j)\n\n    return SphericalHarmonics(_GM, _R, cnmRot, snmRot);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics &SphericalHarmonics::operator+= (const SphericalHarmonics &harm)\n{\n  try\n  {\n    if(_interior != harm._interior)\n      throw(Exception(\"Cannot add inner and outer space spherical harmonics\"));\n\n    // swap: add smaller to larger matrix and adjust GM and R\n    const SphericalHarmonics harm2 = (maxDegree()<harm.maxDegree()) ? get(INFINITYDEGREE, 0, harm.GM(), harm.R()) : harm.get(INFINITYDEGREE, 0, GM(), R());\n    if(maxDegree()<harm.maxDegree())\n      *this = harm;\n\n    _cnm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) += harm2.cnm();\n    _snm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) += harm2.snm();\n    if(harm2.sigma2cnm().size() && !_sigma2cnm.size()) _sigma2cnm = Matrix(maxDegree()+1, Matrix::SYMMETRIC, Matrix::LOWER);\n    if(harm2.sigma2snm().size() && !_sigma2snm.size()) _sigma2snm = Matrix(maxDegree()+1, Matrix::SYMMETRIC, Matrix::LOWER);\n    if(harm2.sigma2cnm().size()) _sigma2cnm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) += harm2.sigma2cnm();\n    if(harm2.sigma2snm().size()) _sigma2snm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) += harm2.sigma2snm();\n\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics &SphericalHarmonics::operator-= (const SphericalHarmonics &harm)\n{\n  try\n  {\n    if(_interior != harm._interior)\n      throw(Exception(\"Cannot subtract inner and outer space spherical harmonics\"));\n\n    // swap: add smaller to larger matrix and adjust GM and R\n    const SphericalHarmonics harm2 = (maxDegree()<harm.maxDegree()) ? get(INFINITYDEGREE, 0, harm.GM(), harm.R()) : harm.get(INFINITYDEGREE, 0, GM(), R());\n    if(maxDegree()<harm.maxDegree())\n      *this = harm;\n\n    _cnm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) -= harm2.cnm();\n    _snm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) -= harm2.snm();\n    if(harm2.sigma2cnm().size() && !_sigma2cnm.size()) _sigma2cnm = Matrix(maxDegree()+1, Matrix::SYMMETRIC, Matrix::LOWER);\n    if(harm2.sigma2snm().size() && !_sigma2snm.size()) _sigma2snm = Matrix(maxDegree()+1, Matrix::SYMMETRIC, Matrix::LOWER);\n    if(harm2.sigma2cnm().size()) _sigma2cnm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) += harm2.sigma2cnm();\n    if(harm2.sigma2snm().size()) _sigma2snm.slice(0, 0, harm2.maxDegree()+1, harm2.maxDegree()+1) += harm2.sigma2snm();\n\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics &SphericalHarmonics::operator*= (Double c)\n{\n  _cnm *= c;\n  _snm *= c;\n  if(_sigma2cnm.size()) _sigma2cnm *= c*c;\n  if(_sigma2snm.size()) _sigma2snm *= c*c;\n  return *this;\n}\n\n/***********************************************/\n\n// Yn = GM/R * sum (cnm*Cnm + snm*Snm)\nVector SphericalHarmonics::Yn(const Vector3d &point, UInt maxDegree) const\n{\n  if(maxDegree==INFINITYDEGREE)\n   maxDegree = this->maxDegree();\n\n  Matrix Cnm, Snm;\n  CnmSnm(1/R() * point, std::min(maxDegree, this->maxDegree()), Cnm, Snm, _interior);\n\n  Vector Y(maxDegree+1);\n  Double *Yn = &Y(0);\n  Double fak = GM()/R();\n  for(UInt n=0; n<=std::min(maxDegree,_maxDegree); n++)\n    *(Yn++) = fak * (inner(_cnm.slice(n,0,1,n+1), Cnm.slice(n,0,1,n+1))\n                    +inner(_snm.slice(n,1,1,n),   Snm.slice(n,1,1,n)));\n  return Y;\n}\n\n/***********************************************/\n\nDouble SphericalHarmonics::potential(const Vector3d &point, UInt maxDegree, UInt minDegree) const\n{\n  try\n  {\n    maxDegree = std::min(maxDegree, this->maxDegree());\n\n    const Vector Y = Yn(point, maxDegree);\n\n    Double sum = 0.0;\n    for(UInt n=minDegree; n<=maxDegree; n++)\n      sum += Y(n);\n\n    return sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SphericalHarmonics::radialGradient(const Vector3d &point, UInt maxDegree, UInt minDegree) const\n{\n  try\n  {\n    maxDegree  = std::min(maxDegree, this->maxDegree());\n    const Double r = point.r();\n    const Vector Y = Yn(point, maxDegree);\n    Double sum = 0.0;\n    if(!_interior)\n      for(UInt n=minDegree; n<=maxDegree; n++)\n        sum += -(n+1.)/r * Y(n);\n    else\n      for(UInt n=minDegree; n<=maxDegree; n++)\n        sum += n/r * Y(n);\n    return sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d SphericalHarmonics::gravity(const Vector3d &point, UInt maxDegree, UInt minDegree) const\n{\n  try\n  {\n    if(_interior)\n      throw(Exception(\"not implemented yet for inner space\"));\n\n    maxDegree = std::min(maxDegree, this->maxDegree());\n\n    Matrix Cnm, Snm;\n    CnmSnm(1/R() * point, maxDegree+1, Cnm, Snm);\n\n    Vector3d g, g_ges;\n\n    // all degrees\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      // 0. Order\n      Double wm0 = std::sqrt(static_cast<Double>(n+1)*(n+1));\n      Double wp1 = std::sqrt(static_cast<Double>(n+1)*(n+2)) / std::sqrt(2.0);\n\n      Double Cm0 = wm0*Cnm(n+1,0);\n      Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n      g.x() = _cnm(n,0) * (-2*Cp1);\n      g.y() = _cnm(n,0) * (-2*Sp1);\n      g.z() = _cnm(n,0) * (-2*Cm0);\n\n      // all other orders\n      for(UInt m=1; m<=n; m++)\n      {\n        Double wm1 = std::sqrt(static_cast<Double>(n-m+1)*(n-m+2)) * ((m==1) ? std::sqrt(2.0) : 1.0);\n        Double wm0 = std::sqrt(static_cast<Double>(n-m+1)*(n+m+1));\n        Double wp1 = std::sqrt(static_cast<Double>(n+m+1)*(n+m+2));\n\n        Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n        Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n        Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n        g.x() += _cnm(n,m) * ( Cm1 - Cp1) + _snm(n,m) * (Sm1 - Sp1);\n        g.y() += _cnm(n,m) * (-Sm1 - Sp1) + _snm(n,m) * (Cm1 + Cp1);\n        g.z() += _cnm(n,m) * (-2*Cm0)     + _snm(n,m) * (-2*Sm0);\n      } // for(m)\n\n      g_ges  += std::sqrt((2.*n+1.)/(2.*n+3.))*g;\n    } // for(n)\n\n    return GM()/(2*R()*R()) * g_ges;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nTensor3d SphericalHarmonics::gravityGradient(const Vector3d &point, UInt maxDegree, UInt minDegree) const\n{\n  try\n  {\n    if(_interior)\n      throw(Exception(\"not implemented yet for inner space\"));\n\n    maxDegree = std::min(maxDegree, this->maxDegree());\n\n    Matrix Cnm, Snm;\n    CnmSnm(1/R() * point, maxDegree+2, Cnm, Snm);\n\n    Tensor3d K, K_ges;\n\n    // all degrees\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      // 0. Order\n      Double wm0 = std::sqrt(static_cast<Double>(n+1)*(n+2)*(n+1)*(n+2));\n      Double wp1 = std::sqrt(static_cast<Double>(n+1)*(n+1)*(n+2)*(n+3)) / std::sqrt(2.0);\n      Double wp2 = std::sqrt(static_cast<Double>(n+1)*(n+2)*(n+3)*(n+4)) / std::sqrt(2.0);\n\n      Double Cm0 = wm0*Cnm(n+2,0);\n      Double Cp1 = wp1*Cnm(n+2,1);  Double Sp1 = wp1*Snm(n+2,1);\n      Double Cp2 = wp2*Cnm(n+2,2);  Double Sp2 = wp2*Snm(n+2,2);\n\n      K.xx() = _cnm(n,0) * (-2*Cm0 + 2*Cp2);\n      K.xy() = _cnm(n,0) * ( 2*Sp2);\n      K.xz() = _cnm(n,0) * ( 4*Cp1);\n      K.yy() = _cnm(n,0) * (-2*Cm0 - 2*Cp2);\n      K.yz() = _cnm(n,0) * ( 4*Sp1);\n      K.zz() = _cnm(n,0) * ( 4*Cm0);\n\n      // 1. order\n      if(n>0)\n      {\n        UInt m=1;\n        Double wm1 = std::sqrt(static_cast<Double>(n-m+1)*(n-m+2)*(n-m+3)*(n+m+1)) * std::sqrt(2.0);\n        Double wm0 = std::sqrt(static_cast<Double>(n-m+1)*(n-m+2)*(n+m+1)*(n+m+2));\n        Double wp1 = std::sqrt(static_cast<Double>(n-m+1)*(n+m+1)*(n+m+2)*(n+m+3));\n        Double wp2 = std::sqrt(static_cast<Double>(n+m+1)*(n+m+2)*(n+m+3)*(n+m+4));\n\n        Double Cm1 = wm1*Cnm(n+2,m-1);  Double Sm1 = wm1*Snm(n+2,m-1);\n        Double Cm0 = wm0*Cnm(n+2,m  );  Double Sm0 = wm0*Snm(n+2,m  );\n        Double Cp1 = wp1*Cnm(n+2,m+1);  Double Sp1 = wp1*Snm(n+2,m+1);\n        Double Cp2 = wp2*Cnm(n+2,m+2);  Double Sp2 = wp2*Snm(n+2,m+2);\n\n        K.xx() += _cnm(n,m) * (- 3*Cm0 + Cp2)  + _snm(n,m) * (- Sm0 + Sp2);\n        K.xy() += _cnm(n,m) * (-   Sm0 + Sp2)  + _snm(n,m) * (- Cm0 - Cp2);\n        K.xz() += _cnm(n,m) * (-2*Cm1 + 2*Cp1) + _snm(n,m) * (-2*Sm1 + 2*Sp1);\n        K.yy() += _cnm(n,m) * (-   Cm0 - Cp2)  + _snm(n,m) * (- 3*Sm0 - Sp2);\n        K.yz() += _cnm(n,m) * (2*Sp1)          + _snm(n,m) * (-2*Cm1 - 2*Cp1);\n        K.zz() += _cnm(n,m) * (4*Cm0)          + _snm(n,m) * (4*Sm0);\n      } // end 1. order\n\n      // all other orders\n      for(UInt m=2; m<=n; m++)\n      {\n        Double wm2 = std::sqrt(static_cast<Double>(n-m+1)*(n-m+2)*(n-m+3)*(n-m+4)) * ((m==2) ? std::sqrt(2.0) : 1.0);\n        Double wm1 = std::sqrt(static_cast<Double>(n-m+1)*(n-m+2)*(n-m+3)*(n+m+1));\n        Double wm0 = std::sqrt(static_cast<Double>(n-m+1)*(n-m+2)*(n+m+1)*(n+m+2));\n        Double wp1 = std::sqrt(static_cast<Double>(n-m+1)*(n+m+1)*(n+m+2)*(n+m+3));\n        Double wp2 = std::sqrt(static_cast<Double>(n+m+1)*(n+m+2)*(n+m+3)*(n+m+4));\n\n        Double Cm2 = wm2*Cnm(n+2,m-2);  Double Sm2 = wm2*Snm(n+2,m-2);\n        Double Cm1 = wm1*Cnm(n+2,m-1);  Double Sm1 = wm1*Snm(n+2,m-1);\n        Double Cm0 = wm0*Cnm(n+2,m  );  Double Sm0 = wm0*Snm(n+2,m  );\n        Double Cp1 = wp1*Cnm(n+2,m+1);  Double Sp1 = wp1*Snm(n+2,m+1);\n        Double Cp2 = wp2*Cnm(n+2,m+2);  Double Sp2 = wp2*Snm(n+2,m+2);\n\n        K.xx() += _cnm(n,m) * ( Cm2 - 2*Cm0 + Cp2) + _snm(n,m) * ( Sm2 - 2*Sm0 + Sp2);\n        K.xy() += _cnm(n,m) * (-Sm2         + Sp2) + _snm(n,m) * ( Cm2         - Cp2);\n        K.xz() += _cnm(n,m) * (-2*Cm1 + 2*Cp1)     + _snm(n,m) * (-2*Sm1 + 2*Sp1);\n        K.yy() += _cnm(n,m) * (-Cm2 - 2*Cm0 - Cp2) + _snm(n,m) * (-Sm2 - 2*Sm0 - Sp2);\n        K.yz() += _cnm(n,m) * ( 2*Sm1 + 2*Sp1)     + _snm(n,m) * (-2*Cm1 - 2*Cp1);\n        K.zz() += _cnm(n,m) * (4*Cm0)              + _snm(n,m) * (4*Sm0);\n      }  // for(m)\n\n      K_ges  += std::sqrt((2.*n+1.)/(2.*n+5.))*K;\n    } // for(n)\n\n    return GM()/(4*R()*R()*R()) * K_ges;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d SphericalHarmonics::deformation(const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, UInt maxDegree, UInt minDegree) const\n{\n  try\n  {\n    if(_interior)\n      throw(Exception(\"not implemented yet for inner space\"));\n\n    maxDegree = std::min(maxDegree, this->maxDegree());\n    Vector3d up = normalize(point);\n\n    Matrix Cnm, Snm;\n    CnmSnm(1/R()*point, maxDegree+1, Cnm, Snm);\n\n    Vector3d disp;\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      // 0. order\n      Double wm0 = std::sqrt((n+1.)*(n+1.));\n      Double wp1 = std::sqrt((n+1.)*(n+2.)) / std::sqrt(2.0);\n      Double Cm0 = wm0*Cnm(n+1,0);\n      Double Cp1 = wp1*Cnm(n+1,1);\n      Double Sp1 = wp1*Snm(n+1,1);\n\n      Double   Vn  =  _cnm(n,0) * Cnm(n,0);\n      Vector3d gradVn(_cnm(n,0) * (-2*Cp1),\n                      _cnm(n,0) * (-2*Sp1),\n                      _cnm(n,0) * (-2*Cm0));\n\n      // other orders\n      for(UInt m=1; m<=n; m++)\n      {\n        Double wm1 = std::sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? std::sqrt(2.0) : 1.0);\n        Double wm0 = std::sqrt((n-m+1.)*(n+m+1.));\n        Double wp1 = std::sqrt((n+m+1.)*(n+m+2.));\n        Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n        Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n        Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n        Vn         += _cnm(n,m) *  Cnm(n,m)    + _snm(n,m) * Snm(n,m);\n        gradVn.x() += _cnm(n,m) * ( Cm1 - Cp1) + _snm(n,m) * (Sm1 - Sp1);\n        gradVn.y() += _cnm(n,m) * (-Sm1 - Sp1) + _snm(n,m) * (Cm1 + Cp1);\n        gradVn.z() += _cnm(n,m) * (-2*Cm0)     + _snm(n,m) * (-2*Sm0);\n      } // for(m)\n\n      Vn     *= GM()/R();\n      gradVn *= GM()/(2*R()) * std::sqrt((2*n+1.)/(2*n+3.));\n\n      disp += (hn(n)/gravity*Vn) * up + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up);\n    } // for(n)\n\n    return disp;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVector SphericalHarmonics::x() const\n{\n  Vector x((_maxDegree+1)*(_maxDegree+1));\n  UInt idx = 0;\n  for(UInt n=0; n<=_maxDegree; n++)\n  {\n    x(idx++) = _cnm(n,0);\n    for(UInt m=1; m<=n; m++)\n    {\n      x(idx++) = _cnm(n,m);\n      x(idx++) = _snm(n,m);\n    }\n  }\n  return x;\n}\n\n/***********************************************/\n\nVector SphericalHarmonics::sigma2x() const\n{\n  Vector x((_maxDegree+1)*(_maxDegree+1));\n  if(_sigma2cnm.size() == 0)\n    return x;\n\n  UInt idx = 0;\n  for(UInt n=0; n<=_maxDegree; n++)\n  {\n    x(idx++) = _sigma2cnm(n,0);\n    for(UInt m=1; m<=n; m++)\n    {\n      x(idx++) = _sigma2cnm(n,m);\n      x(idx++) = _sigma2snm(n,m);\n    }\n  }\n  return x;\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/base/sphericalHarmonics.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonics.h\n*\n* @brief Spherical harmonics and functions of the gravity field.\n*\n* (4Pi normalized).\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICS__\n#define __GROOPS_SPHERICALHARMONICS__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/vector3d.h\"\n\n/***** CLASS ***********************************/\n\nclass Rotary3d;\nclass Tensor3d;\n\n/***** CLASS ***********************************/\n\n/** @brief Spherical harmonics and functions of the gravity field.\n* @ingroup base\n* (4Pi normalized).\n* Implements LinearSpace: SphericalHarmonics can be added/subtracted and be scaled with a Double. */\nclass SphericalHarmonics\n{\n  Double _GM, _R;\n  UInt   _maxDegree;\n  Matrix _cnm, _snm, _sigma2cnm, _sigma2snm;\n  Bool   _interior;\n\n  static Matrix factor1, factor2;\n\n  // factors needed for recursion formular\n  static void computeFactors(UInt degree);\n\npublic:\n  /// Default Constructor.\n  explicit SphericalHarmonics(Bool interior=FALSE);\n\n  /// Constructor from potential coefficients.\n  SphericalHarmonics(Double GM, Double R, const const_MatrixSlice &cnm, const const_MatrixSlice &snm, Bool interior=FALSE);\n\n  /// Constructor from potential coefficients and variances.\n  SphericalHarmonics(Double GM, Double R, const const_MatrixSlice &cnm, const const_MatrixSlice &snm, const const_MatrixSlice &sigma2cnm, const const_MatrixSlice &sigma2snm, Bool interior=FALSE);\n\n  /** @brief Solid spherical harmonics (Cnm und Snm).\n  * Basis functions (4Pi normalized).\n  * @f[ C_{nm}(\\lambda,\\vartheta,r) = \\frac{1}{r^{n+1}} \\cos(m\\lambda)P_n^m(\\cos\\vartheta) @f]\n  * @f[ S_{nm}(\\lambda,\\vartheta,r) = \\frac{1}{r^{n+1}} \\sin(m\\lambda)P_n^m(\\cos\\vartheta) @f]\n  * if interior:\n  * @f[ C_{nm}(\\lambda,\\vartheta,r) = r^n \\cos(m\\lambda)P_n^m(\\cos\\vartheta) @f]\n  * @f[ S_{nm}(\\lambda,\\vartheta,r) = r^n \\sin(m\\lambda)P_n^m(\\cos\\vartheta) @f] */\n  static void CnmSnm(const Vector3d &point, UInt maxDegree, Matrix &Cnm, Matrix &Snm, Bool interior=FALSE);\n\n  /** @brief Solid Legendre functions (Pnm).\n  * (4Pi normalized).\n  * @f[ P_{nm}(\\lambda,\\vartheta,r) = \\frac{1}{r^{n+1}} P_n^m(\\cos\\vartheta) @f]\n  * if interior\n  * @f[ P_{nm}(\\lambda,\\vartheta,r) = r^n P_n^m(\\cos\\vartheta) @f] */\n  static Matrix Pnm(Angle theta, Double r, UInt degree, Bool interior=FALSE);\n\n  /** @brief Interpret coefficients as inner/outer space harmonics. */\n  void setInterior(Bool interior=TRUE) {_interior = interior;}\n\n  /** @brief Interpret coefficients as inner space harmonics? */\n  Bool isInterior() const {return _interior;}\n\n  /** @brief Convert spherical harmonics.\n  * Based on given GM and R.\n  * @param maxDegree maximum degree.\n  * @param minDegree minimum degree.\n  * @param GM Specific gravitational constant, 0: the internal value is used.\n  * @param R  Reference radius, 0: the internal value is used. */\n  SphericalHarmonics get(UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  /** @brief Rotate spherical harmonics.\n  * Variances are not propagated. */\n  SphericalHarmonics rotate(const Rotary3d &rotary) const;\n\n  /** @brief Laplace spherical harmonics.\n  * @f[ Y_n(P) = \\frac{GM}{R} \\sum_{m=0}^n  c_{nm}C^r_{nm}(\\frac{1}{R}P) + s_{nm}S^r_{nm}(\\frac{1}{R}P) @f] */\n  Vector Yn(const Vector3d &point, UInt maxDegree=INFINITYDEGREE) const;\n\n  /** @brief Potential.\n  * @f[ V(P) = \\sum_{n=minDegree}^{maxDegree} Y_n(P) @f]\n  * @see SphericalHarmonics::Yn */\n  Double potential(const Vector3d &point, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) const;\n\n  /** @brief Radial derivative of the potential.\n  * @f[ \\frac{\\partial V(P)}{\\partial r} @f] */\n  Double radialGradient(const Vector3d &point, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) const;\n\n  /** @brief Gravitational acceleration.\n  * @f[ \\mathbf{g}(P) = \\nabla V(P) @f] */\n  Vector3d gravity(const Vector3d &point, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) const;\n\n  /** @brief Gravitational gradient (Tensor).\n  * @f[ T(P) = \\nabla \\nabla V(P) @f] */\n  Tensor3d gravityGradient(const Vector3d &point, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) const;\n\n  /** @brief Deformation due to loading.\n  * @param  point station position [m]\n  * @param  gravity local gravity at station [m/s**2]\n  * @param  hn vertical load love numbers\n  * @param  ln horizontal load love numbers\n  * @param  maxDegree maximum degree (inclusive)\n  * @param  minDegree minimum degree (inclusive)\n  * @return deformation in TRF [m] */\n  Vector3d deformation(const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) const;\n\n  /// Reference radius.\n  Double R() const {return _R;}\n\n  /// Gravitational constant * mass.\n  Double GM() const {return _GM;}\n\n  /// Maximum degree.\n  UInt maxDegree() const {return _maxDegree;}\n\n        Matrix &cnm()       {return _cnm;} //!< Potential coefficients.\n        Matrix &snm()       {return _snm;} //!< Potential coefficients.\n  const Matrix &cnm() const {return _cnm;} //!< Potential coefficients.\n  const Matrix &snm() const {return _snm;} //!< Potential coefficients.\n\n        Matrix &sigma2cnm()       {return _sigma2cnm;} //!< Variances of the potential coefficients.\n        Matrix &sigma2snm()       {return _sigma2snm;} //!< Variances of the potential coefficients.\n  const Matrix &sigma2cnm() const {return _sigma2cnm;} //!< Variances of the potential coefficients.\n  const Matrix &sigma2snm() const {return _sigma2snm;} //!< Variances of the potential coefficients.\n\n\n  /** @brief potential coefficients given as vector.\n  * the potential coefficients are given in a\n  * degree wise sequence with alternating sin, cos:\n  * ..., c20,c21,s21,c22,s22,...\n  * beginning with c00. */\n  Vector x() const;\n\n  /** @brief variances of potential coefficients given as vector.\n  * the variances of the potential coefficients are given in a\n  * degree wise sequence with alternating sin, cos:\n  * ..., c20,c21,s21,c22,s22,...\n  * beginning with c00. */\n  Vector sigma2x() const;\n\n  // linearSpace Operations\n  SphericalHarmonics &operator+= (const SphericalHarmonics &harm);\n  SphericalHarmonics &operator-= (const SphericalHarmonics &harm);\n  SphericalHarmonics &operator*= (Double c);\n}; // end SphericalHarmonics\n\n/***********************************************/\n\ninline SphericalHarmonics operator- (const SphericalHarmonics &t)                  {return SphericalHarmonics(t)  *= -1;}\ninline SphericalHarmonics operator+ (const SphericalHarmonics &t1, const SphericalHarmonics &t2) {return SphericalHarmonics(t1) += t2;}\ninline SphericalHarmonics operator- (const SphericalHarmonics &t1, const SphericalHarmonics &t2) {return SphericalHarmonics(t1) -= t2;}\ninline SphericalHarmonics operator* (Double c, const SphericalHarmonics &t)        {return SphericalHarmonics(t)  *=c;}\ninline SphericalHarmonics operator* (const SphericalHarmonics &t, Double c)        {return SphericalHarmonics(t)  *=c;}\n\n/***********************************************/\n\n#endif /* __GROOPS_SPHERICALHARMONICS__ */\n\n\n\n"
  },
  {
    "path": "source/base/string.cpp",
    "content": "/***********************************************/\n/**\n* @file string.cpp\n*\n* @brief Miscellaneous string functions.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2019-09-04\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/string.h\"\n#include <regex>\n\n/***********************************************/\n\nstd::string String::upperCase(const std::string &str)\n{\n  std::string result = str;\n  std::transform(result.begin(), result.end(), result.begin(), [](auto c){return std::toupper(c);});\n  return result;\n}\n\n/***********************************************/\n\nstd::string String::lowerCase(const std::string &str)\n{\n  std::string result = str;\n  std::transform(result.begin(), result.end(), result.begin(), [](auto c){return std::tolower(c);});\n  return result;\n}\n\n/***********************************************/\n\nstd::string String::trim(const std::string &str)\n{\n  try\n  {\n    auto start = str.find_first_not_of(\" \\t\\r\");\n    if(start == std::string::npos)\n      return \"\";\n    auto end = str.find_last_not_of(\" \\t\\r\");\n    return str.substr(start, end-start+1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nstd::string String::trimLeft(const std::string &str)\n{\n  try\n  {\n    auto start = str.find_first_not_of(\" \\t\\r\");\n    if(start == std::string::npos)\n      return \"\";\n    return str.substr(start);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nstd::string String::trimRight(const std::string &str)\n{\n  try\n  {\n    auto end = str.find_last_not_of(\" \\t\\r\");\n    if(end == std::string::npos)\n      return \"\";\n    return str.substr(0, end+1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nDouble String::toDouble(const std::string &str)\n{\n  try\n  {\n    if(std::all_of(str.begin(), str.end(), ::isspace))\n      return 0.;\n\n    std::string str2 = str;\n    auto dpos = str.find_first_of(\"Dd\");\n    if(dpos != std::string::npos)\n      str2[dpos] = 'e';\n\n    return std::stod(str2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"cannot read double from string '\"+str+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nInt String::toInt(const std::string &str)\n{\n  try\n  {\n    if(std::all_of(str.begin(), str.end(), ::isspace))\n      return 0;\n\n    return std::stoi(str);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"cannot read integer from string '\"+str+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nBool String::contains(const std::string &str, const std::string &test)\n{\n  return str.size() && (str.find(test) != std::string::npos);\n}\n\n/***********************************************/\n\nBool String::startsWith(const std::string &str, const std::string &test)\n{\n  return (str.rfind(test, 0) == 0);\n}\n\n/***********************************************/\n\nBool String::endsWith(const std::string &str, const std::string &test)\n{\n  return (str.size() >= test.size()) && (str.compare(str.size()-test.size(), test.size(), test) == 0);\n}\n\n/***********************************************/\n\nstd::vector<std::string> String::split(const std::string &str, Char seperator)\n{\n  try\n  {\n    std::vector<std::string> parts;\n    UInt pos1 = 0;\n    UInt pos2 = 0;\n    for(;;)\n    {\n      pos2 = str.find(seperator, pos2);\n      parts.push_back(str.substr(pos1, pos2-pos1));\n      if(pos2 == std::string::npos)\n        break;\n      pos1 = ++pos2;\n    }\n    return parts;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<std::string> String::split(const std::string &str, const std::string &seperators)\n{\n  try\n  {\n    std::vector<std::string> parts;\n    UInt pos1 = 0;\n    UInt pos2 = 0;\n    for(;;)\n    {\n      pos2 = str.find_first_of(seperators, pos2);\n      parts.push_back(str.substr(pos1, pos2-pos1));\n      if(pos2 == std::string::npos)\n        break;\n      pos1 = ++pos2;\n    }\n    return parts;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string String::replaceAll(const std::string &str, const std::string &search, const std::string &substitute)\n{\n  std::string result = str;\n  UInt pos = 0;\n  for(;;)\n  {\n    pos = result.find(search, pos);\n    if(pos == std::string::npos)\n        break;\n    result.replace(pos, search.size(), substitute);\n    pos += substitute.size();\n  }\n  return result;\n}\n\n/***********************************************/\n\nstd::string String::replaceAll(const std::string &str, const std::vector<std::pair<std::string, std::string>> &substitutes)\n{\n  std::string result = str;\n  for(const auto &substitute : substitutes)\n  {\n    auto pos = result.find(substitute.first);\n    while(pos != std::string::npos)\n    {\n      result.replace(pos, substitute.first.size(), substitute.second);\n      pos = result.find(substitute.first, pos + substitute.second.size());\n    }\n  }\n  return result;\n}\n\n/***********************************************/\n\nstd::regex String::wildcard2regex(const std::string &pattern)\n{\n  try\n  {\n    // escape ., +, \\*, \\? in regex pattern and\n    // replace valid wildcards *, ? with regex equivalents .*, .\n    std::string regexPattern = pattern;\n    regexPattern = replaceAll(regexPattern, {{\"\\\\*\", \"<backslash_star>\"}, {\"\\\\?\", \"<backslash_question_mark>\"}});  // temp replacement\n    regexPattern = replaceAll(regexPattern, {{\"\\\\\", \"\\\\\\\\\"}, {\"^\", \"\\\\^\"}, {\".\", \"\\\\.\"}, {\"$\", \"\\\\$\"}, {\"|\", \"\\\\|\"}, {\"(\", \"\\\\(\"},\n                                             {\")\", \"\\\\)\"},   {\"[\", \"\\\\[\"}, {\"]\", \"\\\\]\"}, {\"+\", \"\\\\+\"}, {\"/\", \"\\\\/\"}});\n    regexPattern = replaceAll(regexPattern, {{\"*\", \".*\"}, {\"?\", \".\"}});\n    regexPattern = replaceAll(regexPattern, {{\"<backslash_star>\", \"\\\\*\"}, {\"<backslash_question_mark>\", \"\\\\?\"}}); // undo temp replacement\n    return std::regex(regexPattern);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/string.h",
    "content": "/***********************************************/\n/**\n* @file string.h\n*\n* @brief Miscellaneous string functions.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2019-09-04\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_STRING__\n#define __GROOPS_STRING__\n\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include <regex>\n\n/***** CLASS ***********************************/\n\n/**\n* @brief Miscellaneous string functions.\n* @ingroup base */\nnamespace String\n{\n  /** @brief The @p str is converted to upper case. */\n  std::string upperCase(const std::string &str);\n\n  /** @brief The @p str is converted to lower case. */\n  std::string lowerCase(const std::string &str);\n\n  /** @brief Remove all leading and trailing spaces from @p str. */\n  std::string trim(const std::string &str);\n\n  /** @brief Remove all trailing spaces from @p str. */\n  std::string trimRight(const std::string &str);\n\n  /** @brief Remove all leading spaces from @p str. */\n  std::string trimLeft(const std::string &str);\n\n  /** @brief Convert to Double. Returns 0 if substring is all white spaces. */\n  Double toDouble(const std::string &str);\n\n  /** @brief Convert to Int. Returns 0 if substring is all white spaces. */\n  Int toInt(const std::string &str);\n\n  /** @brief test whether the @a str contains @p test. */\n  Bool contains(const std::string &str, const std::string &test);\n\n  /** @brief test whether the @a str starts with @p test. */\n  Bool startsWith(const std::string &str, const std::string &test);\n\n  /** @brief test whether the @a str ends with @p test. */\n  Bool endsWith(const std::string &str, const std::string &test);\n\n  /** @brief Replace all occurrences of @p search in @p str with the @p substitute string. */\n  std::string replaceAll(const std::string &str, const std::string &search, const std::string &substitute);\n\n  /** @brief Replace all occurrences of @p substitutes.first with the @p substitutes.second string. */\n  std::string replaceAll(const std::string &str, const std::vector<std::pair<std::string, std::string>> &substitutes);\n\n  /** @brief Returns a splitted string separated by @p seperator. */\n  std::vector<std::string> split(const std::string &str, Char seperator);\n\n  /** @brief Returns a splitted string separated by any character of @p seperators. */\n  std::vector<std::string> split(const std::string &str, const std::string &seperators);\n\n  /** @brief Convert a simple wildcard pattern into an equivalent regex expression.\n  * Wildcards *, ? can be escaped \\*, \\?. */\n  std::regex wildcard2regex(const std::string &pattern);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/base/tensor3d.h",
    "content": "/***********************************************/\n/**\n* @file tensor3d.h\n*\n* @brief tensor in 3d space.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-01-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TENSOR3D__\n#define __GROOPS_TENSOR3D__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/** @addtogroup vector3dGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Tensor in 3d space.\n* This is the result of a dyadic product of two @a Vector3d.\n* It is a symmetric matrix in cartesian coordinates.\n* For representation of e.g. gravity gradients or covariances of positions.\n* Can be rotated with @a Rotary3d.\n* Can be added, subtracted and scaled with a Double. */\nclass Tensor3d\n{\n    std::array<Double,6> field;  // xx,yy,zz,xy,xz,yz\n\npublic:\n  Tensor3d() : field{0.,0.,0.,0.,0.,0.} {} //!< Default constructor (zero matrix).\n\n  Tensor3d(const_MatrixSliceRef x); //!< Default constructor from symmetric 3x3 matrix\n\n  /** @brief Read/write cartesian coordinates.\n  * Read/write cartesian coordinates in the form:\n  * @code\n  *  Tensor3d t;\n  *  t.xx() = 0.5;\n  *  Double xx = t.xx();\n  * @endcode */\n  Double xx() const {return field[0];}\n  Double yy() const {return field[1];}  //!< @copydoc xx\n  Double zz() const {return field[2];}  //!< @copydoc xx\n  Double xy() const {return field[3];}  //!< @copydoc xx\n  Double xz() const {return field[4];}  //!< @copydoc xx\n  Double yz() const {return field[5];}  //!< @copydoc xx\n\n  Double &xx() {return field[0];} //!< @copydoc xx\n  Double &yy() {return field[1];} //!< @copydoc xx\n  Double &zz() {return field[2];} //!< @copydoc xx\n  Double &xy() {return field[3];} //!< @copydoc xx\n  Double &xz() {return field[4];} //!< @copydoc xx\n  Double &yz() {return field[5];} //!< @copydoc xx\n\n  /// Cast to matrix.\n  Matrix matrix() const;\n\n  Tensor3d &operator+= (Tensor3d const &b);\n  Tensor3d &operator-= (Tensor3d const &b);\n  Tensor3d &operator*= (Double  c);\n};\n\n/***********************************************/\n\ninline Tensor3d operator- (const Tensor3d &t)                      {return Tensor3d(t)  *= -1;}\ninline Tensor3d operator+ (const Tensor3d &t1, const Tensor3d &t2) {return Tensor3d(t1) += t2;}\ninline Tensor3d operator- (const Tensor3d &t1, const Tensor3d &t2) {return Tensor3d(t1) -= t2;}\ninline Tensor3d operator* (Double c, const Tensor3d &t)            {return Tensor3d(t)  *= c;}\ninline Tensor3d operator* (const Tensor3d &t, Double c)            {return Tensor3d(t)  *= c;}\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ninline Tensor3d &Tensor3d::operator+= (Tensor3d const &b)  {for(UInt i=0; i<6; i++) field[i] += b.field[i]; return *this;}\ninline Tensor3d &Tensor3d::operator-= (Tensor3d const &b)  {for(UInt i=0; i<6; i++) field[i] -= b.field[i]; return *this;}\ninline Tensor3d &Tensor3d::operator*= (Double  c)          {for(UInt i=0; i<6; i++) field[i] *= c;          return *this;}\n\n/***********************************************/\n\ninline Tensor3d::Tensor3d(const_MatrixSliceRef T)\n{\n  try\n  {\n    if((T.getType()!=Matrix::SYMMETRIC) || (T.rows()!=3) || !T.isUpper())\n      throw(Exception(\"Matrix T(\"s+T.rows()%\"%i x \"s+T.columns()%\"%i) must be 3x3 upper SYMMETRIC\"s));\n    field[0] = T(0,0);\n    field[1] = T(1,1);\n    field[2] = T(2,2);\n    field[3] = T(0,1);\n    field[4] = T(0,2);\n    field[5] = T(1,2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix Tensor3d::matrix() const\n{\n  Matrix T(3, Matrix::SYMMETRIC);\n  T(0,0) = field[0];\n  T(1,1) = field[1];\n  T(2,2) = field[2];\n  T(0,1) = field[3];\n  T(0,2) = field[4];\n  T(1,2) = field[5];\n  fillSymmetric(T);\n  return T;\n}\n\n/*************************************************/\n\n#endif /* __GROOPS_TENSOR3D__ */\n\n\n"
  },
  {
    "path": "source/base/tideGeneratingPotential.h",
    "content": "/***********************************************/\n/**\n* @file tideGeneratingPotential.h\n*\n* @brief Tide generating potential.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-01-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDEGENERATINGPOTENTIAL__\n#define __GROOPS_TIDEGENERATINGPOTENTIAL__\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n#include \"base/matrix.h\"\n#include \"base/doodson.h\"\n\n/***** CLASS ***********************************/\n\n/**\n* @brief Single constituent of the tide generatin potential.\n* @ingroup base\n* The potential can be computed with\n* @f[ V_{tide}(\\lambda,\\vartheta,r) = \\left(\\frac{r}{R}\\right)^2 ((c\\cos(\\theta_f)+s\\sin(\\theta_f))C_{2m} + (s\\cos(\\theta_f)-c\\sin(\\theta_f))S_{2m}) @f]\n* R is @a DEFAULT_R, m is @a d[0] of the Doodson number (long periodic, diurnal, semidiurnal).\n* c and s with unit m^2/s^2.\n* @see TideGeneratingPotential\n* @relates TideGeneratingPotential */\nclass TideGeneratingConstituent : public Doodson\n{\npublic:\n  UInt   degree; //!< spherical harmonics degree.\n  Double c, s;   //!< potential [m^2/s^2].\n\n  /// Default Constructor.\n  TideGeneratingConstituent() : degree(0), c(0), s(0) {}\n\n  /// Constructor.\n  TideGeneratingConstituent(const Doodson &doodson, UInt degree, Double c, Double s) : Doodson(doodson), degree(degree), c(c), s(s) {}\n\n  /// Amplitude [m^2/s^2].\n  Double amplitude() const {return std::sqrt(c*c+s*s);}\n\n  /// Admitance factor [m^2/s^2].\n  Double admit() const {return c+s;}\n\n  /** @brief Doodson-Wartburg phase correction.\n  * Possible values: 0, PI, +-PI/2.\n  * see IERS conventions 2003, table 6.4. */\n  Double xi() const;\n\n  /** @brief Implementation of Comparable (comparison of frequency). */\n  Bool operator== (const TideGeneratingConstituent &x) const {return (d == x.d) && (degree == x.degree);}\n  /** @brief Implementation of Comparable (comparison of frequency). */\n  Bool operator!= (const TideGeneratingConstituent &x) const {return (d != x.d) || (degree != x.degree);}\n  /** @brief Implementation of Comparable (comparison of frequency). */\n  Bool operator<  (const TideGeneratingConstituent &x) const {return (d == x.d) ? (degree < x.degree) : (frequency() < x.frequency());}\n};\n\n/***** CLASS ***********************************/\n\n/**\n @brief Tide generating potential of sun and moon.\n* @ingroup base\n*/\nclass TideGeneratingPotential : public std::vector<TideGeneratingConstituent>\n{\npublic:\n  /** @brief Doodson-Wartburg phase correction.\n  * Possible values: 0, PI, +-PI/2.\n  * see IERS conventions 2003, table 6.4. */\n  Double xi(const Doodson &doodson) const;\n};\n\n/***********************************************/\n\ninline Double TideGeneratingConstituent::xi() const\n{\n  try\n  {\n    Double phase = std::atan2(s, c);\n    if(degree == 2)\n    {\n      if(d[0] == 0) return std::fmod(phase + PI, 2*PI); // c\n      if(d[0] == 1) return std::fmod(phase + PI, 2*PI); // s\n      if(d[0] == 2) return phase;                       // c\n    }\n    if(degree == 3)\n    {\n      if(d[0] == 0) return phase;                        // s\n      if(d[0] == 1) return std::fmod(phase + PI, 2*PI);  // c\n      if(d[0] == 2) return std::fmod(phase + PI, 2*PI);  // s\n      if(d[0] == 3) return phase;                        // c\n    }\n    throw(Exception(\"xi not (yet) defined for \"+code()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double TideGeneratingPotential::xi(const Doodson &doodson) const\n{\n  try\n  {\n    if(doodson == Doodson(std::vector<Int>{0, 0, 1, 0, 0, 0})) // special case: SA\n      return 0;\n    if(doodson == Doodson(std::vector<Int>{1, 1,-1, 0, 0, 0})) // special case: S1\n      return PI;\n    if(doodson == Doodson(std::vector<Int>{3, 3,-4, 0, 0, 0})) // non-linear T3\n      return 0;\n    if(doodson == Doodson(std::vector<Int>{3, 3,-2, 0, 0, 0})) // non-linear R3\n      return 0;\n    if(doodson.d[0] > 3)  // non-linear tides\n      return 0;\n    for(UInt i=0; i<size(); i++)\n      if(doodson == at(i))\n        return at(i).xi();\n    throw(Exception(\"constituent \"+doodson.code()+\" not in list\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/base/time.cpp",
    "content": "/***********************************************/\n/**\n* @file time.cpp\n*\n* @brief time representation.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @author Sebastian Strasser\n* @date 2002-11-12\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n\n/***********************************************/\n\nTime date2time(UInt year, UInt month, UInt day, UInt hour, UInt minute, Double second)\n{\n  if(second<0)\n    throw(Exception(\"In date2time:\\nNegative seconds\"));\n\n  if((month<1)||(month>13))\n    throw(Exception(\"In date2time:\\nmonth must between 1<=month<=12\"));\n\n  Int Y = static_cast<Int>(year);\n  Int M = static_cast<Int>(month);\n  Int D = static_cast<Int>(day);\n\n  Int _mjd = (1461 * (Y + 4800 + (M - 14)/12))/4 +(367 * (M - 2 - 12 * ((M - 14)/12)))/12 - (3 * ((Y + 4900 + (M - 14)/12)/100))/4 + D - 32075-2400001;\n  return Time(_mjd, ((second/60.+minute)/60.+hour)/24.);\n}\n\n/***********************************************/\n\n// I copied this code from internet, but I cannot remember where it was.\nvoid Time::date(UInt &year, UInt &month, UInt &day, UInt &hour, UInt &minute, Double &second) const\n{\n  // jd0 is the Julian number for noon on the day in question\n  // for example   mjd      jd     jd0   === mjd0\n  //               3.0  ...3.5  ...4.0   === 3.5\n  //               3.3  ...3.8  ...4.0   === 3.5\n  //               3.7  ...4.2  ...4.0   === 3.5\n  //               3.9  ...4.4  ...4.0   === 3.5\n  //               4.0  ...4.5  ...5.0   === 4.5\n  long int jd0 = _mjdInt + 2400001;\n\n  // next we convert to Julian dates to make the rest of the maths easier.\n  // JD1867217 = 1 Mar 400, so $b is the number of complete Gregorian\n  // centuries since then.  The constant 36524.25 is the number of days\n  // in a Gregorian century.  The 0.25 on the other constant ensures that\n  // $b correctly rounds down on the last day of the 400 year cycle.\n  // For example $b == 15.9999... on 2000 Feb 29 not 16.00000.\n  Int b = static_cast<Int>(floor((jd0-1867216.25)/36524.25));\n\n  // b-int(b/4) is the number of Julian leap days that are not counted in\n  // the Gregorian calendar, and 1402 is the number of days from 1 Jan 4713BC\n  // back to 1 Mar 4716BC.  $c represents the date in the Julian calendar\n  // corrected back to the start of a leap year cycle.\n  Int c = jd0+(b-b/4)+1402;\n\n  // d is the whole number of Julian years from 1 Mar 4716BC to the date\n  // we are trying to find.\n  Int d = static_cast<Int>(floor((c+0.9)/365.25));\n\n  // e is the number of days from 1 Mar 4716BC to 1 Mar this year\n  // using the Julian calendar\n  Int e = 365*d+d/4;\n\n  // c-e is now the remaining days in this year from 1 Mar to our date\n  // and we need to work out the magic number f such that f-1 == month\n  Int f = static_cast<Int>(floor((c-e+123)/30.6001));\n\n  // int(f*30.6001) is the day of the start of the month\n  // so the day of the month is the difference between that and c-e+123\n  day = c-e+123-static_cast<Int>(floor(30.6001*f));\n\n  // month is now f-1, except that Jan and Feb are f-13\n  // ie f 4 5 6 7 8 9 10 11 12 13 14 15\n  //    m 3 4 5 6 7 8  9 10 11 12  1  2\n  month = (f-2)%12+1;\n\n  // year is d - 4716 (adjusted for Jan and Feb again)\n  year = d - 4716 + (month<3);\n\n  hour    = static_cast<UInt>(floor(_mjdMod*24.));\n  minute  = static_cast<UInt>(floor((_mjdMod*24-hour)*60));\n  second  = ((_mjdMod*24-hour)*60- minute)*60;\n}\n\n/***********************************************/\n\nDouble Time::decimalYear() const\n{\n  UInt   year, month, day;\n  UInt   hour, minute;\n  Double second;\n  date(year, month, day, hour, minute, second);\n\n  Time time1 = date2time(year,  1,1);\n  Time time2 = date2time(year+1,1,1);\n\n  return year + (*this-time1).mjd()/(time2-time1).mjd();\n}\n\n/***********************************************/\n\nUInt Time::dayOfYear() const\n{\n  UInt   year, month, day;\n  UInt   hour, minute;\n  Double second;\n  date(year, month, day, hour, minute, second);\n\n  Time time1 = date2time(year, 1,1);\n  return static_cast<UInt>(std::floor((*this-time1).mjd()+1));\n}\n\n/***********************************************/\n\nBool Time::operator< (const Time &time) const\n{\n  return (_mjdInt-time._mjdInt) + (_mjdMod-time._mjdMod) < -TIME_EPSILON/86400;\n}\n\n/***********************************************/\n\nTime &Time::operator+= (const Time &time)\n{\n  _mjdInt += time._mjdInt;\n  _mjdMod += time._mjdMod;\n  Int mjd = static_cast<Int>(std::floor(_mjdMod));\n  _mjdInt += mjd;\n  _mjdMod -= mjd;\n  return *this;\n}\n\n/***********************************************/\n\nTime &Time::operator-= (const Time &time)\n{\n  _mjdInt -= time._mjdInt;\n  _mjdMod -= time._mjdMod;\n  Int mjd = static_cast<Int>(std::floor(_mjdMod));\n  _mjdInt += mjd;\n  _mjdMod -= mjd;\n  return *this;\n}\n\n/***********************************************/\n\nTime &Time::operator*= (Double c)\n{\n  Double _tmpInt = std::floor(c*_mjdInt);\n  Double _tmpMod = c*_mjdInt - _tmpInt;\n  _tmpMod += c*_mjdMod;\n\n  _mjdMod = _tmpMod - std::floor(_tmpMod);\n  _mjdInt = static_cast<Int>(_tmpInt) + static_cast<Int>(std::floor(_tmpMod));\n  return *this;\n}\n\n/***********************************************/\n/***********************************************/\n\nTime medianSampling(const std::vector<Time> &times)\n{\n  if(times.size()<2)\n    return Time();\n  if(times.size() == 2)\n    return times.back()-times.front();\n\n  std::vector<Time> diff(times.size()); // first element is times[0], so start from 1\n  std::adjacent_difference(times.begin(), times.end(), diff.begin());\n\n  std::partial_sort(diff.begin()+1, diff.begin()+1+diff.size()/2+1, diff.end()); // first element is times[0], so start from 1\n\n  return (diff.size()-1) % 2 == 0 ? diff[diff.size()/2]*0.5 + diff[diff.size()/2+1]*0.5 : diff[diff.size()/2+1];\n}\n\n/***********************************************/\n\nBool isRegular(const std::vector<Time> &times, Double margin)\n{\n  if(times.size()<=2)\n    return TRUE;\n  std::vector<Time> diff(times.size());\n  std::adjacent_difference(times.begin(), times.end(), diff.begin());\n  auto minmax = std::minmax_element(diff.begin()+1, diff.end());\n  return ((*minmax.second - *minmax.first).seconds() < margin);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/time.h",
    "content": "/***********************************************/\n/**\n* @file time.h\n*\n* @brief time representation.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @author Sebastian Strasser\n* @date 2002-11-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIME__\n#define __GROOPS_TIME__\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n\n/**\n* @defgroup timeGroup Time\n* @brief Classes and functions for accurate time representation.\n* @ingroup base */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief time representation.\n* Precise representation: integer days and additional double for fraction of a day,\n* Implemented Comparable and LinearSpace. */\nclass Time\n{\n  Int    _mjdInt;  // integer days\n  Double _mjdMod;  // fraction of a day\n\npublic:\n  /// Default Constructor.\n  Time() : _mjdInt(0), _mjdMod(0.0) {}\n\n  /// Constructor.\n  explicit Time(Int mjdInt, Double mjdMod);\n\n  /// Time as MJD (modified julian date)\n  Double mjd() const;\n\n  /// Time in seconds.\n  Double seconds() const;\n\n  /// Decimal year e.g. 2008.135\n  Double decimalYear() const;\n\n  /// Day of year (DOY)\n  UInt dayOfYear() const;\n\n  /** @brief The Date of Time.\n  * @param[out] year year\n  * @param[out] month month\n  * @param[out] day day\n  * @param[out] hour hour\n  * @param[out] minute minutes\n  * @param[out] second seconds with frations */\n  void date(UInt &year, UInt &month, UInt &day, UInt &hour, UInt &minute, Double &second) const;\n\n  /// Date as string (yyyy-mm-dd).\n  inline std::string dateStr() const {return *this%\"%y-%m-%d\"s;}\n\n  /** @brief Date and time as string (yyyy-mm-dd_hh-mm-ss).\n  * Useful for file names */\n  inline std::string dateTimeStr() const {return *this%\"%y-%m-%d_%H-%M-%S\"s;}\n\n  /// Time of day as string (hh-mm-ss)\n  inline std::string str() const {return *this%\"%H-%M-%S\"s;}\n\n  /** @brief Started day in MJD without fractional.\n  * Example: gives 2 for mjd=2.25 and -3 for mjd=-2.25. */\n  Int mjdInt() const;\n\n  /** @brief Fractional part of started day.\n  * Example: gives 0.25 for mjd=2.25 and 0.75 for mjd=-2.25. */\n  Double mjdMod() const;\n\n  /** @brief Returns TRUE if calling instance is within given interval [@p intervalStart, @p intervalEnd). */\n  Bool isInInterval(const Time &intervalStart, const Time &intervalEnd) const {return (intervalStart<=*this) && (*this<intervalEnd);}\n\n  Time &operator-= (const Time &time);\n  Time &operator+= (const Time &time);\n  Time &operator*= (Double c);\n  Time  operator+  () const {return *this;}\n  Time  operator-  () const {return Time(-_mjdInt, -_mjdMod);}\n\n  /** @brief Comparisons.\n  * Times considered to be equal within @a TIME_EPSILON seconds margin. */\n  Bool operator<  (const Time &time) const;\n  Bool operator== (const Time &time) const {return !(*this<time) && !(time<*this);}\n  Bool operator!= (const Time &time) const {return !(*this==time);}\n  Bool operator>  (const Time &time) const {return !(*this<time) && !(*this==time);}\n  Bool operator<= (const Time &time) const {return !(*this>time);}\n  Bool operator>= (const Time &time) const {return !(*this<time);}\n};\n\n/***** FUNCTIONS *******************************/\n\n/// MJD (modified julian date) to Time representation.\ninline Time mjd2time(LongDouble mjd);\n\n/// Seconds to Time representation.\ninline Time seconds2time(LongDouble seconds);\n\n/// Date to Time representation.\nTime date2time(UInt year, UInt month, UInt day, UInt hour=0, UInt minute=0, Double second=0.0);\n\n/** @brief Conversion from date to Time representation.\n* @see Time::date */\ninline void time2date(const Time &time, UInt &year, UInt &month, UInt &day, UInt &hour, UInt &minute, Double &second);\n\n/// @brief Median sampling of a time series.\nTime medianSampling(const std::vector<Time> &times);\n\n/** @brief return true if all points are equally spaced.\n* @param times series to be tested\n* @param margin threshold for equality [seconds] */\nBool isRegular(const std::vector<Time> &times, Double margin=1e-5);\n\n/// GPS time to TT time.\ninline Time timeGPS2TT(const Time &timeGPS);\n\n/// GPS time to julian centuries (JC).\ninline Double timeGPS2JC(const Time &timeGPS);\n\n/// TT to GPS-Time.\ninline Time timeTT2GPS(const Time &timeTT);\n\n/** @brief GPS time to Universal Time Coordinated (UTC).\n* Need leap seconds from constants.cpp */\ninline Time timeGPS2UTC(const Time &timeGPS);\n\n/** @brief Universal Time Coordinated (UTC) to GPS time.\n* Need leap seconds from constants.cpp */\ninline Time timeUTC2GPS(const Time &timeUTC);\n\ninline Time operator+ (const Time &t1, const Time &t2) {return Time(t1) += t2;}\ninline Time operator- (const Time &t1, const Time &t2) {return Time(t1) -= t2;}\ninline Time operator* (Double c, const Time &t)        {return Time(t)  *=c;}\ninline Time operator* (const Time &t, Double c)        {return Time(t)  *=c;}\n\n/// @} group time\n\n/***********************************************/\n/***** INLINES   *******************************/\n/***********************************************/\n\ninline Time::Time(Int mjdInt, Double mjdMod) : _mjdInt(mjdInt + static_cast<Int>(floor(mjdMod))), _mjdMod(mjdMod - static_cast<Int>(floor(mjdMod)))\n{\n}\n\ninline Double Time::mjd()     const {return _mjdInt + _mjdMod;}\ninline Int    Time::mjdInt()  const {return _mjdInt;}\ninline Double Time::mjdMod()  const {return _mjdMod;}\ninline Double Time::seconds() const {return mjd()*(24*60*60);}\n\ninline Time mjd2time(LongDouble mjd)\n{\n  Int _mjdInt = static_cast<Int>(std::floor(mjd));\n  return Time(_mjdInt, static_cast<Double>(mjd-_mjdInt));\n}\n\ninline Time seconds2time(LongDouble seconds)\n{\n  return mjd2time(seconds/(24*60*60));\n}\n\ninline void time2date(const Time &time, UInt &year, UInt &month, UInt &day, UInt &hour, UInt &minute, Double &second)\n{\n  time.date(year,month,day,hour,minute,second);\n}\n\ninline Time timeGPS2TT (const Time &timeGPS)\n{\n  return timeGPS + seconds2time(DELTA_TT_GPS);\n}\n\ninline Double timeGPS2JC (const Time &timeGPS)\n{\n  return (timeGPS2TT(timeGPS)-mjd2time(J2000)).mjd()/36525.;\n}\n\ninline Time timeTT2GPS (const Time &timeTT)\n{\n  return timeTT - seconds2time(DELTA_TT_GPS);\n}\n\ninline Time timeGPS2UTC(const Time &timeGPS)\n{\n  const Double mjd = timeGPS.mjd();\n  for(UInt i=0; i<DELTA_UTC_GPS.size(); i++)\n    if(mjd >= MJD_UTC_GPS.at(i)-DELTA_UTC_GPS.at(i)/86400.)\n      return timeGPS + seconds2time(DELTA_UTC_GPS.at(i));\n  throw(Exception(\"no leap seconds available at \"+timeGPS.dateTimeStr()));\n}\n\ninline Time timeUTC2GPS(const Time &timeUTC)\n{\n  const Double mjd = timeUTC.mjd();\n  for(UInt i=0; i<DELTA_UTC_GPS.size(); i++)\n    if(mjd >= MJD_UTC_GPS.at(i))\n      return timeUTC - seconds2time(DELTA_UTC_GPS.at(i));\n  throw(Exception(\"no leap seconds available at \"+timeUTC.dateTimeStr()));\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_TIME__ */\n"
  },
  {
    "path": "source/base/transform3d.cpp",
    "content": "/***********************************************/\n/**\n* @file transform3d.cpp\n*\n* @brief Orthogonal coordinate transformations in 3d space.\n* (rotations and reflections).\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-03-03\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/ellipsoid.h\"\n#include \"base/vector3d.h\"\n#include \"base/tensor3d.h\"\n#include \"base/rotary3d.h\"\n#include \"base/transform3d.h\"\n\n/***********************************************/\n\n/// Contructor from Rotary3d.\nTransform3d::Transform3d(const Rotary3d &rot) : field(rot.field) {}\n\n/***********************************************/\n\n// rotary from 3x3 matrix\nTransform3d::Transform3d(const_MatrixSliceRef A)\n{\n  try\n  {\n    field[0][0] = A(0,0);\n    field[0][1] = A(0,1);\n    field[0][2] = A(0,2);\n    field[1][0] = A(1,0);\n    field[1][1] = A(1,1);\n    field[1][2] = A(1,2);\n    field[2][0] = A(2,0);\n    field[2][1] = A(2,1);\n    field[2][2] = A(2,2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTransform3d::Transform3d(Vector3d x, Vector3d y)\n{\n  // Orthonormalize\n  x.normalize();\n  Vector3d z = normalize(crossProduct(x,y));\n  y = crossProduct(z,x);\n\n  field[0][0] = x.x(); field[0][1] = y.x(); field[0][2] = z.x();\n  field[1][0] = x.y(); field[1][1] = y.y(); field[1][2] = z.y();\n  field[2][0] = x.z(); field[2][1] = y.z(); field[2][2] = z.z();\n}\n\n/***********************************************/\n\nVector3d Transform3d::transform(const Vector3d &v) const\n{\n  Vector3d y;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      y.field[i] += field[i][k] * v.field[k];\n  return y;\n}\n\n/***********************************************/\n\nVector3d Transform3d::inverseTransform(const Vector3d &v) const\n{\n  Vector3d y;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      y.field[i] += field[k][i] * v.field[k];\n  return y;\n}\n\n/***********************************************/\n\nTensor3d Transform3d::transform(const Tensor3d &t) const\n{\n  auto rot = [&](UInt i, UInt k)\n  {\n    return  field[i][0]*field[k][0] * t.xx()\n         +  field[i][1]*field[k][1] * t.yy()\n         +  field[i][2]*field[k][2] * t.zz()\n         + (field[i][0]*field[k][1] + field[i][1]*field[k][0]) * t.xy()\n         + (field[i][0]*field[k][2] + field[i][2]*field[k][0]) * t.xz()\n         + (field[i][1]*field[k][2] + field[i][2]*field[k][1]) * t.yz();\n  };\n\n  Tensor3d t2;\n  t2.xx() = rot(0, 0);\n  t2.yy() = rot(1, 1);\n  t2.zz() = rot(2, 2);\n  t2.xy() = rot(0, 1);\n  t2.xz() = rot(0, 2);\n  t2.yz() = rot(1, 2);\n  return t2;\n}\n\n/***********************************************/\n\nTensor3d Transform3d::inverseTransform(const Tensor3d &t) const\n{\n  auto rot = [&](UInt i, UInt k)\n  {\n    return  field[0][i]*field[0][k] * t.xx()\n         +  field[1][i]*field[1][k] * t.yy()\n         +  field[2][i]*field[2][k] * t.zz()\n         + (field[0][i]*field[1][k] + field[1][i]*field[0][k]) * t.xy()\n         + (field[0][i]*field[2][k] + field[2][i]*field[0][k]) * t.xz()\n         + (field[1][i]*field[2][k] + field[2][i]*field[1][k]) * t.yz();\n  };\n\n  Tensor3d t2;\n  t2.xx() = rot(0, 0);\n  t2.yy() = rot(1, 1);\n  t2.zz() = rot(2, 2);\n  t2.xy() = rot(0, 1);\n  t2.xz() = rot(0, 2);\n  t2.yz() = rot(1, 2);\n  return t2;\n}\n\n/***********************************************/\n\nTransform3d &Transform3d::operator*= (const Transform3d &b)\n{\n  *this = *this * b;\n  return *this;\n}\n\n/***********************************************/\n\nTransform3d &Transform3d::operator*= (const Rotary3d &b)\n{\n  *this = *this * b;\n  return *this;\n}\n\n/***********************************************/\n\nTransform3d Transform3d::operator* (const Transform3d &b) const\n{\n  Transform3d y;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n    {\n      y.field[i][k] = 0.0;\n      for(UInt l=0; l<3; l++)\n        y.field[i][k] += field[i][l] * b.field[l][k];\n    }\n  return y;\n}\n\n/***********************************************/\n\nTransform3d Transform3d::operator* (const Rotary3d &b) const\n{\n  Transform3d y;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n    {\n      y.field[i][k] = 0.0;\n      for(UInt l=0; l<3; l++)\n        y.field[i][k] += field[i][l] * b.field[l][k];\n    }\n  return y;\n}\n\n/***********************************************/\n/***********************************************/\n\nTransform3d inverse(const Transform3d &b)\n{\n  Transform3d rot;\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      rot.field[i][k] = b.field[k][i];\n  return rot;\n}\n\n/***********************************************/\n\nTransform3d localNorthEastUp(const Vector3d &point)\n{\n  const Vector3d z = normalize(point);                            // up\n  const Vector3d y = normalize(crossProduct(Vector3d(0,0,1), z)); // east\n  const Vector3d x = normalize(crossProduct(z, y));               // north\n  Transform3d T;\n  T.field[0][0] = x.x(); T.field[0][1] = y.x(); T.field[0][2] = z.x();\n  T.field[1][0] = x.y(); T.field[1][1] = y.y(); T.field[1][2] = z.y();\n  T.field[2][0] = x.z(); T.field[2][1] = y.z(); T.field[2][2] = z.z();\n  return T;\n}\n\n/***********************************************/\n\nTransform3d localNorthEastUp(const Vector3d &point, const Ellipsoid &ellipsoid)\n{\n  Angle  L, B;\n  Double h;\n  ellipsoid(point, L, B, h);\n  return localNorthEastUp(polar(L, B, 1.));\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/base/transform3d.h",
    "content": "/***********************************************/\n/**\n* @file transform3d.h\n*\n* @brief Orthogonal coordinate transformations in 3d space.\n* (rotations and reflections).\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-03-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TRANSFORM3D__\n#define __GROOPS_TRANSFORM3D__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/** @addtogroup vector3dGroup */\n/// @{\n\nclass Angle;\nclass Vector3d;\nclass Tensor3d;\nclass Rotary3d;\nclass Ellipsoid;\n\n/***** CLASS ***********************************/\n\n/** @brief Coordinate transformations in 3d space.\n* (rotations and reflections). */\nclass Transform3d\n{\n  std::array<std::array<Double,3>,3> field;\n\npublic:\n  Transform3d() : field{{{1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}}} {} //!< Default constructor (Unitary matrix).\n\n  /// Contructor from std::array.\n  Transform3d(const std::array<std::array<Double,3>,3> &x) : field(x) {}\n\n  /// Contructor from Rotary3d.\n  Transform3d(const Rotary3d &rot);\n\n  /// Contructor from matrix (3x3).\n  explicit Transform3d(const_MatrixSliceRef A);\n\n  /** @brief Rotation of a local system.\n  * Rotational matrix from local system (defined by the given axis x,y,z)\n  * in the global system. The axis will be normalized and orthogonalized before.\n  * The z-axis is defined orthogonal to x and y.\n  * Zhe y-axis is defined orthogonal to the new z-axis and x. */\n  Transform3d(Vector3d x, Vector3d y);\n\n  /// Cast to Matrix.\n  Matrix matrix() const;\n\n  /** @brief Transformation of a vector.\n  * \\f[ y = T \\cdot v \\f]. */\n  Vector3d transform(const Vector3d &v) const;\n\n  /** @brief Inverse transformation of a vector.\n  * \\f[ y = T^T \\cdot v \\f]. */\n  Vector3d inverseTransform(const Vector3d &v) const;\n\n  /** @brief Transformation of  a tensor.\n  * Both sides of the dyadic product are rotated.\n  * \\f[ y = T \\cdot t \\cdot T^T \\f]. */\n  Tensor3d transform(const Tensor3d &t) const;\n\n  /** @brief Inverse transformation of a tensor.\n  * Both sides of the dyadic product are rotated.\n  * \\f[ y = T^T \\cdot t \\cdot T \\f]. */\n  Tensor3d inverseTransform(const Tensor3d &t) const;\n\n  Transform3d &operator*=(const Transform3d &b);\n  Transform3d &operator*=(const Rotary3d &b);\n  Transform3d  operator* (const Transform3d &b) const;\n  Transform3d  operator* (const Rotary3d &b) const;\n\n  friend class Rotary3d;\n  friend Transform3d inverse(const Transform3d &b);\n  friend Transform3d localNorthEastUp(const Vector3d &point);\n  friend Transform3d localNorthEastUp(const Vector3d &point, const Ellipsoid &ellipsoid);\n};\n\n/***********************************************/\n\n/** @brief flip x-axis. */\ninline Transform3d flipX() {return Transform3d(std::array<std::array<Double,3>,3>{{{-1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}}});}\n\n/** @brief flip y-axis. */\ninline Transform3d flipY() {return Transform3d(std::array<std::array<Double,3>,3>{{{1.,0.,0.}, {0.,-1.,0.}, {0.,0.,1.}}});}\n\n/** @brief flip z-axis. */\ninline Transform3d flipZ() {return Transform3d(std::array<std::array<Double,3>,3>{{{1.,0.,0.}, {0.,1.,0.}, {0.,0.,-1.}}});}\n\n/** @brief Transform3d of inverse rotation.\n* @ingroup vector3dGroup\n* Transposed matrix. */\nTransform3d inverse(const Transform3d &b);\n\n/** @brief Rotational matrix from local system (north, east, up) to the global system (coordinate system of point).\n* @ingroup vector3dGroup */\nTransform3d localNorthEastUp(const Vector3d &point);\n\n/** @brief Rotational matrix from local system (north, east, up) to the global system (coordinate system of point).\n* @ingroup vector3dGroup\n* Converts @p point to ellipsoidal coordinates beforehand. */\nTransform3d localNorthEastUp(const Vector3d &point, const Ellipsoid &ellipsoid);\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ninline Matrix Transform3d::matrix() const\n{\n  Matrix R(3, 3, Matrix::NOFILL);\n  for(UInt i=0; i<3; i++)\n    for(UInt k=0; k<3; k++)\n      R(i,k) = field[i][k];\n  return R;\n}\n\n/*************************************************/\n\n#endif /* __GROOPS_TRANSFORM3D__ */\n\n\n"
  },
  {
    "path": "source/base/vector3d.h",
    "content": "/***********************************************/\n/**\n* @file vector3d.h\n*\n* @brief Vector in 3d space.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_VECTOR3D__\n#define __GROOPS_VECTOR3D__\n\n#include \"base/importStd.h\"\n#include \"base/angle.h\"\n#include \"base/matrix.h\"\n\n/**\n* @defgroup vector3dGroup Vector3d\n* @brief Coordinates in 3d space.\n* @ingroup base */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Vector in 3d space.\n* For the representation of e.g. positions, velocities, gravity.\n* Can be rotated with @a Rotary3d.\n* Can added, subtracted and multiplied with a Double.\n* (Internally represented by cartesian coordinates). */\nclass Vector3d\n{\n  std::array<Double,3> field;\n\npublic:\n  Vector3d() : field{0.,0.,0.} {} //!< Default constructor (Zero vector).\n\n  Vector3d(Double x, Double y, Double z) : field{x,y,z} {} //!< Constructor from cartesian coordinates.\n  explicit Vector3d(const_MatrixSliceRef x);               //!< Constructor from 3x1 or 1x3 matrix slice\n\n  Double  x() const {return field[0];} //!< Cartesian coordinates: x component.\n  Double  y() const {return field[1];} //!< Cartesian coordinates: y component.\n  Double  z() const {return field[2];} //!< Cartesian coordinates: z component.\n  Double &x()       {return field[0];} //!< Cartesian coordinates: x component.\n  Double &y()       {return field[1];} //!< Cartesian coordinates: y component.\n  Double &z()       {return field[2];} //!< Cartesian coordinates: z component.\n\n  /** @brief Polar coordinates: longitude (-PI,PI].\n  * @f[ \\lambda = \\arctan2(y,x) @f] */\n  Angle lambda()  const;\n\n  /** @brief Polar coordinates: latitude [-PI,PI].\n  * @f[ \\varphi = \\arctan2(z,\\sqrt{x^2+y^2}) @f] */\n  Angle phi() const;\n\n  /** @brief Polar coordinates: zenit angle [-PI,PI].\n  * @f[ \\vartheta = \\pi/2 - \\varphi @f]\n  * @see Vector3d::phi */\n  Angle theta() const;\n\n  /** @brief Polar coordinates: radius.\n  * @f[ r = \\sqrt{x^2+y^2+z^2} @f] */\n  Double r() const;\n\n  /** @brief Quadratic sum.\n  * @f[ x^2+y^2+z^2 @f] */\n  Double quadsum() const;\n\n  /** @brief L2-Norm.\n  * @f[ \\sqrt{x^2+y^2+z^2} @f]*/\n  Double norm() const;\n\n  /** @brief Normalize the vector.\n  * @f[ \\frac{1}{\\sqrt{x^2+y^2+z^2}} \\cdot (x,y,z)^T @f]\n  * @return old length */\n  Double normalize();\n\n  /// Cast to Vector.\n  Vector vector() const;\n\n  Vector3d &operator+= (Vector3d const &b);\n  Vector3d &operator-= (Vector3d const &b);\n  Vector3d &operator*= (Double  c);\n  Vector3d &operator/= (Double  c);\n\n  friend class Rotary3d;\n  friend class Transform3d;\n  friend Double inner(const Vector3d &x, const Vector3d &y);\n  friend Vector3d polar(Angle lambda, Angle phi, Double r);\n  friend Vector3d crossProduct(const Vector3d &x, const Vector3d &y);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Inner Product.\n* @f[ c = x^Ty @f] */\ninline Double inner(const Vector3d &x, const Vector3d &y);\n\n/** @brief Vector3d from polar coordinates. */\ninline Vector3d polar(Angle lambda, Angle phi, Double r);\n\n/** @brief Cross product.\n* @f[ z = x \\times y @f] */\ninline Vector3d crossProduct(const Vector3d &x, const Vector3d &y);\n\n/** @brief Scale vector to unit length. */\ninline Vector3d normalize(const Vector3d &x);\n\ninline const Vector3d operator- (const Vector3d &t)                      {return Vector3d(t)  *= -1;}\ninline const Vector3d operator+ (const Vector3d &t1, const Vector3d &t2) {return Vector3d(t1) += t2;}\ninline const Vector3d operator- (const Vector3d &t1, const Vector3d &t2) {return Vector3d(t1) -= t2;}\ninline const Vector3d operator* (Double c, const Vector3d &t)            {return Vector3d(t)  *=c;}\ninline const Vector3d operator* (const Vector3d &t, Double c)            {return Vector3d(t)  *=c;}\ninline const Vector3d operator/ (const Vector3d &t, Double c)            {return Vector3d(t)  /=c;}\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ninline Vector3d::Vector3d(const_MatrixSliceRef x) {if(x.size()!=3) throw(Exception(\"Vector3d constructor dimension error\")); for(UInt i=0; i<3; i++) field[i]=(x.rows()>1 ? x(i,0) : x(0,i));}\n\ninline Vector3d &Vector3d::operator+= (Vector3d const &b)  {for(UInt i=0; i<3; i++) field[i]+=b.field[i]; return *this;}\ninline Vector3d &Vector3d::operator-= (Vector3d const &b)  {for(UInt i=0; i<3; i++) field[i]-=b.field[i]; return *this;}\ninline Vector3d &Vector3d::operator*= (Double  c)          {for(UInt i=0; i<3; i++) field[i]*=c; return *this;}\ninline Vector3d &Vector3d::operator/= (Double  c)          {for(UInt i=0; i<3; i++) field[i]/=c; return *this;}\n\ninline Double Vector3d::quadsum()const {return field[0]*field[0]+field[1]*field[1]+field[2]*field[2];}\ninline Angle  Vector3d::lambda() const {return Angle(atan2(field[1],field[0]));}\ninline Angle  Vector3d::phi()    const {return Angle(atan2(field[2],sqrt(field[0]*field[0]+field[1]*field[1])));}\ninline Angle  Vector3d::theta()  const {return Angle(PI/2-atan2(field[2],sqrt(field[0]*field[0]+field[1]*field[1])));}\ninline Double Vector3d::r()      const {return norm();}\ninline Double Vector3d::norm()   const {return sqrt(quadsum());}\ninline Double Vector3d::normalize()    {Double n=norm(); *this*=(1/n); return n;}\ninline Vector Vector3d::vector() const {Vector r(3); r(0)=x(); r(1)=y(); r(2)=z(); return r;}\n\ninline Double   inner(const Vector3d &a, const Vector3d &b)        {return a.field[0]*b.field[0]+a.field[1]*b.field[1]+a.field[2]*b.field[2];}\ninline Vector3d crossProduct(const Vector3d &a, const Vector3d &b) {return Vector3d(a.field[1]*b.field[2]-a.field[2]*b.field[1],\n                                                                                    a.field[2]*b.field[0]-a.field[0]*b.field[2],\n                                                                                    a.field[0]*b.field[1]-a.field[1]*b.field[0]);}\ninline Vector3d polar(Angle lambda, Angle phi, Double r) {return Vector3d(r*cos(lambda)*cos(phi), r*sin(lambda)*cos(phi), r*sin(phi));}\ninline Vector3d normalize(const Vector3d &x) {return x/x.norm();}\n\n\n/***********************************************/\n\n#endif /* __GROOPS_VECTOR3D__ */\n"
  },
  {
    "path": "source/base/wavelets.cpp",
    "content": "/***********************************************/\n/**\n* @file wavelets.cpp\n*\n* @brief Basic functions for wavelet decomposition\n*\n* @author Andreas Kvas\n* @date 2017-06-28\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/wavelets.h\"\n\n/***********************************************/\n\nnamespace Wavelets\n{\n\n/***********************************************/\n\nVector lowpass(const Vector &w)\n{\n  Vector b(w.rows());\n  for(UInt k=0; k<b.rows(); k++)\n    b(k) = w(w.rows()-1-k);\n  return b;\n}\n\n/***********************************************/\n\nVector highpass(const Vector &w)\n{\n  Vector b(w.rows());\n  for(UInt k=0; k<b.rows(); k++)\n    b(k) = w(k) * ((k%2) ? 1. : -1.);\n  return b;\n}\n\n/***********************************************/\n\nvoid halfbandFilter(const Matrix &input, const Vector &wl, Matrix &detailCoefficients, Matrix &approxCoefficients)\n{\n  // high/lowpass filters\n  const Vector hn = lowpass(wl);\n  const Vector gn = highpass(wl);\n\n  if(hn.size() != gn.size())\n    throw(Exception(\"Length of high- and low-pass filters do not match.\"));\n\n  // filter order\n  const UInt order = hn.rows();\n\n  // symmetric padding\n  Matrix padded(2*order+input.rows(), input.columns());\n  copy(input, padded.row(order, input.rows()));\n  for(UInt k = 0; k < order; k++)\n  {\n    copy(input.row(k), padded.row(order - 1 - k));\n    copy(input.row(input.rows() - 1 - k), padded.row(input.rows() + order + k));\n  }\n\n  // initialize state\n  Matrix stateLowpass(order, padded.columns());\n  Matrix stateHighpass(order, padded.columns());\n\n  // filter input signal\n  Matrix outputLowpass(padded.rows(), padded.columns());\n  Matrix outputHighpass(padded.rows(), padded.columns());\n\n  for(UInt k = 0; k<padded.rows(); k++)\n  {\n    // yn = b0 * xn + s0\n    axpy(hn(0), padded.row(k), outputLowpass.row(k));\n    axpy(1.0, stateLowpass.row(0), outputLowpass.row(k));\n\n    axpy(gn(0), padded.row(k), outputHighpass.row(k));\n    axpy(1.0, stateHighpass.row(0), outputHighpass.row(k));\n\n    // s_i = b_i+1 * xn + s_i+1 - a_i+1*yn\n    for(UInt i = 0; i<order-1; i++)\n    {\n      copy(stateLowpass.row(i+1), stateLowpass.row(i));\n      if(i+1<hn.rows())\n        axpy(hn(i+1), padded.row(k), stateLowpass.row(i));\n\n      copy(stateHighpass.row(i+1), stateHighpass.row(i));\n      if(i+1<gn.rows())\n        axpy(gn(i+1), padded.row(k), stateHighpass.row(i));\n    }\n  }\n\n  // compute output\n  const UInt outputSize = (padded.rows()-order-1)/2;\n  detailCoefficients = Matrix(outputSize, padded.columns());\n  approxCoefficients = Matrix(outputSize, padded.columns());\n\n  for(UInt k = 0; k<outputSize ; k++)\n  {\n    copy(outputLowpass.row(order+1+2*k), approxCoefficients.row(k));\n    copy(outputHighpass.row(order+1+2*k), detailCoefficients.row(k));\n  }\n}\n\n/***********************************************/\n\nstd::vector<Matrix> waveletTransform(const Matrix &input, const Vector &wl, UInt maxLevel)\n{\n  maxLevel = std::min(maxLevel, static_cast<UInt>(std::log2(static_cast<Double>(input.rows())/static_cast<Double>(wl.rows()-1))));\n\n  std::vector<Matrix> levels;\n\n  Matrix detail, approx;\n  approx = input;\n  for(UInt k = 0; k<maxLevel; k++)\n  {\n    Matrix tmp(approx);\n    halfbandFilter(tmp, wl, detail, approx);\n    levels.push_back(detail);\n  }\n  levels.push_back(approx);\n\n  return levels;\n}\n\n/**************************************************************************/\n\nvoid discreteWaveletTransform(std::vector<Double> &signal, const Vector &wl, UInt J, std::vector<Double> &coefficients, std::vector<UInt> &flag, std::vector<UInt> &length)\n{\n  try\n  {\n    UInt temp_len = signal.size();\n    if((temp_len % 2) != 0)\n    {\n      Double temp =signal.at(temp_len - 1);\n      signal.push_back(temp);\n      flag.push_back(1);\n      temp_len++;\n    }\n    else\n      flag.push_back(0);\n    length.push_back(temp_len);\n    flag.push_back(J);\n    // flag contains symmetric extension length\n\n    std::vector<Double> originalSignal, approxs, details;\n    originalSignal = signal;\n\n    // Storing Filter Values\n    std::vector<Double> lpDecom,hpDecom,lpRecon,hpRecon;\n    filtCoef(wl,lpDecom,hpDecom,lpRecon,hpRecon);\n\n    for(UInt iter = 0; iter < J; iter++)\n    {\n      UInt factor = 2; // Downsampling Factor is 2\n      UInt lf = lpDecom.size();\n      symmExtention(signal,lf-1);\n\n      std::vector<Double> cA;\n      //Low Pass Branch Computation\n      convfft(signal,lpDecom,cA);\n      cA.erase(cA.begin(),cA.begin()+lf);\n      cA.erase(cA.end()-lf+1,cA.end());\n      downSampling(cA, factor, approxs);\n\n      //High Pass Branch Computation\n      std::vector<Double> cD;\n      convfft(signal,hpDecom,cD);\n      cD.erase(cD.begin(),cD.begin()+lf);\n      cD.erase(cD.end()-lf+1,cD.end());\n      downSampling(cD, factor, details);\n\n      coefficients.insert(coefficients.begin(),details.begin(),details.end());\n      length.insert(length.begin(),details.size());\n\n      if(iter == J-1 )\n      {\n        coefficients.insert(coefficients.begin(),approxs.begin(),approxs.end());\n        length.insert(length.begin(),approxs.size());\n      }\n\n      signal.clear();\n      signal = approxs;\n      approxs.clear();\n      details.clear();\n     }\n     signal = originalSignal;\n  }\n\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/********************************************************************/\n\nvoid inverseDiscreteWaveletTransform(std::vector<Double> &dwtop, const Vector &wl, const std::vector<UInt> &flag, std::vector<Double> &recoveredSignal, std::vector<UInt> &length)\n{\n  try\n  {\n    UInt J = flag.at(1);\n    UInt lf;\n\n    std::vector<Double> approxs;\n    std::vector<Double> details;\n    UInt appLen = length.at(0);\n    UInt detLen = length.at(1);\n\n    std::vector<Double>::iterator dwt;\n    dwt = dwtop.begin();\n    approxs.assign(dwt,dwtop.begin()+appLen);\n    details.assign(dwtop.begin()+appLen, dwtop.begin()+ 2* appLen);\n\n    for(UInt i = 0; i < J; i++)\n    {\n      UInt factor = 2; // Upsampling Factor\n      // Storing Filter Values\n      std::vector<Double> lpDecom,hpDecom, lpRecon, hpRecon;\n      filtCoef(wl, lpDecom,hpDecom, lpRecon, hpRecon);\n      lf = lpRecon.size();\n\n      // Operations in the Low Frequency branch of the Synthesis Filter Bank\n      std::vector<Double> X_lp;\n      std::vector<Double> cA_up;\n      upSampling(approxs, factor,cA_up);\n      cA_up.pop_back();\n      convfft(cA_up, lpRecon, X_lp);\n\n      // Operations in the High Frequency branch of the Synthesis Filter Bank\n      std::vector<Double> X_hp;\n      std::vector<Double> cD_up;\n      upSampling(details, factor, cD_up);\n      cD_up.pop_back();\n      convfft(cD_up, hpRecon, X_hp);\n\n      appLen += detLen;\n      recoveredSignal.resize(X_lp.size());\n      transform (X_lp.begin(), X_lp.end(), X_hp.begin(), X_hp.begin(), [](Double i, Double j ){return i+j;});\n      recoveredSignal = X_hp;\n      recoveredSignal.erase(recoveredSignal.begin(),recoveredSignal.begin()+lf-2);\n      recoveredSignal.erase(recoveredSignal.end()-(lf - 2),recoveredSignal.end());\n\n      approxs.clear();\n      details.clear();\n\n      if(i < J - 1)\n      {\n        detLen = length.at(i+2);\n        for (UInt l = 0; l < detLen;l++)\n        {\n          Double temp = dwtop.at(appLen + l);\n          details.push_back(temp);\n        }\n      }\n      approxs = recoveredSignal;\n      for(UInt iter1 = 0; iter1 < (approxs.size() - detLen); iter1++)\n        approxs.pop_back();\n    }\n    // Remove Padding\n    UInt paddLength = flag.at(0);\n    recoveredSignal.erase(recoveredSignal.end()- paddLength,recoveredSignal.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/********************************************/\n\nvoid convfft(std::vector<Double> &a, std::vector<Double> &b, std::vector<Double> &c)\n{\n  try\n  {\n     UInt N = a.size() + b.size() - 1;\n     std::vector<std::complex<Double> > inp, filt;\n     for(UInt i=0; i < a.size(); i++)\n     {\n       Double temp = a.at(i);\n       inp.push_back(std::complex<Double>(temp,0));\n     }\n     for(UInt i =0; i < b.size(); i++)\n     {\n       Double temp = b.at(i);\n       filt.push_back(std::complex<Double>(temp,0));\n     }\n     //apply Fast Fourier Transform\n     dfft(inp,1,N);\n     dfft(filt,1,N);\n     std::vector<std::complex<Double> > temp;\n     UInt K=inp.size();\n     for(UInt i =0; i < K; i++)\n     {\n       std::complex<Double> mult = inp.at(i)*filt.at(i);\n       temp.push_back(mult);\n     }\n     dfft(temp, -1 , K);\n     for(UInt i =0; i < N ; i++)\n     {\n       Double temp1 =real(temp.at(i));\n       c.push_back(temp1);\n     }\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***************************************************************/\n\nvoid dfft(std::vector<std::complex<Double> > &data, int sign,UInt N)\n{\n  try\n  {\n    Double pi = -PI;\n    if(sign == 1 || sign == -1)\n      pi = sign * pi;\n    UInt len = data.size();\n    std::vector<std::complex<Double> >::iterator it;\n    it = data.end();\n    if(len != N)\n    {\n      UInt al = N - len;\n      data.insert(it, al, std::complex<Double> (0,0));\n    }\n\n    UInt K = (UInt) pow(2.0,ceil(log10(static_cast<Double>(N))/log10(2.0)));\n    std::vector<std::complex<Double> >::iterator it1;\n    it1 = data.end();\n    if(N < K)\n    {\n      UInt al = K - N;\n      data.insert(it1,al,std::complex<Double>(0,0));\n      N = K;\n    }\n\n    bitreverse(data);\n\n    for(UInt iter = 1; iter < N; iter <<=1)\n    {\n      const UInt step = iter << 1;\n      const Double theta =  pi / Double(iter);\n      Double wtemp = sin(theta * .5);\n\n      //Multipliers\n      Double wreal = -2 * wtemp * wtemp;\n      Double wimag = sin(theta);\n\n      //Factors\n      Double wr = 1.0;\n      Double wi = 0.0;\n\n      //Iteration through two loops\n      for(UInt m = 0; m < iter; m++)\n      {\n        //Iteration within m\n        for(UInt i = m; i < N; i += step)\n        {\n          //jth position\n          const UInt j = i + iter;\n          Double tempr = wr * real(data.at(j)) - wi * imag(data.at(j));\n          Double tempi = wr * imag(data.at(j)) + wi * real(data.at(j));\n          std::complex<Double> temp(tempr,tempi);\n          data.at(j)  = data.at(i) - temp;\n          data.at(i) += temp;\n        }\n\n        wtemp = wr;\n        wr += wr * wreal - wi * wimag;\n        wi += wi * wreal + wtemp * wimag ;\n      }\n    }\n\n    if(sign == -1)\n    {\n      Double scale = 1.0/Double(N);\n      for (UInt i = 0; i < N; i++)\n        data.at(i) *= scale;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/**************************************************************/\n\nvoid bitreverse(std::vector<std::complex<Double> > &signal)\n{\n  try\n  {\n    UInt len = signal.size();\n    UInt N   = (UInt) pow(2.0,ceil(log10(static_cast<Double>(len))/log10(2.0)));\n    UInt rev = 0;\n    //Processing Input Data\n    for(UInt iter = 0; iter < N; ++iter)\n    {\n      if (rev > iter)\n      {\n        //Replacing current values with reversed values\n        Double tempr = real(signal.at(rev));\n        Double tempi = imag(signal.at(rev));\n        std::complex<Double> temp(tempr,tempi);\n        signal.at(rev)  = signal.at(iter);\n        signal.at(iter) = temp;\n      }\n      //Using filter \"filt\" such that the value of reverse changes with each iteration\n      UInt filt = N;\n      while (rev & (filt >>= 1))\n        rev &= ~filt;\n      rev |= filt;\n    }\n  }\n\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/**************************************************************/\n\nvoid filtCoef(const Vector &wl, std::vector<Double> &lpDecom, std::vector<Double> &hpDecom, std::vector<Double> &lpRecon, std::vector<Double> &hpRecon)\n{\n  try\n  {\n    Vector gn =  highpass(wl);\n    Vector hn =  lowpass (wl);\n    UInt length = gn.size();\n    for(UInt i = 0; i < length; i++)\n    {\n      lpDecom.push_back(hn(i));\n      hpDecom.push_back(gn(i));\n      lpRecon.push_back(hn(length-i-1));\n      hpRecon.push_back(gn(length-i-1));\n    }\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/*************************************************/\n\nvoid symmExtention(std::vector<Double> &sig, UInt paddLength)\n{\n  try\n  {\n    UInt len = sig.size();\n    for(UInt i =0; i < paddLength; i++)\n    {\n      double temp1= sig.at(i * 2);\n      double temp2= sig.at(len - 1);\n      sig.insert(sig.begin(),temp1);\n      sig.insert(sig.end(),temp2);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/****************************************************************/\n\nvoid downSampling(std::vector<Double> &signal, UInt factor, std::vector<Double> &signalNew)\n{\n  try\n  {\n    UInt len = signal.size();\n    UInt lenNew = (UInt) ceil( (double) len / (double) factor);\n    for(UInt i = 0; i < lenNew; i++)\n    {\n      double temp = signal.at(i*factor);\n      signalNew.push_back(temp);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid upSampling(std::vector<Double> &signal, UInt factor, std::vector<Double> &signalNew)\n{\n  try\n  {\n    UInt len     = signal.size();\n    UInt lenNew  = (UInt) ceil( (Double) len * (Double) factor);\n    for(UInt i = 0; i < lenNew; i++)\n      if(i % factor == 0)\n      {\n        Double temp = signal.at(i/factor);\n        signalNew.push_back(temp);\n      }\n    else\n      signalNew.push_back(0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n} // end namespace Wavelets\n\n/***********************************************/\n"
  },
  {
    "path": "source/base/wavelets.h",
    "content": "/***********************************************/\n/**\n* @file wavelets.h\n*\n* @brief Basic functions for wavelet decomposition\n*\n* @author Andreas Kvas\n* @date 2017-06-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_WAVELETS__\n#define __GROOPS_WAVELETS__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Wavelets.\n* @ingroup base */\nnamespace Wavelets\n{\n  /** @brief FIR low-pass representation of wavelet. */\n  Vector lowpass(const Vector &w);\n\n  /** @brief FIR high-pass representation of wavelet. */\n  Vector highpass(const Vector &w);\n\n  /**\n  * @brief Forward wavelet transform\n  *\n  * This routine computes the forward wavelet transform of a regularly sampled time series\n  * using filter banks. The input time series is padded symmetrically around the edges to\n  * reduce warmup effects. This implementation yields the same results as PyWavelets\n  * (https://pywavelets.readthedocs.io/en/latest/).\n  *\n  * @param input data series\n  * @param wl wavelet coefficients\n  * @param maxLevel maximum decomposition level\n  * @return standard vector containing each level of the decomposed time series  */\n  std::vector<Matrix> waveletTransform(const Matrix &input, const Vector &wl, UInt maxLevel = MAX_UINT);\n\n  /**\n  * @brief Apply wavelet-halfband filters to time series and decimate.\n  *\n  * This routine applies the high- and low-pass filter representation of a wavelet\n  * to a time series and decimates the result. The high-pass filtered input is stored in\n  * detailCoefficients, the low-pass filtered input is stored in approxCoefficients.\n  *\n  * @param input data series\n  * @param wl wavelet class object\n  * @param[out] detailCoefficients high-pass filtered and decimated input\n  * @param[out] approxCoefficients low-pass filtered and decimated input  */\n  void halfbandFilter(const Matrix &input, const Vector &wl, Matrix &detailCoefficients, Matrix &approxCoefficients);\n\n  /**\n  * @brief Stationary wavelet transform\n  *\n  * This routine computes the stationary wavelet transform of a regularly sampled time series\n  * using filter banks. As opposed to the regular wavelet transform, no decimation is performed, which means each level contains\n  * the full number of samples. The input time series is padded symmetrically around the edges to\n  * reduce warmup effects. This implementation yields the same results as PyWavelets (https://pywavelets.readthedocs.io/en/latest/).\n  *\n  * @param input data series\n  * @param wl wavelet class object\n  * @param maxLevel maximum decomposition level\n  * @return standard vector containing each level of the decomposed time series\n  */\n  std::vector<Matrix> stationaryWaveletTransform(const Matrix &input, const Vector &wl, UInt maxLevel = MAX_UINT);\n\n  /**\n  * @brief Apply wavelet-halfband filters to time series.\n  *\n  * This routine applies the high- and low-pass filter representation of a wavelet\n  * to a time series. As apposed to the standard half-band filter, no decimation is performed.\n  * The high-pass filtered input is stored in detailCoefficients, the low-pass\n  * filtered input is stored in approxCoefficients.\n  *\n  * @param input data series\n  * @param wl wavelet class object\n  * @param level level\n  * @param[out] detailCoefficients high-pass filtered input\n  * @param[out] approxCoefficients low-pass filtered input   */\n  void stationaryHalfbandFilter(const Matrix &input, const Vector &wl, UInt level, Matrix &detailCoefficients, Matrix &approxCoefficients);\n\n  /**\n  * @brief Apply discrete wavelet transform to time series.\n  *\n  * This routine applies the discrete wavelet transform to time series\n  * and stores the output as a vector with the sequence of approximation and details coefficients.\n  *\n  * @param signal data series\n  * @param wl wavelet class object\n  * @param J level\n  * @param[out] coefficients wavelet coefficients\n  * @param[out] flag padd length (if added) and level of decomposition\n  * @param[out] length length of each set of details and approximation.*/\n  void discreteWaveletTransform(std::vector<Double> &signal, const Vector &wl, UInt J, std::vector<Double> &coefficients, std::vector<UInt> &flag, std::vector<UInt> &length);\n\n  /**\n  * @brief Apply inverse discrete wavelet transform.\n  *\n  * This routine applies the inverse discrete wavelet transform to a set of coefficients.\n  *\n  * @param dwtop set of coefficients ${a_J, d_J,..., d_1}\n  * @param wl wavelet class object\n  * @param flag padd length (if added) and level of decomposition\n  * @param recoveredSignal output in time domain\n  * @param[out] length length of each set of details and approximation.*/\n  void inverseDiscreteWaveletTransform(std::vector<Double> &dwtop, const Vector &wl, const std::vector<UInt> &flag, std::vector<Double> &recoveredSignal, std::vector<UInt> &length);\n\n  /** @brief compute convolution of two vectors $a$ and $b$ and store the output in $c$.*/\n  void convfft(std::vector<Double> &a, std::vector<Double> &b, std::vector<Double> &c);\n\n  /** @brief compute fast fourier transform.*/\n  void dfft(std::vector<std::complex<Double> > &data, int sign,UInt N);\n\n  /** @brief apply a bit reverse algorithm to sort out the output frequencies of the FFT.*/\n  void bitreverse(std::vector<std::complex<Double> > &signal);\n\n  /** @brief compute decomposition and reconstruction filter coefficients from wavelet file.*/\n  void filtCoef(const Vector &wl, std::vector<Double> &lpDecom, std::vector<Double> &hpDecom, std::vector<Double> &lpRecon, std::vector<Double> &hpRecon);\n\n  /** @brief apply symmetric padding to a signal.*/\n  void symmExtention(std::vector<Double> &sig, UInt paddLength);\n\n  /** @brief apply down-sampling to a signal.*/\n  void downSampling(std::vector<Double> &signal, UInt factor, std::vector<Double> &signalNew);\n\n  /** @brief increase the sampling of a signal by inserting 0.*/\n  void upSampling(std::vector<Double> &signal,   UInt factor, std::vector<Double> &signalNew);\n}\n#endif\n"
  },
  {
    "path": "source/classes/border/border.cpp",
    "content": "/***********************************************/\n/**\n* @file border.cpp\n*\n* @brief Borders of an area on sphere/ellipsoid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Border\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"borderRectangle.h\"\n#include \"borderCap.h\"\n#include \"borderPolygon.h\"\n#include \"borderGlobal.h\"\n#include \"border.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Border, \"borderType\",\n                      BorderRectangle,\n                      BorderCap,\n                      BorderPolygon)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(Border, \"borderType\")\n\n/***********************************************/\n\nBorder::Border(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"borders of geographical areas\"))\n    {\n      if(readConfigChoiceElement(config, \"rectangle\", type, \"along lines of geographical coordinates\"))\n        border.push_back(new BorderRectangle(config));\n      if(readConfigChoiceElement(config, \"cap\", type, \"spherical cap\"))\n        border.push_back(new BorderCap(config));\n      if(readConfigChoiceElement(config, \"polygon\", type, \"polygon from file\"))\n        border.push_back(new BorderPolygon(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    };\n\n    if(border.empty())\n      border.push_back(new BorderGlobal());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBorder::~Border()\n{\n  for(UInt i=0; i<border.size(); i++)\n    delete border.at(i);\n}\n\n/***********************************************/\n\nBool Border::isInnerPoint(Angle lambda, Angle phi) const\n{\n  Bool inner = border.at(0)->isExclude();\n  for(UInt i=0; i<border.size(); i++)\n    if(border.at(i)->isInnerPoint(lambda,phi))\n      inner = !border.at(i)->isExclude();\n  return inner;\n}\n\n/***********************************************/\n\nBool Border::isInnerPoint(const Vector3d &point, const Ellipsoid &ellipsoid) const\n{\n  Angle  L,B;\n  Double h;\n  ellipsoid(point, L, B, h);\n  return isInnerPoint(L, B);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/border/border.h",
    "content": "/***********************************************/\n/**\n* @file border.h\n*\n* @brief Borders of an area on sphere/ellipsoid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BORDER__\n#define __GROOPS_BORDER__\n\n// Latex documentation\n#ifdef DOCSTRING_Border\nstatic const char *docstringBorder = R\"(\n\\section{Border}\\label{borderType}\nWith this class you can select one or more region on the surface of the Earth.\nIn every instance of Border you can choose whether the specific region is excluded\nfrom the overall result with the switch \\config{exclude}.\nTo determine whether a specific point will be used furthermore the following algorithm will be applied:\nIn a first step all points are selected if first border excludes points otherwise all points excluded.\nWhen every point will be tested for each instance of border from top to bottom.\nIf the point is not in the selected region nothing happens.\nOtherwise it will included or excluded depending on the switch \\config{exclude}.\n\nFirst Example: The border excludes all continental areas.\nThe result are points on the oceans only.\n\nSecond Example: First border describes the continent north america. The next borders\nexcludes the great lakes and the last border describes Washington island.\nIn this configuration points are selected if they are inside north america\nbut not in the area of the great lakes. But if the point is on Washington island\nit will be included again.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup borderGroup Border\n* @brief Borders of an area on sphere/ellipsoid.\n* @ingroup classesGroup\n* The interface is given by @ref Border. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Border;\nclass BorderBase;\ntypedef std::shared_ptr<Border> BorderPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Borders of an area on sphere/ellipsoid.\n* An instance of this class can be created with @ref readConfig. */\nclass Border\n{\npublic:\n  /// Constructor.\n  Border(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~Border();\n\n  /** @brief Is this point inside the area?\n  * @param lambda longitude (-PI,PI]\n  * @param phi    latitude [PI/2,PI/2] */\n  Bool isInnerPoint(Angle lambda, Angle phi) const;\n\n  /** @brief Is this point inside the area?\n  * @param point point\n  * @param ellipsoid longitude, latitude of point relates to this ellipsoid. */\n  Bool isInnerPoint(const Vector3d &point, const Ellipsoid &ellipsoid=Ellipsoid()) const;\n\n  /** @brief creates an derived instance of this class. */\n  static BorderPtr create(Config &config, const std::string &name) {return BorderPtr(new Border(config, name));}\n\nprivate:\n  std::vector<BorderBase*> border;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Border.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a global border is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] border Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Border */\ntemplate<> Bool readConfig(Config &config, const std::string &name, BorderPtr &border, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass BorderBase\n{\npublic:\n  virtual ~BorderBase() {}\n\n  virtual Bool isInnerPoint(Angle lambda, Angle phi) const = 0;\n  virtual Bool isExclude() const = 0;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_BORDER__ */\n"
  },
  {
    "path": "source/classes/border/borderCap.h",
    "content": "/***********************************************/\n/**\n* @file borderCap.h\n*\n* @brief Spherical cap.\n* @see Border\n*\n* @author Annette Eicker\n* @date 2004-10-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BORDERCAP__\n#define __GROOPS_BORDERCAP__\n\n// Latex documentation\n#ifdef DOCSTRING_Border\nstatic const char *docstringBorderCap = R\"(\n\\subsection{Cap}\nThe region is defined by a spherical cap with the center given in geographical coordinates\nlongitude (\\config{lambdaCenter}) and latitude (\\config{phiCenter}).\nThe radius of the cap is given as aperture angle \\config{psi}.\n\n\\fig{!hb}{0.4}{borderCap}{fig:borderCap}{spherical cap}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Spherical cap.\n* @ingroup borderGroup\n* @see Border */\nclass BorderCap : public BorderBase\n{\n  Double   cosPsi;\n  Vector3d center;\n  Bool     exclude;\n\npublic:\n  BorderCap(Config &config);\n\n  Bool isInnerPoint(Angle lambda, Angle phi) const;\n  Bool isExclude() const {return exclude;}\n};\n\n/***********************************************/\n\ninline BorderCap::BorderCap(Config &config)\n{\n  Angle psi;\n  Angle lambdaCenter, phiCenter;\n\n  readConfig(config, \"lambdaCenter\", lambdaCenter, Config::MUSTSET,  \"\",  \"longitude of the center of the cap\");\n  readConfig(config, \"phiCenter\",    phiCenter,    Config::MUSTSET,  \"\",  \"latitude of the center of the cap\");\n  readConfig(config, \"psi\",          psi,          Config::MUSTSET,  \"\",  \"aperture angle (radius)\");\n  readConfig(config, \"exclude\",      exclude,      Config::DEFAULT,  \"0\", \"dismiss points inside\");\n  if(isCreateSchema(config)) return;\n\n  cosPsi = cos(psi);\n  center = polar(lambdaCenter, phiCenter, 1.0);\n}\n\n/***********************************************/\n\ninline Bool BorderCap::isInnerPoint(Angle lambda, Angle phi) const\n{\n  Vector3d pkt = polar(lambda, phi, 1.0);\n  return cosPsi<=inner(pkt,center);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_BORDER__ */\n"
  },
  {
    "path": "source/classes/border/borderGlobal.h",
    "content": "/***********************************************/\n/**\n* @file borderGlobal.h\n*\n* @brief Complete sphere.\n* @see Border\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BORDERGLOBAL__\n#define __GROOPS_BORDERGLOBAL__\n\n#include \"classes/border/border.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Complete sphere: All points are inside.\n* @ingroup borderGroup\n* @see Border */\nclass BorderGlobal : public BorderBase\n{\npublic:\n  Bool isInnerPoint(Angle, Angle) const {return TRUE;}\n  Bool isExclude() const {return FALSE;}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_BORDER__ */\n"
  },
  {
    "path": "source/classes/border/borderPolygon.h",
    "content": "/***********************************************/\n/**\n* @file borderPolygon.h\n*\n* @brief Borders described by spherical polygons.\n* @see Border\n*\n* @author Andreas Kvas\n* @date 2020-09-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BORDERPOLYGON__\n#define __GROOPS_BORDERPOLYGON__\n\n// Latex documentation\n#ifdef DOCSTRING_Border\nstatic const char *docstringBorderPolygon = R\"(\n\\subsection{Polygon}\\label{borderType:polygon}\nThe region is defined by \\configFile{inputfilePolygon}{polygon}\ncontaining one or more polygons given in longitude and latitude.\nAn additional \\config{buffer} around the polygon can be defined.\nUse a negative value to shrink the polygon area.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/filePolygon.h\"\n#include \"classes/border/border.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief polygon.\n* @ingroup borderGroup\n* @see Border */\nclass BorderPolygon : public BorderBase\n{\n  Ellipsoid             ellipsoid;\n  std::vector<std::vector<Vector3d>> vertices;\n  std::vector<Vector3d> centroid;\n  std::vector<Double>   capThreshold;\n  Bool                  exclude;\n  Double                buffer;\n\n  Bool inPolygon(const Vector3d &testPoint, UInt polyNo) const;\n  Bool inBuffer (const Vector3d &testPoint, UInt polyNo) const;\n\npublic:\n  BorderPolygon(Config &config);\n\n  Bool isInnerPoint(Angle lambda, Angle phi) const;\n  Bool isExclude() const {return exclude;}\n};\n\n/***********************************************/\n\ninline BorderPolygon::BorderPolygon(Config &config)\n{\n  FileName polygonName;\n\n  readConfig(config, \"inputfilePolygon\", polygonName, Config::MUSTSET, \"{groopsDataDir}/border/\", \"\");\n  readConfig(config, \"buffer\",           buffer,      Config::DEFAULT, \"0\", \"buffer around polygon [km], <0: inside\");\n  readConfig(config, \"exclude\",          exclude,     Config::DEFAULT, \"0\", \"dismiss points inside\");\n  if(isCreateSchema(config)) return;\n\n  std::vector<Polygon> polygon;\n  readFilePolygon(polygonName, polygon);\n\n  ellipsoid = Ellipsoid(DEFAULT_GRS80_a, DEFAULT_GRS80_f);\n\n  // find vertices and centroid for every polygon:\n  centroid.resize(polygon.size());\n  vertices.resize(polygon.size());\n  capThreshold.resize(polygon.size(), 1.0);\n  for(UInt i=0; i<polygon.size(); i++)\n  {\n    const UInt vertexCount = polygon.at(i).L.rows();\n    vertices.at(i).resize(vertexCount);\n    for(UInt k=0; k<vertexCount; k++)\n    {\n      vertices.at(i).at(k) = normalize(ellipsoid(Angle(polygon.at(i).L(k)), Angle(polygon.at(i).B(k)), 0.0));\n      centroid.at(i)      += vertices.at(i).at(k);\n    }\n    centroid.at(i).normalize();\n\n    for(auto &v : vertices.at(i))\n      capThreshold.at(i) = std::min(capThreshold.at(i), std::cos(std::acos(inner(centroid.at(i), v)) + std::fabs(buffer)/DEFAULT_R*1e3));\n  }\n}\n\n/***********************************************/\n\ninline Bool BorderPolygon::inPolygon(const Vector3d &testPoint, UInt polyNo) const\n{\n  if(inner(centroid.at(polyNo), testPoint) < capThreshold.at(polyNo))\n    return FALSE;\n\n  const Vector3d p   = crossProduct(testPoint, -centroid.at(polyNo));\n  const Vector3d axp = crossProduct(testPoint, p);\n  const Vector3d cxp = crossProduct(-centroid.at(polyNo), p);\n  const UInt     vertexCount = vertices.at(polyNo).size();\n  UInt crossingCount = 0;\n  for(UInt k=0; k<vertexCount; k++)\n  {\n    const Vector3d q = crossProduct(vertices.at(polyNo).at(k), vertices.at(polyNo).at((k+1)%vertexCount));\n    const Vector3d t = crossProduct(p, q);\n    if(t.norm() == 0.0)\n      continue;\n\n    Bool sign = std::signbit(-inner(t, axp));\n    if((sign == std::signbit( inner(t, cxp))) &&\n       (sign == std::signbit(-inner(t, crossProduct(vertices.at(polyNo).at(k), q)))) &&\n       (sign == std::signbit( inner(t, crossProduct(vertices.at(polyNo).at((k+1)%vertexCount), q)))))\n      crossingCount++;\n  }\n\n  return Bool(crossingCount%2);\n}\n\n/***********************************************/\n\ninline Bool BorderPolygon::inBuffer(const Vector3d &testPoint, UInt polyNo) const\n{\n  if(inner(centroid.at(polyNo), testPoint) < capThreshold.at(polyNo))\n    return FALSE;\n\n  const Double cosBuffer   = std::cos(buffer*1e3/DEFAULT_R);\n  const UInt   vertexCount = vertices.at(polyNo).size();\n  for(UInt k=0; k<vertexCount; k++)\n    if(cosBuffer <= inner(vertices.at(polyNo).at(k), testPoint))\n      return TRUE;\n\n  const Double sinBuffer = std::sin(std::fabs(buffer)*1e3/DEFAULT_R);\n  for(UInt k=0; k<vertexCount; k++)\n  {\n    const Vector3d n = crossProduct(vertices.at(polyNo).at(k), vertices.at(polyNo).at((k+1)%vertexCount));\n    if((inner(n, crossProduct(testPoint, vertices.at(polyNo).at(k))) <= 0) &&\n       (inner(n, crossProduct(testPoint, vertices.at(polyNo).at((k+1)%vertexCount))) >= 0) &&\n       (std::fabs(inner(testPoint, normalize(n))) <= sinBuffer))\n      return TRUE;\n  }\n\n  return FALSE;\n}\n\n/***********************************************/\n\ninline Bool BorderPolygon::isInnerPoint(Angle lambda, Angle phi) const\n{\n  const Vector3d testPoint = normalize(ellipsoid(lambda, phi, 0));\n\n  if(buffer)\n    for(UInt polyNo=0; polyNo<vertices.size(); polyNo++)\n      if(inBuffer(testPoint, polyNo))\n        return (buffer > 0);\n\n  UInt count = 0;\n  for(UInt polyNo=0; polyNo<vertices.size(); polyNo++)\n    if(inPolygon(testPoint, polyNo))\n      count++;\n  return ((count%2)==1);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_BORDER__ */\n"
  },
  {
    "path": "source/classes/border/borderRectangle.h",
    "content": "/***********************************************/\n/**\n* @file borderRectangle.h\n*\n* @brief Rectangle: along lines of geographical coordinates.\n* @see Border\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-10-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BORDERRECTANGLE__\n#define __GROOPS_BORDERRECTANGLE__\n\n// Latex documentation\n#ifdef DOCSTRING_Border\nstatic const char *docstringBorderRectangle = R\"(\n\\subsection{Rectangle}\nThe region is restricted along lines of geographical coordinates.\n\\config{minPhi} and \\config{maxPhi} describe the lower and the upper bound of the region.\n\\config{minLambda} and \\config{maxLambda} define the left and right bound.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/vector3d.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Rectangle: along lines of geographical coordinates.\n* @ingroup borderGroup\n* @see Border */\nclass BorderRectangle : public BorderBase\n{\n  Angle minLambda, maxLambda;\n  Angle minPhi,    maxPhi;\n  Bool  exclude;\n\npublic:\n  BorderRectangle(Config &config);\n\n  Bool isInnerPoint(Angle lambda, Angle phi) const;\n  Bool isExclude() const {return exclude;}\n};\n\n/***********************************************/\n\ninline BorderRectangle::BorderRectangle(Config &config)\n{\n  readConfig(config, \"minLambda\", minLambda, Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"maxLambda\", maxLambda, Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"minPhi\",    minPhi,    Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"maxPhi\",    maxPhi,    Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"exclude\",   exclude,   Config::DEFAULT,  \"0\", \"dismiss points inside\");\n  if(isCreateSchema(config)) return;\n\n  // valid values: -180<=lambda<=180, -90<=phi<=90 ??\n  if(minLambda<-PI)\n    minLambda += Angle(2*PI);\n\n  if(maxLambda>PI)\n    maxLambda += Angle(-2*PI);\n}\n\n/***********************************************/\n\ninline Bool BorderRectangle::isInnerPoint(Angle lambda, Angle phi) const\n{\n  if((phi<minPhi)||(phi>maxPhi))\n    return FALSE;\n  if(minLambda<maxLambda)\n    return ((lambda>=minLambda) && (lambda<=maxLambda));\n  else\n    return ((lambda>=minLambda) || (lambda<=maxLambda));\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_BORDER__ */\n"
  },
  {
    "path": "source/classes/condition/condition.cpp",
    "content": "/***********************************************/\n/**\n* @file condition.cpp\n*\n* @brief Condition.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Condition\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"conditionFileExist.h\"\n#include \"conditionCommand.h\"\n#include \"conditionStringContainsPattern.h\"\n#include \"conditionStringMatchPattern.h\"\n#include \"conditionExpression.h\"\n#include \"conditionMatrix.h\"\n#include \"conditionMatrixEmpty.h\"\n#include \"conditionAnd.h\"\n#include \"conditionOr.h\"\n#include \"conditionNot.h\"\n#include \"condition.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Condition, \"conditionType\",\n                      ConditionFileExist,\n                      ConditionCommand,\n                      ConditionExpression,\n                      ConditionMatrix,\n                      ConditionMatrixEmpty,\n                      ConditionStringContainsPattern,\n                      ConditionStringMatchPattern,\n                      ConditionAnd,\n                      ConditionOr,\n                      ConditionNot)\n\nGROOPS_READCONFIG_CLASS(Condition, \"conditionType\")\n\n/***********************************************/\n\nConditionPtr Condition::create(Config &config, const std::string &name)\n{\n  try\n  {\n    ConditionPtr condition;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"\");\n\n    if(readConfigChoiceElement(config, \"fileExist\",  type, \"\"))\n      condition = ConditionPtr(new ConditionFileExist(config));\n    if(readConfigChoiceElement(config, \"command\",    type, \"\"))\n      condition = ConditionPtr(new ConditionCommand(config));\n    if(readConfigChoiceElement(config, \"expression\", type, \"\"))\n      condition = ConditionPtr(new ConditionExpression(config));\n    if(readConfigChoiceElement(config, \"matrix\", type, \"\"))\n      condition = ConditionPtr(new ConditionMatrix(config));\n    if(readConfigChoiceElement(config, \"matrixEmpty\", type, \"\"))\n      condition = ConditionPtr(new ConditionMatrixEmpty(config));\n    if(readConfigChoiceElement(config, \"stringContainsPattern\", type, \"\"))\n      condition = ConditionPtr(new ConditionStringContainsPattern(config));\n    if(readConfigChoiceElement(config, \"stringMatchPattern\", type, \"\"))\n      condition = ConditionPtr(new ConditionStringMatchPattern(config));\n    if(readConfigChoiceElement(config, \"and\",        type, \"\"))\n      condition = ConditionPtr(new ConditionAnd(config));\n    if(readConfigChoiceElement(config, \"or\",         type, \"\"))\n      condition = ConditionPtr(new ConditionOr(config));\n    if(readConfigChoiceElement(config, \"not\",         type, \"\"))\n      condition = ConditionPtr(new ConditionNot(config));\n    endChoice(config);\n\n    return condition;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/condition/condition.h",
    "content": "/***********************************************/\n/**\n* @file condition.h\n*\n* @brief Condition.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITION__\n#define __GROOPS_CONDITION__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringCondition = R\"(\n\\section{Condition}\\label{conditionType}\nTest for conditions. See \\reference{Loop and conditions}{general.loopsAndConditions} for usage.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup conditionGroup Condition\n* @brief Conditional application of config elements or programs.\n* @ingroup classesGroup\n* The interface is given by @ref Condition. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Condition;\ntypedef std::shared_ptr<Condition> ConditionPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Condition.\n* An instance of this class can be created with @ref readConfig. */\nclass Condition\n{\npublic:\n  /// Destructor.\n  virtual ~Condition() {}\n\n  virtual Bool condition(const VariableList &varList) const = 0;\n\n  /** @brief creates an derived instance of this class. */\n  static ConditionPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Condition.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a condition is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] condition Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Condition */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ConditionPtr &condition, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n#endif /* __GROOPS_DERIVATION__ */\n"
  },
  {
    "path": "source/classes/condition/conditionAnd.h",
    "content": "/***********************************************/\n/**\n* @file conditionAnd.h\n*\n* @brief All conditions must be met (with short-circuit evaluation).\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-08-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONAND__\n#define __GROOPS_CONDITIONAND__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionAnd = R\"(\n\\subsection{And}\nAll conditions must be met (with short-circuit evaluation).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief All conditions must be met (with short-circuit evaluation).\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionAnd : public Condition\n{\n  std::vector<ConditionPtr> conditionPtr;\n\npublic:\n  ConditionAnd(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionAnd::ConditionAnd(Config &config)\n{\n  try\n  {\n    readConfig(config, \"condition\", conditionPtr, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionAnd::condition(const VariableList &varList) const\n{\n  try\n  {\n    for(UInt i=0; i<conditionPtr.size(); i++)\n      if(!conditionPtr.at(i)->condition(varList))\n        return FALSE;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionCommand.h",
    "content": "/***********************************************/\n/**\n* @file conditionCommand.h\n*\n* @brief Execute command and check success.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-08-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONCOMMAND__\n#define __GROOPS_CONDITIONCOMMAND__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionCommand = R\"(\n\\subsection{Command}\nExecute command and check success.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"inputOutput/system.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Execute command and check success.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionCommand : public Condition\n{\n  FileName command;\n  Bool     silently;\n\npublic:\n  ConditionCommand(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionCommand::ConditionCommand(Config &config)\n{\n  try\n  {\n    readConfig(config, \"command\",  command,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"silently\", silently, Config::DEFAULT,  \"0\", \"without showing the output.\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionCommand::condition(const VariableList &varList) const\n{\n  try\n  {\n    std::vector<std::string> outputs;\n    Bool result = System::exec(command(varList), outputs);\n    if(!silently)\n      for(const auto &output : outputs)\n        logInfo<<output<<Log::endl;\n  return result;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionExpression.h",
    "content": "/***********************************************/\n/**\n* @file conditionExpression.h\n*\n* @brief Evaluate expression.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-08-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONEXPRESSION__\n#define __GROOPS_CONDITIONEXPRESSION__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionExpression = R\"(\n\\subsection{Expression}\\label{conditionType:expression}\nEvaluate expression.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Evaluate expression.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionExpression : public Condition\n{\n  ExpressionVariablePtr expr;\n\npublic:\n  ConditionExpression(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionExpression::ConditionExpression(Config &config)\n{\n  try\n  {\n    readConfig(config, \"expression\", expr, Config::MUSTSET, \"\",  \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionExpression::condition(const VariableList &varList) const\n{\n  try\n  {\n    return (expr->evaluate(varList) != 0.);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionFileExist.h",
    "content": "/***********************************************/\n/**\n* @file conditionFileExist.h\n*\n* @brief Check for a file or directory existing.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-08-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONFILEEXIST__\n#define __GROOPS_CONDITIONFILEEXIST__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionFileExist = R\"(\n\\subsection{FileExist}\nCheck for a file or directory existing.\nSupports wildcards * for any number of characters and ? for exactly one character.\nFiles smaller than \\config{minSize} are treated as non-existent.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"inputOutput/system.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Check for a file or directory existing.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionFileExist : public Condition\n{\n  FileName fileName;\n  UInt     minSize;\n\npublic:\n  ConditionFileExist(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionFileExist::ConditionFileExist(Config &config)\n{\n  try\n  {\n    minSize = 0;\n\n    readConfig(config, \"file\",        fileName, Config::MUSTSET,  \"\", \"supports wildcards: * and ?\");\n    readConfig(config, \"minimumSize\", minSize,  Config::OPTIONAL, \"\", \"minimum file size in byte.\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionFileExist::condition(const VariableList &varList) const\n{\n  try\n  {\n    const std::vector<FileName> fileList = System::fileList(fileName(varList));\n    for(auto entry : fileList)\n      if(System::isDirectory(entry) || (System::fileSize(entry) >= minSize))\n        return TRUE;\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionMatrix.h",
    "content": "/***********************************************/\n/**\n* @file conditionMatrix.h\n*\n* @brief Evaluate elements of a matrix based on an expression.\n*\n* @author Sebastian Strasser\n* @date 2021-02-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONMATRIX__\n#define __GROOPS_CONDITIONMATRIX__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionMatrix = R\"(\n\\subsection{Matrix}\nEvaluate elements of a \\configClass{matrix}{matrixGeneratorType} based on an expression.\nIf \\config{all}=\\verb|yes|, all elements of the matrix must evaluate to true\nfor the condition to be fulfilled, otherwise any element evaluating to true is sufficient.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/condition/condition.h\"\n#include \"classes/matrixGenerator/matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Evaluate elements of a matrix based on an expression.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionMatrix : public Condition\n{\n  ExpressionVariablePtr expr;\n  MatrixGeneratorPtr matrixGenerator;\n  Bool all;\n\npublic:\n  ConditionMatrix(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionMatrix::ConditionMatrix(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",     matrixGenerator, Config::MUSTSET, \"\",  \"expression is evaluated for each element of resulting matrix\");\n    readConfig(config, \"expression\", expr,            Config::MUSTSET, \"\",  \"(variable: data) evaluated for each element\");\n    readConfig(config, \"all\",        all,             Config::DEFAULT, \"0\", \"all (=yes)/any (=no) elements must evaluate to true\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionMatrix::condition(const VariableList &varList) const\n{\n  try\n  {\n    Matrix A = matrixGenerator->compute();\n\n    VariableList varListMatrix = varList;\n    for(UInt i=0; i<A.rows(); i++)\n      for(UInt j=0; j<A.columns(); j++)\n      {\n        varListMatrix.setVariable(\"data\", A(i,j));\n        Bool result = (expr->evaluate(varListMatrix) != 0.);\n        if(!all && result)\n          return TRUE;\n        else if(all && !result)\n          return FALSE;\n      }\n\n    return all;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionMatrixEmpty.h",
    "content": "/***********************************************/\n/**\n* @file conditionMatrixEmpty.h\n*\n* @brief Evaluate if matrix (or instrument) file is empty/has zero size.\n*\n* @author Sebastian Strasser\n* @date 2021-09-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONMATRIXEMPTY__\n#define __GROOPS_CONDITIONMATRIXEMPTY__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionMatrixEmpty = R\"(\n\\subsection{MatrixEmpty}\nEvaluate if \\file{matrix}{matrix} (or \\file{instrument}{instrument}) file is empty/has zero size.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Evaluate if matrix (or instrument) file is empty/has zero size.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionMatrixEmpty : public Condition\n{\n  FileName fileName;\n\npublic:\n  ConditionMatrixEmpty(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionMatrixEmpty::ConditionMatrixEmpty(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileMatrix\", fileName, Config::MUSTSET, \"\",  \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionMatrixEmpty::condition(const VariableList &varList) const\n{\n  try\n  {\n    Matrix A;\n    readFileMatrix(fileName(varList), A);\n    return !A.size();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionNot.h",
    "content": "/***********************************************/\n/**\n* @file conditionNot.h\n*\n* @brief The result of the condition is inverted.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-03-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONNOT__\n#define __GROOPS_CONDITIONNOT__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionNot = R\"(\n\\subsection{Not}\nThe result of the condition is inverted.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief The result of the condition is inverted.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionNot : public Condition\n{\n  ConditionPtr conditionPtr;\n\npublic:\n  ConditionNot(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionNot::ConditionNot(Config &config)\n{\n  try\n  {\n    readConfig(config, \"condition\", conditionPtr, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionNot::condition(const VariableList &varList) const\n{\n  try\n  {\n    return !conditionPtr->condition(varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionOr.h",
    "content": "/***********************************************/\n/**\n* @file conditionOr.h\n*\n* @brief One of the conditions must be met (with short-circuit evaluation).\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-08-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONOR__\n#define __GROOPS_CONDITIONOR__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionOr = R\"(\n\\subsection{Or}\nOne of the conditions must be met (with short-circuit evaluation).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief One of the conditions must be met (with short-circuit evaluation).\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionOr : public Condition\n{\n  std::vector<ConditionPtr> conditionPtr;\n\npublic:\n  ConditionOr(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionOr::ConditionOr(Config &config)\n{\n  try\n  {\n    readConfig(config, \"condition\", conditionPtr, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionOr::condition(const VariableList &varList) const\n{\n  try\n  {\n    for(UInt i=0; i<conditionPtr.size(); i++)\n      if(conditionPtr.at(i)->condition(varList))\n        return TRUE;\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionStringContainsPattern.h",
    "content": "/***********************************************/\n/**\n* @file conditionStringContainsPattern.h\n*\n* @brief Determines if there is a match between a pattern or a regular expression and some subsequence in a string.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-03-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONSTRINGCONTAINSPATTERN__\n#define __GROOPS_CONDITIONSTRINGCONTAINSPATTERN__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionStringContainsPattern = R\"(\n\\subsection{StringContainsPattern}\nDetermines if there is a match between a \\config{pattern} and some subsequence in a \\config{string}.\nSupports wildcards * for any number of characters and ? for exactly one character.\nIf \\config{isRegularExpression} is set, \\config{pattern} is interpreted as a\nregular expression instead. In any case, the \\reference{text parser}{general.parser:text}\nis applied beforehand.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"classes/condition/condition.h\"\n#include <regex>\n\n/***** CLASS ***********************************/\n\n/** @brief Determines if there is a match between a pattern or a regular expression and some subsequence in a string.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionStringContainsPattern : public Condition\n{\n  FileName text, pattern;\n  Bool     isRegularExpression, caseSensitive;\n\npublic:\n  ConditionStringContainsPattern(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionStringContainsPattern::ConditionStringContainsPattern(Config &config)\n{\n  try\n  {\n    readConfig(config, \"string\",              text,                Config::OPTIONAL, \"\",  \"should contain a {variable}\");\n    readConfig(config, \"pattern\",             pattern,             Config::OPTIONAL, \"\",  \"supports wildcards: * and ?\");\n    readConfig(config, \"isRegularExpression\", isRegularExpression, Config::DEFAULT,  \"0\", \"pattern is  a regular expression\");\n    readConfig(config, \"caseSensitive\",       caseSensitive,       Config::DEFAULT,  \"1\", \"treat lower and upper case as distinct\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionStringContainsPattern::condition(const VariableList &varList) const\n{\n  try\n  {\n    std::string t = text(varList).str();\n    std::string p = pattern(varList).str();\n    if(!caseSensitive)\n    {\n      t = String::lowerCase(t);\n      p = String::lowerCase(p);\n    }\n\n    return std::regex_search(t, ((isRegularExpression) ? std::regex(p) : String::wildcard2regex(p)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/condition/conditionStringMatchPattern.h",
    "content": "/***********************************************/\n/**\n* @file conditionStringMatchPattern.h\n*\n* @brief Determines if a pattern or a regular expression matches the entire string.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-03-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONDITIONSTRINGMATCHPATTERN__\n#define __GROOPS_CONDITIONSTRINGMATCHPATTERN__\n\n// Latex documentation\n#ifdef DOCSTRING_Condition\nstatic const char *docstringConditionStringMatchPattern = R\"(\n\\subsection{StringMatchPattern}\nDetermines if a \\config{pattern} matches the entire \\config{string}.\nSupports wildcards * for any number of characters and ? for exactly one character.\nIf \\config{isRegularExpression} is set, \\config{pattern} is interpreted as a\nregular expression instead. In any case, the \\reference{text parser}{general.parser:text}\nis applied beforehand.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"classes/condition/condition.h\"\n#include <regex>\n\n/***** CLASS ***********************************/\n\n/** @brief Determines if a pattern or a regular expression matches the entire string.\n* @ingroup conditionGroup\n* @see Condition */\nclass ConditionStringMatchPattern : public Condition\n{\n  FileName text, pattern;\n  Bool     isRegularExpression, caseSensitive;\n\npublic:\n  ConditionStringMatchPattern(Config &config);\n\n  Bool condition(const VariableList &varList) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ConditionStringMatchPattern::ConditionStringMatchPattern(Config &config)\n{\n  try\n  {\n    readConfig(config, \"string\",              text,                Config::OPTIONAL, \"\",  \"should contain a {variable}\");\n    readConfig(config, \"pattern\",             pattern,             Config::OPTIONAL, \"\",  \"supports wildcards: * and ?\");\n    readConfig(config, \"isRegularExpression\", isRegularExpression, Config::DEFAULT,  \"0\", \"pattern is  a regular expression\");\n    readConfig(config, \"caseSensitive\",       caseSensitive,       Config::DEFAULT,  \"1\", \"treat lower and upper case as distinct\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ConditionStringMatchPattern::condition(const VariableList &varList) const\n{\n  try\n  {\n    std::string t = text(varList).str();\n    std::string p = pattern(varList).str();\n    if(!caseSensitive)\n    {\n      t = String::lowerCase(t);\n      p = String::lowerCase(p);\n    }\n\n    return std::regex_match(t, ((isRegularExpression) ? std::regex(p) : String::wildcard2regex(p)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilter.cpp",
    "content": "/***********************************************/\n/**\n* @file digitalFilter.cpp\n*\n* @brief Digital filter implementation.\n*\n* @author Matthias Ellmer\n* @author Andreas Kvas\n* @date 2015-10-29\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_DigitalFilter\n\n#include \"base/import.h\"\n#include \"base/fourier.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/digitalFilter/digitalFilterMovingAverage.h\"\n#include \"classes/digitalFilter/digitalFilterMedian.h\"\n#include \"classes/digitalFilter/digitalFilterDerivative.h\"\n#include \"classes/digitalFilter/digitalFilterIntegral.h\"\n#include \"classes/digitalFilter/digitalFilterGraceLowpass.h\"\n#include \"classes/digitalFilter/digitalFilterButterworth.h\"\n#include \"classes/digitalFilter/digitalFilterFile.h\"\n#include \"classes/digitalFilter/digitalFilterCorrelation.h\"\n#include \"classes/digitalFilter/digitalFilterWavelet.h\"\n#include \"classes/digitalFilter/digitalFilterNotch.h\"\n#include \"classes/digitalFilter/digitalFilterDecorrelation.h\"\n#include \"classes/digitalFilter/digitalFilterLag.h\"\n#include \"classes/digitalFilter/digitalFilterReduceFilterOutput.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(DigitalFilter, \"digitalFilterType\",\n                      DigitalFilterMovingAverage,\n                      DigitalFilterMedian,\n                      DigitalFilterDerivative,\n                      DigitalFilterIntegral,\n                      DigitalFilterCorrelation,\n                      DigitalFilterGraceLowpass,\n                      DigitalFilterButterworth,\n                      DigitalFilterFile,\n                      DigitalFilterWavelet,\n                      DigitalFilterNotch,\n                      DigitalFilterDecorrelation,\n                      DigitalFilterLag,\n                      DigitalFilterReduceFilterOutput)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(DigitalFilter, \"digitalFilterType\")\n\n/***********************************************/\n\nDigitalFilter::DigitalFilter(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"create digital filter\"))\n    {\n      if(readConfigChoiceElement(config, \"movingAverage\", type, \"moving average (boxcar) filter\"))\n        filters.push_back(new DigitalFilterMovingAverage(config));\n      if(readConfigChoiceElement(config, \"movingMedian\",  type, \"moving median filter\"))\n        filters.push_back(new DigitalFilterMedian(config));\n      if(readConfigChoiceElement(config, \"derivative\",    type, \"differentiation by polynomial approximation\"))\n        filters.push_back(new DigitalFilterDerivative(config));\n      if(readConfigChoiceElement(config, \"integral\",      type, \"integration by polynomial approximation\"))\n        filters.push_back(new DigitalFilterIntegral(config));\n      if(readConfigChoiceElement(config, \"correlation\",   type, \"correlation by simple coefficient\"))\n        filters.push_back(new DigitalFilterCorrelation(config));\n      if(readConfigChoiceElement(config, \"graceLowpass\",  type, \"GRACE low pass filter (self convolving kernel)\"))\n        filters.push_back(new DigitalFilterGraceLowpass(config));\n      if(readConfigChoiceElement(config, \"butterworth\",   type, \"fixed order digital Butterworth filter\"))\n        filters.push_back(new DigitalFilterButterworth(config));\n      if(readConfigChoiceElement(config, \"file\",          type, \"read ARMA filter from file\"))\n        filters.push_back(new DigitalFilterFile(config));\n      if(readConfigChoiceElement(config, \"wavelet\",       type, \"filter representation of wavelet\"))\n        filters.push_back(new DigitalFilterWavelet(config));\n      if(readConfigChoiceElement(config, \"notch\",         type, \"notch filter\"))\n        filters.push_back(new DigitalFilterNotch(config));\n      if(readConfigChoiceElement(config, \"decorrelation\",         type, \"decorrelation filter\"))\n        filters.push_back(new DigitalFilterDecorrelation(config));\n      if(readConfigChoiceElement(config, \"lag\",           type, \"lag/lead filter\"))\n        filters.push_back(new DigitalFilterLag(config));\n      if(readConfigChoiceElement(config, \"reduceFilterOutput\",  type, \"remove filter output from input signal\"))\n        filters.push_back(new DigitalFilterReduceFilterOutput(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDigitalFilter::~DigitalFilter()\n{\n  for(UInt i=0; i<filters.size(); i++)\n    delete filters.at(i);\n}\n\n/***********************************************/\n\nMatrix DigitalFilter::filter(const_MatrixSliceRef input) const\n{\n  try\n  {\n    Matrix output = input;\n    for(UInt i=0; i<filters.size(); i++)\n      output = filters.at(i)->filter(output);\n    return output;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<std::complex<Double>> DigitalFilter::frequencyResponse(UInt length) const\n{\n  try\n  {\n    std::vector<std::complex<Double>> F((length+2)/2, 1.);\n    for(UInt i=0; i<filters.size(); i++)\n    {\n      auto H = filters.at(i)->frequencyResponse(length);\n      for(UInt k=0; k<H.size(); k++)\n        F.at(k) *= H.at(k);\n    }\n    return F;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nMatrix DigitalFilterARMA::filter(const_MatrixSliceRef input) const\n{\n  try\n  {\n    // check input\n    // -----------\n    if(input.rows()<warmup())\n      throw(Exception(\"Time series is too short (<\"+input.rows()%\"%i\"s+\"> elements) to apply a filter with a warmup length of <\"+warmup()%\"%i\"s+\">.\"));\n\n    // filter in frequency domain\n    // --------------------------\n    if(inFrequencyDomain)\n    {\n      Matrix padded = pad(input, warmup(), bnStartIndex, padType);\n      auto H = frequencyResponse(padded.rows());\n      for(UInt k=0; k<padded.columns(); k++) // Filter column-wise\n      {\n        auto F = Fourier::fft(padded.column(k));\n        for(UInt i=0; i<F.size(); i++)\n          F.at(i) *= H.at(i);\n        copy(Fourier::synthesis(F, (padded.rows()%2==0)), padded.column(k));\n      }\n      return trim(padded, warmup(), bnStartIndex, padType);\n    }\n\n    // filter in time domain\n    // ---------------------\n    Matrix padded = pad(input, warmup(), bnStartIndex, padType);\n    if(backward)\n    {\n      for(UInt k = 0; k < padded.rows()/2; k++)\n        swap(padded.row(k), padded.row(padded.rows() - k - 1));\n    }\n    Matrix output(padded.rows(), padded.columns());\n\n    const UInt blockSize = std::min(static_cast<UInt>(64), padded.rows());\n\n    Matrix B(bn.rows() + blockSize - 1, blockSize);\n    for(UInt k = 0; k < B.columns(); k++)\n      copy(bn, B.slice(k, k, bn.rows(), 1));\n\n    for(UInt idxStart = 0; idxStart < output.rows(); idxStart+=blockSize)\n    {\n      UInt columnCount = std::min(output.rows() - idxStart, blockSize);\n      UInt rowCount = std::min(output.rows() - idxStart, B.rows());\n      matMult(1.0, B.slice(0, 0, rowCount, columnCount), padded.row(idxStart, columnCount), output.row(idxStart, rowCount));\n    }\n\n    if(an.size() > 1)\n    {\n      Matrix A(an.rows() + blockSize - 1, blockSize);\n      for(UInt k = 0; k < A.columns(); k++)\n        copy(an, A.slice(k, k, an.rows(), 1));\n\n      MatrixSlice A1(A);\n      A1.setType(Matrix::TRIANGULAR, Matrix::LOWER);\n\n      for(UInt idxStart = 0; idxStart < output.rows(); idxStart+=blockSize)\n      {\n        UInt columnCount = std::min(output.rows() - idxStart, blockSize);\n        if(idxStart > 0)\n          matMult(-1.0, A.row(blockSize, std::min(an.size() - 1, columnCount)), output.row(idxStart - blockSize, blockSize), output.row(idxStart, std::min(an.size() - 1, columnCount)));\n\n        triangularSolve(1.0, A1.slice(0, 0, columnCount, columnCount), output.row(idxStart, columnCount));\n      }\n    }\n\n    if(backward)\n    {\n      for(UInt k = 0; k < output.rows()/2; k++)\n        swap(output.row(k), output.row(output.rows() - k - 1));\n    }\n\n    return trim(output, warmup(), bnStartIndex, padType);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<std::complex<Double>> DigitalFilterARMA::frequencyResponse(UInt length) const\n{\n  try\n  {\n    if((bn.rows() > length) || (an.rows() > length))\n      throw(Exception(\"length must be at least\"+std::max(bn.rows(), an.rows())%\"%i\"s+\" for this filter\"));\n\n    Vector bPad(length);\n    copy(bn.row(bnStartIndex, bn.rows()-bnStartIndex), bPad.row(0, bn.rows()-bnStartIndex));\n    copy(bn.row(0, bnStartIndex), bPad.row(bPad.rows()-bnStartIndex, bnStartIndex));\n\n    Vector aPad(length);\n    copy(an, aPad.row(0, an.rows()));\n\n    if(backward) // reflect around element one\n      for(UInt k=0; k<std::max(bn.rows(), an.rows()); k++)\n      {\n        std::swap(aPad(k+1), aPad(aPad.rows()-1-k));\n        std::swap(bPad(k+1), bPad(bPad.rows()-1-k));\n      }\n\n    auto A = Fourier::fft(aPad);\n    auto B = Fourier::fft(bPad);\n    std::vector<std::complex<Double>> F(A.size());\n    for(UInt k=0; k<F.size(); k++)\n      F.at(k) = (std::abs(A.at(k))>0.) ? (B.at(k)/A.at(k)) : 1.;\n\n    return F;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt DigitalFilterARMA::warmup() const\n{\n  return std::max(std::max(bn.rows()-bnStartIndex-1, bnStartIndex), 3*an.rows());\n}\n\n/***********************************************/\n/***********************************************/\n\nMatrix DigitalFilterBase::pad(const_MatrixSliceRef input, UInt length, UInt timeShift, PadType padType)\n{\n  try\n  {\n    if(padType == PadType::NONE)\n    {\n      if(timeShift > 0)\n      {\n        Matrix padded(input.rows()+timeShift, input.columns());\n        copy(input, padded.row(0, input.rows()));\n        return padded;\n      }\n      else\n        return input;\n    }\n\n    if(input.rows()<1)\n      throw(Exception(\"Trying to pad a zero length array (\"+input.rows()%\"%i\"s + \" x \"+ input.columns()%\"%i\"s+\").\"));\n\n    Matrix padded(2*length+input.rows()+timeShift, input.columns());\n    copy(input, padded.row(length, input.rows()));\n\n    switch(padType)\n    {\n      case(PadType::ZERO):\n        break;\n\n      case(PadType::CONSTANT):\n        for(UInt k=0; k<length; k++)\n        {\n          copy(input.row(0), padded.row(k));\n          copy(input.row(input.rows()-1), padded.row(input.rows() + length + k));\n        }\n        break;\n\n      case(PadType::PERIODIC):\n        if(input.rows()<length)\n          throw(Exception(\"Time series is too short ( <\"+input.rows()%\"%i\"s+\"> elements) to apply periodic padding for a filter with a warmup length of <\"+length%\"%i\"s+\">.\"));\n        for(UInt k=0; k<length; k++)\n        {\n          copy(input.row(input.rows()-length+k), padded.row(k));\n          copy(input.row(k), padded.row(input.rows() + length + k));\n        }\n        break;\n\n      case(PadType::SYMMETRIC):\n        if(input.rows()<length+1)\n          throw(Exception(\"Time series is too short ( <\"+input.rows()%\"%i\"s+\"> elements) to apply symmetric padding for a filter with a warmup length of <\"+length%\"%i\"s+\">.\"));\n        for(UInt k=0; k<length; k++)\n        {\n          copy(input.row(k+1), padded.row(length-1-k));\n          copy(input.row(input.rows()-2-k), padded.row(input.rows() + length + k));\n        }\n        break;\n\n      default:\n        throw(Exception(\"Unknown pad type.\"));\n    }\n\n    return padded;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix DigitalFilterBase::trim(const_MatrixSliceRef input, UInt length, UInt timeShift, PadType padType)\n{\n  try\n  {\n    if(padType == PadType::NONE)\n    {\n      if(timeShift > 0)\n      {\n        return Matrix(input.row(timeShift, input.rows() - timeShift));\n      }\n      else\n        return input;\n    }\n\n    return Matrix(input.row(length + timeShift, input.rows()-2*length - timeShift));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, DigitalFilterBase::PadType &padType, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    std::string choice;\n    if(readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n    {\n      if(readConfigChoiceElement(config, \"none\",      choice, \"no padding is applied\"))                          padType = DigitalFilterBase::PadType::NONE;\n      if(readConfigChoiceElement(config, \"zero\",      choice, \"zero padding\"))                                   padType = DigitalFilterBase::PadType::ZERO;\n      if(readConfigChoiceElement(config, \"constant\",  choice, \"pad using first and last value\"))                 padType = DigitalFilterBase::PadType::CONSTANT;\n      if(readConfigChoiceElement(config, \"periodic\",  choice, \"periodic continuation of matrix\"))                padType = DigitalFilterBase::PadType::PERIODIC;\n      if(readConfigChoiceElement(config, \"symmetric\", choice, \"symmetric continuation around the matrix edges\")) padType = DigitalFilterBase::PadType::SYMMETRIC;\n      endChoice(config);\n      return TRUE;\n    }\n\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilter.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilter.h\n*\n* @brief Digital filter implementation.\n*\n* @author Matthias Ellmer\n* @author Andreas Kvas\n* @date 2015-10-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTER__\n#define __GROOPS_DIGITALFILTER__\n\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilter = R\"(\n\\section{DigitalFilter}\\label{digitalFilterType}\nDigital filter implementation for the filtering of equally spaced time series. This class implements the filter equations as\n\\begin{equation}\\label{digitalFilterType:arma}\n  \\sum_{l=0}^Q a_l y_{n-l} = \\sum_{k=-p_0}^{P-p_0-1} b_k x_{n-k}, \\hspace{25pt} a_0 = 1,\n\\end{equation}\nwhere $Q$ is the autoregressive (AR) order and $P$ is the moving average (MA) order. Note that the MA part can also be non-causal.\nThe characteristics of a filter cascade can be computed by the programs \\program{DigitalFilter2FrequencyResponse} and \\program{DigitalFilter2ImpulseResponse}.\nTo apply a filter cascade to a time series (or an instrument file ) use \\program{InstrumentFilter}.\nEach filter can be applyed in forward and backward direction by setting \\config{backwardDirection}.\nIf the same filter is applied in both directions, the combined filter has zero phase and the squared magnitude response.\nSetting \\config{inFrequencyDomain} to true applies the transfer function of the filter to the DFT of the input and synthesizes the result, i.e.:\n\\begin{equation}\n  y_n = \\mathcal{F}^{-1}\\{H\\cdot\\mathcal{F}\\{x_n\\}\\}.\n\\end{equation}\nThis is equivalent to setting \\config{padType} to \\config{periodic}.\n\nTo reduce warmup effects, the input time series can be padded by choosing a \\config{padType}:\n\\begin{itemize}\n\\item \\config{none}: no padding is applied\n\\item \\config{zero}: zeros are appended at the beginning and end of the input time series\n\\item \\config{constant}: the beginning of the input time series is padded with the first value, the end is padded with the last value\n\\item \\config{periodic}: periodic continuation of the input time series (i.,e. the beginning is padded with the last epochs and the end is padded with the first epochs)\n\\item \\config{symmetric}: beginning and end are reflected around the first and last epoch respectively\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup digitalFilterGroup DigitalFilter\n* @brief Digital filter implementation.\n* @ingroup classesGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass DigitalFilter;\nclass DigitalFilterBase;\ntypedef std::shared_ptr<DigitalFilter> DigitalFilterPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Digital filter implementation.\n* An Instance can be created by @ref readConfig. */\nclass DigitalFilter\n{\nprivate:\n  std::vector<DigitalFilterBase*> filters;\n\npublic:\n  /** @brief Constructor from config. */\n  DigitalFilter(Config &config, const std::string &name);\n\n  /// Destructor.\n ~DigitalFilter();\n\n  /** @brief Filter a signal along the first dimension.\n  * The signal is filtered along the first axis. Transpose the input to filter\n  * along the second. Take caution of warmup effects.\n  * @param input   The time series to be filtered.\n  * @returns The filtered time series  */\n  Matrix filter(const_MatrixSliceRef input) const;\n\n  /** @brief Frequency response evaluated at equally spaced spectral lines.\n  * @param length of data in time domain\n  * @return complex representation of the frequency response  */\n  std::vector<std::complex<Double>> frequencyResponse(UInt length) const;\n\n  /** @brief creates an derived instance of this class. */\n  static DigitalFilterPtr create(Config &config, const std::string &name) {return DigitalFilterPtr(new DigitalFilter(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class DigitalFilter.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a class without times is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] digitalFilter Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates DigitalFilter */\ntemplate<> Bool readConfig(Config &config, const std::string &name, DigitalFilterPtr &digitalFilter, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass DigitalFilterBase\n{\npublic:\n  enum class PadType {NONE, ZERO, CONSTANT, PERIODIC, SYMMETRIC};\n\n  static Matrix pad (const_MatrixSliceRef input, UInt length, UInt timeShift, PadType padType);\n  static Matrix trim(const_MatrixSliceRef input, UInt length, UInt timeShift, PadType padType);\n\npublic:\n  virtual ~DigitalFilterBase() {}\n  virtual Matrix filter(const_MatrixSliceRef input) const = 0;\n  virtual std::vector<std::complex<Double>> frequencyResponse(UInt length) const = 0;\n};\n\n/***** CLASS ***********************************/\n\n// Internal class: default implementation with ARMA coefficients\nclass DigitalFilterARMA : public DigitalFilterBase\n{\nprotected:\n  Vector  an, bn; // AR, MA coefficients\n  UInt    bnStartIndex;\n  Bool    inFrequencyDomain;\n  Bool    backward;\n  PadType padType;\n\n  virtual UInt warmup() const;\n\npublic:\n  DigitalFilterARMA() : inFrequencyDomain(FALSE), backward(FALSE), padType(PadType::NONE) {}\n  virtual ~DigitalFilterARMA() {}\n  virtual Matrix filter(const_MatrixSliceRef input) const;\n  virtual std::vector<std::complex<Double>> frequencyResponse(UInt length) const;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class PadType.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a class identity filter is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] padType Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates DigitalFilter */\ntemplate<> Bool readConfig(Config &config, const std::string &name, DigitalFilterBase::PadType &padType, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n// inline std::string DigitalFilterPadding_typeName() {return \"paddingType\";}\n// void DigitalFilterPadding_registerConfigSchema(Config &config);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_DIGITALFILTER__ */\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterButterworth.cpp",
    "content": "/***********************************************/\n/**\n* @file digitalFilterButterworth.cpp\n*\n* @brief Butterworth filter.\n*\n* @author Andreas Kvas\n* @date 2017-02-07\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/fourier.h\"\n#include \"classes/digitalFilter/digitalFilterButterworth.h\"\n\n/***********************************************/\n\nDigitalFilterButterworth::DigitalFilterButterworth(Config& config)\n{\n  try\n  {\n    UInt   order;       // filter order\n    UInt   nparams = 1; // number of parameters in adjustment\n    Double Wn, Vn;      // normalized cutoff frequency\n    std::function<std::vector<std::complex<Double>>(const std::vector<std::complex<Double>>&)> frequencyMapping;\n    std::string choice;\n\n    readConfig(config, \"order\", order, Config::MUSTSET, \"\", \"filter order\");\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"filter type\"))\n    {\n      if(readConfigChoiceElement(config, \"lowpass\",  choice))\n      {\n        readConfig(config, \"Wn\", Wn, Config::MUSTSET, \"\", \"normalized cutoff frequency (f_c / f_nyq)\");\n        frequencyMapping = std::bind(lowpassFrequencyScaling, std::placeholders::_1, Wn);\n        nparams = order;\n      }\n      if(readConfigChoiceElement(config, \"highpass\", choice))\n      {\n        readConfig(config, \"Wn\", Wn, Config::MUSTSET, \"\", \"normalized cutoff frequency (f_c / f_nyq)\");\n        frequencyMapping = std::bind(highpassFrequencyScaling, std::placeholders::_1, Wn);\n        nparams = order;\n      }\n      if(readConfigChoiceElement(config, \"bandpass\", choice))\n      {\n        readConfig(config, \"Wn1\", Wn, Config::MUSTSET, \"\", \"lower normalized cutoff frequency (f_c / f_nyq)\");\n        readConfig(config, \"Wn2\", Vn, Config::MUSTSET, \"\", \"upper normalized cutoff frequency (f_c / f_nyq)\");\n        frequencyMapping = std::bind(bandpassFrequencyScaling, std::placeholders::_1, Wn, Vn);\n        nparams = 2*order;\n      }\n      if(readConfigChoiceElement(config, \"bandstop\", choice))\n      {\n        readConfig(config, \"Wn1\", Wn, Config::MUSTSET, \"\", \"lower normalized cutoff frequency (f_c / f_nyq)\");\n        readConfig(config, \"Wn2\", Vn, Config::MUSTSET, \"\", \"upper normalized cutoff frequency (f_c / f_nyq)\");\n        frequencyMapping = std::bind(bandstopFrequencyScaling, std::placeholders::_1, Wn, Vn);\n        nparams = 2*order;\n      }\n      endChoice(config);\n    }\n    readConfig(config, \"backwardDirection\", backward,          Config::DEFAULT,  \"0\", \"apply filter in backward direction\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    Vector f = Fourier::frequencies(1022, 1.);\n    std::vector<std::complex<Double>> z(f.rows()); // evaluation frequencies for transfer function\n\n    for(UInt k = 0; k<f.rows(); k++)\n      z.at(k) = std::exp(std::complex<Double>(0.,1.) * f(k) * 2.0*PI);\n\n    // compute impulse response from transfer functions\n    std::vector< std::complex<Double> > H =  transferFunction(z, frequencyMapping, order);\n    H.back() = std::complex<Double>(H.back().real(), 0); // IFFT of real symmetric signal\n    Vector h = Fourier::synthesis(H, TRUE/*even*/);\n\n    // set up least squares adjustment\n    Matrix H0(h.rows(), nparams);\n    for(UInt k=0; k<nparams; k++) // columnwise circulant shift\n    {\n      copy(h.row(0, h.rows()-k-1), H0.slice(k+1, k, h.rows()-k-1, 1)); // diagonal and below\n      copy(h.row(h.rows()-k-1, k+1), H0.slice(0, k, k+1, 1));          // above diagonal\n    }\n\n    // solve least squares via QR decomposition\n    Vector l = h.row(nparams+1, h.rows()-nparams-1);\n    Matrix A = H0.row(nparams+1, H0.rows()-nparams-1);\n    Vector a_hat = leastSquares(A, l);\n\n    // set numerator and denominator polynomials\n    bnStartIndex = 0; // causal filter\n    bn =  h.row(0, nparams+1);\n    matMult(-1.0, H0.row(0, nparams+1), a_hat, bn);\n\n    an = Vector(a_hat.rows()+1);\n    an(0) = 1.0;\n    axpy(-1.0, a_hat, an.row(1, a_hat.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector< std::complex<Double> > DigitalFilterButterworth::transferFunction(const std::vector<std::complex<Double> > &z, std::function<std::vector<std::complex<Double>>(const std::vector<std::complex<Double>>&)> &mapping, UInt order, Double g0)\n{\n  std::vector< std::complex<Double> > s  = mapping(z); // map z to s-plane\n  std::vector< std::complex<Double> > Bn = butterworthPolynomial(s, order);\n\n  std::vector< std::complex<Double> > H(z.size());\n  for(UInt l = 0; l<H.size(); l++)\n    H.at(l) = g0/Bn.at(l);\n\n  return H;\n}\n\n/***********************************************/\n\nstd::vector< std::complex<Double> > DigitalFilterButterworth::butterworthPolynomial(const std::vector< std::complex<Double> > &s, UInt order)\n{\n  std::vector< std::complex<Double> > Bn(s.size(), std::complex<Double>(1.0, 0.0));\n  if((order%2) != 0) // odd orders\n    for(UInt l = 0; l<Bn.size(); l++)\n      Bn.at(l) = s.at(l) + 1.0;\n\n  for(UInt k = 1; k<order/2+1; k++)\n    for(UInt l = 0; l<Bn.size(); l++)\n      Bn.at(l) *= (s.at(l)*s.at(l) - 2.0*s.at(l)*std::cos( (2.0*k+order-1.0)/(2.0*order)*PI) + 1.0);\n\n  return Bn;\n}\n\n/***********************************************/\n\nstd::vector< std::complex<Double> > DigitalFilterButterworth::lowpassFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn)\n{\n  std::vector< std::complex<Double> > s(z.size());\n  for(UInt l = 0; l<s.size(); l++)\n    s.at(l) = 1.0/std::tan(0.5*PI*Wn)*(z.at(l)-1.0)/(z.at(l)+1.0);\n\n  return s;\n}\n\n/***********************************************/\n\nstd::vector< std::complex<Double> > DigitalFilterButterworth::highpassFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn)\n{\n  std::vector< std::complex<Double> > s(z.size());\n  for(UInt l = 0; l<s.size(); l++)\n    s.at(l) = std::tan(0.5*PI*Wn)*(z.at(l)+1.0)/(z.at(l)-1.0);\n\n  return s;\n}\n\n/***********************************************/\n\nstd::vector< std::complex<Double> > DigitalFilterButterworth::bandpassFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn, Double Vn)\n{\n  Double omega = std::sqrt(std::tan(0.5*PI*Wn)*std::tan(0.5*PI*Vn));\n  Double Q = omega/(std::tan(0.5*PI*Vn) - std::tan(0.5*PI*Wn));\n\n  std::vector< std::complex<Double> > s(z.size());\n  for(UInt l = 0; l<s.size(); l++)\n    s.at(l) = Q*((z.at(l)-1.0)/(z.at(l)+1.0)/omega + omega*(z.at(l)+1.0)/(z.at(l)-1.0) );\n\n  return s;\n}\n\n/***********************************************/\n\nstd::vector< std::complex<Double> > DigitalFilterButterworth::bandstopFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn, Double Vn)\n{\n  Double omega = std::sqrt(std::tan(0.5*PI*Wn)*std::tan(0.5*PI*Vn));\n  Double Q = omega/(std::tan(0.5*PI*Vn) - std::tan(0.5*PI*Wn));\n\n  std::vector< std::complex<Double> > s(z.size());\n  for(UInt l = 0; l<s.size(); l++)\n    s.at(l) = 1.0/(Q*((z.at(l)-1.0)/(z.at(l)+1.0)/omega + omega*(z.at(l)+1.0)/(z.at(l)-1.0)));\n\n  return s;\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterButterworth.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterButterworth.h\n*\n* @brief Butterworth filter.\n*\n* @author Matthias Ellmer\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERBUTTERWORTH__\n#define __GROOPS_DIGITALFILTERBUTTERWORTH__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterButterworth = R\"(\n\\subsection{Butterworth}\nDigital implementation of the Butterworth filter. The design of the filter is done by modifying the analog (continuous time) transfer function, which is\nthen transformed into the digital domain by using the bilinear transform. The filter coefficients are then determined by a least squares adjustment in time domain.\n\nThe \\config{filterType} can be \\config{lowpass}, \\config{highpass}, where one cutoff frequency has to be specified, and \\config{bandpass} and \\config{bandstop} where to cutoff frequencies have to be specified.\nCutoff frequencies must be given as normalized frequency $w_n = f/f_{\\text{nyq}}$. For a cutoff frequency of 30~mHz for a time series sampled with 5~seconds gives a normalized frequency of $0.03/0.1 = 0.3$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Butterworth filter.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterButterworth : public DigitalFilterARMA\n{\n  static std::vector< std::complex<Double> > transferFunction(const std::vector<std::complex<Double> > &z, std::function<std::vector<std::complex<Double>>(const std::vector<std::complex<Double>>&)>& mapping, UInt order, Double g0=1.0);\n  static std::vector< std::complex<Double> > butterworthPolynomial(const std::vector< std::complex<Double> > &s, UInt order);\n  static std::vector< std::complex<Double> > lowpassFrequencyScaling (const std::vector< std::complex<Double> > &z, Double Wn);\n  static std::vector< std::complex<Double> > highpassFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn);\n  static std::vector< std::complex<Double> > bandpassFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn, Double Vn);\n  static std::vector< std::complex<Double> > bandstopFrequencyScaling(const std::vector< std::complex<Double> > &z, Double Wn, Double Vn);\n\npublic:\n  DigitalFilterButterworth(Config &config);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterCorrelation.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterCorrelation.h\n*\n* @brief Simple correlation of time series.\n*\n* @author Matthias Ellmer\n* @date 2017-11-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERCORRELATION__\n#define __GROOPS_DIGITALFILTERCORRELATION__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterCorrelation = R\"(\n\\subsection{Correlation}\nCorrelation ($\\rho$) of \\config{corr} is introduced into the time series:\n\\begin{equation}\n  y_n = \\rho\\cdot y_{n-1} + \\sqrt{1-\\rho^2}x_n.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Correlation filter.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterCorrelation : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterCorrelation(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterCorrelation::DigitalFilterCorrelation(Config &config)\n{\n  try\n  {\n    Double corr;\n    readConfig(config, \"correlation\",       corr,              Config::MUSTSET, \"\",  \"correlation\");\n    readConfig(config, \"backwardDirection\", backward,          Config::DEFAULT,  \"0\", \"apply filter in backward direction\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    bnStartIndex = 0;\n    an = {1., -corr};\n    bn = {std::sqrt(1-corr*corr)};\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterDecorrelation.h",
    "content": "/***********************************************/\n/**\n* @file DigitalFilterDecorrelation.h\n*\n* @brief Decorrelation filter.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERDECORRELATION__\n#define __GROOPS_DIGITALFILTERDECORRELATION__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterDecorrelation = R\"(\n\\subsection{Decorrelation}\nMoving average decorrelation filter based on eigendecomposition of a Toeplitz covariance matrix.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Decorrelation filter.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterDecorrelation : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterDecorrelation(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterDecorrelation::DigitalFilterDecorrelation(Config &config)\n{\n  try\n  {\n    FileName fileCovarianceFunction;\n\n    readConfig(config, \"inputfileCovarianceFunction\",            fileCovarianceFunction,            Config::MUSTSET, \"\", \"covariance function of time series\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Matrix cov;\n    readFileMatrix(fileCovarianceFunction, cov);\n\n    Matrix C(cov.rows(), Matrix::SYMMETRIC, Matrix::UPPER);\n    for(UInt r = 0; r<cov.rows(); r++)\n      for(UInt c = r; c<cov.rows(); c++)\n        C(r, c) = cov(c-r,1);\n\n    Vector e = eigenValueDecomposition(C);\n    bn = Vector(cov.rows());\n    bnStartIndex = bn.rows()/2;\n\n    Vector qi = C.row(bnStartIndex).trans();\n    for(UInt k=0; k<qi.rows(); k++)\n      qi(k) *= 1./std::sqrt(e(k));\n\n    matMult(1.0, C, qi, bn);\n    for(UInt k = 0; k<bnStartIndex; k++)\n      std::swap(bn(k), bn(bn.rows()-1-k));\n\n    an = Vector(1, 1.);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterDerivative.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterDerivative.h\n*\n* @brief Numerical differentiation using polynomial approximation.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERDERIVATIVE__\n#define __GROOPS_DIGITALFILTERDERIVATIVE__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterDerivative = R\"(\n\\subsection{Derivative}\nSymmetric MA filter for numerical differentiation using polynomial approximation. The input time series is approximated by a moving polynomial of degree \\config{polynomialDegree}, by solving\n\\begin{equation}\n  \\begin{bmatrix} x(t_k+\\tau_0) \\\\ \\vdots \\\\ x(t_k+\\tau_M) \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  1      & \\tau_0 & \\tau_0^2 & \\cdots & \\tau_0^M \\\\\n  \\vdots & \\vdots & \\vdots   &        & \\vdots   \\\\\n  1      & \\tau_M & \\tau_M^2 & \\cdots & \\tau_M^M \\\\\n  \\end{bmatrix}%^{-1}\n  \\begin{bmatrix}\n  a_0 \\\\ \\vdots \\\\ a_M\n  \\end{bmatrix}\n  \\qquad\\text{with}\\quad\n  \\tau_j =  (j-M/2)\\cdot \\Delta t,\n\\end{equation}\nfor each time step $t_k$ ($\\Delta t$ is the \\config{sampling} of the time series).\nThe filter coefficients for the $k$-th derivative are obtained by taking the appropriate row of the inverse coefficient matrix $\\mathbf{W}$:\n\\begin{equation}\n  b_n = \\prod_{i=0}^{k-1} (k-i) \\mathbf{w}_{2,:}.\n\\end{equation}\nThe \\config{polynomialDegree} should be even if no phase shift should be introduced.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Numerical differentiation using polynomial approximation.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterDerivative : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterDerivative(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterDerivative::DigitalFilterDerivative(Config &config)\n{\n  try\n  {\n    UInt   degree;\n    UInt   derivative;\n    Double dt = 1.0;\n\n    readConfig(config, \"polynomialDegree\", degree,     Config::MUSTSET,  \"8\",   \"degree of approximation polynomial\");\n    readConfig(config, \"derivative\",       derivative, Config::DEFAULT,  \"1\",   \"take kth derivative\");\n    readConfig(config, \"sampling\",         dt,         Config::DEFAULT,  \"1.0\", \"assumed time step between points\");\n    readConfig(config, \"padType\",          padType,    Config::MUSTSET,  \"\",    \"\");\n    if(isCreateSchema(config)) return;\n\n    Matrix F(degree+1, degree+1);\n    for(UInt j=0; j<F.rows(); j++)\n    {\n      F(j,0) = 1.;\n      for(UInt n=0; n<F.columns(); n++)\n       F(j,n) = std::pow(0.5*degree-j, n);\n    }\n    inverse(F);\n\n    Double factor = 1.0;\n    for(UInt n=1; n<=derivative; n++)\n      factor *= n/dt;\n\n    an = Vector(1, 1.);\n    bn = Vector(F.row(derivative).trans()*factor);\n    bnStartIndex = bn.size()/2; // non-causal filter\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterFile.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterFile.h\n*\n* @brief Filter from file.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERFILE__\n#define __GROOPS_DIGITALFILTERFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterFile = R\"(\n\\subsection{File}\nRead filter coefficients of \\eqref{digitalFilterType:arma} from a coefficient file.\nOne column might define the index $n$\nof the coefficients $a_n$ and $b_n$ in the other columns.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Filter from file.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterFile : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterFile(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterFile::DigitalFilterFile(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    ExpressionVariablePtr exprId, exprMA, exprAR;\n\n    readConfig(config, \"inputfileMatrix\",   fileName,          Config::MUSTSET,   \"\",      \"matrix with filter coefficients\");\n    readConfig(config, \"index\",             exprId,            Config::OPTIONAL, \"data0\", \"index of coefficients (input columns are named data0, data1, ...)\");\n    readConfig(config, \"bn\",                exprMA,            Config::OPTIONAL, \"data1\", \"MA coefficients (moving average) (input columns are named data0, data1, ...)\");\n    readConfig(config, \"an\",                exprAR,            Config::OPTIONAL, \"data2\", \"AR coefficients (autoregressive) (input columns are named data0, data1, ...)\");\n    readConfig(config, \"backwardDirection\", backward,          Config::DEFAULT,   \"0\",     \"apply filter in backward direction\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,   \"0\",     \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,   \"\",      \"\");\n    if(isCreateSchema(config)) return;\n\n    Matrix A;\n    readFileMatrix(fileName, A);\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(A, varList);\n\n    std::vector< std::pair<Int, Double> > bk;\n    std::vector< std::pair<Int, Double> > ak;\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      evaluateDataVariables(A, i, varList);\n      Int idx = exprId ? static_cast<Int>(exprId->evaluate(varList)) : static_cast<Int>(i);\n      if(exprMA && exprMA->evaluate(varList) != 0.0) bk.push_back({idx, exprMA->evaluate(varList)});\n      if(exprAR && exprAR->evaluate(varList) != 0.0) ak.push_back({idx, exprAR->evaluate(varList)});\n    }\n    if(std::any_of(ak.begin(), ak.end(), [](const std::pair<Int, Double> &a) { return a.first<0; }))\n      throw(Exception(\"negative indicies are not allowed for AR coefficients (non-causal filter)\"));\n\n    // allocate filter coefficient vectors\n    // -----------------------------------\n    auto indexComparable = [](const std::pair<Int, Double> &b1, const std::pair<Int, Double> &b2) { return b1.first < b2.first; };\n    if(bk.size()>0)\n    {\n      auto minMaxIndex = std::minmax_element(bk.begin(), bk.end(), indexComparable);\n      bnStartIndex = std::max(-(*minMaxIndex.first).first, 0);\n      bn = Vector((*minMaxIndex.second).first + bnStartIndex + 1);\n      for(auto &b : bk) bn(b.first+bnStartIndex) = b.second;\n    }\n    if(ak.size()>0)\n    {\n      auto maxIndex = std::max_element(ak.begin(), ak.end(), indexComparable);\n      an = Vector((*maxIndex).first + 1);\n      for(auto &a : ak) an(a.first) = a.second;\n    }\n    else\n      an = Vector(1, 1.0);\n\n    if(an(0) != 1.0)\n    {\n      logWarning<<\"a0 coefficient set to one\"<<Log::endl;\n      an(0) = 1.0;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterGraceLowpass.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterGraceLowpass.h\n*\n* @brief Low pass filter as used in GRACE processing.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERGRACELOWPASS__\n#define __GROOPS_DIGITALFILTERGRACELOWPASS__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterGraceLowpass = R\"(\n\\subsection{GraceLowpass}\nLow pass and differentation filter as used for GRACE KBR and ACC data in the Level1A processing.\n\n\\fig{!hb}{0.8}{DigitalFilter_graceLowpass}{fig:DigitalFilterGraceLowpass}{Amplitude response of the low pass filter used in the L1A processing.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Low pass filter as used in GRACE processing.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterGraceLowpass : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterGraceLowpass(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterGraceLowpass::DigitalFilterGraceLowpass(Config &config)\n{\n  try\n  {\n    Double      fs, B, Tf;\n    UInt        Nc;\n    Double      f0;\n    Bool        reduceFit;\n    UInt        type = 0;\n    std::string choice;\n\n    readConfig(config, \"rawDataRate\",         fs,        Config::MUSTSET,  \"10.0\",    \"sampling frequency in Hz (fs).\");\n    readConfig(config, \"convolutionNumber\",   Nc,        Config::DEFAULT,  \"7\",       \"number of self convolutions of the filter kernel\");\n    readConfig(config, \"fitInterval\",         Tf,        Config::DEFAULT,  \"70.7\",    \"length of the filter kernel [seconds]\");\n    readConfig(config, \"lowPassBandwith\",     B,         Config::DEFAULT,  \"0.1\",     \"target low pass bandwidth\");\n    readConfig(config, \"normFrequency\",       f0,        Config::DEFAULT,  \"0.37e-3\", \"norm filter at this frequency [Hz] (default: GRACE dominant (J2) signal frequency)\");\n    readConfig(config, \"reduceQuadraticFit\",  reduceFit, Config::DEFAULT,  \"1\",       \"remove->filter->restore quadratic fit\");\n    if(readConfigChoice(config, \"derivative\", choice,    Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"derivative1st\", choice, \"range rate\"))         type = 1;\n      if(readConfigChoiceElement(config, \"derivative2nd\", choice, \"range acceleration\")) type = 2;\n      endChoice(config);\n    }\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    const Int NB = static_cast<Int>(round(B*Tf));   // number of frequency bins in the passband\n    const Int Nf = static_cast<Int>(round(fs*Tf));  // number of raw data points in the fit intervall\n    const Int Nh = (Nf-1)/2;\n\n    // self convoluted (Nc times) boxcar in frequency domain -> discrete sinc\n    Vector Fk(2*Nh+1);\n    for(Int k=-Nh; k<=Nh; k++)\n      for(Int m=-NB; m<=NB; m++)\n        Fk(k+Nh) += (k!=m) ? (pow(sin(PI*(k-m)/Nc)/sin(PI*(k-m)/Nf), Nc)) : pow(Nf/Nc, Nc);\n\n    // back transformation into time domain: discrete cos transformation\n    Vector fn(2*Nh+1);\n    for(Int n=-Nh; n<=Nh; n++)\n      for(Int k=-Nh; k<=Nh; k++)\n        if(type == 0)\n          fn(n+Nh) += Fk(Nh-k) * cos(2*PI*k*n/Nf);\n        else if(type == 1)\n          fn(n+Nh) += Fk(Nh-k) * sin(2*PI*k*n/Nf) * (-2*PI*k/Tf); // 1st derivative\n        else if(type == 2)\n          fn(n+Nh) += Fk(Nh-k) * cos(2*PI*k*n/Nf) * (-2*PI*k/Tf)*(2*PI*k/Tf); // 2nd derivative\n\n    // norm filter (preserve dominant (J2) signal frequency)\n    Vector f0n(2*Nh+1);\n    for(Int n=-Nh; n<=Nh; n++)\n      for(Int k=-Nh; k<=Nh; k++)\n        f0n(n+Nh) += Fk(Nh-k) * cos(2*PI*k*n/Nf);\n    Double Fnorm = 0.0;\n    for(Int n=-Nh; n<=Nh; n++)\n      Fnorm += cos(2*PI*f0*n/fs) * f0n(Nh-n);\n    fn *= 1/Fnorm;\n\n    // Reduce Quadratic Fit\n    // --------------------\n    if(reduceFit)\n    {\n      Matrix Qt(3, fn.rows()); // = Q^T\n      for(UInt z=0; z<Qt.columns(); z++)\n      {\n        const Double t = ((fn.rows()-1.)/2.-z)/fs;\n        Qt(0,z) = 1.0;\n        Qt(1,z) = t;\n        Qt(2,z) = t*t;\n      }\n\n      // (Q^T*Q)^-1 * Q^T\n      Matrix QtQ(Qt.rows(), Matrix::SYMMETRIC);\n      rankKUpdate(1., Qt.trans(), QtQ);\n      Matrix QtQQt = solve(QtQ,Qt);\n\n      matMult(-1, QtQQt.trans(), (Qt*fn), fn); // remove\n      if(type == 0)\n        fn += QtQQt.trans().column(0);   // restore\n      else if(type == 1)\n        fn += QtQQt.trans().column(1);   // restore 1st derivative\n      else if(type == 2)\n        fn += 2*QtQQt.trans().column(2); // restore 2nd derivative\n    }\n\n    bn = fn;\n    bnStartIndex = bn.rows()/2;\n    an = Vector(1); an(0) = 1.0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterIntegral.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterIntegral.h\n*\n* @brief Numerical integration using polynomial approximation.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERINTEGRAL__\n#define __GROOPS_DIGITALFILTERINTEGRAL__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterIntegral = R\"(\n\\subsection{Integral}\nNumerical integration using polynomial approximation.\nThe input time series is approximated by a moving polynomial of degree \\config{polynomialDegree}\nby solving\n\\begin{equation}\n  \\begin{bmatrix} x(t_k+\\tau_0) \\\\ \\vdots \\\\ x(t_k+\\tau_M) \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  1      & \\tau_0 & \\tau_0^2 & \\cdots & \\tau_0^M \\\\\n  \\vdots & \\vdots & \\vdots   &        & \\vdots   \\\\\n  1      & \\tau_M & \\tau_M^2 & \\cdots & \\tau_M^M \\\\\n  \\end{bmatrix}%^{-1}\n  \\begin{bmatrix}\n  a_0 \\\\ \\vdots \\\\ a_M\n  \\end{bmatrix}\n  \\qquad\\text{with}\\quad\n  \\tau_j =  (j-M/2)\\cdot \\Delta t,\n\\end{equation}\nfor each time step $t_k$ ($\\Delta t$ is the \\config{sampling} of the time series).\nThe numerical integral for each time step $t_k$ is approximated by the center interval of the estimated polynomial.\n\n\\fig{!hb}{0.7}{DigitalFilter_integral}{fig:DigitalFilterIntegral}{Numerical integration by polynomial approximation.}\n\n\\config{polynomialDegree} should be even to avoid a phase shift.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Numerical integration using polynomial approximation.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterIntegral : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterIntegral(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterIntegral::DigitalFilterIntegral(Config &config)\n{\n  try\n  {\n    UInt   degree;\n    Double dt;\n\n    readConfig(config, \"polynomialDegree\", degree,  Config::MUSTSET,  \"7\",   \"degree of approximation polynomial\");\n    readConfig(config, \"sampling\",         dt,      Config::DEFAULT,  \"1.0\", \"assumed time step between points\");\n    readConfig(config, \"padType\",          padType, Config::MUSTSET,  \"\",    \"\");\n    if(isCreateSchema(config)) return;\n\n    Matrix F(degree+1, degree+1);\n    Matrix D(degree+1, degree+1);\n    Vector v(degree+1);\n    for(UInt j=0; j<F.rows(); j++)\n    {\n      D(j, j) = 1.0/std::pow(dt, j);\n      v(j) = dt/(j+1.);\n      F(j,0) = 1.;\n      for(UInt n=1; n<F.columns(); n++)\n        F(j,n) = std::pow(0.5*degree-j, n);\n    }\n    inverse(F);\n\n    bnStartIndex = bn.rows()/2;\n    bn = Vector(degree+1);\n    matMult(1.0, v.trans(), D*F, bn.trans());\n    an = Vector(2);\n    an(0) = 1.0; an(1) = -1.0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterLag.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterLag.h\n*\n* @brief Digital lag filter.\n*\n* @author Saniya Behzadpour\n* @date 2018-03-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERLAG__\n#define __GROOPS_DIGITALFILTERLAG__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterLag = R\"(\n\\subsection{TimeLag}\nLag operator in digital filter representation.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Digital lag filter.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterLag : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterLag(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterLag::DigitalFilterLag(Config &config)\n{\n  try\n  {\n    Int lag;\n\n    readConfig(config, \"lag\",               lag,               Config::MUSTSET,  \"\",  \"lag epochs: 1 (lag); -1 (lead)\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    an = Vector(1, 1.);\n    bn = Vector(2*(std::abs(lag))+1);\n    bn(std::abs(lag)+lag) = 1.0;\n    bnStartIndex = bn.rows()/2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterMedian.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterMedian.h\n*\n* @brief Moving median filter implementation.\n*\n* @author Andreas Kvas\n* @date 2017-02-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERMEDIAN__\n#define __GROOPS_DIGITALFILTERMEDIAN__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterMedian = R\"(\n\\subsection{Median}\nMoving median filter of length $n$. The filter output at epoch $k$ is the median of the set start at $k-n/2$ to $k+n/2$.\nThe filter length $n$ should be uneven to avoid a phase shift.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Moving median filter implementation.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterMedian : public DigitalFilterBase\n{\n  UInt    length;\n  PadType padType;\n\npublic:\n  DigitalFilterMedian(Config &config);\n\n  Matrix filter(const_MatrixSliceRef input) const;\n  std::vector< std::complex<Double> > frequencyResponse(UInt length) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterMedian::DigitalFilterMedian(Config &config)\n{\n  try\n  {\n    readConfig(config, \"length\",  length,  Config::MUSTSET, \"\", \"length of the moving window [epochs]\");\n    readConfig(config, \"padType\", padType, Config::MUSTSET, \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix DigitalFilterMedian::filter(const_MatrixSliceRef input) const\n{\n  try\n  {\n    Matrix padded = pad(input, length/2, 0, padType);\n    Matrix output(padded.rows(), padded.columns());\n\n    for(UInt k=0; k<output.columns(); k++)\n      for(UInt i=0; i<output.rows(); i++)\n      {\n        const UInt start = std::max(i,length/2)-length/2;\n        const UInt end   = std::min(padded.rows(), i+(length+1)/2);\n        output(i,k) = median(padded.slice(start, k, end-start, 1));\n      }\n\n    return trim(output, length/2, 0, padType);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector< std::complex<Double> > DigitalFilterMedian::frequencyResponse(UInt /*length*/) const\n{\n  throw(Exception(\"Median filter cannot be represented by frequency response.\"));\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterMovingAverage.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterMovingAverage.h\n*\n* @brief Moving average (boxcar) filter.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERMOVINGAVERAGE__\n#define __GROOPS_DIGITALFILTERMOVINGAVERAGE__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterMovingAverage = R\"(\n\\subsection{MovingAverage}\nMoving average (boxcar) filter. For odd lengths, this filter is symmetric and has therefore no phase shift. For even lengths, a phase shift of half a cycle is introduced.\n\n\\[\n  y_n = \\sum_{k=-\\lfloor\\frac{P}{2}\\rfloor}^{\\lfloor\\frac{P}{2}\\rfloor} \\frac{1}{P}x_{n-k}\n\\]\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Moving average (boxcar) filter.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterMovingAverage : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterMovingAverage(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterMovingAverage::DigitalFilterMovingAverage(Config &config)\n{\n  try\n  {\n    UInt length;\n\n    readConfig(config, \"length\",            length,            Config::MUSTSET, \"\", \"number of epochs in averaging operator\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    an = Vector(1, 1.);\n    bn = Vector(length);\n    for(UInt k = 0; k<bn.rows(); k++)\n      bn(k) = 1./length;\n    bnStartIndex = bn.rows()/2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterNotch.cpp",
    "content": "/***********************************************/\n/**\n* @file DigitalFilterNotch.cpp\n*\n* Implemented after Sophocles J. Orfanidis, \"Introduction To Signal Processing\", 2009.\n*\n* @brief Notch filter.\n*\n* @author Andreas Kvas\n* @date 2017-02-07\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/fourier.h\"\n#include \"classes/digitalFilter/digitalFilterNotch.h\"\n#include \"files/fileMatrix.h\"\n\n/***********************************************/\n\nDigitalFilterNotch::DigitalFilterNotch(Config& config)\n{\n  try\n  {\n    Double w0;   // normalized notch frequency\n    Double bw;   // bandwidth at -3db\n\n    readConfig(config, \"notchFrequency\",    w0,                Config::MUSTSET,  \"\",  \"normalized notch frequency w_n = (f_n/f_nyq)\");\n    readConfig(config, \"bandWidth\",         bw,                Config::MUSTSET,  \"\",  \"bandwidth at -3db. Quality factor of filter Q = w_n/bw\");\n    readConfig(config, \"backwardDirection\", backward,          Config::DEFAULT,  \"0\", \"apply filter in backward direction\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    w0 *= PI;\n    bw *= PI;\n\n    Double gb = 1/std::sqrt(2); // |H(w)|^2 = 1/2, p. 575 11.3.1\n\n    Double beta = (std::sqrt(1.0-gb*gb)/gb)*std::tan(bw/2.0); // p. 575 11.3.4\n    Double gain = 1.0/(1.0+beta); // p. 575 11.3.6\n\n    bn = Vector(3, gain);\n    bn(1) = -2.0*std::cos(w0)*gain; // bn = gain*[1.0, -2*cos(w0), 1.0], p. 575 11.3.7\n    bnStartIndex = 0;\n\n    an = Vector(3, 1.0);\n    an(1) = -2.0*gain*std::cos(w0);\n    an(2) = 2.0*gain-1.0; // an = [1.0, -2*gain*cos(w0), 2*gain-1.0], p. 575 11.3.7\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterNotch.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterNotch.h\n*\n* @brief Notch filter.\n*\n* Implemented af Christian Siemes' dissertation, page 106.\n*\n* @author Andreas Kvas\n* @date 2016-06-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERNOTCH__\n#define __GROOPS_DIGITALFILTERNOTCH__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterNotch = R\"(\n\\subsection{Notch}\nImplemented after Christian Siemes' dissertation, page 106.\n\n\\fig{!hb}{0.6}{DigitalFilter_notch}{fig:DigitalFilterNotch}{Amplitude response of a notch filter of order three with default settings.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Butterworth filter.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterNotch : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterNotch(Config &config);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterReduceFilterOutput.h",
    "content": "/***********************************************/\n/**\n* @file DigitalFilterReduceFilterOutput.h\n*\n* @brief Remove filtered result from signal.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-09\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERONEMINUS__\n#define __GROOPS_DIGITALFILTERONEMINUS__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterReduceFilterOutput = R\"(\n\\subsection{ReduceFilterOutput}\nRemoves the filtered signal from the input, i.e. the input is passed\nthrough a \\configClass{digitalFilter}{digitalFilterType} with a frequency response of $1-H(f)$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Remove filtered result from signal.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterReduceFilterOutput : public DigitalFilterBase\n{\n  DigitalFilterPtr filter2;\n\npublic:\n  DigitalFilterReduceFilterOutput(Config &config);\n\n  Matrix filter(const_MatrixSliceRef input) const;\n  std::vector<std::complex<Double>> frequencyResponse(UInt length) const;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterReduceFilterOutput::DigitalFilterReduceFilterOutput(Config &config)\n{\n  try\n  {\n    readConfig(config, \"filter\", filter2, Config::MUSTSET, \"\", \"remove filter output from input signal\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix DigitalFilterReduceFilterOutput::filter(const_MatrixSliceRef input) const\n{\n  try\n  {\n    return input - filter2->filter(input);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<std::complex<Double>> DigitalFilterReduceFilterOutput::frequencyResponse(UInt length) const\n{\n  auto H = filter2->frequencyResponse(length);\n  for(UInt i=0; i<H.size(); i++)\n    H.at(i) = 1.-H.at(i);\n  return H;\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/digitalFilter/digitalFilterWavelet.h",
    "content": "/***********************************************/\n/**\n* @file digitalFilterWavelet.h\n*\n* @brief Filter representation of a wavelet.\n*\n* @author Andreas Kvas\n* @date 2017-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DIGITALFILTERWAVELET__\n#define __GROOPS_DIGITALFILTERWAVELET__\n\n// Latex documentation\n#ifdef DOCSTRING_DigitalFilter\nstatic const char *docstringDigitalFilterWavelet = R\"(\n\\subsection{Wavelet}\nFilter representation of a wavelet.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/wavelets.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Filter representation of a wavelet.\n* @ingroup digitalFilterGroup\n* @see DigitalFilter */\nclass DigitalFilterWavelet : public DigitalFilterARMA\n{\npublic:\n  DigitalFilterWavelet(Config &config);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline DigitalFilterWavelet::DigitalFilterWavelet(Config& config)\n{\n  try\n  {\n    FileName fileNameWavelet;\n    Bool     islowpass = TRUE;\n    UInt     level;\n\n    readConfig(config, \"inputfileWavelet\", fileNameWavelet, Config::MUSTSET, \"{groopsDataDir}/wavelets/\", \"wavelet coefficients\");\n    std::string choice;\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"filter type\"))\n    {\n      if(readConfigChoiceElement(config, \"lowpass\",  choice)) islowpass = TRUE;\n      if(readConfigChoiceElement(config, \"highpass\", choice)) islowpass = FALSE;\n      endChoice(config);\n    }\n    readConfig(config, \"level\",             level,             Config::DEFAULT,  \"0\", \"compute filter for specific decomposition level\");\n    readConfig(config, \"backwardDirection\", backward,          Config::DEFAULT,  \"0\", \"apply filter in backward direction\");\n    readConfig(config, \"inFrequencyDomain\", inFrequencyDomain, Config::DEFAULT,  \"0\", \"apply filter in frequency domain\");\n    readConfig(config, \"padType\",           padType,           Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    Vector wl;\n    readFileMatrix(fileNameWavelet, wl);\n    const Vector hn = (islowpass) ? Wavelets::lowpass(wl) : Wavelets::highpass(wl);\n    const UInt upsamplingFactor = static_cast<UInt>(1)<<level;\n\n    // set numerator and denominator polynomials\n    an = Vector(1, 1.);\n    bn = Vector(hn.rows() * upsamplingFactor);\n    for(UInt k = 0; k < hn.rows(); k++)\n      bn(k * upsamplingFactor) = hn(k);\n    bnStartIndex = 0; // causal filter\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotation.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotation.cpp\n*\n* @brief Transformation between CRF and TRF.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-11-12\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_EarthRotation\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/configRegister.h\"\n#include \"classes/earthRotation/earthRotationFile.h\"\n#include \"classes/earthRotation/earthRotationIers2010.h\"\n#include \"classes/earthRotation/earthRotationIers2010b.h\"\n#include \"classes/earthRotation/earthRotationIers2003.h\"\n#include \"classes/earthRotation/earthRotationIers1996.h\"\n#include \"classes/earthRotation/earthRotationGmst.h\"\n#include \"classes/earthRotation/earthRotationEra.h\"\n#include \"classes/earthRotation/earthRotationZAxis.h\"\n#include \"classes/earthRotation/moonRotation.h\"\n#include \"classes/earthRotation/earthRotationStarCamera.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(EarthRotation, \"earthRotationType\",\n                      EarthRotationFile,\n                      EarthRotationIers2010,\n                      EarthRotationIers2010b,\n                      EarthRotationIers2003,\n                      EarthRotationIers1996,\n                      EarthRotationGmst,\n                      EarthRotationEra,\n                      EarthRotationZAxis,\n                      EarthRotationStarCamera,\n                      MoonRotation)\n\nGROOPS_READCONFIG_CLASS(EarthRotation, \"earthRotationType\")\n\n/***********************************************/\n\nEarthRotationPtr EarthRotation::create(Config &config, const std::string &name)\n{\n  try\n  {\n    EarthRotationPtr earthRotation;\n    std::string choice;\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"transformation from CRF to TRF\");\n\n    renameDeprecatedChoice(config, choice, \"itrf2010\",  \"iers2010\",  date2time(2020, 8, 24));\n    renameDeprecatedChoice(config, choice, \"itrf2010b\", \"iers2010b\", date2time(2020, 8, 24));\n    renameDeprecatedChoice(config, choice, \"itrf2003\",  \"iers2003\",  date2time(2020, 8, 24));\n\n    if(readConfigChoiceElement(config, \"file\",     choice, \"interpolated values from file\"))\n      earthRotation = EarthRotationPtr(new EarthRotationFile(config));\n    if(readConfigChoiceElement(config, \"iers2010\",  choice, \"IERS conventions 2010\"))\n      earthRotation = EarthRotationPtr(new EarthRotationIers2010(config));\n    if(readConfigChoiceElement(config, \"iers2010b\", choice, \"IERS conventions 2010 with HF EOP model\"))\n      earthRotation = EarthRotationPtr(new EarthRotationIers2010b(config));\n    if(readConfigChoiceElement(config, \"iers2003\",  choice, \"IERS conventions 2003\"))\n      earthRotation = EarthRotationPtr(new EarthRotationIers2003(config));\n    if(readConfigChoiceElement(config, \"itrf1996\", choice, \"IERS conventions 1996\"))\n      earthRotation = EarthRotationPtr(new EarthRotationIers1996(config));\n    if(readConfigChoiceElement(config, \"gmst\",     choice, \"z-Axis rotation with gmst\"))\n      earthRotation = EarthRotationPtr(new EarthRotationGmst(config));\n    if(readConfigChoiceElement(config, \"era\",     choice, \"z-Axis rotation with earth rotation angle (ERA)\"))\n      earthRotation = EarthRotationPtr(new EarthRotationEra(config));\n    if(readConfigChoiceElement(config, \"zAxis\",    choice, \"z-Axis rotation\"))\n      earthRotation = EarthRotationPtr(new EarthRotationZAxis(config));\n    if(readConfigChoiceElement(config, \"starCamera\", choice, \"earth rotation from instrument file\"))\n      earthRotation = EarthRotationPtr(new EarthRotationStarCamera(config));\n    if(readConfigChoiceElement(config, \"moonRotation\", choice, \"Libration angles (Moon)\"))\n      earthRotation = EarthRotationPtr(new MoonRotation(config));\n    endChoice(config);\n\n    return earthRotation;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d EarthRotation::rotaryMatrix(const Time &timeGPS) const\n{\n  try\n  {\n    Double xp, yp, sp, deltaUT, LOD, X, Y, S;\n    earthOrientationParameter(timeGPS, xp, yp, sp, deltaUT, LOD, X, Y, S);\n\n    const Double ERA = Planets::ERA(timeGPS2UTC(timeGPS) + seconds2time(deltaUT));\n    const Double r2  = X*X + Y*Y;\n    const Double E   = (r2 != 0.) ? std::atan2(Y, X) : 0.;\n    const Double D   = std::atan(std::sqrt(r2/(1-r2)));\n\n    return  rotaryX(Angle(-yp)) * rotaryY(Angle(-xp)) *\n            rotaryZ(Angle(sp+ERA-S-E)) *\n            rotaryY(Angle(D)) * rotaryZ(Angle(E));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d EarthRotation::rotaryAxis(const Time &timeGPS) const\n{\n  try\n  {\n    const UInt   degree = 8;\n    const Double dt     = 30*60; // 30 min\n    std::vector<Rotary3d> rot(degree+1);\n\n    try\n    {\n      for(UInt i=0; i<=degree; i++)\n        rot.at(i) = rotaryMatrix(timeGPS + seconds2time((i-degree/2.)*dt));\n    }\n    catch(std::exception &/*e*/)\n    {\n      // if time series is too short, use simplified equations\n      Double xp, yp, sp, deltaUT, LOD, X, Y, S;\n      earthOrientationParameter(timeGPS, xp, yp, sp, deltaUT, LOD, X, Y, S);\n      const Double r2  = X*X + Y*Y;\n      const Double E   = (r2 != 0.) ? std::atan2(Y, X) : 0.;\n      const Double D   = std::atan(std::sqrt(r2/(1-r2)));\n      return rotaryZ(Angle(-E)).rotate(rotaryY(Angle(-D)).rotate(Vector3d(0, 0, 72921151.467064e-12*(1-LOD/86400))));\n    }\n\n    Rotary3d rot0 = inverse(rot.at(degree/2));\n    for(UInt i=0; i<=degree; i++)\n      rot.at(i) = rot0*rot.at(i);\n\n    std::vector<Double> coeff = {1./280, -4./105, 1./5., -4./5., 0, 4./5., -1./5., 4./105., -1./280};\n    Vector3d omega;\n    for(UInt i=0; i<coeff.size(); i++)\n    {\n      const Matrix R = rot.at(i).matrix();\n      omega.x() += coeff[i] * (R(1,2)-R(2,1));\n      omega.y() += coeff[i] * (R(2,0)-R(0,2));\n      omega.z() += coeff[i] * (R(0,1)-R(1,0));\n    }\n\n    return 0.5/dt * omega;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d EarthRotation::rotaryAxisDerivate(const Time &timeGPS) const\n{\n  const Double dt = 30*60; // 30 min\n  return 0.5/dt * (rotaryAxis(timeGPS+seconds2time(dt))-rotaryAxis(timeGPS-seconds2time(dt)));\n}\n\n/***********************************************/\n\nvoid EarthRotation::earthOrientationParameter(const Time &/*timeGPS*/, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const\n{\n  xp = yp = sp = deltaUT = LOD = X = Y = S = 0.0;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotation.h",
    "content": "/***********************************************/\n/**\n* @file earthRotation.h\n*\n* @brief Transformation between CRF and TRF.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-11-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATION__\n#define __GROOPS_EARTHROTATION__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotation = R\"(\n\\section{EarthRotation}\\label{earthRotationType}\nThis class realize the transformation between a terestrial\nreference frame (TRF) and a celestial reference frame (CRF).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup earthRotationGroup EarthRotation\n* @brief Transformation between CRF and TRF.\n* @ingroup classesGroup\n* The interface is given by @ref EarthRotation. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass EarthRotation;\ntypedef std::shared_ptr<EarthRotation> EarthRotationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Transformation between CRF and TRF.\n* An Instance of this class can be created by @ref readConfig. */\nclass EarthRotation\n{\npublic:\n  /// Destructor.\n  virtual ~EarthRotation() {}\n\n  /** @brief Rotary matrix.\n  * Inertial system (CRF) -> earth fixed system (TRF).\n  * @param timeGPS modified julian date (MJD) in GPS time system. */\n  virtual Rotary3d rotaryMatrix(const Time &timeGPS) const;\n\n  /** @brief Instantaneous rotation vector of Earth rotation.\n  * Contains the complete rotation with precession, nutation, polar wobble.\n  * Given in inertial system (CRF). [rad/s].\n  * @param timeGPS modified julian date (MJD) in GPS time system. */\n  virtual Vector3d rotaryAxis(const Time &timeGPS) const;\n\n  /** @brief Time derivative of the instantaneous rotation vector.\n  * Given in inertial system (CRF). [rad/s^2].\n  * @param timeGPS modified julian date (MJD) in GPS time system. */\n  virtual Vector3d rotaryAxisDerivate(const Time &timeGPS)  const;\n\n  /** @brief Earth orientation parameter.\n  * All models and corrections applied.\n  * @param timeGPS modified julian date (MJD) in GPS time system.\n  * @param[out] xp polar motion [rad]\n  * @param[out] yp polar motion [rad]\n  * @param[out] sp TIO locator [rad]\n  * @param[out] deltaUT UT1-UTC [seconds]\n  * @param[out] LOD length of day [seconds]\n  * @param[out] X precession & nutation [rad]\n  * @param[out] Y precession & nutation [rad]\n  * @param[out] S CIO locator [rad]. */\n  virtual void earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const;\n\n  /** @brief creates an derived instance of this class. */\n  static EarthRotationPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class EarthRotation.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a earthRotation is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] earthRotation Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates EarthRotation */\ntemplate<> Bool readConfig(Config &config, const std::string &name, EarthRotationPtr &earthRotation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationEra.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationEra.h\n*\n* @brief Simple rotation about z-axis (ERA).\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-11-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONERA__\n#define __GROOPS_EARTHROTATIONERA__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationEra = R\"(\n\\subsection{Earth Rotation Angle (ERA)}\nThe transformation is realized as rotation about the z-axis.\nThe angle ist given by the Earth Rotation Angle (ERA) as\n\\begin{verbatim}\n  const Time T = timeUT1-mjd2time(J2000);\n  ERA = fmod(2*PI*(0.7790572732640 + T.mjdMod() + 0.00273781191135448*T.mjd()), 2*PI);\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/planets.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simple rotation about z-axis (ERA).\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationEra : public EarthRotation\n{\npublic:\n  inline EarthRotationEra(Config &config);\n\n  inline Rotary3d rotaryMatrix (const Time &timeGPS) const;\n  inline Vector3d rotaryAxis   (const Time &timeGPS) const;\n  inline Vector3d rotaryAxisDerivate(const Time &timeGPS) const;\n};\n\n/***********************************************/\n\ninline EarthRotationEra::EarthRotationEra(Config &/*config*/)\n{\n}\n\n/***********************************************/\n\ninline Rotary3d EarthRotationEra::rotaryMatrix(const Time &timeGPS) const\n{\n  return rotaryZ(Angle(Planets::ERA(timeGPS2UTC(timeGPS))));\n}\n\n/***********************************************/\n\ninline Vector3d EarthRotationEra::rotaryAxis(const Time &/*timeGPS*/) const\n{\n  return Vector3d(0.0, 0.0, 2*PI*1.00273781191135448/86400);\n}\n\n/***********************************************/\n\ninline Vector3d EarthRotationEra::rotaryAxisDerivate(const Time &/*timeGPS*/) const\n{\n  return Vector3d(0.0, 0.0, 0.0);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationFile.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotationFile.cpp\n*\n* @brief Interpolated values from file.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-05-26\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/earthRotation/earthRotationFile.h\"\n\n/***********************************************/\n\nEarthRotationFile::EarthRotationFile(Config &config)\n{\n  try\n  {\n    FileName fileNameEOP;\n    UInt     interpolationDegree;\n\n    readConfig(config, \"inputfileEOP\",        fileNameEOP,         Config::MUSTSET,  \"{groopsDataDir}/earthRotation/timeSeries_EOP_rapid_IAU2000_desai.dat\", \"\");\n    readConfig(config, \"interpolationDegree\", interpolationDegree, Config::DEFAULT,  \"3\", \"for polynomial interpolation\");\n    if(isCreateSchema(config)) return;\n\n    readFileMatrix(fileNameEOP, EOP);\n\n    std::vector<Time> times(EOP.rows());\n    for(UInt i=0; i<times.size(); i++)\n      times.at(i) = mjd2time(EOP(i,0));\n\n    // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n    for(UInt i=0; i<times.size(); i++)\n      EOP(i,4) -= (times.at(i)-timeGPS2UTC(times.at(i))).seconds();\n\n    polynomial.init(times, interpolationDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid EarthRotationFile::earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp,\n                                                  Double &dUT1, Double &LOD, Double &X, Double &Y, Double &S) const\n{\n  try\n  {\n    Matrix eop = polynomial.interpolate({timeGPS}, EOP);\n    xp   = eop(0,1);\n    yp   = eop(0,2);\n    sp   = eop(0,3);\n    dUT1 = eop(0,4) + (timeGPS-timeGPS2UTC(timeGPS)).seconds();\n    LOD  = eop(0,5);\n    X    = eop(0,6);\n    Y    = eop(0,7);\n    S    = eop(0,8);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationFile.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationFile.h\n*\n* @brief Interpolated values from file.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONFILE__\n#define __GROOPS_EARTHROTATIONFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationFile = R\"(\n\\subsection{File}\\label{earthRotationType:file}\nThis class realize the transformation by interpolation from file.\nThis file can be created with \\program{EarthOrientationParameterTimeSeries}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief According to IERS2010 conventions.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationFile : public EarthRotation\n{\n  Polynomial        polynomial;\n  Matrix            EOP;\n\npublic:\n  EarthRotationFile(Config &config);\n\n  void earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationGmst.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationGmst.h\n*\n* @brief Simple rotation about z-axis (GMST).\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-12-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONGMST__\n#define __GROOPS_EARTHROTATIONGMST__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationGmst = R\"(\n\\subsection{Gmst}\nThe transformation is realized as rotation about the z-axis.\nThe angle ist given by the Greenwich Mean Siderial Time (GMST).\n\\begin{verbatim}\n  Double Tu0 = (timeUTC.mjdInt()-51544.5)/36525.0;\n\n  Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))\n               + (8640184.812866/(24*60*60))*Tu0\n               + (0.093104/(24*60*60))*Tu0*Tu0\n               + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;\n  Double r = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;\n  GMST = fmod(2*PI*(GMST0 + r * timeUTC.mjdMod()), 2*PI);\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/planets.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simple rotation about z-axis (GMST).\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationGmst : public EarthRotation\n{\npublic:\n  inline EarthRotationGmst(Config &config);\n\n  inline Rotary3d rotaryMatrix (const Time &timeGPS) const;\n  inline Vector3d rotaryAxis   (const Time &timeGPS) const;\n  inline Vector3d rotaryAxisDerivate(const Time &timeGPS) const;\n};\n\n/***********************************************/\n\ninline EarthRotationGmst::EarthRotationGmst(Config &/*config*/)\n{\n}\n\n/***********************************************/\n\ninline Rotary3d EarthRotationGmst::rotaryMatrix(const Time &timeGPS) const\n{\n  return rotaryZ(Angle(Planets::gmst(timeGPS2UTC(timeGPS))));\n}\n\n/***********************************************/\n\ninline Vector3d EarthRotationGmst::rotaryAxis(const Time &/*timeGPS*/) const\n{\n  return Vector3d(0., 0., 2*PI*1.002737909350795/86400);\n}\n\n/***********************************************/\n\ninline Vector3d EarthRotationGmst::rotaryAxisDerivate(const Time &/*timeGPS*/) const\n{\n  return Vector3d(0., 0., 0.);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers1996.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers1996.cpp\n*\n* @brief According to IERS1996 conventions.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"base/planets.h\"\n#include \"external/iers/iers.h\"\n#include \"config/config.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/earthRotation/earthRotationIers1996.h\"\n\n/***********************************************/\n\nEarthRotationIers1996::EarthRotationIers1996(Config &config)\n{\n  try\n  {\n    FileName eopName, nutationName;\n    readConfig(config, \"inputfileEOP\",      eopName,      Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileNutation\", nutationName, Config::MUSTSET,  \"{groopsDataDir}/earthRotation/nutationIAU1980.xml\", \"\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_IERS\n    logWarningOnce<<\"Compiled without IERS sources -> ocean tidal effects in EOP are not calculated\"<<Log::endl;\n#endif\n\n    // read Earth Orientation Parameter (EOP)\n    // --------------------------------------\n    if(!eopName.empty())\n    {\n      InFileArchive eopFile(eopName, \"\", FILE_BASE_VERSION);\n      UInt eopCount;\n      eopFile>>nameValue(\"count\", eopCount);\n      std::vector<Time> times(eopCount);\n      EOP = Matrix(eopCount, 7);\n      Double mjd;\n      for(UInt i=0; i<eopCount; i++)\n      {\n        eopFile>>beginGroup(\"eop\");\n        eopFile>>nameValue(\"mjd\", mjd);\n        times.at(i) = mjd2time(mjd);\n        eopFile>>nameValue(\"xp\",       EOP(i,0));\n        eopFile>>nameValue(\"yp\",       EOP(i,1));\n        eopFile>>nameValue(\"deltaUT\",  EOP(i,2));\n        eopFile>>nameValue(\"lod\",      EOP(i,3));\n        eopFile>>nameValue(\"deltaPsi\", EOP(i,4));\n        eopFile>>nameValue(\"deltaEps\", EOP(i,5));\n        eopFile>>endGroup(\"eop\");\n      }\n\n      // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n      for(UInt i=0; i<eopCount; i++)\n        EOP(i,2) -= (timeUTC2GPS(times.at(i))-times.at(i)).seconds();\n\n      EOP.column(0) *= DEG2RAD/3600; // xp\n      EOP.column(1) *= DEG2RAD/3600; // yp\n      EOP.column(4) *= DEG2RAD/3600; // dPsi\n      EOP.column(5) *= DEG2RAD/3600; // dEps\n\n      polynomial.init(times, 3);\n    }\n\n    // Nutationsserie einlesen\n    // -----------------------\n    InFileArchive nutationFile(nutationName, \"\", FILE_BASE_VERSION);\n    UInt nutationCount;\n    nutationFile>>nameValue(\"count\", nutationCount);\n    argument  = Matrix(nutationCount, 5);\n    psiFactor = Matrix(nutationCount, 2);\n    epsFactor = Matrix(nutationCount, 2);\n\n    for(UInt i=0; i<nutationCount; i++)\n    {\n      nutationFile>>beginGroup(\"nutation\");\n      nutationFile>>nameValue(\"arg1\",argument(i,0))>>nameValue(\"arg2\",argument(i,1))>>nameValue(\"arg3\",argument(i,2))>>nameValue(\"arg4\",argument(i,3))>>nameValue(\"arg5\",argument(i,4));\n      nutationFile>>nameValue(\"A1\",psiFactor(i,0))>>nameValue(\"A2\",psiFactor(i,1));\n      nutationFile>>nameValue(\"B1\",epsFactor(i,0))>>nameValue(\"B2\",epsFactor(i,1));\n      nutationFile>>endGroup(\"nutation\");\n    }\n\n    psiFactor *= 1e-4*DEG2RAD/3600;\n    epsFactor *= 1e-4*DEG2RAD/3600;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d EarthRotationIers1996::rotaryMatrix(const Time &timeGPS) const\n{\n  // Erdrotationsparameter\n  Double xp, yp, deltaUT, LOD, ddpsi, ddeps;\n  eop(timeGPS, xp, yp, deltaUT, LOD, ddpsi, ddeps);\n\n  // The IAU 1980 Theroy of Nutation\n  Double dpsi, deps, Omega;\n  nutationIAU1980(timeGPS, dpsi, deps, Omega);\n  dpsi += ddpsi; // Korr. mit dpsi aus EOP\n  deps += ddeps;\n\n  const Double JC     = timeGPS2JC(timeGPS);\n  const Double zetaA  = (2306.2181*JC + 0.30188*JC*JC + 0.017998*JC*JC*JC)* DEG2RAD/3600;\n  const Double thetaA = (2004.3109*JC - 0.42665*JC*JC - 0.041883*JC*JC*JC)* DEG2RAD/3600;\n  const Double zA     = (2306.2181*JC + 1.09468*JC*JC + 0.018203*JC*JC*JC)* DEG2RAD/3600;\n  const Double epsA   = (84381.448 -46.8150*JC - 0.00059*JC*JC + 0.001813*JC*JC*JC) * DEG2RAD/3600;\n\n  // GST\n  const Double theta = GST(timeGPS2UTC(timeGPS)+seconds2time(deltaUT), dpsi, epsA, Omega);\n\n  return PolMatrix(xp,yp) *\n         RotMatrix(theta) *\n         NutationMatrix(epsA,dpsi,deps) *\n         PraezessionMatrix(zetaA,thetaA,zA);\n}\n\n/***********************************************/\n\nvoid EarthRotationIers1996::earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const\n{\n  Double ddpsi, ddeps;\n  eop(timeGPS, xp, yp, deltaUT, LOD, ddpsi, ddeps);\n  sp = 0;\n  X  = 0; // wrong: must transform from nutation1980 + dpsi,deps\n  Y  = 0;\n  S  = 0;\n}\n\n/***********************************************/\n\n// Erdrotationsparameter\nvoid EarthRotationIers1996::eop(const Time &timeGPS, Double &xp, Double &yp, Double &deltaUT, Double &LOD, Double &ddpsi, Double &ddeps) const\n{\n  try\n  {\n    // interpolate EOP file\n    // --------------------\n    xp = yp = deltaUT = LOD = 0;\n    ddpsi = ddeps = 0;\n    if(EOP.size())\n    {\n      const Time timeUTC = timeGPS2UTC(timeGPS);\n      Matrix eop = polynomial.interpolate({timeUTC}, EOP);\n      xp      = eop(0,0);\n      yp      = eop(0,1);\n      deltaUT = eop(0,2) + (timeGPS-timeUTC).seconds();\n      LOD     = eop(0,3);\n      ddpsi   = eop(0,4);\n      ddeps   = eop(0,5);\n    }\n\n#ifndef GROOPS_DISABLE_IERS\n    // Models\n    // ------\n    // diurnal and semidiurnal variations in EOP (x,y,UT1) from ocean tides\n    const Double mjdUTC = timeGPS2UTC(timeGPS).mjd();\n    Double corx=0, cory=0, cort=0;\n    ray(mjdUTC, corx, cory, cort);\n    xp      += corx * DEG2RAD/3600;\n    yp      += cory * DEG2RAD/3600;\n    deltaUT += cort;\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nDouble EarthRotationIers1996::GMST(const Time &timeUT1) const\n{\n  Double Tu0 = (timeUT1.mjdInt()-51544.5)/36525.0;\n\n  Double GMST0 = (6.0/24 + 41.0/(24*60) + 50.54841/(24*60*60))\n               + (8640184.812866/(24*60*60))*Tu0\n               + (0.093104/(24*60*60))*Tu0*Tu0\n               + (-6.2e-6/(24*60*60))*Tu0*Tu0*Tu0;\n  Double r     = 1.002737909350795 + 5.9006e-11*Tu0 - 5.9e-15*Tu0*Tu0;\n  return fmod(2*PI*(GMST0 + r * timeUT1.mjdMod()), 2*PI);\n}\n\n/***********************************************/\n\nDouble EarthRotationIers1996::GST(const Time &timeUT1, Double dpsi, Double epsA, Double Omega) const\n{\n  return fmod(GMST(timeUT1) + dpsi*cos(epsA)+0.00264*DEG2RAD/3600*sin(Omega)+0.000063*DEG2RAD/3600*sin(2*Omega), 2*PI);\n}\n\n/***********************************************/\n\nvoid EarthRotationIers1996::nutationIAU1980(const Time &timeGPS, Double &dpsi, Double &deps, Double &Omega) const\n{\n  const Double JC  = timeGPS2JC(timeGPS);\n  const Vector F   = Planets::fundamentals(timeGPS);\n  const Vector arg = argument * F;\n\n  Omega = F(4);\n  dpsi  = 0;\n  deps  = 0;\n  for(UInt i=0; i<argument.rows(); i++)\n  {\n    dpsi += (psiFactor(i,0)+psiFactor(i,1)*JC)*sin(arg(i));\n    deps += (epsFactor(i,0)+epsFactor(i,1)*JC)*cos(arg(i));\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nRotary3d EarthRotationIers1996::RotMatrix(Double GST) const\n{\n  return rotaryZ(Angle(GST));\n}\n\n/***********************************************/\n\nRotary3d EarthRotationIers1996::PolMatrix(Double xp, Double yp) const\n{\n  return rotaryY(Angle(-xp)) * rotaryX(Angle(-yp));\n}\n\n/***********************************************/\n\nRotary3d EarthRotationIers1996::PraezessionMatrix(Double zetaA, Double thetaA, Double zA) const\n{\n  return rotaryZ(Angle(-zA))*rotaryY(Angle(thetaA))*rotaryZ(Angle(-zetaA));\n}\n\n/***********************************************/\n\nRotary3d EarthRotationIers1996::NutationMatrix(Double epsA, Double dpsi, Double deps) const\n{\n  return rotaryX(Angle(-epsA-deps))*rotaryZ(Angle(-dpsi))*rotaryX(Angle(epsA));\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers1996.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers1996.h\n*\n* @brief According to IERS1996 conventions.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONIERS1996__\n#define __GROOPS_EARTHROTATIONIERS1996__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationIers1996 = R\"(\n\\subsection{Iers1996}\nVery old.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief According to IERS1996 conventions.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationIers1996 : public EarthRotation\n{\n  Polynomial        polynomial;\n  Matrix            EOP;\n  Matrix            argument, psiFactor, epsFactor; // nutation series\n\n  void     eop(const Time &timeGPS, Double &xp, Double &yp, Double &deltaUT, Double &LOD, Double &ddpsi, Double &ddeps) const;\n  Double   GST (const Time &timeUT1, Double dpsi, Double epsA, Double Omega) const;\n  Double   GMST(const Time &timeUT1)                                         const;\n  void     nutationIAU1980(const Time &timeGPS, Double &dpsi, Double &deps, Double &Omega) const;\n  Rotary3d RotMatrix(Double GST) const;\n  Rotary3d PolMatrix(Double xp, Double yp) const;\n  Rotary3d PraezessionMatrix(Double zetaA, Double thetaA, Double zA) const;\n  Rotary3d NutationMatrix(Double epsA, Double dpsi, Double deps) const;\n\npublic:\n  EarthRotationIers1996(Config &config);\n\n  Rotary3d rotaryMatrix(const Time &timeGPS) const;\n  void     earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers2003.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers2003.cpp\n*\n* @brief According to IERS2003 conventions.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"external/iers/iers.h\"\n#include \"config/config.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/earthRotation/earthRotationIers2003.h\"\n#ifndef GROOPS_DISABLE_ERFA\n#include <erfa.h>\n#endif\n\n/***********************************************/\n\nEarthRotationIers2003::EarthRotationIers2003(Config &config)\n{\n  try\n  {\n    FileName eopName;\n    readConfig(config, \"inputfileEOP\", eopName, Config::MUSTSET, \"{groopsDataDir}/earthRotation/EOP_20C04_IAU2000.txt\", \"\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_ERFA\n    throw(Exception(\"Compiled without ERFA library\"));\n#endif\n#ifdef GROOPS_DISABLE_IERS\n    logWarningOnce<<\"Compiled without IERS sources -> ocean tidal and libration effects in EOP are not calculated\"<<Log::endl;\n#endif\n\n    // read Earth Orientation Parameter (EOP)\n    // --------------------------------------\n    if(!eopName.empty())\n    {\n      readFileEarthOrientationParameter(eopName, EOP);\n      std::vector<Time> times(EOP.rows());\n      for(UInt i=0; i<times.size(); i++)\n        times.at(i) = mjd2time(EOP(i,0));\n      EOP = EOP.column(1, 6); // remove mjd\n\n      // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n      for(UInt i=0; i<EOP.rows(); i++)\n        EOP(i,2) -= (timeUTC2GPS(times.at(i))-times.at(i)).seconds();\n\n      EOP.column(0) *= DEG2RAD/3600; // xp\n      EOP.column(1) *= DEG2RAD/3600; // yp\n      EOP.column(4) *= DEG2RAD/3600; // dX\n      EOP.column(5) *= DEG2RAD/3600; // dY\n\n      polynomial.init(times, 3);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid EarthRotationIers2003::earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const\n{\n  try\n  {\n#ifdef GROOPS_DISABLE_ERFA\n    throw(Exception(\"Compiled without ERFA library\"));\n#else\n    // interpolate EOP file\n    // --------------------\n    xp = yp = deltaUT = LOD = 0;\n    Double dX=0, dY=0;\n    if(EOP.size())\n    {\n      const Time timeUTC = timeGPS2UTC(timeGPS);\n      Matrix eop = polynomial.interpolate({timeUTC}, EOP);\n      xp      = eop(0,0);\n      yp      = eop(0,1);\n      deltaUT = eop(0,2) + (timeGPS-timeUTC).seconds();\n      LOD     = eop(0,3);\n      dX      = eop(0,4);\n      dY      = eop(0,5);\n    }\n\n#ifndef GROOPS_DISABLE_IERS\n    // diurnal and semidiurnal variations in EOP (x,y,UT1) from ocean tides\n    const Double mjdUTC = timeGPS2UTC(timeGPS).mjd();\n    Double dxdydu[3];\n    ortho_eop(mjdUTC, dxdydu);\n    xp      += dxdydu[0]*1e-6*DEG2RAD/3600;\n    yp      += dxdydu[1]*1e-6*DEG2RAD/3600;\n    deltaUT += dxdydu[2]*1e-6;\n\n    Double pm[2];\n    pmsdnut(mjdUTC, pm);\n    xp += pm[0]*1e-6*DEG2RAD/3600;\n    yp += pm[1]*1e-6*DEG2RAD/3600;\n#endif\n    const Time timeTT = timeGPS2TT(timeGPS);\n    sp = eraSp00(2400000.5+timeTT.mjdInt(), timeTT.mjdMod());\n\n    // precession & nutation\n    eraXys00a(2400000.5, timeTT.mjd(), &X, &Y, &S);\n    X += dX;\n    Y += dY;\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers2003.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers2003.h\n*\n* @brief According to IERS2003 conventions.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONIERS2003__\n#define __GROOPS_EARTHROTATIONIERS2003__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationIers2003 = R\"(\n\\subsection{Iers2003}\nThis class realize the transformation according to IERS2003 conventions\ngiven by the \\emph{International Earth Rotation and Reference Systems Service} (IERS).\nA file with the earth orientation parameter is needed (\\configFile{inputfileEOP}{earthOrientationParameter}).\n\nThe following subroutines are used:\n\\begin{itemize}\n\\item BPN2000.f,\n\\item ERA2000.f,\n\\item pmsdnut.f,\n\\item POM2000.f,\n\\item SP2000.f,\n\\item T2C2000.f,\n\\item XYS2000A.f\n\\end{itemize}\nfrom \\url{ftp://maia.usno.navy.mil/conv2000/chapter5/} and\n\\begin{itemize}\n\\item orthoeop.f\n\\end{itemize}\nfrom \\url{ftp://maia.usno.navy.mil/conv2000/chapter8/}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief According to IERS2003 conventions.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationIers2003 : public EarthRotation\n{\n  Polynomial        polynomial;\n  Matrix            EOP;\n\npublic:\n  EarthRotationIers2003(Config &config);\n\n  void earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers2010.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers2010.cpp\n*\n* @brief According to IERS2010 conventions.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"external/iers/iers.h\"\n#include \"config/config.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/earthRotation/earthRotationIers2010.h\"\n#ifndef GROOPS_DISABLE_ERFA\n#include <erfa.h>\n#endif\n\n/***********************************************/\n\nEarthRotationIers2010::EarthRotationIers2010(Config &config)\n{\n  try\n  {\n    FileName eopName;\n    readConfig(config, \"inputfileEOP\",      eopName,       Config::OPTIONAL, \"{groopsDataDir}/earthRotation/EOP_20C04_IAU2000.txt\", \"\");\n    readConfig(config, \"truncatedNutation\", useTruncated,  Config::DEFAULT,  \"0\", \"use truncated nutation model (IAU2006B)\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_ERFA\n    throw(Exception(\"Compiled without ERFA library\"));\n#endif\n#ifdef GROOPS_DISABLE_IERS\n    logWarningOnce<<\"Compiled without IERS sources -> ocean tidal and libration effects in EOP are not calculated\"<<Log::endl;\n#endif\n\n    // read Earth Orientation Parameter (EOP)\n    // --------------------------------------\n    if(!eopName.empty())\n    {\n      readFileEarthOrientationParameter(eopName, EOP);\n      std::vector<Time> times(EOP.rows());\n      for(UInt i=0; i<times.size(); i++)\n        times.at(i) = mjd2time(EOP(i,0));\n      EOP = EOP.column(1, 6); // remove mjd\n\n      // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n      for(UInt i=0; i<EOP.rows(); i++)\n        EOP(i,2) -= (timeUTC2GPS(times.at(i))-times.at(i)).seconds();\n\n      EOP.column(0) *= DEG2RAD/3600; // xp\n      EOP.column(1) *= DEG2RAD/3600; // yp\n      EOP.column(4) *= DEG2RAD/3600; // dX\n      EOP.column(5) *= DEG2RAD/3600; // dY\n\n      polynomial.init(times, 3);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid EarthRotationIers2010::earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const\n{\n  try\n  {\n#ifdef GROOPS_DISABLE_ERFA\n    throw(Exception(\"Compiled without ERFA library\"));\n#else\n    // interpolate EOP file\n    // --------------------\n    xp = yp = deltaUT = LOD = 0;\n    Double dX=0, dY=0;\n    if(EOP.size())\n    {\n      const Time timeUTC = timeGPS2UTC(timeGPS);\n      Matrix eop = polynomial.interpolate({timeUTC}, EOP);\n      xp      = eop(0,0);\n      yp      = eop(0,1);\n      deltaUT = eop(0,2) + (timeGPS-timeUTC).seconds();\n      LOD     = eop(0,3);\n      dX      = eop(0,4);\n      dY      = eop(0,5);\n    }\n\n#ifndef GROOPS_DISABLE_IERS\n    // Models\n    // ------\n    // diurnal and semidiurnal variations in EOP (x,y,UT1) from ocean tides\n    const Double mjdUTC = timeGPS2UTC(timeGPS).mjd();\n    Double dxdydu[3];\n    ortho_eop(mjdUTC, dxdydu);\n    xp      += dxdydu[0]*1e-6*DEG2RAD/3600;\n    yp      += dxdydu[1]*1e-6*DEG2RAD/3600;\n    deltaUT += dxdydu[2]*1e-6;\n\n    Double pm[2];\n    pmsdnut2(mjdUTC, pm);\n    xp += pm[0]*1e-6*DEG2RAD/3600;\n    yp += pm[1]*1e-6*DEG2RAD/3600;\n\n    Double dut1, dlod;\n    utlibr(mjdUTC, dut1, dlod);\n    deltaUT += dut1*1e-6;\n    LOD     += dlod*1e-6;\n#endif\n\n    const Time timeTT = timeGPS2TT(timeGPS);\n    sp = eraSp00(2400000.5+timeTT.mjdInt(), timeTT.mjdMod());\n\n    // precession & nutation\n    X = Y = S =0;\n    if(useTruncated)\n      eraXys00b(2400000.5+timeTT.mjdInt(), timeTT.mjdMod(), &X, &Y, &S);\n    else\n    {\n      eraXy06   (2400000.5+timeTT.mjdInt(), timeTT.mjdMod(), &X, &Y);\n      S = eraS06(2400000.5+timeTT.mjdInt(), timeTT.mjdMod(), X, Y);\n    }\n    X += dX;\n    Y += dY;\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers2010.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers2010.h\n*\n* @brief According to IERS2010 conventions.\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONIERS2010__\n#define __GROOPS_EARTHROTATIONIERS2010__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationIers2010 = R\"(\n\\subsection{Iers2010}\nThis class realize the transformation according to the IERS2010 conventions\ngiven by the \\emph{International Earth Rotation and Reference Systems Service} (IERS).\nA file with the earth orientation parameter is needed (\\configFile{inputfileEOP}{earthOrientationParameter}).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief According to IERS2010 conventions.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationIers2010 : public EarthRotation\n{\n  Bool              useTruncated;\n  Polynomial        polynomial;\n  Matrix            EOP;\n\npublic:\n  EarthRotationIers2010(Config &config);\n\n  void earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers2010b.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers2010b.cpp\n*\n* @brief According to IERS2010 conventions (with HF EOP model).\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-05-15\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"external/iers/iers.h\"\n#include \"config/config.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n#include \"files/fileDoodsonEarthOrientationParameter.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/earthRotation/earthRotationIers2010b.h\"\n#ifndef GROOPS_DISABLE_ERFA\n#include <erfa.h>\n#endif\n\n/***********************************************/\n\nEarthRotationIers2010b::EarthRotationIers2010b(Config &config)\n{\n  try\n  {\n    FileName eopName, doodsonEopName;\n    readConfig(config, \"inputfileEOP\",        eopName,        Config::OPTIONAL,  \"{groopsDataDir}/earthRotation/EOP_20C04_IAU2000.txt\", \"\");\n    readConfig(config, \"inputfileDoodsonEOP\", doodsonEopName, Config::OPTIONAL,  \"{groopsDataDir}/earthRotation/doodsonEOP_desai_jgrb51665-sup-0002-ds01.txt\", \"\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_ERFA\n    throw(Exception(\"Compiled without ERFA library\"));\n#endif\n#ifdef GROOPS_DISABLE_IERS\n    logWarningOnce<<\"Compiled without IERS sources -> libration effects in EOP are not calculated\"<<Log::endl;\n#endif\n\n    // read Earth Orientation Parameter (EOP)\n    // --------------------------------------\n    if(!eopName.empty())\n    {\n      readFileEarthOrientationParameter(eopName, EOP);\n      std::vector<Time> times(EOP.rows());\n      for(UInt i=0; i<times.size(); i++)\n        times.at(i) = mjd2time(EOP(i,0));\n      EOP = EOP.column(1, 6); // remove mjd\n\n      // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n      for(UInt i=0; i<EOP.rows(); i++)\n        EOP(i,2) -= (timeUTC2GPS(times.at(i))-times.at(i)).seconds();\n\n      EOP.column(0) *= DEG2RAD/3600; // xp\n      EOP.column(1) *= DEG2RAD/3600; // yp\n      EOP.column(4) *= DEG2RAD/3600; // dX\n      EOP.column(5) *= DEG2RAD/3600; // dY\n\n      polynomial.init(times, 3);\n    }\n\n    // read high frequent EOP\n    // ----------------------\n    if(!doodsonEopName.empty())\n    {\n      readFileDoodsonEarthOrientationParameter(doodsonEopName, doodsonEop);\n      doodsonEop.coeff.column(0, 4) *= DEG2RAD/3600; // xp,yp   [arcsec -> radiant]\n      doodsonMatrix = Doodson::matrix(doodsonEop.doodson); // Matrix with Doodson multiplicators\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid EarthRotationIers2010b::earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const\n{\n  try\n  {\n#ifdef GROOPS_DISABLE_ERFA\n    throw(Exception(\"Compiled without ERFA library\"));\n#else\n    // interpolate EOP file\n    // --------------------\n    xp = yp = deltaUT = LOD = 0;\n    Double dX=0, dY=0;\n    if(EOP.size())\n    {\n      const Time timeUTC = timeGPS2UTC(timeGPS);\n      Matrix eop = polynomial.interpolate({timeUTC}, EOP);\n      xp      = eop(0,0);\n      yp      = eop(0,1);\n      deltaUT = eop(0,2) + (timeGPS-timeUTC).seconds();\n      LOD     = eop(0,3);\n      dX      = eop(0,4);\n      dY      = eop(0,5);\n    }\n\n    // Models\n    // ------\n    // diurnal and semidiurnal variations in EOP (x,y,UT1) from ocean tides\n    if(doodsonEop.doodson.size())\n    {\n      const Vector thetaf = doodsonMatrix * Doodson::arguments(timeGPS);\n      Matrix cosSin(thetaf.rows(),2);\n      for(UInt i=0; i<thetaf.rows(); i++)\n      {\n        cosSin(i, 0) = std::cos(thetaf(i));\n        cosSin(i, 1) = std::sin(thetaf(i));\n      }\n      xp      += inner(cosSin, doodsonEop.coeff.column(0, 2));\n      yp      += inner(cosSin, doodsonEop.coeff.column(2, 2));\n      deltaUT += inner(cosSin, doodsonEop.coeff.column(4, 2));\n      LOD     += inner(cosSin, doodsonEop.coeff.column(6, 2));\n    }\n\n#ifndef GROOPS_DISABLE_IERS\n    const Double mjdUTC = timeGPS2UTC(timeGPS).mjd();\n    Double pm[2];\n    pmsdnut2(mjdUTC, pm);\n    xp += pm[0]*1e-6*DEG2RAD/3600;\n    yp += pm[1]*1e-6*DEG2RAD/3600;\n\n    Double dut1, dlod;\n    utlibr(mjdUTC, dut1, dlod);\n    deltaUT += dut1*1e-6;\n    LOD     += dlod*1e-6;\n#endif\n\n    const Time timeTT = timeGPS2TT(timeGPS);\n    sp = eraSp00(2400000.5+timeTT.mjdInt(), timeTT.mjdMod());\n\n    // precession & nutation\n    X = Y = S =0;\n    eraXy06   (2400000.5+timeTT.mjdInt(), timeTT.mjdMod(), &X, &Y);\n    S = eraS06(2400000.5+timeTT.mjdInt(), timeTT.mjdMod(), X, Y);\n    X += dX;\n    Y += dY;\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationIers2010b.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationIers2010b.h\n*\n* @brief According to IERS2010 conventions (with HF EOP model).\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-05-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONIERS2010b__\n#define __GROOPS_EARTHROTATIONIERS2010b__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationIers2010b = R\"(\n\\subsection{Iers2010b}\\label{earthRotationType:iers2010b}\nThis class realize the transformation according to the IERS2010 conventions\ngiven by the \\emph{International Earth Rotation and Reference Systems Service} (IERS).\nA file with the earth orientation parameter is needed (\\configFile{inputfileEOP}{earthOrientationParameter}).\nIncludes additional high-frequency EOP models (\\configFile{inputfileDoodsonEOP}{doodsonEarthOrientationParameter}).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"files/fileDoodsonEarthOrientationParameter.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief According to IERS2010 conventions.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationIers2010b : public EarthRotation\n{\n  Polynomial        polynomial;\n  Matrix            EOP;\n  DoodsonEop        doodsonEop;\n  Matrix            doodsonMatrix;\n\npublic:\n  EarthRotationIers2010b(Config &config);\n\n  void earthOrientationParameter(const Time &timeGPS, Double &xp, Double &yp, Double &sp, Double &deltaUT, Double &LOD, Double &X, Double &Y, Double &S) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationStarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotationStarCamera.cpp\n*\n* @brief Earth rotation from quaternion (star camera) file.\n* @see EarthRotation\n*\n* @author Andreas Kvas\n* @date 2019-01-22\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/earthRotation/earthRotationStarCamera.h\"\n\n/***********************************************/\n\nEarthRotationStarCamera::EarthRotationStarCamera(Config &config)\n{\n  try\n  {\n    FileName fileNameStarCamera;\n    UInt polynomialDegree;\n    readConfig(config, \"inputfileStarCamera\", fileNameStarCamera, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"interpolationDegree\", polynomialDegree,   Config::DEFAULT,  \"1\", \"degree of interpolation polynomial\");\n    if(isCreateSchema(config)) return;\n\n    StarCameraArc arc = InstrumentFile::read(fileNameStarCamera);\n    quaternions = arc.matrix().column(1, 4);\n    polynomial.init(arc.times(), polynomialDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d EarthRotationStarCamera::rotaryMatrix(const Time &timeGPS) const\n{\n  try\n  {\n    Matrix q = polynomial.interpolate({timeGPS}, quaternions);\n    return Rotary3d(1./norm(q)*q.trans());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationStarCamera.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationStarCamera.h\n*\n* @brief Earth rotation from quaternion (star camera) file.\n* @see EarthRotation\n*\n* @author Andreas Kvas\n* @date 2019-01-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONSTARCAMAMERA__\n#define __GROOPS_EARTHROTATIONSTARCAMAMERA__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationStarCamera = R\"(\n\\subsection{StarCamera}\nThis class reads quaternions from an instrument file and interpolates to the given time stamp.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Earth rotation from quaternion input.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationStarCamera : public EarthRotation\n{\n  Polynomial polynomial;\n  Matrix     quaternions;\n\npublic:\n  EarthRotationStarCamera(Config &config);\n\n  void earthOrientationParameter(const Time &/*timeGPS*/, Double &/*xp*/, Double &/*yp*/, Double &/*sp*/, Double &/*deltaUT*/, Double &/*LOD*/, Double &/*X*/, Double &/*Y*/, Double &/*S*/) const { throw Exception(\"Earth orientation parameters can not be determined from quaterions alone.\");}\n  Rotary3d rotaryMatrix(const Time &timeGPS) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/earthRotationZAxis.h",
    "content": "/***********************************************/\n/**\n* @file earthRotationZAxis.h\n*\n* @brief Simple rotation about z-axis (GMST).\n* @see EarthRotation\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-11-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EARTHROTATIONZAXIS__\n#define __GROOPS_EARTHROTATIONZAXIS__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringEarthRotationZAxis = R\"(\n\\subsection{Z-Axis}\nThe transformation is realized as rotation about the z-axis.\nYou must specify the angle (\\config{initialAngle}) at \\config{time0} and\nthe angular velocity (\\config{angularVelocity}).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simple rotation about z-axis.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass EarthRotationZAxis : public EarthRotation\n{\n  Double    angle0;           // Drehwinkel zum Zeitpunkt 0 [rad]\n  Double    angleVelocity;    // Drehung pro Sekunde [rad/sek]\n  Time      time0;\n\npublic:\n  inline EarthRotationZAxis(Config &config);\n\n  inline Rotary3d rotaryMatrix (const Time &timeGPS) const;\n  inline Vector3d rotaryAxis   (const Time &timeGPS) const;\n  inline Vector3d rotaryAxisDerivate(const Time &timeGPS) const;\n};\n\n/***********************************************/\n\ninline EarthRotationZAxis::EarthRotationZAxis(Config &config)\n{\n  readConfig(config, \"initialAngle\",    angle0,        Config::MUSTSET, \"5.133658456\", \"Angle at time0 [rad]\");\n  readConfig(config, \"angularVelocity\", angleVelocity, Config::MUSTSET, \"7.29211585531e-5\", \"[rad/s]\");\n  readConfig(config, \"time0\",           time0,         Config::MUSTSET, \"51740.5\", \"\");\n  if(isCreateSchema(config)) return;\n}\n\n/***********************************************/\n\ninline Rotary3d EarthRotationZAxis::rotaryMatrix(const Time &timeGPS) const\n{\n  return rotaryZ(Angle(angle0 + angleVelocity*(timeGPS-time0).seconds()));\n}\n\n/***********************************************/\n\ninline Vector3d EarthRotationZAxis::rotaryAxis(const Time &/*timeGPS*/) const\n{\n  return Vector3d(0.0, 0.0, angleVelocity);\n}\n\n/***********************************************/\n\ninline Vector3d EarthRotationZAxis::rotaryAxisDerivate(const Time &/*timeGPS*/) const\n{\n  return Vector3d(0.0, 0.0, 0.0);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_EARTHROTATION__ */\n"
  },
  {
    "path": "source/classes/earthRotation/moonRotation.h",
    "content": "/***********************************************/\n/**\n* @file moonRotation.h\n*\n* @brief Moon rotation using libration angles.\n* @see EarthRotation\n*\n* @author Beate Klinger\n* @date 2013-01-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MOONROTATIONLIB__\n#define __GROOPS_MOONROTATIONLIB__\n\n// Latex documentation\n#ifdef DOCSTRING_EarthRotation\nstatic const char *docstringMoonRotation = R\"(\n\\subsection{MoonRotation}\nThis class realizes the transformation between the moon-fixed system\n(Principal Axis System (PA) or Mean Earth System (ME))\nand the ICRS according to the JPL ephemeris file.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileEphemerides.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Moon rotation using libration angles.\n* @ingroup earthRotationGroup\n* @see EarthRotation */\nclass MoonRotation : public EarthRotation\n{\n  FileName                  fileName;\n  mutable InFileEphemerides file;\n  Bool                      useME;\n\n  Rotary3d calcApproxLib(const Time &timeGPS) const;\n\npublic:\n  MoonRotation(Config &config);\n\n  Rotary3d rotaryMatrix(const Time &timeGPS) const;\n};\n\n/***********************************************/\n/***********************************************/\n\nMoonRotation::MoonRotation(Config &config)\n{\n  try\n  {\n    std::string choice;\n    useME = FALSE;\n\n    readConfig(config, \"inputfileEphemerides\", fileName, Config::OPTIONAL, \"{groopsDataDir}/tides/ephemerides_JPL_DE432.dat\", \"librations\");\n    if(readConfigChoice(config, \"moonfixedSystem\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"PA\", choice, \"Principal Axis System\")) {useME = FALSE;}\n      if(readConfigChoiceElement(config, \"ME\", choice, \"Mean Earth System\"))     {useME = TRUE;}\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    file.open(fileName);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Rotary3d MoonRotation::rotaryMatrix(const Time &timeGPS) const\n{\n  try\n  {\n    Rotary3d rot;\n    if(fileName.empty())\n    {\n      rot = calcApproxLib(timeGPS);\n    }\n    else\n    {\n      const Matrix A = file.interpolate(timeGPS, InFileEphemerides::LIBRATION);\n      rot = rotaryZ(Angle(A(2,0))) * rotaryX(Angle(A(1,0))) * rotaryZ(Angle(A(0,0)));\n    }\n\n    if(useME)\n      rot = rotaryX(Angle((-0.3/3600)*DEG2RAD)) * rotaryY(Angle((-78.56/3600)*DEG2RAD)) * rotaryZ(Angle((-67.92/3600)*DEG2RAD)) * rot;\n    return rot;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Rotary3d MoonRotation::calcApproxLib (const Time &timeGPS) const\n{\n  const Double d = timeGPS2TT(timeGPS).mjd()-J2000; // interval in days from standard epoch (J2000.0)\n  const Double T = d/36525;             // interval in Julian centuries (36525 days) from standard epoch\n\n  const Double E1  = (125.045*DEG2RAD) - ( 0.0529921*DEG2RAD)*d;\n  const Double E2  = (250.089*DEG2RAD) - ( 0.1059842*DEG2RAD)*d;\n  const Double E3  = (260.008*DEG2RAD) + (13.0120009*DEG2RAD)*d;\n  const Double E4  = (176.625*DEG2RAD) + (13.3407154*DEG2RAD)*d;\n  const Double E5  = (357.529*DEG2RAD) + ( 0.9856003*DEG2RAD)*d;\n  const Double E6  = (311.589*DEG2RAD) + (26.4057084*DEG2RAD)*d;\n  const Double E7  = (134.963*DEG2RAD) + (13.0649930*DEG2RAD)*d;\n  const Double E8  = (276.617*DEG2RAD) + ( 0.3287146*DEG2RAD)*d;\n  const Double E9  = ( 34.226*DEG2RAD) + ( 1.7484877*DEG2RAD)*d;\n  const Double E10 = ( 15.134*DEG2RAD) - ( 0.1589763*DEG2RAD)*d;\n  const Double E11 = (119.743*DEG2RAD) + ( 0.0036096*DEG2RAD)*d;\n  const Double E12 = (239.961*DEG2RAD) + ( 0.1643573*DEG2RAD)*d;\n  const Double E13 = ( 25.053*DEG2RAD) + (12.9590088*DEG2RAD)*d;\n\n  // ICRF equatoral coordinates at epoch J2000.0\n  const Double alpha0 = (269.9949*DEG2RAD) + (0.0031*DEG2RAD)*T - (3.8787*DEG2RAD)*sin(E1)\n                      - (0.1204*DEG2RAD)*sin(E2) + (0.0700*DEG2RAD)*sin(E3) - (0.0172*DEG2RAD)*sin(E4) + (0.0072*DEG2RAD)*sin(E6)\n                      - (0.0052*DEG2RAD)*sin(E10) + (0.0043*DEG2RAD)*sin(E13);\n\n  const Double delta0 = (66.5392*DEG2RAD) + (0.0130*DEG2RAD)*T + (1.5419*DEG2RAD)*cos(E1) + (0.0239*DEG2RAD)*cos(E2) - (0.0278*DEG2RAD)*cos(E3)\n                      + (0.0068*DEG2RAD)*cos(E4) - (0.0029*DEG2RAD)*cos(E6) + (0.0009*DEG2RAD)*cos(E7) + (0.0008*DEG2RAD)*cos(E10) - (0.0009*DEG2RAD)*cos(E13);\n\n\n  const Double W = (38.3213*DEG2RAD) + (13.17635815*DEG2RAD)*d - (1.4*pow(10,-12)*DEG2RAD)*pow(d,2) + (3.5610*DEG2RAD)*sin(E1) + (0.1208*DEG2RAD)*sin(E2)\n                 - (0.0642*DEG2RAD)*sin(E3) + (0.0158*DEG2RAD)*sin(E4) + (0.0252*DEG2RAD)*sin(E5) - (0.0066*DEG2RAD)*sin(E6) - (0.0047*DEG2RAD)*sin(E7)\n                 - (0.0046*DEG2RAD)*sin(E8) + (0.0028*DEG2RAD)*sin(E9) + (0.0052*DEG2RAD)*sin(E10) + (0.0040*DEG2RAD)*sin(E11) + (0.0019*DEG2RAD)*sin(E12) - (0.0044*DEG2RAD)*sin(E13);\n\n\n  return rotaryZ(Angle(W)) * rotaryX(Angle(PI/2-delta0)) * rotaryZ(Angle(alpha0+PI/2));  // Rotationsmatrix: ICRF >> ME\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAILMOONROTATIONLIB__ */\n"
  },
  {
    "path": "source/classes/eclipse/eclipse.cpp",
    "content": "/***********************************************/\n/**\n* @file eclipse.cpp\n*\n* @brief Shadowing of satellites by moon and Earth.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-03-08\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Eclipse\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/eclipse/eclipseConical.h\"\n#include \"classes/eclipse/eclipseSOLAARS.h\"\n#include \"classes/eclipse/eclipse.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Eclipse, \"eclipseType\",\n                      EclipseConical,\n                      EclipseSOLAARS)\n\nGROOPS_READCONFIG_CLASS(Eclipse, \"eclipseType\")\n\n/***********************************************/\n\nEclipsePtr Eclipse::create(Config &config, const std::string &name)\n{\n  try\n  {\n    EclipsePtr eclipse;\n    std::string choice;\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"Shadowing of satellites by moon and Earth\");\n\n    if(readConfigChoiceElement(config, \"conical\", choice, \"Umbra and penumbra shadow model\"))\n      eclipse = EclipsePtr(new EclipseConical(config));\n    if(readConfigChoiceElement(config, \"SOLAARS\", choice, \"Penumbra with Oblateness and Lower Atmospheric Absorption, Refraction, and Scattering\"))\n      eclipse = EclipsePtr(new EclipseSOLAARS(config));\n    endChoice(config);\n\n    return eclipse;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// For detailed information on this calculation, see Montenbruck and Gill (2000, pp. 80-83)\nDouble Eclipse::shadowScalingFactor(const Vector3d &posSat, const Vector3d &posSun, const Vector3d &posBody, const Double &radiusBody)\n{\n  try\n  {\n    const Double R_Sun       = 6.96342e8;\n    const Double distSatSun  = (posSat-posSun).r();\n    const Double distSatBody = (posSat-posBody).r();\n\n    // Apparent radius of Sun (a),\n    // apparent radius of occulting body (Earth, Moon) (b),\n    // apparent separation of the centers of both bodies (c)\n    const Double a = std::asin(R_Sun/distSatSun);\n    const Double b = std::asin(radiusBody/distSatBody);\n    const Double c = std::acos(inner(posBody-posSat, posSun-posSat)/(distSatBody*distSatSun));\n\n    // Satellite is not in occulting body's (Earth, Moon) shadow\n    if(a+b <= c)\n      return 1.;\n\n    // Satellite is in full occulting body's (Earth, Moon) shadow\n    if(std::fabs(a-b) > c)\n      return 0.;\n\n    // Satellite is in partial occulting body's (Earth, Moon) shadow\n    const Double x = (c*c+a*a-b*b)/(2*c);\n    const Double y = std::sqrt(a*a-x*x);\n    const Double A = a*a*std::acos(x/a)+b*b*std::acos((c-x)/b)-c*y; // Apparent visible area of the Sun\n    return 1-A/(PI*a*a);\n  }\n  catch (std::exception& e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/eclipse/eclipse.h",
    "content": "/***********************************************/\n/**\n* @file eclipse.h\n*\n* @brief Shadowing of satellites by moon and Earth.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-03-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ECLIPSE__\n#define __GROOPS_ECLIPSE__\n\n// Latex documentation\n#ifdef DOCSTRING_Eclipse\nstatic const char *docstringEclipse = R\"(\n\\section{Eclipse}\\label{eclipseType}\nShadowing of satellites by moon and Earth provided as factor\nbetween $[0,1]$ with 0: full shadow and 1: full sun light.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/**\n* @defgroup eclipseGroup Eclipse\n* @brief Shadowing of satellites by moon and Earth.\n* @ingroup classesGroup\n* The interface is given by @ref Eclipse. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Eclipse;\ntypedef std::shared_ptr<Eclipse> EclipsePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Shadowing of satellites by moon and Earth.\n* An Instance of this class can be created by @ref readConfig. */\nclass Eclipse\n{\npublic:\n  /// Destructor.\n  virtual ~Eclipse() {}\n\n  /** @brief Scaling factor for satellite during (Earth/Moon) shadow crossing.\n  * @param timeGPS  Modified julian date (MJD) in GPS time system.\n  * @param position Position of the satellite in celestial frame (CRF).\n  * @param ephemerides Position of Sun and Moon.\n  * @return Scaling factor [0..1] (0 = full shadow, 1 = no shadow, between 0 and 1 = partial shadow) */\n  virtual Double factor(const Time &timeGPS, const Vector3d &position, EphemeridesPtr ephemerides) const = 0;\n\n  /** @brief creates an derived instance of this class. */\n  static EclipsePtr create(Config &config, const std::string &name);\n\nprotected:\n  static Double shadowScalingFactor(const Vector3d &posSat, const Vector3d &posSun, const Vector3d &posBody, const Double &radiusBody);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Eclipse.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a eclipse is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] eclipse Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Eclipse */\ntemplate<> Bool readConfig(Config &config, const std::string &name, EclipsePtr &eclipse, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/eclipse/eclipseConical.h",
    "content": "/***********************************************/\n/**\n* @file eclipseConical.h\n*\n* @brief Shadowing of satellites by moon and Earth.\n* @see Eclipse\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-03-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ECLIPSECONICAL__\n#define __GROOPS_ECLIPSECONICAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Eclipse\nstatic const char *docstringEclipseConical = R\"(\n\\subsection{Conical}\n\\fig{!hb}{0.8}{eclipseConical}{fig:eclipseConical}{Modelling umbra and penumbra.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/eclipse/eclipse.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Shadowing of satellites by moon and Earth.\n* @ingroup eclipseGroup\n* @see Eclipse */\nclass EclipseConical : public Eclipse\n{\npublic:\n  EclipseConical(Config &/*config*/) {}\n\n  virtual Double factor(const Time &timeGPS, const Vector3d &position, EphemeridesPtr ephemerides) const override;\n};\n\n/***********************************************/\n\ninline Double EclipseConical::factor(const Time &timeGPS, const Vector3d &position, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    const Vector3d posSun   = ephemerides->position(timeGPS, Ephemerides::SUN);\n    const Vector3d posMoon  = ephemerides->position(timeGPS, Ephemerides::MOON);\n    return shadowScalingFactor(position, posSun, Vector3d(), R_Earth)\n         * shadowScalingFactor(position, posSun, posMoon,    R_Moon);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/eclipse/eclipseSOLAARS.h",
    "content": "/***********************************************/\n/**\n* @file eclipseSOLAARS.h\n*\n* @brief Shadowing of satellites by moon and Earth.\n* @see Eclipse\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-03-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ECLIPSESOLAARS__\n#define __GROOPS_ECLIPSESOLAARS__\n\n// Latex documentation\n#ifdef DOCSTRING_Eclipse\nstatic const char *docstringEclipseSOLAARS = R\"(\n\\subsection{SOLAARS}\nEarth’s penumbra modeling with Solar radiation pressure with\nOblateness and Lower Atmospheric Absorption, Refraction, and Scattering (SOLAARS).\nSee Robertson, Robbie. (2015),\nHighly Physical Solar Radiation Pressure Modeling During Penumbra Transitions (pp. 67-75).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/eclipse/eclipse.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Shadowing of satellites by moon and Earth.\n* @ingroup eclipseGroup\n* @see Eclipse */\nclass EclipseSOLAARS : public Eclipse\n{\npublic:\n  EclipseSOLAARS(Config &/*config*/) {}\n\n  virtual Double factor(const Time &timeGPS, const Vector3d &position, EphemeridesPtr ephemerides) const override;\n};\n\n/***********************************************/\n\ninline Double EclipseSOLAARS::factor(const Time &timeGPS, const Vector3d &position, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    const Vector3d posSun = ephemerides->position(timeGPS, Ephemerides::SUN);\n    Double factorSun      = shadowScalingFactor(position, posSun, Vector3d(), R_Earth+100e3);\n    Double factorMoon     = shadowScalingFactor(position, posSun, ephemerides->position(timeGPS, Ephemerides::MOON), R_Moon);\n    if(factorSun == 1.)\n      return factorSun * factorMoon;\n\n    // For detailed information on this calculation, see Robertson (2015, pp. 67-75)\n    const Vector3d R  = normalize(posSun);\n    const Double   rR = -1e-06 * inner(position, R); // in 1e6 meters\n    Vector3d r = position;\n    r.z() *= 6378137./6356752.; // account for flattening\n    const Double rE = 1e-6 * (r-R*inner(r, R)).r();\n\n    // model parameters\n    constexpr Double b11 =  0.1715;   constexpr Double b12 = -0.1423;    constexpr Double b13 =  0.01061; constexpr Double b14 = -0.01443;\n    constexpr Double b21 =  0.008162; constexpr Double b22 =  0.3401;\n    constexpr Double b31 =  260.9;    constexpr Double b32 = -0.4661;    constexpr Double b33 =  27.81;   constexpr Double b34 = -0.009437;\n    constexpr Double b41 = -0.006119; constexpr Double b42 =  1.176;     constexpr Double b43 =  6.385;\n    constexpr Double b51 =  87.56;    constexpr Double b52 = -0.09188;   constexpr Double b53 =  19.30;   constexpr Double b54 = -0.01089;\n    constexpr Double b61 =  0.002047; constexpr Double b62 =  6.409;\n    constexpr Double b71 =  61.98;    constexpr Double b72 = -0.1629;    constexpr Double b73 =  27.87;   constexpr Double b74 = -0.02217;\n    constexpr Double b81 =  6.413;    constexpr Double b82 = -0.0002593; constexpr Double b83 = -0.01479; constexpr Double b84 = -0.1318;\n\n    const Double a1 = b11 * std::exp(b12 * rR) + b13 * std::exp(b14 * rR);\n    const Double a2 = b21 * rR                 + b22;\n    const Double a3 = b31 * std::exp(b32 * rR) + b33 * std::exp(b34 * rR);\n    const Double a4 = b41 * std::pow(rR, b42)  + b43;\n    const Double a5 = b51 * std::exp(b52 * rR) + b53 * std::exp(b54 * rR);\n    const Double a6 = b61 * rR                 + b62;\n    const Double a7 = b71 * std::exp(b72 * rR) + b73 * std::exp(b74 * rR);\n    const Double a8 = b81 * std::exp(b82 * rR) + b83 * std::exp(b84 * rR);\n\n    factorSun = 0.5*(1+a1+a2+a1*std::tanh(a3*(rE-a4))+a2*std::tanh(a5*(rE-a6))+std::tanh(a7*(rE-a8)))/(1+a1+a2);\n    if(std::isnan(factorSun))\n      factorSun = 1;\n    return factorSun * factorMoon;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/ephemerides/ephemerides.cpp",
    "content": "/***********************************************/\n/**\n* @file ephemerides.cpp\n*\n* @brief Ephemerides of Sun, Moon and planets.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-07\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Ephemerides\n#define DOCSTRING_EphemeridesPlanet\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/ephemerides/ephemeridesJpl.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Ephemerides, \"ephemeridesType\",\n                      EphemeridesJpl)\n\nGROOPS_READCONFIG_CLASS(Ephemerides, \"ephemeridesType\")\n\n/***********************************************/\n\nEphemeridesPtr Ephemerides::create(Config &config, const std::string &name)\n{\n  try\n  {\n    EphemeridesPtr ptr;\n    std::string    type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"ephemerides of Sun, Moon and planets\");\n    if(readConfigChoiceElement(config, \"jpl\", type, \"\"))\n      ptr = std::make_shared<EphemeridesJpl>(config);\n    endChoice(config);\n\n    return ptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n// Wrapper class\nclass EphemeridesPlanet\n{\npublic:\n  Ephemerides::Planet planet;\n  EphemeridesPlanet(Config &config, const std::string &name);\n  static EphemeridesPlanet create(Config &config, const std::string &name) {return EphemeridesPlanet(config, name);}\n};\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(EphemeridesPlanet, \"planetType\")\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, Ephemerides::Planet &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(isCreateSchema(config))\n    {\n      config.xselement(name, \"planetType\", mustSet, Config::ONCE, defaultValue, annotation);\n      return FALSE;\n    }\n\n    if(!hasName(config, name, mustSet))\n      return FALSE;\n    EphemeridesPlanet tmp(config, name);\n    var = tmp.planet;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nEphemeridesPlanet::EphemeridesPlanet(Config &config, const std::string &name)\n{\n  try\n  {\n    planet = Ephemerides::EARTH;\n    std::string choice;\n\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"planet\");\n    if(readConfigChoiceElement(config, \"earth\",               choice, \"\")) planet = Ephemerides::EARTH;\n    if(readConfigChoiceElement(config, \"sun\",                 choice, \"\")) planet = Ephemerides::SUN;\n    if(readConfigChoiceElement(config, \"moon\",                choice, \"\")) planet = Ephemerides::MOON;\n    if(readConfigChoiceElement(config, \"mercury\",             choice, \"\")) planet = Ephemerides::MERCURY;\n    if(readConfigChoiceElement(config, \"venus\",               choice, \"\")) planet = Ephemerides::VENUS;\n    if(readConfigChoiceElement(config, \"mars\",                choice, \"\")) planet = Ephemerides::MARS;\n    if(readConfigChoiceElement(config, \"jupiter\",             choice, \"\")) planet = Ephemerides::JUPITER;\n    if(readConfigChoiceElement(config, \"saturn\",              choice, \"\")) planet = Ephemerides::SATURN;\n    if(readConfigChoiceElement(config, \"uranus\",              choice, \"\")) planet = Ephemerides::URANUS;\n    if(readConfigChoiceElement(config, \"neptune\",             choice, \"\")) planet = Ephemerides::NEPTUNE;\n    if(readConfigChoiceElement(config, \"pluto\",               choice, \"\")) planet = Ephemerides::PLUTO;\n    if(readConfigChoiceElement(config, \"solarBaryCenter\",     choice, \"\")) planet = Ephemerides::SOLARBARYCENTER;\n    if(readConfigChoiceElement(config, \"earthMoonBaryCenter\", choice, \"\")) planet = Ephemerides::EARTHMOONBARYCENTER;\n    endChoice(config);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/ephemerides/ephemerides.h",
    "content": "/***********************************************/\n/**\n* @file ephemerides.h\n*\n* @brief Ephemerides of Sun, Moon and planets.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EPHEMERIDES__\n#define __GROOPS_EPHEMERIDES__\n\n// Latex documentation\n#ifdef DOCSTRING_Ephemerides\nstatic const char *docstringEphemerides = R\"(\n\\section{Ephemerides}\\label{ephemeridesType}\nEphemerides of Sun, Moon and planets.\nThe coordinate system is defined as center of \\configClass{origin}{planetType}.\n)\";\n#endif\n\n// Latex documentation\n#ifdef DOCSTRING_EphemeridesPlanet\nstatic const char *docstringEphemeridesPlanet = R\"(\n\\section{Planet}\\label{planetType}\nDefines the planet to compute the \\configClass{ephemeris}{ephemeridesType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup ephemeridesGroup Ephemerides\n* @brief Ephemerides of Sun, Moon and planets.\n* @ingroup classesGroup\n* The interface is given by @ref Ephemerides. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Ephemerides;\ntypedef std::shared_ptr<Ephemerides> EphemeridesPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Ephemerides of Sun, Moon and planets.\n* An Instance of this class can be created by @ref readConfig. */\nclass Ephemerides\n{\npublic:\n  /// planet identifier\n  enum Planet {MERCURY             = 1,\n               VENUS               = 2,\n               EARTH               = 3,\n               MARS                = 4,\n               JUPITER             = 5,\n               SATURN              = 6,\n               URANUS              = 7,\n               NEPTUNE             = 8,\n               PLUTO               = 9,\n               MOON                = 10,\n               SUN                 = 11,\n               SOLARBARYCENTER     = 12,\n               EARTHMOONBARYCENTER = 13};\n\n  /// Destructor.\n  virtual ~Ephemerides() {}\n\n  /** @brief Position of a planet in celestial reference system (CRF).  */\n  virtual Vector3d position(const Time &timeGPS, Planet planet) = 0;\n\n  /** @brief Position and velocity of a planet in celestial reference system (CRF).  */\n  virtual void ephemeris(const Time &timeGPS, Planet planet, Vector3d &position, Vector3d &velocity) = 0;\n\n  virtual Planet origin() const = 0;\n\n  /** @brief creates an derived instance of this class. */\n  static EphemeridesPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Ephemerides.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Ephemerides */\ntemplate<> Bool readConfig(Config &config, const std::string &name, EphemeridesPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/** @brief Reads an planet from config.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for @a var\n* @param name Tag name in the config.\n* @param[out] var read from config.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Used for @a var if no node is in config.\n* @param annotation Short description. */\ntemplate<> Bool readConfig(Config &config, const std::string &name, Ephemerides::Planet &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/ephemerides/ephemeridesJpl.h",
    "content": "/***********************************************/\n/**\n* @file ephemeridesJpl.h\n*\n* @brief Ephemerides from JPL.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EPHEMERIDESJPL__\n#define __GROOPS_EPHEMERIDESJPL__\n\n// Latex documentation\n#ifdef DOCSTRING_Ephemerides\nstatic const char *docstringEphemeridesJpl = R\"(\n\\section{JPL}\\label{ephemeridesType:jpl}\nUsing \\verb|DExxx| ephemerides from NASA Jet Propulsion Laboratory (JPL).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileEphemerides.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Ephemerides from JPL.\n* @ingroup ephemeridesGroup\n* @see Ephemerides */\nclass EphemeridesJpl : public Ephemerides\n{\n  InFileEphemerides file;\n  Planet origin_;\n\npublic:\n  EphemeridesJpl(Config &config);\n\n  Vector3d position(const Time &timeGPS, Planet planet) override;\n  void     ephemeris(const Time &timeGPS, Planet planet, Vector3d &position, Vector3d &velocity) override;\n  Planet   origin() const override {return origin_;}\n};\n\n/***********************************************/\n\ninline EphemeridesJpl::EphemeridesJpl(Config &config)\n{\n  try\n  {\n    FileName fileName;\n\n    readConfig(config, \"inputfileEphemerides\", fileName, Config::MUSTSET, \"{groopsDataDir}/tides/ephemerides_JPL_DE432.dat\", \"\");\n    readConfig(config, \"origin\",               origin_,  Config::DEFAULT, \"earth\", \"center of coordinate system\");\n    if(isCreateSchema(config)) return;\n\n    file.open(fileName);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d EphemeridesJpl::position(const Time &timeGPS, Planet planet)\n{\n  try\n  {\n    Vector3d position, velocity;\n    file.ephemeris(timeGPS, static_cast<InFileEphemerides::Planet>(planet), static_cast<InFileEphemerides::Planet>(origin_), position, velocity);\n    return position;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void EphemeridesJpl::ephemeris(const Time &timeGPS, Planet planet, Vector3d &position, Vector3d &velocity)\n{\n  try\n  {\n    file.ephemeris(timeGPS, static_cast<InFileEphemerides::Planet>(planet), static_cast<InFileEphemerides::Planet>(origin_), position, velocity);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/forces/forces.cpp",
    "content": "/***********************************************/\n/**\n* @file forces.cpp\n*\n* @brief Wraps forces and force-generating potentials.\n*\n* @author Matthias Ellmer\n* @date 2017-01-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Forces\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/forces/forces.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(Forces, \"forcesType\")\nGROOPS_READCONFIG_CLASS(Forces, \"forcesType\")\n\n/***********************************************/\n\nForces::Forces(Config &config, const std::string &name)\n{\n  try\n  {\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"gravityfield\",      gravityfield,      Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"tides\",             tides,             Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"miscAccelerations\", miscAccelerations, Config::OPTIONAL, \"\", \"\");\n    endSequence(config);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d Forces::acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                              const Rotary3d &rotSat, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    const Vector3d posEarth = rotEarth.rotate(position);\n    Vector3d g;\n    if(gravityfield)      g += gravityfield->gravity(time, posEarth);\n    if(tides)             g += tides->acceleration(time, posEarth, rotEarth, rotation, ephemerides);\n    if(miscAccelerations) g += miscAccelerations->acceleration(satellite, time, position, velocity, rotSat, rotEarth, ephemerides);\n    return g;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/forces/forces.h",
    "content": "/***********************************************/\n/**\n* @file forces.h\n*\n* @brief Wraps forces and force-generating potentials.\n*\n* @author Matthias Ellmer\n* @date 2017-01-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FORCES__\n#define __GROOPS_FORCES__\n\n// Latex documentation\n#ifdef DOCSTRING_Forces\nstatic const char *docstringForces = R\"(\n\\section{Forces}\\label{forcesType}\nThis class provides the forces acting on a satellite.\nThis encompasses \\configClass{gravityfield}{gravityfieldType}, \\configClass{tides}{tidesType}\nand \\configClass{miscAccelerations}{miscAccelerationsType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n#include \"classes/tides/tides.h\"\n\n/**\n* @defgroup forcesGroup Forces\n* @brief Forces acting on satellites.\n* @ingroup classesGroup\n* The interface is given by @ref Forces. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Forces;\ntypedef std::shared_ptr<Forces> ForcesPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Wrapper around forces and force-generating types.\n* An Instance of this class can be created by @ref readConfig. */\nclass Forces\n{\npublic:\n  /// Constructor.\n  Forces(Config &config, const std::string &name);\n\n  /** @brief Compute full acceleration in TRF\n  * @param satellite model for misc accelerations\n  * @param time Time.\n  * @param position in CRF [m].\n  * @param velocity in CRF [m/s].\n  * @param rotSat   Sat -> CRF\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides Position of Sun and Moon.\n  * @return acceleration in TRF(!) [m/s^2] */\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n\n  /** @brief creates an derived instance of this class. */\n  static ForcesPtr create(Config &config, const std::string &name) {return ForcesPtr(new Forces(config, name));}\n\nprivate:\n  GravityfieldPtr      gravityfield;\n  TidesPtr             tides;\n  MiscAccelerationsPtr miscAccelerations;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Forces.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a forces is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] forces Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Forces */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ForcesPtr &forces, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif // __GROOPS_FORCES__\n\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfield.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield.cpp\n*\n* @brief Function values of (time variable) gravity fields.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-15\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Gravityfield\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/configRegister.h\"\n#include \"classes/gravityfield/gravityfieldPotentialCoefficients.h\"\n#include \"classes/gravityfield/gravityfieldPotentialCoefficientsInterior.h\"\n#include \"classes/gravityfield/gravityfieldInInterval.h\"\n#include \"classes/gravityfield/gravityfieldFromParametrization.h\"\n#include \"classes/gravityfield/gravityfieldTimeSplines.h\"\n#include \"classes/gravityfield/gravityfieldTrend.h\"\n#include \"classes/gravityfield/gravityfieldOscillation.h\"\n#include \"classes/gravityfield/gravityfieldTides.h\"\n#include \"classes/gravityfield/gravityfieldTopography.h\"\n#include \"classes/gravityfield/gravityfieldEarthquakeOscillation.h\"\n#include \"classes/gravityfield/gravityfieldFilter.h\"\n#include \"classes/gravityfield/gravityfieldGroup.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Gravityfield, \"gravityfieldType\",\n                      GravityfieldPotentialCoefficients,\n                      GravityfieldPotentialCoefficientsInterior,\n                      GravityfieldFromParametrization,\n                      GravityfieldTimeSplines,\n                      GravityfieldTrend,\n                      GravityfieldOscillation,\n                      GravityfieldInInterval,\n                      GravityfieldTides,\n                      GravityfieldTopography,\n                      GravityfieldEarthquakeOscillation,\n                      GravityfieldFilter,\n                      GravityfieldGroup)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(Gravityfield, \"gravityfieldType\")\n\n/***********************************************/\n\nGravityfield::Gravityfield(Config &config, const std::string &name)\n{\n  try\n  {\n    GravityfieldPotentialCoefficients         *coeff         = nullptr;\n    GravityfieldPotentialCoefficientsInterior *coeffInterior = nullptr;\n\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"functions of the gravity field\"))\n    {\n      renameDeprecatedChoice(config, type, \"fromRepresentation\", \"fromParametrization\", date2time(2020, 6, 3));\n\n      if(readConfigChoiceElement(config, \"potentialCoefficients\", type, \"file with potential coefficients\"))\n      {\n        if(!coeff)\n          gravityfield.push_back(coeff = new GravityfieldPotentialCoefficients(config));\n        else\n          coeff->addPotentialCoefficients(GravityfieldPotentialCoefficients(config).sphericalHarmonics(Time()));\n      }\n      if(readConfigChoiceElement(config, \"potentialCoefficientsInterior\", type, \"file with potential coefficients\"))\n      {\n        if(!coeffInterior)\n          gravityfield.push_back(coeffInterior = new GravityfieldPotentialCoefficientsInterior(config));\n        else\n          coeffInterior->addPotentialCoefficients(GravityfieldPotentialCoefficientsInterior(config).sphericalHarmonics(Time()));\n      }\n      if(readConfigChoiceElement(config, \"fromParametrization\",   type, \"from a solution vector with given parametrization\"))\n        gravityfield.push_back(new GravityfieldFromParametrization(config));\n      if(readConfigChoiceElement(config, \"timeSplines\",           type, \"file with splines in time domain\"))\n        gravityfield.push_back(new GravityfieldTimeSplines(config));\n      if(readConfigChoiceElement(config, \"trend\",                 type, \"gravityfield as trend\"))\n        gravityfield.push_back(new GravityfieldTrend(config));\n      if(readConfigChoiceElement(config, \"oscillation\",           type, \"gravityfield as oscillation\"))\n        gravityfield.push_back(new GravityfieldOscillation(config));\n      if(readConfigChoiceElement(config, \"inInterval\",            type, \"gravityfields only valid in specific time interval\"))\n        gravityfield.push_back(new GravityfieldInInterval(config));\n      if(readConfigChoiceElement(config, \"tides\",                 type, \"gravityfield from tide models\"))\n        gravityfield.push_back(new GravityfieldTides(config));\n      if(readConfigChoiceElement(config, \"topography\",            type, \"gravityfield from topographic masses\"))\n        gravityfield.push_back(new GravityfieldTopography(config));\n      if(readConfigChoiceElement(config, \"earthquakeOscillation\", type, \"gravityfield from earthquake oscillation\"))\n        gravityfield.push_back(new GravityfieldEarthquakeOscillation(config));\n      if(readConfigChoiceElement(config, \"filter\",                type, \"filtered spherical harmonics\"))\n        gravityfield.push_back(new GravityfieldFilter(config));\n      if(readConfigChoiceElement(config, \"group\",                 type, \"group gravityfields\"))\n        gravityfield.push_back(new GravityfieldGroup(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    };\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGravityfield::~Gravityfield()\n{\n  for(UInt i=0; i<gravityfield.size(); i++)\n    delete gravityfield.at(i);\n}\n\n/***********************************************/\n\nDouble Gravityfield::potential(const Time &time, const Vector3d &point) const\n{\n  Double sum = 0.0;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sum += gravityfield.at(i)->potential(time, point);\n  return sum;\n}\n\n/***********************************************/\n\nDouble Gravityfield::radialGradient(const Time &time, const Vector3d &point) const\n{\n  Double sum = 0.0;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sum += gravityfield.at(i)->radialGradient(time, point);\n  return sum;\n}\n\n/***********************************************/\n\nDouble Gravityfield::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  Double sum = 0.0;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sum += gravityfield.at(i)->field(time, point, kernel);\n  return sum;\n}\n\n/***********************************************/\n\nVector3d Gravityfield::gravity(const Time &time, const Vector3d &point) const\n{\n  Vector3d sum;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sum += gravityfield.at(i)->gravity(time, point);\n  return sum;\n}\n\n/***********************************************/\n\nTensor3d Gravityfield::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  Tensor3d sum;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sum += gravityfield.at(i)->gravityGradient(time, point);\n  return sum;\n}\n\n/***********************************************/\n\nVector3d Gravityfield::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  Vector3d sum;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sum += gravityfield.at(i)->deformation(time, point, gravity, hn, ln);\n  return sum;\n}\n\n/***********************************************/\n\nvoid Gravityfield::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  for(UInt i=0; i<gravityfield.size(); i++)\n    gravityfield.at(i)->deformation(time, point, gravity, hn, ln, disp);\n}\n\n/***********************************************/\n\nSphericalHarmonics Gravityfield::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    if(gravityfield.size()==0)\n      return SphericalHarmonics().get(maxDegree, minDegree, GM, R);\n    SphericalHarmonics harmonics = gravityfield.at(0)->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n    for(UInt i=1; i<gravityfield.size(); i++)\n      harmonics += gravityfield.at(i)->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n    return harmonics;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Gravityfield::sphericalHarmonicsCovariance(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    Matrix Cov;\n    for(UInt i=0; i<gravityfield.size(); i++)\n    {\n      Matrix Cov2 = gravityfield.at(i)->sphericalHarmonicsCovariance(time, maxDegree, minDegree, GM, R);\n\n      if(Cov2.size() == 0)\n        continue;\n\n      if(Cov.size() == 0)\n      {\n        Cov = Cov2;\n        continue;\n      }\n\n      if(Cov.rows()<Cov2.columns())\n      {\n        Matrix tmp = Cov;\n        Cov = Cov2;\n        if((Cov.getType()==Matrix::SYMMETRIC) && (Cov2.getType()==Matrix::SYMMETRIC))\n        {\n          axpy(1., tmp, Cov.slice(0,0,tmp.rows(),tmp.columns()));\n          continue;\n        }\n        else if((Cov.getType()!=Matrix::SYMMETRIC) && (Cov2.getType()!=Matrix::SYMMETRIC))\n        {\n          axpy(1., tmp, Cov.row(0,tmp.rows()));\n          continue;\n        }\n        else if((Cov.getType()!=Matrix::SYMMETRIC) && (Cov2.getType()==Matrix::SYMMETRIC))\n        {\n          for(UInt i=0; i<tmp.rows(); i++)\n            Cov(i,i) += tmp(i,0);\n          continue;\n        }\n        else if((Cov.getType()==Matrix::SYMMETRIC) && (Cov2.getType()!=Matrix::SYMMETRIC))\n        {\n          Cov = Matrix(Cov2.rows(), Matrix::SYMMETRIC);\n          copy(tmp, Cov.slice(0,0,tmp.rows(),tmp.columns()));\n        }\n        else\n          throw(Exception(\"something strange\"));\n      }\n\n      if((Cov.getType()==Matrix::SYMMETRIC) && (Cov2.getType()==Matrix::SYMMETRIC))\n        Cov.slice(0,0,Cov2.rows(),Cov2.columns()) += Cov2;\n      else if((Cov.getType()!=Matrix::SYMMETRIC) && (Cov2.getType()!=Matrix::SYMMETRIC))\n        Cov.row(0,Cov2.rows()) += Cov2;\n      else if((Cov.getType()==Matrix::SYMMETRIC) && (Cov2.getType()!=Matrix::SYMMETRIC))\n        for(UInt i=0; i<Cov2.rows(); i++)\n          Cov(i,i) += Cov2(i,0);\n      else\n        throw(Exception(\"something strange\"));\n    }\n\n    return Cov;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Gravityfield::variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel) const\n{\n  Matrix D(point.size(), Matrix::SYMMETRIC);\n  for(UInt i=0; i<gravityfield.size(); i++)\n    gravityfield.at(i)->variance(time, point, kernel, D);\n  return D;\n}\n\n/***********************************************/\n\nDouble Gravityfield::variance(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  Double sigma2 = 0;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sigma2 += gravityfield.at(i)->variance(time, point, kernel);\n  return sigma2;\n}\n\n/***********************************************/\n\nDouble Gravityfield::covariance(const Time &time, const Vector3d &point1, const Vector3d &point2, const Kernel &kernel) const\n{\n  Double sigma2 = 0;\n  for(UInt i=0; i<gravityfield.size(); i++)\n    sigma2 += gravityfield.at(i)->covariance(time, point1, point2, kernel);\n  return sigma2;\n}\n\n/***********************************************/\n/***********************************************/\n\nMatrix GravityfieldBase::deformationMatrix(const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                           const Vector &hn, const Vector &ln, Double GM, Double R, UInt maxDegree)\n{\n  try\n  {\n    Matrix A(3*point.size(), (maxDegree+1)*(maxDegree+1));\n\n    for(UInt k=0; k<point.size(); k++)\n    {\n      Vector3d up = normalize(point.at(k));\n\n      Matrix Cnm, Snm;\n      SphericalHarmonics::CnmSnm(1/R * point.at(k), maxDegree+1, Cnm, Snm);\n\n      // 0. order\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        Double wm0 = sqrt((n+1.)*(n+1.));\n        Double wp1 = sqrt((n+1.)*(n+2.)) / sqrt(2.0);\n        Double Cm0 = wm0*Cnm(n+1,0);\n        Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n        Double   Vn     = GM/R * Cnm(n,0);\n        Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(-2*Cp1, -2*Sp1, -2*Cm0);\n\n\n        Vector3d disp = (hn(n)/gravity.at(k)*Vn) * up // vertical\n                      + (ln(n)/gravity.at(k)) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n        A(3*k+0, n*n) = disp.x();\n        A(3*k+1, n*n) = disp.y();\n        A(3*k+2, n*n) = disp.z();\n      }\n\n      // other orders\n      for(UInt m=1; m<=maxDegree; m++)\n        for(UInt n=m; n<=maxDegree; n++)\n        {\n          Double wm1 = sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? sqrt(2.0) : 1.0);\n          Double wm0 = sqrt((n-m+1.)*(n+m+1.));\n          Double wp1 = sqrt((n+m+1.)*(n+m+2.));\n          Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n          Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n          Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n          Double   Vn     = GM/R * Cnm(n,m);\n          Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Cm1-Cp1, -Sm1-Sp1, -2*Cm0);\n\n          Vector3d disp = (hn(n)/gravity.at(k)*Vn) * up // vertical\n                        + (ln(n)/gravity.at(k)) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          A(3*k+0, n*n+2*m-1) = disp.x();\n          A(3*k+1, n*n+2*m-1) = disp.y();\n          A(3*k+2, n*n+2*m-1) = disp.z();\n\n          Vn     = GM/R * Snm(n,m);\n          gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Sm1-Sp1, Cm1+Cp1, -2*Sm0);\n\n          disp = (hn(n)/gravity.at(k)*Vn) * up // vertical\n               + (ln(n)/gravity.at(k)) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          A(3*k+0, n*n+2*m) = disp.x();\n          A(3*k+1, n*n+2*m) = disp.y();\n          A(3*k+2, n*n+2*m) = disp.z();\n        }\n    } // for(k=point)\n\n    return A;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Default implementation\nDouble GravityfieldBase::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  try\n  {\n    return kernel.inverseKernel(time, point, *this);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Default implementation\nMatrix GravityfieldBase::sphericalHarmonicsCovariance(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  // only diagonal matrix\n  return sphericalHarmonics(time, maxDegree, minDegree, GM, R).sigma2x();\n}\n\n/***********************************************/\n\n// Default implementation\nDouble GravityfieldBase::variance(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  Matrix D(1, Matrix::SYMMETRIC);\n  variance(time, {point}, kernel, D);\n  return D(0,0);\n}\n\n/***********************************************/\n\n// Default implementation\nDouble GravityfieldBase::covariance(const Time &time, const Vector3d &point1, const Vector3d &point2, const Kernel &kernel) const\n{\n  Matrix D(2, Matrix::SYMMETRIC, Matrix::UPPER);\n  variance(time, {point1, point2}, kernel, D);\n  return D(0,1);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfield.h",
    "content": "/***********************************************/\n/**\n* @file gravityfield.h\n*\n* @brief Function values of (time variable) gravity fields.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELD__\n#define __GROOPS_GRAVITYFIELD__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfield = R\"(\n\\section{Gravityfield}\\label{gravityfieldType}\nThis class computes functionals of the time depending gravity field,\ne.g potential, gravity anomalies or gravity gradients.\n\nIf several instances of the class are given the results are summed up.\nBefore summation every single result is multiplicated by a \\config{factor}.\nTo subtract a normal field like GRS80 from a potential\nto get the disturbance potential you must choose one factor by 1\nand the other by -1. To get the mean of two fields just set each factor to 0.5.\n\nSome of the instances gives also information about the accuracy.\nThe variance of the result (sum) is computed by means of variance propagation.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n\n/**\n* @defgroup gravityfieldGroup GravityField\n* @brief Function values of (time variable) gravity fields.\n* @ingroup classesGroup\n* The interface is given by @ref Gravityfield. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Gravityfield;\nclass GravityfieldBase;\ntypedef std::shared_ptr<Gravityfield> GravityfieldPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Function values of (time variable) gravity fields.\n* Calculate at the computation point functionals of (time variable) gravity fields.\n* An Instance of this class can be created by @ref readConfig. */\nclass Gravityfield // : public GravityfieldBase\n{\npublic:\n  /// Constructor.\n  Gravityfield(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~Gravityfield();\n\n  /** @brief Function values of the gravity field.\n  * Convolution of an inverse kernel with the potential.\n  * Example: Computes gravity anomalies with the stokes kernel.\n  * @param time If time==Time(), only the static part will be computed.\n  * @param point computation point in an Earth fixed reference system [m].\n  * @param kernel inverse kernel as differential operator. */\n  Double field(const Time &time, const Vector3d &point, const Kernel &kernel) const;\n\n  /** @brief Potential.\n  * @param time If time==Time(), only the static part will be computed.\n  * @param point computation point in an Earth fixed reference system [m].\n  * @return potential [m^2/s^2]. */\n  Double potential(const Time &time, const Vector3d &point) const;\n\n  /** @brief Radial gradient of the potential.\n  * @f$ \\frac{\\partial V}{\\partial r} @f$.\n  * @param time If time==Time(), only the static part will be computed.\n  * @param point computation point in an Earth fixed reference system [m].\n  * @return radial gradient [m/s^2]. */\n  Double radialGradient(const Time &time, const Vector3d &point) const;\n\n  /** @brief Gravity vector.\n  * @f$ \\nabla V @f$.\n  * @param time If time==Time(), only the static part will be computed.\n  * @param point computation point in an Earth fixed reference system [m].\n  * @return Result is given in an Earth fixed system [m/s^2]. */\n  Vector3d gravity(const Time &time, const Vector3d &point) const;\n\n  /** @brief Gravity gradient.\n  * @f$ \\nabla\\nabla V @f$\n  * @param time If time==Time(), only the static part will be computed.\n  * @param point computation point in an Earth fixed reference system [m].\n  * @return Result is given in an Earth fixed system [1/s^2]. */\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n\n  /** @brief Deformation due to loading.\n  * @param  time point in time\n  * @param  point station position in TRF [m]\n  * @param  gravity local gravity at station [m/s**2]\n  * @param  hn vertical load love numbers\n  * @param  ln horizontal load love numbers\n  * @return deformation in TRF [m] */\n  Vector3d deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n\n  /** @brief Deformation due to loading.\n  * @param  time points in time\n  * @param  point station positions in TRF [m]\n  * @param  gravity local gravity at stations [m/s**2]\n  * @param  hn vertical load love numbers\n  * @param  ln horizontal load love numbers\n  * @param[out] disp series (stationSize x TimeSize) in TRF [m] */\n  void deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  /** @brief Conversion into a series of spherical harmonics.\n  * If @a time==Time(), only the static part will be computed. */\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  /** @brief Variance-Covariance-Matrix.\n  * The result is a full covariance matrix or a vector containing only the variances\n  * of a spherical harmonics expansion.\n  * The coefficients are given in a degree wise sequence with alternating sin, cos:\n  * ..., c20,c21,s21,c22,s22,..., beginning with c00. */\n  Matrix sphericalHarmonicsCovariance(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  /** @brief Variance-Covariance-Matrix.\n  * Variance-Covariance-Matrix of gravity field functionals at a list of grid points. */\n  Matrix variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel) const;\n\n  /** @brief Variance of gravity field functional.\n  * Variance of a gravity field functional at one point. */\n  Double variance(const Time &time, const Vector3d &point, const Kernel &kernel) const;\n\n  /** @brief Covariance between gravity field functional at two different points. */\n  Double covariance(const Time &time, const Vector3d &point1, const Vector3d &point2, const Kernel &kernel) const;\n\n  /** @brief creates an derived instance of this class. */\n  static GravityfieldPtr create(Config &config, const std::string &name) {return GravityfieldPtr(new Gravityfield(config, name));}\n\nprivate:\n  std::vector<GravityfieldBase*> gravityfield;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Gravityfield.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a class with zero gravity is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] gravityfield Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Gravityfield */\ntemplate<> Bool readConfig(Config &config, const std::string &name, GravityfieldPtr &gravityfield, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass GravityfieldBase\n{\npublic:\n  virtual ~GravityfieldBase() {}\n\n  virtual Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  virtual Double   potential      (const Time &time, const Vector3d &point) const = 0;\n  virtual Double   radialGradient (const Time &time, const Vector3d &point) const = 0;\n  virtual Vector3d gravity        (const Time &time, const Vector3d &point) const = 0;\n  virtual Tensor3d gravityGradient(const Time &time, const Vector3d &point) const = 0;\n  virtual Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const = 0;\n  virtual void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                  const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const = 0;\n\n  static Matrix deformationMatrix(const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                  const Vector &hn, const Vector &ln, Double GM, Double R, UInt maxDegree);\n\n  virtual SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const = 0;\n  virtual Matrix   sphericalHarmonicsCovariance(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  virtual void   variance  (const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const=0;\n  virtual Double variance  (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  virtual Double covariance(const Time &time, const Vector3d &point1, const Vector3d &point2, const Kernel &kernel) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldEarthquakeOscillation.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldEarthquakeOscillation.cpp\n*\n* @brief Earthquake oscillation.\n* @see Gravityfield\n*\n* @author Saniya Behzadpour\n* @date 2017-06-07\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldEarthquakeOscillation.h\"\n\n/***********************************************/\n\nGravityfieldEarthquakeOscillation::GravityfieldEarthquakeOscillation(Config &config)\n{\n  try\n  {\n    FileName xName;\n\n    readConfig(config, \"inputCoefficientMatrix\", xName,     Config::MUSTSET,  \"\",  \"oscillation model parameters\");\n    readConfig(config, \"time0\",                  time0,     Config::MUSTSET,  \"\",  \"the time earthquake happened\");\n    readConfig(config, \"minDegree\",              minDegree, Config::DEFAULT,  \"2\", \"\");\n    readConfig(config, \"maxDegree\",              maxDegree, Config::DEFAULT,  \"2\", \"\");\n    readConfig(config, \"GM\",                     GM,        Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                      R,         Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    Matrix mx;\n    readFileMatrix(xName, mx);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\nSphericalHarmonics GravityfieldEarthquakeOscillation::timeVariableCoefficients(const Time &time) const\n{\n  try\n  {\n    if(time < time0)\n      return SphericalHarmonics();\n\n    const Double c = 2*PI*(time-time0).seconds();\n\n    Matrix cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    for(UInt i=0; i<mx.rows(); i++)\n    {\n      cnm(mx(i,1), mx(i,2)) += mx(i,3) * (1-cos(c/mx(i,5)) * exp(-c/mx(i,5)/mx(i,6)/2));\n      snm(mx(i,1), mx(i,2)) += mx(i,4) * (1-cos(c/mx(i,5)) * exp(-c/mx(i,5)/mx(i,6)/2));\n    }\n\n    return SphericalHarmonics(GM, R, cnm, snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\nDouble GravityfieldEarthquakeOscillation::potential(const Time &time, const Vector3d &point) const\n{\n  return timeVariableCoefficients(time).potential(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldEarthquakeOscillation::radialGradient(const Time &time, const Vector3d &point) const\n{\n  return timeVariableCoefficients(time).radialGradient(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldEarthquakeOscillation::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  SphericalHarmonics harmonics = timeVariableCoefficients(time);\n  return inner(kernel.inverseCoefficients(point, harmonics.maxDegree(), harmonics.isInterior()), harmonics.Yn(point, harmonics.maxDegree()));\n}\n\n/***********************************************/\n\nVector3d GravityfieldEarthquakeOscillation::gravity(const Time &time, const Vector3d &point) const\n{\n  return timeVariableCoefficients(time).gravity(point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldEarthquakeOscillation::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  return timeVariableCoefficients(time).gravityGradient(point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldEarthquakeOscillation::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return timeVariableCoefficients(time).deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldEarthquakeOscillation::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                                    const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  for(UInt i=0; i<time.size(); i++)\n    for(UInt k=0; k<point.size(); k++)\n      disp.at(k).at(i) += deformation(time.at(i), point.at(k), gravity.at(k), hn, ln);\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldEarthquakeOscillation::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  return timeVariableCoefficients(time).get(maxDegree, std::max(this->minDegree, minDegree), GM, R);\n}\n\n/***********************************************/\n\nvoid GravityfieldEarthquakeOscillation::variance(const Time &/*time*/, const std::vector<Vector3d> &/*point*/, const Kernel &/*kernel*/, Matrix &/*D*/) const\n{\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldEarthquakeOscillation.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldEarthquakeOscillation.h\n*\n* @brief Earthquake oscillation.\n* @see Gravityfield\n*\n* @author Saniya Behzadpour\n* @date 2017-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDEARTHQUAKEOSCILLATION__\n#define __GROOPS_GRAVITYFIELDEARTHQUAKEOSCILLATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldEarthquakeOscillation = R\"(\n\\subsection{EarthquakeOscillation}\nThe given \\configClass{gravityfield}{gravityfieldType} is interpreted as an oscillation function\nin the gravitational potential field, caused by large earthquakes.\nThe result is computed at time $t$ as follows:\n\\begin{equation}\nC_{lm}(\\M t) = \\sum_{n=0}^NC_{nlm}(1-\\cos(\\omega)\\exp(\\frac{-\\omega}{2Q_{nlm}})),\n\\end{equation}\nwith $\\omega=\\frac{2\\pi}{T_{nlm}}(t-t_0)$. In this equation, $Q_{nlm}$ is the attenuation factor,\n$n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time in second.\n$T_{nlm}$ and $Q_{nlm}$ are computed with the elastic Earth model or observed from the long\nperiod record of superconducting gravimeter measurements after the earthquakes.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravityfield as oscillation.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldEarthquakeOscillation : public GravityfieldBase\n{\n  Matrix   mx;\n  Time     time0;\n  UInt     minDegree, maxDegree;\n  Double   GM, R;\n  SphericalHarmonics timeVariableCoefficients(const Time &time) const;\n\npublic:\n  GravityfieldEarthquakeOscillation(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const;\n\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldFilter.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldFilter.cpp\n*\n* @brief Filtered spherical harmonics.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-07-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldFilter.h\"\n\n/***********************************************/\n\nGravityfieldFilter::GravityfieldFilter(Config &config)\n{\n  try\n  {\n    readConfig(config, \"gravityfield\", gravityfield, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"filter\",       filter,       Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldFilter::potential(const Time &time, const Vector3d &point) const\n{\n  return sphericalHarmonics(time).potential(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldFilter::radialGradient(const Time &time, const Vector3d &point) const\n{\n  return sphericalHarmonics(time).radialGradient(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldFilter::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  SphericalHarmonics harmonics = sphericalHarmonics(time);\n  return inner(kernel.inverseCoefficients(point, harmonics.maxDegree(), harmonics.isInterior()), harmonics.Yn(point, harmonics.maxDegree()));\n}\n\n/***********************************************/\n\nVector3d GravityfieldFilter::gravity(const Time &time, const Vector3d &point) const\n{\n  return sphericalHarmonics(time).gravity(point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldFilter::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  return sphericalHarmonics(time).gravityGradient(point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldFilter::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return sphericalHarmonics(time).deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldFilter::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                     const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  for(UInt i=0; i<time.size(); i++)\n  {\n    SphericalHarmonics harmonics = sphericalHarmonics(time.at(i));\n    for(UInt k=0; k<point.size(); k++)\n      disp.at(k).at(i) += harmonics.deformation(point.at(k), gravity.at(k), hn, ln);\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldFilter::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  return filter->filter(gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R));\n}\n\n/***********************************************/\n\nvoid GravityfieldFilter::variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  try\n  {\n    SphericalHarmonics harmonics = sphericalHarmonics(time);\n    if(!harmonics.sigma2cnm().size())\n      return;\n\n    UInt   maxDegree = harmonics.maxDegree();\n    Double GM = harmonics.GM();\n    Double R  = harmonics.R();\n\n    Matrix Cnm_i, Snm_i, Cnm_k, Snm_k;\n    Matrix sigma2cnm = harmonics.sigma2cnm();\n    Matrix sigma2snm = harmonics.sigma2snm();\n\n    for(UInt i=0; i<point.size(); i++)\n    {\n      Vector coeff_i = GM/R * kernel.inverseCoefficients(point.at(i), maxDegree, harmonics.isInterior());\n      SphericalHarmonics::CnmSnm(1/R * point.at(i), maxDegree, Cnm_i, Snm_i, harmonics.isInterior());\n\n      for(UInt k=i; k<point.size(); k++)\n      {\n        Vector coeff_k = GM/R * kernel.inverseCoefficients(point.at(k), maxDegree, harmonics.isInterior());\n        SphericalHarmonics::CnmSnm(1/R * point.at(k), maxDegree, Cnm_k, Snm_k, harmonics.isInterior());\n\n        for(UInt n=0; n<=maxDegree; n++)\n          for(UInt m=0; m<=n; m++)\n            D(i,k) += coeff_i(n) * Cnm_i(n,m) * sigma2cnm(n,m) * Cnm_k(n,m) * coeff_k(n)\n                   +  coeff_i(n) * Snm_i(n,m) * sigma2snm(n,m) * Snm_k(n,m) * coeff_k(n);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldFilter::variance(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  try\n  {\n    SphericalHarmonics harmonics = sphericalHarmonics(time);\n    if(!harmonics.sigma2cnm().size())\n      return 0.0;\n\n    UInt   maxDegree = harmonics.maxDegree();\n    Double GM = harmonics.GM();\n    Double R  = harmonics.R();\n    Vector coeff = GM/R * kernel.inverseCoefficients(point, maxDegree, harmonics.isInterior());\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm, harmonics.isInterior());\n\n    Double sigma2 = 0;\n    const Matrix sigma2cnm = harmonics.sigma2cnm();\n    const Matrix sigma2snm = harmonics.sigma2snm();\n    for(UInt n=0; n<=maxDegree; n++)\n      for(UInt m=0; m<=n; m++)\n        sigma2  += std::pow(coeff(n)*Cnm(n,m),2) * sigma2cnm(n,m)\n                +  std::pow(coeff(n)*Snm(n,m),2) * sigma2snm(n,m);\n    return sigma2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldFilter.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldFilter.h\n*\n* @brief Filtered spherical harmonics.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-07-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDFILTER__\n#define __GROOPS_GRAVITYFIELDFILTER__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldFilter = R\"(\n\\subsection{Filter}\nConvert \\configClass{gravityfield}{gravityfieldType} to spherical harmonics\nand \\configClass{filter}{sphericalHarmonicsFilterType} the coefficients.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Filtered spherical harmonics.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldFilter : public GravityfieldBase\n{\n  GravityfieldPtr             gravityfield;\n  SphericalHarmonicsFilterPtr filter;\n\npublic:\n  GravityfieldFilter(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  void   variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n  Double variance(const Time &time, const Vector3d &point, const Kernel &kernel) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldFromParametrization.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldFromParametrization.cpp\n*\n* @brief Gravity field from parameter vector.\n* @see Gravityfield\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-10-31\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldFromParametrization.h\"\n\n/***********************************************/\n\nGravityfieldFromParametrization::GravityfieldFromParametrization(Config &config)\n{\n  try\n  {\n    UInt     rightSide, indexStart;\n    FileName xName, WName, sigmaxName;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrization\", date2time(2020, 6, 3));\n\n    readConfig(config, \"parametrization\",   parametrization, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileSolution\", xName,           Config::MUSTSET,  \"\",    \"solution vector\");\n    readConfig(config, \"inputfileSigmax\",   sigmaxName,      Config::OPTIONAL, \"\",    \"standards deviations or covariance matrix of the solution\");\n    readConfig(config, \"indexStart\",        indexStart,      Config::DEFAULT,  \"0\",   \"position in the solution vector\");\n    readConfig(config, \"rightSide\",         rightSide,       Config::DEFAULT,  \"0\",   \"if solution contains several right hand sides, select one\");\n    readConfig(config, \"factor\",            factor,          Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    Matrix mx;\n    readFileMatrix(xName, mx);\n    x = mx.slice(indexStart, rightSide, parametrization->parameterCount(), 1);\n\n    if(!sigmaxName.empty())\n    {\n      Matrix A;\n      readFileMatrix(sigmaxName, A);\n      if(A.getType() == Matrix::SYMMETRIC)\n      {\n        // full covariance matrix\n        C = A.slice(indexStart, indexStart, parametrization->parameterCount(), parametrization->parameterCount());\n        sigma2x = Vector(C.rows());\n        for(UInt i=0; i<sigma2x.rows(); i++)\n          sigma2x(i) = C(i,i);\n      }\n      else\n      {\n        // only diagonal matrix\n        sigma2x = A.row(indexStart, parametrization->parameterCount());\n        for(UInt i=0; i<sigma2x.rows(); i++)\n          sigma2x(i) *= sigma2x(i);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldFromParametrization::potential(const Time &time, const Vector3d &point) const\n{\n  Matrix A(1, parametrization->parameterCount());\n  parametrization->potential(time, point, A);\n  return factor * (A*x)(0,0);\n}\n\n/***********************************************/\n\nDouble GravityfieldFromParametrization::radialGradient(const Time &time, const Vector3d &point) const\n{\n  Matrix A(1, parametrization->parameterCount());\n  parametrization->radialGradient(time, point, A);\n  return factor * (A*x)(0,0);\n}\n\n/***********************************************/\n\nDouble GravityfieldFromParametrization::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  Matrix A(1, parametrization->parameterCount());\n  parametrization->field(time, point, kernel, A);\n  return factor * (A*x)(0,0);\n}\n\n/***********************************************/\n\nVector3d GravityfieldFromParametrization::gravity(const Time &time, const Vector3d &point) const\n{\n  Matrix A(3, parametrization->parameterCount());\n  parametrization->gravity(time, point, A);\n  Vector l = A*x;\n  Vector3d field;\n  field.x() = l(0);\n  field.y() = l(1);\n  field.z() = l(2);\n  return factor * field;\n}\n\n/***********************************************/\n\nTensor3d GravityfieldFromParametrization::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  Matrix A(6, parametrization->parameterCount());\n  parametrization->gravityGradient(time, point, A);\n  Vector l = A*x;\n  Tensor3d field;\n  field.xx() = l(0);\n  field.xy() = l(1);\n  field.xz() = l(2);\n  field.yy() = l(3);\n  field.yz() = l(4);\n  field.zz() = l(5);\n  return factor * field;\n}\n\n/***********************************************/\n\nVector3d GravityfieldFromParametrization::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  Matrix A(3, parametrization->parameterCount());\n  parametrization->deformation(time, point, gravity, hn, ln, A);\n  const Vector l = A*x;\n  return factor * Vector3d(l(0), l(1), l(2));\n}\n\n/***********************************************/\n\nvoid GravityfieldFromParametrization::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                                 const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    for(UInt i=0; i<time.size(); i++)\n      for(UInt k=0; k<point.size(); k++)\n        disp.at(k).at(i) += deformation(time.at(i), point.at(k), gravity.at(k), hn, ln);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldFromParametrization::variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  try\n  {\n    Matrix A(point.size(), parametrization->parameterCount());\n    for(UInt i=0; i<point.size(); i++)\n      parametrization->field(time, point.at(i), kernel, A.row(i));\n    if(C.size())\n      D += A*C*A.trans();\n    else\n    {\n      for(UInt i=0; i<A.columns(); i++)\n        A.column(i) *= sqrt(sigma2x(i));\n      rankKUpdate(1., A.trans(), D);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldFromParametrization::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    if(sigma2x.rows()!=0)\n      return factor * parametrization->sphericalHarmonics(time, x, sigma2x, maxDegree).get(maxDegree, minDegree, GM, R);\n    else\n      return factor * parametrization->sphericalHarmonics(time, x, maxDegree).get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldFromParametrization.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldFromParametrization.h\n*\n* @brief Gravity field from parameter vector.\n* @see Gravityfield\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-10-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDFROMPARAMETRIZATION__\n#define __GROOPS_GRAVITYFIELDFROMPARAMETRIZATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldFromParametrization = R\"(\n\\subsection{FromParametrization}\\label{gravityfieldType:fromParametrization}\nReads a solution vector from file \\configFile{inputfileSolution}{matrix}\nwhich may be computed by a least squares adjustment (e.g. by \\program{NormalsSolverVCE}).\nThe coefficients of the vector are interpreted from position \\config{indexStart}\n(counting from zero) with help of \\configClass{parametrizationGravity}{parametrizationGravityType}.\nIf the solution file contains solution of several right hand sides you can choose\none with number \\config{rightSide} (counting from zero).\nYou can also read a vector from file \\configFile{inputfileSigmax}{matrix}\ncontaining the accuracies of the coefficients.\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravity field from parameter vector.\n* @ingroup gravityfieldGroup\n* @see Gravityfield\n* @see ParametrizationGravity  */\nclass GravityfieldFromParametrization : public GravityfieldBase\n{\n  ParametrizationGravityPtr parametrization;\n  Vector  x;\n  Double  factor;\n  Matrix  C; // full covariance matrix\n  Vector  sigma2x;\n\npublic:\n  GravityfieldFromParametrization(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const override;\n  Double   radialGradient (const Time &time, const Vector3d &point) const override;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const override;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const override;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const override;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldGroup.cpp",
    "content": "/***********************************************/\n/**\n * @file gravityfieldGroup.cpp\n *\n * @brief Group.\n * @see Gravityfield\n *\n * @author Torsten Mayer-Guerr\n * @date 2023-11-13\n *\n */\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldGroup.h\"\n\n/***********************************************/\n\nGravityfieldGroup::GravityfieldGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"gravityfield\", gravityfield, Config::DEFAULT, \"\", \"\");\n    readConfig(config, \"factor\",       factor,       Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldGroup::potential(const Time &time, const Vector3d &point) const\n{\n  return factor * gravityfield->potential(time, point);\n}\n\n/***********************************************/\n\nDouble GravityfieldGroup::radialGradient(const Time &time, const Vector3d &point) const\n{\n  return factor * gravityfield->radialGradient(time, point);\n}\n\n/***********************************************/\n\nDouble GravityfieldGroup::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  return factor * gravityfield->field(time, point, kernel);\n}\n\n/***********************************************/\n\nVector3d GravityfieldGroup::gravity(const Time &time, const Vector3d &point) const\n{\n  return gravityfield->gravity(time, point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldGroup::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  return factor * gravityfield->gravityGradient(time, point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldGroup::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return factor * gravityfield->deformation(time, point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldGroup::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                    const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  gravityfield->deformation(time, point, gravity, hn, ln, disp);\n  if(factor != 1.)\n    for(auto &ds : disp)\n      for(auto &d : ds)\n        d *= factor;\n}\n\n/***********************************************/\n\nvoid GravityfieldGroup::variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  axpy(factor*factor, gravityfield->variance(time, point, kernel), D);\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldGroup::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  return factor * gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldGroup.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldGroup.h\n*\n* @brief Group.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-11-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GravityfieldGroup__\n#define __GROOPS_GravityfieldGroup__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldGroup = R\"(\n\\subsection{Group}\\label{gravityfieldType:group}\nGroups a set of \\configClass{gravityfield}{gravityfieldType} and has no further effect itself.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Group.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldGroup : public GravityfieldBase\n{\n  GravityfieldPtr gravityfield;\n  Double          factor;\n\npublic:\n  GravityfieldGroup(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const;\n\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldInInterval.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldInInterval.cpp\n*\n* @brief Gravity fields which is not zero during a specific time span only.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-11-06\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldInInterval.h\"\n\n/***********************************************/\n\nGravityfieldInInterval::GravityfieldInInterval(Config &config)\n{\n  try\n  {\n    readConfig(config, \"gravityfield\", gravityfield, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"timeStart\",    timeStart,    Config::MUSTSET, \"\", \"first point in time\");\n    readConfig(config, \"timeEnd\",      timeEnd,      Config::MUSTSET, \"\", \"last point in time will be less or equal timeEnd\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldInInterval::potential(const Time &time, const Vector3d &point) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->potential(time, point) : 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldInInterval::radialGradient(const Time &time, const Vector3d &point) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->radialGradient(time, point) : 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldInInterval::field(const Time &time, const Vector3d &point, const Kernel &kernel2) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->field(time, point, kernel2) : 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d GravityfieldInInterval::gravity(const Time &time, const Vector3d &point) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->gravity(time, point) : Vector3d();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTensor3d GravityfieldInInterval::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->gravityGradient(time, point) : Tensor3d();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d GravityfieldInInterval::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->deformation(time, point, gravity, hn, ln) : Vector3d();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldInInterval::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                         const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    std::vector<Time> time2;\n    std::copy_if(time.begin(), time.end(), std::back_inserter(time2), [&](const Time &x) {return ((x >= timeStart) && (x < timeEnd));});\n    if(time2.size() == 0)\n      return;\n\n    std::vector<std::vector<Vector3d>> disp2(point.size(), std::vector<Vector3d>(time2.size()));\n    gravityfield->deformation(time2, point, gravity, hn, ln, disp2);\n\n    auto iter = time.begin();\n    for(UInt k=0; k<time2.size(); k++)\n    {\n      const UInt index = std::distance(time.begin(), std::find(iter++, time.end(), time2.at(k)));\n      for(UInt i=0; i<point.size(); i++)\n        disp.at(i).at(index) = disp2.at(i).at(k);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldInInterval::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    return time.isInInterval(timeStart, timeEnd) ? gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R) : SphericalHarmonics().get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldInInterval::variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  try\n  {\n    if(time.isInInterval(timeStart, timeEnd))\n      D += gravityfield->variance(time, point, kernel);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldInInterval.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldInInterval.h\n*\n* @brief Gravity fields which is not zero during a specific time span only.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-11-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDININTERVAL__\n#define __GROOPS_GRAVITYFIELDININTERVAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldInInterval = R\"(\n\\subsection{InInterval}\nA \\configClass{gravityfield}{gravityfieldType} is only evaluated in the interval between\n\\config{timeStart} inclusively and \\config{timeEnd} exclusively.\nOutside the interval the result is zero.\n\nThis class is useful to get a time series of monthly mean GRACE gravity field solutions.\nIn each month another file of potentialCoefficients is valid.\nThis can easily be created with \\configClass{loop}{loopType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravity fields which is not zero during a specific time span only.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldInInterval : public GravityfieldBase\n{\n  GravityfieldPtr gravityfield;\n  Time            timeStart, timeEnd;\n\npublic:\n  GravityfieldInInterval(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const;\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldOscillation.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldOscillation.cpp\n*\n* @brief Gravityfield as oscillation.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-07\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldOscillation.h\"\n\n/***********************************************/\n\nGravityfieldOscillation::GravityfieldOscillation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"gravityfieldCos\", gravityfieldCos, Config::MUSTSET, \"\", \"multiplicated by cos(2pi/T(time-time0))\");\n    readConfig(config, \"gravityfieldSin\", gravityfieldSin, Config::MUSTSET, \"\", \"multiplicated by sin(2pi/T(time-time0))\");\n    readConfig(config, \"time0\",           time0,           Config::MUSTSET, STRING_J2000, \"reference time\");\n    readConfig(config, \"period\",          timePeriod,      Config::MUSTSET, \"365.25\",     \"[day]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldOscillation::potential(const Time &time, const Vector3d &point) const\n{\n  if(time == Time())\n    return 0;\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->potential(time, point) + sin(omega) * gravityfieldSin->potential(time, point);\n}\n\n/***********************************************/\n\nDouble GravityfieldOscillation::radialGradient(const Time &time, const Vector3d &point) const\n{\n  if(time == Time())\n    return 0;\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->radialGradient(time, point) +\n         sin(omega) * gravityfieldSin->radialGradient(time, point);\n}\n\n/***********************************************/\n\nDouble GravityfieldOscillation::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  if(time == Time())\n    return 0;\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->field(time, point, kernel) +\n         sin(omega) * gravityfieldSin->field(time, point, kernel);\n}\n\n/***********************************************/\n\nVector3d GravityfieldOscillation::gravity(const Time &time, const Vector3d &point) const\n{\n  if(time == Time())\n    return Vector3d();\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->gravity(time, point) +\n         sin(omega) * gravityfieldSin->gravity(time, point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldOscillation::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  if(time == Time())\n    return Tensor3d();\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->gravityGradient(time, point) +\n         sin(omega) * gravityfieldSin->gravityGradient(time, point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldOscillation::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  if(time == Time())\n    return Vector3d();\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->deformation(time, point, gravity, hn, ln) +\n         sin(omega) * gravityfieldSin->deformation(time, point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldOscillation::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                    const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  if((time.size()==0) || (point.size()==0))\n    return;\n\n  std::vector<std::vector<Vector3d>> dispCos(point.size());\n  for(UInt k=0; k<point.size(); k++)\n    dispCos.at(k).resize(time.size());\n  gravityfieldCos->deformation(time, point, gravity, hn, ln, dispCos);\n\n  std::vector<std::vector<Vector3d>> dispSin(point.size());\n  for(UInt k=0; k<point.size(); k++)\n    dispSin.at(k).resize(time.size());\n  gravityfieldCos->deformation(time, point, gravity, hn, ln, dispSin);\n\n  for(UInt i=0; i<time.size(); i++)\n  {\n    const Double omega = 2*PI/timePeriod.mjd()*(time.at(i)-time0).mjd();\n    for(UInt k=0; k<point.size(); k++)\n      disp.at(k).at(i) += cos(omega) * dispCos.at(k).at(i) + sin(omega) * dispSin.at(k).at(i);\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldOscillation::variance(const Time &/*time*/, const std::vector<Vector3d> &/*point*/, const Kernel &/*kernel*/, Matrix &/*D*/) const\n{\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldOscillation::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  if(time == Time())\n    return SphericalHarmonics();\n  const Double omega = 2*PI/timePeriod.mjd()*(time-time0).mjd();\n  return cos(omega) * gravityfieldCos->sphericalHarmonics(time, maxDegree, minDegree, GM, R) +\n         sin(omega) * gravityfieldSin->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldOscillation.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldOscillation.h\n*\n* @brief Gravityfield as oscillation.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDOSCILLATION__\n#define __GROOPS_GRAVITYFIELDOSCILLATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldOscillation = R\"(\n\\subsection{Oscillation}\\label{gravityfieldType:oscillation}\nThe given \\configClass{gravityfield}{gravityfieldType} is interpreted\nas oscillation function and the result is computed at time $t$ as follows\n\\begin{equation}\nV(\\M x,t) = \\cos(\\omega)V_{cos}(\\M x)+\\sin(\\omega)V_{sin}(\\M x),\n\\end{equation}\nwith $\\omega=\\frac{2\\pi}{T}(t-t_0)$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravityfield as oscillation.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldOscillation : public GravityfieldBase\n{\n  Time time0;\n  Time timePeriod;\n  GravityfieldPtr gravityfieldCos;\n  GravityfieldPtr gravityfieldSin;\n\npublic:\n  GravityfieldOscillation(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const;\n\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldPotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldPotentialCoefficients.cpp\n*\n* @brief Potential coefficients (SphericalHarmonics).\n* All classes fo this type are added together before evaluation to speed up the computation.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-25\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldPotentialCoefficients.h\"\n\n/***********************************************/\n\nGravityfieldPotentialCoefficients::GravityfieldPotentialCoefficients(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    Double   factor;\n    UInt     minDegree, maxDegree = INFINITYDEGREE;\n    Bool     zeroVariance;\n\n    readConfig(config, \"inputfilePotentialCoefficients\", fileName, Config::MUSTSET, \"{groopsDataDir}/potential/\", \"\");\n    readConfig(config, \"minDegree\",       minDegree,    Config::DEFAULT,  \"0\",   \"\");\n    readConfig(config, \"maxDegree\",       maxDegree,    Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"factor\",          factor,       Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    readConfig(config, \"setSigmasToZero\", zeroVariance, Config::DEFAULT,  \"0\",   \"set variances to zero, should be used by adding back reference fields\");\n    if(isCreateSchema(config)) return;\n\n    readFileSphericalHarmonics(fileName, harmonics);\n    if(zeroVariance)\n      harmonics.sigma2cnm() = harmonics.sigma2snm() = Matrix();\n    harmonics = factor * harmonics.get(maxDegree, minDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficients::potential(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.potential(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficients::radialGradient(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.radialGradient(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficients::field(const Time &/*time*/, const Vector3d &point, const Kernel &kernel) const\n{\n  // Convolution with kernel\n  return inner(kernel.inverseCoefficients(point, harmonics.maxDegree(), harmonics.isInterior()), harmonics.Yn(point, harmonics.maxDegree()));\n}\n\n/***********************************************/\n\nVector3d GravityfieldPotentialCoefficients::gravity(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.gravity(point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldPotentialCoefficients::gravityGradient(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.gravityGradient(point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldPotentialCoefficients::deformation(const Time &/*time*/, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return harmonics.deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldPotentialCoefficients::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                                         const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  for(UInt k=0; k<point.size(); k++)\n  {\n    Vector3d d = harmonics.deformation(point.at(k), gravity.at(k), hn, ln);\n    for(UInt i=0; i<time.size(); i++)\n      disp.at(k).at(i) += d;\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldPotentialCoefficients::variance(const Time &/*time*/, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  try\n  {\n    if(!harmonics.sigma2cnm().size())\n      return;\n\n    UInt   maxDegree = harmonics.maxDegree();\n    Double GM = harmonics.GM();\n    Double R  = harmonics.R();\n\n    Matrix Cnm_i, Snm_i, Cnm_k, Snm_k;\n    Matrix sigma2cnm = harmonics.sigma2cnm();\n    Matrix sigma2snm = harmonics.sigma2snm();\n\n    for(UInt i=0; i<point.size(); i++)\n    {\n      Vector coeff_i = GM/R * kernel.inverseCoefficients(point.at(i), maxDegree, harmonics.isInterior());\n      SphericalHarmonics::CnmSnm(1/R * point.at(i), maxDegree, Cnm_i, Snm_i, harmonics.isInterior());\n\n      for(UInt k=i; k<point.size(); k++)\n      {\n        Vector coeff_k = GM/R * kernel.inverseCoefficients(point.at(k), maxDegree, harmonics.isInterior());\n        SphericalHarmonics::CnmSnm(1/R * point.at(k), maxDegree, Cnm_k, Snm_k, harmonics.isInterior());\n\n        for(UInt n=0; n<=maxDegree; n++)\n          for(UInt m=0; m<=n; m++)\n            D(i,k) += coeff_i(n) * Cnm_i(n,m) * sigma2cnm(n,m) * Cnm_k(n,m) * coeff_k(n)\n                   +  coeff_i(n) * Snm_i(n,m) * sigma2snm(n,m) * Snm_k(n,m) * coeff_k(n);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficients::variance(const Time &/*time*/, const Vector3d &point, const Kernel &kernel) const\n{\n  try\n  {\n    if(!harmonics.sigma2cnm().size())\n      return 0.0;\n\n    UInt   maxDegree = harmonics.maxDegree();\n    Double GM = harmonics.GM();\n    Double R  = harmonics.R();\n    Vector coeff = GM/R * kernel.inverseCoefficients(point, maxDegree, harmonics.isInterior());\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm, harmonics.isInterior());\n\n    Double sigma2 = 0;\n    const Matrix sigma2cnm = harmonics.sigma2cnm();\n    const Matrix sigma2snm = harmonics.sigma2snm();\n    for(UInt n=0; n<=maxDegree; n++)\n      for(UInt m=0; m<=n; m++)\n        sigma2  += pow(coeff(n)*Cnm(n,m),2) * sigma2cnm(n,m)\n                +  pow(coeff(n)*Snm(n,m),2) * sigma2snm(n,m);\n    return sigma2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldPotentialCoefficients::sphericalHarmonics(const Time &/*time*/, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    return harmonics.get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldPotentialCoefficients.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldPotentialCoefficients.h\n*\n* @brief Potential coefficients (SphericalHarmonics).\n* All classes fo this type are added together before evaluation to speed up the computation.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDPOTENTIALCOEFFICIENTS__\n#define __GROOPS_GRAVITYFIELDPOTENTIALCOEFFICIENTS__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldPotentialCoefficients = R\"(\n\\subsection{PotentialCoefficients}\\label{gravityfieldType:potentialCoefficients}\nReads coefficients of a spherical harmonics expansion from file.\nThe potential is given by\n\\begin{equation}\nV(\\lambda,\\vartheta,r) = \\frac{GM}{R}\\sum_{n=0}^\\infty \\sum_{m=0}^n \\left(\\frac{R}{r}\\right)^{n+1}\n  \\left(c_{nm} C_{nm}(\\lambda,\\vartheta) + s_{nm} S_{nm}(\\lambda,\\vartheta)\\right).\n\\end{equation}\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The computed result\nis multiplied with \\config{factor}. If \\config{setSigmasToZero} is true\nthe variances are set to zero. This option is only important for variance propagation\nand does not change the result of the gravity field functionals.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Potential coefficients (SphericalHarmonics).\n* @ingroup gravityfieldGroup\n* All classes fo this type are added together before evaluation to speed up the computation.\n* @see Gravityfield */\nclass GravityfieldPotentialCoefficients : public GravityfieldBase\n{\n  SphericalHarmonics harmonics;\n\npublic:\n  GravityfieldPotentialCoefficients(Config &config);\n  void addPotentialCoefficients(const SphericalHarmonics &harm) {harmonics += harm;}\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  void   variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n  Double variance(const Time &time, const Vector3d &point, const Kernel &kernel) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldPotentialCoefficientsInterior.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldPotentialCoefficientsInterior.cpp\n*\n* @brief Potential coefficients (SphericalHarmonics).\n* All classes fo this type are added together before evaluation to speed up the computation.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-10-17\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldPotentialCoefficientsInterior.h\"\n\n/***********************************************/\n\nGravityfieldPotentialCoefficientsInterior::GravityfieldPotentialCoefficientsInterior(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    Double   factor;\n    UInt     minDegree, maxDegree = INFINITYDEGREE;\n    Bool     zeroVariance;\n\n    readConfig(config, \"inputfilePotentialCoefficients\", fileName,     Config::MUSTSET, \"{groopsDataDir}/potential/\", \"\");\n    readConfig(config, \"minDegree\",                      minDegree,    Config::DEFAULT,  \"0\",   \"\");\n    readConfig(config, \"maxDegree\",                      maxDegree,    Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"factor\",                         factor,       Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    readConfig(config, \"setSigmasToZero\",                zeroVariance, Config::DEFAULT,  \"0\",   \"set variances to zero, should be used by adding back reference fields\");\n    if(isCreateSchema(config)) return;\n\n    readFileSphericalHarmonics(fileName, harmonics);\n    harmonics.setInterior(TRUE);\n    if(zeroVariance)\n      harmonics.sigma2cnm() = harmonics.sigma2snm() = Matrix();\n    harmonics = factor * harmonics.get(maxDegree, minDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficientsInterior::potential(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.potential(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficientsInterior::radialGradient(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.radialGradient(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficientsInterior::field(const Time &/*time*/, const Vector3d &point, const Kernel &kernel) const\n{\n  // Convolution with kernel\n  return inner(kernel.inverseCoefficients(point, harmonics.maxDegree(), harmonics.isInterior()), harmonics.Yn(point, harmonics.maxDegree()));\n}\n\n/***********************************************/\n\nVector3d GravityfieldPotentialCoefficientsInterior::gravity(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.gravity(point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldPotentialCoefficientsInterior::gravityGradient(const Time &/*time*/, const Vector3d &point) const\n{\n  return harmonics.gravityGradient(point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldPotentialCoefficientsInterior::deformation(const Time &/*time*/, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return harmonics.deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldPotentialCoefficientsInterior::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                                                   const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  for(UInt k=0; k<point.size(); k++)\n  {\n    Vector3d d = harmonics.deformation(point.at(k), gravity.at(k), hn, ln);\n    for(UInt i=0; i<time.size(); i++)\n      disp.at(k).at(i) += d;\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldPotentialCoefficientsInterior::variance(const Time &/*time*/, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  try\n  {\n    if(!harmonics.sigma2cnm().size())\n      return;\n\n    UInt   maxDegree = harmonics.maxDegree();\n    Double GM = harmonics.GM();\n    Double R  = harmonics.R();\n\n    Matrix Cnm_i, Snm_i, Cnm_k, Snm_k;\n    Matrix sigma2cnm = harmonics.sigma2cnm();\n    Matrix sigma2snm = harmonics.sigma2snm();\n\n    for(UInt i=0; i<point.size(); i++)\n    {\n      Vector coeff_i = GM/R * kernel.inverseCoefficients(point.at(i), maxDegree, harmonics.isInterior());\n      SphericalHarmonics::CnmSnm(1/R * point.at(i), maxDegree, Cnm_i, Snm_i, harmonics.isInterior());\n\n      for(UInt k=i; k<point.size(); k++)\n      {\n        Vector coeff_k = GM/R * kernel.inverseCoefficients(point.at(k), maxDegree, harmonics.isInterior());\n        SphericalHarmonics::CnmSnm(1/R * point.at(k), maxDegree, Cnm_k, Snm_k, harmonics.isInterior());\n\n        for(UInt n=0; n<=maxDegree; n++)\n          for(UInt m=0; m<=n; m++)\n            D(i,k) += coeff_i(n) * Cnm_i(n,m) * sigma2cnm(n,m) * Cnm_k(n,m) * coeff_k(n)\n                   +  coeff_i(n) * Snm_i(n,m) * sigma2snm(n,m) * Snm_k(n,m) * coeff_k(n);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldPotentialCoefficientsInterior::variance(const Time &/*time*/, const Vector3d &point, const Kernel &kernel) const\n{\n  try\n  {\n    if(!harmonics.sigma2cnm().size())\n      return 0.0;\n\n    UInt   maxDegree = harmonics.maxDegree();\n    Double GM = harmonics.GM();\n    Double R  = harmonics.R();\n    Vector coeff = GM/R * kernel.inverseCoefficients(point, maxDegree, harmonics.isInterior());\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm, harmonics.isInterior());\n\n    Double sigma2 = 0;\n    const Matrix sigma2cnm = harmonics.sigma2cnm();\n    const Matrix sigma2snm = harmonics.sigma2snm();\n    for(UInt n=0; n<=maxDegree; n++)\n      for(UInt m=0; m<=n; m++)\n        sigma2  += pow(coeff(n)*Cnm(n,m),2) * sigma2cnm(n,m)\n                +  pow(coeff(n)*Snm(n,m),2) * sigma2snm(n,m);\n    return sigma2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldPotentialCoefficientsInterior::sphericalHarmonics(const Time &/*time*/, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    return harmonics.get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldPotentialCoefficientsInterior.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldPotentialCoefficientsInterior.h\n*\n* @brief Potential coefficients (SphericalHarmonics).\n* All classes fo this type are added together before evaluation to speed up the computation.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-10-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDPOTENTIALCOEFFICIENTSINTERIOR__\n#define __GROOPS_GRAVITYFIELDPOTENTIALCOEFFICIENTSINTERIOR__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldPotentialCoefficientsInterior = R\"(\n\\subsection{PotentialCoefficientsInterior}\nReads coefficients of a spherical harmonics expansion (for inner space) from file.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The computed result is multiplied with \\config{factor}.\nIf \\config{setSigmasToZero} is true the variances are set to zero.\nThis option is only important for error propagation\nand does not change the result of the gravity field functionals.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Potential coefficients (SphericalHarmonics).\n* @ingroup gravityfieldGroup\n* All classes fo this type are added together before evaluation to speed up the computation.\n* @see Gravityfield */\nclass GravityfieldPotentialCoefficientsInterior : public GravityfieldBase\n{\n  SphericalHarmonics harmonics;\n\npublic:\n  GravityfieldPotentialCoefficientsInterior(Config &config);\n  void addPotentialCoefficients(const SphericalHarmonics &harm) {harmonics += harm;}\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  void   variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n  Double variance(const Time &time, const Vector3d &point, const Kernel &kernel) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTides.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTides.cpp\n*\n* @brief Tidal forces computed with class Tide.\n* @see Gravityfield\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldTides.h\"\n\n/***********************************************/\n\nGravityfieldTides::GravityfieldTides(Config &config)\n{\n  try\n  {\n    readConfig(config, \"tides\",         tides,         Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"earthRotation\", earthRotation, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",   ephemerides,   Config::OPTIONAL, \"jpl\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldTides::potential(const Time &time, const Vector3d &point) const\n{\n  return tides->potential(time, point, earthRotation->rotaryMatrix(time), earthRotation, ephemerides);\n}\n\n/***********************************************/\n\nDouble GravityfieldTides::radialGradient(const Time &time, const Vector3d &point) const\n{\n  return tides->radialGradient(time, point, earthRotation->rotaryMatrix(time), earthRotation, ephemerides);\n}\n\n/***********************************************/\n\nVector3d GravityfieldTides::gravity(const Time &time, const Vector3d &point) const\n{\n  return tides->acceleration(time, point, earthRotation->rotaryMatrix(time), earthRotation, ephemerides);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldTides::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  return tides->gradient(time, point, earthRotation->rotaryMatrix(time), earthRotation, ephemerides);\n}\n\n/***********************************************/\n\nVector3d GravityfieldTides::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return tides->deformation(time, point, earthRotation->rotaryMatrix(time), earthRotation, ephemerides, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldTides::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                    const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  std::vector<Rotary3d> rotEarth(time.size());\n  for(UInt i=0; i<time.size(); i++)\n    rotEarth[i]= earthRotation->rotaryMatrix(time[i]);\n  tides->deformation(time, point, rotEarth, earthRotation, ephemerides, gravity, hn, ln, disp);\n}\n\n/***********************************************/\n\nvoid GravityfieldTides::variance(const Time &/*time*/, const std::vector<Vector3d> &/*point*/, const Kernel &/*kernel*/, Matrix &/*D*/) const\n{\n  try\n  {\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldTides::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    return tides->sphericalHarmonics(time, earthRotation->rotaryMatrix(time), earthRotation, ephemerides, maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTides.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTides.h\n*\n* @brief Tidal forces computed with class Tide.\n* @see Gravityfield\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDTIDES__\n#define __GROOPS_GRAVITYFIELDTIDES__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldTides = R\"(\n\\subsection{Tides}\\label{gravityfieldType:tides}\nTreat \\configClass{tides}{tidesType} as gravitational forces.\nThe tides need a realization of \\configClass{earthRotation}{earthRotationType}\nto transform between the CRF and TRF and to compute rotational deformation\nfrom polar motion.\nIt also needs \\configClass{ephemerides}{ephemeridesType} from Sun, moon, and planets.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/tides/tides.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Tidal forces computed with class Tide.\n* @ingroup gravityfieldGroup\n* @see Gravityfield\n* @see Tides */\nclass GravityfieldTides : public GravityfieldBase\n{\n  EphemeridesPtr   ephemerides;\n  EarthRotationPtr earthRotation;\n  TidesPtr         tides;\n\npublic:\n  GravityfieldTides(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const override;\n  Double   radialGradient (const Time &time, const Vector3d &point) const override;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const override;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const override;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const override;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTimeSplines.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTimeSplines.cpp\n*\n* @brief TimeSplines.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-04-14\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldTimeSplines.h\"\n\n/***********************************************/\n\nGravityfieldTimeSplines::GravityfieldTimeSplines(Config &config)\n{\n  try\n  {\n    maxDegree = INFINITYDEGREE;\n    FileName fileName, covName;\n\n    readConfig(config, \"inputfileTimeSplinesGravityfield\", fileName,  Config::MUSTSET,  \"{groopsDataDir}/\", \"\");\n    readConfig(config, \"inputfileTimeSplinesCovariance\",   covName,   Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"minDegree\",                        minDegree, Config::DEFAULT,  \"0\",   \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree, Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"factor\",                           factor,    Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    splinesFile.open(fileName, maxDegree, minDegree);\n    hasCovariance = !covName.empty();\n    if(hasCovariance)\n      covarianceFile.open(covName, maxDegree, minDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldTimeSplines::potential(const Time &time, const Vector3d &point) const\n{\n  return splinesFile.sphericalHarmonics(time, factor).potential(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldTimeSplines::radialGradient(const Time &time, const Vector3d &point) const\n{\n  return splinesFile.sphericalHarmonics(time, factor).radialGradient(point);\n}\n\n/***********************************************/\n\nDouble GravityfieldTimeSplines::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  SphericalHarmonics harm = splinesFile.sphericalHarmonics(time, factor);\n  // Convolution with kernel\n  return inner(kernel.inverseCoefficients(point, harm.maxDegree()), harm.Yn(point, harm.maxDegree()));\n}\n\n/***********************************************/\n\nVector3d GravityfieldTimeSplines::gravity(const Time &time, const Vector3d &point) const\n{\n  return splinesFile.sphericalHarmonics(time, factor).gravity(point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldTimeSplines::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  return splinesFile.sphericalHarmonics(time, factor).gravityGradient(point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldTimeSplines::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return splinesFile.sphericalHarmonics(time, factor).deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldTimeSplines::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                          const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  if((time.size()==0) || (point.size()==0))\n    return;\n\n  Matrix A;\n  for(UInt i=0; i<time.size(); i++)\n  {\n    SphericalHarmonics harm = splinesFile.sphericalHarmonics(time.at(i), factor);\n    Vector anm = harm.x();\n\n    if(A.columns() < anm.rows())\n      A = deformationMatrix(point, gravity, hn, ln, harm.GM(), harm.R(), harm.maxDegree());\n\n    Vector x = A.column(0, anm.rows())*anm;\n    for(UInt k=0; k<point.size(); k++)\n    {\n      disp.at(k).at(i).x() += x(3*k+0);\n      disp.at(k).at(i).y() += x(3*k+1);\n      disp.at(k).at(i).z() += x(3*k+2);\n    }\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldTimeSplines::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    if(time==Time())\n      return SphericalHarmonics();\n    SphericalHarmonics harm = splinesFile.sphericalHarmonics(time, factor).get(maxDegree, std::max(this->minDegree,minDegree), GM, R);\n    if(!hasCovariance)\n      return harm;\n\n    Matrix C = covarianceFile.covariance(time, factor, maxDegree, std::max(this->minDegree,minDegree), harm.GM(), harm.R());\n    if(C.size() == 0)\n      return harm;\n    Vector sigma2;\n    if(C.getType() == Matrix::SYMMETRIC)\n    {\n      sigma2 = Vector(C.rows());\n      for(UInt i=0; i<C.rows(); i++)\n        sigma2(i) = C(i,i);\n    }\n    else\n      sigma2 = C;\n\n    Matrix sigma2cnm(harm.maxDegree()+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(harm.maxDegree()+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    UInt idx = 0;\n    for(UInt n=0; n<=harm.maxDegree(); n++)\n    {\n      sigma2cnm(n,0) = sigma2(idx++);\n      for(UInt m=1; m<=n; m++)\n      {\n        sigma2cnm(n,m) = sigma2(idx++);\n        sigma2snm(n,m) = sigma2(idx++);\n      }\n    }\n\n    return SphericalHarmonics(harm.GM(), harm.R(), harm.cnm(), harm.snm(), sigma2cnm, sigma2snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GravityfieldTimeSplines::sphericalHarmonicsCovariance(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    if((!hasCovariance) || (time==Time()))\n      return Matrix();\n\n    return covarianceFile.covariance(time, factor, maxDegree, std::max(this->minDegree,minDegree), GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldTimeSplines::variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const\n{\n  try\n  {\n    if((!hasCovariance) || (time==Time()))\n      return;\n\n    Double GM        = covarianceFile.GM();\n    Double R         = covarianceFile.R();\n    Matrix C         = covarianceFile.covariance(time, 1.);\n    UInt   maxDegree = covarianceFile.maxDegree();\n\n    // A = linear function from spherical harmonics to point values\n    Matrix A(point.size(), C.rows());\n    for(UInt k=0; k<point.size(); k++)\n    {\n      Matrix Cnm, Snm;\n      SphericalHarmonics::CnmSnm(1/R * point.at(k), maxDegree, Cnm, Snm);\n      Vector kn = kernel.inverseCoefficients(point.at(k), maxDegree);\n      UInt idx = 0;\n      for(UInt n=0; idx<A.columns(); n++)\n      {\n        A(k,idx++) = factor * kn(n) * GM/R * Cnm(n,0);\n        for(UInt m=1; m<=n; m++)\n        {\n          A(k,idx++) = factor * kn(n) * GM/R * Cnm(n,m);\n          A(k,idx++) = factor * kn(n) * GM/R * Snm(n,m);\n        }\n      }\n    }\n\n    if(C.getType() == Matrix::SYMMETRIC) // full covariance matrix?\n      D += A * C * A.trans();\n    else // only variances\n    {\n      for(UInt i=0; i<A.columns(); i++)\n        A.column(i) *= sqrt(C(i,0));\n      rankKUpdate(1., A.trans(), D);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTimeSplines.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTimeSplines.h\n*\n* @brief TimeSplines.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-04-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDTIMESPLINES__\n#define __GROOPS_GRAVITYFIELDTIMESPLINES__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldTimeSplines = R\"(\n\\subsection{TimeSplines}\\label{gravityfieldType:timeSplines}\nRead a time variable gravity field from file\n\\configFile{inputfileTimeSplinesGravityfield}{timeSplinesGravityField}\nrepresented by a spherical harmonics expansion in the spatial domain and spline functions\nin the time domain. If set the expansion is limited in the range between\n\\config{minDegree} and \\config{maxDegree} inclusivly.\n\nThis file can be created for example by \\program{Gravityfield2TimeSplines} or\n\\program{PotentialCoefficients2BlockMeanTimeSplines}.\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileTimeSplinesGravityfield.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief TimeSplines.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldTimeSplines : public GravityfieldBase\n{\n  Bool    hasCovariance;\n  Double  factor;\n  UInt    minDegree;\n  UInt    maxDegree;\n  mutable InFileTimeSplinesGravityfield splinesFile;\n  mutable InFileTimeSplinesCovariance   covarianceFile;\n\npublic:\n  GravityfieldTimeSplines(Config &config);\n\n  // Einfluss des Referenzfieldes im Aufpunkt:\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  // Umrechnung der Parameter in Potentialkoeffizienten\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n  Matrix sphericalHarmonicsCovariance  (const Time &time, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTopography.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTopography.cpp\n*\n* @brief Gravity field from topographic masses.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"parser/expressionParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"parallel/parallel.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldTopography.h\"\n\n/***********************************************/\n\nGravityfieldTopography::GravityfieldTopography(Config &config)\n{\n  try\n  {\n    FileName gridName;\n    ExpressionVariablePtr expressionUpper, expressionLower, expressionRho;\n    cosPsiMax = 1e99;\n\n    readConfig(config, \"inputfileGridRectangular\", gridName,        Config::MUSTSET,  \"\",      \"Digital Terrain Model\");\n    readConfig(config, \"density\",                  expressionRho,   Config::DEFAULT,  \"2670\",  \"expression [kg/m**3]\");\n    readConfig(config, \"radialUpperBound\",         expressionUpper, Config::DEFAULT,  \"data0\", \"expression (variables 'height', 'data', 'L', 'B' and, 'area' are taken from the gridded data\");\n    readConfig(config, \"radialLowerBound\",         expressionLower, Config::DEFAULT,  \"0\",     \"expression (variables 'height', 'data', 'L', 'B' and, 'area' are taken from the gridded data\");\n    readConfig(config, \"distanceMin\",              cosPsiMin,       Config::DEFAULT,  \"0\",     \"[km] min. influence distance (ignore near zone)\");\n    readConfig(config, \"distancePrism\",            cosPsiPrism,     Config::DEFAULT,  \"15\",    \"[km] max. distance for prism formular\");\n    readConfig(config, \"distanceLine\",             cosPsiLine,      Config::DEFAULT,  \"100\",   \"[km] max. distance for radial integration\");\n    readConfig(config, \"distanceMax\",              cosPsiMax,       Config::OPTIONAL, \"\",      \"[km] max. influence distance (ignore far zone)\");\n    readConfig(config, \"factor\",                   factor,          Config::DEFAULT,  \"1.0\",   \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    cosPsiMin   = std::cos(std::min(PI, 1e3/DEFAULT_R * cosPsiMin));\n    cosPsiPrism = std::cos(std::min(PI, 1e3/DEFAULT_R * cosPsiPrism));\n    cosPsiLine  = std::cos(std::min(PI, 1e3/DEFAULT_R * cosPsiLine));\n    cosPsiMax   = std::cos(std::min(PI, 1e3/DEFAULT_R * cosPsiMax));\n\n    // read rectangular grid\n    // ---------------------\n    GriddedDataRectangular grid;\n    readFileGriddedData(gridName, grid);\n    std::vector<Double> radius;\n    grid.geocentric(lambda0, phi0, radius);\n    grid.areaElements(dLambda, dPhi);\n    grid.cellBorders(lambda, phi);\n    for(UInt i=0; i<phi.size(); i++)\n      phi.at(i) = grid.ellipsoid(Angle(0.), Angle(phi.at(i)), 0.).phi();  // geocentric\n\n    // evaluate upper and lower height\n    // -------------------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    expressionUpper->simplify(varList);\n    expressionLower->simplify(varList);\n    expressionRho  ->simplify(varList);\n\n    rLower = Matrix(phi0.size(), lambda0.size());\n    rUpper = Matrix(phi0.size(), lambda0.size());\n    rho    = Matrix(phi0.size(), lambda0.size());\n    for(UInt i=0; i<phi0.size(); i++)\n      for(UInt k=0; k<lambda0.size(); k++)\n      {\n        evaluateDataVariables(grid, i, k, varList);\n        rUpper(i,k) = radius.at(i) + expressionUpper->evaluate(varList);\n        rLower(i,k) = radius.at(i) + expressionLower->evaluate(varList);\n        rho(i,k)    = expressionRho->evaluate(varList);\n      }\n\n    // precompute sin & cos terms\n    // --------------------------\n    sinL.resize(lambda0.size());\n    cosL.resize(lambda0.size());\n    for(UInt k=0; k<lambda0.size(); k++)\n    {\n      sinL.at(k) = std::sin(lambda0.at(k));\n      cosL.at(k) = std::cos(lambda0.at(k));\n    }\n    sinPhi.resize(phi0.size());\n    cosPhi.resize(phi0.size());\n    for(UInt i=0; i<phi0.size(); i++)\n    {\n      sinPhi.at(i) = std::sin(phi0.at(i));\n      cosPhi.at(i) = std::cos(phi0.at(i));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GravityfieldTopography::findRectangle(const Vector3d &point, UInt &colsMin, UInt &rowsMin, UInt &colsMax, UInt &rowsMax) const\n{\n  try\n  {\n    colsMin = 0;\n    rowsMin = 0;\n    colsMax = lambda0.size();\n    rowsMax = phi0.size();\n    if(cosPsiMax < -0.999)\n      return;\n\n    const Double phi    = point.phi();\n    const Double lambda = point.lambda();\n    const Double deltaP = std::acos(cosPsiMax);\n    const Double deltaL = deltaP/std::cos(phi);\n\n    rowsMin = std::distance(phi0.begin(),    std::find_if(phi0.begin(),    phi0.end(),    [&](auto x){return std::fabs(x-phi)    < deltaP;}));\n    colsMin = std::distance(lambda0.begin(), std::find_if(lambda0.begin(), lambda0.end(), [&](auto x){return std::fabs(x-lambda) < deltaL;}));\n    rowsMax = std::distance(std::find_if(phi0.rbegin(),    phi0.rend(),    [&](auto x){return std::fabs(x-phi)    < deltaP;}), phi0.rend());\n    colsMax = std::distance(std::find_if(lambda0.rbegin(), lambda0.rend(), [&](auto x){return std::fabs(x-lambda) < deltaL;}), lambda0.rend());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\nDouble GravityfieldTopography::potential(const Time &/*time*/, const Vector3d &point) const\n{\n  try\n  {\n    const Double r = point.r();\n\n    // find rectangle border\n    UInt colsMin, rowsMin, colsMax, rowsMax;\n    findRectangle(point, colsMin, rowsMin, colsMax, rowsMax);\n\n    Double sum = 0.0;\n    for(UInt k=colsMin; k<colsMax; k++)\n    {\n      const Vector3d p = rotaryZ(Angle(lambda0.at(k))).rotate(point);\n\n      for(UInt i=rowsMin; i<rowsMax; i++)\n      {\n        const Double r1 = rLower(i,k);\n        const Double r2 = rUpper(i,k);\n        const Double dr = r2-r1;\n        if(std::fabs(dr) < 0.001)\n          continue;\n\n        // transformation into local system\n        Double x[2], y[2], z[2];\n        x[0] = -sinPhi[i]*p.x() + cosPhi[i]*p.z();\n        y[0] =  p.y();\n        z[0] = z[1] = cosPhi[i]*p.x() + sinPhi[i]*p.z();\n        const Double rcosPsi = z[0];\n        const Double cosPsi  = rcosPsi/r;\n        if((cosPsi < cosPsiMax) || (cosPsi > cosPsiMin))\n          continue;\n\n\n        // point mass\n        // ----------\n        if(cosPsi < cosPsiLine)\n        {\n          const Double r0 = 0.5*(r2+r1);\n          z[0] -= r0;\n          const Double l0 = std::sqrt(x[0]*x[0] + y[0]*y[0] + z[0]*z[0]);\n          sum += rho(i,k)*r0*r0*dr*dLambda[k]*dPhi[i]/l0;\n          continue;\n        }\n\n        // integration of a radial line\n        // ----------------------------\n        if(cosPsi < cosPsiPrism)\n        {\n          z[0] -= r1;\n          z[1] -= r2;\n          const Double hd = x[0]*x[0]+y[0]*y[0];\n          const Double l1 = std::sqrt(hd + z[0]*z[0]);\n          const Double l2 = std::sqrt(hd + z[1]*z[1]);\n          sum += 0.5*(l2*r2 - l1*r1 + 3*rcosPsi * (l2-l1) + (3*rcosPsi*rcosPsi-r*r) * std::log((l2+r2-rcosPsi)/(l1+r1-rcosPsi)))*rho(i,k)*dLambda[k]*dPhi[i];\n          continue;\n        }\n\n        // prism - Franziska Wild-Pfeiffer Page 26\n        // ---------------------------------------\n        // coordinates relative to prism corners\n        const Double r0 = 0.5*(r2+r1);\n        const Double dy = r0*dLambda[k]*dPhi[i] / std::fabs(phi[i+1]-phi[i]); // Volume of tesseroid: r0*r0*dr*dLambda[k]*dPhi[i] = dx*dy*dz\n        x[0] += r0*std::fabs(phi[i]-phi0[i]);\n        x[1]  = x[0]-r0*std::fabs(phi[i+1]-phi[i]);\n        y[0] += 0.5*dy;\n        y[1]  = y[0]-dy;\n        z[0] -= r1;\n        z[1] -= r2;\n\n        Double sum2 = 0.;\n        for(UInt ix=0; ix<2; ix++)\n          for(UInt iy=0; iy<2; iy++)\n            for(UInt iz=0; iz<2; iz++)\n            {\n              const Double l = std::sqrt(x[ix]*x[ix]+y[iy]*y[iy]+z[iz]*z[iz]);\n              sum2 += std::pow(-1, ix+iy+iz) * (x[ix]*y[iy]*std::log(z[iz]+l) + y[iy]*z[iz]*std::log(x[ix]+l) + z[iz]*x[ix]*std::log(y[iy]+l)\n                     -0.5*(x[ix]*x[ix]*std::atan(y[iy]*z[iz]/(x[ix]*l)) + y[iy]*y[iy]*std::atan(z[iz]*x[ix]/(y[iy]*l)) + z[iz]*z[iz]*std::atan(x[ix]*y[iy]/(z[iz]*l))));\n            }\n        sum += sum2 * rho(i,k);\n      } // for(i=0..rows)\n    } // for(k=0..cols)\n\n    return factor * GRAVITATIONALCONSTANT * sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldTopography::radialGradient(const Time &/*time*/, const Vector3d &point) const\n{\n  try\n  {\n    const Double r = point.r();\n\n    // find rectangle border\n    UInt colsMin, rowsMin, colsMax, rowsMax;\n    findRectangle(point, colsMin, rowsMin, colsMax, rowsMax);\n\n    Double sum = 0.0;\n    for(UInt k=colsMin; k<colsMax; k++)\n    {\n      const Vector3d p = rotaryZ(Angle(lambda0.at(k))).rotate(point);\n\n      for(UInt i=rowsMin; i<rowsMax; i++)\n      {\n        const Double r1 = rLower(i,k);\n        const Double r2 = rUpper(i,k);\n        const Double dr = r2-r1;\n        if(std::fabs(dr)<0.001)\n          continue;\n\n        // transformation into local system\n        Double x[2], y[2], z[2];\n        x[0] = -sinPhi[i]*p.x() + cosPhi[i]*p.z();\n        y[0] =  p.y();\n        z[0] = z[1] = cosPhi[i]*p.x() + sinPhi[i]*p.z();\n        const Double rcosPsi = z[0];\n        const Double cosPsi  = rcosPsi/r;\n        if((cosPsi < cosPsiMax) || (cosPsi > cosPsiMin))\n          continue;\n\n        // point mass\n        // ----------\n        if(cosPsi < cosPsiLine)\n        {\n          const Double r0 = 0.5*(r2+r1);\n          z[0] -= r0;\n          const Double l0 = std::sqrt(x[0]*x[0] + y[0]*y[0] + z[0]*z[0]);\n          sum -= (r*r-r0*rcosPsi)/(l0*l0*l0)*rho(i,k)*r0*r0*dr*dLambda[k]*dPhi[i];\n          continue;\n        }\n\n        // integration of a radial line\n        // ----------------------------\n        if(cosPsi < cosPsiPrism)\n        {\n          z[0] -= r1;\n          z[1] -= r2;\n          const Double hd = x[0]*x[0]+y[0]*y[0];\n          const Double l1 = std::sqrt(hd + z[0]*z[0]);\n          const Double l2 = std::sqrt(hd + z[1]*z[1]);\n          sum += (r1*r1*r1/l1 - r2*r2*r2/l2 + l2*r2 - l1*r1 + 3*rcosPsi * (l2-l1)\n                  +(3*rcosPsi*rcosPsi-r*r) * std::log((l2+r2-rcosPsi)/(l1+r1-rcosPsi)))\n                 * rho(i,k)*dLambda[k]*dPhi[i];\n          continue;\n        }\n\n        // computation point in local system\n        const Vector3d p1(x[0], y[0], z[0]);\n\n        // prism - Franziska Wild-Pfeiffer Page 26\n        // ---------------------------------------\n        // coordinates relative to prism corners\n        const Double r0 = 0.5*(r2+r1);\n        const Double dy = r0*dLambda[k]*dPhi[i] / std::fabs(phi[i+1]-phi[i]); // Volume of tesseroid: r0^2*dr*dLambda[k]*dPhi[i] = dx*dy*dz\n        x[0] += r0*std::fabs(phi[i]-phi0[i]);\n        x[1]  = x[0]-r0*std::fabs(phi[i+1]-phi[i]);\n        y[0] += 0.5*dy;\n        y[1]  = y[0]-dy;\n        z[0] -= r1;\n        z[1] -= r2;\n\n        Vector3d dgxyz;\n        for(UInt ix=0; ix<2; ix++)\n          for(UInt iy=0; iy<2; iy++)\n            for(UInt iz=0; iz<2; iz++)\n            {\n              const Double sign = std::pow(-1, ix+iy+iz);\n              const Double l    = std::sqrt(x[ix]*x[ix]+y[iy]*y[iy]+z[iz]*z[iz]);\n              const Double logx = std::log(x[ix]+l);\n              const Double logy = std::log(y[iy]+l);\n              const Double logz = std::log(z[iz]+l);\n\n              //gradients prism\n              dgxyz.x() += sign * (y[iy]*logz + z[iz]*logy - x[ix]*std::atan(y[iy]*z[iz]/(x[ix]*l)));\n              dgxyz.y() += sign * (z[iz]*logx + x[ix]*logz - y[iy]*std::atan(z[iz]*x[ix]/(y[iy]*l)));\n              dgxyz.z() += sign * (x[ix]*logy + y[iy]*logx - z[iz]*std::atan(x[ix]*y[iy]/(z[iz]*l)));\n            }\n        sum += rho(i,k) * inner(dgxyz, p1); // projection into radial direction\n\n      } // for(i=0..rows)\n    } //for(k=0..cols)\n\n    return factor * GRAVITATIONALCONSTANT * sum/r;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d GravityfieldTopography::gravity(const Time &/*time*/, const Vector3d &point) const\n{\n  try\n  {\n    const Double r = point.r();\n\n    // find rectangle border\n    UInt colsMin, rowsMin, colsMax, rowsMax;\n    findRectangle(point, colsMin, rowsMin, colsMax, rowsMax);\n\n    Vector3d sum;\n    for(UInt k=colsMin; k<colsMax; k++)\n    {\n      const Vector3d p = rotaryZ(Angle(lambda0.at(k))).rotate(point);\n\n      Vector3d sum_local;\n      for(UInt i=rowsMin; i<rowsMax; i++)\n      {\n        const Double r1 = rLower(i,k);\n        const Double r2 = rUpper(i,k);\n        const Double dr = r2-r1;\n        if(std::fabs(dr) < 0.001)\n          continue;\n\n        // transformation into local system\n        Double x[2], y[2], z[2];\n        x[0] = -sinPhi[i]*p.x() + cosPhi[i]*p.z();\n        y[0] =  p.y();\n        z[0] = z[1] = cosPhi[i]*p.x() + sinPhi[i]*p.z();\n        const Double rcosPsi = z[0];\n        const Double cosPsi  = rcosPsi/r;\n        if((cosPsi < cosPsiMax) || (cosPsi > cosPsiMin))\n          continue;\n\n        Vector3d dg;\n        if(cosPsi < cosPsiLine)\n        {\n          // point mass\n          // ----------\n          const Double r0 = 0.5*(r2+r1);\n          z[0] -= r0;\n          const Double l0 = std::sqrt(x[0]*x[0] + y[0]*y[0] + z[0]*z[0]);\n          const Double factor = -r0*r0*dr*dLambda[k]*dPhi[i]/(l0*l0*l0);\n          dg = Vector3d(factor*x[0], factor*y[0], factor*z[0]);\n        }\n        else if(cosPsi < cosPsiPrism)\n        {\n          // integration of a radial line\n          // ----------------------------\n          const Vector3d dr(x[0]/r, y[0]/r, z[0]/r);\n          z[0] -= r1;\n          z[1] -= r2;\n          const Double hd = x[0]*x[0]+y[0]*y[0];\n          const Double l1 = std::sqrt(hd + z[0]*z[0]);\n          const Double l2 = std::sqrt(hd + z[1]*z[1]);\n          const Vector3d dl1(x[0]/l1, y[0]/l1, z[0]/l1);\n          const Vector3d dl2(x[0]/l2, y[0]/l2, z[1]/l2);\n          const Double term1 = l1+r1-rcosPsi;\n          const Double term2 = l2+r2-rcosPsi;\n          const Double term3 = 3*rcosPsi*rcosPsi-r*r;\n          const Double logTerm2Term1 = std::log(term2/term1);\n          const Double dV_dr  = -r * logTerm2Term1*dLambda[k]*dPhi[i];\n          const Double dV_dl1 = -(r1 + 3*rcosPsi + term3/term1)*0.5*dLambda[k]*dPhi[i];\n          const Double dV_dl2 =  (r2 + 3*rcosPsi + term3/term2)*0.5*dLambda[k]*dPhi[i];\n          dg      = dV_dr*dr + dV_dl2*dl2 + dV_dl1*dl1;\n          dg.z() += (3*(l2-l1) + 6*rcosPsi * logTerm2Term1 - term3/term2 + term3/term1)*0.5*dLambda[k]*dPhi[i]; // dV_drcosPsi = dV_dz\n        }\n        else\n        {\n          // prism - Franziska Wild-Pfeiffer Page 26\n          // ---------------------------------------\n          // coordinates relative to prism corners\n          const Double r0 = 0.5*(r2+r1);\n          const Double dy = r0*dLambda[k]*dPhi[i] / std::fabs(phi[i+1]-phi[i]); // Volume of tesseroid: r0*r0*dr*dLambda[k]*dPhi[i] = dx*dy*dz\n          x[0] += r0*std::fabs(phi[i]-phi0[i]);\n          x[1]  = x[0]-r0*std::fabs(phi[i+1]-phi[i]);\n          y[0] += 0.5*dy;\n          y[1]  = y[0]-dy;\n          z[0] -= r1;\n          z[1] -= r2;\n\n          for(UInt ix=0; ix<2; ix++)\n            for(UInt iy=0; iy<2; iy++)\n              for(UInt iz=0; iz<2; iz++)\n              {\n                const Double sign = std::pow(-1, ix+iy+iz);\n                const Double l    = std::sqrt(x[ix]*x[ix]+y[iy]*y[iy]+z[iz]*z[iz]);\n                const Double logx = std::log(x[ix]+l);\n                const Double logy = std::log(y[iy]+l);\n                const Double logz = std::log(z[iz]+l);\n\n                //gradients prism\n                dg.x() += sign * (y[iy]*logz + z[iz]*logy - x[ix]*std::atan(y[iy]*z[iz]/(x[ix]*l)));\n                dg.y() += sign * (z[iz]*logx + x[ix]*logz - y[iy]*std::atan(z[iz]*x[ix]/(y[iy]*l)));\n                dg.z() += sign * (x[ix]*logy + y[iy]*logx - z[iz]*std::atan(x[ix]*y[iy]/(z[iz]*l)));\n              }\n        } // prim\n\n        // rotate back (step 1)\n        sum_local.x() += rho(i,k) * (-sinPhi[i]*dg.x() + cosPhi[i]*dg.z());\n        sum_local.y() += rho(i,k) * dg.y();\n        sum_local.z() += rho(i,k) * (cosPhi[i]*dg.x() + sinPhi[i]*dg.z());\n      } // for(i=0..rows)\n\n      // rotate back (step 2)\n      sum += rotaryZ(Angle(-lambda0.at(k))).rotate(sum_local);\n    } //for(k=0..cols)\n\n    return factor * GRAVITATIONALCONSTANT * sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTensor3d GravityfieldTopography::gravityGradient(const Time &/*time*/, const Vector3d &/*point*/) const\n{\n  try\n  {\n    throw(Exception(\"not implemented yet\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d GravityfieldTopography::deformation(const Time &/*time*/, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  SphericalHarmonics harm = sphericalHarmonics(Time(), hn.rows()-1, 0, DEFAULT_GM, DEFAULT_R);\n  return harm.deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldTopography::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                         const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  SphericalHarmonics harm = sphericalHarmonics(Time(), hn.rows()-1, 0, DEFAULT_GM, DEFAULT_R);\n  for(UInt k=0; k<point.size(); k++)\n  {\n    Vector3d d = harm.deformation(point.at(k), gravity.at(k), hn, ln);\n    for(UInt i=0; i<time.size(); i++)\n      disp.at(k).at(i) = d;\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldTopography::variance(const Time &/*time*/, const std::vector<Vector3d> &/*point*/, const Kernel &/*kernel*/, Matrix &/*D*/) const\n{\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldTopography::sphericalHarmonics(const Time &/*time*/, UInt /*maxDegree*/, UInt /*minDegree*/, Double /*GM*/, Double /*R*/) const\n{\n  try\n  {\n    throw(Exception(\"Conversion to spherical harmonics not implemented\\nPlease use program GriddedTopography2PotentialCoefficients before.\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTopography.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTopography.h\n*\n* @brief Gravity field from topographic masses.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDTOPOGRAPHY__\n#define __GROOPS_GRAVITYFIELDTOPOGRAPHY__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldTopography = R\"(\n\\subsection{Topography}\\label{gravityfieldType:topography}\nThe gravity is integrated from a topographic mass distribution.\nFor each grid point in \\configFile{inputfileGridRectangular}{griddedData} a prisma with\n\\config{density} is assumed. The horizontal extension is computed from the grid spacing\nand the vertical extension is given by \\config{radialLowerBound}\nand \\config{radialUpperBound} above ellipsoid. All values are expressions and computed\nfor each point with given data in the grid file. The standard variables for grids\nare available, see~\\reference{dataVariables}{general.parser:dataVariables}.\n\nExample: The grid file contains the orthometric height of the topography in the first\ncolumn, the geoid height in the second and the mean density of each prism in the third\ncolumn. In this case the following settings should be used:\n\\begin{itemize}\n\\item \\config{radialUpperBound} = \\verb|data0+data1|,\n\\item \\config{radialLowerBound} = \\verb|data1|,\n\\item \\config{density} = \\verb|data2|.\n\\end{itemize}\n\nAs the prim computation is time consuming a maximum distance around the evaluation point\ncan defined with \\config{distancePrism}. Afterwards a simplified radial line\n(the prism mass is concentrated to a line in the center) is used up to\na distance of \\config{distanceLine}. At last the prim is approximated by a point mass\nin the center up to a distance \\config{distanceMax} (if set). Prisms nearby the evaluation\npoint can be excluded with \\config{distanceMin}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravity field from topographic masses.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldTopography : public GravityfieldBase\n{\n  Double              factor;\n  std::vector<Angle>  lambda0, phi0;\n  std::vector<Double> lambda, phi, dLambda, dPhi;\n  std::vector<Double> sinL, cosL, sinPhi, cosPhi;\n  Matrix              rLower, rUpper, rho;\n  Double              cosPsiMin, cosPsiPrism, cosPsiLine, cosPsiMax;\n\n  inline void findRectangle(const Vector3d &point, UInt &colsMin, UInt &rowsMin, UInt &colsMax, UInt &rowsMax) const;\n\npublic:\n  GravityfieldTopography(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n  void     variance       (const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTrend.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTrend.cpp\n*\n* @brief Gravityfield as trend.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-06-15\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/gravityfield/gravityfieldTrend.h\"\n\n/***********************************************/\n\nGravityfieldTrend::GravityfieldTrend(Config &config)\n{\n  try\n  {\n    readConfig(config, \"gravityfield\", gravityfield, Config::MUSTSET, \"\",           \"this field is multiplicated by (time-time0)/timeStep\");\n    readConfig(config, \"timeStart\",    time0,        Config::MUSTSET, STRING_J2000, \"reference time\");\n    readConfig(config, \"timeStep\",     timeStep,     Config::MUSTSET, \"365.25\",     \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GravityfieldTrend::factor(Time time) const\n{\n  if(time == Time())\n    return 0;\n  return (time-time0).mjd()/timeStep.mjd();\n}\n\n/***********************************************/\n\nDouble GravityfieldTrend::potential(const Time &time, const Vector3d &point) const\n{\n  return factor(time) * gravityfield->potential(time, point);\n}\n\n/***********************************************/\n\nDouble GravityfieldTrend::radialGradient(const Time &time, const Vector3d &point) const\n{\n  return factor(time) * gravityfield->radialGradient(time, point);\n}\n\n/***********************************************/\n\nDouble GravityfieldTrend::field(const Time &time, const Vector3d &point, const Kernel &kernel) const\n{\n  return factor(time) * gravityfield->field(time, point, kernel);\n}\n\n/***********************************************/\n\nVector3d GravityfieldTrend::gravity(const Time &time, const Vector3d &point) const\n{\n  return factor(time) * gravityfield->gravity(time, point);\n}\n\n/***********************************************/\n\nTensor3d GravityfieldTrend::gravityGradient(const Time &time, const Vector3d &point) const\n{\n  return factor(time) * gravityfield->gravityGradient(time, point);\n}\n\n/***********************************************/\n\nVector3d GravityfieldTrend::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return factor(time) * gravityfield->deformation(time, point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid GravityfieldTrend::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                    const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  if((time.size()==0) || (point.size()==0))\n    return;\n\n  std::vector<std::vector<Vector3d>> disp2(point.size());\n  for(UInt k=0; k<point.size(); k++)\n    disp2.at(k).resize(time.size());\n  gravityfield->deformation(time, point, gravity, hn, ln, disp2);\n\n  for(UInt i=0; i<time.size(); i++)\n  {\n    const Double f = factor(time.at(i));\n    for(UInt k=0; k<point.size(); k++)\n      disp.at(k).at(i) += f * disp2.at(k).at(i);\n  }\n}\n\n/***********************************************/\n\nvoid GravityfieldTrend::variance(const Time &/*time*/, const std::vector<Vector3d> &/*point*/, const Kernel &/*kernel*/, Matrix &/*D*/) const\n{\n}\n\n/***********************************************/\n\nSphericalHarmonics GravityfieldTrend::sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  return factor(time) * gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/gravityfield/gravityfieldTrend.h",
    "content": "/***********************************************/\n/**\n* @file gravityfieldTrend.h\n*\n* @brief Gravityfield as trend.\n* @see Gravityfield\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-06-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRAVITYFIELDTREND__\n#define __GROOPS_GRAVITYFIELDTREND__\n\n// Latex documentation\n#ifdef DOCSTRING_Gravityfield\nstatic const char *docstringGravityfieldTrend = R\"(\n\\subsection{Trend}\\label{gravityfieldType:trend}\nThe given \\configClass{gravityfield}{gravityfieldType} is interpreted\nas trend function and the result is computed at time $t$ as follows\n\\begin{equation}\nV(\\M x,t) = \\frac{t-t_0}{\\Delta t}V(\\M x),\n\\end{equation}\nwith $t_0$ is \\config{timeStart} and $\\Delta t$ is \\config{timeStep}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravityfield as trend.\n* @ingroup gravityfieldGroup\n* @see Gravityfield */\nclass GravityfieldTrend : public GravityfieldBase\n{\n  Time time0;\n  Time timeStep;\n  GravityfieldPtr gravityfield;\n\n  Double factor(Time time) const;\n\npublic:\n  GravityfieldTrend(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point) const;\n  Double   radialGradient (const Time &time, const Vector3d &point) const;\n  Double   field          (const Time &time, const Vector3d &point, const Kernel &kernel) const;\n  Vector3d gravity        (const Time &time, const Vector3d &point) const;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point) const;\n  Vector3d deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln) const;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                           const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, UInt maxDegree, UInt minDegree, Double GM, Double R) const;\n\n  void variance(const Time &time, const std::vector<Vector3d> &point, const Kernel &kernel, Matrix &D) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRAVITYFIELD__ */\n"
  },
  {
    "path": "source/classes/grid/grid.cpp",
    "content": "/***********************************************/\n/**\n* @file grid.cpp\n*\n* @brief point distributions on the sphere/ellipsoid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Grid\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/grid/gridGeograph.h\"\n#include \"classes/grid/gridTriangleVertex.h\"\n#include \"classes/grid/gridTriangleCenter.h\"\n#include \"classes/grid/gridGauss.h\"\n#include \"classes/grid/gridReuter.h\"\n#include \"classes/grid/gridCorput.h\"\n#include \"classes/grid/gridDriscoll.h\"\n#include \"classes/grid/gridSinglePoint.h\"\n#include \"classes/grid/gridSinglePointCartesian.h\"\n#include \"classes/grid/gridFile.h\"\n#include \"classes/grid/grid.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Grid, \"gridType\",\n                      GridGeograph,\n                      GridTriangleVertex,\n                      GridTriangleCenter,\n                      GridGauss,\n                      GridReuter,\n                      GridCorput,\n                      GridDriscoll,\n                      GridSinglePoint,\n                      GridSinglePointCartesian,\n                      GridFile)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(Grid, \"gridType\")\n\n/***********************************************/\n\nGrid::Grid(Config &config, const std::string &name)\n{\n  try\n  {\n    std::unique_ptr<GridBase> base;\n\n    std::string choice;\n    while(readConfigChoice(config, name, choice, Config::OPTIONAL, \"\", \"point distributions on the sphere/ellipsoid\"))\n    {\n      if(readConfigChoiceElement(config, \"geograph\",       choice, \"along lines of geographical coordinates\"))\n        base = std::unique_ptr<GridBase>(new GridGeograph(config));\n      if(readConfigChoiceElement(config, \"triangleVertex\", choice, \"triangle grid (vertcies)\"))\n        base = std::unique_ptr<GridBase>(new GridTriangleVertex(config));\n      if(readConfigChoiceElement(config, \"triangleCenter\", choice, \"triangle grid (center points)\"))\n        base = std::unique_ptr<GridBase>(new GridTriangleCenter(config));\n      if(readConfigChoiceElement(config, \"gauss\",          choice, \"gauss-legendre grid\"))\n        base = std::unique_ptr<GridBase>(new GridGauss(config));\n      if(readConfigChoiceElement(config, \"reuter\",         choice, \"reuter grid\"))\n        base = std::unique_ptr<GridBase>(new GridReuter(config));\n      if(readConfigChoiceElement(config, \"corput\",         choice, \"pseudo random distribution\"))\n        base = std::unique_ptr<GridBase>(new GridCorput(config));\n      if(readConfigChoiceElement(config, \"driscoll\",       choice, \"driscoll-healy grid\"))\n        base = std::unique_ptr<GridBase>(new GridDriscoll(config));\n      if(readConfigChoiceElement(config, \"singlePoint\",    choice, \"one single point\"))\n        base = std::unique_ptr<GridBase>(new GridSinglePoint(config));\n      if(readConfigChoiceElement(config, \"singlePointCartesian\", choice, \"one single point\"))\n        base = std::unique_ptr<GridBase>(new GridSinglePointCartesian(config));\n      if(readConfigChoiceElement(config, \"file\",           choice, \"read points (with values) from file\"))\n        base = std::unique_ptr<GridBase>(new GridFile(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n\n      if(points_.empty())\n      {\n        std::swap(points_, base->points);\n        std::swap(areas_,  base->areas);\n      }\n      else\n      {\n        points_.insert(points_.end(), base->points.begin(), base->points.end());\n        areas_.insert (areas_.end(),  base->areas.begin(),  base->areas.end());\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/grid/grid.h",
    "content": "/***********************************************/\n/**\n* @file grid.h\n*\n* @brief Point distributions on the sphere/ellipsoid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRID__\n#define __GROOPS_GRID__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGrid = R\"(\n\\section{Grid}\\label{gridType}\nThis class generates a set of grid points. In a first step, the grid\nis always generated globally, with \\configClass{border}{borderType} a regional\nsubset of points can be extracted from the global grid. The parameters\n\\config{R} and \\config{inverseFlattening} define the shape of the ellipsoid\non which the grid is generated. In case \\config{inverseFlattening} is\nchosen as zero, a sphere is used. With \\config{height} the distance of\nthe points above the ellipsoid can be defined. In addition to the location\nof the points, weights are assigned to each of the points. These weights\ncan be regarded as the surface element associated with each grid point.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup gridGroup Grid\n* @brief Point distributions on the sphere/ellipsoid.\n* @ingroup classesGroup\n* The interface is given by @ref Grid. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Grid;\ntypedef std::shared_ptr<Grid> GridPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Point distributions on the sphere/ellipsoid.\n* An instance of this class can be created with @ref readConfig. */\nclass Grid\n{\n  std::vector<Vector3d> points_;\n  std::vector<Double>   areas_;\n\npublic:\n  /// Constructor.\n  Grid(Config &config, const std::string &name);\n\n  /** @brief Point distribution. */\n  const std::vector<Vector3d> &points() const {return points_;}\n\n  /** @brief Area element relating to each point.\n  * Computed on a unit sphere (only approximative). */\n  const std::vector<Double> &areas() const {return areas_;}\n\n  /** @brief creates an derived instance of this class. */\n  static GridPtr create(Config &config, const std::string &name) {return GridPtr(new Grid(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Grid.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and an class without points is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] grid Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Grid */\ntemplate<> Bool readConfig(Config &config, const std::string &name, GridPtr &grid, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass GridBase\n{\npublic:\n  std::vector<Vector3d> points;\n  std::vector<Double>   areas;\n\n  virtual ~GridBase() {}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRID__ */\n\n"
  },
  {
    "path": "source/classes/grid/gridCorput.h",
    "content": "/***********************************************/\n/**\n* @file gridCorput.h\n*\n* @brief Corput distribution.\n* @see Grid\n* Pseudo random distribution.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDCORPUT__\n#define __GROOPS_GRIDCORPUT__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridCorput = R\"(\n\\subsection{Corput}\nThis kind of grid distributes an arbitrarily chosen number of $I$ points\n(defined by \\config{globalPointsCount}) following a recursive, quasi random sequence.\nIn longitudinal direction the pattern follows\n\\begin{equation}\n\\Delta\\lambda=\\frac{2\\pi}{I}\\qquad\\Rightarrow\\qquad\\frac{\\Delta\\lambda}{2}+\\lambda_i=i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 1\\leq i\\leq I.\n\\end{equation}\nThis implies that every grid point features a unique longitude, with equi-angular\nlongitudinal differences.\n\nThe polar distance in the form $t_i=\\cos\\vartheta_i$ for each point is determined\nby the following recursive sequence:\n\\begin{itemize}\n\\item Starting from an interval $t\\in[-1,1]$.\n\\item If $I=1$, then the midpoint of the interval is returned as result of\nthe sequence, and the sequence is terminated.\n\\item If the number of points is uneven, the  midpoint is included into the list of $t_i$.\n\\item Subsequently, the interval is bisected into an upper and lower half,\n       and the sequence is called for both halves.\n\\item $t$ from upper and lower half are alternately sorted into the list of $t_i$.\n\\item The polar distances are calculated by\n\\begin{equation}\n\\vartheta_i=\\arccos\\, t_i.\n\\end{equation}\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Corput distribution.\n* Pseudo random distribution.\n* @ingroup gridGroup\n* @see Grid */\nclass GridCorput : public GridBase\n{\n  static std::vector<Double> sequence(Double min, Double max, UInt n);\n\npublic:\n  GridCorput(Config &config);\n};\n\n/***********************************************/\n\ninline GridCorput::GridCorput(Config &config)\n{\n  try\n  {\n    UInt      numberOfGlobalPoints;\n    Double    a, f, height;\n    BorderPtr border;\n\n    readConfig(config, \"globalPointsCount\", numberOfGlobalPoints, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"height\",            height,     Config::DEFAULT,  \"0.0\",                  \"ellipsoidal height\");\n    readConfig(config, \"R\",                 a,          Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,          Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border,     Config::DEFAULT,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Ellipsoid ellipsoid(a,f);\n    std::vector<Double> t = sequence(-1.0, 1.0, numberOfGlobalPoints);\n    for(UInt i=0; i<numberOfGlobalPoints; i++)\n    {\n      Angle L(fmod(2*PI*(i+0.5)/numberOfGlobalPoints+PI,2*PI)-PI);\n      Angle B(PI/2-acos(t.at(i)));\n      if(border->isInnerPoint(L,B))\n      {\n        points.push_back(ellipsoid(L, B, height));\n        areas.push_back(4*PI/numberOfGlobalPoints); // average area\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Double> GridCorput::sequence(Double min, Double max, UInt n)\n{\n  Double middle = (max+min)/2.0;\n\n  UInt nr=0;\n  std::vector<Double> t(n);\n\n  // Ist ein Punkt in der Mitte?\n  if(n%2==1) t.at(nr++) = middle;\n\n  // Wenn nur ein Punkt, dann schon fertig\n  if(n==1) return t;\n\n  // Links und rechts erzeugen\n  std::vector<Double> left  = sequence(min, middle, n/2);\n  std::vector<Double> right = sequence(middle, max, n/2);\n\n  // Abwechselnd sortieren\n  for(UInt i=0; i<n/2; i++)\n  {\n    t.at(nr++) = left.at(i);\n    t.at(nr++) = right.at(i);\n  }\n\n  return t;\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridDriscoll.h",
    "content": "/***********************************************/\n/**\n* @file gridDriscoll.h\n*\n* @brief Driscoll-Healy grid.\n* @see Grid\n*\n* @author Annette Eicker\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDDISCROLL__\n#define __GROOPS_GRIDDISCROLL__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridDriscoll = R\"(\n\\subsection{Driscoll}\nThe Driscoll-Healy grid, has equiangular spacing along the meridians as well\nas along the circles of latitude. In longitudinal direction (along the parallels),\nthese angular differences for a given \\config{dimension} $L$ coincide with those\ndescribed for the corresponding geographical grid and Gauss grid. Along the meridians,\nthe size of the latitudinal differences is half the size compared to the geographical\ngrid. This results in the following point pattern,\n\\begin{equation}\n\\begin{split}\n\\Delta\\lambda=\\frac{\\pi}{L}\\qquad&\\Rightarrow\\qquad\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad&\\mbox{with}\\qquad 0\\leq i< 2L, \\\\\n\\Delta\\vartheta=\\frac{\\pi}{2L}\\qquad&\\Rightarrow\\qquad\\vartheta_j=j\\cdot\\Delta\\vartheta\\qquad&\\mbox{with}\\qquad 1\\leq j\\leq 2L.\n\\end{split}\n\\end{equation}\nConsequently, the number of grid points is\n\\begin{equation}\nI=4\\cdot L^2.\n\\end{equation}\nThe weights are given by\n\\begin{equation}\nw_i=\\Delta\\lambda\\frac{4}{2L}\\sin(\\vartheta_i)\\sum_{l=0}^{L-1}\\frac{\\sin\\left[ (2l+1)\\;\\vartheta_i\\right] }{2l+1}.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Driscoll-Healy grid.\n* @ingroup gridGroup\n* @see Grid */\nclass GridDriscoll : public GridBase\n{\npublic:\n  GridDriscoll(Config &config);\n};\n\n/***********************************************/\n\ninline GridDriscoll::GridDriscoll(Config &config)\n{\n  try\n  {\n    UInt      dim;\n    Double    a, f, height;\n    BorderPtr border;\n\n    readConfig(config, \"dimension\",         dim,        Config::MUSTSET,  \"\",                     \"number of parallels = 2*dimension\");\n    readConfig(config, \"height\",            height,     Config::DEFAULT,  \"0.0\",                  \"ellipsoidal height\");\n    readConfig(config, \"R\",                 a,          Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,          Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border,     Config::DEFAULT,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Double deltaLambda = 2*PI/(2*dim); // # Meridiane gleich # Parallelkreise\n    Double deltaPhi = PI/(2*dim); // # of Parallels muss gleich 2*n sein\n    Double lambda;\n    Double phi;\n    Vector weights(2*dim);\n\n    Ellipsoid ellipsoid(a,f);\n    for(UInt i=0; i<2*dim; i++)   //2*dim Abschnitte entlang des Meridians\n    {\n      Double sum = 0;\n      for(UInt m=0; m<dim; m++)\n        sum += 1.0/(2*m+1)*sin((2*m+1)*i*PI/(2*dim));\n      weights(i) = deltaLambda*4.0/(2*dim)*sin(i*deltaPhi)*sum;\n\n      for(UInt j=0; j<2*dim; j++)  //2*dim Abschnitte entlang des Breitenkreises\n      {\n        lambda = j*deltaLambda+0.5*deltaLambda;\n        phi    = PI/2-i*deltaPhi;\n\n        if(border->isInnerPoint(Angle(lambda), Angle(phi)))\n        {\n          points.push_back(ellipsoid(Angle(lambda), Angle(phi), height));\n          areas.push_back(weights(i));\n        }\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridFile.h",
    "content": "/***********************************************/\n/**\n* @file gridFile.h\n*\n* @brief Read grid from file.\n* @see Grid\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-01-11\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDFILE__\n#define __GROOPS_GRIDFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridFile = R\"(\n\\subsection{File}\\label{gridType:file}\nIn this class grid is read from a file, which is given by \\configFile{inputfileGrid}{griddedData}.\nA corresponding file can be generated with \\program{GriddedDataCreate} or with \\program{Matrix2GriddedData}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read grid from file.\n* @ingroup gridGroup\n* @see Grid */\nclass GridFile : public GridBase\n{\npublic:\n  GridFile(Config &config);\n};\n\n/***********************************************/\n\ninline GridFile::GridFile(Config &config)\n{\n  try\n  {\n    FileName  fileNameGrid;\n    BorderPtr border;\n\n    readConfig(config, \"inputfileGrid\",  fileNameGrid, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"border\",         border,       Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n\n    if(!border)\n    {\n      std::swap(points, grid.points);\n      std::swap(areas,  grid.areas);\n      return;\n    }\n\n    for(UInt i=0; i<grid.points.size(); i++)\n      if(border->isInnerPoint(grid.points.at(i), grid.ellipsoid))\n      {\n        points.push_back(grid.points.at(i));\n        if(grid.areas.size())\n          areas.push_back(grid.areas.at(i));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridGauss.h",
    "content": "/***********************************************/\n/**\n* @file gridGauss.h\n*\n* @brief Gauss-Legendre grid.\n* @see Grid\n*\n* @author Annette Eicker\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDGAUSS__\n#define __GROOPS_GRIDGAUSS__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridGauss = R\"(\n\\subsection{Gauss}\n The grid features equiangular spacing along circles of latitude with\n \\config{parallelsCount} defining the number $L$ of the parallels.\n\\begin{equation}\n\\Delta\\lambda=\\frac{\\pi}{L}\\qquad\\Rightarrow\\qquad\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 0\\leq i< 2L.\n\\end{equation}\nAlong the meridians the points are located at $L$ parallels at\nthe $L$ zeros $\\vartheta_j$ of the Legendre polynomial of degree~$L$,\n\\begin{equation}\nP_L(\\cos\\vartheta_j)=0.\n\\end{equation}\nConsequently, the number of grid points sums up to\n\\begin{equation}\nI=2\\cdot L^2.\n\\end{equation}\nThe weights can be calculated according to\n\\begin{equation}\nw_i(L)=\\Delta\\lambda\\frac{2}{(1-t_i^2)(P'_{L}(\\cos(\\vartheta _i)))^2},\\label{weights}\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/legendrePolynomial.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gauss-Legendre grid.\n* @ingroup gridGroup\n* @see Grid */\nclass GridGauss : public GridBase\n{\npublic:\n  GridGauss(Config &config);\n};\n\n/***********************************************/\n\ninline GridGauss::GridGauss(Config &config)\n{\n  try\n  {\n    UInt      numberOfParallels;\n    Double    a, f;\n    BorderPtr border;\n\n    readConfig(config, \"parallelsCount\",    numberOfParallels, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"R\",                 a,                 Config::DEFAULT, STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,                 Config::DEFAULT, STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border,            Config::DEFAULT, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Ellipsoid ellipsoid(a,f);\n    Double deltaLambda = 2*PI/(2*numberOfParallels); // # Meridiane: 2*anz_nullst\n    // number of zeros is number of latitudes\n    Vector zeros, weights;\n    LegendrePolynomial::zeros(numberOfParallels, zeros, weights);\n    for(UInt i=0; i<numberOfParallels; i++)\n      for(Double lambda=-PI+deltaLambda/2.0; lambda<=PI; lambda+=deltaLambda)\n      {\n        // create point on unit sphere\n        Vector3d point = polar(Angle(lambda), Angle(PI/2-acos(zeros(i))), 1.0);\n        // from sphere to ellipsoidal surface\n        Double r = ellipsoid.b()/sqrt(1-ellipsoid.e()*ellipsoid.e()*cos(point.phi())*cos(point.phi()));\n        point *= r;\n\n        Angle  L,B;\n        Double h;\n        ellipsoid(point, L,B,h);\n\n        if(border->isInnerPoint(L,B))\n        {\n          points.push_back(point);\n          areas.push_back(deltaLambda * weights(i));\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridGeograph.h",
    "content": "/***********************************************/\n/**\n* @file gridGeograph.h\n*\n* @brief Geographical grid.\n* @see Grid\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDGEOGRAPH__\n#define __GROOPS_GRIDGEOGRAPH__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridGeograph = R\"(\n\\subsection{Geograph}\nThe geographical grid is an equal-angular point distribution with points\nlocated along meridians and along circles of latitude. \\config{deltaLambda}\ndenotes the angular difference between adjacent points along meridians and\n\\config{deltaPhi} describes the angular difference between adjacent points\nalong circles of latitude. The point setting results as follows:\n\\begin{equation}\n\\lambda_i=\\frac{\\Delta\\lambda}{2}+i\\cdot\\Delta\\lambda\\qquad\\mbox{with}\\qquad 0\\leq i< \\frac{360^\\circ}{\\Delta\\lambda},\n\\end{equation}\n\\begin{equation}\n\\varphi_j=-90^\\circ+\\frac{\\Delta\\varphi}{2}+j\\cdot\\Delta\\varphi\\qquad\\mbox{with}\\qquad 0\\leq j<\\frac{180^\\circ}{\\Delta\\varphi}.\n\\end{equation}\nThe number of grid points can be determined by\n\\begin{equation}\nI=\\frac{360^\\circ}{\\Delta\\lambda}\\cdot\\frac{180^\\circ}{\\Delta\\varphi}.\n\\end{equation}\nThe weights are calculated according to\n\\begin{equation}\nw_i=\\int\\limits_{\\lambda_i-\\frac{\\Delta\\lambda}{2}}^{\\lambda_i+\\frac{\\Delta\\lambda}{2}}\\int\\limits_{\\vartheta_i-\\frac{\\Delta\\vartheta}{2}}^{\\vartheta_i+\\frac{\\Delta\\vartheta}{2}}=2\\cdot\\Delta\\lambda\\sin(\\Delta\\vartheta)\\sin(\\vartheta_i).\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Geographical grid.\n* @ingroup gridGroup\n* @see Grid */\nclass GridGeograph : public GridBase\n{\npublic:\n  GridGeograph(Config &config);\n};\n\n/***********************************************/\n\ninline GridGeograph::GridGeograph(Config &config)\n{\n  try\n  {\n    Angle       deltaLambda, deltaPhi;\n    Double      a, f, height;\n    BorderPtr   border;\n\n    readConfig(config, \"deltaLambda\",       deltaLambda, Config::MUSTSET,  \"1\", \"\");\n    readConfig(config, \"deltaPhi\",          deltaPhi,    Config::MUSTSET,  \"1\", \"\");\n    readConfig(config, \"height\",            height,      Config::DEFAULT,  \"0.0\",                  \"ellipsoidal height expression (variables 'height', 'L', 'B')\");\n    readConfig(config, \"R\",                 a,           Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,           Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border,      Config::DEFAULT,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Ellipsoid ellipsoid(a,f);\n    for(Double phi=PI/2-deltaPhi/2.0; phi>=-PI/2; phi-=deltaPhi)\n    {\n      Double dPhi = std::sin(ellipsoid(Angle(0), Angle(phi+0.5*deltaPhi), 0).phi())\n                  - std::sin(ellipsoid(Angle(0), Angle(phi-0.5*deltaPhi), 0).phi());\n      for(Double lambda=-PI+deltaLambda/2.0; lambda<=PI; lambda+=deltaLambda)\n        if(border->isInnerPoint(Angle(lambda), Angle(phi)))\n        {\n          points.push_back(ellipsoid(Angle(lambda), Angle(phi), height));\n          areas.push_back(deltaLambda * dPhi);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridReuter.h",
    "content": "/***********************************************/\n/**\n* @file gridReuter.h\n*\n* @brief Reuter grid.\n* @see Grid\n*\n* @author Annette Eicker\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDREUTER__\n#define __GROOPS_GRIDREUTER__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridReuter = R\"(\n\\subsection{Reuter}\nThe Reuter grid features equi-distant spacing along the meridians determined\nby the control parameter~$\\gamma$ according to\n\\begin{equation}\n\\Delta\\vartheta=\\frac{\\pi}{\\gamma}\\qquad\\Rightarrow\\vartheta_j=j\\Delta\\vartheta,\\qquad\\mbox{with}\\qquad 1\\leq j\\leq \\gamma-1.\n\\end{equation}\nThus $\\gamma+1$ denotes the number of points per meridian, as the two poles\nare included in the point distribution as well. Along the circles of latitude,\nthe number of grid points decreases with increasing latitude in order to achieve\nan evenly distributed point pattern. This number is chosen, so that the points\nalong each circle of latitude have the same spherical distance as two adjacent\nlatitudes. The resulting relationship is given by\n\\begin{equation}\\label{eq:sphericalDistance}\n\\Delta\\vartheta=\\arccos\\left( \\cos^2\\vartheta_j+\\sin^2\\vartheta_j\\cos\\Delta\\lambda_j\\right).\n\\end{equation}\nThe left hand side of this equation is the spherical distance between adjacent\nlatitudes, the right hand side stands for the spherical distance between two points\nwith the same polar distance $\\vartheta_j$ and a longitudinal difference of\n$\\Delta\\lambda_i$. This longitudinal distance can be adjusted depending on\n$\\vartheta_j$ to fulfill Eq.~\\eqref{eq:sphericalDistance}. The resulting\nformula for $\\Delta\\lambda_i$ is\n\\begin{equation}\\label{eq:deltaLambdai}\n\\Delta\\lambda_j=\\arccos\\left( \\frac{\\sin\\Delta\\vartheta -\\cos^2\\vartheta_j}{\\sin^2\\vartheta_j}\\right).\n\\end{equation}\nThe number of points~$\\gamma_j$ for each circle of latitude can then be determined by\n\\begin{equation}\\label{eq:gammai}\n\\gamma_j=\\left[ \\frac{2\\pi}{\\Delta\\lambda_j}\\right] .\n\\end{equation}\nHere the Gauss bracket $[x]$ specifies the largest integer equal to or less than $x$.\nThe longitudes are subsequently determined by\n\\begin{equation}\n\\lambda_{ij}=\\frac{\\Delta\\lambda_j}{2}+i\\cdot(2\\pi/\\gamma_j),\\qquad\\mbox{with}\\qquad 0\\leq i< \\gamma_j.\n\\end{equation}\nThe number of grid points can be estimated by\n\\begin{equation}\\label{eq:numberReuter}\nI=\\leq 2+\\frac{4}{\\pi}\\gamma^2,\n\\end{equation}\nThe $\\leq$ results from the fact that the $\\gamma_j$ are restricted to integer values.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Reuter grid.\n* @ingroup gridGroup\n* @see Grid */\nclass GridReuter : public GridBase\n{\npublic:\n  GridReuter(Config &config);\n};\n\n/***********************************************/\n\ninline GridReuter::GridReuter(Config &config)\n{\n  try\n  {\n    UInt      gamma;\n    Double    a, f, height;\n    BorderPtr border;\n\n    readConfig(config, \"gamma\",             gamma,  Config::MUSTSET,  \"\",                     \"number of parallels\");\n    readConfig(config, \"height\",            height, Config::DEFAULT,  \"0.0\",                  \"ellipsoidal height\");\n    readConfig(config, \"R\",                 a,      Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,      Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border, Config::DEFAULT,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Angle     deltaB(PI/gamma);\n    Ellipsoid ellipsoid(a,f);\n\n    // north pole\n    Angle L(0.0);\n    Angle B(PI/2);\n    if(border->isInnerPoint(L,B))\n    {\n      points.push_back(ellipsoid(L, B, height));\n      areas.push_back(2*PI*(1-std::cos(deltaB/2.0)));\n    }\n\n    // other points\n    for(UInt i=1; i<gamma; i++)\n    {\n      Double theta   = i* PI/gamma;\n      UInt   gamma_i = static_cast<UInt>(std::floor(2*PI/std::acos((std::cos(PI/gamma)-std::cos(theta)*std::cos(theta))/(std::sin(theta)*std::sin(theta)))));\n      Angle  B(PI/2-theta);\n      Angle  deltaL(2*PI/gamma_i);\n\n      for(UInt j=1; j<=gamma_i; j++)\n      {\n        Angle L(fmod((j+0.5)*(2*PI/gamma_i)+PI, 2*PI)-PI);\n        if(border->isInnerPoint(L,B))\n        {\n          points.push_back(ellipsoid(L, B, height));\n          areas.push_back(deltaL * 2.0 * std::sin(deltaB/2.0) * std::cos(B));\n        }\n      }\n    }\n\n    // south pole\n    L = Angle(0.0);\n    B = Angle(-PI/2);\n    if(border->isInnerPoint(L,B))\n    {\n      points.push_back(ellipsoid(L, B, height));\n      areas.push_back(2*PI*(1-std::cos(deltaB/2.0)));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridSinglePoint.h",
    "content": "/***********************************************/\n/**\n* @file gridSinglePoint.h\n*\n* @brief Single point.\n* @see Grid\n* single point at sphere/ellipsoid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-11-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDSINGLEPOINT__\n#define __GROOPS_GRIDSINGLEPOINT__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridSinglePoint = R\"(\n\\subsection{SinglePoint}\nCreates one single point.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Single point.\n* @ingroup gridGroup\n* @see Grid */\nclass GridSinglePoint : public GridBase\n{\npublic:\n  GridSinglePoint(Config &config);\n};\n\n/***********************************************/\n\ninline GridSinglePoint::GridSinglePoint(Config &config)\n{\n  try\n  {\n    Angle     L, B;\n    Double    a, f, height, area = NAN_EXPR;\n\n    readConfig(config, \"L\",                 L,          Config::MUSTSET,  \"\",   \"longitude\");\n    readConfig(config, \"B\",                 B,          Config::MUSTSET,  \"\",   \"latitude\");\n    readConfig(config, \"height\",            height,     Config::DEFAULT,  \"0.\", \"ellipsoidal height\");\n    readConfig(config, \"area\",              area,       Config::OPTIONAL, \"\",   \"associated area element on unit sphere\");\n    readConfig(config, \"R\",                 a,          Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,          Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    if(isCreateSchema(config)) return;\n\n    Ellipsoid ellipsoid(a,f);\n    points.push_back(ellipsoid(L, B, height));\n    if(!std::isnan(area))\n      areas.push_back(area);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridSinglePointCartesian.h",
    "content": "/***********************************************/\n/**\n* @file gridSinglePointCartesian.h\n*\n* @brief Single point.\n* @see Grid\n* single point.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-09-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDSINGLEPOINTCARTESIAN__\n#define __GROOPS_GRIDSINGLEPOINTCARTESIAN__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridSinglePointCartesian = R\"(\n\\subsection{SinglePointCartesian}\nCreates one single point.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Single point.\n* @ingroup gridGroup\n* @see Grid */\nclass GridSinglePointCartesian : public GridBase\n{\npublic:\n  GridSinglePointCartesian(Config &config);\n};\n\n/***********************************************/\n\ninline GridSinglePointCartesian::GridSinglePointCartesian(Config &config)\n{\n  try\n  {\n    Double x, y, z, area = NAN_EXPR;\n\n    readConfig(config, \"x\",    x,    Config::MUSTSET,  \"\", \"[m]\");\n    readConfig(config, \"y\",    y,    Config::MUSTSET,  \"\", \"[m]\");\n    readConfig(config, \"z\",    z,    Config::MUSTSET,  \"\", \"[m]\");\n    readConfig(config, \"area\", area, Config::OPTIONAL, \"\", \"associated area element on unit sphere\");\n    if(isCreateSchema(config)) return;\n\n    points.push_back(Vector3d(x,y,z));\n    if(!std::isnan(area))\n      areas.push_back(area);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridTriangleCenter.h",
    "content": "/***********************************************/\n/**\n* @file gridTriangleCenter.h\n*\n* @brief Triangle grid (center points).\n* @see Grid\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDTRIANGLECENTER__\n#define __GROOPS_GRIDTRIANGLECENTER__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridTriangleCenter = R\"(\n\\subsection{TriangleCenter}\nThe points of the zeroth level are located at the centers of the icosahedron triangles.\nTo achieve a finer grid, each of the triangles is divided into four smaller triangles by\nconnecting the midpoints of the triangle edges. The refined grid points are again located\nat the center of the triangles. Subsequently, the triangles can be further densified up to\nthe desired level of densification $n$, which is defined by \\config{level}.\n\nThe number of global grid points for a certain level can be determined by\n\\begin{equation}\\label{eq:numberCenter}\nI=20\\cdot 4^n.\n\\end{equation}\nThus the quantity of grid points depends exponentially on the level $n$, as with\nevery additional level the number of grid points quadruplicates.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Triangle grid (center points).\n* @ingroup gridGroup\n* @see Grid */\nclass GridTriangleCenter : public GridBase\n{\npublic:\n  GridTriangleCenter(Config &config);\n};\n\n/***********************************************/\n\nclass Triangle\n{\n  Vector3d p1, p2, p3; // Eckpunkte\n  public:\n    Triangle() {}\n    Triangle(Vector3d _p1, Vector3d _p2, Vector3d _p3) : p1(_p1), p2(_p2), p3(_p3) {}\n    // Durch Halbieren der Seiten 4 neue Dreiecke erzeugen\n    void divide(Triangle &d1, Triangle &d2, Triangle &d3, Triangle &d4) const;\n    // Schwerpunkt des Dreiecks\n    Vector3d center() const {return normalize(p1+p2+p3);}\n    // Flaeche des Dreiecks\n    Double   area() const;\n};\n\n/***********************************************/\n\ninline void Triangle::divide(Triangle &d1, Triangle &d2, Triangle &d3, Triangle &d4) const\n{\n  Vector3d p12 = normalize(p1+p2);\n  Vector3d p23 = normalize(p2+p3);\n  Vector3d p31 = normalize(p3+p1);\n\n  d1 = Triangle(p1, p12, p31);\n  d2 = Triangle(p2, p23, p12);\n  d3 = Triangle(p3, p31, p23);\n  d4 = Triangle(p12,p23, p31);\n}\n\n/***********************************************/\n\ninline Double Triangle::area() const\n{\n  Vector3d e1 = normalize(crossProduct(p1,p2));\n  Vector3d e2 = normalize(crossProduct(p2,p3));\n  Vector3d e3 = normalize(crossProduct(p3,p1));\n\n  Double w1 = PI-std::acos(inner(e1,e2));\n  Double w2 = PI-std::acos(inner(e2,e3));\n  Double w3 = PI-std::acos(inner(e3,e1));\n\n  return w1+w2+w3-PI;\n}\n\n/***********************************************/\n\n// Einen Vector von Dreiecken unterteilen\n// und 4mal soviel kleinere Dreiecke zurueckliefern\ninline std::vector<Triangle> divide(const std::vector<Triangle> &triangle)\n{\n  std::vector<Triangle> small(4*triangle.size());\n\n  for(UInt i=0; i<triangle.size(); i++)\n    triangle.at(i).divide(small.at(4*i), small.at(4*i+1), small.at(4*i+2), small.at(4*i+3));\n\n  return small;\n}\n\n/***********************************************/\n/***********************************************/\n\ninline GridTriangleCenter::GridTriangleCenter(Config &config)\n{\n  try\n  {\n    UInt      level;\n    Double    a, f;\n    BorderPtr border;\n\n    readConfig(config, \"level\",             level,      Config::MUSTSET,  \"\",                     \"division of icosahedron, point count = 5*4**(n+1)\");\n    readConfig(config, \"R\",                 a,          Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,          Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border,     Config::DEFAULT,  \"\",                     \"\");\n    if(isCreateSchema(config)) return;\n\n    // Create global icosaedron grid\n    // ----------------------------\n    // 12 vertexes of icosaedron\n    std::vector<Vector3d> p0(12);\n    Double phi  = PI/2.0-acos((cos(72*DEG2RAD)+cos(72*DEG2RAD)*cos(72*DEG2RAD))/(sin(72*DEG2RAD)*sin(72*DEG2RAD)));\n    p0.at(0)  = polar(Angle(  0.0*DEG2RAD), Angle( 90*DEG2RAD), 1.0);\n    p0.at(1)  = polar(Angle(  0.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(2)  = polar(Angle( 72.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(3)  = polar(Angle(144.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(4)  = polar(Angle(216.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(5)  = polar(Angle(288.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(6)  = polar(Angle( 36.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(7)  = polar(Angle(108.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(8)  = polar(Angle(180.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(9)  = polar(Angle(252.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(10) = polar(Angle(324.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(11) = polar(Angle(  0.0*DEG2RAD), Angle(-90*DEG2RAD), 1.0);\n\n    // 3 vertexes of 20 triangles\n    const UInt tri[20][3] = {{0,1,2},{0,2,3},{0,3,4},{0,4,5},{0,5,1},\n                             {2,1,6},{3,2,7},{4,3,8},{5,4,9},{1,5,10},\n                             {6,7,2},{7,8,3},{8,9,4},{9,10,5},{10,6,1},\n                             {11,7,6},{11,8,7},{11,9,8},{11,10,9},{11,6,10}};\n\n    // create triangles of the icosahedron\n    std::vector<Triangle> triangle(20);\n    for(UInt i=0; i<20; i++)\n      triangle.at(i) = Triangle(p0.at(tri[i][0]), p0.at(tri[i][1]), p0.at(tri[i][2]));\n\n    // divide triangles\n    for(UInt i=0; i<level; i++)\n      triangle = divide(triangle);\n\n    // create points\n    Ellipsoid ellipsoid(a,f);\n    for(UInt i=0; i<triangle.size(); i++)\n    {\n      Vector3d point = triangle.at(i).center();\n      // from sphere to ellipsoidal surface\n      Double r = ellipsoid.b()/sqrt(1-ellipsoid.e()*ellipsoid.e()*cos(point.phi())*cos(point.phi()));\n      point *= r;\n\n      Angle  L,B;\n      Double h;\n      ellipsoid(point, L,B,h);\n\n      if(border->isInnerPoint(L,B))\n      {\n        points.push_back(point);\n        areas.push_back(triangle.at(i).area());\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/grid/gridTriangleVertex.h",
    "content": "/***********************************************/\n/**\n* @file gridTriangleVertex.h\n*\n* @brief Triangle grid (Vertcies)\n* @see Grid\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRIDTRIANGLEVERTEX__\n#define __GROOPS_GRIDTRIANGLEVERTEX__\n\n// Latex documentation\n#ifdef DOCSTRING_Grid\nstatic const char *docstringGridTriangleVertex = R\"(\n\\subsection{TriangleVertex}\nThe zeroth level of densification\ncoincides with the 12 icosahedron vertices, as displayed in the upper left part\nof Fig.~\\ref{fig:triangle_grid}. Then, depending on the envisaged densification,\neach triangle edge is divided into $n$ parts, illustrated in the upper right\npart of Fig.~\\ref{fig:triangle_grid}. The new nodes on the edges are then connected\nby arcs of great circles parallel to the triangle edges. The intersections of\neach three corresponding parallel lines become nodes of the densified grid as well.\nAs in case of a spherical triangle those three connecting lines do not exactly\nintersect in one point, the center of the resulting triangle is used as location\nfor the new node (lower left part of Fig.~\\ref{fig:triangle_grid}). The lower right\nside of Fig.~\\ref{fig:triangle_grid} finally shows the densified triangle vertex\ngrid for a level of $n=3$. The number of grid points in dependence of the chosen\nlevel of densification can be calculated by\n\\begin{equation}\\label{eq:numberVertex}\nI=10\\cdot(n+1)^2+2.\n\\end{equation}\n\n\\fig{!hb}{0.6}{icogrid}{fig:triangle_grid}{TriangleVertex grid.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/border/border.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Triangle grid (Vertcies).\n* @ingroup gridGroup\n* @see Grid */\nclass GridTriangleVertex : public GridBase\n{\n  static void divideEdge(Vector3d p1, Vector3d p2, UInt level, std::vector<Vector3d> &points);\n  static void divideTriangle(Vector3d p1, Vector3d p2, Vector3d p3, UInt level, std::vector<Vector3d> &points);\n\npublic:\n  GridTriangleVertex(Config &config);\n};\n\n/***********************************************/\n\ninline GridTriangleVertex::GridTriangleVertex(Config &config)\n{\n  try\n  {\n    UInt      level;\n    Double    a, f;\n    BorderPtr border;\n\n    readConfig(config, \"level\",             level,      Config::MUSTSET,  \"\",                     \"division of icosahedron, point count = 10*(n+1)**2+2\");\n    readConfig(config, \"R\",                 a,          Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"major axsis of the ellipsoid/sphere\");\n    readConfig(config, \"inverseFlattening\", f,          Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"flattening of the ellipsoid, 0: sphere\");\n    readConfig(config, \"border\",            border,     Config::DEFAULT,  \"\",                     \"\");\n    if(isCreateSchema(config)) return;\n\n    // Create global icosaedron grid\n    // ----------------------------\n    // 12 vertexes of icosaedron\n    std::vector<Vector3d> p0(12);\n    Double phi  = PI/2.0-acos((cos(72*DEG2RAD)+cos(72*DEG2RAD)*cos(72*DEG2RAD))/(sin(72*DEG2RAD)*sin(72*DEG2RAD)));\n    p0.at(0)  = polar(Angle(  0.0*DEG2RAD), Angle( 90*DEG2RAD), 1.0);\n    p0.at(1)  = polar(Angle(  0.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(2)  = polar(Angle( 72.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(3)  = polar(Angle(144.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(4)  = polar(Angle(216.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(5)  = polar(Angle(288.0*DEG2RAD), Angle( phi), 1.0);\n    p0.at(6)  = polar(Angle( 36.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(7)  = polar(Angle(108.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(8)  = polar(Angle(180.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(9)  = polar(Angle(252.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(10) = polar(Angle(324.0*DEG2RAD), Angle(-phi), 1.0);\n    p0.at(11) = polar(Angle(  0.0*DEG2RAD), Angle(-90*DEG2RAD), 1.0);\n\n    // 3 vertexes of 20 triangles\n    const UInt tri[20][3] = {{0,1,2},{0,2,3},{0,3,4},{0,4,5},{0,5,1},\n                            {2,1,6},{3,2,7},{4,3,8},{5,4,9},{1,5,10},\n                            {6,7,2},{7,8,3},{8,9,4},{9,10,5},{10,6,1},\n                            {11,7,6},{11,8,7},{11,9,8},{11,10,9},{11,6,10}};\n\n    // start and end vertex of 30 edges\n    const UInt edge[30][2] = {{0,1},{0,2},{0,3},{0,4},{0,5},\n                              {1,2},{2,3},{3,4},{4,5},{5,1},\n                              {1,6},{2,7},{3,8},{4,9},{5,10},\n                              {6,2},{7,3},{8,4},{9,5},{10,1},\n                              {6,7},{7,8},{8,9},{9,10},{10,6},\n                              {11,6},{11,7},{11,8},{11,9},{11,10}};\n\n    // divides edges\n    for(UInt i=0; i<30; i++)\n      divideEdge(p0.at(edge[i][0]), p0.at(edge[i][1]), level, p0);\n\n    // create inner points\n    for(UInt i=0; i<20; i++)\n      divideTriangle( p0.at(tri[i][0]), p0.at(tri[i][1]), p0.at(tri[i][2]), level, p0);\n\n    // p0 contain now the global point distribution on unit sphere\n\n    Ellipsoid ellipsoid(a,f);\n    for(UInt i=0; i<p0.size(); i++)\n    {\n      // from sphere to ellipsoidal surface\n      Double r = ellipsoid.b()/sqrt(1-ellipsoid.e()*ellipsoid.e()*cos(p0.at(i).phi())*cos(p0.at(i).phi()));\n      p0.at(i) *= r;\n\n      Angle  L,B;\n      Double h;\n      ellipsoid(p0.at(i), L,B,h);\n\n      if(border->isInnerPoint(L,B))\n      {\n        points.push_back(p0.at(i));\n        areas.push_back(4*PI / p0.size());\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Erzeugt level gleichabstandige Punkte zwischen Anfpkt und Endpkt\ninline void GridTriangleVertex::divideEdge(Vector3d p1, Vector3d p2, UInt level, std::vector<Vector3d> &points)\n{\n  Double psi = acos(inner(p1, p2))/(level+1);\n\n  Vector3d pPerpendicular = normalize(crossProduct(crossProduct(p1, p2), p1));\n\n  for(UInt i=1; i<=level; i++)\n    points.push_back( cos(i*psi)*p1 + sin(i*psi)*pPerpendicular );\n}\n\n/***********************************************/\n\n// Innere Punkte im Dreieck erzeugen\ninline void GridTriangleVertex::divideTriangle(Vector3d p1, Vector3d p2, Vector3d p3, UInt level, std::vector<Vector3d> &points)\n{\n  std::vector<Vector3d> edge1, edge2, edge3;\n\n  divideEdge(p1, p2, level, edge1);\n  divideEdge(p2, p3, level, edge2);\n  divideEdge(p3, p1, level, edge3);\n\n  // innere punkte erzeugen\n  for(UInt i=1; i<level; i++)\n    for(UInt k=0; k<i; k++)\n    {\n      // Verbindungsgraden erzeugen\n      Vector3d line13 = crossProduct(edge1.at(i),     edge3.at(level-1-i));\n      Vector3d line12 = crossProduct(edge1.at(i-1-k), edge2.at(level-i+k));\n      Vector3d line23 = crossProduct(edge2.at(k),     edge3.at(level-1-k));\n\n      // Geraden schneiden (Schnittpunkt)\n      Vector3d p1 = normalize(crossProduct(line13, line12));\n      Vector3d p2 = normalize(crossProduct(line23, line13));\n      Vector3d p3 = normalize(crossProduct(line23, line12));\n\n      // Punkte mitteln\n      Vector3d pMean = normalize(p1 + p2 + p3);\n      points.push_back( -pMean );\n    }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/instrumentType/instrumentType.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentType.cpp\n*\n* @brief Defines the type of an instrument file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_InstrumentType\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileInstrument.h\"\n#include \"instrumentType.h\"\n\n/***** CLASS ***********************************/\n\n// Wrapper class\nclass InstrumentType\n{\npublic:\n  Epoch::Type type;\n  InstrumentType(Config &config, const std::string &name);\n  static InstrumentType create(Config &config, const std::string &name) {return InstrumentType(config, name);}\n};\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(InstrumentType, \"instrumentTypeType\")\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, Epoch::Type &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(isCreateSchema(config))\n    {\n      config.xselement(name, \"instrumentTypeType\", mustSet, Config::ONCE, defaultValue, annotation);\n      return FALSE;\n    }\n\n    if(!hasName(config, name, mustSet))\n      return FALSE;\n    InstrumentType tmp(config, name);\n    var = tmp.type;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nInstrumentType::InstrumentType(Config &config, const std::string &name)\n{\n  try\n  {\n    type = Epoch::EMPTY;\n    std::string choice;\n\n    readConfigChoice(config, name, choice, Config::MUSTSET,     \"\",     \"instrument type\");\n    if(readConfigChoiceElement(config, \"INSTRUMENTTIME\",        choice, \"time without data\"))                type = Epoch::INSTRUMENTTIME;\n    if(readConfigChoiceElement(config, \"MISCVALUE\",             choice, \"single value\"))                     type = Epoch::MISCVALUE;\n    if(readConfigChoiceElement(config, \"MISCVALUES\",            choice, \"multiple values\"))                  type = Epoch::EMPTY;\n    if(readConfigChoiceElement(config, \"VECTOR3D\",              choice, \"x, y, z\"))                          type = Epoch::VECTOR3D;\n    if(readConfigChoiceElement(config, \"COVARIANCE3D\",          choice, \"xx, yy, zz, xy, xz, yz\"))           type = Epoch::COVARIANCE3D;\n    if(readConfigChoiceElement(config, \"ORBIT\",                 choice, \"position [m], velocity [m/s], acceleration [m/s^2] (each x, y, z)\")) type = Epoch::ORBIT;\n    if(readConfigChoiceElement(config, \"STARCAMERA\",            choice, \"quaternions (q0, qx, qy, qz)\"))     type = Epoch::STARCAMERA;\n    if(readConfigChoiceElement(config, \"ACCELEROMETER\",         choice, \"x, y, z [m/s^2]\"))                  type = Epoch::ACCELEROMETER;\n    if(readConfigChoiceElement(config, \"SATELLITETRACKING\",     choice, \"range [m], range rate [m/s], range acceleration [m/s^2]\")) type = Epoch::SATELLITETRACKING;\n    if(readConfigChoiceElement(config, \"GRADIOMETER\",           choice, \"xx, yy, zz, xy, xz, yz [1/s^2]\"))   type = Epoch::GRADIOMETER;\n    if(readConfigChoiceElement(config, \"GNSSRECEIVER\",          choice, \"GNSS phase/code observations [m]\")) type = Epoch::GNSSRECEIVER;\n    if(readConfigChoiceElement(config, \"OBSERVATIONSIGMA\",      choice, \"accuracy\"))                         type = Epoch::OBSERVATIONSIGMA;\n    if(readConfigChoiceElement(config, \"SATELLITELASERRANGING\", choice, \"range [m], accuracy [m], redundancy, window [s], wavelength [m], azimuth [rad], elevation [rad]\")) type = Epoch::SATELLITELASERRANGING;\n    if(readConfigChoiceElement(config, \"METEOROLOGICAL\",        choice, \"temperature [K], pressure [Pa], humidity [%], windSpeed [m/s], radiation [W/m^2], precip. [mm/d]\")) type = Epoch::METEOROLOGICAL;\n    if(readConfigChoiceElement(config, \"MASS\",                  choice, \"\"))                                 type = Epoch::MASS;\n    if(readConfigChoiceElement(config, \"THRUSTER\",              choice, \"\"))                                 type = Epoch::THRUSTER;\n    if(readConfigChoiceElement(config, \"MAGNETOMETER\",          choice, \"\"))                                 type = Epoch::MAGNETOMETER;\n    if(readConfigChoiceElement(config, \"ACCHOUSEKEEPING\",       choice, \"\"))                                 type = Epoch::ACCHOUSEKEEPING;\n    endChoice(config);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/instrumentType/instrumentType.h",
    "content": "/***********************************************/\n/**\n* @file instrumentType.h\n*\n* @brief Defines the type of an instrument file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INSTRUMENTTYPE__\n#define __GROOPS_INSTRUMENTTYPE__\n\n// Latex documentation\n#ifdef DOCSTRING_InstrumentType\nstatic const char *docstringInstrumentType = R\"(\n\\section{InstrumentType}\\label{instrumentTypeType}\nDefines the type of an \\file{instrument file}{instrument}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n\n/**\n* @defgroup instrumentTypeGroup InstrumentType\n* @brief Defines the type of instrument files.\n* @ingroup classesGroup\n* The interface is given by @ref Epoch::Type. */\n/// @{\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Reads an instrument type from config.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for @a var\n* @param name Tag name in the config.\n* @param[out] var read from config.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Short description. */\ntemplate<> Bool readConfig(Config &config, const std::string &name, Epoch::Type &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/interpolatorTimeSeries/interpolatorTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file interpolatorTimeSeries.cpp\n*\n* @brief Interpolation of time series.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-01\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_InterpolatorTimeSeries\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeriesPolynomial.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeriesLeastSquaresPolynomialFit.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeries.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(InterpolatorTimeSeries, \"interpolatorTimeSeriesType\",\n                      InterpolatorTimeSeriesPolynomial,\n                      InterpolatorTimeSeriesLeastSquaresPolynomialFit,\n                      InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit)\n\nGROOPS_READCONFIG_CLASS(InterpolatorTimeSeries, \"interpolatorTimeSeriesType\")\n\n/***********************************************/\n\nInterpolatorTimeSeriesPtr InterpolatorTimeSeries::create(Config &config, const std::string &name)\n{\n  try\n  {\n    InterpolatorTimeSeriesPtr interpolatorTimeSeries;\n    std::string choice;\n\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"resampling method\");\n    if (readConfigChoiceElement(config, \"polynomial\",                        choice, \"polynomial prediction\"))\n      interpolatorTimeSeries = InterpolatorTimeSeriesPtr(new InterpolatorTimeSeriesPolynomial(config));\n    if (readConfigChoiceElement(config, \"leastSquaresPolynomialFit\",         choice, \"least squares polynomial fit\"))\n      interpolatorTimeSeries = InterpolatorTimeSeriesPtr(new InterpolatorTimeSeriesLeastSquaresPolynomialFit(config));\n    if (readConfigChoiceElement(config, \"fillGapsLeastSquaresPolynomialFit\", choice, \"least squares polynomial fit\"))\n      interpolatorTimeSeries = InterpolatorTimeSeriesPtr(new InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit(config));\n    endChoice(config);\n\n    return interpolatorTimeSeries;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/interpolatorTimeSeries/interpolatorTimeSeries.h",
    "content": "/***********************************************/\n/**\n* @file interpolatorTimeSeries.h\n*\n* @brief Interpolation of time series data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INTERPOLATORTIMESERIES__\n#define __GROOPS_INTERPOLATORTIMESERIES__\n\n// Latex documentation\n#ifdef DOCSTRING_InterpolatorTimeSeries\nstatic const char *docstringInterpolatorTimeSeries = R\"(\n\\section{InterpolatorTimeSeries}\\label{interpolatorTimeSeriesType}\nThis class resamples data of a times series to new poins in time.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup interpolatorTimeSeriesGroup InterpolatorTimeSeries\n* @brief Interpolation of time series data.\n* @ingroup classesGroup\n* The interface is given by @ref InterpolatorTimeSeries. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass InterpolatorTimeSeries;\ntypedef std::shared_ptr<InterpolatorTimeSeries> InterpolatorTimeSeriesPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolation of time series data.\n* An Instance of this class can be created by @ref readConfig. */\nclass InterpolatorTimeSeries\n{\npublic:\n  /// Destructor.\n  virtual ~InterpolatorTimeSeries() {}\n\n  /** @brief Initialize the interpolatorTimeSeries.\n  * @param times epochs of the input data.\n  * @param throwException otherwise the non-interpolated values filled with NaN. */\n  virtual void init(const std::vector<Time> &times, Bool throwException) = 0;\n\n  /** @brief Interpolate a matrix to new epochs.\n  * @param timesNew output epochs of the returned matrix.\n  * @param A input data of time series\n  * @param rowsPerEpoch e.g. for @a A with positions (x,y,z) per epoch in separated rows.\n  * @return Interpolated matrix with timesNew.size()*rowsPerEpoch rows. */\n  virtual Matrix interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch=1) const = 0;\n\n  /** @brief creates a derived instance of this class. */\n  static InterpolatorTimeSeriesPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class InterpolatorTimeSeries.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a interpolatorTimeSeries is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] interpolatorTimeSeries Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates InterpolatorTimeSeries */\ntemplate<> Bool readConfig(Config &config, const std::string &name, InterpolatorTimeSeriesPtr &interpolatorTimeSeries, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n#endif\n"
  },
  {
    "path": "source/classes/interpolatorTimeSeries/interpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit.h",
    "content": "/***********************************************/\n/**\n* @file interpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit.h\n*\n* @brief Gap filling with least squares polynomial fit.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INTERPOLATORTIMESERIESFILLGAPSLEASTSQUARESPOLYNOMIALFIT__\n#define __GROOPS_INTERPOLATORTIMESERIESFILLGAPSLEASTSQUARESPOLYNOMIALFIT__\n\n// Latex documentation\n#ifdef DOCSTRING_InterpolatorTimeSeries\nstatic const char *docstringInterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit = R\"(\n\\subsection{Fill gaps with least squares polynomial fit}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolation using a least squares polynomial fit.\n* @ingroup interpolatorTimeSeriesGroup\n* @see InterpolatorTimeSeries */\nclass InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit : public InterpolatorTimeSeries\n{\n  UInt              degree;\n  Double            maxDataGap, maxDataSpan;\n  Double            margin;\n  std::vector<Time> times;\n  Bool              throwException;\n\npublic:\n  InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit(Config &config);\n\n  void init(const std::vector<Time> &times, Bool throwException) override;\n  Matrix interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch) const override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit::InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit(Config &config)\n{\n  try\n  {\n    readConfig(config, \"polynomialDegree\", degree,      Config::DEFAULT, \"3\",    \"degree of the estimated polynomial\");\n    readConfig(config, \"maxDataGap\",       maxDataGap,  Config::DEFAULT, \"100\",  \"[seconds] max data gap to interpolate\");\n    readConfig(config, \"maxDataSpan\",      maxDataSpan, Config::DEFAULT, \"20\",   \"[seconds] time span on each side used for least squares fit\");\n    readConfig(config, \"margin\",           margin,      Config::DEFAULT, \"1e-5\", \"[seconds] margin for identical times\");\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit::init(const std::vector<Time> &times, Bool throwException)\n{\n  try\n  {\n    this->times = times;\n    this->throwException = throwException;\n\n    const Double sampling = medianSampling(times).seconds();\n    if(maxDataGap  < 0) maxDataGap  *= -sampling;\n    if(maxDataSpan < 0) maxDataSpan *= -sampling;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix InterpolatorTimeSeriesFillGapsLeastSquaresPolynomialFit::interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch) const\n{\n  try\n  {\n    if(timesNew == times) // need interpolation?\n      return A;\n    Matrix B(rowsPerEpoch*timesNew.size(), A.columns());\n\n    // new points before data?\n    // -----------------------\n    UInt iStart=0;\n    for(; (iStart<timesNew.size()) && ((timesNew.at(iStart)-times.front()).seconds() < -margin); iStart++)\n    {\n      if(throwException)\n        throw(Exception(\"extrapolation at \"+timesNew.front().dateTimeStr()+\" before start of data at \"+times.front().dateTimeStr()));\n      B.row(iStart*rowsPerEpoch, rowsPerEpoch).fill(NAN_EXPR);\n    }\n\n    // new points after data?\n    // ----------------------\n    UInt iEnd = timesNew.size();\n    for(; (iEnd-- > 0) && ((timesNew.at(iEnd)-times.back()).seconds() > margin);)\n    {\n      if(throwException)\n        throw(Exception(\"extrapolation at \"+timesNew.back().dateTimeStr()+\" after end of data at \"+times.back().dateTimeStr()));\n      B.row(iEnd*rowsPerEpoch, rowsPerEpoch).fill(NAN_EXPR);\n    }\n\n    UInt k = 0;\n    for(UInt i=iStart; i<=iEnd; i++)\n    {\n      for(; (k+1 < times.size()) && ((times.at(k+1)-timesNew.at(i)).seconds() <= margin); k++);\n\n      // no gap?\n      if(std::fabs((timesNew.at(i)-times.at(k)).seconds()) <= margin)\n      {\n        copy(A.row(k, rowsPerEpoch), B.row(i, rowsPerEpoch));\n        continue;\n      }\n\n      if((times.at(k+1)-times.at(k)).seconds() > maxDataGap)\n      {\n        if(throwException)\n          throw(Exception(\"gap too large between \"+times.at(k).dateTimeStr()+\" - \"+times.at(k+1).dateTimeStr()));\n        B.row(i*rowsPerEpoch, rowsPerEpoch).fill(NAN_EXPR);\n        continue;\n      }\n\n      // find interval\n      // -------------\n      UInt idx = k;         // left interval\n      for(; (idx > 0) && ((times.at(k)-times.at(idx-1)).seconds() <= maxDataSpan); idx--);\n      UInt count = k-idx+1; // right interval\n      for(; (idx+count < times.size()) && ((times.at(idx+count)-times.at(k+1)).seconds() <= maxDataSpan); count++);\n      if(count < degree+1)  // not enough points\n      {\n        if(throwException)\n          throw(Exception(\"not enough points to fit at \"+timesNew.at(i).dateTimeStr()));\n        B.row(i*rowsPerEpoch, rowsPerEpoch).fill(NAN_EXPR);\n        continue;\n      }\n\n      // compute interpolation coefficients\n      // ----------------------------------\n      Matrix P(count, degree+1); // polynomial matrix\n      for(UInt k=0; k<count; k++)\n      {\n        const Double factor = (timesNew.at(i)-times.at(idx+k)).seconds()/(times.at(idx+count-1)-times.at(idx)).seconds();\n        P(k,0) = 1.0;\n        for(UInt n=1; n<=degree; n++)\n          P(k,n) = factor * P(k,n-1);\n      }\n\n      Vector coeff(count);\n      coeff(0) = 1.;\n      const Vector tau = QR_decomposition(P);\n      triangularSolve(1., P.row(0, P.columns()).trans(), coeff.row(0, P.columns())); // R^(-T)*coeff\n      QMult(P, tau, coeff);                                                          // coeff := Q*R^(-T)*coeff\n\n      // interpolate\n      // -----------\n      for(UInt k=0; k<coeff.rows(); k++)\n        axpy(coeff(k), A.row(rowsPerEpoch*(idx+k), rowsPerEpoch), B.row(rowsPerEpoch*i, rowsPerEpoch));\n    } // for(i)\n\n    return B;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/interpolatorTimeSeries/interpolatorTimeSeriesLeastSquaresPolynomialFit.h",
    "content": "/***********************************************/\n/**\n* @file interpolatorTimeSeriesLeastSquaresPolynomialFit.h\n*\n* @brief Interpolation using a least squares polynomial fit.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INTERPOLATORTIMESERIESLEASTSQUARESPOLYNOMIALFIT__\n#define __GROOPS_INTERPOLATORTIMESERIESLEASTSQUARESPOLYNOMIALFIT__\n\n// Latex documentation\n#ifdef DOCSTRING_InterpolatorTimeSeries\nstatic const char *docstringInterpolatorTimeSeriesLeastSquaresPolynomialFit = R\"(\n\\subsection{Least squares polynomial fit}\nA polynomial of \\config{polynomialDegree} is estimated using all data points within\n\\config{maxDataPointDistance} of the resampling point. This polynomial is then used\nto predict the resampling point. A resampling point will be extrapolated if there are\nonly data points before/after as long as the closest one is within \\config{maxExtrapolationDistance}.\nThe elements \\config{maxDataPointDistance} and \\config{maxExtrapolationDistance} are given\nin the unit of seconds. If negative values are used, the unit is relative to the median input sampling.\n\n\\fig{!hb}{0.5}{instrumentResample_leastSquares}{fig:instrumentResample_leastSquares}{Example of least squares polynomial fit when resampling from 5 to 1 minute sampling}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolation using a least squares polynomial fit.\n* @ingroup interpolatorTimeSeriesGroup\n* @see InterpolatorTimeSeries */\nclass InterpolatorTimeSeriesLeastSquaresPolynomialFit : public InterpolatorTimeSeries\n{\n  Polynomial polynomial;\n  UInt       polynomialDegree;\n  Double     maxDataPointDistance, maxExtrapolationDistance;\n\npublic:\n  InterpolatorTimeSeriesLeastSquaresPolynomialFit(Config &config);\n\n  void init(const std::vector<Time> &times, Bool throwException) override;\n  Matrix interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch) const override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline InterpolatorTimeSeriesLeastSquaresPolynomialFit::InterpolatorTimeSeriesLeastSquaresPolynomialFit(Config &config)\n{\n  try\n  {\n    readConfig(config, \"polynomialDegree\",         polynomialDegree,         Config::MUSTSET, \"\",  \"degree of the estimated polynomial\");\n    readConfig(config, \"maxDataPointDistance\",     maxDataPointDistance,     Config::MUSTSET, \"\",  \"[seconds] all data points within this distance around the resampling point will be used\");\n    readConfig(config, \"maxExtrapolationDistance\", maxExtrapolationDistance, Config::DEFAULT, \"0\", \"[seconds] resampling points within this range of the polynomial will be extrapolated\");\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void InterpolatorTimeSeriesLeastSquaresPolynomialFit::init(const std::vector<Time> &times, Bool throwException)\n{\n  try\n  {\n    polynomial.init(times, polynomialDegree, throwException, TRUE/*isLeastSquares*/, maxDataPointDistance, maxExtrapolationDistance);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix InterpolatorTimeSeriesLeastSquaresPolynomialFit::interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch) const\n{\n  try\n  {\n    return polynomial.interpolate(timesNew, A, rowsPerEpoch);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/interpolatorTimeSeries/interpolatorTimeSeriesPolynomial.h",
    "content": "/***********************************************/\n/**\n* @file interpolatorTimeSeriesPolynomial.h\n*\n* @brief Interpolation using a moving polynomial.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INTERPOLATORTIMESERIESPOLYNOMIAL__\n#define __GROOPS_INTERPOLATORTIMESERIESPOLYNOMIAL__\n\n// Latex documentation\n#ifdef DOCSTRING_InterpolatorTimeSeries\nstatic const char *docstringInterpolatorTimeSeriesPolynomial = R\"(\n\\subsection{Polynomial}\nPolynomial prediction using a moving polynomial of \\config{polynomialDegree}.\nThe optimal polynomial is chosen based on the centricity of the data points around the resampling\npoint and the distance to all polynomial data points. All polynomial data points must be within\n\\config{maxDataPointRange}. Resampling points within \\config{maxExtrapolationDistance} of the\npolynomial will be extrapolated. The elements \\config{maxDataPointRange} and \\config{maxExtrapolationDistance}\nare given in the unit of seconds. If negative values are used, the unit is relative to the median input sampling.\n\n\\fig{!hb}{0.5}{instrumentResample_polynomial}{fig:instrumentResample_polynomial}{Example of polynomial prediction when resampling from 5 to 1 minute sampling}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolation using a moving polynomial.\n* @ingroup interpolatorTimeSeriesGroup\n* @see InterpolatorTimeSeries */\nclass InterpolatorTimeSeriesPolynomial : public InterpolatorTimeSeries\n{\n  Polynomial polynomial;\n  UInt       polynomialDegree;\n  Double     maxDataPointRange, maxExtrapolationDistance;\n\npublic:\n  InterpolatorTimeSeriesPolynomial(Config &config);\n\n  void init(const std::vector<Time> &times, Bool throwException) override;\n  Matrix interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch) const override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline InterpolatorTimeSeriesPolynomial::InterpolatorTimeSeriesPolynomial(Config &config)\n{\n  try\n  {\n    readConfig(config, \"polynomialDegree\",         polynomialDegree,         Config::MUSTSET, \"3\",        \"degree of the moving polynomial\");\n    readConfig(config, \"maxDataPointRange\",        maxDataPointRange,        Config::MUSTSET, \"-(3+1.1)\", \"[seconds] all degree+1 data points must be within this range for a valid polynomial\");\n    readConfig(config, \"maxExtrapolationDistance\", maxExtrapolationDistance, Config::DEFAULT, \"-1.1\",     \"[seconds] resampling points within this range of the polynomial will be extrapolated\");\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void InterpolatorTimeSeriesPolynomial::init(const std::vector<Time> &times, Bool throwException)\n{\n  try\n  {\n    polynomial.init(times, polynomialDegree, throwException, FALSE/*isLeastSquares*/, maxDataPointRange, maxExtrapolationDistance);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix InterpolatorTimeSeriesPolynomial::interpolate(const std::vector<Time> &timesNew, const_MatrixSliceRef A, UInt rowsPerEpoch) const\n{\n  try\n  {\n    return polynomial.interpolate(timesNew, A, rowsPerEpoch);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernel.cpp",
    "content": "/***********************************************/\n/**\n* @file kernel.cpp\n*\n* @brief Isotropic harmonic integral kernels.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-03\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Kernel\n\n#include \"base/import.h\"\n#include \"base/legendrePolynomial.h\"\n#include \"config/configRegister.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernelPoisson.h\"\n#include \"classes/kernel/kernelStokes.h\"\n#include \"classes/kernel/kernelHotine.h\"\n#include \"classes/kernel/kernelSingleLayer.h\"\n#include \"classes/kernel/kernelWaterHeight.h\"\n#include \"classes/kernel/kernelDeformation.h\"\n#include \"classes/kernel/kernelCoefficients.h\"\n#include \"classes/kernel/kernelGeoid.h\"\n#include \"classes/kernel/kernelRadialGradient.h\"\n#include \"classes/kernel/kernelFilterGauss.h\"\n#include \"classes/kernel/kernelSelenoid.h\"\n#include \"classes/kernel/kernelBottomPressure.h\"\n#include \"classes/kernel/kernelBlackmanLowPass.h\"\n#include \"classes/kernel/kernelTruncation.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Kernel, \"kernelType\",\n                      KernelGeoid,\n                      KernelStokes,\n                      KernelHotine,\n                      KernelPoisson,\n                      KernelSingleLayer,\n                      KernelWaterHeight,\n                      KernelBottomPressure,\n                      KernelDeformation,\n                      KernelRadialGradient,\n                      KernelCoefficients,\n                      KernelFilterGauss,\n                      KernelBlackmanLowPass,\n                      KernelTruncation,\n                      KernelSelenoid)\n\nGROOPS_READCONFIG_CLASS(Kernel, \"kernelType\")\n\n/***********************************************/\n\nKernelPtr Kernel::create(Config &config, const std::string &name)\n{\n  try\n  {\n    KernelPtr   kernel;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"harmonic and isotropic integral kernels\");\n\n    if(readConfigChoiceElement(config, \"geoidHeight\",    type, \"geoid = potential/normalgravity\"))\n      kernel = KernelPtr(new KernelGeoid(config));\n    if(readConfigChoiceElement(config, \"anomalies\",      type, \"gravity anomalies, Stokes kernel\"))\n      kernel = KernelPtr(new KernelStokes(config));\n    if(readConfigChoiceElement(config, \"disturbance\",    type, \"gravity disturbance, Hotine kernel\"))\n      kernel = KernelPtr(new KernelHotine(config));\n    if(readConfigChoiceElement(config, \"potential\",      type, \"Abel-Poisson kernel\"))\n      kernel = KernelPtr(new KernelPoisson(config));\n    if(readConfigChoiceElement(config, \"density\",        type, \"mass on a single layer (1/l kernel)\"))\n      kernel = KernelPtr(new KernelSingleLayer(config));\n    if(readConfigChoiceElement(config, \"waterHeight\",    type, \"equivalent water columns, accounts the loading\"))\n      kernel = KernelPtr(new KernelWaterHeight(config));\n    if(readConfigChoiceElement(config, \"bottomPressure\", type, \"ocean bottom pressure in Pascal, accounts for loading\"))\n      kernel = KernelPtr(new KernelBottomPressure(config));\n    if(readConfigChoiceElement(config, \"deformation\",    type, \"radial deformation by loading\"))\n      kernel = KernelPtr(new KernelDeformation(config));\n    if(readConfigChoiceElement(config, \"radialGradient\", type, \"radial gravity gradient\"))\n      kernel = KernelPtr(new KernelRadialGradient(config));\n    if(readConfigChoiceElement(config, \"coefficients\",   type, \"construct kernel by a legendre-polynomial expansion\"))\n      kernel = KernelPtr(new KernelCoefficients(config));\n    if(readConfigChoiceElement(config, \"filterGauss\",    type, \"smoothing by a gauss filter\"))\n      kernel = KernelPtr(new KernelFilterGauss(config));\n    if(readConfigChoiceElement(config, \"blackmanLowPass\",type, \"Blackman low-pass filter\"))\n      kernel = KernelPtr(new KernelBlackmanLowPass(config));\n    if(readConfigChoiceElement(config, \"truncation\",     type, \"truncate kernel at specific degree\"))\n      kernel = KernelPtr(new KernelTruncation(config));\n    if(readConfigChoiceElement(config, \"selenoidHeight\", type, \"selenoid = potential/normalgravity\"))\n      kernel = KernelPtr(new KernelSelenoid(config));\n    endChoice(config);\n\n    return kernel;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Kernel::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    return kernel(p, q, coefficients(p, maxDegree()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Kernel::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    return radialDerivative(p, q, coefficients(p, maxDegree()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d Kernel::gradient(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    return gradient(p, q, coefficients(p, maxDegree()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTensor3d Kernel::gradientGradient(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    return gradientGradient(p, q, coefficients(p, maxDegree()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Kernel::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel2) const\n{\n  try\n  {\n    const Double r = p.r();\n    const Double R = q.r();\n    const Double t = inner(p, q)/r/R; // t = cos(psi)\n\n    const Vector k2     = kernel2.coefficients(p, kernel2.maxDegree());\n    const Vector k1     = inverseCoefficients (p, k2.size()-1);\n    const UInt   degree = std::min(k1.rows(), k2.rows())-1;\n    Double       *p1 = k1.field();\n    const Double *p2 = k2.field();\n    Double  f1 = R/r;\n    const Double  f2 = R/r;\n\n    for(UInt n=0; n<=degree; n++)\n    {\n      // k1(n) *= (R/r)^(n+1) * sqrt(2n+1) * k2(n));\n      *p1++ *= f1 * sqrt(2*n+1.0) * *p2++;\n      f1  *= f2;\n    }\n\n    return LegendrePolynomial::sum(t, k1, degree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Kernel::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  try\n  {\n    SphericalHarmonics harmonics = field.sphericalHarmonics(time, maxDegree());\n    Vector kn = inverseCoefficients(p, harmonics.maxDegree(), harmonics.isInterior());\n    // Convolution with the kernel\n    return inner(kn, harmonics.Yn(p));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nDouble Kernel::kernel(Vector3d const &p, Vector3d const &q, const Vector &kn) const\n{\n  const Double r = p.r();\n  const Double R = q.r();\n  const Double t = inner(p, q)/r/R; // t = cos(psi)\n  // Factors: radial = sqrt(2n+1)*(R/r)^(n+1) * k_n\n  const Vector radial = computeFactors(r, R, kn);\n  // K = sum_n sqrt(2n+1)*(R/r)^(n+1) * k_n * P_n(t)\n  return LegendrePolynomial::sum(t, radial, kn.size()-1);\n}\n\n/***********************************************/\n\nDouble Kernel::radialDerivative(Vector3d const &p, Vector3d const &q, const Vector &kn) const\n{\n  const Double r = p.r();\n  const Double R = q.r();\n  const Double t = inner(p, q)/r/R; // t = cos(psi)\n\n  // radial_n = -(n+1)/r*(R/r)^(n+1) * sqrt(2n+1) * k_n\n  const Vector radial = computeFactorsRadialDerivative(r, R, kn);\n  // K = sum_n -(n+1)/r*(R/r)^(n+1) * sqrt(2n+1) * k_n * P_n(t)\n  return LegendrePolynomial::sum(t, radial, kn.size()-1);\n}\n\n/***********************************************/\n\nVector3d Kernel::gradient(Vector3d const &p, Vector3d const &q, const Vector &kn) const\n{\n  const Double r  = p.r();\n  const Double r2 = r*r;\n  const Double R  = q.r();\n  const Double t  = inner(p, q)/r/R; // t = cos(psi)\n  const UInt   degree = kn.size()-1;\n\n  const Vector radial           = computeFactors(r, R, kn);\n  const Vector radialDerivative = computeFactorsRadialDerivative(r, R, kn);\n\n  // derivatives of r with respect to x,y,z\n  const Double dr_dx = p.x()/r;\n  const Double dr_dy = p.y()/r;\n  const Double dr_dz = p.z()/r;\n\n  // derivatives of the kernel with respect to t,r\n  const Double dK_dr    = LegendrePolynomial::sum(t, radialDerivative, degree);\n  const Double dK_dt    = LegendrePolynomial::sumDerivative(t, radial, degree);\n\n  // derivatives of t with respect to x,y,z\n  const Double dt_dx = q.x()/r/R-p.x()*t/r2;\n  const Double dt_dy = q.y()/r/R-p.y()*t/r2;\n  const Double dt_dz = q.z()/r/R-p.z()*t/r2;\n\n  // chain rule\n  return Vector3d(dK_dr*dr_dx + dK_dt*dt_dx,\n                  dK_dr*dr_dy + dK_dt*dt_dy,\n                  dK_dr*dr_dz + dK_dt*dt_dz);\n}\n\n/***********************************************/\n\nTensor3d Kernel::gradientGradient(Vector3d const &p, Vector3d const &q, const Vector &kn) const\n{\n  const Double r  = p.r();\n  const Double r2 = r*r;\n  const Double r3 = r2*r;\n  const Double r4 = r3*r;\n  const Double R  = q.r();\n  const Double t  = inner(p, q)/r/R; // t = cos(psi)\n  const UInt   degree = kn.size()-1;\n\n  const Vector radial              = computeFactors                   (r, R, kn);\n  const Vector radialDerivative    = computeFactorsRadialDerivative   (r, R, kn);\n  const Vector radialDerivative2nd = computeFactorsRadialDerivative2nd(r, R, kn);\n\n  // derivatives of r with respect to x,y,z\n  const Double dr_dx = p.x()/r;\n  const Double dr_dy = p.y()/r;\n  const Double dr_dz = p.z()/r;\n\n  // 2nd derivatives of r with respect to x,y,z\n  const Double d2r_dx2 = 1/r-p.x()*p.x()/r3;\n  const Double d2r_dy2 = 1/r-p.y()*p.y()/r3;\n  const Double d2r_dz2 = 1/r-p.z()*p.z()/r3;\n  const Double d2r_dxdy =   -p.x()*p.y()/r3;\n  const Double d2r_dxdz =   -p.x()*p.z()/r3;\n  const Double d2r_dydz =   -p.y()*p.z()/r3;\n\n  // derivatives of t with respect to x,y,z\n  const Double dt_dx = q.x()/(r*R)-p.x()*t/r2;\n  const Double dt_dy = q.y()/(r*R)-p.y()*t/r2;\n  const Double dt_dz = q.z()/(r*R)-p.z()*t/r2;\n\n  // 2nd derivatives of t with respect to x,y,z\n  const Double d2t_dx2  = -t/r2 - 2*q.x()*p.x()/r3/R + 3*p.x()*p.x()*t/r4;\n  const Double d2t_dy2  = -t/r2 - 2*q.y()*p.y()/r3/R + 3*p.y()*p.y()*t/r4;\n  const Double d2t_dz2  = -t/r2 - 2*q.z()*p.z()/r3/R + 3*p.z()*p.z()*t/r4;\n  const Double d2t_dxdy = -(q.x()*p.y()+q.y()*p.x())/r3/R+3*p.x()*p.y()*t/r4;\n  const Double d2t_dxdz = -(q.x()*p.z()+q.z()*p.x())/r3/R+3*p.x()*p.z()*t/r4;\n  const Double d2t_dydz = -(q.y()*p.z()+q.z()*p.y())/r3/R+3*p.y()*p.z()*t/r4;\n\n  // derivatives of the kernel with respect to t,r\n  // K = sum B_n*(R/r)^n+1 * P_n\n  const Double dK_dt    = LegendrePolynomial::sumDerivative(t, radial, degree);\n  const Double d2K_drdt = LegendrePolynomial::sumDerivative(t, radialDerivative, degree);\n  const Double dK_dr    = LegendrePolynomial::sum          (t, radialDerivative, degree);\n  const Double d2K_dr2  = LegendrePolynomial::sum          (t, radialDerivative2nd, degree);\n  const Double d2K_dt2  = LegendrePolynomial::sumDerivative2nd(t, radial, degree);\n\n  // chain rule\n  Tensor3d tns;\n  tns.xx() = dK_dr*d2r_dx2  + dK_dt*d2t_dx2\n           + d2K_dr2*dr_dx*dr_dx + 2*d2K_drdt*dr_dx*dt_dx + d2K_dt2*dt_dx*dt_dx;\n\n  tns.xy() = dK_dr*d2r_dxdy + dK_dt*d2t_dxdy\n           + d2K_dr2*dr_dx*dr_dy + d2K_drdt*dr_dx*dt_dy + d2K_drdt*dr_dy*dt_dx + d2K_dt2*dt_dx*dt_dy;\n\n  tns.xz() = dK_dr*d2r_dxdz + dK_dt*d2t_dxdz\n           + d2K_dr2*dr_dx*dr_dz + d2K_drdt*dr_dx*dt_dz + d2K_drdt*dr_dz*dt_dx + d2K_dt2*dt_dx*dt_dz;\n\n  tns.yy() = dK_dr*d2r_dy2  + dK_dt*d2t_dy2\n           + d2K_dr2*dr_dy*dr_dy + 2*d2K_drdt*dr_dy*dt_dy + d2K_dt2*dt_dy*dt_dy;\n\n  tns.yz() = dK_dr*d2r_dydz + dK_dt*d2t_dydz\n           + d2K_dr2*dr_dy*dr_dz + d2K_drdt*dr_dy*dt_dz + d2K_drdt*dr_dz*dt_dy + d2K_dt2*dt_dy*dt_dz;\n\n  tns.zz() = dK_dr*d2r_dz2  + dK_dt*d2t_dz2\n           + d2K_dr2*dr_dz*dr_dz + 2*d2K_drdt*dr_dz*dt_dz + d2K_dt2*dt_dz*dt_dz;\n\n  return tns;\n}\n\n/***********************************************/\n/***********************************************/\n\n// computes sqrt(2n+1)*(R/r)^(n+1) * k_n\nVector Kernel::computeFactors(Double r, Double R, const Vector &kn) const\n{\n  Vector  radial(kn.size());\n  Double  f1   = R/r;\n  Double  f2   = R/r;\n  Double *rptr = radial.field();\n  const Double *kptr = kn.field();\n\n  for(UInt n=0; n<kn.size(); n++)\n  {\n    *rptr++ = sqrt(2.*n+1.) * f1 * *kptr++;\n    f1 *= f2;\n  }\n  return radial;\n}\n\n/***********************************************/\n\n// computes dK/dr = -(n+1)/r*(R/r)^(n+1) * sqrt(2n+1) * k_n\nVector Kernel::computeFactorsRadialDerivative(Double r, Double R, const Vector &kn) const\n{\n  Vector  radial(kn.size());\n  Double  f1   = R/(r*r);\n  Double  f2   = R/r;\n  Double *rptr = radial.field();\n  const Double *kptr = kn.field();\n\n  for(UInt n=0; n<kn.size(); n++)\n  {\n    *rptr++ = - sqrt(2.*n+1.) * (n+1.) * f1 * *kptr++;\n    f1 *= f2;\n  }\n  return radial;\n}\n\n/***********************************************/\n\n// computes d2K/dr2 = (n+1)*(n+2)/r^2*(R/r)^(n+1) * sqrt(2n+1) * k_n\nVector Kernel::computeFactorsRadialDerivative2nd(Double r, Double R, const Vector &kn) const\n{\n  Vector  radial(kn.size());\n  Double  f1   = R/(r*r*r);\n  Double  f2   = R/r;\n  Double *rptr = radial.field();\n  const Double *kptr = kn.field();\n\n  for(UInt n=0; n<kn.size(); n++)\n  {\n    *rptr++ = sqrt(2.*n+1.) * (n+1.)*(n+2.) * f1 * *kptr++;\n    f1 *= f2;\n  }\n  return radial;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernel.h",
    "content": "/***********************************************/\n/**\n* @file kernel.h\n*\n* @brief Isotropic harmonic integral kernels.\n* E.g. the Abel-Poisson kernel for the continuation of the potential.\n* Can also be used as Radial Basis Functions for splines and wavelets.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNEL__\n#define __GROOPS_KERNEL__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernel = R\"(\n\\section{Kernel}\\label{kernelType}\nKernel defines harmonic isotropic integral kernels $K$.\n\\begin{equation}\nT(P) = \\frac{1}{4\\pi}\\int_\\Omega K(P,Q)\\cdot f(Q)\\,d\\Omega(Q),\n\\end{equation}\nwhere $T$ is the (disturbance)potential and $f$ is a functional on the spherical surface~$\\Omega$.\nThe Kernel can be exapanded into a series of (fully normalized) legendre polynomials\n\\begin{equation}\\label{eq.kernel}\nK(\\cos\\psi,r,R) = \\sum_n \\left(\\frac{R}{r}\\right)^{n+1}\nk_n\\sqrt{2n+1}\\bar{P}_n(\\cos\\psi).\n\\end{equation}\nOn the one hand the kernel defines the type of the functionals~$f$ that are measured\nor have to be computed, e.g. gravity anomalies given by the Stokes-kernel.\nOn the other hand the kernel functions can be used as basis functions to represent\nthe gravity field, e.g. as spline functions or wavelets.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup kernelGroup Kernel\n* @brief Isotropic harmonic integral kernels.\n* @ingroup classesGroup\n* The interface is given by @ref Kernel. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Kernel;\ntypedef std::shared_ptr<Kernel> KernelPtr;\nclass GravityfieldBase;\n\n/***** CLASS ***********************************/\n\n/** @brief Isotropic harmonic integral kernels.\n* E.g. the Abel-Poisson kernel for the continuation of the potential.\n* Can also be used as Radial Basis Functions for splines and wavelets.\n* An Instance of this class can be created by @ref readConfig. */\nclass Kernel\n{\npublic:\n  /// Destructor.\n  virtual ~Kernel() {}\n\n  /** @brief Function value of the Kernel.\n  * @param p Computational point.\n  * @param q Source point. */\n  virtual Double kernel(const Vector3d &p, const Vector3d &q) const;\n\n  /** @brief Radial Derivative.\n  * @f$ \\frac{\\partial K}{\\partial r} @f$.\n  * Applied to the computational point @a p.\n  * @param p Computational point.\n  * @param q Source point. */\n  virtual Double radialDerivative(const Vector3d &p, const Vector3d &q) const;\n\n  /** @brief Gradient of the Kernel.\n  * @f$ \\nabla K @f$.\n  * Applied to the computational point @a p.\n  * @param p Computational point.\n  * @param q Source point. */\n  virtual Vector3d gradient(const Vector3d &p, const Vector3d &q) const;\n\n  /** @brief Gradient of the gradient (Tensor).\n  * @f$ \\nabla \\nabla K @f$.\n  * Applied to the computational point @a p.\n  * @param p Computational point.\n  * @param q Source point. */\n  virtual Tensor3d gradientGradient(const Vector3d &p, const Vector3d &q) const;\n\n  /** @brief Apply inverse kernel to a given Kernel.\n  * Convolution of Kernel of this class with the passed @a kernel.\n  * Example: Is this class the Stokes kernel, the gravity anomalies of the other kernel is returned:\n  * @f[ -\\frac{\\partial K}{\\partial r}-\\frac{2K}{r} @f]\n  * @param kernel This will be convoluted.\n  * @param p Computational point.\n  * @param q Source point. */\n  virtual Double inverseKernel(const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n\n  /** @brief Apply inverse kernel to a gravity field.\n  * Example: Is this class the stokes kernel,\n  * gravity anomalies are computed from the given gravity field:\n  * @f[ -\\frac{\\partial T}{\\partial r}-\\frac{2T}{r} @f]\n  * @param time For time variable gravity fields.\n  * @param p Computational point.\n  * @param field Apply kernel to this field. */\n  virtual Double inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n\n  /** @brief Legendre coefficients.\n  * The Kernel can be represented by a series of LegendrePolynomial:\n  * @f[ K(\\cos\\psi,r,R) = \\sum_n (R/r)^{n+1} k_n \\sqrt{2n+1}P_n(\\cos\\psi)  @f]\n  * This function returns the inverse coefficients @f$ k_n @f$.\n  * Example: The Stokes kernel gives @f$ r/(n-1) @f$.\n  * @param p Computational point.\n  * @param degree maximum degree.\n  * @return vector with size @a degree+1. */\n  virtual Vector coefficients(const Vector3d &p, UInt degree) const=0;\n\n  /** @brief Legendre coefficients of the inverse Kernel.\n  * The inverse Kernel can be represented by a series of LegendrePolynomial:\n  * @f[ K^(\\cos\\psi,r,R) = \\sum_n (R/r)^{n+1} 1/k_n  \\sqrt{2n+1}P_n(\\cos\\psi)   @f]\n  * This function returns the inverse coefficients @f$ 1/k_n @f$.\n  * Example: The Stokes kernel gives @f$ (n-1)/r @f$.\n  * @param p Computational point.\n  * @param degree maximum degree.\n  * @param interior functional is below masses.\n  * @return vector with size @a degree+1. */\n  virtual Vector inverseCoefficients(const Vector3d &p, UInt degree, Bool interior=FALSE) const=0;\n\n  /** @brief Minimum for bandlimited kernels.\n  * Otherwise 0 is returned. */\n  virtual UInt minDegree() const {return  0;}\n\n  /** @brief Maximum degree for bandlimited kernels.\n  * Otherwise INFINITYDEGREE is returned. */\n  virtual UInt maxDegree() const {return INFINITYDEGREE;}\n\n  /** @brief creates an derived instance of this class. */\n  static KernelPtr create(Config &config, const std::string &name);\n\nprotected:\n  Double   kernel          (Vector3d const &p, Vector3d const &q, const Vector &kn) const;\n  Double   radialDerivative(Vector3d const &p, Vector3d const &q, const Vector &kn) const;\n  Vector3d gradient        (Vector3d const &p, Vector3d const &q, const Vector &kn) const;\n  Tensor3d gradientGradient(Vector3d const &p, Vector3d const &q, const Vector &kn) const;\n\n  Vector computeFactors                   (Double r, Double R, const Vector &kn) const;\n  Vector computeFactorsRadialDerivative   (Double r, Double R, const Vector &kn) const;\n  Vector computeFactorsRadialDerivative2nd(Double r, Double R, const Vector &kn) const;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Kernel.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a kernel is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] kernel Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Kernel */\ntemplate<> Bool readConfig(Config &config, const std::string &name, KernelPtr &kernel, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/kernel/kernelBlackmanLowPass.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelBlackmanLowPass.cpp\n*\n* @brief Kernel smoothed by Blackman low-pass filter\n* @see Kernel\n*\n* @author Andreas Kvas\n* @date 2019-03-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelBlackmanLowPass.h\"\n\n/***********************************************/\n\nKernelBlackmanLowPass::KernelBlackmanLowPass(Config &config)\n{\n  try\n  {\n    readConfig(config, \"kernel\",                kernel, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"startDegreeTransition\", n1,     Config::MUSTSET, \"\", \"minimum degree in transition band\");\n    readConfig(config, \"stopDegreeTransition\",  n2,     Config::MUSTSET, \"\", \"maximum degree in transition band\");\n    if(isCreateSchema(config)) return;\n\n    if(n1>n2)\n      throw(Exception(\"Transition band limits must be given in increasing order.\"));\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelBlackmanLowPass::computeFilterCoefficients(UInt degree) const\n{\n  try\n  {\n    Vector wn(degree+1);\n    for(UInt n = 0; n < std::min(n1, degree+1); n++)  // pass band\n      wn(n) = 1.0;\n\n    for(UInt n = n1; n <= std::min(n2, degree); n++)\n    {\n      wn(n) = std::pow(0.42 + 0.5 * std::cos(PI*static_cast<Double>(n-n1)/static_cast<Double>(n2-n1)) +\n      0.08 * std::cos(2*PI*static_cast<Double>(n-n1)/static_cast<Double>(n2-n1)), 1);\n    }\n\n    return wn;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelBlackmanLowPass::coefficients(const Vector3d &p, UInt degree) const\n{\n  Vector kn = kernel->coefficients(p,degree);\n  if(filterCoeff.size()<kn.size())\n    filterCoeff = computeFilterCoefficients(kn.size()-1);\n  for(UInt n=0; n<kn.size(); n++)\n    kn(n) *= filterCoeff(n);\n  return kn;\n}\n\n/***********************************************/\n\nVector KernelBlackmanLowPass::inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const\n{\n  Vector kn = kernel->inverseCoefficients(p, degree, interior);\n  if(filterCoeff.size()<kn.size())\n    filterCoeff = computeFilterCoefficients(kn.size()-1);\n  for(UInt n=0; n<kn.size(); n++)\n    kn(n) *= filterCoeff(n);\n  return kn;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelBlackmanLowPass.h",
    "content": "/***********************************************/\n/**\n* @file kernelBlackmanLowPass.h\n*\n* @brief Kernel smoothed by Blackman low-pass filter\n* @see Kernel\n*\n* @author Andreas Kvas\n* @date 2019-03-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELBLACKMANLOWPASS__\n#define __GROOPS_KERNELBLACKMANLOWPASS__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelBlackmanLowPass = R\"(\n\\subsection{BlackmanLowpass}\nAnother \\configClass{kernel}{kernelType} is smoothed by a Blackman low-pass filter. The filter is\ndefined through the beginning and end of the transition from pass-band to stop-band. This\ntransition band is specified by \\config{startDegreeTransition} ($n_1$) and \\config{stopDegreeTransition} ($n_2$).\n\nThe coefficients of this kernel are defined as\n\\begin{equation}\n\\begin{cases}\n1 & \\text{for } n < n_1 \\\\\nA_n^2 & \\text{for } n_1\\leq n \\leq n_2 \\\\\n0 & \\text{for } n > n_2 \\\\\n\\end{cases}\n\\end{equation}\nwith\n\\begin{equation}\nA_n = 0.42 + 0.5\\cos(\\pi \\frac{n-n_1}{n_2-n_1}) + 0.08 \\cos(2\\pi\\frac{n-n_1}{n_2-n_1}).\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel smoothed by an Gaussian filter.\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelBlackmanLowPass : public Kernel\n{\n  KernelPtr kernel;\n  UInt n1, n2;\n  mutable Vector filterCoeff;\n\n  Vector computeFilterCoefficients(UInt degree) const;\n\npublic:\n  KernelBlackmanLowPass(Config &config);\n\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n\n  UInt maxDegree() const { return n2+1; }\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelBottomPressure.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelBottomPressure.cpp\n*\n* @brief Kernel for computation of ocean bottom pressure.\n*\n* @see Kernel\n*\n* @author Andreas Kvas\n* @date 2017-06-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/legendrePolynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelBottomPressure.h\"\n#include \"base/planets.h\"\n\n/***********************************************/\n\nKernelBottomPressure::KernelBottomPressure(Config &config)\n{\n  try\n  {\n    FileName loveNumberName;\n\n    readConfig(config, \"inputfileLoadingLoveNumber\", loveNumberName, Config::OPTIONAL,  \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"\");\n    if(isCreateSchema(config)) return;\n\n    if(!loveNumberName.empty())\n      readFileMatrix(loveNumberName, kn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVector KernelBottomPressure::coefficients(Vector3d const &q, UInt degree) const\n{\n  try\n  {\n    if((degree==INFINITYDEGREE) && (kn.rows()>0))\n      degree = kn.rows()-1;\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  coeff(degree+1);\n    Double *cp = coeff.field();\n    Double  factor = 4*PI*GRAVITATIONALCONSTANT*q.r()/Planets::normalGravity(q);\n    for(UInt n=0; n<std::min(degree+1, kn.size()); n++)\n      *cp++ = factor * (1.+kn(n)) / (2.*n+1.);\n    for(UInt n=std::min(degree+1, kn.size()); n<=degree; n++)\n      *cp++ = factor / (2.*n+1.);\n\n    return coeff;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelBottomPressure::inverseCoefficients(Vector3d const &p, UInt degree, Bool interior) const\n{\n  try\n  {\n    if((degree==INFINITYDEGREE) && (kn.rows()>0))\n      degree = kn.rows()-1;\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    if(interior)\n      throw(Exception(\"interior not implemented\"));\n\n    Vector  coeff(degree+1);\n    Double *cp = coeff.field();\n    Double  factor = Planets::normalGravity(p)/(4.*PI*GRAVITATIONALCONSTANT*p.r());\n    for(UInt n=0; n<std::min(degree+1, kn.size()); n++)\n      *cp++ = factor * (2.*n+1.) / (1.+kn(n));\n    for(UInt n=std::min(degree+1, kn.size()); n<=degree; n++)\n      *cp++ = factor * (2.*n+1.);\n\n    return coeff;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelBottomPressure::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  try\n  {\n    Double f = -1./(4.*PI*GRAVITATIONALCONSTANT/Planets::normalGravity(p)) * (2*kernel.radialDerivative(p,q) + kernel.kernel(p,q)/p.r());\n\n    if(kn.rows())\n    {\n      Double r  = p.r();\n      Double R  = q.r();\n      Double t  = inner(p, q)/r/R; // t = cos(psi)\n      Vector k2 = kernel.coefficients(p, kn.rows()-1);\n      Vector k1(kn.rows());\n      Double f1 = R/r;\n      Double f2 = R/r;\n      Double factor = 1./(4.*PI*GRAVITATIONALCONSTANT/Planets::normalGravity(p)*p.r());\n      Double       *p1 = k1.field();\n      const Double *p2 = k2.field();\n      for(UInt n=0; n<kn.rows(); n++)\n      {\n        // k1(n) *= (R/r)^(n+1) * sqrt(2n+1) * k2(n));\n        *p1++ = f1 * factor * (2.*n+1.) * (1/(1.+kn(n))-1) * sqrt(2.*n+1.) * *p2++;\n        f1  *= f2;\n      }\n      f += LegendrePolynomial::sum(t, k1, kn.rows()-1);\n    }\n\n    return f;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelBottomPressure::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  try\n  {\n    Double f = -1./(4.*PI*GRAVITATIONALCONSTANT/Planets::normalGravity(p)) * (2*field.radialGradient(time,p) + field.potential(time,p)/p.r());\n\n    if(kn.rows())\n    {\n      Vector  coeff(kn.rows());\n      Double *cp = coeff.field();\n      Double  factor = 1./(4.*PI*GRAVITATIONALCONSTANT/Planets::normalGravity(p)*p.r());\n      for(UInt n=0; n<kn.rows(); n++)\n        *cp++ = factor * (2.*n+1.) * (1/(1.+kn(n))-1);\n      // Convolution with the kernel\n      SphericalHarmonics harmonics = field.sphericalHarmonics(time, coeff.rows()-1);\n      f += inner(coeff, harmonics.Yn(p));\n    }\n\n    return f;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelBottomPressure.h",
    "content": "/************************************************/\n/**\n* @file kernelBottomPressure.h\n*\n* @brief Kernel for computation of ocean bottom pressure.\n*\n* @see Kernel\n*\n* @author Andreas Kvas\n* @date 2017-06-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELBOTTOMPRESSURE__\n#define __GROOPS_KERNELBOTTOMPRESSURE__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelBottomPressure = R\"(\n\\subsection{BottomPressure}\nOcean bottom pressure caused by water and atmosphere masses columns taking the effect of the loading into account.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{4\\pi G R }{\\gamma}\\frac{1+k_n'}{2n+1},\n\\end{equation}\nwhere $G$ is the gravitational constant, $\\gamma$ is the normal gravity and $k_n'$ are the load Love numbers.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel for computation of ocean bottom pressure.\n* @ingroup kernelGroup\n* Conversion of density into ocean bottom pressure.\n* @see Kernel */\nclass KernelBottomPressure : public Kernel\n{\n  Vector kn;\n\npublic:\n  KernelBottomPressure(Config &config);\n\n  Vector coefficients       (const Vector3d &p, UInt degree) const;\n  Vector inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n  Double inverseKernel(const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelCoefficients.cpp\n*\n* @brief Kernel from coefficients.\n* Given as series of Legendre polynomials.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelCoefficients.h\"\n\n/***********************************************/\n\nKernelCoefficients::KernelCoefficients(Config &config)\n{\n  try\n  {\n    FileName knName;\n\n    readConfig(config, \"inputfileCoefficients\", knName, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    readFileMatrix(knName, kn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelCoefficients::coefficients(const Vector3d &/*p*/, UInt degree) const\n{\n  if(degree==INFINITYDEGREE)\n    degree = kn.rows()-1;\n\n  Vector  k(degree+1);\n  Double *kp = k.field();\n  const Double *kf = kn.field();\n  for(UInt n=0; n<=std::min(degree, kn.rows()-1); n++)\n    *kp++ = *kf++;\n\n  return k;\n}\n\n/***********************************************/\n\nVector KernelCoefficients::inverseCoefficients(const Vector3d &/*p*/, UInt degree, Bool /*interior*/) const\n{\n  if(degree==INFINITYDEGREE)\n    degree = kn.rows()-1;\n\n  Vector  k(degree+1);\n  Double *kp = k.field();\n  const Double *kf = kn.field();\n  for(UInt n=0; n<=std::min(degree, kn.rows()-1); n++)\n  {\n    *kp++ = ((*kf == 0.) ? (0.0) : (1.0/ *kf));\n    kf++;\n  }\n\n  return k;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelCoefficients.h",
    "content": "/***********************************************/\n/**\n* @file kernelCoefficients.h\n*\n* @brief Kernel from coefficients.\n* Given as series of Legendre polynomials.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELCOEFF__\n#define __GROOPS_KERNELCOEFF__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelCoefficients = R\"(\n\\subsection{Coefficients}\\label{kernelType:coefficients}\nThe kernel is defined by the coefficients $k_n$ given by file.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel from coefficients.\n* Given as series of Legendre polynomials.\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelCoefficients : public Kernel\n{\n  Vector kn;\n\npublic:\n  KernelCoefficients(Config &config);\n\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n\n  UInt maxDegree() const {return kn.rows()-1;}\n};\n\n/***********************************************/\n\n#endif\n\n"
  },
  {
    "path": "source/classes/kernel/kernelDeformation.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelDeformation.cpp\n*\n* @brief Radial deformation by loading.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-07-29\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelDeformation.h\"\n\n/***********************************************/\n\nKernelDeformation::KernelDeformation(Config &config)\n{\n  try\n  {\n    FileName deformationName, potentialName;\n\n    readConfig(config, \"inputfileDeformationLoadLoveNumber\", deformationName, Config::MUSTSET,   \"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\", \"\");\n    readConfig(config, \"inputfilePotentialLoadLoveNumber\",   potentialName,   Config::OPTIONAL,  \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"if full potential is given and not only loading potential\");\n    if(isCreateSchema(config)) return;\n\n    // deformation load love numbers (hn,ln)\n    // -------------------------------------\n    readFileMatrix(deformationName, love);\n\n    // Compute loading potenial, if full potential is given\n    // ----------------------------------------------------\n    if(!potentialName.empty())\n    {\n      Vector kn;\n      readFileMatrix(potentialName, kn);\n\n      for(UInt n=2; n<std::min(kn.rows(), love.rows()); n++)\n        love(n,0) /= (1.+kn(n));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelDeformation::coefficients(Vector3d const &q, UInt degree) const\n{\n  if(degree==INFINITYDEGREE)\n    degree = love.rows()-1;\n\n  Vector  k(degree+1);\n  Double *kn = k.field();\n  Double  factor = Planets::normalGravity(q);\n  for(UInt n=0; n<std::min(degree+1, love.size()); n++)\n    *kn++ = ((love(n,0) == 0.) ? (0.0) : (factor / love(n,0)));\n\n  return k;\n}\n\n/***********************************************/\n\nVector KernelDeformation::inverseCoefficients(Vector3d const &p, UInt degree, Bool /*interior*/) const\n{\n  if(degree==INFINITYDEGREE)\n    degree = love.rows()-1;\n\n  Vector  k(degree+1);\n  Double *kn = k.field();\n  Double  factor = 1./Planets::normalGravity(p);\n  for(UInt n=0; n<std::min(degree+1, love.size()); n++)\n    *kn++ = factor * love(n,0);\n\n  return k;\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelDeformation.h",
    "content": "/***********************************************/\n/**\n* @file kernelDeformation.h\n*\n* @brief Radial deformation by loading.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-07-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELDEFORMATION__\n#define __GROOPS_KERNELDEFORMATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelDeformation = R\"(\n\\subsection{Deformation}\nComputes the radial deformation caused by loading.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\gamma\\frac{1+k_n'}{h_n'},\n\\end{equation}\nwhere $\\gamma$ is the normal gravity defined in \\eqref{normalgravity},\n$h_n'$ and $k_n'$ are the load Love numbers and the load deformation Love numbers.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Radial deformation by loading.\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelDeformation : public Kernel\n{\n  Matrix love;\n\npublic:\n  KernelDeformation(Config &config);\n\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n\n  UInt maxDegree() const {return love.rows()-1;}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelFilterGauss.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelFilterGauss.cpp\n*\n* @brief Kernel smoothed by an Gaussian filter.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-10-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelFilterGauss.h\"\n\n/***********************************************/\n\nKernelFilterGauss::KernelFilterGauss(Config &config)\n{\n  try\n  {\n    readConfig(config, \"kernel\", kernel, Config::MUSTSET, \"\",    \"\");\n    readConfig(config, \"radius\", radius, Config::MUSTSET, \"500\", \"filter radius [km]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelFilterGauss::computeFilterCoefficients(UInt degree) const\n{\n  try\n  {\n    Double b = log(2.)/(1-cos(1000*radius/DEFAULT_R));\n\n    Vector wn(degree+1);\n    wn(0) = 1;\n    wn(1) = (1+exp(-2*b))/(1-exp(-2*b)) - 1./b;\n    for(UInt n=2; n<=degree; n++)\n    {\n      wn(n) = -(2*n-1.)/b * wn(n-1) + wn(n-2);\n      if(wn(n)<1e-7)\n        break;\n    }\n\n    return wn;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelFilterGauss::coefficients(const Vector3d &p, UInt degree) const\n{\n  Vector kn = kernel->coefficients(p,degree);\n  if(filterCoeff.size()<kn.size())\n    filterCoeff = computeFilterCoefficients(kn.size()-1);\n  for(UInt n=0; n<kn.size(); n++)\n    kn(n) *= filterCoeff(n);\n  return kn;\n}\n\n/***********************************************/\n\nVector KernelFilterGauss::inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const\n{\n  Vector kn = kernel->inverseCoefficients(p, degree, interior);\n  if(filterCoeff.size()<kn.size())\n    filterCoeff = computeFilterCoefficients(kn.size()-1);\n  for(UInt n=0; n<kn.size(); n++)\n    kn(n) *= filterCoeff(n);\n  return kn;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelFilterGauss.h",
    "content": "/***********************************************/\n/**\n* @file kernelFilterGauss.h\n*\n* @brief Kernel smoothed by an Gaussian filter.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELFILTERGAUSS__\n#define __GROOPS_KERNELFILTERGAUSS__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelFilterGauss = R\"(\n\\subsection{FilterGauss}\nAnother \\configClass{kernel}{kernelType} is smoothed by a gauss filter\nwhich is defined by\n\\begin{equation}\nF(\\cos\\psi) = \\frac{b\\cdot e^{-b(1-\\cos\\psi)}}{1-e^{-2b}}\n\\end{equation}\nwith $b = \\frac{ln(2)}{1-\\cos(r/R)}$ where $r$ is the given\nsmoothing \\config{radius} in km and $R=6378.1366$~km is the\nEarth radius.\nThe coefficients~$k_n$ of the \\config{kernel} are multiplicated by\n\\begin{equation}\nf_n = \\frac{1}{2n+1} \\int_{-1}^1 F(t)\\cdot \\bar{P}_n(t)\\,dt.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel smoothed by an Gaussian filter.\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelFilterGauss : public Kernel\n{\n  KernelPtr kernel;\n  Double    radius;\n  mutable Vector filterCoeff;\n\n  Vector computeFilterCoefficients(UInt degree) const;\n\npublic:\n  KernelFilterGauss(Config &config);\n\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelGeoid.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelGeoid.cpp\n*\n* @brief Integral kernel of geoid computation.\n* (= Poisson Kern * gamma).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelGeoid.h\"\n\n/***********************************************/\n\nVector KernelGeoid::coefficients(Vector3d const &q, UInt degree) const\n{\n  try\n  {\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  k(degree+1);\n    Double *kn = k.field();\n    Double gamma = Planets::normalGravity(q);\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = gamma;\n\n    return k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelGeoid::inverseCoefficients(Vector3d const &p, UInt degree, Bool /*interior*/) const\n{\n  try\n  {\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  k(degree+1);\n    Double *kn = k.field();\n    Double gamma = Planets::normalGravity(p);\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = 1./gamma;\n\n    return k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelGeoid::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n\n  return Planets::normalGravity(q) * R*(r*r-R*R)/(l*l*l);\n}\n\n/***********************************************/\n\nDouble KernelGeoid::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n  Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n  Double dl_dr   = (r-R*cos_psi)/l;\n\n  return Planets::normalGravity(q) * R*(2*r*l-(r*r-R*R)*3*dl_dr)/(l*l*l*l);\n}\n\n/***********************************************/\n\nVector3d KernelGeoid::gradient(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double l       = diff.r();\n  Double R       = q.r();\n\n  return Planets::normalGravity(q) * (2/(l*l*l)*p - 3*(r*r-R*R)/(l*l*l*l*l)*diff);\n}\n\n/***********************************************/\n\nTensor3d KernelGeoid::gradientGradient(const Vector3d &p, const Vector3d &q) const\n{\n  Tensor3d tns;\n\n  Vector3d diff = p-q;\n  Double r      = p.r();\n  Double R      = q.r();\n  Double l      = diff.r();\n  Double l2     = l*l;\n  Double l3     = l2*l;\n  Double l5     = l3*l2;\n  Double l7     = l5*l2;\n  Double term   = r*r-R*R;\n\n  tns.xx() =  2.0/l3 - 12.0*p.x()*diff.x()/l5 + 15*term*diff.x()*diff.x()/l7 - 3.0*term/l5;\n  tns.yy() =  2.0/l3 - 12.0*p.y()*diff.y()/l5 + 15*term*diff.y()*diff.y()/l7 - 3.0*term/l5;\n  tns.zz() =  2.0/l3 - 12.0*p.z()*diff.z()/l5 + 15*term*diff.z()*diff.z()/l7 - 3.0*term/l5;\n  tns.xy() = -6.0*(p.x()*diff.y()+p.y()*diff.x())/l5 + 15.0*term*diff.x()*diff.y()/l7;\n  tns.xz() = -6.0*(p.x()*diff.z()+p.z()*diff.x())/l5 + 15.0*term*diff.x()*diff.z()/l7;\n  tns.yz() = -6.0*(p.y()*diff.z()+p.z()*diff.y())/l5 + 15.0*term*diff.y()*diff.z()/l7;\n\n  return Planets::normalGravity(q) * tns;\n}\n\n/***********************************************/\n\nDouble KernelGeoid::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  // geoid = potential/gamma\n  return (1./Planets::normalGravity(p)) * kernel.kernel(p, q);\n}\n\n/***********************************************/\n\nDouble KernelGeoid::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  // geoid = potential/gamma\n  return (1./Planets::normalGravity(p)) * field.potential(time, p);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelGeoid.h",
    "content": "/***********************************************/\n/**\n* @file kernelGeoid.h\n*\n* @brief Integral kernel of geoid computation.\n* (= Poisson Kern * gamma).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELGEOID__\n#define __GROOPS_KERNELGEOID__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelGeoid = R\"(\n\\subsection{GeoidHeight}\\label{kernelType:geoidHeight}\nThe geoid height is defined by Bruns formula\n\\begin{equation}\nN = \\frac{1}{\\gamma}T\n\\end{equation}\nwith $T$ the disturbance potential and the normal gravity\n\\begin{equation}\\label{normalgravity}\n\\gamma  = \\gamma_0 - 0.30877\\cdot 10^{-5}/s^2(1-0.00142\\sin^2(B))h\n\\end{equation}\nand\n\\begin{equation}\n\\gamma_0 = 9.780327\\,m/s^2(1+0.0053024\\sin^2(B)-0.0000058\\sin^2(2B))\n\\end{equation}\nwhere $h$ is the ellipsoidal height in meter and $B$ the longitude.\n\nThe kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\gamma\\frac{R(r^2-R^2)}{l^3},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\gamma.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Integral kernel of geoid computation.\n* @ingroup kernelGroup\n* (= Poisson Kern * gamma).\n* @see Kernel */\nclass KernelGeoid : public Kernel\n{\npublic:\n  KernelGeoid(Config &/*config*/) {}\n  Double   kernel             (const Vector3d &p, const Vector3d &q) const;\n  Double   radialDerivative   (const Vector3d &p, const Vector3d &q) const;\n  Vector3d gradient           (const Vector3d &p, const Vector3d &q) const;\n  Tensor3d gradientGradient   (const Vector3d &p, const Vector3d &q) const;\n  Double   inverseKernel      (const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double   inverseKernel      (const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelHotine.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelHotine.cpp\n*\n* @brief Hotine kernel (gravity disturbances).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n\n#include \"base/import.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelHotine.h\"\n\n/***********************************************/\n\nVector KernelHotine::coefficients(Vector3d const &q, UInt degree) const\n{\n  if(degree==INFINITYDEGREE)\n    throw(Exception(\"In KernelHotine::coefficients: INFINITYDEGREE requested\"));\n\n  Double  R = q.r();\n  Vector  k(degree+1);\n  Double *kn = k.field();\n\n  for(UInt n=0; n<=degree; n++)\n    *kn++ = R/(n+1);\n\n  return k;\n}\n\n/***********************************************/\n\nVector KernelHotine::inverseCoefficients(Vector3d const &p, UInt degree, Bool interior) const\n{\n  if(degree==INFINITYDEGREE)\n    throw(Exception(\"In KernelHotine::inverseCoefficients: INFINITYDEGREE requested\"));\n\n  Double  r = p.r();\n  Vector  k(degree+1);\n  Double *kn = k.field();\n\n  if(interior)\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = -(n/r);\n  else\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = (n+1)/r;\n\n  return k;\n}\n\n/***********************************************/\n\nDouble KernelHotine::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n  Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n\n  return 2*R*R/l-R*log((l+R-r*cos_psi)/(r-r*cos_psi));\n}\n\n/***********************************************/\n\nDouble KernelHotine::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n\n  return -R*R*(r*r-R*R)/(l*l*l*r);\n}\n\n/***********************************************/\n\nDouble KernelHotine::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  // gravity disturbance = -dK/dr\n  return -kernel.radialDerivative(p,q);\n}\n\n/***********************************************/\n\nDouble KernelHotine::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  // gravity disturbance = -dK/dr\n  return -field.radialGradient(time, p);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelHotine.h",
    "content": "/***********************************************/\n/**\n* @file kernelHotine.h\n*\n* @brief Hotine kernel (gravity disturbances).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELHOTINE__\n#define __GROOPS_KERNELHOTINE__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelHotine = R\"(\n\\subsection{Disturbance}\\label{kernelType:disturbance}\nGravity disturbances in linearized form are defined by\n\\begin{equation}\n\\delta g = -\\frac{dT}{dr}.\n\\end{equation}\nThe Hotine kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\frac{2R^2}{l}-R\\ln\\frac{l+R-r\\cos\\psi}{r(1-\\cos\\psi)},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{R}{n+1}.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Hotine kernel (gravity disturbances).\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelHotine : public Kernel\n{\npublic:\n  KernelHotine(Config &/*config*/) {}\n  Double   kernel             (const Vector3d &p, const Vector3d &q) const;\n  Double   radialDerivative   (const Vector3d &p, const Vector3d &q) const;\n  Double   inverseKernel      (const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double   inverseKernel      (const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelPoisson.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelPoisson.cpp\n*\n* @brief Poisson kernel (Potential).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelPoisson.h\"\n\n/***********************************************/\n\nVector KernelPoisson::coefficients(Vector3d const &/*q*/, UInt degree) const\n{\n  try\n  {\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  k(degree+1);\n    Double *kn = k.field();\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = 1.0;\n\n    return k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelPoisson::inverseCoefficients(Vector3d const &/*p*/, UInt degree, Bool /*interior*/) const\n{\n  try\n  {\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  k(degree+1);\n    Double *kn = k.field();\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = 1.0;\n\n    return k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelPoisson::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n\n  return R*(r*r-R*R)/(l*l*l);\n}\n\n/***********************************************/\n\nDouble KernelPoisson::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n  Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n  Double dl_dr   = (r-R*cos_psi)/l;\n\n  return R*(2*r*l-(r*r-R*R)*3*dl_dr)/(l*l*l*l);\n}\n\n/***********************************************/\n\nVector3d KernelPoisson::gradient(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double l       = diff.r();\n  Double R       = q.r();\n\n  return (2/(l*l*l)*p - 3*(r*r-R*R)/(l*l*l*l*l)*diff);\n}\n\n/***********************************************/\n\nTensor3d KernelPoisson::gradientGradient(const Vector3d &p, const Vector3d &q) const\n{\n  Tensor3d tns;\n\n  // Vorausberechnungen\n  Vector3d diff = p-q;\n  Double r      = p.r();\n  Double R      = q.r();\n  Double l      = diff.r();\n  Double l2     = l*l;\n  Double l3     = l2*l;\n  Double l5     = l3*l2;\n  Double l7     = l5*l2;\n  Double term   = r*r-R*R;\n\n  tns.xx() =  2.0/l3 - 12.0*p.x()*diff.x()/l5 + 15*term*diff.x()*diff.x()/l7 - 3.0*term/l5;\n  tns.yy() =  2.0/l3 - 12.0*p.y()*diff.y()/l5 + 15*term*diff.y()*diff.y()/l7 - 3.0*term/l5;\n  tns.zz() =  2.0/l3 - 12.0*p.z()*diff.z()/l5 + 15*term*diff.z()*diff.z()/l7 - 3.0*term/l5;\n  tns.xy() = -6.0*(p.x()*diff.y()+p.y()*diff.x())/l5 + 15.0*term*diff.x()*diff.y()/l7;\n  tns.xz() = -6.0*(p.x()*diff.z()+p.z()*diff.x())/l5 + 15.0*term*diff.x()*diff.z()/l7;\n  tns.yz() = -6.0*(p.y()*diff.z()+p.z()*diff.y())/l5 + 15.0*term*diff.y()*diff.z()/l7;\n\n  return tns;\n}\n\n/***********************************************/\n\nDouble KernelPoisson::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  // potential = K\n  return kernel.kernel(p, q);\n}\n\n/***********************************************/\n\nDouble KernelPoisson::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  return field.potential(time, p);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelPoisson.h",
    "content": "/***********************************************/\n/**\n* @file kernelPoisson.h\n*\n* @brief Poisson kernel (Potential).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELPOISSON__\n#define __GROOPS_KERNELPOISSON__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelPoisson = R\"(\n\\subsection{Potential}\nThe Abel-Poisson kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\frac{R(r^2-R^2)}{l^3},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = 1.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Poisson kernel (Potential).\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelPoisson : public Kernel\n{\npublic:\n  KernelPoisson(Config &/*config*/) {}\n  Double   kernel             (const Vector3d &p, const Vector3d &q) const;\n  Double   radialDerivative   (const Vector3d &p, const Vector3d &q) const;\n  Vector3d gradient           (const Vector3d &p, const Vector3d &q) const;\n  Tensor3d gradientGradient   (const Vector3d &p, const Vector3d &q) const;\n  Double   inverseKernel      (const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double   inverseKernel      (const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelRadialGradient.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelRadialGradient.cpp\n*\n* @brief 2nd radial derivative (gravity gradients).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-04-27\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelRadialGradient.h\"\n\n/***********************************************/\n\nVector KernelRadialGradient::coefficients(Vector3d const &q, UInt degree) const\n{\n  if(degree==INFINITYDEGREE)\n    throw(Exception(\"In KernelRadialGradient::coefficients: INFINITYDEGREE requested\"));\n\n  Double  R2 = pow(q.r(),2);\n  Vector  k(degree+1);\n  Double *kn = k.field();\n\n  for(UInt n=0; n<=degree; n++)\n    *kn++ = R2/((n+1)*(n+2));\n\n  return k;\n}\n\n/***********************************************/\n\nVector KernelRadialGradient::inverseCoefficients(Vector3d const &p, UInt degree, Bool interior) const\n{\n  if(degree==INFINITYDEGREE)\n    throw(Exception(\"In KernelRadialGradient::inverseCoefficients: INFINITYDEGREE requested\"));\n\n  Double  r2 = pow(p.r(),2);\n  Vector  k(degree+1);\n  Double *kn = k.field();\n\n  if(interior)\n    for(UInt n=2; n<=degree; n++)\n      *kn++ = n*(n-1.)/r2;\n  else\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = (n+1)*(n+2)/r2;\n\n  return k;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelRadialGradient.h",
    "content": "/***********************************************/\n/**\n* @file kernelRadialGradient.h\n*\n* @brief 2nd radial derivative (gravity gradients).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELRADIALGRADIENT__\n#define __GROOPS_KERNELRADIALGRADIENT__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelRadialGradient = R\"(\n\\subsection{RadialGradient}\nThis kernel defines the second radial derivative of the (disturbance) potential.\n\\begin{equation}\nT_{rr} = \\frac{\\partial^2 T}{\\partial r^2}.\n\\end{equation}\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{r^2}{(n+1)(n+2)}.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief 2nd radial derivative (gravity gradients).\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelRadialGradient : public Kernel\n{\npublic:\n  KernelRadialGradient(Config &/*config*/) {}\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelSelenoid.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelSelenoid.cpp\n*\n* @brief Integral kernel of selenoid computation.\n* (= Poisson Kern * gamma).\n* @see Kernel\n*\n* @author Beate Klinger\n* @date 2013-xx-xx\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelSelenoid.h\"\n\n/***********************************************/\n\nVector KernelSelenoid::coefficients(Vector3d const &/*p*/, UInt degree) const\n{\n  try\n  {\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  k(degree+1);\n    Double *kn = k.field();\n    const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = gamma;\n\n    return k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelSelenoid::inverseCoefficients(Vector3d const &/*p*/, UInt degree, Bool /*interior*/) const\n{\n  try\n  {\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  k(degree+1);\n    Double *kn = k.field();\n    const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = 1./gamma;\n\n    return k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelSelenoid::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n\n  const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n\n  return gamma * R*(r*r-R*R)/(l*l*l);\n}\n\n/***********************************************/\n\nDouble KernelSelenoid::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n  Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n  Double dl_dr   = (r-R*cos_psi)/l;\n\n  const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n\n  return gamma * R*(2*r*l-(r*r-R*R)*3*dl_dr)/(l*l*l*l);\n}\n\n/***********************************************/\n\nVector3d KernelSelenoid::gradient(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double l       = diff.r();\n  Double R       = q.r();\n\n  const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n\n  return gamma * (2/(l*l*l)*p - 3*(r*r-R*R)/(l*l*l*l*l)*diff);\n}\n\n/***********************************************/\n\nTensor3d KernelSelenoid::gradientGradient(const Vector3d &p, const Vector3d &q) const\n{\n  Tensor3d tns;\n\n  // Vorausberechnungen\n  Vector3d diff = p-q;\n  Double r      = p.r();\n  Double R      = q.r();\n  Double l      = diff.r();\n  Double l2     = l*l;\n  Double l3     = l2*l;\n  Double l5     = l3*l2;\n  Double l7     = l5*l2;\n  Double term   = r*r-R*R;\n\n  const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n\n  tns.xx() =  2.0/l3 - 12.0*p.x()*diff.x()/l5 + 15*term*diff.x()*diff.x()/l7 - 3.0*term/l5;\n  tns.yy() =  2.0/l3 - 12.0*p.y()*diff.y()/l5 + 15*term*diff.y()*diff.y()/l7 - 3.0*term/l5;\n  tns.zz() =  2.0/l3 - 12.0*p.z()*diff.z()/l5 + 15*term*diff.z()*diff.z()/l7 - 3.0*term/l5;\n  tns.xy() = -6.0*(p.x()*diff.y()+p.y()*diff.x())/l5 + 15.0*term*diff.x()*diff.y()/l7;\n  tns.xz() = -6.0*(p.x()*diff.z()+p.z()*diff.x())/l5 + 15.0*term*diff.x()*diff.z()/l7;\n  tns.yz() = -6.0*(p.y()*diff.z()+p.z()*diff.y())/l5 + 15.0*term*diff.y()*diff.z()/l7;\n\n  return gamma * tns;\n}\n\n/***********************************************/\n\nDouble KernelSelenoid::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  // potential = K\n  const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n\n  return (1./gamma) * kernel.kernel(p, q);\n}\n\n/***********************************************/\n\nDouble KernelSelenoid::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  const Double gamma = DEFAULT_GM/(pow(DEFAULT_R,2));\n\n  return (1./gamma) * field.potential(time, p);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelSelenoid.h",
    "content": "/***********************************************/\n/**\n* @file kernelSelenoid.h\n*\n* @brief Integral kernel of selenoid computation.\n* (= Poisson Kern * gamma).\n* @see Kernel\n*\n* @author Beate Klinger\n* @date 2013-xx-xx\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELSELENOID__\n#define __GROOPS_KERNELSELENOID__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelSelenoid = R\"(\n\\subsection{SelenoidHeight}\nThe selenoid height is defined by Bruns formula\n\\begin{equation}\nN = \\frac{1}{\\gamma}T\n\\end{equation}\nwith $T$ the disturbance potential and the normal gravity $\\gamma=\\frac{GM}{R^2}$ of the moon.\n\nThe kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\gamma\\frac{R(r^2-R^2)}{l^3},\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\gamma.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Integral kernel of selenoid computation.\n* @ingroup kernelGroup\n* (= Poisson Kern * gamma).\n* @see Kernel */\nclass KernelSelenoid : public Kernel\n{\npublic:\n  KernelSelenoid(Config &/*config*/) {}\n  Double   kernel             (const Vector3d &p, const Vector3d &q) const;\n  Double   radialDerivative   (const Vector3d &p, const Vector3d &q) const;\n  Vector3d gradient           (const Vector3d &p, const Vector3d &q) const;\n  Tensor3d gradientGradient   (const Vector3d &p, const Vector3d &q) const;\n  Double   inverseKernel      (const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double   inverseKernel      (const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelSingleLayer.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelSingleLayer.cpp\n*\n* @brief Single layer density.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/legendrePolynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelSingleLayer.h\"\n\n/***********************************************/\n\nKernelSingleLayer::KernelSingleLayer(Config &config)\n{\n  try\n  {\n    FileName loveNumberName;\n\n    readConfig(config, \"inputfileLoadingLoveNumber\", loveNumberName, Config::OPTIONAL,  \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"\");\n    if(isCreateSchema(config)) return;\n\n    if(!loveNumberName.empty())\n      readFileMatrix(loveNumberName, kn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelSingleLayer::coefficients(Vector3d const &q, UInt degree) const\n{\n  try\n  {\n    if((degree==INFINITYDEGREE) && (kn.rows()>0))\n      degree = kn.rows()-1;\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  coeff(degree+1);\n    Double *cp = coeff.field();\n    Double  factor = 4*PI*GRAVITATIONALCONSTANT*q.r();\n    for(UInt n=0; n<std::min(degree+1, kn.size()); n++)\n      *cp++ = factor * (1.+kn(n)) / (2.*n+1.);\n    for(UInt n=std::min(degree+1, kn.size()); n<=degree; n++)\n      *cp++ = factor / (2.*n+1.);\n\n    return coeff;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelSingleLayer::inverseCoefficients(Vector3d const &p, UInt degree, Bool interior) const\n{\n  try\n  {\n    if((degree==INFINITYDEGREE) && (kn.rows()>0))\n      degree = kn.rows()-1;\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    if(interior)\n      throw(Exception(\"interior not implemented\"));\n\n    Vector  coeff(degree+1);\n    Double *cp = coeff.field();\n    Double  factor = 1./(4.*PI*GRAVITATIONALCONSTANT*p.r());\n    for(UInt n=0; n<std::min(degree+1, kn.size()); n++)\n      *cp++ = factor * (2.*n+1.) / (1.+kn(n));\n    for(UInt n=std::min(degree+1, kn.size()); n<=degree; n++)\n      *cp++ = factor * (2.*n+1.);\n\n    return coeff;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelSingleLayer::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    Double K = 4*PI*GRAVITATIONALCONSTANT/(p-q).r();\n\n    // add love load numbers\n    if(kn.size())\n    {\n      Vector  coeff(kn.rows());\n      Double *cp = coeff.field();\n      const Double factor = 4*PI*GRAVITATIONALCONSTANT/q.r();\n      for(UInt n=0; n<kn.rows(); n++)\n        *cp++ = factor*kn(n)/(2.*n+1.);\n      K += Kernel::kernel(p, q, coeff);\n    }\n\n    return K;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelSingleLayer::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    const Double r = p.r();\n    const Double R = q.r();\n    const Double l = (p-q).r();\n    const Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n    Double dKdr = -4*PI*GRAVITATIONALCONSTANT/(l*l*l) * (r-R*cos_psi);\n\n    if(kn.rows())\n    {\n      Vector  coeff(kn.rows());\n      Double *cp = coeff.field();\n      const Double factor = 4*PI*GRAVITATIONALCONSTANT/q.r();\n      for(UInt n=0; n<kn.rows(); n++)\n        *cp++ = factor*kn(n)/(2.*n+1.);\n      dKdr += Kernel::radialDerivative(p, q, coeff);\n    }\n\n    return dKdr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d KernelSingleLayer::gradient(Vector3d const &p, Vector3d const &q) const\n{\n  try\n  {\n    const Double l = (p-q).r();\n    Vector3d g = -4*PI*GRAVITATIONALCONSTANT/(l*l*l) * (p-q);\n\n    if(kn.rows())\n    {\n      Vector  coeff(kn.rows());\n      Double *cp = coeff.field();\n      const Double factor = 4*PI*GRAVITATIONALCONSTANT/q.r();\n      for(UInt n=0; n<kn.rows(); n++)\n        *cp++ = factor*kn(n)/(2.*n+1.);\n      g += Kernel::gradient(p, q, coeff);\n    }\n\n    return g;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelSingleLayer::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  try\n  {\n    Double f = -1./(4.*PI*GRAVITATIONALCONSTANT) * (2*kernel.radialDerivative(p,q) + kernel.kernel(p,q)/p.r());\n\n    if(kn.rows())\n    {\n      Double r  = p.r();\n      Double R  = q.r();\n      Double t  = inner(p, q)/r/R; // t = cos(psi)\n      Vector k2 = kernel.coefficients(p, kn.rows()-1);\n      Vector k1(kn.rows());\n      Double f1 = R/r;\n      Double f2 = R/r;\n      Double factor = 1./(4.*PI*GRAVITATIONALCONSTANT*p.r());\n      Double       *p1 = k1.field();\n      const Double *p2 = k2.field();\n      for(UInt n=0; n<kn.rows(); n++)\n      {\n        // k1(n) *= (R/r)^(n+1) * sqrt(2n+1) * k2(n));\n        *p1++ = f1 * factor * (2.*n+1.) * (1/(1.+kn(n))-1) * sqrt(2.*n+1.) * *p2++;\n        f1  *= f2;\n      }\n      f += LegendrePolynomial::sum(t, k1, kn.rows()-1);\n    }\n\n    return f;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelSingleLayer::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  try\n  {\n    Double f = -1./(4.*PI*GRAVITATIONALCONSTANT) * (2*field.radialGradient(time,p) + field.potential(time,p)/p.r());\n\n    if(kn.rows())\n    {\n      Vector  coeff(kn.rows());\n      Double *cp = coeff.field();\n      Double  factor = 1./(4.*PI*GRAVITATIONALCONSTANT*p.r());\n      for(UInt n=0; n<kn.rows(); n++)\n        *cp++ = factor * (2.*n+1.) * (1/(1.+kn(n))-1);\n      // Convolution with the kernel\n      SphericalHarmonics harmonics = field.sphericalHarmonics(time, coeff.rows()-1);\n      f += inner(coeff, harmonics.Yn(p));\n    }\n\n    return f;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelSingleLayer.h",
    "content": "/***********************************************/\n/**\n* @file kernelSingleLayer.h\n*\n* @brief Single layer density.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELSINGLELAYER__\n#define __GROOPS_KERNELSINGLELAYER__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelSingleLayer = R\"(\n\\subsection{Density}\nThis kernel defines a point mass or mass on a single layer ($1/l$-kernel)\ntaking the effect of the loading into account.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = 4\\pi G R\\frac{1+k_n'}{2n+1},\n\\end{equation}\nwhere $G$ is the gravitational constant and $k_n'$ are the load Love numbers.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Single layer density.\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelSingleLayer : public Kernel\n{\n  Vector kn;\n\npublic:\n  KernelSingleLayer(Config &config);\n\n  Double   kernel             (const Vector3d &p, const Vector3d &q) const;\n  Double   radialDerivative   (const Vector3d &p, const Vector3d &q) const;\n  Vector3d gradient           (const Vector3d &p, const Vector3d &q) const;\n  Double   inverseKernel      (const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double   inverseKernel      (const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelStokes.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelStokes.cpp\n*\n* @brief Stokes kernel (gravity anomalies).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelStokes.h\"\n\n/***********************************************/\n\nVector KernelStokes::coefficients(Vector3d const &q, UInt degree) const\n{\n  if(degree==INFINITYDEGREE)\n    throw(Exception(\"In KernelStokes::coefficients: INFINITYDEGREE requested\"));\n\n  Double  R = q.r();\n  Vector  k(degree+1);\n  Double *kn = k.field();\n\n  for(UInt n=0; n<=degree; n++)\n    *kn++ = R * ((n==1) ? (0.0) : (1.0/(n-1.0)) );\n\n  return k;\n}\n\n/***********************************************/\n\nVector KernelStokes::inverseCoefficients(Vector3d const &p, UInt degree, Bool interior) const\n{\n  if(degree==INFINITYDEGREE)\n    throw(Exception(\"In KernelStokes::inverseCoefficients: INFINITYDEGREE requested\"));\n\n  Double  r = p.r();\n  Vector  k(degree+1);\n  Double *kn = k.field();\n\n  if(interior)\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = -(n+2.)/r;\n  else\n    for(UInt n=0; n<=degree; n++)\n      *kn++ = (n-1.)/r;\n\n  return k;\n}\n\n/***********************************************/\n\nDouble KernelStokes::kernel(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n  Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n\n  return R*(2*R/l-3*R*l/(r*r)-R*R/(r*r)*cos_psi*(5+3*log((l+r-R*cos_psi)/(2*r))));\n}\n\n/***********************************************/\n\nDouble KernelStokes::radialDerivative(Vector3d const &p, Vector3d const &q) const\n{\n  Vector3d diff  = p-q;\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = diff.r();\n  Double cos_psi = (R*R+r*r-l*l)/(2*R*r);\n\n  Double term0   = (R*R+r*r-l*l);\n  Double term    = (r+l-R)*(r+l+R);\n  Double ln_term = log(term/(4*r*r));\n  Double r2      = r*r;\n  Double r3      = r2*r;\n  Double r4      = r3*r;\n\n  // Ableitungen Stokes nach r,l\n  // Kettenregel: ds/dr = dS/du*du/dr + dS/dl*dl/dr  mit u = r\n  Double dS_du = R*(6*R*l/r3+1.5*R*term0*(5+3*ln_term)/r4\n                 -R*(5+3*ln_term)/r2\n                 -3*R*term0*(0.25*term0/r3-0.5*(r-0.5*term0/r+l)/r2)/(r2*(r-0.5*term0/r+l)));\n\n  Double dS_dl = R*(R/r3*(-2*r3/(l*l)-3*r+5*l+3*l*ln_term\n                -3*term0*(l+r)/term));\n\n  Double dl_dr = (r-R*cos_psi)/l;\n\n  Double dS_dr = dS_du+dS_dl*dl_dr;\n\n  return dS_dr;\n}\n\n/***********************************************/\n\nVector3d KernelStokes::gradient(Vector3d const &p, Vector3d const &q) const\n{\n  // Vorausberechnungen\n  Vector3d diff  = p-q;\n  Double   r     = p.r();\n  Double   R     = q.r();\n  Double   l     = diff.r();\n  Double term0   = (R*R+r*r-l*l);\n  Double term    = (r+l-R)*(r+l+R);\n  Double ln_term = log(term/(4*r*r));\n  Double r2      = r*r;\n  Double r3      = r2*r;\n  Double r4      = r3*r;\n\n  // Ableitungen r,l nach x,y,z\n  Vector3d dr = 1/r * p;\n  Vector3d dl = 1/l * diff;\n\n  // Ableitungen Stokes nach r,l\n  Double dS_dr = -R/r2+6*R*l/r3+1.5*R/r4*term0*(5+3*ln_term)\n                 -R/r2*(5+3*ln_term)\n                 -3*R/r3*term0*((r+l)/term-1/r);\n\n  Double dS_dl = R/r3*(-2*r3/(l*l)-3*r+5*l+3*l*ln_term\n                -3*term0*(l+r)/term);\n\n  // Kettenregel\n  return R*(dS_dr*dr + dS_dl*dl);\n}\n\n/***********************************************/\n\nTensor3d KernelStokes::gradientGradient(Vector3d const &p, Vector3d const &q) const\n{\n  Tensor3d tns;\n\n  // Vorausberechnungen\n  Double r       = p.r();\n  Double R       = q.r();\n  Double l       = (p-q).r();\n  Double term0   = (R*R+r*r-l*l);\n  Double term    = (r+l-R)*(r+l+R);\n  Double ln_term = log(term/(4*r*r));\n  Double r2      = r*r;\n  Double r3      = r2*r;\n  Double r4      = r3*r;\n  Double r5      = r4*r;\n\n  // Ableitungen r,l nach x,y,z\n  Double dr_dx = p.x()/r;   Double dl_dx = (p.x()-q.x())/l;\n  Double dr_dy = p.y()/r;   Double dl_dy = (p.y()-q.y())/l;\n  Double dr_dz = p.z()/r;   Double dl_dz = (p.z()-q.z())/l;\n\n  // Zweite Ableitungen r,l nach x,y,z\n  Double d2r_dx2 = 1/r-p.x()*p.x()/r3;\n  Double d2r_dy2 = 1/r-p.y()*p.y()/r3;\n  Double d2r_dz2 = 1/r-p.z()*p.z()/r3;\n  Double d2r_dxdy =   -p.x()*p.y()/r3;\n  Double d2r_dxdz =   -p.x()*p.z()/r3;\n  Double d2r_dydz =   -p.y()*p.z()/r3;\n\n  Double d2l_dx2 = 1/l-(p.x()-q.x())*(p.x()-q.x())/(l*l*l);\n  Double d2l_dy2 = 1/l-(p.y()-q.y())*(p.y()-q.y())/(l*l*l);\n  Double d2l_dz2 = 1/l-(p.z()-q.z())*(p.z()-q.z())/(l*l*l);\n  Double d2l_dxdy =   -(p.x()-q.x())*(p.y()-q.y())/(l*l*l);\n  Double d2l_dxdz =   -(p.x()-q.x())*(p.z()-q.z())/(l*l*l);\n  Double d2l_dydz =   -(p.y()-q.y())*(p.z()-q.z())/(l*l*l);\n\n  // Ableitungen Stokes nach r,l\n\n  Double dS_dr = -R/r2+6*R*l/r3+1.5*R*term0*(5+3*ln_term)/r4\n                 -R*(5+3*ln_term)/r2\n                 -3*R*term0*(0.25*term0/r3\n                 -0.5*(r-0.5*term0/r+l)/r2)/(r2*(r-0.5*term0/r+l));\n\n  Double dS_dl = R/r3*(-2*r3/(l*l)-3*r+5*l+3*l*ln_term\n                -3*term0*(l+r)/term);\n\n  // Zweite Ableitungen Stokes nach r,l\n  Double d2S_dr2 = R*(-3/r3-18*l/r4-30*(R*R-l*l)/r5\n                     +(15*r2-18*term0)*ln_term/r5\n                     +12*(R*R-r*l-l*l)*(R*R-l*l)/(r5*term)\n                     +6*term0*(R*R-r*l-l*l)*(r+l)/(r4*term*term)\n                     -3*term0*(3*l*l+2*r*l-3*R*R)/(r5*term));\n\n  Double d2S_drdl= R*(6.0/r3 - 15*l/r4 - 9*l*ln_term/r4\n                     + 6*(l*(R*R-l*r-l*l)-r2*(l+r))/(r4*term)\n                     + 3*term0*(3*l+2*r)/(r4*term)\n                     + 6*(r+l)*(r+l)*term0/(r3*term*term));\n\n  Double d2S_dl2 = R/(r3)*(4*r3/(l*l*l)+5+3*ln_term\n                     + (12*l*(r+l)-3*term0)/term\n                     + 6*(r+l)*(r+l)*term0/(term*term));\n\n  // Kettenregel\n  tns.xx() = dS_dr*d2r_dx2  + dS_dl*d2l_dx2\n           + d2S_dr2*dr_dx*dr_dx + 2*d2S_drdl*dr_dx*dl_dx + d2S_dl2*dl_dx*dl_dx;\n\n  tns.yy() = dS_dr*d2r_dy2  + dS_dl*d2l_dy2\n           + d2S_dr2*dr_dy*dr_dy + 2*d2S_drdl*dr_dy*dl_dy + d2S_dl2*dl_dy*dl_dy;\n\n  tns.zz() = dS_dr*d2r_dz2  + dS_dl*d2l_dz2\n           + d2S_dr2*dr_dz*dr_dz + 2*d2S_drdl*dr_dz*dl_dz + d2S_dl2*dl_dz*dl_dz;\n\n  tns.xy() = dS_dr*d2r_dxdy + dS_dl*d2l_dxdy\n           + d2S_dr2*dr_dx*dr_dy + d2S_drdl*dr_dx*dl_dy + d2S_drdl*dr_dy*dl_dx + d2S_dl2*dl_dx*dl_dy;\n\n  tns.xz() = dS_dr*d2r_dxdz + dS_dl*d2l_dxdz\n           + d2S_dr2*dr_dx*dr_dz + d2S_drdl*dr_dx*dl_dz + d2S_drdl*dr_dz*dl_dx + d2S_dl2*dl_dx*dl_dz;\n\n  tns.yz() = dS_dr*d2r_dydz + dS_dl*d2l_dydz\n           + d2S_dr2*dr_dy*dr_dz + d2S_drdl*dr_dy*dl_dz + d2S_drdl*dr_dz*dl_dy + d2S_dl2*dl_dy*dl_dz;\n\n  return R*tns;\n}\n\n/***********************************************/\n\nDouble KernelStokes::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  // anomalies = -dK/dr - 2K/r\n  return -kernel.radialDerivative(p,q) - 2*kernel.kernel(p,q)/p.r();;\n}\n\n/***********************************************/\n\nDouble KernelStokes::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  // anomalies = -dK/dr - 2K/r\n  return -field.radialGradient(time, p) - 2*field.potential(time, p)/p.r();\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelStokes.h",
    "content": "/***********************************************/\n/**\n* @file kernelStokes.h\n*\n* @brief Stokes kernel (gravity anomalies).\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELSTOKES__\n#define __GROOPS_KERNELSTOKES__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelStokes = R\"(\n\\subsection{Anomalies}\nGravity anomalies in linearized form are defined by\n\\begin{equation}\n\\Delta g = -\\frac{\\partial T}{\\partial r}-\\frac{2}{r}T.\n\\end{equation}\nThe Stokes kernel is given by\n\\begin{equation}\nK(\\cos\\psi,r,R) = \\frac{2R^2}{l}-3\\frac{Rl}{r^2}-\\frac{R^2}{r^2}\\cos\\psi\n\\left(5+3\\ln\\frac{l+r-R\\cos\\psi}{2r}\\right),\n\\end{equation}\nand the coefficients in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = \\frac{R}{n-1}.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Stokes kernel (gravity anomalies).\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelStokes : public Kernel\n{\npublic:\n  KernelStokes(Config &/*config*/) {}\n  Double   kernel             (const Vector3d &p, const Vector3d &q) const;\n  Double   radialDerivative   (const Vector3d &p, const Vector3d &q) const;\n  Vector3d gradient           (const Vector3d &p, const Vector3d &q) const;\n  Tensor3d gradientGradient   (const Vector3d &p, const Vector3d &q) const;\n  Double   inverseKernel      (const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double   inverseKernel      (const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelTruncation.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelTruncation.cpp\n*\n* @brief Kernel truncated at spherical harmonic degree,\n* @see Kernel\n*\n* @author Andreas Kvas\n* @date 2019-03-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelTruncation.h\"\n\n/***********************************************/\n\nKernelTruncation::KernelTruncation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"kernel\",    _kernel,    Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"minDegree\", _minDegree, Config::DEFAULT, \"0\", \"truncate before minDegree\");\n    readConfig(config, \"maxDegree\", _maxDegree, Config::MUSTSET, \"\", \"truncate after maxDegree\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelTruncation::coefficients(const Vector3d &p, UInt degree) const\n{\n  Vector kn = _kernel->coefficients(p, degree);\n  if(_minDegree > 0)\n    kn.row(0, _minDegree).setNull();\n  if(_maxDegree+2 < kn.rows())\n    kn.row(_maxDegree+1, kn.rows()-_maxDegree-1).setNull();\n  return kn;\n}\n\n/***********************************************/\n\nVector KernelTruncation::inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const\n{\n  Vector kn = _kernel->inverseCoefficients(p, degree, interior);\n  if(_minDegree > 0)\n    kn.row(0, _minDegree).setNull();\n  if(_maxDegree+2 < kn.rows())\n    kn.row(_maxDegree+1, kn.rows()-_maxDegree-1).setNull();\n  return kn;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelTruncation.h",
    "content": "/***********************************************/\n/**\n* @file kernelTruncation.h\n*\n* @brief Kernel truncated at spherical harmonic degree\n* @see Kernel\n*\n* @author Andreas Kvas\n* @date 2019-03-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELTRUNCATION__\n#define __GROOPS_KERNELTRUNCATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelTruncation= R\"(\n\\subsection{Truncation}\nAnother \\configClass{kernel}{kernelType} is truncated before \\config{minDegree} and after \\config{maxDegree}.\nThe coefficients of this kernel are defined as\n\\begin{equation}\n  k_n =\n  \\begin{cases}\n  1 & \\text{for } n_{\\text{minDegree}} \\leq n \\leq n_{\\text{maxDegree}}\\\\\n  0 & \\text{else.} \\\\\n  \\end{cases}\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel truncated at spherical harmonic degree.\n* @ingroup kernelGroup\n* @see Kernel */\nclass KernelTruncation : public Kernel\n{\n  KernelPtr _kernel;\n  UInt      _minDegree;\n  UInt      _maxDegree;\n\npublic:\n  KernelTruncation(Config &config);\n\n  Vector   coefficients       (const Vector3d &p, UInt degree) const;\n  Vector   inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n\n  UInt maxDegree() const {return _maxDegree;}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/kernel/kernelWaterHeight.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelWaterHeight.cpp\n*\n* @brief Kernel for computation of equivalent water height.\n* Conversion of density in equivalent water heights.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/legendrePolynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/kernel/kernelWaterHeight.h\"\n\n/***********************************************/\n\nKernelWaterHeight::KernelWaterHeight(Config &config)\n{\n  try\n  {\n    FileName loveNumberName;\n\n    readConfig(config, \"density\", rho, Config::MUSTSET, \"1025\", \"[kg/m**3]\");\n    readConfig(config, \"inputfileLoadingLoveNumber\", loveNumberName, Config::OPTIONAL,  \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"\");\n    if(isCreateSchema(config)) return;\n\n    if(!loveNumberName.empty())\n      readFileMatrix(loveNumberName, kn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVector KernelWaterHeight::coefficients(Vector3d const &q, UInt degree) const\n{\n  try\n  {\n    if((degree==INFINITYDEGREE) && (kn.rows()>0))\n      degree = kn.rows()-1;\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    Vector  coeff(degree+1);\n    Double *cp = coeff.field();\n    Double  factor = 4*PI*GRAVITATIONALCONSTANT*rho*q.r();\n    for(UInt n=0; n<std::min(degree+1, kn.size()); n++)\n      *cp++ = factor * (1.+kn(n)) / (2.*n+1.);\n    for(UInt n=std::min(degree+1, kn.size()); n<=degree; n++)\n      *cp++ = factor / (2.*n+1.);\n\n    return coeff;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector KernelWaterHeight::inverseCoefficients(Vector3d const &p, UInt degree, Bool interior) const\n{\n  try\n  {\n    if((degree==INFINITYDEGREE) && (kn.rows()>0))\n      degree = kn.rows()-1;\n    if(degree==INFINITYDEGREE)\n      throw(Exception(\"INFINITYDEGREE requested\"));\n\n    if(interior)\n      throw(Exception(\"interior not implemented\"));\n\n    Vector  coeff(degree+1);\n    Double *cp = coeff.field();\n    Double  factor = 1./(4.*PI*GRAVITATIONALCONSTANT*rho*p.r());\n    for(UInt n=0; n<std::min(degree+1, kn.size()); n++)\n      *cp++ = factor * (2.*n+1.) / (1.+kn(n));\n    for(UInt n=std::min(degree+1, kn.size()); n<=degree; n++)\n      *cp++ = factor * (2.*n+1.);\n\n    return coeff;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelWaterHeight::inverseKernel(Vector3d const &p, Vector3d const &q, const Kernel &kernel) const\n{\n  try\n  {\n    Double f = -1./(4.*PI*GRAVITATIONALCONSTANT*rho) * (2*kernel.radialDerivative(p,q) + kernel.kernel(p,q)/p.r());\n\n    if(kn.rows())\n    {\n      Double r  = p.r();\n      Double R  = q.r();\n      Double t  = inner(p, q)/r/R; // t = cos(psi)\n      Vector k2 = kernel.coefficients(p, kn.rows()-1);\n      Vector k1(kn.rows());\n      Double f1 = R/r;\n      Double f2 = R/r;\n      Double factor = 1./(4.*PI*GRAVITATIONALCONSTANT*rho*p.r());\n      Double       *p1 = k1.field();\n      const Double *p2 = k2.field();\n      for(UInt n=0; n<kn.rows(); n++)\n      {\n        // k1(n) *= (R/r)^(n+1) * sqrt(2n+1) * k2(n));\n        *p1++ = f1 * factor * (2.*n+1.) * (1/(1.+kn(n))-1) * sqrt(2.*n+1.) * *p2++;\n        f1  *= f2;\n      }\n      f += LegendrePolynomial::sum(t, k1, kn.rows()-1);\n    }\n\n    return f;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble KernelWaterHeight::inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const\n{\n  try\n  {\n    Double f = -1./(4.*PI*GRAVITATIONALCONSTANT*rho) * (2*field.radialGradient(time,p) + field.potential(time,p)/p.r());\n\n    if(kn.rows())\n    {\n      Vector  coeff(kn.rows());\n      Double *cp = coeff.field();\n      Double  factor = 1./(4.*PI*GRAVITATIONALCONSTANT*rho*p.r());\n      for(UInt n=0; n<kn.rows(); n++)\n        *cp++ = factor * (2.*n+1.) * (1/(1.+kn(n))-1);\n      // Convolution with the kernel\n      SphericalHarmonics harmonics = field.sphericalHarmonics(time, coeff.rows()-1);\n      f += inner(coeff, harmonics.Yn(p));\n    }\n\n    return f;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/kernel/kernelWaterHeight.h",
    "content": "/***********************************************/\n/**\n* @file kernelWaterHeight.h\n*\n* @brief Kernel for computation of equivalent water height.\n* Conversion of density in equivalent water heights.\n* @see Kernel\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-09-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KERNELWATERHEIGHT__\n#define __GROOPS_KERNELWATERHEIGHT__\n\n// Latex documentation\n#ifdef DOCSTRING_Kernel\nstatic const char *docstringKernelWaterHeight = R\"(\n\\subsection{WaterHeight}\\label{kernelType:waterHeight}\nHeight of equivalent water columns taking the effect of the loading into account.\n\nThe coefficients of the kernel defined in \\eqref{eq.kernel} are\n\\begin{equation}\nk_n = 4\\pi G \\rho R\\frac{1+k_n'}{2n+1},\n\\end{equation}\nwhere $G$ is the gravitational constant, $\\rho$ is the \\config{density} of water\nand $k_n'$ are the load Love numbers.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel for computation of equivalent water height.\n* @ingroup kernelGroup\n* Conversion of density in equivalent water heights.\n* @see Kernel */\nclass KernelWaterHeight : public Kernel\n{\n  Double rho;\n  Vector kn;\n\npublic:\n  KernelWaterHeight(Config &config);\n\n  Vector coefficients       (const Vector3d &p, UInt degree) const;\n  Vector inverseCoefficients(const Vector3d &p, UInt degree, Bool interior) const;\n  Double inverseKernel(const Vector3d &p, const Vector3d &q, const Kernel &kernel) const;\n  Double inverseKernel(const Time &time, const Vector3d &p, const GravityfieldBase &field) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loop.cpp",
    "content": "/***********************************************/\n/**\n* @file loop.cpp\n*\n* @brief Loop.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Loop\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"loopTimeSeries.h\"\n#include \"loopTimeIntervals.h\"\n#include \"loopStringList.h\"\n#include \"loopStringTable.h\"\n#include \"loopFileStringList.h\"\n#include \"loopFileStringTable.h\"\n#include \"loopFileTextLines.h\"\n#include \"loopMatrix.h\"\n#include \"loopNumberSequence.h\"\n#include \"loopDirectoryListing.h\"\n#include \"loopCommandOutput.h\"\n#include \"loopPlatformEquipment.h\"\n#include \"loopLoop.h\"\n#include \"loopSortAndRemoveDuplicates.h\"\n#include \"loopManualTable.h\"\n#include \"loopFileGnssStationInfo.h\"\n#include \"loop.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Loop, \"loopType\",\n                      LoopTimeSeries,\n                      LoopTimeIntervals,\n                      LoopStringList,\n                      LoopStringTable,\n                      LoopFileStringList,\n                      LoopFileStringTable,\n                      LoopFileTextLines,\n                      LoopMatrix,\n                      LoopNumberSequence,\n                      LoopDirectoryListing,\n                      LoopCommandOutput,\n                      LoopPlatformEquipment,\n                      LoopLoop,\n                      LoopSortAndRemoveDuplicates,\n                      LoopManualTable,\n                      LoopFileGnssStationInfo)\n\n\nGROOPS_READCONFIG_CLASS(Loop, \"loopType\")\n\n/***********************************************/\n\nLoopPtr Loop::create(Config &config, const std::string &name)\n{\n  try\n  {\n    LoopPtr     loop;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"\");\n\n    renameDeprecatedChoice(config, type, \"temporal\",        \"timeIntervals\",   date2time(2018, 5, 31));\n    renameDeprecatedChoice(config, type, \"manualList\",      \"stringList\",      date2time(2025, 9, 26));\n    // renameDeprecatedChoice(config, type, \"manualTable\",     \"stringTable\",     date2time(2025, 9, 26));\n    renameDeprecatedChoice(config, type, \"fileAscii\",       \"fileStringList\",  date2time(2025, 9, 26));\n    renameDeprecatedChoice(config, type, \"fileAsciiTable\",  \"fileStringTable\", date2time(2025, 9, 26));\n    renameDeprecatedChoice(config, type, \"fileLines\",       \"fileTextLines\",   date2time(2025, 9, 26));\n    renameDeprecatedChoice(config, type, \"uniformSampling\", \"numberSequence\",  date2time(2025, 9, 26));\n\n    if(readConfigChoiceElement(config, \"timeSeries\",              type, \"Loop over points in time\"))\n      loop = LoopPtr(new LoopTimeSeries(config));\n    if(readConfigChoiceElement(config, \"timeIntervals\",           type, \"Loop over time intervals\"))\n      loop = LoopPtr(new LoopTimeIntervals(config));\n    if(readConfigChoiceElement(config, \"stringList\",              type, \"Loop over list of strings\"))\n      loop = LoopPtr(new LoopStringList(config));\n    if(readConfigChoiceElement(config, \"stringTable\",             type, \"Loop over table of strings\"))\n      loop = LoopPtr(new LoopStringTable(config));\n    if(readConfigChoiceElement(config, \"fileStringList\",          type, \"Loop over list of strings from file\"))\n      loop = LoopPtr(new LoopFileStringList(config));\n    if(readConfigChoiceElement(config, \"fileStringTable\",         type, \"Loop over of a table containing strings\"))\n      loop = LoopPtr(new LoopFileStringTable(config));\n    if(readConfigChoiceElement(config, \"fileTextLines\",           type, \"Loop over of lines of a text file\"))\n      loop = LoopPtr(new LoopFileTextLines(config));\n    if(readConfigChoiceElement(config, \"matrix\",                  type, \"Loop over rows of a matrix\"))\n      loop = LoopPtr(new LoopMatrix(config));\n    if(readConfigChoiceElement(config, \"numberSequence\",          type, \"Loop over sequence of numbers\"))\n      loop = LoopPtr(new LoopNumberSequence(config));\n    if(readConfigChoiceElement(config, \"directoryListing\",        type, \"Loop over files of a directory\"))\n      loop = LoopPtr(new LoopDirectoryListing(config));\n    if(readConfigChoiceElement(config, \"commandOutput\",           type, \"Loop over lines of command output\"))\n      loop = LoopPtr(new LoopCommandOutput(config));\n    if(readConfigChoiceElement(config, \"platformEquipment\",       type, \"Loop over equipment of a platform file\"))\n      loop = LoopPtr(new LoopPlatformEquipment(config));\n    if(readConfigChoiceElement(config, \"loop\",                    type, \"Loop over loops\"))\n      loop = LoopPtr(new LoopLoop(config));\n    if(readConfigChoiceElement(config, \"sortAndRemoveDuplicates\", type, \"sort loops\"))\n      loop = LoopPtr(new LoopSortAndRemoveDuplicates(config));\n    if(readConfigChoiceElement(config, \"manualTable\",             type, \"DEPRECATED since 2025-09-27. Use stringTable instead\"))\n      loop = LoopPtr(new LoopManualTable(config));\n    if(readConfigChoiceElement(config, \"fileGnssStationInfo\",     type, \"DEPRECATED since 2022-11-11. Use platformEquipment instead\"))\n      loop = LoopPtr(new LoopFileGnssStationInfo(config));\n    endChoice(config);\n\n    return loop;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Loop::readConfigCondition(Config &config)\n{\n  ConditionPtr condition;\n  isCondition = readConfigLater(config, \"condition\", condition, conditionConfig, Config::OPTIONAL, \"\", \"check before each loop step\");\n  index_ = 0;\n}\n\n/***********************************************/\n\nBool Loop::checkCondition(VariableList &varList)\n{\n  try\n  {\n    index_++;\n    if(!isCondition)\n      return TRUE;\n    ConditionPtr condition;\n    conditionConfig.read(condition, varList);\n    // is condition false? -> perfrom directly next iteration\n    return (!condition || condition->condition(varList)) ? TRUE : iteration(varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/loop/loop.h",
    "content": "/***********************************************/\n/**\n* @file loop.h\n*\n* @brief Loop.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOP__\n#define __GROOPS_LOOP__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoop = R\"(\n\\section{Loop}\\label{loopType}\nGenerates a sequence with variables to loop over.\nThe variable names can be set with \\config{variableLoop...} and\nthe current values are assigned to the variables for each loop step.\n\nWith \\configClass{condition}{conditionType} only a subset of loop steps are performed.\nThe \\config{variableLoopIndex} and \\config{variableLoopCount} are not affected by the condition.\nThe result would therefore be the same as using \\program{LoopPrograms} with a nested \\program{IfPrograms}.\n\nSee \\reference{Loop and conditions}{general.loopsAndConditions} for usage.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/condition/condition.h\"\n\n/**\n* @defgroup loopGroup Loop\n* @brief Loop config elements of programs.\n* @ingroup classesGroup\n* The interface is given by @ref Loop. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Loop;\ntypedef std::shared_ptr<Loop> LoopPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Loop.\n* An instance of this class can be created with @ref readConfig. */\nclass Loop\n{\n  UInt         index_;\n  Bool         isCondition;\n  Config       conditionConfig;\n\nprotected:\n  void readConfigCondition(Config &config);\n  Bool checkCondition(VariableList &varList);\n\npublic:\n  /// Destructor.\n  virtual ~Loop() {}\n\n  /** @brief Returns the approximate total number of iterations. */\n  virtual UInt count() const = 0;\n\n  /** @brief Returns the number of already performed iteration steps. */\n  UInt index() const {return index_;}\n\n  /** @brief Sets values of loop variables in @p varList for current iteration.\n  * @return valid iteration step? */\n  virtual Bool iteration(VariableList &varList) = 0;\n\n  /** @brief creates an derived instance of this class. */\n  static LoopPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Loop.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a loop is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] loop Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Loop */\ntemplate<> Bool readConfig(Config &config, const std::string &name, LoopPtr &loop, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n#endif /* __GROOPS_DERIVATION__ */\n"
  },
  {
    "path": "source/classes/loop/loopCommandOutput.h",
    "content": "/***********************************************/\n/**\n* @file loopCommandOutput.h\n*\n* @brief Loop over lines of command output.\n*\n* @author Sebastian Strasser\n* @date 2017-02-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPCOMMANDOUTPUT__\n#define __GROOPS_LOOPCOMMANDOUTPUT__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopCommandOutput = R\"(\n\\subsection{CommandOutput}\\label{loopType:commandOutput}\nLoop over lines of command output.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/system.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over lines of command output.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopCommandOutput : public Loop\n{\n  std::string              nameString, nameIndex, nameCount;\n  std::vector<std::string> strings;\n\npublic:\n  LoopCommandOutput(Config &config);\n\n  UInt count() const override {return strings.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopCommandOutput::LoopCommandOutput(Config &config)\n{\n  try\n  {\n    std::vector<FileName> commands;\n    Bool                  silently;\n\n    readConfig(config, \"command\",            commands,   Config::MUSTSET,  \"\",            \"each output line becomes a loop iteration\");\n    readConfig(config, \"silently\",           silently,   Config::DEFAULT,  \"0\",           \"without showing the output.\");\n    readConfig(config, \"variableLoopString\", nameString, Config::OPTIONAL, \"loopCommand\", \"name of the variable to be replaced\");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL, \"\",            \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL, \"\",            \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    for(const auto &command : commands)\n    {\n      UInt count = strings.size();\n      if(!System::exec(command, strings))\n        throw(Exception(\"Command \\\"\"+command.str()+\"\\\" exited with error\"));\n      if(strings.size() == count)\n        logWarningOnce<<\"Command \\\"\"+command.str()+\"\\\" returned no output\"<<Log::endl;\n    } // for(i)\n\n    if(!silently)\n      for(const auto &str : strings)\n        logInfo<<str<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopCommandOutput::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameString.empty()) varList.setVariable(nameString, strings.at(index()));\n  if(!nameIndex.empty())  varList.setVariable(nameIndex,  index());\n  if(!nameCount.empty())  varList.setVariable(nameCount,  count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopDirectoryListing.h",
    "content": "/***********************************************/\n/**\n* @file loopDirectoryListing.h\n*\n* @brief Loop over files of a directory.\n*\n* @author Torsten Mayer.Guerr\n* @date 2017-02-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPDIRECTORYLISTING__\n#define __GROOPS_LOOPDIRECTORYLISTING__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopDirectoryListing = R\"(\n\\subsection{DirectoryListing}\\label{loopType:directoryListing}\nLoop over files of a directory.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"parallel/parallel.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/system.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over files of a directory.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopDirectoryListing : public Loop\n{\n  std::string           nameFile, nameIndex, nameCount;\n  std::vector<FileName> files;\n\npublic:\n  LoopDirectoryListing(Config &config);\n\n  UInt count() const override {return files.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopDirectoryListing::LoopDirectoryListing(Config &config)\n{\n  try\n  {\n    FileName    directory;\n    std::string pattern;\n    Bool        isRegularExpression;\n\n    readConfig(config, \"directory\",           directory,           Config::MUSTSET,  \"\",         \"directory\");\n    readConfig(config, \"pattern\",             pattern,             Config::DEFAULT,  \"*\",        \"wildcard pattern\");\n    readConfig(config, \"isRegularExpression\", isRegularExpression, Config::DEFAULT,  \"0\",        \"pattern is a regular expression\");\n    readConfig(config, \"variableLoopFile\",    nameFile,            Config::OPTIONAL, \"loopFile\", \"name of the variable to be replaced\");\n    readConfig(config, \"variableLoopIndex\",   nameIndex,           Config::OPTIONAL, \"\",         \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",   nameCount,           Config::OPTIONAL, \"\",         \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    files = System::directoryListing(directory, isRegularExpression ? std::regex(pattern) : String::wildcard2regex(pattern));\n    std::sort(files.begin(), files.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopDirectoryListing::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameFile.empty())  varList.setVariable(nameFile,  files.at(index()).str());\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopFileGnssStationInfo.h",
    "content": "/***********************************************/\n/**\n* @file loopFileGnssStationInfo.h\n*\n* @brief DEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.\n*\n* @author Sebastian Strasser\n* @date 2018-01-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPFILEGNSSSTATIONINFO__\n#define __GROOPS_LOOPFILEGNSSSTATIONINFO__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopFileGnssStationInfo = R\"(\n\\subsection{FileGnssStationInfo}\nDEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2022-11-11. Use LoopPlatformEquipment instead.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopFileGnssStationInfo : public Loop\n{\n  Platform                platform;\n  PlatformEquipment::Type type;\n  std::string             nameName, nameSerial, nameInfo, nameTimeStart, nameTimeEnd;\n  std::string             nameIndex, nameCount;\n\npublic:\n  LoopFileGnssStationInfo(Config &config);\n\n  UInt count() const override {return std::count_if(platform.equipments.begin(), platform.equipments.end(), [&](const auto &x)\n                                                   {return (x->getType() == type);});}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopFileGnssStationInfo::LoopFileGnssStationInfo(Config &config)\n{\n  try\n  {\n    FileName    fileName;\n    std::string choice;\n\n    readConfig(config, \"inputfileGnssStationInfo\", fileName, Config::MUSTSET, \"\", \"station/transmitter info file\");\n    if(readConfigChoice(config, \"infoType\", choice, Config::MUSTSET, \"\", \"info to loop over\"))\n    {\n      if(readConfigChoiceElement(config, \"antenna\",  choice, \"loop over antennas\"))  type = PlatformEquipment::GNSSANTENNA;\n      if(readConfigChoiceElement(config, \"receiver\", choice, \"loop over receivers\")) type = PlatformEquipment::GNSSRECEIVER;\n      endChoice(config);\n    }\n    readConfig(config, \"variableLoopName\",      nameName,      Config::OPTIONAL,  \"loopName\",      \"variable with antenna/receiver name\");\n    readConfig(config, \"variableLoopSerial\",    nameSerial,    Config::OPTIONAL,  \"loopSerial\",    \"variable with antenna/receiver serial\");\n    readConfig(config, \"variableLoopInfo\",      nameInfo,      Config::OPTIONAL,  \"loopInfo\",      \"variable with radome (antenna) or version (receiver)\");\n    readConfig(config, \"variableLoopTimeStart\", nameTimeStart, Config::OPTIONAL,  \"loopTimeStart\", \"variable with antenna/receiver start time\");\n    readConfig(config, \"variableLoopTimeEnd\",   nameTimeEnd,   Config::OPTIONAL,  \"loopTimeEnd\",   \"variable with antenna/receiver end time\");\n    readConfig(config, \"variableLoopIndex\",     nameIndex,     Config::OPTIONAL,  \"\",              \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",     nameCount,     Config::OPTIONAL,  \"\",              \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    logWarningOnce<<\"DEPRECATED since 2022-11-11: Loop->FileGnssStationInfo. Use Loop->PlatformEquipment instead.\"<<Log::endl;\n\n    readFilePlatform(fileName, platform);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopFileGnssStationInfo::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  UInt idx = 0;\n  for(const auto &eq : platform.equipments)\n    if((eq->getType() == type) && (idx++ == index()))\n    {\n      if(!nameIndex.empty())     varList.setVariable(nameIndex,     index());\n      if(!nameCount.empty())     varList.setVariable(nameCount,     count());\n      if(!nameName.empty())      varList.setVariable(nameName,      eq->name);\n      if(!nameSerial.empty())    varList.setVariable(nameSerial,    eq->serial);\n      if(!nameTimeStart.empty()) varList.setVariable(nameTimeStart, eq->timeStart.mjd());\n      if(!nameTimeEnd.empty())   varList.setVariable(nameTimeEnd,   eq->timeEnd.mjd());\n      if(!nameInfo.empty())\n      {\n        switch(eq->getType())\n        {\n          case PlatformEquipment::GNSSANTENNA:  varList.setVariable(nameInfo, std::dynamic_pointer_cast<PlatformGnssAntenna>(eq)->radome); break;\n          case PlatformEquipment::GNSSRECEIVER: varList.setVariable(nameInfo, std::dynamic_pointer_cast<PlatformGnssReceiver>(eq)->version); break;\n          case PlatformEquipment::OTHER:        break;\n          case PlatformEquipment::UNDEFINED:    break;\n          default:                              break;\n        }\n      }\n      break;\n    }\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopFileStringList.h",
    "content": "/***********************************************/\n/**\n* @file loopFileStringList.h\n*\n* @brief Loop over list of strings from files.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPFILESTRINGLIST__\n#define __GROOPS_LOOPFILESTRINGLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopFileStringList = R\"(\n\\subsection{FileStringList}\\label{loopType:fileStringList}\nLoop over list of strings from \\file{files}{stringList}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/loop/loop.h\"\n#include <unordered_set>\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over list of strings from files.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopFileStringList : public Loop\n{\n  std::string nameString, nameIndex, nameCount;\n  std::vector<std::string> strings;\n\npublic:\n  LoopFileStringList(Config &config);\n\n  UInt count() const override {return strings.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopFileStringList::LoopFileStringList(Config &config)\n{\n  try\n  {\n    std::vector<FileName> fileName;\n\n    readConfig(config, \"inputfile\",          fileName,   Config::MUSTSET,  \"\",           \"string list file\");\n    readConfig(config, \"variableLoopString\", nameString, Config::OPTIONAL, \"loopString\", \"name of the variable to be replaced\");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL, \"\",           \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL, \"\",           \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    for(UInt i=0; i<fileName.size(); i++)\n    {\n      std::vector<std::string> str;\n      readFileStringList(fileName.at(i), str);\n      strings.insert(strings.end(), str.begin(), str.end());\n    }\n\n    // DEPRECTATED\n    // -----------\n    // read deprecated config elements (as after if(isCreateSchema(config)) not shown in the GUI and docu)\n    UInt startIndex;\n    UInt countElements = MAX_UINT;\n    Bool sort;\n    Bool removeDuplicates;\n    readConfig(config, \"sort\",               sort,             Config::DEFAULT,  \"0\", \"sort entries alphabetically (ascending)\");\n    readConfig(config, \"removeDuplicates\",   removeDuplicates, Config::DEFAULT,  \"0\", \"remove duplicate entries (order is preserved)\");\n    readConfig(config, \"startIndex\",         startIndex,       Config::DEFAULT,  \"0\", \"start at element startIndex (counting from 0)\");\n    readConfig(config, \"count\",              countElements,    Config::OPTIONAL, \"\",  \"use count elements (default: use all)\");\n    if(sort)\n    {\n      logWarningOnce<<\"DEPRECATED since 2025-09-27: In Loop->FileStringList->sort . Please use SortAndRemoveDuplicates instead.\"<<Log::endl;\n      std::sort(strings.begin(), strings.end());\n    }\n    if(removeDuplicates)\n    {\n      logWarningOnce<<\"DEPRECATED since 2025-09-27: In Loop->FileStringList->removeDuplicates. Please use SortAndRemoveDuplicates instead.\"<<Log::endl;\n      std::unordered_set<std::string> set;\n      auto end = std::copy_if(strings.begin(), strings.end(), strings.begin(), [&set](auto &s) {return set.insert(s).second;});\n      strings.erase(end, strings.end());\n    }\n    if((startIndex != 0) || (countElements != MAX_UINT))\n      logWarningOnce<<\"DEPRECATED since 2025-09-27: In Loop->FileStringList->startIndex and ->count. Please use a condition instead.\"<<Log::endl;\n    strings.erase(strings.begin(), strings.begin()+std::min(startIndex, strings.size()));\n    strings.erase(strings.begin()+std::min(countElements, strings.size()), strings.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopFileStringList::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameString.empty()) varList.setVariable(nameString, strings.at(index()));\n  if(!nameIndex.empty())  varList.setVariable(nameIndex,  index());\n  if(!nameCount.empty())  varList.setVariable(nameCount,  count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopFileStringTable.h",
    "content": "/***********************************************/\n/**\n* @file loopFileStringTable.h\n*\n* @brief Loop over rows of a table containing strings.\n*\n* @author Norbert Zehentner\n* @author Sebastian Strasser\n* @date 2017-02-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPFILESTRINGTABLE__\n#define __GROOPS_LOOPFILESTRINGTABLE__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopFileStringTable = R\"(\n\\subsection{FileStringTable}\\label{loopType:fileStringTable}\nLoop over rows of a \\file{table}{stringTable} containing strings.\nEach row must have the same number of columns.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over rows of a table containing strings.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopFileStringTable : public Loop\n{\n  std::vector<std::vector<std::string>>  stringTable;\n  std::vector<std::string>               nameString;\n  std::string                            nameIndex, nameCount;\n\npublic:\n  LoopFileStringTable(Config &config);\n\n  UInt count() const override {return stringTable.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopFileStringTable::LoopFileStringTable(Config &config)\n{\n  try\n  {\n    std::vector<FileName> fileNames;\n    Bool transpose;\n\n    readConfig(config, \"inputfile\",          fileNames,  Config::MUSTSET,  \"\",           \"string table file with multiple columns\");\n    readConfig(config, \"transpose\",          transpose,  Config::DEFAULT,  \"0\",          \"loop over columns instead of rows\");\n    readConfig(config, \"variableLoopString\", nameString, Config::MUSTSET,  \"loopString\", \"1. variable name for the 1. column, next variable name for the 2. column, ... \");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL, \"\",           \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL, \"\",           \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    for(auto &fileName : fileNames)\n      readFileStringTable(fileName, stringTable);\n\n    // transpose table\n    if(stringTable.size() && transpose)\n    {\n      const UInt cols = std::max_element(stringTable.begin(), stringTable.end(), [](auto &s1, auto &s2){return s1.size() < s2.size();})->size();\n      std::vector<std::vector<std::string>> tmp(cols);\n      for(UInt i=0; i<stringTable.size(); i++)\n        for(UInt k=0; k<stringTable.at(i).size(); k++)\n          tmp.at(k).push_back(stringTable.at(i).at(k));\n      stringTable = std::move(tmp);\n    }\n\n    if(stringTable.size() && (nameString.size() > std::min_element(stringTable.begin(), stringTable.end(), [](auto &s1, auto &s2){return s1.size() < s2.size();})->size()))\n      throw(Exception(\"More variables than minimum columns in the table\"));\n\n    // DEPRECTATED\n    // -----------\n    // read deprecated config elements (as after if(isCreateSchema(config)) not shown in the GUI and docu)\n    UInt startRow, countRows = MAX_UINT;\n    readConfig(config, \"startLine\",  startRow,   Config::DEFAULT,  \"0\", \"start at line startLine (counting from 0)\");\n    readConfig(config, \"countLines\", countRows,  Config::OPTIONAL, \"\",  \"read count lines (default: all)\");\n    if((startRow != 0) || (countRows != MAX_UINT))\n      logWarningOnce<<\"DEPRECATED since 2025-09-27: In Loop->FileStringTable->startIndex and ->count. Please use a condition instead.\"<<Log::endl;\n    stringTable.erase(stringTable.begin(), stringTable.begin()+std::min(startRow, stringTable.size()));\n    stringTable.erase(stringTable.begin()+std::min(countRows, stringTable.size()), stringTable.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopFileStringTable::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  for(UInt i=0; i<nameString.size(); i++)\n    if(!nameString.at(i).empty())\n      varList.setVariable(nameString.at(i), stringTable.at(index()).at(i));\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopFileTextLines.h",
    "content": "/***********************************************/\n/**\n* @file loopFileTextLines.h\n*\n* @brief Loop over lines of a text file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPFILETEXTLINES__\n#define __GROOPS_LOOPFILETEXTLINES__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopFileTextLines = R\"(\n\\subsection{FileTextLines}\\label{loopType:fileTextLines}\nLoop over lines of a text file.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/file.h\"\n#include \"classes/loop/loop.h\"\n#include <unordered_set>\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over lines of a text file.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopFileTextLines : public Loop\n{\n  std::vector<std::string> lines;\n  std::string nameLine, nameIndex, nameCount;\n\npublic:\n  LoopFileTextLines(Config &config);\n\n  UInt count() const override {return lines.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopFileTextLines::LoopFileTextLines(Config &config)\n{\n  try\n  {\n    std::vector<FileName> fileNames;\n    UInt startIndex, countElements = MAX_UINT;\n\n    readConfig(config, \"inputfile\",         fileNames,     Config::MUSTSET,  \"\",         \"simple text file with lines\");\n    readConfig(config, \"startIndex\",        startIndex,    Config::DEFAULT,  \"0\",        \"start at element startIndex (counting from 0)\");\n    readConfig(config, \"count\",             countElements, Config::OPTIONAL, \"\",         \"use number of loops only (default: use all)\");\n    readConfig(config, \"variableLoopLine\",  nameLine,      Config::OPTIONAL, \"loopLine\", \"name of the variable to be replaced\");\n    readConfig(config, \"variableLoopIndex\", nameIndex,     Config::OPTIONAL, \"\",         \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\", nameCount,     Config::OPTIONAL, \"\",         \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    for(auto &fileName : fileNames)\n    {\n      InFile file(fileName);\n      std::string line;\n      while(std::getline(file, line))\n        lines.push_back(line);\n    }\n\n    lines.erase(lines.begin(), lines.begin()+std::min(startIndex, lines.size()));\n    lines.erase(lines.begin()+std::min(countElements, lines.size()), lines.end());\n\n    // DEPRECTATED\n    // -----------\n    // read deprecated config elements (as after if(isCreateSchema(config)) not shown in the GUI and docu)\n    Bool sort;\n    Bool removeDuplicates;\n    readConfig(config, \"sort\",             sort,             Config::DEFAULT,  \"0\", \"sort lines alphabetically (ascending)\");\n    readConfig(config, \"removeDuplicates\", removeDuplicates, Config::DEFAULT,  \"0\", \"remove duplicate lines (order is preserved)\");\n    if(sort)\n    {\n      logWarningOnce<<\"DEPRECATED since 2025-09-27: Loop->FileTextLines->sort. Please use Loop->SortAndRemoveDuplicates instead.\"<<Log::endl;\n      std::sort(lines.begin(), lines.end());\n    }\n    if(removeDuplicates)\n    {\n      logWarningOnce<<\"DEPRECATED since 2025-09-27: Loop->FileTextLines->removeDuplicates. Please use Loop->SortAndRemoveDuplicates instead.\"<<Log::endl;\n      std::unordered_set<std::string> set;\n      lines.erase(std::copy_if(lines.begin(), lines.end(), lines.begin(), [&set](auto &s) {return set.insert(s).second;}), lines.end());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopFileTextLines::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameLine.empty())  varList.setVariable(nameLine,  lines.at(index()));\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopLoop.h",
    "content": "/***********************************************/\n/**\n* @file loopLoop.h\n*\n* @brief Loop over nested loops.\n*\n* @author Matthias Ellmer\n* @author Sebastian Strasser\n* @date 2017-07-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPLOOP__\n#define __GROOPS_LOOPLOOP__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopLoop = R\"(\n\\subsection{Loop}\\label{loopType:loop}\nLoop over nested loops. First \\config{loop} is outermost loop, every subsequent \\config{loop} is one level below the previous \\config{loop}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over nested loops.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopLoop : public Loop\n{\n  std::vector<Config>  loopConfigs;\n  std::vector<LoopPtr> loops;\n  std::string          nameIndex;\n\npublic:\n  LoopLoop(Config &config);\n\n  UInt count() const override;\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopLoop::LoopLoop(Config &config)\n{\n  try\n  {\n    readConfigLater(config, \"loop\", loops, loopConfigs, Config::MUSTSET,  \"\", \"subloop\");\n    readConfig(config, \"variableLoopIndex\", nameIndex, Config::OPTIONAL, \"\", \"variable with index of current iteration (starts with zero)\");\n    readConfigCondition(config);\n    if(isCreateSchema(config))\n      return;\n\n    loops.resize(loopConfigs.size());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline UInt LoopLoop::count() const\n{\n  UInt count = 1;\n  for(auto loop : loops)\n    if(loop)\n      count *= loop->count();\n  return std::max(index(), count);\n}\n\n/***********************************************/\n\ninline Bool LoopLoop::iteration(VariableList &varList)\n{\n  try\n  {\n    std::function<Bool(UInt)> initLoop = [&](UInt i) -> Bool\n    {\n      loopConfigs.at(i).read(loops.at(i), varList);\n      while(loops.at(i)->iteration(varList))\n        if((i+1 >= loops.size()) || initLoop(i+1))\n          return TRUE;\n      return FALSE;\n    };\n\n    if(index() == 0)\n    {\n      if(!initLoop(0))\n        return FALSE;\n      if(!nameIndex.empty())\n        varList.setVariable(nameIndex, index());\n      return checkCondition(varList);\n    }\n\n    for(UInt i=loops.size(); i-->0;)\n      while(loops.at(i)->iteration(varList))\n        if((i+1 >= loops.size()) || initLoop(i+1))\n        {\n          if(!nameIndex.empty())\n            varList.setVariable(nameIndex, index());\n          return checkCondition(varList);\n        }\n\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopManualTable.h",
    "content": "/***********************************************/\n/**\n* @file loopManualTable.h\n*\n* @brief DEPRECATED since 2025-09-27. Use LoopStringTable instead.\n*\n* @author Sebastian Strasser\n* @date 2017-02-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPMANUALTABLE__\n#define __GROOPS_LOOPMANUALTABLE__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopManualTable = R\"(\n\\subsection{ManualTable}\nDEPRECATED since 2025-09-27. Use LoopStringTable instead.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2025-09-27. Use LoopStringTable instead.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopManualTable : public Loop\n{\npublic:\n  class CellVector\n  {\n  public:\n    std::vector<std::string> cells;\n  };\n\nprivate:\n  std::vector<CellVector>  rows;\n  std::vector<std::string> nameString;\n  std::string              nameIndex, nameCount;\n\npublic:\n  LoopManualTable(Config &config);\n\n  UInt count() const override {return rows.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, LoopManualTable::CellVector &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"cell\", var.cells, Config::MUSTSET, \"\", \"explicit list of cells in row/column\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ninline LoopManualTable::LoopManualTable(Config &config)\n{\n  try\n  {\n    std::vector<CellVector> columns;\n\n    std::string choice;\n    if(readConfigChoice(config, \"table\", choice, Config::MUSTSET, \"\", \"define table by rows/columns\"))\n    {\n      if(readConfigChoiceElement(config, \"rowWise\",    choice, \"define table by rows\"))\n        readConfig(config, \"row\",    rows,    Config::MUSTSET, \"\", \"define table by rows\");\n      if(readConfigChoiceElement(config, \"columnWise\", choice, \"define table by columns\"))\n        readConfig(config, \"column\", columns, Config::MUSTSET, \"\", \"define table by columns\");\n      endChoice(config);\n    }\n    readConfig(config, \"variableLoopString\", nameString, Config::MUSTSET,  \"loopString\", \"1. variable name for the 1. column, next variable name for the 2. column, ... \");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL, \"\",           \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL, \"\",           \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    logWarningOnce<<\"DEPRECATED since 2025-09-27: Loop->ManualTable. Use Loop->StringTable instead.\"<<Log::endl;\n\n    // transpose columns\n    for(UInt i=0; i<columns.size(); i++)\n      for(UInt k=0; k<columns.at(i).cells.size(); k++)\n      {\n        rows.resize(k+1);\n        rows.at(k).cells.push_back(columns.at(i).cells.at(k));\n      }\n\n    if(rows.size() > 1)\n    {\n      if(nameString.size() > rows.at(0).cells.size())\n        throw(Exception(\"More variables than columns in the table\"));\n      for(UInt i=1; i<rows.size(); i++)\n        if(rows.at(i).cells.size() != rows.at(0).cells.size())\n          throw(Exception(\"Varying number of columns in the table\"));\n     }\n   }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopManualTable::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  for(UInt i=0; i<nameString.size(); i++)\n    if(!nameString.at(i).empty())\n      varList.setVariable(nameString.at(i), rows.at(index()).cells.at(i));\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopMatrix.h",
    "content": "/***********************************************/\n/**\n* @file loopMatrix.h\n*\n* @brief Loop over rows of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPMATRIX__\n#define __GROOPS_LOOPMATRIX__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopMatrix = R\"(\n\\subsection{Matrix}\\label{loopType:matrix}\nLoop over rows of a \\file{matrix}{matrix}. To define the loop variables the standard\ndata variables of the matrix are available, see~\\reference{dataVariables}{general.parser:dataVariables}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over rows of a matrix.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopMatrix : public Loop\n{\n  Matrix          A;\n  std::vector<ExpressionVariablePtr> variables;\n  std::string     nameIndex, nameCount;\n  VariableList    varListMatrix;\n\npublic:\n  LoopMatrix(Config &config);\n\n  UInt count() const override {return A.rows();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopMatrix::LoopMatrix(Config &config)\n{\n  try\n  {\n    FileName              fileName;\n    ExpressionVariablePtr startRow, countRows;\n    Bool                  transpose;\n\n    readConfig(config, \"inputfile\",          fileName,  Config::MUSTSET,  \"\",                 \"\");\n    readConfig(config, \"transpose\",          transpose, Config::DEFAULT,  \"0\",                \"effectively loop over columns\");\n    readConfig(config, \"startRow\",           startRow,  Config::DEFAULT,  \"0\",                \"start at this row (variable: rows)\");\n    readConfig(config, \"countRows\",          countRows, Config::DEFAULT,  \"rows\",             \"use this many rows (variable: rows)\");\n    readConfig(config, \"variableLoop\",       variables, Config::MUSTSET,  \"loopNumber=data0\", \"define a variable by name = expression (input columns are named data0, data1, ...)\");\n    readConfig(config, \"variableLoopIndex\",  nameIndex, Config::OPTIONAL, \"\",                 \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount, Config::OPTIONAL, \"\",                 \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    readFileMatrix(fileName, A);\n    if(transpose)\n      A = A.trans();\n\n    varListMatrix.setVariable(\"rows\", A.rows());\n    A = A.row(static_cast<UInt>(startRow->evaluate(varListMatrix)), static_cast<UInt>(countRows->evaluate(varListMatrix)));\n\n    for(auto &variable : variables)\n      variable->parseVariableName(); // get real variable names, otherwise all named 'variableLoop'\n    addDataVariables(A, varListMatrix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopMatrix::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  evaluateDataVariables(A, index(), varListMatrix);\n  for(auto &variable : variables)\n    varList.setVariable(variable->name(), variable->evaluate(varListMatrix));\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopNumberSequence.h",
    "content": "/***********************************************/\n/**\n* @file loopNumberSequence.h\n*\n* @brief Loop over sequence of numbers.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPNUMBERSEQUENCE__\n#define __GROOPS_LOOPNUMBERSEQUENCE__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopNumberSequence = R\"(\n\\subsection{NumberSequence}\\label{loopType:numberSequence}\nLoop over sequence of numbers.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over sequence of numbers.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopNumberSequence : public Loop\n{\n  std::string         nameNumber, nameIndex, nameCount;\n  std::vector<Double> numbers;\n\npublic:\n  LoopNumberSequence(Config &config);\n\n  UInt count() const override {return numbers.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopNumberSequence::LoopNumberSequence(Config &config)\n{\n  try\n  {\n    Double rangeStart, rangeEnd, sampling;\n\n    readConfig(config, \"rangeStart\",         rangeStart, Config::MUSTSET,   \"\",           \"start of range\");\n    readConfig(config, \"rangeEnd\",           rangeEnd,   Config::MUSTSET,   \"\",           \"end of range (inclusive)\");\n    readConfig(config, \"sampling\",           sampling,   Config::MUSTSET,   \"\",           \"sampling\");\n    readConfig(config, \"variableLoopNumber\", nameNumber, Config::OPTIONAL,  \"loopNumber\", \"name of the variable to be replaced\");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL,  \"\",           \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL,  \"\",           \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    for(UInt i=0; rangeStart+i*sampling<=rangeEnd; i++)\n      numbers.push_back(rangeStart + i*sampling);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopNumberSequence::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameNumber.empty()) varList.setVariable(nameNumber, numbers.at(index()));\n  if(!nameIndex.empty())  varList.setVariable(nameIndex,  index());\n  if(!nameCount.empty())  varList.setVariable(nameCount,  count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopPlatformEquipment.h",
    "content": "/***********************************************/\n/**\n* @file loopPlatformEquipment.h\n*\n* @brief Loop over equipment of a platform file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-11-11\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPPLATFORMEQUIPMENT__\n#define __GROOPS_LOOPPLATFORMEQUIPMENT__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopPlatformEquipment = R\"(\n\\subsection{PlatformEquipment}\\label{loopType:platformEquipment}\nLoop over specific equipment of a \\file{platform file}{platform}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over equipment of a platform file.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopPlatformEquipment : public Loop\n{\n  Platform                platform;\n  PlatformEquipment::Type type;\n  std::string             nameName, nameSerial, nameInfo, nameTimeStart, nameTimeEnd;\n  std::string             nameIndex, nameCount;\n  std::string             namePositionX, namePositionY, namePositionZ;\n\npublic:\n  LoopPlatformEquipment(Config &config);\n\n  UInt count() const override {return std::count_if(platform.equipments.begin(), platform.equipments.end(), [&](const auto &x)\n                                                   {return (type == PlatformEquipment::UNDEFINED) || (x->getType() == type);});}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopPlatformEquipment::LoopPlatformEquipment(Config &config)\n{\n  try\n  {\n    FileName    fileName;\n    std::string choice;\n\n    readConfig(config, \"inputfilePlatform\", fileName, Config::MUSTSET, \"\", \"platform info file\");\n    if(readConfigChoice(config, \"equipmentType\", choice, Config::MUSTSET, \"\", \"equipment type to loop over\"))\n    {\n      if(readConfigChoiceElement(config, \"all\",                 choice, \"loop over all types\"))             type = PlatformEquipment::UNDEFINED;\n      if(readConfigChoiceElement(config, \"gnssAntenna\",         choice, \"loop over antennas\"))              type = PlatformEquipment::GNSSANTENNA;\n      if(readConfigChoiceElement(config, \"gnssReceiver\",        choice, \"loop over receivers\"))             type = PlatformEquipment::GNSSRECEIVER;\n      if(readConfigChoiceElement(config, \"slrStation\",          choice, \"loop over SLR stations\"))          type = PlatformEquipment::SLRSTATION;\n      if(readConfigChoiceElement(config, \"slrRetroReflector\",   choice, \"loop over laser retroreflectors\")) type = PlatformEquipment::LASERRETROREFLECTOR;\n      if(readConfigChoiceElement(config, \"satelliteIdentifier\", choice, \"loop over satellite identifiers\")) type = PlatformEquipment::SATELLITEIDENTIFIER;\n      if(readConfigChoiceElement(config, \"other\",               choice, \"loop over other types\"))           type = PlatformEquipment::OTHER;\n      endChoice(config);\n    }\n    readConfig(config, \"variableLoopName\",      nameName,            Config::OPTIONAL,  \"loopName\",      \"variable with name\");\n    readConfig(config, \"variableLoopSerial\",    nameSerial,          Config::OPTIONAL,  \"loopSerial\",    \"variable with serial\");\n    readConfig(config, \"variableLoopInfo\",      nameInfo,            Config::OPTIONAL,  \"loopInfo\",      \"variable with radome (antenna) or version (receiver)\");\n    readConfig(config, \"variableLoopTimeStart\", nameTimeStart,       Config::OPTIONAL,  \"loopTimeStart\", \"variable with start time\");\n    readConfig(config, \"variableLoopTimeEnd\",   nameTimeEnd,         Config::OPTIONAL,  \"loopTimeEnd\",   \"variable with end time\");\n    readConfig(config, \"variableLoopPositionX\", namePositionX,       Config::OPTIONAL,  \"loopPositionX\", \"variable with position x\");\n    readConfig(config, \"variableLoopPositionY\", namePositionY,       Config::OPTIONAL,  \"loopPositionY\", \"variable with position y\");\n    readConfig(config, \"variableLoopPositionY\", namePositionZ,       Config::OPTIONAL,  \"loopPositionZ\", \"variable with position z\");\n    readConfig(config, \"variableLoopIndex\",     nameIndex,           Config::OPTIONAL,  \"\",              \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",     nameCount,           Config::OPTIONAL,  \"\",              \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    readFilePlatform(fileName, platform);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopPlatformEquipment::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  UInt idx = 0;\n  for(const auto &eq : platform.equipments)\n    if(((type == PlatformEquipment::UNDEFINED) || (eq->getType() == type)) && (idx++ == index()))\n    {\n      if(!nameIndex.empty())     varList.setVariable(nameIndex,     index());\n      if(!nameCount.empty())     varList.setVariable(nameCount,     count());\n      if(!nameName.empty())      varList.setVariable(nameName,      eq->name);\n      if(!nameSerial.empty())    varList.setVariable(nameSerial,    eq->serial);\n      if(!nameTimeStart.empty()) varList.setVariable(nameTimeStart, eq->timeStart.mjd());\n      if(!nameTimeEnd.empty())   varList.setVariable(nameTimeEnd,   eq->timeEnd.mjd());\n      if(!namePositionX.empty()) varList.setVariable(namePositionX, eq->position.x());\n      if(!namePositionY.empty()) varList.setVariable(namePositionY, eq->position.y());\n      if(!namePositionZ.empty()) varList.setVariable(namePositionZ, eq->position.z());\n      if(!nameInfo.empty())\n      {\n        switch(eq->getType())\n        {\n          case PlatformEquipment::GNSSANTENNA:  varList.setVariable(nameInfo, std::dynamic_pointer_cast<PlatformGnssAntenna>(eq)->radome);   break;\n          case PlatformEquipment::GNSSRECEIVER: varList.setVariable(nameInfo, std::dynamic_pointer_cast<PlatformGnssReceiver>(eq)->version); break;\n          default: varList.setVariable(nameInfo,\"\"); break;\n        }\n      }\n      break;\n    }\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopSortAndRemoveDuplicates.h",
    "content": "/***********************************************/\n/**\n* @file loopSortAndRemoveDuplicates.h\n*\n* @brief Sort and removes duplicates from a loop.\n*\n* @author Torsten Mayer-Guerr\n* @date 2025-09-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPSORTANDREMOVEDUPLICATES__\n#define __GROOPS_LOOPSORTANDREMOVEDUPLICATES__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopSortAndRemoveDuplicates = R\"(\n\\subsection{SortAndRemoveDuplicates}\\label{loopType:sortAndRemoveDuplicates}\nPerform the \\configClass{loop}{loopType} in the alphabetically\norder defined by the evaluated \\config{sortString} for each loop step.\nSo the string must contain loop variables. If \\config{sortString}\nis empty, no sorting will take place.\n\nExample: The \\config{sortString}=\\verb|{loopTime:%m}| of a time series\nsorts the times in ascending order by month.\n\nThe same principle is used to remove duplicates. If different loop steps\nevaluates \\config{removeDuplicatesString} to the same string,\nonly the first loop step is executed.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parser/stringParser.h\"\n#include \"classes/loop/loop.h\"\n#include <unordered_set>\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over lines of a text file.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopSortAndRemoveDuplicates : public Loop\n{\n  class Loop\n  {\n  public:\n    VariableList varList;\n    std::string sortString, duplicatesString;\n  };\n\n  std::vector<Loop> loops;\n  std::string nameIndex, nameCount;\n\npublic:\n  LoopSortAndRemoveDuplicates(Config &config);\n\n  UInt count() const override {return loops.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopSortAndRemoveDuplicates::LoopSortAndRemoveDuplicates(Config &config)\n{\n  try\n  {\n    LoopPtr loopPtr;\n    std::pair<std::string, VariableList> sortString, duplicatesString;\n    Bool    descending;\n\n    readConfig(config, \"loop\",                   loopPtr,          Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"sortString\",             sortString,       Config::OPTIONAL, \"\",  \"use {loopVariables}, sort alphabetically\");\n    readConfig(config, \"descending\",             descending,       Config::DEFAULT,  \"0\", \"sorting descending instead of ascending\");\n    readConfig(config, \"removeDuplicatesString\", duplicatesString, Config::OPTIONAL, \"\",  \"use {loopVariables}, remove duplicates (order is preserved)\");\n    readConfig(config, \"variableLoopIndex\",      nameIndex,        Config::OPTIONAL, \"\",  \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",      nameCount,        Config::OPTIONAL, \"\",  \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    // perform the loops\n    // -----------------\n    VariableList varList;\n    for(;;)\n    {\n      loops.resize(loops.size()+1);\n      if(!loopPtr->iteration(varList))\n        break;\n      loops.back().varList = varList;\n      // evaluate sort string & duplicate string\n      loops.back().sortString       = StringParser::parse(sortString.first,       VariableList(sortString.second)       += loops.back().varList);\n      loops.back().duplicatesString = StringParser::parse(duplicatesString.first, VariableList(duplicatesString.second) += loops.back().varList);\n    }\n    loops.pop_back(); // remove last unused\n\n    // sort\n    // ----\n    if(!sortString.first.empty())\n    {\n      if(descending)\n        std::stable_sort(loops.begin(), loops.end(), [](auto &l1, auto &l2){return l1.sortString > l2.sortString;});\n      else\n        std::stable_sort(loops.begin(), loops.end(), [](auto &l1, auto &l2){return l1.sortString < l2.sortString;});\n    }\n\n    // remove duplicates\n    // -----------------\n    if(!duplicatesString.first.empty())\n    {\n      std::unordered_set<std::string> set;\n      loops.erase(std::copy_if(loops.begin(), loops.end(), loops.begin(), [&set](auto &loop) {return set.insert(loop.duplicatesString).second;}), loops.end());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopSortAndRemoveDuplicates::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  varList += loops.at(index()).varList;\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopStringList.h",
    "content": "/***********************************************/\n/**\n* @file loopStringList.h\n*\n* @brief Loop over list of strings.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPSTRINGLIST__\n#define __GROOPS_LOOPSTRINGLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopStringList = R\"(\n\\subsection{StringList}\\label{loopType:stringList}\nLoop over list of strings.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over list of strings.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopStringList : public Loop\n{\n  std::string              nameString, nameIndex, nameCount;\n  std::vector<std::string> strings;\n\npublic:\n  LoopStringList(Config &config);\n\n  UInt count() const override {return strings.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopStringList::LoopStringList(Config &config)\n{\n  try\n  {\n    readConfig(config, \"string\",             strings,    Config::OPTIONAL,  \"\",          \"explicit list of strings\");\n    readConfig(config, \"variableLoopString\", nameString, Config::OPTIONAL, \"loopString\", \"name of the variable to be replaced\");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL, \"\",           \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL, \"\",           \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopStringList::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameString.empty()) varList.setVariable(nameString, strings.at(index()));\n  if(!nameIndex.empty())  varList.setVariable(nameIndex,  index());\n  if(!nameCount.empty())  varList.setVariable(nameCount,  count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopStringTable.h",
    "content": "/***********************************************/\n/**\n* @file loopStringTable.h\n*\n* @brief Loop over rows of a table containing strings.\n*\n* @author Sebastian Strasser\n* @date 2017-02-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPSTRINGTABLE__\n#define __GROOPS_LOOPSTRINGTABLE__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopStringTable = R\"(\n\\subsection{StringTable}\\label{loopType:stringTable}\nLoop over \\config{row}s of a table containing strings.\nEach row must have the same number of cells.\nFor each column an extra \\config{variableLoopString} can be defined.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over rows of a table containing strings.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopStringTable : public Loop\n{\npublic:\n  class CellVector\n  {\n  public:\n    std::vector<std::string> cells;\n  };\n\nprivate:\n  std::vector<CellVector>  rows;\n  std::vector<std::string> nameString;\n  std::string              nameIndex, nameCount;\n\npublic:\n  LoopStringTable(Config &config);\n\n  UInt count() const override {return rows.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, LoopStringTable::CellVector &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"cell\", var.cells, Config::MUSTSET, \"\", \"list of columns in a row\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ninline LoopStringTable::LoopStringTable(Config &config)\n{\n  try\n  {\n    Bool transpose;\n\n    readConfig(config, \"row\",                rows,       Config::OPTIONAL, \"\",           \"rows of a table\");\n    readConfig(config, \"transpose\",          transpose,  Config::DEFAULT,  \"0\",          \"loop over columns instead of rows\");\n    readConfig(config, \"variableLoopString\", nameString, Config::MUSTSET,  \"loopString\", \"1. variable name for the 1. column, next variable name for the 2. column, ... \");\n    readConfig(config, \"variableLoopIndex\",  nameIndex,  Config::OPTIONAL, \"\",           \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",  nameCount,  Config::OPTIONAL, \"\",           \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    // transpose table\n    if(rows.size() && transpose)\n    {\n      const UInt cols = std::max_element(rows.begin(), rows.end(), [](auto &s1, auto &s2){return s1.cells.size() < s2.cells.size();})->cells.size();\n      std::vector<CellVector> tmp(cols);\n      for(UInt i=0; i<rows.size(); i++)\n        for(UInt k=0; k<rows.at(i).cells.size(); k++)\n          tmp.at(k).cells.push_back(rows.at(i).cells.at(k));\n      rows = std::move(tmp);\n    }\n\n    if(rows.size() && (nameString.size() > std::min_element(rows.begin(), rows.end(), [](auto &s1, auto &s2){return s1.cells.size() < s2.cells.size();})->cells.size()))\n      throw(Exception(\"More variables than columns in the table\"));\n   }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopStringTable::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  for(UInt i=0; i<nameString.size(); i++)\n    if(!nameString.at(i).empty())\n      varList.setVariable(nameString.at(i), rows.at(index()).cells.at(i));\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopTimeIntervals.h",
    "content": "/***********************************************/\n/**\n* @file loopTimeIntervals.h\n*\n* @brief Loop over time intervals.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPTIMEINTERVALS__\n#define __GROOPS_LOOPTIMEINTERVALS__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopTimeIntervals = R\"(\n\\subsection{TimeIntervals}\\label{loopType:timeIntervals}\nLoop over the intervals between points in time.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over time intervals.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopTimeIntervals : public Loop\n{\n  std::string       nameTimeStart, nameTimeEnd, nameIndex, nameCount;\n  std::vector<Time> times;\n\npublic:\n  LoopTimeIntervals(Config &config);\n\n  UInt count() const override {return times.size()-1;}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopTimeIntervals::LoopTimeIntervals(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timesIntervalPtr;\n\n    readConfig(config, \"timeIntervals\",         timesIntervalPtr, Config::MUSTSET,   \"\",            \"loop is called for every interval\");\n    readConfig(config, \"variableLoopTimeStart\", nameTimeStart,    Config::OPTIONAL,  \"loopTime\",    \"variable with starting time of each interval\");\n    readConfig(config, \"variableLoopTimeEnd\",   nameTimeEnd,      Config::OPTIONAL,  \"loopTimeEnd\", \"variable with ending time of each interval\");\n    readConfig(config, \"variableLoopIndex\",     nameIndex,        Config::OPTIONAL,  \"\",            \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",     nameCount,        Config::OPTIONAL,  \"\",            \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    times = timesIntervalPtr->times();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopTimeIntervals::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameTimeStart.empty()) varList.setVariable(nameTimeStart, times.at(index()).mjd());\n  if(!nameTimeEnd.empty())   varList.setVariable(nameTimeEnd,   times.at(index()+1).mjd());\n  if(!nameIndex.empty())     varList.setVariable(nameIndex,     index());\n  if(!nameCount.empty())     varList.setVariable(nameCount,     count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/loop/loopTimeSeries.h",
    "content": "/***********************************************/\n/**\n* @file loopTimeSeries.h\n*\n* @brief Loop over points in time.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2017-01-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOOPTIMESERIES__\n#define __GROOPS_LOOPTIMESERIES__\n\n// Latex documentation\n#ifdef DOCSTRING_Loop\nstatic const char *docstringLoopTimeSeries = R\"(\n\\subsection{TimeSeries}\\label{loopType:timeSeries}\nLoop over points in time.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/loop/loop.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loop over points in time.\n* @ingroup loopGroup\n* @see Loop */\nclass LoopTimeSeries : public Loop\n{\n  std::string       nameTime, nameIndex, nameCount;\n  std::vector<Time> times;\n\npublic:\n  LoopTimeSeries(Config &config);\n\n  UInt count() const override {return times.size();}\n  Bool iteration(VariableList &varList) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline LoopTimeSeries::LoopTimeSeries(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timeSeriesPtr;\n\n    readConfig(config, \"timeSeries\",        timeSeriesPtr, Config::MUSTSET,   \"\",         \"loop is called for every point in time\");\n    readConfig(config, \"variableLoopTime\",  nameTime,      Config::OPTIONAL,  \"loopTime\", \"variable with time of each loop\");\n    readConfig(config, \"variableLoopIndex\", nameIndex,     Config::OPTIONAL,  \"\",         \"variable with index of current iteration (starts with zero)\");\n    readConfig(config, \"variableLoopCount\", nameCount,     Config::OPTIONAL,  \"\",         \"variable with total number of iterations\");\n    readConfigCondition(config);\n    if(isCreateSchema(config)) return;\n\n    times = timeSeriesPtr->times();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool LoopTimeSeries::iteration(VariableList &varList)\n{\n  if(index() >= count())\n    return FALSE;\n\n  if(!nameTime.empty())  varList.setVariable(nameTime,  times.at(index()).mjd());\n  if(!nameIndex.empty()) varList.setVariable(nameIndex, index());\n  if(!nameCount.empty()) varList.setVariable(nameCount, count());\n\n  return checkCondition(varList);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/magnetosphere/magnetosphere.cpp",
    "content": "/***********************************************/\n/**\n* @file magnetosphere.cpp\n*\n* @brief Magentic field of the Earth.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-08\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Magnetosphere\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/configRegister.h\"\n#include \"classes/magnetosphere/magnetosphereIgrf.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Magnetosphere, \"magnetosphereType\",\n                      MagnetosphereIgrf)\nGROOPS_READCONFIG_CLASS(Magnetosphere, \"magnetosphereType\")\n\n/***********************************************/\n\nMagnetospherePtr Magnetosphere::create(Config &config, const std::string &name)\n{\n  try\n  {\n    MagnetospherePtr ptr;\n    std::string choice;\n\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"magentic field of the Earth\");\n    if(readConfigChoiceElement(config, \"igrf\", choice, \"International Geomagnetic Reference Field\"))\n      ptr = std::make_shared<MagnetosphereIgrf>(config);\n    endChoice(config);\n\n    return ptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d Magnetosphere::rotaryCelestial2SolarGeomagneticFrame(const Time &time) const\n{\n  try\n  {\n    const Vector3d z = Planets::celestial2TerrestrialFrame(time).inverseRotate(geomagneticNorthPole(time));\n    const Vector3d y = normalize(crossProduct(z, Planets::positionSun(time)));\n    const Vector3d x = crossProduct(y, z);\n    return inverse(Rotary3d(x,y));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/magnetosphere/magnetosphere.h",
    "content": "/***********************************************/\n/**\n* @file magnetosphere.h\n*\n* @brief Magentic field of the Earth.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MAGNETOSPHERE__\n#define __GROOPS_MAGNETOSPHERE__\n\n// Latex documentation\n#ifdef DOCSTRING_Magnetosphere\nstatic const char *docstringMagnetosphere = R\"(\n\\section{Magnetosphere}\\label{magnetosphereType}\nThis class provides functions of the magnetic field of the Earth.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup magnetosphereGroup Magnetosphere\n* @brief Magentic field of the Earth.\n* @ingroup classesGroup\n* The interface is given by @ref Magnetosphere. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Magnetosphere;\ntypedef std::shared_ptr<Magnetosphere> MagnetospherePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Magentic field of the Earth.\n* An Instance of this class can be created by @ref readConfig. */\nclass Magnetosphere\n{\npublic:\n  /// Destructor.\n  virtual ~Magnetosphere() {}\n\n  /** @brief Magnetic field of the Earth.\n  * @param time GPS time\n  * @param position in TRF [m]\n  * @return Magentic vector in terrestrial reference system (TRF) [Tesla = kg/A/s^2]. */\n  virtual Vector3d magenticFieldVector(const Time &time, const Vector3d &position) const = 0;\n\n  /** @brief Geomagnetic north pole in terrestrial frame (TRF).\n  * Unit vector. */\n  virtual Vector3d geomagneticNorthPole(const Time &time) const = 0;\n\n  /** @brief Rotation from celestial frame (CRF) to solar geomagnetic frame (SGF). */\n  virtual Rotary3d rotaryCelestial2SolarGeomagneticFrame(const Time &time) const;\n\n  /** @brief creates an derived instance of this class. */\n  static MagnetospherePtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Magnetosphere.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a magnetosphere is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] magnetosphere Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Magnetosphere */\ntemplate<> Bool readConfig(Config &config, const std::string &name, MagnetospherePtr &magnetosphere, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/magnetosphere/magnetosphereIgrf.h",
    "content": "/***********************************************/\n/**\n* @file magnetosphereIGRF.h\n*\n* @brief Magentic field of the Earth.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MAGNETOSPHEREIGRF__\n#define __GROOPS_MAGNETOSPHEREIGRF__\n\n// Latex documentation\n#ifdef DOCSTRING_Magnetosphere\nstatic const char *docstringMagnetosphereIgrf = R\"(\n\\subsection{IGRF}\nInternational Geomagnetic Reference Field.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"external/igrf/igrf.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Magentic field of the Earth.\n* @ingroup magnetosphereGroup\n* @see Magnetosphere */\nclass MagnetosphereIgrf : public Magnetosphere\n{\n  Polynomial polynomial;\n  Matrix     lonlat;\n\npublic:\n  MagnetosphereIgrf(Config &config);\n\n  Vector3d geomagneticNorthPole(const Time &time) const override;\n  Vector3d magenticFieldVector(const Time &time, const Vector3d &position) const override;\n};\n\n/***********************************************/\n\nMagnetosphereIgrf::MagnetosphereIgrf(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    readConfig(config, \"inputfileMagneticNorthPole\", fileName, Config::OPTIONAL, \"{groopsDataDir}/magnetosphere/magneticNorthPole.txt\", \"time series of north pole\");\n    if(isCreateSchema(config)) return;\n\n    if(!fileName.empty())\n    {\n      MiscValuesArc arc = InstrumentFile::read(fileName);\n      lonlat = arc.matrix().column(1, 2);\n      polynomial.init(arc.times(), 1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MagnetosphereIgrf::geomagneticNorthPole(const Time &time) const\n{\n  try\n  {\n    if(!lonlat.size())\n      throw(Exception(\"magentic north pole data not provided\"));\n    const Matrix ll = polynomial.interpolate({time}, lonlat);\n    return polar(Angle(ll(0,0)*DEG2RAD), Angle(ll(0,1)*DEG2RAD), 1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MagnetosphereIgrf::magenticFieldVector(const Time &time, const Vector3d &position) const\n{\n  try\n  {\n#ifdef GROOPS_DISABLE_IGRF\n    throw(Exception(\"Compiled without International Geomagnetic Reference Field (IGRF) sources\"));\n#else\n    Double n,e,u,f;\n    igrfSynthesis(0/*main-field*/, time.decimalYear(), 2/*geocentric*/, position.r()/1000, position.theta()*RAD2DEG, position.lambda()*RAD2DEG, n,e,u,f);\n    return 1e-9*localNorthEastUp(position).transform(Vector3d(n,e,u));  // nT -> T (Tesla)\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGenerator.cpp",
    "content": "/***********************************************/\n/**\n* @file matrixGenerator.cpp\n*\n* @brief Matrix calculation.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_MatrixGenerator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/matrixGenerator/matrixGeneratorFile.h\"\n#include \"classes/matrixGenerator/matrixGeneratorNormalsFile.h\"\n#include \"classes/matrixGenerator/matrixGeneratorExpression.h\"\n#include \"classes/matrixGenerator/matrixGeneratorElementManipulation.h\"\n#include \"classes/matrixGenerator/matrixGeneratorElementWiseOperation.h\"\n#include \"classes/matrixGenerator/matrixGeneratorAppend.h\"\n#include \"classes/matrixGenerator/matrixGeneratorShift.h\"\n#include \"classes/matrixGenerator/matrixGeneratorSlice.h\"\n#include \"classes/matrixGenerator/matrixGeneratorReshape.h\"\n#include \"classes/matrixGenerator/matrixGeneratorReorder.h\"\n#include \"classes/matrixGenerator/matrixGeneratorSort.h\"\n#include \"classes/matrixGenerator/matrixGeneratorTranspose.h\"\n#include \"classes/matrixGenerator/matrixGeneratorMultiplication.h\"\n#include \"classes/matrixGenerator/matrixGeneratorInverse.h\"\n#include \"classes/matrixGenerator/matrixGeneratorCholesky.h\"\n#include \"classes/matrixGenerator/matrixGeneratorRankKUpdate.h\"\n#include \"classes/matrixGenerator/matrixGeneratorEigenValues.h\"\n#include \"classes/matrixGenerator/matrixGeneratorDiagonal.h\"\n#include \"classes/matrixGenerator/matrixGeneratorFromDiagonal.h\"\n#include \"classes/matrixGenerator/matrixGeneratorSetType.h\"\n#include \"classes/matrixGenerator/matrixGenerator.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(MatrixGenerator, \"matrixGeneratorType\",\n                      MatrixGeneratorFile,\n                      MatrixGeneratorNormalsFile,\n                      MatrixGeneratorExpression,\n                      MatrixGeneratorElementManipulation,\n                      MatrixGeneratorElementWiseOperation,\n                      MatrixGeneratorAppend,\n                      MatrixGeneratorShift,\n                      MatrixGeneratorSlice,\n                      MatrixGeneratorReshape,\n                      MatrixGeneratorReorder,\n                      MatrixGeneratorSort,\n                      MatrixGeneratorTranspose,\n                      MatrixGeneratorMultiplication,\n                      MatrixGeneratorInverse,\n                      MatrixGeneratorCholesky,\n                      MatrixGeneratorRankKUpdate,\n                      MatrixGeneratorEigenValues,\n                      MatrixGeneratorDiagonal,\n                      MatrixGeneratorFromDiagonal,\n                      MatrixGeneratorSetType)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(MatrixGenerator, \"matrixGeneratorType\")\n\n/***********************************************/\n\nMatrixGenerator::MatrixGenerator(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"matrix calculation\"))\n    {\n      if(readConfigChoiceElement(config, \"file\",                type, \"from file\"))\n        matrix.push_back(new MatrixGeneratorFile(config));\n      if(readConfigChoiceElement(config, \"normalsFile\",         type, \"from normal equation file\"))\n        matrix.push_back(new MatrixGeneratorNormalsFile(config));\n      if(readConfigChoiceElement(config, \"expression\",          type, \"matrix filled by an expression\"))\n        matrix.push_back(new MatrixGeneratorExpression(config));\n      if(readConfigChoiceElement(config, \"elementManipulation\", type, \"elements of a matrix are manipulated by an expression\"))\n        matrix.push_back(new MatrixGeneratorElementManipulation(config));\n      if(readConfigChoiceElement(config, \"elementWiseOperation\", type, \"element wise operation of two matrices\"))\n        matrix.push_back(new MatrixGeneratorElementWiseOperation(config));\n      if(readConfigChoiceElement(config, \"append\",              type, \"append matrix to right or bottom\"))\n        matrix.push_back(new MatrixGeneratorAppend(config));\n      if(readConfigChoiceElement(config, \"shift\",               type, \"shift start row and/or start column\"))\n        matrix.push_back(new MatrixGeneratorShift(config));\n      if(readConfigChoiceElement(config, \"slice\",               type, \"slice of a matrix\"))\n        matrix.push_back(new MatrixGeneratorSlice(config));\n      if(readConfigChoiceElement(config, \"reshape\",             type, \"matrix reshaped columnwise to new row and columns\"))\n        matrix.push_back(new MatrixGeneratorReshape(config));\n      if(readConfigChoiceElement(config, \"reorder\",             type, \"reorder matrix with index vectors\"))\n        matrix.push_back(new MatrixGeneratorReorder(config));\n      if(readConfigChoiceElement(config, \"sort\",                type, \"sort matrix by column\"))\n        matrix.push_back(new MatrixGeneratorSort(config));\n      if(readConfigChoiceElement(config, \"transpose\",           type, \"transposed of a matrix\"))\n        matrix.push_back(new MatrixGeneratorTranspose(config));\n      if(readConfigChoiceElement(config, \"multiplication\",      type, \"multiplication of matrices\"))\n        matrix.push_back(new MatrixGeneratorMultiplication(config));\n      if(readConfigChoiceElement(config, \"inverse\",             type, \"inverse/pseudoinverse\"))\n        matrix.push_back(new MatrixGeneratorInverse(config));\n      if(readConfigChoiceElement(config, \"cholesky\",            type, \"cholesky decomposition\"))\n        matrix.push_back(new MatrixGeneratorCholesky(config));\n      if(readConfigChoiceElement(config, \"rankKUpdate\",         type, \"rank k update (A^T*A)\"))\n        matrix.push_back(new MatrixGeneratorRankKUpdate(config));\n      if(readConfigChoiceElement(config, \"eigenValues\",         type, \"eigen values\"))\n        matrix.push_back(new MatrixGeneratorEigenValues(config));\n      if(readConfigChoiceElement(config, \"diagonal\",            type, \"diagonal of matrix\"))\n        matrix.push_back(new MatrixGeneratorDiagonal(config));\n      if(readConfigChoiceElement(config, \"fromDiagonal\",        type, \"create matrix from diagonal vector\"))\n        matrix.push_back(new MatrixGeneratorFromDiagonal(config));\n      if(readConfigChoiceElement(config, \"setType\",             type, \"set type of a matrix\"))\n        matrix.push_back(new MatrixGeneratorSetType(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixGenerator::~MatrixGenerator()\n{\n  for(UInt i=0; i<matrix.size(); i++)\n    delete matrix.at(i);\n}\n\n/***********************************************/\n\nMatrix MatrixGenerator::compute()\n{\n  try\n  {\n    std::vector<Matrix> A(matrix.size());\n    std::vector<UInt>   startRow(matrix.size(), 0);\n    std::vector<UInt>   startCol(matrix.size(), 0);\n    UInt                rows = 0;\n    UInt                cols = 0;\n    for(UInt i=0; i<matrix.size(); i++)\n    {\n      matrix.at(i)->compute(A.at(i), rows, cols, startRow.at(i), startCol.at(i));\n      rows = std::max(rows, A.at(i).rows()    + startRow.at(i));\n      cols = std::max(cols, A.at(i).columns() + startCol.at(i));\n    }\n\n    // quick return?\n    if((A.size() == 1) && (startRow.at(0) == 0) && (startCol.at(0) == 0))\n      return A.at(0);\n\n    // Accumulate all matrices\n    Matrix B(rows, cols);\n    Bool isTypeDefined = FALSE;\n    for(UInt i=0; i<A.size(); i++)\n      if(A.at(i).size())\n      {\n        // check type\n        if(((A.at(i).getType() == Matrix::SYMMETRIC) || (A.at(i).getType() == Matrix::TRIANGULAR)) && (startRow.at(i) == startCol.at(i)))\n        {\n          if(!isTypeDefined)\n            B.setType(A.at(i).getType(), A.at(i).isUpper() ? Matrix::UPPER : Matrix::LOWER);\n          else if((A.at(i).getType() != B.getType()) || (A.at(i).isUpper() != B.isUpper()))\n            A.at(i).setType(Matrix::GENERAL);\n        }\n        else if(A.at(i).getType() == Matrix::GENERAL)\n          A.at(i).setType(Matrix::GENERAL);\n        isTypeDefined = TRUE;\n\n        // add\n        axpy(1., A.at(i), B.slice(startRow.at(i), startCol.at(i), A.at(i).rows(), A.at(i).columns()));\n      }\n\n    return B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGenerator.h",
    "content": "/***********************************************/\n/**\n* @file matrixGenerator.h\n*\n* @brief Matrix calculation.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATOR__\n#define __GROOPS_MATRIXGENERATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGenerator = R\"(\n\\section{MatrixGenerator}\\label{matrixGeneratorType}\nThis class provides a matrix used e.g. by \\program{MatrixCalculate}.\nIf multiple matrices are given the resulting matrix is the sum all\nand the size is exandeded to fit all matrices. Before the computation of each submatrix\nthe variables \\verb|rowsBefore| and \\verb|columnsBefore| with current size of the overall matrix\nare set. As all matrices can be manipulated before, complex matrix operations are possible.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup matrixGeneratorGroup MatrixGenerator\n* @brief Matrix calculation.\n* @ingroup classesGroup\n* The interface is given by @ref MatrixGenerator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass MatrixGenerator;\nclass MatrixGeneratorBase;\ntypedef std::shared_ptr<MatrixGenerator> MatrixGeneratorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Matrix calculation.\n* This class provides a matrix.\n* An Instance of this class can be created by @ref readConfig. */\nclass MatrixGenerator\n{\n  std::vector<MatrixGeneratorBase*> matrix;\n\npublic:\n  /// Constructor.\n  MatrixGenerator(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~MatrixGenerator();\n\n  /// provides a matrix.\n  Matrix compute();\n\n  /** @brief creates an derived instance of this class. */\n  static MatrixGeneratorPtr create(Config &config, const std::string &name) {return MatrixGeneratorPtr(new MatrixGenerator(config, name));}\n};\n\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class MatrixGenerator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a matrixGenerator with zero-size matrix is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] matrixGenerator Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates MatrixGenerator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, MatrixGeneratorPtr &matrixGenerator, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass MatrixGeneratorBase\n{\npublic:\n  virtual ~MatrixGeneratorBase() {}\n  virtual void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol) = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorAppend.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorAppend.h\n*\n* @brief Append matrix to right or bottom.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXCGENERATORAPPEND__\n#define __GROOPS_MATRIXCGENERATORAPPEND__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorAppend = R\"(\n\\subsection{Append}\nAppend matrix to the right (first row) or bottom (first column).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Append of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorAppend : public MatrixGeneratorBase\n{\n  Bool               right, bottom;\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorAppend(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorAppend::MatrixGeneratorAppend(Config &config)\n{\n  try\n  {\n    std::string choice;\n    readConfig(config, \"matrix\", matrix, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"side\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"right\",    choice, \"\")) {right = TRUE;  bottom = FALSE;}\n      if(readConfigChoiceElement(config, \"bottom\",   choice, \"\")) {right = FALSE; bottom = TRUE;}\n      if(readConfigChoiceElement(config, \"diagonal\", choice, \"\")) {right = TRUE;  bottom = TRUE;}\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorAppend::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol)\n{\n  try\n  {\n    A = matrix->compute();\n    if(right)\n      startCol = columnsBefore;\n    if(bottom)\n      startRow = rowsBefore;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorCholesky.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorCholesky.h\n*\n* @brief Cholesky decomposition of a symmetric matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORCHOLESKY__\n#define __GROOPS_MATRIXGENERATORCHOLESKY__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorCholesky = R\"(\n\\subsection{Cholesky}\nUpper triangular natrix of the cholesky decomposition of a symmetric matrix $\\M A=\\M W^T\\M W$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Cholesky decomposition of a symmetric matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorCholesky : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorCholesky(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorCholesky::MatrixGeneratorCholesky(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\", matrix, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorCholesky::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n    cholesky(A);\n    zeroUnusedTriangle(A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorDiagonal.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorDiagonal.h\n*\n* @brief Exctract the diagonal of a matrix.\n*\n* @author Andreas Kvas\n* @date 2018-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORDIAGONAL__\n#define __GROOPS_MATRIXGENERATORDIAGONAL__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorDiagonal = R\"(\n\\subsection{Diagonal}\nExtract the diagonal or subdiagnoal ($n\\times 1$ vector) of a matrix.\nThe zero \\config{diagonal} means the main diagonal, a positive value the superdiagonal,\nand a negative the subdiagonal.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Exctract the diagonal of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorDiagonal : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr matrix;\n  Int index;\n\npublic:\n  MatrixGeneratorDiagonal(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorDiagonal::MatrixGeneratorDiagonal(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",   matrix, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"diagonal\", index,  Config::DEFAULT,  \"0\", \"zero: main diagonal, positive: superdiagonal, negative: subdiagonal\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorDiagonal::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n\n    Vector d(std::min(A.columns(), A.rows()) - std::abs(index));\n    for(UInt k = 0; k<d.rows(); k++)\n      d(k) = A(k-std::min(0, index), k+std::max(0, index));\n\n    A = d;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorEigenValues.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorEigenValues.h\n*\n* @brief EigenValues of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATOREIGENVALUES__\n#define __GROOPS_MATRIXGENERATOREIGENVALUES__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorEigenValues = R\"(\n\\subsection{EigenValues}\nComputes the eigenvalues of a square matrix and gives a vector of eigenvalues for symmetric matrices\nor a matrix with 2 columns with real and imaginary parts in general case.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief EigenValues of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorEigenValues : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr matrix;\n  Bool eigenVectors;\n\npublic:\n  MatrixGeneratorEigenValues(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorEigenValues::MatrixGeneratorEigenValues(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",       matrix,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"eigenVectors\", eigenVectors, Config::DEFAULT,  \"0\", \"return eigen vectors instead of eigen values\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorEigenValues::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute().trans();\n    Matrix eigen, VL, VR;\n    if(A.getType() == Matrix::SYMMETRIC)\n    {\n      eigen = eigenValueDecomposition(A, eigenVectors);\n\n      // reverse order\n      if(eigenVectors)\n        for(UInt k=0; k<A.columns()/2; k++)\n        {\n          Vector tmp(A.column(k));\n          copy(A.column((A.columns()-1-k)), A.column(k));\n          copy(tmp, A.column((A.columns()-1-k)));\n        }\n      else\n      {\n        A = Matrix(eigen.rows(), eigen.columns());\n        for(UInt i=0; i<eigen.rows(); i++)\n          copy(eigen.row(i), A.row((A.rows()-1-i)));\n      }\n    }\n    else\n    {\n      eigen = eigenValueDecomposition(A, VL, VR, eigenVectors);\n      if(!eigenVectors)\n        A = eigen;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorElementManipulation.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorElementManipulation.h\n*\n* @brief The elements of a matrix are replaced an expression\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORELEMENTMANIPULATION__\n#define __GROOPS_MATRIXGENERATORELEMENTMANIPULATION__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorElementManipulation = R\"(\n\\subsection{Element manipulation}\nThe elements of a matrix are replaced an expression.\nFor each element of the matrix the variables \\verb|data|, \\verb|row|, \\verb|column|\nare set and the expression \\config{element} is evaluated and replaces the element.\nAdditionally the standard data variables are available (assigned each row),\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parser/dataVariables.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief The elements of a matrix are replaced an expression\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorElementManipulation : public MatrixGeneratorBase\n{\n  ExpressionVariablePtr expression;\n  MatrixGeneratorPtr    matrix;\n\npublic:\n  MatrixGeneratorElementManipulation(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorElementManipulation::MatrixGeneratorElementManipulation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",  matrix,     Config::MUSTSET, \"\",     \"\");\n    readConfig(config, \"element\", expression, Config::MUSTSET, \"data\", \"for each element of matrix (variables: data, row, column, rows, columns, rowsBefore, columnsBefore)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorElementManipulation::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n\n    VariableList varList;\n    varList.setVariable(\"rowsBefore\",    static_cast<Double>(rowsBefore));\n    varList.setVariable(\"columnsBefore\", static_cast<Double>(columnsBefore));\n    varList.setVariable(\"rows\",          static_cast<Double>(A.rows()));\n    varList.setVariable(\"columns\",       static_cast<Double>(A.columns()));\n\n    addDataVariables(A, varList);\n    varList.undefineVariable(\"row\");\n    varList.undefineVariable(\"column\");\n    varList.undefineVariable(\"data\");\n    expression->simplify(varList);\n\n    for(UInt z=0; z<A.rows(); z++)\n    {\n      evaluateDataVariables(A, z, varList);\n      for(UInt s=0; s<A.columns(); s++)\n      {\n        varList.setVariable(\"row\",    static_cast<Double>(z));\n        varList.setVariable(\"column\", static_cast<Double>(s));\n        varList.setVariable(\"data\",   A(z,s));\n        A(z,s) = expression->evaluate(varList);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorElementWiseOperation.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorElementWiseOperation.h\n*\n* @brief Elementwise operation between two matrices\n*\n* @author Andreas Kvas\n* @date 2018-08-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORELEMENTWISEOPERATION__\n#define __GROOPS_MATRIXGENERATORELEMENTWISEOPERATION__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorElementWiseOperation = R\"(\n\\subsection{ElementWiseOperation}\nGiven two matrices $\\mathbf{A}$ and $\\mathbf{B}$ this class computes $c_{ij} = f(a_{ij}, b_{ij})$,\nwhere $f$ is an expression (for example \\verb|data0*data1|).\nFor each element of the matrix the variables \\verb|data0|, \\verb|data1|, \\verb|row|, \\verb|column|\nare set and the expression \\config{element} is evaluated.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parser/dataVariables.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Multiplication of matrices.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorElementWiseOperation : public MatrixGeneratorBase\n{\n  ExpressionVariablePtr expression;\n  MatrixGeneratorPtr matrix1, matrix2;\n\npublic:\n  MatrixGeneratorElementWiseOperation(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorElementWiseOperation::MatrixGeneratorElementWiseOperation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix1\",    matrix1,    Config::MUSTSET, \"\",    \"\");\n    readConfig(config, \"matrix2\",    matrix2,    Config::MUSTSET, \"\",    \"\");\n    readConfig(config, \"expression\", expression, Config::DEFAULT, \"data0*data1\", \"for each element of matrix (variables: data0, data1, row, column, rows, columns, rowsBefore, columnsBefore)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorElementWiseOperation::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    Matrix X = matrix1->compute();\n    Matrix Y = matrix2->compute();\n    if( (X.rows() != Y.rows()) || (X.columns() != Y.columns()) )\n      throw(Exception(\"Matrix dimensions do not agree. (\"+X.rows()%\"%i x \"s+X.columns()%\"%i) vs. (\"s+Y.rows()%\"%i x \"s+Y.columns()%\"%i).\"s));\n\n    VariableList varList;\n    varList.setVariable(\"rowsBefore\",    static_cast<Double>(rowsBefore));\n    varList.setVariable(\"columnsBefore\", static_cast<Double>(columnsBefore));\n    varList.setVariable(\"rows\",          static_cast<Double>(X.rows()));\n    varList.setVariable(\"columns\",       static_cast<Double>(X.columns()));\n    varList.undefineVariable(\"row\");\n    varList.undefineVariable(\"column\");\n    varList.undefineVariable(\"data0\");\n    varList.undefineVariable(\"data1\");\n    expression->simplify(varList);\n\n    A = Matrix(X.rows(), X.columns());\n    for(UInt z=0; z<A.rows(); z++)\n      for(UInt s=0; s<A.columns(); s++)\n      {\n        varList.setVariable(\"row\",    static_cast<Double>(z));\n        varList.setVariable(\"column\", static_cast<Double>(s));\n        varList.setVariable(\"data0\",  X(z,s));\n        varList.setVariable(\"data1\",  Y(z,s));\n        A(z,s) = expression->evaluate(varList);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorExpression.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorExpression.h\n*\n* @brief Matrix filled by an expression.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATOREXPRESSION__\n#define __GROOPS_MATRIXGENERATOREXPRESSION__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorExpression = R\"(\n\\subsection{Expression}\nMatrix filled by an expression. For each element of the new matrix the variables\n\\verb|row| and \\verb|column| are set and the expression \\config{element} is evaluated.\n\nExcample: The \\config{element}=\\verb|if(row==column,1,0)| generates an identity matrix.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Matrix filled by an expression.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorExpression : public MatrixGeneratorBase\n{\n  ExpressionVariablePtr exprRows, exprCols;\n  ExpressionVariablePtr expression;\n\npublic:\n  MatrixGeneratorExpression(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorExpression::MatrixGeneratorExpression(Config &config)\n{\n  try\n  {\n    readConfig(config, \"rows\",    exprRows,   Config::MUSTSET,  \"\", \"(variables: rowsBefore, columnsBefore)\");\n    readConfig(config, \"columns\", exprCols,   Config::MUSTSET,  \"\", \"(variables: rowsBefore, columnsBefore)\");\n    readConfig(config, \"element\", expression, Config::MUSTSET,  \"if(row==column,1,0)\",  \"for each element of matrix (variables: row, column, rows, columns, rowsBefore, columnsBefore)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorExpression::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    VariableList varList;\n    varList.setVariable(\"rowsBefore\",    static_cast<Double>(rowsBefore));\n    varList.setVariable(\"columnsBefore\", static_cast<Double>(columnsBefore));\n\n    A = Matrix(static_cast<UInt>(exprRows->evaluate(varList)), static_cast<UInt>(exprCols->evaluate(varList)));\n\n    varList.setVariable(\"rows\",          static_cast<Double>(A.rows()));\n    varList.setVariable(\"columns\",       static_cast<Double>(A.columns()));\n    varList.undefineVariable(\"row\");\n    varList.undefineVariable(\"column\");\n    expression->simplify(varList);\n\n    for(UInt z=0; z<A.rows(); z++)\n      for(UInt s=0; s<A.columns(); s++)\n      {\n        varList.setVariable(\"row\",    static_cast<Double>(z));\n        varList.setVariable(\"column\", static_cast<Double>(s));\n        A(z,s) = expression->evaluate(varList);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorFile.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorFile.h\n*\n* @brief Matrix from file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORFILE__\n#define __GROOPS_MATRIXGENERATORFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorFile = R\"(\n\\subsection{File}\nMatrix from \\file{file}{matrix}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Matrix from file.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorFile : public MatrixGeneratorBase\n{\n  FileName fileName;\n  Double   factor;\n\npublic:\n  MatrixGeneratorFile(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorFile::MatrixGeneratorFile(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileMatrix\", fileName, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"factor\",          factor,   Config::DEFAULT,  \"1.0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorFile::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    readFileMatrix(fileName, A);\n    if(A.getType() == Matrix::SYMMETRIC)\n      fillSymmetric(A);\n    A *= factor;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorFromDiagonal.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorFromDiagonal.h\n*\n* @brief Generate a matrix from a diagonal vector.\n*\n* @author Andreas Kvas\n* @date 2018-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORFROMDIAGONAL__\n#define __GROOPS_MATRIXGENERATORFROMDIAGONAL__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorFromDiagonal = R\"(\n\\subsection{FromDiagonal}\nGenerate a matrix from a diagonal vector.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief  Generate a matrix from a diagonal vector.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorFromDiagonal : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr matrix;\n  Int index;\n\npublic:\n  MatrixGeneratorFromDiagonal(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorFromDiagonal::MatrixGeneratorFromDiagonal(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",   matrix, Config::MUSTSET, \"\",  \"(nx1) or (1xn) diagonal vector\");\n    readConfig(config, \"diagonal\", index,  Config::DEFAULT, \"0\", \"zero: main diagonal, positive: superdiagonal, negative: subdiagonal\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorFromDiagonal::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n    if(std::min(A.rows(), A.columns()) != 1)\n      throw(Exception(\"Input must be a (nx1) or (1xn) vector.\"));\n\n    Vector d(flatten(A));\n    const UInt outputSize = d.rows() + std::abs(index);\n\n    A = Matrix(outputSize, outputSize);\n    for(UInt k = 0; k<d.rows(); k++)\n      A(k-std::min(0, index), k+std::max(0, index)) = d(k);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorInverse.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorInverse.h\n*\n* @brief Inverse of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORINVERSE__\n#define __GROOPS_MATRIXGENERATORINVERSE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorInverse = R\"(\n\\subsection{Inverse}\nInverse of a matrix $\\M A^{-1}$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Inverse of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorInverse : public MatrixGeneratorBase\n{\n  Bool               pseudo;\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorInverse(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorInverse::MatrixGeneratorInverse(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",        matrix, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"pseudoInverse\", pseudo, Config::DEFAULT, \"0\", \"compute pseudo inverse instead of regular one\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorInverse::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n    if(pseudo)\n      A = pseudoInverse(A);\n    else\n      inverse(A);\n    if(A.getType() == Matrix::SYMMETRIC)\n      fillSymmetric(A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorMultiplication.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorMultiplication.h\n*\n* @brief Multiplication of matrices.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORMULTIPLICATION__\n#define __GROOPS_MATRIXGENERATORMULTIPLICATION__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorMultiplication = R\"(\n\\subsection{Multiplication}\nMultiplication of matrices.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Multiplication of matrices.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorMultiplication : public MatrixGeneratorBase\n{\n  Double factor;\n  MatrixGeneratorPtr matrix1, matrix2;\n\npublic:\n  MatrixGeneratorMultiplication(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorMultiplication::MatrixGeneratorMultiplication(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix1\", matrix1, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"matrix2\", matrix2, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"factor\",  factor,  Config::DEFAULT,  \"1.0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorMultiplication::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = factor * matrix1->compute() * matrix2->compute();\n    if(A.getType() == Matrix::SYMMETRIC)\n      fillSymmetric(A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorNormalsFile.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorNormalsFile.h\n*\n* @brief Symmetric matrix from a normal equation file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORNORMALSFILE__\n#define __GROOPS_MATRIXGENERATORNORMALSFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorNormalsFile = R\"(\n\\subsection{Normals file}\nMatrix from a \\file{normal equation file}{normalEquation}. The symmetric normal matrix,\nthe right hand side vector, the lPl vector, or the observation count $(1\\times1)$ can be selected.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Symmetric matrix from a normal equation file.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorNormalsFile : public MatrixGeneratorBase\n{\n  enum Type {MATRIX, RHS, LPL, OBSCOUNT};\n  Type type;\n  FileName fileName;\n  Double   factor;\n\npublic:\n  MatrixGeneratorNormalsFile(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorNormalsFile::MatrixGeneratorNormalsFile(Config &config)\n{\n  try\n  {\n    type = MATRIX;\n    std::string choice;\n\n    renameDeprecatedConfig(config, \"inputfileNormalequation\", \"inputfileNormalEquation\", date2time(2020, 6, 3));\n\n    readConfig(config, \"inputfileNormalEquation\", fileName, Config::MUSTSET,  \"\",    \"\");\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"normalMatrix\",     choice, \"\")) type = MATRIX;\n      if(readConfigChoiceElement(config, \"rightHandSide\",    choice, \"\")) type = RHS;\n      if(readConfigChoiceElement(config, \"lPl\",              choice, \"\")) type = LPL;\n      if(readConfigChoiceElement(config, \"observationCount\", choice, \"\")) type = OBSCOUNT;\n      endChoice(config);\n    }\n    readConfig(config, \"factor\", factor, Config::DEFAULT,  \"1.0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorNormalsFile::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    Matrix n;\n    NormalEquationInfo info;\n\n    if(type == MATRIX)\n    {\n      readFileNormalEquation(fileName, info, A, n);\n      fillSymmetric(A);\n    }\n    else if(type == RHS)\n    {\n      readFileNormalEquation(fileName, info, n);\n      A = n;\n    }\n    else if(type == LPL)\n    {\n      readFileNormalEquation(fileName, info, n);\n      A = info.lPl;\n    }\n    else if(type == OBSCOUNT)\n    {\n      readFileNormalEquation(fileName, info, n);\n      A = Matrix(1, 1, info.observationCount);\n    }\n\n    A *= factor;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorRankKUpdate.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorRankKUpdate.h\n*\n* @brief Rank k update (A^T*A).\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORRANKKUPDATE__\n#define __GROOPS_MATRIXGENERATORRANKKUPDATE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorRankKUpdate = R\"(\n\\subsection{RankKUpdate}\nSymmetric matrix from rank k update: $\\M A^T\\M A$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Rank k update (A^T*A).\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorRankKUpdate : public MatrixGeneratorBase\n{\n  Double             factor;\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorRankKUpdate(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorRankKUpdate::MatrixGeneratorRankKUpdate(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\", matrix, Config::MUSTSET, \"\",    \"\");\n    readConfig(config, \"factor\", factor, Config::DEFAULT, \"1.0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorRankKUpdate::compute(Matrix &N, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    Matrix A = matrix->compute();\n    N = Matrix(A.columns(), Matrix::SYMMETRIC);\n    rankKUpdate(factor, A, N);\n    fillSymmetric(N);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorReorder.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorReorder.h\n*\n* @brief Reorder matrix by index vectors.\n*\n* @author Andreas Kvas\n* @date 2017-11-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORREORDER__\n#define __GROOPS_MATRIXGENERATORREORDER__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorReorder = R\"(\n\\subsection{Reorder}\\label{matrixGeneratorType:reorder}\nReorder rows or columns of a matrix by an index vectors.\nThe index vector can be created with \\program{ParameterSelection2IndexVector}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Reorder matrix by index vectors.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorReorder : public MatrixGeneratorBase\n{\n  FileName fileNameRow, fileNameColumn;\n  std::vector<UInt>  rowIndex;\n  std::vector<UInt>  columnIndex;\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorReorder(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorReorder::MatrixGeneratorReorder(Config &config)\n{\n  try\n  {\n    renameDeprecatedConfig(config, \"rowIndex\",    \"inputfileIndexVectorRow\",    date2time(2018, 6, 6));\n    renameDeprecatedConfig(config, \"columnIndex\", \"inputfileIndexVectorColumn\", date2time(2018, 6, 6));\n\n    readConfig(config, \"matrix\",                     matrix,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileIndexVectorRow\",    fileNameRow,    Config::OPTIONAL, \"\", \"index in input matrix or -1 for new parameter.\");\n    readConfig(config, \"inputfileIndexVectorColumn\", fileNameColumn, Config::OPTIONAL, \"\", \"index in input matrix or -1 for new parameter.\");\n    if(isCreateSchema(config)) return;\n\n    // generate row index\n    // ------------------\n    if(!fileNameRow.empty())\n    {\n      Vector tmp;\n      readFileMatrix(fileNameRow, tmp);\n\n      rowIndex.resize(tmp.rows());\n      for(UInt k = 0; k<rowIndex.size(); k++)\n        rowIndex[k] = (tmp(k)<0.0) ? NULLINDEX : static_cast<UInt>(tmp(k));\n    }\n\n    // generate row index\n    // ------------------\n    if(!fileNameColumn.empty())\n    {\n      Vector tmp;\n      readFileMatrix(fileNameColumn, tmp);\n\n      columnIndex.resize(tmp.rows());\n      for(UInt k = 0; k<columnIndex.size(); k++)\n        columnIndex[k] = (tmp(k)<0.0) ? NULLINDEX : static_cast<UInt>(tmp(k));\n    }\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorReorder::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n    if(!fileNameRow.empty())\n      A = reorder(A, rowIndex);\n    if(!fileNameColumn.empty())\n      A = reorder(A.trans(), columnIndex).trans();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorReshape.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorReshape.h\n*\n* @brief Matrix rechaped columnwise to new row and columns.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORRESHAPE__\n#define __GROOPS_MATRIXGENERATORRESHAPE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorReshape = R\"(\n\\subsection{Reshape}\nMatrix reshaped columnwise to new row and columns.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Matrix rechaped columnwise to new row and columns.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorReshape : public MatrixGeneratorBase\n{\n  ExpressionVariablePtr exprRows, exprCols;\n  MatrixGeneratorPtr    matrix;\n\npublic:\n  MatrixGeneratorReshape(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorReshape::MatrixGeneratorReshape(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",  matrix,   Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"rows\",    exprRows, Config::MUSTSET, \"0\", \"0: auto-determine rows, (variables: rowsBefore, columnsBefore)\");\n    readConfig(config, \"columns\", exprCols, Config::MUSTSET, \"0\", \"0: auto-determine columns (variables: rowsBefore, columnsBefore)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorReshape::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n\n    VariableList varList;\n    varList.setVariable(\"rowsBefore\",    static_cast<Double>(rowsBefore));\n    varList.setVariable(\"columnsBefore\", static_cast<Double>(columnsBefore));\n    varList.setVariable(\"rows\",          static_cast<Double>(A.rows()));\n    varList.setVariable(\"columns\",       static_cast<Double>(A.columns()));\n    A = reshape(A, static_cast<UInt>(exprRows->evaluate(varList)), static_cast<UInt>(exprCols->evaluate(varList)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorSetType.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorSetType.h\n*\n* @brief Set type of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORSETTYPE__\n#define __GROOPS_MATRIXGENERATORSETTYPE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorSetType = R\"(\n\\subsection{Set type}\nSet type (matrix, matrixSymmetricUpper, matrixSymmetricLower, matrixTriangularUpper, matrixTriangularLower)\nof a matrix. If the type is not matrix, the matrix must be quadratic. Symmetric matrices are filled symmetric\nand for triangular matrix the other triangle is set to zero.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Set type of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorSetType : public MatrixGeneratorBase\n{\n  enum Type {GENERAL, SYMMETRICUPPER, SYMMETRICLOWER, TRIANGULARUPPER, TRIANGULARLOWER};\n  Type type;\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorSetType(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorSetType::MatrixGeneratorSetType(Config &config)\n{\n  try\n  {\n    type = GENERAL;\n    std::string choice;\n    readConfig(config, \"matrix\", matrix, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"matrix\",                choice, \"\")) type = GENERAL;\n      if(readConfigChoiceElement(config, \"matrixSymmetricUpper\",  choice, \"\")) type = SYMMETRICUPPER;\n      if(readConfigChoiceElement(config, \"matrixSymmetricLower\",  choice, \"\")) type = SYMMETRICLOWER;\n      if(readConfigChoiceElement(config, \"matrixTriangularUpper\", choice, \"\")) type = TRIANGULARUPPER;\n      if(readConfigChoiceElement(config, \"matrixTriangularLower\", choice, \"\")) type = TRIANGULARLOWER;\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorSetType::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n    if((type != GENERAL) && (A.rows() != A.columns()))\n      throw(Exception(\"Matrix must be quadratic\"));\n    if(type == GENERAL)         {A.setType(Matrix::GENERAL);}\n    if(type == SYMMETRICUPPER)  {A.setType(Matrix::SYMMETRIC,  Matrix::UPPER); fillSymmetric(A);}\n    if(type == SYMMETRICLOWER)  {A.setType(Matrix::SYMMETRIC,  Matrix::LOWER); fillSymmetric(A);}\n    if(type == TRIANGULARUPPER) {A.setType(Matrix::TRIANGULAR, Matrix::UPPER); zeroUnusedTriangle(A);}\n    if(type == TRIANGULARLOWER) {A.setType(Matrix::TRIANGULAR, Matrix::LOWER); zeroUnusedTriangle(A);}\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorShift.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorShift.h\n*\n* @brief Shift start row and start column of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXCGENERATORSHIFT__\n#define __GROOPS_MATRIXCGENERATORSHIFT__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorShift = R\"(\n\\subsection{Shift}\nShift start row and start column of a matrix.\nIn other words: zero lines and columns are inserted at the beginning of the matrix.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Shift of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorShift : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr    matrix;\n  ExpressionVariablePtr exprStartRow, exprStartCol;\n\npublic:\n  MatrixGeneratorShift(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorShift::MatrixGeneratorShift(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",      matrix,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startRow\",    exprStartRow, Config::DEFAULT,  \"0\", \"start row (variables: rowsBefore, columnsBefore, rows, columns)\");\n    readConfig(config, \"startColumn\", exprStartCol, Config::DEFAULT,  \"0\", \"start column (variables: rowsBefore, columnsBefore, rows, columns)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorShift::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol)\n{\n  try\n  {\n    A = matrix->compute();\n\n    VariableList varList;\n    varList.setVariable(\"rowsBefore\",    static_cast<Double>(rowsBefore));\n    varList.setVariable(\"columnsBefore\", static_cast<Double>(columnsBefore));\n    varList.setVariable(\"rows\",          static_cast<Double>(A.rows()));\n    varList.setVariable(\"columns\",       static_cast<Double>(A.columns()));\n    startRow = static_cast<UInt>(exprStartRow->evaluate(varList));\n    startCol = static_cast<UInt>(exprStartCol->evaluate(varList));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorSlice.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorSlice.h\n*\n* @brief Slice of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORSLICE__\n#define __GROOPS_MATRIXGENERATORSLICE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorSlice = R\"(\n\\subsection{Slice}\nSlice of a matrix.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Slice of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorSlice : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr    matrix;\n  ExpressionVariablePtr exprRow, exprCol;\n  ExpressionVariablePtr exprRows, exprCols;\n\npublic:\n  MatrixGeneratorSlice(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorSlice::MatrixGeneratorSlice(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",      matrix,   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startRow\",    exprRow,  Config::DEFAULT,  \"0\", \"start row of matrix (variables: rowsBefore, columnsBefore, rows, columns)\");\n    readConfig(config, \"startColumn\", exprCol,  Config::DEFAULT,  \"0\", \"start column of matrix (variables: rowsBefore, columnsBefore, rows, columns)\");\n    readConfig(config, \"rows\",        exprRows, Config::DEFAULT,  \"0\", \"0: until end (variables: rowsBefore, columnsBefore, rows, columns)\");\n    readConfig(config, \"columns\",     exprCols, Config::DEFAULT,  \"0\", \"0: until end (variables: rowsBefore, columnsBefore, rows, columns)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorSlice::compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n\n    VariableList varList;\n    varList.setVariable(\"rowsBefore\",    static_cast<Double>(rowsBefore));\n    varList.setVariable(\"columnsBefore\", static_cast<Double>(columnsBefore));\n    varList.setVariable(\"rows\",          static_cast<Double>(A.rows()));\n    varList.setVariable(\"columns\",       static_cast<Double>(A.columns()));\n    const UInt row  = static_cast<UInt>(exprRow->evaluate(varList));\n    const UInt col  = static_cast<UInt>(exprCol->evaluate(varList));\n    const UInt rows = static_cast<UInt>(exprRows->evaluate(varList));\n    const UInt cols = static_cast<UInt>(exprCols->evaluate(varList));\n\n    A = A.slice(row, col, rows > 0 ? rows : A.rows()-row, cols > 0 ? cols : A.columns()-col);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorSort.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorSort.h\n*\n* @brief Sort matrix by column.\n*\n* @author Sebastian Strasser\n* @date 2018-02-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORSORT__\n#define __GROOPS_MATRIXGENERATORSORT__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorSort = R\"(\n\\subsection{Sort}\nSort matrix by \\config{column} in ascending order by default or in \\config{descending} order.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Sort matrix by column.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorSort : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr matrix;\n  std::vector<UInt>  column;\n  Bool descending;\n\npublic:\n  MatrixGeneratorSort(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorSort::MatrixGeneratorSort(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\",     matrix,     Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"column\",     column,     Config::MUSTSET, \"0\", \"sort by column, top = highest priority\");\n    readConfig(config, \"descending\", descending, Config::DEFAULT, \"0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorSort::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute();\n\n    for(auto c : column)\n      if(c >= A.columns())\n        throw(Exception(\"column index error: \"+c%\"&i\"s+\" >= \"+A.columns()%\"&i\"s));\n\n    std::vector<UInt> rowIndex(A.rows());\n    std::iota(rowIndex.begin(), rowIndex.end(), 0);\n    for(UInt idCol = column.size(); idCol-->0;)\n      std::stable_sort(rowIndex.begin(), rowIndex.end(), [&](UInt i, UInt j){return A(i, column.at(idCol)) < A(j, column.at(idCol));});\n    if(descending)\n      std::reverse(rowIndex.begin(), rowIndex.end());\n\n    A = reorder(matrix->compute(), rowIndex);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/matrixGenerator/matrixGeneratorTranspose.h",
    "content": "/***********************************************/\n/**\n* @file matrixGeneratorTranspose.h\n*\n* @brief Transpose of a matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXGENERATORTRANSPOSE__\n#define __GROOPS_MATRIXGENERATORTRANSPOSE__\n\n// Latex documentation\n#ifdef DOCSTRING_MatrixGenerator\nstatic const char *docstringMatrixGeneratorTranspose = R\"(\n\\subsection{Transpose}\nTransposed of a matrix $\\M A^T$.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Transposed of a matrix.\n* @ingroup matrixGeneratorGroup\n* @see MatrixGenerator */\nclass MatrixGeneratorTranspose : public MatrixGeneratorBase\n{\n  MatrixGeneratorPtr matrix;\n\npublic:\n  MatrixGeneratorTranspose(Config &config);\n  void compute(Matrix &A, UInt rowsBefore, UInt columnsBefore, UInt &startRow, UInt &startCol);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline MatrixGeneratorTranspose::MatrixGeneratorTranspose(Config &config)\n{\n  try\n  {\n    readConfig(config, \"matrix\", matrix, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void MatrixGeneratorTranspose::compute(Matrix &A, UInt /*rowsBefore*/, UInt /*columnsBefore*/, UInt &/*startRow*/, UInt &/*startCol*/)\n{\n  try\n  {\n    A = matrix->compute().trans();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerations.cpp",
    "content": "/***********************************************/\n/**\n* @file miscAccelerations.cpp\n*\n* @brief Non conservative forces acting on satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-09\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_MiscAccelerations\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/miscAccelerations/miscAccelerationsRelativisticEffect.h\"\n#include \"classes/miscAccelerations/miscAccelerationsRadiationPressure.h\"\n#include \"classes/miscAccelerations/miscAccelerationsSolarRadiationPressure.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAtmosphericDrag.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAtmosphericDragFromDensityFile.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAlbedo.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAntennaThrust.h\"\n#include \"classes/miscAccelerations/miscAccelerationsFromParametrization.h\"\n#include \"classes/miscAccelerations/miscAccelerationsGroup.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(MiscAccelerations, \"miscAccelerationsType\",\n                      MiscAccelerationsRelativisticEffect,\n                      MiscAccelerationsRadiationPressure,\n                      MiscAccelerationsAtmosphericDrag,\n                      MiscAccelerationsAtmosphericDragFromDensityFile,\n                      MiscAccelerationsAntennaThrust,\n                      MiscAccelerationsFromParametrization,\n                      MiscAccelerationsGroup,\n                      MiscAccelerationsSolarRadiationPressure,\n                      MiscAccelerationsAlbedo)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(MiscAccelerations, \"miscAccelerationsType\")\n\n/***********************************************/\n\nMiscAccelerations::MiscAccelerations(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"non conservative forces acting on satellites\"))\n    {\n      if(readConfigChoiceElement(config, \"relativisticEffect\",             type, \"Relativistic effect (IERS2010)\"))\n       acc.push_back(new MiscAccelerationsRelativisticEffect(config));\n      if(readConfigChoiceElement(config, \"radiationPressure\",              type, \"Solar and Earh radiation pressure model\"))\n       acc.push_back(new MiscAccelerationsRadiationPressure(config));\n      if(readConfigChoiceElement(config, \"atmosphericDrag\",                type, \"atmospheric drag\"))\n       acc.push_back(new MiscAccelerationsAtmosphericDrag(config));\n      if(readConfigChoiceElement(config, \"antennaThrust\",                  type, \"antenna thrust\"))\n       acc.push_back(new MiscAccelerationsAntennaThrust(config));\n      if(readConfigChoiceElement(config, \"atmosphericDragFromDensityFile\", type, \"atmospheric drag (from density along orbit)\"))\n       acc.push_back(new MiscAccelerationsAtmosphericDragFromDensityFile(config));\n      if(readConfigChoiceElement(config, \"fromParametrization\",            type, \"from a solution vector with given parametrization\"))\n        acc.push_back(new MiscAccelerationsFromParametrization(config));\n      if(readConfigChoiceElement(config, \"group\",                          type, \"group misc accelerations\"))\n        acc.push_back(new MiscAccelerationsGroup(config));\n      if(readConfigChoiceElement(config, \"solarRadiationPressure\",         type, \"DEPRECATED since 2022-12-19. Use radiationPressure instead.\"))\n       acc.push_back(new MiscAccelerationsSolarRadiationPressure(config));\n      if(readConfigChoiceElement(config, \"albedo\",                         type, \"DEPRECATED since 2022-12-19. Use radiationPressure instead.\"))\n       acc.push_back(new MiscAccelerationsAlbedo(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMiscAccelerations::~MiscAccelerations()\n{\n  for(UInt i=0; i<acc.size(); i++)\n    delete acc.at(i);\n}\n\n/***********************************************/\n\nVector3d MiscAccelerations::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                         const Vector3d &position, const Vector3d &velocity,\n                                         const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    if(satellite)\n    {\n      Vector3d positionSun;\n      if(ephemerides)\n        positionSun = ephemerides->position(time, Ephemerides::SUN);\n      satellite->changeState(time, position, velocity, positionSun, rotSat, rotEarth);\n    }\n\n    Vector3d sum;\n    for(UInt i=0; i<acc.size(); i++)\n      sum += acc.at(i)->acceleration(satellite, time, position, velocity, rotSat, rotEarth, ephemerides);\n    return sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerations.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerations.h\n*\n* @brief Non conservative forces acting on satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-09\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONS__\n#define __GROOPS_MISCACCELERATIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerations = R\"(\n\\section{MiscAccelerations}\\label{miscAccelerationsType}\nThis class gives the non conservative forces acting on satellites.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/**\n* @defgroup miscAccelerationsGroup MiscAccelerations\n* @brief Non conservative forces acting on satellites.\n* @ingroup classesGroup\n* The interface is given by @ref MiscAccelerations. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass MiscAccelerations;\nclass MiscAccelerationsBase;\ntypedef std::shared_ptr<MiscAccelerations> MiscAccelerationsPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Non conservative forces acting on satellites.\n* An Instance of this class can be created by @ref readConfig. */\nclass MiscAccelerations\n{\n  std::vector<MiscAccelerationsBase*> acc;\n\npublic:\n  /// Constructor.\n  MiscAccelerations(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~MiscAccelerations();\n\n  /** @brief Acceleration.\n  * @param satellite Macro model.\n  * @param time Time.\n  * @param position in CRF [m].\n  * @param velocity in CRF [m/s].\n  * @param rotSat   Sat -> CRF\n  * @param rotEarth CRF -> TRF\n  * @param ephemerides Position of Sun and Moon.\n  * @return acceleration in TRF(!) [m/s^2] */\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides);\n\n  /** @brief creates an derived instance of this class. */\n  static MiscAccelerationsPtr create(Config &config, const std::string &name) {return MiscAccelerationsPtr(new MiscAccelerations(config, name));}\n};\n\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class MiscAccelerations.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a acceleration without forces is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] acceleration Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates MiscAccelerations */\ntemplate<> Bool readConfig(Config &config, const std::string &name, MiscAccelerationsPtr &acceleration, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass MiscAccelerationsBase\n{\npublic:\nvirtual ~MiscAccelerationsBase() {}\nvirtual  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsAlbedo.cpp",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsAlbedo.cpp\n*\n* @brief DEPRECATED since 2022-12-19. Use radiationPressure instead.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-21-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n#include \"classes/miscAccelerations/miscAccelerationsRadiationPressure.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAlbedo.h\"\n\n/***********************************************/\n\nMiscAccelerationsAlbedo::MiscAccelerationsAlbedo(Config &config)\n{\n  try\n  {\n    FileName    fileNameReflectivity, fileNameEmissivity;\n\n    renameDeprecatedConfig(config, \"inputfileEmissity\", \"inputfileEmissivity\", date2time(2020, 8, 20));\n\n    readConfig(config, \"inputfileReflectivity\", fileNameReflectivity, Config::OPTIONAL, \"{groopsDataDir}/albedo/earth_ceres_reflectivity_grid2.5.dat\", \"\");\n    readConfig(config, \"inputfileEmissivity\",   fileNameEmissivity,   Config::OPTIONAL, \"{groopsDataDir}/albedo/earth_ceres_emissivity_grid2.5.dat\", \"\");\n    readConfig(config, \"solarflux\",             solarflux,            Config::DEFAULT,  \"1367\", \"solar flux constant in 1 AU [W/m**2]\");\n    readConfig(config, \"factor\",                factor,               Config::DEFAULT,  \"1.0\",  \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    logWarningOnce<<\"MiscAccelerationsAlbedo is DEPRECATDED since 2022-12-19. Use MiscAccelerationsRadiationPressure instead.\"<<Log::endl;\n\n    // read reflectivity\n    if(!fileNameReflectivity.empty())\n    {\n      GriddedData grid;\n      readFileGriddedData(fileNameReflectivity, grid);\n      points       = grid.points;\n      areas        = grid.areas;\n      reflectivity = grid.values;\n    }\n\n    // read emissivity\n    if(!fileNameEmissivity.empty())\n    {\n      GriddedData grid;\n      readFileGriddedData(fileNameEmissivity, grid);\n      if(points.size() && (points.size() != grid.points.size()))\n        throw(Exception(\"reflectivity and emissivity must be given on same grid\"));\n      points   = grid.points;\n      areas    = grid.areas;\n      emissivity = grid.values;\n    }\n\n    // convert area from unit sphere\n    for(UInt i=0; i<points.size(); i++)\n      areas.at(i) *= pow(points.at(i).r(), 2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d MiscAccelerationsAlbedo::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                               const Vector3d &position, const Vector3d &/*velocity*/,\n                                               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector3d posSat = rotSat.inverseRotate(position);\n    Vector3d posSun = rotSat.inverseRotate(ephemerides->position(time, Ephemerides::SUN));\n\n    const Double AU           = 149597870700.0;\n    const Double distanceSun  = posSun.normalize();\n    const Double s0           = solarflux/LIGHT_VELOCITY*pow(AU/distanceSun,2);\n\n    // gridded data given monthly?\n    UInt index1 = 0;\n    UInt index2 = 0;\n    if((reflectivity.size()==12) || (emissivity.size()==12))\n    {\n      UInt   year, month, day, hour, minute;\n      Double second;\n      time.date(year, month, day, hour, minute, second);\n      index1 = std::min(month-1, reflectivity.size()-1);\n      index2 = std::min(month-1, emissivity.size()-1);\n    }\n\n    Vector3d F; // force in SRF\n    Vector   absorbedPressure(satellite->surfaces.size()); // power for each satellite surface\n    for(UInt i=0; i<points.size(); i++)\n    {\n      Vector3d posEarth     = rotSat.inverseRotate(rotEarth.inverseRotate(points.at(i)));\n      Vector3d direction    = posSat-posEarth;\n      const Double distance = direction.normalize();\n      posEarth.normalize();\n\n      // Cosine of angle of reflected radiation\n      const Double cosReflexion = inner(direction, posEarth);\n      if(cosReflexion<=0) // element visible?\n        continue;\n      // Cosine of angle of incident radiation\n      const Double cosIncident = inner(posSun, posEarth);\n\n      // Reflected Irradiance\n      Double eReflectivity = 0;\n      if(reflectivity.size() && (cosIncident>0))\n        eReflectivity = reflectivity.at(index1).at(i)/(PI*distance*distance)*cosIncident*s0*cosReflexion*areas.at(i);\n\n      // Emitted Irradiance\n      Double eEmittance = 0;\n      if(emissivity.size())\n        eEmittance = emissivity.at(index2).at(i)/(4*PI*distance*distance)*s0*cosReflexion*areas.at(i);\n\n      F += MiscAccelerationsRadiationPressure::force(satellite, direction, eReflectivity, eEmittance, absorbedPressure);\n    }\n\n    // compute thermal radition\n    for(UInt i=0; i<satellite->surfaces.size(); i++)\n    {\n      auto &surface = satellite->surfaces.at(i);\n      if(surface.specificHeatCapacity < 0)\n        F -= (2./3.) * surface.area * absorbedPressure(i) * surface.normal; // spontaneous reemission of absorbed radiation\n    }\n\n    return (factor/satellite->mass) * rotEarth.rotate(rotSat.rotate(F));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsAlbedo.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsAlbedo.h\n*\n* @brief DEPRECATED since 2022-12-19. Use radiationPressure instead.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-21-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONALBEDO__\n#define __GROOPS_MISCACCELERATIONALBEDO__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsAlbedo = R\"(\n\\subsection{Albedo}\\label{miscAccelerationsType:albedo}\nDEPRECATED since 2022-12-19. Use radiationPressure instead.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/planets.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2022-12-19. Use radiationPressure instead.\n* @ingroup miscAccelerationsGroup\n* @see MiscAccelerations */\nclass MiscAccelerationsAlbedo : public MiscAccelerationsBase\n{\n  std::vector<Vector3d>            points;\n  std::vector<Double>              areas;\n  std::vector<std::vector<Double>> reflectivity;\n  std::vector<std::vector<Double>> emissivity;\n  Double                           solarflux;\n  Double                           factor;\n\npublic:\n  MiscAccelerationsAlbedo(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsAntennaThrust.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsAntennaThrust.h\n*\n* @brief Antenna thrust (simple model).\n* @see MiscAccelerations\n*\n* @author Sebastian Strasser\n* @date 2015-03-04\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSANTENNATHRUST__\n#define __GROOPS_MISCACCELERATIONSANTENNATHRUST__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsAntennaThrust = R\"(\n\\subsection{Antenna thrust}\\label{miscAccelerationsType:antennaThrust}\nThe thrust (acceleration) in the opposite direction the antenna is facing\nwhich is generated by satellite antenna broadcasts.\nThe thrust is defined in the satellite macro model.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Antenna thrust (simple model).\n* @ingroup miscAccelerationsGroup\n* @see MiscAccelerations */\nclass MiscAccelerationsAntennaThrust : public MiscAccelerationsBase\n{\n  Double factor;\n\npublic:\n  MiscAccelerationsAntennaThrust(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\ninline MiscAccelerationsAntennaThrust::MiscAccelerationsAntennaThrust(Config &config)\n{\n  try\n  {\n\n    readConfig(config, \"factor\", factor, Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsAntennaThrust::acceleration(SatelliteModelPtr satellite, const Time &/*time*/,\n                                                             const Vector3d &/*pos*/, const Vector3d &/*vel*/,\n                                                             const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n\n    return (-factor/satellite->mass/LIGHT_VELOCITY) * rotEarth.rotate(rotSat.rotate(satellite->thrustPower));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsAtmosphericDrag.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsAtmosphericDrag.h\n*\n* @brief Atmospheric drag.\n* @see MiscAccelerations\n*\n* @author Beate Klinger\n* @author Sandro Krauss\n* @date 2015-12-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSATMOSPHERICDRAG__\n#define __GROOPS_MISCACCELERATIONSATMOSPHERICDRAG__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsAtmosphericDrag = R\"(\n\\subsection{AtmosphericDrag}\\label{miscAccelerationsType:atmosphericDrag}\nAtmospheric drag model.\nAlgorithm for the atmospheric drag modelling is based on the free molecule flow\ntheory by Sentman 1961. An analytical expression of this treatise is given in\nMoe and Moe 2005.\n\nSentman L. (1961), Free molecule flow theory and its application to the determination\nof aerodynamic forces, Technical report.\n\nMoe K., Moe M. M. (2005), Gas-surface interactions and satellite drag coefficients,\nPlanetary and Space Science 53(8), 793-801, doi:10.1016/j.pss.2005.03.005.\n\nOptional determination steps:\nTurn temperature on or off.\nIn the first case, the model mentioned above is applied, which estimates variable drag\nand lift coefficients - in the latter case a constant drag coefficient can be specified.\n\nTurn wind on/off:\nIt enables the usage of the Horizontal Wind Model 2014 to add additional thermospheric\nwinds in the calculation process.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/thermosphere/thermosphere.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Atmospheric drag.\n * @ingroup miscAccelerationsGroup\n * @see MiscAccelerations */\nclass MiscAccelerationsAtmosphericDrag : public MiscAccelerationsBase\n{\n  ThermospherePtr thermosphere;\n  Bool            useTemperature, useWind;\n  Vector3d        omega;\n  Double          factor;\n\npublic:\n  MiscAccelerationsAtmosphericDrag(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n\n  static Vector3d force(SatelliteModelPtr satellite, const Vector3d &direction, Double velocity, Double density, Double temperature);\n};\n\n/***********************************************/\n\ninline MiscAccelerationsAtmosphericDrag::MiscAccelerationsAtmosphericDrag(Config &config)\n{\n  try\n  {\n    Double angleVelocity;\n\n    readConfig(config, \"thermosphere\",        thermosphere,   Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"earthRotation\",       angleVelocity,  Config::DEFAULT, \"7.29211585531e-5\", \"[rad/s]\");\n    readConfig(config, \"considerTemperature\", useTemperature, Config::DEFAULT, \"1\",   \"compute drag and lift, otherwise simple drag coefficient is used\");\n    readConfig(config, \"considerWind\",        useWind,        Config::DEFAULT, \"1\",   \"\");\n    readConfig(config, \"factor\",              factor,         Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n\n    omega = Vector3d(0, 0, angleVelocity);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsAtmosphericDrag::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                                               const Vector3d &position, const Vector3d &velocity,\n                                                               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n\n    Double   density, temperature;\n    Vector3d wind;\n    thermosphere->state(time, rotEarth.rotate(position), density, temperature, wind);\n    if(!useTemperature)\n      temperature = 0;\n    if(!useWind)\n      wind = Vector3d();\n\n    // direction and speed of thermosphere relative to satellite in SRF\n    Vector3d direction = rotSat.inverseRotate(rotEarth.inverseRotate(wind) + crossProduct(omega, position) - velocity);\n    const Double v = direction.normalize();\n    Vector3d acc = (factor/satellite->mass) * rotEarth.rotate(rotSat.rotate(force(satellite, direction, v, density, temperature)));\n    if(std::isnan(acc.r()))\n    {\n      logWarning<<satellite->satelliteName<<\" (altitude \"<<1e-3*(position.r()-DEFAULT_R)<<\" km, velocity \"<<1e-3*v<<\" km/s)\"\n                <<\"atmosphericDrag is NaN (set to zero) at \"<<time.dateTimeStr()<<Log::endl;\n      acc = Vector3d();\n    }\n    return acc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsAtmosphericDrag::force(SatelliteModelPtr satellite, const Vector3d &direction, Double velocity, Double density, Double temperature)\n{\n  try\n  {\n    constexpr Double R     = 8.3144;    // universal gas constant [J mol-1 K-1]\n    constexpr Double M     = 15.5/1000; // average modelcular mass [kg/mol]\n    constexpr Double alpha = 0.9;       // accomodation coefficientDrag [-]\n    constexpr Double Tw    = 273;       // temperature of the surface [K]\n\n    Vector3d F;\n    for(UInt i=0; i<satellite->surfaces.size(); i++)\n    {\n      auto &surface = satellite->surfaces.at(i);\n      if((surface.type == SatelliteModel::Surface::PLATE) || (surface.type == SatelliteModel::Surface::GRACESHADOW))\n      {\n        const Double cosPhi = -inner(direction, surface.normal);\n\n        if(temperature > 0)\n        {\n          const Vector3d ul   = crossProduct(direction, crossProduct(direction, surface.normal));\n          const Double   s    = velocity/std::sqrt(2*R*temperature/M); // molecular speed ratio\n          const Double   P    = std::exp(-std::pow(cosPhi*s, 2))/s;\n          const Double   G    = 1/(2*s*s);\n          const Double   Z    = 1 + std::erf(cosPhi*s);\n          const Double   x    = std::sqrt(1./6.*(1 + alpha * (3*R*Tw/(velocity*velocity)-1))) * (cosPhi*std::sqrt(PI)*Z+P);\n          F += 0.5 * density * surface.area *velocity*velocity * ((P/std::sqrt(PI) + cosPhi*((1+G)*Z+x)) * direction + (G*Z+x) * ul);\n        }\n        else if(cosPhi > 0) // simple drag coefficient\n          F += 0.5 * density * surface.area * cosPhi * velocity*velocity * satellite->coefficientDrag * direction;\n      }\n      else if (surface.type == SatelliteModel::Surface::SPHERE)\n      {\n        F += 0.5 * density * surface.area * velocity*velocity * satellite->coefficientDrag * direction;\n      }\n      else\n        throw(Exception(\"cylinder not implemented yet\"));\n    } // for(i=surface)\n\n    return F;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsAtmosphericDragFromDensityFile.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsAtmosphericDragFromDensityFile.h\n*\n* @brief Atmospheric drag from denity along orbit.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSATMOSPHERICDRAGFROMDENSITYFILE__\n#define __GROOPS_MISCACCELERATIONSATMOSPHERICDRAGFROMDENSITYFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsAtmosphericDragFromDensityFile = R\"(\n\\subsection{AtmosphericDragFromDensityFile}\\label{miscAccelerationsType:atmosphericDragFromDensityFile}\nAtmospheric drag computed from thermospheric density along the orbit\n(\\configFile{inputfileDensity}{instrument}, MISCVALUE). The \\configClass{thermosphere}{thermosphereType}\nis used to to compute temperature and wind.\nFor further details see \\configClass{atmosphericDrag}{miscAccelerationsType:atmosphericDrag}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAtmosphericDrag.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Atmospheric drag.\n * @ingroup miscAccelerationsGroup\n * @see MiscAccelerations */\nclass MiscAccelerationsAtmosphericDragFromDensityFile : public MiscAccelerationsBase\n{\n  MiscValueArc    density;\n  ThermospherePtr thermosphere;\n  Bool            useTemperature, useWind;\n  Vector3d        omega;\n  Double          factor;\n  UInt            idx;\n\npublic:\n  MiscAccelerationsAtmosphericDragFromDensityFile(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\ninline MiscAccelerationsAtmosphericDragFromDensityFile::MiscAccelerationsAtmosphericDragFromDensityFile(Config &config)\n{\n  try\n  {\n    FileName fileNameDensity;\n    Double   angleVelocity;\n\n    readConfig(config, \"inputfileDensity\",    fileNameDensity, Config::MUSTSET, \"\",    \"density along orbit, MISCVALUE (kg/m^3)\");\n    readConfig(config, \"thermosphere\",        thermosphere,    Config::MUSTSET, \"\",    \"used to compute temperature and wind\");\n    readConfig(config, \"earthRotation\",       angleVelocity,   Config::DEFAULT, \"7.29211585531e-5\", \"[rad/s]\");\n    readConfig(config, \"considerTemperature\", useTemperature,  Config::DEFAULT, \"1\",   \"compute drag and lift, otherwise simple drag coefficient is used\");\n    readConfig(config, \"considerWind\",        useWind,         Config::DEFAULT, \"1\",   \"\");\n    readConfig(config, \"factor\",              factor,          Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n\n    density = InstrumentFile::read(fileNameDensity);\n    omega = Vector3d(0, 0, angleVelocity);\n    idx = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsAtmosphericDragFromDensityFile::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                                                              const Vector3d &position, const Vector3d &velocity,\n                                                                              const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n\n    if((time < density.front().time)|| (time > density.back().time))\n      throw(Exception(\"time not given in density file: \"+time.dateTimeStr()));\n\n    // find index (interpolations interval)\n    if((idx >= density.size()) || (time < density.at(idx).time))\n      idx = 0;\n    while(time > density.at(idx).time)\n      idx++;\n    if(time != density.at(idx).time)\n      throw(Exception(\"time not given in density file: \"+time.dateTimeStr()));\n\n    Double   densityModel, temperature;\n    Vector3d wind;\n    thermosphere->state(time, rotEarth.rotate(position), densityModel, temperature, wind);\n    if(!useTemperature)\n      temperature = 0;\n    if(!useWind)\n      wind = Vector3d();\n\n    // direction and speed of thermosphere relative to satellite in SRF\n    Vector3d direction = rotSat.inverseRotate(rotEarth.inverseRotate(wind) + crossProduct(omega, position) - velocity);\n    const Double v = direction.normalize();\n\n    return (factor/satellite->mass) * rotEarth.rotate(rotSat.rotate(MiscAccelerationsAtmosphericDrag::force(satellite, direction, v, density.at(idx).value, temperature)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsFromParametrization.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsFromParametrization.h\n*\n* @brief Acceleration from parametrization.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-11-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSFROMPARAMETRIZATION__\n#define __GROOPS_MISCACCELERATIONSFROMPARAMETRIZATION__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsFromParametrization = R\"(\n\\subsection{FromParametrization}\\label{miscAccelerationsType:fromParametrization}\nReads a solution vector from file \\configFile{inputfileSolution}{matrix}\nwhich may be computed by a least squares adjustment (e.g. by \\program{NormalsSolverVCE}).\nThe coefficients of the vector are interpreted from position \\config{indexStart}\n(counting from zero) with help of \\configClass{parametrization}{parametrizationAccelerationType}.\nIf the solution file contains solution of several right hand sides you can choose\none with number \\config{rightSide} (counting from zero).\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileMatrix.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Acceleration from parametrization.\n* @ingroup miscAccelerationsGroup\n* @see MiscAccelerations */\nclass MiscAccelerationsFromParametrization : public MiscAccelerationsBase\n{\n  ParametrizationAccelerationPtr parametrization;\n  Vector x;\n  Double factor;\n\npublic:\n  MiscAccelerationsFromParametrization(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\ninline MiscAccelerationsFromParametrization::MiscAccelerationsFromParametrization(Config &config)\n{\n  try\n  {\n    FileName fileNamex;\n    UInt     rightSide, indexStart;\n\n    readConfig(config, \"parametrization\",   parametrization, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileSolution\", fileNamex,       Config::MUSTSET,  \"\",    \"solution vector\");\n    readConfig(config, \"indexStart\",        indexStart,      Config::DEFAULT,  \"0\",   \"position in the solution vector\");\n    readConfig(config, \"rightSide\",         rightSide,       Config::DEFAULT,  \"0\",   \"if solution contains several right hand sides, select one\");\n    readConfig(config, \"factor\",            factor,          Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    Matrix mx;\n    readFileMatrix(fileNamex, mx);\n    x = mx.slice(indexStart, rightSide, parametrization->parameterCount(), 1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsFromParametrization::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                                                   const Vector3d &pos, const Vector3d &vel,\n                                                                   const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    Matrix A(3, parametrization->parameterCount());\n    Matrix B(3, parametrization->parameterCountArc());\n    parametrization->compute(satellite, time, pos, vel, rotSat, rotEarth, ephemerides, A, B);\n    Vector a(3);\n    if(A.columns()) matMult(factor, A, x.row(0, A.columns()), a);\n    if(B.columns()) matMult(factor, B, x.row(A.columns(), B.columns()), a);\n    return Vector3d(a);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsGroup.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsGroup.h\n*\n* @brief Group.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-11-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSGROUP__\n#define __GROOPS_MISCACCELERATIONSGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsGroup = R\"(\n\\subsection{Group}\\label{miscAccelerationsType:group}\nGroups a set of \\configClass{miscAccelerations}{miscAccelerationsType} and has no further effect itself.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Group.\n* @ingroup miscAccelerationsGroup\n* @see MiscAccelerations */\nclass MiscAccelerationsGroup : public MiscAccelerationsBase\n{\n  MiscAccelerationsPtr miscAccelerations;\n  Double               factor;\n\npublic:\n  MiscAccelerationsGroup(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\ninline MiscAccelerationsGroup::MiscAccelerationsGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"miscAccelerations\", miscAccelerations, Config::DEFAULT, \"\", \"\");\n    readConfig(config, \"factor\",            factor,            Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsGroup::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                                             const Vector3d &pos, const Vector3d &vel,\n                                                             const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    return factor * miscAccelerations->acceleration(satellite, time, pos, vel, rotSat, rotEarth, ephemerides);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsRadiationPressure.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsRadiationPressure.h\n*\n* @brief Solar and Earth radiation pressure model.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-08-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSRADIATIONPRESSURE__\n#define __GROOPS_MISCACCELERATIONSRADIATIONPRESSURE__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsRadiationPressure = R\"(\n\\subsection{RadiationPressure}\\label{miscAccelerationsType:RadiationPressure}\nThis class computes acceleration acting on a satellite caused by Solar and Earth radiation pressure\nand thermal radiation.\n\nSolar radiation pressure: The solar constant at 1~AU can be set via \\config{solarFlux}.\nThe \\config{factorSolarRadation} can be used to scale the computed acceleration of the direct solar radiation.\n\nEarth radiation pressure:\nInput are a time series of gridded albedo values (unitless) as \\configFile{inputfileAlbedoTimeSeries}{griddedDataTimeSeries}\nand a time series of gridded longwave flux (W/m$^2$) as \\configFile{inputfileLongwaveFluxTimeSeries}{griddedDataTimeSeries}.\nBoth files are optional and if not specified, the respective effect on the acceleration is not computed.\nThe \\config{factorEarthRadation} can be used to scale the computed acceleration of the earth radiation.\n\nThe thermal radiation (TRP) of the satellite itself is either computed as direct re-emission or\nbased on the actual temperature of the satellite surfaces, depending on the setings of the\n\\file{satellite macro model}{satelliteModel}. The second one uses a transient temperature model\nwith a temporal differential equation which disallows parallel computing.\nThe \\config{factorThermalRadiation} can be used to scale the computed acceleration of the TRP.\n\nThe algorithms are described in:\n\nWoeske et. al. (2019), GRACE accelerometer calibration by high precision non-gravitational force modeling,\nAdvances in Space Research, \\url{https://doi.org/10.1016/j.asr.2018.10.025}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"classes/eclipse/eclipse.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Solar and Earth radiation pressure model.\n * @ingroup miscAccelerationsGroup\n * @see MiscAccelerations */\nclass MiscAccelerationsRadiationPressure : public MiscAccelerationsBase\n{\n  class State\n  {\n  public:\n    SatelliteModelPtr satellite;\n    Time              time;\n    Vector            absorbedPressure;  // for each surface\n    Bool              needTemperature;\n    Vector            temperature;       // for each surface\n  };\n\n  Double                      solarflux;\n  EclipsePtr                  eclipse;\n  Bool                        hasAlbedo, hasFlux;\n  InFileGriddedDataTimeSeries fileAlbedoTimeSeries, fileFluxTimeSeries;\n  std::vector<Vector3d>       points;\n  std::vector<Double>         areas;\n  Double                      factorSun, factorEarth, factorThermal;\n  std::vector<State>          states;\n\npublic:\n  MiscAccelerationsRadiationPressure(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n\n  static Vector3d force(SatelliteModelPtr satellite, const Vector3d &direction, Double visible, Double infrared, Vector &absorbedPressure);\n};\n\n/***********************************************/\n\ninline MiscAccelerationsRadiationPressure::MiscAccelerationsRadiationPressure(Config &config)\n{\n  try\n  {\n    FileName fileNameInAlbedo, fileNameInFlux;\n\n    readConfig(config, \"solarflux\",                       solarflux,        Config::DEFAULT,  \"1367\", \"solar flux constant in 1 AU [W/m^2]\");\n    readConfig(config, \"eclipse\",                         eclipse,          Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileAlbedoTimeSeries\",       fileNameInAlbedo, Config::OPTIONAL, \"{groopsDataDir}/earthRadiationPressure/CERES_SYN1deg_albedo_climatology.dat\",       \"GriddedDataTimeSeries of albedo values (unitless)\");\n    readConfig(config, \"inputfileLongwaveFluxTimeSeries\", fileNameInFlux,   Config::OPTIONAL, \"{groopsDataDir}/earthRadiationPressure/CERES_SYN1deg_longwaveFlux_climatology.dat\", \"GriddedDataTimeSeries of longwave flux values [W/m^2]\");\n    readConfig(config, \"factorSolarRadation\",             factorSun,        Config::DEFAULT,  \"1.0\",  \"Solar radiation pressure is multiplied by this factor\");\n    readConfig(config, \"factorEarthRadation\",             factorEarth,      Config::DEFAULT,  \"1.0\",  \"Earth radiation preussure is multiplied by this factor\");\n    readConfig(config, \"factorThermalRadiation\",          factorThermal,    Config::DEFAULT,  \"1.0\",  \"Thermal (re-)radiation is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n\n    hasAlbedo = FALSE;\n    if(!fileNameInAlbedo.empty())\n    {\n      fileAlbedoTimeSeries.open(fileNameInAlbedo);\n      GriddedData grid = fileAlbedoTimeSeries.grid();\n      points    = grid.points;\n      areas     = grid.areas;\n      hasAlbedo = TRUE;\n    }\n\n    hasFlux = FALSE;\n    if(!fileNameInFlux.empty())\n    {\n      fileFluxTimeSeries.open(fileNameInFlux);\n      GriddedData grid = fileFluxTimeSeries.grid();\n      if(points.size() && (points.size() != grid.points.size()))  // grid is already set up from albedo file\n        throw(Exception(\"Albedo and longwave flux must be given on same grid\"));\n      points  = grid.points;\n      areas   = grid.areas;\n      hasFlux = TRUE;\n    }\n\n    // convert area from unit sphere\n    for(UInt i=0; i<points.size(); i++)\n      areas.at(i) *= std::pow(points.at(i).r(), 2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsRadiationPressure::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                                                 const Vector3d &position, const Vector3d &/*velocity*/,\n                                                                 const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector absorbedPressure(satellite->surfaces.size()); // power for each satellite surface\n\n    // from sun to satellite in SRF\n    Vector3d posSat = rotSat.inverseRotate(position);\n    Vector3d posSun = rotSat.inverseRotate(ephemerides->position(time, Ephemerides::SUN));\n    constexpr Double AU = 149597870700.0;\n    const Double ny = eclipse ? eclipse->factor(time, position, ephemerides) : 1; // shadowing from Earth and Moon\n\n    // Solar Radiation Pressure (SRP)\n    // ------------------------------\n    Vector3d     directionSunSat = posSat-posSun;\n    const Double distanceSunSat  = directionSunSat.normalize();\n    Vector3d F = factorSun * force(satellite, directionSunSat, ny*solarflux/LIGHT_VELOCITY*std::pow(AU/distanceSunSat, 2), 0., absorbedPressure);\n\n    // Earth Radiation Pressure (ERP)\n    // ------------------------------\n    if((factorEarth || factorThermal) && (hasAlbedo || hasFlux))\n    {\n      Vector dataAlbedo, dataFlux;\n      if(hasAlbedo) dataAlbedo = fileAlbedoTimeSeries.data(time);\n      if(hasFlux)   dataFlux   = fileFluxTimeSeries.data(time);\n\n      for(UInt i=0; i<points.size(); i++)\n      {\n        Vector3d posEarth             = rotSat.inverseRotate(rotEarth.inverseRotate(points.at(i))); // in SRF\n        Vector3d directionEarthSat    = posSat-posEarth;\n        const Double distanceEarthSat = directionEarthSat.normalize();\n\n        // Cosine of angle of reflected radiation\n        const Double cosReflexion = inner(directionEarthSat, normalize(posEarth));\n        if(cosReflexion <= 0) // element visible?\n          continue;\n        const Double f = cosReflexion*areas.at(i)/(PI*distanceEarthSat*distanceEarthSat);\n\n        // Reflected Irradiance\n        Double eReflectivity = 0;\n        if(hasAlbedo)\n        {\n          Vector3d directionSunEarth    = posEarth-posSun;\n          const Double distanceSunEarth = directionSunEarth.normalize();\n          const Double cosIncident      = -inner(directionSunEarth, normalize(posEarth)); // Cosine of angle of incident radiation\n          if(cosIncident > 0)\n            eReflectivity = f * dataAlbedo(i) * cosIncident * solarflux/LIGHT_VELOCITY * std::pow(AU/distanceSunEarth, 2);\n        }\n\n        // Emitted Irradiance\n        Double eEmittance = 0;\n        if(hasFlux)\n          eEmittance = f * dataFlux(i)/LIGHT_VELOCITY;\n\n        F += factorEarth * force(satellite, directionEarthSat, eReflectivity, eEmittance, absorbedPressure);\n      }\n    } // if((factorEarth || factorThermal) && (hasAlbedo || hasFlux)\n\n    // Thermal Radiation Pressure (TRP)\n    // --------------------------------\n    if(factorThermal && absorbedPressure.size() && quadsum(absorbedPressure))\n    {\n      constexpr Double sigma = 5.670374419e-8; // Stefan–Boltzmann constant [W/m^2/K^4]\n\n      // set temperature to be in equillibrium with input power\n      auto computeEquillibriumTemperature = [](State &state, const Time &time, const Vector &absorbedPressure)\n      {\n        auto &surfaces = state.satellite->surfaces;\n        state.time             = time;\n        state.absorbedPressure = absorbedPressure;\n        state.temperature      = Vector(surfaces.size());\n        for(UInt i=0; i<surfaces.size(); i++)\n          if(surfaces.at(i).specificHeatCapacity > 0)\n            state.temperature(i) = std::pow(LIGHT_VELOCITY/sigma/surfaces.at(i).absorptionInfrared * std::max(state.absorbedPressure(i), 0.), 1./4.);\n      };\n\n      // find current state of satellite or create new\n      auto state = std::find_if(states.begin(), states.end(), [&](const State &s) {return s.satellite == satellite;});\n      if(state == states.end())\n      {\n        // first state -> set temperature to be in equillibrium with input power\n        state = states.insert(states.end(), State());\n        state->satellite       = satellite;\n        state->needTemperature = std::any_of(satellite->surfaces.begin(), satellite->surfaces.end(), [](const auto &s) {return s.specificHeatCapacity > 0;});\n        if(state->needTemperature)\n          computeEquillibriumTemperature(*state, time, absorbedPressure);\n      }\n\n      // Update temperature\n      if(state->needTemperature)\n      {\n        if((state->time > time) || ((time - state->time).seconds() > 15*60))\n        {\n          logWarning<<time.dateTimeStr()<<\" thermal radiation pressure: temperature state time \"<<state->time.dateTimeStr()<<\" is not within 15 min before -> restart with equillibrium temperature\"<<Log::endl;\n          logWarning<<\"maybe disable parallel computing?\"<<Log::endl;\n          computeEquillibriumTemperature(*state, time, absorbedPressure);\n        }\n        else\n        {\n          constexpr Double dt = 1.; // integration step size [seconds]\n          while(state->time < time)\n          {\n            axpy(dt/(time-state->time).seconds(), absorbedPressure - state->absorbedPressure, state->absorbedPressure);\n            for(UInt i=0; i<satellite->surfaces.size(); i++)\n              if(satellite->surfaces.at(i).specificHeatCapacity > 0)\n              {\n                auto &surface = satellite->surfaces.at(i);\n                state->temperature(i) += dt/surface.specificHeatCapacity *\n                                        (LIGHT_VELOCITY*state->absorbedPressure(i) - surface.absorptionInfrared * sigma * std::pow(state->temperature(i), 4));\n\n              }\n            state->time += seconds2time(dt);\n          }\n        }\n      }\n\n      // compute thermal radition\n      for(UInt i=0; i<satellite->surfaces.size(); i++)\n      {\n        auto &surface = satellite->surfaces.at(i);\n        if(surface.specificHeatCapacity > 0)\n          F -= factorThermal * (2./3.*sigma/LIGHT_VELOCITY) * surface.area * surface.absorptionInfrared * std::pow(state->temperature(i), 4) * surface.normal;\n        else if(surface.specificHeatCapacity < 0)\n          F -= factorThermal * (2./3.) * surface.area * absorbedPressure(i) * surface.normal; // spontaneous reemission of absorbed radiation\n      }\n    } // if(factorThermal)\n\n    return (1./satellite->mass) * rotEarth.rotate(rotSat.rotate(F));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsRadiationPressure::force(SatelliteModelPtr satellite, const Vector3d &direction, Double visible, Double infrared, Vector &absorbedPressure)\n{\n  try\n  {\n    Vector3d F;\n    for(UInt i=0; i<satellite->surfaces.size(); i++)\n    {\n      auto &surface = satellite->surfaces.at(i);\n\n      // absorptionX + diffusionX + reflexionX = 1.\n      const Double reflexion  = surface.reflexionVisible  * visible + surface.reflexionInfrared  * infrared;\n      const Double diffusion  = surface.diffusionVisible  * visible + surface.diffusionInfrared  * infrared;\n      const Double absorption = surface.absorptionVisible * visible + surface.absorptionInfrared * infrared;\n\n      if((surface.type == SatelliteModel::Surface::PLATE) || (surface.type == SatelliteModel::Surface::GRACESHADOW))\n      {\n        const Double cosPhi = -inner(direction, surface.normal);\n        if(cosPhi < 1e-10)\n          continue;\n\n        // hard-coded GRACE self-shadowing of bottom plate and inner sides\n        Double fraction = 1.;\n        if(surface.type == SatelliteModel::Surface::GRACESHADOW)\n        {\n          constexpr Double sin50 = 0.766044443119; // std::sin(DEG2RAD*50.);\n          constexpr Double cos50 = 0.642787609687; // std::cos(DEG2RAD*50.);\n          constexpr Double a     = 3122.5;         // length of bottom side in x-direction\n          constexpr Double b     = 1643.52084;     // width of the bottom side in y-direction\n          constexpr Double s     = 73.10281*2;     // length of inner plate = 73.1 mm\n          const Double alpha = DEG2RAD*50;\n          const Double c     = std::sqrt(std::pow(s,2)+std::pow(b,2)-2*s*b*std::cos(PI-alpha));\n\n          if(surface.normal.z() > 0.999) // bottom plate\n          {\n            // projected lower point of side plate into bottom side plane along light direction (scaled)\n            Double sx = s/a*sin50 * std::fabs(direction.x()/direction.z());\n            Double sy = s/b*sin50 * std::fabs(direction.y()/direction.z()) - s/b*cos50;\n            if(sx > 1) {sy /= sx; sx = 1.;}\n            if(sy > 1) {sx /= sy; sy = 1.;}\n            fraction = 1.-std::max(sy, 0.)*(1.-0.5*sx);\n          }\n          else // inner sides\n          {\n            Double sy1=0, sy2=1;\n            if(std::fabs(direction.z()) > 1e-10)\n            {\n              // -------------- sy1 --------------\n              const Double lambda1 = std::atan2(direction.z(),std::fabs(direction.y()));\n              if(lambda1 < 1e-10)             // direction is comming from underneath the satellite\n              {\n                const Double gamma1 = PI-alpha-std::fabs(lambda1);\n                sy1 = -(std::sin(std::fabs(lambda1))*b/std::sin(gamma1))/s;\n              }\n              else                            // direction is comming from above the satellite\n              {\n                const Double gamma1 = alpha-lambda1;\n                sy1 = (std::sin(lambda1)*b/std::sin(gamma1))/s;\n              }\n              // -------------- sy2 --------------\n              const Double lambda2 = std::atan2(-direction.z(),std::fabs(-direction.y()));\n              const Double epsilon = std::asin(sin50*s/c);\n              if(lambda2 <= epsilon)\n              {\n                const Double gamma2 = PI-(PI-epsilon-alpha)-(epsilon-lambda2);\n                sy2 = (c*std::sin(epsilon-lambda2)/std::sin(gamma2))/s;\n              }\n              else\n              {\n                const Double gamma2 = PI-(epsilon+alpha)-(lambda2-epsilon);\n                sy2 = -(c*std::sin(lambda2-epsilon)/std::sin(gamma2))/s;\n              }\n            }\n\n            const Double dx = std::fabs(direction.x()/(surface.normal.z()*direction.z()+surface.normal.y()*direction.y()));\n            constexpr Double h = b*sin50+s*0.984807753012;           //(sin80) height of outer point of other side above inner side\n            Double sx1 = b/a*sin50 * dx;                             // bottom\n            Double sx2 = h/a * dx;                                   // other inner side\n\n            if(sx1 > 1) {sy1 /= sx1; sx1 = 1.;}\n            if(sy1 > 1) {sx1 /= sy1; sy1 = 1.;}\n            if(sy1 < 0) {sx1 -= (sx2-sx1)/sy2*sy1; sy1 = 0.;} // final\n            if(sx2 > 1) {sy2 = sy1 + (sy2-sy1)*(1-sx1)/(sx2-sx1); sx2 = 1.;}\n            if(sy2 > 1) {sx2 = sx1 + (sx2-sx1)*(1-sy1)/(sy2-sy1); sy2 = 1.;}\n            fraction = 1. - std::max(sy1, 0.)*(1.-0.5*sx1)- std::max(sy2-sy1, 0.)*((1.-sx1) - 0.5*(sx2-sx1));\n          }\n        }\n\n        // Source: Montenbruck et al. (2015) Enhanced solar radiation pressure modeling for Galileo satellites. (Equ.5) DOI 10.1007/s00190-014-0774-0\n        F += fraction*surface.area*cosPhi*(absorption+diffusion)*direction - fraction*surface.area*cosPhi*(2./3.*diffusion+2.*cosPhi*reflexion)*surface.normal;\n        if(absorbedPressure.size())\n          absorbedPressure(i) += fraction*cosPhi*absorption;\n      }\n      else if(surface.type == SatelliteModel::Surface::CYLINDER)\n      {\n        // Source: Rodriguez Solano (2014) Impact of non-conservative force modeling on GNSS satellite orbits and global solutions. PhD thesis\n        const Double cosPhi = -inner(direction, surface.normal);\n        if(cosPhi < 1e-10)\n          continue;\n        F += surface.area*cosPhi*(absorption+diffusion)*direction - surface.area*cosPhi*(PI/6.*diffusion+4./3.*cosPhi*reflexion)*surface.normal;\n        if(absorbedPressure.size())\n          absorbedPressure(i) += cosPhi*absorption;\n      }\n      else if(surface.type == SatelliteModel::Surface::SPHERE)\n      {\n        // Source: Sosnica Krzysztof: Determination of Precise Satellite Orbits and Geodetic Parameters using Satellite Laser Ranging\n        const Double CR = (1.0+4./9.*surface.diffusionVisible);\n        F += CR * surface.area * direction * (visible + infrared);\n       }\n    } // for(i=surface)\n\n    return F;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsRelativisticEffect.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsRelativisticEffect.h\n*\n* @brief Relativistic effect (IERS2010).\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSRELATIVISTICEFFECT__\n#define __GROOPS_MISCACCELERATIONSRELATIVISTICEFFECT__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsRelativisticEffect = R\"(\n\\subsection{Relativistic effect}\\label{miscAccelerationsType:relativisticEffect}\nThe relativistic effect to the acceleration of an artificial Earth satellite\naccording to IERS2010 conventions.\n\nThe macro model and the attitude of the satellite is not needed.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/planets.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Relativistic effect (IERS2010).\n* @ingroup miscAccelerationsGroup\n* @see MiscAccelerations */\nclass MiscAccelerationsRelativisticEffect : public MiscAccelerationsBase\n{\n  Double   factor;\n  Double   GM;\n  Double   beta, gamma;\n  Vector3d J;\n\npublic:\n  MiscAccelerationsRelativisticEffect(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\ninline MiscAccelerationsRelativisticEffect::MiscAccelerationsRelativisticEffect(Config &config)\n{\n  try\n  {\n    Double momentum;\n\n    readConfig(config, \"beta\",   beta,     Config::DEFAULT,  \"1.0\",   \"PPN (parameterized post-Newtonian) parameter\");\n    readConfig(config, \"gamma\",  gamma,    Config::DEFAULT,  \"1.0\",   \"PPN (parameterized post-Newtonian) parameter\");\n    readConfig(config, \"J\",      momentum, Config::DEFAULT,  \"9.8e8\", \"Earth’s angular momentum per unit mass [m**2/s]\");\n    readConfig(config, \"GM\",     GM,       Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"factor\", factor,   Config::DEFAULT,  \"1.0\",   \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n\n    J = Vector3d(0, 0, momentum);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsRelativisticEffect::acceleration(SatelliteModelPtr /*satellite*/, const Time &time,\n                                                                  const Vector3d &pos, const Vector3d &vel,\n                                                                  const Rotary3d &/*rotSat*/, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n    if(vel.r() == 0.)\n      logWarning<<\"MiscAccelerationsRelativisticEffect: velocity is zero\"<<Log::endl;\n\n    // Position and velocity of sun relative to Earth\n    Vector3d posSun, velSun;\n    ephemerides->ephemeris(time, Ephemerides::SUN, posSun, velSun);\n\n    const Double   r = pos.r();\n    const Vector3d a = GM/pow(LIGHT_VELOCITY,2)/pow(r,3) * ((2*(beta+gamma)*GM/r-gamma*vel.quadsum())*pos + 2*(1+gamma)*inner(pos,vel) * vel\n                                                           +(1+gamma)*(3/r/r*inner(pos,J)*crossProduct(pos,vel) + crossProduct(vel,J)))\n                     + GM_Sun/pow(LIGHT_VELOCITY,2)/pow(posSun.r(),3) * (1+2*gamma) * crossProduct(crossProduct(velSun, posSun), vel);\n    return factor * rotEarth.rotate(a);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/miscAccelerations/miscAccelerationsSolarRadiationPressure.h",
    "content": "/***********************************************/\n/**\n* @file miscAccelerationsSolarRadiationPressure.h\n*\n* @brief DEPRECATED since 2022-12-19. Use radiationPressure instead.\n* @see MiscAccelerations\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-21-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCACCELERATIONSSOLARRADIATIONPRESSURE__\n#define __GROOPS_MISCACCELERATIONSSOLARRADIATIONPRESSURE__\n\n// Latex documentation\n#ifdef DOCSTRING_MiscAccelerations\nstatic const char *docstringMiscAccelerationsSolarRadiationPressure = R\"(\n\\subsection{SolarRadiationPressure}\\label{miscAccelerationsType:solarRadiationPressure}\nDEPRECATED since 2022-12-19. Use radiationPressure instead.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/eclipse/eclipse.h\"\n#include \"classes/miscAccelerations/miscAccelerationsRadiationPressure.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2022-12-19. Use radiationPressure instead.\n * @ingroup miscAccelerationsGroup\n * @see MiscAccelerations */\nclass MiscAccelerationsSolarRadiationPressure : public MiscAccelerationsBase\n{\n  EclipsePtr eclipse;\n  Double     solarflux;\n  Double     factor;\n\npublic:\n  MiscAccelerationsSolarRadiationPressure(Config &config);\n\n  Vector3d acceleration(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides) override;\n};\n\n/***********************************************/\n\ninline MiscAccelerationsSolarRadiationPressure::MiscAccelerationsSolarRadiationPressure(Config &config)\n{\n  try\n  {\n    readConfig(config, \"solarflux\", solarflux, Config::DEFAULT, \"1367\", \"solar flux constant in 1 AU [W/m**2]\");\n    readConfig(config, \"eclipse\",   eclipse,   Config::MUSTSET, \"\",     \"\");\n    readConfig(config, \"factor\",    factor,    Config::DEFAULT, \"1.0\",  \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    logWarningOnce<<\"MiscAccelerationsSolarRadiationPressure is DEPRECATDED since 2022-12-19. Use MiscAccelerationsRadiationPressure instead.\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d MiscAccelerationsSolarRadiationPressure::acceleration(SatelliteModelPtr satellite, const Time &time,\n                                                                      const Vector3d &position, const Vector3d &/*velocity*/,\n                                                                      const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    // from sun to satellite in SRF\n    Vector3d direction = rotSat.inverseRotate(position - ephemerides->position(time, Ephemerides::SUN));\n    const Double distanceSun = direction.normalize();\n    const Double AU = 149597870700.0;\n    const Double ny = eclipse ? eclipse->factor(time, position, ephemerides) : 1; // shadowing from Earth and Moon\n\n    Vector absorbedPressure(satellite->surfaces.size()); // power for each satellite surface\n    Vector3d F = MiscAccelerationsRadiationPressure::force(satellite, direction, ny*solarflux/LIGHT_VELOCITY*std::pow(AU/distanceSun,2), 0., absorbedPressure);\n\n    // compute thermal radition\n    for(UInt i=0; i<satellite->surfaces.size(); i++)\n    {\n      auto &surface = satellite->surfaces.at(i);\n      if(surface.specificHeatCapacity < 0)\n        F -= (2./3.) * surface.area * absorbedPressure(i) * surface.normal; // spontaneous reemission of absorbed radiation\n    }\n\n    return (factor/satellite->mass) * rotEarth.rotate(rotSat.rotate(F));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/noiseGenerator/noiseGenerator.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseGenerator.cpp\n*\n* @brief Generate different types of noise.\n*\n* @author Matthias Ellmer\n* @date 2013-09-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_NoiseGenerator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"classes/noiseGenerator/noiseGeneratorWhite.h\"\n#include \"classes/noiseGenerator/noiseGeneratorExpressionPSD.h\"\n#include \"classes/noiseGenerator/noiseGeneratorDigitalFilter.h\"\n#include \"classes/noiseGenerator/noiseGeneratorPowerLaw.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(NoiseGenerator, \"noiseGeneratorType\",\n                      NoiseGeneratorWhite,\n                      NoiseGeneratorExpressionPSD,\n                      NoiseGeneratorDigitalFilter,\n                      NoiseGeneratorPowerLaw)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(NoiseGenerator, \"noiseGeneratorType\")\n\n/***********************************************/\n\nNoiseGenerator::NoiseGenerator(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"generate different types of noise\"))\n    {\n      if(readConfigChoiceElement(config, \"white\",         type, \"white noise\"))\n        noiseGenerator.push_back(new NoiseGeneratorWhite(config));\n      if(readConfigChoiceElement(config, \"expressionPSD\", type, \"defined by one sided PSD\"))\n        noiseGenerator.push_back(new NoiseGeneratorExpressionPSD(config));\n      if(readConfigChoiceElement(config, \"filter\",        type, \"noise conforms to psd of filter\"))\n        noiseGenerator.push_back(new NoiseGeneratorDigitalFilter(config));\n      if(readConfigChoiceElement(config, \"powerLaw\",      type, \"noise follows power law relationship (f^alpha)\"))\n        noiseGenerator.push_back(new NoiseGeneratorPowerLaw(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nNoiseGenerator::~NoiseGenerator()\n{\n  for(UInt i=0; i<noiseGenerator.size(); i++)\n    delete noiseGenerator.at(i);\n}\n\n/***********************************************/\n\nMatrix NoiseGenerator::noise(UInt samples, UInt series) const\n{\n  try\n  {\n    Matrix sum(samples, series);\n    for(UInt i=0; i<noiseGenerator.size(); i++)\n      sum += noiseGenerator.at(i)->noise(samples, series);\n    return sum;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix NoiseGenerator::covarianceFunction(UInt length, Double sampling) const\n{\n  try\n  {\n    Vector sum(length);\n\n    for(UInt i=0; i<noiseGenerator.size(); i++)\n      sum += noiseGenerator.at(i)->covarianceFunction(length, sampling);\n\n    Matrix covariance(length,2);\n    for(UInt i=0; i<length; i++)\n      covariance(i,0) = i*sampling;\n\n    copy(sum, covariance.column(1));\n    return covariance;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/noiseGenerator/noiseGenerator.h",
    "content": "/***********************************************/\n/**\n* @file noiseGenerator.h\n*\n* @brief Generate different types of noise.\n*\n* @author Matthias Ellmer\n* @date 2013-09-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NOISEGENERATOR__\n#define __GROOPS_NOISEGENERATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_NoiseGenerator\nstatic const char *docstringNoiseGenerator = R\"(\n\\section{NoiseGenerator}\\label{noiseGeneratorType}\nThis class implements the generation of different types of noise.\nIt provides a generic interface that can be implemented by different\ntypes of generators. The characteristics of the generated noise\nis determined by the generators. See the appropriate documentation\nfor more information.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup noiseGeneratorGroup NoiseGenerator\n* @brief Generate different types of noise.\n* @ingroup classesGroup\n* The interface is given by @ref NoiseGenerator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass NoiseGenerator;\nclass NoiseGeneratorBase;\ntypedef std::shared_ptr<NoiseGenerator> NoiseGeneratorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Generate different types of noise.\n* An Instance of this class can be created by @ref readConfig. */\nclass NoiseGenerator\n{\npublic:\n/// Constructor\nNoiseGenerator(Config &config, const std::string &name);\n\n/// Destructor.\n~NoiseGenerator();\n\n/** @brief Generalized Matrix containing one or more columns of noise.\n* The type of noise, as well as details like correlations etc. are up to\n* the specific implementation.\n* @param samples number of noise samples to be returned (rows).\n* @param series  number of noise series to be returned (columns)*/\nMatrix noise(UInt samples, UInt series) const;\n\n/** @brief Realization of noise vector.\n* The type of noise, as well as details like correlations etc. are up to\n* the specific implementation.\n* @param samples number of noise samples to be returned. */\nVector noise(UInt samples) const {return noise(samples, 1);}\n\n/** @brief Covariance function of generated noise\n * @param length of the covariance function.\n * @param sampling of the time series in seconds.\n * @return @p length x 2 Matrix with time lag in first column and autocovariance in second */\nMatrix covarianceFunction(UInt length, Double sampling = 1) const;\n\n/** @brief creates an derived instance of this class. */\nstatic NoiseGeneratorPtr create(Config &config, const std::string &name) {return NoiseGeneratorPtr(new NoiseGenerator(config, name));}\n\nprivate:\n  std::vector<NoiseGeneratorBase*> noiseGenerator;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class NoiseGenerator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a noiseGenerator with zero noise is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] noiseGenerator Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates NoiseGenerator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, NoiseGeneratorPtr &noiseGenerator, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass NoiseGeneratorBase\n{\npublic:\n  virtual ~NoiseGeneratorBase() {}\n  virtual Matrix noise(UInt samples, UInt series) = 0;\n  virtual Vector covarianceFunction(UInt length, Double sampling = 1) = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/noiseGenerator/noiseGeneratorDigitalFilter.h",
    "content": "/***********************************************/\n/**\n* @file noiseGeneratorDigitalFilter.h\n*\n* @brief Generate noise using digital filter.\n* @see NoiseGenerator\n*\n* @author Matthias Ellmer\n* @date 2015-11-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NOISEGENERATORDIGITALFILTER__\n#define __GROOPS_NOISEGENERATORDIGITALFILTER__\n\n// Latex documentation\n#ifdef DOCSTRING_NoiseGenerator\nstatic const char *docstringNoiseGeneratorDigitalFilter = R\"(\n\\subsection{Filter}\nGenerated noise \\configClass{noise}{noiseGeneratorType} is\nfiltered by a \\configClass{filter}{digitalFilterType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/digitalFilter/digitalFilter.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate noise from PSD.\n * @ingroup noiseGeneratorGroup\n * @see NoiseGenerator */\nclass NoiseGeneratorDigitalFilter : public NoiseGeneratorBase\n{\n  DigitalFilterPtr  filter;\n  NoiseGeneratorPtr noisePtr;\n  UInt              warmup, over;\n\npublic:\n  NoiseGeneratorDigitalFilter(Config &config);\n  Matrix noise(UInt samples, UInt series);\n  Vector covarianceFunction(UInt length, Double sampling);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline NoiseGeneratorDigitalFilter::NoiseGeneratorDigitalFilter(Config &config)\n{\n  try\n  {\n    readConfig(config, \"filter\",             filter,   Config::MUSTSET,  \"\",  \"digital filter\");\n    readConfig(config, \"noise\",              noisePtr, Config::MUSTSET,  \"\",  \"Basis noise\");\n    readConfig(config, \"warmupEpochCount\",   warmup,   Config::DEFAULT,  \"0\", \"number of additional epochs at before start and after end\");\n    readConfig(config, \"overSamplingFactor\", over,     Config::DEFAULT,  \"1\", \"noise with multiple higher sampling -> filter -> decimate\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix NoiseGeneratorDigitalFilter::noise(UInt samples, UInt series)\n{\n  try\n  {\n    Matrix n = filter->filter(noisePtr->noise(over*samples+2*warmup, series));\n    Matrix e(samples, series);\n    for(UInt i=0; i<e.rows(); i++)\n      copy(n.row(warmup+i*over), e.row(i));\n    return e;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector NoiseGeneratorDigitalFilter::covarianceFunction(UInt length, Double sampling)\n{\n  try\n  {\n    auto frequencyResponse = filter->frequencyResponse(length*2);\n    Vector psdBase = Fourier::covariance2psd(noisePtr->covarianceFunction(length, sampling).column(1), sampling);\n    Vector psd(length);\n\n    for(UInt i=0; i<length; i++)\n      psd(i) = std::pow( std::abs(frequencyResponse.at(i)), 2) * psdBase(i);\n\n    return Fourier::psd2covariance(psd, sampling);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_NOISEGENERATORDIGITALFILTER__ */\n"
  },
  {
    "path": "source/classes/noiseGenerator/noiseGeneratorExpressionPSD.h",
    "content": "/***********************************************/\n/**\n* @file noiseGeneratorExpressionPSD.h\n*\n* @brief Generate noise defined by one sided PSD.\n* @see NoiseGenerator\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NOISEGENERATOREXPRESSIONPSD__\n#define __GROOPS_NOISEGENERATOREXPRESSIONPSD__\n\n// Latex documentation\n#ifdef DOCSTRING_NoiseGenerator\nstatic const char *docstringNoiseGeneratorExpressionPSD = R\"(\n\\subsection{ExpressionPSD}\nThis generator creates noise defined by a one sided PSD.\nThe \\config{psd} is an expression controlled by the variable 'freq'.\nTo determine the frequency \\config{sampling} must be given.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/fourier.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate noise defined by one sided PSD.\n * @ingroup noiseGeneratorGroup\n * @see NoiseGenerator */\nclass NoiseGeneratorExpressionPSD : public NoiseGeneratorBase\n{\n  NoiseGeneratorPtr     noisePtr;\n  ExpressionVariablePtr expression;\n  Double                sampling;\n\npublic:\n  NoiseGeneratorExpressionPSD(Config &config);\n  Matrix noise(UInt samples, UInt series);\n  Vector covarianceFunction(UInt length, Double sampling);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline NoiseGeneratorExpressionPSD::NoiseGeneratorExpressionPSD(Config &config)\n{\n  try\n  {\n    readConfig(config, \"noise\",    noisePtr,   Config::MUSTSET, \"\",  \"Basis noise\");\n    readConfig(config, \"psd\",      expression, Config::MUSTSET, \"1\", \"one sided PSD (variable: freq [Hz]) [unit^2/Hz]\");\n    readConfig(config, \"sampling\", sampling,   Config::MUSTSET, \"1\", \"to determine frequency [seconds]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix NoiseGeneratorExpressionPSD::noise(UInt samples, UInt series)\n{\n  try\n  {\n    // Fill the sequence wk with white Noise, second half needs to be zero for fourier padding\n    Matrix wk(2*samples, series);\n    copy(noisePtr->noise(samples, series), wk.row(0, samples));\n\n    Vector freq = Fourier::frequencies(wk.rows(), sampling);\n    Vector PSD(freq.rows());\n    VariableList varList;\n    for(UInt i=0; i<freq.rows(); i++)\n    {\n      varList.setVariable(\"freq\", freq(i));\n      PSD(i) = expression->evaluate(varList);\n      if(!std::isfinite(PSD(i)))\n        logWarning << \"Warning: PSD at frequency \"+freq(i) % \"%f [Hz] is \"s + PSD(i) % \"%f\"s << Log::endl;\n    }\n\n    // For each column, perform discrete Fourier transform, multiply the results and synthesize noise\n    Matrix noise(samples, series);\n    for(UInt k=0; k<series; k++)\n    {\n      auto Wk = Fourier::fft(Vector(wk.column(k))); // Complex Fourier transform\n      for(UInt i=0; i<PSD.rows(); i++)\n        Wk.at(i) *= std::sqrt(PSD(i));\n      copy(Fourier::synthesis(Wk, TRUE/*even*/).slice(0, samples), noise.column(k));\n    }\n\n    return noise;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector NoiseGeneratorExpressionPSD::covarianceFunction(UInt length, Double sampling)\n{\n\n  Vector freq = Fourier::frequencies(2*length, sampling);\n  Vector psd  = Fourier::covariance2psd(noisePtr->covarianceFunction(length, sampling).column(1), sampling);\n\n  VariableList varList;\n  for(UInt i=0; i<length; i++)\n  {\n    varList.setVariable(\"freq\", freq(i));\n    psd(i) *= expression->evaluate(varList);\n  }\n\n  return Fourier::psd2covariance(psd, sampling);\n}\n\n/***********************************************/\n#endif /* __GROOPS_NOISEGENERATOR__ */\n"
  },
  {
    "path": "source/classes/noiseGenerator/noiseGeneratorPowerLaw.h",
    "content": "/***********************************************/\n/**\n* @file noiseGeneratorPowerLaw.h\n*\n* @brief Generate noise following a power law relationship like 1/f^alpha.\n* @see NoiseGenerator\n*\n* @see Kasdin (1995): Discrete simulation of colored noise and stochastic processes and 1/f^alpha power law noise generation, Proceedings of the IEEE, Volume 83, Number 5, 1995, pages 802-827.\n* @see Kasdin (1992): Discrete simulation of power law noise [for oscillator stability evaluation]\n*\n* @author Matthias Ellmer\n* @date 2014-01-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NOISEGENERATORPOWERLAW__\n#define __GROOPS_NOISEGENERATORPOWERLAW__\n\n// Latex documentation\n#ifdef DOCSTRING_NoiseGenerator\nstatic const char *docstringNoiseGeneratorPowerLaw = R\"(\n\\subsection{PowerLaw}\nThis generator creates noise that conforms to a power law relationship, where the power\nof the noise at a frequency is proportional to $1/f^\\alpha$, with a typically between -2 and 2.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/fourier.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate noise following power law.\n * @ingroup noiseGeneratorGroup\n * @see NoiseGenerator */\nclass NoiseGeneratorPowerLaw : public NoiseGeneratorBase\n{\n  NoiseGeneratorPtr noisePtr;\n  Double alpha;\n\npublic:\n  NoiseGeneratorPowerLaw(Config &config);\n  Matrix noise(UInt samples, UInt series);\n  Vector covarianceFunction(UInt length, Double sampling);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline NoiseGeneratorPowerLaw::NoiseGeneratorPowerLaw(Config &config)\n{\n  try\n  {\n    readConfig(config, \"noise\", noisePtr, Config::MUSTSET, \"\",  \"Basis noise\");\n    readConfig(config, \"alpha\", alpha,    Config::MUSTSET, \"0\", \"Exponent of the power law relationship 1/f^alpha\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// This is a reimplemantation of the code given in [Kasdin,1995], Appendix 2\ninline Matrix NoiseGeneratorPowerLaw::noise(UInt samples, UInt series)\n{\n  try\n  {\n    // Fill the sequence wk with white Noise, second half padded with zeros\n    Matrix wk(2*samples, series);\n    copy(noisePtr->noise(samples, series), wk.row(0, samples));\n\n    // Generate coefficients hk in first half of vector, second half padded with zeros\n    Vector hk(2*samples);\n    hk(0) = 1.0;\n    for(UInt i=1; i<samples; i++)\n      hk(i) = hk(i-1) * (0.5*alpha+(i-1))/i;\n    auto Hk = Fourier::fft(hk);\n\n    // For each column, perform discrete Fourier transform, multiply the results and synthesize noise\n    Matrix noise(samples, series);\n    for(UInt i=0; i<series; i++)\n    {\n      auto Wk = Fourier::fft(wk.column(i));\n      for(UInt j=0; j<Wk.size(); j++)\n        Wk.at(j) *= Hk.at(j); // complex multiplication\n      copy(Fourier::synthesis(Wk, TRUE/*even*/).slice(0, samples), noise.column(i));\n    }\n\n    return noise;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NoiseGeneratorPowerLaw::covarianceFunction(UInt length, Double sampling)\n{\n  try\n  {\n    Vector freq = Fourier::frequencies(2*length, sampling);\n    Vector psd  = Fourier::covariance2psd(noisePtr->covarianceFunction(length, sampling).column(1), sampling);\n\n    // Skip zero frequency\n    // eq. 98 in [Kasdin,1995]\n    // I think it should be psd(i) = std::pow( freq(i) * (sigma*sigma), -alpha). Why it is not, I don't quite understand.\n    for(UInt i=1; i<length; i++)\n      psd(i) *= std::pow(2 * std::sin(PI * freq(i) * sampling), -alpha);\n\n    return Fourier::psd2covariance(psd, sampling);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_NOISEGENERATORPOWERLAW__ */\n"
  },
  {
    "path": "source/classes/noiseGenerator/noiseGeneratorWhite.h",
    "content": "/***********************************************/\n/**\n* @file noiseGeneratorWhite.h\n*\n* @brief Simple white noise.\n* @see NoiseGenerator\n*\n* @author Matthias Ellmer\n* @date 2013-09-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NOISEGENERATORWHITE__\n#define __GROOPS_NOISEGENERATORWHITE__\n\n// Latex documentation\n#ifdef DOCSTRING_NoiseGenerator\nstatic const char *docstringNoiseGeneratorWhite = R\"(\n\\subsection{White}\nThe noise is Gaussian with a standard deviation \\config{sigma}.\nThe noise is computed via a pseudo random sequence with a start value given\nby \\config{initRandom}. The same value always yields the same sequence.\nBe careful in \\reference{parallel}{general.parallelization} mode\nas all nodes generates the same pseudo random sequence.\nIf this value is set to zero a real random value is used as starting value.\n)\";\n#endif\n\n/***********************************************/\n\n#include <random>\n#include \"parallel/parallel.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simple white noise.\n * @ingroup noiseGeneratorGroup\n * @see NoiseGenerator */\nclass NoiseGeneratorWhite : public NoiseGeneratorBase\n{\n  std::mt19937_64 generator;\n  Double          sigma;\n\npublic:\n  NoiseGeneratorWhite(Config &config);\n  Matrix noise(UInt samples, UInt series);\n  Vector covarianceFunction(UInt length, Double sampling);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline NoiseGeneratorWhite::NoiseGeneratorWhite(Config &config)\n{\n  try\n  {\n    UInt start;\n\n    readConfig(config, \"sigma\",      sigma, Config::MUSTSET,  \"1.0\", \"standard deviation\");\n    readConfig(config, \"initRandom\", start, Config::DEFAULT,  \"0\",   \"start value for pseudo random sequence, 0: real random\");\n    if(isCreateSchema(config)) return;\n\n    if(start)\n      generator.seed(start);\n    else\n    {\n      std::random_device randomDevice;\n      generator.seed(randomDevice());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix NoiseGeneratorWhite::noise(UInt samples, UInt series)\n{\n  try\n  {\n    std::normal_distribution<Double> gaussian(0, sigma);\n    Matrix e(samples, series);\n    for(UInt i=0; i<e.rows(); i++)\n      for(UInt k=0; k<e.columns(); k++)\n        e(i,k) = gaussian(generator);\n    return e;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector NoiseGeneratorWhite::covarianceFunction(UInt length, Double /*sampling*/)\n{\n  Vector covariance(length);\n  covariance(0) = sigma*sigma;\n  return covariance;\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_NOISEGENERATORWHITE__ */\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquation.cpp",
    "content": "/***********************************************/\n/**\n* @file normalEquation.cpp\n*\n* @brief Systems of normal equations.\n* Creation, combination and solving of systems of normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_NormalEquation\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"parallel/parallel.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"normalEquationDesign.h\"\n#include \"normalEquationDesignVCE.h\"\n#include \"normalEquationFile.h\"\n#include \"normalEquationRegularization.h\"\n#include \"normalEquationRegularizationGeneralized.h\"\n#include \"normalEquation.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(NormalEquation, \"normalEquationType\",\n                      NormalEquationDesign,\n                      NormalEquationDesignVCE,\n                      NormalEquationFile,\n                      NormalEquationRegularization,\n                      NormalEquationRegularizationGeneralized)\n\nGROOPS_RENAMED_CLASS(normalequationType, normalEquationType, date2time(2020, 6, 3))\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(NormalEquation, \"normalEquationType\")\n\n/***********************************************/\n\nNormalEquation::NormalEquation(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string choice;\n    while(readConfigChoice(config, name, choice, Config::OPTIONAL, \"\", \"system of normal equations\"))\n    {\n      if(readConfigChoiceElement(config, \"design\",                    choice, \"from observation equations\"))\n        normalsComponent.push_back(new NormalEquationDesign(config));\n      if(readConfigChoiceElement(config, \"designVCE\",                 choice, \"from observation equations with variance component estimation per arc\"))\n        normalsComponent.push_back(new NormalEquationDesignVCE(config));\n      if(readConfigChoiceElement(config, \"file\",                      choice, \"read normal equations from file\"))\n        normalsComponent.push_back(new NormalEquationFile(config));\n      if(readConfigChoiceElement(config, \"regularization\",            choice, \"diagonal matrix\"))\n        normalsComponent.push_back(new NormalEquationRegularization(config));\n      if(readConfigChoiceElement(config, \"regularizationGeneralized\", choice, \"regularization with a sum of partial covariance matrices\"))\n        normalsComponent.push_back(new NormalEquationRegularizationGeneralized(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    };\n\n    status = UNKNOWN;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquation::init(UInt blockSize, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    status = UNKNOWN;\n\n    // determine dimension\n    UInt paraCount = 0;\n    UInt rhsCount  = 0;\n    for(auto component : normalsComponent)\n    {\n      paraCount = std::max(paraCount, component->parameterCount());\n      rhsCount  = std::max(rhsCount,  component->rightHandSideCount());\n    }\n    if((paraCount == 0) || (rhsCount == 0))\n      throw(Exception(\"Cannot determine dimension of normals\"));\n\n    // init distributed normal matrix\n    normals.initEmpty(MatrixDistributed::computeBlockIndex(paraCount, blockSize), comm);\n    n        = Matrix(paraCount, rhsCount);\n    lPl      = Vector(rhsCount);\n    obsCount = 0;\n    x        = Matrix(paraCount, rhsCount);\n    Wz       = Matrix(paraCount, 100);\n\n    // init normals components\n    for(auto component : normalsComponent)\n      component->init(normals, rhsCount);\n\n    status = INIT;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nNormalEquation::~NormalEquation()\n{\n  for(auto component : normalsComponent)\n    delete component;\n}\n\n/***********************************************/\n\nstd::vector<ParameterName> NormalEquation::parameterNames() const\n{\n  try\n  {\n    std::vector<ParameterName> names(parameterCount());\n    for(auto component : normalsComponent)\n      component->parameterNames(names);\n    return names;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquation::varianceComponentFactors() const\n{\n  std::vector<Double> s;\n  for(auto component : normalsComponent)\n  {\n    const std::vector<Double> s2 = component->varianceComponentFactors();\n    s.insert(s.end(), s2.begin(), s2.end());\n  }\n  return s;\n}\n\n/***********************************************/\n\nvoid NormalEquation::setApproximateSolution(const const_MatrixSlice &x0)\n{\n  try\n  {\n    if(status==UNKNOWN)\n      throw(Exception(\"NormalEquation is not initialized\"));\n\n    x = x0;\n    Parallel::broadCast(x, 0, normals.communicator());\n\n    if((x.rows() != n.rows()) || (x.columns() != n.columns()))\n      throw(Exception(\"dimension error\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool NormalEquation::build(UInt rightHandSide)\n{\n  try\n  {\n    if(status==UNKNOWN)\n      throw(Exception(\"NormalEquation is not initialized\"));\n\n    rhsNo = rightHandSide;\n    Parallel::broadCast(rhsNo, 0, normals.communicator());\n\n    // accumulate normals\n    normals.setNull();\n    n.setNull();\n    lPl.setNull();\n    obsCount = 0;\n\n    Bool ready = TRUE;\n    for(auto component : normalsComponent)\n      ready = component->addNormalEquation(rhsNo, x, Wz, normals, n, lPl, obsCount) && ready;\n\n    status = NORMAL;\n    return ready || (varianceComponentFactors().rows() == 1); // if only one sigma -> iteration is not needed\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquation::write(const FileName &fileName)\n{\n  try\n  {\n    if(status!=NORMAL)\n      build(rhsNo);\n\n    NormalEquationInfo info(parameterNames(), lPl, observationCount());\n    writeFileNormalEquation(fileName, info, normals, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix NormalEquation::solve()\n{\n  try\n  {\n    if(status!=NORMAL)\n      build(rhsNo);\n\n    // regularize not used parameters\n    for(UInt i=0; i<normals.blockCount(); i++)\n      if(normals.isMyRank(i,i))\n      {\n        Matrix &N = normals.N(i,i);\n        for(UInt k=0; k<N.rows(); k++)\n          if(N(k,k) == 0.)\n          {\n            N(k,k) += 1.0;\n            logWarning<<normals.blockIndex(i)+k<<\". parameter has zero diagonal element -> set to one\"<<Log::endl;\n          }\n      }\n\n    x = normals.solve(n, TRUE/*timing*/);\n    Parallel::broadCast(x, 0, normals.communicator());\n\n    // N contains now the cholesky decomposition\n    Wz = Vce::monteCarlo(x.rows(), 100);\n    normals.triangularSolve(Wz);\n    Parallel::broadCast(Wz, 0, normals.communicator());\n\n    status = CHOLESKY;\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble NormalEquation::aposterioriSigma()\n{\n  try\n  {\n    Double s;\n    if(Parallel::isMaster(normals.communicator()))\n      s = std::sqrt((lPl(rhsNo) - inner(x.column(rhsNo), n.column(rhsNo))) / (observationCount() - x.rows()));\n    Parallel::broadCast(s, 0, normals.communicator());\n    return s;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquation::sigmaParameter()\n{\n  try\n  {\n    if(status != CHOLESKY)\n      solve();\n\n    Double sigma = aposterioriSigma();\n    if((sigma <= 0) || std::isnan(sigma))\n    {\n      logWarningOnce<<\"sigma = \"<<sigma<<\" not applied to covariance matrix\"<<Log::endl;\n      sigma = 1.;\n    }\n\n    normals.choleskyInverse();\n    Vector diagonal = Vector(normals.dimension());\n    for(UInt i=0; i<normals.blockCount(); i++)\n    {\n      if(normals.isMyRank(i,i))\n      {\n        Matrix &N = normals.N(i,i);\n        for(UInt z=0; z<N.rows(); z++)\n          diagonal(normals.blockIndex(i)+z) += quadsum(N.slice(z,z,1,N.columns()-z));\n      }\n      for(UInt k=i+1; k<normals.blockCount(); k++)\n        if(normals.isMyRank(i,k))\n        {\n          Matrix &N = normals.N(i,k);\n          for(UInt z=0; z<N.rows(); z++)\n            diagonal(normals.blockIndex(i)+z) += quadsum(N.row(z));\n        }\n    }\n    Parallel::reduceSum(diagonal, 0, normals.communicator());\n    Parallel::broadCast(diagonal, 0, normals.communicator());\n    for(UInt i=0; i<diagonal.rows(); i++)\n      diagonal(i) = std::sqrt(diagonal(i));\n\n    status = INVERSECHOLESKY;\n    return sigma * diagonal;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquation::writeCovariance(const FileName &fileName)\n{\n  try\n  {\n    if(status != INVERSE)\n    {\n      if(status != INVERSECHOLESKY)\n        sigmaParameter();\n      normals.choleskyProduct();\n    }\n\n    Double sigma = aposterioriSigma();\n    if((sigma <= 0) || std::isnan(sigma))\n    {\n      logWarningOnce<<\"sigma = \"<<sigma<<\" not applied to covariance matrix\"<<Log::endl;\n      sigma = 1.;\n    }\n\n    for(UInt i=0; i<normals.blockCount(); i++)\n      for(UInt k=i; k<normals.blockCount(); k++)\n        if(normals.isMyRank(i,k))\n          writeFileMatrix(fileName.appendBaseName((normals.blockCount()>1) ? \".\"+i%\"%02i-\"s+k%\"%02i\"s : \"\"s), sigma*sigma * normals.N(i,k));\n\n    status = INVERSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix NormalEquation::contribution()\n{\n  try\n  {\n    if(status != INVERSE)\n    {\n      if(status != INVERSECHOLESKY)\n        sigmaParameter();\n      normals.choleskyProduct();\n      status = INVERSE;\n    }\n\n    Matrix x(normals.dimension(), normalsComponent.size());\n    for(UInt i=0; i<normalsComponent.size(); i++)\n      copy(normalsComponent.at(i)->contribution(normals), x.column(i));\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquation.h",
    "content": "/***********************************************/\n/**\n* @file normalEquation.h\n*\n* @brief Systems of normal equations.\n* Creation, combination and solving of systems of normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALEQUATION__\n#define __GROOPS_NORMALEQUATION__\n\n// Latex documentation\n#ifdef DOCSTRING_NormalEquation\nstatic const char *docstringNormalEquation = R\"(\n\\section{NormalEquation}\\label{normalEquationType}\nThis class provides a system of normal equations.\nThis total system is the weighted sum of individual normals.\n\\begin{equation}\n \\M N_{total} =  \\sum_{k=1} \\frac{1}{\\sigma_k^2}\\M N_k\n \\qquad\\text{and}\\qquad\n\\M n_{total} = \\sum_{k=1} \\frac{1}{\\sigma_k^2} \\M n_k.\n\\end{equation}\nThe normals do not need to have the same dimension. The dimension\nof the total combined system is chosen to cover all individual systems.\nFor each normal a \\config{startIndex} is required which indicates\nthe position of the first unknown of the individual normal within the\ncombined parameter vector.\n\nThe $\\sigma_k$ of the relative weights are defined by \\config{aprioriSigma}\nin a first step. If an apriori solution \\configFile{inputfileApproxSolution}{matrix} is\ngiven or the normals are solved iteratively the weights are determined by means\nof variance compoment estimation (VCE), see \\program{NormalsSolverVCE}:\n\\begin{equation}\n\\sigma_k^2 =\n\\frac{\\M e_k^T\\M P\\M e_k}\n{n_k-\\frac{1}{\\sigma_k^2}\\text{trace}\\left(\\M N_k\\M N_{total}^{-1}\\right)},\n\\end{equation}\nwhere $n_k$ is the number of observations. The square sum of the residuals\nis calculated by\n\\begin{equation}\n\\M e_k^T\\M P\\M e_k = \\M x^T\\M N_k\\M x - 2\\M n_k^T\\M x + \\M l_k^T\\M P_k\\M l_k.\n\\end{equation}\nThe system of normal equations can be solved with several right hand sides at once. But\nonly one right hand side, which can be selected with the index \\config{rightHandSide}\n(counting from zero), can be used to compute the variance factors.\nThe combined normal $\\M N_{total}$ and the solution $\\M x$ are taken from the previous\niteration step. In case of \\configClass{DesignVCE}{normalEquationType:designVCE} the algorithm\nis a little bit different as described below.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"inputOutput/fileName.h\"\n#include \"config/config.h\"\n#include \"parallel/matrixDistributed.h\"\n\n/**\n* @defgroup normalEquationGroup NormalEquation\n* @brief Systems of normal equations.\n* @ingroup classesGroup\n* The interface is given by @ref NormalEquation. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass NormalEquation;\nclass NormalEquationBase;\ntypedef std::shared_ptr<NormalEquation> NormalEquationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Systems of normal equations.\n* Creation, combination and solving of systems of normal equations.\n* An Instance of this class can be created by @ref readConfig. */\nclass NormalEquation\n{\nprivate:\n  enum Status {UNKNOWN, INIT, NORMAL, CHOLESKY, INVERSECHOLESKY, INVERSE};\n  Status            status;\n  UInt              rhsNo;\n  MatrixDistributed normals;\n  Matrix            n;        // right hand sides (at master)\n  Vector            lPl;      // Norm of the observations\n  UInt              obsCount;\n  Matrix            Wz;       // Monte-Carlo-vector\n  Matrix            x;        // current solution\n\n  std::vector<NormalEquationBase*> normalsComponent;\n\npublic:\n  /// Constructor.\n  NormalEquation(Config &config, const std::string &name);\n\n  /// Destructor.\n  virtual ~NormalEquation();\n\n  /** @brief Init systems of normal equations.\n  * @param blockSize normal matrix is divided into blocks, (0: only one block).\n  * @param comm normal matrix is distributed over processes.  */\n  void init(UInt blockSize, Parallel::CommunicatorPtr comm);\n\n  /** @brief Number of unknown parameters.\n  * Dimension of the normal matrix N. */\n  UInt parameterCount() const {return normals.parameterCount();}\n\n  /** @brief Count of the observation vectors on the right hand side.\n  * Columns of the right hand side n. */\n  UInt rightHandSideCount() const {return n.columns();}\n\n  /** @brief Total count of observations.\n  * This includes pseudo observations by the regularization. */\n  UInt observationCount() const {return obsCount;}\n\n  /** @brief Names of the unknown parameters. */\n  std::vector<ParameterName> parameterNames() const;\n\n  /** @brief Variance factors of the different normal equations systems.\n  * Estimated with Variance Component Estimation (VCE). */\n  Vector varianceComponentFactors() const;\n\n  /** @brief Set approximate solution.\n  * To speed up the iterative Variance Component Estimation (VCE). */\n  void setApproximateSolution(const const_MatrixSlice &x0);\n\n  /** @name Status\n  * @brief The following functions changes the state of this class.\n  * Optimal performance is only given if the functions are called in a specific state.\n  * The expected state and the state after the call are given in brackets.\n  * (expected state -> state after call). */\n  //@{\n\n  /** @brief Accumulate normal equations.\n  * The weight of the different normal equation systems are computed\n  * in terms of Variance Component Estimation (VCE).\n  * This is an iterative process as it depends on residuals which depend on the solution.\n  * If convergence is reached TRUE is returned.\n  * Change of state of this class: (->NORMAL). */\n  Bool build(UInt rightHandSide=0);\n\n  /** @brief Write systems of normal equations to file.\n  * Change of state of this class: (NORMAL -> NORMAL). */\n  void write(const FileName &name);\n\n  /** @brief Solve the system of normal equations.\n  * Change of state of this class: (NORMAL -> CHOLESKY).\n  * @return Solution vector as columns of the matrix. */\n  Matrix solve();\n\n  /** @brief A posteriori sigma.\n  * Change of state of this class: (CHOLESKY -> CHOLESKY). */\n  Double aposterioriSigma();\n\n  /** @brief Inverse of the combined normal matrix.\n  * The posteriori sigma is applied if possible.\n  * Change of state of this class: (CHOLESKY -> CHOLESKYINVERSE).\n  * @return Accuracy of the solution (Square root of the diagonals of the inverse). */\n  Vector sigmaParameter();\n\n  /** @brief Write variance/covariance matrix.\n  * Change of state of this class: (CHOLESKYINVERSE -> INVERSE). */\n  void writeCovariance(const FileName &name);\n\n  /** @brief Contribution of normal equation components.\n  * Each column of the returned matrix contains the contribution\n  * of the normal equation component to the solution.\n  * The sum of the elements in each row is one.\n  * Change of state of this class: (INVERSE -> INVERSE).\n  * @return contribution vectors as coulumns of a matrix */\n  Matrix contribution();\n  //@}\n\n  /** @brief creates an derived instance of this class. */\n  static NormalEquationPtr create(Config &config, const std::string &name) {return NormalEquationPtr(new NormalEquation(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class NormalEquation.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and class with empty normals is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] normalEquation Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates NormalEquation */\ntemplate<> Bool readConfig(Config &config, const std::string &name, NormalEquationPtr &normalEquation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass NormalEquationBase\n{\npublic:\n  virtual ~NormalEquationBase() {}\n\nprotected:\n  virtual UInt   rightHandSideCount() const = 0;\n  virtual UInt   parameterCount()     const = 0;\n  virtual void   parameterNames(std::vector<ParameterName> &name) const = 0;\n  virtual void   init(MatrixDistributed &normals, UInt rhsCount) = 0;\n  virtual Bool   addNormalEquation(UInt rightHandSide, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                                   MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) = 0;\n  virtual Vector contribution(MatrixDistributed &Cov) = 0;\n  virtual std::vector<Double> varianceComponentFactors() const = 0;\n\n  friend class NormalEquation;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_NORMALEQUATION__ */\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationDesign.cpp",
    "content": "/***********************************************/\n/**\n* @file normalEquationDesign.cpp\n*\n* @brief Accumulate normals from observation equations.\n* @f[ N = A^TPA,\\quad n=A^TPl @f]\n* @see NormalEquation\n* @see Observation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"parallel/parallel.h\"\n#include \"files/fileArcList.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n#include \"classes/normalEquation/normalEquationDesign.h\"\n\n/***********************************************/\n\nNormalEquationDesign::NormalEquationDesign(Config &config)\n{\n  try\n  {\n    FileName fileNameArcList;\n\n    renameDeprecatedConfig(config, \"arcList\", \"inputfileArcList\", date2time(2020, 7, 7));\n\n    readConfig(config, \"observation\",      observation,     Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"aprioriSigma\",     sigma2,          Config::DEFAULT,  \"1.0\", \"\");\n    readConfig(config, \"startIndex\",       startIndex,      Config::DEFAULT,  \"0\",   \"add this normals at index of total matrix (counting from 0)\");\n    readConfig(config, \"inputfileArcList\", fileNameArcList, Config::OPTIONAL, \"\",    \"to accelerate computation\");\n    if(isCreateSchema(config)) return;\n\n\n    intervals = {0, observation->arcCount()};\n    if(!fileNameArcList.empty())\n    {\n      std::vector<Time> timesInterval;\n      readFileArcList(fileNameArcList, intervals, timesInterval);\n    }\n\n    sigma2   *= sigma2;\n    sigma2New = sigma2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationDesign::parameterNames(std::vector<ParameterName> &names) const\n{\n  try\n  {\n    std::vector<ParameterName> baseNames;\n    observation->parameterName(baseNames);\n\n    for(UInt i=0; i<baseNames.size(); i++)\n      if(!names.at(i+startIndex).combine(baseNames.at(i)))\n        logWarningOnce<<\"Parameter names do not match at index \"<<i+startIndex<<\": '\"<<names.at(i+startIndex).str()<<\"' != '\"<<baseNames.at(i).str()<<\"'\"<< Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationDesign::init(MatrixDistributed &/*normals*/, UInt rhsCount)\n{\n  try\n  {\n    if(rhsCount != observation->rightSideCount())\n      throw(Exception(\"number of right hand sides must agree (\"+rhsCount%\"%i != \"s+observation->rightSideCount()%\"%i)\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool NormalEquationDesign::addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                                             MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount)\n{\n  try\n  {\n    if(!observation->parameterCount())\n      return TRUE;\n\n\n    const UInt blockStart = normals.index2block(startIndex);\n    const UInt blockEnd   = normals.index2block(startIndex+observation->parameterCount()-1);\n    for(UInt i=blockStart; i<=blockEnd; i++)\n      for(UInt k=i; k<=blockEnd; k++)\n      {\n        normals.setBlock(i, k);\n        normals.N(i,k) = (i==k) ? Matrix(normals.blockSize(i), Matrix::SYMMETRIC) : Matrix(normals.blockSize(i), normals.blockSize(k));\n      }\n\n    // compute observation equations\n    // -----------------------------\n    sigma2   = sigma2New;\n    obsCount = 0;\n    Double      ePe        = 0;\n    Double      redundancy = 0;\n    MatrixSlice x0(x.slice(startIndex, rhsNo, observation->parameterCount(), 1));\n    MatrixSlice Wz0(Wz.row(startIndex, observation->parameterCount()));\n\n    logStatus<<\"accumulate normals from observation equations\"<<Log::endl;\n    Parallel::forEachInterval(observation->arcCount(), intervals, [&](UInt arcNo)\n    {\n      // observation equations\n      Matrix l, A, B;\n      observation->observation(arcNo, l, A, B);\n      if(l.rows()==0)\n        return;\n\n      // if equations are orthogonal transformed\n      // additional residuals appended to l\n      Matrix l2;\n      if(l.rows()>A.rows())\n      {\n        l2 = l.row(A.rows(), l.rows()-A.rows());\n        l  = l.row(0, A.rows());\n      }\n\n      // eliminate arc related parameters\n      if(B.size())\n        eliminationParameter(B,A,l);\n\n      // right hand side\n      // ---------------\n      matMult(1/sigma2, A.trans(), l, n);\n      for(UInt i=0; i<l.columns(); i++)\n        lPl(i) += quadsum(l.column(i)) + quadsum(l2.column(i))/sigma2;\n      obsCount   += l.rows() + l2.rows();\n      ePe        += (quadsum(l.column(rhsNo) - A*x0) + quadsum(l2.column(rhsNo)))/sigma2;\n      redundancy += l.rows() - quadsum(A*Wz0)/sigma2;\n\n      // accumulate normals\n      // ------------------\n      for(UInt i=blockStart; i<=blockEnd; i++)\n      {\n        const UInt idxN1 = (normals.blockIndex(i) < startIndex) ? (startIndex-normals.blockIndex(i)) : 0;\n        const UInt idxA1 = (normals.blockIndex(i) < startIndex) ? 0 : (normals.blockIndex(i)-startIndex);\n        const UInt cols1 = std::min(normals.blockSize(i)-idxN1, A.columns()-idxA1);\n        rankKUpdate(1/sigma2, A.column(idxA1, cols1), normals.N(i,i).slice(idxN1, idxN1, cols1, cols1));\n        for(UInt k=i+1; k<=blockEnd; k++)\n        {\n          const UInt idxN2 = (normals.blockIndex(k) < startIndex) ? (startIndex-normals.blockIndex(k)) : 0;\n          const UInt idxA2 = (normals.blockIndex(k) < startIndex) ? 0 : (normals.blockIndex(k)-startIndex);\n          const UInt cols2 = std::min(normals.blockSize(k)-idxN1, A.columns()-idxA1);\n          matMult(1/sigma2, A.column(idxA1, cols1).trans(), A.column(idxA2, cols2), normals.N(i,k).slice(idxN1, idxN2, cols1, cols2));\n        }\n      }\n    }, normals.communicator());\n\n    normals.reduceSum(FALSE);\n    Parallel::reduceSum(n,        0, normals.communicator());\n    Parallel::reduceSum(lPl,      0, normals.communicator());\n    Parallel::reduceSum(obsCount, 0, normals.communicator());\n\n    UInt ready = 0;\n    if(quadsum(x0) > 0)\n    {\n      Parallel::reduceSum(ePe,        0, normals.communicator());\n      Parallel::reduceSum(redundancy, 0, normals.communicator());\n      sigma2New = ePe/redundancy;\n      ready = (std::fabs(sqrt(sigma2New)-std::sqrt(sigma2))/std::sqrt(sigma2New) < 0.01);\n      Parallel::broadCast(sigma2New, 0, normals.communicator());\n      Parallel::broadCast(ready,     0, normals.communicator());\n    }\n\n    return ready;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquationDesign::contribution(MatrixDistributed &Cov)\n{\n  try\n  {\n    logWarningOnce<<\"In NormalEquationDesign: contribution is not implemented\"<<Log::endl;\n    return Vector(Cov.dimension());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationDesign.h",
    "content": "/***********************************************/\n/**\n* @file normalEquationDesign.h\n*\n* @brief Accumulate normals from observation equations.\n* @f[ N = A^TPA,\\quad n=A^TPl @f]\n* @see NormalEquation\n* @see Observation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALEQUATIONDESIGN__\n#define __GROOPS_NORMALEQUATIONDESIGN__\n\n// Latex documentation\n#ifdef DOCSTRING_NormalEquation\nstatic const char *docstringNormalEquationDesign = R\"(\n\\subsection{Design}\\label{normalEquationType:design}\nThis class acculumates normal equations from observation equations.\nThe class \\configClass{observation}{observationType} computes\nthe linearized and decorrelated equation system for each arc $i$:\n\\begin{equation}\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i.\n\\end{equation}\nThe arc depending parameters~$\\M y_i$ are eliminated and the system of normal\nequations is acculumated according to\n\\begin{equation}\n \\M N = \\sum_{i=1}^m \\M A_i^T  \\M A_i\n \\qquad\\text{and}\\qquad\n\\M n = \\sum_{i=1}^m \\M A_i^T \\M l_i.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/observation/observation.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accumulate normals from observation equations.\n* @ingroup normalEquationGroup\n* @f[ N = A^TPA,\\quad n=A^TPl @f]\n* @see NormalEquation\n* @see Observation */\nclass NormalEquationDesign : public NormalEquationBase\n{\n  UInt              startIndex;\n  std::vector<UInt> intervals;\n  ObservationPtr    observation;\n  Double            sigma2, sigma2New;\n\npublic:\n  NormalEquationDesign(Config &config);\n\n  UInt   rightHandSideCount() const override {return observation->rightSideCount();}\n  UInt   parameterCount()     const override {return observation->parameterCount() + startIndex;}\n  void   parameterNames(std::vector<ParameterName> &names) const override;\n  void   init(MatrixDistributed &normals, UInt rhsCount) override;\n  Bool   addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                           MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) override;\n  Vector contribution(MatrixDistributed &Cov) override;\n  std::vector<Double> varianceComponentFactors() const override {return std::vector<Double>({sigma2});}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationDesignVCE.cpp",
    "content": "/***********************************************/\n/**\n* @file normalEquationDesignVCE.cpp\n*\n* @brief Accumulate normals from observation equations.\n* With individual weights of each arc by variance component estimation.\n* @f[ N = A^TPA,\\quad n=A^TPl @f]\n* @see NormalEquation\n* @see Observation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"parallel/parallel.h\"\n#include \"files/fileArcList.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n#include \"classes/normalEquation/normalEquationDesignVCE.h\"\n\n/***********************************************/\n\nNormalEquationDesignVCE::NormalEquationDesignVCE(Config &config)\n{\n  try\n  {\n    FileName fileNameArcList;\n\n    renameDeprecatedConfig(config, \"arcList\", \"inputfileArcList\", date2time(2020, 7, 7));\n\n    readConfig(config, \"observation\",      observation,     Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startIndex\",       startIndex,      Config::DEFAULT,  \"0\", \"add this normals at index of total matrix (counting from 0)\");\n    readConfig(config, \"inputfileArcList\", fileNameArcList, Config::OPTIONAL, \"\", \"to accelerate computation\");\n    if(isCreateSchema(config)) return;\n\n    intervals = {0, observation->arcCount()};\n    if(!fileNameArcList.empty())\n    {\n      std::vector<Time> timesInterval;\n      readFileArcList(fileNameArcList, intervals, timesInterval);\n    }\n\n    iter     = 0;\n    sigma2.resize(observation->arcCount(), 1.0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationDesignVCE::parameterNames(std::vector<ParameterName> &names) const\n{\n  try\n  {\n    std::vector<ParameterName> baseNames;\n    observation->parameterName(baseNames);\n\n    for(UInt i=0; i<baseNames.size(); i++)\n      if(!names.at(i+startIndex).combine(baseNames.at(i)))\n        logWarningOnce<<\"Parameter names do not match at index \"<<i+startIndex<<\": '\"<<names.at(i+startIndex).str()<<\"' != '\"<<baseNames.at(i).str()<<\"'\"<< Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationDesignVCE::init(MatrixDistributed &/*normals*/, UInt rhsCount)\n{\n  try\n  {\n    if(rhsCount != observation->rightSideCount())\n      throw(Exception(\"number of right hand sides must agree (\"+rhsCount%\"%i != \"s+observation->rightSideCount()%\"%i)\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool NormalEquationDesignVCE::addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                                                MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount)\n{\n  try\n  {\n    if(!observation->parameterCount())\n      return TRUE;\n\n    const UInt blockStart = normals.index2block(startIndex);\n    const UInt blockEnd   = normals.index2block(startIndex+observation->parameterCount()-1);\n    for(UInt i=blockStart; i<=blockEnd; i++)\n      for(UInt k=i; k<=blockEnd; k++)\n      {\n        normals.setBlock(i, k);\n        normals.N(i,k) = (i==k) ? Matrix(normals.blockSize(i), Matrix::SYMMETRIC) : Matrix(normals.blockSize(i), normals.blockSize(k));\n      }\n\n    // compute observation equations\n    // -----------------------------\n    logStatus<<\"accumulate normals from observation equations\"<<Log::endl;\n    Vector x0  = x.slice(startIndex, rhsNo, observation->parameterCount(), 1);\n    Matrix Wz0 = Wz.row(startIndex, observation->parameterCount());\n\n    Parallel::forEachInterval(sigma2, intervals, [&](UInt arcNo) -> Double\n    {\n      // observation equations\n      Matrix l, A, B;\n      observation->observation(arcNo, l, A, B);\n      if(l.rows()==0)\n        return 0;\n\n      // if equations are orthogonal transformed\n      // additional residuals appended to l\n      Matrix l2;\n      if(l.rows()>A.rows())\n      {\n        l2 = l.row(A.rows(), l.rows()-A.rows());\n        l  = l.row(0, A.rows());\n      }\n\n      // eliminate arc related parameters\n      if(B.size())\n        eliminationParameter(B,A,l);\n\n      // Partial redundancy\n      // trace(A'A*N^(-1)) = trace(A'A*W^(-1)*W^(-T))\n      //                   = z'*W^(-1)*A'*A*W^(-T)*z (MonteCarlo trace estimation)\n      const Double r      = l.rows() + l2.rows() - quadsum(A*Wz0)/sigma2.at(arcNo);\n      const Double sigma2 = (quadsum(l.column(rhsNo)-A*x0) + quadsum(l2.column(rhsNo)))/r;\n\n      // right hand side\n      // ---------------\n      matMult(1./sigma2, A.trans(),l, n);\n      for(UInt i=0; i<l.columns(); i++)\n        lPl(i) += (quadsum(l.column(i))+quadsum(l2.column(i)))/sigma2;\n      obsCount += l.rows() + l2.rows();\n\n      // accumulate normals\n      // ------------------\n      for(UInt i=blockStart; i<=blockEnd; i++)\n      {\n        const UInt idxN1 = (normals.blockIndex(i) < startIndex) ? (startIndex-normals.blockIndex(i)) : 0;\n        const UInt idxA1 = (normals.blockIndex(i) < startIndex) ? 0 : (normals.blockIndex(i)-startIndex);\n        const UInt cols1 = std::min(normals.blockSize(i)-idxN1, A.columns()-idxA1);\n        rankKUpdate(1/sigma2, A.column(idxA1, cols1), normals.N(i,i).slice(idxN1, idxN1, cols1, cols1));\n        for(UInt k=i+1; k<=blockEnd; k++)\n        {\n          const UInt idxN2 = (normals.blockIndex(k) < startIndex) ? (startIndex-normals.blockIndex(k)) : 0;\n          const UInt idxA2 = (normals.blockIndex(k) < startIndex) ? 0 : (normals.blockIndex(k)-startIndex);\n          const UInt cols2 = std::min(normals.blockSize(k)-idxN1, A.columns()-idxA1);\n          matMult(1/sigma2, A.column(idxA1, cols1).trans(), A.column(idxA2, cols2), normals.N(i,k).slice(idxN1, idxN2, cols1, cols2));\n        }\n      }\n\n      return sigma2;\n    }, normals.communicator());\n\n    normals.reduceSum(FALSE);\n    Parallel::reduceSum(n,        0, normals.communicator());\n    Parallel::reduceSum(lPl,      0, normals.communicator());\n    Parallel::reduceSum(obsCount, 0, normals.communicator());\n    Parallel::broadCast(sigma2,   0, normals.communicator());\n\n    return (++iter >= 3); // ready after 2 iterations\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquationDesignVCE::contribution(MatrixDistributed &Cov)\n{\n  try\n  {\n    logWarningOnce<<\"In NormalEquationDesignVCE: contribution is not implemented\"<<Log::endl;\n    return Vector(Cov.dimension());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationDesignVCE.h",
    "content": "/***********************************************/\n/**\n* @file normalEquationDesignVCE.h\n*\n* @brief Accumulate normals from observation equations.\n* With individual weights of each arc by variance component estimation.\n* @f[ N = A^TPA,\\quad n=A^TPl @f]\n* @see NormalEquation\n* @see Observation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALEQUATIONDESIGNVCE__\n#define __GROOPS_NORMALEQUATIONDESIGNVCE__\n\n// Latex documentation\n#ifdef DOCSTRING_NormalEquation\nstatic const char *docstringNormalEquationDesignVCE = R\"(\n\\subsection{DesignVCE}\\label{normalEquationType:designVCE}\nThis class acculumates normal equations from observation equations.\nThe class \\configClass{observation}{observationType} computes\nthe linearized and decorrelated equation system for each arc $i$:\n\\begin{equation}\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i.\n\\end{equation}\nThe arc depending parameters~$\\M y_i$ are eliminated and the system of normal\nequations is acculumated according to\n\\begin{equation}\n \\M N =  \\sum_{i=1} \\frac{1}{\\sigma_i^2}\\M A_i^T  \\M A_i\n \\qquad\\text{and}\\qquad\n\\M n = \\sum_{i=1} \\frac{1}{\\sigma_i^2} \\M A_i^T \\M l_i.\n\\end{equation}\nThe variance $\\sigma_i^2$ of each individual arc is determined by\n\\begin{equation}\n\\sigma_i^2 =\n\\frac{(\\M l_i-\\M A_i\\M x)^T(\\M l_i-\\M A_i\\M x)}\n{n_i-\\frac{1}{\\sigma_i^2}\\text{trace}\\left(\\M A_i^T  \\M A_i\\M N_{total}^{-1}\\right)},\n\\end{equation}\nwhere $n_i$ is the number of observations. If an apriori solution is not given at the first\niteration step a zero vector is assumed.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/observation/observation.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accumulate normals from observation equations.\n* @ingroup normalEquationGroup\n* With individual weights of each arc by variance component estimation.\n* @f[ N = A^TPA,\\quad n=A^TPl @f]\n* @see NormalEquation\n* @see Observation */\nclass NormalEquationDesignVCE : public NormalEquationBase\n{\n  UInt                 iter;\n  UInt                 startIndex;\n  std::vector<Double>  sigma2;\n  ObservationPtr       observation;\n  std::vector<UInt>    intervals;\n\npublic:\n  NormalEquationDesignVCE(Config &config);\n\n  UInt   rightHandSideCount() const override {return observation->rightSideCount();}\n  UInt   parameterCount()     const override {return observation->parameterCount() + startIndex;}\n  void   parameterNames(std::vector<ParameterName> &names) const override;\n  void   init(MatrixDistributed &normals, UInt rhsCount) override;\n  Bool   addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                           MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) override;\n  Vector contribution(MatrixDistributed &Cov) override;\n  std::vector<Double> varianceComponentFactors() const override {return sigma2;}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationFile.cpp",
    "content": "/***********************************************/\n/**\n* @file normalEquationFile.cpp\n*\n* @brief Read normals from file.\n* @see NormalEquation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"parallel/parallel.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n#include \"classes/normalEquation/normalEquationFile.h\"\n\n/***********************************************/\n\nNormalEquationFile::NormalEquationFile(Config &config)\n{\n  try\n  {\n    Double sigma;\n\n    renameDeprecatedConfig(config, \"inputfileNormalequation\", \"inputfileNormalEquation\", date2time(2020, 6, 3));\n\n    readConfig(config, \"inputfileNormalEquation\", fileName,   Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"aprioriSigma\",            sigma,      Config::DEFAULT,  \"1.0\", \"\");\n    readConfig(config, \"startIndex\",              startIndex, Config::DEFAULT,  \"0\",   \"add this normals at index of total matrix (counting from 0)\");\n    if(isCreateSchema(config)) return;\n\n    NormalEquationInfo info;\n    Matrix             n;\n    readFileNormalEquation(fileName, info, n);\n    lPl       = info.lPl;\n    rhsCount  = n.columns();\n    paraCount = n.rows();\n    obsCount  = info.observationCount;\n    names     = info.parameterName;\n    sigma2    = sigma * sigma;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationFile::parameterNames(std::vector<ParameterName> &names) const\n{\n  try\n  {\n    for(UInt i=0; i<this->names.size(); i++)\n      if(!names.at(i+startIndex).combine(this->names.at(i)))\n        logWarningOnce<<\"Parameter names do not match at index \"<<i+startIndex<<\": '\"<<names.at(i+startIndex).str()<<\"' != '\"<<this->names.at(i).str()<<\"'\"<< Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationFile::init(MatrixDistributed &normalsTotal, UInt rhsCount)\n{\n  try\n  {\n    NormalEquationInfo info;\n    readFileNormalEquation(fileName, info, normals, n, normalsTotal.communicator());\n    if(!Parallel::isMaster(normalsTotal.communicator()))\n      n = Matrix();\n\n    std::vector<UInt> index(normalsTotal.parameterCount(), NULLINDEX);\n    std::iota(index.begin()+startIndex, index.begin()+startIndex+normals.parameterCount(), 0);\n    normals.reorder(index, normalsTotal.blockIndex(), normals.getCalculateRank());\n\n    // init right hand sides\n    // ---------------------\n    if(Parallel::isMaster(normalsTotal.communicator()))\n    {\n      if(rhsCount != n.columns())\n        throw(Exception(\"number of right hand sides must agree (\"+rhsCount%\"%i != \"s+n.columns()%\"%i)\"s));\n      if((startIndex > 0) || (normalsTotal.parameterCount() > n.rows()))\n      {\n        Matrix tmp(normalsTotal.parameterCount(), rhsCount);\n        copy(n, tmp.row(startIndex, n.rows()));\n        std::swap(tmp, n);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool NormalEquationFile::addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                                           MatrixDistributed &normalsTotal, Matrix &nTotal, Vector &lPlTotal, UInt &obsCountTotal)\n{\n  try\n  {\n    UInt ready = 0;\n    const Vector vx = x.column(rhsNo);\n    if(!isStrictlyZero(vx))\n    {\n      Matrix Nvx(vx.rows(), vx.columns());\n      Matrix NWz(Wz.rows(), Wz.columns());\n      for(UInt i=0; i<normals.blockCount(); i++)\n        for(UInt k=i; k<normals.blockCount(); k++)\n          if(normals.isMyRank(i, k))\n          {\n            matMult(1., normals.N(i,k), vx.row(normals.blockIndex(k), normals.blockSize(k)), Nvx.row(normals.blockIndex(i), normals.blockSize(i)));\n            matMult(1., normals.N(i,k), Wz.row(normals.blockIndex(k), normals.blockSize(k)), NWz.row(normals.blockIndex(i), normals.blockSize(i)));\n            if(i == k)\n              continue;\n            matMult(1., normals.N(i,k).trans(), vx.row(normals.blockIndex(i), normals.blockSize(i)), Nvx.row(normals.blockIndex(k), normals.blockSize(k)));\n            matMult(1., normals.N(i,k).trans(), Wz.row(normals.blockIndex(i), normals.blockSize(i)), NWz.row(normals.blockIndex(k), normals.blockSize(k)));\n          }\n      Parallel::reduceSum(Nvx, 0, normalsTotal.communicator());\n      Parallel::reduceSum(NWz, 0, normalsTotal.communicator());\n\n      if(Parallel::isMaster(normalsTotal.communicator()) )\n      {\n        // aposteriori sigma\n        const Double sigma2Old = sigma2;\n        const Double ePe = inner(vx, Nvx) - 2*inner(vx, n.column(rhsNo)) + lPl(rhsNo);\n        const Double r   = obsCount - inner(Wz, NWz)/sigma2;\n        sigma2 = ePe/r;\n        ready  = (std::fabs(std::sqrt(sigma2)-std::sqrt(sigma2Old))/std::sqrt(sigma2) < 0.01);\n      }\n      Parallel::broadCast(sigma2, 0, normalsTotal.communicator());\n      Parallel::broadCast(ready,  0, normalsTotal.communicator());\n    }\n\n    // accumulate normals\n    // ------------------\n    for(UInt i=0; i<normals.blockCount(); i++)\n      for(UInt k=i; k<normals.blockCount(); k++)\n        if(normals.isBlockUsed(i, k))\n        {\n          normalsTotal.setBlock(i, k);\n          if(normals.isMyRank(i, k))\n            axpy(1./sigma2, normals.N(i,k), normalsTotal.N(i,k));\n        }\n\n    // accumulate right hand sides\n    // ---------------------------\n    if(Parallel::isMaster(normalsTotal.communicator()))\n    {\n      axpy(1./sigma2, n,   nTotal);\n      axpy(1./sigma2, lPl, lPlTotal);\n      obsCountTotal += obsCount;\n    }\n\n    return ready;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquationFile::contribution(MatrixDistributed &Cov)\n{\n  try\n  {\n    Vector contrib(Cov.dimension());\n    for(UInt i=0; i<normals.blockCount(); i++)\n    {\n      // diagonal\n      if(normals.isMyRank(i, i))\n      {\n        fillSymmetric(normals.N(i,i));\n        normals.N(i,i).setType(Matrix::GENERAL);\n        Matrix NN = Cov.N(i,i) * normals.N(i,i);\n        for(UInt z=0; z<NN.rows(); z++)\n          contrib(z+Cov.blockIndex(i)) += NN(z,z);\n        normals.N(i,i).setType(Matrix::SYMMETRIC);\n      }\n\n      for(UInt k=i+1; k<normals.blockCount(); k++)\n        if(normals.isMyRank(i, k))\n        {\n          Matrix NN = Cov.N(i,k) * normals.N(i,k).trans();\n          for(UInt z=0; z<NN.rows(); z++)\n            contrib(z+Cov.blockIndex(i)) += NN(z,z);\n          NN = Cov.N(i,k).trans() * normals.N(i,k);\n          for(UInt z=0; z<NN.rows(); z++)\n            contrib(z+Cov.blockIndex(k)) += NN(z,z);\n        }\n    }\n\n    Parallel::reduceSum(contrib, 0, Cov.communicator());\n    Parallel::broadCast(contrib, 0, Cov.communicator());\n    return 1./sigma2 * contrib;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationFile.h",
    "content": "/***********************************************/\n/**\n* @file normalEquationFile.h\n*\n* @brief Read normals from file.\n* @see NormalEquation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALEQUATIONFILE__\n#define __GROOPS_NORMALEQUATIONFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_NormalEquation\nstatic const char *docstringNormalEquationFile = R\"(\n\\subsection{File}\\label{normalEquationType:file}\nReads a system of normal equations from file \\configFile{inputfileNormalEquation}{normalEquation}\nas generated by e.g. \\program{NormalsBuild}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/normalEquation/normalEquation.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read normals from file.\n* @ingroup normalEquationGroup\n* @see NormalEquation */\nclass NormalEquationFile : public NormalEquationBase\n{\n  FileName           fileName;\n  UInt               startIndex;\n  UInt               paraCount, rhsCount, obsCount;\n  std::vector<ParameterName> names;\n  MatrixDistributed  normals;\n  Matrix             n;\n  Vector             lPl;\n  Double             sigma2;\n\npublic:\n  NormalEquationFile(Config &config);\n\n  UInt   rightHandSideCount() const override {return lPl.size();}\n  UInt   parameterCount()     const override {return paraCount + startIndex;}\n  void   parameterNames(std::vector<ParameterName> &names) const override;\n  void   init(MatrixDistributed &normals, UInt rhsCount) override;\n  Bool   addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                           MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) override;\n  Vector contribution(MatrixDistributed &Cov) override;\n  std::vector<Double> varianceComponentFactors() const override {return std::vector<Double>({sigma2});}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationRegularization.cpp",
    "content": "/***********************************************/\n/**\n* @file normalEquationRegularization.cpp\n*\n* @brief Regularization with diagonal matrix.\n* @see NormalEquation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"parallel/parallel.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n#include \"classes/normalEquation/normalEquationRegularization.h\"\n\n/***********************************************/\n\nNormalEquationRegularization::NormalEquationRegularization(Config &config)\n{\n  try\n  {\n    FileName diagName, biasName;\n    Double   sigma;\n\n    readConfig(config, \"inputfileDiagonalMatrix\", diagName,   Config::OPTIONAL, \"\",    \"Vector with the diagonal elements of the weight matrix\");\n    readConfig(config, \"inputfileBias\",           biasName,   Config::OPTIONAL, \"\",    \"Matrix with right hand sides\");\n    readConfig(config, \"aprioriSigma\",            sigma,      Config::DEFAULT,  \"1.0\", \"\");\n    readConfig(config, \"startIndex\",              startIndex, Config::DEFAULT,  \"0\",   \"regularization of parameters starts at this index (counting from 0)\");\n    if(isCreateSchema(config)) return;\n\n    paraCount = 0;\n    obsCount  = 0;\n    rhsCount  = 1;\n    sigma2    = sigma*sigma;\n\n    if(!diagName.empty())\n    {\n      readFileMatrix(diagName, K);\n      paraCount = K.rows();\n    }\n\n    if(!biasName.empty())\n    {\n      readFileMatrix(biasName, bias);\n      paraCount = bias.rows();\n      rhsCount  = bias.columns();\n    }\n\n    if(K.rows() && bias.rows() && (K.rows() != bias.rows()))\n      throw(Exception(\"dimension of diagonal matrix (\"+K.rows()%\"%i) and bias (\"s+bias.rows()%\"%i x \"s+bias.columns()%\"%i) must agree!\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationRegularization::init(MatrixDistributed &normals, UInt rhsCount)\n{\n  try\n  {\n    if(paraCount == 0)\n      paraCount = normals.parameterCount()-startIndex;\n    this->rhsCount = rhsCount;\n\n    // adjust right hand side\n    // ----------------------\n    if(!bias.size())\n      bias = Matrix(paraCount, rhsCount);\n    if(bias.columns() != rhsCount)\n      throw(Exception(\"Dimension error (right hand side count): \"+bias.columns()%\"%i != \"s+rhsCount%\"%i\"s));\n\n    // adjust diagonal matrix\n    // ----------------------\n    if(!K.size())\n      K = Vector(paraCount, 1.);\n\n    // compute lPl\n    // -----------\n    lPl = Vector(rhsCount);\n    for(UInt rhsNo=0; rhsNo<rhsCount; rhsNo++)\n      for(UInt i=0; i<paraCount; i++)\n        lPl(rhsNo) += bias(i, rhsNo) * K(i) * bias(i, rhsNo);\n\n    // compute obsCount\n    // ----------------\n    obsCount = 0;\n    for(UInt i=0; i<paraCount; i++)\n      if(K(i) != 0.)\n        obsCount++;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nBool NormalEquationRegularization::addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                                                     MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount)\n{\n  try\n  {\n    UInt ready = 0;\n    if(Parallel::isMaster(normals.communicator()))\n    {\n      Vector vx = x.slice(startIndex, rhsNo, bias.rows(), 1);\n      if(quadsum(vx) > 0.)\n      {\n        // square sum of residuals\n        Double ePe = 0.0;\n        for(UInt i=0; i<paraCount; i++)\n          ePe += (vx(i)-bias(i, rhsNo)) * K(i) * (vx(i)-bias(i, rhsNo)); // = (x-n)'K(x-n)\n        // redundancy (monte carlo estimation)\n        Double r = static_cast<Double>(this->obsCount);\n        for(UInt i=0; i<paraCount; i++)\n          r -= 1/sigma2 * K(i) * quadsum(Wz.row(i+startIndex)); // = z'W'KWz\n        // aposteriori sigma\n        const Double sigma2Old = sigma2;\n        sigma2 = ePe/r;\n        ready  = (std::fabs(std::sqrt(sigma2)-std::sqrt(sigma2Old))/std::sqrt(sigma2) < 0.01);\n      }\n    }\n    Parallel::broadCast(sigma2, 0, normals.communicator());\n    Parallel::broadCast(ready,  0, normals.communicator());\n\n    // add normals\n    const Double factor = 1/sigma2;\n    for(UInt i=0; i<normals.blockCount(); i++)\n      if((normals.blockIndex(i+1) > startIndex) && (normals.blockIndex(i) < startIndex+paraCount))\n      {\n        normals.setBlock(i,i);\n        if(normals.isMyRank(i,i))\n          for(UInt z=0; z<normals.blockSize(i); z++)\n            if((z+normals.blockIndex(i) >= startIndex) && (z+normals.blockIndex(i)-startIndex < paraCount))\n              normals.N(i,i)(z,z) += factor * K(z+normals.blockIndex(i)-startIndex);\n      }\n\n    // accumulate right hand sides\n    if(Parallel::isMaster(normals.communicator()))\n    {\n      for(UInt z=0; z<paraCount; z++)\n        for(UInt s=0; s<rhsCount; s++)\n          n(z+startIndex, s) += factor * K(z) * bias(z,s);\n      axpy(factor, this->lPl, lPl);\n      obsCount += this->obsCount;\n    }\n\n    return ready;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquationRegularization::contribution(MatrixDistributed &Cov)\n{\n  try\n  {\n    Vector contrib(Cov.dimension());\n\n    for(UInt i=0; i<Cov.blockCount(); i++)\n      if(Cov.isMyRank(i,i))\n        for(UInt z=0; z<Cov.blockSize(i); z++)\n          if((z+Cov.blockIndex(i) >= startIndex) && (z+Cov.blockIndex(i) < startIndex+paraCount))\n            contrib(z+Cov.blockIndex(i)) += Cov.N(i,i)(z,z) * K(z+Cov.blockIndex(i)-startIndex)/sigma2;\n\n    Parallel::reduceSum(contrib, 0, Cov.communicator());\n    Parallel::broadCast(contrib, 0, Cov.communicator());\n    return contrib;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationRegularization.h",
    "content": "/***********************************************/\n/**\n* @file normalEquationRegularization.h\n*\n* @brief Regularization with a diagonal matrix.\n* @see NormalEquation\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-12-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALEQUATIONREGULARIZATION__\n#define __GROOPS_NORMALEQUATIONREGULARIZATION__\n\n// Latex documentation\n#ifdef DOCSTRING_NormalEquation\nstatic const char *docstringNormalEquationRegularization = R\"(\n\\subsection{Regularization}\\label{normalEquationType:regularization}\nSet up a system of normal equations\n\\begin{equation}\n\\M N = \\M R\n\\qquad\\text{and}\\qquad\n\\M n = \\M R \\M b,\n\\end{equation}\nwhere $\\M R$ is a diagonal matrix whose elements are given as a vector by\n\\configFile{inputfileDiagonalMatrix}{matrix} and $\\M b$ is the right hand side towards which will\nbe regularized. It can be given by \\configFile{inputfileBiasVector}{matrix}.\nThe diagonal matrix can be generated with \\program{NormalsRegularizationBorders},\n\\program{NormalsRegularizationSphericalHarmonics}, or \\program{MatrixCalculate}.\nIf $\\M R$ is not given a unit matrix is assumed.\nThe right hand side $\\M b$ may be generated with \\program{Gravityfield2SphericalHarmonicsVector}.\nIf $\\M b$ is not given a zero vector is assumed.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/normalEquation/normalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Regularization with a diagonal matrix.\n* @ingroup normalEquationGroup\n* @see NormalEquation */\nclass NormalEquationRegularization : public NormalEquationBase\n{\n  Vector  K;\n  Matrix  bias;\n  Vector  lPl;\n  UInt    startIndex;\n  UInt    paraCount, rhsCount, obsCount;\n  Double  sigma2;\n\npublic:\n  NormalEquationRegularization(Config &config);\n\n  UInt   rightHandSideCount() const override {return rhsCount;}\n  UInt   parameterCount()     const override {return paraCount + startIndex;}\n  void   parameterNames(std::vector<ParameterName> &/*names*/) const override {}\n  void   init(MatrixDistributed &normals, UInt rhsCount) override;\n  Bool   addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                           MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) override;\n  Vector contribution(MatrixDistributed &Cov) override;\n  std::vector<Double> varianceComponentFactors() const override {return std::vector<Double>({sigma2});}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationRegularizationGeneralized.cpp",
    "content": "/***********************************************/\n/**\n* @file normalEquationRegularizationGeneralized.cpp\n*\n* @brief Regularization with sum of symmetric matrices.\n* @see NormalEquation\n*\n* @author Andreas Kvas\n* @date 2010-02-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"parallel/parallel.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n#include \"classes/normalEquation/normalEquationRegularizationGeneralized.h\"\n\n/***********************************************/\n\nNormalEquationRegularizationGeneralized::NormalEquationRegularizationGeneralized(Config &config)\n{\n  try\n  {\n    FileName fileNameBias;\n\n    readConfig(config, \"inputfilePartialCovarianceMatrix\", fileNamesCovariance, Config::MUSTSET,  \"\",    \"symmetric matrix (sum of all matrices must be positive definite)\");\n    readConfig(config, \"inputfileBiasMatrix\",              fileNameBias,        Config::OPTIONAL, \"\",    \"bias vector (default: zero vector)\");\n    readConfig(config, \"aprioriSigma\",                     sigma2,              Config::MUSTSET,  \"1.0\", \"apriori sigmas for initial iteration (default: 1.0)\");\n    readConfig(config, \"startIndex\",                       startIndex,          Config::DEFAULT,  \"0\",   \"regularization of parameters starts at this index (counting from 0)\");\n    if(isCreateSchema(config)) return;\n\n    if(sigma2.size() == 1)\n      sigma2.resize(fileNamesCovariance.size(), sigma2.front());\n    if(sigma2.size() != fileNamesCovariance.size())\n      throw(Exception(\"Number of partial covariance matrices and apriori sigmas do not match (\"+fileNamesCovariance.size()%\"%i\"s+\" vs. \"+ sigma2.size()%\"%i\"s+\").\"));\n    for(Double &s2 : sigma2)\n      s2 *= s2;\n\n    if(!fileNameBias.empty())\n    {\n      readFileMatrix(fileNameBias, bias);\n      rhsCount = bias.columns();\n      paraCount = bias.rows();\n    }\n    else\n    {\n      rhsCount = 1;\n      paraCount = 0;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalEquationRegularizationGeneralized::init(MatrixDistributed &normals, UInt rhsCount)\n{\n  try\n  {\n    if(Parallel::isMaster(normals.communicator()))\n    {\n      Matrix V;\n      readFileMatrix(fileNamesCovariance.front(), V);\n      paraCount = V.rows();\n\n    }\n    Parallel::broadCast(paraCount, 0, normals.communicator());\n\n    // adjust right hand side\n    // ----------------------\n    if(!bias.size())\n      bias = Matrix(paraCount, rhsCount);\n    if(bias.columns() != rhsCount)\n      throw(Exception(\"Dimension error (right hand side count): \"+bias.columns()%\"%i != \"s+rhsCount%\"%i\"s));\n    this->rhsCount = bias.columns();\n\n    startBlock = normals.index2block(startIndex);\n\n    // index\n    std::vector<UInt> index(paraCount);\n    std::iota(index.begin(), index.end(), 0);\n\n    // blockIndex\n    std::vector<UInt> blockIndex = {0, std::min(normals.blockIndex(startBlock+1)-startIndex, paraCount)};\n    for(UInt i=startBlock+1; blockIndex.back()<paraCount; i++)\n      blockIndex.push_back(std::min(blockIndex.back() + normals.blockSize(i), paraCount));\n\n    // calcRank\n    auto calcRank = [&](UInt i, UInt k, UInt commSize) {return normals.getCalculateRank()(startBlock+i, startBlock+k, commSize);};\n\n    for(const FileName &fileName : fileNamesCovariance)\n    {\n      auto &Vi = V.emplace_back(std::vector<UInt>{0, paraCount}, normals.communicator()); // just one block\n      if(Vi.isMyRank(0, 0))\n      {\n        readFileMatrix(fileName, Vi.N(0, 0));\n        if((Vi.N(0, 0).rows() != paraCount))\n          throw(Exception(\"Dimension error of <\"+fileName.str()+\"> (\"+Vi.N(0, 0).rows()%\"%i\"s+\" vs. \"+paraCount%\"%i\"s + \" parameters).\"));\n        if(Vi.N(0, 0).getType() != Matrix::SYMMETRIC)\n          throw(Exception(\"Matrix <\"+fileName.str()+\"> is not symmetric.\"));\n        fillSymmetric(Vi.N(0, 0));\n      }\n      Vi.reorder(index, blockIndex, [&](UInt, UInt, UInt) {return Vi.rank(0, 0);}); // divide into blocks\n      Vi.reorder(index, blockIndex, calcRank);                                      // distribute blocks\n    }\n\n    Sigma.init(blockIndex, normals.communicator(), calcRank);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool NormalEquationRegularizationGeneralized::addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                                                                MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount)\n{\n  try\n  {\n    // --- lambda function --------------------------\n    auto symMatMult = [](const MatrixDistributed N, const_MatrixSliceRef &x) -> Matrix\n    {\n      Matrix y(x.rows(), x.columns());\n      for(UInt i=0; i<N.blockCount(); i++)\n        for(UInt k=i; k<N.blockCount(); k++)\n          if(N.isMyRank(i, k))\n          {\n            matMult(1.0, N.N(i, k), x.row(N.blockIndex(k), N.blockSize(k)), y.row(N.blockIndex(i), N.blockSize(i)));\n            if(i != k)\n              matMult(1.0, N.N(i, k).trans(), x.row(N.blockIndex(i), N.blockSize(i)), y.row(N.blockIndex(k), N.blockSize(k)));\n          }\n      Parallel::reduceSum(y, 0, N.communicator());\n      return y;\n    };\n    // ----------------------------------------------\n\n    UInt ready = 0;\n    if(quadsum(x.slice(startIndex, rhsNo, paraCount, 1)) > 0.) // estimate sigmas\n    {\n      Matrix Se  = symMatMult(Sigma, bias.column(rhsNo) - x.slice(startIndex, rhsNo, paraCount, 1));\n      Matrix SWz = symMatMult(Sigma, Wz.row(startIndex, paraCount));\n      Parallel::broadCast(Se,  0, normals.communicator());\n      Parallel::broadCast(SWz, 0, normals.communicator());\n\n      for(UInt j=0; j<V.size(); j++)\n      {\n        Matrix VSe  = symMatMult(V.at(j), Se);\n        Matrix VSWz = symMatMult(V.at(j), SWz);\n\n        // trace(V*Sigma^-1)\n        Double r = 0;\n        for(UInt i=0; i<Sigma.blockCount(); i++)\n        {\n          for(UInt k=i+1; k<Sigma.blockCount(); k++)\n            if(Sigma.isMyRank(i, k))\n              r += 2 * inner(V.at(j).N(i,k), Sigma.N(i,k));\n          if(Sigma.isMyRank(i, i))\n          {\n            fillSymmetric(V.at(j).N(i,i));\n            fillSymmetric(Sigma.N(i,i));\n            r += inner(V.at(j).N(i,i), Sigma.N(i,i));\n          }\n        }\n        Parallel::reduceSum(r, 0, normals.communicator());\n\n        if(Parallel::isMaster(normals.communicator()))\n        {\n          const Double sigma2Old = sigma2.at(j);\n          sigma2.at(j) *= inner(Se, VSe)/(r-inner(SWz, VSWz));\n          ready = ready && (std::fabs(std::sqrt(sigma2.at(j))-std::sqrt(sigma2Old))/std::sqrt(sigma2.at(j)) < 0.01);\n        }\n      }\n      Parallel::broadCast(sigma2, 0, normals.communicator());\n      Parallel::broadCast(ready,  0, normals.communicator());\n    }\n\n    // accumulate covariance matrix\n    Sigma.setNull();\n    for(UInt i=0; i<Sigma.blockCount(); i++)\n      for(UInt k=i; k<Sigma.blockCount(); k++)\n        if(Sigma.isMyRank(i, k))\n          for(UInt j=0; j<V.size(); j++)\n            axpy(sigma2.at(j), V.at(j).N(i, k), Sigma.N(i, k));\n\n    // invert for normal equations\n    Sigma.cholesky(FALSE);\n    Sigma.choleskyInverse(FALSE);\n    Sigma.choleskyProduct(FALSE);\n\n    // accumulate right hand side\n    Matrix Pl = symMatMult(Sigma, bias);\n    if(Parallel::isMaster(normals.communicator()))\n    {\n      axpy(1., Pl, n.row(startIndex, paraCount));\n      for(UInt i=0; i<lPl.rows(); i++)\n        lPl += inner(bias.column(i), Pl.column(i));\n      obsCount += paraCount;\n    }\n\n    // accumulate normals\n    for(UInt i=0; i<Sigma.blockCount(); i++)\n      for(UInt k=i; k<Sigma.blockCount(); k++)\n      {\n        normals.setBlock(startBlock+i, startBlock+k);\n        if(Sigma.isMyRank(i, k))\n        {\n          const UInt rowStart = startIndex + Sigma.blockIndex(i) - normals.blockIndex(startBlock+i);\n          const UInt colStart = startIndex + Sigma.blockIndex(k) - normals.blockIndex(startBlock+k);\n          axpy(1.0, Sigma.N(i, k), normals.N(startBlock+i, startBlock+k).slice(rowStart, colStart, Sigma.blockSize(i), Sigma.blockSize(k)));\n        }\n      }\n\n    return ready;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalEquationRegularizationGeneralized::contribution(MatrixDistributed &Cov)\n{\n  try\n  {\n    Vector contrib(Cov.dimension());\n    for(UInt i=0; i<Sigma.blockCount(); i++)\n    {\n      // diagonal block\n      if(Sigma.isMyRank(i, i))\n      {\n        const UInt rowStart = startIndex + Sigma.blockIndex(i) - Cov.blockIndex(startBlock+i);\n        const_MatrixSliceRef C = Cov.N(startBlock+i, startBlock+i).slice(rowStart, rowStart, Sigma.blockSize(i), Sigma.blockSize(i));\n\n        for(UInt z=0; z<Sigma.blockSize(i); z++)\n          contrib(startIndex+Sigma.blockIndex(i)+z) += inner(Sigma.N(i, i).slice(0, z, z, 1), C.slice(0, z, z, 1))\n                                                    +  inner(Sigma.N(i, i).slice(z, z, 1, Sigma.blockSize(i)-z), C.slice(z, z, 1, Sigma.blockSize(i)-z));\n      }\n      // other blocks\n      for(UInt k=i+1; k<Sigma.blockCount(); k++)\n        if(Sigma.isMyRank(i, k))\n        {\n          const UInt rowStart = startIndex + Sigma.blockIndex(i) - Cov.blockIndex(startBlock+i);\n          const UInt colStart = startIndex + Sigma.blockIndex(k) - Cov.blockIndex(startBlock+k);\n          const_MatrixSliceRef C = Cov.N(startBlock+i, startBlock+k).slice(rowStart, colStart, Sigma.blockSize(i), Sigma.blockSize(k));\n\n          for(UInt z=0; z<Sigma.blockSize(i); z++)\n            contrib(startIndex+Sigma.blockIndex(i)+z) += inner(Sigma.N(i, k).row(z), C.row(z));\n          for(UInt s=0; s<Sigma.blockSize(k); s++)\n            contrib(startIndex+Sigma.blockIndex(k)+s) += inner(Sigma.N(i, k).column(s), C.column(s));\n        }\n    }\n    Parallel::reduceSum(contrib, 0, Cov.communicator());\n    Parallel::broadCast(contrib, 0, Cov.communicator());\n    return contrib;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/normalEquation/normalEquationRegularizationGeneralized.h",
    "content": "/***********************************************/\n/**\n* @file normalEquationRegularizationGeneralized.h\n*\n* @brief Regularization with sum of symmetric matrices.\n* @see NormalEquation\n*\n* @author Andreas Kvas\n* @date 2010-02-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALEQUATIONREGULARIZATIONGENERALIZED__\n#define __GROOPS_NORMALEQUATIONREGULARIZATIONGENERALIZED__\n\n// Latex documentation\n#ifdef DOCSTRING_NormalEquation\nstatic const char *docstringNormalEquationRegularizationGeneralized = R\"(\n\\subsection{RegularizationGeneralized}\n\nGeneralized regularization which is represented by the observation equation\n\\begin{equation}\n\\mathbf{x}_0 = \\mathbf{I} \\mathbf{x} + \\mathbf{v}, \\mathbf{v} \\sim \\mathcal{N}(0, \\sum_k \\sigma^2_k \\mathbf{V}_k).\n\\end{equation}\n\nThere are no requirements for partial covariance matrices $\\mathbf{V}_k$ except for them being symmetric.\nThe accumulated covariance matrix $\\sum_k \\sigma^2_k \\mathbf{V}_k$ must be positive definite however.\nThe variance components $\\sigma^2_k$ are estimated during the adjustment process and are assumed to be positive.\nAll \\configFile{inputfilePartialCovarianceMatrix}{matrix} must be of same size\nand must match the dimension of \\configFile{inputfileBiasMatrix}{matrix}\n(if provided, otherwise a zero vector of appropriate dimensions is created).\n\nThe parameter \\config{aprioriSigma} determines the initial variance factor for the partial covariance matrices. Either one $\\sigma_0$ can be\nsupplied or one for each $\\mathbf{V}_k$.\n\nThe regularization matrix can be applied to a subset of parameters by adjusting \\config{startIndex}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/normalEquation/normalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Regularization with sum of symmetric matrices.\n* @ingroup normalEquationGroup\n* @see NormalEquation */\nclass NormalEquationRegularizationGeneralized : public NormalEquationBase\n{\n  std::vector<FileName> fileNamesCovariance;\n  Matrix                bias;\n  UInt                  startIndex, startBlock;\n  UInt                  paraCount, rhsCount;\n  std::vector<Double>   sigma2;\n  MatrixDistributed     Sigma; // = sum_i sigma2_i * V_i\n  std::vector<MatrixDistributed> V;\n\npublic:\n  NormalEquationRegularizationGeneralized(Config &config);\n\n  UInt   rightHandSideCount() const override {return rhsCount;}\n  UInt   parameterCount()     const override {return paraCount + startIndex;}\n  void   parameterNames(std::vector<ParameterName> &/*names*/) const override {}\n  void   init(MatrixDistributed &normals, UInt rhsCount) override;\n  Bool   addNormalEquation(UInt rhsNo, const const_MatrixSlice &x, const const_MatrixSlice &Wz,\n                           MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) override;\n  Vector contribution(MatrixDistributed &Cov) override;\n  std::vector<Double> varianceComponentFactors() const override {return sigma2;}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/observation/observation.cpp",
    "content": "/***********************************************/\n/**\n* @file observation.cpp\n*\n* @brief Observation equations.\n* Set up linearized observation equations (design matrix)\n* to connect unknown parameters with observations.\n* It is used in a least squares adjustment.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-11-12\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Observation\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"parallel/parallel.h\"\n#include \"observationPodIntegral.h\"\n#include \"observationPodAcceleration.h\"\n#include \"observationPodEnergy.h\"\n#include \"observationPodVariational.h\"\n#include \"observationSstIntegral.h\"\n#include \"observationSstVariational.h\"\n#include \"observationDualSstVariational.h\"\n#include \"observationGradiometer.h\"\n#include \"observationTerrestrial.h\"\n#include \"observationDeflections.h\"\n#include \"observationStationLoading.h\"\n#include \"observation.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Observation, \"observationType\",\n                      ObservationPodVariational,\n                      ObservationPodIntegral,\n                      ObservationPodAcceleration,\n                      ObservationPodEnergy,\n                      ObservationSstVariational,\n                      ObservationSstIntegral,\n                      ObservationDualSstVariational,\n                      ObservationGradiometer,\n                      ObservationTerrestrial,\n                      ObservationDeflections,\n                      ObservationStationLoading)\n\nGROOPS_READCONFIG_CLASS(Observation, \"observationType\")\n\n/***********************************************/\n\nObservationPtr Observation::create(Config &config, const std::string &name)\n{\n  try\n  {\n    ObservationPtr ptr;\n    std::string    type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"obervation equations for least squares adjustment\");\n\n    renameDeprecatedChoice(config, type, \"satelliteTracking\", \"sstIntegral\", date2time(2020, 6, 13));\n\n    if(readConfigChoiceElement(config, \"podVariational\",      type, \"precise orbit data (variational equations)\"))\n      ptr = std::make_shared<ObservationPodVariational>(config);\n    if(readConfigChoiceElement(config, \"podIntegral\",         type, \"precise orbit data (integral approach)\"))\n      ptr = std::make_shared<ObservationPodIntegral>(config);\n    if(readConfigChoiceElement(config, \"podAcceleration\",     type, \"precise orbit data (acceleration approach)\"))\n      ptr = std::make_shared<ObservationPodAcceleration>(config);\n    if(readConfigChoiceElement(config, \"podEnergy\",           type, \"precise orbit data (energy approach)\"))\n      ptr = std::make_shared<ObservationPodEnergy>(config);\n    if(readConfigChoiceElement(config, \"sstVariational\",      type, \"sst data and pod\"))\n      ptr = std::make_shared<ObservationSstVariational>(config);\n    if(readConfigChoiceElement(config, \"sstIntegral\",         type, \"sst data and pod\"))\n      ptr = std::make_shared<ObservationSstIntegral>(config);\n    if(readConfigChoiceElement(config, \"dualSstVariational\",  type, \"dual sst data and pod\"))\n      ptr = std::make_shared<ObservationDualSstVariational>(config);\n    if(readConfigChoiceElement(config, \"gradiometer\",         type, \"GOCE gradiometry\"))\n      ptr = std::make_shared<ObservationGradiometer>(config);\n    if(readConfigChoiceElement(config, \"terrestrial\",         type, \"e.g. gravity anomalies, GPS/levelling\"))\n      ptr = std::make_shared<ObservationTerrestrial>(config);\n    if(readConfigChoiceElement(config, \"deflections\",         type, \"e.g. Deflections of the vertical\"))\n      ptr = std::make_shared<ObservationDeflections>(config);\n    if(readConfigChoiceElement(config, \"stationLoading\",      type, \"Loading from station observations.\"))\n      ptr = std::make_shared<ObservationStationLoading>(config);\n    endChoice(config);\n\n    return ptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observation.h",
    "content": "/***********************************************/\n/**\n* @file observation.h\n*\n* @brief Observation equations.\n* Set up linearized observation equations (design matrix)\n* to connect unknown parameters with observations.\n* It is used in a least squares adjustment.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-11-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATION__\n#define __GROOPS_OBSERVATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservation = R\"(\n\\section{Observation}\\label{observationType}\nThis class sets up the observation equations in linearized Gauss-Markov model\n\\begin{equation}\\label{gmm}\n\\M l  = \\M A \\M x + \\M e\\qquad\\text{and}\\qquad\\mathcal{C}(\\M e) = \\sigma^2\\M P^{-1}.\n\\end{equation}\nThe observations are divided into short data blocks which can be computed independently\nand so easily can be parallelized. Usually these data blocks are short arcs of a\nsatellite's orbit. In most cases the unknown parameter vector contains coefficients\nof a gravity field parametrization given by \\configClass{parametrizationGravity}{parametrizationGravityType}.\nAdditional parameters like instrument calibration parameters are appended at the\nend of the vector~$\\M x$.\nIt is possible to give several observation vectors in one model.\n\nThe observations within each arc are decorrelated in the following way:\nIn a first step a Cholesky decomposition of the covariance matrix is performed\n\\begin{equation}\n\\M P^{-1} = \\M W^T\\M W,\n\\end{equation}\nwhere $\\M W$ is an upper regular triangular matrix.\nIn a second step the transformation\n\\begin{equation}\\label{dekorrelierung}\n\\bar{\\M A} = \\M W^{-T}\\M A\\qquad\\text{and}\\qquad \\bar{\\M l} = \\M W^{-T}\\M l\n\\end{equation}\ngives an estimation from decorrelated observations with equal variance\n\\begin{equation}\\label{normal.GMM}\n\\bar{\\M l} = \\bar{\\M A} \\M x + \\bar{\\M e}\n\\qquad\\text{and}\\qquad\n\\mathcal{C}(\\bar{\\M e})= \\sigma^2 \\M I.\n\\end{equation}\nUsually the arc dependent parameters are eliminated in the next step\nand not mentioned for the parameter names in the following.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup observationGroup Observation\n* @brief Observation equations (design matrix).\n* @ingroup classesGroup\n* The interface is given by @ref Observation. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Observation;\ntypedef std::shared_ptr<Observation> ObservationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Observation equations.\n* Set up linearized observation equations (design matrix)\n* to connect unknown parameters with observations.\n* It is used in a least squares adjustment.\n* An instance of this class can be created by @ref readConfig. */\nclass Observation\n{\npublic:\n  virtual ~Observation() {}\n\n  /** @brief Estimate parameters in the given interval only.\n  * Change result of @a parameterCount(), @a gravityParameterCount(), @a parameterName().\n  * @return TRUE if parameters are changed */\n  virtual Bool setInterval(const Time &timeStart, const Time &timeEnd) = 0;\n\n  /** @brief Number of unknown parameters.\n  * This is the column count of the design matrix @a A. */\n  virtual UInt parameterCount() const = 0;\n\n  /** @brief Number of Gravityfield parameters.\n  * The parameterCount of Representation.\n  * (Without parameters added by this class, e.g. instrumental calibration parameters). */\n  virtual UInt gravityParameterCount() const = 0;\n\n  /** @brief Number of observations.\n  * This is the column count of the observation vector @a l. */\n  virtual UInt rightSideCount() const=0;\n\n  /** @brief Number of observation blocks (arcs). */\n  virtual UInt arcCount() const = 0;\n\n  /** @brief Name of parameters.\n  * The names are appended to @a name. */\n  virtual void parameterName(std::vector<ParameterName> &name) const = 0;\n\n  /** @brief Observation equations for an Arc.\n  * The design matrix @a A contains the common parameter (mostly gravity field parameters).\n  * The design matrix for arc specific parameters (e.g. bias, satellite state vector) is separated in Matrix @a B.\n  * @param[in] arcNo Index of the arc to be computed, a number in [0, @a arcCount)\n  * @param[out] l Observation vector (multiple vectors/columns possible)\n  * @param[out] A Design matrix for common parameters.\n  * @param[out] B Design matrix for arc related parameters. */\n  virtual void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) = 0;\n\n  /** @brief creates a derived instance of this class. */\n  static ObservationPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Observation.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a observation is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] observation Created class.\n* @param mustSet If it is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Observation */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationPtr &observation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationDeflections.cpp",
    "content": "/***********************************************/\n/**\n* @file observationDeflections.cpp\n*\n* @brief point measurements of xi and eta.\n*\n*\n* @author Christian Pock\n* @date 2012-05-30\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationDeflections.h\"\n\n/***********************************************/\n\nObservationDeflections::ObservationDeflections(Config &config)\n{\n  try\n  {\n    FileName              fileNameGrid;\n    ExpressionVariablePtr exprXi, exprEta;\n    ExpressionVariablePtr exprSigmaXi, exprSigmaEta;\n    Double                a, f;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\", date2time(2020, 6, 3));\n\n    if(readConfigSequence(config, \"rightHandSide\", Config::MUSTSET, \"\", \"input for observation vectors\"))\n    {\n      readConfig(config, \"inputfileGriddedData\", fileNameGrid,   Config::MUSTSET,  \"\",                \"\");\n      readConfig(config, \"observationXi\",        exprXi,         Config::MUSTSET,  \"data0\",           \"North-South Deflections of the Vertical [rad]\");\n      readConfig(config, \"observationEta\",       exprEta,        Config::MUSTSET,  \"data1\",           \"East-West Deflections of the Vertical  [rad]\");\n      readConfig(config, \"sigmaXi\",              exprSigmaXi,    Config::OPTIONAL, \"sqrt(4*PI/area)\", \"accuracy, 1/sigma used as weighting\");\n      readConfig(config, \"sigmaEta\",             exprSigmaEta,   Config::OPTIONAL, \"sqrt(4*PI/area)\", \"accuracy, 1/sigma used as weighting\");\n      readConfig(config, \"referencefield\",       referencefield, Config::OPTIONAL, \"\",                \"\");\n      endSequence(config);\n    }\n    readConfig(config, \"parametrizationGravity\", parametrization, Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"time\",                   time,            Config::OPTIONAL, \"\",   \"for reference field and parametrization\");\n    readConfig(config, \"R\",                      a,               Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoid\");\n    readConfig(config, \"inverseFlattening\",      f,               Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoid, 0: sphere\");\n    readConfig(config, \"blockingSize\",           obsPerArc,       Config::DEFAULT, \"100\", \"segementation of the obervations if designmatrix can't be build at once\");\n    if(isCreateSchema(config)) return;\n\n    ellipsoid = Ellipsoid(a, f);\n\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    points = grid.points;\n\n    // evaluate expression\n    // -------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    std::vector<ExpressionVariablePtr> expr({exprXi, exprEta, exprSigmaXi, exprSigmaEta});\n    std::for_each(expr.begin(),  expr.end(),  [&](auto expr) {if(expr) expr->simplify(varList);});\n\n    xi.resize(grid.points.size(), 0.);\n    eta.resize(grid.points.size(), 0.);\n    sigmasXi.resize(grid.points.size(), 1.);\n    sigmasEta.resize(grid.points.size(), 1.);\n    for(UInt i=0; i<xi.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      if(exprXi)       xi.at(i)        = exprXi      ->evaluate(varList);\n      if(exprEta)      eta.at(i)       = exprEta     ->evaluate(varList);\n      if(exprSigmaXi)  sigmasXi.at(i)  = exprSigmaXi ->evaluate(varList);\n      if(exprSigmaEta) sigmasEta.at(i) = exprSigmaEta->evaluate(varList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationDeflections::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    const UInt obsCount = observationCount(arcNo);\n\n    l = Vector(2*obsCount);\n    A = Matrix(2*obsCount, parameterCount());\n    B = Matrix();\n    for(UInt obsNo=0; obsNo<obsCount; obsNo++)\n    {\n      const Vector3d    pos     = points.at(idx(arcNo, obsNo));\n      const Transform3d trf2neu = inverse(localNorthEastUp(pos, ellipsoid));\n      Vector3d g;\n      if(referencefield)\n        g = 1./Planets::normalGravity(pos) * trf2neu.transform(referencefield->gravity(time, pos));\n\n      l(2*obsNo+0, 0) = xi.at (idx(arcNo, obsNo)) - g.x();\n      l(2*obsNo+1, 0) = eta.at(idx(arcNo, obsNo)) - g.y();\n\n      Matrix G(3, parameterCount());\n      parametrization->gravity(time, pos, G);\n      matMult(1./Planets::normalGravity(pos), trf2neu.matrix().row(0,2), G, A.row(2*obsNo, 2));\n\n      l.row(2*obsNo+0) *= 1/sigmasXi.at (idx(arcNo, obsNo));\n      l.row(2*obsNo+1) *= 1/sigmasEta.at(idx(arcNo, obsNo));\n      A.row(2*obsNo+0) *= 1/sigmasXi.at (idx(arcNo, obsNo));\n      A.row(2*obsNo+1) *= 1/sigmasEta.at(idx(arcNo, obsNo));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationDeflections.h",
    "content": "/***********************************************/\n/**\n* @file observationDeflections.h\n*\n* @brief point measareuments of xi and eta.\n*\n* @author Christian Pock\n* @date 2012-05-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONDEFLECTIONS__\n#define __GROOPS_OBSERVATIONDEFLECTIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationDeflections = R\"(\n\\subsection{Deflections}\\label{observationType:deflections}\nThe gravity field parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis estimated from deflections of the vertical measurements.\nA \\configClass{referencefield}{gravityfieldType} can be reduced beforehand.\n\nThe observations $\\xi$ in north direction and $\\eta$ in east direction\nat given positions are calculated from\n\\configFile{inputfileGriddedData}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe ellipsoid parameters \\config{R} and \\config{inverseFlattening} are used\nto define the local normal direction.\n\nThe observations can be divided into small blocks for parallelization.\nWith \\config{blockingSize} set the maximum count of observations in each block.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n\n/***** CLASS ***********************************/\n\n/**\n* @brief point measurements of xi and eta\n* @see Observation\n*/\nclass ObservationDeflections : public Observation\n{\n  std::vector<Vector3d>     points;\n  std::vector<Double>       xi, eta;\n  std::vector<Double>       sigmasXi, sigmasEta;\n  GravityfieldPtr           referencefield;\n  ParametrizationGravityPtr parametrization;\n  Time                      time;\n  Ellipsoid                 ellipsoid;\n  UInt                      obsPerArc;\n\n  UInt idx(UInt arc, UInt obs)    const {return arc*obsPerArc+obs;}\n  UInt observationCount(UInt arc) const {return (arc<arcCount()-1) ? (obsPerArc) : (points.size()-arc*obsPerArc);}\n\npublic:\n  ObservationDeflections(Config &config);\n ~ObservationDeflections() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return parametrization->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()        const override {return parametrization->parameterCount();}\n  UInt gravityParameterCount() const override {return parametrization->parameterCount();}\n  UInt rightSideCount()        const override {return 1;}\n  UInt arcCount()              const override {return (points.size()+obsPerArc-1)/obsPerArc;}\n  void parameterName(std::vector<ParameterName> &name) const override {parametrization->parameterName(name);}\n\n  void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationDualSstVariational.cpp",
    "content": "/***********************************************/\n/**\n* @file observationDualSstVariational.cpp\n*\n* @brief Satellite to satellite tracking with two simultaneous ranging observations (Variational equations).\n*\n* @author Andreas\n* @date 2020-07-24\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"misc/observation/observationMiscDualSstVariational.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"classes/observation/observation.h\"\n#include \"observationDualSstVariational.h\"\n\n/***********************************************/\n\nObservationDualSstVariational::ObservationDualSstVariational(Config &config)\n{\n  try\n  {\n    observationMisc = ObservationMiscDualSstVariationalPtr(new ObservationMiscDualSstVariational(config));\n    readConfig(config, \"covarianceSst1\", covSst1, Config::MUSTSET,  \"\", \"covariance matrix of first satellite to satellite tracking observations\");\n    readConfig(config, \"covarianceSst2\", covSst2, Config::MUSTSET,  \"\", \"covariance matrix of second satellite to satellite tracking observations\");\n    readConfig(config, \"covarianceAcc\",  covAcc,  Config::OPTIONAL, \"\", \"common covariance matrix of reduced satellite to satellite tracking observations\");\n    readConfig(config, \"covariancePod1\", covPod1, Config::MUSTSET,  \"\", \"covariance matrix of kinematic orbits (satellite 1)\");\n    readConfig(config, \"covariancePod2\", covPod2, Config::MUSTSET,  \"\", \"covariance matrix of kinematic orbits (satellite 2)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationDualSstVariational::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    ObservationMiscDualSstVariational::Arc arc = observationMisc->computeArc(arcNo, covSst1, covSst2, covAcc, covPod1, covPod2);\n    l = arc.l;\n    A = arc.A;\n    B = arc.B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationDualSstVariational.h",
    "content": "/***********************************************/\n/**\n* @file observationDualSstVariational.h\n*\n* @brief Satellite-to-satellite tracking with two simultaneous ranging observations (Variational equations).\n*\n* @author Andreas Kvas\n* @date 2020-07-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONDUALSSTVARIATIONAL__\n#define __GROOPS_OBSERVATIONDUALSSTVARIATIONAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationDualSstVariational = R\"(\n\\subsection{DualSstVariational}\\label{observationType:dualSstVariational}\nLike \\configClass{observation:sstVariational}{observationType:sstVariational} (see there for details)\nbut with two simultaneous satellite-to-satellite (SST) observations.\n\nThis class reads two SST observation files (\\configFile{inputfileSatelliteTracking1}{instrument} and\n\\configFile{inputfileSatelliteTracking2}{instrument}).\nEmpirical parameters for the SST observations can be set up independently for both SST observation\ntypes with \\configClass{parametrizationSst1}{parametrizationSatelliteTrackingType} and\n\\configClass{parametrizationSst2}{parametrizationSatelliteTrackingType}.\n\nBoth SST observation types are reduced by the same background models and the same impact\nof accelerometer measurements. The covariance matrix of the reduced observations should not consider\nthe instrument noise only (\\configClass{covarianceSst1/2}{covarianceSstType}) but must\ntake the cross correlations \\configClass{covarianceAcc}{covarianceSstType} into account.\nThe covariance matrix of the reduced observations is given by\n\\begin{equation}\n  \\M\\Sigma(\\begin{bmatrix} \\Delta l_{SST1} \\\\ \\Delta l_{SST2} \\end{bmatrix})\n  = \\begin{bmatrix} \\M\\Sigma_{SST1} + \\M\\Sigma_{ACC} & \\M\\Sigma_{ACC} \\\\\n                   \\M\\Sigma_{ACC} & \\M\\Sigma_{SST2} + \\M\\Sigma_{ACC}\n    \\end{bmatrix}.\n\\end{equation}\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite1>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.position0.x::|,\n\\item \\verb|<satellite1>:arc<no>.position0.y::|,\n\\item \\verb|<satellite1>:arc<no>.position0.z::|.\n\\item \\verb|<satellite1>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite2>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.position0.x::|,\n\\item \\verb|<satellite2>:arc<no>.position0.y::|,\n\\item \\verb|<satellite2>:arc<no>.position0.z::|.\n\\item \\verb|<satellite2>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking1>:*:*|.\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking2>:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"misc/observation/observationMiscDualSstVariational.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/covarianceSst.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite-to-satellite tracking with two simultaneous ranging observations (Variational equations).\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationDualSstVariational : public Observation\n{\n  ObservationMiscDualSstVariationalPtr observationMisc;\n  CovarianceSstPtr covSst1, covSst2, covAcc;\n  CovariancePodPtr covPod1, covPod2;\n\npublic:\n  ObservationDualSstVariational(Config &config);\n ~ObservationDualSstVariational() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return observationMisc->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return observationMisc->parameterCount();}\n  UInt gravityParameterCount()   const override {return observationMisc->gravityParameterCount();}\n  UInt rightSideCount()          const override {return observationMisc->rightSideCount();}\n  UInt arcCount()                const override {return observationMisc->arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {observationMisc->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationGradiometer.cpp",
    "content": "/***********************************************/\n/**\n* @file observationGradiometer.cpp\n*\n* @brief GOCE gradiometer observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-05-14\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationGradiometer.h\"\n\n/***********************************************/\n\nObservationGradiometer::ObservationGradiometer(Config &config)\n{\n  try\n  {\n    FileName  orbitName, starCameraName, covarianceName;\n    FileName  sigmaName, covName;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\", date2time(2020, 6, 3));\n\n    readConfig(config, \"rightHandSide\",          rhs,             Config::MUSTSET,  \"\",    \"input for the observation vector\");\n    readConfig(config, \"inputfileOrbit\",         orbitName,       Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileStarCamera\",    starCameraName,  Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"earthRotation\",          earthRotation,   Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",            ephemerides,     Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationGravity\", parametrization, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"parametrizationBias\",    sggBias,         Config::DEFAULT,  \"\",    \"per arc\");\n    readConfig(config, \"useXX\",                  useXX,           Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"useYY\",                  useYY,           Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"useZZ\",                  useZZ,           Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"useXY\",                  useXY,           Config::DEFAULT,  \"0\",   \"\");\n    readConfig(config, \"useXZ\",                  useXZ,           Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"useYZ\",                  useYZ,           Config::DEFAULT,  \"0\",   \"\");\n    if(readConfigSequence(config, \"covarianceSgg\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                       sigma,     Config::DEFAULT,  \"1\", \"general variance factor\");\n      readConfig(config, \"inputfileSigmasPerArc\",       sigmaName, Config::OPTIONAL, \"\",  \"different accuaries for each arc (multplicated with sigma)\");\n      readConfig(config, \"inputfileCovarianceFunction\", covName,   Config::OPTIONAL, \"\",  \"covariance function in time\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    orbitFile.open(orbitName);\n    starCameraFile.open(starCameraName);\n\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n    for(UInt rhsNo=0; rhsNo<rhs.size(); rhsNo++)\n    {\n      InstrumentFile::checkArcCount({orbitFile, *rhs.at(rhsNo)->gradiometerFile});\n      for(UInt k=0; k<rhs.at(rhsNo)->referenceFile.size(); k++)\n        InstrumentFile::checkArcCount({orbitFile, *rhs.at(rhsNo)->referenceFile.at(k)});\n    }\n\n    componentCount = useXX + useXY + useXZ + useYY + useYZ + useZZ;\n\n    if(!sigmaName.empty())\n      readFileMatrix(sigmaName, sigmaArc);\n\n    // covariance matrix from covariance function\n    // ------------------------------------------\n    if(!covName.empty())\n    {\n      Matrix cov;\n      readFileMatrix(covName, cov);\n\n      CovCholesky = Matrix(componentCount*cov.rows(), Matrix::SYMMETRIC, Matrix::UPPER);\n\n      for(UInt i=0; i<cov.rows(); i++)\n        for(UInt k=i; k<cov.rows(); k++)\n        {\n          UInt idx = 0;\n          if(useXX) {CovCholesky(componentCount*i+idx, componentCount*k+idx) = cov(k-i, 1+0); idx++;}\n          if(useXY) {CovCholesky(componentCount*i+idx, componentCount*k+idx) = cov(k-i, 1+1); idx++;}\n          if(useXZ) {CovCholesky(componentCount*i+idx, componentCount*k+idx) = cov(k-i, 1+2); idx++;}\n          if(useYY) {CovCholesky(componentCount*i+idx, componentCount*k+idx) = cov(k-i, 1+3); idx++;}\n          if(useYZ) {CovCholesky(componentCount*i+idx, componentCount*k+idx) = cov(k-i, 1+4); idx++;}\n          if(useZZ) {CovCholesky(componentCount*i+idx, componentCount*k+idx) = cov(k-i, 1+5); idx++;}\n        }\n\n      cholesky(CovCholesky);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************************************/\n\nvoid ObservationGradiometer::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    OrbitArc      orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n    const UInt    epochCount = orbit.size();\n    const UInt    rhsCount   = rhs.size();\n    Arc::checkSynchronized({orbit, starCamera});\n\n    // earth rotation\n    // --------------\n    std::vector<Rotary3d> rotEarth(epochCount);\n    for(UInt i=0; i<epochCount; i++)\n      rotEarth.at(i) = earthRotation->rotaryMatrix(orbit.at(i).time);\n\n    // reduced observations\n    // ---------------------\n    l = Matrix(componentCount*epochCount, rhsCount);\n\n    for(UInt rhsNo=0; rhsNo<rhsCount; rhsNo++)\n    {\n      GradiometerArc gradiometer = rhs.at(rhsNo)->gradiometerFile->readArc(arcNo);\n      Arc::checkSynchronized({orbit, gradiometer});\n\n      std::vector<GradiometerArc> reference(rhs.at(rhsNo)->referenceFile.size());\n      for(UInt k=0; k<rhs.at(rhsNo)->referenceFile.size(); k++)\n      {\n        reference.at(k) = rhs.at(rhsNo)->referenceFile.at(k)->readArc(arcNo);\n        Arc::checkSynchronized({orbit, reference.at(k)});\n      }\n\n      for(UInt i=0; i<epochCount; i++)\n      {\n        const Time     time     = orbit.at(i).time;\n        const Vector3d posEarth = rotEarth.at(i).rotate(orbit.at(i).position);\n        // referencefield + tides\n        const Tensor3d tns = rhs.at(rhsNo)->referencefield->gravityGradient(time, posEarth)\n                           + rhs.at(rhsNo)->tides->gradient(time, posEarth, rotEarth.at(i), earthRotation, ephemerides);\n        // observed minus computed\n        Tensor3d gravityGradient = gradiometer.at(i).gravityGradient - starCamera.at(i).rotary.inverseRotate(rotEarth.at(i).inverseRotate(tns));\n        // gradients from files\n        for(UInt k=0; k<reference.size(); k++)\n          gravityGradient -= reference.at(k).at(i).gravityGradient;\n\n        UInt idx = 0;\n        if(useXX) l(componentCount*i+idx++, rhsNo) = gravityGradient.xx();\n        if(useXY) l(componentCount*i+idx++, rhsNo) = gravityGradient.xy();\n        if(useXZ) l(componentCount*i+idx++, rhsNo) = gravityGradient.xz();\n        if(useYY) l(componentCount*i+idx++, rhsNo) = gravityGradient.yy();\n        if(useYZ) l(componentCount*i+idx++, rhsNo) = gravityGradient.yz();\n        if(useZZ) l(componentCount*i+idx++, rhsNo) = gravityGradient.zz();\n      }\n    }\n\n    // rotary matrix from TRF to satellite system\n    // ------------------------------------------\n    Matrix rotGRF(componentCount*epochCount, 5*epochCount);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      Matrix rot = inverse(rotEarth.at(i) * starCamera.at(i).rotary).matrix();\n      MatrixSlice R(rotGRF.slice(componentCount*i, 5*i, componentCount,5));\n\n      // One row of the rotary matrix for one gradiometer component (e.g. Txy: i=0, k=1)\n      auto rotationLine = [&](UInt i, UInt k, UInt row)\n      {\n        R(row, 0) = rot(i,0)*rot(k,0) - rot(i,2)*rot(k,2);\n        R(row, 1) = rot(i,0)*rot(k,1) + rot(i,1)*rot(k,0);\n        R(row, 2) = rot(i,0)*rot(k,2) + rot(i,2)*rot(k,0);\n        R(row, 3) = rot(i,1)*rot(k,1) - rot(i,2)*rot(k,2);\n        R(row, 4) = rot(i,1)*rot(k,2) + rot(i,2)*rot(k,1);\n      };\n\n      UInt idx = 0;\n      if(useXX) rotationLine(0, 0, idx++);\n      if(useXY) rotationLine(0, 1, idx++);\n      if(useXZ) rotationLine(0, 2, idx++);\n      if(useYY) rotationLine(1, 1, idx++);\n      if(useYZ) rotationLine(1, 2, idx++);\n      if(useZZ) rotationLine(2, 2, idx++);\n    }\n\n    // gradiometer bias for each component\n    // -----------------------------------\n    B = Matrix();\n    const std::vector<Time> times = orbit.times();\n    sggBias->setInterval(times.front(), times.back()+medianSampling(times), TRUE);\n    if(sggBias->parameterCount())\n    {\n      B = Matrix(componentCount*epochCount, componentCount*sggBias->parameterCount());\n      const Matrix I = identityMatrix(componentCount);\n      for(UInt i=0; i<epochCount; i++)\n        sggBias->designMatrix(times.at(i), I, B.row(componentCount*i, componentCount));\n    }\n\n    // apply sigmas\n    // ------------\n    Double factor = 1./sigma;\n    if(sigmaArc.size())\n      factor *= 1./sigmaArc(arcNo);\n    if(factor!=1.)\n    {\n      rotGRF *= factor;\n      l      *= factor;\n      if(B.size())\n        B *= factor;\n    }\n\n    // decorrelation\n    // -------------\n    if(CovCholesky.size())\n    {\n      if(CovCholesky.rows()<l.rows())\n        throw(Exception(\"covariance matrix to small\"));\n      const_MatrixSlice W(CovCholesky.slice(0,0,l.rows(),l.rows()).trans());\n      triangularSolve(1., W, rotGRF);\n      triangularSolve(1., W, l);\n      if(B.size())\n        triangularSolve(1.,W, B);\n    }\n\n    // Design matrix A\n    // ---------------\n    A = Matrix(componentCount*epochCount, parameterCount());\n    Matrix tns(6, parametrization->parameterCount());\n    for(UInt i=0; i<epochCount; i++)\n    {\n      parametrization->gravityGradient(orbit.at(i).time, rotEarth.at(i).rotate(orbit.at(i).position), tns);\n      matMult(1., rotGRF.column(5*i,5), tns.row(0,5), A.column(0,tns.columns()));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationGradiometer.h",
    "content": "/***********************************************/\n/**\n* @file observationGradiometer.h\n*\n* @brief GOCE gradiometer observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-05-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONGRADIOMETER__\n#define __GROOPS_OBSERVATIONGRADIOMETER__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationGradiometer = R\"(\n\\subsection{Gradiometer}\\label{observationType:gradiometer}\nObservation equations for satellite gravity gradiometry (SGG)\n\\begin{equation}\n  \\nabla\\nabla V(\\M r) =\n  \\begin{pmatrix}\n    \\frac{\\partial^2 V}{\\partial x^2}         & \\frac{\\partial^2 V}{\\partial x\\partial y} & \\frac{\\partial^2 V}{\\partial x\\partial z} \\\\\n    \\frac{\\partial^2 V}{\\partial y\\partial x} & \\frac{\\partial^2 V}{\\partial y^2}         & \\frac{\\partial^2 V}{\\partial y\\partial z} \\\\\n    \\frac{\\partial^2 V}{\\partial z\\partial x} & \\frac{\\partial^2 V}{\\partial z\\partial y} & \\frac{\\partial^2 V}{\\partial z^2}\n  \\end{pmatrix}.\n\\end{equation}\nFrom the \\configFile{inputfileGradiometer}{instrument} observations precomputed \\configFile{inputfileReferenceGradiometer}{instrument}\ntogether with other background models are reduced, all given in \\configClass{rightHandSide}{sggRightSideType}.\n\nAll instrument data \\configFile{inputfileGradiometer}{instrument}, \\configFile{inputfileOrbit}{instrument},\nand \\configFile{inputfileStarCamera}{instrument} must be synchronous and be diveded\ninto each short arcs (see \\program{InstrumentSynchronize}).\n\nAdditional to the \\configClass{parametrizationGravity}{parametrizationGravityType}\nan (temporal changing) bias for each gradiometer component and arc can be estimated with\n\\configClass{parametrizationBias}{parametrizationTemporalType}.\n\nThe accuracy or the full covariance matrix of the gradiometer is provided in\n\\config{covarianceSgg} and can be estimated with \\program{PreprocessingGradiometer}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/observationMisc.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GOCE gradiometer observations.\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationGradiometer : public Observation\n{\n  std::vector<SggRightSidePtr> rhs; // right hand sides\n  InstrumentFile               orbitFile;\n  InstrumentFile               starCameraFile;\n  EarthRotationPtr             earthRotation;\n  EphemeridesPtr               ephemerides;\n  ParametrizationGravityPtr    parametrization;\n  ParametrizationTemporalPtr   sggBias;\n  UInt                         componentCount;\n  Bool                         useXX, useYY, useZZ;\n  Bool                         useXY, useXZ, useYZ;\n  Double                       sigma;\n  Vector                       sigmaArc;\n  Matrix                       CovCholesky; // cholesky decomposition of the Covariance\n\npublic:\n  ObservationGradiometer(Config &config);\n ~ObservationGradiometer() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return parametrization->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()        const override {return parametrization->parameterCount();}\n  UInt gravityParameterCount() const override {return parametrization->parameterCount();}\n  UInt rightSideCount()        const override {return rhs.size();}\n  UInt arcCount()              const override {return orbitFile.arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {parametrization->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/observation/observationPodAcceleration.cpp",
    "content": "/***********************************************/\n/**\n* @file observationPodAcceleration.cpp\n*\n* @brief Precise Orbit Data (POD) observations (Acceleration approach).\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-02-02\n* update 2011-06-09 Norbert Zehentner\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationPodAcceleration.h\"\n\n/***********************************************/\n\nObservationPodAcceleration::ObservationPodAcceleration(Config &config)\n{\n  try\n  {\n    FileName fileNameSatellite;\n    FileName orbitName, starCameraName;\n    UInt     epochCount, interpolationDegree;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\",     date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",      date2time(2020, 6,  3));\n    renameDeprecatedConfig(config, \"parameter\",      \"parametrizationAcceleration\", date2time(2020, 6,  3));\n\n    readConfig(config, \"inputfileSatelliteModel\",     fileNameSatellite,            Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"rightHandSide\",               rhs,                          Config::MUSTSET,  \"\",    \"input for the reduced observation vector\");\n    readConfig(config, \"inputfileOrbit\",              orbitName,                    Config::MUSTSET,  \"\",    \"used to evaluate the observation equations, not used as observations\");\n    readConfig(config, \"inputfileStarCamera\",         starCameraName,               Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"earthRotation\",               earthRotation,                Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",                 ephemerides,                  Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationGravity\",      parametrization,              Config::MUSTSET,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration\", parametrizationAcceleration,  Config::DEFAULT,  \"\",    \"orbit force parameters\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,          Config::DEFAULT,  \"8\",   \"orbit differentation  by polynomial approximation of degree n\");\n    readConfig(config, \"numberOfEpochs\",              epochCount,                   Config::DEFAULT,  \"9\",   \"number of used Epochs for polynom computation\");\n    readConfig(config, \"covariancePod\",               covPod,                       Config::OPTIONAL, \"\",    \"covariance matrix of kinematic orbits\");\n    if(isCreateSchema(config)) return;\n\n    // test if epochCount and polynomial degree are correct\n    // ---------------------\n    if(interpolationDegree%2 != 0)\n      throw(Exception(\"polnomial degree for interpolation must be even.\"));\n    if(epochCount <= interpolationDegree)\n      throw(Exception(\"Epochs must be greater than interpolationdegree, at least by one.\"));\n    if(epochCount%2 != 1)\n      throw(Exception(\"Epochs must be odd (symmetry around central point).\"));\n\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    // test instrument files\n    // ---------------------\n    orbitFile.open(orbitName);\n    starCameraFile.open(starCameraName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n    for(UInt j=0; j<rhs.size(); j++)\n      InstrumentFile::checkArcCount({orbitFile, *rhs.at(j)->orbitFile, *rhs.at(j)->accelerometerFile});\n\n    // orbit differentation coefficients (position -> acceleration) by means of QR-decomposition\n    // with or without overdetermination\n    // -----------------------\n    Matrix P(epochCount, interpolationDegree+1);\n    for(UInt i=0; i<epochCount; i++)\n      for(UInt n=0; n<=interpolationDegree; n++)\n        P(i,n) = ((n==0) ? 1.0 : std::pow(i-(epochCount-1.)/2., n));\n\n    const Vector tau = QR_decomposition(P);\n    coeff = Vector(epochCount);\n    coeff(2) = 2.0;\n    triangularSolve(1., P.row(0,interpolationDegree+1).trans(), coeff);\n    QMult(P, tau, coeff);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ObservationPodAcceleration::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    change = parametrization->setInterval(timeStart, timeEnd)             || change;\n    change = parametrizationAcceleration->setInterval(timeStart, timeEnd) || change;\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt ObservationPodAcceleration::parameterCount() const\n{\n  return parametrization->parameterCount() + parametrizationAcceleration->parameterCount();\n}\n\n/***********************************************/\n\nvoid ObservationPodAcceleration::parameterName(std::vector<ParameterName> &name) const\n{\n  if(parametrization)\n    parametrization->parameterName(name);\n\n  if(parametrizationAcceleration)\n  {\n    parametrizationAcceleration->parameterName(name);\n    const std::string satelliteName = satellite ? satellite->satelliteName : \"satellite\";\n    for(UInt i=name.size(); i-->name.size()-parametrizationAcceleration->parameterCount();)\n      name.at(i).object = satelliteName;\n  }\n}\n\n/***********************************************/\n\nvoid ObservationPodAcceleration::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    OrbitArc      orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n    UInt          rhsCount   = rhs.size();\n    UInt          posCount   = orbit.size();\n    UInt          obsCount   = posCount-coeff.rows()+1;\n    UInt          half       = (coeff.rows()-1)/2;\n    Double        dt         = medianSampling(orbit.times()).seconds();\n    Arc::checkSynchronized({orbit, starCamera});\n\n    parametrizationAcceleration->setIntervalArc(orbit.at(half).time, orbit.at(obsCount+half-1).time+seconds2time(dt));\n\n    // calculate earthrotation\n    // -----------------------\n    std::vector<Rotary3d> rotEarth(obsCount);\n    for(UInt k=0; k<obsCount; k++)\n      rotEarth.at(k) = earthRotation->rotaryMatrix(orbit.at(k+half).time);\n\n    // reference acceleration\n    // ----------------------\n    std::vector<std::vector<Vector3d>> reference(rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      reference.at(j).resize(obsCount);\n      AccelerometerArc accelerometer = rhs.at(j)->accelerometerFile->readArc(arcNo);\n      Arc::checkSynchronized({orbit, accelerometer});\n\n      for(UInt k=0; k<obsCount; k++)\n      {\n        Vector3d g = rhs.at(j)->forces->acceleration(satellite, orbit.at(k+half).time, orbit.at(k+half).position, orbit.at(k+half).velocity,\n                                                     starCamera.at(k+half).rotary, rotEarth.at(k), earthRotation, ephemerides);\n        if(accelerometer.size())\n          g += rotEarth.at(k).rotate(starCamera.at(k+half).rotary.rotate(accelerometer.at(k+half).acceleration)); // accelerometer\n        reference.at(j).at(k) = g; // reference observations\n      }\n    }\n\n    // reduced observations\n    // --------------------\n    l = Matrix(3*obsCount, rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      OrbitArc orbitPod = rhs.at(j)->orbitFile->readArc(arcNo);\n      for(UInt k=0; k<obsCount; k++)\n        {\n          Vector3d a;\n          for(UInt i=0; i<coeff.rows(); i++)\n            a += (coeff(i)/dt/dt) * orbitPod.at(k+i).position;\n          a = rotEarth.at(k).rotate(a);\n\n          l(3*k+0,j) = a.x() - reference.at(j).at(k).x();\n          l(3*k+1,j) = a.y() - reference.at(j).at(k).y();\n          l(3*k+2,j) = a.z() - reference.at(j).at(k).z();\n        }\n    }\n\n    // Design matrix A and B\n    // ---------------------\n    A = Matrix(3*obsCount, parametrization->parameterCount() + parametrizationAcceleration->parameterCount());\n    B = Matrix(3*obsCount, parametrizationAcceleration->parameterCountArc());\n    // gravity\n    for(UInt k=0; k<obsCount; k++)\n      parametrization->gravity(orbit.at(k+half).time, rotEarth.at(k).rotate(orbit.at(k+half).position), A.slice(3*k, 0, 3, parametrization->parameterCount()));\n\n    // orbit parameters\n    for(UInt k=0; k<obsCount; k++)\n    {\n      parametrizationAcceleration->compute(satellite, orbit.at(k+half).time, orbit.at(k+half).position, orbit.at(k+half).velocity,\n                                           starCamera.at(k+half).rotary, rotEarth.at(k), ephemerides,\n                                           A.slice(3*k, parametrization->parameterCount(), 3, parametrizationAcceleration->parameterCount()), B.row(3*k,3));\n    }\n\n    // decorrelation\n    // -------------\n    if(covPod)\n    {\n      // linearized variance propagation\n      Matrix D(3*obsCount, 3*posCount);\n      for(UInt k=0; k<obsCount; k++)\n        for(UInt i=0; i<coeff.rows(); i++)\n          axpy((coeff(i)/dt/dt), rotEarth.at(k).matrix(), D.slice(3*k,3*(k+i),3,3));\n      Matrix C = covPod->covariance(arcNo, orbit);\n      Matrix DCD = D * C * D.trans();\n      DCD.setType(Matrix::SYMMETRIC);\n      cholesky(DCD);\n\n      // apply Cholesky matrix\n      triangularSolve(1., DCD.trans(), A);\n      triangularSolve(1., DCD.trans(), l);\n      if(B.size())\n        triangularSolve(1., DCD.trans(), B);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationPodAcceleration.h",
    "content": "/***********************************************/\n/**\n* @file observationPodAcceleration.h\n*\n* @brief Precise Orbit Data (POD) observations (Acceleration approach).\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-02-02\n* update 2011-06-09 Norbert Zehentner\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONPODACCELERATION__\n#define __GROOPS_OBSERVATIONPODACCELERATION__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationPodAcceleration = R\"(\n\\subsection{PodAcceleration}\\label{observationType:podAcceleration}\nThe observation equations for precise orbit data (POD) are given by\n\\begin{equation}\n\\ddot{\\M r}(t) - \\M g_0(t) = \\nabla V(\\M r, t),\n\\end{equation}\nwhere the accelerations of the satellite $\\ddot{\\M r}(t)$ are derived from the kinematic positions\nin \\configClass{rightHandSide}{podRightSideType}. The orbit differentation is performed by a moving\npolynomial interpolation or approximation with degree \\config{interpolationDegree}\nand number of used epochs \\config{numberOfEpochs}. The reference forces $\\M g_0(t)$ are computed\nwith the background models in \\configClass{rightHandSide}{podRightSideType}.\n\nAll instrument data \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument},\nand \\configFile{inputfileAccelerometer}{instrument} must be synchronous and be given\nwith a constant sampling without any gaps in each short arc (see \\program{InstrumentSynchronize}).\n\nThe unknown gravity field $\\nabla V(\\M r, t)$ parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis not evaluated at the observed positions but at the orbit given by \\configFile{inputfileOrbit}{instrument}.\nThe same is true for the reference forces. This orbit may be a more accurate dynamical orbit but\nin most cases the kinematic orbit provides good results.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit Data (POD) observations (Acceleration approach).\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationPodAcceleration : public Observation\n{\n  SatelliteModelPtr              satellite;\n  std::vector<PodRightSidePtr>   rhs; // right hand sides\n  CovariancePodPtr               covPod;\n  InstrumentFile                 orbitFile;\n  InstrumentFile                 starCameraFile;\n  EarthRotationPtr               earthRotation;\n  EphemeridesPtr                 ephemerides;\n  ParametrizationGravityPtr      parametrization;\n  ParametrizationAccelerationPtr parametrizationAcceleration;\n  Vector                         coeff;\n\npublic:\n  ObservationPodAcceleration(Config &config);\n ~ObservationPodAcceleration() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount()        const override;\n  UInt gravityParameterCount() const override {return parametrization->parameterCount();}\n  UInt rightSideCount()        const override {return rhs.size();}\n  UInt arcCount()              const override {return orbitFile.arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationPodEnergy.cpp",
    "content": "/***********************************************/\n/**\n* @file observationPodEnergy.cpp\n*\n* @brief Precise Orbit Data (POD) observations (Energy integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-02-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"classes/observation/observationPodEnergy.h\"\n\n/***********************************************/\n\nObservationPodEnergy::ObservationPodEnergy(Config &config)\n{\n  try\n  {\n    FileName fileNameSatellite;\n    FileName orbitName, starCameraName;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\", date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",  date2time(2020, 6,  3));\n\n    readConfig(config, \"inputfileSatelliteModel\", fileNameSatellite,   Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"rightHandSide\",           rhs,                 Config::MUSTSET,   \"\",   \"input for the reduced observation vector\");\n    readConfig(config, \"inputfileOrbit\",          orbitName,           Config::MUSTSET,   \"\",   \"used to evaluate the observation equations, not used as observations\");\n    readConfig(config, \"inputfileStarCamera\",     starCameraName,      Config::MUSTSET,   \"\",   \"\");\n    readConfig(config, \"earthRotation\",           earthRotation,       Config::MUSTSET,   \"\",   \"\");\n    readConfig(config, \"ephemerides\",             ephemerides,         Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationGravity\",  parametrization,     Config::MUSTSET,   \"\",   \"gravity field parametrization (potential)\");\n    readConfig(config, \"parametrizationBias\",     bias,                Config::MUSTSET,   \"\",   \"unknown total energy per arc\");\n    readConfig(config, \"interpolationDegree\",     interpolationDegree, Config::DEFAULT,   \"8\",  \"orbit differentiation  by polynomial approximation of degree n\");\n    readConfig(config, \"integrationDegree\",       integrationDegree,   Config::DEFAULT,   \"7\",  \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"covariancePod\",           covPod,              Config::OPTIONAL,  \"\",   \"covariance matrix of kinematic orbits\");\n    if(isCreateSchema(config)) return;\n\n    if(interpolationDegree%2 != 0)\n      throw(Exception(\"polnomial degree for interpolation must be even.\"));\n\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    // test instrument files\n    // ---------------------\n    orbitFile.open(orbitName);\n    starCameraFile.open(starCameraName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n    for(UInt j=0; j<rhs.size(); j++)\n      InstrumentFile::checkArcCount({orbitFile, *rhs.at(j)->orbitFile, *rhs.at(j)->accelerometerFile});\n\n    // orbit differentation coefficients (position -> velocity)\n    Matrix P(interpolationDegree+1, interpolationDegree+1);\n    for(UInt i=0; i<=interpolationDegree; i++)\n      for(UInt n=0; n<=interpolationDegree; n++)\n        P(n,i) = ((n==0) ? 1.0 : std::pow((static_cast<Double>(i)-interpolationDegree/2), n));\n    coeff = Vector(interpolationDegree+1);\n    coeff(1) = 1.0;\n    solveInPlace(P, coeff);\n\n    // polynomial integration matrix\n    integrationMatrix = Matrix(integrationDegree+1, integrationDegree+1);\n    for(UInt i=0; i<integrationMatrix.rows(); i++)\n    {\n      integrationMatrix(0,i) = 1.0;\n      for(UInt n=1; n<integrationMatrix.columns(); n++)\n        integrationMatrix(n,i) = (i-integrationDegree/2.) * integrationMatrix(n-1,i);\n    }\n    inverse(integrationMatrix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationPodEnergy::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    OrbitArc      orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n    UInt          rhsCount   = rhs.size();\n    UInt          posCount   = orbit.size();\n    UInt          obsCount   = posCount-interpolationDegree;\n    UInt          half       = interpolationDegree/2;\n    Double        dt         = (orbit.at(half+1).time - orbit.at(half).time).seconds();\n    Arc::checkSynchronized({orbit, starCamera});\n\n    // calculate earthrotation\n    // -----------------------\n    std::vector<Rotary3d>  rotEarth(obsCount);\n    std::vector<Vector3d>  rotAxis(obsCount);\n    std::vector<Vector3d>  rotAxisDot(obsCount);\n    for(UInt k=0; k<obsCount; k++)\n    {\n      const Time time = orbit.at(k+half).time;\n      rotEarth.at(k)   = earthRotation->rotaryMatrix(time);\n      rotAxis.at(k)    = earthRotation->rotaryAxis(time);\n      rotAxisDot.at(k) = earthRotation->rotaryAxisDerivate(time);\n    }\n\n    // position + velocity\n    // -------------------\n    std::vector<std::vector<Vector3d>> position(rhsCount);\n    std::vector<std::vector<Vector3d>> velocity(rhsCount);\n    std::vector<std::vector<Vector3d>> velocityEarth(rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      OrbitArc orbit = rhs.at(j)->orbitFile->readArc(arcNo);\n      position.at(j).resize(obsCount);\n      velocity.at(j).resize(obsCount);\n      velocityEarth.at(j).resize(obsCount);\n      for(UInt k=0; k<obsCount; k++)\n      {\n        position.at(j).at(k) = orbit.at(k+half).position;\n        for(UInt i=0; i<coeff.rows(); i++)\n          velocity.at(j).at(k) += (coeff(i)/dt) * orbit.at(k+i).position;\n        // Earth fixed velocity in spaced fixed coordinates\n        velocityEarth.at(j).at(k) = velocity.at(j).at(k) - crossProduct(rotAxis.at(k), position.at(j).at(k));\n      }\n    }\n\n    // reference acceleration\n    // ----------------------\n    Matrix integrand(obsCount, rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      AccelerometerArc accl = rhs.at(j)->accelerometerFile->readArc(arcNo);\n      for(UInt k=0; k<obsCount; k++)\n      {\n        Vector3d g = rhs.at(j)->forces->acceleration(satellite, orbit.at(k+half).time, orbit.at(k+half).position, orbit.at(k+half).velocity,\n                                                     starCamera.at(k+half).rotary, rotEarth.at(k), earthRotation, ephemerides);\n        g = rotEarth.at(k).inverseRotate(g);                               // rotation into CRF\n        if(accl.size()!=0)\n          g += starCamera.at(k+half).rotary.rotate(accl.at(k+half).acceleration); // accelerometer\n\n        integrand(k,j) = inner(g, velocityEarth.at(j).at(k))\n                       - inner(crossProduct(rotAxisDot.at(k), position.at(j).at(k)), velocity.at(j).at(k));\n      }\n    }\n\n    // reduced observations\n    // --------------------\n    l = Matrix(obsCount, rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      const Double l0 = 0.5 * velocity.at(j).at(0).quadsum() - inner(velocity.at(j).at(0), crossProduct(rotAxis.at(0), position.at(j).at(0)));\n      for(UInt k=1; k<obsCount; k++)\n        l(k,j) = 0.5 * velocity.at(j).at(k).quadsum() - inner(velocity.at(j).at(k), crossProduct(rotAxis.at(k), position.at(j).at(k))) - l0;\n    }\n\n    // reduce integral\n    // ---------------\n    Matrix integral(integrand.rows(), integrand.columns());\n    Vector integralFactors;\n    for(UInt i=1; i<integrand.rows(); i++)\n    {\n      const UInt idx = std::min(std::max(i, integrationDegree/2)-integrationDegree/2, integrand.rows()-integrationDegree-1);\n      if((i<=integrationDegree/2) || (i>=integrand.rows()-(integrationDegree+1)/2))\n      {\n        integralFactors = Vector(integrationDegree+1);\n        const Double tau1 = i-idx-integrationDegree/2.-1;\n        const Double tau2 = i-idx-integrationDegree/2.;\n        for(UInt n=0; n<integralFactors.rows(); n++)\n          axpy(dt/(n+1)*(std::pow(tau2, n+1)-std::pow(tau1, n+1)), integrationMatrix.column(n), integralFactors);\n      }\n      integral.row(i) += integral.row(i-1);\n      matMult(-1., integralFactors.trans(), integrand.row(idx, integralFactors.rows()), integral.row(i));\n    }\n    l -= integral;\n\n    // arc related parameters (energy constant)\n    // ----------------------------------------\n    B = Matrix();\n    const std::vector<Time> times = orbit.times();\n    bias->setInterval(times.front(), times.back()+medianSampling(times), TRUE);\n    if(bias->parameterCount())\n    {\n      B = Matrix(obsCount, bias->parameterCount());\n      for(UInt i=0; i<obsCount; i++)\n        copy(bias->factors(orbit.at(i+half).time).trans(), B.row(i));\n    }\n\n    // Design matrix A (gravitational potential)\n    // -----------------------------------------\n    A = Matrix(obsCount, parametrization->parameterCount());\n    for(UInt k=0; k<obsCount; k++)\n      parametrization->potential(orbit.at(k+half).time, rotEarth.at(k).rotate(orbit.at(k+half).position), A.row(k));\n\n    // decorrelation\n    // -------------\n    if(covPod)\n    {\n      // linearized variance propagation\n      Matrix D(obsCount, 3*posCount);\n      for(UInt k=0; k<obsCount; k++)\n        for(UInt i=0; i<coeff.rows(); i++)\n        {\n          D(k,3*(i+k)+0) = (coeff(i)/dt) * velocity.at(0).at(k).x();\n          D(k,3*(i+k)+1) = (coeff(i)/dt) * velocity.at(0).at(k).y();\n          D(k,3*(i+k)+2) = (coeff(i)/dt) * velocity.at(0).at(k).z();\n        }\n\n      Matrix C = covPod->covariance(arcNo, orbit);\n      Matrix DCD = D * C * D.trans();\n      DCD.setType(Matrix::SYMMETRIC);\n      cholesky(DCD);\n\n      // apply Cholesky matrix\n      triangularSolve(1., DCD.trans(), A);\n      triangularSolve(1., DCD.trans(), l);\n      if(B.size()!=0)\n        triangularSolve(1., DCD.trans(), B);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationPodEnergy.h",
    "content": "/***********************************************/\n/**\n* @file observationPodEnergy.h\n*\n* @brief Precise Orbit Data (POD) observations (Energy integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-02-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONPODENERGY__\n#define __GROOPS_OBSERVATIONPODENERGY__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationPodEnergy = R\"(\n\\subsection{PodEnergy}\\label{observationType:podEnergy}\nThe observation equations for precise orbit data (POD) are given by\n\\begin{equation}\n  \\frac{1}{2}\\dot{\\M r}^2\n  -\\dot{\\M r} \\cdot (\\M\\Omega\\times\\M r)\n  +\\int_{t_0}^t(\\dot{\\M\\Omega}\\times\\M r)\\cdot \\dot{\\M r}\\,dt\n  - \\int_{t_0}^t \\M g_0 \\cdot\\dot{\\M r}'\\,dt\n  = V + E.\n\\end{equation}\nwhere the velocities of the satellite $\\dot{\\M r}(t)$ are derived from\nthe kinematic positions in \\configClass{rightHandSide}{podRightSideType} and the Earth's rotation vector~$\\M\\Omega(t)$ is modeled\nwithin \\configClass{earthRotation}{earthRotationType}. The orbit differentiation is\nperformed by a polynomial interpolation with degree \\config{interpolationDegree}.\nThe integrals are solved by a polynomial interpolation with degree \\config{integrationDegree}.\nThe reference forces $\\M g_0(t)$ are computed with the background models in \\configClass{rightHandSide}{podRightSideType}.\n\nAll instrument data \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument}, and \\configFile{inputfileAccelerometer}{instrument}\nmust be synchronous and be given with a constant sampling without any gaps in each short arc\n(see \\program{InstrumentSynchronize}).\n\nThe unknown gravity potential $V(\\M r)$ parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis not evaluated at the observed positions but at the orbit given by \\configFile{inputfileOrbit}{instrument}.\nThe same is true for the reference forces. This orbit may be a more accurate dynamical orbit but\nin most cases the kinematic orbit provides good results.\n\nAn unknown energy bias~$E$ per arc is parametrized by \\configClass{parametrizationBias}{parametrizationTemporalType}\nand should be a constant in theory but temporal changes might help to absorb other unmodelled effects.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit Data (POD) observations (Energy integral).\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationPodEnergy : public Observation\n{\n  SatelliteModelPtr            satellite;\n  std::vector<PodRightSidePtr> rhs; // right hand sides\n  CovariancePodPtr             covPod;\n  InstrumentFile               orbitFile;\n  InstrumentFile               starCameraFile;\n  EarthRotationPtr             earthRotation;\n  EphemeridesPtr               ephemerides;\n  ParametrizationGravityPtr    parametrization;\n  ParametrizationTemporalPtr   bias;\n  UInt                         interpolationDegree, integrationDegree;\n  Vector                       coeff;\n  Matrix                       integrationMatrix;\n\npublic:\n  ObservationPodEnergy(Config &config);\n ~ObservationPodEnergy() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return parametrization->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()        const override {return parametrization->parameterCount();}\n  UInt gravityParameterCount() const override {return parametrization->parameterCount();}\n  UInt rightSideCount()        const override {return rhs.size();}\n  UInt arcCount()              const override {return orbitFile.arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {parametrization->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationPodIntegral.cpp",
    "content": "/***********************************************/\n/**\n* @file observationPodIntegral.cpp\n*\n* @brief Precise Orbit Data (POD) observations (short arc integral).\n* Solution of the Fredholm integral.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-12-22\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"misc/observation/observationMiscPodIntegral.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationPodIntegral.h\"\n\n/***********************************************/\n\nObservationPodIntegral::ObservationPodIntegral(Config &config)\n{\n  try\n  {\n    observationMisc = ObservationMiscPodIntegralPtr(new ObservationMiscPodIntegral(config));\n    readConfig(config, \"covariancePod\", covPod, Config::OPTIONAL, \"\", \"covariance matrix of kinematic orbits\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationPodIntegral::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    ObservationMiscPod::Arc arc = observationMisc->computeArc(arcNo, covPod);\n    l = arc.l;\n    A = arc.A;\n    B = arc.B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationPodIntegral.h",
    "content": "/***********************************************/\n/**\n* @file observationPodIntegral.h\n*\n* @brief Precise Orbit Data (POD) observations (short arc integral).\n* Solution of the Fredholm integral.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-1222\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONPODINTEGRAL__\n#define __GROOPS_OBSERVATIONPODINTEGRAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationPodIntegral = R\"(\n\\subsection{PodIntegral}\\label{observationType:podIntegral}\nThe observation equations for precise orbit data (POD) of short arcs are given by\n\\begin{equation}\n  {\\M r}_\\epsilon(\\tau) = {\\M r}_A(1-\\tau) + {\\M r}_B\\tau - T^2\\int_0^1 K(\\tau,\\tau')\n  \\left(\\M f_0(\\tau')+\\nabla V(\\tau')\\right)\\,d\\tau'\n\\end{equation}\nwith the integral kernel\n\\begin{equation}\n  K(\\tau,\\tau') = \\begin{cases} \\tau'(1-\\tau) & \\text{for }\\tau'\\le\\tau \\\\\n  \\tau(1-\\tau') & \\text{for }\\tau'>\\tau \\end{cases},\n\\end{equation}\nand the normalized time\n\\begin{equation}\n  \\tau = \\frac{t-t_A}{T}\\qquad\\text{with}\\qquad T=t_B-t_A.\n\\end{equation}\nThe kinematic positions~${\\M r}_\\epsilon(\\tau)$ as pseudo observations are taken from\n\\configClass{rightHandSide}{podRightSideType}. From these positions the influence of the reference forces $\\M f_0(\\tau)$\nis subtracted which are computed with the background models in \\configClass{rightHandSide}{podRightSideType}.\nThe integral is solved by the integration of a moving interpolation polynomial of degree \\config{integrationDegree}.\nThe boundary values ${\\M r}_A$ and ${\\M r}_B$ (satellite's state vector) are estimated per arc\nand are usually directly eliminated if \\config{keepSatelliteStates} is not set.\n\nThe unknown gravity field $\\nabla V(\\M r, t)$ parametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}\nis not evaluated at the observed positions but at the orbit given by \\configFile{inputfileOrbit}{instrument}.\nThe same is true for the reference forces. The linearized effect of the gravity field change by the position\nadjustment is taken into account by \\config{gradientfield}. This may be a low order field up to a\nspherical harmonics degree of $n=2$ or $n=3$.\n\nThe \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument}, and \\configFile{inputfileAccelerometer}{instrument}\nmust be synchronous and must be given with a constant sampling and without any gaps in each short arc\n(see \\program{InstrumentSynchronize}).\nThe kinematic positions~${\\M r}_\\epsilon(\\tau)$ should not given equally spaced in time\nbut must be divided into the same arcs as the other instrument data.\nThe observation equations are interpolated to this time by a polynomial interpolation\nwith degree \\config{interpolationDegree}.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\nFor \\config{accelerateComputation} see \\configClass{observation:podVariational}{observationType:podVariational}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|,\n\\end{itemize}\nand for each arc if \\config{keepSatelliteStates} is set\n\\begin{itemize}\n\\item \\verb|<satellite>:arc<no>.position.start.x::|,\n\\item \\verb|<satellite>:arc<no>.position.start.y::|,\n\\item \\verb|<satellite>:arc<no>.position.start.z::|.\n\\item \\verb|<satellite>:arc<no>.position.end.x::|,\n\\item \\verb|<satellite>:arc<no>.position.end.y::|,\n\\item \\verb|<satellite>:arc<no>.position.end.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/observationMiscPodIntegral.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit Data (POD) observations (short arc integral).\n* @ingroup observationGroup\n* Solution of the Fredholm integral.\n* @see Observation */\nclass ObservationPodIntegral : public Observation\n{\n  ObservationMiscPodIntegralPtr observationMisc;\n  CovariancePodPtr              covPod;\n\npublic:\n  ObservationPodIntegral(Config &config);\n ~ObservationPodIntegral() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return observationMisc->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return observationMisc->parameterCount();}\n  UInt gravityParameterCount()   const override {return observationMisc->gravityParameterCount();}\n  UInt rightSideCount()          const override {return observationMisc->rightSideCount();}\n  UInt arcCount()                const override {return observationMisc->arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {observationMisc->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationPodVariational.cpp",
    "content": "/***********************************************/\n/**\n* @file observationPodVariational.cpp\n*\n* @brief Precise Orbit Data (POD) observations (Variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-08-20\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"misc/observation/observationMiscPodVariational.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationPodVariational.h\"\n\n/***********************************************/\n\nObservationPodVariational::ObservationPodVariational(Config &config)\n{\n  try\n  {\n    observationMisc = ObservationMiscPodVariationalPtr(new ObservationMiscPodVariational(config));\n    readConfig(config, \"covariancePod\", covPod, Config::OPTIONAL, \"\", \"covariance matrix of kinematic orbits\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationPodVariational::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    ObservationMiscPod::Arc arc = observationMisc->computeArc(arcNo, covPod);\n    l = arc.l;\n    A = arc.A;\n    B = arc.B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationPodVariational.h",
    "content": "/***********************************************/\n/**\n* @file observationPodVariational.h\n*\n* @brief Precise Orbit Data (POD) observations (Variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-08-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONPODVARIATIONAL__\n#define __GROOPS_OBSERVATIONPODVARIATIONAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationPodVariational = R\"(\n\\subsection{PodVariational}\\label{observationType:podVariational}\nThe observation equations for precise orbit data (POD) are formulated as variational equations.\nIt is based on \\file{inputfileVariational}{variationalEquation} calculated with \\program{PreprocessingVariationalEquation}.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree \\config{integrationDegree}.\n\nThe kinematic positions as pseudo observations are taken from\n\\config{rightHandSide} and should not be given equally spaced in time. The observation\nequations are interpolated to these times by a moving polynomial of degree \\config{interpolationDegree}.\n\nThe accuracy or the full covariance matrix of the precise orbit data is provided in\n\\configClass{covariancePod}{covariancePodType} and can be estimated with \\program{PreprocessingPod}.\n\n\\config{accelerateComputation}: In the event that the sampling of the kinematic orbit is much higher than the sampling\nof the variational equations (e.g. 1 second vs. 5 seconds) the accumulation of the observation equations\ncan be accelerated by transforming the observation equations\n\\begin{equation}\n  \\M l = \\M J \\M A \\M x + \\M e,\n\\end{equation}\nwhere $\\M J$ describes the interpolation of the sampling of the variational design matrix~$\\M A$\nto the sampling of the observations $\\M l$ with more rows than columns. The QR decomposition\n\\begin{equation}\n  \\M J = \\begin{pmatrix} \\M Q_1 & \\M Q_2 \\end{pmatrix}\n         \\begin{pmatrix} \\M R \\\\ \\M 0 \\end{pmatrix}.\n\\end{equation}\ncan be used to transform the observation equations\n\\begin{equation}\n  \\begin{pmatrix} \\M Q_1^T \\M l \\\\ \\M Q_2^T \\M l \\end{pmatrix} =\n  \\begin{pmatrix} \\M Q_1^T \\M R \\\\ \\M 0 \\end{pmatrix} \\M A \\M x +\n  \\begin{pmatrix} \\M Q_1^T \\M e \\\\ \\M Q_2^T \\M e \\end{pmatrix}.\n\\end{equation}\nAs the zero lines should not be considered, the computational time for the accumulation is reduced.\nThis option is not meaningful for evaluating the residuals such as in \\program{PreprocessingPod}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:arc<no>.position0.x::|,\n\\item \\verb|<satellite>:arc<no>.position0.y::|,\n\\item \\verb|<satellite>:arc<no>.position0.z::|.\n\\item \\verb|<satellite>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/observationMiscPodVariational.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit Data (POD) observations (Variational equations).\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationPodVariational : public Observation\n{\n  ObservationMiscPodVariationalPtr observationMisc;\n  CovariancePodPtr                 covPod;\n\npublic:\n  ObservationPodVariational(Config &config);\n ~ObservationPodVariational() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return observationMisc->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return observationMisc->parameterCount();}\n  UInt gravityParameterCount()   const override {return observationMisc->gravityParameterCount();}\n  UInt rightSideCount()          const override {return observationMisc->rightSideCount();}\n  UInt arcCount()                const override {return observationMisc->arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {observationMisc->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationSstIntegral.cpp",
    "content": "/***********************************************/\n/**\n* @file observationSstIntegral.cpp\n*\n* @brief Satellite to satellite tracking (Short Arc Integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-11-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"misc/observation/observationMiscSstIntegral.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"classes/observation/observation.h\"\n#include \"observationSstIntegral.h\"\n\n/***********************************************/\n\nObservationSstIntegral::ObservationSstIntegral(Config &config)\n{\n  try\n  {\n    observationMisc = ObservationMiscSstIntegralPtr(new ObservationMiscSstIntegral(config));\n    readConfig(config, \"covarianceSst\",  covSst,  Config::MUSTSET, \"\", \"covariance matrix of satellite to satellite tracking observations\");\n    readConfig(config, \"covariancePod1\", covPod1, Config::MUSTSET, \"\", \"covariance matrix of kinematic orbits (satellite 1)\");\n    readConfig(config, \"covariancePod2\", covPod2, Config::MUSTSET, \"\", \"covariance matrix of kinematic orbits (satellite 2)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationSstIntegral::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    ObservationMiscSstIntegral::Arc arc = observationMisc->computeArc(arcNo, covSst, covPod1, covPod2);\n    l = arc.l;\n    A = arc.A;\n    B = arc.B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationSstIntegral.h",
    "content": "/***********************************************/\n/**\n* @file observationSstIntegral.h\n*\n* @brief Satellite to satellite tracking (Short Arc Integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-11-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONSSTINTEGRAL__\n#define __GROOPS_OBSERVATIONSSTINTEGRAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationSstIntegral = R\"(\n\\subsection{SstIntegral}\\label{observationType:sstIntegral}\nLike \\configClass{observation:podIntegral}{observationType:podIntegral} (see there for details)\nbut with two satellites and additional satellite-to-satellite (SST) observations.\n\nIf multiple \\configFile{inputfileSatelliteTracking}{instrument} are given\nall data are added together. So corrections in extra files like the light time correction\ncan easily be added. Empirical parameters for the SST observations can be set up with\n\\configClass{parametrizationSst}{parametrizationSatelliteTrackingType}.\nThe accuracy or the full covariance matrix of SST is provided in\n\\configClass{covarianceSst}{covarianceSstType}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite1>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking>:*:*|,\n\\end{itemize}\nand for each arc if \\config{keepSatelliteStates} is set\n\\begin{itemize}\n\\item \\verb|<satellite1>:arc<no>.position.start.x::|,\n\\item \\verb|<satellite1>:arc<no>.position.start.y::|,\n\\item \\verb|<satellite1>:arc<no>.position.start.z::|.\n\\item \\verb|<satellite1>:arc<no>.position.end.x::|,\n\\item \\verb|<satellite1>:arc<no>.position.end.y::|,\n\\item \\verb|<satellite1>:arc<no>.position.end.z::|.\n\\item \\verb|<satellite2>:arc<no>.position.start.x::|,\n\\item \\verb|<satellite2>:arc<no>.position.start.y::|,\n\\item \\verb|<satellite2>:arc<no>.position.start.z::|.\n\\item \\verb|<satellite2>:arc<no>.position.end.x::|,\n\\item \\verb|<satellite2>:arc<no>.position.end.y::|,\n\\item \\verb|<satellite2>:arc<no>.position.end.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"misc/observation/observationMiscSstIntegral.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/covarianceSst.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite-to-satellite tracking (Short Arc Integral).\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationSstIntegral : public Observation\n{\n  ObservationMiscSstIntegralPtr observationMisc;\n  CovarianceSstPtr covSst;\n  CovariancePodPtr covPod1, covPod2;\n\npublic:\n  ObservationSstIntegral(Config &config);\n ~ObservationSstIntegral() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return observationMisc->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return observationMisc->parameterCount();}\n  UInt gravityParameterCount()   const override {return observationMisc->gravityParameterCount();}\n  UInt rightSideCount()          const override {return observationMisc->rightSideCount();}\n  UInt arcCount()                const override {return observationMisc->arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {observationMisc->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationSstVariational.cpp",
    "content": "/***********************************************/\n/**\n* @file observationSstVariational.cpp\n*\n* @brief Satellite to satellite tracking (Variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-06-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"misc/observation/observationMiscSstVariational.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"classes/observation/observation.h\"\n#include \"observationSstVariational.h\"\n\n/***********************************************/\n\nObservationSstVariational::ObservationSstVariational(Config &config)\n{\n  try\n  {\n    observationMisc = ObservationMiscSstVariationalPtr(new ObservationMiscSstVariational(config));\n    readConfig(config, \"covarianceSst\",  covSst,  Config::MUSTSET, \"\", \"covariance matrix of satellite to satellite tracking observations\");\n    readConfig(config, \"covariancePod1\", covPod1, Config::MUSTSET, \"\", \"covariance matrix of kinematic orbits (satellite 1)\");\n    readConfig(config, \"covariancePod2\", covPod2, Config::MUSTSET, \"\", \"covariance matrix of kinematic orbits (satellite 2)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationSstVariational::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    ObservationMiscSstVariational::Arc arc = observationMisc->computeArc(arcNo, covSst, covPod1, covPod2);\n    l = arc.l;\n    A = arc.A;\n    B = arc.B;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationSstVariational.h",
    "content": "/***********************************************/\n/**\n* @file observationSstVariational.h\n*\n* @brief Satellite to satellite tracking (Variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-06-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONSSTVARIATIONAL__\n#define __GROOPS_OBSERVATIONSSTVARIATIONAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationSstVariational = R\"(\n\\subsection{SstVariational}\\label{observationType:sstVariational}\nLike \\configClass{observation:podVariational}{observationType:podVariational} (see there for details)\nbut with two satellites and additional satellite-to-satellite (SST) observations.\n\nIf multiple \\configFile{inputfileSatelliteTracking}{instrument} are given,\nall data are added together. So corrections in extra files like the light time correction\ncan easily be added. Empirical parameters for the SST observations can be set up with\n\\configClass{parametrizationSst}{parametrizationSatelliteTrackingType}.\nThe accuracy or the full covariance matrix of SST is provided in\n\\configClass{covarianceSst}{covarianceSstType}.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|<satellite1>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite1>:arc<no>.position0.x::|,\n\\item \\verb|<satellite1>:arc<no>.position0.y::|,\n\\item \\verb|<satellite1>:arc<no>.position0.z::|.\n\\item \\verb|<satellite1>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite1>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite2>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite2>:arc<no>.position0.x::|,\n\\item \\verb|<satellite2>:arc<no>.position0.y::|,\n\\item \\verb|<satellite2>:arc<no>.position0.z::|.\n\\item \\verb|<satellite2>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite2>:arc<no>.velocity0.z::|.\n\\item \\verb|<satellite1>.<satellite2>:<parametrizationSatelliteTracking>:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n\n/***********************************************/\n\n#include \"misc/observation/observationMiscSstVariational.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/covarianceSst.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite-to-satellite tracking (Variational equations).\n* @ingroup observationGroup\n* @see Observation */\nclass ObservationSstVariational : public Observation\n{\n  ObservationMiscSstVariationalPtr observationMisc;\n  CovarianceSstPtr covSst;\n  CovariancePodPtr covPod1, covPod2;\n\npublic:\n  ObservationSstVariational(Config &config);\n ~ObservationSstVariational() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return observationMisc->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return observationMisc->parameterCount();}\n  UInt gravityParameterCount()   const override {return observationMisc->gravityParameterCount();}\n  UInt rightSideCount()          const override {return observationMisc->rightSideCount();}\n  UInt arcCount()                const override {return observationMisc->arcCount();}\n  void parameterName(std::vector<ParameterName> &name) const override {observationMisc->parameterName(name);}\n\n  void observation(UInt arc, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationStationLoading.cpp",
    "content": "/***********************************************/\n/**\n* @file observationStationLoading.cpp\n*\n* @brief Loading from station observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-07-17\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationStationLoading.h\"\n\n/***********************************************/\n\nObservationStationLoading::ObservationStationLoading(Config &config)\n{\n  try\n  {\n    FileName              fileNameGrid;\n    ExpressionVariablePtr exprNorth, exprEast, exprUp;\n    ExpressionVariablePtr exprSigmaNorth, exprSigmaEast, exprSigmaUp;\n    FileName              deformationName, potentialName;\n    Double                a, f;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\", date2time(2020, 6, 3));\n\n    if(readConfigSequence(config, \"rightHandSide\", Config::MUSTSET, \"\", \"input for observation vectors\"))\n    {\n      readConfig(config, \"inputfileGriddedData\", fileNameGrid,   Config::MUSTSET,  \"\",      \"station positions with displacement data\");\n      readConfig(config, \"observationNorth\",     exprNorth,      Config::MUSTSET,  \"data0\", \"displacement [m]\");\n      readConfig(config, \"observationEast\",      exprEast,       Config::MUSTSET,  \"data1\", \"displacement [m]\");\n      readConfig(config, \"observationUp\",        exprUp,         Config::MUSTSET,  \"data2\", \"displacement [m]\");\n      readConfig(config, \"sigmaNorth\",           exprSigmaNorth, Config::OPTIONAL, \"data3\", \"accuracy, 1/sigma used as weighting\");\n      readConfig(config, \"sigmaEast\",            exprSigmaEast,  Config::OPTIONAL, \"data4\", \"accuracy, 1/sigma used as weighting\");\n      readConfig(config, \"sigmaUp\",              exprSigmaUp,    Config::OPTIONAL, \"data5\", \"accuracy, 1/sigma used as weighting\");\n      readConfig(config, \"inGlobalFrame\",        inGlobalFrame,  Config::DEFAULT,  \"0\",     \"obs/sigmas given in global x,y,z frame instead of north,east,up\");\n      readConfig(config, \"referencefield\",       referencefield, Config::OPTIONAL, \"\",      \"\");\n      endSequence(config);\n    }\n    readConfig(config, \"time\",                   time,                Config::OPTIONAL, \"\",  \"for reference field and parametrization\");\n    readConfig(config, \"parametrizationGravity\", parametrization,     Config::MUSTSET,  \"\",  \"of loading (+defo) potential\");\n    readConfig(config, \"estimateTranslation\",    estimateTranslation, Config::DEFAULT,  \"1\", \"coordinate center\");\n    readConfig(config, \"estimateScale\",          estimateScale,       Config::DEFAULT,  \"1\", \"scale factor of position\");\n    readConfig(config, \"estimateRotation\",       estimateRotation,    Config::DEFAULT,  \"1\", \"rotation\");\n    readConfig(config, \"inputfileDeformationLoadLoveNumber\", deformationName, Config::MUSTSET,  \"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\", \"\");\n    readConfig(config, \"inputfilePotentialLoadLoveNumber\",   potentialName,   Config::OPTIONAL, \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"if full potential is given and not only loading potential\");\n    readConfig(config, \"R\",                      a,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoid\");\n    readConfig(config, \"inverseFlattening\",      f,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoid, 0: sphere\");\n    if(isCreateSchema(config)) return;\n\n    ellipsoid = Ellipsoid(a, f);\n\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    points = grid.points;\n\n    // evaluate expression\n    // -------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    std::vector<ExpressionVariablePtr> expr({exprNorth, exprEast, exprUp, exprSigmaNorth, exprSigmaEast, exprSigmaUp});\n    std::for_each(expr.begin(), expr.end(), [&](auto expr) {if(expr) expr->simplify(varList);});\n\n    valuesNorth.resize(grid.points.size(), 0.);\n    valuesEast.resize (grid.points.size(), 0.);\n    valuesUp.resize   (grid.points.size(), 0.);\n    sigmasNorth.resize(grid.points.size(), 1.);\n    sigmasEast.resize (grid.points.size(), 1.);\n    sigmasUp.resize   (grid.points.size(), 1.);\n    for(UInt i=0; i<grid.values.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      if(exprNorth)      valuesNorth.at(i) = exprNorth     ->evaluate(varList);\n      if(exprEast)       valuesEast.at(i)  = exprEast      ->evaluate(varList);\n      if(exprUp)         valuesUp.at(i)    = exprUp        ->evaluate(varList);\n      if(exprSigmaNorth) sigmasNorth.at(i) = exprSigmaNorth->evaluate(varList);\n      if(exprSigmaEast)  sigmasEast.at(i)  = exprSigmaEast ->evaluate(varList);\n      if(exprSigmaUp)    sigmasUp.at(i)    = exprSigmaUp   ->evaluate(varList);\n    }\n\n    // load love numbers\n    // -----------------\n    Matrix love;\n    readFileMatrix(deformationName, love);\n    hn = love.column(0);\n    ln = love.column(1);\n\n    // models contain the total mass (loading mass & deformation mass effect)\n    if(!potentialName.empty())\n    {\n      Vector kn;\n      readFileMatrix(potentialName, kn);\n      for(UInt n=2; n<std::min(kn.rows(), hn.rows()); n++)\n        hn(n) /= (1.+kn(n));\n      for(UInt n=2; n<std::min(kn.rows(), ln.rows()); n++)\n        ln(n) /= (1.+kn(n));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationStationLoading::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    parametrization->parameterName(name);\n    if(estimateTranslation)\n    {\n      name.push_back(ParameterName(\"\", \"translation.x\"));\n      name.push_back(ParameterName(\"\", \"translation.y\"));\n      name.push_back(ParameterName(\"\", \"translation.z\"));\n    }\n    if(estimateScale)\n    {\n      name.push_back(ParameterName(\"\", \"scale\"));\n    }\n    if(estimateRotation)\n    {\n      name.push_back(ParameterName(\"\", \"rotation.x\"));\n      name.push_back(ParameterName(\"\", \"rotation.y\"));\n      name.push_back(ParameterName(\"\", \"rotation.z\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationStationLoading::observation(UInt /*arcNo*/, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    // Local (north, east, down) -> global TRF\n    // -------------------------------------\n    std::vector<Transform3d> trf2neu(points.size());\n      for(UInt i=0; i<points.size(); i++)\n        trf2neu.at(i) = inverse(localNorthEastUp(points.at(i), ellipsoid));\n\n    // normal gravity\n    // --------------\n    std::vector<Double> gravity(points.size());\n    for(UInt i=0; i<points.size(); i++)\n      gravity.at(i) = Planets::normalGravity(points.at(i));\n\n    // observations\n    // ------------\n    l = Matrix(3*points.size(), 1);\n    for(UInt i=0; i<points.size(); i++)\n    {\n      const Vector3d obs = Vector3d(valuesNorth.at(i), valuesEast.at(i), valuesUp.at(i));\n      l(3*i+0, 0) = obs.x();\n      l(3*i+1, 0) = obs.y();\n      l(3*i+2, 0) = obs.z();\n    }\n\n    // reduce reference displacement\n    // -----------------------------\n    if(referencefield)\n    {\n      std::vector<std::vector<Vector3d>> referenceDefo(points.size(), std::vector<Vector3d>(1));\n      referencefield->deformation({time}, points, gravity, hn, ln, referenceDefo);\n      for(UInt i=0; i<points.size(); i++)\n      {\n        Vector3d d = referenceDefo.at(i).at(0);\n        if(!inGlobalFrame)\n          d = trf2neu.at(i).transform(d);\n        l(3*i+0, 0) -= d.x();\n        l(3*i+1, 0) -= d.y();\n        l(3*i+2, 0) -= d.z();\n      }\n    }\n\n    // design matrix A\n    // ---------------\n    A = Matrix(3*points.size(), parameterCount());\n    B = Matrix();\n    for(UInt i=0; i<points.size(); i++)\n    {\n      parametrization->deformation(time, points.at(i), gravity.at(i), hn, ln, A.slice(3*i, 0, 3, parametrization->parameterCount()));\n\n      // helmert transformation\n      UInt idx = parametrization->parameterCount();\n      if(estimateTranslation)\n      {\n        A(3*i+0, idx+0) = 1.;\n        A(3*i+1, idx+1) = 1.;\n        A(3*i+2, idx+2) = 1.;\n        idx += 3;\n      }\n      if(estimateScale)\n      {\n        A(3*i+0, idx+3) =  points.at(i).x();\n        A(3*i+1, idx+3) =  points.at(i).y();\n        A(3*i+2, idx+3) =  points.at(i).z();\n        idx++;\n      }\n      if(estimateRotation)\n      {\n        A(3*i+0, idx+5) =  points.at(i).z();\n        A(3*i+0, idx+6) = -points.at(i).y();\n        A(3*i+1, idx+4) = -points.at(i).z();\n        A(3*i+1, idx+6) =  points.at(i).x();\n        A(3*i+2, idx+4) =  points.at(i).y();\n        A(3*i+2, idx+5) = -points.at(i).x();\n        idx += 3;\n      }\n\n      // rotate into local system\n      if(!inGlobalFrame)\n        copy(trf2neu.at(i).matrix()*A.row(3*i,3), A.row(3*i,3));\n    }\n\n    // Decorrelation\n    // -------------\n    for(UInt i=0; i<points.size(); i++)\n    {\n      l.row(3*i+0) *= 1/sigmasNorth.at(i);\n      l.row(3*i+1) *= 1/sigmasEast.at(i);\n      l.row(3*i+2) *= 1/sigmasUp.at(i);\n      A.row(3*i+0) *= 1/sigmasNorth.at(i);\n      A.row(3*i+1) *= 1/sigmasEast.at(i);\n      A.row(3*i+2) *= 1/sigmasUp.at(i);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationStationLoading.h",
    "content": "/***********************************************/\n/**\n* @file observationStationLoading.h\n*\n* @brief Loading from station observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-07-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONSTATIONLOADING__\n#define __GROOPS_OBSERVATIONSTATIONLOADING__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationStationLoading = R\"(\n\\subsection{StationLoading}\\label{observationType:stationLoading}\nObservation equations for displacements of a list of stations\ndue to the effect of time variable loading masses. The displacement~$\\M u$ of a station is calculated according to\n\\begin{equation}\n\\M u(\\M r) = \\frac{1}{\\gamma}\\sum_{n=0}^\\infty \\left[\\frac{h_n}{1+k_n}V_n(\\M r)\\,\\M e_{up}\n+ R\\frac{l_n}{1+k_n}\\left(\n \\frac{\\partial V_n(\\M r)}{\\partial \\M e_{north}}\\M e_{north}\n+\\frac{\\partial V_n(\\M r)}{\\partial \\M e_{east}} \\M e_{east}\\right)\\right],\n\\end{equation}\nwhere $\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by\n\\configFile{inputfileDeformationLoadLoveNumber}{matrix} and the load Love numbers $k_n$ are given by\n\\configFile{inputfilePotentialLoadLoveNumber}{matrix}.\nThe $V_n$ are the spherical harmonics expansion of degree $n$ of the full time variable\ngravitational potential (potential of the loading mass + deformation potential)\nparametrized by \\configClass{parametrizationGravity}{parametrizationGravityType}.\nAdditional parameters can be setup to estimate the realization of the reference frame\nof the station coordinates (\\config{estimateTranslation},\n\\config{estimateRotation}, and \\config{estimateScale}).\n\nThe observations at stations coordinates are calculated from\n\\configFile{inputfileGriddedData}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe ellipsoid parameters \\config{R} and \\config{inverseFlattening} are used\nto define the local frame (north, east, up).\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\begin{itemize}\n\\item \\verb|*:<parametrizationGravity>:*:*|,\n\\item \\verb|*:translation.x:*:*|,\n\\item \\verb|*:translation.y:*:*|,\n\\item \\verb|*:translation.z:*:*|,\n\\item \\verb|*:scale:*:*|,\n\\item \\verb|*:rotation.x:*:*|,\n\\item \\verb|*:rotation.y:*:*|,\n\\item \\verb|*:rotation.z:*:*|.\n\\end{itemize}\n\nSee also \\program{Gravityfield2DisplacementTimeSeries}.\n\nReference:\nRietbroek (2014): Retrieval of Sea Level and Surface Loading Variations from Geodetic Observations\nand Model Simulations: an Integrated Approach, Bonn, 2014. - Dissertation,\n\\url{https://nbn-resolving.org/urn:nbn:de:hbz:5n-35460}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Loading from station observations.\n* @ingroup observationGroup\n* Observed function values of Gravityfield.\n* @see Observation */\nclass ObservationStationLoading : public Observation\n{\n  std::vector<Vector3d>     points;\n  std::vector<Double>       valuesNorth, valuesEast, valuesUp;\n  std::vector<Double>       sigmasNorth, sigmasEast, sigmasUp;\n  Bool                      inGlobalFrame;\n  Time                      time;\n  Vector                    hn, ln;\n  GravityfieldPtr           referencefield;\n  ParametrizationGravityPtr parametrization;\n  Bool                      estimateTranslation, estimateScale, estimateRotation;\n  Ellipsoid                 ellipsoid;\n\npublic:\n  ObservationStationLoading(Config &config);\n ~ObservationStationLoading() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return parametrization->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return gravityParameterCount() + 3*estimateTranslation + estimateScale + 3*estimateRotation;}\n  UInt gravityParameterCount()   const override {return parametrization->parameterCount();}\n  UInt rightSideCount()          const override {return 1;}\n  UInt arcCount()                const override {return 1;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/observation/observationTerrestrial.cpp",
    "content": "/***********************************************/\n/**\n* @file observationTerrestrial.cpp\n*\n* @brief Terrestrial observations (point measurements).\n* Observed function values of Gravityfield.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-03-22\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/observation/observationTerrestrial.h\"\n\n/***********************************************/\n\nObservationTerrestrial::ObservationTerrestrial(Config &config)\n{\n  try\n  {\n    FileName              fileNameGrid;\n    ExpressionVariablePtr exprValue, exprSigma;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\", date2time(2020, 6, 3));\n\n    if(readConfigSequence(config, \"rightHandSide\", Config::MUSTSET, \"\", \"input for observation vectors\"))\n    {\n      readConfig(config, \"inputfileGriddedData\", fileNameGrid,   Config::MUSTSET,  \"\",                \"\");\n      readConfig(config, \"observation\",          exprValue,      Config::MUSTSET,  \"data0\",           \"[SI units]\");\n      readConfig(config, \"sigma\",                exprSigma,      Config::OPTIONAL, \"sqrt(4*PI/area)\", \"accuracy, 1/sigma used as weighting\");\n      readConfig(config, \"referencefield\",       referencefield, Config::DEFAULT,  \"\",                \"\");\n      endSequence(config);\n    }\n    readConfig(config, \"kernel\",                 kernel,          Config::MUSTSET,  \"\",    \"type of observations\");\n    readConfig(config, \"parametrizationGravity\", parametrization, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"time\",                   time,            Config::OPTIONAL, \"\",    \"for reference field and parametrization\");\n    readConfig(config, \"blockingSize\",           obsPerArc,       Config::DEFAULT,  \"100\", \"segementation of the obervations if designmatrix can't be build at once\");\n    if(isCreateSchema(config)) return;\n\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    points = grid.points;\n\n    // evaluate expression\n    // -------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    if(exprValue) exprValue->simplify(varList);\n    if(exprSigma) exprSigma->simplify(varList);\n\n    values.resize(grid.points.size(), 0.);\n    sigmas.resize(grid.points.size(), 1.);\n    for(UInt i=0; i<values.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      if(exprValue) values.at(i) = exprValue->evaluate(varList);\n      if(exprSigma) sigmas.at(i) = exprSigma->evaluate(varList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationTerrestrial::observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    const UInt obsCount = observationCount(arcNo);\n\n    l = Vector(obsCount);\n    A = Matrix(obsCount, parameterCount());\n    B = Matrix();\n    for(UInt obsNo=0; obsNo<obsCount; obsNo++)\n    {\n      l(obsNo, 0) = values.at(idx(arcNo, obsNo)) - referencefield->field(time, points.at(idx(arcNo, obsNo)), *kernel);\n      parametrization->field(time, points.at(idx(arcNo, obsNo)), *kernel, A.row(obsNo));\n      if(sigmas.at(idx(arcNo, obsNo)) != 1.)\n      {\n        l.row(obsNo) *= 1/sigmas.at(idx(arcNo, obsNo));\n        A.row(obsNo) *= 1/sigmas.at(idx(arcNo, obsNo));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/observation/observationTerrestrial.h",
    "content": "/***********************************************/\n/**\n* @file observationTerrestrial.h\n*\n* @brief Terrestrial observations (point measurements).\n* Observed function values of Gravityfield.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-03-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONTERRESTRIAL__\n#define __GROOPS_OBSERVATIONTERRESTRIAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Observation\nstatic const char *docstringObservationTerrestrial = R\"(\n\\subsection{Terrestrial}\\label{observationType:terrestrial}\nThe gravity field is estimated from point wise measurements.\nThe gravity field parametrization is given by \\configClass{parametrizationGravity}{parametrizationGravityType}.\nThere is no need to have the data regular distributed or given on a sphere or ellipsoid.\nThe type of the gridded data (e.g gravity anomalies or geoid heights)\nmust be set with \\configClass{kernel}{kernelType}.\nA \\configClass{referencefield}{gravityfieldType} can be reduced beforehand.\n\nThe observations at given positions are calculated from\n\\configFile{inputfileGriddedData}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe observations can be divided into small blocks for parallelization.\nWith \\config{blockingSize} set the maximum count of observations in each block.\n\nThe following parameters with \\file{parameter names}{parameterName} are set up:\n\\verb|*:<parametrizationGravity>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/observation/observation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Terrestrial observations (point measurements).\n* @ingroup observationGroup\n* Observed function values of Gravityfield.\n* @see Observation */\nclass ObservationTerrestrial : public Observation\n{\n  std::vector<Vector3d>     points;\n  std::vector<Double>       values;\n  std::vector<Double>       sigmas;\n  GravityfieldPtr           referencefield;\n  KernelPtr                 kernel;\n  ParametrizationGravityPtr parametrization;\n  Time                      time;\n  UInt                      obsPerArc;\n\n  UInt idx(UInt arc, UInt obs)    const {return arc*obsPerArc+obs;}\n  UInt observationCount(UInt arc) const {return (arc<arcCount()-1) ? (obsPerArc) : (points.size()-arc*obsPerArc);}\n\npublic:\n  ObservationTerrestrial(Config &config);\n ~ObservationTerrestrial() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return parametrization->setInterval(timeStart, timeEnd);}\n  UInt parameterCount()          const override {return parametrization->parameterCount();}\n  UInt gravityParameterCount()   const override {return parametrization->parameterCount();}\n  UInt rightSideCount()          const override {return 1;}\n  UInt arcCount()                const override {return (points.size()+obsPerArc-1)/obsPerArc;}\n  void parameterName(std::vector<ParameterName> &name) const override {parametrization->parameterName(name);}\n\n  void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATION__ */\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagator.cpp",
    "content": "/***********************************************/\n/**\n* @file orbitPropagator.cpp\n*\n* @brief Propagate orbit using different algorithms.\n*\n* @author Matthias Ellmer\n* @date 2017-01-19\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_OrbitPropagator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/orbitPropagator/orbitPropagatorEuler.h\"\n#include \"classes/orbitPropagator/orbitPropagatorRungeKutta4.h\"\n#include \"classes/orbitPropagator/orbitPropagatorAdamsBashforthMoulton.h\"\n#include \"classes/orbitPropagator/orbitPropagatorStoermerCowell.h\"\n#include \"classes/orbitPropagator/orbitPropagatorGaussJackson.h\"\n#include \"classes/orbitPropagator/orbitPropagatorPolynomial.h\"\n#include \"classes/orbitPropagator/orbitPropagatorFile.h\"\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(OrbitPropagator, \"orbitPropagatorType\",\n                      OrbitPropagatorEuler,\n                      OrbitPropagatorRungeKutta4,\n                      OrbitPropagatorAdamsBashforthMoulton,\n                      OrbitPropagatorStoermerCowell,\n                      OrbitPropagatorGaussJackson,\n                      OrbitPropagatorPolynomial,\n                      OrbitPropagatorFile)\n\nGROOPS_READCONFIG_CLASS(OrbitPropagator, \"orbitPropagatorType\")\n\n/***********************************************/\n\nOrbitPropagatorPtr OrbitPropagator::create(Config &config, const std::string &name)\n{\n  try\n  {\n    OrbitPropagatorPtr orbitPropagator;\n    std::string choice;\n\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"algorithm for integration\");\n    if (readConfigChoiceElement(config, \"euler\",               choice, \"Euler step method\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorEuler(config));\n    if (readConfigChoiceElement(config, \"rungeKutta4\",         choice, \"The classical Runge-Kutta 4 method\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorRungeKutta4(config));\n    if (readConfigChoiceElement(config, \"adamsBashforthMoulton\", choice, \"Adams-Bashforth-Moulton class of predictor-corrector method\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorAdamsBashforthMoulton(config));\n    if (readConfigChoiceElement(config, \"stoermerCowell\",      choice, \"Stoermer-Cowell predictor-corrector method\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorStoermerCowell(config));\n    if (readConfigChoiceElement(config, \"gaussJackson\",        choice, \"Gauss-Jackson method\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorGaussJackson(config));\n    if (readConfigChoiceElement(config, \"polynomial\",          choice, \"Integration Polynomial method using prediction only\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorPolynomial(config));\n    if (readConfigChoiceElement(config, \"file\",                choice, \"Read orbit from file\"))\n      orbitPropagator = OrbitPropagatorPtr(new OrbitPropagatorFile(config));\n    endChoice(config);\n\n    return orbitPropagator;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d OrbitPropagator::orientation(const Time &/*time*/, const Vector3d &position, const Vector3d &velocity, SatelliteModelPtr /*satellite*/) const\n{\n  return Rotary3d(velocity, crossProduct(velocity, position));\n}\n\n/***********************************************/\n\nArc OrbitPropagator::flip(const Arc &arc)\n{\n  try\n  {\n    Arc arcNew;\n    for(UInt i=arc.size(); i-->0;)\n      arcNew.push_back(arc.at(i));\n    return arcNew;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d OrbitPropagator::acceleration(const OrbitEpoch &epoch, ForcesPtr forces, SatelliteModelPtr satellite,\n                                       EarthRotationPtr earthRotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    const Rotary3d rotSat   = orientation(epoch.time, epoch.position, epoch.velocity, satellite);\n    const Rotary3d rotEarth = earthRotation->rotaryMatrix(epoch.time);\n    return rotEarth.inverseRotate(forces->acceleration(satellite, epoch.time, epoch.position, epoch.velocity, rotSat, rotEarth, earthRotation, ephemerides));\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagator.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagator.h\n*\n* @brief Propagate orbit using different algorithms.\n*\n* @author Matthias Ellmer\n* @date 2017-01-19\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATOR__\n#define __GROOPS_ORBITPROPAGATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagator = R\"(\n\\section{OrbitPropagator}\\label{orbitPropagatorType}\nImplements the propagation of a satellite orbit under\nthe influence of \\configClass{forces}{forcesType} as\nused in \\program{SimulateOrbit}\n(dynamic orbits from numerical orbit integration).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/forces/forces.h\"\n\n/**\n* @defgroup orbitPropagatorGroup OrbitPropagator\n* @brief Propagate a satellite orbit.\n* @ingroup classesGroup\n* The interface is given by @ref OrbitPropagator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass OrbitPropagator;\ntypedef std::shared_ptr<OrbitPropagator> OrbitPropagatorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate a satellite orbit.\n* An Instance of this class can be created by @ref readConfig. */\nclass OrbitPropagator\n{\npublic:\n  /// Destructor.\n  virtual ~OrbitPropagator() {}\n\n  /** @brief Propagate orbit arc through force field\n  * @param startEpoch Initial epoch of the orbit\n  * @param sampling Time difference between epochs\n  * @param posCount Total number of epochs in arc (including @a startEpoch)\n  * @param forces Force models to consider\n  * @param satellite Satellite macro model to consider\n  * @param earthRotation for rotations in forces evaluation\n  * @param ephemerides Position of Sun and Moon.\n  * @param timing Show a timer.\n  * @returns OrbitArc arc of size @a posCount, with @a startEpoch at index 0  */\n  virtual OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                                EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing=TRUE) const = 0;\n\n  /** @brief Generic orientation definition in orbital system.\n  * @param time of evaluation\n  * @param position of the satellite\n  * @param velocity of the satellite\n  * @param satellite model of the satellite\n  * @returns Rotary3d satellite orientation, with x as along-track, y cross-track and z perpendicular.  */\n  virtual Rotary3d orientation(const Time &time, const Vector3d &position, const Vector3d &velocity, SatelliteModelPtr satellite) const;\n\n  static Arc flip(const Arc &arc);\n\n  /** @brief creates a derived instance of this class. */\n  static OrbitPropagatorPtr create(Config &config, const std::string &name);\n\nprotected:\n  Vector3d acceleration(const OrbitEpoch &epoch, ForcesPtr forces, SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides) const;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class OrbitPropagator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a orbitPropagator is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] orbitPropagator Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates OrbitPropagator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, OrbitPropagatorPtr &orbitPropagator, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n#endif\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorAdamsBashforthMoulton.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorAdamsBashforthMoulton.h\n*\n* @brief Propagate a dynamic orbit using Adams/Bashforth/Moulton algorithm.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-01-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATORADAMSBASHFORTHMOULTON__\n#define __GROOPS_ORBITPROPAGATORADAMSBASHFORTHMOULTON__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorAdamsBashforthMoulton = R\"(\n\\subsection{AdamsBashforthMoulton}\nThis class implements the Adams-Moulton class of predictor-corrector orbit propagators\nfor a satellite orbit under the influence of \\configClass{Forces}{forcesType} using an implicit\nAdams-Bashforth corrector. The coefficients for the propagator are derived using the equations\ngiven in section 4.2.3 of [1]. Satellite is assumed to be oriented along-track.\n[1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate a dynamic orbit using Adams/Bashforth/Moulton algorithm.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator */\nclass OrbitPropagatorAdamsBashforthMoulton : public OrbitPropagator\n{\n  OrbitPropagatorPtr warmup; // Used for generation of warmup values.\n  Bool   applyMoultonCorrector;\n  UInt   order;\n  Vector betaAM, betaAB;\n\npublic:\n  OrbitPropagatorAdamsBashforthMoulton(Config &config);\n\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                        EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const override;\n\n  static Vector factorsBashforth(UInt order);\n  static Vector factorsMoulton(UInt order);\n  static Vector coefficients(const Vector &gamma);\n};\n\n/***********************************************/\n\ninline OrbitPropagatorAdamsBashforthMoulton::OrbitPropagatorAdamsBashforthMoulton(Config &config)\n{\n  try\n  {\n    readConfig(config, \"order\",                  order,                  Config::MUSTSET,  \"4\", \"Order of the Adams-Bashforth type propagator.\");\n    readConfig(config, \"applyMoultonCorrector\",  applyMoultonCorrector,  Config::DEFAULT,  \"1\", \"Corrector step after Adams-Bashforth predcition.\");\n    readConfig(config, \"warmup\",                 warmup,                 Config::MUSTSET,  \"rungeKutta4\", \"\");\n    if(isCreateSchema(config)) return;\n\n    betaAB = coefficients(factorsBashforth(order)); // Adams-Bashforth predictor coefficients\n    betaAM = coefficients(factorsMoulton(order));   // Coefficients for Adams-Moulton corrector\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline OrbitArc OrbitPropagatorAdamsBashforthMoulton::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                                   SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    const Double dt = sampling.seconds();\n\n    // Compute warmup\n    OrbitArc orbit = flip(warmup->integrateArc(startEpoch, -sampling, order, forces, satellite, earthRotation, ephemerides, FALSE));\n\n    // Integrate remaining arc\n    Single::forEach(posCount-1, [&](UInt k)\n    {\n      // Predict using Adams-Bashforth\n      OrbitEpoch epoch = orbit.back();\n      epoch.time = startEpoch.time + (k+1)*sampling;\n      for(UInt j=1; j<=order; j++)\n        epoch.position += dt * betaAB(j) * orbit.at(k+j-1).velocity;\n      for(UInt j=1; j<=order; j++)\n        epoch.velocity += dt * betaAB(j) * orbit.at(k+j-1).acceleration;\n      epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n      orbit.push_back(epoch);\n\n      // Correct using Adams-Moulton\n      if(applyMoultonCorrector)\n      {\n        epoch = orbit.at(orbit.size()-2);\n        epoch.time = orbit.at(orbit.size()-1).time;\n        for(UInt j=1; j<=order; j++)\n          epoch.position += dt * betaAM(j) * orbit.at(k+j).velocity;\n        for(UInt j=1; j<=order; j++)\n          epoch.velocity += dt * betaAM(j) * orbit.at(k+j).acceleration;\n        epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n        orbit.at(k+order) = epoch;\n      }\n    }, timing);\n\n    // remove warmup\n    orbit.remove(0, order-1);\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Set up coefficients for Adams-Bashforth predictor of requested order.\n// Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits, eq. 4.56\ninline Vector OrbitPropagatorAdamsBashforthMoulton::factorsBashforth(UInt order)\n{\n  Vector gamma(order+1);\n  for (UInt j=0; j<gamma.size(); j++)\n  {\n    gamma(j) = 1;\n    for (UInt k=0; k<j; k++)\n      gamma(j) -= (1./(1.+j-k)) * gamma(k);\n  }\n  return gamma;\n}\n\n/***********************************************/\n\n// Set up coefficients for Adams-Moulton corrector of requested order.\n// Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits, eq. 4.64\ninline Vector OrbitPropagatorAdamsBashforthMoulton::factorsMoulton(UInt order)\n{\n  Vector gamma(order+1);\n  gamma(0) = 1;\n  for (UInt j=1; j<gamma.size(); j++)\n    for (UInt k=0; k<j; k++)\n      gamma(j) -= (1./(1.+j-k)) * gamma(k);\n  return gamma;\n}\n\n/***********************************************/\n\n// Set up coefficients for Adams-Bashforth predictor of requested order.\n// Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits, eq. 4.60\ninline Vector OrbitPropagatorAdamsBashforthMoulton::coefficients(const Vector &gamma)\n{\n  const UInt order = gamma.rows()-1;\n\n  Matrix binomial(order, order, 1.);\n  for(UInt i=2; i<binomial.rows(); i++)\n    for(UInt k=1; k<i; k++)\n      binomial(i,k) = binomial(i-1,k-1) + binomial(i-1,k);\n\n  Vector beta(order+1);\n  for(UInt j=1; j<beta.size(); j++)\n    for(UInt l=order-j; l<order; l++)\n      beta(j) += std::pow(-1, order-j) * gamma(l) * binomial(l, order-j);\n  return beta;\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorEuler.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorEuler.h\n*\n* @brief Propagate a dynamic orbit using Euler's method.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-01-19\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATOREULER__\n#define __GROOPS_ORBITPROPAGATOREULER__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorEuler = R\"(\n\\subsection{Euler}\nThis class implements Euler's method to propagate a satellite orbit under the influence of \\configClass{Forces}{forcesType}.\nSatellite is assumed to be oriented along-track.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate orbit using Euler's method.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator */\nclass OrbitPropagatorEuler : public OrbitPropagator\n{\npublic:\n  OrbitPropagatorEuler(Config &/*config*/) {}\n\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite, EarthRotationPtr earthRotation,\n                        EphemeridesPtr ephemerides, Bool timing) const override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline OrbitArc OrbitPropagatorEuler::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                   SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    OrbitArc orbit;\n    orbit.push_back(startEpoch);\n    orbit.back().acceleration = acceleration(startEpoch, forces, satellite, earthRotation, ephemerides);\n    const Double dt = sampling.seconds();\n\n    Single::forEach(posCount-1, [&](UInt k)\n    {\n      OrbitEpoch epoch;\n      epoch.time         = startEpoch.time + (k+1) * sampling;\n      epoch.position     = orbit.at(k).position + dt * orbit.at(k).velocity;\n      epoch.velocity     = orbit.at(k).velocity + dt * orbit.at(k).acceleration;\n      epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n      orbit.push_back(epoch);\n    }, timing);\n\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_ORBITPROPAGATOREULER__ */\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorFile.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorFile.h\n*\n* @brief Read orbit from file.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-01-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITFILE__\n#define __GROOPS_ORBITFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorFile = R\"(\n\\subsection{File}\nReads an orbit from file. If the needed epochs are not given an exception is thrown.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read orbit from file.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator */\nclass OrbitPropagatorFile : public OrbitPropagator\n{\n  FileName fileNameOrbit;\n  Double   margin;\n  Bool     computeForces;\n\npublic:\n  OrbitPropagatorFile(Config &config);\n\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                        EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const override;\n};\n\n/***********************************************/\n\ninline OrbitPropagatorFile::OrbitPropagatorFile(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileOrbit\",  fileNameOrbit, Config::MUSTSET,  \"\",     \"epoch at timeStart is not used\");\n    readConfig(config, \"margin\",          margin,        Config::MUSTSET,  \"1e-5\", \"[seconds] to find identical times\");\n    readConfig(config, \"recomputeForces\", computeForces, Config::DEFAULT,  \"0\",    \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline OrbitArc OrbitPropagatorFile::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                  SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    OrbitArc orbitFile = InstrumentFile::read(fileNameOrbit);\n\n    OrbitArc orbit;\n    Single::forEach(posCount, [&](UInt k)\n    {\n      const Time time = startEpoch.time + k*sampling;\n      OrbitEpoch epoch;\n      for(UInt i=0; i<orbitFile.size(); i++)\n        if(std::fabs((orbitFile.at(i).time-time).seconds()) < margin)\n          epoch = orbitFile.at(i);\n      if(std::fabs((epoch.time-time).seconds())>margin)\n        throw (Exception(\"Requested time \"+time.dateTimeStr()+\" not present in file <\"+fileNameOrbit.str()+\">\"));\n\n      if(computeForces)\n        epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n\n      orbit.push_back(epoch);\n    }, timing);\n\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorGaussJackson.cpp",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorGaussJackson.cpp\n*\n* @brief Propagate a dynamic orbit using Gauss-Jackson method.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-02-07\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/orbitPropagator/orbitPropagatorAdamsBashforthMoulton.h\"\n#include \"classes/orbitPropagator/orbitPropagatorStoermerCowell.h\"\n#include \"classes/orbitPropagator/orbitPropagatorGaussJackson.h\"\n\n/***********************************************/\n\nOrbitPropagatorGaussJackson::OrbitPropagatorGaussJackson(Config &config)\n{\n  try\n  {\n    readConfig(config, \"order\",               order,                  Config::MUSTSET,  \"8\",     \"of Gauss-Jackson method.\");\n    readConfig(config, \"warmup\",              warmup,                 Config::MUSTSET,  \"rungeKutta4\", \"\");\n    readConfig(config, \"correctorIterations\", maxCorrectorIterations, Config::DEFAULT,  \"10\",    \"Maximum number of iterations to run the corrector step for.\");\n    readConfig(config, \"epsilon\",             epsilon,                Config::DEFAULT,  \"1e-15\", \"Convergence criteria for position, velocity, and acceleration tests.\");\n    if (isCreateSchema(config)) return;\n\n    if(order%2)\n      throw(Exception(\"Gauss-Jackson mid-corrector order must be even, is: \"+order%\"%i\"s));\n\n    // The Gauss-Jackson integrator is the summed form of the\n    // Stoermer-Cowell integrator, which is in turn based on the Adams-Bashforth coefficients.\n    A = gaussJacksonCoefficients(order);\n    B = summedAdamsCoefficients(order);\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nOrbitArc OrbitPropagatorGaussJackson::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                   SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    // Compute warmup\n    OrbitArc orbit = flip(warmup->integrateArc(startEpoch, -sampling, order+1, forces, satellite, earthRotation, ephemerides, FALSE));\n\n    // Compute integration constants\n    // -----------------------------\n    const Double dt = sampling.seconds();\n    std::vector<Vector3d> firstSums, secondSums;\n    computeSums(orbit, dt, firstSums, secondSums);\n    Vector3d firstSum  = firstSums.back();\n    Vector3d secondSum = secondSums.back();\n\n    // Propagate rest of orbit arc\n    // ---------------------------\n    Single::forEach(posCount-1, [&](UInt k)\n    {\n      secondSum += firstSum + 0.5*orbit.at(k+order).acceleration;\n\n      // Predict\n      // -------\n      OrbitEpoch epoch;\n      epoch.time     = startEpoch.time + (k+1) * sampling;\n      epoch.position = dt*dt * secondSum; // eq. 88;\n      for(UInt j=0; j<order+1; j++)\n        epoch.position += dt*dt * A(order+1, j) * orbit.at(k+j).acceleration;\n      epoch.velocity = dt * (firstSum + 0.5 * orbit.at(k+order).acceleration);\n      for(UInt j=0; j<order+1; j++)\n        epoch.velocity += dt * B(order+1, j) * orbit.at(k+j).acceleration;\n      epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n      orbit.push_back(epoch);\n\n      // Correct iteratively\n      // -------------------\n      // Precompute the accelerations from epochs up until the predicted one\n      Vector3d summedAccelerationsPosition;\n      for(UInt j=0; j<order; j++)\n        summedAccelerationsPosition += A(order, j) * orbit.at(k+j+1).acceleration;\n      Vector3d summedAccelerationsVelocity;\n      for(UInt j=0; j<order; j++)\n        summedAccelerationsVelocity += B(order, j) * orbit.at(k+j+1).acceleration;\n\n      Vector3d firstSumOld = firstSum;\n      for(UInt iter=0; iter<maxCorrectorIterations; iter++)\n      {\n        firstSum = firstSumOld + 0.5 * (orbit.at(k+order).acceleration + epoch.acceleration);\n\n        // Compute updated state, including accelerations due to current predicted/corrected epoch\n        const OrbitEpoch epochOld = epoch;\n        epoch.position     = dt * dt * (secondSum + summedAccelerationsPosition + A(order, order) * epoch.acceleration);\n        epoch.velocity     = dt      * (firstSum  + summedAccelerationsVelocity + B(order, order) * epoch.acceleration);\n        epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n        if(((epoch.position-epochOld.position).norm()<=epsilon) && ((epoch.velocity-epochOld.velocity).norm()<=epsilon))\n          break;\n      }\n\n      orbit.at(order+k+1) = epoch;\n    }, timing);\n\n    // remove warmup\n    orbit.remove(0, order);\n\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// eq. 59 + 63\n// Coefficients of a certain degree are combinations of the coefficients of the next-higher degree.\n// Start with the last row of the coefficient matrix and work backwards.\nMatrix OrbitPropagatorGaussJackson::differenceCoefficientsTable(const Vector coefficients, const Bool flipSign)\n{\n  const UInt N = coefficients.rows();\n  Matrix mat(N+1, N);\n  copy(coefficients.trans(), mat.row(N));\n\n  for(UInt i=N; i-->0;)\n  {\n    mat(i, 0) = mat(i+1, 0);\n    if((i==N-1) && flipSign)\n      mat(i, 0) *= -1;\n\n    for(UInt j=1; j<N; j++)\n      mat(i, j) = mat(i+1, j) - mat(i+1, j-1);\n  }\n  return mat;\n}\n\n/***********************************************/\n\n// eq. 67\n// And flip it. m is the current point with larger positive integers for m being the m-th past point.\n// So we want it the other way around.\nMatrix OrbitPropagatorGaussJackson::differenceCoefficientsToOrdinateForm(const_MatrixSliceRef coefficients)\n{\n  Matrix binomial(coefficients.rows(), coefficients.columns(), 1.);\n  for(UInt i=2; i<binomial.rows(); i++)\n    for(UInt k=1; k<i; k++)\n      binomial(i,k) = binomial(i-1,k-1) + binomial(i-1,k);\n\n  Matrix xi(coefficients.rows(), coefficients.columns());\n  for(UInt n=0; n<xi.rows(); n++)\n    for (UInt m=0; m<xi.columns(); m++)\n      for(UInt i=m; i<xi.columns(); i++)\n        xi(n, xi.columns()-1-m) += std::pow(-1, m) * coefficients(n, i) * binomial(i, m);\n  return xi;\n}\n\n/***********************************************/\n\n// Summed Adams coefficients in ordinate form, Table 5\nMatrix OrbitPropagatorGaussJackson::summedAdamsCoefficients(UInt order)\n{\n  Vector summedAdams                 = OrbitPropagatorAdamsBashforthMoulton::factorsBashforth(order+1).row(1, order+1); // Velocity component\n  Matrix summedAdamsCoefficientTable = differenceCoefficientsTable(summedAdams);\n  Matrix saCoefficientsOrdinate      = differenceCoefficientsToOrdinateForm(summedAdamsCoefficientTable);\n  for(UInt i=0; i<saCoefficientsOrdinate.columns(); i++) // removeHalfAccelerationTerm\n    saCoefficientsOrdinate(i, i) -= 0.5;\n  return saCoefficientsOrdinate; // Array a_jk in [1], Table 5\n}\n\n/***********************************************/\n\n// Gauss-Jackson coefficients in ordinate form, Table 6\nMatrix OrbitPropagatorGaussJackson::gaussJacksonCoefficients(UInt order)\n{\n  Vector stoermerCoefficients = OrbitPropagatorStoermerCowell::stoermerCoefficients(order+2).row(2, order+1); // Position component\n  return differenceCoefficientsToOrdinateForm(differenceCoefficientsTable(stoermerCoefficients)); // Array b_jk in [1], Table 6\n}\n\n/***********************************************/\n\nvoid OrbitPropagatorGaussJackson::computeSums(const OrbitArc &orbit, Double dt, std::vector<Vector3d> &firstSums, std::vector<Vector3d> &secondSums) const\n{\n  try\n  {\n    const UInt N      = order+1;\n    const UInt index0 = order/2;\n\n    firstSums  = std::vector<Vector3d>(N); // eq. 75\n    secondSums = std::vector<Vector3d>(N); // eq. 86\n\n    // First integration constant, see: eq. 73\n    Vector3d C1p = orbit.at(index0).velocity/dt;\n    for(UInt k=0; k<N; k++)\n      C1p -= B(index0, k) * orbit.at(k).acceleration;\n    Vector3d C1 = C1p + orbit.at(index0).acceleration/2;\n\n    // Second integration constant, see: eq. 85\n    Vector3d C2 = C1 + orbit.at(index0).position/(dt*dt);\n    for(UInt k=0; k<N; k++)\n      C2 -= A(index0, k) * orbit.at(k).acceleration;\n\n    // Initial values for first and second sums.\n    // -----------------------------------------\n    // At midpoint of arc / start epoch\n    firstSums.at(index0)  = C1p;\n    secondSums.at(index0) = C2 - C1;\n\n    // Epochs around midpoint of arc\n    for(UInt n=1; n<=order/2; n++)\n    {\n      // eq. 75\n      firstSums.at(index0+n) = firstSums.at(index0-1+n) + 0.5 * (orbit.at(index0-1+n).acceleration + orbit.at(index0+n).acceleration); // n > 0 case\n      firstSums.at(index0-n) = firstSums.at(index0+1-n) - 0.5 * (orbit.at(index0+1-n).acceleration + orbit.at(index0-n).acceleration); // n < 0 case\n\n      // eq. 86\n      secondSums.at(index0+n) = secondSums.at(index0-1+n) + firstSums.at(index0-1+n) + 0.5 * orbit.at(index0-1+n).acceleration; // n > 0 case\n      secondSums.at(index0-n) = secondSums.at(index0+1-n) - firstSums.at(index0+1-n) + 0.5 * orbit.at(index0+1-n).acceleration; // n < 0 case\n    }\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorGaussJackson.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorGaussJackson.h\n*\n* @brief Propagate a dynamic orbit using Gauss-Jackson method.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-02-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATORGAUSSJACKSON__\n#define __GROOPS_ORBITPROPAGATORGAUSSJACKSON__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorGaussJackson = R\"(\n\\subsection{GaussJackson}\nThis class implements the Gauss-Jackson multi-step predictor-corrector method to\npropagate a satellite orbit under the influence of \\configClass{Forces}{forcesType}.\nSatellite is assumed to be oriented along-track. Implementation is based on [1].\n[1] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate orbit using GaussJackson method.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator\n* @see [1] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation. */\nclass OrbitPropagatorGaussJackson : public OrbitPropagator\n{\n  OrbitPropagatorPtr warmup;     // Used for generation of warmup values.\n  UInt   order;                  // of Gauss-Jackson method.\n  UInt   maxCorrectorIterations; // For Corrector loop in predictor-corrector algorithm\n  Double epsilon;                // For warmup and Corrector loop\n  Matrix A;                      // Gauss-Jackson coefficients;\n  Matrix B;                      // Summed Adams coefficients\n\n  /** @brief Compute summation operator coefficients.\n  * @param coefficients vector of propagator coefficients of length  @a order+1.\n  * @param flipSign whether to flip the sign of the first element in the second to last row of coefficients.\n  * @returns @a Matrix of size @a order+2, @a order+1, with the difference coefficients for the selected propagator.\n  * The sign must be flipped to get results consistent with [1], Table 3,\n  * computing the beta coefficients. This is not consistent with the\n  * formulation given in eq.59, but leads to correct results. One must\n  * assume that this is a copy & paste error in the paper. To get results\n  * for Table 4 and eq. 63, do not flip the sign.\n  * @see [1], eq. 59, eq. 63, Table 3, Table 4  */\n  static Matrix differenceCoefficientsTable(const Vector coefficients, const Bool flipSign = FALSE);\n\n  /** @brief Shift difference coefficients to the ordinate form.\n  * This allows for the integration to be written as a linear combination of the\n  * original function values.\n  * @param coefficients Matrix of propagator coefficients.\n  * @returns @a Matrix of same size as @a coefficients with the difference coefficients in ordinate form.\n  * @see [1], Section Ordinate form, eq. 67  */\n  static Matrix differenceCoefficientsToOrdinateForm(const_MatrixSliceRef coefficients);\n\n  /** @brief Compute summed Adams propagator coefficients in ordinate form.\n  * @param order of the propagator.\n  * @returns @a Matrix of size order+1,order\n  * @see [1], Table 5  */\n  static Matrix summedAdamsCoefficients(UInt order);\n\n  /** @brief Compute Gauss Jackson propagator coefficients in ordinate form.\n  * @param order of the propagator.\n  * @returns @a Matrix of size order+1,order\n  * @see [1], Table 6  */\n  static Matrix gaussJacksonCoefficients(UInt order);\n\n  /** @brief Compute integration constants\n  * @param orbit arc for which to compute the sums. Must be of length order+1.\n  * @param dt sampling in seconds.\n  * @param[out] firstSums first sum integration constants for the epochs in orbit.\n  * @param[out] secondSums second sum integration constants for the epochs in orbit. */\n  void computeSums(const OrbitArc &orbit, Double dt, std::vector<Vector3d> &firstSums, std::vector<Vector3d> &secondSums) const;\n\npublic:\n  OrbitPropagatorGaussJackson(Config &config);\n\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                        EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_ORBITPROPAGATORGAUSSJACKSON__ */\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorPolynomial.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorPolynomial.h\n*\n* @brief Propagate a dynamic orbit using an integration Polynomial method.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-01-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATORPOLYNOMIAL__\n#define __GROOPS_ORBITPROPAGATORPOLYNOMIAL__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorPolynomial = R\"(\n\\subsection{Polynomial}\\label{orbitPropagatorType:Polynomial}\nThis class implements an integration Polynomial method to propagate a satellite orbit under\nthe influence of \\configClass{Forces}{forcesType}. Satellite is assumed to be oriented along-track.\nImplementation is based on code by Torsten Mayer-Gürr.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate orbit using Polynomial method.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator */\nclass OrbitPropagatorPolynomial : public OrbitPropagator\n{\n  OrbitPropagatorPtr warmup;   // Used for generation of warmup values.\n  UInt   degree;               // of integration polynomial.\n  Int    shift;\n  Double epsilon;\n  Matrix factorPos, factorVel;\n  Bool   corrector;\n\npublic:\n  OrbitPropagatorPolynomial(Config &config);\n\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                        EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const override;\n};\n\n/***********************************************/\n\ninline OrbitPropagatorPolynomial::OrbitPropagatorPolynomial(Config &config)\n{\n  try\n  {\n    readConfig(config, \"degree\",    degree,    Config::MUSTSET, \"9\",           \"polynomial degree to integrate accelerations\");\n    readConfig(config, \"shift\",     shift,     Config::MUSTSET, \"2\",           \"shift polynomial in future (predicted accelerations)\");\n    readConfig(config, \"epsilon\",   epsilon,   Config::MUSTSET, \"1e-6\",        \"[m] max. position change to recompute forces\");\n    readConfig(config, \"warmup\",    warmup,    Config::MUSTSET, \"rungeKutta4\", \"to compute epochs before start epoch\");\n    readConfig(config, \"corrector\", corrector, Config::DEFAULT,  \"0\",          \"apply corrector iteration if position change is larger than epsilon\");\n    if (isCreateSchema(config)) return;\n\n    if(!(degree%2))\n      throw(Exception(\"Polynomial Propagator: Polynomial degree must be odd. Is: [\"+ degree % \"%i\"s +\"]\"));\n\n    if(shift<0)\n      throw(Exception(\"Polynomial Propagator: Polynomial shift must be positive. Is: [\"+ shift % \"%i\"s +\"]\"));\n\n    if(shift>static_cast<Int>(degree))\n      throw(Exception(\"Polynomial Propagator: Polynomial shift must be smaller than degree. Is: [\"+ shift % \"%i\"s +\"]\"));\n\n    // Solve equation system for integration polynomial\n    // tau = 0 at i = shift-degree\n    Matrix  W(degree+1, degree+1);\n    for(UInt i=0; i<=degree; i++)\n      for(UInt n=0; n<=degree; n++)\n        W(i,n) = ((n==0) ? 1. : pow(static_cast<Double>(i)+shift-degree, n));\n    inverse(W);\n\n    factorPos = factorVel = Matrix(shift+1, degree+1); // shift+1 epochs integration in future\n    for(UInt i=0; i<factorPos.rows(); i++)\n      for(UInt k=0; k<=degree; k++)\n        for(UInt n=0; n<=degree; n++)\n        {\n          factorPos(i,k) += 1./((n+1)*(n+2)) * pow(i+1, n+2) * W(n,k);\n          factorVel(i,k) += 1./(n+1)         * pow(i+1, n+1) * W(n,k);\n        }\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline OrbitArc OrbitPropagatorPolynomial::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                       SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    // Compute warmup\n    OrbitArc orbit = flip(warmup->integrateArc(startEpoch, -sampling, degree-shift+1, forces, satellite, earthRotation, ephemerides, FALSE));\n    orbit.append( warmup->integrateArc(startEpoch, sampling, shift+1, forces, satellite, earthRotation, ephemerides, FALSE).subArc(1,shift) );\n    const UInt idx0 = degree-shift; // index of startEpoch\n\n    // Actual integration\n    const Double dt = sampling.seconds();\n    UInt maxCorrectors = 10;\n\n    Single::forEach(posCount-1, [&](UInt k)\n    {\n      // Integration: #shift epochs refinement, one new epoch prediction\n      OrbitEpoch epoch;\n      epoch.time = startEpoch.time + (shift+k+1) * sampling;\n      orbit.push_back(epoch);\n\n      Bool correctorRepeatLoop = FALSE;\n      UInt correctorIterations = 0;\n      do\n      {\n        correctorRepeatLoop = FALSE;\n        for(UInt i=0; i<factorPos.rows(); i++)\n        {\n          const Vector3d posOld = orbit.at(idx0+k+1+i).position;\n          orbit.at(idx0+k+1+i).position = orbit.at(idx0+k).position + (i+1)*dt * orbit.at(idx0+k).velocity;\n          orbit.at(idx0+k+1+i).velocity = orbit.at(idx0+k).velocity;\n          for(UInt n=0; n<=degree; n++)\n          {\n            orbit.at(idx0+k+1+i).position += dt*dt*factorPos(i,n) * orbit.at(idx0+k+n+shift-degree).acceleration;\n            orbit.at(idx0+k+1+i).velocity +=    dt*factorVel(i,n) * orbit.at(idx0+k+n+shift-degree).acceleration;\n          }\n          // recompute forces\n          if((orbit.at(idx0+k+1+i).position-posOld).r()>epsilon)\n          {\n            orbit.at(idx0+k+1+i).acceleration = acceleration(orbit.at(idx0+k+1+i), forces, satellite, earthRotation, ephemerides);\n            correctorRepeatLoop = corrector && TRUE;\n            correctorIterations++;\n          }\n        }\n      } while(correctorRepeatLoop && (correctorIterations < maxCorrectors));\n    }, timing);\n\n    // remove warmup and last epochs\n    orbit.remove(0, degree-shift);\n    orbit.remove(orbit.size()-shift, shift);\n\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_ORBITPROPAGATORPOLYNOMIAL__ */\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorRungeKutta4.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorRungeKutta4.h\n*\n* @brief Propagate a dynamic orbit using the classical Runge-Kutta 4 method.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-01-19\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATORRUNGEKUTTA4__\n#define __GROOPS_ORBITPROPAGATORRUNGEKUTTA4__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorRungeKutta4 = R\"(\n\\subsection{RungeKutta4}\nThis class implements the classical Runge-Kutta 4 method of orbit propagation\nfor satellite orbit under the influence of \\configClass{Forces}{forcesType}.\nNo step-width control or other advanced features are implemented.\nSatellite is assumed to be oriented along-track.\nSee: Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate orbit using the Runge-Kutta 4 method.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator */\nclass OrbitPropagatorRungeKutta4 : public OrbitPropagator\n{\npublic:\n  OrbitPropagatorRungeKutta4(Config &/*config*/) {}\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                        EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const override;\n};\n\n/***********************************************/\n\ninline OrbitArc OrbitPropagatorRungeKutta4::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                         SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    OrbitArc orbit;\n    orbit.push_back(startEpoch);\n    orbit.back().acceleration = acceleration(startEpoch, forces, satellite, earthRotation, ephemerides);\n    const Double dt = sampling.seconds();\n\n    Single::forEach(posCount-1, [&](UInt k)\n    {\n      // Evaluate accelerations at 4 positions between current epoch and next\n      OrbitEpoch k1 = orbit.back();\n\n      OrbitEpoch k2 = k1;\n      k2.time        += seconds2time(dt/2.);\n      k2.position    += dt/2. * k1.velocity;\n      k2.velocity    += dt/2. * k1.acceleration;\n      k2.acceleration = acceleration(k2, forces, satellite, earthRotation, ephemerides);\n\n      OrbitEpoch k3 = k1;\n      k3.time        += seconds2time(dt/2.);\n      k3.position    += dt/2. * k2.velocity;\n      k3.velocity    += dt/2. * k2.acceleration;\n      k3.acceleration = acceleration(k3, forces, satellite, earthRotation, ephemerides);\n\n      OrbitEpoch k4 = k1;\n      k4.time        += sampling;\n      k4.position    += dt * k3.velocity;\n      k4.velocity    += dt * k3.acceleration;\n      k4.acceleration = acceleration(k4, forces, satellite, earthRotation, ephemerides);\n\n      // Compute final value for this epoch\n      OrbitEpoch epoch = k1;\n      epoch.time         = startEpoch.time + (k+1)*sampling;\n      epoch.position    += (dt/6.) * (k1.velocity + 2*k2.velocity + 2*k3.velocity + k4.velocity);\n      epoch.velocity    += (dt/6.) * (k1.acceleration + 2*k2.acceleration + 2*k3.acceleration + k4.acceleration);\n      epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n      orbit.push_back(epoch);\n    }, timing);\n\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_ORBITPROPAGATORRUNGEKUTTA4__ */\n"
  },
  {
    "path": "source/classes/orbitPropagator/orbitPropagatorStoermerCowell.h",
    "content": "/***********************************************/\n/**\n* @file orbitPropagatorStoermerCowell.h\n*\n* @brief Propagate a dynamic orbit using an arbitrary order Stoermer-Cowell predictor-corrector algorithm.\n* @see orbitPropagator\n*\n* @author Matthias Ellmer\n* @date 2017-02-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ORBITPROPAGATORSTOERMERCOWELL__\n#define __GROOPS_ORBITPROPAGATORSTOERMERCOWELL__\n\n// Latex documentation\n#ifdef DOCSTRING_OrbitPropagator\nstatic const char *docstringOrbitPropagatorStoermerCowell = R\"(\n\\subsection{StoermerCowell}\nThis class implements the Stoermer-Cowell class of predictor-corrector orbit propagators for a satellite orbit\nunder the influence of \\configClass{Forces}{forcesType}. The coefficients for the Stoermer predictor and Cowell corrector\nare derived using the equations given in section 4.2.6 of [1]. Stoermer-Cowell is a double integration algorithm,\nyielding positions directly from accelertions. It does not produce velocities. The velocities are derived using\nAdams-type propagators as suggested in [2]. Satellite is assumed to be oriented along-track.\n[1] Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits\n[2] Berry, Matthew M., and Liam M. Healy. 2004. “Implementation of Gauss-Jackson Integration for Orbit Propagation.”\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Propagate orbit using Adams-Bashforth type method.\n* @ingroup orbitPropagatorGroup\n* @see orbitPropagator */\nclass OrbitPropagatorStoermerCowell : public OrbitPropagator\n{\nprivate:\n  OrbitPropagatorPtr warmup;\n  UInt   order;\n  Vector stoermer, bashforth;\n  Vector cowell,   moulton;\n\npublic:\n  OrbitPropagatorStoermerCowell(Config &config);\n\n  OrbitArc integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces, SatelliteModelPtr satellite,\n                        EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const override;\n\n  /** @brief Compute Stoermer predictor coefficients.\n  * @param order of the predictor\n  * @returns @a Vector of length oder+1 */\n  static Vector stoermerCoefficients(UInt order);\n\n  /** @brief Compute Cowell corrector coefficients.\n  * @param order of the corrector\n  * @returns @a Vector of length oder+1 */\n  static Vector cowellCoefficients(UInt order);\n\n  /** @brief Compute backward difference operator coefficients.\n  * @param degree of the backwards difference operator\n  * @param index of the value to which the difference operator is applied\n  * @param order of the integrator\n  * @returns @a Vector of length @a order+1, with the backward difference factors\n  * for the elements i = [0 .. order] of @a degree at the @a i-th position.\n  *\n  * backwardsDifference(0,1,2) -> [ 0.,  1.,  0.]\n  * backwardsDifference(0,2,2) -> [ 0.,  0.,  1.]\n  * backwardsDifference(1,2,2) -> [ 0., -1.,  1.]\n  * backwardsDifference(2,2,2) -> [ 1., -2.,  1.]  */\n  static Vector backwardsDifference(UInt degree, UInt index, UInt order);\n};\n\n/***********************************************/\n\ninline OrbitPropagatorStoermerCowell::OrbitPropagatorStoermerCowell(Config &config)\n{\n  try\n  {\n    readConfig(config, \"order\",  order,  Config::MUSTSET, \"4\", \"Order of the Stoermer-Cowell type propagator.\");\n    readConfig(config, \"warmup\", warmup, Config::MUSTSET, \"rungeKutta4\", \"\");\n    if (isCreateSchema(config)) return;\n\n    if(order<2)\n      throw(Exception(\"Stoermer-Cowell must have an order of at least 2, is: \"+order%\"%i\"s));\n\n    stoermer = Vector(order+1); // Predictor for position\n    const Vector coeffStoermer = stoermerCoefficients(order);\n    for(UInt j=0; j<order; j++)\n      axpy(coeffStoermer(j), backwardsDifference(j, order, order), stoermer);\n\n    cowell = Vector(order+1);\n    const Vector coeffCowell = cowellCoefficients(order);   // Corrector for position\n    for(UInt j=0; j<order; j++)\n      axpy(coeffCowell(j), backwardsDifference(j, order, order), cowell);\n\n    // Set up coefficients for velocity\n    bashforth = OrbitPropagatorAdamsBashforthMoulton::coefficients(OrbitPropagatorAdamsBashforthMoulton::factorsBashforth(order)); // Predictor for velocity\n    moulton   = OrbitPropagatorAdamsBashforthMoulton::coefficients(OrbitPropagatorAdamsBashforthMoulton::factorsMoulton(order));   // Corrector for velocity\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline OrbitArc OrbitPropagatorStoermerCowell::integrateArc(const OrbitEpoch &startEpoch, const Time &sampling, UInt posCount, ForcesPtr forces,\n                                                            SatelliteModelPtr satellite, EarthRotationPtr earthRotation, EphemeridesPtr ephemerides, Bool timing) const\n{\n  try\n  {\n    const Double dt = sampling.seconds();\n\n    // Compute warmup\n    OrbitArc orbit = flip(warmup->integrateArc(startEpoch, -sampling, order, forces, satellite, earthRotation, ephemerides, FALSE));\n\n    // Integrate remaining arc\n    Single::forEach(posCount-1, [&](UInt k)\n    {\n      // Predictor step\n      // --------------\n      OrbitEpoch epoch;\n      epoch.time     = startEpoch.time + (k+1) * sampling;\n      epoch.position += 2*orbit.at(k+order-1).position - orbit.at(k+order-2).position;\n      for(UInt j=1; j<=order; j++) // Stoermer predictor\n        epoch.position += dt*dt * stoermer(j) * orbit.at(k+j-1).acceleration;\n      epoch.velocity += orbit.at(k+order-1).velocity;  // Adams-Bashforth for velocity component\n      for(UInt j=1; j<=order; j++)\n        epoch.velocity += dt * bashforth(j) * orbit.at(k+j-1).acceleration;\n      epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n      orbit.push_back(epoch);\n\n      // Corrector step\n      // --------------\n      epoch.position = 2*orbit.at(k+order-1).position - orbit.at(k+order-2).position;\n      for(UInt j=1; j<=order; j++) // Stoermer predictor\n        epoch.position += dt*dt * cowell(j) * orbit.at(k+j).acceleration;\n      epoch.velocity = orbit.at(k+order-1).velocity;  // Moulton corrector\n      for(UInt j=1; j<=order; j++)\n        epoch.velocity += dt * moulton(j) * orbit.at(k+j).acceleration;\n      epoch.acceleration = acceleration(epoch, forces, satellite, earthRotation, ephemerides);\n      orbit.at(k+order) = epoch;\n    }, timing);\n\n    // remove warmup\n    orbit.remove(0, order-1);\n\n    return orbit;\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Set up coefficients for explicit Stoermer predictor coefficients of requested order.\n// Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits, eq. 4.90\ninline Vector OrbitPropagatorStoermerCowell::stoermerCoefficients(UInt order)\n{\n  Vector gamma = OrbitPropagatorAdamsBashforthMoulton::factorsMoulton(order);\n  Vector stoermer(gamma.size());\n  for(UInt j=0; j<gamma.size(); j++)\n    stoermer(j) = (1.-j) * gamma(j);\n  return stoermer;\n}\n\n/***********************************************/\n\n// Set up coefficients for implicit Cowell corrector coefficients of requested order.\n// Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits, eq. 4.92\ninline Vector OrbitPropagatorStoermerCowell::cowellCoefficients(UInt order)\n{\n  Vector stoermer = stoermerCoefficients(order);\n  Vector cowell(order+1);\n  cowell(0) = 1;\n  for (UInt j = 1; j < cowell.size(); j++)\n    cowell(j) = stoermer(j) - stoermer(j-1);\n  return cowell;\n}\n\n/***********************************************/\n\n// Montenbruck, Oliver, and Eberhard Gill. 2000. Satellite Orbits, eq. 4.53\ninline Vector OrbitPropagatorStoermerCowell::backwardsDifference(UInt degree, UInt index, UInt order)\n{\n  if(degree == 0)\n  {\n    Vector a(order+1);\n    a(index) = 1; // f(index) is 1 at the index-th position\n    return a;\n  }\n  else if(degree == 1)\n  {\n    Vector a(order+1);\n    a(index)   =  1; //  f(index)\n    a(index-1) = -1; // -f(index-1)\n    return a;\n  }\n\n  return backwardsDifference(degree-1, index, order) - backwardsDifference(degree-1, index-1, order);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_ORBITPROPAGATORSTOERMERCOWELL__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNames.cpp",
    "content": "/***********************************************/\n/**\n* @file parameterNames.cpp\n*\n* @brief Generate parameter names.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#define DOCSTRING_ParameterNames\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/parameterNames/parameterNamesName.h\"\n#include \"classes/parameterNames/parameterNamesFile.h\"\n#include \"classes/parameterNames/parameterNamesGravity.h\"\n#include \"classes/parameterNames/parameterNamesAcceleration.h\"\n#include \"classes/parameterNames/parameterNamesSatelliteTracking.h\"\n#include \"classes/parameterNames/parameterNamesTemporal.h\"\n#include \"classes/parameterNames/parameterNamesGnssAntenna.h\"\n#include \"classes/parameterNames/parameterNamesObservation.h\"\n#include \"classes/parameterNames/parameterNamesRename.h\"\n#include \"classes/parameterNames/parameterNamesSelection.h\"\n#include \"classes/parameterNames/parameterNamesWithoutDuplicates.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParameterNames, \"parameterNamesType\",\n                      ParameterNamesName,\n                      ParameterNamesFile,\n                      ParameterNamesGravity,\n                      ParameterNamesAcceleration,\n                      ParameterNamesSatelliteTracking,\n                      ParameterNamesTemporal,\n                      ParameterNamesGnssAntenna,\n                      ParameterNamesObservation,\n                      ParameterNamesRename,\n                      ParameterNamesSelection,\n                      ParameterNamesWithoutDuplicates)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParameterNames, \"parameterNamesType\")\n\n/***********************************************/\n\nParameterNames::ParameterNames(Config &config, const std::string &name)\n{\n  try\n  {\n    std::unique_ptr<ParameterNamesBase> ptr;\n\n    std::string choice;\n    while(readConfigChoice(config, name, choice, Config::OPTIONAL, \"\", \"generate a list of parameter names\"))\n    {\n      if(readConfigChoiceElement(config, \"name\",                             choice, \"\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesName(config));\n      if(readConfigChoiceElement(config, \"file\",                             choice, \"\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesFile(config));\n      if(readConfigChoiceElement(config, \"parametrizationGravity\",           choice, \"parametrization of gravity field\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesGravity(config));\n      if(readConfigChoiceElement(config, \"parametrizationAcceleration\",      choice, \"parametrization of orbit forces\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesAcceleration(config));\n      if(readConfigChoiceElement(config, \"parametrizationSatelliteTracking\", choice, \"satellite tracking parametrization\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesSatelliteTracking(config));\n      if(readConfigChoiceElement(config, \"parametrizationTemporal\",          choice, \"temporal parametrization\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesTemporal(config));\n      if(readConfigChoiceElement(config, \"parametrizationGnssAntenna\",       choice, \"parametrization of GNSS antenna center variations\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesGnssAntenna(config));\n      if(readConfigChoiceElement(config, \"observation\",                      choice, \"parameters of oberservation equations\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesObservation(config));\n      if(readConfigChoiceElement(config, \"rename\",                           choice, \"rename parts\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesRename(config));\n      if(readConfigChoiceElement(config, \"selection\",                        choice, \"\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesSelection(config));\n      if(readConfigChoiceElement(config, \"withoutDuplicates\",                choice, \"\"))\n        ptr = std::unique_ptr<ParameterNamesBase>(new ParameterNamesWithoutDuplicates(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n\n      names.insert(names.end(), ptr->names.begin(), ptr->names.end());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNames.h",
    "content": "/***********************************************/\n/**\n* @file parameterNames.h\n*\n* @brief Generate parameter names.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMES__\n#define __GROOPS_PARAMETERNAMES__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterNames\nstatic const char *docstringParameterNames = R\"(\n\\section{ParameterNames}\\label{parameterNamesType}\nGenerates a list of parameter names. All parameters are appended.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"base/parameterName.h\"\n\n/**\n* @defgroup parameterNamesGroup Parameter names\n* @brief Generate parameter names.\n* @ingroup classesGroup\n* The interface is given by @ref ParameterNames. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParameterNames;\ntypedef std::shared_ptr<ParameterNames> ParameterNamesPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Generate parameter names.\n* An Instance of this class can be created by @ref readConfig. */\nclass ParameterNames\n{\n  std::vector<ParameterName> names;\n\npublic:\n  /// Constructor.\n  ParameterNames(Config &config, const std::string &name);\n\n  /** @brief Point distribution. */\n  const std::vector<ParameterName> &parameterNames() const {return names;}\n\n  /** @brief creates an derived instance of this class. */\n  static ParameterNamesPtr create(Config &config, const std::string &name) {return ParameterNamesPtr(new ParameterNames(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ParameterNames.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and an class without names is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ParameterNames */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParameterNamesPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass ParameterNamesBase\n{\npublic:\n  std::vector<ParameterName> names;\n\n  virtual ~ParameterNamesBase() {}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_GRID__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesAcceleration.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesAcceleration.h\n*\n* @brief Parameter names of satellites forces.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESACCELERATION__\n#define __GROOPS_PARAMETERNAMESACCELERATION__\n\n// Latex documentation\nstatic const char *docstringParameterNamesAcceleration = R\"(\n\\subsection{Acceleration}\nParameter names of satellite acceleration \\configClass{parametrization}{parametrizationAccelerationType}.\nArc related parameters are appended if an \\configFile{inputfileInstrument}{instrument} is provided which\ndefines the arc structure.\nAn additional \\config{object} name can be included in the parameter names.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names of satellites forces.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesAcceleration : public ParameterNamesBase\n{\npublic:\n  ParameterNamesAcceleration(Config &config)\n  {\n    try\n    {\n      std::string object;\n      ParametrizationAccelerationPtr parameterization;\n      FileName fileNameInstrument;\n\n      readConfig(config, \"object\",              object,             Config::OPTIONAL, \"\", \"object these parameters refers to, e.g. graceA, G023\");\n      readConfig(config, \"parameterization\",    parameterization,   Config::MUSTSET,  \"\", \"\");\n      readConfig(config, \"inputfileInstrument\", fileNameInstrument, Config::OPTIONAL, \"\", \"defines the arc structure for arc related parameters\");\n      if(isCreateSchema(config)) return;\n\n      parameterization->parameterName(names);\n\n      // arc related parameters\n      InstrumentFile instrumentFile(fileNameInstrument);\n      for(UInt arcNo=0; arcNo<instrumentFile.arcCount(); arcNo++)\n      {\n        const Arc arc = instrumentFile.readArc(arcNo);\n        parameterization->setIntervalArc(arc.at(0).time, arc.back().time+medianSampling(arc.times()));\n\n        std::vector<ParameterName> namesArc;\n        parameterization->parameterNameArc(namesArc);\n\n        const std::string str = \"arc\"+arcNo%\"%i\"s+\".\";\n        std::for_each(namesArc.begin(), namesArc.end(), [&](auto &x) {x.type = str+x.type;});\n        names.insert(names.end(), namesArc.begin(), namesArc.end());\n      }\n\n      std::for_each(names.begin(), names.end(), [&](auto &x) {x.object = object;});\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesFile.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesFile.h\n*\n* @brief Parameter names from file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESFILE__\n#define __GROOPS_PARAMETERNAMESFILE__\n\n// Latex documentation\nstatic const char *docstringParameterNamesFile = R\"(\n\\subsection{File}\nRead parameter names from \\file{file}{parameterName}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names from file.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesFile : public ParameterNamesBase\n{\npublic:\n  ParameterNamesFile(Config &config)\n  {\n    try\n    {\n      FileName fileName;\n\n      readConfig(config, \"inputfileParameterNames\", fileName, Config::MUSTSET, \"\", \"file with parameter names\");\n      if(isCreateSchema(config)) return;\n\n      readFileParameterName(fileName, names);\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesGnssAntenna.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesGnssAntenna.h\n*\n* @brief Parameter names of GNSS antenna parametrization.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESPARAMETRIZATIONGNSSANTENNA__\n#define __GROOPS_PARAMETERNAMESPARAMETRIZATIONGNSSANTENNA__\n\n// Latex documentation\nstatic const char *docstringParameterNamesGnssAntenna = R\"(\n\\subsection{GnssAntenna}\nParameter names of GNSS antenna center variation \\configClass{parametrization}{parametrizationGnssAntennaType}.\nAn additional \\config{object} name (antenna name) can be included in the parameter names.\nIt is possible to setup the parameters for each \\configClass{gnssType}{gnssType}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names of ParametrizationGnssAntenna.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesGnssAntenna : public ParameterNamesBase\n{\npublic:\n  ParameterNamesGnssAntenna(Config &config)\n  {\n    try\n    {\n      std::string                   object;\n      ParametrizationGnssAntennaPtr parametrization;\n      std::vector<GnssType>         types;\n\n      readConfig(config, \"object\",          object,          Config::OPTIONAL, \"\", \"antenna name\");\n      readConfig(config, \"parametrization\", parametrization, Config::MUSTSET,  \"\", \"\");\n      readConfig(config, \"gnssType\",        types,           Config::OPTIONAL, \"\", \"e.g. C1CG**\");\n      if(isCreateSchema(config)) return;\n\n      std::vector<ParameterName> baseNames;\n      parametrization->parameterName(baseNames);\n      if(types.size())\n        for(GnssType type : types)\n        {\n          std::string typeStr = \".\" + type.str();\n          for(const auto &base : baseNames)\n            names.push_back(ParameterName(object, base.type+typeStr, base.temporal, base.interval));\n        }\n      else\n        for(const auto &base : baseNames)\n          names.push_back(ParameterName(object, base.type, base.temporal, base.interval));\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesGravity.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesGravity.h\n*\n* @brief Parameter names from gravity field parametrization.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESGRAVITY__\n#define __GROOPS_PARAMETERNAMESGRAVITY__\n\n// Latex documentation\nstatic const char *docstringParameterNamesGravity = R\"(\n\\subsection{Gravity}\nParameter names of gravity \\configClass{parametrization}{parametrizationGravityType}.\nAn additional \\config{object} name can be included in the parameter names.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names from gravity field parametrization.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesGravity : public ParameterNamesBase\n{\npublic:\n  ParameterNamesGravity(Config &config)\n  {\n    try\n    {\n      std::string object;\n      ParametrizationGravityPtr parametrization;\n\n      readConfig(config, \"object\",          object,          Config::OPTIONAL, \"\", \"object these parameters refers to, e.g. earth\");\n      readConfig(config, \"parametrization\", parametrization, Config::MUSTSET,  \"\", \"\");\n      if(isCreateSchema(config)) return;\n\n      parametrization->parameterName(names);\n      std::for_each(names.begin(), names.end(), [&](auto &x) {x.object = object;});\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesName.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesName.h\n*\n* @brief Single parameter name.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESNAME__\n#define __GROOPS_PARAMETERNAMESNAME__\n\n// Latex documentation\nstatic const char *docstringParameterNamesName = R\"(\n\\subsection{Name}\nThe parameter is given explicitly by four parts:\n\\begin{enumerate}\n\\item object: Object this parameter refers to, e.g. \\verb|graceA|, \\verb|G023|, \\verb|earth|, \\ldots\n\\item type: Type of this parameter, e.g. \\verb|accBias|, \\verb|position.x|, \\ldots\n\\item temporal: Temporal representation of this parameter, e.g. \\verb|trend|, \\verb|polynomial.degree1|, \\ldots\n\\item interval: Interval/epoch this parameter represents, e.g. \\verb|2017-01-01_00-00-00_2017-01-02_00-00-00|, \\verb|2018-01-01_00-00-00|.\n\\end{enumerate}\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Single parameter name.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesName : public ParameterNamesBase\n{\npublic:\n  ParameterNamesName(Config &config)\n  {\n    try\n    {\n      names.resize(1);\n      readConfig(config, \"object\",   names.at(0).object,   Config::OPTIONAL,  \"\",  \"object this parameter refers to, e.g. graceA, G023, earth\");\n      readConfig(config, \"type\",     names.at(0).type,     Config::OPTIONAL,  \"\",  \"type of this parameter, e.g. accBias, position.x\");\n      readConfig(config, \"temporal\", names.at(0).temporal, Config::OPTIONAL,  \"\",  \"temporal representation of this parameter, e.g. trend, polynomial.degree1\");\n      readConfig(config, \"interval\", names.at(0).interval, Config::OPTIONAL,  \"\",  \"interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00\");\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesObservation.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesObservation.h\n*\n* @brief Parameter names from observation equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESOBSERVATION__\n#define __GROOPS_PARAMETERNAMESOBSERVATION__\n\n// Latex documentation\nstatic const char *docstringParameterNamesObservation = R\"(\n\\subsection{Observation}\nParameter names used in \\configClass{observation equations}{observationType}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names from observation equations.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesObservation : public ParameterNamesBase\n{\npublic:\n  ParameterNamesObservation(Config &config)\n  {\n    try\n    {\n      ObservationPtr observation;\n\n      readConfig(config, \"observation\", observation, Config::MUSTSET,  \"\",  \"\");\n      if(isCreateSchema(config)) return;\n\n      observation->parameterName(names);\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesRename.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesRename.h\n*\n* @brief Single parameter name.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESRENAME__\n#define __GROOPS_PARAMETERNAMESRENAME__\n\n// Latex documentation\nstatic const char *docstringParameterNamesRename = R\"(\n\\subsection{Rename}\nReplaces parts of \\configClass{parameterName}{parameterNamesType}s.\nThe star \"\\verb|*|\" left this part untouched.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Single parameter name.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesRename : public ParameterNamesBase\n{\npublic:\n  ParameterNamesRename(Config &config)\n  {\n    try\n    {\n      ParameterNamesPtr parameterNames;\n      std::string       object, type, temporal, interval;\n\n      readConfig(config, \"parameterName\", parameterNames, Config::MUSTSET,  \"\",  \"\");\n      readConfig(config, \"object\",        object,         Config::OPTIONAL, \"*\", \"*: left this part untouched, object\");\n      readConfig(config, \"type\",          type,           Config::OPTIONAL, \"*\", \"*: left this part untouched, type\");\n      readConfig(config, \"temporal\",      temporal,       Config::OPTIONAL, \"*\", \"*: left this part untouched, temporal representation\");\n      readConfig(config, \"interval\",      interval,       Config::OPTIONAL, \"*\", \"*: left this part untouched, interval/epoch\");\n      if(isCreateSchema(config)) return;\n\n      names = parameterNames->parameterNames();\n      for(auto &name : names)\n      {\n        if(object   != \"*\") name.object   = object;\n        if(type     != \"*\") name.type     = type;\n        if(temporal != \"*\") name.temporal = temporal;\n        if(interval != \"*\") name.interval = interval;\n      }\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesSatelliteTracking.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesSatelliteTracking.h\n*\n* @brief Parameter names of satellite tracking parametrization.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESSATELLITETRACKING__\n#define __GROOPS_PARAMETERNAMESSATELLITETRACKING__\n\n// Latex documentation\nstatic const char *docstringParameterNamesSatelliteTracking = R\"(\n\\subsection{SatelliteTracking}\nParameter names of satellite tracking \\configClass{parametrization}{parametrizationSatelliteTrackingType}.\nAn additional \\config{object} name can be included in the parameter names.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names of satellite tracking parametrization.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesSatelliteTracking : public ParameterNamesBase\n{\npublic:\n  ParameterNamesSatelliteTracking(Config &config)\n  {\n    try\n    {\n      std::string object;\n      ParametrizationSatelliteTrackingPtr parameterization;\n\n      readConfig(config, \"object\",           object,           Config::OPTIONAL, \"\", \"object these parameters refers to, e.g. grace1.grace2\");\n      readConfig(config, \"parameterization\", parameterization, Config::MUSTSET,  \"\", \"\");\n      if(isCreateSchema(config)) return;\n\n      parameterization->parameterName(names);\n      std::for_each(names.begin(), names.end(), [&](auto &x) {x.object = object;});\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesSelection.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesSelection.h\n*\n* @brief Selection of parameter names.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESSELECTION__\n#define __GROOPS_PARAMETERNAMESSELECTION__\n\n// Latex documentation\nstatic const char *docstringParameterNamesSelection = R\"(\n\\subsection{Selection}\nSelect a subset of \\configClass{parameterName}{parameterNamesType}s\nusing \\configClass{parameterSelection}{parameterSelectorType}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Selection of parameter names.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesSelection : public ParameterNamesBase\n{\npublic:\n  ParameterNamesSelection(Config &config)\n  {\n    try\n    {\n      ParameterNamesPtr    parameterNames;\n      ParameterSelectorPtr selector;\n\n      readConfig(config, \"parameterName\",      parameterNames, Config::MUSTSET, \"\", \"\");\n      readConfig(config, \"parameterSelection\", selector,       Config::MUSTSET, \"\", \"parameter order/selection\");\n      if(isCreateSchema(config)) return;\n\n      for(UInt i : selector->indexVector(parameterNames->parameterNames()))\n        names.push_back((i != NULLINDEX) ? parameterNames->parameterNames().at(i) : ParameterName());\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesTemporal.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesTemporal.h\n*\n* @brief Parameter names from temporal parametrization.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESTEMPORAL__\n#define __GROOPS_PARAMETERNAMESTEMPORAL__\n\n// Latex documentation\nstatic const char *docstringParameterNamesTemporal = R\"(\n\\subsection{Temporal}\nParameter names from temporal parametrization.\nIt is possible to setup the temporal parameters for each \\configClass{parameterNameBase}{parameterNamesType}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter names from temporal parametrization.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesTemporal : public ParameterNamesBase\n{\npublic:\n  ParameterNamesTemporal(Config &config)\n  {\n    try\n    {\n      ParameterNamesPtr          parameterNames;\n      ParametrizationTemporalPtr temporal;\n\n      readConfig(config, \"parameterNameBase\",       parameterNames, Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"parametrizationTemporal\", temporal,       Config::MUSTSET,  \"\", \"\");\n      if(isCreateSchema(config)) return;\n\n      if(parameterNames && parameterNames->parameterNames().size())\n        temporal->parameterName(parameterNames->parameterNames(), names);\n      else\n        temporal->parameterName(names);\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterNames/parameterNamesWithoutDuplicates.h",
    "content": "/***********************************************/\n/**\n* @file parameterNamesWithoutDuplicates.h\n*\n* @brief Removes all duplicate names.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-05-29\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERNAMESWITHOUTDUPLICATES__\n#define __GROOPS_PARAMETERNAMESWITHOUTDUPLICATES__\n\n// Latex documentation\nstatic const char *docstringParameterNamesWithoutDuplicates = R\"(\n\\subsection{WithoutDuplicates}\nRemoves all duplicate names (keep first) from \\configClass{parameterName}{parameterNamesType}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Removes all duplicate names.\n* @ingroup parameterNamesGroup\n* @see ParameterNames */\nclass ParameterNamesWithoutDuplicates : public ParameterNamesBase\n{\npublic:\n  ParameterNamesWithoutDuplicates(Config &config)\n  {\n    try\n    {\n      ParameterNamesPtr parameterNames;\n\n      readConfig(config, \"parameterName\", parameterNames, Config::MUSTSET,  \"\", \"\");\n      if(isCreateSchema(config)) return;\n\n      std::set<ParameterName> sortedNames;\n      for(const auto &parameterName : parameterNames->parameterNames())\n        if(sortedNames.find(parameterName) == sortedNames.end())\n        {\n          sortedNames.insert(parameterName);\n          names.push_back(parameterName);\n        }\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelector.cpp",
    "content": "/***********************************************/\n/**\n* @file parameterSelector.cpp\n*\n* @brief Index vector from selected parameters.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_ParameterSelector\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/parameterSelector/parameterSelectorComplement.h\"\n#include \"classes/parameterSelector/parameterSelectorGroup.h\"\n#include \"classes/parameterSelector/parameterSelectorMatrix.h\"\n#include \"classes/parameterSelector/parameterSelectorNames.h\"\n#include \"classes/parameterSelector/parameterSelectorRange.h\"\n#include \"classes/parameterSelector/parameterSelectorWildcard.h\"\n#include \"classes/parameterSelector/parameterSelectorZeros.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParameterSelector, \"parameterSelectorType\",\n                      ParameterSelectorWildcard,\n                      ParameterSelectorNames,\n                      ParameterSelectorRange,\n                      ParameterSelectorMatrix,\n                      ParameterSelectorZeros,\n                      ParameterSelectorGroup,\n                      ParameterSelectorComplement)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParameterSelector, \"parameterSelectorType\")\n\n/***********************************************/\n\nParameterSelector::ParameterSelector(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"selected parameters\"))\n    {\n      renameDeprecatedChoice(config, type, \"name\", \"wildcard\", date2time(2020, 5, 30));\n\n      if(readConfigChoiceElement(config, \"wildcard\",   type, \"parameter name matching\"))\n        parameters.push_back(new ParameterSelectorWildcard(config));\n      if(readConfigChoiceElement(config, \"names\",      type, \"manual list of parameter names\"))\n        parameters.push_back(new ParameterSelectorNames(config));\n      if(readConfigChoiceElement(config, \"range\",      type, \"range of parameters\"))\n        parameters.push_back(new ParameterSelectorRange(config));\n      if(readConfigChoiceElement(config, \"matrix\",     type, \"matrix containing parameter indexes\"))\n        parameters.push_back(new ParameterSelectorMatrix(config));\n      if(readConfigChoiceElement(config, \"zeros\",      type, \"additional zero parameters\"))\n        parameters.push_back(new ParameterSelectorZeros(config));\n      if(readConfigChoiceElement(config, \"group\",      type, \"groups a set of parameter selectors.\"))\n        parameters.push_back(new ParameterSelectorGroup(config));\n      if(readConfigChoiceElement(config, \"complement\", type, \"all parameters except those selected\"))\n        parameters.push_back(new ParameterSelectorComplement(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParameterSelector::~ParameterSelector()\n{\n  for(UInt i=0; i<parameters.size(); i++)\n    delete parameters.at(i);\n}\n\n/***********************************************/\n\nstd::vector<UInt> ParameterSelector::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    std::vector<UInt> vector;\n    for(const auto &param : parameters)\n    {\n      std::vector<UInt> vec = param->indexVector(parameterNames);\n      vector.insert(vector.end(), vec.begin(), vec.end());\n    }\n    return vector;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<UInt> ParameterSelector::indexVectorComplement(std::vector<UInt> vector, UInt referenceLength)\n{\n  try\n  {\n    std::vector<UInt> complement;\n    std::vector<UInt> all(referenceLength);\n    std::iota(all.begin(), all.end(), 0);\n\n    if(!vector.size())\n      return all;\n\n    std::sort(vector.begin(), vector.end());\n    std::set_difference(all.begin(), all.end(), vector.begin(), vector.end(), std::inserter(complement, complement.end()));\n\n    return complement;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelector.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelector.h\n*\n* @brief Index vector from selected parameters.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTOR__\n#define __GROOPS_PARAMETERSELECTOR__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelector = R\"(\n\\section{ParameterSelector}\\label{parameterSelectorType}\nThis class provides an index vector from selected parameters,\nwhich can be used e.g. to reorder a normal equation matrix.\nThe size of the index vector determines the size of the new matrix.\nEntries are the indices of the selected parameters in the provided\nparameter list or NULLINDEX for zero/new parameters.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup parameterSelectorGroup ParameterSelector\n* @brief Index vector from selected parameters.\n* @ingroup classesGroup\n* The interface is given by @ref ParameterSelector. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParameterSelector;\nclass ParameterSelectorBase;\ntypedef std::shared_ptr<ParameterSelector> ParameterSelectorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Index vector from selected parameters.\n* This class provides an index vector from selected parameters.\n* An Instance of this class can be created by @ref readConfig. */\nclass ParameterSelector\n{\n  std::vector<ParameterSelectorBase*> parameters;\n\npublic:\n  /// Constructor.\n  ParameterSelector(Config &config, const std::string &name);\n\n  /// Destructor.\n ~ParameterSelector();\n\n  /** @brief Returns the index vector. */\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames);\n\n  /** @brief Returns an index vector containing all indexes from 0 to @p referenceLength that are not in @p vector. */\n  static std::vector<UInt> indexVectorComplement(std::vector<UInt> vector, UInt referenceLength);\n\n  /** @brief creates an derived instance of this class. */\n  static ParameterSelectorPtr create(Config &config, const std::string &name) {return ParameterSelectorPtr(new ParameterSelector(config, name));}\n};\n\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ParameterSelector.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a ParameterSelector with zero-size matrix is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] parameterSelector Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ParameterSelector */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParameterSelectorPtr &parameterSelector, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass ParameterSelectorBase\n{\npublic:\n  virtual ~ParameterSelectorBase() {}\n  virtual std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames) = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorComplement.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorComplement.h\n*\n* @brief Parameter index vector from a complement of other parameter selector(s).\n*\n* @author Sebastian Strasser\n* @date 2019-09-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORCOMPLEMENT__\n#define __GROOPS_PARAMETERSELECTORCOMPLEMENT__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorComplement = R\"(\n\\subsection{Complement}\\label{parameterSelectorType:complement}\nParameter index vector from a complement of other parameter selector(s).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter index vector from a complement of other parameter selector(s).\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorComplement : public ParameterSelectorBase\n{\n  ParameterSelectorPtr parameterSelector;\n\npublic:\n  ParameterSelectorComplement(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorComplement::ParameterSelectorComplement(Config &config)\n{\n  try\n  {\n    readConfig(config, \"parameterSelection\", parameterSelector, Config::MUSTSET, \"\", \"parameter order/selection\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorComplement::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    return ParameterSelector::indexVectorComplement(parameterSelector->indexVector(parameterNames), parameterNames.size());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorGroup.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorGroup.h\n*\n* @brief Groups a set parameter selectors.\n*\n* @author Torsten Mayer-Guerr\n* @date 2026-93-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORGROUP__\n#define __GROOPS_PARAMETERSELECTORGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorGroup = R\"(\n\\subsection{Group}\\label{parameterSelectorType:group}\nGroups a set of \\configClass{parameterSelection}{parameterSelectorType}s and has no further effect itself.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Groups a set parameter selectors.\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorGroup : public ParameterSelectorBase\n{\n  ParameterSelectorPtr parameterSelector;\n\npublic:\n  ParameterSelectorGroup(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorGroup::ParameterSelectorGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"parameterSelection\", parameterSelector, Config::MUSTSET, \"\", \"parameter order/selection\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorGroup::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    return parameterSelector->indexVector(parameterNames);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorMatrix.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorMatrix.h\n*\n* @brief Parameter index vector from matrix.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORMATRIX__\n#define __GROOPS_PARAMETERSELECTORMATRIX__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorMatrix = R\"(\n\\subsection{Matrix}\nParameter index vector from matrix.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter index vector from matrix.\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorMatrix : public ParameterSelectorBase\n{\n  FileName fileName;\n  ExpressionVariablePtr exprColumn, exprStartRow, exprCountRows;\n\npublic:\n  ParameterSelectorMatrix(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorMatrix::ParameterSelectorMatrix(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileMatrix\", fileName,      Config::MUSTSET,  \"\",  \"index in old parameter list or -1 for new parameter\");\n    readConfig(config, \"column\",          exprColumn,    Config::DEFAULT,  \"0\", \"use this column (counting from 0, variables: columns)\");\n    readConfig(config, \"startRow\",        exprStartRow,  Config::DEFAULT,  \"0\", \"start at this row (counting from 0, variables: rows)\");\n    readConfig(config, \"countRows\",       exprCountRows, Config::OPTIONAL, \"\",  \"use these many rows (default: use all, variables: rows)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorMatrix::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    Matrix matrix;\n    readFileMatrix(fileName, matrix);\n\n    VariableList varList;\n    varList.setVariable(\"rows\",    static_cast<Double>(matrix.rows()));\n    varList.setVariable(\"columns\", static_cast<Double>(matrix.columns()));\n    const UInt   column    = static_cast<UInt>(exprColumn->evaluate(varList));\n    const UInt   startRow  = static_cast<UInt>(exprStartRow->evaluate(varList));\n    const UInt   countRows = (exprCountRows ? static_cast<UInt>(exprCountRows->evaluate(varList)) : matrix.rows()-startRow);\n    const Vector index     = matrix.slice(startRow, column, countRows, 1);\n\n    const UInt parameterCount = parameterNames.size();\n    if(max(index) > static_cast<Double>(MAX_UINT))\n      throw(Exception(\"unsigned integer overflow: \"+max(index)%\"%e > \"s+MAX_UINT%\"%.0f\"s));\n    if(max(index) >= parameterCount)\n      throw(Exception(\"matrix contains index that exceeds parameter count: \"+max(index)%\"%i >= \"s+parameterCount%\"%i\"s));\n\n    std::vector<UInt> vector(index.size());\n    for(UInt i=0; i<index.size(); i++)\n      vector.at(i) = ((index(i) < 0) ? NULLINDEX : static_cast<UInt>(index(i)));\n\n    return vector;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorNames.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorNames.h\n*\n* @brief Parameter index vector from list of parameter names.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORMANUALLIST__\n#define __GROOPS_PARAMETERSELECTORMANUALLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorNames = R\"(\n\\subsection{Names}\nParameter index vector from list of parameter names.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter index vector from list of parameter names.\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorNames : public ParameterSelectorBase\n{\n  std::vector<ParameterName> requestedNames;\n\npublic:\n  ParameterSelectorNames(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &ParameterNames);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorNames::ParameterSelectorNames(Config &config)\n{\n  try\n  {\n    ParameterNamesPtr parameterNames;\n    readConfig(config, \"parameterName\", parameterNames, Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    requestedNames = parameterNames->parameterNames();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorNames::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    std::vector<UInt> vector;\n    auto iter = parameterNames.begin(); // assume ordered list to accelerate search\n    for(const auto &name : requestedNames)\n    {\n      iter = std::find(iter, parameterNames.end(), name);\n      if(iter == parameterNames.end()) // not found? -> restart search from begin\n        iter = std::find(parameterNames.begin(), parameterNames.end(), name);\n      vector.push_back((iter != parameterNames.end()) ? std::distance(parameterNames.begin(), iter) : NULLINDEX);\n    }\n\n    return vector;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorRange.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorRange.h\n*\n* @brief Parameter index vector from range.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORRANGE__\n#define __GROOPS_PARAMETERSELECTORRANGE__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorRange = R\"(\n\\subsection{Range}\nParameter index vector from range.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter index vector from range.\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorRange : public ParameterSelectorBase\n{\n  ExpressionVariablePtr exprStart, exprCount;\n\npublic:\n  ParameterSelectorRange(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorRange::ParameterSelectorRange(Config &config)\n{\n  try\n  {\n    readConfig(config, \"start\",   exprStart, Config::MUSTSET,  \"0\", \"start at this index (variables: length)\");\n    readConfig(config, \"count\",   exprCount, Config::OPTIONAL, \"\",  \"count of parameters, default: all parameters to the end (variables: length)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorRange::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    const UInt parameterCount = parameterNames.size();\n    VariableList varList;\n    varList.setVariable(\"length\", static_cast<Double>(parameterCount));\n    const UInt start = static_cast<UInt>(exprStart->evaluate(varList));\n    const UInt count = (exprCount ? static_cast<UInt>(exprCount->evaluate(varList)) : parameterCount-start);\n\n    if(start >= parameterCount)\n      return {};\n    if(start+count > parameterCount)\n      throw(Exception(\"range exceeds parameter count: \"+(start+count)%\"%i >= \"s+parameterCount%\"%i\"s));\n\n    std::vector<UInt> vector(count);\n    std::iota(vector.begin(), vector.end(), start);\n\n    return vector;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorWildcard.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorWildcard.h\n*\n* @brief Parameter index vector from name.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORNAME__\n#define __GROOPS_PARAMETERSELECTORNAME__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorWildcard = R\"(\n\\subsection{Wildcard}\\label{parameterSelectorType:wildcard}\nParameter index vector from name. Name matching supports wildcards * for any number of characters and ? for exactly one character.\nDoes not add zero/empty parameters if there are no matches.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter index vector from name.\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorWildcard : public ParameterSelectorBase\n{\n  std::string object, type, temporal, interval;\n\npublic:\n  ParameterSelectorWildcard(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterWildcards);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorWildcard::ParameterSelectorWildcard(Config &config)\n{\n  try\n  {\n    readConfig(config, \"object\",   object,   Config::OPTIONAL, \"*\", \"object this parameter refers to, e.g. graceA, G023, earth (wildcards: * and ?)\");\n    readConfig(config, \"type\",     type,     Config::OPTIONAL, \"*\", \"type of this parameter, e.g. accBias, position.x (wildcards: * and ?)\");\n    readConfig(config, \"temporal\", temporal, Config::OPTIONAL, \"*\", \"temporal representation of this parameter, e.g. trend, polynomial.degree1 (wildcards: * and ?)\");\n    readConfig(config, \"interval\", interval, Config::OPTIONAL, \"*\", \"interval/epoch this parameter refers to, e.g. 2017-01-01_00-00-00_2017-01-02_00-00-00, 2008-01-01_00-00-00 (wildcards: * and ?)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorWildcard::indexVector(const std::vector<ParameterName> &parameterWildcards)\n{\n  try\n  {\n    const std::regex pattern = String::wildcard2regex(ParameterName(object, type, temporal, interval).str());\n\n    std::vector<UInt> vector;\n    for(UInt i=0; i<parameterWildcards.size(); i++)\n      if(std::regex_match(parameterWildcards.at(i).str(), pattern))\n        vector.push_back(i);\n\n    return vector;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parameterSelector/parameterSelectorZeros.h",
    "content": "/***********************************************/\n/**\n* @file parameterSelectorZeros.h\n*\n* @brief Expand parameter index vector by adding zero parameters.\n*\n* @author Sebastian Strasser\n* @date 2018-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETERSELECTORZEROS__\n#define __GROOPS_PARAMETERSELECTORZEROS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParameterSelector\nstatic const char *docstringParameterSelectorZeros = R\"(\n\\subsection{Zeros}\nExpand parameter index vector by adding zero parameters.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Expand parameter index vector by adding zero parameters.\n* @ingroup parameterSelectorGroup\n* @see ParameterSelector */\nclass ParameterSelectorZeros : public ParameterSelectorBase\n{\n  ExpressionVariablePtr exprCount;\n\npublic:\n  ParameterSelectorZeros(Config &config);\n  std::vector<UInt> indexVector(const std::vector<ParameterName> &parameterNames);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParameterSelectorZeros::ParameterSelectorZeros(Config &config)\n{\n  try\n  {\n    readConfig(config, \"count\", exprCount, Config::MUSTSET, \"\", \"count of zero parameters (variables: length)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<UInt> ParameterSelectorZeros::indexVector(const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    VariableList varList;\n    varList.setVariable(\"length\", static_cast<Double>(parameterNames.size()));\n    const UInt count = static_cast<UInt>(exprCount->evaluate(varList));\n    return std::vector<UInt>(count, NULLINDEX);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAcceleration.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationAcceleration.cpp\n*\n* @brief Orbit force parameters.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_ParametrizationAcceleration\n\n#include \"base/import.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"config/configRegister.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAccelerationPerRevolution.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAccelerationAccBias.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAccelerationAccScaleFactors.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAccelerationGnssSolarRadiation.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAccelerationThermosphericDensity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAccelerationModelScale.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParametrizationAcceleration, \"parametrizationAccelerationType\",\n                      ParametrizationAccelerationPerRevolution,\n                      ParametrizationAccelerationAccBias,\n                      ParametrizationAccelerationAccScaleFactors,\n                      ParametrizationAccelerationGnssSolarRadiation,\n                      ParametrizationAccelerationThermosphericDensity,\n                      ParametrizationAccelerationModelScale)\n\nGROOPS_RENAMED_CLASS(parameterSatelliteType, parametrizationAccelerationType, date2time(2020, 6, 3))\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParametrizationAcceleration, \"parametrizationAccelerationType\")\n\n/***********************************************/\n\nParametrizationAcceleration::ParametrizationAcceleration(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"orbit force parameters\"))\n    {\n      if(readConfigChoiceElement(config, \"perRevolution\",             type, \"oscillation per revoultion\"))\n        parameter.push_back(new ParametrizationAccelerationPerRevolution(config));\n      if(readConfigChoiceElement(config, \"accBias\"  ,                 type, \"accelerometer bias\"))\n        parameter.push_back(new ParametrizationAccelerationAccBias(config));\n      if(readConfigChoiceElement(config, \"accelerometerScaleFactors\", type, \"accelerometer scale factors\"))\n        parameter.push_back(new ParametrizationAccelerationAccScaleFactors(config));\n      if(readConfigChoiceElement(config, \"gnssSolarRadiation\",        type, \"GNSS solar radiation pressure model\"))\n        parameter.push_back(new ParametrizationAccelerationGnssSolarRadiation(config));\n      if(readConfigChoiceElement(config, \"thermosphericDensity\",      type, \"thermospheric density along the orbit\"))\n        parameter.push_back(new ParametrizationAccelerationThermosphericDensity(config));\n      if(readConfigChoiceElement(config, \"modelScale\",                type, \"model scale factor.\"))\n        parameter.push_back(new ParametrizationAccelerationModelScale(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n\n    computeIndicies();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParametrizationAcceleration::~ParametrizationAcceleration()\n{\n  for(UInt i=0; i<parameter.size(); i++)\n    delete parameter.at(i);\n}\n\n/***********************************************/\n\nvoid ParametrizationAcceleration::computeIndicies()\n{\n  try\n  {\n    parameterCountA = 0;\n    parameterCountB = 0;\n    indexA.resize(parameter.size());\n    indexB.resize(parameter.size());\n    for(UInt i=0; i<parameter.size(); i++)\n    {\n      indexA.at(i) = parameterCountA;\n      indexB.at(i) = parameterCountB;\n      if(parameter.at(i)->isPerArc())\n        parameterCountB += parameter.at(i)->parameterCount();\n      else\n        parameterCountA += parameter.at(i)->parameterCount();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationAcceleration::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    for(UInt i=0; i<parameter.size(); i++)\n      if(!parameter.at(i)->isPerArc())\n        change = parameter.at(i)->setInterval(timeStart, timeEnd) || change;\n    if(change)\n      computeIndicies();\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationAcceleration::setIntervalArc(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    for(UInt i=0; i<parameter.size(); i++)\n      if(parameter.at(i)->isPerArc())\n        change = parameter.at(i)->setInterval(timeStart, timeEnd) || change;\n    if(change)\n      computeIndicies();\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationAcceleration::parameterName(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<parameter.size(); i++)\n    if(!parameter.at(i)->isPerArc())\n      parameter.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nvoid ParametrizationAcceleration::parameterNameArc(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<parameter.size(); i++)\n    if(parameter.at(i)->isPerArc())\n      parameter.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nvoid ParametrizationAcceleration::compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                                 const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    if(satellite)\n    {\n      Vector3d positionSun;\n      if(ephemerides)\n        positionSun = ephemerides->position(time, Ephemerides::SUN);\n      satellite->changeState(time, position, velocity, positionSun, rotSat, rotEarth);\n    }\n\n    for(UInt i=0; i<parameter.size(); i++)\n      parameter.at(i)->compute(satellite, time, position, velocity, rotSat, rotEarth, ephemerides,\n                               (parameter.at(i)->isPerArc() ? B.slice(0, indexB.at(i), 3, parameter.at(i)->parameterCount()) :\n                                                              A.slice(0, indexA.at(i), 3, parameter.at(i)->parameterCount())));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAcceleration.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAcceleration.h\n*\n* @brief Orbit force parameters.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONACCELERATION__\n#define __GROOPS_PARAMETRIZATIONACCELERATION__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAcceleration = R\"(\n\\section{ParametrizationAcceleration}\\label{parametrizationAccelerationType}\nThis class defines parameters of satellite accelerations.\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"config/config.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/**\n* @defgroup parametrizationAccelerationGroup ParametrizationAcceleration\n* @brief Orbit force parameters.\n* @ingroup classesGroup\n* The interface is given by @ref ParametrizationAcceleration. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParametrizationAcceleration;\nclass ParametrizationAccelerationBase;\ntypedef std::shared_ptr<ParametrizationAcceleration> ParametrizationAccelerationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Orbit force parameters.\n* Creates the observation equations of orbit parameters (design matrix).\n* An Instance of this class can be created by @ref readConfig. */\nclass ParametrizationAcceleration\n{\n  UInt parameterCountA, parameterCountB;\n  std::vector<UInt> indexA, indexB;\n  std::vector<ParametrizationAccelerationBase*> parameter;\n\n  void computeIndicies();\n\npublic:\n  /// Constructor.\n  ParametrizationAcceleration(Config &config, const std::string &name);\n\n  /// Destructor.\n ~ParametrizationAcceleration();\n\n  /** @brief Estimate parameter in the given interval only.\n  * Change result of @a parameterCount(), @a parameterName().\n  * @return TRUE if parameters are changed */\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n\n  /** @brief Set the interval for the estimation arc related parameters.\n  * Must be called at the beginning of every new arc.\n  * Can change result of @a parameterCountArc(), @a parameterNameArc().\n  * @return TRUE if parameters are changed */\n  Bool setIntervalArc(const Time &timeStart, const Time &timeEnd);\n\n  /** @brief Number of unknown parameters.\n  * This is the column count of the design matrix @a A. */\n  UInt parameterCount() const {return parameterCountA;}\n\n  /** @brief Number of unknown arc related parameters.\n  * This is the column count of the design matrix @a B. */\n  UInt parameterCountArc() const {return parameterCountB;}\n\n  /** @brief Name of parameters.\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Name of arc related parameters.\n  * The names are appended to @a name. */\n  void parameterNameArc(std::vector<ParameterName> &name) const;\n\n  /** @brief Partial Derivations of force function.\n  * @param satellite Macro model.\n  * @param time GPS time\n  * @param position in CRF [m]\n  * @param velocity in CRF [m/s]\n  * @param rotSat   Sat -> CRF\n  * @param rotEarth CRF -> TRF\n  * @param ephemerides Position of Sun and Moon\n  * @param[out] A (3 x parameterCount) matrix with partial derivatives in TRF(!) [m/s^2]\n  * @param[out] B (3 x parameterCountArc) matrix with partial derivatives in TRF(!) [m/s^2] */\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A, MatrixSliceRef B);\n\n  /** @brief creates an derived instance of this class. */\n  static ParametrizationAccelerationPtr create(Config &config, const std::string &name) {return ParametrizationAccelerationPtr(new ParametrizationAcceleration(config, name));}\n};\n\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ParametrizationAcceleration.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a parametrizationAcceleration without parameters is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] parametrizationAcceleration Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ParametrizationAcceleration */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParametrizationAccelerationPtr &parametrizationAcceleration, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass ParametrizationAccelerationBase\n{\npublic:\nvirtual ~ParametrizationAccelerationBase() {}\nvirtual Bool isPerArc() const = 0;\nvirtual Bool setInterval(const Time &timeStart, const Time &timeEnd) = 0;\nvirtual UInt parameterCount() const = 0;\nvirtual void parameterName(std::vector<ParameterName> &name) const = 0;\nvirtual void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                     const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAccelerationAccBias.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAccelerationAccBias.h\n*\n* @brief Accelerometer bias (time variable).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONACCELERATIONACCBIAS__\n#define __GROOPS_PARAMETRIZATIONACCELERATIONACCBIAS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAccelerationAccBias = R\"(\n\\subsection{AccBias}\\label{parametrizationAccelerationType:accBias}\nTemporal changing accelerometer bias per axis in $[m/s^2]$ in Satellite Reference Frame (SRF).\nIf the attitude of the satellite is not provided the Celestial Reference Frame (CRF) is used instead.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:accBias.x:*:*|,\n\\item \\verb|*:accBias.y:*:*|,\n\\item \\verb|*:accBias.z:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accelerometer bias (time variable).\n* @ingroup parametrizationAccelerationGroup\n* @see ParametrizationAcceleration */\nclass ParametrizationAccelerationAccBias : public ParametrizationAccelerationBase\n{\n  ParametrizationTemporalPtr temporal;\n  UInt countAxis;\n  Bool estimateX, estimateY, estimateZ;\n  Bool perArc;\n\npublic:\n  ParametrizationAccelerationAccBias(Config &config);\n\n  Bool isPerArc() const override {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return temporal->setInterval(timeStart, timeEnd, perArc);}\n  UInt parameterCount() const override {return countAxis*temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationAccelerationAccBias::ParametrizationAccelerationAccBias(Config &config)\n{\n  try\n  {\n    readConfig(config, \"estimateX\", estimateX,  Config::DEFAULT,  \"1\", \"along\");\n    readConfig(config, \"estimateY\", estimateY,  Config::DEFAULT,  \"1\", \"cross\");\n    readConfig(config, \"estimateZ\", estimateZ,  Config::DEFAULT,  \"1\", \"radial\");\n    readConfig(config, \"temporal\",  temporal,   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",    perArc,     Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    countAxis = estimateX+estimateY+estimateZ;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationAccBias::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName;\n    if(estimateX) baseName.push_back(ParameterName(\"satellite\", \"accBias.x\"));\n    if(estimateY) baseName.push_back(ParameterName(\"satellite\", \"accBias.y\"));\n    if(estimateZ) baseName.push_back(ParameterName(\"satellite\", \"accBias.z\"));\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationAccBias::compute(SatelliteModelPtr /*satellite*/, const Time &time, const Vector3d &/*position*/, const Vector3d &/*velocity*/,\n                                                        const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/, MatrixSliceRef A)\n{\n  try\n  {\n    const Matrix rotary = (rotEarth*rotSat).matrix();\n    Matrix R(3, countAxis);\n    UInt idxAxis = 0;\n    if(estimateX) copy(rotary.column(0), R.column(idxAxis++));\n    if(estimateY) copy(rotary.column(1), R.column(idxAxis++));\n    if(estimateZ) copy(rotary.column(2), R.column(idxAxis++));\n\n    temporal->designMatrix(time, R, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAccelerationAccScaleFactors.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAccelerationAccScaleFactors.h\n*\n* @brief Accelerometer scale factors.\n*\n* @author Torsten Mayer-Guerr\n* @author Beate Klinger\n* @date 2015-06-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONACCELERATIONACCSCALEFACTORS__\n#define __GROOPS_PARAMETRIZATIONACCELERATIONACCSCALEFACTORS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAccelerationAccScaleFactors = R\"(\n\\subsection{AccelerometerScaleFactors}\\label{parametrizationAccelerationType:accelerometerScaleFactors}\nAccelerometer scale factor per axis.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:accScale.x:<temporal>:<interval>|,\n\\item \\verb|*:accScale.y:<temporal>:<interval>|,\n\\item \\verb|*:accScale.z:<temporal>:<interval>|,\n\\item \\verb|*:accScaleCross.xy:<temporal>:<interval>|,\n\\item \\verb|*:accScaleCross.xz:<temporal>:<interval>|,\n\\item \\verb|*:accScaleCross.yz:<temporal>:<interval>|,\n\\item \\verb|*:accScaleRotation.xy:<temporal>:<interval>|,\n\\item \\verb|*:accScaleRotation.xz:<temporal>:<interval>|,\n\\item \\verb|*:accScaleRotation.yz:<temporal>:<interval>|.\n\\end{itemize}\n\nThis parametrization needs the attitude of the satellite.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accelerometer scale factors.\n* @ingroup parametrizationAccelerationGroup\n* @see ParametrizationAcceleration */\nclass ParametrizationAccelerationAccScaleFactors : public ParametrizationAccelerationBase\n{\n  AccelerometerArc           accelerometer;\n  ParametrizationTemporalPtr temporal;\n  UInt                       countAxis;\n  Bool                       estimateX, estimateY, estimateZ;\n  Bool                       estimateCross, estimateRotation;\n  Bool                       perArc;\n  UInt                       idx;\n\npublic:\n  ParametrizationAccelerationAccScaleFactors(Config &config);\n\n  Bool isPerArc() const override {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return temporal->setInterval(timeStart, timeEnd, perArc);}\n  UInt parameterCount() const override {return countAxis*temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationAccelerationAccScaleFactors::ParametrizationAccelerationAccScaleFactors(Config &config)\n{\n  try\n  {\n    FileName fileNameAcc;\n\n    readConfig(config, \"inputfileAccelerometer\", fileNameAcc, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"estimateX\",         estimateX,        Config::DEFAULT,  \"1\", \"along\");\n    readConfig(config, \"estimateY\",         estimateY,        Config::DEFAULT,  \"1\", \"cross\");\n    readConfig(config, \"estimateZ\",         estimateZ,        Config::DEFAULT,  \"1\", \"radial\");\n    readConfig(config, \"estimateCrossTalk\", estimateCross,    Config::DEFAULT,  \"0\", \"non-orthognality of axes\");\n    readConfig(config, \"estimateRotation\",  estimateRotation, Config::DEFAULT,  \"0\", \"misalignment\");\n    readConfig(config, \"temporal\",          temporal,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",            perArc,           Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    accelerometer = InstrumentFile::read(fileNameAcc);\n    countAxis     = estimateX+estimateY+estimateZ;\n    if(estimateCross)    countAxis += 3;\n    if(estimateRotation) countAxis += 3;\n    idx = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationAccScaleFactors::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName;\n    if(estimateX) baseName.push_back(ParameterName(\"satellite\", \"accScale.x\"));\n    if(estimateY) baseName.push_back(ParameterName(\"satellite\", \"accScale.y\"));\n    if(estimateZ) baseName.push_back(ParameterName(\"satellite\", \"accScale.z\"));\n    if(estimateCross)\n    {\n      baseName.push_back(ParameterName(\"satellite\", \"accScaleCross.xy\"));\n      baseName.push_back(ParameterName(\"satellite\", \"accScaleCross.xz\"));\n      baseName.push_back(ParameterName(\"satellite\", \"accScaleCross.yz\"));\n    }\n    if(estimateRotation)\n    {\n      baseName.push_back(ParameterName(\"satellite\", \"accScaleRotation.xy\"));\n      baseName.push_back(ParameterName(\"satellite\", \"accScaleRotation.xz\"));\n      baseName.push_back(ParameterName(\"satellite\", \"accScaleRotation.yz\"));\n    }\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationAccScaleFactors::compute(SatelliteModelPtr /*satellite*/, const Time &time, const Vector3d &/*position*/, const Vector3d &/*velocity*/,\n                                                       const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/, MatrixSliceRef A)\n{\n  try\n  {\n    if((time<accelerometer.at(0).time)||(time>accelerometer.at(accelerometer.size()-1).time))\n      throw(Exception(\"time not given in accelerometer file: \"+time.dateTimeStr()));\n\n    // find index (interpolations interval)\n    if((idx>=accelerometer.size()) || (time<accelerometer.at(idx).time))\n      idx = 0;\n    while(time>accelerometer.at(idx).time)\n      idx++;\n    if(time!=accelerometer.at(idx).time)\n      throw(Exception(\"time not given in accelerometer file: \"+time.dateTimeStr()));\n\n    const Matrix rotary = (rotEarth*rotSat).matrix();\n    Matrix R(3, countAxis);\n    UInt idxAxis = 0;\n    if(estimateX) axpy(accelerometer.at(idx).acceleration.x(), rotary.column(0), R.column(idxAxis++));\n    if(estimateY) axpy(accelerometer.at(idx).acceleration.y(), rotary.column(1), R.column(idxAxis++));\n    if(estimateZ) axpy(accelerometer.at(idx).acceleration.z(), rotary.column(2), R.column(idxAxis++));\n\n    if(estimateCross)\n    {\n      axpy(accelerometer.at(idx).acceleration.y(), rotary.column(0), R.column(idxAxis));\n      axpy(accelerometer.at(idx).acceleration.x(), rotary.column(1), R.column(idxAxis++));\n      axpy(accelerometer.at(idx).acceleration.z(), rotary.column(0), R.column(idxAxis));\n      axpy(accelerometer.at(idx).acceleration.x(), rotary.column(2), R.column(idxAxis++));\n      axpy(accelerometer.at(idx).acceleration.z(), rotary.column(1), R.column(idxAxis));\n      axpy(accelerometer.at(idx).acceleration.y(), rotary.column(2), R.column(idxAxis++));\n    }\n\n    if(estimateRotation)\n    {\n      axpy(-accelerometer.at(idx).acceleration.y(), rotary.column(0), R.column(idxAxis));\n      axpy( accelerometer.at(idx).acceleration.x(), rotary.column(1), R.column(idxAxis++));\n      axpy( accelerometer.at(idx).acceleration.z(), rotary.column(0), R.column(idxAxis));\n      axpy(-accelerometer.at(idx).acceleration.x(), rotary.column(2), R.column(idxAxis++));\n      axpy(-accelerometer.at(idx).acceleration.z(), rotary.column(1), R.column(idxAxis));\n      axpy( accelerometer.at(idx).acceleration.y(), rotary.column(2), R.column(idxAxis++));\n    }\n\n    temporal->designMatrix(time, R, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAccelerationGnssSolarRadiation.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAccelerationGnssSolarRadiation.h\n*\n* @brief GNSS solar radtion pressure model.\n*\n* @author Sebastian Strasser\n* @date 2013-12-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONACCELERATIONGNSSSOLARRADIATION__\n#define __GROOPS_PARAMETRIZATIONACCELERATIONGNSSSOLARRADIATION__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAccelerationGnssSolarRadiation = R\"(\n\\subsection{GnssSolarRadiation}\\label{parametrizationAccelerationType:gnssSolarRadiation}\nGNSS solar radiation pressure model. Paramters are estimated in $[nm/s^2=10^{-9}\\,m/s^2]$.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:solarRadiationPressure.ECOM.D0:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DC2:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DS2:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DC4:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.DS4:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.Y0:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.B0:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BC1:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BS1:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BC3:*:*|,\n\\item \\verb|*:solarRadiationPressure.ECOM.BS3:*:*|.\n\\end{itemize}\n\nThis parametrization needs the attitude of the satellite.\n)\";\n#endif\n\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parametrizationAcceleration.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/eclipse/eclipse.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Oscillation per revoultion.\n* @ingroup parametrizationAccelerationGroup\n* @see ParametrizationAcceleration */\nclass ParametrizationAccelerationGnssSolarRadiation : public ParametrizationAccelerationBase\n{\n  UInt       countParameter;\n  Bool       d0, d2, d4;\n  Bool       y0;\n  Bool       b0, b1, b3;\n  Bool       perArc;\n  EclipsePtr eclipse;\n\npublic:\n  ParametrizationAccelerationGnssSolarRadiation(Config &config);\n\n  Bool isPerArc() const override {return perArc;}\n  Bool setInterval(const Time &/*timeStart*/, const Time &/*timeEnd*/) override {return FALSE;}\n  UInt parameterCount() const override {return countParameter;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n\ninline ParametrizationAccelerationGnssSolarRadiation::ParametrizationAccelerationGnssSolarRadiation(Config &config)\n{\n  try\n  {\n    d0 = d2 = d4 = FALSE;\n    y0 = FALSE;\n    b0 = b1 = b3 = FALSE;\n\n    readConfig(config, \"estimateD0\", d0,      Config::DEFAULT,  \"1\", \"constant term along D-axis (sat-sun vector)\");\n    readConfig(config, \"estimateD2\", d2,      Config::DEFAULT,  \"1\", \"2-per-rev terms along D-axis\");\n    readConfig(config, \"estimateD4\", d4,      Config::DEFAULT,  \"0\", \"4-per-rev terms along D-axis\");\n    readConfig(config, \"estimateY0\", y0,      Config::DEFAULT,  \"1\", \"constant term along Y-axis (solar panel axis)\");\n    readConfig(config, \"estimateB0\", b0,      Config::DEFAULT,  \"1\", \"constant term along B-axis (cross product D x Y)\");\n    readConfig(config, \"estimateB1\", b1,      Config::DEFAULT,  \"1\", \"1-per-rev terms along B-axis\");\n    readConfig(config, \"estimateB3\", b3,      Config::DEFAULT,  \"0\", \"3-per-rev terms along B-axis\");\n    readConfig(config, \"perArc\",     perArc,  Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"eclipse\",    eclipse, Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    countParameter = 0;\n    if(d0) countParameter++;\n    if(d2) countParameter += 2;\n    if(d4) countParameter += 2;\n\n    if(y0) countParameter++;\n\n    if(b0) countParameter++;\n    if(b1) countParameter += 2;\n    if(b3) countParameter += 2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationGnssSolarRadiation::parameterName(std::vector<ParameterName> &name) const\n{\n  if(d0) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.D0\"));\n  if(d2) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.DC2\"));\n  if(d2) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.DS2\"));\n  if(d4) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.DC4\"));\n  if(d4) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.DS4\"));\n\n  if(y0) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.Y0\"));\n\n  if(b0) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.B0\"));\n  if(b1) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.BC1\"));\n  if(b1) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.BS1\"));\n  if(b3) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.BC3\"));\n  if(b3) name.push_back(ParameterName(\"satellite\", \"solarRadiationPressure.ECOM.BS3\"));\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationGnssSolarRadiation::compute(SatelliteModelPtr /*satellite*/, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                                                          const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A)\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    // Positions in TRF\n    const Vector3d posSat = rotEarth.rotate(position);\n    const Vector3d posSun = rotEarth.rotate(ephemerides->position(time, Ephemerides::SUN));\n\n    // Argument of latitude of satellite relative to sun\n    Vector3d z = normalize(crossProduct(posSat, rotEarth.rotate(velocity))); // Orbital plane normal vector\n    Vector3d y = normalize(crossProduct(z, posSun));\n    Vector3d x = normalize(crossProduct(y, z));                              // Vector sat-sun projected into orbital plane\n    const Double du = std::atan2(inner(posSat, y), inner(posSat, x));\n\n    // Satellite DYB coordinate system (in TRF)\n    Vector3d dSat = normalize(posSun-posSat);\n    Vector3d ySat = rotEarth.rotate(rotSat.rotate(Vector3d(0,1,0)));\n    Vector3d bSat = normalize(crossProduct(dSat, ySat));\n\n    // Design matrix elements\n    const Double factor = 1e-9 * (eclipse ? eclipse->factor(time, position, ephemerides) : 1);  // Estimate accelerations in [nm/s^2]\n    UInt idx = 0;\n\n    if(d0) axpy(factor,                dSat.vector(), A.column(idx++)); // Constant D0  term\n    if(d2) axpy(factor*std::cos(2*du), dSat.vector(), A.column(idx++)); // Periodic DC2 term\n    if(d2) axpy(factor*std::sin(2*du), dSat.vector(), A.column(idx++)); // Periodic DS2 term\n    if(d4) axpy(factor*std::cos(4*du), dSat.vector(), A.column(idx++)); // Periodic DC4 term\n    if(d4) axpy(factor*std::sin(4*du), dSat.vector(), A.column(idx++)); // Periodic DS4 term\n\n    if(y0) axpy(factor,                ySat.vector(), A.column(idx++)); // Constant Y0  term\n\n    if(b0) axpy(factor,                bSat.vector(), A.column(idx++)); // Constant B0  term\n    if(b1) axpy(factor*std::cos(du),   bSat.vector(), A.column(idx++)); // Periodic BC1 term\n    if(b1) axpy(factor*std::sin(du),   bSat.vector(), A.column(idx++)); // Periodic BS1 term\n    if(b3) axpy(factor*std::cos(3*du), bSat.vector(), A.column(idx++)); // Periodic BC3 term\n    if(b3) axpy(factor*std::sin(3*du), bSat.vector(), A.column(idx++)); // Periodic BS3 term\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAccelerationModelScale.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAccelerationModelScale.h\n*\n* @brief Model scale factor.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONACCELERATIONMODELSCALE__\n#define __GROOPS_PARAMETRIZATIONACCELERATIONMODELSCALE__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAccelerationModelScale = R\"(\n\\subsection{ModelScale}\\label{parametrizationAccelerationType:modelScale}\nEstimate a scale factor for a given model.\nThe \\file{parameter names}{parameterName} are \\verb|*:modelScale:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Model scale factor.\n* @ingroup parametrizationAccelerationGroup\n* @see ParametrizationAcceleration */\nclass ParametrizationAccelerationModelScale : public ParametrizationAccelerationBase\n{\n  MiscAccelerationsPtr       model;\n  ParametrizationTemporalPtr temporal;\n  Bool                       perArc;\n\npublic:\n  ParametrizationAccelerationModelScale(Config &config);\n\n  Bool isPerArc() const override {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return temporal->setInterval(timeStart, timeEnd, perArc);}\n  UInt parameterCount() const override {return temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationAccelerationModelScale::ParametrizationAccelerationModelScale(Config &config)\n{\n  try\n  {\n    readConfig(config, \"miscAccelerations\", model,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"temporal\",          temporal, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",            perArc,   Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationModelScale::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName;\n    baseName.push_back(ParameterName(\"satellite\", \"modelScale\"));\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationModelScale::compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                                                       const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A)\n{\n  try\n  {\n    const Vector a = model->acceleration(satellite, time, position, velocity, rotSat, rotEarth, ephemerides).vector();\n    temporal->designMatrix(time, a, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAccelerationPerRevolution.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAccelerationPerRevolution.h\n*\n* @brief Oscillation per revoultion.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONACCELERATIONPERREVOLUTION__\n#define __GROOPS_PARAMETRIZATIONACCELERATIONPERREVOLUTION__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAccelerationPerRevolution = R\"(\n\\subsection{PerRevolution}\\label{parametrizationAccelerationType:perRevolution}\nOscillation once, twice, ... per revolution in Satellite Reference Frame (SRF)\nwith the argument of latitude as input angle.  If the attitude of the satellite\nis not provided the Celestial Reference Frame (CRF) is used instead.\nParamters are estimated in $[nm/s^2=10^{-9}\\,m/s^2]$.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:perRevolution.cos(<order>*u).x::<interval>|,\n\\item \\verb|*:perRevolution.cos(<order>*u).y::<interval>|,\n\\item \\verb|*:perRevolution.cos(<order>*u).z::<interval>|,\n\\item \\verb|*:perRevolution.sin(<order>*u).x::<interval>|,\n\\item \\verb|*:perRevolution.sin(<order>*u).y::<interval>|,\n\\item \\verb|*:perRevolution.sin(<order>*u).z::<interval>|.\n\\end{itemize}\n)\";\n#endif\n\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Oscillation per revoultion.\n* @ingroup parametrizationAccelerationGroup\n* @see ParametrizationAcceleration */\nclass ParametrizationAccelerationPerRevolution : public ParametrizationAccelerationBase\n{\n  std::vector<Time>  times;\n  UInt               idxStart, idxEnd;\n  UInt               order, countAxis;\n  Bool               estimateX, estimateY, estimateZ;\n  Bool               perArc;\n\npublic:\n  ParametrizationAccelerationPerRevolution(Config &config);\n\n  Bool isPerArc() const override {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount() const override {return 2*order*countAxis*(idxEnd-idxStart);}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationAccelerationPerRevolution::ParametrizationAccelerationPerRevolution(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timeSeries;\n    readConfig(config, \"order\",     order,      Config::MUSTSET,  \"1\", \"once, twice, ...\");\n    readConfig(config, \"estimateX\", estimateX,  Config::DEFAULT,  \"1\", \"along\");\n    readConfig(config, \"estimateY\", estimateY,  Config::DEFAULT,  \"1\", \"cross\");\n    readConfig(config, \"estimateZ\", estimateZ,  Config::DEFAULT,  \"1\", \"radial\");\n    readConfig(config, \"interval\",  timeSeries, Config::DEFAULT,  \"\",  \"setup new parameters each interval\");\n    readConfig(config, \"perArc\",    perArc,     Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    countAxis = estimateX+estimateY+estimateZ;\n\n    times = timeSeries->times();\n    if(times.size()==0)\n    {\n      times.push_back( Time() );\n      times.push_back( date2time(2500,1,1) );\n    }\n    idxStart = 0;\n    idxEnd   = times.size()-1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationAccelerationPerRevolution::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    const UInt idxStartOld = idxStart;\n    const UInt idxEndOld   = idxEnd;\n\n    idxStart = 0;\n    while((idxStart+1<times.size()) && (timeStart>=times.at(idxStart+1)))\n      idxStart++;\n    idxEnd = idxStart;\n    while((idxEnd<times.size()-1) && (timeEnd>times.at(idxEnd)))\n      idxEnd++;\n\n    return (idxStartOld != idxStart) || (idxEndOld != idxEnd);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationPerRevolution::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=idxStart; i<idxEnd; i++)\n    {\n      std::string dateStr;\n      if(times.front() != Time())\n        dateStr = times.at(i).dateTimeStr()+\"_\"+times.at(i+1).dateTimeStr();\n\n      for(UInt k=0; k<order; k++)\n      {\n        if(estimateX) name.push_back(ParameterName(\"satellite\", \"perRevolution.cos(\"+(k+1)%\"%i\"s+\"*u).x\", \"\", dateStr));\n        if(estimateY) name.push_back(ParameterName(\"satellite\", \"perRevolution.cos(\"+(k+1)%\"%i\"s+\"*u).y\", \"\", dateStr));\n        if(estimateZ) name.push_back(ParameterName(\"satellite\", \"perRevolution.cos(\"+(k+1)%\"%i\"s+\"*u).z\", \"\", dateStr));\n        if(estimateX) name.push_back(ParameterName(\"satellite\", \"perRevolution.sin(\"+(k+1)%\"%i\"s+\"*u).x\", \"\", dateStr));\n        if(estimateY) name.push_back(ParameterName(\"satellite\", \"perRevolution.sin(\"+(k+1)%\"%i\"s+\"*u).y\", \"\", dateStr));\n        if(estimateZ) name.push_back(ParameterName(\"satellite\", \"perRevolution.sin(\"+(k+1)%\"%i\"s+\"*u).z\", \"\", dateStr));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationPerRevolution::compute(SatelliteModelPtr /*satellite*/, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                                                     const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/, MatrixSliceRef A)\n{\n  try\n  {\n    if((time<times.at(idxStart))||(time>=times.at(idxEnd)))\n      return;\n\n    // findex index (interval)\n    UInt idx = idxStart;\n    while(time>=times.at(idx+1))\n      idx++;\n\n    // Argument of latitude of satellite\n    Vector3d z = normalize(crossProduct(position, velocity));\n    Vector3d x = normalize(crossProduct(Vector3d(0,0,1), z));\n    Vector3d y = crossProduct(z, x);\n    Double   u = atan2(inner(position,y), inner(position,x));\n\n    const Matrix rotary = (rotEarth*rotSat).matrix();\n    Matrix R(3, countAxis);\n    UInt idxAxis = 0;\n    if(estimateX) copy(rotary.column(0),  R.column(idxAxis++));\n    if(estimateY) copy(rotary.column(1),  R.column(idxAxis++));\n    if(estimateZ) copy(rotary.column(2),  R.column(idxAxis++));\n\n    for(UInt k=0; k<order; k++)\n    {\n      axpy(1e-9*cos((k+1)*u), R, A.column(2*order*countAxis*(idx-idxStart)+countAxis*(2*k+0), countAxis));\n      axpy(1e-9*sin((k+1)*u), R, A.column(2*order*countAxis*(idx-idxStart)+countAxis*(2*k+1), countAxis));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationAcceleration/parametrizationAccelerationThermosphericDensity.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationAccelerationThermosphericDensity.h\n*\n* @brief Estimate the thermospheric density along the orbit.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-11-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTHERMOSPHERICDENSITY__\n#define __GROOPS_PARAMETRIZATIONTHERMOSPHERICDENSITY__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationAcceleration\nstatic const char *docstringParametrizationAccelerationThermosphericDensity = R\"(\n\\subsection{ThermosphericDensity}\\label{parametrizationAccelerationType:thermosphericDensity}\nEstimate the thermospheric density along the orbit using a satllite macro model.\nAn optional thermospheric model can be used to compute temperature and wind.\nThe temperature is used to estimate variable drag and lift coefficients, otherwise a constant drag coefficient is used.\nThe density is estimated in $[kg/m^3]$.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:density:<temporal>:<interval>|.\n\nThis parametrization needs the macro model and the attitude of the satellite.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAtmosphericDrag.h\"\n#include \"parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate the thermospheric density along the orbit.\n* @ingroup parametrizationAccelerationGroup\n* @see ParametrizationAcceleration */\nclass ParametrizationAccelerationThermosphericDensity : public ParametrizationAccelerationBase\n{\n  ThermospherePtr            thermosphere;\n  Bool                       useTemperature, useWind;\n  Vector3d                   omega;\n  ParametrizationTemporalPtr temporal;\n  Bool                       perArc;\n\npublic:\n  ParametrizationAccelerationThermosphericDensity(Config &config);\n\n  Bool isPerArc() const override {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override {return temporal->setInterval(timeStart, timeEnd, perArc);}\n  UInt parameterCount() const override {return temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n               const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr ephemerides, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationAccelerationThermosphericDensity::ParametrizationAccelerationThermosphericDensity(Config &config)\n{\n  try\n  {\n    Double angleVelocity;\n\n    readConfig(config, \"thermosphere\",        thermosphere,   Config::OPTIONAL, \"\",  \"for wind and temperature\");\n    readConfig(config, \"earthRotation\",       angleVelocity,  Config::DEFAULT,  \"7.29211585531e-5\", \"[rad/s]\");\n    readConfig(config, \"considerTemperature\", useTemperature, Config::DEFAULT,  \"1\", \"compute drag and lift, otherwise simple drag coefficient is used\");\n    readConfig(config, \"considerWind\",        useWind,        Config::DEFAULT,  \"1\", \"\");\n    readConfig(config, \"temporalDensity\",     temporal,       Config::MUSTSET,  \"\",  \"parameters along orbit\");\n    readConfig(config, \"perArc\",              perArc,         Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    omega = Vector3d(0, 0, angleVelocity);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationThermosphericDensity::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    temporal->parameterName({ParameterName(\"satellite\", \"density\")}, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationAccelerationThermosphericDensity::compute(SatelliteModelPtr satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                                                                     const Rotary3d &rotSat, const Rotary3d &rotEarth, EphemeridesPtr /*ephemerides*/, MatrixSliceRef A)\n{\n  try\n  {\n    if(!satellite)\n      throw(Exception(\"No satellite model given\"));\n\n    Double   temperature=0;\n    Vector3d wind;\n    if(thermosphere)\n    {\n      Double density;\n      thermosphere->state(time, rotEarth.rotate(position), density, temperature, wind);\n      if(!useTemperature) temperature = 0;\n      if(!useWind)        wind = Vector3d();\n    }\n\n    // direction and speed of thermosphere relative to satellite in SRF\n    Vector3d direction = rotSat.inverseRotate(rotEarth.inverseRotate(wind) + crossProduct(omega, position) - velocity);\n    const Double   v   = direction.normalize();\n    const Vector3d acc = (1./satellite->mass) * MiscAccelerationsAtmosphericDrag::force(satellite, direction, v, 1/*density*/, temperature);\n    temporal->designMatrix(time, rotEarth.rotate(rotSat.rotate(acc)).vector(), A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationGnssAntenna/parametrizationGnssAntenna.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGnssAntenna.cpp\n*\n* @brief Parametrization of antenna center variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-08\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_ParametrizationGnssAntenna\n\n#include \"base/import.h\"\n#include \"base/gnssType.h\"\n#include \"config/configRegister.h\"\n#include \"parametrizationGnssAntennaSphericalHarmonics.h\"\n#include \"parametrizationGnssAntennaRadialBasis.h\"\n#include \"parametrizationGnssAntennaCenter.h\"\n#include \"parametrizationGnssAntenna.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParametrizationGnssAntenna, \"parametrizationGnssAntennaType\",\n                      ParametrizationGnssAntennaCenter,\n                      ParametrizationGnssAntennaSphericalHarmonics,\n                      ParametrizationGnssAntennaRadialBasis)\n\nGROOPS_RENAMED_CLASS(gnssAntennaRepresentationType, parametrizationGnssAntennaType, date2time(2020, 6, 3))\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParametrizationGnssAntenna, \"parametrizationGnssAntennaType\")\n\n/***********************************************/\n\nParametrizationGnssAntenna::ParametrizationGnssAntenna(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"antenna center variations\"))\n    {\n      if(readConfigChoiceElement(config, \"center\",  type, \"\"))\n        base.push_back(new ParametrizationGnssAntennaCenter(config));\n      if(readConfigChoiceElement(config, \"sphericalHarmonics\",  type, \"\"))\n        base.push_back(new ParametrizationGnssAntennaSphericalHarmonics(config));\n      if(readConfigChoiceElement(config, \"radialBasis\",  type, \"\"))\n        base.push_back(new ParametrizationGnssAntennaRadialBasis(config));\n\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n\n    parameterCount_ = 0;\n    index.resize(base.size());\n    for(UInt i=0; i<base.size(); i++)\n    {\n      index.at(i) = parameterCount_;\n      parameterCount_ += base.at(i)->parameterCount();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParametrizationGnssAntenna::~ParametrizationGnssAntenna()\n{\n  for(UInt i=0; i<base.size(); i++)\n    delete base.at(i);\n}\n\n/***********************************************/\n\nvoid ParametrizationGnssAntenna::parameterName(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<base.size(); i++)\n    base.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nMatrix ParametrizationGnssAntenna::designMatrix(Angle azimut, Angle elevation)\n{\n  try\n  {\n    Matrix A(1, parameterCount_);\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->designMatrix(azimut, elevation, A.column(index.at(i), base.at(i)->parameterCount()));\n    return A;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGnssAntenna.h\n*\n* @brief Parametrization of antenna center variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGNSSANTENNA__\n#define __GROOPS_PARAMETRIZATIONGNSSANTENNA__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGnssAntenna\nstatic const char *docstringParametrizationGnssAntenna = R\"(\n\\section{ParametrizationGnssAntenna}\\label{parametrizationGnssAntennaType}\nParametrization of antenna center variations. It will be used to set up the design matrix in a least squares adjustment.\nUsually the parametrization is setup separately for different \\configClass{gnssType}{gnssType}.\n\nIf multiple parametrizations are given the parameters are sequently appended in the design matrix and parameter vector.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"base/parameterName.h\"\n\n/**\n* @defgroup parametrizationGnssAntennaGroup ParametrizationGnssAntenna\n* @brief Parametrization of antenna center variations.\n* @ingroup classesGroup\n* The interface is given by @ref ParametrizationGnssAntenna. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParametrizationGnssAntenna;\nclass ParametrizationGnssAntennaBase;\ntypedef std::shared_ptr<ParametrizationGnssAntenna> ParametrizationGnssAntennaPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Parametrization of antenna center variations.\n* An Instance of this class can be created by @ref readConfig. */\nclass ParametrizationGnssAntenna\n{\n  UInt parameterCount_;\n  std::vector<UInt> index;\n  std::vector<ParametrizationGnssAntennaBase*> base;\n\npublic:\n  /// Constructor.\n  ParametrizationGnssAntenna(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~ParametrizationGnssAntenna();\n\n  /** @brief Number of parameters.\n  * This is the column count of the design matrix @a A. */\n  UInt parameterCount() const {return parameterCount_;}\n\n  /** @brief Name of parameters.\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Partial Derivations of antenna center variations.\n  * @return (1 x parameterCount) matrix with partial derivatives. */\n  Matrix designMatrix(Angle azimut, Angle elevation);\n\n  /** @brief creates an derived instance of this class. */\n  static ParametrizationGnssAntennaPtr create(Config &config, const std::string &name) {return ParametrizationGnssAntennaPtr(new ParametrizationGnssAntenna(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief creates an instance of the class ParametrizationGnssAntenna.\n* search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE.\n* @param config the config node which includes the node with the options for this class\n* @param name tag name in the config.\n* @param var output: created class.\n* @param mustSet if @a name is not found and @a mustSet=Config::MUSTSET, this function throws an exception instead of returning with FALSE.\n* @param defaultValue ignored at the moment.\n* @param annotation description of the function of this class.\n* @relates ParametrizationGnssAntenna */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParametrizationGnssAntennaPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass ParametrizationGnssAntennaBase\n{\npublic:\n  virtual ~ParametrizationGnssAntennaBase() {}\n  virtual UInt parameterCount() const = 0;\n  virtual void parameterName(std::vector<ParameterName> &name) const = 0;\n  virtual void designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A) = 0;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/classes/parametrizationGnssAntenna/parametrizationGnssAntennaCenter.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGnssAntennaCenter.h\n*\n* @brief Parametrization of antenna center variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-07-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGNSSANTENNACENTER__\n#define __GROOPS_PARAMETRIZATIONGNSSANTENNACENTER__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGnssAntenna\nstatic const char *docstringParametrizationGnssAntennaCenter = R\"(\n\\subsection{Center}\\label{parametrizationGnssAntennaType:center}\nAntenna center or, if setup for a specific \\configClass{gnssType}{gnssType},\nphase/code center offset (e.g. \\verb|*1*G| for GPS L1 phase center offset) in $[m]$.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:antennaCenter.x:*:*|,\n\\item \\verb|*:antennaCenter.y:*:*|,\n\\item \\verb|*:antennaCenter.z:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"parametrizationGnssAntenna.h\"\n\n/***** CLASS ***********************************/\n\nclass ParametrizationGnssAntennaCenter : public ParametrizationGnssAntennaBase\n{\n  Bool estimateX, estimateY, estimateZ;\n\npublic:\n  ParametrizationGnssAntennaCenter(Config &config);\n  UInt parameterCount() const override {return estimateX+estimateY+estimateZ;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationGnssAntennaCenter::ParametrizationGnssAntennaCenter(Config &config)\n{\n  try\n  {\n    readConfig(config, \"estimateX\", estimateX,  Config::DEFAULT,  \"1\", \"\");\n    readConfig(config, \"estimateY\", estimateY,  Config::DEFAULT,  \"1\", \"\");\n    readConfig(config, \"estimateZ\", estimateZ,  Config::DEFAULT,  \"1\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationGnssAntennaCenter::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    if(estimateX) name.push_back(ParameterName(\"\", \"antennaCenter.x\"));\n    if(estimateY) name.push_back(ParameterName(\"\", \"antennaCenter.y\"));\n    if(estimateZ) name.push_back(ParameterName(\"\", \"antennaCenter.z\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationGnssAntennaCenter::designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A)\n{\n  try\n  {\n    UInt idxAxis = 0;\n    if(estimateX) A(0, idxAxis++) = -std::cos(elevation) * std::cos(azimut);\n    if(estimateY) A(0, idxAxis++) = -std::cos(elevation) * std::sin(azimut);\n    if(estimateZ) A(0, idxAxis++) = -std::sin(elevation);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/classes/parametrizationGnssAntenna/parametrizationGnssAntennaRadialBasis.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGnssAntennaRadialBasis.h\n*\n* @brief Parametrization of antenna center variations.\n*\n* @author Norbert Zehentner\n* @date 2018-07-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGNSSANTENNARADIALBASIS__\n#define __GROOPS_PARAMETRIZATIONGNSSANTENNARADIALBASIS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGnssAntenna\nstatic const char *docstringParametrizationGnssAntennaRadialBasis = R\"(\n\\subsection{RadialBasis}\nParametrization of antenna center variations with radial basis functions\n\\begin{equation}\n  ACV(\\M x(A, E)) = \\sum_i a_i \\Phi(\\M x\\cdot\\M x_i)\n\\end{equation}\nwhere $a_i$ in $[m]$ the coefficients which has to be estimated and $\\Phi$ are the basis\nfunctions\n\\begin{equation}\n  \\Phi(\\cos\\psi) = \\sum_n \\sqrt{2n+1}P_n(\\cos\\psi).\n\\end{equation}\n\nThe \\file{parameter names}{parameterName} are\n\\verb|*:antennaCenterVariations.radialBasis.<index>.<total count>:*:*|.\n\n\\fig{!hb}{0.4}{parametrizationGnssAntennaRadialBasis}{fig:parametrizationGnssAntennaRadialBasis}{Nodal points of the basis functions\nusing a Reuter grid for transmitting satellites (view angle of 18 deg). The red line indicates the view angle of 14 deg of ground stations.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/legendrePolynomial.h\"\n#include \"classes/grid/grid.h\"\n#include \"parametrizationGnssAntenna.h\"\n\n/***** CLASS ***********************************/\n\nclass ParametrizationGnssAntennaRadialBasis : public ParametrizationGnssAntennaBase\n{\n  std::vector<Vector3d> point;\n  Vector                coeff;\n\npublic:\n  ParametrizationGnssAntennaRadialBasis(Config &config);\n  UInt parameterCount() const override {return point.size();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationGnssAntennaRadialBasis::ParametrizationGnssAntennaRadialBasis(Config &config)\n{\n  try\n  {\n    GridPtr grid;\n    UInt    minDegree, maxDegree;\n\n    readConfig(config, \"grid\",      grid,      Config::MUSTSET, \"\",  \"nodal points of shannon kernels\");\n    readConfig(config, \"minDegree\", minDegree, Config::MUSTSET, \"2\", \"min degree of shannon kernel\");\n    readConfig(config, \"maxDegree\", maxDegree, Config::MUSTSET, \"\",  \"max degree of shannon kernel\");\n    if(isCreateSchema(config)) return;\n\n    // init nodal points\n    point = grid->points();\n    for(UInt i=0; i<point.size(); i++)\n      point.at(i).normalize();\n\n    // init kernel coefficients\n    coeff = Vector(maxDegree+1);\n    for(UInt n=minDegree; n<=maxDegree; n++)\n      coeff(n) = 1.0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationGnssAntennaRadialBasis::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=0; i<point.size(); i++)\n      name.push_back(ParameterName(\"\", \"antennaCenterVariations.radialBasis.\"+i%\"%i\"s+\".\"+point.size()%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationGnssAntennaRadialBasis::designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A)\n{\n  try\n  {\n    const Vector3d e12 = polar(azimut, elevation, 1.);\n    for(UInt i=0; i<point.size(); i++)\n      A(0,i) = LegendrePolynomial::sum(inner(e12, point.at(i)), coeff, coeff.size()-1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/classes/parametrizationGnssAntenna/parametrizationGnssAntennaSphericalHarmonics.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGnssAntennaSphericalHarmonics.h\n*\n* @brief Parametrization of antenna center variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGNSSANTENNASPHERICALHARMONICS__\n#define __GROOPS_PARAMETRIZATIONGNSSANTENNASPHERICALHARMONICS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGnssAntenna\nstatic const char *docstringParametrizationGnssAntennaSphericalHarmonics = R\"(\n\\subsection{SphericalHarmonics}\nParametrization of antenna center variations in $[m]$ in terms of spherical harmonics.\nAs usually only data above the horizon are observed only the even spherical harmonics\n(degree/order $m+n$ even), which are symmetric to the equator, are setup.\n\nThe total count of parameters is $((n_{max}+1)(n_{max}+2)-n_{min}(n_{min}+1)/2$ and\nthe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:antennaCenterVariations.sphericalHarmonics.c_<degree>_<order>:*:*|,\n\\item \\verb|*:antennaCenterVariations.sphericalHarmonics.s_<degree>_<order>:*:*|.\n\\end{itemize}\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/sphericalHarmonics.h\"\n#include \"parametrizationGnssAntenna.h\"\n\n/***** CLASS ***********************************/\n\nclass ParametrizationGnssAntennaSphericalHarmonics : public ParametrizationGnssAntennaBase\n{\n  UInt minDegree, maxDegree;\n  UInt parameterCount_;\n\npublic:\n  ParametrizationGnssAntennaSphericalHarmonics(Config &config);\n  UInt parameterCount() const override {return parameterCount_;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A) override;\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationGnssAntennaSphericalHarmonics::ParametrizationGnssAntennaSphericalHarmonics(Config &config)\n{\n  try\n  {\n    readConfig(config, \"minDegree\", minDegree, Config::MUSTSET, \"2\", \"min degree\");\n    readConfig(config, \"maxDegree\", maxDegree, Config::MUSTSET, \"\",  \"max degree\");;\n    if(isCreateSchema(config)) return;\n\n    parameterCount_ = ((maxDegree+1)*(maxDegree+2)-minDegree*(minDegree+1))/2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationGnssAntennaSphericalHarmonics::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(n%2 == 0) // even?\n        name.push_back(ParameterName(\"\", \"antennaCenterVariations.sphericalHarmonics.c_\"+n%\"%i\"s+\"_0\"));\n      for(UInt m=2-n%2; m<=n; m+=2)\n      {\n        name.push_back(ParameterName(\"\", \"antennaCenterVariations.sphericalHarmonics.c_\"+n%\"%i\"s+\"_\"+m%\"%i\"s));\n        name.push_back(ParameterName(\"\", \"antennaCenterVariations.sphericalHarmonics.s_\"+n%\"%i\"s+\"_\"+m%\"%i\"s));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationGnssAntennaSphericalHarmonics::designMatrix(Angle azimut, Angle elevation, MatrixSliceRef A)\n{\n  try\n  {\n    const Vector3d e12 = polar(azimut, elevation, 1.);\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(e12, maxDegree, Cnm, Snm);\n    // only the functions which are symmetric to equator\n    UInt idx = 0;\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if((n%2) == 0) // even?\n        A(0,idx++) = Cnm(n,0);\n      for(UInt m=2-n%2; m<=n; m+=2)\n      {\n        A(0,idx++) = Cnm(n,m);\n        A(0,idx++) = Snm(n,m);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravity.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravity.cpp\n*\n* @brief Parametrization of the gravity field.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-25\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_ParametrizationGravity\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/configRegister.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/parametrizationGravity/parametrizationGravitySphericalHarmonics.h\"\n#include \"classes/parametrizationGravity/parametrizationGravityRadialBasis.h\"\n#include \"classes/parametrizationGravity/parametrizationGravityTemporal.h\"\n#include \"classes/parametrizationGravity/parametrizationGravityLinearTransformation.h\"\n#include \"classes/parametrizationGravity/parametrizationGravityEarthquakeOscillation.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParametrizationGravity, \"parametrizationGravityType\",\n                      ParametrizationGravitySphericalHarmonics,\n                      ParametrizationGravityRadialBasis,\n                      ParametrizationGravityTemporal,\n                      ParametrizationGravityLinearTransformation,\n                      ParametrizationGravityEarthquakeOscillation)\n\nGROOPS_RENAMED_CLASS(representationType, parametrizationGravityType, date2time(2020, 6, 3))\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParametrizationGravity, \"parametrizationGravityType\")\n\n/***********************************************/\n\nParametrizationGravity::ParametrizationGravity(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"parametrization of the gravity field\"))\n    {\n      if(readConfigChoiceElement(config, \"sphericalHarmonics\",   type, \"potential coefficients!\"))\n        parametrizations.push_back(new ParametrizationGravitySphericalHarmonics(config));\n      if(readConfigChoiceElement(config, \"radialBasis\",          type, \"harmonic radial basis functions\"))\n        parametrizations.push_back(new ParametrizationGravityRadialBasis(config));\n      if(readConfigChoiceElement(config, \"temporal\",             type, \"time variable gravity field\"))\n        parametrizations.push_back(new ParametrizationGravityTemporal(config));\n      if(readConfigChoiceElement(config, \"linearTransformation\", type, \"linear transformation of a original parameters\"))\n        parametrizations.push_back(new ParametrizationGravityLinearTransformation(config));\n      if(readConfigChoiceElement(config, \"earthquakeOscillation\", type, \"earthquake oscillation parameters\"))\n        parametrizations.push_back(new ParametrizationGravityEarthquakeOscillation(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n\n    computeIndices();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParametrizationGravity::~ParametrizationGravity()\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    delete parametrizations.at(i);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid ParametrizationGravity::computeIndices()\n{\n  try\n  {\n    _parameterCount = 0;\n    index.resize(parametrizations.size());\n    for(UInt i=0; i<parametrizations.size(); i++)\n    {\n      index.at(i) = _parameterCount;\n      _parameterCount += parametrizations.at(i)->parameterCount();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationGravity::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  Bool change = FALSE;\n  for(UInt i=0; i<parametrizations.size(); i++)\n    change = parametrizations.at(i)->setInterval(timeStart, timeEnd) || change;\n  if(change)\n    computeIndices();\n  return change;\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::parameterName(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::field(const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->field(time, point, kernel, A.slice(0,index.at(i),1,parametrizations.at(i)->parameterCount()));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::potential(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->potential(time, point, A.slice(0,index.at(i),1,parametrizations.at(i)->parameterCount()));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::radialGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->radialGradient(time, point, A.slice(0,index.at(i),1,parametrizations.at(i)->parameterCount()));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::gravity(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->gravity(time, point, A.slice(0,index.at(i),3,parametrizations.at(i)->parameterCount()));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->gravityGradient(time, point, A.slice(0,index.at(i),6,parametrizations.at(i)->parameterCount()));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravity::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<parametrizations.size(); i++)\n    parametrizations.at(i)->deformation(time, point, gravity, hn, ln, A.slice(0,index.at(i),3,parametrizations.at(i)->parameterCount()));\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravity::sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const\n{\n  try\n  {\n    SphericalHarmonics harmonics;\n    for(UInt i=0; i<parametrizations.size(); i++)\n      harmonics += parametrizations.at(i)->sphericalHarmonics(time, x.slice(index.at(i),parametrizations.at(i)->parameterCount()), maxDegree);\n    return harmonics;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravity::sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const\n{\n  try\n  {\n    SphericalHarmonics harmonics;\n    for(UInt i=0; i<parametrizations.size(); i++)\n      harmonics += parametrizations.at(i)->sphericalHarmonics(time, x.slice(index.at(i),parametrizations.at(i)->parameterCount()), sigma2x.slice(index.at(i),parametrizations.at(i)->parameterCount()), maxDegree);\n    return harmonics;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravity.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravity.h\n*\n* @brief Parametrization of the gravity field.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGRAVITY__\n#define __GROOPS_PARAMETRIZATIONGRAVITY__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGravity\nstatic const char *docstringParametrizationGravity = R\"(\n\\section{ParametrizationGravity}\\label{parametrizationGravityType}\nThis class gives a parametrization of the time depending gravity field.\nTogether with the class \\configClass{oberservation}{observationType} it will be used\nto set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n\n/**\n* @defgroup parametrizationGravityGroup ParametrizationGravity.\n* @brief Parametrization of the gravity field.\n* @ingroup classesGroup\n* The interface is given by @ref ParametrizationGravity. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParametrizationGravity;\nclass ParametrizationGravityBase;\ntypedef std::shared_ptr<ParametrizationGravity> ParametrizationGravityPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Parametrization of the gravity field.\n* Parametrization of the (time variable) gravity field.\n* Creates the observation equtions for different functions of the field (design matrix).\n* An Instance of this class can be created by @ref readConfig. */\nclass ParametrizationGravity\n{\n  UInt _parameterCount;\n  std::vector<UInt> index;\n  std::vector<ParametrizationGravityBase*> parametrizations;\n\n  void computeIndices();\n\npublic:\n  /// Constructor.\n  ParametrizationGravity(Config &config, const std::string &name);\n\n  /// Destructor.\n ~ParametrizationGravity();\n\n  /** @brief Estimate parameter in the given interval only.\n  * Change result of @a parameterCount(), @a parameterName().\n  * @return TRUE if parameters are changed */\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n\n  /** @brief Number of parameters.\n  * This is the column count of the design matrix. */\n  UInt parameterCount() const {return _parameterCount;}\n\n  /** @brief Name of parameters.\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Values of the gravity field.\n  * Observation equations for values of the gravity field.\n  * The values are computed by the convolution of the potential with the inverse @a kernel.\n  * Example: If @a kernel is the Stokes function, @a field gives the observation equations for gravity anomalies.\n  * @param time Time of observation.\n  * @param point Computational point in TRF [m].\n  * @param kernel Stellt den Typ der Beobachtung dar (z.B. Stokes-Kern fuer Schwereanomalien).\n  * @param A Must be a (sub)matrix with the dimension (1 x parameterCount()). It is filled with the partial derivatives with respect to the parameters. */\n  void field(const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const;\n\n  /** @brief Gravitational potential.\n  * Observation equation for the gravitational potential at @a point [m^2/s^2].\n  * @param time Time of observation.\n  * @param point Computational point in TRF [m].\n  * @param A Must be a (sub)matrix with the dimension (1 x parameterCount()). It is filled with the partial derivatives with respect to the parameters. */\n  void potential(const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n\n  /** @brief Radial derivative.\n  * Observation equations for the radial derivative of the potential in TRF at @a point [m/s^2].\n  * @param time Time of observation.\n  * @param point Computational point in TRF [m].\n  * @param A Must be a (sub)matrix with the dimension (1 x parameterCount()). It is filled with the partial derivatives with respect to the parameters. */\n  void radialGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n\n  /** @brief Gravity vector.\n  * Three observation equations for the gravity (x,y,z) in TRF at @a point [m/s^2].\n  * @param time Time of observation.\n  * @param point Computational point in TRF [m].\n  * @param A Must be a (sub)matrix with the dimension (3 x parameterCount()). It is filled with the partial derivatives with respect to the parameters. */\n  void gravity(const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n\n  /** @brief Gravity Gradient.\n  * Six observations equations for gravity gradients (xx,xy,xz,yy,yz,zz) in TRF at @a point [1/s].\n  * @param time Time of observation.\n  * @param point Computational point in TRF [m].\n  * @param A Must be a (sub)matrix with the dimension (6 x parameterCount()). It is filled with the partial derivatives with respect to the parameters. */\n  void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n\n  /** @brief Loading deformation.\n  * Three observation equations for loading deformation at a station (x,y,z) in TRF [m].\n  * @param time Time of observation.\n  * @param point station position in TRF [m]\n  * @param gravity local gravity at station [m/s**2]\n  * @param hn vertical load love numbers\n  * @param ln horizontal load love numbers\n  * @param A Must be a (sub)matrix with the dimension (3 x parameterCount()). It is filled with the partial derivatives with respect to the parameters. */\n  void deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const;\n\n  /** @brief Conversion of parameter Vector into SphericalHarmonics. */\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree=INFINITYDEGREE) const;\n\n  /** @brief Conversion of parameter Vector into SphericalHarmonics.\n  * Additionally the variances of the parameters can be provided. */\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree=INFINITYDEGREE) const;\n\n  /** @brief creates an derived instance of this class. */\n  static ParametrizationGravityPtr create(Config &config, const std::string &name) {return ParametrizationGravityPtr(new ParametrizationGravity(config, name));}\n};\n\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ParametrizationGravity.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var without parameters is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ParametrizationGravity */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParametrizationGravityPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Interne Klasse\nclass ParametrizationGravityBase\n{\npublic:\n  virtual ~ParametrizationGravityBase() {}\n\n  virtual Bool setInterval(const Time &/*timeStart*/, const Time &/*timeEnd*/) {return FALSE;}\n  virtual UInt parameterCount() const = 0;\n  virtual void parameterName(std::vector<ParameterName> &name) const = 0;\n  virtual void field          (const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const = 0;\n  virtual void potential      (const Time &time, const Vector3d &point, MatrixSliceRef A) const = 0;\n  virtual void radialGradient (const Time &time, const Vector3d &point, MatrixSliceRef A) const = 0;\n  virtual void gravity        (const Time &time, const Vector3d &point, MatrixSliceRef A) const = 0;\n  virtual void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const = 0;\n  virtual void deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const = 0;\n\n  virtual SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const = 0;\n  virtual SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree)  const = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityEarthquakeOscillation.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityEarthquakeOscillation.cpp\n*\n* @brief Earthquake oscillation.\n* @see ParametrizationGravity\n*\n* @author Saniya Behzadpour\n* @date 2017-05-08\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileMatrix.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationGravity/parametrizationGravityEarthquakeOscillation.h\"\n\n/***********************************************/\n\nParametrizationGravityEarthquakeOscillation::ParametrizationGravityEarthquakeOscillation(Config &config)\n{\n  try\n  {\n    FileName xName;\n\n    readConfig(config, \"inputInitialCoefficient\", xName,     Config::MUSTSET,  \"\",  \"initial values for oscillation parameters\");\n    readConfig(config, \"time0\",                   time0,     Config::MUSTSET,  \"\",  \"the time earthquake happened\");\n    readConfig(config, \"minDegree\",               minDegree, Config::MUSTSET,  \"2\", \"\");\n    readConfig(config, \"maxDegree\",               maxDegree, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"GM\",                      GM,        Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                       R,         Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",               numbering, Config::MUSTSET,  \"\",  \"numbering scheme\");\n    if(isCreateSchema(config)) return;\n\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    _parameterCount = 3*numbering->parameterCount(maxDegree, minDegree);\n\n    readFileMatrix(xName, mx);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::coefficients(const Time &time, MatrixSliceRef B, MatrixSliceRef A) const\n{\n  try\n  {\n    const Double dt = (time-time0).seconds();\n\n    Matrix cnm0(maxDegree+1,maxDegree+1);\n    Matrix snm0(maxDegree+1,maxDegree+1);\n\n    Matrix cnmW = cnm0; Matrix cnmP = cnm0;\n    Matrix snmW = snm0; Matrix snmP = snm0;\n\n    for(UInt i=0; i<mx.rows(); i++)\n    {\n      cnm0(mx(i,1), mx(i,2)) = mx(i,3);\n      snm0(mx(i,1), mx(i,2)) = mx(i,4);\n      cnmW(mx(i,1), mx(i,2)) = mx(i,5);\n      snmW(mx(i,1), mx(i,2)) = mx(i,6);\n      cnmP(mx(i,1), mx(i,2)) = mx(i,7);\n      snmP(mx(i,1), mx(i,2)) = mx(i,8);\n    }\n\n    std::vector<std::vector<Matrix>> cnm(maxDegree+1, std::vector<Matrix>(maxDegree+1));\n    std::vector<std::vector<Matrix>> snm(maxDegree+1, std::vector<Matrix>(maxDegree+1));\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        cnm[n][0] = Matrix(1, 3);\n        cnm[n][0](0,0) = 1 - cos( cnmW(n,0) * dt ) * std::exp(cnmW(n,0)*dt*cnmP(n,0));\n        cnm[n][0](0,1) = (cnm0(n,0)*dt)*sin(cnmW(n,0)*dt)*std::exp(cnmW(n,0)*dt*cnmP(n,0))-\n                         (cnm0(n,0)*dt*cnmP(n,0))*cos(cnmW(n,0)*dt)*std::exp(cnmW(n,0)*dt*cnmP(n,0));\n        cnm[n][0](0,2) = (-cnm0(n,0)*cnmW(n,0)*dt)*cos(cnmW(n,0)*dt)*std::exp(cnmW(n,0)*dt*cnmP(n,0));\n\n      }\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          cnm[n][m] = Matrix(1, 3);\n          cnm[n][m](0,0) = 1 - cos(cnmW(n,m)*dt)*std::exp(cnmW(n,m)*dt*cnmP(n,m));\n          cnm[n][m](0,1) = (cnm0(n,m)*dt)*sin(cnmW(n,m)*dt)*std::exp(cnmW(n,m)*dt*cnmP(n,m))-\n                           (cnm0(n,m)*dt*cnmP(n,m))*cos(cnmW(n,m)*dt)*std::exp(cnmW(n,m)*dt*cnmP(n,m));\n          cnm[n][m](0,2) = (-cnm0(n,m)*cnmW(n,m)*dt)*cos(cnmW(n,m)*dt)*std::exp(cnmW(n,m)*dt*cnmP(n,m));\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          snm[n][m] = Matrix(1, 3);\n          snm[n][m](0,0) = 1 - cos(snmW(n,m)*dt)*std::exp(snmW(n,m)*dt*snmP(n,m));\n          snm[n][m](0,1) = (snm0(n,m)*dt)*sin(snmW(n,m)*dt)*std::exp(snmW(n,m)*dt*snmP(n,m))-\n                           (snm0(n,m)*dt*snmP(n,m))*cos(snmW(n,m)*dt)*std::exp(snmW(n,m)*dt*snmP(n,m));\n          snm[n][m](0,2) = (-snm0(n,m)*snmW(n,m)*dt)*cos(snmW(n,m)*dt)*std::exp(snmW(n,m)*dt*snmP(n,m));\n        }\n      }\n    }\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX)\n        copy (B.column(idxC[n][0]) * cnm[n][0] , A.column(3*idxC[n][0], 3));\n\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX)\n            copy(B.column(idxC[n][m])* cnm[n][m] , A.column(3*idxC[n][m], 3));\n\n        if(idxS[n][m]!=NULLINDEX)\n            copy(B.column(idxS[n][m])* snm[n][m] , A.column(3*idxS[n][m], 3));\n      }\n     }\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<UInt> degree, order, cs;\n    numbering->numbering(maxDegree, minDegree, degree, order, cs);\n    for(UInt i=0; i<cs.size(); i++)\n    {\n      name.push_back(ParameterName(\"\", \"earthquakeParameter.\"+std::string((cs.at(i)==0) ? \"c_\" : \"s_\")+degree.at(i)%\"%i\"s+\"_\"+order.at(i)%\"%i\"s+\"_A\"));\n      name.push_back(ParameterName(\"\", \"earthquakeParameter.\"+std::string((cs.at(i)==0) ? \"c_\" : \"s_\")+degree.at(i)%\"%i\"s+\"_\"+order.at(i)%\"%i\"s+\"_W\"));\n      name.push_back(ParameterName(\"\", \"earthquakeParameter.\"+std::string((cs.at(i)==0) ? \"c_\" : \"s_\")+degree.at(i)%\"%i\"s+\"_\"+order.at(i)%\"%i\"s+\"_P\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::field(const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm);\n    Vector coeff = GM/R * kernel.inverseCoefficients(point, maxDegree);\n    Matrix B(1, parameterCount()/3);\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) B(0, idxC[n][0]) = coeff(n) * Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) B(0, idxC[n][m]) = coeff(n) * Cnm(n,m);\n        if(idxS[n][m]!=NULLINDEX) B(0, idxS[n][m]) = coeff(n) * Snm(n,m);\n      }\n    }\n    coefficients(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::potential(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm);\n    Matrix B(1, parameterCount()/3);\n\n    Double factor = GM/R;\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) B(0, idxC[n][0]) = factor * Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) B(0, idxC[n][m]) = factor * Cnm(n,m);\n        if(idxS[n][m]!=NULLINDEX) B(0, idxS[n][m]) = factor * Snm(n,m);\n      }\n    }\n    coefficients(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::radialGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm);\n    Matrix B(1, parameterCount()/3);\n\n    Double factor = -GM/R/point.r();\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) B(0, idxC[n][0]) = factor * (n+1) * Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) B(0, idxC[n][m]) = factor * (n+1) * Cnm(n,m);\n        if(idxS[n][m]!=NULLINDEX) B(0, idxS[n][m]) = factor * (n+1) * Snm(n,m);\n      }\n    }\n    coefficients(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::gravity(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree+1, Cnm, Snm);\n    Matrix B(3, parameterCount()/3);\n\n    // 0. Order\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      Double factor = sqrt((2.*n+1.)/(2.*n+3.))*GM/(2.*R*R);\n\n      Double wm0 = sqrt((n+1.)*(n+1.));\n      Double wp1 = sqrt((n+1.)*(n+2.)) / sqrt(2.0);\n\n      Double Cm0 = wm0*Cnm(n+1,0);\n      Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        B(0, idxC[n][0]) = factor*(-2*Cp1);\n        B(1, idxC[n][0]) = factor*(-2*Sp1);\n        B(2, idxC[n][0]) = factor*(-2*Cm0);\n      }\n    }\n\n    // all other orders\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      {\n        Double factor = sqrt((2.*n+1.)/(2.*n+3.))*GM/(2.*R*R);\n\n        Double wm1 = sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? sqrt(2.0) : 1.0);\n        Double wm0 = sqrt((n-m+1.)*(n+m+1.));\n        Double wp1 = sqrt((n+m+1.)*(n+m+2.));\n\n        Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n        Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n        Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          B(0, idxC[n][m]) = factor*( Cm1 - Cp1);\n          B(1, idxC[n][m]) = factor*(-Sm1 - Sp1);\n          B(2, idxC[n][m]) = factor*(-2*Cm0);\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          B(0, idxS[n][m]) = factor*(Sm1 - Sp1);\n          B(1, idxS[n][m]) = factor*(Cm1 + Cp1);\n          B(2, idxS[n][m]) = factor*(-2*Sm0);\n        }\n      }\n    }\n    coefficients(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree+2, Cnm, Snm);\n    Matrix B(6, parameterCount()/3);\n\n    // 0. Order\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      Double factor = sqrt((2.*n+1.)/(2.*n+5.))*GM/(4.*R*R*R);\n\n      Double wm0 = sqrt((n+1.)*(n+2.)*(n+1.)*(n+2.));\n      Double wp1 = sqrt((n+1.)*(n+1.)*(n+2.)*(n+3.)) / sqrt(2.0);\n      Double wp2 = sqrt((n+1.)*(n+2.)*(n+3.)*(n+4.)) / sqrt(2.0);\n\n      Double Cm0 = wm0*Cnm(n+2,0);\n      Double Cp1 = wp1*Cnm(n+2,1);  Double Sp1 = wp1*Snm(n+2,1);\n      Double Cp2 = wp2*Cnm(n+2,2);  Double Sp2 = wp2*Snm(n+2,2);\n\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        B(0, idxC[n][0]) = factor * (-2*Cm0 + 2*Cp2);\n        B(1, idxC[n][0]) = factor * ( 2*Sp2);\n        B(2, idxC[n][0]) = factor * ( 4*Cp1);\n        B(3, idxC[n][0]) = factor * (-2*Cm0 - 2*Cp2);\n        B(4, idxC[n][0]) = factor * ( 4*Sp1);\n        B(5, idxC[n][0]) = factor * ( 4*Cm0);\n      }\n    }\n\n    // 1. order\n    UInt m=1;\n    for(UInt n=std::max(minDegree, static_cast<UInt>(1)); n<=maxDegree; n++)\n    {\n      Double factor = sqrt((2.*n+1.)/(2.*n+5.))*GM/(4.*R*R*R);\n\n      Double wm1 = sqrt((n-m+1.)*(n-m+2.)*(n-m+3.)*(n+m+1.)) * sqrt(2.0);\n      Double wm0 = sqrt((n-m+1.)*(n-m+2.)*(n+m+1.)*(n+m+2.));\n      Double wp1 = sqrt((n-m+1.)*(n+m+1.)*(n+m+2.)*(n+m+3.));\n      Double wp2 = sqrt((n+m+1.)*(n+m+2.)*(n+m+3.)*(n+m+4.));\n\n      Double Cm1 = wm1*Cnm(n+2,m-1);  Double Sm1 = wm1*Snm(n+2,m-1);\n      Double Cm0 = wm0*Cnm(n+2,m  );  Double Sm0 = wm0*Snm(n+2,m  );\n      Double Cp1 = wp1*Cnm(n+2,m+1);  Double Sp1 = wp1*Snm(n+2,m+1);\n      Double Cp2 = wp2*Cnm(n+2,m+2);  Double Sp2 = wp2*Snm(n+2,m+2);\n\n      if(idxC[n][m]!=NULLINDEX)\n      {\n        B(0, idxC[n][m]) = factor * (- 3*Cm0 + Cp2);\n        B(1, idxC[n][m]) = factor * (-   Sm0 + Sp2);\n        B(2, idxC[n][m]) = factor * (-2*Cm1 + 2*Cp1);\n        B(3, idxC[n][m]) = factor * (-   Cm0 - Cp2);\n        B(4, idxC[n][m]) = factor * (2*Sp1);\n        B(5, idxC[n][m]) = factor * (4*Cm0);\n      }\n\n      if(idxS[n][m]!=NULLINDEX)\n      {\n        B(0, idxS[n][m]) = factor * (- Sm0 + Sp2);\n        B(1, idxS[n][m]) = factor * (- Cm0 - Cp2);\n        B(2, idxS[n][m]) = factor * (-2*Sm1 + 2*Sp1);\n        B(3, idxS[n][m]) = factor * (- 3*Sm0 - Sp2);\n        B(4, idxS[n][m]) = factor * (-2*Cm1 - 2*Cp1);\n        B(5, idxS[n][m]) = factor * (4*Sm0);\n      }\n    } // end 1. order\n\n    // all other orders\n    for(UInt m=2; m<=maxDegree; m++)\n    {\n      for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      {\n        Double factor = sqrt((2.*n+1.)/(2.*n+5.))*GM/(4.*R*R*R);\n\n        Double wm2 = sqrt((n-m+1.)*(n-m+2.)*(n-m+3.)*(n-m+4.)) * ((m==2) ? sqrt(2.0) : 1.0);\n        Double wm1 = sqrt((n-m+1.)*(n-m+2.)*(n-m+3.)*(n+m+1.));\n        Double wm0 = sqrt((n-m+1.)*(n-m+2.)*(n+m+1.)*(n+m+2.));\n        Double wp1 = sqrt((n-m+1.)*(n+m+1.)*(n+m+2.)*(n+m+3.));\n        Double wp2 = sqrt((n+m+1.)*(n+m+2.)*(n+m+3.)*(n+m+4.));\n\n        Double Cm2 = wm2*Cnm(n+2,m-2);  Double Sm2 = wm2*Snm(n+2,m-2);\n        Double Cm1 = wm1*Cnm(n+2,m-1);  Double Sm1 = wm1*Snm(n+2,m-1);\n        Double Cm0 = wm0*Cnm(n+2,m  );  Double Sm0 = wm0*Snm(n+2,m  );\n        Double Cp1 = wp1*Cnm(n+2,m+1);  Double Sp1 = wp1*Snm(n+2,m+1);\n        Double Cp2 = wp2*Cnm(n+2,m+2);  Double Sp2 = wp2*Snm(n+2,m+2);\n\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          B(0, idxC[n][m]) = factor * ( Cm2 - 2*Cm0 + Cp2);\n          B(1, idxC[n][m]) = factor * (-Sm2         + Sp2);\n          B(2, idxC[n][m]) = factor * (-2*Cm1 + 2*Cp1);\n          B(3, idxC[n][m]) = factor * (-Cm2 - 2*Cm0 - Cp2);\n          B(4, idxC[n][m]) = factor * ( 2*Sm1 + 2*Sp1);\n          B(5, idxC[n][m]) = factor * (4*Cm0);\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          B(0, idxS[n][m]) = factor * ( Sm2 - 2*Sm0 + Sp2);\n          B(1, idxS[n][m]) = factor * ( Cm2         - Cp2);\n          B(2, idxS[n][m]) = factor * (-2*Sm1 + 2*Sp1);\n          B(3, idxS[n][m]) = factor * (-Sm2 - 2*Sm0 - Sp2);\n          B(4, idxS[n][m]) = factor * (-2*Cm1 - 2*Cp1);\n          B(5, idxS[n][m]) = factor * (4*Sm0);\n        }\n      }\n    }\n\n    coefficients(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityEarthquakeOscillation::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const\n{\n  try\n  {\n    Vector3d up = normalize(point);\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree+1, Cnm, Snm);\n    Matrix B(3, parameterCount()/3);\n\n    // 0. order\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      Double wm0 = sqrt((n+1.)*(n+1.));\n      Double wp1 = sqrt((n+1.)*(n+2.)) / sqrt(2.0);\n      Double Cm0 = wm0*Cnm(n+1,0);\n      Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        Double   Vn     = GM/R * Cnm(n,0);\n        Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(-2*Cp1, -2*Sp1, -2*Cm0);\n\n\n        Vector3d disp = (hn(n)/gravity*Vn) * up // vertical\n                      + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n        B(0, idxC[n][0]) = disp.x();\n        B(1, idxC[n][0]) = disp.y();\n        B(2, idxC[n][0]) = disp.z();\n      }\n    }\n\n    // other orders\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      {\n        Double wm1 = sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? sqrt(2.0) : 1.0);\n        Double wm0 = sqrt((n-m+1.)*(n+m+1.));\n        Double wp1 = sqrt((n+m+1.)*(n+m+2.));\n        Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n        Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n        Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          Double   Vn     = GM/R * Cnm(n,m);\n          Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Cm1-Cp1, -Sm1-Sp1, -2*Cm0);\n\n          Vector3d disp = (hn(n)/gravity*Vn) * up // vertical\n                        + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          B(0, idxC[n][m]) = disp.x();\n          B(1, idxC[n][m]) = disp.y();\n          B(2, idxC[n][m]) = disp.z();\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          Double   Vn     = GM/R * Snm(n,m);\n          Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Sm1-Sp1, Cm1+Cp1, -2*Sm0);\n\n          Vector3d disp = (hn(n)/gravity*Vn) * up // vertical\n                        + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          B(0, idxS[n][m]) = disp.x();\n          B(1, idxS[n][m]) = disp.y();\n          B(2, idxS[n][m]) = disp.z();\n        }\n      }\n    }\n    coefficients(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityEarthquakeOscillation::sphericalHarmonics(const Time &time, const Vector &x, UInt _maxDegree) const\n{\n  try\n  {\n    Matrix cnm0(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm0(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix cnmW =cnm0; Matrix cnmP = cnm0;\n    Matrix snmW =snm0; Matrix snmP = snm0;\n    const Double dt = (time-time0).seconds();\n    if (dt >0)\n    {\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        cnm0(n,0)  = x(3*idxC[n][0]+0);\n        cnmW(n,0)  = x(3*idxC[n][0]+1);\n        cnmP(n,0)  = x(3*idxC[n][0]+2);\n      }\n\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          cnm0(n,m)  = x(3*idxC[n][m]+0);\n          cnmW(n,m)  = x(3*idxC[n][m]+1);\n          cnmP(n,m)  = x(3*idxC[n][m]+2);\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          snm0(n,m)  = x(3*idxS[n][m]+0);\n          snmW(n,m)  = x(3*idxS[n][m]+1);\n          snmP(n,m)  = x(3*idxS[n][m]+2);\n        }\n      }\n    }\n    Matrix cnm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX)\n        cnm(n,0)  = cnm0(n,0)*(1 - cos(cnmW(n,0)*dt)*std::exp(cnmW(n,0)*dt*cnmP(n,0)));\n\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX)\n          cnm(n,m)  = cnm0(n,m)*(1 - cos(cnmW(n,m)*dt)*std::exp(cnmW(n,m)*dt*cnmP(n,m)));\n\n        if(idxS[n][m]!=NULLINDEX)\n          snm(n,m)  = snm0(n,m)*(1 - cos(snmW(n,m)*dt)*std::exp(snmW(n,m)*dt*snmP(n,m)));\n      }\n    }\n\n    if(_maxDegree==INFINITYDEGREE)\n      _maxDegree = this->maxDegree;\n    return SphericalHarmonics(GM,R, cnm,snm).get(maxDegree);\n    }\n    else\n      return SphericalHarmonics().get();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityEarthquakeOscillation::sphericalHarmonics(const Time &/*time*/, const Vector &x, const Vector &sigma2x, UInt _maxDegree) const\n{\n  try\n  {\n    Matrix cnm      (this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm      (this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2cnm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(UInt n=minDegree; n<=this->maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) cnm(n,0)       = x(idxC[n][0]);\n      if(idxC[n][0]!=NULLINDEX) sigma2cnm(n,0) = sigma2x(idxC[n][0]);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][0]!=NULLINDEX) cnm(n,m)       = x(idxC[n][m]);\n        if(idxS[n][m]!=NULLINDEX) snm(n,m)       = x(idxS[n][m]);\n        if(idxC[n][0]!=NULLINDEX) sigma2cnm(n,m) = sigma2x(idxC[n][m]);\n        if(idxS[n][m]!=NULLINDEX) sigma2snm(n,m) = sigma2x(idxS[n][m]);\n      }\n    }\n\n\n    if(_maxDegree==INFINITYDEGREE)\n      _maxDegree = this->maxDegree;\n    return SphericalHarmonics(GM,R, cnm,snm, sigma2cnm, sigma2snm).get(_maxDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityEarthquakeOscillation.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityEarthquakeOscillation.h\n*\n* @brief Earthquake oscillation.\n* @see ParametrizationGravity\n*\n* @author Saniya Behzadpour\n* @date 2017-05-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGRAVITYEARTHQUAKE__\n#define __GROOPS_PARAMETRIZATIONGRAVITYEARTHQUAKE__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGravity\nstatic const char *docstringParametrizationGravityEarthquakeOscillation = R\"(\n\\subsection{EarthquakeOscillation}\nThis class is used to estimate the earthquake oscillation function parameters,\ni.e. $C_{nlm}$, $\\omega_{nlm}$, and $P_{nlm}$.\nThe results describes the variation in the gravitational potential field caused by large earthquakes.\n\\begin{equation}\nC_{lm}(\\M t) = \\sum_{n=0}^NC_{nlm}(1-\\cos(\\omega_{nlm}d\\M t)\\exp(P_{nlm}\\omega_{nlm}d\\M t)),\n\\end{equation}\nwith $\\omega_{nlm}=\\frac{2\\pi}{T_{nlm}}$ and $P_{nlm}=\\frac{-1}{2Q_{nlm}}$ . In this equation, $Q_{nlm}$ is the attenuation factor,\n$n$ is the overtone factor, $m$ is degree, $l$ is order, and $t$ is time after earthquake in second.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:earthquakeParameter.c_<degree>_<order>_A:*:*|,\n\\item \\verb|*:earthquakeParameter.s_<degree>_<order>_A:*:*|,\n\\item \\verb|*:earthquakeParameter.c_<degree>_<order>_W:*:*|,\n\\item \\verb|*:earthquakeParameter.s_<degree>_<order>_W:*:*|,\n\\item \\verb|*:earthquakeParameter.c_<degree>_<order>_P:*:*|,\n\\item \\verb|*:earthquakeParameter.s_<degree>_<order>_P:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Earthquake oscillation.\n* @ingroup parametrizationGravityGroup\n* @see ParametrizationGravity */\nclass ParametrizationGravityEarthquakeOscillation : public ParametrizationGravityBase\n{\n  SphericalHarmonicsNumberingPtr numbering;\n  Matrix mx;\n\n  std::vector<std::vector<UInt>> idxC, idxS;\n  Time     time0;\n  UInt     _parameterCount;\n  UInt     maxDegree, minDegree;\n  Double   GM,R;\n\npublic:\n  ParametrizationGravityEarthquakeOscillation(Config &config);\n\n  UInt parameterCount() const {return _parameterCount;}\n  void coefficients(const Time &time,  MatrixSliceRef B,  MatrixSliceRef A) const;\n  void parameterName(std::vector<ParameterName> &name) const;\n  void field          (const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const;\n  void potential      (const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n  void radialGradient (const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n  void gravity        (const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n  void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const;\n  void deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityLinearTransformation.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityLinearTransformation.cpp\n*\n* @brief Gravity field parametrization based on the linear transformation of another parametrizationGravity.\n* @see ParametrizationGravity\n*\n* @author Andreas Kvas\n* @date 2020-06-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"parametrizationGravityLinearTransformation.h\"\n\n/***********************************************/\n\nParametrizationGravityLinearTransformation::ParametrizationGravityLinearTransformation(Config &config)\n{\n  try\n  {\n    FileName fileNameTransformationMatrix;\n\n    readConfig(config, \"parametrizationGravitySource\",  source, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileTransformationMatrix\", fileNameTransformationMatrix, Config::MUSTSET, \"\", \"transformation matrix from target to source parametrization (rows of this matrix must coincide with the parameter count of the source parametrization)\");\n    if(isCreateSchema(config)) return;\n\n    readFileMatrix(fileNameTransformationMatrix, transformationMatrix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=0; i<parameterCount(); i++)\n      name.push_back(ParameterName(\"\", \"transformedParameter.\"+i%\"%i\"s+\".\"+parameterCount()%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::field(const Time &time, const Vector3d &point, const Kernel &kernel2, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(1,source->parameterCount());\n    source->field(time, point, kernel2, B);\n    matMult(1.0, B, transformationMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::potential(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(1,source->parameterCount());\n    source->potential(time, point, B);\n    matMult(1.0, B, transformationMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::radialGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(1,source->parameterCount());\n    source->radialGradient(time, point, B);\n    matMult(1.0, B, transformationMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::gravity(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(3,source->parameterCount());\n    source->gravity(time, point, B);\n    matMult(1.0, B, transformationMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(6,source->parameterCount());\n    source->gravityGradient(time, point, B);\n    matMult(1.0, B, transformationMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityLinearTransformation::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(3,source->parameterCount());\n    source->deformation(time, point, gravity, hn, ln, A);\n    matMult(1.0, B, transformationMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityLinearTransformation::sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const\n{\n  try\n  {\n    return source->sphericalHarmonics(time, transformationMatrix*x, maxDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityLinearTransformation::sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const\n{\n  try\n  {\n    // variance propagation\n    Vector sigma2y(transformationMatrix.rows());\n    for(UInt i=0; i<transformationMatrix.rows(); i++)\n      for(UInt k=0; k<transformationMatrix.columns(); k++)\n        sigma2y(i) = std::pow(transformationMatrix(i, k), 2) * sigma2x(k);\n\n    return source->sphericalHarmonics(time, transformationMatrix*x, sigma2y, maxDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityLinearTransformation.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityLinearTransformation.h\n*\n* @brief Gravity field parametrization based on the linear transformation of another parametrizationGravity.\n* @see ParametrizationGravity\n*\n* @author Andreas Kvas\n* @date 2020-06-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGRAVITYLINEARTRANSFORMATION__\n#define __GROOPS_PARAMETRIZATIONGRAVITYLINEARTRANSFORMATION__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGravity\nstatic const char *docstringParametrizationGravityLinearTransformation = R\"(\n\\subsection{LinearTransformation}\nParametrization of the gravity field on the basis of a linear transformation of a source parametrization.\nThe linear transformation changes the original solution space represented by\n\\configClass{pararametrizationGravitySource}{parametrizationGravityType} from\n\\begin{equation}\n  \\mathbf{l} = \\mathbf{A}\\mathbf{x} + \\mathbf{e}\n\\end{equation}\nto\n\\begin{equation}\n  \\mathbf{l} = \\mathbf{A}\\mathbf{F}\\mathbf{y} + \\mathbf{e}\n\\end{equation}\nthrough the linear transformation $\\mathbf{x}=\\mathbf{F}\\mathbf{y}$.\nIt follows that the rows of the matrix $\\mathbf{F}$ in \\file{inputfileTransformationMatrix}{matrix} coincides with\nthe number of parameters in \\configClass{pararametrizationGravitySource}{parametrizationGravityType}.\nThe new parameter count is given by the number of columns in $\\mathbf{F}$ and may be smaller, equal or larger\nthan the original parameter count.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:transformedParameter.<index>.<total count>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravity field parametrization based on the linear transformation of another parametrizationGravity.\n* @ingroup parametrizationGravityGroup\n* @see ParametrizationGravity */\nclass ParametrizationGravityLinearTransformation : public ParametrizationGravityBase\n{\n  ParametrizationGravityPtr  source;\n  Matrix                     transformationMatrix;\n\npublic:\n  ParametrizationGravityLinearTransformation(Config &config);\n\n  UInt parameterCount() const override {return transformationMatrix.columns();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void field          (const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const override;\n  void potential      (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void radialGradient (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravity        (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityRadialBasis.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityRadialBasis.cpp\n*\n* @brief Radial basis functions.\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-03-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationGravity/parametrizationGravityRadialBasis.h\"\n\n/***********************************************/\n\nParametrizationGravityRadialBasis::ParametrizationGravityRadialBasis(Config &config)\n{\n  try\n  {\n    GridPtr grid;\n\n    readConfig(config, \"kernel\",kernel, Config::MUSTSET, \"\", \"shape of the radial basis function\");\n    readConfig(config, \"grid\",  grid,   Config::MUSTSET, \"\", \"nodal point distribution\");\n    if(isCreateSchema(config)) return;\n\n    sourcePoint = grid->points();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::parameterName(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<sourcePoint.size(); i++)\n    name.push_back(ParameterName(\"\", \"radialBasis.\"+i%\"%i\"s+\".\"+sourcePoint.size()%\"%i\"s));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::field(const Time &/*time*/, const Vector3d &point, const Kernel &kernel2, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<sourcePoint.size(); i++)\n    A(0,i) = kernel2.inverseKernel(point, sourcePoint.at(i), *kernel);\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::potential(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<sourcePoint.size(); i++)\n    A(0,i) = kernel->kernel(point, sourcePoint.at(i));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::radialGradient(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<sourcePoint.size(); i++)\n    A(0,i) = kernel->radialDerivative(point, sourcePoint.at(i));\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::gravity(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<sourcePoint.size(); i++)\n  {\n    Vector3d field = kernel->gradient(point, sourcePoint.at(i));\n    A(0,i) = field.x();\n    A(1,i) = field.y();\n    A(2,i) = field.z();\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::gravityGradient(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  for(UInt i=0; i<sourcePoint.size(); i++)\n  {\n    Tensor3d field = kernel->gradientGradient(point, sourcePoint.at(i));\n    A(0,i) = field.xx();\n    A(1,i) = field.xy();\n    A(2,i) = field.xz();\n    A(3,i) = field.yy();\n    A(4,i) = field.yz();\n    A(5,i) = field.zz();\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityRadialBasis::deformation(const Time &/*time*/, const Vector3d &/*point*/, Double /*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/, MatrixSliceRef /*A*/) const\n{\n  try\n  {\n    throw(Exception(\"not implemented\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityRadialBasis::sphericalHarmonics(const Time &/*time*/, const Vector &x, UInt maxDegree) const\n{\n  try\n  {\n    // Determine max. degree of the kernel\n    if(maxDegree == INFINITYDEGREE)\n      maxDegree = kernel->maxDegree();\n    if(maxDegree == INFINITYDEGREE)\n      throw(Exception(\"In ParametrizationGravityRadialBasis::sphericalHarmonics: INFINITYDEGREE requested\"));\n\n    Matrix cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(UInt i=0; i<sourcePoint.size(); i++)\n    {\n      Vector coeff = kernel->coefficients(sourcePoint.at(i), maxDegree);\n\n      Double Ri = sourcePoint.at(i).r();\n      Matrix Cnm, Snm;\n      SphericalHarmonics::CnmSnm((1/Ri) * sourcePoint.at(i), maxDegree, Cnm, Snm);\n\n      Double factor = DEFAULT_R/DEFAULT_GM * Ri/DEFAULT_R;\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        for(UInt m=0; m<=n; m++)\n        {\n          cnm(n,m) += factor * coeff(n) * Cnm(n,m) * x(i);\n          snm(n,m) += factor * coeff(n) * Snm(n,m) * x(i);\n        }\n        factor *= Ri/DEFAULT_R;\n      }\n    }\n\n    return SphericalHarmonics(DEFAULT_GM, DEFAULT_R, cnm, snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityRadialBasis::sphericalHarmonics(const Time &/*time*/, const Vector &x, const Vector &sigma2x, UInt maxDegree) const\n{\n  try\n  {\n    // Determine max. degree of the kernel\n    if(maxDegree == INFINITYDEGREE)\n      maxDegree = kernel->maxDegree();\n    if(maxDegree == INFINITYDEGREE)\n      throw(Exception(\"In ParametrizationGravityRadialBasis::sphericalHarmonics: INFINITYDEGREE requested\"));\n\n    Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    // mit Fehlerfortplanzung\n    for(UInt i=0; i<sourcePoint.size(); i++)\n    {\n      Vector coeff = kernel->coefficients(sourcePoint.at(i), maxDegree);\n\n      Double Ri = sourcePoint.at(i).r();\n      Matrix Cnm, Snm;\n      SphericalHarmonics::CnmSnm((1/Ri) * sourcePoint.at(i), maxDegree, Cnm, Snm);\n\n      Double factor = DEFAULT_R/DEFAULT_GM * Ri/DEFAULT_R;\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        for(UInt m=0; m<=n; m++)\n        {\n          cnm(n,m)       += factor * coeff(n) * Cnm(n,m) * x(i);\n          snm(n,m)       += factor * coeff(n) * Snm(n,m) * x(i);\n          sigma2cnm(n,m) += pow(factor * coeff(n) * Cnm(n,m), 2) * sigma2x(i);\n          sigma2snm(n,m) += pow(factor * coeff(n) * Snm(n,m), 2) * sigma2x(i);\n        }\n        factor *= Ri/DEFAULT_R;\n      }\n    }\n\n    return SphericalHarmonics(DEFAULT_GM, DEFAULT_R, cnm, snm, sigma2cnm, sigma2snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityRadialBasis.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityRadialBasis.h\n*\n* @brief Radial basis functions.\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-03-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGRAVITYRADIALBASIS__\n#define __GROOPS_PARAMETRIZATIONGRAVITYRADIALBASIS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGravity\nstatic const char *docstringParametrizationGravityRadialBasis = R\"(\n\\subsection{RadialBasis}\\label{parametrizationGravityType:radialBasis}\nThe potential~$V$ is represented by a sum of space localizing basis functions\n\\begin{equation}\n  V(\\M x) = \\sum_i a_i \\Phi(\\M x, \\M x_i)\n\\end{equation}\nwhere $a_i$ the coefficients which has to be estimated and $\\Phi$ are the basis\nfunctions given by isotropic radial \\configClass{kernel}{kernelType} functions\n\\begin{equation}\n  \\Phi(\\cos\\psi,r,R) = \\sum_n \\left(\\frac{R}{r}\\right)^{n+1} k_n\\sqrt{2n+1}\\bar{P}_n(\\cos\\psi).\n\\end{equation}\nThe basis functions are located on a grid~$\\M x_i$ given by \\configClass{grid}{gridType}.\nThis class can also be used to estimate point masses if \\configClass{kernel}{kernelType} is set to density.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:radialBasis.<index>.<total count>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Radial basis functions.\n* @ingroup parametrizationGravityGroup\n* @see ParametrizationGravity */\nclass ParametrizationGravityRadialBasis : public ParametrizationGravityBase\n{\n  KernelPtr kernel;                  // basis functions\n  std::vector<Vector3d> sourcePoint; // center of basis functions\n\npublic:\n  ParametrizationGravityRadialBasis(Config &config);\n\n  UInt parameterCount() const override {return sourcePoint.size();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void field          (const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const override;\n  void potential      (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void radialGradient (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravity        (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravitySphericalHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravitySphericalHarmonics.cpp\n*\n* @brief Spherical Harmonics.\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-03-10\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationGravity/parametrizationGravitySphericalHarmonics.h\"\n\n/***********************************************/\n\nParametrizationGravitySphericalHarmonics::ParametrizationGravitySphericalHarmonics(Config &config)\n{\n  try\n  {\n    readConfig(config, \"minDegree\", minDegree, Config::MUSTSET, \"2\", \"\");\n    readConfig(config, \"maxDegree\", maxDegree, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"GM\",        GM,        Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",         R,         Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\", numbering, Config::MUSTSET, \"\",  \"numbering scheme\");\n    if(isCreateSchema(config)) return;\n\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    _parameterCount = numbering->parameterCount(maxDegree, minDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<UInt> degree, order, cs;\n    numbering->numbering(maxDegree, minDegree, degree, order, cs);\n    for(UInt i=0; i<cs.size(); i++)\n      name.push_back(ParameterName(\"\", \"sphericalHarmonics.\"+std::string((cs.at(i)==0) ? \"c_\" : \"s_\")+degree.at(i)%\"%i\"s+\"_\"+order.at(i)%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::field(const Time &/*time*/, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm);\n    Vector coeff = GM/R * kernel.inverseCoefficients(point, maxDegree);\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) A(0, idxC[n][0]) = coeff(n) * Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) A(0, idxC[n][m]) = coeff(n) * Cnm(n,m);\n        if(idxS[n][m]!=NULLINDEX) A(0, idxS[n][m]) = coeff(n) * Snm(n,m);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::potential(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm);\n\n    Double factor = GM/R;\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) A(0, idxC[n][0]) = factor * Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) A(0, idxC[n][m]) = factor * Cnm(n,m);\n        if(idxS[n][m]!=NULLINDEX) A(0, idxS[n][m]) = factor * Snm(n,m);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::radialGradient(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree, Cnm, Snm);\n\n    Double factor = -GM/R/point.r();\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) A(0, idxC[n][0]) = factor * (n+1) * Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) A(0, idxC[n][m]) = factor * (n+1) * Cnm(n,m);\n        if(idxS[n][m]!=NULLINDEX) A(0, idxS[n][m]) = factor * (n+1) * Snm(n,m);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::gravity(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree+1, Cnm, Snm);\n\n    // 0. Order\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      Double factor = sqrt((2.*n+1.)/(2.*n+3.))*GM/(2.*R*R);\n\n      Double wm0 = sqrt((n+1.)*(n+1.));\n      Double wp1 = sqrt((n+1.)*(n+2.)) / sqrt(2.0);\n\n      Double Cm0 = wm0*Cnm(n+1,0);\n      Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        A(0, idxC[n][0]) = factor*(-2*Cp1);\n        A(1, idxC[n][0]) = factor*(-2*Sp1);\n        A(2, idxC[n][0]) = factor*(-2*Cm0);\n      }\n    }\n\n    // all other orders\n    for(UInt m=1; m<=maxDegree; m++)\n      for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      {\n        Double factor = sqrt((2.*n+1.)/(2.*n+3.))*GM/(2.*R*R);\n\n        Double wm1 = sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? sqrt(2.0) : 1.0);\n        Double wm0 = sqrt((n-m+1.)*(n+m+1.));\n        Double wp1 = sqrt((n+m+1.)*(n+m+2.));\n\n        Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n        Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n        Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          A(0, idxC[n][m]) = factor*( Cm1 - Cp1);\n          A(1, idxC[n][m]) = factor*(-Sm1 - Sp1);\n          A(2, idxC[n][m]) = factor*(-2*Cm0);\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          A(0, idxS[n][m]) = factor*(Sm1 - Sp1);\n          A(1, idxS[n][m]) = factor*(Cm1 + Cp1);\n          A(2, idxS[n][m]) = factor*(-2*Sm0);\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::gravityGradient(const Time &/*time*/, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree+2, Cnm, Snm);\n\n    // 0. Order\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      Double factor = sqrt((2.*n+1.)/(2.*n+5.))*GM/(4.*R*R*R);\n\n      Double wm0 = sqrt((n+1.)*(n+2.)*(n+1.)*(n+2.));\n      Double wp1 = sqrt((n+1.)*(n+1.)*(n+2.)*(n+3.)) / sqrt(2.0);\n      Double wp2 = sqrt((n+1.)*(n+2.)*(n+3.)*(n+4.)) / sqrt(2.0);\n\n      Double Cm0 = wm0*Cnm(n+2,0);\n      Double Cp1 = wp1*Cnm(n+2,1);  Double Sp1 = wp1*Snm(n+2,1);\n      Double Cp2 = wp2*Cnm(n+2,2);  Double Sp2 = wp2*Snm(n+2,2);\n\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        A(0, idxC[n][0]) = factor * (-2*Cm0 + 2*Cp2);\n        A(1, idxC[n][0]) = factor * ( 2*Sp2);\n        A(2, idxC[n][0]) = factor * ( 4*Cp1);\n        A(3, idxC[n][0]) = factor * (-2*Cm0 - 2*Cp2);\n        A(4, idxC[n][0]) = factor * ( 4*Sp1);\n        A(5, idxC[n][0]) = factor * ( 4*Cm0);\n      }\n    }\n\n    // 1. order\n    UInt m=1;\n    for(UInt n=std::max(minDegree, static_cast<UInt>(1)); n<=maxDegree; n++)\n    {\n      Double factor = sqrt((2.*n+1.)/(2.*n+5.))*GM/(4.*R*R*R);\n\n      Double wm1 = sqrt((n-m+1.)*(n-m+2.)*(n-m+3.)*(n+m+1.)) * sqrt(2.0);\n      Double wm0 = sqrt((n-m+1.)*(n-m+2.)*(n+m+1.)*(n+m+2.));\n      Double wp1 = sqrt((n-m+1.)*(n+m+1.)*(n+m+2.)*(n+m+3.));\n      Double wp2 = sqrt((n+m+1.)*(n+m+2.)*(n+m+3.)*(n+m+4.));\n\n      Double Cm1 = wm1*Cnm(n+2,m-1);  Double Sm1 = wm1*Snm(n+2,m-1);\n      Double Cm0 = wm0*Cnm(n+2,m  );  Double Sm0 = wm0*Snm(n+2,m  );\n      Double Cp1 = wp1*Cnm(n+2,m+1);  Double Sp1 = wp1*Snm(n+2,m+1);\n      Double Cp2 = wp2*Cnm(n+2,m+2);  Double Sp2 = wp2*Snm(n+2,m+2);\n\n      if(idxC[n][m]!=NULLINDEX)\n      {\n        A(0, idxC[n][m]) = factor * (- 3*Cm0 + Cp2);\n        A(1, idxC[n][m]) = factor * (-   Sm0 + Sp2);\n        A(2, idxC[n][m]) = factor * (-2*Cm1 + 2*Cp1);\n        A(3, idxC[n][m]) = factor * (-   Cm0 - Cp2);\n        A(4, idxC[n][m]) = factor * (2*Sp1);\n        A(5, idxC[n][m]) = factor * (4*Cm0);\n      }\n\n      if(idxS[n][m]!=NULLINDEX)\n      {\n        A(0, idxS[n][m]) = factor * (- Sm0 + Sp2);\n        A(1, idxS[n][m]) = factor * (- Cm0 - Cp2);\n        A(2, idxS[n][m]) = factor * (-2*Sm1 + 2*Sp1);\n        A(3, idxS[n][m]) = factor * (- 3*Sm0 - Sp2);\n        A(4, idxS[n][m]) = factor * (-2*Cm1 - 2*Cp1);\n        A(5, idxS[n][m]) = factor * (4*Sm0);\n      }\n    } // end 1. order\n\n    // all other orders\n    for(UInt m=2; m<=maxDegree; m++)\n      for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      {\n        Double factor = sqrt((2.*n+1.)/(2.*n+5.))*GM/(4.*R*R*R);\n\n        Double wm2 = sqrt((n-m+1.)*(n-m+2.)*(n-m+3.)*(n-m+4.)) * ((m==2) ? sqrt(2.0) : 1.0);\n        Double wm1 = sqrt((n-m+1.)*(n-m+2.)*(n-m+3.)*(n+m+1.));\n        Double wm0 = sqrt((n-m+1.)*(n-m+2.)*(n+m+1.)*(n+m+2.));\n        Double wp1 = sqrt((n-m+1.)*(n+m+1.)*(n+m+2.)*(n+m+3.));\n        Double wp2 = sqrt((n+m+1.)*(n+m+2.)*(n+m+3.)*(n+m+4.));\n\n        Double Cm2 = wm2*Cnm(n+2,m-2);  Double Sm2 = wm2*Snm(n+2,m-2);\n        Double Cm1 = wm1*Cnm(n+2,m-1);  Double Sm1 = wm1*Snm(n+2,m-1);\n        Double Cm0 = wm0*Cnm(n+2,m  );  Double Sm0 = wm0*Snm(n+2,m  );\n        Double Cp1 = wp1*Cnm(n+2,m+1);  Double Sp1 = wp1*Snm(n+2,m+1);\n        Double Cp2 = wp2*Cnm(n+2,m+2);  Double Sp2 = wp2*Snm(n+2,m+2);\n\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          A(0, idxC[n][m]) = factor * ( Cm2 - 2*Cm0 + Cp2);\n          A(1, idxC[n][m]) = factor * (-Sm2         + Sp2);\n          A(2, idxC[n][m]) = factor * (-2*Cm1 + 2*Cp1);\n          A(3, idxC[n][m]) = factor * (-Cm2 - 2*Cm0 - Cp2);\n          A(4, idxC[n][m]) = factor * ( 2*Sm1 + 2*Sp1);\n          A(5, idxC[n][m]) = factor * (4*Cm0);\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          A(0, idxS[n][m]) = factor * ( Sm2 - 2*Sm0 + Sp2);\n          A(1, idxS[n][m]) = factor * ( Cm2         - Cp2);\n          A(2, idxS[n][m]) = factor * (-2*Sm1 + 2*Sp1);\n          A(3, idxS[n][m]) = factor * (-Sm2 - 2*Sm0 - Sp2);\n          A(4, idxS[n][m]) = factor * (-2*Cm1 - 2*Cp1);\n          A(5, idxS[n][m]) = factor * (4*Sm0);\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravitySphericalHarmonics::deformation(const Time &/*time*/, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const\n{\n  try\n  {\n    Vector3d up = normalize(point);\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(1/R * point, maxDegree+1, Cnm, Snm);\n\n    // 0. order\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      Double wm0 = sqrt((n+1.)*(n+1.));\n      Double wp1 = sqrt((n+1.)*(n+2.)) / sqrt(2.0);\n      Double Cm0 = wm0*Cnm(n+1,0);\n      Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n      if(idxC[n][0]!=NULLINDEX)\n      {\n        Double   Vn     = GM/R * Cnm(n,0);\n        Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(-2*Cp1, -2*Sp1, -2*Cm0);\n\n\n        Vector3d disp = (hn(n)/gravity*Vn) * up // vertical\n                      + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n        A(0, idxC[n][0]) = disp.x();\n        A(1, idxC[n][0]) = disp.y();\n        A(2, idxC[n][0]) = disp.z();\n      }\n    }\n\n    // other orders\n    for(UInt m=1; m<=maxDegree; m++)\n      for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      {\n        Double wm1 = sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? sqrt(2.0) : 1.0);\n        Double wm0 = sqrt((n-m+1.)*(n+m+1.));\n        Double wp1 = sqrt((n+m+1.)*(n+m+2.));\n        Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n        Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n        Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n        if(idxC[n][m]!=NULLINDEX)\n        {\n          Double   Vn     = GM/R * Cnm(n,m);\n          Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Cm1-Cp1, -Sm1-Sp1, -2*Cm0);\n\n          Vector3d disp = (hn(n)/gravity*Vn) * up // vertical\n                        + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          A(0, idxC[n][m]) = disp.x();\n          A(1, idxC[n][m]) = disp.y();\n          A(2, idxC[n][m]) = disp.z();\n        }\n\n        if(idxS[n][m]!=NULLINDEX)\n        {\n          Double   Vn     = GM/R * Snm(n,m);\n          Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Sm1-Sp1, Cm1+Cp1, -2*Sm0);\n\n          Vector3d disp = (hn(n)/gravity*Vn) * up // vertical\n                        + (ln(n)/gravity) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          A(0, idxS[n][m]) = disp.x();\n          A(1, idxS[n][m]) = disp.y();\n          A(2, idxS[n][m]) = disp.z();\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravitySphericalHarmonics::sphericalHarmonics(const Time &/*time*/, const Vector &x, UInt _maxDegree) const\n{\n  try\n  {\n    Matrix cnm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) cnm(n,0) = x(idxC[n][0]);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) cnm(n,m) = x(idxC[n][m]);\n        if(idxS[n][m]!=NULLINDEX) snm(n,m) = x(idxS[n][m]);\n      }\n    }\n\n    if(_maxDegree==INFINITYDEGREE)\n      _maxDegree = this->maxDegree;\n    return SphericalHarmonics(GM,R, cnm,snm).get(maxDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravitySphericalHarmonics::sphericalHarmonics(const Time &/*time*/, const Vector &x, const Vector &sigma2x, UInt _maxDegree) const\n{\n  try\n  {\n    Matrix cnm      (this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm      (this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2cnm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(this->maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(UInt n=minDegree; n<=this->maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) cnm(n,0)       = x(idxC[n][0]);\n      if(idxC[n][0]!=NULLINDEX) sigma2cnm(n,0) = sigma2x(idxC[n][0]);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][0]!=NULLINDEX) cnm(n,m)       = x(idxC[n][m]);\n        if(idxS[n][m]!=NULLINDEX) snm(n,m)       = x(idxS[n][m]);\n        if(idxC[n][0]!=NULLINDEX) sigma2cnm(n,m) = sigma2x(idxC[n][m]);\n        if(idxS[n][m]!=NULLINDEX) sigma2snm(n,m) = sigma2x(idxS[n][m]);\n      }\n    }\n\n    if(_maxDegree==INFINITYDEGREE)\n      _maxDegree = this->maxDegree;\n    return SphericalHarmonics(GM,R, cnm,snm, sigma2cnm, sigma2snm).get(_maxDegree);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravitySphericalHarmonics.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravitySphericalHarmonics.h\n*\n* @brief Spherical Harmonics.\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-03-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGRAVITYHARMONICS__\n#define __GROOPS_PARAMETRIZATIONGRAVITYHARMONICS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGravity\nstatic const char *docstringParametrizationGravitySphericalHarmonics = R\"(\n\\subsection{SphericalHarmonics}\\label{parametrizationGravityType:sphericalHarmonics}\nThe potential~$V$ is parametrized by a expansion of (fully normalized) spherical harmonics\n\\begin{equation}\nV(\\lambda,\\vartheta,r) = \\frac{GM}{R}\\sum_{n=0}^\\infty \\sum_{m=0}^n \\left(\\frac{R}{r}\\right)^{n+1}\n  \\left(c_{nm} C_{nm}(\\lambda,\\vartheta) + s_{nm} S_{nm}(\\lambda,\\vartheta)\\right).\n\\end{equation}\nYou can set the range of degree~$n$ with \\config{minDegree} and \\config{maxDegree}.\nThe sorting sequence of the potential coefficients in the parameter vector can be defined by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}.\n\nThe total count of parameters is $(n_{max}+1)^2-n_{min}^2$ and\nthe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|*:sphericalHarmonics.c_<degree>_<order>:*:*|,\n\\item \\verb|*:sphericalHarmonics.s_<degree>_<order>:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Spherical Harmonics.\n* @ingroup parametrizationGravityGroup\n* @see ParametrizationGravity */\nclass ParametrizationGravitySphericalHarmonics : public ParametrizationGravityBase\n{\n  SphericalHarmonicsNumberingPtr numbering;\n  std::vector<std::vector<UInt>> idxC, idxS;\n  UInt     _parameterCount;\n  UInt     maxDegree, minDegree;\n  Double   GM, R;\n\npublic:\n  ParametrizationGravitySphericalHarmonics(Config &config);\n\n  UInt parameterCount() const override {return _parameterCount;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void field          (const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const override;\n  void potential      (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void radialGradient (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravity        (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityTemporal.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityTemporal.cpp\n*\n* @brief Time variable gravity field.\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"parametrizationGravityTemporal.h\"\n\n/***********************************************/\n\nParametrizationGravityTemporal::ParametrizationGravityTemporal(Config &config)\n{\n  try\n  {\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",  date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"temporal\",       \"parametrizationTemporal\", date2time(2020, 6, 3));\n\n    readConfig(config, \"parametrizationGravity\",  spatial,  Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"parametrizationTemporal\", temporal, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationGravityTemporal::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    return temporal->setInterval(timeStart, timeEnd);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName;\n    spatial->parameterName(baseName);\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::field(const Time &time, const Vector3d &point, const Kernel &kernel2, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(1,spatial->parameterCount());\n    spatial->field(time, point, kernel2, B);\n    temporal->designMatrix(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::potential(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(1,spatial->parameterCount());\n    spatial->potential(time, point, B);\n    temporal->designMatrix(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::radialGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(1,spatial->parameterCount());\n    spatial->radialGradient(time, point, B);\n    temporal->designMatrix(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::gravity(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(3,spatial->parameterCount());\n    spatial->gravity(time, point, B);\n    temporal->designMatrix(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(6,spatial->parameterCount());\n    spatial->gravityGradient(time, point, B);\n    temporal->designMatrix(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationGravityTemporal::deformation(const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const\n{\n  try\n  {\n    Matrix B(3,spatial->parameterCount());\n    spatial->deformation(time, point, gravity, hn, ln, A);\n    temporal->designMatrix(time, B, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityTemporal::sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const\n{\n  try\n  {\n    if(time==Time())\n      return ::SphericalHarmonics();\n\n    std::vector<UInt>   index;\n    std::vector<Double> factor;\n    temporal->factors(time, index, factor);\n\n    SphericalHarmonics harm;\n    UInt count = spatial->parameterCount();\n    for(UInt i=0; i<index.size(); i++)\n      harm  += factor.at(i) * spatial->sphericalHarmonics(time, x.row(index.at(i)*count,count), maxDegree);\n\n    return harm;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics ParametrizationGravityTemporal::sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const\n{\n  try\n  {\n    if(time==Time())\n      return ::SphericalHarmonics();\n\n    std::vector<UInt>   index;\n    std::vector<Double> factor;\n    temporal->factors(time, index, factor);\n\n    SphericalHarmonics harm;\n    UInt count = spatial->parameterCount();\n    for(UInt i=0; i<index.size(); i++)\n      harm  += factor.at(i) * spatial->sphericalHarmonics(time, x.row(index.at(i)*count,count), sigma2x.row(index.at(i)*count,count), maxDegree);\n\n    return harm;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationGravity/parametrizationGravityTemporal.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationGravityTemporal.h\n*\n* @brief Time variable gravity field.\n* @see ParametrizationGravity\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONGRAVITYTEMPORAL__\n#define __GROOPS_PARAMETRIZATIONGRAVITYTEMPORAL__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationGravity\nstatic const char *docstringParametrizationGravityTemporal = R\"(\n\\subsection{Temporal}\nThe time variable potential is given by\n\\begin{equation}\n  V(\\M x,t) = \\sum_i V_i(\\M x)\\Psi_i(t),\n\\end{equation}\nwehre $V_i(\\M x)$ is the spatial parametrization of the gravity field\nand can be choosen with \\configClass{parametrizationGravity}{parametrizationGravityType}.\nThe parametrization in time domain $\\Psi_i(t)$ is selected by\n\\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nThe total parameter count is the parameter count of \\configClass{parametrizationTemporal}{parametrizationTemporalType}\ntimes the parameter count of \\configClass{parametrizationGravity}{parametrizationGravityType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time variable gravity field.\n* @ingroup parametrizationGravityGroup\n* @see ParametrizationGravity */\nclass ParametrizationGravityTemporal : public ParametrizationGravityBase\n{\n  ParametrizationGravityPtr  spatial;\n  ParametrizationTemporalPtr temporal;\n\npublic:\n  ParametrizationGravityTemporal(Config &config);\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount() const override {return spatial->parameterCount() * temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const override;\n  void field          (const Time &time, const Vector3d &point, const Kernel &kernel, MatrixSliceRef A) const override;\n  void potential      (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void radialGradient (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravity        (const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void gravityGradient(const Time &time, const Vector3d &point, MatrixSliceRef A) const override;\n  void deformation    (const Time &time, const Vector3d &point, Double gravity, const Vector &hn, const Vector &ln, MatrixSliceRef A) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, UInt maxDegree) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Vector &x, const Vector &sigma2x, UInt maxDegree) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTracking.cpp\n*\n* @brief SST parameter.\n*\n* @author Beate Klinger\n* @date 2015-04-27\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_ParametrizationSatelliteTracking\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/configRegister.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingAntennaCenter.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingBias.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingScale.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingTimeBias.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingScaleModel.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingSpecialEffect.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParametrizationSatelliteTracking, \"parametrizationSatelliteTrackingType\",\n                      ParametrizationSatelliteTrackingAntennaCenter,\n                      ParametrizationSatelliteTrackingBias,\n                      ParametrizationSatelliteTrackingScale,\n                      ParametrizationSatelliteTrackingTimeBias,\n                      ParametrizationSatelliteTrackingScaleModel,\n                      ParametrizationSatelliteTrackingSpecialEffect)\n\nGROOPS_RENAMED_CLASS(parameterSatelliteTrackingType, parametrizationSatelliteTrackingType, date2time(2020, 6, 3))\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParametrizationSatelliteTracking, \"parametrizationSatelliteTrackingType\")\n\n/***********************************************/\n\nParametrizationSatelliteTracking::ParametrizationSatelliteTracking(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"SST parameters\"))\n    {\n      if(readConfigChoiceElement(config, \"antennaCenter\",            type, \"antenna center\"))\n        parameter.push_back(new ParametrizationSatelliteTrackingAntennaCenter(config));\n      if(readConfigChoiceElement(config, \"bias\",                     type, \"SST bias\"))\n        parameter.push_back(new ParametrizationSatelliteTrackingBias(config));\n      if(readConfigChoiceElement(config, \"scale\",                    type, \"SST scale\"))\n        parameter.push_back(new ParametrizationSatelliteTrackingScale(config));\n      if(readConfigChoiceElement(config, \"timeBias\",                 type, \"SST time bias\"))\n        parameter.push_back(new ParametrizationSatelliteTrackingTimeBias(config));\n      if(readConfigChoiceElement(config, \"scaleModel\",               type, \"scale factors for model from file\"))\n        parameter.push_back(new ParametrizationSatelliteTrackingScaleModel(config));\n      if(readConfigChoiceElement(config, \"specialEffect\",            type, \"special effects from file\"))\n        parameter.push_back(new ParametrizationSatelliteTrackingSpecialEffect(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n\n    computeIndicies();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParametrizationSatelliteTracking::~ParametrizationSatelliteTracking()\n{\n  for(UInt i=0; i<parameter.size(); i++)\n    delete parameter.at(i);\n}\n\n/***********************************************/\n\nvoid ParametrizationSatelliteTracking::computeIndicies()\n{\n  try\n  {\n    parameterCountA = 0;\n    parameterCountB = 0;\n    indexA.resize(parameter.size());\n    indexB.resize(parameter.size());\n    for(UInt i=0; i<parameter.size(); i++)\n    {\n      indexA.at(i) = parameterCountA;\n      indexB.at(i) = parameterCountB;\n      if(parameter.at(i)->isPerArc())\n        parameterCountB += parameter.at(i)->parameterCount();\n      else\n        parameterCountA += parameter.at(i)->parameterCount();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationSatelliteTracking::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    for(UInt i=0; i<parameter.size(); i++)\n      if(!parameter.at(i)->isPerArc())\n        change = parameter.at(i)->setInterval(timeStart, timeEnd) || change;\n    if(change)\n      computeIndicies();\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationSatelliteTracking::setIntervalArc(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    for(UInt i=0; i<parameter.size(); i++)\n      if(parameter.at(i)->isPerArc())\n        change = parameter.at(i)->setInterval(timeStart, timeEnd) || change;\n    if(change)\n      computeIndicies();\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationSatelliteTracking::parameterName(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<parameter.size(); i++)\n    if(!parameter.at(i)->isPerArc())\n      parameter.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nvoid ParametrizationSatelliteTracking::parameterNameArc(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<parameter.size(); i++)\n    if(parameter.at(i)->isPerArc())\n      parameter.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nvoid ParametrizationSatelliteTracking::compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n                                         const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n                                         const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A, MatrixSliceRef B)\n{\n  try\n  {\n    for(UInt i=0; i<parameter.size(); i++)\n      parameter.at(i)->compute(sstType, time, sst0, position1, position2, velocity1, velocity2, rotSat1, rotSat2,\n                               (parameter.at(i)->isPerArc() ? B.slice(0, indexB.at(i), time.size(), parameter.at(i)->parameterCount()) :\n                                                              A.slice(0, indexA.at(i), time.size(), parameter.at(i)->parameterCount())));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTracking.h\n*\n* @brief SST parameter.\n*\n* @author Beate Klinger\n* @date 2015-04-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONSATELLITETRACKING__\n#define __GROOPS_PARAMETRIZATIONSATELLITETRACKING__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTracking = R\"(\n\\section{ParametrizationSatelliteTracking}\\label{parametrizationSatelliteTrackingType}\nThis class defines parameters of Satellite-to-Satellite tracking observations.\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup parametrizationSatelliteTrackingGroup ParametrizationSatelliteTracking\n* @brief SST parameters.\n* @ingroup classesGroup\n* The interface is given by @ref ParametrizationSatelliteTracking. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParametrizationSatelliteTracking;\nclass ParametrizationSatelliteTrackingBase;\ntypedef std::shared_ptr<ParametrizationSatelliteTracking> ParametrizationSatelliteTrackingPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief SST parameters.\n* Parametrization of the (time variable) gravity field.\n* Creates the observation equations of SST parameters (design matrix).\n* An Instance of this class can be created by @ref readConfig. */\nclass ParametrizationSatelliteTracking\n{\n  UInt parameterCountA, parameterCountB;\n  std::vector<UInt> indexA, indexB;\n  std::vector<ParametrizationSatelliteTrackingBase*> parameter;\n\n  void computeIndicies();\n\npublic:\n  /// Constructor.\n  ParametrizationSatelliteTracking(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~ParametrizationSatelliteTracking();\n\n  /** @brief Estimate parameter in the given interval only.\n  * Change result of @a parameterCount(), @a parameterName().\n  * @return TRUE if parameters are changed */\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n\n  /** @brief Initialize arc.\n  * Must be called at the beginning of every new arc.\n  * @return TRUE if parameters are changed */\n  Bool setIntervalArc(const Time &timeStart, const Time &timeEnd);\n\n  /** @brief Number of unknown parameters.\n  * This is the column count of the design matrix @a A. */\n  UInt parameterCount() const {return parameterCountA;}\n\n  /** @brief Number of unknown arc related parameters.\n  * This is the column count of the design matrix @a B. */\n  UInt parameterCountArc() const {return parameterCountB;}\n\n  /** @brief Name of parameters.\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Name of arc related parameters.\n  * The names are appended to @a name. */\n  void parameterNameArc(std::vector<ParameterName> &name) const;\n\n  /** @brief Partial Derivations of force function.\n  * @param sstType   SST observation type (0 = range, 1 = range rate, 2 = range acceleration)\n  * @param time      GPS time\n  * @param sst0      reference SST observations (Taylor point)\n  * @param position1 (3*epochCount) in CRF [m]\n  * @param position2 (3*epochCount) in CRF [m]\n  * @param velocity1 (3*epochCount) in CRF [m/s]\n  * @param velocity2 (3*epochCount) in CRF [m/s]\n  * @param rotSat1   Sat1 -> CRF\n  * @param rotSat2   Sat2 -> CRF\n  * @param[out] A    (epochCount x parameterCount) matrix with partial derivatives\n  * @param[out] B    (epochCount x parameterCountArc) matrix with partial derivatives */\n  void compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n              const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n              const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2,\n              MatrixSliceRef A, MatrixSliceRef B);\n\n  /** @brief creates an derived instance of this class. */\n  static ParametrizationSatelliteTrackingPtr create(Config &config, const std::string &name) {return ParametrizationSatelliteTrackingPtr(new ParametrizationSatelliteTracking(config, name));}\n};\n\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ParametrizationSatelliteTracking.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a parametrizationSatelliteTracking without parameters is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] parametrizationSatelliteTracking Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ParametrizationSatelliteTracking */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParametrizationSatelliteTrackingPtr &parametrizationSatelliteTracking, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass ParametrizationSatelliteTrackingBase\n{\npublic:\nvirtual ~ParametrizationSatelliteTrackingBase() {}\nvirtual Bool isPerArc() const = 0;\nvirtual Bool setInterval(const Time &timeStart, const Time &timeEnd) = 0;\nvirtual UInt parameterCount()    const = 0;\nvirtual void parameterName(std::vector<ParameterName> &name) const = 0;\nvirtual void compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n                     const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n                     const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A) = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingAntennaCenter.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTrackingAntennaCenter.h\n*\n* @brief KBR antenna center parameter.\n*\n* @author Beate Klinger\n* @date 2015-06-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONSATELLITETRACKINGANTENNACENTER__\n#define __GROOPS_PARAMETRIZATIONSATELLITETRACKINGANTENNACENTER__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTrackingAntennaCenter = R\"(\n\\subsection{AntennaCenter}\\label{parametrizationSatelliteTrackingType:antennaCenter}\nEstimate the KBR antenna phase centre (APC) coordinates in $[m]$ for each spacecraft in satellite reference frame (SRF)\nas constant per axis. The observation equations are computed by taking the derivative\nof the antenna offset correction equation w.r.t. the KBR APC coordinates.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|satellite1.satellite2:sstAntennaCenter1.x:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter1.y:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter1.z:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter2.x:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter2.y:*:*|,\n\\item \\verb|satellite1.satellite2:sstAntennaCenter2.z:*:*|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"parametrizationSatelliteTracking.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SST bias.\n* @ingroup parametrizationSatelliteTrackingGroup\n* @see ParametrizationSatelliteTracking */\nclass ParametrizationSatelliteTrackingAntennaCenter : public ParametrizationSatelliteTrackingBase\n{\n  Bool estimate1x, estimate1y, estimate1z;\n  Bool estimate2x, estimate2y, estimate2z;\n  UInt degree;\n\npublic:\n  ParametrizationSatelliteTrackingAntennaCenter(Config &config);\n\n  Bool isPerArc() const {return FALSE;}\n  Bool setInterval(const Time &/*timeStart*/, const Time &/*timeEnd*/) {return FALSE;}\n  UInt parameterCount() const {return estimate1x+estimate1y+estimate1z+estimate2x+estimate2y+estimate2z;}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void compute(UInt sstType, const std::vector<Time> &times, const Vector &sst0,\n               const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n               const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationSatelliteTrackingAntennaCenter::ParametrizationSatelliteTrackingAntennaCenter(Config &config)\n{\n  try\n  {\n    readConfig(config, \"estimate1X\",          estimate1x,  Config::DEFAULT,  \"1\", \"along (satellite 1)\");\n    readConfig(config, \"estimate1Y\",          estimate1y,  Config::DEFAULT,  \"1\", \"cross (satellite 1)\");\n    readConfig(config, \"estimate1Z\",          estimate1z,  Config::DEFAULT,  \"1\", \"nadir (satellite 1)\");\n    readConfig(config, \"estimate2X\",          estimate2x,  Config::DEFAULT,  \"1\", \"along (satellite 2)\");\n    readConfig(config, \"estimate2Y\",          estimate2y,  Config::DEFAULT,  \"1\", \"cross (satellite 2)\");\n    readConfig(config, \"estimate2Z\",          estimate2z,  Config::DEFAULT,  \"1\", \"nadir (satellite 2)\");\n    readConfig(config, \"interpolationDegree\", degree,      Config::DEFAULT,  \"2\", \"differentiation by polynomial approximation of degree n\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingAntennaCenter::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    if(estimate1x) name.push_back(ParameterName(\"satellite1.satellite2\", \"sstAntennaCenter1.x\"));\n    if(estimate1y) name.push_back(ParameterName(\"satellite1.satellite2\", \"sstAntennaCenter1.y\"));\n    if(estimate1z) name.push_back(ParameterName(\"satellite1.satellite2\", \"sstAntennaCenter1.z\"));\n    if(estimate2x) name.push_back(ParameterName(\"satellite1.satellite2\", \"sstAntennaCenter2.x\"));\n    if(estimate2y) name.push_back(ParameterName(\"satellite1.satellite2\", \"sstAntennaCenter2.y\"));\n    if(estimate2z) name.push_back(ParameterName(\"satellite1.satellite2\", \"sstAntennaCenter2.z\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingAntennaCenter::compute(UInt sstType, const std::vector<Time> &times, const Vector &/*sst0*/,\n                                                             const Vector &position1, const Vector &position2, const Vector &/*velocity1*/, const Vector &/*velocity2*/,\n                                                             const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A)\n{\n  try\n  {\n    for(UInt i=0; i<times.size(); i++)\n    {\n      Matrix e = (position2.row(3*i,3)-position1.row(3*i,3)).trans();\n      e *= 1./norm(e);\n      Matrix B(1,6);\n      matMult(-1, e, rotSat1.at(i).matrix(), B.column(0, 3));\n      matMult( 1, e, rotSat2.at(i).matrix(), B.column(3, 3));\n      UInt idx = 0;\n      if(estimate1x) A(i, idx++) = B(0, 0);\n      if(estimate1y) A(i, idx++) = B(0, 1);\n      if(estimate1z) A(i, idx++) = B(0, 2);\n      if(estimate2x) A(i, idx++) = B(0, 3);\n      if(estimate2y) A(i, idx++) = B(0, 4);\n      if(estimate2z) A(i, idx++) = B(0, 5);\n    }\n\n    if(sstType == 0) // range\n      return;\n    Polynomial polynomial(times, degree);\n    if(sstType == 1) // range rate\n      copy(polynomial.derivative(times, A), A);\n    else if(sstType == 2) // range acceleration\n      copy(polynomial.derivative2nd(times, A), A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingBias.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTrackingBias.h\n*\n* @brief SST bias.\n*\n* @author Beate Klinger\n* @date 2015-05-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONSATELLITETRACKINGBIAS__\n#define __GROOPS_PARAMETRIZATIONSATELLITETRACKINGBIAS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTrackingBias = R\"(\n\\subsection{Bias}\\label{parametrizationSatelliteTrackingType:bias}\nEstimate bias for SST observations in $[m]$ or $[m/s$]. The temporal variation is defined by\n\\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:sstBias:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationSatelliteTracking.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SST bias.\n* @ingroup parametrizationSatelliteTrackingGroup\n* @see ParametrizationSatelliteTracking */\nclass ParametrizationSatelliteTrackingBias : public ParametrizationSatelliteTrackingBase\n{\n  ParametrizationTemporalPtr temporal;\n  Bool                       perArc;\n\npublic:\n  ParametrizationSatelliteTrackingBias(Config &config);\n\n  Bool isPerArc() const {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n  UInt parameterCount() const {return temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n               const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n               const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationSatelliteTrackingBias::ParametrizationSatelliteTrackingBias(Config &config)\n{\n  try\n  {\n    readConfig(config, \"temporal\", temporal, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",   perArc,   Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationSatelliteTrackingBias::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    return temporal->setInterval(timeStart, timeEnd, perArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingBias::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName(1);\n    baseName.at(0) = ParameterName(\"satellite1.satellite2\", \"sstBias\");\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingBias::compute(UInt /*sstType*/, const std::vector<Time> &time, const Vector &/*sst0*/,\n                                                    const Vector &/*position1*/, const Vector &/*position2*/, const Vector &/*velocity1*/, const Vector &/*velocity2*/,\n                                                    const std::vector<Rotary3d> &/*rotSat1*/, const std::vector<Rotary3d> &/*rotSat2*/, MatrixSliceRef A)\n{\n  try\n  {\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      temporal->factors(time.at(idEpoch), index, factor);\n      for(UInt i=0; i<index.size(); i++)\n        A(idEpoch, index.at(i)) = factor.at(i);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingScale.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTrackingScale.h\n*\n* @brief SST scale.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-08-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONSATELLITETRACKINGSCALE__\n#define __GROOPS_PARAMETRIZATIONSATELLITETRACKINGSCALE__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTrackingScale = R\"(\n\\subsection{Scale}\\label{parametrizationSatelliteTrackingType:scale}\nEstimate scale factor for SST observations with respect to reference SST data\n\\configFile{inputfileSatelliteTracking}{instrument}.\nThe temporal variation is defined by \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:sstScale:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationSatelliteTracking.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SST scale.\n* @ingroup parametrizationSatelliteTrackingGroup\n* @see ParametrizationSatelliteTracking */\nclass ParametrizationSatelliteTrackingScale : public ParametrizationSatelliteTrackingBase\n{\n  SatelliteTrackingArc       sst;\n  ParametrizationTemporalPtr temporal;\n  Bool                       perArc;\n  UInt                       idx;\n\npublic:\n  ParametrizationSatelliteTrackingScale(Config &config);\n\n  Bool isPerArc() const {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n  UInt parameterCount() const {return temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n               const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n               const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A);\n};\n\n/***********************************************/\n/***** Inlines *********************************/\n/***********************************************/\n\ninline ParametrizationSatelliteTrackingScale::ParametrizationSatelliteTrackingScale(Config &config)\n{\n  try\n  {\n    FileName fileNameSst;\n\n    readConfig(config, \"inputfileSatelliteTracking\", fileNameSst, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"temporal\",                   temporal,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",                     perArc,      Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    sst = InstrumentFile::read(fileNameSst);\n    idx = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationSatelliteTrackingScale::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    return temporal->setInterval(timeStart, timeEnd, perArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingScale::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName(1);\n    baseName.at(0) = ParameterName(\"satellite1.satellite2\", \"sstScale\");\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingScale::compute(UInt sstType, const std::vector<Time> &time, const Vector &/*sst0*/,\n                                                     const Vector &/*position1*/, const Vector &/*position2*/, const Vector &/*velocity1*/, const Vector &/*velocity2*/,\n                                                     const std::vector<Rotary3d> &/*rotSat1*/, const std::vector<Rotary3d> &/*rotSat2*/, MatrixSliceRef A)\n{\n  try\n  {\n    if((time.at(0) < sst.at(0).time) || (time.back() > sst.at(sst.size()-1).time))\n      throw(Exception(\"time not given in satellite tracking file: \"+time.at(0).dateTimeStr()));\n\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      // find index\n      if((idx >= sst.size()) || (time.at(idEpoch) < sst.at(idx).time))\n        idx = 0;\n      while(time.at(idEpoch) > sst.at(idx).time)\n        idx++;\n      if(time.at(idEpoch) != sst.at(idx).time)\n        throw(Exception(\"time not given in sst file: \"+time.at(idEpoch).dateTimeStr()));\n      Double scale = 0;\n           if(sstType == 0) scale = sst.at(idx).range;\n      else if(sstType == 1) scale = sst.at(idx).rangeRate;\n      else if(sstType == 2) scale = sst.at(idx).rangeAcceleration;\n\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      temporal->factors(time.at(idEpoch), index, factor);\n      for(UInt i=0; i<index.size(); i++)\n        A(idEpoch, index.at(i)) = scale * factor.at(i);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingScaleModel.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTrackingScaleModel.h\n*\n* @brief Estimate scale factors for model from file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-06-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ParametrizationSatelliteTrackingScaleModel__\n#define __GROOPS_ParametrizationSatelliteTrackingScaleModel__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTrackingScaleModel = R\"(\n\\subsection{ScaleModel}\\label{parametrizationSatelliteTrackingType:scaleModel}\nEstimate scale factors for deterministic signal models from satellite tracking instrument file \\configFile{inputfileSatelliteTracking}{instrument}, see \\program{EnsembleAveragingScaleModel}.\nAmplitude variation of model waveforms is defined by \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:scaleModel:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationSatelliteTracking.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate scale factors for model from file.\n* @ingroup parametrizationSatelliteTrackingGroup\n* @see ParametrizationSatelliteTracking */\nclass ParametrizationSatelliteTrackingScaleModel : public ParametrizationSatelliteTrackingBase\n{\n  SatelliteTrackingArc       sst;\n  ParametrizationTemporalPtr temporal;\n  Bool                       perArc;\n  UInt                       idx;\n\npublic:\n  ParametrizationSatelliteTrackingScaleModel(Config &config);\n\n  Bool isPerArc() const {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n  UInt parameterCount() const {return temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n               const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n               const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A);\n};\n\n/***********************************************/\n\ninline ParametrizationSatelliteTrackingScaleModel::ParametrizationSatelliteTrackingScaleModel(Config &config)\n{\n  try\n  {\n    FileName fileName;\n\n    readConfig(config, \"inputfileSatelliteTracking\", fileName, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"temporal\",                   temporal, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",                     perArc,   Config::DEFAULT,  \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    sst = InstrumentFile::read(fileName);\n    idx = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationSatelliteTrackingScaleModel::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    return temporal->setInterval(timeStart, timeEnd, perArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingScaleModel::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName(1);\n    baseName.at(0) = ParameterName(\"satellite1.satellite2\", \"scaleModel\");\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingScaleModel::compute(UInt sstType, const std::vector<Time> &time, const Vector &/*sst0*/,\n                                                          const Vector &/*position1*/, const Vector &/*position2*/, const Vector &/*velocity1*/, const Vector &/*velocity2*/,\n                                                          const std::vector<Rotary3d> &/*rotSat1*/, const std::vector<Rotary3d> &/*rotSat2*/, MatrixSliceRef A)\n{\n  try\n  {\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      if((time.at(idEpoch) < sst.at(0).time) || (time.at(idEpoch) > sst.at(sst.size()-1).time))\n        throw(Exception(\"time not given in sst file: \"+time.at(idEpoch).dateTimeStr()));\n\n      // find index (interpolations interval)\n      if((idx >= sst.size()) || (time.at(idEpoch) < sst.at(idx).time))\n        idx = 0;\n      while(time.at(idEpoch) > sst.at(idx).time)\n        idx++;\n\n      Double value = 0;\n      switch(sstType)\n      {\n        case 0: value = sst.at(idx).range;             break;\n        case 1: value = sst.at(idx).rangeRate;         break;\n        case 2: value = sst.at(idx).rangeAcceleration; break;\n      }\n\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      temporal->factors(time.at(idEpoch), index, factor);\n      for(UInt i=0; i<index.size(); i++)\n        A(idEpoch, index.at(i)) = value * factor.at(i);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingSpecialEffect.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTrackingSpecialEffect.h\n*\n* @brief Model GRACE special effects as time variable polynomials.\n*\n* @author Torsten Mayer-Guerr\n* @author Saniya Behzadpour\n* @date 2018-06-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONSATELLITETRACKINGSPECIALEFFECT__\n#define __GROOPS_PARAMETRIZATIONSATELLITETRACKINGSPECIALEFFECT__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTrackingSpecialEffect = R\"(\n\\subsection{SpecialEffect}\\label{parametrizationSatelliteTrackingType:specialEffect}\nEstimate deterministic signals in the GRACE K-Band measurements caused by Sun intrusions\ninto the star camera baffles of GRACE-A and eclipse transits of the satellites.\nThese events can be time-indexed beforehand using satellite position and orientation,\nsee \\program{GraceSstSpecialEvents}. The shape of this short-period waveform is nearly\nconstant within one month and can be approximated by a polynomial.\nThe amplitude variation of the waveform can also be taken into account\nby \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:<type>.legendrePolynomial.n<degree>:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationSatelliteTracking.h\"\n#include \"files/fileInstrument.h\"\n#include \"base/legendrePolynomial.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Model GRACE special effects as time variable polynomials.\n* @ingroup parametrizationSatelliteTrackingGroup\n* @see ParametrizationSatelliteTracking */\nclass ParametrizationSatelliteTrackingSpecialEffect : public ParametrizationSatelliteTrackingBase\n{\n  Bool                       use;\n  MiscValueArc               event;\n  ParametrizationTemporalPtr temporal;\n  UInt                       type;\n  UInt                       degree;\n  Double                     marginBefore, marginAfter;\n  UInt                       idx;\n\npublic:\n  ParametrizationSatelliteTrackingSpecialEffect(Config &config);\n\n  Bool isPerArc() const {return FALSE;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n  UInt parameterCount() const {return use * (degree+1) * temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void compute(UInt sstType, const std::vector<Time> &time, const Vector &sst0,\n               const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n               const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A);\n};\n\n/***********************************************/\n\ninline ParametrizationSatelliteTrackingSpecialEffect::ParametrizationSatelliteTrackingSpecialEffect(Config &config)\n{\n  try\n  {\n    FileName    fileName;\n    UInt        minCount;\n    std::string choice;\n\n    readConfig(config, \"inputfileEvents\", fileName, Config::MUSTSET, \"\", \"instrument with GRACE events\");\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"eclipse1\",       choice, \"\")) type = 1;\n      if(readConfigChoiceElement(config, \"eclipse2\",       choice, \"\")) type = 2;\n      if(readConfigChoiceElement(config, \"starCameraBox1\", choice, \"\")) type = 3;\n      if(readConfigChoiceElement(config, \"starCameraBox2\", choice, \"\")) type = 4;\n      if(readConfigChoiceElement(config, \"starCameraBox3\", choice, \"\")) type = 5;\n      if(readConfigChoiceElement(config, \"starCameraBox4\", choice, \"\")) type = 6;\n      if(readConfigChoiceElement(config, \"starCameraBox5\", choice, \"\")) type = 7;\n      if(readConfigChoiceElement(config, \"starCameraBox6\", choice, \"\")) type = 8;\n      endChoice(config);\n    }\n    readConfig(config, \"marginLeft\",        marginBefore, Config::MUSTSET, \"20\", \"margin size (on both sides) [seconds]\");\n    readConfig(config, \"marginRight\",       marginAfter,  Config::MUSTSET, \"20\", \"margin size (on both sides) [seconds]\");\n    readConfig(config, \"minNumberOfEvents\", minCount,     Config::DEFAULT, \"1\",  \"min. number of events to setup parameters\");\n    readConfig(config, \"polynomialDegree\",  degree,       Config::MUSTSET, \"10\", \"polynomial degree\");\n    readConfig(config, \"temporal\",          temporal,     Config::MUSTSET, \"\",   \"\");\n    if(isCreateSchema(config)) return;\n\n    event = InstrumentFile::read(fileName);\n\n    UInt count = 0;\n    for(UInt i=0; i<event.size(); i++)\n      if(event.at(i).value == type)\n        count++;\n    use = (count >= minCount);\n\n    idx = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationSatelliteTrackingSpecialEffect::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    return temporal->setInterval(timeStart, timeEnd, FALSE/*perArc*/);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingSpecialEffect::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    if(!use)\n      return;\n\n    std::string effectName;\n    switch(type)\n    {\n      case 1: effectName = \"eclipse1\";       break;\n      case 2: effectName = \"eclipse2\";       break;\n      case 3: effectName = \"starCameraBox1\"; break;\n      case 4: effectName = \"starCameraBox2\"; break;\n      case 5: effectName = \"starCameraBox3\"; break;\n      case 6: effectName = \"starCameraBox4\"; break;\n      case 7: effectName = \"starCameraBox5\"; break;\n      case 8: effectName = \"starCameraBox6\"; break;\n    };\n\n    std::vector<ParameterName> baseName;\n    for(UInt n=0; n<=degree; n++)\n      baseName.push_back(ParameterName(\"satellite1.satellite2\", effectName+\".legendrePolynomial.n\"+n%\"%i\"s));\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingSpecialEffect::compute(UInt /*sstType*/, const std::vector<Time> &time, const Vector &/*sst0*/,\n                                                          const Vector &/*position1*/, const Vector &/*position2*/, const Vector &/*velocity1*/, const Vector &/*velocity2*/,\n                                                          const std::vector<Rotary3d> &/*rotSat1*/, const std::vector<Rotary3d> &/*rotSat2*/, MatrixSliceRef A)\n{\n  try\n  {\n    if(!use)\n      return;\n\n    UInt idx = 0;\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      // find event\n      while((idx < event.size()) && ((event.at(idx).value != type) || (event.at(idx).time+seconds2time(marginAfter) < time.at(idEpoch))))\n        idx++;\n      if(idx >= event.size())\n        break;\n      if(time.at(idEpoch) < event.at(idx).time-seconds2time(marginBefore))\n        continue;\n\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      temporal->factors(event.at(idx).time, index, factor);\n\n      const Double t  = 2*(time.at(idEpoch)-event.at(idx).time).seconds()/(marginBefore+marginAfter); // t = [-1,1]\n      const Vector Pn = LegendrePolynomial::compute(t, degree);\n      for(UInt i=0; i<index.size(); i++)\n        axpy(factor.at(i), Pn.trans(), A.slice(idEpoch, (degree+1)*index.at(i), 1, degree+1));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationSatelliteTracking/parametrizationSatelliteTrackingTimeBias.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationSatelliteTrackingTimeBias.h\n*\n* @brief SST time bias (temporal changing).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONSATELLITETRACKINGTIMEBIAS__\n#define __GROOPS_PARAMETRIZATIONSATELLITETRACKINGTIMEBIAS__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationSatelliteTracking\nstatic const char *docstringParametrizationSatelliteTrackingTimeBias = R\"(\n\\subsection{TimeBias}\\label{parametrizationSatelliteTrackingType:timeBias}\nEstimate time shift in seconds in SST observations, with defined temporal variation\nby \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nThe design matrix is computed by taking the derivative of the ranging data w.r.t. time.\n\nThe \\file{parameter names}{parameterName} are \\verb|satellite1.satellite2:sstTimeBias:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationSatelliteTracking.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SST time bias.\n* @ingroup parametrizationSatelliteTrackingGroup\n* @see ParametrizationSatelliteTracking */\nclass ParametrizationSatelliteTrackingTimeBias : public ParametrizationSatelliteTrackingBase\n{\n  UInt                       degree;\n  ParametrizationTemporalPtr temporal;\n  Bool                       perArc;\n\npublic:\n  ParametrizationSatelliteTrackingTimeBias(Config &config);\n\n  Bool isPerArc() const {return perArc;}\n  Bool setInterval(const Time &timeStart, const Time &timeEnd);\n  UInt parameterCount() const {return temporal->parameterCount();}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void compute(UInt sstType, const std::vector<Time> &times, const Vector &sst0,\n               const Vector &position1, const Vector &position2, const Vector &velocity1, const Vector &velocity2,\n               const std::vector<Rotary3d> &rotSat1, const std::vector<Rotary3d> &rotSat2, MatrixSliceRef A);\n};\n\n/***********************************************/\n\ninline ParametrizationSatelliteTrackingTimeBias::ParametrizationSatelliteTrackingTimeBias(Config &config)\n{\n  try\n  {\n    readConfig(config, \"polynomialDegree\",  degree,   Config::MUSTSET,  \"10\", \"polynomial degree\");\n    readConfig(config, \"temporal\",          temporal, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"perArc\",            perArc,   Config::DEFAULT,  \"0\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Bool ParametrizationSatelliteTrackingTimeBias::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    return temporal->setInterval(timeStart, timeEnd, perArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingTimeBias::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> baseName(1);\n    baseName.at(0) = ParameterName(\"satellite1.satellite2\", \"sstTimeBias\");\n    temporal->parameterName(baseName, name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationSatelliteTrackingTimeBias::compute(UInt /*sstType*/, const std::vector<Time> &times, const Vector &sst0,\n                                                              const Vector &/*position1*/, const Vector &/*position2*/, const Vector &/*velocity1*/, const Vector &/*velocity2*/,\n                                                              const std::vector<Rotary3d> &/*rotSat1*/, const std::vector<Rotary3d> &/*rotSat2*/, MatrixSliceRef A)\n{\n  try\n  {\n    Polynomial polynomial(times, degree);\n    const Vector rate = polynomial.derivative(times, sst0); // drho/dt\n    for(UInt idEpoch=0; idEpoch<sst0.rows(); idEpoch++)\n    {\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      temporal->factors(times.at(idEpoch), index, factor);\n      for(UInt i=0; i<index.size(); i++)\n        A(idEpoch, index.at(i)) = rate(idEpoch)*factor.at(i);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporal.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporal.cpp\n*\n* @brief Parametrization of temporal variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_ParametrizationTemporal\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalConstant.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalTrend.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalSplines.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalPolynomial.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalOscillation.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalFourier.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporalDoodsonHarmonic.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(ParametrizationTemporal, \"parametrizationTemporalType\",\n                      ParametrizationTemporalConstant,\n                      ParametrizationTemporalTrend,\n                      ParametrizationTemporalSplines,\n                      ParametrizationTemporalPolynomial,\n                      ParametrizationTemporalOscillation,\n                      ParametrizationTemporalFourier,\n                      ParametrizationTemporalDoodsonHarmonic)\n\nGROOPS_RENAMED_CLASS(temporalRepresentationType, parametrizationTemporalType, date2time(2020, 6, 3))\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(ParametrizationTemporal, \"parametrizationTemporalType\")\n\n/***********************************************/\n\nParametrizationTemporal::ParametrizationTemporal(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"Parametrization of temporal variations\"))\n    {\n      if(readConfigChoiceElement(config, \"constant\",        type, \"Constant in time\"))\n        representation.push_back(new ParametrizationTemporalConstant(config));\n      if(readConfigChoiceElement(config, \"trend\",           type, \"Linear trend\"))\n        representation.push_back(new ParametrizationTemporalTrend(config));\n      if(readConfigChoiceElement(config, \"splines\",         type, \"Splines\"))\n        representation.push_back(new ParametrizationTemporalSplines(config));\n      if(readConfigChoiceElement(config, \"polynomial\",      type, \"Polynomial\"))\n        representation.push_back(new ParametrizationTemporalPolynomial(config));\n      if(readConfigChoiceElement(config, \"oscillation\",     type, \"Oscillations\"))\n        representation.push_back(new ParametrizationTemporalOscillation(config));\n      if(readConfigChoiceElement(config, \"fourier\",         type, \"Fourier series\"))\n        representation.push_back(new ParametrizationTemporalFourier(config));\n      if(readConfigChoiceElement(config, \"doodsonHarmonic\", type, \"Tidal variations\"))\n        representation.push_back(new ParametrizationTemporalDoodsonHarmonic(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n\n    parameterCount_ = 0;\n    index.resize(representation.size());\n    for(UInt i=0; i<representation.size(); i++)\n    {\n      index.at(i) = parameterCount_;\n      parameterCount_ += representation.at(i)->parameterCount();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nParametrizationTemporal::~ParametrizationTemporal()\n{\n  for(UInt i=0; i<representation.size(); i++)\n    delete representation.at(i);\n}\n\n/***********************************************/\n\nBool ParametrizationTemporal::setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc)\n{\n  try\n  {\n    if(timeStart>=timeEnd)\n      throw(Exception(\"wrong time interval: \"+timeStart.dateTimeStr()+\" - \"+timeEnd.dateTimeStr()));\n\n    Bool change = FALSE;\n    for(UInt i=0; i<representation.size(); i++)\n      change = representation.at(i)->setInterval(timeStart, timeEnd, estimatePerArc) || change;\n    if(!change)\n      return FALSE;\n\n    // count parameter\n    parameterCount_ = 0;\n    index.resize(representation.size());\n    for(UInt i=0; i<representation.size(); i++)\n    {\n      index.at(i) = parameterCount_;\n      parameterCount_ += representation.at(i)->parameterCount();\n    }\n\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporal::factors(const Time &time, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  index.clear();\n  factor.clear();\n  for(UInt i=0; i<representation.size(); i++)\n    representation.at(i)->factors(time, this->index.at(i), index, factor);\n}\n\n/***********************************************/\n\nVector ParametrizationTemporal::factors(const Time &time) const\n{\n  std::vector<UInt>   index;\n  std::vector<Double> factor;\n  factors(time, index, factor);\n  Vector A(parameterCount());\n  for(UInt i=0; i<index.size(); i++)\n    A(index.at(i)) = factor.at(i);\n  return A;\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporal::designMatrix(const Time &time, const const_MatrixSlice &B, MatrixSliceRef A) const\n{\n  std::vector<UInt>   index;\n  std::vector<Double> factor;\n  factors(time, index, factor);\n  A.slice(0, 0, B.rows(), B.columns()*parameterCount_).setNull();\n  for(UInt i=0; i<index.size(); i++)\n    axpy(factor.at(i), B, A.slice(0, index.at(i)*B.columns(), B.rows(), B.columns()));\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporal::parameterName(std::vector<ParameterName> &name) const\n{\n  for(UInt i=0; i<representation.size(); i++)\n    representation.at(i)->parameterName(name);\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporal::parameterName(const std::vector<ParameterName> &baseName, std::vector<ParameterName> &name) const\n{\n  std::vector<ParameterName> temporalName;\n  parameterName(temporalName);\n  for(UInt i=0; i<temporalName.size(); i++)\n    for(UInt k=0; k<baseName.size(); k++)\n    {\n      ParameterName param = baseName.at(k);\n      param.interval = temporalName.at(i).interval;\n      param.temporal = temporalName.at(i).temporal;\n      name.push_back(param);\n    }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporal.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporal.h\n*\n* @brief Parametrization of temporal variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORAL__\n#define __GROOPS_PARAMETRIZATIONTEMPORAL__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporal = R\"(\n\\section{ParametrizationTemporal}\\label{parametrizationTemporalType}\nThis class gives a parametrization of time depending parameters (gravity field, positions, ...).\nIt will be used to set up the design matrix in a least squares adjustment.\nIf multiple parametrizations are given the coefficients in the parameter vector\nare sequently appended.\n\nUseally time intervals are defined half open meaning the last time belongs not to the interval.\nThis behaviour can be changed for the last interval with \\config{includeLastTime}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup parametrizationTemporalGroup ParametrizationTemporal\n* @brief Parametrization of temporal variations.\n* @ingroup classesGroup\n* The interface is given by @ref ParametrizationTemporal. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass ParametrizationTemporal;\nclass ParametrizationTemporalBase;\ntypedef std::shared_ptr<ParametrizationTemporal> ParametrizationTemporalPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Parametrization of temporal variations.\n* An Instance of this class can be created by @ref readConfig. */\nclass ParametrizationTemporal\n{\n  UInt parameterCount_;\n  std::vector<UInt> index;\n  std::vector<ParametrizationTemporalBase*> representation;\n\npublic:\n  /// Constructor.\n  ParametrizationTemporal(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~ParametrizationTemporal();\n\n  /** @brief Estimate parameter in the given interval only.\n  * Interval is defined as [@a timeStart, @a timeEnd).\n  * Change result of @a parameterCount(), @a parameterName().\n  * @return TRUE if parameters are changed */\n  Bool setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc=FALSE);\n\n  /** @brief number of parameters. */\n  UInt parameterCount() const {return parameterCount_;}\n\n  /** @brief Multipliers of unknown parameters for a point in @a time. */\n  Vector factors(const Time &time) const;\n\n  /** @brief Multipliers of unknown parameters for a point in @a time.\n  * @param time Time.\n  * @param[out] index Position of multipliers in the design matrix.\n  * @param[out] factor Multipliers of unknown parameters. */\n  void factors(const Time &time, std::vector<UInt> &index, std::vector<Double> &factor) const;\n\n  /** @brief Temporal design matrix.\n  * The temporal design matrix @a A is constructed\n  * from the basic design matrix @a B at this point in time. */\n  void designMatrix(const Time &time, const const_MatrixSlice &B, MatrixSliceRef A) const;\n\n  /** @brief Name of parameters.\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Name of parameters.\n  * @a baseName contain the name of each temporal component (e.g. x,y,z).\n  * They are connected with ':', e.g. x:cos, y:cos, z:cos, x:sin, y:sin, z:sin.\n  * The names are appended to @a name. */\n  void parameterName(const std::vector<ParameterName> &baseName, std::vector<ParameterName> &name) const;\n\n  /** @brief creates an derived instance of this class. */\n  static ParametrizationTemporalPtr create(Config &config, const std::string &name) {return ParametrizationTemporalPtr(new ParametrizationTemporal(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ParametrizationTemporal.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a representation without parameters is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] representation Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ParametrizationTemporal */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ParametrizationTemporalPtr &representation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass ParametrizationTemporalBase\n{\npublic:\nvirtual ~ParametrizationTemporalBase() {}\nvirtual Bool setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc) = 0;\nvirtual UInt parameterCount() const = 0;\nvirtual void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const = 0;\nvirtual void parameterName(std::vector<ParameterName> &name) const = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalConstant.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalConstant.cpp\n*\n* @brief Constant in time.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"parametrizationTemporalConstant.h\"\n\n/***********************************************/\n\nParametrizationTemporalConstant::ParametrizationTemporalConstant(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timeSeries;\n    readConfig(config, \"interval\",        timeSeries,      Config::DEFAULT, \"\", \"\");\n    readConfig(config, \"includeLastTime\", includeLastTime, Config::DEFAULT, \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    times      = timeSeries->times();\n    isInterval = (times.size() != 0);\n    if(!isInterval)\n      times = {Time(), date2time(2500,1,1)};\n    idxStart = 0;\n    idxEnd   = times.size()-1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationTemporalConstant::setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc)\n{\n  try\n  {\n    const UInt idxStartOld = idxStart;\n    const UInt idxEndOld   = idxEnd;\n\n    if(estimatePerArc && !isInterval)\n      times = {timeStart, timeEnd};\n\n    idxStart = 0;\n    while((idxStart+1<times.size()) && (timeStart>=times.at(idxStart+1)))\n      idxStart++;\n    idxEnd = idxStart;\n    while((idxEnd<times.size()-1) && (timeEnd>times.at(idxEnd)))\n      idxEnd++;\n\n    return (idxStartOld != idxStart) || (idxEndOld != idxEnd);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalConstant::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=idxStart; i<idxEnd; i++)\n      name.push_back(ParameterName(\"\", \"\", \"\", times.at(i), times.at(i+1)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalConstant::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  try\n  {\n    if(!times.size())\n    {\n      index.push_back(startIndex);\n      factor.push_back(1.);\n      return;\n    }\n\n    if((time < times.at(idxStart)) || (time > times.at(idxEnd)) || (!includeLastTime && (time == times.at(idxEnd))))\n      return;\n\n    // find index (interval)\n    UInt idx = idxStart;\n    while((idx+1 < idxEnd) && (time >= times.at(idx+1)))\n      idx++;\n\n    index.push_back(idx-idxStart+startIndex);\n    factor.push_back(1.);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalConstant.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalConstant.h\n*\n* @brief Constant in time.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALCONSTANT__\n#define __GROOPS_PARAMETRIZATIONTEMPORALCONSTANT__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalConstant = R\"(\n\\subsection{Constant}\\label{parametrizationTemporalType:constant}\nRepresents a parameter being constant in time in each \\config{interval}.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:*:*:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Constant in time.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalConstant : public ParametrizationTemporalBase\n{\n  std::vector<Time> times;\n  Bool              isInterval, includeLastTime;\n  UInt              idxStart, idxEnd;\n\npublic:\n  ParametrizationTemporalConstant(Config &config);\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc);\n  UInt parameterCount() const {return (idxEnd-idxStart);}\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n  void parameterName(std::vector<ParameterName> &name) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalDoodsonHarmonic.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalDoodsonHarmonic.cpp\n*\n* @brief Tidal variations.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"base/doodson.h\"\n#include \"files/fileAdmittance.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationTemporalDoodsonHarmonic.h\"\n\n/***********************************************/\n\nParametrizationTemporalDoodsonHarmonic::ParametrizationTemporalDoodsonHarmonic(Config &config)\n{\n  try\n  {\n    FileName admittanceName;\n\n    readConfig(config, \"doodson\",             majorDoodson,   Config::MUSTSET,  \"\", \"code number (e.g. 255.555) or darwin name (e.g. M2)\");\n    readConfig(config, \"inputfileAdmittance\", admittanceName, Config::OPTIONAL, \"\", \"interpolation of minor constituents\");\n    if(isCreateSchema(config)) return;\n\n    // read admittace file\n    // -------------------\n    if(!admittanceName.empty())\n    {\n      Admittance admit;\n      readFileAdmittance(admittanceName, admit);\n\n      admittance = Matrix(majorDoodson.size(), admit.doodsonMinor.size());\n      for(UInt i=0; i<majorDoodson.size(); i++)\n      {\n        Bool found = FALSE;\n        for(UInt k=0; k<admit.doodsonMajor.size(); k++)\n          if(majorDoodson.at(i) == admit.doodsonMajor.at(k))\n          {\n            found = TRUE;\n            copy(admit.admittance.row(k), admittance.row(i));\n            break;\n          }\n        if(!found)\n          throw(Exception(majorDoodson.at(i).name()+\" not found in admittance file\"));\n      }\n\n      // Matrix with Doodson multiplicators\n      doodsonMatrix = Doodson::matrix(admit.doodsonMinor);\n    }\n    else\n    {\n      // Matrix with Doodson multiplicators\n      doodsonMatrix = Doodson::matrix(majorDoodson);\n    }\n\n    _parameterCount = 2 * majorDoodson.size();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalDoodsonHarmonic::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=0; i<majorDoodson.size(); i++)\n    {\n      name.push_back(ParameterName(\"\", \"\", \"doodson.cos(\"+majorDoodson.at(i).name()+\")\"));\n      name.push_back(ParameterName(\"\", \"\", \"doodson.sin(\"+majorDoodson.at(i).name()+\")\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalDoodsonHarmonic::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  try\n  {\n    Vector thetaf = doodsonMatrix * Doodson::arguments(time);\n\n    Matrix csMinor(thetaf.rows(), 2);\n    for(UInt i=0; i<thetaf.rows(); i++)\n    {\n      csMinor(i,0) = cos(thetaf(i));\n      csMinor(i,1) = sin(thetaf(i));\n    }\n    Matrix csMajor = ((admittance.size()) ? (admittance * csMinor) : csMinor);\n\n    for(UInt i=0; i<csMajor.rows(); i++)\n    {\n      index.push_back(startIndex++);\n      index.push_back(startIndex++);\n      factor.push_back(csMajor(i,0));\n      factor.push_back(csMajor(i,1));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalDoodsonHarmonic.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalDoodsonHarmonic.h\n*\n* @brief Tidal variations.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALDOODSONHARMONIC__\n#define __GROOPS_PARAMETRIZATIONTEMPORALDOODSONHARMONIC__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalDoodsonHarmonic = R\"(\n\\subsection{DoodsonHarmonic}\nThe time variable function is given by a fourier expansion\n\\begin{equation}\n  f(x,t) = \\sum_{i} f_i^c(x)\\cos(\\Theta_i(t)) + f_i^s(x)\\sin(\\Theta_i(t)),\n\\end{equation}\nwhere $\\Theta_i(t)$ are the arguments of the tide constituents $i$\n\\begin{equation}\n  \\Theta_i(t) = \\sum_{k=1}^6 n_i^k\\beta_k(t),\n\\end{equation}\nwhere $\\beta_k(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$) and $n_i^k$\nare the Doodson multipliers for the term at frequency~$i$.\nThe multipliers must be given by \\configClass{doodson}{doodson} coded as Doodson number\n(e.g. 255.555) or as names intoduced by Darwin (e.g. M2).\n\nThe major constituents given by \\configClass{doodson}{doodson} can be used to interpolate minor tidal constituents\nusing the file \\configFile{inputfileAdmittance}{admittance}. This file can be created with\n\\program{DoodsonHarmonicsCalculateAdmittance}.\n\nThe total parameter count is $2N$ with $N$ the number of doodson frequencies.\nThe parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\ldots$ with\nthe \\file{parameter names}{parameterName} \\verb|*:*:doodson.cos(<doodsonName>):*| and \\verb|*:*:doodson.sin(<doodsonName>):*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/doodson.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Tidal variations.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalDoodsonHarmonic : public ParametrizationTemporalBase\n{\n  UInt   _parameterCount;\n  Matrix  doodsonMatrix;\n  Matrix  admittance;\n  std::vector<Doodson> majorDoodson;\n\npublic:\n  ParametrizationTemporalDoodsonHarmonic(Config &config);\n\n  Bool setInterval(const Time &/*timeStart*/, const Time &/*timeEnd*/, Bool /*estimatePerArc*/) {return FALSE;};\n  UInt parameterCount() const {return _parameterCount;}\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n  void parameterName(std::vector<ParameterName> &name) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalFourier.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalFourier.cpp\n*\n* @brief Fourier expansion.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationTemporalFourier.h\"\n\n/***********************************************/\n\nParametrizationTemporalFourier::ParametrizationTemporalFourier(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timeSeries;\n\n    readConfig(config, \"fourierDegree\",   order,           Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"interval\",        timeSeries,      Config::DEFAULT, \"\", \"intervals of fourier series\");\n    readConfig(config, \"includeLastTime\", includeLastTime, Config::DEFAULT, \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    times      = timeSeries->times();\n    isInterval = (times.size() != 0);\n    if(!isInterval)\n      times = {Time(), date2time(2500,1,1)};\n    idxStart = 0;\n    idxEnd   = times.size()-1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationTemporalFourier::setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc)\n{\n  try\n  {\n    const UInt idxStartOld = idxStart;\n    const UInt idxEndOld   = idxEnd;\n\n    if(estimatePerArc && !isInterval)\n      times = {timeStart, timeEnd};\n\n    idxStart = 0;\n    while((idxStart+1<times.size()) && (timeStart>=times.at(idxStart+1)))\n      idxStart++;\n    idxEnd = idxStart;\n    while((idxEnd<times.size()-1) && (timeEnd>times.at(idxEnd)))\n      idxEnd++;\n\n    return (idxStartOld != idxStart) || (idxEndOld != idxEnd);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalFourier::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=idxStart; i<idxEnd; i++)\n      for(UInt m=1; m<=order; m++)\n      {\n        name.push_back(ParameterName(\"\", \"\", \"fourier.cos(\"+m%\"%i\"s+\"*x)\", times.at(i), times.at(i+1)));\n        name.push_back(ParameterName(\"\", \"\", \"fourier.sin(\"+m%\"%i\"s+\"*x)\", times.at(i), times.at(i+1)));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalFourier::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  try\n  {\n    if((time < times.at(idxStart)) || (time > times.at(idxEnd)) || (!includeLastTime && (time == times.at(idxEnd))))\n      return;\n\n    // find index (interval)\n    UInt idx = idxStart;\n    while((idx+1 < idxEnd) && (time >= times.at(idx+1)))\n      idx++;\n\n    const Double angle = 2*PI*(time-times.at(idx)).mjd()/(times.at(idx+1)-times.at(idx)).mjd();\n    for(UInt m=1; m<=order; m++)\n    {\n      index.push_back(2*order*(idx-idxStart)+2*m-2+startIndex);\n      index.push_back(2*order*(idx-idxStart)+2*m-1+startIndex);\n      factor.push_back(cos(m*angle));\n      factor.push_back(sin(m*angle));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalFourier.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalFourier.h\n*\n* @brief Fourier expansion in time domain.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALFOURIER__\n#define __GROOPS_PARAMETRIZATIONTEMPORALFOURIER__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalFourier = R\"(\n\\subsection{Fourier}\nA time variable function is given by a fourier expansion\n\\begin{equation}\nf(x,t) = \\sum_{m=1}^M f_m^c(\\M x)\\cos(2\\pi m \\tau) + f_m^s(\\M x)\\sin(2\\pi m \\tau)\n\\end{equation}\nwith the normalized time\n\\begin{equation}\n\\tau = \\frac{t-t_A}{t_B-t_A},\n\\end{equation}\nand $t_A$ is \\config{timeStart}, $t_B$ is \\config{timeEnd} in each \\config{interval}\nand $M$ is the \\config{fourierDegree}.\n\nThe total parameter count is $2MN$, where $N$ is the number of intervals.\nThe parameters are sorted in following order: $f_1^c, f_1^s, f_2^c, \\ldots$ with\nthe \\file{parameter names}{parameterName} \\verb|*:*:fourier.cos(<m>*x):<interval>| and \\verb|*:*:fourier.sin(<m>*x):<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Fourier expansion.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalFourier : public ParametrizationTemporalBase\n{\n  std::vector<Time> times;\n  Bool              isInterval, includeLastTime;\n  UInt              idxStart, idxEnd;\n  UInt              order;\n\npublic:\n  ParametrizationTemporalFourier(Config &config);\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc);\n  UInt parameterCount() const  {return 2*order*(idxEnd-idxStart);}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalOscillation.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalOscillation.cpp\n*\n* @brief Oscillations.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-07\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationTemporalOscillation.h\"\n\n/***********************************************/\n\nParametrizationTemporalOscillation::ParametrizationTemporalOscillation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"period\", timePeriod, Config::MUSTSET, \"365.25\",     \"[day]\");\n    readConfig(config, \"time0\",  time0,      Config::MUSTSET, STRING_J2000, \"reference time\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalOscillation::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=0; i<timePeriod.size(); i++)\n    {\n      const std::string str = \"(2*pi/\"+timePeriod.at(i).mjd()%\"%g\"s+\"*(t-\"+time0.dateTimeStr()+\"))\";\n      name.push_back(ParameterName(\"\", \"\", \"oscillation.cos\"+str));\n      name.push_back(ParameterName(\"\", \"\", \"oscillation.sin\"+str));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalOscillation::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  try\n  {\n    for(UInt i=0; i<timePeriod.size(); i++)\n    {\n      const Double omega = 2*PI/timePeriod.at(i).mjd()*(time-time0).mjd();\n      index.push_back(2*i+0+startIndex);\n      index.push_back(2*i+1+startIndex);\n      factor.push_back(cos(omega));\n      factor.push_back(sin(omega));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalOscillation.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalOscillation.h\n*\n* @brief Oscillations.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALOSCILLATION__\n#define __GROOPS_PARAMETRIZATIONTEMPORALOSCILLATION__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalOscillation = R\"(\n\\subsection{Oscillation}\nA time variable function is given by a oscillation\n\\begin{equation}\nf(x,t) = f^c(\\M x)\\cos(\\omega_i(t)) + f^s(\\M x)\\sin(\\omega_i(t))\n\\end{equation}\nwith $\\omega_i=\\frac{2\\pi}{T_i}(t-t_0)$,\n$t_0$ is \\config{timeStart} and $T$ is \\config{timePeriod} in days.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:*:oscillation.cos(2*pi/<period(days)>*(t-<timeStart>)):*|\nand \\verb|*:*:oscillation.sin(2*pi/<period(days)>*(t-<timeStart>)):*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Oscillations.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalOscillation : public ParametrizationTemporalBase\n{\n  Time               time0;\n  std::vector<Time>  timePeriod;\n\npublic:\n  ParametrizationTemporalOscillation(Config &config);\n\n  Bool setInterval(const Time &/*timeStart*/, const Time &/*timeEnd*/, Bool /*estimatePerArc*/) {return FALSE;};\n  UInt parameterCount() const  {return 2*timePeriod.size();}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalPolynomial.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalPolynomial.cpp\n*\n* @brief Legendre Polynomials in time intervals.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-05-31\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/legendrePolynomial.h\"\n#include \"config/config.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationTemporalPolynomial.h\"\n\n/***********************************************/\n\nParametrizationTemporalPolynomial::ParametrizationTemporalPolynomial(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timeSeries;\n    readConfig(config, \"polynomialDegree\", degree,          Config::MUSTSET, \"0\", \"polynomial degree\");\n    readConfig(config, \"interval\",         timeSeries,      Config::DEFAULT, \"\",  \"intervals of polynomials\");\n    readConfig(config, \"includeLastTime\",  includeLastTime, Config::DEFAULT, \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    times      = timeSeries->times();\n    isInterval = (times.size() != 0);\n    if(!isInterval)\n      times = {Time(), date2time(2500,1,1)};\n    idxStart   = 0;\n    idxEnd = times.size()-1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationTemporalPolynomial::setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc)\n{\n  try\n  {\n    const UInt idxStartOld = idxStart;\n    const UInt idxEndOld   = idxEnd;\n\n    if(estimatePerArc && !isInterval)\n      times = {timeStart, timeEnd};\n\n    idxStart = 0;\n    while((idxStart+1<times.size()) && (timeStart>=times.at(idxStart+1)))\n      idxStart++;\n    idxEnd = idxStart;\n    while((idxEnd<times.size()-1) && (timeEnd>times.at(idxEnd)))\n      idxEnd++;\n\n    return (idxStartOld != idxStart) || (idxEndOld != idxEnd);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalPolynomial::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=idxStart; i<idxEnd; i++)\n    {\n      name.push_back(ParameterName(\"\", \"\", \"\", times.at(i), times.at(i+1))); // constant part\n      for(UInt n=1; n<=degree; n++)\n        name.push_back(ParameterName(\"\", \"\", \"legendrePolynomial.n\"+n%\"%i\"s, times.at(i), times.at(i+1)));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalPolynomial::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  try\n  {\n    if((time < times.at(idxStart)) || (time > times.at(idxEnd)) || (!includeLastTime && (time == times.at(idxEnd))))\n      return;\n\n    // find index (interval)\n    UInt idx = idxStart;\n    while((idx+1 < idxEnd) && (time >= times.at(idx+1)))\n      idx++;\n\n    const Double t  = 2*(time-times.at(idx)).mjd()/(times.at(idx+1)-times.at(idx)).mjd()-1; // t is [-1,+1]\n    const Vector Pn = LegendrePolynomial::compute(t, degree);\n    for(UInt n=0; n<=degree; n++)\n    {\n      index.push_back( (degree+1)*(idx-idxStart)+n+startIndex );\n      factor.push_back( Pn(n) );\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalPolynomial.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalPolynomial.h\n*\n* @brief Legendre Polynomials in time intervals.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-05-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALPOLYNOMIAL__\n#define __GROOPS_PARAMETRIZATIONTEMPORALPOLYNOMIAL__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalPolynomial = R\"(\n\\subsection{Polynomial}\nA time variable function is represented by Legendre polynomials in each \\config{interval}.\nThe time is normed to $[-1,1)$ in each interval.\n\nThe total parameter count is $(N+1)M$,\nwhere $N$ is the polynmial degree and $M$ the number of intervals with\nthe \\file{parameter names}{parameterName} \\verb|*:*:legendrePolynomial.n<degree>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Splines in time domain.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalPolynomial : public ParametrizationTemporalBase\n{\n  std::vector<Time> times;\n  Bool              isInterval, includeLastTime;\n  UInt              idxStart, idxEnd;\n  UInt              degree;\n\npublic:\n  ParametrizationTemporalPolynomial(Config &config);\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc);\n  UInt parameterCount() const {return (degree+1)*(idxEnd-idxStart);}\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n  void parameterName(std::vector<ParameterName> &name) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalSplines.cpp",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalSplines.cpp\n*\n* @brief Splines expansion.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/basisSplines.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"parametrizationTemporalSplines.h\"\n\n/***********************************************/\n\nParametrizationTemporalSplines::ParametrizationTemporalSplines(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr timeSeriesPtr, timesIntervalPtr;\n\n    readConfig(config, \"degree\",          degree,           Config::MUSTSET, \"\",  \"degree of splines\");\n    readConfig(config, \"timeSeries\",      timeSeriesPtr,    Config::MUSTSET, \"\",  \"nodal points in time domain\");\n    readConfig(config, \"intervals\",       timesIntervalPtr, Config::DEFAULT, \"\",  \"\");\n    readConfig(config, \"includeLastTime\", includeLastTime,  Config::DEFAULT, \"0\", \"\");\n    if(isCreateSchema(config)) return;\n\n    times = timeSeriesPtr->times();\n\n    // init time intervals\n    // -------------------\n    std::vector<Time> timesInterval = timesIntervalPtr->times();\n    isInterval = (timesInterval.size() != 0);\n    if(!isInterval)\n      timesInterval = {times.at(0), times.back()};\n    computeIntervals(timesInterval);\n    idxStart = 0;\n    idxEnd   = idEpochStart.size();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalSplines::computeIntervals(const std::vector<Time> &timesInterval)\n{\n  try\n  {\n    idEpochStart.clear();\n    idEpochEnd.clear();\n    for(UInt idInterval=0; idInterval<timesInterval.size()-1; idInterval++)\n    {\n      UInt start = 0;\n      while((start+1<times.size()) && (times.at(start+1)<=timesInterval.at(idInterval)))\n        start++;\n      UInt count = 0;\n      while((start+count<times.size()) && (times.at(start+count)<=timesInterval.at(idInterval+1)))\n        count++;\n      if(count==0)\n        continue;\n\n      for(UInt n=0; n<degree; n++)\n        idEpochStart.push_back(start);\n      for(UInt i=0; i<count-1; i++)\n      {\n        idEpochStart.push_back(start+i);\n        idEpochEnd.push_back(start+i+1);\n      }\n      for(UInt n=0; n<degree; n++)\n        idEpochEnd.push_back(start+count-1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ParametrizationTemporalSplines::setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc)\n{\n  try\n  {\n    const UInt idxStartOld = idxStart;\n    const UInt idxEndOld   = idxEnd;\n\n    if((timeEnd<=times.at(0)) || (timeStart>=times.back()))\n    {\n      idxStart = idxEnd = 0; // time interval outside spline nodal points\n      return (idxStartOld != idxStart) || (idxEndOld != idxEnd);\n    }\n\n    if(estimatePerArc && !isInterval)\n      computeIntervals({timeStart, timeEnd});\n\n    idxStart = 0;\n    while((idxStart<idEpochEnd.size()) && (times.at(idEpochEnd.at(idxStart))<=timeStart))\n      idxStart++;\n\n    idxEnd = idxStart;\n    while((idxEnd<idEpochStart.size()) && (times.at(idEpochStart.at(idxEnd))<timeEnd))\n      idxEnd++;\n\n    return (idxStartOld != idxStart) || (idxEndOld != idxEnd);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalSplines::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    for(UInt i=idxStart; i<idxEnd; i++)\n      name.push_back(ParameterName(\"\", \"\", \"spline.n\"+degree%\"%i\"s, times.at(idEpochStart.at(i)), times.at(idEpochEnd.at(i))));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ParametrizationTemporalSplines::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  try\n  {\n    if(idxEnd == idxStart)\n      return;\n    if((time < times.at(idEpochStart.at(idxStart))) || (time > times.at(idEpochEnd.at(idxEnd-1))) || (!includeLastTime && (time == times.at(idEpochEnd.at(idxEnd-1)))))\n      return;\n\n    // find first used parameter\n    UInt idx = idxStart;\n    while((idx+1+degree < idxEnd) && (time >= times.at(idEpochEnd.at(idx))))\n      idx++;\n\n    const UInt   idEpoch = idEpochEnd.at(idx)-1;\n    const Double t = (time-times.at(idEpoch)).mjd()/(times.at(idEpoch+1)-times.at(idEpoch)).mjd();\n    const Vector f = BasisSplines::compute(t, degree);\n    for(UInt i=0; i<=degree; i++)\n      if(std::fabs(f(i)) > 1e-8)\n      {\n        index.push_back( i+idx-idxStart+startIndex );\n        factor.push_back( f(i) );\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalSplines.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalSplines.h\n*\n* @brief Splines in time domain.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALSPLINES__\n#define __GROOPS_PARAMETRIZATIONTEMPORALSPLINES__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalSplines = R\"(\n\\subsection{Splines}\\label{parametrizationTemporalType:splines}\nA time variable function is given by\n\\begin{equation}\nf(x,t) =  \\sum_i f_i(x)\\Psi_i(t),\n\\end{equation}\nwith the (spatial) coefficients $f_i(x)$ as parameters and the temporal basis functions~$\\Psi_i(t)$.\nBasis splines are defined as polynomials of degree~$n$ in intervals between nodal points in time $t_i$,\nfor details see~\\reference{basis splines}{fundamentals.basisSplines}.\n\nThe parameters are ordered timewise. First all parameters of $f_{i=1}(x)$ then\n$f_{i=2}(x)$ and so on. The total parameter count in each \\config{interval} is $N=N_t+n-1$,\nwhere $N_t$ is the count of time points from \\configClass{timeSeries}{timeSeriesType} in each interval and $n$\nis the \\config{degree}.\n\nThe \\file{parameter names}{parameterName} are \\verb|*:*:spline.n<degree>:<interval of each spline>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Splines in time domain.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalSplines : public ParametrizationTemporalBase\n{\n  std::vector<Time> times;\n  std::vector<UInt> idEpochStart, idEpochEnd;\n  Bool              isInterval, includeLastTime;\n  UInt              idxStart, idxEnd;\n  UInt              degree;\n\n  void computeIntervals(const std::vector<Time> &timesInterval);\n\npublic:\n  ParametrizationTemporalSplines(Config &config);\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd, Bool estimatePerArc);\n  UInt parameterCount() const {return idxEnd-idxStart;}\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n  void parameterName(std::vector<ParameterName> &name) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/parametrizationTemporal/parametrizationTemporalTrend.h",
    "content": "/***********************************************/\n/**\n* @file parametrizationTemporalTrend.h\n*\n* @brief Linear trend in time.\n* @see ParametrizationTemporal\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-12-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARAMETRIZATIONTEMPORALTREND__\n#define __GROOPS_PARAMETRIZATIONTEMPORALTREND__\n\n// Latex documentation\n#ifdef DOCSTRING_ParametrizationTemporal\nstatic const char *docstringParametrizationTemporalTrend = R\"(\n\\subsection{Trend}\\label{parametrizationTemporalType:trend}\nA time variable function is given by a linear trend\n\\begin{equation}\nf(x,t) = \\frac{1}{T}(t-t_0) \\cdot f_t(x),\n\\end{equation}\nwith $t_0$ is \\config{timeStart} and $T$ is \\config{timeStep} in days.\nA constant term is not included and must added separately.\n\nThe \\file{parameter name}{parameterName} is \\verb|*:*:trend.<timeStep(days)>*(t-<timeStart>):*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Linear trend in time.\n* @ingroup parametrizationTemporalGroup\n* @see ParametrizationTemporal */\nclass ParametrizationTemporalTrend : public ParametrizationTemporalBase\n{\n  Time time0, timeStep;\n\npublic:\n  ParametrizationTemporalTrend(Config &config);\n\n  Bool setInterval(const Time &/*timeStart*/, const Time &/*timeEnd*/, Bool /*estimatePerArc*/) {return FALSE;}\n  UInt parameterCount() const {return 1;}\n  void parameterName(std::vector<ParameterName> &name) const;\n  void factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const;\n};\n\n/***********************************************/\n\ninline ParametrizationTemporalTrend::ParametrizationTemporalTrend(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeStart\", time0,    Config::MUSTSET,  STRING_J2000, \"reference time\");\n    readConfig(config, \"timeStep\",  timeStep, Config::MUSTSET,  \"365.25\",     \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationTemporalTrend::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    name.push_back(ParameterName(\"\", \"\", \"trend.\"+timeStep.mjd()%\"%g\"s+\"*(t-\"+time0.dateTimeStr()+\")\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ParametrizationTemporalTrend::factors(const Time &time, UInt startIndex, std::vector<UInt> &index, std::vector<Double> &factor) const\n{\n  index.push_back(startIndex);\n  factor.push_back((time-time0).mjd()/timeStep.mjd());\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelector.cpp",
    "content": "/***********************************************/\n/**\n* @file platformSelector.cpp\n*\n* @brief Selected platforms.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlatformSelector\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/platformSelector/platformSelectorAll.h\"\n#include \"classes/platformSelector/platformSelectorEquipment.h\"\n#include \"classes/platformSelector/platformSelectorExclude.h\"\n#include \"classes/platformSelector/platformSelectorFile.h\"\n#include \"classes/platformSelector/platformSelectorWildcard.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(PlatformSelector, \"platformSelectorType\",\n                      PlatformSelectorAll,\n                      PlatformSelectorWildcard,\n                      PlatformSelectorFile,\n                      PlatformSelectorEquipment,\n                      PlatformSelectorExclude)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(PlatformSelector, \"platformSelectorType\")\n\n/***********************************************/\n\nPlatformSelector::PlatformSelector(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string choice;\n    while(readConfigChoice(config, name, choice, Config::OPTIONAL, \"\", \"selected platforms (stations, satellites, ...)\"))\n    {\n      if(readConfigChoiceElement(config, \"all\",      choice,  \"all available platforms\"))\n        bases.push_back(std::unique_ptr<PlatformSelectorBase>(new PlatformSelectorAll(config)));\n      if(readConfigChoiceElement(config, \"wildcard\", choice,  \"select by name and number\"))\n        bases.push_back(std::unique_ptr<PlatformSelectorBase>(new PlatformSelectorWildcard(config)));\n      if(readConfigChoiceElement(config, \"file\",     choice,  \"select from file (with alternatives)\"))\n        bases.push_back(std::unique_ptr<PlatformSelectorBase>(new PlatformSelectorFile(config)));\n      if(readConfigChoiceElement(config, \"equipment\", choice, \"select by equipment\"))\n        bases.push_back(std::unique_ptr<PlatformSelectorBase>(new PlatformSelectorEquipment(config)));\n      if(readConfigChoiceElement(config, \"exclude\",  choice,  \"deselect from selection\"))\n        bases.push_back(std::unique_ptr<PlatformSelectorBase>(new PlatformSelectorExclude(config)));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Byte> PlatformSelector::select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms) const\n\n{\n  try\n  {\n    std::vector<Byte> selected(platforms.size());\n    for(UInt i=0; i<platforms.size(); i++)\n      selected.at(i) = bases.size() && bases.front()->exclude && platforms.at(i);\n    for(auto &base : bases)\n      base->select(timeStart, timeEnd, platforms, selected);\n    return selected;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelector.h",
    "content": "/***********************************************/\n/**\n* @file platformSelector.h\n*\n* @brief Selected platforms.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLATFORMSELECTOR__\n#define __GROOPS_PLATFORMSELECTOR__\n\n// Latex documentation\n#ifdef DOCSTRING_PlatformSelector\nstatic const char *docstringPlatformSelector = R\"(\n\\section{PlatformSelector}\\label{platformSelectorType}\nSelect a list of platforms (stations, satellites, ...).\nIn a first step all platforms are selected if first selector \\config{exclude}s platforms\notherwise all platforms excluded. When every selector from top to bottom selects or deselects\n(with \\config{exclude}) the matching platforms.\n\nSee also \\program{GnssProcessing} or \\program{SlrProcessing}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/filePlatform.h\"\n\n/**\n* @defgroup platformSelectorGroup PlatformSelector\n* @brief Selected platforms.\n* @ingroup classesGroup\n* The interface is given by @ref PlatformSelector. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass PlatformSelector;\nclass PlatformSelectorBase;\ntypedef std::shared_ptr<PlatformSelector> PlatformSelectorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Selected platforms.\n* An instance of this class can be created with @ref readConfig. */\nclass PlatformSelector\n{\n  std::vector<std::unique_ptr<PlatformSelectorBase>> bases;\n\npublic:\n  /// Constructor.\n  PlatformSelector(Config &config, const std::string &name);\n\n  /** @brief returns a boolean vector which platforms are selected. */\n  std::vector<Byte> select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms) const;\n\n  /** @brief creates an derived instance of this class. */\n  static PlatformSelectorPtr create(Config &config, const std::string &name) {return PlatformSelectorPtr(new PlatformSelector(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class PlatformSelector.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and an class without points is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlatformSelector */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlatformSelectorPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass PlatformSelectorBase\n{\npublic:\n  Bool exclude;\n\n  virtual ~PlatformSelectorBase() {}\n  virtual void select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const = 0;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelectorAll.h",
    "content": "/***********************************************/\n/**\n* @file platformSelectorAll.h\n*\n* @brief All available platforms.\n* @see PlatformSelector\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLATFORMSELECTORALL__\n#define __GROOPS_PLATFORMSELECTORALL__\n\n// Latex documentation\n#ifdef DOCSTRING_PlatformSelector\nstatic const char *docstringPlatformSelectorAll = R\"(\n\\subsection{All}\\label{platformSelectorType:all}\nSelect all platforms.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief All available platforms.\n* @ingroup platformSelectorGroup\n* @see PlatformSelector */\nclass PlatformSelectorAll : public PlatformSelectorBase\n{\npublic:\n  PlatformSelectorAll(Config &/*config*/) {exclude = FALSE;}\n\n  void select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const override;\n};\n\n/***********************************************/\n\ninline void PlatformSelectorAll::select(const Time &/*timeStart*/, const Time &/*timeEnd*/, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const\n{\n  for(UInt i=0; i<platforms.size(); i++)\n    selected.at(i) = (platforms.at(i) != nullptr);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelectorEquipment.h",
    "content": "/***********************************************/\n/**\n* @file platformSelectorEquipment.h\n*\n* @brief Select platforms with wildcards.\n* @see PlatformSelector\n*\n* @author Torsten Mayer-Guerr\n* @date 2024-02-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLATFORMSELECTOREQUIPMENT__\n#define __GROOPS_PLATFORMSELECTOREQUIPMENT__\n\n// Latex documentation\n#ifdef DOCSTRING_PlatformSelector\nstatic const char *docstringPlatformSelectorEquipment = R\"(\n\\subsection{Equipment}\\label{platformSelectorType:equipment}\nSelect all platforms which has the specified equipment in the processed time interval.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Select platforms with wildcards.\n* @ingroup platformSelectorGroup\n* @see PlatformSelector */\nclass PlatformSelectorEquipment : public PlatformSelectorBase\n{\n  PlatformEquipment::Type type;\n  std::regex patternName, patternSerial;\n  std::regex patternRadome, patternVersion;\n  std::regex patternCospar, patternNorad, patternSic, patternSp3;\n\npublic:\n  PlatformSelectorEquipment(Config &config);\n  void select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const override;\n};\n\n/***********************************************/\n\ninline PlatformSelectorEquipment::PlatformSelectorEquipment(Config &config)\n{\n  try\n  {\n    std::string choice;\n    std::string name(\"*\"), serial(\"*\"), radome(\"*\"), version(\"*\");\n    std::string cospar(\"*\"), norad(\"*\"), sic(\"*\"), sp3(\"*\");\n\n    readConfig(config, \"name\",   name,   Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n    readConfig(config, \"serial\", serial, Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n    if(readConfigChoice(config, \"equipmentType\", choice, Config::MUSTSET, \"\", \"equipment type\"))\n    {\n      if(readConfigChoiceElement(config, \"all\", choice, \"all types\")) type = PlatformEquipment::UNDEFINED;\n      if(readConfigChoiceElement(config, \"gnssAntenna\", choice, \"antennas\"))\n      {\n        type = PlatformEquipment::GNSSANTENNA;\n        readConfig(config, \"radome\", radome, Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n      }\n      if(readConfigChoiceElement(config, \"gnssReceiver\", choice, \"receivers\"))\n      {\n        type = PlatformEquipment::GNSSRECEIVER;\n        readConfig(config, \"version\", version, Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n      }\n      if(readConfigChoiceElement(config, \"slrStation\",          choice, \"SLR station\"))          type = PlatformEquipment::SLRSTATION;\n      if(readConfigChoiceElement(config, \"slrRetroReflector\",   choice, \"laser retroreflector\")) type = PlatformEquipment::LASERRETROREFLECTOR;\n      if(readConfigChoiceElement(config, \"satelliteIdentifier\", choice, \"satellite identifier\"))\n      {\n        type = PlatformEquipment::SATELLITEIDENTIFIER;\n        readConfig(config, \"cospar\", cospar, Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n        readConfig(config, \"norad\",  norad,  Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n        readConfig(config, \"sic\",    sic,    Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n        readConfig(config, \"sp3\",    sp3,    Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n      }\n      if(readConfigChoiceElement(config, \"other\", choice, \"other types\")) type = PlatformEquipment::OTHER;\n      endChoice(config);\n    }\n    readConfig(config, \"exclude\", exclude, Config::DEFAULT, \"0\", \"deselect matching platforms\");\n    if(isCreateSchema(config)) return;\n\n    patternName     = String::wildcard2regex(name);\n    patternSerial   = String::wildcard2regex(serial);\n    patternRadome   = String::wildcard2regex(radome);\n    patternVersion  = String::wildcard2regex(version);\n    patternCospar   = String::wildcard2regex(cospar);\n    patternNorad    = String::wildcard2regex(norad);\n    patternSic      = String::wildcard2regex(sic);\n    patternSp3      = String::wildcard2regex(sp3);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void PlatformSelectorEquipment::select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const\n{\n  try\n  {\n    for(UInt i=0; i<platforms.size(); i++)\n      if(platforms.at(i))\n        for(const auto &eq : platforms.at(i)->equipments)\n          if(((type == PlatformEquipment::UNDEFINED) || (eq->getType() == type)) &&\n             (eq->timeStart < timeEnd) && (eq->timeEnd > timeStart))\n          {\n            if(!std::regex_match(eq->name, patternName) || !std::regex_match(eq->serial, patternSerial))\n              continue;\n            switch(eq->getType())\n            {\n              case PlatformEquipment::GNSSANTENNA:\n                if(std::regex_match(std::dynamic_pointer_cast<PlatformGnssAntenna>(eq)->radome, patternRadome))\n                  selected.at(i) = !exclude;\n                break;\n              case PlatformEquipment::GNSSRECEIVER:\n                if(std::regex_match(std::dynamic_pointer_cast<PlatformGnssReceiver>(eq)->version, patternVersion))\n                  selected.at(i) = !exclude;\n                break;\n              case PlatformEquipment::SATELLITEIDENTIFIER:\n                if(std::regex_match(std::dynamic_pointer_cast<PlatformSatelliteIdentifier>(eq)->cospar, patternCospar) &&\n                   std::regex_match(std::dynamic_pointer_cast<PlatformSatelliteIdentifier>(eq)->norad,  patternNorad)  &&\n                   std::regex_match(std::dynamic_pointer_cast<PlatformSatelliteIdentifier>(eq)->sic,    patternSic)    &&\n                   std::regex_match(std::dynamic_pointer_cast<PlatformSatelliteIdentifier>(eq)->sp3,    patternSp3))\n                selected.at(i) = !exclude;\n                break;\n              case PlatformEquipment::SLRSTATION:          [[fallthrough]];\n              case PlatformEquipment::LASERRETROREFLECTOR: [[fallthrough]];\n              case PlatformEquipment::OTHER:               [[fallthrough]];\n              case PlatformEquipment::UNDEFINED:           [[fallthrough]];\n              default:\n                selected.at(i) = !exclude;\n            }\n          }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelectorExclude.h",
    "content": "/***********************************************/\n/**\n* @file platformSelectorExclude.h\n*\n* @brief Exclude platforms.\n* @see PlatformSelector\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLATFORMSELECTOREXCLUDE__\n#define __GROOPS_PLATFORMSELECTOREXCLUDE__\n\n// Latex documentation\n#ifdef DOCSTRING_PlatformSelector\nstatic const char *docstringPlatformSelectorExclude = R\"(\n\\subsection{Exclude}\\label{platformSelectorType:exclude}\nDeselects all selected receivers/transmitters of\n\\configClass{selector}{platformSelectorType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Exclude platforms.\n* @ingroup platformSelectorGroup\n* @see PlatformSelector */\nclass PlatformSelectorExclude : public PlatformSelectorBase\n{\n  PlatformSelectorPtr selector;\n\npublic:\n  PlatformSelectorExclude(Config &config);\n  void select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const override;\n};\n\n/***********************************************/\n\ninline PlatformSelectorExclude::PlatformSelectorExclude(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selector\", selector, Config::MUSTSET, \"\", \"\");\n    exclude = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void PlatformSelectorExclude::select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const\n{\n  try\n  {\n    std::vector<Byte> excl = selector->select(timeStart, timeEnd, platforms);\n    for(UInt i=0; i<excl.size(); i++)\n      if(excl.at(i))\n        selected.at(i) = FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelectorFile.h",
    "content": "/***********************************************/\n/**\n* @file platformSelectorFile.h\n*\n* @brief Select platforms from file list.\n* @see PlatformSelector\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLATFORMSELECTORFILE__\n#define __GROOPS_PLATFORMSELECTORFILE__\n\n// Latex documentation\n#ifdef DOCSTRING_PlatformSelector\nstatic const char *docstringPlatformSelectorFile = R\"(\n\\subsection{File}\\label{platformSelectorType:file}\nSelect receivers/transmitters from each row of\n\\configFile{inputfileStringTable}{stringTable}.\nAdditional columns in a row represent alternatives\nif previous names are not available (e.g. without observation file).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Select platforms from file list.\n* @ingroup platformSelectorGroup\n* @see PlatformSelector */\nclass PlatformSelectorFile : public PlatformSelectorBase\n{\n  std::vector<std::vector<std::string>> names;\n\npublic:\n  PlatformSelectorFile(Config &config);\n  void select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const override;\n};\n\n/***********************************************/\n\ninline PlatformSelectorFile::PlatformSelectorFile(Config &config)\n{\n  try\n  {\n    FileName fileNameList;\n    readConfig(config, \"inputfileStringTable\", fileNameList, Config::MUSTSET,  \"\",  \"list of names with alternatives\");\n    readConfig(config, \"exclude\",              exclude,      Config::DEFAULT,  \"0\", \"deselect first matching platforms\");\n    if(isCreateSchema(config)) return;\n\n    readFileStringTable(fileNameList, names);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void PlatformSelectorFile::select(const Time &/*timeStart*/, const Time &/*timeEnd*/, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const\n{\n  try\n  {\n    for(UInt i=0; i<names.size(); i++)\n      for(UInt k=0; k<names.at(i).size(); k++) // alternatives\n      {\n        const UInt id = std::distance(platforms.begin(), std::find_if(platforms.begin(), platforms.end(),\n                                                                      [&](auto &t){return t && (t->name == names.at(i).at(k));}));\n        if((id < platforms.size()) && (selected.at(id) == exclude))\n        {\n          selected.at(id) = !exclude;\n          break; // skip alternative stations\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/platformSelector/platformSelectorWildcard.h",
    "content": "/***********************************************/\n/**\n* @file platformSelectorWildcard.h\n*\n* @brief Select platforms with wildcards.\n* @see PlatformSelector\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLATFORMSELECTORWILDCARD__\n#define __GROOPS_PLATFORMSELECTORWILDCARD__\n\n// Latex documentation\n#ifdef DOCSTRING_PlatformSelector\nstatic const char *docstringPlatformSelectorWildcard = R\"(\n\\subsection{Wildcard}\\label{platformSelectorType:wildcard}\nSelect all receivers/transmitters which match the\n\\config{name}, \\config{markerName}, and \\config{markerNumber}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Select platforms with wildcards.\n* @ingroup platformSelectorGroup\n* @see PlatformSelector */\nclass PlatformSelectorWildcard : public PlatformSelectorBase\n{\n  std::regex patternName, patternMarkerName, pattermMarkerNumber;\n\npublic:\n  PlatformSelectorWildcard(Config &config);\n  void select(const Time &timeStart, const Time &timeEnd, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const override;\n};\n\n/***********************************************/\n\ninline PlatformSelectorWildcard::PlatformSelectorWildcard(Config &config)\n{\n  try\n  {\n    std::string name, markerName, markerNumber;\n\n    readConfig(config, \"name\",         name,         Config::OPTIONAL, \"*\", \"wildcards: * and ?\");\n    readConfig(config, \"markerName\",   markerName,   Config::OPTIONAL, \"*\", \"wildcards: * and ?, from platform\");\n    readConfig(config, \"markerNumber\", markerNumber, Config::OPTIONAL, \"*\", \"wildcards: * and ?, from platform\");\n    readConfig(config, \"exclude\",      exclude,      Config::DEFAULT,  \"0\", \"deselect matching platforms\");\n    if(isCreateSchema(config)) return;\n\n    patternName         = String::wildcard2regex(name);\n    patternMarkerName   = String::wildcard2regex(markerName);\n    pattermMarkerNumber = String::wildcard2regex(markerNumber);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void PlatformSelectorWildcard::select(const Time &/*timeStart*/, const Time &/*timeEnd*/, const std::vector<const Platform*> &platforms, std::vector<Byte> &selected) const\n{\n  try\n  {\n    for(UInt i=0; i<platforms.size(); i++)\n      if(platforms.at(i) &&\n         std::regex_match(platforms.at(i)->name,         patternName) &&\n         std::regex_match(platforms.at(i)->markerName,   patternMarkerName) &&\n         std::regex_match(platforms.at(i)->markerNumber, pattermMarkerNumber))\n        selected.at(i) = !exclude;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.cpp",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsFilter.cpp\n*\n* @brief Filtering spherical harmonics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-06-08\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_SphericalHarmonicsFilter\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilterDdk.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilterGauss.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilterMatrix.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(SphericalHarmonicsFilter, \"sphericalHarmonicsFilterType\",\n                      SphericalHarmonicsFilterDdk,\n                      SphericalHarmonicsFilterGauss,\n                      SphericalHarmonicsFilterMatrix)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(SphericalHarmonicsFilter, \"sphericalHarmonicsFilterType\")\n\n/***********************************************/\n\nSphericalHarmonicsFilter::SphericalHarmonicsFilter(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"filtering of spherical harmonics\"))\n    {\n      if(readConfigChoiceElement(config, \"filterDdk\",       type, \"smoothing by a DDK filter\"))\n        filters.push_back(new SphericalHarmonicsFilterDdk(config));\n      if(readConfigChoiceElement(config, \"filterGauss\",       type, \"smoothing by a isotropic gaussian filter\"))\n        filters.push_back(new SphericalHarmonicsFilterGauss(config));\n      if(readConfigChoiceElement(config, \"filterMatrix\",      type, \"smoothing by a filter matrix\"))\n        filters.push_back(new SphericalHarmonicsFilterMatrix(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonicsFilter::~SphericalHarmonicsFilter()\n{\n  for(UInt i=0; i<filters.size(); i++)\n    delete filters.at(i);\n}\n\n/***********************************************/\n\nSphericalHarmonics SphericalHarmonicsFilter::filter(const SphericalHarmonics &harm) const\n{\n  try\n  {\n    SphericalHarmonics harm2 = harm;\n    for(UInt i=0; i<filters.size(); i++)\n      harm2 = filters.at(i)->filter(harm2);\n    return harm2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsFilter.h\n*\n* @brief Filtering spherical harmonics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-06-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSFILTER__\n#define __GROOPS_SPHERICALHARMONICSFILTER__\n\n// Latex documentation\n#ifdef DOCSTRING_SphericalHarmonicsFilter\nstatic const char *docstringSphericalHarmonicsFilter = R\"(\n\\section{SphericalHarmonicsFilter}\\label{sphericalHarmonicsFilterType}\nFiltering of a spherical harmonics expansion.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup sphericalHarmonicsFilterGroup SphericalHarmonicsFilter\n* @brief Filtering spherical harmonics.\n* @ingroup classesGroup\n* The interface is given by @ref SphericalHarmonicsFilter. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SphericalHarmonicsFilter;\nclass SphericalHarmonicsFilterBase;\ntypedef std::shared_ptr<SphericalHarmonicsFilter> SphericalHarmonicsFilterPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Filtering spherical harmonics.\n* An Instance of this class can be created by @ref readConfig. */\nclass SphericalHarmonicsFilter\n{\n  std::vector<SphericalHarmonicsFilterBase*> filters;\n\npublic:\n  /// Constructor.\n  SphericalHarmonicsFilter(Config &config, const std::string &name);\n\n  /// Destructor.\n  virtual ~SphericalHarmonicsFilter();\n\n  /** @brief returns a filtered version of given harmonics. */\n  virtual SphericalHarmonics filter(const SphericalHarmonics &harm) const;\n\n  /** @brief creates an derived instance of this class. */\n  static SphericalHarmonicsFilterPtr create(Config &config, const std::string &name) {return SphericalHarmonicsFilterPtr(new SphericalHarmonicsFilter(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class SphericalHarmonicsFilter.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a filter with no effect is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] filter Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SphericalHarmonicsFilter */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SphericalHarmonicsFilterPtr &filter, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass SphericalHarmonicsFilterBase\n{\npublic:\nvirtual ~SphericalHarmonicsFilterBase() {}\nvirtual SphericalHarmonics filter(const SphericalHarmonics &harm) const = 0;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_FILTER__ */\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsFilter/sphericalHarmonicsFilterDdk.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsFilterDdk.h\n*\n* @brief Smoothing by a DDK filter (order wise).\n* @see SphericalHarmonicsFilter\n*\n* @author Andreas Kvas\n* @date 2020-04-16\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSFILTERDDK__\n#define __GROOPS_SPHERICALHARMONICSFILTERDDK__\n\n// Latex documentation\n#ifdef DOCSTRING_SphericalHarmonicsFilter\nstatic const char *docstringSphericalHarmonicsFilterDdk = R\"(\n\\subsection{DDK}\nOrderwise filtering with the DDK filter by Kusche et al. 2009.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Smoothing by a DDK filter (order wise).\n* @ingroup sphericalHarmonicsFilterGroup\n* @see SphericalHarmonicsFilter */\nclass SphericalHarmonicsFilterDdk : public SphericalHarmonicsFilterBase\n{\n  std::vector<Matrix> matrix;\n\npublic:\n  SphericalHarmonicsFilterDdk(Config &config);\n\n  SphericalHarmonics filter(const SphericalHarmonics &harm) const override;\n};\n\n/***********************************************/\n\ninline SphericalHarmonicsFilterDdk::SphericalHarmonicsFilterDdk(Config &config)\n{\n  try\n  {\n    FileName inName;\n    UInt     level;\n\n    renameDeprecatedConfig(config, \"inputfileNormalequation\", \"inputfileNormalEquation\", date2time(2020, 6, 3));\n\n    readConfig(config, \"level\",                   level,  Config::MUSTSET, \"\", \"DDK filter level (1, 2, 3, ..., 8)\");\n    readConfig(config, \"inputfileNormalEquation\", inName, Config::MUSTSET, \"{groopsDataDir}/sphericalHarmonicsFilter/DDK/normalsKuscheGfzBlock_n2-120_orderwiseNonAlternating.dat.gz\", \"\");\n    if(isCreateSchema(config)) return;\n\n    const std::array<Double,9> factors = {0, 1e14, 1e13, 1e12, 5e11, 1e11, 5e10, 1e10, 5e9};\n    if(level >= factors.size())\n      throw(Exception(\"level higher than 8 not implemented.\"));\n    const Double factor = factors.at(level);\n    const Double power  = 4.0;\n\n    Matrix N, n;\n    NormalEquationInfo info;\n    readFileNormalEquation(inName, info, N, n);\n    fillSymmetric(N);\n\n    std::vector<std::vector<UInt>> idxC, idxS;\n    std::vector<UInt>              cs, orders, degrees;\n    for(UInt idx=0; idx<info.parameterName.size(); idx++)\n    {\n      std::string parameter = info.parameterName.at(idx).type;\n      auto pos = parameter.find('.');\n      std::string baseName = parameter.substr(0, pos);\n      if(baseName != \"sphericalHarmonics\")\n        throw(Exception(\"Non-spherical harmonic parameter found.\"));\n\n      std::istringstream is(parameter.substr(pos+1));\n      std::vector<std::string> tokens;\n      std::string part;\n      while(std::getline(is, part, '_'))\n        tokens.push_back(part);\n\n      cs.push_back((tokens.at(0) == \"c\") ? 0 : 1);\n      degrees.push_back(std::stoul(tokens.at(1)));\n      orders.push_back(std::stoul(tokens.at(2)));\n    }\n\n    const UInt maxDegree = *std::max_element(degrees.begin(), degrees.end());\n    idxC.resize(maxDegree+1);\n    idxS.resize(maxDegree+1);\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      idxC.at(n).resize(n+1, NULLINDEX);\n      idxS.at(n).resize(n+1, NULLINDEX);\n    }\n\n    for(UInt idx=0; idx<cs.size(); idx++)\n    {\n      const UInt n = degrees[idx];\n      const UInt m = orders[idx];\n      if(cs[idx] == 0)\n        idxC.at(n).at(m) = idx;\n      else\n        idxS.at(n).at(m) = idx;\n    }\n\n    matrix.resize(2*maxDegree+1);\n    matrix.at(0) = Matrix(maxDegree+1, maxDegree+1);\n    for(UInt m=1; m<=maxDegree; m++)\n      matrix.at(2*m-1) = matrix.at(2*m-0) = Matrix(maxDegree+1-m, maxDegree+1-m);\n\n    // order 0\n    for(UInt n1=0; n1<=maxDegree; n1++) // rows\n      for(UInt n2=0; n2<=maxDegree; n2++) // columns\n        if((idxC[n1][0]!=NULLINDEX)&&(idxC[n2][0]!=NULLINDEX))\n          matrix.at(0)(n1,n2) = N(idxC[n1][0], idxC[n2][0]);\n\n    // order >0\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      UInt idx1 = 0;\n      for(UInt n1=m; n1<=maxDegree; n1++) // rows\n      {\n          UInt idx2 = 0;\n          for(UInt n2=m; n2<=maxDegree; n2++) // columns\n          {\n            if((idxC[n1][m]!=NULLINDEX)&&(idxC[n2][m]!=NULLINDEX))\n              matrix.at(2*m-1)(idx1, idx2) = N(idxC[n1][m], idxC[n2][m]);\n            if((idxS[n1][m]!=NULLINDEX)&&(idxS[n2][m]!=NULLINDEX))\n              matrix.at(2*m-0)(idx1, idx2) = N(idxS[n1][m], idxS[n2][m]);\n            idx2++;\n          } // for(n2)\n        idx1++;\n      } // for(n1)\n    } // for(m)\n\n    // order 0\n    Matrix matrix2 = matrix.at(0);\n    matrix2(0,0) = 1.0;\n    for(UInt n=1; n<=maxDegree; n++)\n      matrix2(n,n) += factor*pow(static_cast<Double>(n),power);\n    matrix2.setType(Matrix::SYMMETRIC);\n    solveInPlace(matrix2,matrix.at(0));\n\n    // order >0\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      Matrix matrix2c = matrix.at(2*m-1);\n      Matrix matrix2s = matrix.at(2*m-0);\n      UInt idx = 0;\n      for(UInt n=m; n<=maxDegree; n++)\n      {\n        matrix2c(idx,idx) += factor*pow(static_cast<Double>(n),power);\n        matrix2s(idx,idx) += factor*pow(static_cast<Double>(n),power);\n        idx++;\n      }\n      matrix2c.setType(Matrix::SYMMETRIC);\n      matrix2s.setType(Matrix::SYMMETRIC);\n      solveInPlace(matrix2c,matrix.at(2*m-1));\n      solveInPlace(matrix2s,matrix.at(2*m-0));\n    }\n\n    const UInt minDegreeFilter = 2;\n    for(UInt n=0; n<minDegreeFilter; n++)\n      matrix.at(0)(n,n) = 1.0;\n\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      UInt idx = 0;\n      for(UInt n=m; n<minDegreeFilter; n++)\n      {\n        matrix.at(2*m-1)(idx, idx) = 1.0;\n        matrix.at(2*m-0)(idx, idx) = 1.0;\n        idx++;\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SphericalHarmonics SphericalHarmonicsFilterDdk::filter(const SphericalHarmonics &harm) const\n{\n  try\n  {\n    const UInt maxDegree = std::min(harm.maxDegree(), matrix.size()-1);\n\n    Matrix cnm = harm.cnm();\n    Matrix snm = harm.snm();\n\n    Matrix cnmNew(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snmNew(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    // filter order 0\n    Vector x(maxDegree+1);\n    for(UInt n=0; n<=maxDegree; n++)\n      x(n) = cnm(n,0);\n    x = matrix.at(0).slice(0,0,x.rows(),x.rows()) * x;\n    for(UInt n=0; n<=maxDegree; n++)\n      cnmNew(n,0) = x(n);\n\n    // filter order >0\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      Vector x(maxDegree+1-m);\n\n      // cnm\n      UInt idx = 0;\n      for(UInt n=m; n<=maxDegree; n++)\n        x(idx++) = cnm(n,m);\n      x = matrix.at(2*m-1).slice(0,0,x.rows(),x.rows()) * x;\n      idx = 0;\n      for(UInt n=m; n<=maxDegree; n++)\n        cnmNew(n,m) = x(idx++);\n\n      // snm\n      idx = 0;\n      for(UInt n=m; n<=maxDegree; n++)\n        x(idx++) = snm(n,m);\n      x = matrix.at(2*m-0).slice(0,0,x.rows(),x.rows()) * x;\n      idx = 0;\n      for(UInt n=m; n<=maxDegree; n++)\n        snmNew(n,m) = x(idx++);\n    }\n\n    return SphericalHarmonics(harm.GM(), harm.R(), cnmNew, snmNew);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsFilter/sphericalHarmonicsFilterGauss.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsFilterGauss.h\n*\n* @brief Isotropic gaussian filter.\n* @see SphericalHarmonicsFilter\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSFILTERGAUSS__\n#define __GROOPS_SPHERICALHARMONICSFILTERGAUSS__\n\n// Latex documentation\n#ifdef DOCSTRING_SphericalHarmonicsFilter\nstatic const char *docstringSphericalHarmonicsFilterGauss = R\"(\n\\subsection{Gauss}\nFiltering the spherical harmonics expansion with a Gaussian filter.\n\\config{radius} gives the filter radius on the Earth surface in km.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Isotropic gaussian filter.\n* @ingroup sphericalHarmonicsFilterGroup\n* @see SphericalHarmonicsFilter */\nclass SphericalHarmonicsFilterGauss : public SphericalHarmonicsFilterBase\n{\n  mutable Vector filterCoeff;\n  Double  radius;\n\n  Vector computeFilterCoefficients(UInt degree) const;\n\npublic:\n  SphericalHarmonicsFilterGauss(Config &config);\n\n  SphericalHarmonics filter(const SphericalHarmonics &harm) const;\n};\n\n/***********************************************/\n\ninline SphericalHarmonicsFilterGauss::SphericalHarmonicsFilterGauss(Config &config)\n{\n  try\n  {\n    readConfig(config, \"radius\", radius, Config::MUSTSET, \"500\", \"filter radius [km]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector SphericalHarmonicsFilterGauss::computeFilterCoefficients(UInt degree) const\n{\n  try\n  {\n    const Double b = std::log(2.)/(1-std::cos(1000*radius/DEFAULT_R));\n\n    Vector wn(degree+1);\n    wn(0) = 1;\n    wn(1) = (1+std::exp(-2*b))/(1-std::exp(-2*b)) - 1./b;\n    for(UInt n=2; n<=degree; n++)\n    {\n      wn(n) = -(2*n-1.)/b * wn(n-1) + wn(n-2);\n      if(wn(n)<1e-7)\n        break;\n    }\n    return wn;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SphericalHarmonics SphericalHarmonicsFilterGauss::filter(const SphericalHarmonics &harm) const\n{\n  try\n  {\n    if(harm.maxDegree()+1 > filterCoeff.size())\n      filterCoeff = computeFilterCoefficients(harm.maxDegree());\n\n    Matrix cnm       = harm.cnm();\n    Matrix snm       = harm.snm();\n    Matrix sigma2cnm = harm.sigma2cnm();\n    Matrix sigma2snm = harm.sigma2snm();\n    for(UInt n=0; n<cnm.rows(); n++)\n    {\n      cnm.slice(n,0,1,n+1)       *= filterCoeff(n);\n      snm.slice(n,0,1,n+1)       *= filterCoeff(n);\n      if(sigma2cnm.size()) sigma2cnm.slice(n,0,1,n+1) *= pow(filterCoeff(n),2);\n      if(sigma2snm.size()) sigma2snm.slice(n,0,1,n+1) *= pow(filterCoeff(n),2);\n    }\n    return SphericalHarmonics(harm.GM(), harm.R(), cnm, snm, sigma2cnm, sigma2snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsFilter/sphericalHarmonicsFilterMatrix.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsFilterMatrix.h\n*\n* @brief Smoothing by a filter matrix.\n* @see SphericalHarmonicsFilter\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2017-02-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSFILTERMATRIX__\n#define __GROOPS_SPHERICALHARMONICSFILTERMATRIX__\n\n// Latex documentation\n#ifdef DOCSTRING_SphericalHarmonicsFilter\nstatic const char *docstringSphericalHarmonicsFilterMatrix = R\"(\n\\subsection{Matrix}\nFiltering the spherical harmonics expansion with a matrix filter.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileMatrix.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Smoothing by a filter matrix.\n* @ingroup sphericalHarmonicsFilterGroup\n* @see SphericalHarmonicsFilter */\nclass SphericalHarmonicsFilterMatrix : public SphericalHarmonicsFilterBase\n{\n  Matrix A;\n  UInt   minDegree, maxDegree;\n  std::vector< std::vector<UInt> > idxC, idxS;\n\npublic:\n  SphericalHarmonicsFilterMatrix(Config &config);\n\n  SphericalHarmonics filter(const SphericalHarmonics &harm) const;\n};\n\n/***********************************************/\n\ninline SphericalHarmonicsFilterMatrix::SphericalHarmonicsFilterMatrix(Config &config)\n{\n  try\n  {\n    FileName fileNameMatrix;\n    SphericalHarmonicsNumberingPtr numbering;\n\n    readConfig(config, \"inputfileMatrix\", fileNameMatrix, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"minDegree\",       minDegree,      Config::MUSTSET, \"2\", \"of matrix\");\n    readConfig(config, \"maxDegree\",       maxDegree,      Config::MUSTSET, \"\",  \"of matrix\");\n    readConfig(config, \"numbering\",       numbering,      Config::MUSTSET, \"\",  \"numbering scheme of the matrix\");\n    if(isCreateSchema(config)) return;\n\n    readFileMatrix(fileNameMatrix, A);\n\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    const UInt dim = numbering->parameterCount(maxDegree, minDegree);\n    if((A.rows() != dim) || (A.columns() != dim))\n      throw(Exception(\"Matrix dimension and numbering disagree\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SphericalHarmonics SphericalHarmonicsFilterMatrix::filter(const SphericalHarmonics &harm) const\n{\n  try\n  {\n    // sort into matrix ordering\n    const Vector xDegreeWise = harm.get(maxDegree).x(); // degree wise\n    Vector x(A.columns());\n    UInt idx = 0;\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) x(idxC[n][0]) = xDegreeWise(idx);\n      idx++;\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) x(idxC[n][m]) = xDegreeWise(idx);\n        if(idxS[n][m]!=NULLINDEX) x(idxS[n][m]) = xDegreeWise(idx + 1);\n        idx += 2;\n      }\n    }\n\n    // filter\n    x = A*x;\n\n    // sort back\n    Matrix cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      if(idxC[n][0]!=NULLINDEX) cnm(n,0) = x(idxC[n][0]);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(idxC[n][m]!=NULLINDEX) cnm(n,m) = x(idxC[n][m]);\n        if(idxS[n][m]!=NULLINDEX) snm(n,m) = x(idxS[n][m]);\n      }\n    }\n\n    return SphericalHarmonics(harm.GM(), harm.R(), cnm, snm).get(harm.maxDegree());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.cpp",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsNumbering.cpp\n*\n* @brief Numbering schema of spherical harmonics coefficients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-01-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_SphericalHarmonicsNumbering\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingDegree.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingOrder.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingOrderNonAlternating.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingFile.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(SphericalHarmonicsNumbering, \"sphericalHarmonicsNumberingType\",\n                      SphericalHarmonicsNumberingDegree,\n                      SphericalHarmonicsNumberingOrder,\n                      SphericalHarmonicsNumberingOrderNonAlternating,\n                      SphericalHarmonicsNumberingFile)\n\nGROOPS_READCONFIG_CLASS(SphericalHarmonicsNumbering, \"sphericalHarmonicsNumberingType\")\n\n/***********************************************/\n\nSphericalHarmonicsNumberingPtr SphericalHarmonicsNumbering::create(Config &config, const std::string &name)\n{\n  try\n  {\n    SphericalHarmonicsNumberingPtr numbering;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"Numbering schema of spherical harmonics coefficients\");\n\n    if(readConfigChoiceElement(config, \"degreewise\",  type, \"sort degree by degree\"))\n      numbering = SphericalHarmonicsNumberingPtr(new SphericalHarmonicsNumberingDegree(config));\n    if(readConfigChoiceElement(config, \"orderwise\",   type, \"sort order by order\"))\n      numbering = SphericalHarmonicsNumberingPtr(new SphericalHarmonicsNumberingOrder(config));\n    if(readConfigChoiceElement(config, \"orderwiseNonAlternating\",  type, \"sort order by order with cnm, snm non-alternating\"))\n      numbering = SphericalHarmonicsNumberingPtr(new SphericalHarmonicsNumberingOrderNonAlternating(config));\n    if(readConfigChoiceElement(config, \"file\",  type, \"sort as specified in the chosen file\"))\n      numbering = SphericalHarmonicsNumberingPtr(new SphericalHarmonicsNumberingFile(config));\n\n    endChoice(config);\n\n    return numbering;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SphericalHarmonicsNumbering::numbering(UInt maxDegree, UInt minDegree, std::vector<UInt> &degree, std::vector<UInt> &order, std::vector<UInt> &cs) const\n{\n  try\n  {\n    const UInt paraCount = parameterCount(maxDegree, minDegree);\n    degree.resize(paraCount);\n    order.resize(paraCount);\n    cs.resize(paraCount);\n\n    std::vector<std::vector<UInt>> idxC, idxS;\n    numbering(maxDegree, minDegree, idxC, idxS);\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n      for(UInt m=0; m<=n; m++)\n      {\n        if(idxC[n][m] != NULLINDEX)\n        {\n          degree[idxC[n][m]] = n;\n          order[idxC[n][m]]  = m;\n          cs[idxC[n][m]]     = 0;\n        }\n\n        if(idxS[n][m] != NULLINDEX)\n        {\n          degree[idxS[n][m]] = n;\n          order[idxS[n][m]]  = m;\n          cs[idxS[n][m]]     = 1;\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsNumbering.h\n*\n* @brief Numbering schema of spherical harmonics coefficients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSNUMBERING__\n#define __GROOPS_SPHERICALHARMONICSNUMBERING__\n\n// Latex documentation\n#ifdef DOCSTRING_SphericalHarmonicsNumbering\nstatic const char *docstringSphericalHarmonicsNumbering = R\"(\n\\section{SphericalHarmonicsNumbering}\\label{sphericalHarmonicsNumberingType}\nThis class organizes the numbering scheme of spherical harmonics coefficients\nin a parameter vector (e.g \\program{Gravityfield2SphericalHarmonicsVector} and the design matrix of\n\\configClass{parametrizationGravity:sphericalHarmoncis}{parametrizationGravityType:sphericalHarmonics}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup sphericalHarmonicsNumberingGroup SphericalHarmonicsNumbering\n* @brief Numbering schema of spherical harmonics coefficients.\n* @ingroup classesGroup\n* The interface is given by @ref SphericalHarmonicsNumbering. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SphericalHarmonicsNumbering;\ntypedef std::shared_ptr<SphericalHarmonicsNumbering> SphericalHarmonicsNumberingPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Numbering schema of spherical harmonics coefficients.\n* An Instance of this class can be created by @ref readConfig. */\nclass SphericalHarmonicsNumbering\n{\npublic:\n  /// Destructor.\n  virtual ~SphericalHarmonicsNumbering() {}\n\n  /** @brief Total number of coefficients. */\n  virtual UInt parameterCount(UInt maxDegree, UInt minDegree) const = 0;\n\n  /** @brief Numbering scheme to interpret values in x-vector.\n  * @param maxDegree input\n  * @param minDegree input\n  * @param[out] degree degree n of the value in x(idx) at index idx.\n  * @param[out] order  order m of the value in x(idx) at index idx.\n  * @param[out] cs     is the value in x(idx) at index idx Cnm (cs[idx]==0) or Snm (cs[idx]==1). */\n  void numbering(UInt maxDegree, UInt minDegree, std::vector<UInt> &degree, std::vector<UInt> &order, std::vector<UInt> &cs) const;\n\n  /** @brief Numbering scheme to find coefficient in x-vector.\n  * Coefficients not included in the x vector are indicated with NULLINDEX.\n  * @param maxDegree input\n  * @param minDegree input\n  * @param[out] Cnm index in x vector for Cnm(n,m).\n  * @param[out] Snm index in x vector for Cnm(n,m). */\n  virtual void numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const = 0;\n\n  /** @brief Creates an derived instance of this class. */\n  static SphericalHarmonicsNumberingPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class SphericalHarmonicsNumbering.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a numbering remains untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] numbering Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SphericalHarmonicsNumbering */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SphericalHarmonicsNumberingPtr &numbering,\n                           Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingDegree.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsNumberingDegree.h\n*\n* @brief Numbering schema of spherical harmonics coefficients.\n* Numbering degree by degree:\n* c20, c21, s21, c22, s22, c30, c31, s31, c32, s32, ...\n* @see SphericalHarmonicsNumbering\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSNUMBERINGDEGREE__\n#define __GROOPS_SPHERICALHARMONICSNUMBERINGDEGREE__\n\n// Latex documentation\n#ifdef DOCSTRING_SphericalHarmonicsNumbering\nstatic const char *docstringSphericalHarmonicsNumberingDegree = R\"(\n\\subsection{Degree}\nNumbering degree by degree:\n\\[ c20, c21, s21, c22, s22, c30, c31, s31, c32, s32,\\ldots \\]\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Numbering schema of spherical harmonics coefficients.\n* @ingroup sphericalHarmonicsNumberingGroup\n* Numbering degree by degree:\n* c20, c21, s21, c22, s22, c30, c31, s31, c32, s32, ...\n* @see SphericalHarmonicsNumbering */\nclass SphericalHarmonicsNumberingDegree : public SphericalHarmonicsNumbering\n{\npublic:\n  SphericalHarmonicsNumberingDegree(Config &/*config*/) {}\n\n  virtual UInt parameterCount(UInt maxDegree, UInt minDegree) const override {return (maxDegree+1)*(maxDegree+1) - minDegree*minDegree;}\n  virtual void numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const override;\n};\n\n/***********************************************/\n\ninline void SphericalHarmonicsNumberingDegree::numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const\n{\n  Cnm.clear(); Cnm.resize(maxDegree+1);\n  Snm.clear(); Snm.resize(maxDegree+1);\n  for(UInt n=0; n<=maxDegree; n++)\n  {\n    Cnm[n].resize(n+1, NULLINDEX);\n    Snm[n].resize(n+1, NULLINDEX);\n  }\n\n  UInt idx = 0;\n  for(UInt n=minDegree; n<=maxDegree; n++)\n  {\n    Cnm[n][0] = idx++;\n    for(UInt m=1; m<=n; m++)\n    {\n      Cnm[n][m] = idx++;\n      Snm[n][m] = idx++;\n    }\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingFile.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsNumberingFile.h\n*\n* @brief Numbering schema of spherical harmonics coefficients.\n* Numbering as specified in the chosen file.\n* E.g. the kite numbering scheme.\n* @see SphericalHarmonicsNumbering\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSNUMBERINGFILE__\n#define __GROOPS_SPHERICALHARMONICSNUMBERINGFILE__\n\n#ifdef DOCSTRING_SphericalHarmonicsNumbering\nstatic const char *docstringSphericalHarmonicsNumberingFile = R\"(\n\\subsection{File}\nNumbering as specified in the chosen file.\nThe \\configFile{inputfile}{matrix} is a matrix with the first column indicating cnm/snm with 0 or 1.\nThe second and third column specify degree and order.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileMatrix.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Numbering schema of spherical harmonics coefficients.\n* Numbering as specified in the chosen file.\n* E.g. the kite numbering scheme.\n* @see SphericalHarmonicsNumbering */\nclass SphericalHarmonicsNumberingFile : public SphericalHarmonicsNumbering\n{\nprivate:\n  std::vector<UInt> degree, order, cs;\n  UInt maxDegree, minDegree;\n\npublic:\n  SphericalHarmonicsNumberingFile(Config &config);\n\n  virtual UInt parameterCount(UInt maxDegree, UInt minDegree) const override;\n  virtual void numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const override;\n};\n\n/***********************************************/\n\ninline SphericalHarmonicsNumberingFile::SphericalHarmonicsNumberingFile(Config &config)\n{\n  try\n  {\n    FileName inName;\n    readConfig(config, \"inputfile\", inName, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Matrix A;\n    readFileMatrix(inName, A);\n\n    cs.resize(A.rows());\n    degree.resize(A.rows());\n    order.resize(A.rows());\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      if(!((cs.at(i) == 0) || (cs.at(i) == 1)))\n        throw(Exception(\"First column must contain 0 or 1 for cnm/snm\"));\n      if(order.at(i) > degree.at(i))\n        throw(Exception(\"order must not greater than degree in column \"+i%\"%i\"s));\n      cs.at(i)     = static_cast<UInt>(A(i,0));\n      degree.at(i) = static_cast<UInt>(A(i,1));\n      order.at(i)  = static_cast<UInt>(A(i,2));\n    }\n\n    minDegree = *std::min_element(degree.begin(), degree.end());\n    maxDegree = *std::max_element(degree.begin(), degree.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline UInt SphericalHarmonicsNumberingFile::parameterCount(UInt maxDegree, UInt minDegree) const\n{\n  return std::count_if(degree.begin(), degree.end(), [&](UInt n) {return (n <= maxDegree) && (n >= minDegree);});\n}\n\n/***********************************************/\n\nvoid SphericalHarmonicsNumberingFile::numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const\n{\n  try\n  {\n    Cnm.clear(); Cnm.resize(maxDegree+1);\n    Snm.clear(); Snm.resize(maxDegree+1);\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      Cnm[n].resize(n+1, NULLINDEX);\n      Snm[n].resize(n+1, NULLINDEX);\n    }\n\n    UInt idx = 0;\n    for(UInt i=0; i<degree.size(); i++)\n      if((degree[i] <= maxDegree) && (degree[i] >= minDegree))\n      {\n        if(cs[i] == 0)\n          Cnm[degree[i]][order[i]] = idx++;\n        else\n          Snm[degree[i]][order[i]] = idx++;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingOrder.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsNumberingOrder.h\n*\n* @brief Numbering schema of spherical harmonics coefficients.\n* Numbering order by order:\n* c20, c30, c40, ..., c21, s21, c31, s31, ..., c22, s22\n* @see SphericalHarmonicsNumbering\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSNUMBERINGORDER__\n#define __GROOPS_SPHERICALHARMONICSNUMBERINGORDER__\n\n#ifdef DOCSTRING_SphericalHarmonicsNumbering\nstatic const char *docstringSphericalHarmonicsNumberingOrder = R\"(\n\\subsection{Order}\nNumbering order by order:\n\\[ c20, c30, c40, \\ldots, c21, s21, c31, s31, \\ldots, c22, s22 \\]\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Numbering schema of spherical harmonics coefficients.\n* @ingroup sphericalHarmonicsNumberingGroup\n* Numbering order by order:\n* c20, c30, c40, ..., c21, s21, c31, s31, ..., c22, s22\n* @see SphericalHarmonicsNumbering */\nclass SphericalHarmonicsNumberingOrder : public SphericalHarmonicsNumbering\n{\npublic:\n  SphericalHarmonicsNumberingOrder(Config &/*config*/) {}\n\n  virtual UInt parameterCount(UInt maxDegree, UInt minDegree) const override {return (maxDegree+1)*(maxDegree+1) - minDegree*minDegree;}\n  virtual void numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const override;\n};\n\n/***********************************************/\n\ninline void SphericalHarmonicsNumberingOrder::numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const\n{\n  Cnm.clear(); Cnm.resize(maxDegree+1);\n  Snm.clear(); Snm.resize(maxDegree+1);\n  for(UInt n=0; n<=maxDegree; n++)\n  {\n    Cnm[n].resize(n+1, NULLINDEX);\n    Snm[n].resize(n+1, NULLINDEX);\n  }\n\n  UInt idx = 0;\n  for(UInt n=minDegree; n<=maxDegree; n++)\n    Cnm[n][0] = idx++;\n  for(UInt m=1; m<=maxDegree; m++)\n    for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n    {\n      Cnm[n][m] = idx++;\n      Snm[n][m] = idx++;\n    }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumberingOrderNonAlternating.h",
    "content": "/***********************************************/\n/**\n* @file sphericalHarmonicsNumberingOrderNonAlternating.h\n*\n* @brief Numbering schema of spherical harmonics coefficients.\n* Numbering order by order with cnm, snm non-alternating:\n* c20, c30, c40, [...], c21, c31, c41, [...], s21, s31, s41, [...]\n* @see SphericalHarmonicsNumbering\n*\n* @author Judith Schall\n* @date 2009-08-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SPHERICALHARMONICSNUMBERINGORDERNONALTERNATING__\n#define __GROOPS_SPHERICALHARMONICSNUMBERINGORDERNONALTERNATING__\n\n#ifdef DOCSTRING_SphericalHarmonicsNumbering\nstatic const char *docstringSphericalHarmonicsNumberingOrderNonAlternating = R\"(\n\\subsection{OrderNonAlternating}\nNumbering order by order with cnm, snm non-alternating:\n\\[ c20, c30, c40, \\ldots, c21, c31, c41, \\ldots, s21, s31, s41, \\]\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Numbering schema of spherical harmonics coefficients.\n* @ingroup sphericalHarmonicsNumberingGroup\n* Numbering order by order with cnm, snm non-alternating:\n* c20, c30, c40, [...], c21, c31, c41, [...], s21, s31, s41, [...]\n* @see SphericalHarmonicsNumbering */\nclass SphericalHarmonicsNumberingOrderNonAlternating : public SphericalHarmonicsNumbering\n{\npublic:\n  SphericalHarmonicsNumberingOrderNonAlternating(Config &/*config*/) {}\n\n  virtual UInt parameterCount(UInt maxDegree, UInt minDegree) const override {return (maxDegree+1)*(maxDegree+1) - minDegree*minDegree;}\n  virtual void numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const override;\n};\n\n/***********************************************/\n\ninline void SphericalHarmonicsNumberingOrderNonAlternating::numbering(UInt maxDegree, UInt minDegree, std::vector<std::vector<UInt>> &Cnm, std::vector<std::vector<UInt>> &Snm) const\n{\n  Cnm.resize(0); Cnm.resize(maxDegree+1);\n  Snm.resize(0); Snm.resize(maxDegree+1);\n  for(UInt n=0; n<=maxDegree; n++)\n  {\n    Cnm[n].resize(n+1, NULLINDEX);\n    Snm[n].resize(n+1, NULLINDEX);\n  }\n\n  UInt idx = 0;\n  for(UInt n=minDegree; n<=maxDegree; n++)\n    Cnm[n][0] = idx++;\n  for(UInt m=1; m<=maxDegree; m++)\n  {\n    for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      Cnm[n][m] = idx++;\n    for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n      Snm[n][m] = idx++;\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/thermosphere/thermosphere.cpp",
    "content": "/***********************************************/\n/**\n* @file thermosphere.cpp\n*\n* @brief Density, temperature and velocity.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2020-02-20\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Thermosphere\n\n#include \"base/import.h\"\n#include \"external/hwm/hwm.h\"\n#include \"config/configRegister.h\"\n#include \"classes/thermosphere/thermosphereJB2008.h\"\n#include \"classes/thermosphere/thermosphereNRLMSIS2.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Thermosphere, \"thermosphereType\",\n                      ThermosphereJB2008,\n                      ThermosphereNRLMSIS2)\n\nGROOPS_READCONFIG_CLASS(Thermosphere, \"thermosphereType\")\n\n/***********************************************/\n\nThermospherePtr Thermosphere::create(Config &config, const std::string &name)\n{\n  try\n  {\n    ThermospherePtr thermosphere;\n    std::string choice;\n\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"density, temperature and velocity\");\n    if(readConfigChoiceElement(config, \"jb2008\",  choice, \"Jacchia-Bowman 2008 Empirical Thermospheric Density Model\"))\n      thermosphere = ThermospherePtr(new ThermosphereJB2008(config));\n    if(readConfigChoiceElement(config, \"nrlmsis2\",  choice, \"NRLMSIS 2.0 Empirical Thermospheric Density Model\"))\n      thermosphere = ThermospherePtr(new ThermosphereNRLMSIS2(config));\n    endChoice(config);\n\n    return thermosphere;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Thermosphere::getIndices(const MiscValuesArc &arc, const Time &time, Bool interpolate)\n{\n  try\n  {\n    const Time timeUt = timeGPS2UTC(time);\n    auto iter = std::upper_bound(arc.begin(), arc.end(), timeUt, [](const Time &time, auto &epoch) {return time < epoch.time;});\n    if((iter == arc.begin()) || (iter == arc.end()))\n      throw(Exception(\"Cannot find index for \"+time.dateTimeStr()));\n    iter--;\n    if(!interpolate)\n      return iter->values;\n    const Double t = (timeUt - iter->time).seconds()/((iter+1)->time - iter->time).seconds();\n    return (1-t) * iter->values + t * (iter+1)->values;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d Thermosphere::wind(const Time &time, const Vector3d &position) const\n{\n  try\n  {\n#ifdef GROOPS_DISABLE_HWM14\n    return Vector3d();\n#else\n    if(fileNameHwm14Path.empty())\n      return Vector3d();\n\n    Double ap2 = -1;\n    if(magnetic3hAp.size())\n      ap2 = getIndices(magnetic3hAp, time, FALSE)(0);\n\n    Ellipsoid ellipsoid;\n    Angle     lon, lat;\n    Double    height;\n    ellipsoid(position, lon, lat, height);\n\n    UInt   year, month, day, hour, min;\n    Double seconds;\n    const Time timeUt = timeGPS2UTC(time);\n    timeUt.date(year, month, day, hour, min, seconds);\n    F77Int yyddd = ((year<2000) ? (year-1900) : (year-2000))*1000 + timeUt.dayOfYear();\n\n#ifdef _WIN32\n    _putenv_s(\"HWMPATH\", fileNameHwm14Path.c_str());\n#else\n    setenv(\"HWMPATH\", fileNameHwm14Path.c_str(), 1);\n#endif\n    F77Float outf[2];\n    const F77Float ap[] = {0.0, static_cast<F77Float>(ap2)};\n    hwm(yyddd, 3600*hour+60*min+seconds, height*0.001, lat*RAD2DEG, std::fmod(lon*RAD2DEG+360, 360), 0, 0., 0., ap, outf);\n#ifndef _WIN32\n    unsetenv(\"HWMPATH\");\n#endif\n\n    return localNorthEastUp(position, ellipsoid).transform(Vector3d(outf[0], outf[1], 0));\n#endif // #ifndef GROOPS_DISABLE_HWM14\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/thermosphere/thermosphere.h",
    "content": "/***********************************************/\n/**\n* @file thermosphere.h\n*\n* @brief Density, temperature and velocity.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-02-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_THERMOSPHERE__\n#define __GROOPS_THERMOSPHERE__\n\n// Latex documentation\n#ifdef DOCSTRING_Thermosphere\nstatic const char *docstringThermosphere = R\"(\n\\section{Thermosphere}\\label{thermosphereType}\nThis class provides functions for calculating the density, temperature and velocity\nin the thermosphere.\nThe wind is computed by HWM14 model if \\config{hwm14DataDirectory} is provided.\nA quiet thermosphere is assumed if \\config{inputfileMagnetic3hAp} is not given.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n\n/**\n* @defgroup thermosphereGroup Thermosphere\n* @brief Density, temperature and velocity.\n* @ingroup classesGroup\n* The interface is given by @ref Thermosphere. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Thermosphere;\ntypedef std::shared_ptr<Thermosphere> ThermospherePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Density, temperature and velocity.\n* An Instance of this class can be created by @ref readConfig. */\nclass Thermosphere\n{\npublic:\n  /// Destructor.\n  virtual ~Thermosphere() {}\n\n  /** @brief Thermospheric state.\n  * @param time GPS time\n  * @param position in TRF [m]\n  * @param[out] density  [kg/m^3]\n  * @param[out] temperature  [K]\n  * @param[out] velocity wind in TRF [m/s] */\n  virtual void state(const Time &time, const Vector3d &position, Double &density, Double &temperature, Vector3d &velocity) const = 0;\n\n  /** @brief creates an derived instance of this class. */\n  static ThermospherePtr create(Config &config, const std::string &name);\n\nprotected:\n  FileName fileNameHwm14Path;\n\n  static Vector getIndices(const MiscValuesArc &arc, const Time &time, Bool interpolate);\n\n  MiscValuesArc magnetic3hAp;\n  Vector3d wind(const Time &time, const Vector3d &position) const;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Thermosphere.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a thermosphere is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] thermosphere Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Thermosphere */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ThermospherePtr &thermosphere, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/thermosphere/thermosphereJB2008.h",
    "content": "/***********************************************/\n/**\n* @file thermosphereJB2008.h\n*\n* @brief Density, temperature and velocity.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-02-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_THERMOSPHEREJB2008__\n#define __GROOPS_THERMOSPHEREJB2008__\n\n// Latex documentation\n#ifdef DOCSTRING_Thermosphere\nstatic const char *docstringThermosphereJB2008 = R\"(\n\\subsection{JB2008}\nThermosphere parameters from the JB2008 model:\n\nBowman, B. R., Tobiska, W. K., Marcos, F. A., Huang, C. Y., Lin, C. S., Burke, W. J. (2008).\nA new empirical thermospheric density model JB2008 using new solar and geomagnetic indices.\n In AIAA/AAS Astrodynamics Specialist Conference and Exhibit. \\url{https://doi.org/10.2514/6.2008-6438}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/planets.h\"\n#include \"external/jb2008/jb2008.h\"\n#include \"inputOutput/file.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Density, temperature and velocity.\n* @ingroup thermosphereGroup\n* @see Thermosphere */\nclass ThermosphereJB2008 : public Thermosphere\n{\n  MiscValuesArc solarFSMY;\n  MiscValuesArc dtc;\n\npublic:\n  inline ThermosphereJB2008(Config &config);\n\n  inline void state(const Time &time, const Vector3d &position, Double &density, Double &temperature, Vector3d &velocity) const override;\n};\n\n/***********************************************/\n\ninline ThermosphereJB2008::ThermosphereJB2008(Config &config)\n{\n  try\n  {\n    FileName fileNameSolfsmy, fileNameDtc, fileNameMagnetic3hAp;\n\n    readConfig(config, \"inputfileSolfsmy\",      fileNameSolfsmy,      Config::MUSTSET,  \"{groopsDataDir}/thermosphere/jb2008/SOLFSMY.TXT\",   \"solar indices\");\n    readConfig(config, \"inputfileDtc\",          fileNameDtc,          Config::MUSTSET,  \"{groopsDataDir}/thermosphere/jb2008/DTCFILE.TXT\",   \"\");\n    readConfig(config, \"inputfileMagnetic3hAp\", fileNameMagnetic3hAp, Config::OPTIONAL, \"{groopsDataDir}/thermosphere/hwm14/apActivity.txt\", \"indicies for wind model\");\n    readConfig(config, \"hwm14DataDirectory\",    fileNameHwm14Path,    Config::OPTIONAL, \"{groopsDataDir}/thermosphere/hwm14\",                \"directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_JB2008\n    throw(Exception(\"Compiled without JB2008 sources\"));\n#endif\n\n    if(!fileNameSolfsmy.empty())\n    {\n      InFile file(fileNameSolfsmy);\n      std::string line;\n      for(UInt i=0; i<4; i++)\n        std::getline(file, line);\n      while(std::getline(file, line))\n      {\n        std::stringstream ss(line);\n        UInt        year, day;\n        Double      jd, f, fb, s, sb, m, mb, y, yb;\n        std::string flags;\n        ss>>year>>day>>jd>>f>>fb>>s>>sb>>m>>mb>>y>>yb>>flags;\n\n        MiscValuesEpoch epoch(8);\n        epoch.time = mjd2time(jd-2400001);\n        epoch.values = {f, fb, s, sb, m, mb, y, yb};\n        solarFSMY.push_back(epoch);\n      }\n    }\n\n    if(!fileNameDtc.empty())\n    {\n      InFile file(fileNameDtc);\n      std::string line;\n      while(std::getline(file, line))\n      {\n        std::stringstream ss(line);\n        std::string tag;\n        UInt        year, day;\n        ss>>tag>>year>>day;\n        for(UInt i=0; i<24; i++)\n        {\n          MiscValuesEpoch epoch(1);\n          epoch.time = date2time(year, 1, 1, i, 0, 0.) + mjd2time(day-1.);\n          ss>>epoch.values(0);\n          dtc.push_back(epoch);\n        }\n      }\n    }\n\n    magnetic3hAp = InstrumentFile::read(fileNameMagnetic3hAp);\n#ifdef GROOPS_DISABLE_HWM14\n    if(!fileNameHwm14Path.empty())\n      logWarningOnce<<\"Compiled without HWM14 wind model sources -> thermospheric wind is not calculated\"<<Log::endl;\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ThermosphereJB2008::state(const Time &time, const Vector3d &position, Double &density, Double &temperature, Vector3d &velocity) const\n{\n  try\n  {\n#ifndef GROOPS_DISABLE_JB2008\n    Ellipsoid ellipsoid;\n    Angle     lon, lat;\n    Double    height;\n    ellipsoid(position, lon, lat, height);\n\n    // use 5 day lag for y10 for jb2008\n    const Vector index5 = getIndices(solarFSMY, time - mjd2time(5), FALSE);\n    const Double Y10  = index5(6);\n    const Double Y10B = index5(7);\n\n    // use 2 day lag for m10 for jb2008\n    const Vector index2 = getIndices(solarFSMY, time - mjd2time(2), FALSE);\n    const Double M10  = index2(4);\n    const Double M10B = index2(5);\n\n    // use 1 day lag for f10 and s10 for jb2008\n    const Vector index1 = getIndices(solarFSMY, time - mjd2time(1), FALSE);\n    const Double F10  = index1(0);\n    const Double F10B = index1(1);\n    const Double S10  = index1(2);\n    const Double S10B = index1(3);\n\n    // read geomagnetic storm dtc value\n    const Double dstdtc = getIndices(dtc, time, TRUE)(0);\n\n    const Vector3d sunPos = Planets::positionSun(time);\n\n    F77Double sun[2] = {sunPos.lambda(), sunPos.phi()};\n    F77Double pos[3] = {std::fmod(Double(lon+Planets::gmst(timeGPS2UTC(time)))+2*PI, 2*PI), lat, height*1e-3};\n    F77Double temp[2], rho;\n\n    jb2008(time.mjd(), sun, pos, F10, F10B, S10, S10B, M10, M10B, Y10, Y10B, dstdtc, temp, rho);\n\n    density     = rho;\n    temperature = temp[1];\n    velocity    = wind(time, position);\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/thermosphere/thermosphereNRLMSIS2.h",
    "content": "/***********************************************/\n/**\n* @file thermosphereNRLMSIS2.h\n*\n* @brief Density, temperature and velocity.\n*\n* @author Sandro Krauss\n* @date 2021-03-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_THERMOSPHERENRLMSIS2__\n#define __GROOPS_THERMOSPHERENRLMSIS2__\n\n// Latex documentation\n#ifdef DOCSTRING_Thermosphere\nstatic const char *docstringThermosphereNRLMSIS2 = R\"(\n\\subsection{NRLMSIS2}\nThermosphere parameters from the NRLMSIS2 model:\n\nEmmert J.D, D.P.Drob, J.M. Picone, et al. (2020), NRLMSIS 2.0: A whole-atmosphere empirical\nmodel of temperature and neutral species densities. Earth and Space Science, Volume 8, 3\n\\url{https://doi.org/10.1029/2020EA001321}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/planets.h\"\n#include \"external/nrlmsis2/nrlmsis2.h\"\n#include \"inputOutput/file.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Density, temperature and velocity.\n* @ingroup thermosphereGroup\n* @see Thermosphere */\nclass ThermosphereNRLMSIS2 : public Thermosphere\n{\n  MiscValuesArc msisData;\n\npublic:\n  inline ThermosphereNRLMSIS2(Config &config);\n\n  inline void state(const Time &time, const Vector3d &position, Double &density, Double &temperature, Vector3d &velocity) const override;\n};\n\n/***********************************************/\n\ninline ThermosphereNRLMSIS2::ThermosphereNRLMSIS2(Config &config)\n{\n  try\n  {\n    FileName fileNameMsis, fileNameParm, fileNameMagnetic3hAp;\n\n    readConfig(config, \"inputfileMsis\",            fileNameMsis,         Config::MUSTSET,  \"{groopsDataDir}/thermosphere/nrlmsis2/inputMSIS.txt\", \"input NRLMSIS 2.0\");\n    readConfig(config, \"inputfileModelParameters\", fileNameParm,         Config::MUSTSET,  \"{groopsDataDir}/thermosphere/nrlmsis2/msis20.parm\",   \"path to msis20.parm file\");\n    readConfig(config, \"inputfileMagnetic3hAp\",    fileNameMagnetic3hAp, Config::OPTIONAL, \"{groopsDataDir}/thermosphere/hwm14/apActivity.txt\",   \"indicies for wind model\");\n    readConfig(config, \"hwm14DataDirectory\",       fileNameHwm14Path,    Config::OPTIONAL, \"{groopsDataDir}/thermosphere/hwm14\",                  \"directory containing dwm07b104i.dat, gd2qd.dat, hwm123114.bin\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_NRLMSIS\n    throw(Exception(\"Compiled without NRLMSIS sources\"));\n#endif\n\n    msisData = InstrumentFile::read(fileNameMsis);\n    msisinitWrapper(fileNameParm.directory(), fileNameParm.stripDirectory());\n\n    magnetic3hAp = InstrumentFile::read(fileNameMagnetic3hAp);\n#ifdef GROOPS_DISABLE_HWM14\n    if(!fileNameHwm14Path.empty())\n      logWarningOnce<<\"Compiled without HWM14 wind model sources -> thermospheric wind is not calculated\"<<Log::endl;\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void ThermosphereNRLMSIS2::state(const Time &time, const Vector3d &position, Double &density, Double &temperature, Vector3d &velocity) const\n{\n  try\n  {\n#ifndef GROOPS_DISABLE_NRLMSIS\n    Ellipsoid ellipsoid;\n    Angle     lon, lat;\n    Double    height;\n    ellipsoid(position, lon, lat, height);\n    if(lon < 0)\n      lon += Angle(2*PI);\n\n    // get data\n    const Time     timeUt      =  timeGPS2UTC(time);\n    const Vector   index       =  getIndices(msisData, time, FALSE);\n    const F77Float dailyF107   =  static_cast<F77Float>(getIndices(msisData, time-mjd2time(1), FALSE)(1));\n    const F77Float averageF107 =  static_cast<F77Float>(index(0));\n    const F77Float aps[7]      = {static_cast<F77Float>(index(2)),\n                                  static_cast<F77Float>(index(3)),\n                                  static_cast<F77Float>(index(4)),\n                                  static_cast<F77Float>(index(5)),\n                                  static_cast<F77Float>(index(6)),\n                                  static_cast<F77Float>(index(7)),\n                                  static_cast<F77Float>(index(8))};\n\n    // CALL NRLMSIS 2.0 model\n    F77Float tempAlt = 0, tempExo = 0, rho[10] = {0.};\n    msiscalcWrapper(timeUt.dayOfYear()+timeUt.mjdMod(), time.mjdMod()*86400, height*1e-3, lat*RAD2DEG, lon*RAD2DEG, averageF107, dailyF107, aps, tempAlt, rho, tempExo);\n    density     = rho[0];\n    temperature = tempAlt;\n    velocity    = wind(time, position);\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/tides/tides.cpp",
    "content": "/***********************************************/\n/**\n* @file tides.cpp\n*\n* @brief tidal forces.\n* astronomic tides, earth tides, ocean tides, pole tides ...\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-12-13.\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_Tides\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/configRegister.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tidesAstronomical.h\"\n#include \"classes/tides/tidesEarth.h\"\n#include \"classes/tides/tidesDoodsonHarmonic.h\"\n#include \"classes/tides/tidesPole.h\"\n#include \"classes/tides/tidesOceanPole.h\"\n#include \"classes/tides/tidesCentrifugal.h\"\n#include \"classes/tides/tidesSolidMoon.h\"\n#include \"classes/tides/tidesGroup.h\"\n#include \"classes/tides/tides.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Tides, \"tidesType\",\n                      TidesAstronomical,\n                      TidesEarth,\n                      TidesPole,\n                      TidesOceanPole,\n                      TidesDoodsonHarmonic,\n                      TidesCentrifugal,\n                      TidesSolidMoon,\n                      TidesGroup)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(Tides, \"tidesType\")\n\n/***********************************************/\n\nTides::Tides(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"tidal forces\"))\n    {\n      renameDeprecatedChoice(config, type, \"poleTide2010\",      \"poleTide\",      date2time(2020, 8, 24));\n      renameDeprecatedChoice(config, type, \"poleOceanTide2010\", \"oceanPoleTide\", date2time(2020, 8, 24));\n      renameDeprecatedChoice(config, type, \"moonTide\",          \"solidMoonTide\", date2time(2020, 8, 24));\n\n      if(readConfigChoiceElement(config, \"astronomicalTide\",    type, \"direct tides from sun, moon and planets\"))\n        tides.push_back(new TidesAstronomical(config));\n      if(readConfigChoiceElement(config, \"earthTide\",           type, \"solid earth tides\"))\n        tides.push_back(new TidesEarth(config));\n      if(readConfigChoiceElement(config, \"doodsonHarmonicTide\", type, \"tides with harmonic representation, e.g. ocean tides\"))\n        tides.push_back(new TidesDoodsonHarmonic(config));\n      if(readConfigChoiceElement(config, \"poleTide\",            type, \"centrifugal effect of polar motion\"))\n        tides.push_back(new TidesPole(config));\n      if(readConfigChoiceElement(config, \"oceanPoleTide\",       type, \"The ocean pole tide is generated by the centrifugal effect of polar motion on the oceans\"))\n        tides.push_back(new TidesOceanPole(config));\n      if(readConfigChoiceElement(config, \"centrifugal\",         type, \"Current centrifugal force from Earth rotation\"))\n        tides.push_back(new TidesCentrifugal(config));\n      if(readConfigChoiceElement(config, \"solidMoonTide\",       type, \"solid moon tides (at moon)\"))\n        tides.push_back(new TidesSolidMoon(config));\n      if(readConfigChoiceElement(config, \"group\",               type, \"group tides\"))\n        tides.push_back(new TidesGroup(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    };\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTides::~Tides()\n{\n  for(UInt i=0; i<tides.size(); i++)\n    delete tides.at(i);\n}\n\n/***********************************************/\n\nDouble Tides::potential(const Time &timeGPS, const Vector3d &point,\n                        const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    Double V = 0;\n    for(UInt i=0; i<tides.size(); i++)\n      V += tides.at(i)->potential(timeGPS, point, rotEarth, rotation, ephemerides);\n    return V;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Tides::radialGradient(const Time &timeGPS, const Vector3d &point,\n                             const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    Double dVdr = 0;\n    for(UInt i=0; i<tides.size(); i++)\n      dVdr += tides.at(i)->radialGradient(timeGPS, point, rotEarth, rotation, ephemerides);\n    return dVdr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d Tides::acceleration(const Time &timeGPS, const Vector3d &point,\n                             const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    Vector3d g;\n    for(UInt i=0; i<tides.size(); i++)\n      g += tides.at(i)->gravity(timeGPS, point, rotEarth, rotation, ephemerides);\n    return g;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTensor3d Tides::gradient(const Time &timeGPS, const Vector3d &point,\n                         const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    Tensor3d T;\n    for(UInt i=0; i<tides.size(); i++)\n      T += tides.at(i)->gravityGradient(timeGPS, point, rotEarth, rotation, ephemerides);\n    return T;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d Tides::deformation(const Time &timeGPS, const Vector3d &point,\n                            const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                            Double gravity, const Vector &hn, const Vector &ln) const\n{\n  try\n  {\n    Vector3d pos;\n    for(UInt i=0; i<tides.size(); i++)\n      pos += tides.at(i)->deformation(timeGPS, point, rotEarth, rotation, ephemerides, gravity, hn, ln);\n    return pos;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Tides::deformation(const std::vector<Time> &timeGPS, const std::vector<Vector3d> &point,\n                        const std::vector<Rotary3d> &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                        const std::vector<Double> &gravity, const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    for(UInt i=0; i<tides.size(); i++)\n      tides.at(i)->deformation(timeGPS, point, rotEarth, rotation, ephemerides, gravity, hn, ln, disp);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics Tides::sphericalHarmonics(const Time &timeGPS, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                             UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    if(tides.empty())\n      return SphericalHarmonics();\n\n    SphericalHarmonics harmonics = tides.at(0)->sphericalHarmonics(timeGPS, rotEarth, rotation, ephemerides, maxDegree, minDegree, GM, R);\n    for(UInt i=1; i<tides.size(); i++)\n      harmonics += tides.at(i)->sphericalHarmonics(timeGPS, rotEarth, rotation, ephemerides, maxDegree, minDegree, GM, R);\n    return harmonics;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nDouble TidesBase::potential(const Time &time, const Vector3d &point,\n                            const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  return sphericalHarmonics(time, rotEarth, rotation, ephemerides).potential(point);\n}\n\n/***********************************************/\n\nDouble TidesBase::radialGradient(const Time &time, const Vector3d &point,\n                                 const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  return sphericalHarmonics(time, rotEarth, rotation, ephemerides).radialGradient(point);\n}\n\n/***********************************************/\n\nVector3d TidesBase::gravity(const Time &time, const Vector3d &point,\n                            const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  return sphericalHarmonics(time, rotEarth, rotation, ephemerides).gravity(point);\n}\n\n/***********************************************/\n\nTensor3d TidesBase::gravityGradient(const Time &time, const Vector3d &point,\n                                    const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  return sphericalHarmonics(time, rotEarth, rotation, ephemerides).gravityGradient(point);\n}\n\n/***********************************************/\n\nVector3d TidesBase::deformation(const Time &time, const Vector3d &point,\n                                const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                Double gravity, const Vector &hn, const Vector &ln) const\n{\n  return sphericalHarmonics(time, rotEarth, rotation, ephemerides).deformation(point, gravity, hn, ln);\n}\n\n/***********************************************/\n\nvoid TidesBase::deformation (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                             EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                             std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    if((time.size()==0) || (point.size()==0))\n      return;\n\n    SphericalHarmonics harm = sphericalHarmonics(time.at(0), rotEarth.at(0), rotation, ephemerides);\n    Matrix A = deformationMatrix(point, gravity, hn, ln, harm.GM(), harm.R(), harm.maxDegree());\n    for(UInt i=0; i<time.size(); i++)\n    {\n      Vector Ax = A * sphericalHarmonics(time.at(i), rotEarth.at(i), rotation, ephemerides).x();\n      for(UInt k=0; k<point.size(); k++)\n      {\n        disp.at(k).at(i).x() += Ax(3*k+0);\n        disp.at(k).at(i).y() += Ax(3*k+1);\n        disp.at(k).at(i).z() += Ax(3*k+2);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix TidesBase::deformationMatrix(const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                    const Vector &hn, const Vector &ln, Double GM, Double R, UInt maxDegree)\n{\n  try\n  {\n    Matrix A(3*point.size(), (maxDegree+1)*(maxDegree+1));\n\n    for(UInt k=0; k<point.size(); k++)\n    {\n      Vector3d up = normalize(point.at(k));\n\n      Matrix Cnm, Snm;\n      SphericalHarmonics::CnmSnm(1/R * point.at(k), maxDegree+1, Cnm, Snm);\n\n      // 0. order\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        Double wm0 = sqrt((n+1.)*(n+1.));\n        Double wp1 = sqrt((n+1.)*(n+2.)) / sqrt(2.0);\n        Double Cm0 = wm0*Cnm(n+1,0);\n        Double Cp1 = wp1*Cnm(n+1,1); Double Sp1 = wp1*Snm(n+1,1);\n\n        Double   Vn     = GM/R * Cnm(n,0);\n        Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(-2*Cp1, -2*Sp1, -2*Cm0);\n\n\n        Vector3d disp = (hn(n)/gravity.at(k)*Vn) * up // vertical\n                      + (ln(n)/gravity.at(k)) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n        A(3*k+0, n*n) = disp.x();\n        A(3*k+1, n*n) = disp.y();\n        A(3*k+2, n*n) = disp.z();\n      }\n\n      // other orders\n      for(UInt m=1; m<=maxDegree; m++)\n        for(UInt n=m; n<=maxDegree; n++)\n        {\n          Double wm1 = sqrt((n-m+1.)*(n-m+2.)) * ((m==1) ? sqrt(2.0) : 1.0);\n          Double wm0 = sqrt((n-m+1.)*(n+m+1.));\n          Double wp1 = sqrt((n+m+1.)*(n+m+2.));\n          Double Cm1 = wm1*Cnm(n+1,m-1);  Double Sm1 = wm1*Snm(n+1,m-1);\n          Double Cm0 = wm0*Cnm(n+1,m  );  Double Sm0 = wm0*Snm(n+1,m  );\n          Double Cp1 = wp1*Cnm(n+1,m+1);  Double Sp1 = wp1*Snm(n+1,m+1);\n\n          Double   Vn     = GM/R * Cnm(n,m);\n          Vector3d gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Cm1-Cp1, -Sm1-Sp1, -2*Cm0);\n\n          Vector3d disp = (hn(n)/gravity.at(k)*Vn) * up // vertical\n                        + (ln(n)/gravity.at(k)) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          A(3*k+0, n*n+2*m-1) = disp.x();\n          A(3*k+1, n*n+2*m-1) = disp.y();\n          A(3*k+2, n*n+2*m-1) = disp.z();\n\n          Vn     = GM/R * Snm(n,m);\n          gradVn = GM/(2*R) * sqrt((2*n+1.)/(2*n+3.)) * Vector3d(Sm1-Sp1, Cm1+Cp1, -2*Sm0);\n\n          disp = (hn(n)/gravity.at(k)*Vn) * up // vertical\n               + (ln(n)/gravity.at(k)) * (gradVn-inner(gradVn,up)*up); // horizontal\n\n          A(3*k+0, n*n+2*m) = disp.x();\n          A(3*k+1, n*n+2*m) = disp.y();\n          A(3*k+2, n*n+2*m) = disp.z();\n        }\n    } // for(k=point)\n\n    return A;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tides.h",
    "content": "/***********************************************/\n/**\n* @file tides.h\n*\n* @brief Tidal forces.\n* Astronomic tides, earth tides, ocean tides, pole tides and so on.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-12-13.\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDES__\n#define __GROOPS_TIDES__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTides = R\"(\n\\section{Tides}\\label{tidesType}\nThis class computes functionals of the time depending tide potential,\ne.g potential, acceleration or gravity gradients.\n\nIf several instances of the class are given the results are summed up.\nBefore summation every single result is multiplicated by a \\config{factor}.\nTo get the difference between two ocean tide models you must choose one factor by 1\nand the other by -1. To get the mean of two models just set each factor to 0.5.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/**\n* @defgroup tidesGroup Tides\n* @brief Tidal forces.\n* @ingroup classesGroup\n* The interface is given by @ref Tides. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Tides;\nclass TidesBase;\ntypedef std::shared_ptr<Tides> TidesPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Tidal forces.\n* Astronomic tides, earth tides, ocean tides, pole tides and so on.\n* An Instance of this class can be created by @ref readConfig. */\nclass Tides\n{\n  std::vector<TidesBase*> tides;\n\npublic:\n  /// Constructor.\n  Tides(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~Tides();\n\n  /** @brief Tidal potential.\n  * @param timeGPS point in time (GPS)\n  * @param point Computation point in TRF [m].\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides ephemerides of sun and moon.\n  * @return Potential [@f$m^2/s^2@f$] */\n  Double potential(const Time &timeGPS, const Vector3d &point,\n                   const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n\n  /** @brief Radial derivative of tidal potential.\n  * @param timeGPS point in time (GPS)\n  * @param point Computation point in TRF [m].\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides ephemerides of sun and moon.\n  * @return Radial derivative of tidal potential [@f$m/s^2@f$]\n  */\n  Double radialGradient(const Time &timeGPS, const Vector3d &point,\n                        const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n\n  /** @brief Tidal acceleration.\n  * @param timeGPS point in time (GPS)\n  * @param point Computation point in TRF [m].\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides ephemerides of sun and moon.\n  * @return acceleration in TRF [@f$m/s^2@f$] */\n  Vector3d acceleration(const Time &timeGPS, const Vector3d &point,\n                        const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n\n  /** @brief Tidal acceleration gradient.\n  * @param timeGPS point in time (GPS)\n  * @param point Computation point in TRF [m].\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides ephemerides of sun and moon.\n  * @return gradient in TRF [@f$1/s^2@f$] */\n  Tensor3d gradient(const Time &timeGPS, const Vector3d &point,\n                    const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n\n  /** @brief Deformation.\n  * Direct tides creates no deformation.\n  * Earth tides and polar tides do not use @a gravity, @a hn, @a ln.\n  * @param timeGPS point in time (GPS)\n  * @param point station position in TRF [m]\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides ephemerides of sun and moon.\n  * @param gravity local gravity at station [m/s**2]\n  * @param hn vertical load love numbers\n  * @param ln horizontal load love numbers\n  * @return deformation in TRF [m] */\n  Vector3d deformation(const Time &timeGPS, const Vector3d &point,\n                       const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                       Double gravity, const Vector &hn, const Vector &ln) const;\n\n  /** @brief Deformation.\n  * Direct tides creates no deformation.\n  * Earth tides and polar tides do not use @a gravity, @a hn, @a ln.\n  * @param timeGPS point in time (GPS)\n  * @param point station position in TRF [m]\n  * @param rotEarth CRF -> TRF\n  * @param rotation need for computation of polar motion.\n  * @param ephemerides ephemerides of sun and moon.\n  * @param gravity local gravity at station [m/s**2]\n  * @param hn vertical load love numbers\n  * @param ln horizontal load love numbers\n  * @param[out] disp series (stationSize x TimeSize) in TRF [m] */\n  void deformation(const std::vector<Time> &timeGPS, const std::vector<Vector3d> &point,\n                   const std::vector<Rotary3d> &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                   const std::vector<Double> &gravity, const Vector &hn, const Vector &ln, std::vector<std::vector<Vector3d>> &disp) const;\n\n  /** @brief Tides in terms of SphericalHarmonics.\n  * Only gravitational potential of mass distributions of the Earth is considered\n  * (Earth tides, ocean tides, without planetary tides). */\n  SphericalHarmonics sphericalHarmonics(const Time &timeGPS, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const;\n\n  /** @brief creates an derived instance of this class. */\n  static TidesPtr create(Config &config, const std::string &name) {return TidesPtr(new Tides(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Tides.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a class without effect is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] tides Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Tides */\ntemplate<> Bool readConfig(Config &config, const std::string &name, TidesPtr &tides, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass TidesBase\n{\npublic:\n  virtual ~TidesBase() {}\n\n  virtual Double   potential      (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n  virtual Double   radialGradient (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n  virtual Vector3d gravity        (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n  virtual Tensor3d gravityGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const;\n  virtual Vector3d deformation    (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                   Double gravity, const Vector &hn, const Vector &ln) const;\n  virtual void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                                   EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                                   std::vector<std::vector<Vector3d>> &disp) const;\n\n  static Matrix deformationMatrix (const std::vector<Vector3d> &point, const std::vector<Double> &gravity,\n                                   const Vector &hn, const Vector &ln, Double GM, Double R, UInt maxDegree);\n\n  virtual SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                                UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0) const = 0;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_TIDES__ */\n"
  },
  {
    "path": "source/classes/tides/tidesAstronomical.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesAstronomical.cpp\n*\n* @brief Astronomical tides\n* Computed from planetary ephemerides.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-01-24\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/tides/tidesAstronomical.h\"\n\n/***********************************************/\n\nTidesAstronomical::TidesAstronomical(Config &config)\n{\n  try\n  {\n    Double c20;\n\n    readConfig(config, \"useMoon\",    useMoon,    Config::DEFAULT,  \"1\", \"TGP of moon\");\n    readConfig(config, \"useSun\",     useSun,     Config::DEFAULT,  \"1\", \"TGP of sun\");\n    readConfig(config, \"usePlanets\", usePlanets, Config::DEFAULT,  \"1\", \"TGP of planets\");\n    readConfig(config, \"useEarth\",   useEarth,   Config::DEFAULT,  \"1\", \"TGP of Earth\");\n    readConfig(config, \"c20Earth\",   c20,        Config::DEFAULT,  \"-4.84166854896119e-04\", \"J2 flattening of the Earth\");\n    readConfig(config, \"factor\",     factor,     Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    // Earth with flattening\n    // ---------------------\n    Matrix cnm(3,Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(3,Matrix::TRIANGULAR, Matrix::LOWER);\n    cnm(2,0) = c20;\n    j2earth = SphericalHarmonics(GM_Earth, R_Earth, cnm, snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\n// Tidal potential at point2 of a body with point mass GM at point1\n// relative to coordinate center\nDouble TidesAstronomical::directTidePotential(Double GM, const Vector3d &point1, const Vector3d &point2) const\n{\n  Vector3d diff = point2-point1;\n  Double r1  = point1.r();\n  Double r12 = diff.r();\n\n  return -GM*(1/r1 + 1/(r1*r1*r1)*inner(point1,point2) - 1/r12);\n}\n\n/************************************************/\n\nDouble TidesAstronomical::directTideRadialGradient(Double /*GM*/, const Vector3d &/*point1*/, const Vector3d &/*point2*/) const\n{\n  try\n  {\n    throw(Exception(\"not yet implemented\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\n// Tidal acceleration at point2 of a body with point mass GM at point1\n// relative to coordinate center\nVector3d TidesAstronomical::directTideAcceleration(Double GM, const Vector3d &point1, const Vector3d &point2) const\n{\n  Vector3d diff = point2-point1;\n  Double   r12  = diff.r();\n  Double   r1   = point1.r();\n\n  return -GM/(r12*r12*r12)*diff - GM/(r1*r1*r1)*point1;\n}\n\n/************************************************/\n\n// Tidal acceleration gradient at point2 of a body with point mass GM at point1\n// relative to coordinate center\nTensor3d TidesAstronomical::directTideGradient(Double GM, const Vector3d &point1, const Vector3d &point2) const\n{\n  Vector3d diff = point2-point1;\n  Double   r12 = diff.r();\n  Double   r3  = pow(r12,3);\n  Double   r5  = pow(r12,5);\n  Tensor3d T;\n  T.xx() = 3*GM*diff.x()*diff.x()/r5 - 1/r3;\n  T.yy() = 3*GM*diff.y()*diff.y()/r5 - 1/r3;\n  T.zz() = 3*GM*diff.y()*diff.y()/r5 - 1/r3;\n  T.xy() = 3*GM*diff.x()*diff.y()/r5;\n  T.xz() = 3*GM*diff.x()*diff.z()/r5;\n  T.yz() = 3*GM*diff.y()*diff.z()/r5;\n\n  return T;\n}\n\n/************************************************/\n\nDouble TidesAstronomical::potential(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector3d posSat = rotEarth.inverseRotate(point);\n\n    Double V = 0;\n    if(useEarth && (ephemerides->origin() != Ephemerides::EARTH))\n      V += directTidePotential(GM_Sun,  ephemerides->position(time, Ephemerides::EARTH), posSat);\n    if(useMoon && (ephemerides->origin() != Ephemerides::MOON))\n      V += directTidePotential(GM_Moon, ephemerides->position(time, Ephemerides::MOON),  posSat);\n    if(useSun && (ephemerides->origin() != Ephemerides::SUN))\n      V += directTidePotential(GM_Sun,  ephemerides->position(time, Ephemerides::SUN),   posSat);\n    if(usePlanets)\n    {\n      V += directTidePotential(GM_MERCURY, ephemerides->position(time, Ephemerides::MERCURY), posSat)  // Mercury\n         + directTidePotential(GM_VENUS  , ephemerides->position(time, Ephemerides::VENUS),   posSat)  // Venus\n         + directTidePotential(GM_MARS   , ephemerides->position(time, Ephemerides::MARS),    posSat)  // Mars\n         + directTidePotential(GM_JUPITER, ephemerides->position(time, Ephemerides::JUPITER), posSat)  // Jupiter\n         + directTidePotential(GM_SATURN , ephemerides->position(time, Ephemerides::SATURN),  posSat); // Saturn\n    }\n    return factor*V;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\nDouble TidesAstronomical::radialGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector3d posSat = rotEarth.inverseRotate(point);\n\n    Double dVdr = 0;\n    if(useEarth && (ephemerides->origin() != Ephemerides::EARTH))\n      dVdr += directTideRadialGradient(GM_Sun,  ephemerides->position(time, Ephemerides::EARTH), posSat);\n    if(useMoon && (ephemerides->origin() != Ephemerides::MOON))\n      dVdr += directTideRadialGradient(GM_Moon, ephemerides->position(time, Ephemerides::MOON),  posSat);\n    if(useSun && (ephemerides->origin() != Ephemerides::SUN))\n      dVdr += directTideRadialGradient(GM_Sun,  ephemerides->position(time, Ephemerides::SUN),   posSat);\n    if(usePlanets)\n    {\n      dVdr += directTideRadialGradient(GM_MERCURY, ephemerides->position(time, Ephemerides::MERCURY), posSat)  // Mercury\n            + directTideRadialGradient(GM_VENUS  , ephemerides->position(time, Ephemerides::VENUS),   posSat)  // Venus\n            + directTideRadialGradient(GM_MARS   , ephemerides->position(time, Ephemerides::MARS),    posSat)  // Mars\n            + directTideRadialGradient(GM_JUPITER, ephemerides->position(time, Ephemerides::JUPITER), posSat)  // Jupiter\n            + directTideRadialGradient(GM_SATURN , ephemerides->position(time, Ephemerides::SATURN),  posSat); // Saturn\n    }\n    return factor*dVdr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d TidesAstronomical::gravity(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector3d posSat = rotEarth.inverseRotate(point);\n\n    Vector3d g;\n    if(useEarth && (ephemerides->origin() != Ephemerides::EARTH))\n    {\n      Vector3d posEarth = ephemerides->position(time, Ephemerides::EARTH);\n      g += directTideAcceleration(GM_Earth, posEarth, posSat);\n      g += j2earth.gravity(posSat-posEarth) - j2earth.gravity(-posEarth);\n    }\n    if(useMoon && (ephemerides->origin() != Ephemerides::MOON))\n    {\n      Vector3d posMoon = ephemerides->position(time, Ephemerides::MOON);\n      g += directTideAcceleration(GM_Moon, posMoon, posSat);\n      if(ephemerides->origin() == Ephemerides::EARTH)\n        g -= GM_Moon/GM_Earth * j2earth.gravity(-posMoon);\n    }\n    if(useSun && (ephemerides->origin() != Ephemerides::SUN))\n      g += directTideAcceleration(GM_Sun,  ephemerides->position(time, Ephemerides::SUN), posSat);\n    if(usePlanets)\n    {\n      g += directTideAcceleration(GM_MERCURY, ephemerides->position(time, Ephemerides::MERCURY), posSat)  // Mercury\n         + directTideAcceleration(GM_VENUS  , ephemerides->position(time, Ephemerides::VENUS),   posSat)  // Venus\n         + directTideAcceleration(GM_MARS   , ephemerides->position(time, Ephemerides::MARS),    posSat)  // Mars\n         + directTideAcceleration(GM_JUPITER, ephemerides->position(time, Ephemerides::JUPITER), posSat)  // Jupiter\n         + directTideAcceleration(GM_SATURN , ephemerides->position(time, Ephemerides::SATURN),  posSat); // Saturn\n    }\n    return factor*rotEarth.rotate(g);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTensor3d TidesAstronomical::gravityGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector3d posSat = rotEarth.inverseRotate(point);\n\n    Tensor3d T;\n    if(useEarth && (ephemerides->origin() != Ephemerides::EARTH))\n      T += directTideGradient(GM_Sun,  ephemerides->position(time, Ephemerides::EARTH), posSat);\n    if(useMoon && (ephemerides->origin() != Ephemerides::MOON))\n      T += directTideGradient(GM_Moon, ephemerides->position(time, Ephemerides::MOON),  posSat);\n    if(useSun && (ephemerides->origin() != Ephemerides::SUN))\n      T += directTideGradient(GM_Sun,  ephemerides->position(time, Ephemerides::SUN),   posSat);\n    if(usePlanets)\n    {\n      T += directTideGradient(GM_MERCURY, ephemerides->position(time, Ephemerides::MERCURY), posSat)  // Mercury\n         + directTideGradient(GM_VENUS  , ephemerides->position(time, Ephemerides::VENUS),   posSat)  // Venus\n         + directTideGradient(GM_MARS   , ephemerides->position(time, Ephemerides::MARS),    posSat)  // Mars\n         + directTideGradient(GM_JUPITER, ephemerides->position(time, Ephemerides::JUPITER), posSat)  // Jupiter\n         + directTideGradient(GM_SATURN , ephemerides->position(time, Ephemerides::SATURN),  posSat); // Saturn\n    }\n    return factor*rotEarth.rotate(T);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d TidesAstronomical::deformation(const Time &/*time*/, const Vector3d &/*point*/, const Rotary3d &/*rotEarth*/,\n                                        EarthRotationPtr /*rotation*/, EphemeridesPtr /*ephemerides*/,\n                                        Double /*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/) const\n{\n  return Vector3d(0,0,0);\n}\n\n/***********************************************/\n\nvoid TidesAstronomical::deformation(const std::vector<Time> &/*time*/, const std::vector<Vector3d> &/*point*/, const std::vector<Rotary3d> &/*rotEarth*/,\n                              EarthRotationPtr /*rotation*/, EphemeridesPtr /*ephemerides*/, const std::vector<Double> &/*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/,\n                              std::vector<std::vector<Vector3d>> &/*disp*/) const\n{\n}\n\n/***********************************************/\n\nSphericalHarmonics TidesAstronomical::sphericalHarmonics(const Time &/*time*/, const Rotary3d &/*rotEarth*/, EarthRotationPtr /*rotation*/, EphemeridesPtr /*ephemerides*/,\n                                                         UInt /*maxDegree*/, UInt /*minDegree*/, Double /*GM*/, Double /*R*/) const\n{\n  // tide generating potential is not harmonic\n  return SphericalHarmonics();\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesAstronomical.h",
    "content": "/***********************************************/\n/**\n* @file tidesAstronomical.h\n*\n* @brief Astronomical tides\n* Computed from planetary ephemerides.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-01-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDESASTRONOMICAL__\n#define __GROOPS_TIDESASTRONOMICAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesAstronomical = R\"(\n\\subsection{AstronomicalTide}\\label{tidesType:astronomicalTide}\nThis class computes the tide generating potential (TGP) of sun, moon\nand planets (Mercury, Venus, Mars, Jupiter, Saturn).\nIt takes into account the flattening of the Earth (At the moment only at the acceleration level).\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n\n/***********************************************/\n\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Astronomical tides.\n* @ingroup tidesGroup\n* Computed from planetary ephemerids.\n* @see Tides */\nclass TidesAstronomical : public TidesBase\n{\n  Double             factor;\n  Bool               useEarth, useMoon, useSun, usePlanets;\n  SphericalHarmonics j2earth;\n\n  Double   directTidePotential     (Double GM, const Vector3d &point1, const Vector3d &point2) const;\n  Double   directTideRadialGradient(Double GM, const Vector3d &point1, const Vector3d &point2) const;\n  Vector3d directTideAcceleration  (Double GM, const Vector3d &point1, const Vector3d &point2) const;\n  Tensor3d directTideGradient      (Double GM, const Vector3d &point1, const Vector3d &point2) const;\n\npublic:\n  TidesAstronomical(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Double   radialGradient (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Vector3d gravity        (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Vector3d deformation    (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                           Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                           EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                           std::vector<std::vector<Vector3d>> &disp) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/tides/tidesCentrifugal.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesCentrifugal.cpp\n*\n* @brief Centrifugal force.\n* Actual centrifugal force computed from Earth rotation at given time.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-10-19\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/tides/tidesCentrifugal.h\"\n\n/***********************************************/\n\nTidesCentrifugal::TidesCentrifugal(Config &config)\n{\n  try\n  {\n    readConfig(config, \"factor\", factor, Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TidesCentrifugal::potential(const Time &time, const Vector3d &point, const Rotary3d &/*rotEarth*/, EarthRotationPtr rotation, EphemeridesPtr /*ephemerides*/) const\n{\n  Vector3d Omega = rotation->rotaryAxis((time==Time()) ? mjd2time(J2000) : time);\n  return factor * 0.5 * crossProduct(Omega, point).quadsum();\n}\n\n/***********************************************/\n\nDouble TidesCentrifugal::radialGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  // df/dr = df/dpoint * dpoint/dr\n  // with dpoint/dr = (1/norm(point))*point\n  return inner(gravity(time, point, rotEarth, rotation, ephemerides), point)/point.r();\n}\n\n/***********************************************/\n\nVector3d TidesCentrifugal::gravity(const Time &time, const Vector3d &point, const Rotary3d &/*rotEarth*/, EarthRotationPtr rotation, EphemeridesPtr /*ephemerides*/) const\n{\n  Vector3d Omega = rotation->rotaryAxis((time==Time()) ? mjd2time(J2000) : time);\n  return -factor * crossProduct(Omega, crossProduct(Omega, point));\n}\n\n/***********************************************/\n\nTensor3d TidesCentrifugal::gravityGradient(const Time &time, const Vector3d &/*point*/, const Rotary3d &/*rotEarth*/, EarthRotationPtr rotation, EphemeridesPtr /*ephemerides*/) const\n{\n  Vector3d Omega = rotation->rotaryAxis((time==Time()) ? mjd2time(J2000) : time);\n  Tensor3d T;\n  T.xx() = pow(Omega.y(),2)+pow(Omega.z(),2);\n  T.yy() = pow(Omega.x(),2)+pow(Omega.z(),2);\n  T.zz() = pow(Omega.x(),2)+pow(Omega.y(),2);\n  T.xy() = -Omega.x() * Omega.y();\n  T.xz() = -Omega.x() * Omega.z();\n  T.yz() = -Omega.y() * Omega.z();\n  return factor * T;\n}\n\n/***********************************************/\n\nVector3d TidesCentrifugal::deformation(const Time &/*time*/, const Vector3d &/*point*/, const Rotary3d &/*rotEarth*/, EarthRotationPtr /*earthRotation*/, EphemeridesPtr /*ephemerides*/,\n                                       Double /*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/) const\n{\n  return Vector3d(0,0,0);\n}\n\n/***********************************************/\n\nvoid TidesCentrifugal::deformation(const std::vector<Time> &/*time*/, const std::vector<Vector3d> &/*point*/, const std::vector<Rotary3d> &/*rotEarth*/,\n                                   EarthRotationPtr /*rotation*/, EphemeridesPtr /*ephemerides*/, const std::vector<Double> &/*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/,\n                                   std::vector<std::vector<Vector3d>> &/*disp*/) const\n{\n}\n\n/***********************************************/\n\nSphericalHarmonics TidesCentrifugal::sphericalHarmonics(const Time &/*time*/, const Rotary3d &/*rotEarth*/, EarthRotationPtr /*earthRotation*/, EphemeridesPtr /*ephemerides*/,\n                                                        UInt /*maxDegree*/, UInt /*minDegree*/, Double /*GM*/, Double /*R*/) const\n{\n  return SphericalHarmonics();\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesCentrifugal.h",
    "content": "/***********************************************/\n/**\n* @file tidesCentrifugal.h\n*\n* @brief Centrifugal force.\n* Actual centrifugal force computed from Earth rotation at given time.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-10-19\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDESCENTRIFUGAL__\n#define __GROOPS_TIDESCENTRIFUGAL__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesCentrifugal = R\"(\n\\subsection{Centrifugal}\\label{tidesType:centrifugal}\nComputes the centrifugal potential in a rotating system\n\\begin{equation}\nV(\\M r, t) = \\frac{1}{2} (\\M\\omega(t)\\times\\M r)^2.\n\\end{equation}\nThe current rotation vector $\\M\\omega(t)$ is computed from the\n\\configClass{earthRotation}{earthRotationType}\nprovided by the calling program.\nThe computed result is multiplied with \\config{factor}.\n\nBe careful, the centrifugal potential is not harmonic.\nConvolution with a harmonic kernel (e.g. to compute gravity\nanomalies) is not meaningful.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Centrifugal force.\n* @ingroup tidesGroup\n* Actual centrifugal force computed from Earth rotation at given time.\n* @see Tides */\nclass TidesCentrifugal : public TidesBase\n{\n  Double factor;\n\npublic:\n  TidesCentrifugal(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Double   radialGradient (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Vector3d gravity        (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Vector3d deformation    (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                           Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                           EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                           std::vector<std::vector<Vector3d>> &disp) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/tides/tidesDoodsonHarmonic.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesDoodsonHarmonic.cpp\n*\n* @brief Ocean or atmospheric tides.\n* In terms of spherical harmonics.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @author Daniel Rieser\n* @date 2002-12-13.\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/doodson.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileAdmittance.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"classes/tides/tidesDoodsonHarmonic.h\"\n\n/***********************************************/\n\nTidesDoodsonHarmonic::TidesDoodsonHarmonic(Config &config)\n{\n  try\n  {\n    FileName    tidesName, admittanceName;\n    UInt        minDegree;\n    UInt        maxDegree = INFINITYDEGREE;\n    Double      factor;\n    std::vector<Doodson> selectDoodson;\n\n    renameDeprecatedConfig(config, \"inputfileOcean\", \"inputfileTides\", date2time(2020, 10, 2));\n\n    readConfig(config, \"inputfileTides\",      tidesName,      Config::MUSTSET,  \"{groopsDataDir}/tides/oceanTide_fes2022_n180_version20241110.dat\", \"\");\n    readConfig(config, \"inputfileAdmittance\", admittanceName, Config::OPTIONAL, \"{groopsDataDir}/tides/oceanTide_fes2022_admittance_linear_linear.txt\", \"interpolation of minor constituents\");\n    readConfig(config, \"selectDoodson\",       selectDoodson,  Config::OPTIONAL, \"\",    \"consider only these constituents, code number (e.g. 255.555) or darwin name (e.g. M2)\");\n    readConfig(config, \"minDegree\",           minDegree,      Config::DEFAULT,  \"2\",   \"\");\n    readConfig(config, \"maxDegree\",           maxDegree,      Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"nodeCorr\",            nCorr,          Config::DEFAULT,  \"0\",   \"nodal corrections: 0-no corr, 1-IHO, 2-Schureman\");\n    readConfig(config, \"factor\",              factor,         Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    // read tide file\n    // --------------------\n    DoodsonHarmonic d;\n    readFileDoodsonHarmonic(tidesName, d);\n    GM = d.GM;\n    R  = d.R;\n    cnmCos.resize(d.doodson.size());\n    snmCos.resize(d.doodson.size());\n    cnmSin.resize(d.doodson.size());\n    snmSin.resize(d.doodson.size());\n    for(UInt i=0; i<d.doodson.size(); i++)\n    {\n      SphericalHarmonics harmCos = SphericalHarmonics(d.GM, d.R, d.cnmCos.at(i), d.snmCos.at(i)).get(maxDegree, minDegree);\n      SphericalHarmonics harmSin = SphericalHarmonics(d.GM, d.R, d.cnmSin.at(i), d.snmSin.at(i)).get(maxDegree, minDegree);\n      cnmCos.at(i) = harmCos.cnm();\n      snmCos.at(i) = harmCos.snm();\n      cnmSin.at(i) = harmSin.cnm();\n      snmSin.at(i) = harmSin.snm();\n    }\n\n    // read admittace file\n    // -------------------\n    doodson    = d.doodson;\n    admittance = identityMatrix(d.doodson.size());\n    if(!admittanceName.empty())\n    {\n      Admittance admit;\n      readFileAdmittance(admittanceName, admit);\n      doodson    = admit.doodsonMinor;\n      admittance = admit.admittance;\n\n      for(UInt i=0; i<d.doodson.size(); i++)\n        if(admit.doodsonMajor.at(i) != d.doodson.at(i))\n          throw(Exception(\"different MajorTides in <\"+tidesName.str()+\"> and <\"+admittanceName.str()+\">\"));\n    }\n\n    // Matrix with Doodson multiplicators\n    doodsonMatrix = Doodson::matrix(doodson);\n\n    admittance *= factor;\n\n    // calculate only selected tides\n    // -----------------------------\n    if(selectDoodson.size()!=0)\n    {\n      std::vector<Bool> found(selectDoodson.size(), FALSE);\n      Matrix I(admittance.rows(), Matrix::SYMMETRIC);\n      for(UInt i=0; i<doodson.size(); i++)\n      {\n        Bool remove = TRUE;\n        for(UInt k=0; k<selectDoodson.size(); k++)\n          if(doodson.at(i) == selectDoodson.at(k))\n          {\n            found.at(k) = TRUE;\n            remove      = FALSE;\n            break;\n          }\n        if(remove)\n          admittance.column(i) *= 0.;\n      }\n      for(UInt k=0; k<selectDoodson.size(); k++)\n        if(!found.at(k))\n          logWarning<<selectDoodson.at(k).code()<<\" not found in admittance/tides\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix TidesDoodsonHarmonic::interpolationFactors(const Time &time) const\n{\n  try\n  {\n    Vector thetaf = doodsonMatrix * Doodson::arguments(time);\n    Matrix csMinor(thetaf.rows(), 2);\n\n    if(nCorr!=0) //apply nodal corrections here\n    {\n      Matrix fu = Doodson::nodeCorr(doodson, time, nCorr);\n      for(UInt i=0; i<thetaf.rows(); i++)\n      {\n        csMinor(i,0) = fu(i,0) * cos(thetaf(i)+fu(i,1));\n        csMinor(i,1) = fu(i,0) * sin(thetaf(i)+fu(i,1));\n      }\n    }\n    else\n    {\n      for(UInt i=0; i<thetaf.rows(); i++)\n      {\n        csMinor(i,0) = cos(thetaf(i));\n        csMinor(i,1) = sin(thetaf(i));\n      }\n    }\n\n    return ((admittance.size()) ? (admittance * csMinor) : csMinor);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics TidesDoodsonHarmonic::sphericalHarmonics(const Time &time, const Rotary3d &/*rotEarth*/, EarthRotationPtr /*rotation*/, EphemeridesPtr /*ephemerides*/, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    const Matrix csMajor = interpolationFactors(time);\n\n    Matrix cnm(cnmCos.at(0).rows(), Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(snmCos.at(0).rows(), Matrix::TRIANGULAR, Matrix::LOWER);\n    for(UInt i=0; i<csMajor.rows(); i++)\n    {\n      axpy(csMajor(i,0), cnmCos.at(i), cnm);\n      axpy(csMajor(i,1), cnmSin.at(i), cnm);\n      axpy(csMajor(i,0), snmCos.at(i), snm);\n      axpy(csMajor(i,1), snmSin.at(i), snm);\n    }\n    return SphericalHarmonics(this->GM, this->R, cnm, snm).get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesDoodsonHarmonic::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &/*rotEarth*/,\n                                       EarthRotationPtr /*rotation*/, EphemeridesPtr /*ephemerides*/,\n                                       const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                                       std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    if((time.size()==0) || (point.size()==0))\n      return;\n\n    Matrix A = deformationMatrix(point, gravity, hn, ln, GM, R, cnmCos.at(0).rows()-1);\n    std::vector<Matrix> xCos(cnmCos.size());\n    std::vector<Matrix> xSin(snmCos.size());\n    for(UInt i=0; i<xCos.size(); i++)\n    {\n      xCos.at(i) = A * SphericalHarmonics(GM, R, cnmCos.at(i), snmCos.at(i)).x();\n      xSin.at(i) = A * SphericalHarmonics(GM, R, cnmSin.at(i), snmSin.at(i)).x();\n    }\n\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      const Matrix csMajor = interpolationFactors(time.at(idEpoch));\n\n      Vector x(3*point.size());\n      for(UInt i=0; i<csMajor.rows(); i++)\n      {\n        axpy(csMajor(i,0), xCos.at(i), x);\n        axpy(csMajor(i,1), xSin.at(i), x);\n      }\n\n      for(UInt k=0; k<point.size(); k++)\n      {\n        disp.at(k).at(idEpoch).x() += x(3*k+0);\n        disp.at(k).at(idEpoch).y() += x(3*k+1);\n        disp.at(k).at(idEpoch).z() += x(3*k+2);\n      }\n    } // for(idEpoch)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesDoodsonHarmonic.h",
    "content": "/***********************************************/\n/**\n* @file tidesDoodsonHarmonic.h\n*\n* @brief Ocean tides.\n* In terms of spherical harmonics.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @author Daniel Rieser\n* @date 2002-12-13.\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDEDOODSONHARMONIC__\n#define __GROOPS_TIDEDOODSONHARMONIC__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesDoodsonHarmonic = R\"(\n\\subsection{DoodsonHarmonicTide}\\label{tidesType:doodsonHarmonicTide}\nThe time variable potential of ocean tides is given by a fourier expansion\n\\begin{equation}\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\Theta_f(t)) + V_f^s(\\M x)\\sin(\\Theta_f(t)),\n\\end{equation}\nwhere $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics expansions and are\nread from the file \\configFile{inputfileDoodsonHarmonic}{doodsonHarmonic}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\n$\\Theta_f(t)$ are the arguments of the tide constituents~$f$:\n\\begin{equation}\n\\Theta_f(t) = \\sum_{i=1}^6 n_f^i\\beta_i(t),\n\\end{equation}\nwhere $\\beta_i(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$)\nand $n_f^i$ are the Doodson multipliers for the term at frequency~$f$.\n\nThe major constituents given by \\configFile{inputfileDoodsonHarmonic}{doodsonHarmonic} can be used to\ninterpolate minor tidal constituents using the file \\configFile{inputfileAdmittance}{admittance}.\nThis file can be created with \\program{DoodsonHarmonicsCalculateAdmittance}.\n\nAfter the interpolation step a selection of the computed constituents can be\nchoosen by \\configClass{selectDoodson}{doodson}. Only these constiuents are considered for the results.\nIf no \\configClass{selectDoodson}{doodson} is set all constituents will be used. The constituents can\nbe coded as Doodson number (e.g. 255.555) or as names intoduced by Darwin (e.g. M2).\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/doodson.h\"\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Ocean tides.\n* @ingroup tidesGroup\n* In terms of spherical harmonics.\n* @see Tides */\nclass TidesDoodsonHarmonic : public TidesBase\n{\n  Double               GM, R;\n  std::vector<Matrix>  cnmCos, cnmSin;\n  std::vector<Matrix>  snmCos, snmSin;\n  std::vector<Doodson> doodson;\n  Matrix               doodsonMatrix;\n  Matrix               admittance;\n  UInt                 nCorr;\n\n  Matrix interpolationFactors(const Time &time) const;\n\npublic:\n  TidesDoodsonHarmonic(Config &config);\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n  void deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                   EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                   std::vector<std::vector<Vector3d>> &disp) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/tides/tidesEarth.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesEarth.cpp\n*\n* @brief Earth tides.\n* Following the IERS conventions.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-12-13\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/doodson.h\"\n#include \"config/config.h\"\n#include \"files/fileEarthTide.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tidesEarth.h\"\n\n/***********************************************/\n\nTidesEarth::TidesEarth(Config &config)\n{\n  try\n  {\n    FileName earthTidesName;\n    readConfig(config, \"inputfileEarthtide\",   earthTidesName,       Config::MUSTSET, \"{groopsDataDir}/tides/earthAnelastic2003.xml\", \"\");\n    readConfig(config, \"includePermanentTide\", includePermanentTide, Config::DEFAULT, \"0\",   \"results in FALSE: zero tide, TRUE: tide free gravity field\");\n    readConfig(config, \"factor\",               factor,               Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    readFileEarthTide(earthTidesName, kReal, kImag, kPlus, doodson20, doodson21, doodson22,\n                      ampIp20, ampOp20, ampIp21, ampOp21, amp22,\n                      h2_0, h2_2, l2_0, l2_2, l21_1, l22_1, h21_imag, l21_imag, h22_imag, l22_imag, h3, l3,\n                      deformationArg21, deformationArg20,\n                      dR21_ip, dR21_op, dR20_ip, dR20_op, dT21_ip, dT21_op, dT20_ip, dT20_op);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\n// Geopotential (IERS-Convetions 1996, S.40) Step 1\n// ------------------------------------------------\nvoid TidesEarth::earthCoefficients1(Double GM_third, const Vector3d &third, Matrix &cnm, Matrix &snm) const\n{\n  // Kugelflaechenfunktionen berechnen\n  Matrix Cnm, Snm;\n  SphericalHarmonics::CnmSnm(1./R_Earth * third, 3, Cnm, Snm);\n\n  Double factor = GM_third/GM_Earth;\n\n  // Formel (1)\n  for(UInt n=2; n<=3; n++)\n    for(UInt m=0; m<=n; m++)\n    {\n      cnm(n,m) += factor/(2.*n+1.) * (kReal(n,m) * Cnm(n,m) + kImag(n,m) * Snm(n,m));\n      snm(n,m) += factor/(2.*n+1.) * (kReal(n,m) * Snm(n,m) - kImag(n,m) * Cnm(n,m));\n    }\n\n  // Formel (4)\n  for(UInt m=0; m<=2; m++)\n  {\n    cnm(4,m) += kPlus(2,m)/5. * factor * Cnm(2,m);\n    snm(4,m) += kPlus(2,m)/5. * factor * Snm(2,m);\n  }\n}\n\n/***********************************************/\n\n// Geopotential (IERS-Convetions 1996, S.40) Step 2\n// ------------------------------------------------\nvoid TidesEarth::earthCoefficients2(const Time &time, Matrix &cnm, Matrix &snm) const\n{\n  Vector d = Doodson::arguments(time);\n\n  // Korrektion fuer c20\n  Vector thetaf = doodson20 * d;\n  for(UInt i=0; i<thetaf.rows(); i++)\n    cnm(2,0) += 1e-12 * (ampIp20(i) * cos(thetaf(i)) - ampOp20(i) * sin(thetaf(i)));\n\n  // Korrektion fur c21 und s21\n  thetaf = doodson21 * d;\n  for(UInt i=0; i<thetaf.rows(); i++)\n  {\n    cnm(2,1) += 1e-12 * (ampIp21(i) * sin(thetaf(i)) + ampOp21(i) * cos(thetaf(i)));\n    snm(2,1) += 1e-12 * (ampIp21(i) * cos(thetaf(i)) - ampOp21(i) * sin(thetaf(i)));\n  }\n\n  // Korrektion fur c22 und s22\n  thetaf = doodson22 * d;\n  for(UInt i=0; i<thetaf.rows(); i++)\n  {\n    cnm(2,2) +=  1e-12 * amp22(i) * cos(thetaf(i));\n    snm(2,2) += -1e-12 * amp22(i) * sin(thetaf(i));\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics TidesEarth::sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Matrix cnm(5, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(5, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    const Vector3d moon = rotEarth.rotate(ephemerides->position(time, Ephemerides::MOON));\n    const Vector3d sun  = rotEarth.rotate(ephemerides->position(time, Ephemerides::SUN));\n\n    earthCoefficients1(GM_Sun,  sun,  cnm, snm);\n    earthCoefficients1(GM_Moon, moon, cnm, snm);\n    earthCoefficients2(time, cnm, snm);\n\n    if(!includePermanentTide)\n      cnm(2,0) -= 4.4228e-8*(-0.31460)*kReal(2,0);  // Abzug Permanentgezeiten\n\n    return SphericalHarmonics(GM_Earth, R_Earth, factor*cnm, factor*snm).get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVector3d TidesEarth::deformation(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides,\n                                 Double /*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/) const\n{\n  try\n  {\n    if(!ephemerides)\n      throw(Exception(\"No ephemerides given\"));\n\n    Vector3d displacement; // the result\n\n    // local coordinate system\n    Double   lambda = point.lambda();\n    Double   phi    = point.phi();\n    Vector3d up     = normalize(point);\n    Vector3d east   = normalize(Vector3d(-up.y(), up.x(), 0.0));\n    Vector3d north  = crossProduct(up, east);\n\n    const Vector3d moon = rotEarth.rotate(ephemerides->position(time, Ephemerides::MOON));\n    const Vector3d sun  = rotEarth.rotate(ephemerides->position(time, Ephemerides::SUN));\n\n    // in-phase\n    // --------\n    Double h2 = h2_0 + h2_2*0.5*(3.*pow(sin(phi),2)-1.);\n    Double l2 = l2_0 + l2_2*0.5*(3.*pow(sin(phi),2)-1.);\n    displacement += deformationInPhase(GM_Sun,  sun,  point, h2, l2, h3, l3);\n    displacement += deformationInPhase(GM_Moon, moon, point, h2, l2, h3, l3);\n\n    // out-phase\n    // ---------\n    Double dUp    = 0;\n    Double dEast  = 0;\n    Double dNorth = 0;\n    deformationOutPhase(GM_Sun,  sun,  lambda, phi, dUp, dEast, dNorth);\n    deformationOutPhase(GM_Moon, moon, lambda, phi, dUp, dEast, dNorth);\n\n    // frequency dependent correction\n    // ------------------------------\n    Vector d = Doodson::arguments(time);\n\n    // diurnal band, equation (16)\n    Vector thetaf = deformationArg21 * d;\n    Double dUp21    = 0;\n    Double dEast21  = 0;\n    Double dNorth21 = 0;\n    for(UInt i=0; i<thetaf.rows(); i++)\n    {\n      Double cosf = cos(thetaf(i)+lambda);\n      Double sinf = sin(thetaf(i)+lambda);\n      dUp21    += dR21_ip(i)*sinf + dR21_op(i)*cosf;\n      dEast21  += dT21_ip(i)*cosf - dT21_op(i)*sinf;\n      dNorth21 += dT21_ip(i)*sinf + dT21_op(i)*cosf;\n    }\n    dUp21    *= sin(2*phi);\n    dEast21  *= sin(phi);\n    dNorth21 *= cos(2*phi);\n\n    // long periodic band, equation (17)\n    thetaf = deformationArg20 * d;\n    Double dUp20    = 0;\n    Double dNorth20 = 0;\n    for(UInt i=0; i<thetaf.rows(); i++)\n    {\n      Double cosf = cos(thetaf(i));\n      Double sinf = sin(thetaf(i));\n      dUp20    += dR20_ip(i)*cosf + dR20_op(i)*sinf;\n      dNorth20 += dT20_ip(i)*cosf + dT20_op(i)*sinf;\n    }\n    dUp20    *= 1.5*pow(sin(phi),2)-0.5;\n    dNorth20 *= sin(2*phi);\n\n    displacement += (dUp+dUp21+dUp20)*up + (dEast+dEast21)*east + (dNorth+dNorth21+dNorth20)*north;\n\n    return this->factor*displacement;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesEarth::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                             EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                             std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    for(UInt i=0; i<time.size(); i++)\n      for(UInt k=0; k<point.size(); k++)\n        disp.at(k).at(i) += deformation(time.at(i), point.at(k), rotEarth.at(i), rotation, ephemerides, gravity.at(k), hn, ln);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\nVector3d TidesEarth::deformationInPhase(Double GM_third, const Vector3d &third, const Vector3d &point, Double h2, Double l2, Double h3, Double l3) const\n{\n  Vector3d er = normalize(point);\n  Vector3d eR = third;\n  Double   R  = eR.normalize();\n  Double   rR = inner(eR,er);\n  Double   factor = GM_third/GM_Earth * R_Earth * pow(R_Earth/R,3);\n\n  // displacement due to degree 2 tides, (eq.9)\n  Vector3d displacement = factor * (h2*(1.5*rR*rR-0.5) * er + 3*l2*rR*(eR - rR*er));\n\n  // displacement due to degree 3 tides, (eq.10)\n  factor *= R_Earth/R;\n  displacement += factor * (h3*(2.5*pow(rR,3)-1.5*rR) * er + l3*(7.5*rR*rR-1.5)*(eR - rR*er));\n\n  return displacement;\n}\n\n/************************************************/\n\nvoid TidesEarth::deformationOutPhase(Double GM_third, const Vector3d &third, Double lambda, Double phi, Double &dUp, Double &dEast, Double &dNorth) const\n{\n  Matrix Pnm     = SphericalHarmonics::Pnm(third.theta(), 1.0, 2);\n  Double phij    = third.phi();\n  Double dlambda = lambda-third.lambda();\n  Double factor  = GM_third/GM_Earth * R_Earth * pow(R_Earth/third.r(),3);\n\n  // equation (12) and (13)\n  dNorth +=   -l21_1 * sin(phi) * sin(phi)  * factor * Pnm(2,1)*sqrt(3./5.)  * cos(dlambda)\n         - 0.5*l22_1 * sin(phi) * cos(phi)  * factor * Pnm(2,2)*sqrt(12./5.) * cos(2*dlambda);\n  dEast  +=    l21_1 * sin(phi) * cos(2*phi)* factor * Pnm(2,1)*sqrt(3./5.)  * sin(dlambda)\n         - 0.5*l22_1 * sin(phi) * cos(phi)  * factor * Pnm(2,2)*sqrt(12./5.) * sin(phi) * sin(2*dlambda);\n  // equation (14a) and (15a)\n  dUp    += -0.75 * h21_imag * factor * sin(2*phij)*sin(2*phi)    * sin(dlambda)\n         +  -0.75 * h22_imag * factor * pow(cos(phij)*cos(phi),2) * sin(2*dlambda);\n  // equation (14b) and (15b)\n  dNorth +=  -1.5 * l21_imag * factor * sin(2*phij)*cos(2*phi)      * sin(dlambda)\n         +   0.75 * l22_imag * factor * pow(cos(phij),2)*sin(2*phi) * sin(2*dlambda);\n  dEast  +=  -1.5 * l21_imag * factor * sin(2*phij)*sin(phi)        * cos(dlambda)\n         +  -0.75 * l22_imag * factor * pow(cos(phij),2)*2*cos(phi) * cos(2*dlambda);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesEarth.h",
    "content": "/***********************************************/\n/**\n* @file tidesEarth.h\n*\n* @brief Earth tides.\n* Following the IERS conventions.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-12-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDESEARTH__\n#define __GROOPS_TIDESEARTH__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesEarth = R\"(\n\\subsection{EarthTide}\\label{tidesType:earthTide}\nThis class computes the earth tide according to the IERS2003 conventions.\nThe values of solid Earth tide external potential Love numbers and\nthe frequency dependent corrections of these values are given in the file\n\\configFile{inputfileEarthtide}{earthTide}. The effect of the permanent tide is removed if\n\\config{includePermanentTide} is set to false.\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/matrix.h\"\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Earth tides.\n* @ingroup tidesGroup\n* Following the IERS conventions.\n* @see Tides */\nclass TidesEarth : public TidesBase\n{\n  Bool             includePermanentTide;\n  Matrix           kReal, kImag, kPlus;\n  Matrix           doodson20, doodson21, doodson22;\n  Vector           ampIp20, ampOp20;\n  Vector           ampIp21, ampOp21;\n  Vector           amp22;\n  Double           factor;\n\n  void  earthCoefficients1(Double GM_third, const Vector3d &third, Matrix &cnm, Matrix &snm) const;\n  void  earthCoefficients2(const Time &time, Matrix &cnm, Matrix &snm) const;\n\n  // deformation\n  Double h2_0, h2_2;\n  Double l2_0, l2_2;\n  Double l21_1;\n  Double l22_1;\n  Double h21_imag, l21_imag;\n  Double h22_imag, l22_imag;\n  Double h3, l3;\n  Matrix deformationArg21, deformationArg20;\n  Vector dR21_ip, dR21_op;\n  Vector dR20_ip, dR20_op;\n  Vector dT21_ip, dT21_op;\n  Vector dT20_ip, dT20_op;\n\n  Vector3d deformationInPhase (Double GM_third, const Vector3d &third, const Vector3d &point, Double h2, Double l2, Double h3, Double l3) const;\n  void     deformationOutPhase(Double GM_third, const Vector3d &third, Double lambda, Double phi, Double &dUp, Double &dEast, Double &dNorth) const;\n\n\npublic:\n  TidesEarth(Config &config);\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n  Vector3d deformation(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                       Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                       EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                       std::vector<std::vector<Vector3d>> &disp) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/tides/tidesGroup.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesGroup.cpp\n*\n* @brief Group.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-11-13\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileMeanPolarMotion.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/tides/tidesGroup.h\"\n\n/***********************************************/\n\nTidesGroup::TidesGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"tides\",  tides,  Config::DEFAULT, \"\", \"\");\n    readConfig(config, \"factor\", factor, Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nDouble TidesGroup::potential(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    return factor * tides->potential(time, point, rotEarth, rotation, ephemerides);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TidesGroup::radialGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    return factor * tides->radialGradient(time, point, rotEarth, rotation, ephemerides);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d TidesGroup::gravity(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    return factor * tides->acceleration(time, point, rotEarth, rotation, ephemerides);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTensor3d TidesGroup::gravityGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const\n{\n  try\n  {\n    return factor * tides->gradient(time, point, rotEarth, rotation, ephemerides);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d TidesGroup::deformation(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                 Double gravity, const Vector &hn, const Vector &ln) const\n{\n  try\n  {\n    return factor * tides->deformation(time, point, rotEarth, rotation, ephemerides, gravity, hn, ln);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesGroup::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                             EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                             std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    tides->deformation(time, point, rotEarth, rotation, ephemerides, gravity, hn, ln, disp);\n    if(factor != 1.)\n      for(auto &ds : disp)\n        for(auto &d : ds)\n          d *= factor;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics TidesGroup::sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                                  UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    return factor * tides->sphericalHarmonics(time, rotEarth, rotation, ephemerides, maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesGroup.h",
    "content": "/***********************************************/\n/**\n * @file tidesGroup.h\n *\n * @brief Group.\n * @see Tides\n *\n * @author Torsten Mayer-Guerr\n * @date 2023-11-13\n *\n */\n/***********************************************/\n\n#ifndef __GROOPS_TIDESGROUP__\n#define __GROOPS_TIDESGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesGroup = R\"(\n\\subsection{Group}\\label{tidesType:group}\nGroups a set of \\configClass{tides}{tidesType} and has no further effect itself.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Group.\n* @ingroup tidesGroup\n* @see Tides */\nclass TidesGroup : public TidesBase\n{\n  TidesPtr tides;\n  Double   factor;\n\npublic:\n  TidesGroup(Config &config);\n\n  Double   potential      (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Double   radialGradient (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Vector3d gravity        (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Tensor3d gravityGradient(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides) const override;\n  Vector3d deformation    (const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                           Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation    (const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                           EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                           std::vector<std::vector<Vector3d>> &disp) const override;\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/tides/tidesOceanPole.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesOceanPole.cpp\n*\n* @brief Ocean pole tide.\n* Pole tides is generated by the centrifugal effect of polar motion on the oceans.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-05-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileMeanPolarMotion.h\"\n#include \"files/fileOceanPoleTide.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/tides/tidesOceanPole.h\"\n\n/***********************************************/\n\nTidesOceanPole::TidesOceanPole(Config &config)\n{\n  try\n  {\n    FileName oceanPoleName, fileNameMeanPole;\n    UInt     minDegree;\n    UInt     maxDegree  = INFINITYDEGREE;\n    Double   factor;\n\n    readConfig(config, \"inputfileOceanPole\", oceanPoleName,    Config::MUSTSET,  \"{groopsDataDir}/tides/oceanPoleTide_desai2004.dat\", \"\");\n    readConfig(config, \"minDegree\",          minDegree,        Config::DEFAULT,  \"2\",      \"\");\n    readConfig(config, \"maxDegree\",          maxDegree,        Config::OPTIONAL, \"\",       \"\");\n    readConfig(config, \"gammaReal\",          gammaR,           Config::DEFAULT,  \"0.6870\", \"\");\n    readConfig(config, \"gammaImaginary\",     gammaI,           Config::DEFAULT,  \"0.0036\", \"\");\n    readConfig(config, \"inputfileMeanPole\",  fileNameMeanPole, Config::MUSTSET,  \"{groopsDataDir}/tides/secularPole2018.xml\", \"\");\n    readConfig(config, \"factor\",             factor,           Config::DEFAULT,  \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    // read ocean spherical harmonics\n    // ------------------------------\n    readFileOceanPoleTide(oceanPoleName, harmReal, harmImag);\n    harmReal = factor * harmReal.get(maxDegree, minDegree);\n    harmImag = factor * harmImag.get(maxDegree, minDegree);\n\n    // read mean pole tide model\n    // -------------------------\n    readFileMeanPolarMotion(fileNameMeanPole, meanPole);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesOceanPole::pole(const Time &time, EarthRotationPtr earthRotation, Double &m1, Double &m2) const\n{\n  try\n  {\n    Double xBar, yBar;\n    meanPole.compute(time, xBar, yBar);\n\n    // pole (IERS2010, eq. (7.24))\n    Double xp, yp, sp, deltaUT, LOD, X, Y, S;\n    earthRotation->earthOrientationParameter(time, xp, yp, sp, deltaUT, LOD, X, Y, S);\n    m1 =  (xp*RAD2DEG*3600 - xBar);\n    m2 = -(yp*RAD2DEG*3600 - yBar);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nSphericalHarmonics TidesOceanPole::sphericalHarmonics(const Time &time, const Rotary3d &/*rotEarth*/, EarthRotationPtr earthRotation, EphemeridesPtr /*ephemerides*/, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    Double m1, m2;\n    pole(time, earthRotation, m1, m2);\n\n    Matrix cnm  = harmReal.cnm() * ((m1*gammaR+m2*gammaI)*DEG2RAD/3600);\n    Matrix snm  = harmReal.snm() * ((m1*gammaR+m2*gammaI)*DEG2RAD/3600);\n           cnm += harmImag.cnm() * ((m2*gammaR-m1*gammaI)*DEG2RAD/3600);\n           snm += harmImag.snm() * ((m2*gammaR-m1*gammaI)*DEG2RAD/3600);\n\n    return SphericalHarmonics(harmReal.GM(), harmReal.R(), cnm, snm).get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesOceanPole::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &/*rotEarth*/,\n                                 EarthRotationPtr rotation, EphemeridesPtr /*ephemerides*/, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                                 std::vector< std::vector<Vector3d> > &disp) const\n{\n  try\n  {\n    if((time.size()==0) || (point.size()==0))\n      return;\n\n    Matrix A = deformationMatrix(point, gravity, hn, ln, harmReal.GM(), harmReal.R(), harmReal.maxDegree());\n    Vector xReal = A * harmReal.x();\n    Vector xImag = A * harmImag.x();\n\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      Double m1, m2;\n      pole(time.at(idEpoch), rotation, m1, m2);\n      Vector x =  xReal * ((m1*gammaR+m2*gammaI)*DEG2RAD/3600) + xImag * ((m2*gammaR-m1*gammaI)*DEG2RAD/3600);\n\n      for(UInt k=0; k<point.size(); k++)\n      {\n        disp.at(k).at(idEpoch).x() += x(3*k+0);\n        disp.at(k).at(idEpoch).y() += x(3*k+1);\n        disp.at(k).at(idEpoch).z() += x(3*k+2);\n      }\n    } // for(idEpoch)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesOceanPole.h",
    "content": "/***********************************************/\n/**\n* @file tidesOceanPole.h\n*\n* @brief Ocean pole tide.\n* Pole tides is generated by the centrifugal effect of polar motion on the oceans.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-05-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDESOCEANPOLE__\n#define __GROOPS_TIDESOCEANPOLE__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesOceanPole = R\"(\n\\subsection{OceanPoleTide}\\label{tidesType:oceanPoleTide}\nThe ocean pole tide is generated by the centrifugal effect of polar motion on the oceans.\nThe potential coefficients of this effect is given by\nIERS2003 conventions are given by\n\\begin{equation}\n\\begin{Bmatrix}\n\\Delta c_{nm}  \\\\\n\\Delta s_{nm}\n\\end{Bmatrix}=\n\\begin{Bmatrix}\nc_{nm}^R  \\\\\ns_{nm}^R\n\\end{Bmatrix}\n(m_1\\gamma^R+m_2\\gamma^I)+\n\\begin{Bmatrix}\nc_{nm}^I  \\\\\ns_{nm}^I\n\\end{Bmatrix}\n(m_2\\gamma^R-m_1\\gamma^I)\n\\end{equation}\nwhere the coefficients are read from file \\configFile{inputfileOceanPole}{oceanPoleTide},\n$\\gamma=\\gamma^R+i\\gamma^I$ is given by \\config{gammaReal} and\n\\config{gammaImaginary} and $(m_1,m_2)$ are the wobble variables in radians.\nThey are related to the polar motion variables $(x_p,y_p)$ according to\n\\begin{equation}\n\\begin{split}\nm_1 &=  (x_p - \\bar{x}_p), \\\\\nm_2 &= -(y_p - \\bar{y}_p),\n\\end{split}\n\\end{equation}\nThe mean pole $(\\bar{x}_p, \\bar{y}_p)$ is approximated by a polynomial\nread from \\configFile{inputfileMeanPole}{meanPolarMotion}.\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileMeanPolarMotion.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Ocean pole tide.\n* @ingroup tidesGroup\n* Pole tides is generated by the centrifugal effect of polar motion on the oceans.\n* @see Tides */\nclass TidesOceanPole : public TidesBase\n{\n  Double              gammaR,    gammaI;\n  SphericalHarmonics  harmReal, harmImag;\n  MeanPolarMotion     meanPole;\n\n  void pole(const Time &time, EarthRotationPtr rotation, Double &m1, Double &m2) const;\n\npublic:\n  TidesOceanPole(Config &config);\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n  void deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                   EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                   std::vector<std::vector<Vector3d>> &disp) const override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_TIDES__ */\n"
  },
  {
    "path": "source/classes/tides/tidesPole.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesPole.cpp\n*\n* @brief Centrifugal effect of polar motion.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-05-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileMeanPolarMotion.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/tides/tidesPole.h\"\n\n/***********************************************/\n\nTidesPole::TidesPole(Config &config)\n{\n  try\n  {\n    FileName fileNameMeanPole;\n\n    readConfig(config, \"scale\",                  scale,                  Config::DEFAULT, \"1.333e-9\", \"\");\n    readConfig(config, \"outPhase\",               outPhase,               Config::DEFAULT, \"0.0115\",   \"\");\n    readConfig(config, \"inputfileMeanPole\",      fileNameMeanPole,       Config::MUSTSET, \"{groopsDataDir}/tides/secularPole2018.xml\", \"\");\n    readConfig(config, \"horizontalDisplacement\", horizontalDisplacement, Config::DEFAULT, \"0.009\",    \"[m]\");\n    readConfig(config, \"verticalDisplacement\",   verticalDisplacement,   Config::DEFAULT, \"0.033\",    \"[m]\");\n    readConfig(config, \"factor\",                 factor,                 Config::DEFAULT, \"1.0\",      \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n\n    readFileMeanPolarMotion(fileNameMeanPole, meanPole);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesPole::pole(const Time &time, EarthRotationPtr earthRotation, Double &m1, Double &m2) const\n{\n  try\n  {\n    Double xBar, yBar;\n    meanPole.compute(time, xBar, yBar);\n\n    // pole (IERS2010, eq. (7.24))\n    Double xp, yp, sp, deltaUT, LOD, X, Y, S;\n    earthRotation->earthOrientationParameter(time, xp, yp, sp, deltaUT, LOD, X, Y, S);\n    m1 =  (xp*RAD2DEG*3600 - xBar);\n    m2 = -(yp*RAD2DEG*3600 - yBar);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nSphericalHarmonics TidesPole::sphericalHarmonics(const Time &time, const Rotary3d &/*rotEarth*/, EarthRotationPtr earthRotation, EphemeridesPtr /*ephemerides*/,\n                                                 UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    Double m1, m2;\n    pole(time, earthRotation, m1, m2);\n\n    Matrix cnm(3, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(3, Matrix::TRIANGULAR, Matrix::LOWER);\n    cnm(2,1) = -factor * scale * (m1 + outPhase*m2);\n    snm(2,1) = -factor * scale * (m2 - outPhase*m1);\n\n    return SphericalHarmonics(GM_Earth, R_Earth, cnm, snm).get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d TidesPole::deformation(const Time &time, const Vector3d &point, const Rotary3d &/*rotEarth*/, EarthRotationPtr earthRotation, EphemeridesPtr /*ephemerides*/,\n                                Double /*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/) const\n{\n  try\n  {\n    Double m1, m2;\n    pole(time, earthRotation, m1, m2);\n\n    Angle lambda = point.lambda();\n    Angle theta  = point.theta();\n\n    Vector3d disp(horizontalDisplacement*cos(2.*theta)*(m1*cos(lambda)+m2*sin(lambda)),  // north\n                  horizontalDisplacement*cos(theta)   *(m1*sin(lambda)-m2*cos(lambda)),  // east\n                 -verticalDisplacement  *sin(2.*theta)*(m1*cos(lambda)+m2*sin(lambda))); // up\n\n    return factor * localNorthEastUp(point).transform(disp);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TidesPole::deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &/*rotEarth*/,\n                            EarthRotationPtr rotation, EphemeridesPtr /*ephemerides*/, const std::vector<Double> &/*gravity*/, const Vector &/*hn*/, const Vector &/*ln*/,\n                            std::vector<std::vector<Vector3d>> &disp) const\n{\n  try\n  {\n    for(UInt i=0; i<time.size(); i++)\n    {\n      Double m1, m2;\n      pole(time.at(i), rotation, m1, m2);\n\n      for(UInt k=0; k<point.size(); k++)\n      {\n        Angle lambda = point.at(k).lambda();\n        Angle theta  = point.at(k).theta();\n\n        Vector3d displ(horizontalDisplacement*cos(2.*theta)*(m1*cos(lambda)+m2*sin(lambda)),  // north\n                       horizontalDisplacement*cos(theta)   *(m1*sin(lambda)-m2*cos(lambda)),  // east\n                      -verticalDisplacement  *sin(2.*theta)*(m1*cos(lambda)+m2*sin(lambda))); // down\n\n        disp.at(k).at(i) += factor * localNorthEastUp(point.at(k)).transform(displ);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesPole.h",
    "content": "/***********************************************/\n/**\n* @file tidesPole.h\n*\n* @brief Centrifugal effect of polar motion.\n* @see Tides\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-05-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIDESPOLE__\n#define __GROOPS_TIDESPOLE__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesPole = R\"(\n\\subsection{PoleTide}\\label{tidesType:poleTide}\nThe potential coefficients of the solid Earth pole tide according to the\nIERS2003 conventions are given by\n\\begin{equation}\n\\begin{split}\n\\Delta c_{21} &= s\\cdot(m_1 + o\\cdot m_2), \\\\\n\\Delta s_{21} &= s\\cdot(m_2 - o\\cdot m_1),\n\\end{split}\n\\end{equation}\nwith $s$ is the \\config{scale}, $o$ is the \\config{outPhase} and\n$(m_1,m_2)$ are the wobble variables in seconds of arc.\nThey are related to the polar motion variables $(x_p,y_p)$ according to\n\\begin{equation}\n\\begin{split}\nm_1 &=  (x_p - \\bar{x}_p), \\\\\nm_2 &= -(y_p - \\bar{y}_p),\n\\end{split}\n\\end{equation}\nThe mean pole $(\\bar{x}_p, \\bar{y}_p)$ is approximated by a polynomial\nread from \\configFile{inputfileMeanPole}{meanPolarMotion}.\n\nThe displacment is calculated with\n\\begin{equation}\n\\begin{split}\nS_r          &= -v\\sin2\\vartheta(m_1\\cos\\lambda+m_2\\sin\\lambda),\\\\\nS_\\vartheta &= -h\\cos2\\vartheta(m_1\\cos\\lambda+m_2\\sin\\lambda),\\\\\nS_\\lambda   &=  h\\cos\\vartheta(m_1\\sin\\lambda-m_2\\cos\\lambda),\n\\end{split}\n\\end{equation}\nwhere $h$ is the \\config{horizontalDisplacement}\nand $v$ is the \\config{verticalDisplacement}.\n\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileMeanPolarMotion.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Centrifugal effect of polar motion.\n* @ingroup tidesGroup\n* @see Tides */\nclass TidesPole : public TidesBase\n{\n  Double          scale,     outPhase;\n  Double          horizontalDisplacement, verticalDisplacement;\n  Double          factor;\n  MeanPolarMotion meanPole;\n\n  void pole(const Time &time, EarthRotationPtr rotation, Double &m1, Double &m2) const;\n\npublic:\n  TidesPole(Config &config);\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n  Vector3d deformation(const Time &time, const Vector3d &point, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                       Double gravity, const Vector &hn, const Vector &ln) const override;\n  void     deformation(const std::vector<Time> &time, const std::vector<Vector3d> &point, const std::vector<Rotary3d> &rotEarth,\n                       EarthRotationPtr rotation, EphemeridesPtr ephemerides, const std::vector<Double> &gravity, const Vector &hn, const Vector &ln,\n                       std::vector<std::vector<Vector3d>> &disp) const override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS_TIDES__ */\n"
  },
  {
    "path": "source/classes/tides/tidesSolidMoon.cpp",
    "content": "/***********************************************/\n/**\n* @file tidesSolidMoon.cpp\n*\n* @brief Solid moon tides.\n* @see Tides\n*\n* @author Beate Klinger\n* @date 2013-xx-xx\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tidesSolidMoon.h\"\n\n/***********************************************/\n\nTidesSolidMoon::TidesSolidMoon(Config &config)\n{\n  try\n  {\n    readConfig(config, \"k20\",    kReal20, Config::DEFAULT,  \"0.0213\", \"\");\n    readConfig(config, \"k30\",    kReal30, Config::DEFAULT,  \"0.0\",    \"\");\n    readConfig(config, \"factor\", factor,  Config::DEFAULT,  \"1.0\",    \"the result is multiplied by this factor, set -1 to subtract the field\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\n// Geopotential (IERS-Convetions 2010) Step 1\n// ------------------------------------------------\nvoid TidesSolidMoon::moonCoefficients1(Double GM_third, const Vector3d &third, Matrix &cnm, Matrix &snm) const\n{\n  // Kugelflaechenfunktionen berechnen\n  Matrix Cnm, Snm;\n  SphericalHarmonics::CnmSnm(1./R_Moon * third, 3, Cnm, Snm);\n\n  Double factor1 = GM_third/GM_Moon;\n  Double kReal = 0.0;\n\n  // Formel (1)\n  for(UInt n=2; n<=3; n++)\n    for(UInt m=0; m<=0; m++)\n    {\n      if (n == 2)\n        kReal = kReal20;\n      if (n == 3)\n        kReal = kReal30;\n\n      // nur Realteil berücksichtigt, kein Imaginärteil\n      cnm(n,m) += factor1/(2.*n+1.) * (kReal * Cnm(n,m));\n      snm(n,m) += factor1/(2.*n+1.) * (kReal * Snm(n,m));\n    }\n}\n\n/***********************************************/\n\nSphericalHarmonics TidesSolidMoon::sphericalHarmonics(const Time &time, const Rotary3d &rotMoon, EarthRotationPtr /*rotation*/, EphemeridesPtr ephemerides, UInt maxDegree, UInt minDegree, Double GM, Double R) const\n{\n  try\n  {\n    Matrix cnm(5, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(5, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    const Vector3d posMoon = ephemerides->position(time, Ephemerides::MOON);\n    moonCoefficients1(GM_Sun,   rotMoon.rotate(ephemerides->position(time, Ephemerides::SUN)   - posMoon), cnm, snm);\n    moonCoefficients1(GM_Earth, rotMoon.rotate(ephemerides->position(time, Ephemerides::EARTH) - posMoon), cnm, snm);\n\n    return SphericalHarmonics(GM_Moon, R_Moon, factor*cnm, factor*snm).get(maxDegree, minDegree, GM, R);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/tides/tidesSolidMoon.h",
    "content": "/***********************************************/\n/**\n* @file tidesSolidMoon.h\n*\n* @brief Solid moon tides.\n* @see Tides\n*\n* @author Beate Klinger\n* @date 2013-xx-xx\n*\n*/\n/***********************************************/\n\n\n#ifndef __GROOPS_TIDESSOLIDMOON__\n#define __GROOPS_TIDESSOLIDMOON__\n\n// Latex documentation\n#ifdef DOCSTRING_Tides\nstatic const char *docstringTidesSolidMoon = R\"(\n\\subsection{SolidMoonTide}\nThis class computes the solid moon tide according to the IERS2010 conventions.\nThe values of solid Moon tide external potential Love numbers are given and\nthere are no frequency dependent corrections of these values.\nThe computed result is multiplied with \\config{factor}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/matrix.h\"\n#include \"classes/tides/tides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Solid moon tides.\n* @ingroup tidesGroup\n* @see Tides */\nclass TidesSolidMoon : public TidesBase\n{\n  Double kReal20;\n  Double kReal30;\n  Double factor;\n\n  void moonCoefficients1(Double GM_third, const Vector3d &third, Matrix &cnm, Matrix &snm) const;\n\npublic:\n  TidesSolidMoon(Config &config);\n\n  SphericalHarmonics sphericalHarmonics(const Time &time, const Rotary3d &rotEarth, EarthRotationPtr rotation, EphemeridesPtr ephemerides,\n                                        UInt maxDegree, UInt minDegree, Double GM, Double R) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file timeSeries.cpp\n*\n* @brief Generates time series.\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-03-02\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_TimeSeries\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/timeSeries/timeSeriesUniformSampling.h\"\n#include \"classes/timeSeries/timeSeriesUniformInterval.h\"\n#include \"classes/timeSeries/timeSeriesIrregular.h\"\n#include \"classes/timeSeries/timeSeriesMonthly.h\"\n#include \"classes/timeSeries/timeSeriesYearly.h\"\n#include \"classes/timeSeries/timeSeriesEveryMonth.h\"\n#include \"classes/timeSeries/timeSeriesEveryYear.h\"\n#include \"classes/timeSeries/timeSeriesInstrument.h\"\n#include \"classes/timeSeries/timeSeriesInstrumentArcIntervals.h\"\n#include \"classes/timeSeries/timeSeriesOrbitRevolutions.h\"\n#include \"classes/timeSeries/timeSeriesExclude.h\"\n#include \"classes/timeSeries/timeSeriesConditional.h\"\n#include \"classes/timeSeries/timeSeriesInterpolate.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(TimeSeries, \"timeSeriesType\",\n                      TimeSeriesUniformSampling,\n                      TimeSeriesUniformInterval,\n                      TimeSeriesIrregular,\n                      TimeSeriesMonthly,\n                      TimeSeriesYearly,\n                      TimeSeriesEveryMonth,\n                      TimeSeriesEveryYear,\n                      TimeSeriesInstrument,\n                      TimeSeriesInstrumentArcIntervals,\n                      TimeSeriesOrbitRevolutions,\n                      TimeSeriesExclude,\n                      TimeSeriesConditional,\n                      TimeSeriesInterpolate)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(TimeSeries, \"timeSeriesType\")\n\n/***********************************************/\n\nTimeSeries::TimeSeries(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"Generates time series\"))\n    {\n      std::vector<Time> times;\n      if(readConfigChoiceElement(config, \"uniformSampling\",        type, \"uniform series with given sampling\"))\n        base.push_back(new TimeSeriesUniformSampling(config));\n      if(readConfigChoiceElement(config, \"uniformInterval\",        type, \"uniform series with given interval count\"))\n        base.push_back(new TimeSeriesUniformInterval(config));\n      if(readConfigChoiceElement(config, \"irregular\",              type, \"every single point in time is given\"))\n        base.push_back(new TimeSeriesIrregular(config));\n      if(readConfigChoiceElement(config, \"monthly\",                type, \"time series based on months\"))\n        base.push_back(new TimeSeriesMonthly(config));\n      if(readConfigChoiceElement(config, \"yearly\",                 type, \"time series based on years\"))\n        base.push_back(new TimeSeriesYearly(config));\n      if(readConfigChoiceElement(config, \"everyMonth\",             type, \"time series based on months\"))\n        base.push_back(new TimeSeriesEveryMonth(config));\n      if(readConfigChoiceElement(config, \"everyYear\",              type, \"time series based on years\"))\n        base.push_back(new TimeSeriesEveryYear(config));\n      if(readConfigChoiceElement(config, \"instrument\",             type, \"read time series from an instrument file\"))\n        base.push_back(new TimeSeriesInstrument(config));\n      if(readConfigChoiceElement(config, \"instrumentArcIntervals\", type, \"try to reproduce arc interval time series from an instrument file\"))\n        base.push_back(new TimeSeriesInstrumentArcIntervals(config));\n      if(readConfigChoiceElement(config, \"revolutions\",            type, \"create time series from orbit file (revolutions)\"))\n        base.push_back(new TimeSeriesOrbitRevolutions(config));\n      if(readConfigChoiceElement(config, \"exclude\",                type, \"exclude times from a given time series\"))\n        base.push_back(new TimeSeriesExclude(config));\n      if(readConfigChoiceElement(config, \"conditional\",            type, \"time series based depending on conditions\"))\n        base.push_back(new TimeSeriesConditional(config));\n      if(readConfigChoiceElement(config, \"interpolate\",            type, \"interpolate between created times\"))\n        base.push_back(new TimeSeriesInterpolate(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    };\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTimeSeries::~TimeSeries()\n{\n  for(UInt i=0; i<base.size(); i++)\n    delete base.at(i);\n}\n\n/***********************************************/\n\nstd::vector<Time> TimeSeries::times() const\n{\n  try\n  {\n    std::vector<Time> times;\n    for(UInt i=0; i<base.size(); i++)\n    {\n      auto times2 = base.at(i)->times();\n      times.insert(times.end(), times2.begin(), times2.end());\n    }\n    std::sort(times.begin(), times.end());\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeries.h",
    "content": "/***********************************************/\n/**\n* @file timeSeries.h\n*\n* @brief Generates time series.\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-03-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIES__\n#define __GROOPS_TIMESERIES__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeries = R\"(\n\\section{TimeSeries}\\label{timeSeriesType}\nThis class generates a series of points in time. The series is always sorted in ascending order.\nDepending of the application the series is interpreted as list of points or as intervals between the points.\n\n\\fig{!hb}{0.4}{timeSeriesIntervals}{fig:timeSeriesIntervals}{List of points $t_i$ vs. intervals $T_i$.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup timeSeriesGroup TimeSeries\n* @brief Generates time series.\n* @ingroup classesGroup\n* The interface is given by @ref TimeSeries. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass TimeSeries;\nclass TimeSeriesBase;\ntypedef std::shared_ptr<TimeSeries> TimeSeriesPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Generates time series.\n* An instance of this class can be created with @ref readConfig. */\nclass TimeSeries\n{\n  std::vector<TimeSeriesBase*> base;\n\npublic:\n  /// Constructor.\n  TimeSeries(Config &config, const std::string &name);\n\n  /// Destructor.\n  ~TimeSeries();\n\n  /** @brief Time series with increasing order. */\n  std::vector<Time> times() const;\n\n  /** @brief creates an derived instance of this class. */\n  static TimeSeriesPtr create(Config &config, const std::string &name) {return TimeSeriesPtr(new TimeSeries(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class TimeSeries.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and a class without times is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] timeSeries Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates TimeSeries */\ntemplate<> Bool readConfig(Config &config, const std::string &name, TimeSeriesPtr &timeSeries, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass TimeSeriesBase\n{\npublic:\n  virtual ~TimeSeriesBase() {}\n  virtual std::vector<Time> times() const = 0;\n};\n\n/***********************************************/\n\n#endif\n\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesConditional.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesConditional.h\n*\n* @brief Create time series based on existence of files/directories\n* @see TimeSeries\n*\n* @author Matthias Ellmer\n* @author Torsten Mayer-Guerr\n* @date 2018-05-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESCONDITIONAL__\n#define __GROOPS_TIMESERIESCONDITIONAL__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesConditional = R\"(\n\\subsection{Conditional}\nOnly times for which the \\configClass{condition}{conditionType} is met are included in the time series.\nThe \\config{variableLoopTime} is set to every time and the \\configClass{condition}{conditionType} is evaluated.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/condition/condition.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Only times for which the condition is met are included in the time series.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesConditional : public TimeSeriesBase\n{\n  TimeSeriesPtr timeSeries;\n  ConditionPtr  conditionPtr;\n  std::string   nameTime;\n\npublic:\n  TimeSeriesConditional(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesConditional::TimeSeriesConditional(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeSeries\",       timeSeries,   Config::MUSTSET,   \"\",         \"only times for which condition is met will be included\");\n    readConfig(config, \"variableLoopTime\", nameTime,     Config::OPTIONAL,  \"loopTime\", \"variable with time of each loop\");\n    readConfig(config, \"condition\",        conditionPtr, Config::MUSTSET,   \"\",         \"test for each time\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesConditional::times() const\n{\n  try\n  {\n    VariableList varList;\n    std::vector<Time> times;\n    for(const auto &t : timeSeries->times())\n    {\n      if(!nameTime.empty())\n        varList.setVariable(nameTime, t.mjd());\n      if(conditionPtr->condition(varList))\n        times.push_back(t);\n    }\n\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesEveryMonth.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesEveryMonth.h\n*\n* @brief Time series oriented on months.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-11-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESYEVERYMONTH__\n#define __GROOPS_TIMESERIESYEVERYMONTH__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesEveryMonth = R\"(\n\\subsection{EveryMonth}\nGenerates a time series with monthly sampling. The first point in time will be \\config{timeStart} and the following\npoints are generated for each month at the same day and time in month.\nThe last generated point in time will be less or equal \\config{timeEnd}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series oriented on months.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesEveryMonth : public TimeSeriesBase\n{\n  Time timeStart, timeEnd;\n\npublic:\n  TimeSeriesEveryMonth(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesEveryMonth::TimeSeriesEveryMonth(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeStart\", timeStart, Config::MUSTSET, \"\", \"first point in time\");\n    readConfig(config, \"timeEnd\",   timeEnd,   Config::MUSTSET, \"\", \"last point in time will be less or equal timeEnd\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesEveryMonth::times() const\n{\n  try\n  {\n    std::vector<Time> times = {timeStart};\n    for(;;)\n    {\n      UInt   year, month, day, hour, min;\n      Double sec;\n      times.back().date(year, month, day, hour, min, sec);\n      const Time time = date2time(year, month+1, day, hour, min, sec);\n      if(time > timeEnd)\n        break;\n      times.push_back(time);\n    }\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesEveryYear.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesEveryYear.h\n*\n* @brief Time series oriented on years.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-11-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESYEVERYYEAR__\n#define __GROOPS_TIMESERIESYEVERYYEAR__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesEveryYear = R\"(\n\\subsection{EveryYear}\nGenerates a time series with yearly sampling. The first point in time will be \\config{timeStart} and the following\npoints are generated for each year at the same day and time in year.\nThe last generated point in time will be less or equal \\config{timeEnd}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series oriented on years.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesEveryYear : public TimeSeriesBase\n{\n  Time timeStart, timeEnd;\n\npublic:\n  TimeSeriesEveryYear(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesEveryYear::TimeSeriesEveryYear(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeStart\", timeStart, Config::MUSTSET, \"\", \"first point in time\");\n    readConfig(config, \"timeEnd\",   timeEnd,   Config::MUSTSET, \"\", \"last point in time will be less or equal timeEnd\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesEveryYear::times() const\n{\n  try\n  {\n    std::vector<Time> times = {timeStart};\n\n    for(;;)\n    {\n      UInt   year, month, day, hour, min;\n      Double sec;\n      times.back().date(year, month, day, hour, min, sec);\n      const Time time = date2time(year+1, month, day, hour, min, sec);\n      if(time > timeEnd)\n        break;\n      times.push_back(time);\n    }\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesExclude.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesExclude.h\n*\n* @brief Exclude times from a given time series.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-11-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESEXCLUDE__\n#define __GROOPS_TIMESERIESEXCLUDE__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesExclude = R\"(\n\\subsection{Exclude}\nIn a first step a \\configClass{timeSeries}{timeSeriesType} is generated.\nIn a second step all times are removed which are in range before or after \\config{excludeMargin} seconds\nof the times given by \\configClass{timeSeriesExclude}{timeSeriesType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Exclude times from a given time series.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesExclude : public TimeSeriesBase\n{\n  TimeSeriesPtr timeSeries, timeSeriesExcl;\n  Double        margin;\n\npublic:\n  TimeSeriesExclude(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesExclude::TimeSeriesExclude(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeSeries\",        timeSeries,     Config::MUSTSET,  \"\",     \"time series to be created\");\n    readConfig(config, \"timeSeriesExclude\", timeSeriesExcl, Config::MUSTSET,  \"\",     \"exclude this time points from time series (within margin)\");\n    readConfig(config, \"excludeMargin\",     margin,         Config::DEFAULT,  \"1e-5\", \"on both sides [seconds]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesExclude::times() const\n{\n  try\n  {\n    std::vector<Time> times;\n    std::vector<Time> timesOld  = timeSeries->times();\n    std::vector<Time> timesExcl = timeSeriesExcl->times();\n\n    UInt idxTime = 0;\n    for(UInt i=0; i<timesOld.size(); i++)\n    {\n      while((idxTime < timesExcl.size()) && ((timesExcl.at(idxTime)-timesOld.at(i)).seconds() < -margin))\n        idxTime++;\n      if((idxTime >= timesExcl.size()) || ((timesExcl.at(idxTime)-timesOld.at(i)).seconds() > +margin))\n        times.push_back(timesOld.at(i));\n    }\n\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesInstrument.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesInstrument.h\n*\n* @brief Read time series from a instrument file.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-06-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESINSTRUMENT__\n#define __GROOPS_TIMESERIESINSTRUMENT__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesInstrument = R\"(\n\\subsection{Instrument}\\label{timeSeriesType:instrument}\nRead a time series (epochs) from an \\file{instrument file}{instrument}.\nThe time series can be restricted to the interval\nstarting from \\config{timeStart} and before \\config{timeEnd}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read time series from a instrument file.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesInstrument : public TimeSeriesBase\n{\n  FileName fileName;\n  Time     timeStart, timeEnd;\n\npublic:\n  TimeSeriesInstrument(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesInstrument::TimeSeriesInstrument(Config &config)\n{\n  try\n  {\n    timeEnd = date2time(9999, 1, 1);\n\n    readConfig(config, \"inputfileInstrument\", fileName,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeStart\",           timeStart, Config::OPTIONAL, \"\", \"inclusive, i.e. exclude eochs before this epoch\");\n    readConfig(config, \"timeEnd\",             timeEnd,   Config::OPTIONAL, \"\", \"exclusive, i.e. only epochs before this time are used\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesInstrument::times() const\n{\n  try\n  {\n    const Arc arc = InstrumentFile::read(fileName);\n\n    std::vector<Time> times;\n    for(UInt i=0; i<arc.size(); i++)\n    {\n      if(arc.at(i).time >= timeEnd)\n        break;\n      if(arc.at(i).time >= timeStart)\n        times.push_back(arc.at(i).time);\n    }\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesInstrumentArcIntervals.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesInstrumentArcIntervals.h\n*\n* @brief Reconstruct arc intervals from instrument file.\n* @see TimeSeries\n*\n* @author Matthias Ellmer\n* @date 2017-08-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESINSTRUMENTARCINTERVALS__\n#define __GROOPS_TIMESERIESINSTRUMENTARCINTERVALS__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesInstrumentArcIntervals = R\"(\n\\subsection{InstrumentArcIntervals}\nReconstruct a time series from an \\file{instrument file}{instrument}.\nThe time series is the first epoch of each arc plus one time step beyond the last\nepoch of the last arc (using median sampling).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read time series from a instrument file.\n * @ingroup timeSeriesGroup\n * @see TimeSeries */\nclass TimeSeriesInstrumentArcIntervals : public TimeSeriesBase\n{\n  FileName fileName;\n\npublic:\n  TimeSeriesInstrumentArcIntervals(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesInstrumentArcIntervals::TimeSeriesInstrumentArcIntervals(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileInstrument\", fileName,  Config::MUSTSET,  \"\", \"Must be regular. Time series is first epoch of each arc plus one time step extrapolated from last epoch of last arc.\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesInstrumentArcIntervals::times() const\n{\n  try\n  {\n    std::vector<Time> times;\n\n    InstrumentFile file(fileName);\n    Time finalTime;\n    for(UInt arcNo=0; arcNo<file.arcCount(); arcNo++)\n    {\n      std::vector<Time> arcTimes = file.readArc(arcNo).times();\n      if(arcTimes.size())\n      {\n        times.push_back(arcTimes.front());\n        finalTime = arcTimes.back() + medianSampling(arcTimes);\n      }\n      else\n        times.push_back(finalTime);\n    }\n    times.push_back(finalTime);\n\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_TIMESERIESINSTRUMENTARCINTERVALS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesInterpolate.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesInterpolate.h\n*\n* @brief Interpolates between times of a series.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-11-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESINTERPOLATE__\n#define __GROOPS_TIMESERIESINTERPOLATE__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesInterpolate = R\"(\n\\subsection{Interpolate}\nInterpolates \\config{nodeInterpolation} count points between\nthe given \\configClass{timeSeries}{timeSeriesType} uniformly.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolates between times of a series\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesInterpolate : public TimeSeriesBase\n{\n  TimeSeriesPtr timeSeries;\n  UInt          interpCount;\n\npublic:\n  TimeSeriesInterpolate(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesInterpolate::TimeSeriesInterpolate(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeSeries\",        timeSeries,  Config::MUSTSET, \"\",  \"time series to be created\");\n    readConfig(config, \"nodeInterpolation\", interpCount, Config::MUSTSET, \"1\", \"interpolates count points in each time interval given by the time series\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesInterpolate::times() const\n{\n  try\n  {\n    std::vector<Time> times = timeSeries->times();\n\n    const UInt timeCount = times.size();\n    for(UInt i=0; i<timeCount-1; i++)\n      for(UInt k=1; k<=interpCount; k++)\n        times.push_back(times.at(i) + (k/(interpCount+1.))*(times.at(i+1)-times.at(i)));\n    std::sort(times.begin(), times.end());\n\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesIrregular.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesIrregular.h\n*\n* @brief Time series given as explicit list.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-03-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESIRREGULAR__\n#define __GROOPS_TIMESERIESIRREGULAR__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesIrregular = R\"(\n\\subsection{Irregular}\\label{timeSeriesType:irregular}\nThe points of the time series are given explicitly with \\config{time}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read time given as explicit list.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesIrregular : public TimeSeriesBase\n{\n  std::vector<Time> times_;\n\npublic:\n  TimeSeriesIrregular(Config &config);\n\n  std::vector<Time> times() const {return times_;}\n};\n\n/***********************************************/\n\ninline TimeSeriesIrregular::TimeSeriesIrregular(Config &config)\n{\n  try\n  {\n    readConfig(config, \"time\", times_, Config::MUSTSET, \"\", \"explicit list of points in time\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesMonthly.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesMonthly.h\n*\n* @brief Time series oriented on months.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-03-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESYMONTHLY__\n#define __GROOPS_TIMESERIESYMONTHLY__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesMonthly = R\"(\n\\subsection{Monthly}\nIf \\config{useMonthMiddle} is set, time points are generated at mid of each month inclusively\nthe \\config{monthStart} in \\config{yearStart} and \\config{monthEnd} in \\config{yearEnd}.\nOtherwise times are given at the first of each month and a time point after the last month.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series oriented on months.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesMonthly : public TimeSeriesBase\n{\n  UInt monthStart, yearStart;\n  UInt monthEnd,   yearEnd;\n  Bool monthMiddle;\n\npublic:\n  TimeSeriesMonthly(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesMonthly::TimeSeriesMonthly(Config &config)\n{\n  try\n  {\n    readConfig(config, \"monthStart\",     monthStart,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"yearStart\",      yearStart,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"monthEnd\",       monthEnd,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"yearEnd\",        yearEnd,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"useMonthMiddle\", monthMiddle, Config::DEFAULT,  \"0\", \"time points are mid of months, otherwise the 1st of each month + a time point behind the last month\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesMonthly::times() const\n{\n  try\n  {\n    std::vector<Time> times;\n    for(UInt year=yearStart; year<=yearEnd; year++)\n    {\n      const UInt monthStart2 = (year==yearStart) ? monthStart : 1;\n      const UInt monthEnd2   = (year==yearEnd)   ? monthEnd   : 12;\n      for(UInt month=monthStart2; month<=monthEnd2; month++)\n        if(monthMiddle)\n          times.push_back( 0.5 * (date2time(year, month, 1) + date2time(year, month+1, 1)) );\n        else\n          times.push_back( date2time(year, month, 1) );\n    }\n    if(!monthMiddle)\n      times.push_back(date2time(yearEnd, monthEnd+1, 1));\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesOrbitRevolutions.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesOrbitRevolutions.h\n*\n* @brief Read orbit file and create a time stamp for each ascending equator crossing.\n* @see TimeSeries\n*\n* @author Norbert Zehentner\n* @date 2017-05-16\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESORBITREVOLUTIONS__\n#define __GROOPS_TIMESERIESORBITREVOLUTIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesOrbitRevolutions = R\"(\n\\subsection{Revolution}\nReads an \\file{orbit file}{instrument} and create a time stamp for each ascending equator crossing.\nThe time series can be restricted to the interval\nstarting from \\config{timeStart} and before \\config{timeEnd}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read orbit file and create a time stamp for each ascending equator crossing.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesOrbitRevolutions : public TimeSeriesBase\n{\n  FileName fileName;\n  Time     timeStart, timeEnd;\n\npublic:\n  TimeSeriesOrbitRevolutions(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesOrbitRevolutions::TimeSeriesOrbitRevolutions(Config &config)\n{\n  try\n  {\n    timeEnd = date2time(9999, 1, 1);\n\n    readConfig(config, \"inputfileOrbit\", fileName,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeStart\",      timeStart, Config::OPTIONAL, \"\", \"exclude eochs before this epoch\");\n    readConfig(config, \"timeEnd\",        timeEnd,   Config::OPTIONAL, \"\", \"only epochs before this time are used\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesOrbitRevolutions::times() const\n{\n  try\n  {\n    const OrbitArc orbit = InstrumentFile::read(fileName);\n\n    std::vector<Time> times;\n    for(UInt i=0; i<orbit.size()-1; i++)\n      if((orbit.at(i).position.phi() < 0) && (orbit.at(i+1).position.phi() > 0))\n      {\n        const Double deltaPhi = Double(orbit.at(i+1).position.phi())-Double(orbit.at(i).position.phi());\n        const Time   time     = orbit.at(i).time + (Double(orbit.at(i).position.phi())/deltaPhi) * (orbit.at(i+1).time-orbit.at(i).time);\n        if(time.isInInterval(timeStart, timeEnd))\n          times.push_back(time);\n      }\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesUniformInterval.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesUniformInterval.h\n*\n* @brief Time series from given interval count.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-03-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESUNIFORMINTERVAL__\n#define __GROOPS_TIMESERIESUNIFORMINTERVAL__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesUniformInterval = R\"(\n\\subsection{UniformInterval}\nGenerates a time series with uniform sampling between \\config{timeStart} and \\config{timeEnd}.\n\\config{intervallCount} gives the count of intervals. This class generates count+1 points in time\ninclusive \\config{timeStart} and \\config{timeEnd}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series from given interval count.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesUniformInterval : public TimeSeriesBase\n{\n  Time timeStart, timeEnd;\n  UInt count;\n\npublic:\n  TimeSeriesUniformInterval(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesUniformInterval::TimeSeriesUniformInterval(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeStart\",      timeStart, Config::MUSTSET, \"\", \"1st point of the time series\");\n    readConfig(config, \"timeEnd\",        timeEnd,   Config::MUSTSET, \"\", \"last point of the time series\");\n    readConfig(config, \"intervalCount\",  count,     Config::MUSTSET, \"\", \"count of intervals, count+1 points in time will generated\");\n    if(isCreateSchema(config)) return;\n\n    if(timeStart>=timeEnd)\n      throw(Exception(\"Points in time must be given in increasing order.\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesUniformInterval::times() const\n{\n  try\n  {\n    std::vector<Time> times(count+1);\n    const Time deltaT = 1./count * (timeEnd-timeStart);\n    for(UInt i=0; i<=count; i++)\n      times.at(i) = timeStart + i * deltaT;\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesUniformSampling.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesUniformSampling.h\n*\n* @brief Time series with uniform sampling.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-03-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESUNIFORMSAMPLING__\n#define __GROOPS_TIMESERIESUNIFORMSAMPLING__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesUniformSampling = R\"(\n\\subsection{UniformSampling}\\label{timeSeriesType:uniformSampling}\nGenerates a time series with uniform sampling. The first point in time will be \\config{timeStart}.\nThe last generated point in time will be less or equal \\config{timeEnd}.\nThe time step between generated points in time is given by \\config{sampling}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series with uniform sampling.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesUniformSampling : public TimeSeriesBase\n{\n  Time timeStart, timeEnd, deltaTime;\n\npublic:\n  TimeSeriesUniformSampling(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesUniformSampling::TimeSeriesUniformSampling(Config &config)\n{\n  try\n  {\n    readConfig(config, \"timeStart\", timeStart, Config::MUSTSET, \"\", \"first point in time\");\n    readConfig(config, \"timeEnd\",   timeEnd,   Config::MUSTSET, \"\", \"last point in time will be less or equal timeEnd\");\n    readConfig(config, \"sampling\",  deltaTime, Config::MUSTSET, \"\", \"time step between points in time\");\n    if(isCreateSchema(config)) return;\n\n    if(deltaTime <= Time(0, 0.0))\n      throw(Exception(\"Sampling must be strictly positive.\"));\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesUniformSampling::times() const\n{\n  try\n  {\n    std::vector<Time> times;\n    for(UInt i=0; timeStart+i*deltaTime <= timeEnd; i++)\n      times.push_back(timeStart+i*deltaTime);\n\n    if(times.size()<1)\n      throw(Exception(\"Points in time must be given in increasing order.\"));\n\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/timeSeries/timeSeriesYearly.h",
    "content": "/***********************************************/\n/**\n* @file timeSeriesYearly.h\n*\n* @brief Time series oriented on years.\n* @see TimeSeries\n*\n* @author Torsten Mayer-Guerr\n* @date 2016-06-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TIMESERIESYEARLY__\n#define __GROOPS_TIMESERIESYEARLY__\n\n// Latex documentation\n#ifdef DOCSTRING_TimeSeries\nstatic const char *docstringTimeSeriesYearly = R\"(\n\\subsection{Yearly}\nIf \\config{useYearMiddle} is set, time points are generated at mid of each year inclusively \\config{yearStart}\nand \\config{yearEnd}. Otherwise times are given at the first of each year and a time point after the last year.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series oriented on years.\n* @ingroup timeSeriesGroup\n* @see TimeSeries */\nclass TimeSeriesYearly : public TimeSeriesBase\n{\n  UInt yearStart, yearEnd;\n  Bool yearMiddle;\n\npublic:\n  TimeSeriesYearly(Config &config);\n\n  std::vector<Time> times() const;\n};\n\n/***********************************************/\n\ninline TimeSeriesYearly::TimeSeriesYearly(Config &config)\n{\n  try\n  {\n    readConfig(config, \"yearStart\",         yearStart,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"yearEnd\",           yearEnd,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"useYearMiddle\",     yearMiddle,  Config::DEFAULT,  \"0\", \"time points are mid of years, otherwise the 1st of each year + a time point behind the last year\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<Time> TimeSeriesYearly::times() const\n{\n  try\n  {\n    std::vector<Time> times;\n    for(UInt year=yearStart; year<=yearEnd; year++)\n    {\n      if(yearMiddle)\n        times.push_back( 0.5 * (date2time(year, 1, 1) + date2time(year+1, 1, 1)) );\n      else\n        times.push_back( date2time(year, 1, 1) );\n    }\n    if(!yearMiddle)\n      times.push_back(date2time(yearEnd+1, 1, 1));\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/troposphere/troposphere.cpp",
    "content": "/***********************************************/\n/**\n* @file troposphere.cpp\n*\n* @brief Signal delay in the atmosphere.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-04-03\n*/\n/***********************************************/\n\n#define DOCSTRING_Troposphere\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileGriddedData.h\"\n#include \"troposphereGpt.h\"\n#include \"troposphereMendesAndPavlis.h\"\n#include \"troposphereViennaMapping.h\"\n#include \"troposphere.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(Troposphere, \"troposphereType\",\n                      TroposphereViennaMapping,\n                      TroposphereGpt,\n                      TroposphereMendesAndPavlis)\n\nGROOPS_READCONFIG_CLASS(Troposphere, \"troposphereType\")\n\n/***********************************************/\n\nTropospherePtr Troposphere::create(Config &config, const std::string &name)\n{\n  try\n  {\n    TropospherePtr troposphere;\n    std::string type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"signal delay in the atmosphere\");\n    if(readConfigChoiceElement(config, \"viennaMapping\",   type, \"Vienna Mapping Function\"))\n      troposphere = TropospherePtr(new TroposphereViennaMapping(config));\n    if(readConfigChoiceElement(config, \"gpt\",             type, \"GPT empirical troposphere model\"))\n      troposphere = TropospherePtr(new TroposphereGpt(config));\n    if(readConfigChoiceElement(config, \"mendesAndPavlis\", type, \"SLR troposphere model by Mendes and Pavlis, 2004\"))\n      troposphere = TropospherePtr(new TroposphereMendesAndPavlis(config));\n    endChoice(config);\n\n    return troposphere;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Troposphere::initEmpiricalCoefficients(const FileName &fileNameGpt, const std::vector<Vector3d> &stationPositions)\n{\n  try\n  {\n    GriddedDataRectangular grid;\n    readFileGriddedData(fileNameGpt, grid);\n\n    const UInt stationCount = stationPositions.size();\n    longitude = Vector(stationCount);\n    latitude  = Vector(stationCount);\n    height    = Vector(stationCount);\n    coeff     = Matrix(grid.values.size(), stationCount);\n\n    for(UInt stationId=0; stationId<stationCount; stationId++)\n    {\n      Angle  L, B;\n      grid.ellipsoid(stationPositions.at(stationId), L, B, height(stationId));\n      longitude(stationId) = L;\n      latitude(stationId)  = B;\n\n      // interpolation factors and indices\n      Double tx   = (grid.latitudes.front()-latitude(stationId)) * (grid.latitudes.size()-1)/(grid.latitudes.front()-grid.latitudes.back());\n      Double ty   = std::fmod(longitude(stationId)-grid.longitudes.front()+4*PI, 2*PI)/(2*PI) * grid.longitudes.size();\n      UInt   idxX = std::min(static_cast<UInt>(std::max(std::floor(tx), 0.)), grid.latitudes.size()-2);\n      UInt   idxY = static_cast<UInt>(std::floor(ty));\n      tx -= idxX; // latitudinal  interpolation factor [0..1]\n      ty -= idxY; // longitudinal interpolation factor [0..1]\n\n      for(UInt k=0; k<grid.values.size(); k++)\n      {\n        coeff(k, stationId) = (1-tx) * (1-ty) * grid.values.at(k)(idxX,   (idxY)  %grid.longitudes.size())\n                            + (1-tx) * (ty)   * grid.values.at(k)(idxX,   (idxY+1)%grid.longitudes.size())\n                            + (tx)   * (1-ty) * grid.values.at(k)(idxX+1, (idxY)  %grid.longitudes.size())\n                            + (tx)   * (ty)   * grid.values.at(k)(idxX+1, (idxY+1)%grid.longitudes.size());\n      }\n    }\n\n    timeRef = Time();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Troposphere::computeEmpiricalCoefficients(const Time &time) const\n{\n  try\n  {\n    if(timeRef.mjdInt() == time.mjdInt())\n      return; // computing empirical coefficients once per day is sufficient, since they only have annual and semiannual variations\n\n    timeRef = time;\n\n    const Double t = (time.mjd()-J2000)/365.25;\n    Vector fourier(5);\n    fourier(0) = 1.;               // constant\n    fourier(1) = std::cos(2*PI*t); // cos annual\n    fourier(2) = std::sin(2*PI*t); // sin annual\n    fourier(3) = std::cos(4*PI*t); // cos semiannual\n    fourier(4) = std::sin(4*PI*t); // sin semiannual\n\n    topo = ah = aw = bh = bw = ch = cw = p = T = Q = dT = la = Tm = zhd = zwd = gnh = geh = gnw = gew = Vector(longitude.rows());\n    for(UInt stationId=0; stationId<longitude.size(); stationId++)\n    {\n      topo(stationId)  = coeff(0, stationId);                                                // [m]\n\n      ah(stationId)    = inner(fourier, coeff.slice(1+ 0*5,  stationId, fourier.rows(), 1));\n      aw(stationId)    = inner(fourier, coeff.slice(1+ 1*5,  stationId, fourier.rows(), 1));\n      bh(stationId)    = inner(fourier, coeff.slice(1+ 2*5,  stationId, fourier.rows(), 1));\n      bw(stationId)    = inner(fourier, coeff.slice(1+ 3*5,  stationId, fourier.rows(), 1));\n      ch(stationId)    = inner(fourier, coeff.slice(1+ 4*5,  stationId, fourier.rows(), 1));\n      cw(stationId)    = inner(fourier, coeff.slice(1+ 5*5,  stationId, fourier.rows(), 1));\n\n      p(stationId)     = inner(fourier, coeff.slice(1+ 6*5,  stationId, fourier.rows(), 1)); // [Pa]\n      T(stationId)     = inner(fourier, coeff.slice(1+ 7*5,  stationId, fourier.rows(), 1)); // [Kelvin]\n      Q(stationId)     = inner(fourier, coeff.slice(1+ 8*5,  stationId, fourier.rows(), 1)); // [kg/kg]\n      dT(stationId)    = inner(fourier, coeff.slice(1+ 9*5,  stationId, fourier.rows(), 1)); // tempLapseRate [Kelvin/m]\n      la(stationId)    = inner(fourier, coeff.slice(1+10*5,  stationId, fourier.rows(), 1)); // waterWaporDecreaseFactor []\n      Tm(stationId)    = inner(fourier, coeff.slice(1+11*5,  stationId, fourier.rows(), 1)); // waterWaporMeanTemperature [Kelvin]\n\n      gnh(stationId)   = inner(fourier, coeff.slice(1+12*5, stationId, fourier.rows(), 1)); // [m]\n      geh(stationId)   = inner(fourier, coeff.slice(1+13*5, stationId, fourier.rows(), 1)); // [m]\n      gnw(stationId)   = inner(fourier, coeff.slice(1+14*5, stationId, fourier.rows(), 1)); // [m]\n      gew(stationId)   = inner(fourier, coeff.slice(1+15*5, stationId, fourier.rows(), 1)); // [m]\n\n      constexpr Double g    = 9.80665;                  // mean gravity in [m/s^2]\n      constexpr Double dMtr = 2.8965e-2;                // molar mass of dry air in [kg/mol]\n      constexpr Double Rg   = 8.3143;                   // universal gas constant in [J/K/mol]\n      constexpr Double k1   = 77.604;                   // coefficient [K/hPa]\n      constexpr Double k2   = 64.79;                    // coefficient [K/hPa]\n      constexpr Double k2p  = k2 - k1*18.0152/28.9644;  // coefficient [K/hPa]\n      constexpr Double k3   = 377600.;                  // coefficient [KK/hPa]\n\n      const Double h   = height(stationId) - topo(stationId);            // reduced height\n      const Double Tv = T(stationId) * (1. + 0.6077*Q(stationId));       // virtual temperature in [Kelvin]\n      const Double P  = 0.01 * p(stationId) * std::exp(-g*dMtr/Rg/Tv*h); // pressure in [hPa]\n\n      // zenith hydrostatic delay (Saastamoinen, 1972) and zenith wet delay (Askne and Nordius, 1987)\n      zhd(stationId) = 0.0022768 * P / (1. - 0.00266*std::cos(2*latitude(stationId)) - 0.00000028*height(stationId));\n      zwd(stationId) = 1e-6*Rg/dMtr/g * (k2p + k3/Tm(stationId)) * P * Q(stationId)/(0.622 + 0.378*Q(stationId))/(1+la(stationId));\n      zwd(stationId) *= std::exp(-h/2000); // extrapolate ZWD to station height\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/troposphere/troposphere.h",
    "content": "/***********************************************/\n/**\n* @file troposphere.h\n*\n* @brief Signal delay in the atmosphere.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-04-03\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TROPOSPHERE__\n#define __GROOPS_TROPOSPHERE__\n\n// Latex documentation\n#ifdef DOCSTRING_Troposphere\nstatic const char *docstringTroposphere = R\"(\n\\section{Troposphere}\\label{troposphereType}\nThis class provides functions for calculating and estimating\nthe signal delay in the dry and wet atmosphere.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/**\n* @defgroup troposphereGroup Troposphere\n* @brief Signal delay in the atmosphere.\n* @ingroup classesGroup\n* Functions for calculating and estimating\n* the signal delay in the dry and wet atmosphere.\n* The interface is given by @ref Troposphere. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Troposphere;\ntypedef std::shared_ptr<Troposphere> TropospherePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Signal delay in the atmosphere.\n* Functions for calculating and estimating\n* the signal delay in the dry and wet atmosphere.\n* An Instance of this class can be created by @ref readConfig. */\nclass Troposphere\n{\npublic:\n  /// Destructor.\n  virtual ~Troposphere() {}\n\n  /** @brief Init the station list.\n  * To speed up the computation and to reduce memory consumption the coordinates\n  * of the station (given in TRF [m]) must be set before calling the other functions. */\n  virtual void init(const std::vector<std::string> &stationNames, const std::vector<Vector3d> &stationPositions) = 0;\n\n  /** @brief Approx value of the slant delay.\n  * @param stationId Station number from the list given at init.\n  * @param time Time of the measurement.\n  * @param frequency of the electromagnetic signal [Hz].\n  * @param azimuth  Azimuth.\n  * @param elevation  Elevation.\n  * @return delay [m] */\n  virtual Double slantDelay(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const = 0;\n\n  /** @brief Mapping Function of the hydrostatic atmosphere.\n  * @param stationId Station number from the list given at init.\n  * @param time Time of the measurement.\n  * @param frequency of the electromagnetic signal [Hz].\n  * @param azimuth  Azimuth.\n  * @param elevation  Elevation.\n  * @return function value [] */\n  virtual Double mappingFunctionHydrostatic(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const = 0;\n\n  /** @brief Mapping Function of the wet atmosphere.\n  * @param stationId Station number from the list given at init.\n  * @param time Time of the measurement.\n  * @param frequency of the electromagnetic signal [Hz].\n  * @param azimuth  Azimuth.\n  * @param elevation  Elevation.\n  * @return function value [] */\n  virtual Double mappingFunctionWet(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const = 0;\n\n  /** @brief Gradient of the mapping function.\n  * @param stationId Station number from the list given at init.\n  * @param time Time of the measurement.\n  * @param frequency of the electromagnetic signal [Hz].\n  * @param azimuth  Azimuth.\n  * @param elevation  Elevation.\n  * @param[out] dx  Gradient function value in North direction [].\n  * @param[out] dy  Gradient function value in East direction []. */\n  virtual void mappingFunctionGradient(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation, Double &dx, Double &dy) const = 0;\n\n\n  /** @brief Get tropospheric zenith dry/wet delay and dry/wet gradients in North and East directions at a specific time stamp.\n  * @param stationId Station number from the list given at init.\n  * @param time Time of the measurement.\n  * @param frequency of the electromagnetic signal [Hz].\n  * @param[out] zenithDryDelay Zenith dry delay [m].\n  * @param[out] zenithWetDelay Zenith wet delay [m].\n  * @param[out] gradientDryNorth Dry gradient in North direction [m].\n  * @param[out] gradientWetNorth Wet gradient in North direction [m].\n  * @param[out] gradientDryEast Dry gradient in East direction [m].\n  * @param[out] gradientWetEast Wet gradient in East direction [m].\n  * @param[out] aDry Dry mapping function coefficient a [].\n  * @param[out] aWet Wet mapping function coefficient a []. */\n  virtual void getAprioriValues(UInt stationId, const Time &time, Double frequency, Double &zenithDryDelay, Double &zenithWetDelay, Double &gradientDryNorth,\n                                Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast, Double &aDry, Double &aWet) const = 0;\n\n  static Double mappingFunction(Double sinE, Double a, Double b, Double c) {return (1+(a/(1+(b/(1+c)))))/(sinE+(a/(sinE+(b/(sinE+c)))));}\n\n  /** @brief creates an derived instance of this class. */\n  static TropospherePtr create(Config &config, const std::string &name);\n\nprivate:\n  mutable Time timeRef;\n  Matrix coeff;\n\nprotected:\n  Vector longitude, latitude, height;\n\n  mutable Vector topo;\n  mutable Vector ah, aw, bh, bw, ch, cw;\n  mutable Vector p, T, Q, dT, la, Tm;\n  mutable Vector zhd, zwd;\n  mutable Vector gnh, geh, gnw, gew;\n\n  void initEmpiricalCoefficients(const FileName &fileNameGpt, const std::vector<Vector3d> &stationPositions);\n  void computeEmpiricalCoefficients(const Time &time) const;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class Troposphere.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a troposphere is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] troposphere Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates Troposphere */\ntemplate<> Bool readConfig(Config &config, const std::string &name, TropospherePtr &troposphere, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/classes/troposphere/troposphereGpt.cpp",
    "content": "/***********************************************/\n/**\n* @file troposphereGpt.cpp\n*\n* @brief GPT empirical troposphere model.\n* @see Troposphere\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2017-02-23\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"troposphere.h\"\n#include \"troposphereGpt.h\"\n\n/***********************************************/\n\nTroposphereGpt::TroposphereGpt(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileGpt\", fileNameGpt, Config::MUSTSET, \"{groopsDataDir}/troposphere/gpt3_grid1deg.dat\",  \"gridded GPT data\");\n    readConfig(config, \"aHeight\",      a_ht,        Config::DEFAULT, \"2.53e-5\", \"parameter a (height correction)\");\n    readConfig(config, \"bHeight\",      b_ht,        Config::DEFAULT, \"5.49e-3\", \"parameter b (height correction)\");\n    readConfig(config, \"cHeight\",      c_ht,        Config::DEFAULT, \"1.14e-3\", \"parameter c (height correction)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereGpt::init(const std::vector<std::string> &/*stationNames*/, const std::vector<Vector3d> &stationPositions)\n{\n  try\n  {\n    initEmpiricalCoefficients(fileNameGpt, stationPositions);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TroposphereGpt::slantDelay(UInt stationId, const Time &time, Double /*frequency*/, Angle azimuth, Angle elevation) const\n{\n  try\n  {\n    computeEmpiricalCoefficients(time);\n\n    const Double sinE = std::sin(elevation);\n    const Double vmfh = mappingFunction(sinE, ah(stationId), bh(stationId), ch(stationId))\n                      + (1./sinE - mappingFunction(sinE, a_ht, b_ht, c_ht)) * height(stationId)*0.001;\n    const Double vmfw = mappingFunction(sinE, aw(stationId), bw(stationId), cw(stationId));\n    const Double mfgh = 1. / (sinE*std::tan(elevation) + 0.0031); // hydrostatic gradient mapping function [Chen and Herring, 1997]\n    const Double mfgw = 1. / (sinE*std::tan(elevation) + 0.0007); // wet -\"-\n\n    return vmfh*zhd(stationId) + vmfw*zwd(stationId)\n        + (mfgh*gnh(stationId) + mfgw*gnw(stationId)) * std::cos(azimuth)\n        + (mfgh*geh(stationId) + mfgw*gew(stationId)) * std::sin(azimuth);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TroposphereGpt::mappingFunctionHydrostatic(UInt stationId, const Time &time, Double /*frequency*/, Angle /*azimuth*/, Angle elevation) const\n{\n  try\n  {\n    computeEmpiricalCoefficients(time);\n    const Double sinE  = sin(elevation);\n    return mappingFunction(sinE, ah(stationId), bh(stationId), ch(stationId))\n           + (1./sinE - mappingFunction(sinE, a_ht, b_ht, c_ht)) * height(stationId)*0.001;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TroposphereGpt::mappingFunctionWet(UInt stationId, const Time &time, Double /*frequency*/, Angle /*azimuth*/, Angle elevation) const\n{\n  try\n  {\n    computeEmpiricalCoefficients(time);\n    return mappingFunction(sin(elevation), aw(stationId), bw(stationId), cw(stationId));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereGpt::mappingFunctionGradient(UInt /*stationId*/, const Time &/*time*/, Double /*frequency*/, Angle azimuth, Angle elevation, Double &dx, Double &dy) const\n{\n  try\n  {\n    const Double mfgw = 1./(std::sin(elevation)*std::tan(elevation) + 0.0031); // hydrostatic gradient mapping function [Chen and Herring, 1997] (unitless)\n    dx = mfgw * std::cos(azimuth);\n    dy = mfgw * std::sin(azimuth);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereGpt::getAprioriValues(UInt stationId, const Time &time, Double /*frequency*/, Double &zenithDryDelay, Double &zenithWetDelay, Double &gradientDryNorth,\n                                      Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast, Double &aDry, Double &aWet) const\n{\n  try\n  {\n    computeEmpiricalCoefficients(time);\n    zenithDryDelay   = zhd(stationId);\n    zenithWetDelay   = zwd(stationId);\n    gradientDryNorth = gnh(stationId);\n    gradientWetNorth = gnw(stationId);\n    gradientDryEast  = geh(stationId);\n    gradientWetEast  = gew(stationId);\n    aDry             = ah(stationId);\n    aWet             = aw(stationId);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/troposphere/troposphereGpt.h",
    "content": "/***********************************************/\n/**\n* @file troposphereGpt.h\n*\n* @brief GPT empirical troposphere model.\n* @see Troposphere\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2017-02-23\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TROPOSPHEREGPT__\n#define __GROOPS_TROPOSPHEREGPT__\n\n// Latex documentation\n#ifdef DOCSTRING_Troposphere\nstatic const char *docstringTroposphereGpt = R\"(\n\\subsection{GPT}\\label{troposphereType:gpt}\n\nTropospheric delays based on the Global Pressure and Temperature 3 (GPT3) model\n(Landskron and Boehm 2017, DOI: \\href{https://doi.org/10.1007/s00190-017-1066-2}{10.1007/s00190-017-1066-2}).\n\nIt is an empirical model derived from the Vienna Mapping Functions 3\n(VMF3, see \\configClass{viennaMapping}{troposphereType:viennaMapping}) and thus does not require\nadditional mapping coefficients and zenith delay values.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"troposphere.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GPT empirical troposphere model.\n* @ingroup troposphereGroup\n* @see Troposphere */\nclass TroposphereGpt : public Troposphere\n{\n  FileName fileNameGpt;\n  Double   a_ht, b_ht, c_ht;\n\npublic:\n  TroposphereGpt(Config &config);\n ~TroposphereGpt() {}\n\n  void   init(const std::vector<std::string> &stationNames, const std::vector<Vector3d> &stationPositions) override;\n  Double slantDelay                (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  Double mappingFunctionHydrostatic(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  Double mappingFunctionWet        (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  void   mappingFunctionGradient   (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation, Double &dx, Double &dy) const override;\n  void   getAprioriValues          (UInt stationId, const Time &time, Double frequency, Double &zenithDryDelay, Double &zenithWetDelay, Double &gradientDryNorth,\n                                    Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast, Double &aDry, Double &aWet) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/troposphere/troposphereMendesAndPavlis.h",
    "content": "/***********************************************/\n/**\n* @file troposphereMendesAndPavlis.h\n*\n* @brief Atmospheric Delay Correction by Mendes and Pavlis.\n* @see Troposphere\n*\n* @author Torsten Mayer-Guerr\n* @author Barbara Suesser-Rechberger\n* @date 2022-09-24\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TROPOSPHEREMENDESANDPAVLIS__\n#define __GROOPS_TROPOSPHEREMENDESANDPAVLIS__\n\n// Latex documentation\n#ifdef DOCSTRING_Troposphere\nstatic const char *docstringTroposphereMendesAndPavlis = R\"(\n\\subsection{MendesAndPavlis}\\label{troposphereType:mendesAndPavlis}\n\nTropospheric delays based on the Mendes-Pavlis model that employs meteorological data.\n(Mendes et al. (2002), \\href{https://doi.org/10.1029/2001GL014394}{10.1029/2001GL014394} and\nMendes and Pavlis (2004), \\href{https://doi.org/10.1029/2004GL020308}{110.1029/2004GL020308})\n\nThe meteorological data have to be provided via \\configFile{inputfileStationMeteorology}{instrument}.\nThis file contains the temperature, air pressure and humidity and must be first generated using the\nprograms \\program{Crd2NormalPoints}, \\program{Cstg2NormalPoints}, \\program{Merit2NormalPoints} or \\program{Merit2FullRate}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"troposphere.h\"\n#include \"base/polynomial.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Vienna Mapping Function.\n* @ingroup troposphereGroup\n* @see Troposphere */\nclass TroposphereMendesAndPavlis : public Troposphere\n{\n  FileName                       fileNameMeteo, fileNameGeoid;\n  Vector                         latitude, height, f;\n  std::vector<std::vector<Time>> times;       // for each station\n  std::vector<Matrix>            meteorology; // for each station: times x (temperature, pressure, waterVapor)\n\n  Matrix interpolate(UInt stationId, const Time &time, const_MatrixSliceRef A) const;\n\npublic:\n  TroposphereMendesAndPavlis(Config &config);\n ~TroposphereMendesAndPavlis() {}\n\n  void   init(const std::vector<std::string> &stationNames, const std::vector<Vector3d> &stationPositions) override;\n  Double slantDelay                (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  Double mappingFunctionHydrostatic(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  Double mappingFunctionWet        (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  void   mappingFunctionGradient   (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation, Double &dx, Double &dy) const override;\n  void   getAprioriValues          (UInt stationId, const Time &time, Double frequency, Double &zenithDryDelay, Double &zenithWetDelay, Double &gradientDryNorth,\n                                    Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast, Double &aDry, Double &aWet) const override;\n};\n\n/***********************************************/\n\ninline TroposphereMendesAndPavlis::TroposphereMendesAndPavlis(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileStationMeteorology\", fileNameMeteo, Config::MUSTSET, \"meteorology_{loopTime:%y}.{station}.dat\",  \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void TroposphereMendesAndPavlis::init(const std::vector<std::string> &stationNames, const std::vector<Vector3d> &stationPositions)\n{\n  try\n  {\n    latitude = Vector(stationPositions.size());\n    height   = Vector(stationPositions.size());\n    f        = Vector(stationPositions.size());\n    Ellipsoid ellipsoid;\n    for(UInt stationId=0; stationId<stationPositions.size(); stationId++)\n    {\n      Angle L, B;\n      ellipsoid(stationPositions.at(stationId), L, B, height(stationId));\n      latitude(stationId) = B;\n      f(stationId)        = (1. - 0.00266*std::cos(2.*B) - 0.00028e-3 * height(stationId));\n    }\n\n    // read station wise meteorology data\n    meteorology.resize(stationNames.size());\n    times.resize(stationNames.size());\n    for(UInt stationId=0; stationId<stationPositions.size(); stationId++)\n    {\n      VariableList varList;\n      varList.setVariable(\"station\", stationNames.at(stationId));\n      MeteorologicalArc arc = InstrumentFile::read(fileNameMeteo(varList));\n      times.at(stationId)       = arc.times();\n      meteorology.at(stationId) = arc.matrix().column(1, 3); // temperature [K], pressure [Pa], humidity [%]\n\n      // Calculation of the water vapour pressure [Pa] from relative humidity [%]:\n      // Equation source: Marini, J. W. and Murray Jr, C. (1973).\n      // Correction of laser range tracking data for atmospheric refraction at elevations above 10 degrees.\n      for(UInt i=0; i<meteorology.at(stationId).rows(); i++)\n      {\n        const Double T = meteorology.at(stationId)(i, 0)-273.15; // temperature [C°]\n        meteorology.at(stationId)(i, 2) *= 6.11*std::pow(10, 7.5*T/(237.3+T));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Matrix TroposphereMendesAndPavlis::interpolate(UInt stationId, const Time &time, const_MatrixSliceRef A) const\n{\n  try\n  {\n    auto closestTimeIter = std::min_element(times.at(stationId).begin(), times.at(stationId).end(), [&](const Time &t1, const Time &t2)\n                          {return std::fabs((t1-time).seconds()) < std::fabs((t2-time).seconds());});\n\n    Time closestTime = *closestTimeIter;\n\n    if(times.at(stationId).size() >= 2)\n    {\n      // Linear interpolation should be possible but shall be only done if the distance between the points is less than one hour\n      Double distanceToClosestPoint = closestTime.seconds() - time.seconds();\n      auto closestTimeNeighbourIter = closestTimeIter;\n\n      if(distanceToClosestPoint < 0)\n      {\n        if(closestTimeNeighbourIter < (times.at(stationId).end()-1))\n          closestTimeNeighbourIter++;\n      }\n      else\n      {\n        if(closestTimeNeighbourIter > times.at(stationId).begin())\n          closestTimeNeighbourIter--;\n      }\n\n      if((std::fabs(closestTime.seconds() - (*closestTimeNeighbourIter).seconds()) < 60*60) && (closestTimeNeighbourIter != closestTimeIter))\n      {\n        Polynomial polynomial(times.at(stationId), 1, FALSE);\n        Matrix interpolatedValues = polynomial.interpolate({time}, A);\n\n        // Check if interpolation was done\n        if(!std::isnan(sum(interpolatedValues)))\n        {\n          // Interpolation was successful\n          return interpolatedValues;\n        }\n        else\n        {\n          // Interpolation was not done, element which is closest to the given time is returned\n          return A.row(std::distance(times.at(stationId).begin(), closestTimeIter));\n        }\n      }\n      else\n      {\n        // Interpolation was not done, element which is closest to the given time is returned\n        return A.row(std::distance(times.at(stationId).begin(), closestTimeIter));\n      }\n    }\n    else\n    {\n      // Interpolation was not done, element which is closest to the given time is returned\n      return A.row(std::distance(times.at(stationId).begin(), closestTimeIter));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double TroposphereMendesAndPavlis::slantDelay(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const\n{\n  try\n  {\n    Double zenithDryDelay, zenithWetDelay, gradientDryNorth, gradientWetNorth, gradientDryEast, gradientWetEast, aDry, aWet;\n    getAprioriValues(stationId, time, frequency, zenithDryDelay, zenithWetDelay, gradientDryNorth, gradientWetNorth, gradientDryEast, gradientWetEast, aDry, aWet);\n    return (zenithDryDelay + zenithWetDelay) * mappingFunctionHydrostatic(stationId, time, frequency, azimuth, elevation);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double TroposphereMendesAndPavlis::mappingFunctionHydrostatic(UInt stationId, const Time &time, Double /*frequency*/, Angle /*azimuth*/, Angle elevation) const\n{\n  try\n  {\n    // FCULa source: IERS 2010 conventions, Table 9.1\n    constexpr Double a10 = 12100.8e-7;\n    constexpr Double a11 =  1729.5e-9;\n    constexpr Double a12 =   319.1e-7;\n    constexpr Double a13 = -1847.8e-11;\n    constexpr Double a20 = 30496.5e-7;\n    constexpr Double a21 =   234.6e-8;\n    constexpr Double a22 =  -103.5e-6;\n    constexpr Double a23 =  -185.6e-10;\n    constexpr Double a30 =  6877.7e-5;\n    constexpr Double a31 =   197.2e-7;\n    constexpr Double a32 =  -345.8e-5;\n    constexpr Double a33 =   106.0e-9;\n\n    const Double T    = interpolate(stationId, time, meteorology.at(stationId).column(0))(0, 0)-273.15; // convert temperature in [°C]\n    const Double cosL = std::cos(latitude(stationId));\n    const Double a1   = a10 + a11*T + a12*cosL + a13*height(stationId);\n    const Double a2   = a20 + a21*T + a22*cosL + a23*height(stationId);\n    const Double a3   = a30 + a31*T + a32*cosL + a33*height(stationId);\n\n    return mappingFunction(std::sin(elevation), a1, a2, a3);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double TroposphereMendesAndPavlis::mappingFunctionWet(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const\n{\n  return mappingFunctionHydrostatic(stationId, time, frequency, azimuth, elevation);\n}\n\n/***********************************************/\n\ninline void TroposphereMendesAndPavlis::mappingFunctionGradient(UInt /*stationId*/, const Time &/*time*/, Double /*frequency*/, Angle /*azimuth*/, Angle /*elevation*/, Double &dx, Double &dy) const\n{\n  try\n  {\n    throw(Exception(\"not implemented yet\"));\n    dx = dy = 0.;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void TroposphereMendesAndPavlis::getAprioriValues(UInt stationId, const Time &time, Double frequency,\n                                                         Double &zenithDryDelay, Double &zenithWetDelay,\n                                                         Double &gradientDryNorth, Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast,\n                                                         Double &aDry, Double &aWet) const\n{\n  try\n  {\n    // Values source: Mendes, V. B., and Pavlis, E. C. (2004), High-accuracy zenith delay prediction at optical wavelengths, Geophys. Res. Lett., 31, L14602\n    constexpr Double k0     = 238.0185;  // [um^-2]\n    constexpr Double k1     = 19990.975; // [um^-2]\n    constexpr Double k2     = 57.362;    // [um^-2]\n    constexpr Double k3     = 579.55174; // [um^-2]\n    constexpr Double xc     = 375;       // [ppm] carbon dioxide content according to IAG recommendations\n    constexpr Double cco2   = 1 + 0.534e-6 * (xc - 450); // carbon dioxide coefficient\n\n    constexpr Double omega0 =  295.235;  // [-]\n    constexpr Double omega1 =  2.6422;   // [um^2]\n    constexpr Double omega2 = -0.032380; // [um^4]\n    constexpr Double omega3 =  0.004028; // [um^6]\n\n    const Double sigma2 = std::pow(1e-6*frequency/LIGHT_VELOCITY, 2); // [1/um^2]\n    const Double fh   = 1e-2 * (k1*(k0+sigma2)/std::pow((k0-sigma2), 2) + k3*(k2+sigma2)/std::pow(k2-sigma2, 2)) * cco2;\n    const Double fnh  = 0.003101 * (omega0 + 3*omega1*sigma2 + 5*omega2*std::pow(sigma2, 2) + 7*omega3*std::pow(sigma2, 3));\n\n    const Matrix M = interpolate(stationId, time, meteorology.at(stationId)).column(1, 2); // pressure [Pa], waterVaporPressure [Pa]\n    zenithDryDelay = 0.00002416579*fh/f(stationId) * M(0, 0)/*pressure*/;\n    zenithWetDelay = (5.316e-6*fnh - 3.759e-6*fh)/f(stationId) * M(0, 1)/*waterVaporPressure*/;\n\n    gradientDryNorth = gradientWetNorth = gradientDryEast = gradientWetEast = 0.;\n    aDry = aWet = 0.;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/classes/troposphere/troposphereViennaMapping.cpp",
    "content": "/***********************************************/\n/**\n* @file troposphereViennaMapping.cpp\n*\n* @brief Vienna Mapping Functions.\n* @see Troposphere\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-04-03\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"troposphere.h\"\n#include \"troposphereViennaMapping.h\"\n\n/***********************************************/\n\nTroposphereViennaMapping::TroposphereViennaMapping(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileVmfCoefficients\", fileNamesCoefficients, Config::MUSTSET, \"{groopsDataDir}/troposphere/\", \"ah, aw, zhd, zwd coefficients\");\n    readConfig(config, \"inputfileGpt\",             fileNameGpt,           Config::MUSTSET, \"{groopsDataDir}/troposphere/gpt3_grid1deg.dat\",  \"gridded GPT data\");\n    readConfig(config, \"aHeight\",                  a_ht,                  Config::DEFAULT, \"2.53e-5\", \"parameter a (height correction)\");\n    readConfig(config, \"bHeight\",                  b_ht,                  Config::DEFAULT, \"5.49e-3\", \"parameter b (height correction)\");\n    readConfig(config, \"cHeight\",                  c_ht,                  Config::DEFAULT, \"1.14e-3\", \"parameter c (height correction)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereViennaMapping::init(const std::vector<std::string> &/*stationNames*/, const std::vector<Vector3d> &stationPositions)\n{\n  try\n  {\n    initEmpiricalCoefficients(fileNameGpt, stationPositions);\n\n    GriddedData grid;\n    // count epochs\n    times.clear();\n    for(const FileName &fileName : fileNamesCoefficients)\n    {\n      InFileGriddedDataTimeSeries file(fileName);\n      times.insert(times.end(), file.times().begin(), file.times().end());\n      if(!grid.points.size())\n        grid = file.grid();\n      if(!std::equal(grid.points.begin(), grid.points.end(), file.grid().points.begin(), file.grid().points.end(),\n                     [](const Vector3d &p1, const Vector3d &p2) {return (p1-p2).r() < 0.1;}))\n        throw(Exception(fileName.str()+\": VMF grids differ\"));\n      if(file.dataCount() != 8)\n        throw(Exception(fileName.str()+\": data columns \"+file.dataCount()%\"%i != 8\"s));\n      if(file.splineDegree() != 1)\n        throw(Exception(fileName.str()+\": splineDegree \"+file.splineDegree()%\"%i != 1\"s));\n    }\n\n    std::sort(times.begin(), times.end());\n    times.erase(std::unique(times.begin(), times.end()), times.end()); // remove duplicates\n    sampling  = medianSampling(times).mjd();\n    if(!isRegular(times))\n      throw(Exception(\"VMF data epochs are uncontinuous\"));\n\n    // test grid\n    std::vector<std::vector<UInt>>   index(stationPositions.size());\n    std::vector<std::vector<Double>> factor(stationPositions.size());\n    GriddedDataRectangular gridRectangular;\n    if(gridRectangular.init(grid))\n    {\n      // bilinear interpolation factors and indices\n      for(UInt stationId=0; stationId<stationPositions.size(); stationId++)\n      {\n        Double tx   = (gridRectangular.latitudes.front()-latitude(stationId)) * (gridRectangular.latitudes.size()-1)/(gridRectangular.latitudes.front()-gridRectangular.latitudes.back());\n        Double ty   = std::fmod(longitude(stationId)-gridRectangular.longitudes.front()+4*PI, 2*PI)/(2*PI) * gridRectangular.longitudes.size();\n        UInt   idxX = std::min(static_cast<UInt>(std::max(std::floor(tx), 0.)), gridRectangular.latitudes.size()-2);\n        UInt   idxY = static_cast<UInt>(std::floor(ty));\n        tx -= idxX; // latitudinal  interpolation factor [0..1]\n        ty -= idxY; // longitudinal interpolation factor [0..1]\n\n        index.at(stationId).push_back(gridRectangular.longitudes.size()*(idxX  ) + (idxY)  %gridRectangular.longitudes.size());\n        index.at(stationId).push_back(gridRectangular.longitudes.size()*(idxX  ) + (idxY+1)%gridRectangular.longitudes.size());\n        index.at(stationId).push_back(gridRectangular.longitudes.size()*(idxX+1) + (idxY)  %gridRectangular.longitudes.size());\n        index.at(stationId).push_back(gridRectangular.longitudes.size()*(idxX+1) + (idxY+1)%gridRectangular.longitudes.size());\n\n        factor.at(stationId).push_back((1-tx) * (1-ty));\n        factor.at(stationId).push_back((1-tx) * (ty)  );\n        factor.at(stationId).push_back((tx)   * (1-ty));\n        factor.at(stationId).push_back((tx)   * (ty)  );\n      }\n    }\n    else\n    {\n      // find closest station\n      for(UInt stationId=0; stationId<stationPositions.size(); stationId++)\n      {\n        std::vector<Double> distances(grid.points.size());\n        for(UInt i=0; i<distances.size(); i++)\n          distances.at(i) = (stationPositions.at(stationId)-grid.points.at(i)).r();\n        auto iter = std::min_element(distances.begin(), distances.end());\n        if(iter == distances.end() || *iter > 10e3)\n        {\n          Angle  lon, lat;\n          Double h;\n          grid.ellipsoid(stationPositions.at(stationId), lon, lat, h);\n          throw(Exception(\"no troposphere data for station id \"+stationId%\"%i (L=\"s+(lon*RAD2DEG)%\"%f, B=\"s+(lat*RAD2DEG)%\"%f)\"s));\n        }\n        index.at(stationId).push_back(std::distance(distances.begin(), iter));\n        factor.at(stationId).push_back(1.0);\n      }\n    }\n\n    ah  = Matrix(times.size(), stationPositions.size());\n    aw  = Matrix(times.size(), stationPositions.size());\n    zhd = Matrix(times.size(), stationPositions.size());\n    zwd = Matrix(times.size(), stationPositions.size());\n    gnh = Matrix(times.size(), stationPositions.size());\n    geh = Matrix(times.size(), stationPositions.size());\n    gnw = Matrix(times.size(), stationPositions.size());\n    gew = Matrix(times.size(), stationPositions.size());\n\n    for(const FileName &fileName : fileNamesCoefficients)\n    {\n      InFileGriddedDataTimeSeries file(fileName);\n\n      // loop over all epochs in VMF troposphere data file\n      for(UInt k=0; k<file.times().size(); k++)\n      {\n        const UInt   idEpoch = std::distance(times.begin(), std::lower_bound(times.begin(), times.end(), file.times().at(k)));\n        const Matrix data    = file.data(k);\n\n        for(UInt stationId=0; stationId<stationPositions.size(); stationId++)\n        {\n          for(UInt i=0; i<index.at(stationId).size(); i++)\n          {\n            ah (idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 0);\n            aw (idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 1);\n            zhd(idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 2);\n            zwd(idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 3);\n            gnh(idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 4);\n            geh(idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 5);\n            gnw(idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 6);\n            gew(idEpoch, stationId) += factor.at(stationId).at(i) * data(index.at(stationId).at(i), 7);\n          }\n\n          // interpolate to height\n          if(index.at(stationId).size() > 1)\n          {\n            constexpr Double g    = 9.80665;   // mean gravity in [m/s^2]\n            constexpr Double dMtr = 2.8965e-2; // molar mass of dry air in [kg/mol]\n            constexpr Double Rg   = 8.3143;    // universal gas constant in [J/K/mol]\n\n            computeEmpiricalCoefficients(times.at(idEpoch));\n\n            const Double h  = height(stationId) - topo(stationId);\n            const Double Tv = T(stationId) * (1. + 0.6077*Q(stationId));  // virtual temperature in [Kelvin]\n//             const Double Tv = (T(stationId) + dT(stationId) * hRed) * (1. + 0.378*Q(stationId)/(0.622 + 0.378*Q(stationId))); // virtual temperature in [Kelvin]\n            zhd(idEpoch, stationId) *= std::exp(-g*dMtr/Rg/Tv*h);\n            zwd(idEpoch, stationId) *= std::exp(-h/2000);\n          }\n        }\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereViennaMapping::findIndex(const Time &time, UInt &idx, Double &tau) const\n{\n  try\n  {\n    // interpolate coefficients\n    tau = (time-times.front()).mjd()/sampling;\n    if(tau < 0)\n    {\n      if((time-times.front()).seconds()<-1.0) // possible clock error\n        throw(Exception(\"time out of range: \"+time.dateTimeStr() + \" - \" + times.front().dateTimeStr() + \" < -1.0 seconds\"));\n      tau = 0;\n      idx = 0;\n      return;\n    }\n    idx = static_cast<UInt>(std::floor(tau));\n    tau -= idx;\n    if(idx == times.size()-1)\n    {\n      idx -= 1;\n      tau += 1.;\n    }\n    if(idx >= times.size()-1)\n      throw(Exception(\"time out of range: \"+time.dateTimeStr() + \" idx :\" + idx%\"%i\"s +  \" >= \" + (times.size()-1)%\"%i\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TroposphereViennaMapping::slantDelay(UInt stationId, const Time &time, Double /*frequency*/, Angle azimuth, Angle elevation) const\n{\n  try\n  {\n    UInt   idx;\n    Double tau;\n    findIndex(time, idx, tau);\n    computeEmpiricalCoefficients(time);\n\n    const Double _ah  = (1-tau) * ah (idx, stationId) + tau * ah (idx+1, stationId);\n    const Double _aw  = (1-tau) * aw (idx, stationId) + tau * aw (idx+1, stationId);\n    const Double _zhd = (1-tau) * zhd(idx, stationId) + tau * zhd(idx+1, stationId);\n    const Double _zwd = (1-tau) * zwd(idx, stationId) + tau * zwd(idx+1, stationId);\n    const Double _gnh = (1-tau) * gnh(idx, stationId) + tau * gnh(idx+1, stationId);\n    const Double _geh = (1-tau) * gnw(idx, stationId) + tau * gnw(idx+1, stationId);\n    const Double _gnw = (1-tau) * geh(idx, stationId) + tau * geh(idx+1, stationId);\n    const Double _gew = (1-tau) * gew(idx, stationId) + tau * gew(idx+1, stationId);\n\n    const Double sinE = std::sin(elevation);\n    const Double vmfh = mappingFunction(sinE, _ah, bh(stationId), ch(stationId))\n                      + (1./sinE - mappingFunction(sinE, a_ht, b_ht, c_ht)) * height(stationId)*0.001;\n    const Double vmfw = mappingFunction(sinE, _aw, bw(stationId), cw(stationId));\n    const Double mfgh = 1. / (sinE*std::tan(elevation) + 0.0031); // hydrostatic gradient mapping function [Chen and Herring, 1997]\n    const Double mfgw = 1. / (sinE*std::tan(elevation) + 0.0007); // wet -\"-\n\n    return vmfh*_zhd + vmfw*_zwd + (mfgh*_gnh + mfgw*_gnw) * std::cos(azimuth) + (mfgh*_geh + mfgw*_gew) * std::sin(azimuth);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TroposphereViennaMapping::mappingFunctionHydrostatic(UInt stationId, const Time &time, Double /*frequency*/, Angle /*azimuth*/, Angle elevation) const\n{\n  try\n  {\n    UInt   idx;\n    Double tau;\n    findIndex(time, idx, tau);\n    computeEmpiricalCoefficients(time);\n\n    const Double sinE  = std::sin(elevation);\n\n    return mappingFunction(sinE, (1-tau) * ah(idx, stationId) + tau * ah(idx+1, stationId), bh(stationId), ch(stationId))\n           + (1./sinE - mappingFunction(sinE, a_ht, b_ht, c_ht)) * height(stationId)*0.001;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble TroposphereViennaMapping::mappingFunctionWet(UInt stationId, const Time &time, Double /*frequency*/, Angle /*azimuth*/, Angle elevation) const\n{\n  try\n  {\n    UInt   idx;\n    Double tau;\n    findIndex(time, idx, tau);\n    computeEmpiricalCoefficients(time);\n\n    return mappingFunction(std::sin(elevation), (1-tau) * aw(idx, stationId) + tau * aw(idx+1, stationId), bw(stationId), cw(stationId));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereViennaMapping::mappingFunctionGradient(UInt /*stationId*/, const Time &/*time*/, Double /*frequency*/, Angle azimuth, Angle elevation, Double &dx, Double &dy) const\n{\n  try\n  {\n    const Double mfgw = 1./(std::sin(elevation)*std::tan(elevation) + 0.0031); // hydrostatic gradient mapping function [Chen and Herring, 1997] (unitless)\n    dx = mfgw * std::cos(azimuth);\n    dy = mfgw * std::sin(azimuth);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TroposphereViennaMapping::getAprioriValues(UInt stationId, const Time &time, Double /*frequency*/, Double &zenithDryDelay, Double &zenithWetDelay,\n                                                Double &gradientDryNorth, Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast,\n                                                Double &aDry, Double &aWet) const\n{\n  try\n  {\n    UInt   idx;\n    Double tau;\n    findIndex(time, idx, tau);\n\n    aDry             = (1-tau) * ah (idx, stationId) + tau * ah (idx+1, stationId);\n    aWet             = (1-tau) * aw (idx, stationId) + tau * aw (idx+1, stationId);\n    zenithDryDelay   = (1-tau) * zhd(idx, stationId) + tau * zhd(idx+1, stationId);\n    zenithWetDelay   = (1-tau) * zwd(idx, stationId) + tau * zwd(idx+1, stationId);\n    gradientDryNorth = (1-tau) * gnh(idx, stationId) + tau * gnh(idx+1, stationId);\n    gradientWetNorth = (1-tau) * gnw(idx, stationId) + tau * gnw(idx+1, stationId);\n    gradientDryEast  = (1-tau) * geh(idx, stationId) + tau * geh(idx+1, stationId);\n    gradientWetEast  = (1-tau) * gew(idx, stationId) + tau * gew(idx+1, stationId);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/classes/troposphere/troposphereViennaMapping.h",
    "content": "/***********************************************/\n/**\n* @file troposphereViennaMapping.h\n*\n* @brief Vienna Mapping Functions.\n* @see Troposphere\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-04-03\n*/\n/***********************************************/\n\n#ifndef __GROOPS_TROPOSPHEREVIENNAMAPPING__\n#define __GROOPS_TROPOSPHEREVIENNAMAPPING__\n\n// Latex documentation\n#ifdef DOCSTRING_Troposphere\nstatic const char *docstringTroposphereViennaMapping = R\"(\n\\subsection{ViennaMapping}\\label{troposphereType:viennaMapping}\n\nTropospheric delays based on the Vienna Mapping Functions 3 (VMF3) model\n(Landskron and Boehm 2017, DOI: \\href{https://doi.org/10.1007/s00190-017-1066-2}{10.1007/s00190-017-1066-2}).\n\nHydrostatic and wet mapping function coefficients ($a_h$, $a_w$) and zenith delays (ZHD, ZWD) have to be provided\nvia \\configFile{inputfileVmfCoefficients}{griddedDataTimeSeries}. This file can contain either station-specific data\n(see \\program{ViennaMappingFunctionStation2File}) or data on a regular global grid\n(see \\program{ViennaMappingFunctionGrid2File}). In the second case mapping coefficients and zenith delays are\ninterpolated to the requested coordinates. This includes a height correction that requires approximate meteorological\ndata provided via \\configFile{inputfileGpt}{griddedData}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"troposphere.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Vienna Mapping Function.\n* @ingroup troposphereGroup\n* @see Troposphere */\nclass TroposphereViennaMapping : public Troposphere\n{\n  std::vector<FileName> fileNamesCoefficients;\n  FileName              fileNameGpt;\n  Double                a_ht, b_ht, c_ht;\n  std::vector<Time>     times;\n  Double                sampling;\n  Matrix                ah, aw, zhd, zwd, gnh, geh, gnw, gew;\n\n  void findIndex(const Time &time, UInt &idx, Double &tau) const;\n\npublic:\n  TroposphereViennaMapping(Config &config);\n ~TroposphereViennaMapping() {}\n\n  void   init(const std::vector<std::string> &stationNames, const std::vector<Vector3d> &stationPositions) override;\n  Double slantDelay                (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  Double mappingFunctionHydrostatic(UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  Double mappingFunctionWet        (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation) const override;\n  void   mappingFunctionGradient   (UInt stationId, const Time &time, Double frequency, Angle azimuth, Angle elevation, Double &dx, Double &dy) const override;\n  void   getAprioriValues          (UInt stationId, const Time &time, Double frequency, Double &zenithDryDelay, Double &zenithWetDelay, Double &gradientDryNorth,\n                                    Double &gradientWetNorth, Double &gradientDryEast, Double &gradientWetEast, Double &aDry, Double &aWet) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/config/config.cpp",
    "content": "/***********************************************/\n/**\n* @file config.cpp\n*\n* @brief Read a configuration file or writes the configuration options in a XSD-Schema.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2008-07-22\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"base/doodson.h\"\n#include \"base/gnssType.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/system.h\"\n#include \"parser/xml.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/expressionParser.h\"\n#include \"parallel/parallel.h\"\n#include \"classes/condition/condition.h\"\n#include \"classes/loop/loop.h\"\n#include \"programs/program.h\"\n#include \"config.h\"\n\n/***********************************************/\n/*** Stack management **************************/\n/***********************************************/\n\nvoid Config::push(XmlNodePtr xmlNode, ComplexType type, const std::string &name)\n{\n  VariableList varList;\n  std::map<std::string, XmlNodePtr> links;\n  if(stack.size())\n  {\n    varList = stack.top().varList;\n    links   = stack.top().links;\n  }\n  std::string name_ = (name.empty()) ? Config::currentNodeName()+\".\"+xmlNode->getName() : name;\n  stack.emplace(xmlNode, type, name_);\n  stack.top().varList = varList;\n  stack.top().links   = links;\n}\n\n/***********************************************/\n\nvoid Config::pop()\n{\n  if(stack.top().loopPtr) // finish old loop\n    throw(Exception(\"exit node with unfinished loop\"));\n  stack.pop();\n}\n\n/***********************************************/\n\nstd::string Config::currentNodeName() const\n{\n  return stack.top().name;\n}\n\n/***********************************************/\n/*** Normal mode (readConfig) ******************/\n/***********************************************/\n\nConfig::Config(FileName &fileName, const std::map<std::string, std::string> &commandlineGlobals)\n{\n  try\n  {\n    createSchema = FALSE;\n\n    InFile stream(fileName);\n    XmlNodePtr root = XmlNode::read(stream);\n\n    push(root, SEQUENCE, \"groops\");\n\n    // local variables before global?\n    // ------------------------------\n    XmlNodePtr xmlNode = XmlNode::create(\"groopsConfigFile\");\n    xmlNode->setText(fileName.str());\n    stack.top().links[\"groopsConfigFile\"] = xmlNode;\n\n    xmlNode = XmlNode::create(\"workingDir\");\n    xmlNode->setText(System::currentWorkingDirectory());\n    stack.top().links[\"workingDir\"] = xmlNode;\n\n    while((xmlNode = root->findNextChild()))\n    {\n      XmlAttrPtr label = xmlNode->getAttribute(\"label\");\n      if(!label)                           // is not local variable?\n        break;\n      xmlNode = root->getNextChild();      // remove\n      xmlNode->setName(label->getText());  // replace typename with label\n      stack.top().links[xmlNode->getName()] = xmlNode;\n    }\n\n    // global: replace typename with label\n    // -----------------------------------\n    XmlNodePtr global = root->getChild(\"global\");\n    if(global)\n      for(XmlNodePtr &child : global->getChildren())\n      {\n        XmlAttrPtr label = child->getAttribute(\"label\");\n        if(!label)\n          throw(Exception(\"elements in global must have attribute 'label'\"));\n        child->setName(label->getText());\n        stack.top().links[child->getName()] = child;\n      }\n\n    // add global elements from command line\n    // -------------------------------------\n    for(const auto &command : commandlineGlobals)\n    {\n      XmlNodePtr xmlNode = XmlNode::create(command.first);\n      xmlNode->setText(command.second);\n      stack.top().links[command.first] = xmlNode;\n    }\n\n    // set global variables\n    // --------------------\n    for(auto &pair : stack.top().links)\n      if(!pair.second->hasChildren())  // not complex type?\n      {\n        XmlAttrPtr link = pair.second->findAttribute(\"link\");\n        stack.top().varList.setVariable(pair.second->getName(), ((link) ? \"{\"+link->getText()+\"}\" : pair.second->getText()));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool Config::hasName(const std::string &name)\n{\n  for(;;)\n  {\n    if(stack.top().xmlLastChild)\n    {\n      if(stack.top().xmlLastChild->getName() != name)\n        throw(Exception(\"loop error\"));\n      return TRUE;\n    }\n\n    if(!stack.top().xmlNode->findChild(name))\n      return FALSE;\n\n    // local variables before?\n    // -----------------------\n    XmlNodePtr xmlNode;\n    while((xmlNode = stack.top().xmlNode->getNextChild()))\n    {\n      XmlAttrPtr label = xmlNode->getAttribute(\"label\");\n      if(label) // xmlNode is local variable\n      {\n        xmlNode->setName(label->getText());  // replace typename with label\n        stack.top().links[xmlNode->getName()] = xmlNode;\n        if(!xmlNode->hasChildren())          // not complex type? -> variable\n        {\n          XmlAttrPtr link = xmlNode->findAttribute(\"link\");\n          stack.top().varList.setVariable(xmlNode->getName(), ((link) ? \"{\"+link->getText()+\"}\" : xmlNode->getText()));\n        }\n        continue;\n      }\n      if(xmlNode->getName() == name)\n        break;\n      // unknown element: move to end\n      stack.top().xmlNode->addChild(xmlNode);\n    }\n\n    if(xmlNode == nullptr)\n      return FALSE;\n\n    // -----------------------\n    std::function<void(XmlNodePtr&)> resolveLink = [&](XmlNodePtr &xmlNode)\n    {\n\n      XmlAttrPtr link = xmlNode->getAttribute(\"link\");\n      if(link)\n      {\n        XmlNodePtr xmlNodeLink = stack.top().links[link->getText()];\n        if(!xmlNodeLink || xmlNodeLink->getAttribute(\"resolving\"))\n          throw(Exception(std::string(\"cannot resolve link: \")+xmlNode->getName()+\" -> \"+link->getText()+\"'\"));\n\n\n        // add temporary resolving attribute to prevent link loops\n        writeAttribute(xmlNodeLink, \"resolving\", 1);\n\n        XmlNodePtr xmlNodeNew = xmlNodeLink->clone();\n        resolveLink(xmlNodeNew);\n        xmlNodeNew->setName(xmlNode->getName());\n        while(xmlNode->hasAttribute())\n          xmlNodeNew->addAttribute(xmlNode->getNextAttribute());\n        xmlNode = xmlNodeNew;\n\n        // remove attributes as link was resolved successfully\n        xmlNodeLink->getAttribute(\"resolving\");\n      }\n    };\n    // -----------------------\n\n    resolveLink(xmlNode);\n\n    // loop?\n    // -----\n    if(stack.top().loopPtr)\n    {\n      if(!stack.top().loopPtr->iteration(stack.top().varList)) // finish loop\n      {\n        stack.top().varList = stack.top().loopVarListOld; // restore old varList\n        stack.top().loopPtr = nullptr;\n        continue;\n      }\n      stack.top().xmlNode->prependChild(xmlNode->clone());  // restore for next loop\n    }\n    else\n    {\n      // expand loop\n      XmlAttrPtr attr = xmlNode->getAttribute(\"loop\");\n      if(attr)\n      {\n        XmlNodePtr xmlNodeLoop = stack.top().links[attr->getText()];\n        if(!xmlNodeLoop)\n          throw(Exception(std::string(\"cannot resolve loop link: \")+xmlNode->getName()+\" -> '\"+attr->getText()+\"'\"));\n        XmlNodePtr tmp = XmlNode::create(\"tmp\");\n        tmp->addChild(xmlNodeLoop->clone());  // make copy\n        push(tmp, SEQUENCE, currentNodeName());\n        LoopPtr loopPtr;\n        readConfig(*this, xmlNodeLoop->getName(), loopPtr, Config::MUSTSET, \"\", \"\");\n        pop();\n        stack.top().loopPtr = loopPtr;\n        stack.top().loopVarListOld = stack.top().varList;\n        stack.top().xmlNode->prependChild(xmlNode);  // restore for next loop\n        continue;  // start loop\n      }\n    }\n\n    // check condition\n    XmlAttrPtr attr = xmlNode->getAttribute(\"condition\");\n    if(attr)\n    {\n      // expand condition\n      XmlNodePtr xmlNodeCondition = stack.top().links[attr->getText()];\n      if(!xmlNodeCondition)\n        throw(Exception(std::string(\"cannot resolve condition link: '\")+xmlNode->getName()+\"' -> '\"+attr->getText()+\"'\"));\n      attr = nullptr;\n      XmlNodePtr tmp = XmlNode::create(\"tmp\");\n      tmp->addChild(xmlNodeCondition->clone()); // make copy\n      push(tmp, SEQUENCE, currentNodeName());\n      ConditionPtr condition;\n      readConfig(*this, xmlNodeCondition->getName(), condition, Config::MUSTSET, \"\", \"\");\n      pop();\n\n      // check condition\n      if(!condition->condition(stack.top().varList))\n        continue; // node disabled -> try next element\n    }\n\n    stack.top().xmlLastChild = xmlNode;\n    return TRUE;\n  } // for(;;)\n}\n\n/***********************************************/\n\nXmlNodePtr Config::getChild(const std::string &name)\n{\n  try\n  {\n    hasName(name); // get current node in xmlLastChild\n    XmlNodePtr xmlNode;\n    std::swap(stack.top().xmlLastChild, xmlNode);\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool Config::getConfigText(const std::string &name, const std::string &type, Config::Appearance mustSet,\n                           const std::string &defaultValue, const std::string &annotation, Bool parse, std::string &text)\n{\n  if(createSchema)\n  {\n    if((mustSet == Config::DEFAULT) && defaultValue.empty())\n      throw(Exception(\"In readConfig(\"+currentNodeName()+\".\"+name+\", type=\"+type+\"): Config::DEFAULT with empty defaultValue\"));\n    xselement(name, type, mustSet, ONCE, defaultValue, annotation);\n    return FALSE;\n  }\n\n  XmlNodePtr child = getChild(name);\n  if(child)\n  {\n    if(child->hasChildren())\n      throw(Exception(currentNodeName()+\".\"+child->getName()+\" with unexpected children\"));\n    text = child->getText();\n  }\n\n  if(text.empty() && (mustSet == MUSTSET))\n    throw(Exception(\"config element '\"+currentNodeName()+\"' must contain '\"+name+\"'\"));\n  if(text.empty() && (mustSet == DEFAULT))\n    text = defaultValue;\n\n  if(parse)\n  {\n    Bool resolved = TRUE;\n    text = StringParser::parse(name, text, stack.top().varList, resolved);\n    if(!resolved)\n      throw(Exception(\"In readConfig(\"+currentNodeName()+\".\"+name+\", type=\"+type+\")='\"+text+\"': unresolved variables\"));\n  }\n  return !text.empty();\n}\n\n/***********************************************/\n\nBool Config::getConfigValue(const std::string &name, const std::string &type, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation, Double &v)\n{\n  std::string text;\n  try\n  {\n    if(!getConfigText(name, type, mustSet, defaultValue, annotation, TRUE, text))\n      return FALSE;\n    v = ExpressionVariable::parse(text, stack.top().varList);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"'\"+name+\"' = '\"+text+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nBool Config::getConfig(const std::string &name, Config::Appearance mustSet, Config &conf)\n{\n  try\n  {\n    XmlNodePtr xmlNode = XmlNode::create(name);\n    XmlNodePtr child   = getChild(name);\n    if(child)\n      xmlNode->addChild(child);\n    else if(mustSet == MUSTSET)\n      throw(Exception(\"config element '\"+currentNodeName()+\"' must contain '\"+name+\"'\"));\n\n    // make copy\n    conf.createSchema = FALSE;\n    conf.push(xmlNode, Config::SEQUENCE, currentNodeName());\n    conf.stack.top().links   = stack.top().links;\n    conf.stack.top().varList = stack.top().varList;\n\n    return child != nullptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"'\"+name+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nBool Config::getUnboundedConfig(const std::string &name, Config &conf)\n{\n  try\n  {\n    if(stack.top().xmlLastChild || stack.top().loopPtr)\n      throw(Exception(\"last element not yet finished processed\"));\n\n    XmlNodePtr xmlNode = XmlNode::create(name);\n    XmlNodePtr child;\n    while((child = stack.top().xmlNode->findNextChild()))\n    {\n      if((child->getName() == name) || child->findAttribute(\"label\")) // child is element or local variable\n        xmlNode->addChild(stack.top().xmlNode->getNextChild());\n      else if(!stack.top().xmlNode->findChild(name))\n        break;\n    }\n\n    // make copy\n    conf.createSchema = FALSE;\n    conf.push(xmlNode, Config::SEQUENCE, currentNodeName());\n    conf.stack.top().links   = stack.top().links;\n    conf.stack.top().varList = stack.top().varList;\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"'\"+name+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::notEmptyWarning()\n{\n  try\n  {\n    if(stack.top().xmlNode->hasChildren())\n    {\n      logWarningOnce<<\"*** Warning: unknown variables in '\"<<currentNodeName()<<\"' (ignored):\"<<Log::endl;\n      while(stack.top().xmlNode->hasChildren())\n        logWarningOnce<<\"  name = \"<<stack.top().xmlNode->getNextChild()->getName()<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string Config::copy(Config &config, const VariableList &variableList) const\n{\n  try\n  {\n    config.createSchema = FALSE;\n    config.push(stack.top().xmlNode->clone(), Config::SEQUENCE, currentNodeName());\n    config.stack.top().links    = stack.top().links;\n    config.stack.top().varList  = stack.top().varList;\n    config.stack.top().varList += variableList;\n    return stack.top().xmlNode->getName();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/*** Schema mode *******************************/\n/***********************************************/\n\n// Only used by generateDocumentation\nConfig::Config()\n{\n  try\n  {\n    createSchema = TRUE;\n    XmlNodePtr rootNode = XmlNode::create(\"xs:schema\");\n    writeAttribute(rootNode, \"xmlns:xs\",             \"http://www.w3.org/2001/XMLSchema\");\n    writeAttribute(rootNode, \"elementFormDefault\",   \"qualified\");\n    writeAttribute(rootNode, \"attributeFormDefault\", \"unqualified\");\n    push(rootNode, SEQUENCE, \"xs:schema\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::writeSchema(const std::string &fileName)\n{\n  try\n  {\n    Config config;\n    XmlNodePtr rootNode = config.stack.top().xmlNode;\n    config.stack.top().type = Config::COMPLEXTYPE;\n\n    // all types are string types as they can contain expressions\n    config.xssimpleType(\"int\",        \"xs:string\"); //\"xs:int\");\n    config.xssimpleType(\"uint\",       \"xs:string\"); //\"xs:nonNegativeInteger\");\n    config.xssimpleType(\"double\",     \"xs:string\"); //\"xs:double\");\n    config.xssimpleType(\"angle\",      \"xs:string\"); //\"xs:double\");\n    config.xssimpleType(\"boolean\",    \"xs:string\"); //\"xs:boolean\");\n    config.xssimpleType(\"time\",       \"xs:string\"); //\"xs:double\");\n    config.xssimpleType(\"doodson\",    \"xs:string\");\n    config.xssimpleType(\"string\",     \"xs:string\");\n    config.xssimpleType(\"filename\",   \"xs:string\");\n    config.xssimpleType(\"expression\", \"xs:string\");\n    config.xssimpleType(\"gnssType\",   \"xs:string\");\n\n    std::vector<SchemaClass*> classList = SchemaClass::classList();\n    SchemaClass::sort(classList);\n    for(UInt i=0; i<classList.size(); i++)\n    {\n      const std::string name = config.stack.top().name;\n      classList.at(i)->registerConfigSchema(config);\n      if(name != config.stack.top().name)\n        throw(Exception(\"In class \"+classList.at(i)->typeName()+\": Missing endSequence() or endChoice()?\"));\n    }\n\n    XmlNodePtr xmlNodeTypes = rootNode->clone(); // type for the global section\n\n    // list of programs\n    std::string choice;\n    readConfigChoice(config, \"programType\", choice, Config::MUSTSET, \"\", \"\");\n    const auto renamedList = Program::RenamedProgram::renamedList();\n    for(auto &renamed : renamedList)\n      renameDeprecatedChoice(config, choice, renamed.oldName, renamed.newName, renamed.time);\n    std::vector<Program::Program*> programList = Program::Program::programList();\n    Program::Program::sortList(programList);\n    for(auto program : programList)\n    {\n      readConfigChoiceElement(config, program->name(), choice, program->description());\n      const std::string name = config.stack.top().name;\n      program->run(config, Parallel::selfCommunicator());\n      if(name != config.stack.top().name)\n        throw(Exception(\"In program \"+program->name()+\": Missing endSequence() or endChoice()?\"));\n      for(UInt idx : program->tags())\n        config.addAppInfo(\"tag: \"s+Program::tagStrings[idx]);\n    }\n    endChoice(config); // end program\n\n    // type definition finished, now the elements\n    config.stack.top().type = SEQUENCE;\n    config.xscomplexElement(\"groops\", Config::SEQUENCE, Config::MUSTSET, \"\", \"GROOPS (Gravity Recovery Object Oriented Programming System)\");\n    renameDeprecatedConfig(config, \"programme\", \"program\", date2time(2020, 6, 3));\n\n    // global section\n    readConfigSequence(config, \"global\", Config::MUSTSET, \"\", \"global settings\");\n    const auto renamedClassList = RenamedSchemaClass::renamedList();\n    for(auto &renamed : renamedClassList)\n      renameDeprecatedConfig(config, renamed.oldName, renamed.newName, renamed.time);\n    while(xmlNodeTypes->hasChildren())\n    {\n      std::string name;\n      readAttribute(xmlNodeTypes->getNextChild(), \"name\", name, TRUE/*mustSet*/);\n      config.xselement(name, name, Config::OPTIONAL, Config::UNBOUNDED, \"\", \"\");\n    }\n    endSequence(config); // end global\n\n    // program\n    config.xselement(\"program\", \"programType\", Config::OPTIONAL, Config::UNBOUNDED, \"\", \"\");\n    endSequence(config); // end <groops>\n    OutFile file(fileName);\n    XmlNode::write(file, rootNode);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr Config::createSchemaNode(const std::string &name)\n{\n  try\n  {\n    XmlNodePtr xmlNode = createXmlNode(stack.top().xmlNode, name);\n    stack.top().xmlLastChild = xmlNode;\n    return xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::xssimpleType(const std::string &name, const std::string &base)\n{\n  try\n  {\n    XmlNodePtr xmlNode = createSchemaNode(\"xs:simpleType\");\n    writeAttribute(xmlNode, \"name\", name);\n    writeAttribute(createXmlNode(xmlNode, \"xs:restriction\"), \"base\", base);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::xselement(const std::string &name, const std::string &type, Config::Appearance mustSet, Config::AppearanceCount count, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!createSchema)\n      throw(Exception(\"modus of config is not createSchema\"));\n\n    XmlNodePtr xmlNode = createSchemaNode(\"xs:element\");\n    writeAttribute(xmlNode, \"name\", name);\n    writeAttribute(xmlNode, \"type\", type);\n    if(mustSet != MUSTSET)\n      writeAttribute(xmlNode, \"minOccurs\", \"0\");\n    if(count == UNBOUNDED)\n      writeAttribute(xmlNode, \"maxOccurs\", \"unbounded\");\n    if(!defaultValue.empty())\n      writeAttribute(xmlNode, \"default\", defaultValue);\n    if(!annotation.empty())\n      writeXml(createXmlNode(xmlNode, \"xs:annotation\"), \"xs:documentation\", annotation);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::xscomplexElement(const std::string &name, Config::ComplexType type, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    XmlNodePtr xmlNode = createSchemaNode((stack.top().type == COMPLEXTYPE) ? \"xs:complexType\" : \"xs:element\");\n    writeAttribute(xmlNode, \"name\", name);\n    if(!annotation.empty())\n      writeXml(createXmlNode(xmlNode, \"xs:annotation\"), \"xs:documentation\", annotation);\n\n    if(stack.top().type != Config::COMPLEXTYPE) // is not root level?\n    {\n      if(mustSet == OPTIONAL)\n        writeAttribute(xmlNode, \"minOccurs\", \"0\");\n      if(!defaultValue.empty())\n        writeAttribute(xmlNode, \"default\", defaultValue);\n      xmlNode = createXmlNode(xmlNode, \"xs:complexType\"); // <xs:element> -> <xs:complexType>\n    }\n\n    if(type==SEQUENCE)\n      push(createXmlNode(xmlNode, \"xs:sequence\"), SEQUENCE, currentNodeName()+\".\"+name);\n    else\n      push(createXmlNode(xmlNode, \"xs:choice\"), CHOICE, currentNodeName()+\".\"+name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::addAppInfo(const std::string &text)\n{\n  try\n  {\n    StackNode top = stack.top();\n    stack.pop();\n    if(!stack.empty())\n    {\n      XmlNodePtr xmlNode = stack.top().xmlLastChild;\n      if(!xmlNode)\n        throw(Exception(top.name+ \" \" +text));\n      XmlNodePtr xmlAnnotation = xmlNode->findChild(\"xs:annotation\");\n      if(!xmlAnnotation)\n      {\n        xmlAnnotation = XmlNode::create(\"xs:annotation\");\n        xmlNode->prependChild(xmlAnnotation);\n      }\n      writeXml(xmlAnnotation, \"xs:appinfo\", text);\n    }\n    stack.push(top);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Config::setNodeUnbounded()\n{\n  try\n  {\n    if(!stack.top().xmlLastChild)\n      throw(Exception(\"schemaNode = nullptr\"));\n    writeAttribute(stack.top().xmlLastChild, \"maxOccurs\", \"unbounded\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nXmlNodePtr Config::table()\n{\n  try\n  {\n    return stack.top().xmlNode;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid ProgramConfig::run(VariableList &variableList, Parallel::CommunicatorPtr comm) const\n{\n  try\n  {\n    Config config;\n    const std::string name = copy(config, variableList);\n\n    std::string type;\n    while(readConfigChoice(config, name, type, OPTIONAL, \"\", \"\"))\n    {\n      for(auto &renamed : Program::RenamedProgram::renamedList())\n        renameDeprecatedChoice(config, type, renamed.oldName, renamed.newName, renamed.time);\n\n      for(auto &program : Program::Program::programList())\n        if(readConfigChoiceElement(config, program->name(), type, \"\"))\n        {\n          std::string comment;\n          StackNode top = config.stack.top();\n          config.stack.pop(); // comment is given in <program> not in <choiceElement>\n          XmlAttrPtr attr = config.stack.top().xmlNode->getAttribute(\"comment\");\n          if(attr)\n            comment = attr->getText();\n          config.stack.push(top);\n\n          Parallel::barrier(comm);\n          if(comment.empty())\n            logStatus<<\"--- \"<<program->name()<<\" ---\"<<Log::endl;\n          else\n          {\n            try\n            {\n              Bool resolved = TRUE;\n              comment = StringParser::parse(\"comment\", comment, config.getVarList(), resolved);\n            }\n            catch(std::exception &/*e*/) {}\n            logStatus<<\"--- \"<<program->name()<<\" (\"<<comment<<\") ---\"<<Log::endl;\n          }\n          program->run(config, comm);\n          Parallel::barrier(comm);\n          break;\n        }\n\n      endChoice(config);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/*** Functions *********************************/\n/***********************************************/\n\nBool isCreateSchema(Config &config)\n{\n  return config.createSchema;\n}\n\n/***********************************************/\n\nvoid renameDeprecatedConfig(Config &config, const std::string &oldName, const std::string &newName, const Time &time)\n{\n  try\n  {\n    if(isCreateSchema(config))\n    {\n      config.addAppInfo(\"rename: \"+oldName+\" = \"+newName);\n      return;\n    }\n\n    for(;;)\n    {\n      XmlNodePtr xmlChild = config.stack.top().xmlNode->findChild(oldName);\n      if(!xmlChild)\n        break;\n      logWarningOnce<<\"DEPRECATED (please update the config file in the GUI): \"\n                    <<\"In '\"<<config.currentNodeName()<<\"':\"<<\" config element '\"<<oldName<<\"' has new name '\"<<newName<<\"' since \"<<time.dateStr()<<Log::endl;\n      xmlChild->setName(newName);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid renameDeprecatedChoice(Config &config, std::string &type, const std::string &oldName, const std::string &newName, const Time &time)\n{\n  try\n  {\n    if(isCreateSchema(config))\n    {\n      config.addAppInfo(\"rename: \"+oldName+\" = \"+newName);\n      return;\n    }\n\n    if(type == oldName)\n    {\n      logWarningOnce<<\"DEPRECATED (please update the config file in the GUI): \"\n                    <<\"'\"<<config.currentNodeName()<<\"':' has new choice name '\"<<newName<<\"' since \"<<time.dateStr()<<Log::endl;\n      type = newName;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool hasName(Config &config, const std::string &name, Config::Appearance mustSet)\n{\n  try\n  {\n    if(isCreateSchema(config))\n      return TRUE;\n\n    const Bool found = config.hasName(name);\n    if((mustSet == Config::MUSTSET) && !found)\n      throw(Exception(\"config '\"+config.currentNodeName()+\"' must contain '\"+name+\"'\"));\n    return found;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool readConfigSequence(Config &config, const std::string &name, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    config.xscomplexElement(name, Config::SEQUENCE, mustSet, defaultValue, annotation);\n    return TRUE;\n  }\n\n  XmlNodePtr child = config.getChild(name);\n  if(child==nullptr)\n  {\n    if(mustSet == Config::MUSTSET)\n      throw(Exception(\"config '\"+config.currentNodeName()+\"' must contain '\"+name+\"'\"));\n    return FALSE;\n  }\n  config.push(child, Config::SEQUENCE);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid endSequence(Config &config)\n{\n  if(isCreateSchema(config))\n  {\n    Bool hasChildren = config.stack.top().xmlNode->hasChildren();\n    config.pop();\n    if(!hasChildren) // without children -> remove complexType\n      config.stack.top().xmlLastChild->getChild(\"xs:complexType\");\n    return;\n  }\n\n  config.notEmptyWarning();\n  config.pop();\n}\n\n/***********************************************/\n\nBool readConfigChoice(Config &config, const std::string &name, std::string &choice, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    config.xscomplexElement(name, Config::CHOICE, mustSet, defaultValue, annotation);\n    return TRUE;\n  }\n\n  XmlNodePtr xmlNode = config.getChild(name);\n  if(!xmlNode)\n  {\n    if(mustSet == Config::MUSTSET)\n      throw(Exception(\"config '\"+config.currentNodeName()+\"' must contain '\"+name+\"'\"));\n    choice = \"\";\n    return FALSE;\n  }\n  XmlNodePtr child = xmlNode->getNextChild();\n  if(!child)\n    throw(Exception(\"config choice element '\"+name+\"' in '\"+config.currentNodeName()+\"' has no child\"));\n  choice = child->getName();\n\n  config.push(xmlNode, Config::CHOICE);\n  config.push(child,   Config::CHOICE, config.currentNodeName()+\"(\"+choice+\")\");\n  return TRUE;\n}\n\n/***********************************************/\n\nBool readConfigChoiceElement(Config &config, const std::string &name, const std::string &choice, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    if(config.stack.top().type == Config::SEQUENCE) // is last choice element a SEQUENCE?\n      endSequence(config);\n    config.xscomplexElement(name, Config::SEQUENCE, Config::MUSTSET, \"\", annotation);\n    return TRUE;\n  }\n\n  return (name == choice);\n}\n\n/***********************************************/\n\nvoid endChoice(Config &config)\n{\n  if(isCreateSchema(config))\n  {\n    if(config.stack.top().type == Config::SEQUENCE) // is last choice element a SEQUENCE?\n      endSequence(config);\n    config.pop();\n    return;\n  }\n\n  config.notEmptyWarning();\n  config.pop();\n  config.pop();\n}\n\n/***********************************************/\n/*** Read Simple Elements **********************/\n/***********************************************/\n\n// read Int\ntemplate<> Bool readConfig(Config &config, const std::string &name, Int &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  Double v;\n  Bool   found = config.getConfigValue(name, \"int\", mustSet, defaultValue, annotation, v);\n  if(found)\n    var = static_cast<Int>(round(v));\n  return found;\n}\n\n/***********************************************/\n\n// read UInt\ntemplate<> Bool readConfig(Config &config, const std::string &name, UInt &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  Double v;\n  Bool   found = config.getConfigValue(name, \"uint\", mustSet, defaultValue, annotation, v);\n  if(found)\n    var = static_cast<UInt>(round(v));\n  return found;\n}\n\n/***********************************************/\n\n// read Double\ntemplate<> Bool readConfig(Config &config, const std::string &name, Double &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  Double v;\n  Bool   found = config.getConfigValue(name, \"double\", mustSet, defaultValue, annotation, v);\n  if(found)\n    var = v;\n  return found;\n}\n\n/***********************************************/\n\n// read std::string\ntemplate<> Bool readConfig(Config &config, const std::string &name, std::string &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string text;\n  Bool found = config.getConfigText(name, \"string\", mustSet, defaultValue, annotation, TRUE, text);\n  if(found)\n    var = text;\n  return found;\n}\n\n/***********************************************/\n\n// read std::string\ntemplate<> Bool readConfig(Config &config, const std::string &name, std::pair<std::string, VariableList> &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string text;\n  Bool found = config.getConfigText(name, \"string\", mustSet, defaultValue, annotation, FALSE, text);\n  if(found)\n  {\n    Bool resolved = TRUE;\n    std::string textResolved = StringParser::parse(name, text, VariableList(), resolved);\n    if(resolved)\n      var = std::pair<std::string, VariableList>(textResolved, VariableList());\n    else\n      var = std::pair<std::string, VariableList>(text, config.getVarList());\n  }\n  return found;\n}\n\n/***********************************************/\n\n// read Bool\ntemplate<> Bool readConfig(Config &config, const std::string &name, Bool &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  Double v;\n  Bool   found = config.getConfigValue(name, \"boolean\", mustSet, defaultValue, annotation, v);\n  if(found)\n    var = static_cast<Bool>(v);\n  return found;\n}\n\n/***********************************************/\n\n// read Angle\ntemplate<> Bool readConfig(Config &config, const std::string &name, Angle &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  Double v;\n  Bool   found = config.getConfigValue(name, \"angle\", mustSet, defaultValue, annotation, v);\n  if(found)\n    var = Angle(v*DEG2RAD);\n  return found;\n}\n\n/***********************************************/\n\n// read Time\ntemplate<> Bool readConfig(Config &config, const std::string &name, Time &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  Double v;\n  Bool   found = config.getConfigValue(name, \"time\", mustSet, defaultValue, annotation, v);\n  if(found)\n    var = mjd2time(v);\n  return found;\n}\n\n/***********************************************/\n\n// read Doodson\ntemplate<> Bool readConfig(Config &config, const std::string &name, Doodson &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string text;\n  Bool found = config.getConfigText(name, \"doodson\", mustSet, defaultValue, annotation, TRUE, text);\n  if(found)\n    var = Doodson(text);\n  return found;\n}\n\n/***********************************************/\n\n// read FileName\ntemplate<> Bool readConfig(Config &config, const std::string &name, FileName &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string text;\n  Bool found = config.getConfigText(name, \"filename\", mustSet, defaultValue, annotation, FALSE, text);\n  if(found)\n  {\n    Bool resolved = TRUE;\n    std::string textResolved = StringParser::parse(name, text, VariableList(), resolved);\n    if(resolved)\n      var = FileName(textResolved);\n    else\n      var = FileName(text, config.getVarList());\n  }\n  return found;\n}\n\n/***********************************************/\n\n// read Expression\ntemplate<> Bool readConfig(Config &config, const std::string &name, ExpressionVariablePtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string text;\n  Bool found = config.getConfigText(name, \"expression\", mustSet, defaultValue, annotation, FALSE, text);\n  if(found)\n    var = std::make_shared<ExpressionVariable>(name, text, config.getVarList());\n  return found;\n}\n\n/***********************************************/\n\n// read GnssType\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssType &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string text;\n  Bool found = config.getConfigText(name, \"gnssType\", mustSet, defaultValue, annotation, TRUE, text);\n  if(found)\n    var = GnssType(text);\n  return found;\n}\n\n/***********************************************/\n\n// read Program\ntemplate<> Bool readConfig(Config &config, const std::string &name, ProgramConfig &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    config.xselement(name, \"programType\", mustSet, Config::UNBOUNDED, defaultValue, annotation);\n    return FALSE;\n  }\n\n  return config.getUnboundedConfig(name, var);\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/config/config.h",
    "content": "/***********************************************/\n/**\n* @file config.h\n*\n* @brief Reads a configuration file or writes configuration options to an XSD Schema.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2008-07-22\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONFIG__\n#define __GROOPS_CONFIG__\n\n#include \"base/import.h\"\n#include \"parser/xml.h\"\n#include \"parser/expressionParser.h\"\n#include \"inputOutput/fileName.h\"\n#include \"parallel/parallel.h\"\n\n/** @addtogroup configGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Loop;\ntypedef std::shared_ptr<Loop> LoopPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Reads a configuration file or writes configuration options to an XSD Schema. */\nclass Config\n{\npublic:\n  enum Appearance      {MUSTSET, DEFAULT, OPTIONAL};\n  enum AppearanceCount {ONCE, UNBOUNDED};\n  enum ComplexType     {CHOICE, SEQUENCE, COMPLEXTYPE};\n\n  /** @brief Creates a Configuration from an XML file.\n  * Elements from @a Config can be read with @a readConfig. */\n  Config(FileName &fileName, const std::map<std::string, std::string> &commandlineGlobals = std::map<std::string, std::string>());\n\n  Config(Config &&)                 = default; //!< Move is allowed\n  Config(const Config &)            = delete;  //!< Copy constructor not allowed\n  Config &operator=(const Config &) = delete;  //!< Assignment not allowed\n\n  /** @brief Gives the parsed content of the node with @a name. */\n  Bool getConfigText(const std::string &name, const std::string &type, Config::Appearance mustSet,\n                     const std::string &defaultValue, const std::string &annotation, Bool parse, std::string &text);\n\n  /** @brief Gives the parsed content of the node with @a name. */\n  Bool getConfigValue(const std::string &name, const std::string &type, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation, Double &v);\n\n  /** @brief Removes the node with @a name from @a config and stores it in @a conf. */\n  Bool getConfig(const std::string &name, Config::Appearance mustSet, Config &conf);\n\n  /** @brief Removes all nodes with @a name from @a config and stores it in @a conf.\n  * The number of elements is unknown as loops and conditions are not evaluated.  */\n  Bool getUnboundedConfig(const std::string &name, Config &conf);\n\n  /** @brief Reads the first variable(s) @p var.\n  * The nodes are not removed from the config.\n  * Should be used after @a readConfigLater. */\n  template<typename T> void read(T &var, VariableList &variableList) const;\n\n  /** @brief Gets the current variable list. */\n  VariableList &getVarList() {return stack.top().varList;}\n\n  // --- Schema mode ----\n\n  /** @brief Default Constructor.\n  * Schema mode. Only used by generateDocumentation. */\n  Config();\n\n  /** @brief Writes configuration options to an XSD Schema file.\n  * Every program and class will be called. A call to @a readConfig does\n  * not read any variables but identifies the configuration options.\n  * These options will be saved in an XSD Schema file. */\n  static void writeSchema(const std::string &fileName);\n\n  /** @brief Registers an element in an XSD Schema. */\n  void xselement(const std::string &name, const std::string &type, Config::Appearance mustSet, Config::AppearanceCount count, const std::string &defaultValue, const std::string &annotation);\n\n  /** @brief XML node with elements for documentationTable. */\n  XmlNodePtr table();\n\n  /** @brief Nested name of the current xmlNode. */\n  std::string currentNodeName() const;\n\nprotected:\n  // Internal class\n  class StackNode\n  {\n  public:\n    std::string  name;\n    ComplexType  type;\n    XmlNodePtr   xmlNode;        // complex node with children\n    XmlNodePtr   xmlLastChild;   // last processed child\n    LoopPtr      loopPtr;\n    VariableList loopVarListOld; // varList without loop variables\n    VariableList varList;\n    std::map<std::string, XmlNodePtr> links;\n\n    StackNode(XmlNodePtr _xmlNode, ComplexType _type, const std::string &_name) : name(_name), type(_type), xmlNode(_xmlNode) {}\n  };\n\n  std::stack<StackNode>  stack;\n  Bool                   createSchema;\n\n  // stack management\n  void         push(XmlNodePtr xmlNode, ComplexType type, const std::string &name=std::string());\n  void         pop();\n\n  // normal mode\n  Bool         hasName(const std::string &name);\n  XmlNodePtr   getChild(const std::string &name);\n  void         notEmptyWarning();\n  std::string  copy(Config &config, const VariableList &variableList) const;\n\n  // schema mode\n  XmlNodePtr   createSchemaNode(const std::string &name);\n  void         xssimpleType(const std::string &name, const std::string &baseType);\n  void         xscomplexElement(const std::string &name, Config::ComplexType type, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n  void         addAppInfo(const std::string &text);\npublic:\n  void         setNodeUnbounded(); // need access from readConfig(std::vector<T> &var, ...)\n\n  friend class ProgramConfig;\n  friend Bool isCreateSchema(Config &config);\n  friend void renameDeprecatedConfig(Config &config, const std::string &oldName, const std::string &newName, const Time &time);\n  friend void renameDeprecatedChoice(Config &config, std::string &type, const std::string &oldName, const std::string &newName, const Time &time);\n  friend Bool hasName(Config &config, const std::string &name, Config::Appearance mustSet);\n  friend Bool readConfigSequence(Config &config, const std::string &name, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n  friend void endSequence(Config &config);\n  friend Bool readConfigChoice(Config &config, const std::string &name, std::string &choice, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n  friend Bool readConfigChoiceElement(Config &config, const std::string &name, const std::string &choice, const std::string &annotation);\n  friend void endChoice(Config &config);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Config elements of a program.\n* It can be read with @a readConfig().\n* The config is evaluated and the program is executed with @a run().\n* @ingroup configGroup */\nclass ProgramConfig : public Config\n{\npublic:\n  void run(VariableList &variableList, Parallel::CommunicatorPtr comm) const;\n};\n\n/***** FUNCTIONS ***********************************/\n\n/** @brief Checks if functions are called in schema mode.\n* No code is allowed except the readConfig functions in schema mode.\n* @ingroup configGroup */\nBool isCreateSchema(Config &config);\n\n/** @brief Does Config have an element with @a name?\n* If @a mustSet is MUSTSET and name is not found, an exception is thrown.\n* @ingroup configGroup */\nBool hasName(Config &config, const std::string &name, Config::Appearance mustSet=Config::OPTIONAL);\n\n/** @brief Indicates a renamed config element.\n* Must be called before the @a readConfig functions.\n* @ingroup configGroup */\nvoid renameDeprecatedConfig(Config &config, const std::string &oldName, const std::string &newName, const Time &time);\n\n/** @brief Indicates a renamed choice element.\n* Must be called after @a readConfigChoice and before the @a readConfigChoiceElement functions.\n* @ingroup configGroup */\nvoid renameDeprecatedChoice(Config &config, std::string &type, const std::string &oldName, const std::string &newName, const Time &time);\n\n/** @brief Starts a group of readConfig elements.\n* If @a mustSet is MUSTSET and name is not found, an exception is thrown.\n* @ingroup configGroup */\nBool readConfigSequence(Config &config, const std::string &name, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/** @brief Ends a group of readConfig elements.\n* Must be called only if the @a readConfigSequence returns TRUE.\n* @ingroup configGroup */\nvoid endSequence(Config &config);\n\n/** @brief Starts a choice.\n* If the result is TRUE, the selected choice is given in @a choice.\n* If @a mustSet is MUSTSET and name is not found, an exception is thrown.\n* @ingroup configGroup */\nBool readConfigChoice(Config &config, const std::string &name, std::string &choice, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/** @brief Checks the selected choice.\n* Returns TRUE if @a name is the selected @a choice.\n* In schema mode all possible @a readConfigChoiceElement must be called.\n* @ingroup configGroup */\nBool readConfigChoiceElement(Config &config, const std::string &name, const std::string &choice, const std::string &annotation=\"\");\n\n/** @brief Ends a group of choice elements.\n* Must be called only if the @a readConfigChoice returns TRUE.\n* @ingroup configGroup */\nvoid endChoice(Config &config);\n\n/** @brief Reads a variable from @a config.\n* If @a name is in the @a config, the value is set in @a var and TRUE is returned.\n* If @a name is not in the @a config or the content is empty, FALSE is returned. In this case the value of @a var depends on @a mustSet:\n* @a mustSet = Config::MUSTSET: an exception is thrown.\n* @a mustSet = Config::OPTIONAL: @a var is left untouched and @a defaultValue is not used (@a defaultValue might be set as a hint for groopsGui).\n* @a mustSet = Config::DEFAULT: @a var is set to @a defaultValue (or in case an empty class is created).\n* @ingroup configGroup */\ntemplate<typename T> Bool readConfig(Config &config, const std::string &name, T &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/** @brief Removes the config of a variable from @a config and stores it in configNew.\n* It can be later evaluated with configNew.read(). @a var is untouched and only used to determine the type.\n* @ingroup configGroup */\ntemplate<typename T> Bool readConfigLater(Config &config, const std::string &name, const T &var, Config &configNew, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/** @brief Removes the config of a variable from @a config and stores it in configNew.\n* It can be later evaluated with configNew.read(). @a var is untouched and only used to determine the type.\n* @ingroup configGroup */\ntemplate<typename T> Bool readConfigLater(Config &config, const std::string &name, const std::vector<T> &var, std::vector<Config> &configNew, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n/***** INLINES   *******************************/\n/***********************************************/\n\ntemplate<typename T> inline void Config::read(T &var, VariableList &variableList) const\n{\n  try\n  {\n    Config config;\n    const std::string name = copy(config, variableList);\n    readConfig(config, name, var, MUSTSET, \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename T> inline Bool readConfig(Config &config, const std::string &name, std::vector<T> &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    if(mustSet == Config::DEFAULT)\n      throw(Exception(\"In readConfig(\"+config.currentNodeName()+\".\"+name+\"): Config::DEFAULT is not allowed for std::vector. Please change to Config::OPTIONAL\"));\n    T tmp;\n    readConfig(config, name, tmp, mustSet, defaultValue, annotation);\n    config.setNodeUnbounded();\n    return FALSE;\n  }\n\n  if(hasName(config, name, mustSet))\n    do\n    {\n      var.resize(var.size()+1);\n      readConfig(config, name, var.back(), mustSet, defaultValue, annotation);\n    }\n    while(hasName(config, name, Config::OPTIONAL));\n\n  return (var.size()!=0);\n}\n\n/***********************************************/\n\ntemplate<typename T> inline Bool readConfigLater(Config &config, const std::string &name, const T &var, Config &configNew, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    readConfig(config, name, const_cast<T&>(var), mustSet, defaultValue, annotation);\n    return FALSE;\n  }\n\n  // get type and unbounded\n  Config configXsd;\n  readConfig(configXsd, name, const_cast<T&>(var), mustSet, defaultValue, annotation);\n  XmlNodePtr xmlNode = configXsd.table()->getNextChild();\n\n  if(xmlNode->getAttribute(\"maxOccurs\"))\n    return config.getUnboundedConfig(name, configNew);\n  return config.getConfig(name, mustSet, configNew);\n}\n\n/***********************************************/\n\ntemplate<typename T> inline Bool readConfigLater(Config &config, const std::string &name, const std::vector<T> &var, std::vector<Config> &configNew, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(isCreateSchema(config))\n  {\n    readConfig(config, name, const_cast<std::vector<T>&>(var), mustSet, defaultValue, annotation);\n    return FALSE;\n  }\n\n  if(hasName(config, name, mustSet))\n    do\n    {\n      configNew.resize(configNew.size()+1);\n      config.getConfig(name, mustSet, configNew.back());\n    }\n    while(hasName(config, name, Config::OPTIONAL));\n\n  return (configNew.size()!=0);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/config/configRegister.h",
    "content": "/***********************************************/\n/**\n* @file configRegister.h\n*\n* @brief Interface for classes in groops.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-20\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_CONFIGREGISTER__\n#define __GROOPS_CONFIGREGISTER__\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"config/generateDocumentation.h\"\n\n/** @addtogroup configGroup */\n/// @{\n\n/***** DEFINE **********************************/\n\n// workaround for Microsoft compiler\n// https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/index\n#define _GROOPS_PASS_ON(...) __VA_ARGS__\n\n/// calls func for every following argument, e.g. _GROOPS_FOR_EACH(test, a, b, c) -> test(a) test(b) test(c)\n#define _GROOPS_FOR_EACH(_func, ...) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GRROPS_FUNC)(_GROOPS_func, _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_NARG)(__VA_ARGS__)))(_func, __VA_ARGS__))\n\n// Macro magic: Overloading Macro on Number of Arguments\n// https://stackoverflow.com/questions/11761703/overloading-macro-on-number-of-arguments/11763277#11763277\n#define _GROOPS_ARG_N(_01, _02, _03, _04, _05, _06, _07, _08, _09, _10,\\\n                      _11, _12, _13, _14, _15, _16, _17, _18, _19, _20,\\\n                      _21, _22, _23, _24, _25, _26, _27, _28, _29, _30,\\\n                      _31, _32, _33, _34, _35, _36, _37, _38, _39, _40,\\\n                      _41, _42, _43, _44, _45, _46, _47, _48, _49, N, ...) N\n\n#define _GROOPS_SEQUENCE 49, 48, 47, 46, 45, 44, 43, 42, 41, 40,\\\n                         39, 38, 37, 36, 35, 34, 33, 32, 31, 30,\\\n                         29, 28, 27, 26, 25, 24, 23, 22, 21, 20,\\\n                         19, 18, 17, 16, 15, 14, 13, 12, 11, 10,\\\n                         09, 08, 07, 06, 05, 04, 03, 02, 01, 00\n\n#define _GROOPS_func00(_func)\n#define _GROOPS_func01(_func, x)      _func(x)\n#define _GROOPS_func02(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func01)(_func, __VA_ARGS__))\n#define _GROOPS_func03(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func02)(_func, __VA_ARGS__))\n#define _GROOPS_func04(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func03)(_func, __VA_ARGS__))\n#define _GROOPS_func05(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func04)(_func, __VA_ARGS__))\n#define _GROOPS_func06(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func05)(_func, __VA_ARGS__))\n#define _GROOPS_func07(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func06)(_func, __VA_ARGS__))\n#define _GROOPS_func08(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func07)(_func, __VA_ARGS__))\n#define _GROOPS_func09(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func08)(_func, __VA_ARGS__))\n#define _GROOPS_func10(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func09)(_func, __VA_ARGS__))\n#define _GROOPS_func11(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func10)(_func, __VA_ARGS__))\n#define _GROOPS_func12(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func11)(_func, __VA_ARGS__))\n#define _GROOPS_func13(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func12)(_func, __VA_ARGS__))\n#define _GROOPS_func14(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func13)(_func, __VA_ARGS__))\n#define _GROOPS_func15(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func14)(_func, __VA_ARGS__))\n#define _GROOPS_func16(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func15)(_func, __VA_ARGS__))\n#define _GROOPS_func17(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func16)(_func, __VA_ARGS__))\n#define _GROOPS_func18(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func17)(_func, __VA_ARGS__))\n#define _GROOPS_func19(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func18)(_func, __VA_ARGS__))\n#define _GROOPS_func20(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func19)(_func, __VA_ARGS__))\n#define _GROOPS_func21(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func20)(_func, __VA_ARGS__))\n#define _GROOPS_func22(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func21)(_func, __VA_ARGS__))\n#define _GROOPS_func23(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func22)(_func, __VA_ARGS__))\n#define _GROOPS_func24(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func23)(_func, __VA_ARGS__))\n#define _GROOPS_func25(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func24)(_func, __VA_ARGS__))\n#define _GROOPS_func26(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func25)(_func, __VA_ARGS__))\n#define _GROOPS_func27(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func26)(_func, __VA_ARGS__))\n#define _GROOPS_func28(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func27)(_func, __VA_ARGS__))\n#define _GROOPS_func29(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func28)(_func, __VA_ARGS__))\n#define _GROOPS_func30(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func29)(_func, __VA_ARGS__))\n#define _GROOPS_func31(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func30)(_func, __VA_ARGS__))\n#define _GROOPS_func32(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func31)(_func, __VA_ARGS__))\n#define _GROOPS_func33(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func32)(_func, __VA_ARGS__))\n#define _GROOPS_func34(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func33)(_func, __VA_ARGS__))\n#define _GROOPS_func35(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func34)(_func, __VA_ARGS__))\n#define _GROOPS_func36(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func35)(_func, __VA_ARGS__))\n#define _GROOPS_func37(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func36)(_func, __VA_ARGS__))\n#define _GROOPS_func38(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func37)(_func, __VA_ARGS__))\n#define _GROOPS_func39(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func38)(_func, __VA_ARGS__))\n#define _GROOPS_func40(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func39)(_func, __VA_ARGS__))\n#define _GROOPS_func41(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func40)(_func, __VA_ARGS__))\n#define _GROOPS_func42(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func41)(_func, __VA_ARGS__))\n#define _GROOPS_func43(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func42)(_func, __VA_ARGS__))\n#define _GROOPS_func44(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func43)(_func, __VA_ARGS__))\n#define _GROOPS_func45(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func44)(_func, __VA_ARGS__))\n#define _GROOPS_func46(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func45)(_func, __VA_ARGS__))\n#define _GROOPS_func47(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func46)(_func, __VA_ARGS__))\n#define _GROOPS_func48(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func47)(_func, __VA_ARGS__))\n#define _GROOPS_func49(_func, x, ...) _func(x) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_func48)(_func, __VA_ARGS__))\n\n#define _GRROPS_FUNC_(name, n) name##n\n#define _GRROPS_FUNC(name, n) _GRROPS_FUNC_(name, n)\n#define _GROOPS_NARG(...)  _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_NARG_)(__VA_ARGS__,_GROOPS_SEQUENCE))\n#define _GROOPS_NARG_(...) _GROOPS_PASS_ON(_GROOPS_PASS_ON(_GROOPS_ARG_N)(__VA_ARGS__))\n\n/***********************************************/\n\n/** @brief Macro for class registration in schema and documenation.\n* Call: GROOPS_REGISTER_CLASS_WITHOUT_SUBS(ClassName, \"schemaType\").\n* A string named \"docstring{ClassName}\" must exist.\n* The class must provide a static function \"create(Config &config, const std::string &name)\".\n* @ingroup configGroup */\n#define GROOPS_REGISTER_CLASS_WITHOUT_SUBS(_className, _typeName)\\\n_GROOPS_REGISTER_CLASS(_className, _typeName)\\\ninline void _Class##_className::generateDocumentation(Documentation &documentation) const\\\n{\\\n  Config config;\\\n  _className::create(config, typeName());\\\n  documentation.writeText(docstring##_className);\\\n  documentation.writeConfigTable(config);\\\n}\\\n// end macro\n\n/***********************************************/\n\n/** @brief Macro for class registration in schema and documenation.\n* Call: GROOPS_REGISTER_CLASS(ClassName, \"schemaType\", subClasses...)\n* A string named \"docstring{ClassName}\" must exist for the class and subclasses.\n* The class must provide a static function \"create(Config &config, const std::string &name)\".\n* The sub classes must have a constructor of type {ClassName}(Config &config).\n* @ingroup configGroup */\n#define GROOPS_REGISTER_CLASS(_className, _typeName, ...)\\\n_GROOPS_REGISTER_CLASS(_className, _typeName)\\\ninline void _Class##_className::generateDocumentation(Documentation &documentation) const\\\n{\\\n  documentation.writeText(docstring##_className);\\\n  Config config;\\\n  _GROOPS_FOR_EACH(_GROOPS_CLASS_DOCUMENTATION, __VA_ARGS__)\\\n}\\\n// end macro\n\n/***** DEFINE **********************************/\n\n/** @brief Register an old name of a renamed class.\n* This macro can be used to keep old config files working.\n* @ingroup configGroup */\n#define GROOPS_RENAMED_CLASS(_oldname, _newname, _time) \\\nclass _RenamedSchemaClass##_oldname : public RenamedSchemaClass\\\n{\\\npublic:\\\n  _RenamedSchemaClass##_oldname(const Renamed &renamed) : RenamedSchemaClass(renamed) {}\\\n};\\\nstatic _RenamedSchemaClass##_oldname renamedSchemaClass##_oldname(RenamedSchemaClass::Renamed(#_oldname, #_newname, _time));\\\n// end macro\n\n/***********************************************/\n\n/** @brief Generate the readConfig function for a class.\n* Call: GROOPS_READCONFIG_CLASS(ClassName, \"schemaType\").\n* @ingroup configGroup */\n#define GROOPS_READCONFIG_CLASS(_className, _typeName)\\\ntemplate<> Bool readConfig(Config &config, const std::string &name, _className##Ptr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\\\n{\\\n  try\\\n  {\\\n    if(isCreateSchema(config))\\\n    {\\\n      if(mustSet == Config::DEFAULT)\\\n        throw(Exception(\"In readConfig(\"+config.currentNodeName()+\".\"+name+\", type=\"+#_typeName+\"): Config::DEFAULT is not allowed. Please change to Config::OPTIONAL\"));\\\n      config.xselement(name, _typeName, mustSet, Config::ONCE, defaultValue, annotation); \\\n      return FALSE;\\\n    }\\\n\\\n    if(!hasName(config, name, mustSet))\\\n      return FALSE;\\\n    var = _className::create(config, name);\\\n    return TRUE;\\\n  }\\\n  catch(std::exception &e)\\\n  {\\\n    GROOPS_RETHROW(e)\\\n  }\\\n}\\\n// end macro\n\n/***********************************************/\n\n/** @brief Generate the readConfig function for an unbounded class.\n* Call: GROOPS_READCONFIG_UNBOUNDED_CLASS(ClassName, \"schemaType\").\n* @ingroup configGroup */\n#define GROOPS_READCONFIG_UNBOUNDED_CLASS(_className, _typeName)\\\ntemplate<> Bool readConfig(Config &config, const std::string &name, _className##Ptr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\\\n{\\\n  try\\\n  {\\\n    if(isCreateSchema(config))\\\n    {\\\n      config.xselement(name, _typeName, mustSet, Config::UNBOUNDED, defaultValue, annotation); \\\n      return FALSE;\\\n    }\\\n\\\n    Bool found = hasName(config, name, mustSet);\\\n    if(found || (mustSet == Config::DEFAULT))\\\n      var = _className##Ptr(new _className(config, name));\\\n    return found;\\\n  }\\\n  catch(std::exception &e)\\\n  {\\\n    GROOPS_RETHROW(e)\\\n  }\\\n}\\\n// end macro\n\n/***********************************************/\n\n// Internal macro\n#define _GROOPS_REGISTER_CLASS(_className, _typeName)\\\nclass _Class##_className : public SchemaClass\\\n{\\\npublic:\\\n  std::string typeName() const {return _typeName;}\\\n  void registerConfigSchema(Config &config) const {_className::create(config, typeName());}\\\n  void generateDocumentation(Documentation &documentation) const;\\\n};\\\nstatic _Class##_className _class##_className;\\\n// end macro\n\n\n/***********************************************/\n\n// Internal macro\n#define _GROOPS_CLASS_DOCUMENTATION(_className)\\\n{\\\n  _className tmp(config);\\\n  documentation.writeText(docstring##_className);\\\n  documentation.writeConfigTable(config);\\\n}\\\n// end macro\n\n/***** CLASS ***********************************/\n\n/** @brief Class registration in schema and documentation.\n* Use macros GROOPS_REGISTER_CLASS and GROOPS_REGISTER_CLASS_WITHOUT_SUBS.\n* @ingroup configGroup */\nclass SchemaClass\n{\npublic:\n  SchemaClass() {classList(this);}\n  virtual ~SchemaClass() {}\n\n  virtual std::string typeName() const = 0;\n  virtual void registerConfigSchema(Config &config) const = 0;\n  virtual void generateDocumentation(Documentation &documentation) const = 0;\n\n  static std::vector<SchemaClass*> classList(SchemaClass *schemaClass=nullptr)\n  {\n    static std::vector<SchemaClass*> list;\n    if(schemaClass != nullptr)\n      list.push_back(schemaClass);\n    return list;\n  }\n\n  static void sort(std::vector<SchemaClass*> &list)\n  {\n    std::sort(list.begin(), list.end(), [](SchemaClass *a, SchemaClass *b) {return a->typeName() < b->typeName();});\n  }\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Interface for renamed classes.\n* @ingroup configGroup */\nclass RenamedSchemaClass\n{\npublic:\n  class Renamed\n  {\n  public:\n    std::string oldName;\n    std::string newName;\n    Time        time;\n    Renamed(const std::string &oldName_, const std::string &newName_, const Time &time_) : oldName(oldName_), newName(newName_), time(time_) {}\n  };\n\n  RenamedSchemaClass(const Renamed &renamed) {renamedList(renamed);}\n  virtual ~RenamedSchemaClass() {}\n\n  static std::vector<Renamed> renamedList(const Renamed &renamed = Renamed(\"\", \"\", Time()))\n  {\n    static std::vector<Renamed> list;\n    if(!renamed.oldName.empty())\n      list.push_back(renamed);\n    return list;\n  }\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS__ */\n\n"
  },
  {
    "path": "source/config/generateDocumentation.cpp",
    "content": "/***********************************************/\n/**\n* @file generateDocumentation.cpp\n*\n* @brief Generates a latex user documentation file.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2008-10-14\n*/\n/***********************************************/\n\n#define DOCSTRING_Doodson\n#define DOCSTRING_GnssType\n#define DOCSTRING_Parser\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"base/doodson.h\"\n#include \"base/gnssType.h\"\n#include \"parser/expressionParser.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"config/configRegister.h\"\n#include \"programs/program.h\"\n#include \"generateDocumentation.h\"\n\n/***********************************************/\n\nclass _ClassDoodson : public SchemaClass\n{\npublic:\n  std::string typeName() const {return \"doodson\";}\n  void registerConfigSchema(Config &/*config*/) const {}\n  void generateDocumentation(Documentation &documentation) const {documentation.writeText(docstringDoodson);}\n};\nstatic _ClassDoodson _classDoodson;\n\n/***********************************************/\n\nclass _ClassGnssType : public SchemaClass\n{\npublic:\n  std::string typeName() const {return \"gnssType\";}\n  void registerConfigSchema(Config &/*config*/) const {}\n  void generateDocumentation(Documentation &documentation) const {documentation.writeText(docstringGnssType);}\n};\nstatic _ClassGnssType _classGnssType;\n\n/***********************************************/\n\nclass Documentation::Token\n{\npublic:\n  enum Type {TEXT, PARAGRAPH, NEWLINE, ESCAPE, BRACKET, COMMAND, EQUATION, EQUATIONINLINE};\n  Type        type;\n  std::string text;\n  std::vector<std::string> options;\n\n  Token(Type type_, const std::string &text_) : type(type_), text(text_) {}\n};\n\n/***********************************************/\n\nstd::vector<Documentation::Token> Documentation::tokenize(const std::string &text)\n{\n  try\n  {\n    std::vector<Token> tokens;\n    if(text.empty())\n      return tokens;\n\n    std::string::size_type pos = 0, posOld = 0;\n    for(;;)\n    {\n      pos = text.find_first_of(\"\\n%{$\\\\\", pos);\n\n      // single return -> ignore\n      if((pos != std::string::npos) && (text.at(pos) == '\\n') && !((pos+1 < text.size()) && (text.at(pos+1) == '\\n')))\n      {\n        pos++;\n        continue;\n      }\n\n      // save old text before\n      if(pos > posOld)\n        tokens.push_back(Token(Token::TEXT, String::replaceAll(text.substr(posOld, pos-posOld), {{\"~\", \" \"}, {\"<\", \"&lt;\"}})));\n      if(pos == std::string::npos)\n        break;\n\n      if(text.at(pos) == '%')       // comment\n      {\n        pos = text.find(\"\\n\", pos);\n      }\n      else if(text.at(pos) == '\\n') // paragraph\n      {\n        pos += 2;\n        if(tokens.size() && (tokens.back().type != Token::PARAGRAPH))\n          tokens.push_back(Token(Token::PARAGRAPH, \"\"));\n      }\n      else if(text.at(pos) == '{') // bracket\n      {\n        auto posTmp = ++pos;\n        Int depth  = 1;\n        do\n        {\n          posTmp = text.find_first_of(\"{}\", posTmp);\n          if(posTmp == std::string::npos)\n            throw(Exception(\"missing '}'\"));\n          depth += (text.at(posTmp++) == '{') ? +1 : -1;\n        }\n        while(depth>0);\n\n        // special case \\begin{equation}\n        if((text.substr(pos, posTmp-pos-1) == \"equation\") && (tokens.back().text == \"begin\"))\n        {\n          pos = posTmp;\n          posTmp = text.find(R\"(\\end{equation})\", pos);\n          if(posTmp == std::string::npos)\n            throw(Exception(\"expected '\\\\end{equation}'\"));\n          tokens.back() = Token(Token::EQUATION, text.substr(pos, posTmp-pos));\n          pos = posTmp + 15;\n        }\n        else\n        {\n          tokens.push_back(Token(Token::BRACKET, text.substr(pos, posTmp-pos-1)));\n          pos = posTmp;\n        }\n      }\n      else if(text.at(pos) == '$') // EQUATIONINLINE\n      {\n        auto posTmp = text.find('$', ++pos);\n        if(posTmp == std::string::npos)\n          throw(Exception(\"missing '$'\"));\n        tokens.push_back(Token(Token::EQUATIONINLINE, text.substr(pos, posTmp-pos)));\n        pos = posTmp+1;\n      }\n      else if(text.at(pos) == '\\\\')\n      {\n        pos++;\n        if(pos >= text.size())\n          throw(Exception(\"text ended unexpectedly after '\\\\'\"));\n        if(text.at(pos) == '[') // EQUATION\n        {\n          auto posTmp = text.find(R\"(\\])\", ++pos);\n          if(posTmp == std::string::npos)\n            throw(Exception(\"missing '\\\\]'\"));\n          tokens.push_back(Token(Token::EQUATION, text.substr(pos, posTmp-pos)));\n          pos = posTmp+2;\n        }\n        else if(text.at(pos) == '\\\\')        // NEWLINE\n          tokens.push_back(Token(Token::NEWLINE, text.substr(pos++, 1)));\n        else if(!std::isalpha(text.at(pos))) // ESCPAE\n          tokens.push_back(Token(Token::ESCAPE, text.substr(pos++, 1)));\n        else // COMMAND\n        {\n          posOld = pos;\n          while((pos < text.size()) && std::isalpha(text.at(pos))) pos++;\n          tokens.push_back(Token(Token::COMMAND, text.substr(posOld, pos-posOld)));\n          while((pos < text.size()) && std::isspace(text.at(pos))) pos++;\n          if(tokens.back().text == \"verb\")\n          {\n            auto separator = text.at(pos++);\n            auto posTmp = text.find(separator, pos);\n            if(posTmp == std::string::npos)\n              throw(Exception(\"missing end of \\\\verb\"s+separator));\n            tokens.push_back(Token(Token::BRACKET, String::replaceAll(text.substr(pos, posTmp-pos), \"<\", \"&lt;\")));\n            pos = posTmp+1;\n          }\n        }\n      }\n      else\n        throw(Exception(\"unexpected character\"));\n\n      posOld = pos;\n    } // for(;;)\n\n    return tokens;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass Documentation::TableLine\n{\npublic:\n  std::string name, type, annotation;\n  Bool        optional, unbounded;\n  UInt        depth;\n};\n\n/***********************************************/\n\nvoid Documentation::generateTableLine(XmlNodePtr xmlNode, UInt depth, std::vector<TableLine> &tableLines)\n{\n  try\n  {\n    TableLine tableLine;\n    tableLine.depth = depth;\n\n    // name\n    XmlAttrPtr attr = xmlNode->getAttribute(\"name\");\n    if(attr)\n      tableLine.name = attr->getText();\n\n    // optional\n    tableLine.optional = FALSE;\n    if(xmlNode->getAttribute(\"minOccurs\"))\n      tableLine.optional = TRUE;\n\n    // unbounded\n    tableLine.unbounded = FALSE;\n    if(xmlNode->getAttribute(\"maxOccurs\"))\n      tableLine.unbounded = TRUE;\n\n    // comment\n    XmlNodePtr xmlChild = xmlNode->getChild(\"xs:annotation\");\n    if(xmlChild)\n      xmlChild = xmlChild->getChild(\"xs:documentation\");\n    if(xmlChild)\n      tableLine.annotation = xmlChild->getText();\n\n    // type\n    attr = xmlNode->getAttribute(\"type\");\n    if(attr)\n      tableLine.type = attr->getText();\n\n    if(xmlNode->findChild(\"xs:complexType\"))\n      xmlNode  = xmlNode->getChild(\"xs:complexType\");\n    XmlNodePtr sequence = xmlNode->getChild(\"xs:sequence\");\n    XmlNodePtr choice   = xmlNode->getChild(\"xs:choice\");\n\n    // setType\n    if(choice)\n      tableLine.type = \"choice\";\n    if(sequence)\n      tableLine.type = \"sequence\";\n\n    tableLines.push_back(tableLine);\n\n    // sequence\n    if(sequence)\n      while(sequence->hasChildren())\n        generateTableLine(sequence->getNextChild(), depth+1, tableLines);\n\n    // choice\n    if(choice)\n      while(choice->hasChildren())\n        generateTableLine(choice->getNextChild(), depth+1, tableLines);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Documentation::TableLine> Documentation::generateTable(Config &config)\n{\n  try\n  {\n    std::vector<TableLine> tableLines;\n    XmlNodePtr rootNode = config.table();\n    if(!rootNode->hasChildren())\n      return tableLines;\n    while(rootNode->hasChildren())\n      generateTableLine(rootNode->getNextChild(), 0, tableLines);\n    return tableLines;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool Documentation::isClassType(const std::string &type)\n{\n  try\n  {\n    const std::vector<SchemaClass*> classList = SchemaClass::classList();\n    return std::find_if(classList.begin(), classList.end(), [&](auto c) {return c->typeName() == type;}) != classList.end();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n/***** LaTex ***********************************/\n/***********************************************/\n\nclass DocumentationLatex : public Documentation\n{\npublic:\n  OutFile file;\n\n  DocumentationLatex(const FileName &fileName);\n ~DocumentationLatex() {}\n\n  std::string escaping(const std::string &text);\n\n  void writeText(const std::string &text) override {file<<text<<std::endl;}\n  void writeConfigTable(Config &config) override;\n};\n\n/***********************************************/\n\nDocumentationLatex::DocumentationLatex(const FileName &fileName)\n{\n  try\n  {\n    file.open(fileName);\n    file<<\"% auto generated by GROOPS\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string DocumentationLatex::escaping(const std::string &text)\n{\n  return String::replaceAll(text, {{\"\\\\\", \"\\\\textbackslash{}\"}, {\"{\", \"\\\\{\"}, {\"}\", \"\\\\}\"}, {\"<\", \"$<$\"}, {\">\", \"$>$\"},\n                                   {\"&\", \"\\\\&\"}, {\"%\", \"\\\\%\"}, {\"$\", \"\\\\$\"}, {\"#\", \"\\\\#\"}, {\"_\", \"\\\\_\"},\n                                   {\"~\", \"\\\\textasciitilde{}\"}, {\"^\", \"\\\\textasciicircum{}\"}});\n}\n\n/***********************************************/\n\nvoid DocumentationLatex::writeConfigTable(Config &config)\n{\n  try\n  {\n    std::vector<TableLine> tableLines = generateTable(config);\n    if(!tableLines.size())\n      return;\n\n    file<<std::endl;\n    file<<R\"(\\keepXColumns)\"<<std::endl;\n    file<<R\"(\\begin{tabularx}{\\textwidth}{N T A})\"<<std::endl;\n    file<<R\"(\\hline)\"<<std::endl;\n    file<<R\"(Name & Type & Annotation\\\\)\"<<std::endl;\n    file<<R\"(\\hline)\"<<std::endl;\n    for(UInt i=0; i<tableLines.size(); i++)\n    {\n      std::string type = tableLines.at(i).type;\n      if(type == \"gnssType\")\n        type = R\"(\\hyperref[gnssType]{gnssType})\"; // set link\n      else if(isClassType(type))\n        type = R\"(\\hyperref[)\"+type+\"]{\"+type.substr(0, type.rfind(\"Type\"))+\"}\"; // set link\n\n      file<<R\"(\\hfuzz=500pt)\";\n      for(UInt k=1; k<tableLines.at(i).depth; k++)\n        file<<R\"(\\quad)\";\n      if(tableLines.at(i).depth > 0)\n        file<<R\"(\\includegraphics[width=1em]{connector.pdf})\";\n      if(tableLines.at(i).optional && tableLines.at(i).unbounded)        file<<R\"(\\includegraphics[width=1em]{element-unbounded.pdf}~)\";\n      else if(tableLines.at(i).optional && !tableLines.at(i).unbounded)  file<<R\"(\\includegraphics[width=1em]{element.pdf}~)\";\n      else if(!tableLines.at(i).optional && tableLines.at(i).unbounded)  file<<R\"(\\includegraphics[width=1em]{element-mustset-unbounded.pdf}~)\";\n      else if(!tableLines.at(i).optional && !tableLines.at(i).unbounded) file<<R\"(\\includegraphics[width=1em]{element-mustset.pdf}~)\";\n      file<<escaping(tableLines.at(i).name)<<R\"( & \\hfuzz=500pt )\"<<type<<R\"( & \\hfuzz=500pt )\"<<escaping(tableLines.at(i).annotation)<<R\"(\\\\)\"<<std::endl;\n    }\n    file<<R\"(\\hline)\"<<std::endl;\n    file<<R\"(\\end{tabularx})\"<<std::endl;\n    file<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Documentation::writeLatex(const FileName &directoryName)\n{\n  try\n  {\n    // section parser\n    // --------------\n    {\n      DocumentationLatex docu(directoryName.append(\"general.parser.auto.tex\"));\n      docu.writeText(docstringParserExpression);\n      docu.writeText(docstringParserText);\n      docu.writeText(docstringParserDataVariables);\n    }\n\n    // File description\n    // ----------------\n    {\n      DocumentationLatex docu(directoryName.append(\"general.fileFormat.auto.tex\"));\n      std::vector<FileFormat*> fileFormatList = FileFormat::list();\n      FileFormat::sort(fileFormatList);\n      for(UInt i=0; i<fileFormatList.size(); i++)\n      {\n        docu.file<<\"\\\\subsection{\"<<fileFormatList.at(i)->title()<<\"}\\\\label{general.fileFormat:\"<<fileFormatList.at(i)->type()<<\"}\";\n        docu.writeText(fileFormatList.at(i)->documentation());\n        docu.file<<\"\\n%==================================\\n\";\n      }\n    }\n\n    // Program description\n    // -------------------\n    {\n      DocumentationLatex docu(directoryName.append(\"programs.auto.tex\"));\n      std::vector<Program::Program*> programList = Program::Program::programList();\n      Program::Program::sortList(programList);\n      Program::Tags tag = Program::NONE;\n      for(UInt i=0; i<programList.size(); i++)\n      {\n        if(programList.at(i)->tags().at(0) != tag)\n        {\n          tag = programList.at(i)->tags().at(0);\n          docu.file<<\"\\\\section{Programs: \"<<Program::tagStrings[tag]<<\"}\"<<std::endl;\n        }\n\n        Config config;\n        programList.at(i)->run(config, Parallel::selfCommunicator());\n        docu.file<<\"\\\\subsection{\"<<programList.at(i)->name()<<\"}\\\\label{\"<<programList.at(i)->name()<<\"}\";\n        docu.writeText(programList.at(i)->documentation());\n        docu.writeConfigTable(config);\n        if(!programList.at(i)->isSingleProcess())\n          docu.file<<\"This program is \\\\reference{parallelized}{general.parallelization}.\"<<std::endl;\n        docu.file<<\"\\\\clearpage\\n%==================================\\n\";\n      }\n    }\n\n    // Classes description\n    // -------------------\n    {\n      DocumentationLatex docu(directoryName.append(\"classes.auto.tex\"));\n      std::vector<SchemaClass*> classList = SchemaClass::classList();\n      SchemaClass::sort(classList);\n      for(UInt i=0; i<classList.size(); i++)\n      {\n        classList.at(i)->generateDocumentation(docu);\n        docu.file<<\"\\\\clearpage\\n%==================================\\n\";\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***** HTML ************************************/\n/***********************************************/\n\nclass DocumentationHtml : public Documentation\n{\npublic:\n  FileName          directoryName;\n  std::stringstream ss;\n  std::stringstream ssSearchDisplayText; //  display text for search results\n  std::stringstream ssSearchTokens; // description text tokens\n  std::stringstream ssSearchMiscTokens; // config table, tags, ...\n\n  DocumentationHtml(const FileName &directoryName_) : directoryName(directoryName_) {}\n ~DocumentationHtml() {}\n\n  void writeText(const std::string &text) override;\n  void writeConfigTable(Config &config) override;\n};\n\n/***********************************************/\n\nvoid DocumentationHtml::writeText(const std::string &text)\n{\n  try\n  {\n    std::vector<Token> token = tokenize(text);\n    std::string searchTokens;\n\n    Bool isItemOpen = FALSE;\n    for(UInt i=0; i<token.size(); i++)\n    {\n      // lambda function\n      // --------------\n      auto reference = [](const std::string &text) -> std::string\n      {\n        auto pos = text.find(\":\");\n        if(pos != std::string::npos)\n          return text.substr(0, pos)+\".html#\"+text.substr(pos+1);\n        return text+\".html\";\n      };\n      // --------------\n\n      // lambda function\n      // --------------\n      auto checkBrackets = [&](UInt count=1)\n      {\n        for(UInt k=0; k<count; k++)\n          if(token.at(++i).type != Token::BRACKET)\n            throw(Exception(\"expected '{'\"));\n      };\n      // --------------\n\n      // lambda function\n      // --------------\n      auto checkLabel = [&]() -> std::string\n      {\n        if((token.at(i+1).type != Token::COMMAND) || (token.at(i+1).text != \"label\"))\n          return \"\";\n        i++;\n        checkBrackets();\n        std::string refFile, refAnchor = token.at(i).text;\n        auto pos = token.at(i).text.find(\":\");\n        if(pos != std::string::npos)\n        {\n          refFile   = token.at(i).text.substr(0, pos);\n          refAnchor = token.at(i).text.substr(pos+1);\n        }\n        return R\"( id=\")\"+refAnchor+R\"(\")\";\n      };\n      // --------------\n\n      // lambda function\n      // --------------\n      auto addToSearchTokens = [&](const std::string &token)\n      {\n        searchTokens += (token+\" \");\n      };\n\n      std::string html;\n      Bool addToSearchDisplayText = TRUE;\n\n      const std::string &text = token.at(i).text;\n      switch(token.at(i).type)\n      {\n        case Token::TEXT:           html = text; addToSearchTokens(text); break;\n        case Token::EQUATIONINLINE: html = \"$\"+text+\"$\"; break;\n        case Token::EQUATION:       html = \"\\\\[\"+ text +\"\\\\]\"; break;\n        case Token::ESCAPE:         html = text; break;\n        case Token::PARAGRAPH:      html = \"</p><p>\"; break;\n        case Token::NEWLINE:\n        {\n          logWarning<<\"Ignored newline '\\\\\\\\'\"<<Log::endl;\n          break;\n        }\n        case Token::BRACKET:\n        {\n          html = R\"(<strong style=\"color: red;\">{)\" + text + \"}</strong>\";\n          logWarning<<\"Unexpected {\"<<token.at(i).text<<\"}\"<<Log::endl;\n          break;\n        }\n        case Token::COMMAND:\n        {\n          const std::string &cmd = token.at(i).text;\n          if(cmd == \"ldots\")            {ss<<\"&hellip; \";}\n          else if(cmd == \"section\")     {checkBrackets();  std::string title = token.at(i).text; html = R\"(<h1)\" + checkLabel() + \">\" + title + R\"(</h1><p>)\"; addToSearchDisplayText = FALSE; }\n          else if(cmd == \"subsection\")  {checkBrackets();  std::string title = token.at(i).text; html = R\"(<h2)\" + checkLabel() + \">\" + title + R\"(</h2><p>)\";}\n          else if(cmd == \"emph\")        {checkBrackets();  html = R\"(<em>)\" + token.at(i).text + R\"(</em>)\"; addToSearchTokens(token.at(i).text); }\n          else if(cmd == \"textbf\")      {checkBrackets();  html = R\"(<b>)\" + token.at(i).text + R\"(</b>)\"; addToSearchTokens(token.at(i).text); }\n          else if(cmd == \"verb\")        {checkBrackets();  html = R\"(<code>)\" + token.at(i).text + R\"(</code>)\"; addToSearchTokens(token.at(i).text); }\n          else if(cmd == \"url\")         {checkBrackets();  html = R\"(<a href=\")\" + token.at(i).text + R\"(\" target=\"_blank\">)\" + token.at(i).text + R\"(</a>)\"; addToSearchTokens(token.at(i).text); }\n          else if(cmd == \"href\")        {checkBrackets(2); html = R\"(<a href=\")\" + token.at(i-1).text + R\"(\">)\" + token.at(i).text + R\"(</a>)\";}\n          else if(cmd == \"eqref\")       {checkBrackets();  html = R\"(\\eqref{)\" + token.at(i).text + R\"(})\";}\n          else if(cmd == \"program\")     {checkBrackets();  html = R\"(<a class=\"groops-program\" href=\")\" + reference(token.at(i).text) + R\"(\">)\" + token.at(i).text + R\"(</a>)\"; addToSearchTokens(token.at(i).text); }\n          else if(cmd == \"config\")      {checkBrackets();  html = R\"(<strong class=\"groops-config-element\">)\" + token.at(i).text + R\"(</strong>)\"; addToSearchTokens(token.at(i).text); }\n          else if(cmd == \"configClass\") {checkBrackets(2); html = R\"(<a class=\"groops-class\" href=\")\" + reference(token.at(i).text) + R\"(\">)\" + token.at(i-1).text + R\"(</a>)\"; addToSearchTokens(token.at(i-i).text);}\n          else if(cmd == \"configFile\")  {checkBrackets(2); html = R\"(<a class=\"groops-class\" href=\")\" + reference(\"fileFormat_\"+token.at(i).text) + R\"(\">)\" + token.at(i-1).text + R\"(</a>)\"; addToSearchTokens(token.at(i-i).text);}\n          else if(cmd == \"file\")        {checkBrackets(2); html = R\"(<a class=\"groops-file\" href=\")\" + reference(\"fileFormat_\"+token.at(i).text) + R\"(\">)\" + token.at(i-1).text + R\"(</a>)\"; addToSearchTokens(token.at(i-1).text); }\n          else if(cmd == \"reference\")   {checkBrackets(2); html = R\"(<a class=\"groops-ref\" href=\")\" + reference(token.at(i).text) + R\"(\">)\" + token.at(i-1).text + R\"(</a>)\"; addToSearchTokens(token.at(i-1).text); }\n          else if(cmd == \"ref\")         {checkBrackets();  html = R\"(<a href=\")\" + reference(token.at(i).text) + R\"(\">)\" + token.at(i).text + R\"(</a>)\";}\n          else if(cmd == \"fig\")\n          {\n            addToSearchDisplayText = FALSE;\n            checkBrackets(5);\n            html = R\"(<figure><img class=\"figure\" style=\"width:)\" + (100*String::toDouble(token.at(i-3).text))%\"%i\"s + R\"(%;\" )\"\n                 + R\"(src=\"../figures/)\" + token.at(i-2).text + R\"(.png\" alt=\")\" + token.at(i-2).text + R\"(\">)\"\n                 + R\"(<figcaption class=\"center\">Figure: )\" + token.at(i).text + R\"(</figcaption></figure>)\";\n          }\n          else if(cmd == \"input\")\n          {\n            checkBrackets();\n            InFile infile(directoryName.append(\"..\").append(\"latex\").append(token.at(i).text+\".tex\"));\n            std::string text((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());\n            writeText(text);\n          }\n          else if(cmd == \"label\")\n          {\n            checkBrackets();\n            html = R\"(<a id=\")\" + token.at(i).text + R\"(\"></a>)\";\n            logWarning<<\"Label at unexpected position: \\\\label{\"<<token.at(i).text<<\"} -> ignored\"<<Log::endl;\n          }\n          else if(cmd == \"begin\")\n          {\n            checkBrackets();\n            if(token.at(i).text == \"itemize\")\n             html = \"<ul>\\n\";\n            else if(token.at(i).text == \"enumerate\")\n              html = \"<ol>\\n\";\n            else if(token.at(i).text == \"verbatim\")\n              html = \"<pre>\";\n            else if(token.at(i).text == \"equation\")\n              html = R\"(\\begin{)\" + token.at(i).text + \"}\";\n            else\n            {\n              html = R\"(\\begin{)\" + token.at(i).text + \"}\";\n              logWarning<<\"Unknown Latex command: \\\\begin{\"<<token.at(i).text<<\"}\"<<Log::endl;\n            }\n          }\n          else if(cmd == \"end\")\n          {\n            checkBrackets();\n            if(token.at(i).text == \"itemize\")\n            {\n              if(isItemOpen)\n                html = \"</li></ul>\\n\";\n              else\n                html = \"</ul>\";\n              isItemOpen = FALSE;\n            }\n            else if(token.at(i).text == \"enumerate\")\n            {\n              if(isItemOpen)\n                html = \"</li></ol>\\n\";\n              else\n                html = \"</ol>\";\n              isItemOpen = FALSE;\n            }\n            else if(token.at(i).text == \"verbatim\")\n              html = \"</pre>\";\n            else if(token.at(i).text == \"equation\")\n              html = R\"(\\end{)\" + token.at(i).text + \"}\";\n            else\n            {\n              html = R\"(\\end{)\" + token.at(i).text + \"}\";\n              logWarning<<\"Unknown Latex command: \\\\end{\"<<token.at(i).text<<\"}\"<<Log::endl;\n            }\n          } // \"end\"\n          else if(cmd == \"item\")\n          {\n            if(isItemOpen)\n              html = \"</li><li>\\n\";\n            else\n              html = \"<li>\";\n            isItemOpen = TRUE;\n          } // \"item\"\n          else\n          {\n            html = R\"(<strong style=\"color: red;\">\\)\" + cmd + \"</strong>\";\n            logWarning<<\"Unknown Latex command: \\\\\"<<cmd<<Log::endl;\n          }\n          break;\n        }\n      }\n      ss<<html;\n      if(addToSearchDisplayText) ssSearchDisplayText<<html;\n    } // for(i)\n    ss<<R\"(</p>)\"<<std::endl;\n    ssSearchTokens<<searchTokens;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"text='\"+text+\"'\", e)\n  }\n}\n\n/***********************************************/\n\nvoid DocumentationHtml::writeConfigTable(Config &config)\n{\n  try\n  {\n    std::vector<TableLine> tableLines = generateTable(config);\n    if(!tableLines.size())\n      return;\n\n    ss<<R\"(<table class=\"table table-hover\">)\"<<std::endl;\n    ss<<R\"(<tr class=\"table-primary\"><th>Name</th><th>Type</th><th>Annotation</th></tr>)\"<<std::endl;\n    for(UInt i=0; i<tableLines.size(); i++)\n    {\n      if(i%2)\n        ss<<R\"(<tr class=\"\">)\";\n      else\n        ss<<R\"(<tr class=\"table-light\">)\";\n      ss<<R\"(<td class=\"m-0\"><div class=\"h-100 config-tree depth-)\"<<tableLines.at(i).depth<<R\"(\"><div class=\"h-100 config )\";\n      if(tableLines.at(i).optional && tableLines.at(i).unbounded)        ss<<R\"(optional-unbounded)\";\n      else if(tableLines.at(i).optional && !tableLines.at(i).unbounded)  ss<<R\"(optional)\";\n      else if(!tableLines.at(i).optional && tableLines.at(i).unbounded)  ss<<R\"(mustset-unbounded)\";\n      else if(!tableLines.at(i).optional && !tableLines.at(i).unbounded) ss<<R\"(mustset)\";\n      ss<<R\"(\">)\"<<tableLines.at(i).name<<R\"(</div></div></td>)\";\n      if(tableLines.at(i).type == \"gnssType\")\n        ss<<R\"(<td><a href=\"gnssType.html\">gnssType</a></td>)\";\n      else if(isClassType(tableLines.at(i).type))\n        ss<<R\"(<td><a href=\")\"<<tableLines.at(i).type<<R\"(.html\">)\"<<tableLines.at(i).type.substr(0,tableLines.at(i).type.rfind(\"Type\"))<<R\"(</a></td>)\";\n      else\n        ss<<R\"(<td>)\"<<tableLines.at(i).type<<R\"(</td>)\";\n      ss<<R\"(<td>)\"<<tableLines.at(i).annotation<<R\"(</td>)\";\n      ss<<R\"(</tr>)\"<<std::endl;\n      ssSearchMiscTokens<<tableLines.at(i).name<<\" \"<<tableLines.at(i).type<<\" \"<<tableLines.at(i).annotation<<\" \";\n    }\n    ss<<R\"(</table>)\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Documentation::writeHtml(const FileName &directoryName)\n{\n  try\n  {\n    // Load Template\n    // -------------\n    InFile templateFile(directoryName.append(\"static\").append(\"template.html\"));\n    std::string templateHtml((std::istreambuf_iterator<char>(templateFile)), std::istreambuf_iterator<char>());\n\n    OutFile documentationSearchIndex(directoryName.append(\"documentationSearchIndex.js\"));\n    documentationSearchIndex<<\"var documents = {\"<<std::endl;\n\n    // lambda function\n    // --------------\n    auto writeHtmlFile = [&](const FileName &fileName, const std::string &name, const std::string &content)\n    {\n      OutFile htmlFile(directoryName.append(fileName));\n      std::string page = templateHtml;\n      const std::string tagTitle   = \"[[[title]]]\";\n      const std::string tagContent = \"[[[content]]]\";\n      page.replace(page.find(tagTitle),   tagTitle.length(),   name);\n      page.replace(page.find(tagContent), tagContent.length(), content);\n      htmlFile<<page;\n    };\n    // --------------\n\n    // lambda function\n    // --------------\n    auto writeSearchIndex = [&](const std::string &fileName, const std::string &name, const std::string &search, const std::string &table, const std::string &displayText)\n    {\n      documentationSearchIndex<<\"'\"<<fileName<<\"': { 'name': '\"<<name<<\"', 'key': '\"<<fileName;\n      documentationSearchIndex<<\"', 'description': '\" <<String::trim(String::replaceAll(search,      {{\"\\n\", \" \"}, {\"\\\\\", \"\\\\\\\\\"}, {\"\\'\", \"\\\\'\"}}));\n      documentationSearchIndex<<\"', 'config_table': '\"<<String::trim(String::replaceAll(table,       {{\"\\n\", \" \"}, {\"\\\\\", \"\\\\\\\\\"}, {\"\\'\", \"\\\\'\"}}));\n      documentationSearchIndex<<\"', 'display_text': '\"<<String::trim(String::replaceAll(displayText, {{\"\\n\", \" \"}, {\"\\\\\", \"\\\\\\\\\"}, {\"\\'\", \"\\\\'\"}}));\n      documentationSearchIndex<<\"'},\"<<std::endl;\n    };\n    // --------------\n\n    // lambda function\n    // --------------\n    auto writeLatexFile = [&](const std::string &fileName, const std::string &title)\n    {\n      InFile infile(directoryName.append(\"..\").append(\"latex\").append(fileName+\".tex\"));\n      std::string text((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());\n      DocumentationHtml doc(directoryName);\n      doc.writeText(text);\n      writeHtmlFile(fileName+\".html\", title, doc.ss.str());\n      writeSearchIndex(fileName, fileName, doc.ssSearchTokens.str(), doc.ssSearchMiscTokens.str(), doc.ssSearchDisplayText.str());\n    };\n    // --------------\n\n    std::vector<Program::Program*> programList = Program::Program::programList();\n    Program::Program::sortList(programList);\n\n    std::vector<SchemaClass*> classList = SchemaClass::classList();\n    SchemaClass::sort(classList);\n\n    std::vector<FileFormat*> fileFormatList = FileFormat::list();\n    FileFormat::sort(fileFormatList);\n\n    // Index\n    // -----\n    {\n      std::stringstream content;\n      content<<R\"(<h1>GROOPS Documentation and Cookbook</h1>)\"<<std::endl;\n      content<<R\"(<p>GROOPS is a software toolkit for gravity field recovery, GNSS processing, and statistical analysis of time series and spatial data.)\"<<std::endl;\n      content<<R\"(It is licensed under GPLv3 and hosted at <a target=\"_blank\" href=\"https://github.com/groops-devs/groops\">GitHub</a>.</p>)\"<<std::endl;\n\n      content<<R\"(<p>GROOPS depends on data files such as Earth rotation, Love numbers, and GNSS meta information.)\"<<std::endl;\n      content<<R\"(An initial data set that is regularly updated is available on our FTP server,)\"<<std::endl;\n      content<<R\"(<a target=\"_blank\" href=\"https://ftp.tugraz.at/pub/ITSG/groops\">https://ftp.tugraz.at/pub/ITSG/groops</a>.)\"<<std::endl;\n      content<<R\"(You can choose between downloading the data directory or a single)\"<<std::endl;\n      content<<R\"(<a href=\"https://ftp.tugraz.at/pub/ITSG/groops/data.zip\">data.zip</a> with the same content.</p>)\"<<std::endl;\n\n      content<<R\"(<p>Additional tutorial videos are available at our <a target=\"_blank\" href=\"https://www.youtube.com/channel/UCzUirVN2JuEKZwdM9dIqllg/videos\">YouTube channel</a>.)\"<<std::endl;\n      content<<R\"(Questions about the usage of GROOPS can be posted in the)\"<<std::endl;\n      content<<R\"(<a target=\"_blank\" href=\"https://github.com/groops-devs/groops/discussions\">Discussions</a>.</p>)\"<<std::endl;\n\n      content<<R\"(<div class=\"container\">)\"<<std::endl;\n      content<<R\"(<div class=\"row\">)\"<<std::endl;\n      content<<R\"(  <div class=\"col-sm top-buffer\">)\"<<std::endl;\n      content<<R\"(        <h5 class=\"card-title\">General Information</h5>)\"<<std::endl;\n      content<<R\"(          <p class=\"card-text\">File formats and basic concepts for using GROOPS and its GUI.</p>)\"<<std::endl;\n      content<<R\"(        <ul class=\"list-group list-group-flush\">)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.configFiles.html\">Config files</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.parser.html\">Parser</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.loopsAndConditions.html\">Loops and conditions</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.constants.html\">Constants and the setting file</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.parallelization.html\">Parallelization</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.gui.html\">Graphical User Interface (GUI)</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"general.fileFormat.html\">File formats</a></li>)\"<<std::endl;\n      content<<R\"(        </ul>)\"<<std::endl;\n      content<<R\"(  </div>)\"<<std::endl;\n      content<<R\"(  <div class=\"col-sm top-buffer\">)\"<<std::endl;\n      content<<R\"(        <h5 class=\"card-title\">Mathematic Fundamentals</h5>)\"<<std::endl;\n      content<<R\"(          <p class=\"card-text\">Description of methods used throughout GROOPS.</p>)\"<<std::endl;\n      content<<R\"(        <ul class=\"list-group list-group-flush\">)\"<<std::endl;\n      content<<R\"(          <li><a href=\"fundamentals.robustLeastSquares.html\">Robust least squares adjustment</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"fundamentals.basisSplines.html\">Basis splines</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"fundamentals.autoregressiveModel.html\">Autoregressive models</a></li>)\"<<std::endl;\n      content<<R\"(        </ul>)\"<<std::endl;\n      content<<R\"(  </div>)\"<<std::endl;\n      content<<R\"(</div>)\"<<std::endl;\n      content<<R\"(<div class=\"row\">)\"<<std::endl;\n      content<<R\"(  <div class=\"col-sm top-buffer\">)\"<<std::endl;\n      content<<R\"(        <h5 class=\"card-title\">Cookbook</h5>)\"<<std::endl;\n      content<<R\"(          <p class=\"card-text\">Recipes to explore the GROOPS feature set.</p>)\"<<std::endl;\n      content<<R\"(        <ul class=\"list-group list-group-flush\">)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.instrument.html\">Instrument data handling</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.gnssNetwork.html\">GNSS satellite orbit determination and station network analysis</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.gnssPpp.html\">GNSS precise point positioning (PPP)</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.kinematicOrbit.html\">Kinematic orbit determination of LEO satellites</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.gravityFieldPod.html\">Gravity field determination from POD data</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.gravityFieldGrace.html\">GRACE gravity field recovery</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"cookbook.regionalGeoid.html\">Regional geoid determination</a></li>)\"<<std::endl;\n      content<<R\"(        </ul>)\"<<std::endl;\n      content<<R\"(  </div>)\"<<std::endl;\n      content<<R\"(  <div class=\"col-sm top-buffer\">)\"<<std::endl;\n      content<<R\"(        <h5 class=\"card-title\">Program/Class Reference</h5>)\"<<std::endl;\n      content<<R\"(        <p class=\"card-text\">Reference and documentation for all programs and classes in GROOPS.</p>)\"<<std::endl;\n      content<<R\"(        <ul class=\"list-group list-group-flush\">)\"<<std::endl;\n      content<<R\"(          <li><a href=\"programType.html\">List of programs</a></li>)\"<<std::endl;\n      content<<R\"(          <li><a href=\"classes.html\">List of classes</a></li>)\"<<std::endl;\n      content<<R\"(        </ul>)\"<<std::endl;\n      content<<R\"(  </div>)\"<<std::endl;\n      content<<R\"(</div>)\"<<std::endl;\n      content<<R\"(</div>)\"<<std::endl;\n      writeHtmlFile(\"index.html\", \"Overview\", content.str());\n    }\n\n    // Translate Latex files\n    // ---------------------\n    writeLatexFile(\"general.configFiles\",              \"Config files\");\n    writeLatexFile(\"general.parser\",                   \"Parser\");\n    writeLatexFile(\"general.loopsAndConditions\",       \"Loops and conditions\");\n    writeLatexFile(\"general.gui\",                      \"Graphical User Interface (GUI)\");\n    writeLatexFile(\"general.constants\",                \"Constants and the setting file\");\n    writeLatexFile(\"general.parallelization\",          \"Parallelization\");\n    writeLatexFile(\"fundamentals.robustLeastSquares\",  \"Robust least squares adjustment\");\n    writeLatexFile(\"fundamentals.basisSplines\",        \"Basis splines\");\n    writeLatexFile(\"fundamentals.autoregressiveModel\", \"Autoregressive model\");\n    writeLatexFile(\"cookbook.instrument\",              \"Instrument data handling\");\n    writeLatexFile(\"cookbook.gnssNetwork\",             \"GNSS satellite orbit determination and station network analysis\");\n    writeLatexFile(\"cookbook.gnssPpp\",                 \"GNSS precise point positioning (PPP)\");\n    writeLatexFile(\"cookbook.kinematicOrbit\",          \"Kinematic orbit determination of LEO satellites\");\n    writeLatexFile(\"cookbook.gravityFieldPod\",         \"Gravity field determination from POD data\");\n    writeLatexFile(\"cookbook.gravityFieldGrace\",       \"GRACE gravity field recovery\");\n    writeLatexFile(\"cookbook.regionalGeoid\",           \"Regional geoid determination\");\n\n    // Search page\n    // -----------\n    {\n      std::stringstream content;\n      content<<R\"(<h1>Search</h1>)\"<<std::endl;\n      content<<R\"(<p id=\"search-meta-info\"></p>)\"<<std::endl;\n      content<<R\"(<div id=\"searchResults\"></div>)\"<<std::endl;\n      content<<R\"(<script type=\"text/javascript\" src=\"documentationSearchIndex.js\"></script>)\"<<std::endl;\n      content<<R\"(<script type=\"text/javascript\" src=\"static/searchtools.js\"></script>)\"<<std::endl;\n      content<<R\"(<script>window.onload = startSearch();</script>)\"<<std::endl;\n      writeHtmlFile(\"search.html\", \"Search\", content.str());\n    }\n\n    // Progams overview page\n    // ---------------------\n    {\n      std::stringstream content;\n      content<<R\"(<h1>Programs</h1>)\"<<std::endl;\n      content<<R\"(<p>This reference manual details programs included in GROOPS, describing what they are and what they do.\n      For usage examples see the cookbook in the <a href=\"index.html\">documentation overview</a>.</p>)\"<<std::endl;\n      Program::Tags tag = Program::NONE;\n      for(UInt i=0; i<programList.size(); i++)\n      {\n        if(programList.at(i)->tags().at(0) != tag)\n        {\n          if(tag != Program::NONE)\n            content<<R\"(</ul></p>)\"<<std::endl;\n          tag = programList.at(i)->tags().at(0);\n          content<<R\"(<h2>)\"<<Program::tagStrings[tag]<<R\"(</h2>)\"<<std::endl;\n          content<<R\"(<p><ul>)\"<<std::endl;\n        }\n        std::string name = programList.at(i)->name();\n        content<<R\"(<li><a href=\")\"<<name<<R\"(.html\">)\"<<name<<R\"(</a></li>)\"<<std::endl;\n      }\n      content<<R\"(</ul></p>)\"<<std::endl;\n      writeHtmlFile(\"programType.html\", \"Programs\", content.str());\n    }\n\n    // Program pages\n    // -------------\n    for(UInt i=0; i<programList.size(); i++)\n    {\n      const std::string name = programList.at(i)->name();\n      DocumentationHtml doc(directoryName);\n      doc.ss<<R\"(<h1>)\"<<name<<R\"(</h1><p>)\"<<std::endl;\n      doc.writeText(programList.at(i)->documentation());\n      Config config;\n      programList.at(i)->run(config, Parallel::selfCommunicator());\n      doc.writeConfigTable(config);\n      if(!programList.at(i)->isSingleProcess())\n        doc.ss<<R\"(This program is <a class=\"groops-ref\" href=\"general.parallelization.html\">parallelized</a>.)\"<<std::endl;\n      writeHtmlFile(name+\".html\", name, doc.ss.str());\n      writeSearchIndex(name, name, doc.ssSearchTokens.str(), doc.ssSearchMiscTokens.str(), doc.ssSearchDisplayText.str());\n    }\n\n    // Classes overview page\n    // ---------------------\n    {\n      std::stringstream content;\n      content<<R\"(<h1>Classes</h1>)\"<<std::endl;\n      content<<R\"(<p>This reference manual details classes included in GROOPS, describing what they are and what they do.\n      For usage examples see the cookbook in the <a href=\"index.html\">documentation overview</a>.</p>)\"<<std::endl;\n      content<<R\"(<p><ul>)\"<<std::endl;\n      for(UInt i=0; i<classList.size(); i++)\n      {\n        std::string type = classList.at(i)->typeName();\n        if(type == \"gnssType\")\n          content<<R\"(<li><a href=\"gnssType.html\">gnssType</a></li>)\"<<std::endl;\n        else\n          content<<R\"(<li><a href=\")\"<<type<<R\"(.html\">)\"<<type.substr(0, type.rfind(\"Type\"))<<R\"(</a></li>)\"<<std::endl;\n      }\n      content<<R\"(</ul></p>)\"<<std::endl;\n      writeHtmlFile(\"classes.html\", \"Classes\", content.str());\n    }\n\n    // Class pages\n    // -----------\n    for(UInt i=0; i<classList.size(); i++)\n    {\n      std::string pageContent = templateHtml;\n      const std::string name = classList.at(i)->typeName();\n      DocumentationHtml doc(directoryName);\n      classList.at(i)->generateDocumentation(doc);\n      writeHtmlFile(name+\".html\", name, doc.ss.str());\n      writeSearchIndex(name, name/*.substr(0, name.find(\"Type\"))*/, doc.ssSearchTokens.str(), doc.ssSearchMiscTokens.str(), doc.ssSearchDisplayText.str());\n    }\n\n    // File format overview page\n    // -------------------------\n    {\n      const std::string fileName = \"general.fileFormat\";\n      const std::string title    = \"File Formats\";\n      InFile infile(directoryName.append(\"..\").append(\"latex\").append(fileName+\".tex\"));\n      std::string text((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());\n      DocumentationHtml doc(directoryName);\n      doc.writeText(text);\n\n      std::stringstream content;\n      content<<R\"(<p><ul>)\"<<std::endl;\n      for(UInt i=0; i<fileFormatList.size(); i++)\n      {\n        const std::string name = fileFormatList.at(i)->title();\n        content<<R\"(<li><a href=\"fileFormat_)\"<<fileFormatList.at(i)->type()<<R\"(.html\">)\"<<name<<R\"(</a></li>)\"<<std::endl;\n      }\n      content<<R\"(</ul></p>)\"<<std::endl;\n\n      writeHtmlFile(fileName+\".html\", title, doc.ss.str() + content.str());\n      writeSearchIndex(fileName, fileName, doc.ssSearchTokens.str(), doc.ssSearchMiscTokens.str(), doc.ssSearchDisplayText.str());\n    }\n\n    // File format pages\n    // -----------------\n    for(UInt i=0; i<fileFormatList.size(); i++)\n    {\n      const std::string name = fileFormatList.at(i)->title();\n      DocumentationHtml doc(directoryName);\n      doc.ss<<R\"(<h1>)\"<<name<<R\"( (file format)</h1><p>)\"<<std::endl;\n      doc.writeText(fileFormatList.at(i)->documentation());\n      writeHtmlFile(\"fileFormat_\"+fileFormatList.at(i)->type()+\".html\", name, doc.ss.str());\n      writeSearchIndex(\"fileFormat_\"+fileFormatList.at(i)->type(), name, doc.ssSearchTokens.str(), doc.ssSearchMiscTokens.str(), doc.ssSearchDisplayText.str());\n    }\n\n    documentationSearchIndex<<\"};\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Documentation::write(const FileName &directoryName)\n{\n  try\n  {\n    writeLatex(directoryName.append(\"latex\"));\n    writeHtml(directoryName.append(\"html\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/config/generateDocumentation.h",
    "content": "/***********************************************/\n/**\n* @file generateDocumentation.h\n*\n* @brief Generates a latex user documentation file.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2008-10-14\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GENERATEDOCUMENTATION__\n#define __GROOPS_GENERATEDOCUMENTATION__\n\n#include \"inputOutput/fileName.h\"\n#include \"config/config.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generates a user documentation.\n* @ingroup configGroup */\nclass Documentation\n{\npublic:\n  virtual ~Documentation() {}\n\n  virtual void writeText(const std::string &text) = 0;\n  virtual void writeConfigTable(Config &config) = 0;\n\n  /** @brief Generates a html user documentation files.\n  * @ingroup configGroup */\n  static void writeHtml(const FileName &directoryName);\n\n  /** @brief Generates a latex user documentation files.\n  * @ingroup configGroup */\n  static void writeLatex(const FileName &directoryName);\n\n  /** @brief Generates documentation files.\n  * @ingroup configGroup */\n  static void write(const FileName &directoryName);\n\nprotected:\n  class Token;\n  class TableLine;\n\n  static std::vector<Token> tokenize(const std::string &text);\n  static void generateTableLine(XmlNodePtr xmlNode, UInt depth, std::vector<TableLine> &tableLines);\n  static std::vector<TableLine> generateTable(Config &config);\n  static Bool isClassType(const std::string &type);\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/external/README.md",
    "content": "## External source code used in GROOPS\n\nWhile GROOPS is intended to be a standalone software package, some functionality depends on external software.\nWe list external source code contained in the GROOPS repository with references and licenses here.\n\n### NRLMSIS 2.0\n\n* Original Website: https://map.nrl.navy.mil/map/pub/nrl/NRLMSIS/NRLMSIS2.0/\n* Reference: Emmert, J. T., Drob, D. P., Picone, J. M., Siskind, D. E., Jones, M., Mlynczak, M. G., et al. (2021). NRLMSIS 2.0: A whole-atmosphere empirical model of temperature and neutral species densities. Earth and Space Science, 8, e2020EA001321. https://doi.org/10.1029/2020EA001321\n* Files: `nrlmsis2/alt2gph.F90`,  `nrlmsis2/msis_calc.F90`,  `nrlmsis2/msis_constants.F90`,  `nrlmsis2/msis_dfn.F90`,  `nrlmsis2/msis_gfn.F90`,  `nrlmsis2/msis_init.F90`,  `nrlmsis2/msis_tfn.F90`, `nrlmsis2/readme.txt`\n* License: See [nrlmsis2/readme.txt](https://github.com/groops-devs/groops/blob/main/source/external/nrlmsis2/readme.txt).\n\n### Horizontal Wind Model 2014 (HWM14)\n\n* Original Website: https://map.nrl.navy.mil/map/pub/nrl/HWM/HWM14/\n* Reference: Drob, D. P., Emmert, J. T., Meriwether, J. W., Makela, J. J., Doornbos, E., Conde, M., Hernandez, G., Noto, J., Zawdie, K. A., McDonald, S. E., et al. (2015), An update to the Horizontal Wind Model (HWM): The quiet time thermosphere, Earth and Space Science, 2, 301– 319, https://doi.org/10.1002/2014EA000089\n* Files: `hwm/hwm14.f90`, `hwm/README.txt`\n* License: [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0)\n\n### The Jacchia-Bowman 2008 Empirical Thermospheric Density Model (JB2008)\n\n* Reference: Bowman, B. R., Tobiska, W. K., Marcos, F. A., Huang, C. Y., Lin, C. S., & Burke, W. J. (2008). A new empirical thermospheric density model JB2008 using new solar and geomagnetic indices. In AIAA/AAS Astrodynamics Specialist Conference and Exhibit. https://doi.org/10.2514/6.2008-6438\n* Files: `jb2008/JB2008.f`, `jb2008/README.txt`\n* License: Space Environment Technologies License and Warranty Agreement (http://sol.spacenvironment.net/jb2008/License.html)\n\n### International Geomagnetic Reference Field (IGRF)\n\n* Reference: Thébault, E., Finlay, C.C., Beggan, C.D. et al. International Geomagnetic Reference Field:\n  the 12th generation. Earth Planet Sp 67, 79 (2015). https://doi.org/10.1186/s40623-015-0228-9\n* Files: `igrf/igrf14.f`\n* License: none (included with permission of the authors)\n\n### International Earth Rotation and Reference Systems Service (IERS) Conventions software collection\n\n* Reference: IERS Conventions (2010). Gérard Petit and Brian Luzum (eds.). (IERS Technical Note ; 36)\n  Frankfurt am Main: Verlag des Bundesamts für Kartographie und Geodäsie, 2010. 179 pp., ISBN 3-89888-989-6\n* Files: `iers/*` except `iers.h`\n* License: IERS Conventions Software License\n"
  },
  {
    "path": "source/external/compress.h",
    "content": "/********************************************************************************************\n* Public domain implementation of the LZW algorithm. See https://github.com/vapier/ncompress.\n*/\n\n#ifndef GROOPS_UNCOMPRESS_H\n#define GROOPS_UNCOMPRESS_H\n\n\n#include <string.h>\n#include <sstream>\n#include <fstream>\n\n#define IBUFSIZ 2048 /* Defailt input buffer size\t\t\t\t\t\t\t*/\n#define OBUFSIZ 2048 /* Default output buffer size\t\t\t\t\t\t\t*/\n\n#define MAGIC_1 (unsigned char)'\\037' /* First byte of compressed file\t\t\t\t*/\n#define MAGIC_2 (unsigned char)'\\235' /* Second byte of compressed file\t\t\t\t*/\n#define BIT_MASK 0x1f                 /* Mask for 'number of compresssion bits'\t\t*/\n                                      /* Masks 0x20 and 0x40 are free.  \t\t\t\t*/\n                                      /* I think 0x20 should mean that there is\t\t*/\n                                      /* a fourth header byte (for expansion).    \t*/\n#define BLOCK_MODE 0x80               /* Block compresssion if table is full and\t\t*/\n                                      /* compression rate is dropping flush tables\t*/\n                                      /* the next two codes should not be changed lightly, as they must not\t*/\n                                      /* lie within the contiguous general code space.\t\t\t\t\t\t*/\n#define FIRST 257                     /* first free entry \t\t\t\t\t\t\t*/\n#define CLEAR 256                     /* table clear output code \t\t\t\t\t\t*/\n\n#define INIT_BITS 9 /* initial number of bits/code */\n\n#define HBITS 17   /* 50% occupancy */\n#define HSIZE (1 << HBITS)\n\n#define BITS 16\n\n#define MAXCODE(n) (1L << (n))\n\nunion bytes {\n  long word;\n  struct\n  {\n    unsigned char b4;\n    unsigned char b3;\n    unsigned char b2;\n    unsigned char b1;\n  } bytes;\n};\n\n#define input(b, o, c, n, m)                       \\\n  {                                                \\\n    unsigned char *p = &(b)[(o) >> 3];             \\\n    (c) = ((((long)(p[0])) | ((long)(p[1]) << 8) | \\\n            ((long)(p[2]) << 16)) >>               \\\n           ((o)&0x7)) &                            \\\n          (m);                                     \\\n    (o) += (n);                                    \\\n  }\n\n/*\n * Decompress stdin to stdout.  This routine adapts to the codes in the\n * file building the \"string\" table on-the-fly; requiring no table to\n * be stored in the compressed file.  The tables used herein are shared\n * with those of the compress() routine.  See the definitions above.\n */\n\nvoid decompress(std::ifstream& infile, std::stringstream &ss)\n{\n  unsigned char inbuf[IBUFSIZ + 64];    /* Input buffer\t\t\t\t\t\t\t\t\t*/\n  unsigned char outbuf[OBUFSIZ + 2048]; /* Output buffer\t\t\t\t\t\t\t\t*/\n\n  long int htab[HSIZE];\n  unsigned short codetab[HSIZE];\n\n  int insize = 0;\n  int rsize;\n  while (insize < 3 && (rsize = infile.readsome((char*)&inbuf + insize, IBUFSIZ)) > 0)\n    insize += rsize;\n\n  if(insize < 3 || inbuf[0] != MAGIC_1 || inbuf[1] != MAGIC_2)\n  {\n    if(rsize < 0)\n      throw(std::ios_base::failure(\"uncompress: unable to read input file\"));\n\n    if (insize > 0)\n      throw(std::ios_base::failure(\"uncompress: input file does not seem to be in compressed format.\"));\n  }\n\n  int maxbits = inbuf[2] & BIT_MASK;\n  int block_mode = inbuf[2] & BLOCK_MODE;\n  long int maxmaxcode = MAXCODE(maxbits);\n\n  if (maxbits > BITS)\n    throw(std::ios_base::failure(\"uncompress: number of compression bits in input file does not match algorithm.\"));\n\n  int n_bits;\n  long int maxcode = MAXCODE(n_bits = INIT_BITS) - 1;\n  int bitmask = (1 << n_bits) - 1;\n  long int oldcode = -1;\n  int finchar = 0;\n  int outpos = 0;\n  int posbits = 3 << 3;\n\n  long int free_ent = ((block_mode) ? FIRST : 256);\n\n  memset(codetab, 0, 256); /* As above, initialize the first 256 entries in the table. */\n  long int code;\n  for (code = 255; code >= 0; --code)\n    ((unsigned char *)(htab))[code] = (unsigned char)code;\n\n  do\n  {\n  resetbuf:;\n    {\n      int o = posbits >> 3;\n      int e = o <= insize ? insize - o : 0;\n\n      for (int i = 0; i < e; ++i)\n        inbuf[i] = inbuf[i + o];\n\n      insize = e;\n      posbits = 0;\n    }\n\n    if (insize < (int)sizeof(inbuf) - IBUFSIZ)\n    {\n      if ((rsize = infile.readsome((char*)&inbuf + insize, IBUFSIZ)) < 0)\n        throw(std::ios_base::failure(\"uncompress: unable to read input file\"));\n\n      insize += rsize;\n    }\n\n    int inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 : (insize << 3) - (n_bits - 1));\n\n    while (inbits > posbits)\n    {\n      if (free_ent > maxcode)\n      {\n        posbits = ((posbits - 1) + ((n_bits << 3) - (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));\n\n        ++n_bits;\n        if (n_bits == maxbits)\n          maxcode = maxmaxcode;\n        else\n          maxcode = MAXCODE(n_bits) - 1;\n\n        bitmask = (1 << n_bits) - 1;\n        goto resetbuf;\n      }\n\n      input(inbuf, posbits, code, n_bits, bitmask);\n\n      if (oldcode == -1)\n      {\n        if (code >= 256)\n          throw(std::ios_base::failure(\"uncompress: input seems to be corrupt.\"));\n\n        outbuf[outpos++] = (unsigned char)(finchar = (int)(oldcode = code));\n        continue;\n      }\n\n      if (code == CLEAR && block_mode)\n      {\n        memset(codetab, 0, 256); //clear_tab_prefixof();\n        free_ent = FIRST - 1;\n        posbits = ((posbits - 1) + ((n_bits << 3) -\n                                    (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));\n        maxcode = MAXCODE(n_bits = INIT_BITS) - 1;\n        bitmask = (1 << n_bits) - 1;\n        goto resetbuf;\n      }\n\n      long int incode = code;\n      unsigned char *stackp = ((unsigned char *)&(htab[HSIZE - 1]));\n\n      if (code >= free_ent) /* Special case for KwKwK string.\t*/\n      {\n        if (code > free_ent)\n        {\n          unsigned char *p;\n\n          posbits -= n_bits;\n          p = &inbuf[posbits >> 3];\n\n          fprintf(stderr, \"insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)\\n\", insize, posbits,\n                  p[-1], p[0], p[1], p[2], p[3], (posbits & 07));\n          fprintf(stderr, \"uncompress: corrupt input\\n\");\n          throw(std::exception()); //exit(1); // read error\n        }\n\n        *--stackp = (unsigned char)finchar;\n        code = oldcode;\n      }\n\n      while ((long int)code >= (long int)256)\n      { /* Generate output characters in reverse order */\n        *--stackp = ((unsigned char *)(htab))[code];\n        code = codetab[code];\n      }\n      *--stackp = (unsigned char)(finchar = ((unsigned char *)(htab))[code]);\n\n      /* And put them out in forward order */\n      {\n        int i;\n\n        if (outpos + (i = (((unsigned char *)&(htab[HSIZE - 1])) - stackp)) >= OBUFSIZ)\n        {\n          do\n          {\n            if (i > OBUFSIZ - outpos)\n              i = OBUFSIZ - outpos;\n\n            if (i > 0)\n            {\n              memcpy(outbuf + outpos, stackp, i);\n              outpos += i;\n            }\n\n            if (outpos >= OBUFSIZ)\n            {\n              for (int k = 0; k < outpos; k++)\n                ss << outbuf[k];\n\n              outpos = 0;\n            }\n            stackp += i;\n          } while ((i = (((unsigned char *)&(htab[HSIZE - 1])) - stackp)) > 0);\n        }\n        else\n        {\n          memcpy(outbuf + outpos, stackp, i);\n          outpos += i;\n        }\n      }\n\n      if ((code = free_ent) < maxmaxcode) /* Generate the new entry. */\n      {\n        codetab[code] = (unsigned short)oldcode;\n        ((unsigned char *)(htab))[code] = (unsigned char)finchar;\n        free_ent = code + 1;\n      }\n      oldcode = incode; /* Remember previous code.\t*/\n    }\n  } while (rsize > 0);\n\n  for (int k = 0; k < outpos; k++)\n    ss << outbuf[k];\n}\n\n/*****************************************************************\n * Algorithm:\n *   Modified Lempel-Ziv method (LZW).  Basically finds common\n *   substrings and replaces them with a variable size code.  This is\n *   deterministic, and can be done on the fly.  Thus, the decompression\n *   procedure needs no input table, but tracks the way the table was built.\n */\nstd::string decompress_file(const char *fileName)\n{\n  std::ifstream infile(fileName, std::ios::in|std::ios::binary);\n  if(!infile.good())\n    throw(std::runtime_error(\"error by opening file\"));\n\n  std::stringstream ss;\n  decompress(infile, ss);\n\n  return ss.str();\n}\n\n#endif\n"
  },
  {
    "path": "source/external/fortran.h",
    "content": "/***********************************************/\n/**\n* @file fortran.h\n*\n* @brief Defines for calling fortran subroutines.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-04-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FORTRAN__\n#define __GROOPS_FORTRAN__\n\n/***** DEFINES *********************************/\n\n/// Name conventions for Fortran subroutines.\n#define FORTRANCALL(lower, upper) lower ## _ // append underscore to lower-case name\n// #define FOTRANCALL(lower, upper) upper    // object references in capital letters\n\n/***** TYPES ***********************************/\n\n/// Data types in Fortran.\n//@{\ntypedef char   F77Char;\ntypedef int    F77Int;\ntypedef double F77Double;\ntypedef float  F77Float;\ntypedef bool   F77Bool;\n//@}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/external/hwm/README.txt",
    "content": "﻿Horizontal Wind Model 2014 (HWM14)\nVersion HWM14.123114\n\nVERSION HISTORY\n  31 Dec 2014 (Release version)\n\nPACKAGE CONTENTS\n\n  README.txt           This file\n  hwm14.f90            Source code for HWM14 and DWM07\n  hwm123114.bin        Binary Data file containing quiet-time HWM parameters\n  dwm07b104i.dat       Data file containing DWM parameters\n  gd2qd.dat            Data file containing parameters for QD coordinate\n                       conversion\n  makefile             Very simple example Makefile\n  checkhwm14.f90       Test driver and test output data\n  Check/ifort.opt.txt  Test driver results, Intel Fortran (v14.0.0) default flags\n  Check/ifort.nopt.txt Test driver results, Intel Fortran (v14.0.0) no optimization\n  Check/gfortan.txt    Test driver results, gfortran (v4.8.1) default flags\n\nPOINT OF CONTACT\n  Douglas P. Drob and John Emmert\n  Space Science Division\n  Naval Research Laboratory\n  4555 Overlook Ave.\n  Washington, DC 20375\n  douglas.drob@nrl.navy.mil\n\n\nREFERENCES\n  Drob, D. P., et al. (2015), An Update to the Horizontal Wind Model (HWM): The\n    Quiet Time Thermosphere, Earth and Space Science, submitted.\n  Drob, D. P., et al. (2008), An Empirical Model of the Earth's Horizontal\n    Wind Fields: HWM07, J. Geophys Res., 113, doi:10.1029/2008JA013668.\n  Emmert, J. T., et al. (2008), DWM07 global empirical model of upper\n    thermospheric storm-induced disturbance winds, J. Geophys Res., 113,\n    doi:10.1029/2008JA013541.\n\nCOMPILER NOTES\n\n  - The model package has been compiled succesfully with the following\n    FORTRAN compiler system combinations: Intel (Windows, Linux, Mac),\n    pgi (Linux), and gfortran (Mac, Linux).\n\n  - No special compiler flags or options should be needed; but as the result\n    of rounding, optimization, and floating point instruction reordering\n    various compiler result in slightly different numerical results on the order\n    of 1 x 10^-4 (i.e. +/- 1 mm/s) in certain regions of space and time. These\n    differences are negligable with respect to the HWM14 empirical model's other\n    climatological and observational uncertainties.  The results from gfortran\n    (v4.8.1) and the ifort (intel) compiler without optimizations (-00) are\n    identical. The default optimization level for the intel fortran compiler is\n    '-O2', so example reaults from 'ifort -O0' and 'ifort' differ slightly.\n    See included files Check/ifort.nopt.txt (ifort -O0), Check/gfortran.txt\n    (gfortran), and Check/ifort.opt.txt (ifort -O2).\n\nRELEASE NOTES\n\n  HWM14 contains several updates to HWM07 and HWM93\n  Improvements to the code include:\n\n      - A more efficient routine (ALFBASIS) for computing associated\n        Legendre functions and the latitude portion of vector spherical\n        harmonic functions.\n\n      - A new routine for the conversion of geodetic to Quasi-Dipole\n        coordinates for the disturbance wind component. This is now done using\n        a spherical harmonic expansion of QD coordinates, rather than gridded\n        interpolation. This modification results in slightly different\n        disturbance winds than in the previous version, because the\n        representation is not exact. The difference is less than 1 m/s.\n\n      - The code has been streamlined and combined into a single file.\n\n      - The FORTRAN90 module layout has been reorganized to be compatable\n        with the python NUMPY f2py feature.\n\n  HWM14 requires three binary data files: hwm123114.bin,\n  dwm07b104i.dat, and gd2qd.dat. These file should be located in one of the\n  following locations; 1) directory from which the program is run, 2) a\n  subdirectory \"../Meta/\" with respect to the\n  directory from which the program is run; and/or 3) in a directory\n  defined by the shell variable HWMPATH. See the subroutine findandopen()\n  for additional details.\n\nMODEL FORMULATION\n  This is an update to the HWM07 empirical model of horizontal winds in the\n  troposphere, stratosphere, mesosphere, and thermosphere, [Drob, D. P., et al.\n  (2008), An Empirical Model of the Earth's Horizontal Wind Fields: HWM07, J.\n  Geophys Res., 113, doi:10.1029/2008JA013668.] which also supersedes  HWM93\n  [Hedin et al., J. Atmos. Terr. Phys., vol. 58, 1421-1447, 1996]. In addition\n  to the date used in HWM93, the HWM07 used extensive new ground-based and space-\n  based wind measurements, including height profiles from NASA-UARS/WINDII,\n  NASA-UARS/HRDI, measurements from ground-based optical and radar instruments\n  obtained from the NSF-CEDAR database, and lower atmospheric NCEP data. This\n  model (HWM14) now includes additional ground-based 630-nm FPI wind\n  measurements at both equatorial and high latitudes (~250 km altitude), in\n  addition to cross track accelerometer wind measurements from the GOCE\n  satellite (~250 km altitude).\n     As in HWM07, in the thermosphere, the model consists of two parts: a quiet-time\n  portion, and a geomagnetically disturbed portion. The quiet-time part\n  represents average wind conditions when ap <= 12. The disturbed part\n  represents average perturbation winds for the specified ap input.\n      The quiet part is represented by vector spherical harmonics in geodetic\n  latitude, geodetic longitude, and solar local time, up to wave number 8 in\n  latitude, 2 in longitude, and 3 in local time. The seasonal dependence is\n  represented by harmonic terms up to semiannual. The vertical structure is\n  represented below 250 km by cubic B-splines with node spacing of 5 km below\n  110 km and higher nodes at 110, 117, 130, 140, 155, 200, and 250 km (modified\n  from HWM07). Above 250 km, an exponential decay function with a scale height\n  of 60 km is used; continuity up to the second derivative is imposed at 250 km.\n      The disturbance winds depend on magnetic latitude, magnetic local time,\n  and Kp. The Quasi-Dipole magnetic coordinates described by Richmond\n  [J Geomagn. Geoelectr., vol. 47, 191-212, 1995] are used for the magnetic\n  coordinates; the code was obtained from the NSF-CEDAR database, and the\n  interpolation grid was computed from IGRF at 250 km and epoch 1994.0 (a\n  modified FORTRAN-90 version of the code, apexcord.f90, is included in this\n  package; it contains only those subroutines needed for reading the\n  interpolation grid and computing QD coordinates). The magnetic latitude and\n  magnetic local time dependence of the disturbance winds is represented by\n  vector spherical harmonics up to wave number 10 in magnetic latitude and wave\n  number 3 in magnetic local time. At mid and low latitudes, only latitudinal\n  terms up to wave number 4 are used; the transition from low resolution at low\n  latitudes to high resolution at high latitudes occurs at a pre-determined\n  latitude that depends on local time and Kp. The transition is made with an\n  exponential function with a width of 4 degrees. The Kp dependence is\n  represented by cubic splines with nodes at 0, 2, 5, and 8. The Kp dependence\n  is constrained to have zero slope at Kp=0 and Kp=8, and is constant above\n  Kp=8.\n\n\nHWM07 ARGUMENT CHANGES FROM HWM93\n  The input and output argument list remains unchanged from that of HWM93,\n  however some of specifics of the arguments have been modified as follows:\n   - The STL (solar local time) input argument is ignored. Local time is\n     computed from the SEC (UT) and GLON (geographic longitude) input arguments.\n   - Only the second element of the AP argument (the 3-hour ap) is used to\n     compute disturbance winds.\n   - The F107 and F107A arguments are ignored in this version.\n   - Module component on/off switches are not yet fully implemented in this\n     version. There is no longer a TSELEC subroutine. For now, for example if\n     longitudinally averaged winds are desired, the model must be evaluated on\n     a longitude grid and the output averaged by the user.\n\nHWM14 ARGUMENT CHANGES FROM HWM07\n   - None\n\nMODEL LIMITATIONS AND FUTURE IMPROVEMENTS\n   - The model currently contains no solar activity dependence, and the F107 and\n     F107A arguments are ignored. During the day, solar activity has a\n     relatively insignificant effect on thermospheric winds. At night, however,\n     the effect is signficant. Solar activity dependencies will be included in\n     a future version.\n   - The disturbed part depends only on magnetic latitude, magnetic local time,\n     and Kp (via the ap argument), and represents average disturbance winds in\n     the upper thermosphere (above 225 km). The disturbance winds are assumed\n     to be constant with height, with a smooth artificial cutoff below 125 km.\n     Height, seasonal, and solar activity dependences will be included in a\n     future version.\n\n\nTO GET TOTAL WINDS:\n  Call HWM14 with the following input arguments:\n        IYD - YEAR AND DAY AS YYDDD\n        SEC - UT(SEC)\n        ALT - ALTITUDE(KM)\n        GLAT - GEODETIC LATITUDE(DEG)\n        GLON - GEODETIC LONGITUDE(DEG)\n        STL - Not used\n        F107A - Not used\n        F107 - Not used\n        AP - Two element array with\n             AP(1) = Not used\n             AP(2) = CURRENT 3HR ap INDEX\n  The output argument is\n        W(1) = MERIDIONAL WIND (m/sec + Northward)\n        W(2) = ZONAL WIND (m/sec + Eastward)\n\n\nTO GET QUIET TIME WINDS:\n  Call HWM14 with a negative value for AP(2)\n\n\nTO GET DISTURBANCE WINDS IN GEOGRAPHIC COORDINATES:\n  Call DWM07 with the following input arguments:\n        IYD - YEAR AND DAY AS YYDDD\n        SEC - UT(SEC)\n        ALT - ALTITUDE(KM)\n        GLAT - GEODETIC LATITUDE(DEG)\n        GLON - GEODETIC LONGITUDE(DEG)\n        AP - Two element array with\n             AP(1) = Not used\n             AP(2) = CURRENT 3HR ap INDEX\n  The output argument is\n        DW(1) = MERIDIONAL DISTURBANCE WIND (m/sec + Geo. Northward)\n        DW(2) = ZONAL DISTURBANCE WIND (m/sec + Geo. Eastward)\n\n\nTO GET DISTURBANCE WINDS IN MAGNETIC COORDINATES:\n  Call DWM07b with the following input arguments:\n        MLT - MAGNETIC LOCAL TIME (HRS)\n        MLAT - MAGNETIC LATITUDE(DEG)\n        KP - CURRENT 3HR Kp INDEX\n  The output arguments are\n        MMPWIND = MERIDIONAL DISTURBANCE WIND (m/sec + Magnetic Northward)\n        MZPWIND = ZONAL DISTURBANCE WIND (m/sec + Magnetic Eastward)\n"
  },
  {
    "path": "source/external/hwm/hwm.h",
    "content": "/***********************************************/\n/**\n* @file hwm.h\n*\n* @brief Fortran Wrapper.\n*\n* @author Sandro Krauss\n* @date 2019-03-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_HWM__\n#define __GROOPS_HWM__\n\n#include \"external/fortran.h\"\n\n#define hwm FORTRANCALL(hwm14, HWM14)\n\nextern \"C\" void hwm(const F77Int &yd, const F77Float &sec, const F77Float &alt,\n                    const F77Float &lat, const F77Float &lon, const F77Float &/*stl*/,\n                    const F77Float &/*f107a*/, const F77Float &/*f107*/,\n                    const F77Float ap[], F77Float outf[]);\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/external/hwm/hwm14.f90",
    "content": "!!!\n!!!  Horizontal Wind Model 14\n!!!\n!!!  AUTHORS\n!!!    Douglas Drob  (0 to ~450+ km, quite-time)\n!!!    John Emmert   (disturbance winds, DWM Emmert et al., (2008))\n!!!    Geospace Science and Technology Branch\n!!!    Space Science Division\n!!!    Naval Research Laboratory\n!!!    4555 Overlook Ave.\n!!!    Washington, DC 20375\n!!!\n!!!  Point of Contact\n!!!   douglas.drob@nrl.navy.mil\n!!!\n!!!   DATE\n!!!    July 8, 2014\n!!!\n!!!\n!!!\n!!!================================================================================\n!!! Input arguments:\n!!!        iyd - year and day as yyddd\n!!!        sec - ut(sec)\n!!!        alt - altitude(km)\n!!!        glat - geodetic latitude(deg)\n!!!        glon - geodetic longitude(deg)\n!!!        stl - not used\n!!!        f107a - not used\n!!!        f107 - not used\n!!!        ap - two element array with\n!!!             ap(1) = not used\n!!!             ap(2) = current 3hr ap index\n!!!\n!!! Output argument:\n!!!        w(1) = meridional wind (m/sec + northward)\n!!!        w(2) = zonal wind (m/sec + eastward)\n!!!\n!!!================================================================================\n\n\nmodule hwm\n\n    integer(4)           :: nmaxhwm = 0        ! maximum degree hwmqt\n    integer(4)           :: omaxhwm = 0        ! maximum order hwmqt\n    integer(4)           :: nmaxdwm = 0        ! maximum degree hwmqt\n    integer(4)           :: mmaxdwm = 0        ! maximum order hwmqt\n    integer(4)           :: nmaxqdc = 0        ! maximum degree of coordinate coversion\n    integer(4)           :: mmaxqdc = 0        ! maximum order of coordinate coversion\n    integer(4)           :: nmaxgeo = 0        ! maximum of nmaxhwm, nmaxqd\n    integer(4)           :: mmaxgeo = 0        ! maximum of omaxhwm, nmaxqd\n\n    real(8),allocatable  :: gpbar(:,:),gvbar(:,:),gwbar(:,:) ! alfs for geo coordinates\n    real(8),allocatable  :: spbar(:,:),svbar(:,:),swbar(:,:) ! alfs MLT calculation\n\n    real(8)              :: glatalf = -1.d32\n\n    logical              :: hwminit = .true.\n\nend module hwm\n\nsubroutine hwm14(iyd,sec,alt,glat,glon,stl,f107a,f107,ap,w)\n\n    use hwm\n    implicit none\n    integer(4),intent(in)   :: iyd\n    real(4),intent(in)      :: sec,alt,glat,glon,stl,f107a,f107\n    real(4),intent(in)      :: ap(2)\n    real(4),intent(out)     :: w(2)\n    real(4)                 :: dw(2)\n\n    if (hwminit) call inithwm()\n\n    call hwmqt(iyd,sec,alt,glat,glon,stl,f107a,f107,ap,w)\n\n    if (ap(2) .ge. 0.0) then\n        call dwm07(iyd,sec,alt,glat,glon,ap,dw)\n        w = w + dw\n    endif\n\n    return\n\nend subroutine hwm14\n\n! ################################################################################\n! Portable utility to compute vector spherical harmonical harmonic basis functions\n! ################################################################################\n\nmodule alf\n\n    implicit none\n\n    integer(4)              :: nmax0,mmax0\n\n    ! static normalizational coeffiecents\n\n    real(8), allocatable    :: anm(:,:),bnm(:,:),dnm(:,:)\n    real(8), allocatable    :: cm(:),en(:)\n    real(8), allocatable    :: marr(:),narr(:)\n\ncontains\n\n    ! -------------------------------------------------------------\n    ! routine to compute vector spherical harmonic basis functions\n    ! -------------------------------------------------------------\n\n    subroutine alfbasis(nmax,mmax,theta,P,V,W)\n\n        implicit none\n\n        integer(4), intent(in)  :: nmax, mmax\n        real(8), intent(in)     :: theta\n        real(8), intent(out)    :: P(0:nmax,0:mmax)\n        real(8), intent(out)    :: V(0:nmax,0:mmax)\n        real(8), intent(out)    :: W(0:nmax,0:mmax)\n\n        integer(8)              :: n, m\n        real(8)                 :: x, y\n        real(8), parameter      :: p00 = 0.70710678118654746d0\n\n        P(0,0) = p00\n        x = dcos(theta)\n        y = dsin(theta)\n        do m = 1, mmax\n            W(m,m) = cm(m) * P(m-1,m-1)\n            P(m,m) = y * en(m) * W(m,m)\n            do n = m+1, nmax\n                W(n,m) = anm(n,m) * x * W(n-1,m) - bnm(n,m) * W(n-2,m)\n                P(n,m) = y * en(n) * W(n,m)\n                V(n,m) = narr(n) * x * W(n,m) - dnm(n,m) * W(n-1,m)\n                W(n-2,m) = marr(m) * W(n-2,m)\n            enddo\n            W(nmax-1,m) = marr(m) * W(nmax-1,m)\n            W(nmax,m) = marr(m) * W(nmax,m)\n            V(m,m) = x * W(m,m)\n        enddo\n        P(1,0) = anm(1,0) * x * P(0,0)\n        V(1,0) = -P(1,1)\n        do n = 2, nmax\n            P(n,0) = anm(n,0) * x * P(n-1,0) - bnm(n,0) * P(n-2,0)\n            V(n,0) = -P(n,1)\n        enddo\n\n        return\n\n    end subroutine alfbasis\n\n    ! -----------------------------------------------------\n    ! routine to compute static normalization coeffiecents\n    ! -----------------------------------------------------\n\n    subroutine initalf(nmaxin,mmaxin)\n\n        implicit none\n\n        integer(4), intent(in) :: nmaxin, mmaxin\n        integer(8)             :: n, m   ! 64 bits to avoid overflow for (m,n) > 60\n\n        nmax0 = nmaxin\n        mmax0 = mmaxin\n\n        if (allocated(anm)) deallocate(anm, bnm, cm, dnm, en, marr, narr)\n        allocate( anm(0:nmax0, 0:mmax0) )\n        allocate( bnm(0:nmax0, 0:mmax0) )\n        allocate( cm(0:mmax0) )\n        allocate( dnm(0:nmax0, 0:mmax0) )\n        allocate( en(0:nmax0) )\n        allocate( marr(0:mmax0) )\n        allocate( narr(0:nmax0) )\n\n        do n = 1, nmax0\n            narr(n) = dble(n)\n            en(n)    = dsqrt(dble(n*(n+1)))\n            anm(n,0) = dsqrt( dble((2*n-1)*(2*n+1)) ) / narr(n)\n            bnm(n,0) = dsqrt( dble((2*n+1)*(n-1)*(n-1)) / dble(2*n-3) ) / narr(n)\n        end do\n        do m = 1, mmax0\n            marr(m) = dble(m)\n            cm(m)    = dsqrt(dble(2*m+1)/dble(2*m*m*(m+1)))\n            do n = m+1, nmax0\n                anm(n,m) = dsqrt( dble((2*n-1)*(2*n+1)*(n-1)) / dble((n-m)*(n+m)*(n+1)) )\n                bnm(n,m) = dsqrt( dble((2*n+1)*(n+m-1)*(n-m-1)*(n-2)*(n-1)) &\n                    / dble((n-m)*(n+m)*(2*n-3)*n*(n+1)) )\n                dnm(n,m) = dsqrt( dble((n-m)*(n+m)*(2*n+1)*(n-1)) / dble((2*n-1)*(n+1)) )\n            end do\n        enddo\n\n        return\n\n    end subroutine initalf\n\nend module alf\n\n!####################################################################################\n! Model Modules\n!####################################################################################\n\nmodule qwm\n\n    implicit none\n\n    integer(4)                 :: nbf              ! Count of basis terms per model level\n    integer(4)                 :: maxn             ! latitude\n    integer(4)                 :: maxs,maxm,maxl   ! seasonal,stationary,migrating\n    integer(4)                 :: maxo\n\n    integer(4)                 :: p                ! B-splines order, p=4 cubic, p=3 quadratic\n    integer(4)                 :: nlev             ! e.g. Number of B-spline nodes\n    integer(4)                 :: nnode            ! nlev + p\n\n    real(8)                    :: alttns           ! Transition 1\n    real(8)                    :: altsym           ! Transition 2\n    real(8)                    :: altiso           ! Constant Limit\n    real(8)                    :: e1(0:4)\n    real(8)                    :: e2(0:4)\n    real(8),parameter          :: H = 60.0d0\n\n    integer(4),allocatable     :: nb(:)            ! total number of basis functions @ level\n    integer(4),allocatable     :: order(:,:)       ! spectral content @ level\n    real(8),allocatable        :: vnode(:)         ! Vertical Altitude Nodes\n    real(8),allocatable        :: mparm(:,:)       ! Model Parameters\n    real(8),allocatable        :: tparm(:,:)       ! Model Parameters\n\n    real(8)                    :: previous(1:5) = -1.0d32\n    integer(4)                 :: priornb = 0\n\n    real(8),allocatable        :: fs(:,:),fm(:,:),fl(:,:)\n    real(8),allocatable        :: bz(:),bm(:)\n\n    real(8),allocatable        :: zwght(:)\n    integer(4)                 :: lev\n\n    integer(4)                 :: cseason = 0\n    integer(4)                 :: cwave = 0\n    integer(4)                 :: ctide = 0\n\n    logical                    :: content(5) = .true.          ! Season/Waves/Tides\n    logical                    :: component(0:1) = .true.      ! Compute zonal/meridional\n\n    character(128)             :: qwmdefault = 'hwm123114.bin'\n    logical                    :: qwminit = .true.\n\n    real(8)                    :: wavefactor(4) = 1.0\n    real(8)                    :: tidefactor(4) = 1.0\n\nend module qwm\n\nmodule dwm\n\n    implicit none\n\n    integer(4)                 :: nterm             ! Number of terms in the model\n    integer(4)                 :: nmax,mmax         ! Max latitudinal degree\n    integer(4)                 :: nvshterm          ! # of VSH basis functions\n\n    integer(4),allocatable     :: termarr(:,:)      ! 3 x nterm index of coupled terms\n    real(4),allocatable        :: coeff(:)          ! Model coefficients\n    real(4),allocatable        :: vshterms(:,:)     ! VSH basis values\n    real(4),allocatable        :: termval(:,:)      ! Term values to which coefficients are applied\n    real(8),allocatable        :: dpbar(:,:)        ! Associated lengendre fns\n    real(8),allocatable        :: dvbar(:,:)\n    real(8),allocatable        :: dwbar(:,:)\n    real(8),allocatable        :: mltterms(:,:)     ! MLT Fourier terms\n    real(4)                    :: twidth            ! Transition width of high-lat mask\n\n    real(8), parameter         :: pi=3.1415926535897932\n    real(8), parameter         :: dtor=pi/180.d0\n\n    logical                    :: dwminit = .true.\n    character(128), parameter  :: dwmdefault = 'dwm07b104i.dat'\n\nend module dwm\n\nsubroutine inithwm()\n\n    use hwm\n    use qwm\n    use dwm\n    use alf,only:initalf\n    implicit none\n\n    integer(4)           :: nmax0, mmax0\n\n    call initqwm(qwmdefault)\n    call initdwm(nmaxdwm, mmaxdwm)\n\n    nmaxgeo = max(nmaxhwm, nmaxqdc)\n    mmaxgeo = max(omaxhwm, mmaxqdc)\n\n    nmax0 = max(nmaxgeo, nmaxdwm)\n    mmax0 = max(mmaxgeo, mmaxdwm)\n\n    call initalf(nmax0,mmax0)\n\n    ! shared for QWM and DWM, no need to compute twice\n\n    if (allocated(gpbar)) deallocate(gpbar,gvbar,gwbar)\n    allocate(gpbar(0:nmaxgeo,0:mmaxgeo))\n    allocate(gvbar(0:nmaxgeo,0:mmaxgeo))\n    allocate(gwbar(0:nmaxgeo,0:mmaxgeo))\n    gpbar = 0\n    gvbar = 0\n    gwbar = 0\n\n    if (allocated(spbar)) deallocate(spbar,svbar,swbar)\n    allocate(spbar(0:nmaxgeo,0:mmaxgeo))\n    allocate(svbar(0:nmaxgeo,0:mmaxgeo))\n    allocate(swbar(0:nmaxgeo,0:mmaxgeo))\n    spbar = 0\n    svbar = 0\n    swbar = 0\n\n    hwminit = .false.\n\n    return\n\nend subroutine inithwm\n\n! ########################################################################################\n!                               The quiet time model functions\n! ########################################################################################\n\n!============================================================================\n! A routine to load the quiet time HWM coeffiecents into memory\n!============================================================================\n\nsubroutine initqwm(filename)\n\n    use qwm\n    use hwm,only:omaxhwm,nmaxhwm\n    implicit none\n\n    character(128),intent(in)      :: filename\n    integer(4)                     :: i,j\n    integer(4)                     :: ncomp\n\n    if (allocated(vnode)) then\n        deallocate(order,nb,vnode,mparm,tparm)\n        deallocate(fs,fm,fl,zwght,bz,bm)\n    endif\n\n    call findandopen(filename,23)\n    read(23) nbf,maxs,maxm,maxl,maxn,ncomp\n    read(23) nlev,p\n    nnode = nlev + p\n    allocate(nb(0:nnode),order(ncomp,0:nnode),vnode(0:nnode))\n    read(23) vnode\n    vnode(3) = 0.0\n    allocate(mparm(nbf,0:nlev))\n    mparm = 0.0d0\n    do i = 0,nlev-p+1-2\n        read(23) order(1:ncomp,i)\n        read(23) nb(i)\n        read(23) mparm(1:nbf,i)\n    enddo\n    read(23) e1,e2\n    close(23)\n\n    ! Calculate the parity relationship permutations\n\n    allocate(tparm(nbf,0:nlev))\n    do i = 0,nlev-p+1-2\n        call parity(order(:,i),nb(i),mparm(:,i),tparm(:,i))\n    enddo\n\n    ! Set transition levels\n\n    alttns = vnode(nlev-2)\n    altsym = vnode(nlev-1)\n    altiso = vnode(nlev)\n\n    ! Allocate the global store of quasi-static parameters\n\n    maxo = max(maxs,maxm,maxl)\n    omaxhwm = maxo\n    nmaxhwm = maxn\n\n    allocate(fs(0:maxs,2),fm(0:maxm,2),fl(0:maxl,2))\n    allocate(bz(nbf),bm(nbf))\n    allocate(zwght(0:p))\n\n    bz = 0.0d0\n    bm = 0.0d0\n\n    ! change the initalization flag and reset some other things\n\n    previous(1:5) = -1.0d32\n    qwminit = .false.\n    qwmdefault = filename\n\n    return\n\ncontains\n\n    subroutine parity(order,nb,mparm,tparm)\n\n        implicit none\n\n        integer(4),intent(in)     :: order(8)\n        integer(4),intent(in)     :: nb\n        real(8),intent(inout)     :: mparm(nb)\n        real(8),intent(out)       :: tparm(nb)\n\n        integer(4)                :: c,m,n,s,l\n\n        integer(4)                :: amaxs,amaxn\n        integer(4)                :: pmaxm,pmaxs,pmaxn\n        integer(4)                :: tmaxl,tmaxs,tmaxn\n\n        amaxs = order(1)\n        amaxn = order(2)\n        pmaxm = order(3)\n        pmaxs = order(4)\n        pmaxn = order(5)\n        tmaxl = order(6)\n        tmaxs = order(7)\n        tmaxn = order(8)\n\n        c = 1\n\n        do n = 1,amaxn\n            tparm(c) = 0.0\n            tparm(c+1) = -mparm(c+1)\n            mparm(c+1) = 0.0\n            c = c + 2\n        enddo\n        do s = 1,amaxs\n            do n = 1,amaxn\n                tparm(c) = 0.0\n                tparm(c+1) = 0.0\n                tparm(c+2) = -mparm(c+2)\n                tparm(c+3) = -mparm(c+3)\n                mparm(c+2) = 0.0\n                mparm(c+3) = 0.0\n                c = c + 4\n            enddo\n        enddo\n\n        do m = 1,pmaxm\n            do n = m,pmaxn\n                tparm(c) = mparm(c+2)\n                tparm(c+1) = mparm(c+3)\n                tparm(c+2) = -mparm(c)\n                tparm(c+3) = -mparm(c+1)\n                c = c + 4\n            enddo\n            do s = 1,pmaxs\n                do n = m,pmaxn\n                    tparm(c) = mparm(c+2)\n                    tparm(c+1) = mparm(c+3)\n                    tparm(c+2) = -mparm(c)\n                    tparm(c+3) = -mparm(c+1)\n                    tparm(c+4) = mparm(c+6)\n                    tparm(c+5) = mparm(c+7)\n                    tparm(c+6) = -mparm(c+4)\n                    tparm(c+7) = -mparm(c+5)\n                    c = c + 8\n                enddo\n            enddo\n\n        enddo\n\n        do l = 1,tmaxl\n            do n = l,tmaxn\n                tparm(c) = mparm(c+2)\n                tparm(c+1) = mparm(c+3)\n                tparm(c+2) = -mparm(c)\n                tparm(c+3) = -mparm(c+1)\n                c = c + 4\n            enddo\n            do s = 1,tmaxs\n                do n = l,tmaxn\n                    tparm(c) = mparm(c+2)\n                    tparm(c+1) = mparm(c+3)\n                    tparm(c+2) = -mparm(c)\n                    tparm(c+3) = -mparm(c+1)\n                    tparm(c+4) = mparm(c+6)\n                    tparm(c+5) = mparm(c+7)\n                    tparm(c+6) = -mparm(c+4)\n                    tparm(c+7) = -mparm(c+5)\n                    c = c + 8\n                enddo\n            enddo\n        enddo\n\n        return\n\n    end subroutine parity\n\nend subroutine initqwm\n\n! ------------------------------------------------------------\n! The quiet time only HWM function call\n! ------------------------------------------------------------\n\nsubroutine hwmqt(IYD,SEC,ALT,GLAT,GLON,STL,F107A,F107,AP,W)\n\n    use hwm\n    use qwm\n    use alf,only:alfbasis\n    implicit none\n\n    integer,intent(in)      :: IYD\n    real(4),intent(in)      :: SEC,ALT,GLAT,GLON,STL,F107A,F107\n    real(4),intent(in)      :: AP(2)\n    real(4),intent(out)     :: W(2)\n\n    ! Local variables\n\n    real(8)                 :: input(5)\n    real(8)                 :: u,v\n\n    real(8)                 :: cs,ss,cm,sm,cl,sl\n    real(8)                 :: cmcs,smcs,cmss,smss\n    real(8)                 :: clcs,slcs,clss,slss\n    real(8)                 :: AA,BB,CC,DD\n    real(8)                 :: vb,wb\n    real(8)                 :: theta,sc\n\n    integer(4)              :: b,c,d,m,n,s,l\n\n    integer(4)              :: amaxs,amaxn\n    integer(4)              :: pmaxm,pmaxs,pmaxn\n    integer(4)              :: tmaxl,tmaxs,tmaxn\n\n    logical                 :: refresh(5)\n\n    real(8),parameter       :: twoPi = 2.0d0*3.1415926535897932384626433832795d0\n    real(8),parameter       :: deg2rad = twoPi/360.0d0\n\n    ! ====================================================================\n    ! Update VSH model terms based on any change in the input parameters\n    ! ====================================================================\n\n    if (qwminit) call initqwm(qwmdefault)\n\n    input(1) = dble(mod(IYD,1000))\n    input(2) = dble(sec)\n    input(3) = dble(glon)\n    input(4) = dble(glat)\n    input(5) = dble(alt)\n\n    refresh(1:5) = .false.\n\n    ! Seasonal variations\n    if (input(1) .ne. previous(1)) then\n        AA = input(1)*twoPi/365.25d0\n        do s = 0,MAXS\n            BB = dble(s)*AA\n            fs(s,1) = dcos(BB)\n            fs(s,2) = dsin(BB)\n        enddo\n        refresh(1:5) = .true.\n        previous(1) = input(1)\n    endif\n\n    ! Hourly time changes, tidal variations\n\n    if (input(2) .ne. previous(2) .or. input(3) .ne. previous(3)) then\n        AA = mod(input(2)/3600.d0 + input(3)/15.d0 + 48.d0,24.d0)\n        BB = AA*twoPi/24.d0\n        do l = 0,MAXL\n            CC = dble(l)*BB\n            fl(l,1) = dcos(CC)\n            fl(l,2) = dsin(CC)\n        enddo\n        refresh(3) = .true.   ! tides\n        previous(2) = input(2)\n    endif\n\n    ! Longitudinal variations, stationary planetary waves\n\n    if (input(3) .ne. previous(3)) then\n        AA = input(3)*deg2rad\n        do m = 0,MAXM\n            BB = dble(m)*AA\n            fm(m,1) = dcos(BB)\n            fm(m,2) = dsin(BB)\n        enddo\n        refresh(2) = .true.   ! stationary planetary waves\n        previous(3) = input(3)\n    endif\n\n    ! Latitude\n\n    theta = (90.0d0 - input(4))*deg2rad\n    if (input(4) .ne. glatalf) then\n        AA = (90.0d0 - input(4))*deg2rad        ! theta = colatitude in radians\n        call alfbasis(maxn,maxm,AA,gpbar,gvbar,gwbar)\n        refresh(1:4) = .true.\n        glatalf = input(4)\n        previous(4) = input(4)\n    endif\n\n    ! Altitude\n\n    if (input(5) .ne. previous(5)) then\n        call vertwght(input(5),zwght,lev)\n        previous(5) = input(5)\n    endif\n\n    ! ====================================================================\n    ! Calculate the VSH functions\n    ! ====================================================================\n\n    u = 0.0d0\n    v = 0.0d0\n\n    do b = 0,p\n\n        if (zwght(b) .eq. 0.d0) cycle\n\n        d = b + lev\n\n        if (priornb .ne. nb(d)) refresh(1:5) = .true. ! recalculate basis functions\n        priornb = nb(d)\n\n        if (.not. any(refresh)) then\n            c = nb(d)\n            if (component(0)) u = u + zwght(b)*dot_product(bz(1:c),mparm(1:c,d))\n            if (component(1)) v = v + zwght(b)*dot_product(bz(1:c),tparm(1:c,d))\n            cycle\n        endif\n\n        amaxs = order(1,d)\n        amaxn = order(2,d)\n        pmaxm = order(3,d)\n        pmaxs = order(4,d)\n        pmaxn = order(5,d)\n        tmaxl = order(6,d)\n        tmaxs = order(7,d)\n        tmaxn = order(8,d)\n\n        c = 1\n\n        ! ------------- Seasonal - Zonal average (m = 0) ----------------\n\n        if (refresh(1) .and. content(1)) then\n            do n = 1,amaxn               ! s = 0\n                bz(c) = -dsin(n*theta)   !\n                bz(c+1) = dsin(n*theta)\n                c = c + 2\n            enddo\n            do s = 1,amaxs                   ! Seasonal variations\n                cs = fs(s,1)\n                ss = fs(s,2)\n                do n = 1,amaxn\n                    sc = dsin(n*theta)\n                    bz(c) = -sc*cs   ! Cr     A\n                    bz(c+1) = sc*ss  ! Ci     B\n                    bz(c+2) = sc*cs\n                    bz(c+3) = -sc*ss\n                    c = c + 4\n                enddo\n            enddo\n            cseason = c\n        else\n            c = cseason\n        endif\n\n        ! ---------------- Stationary planetary waves --------------------\n\n        if (refresh(2) .and. content(2)) then\n            do m = 1,pmaxm\n                cm = fm(m,1)*wavefactor(m)\n                sm = fm(m,2)*wavefactor(m)\n                do n = m,pmaxn           ! s = 0\n                    vb = gvbar(n,m)\n                    wb = gwbar(n,m)\n                    bz(c) =   -vb*cm    ! Cr * (cm) * -vb   A\n                    bz(c+1) =  vb*sm    ! Ci * (sm) *  vb   B\n                    bz(c+2) = -wb*sm\t! Br * (sm) * -wb   C\n                    bz(c+3) = -wb*cm\t! Bi * (cm) * -wb   D\n                    c = c + 4\n                enddo\n                do s = 1,pmaxs\n                    cs = fs(s,1)\n                    ss = fs(s,2)\n                    do n = m,pmaxn\n                        vb = gvbar(n,m)\n                        wb = gwbar(n,m)\n                        bz(c) =   -vb*cm*cs\t! Crc * (cmcs) * -vb   A\n                        bz(c+1) =  vb*sm*cs ! Cic * (smcs) *  vb   B\n                        bz(c+2) = -wb*sm*cs\t! Brc * (smcs) * -wb   C\n                        bz(c+3) = -wb*cm*cs\t! Bic * (cmcs) * -wb   D\n                        bz(c+4) = -vb*cm*ss\t! Crs * (cmss) * -vb   E\n                        bz(c+5) =  vb*sm*ss ! Cis * (smss) *  vb   F\n                        bz(c+6) = -wb*sm*ss\t! Brs * (smss) * -wb   G\n                        bz(c+7) = -wb*cm*ss\t! Bis * (cmss) * -wb   H\n                        c = c + 8\n                    enddo\n                enddo\n                cwave = c\n            enddo\n        else\n            c = cwave\n        endif\n\n        ! ---------------- Migrating Solar Tides ---------------------\n\n        if (refresh(3) .and. content(3)) then\n            do l = 1,tmaxl\n                cl = fl(l,1)*tidefactor(l)\n                sl = fl(l,2)*tidefactor(l)\n                do n = l,tmaxn           ! s = 0\n                    vb = gvbar(n,l)\n                    wb = gwbar(n,l)\n                    bz(c) =   -vb*cl    ! Cr * (cl) * -vb\n                    bz(c+1) =  vb*sl    ! Ci * (sl) *  vb\n                    bz(c+2) = -wb*sl\t! Br * (sl) * -wb\n                    bz(c+3) = -wb*cl\t! Bi * (cl) * -wb\n                    c = c + 4\n                enddo\n                do s = 1,tmaxs\n                    cs = fs(s,1)\n                    ss = fs(s,2)\n                    do n = l,tmaxn\n                        vb = gvbar(n,l)\n                        wb = gwbar(n,l)\n                        bz(c) =   -vb*cl*cs\t! Crc * (clcs) * -vb\n                        bz(c+1) =  vb*sl*cs ! Cic * (slcs) *  vb\n                        bz(c+2) = -wb*sl*cs\t! Brc * (slcs) * -wb\n                        bz(c+3) = -wb*cl*cs\t! Bic * (clcs) * -wb\n                        bz(c+4) = -vb*cl*ss\t! Crs * (clss) * -vb\n                        bz(c+5) =  vb*sl*ss ! Cis * (slss) *  vb\n                        bz(c+6) = -wb*sl*ss\t! Brs * (slss) * -wb\n                        bz(c+7) = -wb*cl*ss\t! Bis * (clss) * -wb\n                        c = c + 8\n                    enddo\n                enddo\n                ctide = c\n            enddo\n        else\n            c = ctide\n        endif\n\n        ! ---------------- Non-Migrating Solar Tides ------------------\n\n        ! TBD\n\n        c = c - 1\n\n        ! ====================================================================\n        ! Calculate the wind components\n        ! ====================================================================\n\n        if (component(0)) u = u + zwght(b)*dot_product(bz(1:c),mparm(1:c,d))\n        if (component(1)) v = v + zwght(b)*dot_product(bz(1:c),tparm(1:c,d))\n\n    enddo\n\n    w(1) = sngl(v)\n    w(2) = sngl(u)\n\n    return\n\nend subroutine hwmqt\n\n\nsubroutine vertwght(alt,wght,iz)\n\n    use qwm\n    implicit none\n\n    real(8),intent(in)      :: alt\n    real(8),intent(out)     :: wght(4)\n    integer(4),intent(out)  :: iz\n\n    real(8)             :: we(0:4)\n\n    iz = findspan(nnode-p-1_4,p,alt,vnode) - p\n\n    iz = min(iz,26)\n\n    wght(1) = bspline(p,nnode,vnode,iz,alt)\n    wght(2) = bspline(p,nnode,vnode,iz+1_4,alt)\n    if (iz .le. 25) then\n        wght(3) = bspline(p,nnode,vnode,iz+2_4,alt)\n        wght(4) = bspline(p,nnode,vnode,iz+3_4,alt)\n        return\n    endif\n    if (alt .gt. alttns) then\n        we(0) = 0.0d0\n        we(1) = 0.0d0\n        we(2) = 0.0d0\n        we(3) = exp(-(alt - alttns)/H)\n        we(4) = 1.0d0\n    else\n        we(0) = bspline(p,nnode,vnode,iz+2_4,alt)\n        we(1) = bspline(p,nnode,vnode,iz+3_4,alt)\n        we(2) = bspline(p,nnode,vnode,iz+4_4,alt)\n        we(3) = 0.0d0\n        we(4) = 0.0d0\n    endif\n    wght(3) = dot_product(we,e1)\n    wght(4) = dot_product(we,e2)\n\n    return\n\ncontains\n\n    function bspline(p,m,V,i,u)\n\n        implicit none\n\n        real(8)     :: bspline\n        integer(4)  :: p,m\n        real(8)     :: V(0:m)\n        integer(4)  :: i\n        real(8)     :: u\n\n        real(8)     :: N(0:p+1)\n        real(8)     :: Vleft,Vright\n        real(8)     :: saved,temp\n        integer(4)  :: j,k\n\n        if ((i .eq. 0) .and. (u .eq. V(0))) then\n            bspline = 1.d0\n            return\n        endif\n\n        if ((i .eq. (m-p-1)) .and. (u .eq. V(m))) then\n            bspline = 1.d0\n            return\n        endif\n\n        if (u .lt. V(i) .or. u .ge. V(i+p+1)) then\n            bspline = 0.d0\n            return\n        endif\n\n        N = 0.0d0\n        do j = 0,p\n            if (u .ge. V(i+j) .and. u .lt. V(i+j+1)) then\n                N(j) = 1.0d0\n            else\n                N(j) = 0.0d0\n            endif\n        enddo\n\n        do k = 1,p\n            if (N(0) .eq. 0.d0) then\n                saved = 0.d0\n            else\n                saved = ((u - V(i))*N(0))/(V(i+k) - V(i))\n            endif\n            do j = 0,p-k\n                Vleft = V(i+j+1)\n                Vright = V(i+j+k+1)\n                if (N(j+1) .eq. 0.d0) then\n                    N(j) = saved\n                    saved = 0.d0\n                else\n                    temp = N(j+1)/(Vright - Vleft)\n                    N(j) = saved + (Vright - u)*temp\n                    saved = (u - Vleft)*temp\n                endif\n            enddo\n        enddo\n\n        bspline = N(0)\n\n        return\n\n    end function bspline\n\n    ! =====================================================\n    ! Function to locate the knot span\n    ! =====================================================\n\n    integer(4) function findspan(n,p,u,V)\n\n        implicit none\n\n        integer(4),intent(in)   :: n,p\n        real(8),intent(in)      :: u\n        real(8),intent(in)      :: V(0:n+1)\n        integer(4)              :: low,mid,high\n\n        if (u .ge. V(n+1)) then\n            findspan = n\n            return\n        endif\n\n        low = p\n        high = n+1\n        mid = (low + high)/2\n\n        do while (u .lt. V(mid) .or. u .ge. V(mid + 1))\n            if (u .lt. V(mid)) then\n                high = mid\n            else\n                low = mid\n            endif\n            mid = (low + high)/2\n        end do\n\n        findspan = mid\n        return\n\n    end function findspan\n\nend subroutine vertwght\n\n! #################################################################################\n!                         Disturbance Wind Model Functions\n! #################################################################################\n\nsubroutine initdwm(nmaxout,mmaxout)\n\n    use hwm\n    use dwm\n    implicit none\n\n    integer(4),intent(out)     :: nmaxout, mmaxout\n\n    call findandopen(dwmdefault,23)\n    if (allocated(termarr)) deallocate(termarr,coeff)\n    read(23) nterm, mmax, nmax\n    allocate(termarr(0:2, 0:nterm-1))\n    read(23) termarr\n    allocate(coeff(0:nterm-1))\n    read(23) coeff\n    read(23) twidth\n    close(23)\n\n    if (allocated(termval)) deallocate(termval,dpbar,dvbar,dwbar,mltterms,vshterms)\n    nvshterm = ( ((nmax+1)*(nmax+2) - (nmax-mmax)*(nmax-mmax+1))/2 - 1 ) * 4 - 2*nmax\n    allocate(termval(0:1, 0:nterm-1))\n    allocate(dpbar(0:nmax,0:mmax),dvbar(0:nmax,0:mmax),dwbar(0:nmax,0:mmax))\n    allocate(mltterms(0:mmax,0:1))\n    allocate(vshterms(0:1, 0:nvshterm-1))\n    dpbar = 0\n    dvbar = 0\n    dwbar = 0\n\n    nmaxout = nmax\n    mmaxout = mmax\n\n    dwminit = .false.\n\n    return\n\nend subroutine initdwm\n\nsubroutine dwm07(IYD,SEC,ALT,GLAT,GLON,AP,DW)\n\n    use hwm\n    use dwm\n    implicit none\n\n    INTEGER,intent(in)      :: IYD\n    REAL(4),intent(in)      :: SEC,ALT,GLAT,GLON\n    REAL(4),intent(in)      :: AP(2)\n    REAL(4),intent(out)     :: DW(2)\n\n    real(4), save           :: day, ut, mlat, mlon, mlt, kp\n    real(4)                 :: mmpwind, mzpwind\n    real(4), save           :: f1e, f1n, f2e, f2n\n    real(4), save           :: glatlast=1.0e16, glonlast=1.0e16\n    real(4), save           :: daylast=1.0e16, utlast=1.0e16, aplast=1.0e16\n    real(4), parameter      :: talt=125.0 !, twidth=5.0\n\n    real(4), external       :: ap2kp, mltcalc\n\n    !CONVERT AP TO KP\n    if (ap(2) .ne. aplast) then\n      kp = ap2kp(ap(2))\n    endif\n\n    !CONVERT GEO LAT/LON TO QD LAT/LON\n    if ((glat .ne. glatlast) .or. (glon .ne. glonlast)) then\n      call gd2qd(glat,glon,mlat,mlon,f1e,f1n,f2e,f2n)\n    endif\n\n    !COMPUTE QD MAGNETIC LOCAL TIME (LOW-PRECISION)\n    day = real(mod(iyd,1000))\n    ut = sec / 3600.0\n    if ((day .ne. daylast) .or. (ut .ne. utlast) .or. &\n        (glat .ne. glatlast) .or. (glon .ne. glonlast)) then\n      mlt = mltcalc(mlat,mlon,day,ut)\n    endif\n\n    !RETRIEVE DWM WINDS\n    call dwm07b(mlt, mlat, kp, mmpwind, mzpwind)\n\n    !CONVERT TO GEOGRAPHIC COORDINATES\n    dw(1) = f2n*mmpwind + f1n*mzpwind\n    dw(2) = f2e*mmpwind + f1e*mzpwind\n\n    !APPLY HEIGHT PROFILE\n    dw = dw / (1 + exp(-(alt - talt)/twidth))\n\n    glatlast = glat\n    glonlast = glon\n    daylast = day\n    utlast = ut\n    aplast = ap(2)\n\n    return\n\nend subroutine dwm07\n\nsubroutine dwm07b(mlt, mlat, kp, mmpwind, mzpwind)\n\n    use hwm\n    use dwm\n    use alf,only:alfbasis\n    implicit none\n\n    real(4),intent(in)        :: mlt       !Magnetic local time (hours)\n    real(4),intent(in)        :: mlat      !Magnetic latitude (degrees)\n    real(4),intent(in)        :: kp        !3-hour Kp\n\n    real(4),intent(out)       :: mmpwind   !Mer. disturbance wind (+north, QD coordinates)\n    real(4),intent(out)       :: mzpwind   !Zon. disturbance wind (+east, QD coordinates)\n\n    ! Local variables\n    integer(4)                :: iterm, ivshterm, n, m\n    real(4)                   :: termvaltemp(0:1)\n    real(4),save              :: kpterms(0:2)\n    real(4)                   :: latwgtterm\n    real(4),save              :: mltlast=1.e16, mlatlast=1.e16, kplast=1.e16\n    real(8)                   :: theta, phi, mphi\n\n    real(4),external          :: latwgt2\n\n    !LOAD MODEL PARAMETERS IF NECESSARY\n    if (dwminit) call initdwm(nmaxdwm, mmaxdwm)\n\n    !COMPUTE LATITUDE PART OF VSH TERMS\n    if (mlat .ne. mlatlast) then\n        theta = (90.d0 - dble(mlat))*dtor\n        call alfbasis(nmax,mmax,theta,dpbar,dvbar,dwbar)\n    endif\n\n    !COMPUTE MLT PART OF VSH TERMS\n    if (mlt .ne. mltlast) then\n        phi = dble(mlt)*dtor*15.d0\n        do m = 0, mmax\n            mphi = dble(m)*phi\n            mltterms(m,0) = dcos(mphi)\n            mltterms(m,1) = dsin(mphi)\n        enddo\n    endif\n\n    !COMPUTE VSH TERMS\n    if ((mlat .ne. mlatlast) .or. (mlt .ne. mltlast)) then\n        ivshterm = 0\n        do n = 1, nmax\n            vshterms(0,ivshterm)   = -sngl(dvbar(n,0)*mltterms(0,0))\n            vshterms(0,ivshterm+1) =  sngl(dwbar(n,0)*mltterms(0,0))\n            vshterms(1,ivshterm)   = -vshterms(0,ivshterm+1)\n            vshterms(1,ivshterm+1) =  vshterms(0,ivshterm)\n            ivshterm = ivshterm + 2\n            do m = 1, mmax\n                if (m .gt. n) cycle\n                vshterms(0,ivshterm)   = -sngl(dvbar(n,m)*mltterms(m,0))\n                vshterms(0,ivshterm+1) =  sngl(dvbar(n,m)*mltterms(m,1))\n                vshterms(0,ivshterm+2) =  sngl(dwbar(n,m)*mltterms(m,1))\n                vshterms(0,ivshterm+3) =  sngl(dwbar(n,m)*mltterms(m,0))\n                vshterms(1,ivshterm)   = -vshterms(0,ivshterm+2)\n                vshterms(1,ivshterm+1) = -vshterms(0,ivshterm+3)\n                vshterms(1,ivshterm+2) =  vshterms(0,ivshterm)\n                vshterms(1,ivshterm+3) =  vshterms(0,ivshterm+1)\n                ivshterm = ivshterm + 4\n            enddo\n        enddo\n    endif\n\n    !COMPUTE KP TERMS\n    if (kp .ne. kplast) then\n        call kpspl3(kp, kpterms)\n    endif\n\n    !COMPUTE LATITUDINAL WEIGHTING TERM\n    latwgtterm = latwgt2(mlat, mlt, kp, twidth)\n\n    !GENERATE COUPLED TERMS\n    do iterm = 0, nterm-1\n        termvaltemp = (/1.0, 1.0/)\n        if (termarr(0,iterm) .ne. 999) termvaltemp = termvaltemp * vshterms(0:1,termarr(0,iterm))\n        if (termarr(1,iterm) .ne. 999) termvaltemp = termvaltemp * kpterms(termarr(1,iterm))\n        if (termarr(2,iterm) .ne. 999) termvaltemp = termvaltemp * latwgtterm\n        termval(0:1,iterm) = termvaltemp(0:1)\n    enddo\n\n    !APPLY COEFFICIENTS\n    mmpwind = dot_product(coeff, termval(0,0:nterm-1))\n    mzpwind = dot_product(coeff, termval(1,0:nterm-1))\n\n    mlatlast = mlat\n    mltlast = mlt\n    kplast = kp\n\n    return\n\nend subroutine dwm07b\n\n!=================================================================================\n!                           Convert Ap to Kp\n!=================================================================================\n\nfunction ap2kp(ap0)\n\n  real(4), parameter :: apgrid(0:27) = (/0.,2.,3.,4.,5.,6.,7.,9.,12.,15.,18., &\n                                         22.,27.,32.,39.,48.,56.,67.,80.,94., &\n                                       111.,132.,154.,179.,207.,236.,300.,400./)\n  real(4), parameter :: kpgrid(0:27) = (/0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11., &\n                                         12.,13.,14.,15.,16.,17.,18.,19.,20.,21., &\n                                         22.,23.,24.,25.,26.,27./) / 3.0\n  real(4)            :: ap0, ap, ap2kp\n  integer(4)         :: i\n\n\n  ap = ap0\n  if (ap .lt. 0) ap = 0\n  if (ap .gt. 400) ap = 400\n\n  i = 1\n  do while (ap .gt. apgrid(i))\n    i = i + 1\n  end do\n  if (ap .eq. apgrid(i)) then\n    ap2kp = kpgrid(i)\n  else\n    ap2kp = kpgrid(i-1) + (ap - apgrid(i-1)) / (3.0 * (apgrid(i) - apgrid(i-1)))\n  end if\n\n  return\n\nend function ap2kp\n\n! ########################################################################\n!     Geographic <=> Geomagnetic Coordinate Transformations\n!\n!  Converts geodetic coordinates to Quasi-Dipole coordinates (Richmond, J. Geomag.\n!  Geoelec., 1995, p. 191), using a spherical harmonic representation.\n!\n! ########################################################################\n\nmodule gd2qdc\n\n    implicit none\n\n    integer(4)               :: nterm, nmax, mmax  !Spherical harmonic expansion parameters\n\n    real(8), allocatable     :: coeff(:,:)         !Coefficients for spherical harmonic expansion\n    real(8), allocatable     :: xcoeff(:)          !Coefficients for x coordinate\n    real(8), allocatable     :: ycoeff(:)          !Coefficients for y coordinate\n    real(8), allocatable     :: zcoeff(:)          !Coefficients for z coordinate\n    real(8), allocatable     :: sh(:)              !Array to hold spherical harmonic fuctions\n    real(8), allocatable     :: shgradtheta(:)     !Array to hold spherical harmonic gradients\n    real(8), allocatable     :: shgradphi(:)       !Array to hold spherical harmonic gradients\n    real(8), allocatable     :: normadj(:)         !Adjustment to VSH normalization factor\n    real(4)                  :: epoch, alt\n\n    real(8), parameter       :: pi = 3.1415926535897932d0\n    real(8), parameter       :: dtor = pi/180.0d0\n    real(8), parameter       :: sineps = 0.39781868d0\n\n    logical                  :: gd2qdinit = .true.\n\ncontains\n\n    subroutine initgd2qd()\n\n        use hwm\n        implicit none\n\n        character(128), parameter   :: datafile='gd2qd.dat'\n        integer(4)                  :: iterm, n\n        integer(4)                  :: j\n\n        call findandopen(datafile,23)\n        read(23) nmax, mmax, nterm, epoch, alt\n        if (allocated(coeff)) then\n            deallocate(coeff,xcoeff,ycoeff,zcoeff,sh,shgradtheta,shgradphi,normadj)\n        endif\n        allocate( coeff(0:nterm-1, 0:2) )\n        read(23) coeff\n        close(23)\n\n        allocate( xcoeff(0:nterm-1) )\n        allocate( ycoeff(0:nterm-1) )\n        allocate( zcoeff(0:nterm-1) )\n        allocate( sh(0:nterm-1) )\n        allocate( shgradtheta(0:nterm-1) )\n        allocate( shgradphi(0:nterm-1) )\n        allocate( normadj(0:nmax) )\n\n        do iterm = 0, nterm-1\n            xcoeff(iterm) = coeff(iterm,0)\n            ycoeff(iterm) = coeff(iterm,1)\n            zcoeff(iterm) = coeff(iterm,2)\n        enddo\n\n        do n = 0, nmax\n            normadj(n) = dsqrt(dble(n*(n+1)))\n        end do\n\n        nmaxqdc = nmax\n        mmaxqdc = mmax\n\n        gd2qdinit = .false.\n\n        return\n\n    end subroutine initgd2qd\n\nend module gd2qdc\n\nsubroutine gd2qd(glatin,glon,qlat,qlon,f1e,f1n,f2e,f2n)\n\n    use hwm\n    use gd2qdc\n    use alf\n\n    implicit none\n\n    real(4), intent(in)         :: glatin, glon\n    real(4), intent(out)        :: qlat, qlon\n    real(4), intent(out)        :: f1e, f1n, f2e, f2n\n\n    integer(4)               :: n, m, i\n    real(8)                  :: glat, theta, phi\n    real(8)                  :: mphi, cosmphi, sinmphi\n    real(8)                  :: x, y, z\n    real(8)                  :: cosqlat, cosqlon, sinqlon\n    real(8)                  :: xgradtheta, ygradtheta, zgradtheta\n    real(8)                  :: xgradphi, ygradphi, zgradphi\n    real(8)                  :: qlonrad\n\n   if (gd2qdinit) call initgd2qd()\n\n    glat = dble(glatin)\n    if (glat .ne. glatalf) then\n      theta = (90.d0 - glat) * dtor\n      call alfbasis(nmax,mmax,theta,gpbar,gvbar,gwbar)\n      glatalf = glat\n    endif\n    phi = dble(glon) * dtor\n\n    i = 0\n    do n = 0, nmax\n      sh(i) = gpbar(n,0)\n      shgradtheta(i) =  gvbar(n,0) * normadj(n)\n      shgradphi(i) = 0\n      i = i + 1\n    enddo\n    do m = 1, mmax\n      mphi = dble(m) * phi\n      cosmphi = dcos(mphi)\n      sinmphi = dsin(mphi)\n      do n = m, nmax\n        sh(i)   = gpbar(n,m) * cosmphi\n        sh(i+1) = gpbar(n,m) * sinmphi\n        shgradtheta(i)   =  gvbar(n,m) * normadj(n) * cosmphi\n        shgradtheta(i+1) =  gvbar(n,m) * normadj(n) * sinmphi\n        shgradphi(i)     = -gwbar(n,m) * normadj(n) * sinmphi\n        shgradphi(i+1)   =  gwbar(n,m) * normadj(n) * cosmphi\n        i = i + 2\n      enddo\n    enddo\n\n    x = dot_product(sh, xcoeff)\n    y = dot_product(sh, ycoeff)\n    z = dot_product(sh, zcoeff)\n\n    qlonrad = datan2(y,x)\n    cosqlon = dcos(qlonrad)\n    sinqlon = dsin(qlonrad)\n    cosqlat = x*cosqlon + y*sinqlon\n\n    qlat = sngl(datan2(z,cosqlat) / dtor)\n    qlon = sngl(qlonrad / dtor)\n\n    xgradtheta = dot_product(shgradtheta, xcoeff)\n    ygradtheta = dot_product(shgradtheta, ycoeff)\n    zgradtheta = dot_product(shgradtheta, zcoeff)\n\n    xgradphi = dot_product(shgradphi, xcoeff)\n    ygradphi = dot_product(shgradphi, ycoeff)\n    zgradphi = dot_product(shgradphi, zcoeff)\n\n    f1e = sngl(-zgradtheta*cosqlat + (xgradtheta*cosqlon + ygradtheta*sinqlon)*z )\n    f1n = sngl(-zgradphi*cosqlat   + (xgradphi*cosqlon   + ygradphi*sinqlon)*z )\n    f2e = sngl( ygradtheta*cosqlon - xgradtheta*sinqlon )\n    f2n = sngl( ygradphi*cosqlon   - xgradphi*sinqlon )\n\n    return\n\nend subroutine gd2qd\n\n!==================================================================================\n!                  (Function) Calculate Magnetic Local Time\n!==================================================================================\n\nfunction mltcalc(qlat,qlon,day,ut)\n\n    use hwm\n    use gd2qdc\n    use alf\n\n    implicit none\n\n    real(4), intent(in)      :: qlat, qlon, day, ut\n    real(4)                  :: mltcalc\n\n    integer(4)               :: n, m, i\n    real(8)                  :: asunglat, asunglon, asunqlon\n    real(8)                  :: glat, theta, phi\n    real(8)                  :: mphi, cosmphi, sinmphi\n    real(8)                  :: x, y\n    real(8)                  :: cosqlat, cosqlon, sinqlon\n    real(8)                  :: qlonrad\n\n    if (gd2qdinit) call initgd2qd()\n\n    !COMPUTE GEOGRAPHIC COORDINATES OF ANTI-SUNWARD DIRECTION (LOW PRECISION)\n    asunglat = -asin(sin((dble(day)+dble(ut)/24.0d0-80.0d0)*dtor) * sineps) / dtor\n    asunglon = -ut * 15.d0\n\n    !COMPUTE MAGNETIC COORDINATES OF ANTI-SUNWARD DIRECTION\n    theta = (90.d0 - asunglat) * dtor\n    call alfbasis(nmax,mmax,theta,spbar,svbar,swbar)\n    phi = asunglon * dtor\n    i = 0\n    do n = 0, nmax\n      sh(i) = spbar(n,0)\n      i = i + 1\n    enddo\n    do m = 1, mmax\n      mphi = dble(m) * phi\n      cosmphi = dcos(mphi)\n      sinmphi = dsin(mphi)\n      do n = m, nmax\n        sh(i)   = spbar(n,m) * cosmphi\n        sh(i+1) = spbar(n,m) * sinmphi\n        i = i + 2\n      enddo\n    enddo\n    x = dot_product(sh, xcoeff)\n    y = dot_product(sh, ycoeff)\n    asunqlon = sngl(datan2(y,x) / dtor)\n\n    !COMPUTE MLT\n    mltcalc = (qlon - asunqlon) / 15.0\n\n    return\n\nend function mltcalc\n\n!================================================================================\n!                           Cubic Spline interpolation of Kp\n!================================================================================\n\nsubroutine kpspl3(kp, kpterms)\n\n    implicit none\n\n    real(4), intent(in)       :: kp\n    real(4), intent(out)      :: kpterms(0:2)\n\n    integer(4)                :: i, j\n    real(4)                   :: x, kpspl(0:6)\n    real(4), parameter        :: node(0:7)=(/-10., -8., 0., 2., 5., 8., 18., 20./)\n\n    x = max(kp, 0.0)\n    x = min(x,  8.0)\n\n    kpterms(0:2) = 0.0\n    do i = 0, 6\n      kpspl(i) = 0.0\n      if ((x .ge. node(i)) .and. (x .lt. node(i+1))) kpspl(i) = 1.0\n    enddo\n    do j = 2,3\n      do i = 0, 8-j-1\n        kpspl(i) = kpspl(i)   * (x - node(i))   / (node(i+j-1) - node(i)) &\n                 + kpspl(i+1) * (node(i+j) - x) / (node(i+j)   - node(i+1))\n      enddo\n    enddo\n    kpterms(0) = kpspl(0) + kpspl(1)\n    kpterms(1) = kpspl(2)\n    kpterms(2) = kpspl(3) + kpspl(4)\n\n    return\n\nend subroutine kpspl3\n\n!================================================================================\n!                           (Function) Latitude weighting factors\n!================================================================================\n\nfunction latwgt2(mlat, mlt, kp0, twidth)\n\n    implicit none\n\n    real(4)                   :: latwgt2\n    real(4)                   :: mlat, mlt, kp0, kp, twidth\n    real(4)                   :: mltrad, sinmlt, cosmlt, tlat\n\n    real(4), parameter :: coeff(0:5) = (/ 65.7633,  -4.60256,  -3.53915,  &\n                                         -1.99971,  -0.752193,  0.972388 /)\n\n    real(4), parameter :: pi=3.141592653590\n    real(4), parameter :: dtor=pi/180.d0\n\n    mltrad = mlt * 15.0 * dtor\n    sinmlt = sin(mltrad)\n    cosmlt = cos(mltrad)\n    kp = max(kp0, 0.0)\n    kp = min(kp,  8.0)\n    tlat = coeff(0) + coeff(1)*cosmlt + coeff(2)*sinmlt +   &\n           kp*(coeff(3) + coeff(4)*cosmlt + coeff(5)*sinmlt)\n    latwgt2 = 1.0 / ( 1 + exp(-(abs(mlat)-tlat)/twidth) )\n\n    return\n\nend function latwgt2\n\n! ========================================================================\n! Utility to find and open the supporting data files\n! ========================================================================\n\nsubroutine findandopen(datafile,unitid)\n\n    implicit none\n\n    character(128)      :: datafile\n    integer             :: unitid\n    character(128)      :: hwmpath\n    logical             :: havefile\n    integer             :: i\n\n    i = index(datafile,'bin')\n    if (i .eq. 0) then\n        inquire(file=trim(datafile),exist=havefile)\n        if (havefile) open(unit=unitid,file=trim(datafile),status='old',form='unformatted')\n        if (.not. havefile) then\n            call get_environment_variable('HWMPATH',hwmpath)\n            inquire(file=trim(hwmpath)//'/'//trim(datafile),exist=havefile)\n            if (havefile) open(unit=unitid, &\n                file=trim(hwmpath)//'/'//trim(datafile),status='old',form='unformatted')\n        endif\n        if (.not. havefile) then\n            inquire(file='../Meta/'//trim(datafile),exist=havefile)\n            if (havefile) open(unit=unitid, &\n                file='../Meta/'//trim(datafile),status='old',form='unformatted')\n        endif\n    else\n        inquire(file=trim(datafile),exist=havefile)\n        if (havefile) open(unit=unitid,file=trim(datafile),status='old',access='stream')\n        if (.not. havefile) then\n            call get_environment_variable('HWMPATH',hwmpath)\n            inquire(file=trim(hwmpath)//'/'//trim(datafile),exist=havefile)\n            if (havefile) open(unit=unitid, &\n                file=trim(hwmpath)//'/'//trim(datafile),status='old',access='stream')\n        endif\n        if (.not. havefile) then\n            inquire(file='../Meta/'//trim(datafile),exist=havefile)\n            if (havefile) open(unit=unitid, &\n                file='../Meta/'//trim(datafile),status='old',access='stream')\n        endif\n    endif\n\n    if (havefile) then\n        return\n    else\n        print *,\"Can not find file \",trim(datafile)\n        stop\n    endif\n\nend subroutine findandopen\n"
  },
  {
    "path": "source/external/iers/CNMTX.F",
    "content": "      SUBROUTINE CNMTX ( DMJD,H )\n*+\n*  - - - - - - - - - -\n*   C N M T X \n*  - - - - - - - - - -\n*\n*  This routine is part of the International Earth Rotation and\n*  Reference Systems Service (IERS) Conventions software collection.\n*\n*  The purpose of the subroutine is to compute the time dependent part\n*  of second degree diurnal and semidiurnal tidal potential from\n*  the dominant spectral lines in the Cartwright-Tayler-Edden harmonic\n*  decomposition.\n*   \n*  In general, Class 1, 2, and 3 models represent physical effects that\n*  act on geodetic parameters while canonical models provide lower-level\n*  representations or basic computations that are used by Class 1, 2, or\n*  3 models.\n*\n*  Status: Canonical model\n* \n*     Class 1 models are those recommended to be used a priori in the\n*     reduction of raw space geodetic data in order to determine\n*     geodetic parameter estimates.\n*     Class 2 models are those that eliminate an observational\n*     singularity and are purely conventional in nature.\n*     Class 3 models are those that are not required as either Class\n*     1 or 2.\n*     Canonical models are accepted as is and cannot be classified as a\n*     Class 1, 2, or 3 model.\n*\n*  Given:\n*     dmjd           d     Modified Julian Date \n*\n*  Returned:\n*     h              d     vector of length 12 with partials of the \n*                          tidal variation with respect to the\n*                          orthoweights (Note 1) \n*\n*  Notes:\n*\n*  1) The diurnal and semidiurnal orthoweights fit to the 8 constituents\n*     are listed in Reference Ray et al.          \n*\n*  Test case:\n*     given input: dmjd = 54964.0D0\n*\n*     expected output: h(1) = 15.35873641938967360D0\n*                      h(2) = 9.784941251812741214D0\n*                      h(3) = -5.520740128266865554D0\n*                      h(4) = 3.575314211234633888D0\n*                      h(5) = -13.93717453496387648D0\n*                      h(6) = -9.167400321705855504D0\n*                      h(7) = 5.532815475865292321D0\n*                      h(8) = 9.558741883500834646D0\n*                      h(9) = -10.22541212627272600D0\n*                      h(10)= 0.8367570529461261231D0\n*                      h(11)= 1.946355176475630611D0\n*                      h(12)= -13.55702062247304696D0\n*\n*  References:\n*\n*     Ray,R. D., Steinberg, D. J., Chao, B. F., and Cartwright, D. E.,\n*     \"Diurnal and Semidiurnal Variations in the Earth's Rotation\n*     Rate Induced by Ocean Tides\", 1994, Science, 264, pp. 830-832\n*\n*     Petit, G. and Luzum, B. (eds.), IERS Conventions (2010),\n*     IERS Technical Note No. 36, BKG (2010)\n*\n*  Revisions:\n*  2008 November 07 B.E. Stetzler    Added header and copyright\n*  2008 November 21 B.E. Stetzler    Redefined variables as double\n*                                    precision and changed twopi\n*  2009 May      12 B.E. Stetzler    Added D0 to DATA structure values\n*  2009 May      19 B.E. Stetzler    Provided validated test case\n*  2009 June     08 B.E. Stetzler    Redefined pinm and alpha, used\n*                                    double precision exclusively, and\n*                                    updated validated test case values\n*  2009 September 03 B.E.Stetzler    Capitalized all variables for Fortran\n*                                    77 compatibility\n*  2010 March     17 B.E.Stetzler    Aligned table array values in DATA\n*                                    structures\n*-----------------------------------------------------------------------\n      IMPLICIT NONE\n      INTEGER I,J,K,M,N,NLINES,NMAX\n      PARAMETER (NLINES=71)\n      CHARACTER*7 NUMARG(NLINES)\n      DOUBLE PRECISION H(12),DMJD, DT60, D1960, DT, TWOPI\n      DOUBLE PRECISION NJ(NLINES),MJ(NLINES)\n      DOUBLE PRECISION HS(NLINES),PHASE(NLINES),FREQ(NLINES)\n      DOUBLE PRECISION ANM(2:3,0:3,-1:1),BNM(2:3,0:3,-1:1)\n      DOUBLE PRECISION AP, AM, BP, BM, PINM, ALPHA\n      DOUBLE PRECISION P(0:2,2),Q(0:2,2),SP(6,2)\n\n* Define the orthotide weight factors\n      DATA ((SP(I,M),I=1,6),M=1,2) /\n     . 0.0298D0,0.1408D0,+0.0805D0, 0.6002D0,+0.3025D0, 0.1517D0,\n     . 0.0200D0,0.0905D0,+0.0638D0, 0.3476D0,+0.1645D0, 0.0923D0/\n\n      PARAMETER (TWOPI = 6.283185307179586476925287D0)\n      DATA DT /2D0/\n      DATA NMAX /2/\n\n* tidal potential model for 71 diurnal and semidiurnal lines\n\n      DATA D1960/37076.5D0/\n      DATA (NJ(J),MJ(J),HS(J),PHASE(J),FREQ(J),NUMARG(J),J=1,15)\n     ./2D0,1D0,  -1.94D0,  9.0899831D0,  5.18688050D0,'117.655',\n     . 2D0,1D0,  -1.25D0,  8.8234208D0,  5.38346657D0,'125.745',\n     . 2D0,1D0,  -6.64D0, 12.1189598D0,  5.38439079D0,'125.755',\n     . 2D0,1D0,  -1.51D0,  1.4425700D0,  5.41398343D0,'127.545',\n     . 2D0,1D0,  -8.02D0,  4.7381090D0,  5.41490765D0,'127.555',\n     . 2D0,1D0,  -9.47D0,  4.4715466D0,  5.61149372D0,'135.645',\n     . 2D0,1D0, -50.20D0,  7.7670857D0,  5.61241794D0,'135.655',\n     . 2D0,1D0,  -1.80D0, -2.9093042D0,  5.64201057D0,'137.445',\n     . 2D0,1D0,  -9.54D0,  0.3862349D0,  5.64293479D0,'137.455',\n     . 2D0,1D0,   1.52D0, -3.1758666D0,  5.83859664D0,'145.535',\n     . 2D0,1D0, -49.45D0,  0.1196725D0,  5.83952086D0,'145.545',\n     . 2D0,1D0,-262.21D0,  3.4152116D0,  5.84044508D0,'145.555',\n     . 2D0,1D0,   1.70D0, 12.8946194D0,  5.84433381D0,'145.755',\n     . 2D0,1D0,   3.43D0,  5.5137686D0,  5.87485066D0,'147.555',\n     . 2D0,1D0,   1.94D0,  6.4441883D0,  6.03795537D0,'153.655'/\n      DATA (NJ(J),MJ(J),HS(J),PHASE(J),FREQ(J),NUMARG(J),J=16,30)\n     ./2D0,1D0,   1.37D0, -4.2322016D0,  6.06754801D0,'155.445',\n     . 2D0,1D0,   7.41D0, -0.9366625D0,  6.06847223D0,'155.455',\n     . 2D0,1D0,  20.62D0,  8.5427453D0,  6.07236095D0,'155.655',\n     . 2D0,1D0,   4.14D0, 11.8382843D0,  6.07328517D0,'155.665',\n     . 2D0,1D0,   3.94D0,  1.1618945D0,  6.10287781D0,'157.455',\n     . 2D0,1D0,  -7.14D0,  5.9693878D0,  6.24878055D0,'162.556',\n     . 2D0,1D0,   1.37D0, -1.2032249D0,  6.26505830D0,'163.545',\n     . 2D0,1D0,-122.03D0,  2.0923141D0,  6.26598252D0,'163.555',\n     . 2D0,1D0,   1.02D0, -1.7847596D0,  6.28318449D0,'164.554',\n     . 2D0,1D0,   2.89D0,  8.0679449D0,  6.28318613D0,'164.556',\n     . 2D0,1D0,  -7.30D0,  0.8953321D0,  6.29946388D0,'165.545',\n     . 2D0,1D0, 368.78D0,  4.1908712D0,  6.30038810D0,'165.555',\n     . 2D0,1D0,  50.01D0,  7.4864102D0,  6.30131232D0,'165.565',\n     . 2D0,1D0,  -1.08D0, 10.7819493D0,  6.30223654D0,'165.575',\n     . 2D0,1D0,   2.93D0,  0.3137975D0,  6.31759007D0,'166.554'/\n      DATA (NJ(J),MJ(J),HS(J),PHASE(J),FREQ(J),NUMARG(J),J=31,45)\n     ./2D0,1D0,   5.25D0,  6.2894282D0,  6.33479368D0,'167.555',\n     . 2D0,1D0,   3.95D0,  7.2198478D0,  6.49789839D0,'173.655',\n     . 2D0,1D0,  20.62D0, -0.1610030D0,  6.52841524D0,'175.455',\n     . 2D0,1D0,   4.09D0,  3.1345361D0,  6.52933946D0,'175.465',\n     . 2D0,1D0,   3.42D0,  2.8679737D0,  6.72592553D0,'183.555',\n     . 2D0,1D0,   1.69D0, -4.5128771D0,  6.75644239D0,'185.355',\n     . 2D0,1D0,  11.29D0,  4.9665307D0,  6.76033111D0,'185.555',\n     . 2D0,1D0,   7.23D0,  8.2620698D0,  6.76125533D0,'185.565',\n     . 2D0,1D0,   1.51D0, 11.5576089D0,  6.76217955D0,'185.575',\n     . 2D0,1D0,   2.16D0,  0.6146566D0,  6.98835826D0,'195.455',\n     . 2D0,1D0,   1.38D0,  3.9101957D0,  6.98928248D0,'195.465',\n     . 2D0,2D0,   1.80D0, 20.6617051D0, 11.45675174D0,'225.855',\n     . 2D0,2D0,   4.67D0, 13.2808543D0, 11.48726860D0,'227.655',\n     . 2D0,2D0,  16.01D0, 16.3098310D0, 11.68477889D0,'235.755',\n     . 2D0,2D0,  19.32D0,  8.9289802D0, 11.71529575D0,'237.555'/\n      DATA (NJ(J),MJ(J),HS(J),PHASE(J),FREQ(J),NUMARG(J),J=46,60)\n     ./2D0,2D0,   1.30D0,  5.0519065D0, 11.73249771D0,'238.554',\n     . 2D0,2D0,  -1.02D0, 15.8350306D0, 11.89560406D0,'244.656',\n     . 2D0,2D0,  -4.51D0,  8.6624178D0, 11.91188181D0,'245.645',\n     . 2D0,2D0, 120.99D0, 11.9579569D0, 11.91280603D0,'245.655',\n     . 2D0,2D0,   1.13D0,  8.0808832D0, 11.93000800D0,'246.654',\n     . 2D0,2D0,  22.98D0,  4.5771061D0, 11.94332289D0,'247.455',\n     . 2D0,2D0,   1.06D0,  0.7000324D0, 11.96052486D0,'248.454',\n     . 2D0,2D0,  -1.90D0, 14.9869335D0, 12.11031632D0,'253.755',\n     . 2D0,2D0,  -2.18D0, 11.4831564D0, 12.12363121D0,'254.556',\n     . 2D0,2D0, -23.58D0,  4.3105437D0, 12.13990896D0,'255.545',\n     . 2D0,2D0, 631.92D0,  7.6060827D0, 12.14083318D0,'255.555',\n     . 2D0,2D0,   1.92D0,  3.7290090D0, 12.15803515D0,'256.554',\n     . 2D0,2D0,  -4.66D0, 10.6350594D0, 12.33834347D0,'263.655',\n     . 2D0,2D0, -17.86D0,  3.2542086D0, 12.36886033D0,'265.455',\n     . 2D0,2D0,   4.47D0, 12.7336164D0, 12.37274905D0,'265.655'/\n      DATA (NJ(J),MJ(J),HS(J),PHASE(J),FREQ(J),NUMARG(J),J=61,71)\n     ./2D0,2D0,   1.97D0, 16.0291555D0, 12.37367327D0,'265.665',\n     . 2D0,2D0,  17.20D0, 10.1602590D0, 12.54916865D0,'272.556',\n     . 2D0,2D0, 294.00D0,  6.2831853D0, 12.56637061D0,'273.555',\n     . 2D0,2D0,  -2.46D0,  2.4061116D0, 12.58357258D0,'274.554',\n     . 2D0,2D0,  -1.02D0,  5.0862033D0, 12.59985198D0,'275.545',\n     . 2D0,2D0,  79.96D0,  8.3817423D0, 12.60077620D0,'275.555',\n     . 2D0,2D0,  23.83D0, 11.6772814D0, 12.60170041D0,'275.565',\n     . 2D0,2D0,   2.59D0, 14.9728205D0, 12.60262463D0,'275.575',\n     . 2D0,2D0,   4.47D0,  4.0298682D0, 12.82880334D0,'285.455',\n     . 2D0,2D0,   1.95D0,  7.3254073D0, 12.82972756D0,'285.465',\n     . 2D0,2D0,   1.17D0,  9.1574019D0, 13.06071921D0,'295.555'/\n\n* Compute the time dependent potential matrix\n\n      DO 50 K=-1,1\n         DT60 = (DMJD - K*DT) - D1960\n         ANM(2,1:2,K) = 0D0\n         BNM(2,1:2,K) = 0D0\n         DO 100 J=1,NLINES\n            N = NJ(J)\n            M = MJ(J)\n            PINM = DFLOAT(MOD(N+M,2))*TWOPI/4.0D0\n            !alpha = phase(j) + freq(j)*dt60 - pinm\n            ALPHA = DMOD(PHASE(J) - PINM,TWOPI) \n     .              + DMOD(FREQ(J)*DT60,TWOPI)\n            ANM(N,M,K) = ANM(N,M,K) + HS(J)*DCOS(ALPHA)\n            BNM(N,M,K) = BNM(N,M,K) - HS(J)*DSIN(ALPHA)\n100      CONTINUE\n50    CONTINUE\n\n* orthogonalize the response terms\n\n      DO 150 M = 1,2\n        AP = ANM(2,M,1) + ANM(2,M,-1)\n        AM = ANM(2,M,1) - ANM(2,M,-1)\n        BP = BNM(2,M,1) + BNM(2,M,-1)\n        BM = BNM(2,M,1) - BNM(2,M,-1)\n        P(0,M) = SP(1,M)*ANM(2,M,0)\n        P(1,M) = SP(2,M)*ANM(2,M,0) - SP(3,M)*AP\n        P(2,M) = SP(4,M)*ANM(2,M,0) - SP(5,M)*AP + SP(6,M)*BM\n        Q(0,M) = SP(1,M)*BNM(2,M,0)\n        Q(1,M) = SP(2,M)*BNM(2,M,0) - SP(3,M)*BP\n        Q(2,M) = SP(4,M)*BNM(2,M,0) - SP(5,M)*BP - SP(6,M)*AM\n        ANM(2,M,-1) = P(0,M)\n        ANM(2,M,0) = P(1,M)\n        ANM(2,M,1) = P(2,M)\n        BNM(2,M,-1) = Q(0,M)\n        BNM(2,M,0) = Q(1,M)\n        BNM(2,M,1) = Q(2,M)\n150   CONTINUE\n\n* fill partials vector\n      J = 1\n      DO 200 N=2,NMAX\n         DO 250 M = 1,N\n            DO 300 K = -1,1\n               H(J)  = ANM(N,M,K)\n               H(J+1)= BNM(N,M,K)\n               J = J + 2\n300         CONTINUE\n250      CONTINUE \n200   CONTINUE\n\n      RETURN\n\n* Finished.\n\n*+----------------------------------------------------------------------\n*\n*  Copyright (C) 2008\n*  IERS Conventions Center\n*\n*  ==================================\n*  IERS Conventions Software License\n*  ==================================\n*\n*  NOTICE TO USER:\n*\n*  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING TERMS AND CONDITIONS\n*  WHICH APPLY TO ITS USE.\n*\n*  1. The Software is provided by the IERS Conventions Center (\"the\n*     Center\").\n*\n*  2. Permission is granted to anyone to use the Software for any\n*     purpose, including commercial applications, free of charge,\n*     subject to the conditions and restrictions listed below.\n*\n*  3. You (the user) may adapt the Software and its algorithms for your\n*     own purposes and you may distribute the resulting \"derived work\"\n*     to others,provided that the derived work complies with the\n*     following requirements:\n*\n*     a) Your work shall be clearly identified so that it cannot be\n*        mistaken for IERS Conventions software and that it has been\n*        neither distributed by nor endorsed by the Center.\n*\n*     b) Your work (including source code) must contain descriptions of\n*        how the derived work is based upon and/or differs from the\n*        original Software.\n*\n*     c) The name(s) of all modified routine(s) that you distribute\n*        shall be changed.\n* \n*     d) The origin of the IERS Conventions components of your derived\n*        work must not be misrepresented; you must not claim that you\n*        wrote the original Software.\n*\n*     e) The source code must be included for all routine(s) that you\n*        distribute.  This notice must be reproduced intact in any\n*        source distribution. \n*\n*  4. In any published work produced by the user and which includes\n*     results achieved by using the Software, you shall acknowledge\n*     that the Software was used in obtaining those results.\n*\n*  5. The Software is provided to the user \"as is\" and the Center makes\n*     no warranty as to its use or performance.   The Center does not\n*     and cannot warrant the performance or results which the user may\n*     obtain by using the Software.  The Center makes no warranties,\n*     express or implied, as to non-infringement of third party rights,\n*     merchantability, or fitness for any particular purpose.  In no\n*     event will the Center be liable to the user for any consequential,\n*     incidental, or special damages, including any lost profits or lost\n*     savings, even if a Center representative has been advised of such\n*     damages, or for any claim by any third party.\n*\n*  Correspondence concerning IERS Conventions software should be\n*  addressed as follows:\n*\n*                     Gerard Petit\n*     Internet email: gpetit[at]bipm.org\n*     Postal address: IERS Conventions Center\n*                     Time, frequency and gravimetry section, BIPM\n*                     Pavillon de Breteuil\n*                     92312 Sevres  FRANCE\n*\n*     or\n*\n*                     Brian Luzum\n*     Internet email: brian.luzum[at]usno.navy.mil\n*     Postal address: IERS Conventions Center\n*                     Earth Orientation Department\n*                     3450 Massachusetts Ave, NW\n*                     Washington, DC 20392\n*\n*\n*-----------------------------------------------------------------------\n      END\n"
  },
  {
    "path": "source/external/iers/FUNDARG.f",
    "content": "      SUBROUTINE FUNDARG ( T, L, LP, F, D, OM )\n*+\n*  - - - - - - - - - - -\n*   F U N D A R G \n*  - - - - - - - - - - -\n*\n*  This routine is part of the International Earth Rotation and\n*  Reference Systems Service (IERS) Conventions software collection.\n*\n*  This subroutine computes the lunisolar fundamental arguments.\n*  The model used is from Simon et al. (1994) as recommended by the IERS\n*  Conventions (2010).  Refer to IERS Conventions (2010) Chapter 5 \n*  Sections 5.7.1 - 5.7.2 (pp. 57 - 59).\n*\n*  In general, Class 1, 2, and 3 models represent physical effects that\n*  act on geodetic parameters while canonical models provide lower-level\n*  representations or basic computations that are used by Class 1, 2, or\n*  3 models.\n* \n*  Status: Canonical model\n*\n*     Class 1 models are those recommended to be used a priori in the\n*     reduction of raw space geodetic data in order to determine\n*     geodetic parameter estimates.\n*     Class 2 models are those that eliminate an observational\n*     singularity and are purely conventional in nature.\n*     Class 3 models are those that are not required as either Class\n*     1 or 2.\n*     Canonical models are accepted as is and cannot be classified as a\n*     Class 1, 2, or 3 model.\n*\n*  Given:\n*     T           d      TT, Julian centuries since J2000 (Note 1)\n*\n*  Returned:\n*     L           d      Mean anomaly of the Moon (Note 2)\n*     LP          d      Mean anomaly of the Sun (Note 2)\n*     F           d      L - OM (Notes 2 and 3)\n*     D           d      Mean elongation of the Moon from the Sun\n*                                                         (Note 2)\n*     OM          d      Mean longitude of the ascending node of\n*                                                the Moon (Note 2)\n*\n*  Notes:\n*\n*  1) Though T is strictly TDB, it is usually more convenient to use\n*     TT, which makes no significant difference.  Julian centuries since\n*     J2000 is (JD - 2451545.0)/36525.\n*\n*  2) The expression used is as adopted in IERS Conventions (2010) and\n*     is from Simon et al. (1994).  Arguments are in radians.\n*\n*  3) L in this instance is the Mean Longitude of the Moon. OM is the \n*     Mean longitude of the ascending node of the Moon.\n*\n*  Test case:\n*     given input: T = 0.07995893223819302 Julian centuries since J2000\n*                  (MJD = 54465)\n*     expected output:  L = 2.291187512612069099 radians\n*                       LP = 6.212931111003726414 radians\n*                       F = 3.658025792050572989 radians\n*                       D = 4.554139562402433228 radians\n*                       OM = -0.5167379217231804489 radians\n*\n*  References:\n*\n*     Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M.,\n*     Francou, G., Laskar, J., 1994, Astron.Astrophys. 282, 663-683\n*\n*     Petit, G. and Luzum, B. (eds.), IERS Conventions (2010),\n*     IERS Technical Note No. 36, BKG (2010)\n*\n*  Revisions:\n*  2008 January 18 B.E.Stetzler  Initial changes to header\n*               and used 2PI instead of PI as parameter\n*  2008 January 25 B.E. Stetzler Additional changes to header\n*               and defined fundamental arguments\n*  2008 January 28 B.E. Stetzler Additional changes to header\n*  2008 March   12 B.E. Stetzler Applied changes to wording of notes.\n*  2008 April   03 B.E. Stetzler Provided example test case.\n*  2009 February 11 B.E. Stetzler Corrected term in OM from 6962890.2665\n*                                 to 6962890.5431 and updated test case\n*  2009 May     07 B.E. Stetzler Code formatting changes based on \n*                                client recommendations\n*  2009 May     07 B.E. Stetzler Updated test case due to above changes\n*  2010 February 25 B.E. Stetzler Recalculation of fundamental arguments\n*-----------------------------------------------------------------------\n\n      IMPLICIT NONE\n\n      DOUBLE PRECISION T, L, LP, F, D, OM\n\n*  Arcseconds to radians\n      DOUBLE PRECISION DAS2R\n      PARAMETER ( DAS2R = 4.848136811095359935899141D-6 )\n\n*  Arcseconds in a full circle\n      DOUBLE PRECISION TURNAS\n      PARAMETER ( TURNAS = 1296000D0 )\n\n*  2Pi\n      DOUBLE PRECISION D2PI\n      PARAMETER ( D2PI = 6.283185307179586476925287D0 )\n\n* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n*  Compute the fundamental argument L.\n      L = MOD (       485868.249036D0 +\n     .                  T*( 1717915923.2178D0 +\n     .                  T*(         31.8792D0 +\n     .                  T*(          0.051635D0 +\n     .                  T*(        - 0.00024470D0 )))), TURNAS ) * DAS2R\n\n*  Compute the fundamental argument LP.\n      LP = MOD (       1287104.79305D0 +\n     .            T*( 129596581.0481D0 +\n     .            T*(       - 0.5532D0 +\n     .            T*(         0.000136D0 +\n     .            T*(       - 0.00001149D0 )))), TURNAS ) * DAS2R\n\n*  Compute the fundamental argument F.\n      F  = MOD (       335779.526232D0 +\n     .                  T*( 1739527262.8478D0 +\n     .                  T*(       - 12.7512D0 +\n     .                  T*(       -  0.001037D0 +\n     .                  T*(          0.00000417D0 )))), TURNAS ) * DAS2R\n\n*  Compute the fundamental argument D.\n      D = MOD (        1072260.70369D0 +\n     .          T*( 1602961601.2090D0 +\n     .          T*(        - 6.3706D0 +\n     .          T*(          0.006593D0 +\n     .          T*(        - 0.00003169D0 )))), TURNAS ) * DAS2R\n\n*  Compute the fundamental argument OM.\n      OM = MOD (       450160.398036D0 +\n     .             T*( - 6962890.5431D0 +\n     .             T*(         7.4722D0 +\n     .             T*(         0.007702D0 +\n     .             T*(       - 0.00005939D0 )))), TURNAS ) * DAS2R\n\n*  Finished.\n\n*+----------------------------------------------------------------------\n*\n*  Copyright (C) 2008\n*  IERS Conventions Center\n*\n*  ==================================\n*  IERS Conventions Software License\n*  ==================================\n*\n*  NOTICE TO USER:\n*\n*  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING TERMS AND CONDITIONS\n*  WHICH APPLY TO ITS USE.\n*\n*  1. The Software is provided by the IERS Conventions Center (\"the\n*     Center\").\n*\n*  2. Permission is granted to anyone to use the Software for any\n*     purpose, including commercial applications, free of charge,\n*     subject to the conditions and restrictions listed below.\n*\n*  3. You (the user) may adapt the Software and its algorithms for your\n*     own purposes and you may distribute the resulting \"derived work\"\n*     to others, provided that the derived work complies with the\n*     following requirements:\n*\n*     a) Your work shall be clearly identified so that it cannot be\n*        mistaken for IERS Conventions software and that it has been\n*        neither distributed by nor endorsed by the Center.\n*\n*     b) Your work (including source code) must contain descriptions of\n*        how the derived work is based upon and/or differs from the\n*        original Software.\n*\n*     c) The name(s) of all modified routine(s) that you distribute\n*        shall be changed.\n* \n*     d) The origin of the IERS Conventions components of your derived\n*        work must not be misrepresented; you must not claim that you\n*        wrote the original Software.\n*\n*     e) The source code must be included for all routine(s) that you\n*        distribute.  This notice must be reproduced intact in any\n*        source distribution. \n*\n*  4. In any published work produced by the user and which includes\n*     results achieved by using the Software, you shall acknowledge\n*     that the Software was used in obtaining those results.\n*\n*  5. The Software is provided to the user \"as is\" and the Center makes\n*     no warranty as to its use or performance.   The Center does not\n*     and cannot warrant the performance or results which the user may\n*     obtain by using the Software.  The Center makes no warranties,\n*     express or implied, as to non-infringement of third party rights,\n*     merchantability, or fitness for any particular purpose.  In no\n*     event will the Center be liable to the user for any consequential,\n*     incidental, or special damages, including any lost profits or lost\n*     savings, even if a Center representative has been advised of such\n*     damages, or for any claim by any third party.\n*\n*  Correspondence concerning IERS Conventions software should be\n*  addressed as follows:\n*\n*                     Gerard Petit\n*     Internet email: gpetit[at]bipm.org\n*     Postal address: IERS Conventions Center\n*                     Time, frequency and gravimetry section, BIPM\n*                     Pavillon de Breteuil\n*                     92312 Sevres  FRANCE\n*\n*     or\n*\n*                     Brian Luzum\n*     Internet email: brian.luzum[at]usno.navy.mil\n*     Postal address: IERS Conventions Center\n*                     Earth Orientation Department\n*                     3450 Massachusetts Ave, NW\n*                     Washington, DC 20392\n*\n*\n*-----------------------------------------------------------------------\n      END\n"
  },
  {
    "path": "source/external/iers/ORTHO_EOP.F",
    "content": "      SUBROUTINE ORTHO_EOP ( TIME, EOP )\n*+\n*  - - - - - - - - - -\n*   O R T H O _ E O P \n*  - - - - - - - - - -\n*\n*  This routine is part of the International Earth Rotation and\n*  Reference Systems Service (IERS) Conventions software collection.\n*\n*  The purpose of the subroutine is to compute the diurnal and semi-\n*  diurnal variations in Earth Orientation Parameters (x,y, UT1) from\n*  ocean tides.\n* \n*  In general, Class 1, 2, and 3 models represent physical effects that\n*  act on geodetic parameters while canonical models provide lower-level\n*  representations or basic computations that are used by Class 1, 2, or\n*  3 models.\n* \n*  Status: Class 1 model\n* \n*     Class 1 models are those recommended to be used a priori in the\n*     reduction of raw space geodetic data in order to determine\n*     geodetic parameter estimates.\n*     Class 2 models are those that eliminate an observational\n*     singularity and are purely conventional in nature.\n*     Class 3 models are those that are not required as either Class\n*     1 or 2.\n*     Canonical models are accepted as is and cannot be classified as a\n*     Class 1, 2, or 3 model.\n*\n*  Given:\n*     TIME           d     Modified Julian Date \n*\n*  Returned:\n*     EOP            d     delta_x, in microarcseconds\n*                          delta_y, in microarcseconds\n*                          delta_UT1, in microseconds \n*\n*  Notes:\n*\n*  1) The diurnal and semidiurnal orthoweights fit to the 8 constituents\n*     are listed in Reference 1.\n*     \n*  Called:\n*     CNMTX                Compute time dependent part of second degree\n*                          diurnal and semidiurnal tidal potential from\n*                          the dominant spectral lines in the Cartwright-\n*                          Tayler-Edden harmonic decomposition                  *            \n*  Test case:\n*     given input: MJD = 47100D0\n*\n*     expected output: delta_x = -162.8386373279636530D0 microarcseconds\n*                      delta_y = 117.7907525842668974D0 microarcseconds\n*                      delta_UT1 = -23.39092370609808214D0 microseconds\n*\n*  References:\n*\n*     Ray, R. D., Steinberg, D. J., Chao, B. F., and Cartwright, D. E.,\n*     \"Diurnal and Semidiurnal Variations in the Earth's Rotation\n*     Rate Induced by Ocean Tides\", 1994, Science, 264, pp. 830-832\n*\n*     Petit, G. and Luzum, B. (eds.), IERS Conventions (2010),\n*     IERS Technical Note No. 36, BKG (2010)\n*\n*  Revisions:\n*  1997 February    R. Eanes         Original code\n*  2008 November 07 B.E. Stetzler    Added header and copyright\n*  2008 November 07 B.E. Stetzler    Provided test case\n*  2009 May      12 B.E. Stetzler    Replaced ENDDO statements with\n*                                    CONTINUE statements\n*  2009 June     09 B.E. Stetzler    Updated validated test case values\n*                                    based on changes to CNMTX.F\n*  2010 March    19 B.E. Stetzler    Capitalized variables for FORTRAN\n*                                    77 backwards compatibility\n*-----------------------------------------------------------------------\n\n      IMPLICIT NONE\n      INTEGER K, J\n      DOUBLE PRECISION EOP(3), ORTHOW(12,3), TIME, H(12)\n      DATA ORTHOW /\n     .-6.77832D0,-14.86323D0,0.47884D0,-1.45303D0,0.16406D0,  0.42030D0,\n     . 0.09398D0,25.73054D0,-4.77974D0, 0.28080D0,1.94539D0, -0.73089D0,\n     .14.86283D0,-6.77846D0, 1.45234D0, 0.47888D0,-0.42056D0, 0.16469D0,\n     .15.30276D0,-4.30615D0, 0.07564D0, 2.28321D0,-0.45717D0,-1.62010D0,\n     .-1.76335D0,1.03364D0, -0.27553D0, 0.34569D0,-0.12343D0,-0.10146D0,\n     .-0.47119D0,1.28997D0, -0.19336D0, 0.02724D0, 0.08955D0, 0.04726D0/\n\n* Compute the partials of the tidal variations to the orthoweights\n      CALL CNMTX (TIME, H)\n\n* Compute eop changes\n      DO 20 K=1,3\n         EOP(K) = 0D0\n         DO 40 J=1,12\n            EOP(K) = EOP(K) + H(J)*ORTHOW(J,K)\n40       CONTINUE         \n\n20    CONTINUE\n      RETURN\n\n* Finished.\n\n*+----------------------------------------------------------------------\n*\n*  Copyright (C) 2008\n*  IERS Conventions Center\n*\n*  ==================================\n*  IERS Conventions Software License\n*  ==================================\n*\n*  NOTICE TO USER:\n*\n*  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING TERMS AND CONDITIONS\n*  WHICH APPLY TO ITS USE.\n*\n*  1. The Software is provided by the IERS Conventions Center (\"the\n*     Center\").\n*\n*  2. Permission is granted to anyone to use the Software for any\n*     purpose, including commercial applications, free of charge,\n*     subject to the conditions and restrictions listed below.\n*\n*  3. You (the user) may adapt the Software and its algorithms for your\n*     own purposes and you may distribute the resulting \"derived work\"\n*     to others, provided that the derived work complies with the\n*     following requirements:\n*\n*     a) Your work shall be clearly identified so that it cannot be\n*        mistaken for IERS Conventions software and that it has been\n*        neither distributed by nor endorsed by the Center.\n*\n*     b) Your work (including source code) must contain descriptions of\n*        how the derived work is based upon and/or differs from the\n*        original Software.\n*\n*     c) The name(s) of all modified routine(s) that you distribute\n*        shall be changed.\n* \n*     d) The origin of the IERS Conventions components of your derived\n*        work must not be misrepresented; you must not claim that you\n*        wrote the original Software.\n*\n*     e) The source code must be included for all routine(s) that you\n*        distribute.  This notice must be reproduced intact in any\n*        source distribution. \n*\n*  4. In any published work produced by the user and which includes\n*     results achieved by using the Software, you shall acknowledge\n*     that the Software was used in obtaining those results.\n*\n*  5. The Software is provided to the user \"as is\" and the Center makes\n*     no warranty as to its use or performance.   The Center does not\n*     and cannot warrant the performance or results which the user may\n*     obtain by using the Software.  The Center makes no warranties,\n*     express or implied, as to non-infringement of third party rights,\n*     merchantability, or fitness for any particular purpose.  In no\n*     event will the Center be liable to the user for any consequential,\n*     incidental, or special damages, including any lost profits or lost\n*     savings, even if a Center representative has been advised of such\n*     damages, or for any claim by any third party.\n*\n*  Correspondence concerning IERS Conventions software should be\n*  addressed as follows:\n*\n*                     Gerard Petit\n*     Internet email: gpetit[at]bipm.org\n*     Postal address: IERS Conventions Center\n*                     Time, frequency and gravimetry section, BIPM\n*                     Pavillon de Breteuil\n*                     92312 Sevres  FRANCE\n*\n*     or\n*\n*                     Brian Luzum\n*     Internet email: brian.luzum[at]usno.navy.mil\n*     Postal address: IERS Conventions Center\n*                     Earth Orientation Department\n*                     3450 Massachusetts Ave, NW\n*                     Washington, DC 20392\n*\n*\n*-----------------------------------------------------------------------\n      END\n"
  },
  {
    "path": "source/external/iers/PMSDNUT2.F",
    "content": "      SUBROUTINE PMSDNUT2 (RMJD, PM)\n*+\n*  - - - - - - - - - - -\n*   P M S D N U T 2\n*  - - - - - - - - - - -\n*\n*  This routine is part of the International Earth Rotation and\n*  Reference Systems Service (IERS) Conventions software collection.\n*\n*  This subroutine evaluates the model of polar motion for\n*  a nonrigid Earth due to tidal gravitation. This polar motion\n*  is equivalent to the so-called \"subdiurnal nutation.\" The model\n*  is a sum of a first order polynomial and 25 trigonometric terms\n*  (15 long periodic and 10 quasi diurnal) with coefficients given\n*  in Table 5.1a of the IERS Conventions (2010).\n*\n*     :------------------------------------------:\n*     :                                          :\n*     :                 IMPORTANT                :\n*     :                                          :\n*     : In the present version this subroutine   :\n*     : neglects the linear trend and the long   :\n*     : periodic terms of the expansion, for the :\n*     : reasons explained in Section 5.5.1.1 of  :\n*     : the IERS Conventions (2010).             :\n*     : If the full expansion is needed, set the :\n*     : parameter iband to 0 instead of 1,       :\n*     : that is, replace the statement           :\n*     :     PARAMETER ( iband = 1 )              :\n*     : to  PARAMETER ( iband = 0 )              :            \n*     :                                          :\n*     :__________________________________________:\n*\n*  In general, Class 1, 2, and 3 models represent physical effects that\n*  act on geodetic parameters while canonical models provide lower-level\n*  representations or basic computations that are used by Class 1, 2, or\n*  3 models.\n* \n*  Status:  Class 1 model\n*\n*     Class 1 models are those recommended to be used a priori in the\n*     reduction of raw space geodetic data in order to determine\n*     geodetic parameter estimates.\n*     Class 2 models are those that eliminate an observational\n*     singularity and are purely conventional in nature.\n*     Class 3 models are those that are not required as either Class\n*     1 or 2.\n*     Canonical models are accepted as is and cannot be classified as\n*     a Class 1, 2, or 3 model.\n*\n*  Given:\n*     rmjd        d      Time expressed as modified Julian date\n*\n*  Returned:\n*     pm          d(2)      Vector of length 2 (Note 1)\n*\n*  Notes:\n*\n*  1) The polar motion coordinates (dx, dy) are expressed in\n*     microarcseconds.\n*\n*  Called:\n*     FUNDARG             Compute the angular fundamental arguments\n*\n*  Test case:\n*     given input: rmjd = 54335D0 ( August 23, 2007 ) \n*\n*     expected output: (dx) pm(1)  = 24.83144238273364834D0 microarcseconds\n*                      (dy) pm(2) = -14.09240692041837661D0 microarcseconds\n*\n*  References:\n*\n*     Petit, G. and Luzum, B. (eds.), IERS Conventions (2010),\n*     IERS Technical Note No. 36, BKG (2010)\n*\n*  Revisions:\n*  2005 March       A.Brzezinski   Original code\n*  2008 November 26 B.E.Stetzler   Initial changes to code\n*  2008 December 01 B.E.Stetzler   Provided test case\n*  2009 August   18 B.E.Stetzler   Capitalized all variables for FORTRAN\n*                                  77 compatibility\n*  2010 May      14 B.E.Stetzler   Replaced call to PMARGS to FUNDARG\n*                                  for universal fundamental argument\n*                                  subroutine\n*  2010 May      17 B.E.Stetzler   Validated test case using internally\n*                                  computed GMST and call to FUNDARG\n*                                  matched previous external call to\n*                                  PMARGS for all six parameters\n*  2010 June     23 B.E.Stetzler   Modified coefficients of the long\n*                                  and short period terms in polar \n*                                  motion and secular polar motion\n*                                  rate to coincide with Table 5.1a\n*  2011 October  13 B.E. Stetzler  Modification above yields difference\n*                                  in output between the original PMsdnut\n*                                  and PMSDNUT2.F at the 10^-2 muas level\n*                                  Test case header corrected to match\n*                                  output from PMSDNUT2.F\n*-----------------------------------------------------------------------\n\n      IMPLICIT NONE\n      DOUBLE PRECISION RMJD, PM(2)\n\n*         ----------------------------\n*           D E F I N I T I O N S\n*         ----------------------------\n*  iband  - parameter defining the range of periods for the terms which\n*           are included in computations; if equal to 1 only the quasi \n*           diurnal terms are computed, otherwise the full model\n*  iarg   - array defining for each of the 25 trigonometric terms a set\n*           of 6 integer multipliers of the fundamental angular arguments\n*  arg    - vector of the following 6 fundamental arguments used to\n*           compute the angular argument of the trigonometric functions\n*           arg(1:6) = [ GMST+pi, el, elp, f, d, om ]; this vector is\n*           evaluated by the subroutine FUNDARG which is called as an \n*           external subroutine.  Originally evaluated by the subroutine\n*           PMARGS. \n*  period - array of periods of the trigonometric terms of expansion, in\n*           mean solar days; only for a check - not used in computations\n*  xs, xc - sine and cosine coefficients of the x coordinate of the pole,\n*           in microarcseconds\n*  ys, yc - sine and cosine coefficients of the y coordinate of the pole,\n*           in microarcseconds\n*  angle  - angular argument of the trigonometric functions\n*           angle = Sum(i=1:6) iarg(i,j)*arg(i), for j=1,25\n\n      INTEGER IBAND, I, J, JSTART\n      PARAMETER ( IBAND = 1 )\n      INTEGER IARG(6,25)\n      DOUBLE PRECISION T, GMST, L, LP, F, D, OM\n      DOUBLE PRECISION ARG(6)\n      DOUBLE PRECISION PER(25), XS(25), XC(25), YS(25), YC(25)\n      DOUBLE PRECISION ANGLE, XRATE, YRATE\n\n* Set constants\n\n*  Arcseconds to radians\n      DOUBLE PRECISION DAS2R\n      PARAMETER ( DAS2R = 4.848136811095359935899141D-6 )\n\n*  Arcseconds in a full circle\n      DOUBLE PRECISION TURNAS\n      PARAMETER ( TURNAS = 1296000D0 )\n\n*  rmjd0   - modified Julian date of J2000\n*  twopi   - 2*pi\n\n      DOUBLE PRECISION RMJD0, PI, TWOPI\n      PARAMETER ( RMJD0   = 51544.5D0                )\n      PARAMETER ( PI      = 3.141592653589793238462643D0 )\n      PARAMETER ( TWOPI   = 6.283185307179586476925287D0 )\n\n*  Radians to seconds\n      DOUBLE PRECISION RAD2SEC\n      PARAMETER ( RAD2SEC = 86400D0/TWOPI            )\n\n* Coefficients of the long periodic terms in polar motion\n* Source: IERS Conventions (2010), Table 5.1a\n\n      DATA \n     . (  (IARG(I,J),I=1,6),    PER(J),   XS(J),  XC(J),  YS(J),  YC(J),\n     .                                                           J=1,15)\n     ./ 0,  0, 0,  0,  0, -1, 6798.3837,    0.0,   0.6,   -0.1,   -0.1,\n     .  0, -1, 0,  1,  0,  2, 6159.1355,    1.5,   0.0,   -0.2,    0.1,\n     .  0, -1, 0,  1,  0,  1, 3231.4956,  -28.5,  -0.2,    3.4,   -3.9,\n     .  0, -1, 0,  1,  0,  0, 2190.3501,   -4.7,  -0.1,    0.6,   -0.9,\n     .  0,  1, 1, -1,  0,  0, 438.35990,   -0.7,   0.2,   -0.2,   -0.7,\n     .  0,  1, 1, -1,  0, -1, 411.80661,    1.0,   0.3,   -0.3,    1.0,\n     .  0,  0, 0,  1, -1,  1, 365.24219,    1.2,   0.2,   -0.2,    1.4,\n     .  0,  1, 0,  1, -2,  1, 193.55971,    1.3,   0.4,   -0.2,    2.9,\n     .  0,  0, 0,  1,  0,  2, 27.431826,   -0.1,  -0.2,    0.0,   -1.7,\n     .  0,  0, 0,  1,  0,  1, 27.321582,    0.9,   4.0,   -0.1,   32.4,\n     .  0,  0, 0,  1,  0,  0, 27.212221,    0.1,   0.6,    0.0,    5.1,\n     .  0, -1, 0,  1,  2,  1, 14.698136,    0.0,   0.1,    0.0,    0.6,\n     .  0,  1, 0,  1,  0,  1, 13.718786,   -0.1,   0.3,    0.0,    2.7,\n     .  0,  0, 0,  3,  0,  3, 9.1071941,   -0.1,   0.1,    0.0,    0.9,\n     .  0,  0, 0,  3,  0,  2, 9.0950103,   -0.1,   0.1,    0.0,    0.6/\n\n* Coefficients of the quasi diurnal terms in polar motion\n* Source: IERS Conventions (2010), Table 5.1a\n\n      DATA \n     .(  (IARG(I,J),i=1,6),     PER(J),   XS(J),  XC(J),  YS(J),  YC(J),\n     .                                                          J=16,25)\n     ./ 1, -1, 0, -2,  0, -1, 1.1196992,   -0.4,   0.3,   -0.3,   -0.4,\n     .  1, -1, 0, -2,  0, -2, 1.1195149,   -2.3,   1.3,   -1.3,   -2.3,\n     .  1,  1, 0, -2, -2, -2, 1.1134606,   -0.4,   0.3,   -0.3,   -0.4,\n     .  1,  0, 0, -2,  0, -1, 1.0759762,   -2.1,   1.2,   -1.2,   -2.1,\n     .  1,  0, 0, -2,  0, -2, 1.0758059,  -11.4,   6.5,   -6.5,  -11.4,\n     .  1, -1, 0,  0,  0,  0, 1.0347187,    0.8,  -0.5,    0.5,    0.8,\n     .  1,  0, 0, -2,  2, -2, 1.0027454,   -4.8,   2.7,   -2.7,   -4.8,\n     .  1,  0, 0,  0,  0,  0, 0.9972696,   14.3,  -8.2,    8.2,   14.3,\n     .  1,  0, 0,  0,  0, -1, 0.9971233,    1.9,  -1.1,    1.1,    1.9,\n     .  1,  1, 0,  0,  0,  0, 0.9624365,    0.8,  -0.4,    0.4,    0.8/\n\n* Rate of secular polar motion, in microarcseconds per year\n* Source: IERS Conventions (2010), Table 5.1a\n\n      DATA XRATE, YRATE / -3.8, -4.3/\n\n* Compute the periodical part of the model\n* Coordinates of the pole are set to zero first\n      PM(1) = 0D0\n      PM(2) = 0D0\n\n* Evaluate the vector of the fundamental arguments\n* arg(1:6) = [ GMST+pi, el, elp, f, d, om ] at t = rmjd\n\n*  Convert the input epoch to Julian centuries of TDB since J2000\n      T = (RMJD-RMJD0)/36525D0\n\n*  Compute GMST + pi\n      GMST = MOD (   67310.54841D0 +\n     .               T*( (8640184.812866D0 + 3155760000D0) +\n     .               T*( 0.093104D0 +\n     .               T*( -0.0000062 ))), 86400D0 )\n\n      CALL FUNDARG ( T, L, LP, F, D, OM )\n\n      ARG(1) = GMST / RAD2SEC + PI\n      ARG(1) = DMOD( ARG(1), TWOPI )\n      ARG(2) = L\n      ARG(3) = LP\n      ARG(4) = F\n      ARG(5) = D\n      ARG(6) = OM \n\n      IF (IBAND.EQ.1) THEN\n        JSTART = 16\n      ELSE\n        JSTART = 1\n      ENDIF\n      DO 20 J=JSTART,25\n\n* For the j-th term of the trigonometric expansion, compute the angular\n* argument angle of sine and cosine functions as a linear integer\n* combination of the 6 fundamental arguments\n        ANGLE = 0D0\n        DO 10 I=1,6\n          ANGLE = ANGLE + IARG(I,J) * ARG(I)\n   10   CONTINUE\n        ANGLE = DMOD( ANGLE, TWOPI )\n\n\n* Compute contribution from the j-th term to the polar motion coordinates\n        PM(1) = PM(1) + XS(J)*DSIN(ANGLE) + XC(J)*DCOS(ANGLE)\n        PM(2) = PM(2) + YS(J)*DSIN(ANGLE) + YC(J)*DCOS(ANGLE)\n   20 CONTINUE\n      IF (IBAND.EQ.1) RETURN\n\n* Add the secular term of the model\n      PM(1) = PM(1) + XRATE * (RMJD-RMJD0) / 365.25D0\n      PM(2) = PM(2) + YRATE * (RMJD-RMJD0) / 365.25D0\n\n      RETURN\n\n*  Finished.\n\n*+----------------------------------------------------------------------\n*\n*  Copyright (C) 2008\n*  IERS Conventions Center\n*\n*  ==================================\n*  IERS Conventions Software License\n*  ==================================\n*\n*  NOTICE TO USER:\n*\n*  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING TERMS AND CONDITIONS\n*  WHICH APPLY TO ITS USE.\n*\n*  1. The Software is provided by the IERS Conventions Center (\"the\n*     Center\").\n*\n*  2. Permission is granted to anyone to use the Software for any\n*     purpose, including commercial applications, free of charge,\n*     subject to the conditions and restrictions listed below.\n*\n*  3. You (the user) may adapt the Software and its algorithms for your\n*     own purposes and you may distribute the resulting \"derived work\"\n*     to others, provided that the derived work complies with the\n*     following requirements:\n*\n*     a) Your work shall be clearly identified so that it cannot be\n*        mistaken for IERS Conventions software and that it has been\n*        neither distributed by nor endorsed by the Center.\n*\n*     b) Your work (including source code) must contain descriptions of\n*        how the derived work is based upon and/or differs from the\n*        original Software.\n*\n*     c) The name(s) of all modified routine(s) that you distribute\n*        shall be changed.\n* \n*     d) The origin of the IERS Conventions components of your derived\n*        work must not be misrepresented; you must not claim that you\n*        wrote the original Software.\n*\n*     e) The source code must be included for all routine(s) that you\n*        distribute.  This notice must be reproduced intact in any\n*        source distribution. \n*\n*  4. In any published work produced by the user and which includes\n*     results achieved by using the Software, you shall acknowledge\n*     that the Software was used in obtaining those results.\n*\n*  5. The Software is provided to the user \"as is\" and the Center makes\n*     no warranty as to its use or performance.   The Center does not\n*     and cannot warrant the performance or results which the user may\n*     obtain by using the Software.  The Center makes no warranties,\n*     express or implied, as to non-infringement of third party rights,\n*     merchantability, or fitness for any particular purpose.  In no\n*     event will the Center be liable to the user for any consequential,\n*     incidental, or special damages, including any lost profits or lost\n*     savings, even if a Center representative has been advised of such\n*     damages, or for any claim by any third party.\n*\n*  Correspondence concerning IERS Conventions software should be\n*  addressed as follows:\n*\n*                     Gerard Petit\n*     Internet email: gpetit[at]bipm.org\n*     Postal address: IERS Conventions Center\n*                     Time, frequency and gravimetry section, BIPM\n*                     Pavillon de Breteuil\n*                     92312 Sevres  FRANCE\n*\n*     or\n*\n*                     Brian Luzum\n*     Internet email: brian.luzum[at]usno.navy.mil\n*     Postal address: IERS Conventions Center\n*                     Earth Orientation Department\n*                     3450 Massachusetts Ave, NW\n*                     Washington, DC 20392\n*\n*\n*-----------------------------------------------------------------------\n      END\n"
  },
  {
    "path": "source/external/iers/UTLIBR.F",
    "content": "      SUBROUTINE UTLIBR (RMJD, DUT1, DLOD)\n*+\n*  - - - - - - - - \n*   U T L I B R\n*  - - - - - - - -\n*\n*  This routine is part of the International Earth Rotation and\n*  Reference Systems Service (IERS) Conventions software collection.\n*\n*  This subroutine evaluates the model of subdiurnal libration\n*  in the axial component of rotation, expressed by UT1 and LOD.\n*  This effect is due to the influence of tidal gravitation on the\n*  departures of the Earth's mass distribution from the rotational\n*  symmetry, expressed by the non-zonal components of geopotential.\n*  The amplitudes have been computed for an elastic Earth with liquid\n*  core. The adopted truncation level is 0.033 microseconds in UT1\n*  corresponding to the angular displacement of 0.5 microarcseconds\n*  or to 0.015 mm at the planet surface. With this truncation level\n*  the model contains 11 semidiurnal terms. The coefficients of\n*  the model are given in Table 5.1b of the IERS Conventions (2010).\n*\n*  In general, Class 1, 2, and 3 models represent physical effects that\n*  act on geodetic parameters while canonical models provide lower-level\n*  representations or basic computations that are used by Class 1, 2, or\n*  3 models.\n* \n*  Status:  Class 3 model\n*\n*     Class 1 models are those recommended to be used a priori in the\n*     reduction of raw space geodetic data in order to determine\n*     geodetic parameter estimates.\n*     Class 2 models are those that eliminate an observational\n*     singularity and are purely conventional in nature.\n*     Class 3 models are those that are not required as either Class\n*     1 or 2.\n*     Canonical models are accepted as is and cannot be classified as\n*     a Class 1, 2, or 3 model.\n*\n*  Given:\n*     rmjd        d      Time expressed as modified Julian date\n*\n*  Returned:\n*     dUT1        d      Incremental UT1 in microseconds\n*     dLOD        d      Incremental LOD in microseconds per day\n*\n*  Notes:\n*  1) The procedure FUNDARG.F is the same as used by the program PMSDNUT2.F\n*     which implements the corresponding model of the lunisolar libration in\n*     polar motion.\n*\n*  Called:\n*     FUNDARG             Compute the angular fundamental arguments\n*\n*  Test cases:\n*     given input:  rmjd_a = 44239.1 ( January 1, 1980 2:24.00 )\n*                   rmjd_b = 55227.4 ( January 31, 2010 9:35.59 )\n*\n*     expected output: dUT1_a =   2.441143834386761746D0 mus;\n*                      dLOD_a = -14.78971247349449492D0 mus / day\n*                      dUT1_b = - 2.655705844335680244D0 mus;\n*                      dLOD_b =  27.39445826599846967D0 mus / day\n*\n*  References:\n*\n*     Petit, G. and Luzum, B. (eds.), IERS Conventions (2010),\n*     IERS Technical Note No. 36, BKG (2010)\n*\n*  Revisions:\n*  2010 May       A.Brzezinski   Original code\n*  2010 June  1   B.E.Stetzler   Initial changes to code\n*  2010 June  2   B.E.Stetzler   Provided test case\n*  2010 June  2   B.E.Stetzler   Capitalized all variables for FORTRAN\n*                                77 compatibility\n*  2010 June  2   B.E.Stetzler   Replaced call to PMARGS to FUNDARG\n*                                for universal fundamental argument\n*                                subroutine\n*  2010 June  2   B.E.Stetzler   Validated test case using internally\n*                                computed GMST and call to FUNDARG\n*                                matched previous external call to\n*                                PMARGS for all six parameters\n*  2010 June  23  B.E.Stetzler   Modified coefficients of semi-diurnal\n*                                variations in UT1 and LOD due to\n*                                libration for a non-rigid Earth to\n*                                coincide with Table 5.1b\n*-----------------------------------------------------------------------\n\n      IMPLICIT NONE\n      DOUBLE PRECISION RMJD, DUT1, DLOD\n\n*         ----------------------------\n*           D E F I N I T I O N S\n*         ----------------------------\n*  iarg   - array defining for each of the 11 trigonometric terms a set\n*           of 6 integer multipliers of the fundamental angular arguments\n*  arg    - vector of the following 6 fundamental arguments used to\n*           compute the angular argument of the trigonometric functions\n*           arg(1:6) = [ GMST+pi, el, elp, f, d, om ]; this vector is\n*           evaluated by the subroutine FUNDARG which is called as an \n*           external subroutine.  Originally evaluated by the subroutine\n*           PMARGS. \n*  period - array of periods of the trigonometric terms of expansion, in\n*           mean solar days; only for a check - not used in computations\n*  dUT1s, dUT1c - sine and cosine coefficients of dUT1, in microseconds\n*  dLODs, dLODc - sine and cosine coefficients of dLOD, in microseconds\n*                 per day\n*  angle  - angular argument of the trigonometric functions\n*           angle = Sum(i=1:6) iarg(i,j)*arg(i), for j=1,11\n\n      INTEGER I, J\n      INTEGER IARG(6,11)\n      DOUBLE PRECISION T, GMST, L, LP, F, D, OM\n      DOUBLE PRECISION ARG(6)\n      DOUBLE PRECISION PER(11), DUT1S(11), DUT1C(11), DLODS(11),\n     .                 DLODC(11) \n      DOUBLE PRECISION ANGLE\n\n* Set constants\n\n*  Arcseconds to radians\n      DOUBLE PRECISION DAS2R\n      PARAMETER ( DAS2R = 4.848136811095359935899141D-6 )\n\n*  Arcseconds in a full circle\n      DOUBLE PRECISION TURNAS\n      PARAMETER ( TURNAS = 1296000D0 )\n\n*  rmjd0   - modified Julian date of J2000\n*  twopi   - 2*pi\n\n      DOUBLE PRECISION RMJD0, PI, TWOPI\n      PARAMETER ( RMJD0   = 51544.5D0                )\n      PARAMETER ( PI      = 3.141592653589793238462643D0 )\n      PARAMETER ( TWOPI   = 6.283185307179586476925287D0 )\n\n*  Radians to seconds\n      DOUBLE PRECISION RAD2SEC\n      PARAMETER ( RAD2SEC = 86400D0/TWOPI            )\n\n* Coefficients of the quasi semidiurnal terms in dUT1, dLOD \n* Source: IERS Conventions (2010), Table 5.1b\n\n      DATA \n     .((IARG(I,J),I=1,6), PER(J), DUT1S(J),DUT1C(J), DLODS(J), DLODC(J),\n     .                                                           J=1,11)\n     ./2, -2,  0, -2,  0, -2, 0.5377239,  0.05, -0.03,  -0.3,  -0.6,\n     . 2,  0,  0, -2, -2, -2, 0.5363232,  0.06, -0.03,  -0.4,  -0.7,\n     . 2, -1,  0, -2,  0, -2, 0.5274312,  0.35, -0.20,  -2.4,  -4.1,\n     . 2,  1,  0, -2, -2, -2, 0.5260835,  0.07, -0.04,  -0.5,  -0.8,\n     . 2,  0,  0, -2,  0, -1, 0.5175645, -0.07,  0.04,   0.5,   0.8,\n     . 2,  0,  0, -2,  0, -2, 0.5175251,  1.75, -1.01, -12.2, -21.3,\n     . 2,  1,  0, -2,  0, -2, 0.5079842, -0.05,  0.03,   0.3,   0.6,\n     . 2,  0, -1, -2,  2, -2, 0.5006854,  0.04, -0.03,  -0.3,  -0.6,\n     . 2,  0,  0, -2,  2, -2, 0.5000000,  0.76, -0.44,  -5.5,  -9.6,\n     . 2,  0,  0,  0,  0,  0, 0.4986348,  0.21, -0.12,  -1.5,  -2.6,\n     . 2,  0,  0,  0,  0, -1, 0.4985982,  0.06, -0.04,  -0.4,  -0.8/\n\n* Compute the harmonic model of dUT1 and dLOD \n* dUT1 and dLOD are set to zero first \n      DUT1 = 0D0\n      DLOD = 0D0\n\n* Evaluate the vector of the fundamental arguments\n* arg(1:6) = [ GMST+pi, el, elp, f, d, om ] at t = rmjd\n\n*  Convert the input epoch to Julian centuries of TDB since J2000\n      T = (RMJD-RMJD0)/36525D0\n\n*  Compute GMST + pi\n      GMST = MOD (   67310.54841D0 +\n     .               T*( (8640184.812866D0 + 3155760000D0) +\n     .               T*( 0.093104D0 +\n     .               T*( -0.0000062 ))), 86400D0 )\n\n      CALL FUNDARG ( T, L, LP, F, D, OM )\n\n      ARG(1) = GMST / RAD2SEC + PI\n      ARG(1) = DMOD( ARG(1), TWOPI )\n      ARG(2) = L\n      ARG(3) = LP\n      ARG(4) = F\n      ARG(5) = D\n      ARG(6) = OM \n\n      DO 20 J=1,11\n\n* For the j-th term of the trigonometric expansion, compute the angular\n* argument angle of sine and cosine functions as a linear integer\n* combination of the 6 fundamental arguments\n        ANGLE = 0D0\n        DO 10 I=1,6\n          ANGLE = ANGLE + IARG(I,J) * ARG(I)\n   10   CONTINUE\n        ANGLE = DMOD( ANGLE, TWOPI )\n\n* Compute contribution from the j-th term of expansion to dUT1 and dLOD \n        DUT1 = DUT1 + DUT1S(J)*DSIN(ANGLE) + DUT1C(J)*DCOS(ANGLE)\n        DLOD = DLOD + DLODS(J)*DSIN(ANGLE) + DLODC(J)*DCOS(ANGLE)\n   20 CONTINUE\n      RETURN\n\n*  Finished.\n\n*+----------------------------------------------------------------------\n*\n*  Copyright (C) 2008\n*  IERS Conventions Center\n*\n*  ==================================\n*  IERS Conventions Software License\n*  ==================================\n*\n*  NOTICE TO USER:\n*\n*  BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING TERMS AND CONDITIONS\n*  WHICH APPLY TO ITS USE.\n*\n*  1. The Software is provided by the IERS Conventions Center (\"the\n*     Center\").\n*\n*  2. Permission is granted to anyone to use the Software for any\n*     purpose, including commercial applications, free of charge,\n*     subject to the conditions and restrictions listed below.\n*\n*  3. You (the user) may adapt the Software and its algorithms for your\n*     own purposes and you may distribute the resulting \"derived work\"\n*     to others, provided that the derived work complies with the\n*     following requirements:\n*\n*     a) Your work shall be clearly identified so that it cannot be\n*        mistaken for IERS Conventions software and that it has been\n*        neither distributed by nor endorsed by the Center.\n*\n*     b) Your work (including source code) must contain descriptions of\n*        how the derived work is based upon and/or differs from the\n*        original Software.\n*\n*     c) The name(s) of all modified routine(s) that you distribute\n*        shall be changed.\n* \n*     d) The origin of the IERS Conventions components of your derived\n*        work must not be misrepresented; you must not claim that you\n*        wrote the original Software.\n*\n*     e) The source code must be included for all routine(s) that you\n*        distribute.  This notice must be reproduced intact in any\n*        source distribution. \n*\n*  4. In any published work produced by the user and which includes\n*     results achieved by using the Software, you shall acknowledge\n*     that the Software was used in obtaining those results.\n*\n*  5. The Software is provided to the user \"as is\" and the Center makes\n*     no warranty as to its use or performance.   The Center does not\n*     and cannot warrant the performance or results which the user may\n*     obtain by using the Software.  The Center makes no warranties,\n*     express or implied, as to non-infringement of third party rights,\n*     merchantability, or fitness for any particular purpose.  In no\n*     event will the Center be liable to the user for any consequential,\n*     incidental, or special damages, including any lost profits or lost\n*     savings, even if a Center representative has been advised of such\n*     damages, or for any claim by any third party.\n*\n*  Correspondence concerning IERS Conventions software should be\n*  addressed as follows:\n*\n*                     Gerard Petit\n*     Internet email: gpetit[at]bipm.org\n*     Postal address: IERS Conventions Center\n*                     Time, frequency and gravimetry section, BIPM\n*                     Pavillon de Breteuil\n*                     92312 Sevres  FRANCE\n*\n*     or\n*\n*                     Brian Luzum\n*     Internet email: brian.luzum[at]usno.navy.mil\n*     Postal address: IERS Conventions Center\n*                     Earth Orientation Department\n*                     3450 Massachusetts Ave, NW\n*                     Washington, DC 20392\n*\n*\n*-----------------------------------------------------------------------\n      END\n"
  },
  {
    "path": "source/external/iers/iers.h",
    "content": "/***********************************************/\n/**\n* @file iers.h\n*\n* @brief Fortran Wrapper.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-04-26\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_IERS__\n#define __GROOPS_IERS__\n\n#include \"external/fortran.h\"\n\n#define ray       FORTRANCALL(ray,       RAY)\n#define ortho_eop FORTRANCALL(ortho_eop, ORTHO_EOP)\n#define pmsdnut   FORTRANCALL(pmsdnut,   PMSDNUT)\n#define pmsdnut2  FORTRANCALL(pmsdnut2,  PMSDNUT2)\n#define utlibr    FORTRANCALL(utlibr,    UTLIBR)\n\nextern \"C\" void ray(const F77Double &mjd, F77Double &corx, F77Double &cory, F77Double &cort);\nextern \"C\" void ortho_eop(const F77Double &mjd, F77Double dxdydt[]);\nextern \"C\" void pmsdnut(const F77Double &mjd, F77Double dxdy[]);\nextern \"C\" void pmsdnut2(const F77Double &mjd, F77Double dxdy[]);\nextern \"C\" void utlibr(const F77Double &mjd, F77Double &dut1, F77Double &dlod);\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/external/iers/pmsdnut.f",
    "content": "      subroutine PMsdnut (rmjd, pm)\nc\nc*******************************************************************\nc   Fortran subroutine to evaluate the model of polar motion for\nc   a nonrigid Earth due to tidal gravitation. This polar motion\nc   is equivalent to the so-called \"subdiurnal nutation\". The model\nc   is a sum of a first order polynomial and 25 trigonometric terms\nc   (15 long periodic and 10 quasi diurnal) with coefficients given\nc   in Table 5.1 of the IERS Conventions (2003).\nc\nc********IMPORTANT*********\nc   In the present version this subroutine neglects the linear trend\nc   and the long periodic terms of the expansion, for the reasons\nc   explained in Section 5.4.2 of the IERS Conventions (2003), last\nc   paragraph before Table 5.1. If the full expansion is needed set\nc   the parameter iband to 0 instead of 1, that is replace the statement\nc      parameter ( iband = 1 )\nc   below by\nc      parameter ( iband = 0 )\nc*************************\nc\nc   Written by Aleksander Brzezinski,\nc              Space Research Centre PAS, Warsaw, March 2005\nc\nc INPUT:\nc   rmjd    r*8  time expressed as modified Julian date\nc\nc OUTPUT:\nc   pm      r*8  vector of length 2 with the incremental polar motion\nc                coordinates (dx,dy) expressed in microarcseconds\nc\nc  External calls: PMargs\nc*******************************************************************\nc\nc Declarations\n      real*8 rmjd, pm(2)\nc\nc  iband  - parameter defining the range of periods for the terms which\nc           are included in comutations; if equal to 1 only the quasi\nc           diurnal terms are computed, otherwise the full model\n      integer iband\n      parameter ( iband = 1 )\nc\nc  iarg   - array defining for each of the 25 trigonometric terms a set\nc           of 6 integer multipliers of the fundamental angular arguments\nc  arg    - vector of the following 6 fundamental arguments used to\nc           compute the angular argument of the trigonometric functions\nc           arg(1:6) = [ GMST+pi, el, elp, f, d, om ]; this vector is\nc           evaluated by the subroutine PMargs which is enclosed below\nc  period - array of periods of the trigonometric terms of expansion, in\nc           mean solar days; only for a check - not used in computations\nc  xs, xc - sine and cosine coefficients of the x coordinate of the pole,\nc           in microarcseconds\nc  ys, yc - sine and cosine coefficients of the y coordinate of the pole,\nc           in microarcseconds\nc  angle  - angular argument of the trigonometric functions\nc           angle = Sum(i=1:6) iarg(i,j)*arg(i), for j=1,25\nc\n      integer iarg(6,25)\n      real*8 arg(6)\n      real*8 per(25), xs(25), xc(25), ys(25), yc(25)\n      real*8 angle\nc\nc Set constants\nc\nc  rmjd0   - modified Julian date of J2000\nc  twopi   - 2*pi\nc\n      real*8 rmjd0, twopi\n      parameter ( rmjd0   = 51544.5d0                )\n      parameter ( twopi   = 6.28318530717958647692d0 )\nc\nc Coefficients of the long periodic terms in polar motion\nc Source: IERS Conventions 2003, Table 5.1\nc\n      data\n     * (  (iarg(i,j),i=1,6),    per(j),   xs(j),  xc(j),  ys(j),  yc(j),\n     *                                                           j=1,15)\n     */ 0,  0, 0,  0,  0, -1, 6798.3837,  -0.03,   0.63,  -0.05,  -0.55,\n     *  0, -1, 0,  1,  0,  2, 6159.1355,   1.46,   0.00,  -0.18,   0.11,\n     *  0, -1, 0,  1,  0,  1, 3231.4956, -28.53,  -0.23,   3.42,  -3.86,\n     *  0, -1, 0,  1,  0,  0, 2190.3501,  -4.65,  -0.08,   0.55,  -0.92,\n     *  0,  1, 1, -1,  0,  0, 438.35990,  -0.69,   0.15,  -0.15,  -0.68,\n     *  0,  1, 1, -1,  0, -1, 411.80661,   0.99,   0.26,  -0.25,   1.04,\n     *  0,  0, 0,  1, -1,  1, 365.24219,   1.19,   0.21,  -0.19,   1.40,\n     *  0,  1, 0,  1, -2,  1, 193.55971,   1.30,   0.37,  -0.17,   2.91,\n     *  0,  0, 0,  1,  0,  2, 27.431826,  -0.05,  -0.21,   0.01,  -1.68,\n     *  0,  0, 0,  1,  0,  1, 27.321582,   0.89,   3.97,  -0.11,  32.39,\n     *  0,  0, 0,  1,  0,  0, 27.212221,   0.14,   0.62,  -0.02,   5.09,\n     *  0, -1, 0,  1,  2,  1, 14.698136,  -0.02,   0.07,   0.00,   0.56,\n     *  0,  1, 0,  1,  0,  1, 13.718786,  -0.11,   0.33,   0.01,   2.66,\n     *  0,  0, 0,  3,  0,  3, 9.1071941,  -0.08,   0.11,   0.01,   0.88,\n     *  0,  0, 0,  3,  0,  2, 9.0950103,  -0.05,   0.07,   0.01,   0.55/\nc\nc Coefficients of the quasi diurnal terms in polar motion\nc Source: IERS Conventions 2003, Table 5.1\nc\n      data\n     *(  (iarg(i,j),i=1,6),     per(j),   xs(j),  xc(j),  ys(j),  yc(j),\n     *                                                          j=16,25)\n     */ 1, -1, 0, -2,  0, -1, 1.1196992,  -0.44,   0.25,  -0.25,  -0.44,\n     *  1, -1, 0, -2,  0, -2, 1.1195149,  -2.31,   1.32,  -1.32,  -2.31,\n     *  1,  1, 0, -2, -2, -2, 1.1134606,  -0.44,   0.25,  -0.25,  -0.44,\n     *  1,  0, 0, -2,  0, -1, 1.0759762,  -2.14,   1.23,  -1.23,  -2.14,\n     *  1,  0, 0, -2,  0, -2, 1.0758059, -11.36,   6.52,  -6.52, -11.36,\n     *  1, -1, 0,  0,  0,  0, 1.0347187,   0.84,  -0.48,   0.48,   0.84,\n     *  1,  0, 0, -2,  2, -2, 1.0027454,  -4.76,   2.73,  -2.73,  -4.76,\n     *  1,  0, 0,  0,  0,  0, 0.9972696,  14.27,  -8.19,   8.19,  14.27,\n     *  1,  0, 0,  0,  0, -1, 0.9971233,   1.93,  -1.11,   1.11,   1.93,\n     *  1,  1, 0,  0,  0,  0, 0.9624365,   0.76,  -0.43,   0.43,   0.76/\nc\nc Rate of secular polar motion, in microarcseconds per year\nc Source: IERS Conventions 2003, Table 5.1\nc\n      data xrate, yrate / -3.80, -4.31/\nc\nc Compute the periodical part of the model\nc Coordinates of the pole are set to zero first\n      pm(1) = 0.d0\n      pm(2) = 0.d0\nc\nc Evaluate the vector of the fundamental arguments\nc arg(1:6) = [ GMST+pi, el, elp, f, d, om ] at t = rmjd\n      call PMargs (rmjd,arg)\nc\n      if (iband.eq.1) then\n        jstart = 16\n      else\n        jstart = 1\n      endif\n      do 20 j=jstart,25\nc For the j-th term of the trigonometric expansion, compute the angular\nc argument angle of sine and cosine functions as a linear integer\nc combination of the 6 fundamental arguments\n        angle = 0.d0\n        do 10 i=1,6\n          angle = angle + iarg(i,j) * arg(i)\n   10   continue\n        angle = dmod( angle, twopi)\nc\nc Compute contribution from the j-th term to the polar motion coordinates\n        pm(1) = pm(1) + xs(j)*dsin(angle) + xc(j)*dcos(angle)\n        pm(2) = pm(2) + ys(j)*dsin(angle) + yc(j)*dcos(angle)\n   20 continue\n      if (iband.eq.1) return\nc\nc Add the secular term of the model\n      pm(1) = pm(1) + xrate * (rmjd-rmjd0) / 365.25d0\n      pm(2) = pm(2) + yrate * (rmjd-rmjd0) / 365.25d0\nc\n      return\n      end\nc\nc\nc\n      subroutine PMargs (rmjd, pmarg)\nc\nc*******************************************************************\nc   Fortran subroutine to compute the angular arguments used in\nc   the trigonometric expansion of the model of polar motion for\nc   a nonrigid Earth due to tidal gravitation, as describe by\nc   Table 5.1 of the IERS Conventions (2003).\nc\nc   Written by Aleksander Brzezinski,\nc              Space Research Centre PAS, Warsaw, March 2005\nc\nc INPUT:\nc   rmjd    r*8  time expressed as modified Julian date\nc\nc OUTPUT:\nc   pmarg   r*8  vector of length 6 with the following angular arguments\nc                expressed in radians:\nc   1.           GMST (Greenwich mean sidereal time) + pi\nc   2.           el  - mean anomaly of the Moon\nc   3.           elp - mean anomaly of the Sun\nc   4.           f   - L minus om, where L is the mean longitude\nc                      of the Moon and om is defined below\nc   5.           d   - mean elongation of the Moon from the Sun\nc   6.           om  - mean longitude of the ascending node of the Moon\nc\nc  There is no external calls in this subroutine\nc*******************************************************************\nc\nc Declarations\n      real*8 rmjd, pmarg(6), GMST, el, elp, f, d, om\nc\nc  GMSTc, elc, elpc, fc, dc, omc - vectors of length 5 containing\nc                        coefficients of the polynomial expansion\nc                        of GMST, el, elp, f, d, om\nc  cent                - epoch in Julian centuries of TDB since J2000\nc  cent2, cent3, cent4 - powers of cent\n      real*8 GMSTc(5), elc(5), elpc(5), fc(5), dc(5), omc(5)\n      real*8 cent, cent2, cent3, cent4\nc Constants\nc\nc   pi, twopi   - pi, 2*pi\nc   rmjd0       - modified Julian date of J2000\nc   sec360      - number of arcseconds in 360 degrees\nc   rad2deg     - conversion from radians to degrees\nc   rad2sec     - conversion from radians to time seconds\nc\n      real*8 pi, twopi, rmjd0, sec360, rad2deg, rad2sec\nc\n      parameter ( pi      = 3.14159265358979323846 d0 )\n      parameter ( twopi   = 6.28318530717958647692 d0 )\n      parameter ( rmjd0   = 51544.5d0                 )\n      parameter ( sec360  = 1296000.d0                )\n      parameter ( rad2deg = 180.d0/pi                 )\n      parameter ( rad2sec = 86400.d0/twopi            )\nc\nc  Coefficients of the polynomial expansion of GMST (in seconds) and of\nc  the fundamental arguments of nutation (in arcseconds). Source:\nc  IERS Conventions (1996), Chapter 5 for GMST\nc  IERS Conventions (2003), eq.(40) for the nutation arguments\nc\n      data GMSTc  / -0.0000062d0,  0.093104d0,  8640184.812866d0,\n     *         3155760000.d0,   67310.54841d0 /\n      data elc    /    -0.00024470d0,     0.051635d0,  31.8792d0,\n     *         1717915923.2178d0,   485868.249036d0 /\n      data elpc   /    -0.00001149d0,    +0.000136d0,  -0.5532d0,\n     *          129596581.0481d0,   1287104.79305d0 /\n      data fc     /     0.00000417d0,    -0.001037d0,  -12.7512d0,\n     *         1739527262.8478d0,   335779.526232d0 /\n      data dc     /    -0.00003169d0,     0.006593d0,   -6.3706d0,\n     *         1602961601.2090d0,   1072260.70369d0 /\n      data omc    /    -0.00005939d0,     0.007702d0,    7.4722d0,\n     *           -6962890.5431d0,   450160.398036d0 /\nc\nc  Convert the input epoch to Julian centuries of TDB since J2000,\nc  and compute its powers\nc\n      cent = (rmjd-rmjd0)/36525.d0\n      cent2 = cent*cent\n      cent3 = cent2*cent\n      cent4 = cent3*cent\nc\nc  Evaluate the polynomial expansions of GMST and of\nc  the fundamental arguments of nutation\nc\n      GMST = GMSTc(1)*cent3 + GMSTc(2)*cent2\n     *      + (GMSTc(3) + GMSTc(4))*cent + GMSTc(5)\n      GMST = dmod( GMST, 86400.d0 )\nc\n      el = elc(1)*cent4 + elc(2)*cent3 + elc(3)*cent2\n     *    + elc(4)*cent + elc(5)\n      el = dmod( el, sec360 )\nc\n      elp = elpc(1)*cent4 + elpc(2)*cent3 + elpc(3)*cent2\n     *     + elpc(4)*cent + elpc(5)\n      elp = dmod( elp, sec360 )\nc\n      f = fc(1)*cent4 + fc(2)*cent3 + fc(3)*cent2\n     *   + fc(4)*cent + fc(5)\n      f = dmod( f, sec360 )\nc\n      d = dc(1)*cent4 + dc(2)*cent3 + dc(3)*cent2\n     *   + dc(4)*cent + dc(5)\n      d = dmod( d, sec360 )\nc\n      om = omc(1)*cent4 + omc(2)*cent3 + omc(3)*cent2\n     *    + omc(4)*cent + omc(5)\n      om = dmod( om, sec360 )\nc\nc  Convert the arguments to radians\nc\n      pmarg(1) = GMST / rad2sec + pi\n      pmarg(1) = dmod( pmarg(1), twopi )\n      pmarg(2) = el   / (3600.d0*rad2deg)\n      pmarg(3) = elp  / (3600.d0*rad2deg)\n      pmarg(4) = f    / (3600.d0*rad2deg)\n      pmarg(5) = d    / (3600.d0*rad2deg)\n      pmarg(6) = om   / (3600.d0*rad2deg)\nc\n      return\n      end\n\n"
  },
  {
    "path": "source/external/iers/ray.f",
    "content": "C *********************************************************************\n\n      SUBROUTINE RAY (RJD,CORX,CORY,CORT)\nC\nC   THIS SUBROUTINE IMPLEMENTS THE RAY MODEL FOR\nC   DIURNAL/SUBDIURNAL TIDES.  IT USES THE SIMON ET AL.\nC   FUNDAMENTAL ARGUMENTS.  THE CORRECTIONS IN X AND Y ARE IN\nC   UNITS OF SEC. OF ARC AND UT1-UTC IN SEC. OF TIME.  THESE\nC   CORRECTIONS SHOULD BE ADDED TO \"AVERAGE\" EOP VALUES TO GET\nC   ESTIMATES OF THE INSTANTANEOUS VALUES.\nC\nC     PARAMETERS ARE :\nC     RJD   - EPOCH OF INTEREST GIVEN IN MJD\nC     CORX  - TIDAL CORRECTION IN X (SEC. OF ARC)\nC     CORY  - TIDAL CORRECTION IN Y (SEC. OF ARC)\nC     CORT  - TIDAL CORRECTION IN UT1-UTC (SEC. OF TIME)\nC\n      IMPLICIT DOUBLE PRECISION (A-H,O-Z)\n      DOUBLE PRECISION\n     .   L,        LPRIME\n      HALFPI = 1.5707963267948966d0\n      T = (RJD - 51544.5D0)/36525.0D0\n      L = -0.00024470d0*T**4 + 0.051635d0*T**3 + 31.8792d0*T**2\n     .  + 1717915923.2178d0*T + 485868.249036d0\n      L = DMOD(L,1296000d0)\n      LPRIME = -0.00001149d0*T**4 - 0.000136d0*T**3\n     .  -  0.5532d0*T**2\n     .  + 129596581.0481d0*T + 1287104.79305d0\n      LPRIME = DMOD(LPRIME,1296000d0)\n      CAPF = 0.00000417d0*T**4 - 0.001037d0*T**3 - 12.7512d0*T**2\n     .  + 1739527262.8478d0*T + 335779.526232d0\n      CAPF = DMOD(CAPF,1296000d0)\n      CAPD = -0.00003169d0*T**4 + 0.006593d0*T**3 - 6.3706d0*T**2\n     .  + 1602961601.2090d0*T + 1072260.70369d0\n      CAPD = DMOD(CAPD,1296000d0)\n      OMEGA = -0.00005939d0*T**4 + 0.007702d0*T**3\n     .  + 7.4722d0*T**2\n     .  - 6962890.2665d0*T + 450160.398036d0\n      OMEGA = DMOD(OMEGA,1296000d0)\n      THETA = (67310.54841d0 +\n     .        (876600d0*3600d0 + 8640184.812866d0)*T +\n     .         0.093104d0*T**2 -\n     .         6.2d-6*T**3)*15.0d0 + 648000.0d0\n      ARG7 = DMOD((-L - 2.0D0*CAPF - 2.0D0*OMEGA + THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0) - HALFPI\n      ARG1 = DMOD((-2.0d0*CAPF - 2.0d0*OMEGA + THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0) - HALFPI\n      ARG2 = DMOD((-2.0d0*CAPF + 2.0d0*CAPD - 2.0d0*OMEGA\n     .       + THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0) - HALFPI\n      ARG3 = DMOD(THETA *\n     .        3.14159265D0/648000.0D0,6.28318530718D0)\n     .     + HALFPI\n      ARG4 = DMOD((-L - 2.0d0*CAPF - 2.0D0*OMEGA + 2.0d0*THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0)\n      ARG5 = DMOD((-2.0D0*CAPF - 2.0D0*OMEGA + 2.0d0*THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0)\n      ARG6 = DMOD((-2.0d0*CAPF + 2.0d0*CAPD - 2.0d0*OMEGA\n     .     + 2.0d0*THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0)\n      ARG8 = DMOD((2.0d0*THETA)\n     .     * 3.14159265D0/648000.0D0,6.28318530718D0)\n      CORX = - 0.026D0*DSIN(ARG7) + 0.006D0*DCOS(ARG7)\n     .       - 0.133D0*DSIN(ARG1) + 0.049D0*DCOS(ARG1)\n     .       - 0.050D0*DSIN(ARG2) + 0.025D0*DCOS(ARG2)\n     .       - 0.152D0*DSIN(ARG3) + 0.078D0*DCOS(ARG3)\n     .       - 0.057D0*DSIN(ARG4) - 0.013D0*DCOS(ARG4)\n     .       - 0.330D0*DSIN(ARG5) - 0.028D0*DCOS(ARG5)\n     .       - 0.145D0*DSIN(ARG6) + 0.064D0*DCOS(ARG6)\n     .       - 0.036D0*DSIN(ARG8) + 0.017D0*DCOS(ARG8)\n      CORY = - 0.006D0*DSIN(ARG7) - 0.026D0*DCOS(ARG7)\n     .       - 0.049D0*DSIN(ARG1) - 0.133D0*DCOS(ARG1)\n     .       - 0.025D0*DSIN(ARG2) - 0.050D0*DCOS(ARG2)\n     .       - 0.078D0*DSIN(ARG3) - 0.152D0*DCOS(ARG3)\n     .       + 0.011D0*DSIN(ARG4) + 0.033D0*DCOS(ARG4)\n     .       + 0.037D0*DSIN(ARG5) + 0.196D0*DCOS(ARG5)\n     .       + 0.059D0*DSIN(ARG6) + 0.087D0*DCOS(ARG6)\n     .       + 0.018D0*DSIN(ARG8) + 0.022D0*DCOS(ARG8)\n      CORT = + 0.0245D0*DSIN(ARG7) + 0.0503D0*DCOS(ARG7)\n     .       + 0.1210D0*DSIN(ARG1) + 0.1605D0*DCOS(ARG1)\n     .       + 0.0286D0*DSIN(ARG2) + 0.0516D0*DCOS(ARG2)\n     .       + 0.0864D0*DSIN(ARG3) + 0.1771D0*DCOS(ARG3)\n     .       - 0.0380D0*DSIN(ARG4) - 0.0154D0*DCOS(ARG4)\n     .       - 0.1617D0*DSIN(ARG5) - 0.0720D0*DCOS(ARG5)\n     .       - 0.0759D0*DSIN(ARG6) - 0.0004D0*DCOS(ARG6)\n     .       - 0.0196D0*DSIN(ARG8) - 0.0038D0*DCOS(ARG8)\n      CORX = CORX * 1.0d-3\n      CORY = CORY * 1.0d-3\n      CORT = CORT * 0.1d-3\n      RETURN\n      END\nC\nC *********************************************************************\nC\n"
  },
  {
    "path": "source/external/igrf/igrf.h",
    "content": "/***********************************************/\n/**\n* @file igrf.h\n*\n* @brief Fortran Wrapper.\n*\n* @author Sebastian Strasser\n* @date 2016-03-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_IGRF__\n#define __GROOPS_IGRF__\n\n#include \"external/fortran.h\"\n\n#define igrfSynthesis FORTRANCALL(igrf14syn, IGRF14SYN)\n\nextern \"C\" void igrfSynthesis(const F77Int &isv, const F77Double &date, const F77Int &itype, const F77Double &alt, const F77Double &colat, const F77Double &elong, F77Double &x, F77Double &y, F77Double &z, F77Double &f);\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/external/igrf/igrf14.f",
    "content": "C\nC     This is a program for synthesising geomagnetic field values from the\nC     International Geomagnetic Reference Field series of models as agreed\nc     in November 2024 by IAGA Working Group V-MOD.\nC     It is the 14th generation IGRF, ie the 13th revision.\nC     The main-field models for 1900.0, 1905.0,..1940.0 and 2025.0 are\nC     non-definitive, those for 1945.0, 1950.0,...2020.0 are definitive and\nC     the secular-variation model for 2025.0 to 2030.0 is non-definitive.\nC\nC     Main-field models are to degree and order 10 (ie 120 coefficients)\nC     for 1900.0-1995.0 and to 13 (ie 195 coefficients) for 2000.0 onwards.\nC     The predictive secular-variation model is to degree and order 8 (ie 80\nC     coefficients).\nC\nC     Options include values at different locations at different\nC     times (spot), values at same location at one year intervals\nC     (time series), grid of values at one time (grid); geodetic or\nC     geocentric coordinates, latitude & longitude entered as decimal\nC     degrees or degrees & minutes (not in grid), choice of main field\nC     or secular variation or both (grid only).\nC Recent history of code:\nc     Aug 2003:\nc     Adapted from 8th generation version to include new maximum degree for\nc     main-field models for 2000.0 and onwards and use WGS84 spheroid instead\nc     of International Astronomical Union 1966 spheroid as recommended by IAGA\nc     in July 2003. Reference radius remains as 6371.2 km - it is NOT the mean\nc     radius (= 6371.0 km) but 6371.2 km is what is used in determining the\nc     coefficients.\nc     Dec 2004:\nc     Adapted for 10th generation\nc     Jul 2005:\nc     1995.0 coefficients as published in igrf9coeffs.xls and igrf10coeffs.xls\nc     now used in code - (Kimmo Korhonen spotted 1 nT difference in 11 coefficients)\nc     Dec 2009:\nc     Adapted for 11th generation\nc     Dec 2014:\nc     Adapted for 12th generation\nc     Dec 2019 (W. Brown, BGS):\nc     Adapted for 13th generation\nc     Feb 2020 (W. Brown, BGS):\nc     Correction of coefficient rounding for 2020 and 2020 SV values\nc     Nov 2024 (C. Beggan, BGS)\nc\n      subroutine igrf14syn (isv,date,itype,alt,colat,elong,x,y,z,f)\nc\nc     This is a synthesis routine for the 14th generation IGRF as agreed\nc     in December 2024 by IAGA Working Group V-MOD. It is valid 1900.0 to\nc     2030.0 inclusive. Values for dates from 1945.0 to 2020.0 inclusive are\nc     definitive, otherwise they are non-definitive.\nc   INPUT\nc     isv   = 0 if main-field values are required\nc     isv   = 1 if secular variation values are required\nc     date  = year A.D. Must be greater than or equal to 1900.0 and\nc             less than or equal to 2035.0. Warning message is given\nc             for dates greater than 2030.0. Must be double precision.\nc     itype = 1 if geodetic (spheroid)\nc     itype = 2 if geocentric (sphere)\nc     alt   = height in km above sea level if itype = 1\nc           = distance from centre of Earth in km if itype = 2 (>3485 km)\nc     colat = colatitude (0-180)\nc     elong = east-longitude (0-360)\nc     alt, colat and elong must be double precision.\nc   OUTPUT\nc     x     = north component (nT) if isv = 0, nT/year if isv = 1\nc     y     = east component (nT) if isv = 0, nT/year if isv = 1\nc     z     = vertical component (nT) if isv = 0, nT/year if isv = 1\nc     f     = total intensity (nT) if isv = 0, rubbish if isv = 1\nc\nc     To get the other geomagnetic elements (D, I, H and secular\nc     variations dD, dH, dI and dF) use routines ptoc and ptocsv.\nc\nc     Adapted from 8th generation version to include new maximum degree for\nc     main-field models for 2000.0 and onwards and use WGS84 spheroid instead\nc     of International Astronomical Union 1966 spheroid as recommended by IAGA\nc     in July 2003. Reference radius remains as 6371.2 km - it is NOT the mean\nc     radius (= 6371.0 km) but 6371.2 km is what is used in determining the\nc     coefficients. Adaptation by Susan Macmillan, August 2003 (for\nc     9th generation), December 2004, December 2009 & December 2014;\nc     by William Brown, December 2019, February 2020. Updated by\nc     Ciaran Beggan, November 2024\nc\nc     Coefficients at 1995.0 incorrectly rounded (rounded up instead of\nc     to even) included as these are the coefficients published in Excel\nc     spreadsheet July 2005.\nc\n      implicit double precision (a-h,o-z)\n      dimension gh(3840),g0(120),g1(120),g2(120),g3(120),g4(120),\n     1          g5(120),g6(120),g7(120),g8(120),g9(120),ga(120),\n     2          gb(120),gc(120),gd(120),ge(120),gf(120),gg(120),\n     3          gi(120),gj(120),gk(195),gl(195),gm(195),gp(195),\n     4          gq(195),gr(195),gs(195),gt(195),\n     5          p(105),q(105),cl(13),sl(13)\n      equivalence (g0,gh(1)),(g1,gh(121)),(g2,gh(241)),(g3,gh(361)),\n     1            (g4,gh(481)),(g5,gh(601)),(g6,gh(721)),(g7,gh(841)),\n     2            (g8,gh(961)),(g9,gh(1081)),(ga,gh(1201)),\n     3            (gb,gh(1321)),(gc,gh(1441)),(gd,gh(1561)),\n     4            (ge,gh(1681)),(gf,gh(1801)),(gg,gh(1921)),\n     5            (gi,gh(2041)),(gj,gh(2161)),(gk,gh(2281)),\n     6            (gl,gh(2476)),(gm,gh(2671)),(gp,gh(2866)),\n     7            (gq,gh(3061)),(gr,gh(3256)),(gs,gh(3451)),\n     8            (gt,gh(3646))\nc\n      data g0/ -31543.,-2298., 5922., -677., 2905.,-1061.,  924., 1121., 1900\n     1           1022.,-1469., -330., 1256.,    3.,  572.,  523.,  876., 1900\n     2            628.,  195.,  660.,  -69., -361., -210.,  134.,  -75., 1900\n     3           -184.,  328., -210.,  264.,   53.,    5.,  -33.,  -86., 1900\n     4           -124.,  -16.,    3.,   63.,   61.,   -9.,  -11.,   83., 1900\n     5           -217.,    2.,  -58.,  -35.,   59.,   36.,  -90.,  -69., 1900\n     6             70.,  -55.,  -45.,    0.,  -13.,   34.,  -10.,  -41., 1900\n     7             -1.,  -21.,   28.,   18.,  -12.,    6.,  -22.,   11., 1900\n     8              8.,    8.,   -4.,  -14.,   -9.,    7.,    1.,  -13., 1900\n     9              2.,    5.,   -9.,   16.,    5.,   -5.,    8.,  -18., 1900\n     a              8.,   10.,  -20.,    1.,   14.,  -11.,    5.,   12., 1900\n     b             -3.,    1.,   -2.,   -2.,    8.,    2.,   10.,   -1., 1900\n     c             -2.,   -1.,    2.,   -3.,   -4.,    2.,    2.,    1., 1900\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1900\n     e              0.,   -2.,    2.,    4.,    2.,    0.,    0.,   -6./ 1900\n      data g1/ -31464.,-2298., 5909., -728., 2928.,-1086., 1041., 1065., 1905\n     1           1037.,-1494., -357., 1239.,   34.,  635.,  480.,  880., 1905\n     2            643.,  203.,  653.,  -77., -380., -201.,  146.,  -65., 1905\n     3           -192.,  328., -193.,  259.,   56.,   -1.,  -32.,  -93., 1905\n     4           -125.,  -26.,   11.,   62.,   60.,   -7.,  -11.,   86., 1905\n     5           -221.,    4.,  -57.,  -32.,   57.,   32.,  -92.,  -67., 1905\n     6             70.,  -54.,  -46.,    0.,  -14.,   33.,  -11.,  -41., 1905\n     7              0.,  -20.,   28.,   18.,  -12.,    6.,  -22.,   11., 1905\n     8              8.,    8.,   -4.,  -15.,   -9.,    7.,    1.,  -13., 1905\n     9              2.,    5.,   -8.,   16.,    5.,   -5.,    8.,  -18., 1905\n     a              8.,   10.,  -20.,    1.,   14.,  -11.,    5.,   12., 1905\n     b             -3.,    1.,   -2.,   -2.,    8.,    2.,   10.,    0., 1905\n     c             -2.,   -1.,    2.,   -3.,   -4.,    2.,    2.,    1., 1905\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1905\n     e              0.,   -2.,    2.,    4.,    2.,    0.,    0.,   -6./ 1905\n      data g2/ -31354.,-2297., 5898., -769., 2948.,-1128., 1176., 1000., 1910\n     1           1058.,-1524., -389., 1223.,   62.,  705.,  425.,  884., 1910\n     2            660.,  211.,  644.,  -90., -400., -189.,  160.,  -55., 1910\n     3           -201.,  327., -172.,  253.,   57.,   -9.,  -33., -102., 1910\n     4           -126.,  -38.,   21.,   62.,   58.,   -5.,  -11.,   89., 1910\n     5           -224.,    5.,  -54.,  -29.,   54.,   28.,  -95.,  -65., 1910\n     6             71.,  -54.,  -47.,    1.,  -14.,   32.,  -12.,  -40., 1910\n     7              1.,  -19.,   28.,   18.,  -13.,    6.,  -22.,   11., 1910\n     8              8.,    8.,   -4.,  -15.,   -9.,    6.,    1.,  -13., 1910\n     9              2.,    5.,   -8.,   16.,    5.,   -5.,    8.,  -18., 1910\n     a              8.,   10.,  -20.,    1.,   14.,  -11.,    5.,   12., 1910\n     b             -3.,    1.,   -2.,   -2.,    8.,    2.,   10.,    0., 1910\n     c             -2.,   -1.,    2.,   -3.,   -4.,    2.,    2.,    1., 1910\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1910\n     e              0.,   -2.,    2.,    4.,    2.,    0.,    0.,   -6./ 1910\n      data g3/ -31212.,-2306., 5875., -802., 2956.,-1191., 1309.,  917., 1915\n     1           1084.,-1559., -421., 1212.,   84.,  778.,  360.,  887., 1915\n     2            678.,  218.,  631., -109., -416., -173.,  178.,  -51., 1915\n     3           -211.,  327., -148.,  245.,   58.,  -16.,  -34., -111., 1915\n     4           -126.,  -51.,   32.,   61.,   57.,   -2.,  -10.,   93., 1915\n     5           -228.,    8.,  -51.,  -26.,   49.,   23.,  -98.,  -62., 1915\n     6             72.,  -54.,  -48.,    2.,  -14.,   31.,  -12.,  -38., 1915\n     7              2.,  -18.,   28.,   19.,  -15.,    6.,  -22.,   11., 1915\n     8              8.,    8.,   -4.,  -15.,   -9.,    6.,    2.,  -13., 1915\n     9              3.,    5.,   -8.,   16.,    6.,   -5.,    8.,  -18., 1915\n     a              8.,   10.,  -20.,    1.,   14.,  -11.,    5.,   12., 1915\n     b             -3.,    1.,   -2.,   -2.,    8.,    2.,   10.,    0., 1915\n     c             -2.,   -1.,    2.,   -3.,   -4.,    2.,    2.,    1., 1915\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1915\n     e              0.,   -2.,    1.,    4.,    2.,    0.,    0.,   -6./ 1915\n      data g4/ -31060.,-2317., 5845., -839., 2959.,-1259., 1407.,  823., 1920\n     1           1111.,-1600., -445., 1205.,  103.,  839.,  293.,  889., 1920\n     2            695.,  220.,  616., -134., -424., -153.,  199.,  -57., 1920\n     3           -221.,  326., -122.,  236.,   58.,  -23.,  -38., -119., 1920\n     4           -125.,  -62.,   43.,   61.,   55.,    0.,  -10.,   96., 1920\n     5           -233.,   11.,  -46.,  -22.,   44.,   18., -101.,  -57., 1920\n     6             73.,  -54.,  -49.,    2.,  -14.,   29.,  -13.,  -37., 1920\n     7              4.,  -16.,   28.,   19.,  -16.,    6.,  -22.,   11., 1920\n     8              7.,    8.,   -3.,  -15.,   -9.,    6.,    2.,  -14., 1920\n     9              4.,    5.,   -7.,   17.,    6.,   -5.,    8.,  -19., 1920\n     a              8.,   10.,  -20.,    1.,   14.,  -11.,    5.,   12., 1920\n     b             -3.,    1.,   -2.,   -2.,    9.,    2.,   10.,    0., 1920\n     c             -2.,   -1.,    2.,   -3.,   -4.,    2.,    2.,    1., 1920\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1920\n     e              0.,   -2.,    1.,    4.,    3.,    0.,    0.,   -6./ 1920\n      data g5/ -30926.,-2318., 5817., -893., 2969.,-1334., 1471.,  728., 1925\n     1           1140.,-1645., -462., 1202.,  119.,  881.,  229.,  891., 1925\n     2            711.,  216.,  601., -163., -426., -130.,  217.,  -70., 1925\n     3           -230.,  326.,  -96.,  226.,   58.,  -28.,  -44., -125., 1925\n     4           -122.,  -69.,   51.,   61.,   54.,    3.,   -9.,   99., 1925\n     5           -238.,   14.,  -40.,  -18.,   39.,   13., -103.,  -52., 1925\n     6             73.,  -54.,  -50.,    3.,  -14.,   27.,  -14.,  -35., 1925\n     7              5.,  -14.,   29.,   19.,  -17.,    6.,  -21.,   11., 1925\n     8              7.,    8.,   -3.,  -15.,   -9.,    6.,    2.,  -14., 1925\n     9              4.,    5.,   -7.,   17.,    7.,   -5.,    8.,  -19., 1925\n     a              8.,   10.,  -20.,    1.,   14.,  -11.,    5.,   12., 1925\n     b             -3.,    1.,   -2.,   -2.,    9.,    2.,   10.,    0., 1925\n     c             -2.,   -1.,    2.,   -3.,   -4.,    2.,    2.,    1., 1925\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1925\n     e              0.,   -2.,    1.,    4.,    3.,    0.,    0.,   -6./ 1925\n      data g6/ -30805.,-2316., 5808., -951., 2980.,-1424., 1517.,  644., 1930\n     1           1172.,-1692., -480., 1205.,  133.,  907.,  166.,  896., 1930\n     2            727.,  205.,  584., -195., -422., -109.,  234.,  -90., 1930\n     3           -237.,  327.,  -72.,  218.,   60.,  -32.,  -53., -131., 1930\n     4           -118.,  -74.,   58.,   60.,   53.,    4.,   -9.,  102., 1930\n     5           -242.,   19.,  -32.,  -16.,   32.,    8., -104.,  -46., 1930\n     6             74.,  -54.,  -51.,    4.,  -15.,   25.,  -14.,  -34., 1930\n     7              6.,  -12.,   29.,   18.,  -18.,    6.,  -20.,   11., 1930\n     8              7.,    8.,   -3.,  -15.,   -9.,    5.,    2.,  -14., 1930\n     9              5.,    5.,   -6.,   18.,    8.,   -5.,    8.,  -19., 1930\n     a              8.,   10.,  -20.,    1.,   14.,  -12.,    5.,   12., 1930\n     b             -3.,    1.,   -2.,   -2.,    9.,    3.,   10.,    0., 1930\n     c             -2.,   -2.,    2.,   -3.,   -4.,    2.,    2.,    1., 1930\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1930\n     e              0.,   -2.,    1.,    4.,    3.,    0.,    0.,   -6./ 1930\n      data g7/ -30715.,-2306., 5812.,-1018., 2984.,-1520., 1550.,  586., 1935\n     1           1206.,-1740., -494., 1215.,  146.,  918.,  101.,  903., 1935\n     2            744.,  188.,  565., -226., -415.,  -90.,  249., -114., 1935\n     3           -241.,  329.,  -51.,  211.,   64.,  -33.,  -64., -136., 1935\n     4           -115.,  -76.,   64.,   59.,   53.,    4.,   -8.,  104., 1935\n     5           -246.,   25.,  -25.,  -15.,   25.,    4., -106.,  -40., 1935\n     6             74.,  -53.,  -52.,    4.,  -17.,   23.,  -14.,  -33., 1935\n     7              7.,  -11.,   29.,   18.,  -19.,    6.,  -19.,   11., 1935\n     8              7.,    8.,   -3.,  -15.,   -9.,    5.,    1.,  -15., 1935\n     9              6.,    5.,   -6.,   18.,    8.,   -5.,    7.,  -19., 1935\n     a              8.,   10.,  -20.,    1.,   15.,  -12.,    5.,   11., 1935\n     b             -3.,    1.,   -3.,   -2.,    9.,    3.,   11.,    0., 1935\n     c             -2.,   -2.,    2.,   -3.,   -4.,    2.,    2.,    1., 1935\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1935\n     e              0.,   -1.,    2.,    4.,    3.,    0.,    0.,   -6./ 1935\n      data g8/ -30654.,-2292., 5821.,-1106., 2981.,-1614., 1566.,  528., 1940\n     1           1240.,-1790., -499., 1232.,  163.,  916.,   43.,  914., 1940\n     2            762.,  169.,  550., -252., -405.,  -72.,  265., -141., 1940\n     3           -241.,  334.,  -33.,  208.,   71.,  -33.,  -75., -141., 1940\n     4           -113.,  -76.,   69.,   57.,   54.,    4.,   -7.,  105., 1940\n     5           -249.,   33.,  -18.,  -15.,   18.,    0., -107.,  -33., 1940\n     6             74.,  -53.,  -52.,    4.,  -18.,   20.,  -14.,  -31., 1940\n     7              7.,   -9.,   29.,   17.,  -20.,    5.,  -19.,   11., 1940\n     8              7.,    8.,   -3.,  -14.,  -10.,    5.,    1.,  -15., 1940\n     9              6.,    5.,   -5.,   19.,    9.,   -5.,    7.,  -19., 1940\n     a              8.,   10.,  -21.,    1.,   15.,  -12.,    5.,   11., 1940\n     b             -3.,    1.,   -3.,   -2.,    9.,    3.,   11.,    1., 1940\n     c             -2.,   -2.,    2.,   -3.,   -4.,    2.,    2.,    1., 1940\n     d             -5.,    2.,   -2.,    6.,    6.,   -4.,    4.,    0., 1940\n     e              0.,   -1.,    2.,    4.,    3.,    0.,    0.,   -6./ 1940\n      data g9/ -30594.,-2285., 5810.,-1244., 2990.,-1702., 1578.,  477., 1945\n     1           1282.,-1834., -499., 1255.,  186.,  913.,  -11.,  944., 1945\n     2            776.,  144.,  544., -276., -421.,  -55.,  304., -178., 1945\n     3           -253.,  346.,  -12.,  194.,   95.,  -20.,  -67., -142., 1945\n     4           -119.,  -82.,   82.,   59.,   57.,    6.,    6.,  100., 1945\n     5           -246.,   16.,  -25.,   -9.,   21.,  -16., -104.,  -39., 1945\n     6             70.,  -40.,  -45.,    0.,  -18.,    0.,    2.,  -29., 1945\n     7              6.,  -10.,   28.,   15.,  -17.,   29.,  -22.,   13., 1945\n     8              7.,   12.,   -8.,  -21.,   -5.,  -12.,    9.,   -7., 1945\n     9              7.,    2.,  -10.,   18.,    7.,    3.,    2.,  -11., 1945\n     a              5.,  -21.,  -27.,    1.,   17.,  -11.,   29.,    3., 1945\n     b             -9.,   16.,    4.,   -3.,    9.,   -4.,    6.,   -3., 1945\n     c              1.,   -4.,    8.,   -3.,   11.,    5.,    1.,    1., 1945\n     d              2.,  -20.,   -5.,   -1.,   -1.,   -6.,    8.,    6., 1945\n     e             -1.,   -4.,   -3.,   -2.,    5.,    0.,   -2.,   -2./ 1945\n      data ga/ -30554.,-2250., 5815.,-1341., 2998.,-1810., 1576.,  381., 1950\n     1           1297.,-1889., -476., 1274.,  206.,  896.,  -46.,  954., 1950\n     2            792.,  136.,  528., -278., -408.,  -37.,  303., -210., 1950\n     3           -240.,  349.,    3.,  211.,  103.,  -20.,  -87., -147., 1950\n     4           -122.,  -76.,   80.,   54.,   57.,   -1.,    4.,   99., 1950\n     5           -247.,   33.,  -16.,  -12.,   12.,  -12., -105.,  -30., 1950\n     6             65.,  -55.,  -35.,    2.,  -17.,    1.,    0.,  -40., 1950\n     7             10.,   -7.,   36.,    5.,  -18.,   19.,  -16.,   22., 1950\n     8             15.,    5.,   -4.,  -22.,   -1.,    0.,   11.,  -21., 1950\n     9             15.,   -8.,  -13.,   17.,    5.,   -4.,   -1.,  -17., 1950\n     a              3.,   -7.,  -24.,   -1.,   19.,  -25.,   12.,   10., 1950\n     b              2.,    5.,    2.,   -5.,    8.,   -2.,    8.,    3., 1950\n     c            -11.,    8.,   -7.,   -8.,    4.,   13.,   -1.,   -2., 1950\n     d             13.,  -10.,   -4.,    2.,    4.,   -3.,   12.,    6., 1950\n     e              3.,   -3.,    2.,    6.,   10.,   11.,    3.,    8./ 1950\n      data gb/ -30500.,-2215., 5820.,-1440., 3003.,-1898., 1581.,  291., 1955\n     1           1302.,-1944., -462., 1288.,  216.,  882.,  -83.,  958., 1955\n     2            796.,  133.,  510., -274., -397.,  -23.,  290., -230., 1955\n     3           -229.,  360.,   15.,  230.,  110.,  -23.,  -98., -152., 1955\n     4           -121.,  -69.,   78.,   47.,   57.,   -9.,    3.,   96., 1955\n     5           -247.,   48.,   -8.,  -16.,    7.,  -12., -107.,  -24., 1955\n     6             65.,  -56.,  -50.,    2.,  -24.,   10.,   -4.,  -32., 1955\n     7              8.,  -11.,   28.,    9.,  -20.,   18.,  -18.,   11., 1955\n     8              9.,   10.,   -6.,  -15.,  -14.,    5.,    6.,  -23., 1955\n     9             10.,    3.,   -7.,   23.,    6.,   -4.,    9.,  -13., 1955\n     a              4.,    9.,  -11.,   -4.,   12.,   -5.,    7.,    2., 1955\n     b              6.,    4.,   -2.,    1.,   10.,    2.,    7.,    2., 1955\n     c             -6.,    5.,    5.,   -3.,   -5.,   -4.,   -1.,    0., 1955\n     d              2.,   -8.,   -3.,   -2.,    7.,   -4.,    4.,    1., 1955\n     e             -2.,   -3.,    6.,    7.,   -2.,   -1.,    0.,   -3./ 1955\n      data gc/ -30421.,-2169., 5791.,-1555., 3002.,-1967., 1590.,  206., 1960\n     1           1302.,-1992., -414., 1289.,  224.,  878., -130.,  957., 1960\n     2            800.,  135.,  504., -278., -394.,    3.,  269., -255., 1960\n     3           -222.,  362.,   16.,  242.,  125.,  -26., -117., -156., 1960\n     4           -114.,  -63.,   81.,   46.,   58.,  -10.,    1.,   99., 1960\n     5           -237.,   60.,   -1.,  -20.,   -2.,  -11., -113.,  -17., 1960\n     6             67.,  -56.,  -55.,    5.,  -28.,   15.,   -6.,  -32., 1960\n     7              7.,   -7.,   23.,   17.,  -18.,    8.,  -17.,   15., 1960\n     8              6.,   11.,   -4.,  -14.,  -11.,    7.,    2.,  -18., 1960\n     9             10.,    4.,   -5.,   23.,   10.,    1.,    8.,  -20., 1960\n     a              4.,    6.,  -18.,    0.,   12.,   -9.,    2.,    1., 1960\n     b              0.,    4.,   -3.,   -1.,    9.,   -2.,    8.,    3., 1960\n     c              0.,   -1.,    5.,    1.,   -3.,    4.,    4.,    1., 1960\n     d              0.,    0.,   -1.,    2.,    4.,   -5.,    6.,    1., 1960\n     e              1.,   -1.,   -1.,    6.,    2.,    0.,    0.,   -7./ 1960\n      data gd/ -30334.,-2119., 5776.,-1662., 2997.,-2016., 1594.,  114., 1965\n     1           1297.,-2038., -404., 1292.,  240.,  856., -165.,  957., 1965\n     2            804.,  148.,  479., -269., -390.,   13.,  252., -269., 1965\n     3           -219.,  358.,   19.,  254.,  128.,  -31., -126., -157., 1965\n     4            -97.,  -62.,   81.,   45.,   61.,  -11.,    8.,  100., 1965\n     5           -228.,   68.,    4.,  -32.,    1.,   -8., -111.,   -7., 1965\n     6             75.,  -57.,  -61.,    4.,  -27.,   13.,   -2.,  -26., 1965\n     7              6.,   -6.,   26.,   13.,  -23.,    1.,  -12.,   13., 1965\n     8              5.,    7.,   -4.,  -12.,  -14.,    9.,    0.,  -16., 1965\n     9              8.,    4.,   -1.,   24.,   11.,   -3.,    4.,  -17., 1965\n     a              8.,   10.,  -22.,    2.,   15.,  -13.,    7.,   10., 1965\n     b             -4.,   -1.,   -5.,   -1.,   10.,    5.,   10.,    1., 1965\n     c             -4.,   -2.,    1.,   -2.,   -3.,    2.,    2.,    1., 1965\n     d             -5.,    2.,   -2.,    6.,    4.,   -4.,    4.,    0., 1965\n     e              0.,   -2.,    2.,    3.,    2.,    0.,    0.,   -6./ 1965\n      data ge/ -30220.,-2068., 5737.,-1781., 3000.,-2047., 1611.,   25., 1970\n     1           1287.,-2091., -366., 1278.,  251.,  838., -196.,  952., 1970\n     2            800.,  167.,  461., -266., -395.,   26.,  234., -279., 1970\n     3           -216.,  359.,   26.,  262.,  139.,  -42., -139., -160., 1970\n     4            -91.,  -56.,   83.,   43.,   64.,  -12.,   15.,  100., 1970\n     5           -212.,   72.,    2.,  -37.,    3.,   -6., -112.,    1., 1970\n     6             72.,  -57.,  -70.,    1.,  -27.,   14.,   -4.,  -22., 1970\n     7              8.,   -2.,   23.,   13.,  -23.,   -2.,  -11.,   14., 1970\n     8              6.,    7.,   -2.,  -15.,  -13.,    6.,   -3.,  -17., 1970\n     9              5.,    6.,    0.,   21.,   11.,   -6.,    3.,  -16., 1970\n     a              8.,   10.,  -21.,    2.,   16.,  -12.,    6.,   10., 1970\n     b             -4.,   -1.,   -5.,    0.,   10.,    3.,   11.,    1., 1970\n     c             -2.,   -1.,    1.,   -3.,   -3.,    1.,    2.,    1., 1970\n     d             -5.,    3.,   -1.,    4.,    6.,   -4.,    4.,    0., 1970\n     e              1.,   -1.,    0.,    3.,    3.,    1.,   -1.,   -4./ 1970\n      data gf/ -30100.,-2013., 5675.,-1902., 3010.,-2067., 1632.,  -68., 1975\n     1           1276.,-2144., -333., 1260.,  262.,  830., -223.,  946., 1975\n     2            791.,  191.,  438., -265., -405.,   39.,  216., -288., 1975\n     3           -218.,  356.,   31.,  264.,  148.,  -59., -152., -159., 1975\n     4            -83.,  -49.,   88.,   45.,   66.,  -13.,   28.,   99., 1975\n     5           -198.,   75.,    1.,  -41.,    6.,   -4., -111.,   11., 1975\n     6             71.,  -56.,  -77.,    1.,  -26.,   16.,   -5.,  -14., 1975\n     7             10.,    0.,   22.,   12.,  -23.,   -5.,  -12.,   14., 1975\n     8              6.,    6.,   -1.,  -16.,  -12.,    4.,   -8.,  -19., 1975\n     9              4.,    6.,    0.,   18.,   10.,  -10.,    1.,  -17., 1975\n     a              7.,   10.,  -21.,    2.,   16.,  -12.,    7.,   10., 1975\n     b             -4.,   -1.,   -5.,   -1.,   10.,    4.,   11.,    1., 1975\n     c             -3.,   -2.,    1.,   -3.,   -3.,    1.,    2.,    1., 1975\n     d             -5.,    3.,   -2.,    4.,    5.,   -4.,    4.,   -1., 1975\n     e              1.,   -1.,    0.,    3.,    3.,    1.,   -1.,   -5./ 1975\n      data gg/ -29992.,-1956., 5604.,-1997., 3027.,-2129., 1663., -200., 1980\n     1           1281.,-2180., -336., 1251.,  271.,  833., -252.,  938., 1980\n     2            782.,  212.,  398., -257., -419.,   53.,  199., -297., 1980\n     3           -218.,  357.,   46.,  261.,  150.,  -74., -151., -162., 1980\n     4            -78.,  -48.,   92.,   48.,   66.,  -15.,   42.,   93., 1980\n     5           -192.,   71.,    4.,  -43.,   14.,   -2., -108.,   17., 1980\n     6             72.,  -59.,  -82.,    2.,  -27.,   21.,   -5.,  -12., 1980\n     7             16.,    1.,   18.,   11.,  -23.,   -2.,  -10.,   18., 1980\n     8              6.,    7.,    0.,  -18.,  -11.,    4.,   -7.,  -22., 1980\n     9              4.,    9.,    3.,   16.,    6.,  -13.,   -1.,  -15., 1980\n     a              5.,   10.,  -21.,    1.,   16.,  -12.,    9.,    9., 1980\n     b             -5.,   -3.,   -6.,   -1.,    9.,    7.,   10.,    2., 1980\n     c             -6.,   -5.,    2.,   -4.,   -4.,    1.,    2.,    0., 1980\n     d             -5.,    3.,   -2.,    6.,    5.,   -4.,    3.,    0., 1980\n     e              1.,   -1.,    2.,    4.,    3.,    0.,    0.,   -6./ 1980\n      data gi/ -29873.,-1905., 5500.,-2072., 3044.,-2197., 1687., -306., 1985\n     1           1296.,-2208., -310., 1247.,  284.,  829., -297.,  936., 1985\n     2            780.,  232.,  361., -249., -424.,   69.,  170., -297., 1985\n     3           -214.,  355.,   47.,  253.,  150.,  -93., -154., -164., 1985\n     4            -75.,  -46.,   95.,   53.,   65.,  -16.,   51.,   88., 1985\n     5           -185.,   69.,    4.,  -48.,   16.,   -1., -102.,   21., 1985\n     6             74.,  -62.,  -83.,    3.,  -27.,   24.,   -2.,   -6., 1985\n     7             20.,    4.,   17.,   10.,  -23.,    0.,   -7.,   21., 1985\n     8              6.,    8.,    0.,  -19.,  -11.,    5.,   -9.,  -23., 1985\n     9              4.,   11.,    4.,   14.,    4.,  -15.,   -4.,  -11., 1985\n     a              5.,   10.,  -21.,    1.,   15.,  -12.,    9.,    9., 1985\n     b             -6.,   -3.,   -6.,   -1.,    9.,    7.,    9.,    1., 1985\n     c             -7.,   -5.,    2.,   -4.,   -4.,    1.,    3.,    0., 1985\n     d             -5.,    3.,   -2.,    6.,    5.,   -4.,    3.,    0., 1985\n     e              1.,   -1.,    2.,    4.,    3.,    0.,    0.,   -6./ 1985\n      data gj/ -29775.,-1848., 5406.,-2131., 3059.,-2279., 1686., -373., 1990\n     1           1314.,-2239., -284., 1248.,  293.,  802., -352.,  939., 1990\n     2            780.,  247.,  325., -240., -423.,   84.,  141., -299., 1990\n     3           -214.,  353.,   46.,  245.,  154., -109., -153., -165., 1990\n     4            -69.,  -36.,   97.,   61.,   65.,  -16.,   59.,   82., 1990\n     5           -178.,   69.,    3.,  -52.,   18.,    1.,  -96.,   24., 1990\n     6             77.,  -64.,  -80.,    2.,  -26.,   26.,    0.,   -1., 1990\n     7             21.,    5.,   17.,    9.,  -23.,    0.,   -4.,   23., 1990\n     8              5.,   10.,   -1.,  -19.,  -10.,    6.,  -12.,  -22., 1990\n     9              3.,   12.,    4.,   12.,    2.,  -16.,   -6.,  -10., 1990\n     a              4.,    9.,  -20.,    1.,   15.,  -12.,   11.,    9., 1990\n     b             -7.,   -4.,   -7.,   -2.,    9.,    7.,    8.,    1., 1990\n     c             -7.,   -6.,    2.,   -3.,   -4.,    2.,    2.,    1., 1990\n     d             -5.,    3.,   -2.,    6.,    4.,   -4.,    3.,    0., 1990\n     e              1.,   -2.,    3.,    3.,    3.,   -1.,    0.,   -6./ 1990\n      data gk/ -29692.,-1784., 5306.,-2200., 3070.,-2366., 1681., -413., 1995\n     1           1335.,-2267., -262., 1249.,  302.,  759., -427.,  940., 1995\n     2            780.,  262.,  290., -236., -418.,   97.,  122., -306., 1995\n     3           -214.,  352.,   46.,  235.,  165., -118., -143., -166., 1995\n     4            -55.,  -17.,  107.,   68.,   67.,  -17.,   68.,   72., 1995\n     5           -170.,   67.,   -1.,  -58.,   19.,    1.,  -93.,   36., 1995\n     6             77.,  -72.,  -69.,    1.,  -25.,   28.,    4.,    5., 1995\n     7             24.,    4.,   17.,    8.,  -24.,   -2.,   -6.,   25., 1995\n     8              6.,   11.,   -6.,  -21.,   -9.,    8.,  -14.,  -23., 1995\n     9              9.,   15.,    6.,   11.,   -5.,  -16.,   -7.,   -4., 1995\n     a              4.,    9.,  -20.,    3.,   15.,  -10.,   12.,    8., 1995\n     b             -6.,   -8.,   -8.,   -1.,    8.,   10.,    5.,   -2., 1995\n     c             -8.,   -8.,    3.,   -3.,   -6.,    1.,    2.,    0., 1995\n     d             -4.,    4.,   -1.,    5.,    4.,   -5.,    2.,   -1., 1995\n     e              2.,   -2.,    5.,    1.,    1.,   -2.,    0.,   -7., 1995\n     f           75*0./                                                  1995\n      data gl/ -29619.4,-1728.2, 5186.1,-2267.7, 3068.4,-2481.6, 1670.9, 2000\n     1           -458.0, 1339.6,-2288.0, -227.6, 1252.1,  293.4,  714.5, 2000\n     2           -491.1,  932.3,  786.8,  272.6,  250.0, -231.9, -403.0, 2000\n     3            119.8,  111.3, -303.8, -218.8,  351.4,   43.8,  222.3, 2000\n     4            171.9, -130.4, -133.1, -168.6,  -39.3,  -12.9,  106.3, 2000\n     5             72.3,   68.2,  -17.4,   74.2,   63.7, -160.9,   65.1, 2000\n     6             -5.9,  -61.2,   16.9,    0.7,  -90.4,   43.8,   79.0, 2000\n     7            -74.0,  -64.6,    0.0,  -24.2,   33.3,    6.2,    9.1, 2000\n     8             24.0,    6.9,   14.8,    7.3,  -25.4,   -1.2,   -5.8, 2000\n     9             24.4,    6.6,   11.9,   -9.2,  -21.5,   -7.9,    8.5, 2000\n     a            -16.6,  -21.5,    9.1,   15.5,    7.0,    8.9,   -7.9, 2000\n     b            -14.9,   -7.0,   -2.1,    5.0,    9.4,  -19.7,    3.0, 2000\n     c             13.4,   -8.4,   12.5,    6.3,   -6.2,   -8.9,   -8.4, 2000\n     d             -1.5,    8.4,    9.3,    3.8,   -4.3,   -8.2,   -8.2, 2000\n     e              4.8,   -2.6,   -6.0,    1.7,    1.7,    0.0,   -3.1, 2000\n     f              4.0,   -0.5,    4.9,    3.7,   -5.9,    1.0,   -1.2, 2000\n     g              2.0,   -2.9,    4.2,    0.2,    0.3,   -2.2,   -1.1, 2000\n     h             -7.4,    2.7,   -1.7,    0.1,   -1.9,    1.3,    1.5, 2000\n     i             -0.9,   -0.1,   -2.6,    0.1,    0.9,   -0.7,   -0.7, 2000\n     j              0.7,   -2.8,    1.7,   -0.9,    0.1,   -1.2,    1.2, 2000\n     k             -1.9,    4.0,   -0.9,   -2.2,   -0.3,   -0.4,    0.2, 2000\n     l              0.3,    0.9,    2.5,   -0.2,   -2.6,    0.9,    0.7, 2000\n     m             -0.5,    0.3,    0.3,    0.0,   -0.3,    0.0,   -0.4, 2000\n     n              0.3,   -0.1,   -0.9,   -0.2,   -0.4,   -0.4,    0.8, 2000\n     o             -0.2,   -0.9,   -0.9,    0.3,    0.2,    0.1,    1.8, 2000\n     p             -0.4,   -0.4,    1.3,   -1.0,   -0.4,   -0.1,    0.7, 2000\n     q              0.7,   -0.4,    0.3,    0.3,    0.6,   -0.1,    0.3, 2000\n     r              0.4,   -0.2,    0.0,   -0.5,    0.1,   -0.9/         2000\n      data gm/-29554.63,-1669.05, 5077.99,-2337.24, 3047.69,-2594.50,    2005\n     1          1657.76, -515.43, 1336.30,-2305.83, -198.86, 1246.39,    2005\n     2           269.72,  672.51, -524.72,  920.55,  797.96,  282.07,    2005\n     3           210.65, -225.23, -379.86,  145.15,  100.00, -305.36,    2005\n     4          -227.00,  354.41,   42.72,  208.95,  180.25, -136.54,    2005\n     5          -123.45, -168.05,  -19.57,  -13.55,  103.85,   73.60,    2005\n     6            69.56,  -20.33,   76.74,   54.75, -151.34,   63.63,    2005\n     7           -14.58,  -63.53,   14.58,    0.24,  -86.36,   50.94,    2005\n     8            79.88,  -74.46,  -61.14,   -1.65,  -22.57,   38.73,    2005\n     9             6.82,   12.30,   25.35,    9.37,   10.93,    5.42,    2005\n     a           -26.32,    1.94,   -4.64,   24.80,    7.62,   11.20,    2005\n     b           -11.73,  -20.88,   -6.88,    9.83,  -18.11,  -19.71,    2005\n     c            10.17,   16.22,    9.36,    7.61,  -11.25,  -12.76,    2005\n     d            -4.87,   -0.06,    5.58,    9.76,  -20.11,    3.58,    2005\n     e            12.69,   -6.94,   12.67,    5.01,   -6.72,  -10.76,    2005\n     f            -8.16,   -1.25,    8.10,    8.76,    2.92,   -6.66,    2005\n     g            -7.73,   -9.22,    6.01,   -2.17,   -6.12,    2.19,    2005\n     h             1.42,    0.10,   -2.35,    4.46,   -0.15,    4.76,    2005\n     i             3.06,   -6.58,    0.29,   -1.01,    2.06,   -3.47,    2005\n     j             3.77,   -0.86,   -0.21,   -2.31,   -2.09,   -7.93,    2005\n     k             2.95,   -1.60,    0.26,   -1.88,    1.44,    1.44,    2005\n     l            -0.77,   -0.31,   -2.27,    0.29,    0.90,   -0.79,    2005\n     m            -0.58,    0.53,   -2.69,    1.80,   -1.08,    0.16,    2005\n     n            -1.58,    0.96,   -1.90,    3.99,   -1.39,   -2.15,    2005\n     o            -0.29,   -0.55,    0.21,    0.23,    0.89,    2.38,    2005\n     p            -0.38,   -2.63,    0.96,    0.61,   -0.30,    0.40,    2005\n     q             0.46,    0.01,   -0.35,    0.02,   -0.36,    0.28,    2005\n     r             0.08,   -0.87,   -0.49,   -0.34,   -0.08,    0.88,    2005\n     s            -0.16,   -0.88,   -0.76,    0.30,    0.33,    0.28,    2005\n     t             1.72,   -0.43,   -0.54,    1.18,   -1.07,   -0.37,    2005\n     u            -0.04,    0.75,    0.63,   -0.26,    0.21,    0.35,    2005\n     v             0.53,   -0.05,    0.38,    0.41,   -0.22,   -0.10,    2005\n     w            -0.57,   -0.18,   -0.82/                               2005\n      data gp/-29496.57,-1586.42, 4944.26,-2396.06, 3026.34,-2708.54,    2010\n     1          1668.17, -575.73, 1339.85,-2326.54, -160.40, 1232.10,    2010\n     2           251.75,  633.73, -537.03,  912.66,  808.97,  286.48,    2010\n     3           166.58, -211.03, -356.83,  164.46,   89.40, -309.72,    2010\n     4          -230.87,  357.29,   44.58,  200.26,  189.01, -141.05,    2010\n     5          -118.06, -163.17,   -0.01,   -8.03,  101.04,   72.78,    2010\n     6            68.69,  -20.90,   75.92,   44.18, -141.40,   61.54,    2010\n     7           -22.83,  -66.26,   13.10,    3.02,  -78.09,   55.40,    2010\n     8            80.44,  -75.00,  -57.80,   -4.55,  -21.20,   45.24,    2010\n     9             6.54,   14.00,   24.96,   10.46,    7.03,    1.64,    2010\n     a           -27.61,    4.92,   -3.28,   24.41,    8.21,   10.84,    2010\n     b           -14.50,  -20.03,   -5.59,   11.83,  -19.34,  -17.41,    2010\n     c            11.61,   16.71,   10.85,    6.96,  -14.05,  -10.74,    2010\n     d            -3.54,    1.64,    5.50,    9.45,  -20.54,    3.45,    2010\n     e            11.51,   -5.27,   12.75,    3.13,   -7.14,  -12.38,    2010\n     f            -7.42,   -0.76,    7.97,    8.43,    2.14,   -8.42,    2010\n     g            -6.08,  -10.08,    7.01,   -1.94,   -6.24,    2.73,    2010\n     h             0.89,   -0.10,   -1.07,    4.71,   -0.16,    4.44,    2010\n     i             2.45,   -7.22,   -0.33,   -0.96,    2.13,   -3.95,    2010\n     j             3.09,   -1.99,   -1.03,   -1.97,   -2.80,   -8.31,    2010\n     k             3.05,   -1.48,    0.13,   -2.03,    1.67,    1.65,    2010\n     l            -0.66,   -0.51,   -1.76,    0.54,    0.85,   -0.79,    2010\n     m            -0.39,    0.37,   -2.51,    1.79,   -1.27,    0.12,    2010\n     n            -2.11,    0.75,   -1.94,    3.75,   -1.86,   -2.12,    2010\n     o            -0.21,   -0.87,    0.30,    0.27,    1.04,    2.13,    2010\n     p            -0.63,   -2.49,    0.95,    0.49,   -0.11,    0.59,    2010\n     q             0.52,    0.00,   -0.39,    0.13,   -0.37,    0.27,    2010\n     r             0.21,   -0.86,   -0.77,   -0.23,    0.04,    0.87,    2010\n     s            -0.09,   -0.89,   -0.87,    0.31,    0.30,    0.42,    2010\n     t             1.66,   -0.45,   -0.59,    1.08,   -1.14,   -0.31,    2010\n     u            -0.07,    0.78,    0.54,   -0.18,    0.10,    0.38,    2010\n     v             0.49,    0.02,    0.44,    0.42,   -0.25,   -0.26,    2010\n     w            -0.53,   -0.26,   -0.79/                               2010\n      data gq/-29441.46,-1501.77, 4795.99,-2445.88, 3012.20,-2845.41,    2015\n     1          1676.35, -642.17, 1350.33,-2352.26, -115.29, 1225.85,    2015\n     2           245.04,  581.69, -538.70,  907.42,  813.68,  283.54,    2015\n     3           120.49, -188.43, -334.85,  180.95,   70.38, -329.23,    2015\n     4          -232.91,  360.14,   46.98,  192.35,  196.98, -140.94,    2015\n     5          -119.14, -157.40,   15.98,    4.30,  100.12,   69.55,    2015\n     6            67.57,  -20.61,   72.79,   33.30, -129.85,   58.74,    2015\n     7           -28.93,  -66.64,   13.14,    7.35,  -70.85,   62.41,    2015\n     8            81.29,  -75.99,  -54.27,   -6.79,  -19.53,   51.82,    2015\n     9             5.59,   15.07,   24.45,    9.32,    3.27,   -2.88,    2015\n     a           -27.50,    6.61,   -2.32,   23.98,    8.89,   10.04,    2015\n     b           -16.78,  -18.26,   -3.16,   13.18,  -20.56,  -14.60,    2015\n     c            13.33,   16.16,   11.76,    5.69,  -15.98,   -9.10,    2015\n     d            -2.02,    2.26,    5.33,    8.83,  -21.77,    3.02,    2015\n     e            10.76,   -3.22,   11.74,    0.67,   -6.74,  -13.20,    2015\n     f            -6.88,   -0.10,    7.79,    8.68,    1.04,   -9.06,    2015\n     g            -3.89,  -10.54,    8.44,   -2.01,   -6.26,    3.28,    2015\n     h             0.17,   -0.40,    0.55,    4.55,   -0.55,    4.40,    2015\n     i             1.70,   -7.92,   -0.67,   -0.61,    2.13,   -4.16,    2015\n     j             2.33,   -2.85,   -1.80,   -1.12,   -3.59,   -8.72,    2015\n     k             3.00,   -1.40,    0.00,   -2.30,    2.11,    2.08,    2015\n     l            -0.60,   -0.79,   -1.05,    0.58,    0.76,   -0.70,    2015\n     m            -0.20,    0.14,   -2.12,    1.70,   -1.44,   -0.22,    2015\n     n            -2.57,    0.44,   -2.01,    3.49,   -2.34,   -2.09,    2015\n     o            -0.16,   -1.08,    0.46,    0.37,    1.23,    1.75,    2015\n     p            -0.89,   -2.19,    0.85,    0.27,    0.10,    0.72,    2015\n     q             0.54,   -0.09,   -0.37,    0.29,   -0.43,    0.23,    2015\n     r             0.22,   -0.89,   -0.94,   -0.16,   -0.03,    0.72,    2015\n     s            -0.02,   -0.92,   -0.88,    0.42,    0.49,    0.63,    2015\n     t             1.56,   -0.42,   -0.50,    0.96,   -1.24,   -0.19,    2015\n     u            -0.10,    0.81,    0.42,   -0.13,   -0.04,    0.38,    2015\n     v             0.48,    0.08,    0.48,    0.46,   -0.30,   -0.35,    2015\n     w            -0.43,   -0.36,   -0.71/                               2015\n      data gr/-29403.41,-1451.37, 4653.35,-2499.78, 2981.96,-2991.72,    2020\n     1          1676.85, -734.62, 1363.00,-2380.80,  -81.96, 1236.06,    2020\n     2           241.80,  525.60, -542.52,  902.82,  809.47,  282.10,    2020\n     3            86.18, -158.50, -309.47,  199.75,   47.44, -350.30,    2020\n     4          -234.42,  363.26,   47.52,  187.86,  208.36, -140.73,    2020\n     5          -121.43, -151.16,   32.09,   13.98,   99.14,   65.97,    2020\n     6            65.56,  -19.22,   72.96,   25.02, -121.57,   52.76,    2020\n     7           -36.06,  -64.40,   13.60,    8.96,  -64.80,   68.04,    2020\n     8            80.54,  -76.63,  -51.50,   -8.23,  -16.85,   56.45,    2020\n     9             2.36,   15.80,   23.56,    6.30,   -2.19,   -7.21,    2020\n     a           -27.19,    9.77,   -1.90,   23.66,    9.74,    8.43,    2020\n     b           -17.49,  -15.23,   -0.49,   12.83,  -21.07,  -11.76,    2020\n     c            15.28,   14.94,   13.65,    3.62,  -16.59,   -6.90,    2020\n     d            -0.34,    2.90,    5.03,    8.36,  -23.44,    2.84,    2020\n     e            11.04,   -1.48,    9.86,   -1.14,   -5.13,  -13.22,    2020\n     f            -6.20,    1.08,    7.79,    8.82,    0.40,   -9.23,    2020\n     g            -1.44,  -11.86,    9.60,   -1.84,   -6.25,    3.38,    2020\n     h            -0.11,   -0.18,    1.66,    3.50,   -0.86,    4.86,    2020\n     i             0.65,   -8.62,   -0.88,   -0.11,    1.88,   -4.26,    2020\n     j             1.44,   -3.43,   -2.38,   -0.10,   -3.84,   -8.84,    2020\n     k             2.96,   -1.36,   -0.02,   -2.51,    2.50,    2.31,    2020\n     l            -0.55,   -0.85,   -0.39,    0.28,    0.62,   -0.66,    2020\n     m            -0.21,   -0.07,   -1.66,    1.44,   -1.60,   -0.59,    2020\n     n            -2.98,    0.18,   -1.97,    3.09,   -2.51,   -2.00,    2020\n     o            -0.13,   -1.15,    0.43,    0.52,    1.28,    1.37,    2020\n     p            -1.14,   -1.81,    0.71,    0.08,    0.31,    0.71,    2020\n     q             0.49,   -0.15,   -0.26,    0.55,   -0.47,    0.16,    2020\n     r             0.09,   -0.93,   -1.13,   -0.04,   -0.33,    0.52,    2020\n     s             0.08,   -0.93,   -0.88,    0.53,    0.64,    0.72,    2020\n     t             1.40,   -0.30,   -0.38,    0.75,   -1.31,   -0.01,    2020\n     u            -0.09,    0.76,    0.29,   -0.05,   -0.11,    0.37,    2020\n     v             0.47,    0.13,    0.54,    0.45,   -0.41,   -0.46,    2020\n     w            -0.36,   -0.40,   -0.60/                               2020\n      data gs/ -29350.0, -1410.3,  4545.5, -2556.2,  2950.9, -3133.6,    2025\n     1           1648.7,  -814.2,  1360.9, -2404.2,   -56.9,  1243.8,    2025\n     2            237.6,   453.4,  -549.6,   894.7,   799.6,   278.6,    2025\n     3             55.8,  -134.0,  -281.1,   212.0,    12.0,  -375.4,    2025\n     4           -232.9,   369.0,    45.3,   187.2,   220.0,  -138.7,    2025\n     5           -122.9,  -141.9,    42.9,    20.9,   106.2,    64.3,    2025\n     6             63.8,   -18.4,    76.7,    16.8,  -115.7,    48.9,    2025\n     7            -40.9,   -59.8,    14.9,    10.9,   -60.8,    72.8,    2025\n     8             79.6,   -76.9,   -48.9,    -8.8,   -14.4,    59.3,    2025\n     9             -1.0,    15.8,    23.5,     2.5,    -7.4,   -11.2,    2025\n     a            -25.1,    14.3,    -2.2,    23.1,    10.9,     7.2,    2025\n     b            -17.5,   -12.6,     2.0,    11.5,   -21.8,    -9.7,    2025\n     c             16.9,    12.7,    14.9,     0.7,   -16.8,    -5.2,    2025\n     d              1.0,     3.9,     4.7,     8.0,   -24.8,     3.0,    2025\n     e             12.1,    -0.2,     8.3,    -2.5,    -3.4,   -13.1,    2025\n     f             -5.3,     2.4,     7.2,     8.6,    -0.6,    -8.7,    2025\n     g              0.8,   -12.8,     9.8,    -1.3,    -6.4,     3.3,    2025\n     h              0.2,     0.1,     2.0,     2.5,    -1.0,     5.4,    2025\n     i             -0.5,    -9.0,    -0.9,     0.4,     1.5,    -4.2,    2025\n     j              0.9,    -3.8,    -2.6,     0.9,    -3.9,    -9.0,    2025\n     k              3.0,    -1.4,     0.0,    -2.5,     2.8,     2.4,    2025\n     l             -0.6,    -0.6,     0.1,     0.0,     0.5,    -0.6,    2025\n     m             -0.3,    -0.1,    -1.2,     1.1,    -1.7,    -1.0,    2025\n     n             -2.9,    -0.1,    -1.8,     2.6,    -2.3,    -2.0,    2025\n     o             -0.1,    -1.2,     0.4,     0.6,     1.2,     1.0,    2025\n     p             -1.2,    -1.5,     0.6,     0.0,     0.5,     0.6,    2025\n     q              0.5,    -0.2,    -0.1,     0.8,    -0.5,     0.1,    2025\n     r             -0.2,    -0.9,    -1.2,     0.1,    -0.7,     0.2,    2025\n     s              0.2,    -0.9,    -0.9,     0.6,     0.7,     0.7,    2025\n     t              1.2,    -0.2,    -0.3,     0.5,    -1.3,     0.1,    2025\n     u             -0.1,     0.7,     0.2,     0.0,    -0.2,     0.3,    2025\n     v              0.5,     0.2,     0.6,     0.4,    -0.6,    -0.5,    2025\n     w             -0.3,    -0.4,    -0.5/                               2025\n      data gt/     12.6,    10.0,   -21.5,   -11.2,    -5.3,   -27.3,    2027\n     1             -8.3,   -11.1,    -1.5,    -4.4,     3.8,     0.4,    2027\n     2             -0.2,   -15.6,    -3.9,    -1.7,    -2.3,    -1.3,    2027\n     3             -5.8,     4.1,     5.4,     1.6,    -6.8,    -4.1,    2027\n     4              0.6,     1.3,    -0.5,     0.0,     2.1,     0.7,    2027\n     5              0.5,     2.3,     1.7,     1.0,     1.9,    -0.2,    2027\n     6             -0.3,     0.3,     0.8,    -1.6,     1.2,    -0.4,    2027\n     7             -0.8,     0.8,     0.4,     0.7,     0.9,     0.9,    2027\n     8             -0.1,    -0.1,     0.6,    -0.1,     0.5,     0.5,    2027\n     9             -0.7,    -0.1,     0.0,    -0.8,    -0.9,    -0.8,    2027\n     a              0.5,     0.9,    -0.3,    -0.1,     0.2,    -0.3,    2027\n     b              0.0,     0.4,     0.4,    -0.3,    -0.1,     0.4,    2027\n     c              0.3,    -0.5,     0.1,    -0.6,     0.0,     0.3,    2027\n     d              0.3,     0.2, 115*0.0/                               2027\nc\nc     set initial values\nc\n      x     = 0.0\n      y     = 0.0\n      z     = 0.0\n      if (date.lt.1900.0.or.date.gt.2035.0) go to 11\n      if (date.gt.2030.0) write (6,960) date\n  960 format (/' This version of the IGRF is intended for use up',\n     1        ' to 2030.0.'/' values for',f9.3,' will be computed',\n     2        ' but may be of reduced accuracy'/)\n      if (date.ge.2025.0) go to 1\n      t     = 0.2*(date - 1900.0)\n      ll    = t\n      one   = ll\n      t     = t - one\nc\nc     SH models before 1995.0 are only to degree 10\nc\n      if (date.lt.1995.0) then\n       nmx   = 10\n       nc    = nmx*(nmx+2)\n       ll    = nc*ll\n       kmx   = (nmx+1)*(nmx+2)/2\n      else\n       nmx   = 13\n       nc    = nmx*(nmx+2)\n       ll    = 0.2*(date - 1995.0)\nc\nc     19 is the number of SH models that extend to degree 10\nc\n       ll    = 120*19 + nc*ll\n       kmx   = (nmx+1)*(nmx+2)/2\n      endif\n      tc    = 1.0 - t\n      if (isv.eq.1) then\n       tc = -0.2\n       t = 0.2\n      end if\n      go to 2\nc\n    1 t     = date - 2025.0\n      tc    = 1.0\n      if (isv.eq.1) then\n       t = 1.0\n       tc = 0.0\n      end if\nc\nc     pointer for last coefficient in pen-ultimate set of MF coefficients...\nc\n      ll    = 3450\n      nmx   = 13\n      nc    = nmx*(nmx+2)\n      kmx   = (nmx+1)*(nmx+2)/2\n    2 r     = alt\n      one   = colat*0.017453292\n      ct    = cos(one)\n      st    = sin(one)\n      one   = elong*0.017453292\n      cl(1) = cos(one)\n      sl(1) = sin(one)\n      cd    = 1.0\n      sd    = 0.0\n      l     = 1\n      m     = 1\n      n     = 0\n      if (itype.eq.2) go to 3\nc\nc     conversion from geodetic to geocentric coordinates\nc     (using the WGS84 spheroid)\nc\n      a2    = 40680631.6\n      b2    = 40408296.0\n      one   = a2*st*st\n      two   = b2*ct*ct\n      three = one + two\n      rho   = sqrt(three)\n      r     = sqrt(alt*(alt + 2.0*rho) + (a2*one + b2*two)/three)\n      cd    = (alt + rho)/r\n      sd    = (a2 - b2)/rho*ct*st/r\n      one   = ct\n      ct    = ct*cd -  st*sd\n      st    = st*cd + one*sd\nc\n    3 ratio = 6371.2/r\n      rr    = ratio*ratio\nc\nc     computation of Schmidt quasi-normal coefficients p and x(=q)\nc\n      p(1)  = 1.0\n      p(3)  = st\n      q(1)  = 0.0\n      q(3)  =  ct\n      do 10 k=2,kmx\n       if (n.ge.m) go to 4\n       m     = 0\n       n     = n + 1\n       rr    = rr*ratio\n       fn    = n\n       gn    = n - 1\n    4  fm    = m\n       if (m.ne.n) go to 5\n       if (k.eq.3) go to 6\n       one   = sqrt(1.0 - 0.5/fm)\n       j     = k - n - 1\n       p(k)  = one*st*p(j)\n       q(k)  = one*(st*q(j) + ct*p(j))\n       cl(m) = cl(m-1)*cl(1) - sl(m-1)*sl(1)\n       sl(m) = sl(m-1)*cl(1) + cl(m-1)*sl(1)\n       go to 6\n    5  gmm    = m*m\n       one   = sqrt(fn*fn - gmm)\n       two   = sqrt(gn*gn - gmm)/one\n       three = (fn + gn)/one\n       i     = k - n\n       j     = i - n + 1\n       p(k)  = three*ct*p(i) - two*p(j)\n       q(k)  = three*(ct*q(i) - st*p(i)) - two*q(j)\nc\nc     synthesis of x, y and z in geocentric coordinates\nc\n    6  lm    = ll + l\n       one   = (tc*gh(lm) + t*gh(lm+nc))*rr\n       if (m.eq.0) go to 9\n       two   = (tc*gh(lm+1) + t*gh(lm+nc+1))*rr\n       three = one*cl(m) + two*sl(m)\n       x     = x + three*q(k)\n       z     = z - (fn + 1.0)*three*p(k)\n       if (st.eq.0.0) go to 7\n       y     = y + (one*sl(m) - two*cl(m))*fm*p(k)/st\n       go to 8\n    7  y     = y + (one*sl(m) - two*cl(m))*q(k)*ct\n    8  l     = l + 2\n       go to 10\n    9  x     = x + one*q(k)\n       z     = z - (fn + 1.0)*one*p(k)\n       l     = l + 1\n   10 m     = m + 1\nc\nc     conversion to coordinate system specified by itype\nc\n      one   = x\n      x     = x*cd +   z*sd\n      z     = z*cd - one*sd\n      f     = sqrt(x*x + y*y + z*z)\nc\n      return\nc\nc     error return if date out of bounds\nc\n   11 f     = 1.0d8\n      write (6,961) date\n  961 format (/' This subroutine will not work with a date of',\n     1        f9.3,'.  Date must be in the range 1900.0.ge.date',\n     2        '.le.2035.0. On return f = 1.0d8., x = y = z = 0.')\n      return\n      end\n"
  },
  {
    "path": "source/external/jb2008/JB2008.f",
    "content": "C\n      SUBROUTINE JB2008 (AMJD,SUN,SAT,F10,F10B,S10,S10B,XM10,XM10B,\n     *                   Y10,Y10B,DSTDTC,TEMP,RHO)\nC\nC     Jacchia-Bowman 2008 Model Atmosphere\nC\nC\nC***********************************************************************\nC\nC     This is the CIRA \"Integration Form\" of a Jacchia Model.\nC     There are no tabular values of density.  Instead, the barometric\nC     equation and diffusion equation are integrated numerically using\nC     the Newton-Coates method to produce the density profile up to the\nC     input position.\nC\nC     INPUT:\nC\nC           AMJD   : Date and Time, in modified Julian Days\nC                    and Fraction (MJD = JD-2400000.5)\nC           SUN(1) : Right Ascension of Sun (radians)\nC           SUN(2) : Declination of Sun (radians)\nC           SAT(1) : Right Ascension of Position (radians)\nC           SAT(2) : Geocentric Latitude of Position (radians)\nC           SAT(3) : Height of Position (km)\nC           F10    : 10.7-cm Solar Flux (1.0E-22*Watt/(M**2*Hertz))\nC                    (Tabular time 1.0 day earlier)\nC           F10B   : 10.7-cm Solar Flux, ave.\nC                    81-day centered on the input time\nC                    (Tabular time 1.0 day earlier)\nC           S10    : EUV index (26-34 nm) scaled to F10\nC                    (Tabular time 1.0 day earlier)\nC           S10B   : EUV 81-day ave. centered index\nC                    (Tabular time 1.0 day earlier)\nC           XM10   : MG2 index scaled to F10\nC                    (Tabular time 2.0 days earlier)\nC           XM10B  : MG2 81-day ave. centered index\nC                    (Tabular time 2.0 days earlier)\nC           Y10    : Solar X-Ray & Lya index scaled to F10\nC                    (Tabular time 5.0 days earlier)\nC           Y10B   : Solar X-Ray & Lya 81-day ave. centered index\nC                    (Tabular time 5.0 days earlier)\nC           DSTDTC : Temperature change computed from Dst index\nC\nC     OUTPUT:\nC\nC           TEMP(1): Exospheric Temperature above Input Position (deg K)\nC           TEMP(2): Temperature at Input Position (deg K)\nC           RHO    : Total Mass-Desnity at Input Position (kg/m**3)\nC\nC\nC     JB2008 Model Development: (Ref. 7)\nC\nC\nC     A. Development of the JB2006 model:\nC\nC       1. Started with the CIRA72 model (Jacchia 71).\nC\nC       2. Converted to CIRA70 model replacing equations from Jacchia 70\nC          model (Ref. 5)\nC\nC       3. Replaced Tc equation using new solar indices (Ref. 1 and 2)\nC\nC       4. Replaced semiannual equation with new global model based\nC          on F10B (Ref. 1 and 3)\nC\nC       5. Added correction for local solar time and latitude errors\nC          (Ref. 1)\nC          Added smooth transition between altitude bands\nC\nC       6. Added high altitude ( z > 1500 km ) correction\nC          (Ref. 1 and 4)\nC\nC       7. REV A of JB2006 - Oct 2006\nC                Smoothing of density corrections and scale height\nC                through different altitude bands in the latitude-\nC                local time correction subroutine DTSUB\nC                dTx correction replaced with dTc correction\nC\nC     B. Modification to develop JB2008 model:\nC\nC       1. Replaced Tc equation in JB2006 using new solar indices\nC          (Ref. 7)\nC\nC       2. Replaced semiannual equation with new global model based\nC          on F10B and S10B (Ref. 6)\nC\nC       3. Use dTc value based on Dst geomagnetic storm index\nC          (This replaces ap use) (Ref. 7)\nC\nC\nC         All equation references below refer to the original\nC         Jacchia 1971 (CIRA 1972) model papers.\nC\nC\nC     References:\nC\nC      1. Bowman, Bruce R., etc. : \"A New Empirical Thermospheric\nC         Density Model JB2006 Using New Solar Indices\",\nC         AIAA/AAS Astrodynamics Specialists Conference, Keystone, CO,\nC         21-24 Aug 2006, (Paper AIAA 2006-6166).\nC\nC      2. Bowman, Bruce R., etc. : \"Improvements in Modeling\nC         Thermospheric Densities Using New EUV and FUV Solar Indices\",\nC         AAS/AIAA Space Flight Mechanics Meeting, Tampa, FL,\nC         23-26 Jan 2006, (Paper AAS 06-237).\nC\nC      3. Bowman, Bruce R.: \"The Semiannual Thermospheric Density\nC         Variation From 1970 to 2002 Between 200-1100 km\",\nC         AAS/AIAA Space Flight Mechanics Meeting, Maui, HI,\nC         8-12 Feb 2004, (Paper AAS 04-174).\nC\nC      4. Bowman, Bruce R.; \"Atmospheric Density Variations at\nC         1500 km to 4000 km Height Determined from Long Term\nC         Orbit Perturbation Analysis\", AAS/AIAA Space Flight\nC         Mechanics Meeting, Santa Barbara, CA, 11-14 Feb 2001,\nC         (Paper AAS 01-132).\nC\nC      5. Jacchia, Luigi G.; \"New Static Models of the\nC         Thermosphere and Exosphere with Empirical Temperature\nC         Profiles\", (Smithsonian Astrophysical Observatory\nC         Special Report 313), 6 May 1970.\nC\nC      6. Bowman, Bruce R., etc. : \"The Thermospheric Semiannual Density\nC         Response to Solar EUV Heating,\" JASTP, 2008\nC\nC      7. Bowman, Bruce R., etc. : \"A New Empirical Thermospheric\nC         Density Model JB2008 Using New Solar and Geomagnetic Indices\",\nC         AIAA/AAS 2008, COSPAR CIRA 2008 Model\nC\nC\nC\nC     Written by: Bruce R Bowman (HQ AFSPC, Space Analysis Division),\nC                 2008\nC\nC\nC\nC***********************************************************************\n\n      IMPLICIT REAL*8(A-H,O-Z)\n      IMPLICIT INTEGER*4(I-N)\n\n      DIMENSION SUN(2), SAT(3), TEMP(2), AL10N(6), CHT(4)\n      DIMENSION ALN(6), ALPHA(5), AMW(6), FRAC(4), TC(4), WT(5)\n\nC     The alpha are the thermal diffusion coefficients in Eq. (6)\n\n      DATA ALPHA(1) /0.D0/\n      DATA ALPHA(2) /0.D0/\n      DATA ALPHA(3) /0.D0/\n      DATA ALPHA(4) /0.D0/\n      DATA ALPHA(5) /-0.38D0/\n\nC     AL10 is DLOG(10.0)\n\n      DATA AL10 /2.3025851D0/\n\nC     The AMW are the molecular weights in order: N2, O2, O, Ar, He & H\n\n      DATA AMW(1) /28.0134D0/\n      DATA AMW(2) /31.9988D0/\n      DATA AMW(3) /15.9994D0/\n      DATA AMW(4) /39.9480D0/\n      DATA AMW(5) /4.0026D0/\n      DATA AMW(6) /1.00797D0/\n\nC     AVOGAD is Avogadro's number in mks units (molecules/kmol)\n\n      DATA AVOGAD /6.02257D26/\n\n      DATA FOURPI /12.566371D0/\n      DATA TWOPI  /6.2831853D0/\n      DATA PI     /3.1415927D0/\n      DATA PIOV2  /1.5707963D0/\n      DATA PIOV4  /0.78539816D0/\n\nC     The FRAC are the assumed sea-level volume fractions in order:\nC     N2, O2, Ar, and He\n\n      DATA FRAC(1) /0.78110D0/\n      DATA FRAC(2) /0.20955D0/\n      DATA FRAC(3) /9.3400D-3/\n      DATA FRAC(4) /1.2890D-5/\n\nC     RSTAR is the universal gas-constant in mks units (joules/K/kmol)\n\n      DATA RSTAR /8314.32D0/\n\nC     The R# are values used to establish height step sizes in\nC     the regimes 90km to 105km, 105km to 500km and 500km upward.\n\n      DATA R1 /0.010D0/\n      DATA R2 /0.025D0/\n      DATA R3 /0.075D0/\n\nC     The WT are weights for the Newton-Cotes Five-Point Quad. formula\n\n      DATA WT(1) /0.311111111111111D0/\n      DATA WT(2) /1.422222222222222D0/\n      DATA WT(3) /0.533333333333333D0/\n      DATA WT(4) /1.422222222222222D0/\n      DATA WT(5) /0.311111111111111D0/\n\nC     The CHT are coefficients for high altitude density correction\n\n      DATA CHT /0.22D0,-0.20D-02,0.115D-02,-0.211D-05/\nC\n      DEGRAD  =   PI / 180.D0\nC\n      IDEBUG = 0\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,101) (SAT(I),I=1,3),F10,F10B,XM10B\n 101    FORMAT(' JB2008 - SAT,F10,F10B ',3F20.6,3F8.1)\n      ENDIF\nC\nC     Equation (14)\nC\n      FN = (F10B/240.)**(1./4.)\n      IF (FN.GT.1.) FN = 1.0\n      FSB = F10B*FN + S10B*(1.-FN)\n      TSUBC = 392.4D0 + 3.227D0*FSB + 0.298D0*(F10-F10B)\n     *                + 2.259D0*(S10-S10B) + 0.312D0*(XM10-XM10B)\n     *                + 0.178D0*(Y10-Y10B)\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,130) TSUBC,F10B,S10B,XM10B\n 130    FORMAT(' JB2008 - TSUBC',4F15.2)\n      ENDIF\nC\nC     Equation (15)\n\n      ETA =   0.5D0 * DABS(SAT(2) - SUN(2))\n      THETA = 0.5D0 * DABS(SAT(2) + SUN(2))\n\nC     Equation (16)\n\n      H = SAT(1) - SUN(1)\n      TAU = H - 0.64577182D0 + 0.10471976D0 * DSIN(H + 0.75049158D0)\nC\n      GLAT  = SAT(2)\n      ZHT   = SAT(3)\n      GLST  = H + PI\n      GLSTHR = (GLST/DEGRAD)*(24.D0/360.D0)\n      IF (GLSTHR.GE.24.D0) GLSTHR = GLSTHR - 24.D0\n      IF (GLSTHR.LT. 0.D0) GLSTHR = GLSTHR + 24.D0\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,131) ETA,THETA,TAU\n 131    FORMAT(' JB2008 - ETA,THETA,TAU',3D25.12)\n      ENDIF\nC\nC     Equation (17)\n\n      C = DCOS(ETA)**2.5\n      S = DSIN(THETA)**2.5\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,132) C,S\n 132    FORMAT(' JB2008 - C,S',2D25.12)\n      ENDIF\nC\n      DF = S + (C - S) * DABS(DCOS(0.5 * TAU))**3\n      TSUBL = TSUBC * (1.D0 + 0.31D0 * DF)\n\nC     Compute correction to dTc for local solar time and lat correction\nC\n      CALL DTSUB (F10,GLSTHR,GLAT,ZHT,DTCLST)\nC\n      IF (IDEBUG.EQ.2) THEN\n        WRITE(8,133) SAT(3),DTCLST\n 133    FORMAT(' HT,DTCLST ',2F10.1)\n      ENDIF\nC\nC     Compute the local exospheric temperature.\nC     Add geomagnetic storm effect from input dTc value\n\n      TEMP(1) = TSUBL + DSTDTC\n      TINF    = TSUBL + DSTDTC + DTCLST\n\nC     Equation (9)\n\n      TSUBX = 444.3807D0 + 0.02385D0 * TINF - 392.8292D0 *\n     >        DEXP(-0.0021357D0 * TINF)\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,142) TINF,TSUBX,CAPPHI\n 142    FORMAT(' JB2008 - TINF,TSUBX,CAPPHI',3D20.8)\n      ENDIF\nC\nC     Equation (11)\n\n      GSUBX = 0.054285714D0 * (TSUBX - 183.D0)\n\nC     The TC array will be an argument in the call to\nC     XLOCAL, which evaluates Equation (10) or Equation (13)\n\n      TC(1) = TSUBX\n      TC(2) = GSUBX\n\nC     A AND GSUBX/A OF Equation (13)\n\n      TC(3) = (TINF - TSUBX)/PIOV2\n      TC(4) = GSUBX/TC(3)\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,123) TC\n 123    FORMAT(' JB2008 - TC',4F20.6)\n      ENDIF\nC\nC     Equation (5)\n\n      Z1 = 90.D0\n      Z2 = DMIN1(SAT(3),105.D0)\n      AL = DLOG(Z2/Z1)\n      N = IDINT(AL/R1) + 1\n      ZR = DEXP(AL/DFLOAT(N))\n      AMBAR1 = XAMBAR(Z1)\n      TLOC1 = XLOCAL(Z1,TC)\n      ZEND = Z1\n      SUM2 = 0.D0\n      AIN = AMBAR1 * XGRAV(Z1)/TLOC1\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,163) ZR,AMBAR1,TLOC1,AIN\n 163    FORMAT(' JB2008 - ZR-AIN',4D20.8)\n      ENDIF\nC\n      DO 2 I = 1,N\n        Z = ZEND\n        ZEND = ZR * Z\n        DZ = 0.25D0 * (ZEND-Z)\n        SUM1 = WT(1)*AIN\n        DO 1 J = 2,5\n          Z = Z + DZ\n          AMBAR2 = XAMBAR(Z)\n          TLOC2 = XLOCAL(Z,TC)\n          GRAVL = XGRAV(Z)\n          AIN = AMBAR2 * GRAVL/TLOC2\nC\nC     IF (IDEBUG.EQ.1) THEN\nC       WRITE(8,168) I,J,SUM1,TLOC2\nC168    FORMAT(' JB2008 - SUM1,TLOC2',2I4,2D20.8)\nC     ENDIF\nC\n    1 SUM1 = SUM1 + WT(J) * AIN\n    2 SUM2 = SUM2 + DZ * SUM1\n\n      FACT1 = 1000.0/RSTAR\n      RHO = 3.46D-6 * AMBAR2 * TLOC1 * DEXP(-FACT1*SUM2) /AMBAR1 /TLOC2\n\nC     Equation (2)\n\n      ANM = AVOGAD * RHO\n      AN  = ANM/AMBAR2\n\nC     Equation (3)\n\n      FACT2  = ANM/28.960D0\n      ALN(1) = DLOG(FRAC(1)*FACT2)\n      ALN(4) = DLOG(FRAC(3)*FACT2)\n      ALN(5) = DLOG(FRAC(4)*FACT2)\n\nC     Equation (4)\n\n      ALN(2) = DLOG(FACT2 * (1.D0 + FRAC(2)) - AN)\n      ALN(3) = DLOG(2.D0 * (AN - FACT2))\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,143) ALN\n 143    FORMAT(' JB2008 - ALN',6D20.8)\n      ENDIF\nC\n      IF (SAT(3) .GT. 105.D0) GO TO 3\n      TEMP(2) = TLOC2\n\nC     Put in negligible hydrogen for use in DO-LOOP 13\n\n      ALN(6) = ALN(5) - 25.D0\n      GO TO 11\n\nC     Equation (6)\n\n    3 Z3 = DMIN1(SAT(3),500.D0)\n      AL = DLOG(Z3/Z)\n      N = IDINT(AL/R2) + 1\n      ZR = DEXP(AL/DFLOAT(N))\n      SUM2 = 0.D0\n      AIN = GRAVL/TLOC2\n\n      DO 5 I = 1,N\n        Z = ZEND\n        ZEND = ZR * Z\n        DZ = 0.25D0 * (ZEND - Z)\n        SUM1 = WT(1) * AIN\n        DO 4 J = 2,5\n          Z = Z + DZ\n          TLOC3 = XLOCAL(Z,TC)\n          GRAVL = XGRAV(Z)\n          AIN = GRAVL/TLOC3\n    4   SUM1 = SUM1 + WT(J) * AIN\n    5 SUM2 = SUM2 + DZ * SUM1\nC\n      IF (IDEBUG.EQ.1) THEN\n        WRITE(8,124) SUM2,TLOC1,TLOC2,TLOC3\n 124    FORMAT(' JB2008 - SUM2,TLOC..',4D20.6)\n      ENDIF\nC\n      Z4 = DMAX1(SAT(3),500.D0)\n      AL = DLOG(Z4/Z)\n      R = R2\n      IF (SAT(3) .GT. 500.D0) R = R3\n      N = IDINT(AL/R) + 1\n      ZR = DEXP(AL/DFLOAT(N))\n      SUM3 = 0.D0\n\n      DO 7 I=1,N\n        Z = ZEND\n        ZEND = ZR * Z\n        DZ = 0.25D0 * (ZEND - Z)\n        SUM1 = WT(1) * AIN\n        DO 6 J = 2,5\n          Z = Z + DZ\n          TLOC4 = XLOCAL(Z,TC)\n          GRAVL = XGRAV(Z)\n          AIN = GRAVL/TLOC4\n    6   SUM1 = SUM1 + WT(J) * AIN\n    7 SUM3 = SUM3 + DZ * SUM1\nC\n      IF(IDEBUG.EQ.1) THEN\n        WRITE(8,106) SUM3,TLOC4\n  106   FORMAT(' SUM3,TLOC4 ',D20.9,F16.5)\n      ENDIF\nC\n      IF (SAT(3) .GT. 500.D0) GO TO 8\n      T500 = TLOC4\n      TEMP(2) = TLOC3\n      ALTR = DLOG(TLOC3/TLOC2)\n      FACT2 = FACT1 * SUM2\n      HSIGN = 1.D0\n      GO TO 9\n    8 T500 = TLOC3\n      TEMP(2) = TLOC4\n      ALTR = DLOG(TLOC4/TLOC2)\n      FACT2 = FACT1 * (SUM2 + SUM3)\n      HSIGN = -1.D0\n\n    9 DO 10 I = 1,5\n   10 ALN(I) = ALN(I) - (1.0 + ALPHA(I)) * ALTR - FACT2 * AMW(I)\nC     Equation (7) - Note that in CIRA72, AL10T5 = DLOG10(T500)\nC\n      IF(IDEBUG.EQ.1) THEN\n        WRITE(8,149) ALTR,FACT2\n  149   FORMAT(' JB2008 ALTR,FACT2 ',2D20.8)\n      ENDIF\nC\nC\n      AL10T5 = DLOG10(TINF)\n      ALNH5 = (5.5D0 * AL10T5 - 39.40D0) * AL10T5 + 73.13D0\n      ALN(6) = AL10 * (ALNH5 + 6.D0) + HSIGN * (DLOG(TLOC4/TLOC3)\n     >       + FACT1 * SUM3 * AMW(6))\nC\n      IF(IDEBUG.EQ.1) THEN\n        WRITE(8,146) ALN\n  146   FORMAT(' JB2008 ALN ',6D20.8)\n      ENDIF\nC\n   11 CONTINUE\n\nC     Equation (24)  - J70 Seasonal-Latitudinal Variation\nC\n      TRASH = (AMJD - 36204.D0) / 365.2422D0\n      CAPPHI = DMOD(TRASH,1.D0)\nC\n      DLRSL = 0.02D0 * (SAT(3) - 90.D0)\n     >      * DEXP(-0.045D0 * (SAT(3) - 90.D0))\n     >      * DSIGN(1.D0,SAT(2)) * DSIN(TWOPI * CAPPHI+ 1.72D0)\n     >      * DSIN(SAT(2))**2\nC\nC     Equation (23) - Computes the semiannual variation\nC\n      DLRSA = 0.D0\n      IF (Z.LT.2000.) THEN\n        D1950 = AMJD - 33281.D0\n        CALL TMOUTD (D1950,IYR,YRDAY)\nC       Use new semiannual model\n        CALL SEMIAN08 (YRDAY,ZHT,F10B,S10B,XM10B,FZZ,GTZ,DLRSA)\nC\n        IF (FZZ.LT.0.0D0) DLRSA   = 0.D0\n      ENDIF\nC\nC\n      IF(IDEBUG.EQ.1) THEN\n        WRITE(8,147) DLRSL, DLRSA\n  147   FORMAT(' JB2008 DLRSL',2D20.8)\n      ENDIF\nC\nC\nC     Sum the delta-log-rhos and apply to the number densities.\nC     In CIRA72 the following equation contains an actual sum,\nC     namely DLR = AL10 * (DLRGM + DLRSA + DLRSL)\nC     However, for Jacchia 70, there is no DLRGM or DLRSA.\n\n      DLR = AL10 * (DLRSL + DLRSA)\n\n      DO 12 I = 1,6\n   12 ALN(I) = ALN(I) + DLR\n\nC     Compute mass-density and mean-molecular-weight and\nC     convert number density logs from natural to common.\n\n      SUMN = 0.D0\n      SUMNM = 0.D0\n\n      DO 13 I = 1,6\n        AN = DEXP(ALN(I))\n        SUMN = SUMN + AN\n        SUMNM = SUMNM + AN*AMW(I)\n        AL10N(I) = ALN(I)/AL10\n        IF(IDEBUG.EQ.1) THEN\n          XVAL = 10.D0**AL10N(I)\n          WRITE (8,100) I,SUMNM,XVAL,ALN(I)\n 100      FORMAT(' JB2008 I,SUMN,XVAL,ALN ',I5,3D20.9)\n        ENDIF\n   13 CONTINUE\n\n      RHO = SUMNM/AVOGAD\n\nC     Compute the high altitude exospheric density correction factor\n\n      FEX = 1.D0\nC\n      IF ((ZHT.GE.1000.D0).AND.(ZHT.LT.1500.D0)) THEN\n        ZETA   = (ZHT - 1000.D0) * 0.002D0\n        ZETA2  =  ZETA * ZETA\n        ZETA3  =  ZETA * ZETA2\n        F15C   = CHT(1) + CHT(2)*F10B + CHT(3)*1500.D0\n     *                  + CHT(4)*F10B*1500.D0\n        F15C_ZETA = (CHT(3) + CHT(4)*F10B) * 500.D0\n        FEX2   = 3.D0 * F15C - F15C_ZETA - 3.D0\n        FEX3   = F15C_ZETA - 2.D0 * F15C + 2.D0\n        FEX    = 1.D0 + FEX2 * ZETA2 + FEX3 * ZETA3\n      ENDIF\n      IF (ZHT .GE. 1500.D0) THEN\n        FEX    = CHT(1) + CHT(2)*F10B + CHT(3)*ZHT + CHT(4)*F10B*ZHT\n      ENDIF\n\nC     Apply the exospheric density correction factor.\n\n      RHO    = FEX * RHO\n\nC\n      IF(IDEBUG.EQ.1) THEN\n        WRITE (8,160) RHO\n 160    FORMAT(' JB2008 RHO ',D20.8,F10.4)\n      ENDIF\nC\n      RETURN\n      END\n\nC***********************************************************************\n\n      DOUBLE PRECISION FUNCTION XAMBAR(Z)\n\nC     Evaluates Equation (1)\n\n      IMPLICIT REAL*8(A-H,O-Z)\n\n      DIMENSION C(7)\n\n      DATA C(1) /28.15204D0/\n      DATA C(2) /-8.5586D-2/\n      DATA C(3) /+1.2840D-4/\n      DATA C(4) /-1.0056D-5/\n      DATA C(5) /-1.0210D-5/\n      DATA C(6) /+1.5044D-6/\n      DATA C(7) /+9.9826D-8/\n\n      DZ = Z - 100.D0\n      AMB = C(7)\n      DO 1 I = 1,6\n      J = 7-I\n    1 AMB = DZ * AMB + C(J)\n      XAMBAR = AMB\n      RETURN\n      END\n\nC***********************************************************************\n\n      DOUBLE PRECISION FUNCTION XGRAV(Z)\n\nC     Evaluates Equation (8)\n\n      IMPLICIT REAL*8(A-H,O-Z)\n\n      XGRAV = 9.80665D0/(1.D0 + Z/6356.766D0)**2\n      RETURN\n      END\n\nC***********************************************************************\n\n      DOUBLE PRECISION FUNCTION XLOCAL(Z,TC)\n\nC     Evaluates Equation (10) or Equation (13), depending on Z\n\n      IMPLICIT REAL*8(A-H,O-Z)\n\n      DIMENSION TC(4)\n\n      DZ = Z - 125.D0\n      IF (DZ .GT. 0.D0) GO TO 1\n\n      XLOCAL = ((-9.8204695D-6 * DZ - 7.3039742D-4) * DZ**2 + 1.0)\n     >       * DZ * TC(2) + TC(1)\n      RETURN\n 1    XLOCAL = TC(1) + TC(3) * DATAN(TC(4)*DZ*(1.D0 + 4.5D-6*DZ**2.5))\n      RETURN\n      END\n\nC***********************************************************************\n\n      SUBROUTINE DTSUB (F10,XLST,XLAT,ZHT,DTC)\nC\nC     COMPUTE dTc correction for Jacchia-Bowman model\nC\nC        Calling Args:\nC        ------------\nC        F10       = (I)   F10 FLUX\nC        XLST      = (I)   LOCAL SOLAR TIME (HOURS 0-23.999)\nC        XLAT      = (I)   XLAT = SAT LAT (RAD)\nC        ZHT       = (I)   ZHT = HEIGHT (KM)\nC        DTC       = (O)   dTc correction\nC\n      IMPLICIT REAL*8(A-H,O-Z)\nC\n      DIMENSION B(19),C(23)\nC\n      DATA B /\nC\n     1       -0.457512297D+01, -0.512114909D+01, -0.693003609D+02,\n     2        0.203716701D+03,  0.703316291D+03, -0.194349234D+04,\n     3        0.110651308D+04, -0.174378996D+03,  0.188594601D+04,\n     4       -0.709371517D+04,  0.922454523D+04, -0.384508073D+04,\n     5       -0.645841789D+01,  0.409703319D+02, -0.482006560D+03,\n     6        0.181870931D+04, -0.237389204D+04,  0.996703815D+03,\n     7        0.361416936D+02/\nC\n      DATA C /\nC\n     1       -0.155986211D+02, -0.512114909D+01, -0.693003609D+02,\n     2        0.203716701D+03,  0.703316291D+03, -0.194349234D+04,\n     3        0.110651308D+04, -0.220835117D+03,  0.143256989D+04,\n     4       -0.318481844D+04,  0.328981513D+04, -0.135332119D+04,\n     5        0.199956489D+02, -0.127093998D+02,  0.212825156D+02,\n     6       -0.275555432D+01,  0.110234982D+02,  0.148881951D+03,\n     7       -0.751640284D+03,  0.637876542D+03,  0.127093998D+02,\n     8       -0.212825156D+02,  0.275555432D+01/\nC\nC\n      DTC = 0.D0\nC\n      tx  = XLST/24.D0\n      ycs = DCOS(XLAT)\n      F   = (F10 - 100.D0)/100.D0\nC\nC         calculates dTc\nC\n      IF (ZHT.GE.120.0.AND.ZHT.LE.200.0) THEN\n        H = (ZHT - 200.D0)/50.D0\n        DTC200 =\n     1    + C(17)             + C(18)*tx*ycs      + C(19)*tx**2*ycs\n     2    + C(20)*tx**3*ycs   + C(21)*F*ycs       + C(22)*tx*F*ycs\n     3    + C(23)*tx**2*F*ycs\n        sum = C(1) + B(2)*F + C(3)*tx*F     + C(4)*tx**2*F\n     1    + C(5)*tx**3*F    + C(6)*tx**4*F    + C(7)*tx**5*F\n     2    + C(8)*tx*ycs     + C(9)*tx**2*ycs  + C(10)*tx**3*ycs\n     3    + C(11)*tx**4*ycs + C(12)*tx**5*ycs + C(13)*ycs\n     4    + C(14)*F*ycs     + C(15)*tx*F*ycs  + C(16)*tx**2*F*ycs\n        DTC200DZ = SUM\n        CC  = 3.*DTC200 - DTC200DZ\n        DD  = DTC200 - CC\n        ZP  = (ZHT-120.)/80.D0\n        DTC = CC*ZP*ZP + DD*ZP*ZP*ZP\n      ENDIF\nC\nC\n      IF (ZHT.GT.200.0.AND.ZHT.LE.240.0) THEN\n        H = (ZHT - 200.D0)/50.D0\n        sum = C(1)*H + B(2)*F*H + C(3)*tx*F*H     + C(4)*tx**2*F*H\n     1    + C(5)*tx**3*F*H    + C(6)*tx**4*F*H    + C(7)*tx**5*F*H\n     2    + C(8)*tx*ycs*H     + C(9)*tx**2*ycs*H  + C(10)*tx**3*ycs*H\n     3    + C(11)*tx**4*ycs*H + C(12)*tx**5*ycs*H + C(13)*ycs*H\n     4    + C(14)*F*ycs*H     + C(15)*tx*F*ycs*H  + C(16)*tx**2*F*ycs*H\n     5    + C(17)             + C(18)*tx*ycs      + C(19)*tx**2*ycs\n     6    + C(20)*tx**3*ycs   + C(21)*F*ycs       + C(22)*tx*F*ycs\n     7    + C(23)*tx**2*F*ycs\n        DTC = sum\n      ENDIF\nC\nC\n      IF (ZHT.GT.240.0.AND.ZHT.LE.300.0) THEN\n        H = (40.D0)/50.D0\n        sum = C(1)*H + B(2)*F*H + C(3)*tx*F*H     + C(4)*tx**2*F*H\n     1    + C(5)*tx**3*F*H    + C(6)*tx**4*F*H    + C(7)*tx**5*F*H\n     2    + C(8)*tx*ycs*H     + C(9)*tx**2*ycs*H  + C(10)*tx**3*ycs*H\n     3    + C(11)*tx**4*ycs*H + C(12)*tx**5*ycs*H + C(13)*ycs*H\n     4    + C(14)*F*ycs*H     + C(15)*tx*F*ycs*H  + C(16)*tx**2*F*ycs*H\n     5    + C(17)             + C(18)*tx*ycs      + C(19)*tx**2*ycs\n     6    + C(20)*tx**3*ycs   + C(21)*F*ycs       + C(22)*tx*F*ycs\n     7    + C(23)*tx**2*F*ycs\n        AA = SUM\n        BB = C(1) + B(2)*F  + C(3)*tx*F       + C(4)*tx**2*F\n     1    + C(5)*tx**3*F    + C(6)*tx**4*F    + C(7)*tx**5*F\n     2    + C(8)*tx*ycs     + C(9)*tx**2*ycs  + C(10)*tx**3*ycs\n     3    + C(11)*tx**4*ycs + C(12)*tx**5*ycs + C(13)*ycs\n     4    + C(14)*F*ycs     + C(15)*tx*F*ycs  + C(16)*tx**2*F*ycs\n        H   = 300./100.D0\n        sum = B(1)    + B(2)*F  + B(3)*tx*F         + B(4)*tx**2*F\n     1      + B(5)*tx**3*F      + B(6)*tx**4*F      + B(7)*tx**5*F\n     2      + B(8)*tx*ycs       + B(9)*tx**2*ycs    + B(10)*tx**3*ycs\n     3      + B(11)*tx**4*ycs   + B(12)*tx**5*ycs   + B(13)*H*ycs\n     4      + B(14)*tx*H*ycs    + B(15)*tx**2*H*ycs + B(16)*tx**3*H*ycs\n     5      + B(17)*tx**4*H*ycs + B(18)*tx**5*H*ycs + B(19)*ycs\n        DTC300 = SUM\n        sum = B(13)*ycs\n     1      + B(14)*tx*ycs    + B(15)*tx**2*ycs + B(16)*tx**3*ycs\n     2      + B(17)*tx**4*ycs + B(18)*tx**5*ycs\n        DTC300DZ = SUM\n        CC = 3.*DTC300 - DTC300DZ - 3.*AA - 2.*BB\n        DD = DTC300 - AA - BB - CC\n        ZP  = (ZHT-240.)/60.D0\n        DTC = AA + BB*ZP + CC*ZP*ZP + DD*ZP*ZP*ZP\n      ENDIF\nC\nC\n      IF (ZHT.GT.300.0.AND.ZHT.LE.600.0) THEN\n        H   = ZHT/100.D0\n        sum = B(1)    + B(2)*F  + B(3)*tx*F         + B(4)*tx**2*F\n     1      + B(5)*tx**3*F      + B(6)*tx**4*F      + B(7)*tx**5*F\n     2      + B(8)*tx*ycs       + B(9)*tx**2*ycs    + B(10)*tx**3*ycs\n     3      + B(11)*tx**4*ycs   + B(12)*tx**5*ycs   + B(13)*H*ycs\n     4      + B(14)*tx*H*ycs    + B(15)*tx**2*H*ycs + B(16)*tx**3*H*ycs\n     5      + B(17)*tx**4*H*ycs + B(18)*tx**5*H*ycs + B(19)*ycs\n        DTC = sum\n      ENDIF\nC\nC\n      IF (ZHT.GT.600.0.AND.ZHT.LE.800.0) THEN\n        ZP = (ZHT - 600.D0)/100.\n        HP = 600.D0/100.D0\n        AA  = B(1)    + B(2)*F  + B(3)*tx*F         + B(4)*tx**2*F\n     1      + B(5)*tx**3*F      + B(6)*tx**4*F      + B(7)*tx**5*F\n     2      + B(8)*tx*ycs       + B(9)*tx**2*ycs    + B(10)*tx**3*ycs\n     3      + B(11)*tx**4*ycs   + B(12)*tx**5*ycs   + B(13)*HP*ycs\n     4      + B(14)*tx*HP*ycs   + B(15)*tx**2*HP*ycs+ B(16)*tx**3*HP*ycs\n     5      + B(17)*tx**4*HP*ycs + B(18)*tx**5*HP*ycs + B(19)*ycs\n        BB  = B(13)*ycs\n     1      + B(14)*tx*ycs    + B(15)*tx**2*ycs + B(16)*tx**3*ycs\n     2      + B(17)*tx**4*ycs + B(18)*tx**5*ycs\n        CC  = -(3.*AA+4.*BB)/4.\n        DD  = (AA+BB)/4.\n        DTC = AA + BB*ZP + CC*ZP*ZP + DD*ZP*ZP*ZP\n      ENDIF\nC\n      RETURN\n      END SUBROUTINE DTSUB\nC\nC******************************************************************\nC\n      SUBROUTINE SEMIAN08 (DAY,HT,F10B,S10B,XM10B,FZZ,GTZ,DRLOG)\nC\nC     COMPUTE SEMIANNUAL VARIATION (DELTA LOG RHO)\nC     INPUT DAY, HEIGHT, F10B, S10B, M10B FSMB\nC           025.  650.   150.  148.  147. 151.\nC     OUTPUT FUNCTIONS FZ, GT, AND DEL LOG RHO VALUE\nC\nC     DAY     (I)   DAY OF YEAR\nC     HT      (I)   HEIGHT (KM)\nC     F10B    (I)   AVE 81-DAY CENTERED F10\nC     S10B    (I)   AVE 81-DAY CENTERED S10\nC     XM10B   (I)   AVE 81-DAY CENTERED M10\nC     FZZ     (O)   SEMIANNUAL AMPLITUDE\nC     GTZ     (O)   SEMIANNUAL PHASE FUNCTION\nC     DRLOG   (O)   DELTA LOG RHO\nC\n      IMPLICIT REAL*8(A-H,O-Z)\nC\n      REAL*8 FZM(5),GTM(10)\nC\n      DATA TWOPI/6.2831853072D0/\nC\nC     FZ GLOBAL MODEL VALUES\nC     1997-2006 FIT:\n      DATA FZM /\n     1   0.2689D+00,-0.1176D-01, 0.2782D-01,\n     2  -0.2782D-01, 0.3470D-03/\nC\nC     GT GLOBAL MODEL VALUES\nC     1997-2006 FIT:\n      DATA GTM /\n     1  -0.3633D+00, 0.8506D-01, 0.2401D+00,-0.1897D+00,\n     2  -0.2554D+00,-0.1790D-01, 0.5650D-03,-0.6407D-03,\n     3  -0.3418D-02,-0.1252D-02/\nC\nC\nC     COMPUTE NEW 81-DAY CENTERED SOLAR INDEX FOR FZ\n      FSMB  = 1.00*F10B - 0.70*S10B - 0.04*XM10B\nC\n      HTZ = HT/1000.D0\nC\n      FZZ = FZM(1) + FZM(2)*FSMB  + FZM(3)*FSMB*HTZ\n     *    + FZM(4)*FSMB*HTZ**2    + FZM(5)*FSMB**2*HTZ\nC\nC\nC     COMPUTE DAILY 81-DAY CENTERED SOLAR INDEX FOR GT\n      FSMB  = 1.00*F10B - 0.75*S10B - 0.37*XM10B\nC\n      TAU   = (DAY-1.D0)/365.D0\n      SIN1P = DSIN(TWOPI*TAU)\n      COS1P = DCOS(TWOPI*TAU)\n      SIN2P = DSIN(2.*TWOPI*TAU)\n      COS2P = DCOS(2.*TWOPI*TAU)\nC\n      GTZ = GTM(1) + GTM(2)*SIN1P + GTM(3)*COS1P\n     1             + GTM(4)*SIN2P + GTM(5)*COS2P\n     2             + GTM(6)*FSMB\n     3             + GTM(7)*FSMB*SIN1P + GTM( 8)*FSMB*COS1P\n     4             + GTM(9)*FSMB*SIN2P + GTM(10)*FSMB*COS2P\nC\n      IF (FZZ.LT.1.D-6) FZZ = 1.D-6\nC\n      DRLOG = FZZ*GTZ\nC\n      RETURN\n      END SUBROUTINE SEMIAN08\nC\nC******************************************************************\nC\n      SUBROUTINE TMOUTD(D1950,IYR,DAY)\nC\nC     COMPUTE DAY AND YEAR FROM TIME D1950 (DAYS SINCE 1950)\nC\n      IMPLICIT REAL*8(A-H,O-Z)\nC\n      IYDAY = D1950\n      FRAC = D1950 - IYDAY\n      IYDAY = IYDAY + 364\n      ITEMP = IYDAY/1461\n      IYDAY = IYDAY - ITEMP*1461\n      IYR = 1949 + 4*ITEMP\n      ITEMP = IYDAY/365\n      IF (ITEMP.GE.3) ITEMP = 3\n      IYR = IYR + ITEMP\n      IYDAY = IYDAY - 365*ITEMP + 1\n      IYR = IYR - 1900\n      DAY = IYDAY + FRAC\n      IF (IYR.GE.100) IYR = IYR - 100\nC\n      RETURN\n      END SUBROUTINE TMOUTD\n"
  },
  {
    "path": "source/external/jb2008/README.txt",
    "content": "The Jacchia-Bowman 2008 Empirical Thermospheric Density Model\n(http://sol.spacenvironment.net/jb2008/index.html)\n\nFORTRAN source code can be downloaded at:\nhttp://sol.spacenvironment.net/jb2008/code.html\n\nImproved versions of JB2008 solar indices (SOLFSMY.TXT) and\ngeomagnetic storm indices (DTCFILE.TXT) are used as input.\n\nBoth indices (SOLFSMY.TXT and DTCFILE.TXT) are updated daily and can be downloaded at:\nhttp://sol.spacenvironment.net/jb2008/indices.html\n\n"
  },
  {
    "path": "source/external/jb2008/jb2008.h",
    "content": "/***********************************************/\n/**\n* @file jb2008.h\n*\n* @brief Fortran Wrapper.\n*\n* @author Beate Klinger\n* @date   2015-12-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_JB2008MODEL__\n#define __GROOPS_JB2008MODEL__\n\n#include \"external/fortran.h\"\n\n#define jb2008 FORTRANCALL(jb2008, JB2008)\n\nextern \"C\" void jb2008(const F77Double &AMJD, const F77Double SUN[2], const F77Double SAT[3],\n                       const F77Double &F10,  const F77Double &F10B,\n                       const F77Double &S10,  const F77Double &S10B,\n                       const F77Double &M10,  const F77Double &M10B,\n                       const F77Double &Y10,  const F77Double &Y10B,\n                       const F77Double &DSTDTC,\n                       F77Double TEMP[2], F77Double &RHO);\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/external/lapack/blas.h",
    "content": "/***********************************************/\n/**\n* @file blas.h\n*\n* @brief BLAS Wrapper fur C.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-12-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_BLAS__\n#define __GROOPS_BLAS__\n\n#include \"external/fortran.h\"\n\n/***** DEFINES *********************************/\n\n#define blas_dswap   FORTRANCALL(dswap     , DSWAP     )\n#define blas_dscal   FORTRANCALL(dscal     , DSCAL     )\n#define blas_dcopy   FORTRANCALL(dcopy     , DCOPY     )\n#define blas_daxpy   FORTRANCALL(daxpy     , DAXPY     )\n#define blas_ddot    FORTRANCALL(ddot      , DDOT      )\n#define blas_dgemv   FORTRANCALL(wrapdgemv , WRAPDGEMV )\n#define blas_dsymv   FORTRANCALL(wrapdsymv , WRAPDSYMV )\n#define blas_dtrmv   FORTRANCALL(wrapdtrmv , WRAPDTRMV )\n#define blas_dtrsv   FORTRANCALL(wrapdtrsv , WRAPDTRSV )\n#define blas_dgemm   FORTRANCALL(wrapdgemm , WRAPDGEMM )\n#define blas_dsymm   FORTRANCALL(wrapdsymm , WRAPDSYMM )\n#define blas_dtrmm   FORTRANCALL(wrapdtrmm , WRAPDTRMM )\n#define blas_dtrsm   FORTRANCALL(wrapdtrsm , WRAPDTRSM )\n#define blas_dsyrk   FORTRANCALL(wrapdsyrk , WRAPDSYRK )\n#define blas_dsyr2k  FORTRANCALL(wrapdsyr2k, WRAPDSYR2K)\n\nextern \"C\"\n{\nvoid   blas_dswap (const F77Int &n,                         const F77Double x[], const F77Int &incx, F77Double y[], const F77Int &inxy);\nvoid   blas_dscal (const F77Int &n, const F77Double &alpha,       F77Double x[], const F77Int &incx);\nvoid   blas_dcopy (const F77Int &n,                         const F77Double x[], const F77Int &incx, F77Double y[], const F77Int &inxy);\nvoid   blas_daxpy (const F77Int &n, const F77Double &alpha, const F77Double x[], const F77Int &incx, F77Double y[], const F77Int &inxy);\nDouble blas_ddot  (const F77Int &n, const F77Double x[], const F77Int &incx, const F77Double y[], const F77Int &incy);\nvoid   blas_dgemv (const F77Bool &trans,  const F77Int  &m, const F77Int &n, const F77Double &alpha, const F77Double A[], const F77Int &ldA, const F77Double x[], const F77Int &incx, const F77Double &beta, F77Double y[], const F77Int &incy);\nvoid   blas_dsymv (const F77Bool &upper,  const F77Int  &n, const F77Double &alpha, const F77Double A[], const F77Int &ldA, const F77Double x[], const F77Int &incx, const F77Double &beta, F77Double y[], const F77Int &incy);\nvoid   blas_dtrmv (const F77Bool &upper,  const F77Bool &trans,  const F77Bool &unitDiag, const F77Int &n, const F77Double A[], const F77Int &ldA, F77Double x[], const F77Int &incx);\nvoid   blas_dtrsv (const F77Bool &upper,  const F77Bool &trans,  const F77Bool &unitDiag, const F77Int &n, const F77Double A[], const F77Int &ldA, F77Double x[], const F77Int &incx);\nvoid   blas_dgemm (const F77Bool &transA, const F77Bool &transB, const F77Int  &m, const F77Int &n, const F77Int &k, const F77Double &alpha, const F77Double A[], const F77Int &ldA, const F77Double B[], const F77Int &ldB, const F77Double &beta, F77Double C[], const F77Int &ldC);\nvoid   blas_dsymm (const F77Bool &left,   const F77Bool &upper,  const F77Int  &m, const F77Int &n,                   const F77Double &alpha, const F77Double A[], const F77Int &ldA, const F77Double B[], const F77Int &ldB, const F77Double &beta, F77Double C[], const F77Int &ldC);\nvoid   blas_dtrmm (const F77Bool &left,   const F77Bool &upper,  const F77Bool &trans, const F77Bool &unitDiag, const F77Int &m, const F77Int &n, const F77Double &alpha, const F77Double A[], const F77Int &ldA, F77Double B[], const F77Int &ldB);\nvoid   blas_dtrsm (const F77Bool &left,   const F77Bool &upper,  const F77Bool &trans, const F77Bool &unitDiag, const F77Int &m, const F77Int &n, const F77Double &alpha, const F77Double A[], const F77Int &ldA, F77Double B[], const F77Int &ldB);\nvoid   blas_dsyrk (const F77Bool &upper,  const F77Bool &trans,  const F77Int  &n, const F77Int &k, const F77Double &alpha, const F77Double A[], const F77Int &ldA, const F77Double &beta, F77Double C[], const F77Int &ldC);\nvoid   blas_dsyr2k(const F77Bool &upper,  const F77Bool &trans,  const F77Int  &n, const F77Int &k, const F77Double &alpha, const F77Double A[], const F77Int &ldA, const F77Double B[], const F77Int &ldB, const F77Double &beta, F77Double C[], const F77Int &ldC);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/external/lapack/blasWrapper.f",
    "content": "c\nc *******************************************\nc\n      subroutine wrapdgemv(trans,m,n,alpha,A,ldA,x,incx,beta,y,incy)\n      logical*1 trans\n      character tr\n      external dgemv\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      call dgemv(tr,m,n,alpha,A,ldA,x,incx,beta,y,incy)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdsymv(upper,n,alpha,A,ldA,x,incx,beta,y,incy)\n      logical*1 upper\n      character uplo\n      external dsymv\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dsymv(uplo,n,alpha,A,ldA,x,incx,beta,y,incy)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdtrmv(upper,trans,diag,n,A,ldA,x,incx)\n      external dtrmv\n      logical*1 upper, trans, diag\n      character uplo,  tr,    diago\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      if(.not.diag) then\n        diago = 'N'\n      else\n        diago = 'U'\n      endif\n      call dtrmv(uplo,tr,diago,n,A,ldA,x,incx)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdtrsv(upper,trans,diag,n,A,ldA,x,incx)\n      external dtrsv\n      logical*1 upper, trans, diag\n      character uplo,  tr,    diago\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      if(.not.diag) then\n        diago = 'N'\n      else\n        diago = 'U'\n      endif\n      call dtrsv(uplo,tr,diago,n,A,ldA,x,incx);\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgemm(transA,transB,m,n,k,alpha,\n     $                     A,ldA,B,ldB,beta,C,ldC)\n      external dgemm\n      logical*1 transA, transB\n      character trA, trB\n      if(.not.transA) then\n        trA = 'N'\n      else\n        trA = 'T'\n      endif\n      if(.not.transB) then\n        trB = 'N'\n      else\n        trB = 'T'\n      endif\n      call dgemm(trA,trB,m,n,k,alpha,A,ldA,B,ldB,beta,C,ldC)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdsymm(left,upper,m,n,alpha,A,ldA,B,ldB,beta,C,ldC)\n      external dsymm\n      logical*1 left, upper\n      character side, uplo\n      if(.not.left) then\n        side = 'R'\n      else\n        side = 'L'\n      endif\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dsymm(side,uplo,m,n,alpha,A,ldA,B,ldB,beta,C,ldC)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdtrmm(left,upper,trans,diag,m,n,alpha,A,ldA,B,ldB)\n      external dtrmm\n      logical*1 left, upper, trans, diag\n      character side, uplo,  tr,    diago\n      if(.not.left) then\n        side = 'R'\n      else\n        side = 'L'\n      endif\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      if(.not.diag) then\n        diago = 'N'\n      else\n        diago = 'U'\n      endif\n      call dtrmm(side,uplo,tr,diago,m,n,alpha,A,ldA,B,ldB)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdtrsm(left,upper,trans,diag,m,n,alpha,A,ldA,B,ldB)\n      external dtrsm\n      logical*1 left, upper, trans, diag\n      character side, uplo,  tr,    diago\n      if(.not.left) then\n        side = 'R'\n      else\n        side = 'L'\n      endif\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      if(.not.diag) then\n        diago = 'N'\n      else\n        diago = 'U'\n      endif\n      call dtrsm(side,uplo,tr,diago,m,n,alpha,A,ldA,B,ldB)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdsyrk(upper,trans,n,k,alpha,A,ldA,beta,C,ldC)\n      external dsyrk\n      logical*1 upper, trans\n      character uplo, tr\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      call dsyrk(uplo,tr,n,k,alpha,A,ldA,beta,C,ldC)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdsyr2k(upper,trans,n,k,alpha,A,ldA,\n     $                      B,ldB,beta,C,ldC)\n      external dsyr2k\n      logical*1 upper, trans\n      character uplo, tr\n      if(.not.upper) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(.not.trans) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      call dsyr2k(uplo,tr,n,k,alpha,A,ldA,B,ldB,beta,C,ldC)\n      end\nc\nc *******************************************\nc\n"
  },
  {
    "path": "source/external/lapack/lapack.h",
    "content": "/***********************************************/\n/**\n* @file lapack.h\n*\n* LAPACK Wrapper.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-12-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LAPACK__\n#define __GROOPS_LAPACK__\n\n#include \"external/fortran.h\"\n\n/***** DEFINES *********************************/\n\n#define wrapdlacpy  FORTRANCALL(wrapdlacpy, WRAPDLACPY)\n#define wrapdpotrf  FORTRANCALL(wrapdpotrf, WRAPDPOTRF)\n#define wrapdpotri  FORTRANCALL(wrapdpotri, WRAPDPOTRI)\n#define wrapdpstrf  FORTRANCALL(wrapdpstrf, WRAPDPSTRF)\n#define wrapdtrtri  FORTRANCALL(wrapdtrtri, WRAPDTRTRI)\n#define wrapdlauum  FORTRANCALL(wrapdlauum, WRAPDLAUUM)\n#define wrapdgetrf  FORTRANCALL(wrapdgetrf, WRAPDGETRF)\n#define wrapdgesv   FORTRANCALL(wrapdgesv , WRAPDGESV )\n#define wrapdsgesv  FORTRANCALL(wrapdsgesv, WRAPDSGESV)\n#define wrapdgetri  FORTRANCALL(wrapdgetri, WRAPDGETRI)\n#define wrapdgels   FORTRANCALL(wrapdgels , WRAPDGELS )\n#define wrapdgeqrf  FORTRANCALL(wrapdgeqrf, WRAPDGEQRF)\n#define wrapdormqr  FORTRANCALL(wrapdormqr, WRAPDORMQR)\n#define wrapdorgqr  FORTRANCALL(wrapdorgqr, WRAPDORGQR)\n#define wrapdpbsv   FORTRANCALL(wrapdpbsv , WRAPDPBSV )\n#define wrapdpbtrf  FORTRANCALL(wrapdpbtrf, WRAPDPBTRF)\n#define wrapdgbtrf  FORTRANCALL(wrapdgbtrf, WRAPDGBTRF)\n#define wrapdtbtrs  FORTRANCALL(wrapdtbtrs, WRAPDTBTRS)\n#define wrapdgbtrs  FORTRANCALL(wrapdgbtrs, WRAPDGBTRS)\n#define wrapdsyev   FORTRANCALL(wrapdsyev,  WRAPDSYEV )\n#define wrapdgeev   FORTRANCALL(wrapdgeev , WRAPDGEEV )\n#define wrapdgesvd  FORTRANCALL(wrapdgesvd, WRAPDGESVD)\n#define wrapdgesdd  FORTRANCALL(wrapdgesdd, WRAPDGESDD)\n\n/***********************************************/\n\n// copy\nvoid lapack_dlacpy(UInt m, UInt n, const Double A[], UInt ldA, Double B[], UInt ldB);\n\n// Cholesky, Inverse\nInt lapack_dpotrf(Bool upper, UInt n, Double A[], UInt ldA);\nInt lapack_dpotri(Bool upper, UInt n, Double A[], UInt ldA);\nInt lapack_dtrtri(Bool upper, UInt n, Double A[], UInt ldA);\nInt lapack_dlaumm(Bool upper, UInt n, Double A[], UInt ldA);\n\n// LU-decomposition, Solve, Inverse\nInt lapack_dgetrf(UInt m, UInt n, Double A[], UInt ldA, F77Int ipiv[]);\nInt lapack_dgesv (UInt n, UInt nrhs, Double A[], UInt ldA, F77Int ipiv[], Double B[], UInt ldB);\nInt lapack_dsgesv(UInt n, UInt nrhs, Double A[], UInt ldA, F77Int ipiv[], Double B[], UInt ldB, Double X[], UInt ldX, Int iter);\nInt lapack_dgetri(UInt n, Double A[], UInt ldA, F77Int ipiv[]);\nInt lapack_dpstrf(Bool upper, UInt n, Double A[], UInt ldA, F77Int ipiv[], F77Int &rank, Double tol);\n\n// Least-Square\nInt lapack_dgels (Bool trans, UInt m, UInt n, UInt nrhs, Double A[], UInt ldA, Double B[], UInt ldB);\n\n// QR-decomposition\nInt lapack_dgeqrf(UInt m, UInt n, Double A[], UInt ldA, Double tau[]);\nInt lapack_dormqr(Bool left, Bool trans, UInt m, UInt n, UInt k, const Double A[], UInt ldA, const Double tau[], Double C[], UInt ldC);\nInt lapack_dorgqr(UInt m, UInt n, UInt k, Double A[], UInt ldA, const Double tau[]);\n\n// Band matrices\nInt lapack_dpbsv(Bool upper, UInt n, UInt kd, UInt nrhs, Double A[], UInt ldA, Double B[], UInt ldB);\nInt lapack_dpbtrf(Bool upper, UInt n, UInt kd, Double A[], UInt ldA);\nInt lapack_dgbtrf(UInt n, UInt m, UInt kl, UInt ku, Double A[], UInt ldA, F77Int ipiv[]);\nInt lapack_dtbtrs(Bool upper, Bool trans, Bool unitDiag, UInt n, UInt kd, UInt nrhs, const Double A[], UInt ldA, Double B[], UInt ldB);\nInt lapack_dgbtrs(Bool trans, UInt n, UInt kl, UInt ku, UInt nrhs, const Double A[], UInt ldA, F77Int ipiv[], Double B[], UInt ldB);\n\n// eigen value decomposition\nInt lapack_dsyev(Bool jobz, Bool upper, UInt n, Double A[], UInt ldA, Double W[]);\nInt lapack_dgeev(Bool jobvl, Bool jobvr, UInt n, Double A[], UInt ldA, Double WR[], Double WI[], Double VL[], UInt ldVL, Double VR[], UInt ldVR);\n\n// sigular value decomposition\nInt lapack_dgesvd(Bool jobu, Bool jobvt, UInt m, UInt n, Double A[], UInt ldA, Double S[], Double U[], UInt ldU, Double VT[], UInt ldvt);\nInt lapack_dgesdd(Bool jobz, UInt m, UInt n, Double A[], UInt ldA, Double S[], Double U[], UInt ldU, Double VT[], UInt ldvt);\n\n/***********************************************/\n/***********************************************/\n\nextern \"C\"\n{\nvoid wrapdlacpy(const F77Int &m, const F77Int &n, const F77Double A[], const F77Int &ldA, F77Double B[], const F77Int &ldB);\nvoid wrapdpotrf(const F77Int &upper, const F77Int &n, F77Double A[], const F77Int &ldA, F77Int &info);\nvoid wrapdpotri(const F77Int &upper, const F77Int &n, F77Double A[], const F77Int &ldA, F77Int &info);\nvoid wrapdpstrf(const F77Int &upper, const F77Int &n, F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Int &rank, F77Double &tol, F77Double work[], F77Int &info);\nvoid wrapdtrtri(const F77Int &upper, const F77Int &n, F77Double A[], const F77Int &ldA, F77Int &info);\nvoid wrapdlauum(const F77Int &upper, const F77Int &n, F77Double A[], const F77Int &ldA, F77Int &info);\nvoid wrapdgetrf(const F77Int &m, const F77Int &n,    F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Int &info);\nvoid wrapdgesv (const F77Int &n, const F77Int &nrhs, F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Double B[], const F77Int &ldB, F77Int &info);\nvoid wrapdsgesv(const F77Int &n, const F77Int &nrhs, F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Double B[], const F77Int &ldB, F77Double X[], const F77Int &ldX, F77Double work[], F77Float swork[], F77Int &iter, F77Int &info);\nvoid wrapdgetri(const F77Int &n, F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdgels (const F77Int &trans, const F77Int &m, const F77Int &n, const F77Int &nrhs, F77Double A[], const F77Int &ldA, F77Double B[], const F77Int &ldB, F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdgeqrf(const F77Int &m, const F77Int &n, F77Double A[], const F77Int &ldA, F77Double tau[], F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdormqr(const F77Int &left, const F77Int &trans, const F77Int &m, const F77Int &n, const F77Int &k, const F77Double A[], const F77Int &ldA, const F77Double tau[], F77Double C[], const F77Int &ldC, F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdorgqr(const F77Int &m, const F77Int &n, const F77Int &k, F77Double A[], const F77Int &ldA, const F77Double tau[], F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdpbsv (const F77Int &upper, const F77Int &n, const F77Int &kd, const F77Int &nrhs, F77Double A[], const F77Int &ldA, F77Double B[], const F77Int &ldB, F77Int &info);\nvoid wrapdpbtrf(const F77Int &upper, const F77Int &n, const F77Int &kd, F77Double A[], const F77Int &ldA, F77Int &info);\nvoid wrapdgbtrf(const F77Int &n, const F77Int &m, const F77Int &kl, const F77Int &ku, F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Int &info);\nvoid wrapdtbtrs(const F77Int &upper,  const F77Int &trans, const F77Int &unitDiag, const F77Int &n, const F77Int &kd, const F77Int &nrhs, const F77Double A[], const F77Int &ldA, F77Double B[], const F77Int &ldB, F77Int &info);\nvoid wrapdgbtrs(const F77Int &trans, const F77Int &n, const F77Int &kl, const F77Int &ku, const F77Int &nrhs, const F77Double A[], const F77Int &ldA, F77Int ipiv[], F77Double B[], const F77Int &ldB, F77Int &info);\nvoid wrapdsyev (const F77Int &jobz, const F77Int &upper, const F77Int &n, F77Double A[], const F77Int &ldA, F77Double W[], F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdgeev (const F77Int &jobvl, const F77Int &jobvr, const F77Int &n, F77Double A[], const F77Int &ldA, F77Double WR[], F77Double WI[], F77Double VL[], const F77Int &ldVL, F77Double VR[], const F77Int &ldVR, F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdgesvd(const F77Int &jobu, const F77Int &jobvt, const F77Int &m, const F77Int &n, F77Double A[], const F77Int &ldA, F77Double S[], F77Double U[], const F77Int &ldU, F77Double VT[], const F77Int &ldvt, F77Double work[], const F77Int &lwork, F77Int &info);\nvoid wrapdgesdd(const F77Int &jobz, const F77Int &m, const F77Int &n, F77Double A[], const F77Int &ldA, F77Double S[], F77Double U[], const F77Int &ldU, F77Double VT[], const F77Int &ldvt, F77Double work[], const F77Int &lwork, F77Int iwork[], F77Int &info);\n}\n\n/***** INLINES *********************************/\n\ninline void lapack_dlacpy(UInt m, UInt n, const Double A[], UInt ldA, Double B[], UInt ldB)\n{\n  wrapdlacpy(static_cast<F77Int>(m), static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), B, static_cast<F77Int>(ldB));\n}\n\ninline Int lapack_dpotrf(Bool upper, UInt n, Double A[], UInt ldA)\n{\n  F77Int info;\n  wrapdpotrf(upper, static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), info);\n  return info;\n}\n\ninline Int lapack_dpotri(Bool upper, UInt n, Double A[], UInt ldA)\n{\n  F77Int info;\n  wrapdpotri(upper, static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), info);\n  return info;\n}\n\ninline Int lapack_dpstrf(Bool upper, UInt n, Double A[], UInt ldA, F77Int ipiv[], F77Int &rank, Double tol)\n{\n  F77Int info;\n  F77Double *work  = new F77Double[2*n];\n  wrapdpstrf(upper, static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), ipiv, rank, tol, work,info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dtrtri(Bool upper, UInt n, Double A[], UInt ldA)\n{\n  F77Int info;\n  wrapdtrtri(upper, static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), info);\n  return info;\n}\n\ninline Int lapack_dlauum(Bool upper, UInt n, Double A[], UInt ldA)\n{\n  F77Int info;\n  wrapdlauum(upper, static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), info);\n  return info;\n}\n\ninline Int lapack_dgetrf(UInt m, UInt n, Double A[], UInt ldA, F77Int ipiv[])\n{\n  F77Int info;\n  wrapdgetrf(static_cast<F77Int>(m), static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), ipiv, info);\n  return info;\n}\n\ninline Int lapack_dgesv (UInt n, UInt nrhs, Double A[], UInt ldA, F77Int ipiv[], Double B[], UInt ldB)\n{\n  F77Int info;\n  wrapdgesv(static_cast<F77Int>(n), static_cast<F77Int>(nrhs), A, static_cast<F77Int>(ldA), ipiv, B, static_cast<F77Int>(ldB), info);\n  return info;\n}\n\ninline Int lapack_dsgesv (UInt n, UInt nrhs, Double A[], UInt ldA, F77Int ipiv[], Double B[], UInt ldB, Double X[], UInt ldX, Int iter)\n{\n  F77Int info;\n  F77Double *work  = new F77Double[n*nrhs];\n  F77Float  *swork = new F77Float [n*(n+nrhs)];\n  wrapdsgesv(static_cast<F77Int>(n), static_cast<F77Int>(nrhs), A, static_cast<F77Int>(ldA), ipiv, B, static_cast<F77Int>(ldB), X, static_cast<F77Int>(ldX), work, swork, iter, info);\n  delete[] work;\n  delete[] swork;\n  return info;\n}\n\ninline Int lapack_dgetri(UInt n, Double A[], UInt ldA, F77Int ipiv[])\n{\n  F77Int info;\n  F77Double tmp;\n  wrapdgetri(static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), ipiv, &tmp, -1, info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(n);\n  F77Double *work = new F77Double[lwork];\n  wrapdgetri(static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), ipiv, work, lwork, info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dgels (Bool trans, UInt m, UInt n, UInt nrhs, Double A[], UInt ldA, Double B[], UInt ldB)\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdgels(trans,static_cast<F77Int>(m), static_cast<F77Int>(n), static_cast<F77Int>(nrhs), A, static_cast<F77Int>(ldA), B, static_cast<F77Int>(ldB), &tmp, -1, info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(std::max(n,m));\n  F77Double *work = new F77Double[lwork];\n  wrapdgels(trans, static_cast<F77Int>(m), static_cast<F77Int>(n), static_cast<F77Int>(nrhs), A, static_cast<F77Int>(ldA), B, static_cast<F77Int>(ldB), work, lwork, info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dgeqrf(UInt m, UInt n, Double A[], UInt ldA, Double tau[])\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdgeqrf(static_cast<F77Int>(m), static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), tau, &tmp, -1, info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(std::max(n,m));\n  F77Double *work = new F77Double[lwork];\n  wrapdgeqrf(static_cast<F77Int>(m), static_cast<F77Int>(n), A, static_cast<F77Int>(ldA), tau, work, lwork, info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dormqr(Bool left, Bool trans, UInt m, UInt n, UInt k, const Double A[], UInt ldA, const Double tau[], Double C[], UInt ldC)\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdormqr(left, trans, static_cast<F77Int>(m), static_cast<F77Int>(n), static_cast<F77Int>(k), A, static_cast<F77Int>(ldA), tau, C, static_cast<F77Int>(ldC), &tmp, -1, info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(std::max(n,m));\n  F77Double *work = new F77Double[lwork];\n  wrapdormqr(left,trans,static_cast<F77Int>(m), static_cast<F77Int>(n), static_cast<F77Int>(k), A,static_cast<F77Int>(ldA), tau, C, static_cast<F77Int>(ldC), work, lwork, info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dorgqr(UInt m, UInt n, UInt k, Double A[], UInt ldA, const Double tau[])\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdorgqr(static_cast<F77Int>(m), static_cast<F77Int>(n), static_cast<F77Int>(k),A,static_cast<F77Int>(ldA), tau,&tmp,-1,info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(std::max(n,m));\n\n  F77Double *work = new F77Double[lwork];\n  wrapdorgqr(static_cast<F77Int>(m), static_cast<F77Int>(n), static_cast<F77Int>(k),A,static_cast<F77Int>(ldA), tau,work,lwork,info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dpbsv(Bool upper, UInt n, UInt kd, UInt nrhs, Double A[], UInt ldA, Double B[], UInt ldB)\n{\n  F77Int info;\n  wrapdpbsv(upper,static_cast<F77Int>(n), static_cast<F77Int>(kd), static_cast<F77Int>(nrhs), A,static_cast<F77Int>(ldA), B,static_cast<F77Int>(ldB), info);\n  return info;\n}\n\ninline Int lapack_dpbtrf(Bool upper, UInt n, UInt kd, Double A[], UInt ldA)\n{\n  F77Int info;\n  wrapdpbtrf(upper,static_cast<F77Int>(n), static_cast<F77Int>(kd), A,static_cast<F77Int>(ldA), info);\n  return info;\n}\n\ninline Int lapack_dgbtrf(UInt n, UInt m, UInt kl, UInt ku, Double A[], UInt ldA, F77Int ipiv[])\n{\n  F77Int info;\n  wrapdgbtrf(static_cast<F77Int>(n), static_cast<F77Int>(m), static_cast<F77Int>(kl), static_cast<F77Int>(ku), A,static_cast<F77Int>(ldA), ipiv,info);\n  return info;\n}\n\ninline Int lapack_dtbtrs(Bool upper, Bool trans, Bool unitDiag, UInt n, UInt kd, UInt nrhs, const Double A[], UInt ldA, Double B[], UInt ldB)\n{\n  F77Int info;\n  wrapdtbtrs(upper,trans,unitDiag,static_cast<F77Int>(n), static_cast<F77Int>(kd), static_cast<F77Int>(nrhs), A,static_cast<F77Int>(ldA), B,static_cast<F77Int>(ldB), info);\n  return info;\n}\n\ninline Int lapack_dgbtrs(Bool trans, UInt n, UInt kl, UInt ku, UInt nrhs, const Double A[], UInt ldA, F77Int ipiv[], Double B[], UInt ldB)\n{\n  F77Int info;\n  wrapdgbtrs(trans,static_cast<F77Int>(n), static_cast<F77Int>(kl), static_cast<F77Int>(ku), static_cast<F77Int>(nrhs), A, static_cast<F77Int>(ldA), ipiv, B, static_cast<F77Int>(ldB), info);\n  return info;\n}\n\ninline Int lapack_dsyev(Bool jobz, Bool upper, UInt n, Double A[], UInt ldA, Double W[])\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdsyev(jobz, upper,static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), W,&tmp,-1,info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(n);\n  F77Double *work = new F77Double[lwork];\n  wrapdsyev(jobz, upper,static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), W,work,lwork,info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dgeev(Bool jobvl, Bool jobvr, UInt n, Double A[], UInt ldA, Double WR[], Double WI[], Double VL[], UInt ldVL, Double VR[], UInt ldVR)\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdgeev(jobvl,jobvr,static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), WR,WI,VL, static_cast<F77Int>(ldVL), VR, static_cast<F77Int>(ldVR), &tmp,-1,info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(n);\n  F77Double *work = new F77Double[lwork];\n  wrapdgeev(jobvl,jobvr,static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), WR,WI,VL, static_cast<F77Int>(ldVL), VR, static_cast<F77Int>(ldVR), work,lwork,info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dgesvd(Bool jobu, Bool jobvt, UInt m, UInt n, Double A[], UInt ldA, Double S[], Double U[], UInt ldU, Double VT[], UInt ldvt)\n{\n  F77Int    info;\n  F77Double tmp;\n  wrapdgesvd(jobu,jobvt,static_cast<F77Int>(m), static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), S,U, static_cast<F77Int>(ldU), VT, static_cast<F77Int>(ldvt), &tmp,-1,info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(std::max(n,m));\n  F77Double *work = new F77Double[lwork];\n  wrapdgesvd(jobu,jobvt,static_cast<F77Int>(m), static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), S,U, static_cast<F77Int>(ldU), VT, static_cast<F77Int>(ldvt), work,lwork,info);\n  delete[] work;\n  return info;\n}\n\ninline Int lapack_dgesdd(Bool jobz, UInt m, UInt n, Double A[], UInt ldA, Double S[], Double U[], UInt ldU, Double VT[], UInt ldvt)\n{\n  F77Int    info;\n  F77Double tmp;\n  F77Int itmp;\n  wrapdgesdd(jobz,static_cast<F77Int>(m), static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), S,U, static_cast<F77Int>(ldU), VT, static_cast<F77Int>(ldvt), &tmp,-1,&itmp,info);\n  F77Int lwork = (tmp>0) ? static_cast<F77Int>(tmp) : static_cast<F77Int>(std::max(n,m));\n  F77Double *work = new F77Double[lwork];\n  F77Int *iwork = new F77Int[8*std::min(m,n)];\n  wrapdgesdd(jobz,static_cast<F77Int>(m), static_cast<F77Int>(n), A,static_cast<F77Int>(ldA), S,U, static_cast<F77Int>(ldU), VT, static_cast<F77Int>(ldvt), work,lwork,iwork,info);\n  delete[] work;\n  delete[] iwork;\n  return info;\n}\n\n/***********************************************/\n\n#endif /* __GROOPS_LAPACK__ */\n"
  },
  {
    "path": "source/external/lapack/lapackWrapper.f",
    "content": "c\nc *******************************************\nc\n      subroutine wrapdlacpy(m,n,A,ldA,B,ldB)\n      external dlacpy\n      call dlacpy('G',m,n,A,ldA,B,ldB)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdpotrf(upper,n,A,ldA,info)\n      integer   upper\n      character uplo\n      external dpotrf\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dpotrf(uplo,n,A,ldA,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdpstrf(upper,n,A,ldA,piv,rank,\n     $                      tol,work,info)\n      integer   upper\n      character uplo\n      external dpstrf\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dpstrf(uplo,n,A,ldA,piv,rank,tol,work,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdpotri(upper,n,A,ldA,info)\n      integer   upper\n      character uplo\n      external dpotri\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dpotri(uplo,n,A,ldA,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdtrtri(upper,n,A,ldA,info)\n      integer   upper\n      character uplo\n      external dpotri\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dtrtri(uplo,'N',n,A,ldA,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdlauum(upper,n,A,ldA,info)\n      integer   upper\n      character uplo\n      external dlauum\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dlauum(uplo,n,A,ldA,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgetrf(m,n,A,ldA,ipiv,info)\n      external dgetrf\n      call dgetrf(m,n,A,ldA,ipiv,info);\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgesv(n,nrhs,A,ldA,ipiv,B,ldB,info)\n      external dgesv\n      call dgesv(n,nrhs,A,ldA,ipiv,B,ldB,info);\n      end\nc\nc *******************************************\nc\n      subroutine wrapdsgesv(n,nrhs,A,ldA,ipiv,B,ldB,X,ldX,\n     $                      work,swork,iter,info)\n      external dsgesv\n      call dsgesv(n,nrhs,A,ldA,ipiv,B,ldB,X,ldX,\n     $            work,swork,iter,info);\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgetri(n,A,ldA,ipiv,work,lwork,info)\n      external dgetri\n      call dgetri(n,A,ldA,ipiv,work,lwork,info);\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgels(trans,m,n,nrhs,A,ldA,B,ldB,work,lwork,info)\n      integer   trans\n      character tr\n      external dgels\n      if(trans.eq.0) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      call dgels(tr,m,n,nrhs,A,ldA,B,ldB,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgeqrf(m,n,A,ldA,tau,work,lwork,info)\n      external dgeqrf\n      call dgeqrf(m,n,A,ldA,tau,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdormqr(left,trans,m,n,k,A,ldA,tau,\n     $                      C,ldC,work,lwork,info)\n      external dormqr\n      integer   left, trans\n      character side,  tr\n      if(left.eq.0) then\n        side = 'R'\n      else\n        side = 'L'\n      endif\n      if(trans.eq.0) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      call dormqr(side,tr,m,n,k,A,ldA,tau,C,ldC,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdorgqr(m,n,k,A,ldA,tau,work,lwork,info)\n      external dgeqrf\n      call dorgqr(m,n,k,A,ldA,tau,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdpbtrf(upper,n,kd,A,ldA,info)\n      integer   upper\n      character uplo\n      external dpbtrf\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dpbtrf(uplo,n,kd,A,ldA,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdpbsv(upper,n,kd,nrhs,A,ldA,B,ldB,info)\n      integer   upper\n      character uplo\n      external dpbtrf\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      call dpbsv(uplo,n,kd,nrhs,A,ldA,B,ldB,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgbtrf(n,m,kl,ku,A,ldA,ipiv,info)\n      external dgbtrf\n      call dgbtrf(n,m,kl,ku,A,ldA,ipiv,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdtbtrs(upper,trans,diag,n,kd,nrhs,A,ldA,B,ldB,info)\n      external dtrsm\n      integer   upper, trans, diag\n      character uplo,  tr,    diago\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(trans.eq.0) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      if(diag.eq.0) then\n        diago = 'N'\n      else\n        diago = 'U'\n      endif\n      call dtbtrs(uplo,tr,diago,n,kd,nrhs,A,ldA,B,ldB,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgbtrs(trans,n,kl,ku,nrhs,A,ldA,ipiv,B,ldB,info)\n      external  dgbtrs\n      integer   trans\n      character tr\n      if(trans.eq.0) then\n        tr = 'N'\n      else\n        tr = 'T'\n      endif\n      call dgbtrs(tr,n,kl,ku,nrhs,A,ldA,ipiv,B,ldB,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdsyev(job,upper,n,A,ldA,W,work,lwork,info)\n      external dsyev\n      integer   job, upper\n      character jobz,uplo\n      if(upper.eq.0) then\n        uplo = 'L'\n      else\n        uplo = 'U'\n      endif\n      if(job.eq.0) then\n        jobz = 'N'\n      else\n        jobz = 'V'\n      endif\n      call dsyev(jobz,uplo,n,A,ldA,W,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgeev(jobvl,jobvr,n,A,ldA,WR,WI,VL,ldVL,VR,\n     $                     ldVR,work,lwork,info)\n      external dgeev\n      integer   jobvl, jobvr\n      character jobvlc, jobvrc\n      if(jobvl.eq.0) then\n        jobvlc = 'N'\n      else\n        jobvlc = 'V'\n      endif\n      if(jobvr.eq.0) then\n        jobvrc = 'N'\n      else\n        jobvrc = 'V'\n      endif\n      call dgeev(jobvlc,jobvrc,n,A,ldA,WR,WI,VL,ldVL,VR,\n     $           ldVR,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgesvd(jobz,jobvt,m,n,A,ldA,S,\n     $                      U,ldU,Vt,ldVt,work,lwork,info)\n      external dsyev\n      integer   jobz,  jobvt\n      character cjobz,cjobvt\n      if(jobz.eq.0) then\n        cjobz = 'N'\n      else\n        cjobz = 'S'\n      endif\n      if(jobvt.eq.0) then\n        cjobvt = 'N'\n      else\n        cjobvt = 'S'\n      endif\n      call dgesvd(cjobz,cjobvt,m,n,A,ldA,\n     $            S,U,ldU,Vt,ldVt,work,lwork,info)\n      end\nc\nc *******************************************\nc\n      subroutine wrapdgesdd(jobz,m,n,A,ldA,S,\n     $                      U,ldU,Vt,ldVt,work,lwork,iwork,info)\n      external dsyev\n      integer   jobz\n      character cjobz\n      if(jobz.eq.0) then\n        cjobz = 'N'\n      else\n        cjobz = 'S'\n      endif\n      call dgesdd(cjobz,m,n,A,ldA,\n     $            S,U,ldU,Vt,ldVt,work,lwork,iwork,info)\n      end\nc\nc *******************************************\nc\n"
  },
  {
    "path": "source/external/nrlmsis2/alt2gph.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n\n!==================================================================================================\n! ALT2GPH: Altitude to Geopotential Height\n! References:\n!   DMA Technical Report TR8350.2 (1987),\n!     http://earth-info.nga.mil/GandG/publications/historic/historic.html\n!   Featherstone, W. E., and S. J. Claessens (2008), Closed-form transformation between\n!     geodetic and ellipsoidal coordinates, Studia Geophysica et Geodaetica, 52, 1-18\n!   Jekeli, C. (2009), Potential theory and static gravity field of the Earth, in \n!     Treatise on Geophysics, ed. T. Herring, vol 3, 11-42\n!   NIMA Technical Report TR8350.2 (2000, 3rd edition, Amendment1), \n!     http://earth-info.nga.mil/GandG/publications/tr8350.2/tr8350_2.html\n!==================================================================================================\nreal(8) function alt2gph(lat,alt)\n\n  implicit none\n\n  ! Input variables\n  real(8), intent(in) :: lat    !Geodetic latitude (deg)\n  real(8), intent(in) :: alt    !Geodetic altitude (km)\n\n  real(8), parameter  :: deg2rad = 0.017453292519943295d0\n\n  ! WGS84 Defining parameters\n  real(8), parameter  :: a = 6378.1370d0 * 1d3 !Semi-major axis of reference ellipsoid (m)\n  real(8), parameter  :: finv = 298.257223563d0 ! 1/f = Reciprocal of flattening\n  real(8), parameter  :: w = 7292115d-11 !Angular velocity of Earth rotation (rad/s)\n  real(8), parameter  :: GM = 398600.4418 * 1d9 !Gravitational constant x Earth mass (m^3/s^2)\n\n  ! WGS84 Derived parameters\n  real(8), parameter  :: asq = a*a\n  real(8), parameter  :: wsq = w*w\n  real(8), parameter  :: f = 1.0d0 / finv\n  real(8), parameter  :: esq = 2*f - f*f\n  real(8), parameter  :: e = sqrt(esq)  !Ellipsoid eccentricity\n  real(8), parameter  :: Elin = a*e     !Linear eccentricity of ellipsoid\n  real(8), parameter  :: Elinsq = Elin*Elin\n  real(8), parameter  :: epr = e / (1-f)  !Second eccentricity\n  real(8), parameter  :: q0 = ((1.0d0 + 3.0d0/(epr*epr))*atan(epr) - 3.0d0/epr)/2.0d0  !DMA Technical Report tr8350.2, Eq. 3-25\n  real(8), parameter  :: U0 = -GM*atan(epr)/Elin - wsq*asq/3d0 !Theoretical potential of reference ellipsoid (m^2/s^2), DMA Technical Report tr8350.2, Eq. 3-51\n  real(8), parameter  :: g0 = 9.80665d0 !Standard gravity (m/s^2), CGPM 1901; WMO\n  real(8), parameter  :: GMdivElin = GM / Elin\n  \n  ! Parameters for centrifugal potential taper\n  real(8), parameter  :: x0sq = 2d7**2   !Axial distance squared at which tapering begins (m^2)\n  real(8), parameter  :: Hsq = 1.2d7**2  !Relaxation scale length of taper (m^2)\n\n  ! Working variables\n  real(8)             :: altm, sinsqlat, v, xsq, zsq\n  real(8)             :: rsqminElinsq, usq, cossqdelta, epru, atanepru, q, U, Vc\n\n  ! Compute Cartesian and ellipsoidal coordinates\n  altm = alt * 1000.0d0\n  sinsqlat = sin(lat*deg2rad)**2\n  v = a / sqrt(1-esq*sinsqlat)           !Radius of curvature of the reference ellipsoid, Featherstone eq. 4\n  xsq = (v + altm)**2 * (1 - sinsqlat)   !Squared x-coordinate of geocentric system, Featherstone eq. 1\n  zsq = (v*(1-esq) + altm)**2 * sinsqlat !Squared z-coordinate of geocentric system, Featherstone eq. 3\n  rsqminElinsq = xsq + zsq - Elinsq\n  usq = rsqminElinsq/2.0d0 + sqrt(rsqminElinsq**2 / 4.0d0 + Elinsq*zsq)  !Ellipsoidal distance coordinate, Featherstone eq. 19 \n  cossqdelta = zsq / usq                 !Ellipsoidal polar angle, Featherstone eq. 21\n\n  ! Compute gravitational potential\n  epru = Elin / sqrt(usq)                !Second eccentricity at ellipsoidal coordinate u\n  atanepru = atan(epru)\n  q = ((1+3.0d0/(epru*epru))*atanepru - 3.0d0/epru)/2.0d0   !Jekeli, eq. 114\n  U = -GMdivElin * atanepru - wsq * ( asq * q * (cossqdelta - 1/3.0d0) / q0 ) / 2.0d0   !Jekeli, eq. 113\n\n  ! Compute centrifugal potential and adjust total potential\n  if (xsq .le. x0sq) then\n    Vc = (wsq/2.0d0) * xsq\n  else\n    Vc = (wsq/2.0d0) * (Hsq*tanh((xsq-x0sq)/Hsq) + x0sq) !Centrifugal potential taper\n  endif\n  U = U - Vc\n  \n  ! Compute geopotential height\n  alt2gph = (U - U0) / g0 / 1000.0d0\n\n  return\n\nend function alt2gph\n\n!==================================================================================================\n! GPH2ALT: Geopotential Height to Altitude\n!==================================================================================================\nreal(8) function gph2alt(theta,gph)\n\n  implicit none\n\n  real(8), external    :: alt2gph\n\n  real(8), intent(in)  :: theta\n  real(8), intent(in)  :: gph\n\n  integer, parameter   :: maxn = 10\n  real(8), parameter   :: epsilon = 0.0005\n\n  real(8)              :: x,dx,y,dydz\n  integer              :: n\n\n  x = gph\n  n = 0\n  dx = epsilon + epsilon\n  do while ((abs(dx) .gt. epsilon) .and. (n .lt. 10))\n    y = alt2gph(theta,x)\n    dydz = (alt2gph(theta,x+dx) - y)/dx\n    dx = (gph - y)/dydz\n    x = x + dx\n    n = n + 1\n  end do\n\n  gph2alt = x\n\nend function gph2alt\n    \n"
  },
  {
    "path": "source/external/nrlmsis2/msis_calc.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n!!!\n!!! MSISCALC: New interface with re-ordered input arguments and output arrays.\n!\n!     PREREQUISITES:\n!       Must first run MSISINIT to load parameters and set switches. The \n!       MSISCALC subroutine checks for initialization and does a default\n!       initialization if necessary. This self-initialization will be removed\n!       in future versions.\n!\n!     CALLING SEQUENCE:\n!       CALL MSISCALC(DAY, UTSEC, Z, LAT, LON, SFLUXAVG, SFLUX, AP, TN, DN, [TEX])\n!  \n!     INPUT VARIABLES:\n!       DAY       Day of year (1.0 to 365.0 or 366.0)\n!       UTSEC     Universal time (seconds)\n!       Z         Geodetic altitude (km) (default) or Geopotential height (km)\n!       LAT       Geodetic latitude (deg)\n!       LON       Geodetic longitude (deg)\n!       SFLUXAVG  81 day average, centered on input time, of F10.7 solar\n!                 activity index\n!       SFLUX     Daily F10.7 for previous day\n!       AP        Geomagnetic activity index array:\n!                   (1) Daily Ap\n!                   (2) 3 hr ap index for current time\n!                   (3) 3 hr ap index for 3 hrs before current time\n!                   (4) 3 hr ap index for 6 hrs before current time\n!                   (5) 3 hr ap index for 9 hrs before current time\n!                   (6) Average of eight 3 hr ap indices from 12 to 33 hrs\n!                       prior to current time\n!                   (7) Average of eight 3 hr ap indices from 36 to 57 hrs\n!                       prior to current time\n!                 AP(2:7) are only used when switch_legacy(9) = -1.0 in MSISINIT\n!\n!     NOTES ON INPUT VARIABLES: \n!       - The day-of-year dependence of the model only uses the DAY argument. If\n!         a continuous day-of-year dependence is desired, this argument should\n!         include the fractional day (e.g., DAY = <day of year> + UTSEC/86400.0\n!       - If lzalt_type = .true. (default) in the MSISINIT call, then Z is\n!         treated as geodetic altitude.\n!         If lzalt_type = .false., then Z is treated as geopotential height.\n!       - F107 and F107A values are the 10.7 cm radio flux at the Sun-Earth\n!         distance, not the radio flux at 1 AU. \n!\n!     OUTPUT VARIABLES:\n!       TN     Temperature at altitude (K)\n!       DN(1)  Total mass density (kg/m3)\n!       DN(2)  N2 number density (m-3)\n!       DN(3)  O2 number density (m-3)\n!       DN(4)  O number density (m-3)\n!       DN(5)  He number density (m-3)\n!       DN(6)  H number density (m-3)\n!       DN(7)  Ar number density (m-3)\n!       DN(8)  N number density (m-3)\n!       DN(9)  Anomalous oxygen number density (m-3)\n!       DN(10) Not used in NRLMSIS 2.0 (will contain NO in future release)\n!       TEX    Exospheric temperature (K) (optional argument)\n!\n!     NOTES ON OUTPUT VARIABLES: \n!       - Missing density values are returned as 9.999e-38\n!       - Species included in mass density calculation are set in MSISINIT\n!\n!!! =========================================================================\n\n!**************************************************************************************************\n! MSIS_CALC Module: Contains main MSIS entry point\n!**************************************************************************************************\nmodule msis_calc\n\ncontains\n\n  !==================================================================================================\n  ! MSISCALC: The main MSIS subroutine entry point\n  !==================================================================================================\n  subroutine msiscalc(day,utsec,z,lat,lon,sfluxavg,sflux,ap,tn,dn,tex)\n\n    use msis_constants, only    : rp, dmissing, lnp0, Mbarg0divkB, kB, nspec, nodesTN, nd, zetaF, zetaB, &\n                                  Hgamma, zetagamma, maxnbf\n    use msis_init, only         : msisinit, initflag, zaltflag, specflag, massflag, masswgt, etaTN\n    use msis_gfn, only          : globe\n    use msis_tfn, only          : tnparm, tfnparm, tfnx\n    use msis_dfn, only          : dnparm, dfnparm, dfnx\n\n    implicit none\n\n    real(8), external          :: alt2gph\n    real(kind=rp), external    :: dilog\n\n    real(kind=rp), intent(in)  :: day\n    real(kind=rp), intent(in)  :: utsec\n    real(kind=rp), intent(in)  :: z\n    real(kind=rp), intent(in)  :: lat\n    real(kind=rp), intent(in)  :: lon\n    real(kind=rp), intent(in)  :: sfluxavg,sflux,ap(1:7)\n    real(kind=rp), intent(out) :: tn, dn(1:10)\n    real(kind=rp), intent(out), optional :: tex\n  \n    real(kind=rp), save        :: lastday = -9999.0\n    real(kind=rp), save        :: lastutsec = -9999.0\n    real(kind=rp), save        :: lastlat = -9999.0\n    real(kind=rp), save        :: lastlon = -9999.0\n    real(kind=rp), save        :: lastz = -9999.0\n    real(kind=rp), save        :: lastsflux = -9999.0\n    real(kind=rp), save        :: lastsfluxavg = -9999.0\n    real(kind=rp), save        :: lastap(1:7) = -9999.0\n    real(kind=rp), save        :: gf(0:maxnbf-1)\n    real(kind=rp), save        :: Sz(-5:0,2:6)\n    integer, save              :: iz\n    type(tnparm), save         :: tpro\n    type(dnparm), save         :: dpro(1:nspec-1)\n\n    real(8)                    :: zaltd, latd\n    real(kind=rp)              :: zeta, lndtotz, Vz, Wz, HRfact, lnPz, delz\n    integer                    :: i, j, kmax, ispec\n\n    ! Check if model has been initialized; if not, perform default initialization\n    if (.not. initflag) call msisinit()\n\n    ! Calculate geopotential height, if necessary\n    if(zaltflag) then\n      zaltd = dble(z)\n      latd = dble(lat)\n      zeta = alt2gph(latd,zaltd)\n    else\n      zeta = z\n    endif\n\n    ! If only altitude changes then update the local spline weights\n    if (zeta .lt. zetaB) then\n      if (zeta .ne. lastz) then\n        if (zeta .lt. zetaF) then\n          kmax = 5\n        else\n          kmax = 6\n        endif\n        call bspline(zeta,nodesTN,nd+2,kmax,etaTN,Sz,iz)\n        lastz = zeta\n      endif\n    endif\n\n    ! If location, time, or solar/geomagnetic conditions change then recompute the profile parameters\n    if ((day .ne. lastday)     .or. (utsec .ne. lastutsec)       .or. &\n        (lat .ne. lastlat)     .or. (lon .ne. lastlon)           .or. &\n        (sflux .ne. lastsflux) .or. (sfluxavg .ne. lastsfluxavg) .or. &\n        any(ap .ne. lastap)) then\n      call globe(day,utsec,lat,lon,sfluxavg,sflux,ap,gf)\n      call tfnparm(gf,tpro)\n      do ispec = 2, nspec-1\n        if (specflag(ispec)) call dfnparm(ispec,gf,tpro,dpro(ispec))\n      enddo\n      lastday = day\n      lastutsec = utsec\n      lastlat = lat\n      lastlon = lon\n      lastsflux = sflux\n      lastsfluxavg = sfluxavg\n      lastap = ap\n    endif\n\n    ! Exospheric temperature\n    if (present(tex)) then\n      tex = tpro%tex\n    endif\n\n    ! Temperature at altitude\n    tn = tfnx(zeta,iz,Sz(-3:0,4),tpro)\n\n    ! Temperature integration terms at altitude, total number density\n    delz = zeta - zetaB\n    if (zeta .lt. zetaF) then\n      i = max(iz-4,0)\n      if (iz .lt. 4) then\n        j = -iz\n      else\n        j = -4\n      endif\n      Vz = dot_product(tpro%beta(i:iz),Sz(j:0,5)) + tpro%cVS\n      Wz = 0.0_rp\n      lnPz = lnP0 - Mbarg0divkB*(Vz - tpro%Vzeta0)\n      lndtotz = lnPz - log(kB*tn)\n    else\n      if (zeta .lt. zetaB) then\n        Vz = dot_product(tpro%beta(iz-4:iz),Sz(-4:0,5)) + tpro%cVS\n        Wz = dot_product(tpro%gamma(iz-5:iz),Sz(-5:0,6)) + tpro%cVS*delz + tpro%cWS\n      else\n        Vz = (delz + log(tn/tpro%tex)/tpro%sigma)/tpro%tex + tpro%cVB\n        Wz = (0.5_rp*delz*delz + dilog(tpro%b*exp(-tpro%sigma*delz))/tpro%sigmasq)/tpro%tex &\n              + tpro%cVB*delz + tpro%cWB\n      endif\n    endif\n        \n    ! Species number densities at altitude\n    HRfact = 0.5_rp * (1.0_rp + tanh(Hgamma*(zeta - zetagamma)))  !Reduction factor for chemical/dynamical correction scale height below zetagamma\n    do ispec = 2, nspec-1\n      if (specflag(ispec)) then\n        dn(ispec) = dfnx(zeta,tn,lndtotz,Vz,Wz,HRfact,tpro,dpro(ispec))\n      else\n        dn(ispec) = dmissing\n      endif\n    enddo\n\n    ! Mass density\n    if (specflag(1)) then\n      dn(1) = dot_product(dn,masswgt)\n    else\n      dn(1) = dmissing\n    endif\n\n    return\n\n  end subroutine msiscalc\n\nend module msis_calc\n\n!==================================================================================================\n! BSPLINE: Returns array of nonzero b-spline values, for all orders up to specified order (max 6)\n!==================================================================================================\nsubroutine bspline(x,nodes,nd,kmax,eta,S,i)\n\n  use msis_constants, only:  rp\n\n  implicit none\n\n  ! Input variables\n  real(kind=rp), intent(in)  :: x             !Location at which splines are to be evaluated\n  real(kind=rp), intent(in)  :: nodes(0:30)   !Spline node locations\n  integer, intent(in)        :: nd            !Number of spline nodes minus one (0:nd)\n  integer, intent(in)        :: kmax          !Maximum order (up to 6 allowed) of evaluated splines\n  real(kind=rp), intent(in)  :: eta(0:30,2:6) !Array of precomputed weights for recursion (reciprocals of node differences)\n  ! Ouput variables\n  real(kind=rp), intent(out) :: S(-5:0,2:6)   !Array of b-spline values (spline index relative to i (-5:0), spline order (2:6))\n  integer, intent(out)       :: i             !Index of last nonzero b-spline\n\n  ! Working variables\n  integer                    :: j, k, l\n  integer                    :: low, high\n  real(kind=rp)              :: w(-4:0) !Weights for recursion relation\n \n  ! Initialize to zero\n  S(:,:) = 0.0_rp\n\n  ! Find index of last (rightmost) nonzero spline\n  if (x .ge. nodes(nd)) then\n    i = nd\n    return\n  endif\n  if (x .le. nodes(0)) then\n    i = -1\n    return\n  endif\n  low = 0\n  high = nd\n  i = (low + high)/2\n  do while (x .lt. nodes(i) .or. x .ge. nodes(i + 1))\n      if (x .lt. nodes(i)) then\n        high = i\n      else\n        low = i\n      endif\n      i = (low + high)/2\n  end do\n\n  ! Initialize with linear splines\n  S(0,2) = (x - nodes(i)) * eta(i,2)\n  if (i .gt. 0) S(-1,2) = 1 - S(0,2)\n  if (i .ge. nd-1) S(0,2) = 0.0_rp   !Reset out-of-bounds spline to zero\n\n  ! k = 3 (quadratic splines)\n  w(:) = 0.0_rp\n  w(0) = (x - nodes(i)) * eta(i,3)\n  if (i .ne. 0) w(-1) = (x - nodes(i-1)) * eta(i-1,3)\n  if (i .lt. (nd-2)) S(0,3) = w(0)*S(0,2)\n  if ( ((i-1) .ge. 0) .and. ((i-1) .lt. (nd-2)) ) &\n      S(-1,3) = w(-1) * S(-1,2) + (1.0_rp - w(0))*S(0,2)\n  if ((i-2) .ge. 0) S(-2,3) = (1.0_rp - w(-1))*S(-1,2)\n    \n  ! k = 4 (cubic splines)\n  do l = 0, -2, -1\n    j = i + l\n    if (j .lt. 0) exit  !Skip out-of-bounds splines\n    w(l) = (x - nodes(j)) * eta(j,4)\n  enddo\n  if (i .lt. (nd-3)) S(0,4) = w(0)*S(0,3)\n  do l = -1, -2, -1\n      if ( ((i+l) .ge. 0) .and. ((i+l) .lt. (nd-3)) ) &\n          S(l,4) = w(l)*S(l,3) + (1.0_rp - w(l+1))*S(l+1,3)\n  enddo\n  if ((i-3) .ge. 0) S(-3,4) = (1.0_rp - w(-2))*S(-2,3)\n  \n  ! k = 5\n  do l = 0, -3, -1\n    j = i + l\n    if (j .lt. 0) exit  !Skip out-of-bounds splines\n    w(l) = (x - nodes(j)) * eta(j,5)\n  enddo\n  if (i .lt. (nd-4)) S(0,5) = w(0)*S(0,4)\n  do l = -1, -3, -1\n      if ( ((i+l) .ge. 0) .and. ((i+l) .lt. (nd-4)) ) &\n          S(l,5) = w(l)*S(l,4) + (1.0_rp - w(l+1))*S(l+1,4)\n  enddo\n  if ((i-4) .ge. 0) S(-4,5) = (1.0_rp - w(-3))*S(-3,4)\n  if (kmax .eq. 5) return  !Exit if only 5th order spline is needed\n\n  ! k = 6\n  do l = 0, -4, -1\n    j = i + l\n    if (j .lt. 0) exit  !Skip out-of-bounds splines\n    w(l) = (x - nodes(j)) * eta(j,6)\n  enddo\n  if (i .lt. (nd-5)) S(0,6) = w(0)*S(0,5)\n  do l = -1, -4, -1\n    if ( ((i+l) .ge. 0) .and. ((i+l) .lt. (nd-5)) ) &\n        S(l,6) = w(l)*S(l,5) + (1.0_rp - w(l+1))*S(l+1,5)\n  enddo\n  if ((i-5) .ge. 0) S(-5,6) = (1.0_rp - w(-4))*S(-4,5)\n\n  return\n\nend subroutine bspline\n\n!==================================================================================================\n! DILOG: Calculate dilogarithm in the domain [0,1)\n! Retains terms up to order 3 in the expansion, which results in relative errors less than 1E-5.\n! Reference: \n!   Ginsberg, E. S., and D. Zaborowski (1975), The Dilogarithm function of a real argument, \n!   Commun. ACM, 18, 200202.\n!==================================================================================================\nreal(kind=rp) function dilog(x0)\n\n  use msis_constants, only     : rp, pi\n\n  implicit none\n\n  real(kind=rp), intent(in)   :: x0\n  real(kind=rp), parameter    :: pi2_6 = pi*pi / 6.0_rp\n  real(kind=rp)               :: x, xx, x4, lnx\n\n  x = x0\n  if (x .gt. 0.5_rp) then\n    lnx = log(x)\n    x = 1.0_rp - x          !Reflect argument into [0,0.5] range\n    xx = x*x\n    x4 = 4.0_rp*x\n    dilog = pi2_6 - lnx*log(x) &\n            - (4.0_rp*xx*(23.0_rp/16.0_rp + x/36.0_rp + xx/576.0_rp + xx*x/3600.0_rp) &\n                + x4 + 3.0_rp*(1.0_rp - xx)*lnx) / (1.0_rp + x4 + xx)\n  else\n    xx = x*x\n    x4 = 4.0_rp*x\n    dilog = (4.0_rp*xx*(23.0_rp/16.0_rp + x/36.0_rp + xx/576.0_rp + xx*x/3600.0_rp) &\n              + x4 + 3.0_rp*(1.0_rp - xx)*log(1.0_rp - x)) / (1.0_rp + x4 + xx)\n  endif\n\n  return\n\nend function dilog\n"
  },
  {
    "path": "source/external/nrlmsis2/msis_constants.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n\n!**************************************************************************************************\n! MSIS_CONSTANTS Module: Contains constants and hardwired parameters\n!**************************************************************************************************\nmodule msis_constants\n\n  implicit none\n\n  ! Floating Point Precision\n#ifdef DBLE\n  integer, parameter         :: rp = 8\n#else\n  integer, parameter         :: rp = 4\n#endif\n\n  ! Missing density value\n  real(kind=rp),parameter    :: dmissing = 9.999e-38_rp\n\n  ! Trigonometric constants\n  real(kind=rp), parameter   :: pi = 3.1415926535897932384626433832795_rp\n  real(kind=rp), parameter   :: deg2rad = pi / 180.0_rp\n  real(kind=rp), parameter   :: doy2rad = 2.0_rp*pi / 365.0_rp\n  real(kind=rp), parameter   :: lst2rad = pi / 12.0_rp\n  !real(kind=rp), parameter   :: tanh1 = 0.761594155955765485_rp  ! tanh(1.0)\n  real(kind=rp), parameter   :: tanh1 = tanh(1.0_rp)\n\n  ! Thermodynamic constants\n  ! Boltzmann constant (CODATA 2018) (J/kg)\n  real(kind=rp), parameter   :: kB = 1.380649e-23_rp\n  ! Avogadro constant (CODATA 2018)\n  real(kind=rp), parameter   :: NA = 6.02214076e23_rp\n  ! Reference gravity (CIMO Guide 2014) (m/s^2) (specified separately in alt2gph.f90)\n  real(kind=rp), parameter   :: g0 = 9.80665_rp\n  ! Species molecular masses (kg/molecule) (CIPM 2007)\n  real(kind=rp), parameter   :: specmass(1:10) = (/  0.0_rp,                          & ! Mass density (dummy value)\n                                                    28.0134_rp,                       & ! N2\n                                                    31.9988_rp,                       & ! O2\n                                                    31.9988_rp/2.0_rp,                & ! O\n                                                     4.0_rp,                          & ! He\n                                                     1.0_rp,                          & ! H\n                                                    39.948_rp,                        & ! Ar\n                                                    28.0134_rp/2.0_rp,                & ! N\n                                                    31.9988_rp/2.0_rp,                & ! Anomalous O\n                                                    (28.0134_rp+31.9988_rp)/2.0_rp /) & ! NO\n                                                    / (1.0e3_rp * NA)                   ! Convert from g/mol to kg/molecule\n  ! Dry air mean mass in fully mixed atmosphere (CIPM 2007) (includes CO2 and other trace species that are not yet in MSIS)\n  real(kind=rp), parameter   :: Mbar = 28.96546_rp / (1.0e3_rp * NA)   ! kg/molecule\n  ! Dry air log volume mixing ratios (CIPM 2007)\n  real(kind=rp), parameter   :: lnvmr(1:10) = log( (/ 1.0_rp,        & ! Mass density (dummy value)\n                                                      0.780848_rp,   & ! N2\n                                                      0.209390_rp,   & ! O2\n                                                      1.0_rp,        & ! O (dummy value)\n                                                      0.0000052_rp,  & ! He\n                                                      1.0_rp,        & ! H (dummy value)\n                                                      0.009332_rp,   & ! Ar\n                                                      1.0_rp,        & ! N (dummy value)\n                                                      1.0_rp,        & ! Anomalous O (dummy value)\n                                                      1.0_rp /) )      ! NO (dummy value)\n  ! Natural log of global average surface pressure (Pa)\n  !real(kind=rp), parameter   :: lnP0 = 11.5080482 !+ 0.00759597 After calibration with MERRA2\n  real(kind=rp), parameter   :: lnP0 = 11.515614\n  ! Derived constants\n  real(kind=rp), parameter   :: g0divkB = g0/kB * 1.0e3_rp  ! K/(kg km)\n  real(kind=rp), parameter   :: Mbarg0divkB = Mbar*g0/kB * 1.0e3_rp   ! K/km\n  ! References:\n  ! CODATA Internationally recommended 2018 values of the fundamental physical constants.\n  !   https://pml.nist.gov/cuu/Constants/; https://pml.nist.gov/cuu/pdf/wallet_2018.pdf\n  ! Picard, A., Davis, R. S., Glaeser, M., and Fujii, K. (2007). Revised formula for the density of\n  !   air (CIPM 2007). Metrologia 45, 149155. doi:10.1088/0026-1394/45/2/004\n  ! World Meteorological Organization (2014). WMO guide to meteorological instruments and methods of observation\n  !   (the CIMO Guide). Part I, Chapter 12. https://www.wmo.int/pages/prog/www/IMOP/CIMO-Guide.html\n\n  ! Vertical profile parameters\n  integer, parameter         :: nspec = 11  !Number of species including temperature\n  integer, parameter         :: nd = 27     !Number of temperature profile nodes\n  integer, parameter         :: p = 4       !Spline order\n  integer, parameter         :: nl = nd - p !Last temperature profile level index\n  integer, parameter         :: nls = 9     !Last parameter index for each species (excluding O, NO splines)\n  real(kind=rp), parameter   :: bwalt = 122.5_rp ! Reference geopotential height for Bates Profile\n  real(kind=rp), parameter   :: zetaF = 70.0_rp  ! Fully mixed below this, uses constant mixing ratios\n  real(kind=rp), parameter   :: zetaB = bwalt    ! Bates Profile above this altitude\n  real(kind=rp), parameter   :: zetaA = 85.0_rp  ! Default reference height for active minor species\n  real(kind=rp), parameter   :: zetagamma = 100.0_rp  ! Reference height of tanh taper of chemical/dynamical correction scale height\n  real(kind=rp), parameter   :: Hgamma = 1.0_rp/30.0_rp  ! Inverse scale height of tanh taper of chemical/dynamical correction scale height\n  real(kind=rp), parameter   :: nodesTN(0:nd+2) = &  !Nodes for temperature profile splines\n      (/ -15., -10.,  -5.,   0.,   5., 10., 15., 20.,  25.,  30.,  35.,  40., 45., 50., &\n          55.,  60.,  65.,  70.,  75., 80., 85., 92.5, 102.5, 112.5, 122.5, 132.5, 142.5, &\n          152.5, 162.5, 172.5/)\n  integer, parameter         :: izfmx = 13       ! fully mixed below this spline index\n  integer, parameter         :: izfx = 14        ! Spline index at zetaF\n  integer, parameter         :: izax = 17        ! Spline index at zetaA\n  integer, parameter         :: itex = nl        ! Index of Bates exospheric temperature\n  integer, parameter         :: itgb0 = nl - 1   ! Index of Bates temperature gradient at lower boundary\n  integer, parameter         :: itb0 = nl - 2    ! Index of Bates temperature at lower boundary\n  ! O1 Spline parameters\n  integer, parameter         :: ndO1 = 13\n  integer, parameter         :: nsplO1 = ndO1-5     !Number of unconstrained spline parameters for O1 (there are 2 additional C1-constrained splines)\n  real(kind=rp), parameter   :: nodesO1(0:ndO1) = & !Nodes for O1 splines (Domain 50-85 km)\n      (/ 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 92.5, 102.5, 112.5/)\n  real(kind=rp), parameter   :: zetarefO1 = zetaA   !Joining height for O1 splines, and reference height for O1 density\n  ! NO Spline parameters\n  integer, parameter         :: ndNO = 13\n  integer, parameter         :: nsplNO = ndNO-5     !Number of unconstrained spline parameters for NO (there are 2 additional C1-constrained splines)\n  real(kind=rp), parameter   :: nodesNO(0:ndNO) = & !Nodes for NO splines (Domain 70-122.5 km)\n      (/ 47.5, 55., 62.5, 70., 77.5, 85., 92.5, 100., 107.5, 115., 122.5, 130., 137.5, 145./)\n  real(kind=rp), parameter   :: zetarefNO = zetaB   !Joining height for NO splines, and reference height for NO density\n  !C2 Continuity matrix for temperature; Last 3 splines are constrained (must be recomputed if nodes change)\n  real(kind=rp), parameter   :: c2tn(3,3) = reshape((/1.0_rp, -10.0_rp,  33.333333333333336_rp, &\n                                                      1.0_rp,   0.0_rp, -16.666666666666668_rp, &\n                                                      1.0_rp,  10.0_rp,  33.333333333333336_rp/), &\n                                                    (/3,3/))\n  !C1 Continuity for O1; Last 2 splines are constrained (must be recomputed if nodes change)\n  real(kind=rp), parameter   :: c1o1(2,2) = reshape((/ 1.75_rp,               -2.916666573405061_rp, &\n                                                      -1.624999900076852_rp,  21.458332647194382_rp /), &\n                                                    (/2,2/))\n  real(kind=rp), parameter   :: c1o1adj(2) = (/0.257142857142857_rp, -0.102857142686844_rp/) !Weights for coefficents on 3rd to last spline; product to be subtracted from RHS of continuity equation\n  !C1 Continuity for NO; Last 2 splines are constrained (must be recomputed if nodes change)\n  real(kind=rp), parameter   :: c1NO(2,2) = reshape((/ 1.5_rp, -3.75_rp, &\n                                                       0.0_rp,  15.0_rp /), &\n                                                    (/2,2/))\n  real(kind=rp), parameter   :: c1NOadj(2) = (/0.166666666666667_rp, -0.066666666666667_rp/) !Weights for coefficents on 3rd to last spline; product to be subtracted from RHS of continuity equation\n  ! Anomalous Oxygen parameters (legacy profile from NRLMSISE-00)\n  real(kind=rp),parameter    :: zetarefOA = zetaB   !Reference height for anomalous oxygen density\n  real(kind=rp),parameter    :: TOA = 4000.         !Temperature of anomalous oxygen density (K)\n  real(kind=rp),parameter    :: HOA = (kB * TOA) / ( (16.0_rp/(1.0e3_rp*NA)) * g0 ) * 1.0e-3_rp  !Hydrostatic scale height of anomalous oxygen density (km)\n    \n  ! Horizontal and time-dependent basis function (gfn) parameters\n  integer, parameter      :: maxnbf = 512   ! Number of basis functions to be allocated\n  integer, parameter      :: maxn = 6       ! Maximum latitude (Legendre) spectral degree\n  integer, parameter      :: maxl = 3       ! Maximum local time (tidal) spectral order\n  integer, parameter      :: maxm = 2       ! Maximum longitude (stationary planetary wave) order\n  integer, parameter      :: maxs = 2       ! Maximimum day of year (intra-annual) Fourier order\n  integer, parameter      :: amaxn = 6      ! Maximum Legendre degree used in time independent and intra-annual zonal mean terms\n  integer, parameter      :: amaxs = 2      ! Maximum intra-annual order used in zonal mean terms\n  integer, parameter      :: tmaxl = 3      ! Maximum tidal order used\n  integer, parameter      :: tmaxn = 6      ! Maximum Legendre degree coupled with tides\n  integer, parameter      :: tmaxs = 2      ! Maximum intra-annual order coupled with tides\n  integer, parameter      :: pmaxm = 2      ! Maximum stationary planetary wave order used\n  integer, parameter      :: pmaxn = 6      ! Maximum Legendre degree coupled with SPW\n  integer, parameter      :: pmaxs = 2      ! Maximum intra-annual order coupled with SPW\n  integer, parameter      :: nsfx = 5       ! Number of linear solar flux terms\n  integer, parameter      :: nsfxmod = 5    ! Number of nonlinear modulating solar flux terms (legacy NRLMSISE-00 terms)\n  integer, parameter      :: nmag = 54      ! Number of terms in NRLMSISE-00 legacy geomagnetic parameterization\n  integer, parameter      :: nut = 12       ! Number of terms in NRLMSISE-00 legacy UT parameterization\n  integer, parameter      :: ctimeind = 0             ! Starting index of time-independent terms\n  integer, parameter      :: cintann = ctimeind + (amaxn+1)   ! Starting index of zonal mean intra-annual terms\n  integer, parameter      :: ctide = cintann + ((amaxn+1)*2*amaxs)   ! Starting index of zonal mean intra-annual terms\n  integer, parameter      :: cspw = ctide + (4*tmaxs+2)*(tmaxl*(tmaxn+1)-(tmaxl*(tmaxl+1))/2) ! Starting index of SPW terms\n  integer, parameter      :: csfx = cspw + (4*pmaxs+2)*(pmaxm*(pmaxn+1)-(pmaxm*(pmaxm+1))/2)   ! Starting index of linear solar flux terms\n  integer, parameter      :: cextra = csfx + nsfx     ! Starting index of time-independent terms\n  integer, parameter      :: mbf = 383                ! Last index of linear terms\n  integer, parameter      :: cnonlin = mbf + 1        ! Starting index of nonlinear terms\n  integer, parameter      :: csfxmod = cnonlin        ! Starting index of modulating solar flux terms\n  integer, parameter      :: cmag = csfxmod + nsfxmod ! Starting index of daily geomagnetic terms\n  integer, parameter      :: cut = cmag + nmag        ! Starting index of UT terms\n    \n  ! Weights for calculation log pressure spline coefficients from temperature coefficients (must be recalcuated if nodes change)\n  real(kind=rp), parameter   :: gwht(0:3) =  (/ 5.0_rp/24.0_rp, 55.0_rp/24.0_rp, 55.0_rp/24.0_rp, 5.0_rp/24.0_rp /)\n\n  ! Constants needed for analytical integration by parts of hydrostatic piecewise effective mass profile\n  real(kind=rp), parameter   :: wbeta(0:nl) =  (nodesTN(4:nd)  - nodesTN(0:nl)) / 4.0_rp !Weights for 1st spline integration\n  real(kind=rp), parameter   :: wgamma(0:nl) = (nodesTN(5:nd+1)- nodesTN(0:nl)) / 5.0_rp !Weights for 2nd spline integration\n  ! Non-zero bspline values at zetaB (5th and 6th order) (must be recalcuated if nodes change)\n  real(kind=rp), parameter   :: S5zetaB(0:3) = (/0.041666666666667_rp, 0.458333333333333_rp, 0.458333333333333_rp, &\n                                                 0.041666666666667_rp/)\n  real(kind=rp), parameter   :: S6zetaB(0:4) = (/0.008771929824561_rp, 0.216228070175439_rp, 0.550000000000000_rp, &\n                                                 0.216666666666667_rp, 0.008333333333333_rp/)\n  !Weights for calculating temperature gradient at zetaA (must be recalcuated if nodes change)\n  real(kind=rp), parameter   :: wghtAxdz(0:2) = (/-0.102857142857_rp, 0.0495238095238_rp, 0.053333333333_rp/)\n  !Non-zero bspline values at zetaA (4th, 5th and 6th order) (must be recalcuated if nodes change)\n  real(kind=rp), parameter   :: S4zetaA(0:2) = (/0.257142857142857_rp, 0.653968253968254_rp, 0.088888888888889_rp/)\n  real(kind=rp), parameter   :: S5zetaA(0:3) = (/0.085714285714286_rp, 0.587590187590188_rp, 0.313020313020313_rp, &\n                                                 0.013675213675214_rp/)\n  real(kind=rp), parameter   :: S6zetaA(0:4) = (/0.023376623376623_rp, 0.378732378732379_rp, 0.500743700743701_rp, &\n                                                 0.095538448479625_rp, 0.001608848667672_rp/)\n  !Non-zero bspline values at zetaF (4th and 5th order) (must be recalcuated if nodes change)\n  real(kind=rp), parameter   :: S4zetaF(0:2) = (/0.166666666666667_rp, 0.666666666666667_rp, 0.166666666666667_rp/)\n  real(kind=rp), parameter   :: S5zetaF(0:3) = (/0.041666666666667_rp, 0.458333333333333_rp, 0.458333333333333_rp, &\n                                                 0.041666666666667_rp/)\n  !Non-zero bspline values at zeta=0 (5th order) (must be recalcuated if nodes change)\n  real(kind=rp), parameter   :: S5zeta0(0:2) = (/0.458333333333333_rp, 0.458333333333333_rp, 0.041666666666667_rp/)\n\nend module msis_constants\n"
  },
  {
    "path": "source/external/nrlmsis2/msis_dfn.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n\n!**************************************************************************************************\n! MSIS_DFN Module: Contains vertical species density profile parameters and subroutines\n!**************************************************************************************************\nmodule msis_dfn\n\n  use msis_constants, only : rp, nl, nsplO1, nsplNO\n\n  type dnparm\n    sequence\n    real(kind=rp)         :: lnPhiF            ! (Except O, H) Natural log of mixing ratio at zetaF (70 km), before chemical and dynamical corrections are applied (ln m^-3) (global term only)\n    real(kind=rp)         :: lndref            ! Natural log of number density at reference height\n    real(kind=rp)         :: zetaM             ! \"Turbopause Height\": Height of midpoint of effective mass transition (km)\n    real(kind=rp)         :: HML               ! Scale height of lower portion of effective mass profile (km)\n    real(kind=rp)         :: HMU               ! Scale height of upper portion of effective mass profile (km)\n    real(kind=rp)         :: C                 ! Chapman term coefficient\n    real(kind=rp)         :: zetaC             ! Chapman term reference height (km)\n    real(kind=rp)         :: HC                ! Chapman term scale height (km)\n    real(kind=rp)         :: R                 ! Chemical/dynamical term coefficient\n    real(kind=rp)         :: zetaR             ! Chemical/dynamical term reference height (km)\n    real(kind=rp)         :: HR                ! Chemical/dynamical term scale height (km)\n    real(kind=rp)         :: cf(0:nsplO1+1)    ! Merged spline coefficients (for chemistry-dominated region of O1, NO, and (eventually), H, N)\n    real(kind=rp)         :: zref              ! Reference height for hydrostatic integral and ideal gas terms\n    real(kind=rp)         :: Mi(0:4)           ! Effective mass at nodes of piecewise mass profile (derived from zetaM, HML, HMU)\n    real(kind=rp)         :: zetaMi(0:4)       ! Height of nodes of piecewise mass profile (derived from zetaM, HML, HMU)\n    real(kind=rp)         :: aMi(0:4) = 0.0_rp ! Slopes of piecewise mass profile segments (derived from zetaM, HML, HMU)\n    real(kind=rp)         :: WMi(0:4) = 0.0_rp ! 2nd indefinite integral of 1/T at mass profile nodes\n    real(kind=rp)         :: XMi(0:4) = 0.0_rp ! Cumulative adjustment to M/T integral due to changing effective mass\n    real(kind=rp)         :: Izref             ! Indefinite hydrostatic integral at reference height\n    real(kind=rp)         :: Tref              ! Temperature at reference height (for ideal gas law term)\n    real(kind=rp)         :: zmin              ! Minimum height of profile (missing values below)\n    real(kind=rp)         :: zhyd              ! Hydrostatic terms needed above this height\n    integer(kind=rp)      :: ispec             ! Species index\n  end type dnparm\n\n  contains\n\n  !==================================================================================================\n  ! DFNPARM: Compute the species density profile parameters\n  !==================================================================================================\n  subroutine dfnparm(ispec,gf,tpro,dpro)\n\n    use msis_constants, only   : tanh1, specmass, lnvmr, Mbar, g0divkB, &\n                                 nd, zetaF, zetaB, zetaA, nodesTN, &\n                                 nodesO1, zetarefO1, c1o1, c1o1adj, &\n                                 nodesNO, zetarefNO, c1NO, c1NOadj, &\n                                 zetarefOA, &\n                                 maxnbf, mbf, nmag, nut, cmag, cut\n    use msis_init, only        : etaTN, TN,PR,N2,O2,O1,HE,H1,AR,N1,OA,NO, N2Rflag, &\n                                 HRfactO1ref, dHRfactO1ref, HRfactNOref, dHRfactNOref\n    use msis_gfn, only         : sfluxmod, geomag, utdep\n    use msis_tfn, only         : tnparm\n\n    implicit none\n\n    real(kind=rp), external  :: dilog\n\n    integer, intent(in)       :: ispec          ! Species index\n    real(kind=rp), intent(in) :: gf(0:maxnbf-1) ! Array of horizontal and temporal basis function terms   \n    type(tnparm), intent(in)  :: tpro           ! Structure containing temperature vertical profile parameters\n    type(dnparm), intent(out) :: dpro           ! Output structure containing density vertical profile parameters\n        \n    integer                   :: izf, i, i1, iz\n    real(kind=rp)             :: Cterm, Rterm0, Rterm\n    real(kind=rp)             :: bc(2)\n    real(kind=rp)             :: hbetaL,hbetaU\n    real(kind=rp)             :: delM, delz\n    real(kind=rp)             :: Wi           ! 2nd indefinite integral at a piecewise mass profile node\n    real(kind=rp)             :: Si(-5:0,2:6) ! Array of b-spline values at a mass profile node\n    real(kind=rp)             :: Mzref        ! Effective mass at reference altitude\n\n    dpro%ispec = ispec\n\n    select case(ispec)\n\n    ! Molecular Nitrogen ----------------------\n    case(2)\n      ! Mixing ratio and reference number density\n      dpro%lnPhiF = lnvmr(ispec)\n      dpro%lndref = tpro%lndtotF + dpro%lnPhiF\n      dpro%zref = zetaF\n      dpro%zmin = -1.0_rp\n      dpro%zhyd = zetaF\n      ! Effective mass\n      dpro%zetaM = dot_product(N2%beta(0:mbf,1),gf(0:mbf))\n      dpro%HML   = N2%beta(0,2)\n      dpro%HMU   = N2%beta(0,3)\n      ! Photochemical correction\n      dpro%R     = 0.0_rp\n      if (N2Rflag) dpro%R = dot_product(N2%beta(0:mbf,7),gf(0:mbf))\n      dpro%zetaR = N2%beta(0,8)\n      dpro%HR    = N2%beta(0,9)\n\n    ! Molecular Oxygen ------------------------\n    case(3)\n      ! Mixing ratio and reference number density\n      dpro%lnPhiF = lnvmr(ispec)\n      dpro%lndref = tpro%lndtotF + dpro%lnPhiF\n      dpro%zref = zetaF\n      dpro%zmin = -1.0_rp\n      dpro%zhyd = zetaF\n      ! Effective mass\n      dpro%zetaM = O2%beta(0,1)\n      dpro%HML   = O2%beta(0,2)\n      dpro%HMU   = O2%beta(0,3)\n      ! Photochemical correction\n      dpro%R     = dot_product(O2%beta(0:mbf,7),gf(0:mbf))\n      dpro%R     = dpro%R + geomag(O2%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%zetaR = O2%beta(0,8)\n      dpro%HR    = O2%beta(0,9)\n\n    ! Atomic Oxygen --------------------------\n    case(4)\n      ! Reference number density\n      dpro%lnPhiF = 0.0_rp\n      dpro%lndref = dot_product(O1%beta(0:mbf,0),gf(0:mbf))\n      dpro%zref = zetarefO1\n      dpro%zmin = nodesO1(3)\n      dpro%zhyd = zetarefO1\n      ! Effective mass\n      dpro%zetaM = O1%beta(0,1)\n      dpro%HML   = O1%beta(0,2)\n      dpro%HMU   = O1%beta(0,3)\n      ! Chapman correction\n      dpro%C     = dot_product(O1%beta(0:mbf,4),gf(0:mbf))\n      dpro%zetaC = O1%beta(0,5)\n      dpro%HC    = O1%beta(0,6)\n      ! Dynamical correction\n      dpro%R     = dot_product(O1%beta(0:mbf,7),gf(0:mbf))\n      dpro%R     = dpro%R + sfluxmod(7,gf,O1,0.0_rp)         \n      dpro%R     = dpro%R + geomag(O1%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%R     = dpro%R + utdep(O1%beta(cut:cut+nut-1,7),gf(cut:cut+8))\n      dpro%zetaR = O1%beta(0,8)\n      dpro%HR    = O1%beta(0,9)\n      ! Unconstrained splines\n      do izf = 0, nsplO1-1\n        dpro%cf(izf) = dot_product(O1%beta(0:mbf,izf+10),gf(0:mbf))\n      enddo\n      ! Constrained splines calculated after case statement\n\n    ! Helium ----------------------\n    case(5)\n      ! Mixing ratio and reference number density\n      dpro%lnPhiF = lnvmr(ispec)\n      dpro%lndref = tpro%lndtotF + dpro%lnPhiF\n      dpro%zref = zetaF\n      dpro%zmin = -1.0_rp\n      dpro%zhyd = zetaF\n      ! Effective mass\n      dpro%zetaM = HE%beta(0,1)\n      dpro%HML   = HE%beta(0,2)\n      dpro%HMU   = HE%beta(0,3)\n      ! Dynamical correction\n      dpro%R     = dot_product(HE%beta(0:mbf,7),gf(0:mbf))\n      dpro%R     = dpro%R + sfluxmod(7,gf,HE,1.0_rp)         \n      dpro%R     = dpro%R + geomag(HE%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%R     = dpro%R + utdep(HE%beta(cut:cut+nut-1,7),gf(cut:cut+8))\n      dpro%zetaR = HE%beta(0,8)\n      dpro%HR    = HE%beta(0,9)\n\n    ! Atomic Hydrogen ----------------------\n    case(6)\n      ! Reference number density\n      dpro%lnPhiF = 0.0_rp\n      dpro%lndref = dot_product(H1%beta(0:mbf,0),gf(0:mbf))\n      dpro%zref = zetaA\n      dpro%zmin = 75.0_rp\n      dpro%zhyd = zetaF\n      ! Effective mass\n      dpro%zetaM = H1%beta(0,1)\n      dpro%HML   = H1%beta(0,2)\n      dpro%HMU   = H1%beta(0,3)\n      ! Chapman correction\n      dpro%C     = dot_product(H1%beta(0:mbf,4),gf(0:mbf))\n      dpro%zetaC = dot_product(H1%beta(0:mbf,5),gf(0:mbf))\n      dpro%HC    = H1%beta(0,6)\n      ! Dynamical correction\n      dpro%R     = dot_product(H1%beta(0:mbf,7),gf(0:mbf))\n      dpro%R     = dpro%R + sfluxmod(7,gf,H1,0.0_rp)        \n      dpro%R     = dpro%R + geomag(H1%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%R     = dpro%R + utdep(H1%beta(cut:cut+nut-1,7),gf(cut:cut+8))\n      dpro%zetaR = H1%beta(0,8)\n      dpro%HR    = H1%beta(0,9)\n\n    ! Argon ----------------------\n    case(7)\n      ! Mixing ratio and reference number density\n      dpro%lnPhiF = lnvmr(ispec)\n      dpro%lndref = tpro%lndtotF + dpro%lnPhiF\n      dpro%zref = zetaF\n      dpro%zmin = -1.0_rp\n      dpro%zhyd = zetaF\n      ! Effective mass\n      dpro%zetaM = AR%beta(0,1)\n      dpro%HML   = AR%beta(0,2)\n      dpro%HMU   = AR%beta(0,3)\n      ! Dynamical correction\n      dpro%R     = dot_product(AR%beta(0:mbf,7),gf(0:mbf))\n      dpro%R     = dpro%R + geomag(AR%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%R     = dpro%R + utdep(AR%beta(cut:cut+nut-1,7),gf(cut:cut+8))\n      dpro%zetaR = AR%beta(0,8)\n      dpro%HR    = AR%beta(0,9)\n\n    ! Atomic Nitrogen ----------------------\n    case(8)\n      ! Reference number density\n      dpro%lnPhiF = 0.0_rp\n      dpro%lndref = dot_product(N1%beta(0:mbf,0),gf(0:mbf))\n      dpro%lndref = dpro%lndref + sfluxmod(0,gf,N1,0.0_rp)         \n      dpro%lndref = dpro%lndref + geomag(N1%beta(cmag:cmag+nmag-1,0),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%lndref = dpro%lndref + utdep(N1%beta(cut:cut+nut-1,0),gf(cut:cut+8))\n      dpro%zref = zetaB\n      dpro%zmin = 90.0_rp\n      dpro%zhyd = zetaF\n      ! Effective mass\n      dpro%zetaM = N1%beta(0,1)\n      dpro%HML   = N1%beta(0,2)\n      dpro%HMU   = N1%beta(0,3)\n      ! Chapman correction\n      dpro%C     = N1%beta(0,4)\n      dpro%zetaC = N1%beta(0,5)\n      dpro%HC    = N1%beta(0,6)\n      ! Dynamical correction\n      dpro%R     = dot_product(N1%beta(0:mbf,7),gf(0:mbf))\n      dpro%zetaR = N1%beta(0,8)\n      dpro%HR    = N1%beta(0,9)\n\n    ! Anomalous Oxygen ----------------------\n    case(9)\n      dpro%lndref = dot_product(OA%beta(0:mbf,0),gf(0:mbf))\n      dpro%lndref = dpro%lndref + geomag(OA%beta(cmag:cmag+nmag-1,0),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n      dpro%zref = zetarefOA\n      dpro%zmin = 120.0_rp\n      dpro%zhyd = 0.0_rp\n      dpro%C     = OA%beta(0,4)\n      dpro%zetaC = OA%beta(0,5)\n      dpro%HC    = OA%beta(0,6)\n      return !No further parameters needed for legacy anomalous oxygen profile\n\n    ! Nitic Oxide ----------------------\n    case(10)\n      ! Skip if parameters are not defined\n      if (NO%beta(0,0) .eq. 0.0_rp) then\n          dpro%lndref = 0.0_rp\n          return\n      endif\n      ! Reference number density\n      dpro%lnPhiF = 0.0_rp\n      dpro%lndref = dot_product(NO%beta(0:mbf,0),gf(0:mbf))\n      dpro%zref = zetarefNO\n      dpro%zmin = nodesNO(3)\n      dpro%zhyd = zetarefNO\n      ! Effective mass\n      dpro%zetaM = dot_product(NO%beta(0:mbf,1),gf(0:mbf))\n      dpro%HML   = dot_product(NO%beta(0:mbf,2),gf(0:mbf))\n      dpro%HMU   = dot_product(NO%beta(0:mbf,3),gf(0:mbf))\n      ! Chapman correction\n      dpro%C     = dot_product(NO%beta(0:mbf,4),gf(0:mbf))\n      dpro%zetaC = dot_product(NO%beta(0:mbf,5),gf(0:mbf))\n      dpro%HC    = dot_product(NO%beta(0:mbf,6),gf(0:mbf))\n      ! Dynamical correction\n      dpro%R     = dot_product(NO%beta(0:mbf,7),gf(0:mbf))\n      dpro%zetaR = dot_product(NO%beta(0:mbf,8),gf(0:mbf))\n      dpro%HR    = dot_product(NO%beta(0:mbf,9),gf(0:mbf))\n      ! Unconstrained splines\n      do izf = 0,nsplNO-1\n          dpro%cf(izf) = dot_product(NO%beta(0:mbf,izf+10),gf(0:mbf))\n      enddo\n      ! Constrained splines calculated after case statement\n\n! Failsafe -----   ---------------------------\n    case default\n      stop 'Species not yet implemented'\n\n    endselect\n        \n    ! Compute piecewise mass profile values and integration terms\n    dpro%zetaMi(0) = dpro%zetaM - 2.0_rp*dpro%HML\n    dpro%zetaMi(1) = dpro%zetaM - dpro%HML\n    dpro%zetaMi(2) = dpro%zetaM\n    dpro%zetaMi(3) = dpro%zetaM + dpro%HMU\n    dpro%zetaMi(4) = dpro%zetaM + 2.0_rp*dpro%HMU\n    dpro%Mi(0) = Mbar\n    dpro%Mi(4) = specmass(ispec)\n    dpro%Mi(2) = (dpro%Mi(0) + dpro%Mi(4)) / 2.0_rp\n    delM = tanh1 * (dpro%Mi(4) - dpro%Mi(0)) / 2.0_rp\n    dpro%Mi(1) = dpro%Mi(2) - delM\n    dpro%Mi(3) = dpro%Mi(2) + delM\n    !do i = 0, 4\n    !  i1 = i + 1\n    !  if (i .lt. 4) dpro%aMi(i) = (dpro%Mi(i1) - dpro%Mi(i)) / (dpro%zetaMi(i1) - dpro%zetaMi(i))\n    !  delz = dpro%zetaMi(i) - zetaB\n    !  if (dpro%zetaMi(i) .lt. zetaB) then\n    !    call bspline(dpro%zetaMi(i),nodesTN,nd+2,6,etaTN,Si,iz)\n    !    dpro%WMi(i) = dot_product(tpro%gamma(iz-5:iz),Si(:,6)) + tpro%cVS*delz + tpro%cWS\n    !  else\n    !    dpro%WMi(i) = (0.5_rp*delz*delz + dilog(tpro%b*exp(-tpro%sigma*delz))/tpro%sigmasq)/tpro%tex &\n    !                  + tpro%cVB*delz + tpro%cWB\n    !  endif\n    !end do\n    do i = 0, 3\n      dpro%aMi(i) = (dpro%Mi(i+1) - dpro%Mi(i)) / (dpro%zetaMi(i+1) - dpro%zetaMi(i))\n    enddo\n    do i = 0, 4\n      delz = dpro%zetaMi(i) - zetaB\n      if (dpro%zetaMi(i) .lt. zetaB) then\n        call bspline(dpro%zetaMi(i),nodesTN,nd+2,6,etaTN,Si,iz)\n        dpro%WMi(i) = dot_product(tpro%gamma(iz-5:iz),Si(:,6)) + tpro%cVS*delz + tpro%cWS\n      else\n        dpro%WMi(i) = (0.5_rp*delz*delz + dilog(tpro%b*exp(-tpro%sigma*delz))/tpro%sigmasq)/tpro%tex &\n                      + tpro%cVB*delz + tpro%cWB\n      endif\n    end do\n    dpro%XMi(0) = -dpro%aMi(0) * dpro%WMi(0)\n    do i = 1, 3\n      dpro%XMi(i) = dpro%XMi(i-1) - dpro%WMi(i) * (dpro%aMi(i) - dpro%aMi(i-1))\n    end do\n    dpro%XMi(4) = dpro%XMi(3) + dpro%WMi(4) * dpro%aMi(3)\n\n    ! Calculate hydrostatic integral at reference height, and copy temperature\n    if (dpro%zref .eq. zetaF) then\n      Mzref = Mbar\n      dpro%Tref = tpro%TzetaF\n      dpro%Izref = Mbar * tpro%VzetaF\n    else if (dpro%zref .eq. zetaB) then\n      Mzref = pwmp(dpro%zref,dpro%zetaMi,dpro%Mi,dpro%aMi)\n      dpro%Tref = tpro%Tb0\n      dpro%Izref = 0.0_rp\n      if ((zetaB .gt. dpro%zetaMi(0)) .and. (zetaB .lt. dpro%zetaMi(4))) then\n        i = 0\n        do i1 = 1, 3\n          if (zetaB .lt. dpro%zetaMi(i1)) then\n            exit\n          else\n            i = i1\n          endif\n        enddo\n        dpro%Izref = dpro%Izref -  dpro%XMi(i)\n      else\n        dpro%Izref = dpro%Izref - dpro%XMi(4)                \n      endif\n    else if (dpro%zref .eq. zetaA) then\n      Mzref = pwmp(dpro%zref,dpro%zetaMi,dpro%Mi,dpro%aMi)\n      dpro%Tref = tpro%TzetaA\n      dpro%Izref = Mzref * tpro%VzetaA\n      if ((zetaA .gt. dpro%zetaMi(0)) .and. (zetaA .lt. dpro%zetaMi(4))) then\n        i = 0\n        do i1 = 1, 3\n          if (zetaA .lt. dpro%zetaMi(i1)) then\n            exit\n          else\n            i = i1\n          endif\n        enddo\n        dpro%Izref = dpro%Izref - (dpro%aMi(i)*tpro%WzetaA + dpro%XMi(i))\n      else\n        dpro%Izref = dpro%Izref - dpro%XMi(4)                \n      endif\n    else \n      stop 'Integrals at reference height not available'\n    endif\n\n    ! C1 constraint for O1 at 85 km\n    if (ispec .eq. 4) then\n      Cterm = dpro%C*exp(-(dpro%zref-dpro%zetaC)/dpro%HC)\n      Rterm0 = tanh((dpro%zref-dpro%zetaR)/(HRfactO1ref*dpro%HR))\n      Rterm = dpro%R*(1+Rterm0)\n      bc(1) = dpro%lndref - Cterm + Rterm - dpro%cf(7)*c1o1adj(1)      !Reference density, Chapman term, logistic term, and subtraction of last unconstrained spline(7)\n      bc(2) = -Mzref*g0divkB/tpro%tzetaA &   !Gradient of hydrostatic term\n              -tpro%dlntdzA &  !Gradient of ideal gas law term\n              +Cterm/dpro%HC & !Gradient of Chapman term\n              +Rterm*(1-Rterm0)/dpro%HR*dHrfactO1ref  & !Gradient of tapered logistic term\n              -dpro%cf(7)*c1o1adj(2)  !Subtraction of gradient of last unconstrained spline(7)\n      ! Compute coefficients for constrained splines\n      dpro%cf(8:9) = matmul(bc,c1o1)\n    endif\n        \n    ! C1 constraint for NO at 122.5 km\n    if (ispec .eq. 10) then\n      Cterm = dpro%C*exp(-(dpro%zref - dpro%zetaC)/dpro%HC)\n      Rterm0 = tanh((dpro%zref-dpro%zetaR)/(HRfactNOref*dpro%HR))\n      Rterm = dpro%R*(1+Rterm0)\n      bc(1) = dpro%lndref - Cterm + Rterm - dpro%cf(7)*c1noadj(1)      !Reference density, Chapman term, logistic term, and subtraction of last unconstrained spline(7)\n      bc(2) = -Mzref*g0divkB/tpro%tb0 &   !Gradient of hydrostatic term\n              -tpro%tgb0/tpro%tb0 &  !Gradient of ideal gas law term\n              +Cterm/dpro%HC & !Gradient of Chapman term\n              +Rterm*(1-Rterm0)/dpro%HR*dHrfactNOref  & !Gradient of tapered logistic term\n              -dpro%cf(7)*c1noadj(2)  !Subtraction of gradient of last unconstrained spline(7)\n      ! Compute coefficients for constrained splines\n      dpro%cf(8:9) = matmul(bc,c1no)\n    endif\n        \n  return\n\n  end subroutine dfnparm\n\n  !==================================================================================================\n  ! DFNX: Compute a species density at specified geopotential height\n  !==================================================================================================\n  real(kind=rp) function dfnx(z,tnz,lndtotz,Vz,Wz,HRfact,tpro,dpro)\n\n    use msis_constants, only   : dmissing, g0divkB, ndO1, nodesO1, ndNO, nodesNO, HOA\n    use msis_init, only        : etaO1, etaNO\n    use msis_tfn, only         : tnparm\n\n    implicit none\n\n    real(kind=rp), intent(in) :: z            ! Geopotential height\n    real(kind=rp), intent(in) :: tnz, lndtotz ! Temperature, total number density at input z \n    real(kind=rp), intent(in) :: Vz, Wz       ! First and second indefinite integrals of 1/T at z\n    real(kind=rp), intent(in) :: HRfact       ! Reduction factor for chemical/dynamical correction scale height below zetaF\n    type(tnparm), intent(in)  :: tpro         ! Structure containing temperature vertical profile parameters\n    type(dnparm), intent(in)  :: dpro         ! Structure containing density vertical profile parameters\n\n    integer(4)                :: i, i1, iz\n    real(kind=rp)             :: Mz\n    real(kind=rp)             :: Sz(-5:0,2:6)\n    real(kind=rp)             :: Ihyd         ! Hydrostatic definite integral\n    real(kind=rp)             :: ccor         ! Chapman and logistical corrections\n\n    ! Below minimum height of profile\n    if (z .lt. dpro%zmin) then\n      dfnx = dmissing\n      return\n    endif\n        \n    ! Anomalous Oxygen (legacy MSISE-00 formulation)\n    if (dpro%ispec .eq. 9) then\n      dfnx = dpro%lndref - (z - dpro%zref)/HOA - dpro%C*exp(-(z-dpro%zetaC)/dpro%HC)\n      dfnx = exp(dfnx)\n      return               !No further calculation needed for anomalous oxygen\n    endif\n\n    ! Nitric Oxide: Skip if parameters are not defined\n    if (dpro%ispec .eq. 10) then\n      if (dpro%lndref .eq. 0.0_rp) then\n        dfnx = dmissing\n        return\n      endif\n    endif\n        \n    ! Chapman and logistic corrections\n    select case(dpro%ispec)\n    case(2,3,5,7)             !For N2, O2, He, and Ar: logistic correction only\n      ccor =   dpro%R*(1+tanh((z-dpro%zetaR)/(HRfact*dpro%HR)))\n    case(4,6,8,10)            !For O, H, N, and NO: Chapman and logistic corrections\n      ccor = - dpro%C*exp(-(z-dpro%zetaC)/dpro%HC) &\n             + dpro%R*(1+tanh((z-dpro%zetaR)/(HRfact*dpro%HR)))\n    endselect\n\n    ! Below height where hydrostatic terms are needed\n    if (z .lt. dpro%zhyd) then\n      select case(dpro%ispec)\n      case(2,3,5,7)           !For N2, O2, He, and Ar, apply mixing ratios and exit\n        dfnx = exp(lndtotz + dpro%lnPhiF + ccor)\n        return\n      case(4)                 !For O, evaluate splines\n        call bspline(z,nodesO1,ndO1,4,etaO1,Sz,iz)\n        dfnx = exp(dot_product(dpro%cf(iz-3:iz),Sz(-3:0,4)))\n        return\n      case(10)                !For NO, evaluate splines\n        call bspline(z,nodesNO,ndNO,4,etaNO,Sz,iz)\n        dfnx = exp(dot_product(dpro%cf(iz-3:iz),Sz(-3:0,4)))\n        return\n      endselect\n    endif\n        \n    ! Calculate hydrostatic term and apply to reference density\n    Mz = pwmp(z,dpro%zetaMi,dpro%Mi,dpro%aMi)\n    Ihyd = Mz * Vz - dpro%Izref\n    if ((z .gt. dpro%zetaMi(0)) .and. (z .lt. dpro%zetaMi(4))) then\n      i = 0\n      do i1 = 1, 3\n        if (z .lt. dpro%zetaMi(i1)) then\n          exit\n        else\n          i = i1\n        endif\n      enddo\n      Ihyd = Ihyd - (dpro%aMi(i)*Wz + dpro%XMi(i))\n    else if (z .ge. dpro%zetaMi(4)) then\n      Ihyd = Ihyd - dpro%XMi(4)                \n    endif\n    dfnx = dpro%lndref - Ihyd * g0divkB  + ccor\n        \n    ! Apply ideal gas law                \n    dfnx = exp(dfnx) * dpro%Tref/tnz\n\n    return\n\n  end function dfnx\n\n  !==================================================================================================\n  ! PWMP: Piecewise effective mass profile interpolation\n  !==================================================================================================\n  real(kind=rp) function pwmp(z,zm,m,dmdz)\n\n    use msis_constants, only   : rp\n\n    real(kind=rp), intent(in) :: z\n    real(kind=rp), intent(in) :: zm(0:4)\n    real(kind=rp), intent(in) :: m(0:4)\n    real(kind=rp), intent(in) :: dmdz(0:3)\n\n    integer                   :: irng  !Index of piecwise interval\n    integer                   :: inode\n\n    ! Most probable case\n    if (z .ge. zm(4)) then\n      pwmp = m(4)\n      return\n    endif\n\n    ! Second most probable case\n    if (z .le. zm(0)) then\n      pwmp = m(0)\n      return\n    endif\n\n    ! None of the above\n    do inode = 0,3\n      if (z .lt. zm(inode+1)) then\n        pwmp = m(inode) + dmdz(inode)*(z - zm(inode))\n        return\n      endif\n    enddo\n\n    ! If we are here this is a problem\n    stop 'Error in pwmp'\n\n  end function pwmp\n\nend module msis_dfn\n\n"
  },
  {
    "path": "source/external/nrlmsis2/msis_gfn.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n\n!**************************************************************************************************\n! MSIS_GFN Module: Contains subroutines to calculate global (horizontal and time-dependent) model \n!                  basis functions\n!**************************************************************************************************\nmodule msis_gfn\n\n  use msis_constants, only : rp, maxn\n  use msis_init, only      : TN,PR,N2,O2,O1,HE,H1,AR,N1,OA,NO, swg\n\n  implicit none\n  \n  real(kind=rp)                :: plg(0:maxn,0:maxn)\n  real(kind=rp)                :: cdoy(2), sdoy(2)\n  real(kind=rp)                :: clst(3), slst(3)\n  real(kind=rp)                :: clon(2), slon(2)\n  real(kind=rp)                :: sfluxavgref = 150.0 ! Reference F10.7 value (=150 in NRLMSISE-00)\n  real(kind=rp)                :: lastlat = -999.9\n  real(kind=rp)                :: lastdoy = -999.9\n  real(kind=rp)                :: lastlst = -999.9\n  real(kind=rp)                :: lastlon = -999.9\n \ncontains\n\n  !==================================================================================================\n  ! GLOBE: Calculate horizontal and time-dependent basis functions\n  !        (Same purpose as NRLMSISE-00 \"GLOBE7\" subroutine)\n  !==================================================================================================\n  subroutine globe(doy,utsec,lat,lon,sfluxavg,sflux,ap,bf)\n\n    use msis_constants, only    : deg2rad, doy2rad, lst2rad, &\n                                  maxnbf, mbf, maxn, amaxn, amaxs, tmaxl, tmaxn, tmaxs, pmaxm, pmaxn, pmaxs, &\n                                  nsfx, nsfxmod, ctimeind, cintann, ctide, cspw, csfx, cextra, cnonlin, csfxmod, cmag, cut\n    implicit none\n\n    real(kind=rp), intent(in)  :: doy                       ! Day of year\n    real(kind=rp), intent(in)  :: utsec                     ! Universal time in seconds\n    real(kind=rp), intent(in)  :: lat                       ! Latitude\n    real(kind=rp), intent(in)  :: lon                       ! Longitdue\n    real(kind=rp), intent(in)  :: sfluxavg                  ! 81-day average F10.7\n    real(kind=rp), intent(in)  :: sflux                     ! Daily F10.7\n    real(kind=rp), intent(in)  :: ap(1:7)                   ! Ap geomagnetic activity index history array\n    real(kind=rp), intent(out) :: bf(0:maxnbf-1)            ! Output array of basis function terms\n\n    real(kind=rp)              :: lst\n    real(kind=rp)              :: slat, clat, clat2, clat4, slat2\n    real(kind=rp)              :: cosdoy, sindoy\n    real(kind=rp)              :: coslon, sinlon\n    real(kind=rp)              :: pl\n    real(kind=rp)              :: coslst, sinlst\n    real(kind=rp)              :: dfa, df\n    real(kind=rp)              :: theta\n    real(kind=rp)              :: sza\n    integer                    :: n, m, l, s, c\n\n    ! Associated Legendre polynomials\n    if (lat .ne. lastlat) then\n      clat = sin(lat*deg2rad)  ! clat <=> sin, Legendre polyomial defined in colat\n      slat = cos(lat*deg2rad)  ! slat <=> cos, Legendre polyomial defined in colat\n      clat2 = clat*clat\n      clat4 = clat2*clat2\n      slat2 = slat*slat\n\n      plg(0,0) = 1.0_rp\n      plg(1,0) = clat\n      plg(2,0) = 0.5_rp * (3.0_rp * clat2 - 1.0_rp)\n      plg(3,0) = 0.5_rp * (5.0_rp * clat * clat2 - 3.0_rp * clat)\n      plg(4,0) = (35.0_rp * clat4 - 30.0_rp * clat2 + 3.0_rp)/8.0_rp\n      plg(5,0) = (63.0_rp * clat2 * clat2 * clat - 70.0_rp * clat2 * clat + 15.0_rp * clat)/8.0_rp\n      plg(6,0) = (11.0_rp * clat * plg(5, 0) - 5.0_rp * plg(4, 0))/6.0_rp\n\n      plg(1,1) = slat\n      plg(2,1) = 3.0_rp * clat * slat\n      plg(3,1) = 1.5_rp * (5.0_rp * clat2 - 1.0_rp) * slat\n      plg(4,1) = 2.5_rp * (7.0_rp * clat2 * clat - 3.0_rp * clat) * slat\n      plg(5,1) = 1.875_rp * (21.0_rp * clat4 - 14.0_rp * clat2 + 1.0_rp) * slat\n      plg(6,1) = (11.0_rp * clat * plg(5, 1) - 6.0_rp * plg(4, 1))/5.0_rp\n\n      plg(2,2) = 3.0_rp * slat2\n      plg(3,2) = 15.0_rp * slat2 * clat\n      plg(4,2) = 7.5_rp * (7.0_rp * clat2 - 1.0_rp) * slat2\n      plg(5,2) = 3.0_rp * clat * plg(4, 2) - 2.0_rp * plg(3, 2)\n      plg(6,2) = (11.0_rp * clat * plg(5, 2) - 7.0_rp * plg(4, 2))/4.0_rp\n\n      plg(3,3) = 15.0_rp * slat2 * slat\n      plg(4,3) = 105.0_rp * slat2 * slat * clat\n      plg(5,3) = (9.0_rp * clat * plg(4, 3) - 7.0_rp * plg(3, 3))/2.0_rp\n      plg(6,3) = (11.0_rp * clat * plg(5, 3) - 8.0_rp * plg(4, 3))/3.0_rp\n\n      lastlat = lat\n    endif\n\n    ! Fourier harmonics of day of year\n    if (doy .ne. lastdoy) then\n      cdoy(1) = cos(doy2rad*doy)\n      sdoy(1) = sin(doy2rad*doy)\n      cdoy(2) = cos(doy2rad*doy*2.0_rp)\n      sdoy(2) = sin(doy2rad*doy*2.0_rp)\n      lastdoy = doy\n    endif\n\n    ! Fourier harmonics of local time\n    lst = mod(utsec/3600.0_rp + lon/15.0_rp + 24.0_rp, 24.0_rp)\n    if (lst .ne. lastlst) then\n      clst(1) = cos(lst2rad*lst)\n      slst(1) = sin(lst2rad*lst)\n      clst(2) = cos(lst2rad*lst*2.0_rp)\n      slst(2) = sin(lst2rad*lst*2.0_rp)\n      clst(3) = cos(lst2rad*lst*3.0_rp)\n      slst(3) = sin(lst2rad*lst*3.0_rp)\n      lastlst = lst\n    endif\n\n    ! Fourier harmonics of longitude\n    if (lon .ne. lastlon) then\n      clon(1) = cos(deg2rad*lon)\n      slon(1) = sin(deg2rad*lon)\n      clon(2) = cos(deg2rad*lon*2.0_rp)\n      slon(2) = sin(deg2rad*lon*2.0_rp)\n      lastlon = lon\n    endif\n\n    !---------------------------------------------\n    ! Coupled Linear Terms\n    !---------------------------------------------\n\n    ! Reset basis functions\n    bf(:) = 0.0_rp\n\n    ! Time-independent (pure latitude dependence)\n    c = ctimeind\n    do n = 0, amaxn\n      bf(c) = plg(n,0)\n      c = c + 1\n    enddo\n\n    ! Intra-annual (annual and semiannual)\n    if (c .ne. cintann) stop 'problem with basis definitions'\n    do s = 1, amaxs\n      cosdoy = cdoy(s)\n      sindoy = sdoy(s)\n      do n = 0, amaxn\n        pl = plg(n,0)\n        bf(c) = pl*cosdoy\n        bf(c+1) = pl*sindoy\n        c = c + 2\n      enddo\n    enddo\n\n    ! Migrating Tides (local time dependence)\n    if (c .ne. ctide) stop 'problem with basis definitions'\n    do l = 1, tmaxl\n      coslst = clst(l)\n      sinlst = slst(l)\n      do n = l, tmaxn\n        pl = plg(n,l)\n        bf(c) = pl*coslst\n        bf(c+1) = pl*sinlst\n        c = c + 2\n      enddo\n      ! Intra-annual modulation of tides\n      do s = 1, tmaxs\n        cosdoy = cdoy(s)\n        sindoy = sdoy(s)\n        do n = l, tmaxn\n          pl = plg(n,l)\n          bf(c) = pl*coslst*cosdoy\n          bf(c+1) = pl*sinlst*cosdoy\n          bf(c+2) = pl*coslst*sindoy\n          bf(c+3) = pl*sinlst*sindoy\n          c = c + 4\n        enddo\n      enddo\n    enddo\n\n    ! Stationary Planetary Waves (longitude dependence)\n    if (c .ne. cspw) stop 'problem with basis definitions'\n    do m = 1, pmaxm\n      coslon = clon(m)\n      sinlon = slon(m)\n      do n = m, pmaxn\n        pl = plg(n,m)\n        bf(c) = pl*coslon\n        bf(c+1) = pl*sinlon\n        c = c + 2\n      enddo\n      ! Intra-annual modulation of SPWs\n      do s = 1, pmaxs\n        cosdoy = cdoy(s)\n        sindoy = sdoy(s)\n        do n = m, pmaxn\n          pl = plg(n,m)\n          bf(c) = pl*coslon*cosdoy\n          bf(c+1) = pl*sinlon*cosdoy\n          bf(c+2) = pl*coslon*sindoy\n          bf(c+3) = pl*sinlon*sindoy\n          c = c + 4\n        enddo\n      enddo\n    enddo\n    \n    ! Linear solar flux terms\n    if (c .ne. csfx) stop 'problem with basis definitions'\n    dfa = sfluxavg - sfluxavgref\n    df = sflux - sfluxavg\n    bf(c) = dfa\n    bf(c+1) = dfa*dfa\n    bf(c+2) = df\n    bf(c+3) = df*df\n    bf(c+4) = df*dfa\n    c = c + nsfx\n\n    ! Additional linear terms\n    if (c .ne. cextra) stop 'problem with basis definitions'\n    sza = solzen(doy,lst,lat,lon)\n    bf(c)    = -0.5_rp*tanh((sza-98.0_rp)/6.0_rp)  !Solar zenith angle logistic function for O, H (transition width 3 deg, transition sza for horizon at ~65 km altitude)\n    bf(c+1)  = -0.5_rp*tanh((sza-101.5_rp)/20.0_rp) !Solar zenith angle logistic function for NO (transition width 10 deg, transition sza for horizon at ~130 km altitude)\n    bf(c+2)  = dfa*bf(c)                        !Solar flux modulation of logistic sza term\n    bf(c+3)  = dfa*bf(c+1)                      !Solar flux modulation of logistic sza term\n    bf(c+4)  = dfa*plg(2,0)                     !Solar flux modulation of P(2,0) term\n    bf(c+5)  = dfa*plg(4,0)                     !Solar flux modulation of P(4,0) term\n    bf(c+6)  = dfa*plg(0,0)*cdoy(1)             !Solar flux modulation of global AO\n    bf(c+7)  = dfa*plg(0,0)*sdoy(1)             !Solar flux modulation of global AO\n    bf(c+8) = dfa*plg(0,0)*cdoy(2)              !Solar flux modulation of global SAO\n    bf(c+9) = dfa*plg(0,0)*sdoy(2)              !Solar flux modulation of global SAO\n    \n    !---------------------------------------------\n    ! Nonlinear Terms\n    !---------------------------------------------\n\n    c = cnonlin\n\n    ! Solar flux modulation terms\n    if (c .ne. csfxmod) stop 'problem with basis definitions'\n    bf(c) = dfa  \n    bf(c+1) = dfa*dfa\n    bf(c+2) = df \n    bf(c+3) = df*df\n    bf(c+4) = df*dfa\n    c = c + nsfxmod\n\n    ! Terms needed for legacy geomagnetic activity dependence\n    if (c .ne. cmag) stop 'problem with basis set'\n    bf(c:c+6) = ap - 4.0\n    bf(c+8) =   doy2rad*doy\n    bf(c+9) =   lst2rad*lst\n    bf(c+10) =  deg2rad*lon\n    bf(c+11) =  lst2rad*utsec/3600.0\n    bf(c+12) =  abs(lat)\n    c = c + 13\n    do m = 0,1\n      do n = 0,amaxn\n        bf(c) = plg(n,m)\n        c = c + 1\n      enddo\n    enddo\n\n    ! Terms needed for legacy UT dependence\n    c = cut\n    bf(c) =   lst2rad*utsec/3600.0\n    bf(c+1) = doy2rad*doy\n    bf(c+2) = dfa\n    bf(c+3) = deg2rad*lon\n    bf(c+4) = plg(1,0)\n    bf(c+5) = plg(3,0)\n    bf(c+6) = plg(5,0)\n    bf(c+7) = plg(3,2)\n    bf(c+8) = plg(5,2)\n\n    !---------------------------------------------\n    ! Apply Switches\n    !---------------------------------------------\n    where(.not. swg(0:mbf)) bf(0:mbf) = 0.0_rp\n    \n    return\n\n  end subroutine globe\n\n  !==================================================================================================\n  ! SOLZEN: Calculate solar zenith angle (adapted from IRI subroutine)\n  !==================================================================================================\n  real(kind=rp) function solzen(ddd,lst,lat,lon)\n\n    use msis_constants, only    : pi, deg2rad\n\n    implicit none\n\n    real(kind=rp), intent(in)  :: ddd\n    real(kind=rp), intent(in)  :: lst\n    real(kind=rp), intent(in)  :: lat\n    real(kind=rp), intent(in)  :: lon\n\n    real(kind=rp)              :: wlon,dec\n    real(kind=rp)              :: teqnx,tf,teqt\n    real(kind=rp)              :: rlat,phi,cosx\n    real(kind=rp), parameter   :: humr = pi/12.0_rp\n    real(kind=rp), parameter   :: dumr = pi/182.5_rp\n    real(kind=rp), parameter   :: p(5) = (/0.017203534,0.034407068,0.051610602,0.068814136,0.103221204/)\n\n    wlon = 360.0 - lon\n    teqnx = ddd + (lst + wlon / 15.0_rp) / 24.0_rp + 0.9369_rp\n    teqnx = ddd + 0.9369_rp\n\n    ! Solar declination\n    dec = 23.256_rp * sin(p(1) * (teqnx - 82.242_rp)) + 0.381_rp * sin(p(2)*(teqnx - 44.855_rp))  &\n         + 0.167_rp * sin(p(3) * (teqnx - 23.355_rp)) - 0.013_rp * sin(p(4)*(teqnx + 11.97_rp)) &\n         + 0.011_rp * sin(p(5) * (teqnx - 10.410_rp)) + 0.339137_rp\n    dec = dec * deg2rad\n\n    ! Equation of time\n    tf = teqnx - 0.5_rp\n    teqt = -7.38_rp * sin(p(1) * (tf -  4.0_rp)) - 9.87_rp * sin(p(2) * (tf +  9.0_rp)) &\n          + 0.27_rp * sin(p(3) * (tf - 53.0_rp)) -  0.2_rp * cos(p(4) * (tf - 17.0_rp))\n\n    phi = humr * (lst - 12.0_rp) + teqt * deg2rad / 4.0_rp\n    rlat = lat * deg2rad\n\n    ! Cosine of solar zenith angle\n    cosx = sin(rlat) * sin(dec) + cos(rlat) * cos(dec) * cos(phi)\n    if (abs(cosx) .gt. 1.0_rp) cosx = sign(1.0_rp,cosx)\n\n    solzen = acos(cosx) / deg2rad\n\n    return\n\n  end function solzen\n\n  !==================================================================================================\n  ! SFLUXMOD: Legacy nonlinear modulation of intra-annual, tide, and SPW terms\n  !==================================================================================================\n  real(kind=rp) function sfluxmod(iz,gf,parmset,dffact)\n\n    use msis_constants, only       : maxnbf, mbf, csfx, csfxmod\n    use msis_init, only            : basissubset, zsfx, tsfx, psfx\n\n    implicit none\n\n    integer, intent(in)           :: iz\n    real(kind=rp), intent(in)     :: gf(0:maxnbf-1)\n    type(basissubset), intent(in) :: parmset\n    real(kind=rp), intent(in)     :: dffact  !Turns on or adjusts the delta-F terms added to F1 and F2 (eqns. A22b and A22c in Hedin (1987)).\n\n    real(kind=rp)                 :: f1, f2, f3, sum\n    integer                       :: j\n\n    ! Intra-annual modulation factor\n    if (swg(csfxmod)) then\n      f1 = parmset%beta(csfxmod,iz) * gf(csfxmod) &\n           + (parmset%beta(csfx+2,iz) * gf(csfxmod+2) + parmset%beta(csfx+3,iz) * gf(csfxmod+3) ) * dffact\n    else\n      f1 = 0.0_rp\n    endif\n\n    ! Migrating tide (local time) modulation factor\n    if (swg(csfxmod+1)) then\n      f2 = parmset%beta(csfxmod+1,iz) * gf(csfxmod) &\n           + (parmset%beta(csfx+2,iz) * gf(csfxmod+2) + parmset%beta(csfx+3,iz) * gf(csfxmod+3) ) * dffact\n    else\n      f2 = 0.0_rp\n    endif\n\n    ! SPW (longitude) modulation factor\n    if (swg(csfxmod+2)) then\n      f3 = parmset%beta(csfxmod+2,iz) * gf(csfxmod)\n    else\n      f3 = 0.0_rp\n    endif\n\n    sum = 0.0\n    do j = 0, mbf\n      ! Apply intra-annual modulation\n      if (zsfx(j)) then\n        sum = sum + parmset%beta(j,iz)*gf(j)*f1\n        cycle\n      endif\n      ! Apply migrating tide modulation\n      if (tsfx(j)) then\n        sum = sum + parmset%beta(j,iz)*gf(j)*f2\n        cycle\n      endif\n      ! Apply SPW modulation\n      if (psfx(j)) then\n        sum = sum + parmset%beta(j,iz)*gf(j)*f3\n        cycle\n      endif\n    enddo\n\n    sfluxmod = sum\n\n    return\n\n  end function sfluxmod\n\n  !==================================================================================================\n  ! GEOMAG: Legacy nonlinear ap dependence (daily ap mode and ap history mode), including mixed \n  !         ap/UT/Longitude terms.\n  ! Master switch control is as follows:\n  !   swg(cmag) .nor. swg(cmag+1)   Do nothing: Return zero\n  !   swg(cmag) .and. swg(cmag+1)   Daily Ap mode\n  !   swg(cmag) .neqv. swg(cmag+1)  3-hour ap history mode\n  !==================================================================================================\n  real(kind=rp) function geomag(p0,bf,plg)\n\n    use msis_constants, only    : nmag, cmag\n\n    implicit none\n\n    real(kind=rp), intent(in)  :: p0(0:nmag-1)\n    real(kind=rp), intent(in)  :: bf(0:12)\n    real(kind=rp), intent(in)  :: plg(0:6,0:1)\n\n    logical                    :: swg1(0:nmag-1) !Copy of switches\n    real(kind=rp)              :: p(0:nmag-1)    !Copy of parameters used to apply switches\n    real(kind=rp)              :: delA, gbeta, ex, sumex, G(1:6)\n    integer(4)                 :: i\n\n    ! Return zero if both master switches are off    \n    if (.not. (swg(cmag) .or. swg(cmag+1))) then\n      geomag = 0.0_rp\n      return\n    endif\n\n    ! Copy parameters\n    p = p0\n    swg1 = swg(cmag:cmag+nmag-1)\n\n    ! Calculate function\n    if (swg1(0) .eqv. swg1(1)) then\n      ! Daily Ap mode\n      if (p(1) .eq. 0) then  !If k00s is zero, then cannot compute function\n        geomag = 0.0_rp\n        return\n      endif\n      where(.not. swg1(2:25)) p(2:25) = 0.0_rp !Apply switches\n      p(8) = p0(8) !Need doy phase term\n      delA = G0fn(bf(0),p(0),p(1))\n      geomag = ( p(2)*plg(0,0) +  p(3)*plg(2,0) +  p(4)*plg(4,0)                     &  ! time independent\n        + (p(5)*plg(1,0) + p(6)*plg(3,0) + p(7)*plg(5,0)) * cos(bf(8) - p(8))        &  ! doy modulation\n        + (p(9)*plg(1,1) + p(10)*plg(3,1) + p(11)*plg(5,1)) * cos(bf(9) - p(12))     &  ! local time modulation\n        + (1.0_rp + p(13)*plg(1,0)) *                                                &\n          (p(14)*plg(2,1) + p(15)*plg(4,1) + p(16)*plg(6,1)) * cos(bf(10) - p(17))   &  ! longitude effect\n        + (p(18)*plg(1,1) + p(19)*plg(3,1) + p(20)*plg(5,1)) * cos(bf(10) - p(21)) * &\n          cos(bf(8) - p(8))                                                          &  ! longitude with doy modulaiton\n        + (p(22)*plg(1,0) + p(23)*plg(3,0) + p(24)*plg(5,0)) * cos(bf(11) - p(25)) ) &  ! universal time\n        *delA\n    else\n      ! 3-hour ap history mode\n      if (p(28) .eq. 0) then  !If beta00 is zero, then cannot compute function\n        geomag = 0.0\n        return\n      endif\n      where(.not. swg1(30:)) p(30:) = 0.0  !Apply switches\n      p(36) = p0(36) !Need doy phase term\n      gbeta = p(28)/(1 + p(29)*(45.0_rp - bf(12)))\n      ex = exp(-10800.0_rp*gbeta)\n      sumex = 1 + (1 - ex**19.0_rp) * ex**(0.5_rp) / (1 - ex)\n      do i = 1, 6\n        G(i) = G0fn(bf(i),p(26),p(27))\n      enddo\n      delA = ( G(1)                                                                 &\n                    + ( G(2)*ex + G(3)*ex*ex + G(4)*ex**3.0_rp                      &\n                       +(G(5)*ex**4.0_rp + G(6)*ex**12.0_rp)*(1-ex**8.0_rp)/(1-ex) ) ) / sumex\n      geomag = ( p(30)*plg(0,0) +  p(31)*plg(2,0) +  p(32)*plg(4,0)                  &  ! time independent\n        + (p(33)*plg(1,0) + p(34)*plg(3,0) + p(35)*plg(5,0)) * cos(bf(8) - p(36))    &  ! doy modulation\n        + (p(37)*plg(1,1) + p(38)*plg(3,1) + p(39)*plg(5,1)) * cos(bf(9) - p(40))    &  ! local time modulation\n        + (1.0_rp + p(41)*plg(1,0)) *                                                &\n          (p(42)*plg(2,1) + p(43)*plg(4,1) + p(44)*plg(6,1)) * cos(bf(10) - p(45))   &  ! longitude effect\n        + (p(46)*plg(1,1) + p(47)*plg(3,1) + p(48)*plg(5,1)) * cos(bf(10) - p(49)) * &\n          cos(bf(8) - p(36))                                                         &  ! longitude with doy modulaiton\n        + (p(50)*plg(1,0) + p(51)*plg(3,0) + p(52)*plg(5,0)) * cos(bf(11) - p(53)) ) &  ! universal time\n        *delA\n    endif\n\n    return\n\n    contains\n\n      real(kind=rp) function G0fn(a,k00r,k00s)\n          real(kind=rp),intent(in)  :: a, k00r, k00s\n          G0fn = a + (k00r - 1.0_rp) * (a + (exp(-a*k00s) - 1.0_rp)/k00s)\n          return\n      end function G0fn\n\n  end function geomag\n\n  !==================================================================================================\n  ! UTDEP: Legacy nonlinear UT dependence\n  !==================================================================================================\n  real(kind=rp) function utdep(p0,bf)\n\n    use msis_constants, only    : nut, cut\n\n    implicit none\n\n    real(kind=rp), intent(in)  :: p0(0:nut-1)\n    real(kind=rp), intent(in)  :: bf(0:8)\n\n    real(kind=rp)              :: p(0:nut-1)    !Copy of parameters used to apply switches\n    logical                    :: swg1(0:nut-1) !Copy of switches\n\n    !Copy parameters\n    p = p0\n    swg1 = swg(cut:cut+nut-1)\n    where(.not. swg1(3:nut-1)) p(3:nut-1) = 0.0  !Apply switches\n\n    ! Calculate function\n    utdep = cos(bf(0)-p(0)) *                          &\n            (1 + p(3)*bf(4)*cos(bf(1)-p(1)))  *        &\n            (1 + p(4)*bf(2)) * (1 + p(5)*bf(4)) *      &\n            (p(6)*bf(4) + p(7)*bf(5) + p(8)*bf(6)) +   &\n            cos(bf(0)-p(2)+2*bf(3)) * (p(9)*bf(7) + p(10)*bf(8)) * (1 + p(11)*bf(2))\n\n    return\n\n  end function utdep\n\nend module msis_gfn\n"
  },
  {
    "path": "source/external/nrlmsis2/msis_init.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n!!!\n!!! MSISINIT: Initialization of MSIS parameters, switches, and options.\n!\n!     PREREQUISITES:\n!       MSIS binary parameter file (msis2.0.parm)\n!\n!     CALLING SEQUENCE:\n!       CALL MSISINIT([OPTIONAL ARGUMENTS])\n!  \n!     OPTIONAL ARGUMENTS:\n!       parmpath        File path pointing to the MSIS parameter file.\n!                         Default: Null string (current directory)\n!       parmfile        Name of MSIS parameter file.\n!                         Default: 'msis2.0.parm'\n!       iun             File unit number for reading parameter file.\n!                         Default: 67\n!       switch_gfn      Logical array of 512 swtiches for individual terms. For\n!                         advanced users.\n!                         Default values: True (all switches on)\n!       switch_legacy   Floating point array (1:25) of legacy switches that\n!                         control groups of terms:\n!                            1 - F10.7\n!                            2 - Time independent\n!                            3 - Symmetrical annual\n!                            4 - Symmetrical semiannual\n!                            5 - Asymmetrical annual\n!                            6 - Asymmetrical semiannual\n!                            7 - Diurnal\n!                            8 - Semidiurnal\n!                            9 - Geomagnetic activity:\n!                                  1.0 = Daily Ap mode\n!                                 -1.0 = Storm-time ap mode\n!                           10 - All UT/long effects\n!                           11 - Longitudinal\n!                           12 - UT and mixed UT/long\n!                           13 - Mixed Ap/UT/long\n!                           14 - Terdiurnal\n!                           15-25 - Not used in NRLMSIS 2.0\n!                         For all switches:\n!                           0.0 = Off\n!                           1.0 = On\n!                           2.0 = Main effects off, cross terms on\n!                         Default values: 1.0\n!       lzalt_type      Logical flag for altitude input type:\n!                         True = Geodetic altitude (km)\n!                         False = Geopotential height (km)\n!                         Default: True (Geodetic altitude)\n!       lspec_select    Logical array (1:10) flagging which densities to \n!                         calculate.\n!                         True = Calculate, False = Do not calculate\n!                            1 - Mass density\n!                            2 - N2\n!                            3 - O2\n!                            4 - O\n!                            5 - He\n!                            6 - H\n!                            7 - Ar\n!                            8 - N\n!                            9 - Anomalous O\n!                           10 - Not used in NRLMSIS 2.0\n!                         Default values: True\n!       lmass_include   Logical array (1:10) flagging which species to include\n!                         in mass density calculation. Same ordering as \n!                         lspec_select.\n!                         Default values: True\n!       lN2_msis00      Logical flag for retrieving NRLMSISE-00 upper\n!                         thermospheric N2 variation. See paper for details.\n!                           False: Thermospheric N2 determined entirely by\n!                             temperature profile and the constant mixing ratio\n!                             of N2 in the lower atmosphere. \n!                           True: Upper thermospheric N2 relaxes to NRLMSISE-00\n!                             Values.\n!                         Default: False\n!\n!     NOTES:\n!       - The switch_legacy optional argument performs the same function as\n!         TSELEC(SW) in NRLSMSISE-00, except that switches 15-25 are not used in\n!         NRLMSIS 2.0. The change in the switch-setting call is illustrated as\n!         follows, where SW is the 25-element array of switches:\n!           NRLMSISE-00: CALL TSELEC(SW)\n!           NRLMSIS 2.0: call msisinit(switch_legacy=SW)\n!\n!!! ===========================================================================\n\n!**************************************************************************************************\n! MSIS_INIT Module: Contains initialization subroutines, model options, and model parameters\n!**************************************************************************************************\nmodule msis_init\n\n  use msis_constants, only    : rp, nspec, nl, maxnbf, mbf\n\n  implicit none\n  \n  !Model flags\n  logical       :: initflag = .false.           !Flags whether model has been initialized\n  logical       :: haveparmspace = .false.      !Flags whether parameter space has been initialized and allocated\n  logical       :: zaltflag = .true.            !true: height input is geometric, false: height input is geopotential\n  logical       :: specflag(1:nspec-1) = .true. !Array flagging which species densities are required\n  logical       :: massflag(1:nspec-1) = .true. !Array flagging which species should be included in mass density\n  logical       :: N2Rflag = .false.            !Flag for retrieving NRLMSISE-00 thermospheric N2 variations\n  logical       :: zsfx(0:mbf) = .false.        !Flags zonal mean terms to be modulated by F1 (MSISE-00 legacy multiplier)\n  logical       :: tsfx(0:mbf) = .false.        !Flags tide terms to be modulated by F2 (MSISE-00 legacy multiplier)\n  logical       :: psfx(0:mbf) = .false.        !Flags SPW terms to be modulated by F3 (MSISE-00 legacy multiplier)\n  logical       :: smod(0:nl) = .false.         !Flags which temperature levels get solar flux modulation; loadparmset turns flags on based on parameter values\n  logical       :: swg(0:maxnbf-1) = .true.     !Switch array for globe subroutine.\n  real(kind=rp) :: masswgt(1:nspec-1)  = 0.0_rp !Weights for calculating mass density\n  real(4)       :: swleg(1:25)=1.0, swc(1:25), sav(1:25) !Legacy switch arrays\n\n  ! Model parameter arrays\n  type basissubset\n    sequence\n    character(8)               :: name\n    integer                    :: bl,nl\n    real(kind=rp), allocatable :: beta(:,:)\n    !logical, allocatable       :: active(:,:)\n    !integer, allocatable       :: fitb(:,:)\n  end type basissubset\n  type (basissubset)     :: TN\n  type (basissubset)     :: PR\n  type (basissubset)     :: N2\n  type (basissubset)     :: O2\n  type (basissubset)     :: O1\n  type (basissubset)     :: HE\n  type (basissubset)     :: H1\n  type (basissubset)     :: AR\n  type (basissubset)     :: N1\n  type (basissubset)     :: OA   !Anomalous O\n  type (basissubset)     :: NO\n  integer                :: nvertparm\n  \n  ! Reciprocal node difference arrays (constant values needed for B-spline calculations)\n  real(kind=rp)          :: etaTN(0:30,2:6) = 0.0_rp\n  real(kind=rp)          :: etaO1(0:30,2:6) = 0.0_rp\n  real(kind=rp)          :: etaNO(0:30,2:6) = 0.0_rp\n\n  ! C1 constraint terms for O and NO related to the tapered logistic correction\n  real(kind=rp)          :: HRfactO1ref, dHRfactO1ref, HRfactNOref, dHRfactNOref\n\ncontains\n\n  !==================================================================================================\n  ! MSISINIT: Entry point for initializing model and loading parameters\n  !==================================================================================================\n  subroutine msisinit(parmpath,parmfile,iun,switch_gfn,switch_legacy, &\n                      lzalt_type,lspec_select,lmass_include,lN2_msis00)\n\n    use msis_constants, only : specmass, nspec, maxnbf \n\n    implicit none\n\n    character(len=*), intent(in), optional    :: parmpath                 !Path to parameter file\n    character(len=*), intent(in), optional    :: parmfile                 !Parameter file name\n    integer, intent(in), optional             :: iun                      !File unit number for reading parameter file\n    logical, intent(in), optional             :: switch_gfn(0:maxnbf-1)   !Switch array for globe subroutine.\n    real(4), intent(in), optional             :: switch_legacy(1:25)      !Legacy switch array\n    logical, intent(in), optional             :: lzalt_type               !true: height input is geometric, false: height input is geopotential\n    logical, intent(in), optional             :: lspec_select(1:nspec-1)  !Array flagging which species densities are required\n    logical, intent(in), optional             :: lmass_include(1:nspec-1) !Array flagging which species should be included in mass density\n    logical, intent(in), optional             :: lN2_msis00               !Flag for retrieving NRLMSISE-00 thermospheric N2 variations\n\n    character(len=128)                        :: parmpath1\n    character(len=128)                        :: parmfile1\n    integer                                   :: iun1\n\n    ! Path to parameter file\n    if (present(parmpath)) then\n      parmpath1 = parmpath\n    else\n      parmpath1 = ''\n    endif\n\n    ! Parameter file name\n    if (present(parmfile)) then\n      parmfile1 = parmfile\n    else\n      parmfile1 = 'msis2.0.parm'\n    endif\n\n    ! Initialize model parameter space\n    if (.not. haveparmspace) call initparmspace()\n\n    ! Load parameter set\n    if (present(iun)) then\n      iun1 = iun\n    else\n      iun1 = 67\n    endif\n    call loadparmset(trim(parmpath1)//trim(parmfile1),iun1)\n\n    ! Set switches\n    swg(:) = .true.\n    swleg(:) = 1.0\n    if (present(switch_gfn)) then\n      swg = switch_gfn\n    else\n      if (present(switch_legacy)) then\n        swleg = switch_legacy\n        call tselec(swleg)\n      endif\n    endif\n\n    ! Input altitude type flag\n    if (present(lzalt_type)) then\n      zaltflag = lzalt_type\n    else\n      zaltflag = .true.\n    endif\n\n    ! Species flags for number density and mass density\n    if (present(lspec_select)) then\n      specflag = lspec_select\n    else\n      specflag(:) = .true.\n    endif\n    if (specflag(1)) then\n      if (present(lmass_include)) then\n        massflag = lmass_include\n      else\n        massflag(:) = .true.\n      endif\n    else\n      massflag(:) = .false.\n    endif\n    where(massflag) specflag = .true.\n    masswgt(:) = 0.0_rp\n    where(massflag) masswgt = 1.0_rp\n    masswgt(1) = 0.0_rp\n    masswgt = masswgt * specmass\n    masswgt(10) = 0.0_rp\n\n    ! Flag for retrieving NRLMSISE-00 thermospheric N2 variations\n    if (present(lN2_msis00)) then\n      N2Rflag = lN2_msis00\n    else\n      N2Rflag = .false.\n    endif\n\n    ! Set model initialization flag\n    initflag = .true.\n\n    return\n\n  end subroutine msisinit\n\n  !==================================================================================================\n  ! INITPARMSPACE: Initialize and allocate the model parameter space\n  !==================================================================================================\n  subroutine initparmspace()\n\n    use msis_constants, only : nl, nls, nodesTN, ndO1, nsplO1, nodesO1, nsplNO, ndNO, nodesNO, &\n                               zetagamma, Hgamma, zetarefO1, zetarefNO, maxnbf, ctide, cspw\n\n    implicit none\n\n    integer             :: n, m, j, k\n    real(kind=rp)       :: gammaterm0\n\n    ! Vertical parameter counter (number of vertical parameters in the parmeter file)\n    nvertparm = 0\n\n    ! Model formulation parameter subsets\n    call initsubset(TN,0,nl,        maxnbf,'TN')\n    call initsubset(PR,0,nl,        maxnbf,'PR')\n    call initsubset(N2,0,nls,       maxnbf,'N2')\n    call initsubset(O2,0,nls,       maxnbf,'O2')\n    call initsubset(O1,0,nls+nsplO1,maxnbf,'O1')\n    call initsubset(HE,0,nls,       maxnbf,'HE')\n    call initsubset(H1,0,nls,       maxnbf,'H1')\n    call initsubset(AR,0,nls,       maxnbf,'AR')\n    call initsubset(N1,0,nls,       maxnbf,'N1')\n    call initsubset(OA,0,nls,       maxnbf,'OA')\n    call initsubset(NO,0,nls+nsplNO,maxnbf,'NO')\n\n    ! Add the surface pressure parameter to the vertical parameter counter\n    nvertparm = nvertparm + 1\n\n    ! Set solar flux modulation flags\n    zsfx(:) = .false.\n    tsfx(:) = .false.\n    psfx(:) = .false.\n    ! F1, solar flux modulation of the zonal mean asymmetric annual terms\n    zsfx(9:10) = .true.    !Pl(1,0) annual terms\n    zsfx(13:14) = .true.   !Pl(3,0) annual terms\n    zsfx(17:18) = .true.   !Pl(5,0) annual terms\n    ! F2, solar sflux modulation of the tides\n    tsfx(ctide:cspw-1) = .true.\n    ! F3, solar sflux modulation of stationary planetary wave 1\n    psfx(cspw:cspw+59) = .true. \n\n    ! Calculate reciprocal node difference arrays\n    do k = 2, 6\n      do j = 0, nl\n        etaTN(j,k) = 1.0_rp / (nodesTN(j+k-1) - nodesTN(j))\n      enddo\n    enddo\n    do k = 2, 4\n      do j = 0, ndO1-k+1\n        etaO1(j,k) = 1.0_rp / (nodesO1(j+k-1) - nodesO1(j))\n      enddo\n      do j = 0, ndNO-k+1\n        etaNO(j,k) = 1.0_rp / (nodesNO(j+k-1) - nodesNO(j))\n      enddo\n    enddo\n\n    ! Calculate C1 constraint terms for O and NO related to the tapered logistic correction\n    gammaterm0 = tanh((zetarefO1 - zetagamma)*Hgamma)\n    HRfactO1ref = 0.5_rp * (1.0_rp + gammaterm0)\n    dHRfactO1ref = (1.0_rp - (zetarefO1 - zetagamma)*(1.0_rp - gammaterm0)*Hgamma) / HRfactO1ref\n    gammaterm0 = tanh((zetarefNO - zetagamma)*Hgamma)\n    HRfactNOref = 0.5_rp * (1.0_rp + gammaterm0)\n    dHRfactNOref = (1.0_rp - (zetarefNO - zetagamma)*(1.0_rp - gammaterm0)*Hgamma) / HRfactNOref\n\n    ! Set parameter space initialization flag\n    haveparmspace = .true.\n\n    return\n\n  contains\n\n      !--------------------------------------------------------------------------------------------------\n      ! INITSUBSET: Initialize and allocate a parameter subset\n      !--------------------------------------------------------------------------------------------------\n      subroutine initsubset(subset,bl,nl,maxnbf,name)\n\n        implicit none\n\n        type (basissubset), intent(inout) :: subset\n        integer, intent(in)               :: bl\n        integer, intent(in)               :: nl\n        integer, intent(in)               :: maxnbf\n        character(2), intent(in)          :: name\n\n        integer                           :: iz\n\n        ! Allocate and initialize subset structure\n        subset%name = name\n        subset%bl = bl\n        subset%nl = nl\n        allocate(subset%beta(0:maxnbf-1,bl:nl))\n        !allocate(subset%beta(0:maxnbf-1,bl:nl), &\n        !         subset%active(0:maxnbf-1,bl:nl), &\n        !         subset%fitb(0:maxnbf-1,bl:nl))\n        subset%beta = 0.0_rp\n        !subset%active = .false.\n        !subset%fitb = 0\n        \n        ! Increment vertical parameter counter except for pressure\n        if (name .ne. 'PR') nvertparm = nvertparm + nl - bl + 1\n\n        return\n\n      end subroutine initsubset\n\n  end subroutine initparmspace\n\n  !==================================================================================================\n  ! LOADPARMSET: Read in a parameter file\n  !==================================================================================================\n  subroutine loadparmset(name,iun)\n\n    use msis_constants, only      : maxnbf, csfxmod\n\n    implicit none\n\n    character(len=*), intent(in) :: name\n    integer, intent(in)          :: iun\n\n    integer                      :: i0, i1\n    logical                      :: havefile\n    real(8), allocatable         :: parmin(:,:)\n\n    ! Check if file exists\n    inquire(file=trim(name),exist=havefile)\n    if (havefile) then\n       open(unit=iun,file=trim(name),status='old',access='stream',convert='little_endian')\n    else\n       print *,\"MSIS parameter set \",trim(name),\" not found. Stopping.\"\n       stop\n    endif\n\n    ! Read in parameter values into temporary double-precision array\n    allocate(parmin(0:maxnbf-1,0:nvertparm-1))\n    read(iun) parmin\n    close(iun)\n\n    ! Transfer parameters to structures\n    i0 = 0\n    i1 = TN%nl - TN%bl\n    TN%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0\n    PR%beta(:,0) = parmin(:,i0)\n    i0 = i1 + 1\n    i1 = i0 + N2%nl - N2%bl\n    N2%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + O2%nl - O2%bl\n    O2%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + O1%nl - O1%bl\n    O1%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + HE%nl - HE%bl\n    HE%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + H1%nl - H1%bl\n    H1%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + AR%nl - AR%bl\n    AR%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + N1%nl - N1%bl\n    N1%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + OA%nl - OA%bl\n    OA%beta = parmin(:,i0:i1)\n    i0 = i1 + 1\n    i1 = i0 + NO%nl - NO%bl\n    NO%beta = parmin(:,i0:i1)\n\n    !Set solar flux modulation flags; if on for a given vertical parameter, then sfluxmod is called by tfnparm\n    smod(:) = .false.\n    where((Tn%beta(csfxmod+0,:) .ne. 0) .or. &\n          (Tn%beta(csfxmod+1,:) .ne. 0) .or. &\n          (Tn%beta(csfxmod+2,:) .ne. 0)) smod = .true.\n\n    ! Compute log pressure spline coefficients from temperature spline coeffcients\n    call pressparm()\n\n    return\n\n  end subroutine loadparmset\n\n  !==================================================================================================\n  ! PRESSPARM: Compute log pressure spline coefficients from temperature spline coeffcients\n  !==================================================================================================\n  subroutine pressparm()\n\n    use msis_constants, only    : Mbarg0divkB, izfmx, mbf, gwht\n\n    implicit none\n\n    integer                    :: j, b, iz\n    real(kind=rp)              :: lnz\n\n    !Integrate pressure on nodes up to the last fully mixed level\n    do j = 0, mbf\n        lnz = 0.0\n        do b = 0, 3\n            lnz = lnz + TN%beta(j,b)*gwht(b)*Mbarg0divkB\n        enddo\n        PR%beta(j,1) = -lnz\n        do iz = 1, izfmx\n            lnz = 0.0\n            do b = 0, 3\n                lnz = lnz + TN%beta(j,iz+b)*gwht(b)*Mbarg0divkB\n            enddo\n            PR%beta(j,iz+1) = PR%beta(j,iz) - lnz\n        enddo\n    enddo\n\n    return\n\n  end subroutine pressparm\n\n  !==================================================================================================\n  ! TSELEC: Legacy switches and mapping to new switches\n  !==================================================================================================\n  subroutine tselec(sv)\n  \n    use msis_constants, only  : nsfx, nsfxmod, nut, cspw, csfx, csfxmod, cmag, cut\n\n    implicit none\n\n    real(4), intent(in)  :: sv(1:25)\n\n    integer              :: i\n    \n    !Set cross-terms flags\n    do i = 1, 25\n      sav(i) = sv(i)\n      swleg(i) = amod(sv(i), 2.0)\n      if(abs(sv(i)) .eq. 1.0 .or. abs(sv(i)) .eq. 2.0) then\n        swc(i) = 1.0\n      else\n        swc(i) = 0.0\n      endif\n    enddo\n    \n    !Main effects\n    swg(0)                           = .true.                !Global term must be on\n    swg(csfx:csfx+nsfx-1)            = (swleg(1) .eq. 1.0)   !Solar flux\n    swg(1:6)                         = (swleg(2) .eq. 1.0)   !Time independent\n    swg(304:305)                     = (swleg(2) .eq. 1.0)   !Time independent (extra, solar-flux modulated terms)\n    swg((/7,8,11,12,15,16,19,20/))   = (swleg(3) .eq. 1.0)   !Symmetric annual\n    swg(306:307)                     = (swleg(3) .eq. 1.0)   !Global AO (extra, solar-flux modulated terms)\n    swg((/21,22,25,26,29,30,33,34/)) = (swleg(4) .eq. 1.0)   !Symmetric semiannual\n    swg(308:309)                     = (swleg(4) .eq. 1.0)   !Global SAO (extra, solar-flux modulated terms)\n    swg((/9,10,13,14,17,18/))        = (swleg(5) .eq. 1.0)   !Asymmetric annual\n    swg((/23,24,27,28,31,32/))       = (swleg(6) .eq. 1.0)   !Asymmetric semiannual\n    swg(35:94)                       = (swleg(7) .eq. 1.0)   !Diurnal\n    swg(300:303)                     = (swleg(7) .eq. 1.0)   !Solar zenith angle\n    swg(95:144)                      = (swleg(8) .eq. 1.0)   !Semidiurnal\n    swg(145:184)                     = (swleg(14) .eq. 1.0)  !Terdiurnal\n    swg(cmag:cmag+1)                 = .false.               !Geomagnetic activity mode master switch\n    if((swleg(9) .gt. 0) .or. (swleg(13) .eq. 1)) swg(cmag:cmag+1) = (/.true.,.true./)  !Daily mode master switch\n    if(swleg(9) .lt. 0)                           swg(cmag:cmag+1) = (/.false.,.true./) !Storm-time mode master switch\n    swg(cmag+2:cmag+12)              = (swleg(9) .eq. 1.0)   !Daily geomagnetic activity terms\n    swg(cmag+28:cmag+40)             = (swleg(9) .eq. -1.0)  !Storm-time geomagnetic activity terms\n    swg(cspw:csfx-1)                 = ((swleg(11) .eq. 1.0) .and. (swleg(10) .eq. 1.0))  !Longitudinal\n    swg(cut:cut+nut-1)               = ((swleg(12) .eq. 1.0) .and. (swleg(10) .eq. 1.0))  !UT/Lon\n    swg(cmag+13:cmag+25)             = ((swleg(13) .eq. 1.0) .and. (swleg(10) .eq. 1.0))  !Mixed UT/Lon/Geomag (Daily mode terms)\n    swg(cmag+41:cmag+53)             = ((swleg(13) .eq. 1.0) .and. (swleg(10) .eq. 1.0))  !Mixed UT/Lon/Geomag (Storm-time mode terms)\n\n    !Cross terms\n    swg(csfxmod:csfxmod+nsfxmod-1)   = (swc(1) .eq. 1.0)    !Solar activity modulation\n    if (swc(1) .eq. 0) then                                 !Solar activity modulation\n      swg(302:303) = .false.                                   !Solar zenith angle\n      swg(304:305) = .false.                                   !Time independent\n      swg(306:307) = .false.                                   !Global AO\n      swg(308:309) = .false.                                   !Global SAO\n      swg(447) = .false.                                       !UT/Lon\n      swg(454) = .false.                                       !UT/Lon\n    endif\n    if (swc(2) .eq. 0) then                                 !Time independent (latitude terms) (in MSISE-00, SWC(2) is not used - latitude modulations are always on)\n      swg(9:20) = .false.                                      !AO\n      swg(23:34) = .false.                                     !SAO\n      swg(35:184) = .false.                                    !All tides\n      swg(185:294) = .false.                                   !All SPW\n      swg(392:414) = .false.                                   !Daily geomagnetic activity\n      swg(420:442) = .false.                                   !Storm-time geomagnetic activity\n      swg(449:453) = .false.                                   !UT/Lon\n    endif\n    if (swc(3) .eq. 0) then                                 !Symmetric annual\n      swg(201:204) = .false.                                   !SPW1 (2,1)\n      swg(209:212) = .false.                                   !SPW1 (4,1)\n      swg(217:220) = .false.                                   !SPW1 (6,1)\n      swg(255:258) = .false.                                   !SPW2 (2,2)\n      swg(263:266) = .false.                                   !SPW2 (4,2)\n      swg(271:274) = .false.                                   !SPW2 (6,2)\n      swg(306:307) = .false.                                   !Global AO solar flux modulation\n    endif\n    if (swc(4) .eq. 0) then                                 !Symmetric semiannual\n      swg(225:228) = .false.                                   !SPW1 (2,1)\n      swg(233:236) = .false.                                   !SPW1 (4,1)\n      swg(241:244) = .false.                                   !SPW1 (6,1)\n      swg(275:278) = .false.                                   !SPW2 (2,2)\n      swg(283:286) = .false.                                   !SPW2 (4,2)\n      swg(291:294) = .false.                                   !SPW2 (6,2)\n      swg(308:309) = .false.                                   !Global SAO solar flux modulation\n    endif\n    if (swc(5) .eq. 0) then                                 !Asymmetric annual\n      swg(47:50) = .false.                                     !Diurnal (1,1)\n      swg(51:54) = .false.                                     !Diurnal (2,1) !In MSISE-00, swc(5) is applied to all annual modulated tides\n      swg(55:58) = .false.                                     !Diurnal (3,1)\n      swg(59:62) = .false.                                     !Diurnal (4,1)\n      swg(63:66) = .false.                                     !Diurnal (5,1)\n      swg(67:70) = .false.                                     !Diurnal (6,1)\n      swg(105:108) = .false.                                   !Semidiurnal (2,2)\n      swg(109:112) = .false.                                   !Semidiurnal (3,2)\n      swg(113:116) = .false.                                   !Semidiurnal (4,2)\n      swg(117:120) = .false.                                   !Semidiurnal (5,2)\n      swg(121:124) = .false.                                   !Semidiurnal (6,2)\n      swg(153:156) = .false.                                   !Terdiurnal (3,3)\n      swg(157:160) = .false.                                   !Terdiurnal (4,3)\n      swg(161:164) = .false.                                   !Terdiurnal (5,3)\n      swg(165:168) = .false.                                   !Terdiurnal (6,3)\n      swg(197:200) = .false.                                   !SPW1 (1,1)\n      swg(205:208) = .false.                                   !SPW1 (3,1)\n      swg(213:216) = .false.                                   !SPW1 (5,1)\n      swg(259:262) = .false.                                   !SPW2 (3,2)\n      swg(267:270) = .false.                                   !SPW2 (5,2)\n      swg(394:397) = .false.                                   !Geomag (Daily mode terms)\n      swg(407:410) = .false.                                   !Mixed UT/Lon/Geomag (Daily mode terms)\n      swg(422:425) = .false.                                   !Geomag (Storm-time mode terms)\n      swg(435:438) = .false.                                   !Mixed UT/Lon/Geomag (Storm-time mode terms)\n      swg(446)     = .false.                                   !UT/Lon\n    endif\n    if (swc(6) .eq. 0) then                                 !Asymmetric semiannual\n      swg(221:224) = .false.                                   !SPW1 (1,1)\n      swg(229:232) = .false.                                   !SPW1 (3,1)\n      swg(237:240) = .false.                                   !SPW1 (5,1)\n      swg(279:282) = .false.                                   !SPW2 (3,2)\n      swg(287:290) = .false.                                   !SPW2 (5,2)\n    endif\n    if (swc(7) .eq. 0) then                                 !Diurnal\n      swg(398:401) = .false.                                   !Geomag (Daily mode terms)\n      swg(426:429) = .false.                                   !Geomag (Storm-time mode terms)\n    endif\n    if (swc(11) .eq. 0) then                                !Longitude\n      swg(402:410) = .false.                                   !Mixed UT/Lon/Geomag (Daily mode terms)\n      swg(430:438) = .false.                                   !Mixed UT/Lon/Geomag (Storm-time mode terms)\n      swg(452:453) = .false.                                   !UT/Lon\n    endif\n    if (swc(12) .eq. 0) then                                !UT/Lon\n      swg(411:414) = .false.                                   !Mixed UT/Lon/Geomag (Daily mode terms)\n      swg(439:440) = .false.                                   !Mixed UT/Lon/Geomag (Storm-time mode terms)\n    endif\n    \n  end subroutine tselec\n\n  !==================================================================================================\n  ! TRETRV: Legacy routine for retrieving switch settings\n  !==================================================================================================\n  subroutine tretrv(svv)\n\n    implicit none\n\n    real(4), intent(out) :: svv(1:25)\n\n    integer              :: i\n\n    do i = 1, 25\n      svv(i) = sav(i)\n    enddo\n  \n  end subroutine tretrv\n\nend module msis_init\n"
  },
  {
    "path": "source/external/nrlmsis2/msis_tfn.F90",
    "content": "!##############################################################################\n! MSIS (NRL-SOF-014-1) SOFTWARE\n!\n! MSIS is a registered trademark of the Government of the United States of \n! America, as represented by the Secretary of the Navy. Unauthorized use of \n! the trademark is prohibited. \n!\n! The MSIS Software (hereinafter Software) is property of the United States \n! Government, as represented by the Secretary of the Navy. Methods performed\n! by this software are covered by U.S. Patent Number 10,641,925. The Government\n! of the United States of America, as represented by the Secretary of the Navy, \n! herein grants a non-exclusive, non-transferable license to the Software for \n! academic, non-commercial, purposes only. A user of the Software shall not: \n! (i) use the Software for any non-academic, commercial purposes, (ii) make \n! any modification or improvement to the Software, (iii) disseminate the \n! Software or any supporting data to any other person or entity who will use \n! the Software for any non-academic, commercial purposes, or (iv) copy the \n! Software or any documentation related thereto except for (a) distribution \n! among the users personal computer systems, archival, or emergency repair \n! purposes, or (b) distribution for non-commercial, academic purposes, without \n! first obtaining the written consent of IP Counsel for the Naval Research \n! Laboratory. \n!\n! As the owner of MSIS, the United States, the United States Department of \n! Defense, and their employees: (1) Disclaim any warranties, express, or \n! implied, including but not limited to any implied warranties of \n! merchantability, fitness for a particular purpose, title or non-infringement, \n! (2) Do not assume any legal liability or responsibility for the accuracy, \n! completeness, or usefulness of the software, (3) Do not represent that use of \n! the software would not infringe privately owned rights, (4) Do not warrant \n! that the software will function uninterrupted, that is error-free or that any \n! errors will be corrected.\n!\n! BY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n!##############################################################################\n\n!!! ===========================================================================\n!!! NRLMSIS 2.0:\n!!! Neutral atmosphere empirical model from the surface to lower exosphere\n!!! John Emmert (john.emmert@nrl.navy.mil)\n!!! Doug Drob (douglas.drob@nrl.navy.mil)\n!!! ===========================================================================\n\n!**************************************************************************************************\n! MSIS_TFN Module: Contains vertical temperature profile parameters and subroutines, including \n!                  temperature integration terms.\n!**************************************************************************************************\nmodule msis_tfn  \n\n  use msis_constants, only     : rp, nl\n    \n  type tnparm\n    sequence\n    real(kind=rp)             :: cf(0:nl)    ! Spline coefficients\n    real(kind=rp)             :: tzetaF      ! Tn at zetaF\n    real(kind=rp)             :: tzetaA      ! Tn at zetaA (reference altitude for O1, H1)\n    real(kind=rp)             :: dlntdzA     ! log-temperature gradient at zetaA (km^-1)\n    real(kind=rp)             :: lndtotF     ! ln total number density at zetaF (m^-3)\n    real(kind=rp)             :: tex\n    real(kind=rp)             :: tgb0\n    real(kind=rp)             :: tb0\n    real(kind=rp)             :: sigma\n    real(kind=rp)             :: sigmasq\n    real(kind=rp)             :: b           ! b = 1-tb0/tex\n    real(kind=rp)             :: beta(0:nl)  ! 1st integration coefficients on k=5 splines \n    real(kind=rp)             :: gamma(0:nl) ! 2nd integration coefficients on k=6 splines \n    real(kind=rp)             :: cVs         ! 1st integration constant (spline portion)\n    real(kind=rp)             :: cVb         ! 1st integration constant (Bates portion)\n    real(kind=rp)             :: cWs         ! 2nd integration constant (spline portion)\n    real(kind=rp)             :: cWb         ! 2nd integration constant (Bates portion)\n    real(kind=rp)             :: VzetaF      ! 1st indefinite integral at zetaF\n    real(kind=rp)             :: VzetaA      ! 1st indefinite integral at zetaA\n    real(kind=rp)             :: WzetaA      ! 2nd indefinite integral at zetaA\n    real(kind=rp)             :: Vzeta0      ! 1st indefinite integral at zeta=0 (needed for pressure calculation)\n  end type tnparm\n\n  contains\n    \n  !==================================================================================================\n  ! TFNPARM: Compute the vertical temperature and species-independent profile parameters\n  !==================================================================================================\n  subroutine tfnparm(gf,tpro)\n\n    use msis_constants, only   : kB, lnP0, Mbarg0divkB, zetaB, zetaA, izfx, izax, itex, itgb0, itb0, c2tn, &\n                                 maxnbf, mbf, nmag, nut, cmag, cut, &\n                                 wbeta, wgamma, S5zetaB, S6zetaB, wghtAxdz, S4zetaA, S5zetaA, S6zetaA, &\n                                 S4zetaF, S5zetaF, S5zeta0\n    use msis_init, only        : smod, TN, PR\n    use msis_gfn, only         : sfluxmod, geomag, utdep\n\n    implicit none\n\n    real(kind=rp), external   :: dilog\n\n    real(kind=rp), intent(in) :: gf(0:maxnbf-1) ! Array of horizontal and temporal basis function terms   \n    type(tnparm), intent(out) :: tpro           ! Output structure containing temperature vertical profile parameters\n    \n    integer(4)                :: ix\n    real(kind=rp)             :: bc(3)\n        \n    ! Unconstrained spline coefficients\n    do ix = 0, itb0-1\n      tpro%cf(ix) = dot_product(TN%beta(0:mbf,ix),gf(0:mbf))\n    enddo\n    do ix = 0, itb0-1\n      if (smod(ix)) then\n        tpro%cf(ix) = tpro%cf(ix) + sfluxmod(ix,gf,TN,1.0_rp/TN%beta(0,ix))    !sfluxmod adds F10.7 modulation of tides\n      endif\n    enddo\n\n    ! Exospheric temperature\n    tpro%tex = dot_product(TN%beta(0:mbf,itex),gf(0:mbf))\n    tpro%tex = tpro%tex + sfluxmod(itex,gf,TN,1.0_rp/TN%beta(0,itex))         \n    tpro%tex = tpro%tex + geomag(TN%beta(cmag:cmag+nmag-1,itex),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n    tpro%tex = tpro%tex + utdep(TN%beta(cut:cut+nut-1,itex),gf(cut:cut+8))\n\n    ! Temperature gradient at zetaB (122.5 km)\n    tpro%tgb0 = dot_product(TN%beta(0:mbf,itgb0),gf(0:mbf))\n    if (smod(itgb0)) tpro%tgb0 = tpro%tgb0 + sfluxmod(itgb0,gf,TN,1.0_rp/TN%beta(0,itgb0))         \n    tpro%tgb0 = tpro%tgb0 + geomag(TN%beta(cmag:cmag+nmag-1,itgb0),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n\n    ! Temperature at zetaB (122.5 km)\n    tpro%tb0 = dot_product(TN%beta(0:mbf,itb0),gf(0:mbf))\n    if (smod(itb0)) tpro%tb0 = tpro%tb0 + sfluxmod(itb0,gf,TN,1.0_rp/TN%beta(0,itb0))         \n    tpro%tb0 = tpro%tb0 + geomag(TN%beta(cmag:cmag+nmag-1,itb0),gf(cmag:cmag+12),gf(cmag+13:cmag+26))\n\n    ! Shape factor\n    tpro%sigma = tpro%tgb0/(tpro%tex-tpro%tb0)\n\n    ! Constrain top three spline coefficients for C2 continuity\n    bc(1) = 1.0_rp/tpro%tb0\n    bc(2) = -tpro%tgb0/(tpro%tb0*tpro%tb0)\n    bc(3) = -bc(2)*(tpro%sigma + 2.0_rp*tpro%tgb0/tpro%tb0)    \n    tpro%cf(itb0:itex) = matmul(bc, c2tn)\n\n    ! Reference temperature at zetaF (70 km)\n    tpro%tzetaF = 1.0_rp / dot_product(tpro%cf(izFx:izFx+2),S4zetaF)\n\n    ! Reference temperature and gradient at zetaA (85 km)\n    tpro%tzetaA = 1.0_rp / dot_product(tpro%cf(izAx:izAx+2),S4zetaA)\n    tpro%dlntdzA = -dot_product(tpro%cf(izAx:izAx+2),wghtAxdz) * tpro%tzetaA\n        \n    ! Calculate spline coefficients for first and second 1/T integrals \n    tpro%beta(0) = tpro%cf(0)*wbeta(0)\n    do ix = 1, nl\n      tpro%beta(ix) = tpro%beta(ix-1) + tpro%cf(ix)*wbeta(ix)\n    enddo\n    tpro%gamma(0) = tpro%beta(0)*wgamma(0)\n    do ix = 1, nl\n      tpro%gamma(ix) = tpro%gamma(ix-1) + tpro%beta(ix)*wgamma(ix)\n    enddo\n        \n    ! Integration terms and constants\n    tpro%b = 1 - tpro%tb0 / tpro%tex\n    tpro%sigmasq = tpro%sigma * tpro%sigma\n    tpro%cVS = -dot_product(tpro%beta(itb0-1:itb0+2),S5zetaB)\n    tpro%cWS = -dot_product(tpro%gamma(itb0-2:itb0+2),S6zetaB)\n    tpro%cVB = -log(1-tpro%b) / (tpro%sigma * tpro%tex)\n    tpro%cWB = -dilog(tpro%b) / (tpro%sigmasq * tpro%tex)\n    tpro%VzetaF = dot_product(tpro%beta(izfx-1:izfx+2),S5zetaF) + tpro%cVS\n    tpro%VzetaA = dot_product(tpro%beta(izax-1:izax+2),S5zetaA) + tpro%cVS\n    tpro%WzetaA = dot_product(tpro%gamma(izax-2:izax+2),S6zetaA) + tpro%cVS*(zetaA-zetaB) + tpro%cWS\n    tpro%Vzeta0 = dot_product(tpro%beta(0:2),S5zeta0) + tpro%cVS\n\n    ! Compute total number density at zetaF\n    tpro%lndtotF = lnP0 - Mbarg0divkB*(tpro%VzetaF - tpro%Vzeta0) - log(kB*tpro%TzetaF)\n\n    return\n    \n  end subroutine tfnparm\n    \n  !==================================================================================================\n  ! TFNX: Compute the temperature at specified geopotential height\n  !==================================================================================================\n  real(kind=rp) function tfnx(z,iz,wght,tpro)\n\n    use msis_constants, only   : zetaB\n\n    implicit none\n\n    real(kind=rp), intent(in) :: z            ! Geopotential height\n    integer, intent(in)       :: iz           ! Bspline reference index\n    real(kind=rp), intent(in) :: wght(-3:0)   ! Bspline weights\n    type(tnparm), intent(in)  :: tpro         ! Structure containing temperature vertical profile parameters\n\n    integer                   :: i, j\n  \n    if (z .lt. zetaB) then \n      ! Spline region\n      i = max(iz-3,0)\n      if (iz .lt. 3) then\n        j = -iz\n      else\n        j = -3\n      endif\n      tfnx = 1.0_rp / dot_product(tpro%cf(i:iz),wght(j:0))\n    else\n      ! Bates profile region\n      tfnx = tpro%tex - (tpro%tex - tpro%tb0)*exp(-tpro%sigma * (z - zetaB))\n    endif\n\n    return\n\n  end function tfnx\n    \nend module msis_tfn\n"
  },
  {
    "path": "source/external/nrlmsis2/nrlmsis2.h",
    "content": "/***********************************************/\n/**\n* @file nrlmsis2.h\n*\n* @brief Fortran Wrapper.\n*\n* @author Sandro Krauss\n* @date   2021-03-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NRLMSIS2MODEL__\n#define __GROOPS_NRLMSIS2MODEL__\n\nextern \"C\" void msisinitWrapper(const char *path, const char *file);\nextern \"C\" void msiscalcWrapper(const F77Float &day, const F77Float &utsec, const F77Float &z,const F77Float &lat, const F77Float &lon, const F77Float &sfluxavg, const F77Float &sflux, const F77Float ap[7], F77Float &tn, F77Float dn[10], F77Float &tex);\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/external/nrlmsis2/nrlmsis2Wrapper.F90",
    "content": "!***********************************************/\n!**\n!* @file nrlmsis2wrapper.F90\n!*\n!* @brief Fortran Wrapper.\n!*\n!* @author Sandro Krauss\n!* @date   2021-03-18\n!*\n!/***********************************************/\n\nSUBROUTINE msisinitWrapper(inputPath, inputFile) bind(C, name=\"msisinitWrapper\")\n\n  use msis_init, only                          : msisinit\n  use, intrinsic                              :: ISO_C_BINDING\n\n  IMPLICIT NONE\n  real(4)                                     :: switches(1:25)=1.0\n  character(len=1,kind=C_char), intent(in)    :: inputPath(*)\n  character(len=1,kind=C_char), intent(in)    :: inputFile(*)\n  character(len=:), allocatable               :: str1, str2\n  integer                                     :: i, nchars\n\n\n  ! DEFINE: Options for initializing NRLMSIS 2.0 model\n  ! --------------------------------------------------\n  !  switch_legacy   Floating point array (1:25) of legacy switches that\n  !  control groups of terms:\n  ! 1 - F10.7\n  ! 2 - Time independent\n  ! 3 - Symmetrical annual\n  ! 4 - Symmetrical semiannual\n  ! 5 - Asymmetrical annual\n  ! 6 - Asymmetrical semiannual\n  ! 7 - Diurnal\n  ! 8 - Semidiurnal\n  ! 9 - Geomagnetic activity:\n  !     1.0 = Daily Ap mode\n  !    -1.0 = Storm-time ap mode\n  ! 10 - All UT/long effects\n  ! 11 - Longitudinal\n  ! 12 - UT and mixed UT/long\n  ! 13 - Mixed Ap/UT/long\n  ! 14 - Terdiurnal\n  ! 15-25 - Not used in NRLMSIS 2.0\n  switches(9) = -1.0\n\n  ! CONVERT: c_char -> char necessary to call the msisinit subroutine\n  i = 1\n  do\n     if (inputPath(i) == c_null_char) exit\n     i = i + 1\n  end do\n  nchars = i - 1  ! Exclude null character from Fortran string\n  allocate(character(len=nchars) :: str1)\n  str1 = transfer(inputPath(1:nchars), str1)\n\n  i = 1\n  do\n     if (inputFile(i) == c_null_char) exit\n     i = i + 1\n  end do\n  nchars = i - 1  ! Exclude null character from Fortran string\n  allocate(character(len=nchars) :: str2)\n  str2 = transfer(inputFile(1:nchars), str2)\n\n  ! initialise the model\n  CALL MSISINIT(str1, str2, switch_legacy=switches)\n\n  deallocate(str1)\n  deallocate(str2)\n\nEND SUBROUTINE msisinitWrapper\n\n!**********************************************\n\nSUBROUTINE msiscalcWrapper(day,utsec,z,lat,lon,sfluxavg,sflux,ap,tn,dn,tex) bind(C, name=\"msiscalcWrapper\")\n\n  use msis_calc, only   : msiscalc\n  use, intrinsic       :: ISO_C_BINDING\n\n  IMPLICIT NONE\n  real(4), intent(in)  :: day\n  real(4), intent(in)  :: utsec\n  real(4), intent(in)  :: z\n  real(4), intent(in)  :: lat\n  real(4), intent(in)  :: lon\n  real(4), intent(in)  :: sfluxavg,sflux,ap(1:7)\n  real(4), intent(out) :: tn, dn(1:10)\n  real(4), intent(out) :: tex\n\n  CALL msiscalc(day,utsec,z,lat,lon,sfluxavg,sflux,ap,tn,dn,tex)\n\nEND SUBROUTINE msiscalcWrapper\n\n!**********************************************\n"
  },
  {
    "path": "source/external/nrlmsis2/readme.txt",
    "content": "===============================================================================\nMSIS® (NRL-SOF-014-1) SOFTWARE\n\nMSIS® is a registered trademark of the Government of the United States of \nAmerica, as represented by the Secretary of the Navy. Unauthorized use of \nthe trademark is prohibited. \n\nThe MSIS® Software (hereinafter Software) is property of the United States \nGovernment, as represented by the Secretary of the Navy. Methods performed\nby this software are covered by U.S. Patent Number 10,641,925. The Government\nof the United States of America, as represented by the Secretary of the Navy, \nherein grants a non-exclusive, non-transferable license to the Software for \nacademic, non-commercial, purposes only. A user of the Software shall not: \n(i) use the Software for any non-academic, commercial purposes, (ii) make \nany modification or improvement to the Software, (iii) disseminate the \nSoftware or any supporting data to any other person or entity who will use \nthe Software for any non-academic, commercial purposes, or (iv) copy the \nSoftware or any documentation related thereto except for (a) distribution \namong the user’s personal computer systems, archival, or emergency repair \npurposes, or (b) distribution for non-commercial, academic purposes, without \nfirst obtaining the written consent of IP Counsel for the Naval Research \nLaboratory. \n\nAs the owner of MSIS®, the United States, the United States Department of \nDefense, and their employees: (1) Disclaim any warranties, express, or \nimplied, including but not limited to any implied warranties of \nmerchantability, fitness for a particular purpose, title or non-infringement, \n(2) Do not assume any legal liability or responsibility for the accuracy, \ncompleteness, or usefulness of the software, (3) Do not represent that use of \nthe software would not infringe privately owned rights, (4) Do not warrant \nthat the software will function uninterrupted, that is error-free or that any \nerrors will be corrected.\n\nBY USING THIS SOFTWARE YOU ARE AGREEING TO THE ABOVE TERMS AND CONDITIONS.  \n===============================================================================\n\nNRLMSIS 2.0 Whole-Atmosphere Empirical Model of Temperature and Neutral Species\n  Densities\n\nThis software package is a major upgrade to the NRLMSISE-00 model.\n\nVERSION HISTORY\n  08 MAR 19 Version 1.97 (Beta version)\n  27 APR 20 Version 1.99 (Beta version)\n  26 MAY 20 Version 2.0 (Release version)\n\nAUTHORS\n  Douglas Drob (douglas.drob@nrl.navy.mil)\n  John Emmert (john.emmert@nrl.navy.mil)\n  \nREFERENCE\n  Emmert, J.T., Drob, D. P., Picone, J. M., Siskind, D. E., Jones Jr., M.,\n  et al. (2020). NRLMSIS 2.0: A whole-atmosphere empirical model of temperature\n  and neutral species densities. Manuscript in preparation, to be submitted to\n  Earth and Space Science.\n\nPACKAGE CONTENTS\n  readme.txt               This file\n  msis2.0_test.F90         Test program\n  msis_init.F90            Subroutines to initialize the model, set switches and\n                             options, and load parameter file\n  msis_gtd8d.F90           Subroutine to evaluate the model using the legacy\n                             interface\n  msis_calc.F90            Subroutine for evaluating the model using the new\n                             interface\n  msis_constants.F90       Module containing model constants\n  msis_gfn.F90             Subroutines to calculate horizontal expansion\n                             functions\n  msis_tfn.F90             Subroutines to calculate the vertical temperature\n                             profile\n  msis_dfn.F90             Subroutines to calculate vertical density profiles\n  alt2gph.F90              Subroutines to convert between geodetic height and\n                             geopotential height\n  subroutine_dir.jpg       Graphical directory of modules and subroutines\n                             contained in the source code files\n  msis2.0.parm             Binary data file containing model parameters\n  msis2.0_test_in.txt      ASCII file containing input for test program.\n  msis2.0_test_ref_dp.txt  ASCII file containing expected output of test program\n                             (double-precision internally)\n  msis2.0_test_ref_sp.txt  ASCII file containing expected output of test program\n                             (single-precision internally)\n \nRELEASE NOTES: MODEL FORMULATION\n  Major changes to the NRLMSISE-00 formulation include:\n  - The transition from a fully mixed atmosphere to diffusive separation is now\n    represented via height-dependent effective mass for each species.\n  - The temperature profile is now C2 continuous.\n  - A global geopotential height function is now used internally.\n  - Atomic oxygen now extends down to 50 km; below 85 km, the O profile is\n    represented by cubic B splines decoupled from temperature.\n  - Thermal diffusion is no longer applied to any species.\n \nRELEASE NOTES: PARAMETER ESTIMATION\n  - The parameters of the model were tuned to extensive new data in the\n    troposphere, stratosphere, and mesosphere, and to NRLMSISE-00 in the\n    thermosphere. In the thermosphere, the model atomic oxygen was additionally\n    tuned to global average orbit-derived density data.\n  - Thermospheric N2 is now controlled entirely by the temperature profile and\n    the constant mixing ratio of N2 in the lower atmosphere. See paper for\n    details. To instead retrieve the NRLMSISE-00 thermospheric N2, set \n    lN2_msis00 = .true. in the call to MSISINIT.\n\nCOMPILING THE MODEL CODE\n  The model package was tested on Windows, Linux, and Mac systems using the\n    following Fortran compilers and compile statements:\n    gfortran 4.8.5, 6.3.0, 8.1.0\n      gfortran -O3 -cpp -o msis2.0_test.exe alt2gph.F90 msis_constants.F90\n      msis_init.F90 msis_gfn.F90 msis_tfn.F90 msis_dfn.F90 msis_calc.F90\n      msis_gtd8d.F90 msis2.0_test.F90\n        NOTES:\n        - For double precision, add the flag -DDBLE\n        - The following optimization flags may improve performance:\n            -march=native -ffast-math\n    Intel 17.0.2.163, 18.0.1.156\n      ifort -O2 -fpp -o msis2.0_test.exe alt2gph.F90 msis_constants.F90\n      msis_init.F90 msis_gfn.F90 msis_tfn.F90 msis_dfn.F90 msis_calc.F90\n      msis_gtd8d.F90 msis2.0_test.F90\n        NOTES:\n        - For double precision, add the flag -DDBLE\n        - The following optimization flags may improve performance:\n            Windows:     -Qipo -QxHost\n            Linux/macOS: -ipo -xHost\n\nINITIALIZING AND RUNNING THE MODEL\n  - The model must be initialized using the MSISINIT subroutine, which sets\n    switches and options and loads the model parameter values from a file.\n  - The switch_legacy optional argument to MSISINIT performs the same function\n    as TSELEC(SW) in NRLSMSISE-00, except that switches 15-25 are not used in\n    NRLMSIS 2.0. The change in the switch-setting call is illustrated as\n    follows, where SW is the 25-element array of switches:\n        NRLMSISE-00: CALL TSELEC(SW)\n        NRLMSIS 2.0: call msisinit(switch_legacy=SW)\n  - The MSISCALC subroutine checks for initialization and does a default\n    initialization if necessary. This self-initialization will be removed in\n    future versions.\n  - The model can be called using either the legacy interface (subroutine\n    GTD8D) or the new interface (subroutine MSISCALC).\n  - Details of the input and output arguments of MSISINIT, GTD8D, and MSISCALC\n    are provided in the headers of the respective source code files.\n  \nCOMPUTATIONAL PERFORMANCE\n  - The model should be initialized (by calling MSISINIT) only before first use\n    or when switches and options need to be changed. Re-initializing before each\n    model call will significantly slow down the code.\n  - The code is most efficient when computing vertical profiles at the same\n    horizontal location and time, in which case the computed vertical profile\n    parameters are re-used from call to call. Therefore, altitude should be in\n    the inner loop of multiple calls, when possible.\n  - For \"column\" calls (inner loop on altitude) with 100 vertical levels, \n    NRLMSIS 2.0 is 4-5 times faster than NRLMSISE-00.\n  - For applications in which the horizontal location or time changes with every\n    call (e.g., satellite ephemerides), users may find that NRLMSIS 2.0 is 1/3\n    to 1/2 as fast as NRLMSISE-00. The reduction in speed is due to the greater\n    number of model parameters in NRLMSIS 2.0, as well its stronger coupling\n    with the lower atmosphere, compared to NRLMSISE-00. However, the model is\n    still very fast: a typical desktop system can process at least 100,000\n    serial calls per second.\n  - Additional improvement in speed can be obtained by computing only those\n    species that are needed, via the lspec_select input argument of MSISINIT.\n\nACKNOWLEDGEMENTS\n  This work was supported by the Chief of Naval Research, the Office of Naval\n  Research (BSION program), and NASA (Grants NNH16ZDA001N-HSR/ITM16_2-0013, \n  NNH14ZDA001N-GIODDE14_2/NNH15AZ72I)"
  },
  {
    "path": "source/external/sgp4/LICENSE",
    "content": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n"
  },
  {
    "path": "source/external/sgp4/README.txt",
    "content": "modfied from\nhttps://github.com/aholinch/sgp4\n"
  },
  {
    "path": "source/external/sgp4/SGP4.cpp",
    "content": "#include <stdio.h>\n#include <math.h>\n#include \"SGP4.h\"\n\n#define wgs72old 1\n#define wgs72 2\n#define wgs84 3\n#define pi 3.14159265358979323846\n#define twopi  (2.0*pi)\n#define deg2rad  (pi/180.0)\n\n#define TRUE 1\n#define FALSE 0\n\nstatic void dpper(double e3, double ee2, double peo, double pgho, double pho,\n                  double pinco, double plo, double se2, double se3, double sgh2,\n                  double sgh3, double sgh4, double sh2, double sh3, double si2,\n                  double si3, double sl2, double sl3, double sl4, double t,\n                  double xgh2, double xgh3, double xgh4, double xh2, double xh3,\n                  double xi2, double xi3, double xl2, double xl3, double xl4,\n                  double zmol, double zmos, char init,\n                  ElsetRec &rec, char opsmode);\n\nstatic void dscom(double epoch, double ep, double argpp, double tc, double inclp,\n                  double nodep, double np, ElsetRec &rec);\n\nstatic void dsinit(double tc, double xpidot, ElsetRec &rec);\n\nstatic void dspace(double tc, ElsetRec &rec);\n\nstatic void initl(double epoch, ElsetRec &rec);\n\nbool sgp4init(char opsmode,ElsetRec &rec);\n\nbool sgp4 (ElsetRec &rec, double tsince, double r[3], double v[3]);\n\nstatic void getgravconst(int whichconst, ElsetRec &rec);\n\nstatic double gstime(double jdut1);\n\n// static double fmod(double numer, double denom)\n// {\n//     long tquot = (long)floor(numer/denom);\n//     return numer-tquot*denom;\n// }\n\n/*     ----------------------------------------------------------------\n*\n*                               sgp4unit.cpp\n*\n*    this file contains the sgp4 procedures for analytical propagation\n*    of a satellite. the code was originally released in the 1980 and 1986\n*    spacetrack papers. a detailed discussion of the theory and history\n*    may be found in the 2006 aiaa paper by vallado, crawford, hujsak,\n*    and kelso.\n*\n*                            companion code for\n*               fundamentals of astrodynamics and applications\n*                                    2013\n*                              by david vallado\n*\n*     (w) 719-573-2600, email dvallado@agi.com, davallado@gmail.com\n*\n*    current :\n*               7 dec 15  david vallado\n*                           fix jd, jdfrac\n*    changes :\n*               3 nov 14  david vallado\n*                           update to msvs2013 c++\n*              30 aug 10  david vallado\n*                           delete unused variables in initl\n*                           replace pow integer 2, 3 with multiplies for speed\n*               3 nov 08  david vallado\n*                           put returns in for error codes\n*              29 sep 08  david vallado\n*                           fix atime for faster operation in dspace\n*                           add operationmode for afspc (a) or improved (i)\n*                           performance mode\n*              16 jun 08  david vallado\n*                           update small eccentricity check\n*              16 nov 07  david vallado\n*                           misc fixes for better compliance\n*              20 apr 07  david vallado\n*                           misc fixes for constants\n*              11 aug 06  david vallado\n*                           chg lyddane choice back to strn3, constants, misc doc\n*              15 dec 05  david vallado\n*                           misc fixes\n*              26 jul 05  david vallado\n*                           fixes for paper\n*                           note that each fix is preceded by a\n*                           comment with \"sgp4fix\" and an explanation of\n*                           what was changed\n*              10 aug 04  david vallado\n*                           2nd printing baseline working\n*              14 may 01  david vallado\n*                           2nd edition baseline\n*                     80  norad\n*                           original baseline\n*       ----------------------------------------------------------------      */\n\n\n\n\n    /* -----------------------------------------------------------------------------\n    *\n    *                           procedure dpper\n    *\n    *  this procedure provides deep space long period periodic contributions\n    *    to the mean elements.  by design, these periodics are zero at epoch.\n    *    this used to be dscom which included initialization, but it's really a\n    *    recurring function.\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    e3          -\n    *    ee2         -\n    *    peo         -\n    *    pgho        -\n    *    pho         -\n    *    pinco       -\n    *    plo         -\n    *    se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 -\n    *    t           -\n    *    xh2, xh3, xi2, xi3, xl2, xl3, xl4 -\n    *    zmol        -\n    *    zmos        -\n    *    ep          - eccentricity                           0.0 - 1.0\n    *    inclo       - inclination - needed for lyddane modification\n    *    nodep       - right ascension of ascending node\n    *    argpp       - argument of perigee\n    *    mp          - mean anomaly\n    *\n    *  outputs       :\n    *    ep          - eccentricity                           0.0 - 1.0\n    *    inclp       - inclination\n    *    nodep        - right ascension of ascending node\n    *    argpp       - argument of perigee\n    *    mp          - mean anomaly\n    *\n    *  locals        :\n    *    alfdp       -\n    *    betdp       -\n    *    cosip  , sinip  , cosop  , sinop  ,\n    *    dalf        -\n    *    dbet        -\n    *    dls         -\n    *    f2, f3      -\n    *    pe          -\n    *    pgh         -\n    *    ph          -\n    *    pinc        -\n    *    pl          -\n    *    sel   , ses   , sghl  , sghs  , shl   , shs   , sil   , sinzf , sis   ,\n    *    sll   , sls\n    *    xls         -\n    *    xnoh        -\n    *    zf          -\n    *    zm          -\n    *\n    *  coupling      :\n    *    none.\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    void dpper(double e3, double ee2, double peo, double pgho, double pho,\n               double pinco, double plo, double se2, double se3, double sgh2,\n               double sgh3, double sgh4, double sh2, double sh3, double si2,\n               double si3, double sl2, double sl3, double sl4, double t,\n               double xgh2, double xgh3, double xgh4, double xh2, double xh3,\n               double xi2, double xi3, double xl2, double xl3, double xl4,\n               double zmol, double zmos,\n               char init, ElsetRec &rec, char opsmode)\n    {\n        /* --------------------- local variables ------------------------ */\n        double alfdp, betdp, cosip, cosop, dalf, dbet, dls,\n            f2, f3, pe, pgh, ph, pinc, pl,\n            sel, ses, sghl, sghs, shll, shs, sil,\n            sinip, sinop, sinzf, sis, sll, sls, xls,\n            xnoh, zf, zm, zel, zes, znl, zns;\n\n\n        /* ---------------------- constants ----------------------------- */\n        zns = 1.19459e-5;\n        zes = 0.01675;\n        znl = 1.5835218e-4;\n        zel = 0.05490;\n\n        /* --------------- calculate time varying periodics ----------- */\n        zm = zmos + zns * t;\n        // be sure that the initial call has time set to zero\n        if(init == 'y')\n            zm = zmos;\n        zf = zm + 2.0 * zes * sin(zm);\n        sinzf = sin(zf);\n        f2 = 0.5 * sinzf * sinzf - 0.25;\n        f3 = -0.5 * sinzf * cos(zf);\n        ses = se2* f2 + se3 * f3;\n        sis = si2 * f2 + si3 * f3;\n        sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf;\n        sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf;\n        shs = sh2 * f2 + sh3 * f3;\n        zm = zmol + znl * t;\n        if(init == 'y')\n            zm = zmol;\n        zf = zm + 2.0 * zel * sin(zm);\n        sinzf = sin(zf);\n        f2 = 0.5 * sinzf * sinzf - 0.25;\n        f3 = -0.5 * sinzf * cos(zf);\n        sel = ee2 * f2 + e3 * f3;\n        sil = xi2 * f2 + xi3 * f3;\n        sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf;\n        sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf;\n        shll = xh2 * f2 + xh3 * f3;\n        pe = ses + sel;\n        pinc = sis + sil;\n        pl = sls + sll;\n        pgh = sghs + sghl;\n        ph = shs + shll;\n\n        if(init == 'n')\n        {\n            pe = pe - peo;\n            pinc = pinc - pinco;\n            pl = pl - plo;\n            pgh = pgh - pgho;\n            ph = ph - pho;\n            rec.inclp = rec.inclp + pinc;\n            rec.ep = rec.ep + pe;\n            sinip = sin(rec.inclp);\n            cosip = cos(rec.inclp);\n\n            /* ----------------- apply periodics directly ------------ */\n            //  sgp4fix for lyddane choice\n            //  strn3 used original inclination - this is technically feasible\n            //  gsfc used perturbed inclination - also technically feasible\n            //  probably best to readjust the 0.2 limit value and limit discontinuity\n            //  0.2 rad = 11.45916 deg\n            //  use next line for original strn3 approach and original inclination\n            //  if(inclo >= 0.2)\n            //  use next line for gsfc version and perturbed inclination\n            if(rec.inclp >= 0.2)\n            {\n                ph = ph / sinip;\n                pgh = pgh - cosip * ph;\n                rec.argpp = rec.argpp + pgh;\n                rec.nodep = rec.nodep + ph;\n                rec.mp = rec.mp + pl;\n            }\n            else\n            {\n                /* ---- apply periodics with lyddane modification ---- */\n                sinop = sin(rec.nodep);\n                cosop = cos(rec.nodep);\n                alfdp = sinip * sinop;\n                betdp = sinip * cosop;\n                dalf = ph * cosop + pinc * cosip * sinop;\n                dbet = -ph * sinop + pinc * cosip * cosop;\n                alfdp = alfdp + dalf;\n                betdp = betdp + dbet;\n                rec.nodep = fmod(rec.nodep, twopi);\n                //  sgp4fix for afspc written intrinsic functions\n                // nodep used without a trigonometric function ahead\n                if((rec.nodep < 0.0) && (opsmode == 'a'))\n                    rec.nodep = rec.nodep + twopi;\n                xls = rec.mp + rec.argpp + cosip * rec.nodep;\n                dls = pl + pgh - pinc * rec.nodep * sinip;\n                xls = xls + dls;\n                xls = fmod(xls,twopi);\n                xnoh = rec.nodep;\n                rec.nodep = atan2(alfdp, betdp);\n                //  sgp4fix for afspc written intrinsic functions\n                // nodep used without a trigonometric function ahead\n                if((rec.nodep < 0.0) && (opsmode == 'a'))\n                    rec.nodep = rec.nodep + twopi;\n                if(fabs(xnoh - rec.nodep) > pi)\n                {\n                    if(rec.nodep < xnoh)\n                        rec.nodep = rec.nodep + twopi;\n                    else\n                        rec.nodep = rec.nodep - twopi;\n                }\n                rec.mp = rec.mp + pl;\n                rec.argpp = xls - rec.mp - cosip * rec.nodep;\n            }\n        }   // if init == 'n'\n\n    }  // dpper\n\n    /*-----------------------------------------------------------------------------\n    *\n    *                           procedure dscom\n    *\n    *  this procedure provides deep space common items used by both the secular\n    *    and periodics subroutines.  input is provided as shown. this routine\n    *    used to be called dpper, but the functions inside weren't well organized.\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    epoch       -\n    *    ep          - eccentricity\n    *    argpp       - argument of perigee\n    *    tc          -\n    *    inclp       - inclination\n    *    nodep       - right ascension of ascending node\n    *    np          - mean motion\n    *\n    *  outputs       :\n    *    sinim  , cosim  , sinomm , cosomm , snodm  , cnodm\n    *    day         -\n    *    e3          -\n    *    ee2         -\n    *    em          - eccentricity\n    *    emsq        - eccentricity squared\n    *    gam         -\n    *    peo         -\n    *    pgho        -\n    *    pho         -\n    *    pinco       -\n    *    plo         -\n    *    rtemsq      -\n    *    se2, se3         -\n    *    sgh2, sgh3, sgh4        -\n    *    sh2, sh3, si2, si3, sl2, sl3, sl4         -\n    *    s1, s2, s3, s4, s5, s6, s7          -\n    *    ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3         -\n    *    sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33        -\n    *    xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4         -\n    *    nm          - mean motion\n    *    z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33         -\n    *    zmol        -\n    *    zmos        -\n    *\n    *  locals        :\n    *    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10         -\n    *    betasq      -\n    *    cc          -\n    *    ctem, stem        -\n    *    x1, x2, x3, x4, x5, x6, x7, x8          -\n    *    xnodce      -\n    *    xnoi        -\n    *    zcosg  , zsing  , zcosgl , zsingl , zcosh  , zsinh  , zcoshl , zsinhl ,\n    *    zcosi  , zsini  , zcosil , zsinil ,\n    *    zx          -\n    *    zy          -\n    *\n    *  coupling      :\n    *    none.\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    void dscom(double epoch, double ep, double argpp, double tc, double inclp,\n               double nodep, double np, ElsetRec &rec)\n    {\n        /* -------------------------- constants ------------------------- */\n        const double zes = 0.01675;\n        const double zel = 0.05490;\n        const double c1ss = 2.9864797e-6;\n        const double c1l = 4.7968065e-7;\n        const double zsinis = 0.39785416;\n        const double zcosis = 0.91744867;\n        const double zcosgs = 0.1945905;\n        const double zsings = -0.98088458;\n\n        /* --------------------- local variables ------------------------ */\n        int lsflg;\n        double a1, a2, a3, a4, a5, a6, a7,\n            a8, a9, a10, betasq, cc, ctem, stem,\n            x1, x2, x3, x4, x5, x6, x7,\n            x8, xnodce, xnoi, zcosg, zcosgl, zcosh, zcoshl,\n            zcosi, zcosil, zsing, zsingl, zsinh, zsinhl, zsini,\n            zsinil, zx, zy;\n\n        rec.nm = np;\n        rec.em = ep;\n        rec.snodm = sin(nodep);\n        rec.cnodm = cos(nodep);\n        rec.sinomm = sin(argpp);\n        rec.cosomm = cos(argpp);\n        rec.sinim = sin(inclp);\n        rec.cosim = cos(inclp);\n        rec.emsq = rec.em * rec.em;\n        betasq = 1.0 - rec.emsq;\n        rec.rtemsq = sqrt(betasq);\n\n        /* ----------------- initialize lunar solar terms --------------- */\n        rec.peo = 0.0;\n        rec.pinco = 0.0;\n        rec.plo = 0.0;\n        rec.pgho = 0.0;\n        rec.pho = 0.0;\n        rec.day = epoch + 18261.5 + tc / 1440.0;\n        xnodce = fmod(4.5236020 - 9.2422029e-4 * rec.day, twopi);\n        stem = sin(xnodce);\n        ctem = cos(xnodce);\n        zcosil = 0.91375164 - 0.03568096 * ctem;\n        zsinil = sqrt(1.0 - zcosil * zcosil);\n        zsinhl = 0.089683511 * stem / zsinil;\n        zcoshl = sqrt(1.0 - zsinhl * zsinhl);\n        rec.gam = 5.8351514 + 0.0019443680 * rec.day;\n        zx = 0.39785416 * stem / zsinil;\n        zy = zcoshl * ctem + 0.91744867 * zsinhl * stem;\n        zx = atan2(zx, zy);\n        zx = rec.gam + zx - xnodce;\n        zcosgl = cos(zx);\n        zsingl = sin(zx);\n\n        /* ------------------------- do solar terms --------------------- */\n        zcosg = zcosgs;\n        zsing = zsings;\n        zcosi = zcosis;\n        zsini = zsinis;\n        zcosh = rec.cnodm;\n        zsinh = rec.snodm;\n        cc = c1ss;\n        xnoi = 1.0 / rec.nm;\n\n        for(lsflg = 1; lsflg <= 2; lsflg++)\n        {\n            a1 = zcosg * zcosh + zsing * zcosi * zsinh;\n            a3 = -zsing * zcosh + zcosg * zcosi * zsinh;\n            a7 = -zcosg * zsinh + zsing * zcosi * zcosh;\n            a8 = zsing * zsini;\n            a9 = zsing * zsinh + zcosg * zcosi * zcosh;\n            a10 = zcosg * zsini;\n            a2 = rec.cosim * a7 + rec.sinim * a8;\n            a4 = rec.cosim * a9 + rec.sinim * a10;\n            a5 = -rec.sinim * a7 + rec.cosim * a8;\n            a6 = -rec.sinim * a9 + rec.cosim * a10;\n\n            x1 = a1 * rec.cosomm + a2 * rec.sinomm;\n            x2 = a3 * rec.cosomm + a4 * rec.sinomm;\n            x3 = -a1 * rec.sinomm + a2 * rec.cosomm;\n            x4 = -a3 * rec.sinomm + a4 * rec.cosomm;\n            x5 = a5 * rec.sinomm;\n            x6 = a6 * rec.sinomm;\n            x7 = a5 * rec.cosomm;\n            x8 = a6 * rec.cosomm;\n\n            rec.z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3;\n            rec.z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4;\n            rec.z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4;\n            rec.z1 = 3.0 *  (a1 * a1 + a2 * a2) + rec.z31 * rec.emsq;\n            rec.z2 = 6.0 *  (a1 * a3 + a2 * a4) + rec.z32 * rec.emsq;\n            rec.z3 = 3.0 *  (a3 * a3 + a4 * a4) + rec.z33 * rec.emsq;\n            rec.z11 = -6.0 * a1 * a5 + rec.emsq *  (-24.0 * x1 * x7 - 6.0 * x3 * x5);\n            rec.z12 = -6.0 *  (a1 * a6 + a3 * a5) + rec.emsq *\n                (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5));\n            rec.z13 = -6.0 * a3 * a6 + rec.emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6);\n            rec.z21 = 6.0 * a2 * a5 + rec.emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7);\n            rec.z22 = 6.0 *  (a4 * a5 + a2 * a6) + rec.emsq *\n                (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8));\n            rec.z23 = 6.0 * a4 * a6 + rec.emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8);\n            rec.z1 = rec.z1 + rec.z1 + betasq * rec.z31;\n            rec.z2 = rec.z2 + rec.z2 + betasq * rec.z32;\n            rec.z3 = rec.z3 + rec.z3 + betasq * rec.z33;\n            rec.s3 = cc * xnoi;\n            rec.s2 = -0.5 * rec.s3 / rec.rtemsq;\n            rec.s4 = rec.s3 * rec.rtemsq;\n            rec.s1 = -15.0 * rec.em * rec.s4;\n            rec.s5 = x1 * x3 + x2 * x4;\n            rec.s6 = x2 * x3 + x1 * x4;\n            rec.s7 = x2 * x4 - x1 * x3;\n\n            /* ----------------------- do lunar terms ------------------- */\n            if(lsflg == 1)\n            {\n                rec.ss1 = rec.s1;\n                rec.ss2 = rec.s2;\n                rec.ss3 = rec.s3;\n                rec.ss4 = rec.s4;\n                rec.ss5 = rec.s5;\n                rec.ss6 = rec.s6;\n                rec.ss7 = rec.s7;\n                rec.sz1 = rec.z1;\n                rec.sz2 = rec.z2;\n                rec.sz3 = rec.z3;\n                rec.sz11 = rec.z11;\n                rec.sz12 = rec.z12;\n                rec.sz13 = rec.z13;\n                rec.sz21 = rec.z21;\n                rec.sz22 = rec.z22;\n                rec.sz23 = rec.z23;\n                rec.sz31 = rec.z31;\n                rec.sz32 = rec.z32;\n                rec.sz33 = rec.z33;\n                zcosg = zcosgl;\n                zsing = zsingl;\n                zcosi = zcosil;\n                zsini = zsinil;\n                zcosh = zcoshl * rec.cnodm + zsinhl * rec.snodm;\n                zsinh = rec.snodm * zcoshl - rec.cnodm * zsinhl;\n                cc = c1l;\n            }\n        }\n\n        rec.zmol = fmod(4.7199672 + 0.22997150  * rec.day - rec.gam, twopi);\n        rec.zmos = fmod(6.2565837 + 0.017201977 * rec.day, twopi);\n\n        /* ------------------------ do solar terms ---------------------- */\n        rec.se2  =   2.0 * rec.ss1 * rec.ss6;\n        rec.se3  =   2.0 * rec.ss1 * rec.ss7;\n        rec.si2  =   2.0 * rec.ss2 * rec.sz12;\n        rec.si3  =   2.0 * rec.ss2 * (rec.sz13 - rec.sz11);\n        rec.sl2  =  -2.0 * rec.ss3 * rec.sz2;\n        rec.sl3  =  -2.0 * rec.ss3 * (rec.sz3 - rec.sz1);\n        rec.sl4  =  -2.0 * rec.ss3 * (-21.0 - 9.0 * rec.emsq) * zes;\n        rec.sgh2 =   2.0 * rec.ss4 * rec.sz32;\n        rec.sgh3 =   2.0 * rec.ss4 * (rec.sz33 - rec.sz31);\n        rec.sgh4 = -18.0 * rec.ss4 * zes;\n        rec.sh2  =  -2.0 * rec.ss2 * rec.sz22;\n        rec.sh3  =  -2.0 * rec.ss2 * (rec.sz23 - rec.sz21);\n\n        /* ------------------------ do lunar terms ---------------------- */\n        rec.ee2  =   2.0 * rec.s1 * rec.s6;\n        rec.e3   =   2.0 * rec.s1 * rec.s7;\n        rec.xi2  =   2.0 * rec.s2 * rec.z12;\n        rec.xi3  =   2.0 * rec.s2 * (rec.z13 - rec.z11);\n        rec.xl2  =  -2.0 * rec.s3 * rec.z2;\n        rec.xl3  =  -2.0 * rec.s3 * (rec.z3 - rec.z1);\n        rec.xl4  =  -2.0 * rec.s3 * (-21.0 - 9.0 * rec.emsq) * zel;\n        rec.xgh2 =   2.0 * rec.s4 * rec.z32;\n        rec.xgh3 =   2.0 * rec.s4 * (rec.z33 - rec.z31);\n        rec.xgh4 = -18.0 * rec.s4 * zel;\n        rec.xh2  =  -2.0 * rec.s2 * rec.z22;\n        rec.xh3  =  -2.0 * rec.s2 * (rec.z23 - rec.z21);\n\n    }  // dscom\n\n    /*-----------------------------------------------------------------------------\n    *\n    *                           procedure dsinit\n    *\n    *  this procedure provides deep space contributions to mean motion dot due\n    *    to geopotential resonance with half day and one day orbits.\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    xke         - reciprocal of tumin\n    *    cosim, sinim-\n    *    emsq        - eccentricity squared\n    *    argpo       - argument of perigee\n    *    s1, s2, s3, s4, s5      -\n    *    ss1, ss2, ss3, ss4, ss5 -\n    *    sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 -\n    *    t           - time\n    *    tc          -\n    *    gsto        - greenwich sidereal time                   rad\n    *    mo          - mean anomaly\n    *    mdot        - mean anomaly dot (rate)\n    *    no          - mean motion\n    *    nodeo       - right ascension of ascending node\n    *    nodedot     - right ascension of ascending node dot (rate)\n    *    xpidot      -\n    *    z1, z3, z11, z13, z21, z23, z31, z33 -\n    *    eccm        - eccentricity\n    *    argpm       - argument of perigee\n    *    inclm       - inclination\n    *    mm          - mean anomaly\n    *    xn          - mean motion\n    *    nodem       - right ascension of ascending node\n    *\n    *  outputs       :\n    *    em          - eccentricity\n    *    argpm       - argument of perigee\n    *    inclm       - inclination\n    *    mm          - mean anomaly\n    *    nm          - mean motion\n    *    nodem       - right ascension of ascending node\n    *    irez        - flag for resonance           0-none, 1-one day, 2-half day\n    *    atime       -\n    *    d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433    -\n    *    dedt        -\n    *    didt        -\n    *    dmdt        -\n    *    dndt        -\n    *    dnodt       -\n    *    domdt       -\n    *    del1, del2, del3        -\n    *    ses  , sghl , sghs , sgs  , shl  , shs  , sis  , sls\n    *    theta       -\n    *    xfact       -\n    *    xlamo       -\n    *    xli         -\n    *    xni\n    *\n    *  locals        :\n    *    ainv2       -\n    *    aonv        -\n    *    cosisq      -\n    *    eoc         -\n    *    f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543  -\n    *    g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533  -\n    *    sini2       -\n    *    temp        -\n    *    temp1       -\n    *    theta       -\n    *    xno2        -\n    *\n    *  coupling      :\n    *    getgravconst- no longer used\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    void dsinit(double tc, double xpidot, ElsetRec &rec)\n    {\n        /* --------------------- local variables ------------------------ */\n\n        double ainv2, aonv = 0.0, cosisq, eoc, f220, f221, f311,\n            f321, f322, f330, f441, f442, f522, f523,\n            f542, f543, g200, g201, g211, g300, g310,\n            g322, g410, g422, g520, g521, g532, g533,\n            ses, sgs, sghl, sghs, shs, shll, sis,\n            sini2, sls, temp, temp1, theta, xno2, q22,\n            q31, q33, root22, root44, root54, rptim, root32,\n            root52, x2o3, znl, emo, zns, emsqo;\n\n        q22 = 1.7891679e-6;\n        q31 = 2.1460748e-6;\n        q33 = 2.2123015e-7;\n        root22 = 1.7891679e-6;\n        root44 = 7.3636953e-9;\n        root54 = 2.1765803e-9;\n        rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec\n        root32 = 3.7393792e-7;\n        root52 = 1.1428639e-7;\n        x2o3 = 2.0 / 3.0;\n        znl = 1.5835218e-4;\n        zns = 1.19459e-5;\n\n        // sgp4fix identify constants and allow alternate values\n        // just xke is used here so pass it in rather than have multiple calls\n        // getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );\n\n        /* -------------------- deep space initialization ------------ */\n        rec.irez = 0;\n        if((rec.nm < 0.0052359877) && (rec.nm > 0.0034906585))\n            rec.irez = 1;\n        if((rec.nm >= 8.26e-3) && (rec.nm <= 9.24e-3) && (rec.em >= 0.5))\n            rec.irez = 2;\n\n        /* ------------------------ do solar terms ------------------- */\n        ses = rec.ss1 * zns * rec.ss5;\n        sis = rec.ss2 * zns * (rec.sz11 + rec.sz13);\n        sls = -zns * rec.ss3 * (rec.sz1 + rec.sz3 - 14.0 - 6.0 * rec.emsq);\n        sghs = rec.ss4 * zns * (rec.sz31 + rec.sz33 - 6.0);\n        shs = -zns * rec.ss2 * (rec.sz21 + rec.sz23);\n        // sgp4fix for 180 deg incl\n        if((rec.inclm < 5.2359877e-2) || (rec.inclm > pi - 5.2359877e-2))\n            shs = 0.0;\n        if(rec.sinim != 0.0)\n            shs = shs / rec.sinim;\n        sgs = sghs - rec.cosim * shs;\n\n        /* ------------------------- do lunar terms ------------------ */\n        rec.dedt = ses + rec.s1 * znl * rec.s5;\n        rec.didt = sis + rec.s2 * znl * (rec.z11 + rec.z13);\n        rec.dmdt = sls - znl * rec.s3 * (rec.z1 + rec.z3 - 14.0 - 6.0 * rec.emsq);\n        sghl = rec.s4 * znl * (rec.z31 + rec.z33 - 6.0);\n        shll = -znl * rec.s2 * (rec.z21 + rec.z23);\n        // sgp4fix for 180 deg incl\n        if((rec.inclm < 5.2359877e-2) || (rec.inclm > pi - 5.2359877e-2))\n            shll = 0.0;\n        rec.domdt = sgs + sghl;\n        rec.dnodt = shs;\n        if(rec.sinim != 0.0)\n        {\n            rec.domdt = rec.domdt - rec.cosim / rec.sinim * shll;\n            rec.dnodt = rec.dnodt + shll / rec.sinim;\n        }\n\n        /* ----------- calculate deep space resonance effects -------- */\n        rec.dndt = 0.0;\n        theta = fmod(rec.gsto + tc * rptim, twopi);\n        rec.em = rec.em + rec.dedt * rec.t;\n        rec.inclm = rec.inclm + rec.didt * rec.t;\n        rec.argpm = rec.argpm + rec.domdt * rec.t;\n        rec.nodem = rec.nodem + rec.dnodt * rec.t;\n        rec.mm = rec.mm + rec.dmdt * rec.t;\n        //   sgp4fix for negative inclinations\n        //   the following if statement should be commented out\n        //if(inclm < 0.0)\n        //  {\n        //    inclm  = -inclm;\n        //    argpm  = argpm - pi;\n        //    nodem = nodem + pi;\n        //  }\n\n        /* -------------- initialize the resonance terms ------------- */\n        if(rec.irez != 0)\n        {\n            aonv = pow(rec.nm / rec.xke, x2o3);\n\n            /* ---------- geopotential resonance for 12 hour orbits ------ */\n            if(rec.irez == 2)\n            {\n                cosisq = rec.cosim * rec.cosim;\n                emo = rec.em;\n                rec.em = rec.ecco;\n                emsqo = rec.emsq;\n                rec.emsq = rec.eccsq;\n                eoc = rec.em * rec.emsq;\n                g201 = -0.306 - (rec.em - 0.64) * 0.440;\n\n                if(rec.em <= 0.65)\n                {\n                    g211 = 3.616 - 13.2470 * rec.em + 16.2900 * rec.emsq;\n                    g310 = -19.302 + 117.3900 * rec.em - 228.4190 * rec.emsq + 156.5910 * eoc;\n                    g322 = -18.9068 + 109.7927 * rec.em - 214.6334 * rec.emsq + 146.5816 * eoc;\n                    g410 = -41.122 + 242.6940 * rec.em - 471.0940 * rec.emsq + 313.9530 * eoc;\n                    g422 = -146.407 + 841.8800 * rec.em - 1629.014 * rec.emsq + 1083.4350 * eoc;\n                    g520 = -532.114 + 3017.977 * rec.em - 5740.032 * rec.emsq + 3708.2760 * eoc;\n                }\n                else\n                {\n                    g211 = -72.099 + 331.819 * rec.em - 508.738 * rec.emsq + 266.724 * eoc;\n                    g310 = -346.844 + 1582.851 * rec.em - 2415.925 * rec.emsq + 1246.113 * eoc;\n                    g322 = -342.585 + 1554.908 * rec.em - 2366.899 * rec.emsq + 1215.972 * eoc;\n                    g410 = -1052.797 + 4758.686 * rec.em - 7193.992 * rec.emsq + 3651.957 * eoc;\n                    g422 = -3581.690 + 16178.110 * rec.em - 24462.770 * rec.emsq + 12422.520 * eoc;\n                    if(rec.em > 0.715)\n                        g520 = -5149.66 + 29936.92 * rec.em - 54087.36 * rec.emsq + 31324.56 * eoc;\n                    else\n                        g520 = 1464.74 - 4664.75 * rec.em + 3763.64 * rec.emsq;\n                }\n                if(rec.em < 0.7)\n                {\n                    g533 = -919.22770 + 4988.6100 * rec.em - 9064.7700 * rec.emsq + 5542.21  * eoc;\n                    g521 = -822.71072 + 4568.6173 * rec.em - 8491.4146 * rec.emsq + 5337.524 * eoc;\n                    g532 = -853.66600 + 4690.2500 * rec.em - 8624.7700 * rec.emsq + 5341.4  * eoc;\n                }\n                else\n                {\n                    g533 = -37995.780 + 161616.52 * rec.em - 229838.20 * rec.emsq + 109377.94 * eoc;\n                    g521 = -51752.104 + 218913.95 * rec.em - 309468.16 * rec.emsq + 146349.42 * eoc;\n                    g532 = -40023.880 + 170470.89 * rec.em - 242699.48 * rec.emsq + 115605.82 * eoc;\n                }\n\n                sini2 = rec.sinim * rec.sinim;\n                f220 = 0.75 * (1.0 + 2.0 * rec.cosim + cosisq);\n                f221 = 1.5 * sini2;\n                f321 = 1.875 * rec.sinim  *  (1.0 - 2.0 * rec.cosim - 3.0 * cosisq);\n                f322 = -1.875 * rec.sinim  *  (1.0 + 2.0 * rec.cosim - 3.0 * cosisq);\n                f441 = 35.0 * sini2 * f220;\n                f442 = 39.3750 * sini2 * sini2;\n                f522 = 9.84375 * rec.sinim * (sini2 * (1.0 - 2.0 * rec.cosim - 5.0 * cosisq) +\n                    0.33333333 * (-2.0 + 4.0 * rec.cosim + 6.0 * cosisq));\n                f523 = rec.sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * rec.cosim +\n                    10.0 * cosisq) + 6.56250012 * (1.0 + 2.0 * rec.cosim - 3.0 * cosisq));\n                f542 = 29.53125 * rec.sinim * (2.0 - 8.0 * rec.cosim + cosisq *\n                    (-12.0 + 8.0 * rec.cosim + 10.0 * cosisq));\n                f543 = 29.53125 * rec.sinim * (-2.0 - 8.0 * rec.cosim + cosisq *\n                    (12.0 + 8.0 * rec.cosim - 10.0 * cosisq));\n                xno2 = rec.nm * rec.nm;\n                ainv2 = aonv * aonv;\n                temp1 = 3.0 * xno2 * ainv2;\n                temp = temp1 * root22;\n                rec.d2201 = temp * f220 * g201;\n                rec.d2211 = temp * f221 * g211;\n                temp1 = temp1 * aonv;\n                temp = temp1 * root32;\n                rec.d3210 = temp * f321 * g310;\n                rec.d3222 = temp * f322 * g322;\n                temp1 = temp1 * aonv;\n                temp = 2.0 * temp1 * root44;\n                rec.d4410 = temp * f441 * g410;\n                rec.d4422 = temp * f442 * g422;\n                temp1 = temp1 * aonv;\n                temp = temp1 * root52;\n                rec.d5220 = temp * f522 * g520;\n                rec.d5232 = temp * f523 * g532;\n                temp = 2.0 * temp1 * root54;\n                rec.d5421 = temp * f542 * g521;\n                rec.d5433 = temp * f543 * g533;\n                rec.xlamo = fmod(rec.mo + rec.nodeo + rec.nodeo - theta - theta, twopi);\n                rec.xfact = rec.mdot + rec.dmdt + 2.0 * (rec.nodedot + rec.dnodt - rptim) - rec.no_unkozai;\n                rec.em = emo;\n                rec.emsq = emsqo;\n            }\n\n            /* ---------------- synchronous resonance terms -------------- */\n            if(rec.irez == 1)\n            {\n                g200 = 1.0 + rec.emsq * (-2.5 + 0.8125 * rec.emsq);\n                g310 = 1.0 + 2.0 * rec.emsq;\n                g300 = 1.0 + rec.emsq * (-6.0 + 6.60937 * rec.emsq);\n                f220 = 0.75 * (1.0 + rec.cosim) * (1.0 + rec.cosim);\n                f311 = 0.9375 * rec.sinim * rec.sinim * (1.0 + 3.0 * rec.cosim) - 0.75 * (1.0 + rec.cosim);\n                f330 = 1.0 + rec.cosim;\n                f330 = 1.875 * f330 * f330 * f330;\n                rec.del1 = 3.0 * rec.nm * rec.nm * aonv * aonv;\n                rec.del2 = 2.0 * rec.del1 * f220 * g200 * q22;\n                rec.del3 = 3.0 * rec.del1 * f330 * g300 * q33 * aonv;\n                rec.del1 = rec.del1 * f311 * g310 * q31 * aonv;\n                rec.xlamo = fmod(rec.mo + rec.nodeo + rec.argpo - theta, twopi);\n                rec.xfact = rec.mdot + xpidot - rptim + rec.dmdt + rec.domdt + rec.dnodt - rec.no_unkozai;\n            }\n\n            /* ------------ for sgp4, initialize the integrator ---------- */\n            rec.xli = rec.xlamo;\n            rec.xni = rec.no_unkozai;\n            rec.atime = 0.0;\n            rec.nm = rec.no_unkozai + rec.dndt;\n        }\n\n    }  // dsinit\n\n    /*-----------------------------------------------------------------------------\n    *\n    *                           procedure dspace\n    *\n    *  this procedure provides deep space contributions to mean elements for\n    *    perturbing third body.  these effects have been averaged over one\n    *    revolution of the sun and moon.  for earth resonance effects, the\n    *    effects have been averaged over no revolutions of the satellite.\n    *    (mean motion)\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 -\n    *    dedt        -\n    *    del1, del2, del3  -\n    *    didt        -\n    *    dmdt        -\n    *    dnodt       -\n    *    domdt       -\n    *    irez        - flag for resonance           0-none, 1-one day, 2-half day\n    *    argpo       - argument of perigee\n    *    argpdot     - argument of perigee dot (rate)\n    *    t           - time\n    *    tc          -\n    *    gsto        - gst\n    *    xfact       -\n    *    xlamo       -\n    *    no          - mean motion\n    *    atime       -\n    *    em          - eccentricity\n    *    ft          -\n    *    argpm       - argument of perigee\n    *    inclm       - inclination\n    *    xli         -\n    *    mm          - mean anomaly\n    *    xni         - mean motion\n    *    nodem       - right ascension of ascending node\n    *\n    *  outputs       :\n    *    atime       -\n    *    em          - eccentricity\n    *    argpm       - argument of perigee\n    *    inclm       - inclination\n    *    xli         -\n    *    mm          - mean anomaly\n    *    xni         -\n    *    nodem       - right ascension of ascending node\n    *    dndt        -\n    *    nm          - mean motion\n    *\n    *  locals        :\n    *    delt        -\n    *    ft          -\n    *    theta       -\n    *    x2li        -\n    *    x2omi       -\n    *    xl          -\n    *    xldot       -\n    *    xnddt       -\n    *    xndt        -\n    *    xomi        -\n    *\n    *  coupling      :\n    *    none        -\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    void dspace(double tc, ElsetRec &rec)\n    {\n        int iretn;\n        double delt, ft, theta, x2li, x2omi, xl, xldot, xnddt, xndt, xomi, g22, g32,\n            g44, g52, g54, fasx2, fasx4, fasx6, rptim, step2, stepn, stepp;\n\n        xndt = 0;\n        xnddt = 0;\n        xldot = 0;\n\n        fasx2 = 0.13130908;\n        fasx4 = 2.8843198;\n        fasx6 = 0.37448087;\n        g22 = 5.7686396;\n        g32 = 0.95240898;\n        g44 = 1.8014998;\n        g52 = 1.0508330;\n        g54 = 4.4108898;\n        rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec\n        stepp = 720.0;\n        stepn = -720.0;\n        step2 = 259200.0;\n\n        /* ----------- calculate deep space resonance effects ----------- */\n        rec.dndt = 0.0;\n        theta = fmod(rec.gsto + tc * rptim, twopi);\n        rec.em = rec.em + rec.dedt * rec.t;\n\n        rec.inclm = rec.inclm + rec.didt * rec.t;\n        rec.argpm = rec.argpm + rec.domdt * rec.t;\n        rec.nodem = rec.nodem + rec.dnodt * rec.t;\n        rec.mm = rec.mm + rec.dmdt * rec.t;\n\n        //   sgp4fix for negative inclinations\n        //   the following if statement should be commented out\n        //  if(inclm < 0.0)\n        // {\n        //    inclm = -inclm;\n        //    argpm = argpm - pi;\n        //    nodem = nodem + pi;\n        //  }\n\n        /* - update resonances : numerical (euler-maclaurin) integration - */\n        /* ------------------------- epoch restart ----------------------  */\n        //   sgp4fix for propagator problems\n        //   the following integration works for negative time steps and periods\n        //   the specific changes are unknown because the original code was so convoluted\n\n        // sgp4fix take out atime = 0.0 and fix for faster operation\n        ft = 0.0;\n        if(rec.irez != 0)\n        {\n            // sgp4fix streamline check\n            if((rec.atime == 0.0) || (rec.t * rec.atime <= 0.0) || (fabs(rec.t) < fabs(rec.atime)))\n            {\n                rec.atime = 0.0;\n                rec.xni = rec.no_unkozai;\n                rec.xli = rec.xlamo;\n            }\n            // sgp4fix move check outside loop\n            if(rec.t > 0.0)\n                delt = stepp;\n            else\n                delt = stepn;\n\n            iretn = 381; // added for do loop\n            while(iretn == 381)\n            {\n                /* ------------------- dot terms calculated ------------- */\n                /* ----------- near - synchronous resonance terms ------- */\n                if(rec.irez != 2)\n                {\n                    xndt = rec.del1 * sin(rec.xli - fasx2) + rec.del2 * sin(2.0 * (rec.xli - fasx4)) +\n                            rec.del3 * sin(3.0 * (rec.xli - fasx6));\n                    xldot = rec.xni + rec.xfact;\n                    xnddt = rec.del1 * cos(rec.xli - fasx2) +\n                        2.0 * rec.del2 * cos(2.0 * (rec.xli - fasx4)) +\n                        3.0 * rec.del3 * cos(3.0 * (rec.xli - fasx6));\n                    xnddt = xnddt * xldot;\n                }\n                else\n                {\n                    /* --------- near - half-day resonance terms -------- */\n                    xomi = rec.argpo + rec.argpdot * rec.atime;\n                    x2omi = xomi + xomi;\n                    x2li = rec.xli + rec.xli;\n                    xndt = rec.d2201 * sin(x2omi + rec.xli - g22) + rec.d2211 * sin(rec.xli - g22) +\n                            rec.d3210 * sin(xomi + rec.xli - g32) + rec.d3222 * sin(-xomi + rec.xli - g32) +\n                            rec.d4410 * sin(x2omi + x2li - g44) + rec.d4422 * sin(x2li - g44) +\n                            rec.d5220 * sin(xomi + rec.xli - g52) + rec.d5232 * sin(-xomi + rec.xli - g52) +\n                            rec.d5421 * sin(xomi + x2li - g54) + rec.d5433 * sin(-xomi + x2li - g54);\n                    xldot = rec.xni + rec.xfact;\n                    xnddt = rec.d2201 * cos(x2omi + rec.xli - g22) + rec.d2211 * cos(rec.xli - g22) +\n                            rec.d3210 * cos(xomi + rec.xli - g32) + rec.d3222 * cos(-xomi + rec.xli - g32) +\n                            rec.d5220 * cos(xomi + rec.xli - g52) + rec.d5232 * cos(-xomi + rec.xli - g52) +\n                        2.0 * (rec.d4410 * cos(x2omi + x2li - g44) +\n                                rec.d4422 * cos(x2li - g44) + rec.d5421 * cos(xomi + x2li - g54) +\n                                rec.d5433 * cos(-xomi + x2li - g54));\n                    xnddt = xnddt * xldot;\n                }\n\n                /* ----------------------- integrator ------------------- */\n                // sgp4fix move end checks to end of routine\n                if(fabs(rec.t - rec.atime) >= stepp)\n                {\n                    iretn = 381;\n                }\n                else // exit here\n                {\n                    ft = rec.t - rec.atime;\n                    iretn = 0;\n                }\n\n                if(iretn == 381)\n                {\n                    rec.xli = rec.xli + xldot * delt + xndt * step2;\n                    rec.xni = rec.xni + xndt * delt + xnddt * step2;\n                    rec.atime = rec.atime + delt;\n                }\n            }  // while iretn = 381\n\n\n            rec.nm = rec.xni + xndt * ft + xnddt * ft * ft * 0.5;\n            xl = rec.xli + xldot * ft + xndt * ft * ft * 0.5;\n            if(rec.irez != 1)\n            {\n                rec.mm = xl - 2.0 * rec.nodem + 2.0 * theta;\n                rec.dndt = rec.nm - rec.no_unkozai;\n            }\n            else\n            {\n                rec.mm = xl - rec.nodem - rec.argpm + theta;\n                rec.dndt = rec.nm - rec.no_unkozai;\n            }\n            rec.nm = rec.no_unkozai + rec.dndt;\n        }\n\n    }  // dsspace\n\n    /*-----------------------------------------------------------------------------\n    *\n    *                           procedure initl\n    *\n    *  this procedure initializes the spg4 propagator. all the initialization is\n    *    consolidated here instead of having multiple loops inside other routines.\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    satn        - satellite number - not needed, placed in rec\n    *    xke         - reciprocal of tumin\n    *    j2          - j2 zonal harmonic\n    *    ecco        - eccentricity                           0.0 - 1.0\n    *    epoch       - epoch time in days from jan 0, 1950. 0 hr\n    *    inclo       - inclination of satellite\n    *    no          - mean motion of satellite\n    *\n    *  outputs       :\n    *    ainv        - 1.0 / a\n    *    ao          - semi major axis\n    *    con41       -\n    *    con42       - 1.0 - 5.0 cos(i)\n    *    cosio       - cosine of inclination\n    *    cosio2      - cosio squared\n    *    eccsq       - eccentricity squared\n    *    method      - flag for deep space                    'd', 'n'\n    *    omeosq      - 1.0 - ecco * ecco\n    *    posq        - semi-parameter squared\n    *    rp          - radius of perigee\n    *    rteosq      - square root of (1.0 - ecco*ecco)\n    *    sinio       - sine of inclination\n    *    gsto        - gst at time of observation               rad\n    *    no          - mean motion of satellite\n    *\n    *  locals        :\n    *    ak          -\n    *    d1          -\n    *    del         -\n    *    adel        -\n    *    po          -\n    *\n    *  coupling      :\n    *    getgravconst- no longer used\n    *    gstime      - find greenwich sidereal time from the julian date\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    void initl(double epoch, ElsetRec &rec)\n    {\n        /* --------------------- local variables ------------------------ */\n        double ak, d1, del, adel, po, x2o3;\n\n        // sgp4fix use old way of finding gst\n        double ds70;\n        double ts70, tfrac, c1, thgr70, fk5r, c1p2p;\n\n        /* ----------------------- earth constants ---------------------- */\n        // sgp4fix identify constants and allow alternate values\n        // only xke and j2 are used here so pass them in directly\n        // getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );\n        x2o3 = 2.0 / 3.0;\n\n        /* ------------- calculate auxillary epoch quantities ---------- */\n        rec.eccsq = rec.ecco * rec.ecco;\n        rec.omeosq = 1.0 - rec.eccsq;\n        rec.rteosq = sqrt(rec.omeosq);\n        rec.cosio = cos(rec.inclo);\n        rec.cosio2 = rec.cosio * rec.cosio;\n\n        /* ------------------ un-kozai the mean motion ----------------- */\n        ak = pow(rec.xke / rec.no_kozai, x2o3);\n        d1 = 0.75 * rec.j2 * (3.0 * rec.cosio2 - 1.0) / (rec.rteosq * rec.omeosq);\n        del = d1 / (ak * ak);\n        adel = ak * (1.0 - del * del - del *\n            (1.0 / 3.0 + 134.0 * del * del / 81.0));\n        del = d1 / (adel * adel);\n        rec.no_unkozai = rec.no_kozai / (1.0 + del);\n\n        rec.ao = pow(rec.xke / (rec.no_unkozai), x2o3);\n        rec.sinio = sin(rec.inclo);\n        po = rec.ao * rec.omeosq;\n        rec.con42 = 1.0 - 5.0 * rec.cosio2;\n        rec.con41 = -rec.con42 - rec.cosio2 - rec.cosio2;\n        rec.ainv = 1.0 / rec.ao;\n        rec.posq = po * po;\n        rec.rp = rec.ao * (1.0 - rec.ecco);\n        rec.method = 'n';\n\n        // sgp4fix modern approach to finding sidereal time\n        //   if(opsmode == 'a')\n        //      {\n        // sgp4fix use old way of finding gst\n        // count integer number of days from 0 jan 1970\n        ts70 = epoch - 7305.0;\n        ds70 = floor(ts70 + 1.0e-8);\n        tfrac = ts70 - ds70;\n        // find greenwich location at epoch\n        c1 = 1.72027916940703639e-2;\n        thgr70 = 1.7321343856509374;\n        fk5r = 5.07551419432269442e-15;\n        c1p2p = c1 + twopi;\n        double gsto1 = fmod(thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi);\n        if(gsto1 < 0.0)\n            gsto1 = gsto1 + twopi;\n        //    }\n        //    else\n        rec.gsto = gstime(epoch + 2433281.5);\n\n    }  // initl\n\n    /*-----------------------------------------------------------------------------\n    *\n    *                             procedure sgp4init\n    *\n    *  this procedure initializes variables for sgp4.\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    opsmode     - mode of operation afspc or improved 'a', 'i'\n    *    whichconst  - which set of constants to use  72, 84\n    *    satn        - satellite number\n    *    bstar       - sgp4 type drag coefficient              kg/m2er\n    *    ecco        - eccentricity\n    *    epoch       - epoch time in days from jan 0, 1950. 0 hr\n    *    argpo       - argument of perigee (output if ds)\n    *    inclo       - inclination\n    *    mo          - mean anomaly (output if ds)\n    *    no          - mean motion\n    *    nodeo       - right ascension of ascending node\n    *\n    *  outputs       :\n    *    rec      - common values for subsequent calls\n    *    return code - non-zero on error.\n    *                   1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er\n    *                   2 - mean motion less than 0.0\n    *                   3 - pert elements, ecc < 0.0  or  ecc > 1.0\n    *                   4 - semi-latus rectum < 0.0\n    *                   5 - epoch elements are sub-orbital\n    *                   6 - satellite has decayed\n    *\n    *  locals        :\n    *    cnodm  , snodm  , cosim  , sinim  , cosomm , sinomm\n    *    cc1sq  , cc2    , cc3\n    *    coef   , coef1\n    *    cosio4      -\n    *    day         -\n    *    dndt        -\n    *    em          - eccentricity\n    *    emsq        - eccentricity squared\n    *    eeta        -\n    *    etasq       -\n    *    gam         -\n    *    argpm       - argument of perigee\n    *    nodem       -\n    *    inclm       - inclination\n    *    mm          - mean anomaly\n    *    nm          - mean motion\n    *    perige      - perigee\n    *    pinvsq      -\n    *    psisq       -\n    *    qzms24      -\n    *    rtemsq      -\n    *    s1, s2, s3, s4, s5, s6, s7          -\n    *    sfour       -\n    *    ss1, ss2, ss3, ss4, ss5, ss6, ss7         -\n    *    sz1, sz2, sz3\n    *    sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33        -\n    *    tc          -\n    *    temp        -\n    *    temp1, temp2, temp3       -\n    *    tsi         -\n    *    xpidot      -\n    *    xhdot1      -\n    *    z1, z2, z3          -\n    *    z11, z12, z13, z21, z22, z23, z31, z32, z33         -\n    *\n    *  coupling      :\n    *    getgravconst-\n    *    initl       -\n    *    dscom       -\n    *    dpper       -\n    *    dsinit      -\n    *    sgp4        -\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    bool sgp4init(char opsmode, ElsetRec &rec)\n    {\n        /* --------------------- local variables ------------------------ */\n\n        double cc1sq,\n            cc2, cc3, coef, coef1, cosio4,\n            eeta, etasq, perige, pinvsq, psisq, qzms24,\n            sfour,tc, temp, temp1, temp2, temp3, tsi, xpidot,\n            xhdot1,qzms2t, ss, x2o3, r[3], v[3],\n            delmotemp, qzms2ttemp, qzms24temp;\n\n\n        double epoch = (rec.jdsatepoch - 2433281.5) + rec.jdsatepochF;\n\n        /* ------------------------ initialization --------------------- */\n        // sgp4fix divisor for divide by zero check on inclination\n        // the old check used 1.0 + cos(pi-1.0e-9), but then compared it to\n        // 1.5 e-12, so the threshold was changed to 1.5e-12 for consistency\n        const double temp4 = 1.5e-12;\n\n        /* ----------- set all near earth variables to zero ------------ */\n        rec.isimp = 0;   rec.method = 'n'; rec.aycof = 0.0;\n        rec.con41 = 0.0; rec.cc1 = 0.0; rec.cc4 = 0.0;\n        rec.cc5 = 0.0; rec.d2 = 0.0; rec.d3 = 0.0;\n        rec.d4 = 0.0; rec.delmo = 0.0; rec.eta = 0.0;\n        rec.argpdot = 0.0; rec.omgcof = 0.0; rec.sinmao = 0.0;\n        rec.t = 0.0; rec.t2cof = 0.0; rec.t3cof = 0.0;\n        rec.t4cof = 0.0; rec.t5cof = 0.0; rec.x1mth2 = 0.0;\n        rec.x7thm1 = 0.0; rec.mdot = 0.0; rec.nodedot = 0.0;\n        rec.xlcof = 0.0; rec.xmcof = 0.0; rec.nodecf = 0.0;\n\n        /* ----------- set all deep space variables to zero ------------ */\n        rec.irez = 0;   rec.d2201 = 0.0; rec.d2211 = 0.0;\n        rec.d3210 = 0.0; rec.d3222 = 0.0; rec.d4410 = 0.0;\n        rec.d4422 = 0.0; rec.d5220 = 0.0; rec.d5232 = 0.0;\n        rec.d5421 = 0.0; rec.d5433 = 0.0; rec.dedt = 0.0;\n        rec.del1 = 0.0; rec.del2 = 0.0; rec.del3 = 0.0;\n        rec.didt = 0.0; rec.dmdt = 0.0; rec.dnodt = 0.0;\n        rec.domdt = 0.0; rec.e3 = 0.0; rec.ee2 = 0.0;\n        rec.peo = 0.0; rec.pgho = 0.0; rec.pho = 0.0;\n        rec.pinco = 0.0; rec.plo = 0.0; rec.se2 = 0.0;\n        rec.se3 = 0.0; rec.sgh2 = 0.0; rec.sgh3 = 0.0;\n        rec.sgh4 = 0.0; rec.sh2 = 0.0; rec.sh3 = 0.0;\n        rec.si2 = 0.0; rec.si3 = 0.0; rec.sl2 = 0.0;\n        rec.sl3 = 0.0; rec.sl4 = 0.0; rec.gsto = 0.0;\n        rec.xfact = 0.0; rec.xgh2 = 0.0; rec.xgh3 = 0.0;\n        rec.xgh4 = 0.0; rec.xh2 = 0.0; rec.xh3 = 0.0;\n        rec.xi2 = 0.0; rec.xi3 = 0.0; rec.xl2 = 0.0;\n        rec.xl3 = 0.0; rec.xl4 = 0.0; rec.xlamo = 0.0;\n        rec.zmol = 0.0; rec.zmos = 0.0; rec.atime = 0.0;\n        rec.xli = 0.0; rec.xni = 0.0;\n\n        /* ------------------------ earth constants ----------------------- */\n        // sgp4fix identify constants and allow alternate values\n        // this is now the only call for the constants\n        getgravconst(rec.whichconst, rec);\n\n        //-------------------------------------------------------------------------\n\n        rec.error = 0;\n        rec.operationmode = opsmode;\n\n\n        // single averaged mean elements\n        rec.am = rec.em = rec.im = rec.Om = rec.mm = rec.nm = 0.0;\n\n        /* ------------------------ earth constants ----------------------- */\n        // sgp4fix identify constants and allow alternate values no longer needed\n        // getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );\n        ss = 78.0 / rec.radiusearthkm + 1.0;\n        // sgp4fix use multiply for speed instead of pow\n        qzms2ttemp = (120.0 - 78.0) / rec.radiusearthkm;\n        qzms2t = qzms2ttemp * qzms2ttemp * qzms2ttemp * qzms2ttemp;\n        x2o3 = 2.0 / 3.0;\n\n        rec.init = 'y';\n        rec.t = 0.0;\n\n        // sgp4fix remove satn as it is not needed in initl\n\n        initl(epoch,rec);\n\n        rec.a = pow(rec.no_unkozai * rec.tumin, (-2.0 / 3.0));\n        rec.alta = rec.a * (1.0 + rec.ecco) - 1.0;\n        rec.altp = rec.a * (1.0 - rec.ecco) - 1.0;\n        rec.error = 0;\n\n        // sgp4fix remove this check as it is unnecessary\n        // the mrt check in sgp4 handles decaying satellite cases even if the starting\n        // condition is below the surface of te earth\n        //     if(rp < 1.0)\n        //       {\n        //         rec.error = 5;\n        //       }\n\n        if((rec.omeosq >= 0.0) || (rec.no_unkozai >= 0.0))\n        {\n            rec.isimp = 0;\n            if(rec.rp < (220.0 / rec.radiusearthkm + 1.0))\n                rec.isimp = 1;\n            sfour = ss;\n            qzms24 = qzms2t;\n            perige = (rec.rp - 1.0) * rec.radiusearthkm;\n\n            /* - for perigees below 156 km, s and qoms2t are altered - */\n            if(perige < 156.0)\n            {\n                sfour = perige - 78.0;\n                if(perige < 98.0)\n                    sfour = 20.0;\n                // sgp4fix use multiply for speed instead of pow\n                qzms24temp = (120.0 - sfour) / rec.radiusearthkm;\n                qzms24 = qzms24temp * qzms24temp * qzms24temp * qzms24temp;\n                sfour = sfour / rec.radiusearthkm + 1.0;\n            }\n            pinvsq = 1.0 / rec.posq;\n\n            tsi = 1.0 / (rec.ao - sfour);\n            rec.eta = rec.ao * rec.ecco * tsi;\n            etasq = rec.eta * rec.eta;\n            eeta = rec.ecco * rec.eta;\n            psisq = fabs(1.0 - etasq);\n            coef = qzms24 * pow(tsi, 4.0);\n            coef1 = coef / pow(psisq, 3.5);\n            cc2 = coef1 * rec.no_unkozai * (rec.ao * (1.0 + 1.5 * etasq + eeta *\n                (4.0 + etasq)) + 0.375 * rec.j2 * tsi / psisq * rec.con41 *\n                (8.0 + 3.0 * etasq * (8.0 + etasq)));\n            rec.cc1 = rec.bstar * cc2;\n            cc3 = 0.0;\n            if(rec.ecco > 1.0e-4)\n                cc3 = -2.0 * coef * tsi * rec.j3oj2 * rec.no_unkozai * rec.sinio / rec.ecco;\n            rec.x1mth2 = 1.0 - rec.cosio2;\n            rec.cc4 = 2.0* rec.no_unkozai * coef1 * rec.ao * rec.omeosq *\n                (rec.eta * (2.0 + 0.5 * etasq) + rec.ecco *\n                (0.5 + 2.0 * etasq) - rec.j2 * tsi / (rec.ao * psisq) *\n                (-3.0 * rec.con41 * (1.0 - 2.0 * eeta + etasq *\n                (1.5 - 0.5 * eeta)) + 0.75 * rec.x1mth2 *\n                (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * rec.argpo)));\n            rec.cc5 = 2.0 * coef1 * rec.ao * rec.omeosq * (1.0 + 2.75 *\n                (etasq + eeta) + eeta * etasq);\n            cosio4 = rec.cosio2 * rec.cosio2;\n            temp1 = 1.5 * rec.j2 * pinvsq * rec.no_unkozai;\n            temp2 = 0.5 * temp1 * rec.j2 * pinvsq;\n            temp3 = -0.46875 * rec.j4 * pinvsq * pinvsq * rec.no_unkozai;\n            rec.mdot = rec.no_unkozai + 0.5 * temp1 * rec.rteosq * rec.con41 + 0.0625 *\n                temp2 * rec.rteosq * (13.0 - 78.0 * rec.cosio2 + 137.0 * cosio4);\n            rec.argpdot = -0.5 * temp1 * rec.con42 + 0.0625 * temp2 *\n                (7.0 - 114.0 * rec.cosio2 + 395.0 * cosio4) +\n                temp3 * (3.0 - 36.0 * rec.cosio2 + 49.0 * cosio4);\n            xhdot1 = -temp1 * rec.cosio;\n            rec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * rec.cosio2) +\n                2.0 * temp3 * (3.0 - 7.0 * rec.cosio2)) * rec.cosio;\n            xpidot = rec.argpdot + rec.nodedot;\n            rec.omgcof = rec.bstar * cc3 * cos(rec.argpo);\n            rec.xmcof = 0.0;\n            if(rec.ecco > 1.0e-4)\n                rec.xmcof = -x2o3 * coef * rec.bstar / eeta;\n            rec.nodecf = 3.5 * rec.omeosq * xhdot1 * rec.cc1;\n            rec.t2cof = 1.5 * rec.cc1;\n            // sgp4fix for divide by zero with xinco = 180 deg\n            if(fabs(rec.cosio + 1.0) > 1.5e-12)\n                rec.xlcof = -0.25 * rec.j3oj2 * rec.sinio * (3.0 + 5.0 * rec.cosio) / (1.0 + rec.cosio);\n            else\n                rec.xlcof = -0.25 * rec.j3oj2 * rec.sinio * (3.0 + 5.0 * rec.cosio) / temp4;\n            rec.aycof = -0.5 * rec.j3oj2 * rec.sinio;\n            // sgp4fix use multiply for speed instead of pow\n            delmotemp = 1.0 + rec.eta * cos(rec.mo);\n            rec.delmo = delmotemp * delmotemp * delmotemp;\n            rec.sinmao = sin(rec.mo);\n            rec.x7thm1 = 7.0 * rec.cosio2 - 1.0;\n\n            /* --------------- deep space initialization ------------- */\n            if((2 * pi / rec.no_unkozai) >= 225.0)\n            {\n                rec.method = 'd';\n                rec.isimp = 1;\n                tc = 0.0;\n                rec.inclm = rec.inclo;\n\n                dscom(epoch, rec.ecco, rec.argpo, tc, rec.inclo, rec.nodeo, rec.no_unkozai,rec);\n\n\n                rec.ep=rec.ecco;\n                rec.inclp=rec.inclo;\n                rec.nodep=rec.nodeo;\n                rec.argpp=rec.argpo;\n                rec.mp=rec.mo;\n\n\n                dpper(rec.e3, rec.ee2, rec.peo, rec.pgho,\n                    rec.pho, rec.pinco, rec.plo, rec.se2,\n                    rec.se3, rec.sgh2, rec.sgh3, rec.sgh4,\n                    rec.sh2, rec.sh3, rec.si2, rec.si3,\n                    rec.sl2, rec.sl3, rec.sl4, rec.t,\n                    rec.xgh2, rec.xgh3, rec.xgh4, rec.xh2,\n                    rec.xh3, rec.xi2, rec.xi3, rec.xl2,\n                    rec.xl3, rec.xl4, rec.zmol, rec.zmos, rec.init,rec,\n                    rec.operationmode);\n\n\n                rec.ecco=rec.ep;\n                rec.inclo=rec.inclp;\n                rec.nodeo=rec.nodep;\n                rec.argpo=rec.argpp;\n                rec.mo=rec.mp;\n\n\n                rec.argpm = 0.0;\n                rec.nodem = 0.0;\n                rec.mm = 0.0;\n\n                dsinit(tc, xpidot, rec);\n            }\n\n            /* ----------- set variables if not deep space ----------- */\n            if(rec.isimp != 1)\n            {\n                cc1sq = rec.cc1 * rec.cc1;\n                rec.d2 = 4.0 * rec.ao * tsi * cc1sq;\n                temp = rec.d2 * tsi * rec.cc1 / 3.0;\n                rec.d3 = (17.0 * rec.ao + sfour) * temp;\n                rec.d4 = 0.5 * temp * rec.ao * tsi * (221.0 * rec.ao + 31.0 * sfour) * rec.cc1;\n                rec.t3cof = rec.d2 + 2.0 * cc1sq;\n                rec.t4cof = 0.25 * (3.0 * rec.d3 + rec.cc1 *\n                    (12.0 * rec.d2 + 10.0 * cc1sq));\n                rec.t5cof = 0.2 * (3.0 * rec.d4 +\n                    12.0 * rec.cc1 * rec.d3 +\n                    6.0 * rec.d2 * rec.d2 +\n                    15.0 * cc1sq * (2.0 * rec.d2 + cc1sq));\n            }\n        } // if omeosq = 0 ...\n\n        /* finally propogate to zero epoch to initialize all others. */\n        // sgp4fix take out check to let satellites process until they are actually below earth surface\n        //       if(rec.error == 0)\n\n\n        sgp4(rec, 0.0, r, v);\n\n        rec.init = 'n';\n\n        //sgp4fix return boolean. rec.error contains any error codes\n        return TRUE;\n    }  // sgp4init\n\n    /*-----------------------------------------------------------------------------\n    *\n    *                             procedure sgp4\n    *\n    *  this procedure is the sgp4 prediction model from space command. this is an\n    *    updated and combined version of sgp4 and sdp4, which were originally\n    *    published separately in spacetrack report #3. this version follows the\n    *    methodology from the aiaa paper (2006) describing the history and\n    *    development of the code.\n    *\n    *  author        : david vallado                  719-573-2600   28 jun 2005\n    *\n    *  inputs        :\n    *    rec     - initialised structure from sgp4init() call.\n    *    tsince     - time since epoch (minutes)\n    *\n    *  outputs       :\n    *    r           - position vector                     km\n    *    v           - velocity                            km/sec\n    *  return code - non-zero on error.\n    *                   1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er\n    *                   2 - mean motion less than 0.0\n    *                   3 - pert elements, ecc < 0.0  or  ecc > 1.0\n    *                   4 - semi-latus rectum < 0.0\n    *                   5 - epoch elements are sub-orbital\n    *                   6 - satellite has decayed\n    *\n    *  locals        :\n    *    am          -\n    *    axnl, aynl        -\n    *    betal       -\n    *    cosim   , sinim   , cosomm  , sinomm  , cnod    , snod    , cos2u   ,\n    *    sin2u   , coseo1  , sineo1  , cosi    , sini    , cosip   , sinip   ,\n    *    cosisq  , cossu   , sinsu   , cosu    , sinu\n    *    delm        -\n    *    delomg      -\n    *    dndt        -\n    *    eccm        -\n    *    emsq        -\n    *    ecose       -\n    *    el2         -\n    *    eo1         -\n    *    eccp        -\n    *    esine       -\n    *    argpm       -\n    *    argpp       -\n    *    omgadf      -c\n    *    pl          -\n    *    r           -\n    *    rtemsq      -\n    *    rdotl       -\n    *    rl          -\n    *    rvdot       -\n    *    rvdotl      -\n    *    su          -\n    *    t2  , t3   , t4    , tc\n    *    tem5, temp , temp1 , temp2  , tempa  , tempe  , templ\n    *    u   , ux   , uy    , uz     , vx     , vy     , vz\n    *    inclm       - inclination\n    *    mm          - mean anomaly\n    *    nm          - mean motion\n    *    nodem       - right asc of ascending node\n    *    xinc        -\n    *    xincp       -\n    *    xl          -\n    *    xlm         -\n    *    mp          -\n    *    xmdf        -\n    *    xmx         -\n    *    xmy         -\n    *    nodedf      -\n    *    xnode       -\n    *    nodep       -\n    *    np          -\n    *\n    *  coupling      :\n    *    getgravconst- no longer used. Variables are conatined within rec\n    *    dpper\n    *    dpspace\n    *\n    *  references    :\n    *    hoots, roehrich, norad spacetrack report #3 1980\n    *    hoots, norad spacetrack report #6 1986\n    *    hoots, schumacher and glover 2004\n    *    vallado, crawford, hujsak, kelso  2006\n    ----------------------------------------------------------------------------*/\n\n    bool sgp4(ElsetRec &rec, double tsince, double r[3], double v[3])\n    {\n\n        double axnl, aynl, betal, cnod,\n            cos2u, coseo1, cosi, cosip, cosisq, cossu, cosu,\n            delm, delomg, ecose, el2, eo1,\n            esine, argpdf, pl, mrt = 0.0,\n            mvt, rdotl, rl, rvdot, rvdotl,\n            sin2u, sineo1, sini, sinip, sinsu, sinu,\n            snod, su, t2, t3, t4, tem5, temp,\n            temp1, temp2, tempa, tempe, templ, u, ux,\n            uy, uz, vx, vy, vz,\n            xinc, xincp, xl, xlm,\n            xmdf, xmx, xmy, nodedf, xnode, tc,\n            x2o3, vkmpersec, delmtemp;\n\n        int ktr;\n\n        /* ------------------ set mathematical constants --------------- */\n        // sgp4fix divisor for divide by zero check on inclination\n        // the old check used 1.0 + cos(pi-1.0e-9), but then compared it to\n        // 1.5 e-12, so the threshold was changed to 1.5e-12 for consistency\n        const double temp4 = 1.5e-12;\n        x2o3 = 2.0 / 3.0;\n        // sgp4fix identify constants and allow alternate values\n        // getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );\n        vkmpersec = rec.radiusearthkm * rec.xke / 60.0;\n\n        /* --------------------- clear sgp4 error flag ----------------- */\n        rec.t = tsince;\n        rec.error = 0;\n\n        /* ------- update for secular gravity and atmospheric drag ----- */\n        xmdf = rec.mo + rec.mdot * rec.t;\n        argpdf = rec.argpo + rec.argpdot * rec.t;\n        nodedf = rec.nodeo + rec.nodedot * rec.t;\n        rec.argpm = argpdf;\n        rec.mm = xmdf;\n        t2 = rec.t * rec.t;\n        rec.nodem = nodedf + rec.nodecf * t2;\n        tempa = 1.0 - rec.cc1 * rec.t;\n        tempe = rec.bstar * rec.cc4 * rec.t;\n        templ = rec.t2cof * t2;\n\n        delomg = 0;\n        delmtemp = 0;\n        delm = 0;\n        temp = 0;\n        t3 = 0;\n        t4 = 0;\n        mrt = 0;\n\n        if(rec.isimp != 1)\n        {\n            delomg = rec.omgcof * rec.t;\n            // sgp4fix use mutliply for speed instead of pow\n            delmtemp = 1.0 + rec.eta * cos(xmdf);\n            delm = rec.xmcof *\n                (delmtemp * delmtemp * delmtemp -\n                rec.delmo);\n            temp = delomg + delm;\n            rec.mm = xmdf + temp;\n            rec.argpm = argpdf - temp;\n            t3 = t2 * rec.t;\n            t4 = t3 * rec.t;\n            tempa = tempa - rec.d2 * t2 - rec.d3 * t3 -\n                rec.d4 * t4;\n            tempe = tempe + rec.bstar * rec.cc5 * (sin(rec.mm) -rec.sinmao);\n            templ = templ + rec.t3cof * t3 + t4 * (rec.t4cof + rec.t * rec.t5cof);\n        }\n\n\n        tc = 0;\n        rec.nm = rec.no_unkozai;\n        rec.em = rec.ecco;\n        rec.inclm = rec.inclo;\n        if(rec.method == 'd')\n        {\n            tc = rec.t;\n            dspace(tc,rec);\n        } // if method = d\n\n        if(rec.nm <= 0.0)\n        {\n            rec.error = 2;\n            // sgp4fix add return\n            return FALSE;\n        }\n\n        rec.am = pow((rec.xke / rec.nm), x2o3) * tempa * tempa;\n        rec.nm = rec.xke / pow(rec.am, 1.5);\n        rec.em = rec.em - tempe;\n\n        // fix tolerance for error recognition\n        // sgp4fix am is fixed from the previous nm check\n        if((rec.em >= 1.0) || (rec.em < -0.001)/* || (am < 0.95)*/)\n        {\n            rec.error = 1;\n            // sgp4fix to return if there is an error in eccentricity\n            return FALSE;\n        }\n        // sgp4fix fix tolerance to avoid a divide by zero\n        if(rec.em < 1.0e-6)\n            rec.em = 1.0e-6;\n        rec.mm = rec.mm + rec.no_unkozai * templ;\n        xlm = rec.mm + rec.argpm + rec.nodem;\n        rec.emsq = rec.em * rec.em;\n        temp = 1.0 - rec.emsq;\n\n        rec.nodem = fmod(rec.nodem, twopi);\n        rec.argpm = fmod(rec.argpm, twopi);\n        xlm = fmod(xlm, twopi);\n        rec.mm = fmod(xlm - rec.argpm - rec.nodem, twopi);\n\n        // sgp4fix recover singly averaged mean elements\n        rec.am = rec.am;\n        rec.em = rec.em;\n        rec.im = rec.inclm;\n        rec.Om = rec.nodem;\n        rec.om = rec.argpm;\n        rec.mm = rec.mm;\n        rec.nm = rec.nm;\n\n        /* ----------------- compute extra mean quantities ------------- */\n        rec.sinim = sin(rec.inclm);\n        rec.cosim = cos(rec.inclm);\n\n        /* -------------------- add lunar-solar periodics -------------- */\n        rec.ep = rec.em;\n        xincp = rec.inclm;\n        rec.inclp = rec.inclm;\n        rec.argpp = rec.argpm;\n        rec.nodep = rec.nodem;\n        rec.mp = rec.mm;\n        sinip = rec.sinim;\n        cosip = rec.cosim;\n        if(rec.method == 'd')\n        {\n            dpper(rec.e3, rec.ee2, rec.peo, rec.pgho,\n                    rec.pho, rec.pinco, rec.plo, rec.se2,\n                    rec.se3, rec.sgh2, rec.sgh3, rec.sgh4,\n                    rec.sh2, rec.sh3, rec.si2, rec.si3,\n                    rec.sl2, rec.sl3, rec.sl4, rec.t,\n                    rec.xgh2, rec.xgh3, rec.xgh4, rec.xh2,\n                    rec.xh3, rec.xi2, rec.xi3, rec.xl2,\n                    rec.xl3, rec.xl4, rec.zmol, rec.zmos,\n                    'n', rec, rec.operationmode);\n\n            xincp = rec.inclp;\n            if(xincp < 0.0)\n            {\n                xincp = -xincp;\n                rec.nodep = rec.nodep + pi;\n                rec.argpp = rec.argpp - pi;\n            }\n            if((rec.ep < 0.0) || (rec.ep > 1.0))\n            {\n                rec.error = 3;\n                // sgp4fix add return\n                return FALSE;\n            }\n        } // if method = d\n\n        /* -------------------- long period periodics ------------------ */\n        if(rec.method == 'd')\n        {\n            sinip = sin(xincp);\n            cosip = cos(xincp);\n            rec.aycof = -0.5*rec.j3oj2*sinip;\n            // sgp4fix for divide by zero for xincp = 180 deg\n            if(fabs(cosip + 1.0) > 1.5e-12)\n                rec.xlcof = -0.25 * rec.j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip);\n            else\n                rec.xlcof = -0.25 * rec.j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4;\n        }\n        axnl = rec.ep * cos(rec.argpp);\n        temp = 1.0 / (rec.am * (1.0 - rec.ep * rec.ep));\n        aynl = rec.ep* sin(rec.argpp) + temp * rec.aycof;\n        xl = rec.mp + rec.argpp + rec.nodep + temp * rec.xlcof * axnl;\n\n        /* --------------------- solve kepler's equation --------------- */\n        u = fmod(xl - rec.nodep, twopi);\n        eo1 = u;\n        tem5 = 9999.9;\n        ktr = 1;\n        sineo1 = 0;\n        coseo1 = 0;\n        //   sgp4fix for kepler iteration\n        //   the following iteration needs better limits on corrections\n        while((fabs(tem5) >= 1.0e-12) && (ktr <= 10))\n        {\n            sineo1 = sin(eo1);\n            coseo1 = cos(eo1);\n            tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl;\n            tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5;\n            if(fabs(tem5) >= 0.95)\n                tem5 = tem5 > 0.0 ? 0.95 : -0.95;\n            eo1 = eo1 + tem5;\n            ktr = ktr + 1;\n        }\n\n        /* ------------- short period preliminary quantities ----------- */\n        ecose = axnl*coseo1 + aynl*sineo1;\n        esine = axnl*sineo1 - aynl*coseo1;\n        el2 = axnl*axnl + aynl*aynl;\n        pl = rec.am*(1.0 - el2);\n        if(pl < 0.0)\n        {\n            rec.error = 4;\n            // sgp4fix add return\n            return FALSE;\n        }\n        else\n        {\n            rl = rec.am * (1.0 - ecose);\n            rdotl = sqrt(rec.am) * esine / rl;\n            rvdotl = sqrt(pl) / rl;\n            betal = sqrt(1.0 - el2);\n            temp = esine / (1.0 + betal);\n            sinu = rec.am / rl * (sineo1 - aynl - axnl * temp);\n            cosu = rec.am / rl * (coseo1 - axnl + aynl * temp);\n            su = atan2(sinu, cosu);\n            sin2u = (cosu + cosu) * sinu;\n            cos2u = 1.0 - 2.0 * sinu * sinu;\n            temp = 1.0 / pl;\n            temp1 = 0.5 * rec.j2 * temp;\n            temp2 = temp1 * temp;\n\n            /* -------------- update for short period periodics ------------ */\n            if(rec.method == 'd')\n            {\n                cosisq = cosip * cosip;\n                rec.con41 = 3.0*cosisq - 1.0;\n                rec.x1mth2 = 1.0 - cosisq;\n                rec.x7thm1 = 7.0*cosisq - 1.0;\n            }\n            mrt = rl * (1.0 - 1.5 * temp2 * betal * rec.con41) +\n                0.5 * temp1 * rec.x1mth2 * cos2u;\n            su = su - 0.25 * temp2 * rec.x7thm1 * sin2u;\n            xnode = rec.nodep + 1.5 * temp2 * cosip * sin2u;\n            xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u;\n            mvt = rdotl - rec.nm * temp1 * rec.x1mth2 * sin2u / rec.xke;\n            rvdot = rvdotl + rec.nm * temp1 * (rec.x1mth2 * cos2u +\n                1.5 * rec.con41) / rec.xke;\n\n            /* --------------------- orientation vectors ------------------- */\n            sinsu = sin(su);\n            cossu = cos(su);\n            snod = sin(xnode);\n            cnod = cos(xnode);\n            sini = sin(xinc);\n            cosi = cos(xinc);\n            xmx = -snod * cosi;\n            xmy = cnod * cosi;\n            ux = xmx * sinsu + cnod * cossu;\n            uy = xmy * sinsu + snod * cossu;\n            uz = sini * sinsu;\n            vx = xmx * cossu - cnod * sinsu;\n            vy = xmy * cossu - snod * sinsu;\n            vz = sini * cossu;\n\n            /* --------- position and velocity (in km and km/sec) ---------- */\n            r[0] = (mrt * ux)* rec.radiusearthkm;\n            r[1] = (mrt * uy)* rec.radiusearthkm;\n            r[2] = (mrt * uz)* rec.radiusearthkm;\n            v[0] = (mvt * ux + rvdot * vx) * vkmpersec;\n            v[1] = (mvt * uy + rvdot * vy) * vkmpersec;\n            v[2] = (mvt * uz + rvdot * vz) * vkmpersec;\n        }  // if pl > 0\n\n        // sgp4fix for decaying satellites\n        if(mrt < 1.0)\n        {\n            rec.error = 6;\n            return FALSE;\n        }\n\n        return TRUE;\n    }  // sgp4\n\n\n\n    /* -----------------------------------------------------------------------------\n    *\n    *                           function getgravconst\n    *\n    *  this function gets constants for the propagator. note that mu is identified to\n    *    facilitiate comparisons with newer models. the common useage is wgs72.\n    *\n    *  author        : david vallado                  719-573-2600   21 jul 2006\n    *\n    *  inputs        :\n    *    whichconst  - which set of constants to use  wgs72old, wgs72, wgs84\n    *\n    *  outputs       :\n    *    tumin       - minutes in one time unit\n    *    mu          - earth gravitational parameter\n    *    radiusearthkm - radius of the earth in km\n    *    xke         - reciprocal of tumin\n    *    j2, j3, j4  - un-normalized zonal harmonic values\n    *    j3oj2       - j3 divided by j2\n    *\n    *  locals        :\n    *\n    *  coupling      :\n    *    none\n    *\n    *  references    :\n    *    norad spacetrack report #3\n    *    vallado, crawford, hujsak, kelso  2006\n    --------------------------------------------------------------------------- */\n\n    void getgravconst(int whichconst, ElsetRec &rec)\n    {\n        rec.whichconst = whichconst;\n        switch (whichconst)\n        {\n            // -- wgs-72 low precision str#3 constants --\n        case wgs72old:\n            rec.mu = 398600.79964;        // in km3 / s2\n            rec.radiusearthkm = 6378.135;     // km\n            rec.xke = 0.0743669161;        // reciprocal of tumin\n            rec.tumin = 1.0 / rec.xke;\n            rec.j2 = 0.001082616;\n            rec.j3 = -0.00000253881;\n            rec.j4 = -0.00000165597;\n            rec.j3oj2 = rec.j3 / rec.j2;\n            break;\n            // ------------ wgs-72 constants ------------\n        case wgs72:\n            rec.mu = 398600.8;            // in km3 / s2\n            rec.radiusearthkm = 6378.135;     // km\n            rec.xke = 60.0 / sqrt(rec.radiusearthkm*rec.radiusearthkm*rec.radiusearthkm / rec.mu);\n            rec.tumin = 1.0 / rec.xke;\n            rec.j2 = 0.001082616;\n            rec.j3 = -0.00000253881;\n            rec.j4 = -0.00000165597;\n            rec.j3oj2 = rec.j3 / rec.j2;\n            break;\n        default:\n        case wgs84:\n            // ------------ wgs-84 constants ------------\n            rec.mu = 398600.5;            // in km3 / s2\n            rec.radiusearthkm = 6378.137;     // km\n            rec.xke = 60.0 / sqrt(rec.radiusearthkm*rec.radiusearthkm*rec.radiusearthkm / rec.mu);\n            rec.tumin = 1.0 / rec.xke;\n            rec.j2 = 0.00108262998905;\n            rec.j3 = -0.00000253215306;\n            rec.j4 = -0.00000161098761;\n            rec.j3oj2 = rec.j3 / rec.j2;\n            break;\n        }\n\n    }   // getgravconst\n\n\n\n    /* -----------------------------------------------------------------------------\n    *\n    *                           function gstime\n    *\n    *  this function finds the greenwich sidereal time.\n    *\n    *  author        : david vallado                  719-573-2600    1 mar 2001\n    *\n    *  inputs          description                    range / units\n    *    jdut1       - julian date in ut1             days from 4713 bc\n    *\n    *  outputs       :\n    *    gstime      - greenwich sidereal time        0 to 2pi rad\n    *\n    *  locals        :\n    *    temp        - temporary variable for doubles   rad\n    *    tut1        - julian centuries from the\n    *                  jan 1, 2000 12 h epoch (ut1)\n    *\n    *  coupling      :\n    *    none\n    *\n    *  references    :\n    *    vallado       2013, 187, eq 3-45\n    * --------------------------------------------------------------------------- */\n\n    double gstime(double jdut1)\n    {\n        double       temp, tut1;\n\n        tut1 = (jdut1 - 2451545.0) / 36525.0;\n        temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 +\n            (876600.0 * 3600 + 8640184.812866) * tut1 + 67310.54841;  // sec\n        temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad\n\n        // ------------------------ check quadrants ---------------------\n        if(temp < 0.0)\n            temp += twopi;\n\n        return temp;\n    }  // gstime\n\n"
  },
  {
    "path": "source/external/sgp4/SGP4.h",
    "content": "#ifndef __sgp4header__\n#define __sgp4header__\n\n/**\n * This class implements the elsetrec data type from Vallado's SGP4 code.\n * \"SGP4 Version 2016-03-09\"\n * @author aholinch\n */\nclass ElsetRec\n{\n  public:\n    int whichconst;\n    int epochtynumrev;\n    int error;\n    char operationmode;\n    char init;\n    char method;\n    double a;\n    double altp;\n    double alta;\n    double jdsatepoch;\n    double jdsatepochF;\n    double nddot;\n    double ndot;\n    double bstar;\n    double rcse;\n    double inclo;\n    double nodeo;\n    double ecco;\n    double argpo;\n    double mo;\n    double no_kozai;\n\n    // sgp4fix add unkozai'd variable\n    double no_unkozai;\n\n    // sgp4fix add singly averaged variables\n    double am;\n    double em;\n    double im;\n    double Om;\n    double om;\n    double mm;\n    double nm;\n    double t;\n\n    // sgp4fix add constant parameters to eliminate mutliple calls during execution\n    double tumin;\n    double mu;\n    double radiusearthkm;\n    double xke;\n    double j2;\n    double j3;\n    double j4;\n    double j3oj2;\n\n    // Additional elements to capture relevant TLE and object information:\n    long dia_mm; // RSO dia in mm\n    double period_sec; // Period in seconds\n    char active; // \"Active S/C\" flag (0=n, 1=y)\n    char not_orbital; // \"Orbiting S/C\" flag (0=n, 1=y)\n    double rcs_m2; // \"RCS (m^2)\" storage\n\n    // temporary variables because the original authors call the same method with different variables\n    double ep;\n    double inclp;\n    double nodep;\n    double argpp;\n    double mp;\n\n    int isimp;\n    double aycof;\n    double con41;\n    double cc1;\n    double cc4;\n    double cc5;\n    double d2;\n    double d3;\n    double d4;\n    double delmo;\n    double eta;\n    double argpdot;\n    double omgcof;\n    double sinmao;\n    double t2cof;\n    double t3cof;\n    double t4cof;\n    double t5cof;\n    double x1mth2;\n    double x7thm1;\n    double mdot;\n    double nodedot;\n    double xlcof;\n    double xmcof;\n    double nodecf;\n\n    // deep space\n    int irez;\n    double d2201;\n    double d2211;\n    double d3210;\n    double d3222;\n    double d4410;\n    double d4422;\n    double d5220;\n    double d5232;\n    double d5421;\n    double d5433;\n    double dedt;\n    double del1;\n    double del2;\n    double del3;\n    double didt;\n    double dmdt;\n    double dnodt;\n    double domdt;\n    double e3;\n    double ee2;\n    double peo;\n    double pgho;\n    double pho;\n    double pinco;\n    double plo;\n    double se2;\n    double se3;\n    double sgh2;\n    double sgh3;\n    double sgh4;\n    double sh2;\n    double sh3;\n    double si2;\n    double si3;\n    double sl2;\n    double sl3;\n    double sl4;\n    double gsto;\n    double xfact;\n    double xgh2;\n    double xgh3;\n    double xgh4;\n    double xh2;\n    double xh3;\n    double xi2;\n    double xi3;\n    double xl2;\n    double xl3;\n    double xl4;\n    double xlamo;\n    double zmol;\n    double zmos;\n    double atime;\n    double xli;\n    double xni;\n    double snodm;\n    double cnodm;\n    double sinim;\n    double cosim;\n    double sinomm;\n    double cosomm;\n    double day;\n    double emsq;\n    double gam;\n    double rtemsq;\n    double s1;\n    double s2;\n    double s3;\n    double s4;\n    double s5;\n    double s6;\n    double s7;\n    double ss1;\n    double ss2;\n    double ss3;\n    double ss4;\n    double ss5;\n    double ss6;\n    double ss7;\n    double sz1;\n    double sz2;\n    double sz3;\n    double sz11;\n    double sz12;\n    double sz13;\n    double sz21;\n    double sz22;\n    double sz23;\n    double sz31;\n    double sz32;\n    double sz33;\n    double z1;\n    double z2;\n    double z3;\n    double z11;\n    double z12;\n    double z13;\n    double z21;\n    double z22;\n    double z23;\n    double z31;\n    double z32;\n    double z33;\n    double argpm;\n    double inclm;\n    double nodem;\n    double dndt;\n    double eccsq;\n\n    // for initl\n    double ainv;\n    double ao;\n    double con42;\n    double cosio;\n    double cosio2;\n    double omeosq;\n    double posq;\n    double rp;\n    double rteosq;\n    double sinio;\n};  // end struct\n\n\nbool sgp4init(char opsmode, ElsetRec &rec);\n\nbool sgp4(ElsetRec &rec, double tsince, double r[3], double v[3]);\n\n#endif\n"
  },
  {
    "path": "source/files/fileAdmittance.cpp",
    "content": "/***********************************************/\n/**\n* @file fileAdmittance.cpp\n*\n* @brief Read/write admittance.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-08\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_Admittance\n\n#include \"base/import.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileAdmittance.h\"\n\nGROOPS_REGISTER_FILEFORMAT(Admittance, FILE_ADMITTANCE_TYPE)\n\n/***********************************************/\n\nvoid writeFileAdmittance(const FileName &fileName, const Admittance &admittance)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_ADMITTANCE_TYPE, FILE_ADMITTANCE_VERSION);\n    file<<nameValue(\"major\",      admittance.doodsonMajor);\n    file<<nameValue(\"minor\",      admittance.doodsonMinor);\n    file<<nameValue(\"admittance\", admittance.admittance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileAdmittance(const FileName &fileName, Admittance &admittance)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_ADMITTANCE_TYPE, FILE_ADMITTANCE_VERSION);\n    file>>nameValue(\"major\",      admittance.doodsonMajor);\n    file>>nameValue(\"minor\",      admittance.doodsonMinor);\n    file>>nameValue(\"admittance\", admittance.admittance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileAdmittance.h",
    "content": "/***********************************************/\n/**\n* @file fileAdmittance.h\n*\n* @brief Read/write admittance.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-08\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEADMITTANCE__\n#define __GROOPS_FILEADMITTANCE__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_Admittance\nstatic const char *docstringAdmittance = R\"(\nInterpolation matrix to create ocean minor tides from modeled major tides.\nThe file can be created with \\program{DoodsonHarmonicsCalculateAdmittance} and used e.g. in\n\\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}.\n\nSee \\program{DoodsonHarmonicsCalculateAdmittance}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_ADMITTANCE_TYPE    = \"admittance\";\nconstexpr UInt    FILE_ADMITTANCE_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Admittance to interpolate minor tides from major tides. */\nclass Admittance\n{\npublic:\n  /// List of major tides.\n  std::vector<Doodson> doodsonMajor;\n\n  /// List of minor tides (inclusive major tides).\n  std::vector<Doodson> doodsonMinor;\n\n  /** @brief Interpolation matrix.\n  Dimension: major count times minor count. */\n  Matrix admittance;\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a Admittance file. */\nvoid writeFileAdmittance(const FileName &fileName, const Admittance &admittance);\n\n/** @brief Read from a Admittance file. */\nvoid readFileAdmittance(const FileName &fileName, Admittance &admittance);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileArcList.cpp",
    "content": "/***********************************************/\n/**\n* @file fileArcList.cpp\n*\n* @brief Read/write Arc list.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-07\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_ArcList\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileArcList.h\"\n\nGROOPS_REGISTER_FILEFORMAT(ArcList, \"arcList\")\n\n/***********************************************/\n\nvoid writeFileArcList(const FileName &fileName, const std::vector<UInt> &arcsInterval, const std::vector<Time> &timesInterval)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_ARCLIST_TYPE, FILE_ARCLIST_VERSION);\n    file<<nameValue(\"intervalCount\", arcsInterval.size());\n    file.comment(\"time [MJD]               first arc\");\n    file.comment(\"==================================\");\n    for(UInt i=0; i<arcsInterval.size(); i++)\n    {\n      file<<beginGroup(\"interval\");\n      file<<nameValue(\"time\", timesInterval.at(i));\n      file<<nameValue(\"arc\",  arcsInterval.at(i));\n      file<<endGroup(\"interval\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileArcList(const FileName &fileName, std::vector<UInt> &arcsInterval, std::vector<Time> &timesInterval)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_ARCLIST_TYPE, FILE_ARCLIST_VERSION);\n    if(file.version() < 20200123)\n    {\n      file>>nameValue(\"arcList\", arcsInterval);\n      file>>nameValue(\"times\",   timesInterval);\n      return;\n    }\n    UInt count;\n    file>>nameValue(\"intervalCount\", count);\n    arcsInterval.resize(count);\n    timesInterval.resize(count);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"interval\");\n      file>>nameValue(\"time\", timesInterval.at(i));\n      file>>nameValue(\"arc\",  arcsInterval.at(i));\n      file>>endGroup(\"interval\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileArcList.h",
    "content": "/***********************************************/\n/**\n* @file fileArcList.h\n*\n* @brief Read/write Arc list.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEARCLIST__\n#define __GROOPS_FILEARCLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_ArcList\nstatic const char *docstringArcList = R\"(\nWith the \\program{InstrumentSynchronize} an \\file{instrument file}{instrument} can\nbe divided into time intervals and within the intervals into arcs.\nThis file provides the information about the mapping of arcs to time intervals.\n\nThis file can be used for the variational equation approach or \\program{KalmanBuildNormals}.\n\n\\begin{verbatim}\ngroops arclist version=20200123\n         32  # number of times\n# time [MJD]               first arc\n# ==================================\n 58909.000000000000000000          0\n 58910.000000000000000000          8\n 58911.000000000000000000         17\n 58912.000000000000000000         25\n 58913.000000000000000000         29\n 58914.000000000000000000         37\n 58915.000000000000000000         45\n 58916.000000000000000000         53\n 58917.000000000000000000         61\n 58918.000000000000000000         69\n 58919.000000000000000000         78\n 58920.000000000000000000         86\n 58921.000000000000000000         95\n 58922.000000000000000000        103\n 58923.000000000000000000        112\n 58924.000000000000000000        120\n 58925.000000000000000000        128\n 58926.000000000000000000        136\n 58927.000000000000000000        144\n 58928.000000000000000000        153\n 58929.000000000000000000        161\n 58930.000000000000000000        169\n 58931.000000000000000000        177\n 58932.000000000000000000        185\n 58933.000000000000000000        193\n 58934.000000000000000000        201\n 58935.000000000000000000        210\n 58936.000000000000000000        218\n 58937.000000000000000000        226\n 58938.000000000000000000        234\n 58939.000000000000000000        242\n 58940.000000000000000000        250\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/time.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_ARCLIST_TYPE    = \"arclist\";\nconstexpr UInt    FILE_ARCLIST_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a ArcList file. */\nvoid writeFileArcList(const FileName &fileName, const std::vector<UInt> &arcsInterval, const std::vector<Time> &timesInterval);\n\n/** @brief Read from a ArcList file. */\nvoid readFileArcList(const FileName &fileName, std::vector<UInt> &arcsInterval, std::vector<Time> &timesInterval);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileDoodsonEarthOrientationParameter.cpp",
    "content": "/***********************************************/\n/**\n* @file fileDoodsonEarthOrientationParameter.cpp\n*\n* @brief Read/write high frequent EOPs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-05-15\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_DoodsonEarthOrientationParameter\n\n#include \"base/import.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileDoodsonEarthOrientationParameter.h\"\n\nGROOPS_REGISTER_FILEFORMAT(DoodsonEarthOrientationParameter, FILE_DOODSONEARTHORIENTATIONPARAMETER_TYPE)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const DoodsonEop &x)\n{\n  ar<<nameValue(\"constituentsCount\", x.doodson.size());\n  ar.comment(\"dood.   xpCos [arcsec]            xpSin [arcsec]            ypCos [arcsec]            ypSin [arcsec]            ut1Cos [sec]              ut1Sin [sec]              lodCos [sec]              lodSin [sec]             name\");\n  ar.comment(\"===========================================================================================================================================================================================================================\");\n  for(UInt i=0; i<x.doodson.size(); i++)\n  {\n    ar<<beginGroup(\"constituent\");\n    ar<<nameValue(\"doodson\", x.doodson.at(i));\n    ar<<nameValue(\"xpCos\",   x.coeff(i, 0));\n    ar<<nameValue(\"xpSin\",   x.coeff(i, 1));\n    ar<<nameValue(\"ypCos\",   x.coeff(i, 2));\n    ar<<nameValue(\"ypSin\",   x.coeff(i, 3));\n    ar<<nameValue(\"ut1Cos\",  x.coeff(i, 4));\n    ar<<nameValue(\"ut1Sin\",  x.coeff(i, 5));\n    ar<<nameValue(\"lodCos\",  x.coeff(i, 6));\n    ar<<nameValue(\"lodSin\",  x.coeff(i, 7));\n    ar<<nameValue(\"name\",    (x.doodson.at(i).name() != x.doodson.at(i).code()) ? x.doodson.at(i).name() : \"\");\n    ar<<endGroup(\"constituent\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, DoodsonEop &x)\n{\n  UInt constituentsCount;\n  ar>>nameValue(\"constituentsCount\", constituentsCount);\n  x.doodson.resize(constituentsCount);\n  x.coeff = Matrix(constituentsCount, 8);\n  for(UInt i=0; i<constituentsCount; i++)\n  {\n    std::string name;\n    ar>>beginGroup(\"constituent\");\n    ar>>nameValue(\"doodson\", x.doodson.at(i));\n    ar>>nameValue(\"xpCos\",   x.coeff(i, 0));\n    ar>>nameValue(\"xpSin\",   x.coeff(i, 1));\n    ar>>nameValue(\"ypCos\",   x.coeff(i, 2));\n    ar>>nameValue(\"ypSin\",   x.coeff(i, 3));\n    ar>>nameValue(\"ut1Cos\",  x.coeff(i, 4));\n    ar>>nameValue(\"ut1Sin\",  x.coeff(i, 5));\n    ar>>nameValue(\"lodCos\",  x.coeff(i, 6));\n    ar>>nameValue(\"lodSin\",  x.coeff(i, 7));\n    ar>>nameValue(\"name\",    name);\n    ar>>endGroup(\"constituent\");\n  }\n}\n\n/***********************************************/\n\nvoid writeFileDoodsonEarthOrientationParameter(const FileName &fileName, const DoodsonEop &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_DOODSONEARTHORIENTATIONPARAMETER_TYPE, FILE_DOODSONEARTHORIENTATIONPARAMETER_VERSION);\n    file<<nameValue(\"doodsonEarthOrientationParameter\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileDoodsonEarthOrientationParameter(const FileName &fileName, DoodsonEop &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_DOODSONEARTHORIENTATIONPARAMETER_TYPE, FILE_DOODSONEARTHORIENTATIONPARAMETER_VERSION);\n    file>>nameValue(\"doodsonEarthOrientationParameter\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileDoodsonEarthOrientationParameter.h",
    "content": "/***********************************************/\n/**\n* @file fileDoodsonEarthOrientationParameter.h\n*\n* @brief Read/write high frequent EOPs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-05-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEDOODSONEARTHORIENTATIONPARAMETER__\n#define __GROOPS_FILEDOODSONEARTHORIENTATIONPARAMETER__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_DoodsonEarthOrientationParameter\nstatic const char *docstringDoodsonEarthOrientationParameter = R\"(\nCorrections for Earth orientation parameters (EOP) ($x_p, y_p, UT1, LOD$)\nas cos/sin oscillations for a list of doodson tidal frequencies.\n\n\\begin{verbatim}\ngroops doodsonEarthOrientationParameter version=20200123\n        11 # number of constituents\n# dood.   xpCos [arcsec]            xpSin [arcsec]            ypCos [arcsec]            ypSin [arcsec]            ut1Cos [sec]              ut1Sin [sec]              lodCos [sec]              lodSin [sec]             name\n# ===========================================================================================================================================================================================================================\n 155.645  2.399999999999999786e-07  1.799999999999999971e-07  1.799999999999999971e-07 -2.399999999999999786e-07 -2.000000000000000042e-08  2.000000000000000042e-08 -1.499999999999999932e-07 -1.400000000000000095e-07 \"\"\n 155.655 -8.220000000000000920e-06 -6.280000000000000012e-06 -6.280000000000000012e-06  8.220000000000000920e-06  7.899999999999999537e-07 -8.599999999999999187e-07  5.219999999999999150e-06  4.829999999999999496e-06 m1\n 155.665 -1.649999999999999872e-06 -1.260000000000000007e-06 -1.260000000000000007e-06  1.649999999999999872e-06  1.600000000000000033e-07 -1.700000000000000135e-07  1.049999999999999900e-06  9.700000000000000302e-07 \"\"\n 157.455 -1.539999999999999867e-06 -1.199999999999999946e-06 -1.199999999999999946e-06  1.539999999999999867e-06  1.499999999999999932e-07 -1.600000000000000033e-07  9.799999999999999345e-07  8.899999999999999491e-07 chi1\n 157.465 -3.400000000000000270e-07 -2.599999999999999988e-07 -2.599999999999999988e-07  3.400000000000000270e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.099999999999999746e-07  1.999999999999999909e-07 \"\"\n 161.557  9.999999999999999547e-08  8.000000000000000167e-08  8.000000000000000167e-08 -9.999999999999999547e-08 -1.000000000000000021e-08  1.000000000000000021e-08 -7.000000000000000477e-08 -4.999999999999999774e-08 \"\"\n 162.556  2.549999999999999726e-06  2.019999999999999718e-06  2.019999999999999718e-06 -2.549999999999999726e-06 -2.099999999999999746e-07  2.899999999999999763e-07 -1.799999999999999919e-06 -1.289999999999999931e-06 pi1\n 163.545 -4.899999999999999672e-07 -3.799999999999999616e-07 -3.799999999999999616e-07  4.899999999999999672e-07  4.000000000000000084e-08 -5.999999999999999464e-08  3.499999999999999842e-07  2.399999999999999786e-07 \"\"\n 163.555  4.272999999999999238e-05  3.010999999999999801e-05  3.010999999999999801e-05 -4.272999999999999238e-05 -3.079999999999999734e-06  5.219999999999999150e-06 -3.270999999999999684e-05 -1.929999999999999817e-05 p1\n 164.554 -3.599999999999999943e-07 -2.800000000000000191e-07 -2.800000000000000191e-07  3.599999999999999943e-07  2.999999999999999732e-08 -4.000000000000000084e-08  2.700000000000000090e-07  1.700000000000000135e-07 \"\"\n 164.556 -1.029999999999999879e-06 -7.999999999999999638e-07 -7.999999999999999638e-07  1.029999999999999879e-06  8.000000000000000167e-08 -1.199999999999999893e-07  7.599999999999999233e-07  4.899999999999999672e-07 \"\"\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_DOODSONEARTHORIENTATIONPARAMETER_TYPE    = \"doodsonEarthOrientationParameter\";\nconstexpr UInt    FILE_DOODSONEARTHORIENTATIONPARAMETER_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Point list with (multiple) data. */\nclass DoodsonEop\n{\npublic:\n  std::vector<Doodson> doodson;\n  Matrix coeff; // for each consituent (row), columns: xpCos,  xpSin, ypCos, ypSin [arcsec], ut1Cos, ut1Sin, lodCos, lodSin [sec];\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const DoodsonEop &x);\ntemplate<> void load(InArchive  &ar, DoodsonEop &x);\n\n/** @brief Write into a DoodsonEarthOrientationParameter file. */\nvoid writeFileDoodsonEarthOrientationParameter(const FileName &fileName, const DoodsonEop &x);\n\n/** @brief Read from a DoodsonEarthOrientationParameter file. */\nvoid readFileDoodsonEarthOrientationParameter(const FileName &fileName, DoodsonEop &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_FILEDOODSONEARTHORIENTATIONPARAMETER__ */\n"
  },
  {
    "path": "source/files/fileDoodsonHarmonic.cpp",
    "content": "/***********************************************/\n/**\n* @file fileDoodsonHarmonic.cpp\n*\n* @brief Read/write harmonics coded with doodson frequencies.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-06-10\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_DoodsonHarmonic\n\n#include \"base/import.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n\nGROOPS_REGISTER_FILEFORMAT(DoodsonHarmonic, FILE_DOODSONHARMONIC_TYPE)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const DoodsonHarmonic &x)\n{\n  UInt count = x.doodson.size();\n  ar<<nameValue(\"GM\", x.GM);\n  ar<<nameValue(\"R\",  x.R);\n  ar<<nameValue(\"constituentsCount\", count);\n  for(UInt i=0; i<count; i++)\n  {\n    ar<<beginGroup(\"constituent\");\n    ar<<nameValue(\"doodson\", x.doodson.at(i));\n    ar<<nameValue(\"cnmCos\",  x.cnmCos.at(i));\n    ar<<nameValue(\"snmCos\",  x.snmCos.at(i));\n    ar<<nameValue(\"cnmSin\",  x.cnmSin.at(i));\n    ar<<nameValue(\"snmSin\",  x.snmSin.at(i));\n    ar<<endGroup(\"constituent\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, DoodsonHarmonic &x)\n{\n  UInt count;\n\n  ar>>nameValue(\"GM\", x.GM);\n  ar>>nameValue(\"R\",  x.R);\n  ar>>nameValue(\"constituentsCount\", count);\n\n  x.doodson.resize(count);\n  x.cnmCos.resize(count);\n  x.cnmSin.resize(count);\n  x.snmCos.resize(count);\n  x.snmSin.resize(count);\n\n  for(UInt i=0; i<count; i++)\n  {\n    ar>>beginGroup(\"constituent\");\n    ar>>nameValue(\"doodson\", x.doodson.at(i));\n    ar>>nameValue(\"cnmCos\",  x.cnmCos.at(i));\n    ar>>nameValue(\"snmCos\",  x.snmCos.at(i));\n    ar>>nameValue(\"cnmSin\",  x.cnmSin.at(i));\n    ar>>nameValue(\"snmSin\",  x.snmSin.at(i));\n    ar>>endGroup(\"constituent\");\n  }\n}\n\n/***********************************************/\n\nvoid writeFileDoodsonHarmonic(const FileName &fileName, const DoodsonHarmonic &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_DOODSONHARMONIC_TYPE, FILE_DOODSONHARMONIC_VERSION);\n    file<<nameValue(\"doodsonHarmonic\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileDoodsonHarmonic(const FileName &fileName, DoodsonHarmonic &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_DOODSONHARMONIC_TYPE, FILE_DOODSONHARMONIC_VERSION);\n    file>>nameValue(\"doodsonHarmonic\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileDoodsonHarmonic.h",
    "content": "/***********************************************/\n/**\n* @file fileDoodsonHarmonic.h\n*\n* @brief Read/write harmonics coded with doodson frequencies.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-06-10\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEDOODSONHARMONIC__\n#define __GROOPS_FILEDOODSONHARMONIC__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_DoodsonHarmonic\nstatic const char *docstringDoodsonHarmonic = R\"(\nOcean tides are represented as time variable gravitational potential\nand is given by a fourier expansion\n\\begin{equation}\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\Theta_f(t)) + V_f^s(\\M x)\\sin(\\Theta_f(t)),\n\\end{equation}\nwhere $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics.\nThe $\\Theta_f(t)$ are the arguments of the tide constituents $f$:\n\\begin{equation}\n\\Theta_f(t) = \\sum_{i=1}^6 n_f^i\\beta_i(t),\n\\end{equation}\nwhere $\\beta_i(t)$ are the Doodson's fundamental arguments ($\\tau,s,h,p,N',p_s$) and $n_f^i$\nare the Doodson multipliers for the term at frequency~$f$.\n\nTo extract the potential coefficients of $V_f^c$ and $V_f^s$\nfor each frequency $f$ use \\program{DoodsonHarmonics2PotentialCoefficients}.\n\nSee also \\program{PotentialCoefficients2DoodsonHarmonics}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/matrix.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_DOODSONHARMONIC_TYPE    = \"doodsonHarmonic\";\nconstexpr UInt    FILE_DOODSONHARMONIC_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Tides: Spherical harmonics coded with doodson frequencies. */\nclass DoodsonHarmonic\n{\npublic:\n  Double GM, R;\n  std::vector<Doodson> doodson;\n  std::vector<Matrix>  cnmCos, snmCos;\n  std::vector<Matrix>  cnmSin, snmSin;\n\n/// Default Constructor.\nDoodsonHarmonic() {}\n\n/// Constructor.\nexplicit DoodsonHarmonic(Double _GM, Double _R, const std::vector<Doodson> &_doodson,\n                         const std::vector<Matrix> &_cnmCos, const std::vector<Matrix> &_snmCos,\n                         const std::vector<Matrix> &_cnmSin, const std::vector<Matrix> &_snmSin)\n        : GM(_GM), R(_R), doodson(_doodson), cnmCos(_cnmCos), snmCos(_snmCos), cnmSin(_cnmSin), snmSin(_snmSin) {}\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const DoodsonHarmonic &x);\ntemplate<> void load(InArchive  &ar, DoodsonHarmonic &x);\n\n/** @brief Write into a DoodsonHarmonic file. */\nvoid writeFileDoodsonHarmonic(const FileName &fileName, const DoodsonHarmonic &x);\n\n/** @brief Read from a DoodsonHarmonic file. */\nvoid readFileDoodsonHarmonic(const FileName &fileName, DoodsonHarmonic &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileEarthOrientationParameter.cpp",
    "content": "/***********************************************/\n/**\n* @file fileEarthOrientationParameter.cpp\n*\n* @brief Read/write EarthOrientationParameter.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_EarthOrientationParameter\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n\nGROOPS_REGISTER_FILEFORMAT(EarthOrientationParameter, FILE_EARTHORIENTATIONPARAMETER_TYPE)\n\n/***********************************************/\n\nvoid writeFileEarthOrientationParameter(const FileName &fileName, const const_MatrixSlice &EOP)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_EARTHORIENTATIONPARAMETER_TYPE, FILE_EARTHORIENTATIONPARAMETER_VERSION);\n    file<<nameValue(\"count\", EOP.rows());\n    file.comment(\"UTC [MJD]                 xp [arcsec]               yp [arcsec]               deltUT [sec]              LOD [sec]                 dX [arcsec]               dY [arcsec]             \");\n    file.comment(\"====================================================================================================================================================================================\");\n    for(UInt i=0; i<EOP.rows(); i++)\n    {\n      file<<beginGroup(\"eop\");\n      file<<nameValue(\"mjd\",     EOP(i,0));\n      file<<nameValue(\"xp\",      EOP(i,1));\n      file<<nameValue(\"yp\",      EOP(i,2));\n      file<<nameValue(\"deltaUT\", EOP(i,3));\n      file<<nameValue(\"lod\",     EOP(i,4));\n      file<<nameValue(\"dX\",      EOP(i,5));\n      file<<nameValue(\"dY\",      EOP(i,6));\n      file<<endGroup(\"eop\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileEarthOrientationParameter(const FileName &fileName, Matrix &EOP)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_EARTHORIENTATIONPARAMETER_TYPE, FILE_EARTHORIENTATIONPARAMETER_VERSION);\n    UInt count;\n    file>>nameValue(\"count\", count);\n    EOP = Matrix(count, 7);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"eop\");\n      file>>nameValue(\"mjd\",     EOP(i,0));\n      file>>nameValue(\"xp\",      EOP(i,1));\n      file>>nameValue(\"yp\",      EOP(i,2));\n      file>>nameValue(\"deltaUT\", EOP(i,3));\n      file>>nameValue(\"lod\",     EOP(i,4));\n      file>>nameValue(\"dX\",      EOP(i,5));\n      file>>nameValue(\"dY\",      EOP(i,6));\n      file>>endGroup(\"eop\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileEarthOrientationParameter.h",
    "content": "/***********************************************/\n/**\n* @file fileEarthOrientationParameter.h\n*\n* @brief Read/write EarthOrientationParameter.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEEARTHORIENTATIONPARAMETER__\n#define __GROOPS_FILEEARTHORIENTATIONPARAMETER__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_EarthOrientationParameter\nstatic const char *docstringEarthOrientationParameter = R\"(\nEarth Orientation Parameter (EOP) as provided by the International Earth Rotation and Reference Systems Service (IERS) (e.g \\verb|EOP 14 C04 (IAU2000A)|).\n\nSee \\program{IersC04IAU2000EarthOrientationParameter}, \\program{IersRapidIAU2000EarthOrientationParameter}.\n\n\\begin{verbatim}\ngroops earthOrientationParameter version=20200123\n       9641 # number of epochs\n# UTC [MJD]                 xp [arcsec]               yp [arcsec]               deltUT [sec]              LOD [sec]                 dX [arcsec]               dY [arcsec]\n# ====================================================================================================================================================================================\n  5.894700000000000000e+04  5.690599999999999825e-02  4.099130000000000273e-01 -2.316246000000000138e-01  1.636400000000000094e-03 -2.900000000000000017e-05  5.800000000000000034e-05\n  5.894800000000000000e+04  5.771400000000000141e-02  4.110159999999999925e-01 -2.332083000000000073e-01  1.520099999999999923e-03 -6.000000000000000152e-05  2.199999999999999943e-05\n  5.894900000000000000e+04  5.813000000000000111e-02  4.120099999999999874e-01 -2.346157000000000104e-01  1.293099999999999935e-03 -7.200000000000000182e-05  3.199999999999999855e-05\n  5.895000000000000000e+04  5.854100000000000276e-02  4.129849999999999910e-01 -2.357567999999999886e-01  9.872999999999999832e-04 -7.600000000000000418e-05  5.899999999999999754e-05\n  5.895100000000000000e+04  5.908599999999999963e-02  4.139869999999999939e-01 -2.366149999999999920e-01  7.075000000000000126e-04 -8.000000000000000654e-05  8.600000000000000331e-05\n  5.895200000000000000e+04  5.976900000000000268e-02  4.154180000000000095e-01 -2.372105999999999937e-01  4.798000000000000073e-04 -8.399999999999999535e-05  1.129999999999999955e-04\n  5.895300000000000000e+04  6.095400000000000124e-02  4.167310000000000181e-01 -2.375994999999999913e-01  3.118999999999999919e-04 -8.700000000000000051e-05  1.399999999999999877e-04\n  5.895400000000000000e+04  6.210199999999999748e-02  4.180929999999999924e-01 -2.378588000000000091e-01  1.710000000000000094e-04 -9.100000000000000287e-05  1.669999999999999935e-04\n  5.895500000000000000e+04  6.290999999999999370e-02  4.196619999999999795e-01 -2.380454999999999932e-01  1.719000000000000042e-04 -6.000000000000000152e-06  8.100000000000000375e-05\n  5.895600000000000000e+04  6.385599999999999610e-02  4.214060000000000028e-01 -2.382557999999999898e-01  2.683000000000000163e-04  1.029999999999999964e-04 -3.600000000000000091e-05\n  5.895700000000000000e+04  6.455500000000000127e-02  4.229890000000000039e-01 -2.385857000000000117e-01  4.040000000000000080e-04  1.019999999999999992e-04 -2.000000000000000164e-05\n  5.895800000000000000e+04  6.440300000000000191e-02  4.242549999999999932e-01 -2.390210000000000112e-01  4.910999999999999567e-04  5.899999999999999754e-05  4.399999999999999886e-05\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_EARTHORIENTATIONPARAMETER_TYPE    = \"earthOrientationParameter\";\nconstexpr UInt    FILE_EARTHORIENTATIONPARAMETER_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a EarthOrientationParameter file.\n* each row: mjd(UTC), xp[arcsec], yp[arcsec], dUT1[s], lod[s], dX[arcsec], dY[arcsec]. */\nvoid writeFileEarthOrientationParameter(const FileName &fileName, const const_MatrixSlice &EOP);\n\n/** @brief Read from a EarthOrientationParameter file.\n* each row: mjd(UTC), xp[arcsec], yp[arcsec], dUT1[s], lod[s], dX[arcsec], dY[arcsec]. */\nvoid readFileEarthOrientationParameter(const FileName &fileName, Matrix &EOP);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_FILEEARTHORIENTATIONPARAMETER__ */\n"
  },
  {
    "path": "source/files/fileEarthTide.cpp",
    "content": "/***********************************************/\n/**\n* @file fileEarthTide.cpp\n*\n* @brief Read/write EarthTide.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_EarthTide\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileEarthTide.h\"\n\nGROOPS_REGISTER_FILEFORMAT(EarthTide, FILE_EARTHTIDE_TYPE)\n\n/***********************************************/\n\nvoid readFileEarthTide(const FileName &fileName,\n                       Matrix &kReal, Matrix &kImag, Matrix &kPlus,\n                       Matrix &doodson20, Matrix &doodson21, Matrix &doodson22,\n                       Vector &ampIp20, Vector &ampOp20, Vector &ampIp21, Vector &ampOp21, Vector &amp22,\n                       Double &h2_0, Double &h2_2,\n                       Double &l2_0, Double &l2_2, Double &l21_1, Double &l22_1,\n                       Double &h21_imag, Double &l21_imag, Double &h22_imag, Double &l22_imag,\n                       Double &h3, Double &l3,\n                       Matrix &deformationArg21, Matrix &deformationArg20,\n                       Vector &dR21_ip, Vector &dR21_op, Vector &dR20_ip, Vector &dR20_op,\n                       Vector &dT21_ip, Vector &dT21_op, Vector &dT20_ip, Vector &dT20_op)\n{\n  try\n  {\n    UInt count;\n    std::vector<Doodson> doodson;\n\n    InFileArchive file(fileName, FILE_EARTHTIDE_TYPE, FILE_EARTHTIDE_VERSION);\n\n    file>>beginGroup(\"loveNumber\");\n    file>>nameValue(\"kReal\", kReal);\n    file>>nameValue(\"kImag\", kImag);\n    file>>nameValue(\"kPlus\", kPlus);\n    file>>endGroup(\"loveNumber\");\n\n    file>>beginGroup(\"longPeriodic\");\n    file>>nameValue(\"count\", count);\n    doodson.resize(count);\n    ampIp20   = Vector(count);\n    ampOp20   = Vector(count);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"constituent\");\n      file>>nameValue(\"doodson\", doodson.at(i));\n      file>>nameValue(\"ampInPhase\",  ampIp20(i));\n      file>>nameValue(\"ampOutPhase\", ampOp20(i));\n      file>>endGroup(\"constituent\");\n    }\n    doodson20 = Doodson::matrix(doodson);\n    file>>endGroup(\"longPeriodic\");\n\n    file>>beginGroup(\"diurnal\");\n    file>>nameValue(\"count\", count);\n    doodson.resize(count);\n    ampIp21   = Vector(count);\n    ampOp21   = Vector(count);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"constituent\");\n      file>>nameValue(\"doodson\", doodson.at(i));\n      file>>nameValue(\"ampInPhase\",  ampIp21(i));\n      file>>nameValue(\"ampOutPhase\", ampOp21(i));\n      file>>endGroup(\"constituent\");\n    }\n    doodson21 = Doodson::matrix(doodson);\n    file>>endGroup(\"diurnal\");\n\n    file>>beginGroup(\"semidiurnal\");\n    file>>nameValue(\"count\", count);\n    doodson.resize(count);\n    amp22 = Vector(count);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"constituent\");\n      file>>nameValue(\"doodson\", doodson.at(i));\n      file>>nameValue(\"ampInPhase\",  amp22(i));\n      file>>endGroup(\"constituent\");\n    }\n    doodson22 = Doodson::matrix(doodson);\n    file>>endGroup(\"semidiurnal\");\n\n    // read displacement values\n    file>>beginGroup(\"displacement\");\n    file>>nameValue(\"h2_0\",     h2_0);\n    file>>nameValue(\"h2_2\",     h2_2);\n    file>>nameValue(\"l2_0\",     l2_0);\n    file>>nameValue(\"l2_2\",     l2_2);\n    file>>nameValue(\"h3\",       h3);\n    file>>nameValue(\"l3\",       l3);\n    file>>nameValue(\"h21_imag\", h21_imag);\n    file>>nameValue(\"l21_imag\", l21_imag);\n    file>>nameValue(\"h22_imag\", h22_imag);\n    file>>nameValue(\"l22_imag\", l22_imag);\n    file>>nameValue(\"l21_1\",    l21_1);\n    file>>nameValue(\"l22_1\",    l22_1);\n\n    file>>beginGroup(\"longPeriodic\");\n    file>>nameValue(\"count\", count);\n    doodson.resize(count);\n    dR20_ip = Vector(count);\n    dR20_op = Vector(count);\n    dT20_ip = Vector(count);\n    dT20_op = Vector(count);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"constituent\");\n      file>>nameValue(\"doodson\", doodson.at(i));\n      file>>nameValue(\"dRInPhase\",  dR20_ip(i));\n      file>>nameValue(\"dROutPhase\", dR20_op(i));\n      file>>nameValue(\"dTInPhase\",  dT20_ip(i));\n      file>>nameValue(\"dTOutPhase\", dT20_op(i));\n      file>>endGroup(\"constituent\");\n    }\n    deformationArg20 = Doodson::matrix(doodson);\n    file>>endGroup(\"longPeriodic\");\n\n    file>>beginGroup(\"diurnal\");\n    file>>nameValue(\"count\", count);\n    doodson.resize(count);\n    dR21_ip = Vector(count);\n    dR21_op = Vector(count);\n    dT21_ip = Vector(count);\n    dT21_op = Vector(count);\n    for(UInt i=0; i<count; i++)\n    {\n      file>>beginGroup(\"constituent\");\n      file>>nameValue(\"doodson\", doodson.at(i));\n      file>>nameValue(\"dRInPhase\",  dR21_ip(i));\n      file>>nameValue(\"dROutPhase\", dR21_op(i));\n      file>>nameValue(\"dTInPhase\",  dT21_ip(i));\n      file>>nameValue(\"dTOutPhase\", dT21_op(i));\n      file>>endGroup(\"constituent\");\n    }\n    deformationArg21 = Doodson::matrix(doodson);\n    file>>endGroup(\"diurnal\");\n\n    file>>endGroup(\"displacement\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileEarthTide(const FileName &fileName,\n                        const_MatrixSliceRef kReal, const_MatrixSliceRef kImag, const_MatrixSliceRef kPlus,\n                        const_MatrixSliceRef doodson20, const_MatrixSliceRef doodson21, const_MatrixSliceRef doodson22,\n                        const_MatrixSliceRef ampIp20, const_MatrixSliceRef ampOp20, const_MatrixSliceRef ampIp21, const_MatrixSliceRef ampOp21, const_MatrixSliceRef amp22,\n                        Double h2_0, Double h2_2,\n                        Double l2_0, Double l2_2, Double l21_1, Double l22_1,\n                        Double h21_imag, Double l21_imag, Double h22_imag, Double l22_imag,\n                        Double h3, Double l3,\n                        const_MatrixSliceRef deformationArg21, const_MatrixSliceRef deformationArg20,\n                        const_MatrixSliceRef dR21_ip, const_MatrixSliceRef dR21_op, const_MatrixSliceRef dR20_ip, const_MatrixSliceRef dR20_op,\n                        const_MatrixSliceRef dT21_ip, const_MatrixSliceRef dT21_op, const_MatrixSliceRef dT20_ip, const_MatrixSliceRef dT20_op)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_EARTHTIDE_TYPE, FILE_EARTHTIDE_VERSION);\n\n    file<<beginGroup(\"loveNumber\");\n    file<<nameValue(\"kReal\", kReal);\n    file<<nameValue(\"kImag\", kImag);\n    file<<nameValue(\"kPlus\", kPlus);\n    file<<endGroup(\"loveNumber\");\n\n    file<<beginGroup(\"longPeriodic\");\n    file<<nameValue(\"count\", doodson20.rows());\n    for(UInt i=0; i<doodson20.rows(); i++)\n    {\n      Doodson doodson;\n      for(UInt k=0; k<6; k++)\n        doodson.d[k] = static_cast<Int>(doodson20(i, k));\n      file<<beginGroup(\"constituent\");\n      file<<nameValue(\"doodson\",     doodson);\n      file<<nameValue(\"ampInPhase\",  ampIp20(i,0));\n      file<<nameValue(\"ampOutPhase\", ampOp20(i,0));\n      file<<endGroup(\"constituent\");\n    }\n    file<<endGroup(\"longPeriodic\");\n\n    file<<beginGroup(\"diurnal\");\n    file<<nameValue(\"count\", doodson21.rows());\n    for(UInt i=0; i<doodson21.rows(); i++)\n    {\n      Doodson doodson;\n      for(UInt k=0; k<6; k++)\n        doodson.d[k] = static_cast<Int>(doodson21(i, k));\n      file<<beginGroup(\"constituent\");\n      file<<nameValue(\"doodson\",     doodson);\n      file<<nameValue(\"ampInPhase\",  ampIp21(i,0));\n      file<<nameValue(\"ampOutPhase\", ampOp21(i,0));\n      file<<endGroup(\"constituent\");\n    }\n    file<<endGroup(\"diurnal\");\n\n    file<<beginGroup(\"semidiurnal\");\n    file<<nameValue(\"count\", doodson22.rows());\n    for(UInt i=0; i<doodson22.rows(); i++)\n    {\n      Doodson doodson;\n      for(UInt k=0; k<6; k++)\n        doodson.d[k] = static_cast<Int>(doodson22(i, k));\n      file<<beginGroup(\"constituent\");\n      file<<nameValue(\"doodson\",    doodson);\n      file<<nameValue(\"ampInPhase\", amp22(i,0));\n      file<<endGroup(\"constituent\");\n    }\n    file<<endGroup(\"semidiurnal\");\n\n    // read displacement values\n    file<<beginGroup(\"displacement\");\n    file<<nameValue(\"h2_0\",     h2_0);\n    file<<nameValue(\"h2_2\",     h2_2);\n    file<<nameValue(\"l2_0\",     l2_0);\n    file<<nameValue(\"l2_2\",     l2_2);\n    file<<nameValue(\"h3\",       h3);\n    file<<nameValue(\"l3\",       l3);\n    file<<nameValue(\"h21_imag\", h21_imag);\n    file<<nameValue(\"l21_imag\", l21_imag);\n    file<<nameValue(\"h22_imag\", h22_imag);\n    file<<nameValue(\"l22_imag\", l22_imag);\n    file<<nameValue(\"l21_1\",    l21_1);\n    file<<nameValue(\"l22_1\",    l22_1);\n\n    file<<beginGroup(\"longPeriodic\");\n    file<<nameValue(\"count\", deformationArg20.rows());\n    for(UInt i=0; i<deformationArg20.rows(); i++)\n    {\n      Doodson doodson;\n      for(UInt k=0; k<6; k++)\n        doodson.d[k] = static_cast<Int>(deformationArg20(i, k));\n      file<<beginGroup(\"constituent\");\n      file<<nameValue(\"doodson\",    doodson);\n      file<<nameValue(\"dRInPhase\",  dR20_ip(i,0));\n      file<<nameValue(\"dROutPhase\", dR20_op(i,0));\n      file<<nameValue(\"dTInPhase\",  dT20_ip(i,0));\n      file<<nameValue(\"dTOutPhase\", dT20_op(i,0));\n      file<<endGroup(\"constituent\");\n    }\n    file<<endGroup(\"longPeriodic\");\n\n    file<<beginGroup(\"diurnal\");\n    file<<nameValue(\"count\", deformationArg21.rows());\n    for(UInt i=0; i<deformationArg21.rows(); i++)\n    {\n      Doodson doodson;\n      for(UInt k=0; k<6; k++)\n        doodson.d[k] = static_cast<Int>(deformationArg21(i, k));\n      file<<beginGroup(\"constituent\");\n      file<<nameValue(\"doodson\",    doodson);\n      file<<nameValue(\"dRInPhase\",  dR21_ip(i,0));\n      file<<nameValue(\"dROutPhase\", dR21_op(i,0));\n      file<<nameValue(\"dTInPhase\",  dT21_ip(i,0));\n      file<<nameValue(\"dTOutPhase\", dT21_op(i,0));\n      file<<endGroup(\"constituent\");\n    }\n    file<<endGroup(\"diurnal\");\n\n    file<<endGroup(\"displacement\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileEarthTide.h",
    "content": "/***********************************************/\n/**\n* @file fileEarthTide.h\n*\n* @brief Read/write EarthTide.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEMEARTHTIDE__\n#define __GROOPS_FILEMEARTHTIDE__\n\n#include \"base/doodson.h\"\n#include \"inputOutput/fileArchive.h\"\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_EarthTide\nstatic const char *docstringEarthTide = R\"(\nContaining the Love numbers together with frequency corrections to compute\nthe gravitational potential and the geometric displacements due to solid Earth tides.\nIt is used by \\configClass{tides}{tidesType}.\n)\";\n#endif\n\n/***********************************************/\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_EARTHTIDE_TYPE    = \"earthTide\";\nconstexpr UInt    FILE_EARTHTIDE_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Read from a EarthTide file. */\nvoid readFileEarthTide(const FileName &fileName,\n                       Matrix &kReal, Matrix &kImag, Matrix &kPlus,\n                       Matrix &doodson20, Matrix &doodson21, Matrix &doodson22,\n                       Vector &ampIp20, Vector &ampOp20, Vector &ampIp21, Vector &ampOp21, Vector &amp22,\n                       Double &h2_0, Double &h2_2,\n                       Double &l2_0, Double &l2_2, Double &l21_1, Double &l22_1,\n                       Double &h21_imag, Double &l21_imag, Double &h22_imag, Double &l22_imag,\n                       Double &h3, Double &l3,\n                       Matrix &deformationArg21, Matrix &deformationArg20,\n                       Vector &dR21_ip, Vector &dR21_op, Vector &dR20_ip, Vector &dR20_op,\n                       Vector &dT21_ip, Vector &dT21_op, Vector &dT20_ip, Vector &dT20_op);\n\n/** @brief Write an EarthTide file. */\nvoid writeFileEarthTide(const FileName &fileName,\n                        const_MatrixSliceRef kReal, const_MatrixSliceRef kImag, const_MatrixSliceRef kPlus,\n                        const_MatrixSliceRef doodson20, const_MatrixSliceRef doodson21, const_MatrixSliceRef doodson22,\n                        const_MatrixSliceRef ampIp20, const_MatrixSliceRef ampOp20, const_MatrixSliceRef ampIp21, const_MatrixSliceRef ampOp21, const_MatrixSliceRef amp22,\n                        Double h2_0, Double h2_2,\n                        Double l2_0, Double l2_2, Double l21_1, Double l22_1,\n                        Double h21_imag, Double l21_imag, Double h22_imag, Double l22_imag,\n                        Double h3, Double l3,\n                        const_MatrixSliceRef deformationArg21, const_MatrixSliceRef deformationArg20,\n                        const_MatrixSliceRef dR21_ip, const_MatrixSliceRef dR21_op, const_MatrixSliceRef dR20_ip, const_MatrixSliceRef dR20_op,\n                        const_MatrixSliceRef dT21_ip, const_MatrixSliceRef dT21_op, const_MatrixSliceRef dT20_ip, const_MatrixSliceRef dT20_op);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileEphemerides.cpp",
    "content": "/***********************************************/\n/**\n* @file fileEphemerides.cpp\n*\n* @brief Ephemerides of sun, moon, and planets.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-08-11\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_Ephemerides\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileEphemerides.h\"\n\nGROOPS_REGISTER_FILEFORMAT(Ephemerides, FILE_EPHEMERIDES_TYPE)\n\n/***********************************************/\n\nvoid InFileEphemerides::open(const FileName &name)\n{\n  try\n  {\n    close();\n    if(name.empty())\n      return;\n\n    UInt intervalsCount, bodyCount;\n\n    file.open(name, FILE_EPHEMERIDES_TYPE, FILE_EPHEMERIDES_VERSION);\n    file>>nameValue(\"bodyCount\",      bodyCount);\n    file>>nameValue(\"intervalsCount\", intervalsCount);\n    file>>nameValue(\"earthMoonRatio\", earthMoonRatio);\n\n    degree.resize(bodyCount);\n    subintervals.resize(bodyCount);\n    components.resize(bodyCount);\n\n    for(UInt idBody=0; idBody<bodyCount; idBody++)\n    {\n      file>>beginGroup(\"body\");\n      file>>nameValue(\"subintervals\", subintervals.at(idBody));\n      file>>nameValue(\"components\",   components.at(idBody));\n      file>>nameValue(\"degree\",       degree.at(idBody));\n      file>>endGroup(\"body\");\n    }\n\n    times.resize(intervalsCount+1);\n    for(UInt i=0; i<times.size(); i++)\n      file>>nameValue(\"time\", times.at(i));\n\n    coeff.resize(bodyCount);\n    for(UInt idBody=0; idBody<bodyCount; idBody++)\n      coeff.at(idBody).resize(subintervals.at(idBody), Matrix(components.at(idBody), degree.at(idBody)+1));\n\n    // If we have a binary file, we can efficiently seek to the needed position in the file.\n    if(file.canSeek())\n      seekStart = file.position();\n    seekSize = 0;\n    idInterval = 0;\n    readInterval(0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+name.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid InFileEphemerides::close()\n{\n  file.close();\n}\n\n/***********************************************/\n\nvoid InFileEphemerides::readInterval(UInt idInterval_)\n{\n  try\n  {\n    // must restart?\n    if(idInterval > idInterval_)\n    {\n      if(file.canSeek() && seekSize)\n        idInterval = 0;\n      else\n        open(file.fileName());\n    }\n\n    while(idInterval <= idInterval_)\n    {\n      // Seek to appropriate interval.\n      if(file.canSeek() && seekSize)\n      {\n        file.seek(seekStart + static_cast<std::streamoff>(idInterval_ * seekSize));\n        idInterval = idInterval_;\n      }\n\n      file>>beginGroup(\"interval\");\n      for(UInt idBody=0; idBody<subintervals.size(); idBody++)\n      {\n        file>>beginGroup(\"body\");\n        for(UInt idSub=0; idSub<subintervals.at(idBody); idSub++)\n        {\n          file>>beginGroup(\"subinterval\");\n          for(UInt n=0; n<=degree.at(idBody); n++)\n            for(UInt i=0; i<components.at(idBody); i++)\n              file>>nameValue(\"coefficient\", coeff.at(idBody).at(idSub)(i, n));\n          file>>endGroup(\"subinterval\");\n        }\n        file>>endGroup(\"body\");\n      }\n      file>>endGroup(\"interval\");\n\n      if(file.canSeek() && (idInterval == 0))\n        seekSize = file.position() - seekStart;\n      idInterval++;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+file.fileName().str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nMatrix InFileEphemerides::interpolate(const Time &time, Planet planet)\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n\n    // read new data block?\n    if((time < times.at(idInterval-1)) || (time >= times.at(idInterval)))\n    {\n      if((time < times.front()) || (time >= times.back()))\n        throw(Exception(time.dateTimeStr()+\" outside interval [\"+times.front().dateTimeStr()+\", \"+times.back().dateTimeStr()+\")\"));\n      readInterval(static_cast<UInt>(std::floor((time-times.front()).mjd()/(times.back()-times.front()).mjd()*(times.size()-1))));\n    }\n\n    UInt idBody = 0;\n    switch(planet)\n    {\n      case MERCURY:             idBody =  0; break;\n      case VENUS:               idBody =  1; break;\n      case EARTH:               idBody =  9; break; // moon relative to earth\n      case MARS:                idBody =  3; break;\n      case JUPITER:             idBody =  4; break;\n      case SATURN:              idBody =  5; break;\n      case URANUS:              idBody =  6; break;\n      case NEPTUNE:             idBody =  7; break;\n      case PLUTO:               idBody =  8; break;\n      case MOON:                idBody =  9; break;  // moon relative to earth\n      case SUN:                 idBody = 10; break;\n      case SOLARBARYCENTER:     return Matrix(3, 2);\n      case EARTHMOONBARYCENTER: idBody =  2; break;\n      case NUTATION:            idBody = 11; break;\n      case LIBRATION:           idBody = 12; break;\n      case MOONFROMEARTH:       idBody =  9; break;\n    }\n\n    if(idBody >= subintervals.size() || subintervals.at(idBody) == 0)\n      throw(Exception(static_cast<UInt>(planet)%\"No data for requested planet id %i\"s));\n\n    Double dt = (times.at(idInterval)-times.at(idInterval-1)).seconds()/subintervals.at(idBody);\n    Double t  = (time-times.at(idInterval-1)).seconds()/dt;\n    const UInt idSub = static_cast<UInt>(std::floor(t));\n    t = 2.*(t-idSub)-1.; // [-1, 1) in subinterval idSub\n\n    // Chebyshev polynomials and derivative in second column\n    Matrix p(degree.at(idBody)+1, 2);\n    p(0, 0) = 1.;\n    p(1, 0) = t;\n    p(1, 1) = 2./dt;\n    for(UInt n=2; n<p.rows(); n++)\n    {\n      p(n, 0) = 2*t*p(n-1, 0) - p(n-2, 0);\n      p(n, 1) = 2*t*p(n-1, 1) - p(n-2, 1) + 4./dt*p(n-1, 0);\n    }\n\n    Matrix posVel = coeff.at(idBody).at(idSub) * p;\n    if(planet == MOON)\n    {\n      posVel *= earthMoonRatio/(1.+earthMoonRatio);     // relative to earth-moon bary center\n      posVel += interpolate(time, EARTHMOONBARYCENTER); // add earth-moon bary center\n    }\n    if(planet == EARTH)\n    {\n      posVel *= -1./(1.+earthMoonRatio);                // relative to earth-moon bary center\n      posVel += interpolate(time, EARTHMOONBARYCENTER); // add earth-moon bary center\n    }\n    return posVel;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+file.fileName().str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid InFileEphemerides::ephemeris(const Time &time, Planet planet, Planet center, Vector3d &position, Vector3d &velocity)\n{\n  try\n  {\n    Matrix posVel;\n    if(planet == MOON && center == EARTH)\n      posVel = interpolate(time, MOONFROMEARTH);\n    else\n      posVel = interpolate(time, planet) - interpolate(time, center);\n    position = Vector3d(posVel.column(0));\n    velocity = Vector3d(posVel.column(1));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+file.fileName().str()+\">\", e)\n  }\n}\n\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileEphemerides(const FileName &fileName, Double earthMoonRatio, const std::vector<Time> &times,\n                          const std::vector<UInt> &subintervals, const std::vector<UInt> &components, const std::vector<UInt> &degree,\n                          const std::vector<std::vector<std::vector<Matrix>>> &coefficients)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_EPHEMERIDES_TYPE, FILE_EPHEMERIDES_VERSION);\n    file<<nameValue(\"bodyCount\",      components.size());\n    file<<nameValue(\"intervalsCount\", times.size()-1);\n    file<<nameValue(\"earthMoonRatio\", earthMoonRatio);\n    file.comment(\"subintervals  components   degree\");\n    file.comment(\"=================================\");\n    for(UInt idBody=0; idBody<components.size(); idBody++)\n    {\n      file<<beginGroup(\"body\");\n      file<<nameValue(\"subintervals\", subintervals.at(idBody));\n      file<<nameValue(\"components\",   components.at(idBody));\n      file<<nameValue(\"degree\",       degree.at(idBody));\n      file<<endGroup(\"body\");\n    }\n    file.comment(\"times\");\n    file.comment(\"=====\");\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      file<<nameValue(\"time\", times.at(idEpoch));\n\n    file.comment(\"Chebyshev polynomial coefficients\");\n    file.comment(\"=================================\");\n    for(UInt idInterval=0; idInterval<coefficients.size(); idInterval++)\n    {\n      file<<beginGroup(\"interval\");\n      for(UInt idBody=0; idBody<subintervals.size(); idBody++)\n      {\n        file<<beginGroup(\"body\");\n        for(UInt idSub=0; idSub<subintervals.at(idBody); idSub++)\n        {\n          file<<beginGroup(\"subinterval\");\n          for(UInt n=0; n<=degree.at(idBody); n++)\n            for(UInt i=0; i<components.at(idBody); i++)\n              file<<nameValue(\"coefficient\", coefficients.at(idInterval).at(idBody).at(idSub)(i, n));\n          file<<endGroup(\"subinterval\");\n        }\n        file<<endGroup(\"body\");\n      }\n      file<<endGroup(\"interval\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileEphemerides.h",
    "content": "/***********************************************/\n/**\n* @file fileEphemerides.h\n*\n* @brief Ephemerides of sun, moon, and planets.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-08-11\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEEPHEMERIDES__\n#define __GROOPS_FILEEPHEMERIDES__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_Ephemerides\nstatic const char *docstringEphemerides = R\"(\nEphemerides of sun, moon, and planets stored as coefficients of Chebyshev polynomials.\nUsed in \\configClass{Ephemerides:jpl}{ephemeridesType:jpl}.\n\nSee also \\program{JplAscii2Ephemerides}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_EPHEMERIDES_TYPE    = \"ephemerides\";\nconstexpr UInt    FILE_EPHEMERIDES_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Ephemerides of sun, moon, and planets. */\nclass InFileEphemerides\n{\n  InFileArchive     file;\n  Double            earthMoonRatio;\n  std::vector<Time> times;                // interval boundaries\n  std::vector<UInt> subintervals;         // for each body: number of subintervals\n  std::vector<UInt> components;           // for each body: number of components: 3 for x,y,z\n  std::vector<UInt> degree;               // for each body: polynomial degree\n  std::streampos    seekStart;\n  std::streamoff    seekSize;\n  UInt              idInterval;           // next interval to read\n  std::vector<std::vector<Matrix>> coeff; // for each body, subinterval: Matrix(components, degree+1)\n\n  void readInterval(UInt idInterval_);\n\npublic:\n  /// planet identifier\n  enum Planet {MERCURY             = 1,\n               VENUS               = 2,\n               EARTH               = 3,\n               MARS                = 4,\n               JUPITER             = 5,\n               SATURN              = 6,\n               URANUS              = 7,\n               NEPTUNE             = 8,\n               PLUTO               = 9,\n               MOON                = 10,\n               SUN                 = 11,\n               SOLARBARYCENTER     = 12,\n               EARTHMOONBARYCENTER = 13,\n               NUTATION            = 14,\n               LIBRATION           = 15,\n               MOONFROMEARTH       = 99};\n\n  InFileEphemerides() {}\n  explicit InFileEphemerides(const FileName &name) {open(name);}     //!< Constructor.\n  InFileEphemerides(const InFileEphemerides &) = delete;             //!< Disallow copy constructor\n  InFileEphemerides &operator=(const InFileEphemerides &x) = delete; //!< Disallow copying\n ~InFileEphemerides() {close();}\n\n  void open(const FileName &name);\n  void close();\n\n  /// ephemeris of @p planet relative to @p center.\n  void ephemeris(const Time &timeGPS, Planet planet, Planet center, Vector3d &position, Vector3d &velocity);\n\n  /// interpolate data (e.g. libration) to @p timeGPS (second column: derivative).\n  Matrix interpolate(const Time &timeGPS, Planet planet);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into an ephemerides file. */\nvoid writeFileEphemerides(const FileName &fileName, Double earthMoonRatio, const std::vector<Time> &times,\n                          const std::vector<UInt> &subintervals, const std::vector<UInt> &components, const std::vector<UInt> &degree,\n                          const std::vector<std::vector<std::vector<Matrix>>> &coefficients);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileFormatRegister.h",
    "content": "/***********************************************/\n/**\n* @file fileFormatRegister.h\n*\n* @brief Desciption of file format in groops.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-06-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEFORMATGREGISTER__\n#define __GROOPS_FILEFORMATGREGISTER__\n\n#include \"base/import.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** DEFINE **********************************/\n\n/** @brief Macro for file format registration in documenation.\n* Call: GROOPS_REGISTER_FILEFORMAT(Title, \"type\").\n* A string named \"docstring{Title}\" must exist. */\n#define GROOPS_REGISTER_FILEFORMAT(_title, _type)\\\nclass _FileFormat##_title : public FileFormat\\\n{\\\npublic:\\\n  std::string title() const override {return #_title;}\\\n  std::string type()  const override {return _type;}\\\n  std::string documentation() const override {return docstring##_title;}\\\n};\\\nstatic _FileFormat##_title _fileFormat##_title;\\\n// end macro\n\n/***** CLASS ***********************************/\n\n/** @brief Class registration in documentation.\n* Use macro GROOPS_REGISTER_FILEFORMAT. */\nclass FileFormat\n{\npublic:\n  FileFormat() {list(this);}\n  virtual ~FileFormat() {}\n\n  virtual std::string title() const = 0;\n  virtual std::string type()  const = 0;\n  virtual std::string documentation() const = 0;\n\n  static std::vector<FileFormat*> list(FileFormat *fileFormat=nullptr)\n  {\n    static std::vector<FileFormat*> list_;\n    if(fileFormat != nullptr)\n      list_.push_back(fileFormat);\n    return list_;\n  }\n\n  static void sort(std::vector<FileFormat*> &list)\n  {\n    std::sort(list.begin(), list.end(), [](FileFormat *a, FileFormat *b) {return a->type() < b->type();});\n  }\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS__ */\n\n"
  },
  {
    "path": "source/files/fileGnssAntennaDefinition.cpp",
    "content": "/***********************************************/\n/**\n* @file fileGnssAntennaDefinition.cpp\n*\n* @brief Antenna center variations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-11-22\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_GnssAntennaDefinition\n\n#include \"base/import.h\"\n#include \"base/gnssType.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n\nGROOPS_REGISTER_FILEFORMAT(GnssAntennaDefinition, \"gnssAntennaDefinition\")\n\n/***********************************************/\n\nVector GnssAntennaDefinition::antennaVariations(Angle azimut, Angle elevation, const std::vector<GnssType> &types, NoPatternFoundAction noPatternFoundAction) const\n{\n  try\n  {\n    Vector acv(types.size());\n    for(UInt idType=0; idType<types.size(); idType++)\n      if((types.at(idType) == GnssType::PHASE) || (types.at(idType) == GnssType::RANGE))\n      {\n        const UInt idPattern = findAntennaPattern(types.at(idType), noPatternFoundAction);\n        acv(idType) = (idPattern == NULLINDEX) ? NAN_EXPR : patterns.at(idPattern).antennaVariations(azimut, elevation);\n      }\n\n    return acv;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt GnssAntennaDefinition::findAntennaPattern(const GnssType &type, NoPatternFoundAction noPatternFoundAction) const\n{\n  try\n  {\n    auto iter = std::find_if(patterns.begin(), patterns.end(), [&](const GnssAntennaPattern &p) {return p.type == type;});\n    if(iter == patterns.end()) // no matching pattern found\n    {\n      if(noPatternFoundAction == IGNORE_OBSERVATION)\n        return NULLINDEX;\n      if(noPatternFoundAction == USE_NEAREST_FREQUENCY)\n      {\n        // TODO: there should be the following priorities: phase? nearest phase; code? nearest code or if no code then nearest phase\n        iter = std::min_element(patterns.begin(), patterns.end(), [&](const GnssAntennaPattern &p1, const GnssAntennaPattern &p2)\n        {\n          GnssType t1 = p1.type; if(t1 == GnssType::GLONASS) t1.setFrequencyNumber(0);\n          GnssType t2 = p2.type; if(t2 == GnssType::GLONASS) t2.setFrequencyNumber(0);\n          return std::fabs(t1.frequency() - type.frequency()) < std::fabs(t2.frequency() - type.frequency());\n        });\n      }\n      if(noPatternFoundAction == THROW_EXCEPTION || iter == patterns.end()) // still no matching pattern found\n        throw(Exception(\"no pattern found for \"+type.str()));\n    }\n\n    return static_cast<UInt>(std::distance(patterns.begin(), iter));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssAntennaDefinitionPtr GnssAntennaDefinition::find(const std::vector<GnssAntennaDefinitionPtr> &antennaList, const std::string &name, const std::string &serial, const std::string radome)\n{\n  try\n  {\n    for(UInt i=antennaList.size(); i-->0;) // backwards search\n      if((name == antennaList.at(i)->name) || antennaList.at(i)->name.empty())\n        if((serial == antennaList.at(i)->serial) || antennaList.at(i)->serial.empty())\n          if((radome == antennaList.at(i)->radome) || antennaList.at(i)->radome.empty())\n            return antennaList.at(i);\n\n    return GnssAntennaDefinitionPtr(nullptr);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nDouble GnssAntennaPattern::antennaVariations(Angle azimut, Angle elevation, Bool applyOffset) const\n{\n  try\n  {\n    Double tauA  = std::fmod(Double(azimut)/(2*PI)+1,1) * pattern.rows();\n    Double tauZ  = (PI/2-Double(elevation))/Double(dZenit);\n    const UInt idxA1 = static_cast<UInt>(std::floor(tauA));\n    const UInt idxA2 = (idxA1+1)%pattern.rows();\n    const UInt idxZ1 = std::min(static_cast<UInt>(std::floor(tauZ)), pattern.columns()-1);\n    const UInt idxZ2 = std::min(idxZ1+1, pattern.columns()-1);\n    tauA -= std::floor(tauA);\n    tauZ -= std::floor(tauZ);\n\n    // bilinear interpolation\n    Double acv = (1-tauA) * (1-tauZ) * pattern(idxA1, idxZ1)\n               + (1-tauA) *  (tauZ)  * pattern(idxA1, idxZ2)\n               +  (tauA)  * (1-tauZ) * pattern(idxA2, idxZ1)\n               +  (tauA)  *  (tauZ)  * pattern(idxA2, idxZ2);\n\n    if(applyOffset)\n      acv -= inner(offset, polar(azimut, elevation, 1.));\n\n    return acv;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GnssAntennaDefinition &x)\n{\n  try\n  {\n    ar<<nameValue(\"name\",      x.name);\n    ar<<nameValue(\"serial\",    x.serial);\n    ar<<nameValue(\"radome\",    x.radome);\n    ar<<nameValue(\"comment\",   x.comment);\n    ar<<nameValue(\"pattern\",   x.patterns);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, GnssAntennaDefinition  &x)\n{\n  try\n  {\n    ar>>nameValue(\"name\",      x.name);\n    ar>>nameValue(\"serial\",    x.serial);\n    ar>>nameValue(\"radome\",    x.radome);\n    ar>>nameValue(\"comment\",   x.comment);\n    ar>>nameValue(\"pattern\",   x.patterns);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GnssAntennaDefinitionPtr &x)\n{\n  try\n  {\n    save(ar, *x.get());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, GnssAntennaDefinitionPtr &x)\n{\n  try\n  {\n    if(!x)\n      x = GnssAntennaDefinitionPtr(new GnssAntennaDefinition);\n    load(ar, *x.get());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GnssAntennaPattern &x)\n{\n  try\n  {\n    ar<<nameValue(\"type\",     x.type);\n    ar<<nameValue(\"offset\",   x.offset);\n    ar<<nameValue(\"dZenit\",   x.dZenit);\n    ar<<nameValue(\"pattern\",  x.pattern);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, GnssAntennaPattern &x)\n{\n  try\n  {\n    ar>>nameValue(\"type\",     x.type);\n    ar>>nameValue(\"offset\",   x.offset);\n    ar>>nameValue(\"dZenit\",   x.dZenit);\n    ar>>nameValue(\"pattern\",  x.pattern);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileGnssAntennaDefinition(const FileName &fileName, const GnssAntennaDefinition &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_GNSSANTENNADEFINITION_TYPE, FILE_GNSSANTENNADEFINITION_VERSION);\n    file<<nameValue(\"antennaCount\", 1);\n    file<<nameValue(\"antenna\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileGnssAntennaDefinition(const FileName &fileName, const std::vector<GnssAntennaDefinitionPtr> &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_GNSSANTENNADEFINITION_TYPE, FILE_GNSSANTENNADEFINITION_VERSION);\n    file<<nameValue(\"antennaCount\", x.size());\n    for(UInt i=0; i<x.size(); i++)\n      file<<nameValue(\"antenna\", x.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileGnssAntennaDefinition(const FileName &fileName, GnssAntennaDefinition &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_GNSSANTENNADEFINITION_TYPE, FILE_GNSSANTENNADEFINITION_VERSION);\n    if(file.version() < 20190304)\n      throw(Exception(fileName.str()+\": old GnssAntennaDefinition file, definition of reference frames changed\"));\n\n    UInt count;\n    file>>nameValue(\"antennaCount\", count);\n    if(count>1)\n      logWarning<<fileName<<\" contain more than one antenna, only the first is used\"<<Log::endl;\n    file>>nameValue(\"antenna\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileGnssAntennaDefinition(const FileName &fileName, std::vector<GnssAntennaDefinitionPtr> &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_GNSSANTENNADEFINITION_TYPE, FILE_GNSSANTENNADEFINITION_VERSION);\n    if(file.version() < 20190304)\n      throw(Exception(fileName.str()+\": old GnssAntennaDefinition file, definition of reference frames changed\"));\n\n    UInt count;\n    file>>nameValue(\"antennaCount\", count);\n    x.resize(count);\n    for(UInt i=0; i<x.size(); i++)\n      file>>nameValue(\"antenna\", x.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileGnssAntennaDefinition.h",
    "content": "/***********************************************/\n/**\n* @file fileGnssAntennaDefinition.h\n*\n* @brief Antenna center variations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 201-11-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEGNSSANTENNADEFINITION__\n#define __GROOPS_FILEGNSSANTENNADEFINITION__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_GnssAntennaDefinition\nstatic const char *docstringGnssAntennaDefinition = R\"(\nContains a list of GNSS antennas which are identified by its\nname (type), serial, and radome. Each antenna consists of\nantenna center offsets (ACO) and antenna center variations (ACV)\nfor different signal \\configClass{types}{gnssType} (code and phase).\nThe ACV values for each type are stored in an elevation and azimuth dependent grid.\n\n%New \\config{antenna} with \\config{pattern}s for code (\\config{type}=\\verb|C**|) and phase\n%(\\config{type}=\\verb|L**|).\n%The standard deviation is expressed e.g. with \\config{values}=\\verb|0.001/cos(2*PI/180*zenith)|.\n\nSee also \\program{GnssAntennaDefinitionCreate}, \\program{GnssAntex2AntennaDefinition}.\n\n\\fig{!hb}{1.0}{fileFormatGnssAntennaDefinition}{fig:fileFormatGnssAntennaDefinition}{Antenna center variations of ASH701945D\\_M for two frequencies of GPS and GLONASS}\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"antennaDefinition\" version=\"20190429\">\n    <antennaCount>65</antennaCount>\n    ...\n    <antenna>\n        <name>BLOCK IIIA</name>\n        <serial>G074</serial>\n        <radome>2018-109A</radome>\n        <comment>PCO provided by the Aerospace Corporation, PV from estimations by ESA/CODE</comment>\n        <pattern>\n            <count>3</count>\n            <cell>\n                <type>*1*G**</type>\n                <offset>\n                    <x>-1.23333333333333e-03</x>\n                    <y>4.33333333333333e-04</y>\n                    <z>3.15200000000000e-01</z>\n                </offset>\n                <dZenit>1.00000000000000e+00</dZenit>\n                <pattern>\n                    <type>0</type>\n                    <rows>1</rows>\n                    <columns>18</columns>\n                    <cell row=\"0\" col=\"0\">1.39000000000000e-02</cell>\n                    <cell row=\"0\" col=\"1\">1.28000000000000e-02</cell>\n                    <cell row=\"0\" col=\"2\">1.02000000000000e-02</cell>\n                    <cell row=\"0\" col=\"3\">5.80000000000000e-03</cell>\n                    <cell row=\"0\" col=\"4\">1.10000000000000e-03</cell>\n                    <cell row=\"0\" col=\"5\">-4.50000000000000e-03</cell>\n                    <cell row=\"0\" col=\"6\">-9.70000000000000e-03</cell>\n                    <cell row=\"0\" col=\"7\">-1.28000000000000e-02</cell>\n                    <cell row=\"0\" col=\"8\">-1.34000000000000e-02</cell>\n                    <cell row=\"0\" col=\"9\">-1.18000000000000e-02</cell>\n                    <cell row=\"0\" col=\"10\">-8.90000000000000e-03</cell>\n                    <cell row=\"0\" col=\"11\">-4.50000000000000e-03</cell>\n                    <cell row=\"0\" col=\"12\">1.20000000000000e-03</cell>\n                    <cell row=\"0\" col=\"13\">7.20000000000000e-03</cell>\n                    <cell row=\"0\" col=\"14\">1.33000000000000e-02</cell>\n                    <cell row=\"0\" col=\"15\">1.33000000000000e-02</cell>\n                    <cell row=\"0\" col=\"16\">1.33000000000000e-02</cell>\n                    <cell row=\"0\" col=\"17\">1.33000000000000e-02</cell>\n                </pattern>\n            </cell>\n            ...\n        </pattern>\n    </antenna>\n</groops>\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/gnssType.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_GNSSANTENNADEFINITION_TYPE    = \"antennaDefinition\";\nconstexpr UInt    FILE_GNSSANTENNADEFINITION_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** TYPES ***********************************/\n\nclass GnssAntennaDefinition;\nclass GnssAntennaPattern;\ntypedef std::shared_ptr<GnssAntennaDefinition> GnssAntennaDefinitionPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Antenna center variations.\n* with different patterns for different signals. */\nclass GnssAntennaDefinition\n{\n  public:\n  enum NoPatternFoundAction\n  {\n    IGNORE_OBSERVATION,\n    USE_NEAREST_FREQUENCY,\n    THROW_EXCEPTION\n  };\n\n  std::string name, serial;\n  std::string radome;\n  std::string comment;\n  std::vector<GnssAntennaPattern> patterns;\n\n  /** @brief Returns the separator between parts of the full antenna name. */\n  static constexpr Char sep = '|';\n  static std::string str(const std::string &name, const std::string &serial, const std::string &radome) {return name+sep+serial+sep+radome;}\n  std::string str() const {return str(name, serial, radome);}\n\n  Vector antennaVariations(Angle azimut, Angle elevation, const std::vector<GnssType> &types, NoPatternFoundAction noPatternFoundAction) const;\n\n  /** @brief Returns id of pattern matching @p type or of nearest frequency pattern depending on @p noPatternFoundAction. Returns NULLINDEX if there are no patterns. */\n  UInt findAntennaPattern(const GnssType &type, NoPatternFoundAction noPatternFoundAction) const;\n\n  static GnssAntennaDefinitionPtr find(const std::vector<GnssAntennaDefinitionPtr> &antennaList, const std::string &name, const std::string &serial, const std::string radome);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Antenna center variations.\n* for one specfic observation type. */\nclass GnssAntennaPattern\n{\n  public:\n  GnssType type;\n  Vector3d offset;   // phase center relative to antenna reference point\n  Angle    dZenit;\n  Matrix   pattern;  // phase center variations (azimut(0..360) x zenit(0..dZenit*rows))\n\n  // pattern estimation -> not written to file\n  std::vector<std::vector<std::vector<Double>>> residuals;\n  Matrix   ePe, redundancy;\n  Matrix   sum, count;\n\n  Double antennaVariations(Angle azimut, Angle elevation, Bool applyOffset=TRUE) const;\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const GnssAntennaDefinition    &x);\ntemplate<> void save(OutArchive &ar, const GnssAntennaDefinitionPtr &x);\ntemplate<> void load(InArchive  &ar, GnssAntennaDefinition    &x);\ntemplate<> void load(InArchive  &ar, GnssAntennaDefinitionPtr &x);\n\ntemplate<> void save(OutArchive &ar, const GnssAntennaPattern &x);\ntemplate<> void load(InArchive  &ar, GnssAntennaPattern  &x);\n\n/** @brief Write into a GnssAntennaDefinition file. */\nvoid writeFileGnssAntennaDefinition(const FileName &fileName, const GnssAntennaDefinition &x);\n\n/** @brief Write into a GnssAntennaDefinition file. */\nvoid writeFileGnssAntennaDefinition(const FileName &fileName, const std::vector<GnssAntennaDefinitionPtr> &x);\n\n\n/** @brief Read from a GnssAntennaDefinition file. */\nvoid readFileGnssAntennaDefinition(const FileName &fileName, GnssAntennaDefinition &x);\n\n/** @brief Read from a GnssAntennaDefinition file. */\nvoid readFileGnssAntennaDefinition(const FileName &fileName, std::vector<GnssAntennaDefinitionPtr> &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/files/fileGnssReceiverDefinition.cpp",
    "content": "/***********************************************/\n/**\n* @file fileGnssReceiverDefinition.cpp\n*\n* @brief GNSS receiver definition.\n*\n* @author Sebastian Strasser\n* @date 2019-08-28\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_GnssReceiverDefinition\n\n#include \"base/import.h\"\n#include \"base/gnssType.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n\nGROOPS_REGISTER_FILEFORMAT(GnssReceiverDefinition, \"gnssReceiverDefinition\")\n\n/***********************************************/\n\nGnssReceiverDefinitionPtr GnssReceiverDefinition::find(const std::vector<GnssReceiverDefinitionPtr> &receivers, const std::string &name, const std::string &serial, const std::string version)\n{\n  try\n  {\n    for(UInt i=receivers.size(); i-->0;) // backwards search\n      if((name == receivers.at(i)->name) || receivers.at(i)->name.empty())\n        if((serial == receivers.at(i)->serial) || receivers.at(i)->serial.empty())\n          if((version == receivers.at(i)->version) || receivers.at(i)->version.empty())\n            return receivers.at(i);\n\n    return GnssReceiverDefinitionPtr(nullptr);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GnssReceiverDefinition &x)\n{\n  try\n  {\n    ar<<nameValue(\"name\",      x.name);\n    ar<<nameValue(\"serial\",    x.serial);\n    ar<<nameValue(\"version\",   x.version);\n    ar<<nameValue(\"comment\",   x.comment);\n    ar<<nameValue(\"types\",     x.types);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, GnssReceiverDefinition  &x)\n{\n  try\n  {\n    ar>>nameValue(\"name\",      x.name);\n    ar>>nameValue(\"serial\",    x.serial);\n    ar>>nameValue(\"version\",   x.version);\n    ar>>nameValue(\"comment\",   x.comment);\n    ar>>nameValue(\"types\",     x.types);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GnssReceiverDefinitionPtr &x)\n{\n  try\n  {\n    save(ar, *x.get());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, GnssReceiverDefinitionPtr &x)\n{\n  try\n  {\n    if(!x)\n      x = GnssReceiverDefinitionPtr(new GnssReceiverDefinition);\n    load(ar, *x.get());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileGnssReceiverDefinition(const FileName &fileName, const GnssReceiverDefinition &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_GNSSRECEIVERDEFINITION_TYPE, FILE_GNSSRECEIVERDEFINITION_VERSION);\n    file<<nameValue(\"receiverCount\", 1);\n    file<<nameValue(\"receiver\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileGnssReceiverDefinition(const FileName &fileName, const std::vector<GnssReceiverDefinitionPtr> &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_GNSSRECEIVERDEFINITION_TYPE, FILE_GNSSRECEIVERDEFINITION_VERSION);\n    file<<nameValue(\"receiverCount\", x.size());\n    for(UInt i=0; i<x.size(); i++)\n      file<<nameValue(\"receiver\", x.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileGnssReceiverDefinition(const FileName &fileName, GnssReceiverDefinition &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_GNSSRECEIVERDEFINITION_TYPE, FILE_GNSSRECEIVERDEFINITION_VERSION);\n\n    UInt count;\n    file>>nameValue(\"receiverCount\", count);\n    if(count>1)\n      logWarning<<fileName<<\" contains more than one receiver, only the first is used\"<<Log::endl;\n    file>>nameValue(\"receiver\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileGnssReceiverDefinition(const FileName &fileName, std::vector<GnssReceiverDefinitionPtr> &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_GNSSRECEIVERDEFINITION_TYPE, FILE_GNSSRECEIVERDEFINITION_VERSION);\n\n    UInt count;\n    file>>nameValue(\"receiverCount\", count);\n    x.resize(count);\n    for(UInt i=0; i<x.size(); i++)\n      file>>nameValue(\"receiver\", x.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileGnssReceiverDefinition.h",
    "content": "/***********************************************/\n/**\n* @file fileGnssReceiverDefinition.h\n*\n* @brief GNSS receiver definition.\n*\n* @author Sebastian Strasser\n* @date 2019-08-28\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEGNSSRECEIVERDEFINITION__\n#define __GROOPS_FILEGNSSRECEIVERDEFINITION__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_GnssReceiverDefinition\nstatic const char *docstringGnssReceiverDefinition = R\"(\nContains a list of GNSS receivers which are identified by its\nname, serial, and version. Defines for each receiver a list of\nsignal \\configClass{types}{gnssType} which can be observed.\nCan also be used for GNSS transmitters to define a list of\ntransmitted signal types. For GLONASS satellites the frequency\nnumber can be stored in the \\emph{version} field.\n\nSee \\program{GnssReceiverDefinitionCreate}.\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"receiverDefinition\" version=\"20190429\">\n    <receiverCount>112</receiverCount>\n    <receiver>\n        <name>GLONASS</name>\n        <serial>R779</serial>\n        <version>2</version>\n        <comment/>\n        <types>\n            <count>4</count>\n            <cell>*1CR**J</cell>\n            <cell>*1PR**J</cell>\n            <cell>*2CR**J</cell>\n            <cell>*2PR**J</cell>\n        </types>\n    </receiver>\n    ...\n    <receiver>\n        <name>GLONASS-K1</name>\n        <serial>R802</serial>\n        <version>7</version>\n        <comment/>\n        <types>\n            <count>10</count>\n            <cell>*1CR**O</cell>\n            <cell>*1PR**O</cell>\n            <cell>*2CR**O</cell>\n            <cell>*2PR**O</cell>\n            <cell>*3IR**</cell>\n            <cell>*3QR**</cell>\n            <cell>*4AR**</cell>\n            <cell>*4BR**</cell>\n            <cell>*6AR**</cell>\n            <cell>*6BR**</cell>\n        </types>\n    </receiver>\n</groops>\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/gnssType.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_GNSSRECEIVERDEFINITION_TYPE    = \"receiverDefinition\";\nconstexpr UInt    FILE_GNSSRECEIVERDEFINITION_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** TYPES ***********************************/\n\nclass GnssReceiverDefinition;\ntypedef std::shared_ptr<GnssReceiverDefinition> GnssReceiverDefinitionPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS receiver definition. */\nclass GnssReceiverDefinition\n{\n  public:\n  std::string name;\n  std::string serial;\n  std::string version;\n  std::string comment;\n  std::vector<GnssType> types;\n\n  /** @brief Returns the separator between parts of the full receiver name. */\n  static constexpr Char sep = '|';\n  static std::string str(const std::string &name, const std::string &serial, const std::string &version) {return name+sep+serial+sep+version;}\n  std::string str() const {return str(name, serial, version);}\n\n  static GnssReceiverDefinitionPtr find(const std::vector<GnssReceiverDefinitionPtr> &receivers, const std::string &name, const std::string &serial, const std::string version);\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const GnssReceiverDefinition    &x);\ntemplate<> void save(OutArchive &ar, const GnssReceiverDefinitionPtr &x);\ntemplate<> void load(InArchive  &ar, GnssReceiverDefinition    &x);\ntemplate<> void load(InArchive  &ar, GnssReceiverDefinitionPtr &x);\n\n\n/** @brief Write into a GnssReceiverDefinition file. */\nvoid writeFileGnssReceiverDefinition(const FileName &fileName, const GnssReceiverDefinition &x);\n\n/** @brief Write into a GnssReceiverDefinition file. */\nvoid writeFileGnssReceiverDefinition(const FileName &fileName, const std::vector<GnssReceiverDefinitionPtr> &x);\n\n\n/** @brief Read from a GnssReceiverDefinition file. */\nvoid readFileGnssReceiverDefinition(const FileName &fileName, GnssReceiverDefinition &x);\n\n/** @brief Read from a GnssReceiverDefinition file. */\nvoid readFileGnssReceiverDefinition(const FileName &fileName, std::vector<GnssReceiverDefinitionPtr> &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/files/fileGnssSignalBias.cpp",
    "content": "/***********************************************/\n/**\n* @file fileGnssSignalBias.cpp\n*\n* @brief Code/Phase biases.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-08-11\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_GnssSignalBias\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileGnssSignalBias.h\"\n\nGROOPS_REGISTER_FILEFORMAT(GnssSignalBias, FILE_GNSSSIGNALBIAS_TYPE)\n\n/***********************************************/\n\nVector GnssSignalBias::compute(const std::vector<GnssType> &types) const\n{\n  try\n  {\n    Vector b(types.size());\n    UInt idx;\n    for(UInt idType=0; idType<types.size(); idType++)\n      if(types.at(idType).isInList(this->types, idx))\n        b(idType) = biases.at(idx);\n    return b;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GnssSignalBias &x)\n{\n  try\n  {\n    ar<<nameValue(\"count\", x.types.size());\n    ar.comment(\"type   bias [m]\");\n    ar.comment(\"===============================\");\n    for(UInt i=0; i<x.types.size(); i++)\n    {\n      ar.endLine();\n      ar<<nameValue(\"type\", x.types.at(i));\n      ar<<nameValue(\"bias\", x.biases.at(i));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, GnssSignalBias &x)\n{\n  try\n  {\n    UInt count;\n    ar>>nameValue(\"count\", count);\n    x.types.resize(count);\n    x.biases.resize(count);\n    for(UInt i=0; i<count; i++)\n    {\n      ar>>nameValue(\"type\", x.types.at(i));\n      ar>>nameValue(\"bias\", x.biases.at(i));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileGnssSignalBias(const FileName &fileName, const GnssSignalBias &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_GNSSSIGNALBIAS_TYPE, FILE_GNSSSIGNALBIAS_VERSION);\n    file<<nameValue(\"signalBias\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileGnssSignalBias(const FileName &fileName, GnssSignalBias &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_GNSSSIGNALBIAS_TYPE, FILE_GNSSSIGNALBIAS_VERSION);\n    file>>nameValue(\"signalBias\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileGnssSignalBias.h",
    "content": "/***********************************************/\n/**\n* @file fileGnssSignalBias.h\n*\n* @brief Code/Phase biases.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-08-11\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSSIGNALBIAS__\n#define __GROOPS_GNSSSIGNALBIAS__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_GnssSignalBias\nstatic const char *docstringGnssSignalBias = R\"(\nSignal biases of GNSS transmitters or receivers for different \\configClass{gnssType}{gnssType}.\n\n\\begin{verbatim}\ngroops gnssSignalBias version=20200123\n          5 # number of signals\n# type   bias [m]\n# ===============================\n C1CG06 -1.752461109688110974e-01\n C1WG06  4.005884595055994590e-02\n C2WG06  6.597469378913034532e-02\n L1*G06 -2.736169875580296909e-02\n L2*G06  3.422596762686257871e-02\n \\end{verbatim}\n\nSee also \\program{GnssProcessing}, \\program{GnssSimulateReceiver}, \\program{GnssSignalBias2Matrix}, \\program{GnssSignalBias2SinexBias}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/gnssType.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_GNSSSIGNALBIAS_TYPE    = \"gnssSignalBias\";\nconstexpr UInt    FILE_GNSSSIGNALBIAS_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** TYPES ***********************************/\n\nclass GnssSignalBias;\ntypedef std::shared_ptr<GnssSignalBias> GnssSignalBiasPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Code/Phase biases. */\nclass GnssSignalBias\n{\n  public:\n  std::vector<GnssType> types;\n  std::vector<Double>   biases;\n\n  Vector compute(const std::vector<GnssType> &types) const;\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const GnssSignalBias &x);\ntemplate<> void load(InArchive  &ar, GnssSignalBias &x);\n\n/** @brief Write into a GnssSignalBias file. */\nvoid writeFileGnssSignalBias(const FileName &fileName, const GnssSignalBias &x);\n\n/** @brief Read from a GnssSignalBias file. */\nvoid readFileGnssSignalBias(const FileName &fileName, GnssSignalBias &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/files/fileGriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file fileGriddedData.cpp\n*\n* @brief Read/write gridded values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_GriddedData\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileGriddedData.h\"\n\nGROOPS_REGISTER_FILEFORMAT(GriddedData, FILE_GRIDDEDDATA_TYPE)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GriddedData &x)\n{\n  // can save efficiently?\n  std::vector<Angle>  lambda, phi;\n  std::vector<Double> radius;\n  if((ar.archiveType() == OutArchive::BINARY) && x.isRectangle(lambda, phi, radius))\n  {\n    // points\n    ar<<nameValue(\"isRectangle\", TRUE);\n    ar<<nameValue(\"ellipsoid\",   x.ellipsoid);\n    ar<<nameValue(\"lambda\",      lambda);\n    ar<<nameValue(\"phi\",         phi);\n    ar<<nameValue(\"radius\",      radius);\n\n    // area elements\n    // -------------\n    if(!x.areas.size()) // empty\n    {\n      ar<<nameValue(\"dLambda\", std::vector<Double>{});\n      ar<<nameValue(\"dPhi\",    std::vector<Double>{});\n    }\n    else\n    {\n      // try to reconstruct area = dLambda * dPhi\n      std::vector<Double> dLambda(lambda.size(), 2*PI);\n      if(lambda.size() > 1)\n      {\n        dLambda.front() = std::fabs(std::remainder(lambda.at(1)-lambda.at(0), 2*PI));\n        for(UInt k=1; k<lambda.size()-1; k++)\n          dLambda.at(k) = std::fabs(0.5*std::remainder(lambda.at(k+1)-lambda.at(k-1), 2*PI));\n        dLambda.back() = std::fabs(std::remainder(lambda.at(lambda.size()-1)-lambda.at(lambda.size()-2), 2*PI));\n      }\n\n      std::vector<Double> dPhi(phi.size(), 0.);\n      for(UInt i=0; i<dPhi.size(); i++)\n        for(UInt k=0; k<dLambda.size(); k++)\n          dPhi.at(i) += x.areas.at(i*dLambda.size()+k)/(dLambda.at(k)*dLambda.size());\n\n      Bool differ = FALSE;\n      for(UInt i=0; i<dPhi.size(); i++)\n        for(UInt k=0; k<dLambda.size(); k++)\n          if(std::fabs(x.areas.at(i*dLambda.size()+k) - dPhi.at(i)*dLambda.at(k)) > 1e-8)\n          {\n            differ = TRUE;\n            ar<<nameValue(\"dLambda\", x.areas);\n            ar<<nameValue(\"dPhi\",    std::vector<Double>{1.});\n            break;\n          }\n      if(!differ)\n      {\n        ar<<nameValue(\"dLambda\", dLambda);\n        ar<<nameValue(\"dPhi\",    dPhi);\n      }\n    } // if(x.areas.size())\n\n    // values\n    ar<<nameValue(\"valueCount\", x.values.size());\n    for(UInt idx=0; idx<x.values.size(); idx++)\n      for(UInt i=0; i<x.values.at(idx).size(); i++)\n        ar<<nameValue(\"value\", x.values.at(idx).at(i));\n    return;\n  } // if(isRectangle)\n\n  const Bool hasArea = (x.areas.size() != 0);\n\n  if(ar.archiveType() == OutArchive::BINARY)\n    ar<<nameValue(\"isRectangle\",  FALSE);\n  ar<<nameValue(\"hasArea\",    hasArea);\n  ar<<nameValue(\"valueCount\", x.values.size());\n  ar<<nameValue(\"ellipsoid\",  x.ellipsoid);\n  ar<<nameValue(\"pointCount\", x.points.size());\n\n  // comment\n  std::string str = \"longitude [deg]           latitude [deg]            height [m]              \";\n  if(hasArea)\n    str += \"  unit areas [-]           \";\n   for(UInt i=0; i<x.values.size(); i++)\n   {\n     std::string str2 = \"  data\"+i%\"%i\"s;\n     str += str2 + std::string(26-str2.size(), ' ');\n   }\n   ar.comment(str);\n   ar.comment(std::string(str.size(), '='));\n\n  for(UInt i=0; i<x.points.size(); i++)\n  {\n    Angle  L,B;\n    Double h;\n    x.ellipsoid(x.points.at(i), L,B,h);\n\n    ar<<beginGroup(\"points\");\n    ar<<nameValue(\"longitude\", L);\n    ar<<nameValue(\"latitude\",  B);\n    ar<<nameValue(\"height\",    h);\n    if(hasArea)  ar<<nameValue(\"areas\",  x.areas.at(i));\n    for(UInt k=0; k<x.values.size(); k++)\n      ar<<nameValue(\"value\", x.values.at(k).at(i));\n    ar<<endGroup(\"points\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const GriddedDataRectangular &x)\n{\n  // can save efficiently?\n  if(ar.archiveType() == OutArchive::BINARY)\n  {\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius;\n    std::vector<Double> dLambda, dPhi;\n    x.geocentric(lambda, phi, radius);\n    x.areaElements(dLambda, dPhi);\n    ar<<nameValue(\"isRectangle\", TRUE);\n    ar<<nameValue(\"ellipsoid\",   x.ellipsoid);\n    ar<<nameValue(\"lambda\",      lambda);\n    ar<<nameValue(\"phi\",         phi);\n    ar<<nameValue(\"radius\",      radius);\n    ar<<nameValue(\"dLambda\",     dLambda);\n    ar<<nameValue(\"dPhi\",        dPhi);\n    ar<<nameValue(\"valueCount\",  x.values.size());\n    for(UInt id=0; id<x.values.size(); id++)\n      for(UInt i=0; i<x.values.at(id).rows(); i++)\n        for(UInt k=0; k<x.values.at(id).columns(); k++)\n          ar<<nameValue(\"value\", x.values.at(id)(i, k));\n    return;\n  }\n\n  save(ar, GriddedData(x));\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, GriddedData &x)\n{\n  // saved efficiently?\n  if((ar.archiveType() == InArchive::BINARY) && (ar.version() >= 20200123))\n  {\n    Bool isRectangle;\n    ar>>nameValue(\"isRectangle\", isRectangle);\n    if(isRectangle)\n    {\n      // points\n      std::vector<Angle>  lambda, phi;\n      std::vector<Double> radius;\n      std::vector<Double> dLambda, dPhi;\n      ar>>nameValue(\"ellipsoid\", x.ellipsoid);\n      ar>>nameValue(\"lambda\",    lambda);\n      ar>>nameValue(\"phi\",       phi);\n      ar>>nameValue(\"radius\",    radius);\n      ar>>nameValue(\"dLambda\",   dLambda);\n      ar>>nameValue(\"dPhi\",      dPhi);\n\n      std::vector<Double> cosL(lambda.size()), sinL(lambda.size());\n      for(UInt s=0; s<lambda.size(); s++)\n      {\n        cosL[s] = std::cos(lambda[s]);\n        sinL[s] = std::sin(lambda[s]);\n      }\n\n      x.points.resize(phi.size()*lambda.size());\n      for(UInt z=0; z<phi.size(); z++)\n      {\n        const Double cosPhi = std::cos(phi[z]);\n        const Double sinPhi = std::sin(phi[z]);\n        for(UInt s=0; s<lambda.size(); s++)\n          x.points[z*lambda.size()+s] = Vector3d(radius[z]*cosPhi*cosL[s], radius[z]*cosPhi*sinL[s], radius[z]*sinPhi);\n      }\n\n      // areas\n      x.areas.resize(dLambda.size()*dPhi.size());\n      for(UInt i=0; i<dPhi.size(); i++)\n        for(UInt k=0; k<dLambda.size(); k++)\n          x.areas.at(i*dLambda.size()+k) = dPhi.at(i) * dLambda.at(k);\n\n      // values\n      UInt valueCount;\n      ar>>nameValue(\"valueCount\", valueCount);\n      x.values.resize(valueCount);\n      for(UInt id=0; id<x.values.size(); id++)\n      {\n        x.values.at(id).resize(x.points.size());\n        for(UInt i=0; i<x.values.at(id).size(); i++)\n          ar>>nameValue(\"value\", x.values.at(id).at(i));\n      }\n      return;\n    }\n  }\n\n  Bool hasArea;\n  UInt valueCount;\n  UInt pointCount;\n\n  ar>>nameValue(\"hasArea\",    hasArea);\n  ar>>nameValue(\"valueCount\", valueCount);\n  ar>>nameValue(\"ellipsoid\",  x.ellipsoid);\n  ar>>nameValue(\"pointCount\", pointCount);\n\n  x.points.resize(pointCount);\n  x.areas.resize ((hasArea)  ? pointCount : 0);\n  x.values.resize(valueCount);\n  for(UInt k=0; k<x.values.size(); k++)\n    x.values.at(k).resize(pointCount);\n\n  Angle  lat, lon;\n  Double h;\n  for(UInt i=0; i<pointCount; i++)\n  {\n    ar>>beginGroup(\"points\");\n    ar>>nameValue(\"longitude\", lon);\n    ar>>nameValue(\"latitude\",  lat);\n    ar>>nameValue(\"height\",    h);\n    x.points.at(i) = x.ellipsoid(lon, lat, h);\n    if(hasArea)\n      ar>>nameValue(\"areas\",  x.areas.at(i));\n    for(UInt k=0; k<x.values.size(); k++)\n      ar>>nameValue(\"value\", x.values.at(k).at(i));\n    ar>>endGroup(\"points\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, GriddedDataRectangular &x)\n{\n  // saved efficiently?\n  if((ar.archiveType() == InArchive::BINARY) && (ar.version() >= 20200123))\n  {\n    Bool isRectangle;\n    ar>>nameValue(\"isRectangle\", isRectangle);\n    if(!isRectangle)\n      throw(Exception(\"GriddedData must be a rectangle grid\"));\n    std::vector<Double> dLambda, dPhi;\n    ar>>nameValue(\"ellipsoid\", x.ellipsoid);\n    ar>>nameValue(\"lambda\",    x.longitudes);\n    ar>>nameValue(\"phi\",       x.latitudes);\n    ar>>nameValue(\"radius\",    x.heights);\n    ar>>nameValue(\"dLambda\",   dLambda);\n    ar>>nameValue(\"dPhi\",      dPhi);\n    // points\n    Angle lon;\n    for(UInt i=0; i<x.latitudes.size(); i++)\n      x.ellipsoid(polar(Angle(0), x.latitudes.at(i), x.heights.at(i)), lon, x.latitudes.at(i), x.heights.at(i));\n    // values\n    UInt valueCount;\n    ar>>nameValue(\"valueCount\", valueCount);\n    x.values.resize(valueCount);\n    for(UInt id=0; id<x.values.size(); id++)\n    {\n      x.values.at(id) = Matrix(x.latitudes.size(), x.longitudes.size(), Matrix::NOFILL);\n      for(UInt i=0; i<x.values.at(id).rows(); i++)\n        for(UInt k=0; k<x.values.at(id).columns(); k++)\n          ar>>nameValue(\"value\", x.values.at(id)(i, k));\n    }\n    return;\n  }\n\n  GriddedData griddedData;\n  load(ar, griddedData);\n  if(!x.init(griddedData))\n    throw(Exception(\"GriddedData must be a rectangle grid\"));\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileGriddedData(const FileName &fileName, const GriddedData &x)\n{\n  try\n  {\n    if(!x.isValid())\n      throw(Exception(\"GriddedData is not valid\"));\n    OutFileArchive file(fileName, FILE_GRIDDEDDATA_TYPE, FILE_GRIDDEDDATA_VERSION);\n    file<<nameValue(\"grid\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileGriddedData(const FileName &fileName, const GriddedDataRectangular &x)\n{\n  try\n  {\n    if(!x.isValid())\n      throw(Exception(\"GriddedData is not valid\"));\n    OutFileArchive file(fileName, FILE_GRIDDEDDATA_TYPE, FILE_GRIDDEDDATA_VERSION);\n    file<<nameValue(\"grid\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\n// backward compatibility\nconst char *const FILE_GRIDRECTANGULAR_TYPE = \"gridRectangular\";\n\n// backward compatibility\nstatic void readFileGriddedDataRectangular(InFileArchive &file, GriddedDataRectangular &grid)\n{\n  file>>beginGroup(\"gridRectangular\");\n  file>>nameValue(\"ellipsoid\",  grid.ellipsoid);\n  file>>nameValue(\"longitude\",  grid.longitudes);\n  file>>nameValue(\"latitude\",   grid.latitudes);\n  file>>nameValue(\"height\",     grid.heights);\n  file>>nameValue(\"value\",      grid.values);\n  file>>endGroup(\"gridRectangular\");\n}\n\n/***********************************************/\n\nvoid readFileGriddedData(const FileName &fileName, GriddedData &x)\n{\n  try\n  {\n    InFileArchive file(fileName, \"\", FILE_GRIDDEDDATA_VERSION);\n\n    // Contain file an old rectangular grid?\n    if(file.type() == FILE_GRIDRECTANGULAR_TYPE)\n    {\n      GriddedDataRectangular rectangular;\n      readFileGriddedDataRectangular(file, rectangular);\n      x.init(rectangular);\n      return;\n    }\n\n    // check type\n    if(!file.type().empty() && (file.type() != FILE_GRIDDEDDATA_TYPE))\n      throw(Exception(\"file type is '\"+file.type()+\"' but must be '\"+FILE_GRIDDEDDATA_TYPE+\"'\"));\n\n    file>>nameValue(\"grid\", x);\n    if(!x.isValid())\n      throw(Exception(\"GriddedData is not valid\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileGriddedData(const FileName &fileName, GriddedDataRectangular &x)\n{\n  try\n  {\n    InFileArchive file(fileName, \"\", FILE_GRIDDEDDATA_VERSION);\n\n    // Contain file an old rectangular grid?\n    if(file.type() == FILE_GRIDRECTANGULAR_TYPE)\n    {\n      readFileGriddedDataRectangular(file, x);\n      return;\n    }\n\n    // check type\n    if(!file.type().empty() && (file.type() != FILE_GRIDDEDDATA_TYPE))\n      throw(Exception(\"file type is '\"+file.type()+\"' but must be '\"+FILE_GRIDDEDDATA_TYPE+\"'\"));\n\n    file>>nameValue(\"grid\", x);\n    if(!x.isValid())\n      throw(Exception(\"GriddedData is not valid\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileGriddedData.h",
    "content": "/***********************************************/\n/**\n* @file fileGriddedData.h\n*\n* @brief Read/write gridded values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEGRIDDEDDATA__\n#define __GROOPS_FILEGRIDDEDDATA__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_GriddedData\nstatic const char *docstringGriddedData = R\"(\nList of arbitrarily distributed points defined by geographic coordinates and ellipsoidal\nheight. Each point can also have an associated area\n(projected on the unit sphere with a total area of $4\\pi$).\nThis file format supports multiple values per point (called \\verb|data0|, \\verb|data1| and so on).\n\nFor regular gridded data and binary format (\\verb|*.dat|) a more efficient storage scheme is used.\n\nSee also: \\program{GriddedDataCreate}.\n\n\\begin{verbatim}\ngroops griddedData version=20200123\n 1  2  6.378137000000000000e+06  6.356752314140356146e+06 72 # hasArea, data columns, ellipoid a, ellipoid b, data rows\n# longitude [deg]           latitude [deg]            height [m]                unit areas [-]             data0                     data1\n# ===========================================================================================================================================================\n -1.650000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.350000000000000000e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.050000000000000142e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -7.500000000000001421e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -4.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.500000000000002132e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.499999999999997691e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  4.499999999999997868e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  7.499999999999997158e+01  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.049999999999999574e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.349999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n  1.649999999999999432e+02  7.500000000000000000e+01  0.000000000000000000e+00  7.014893453974438420e-02  1.000000000000000000e+00  2.000000000000000000e+00\n -1.650000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00\n -1.350000000000000000e+02  4.500000000000000711e+01  0.000000000000000000e+00  1.916504532594049681e-01  1.000000000000000000e+00  2.000000000000000000e+00\n\\end{verbatim}\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/griddedData.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_GRIDDEDDATA_TYPE    = \"griddedData\";\nconstexpr UInt    FILE_GRIDDEDDATA_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const GriddedData &x);\ntemplate<> void save(OutArchive &ar, const GriddedDataRectangular &x);\ntemplate<> void load(InArchive  &ar, GriddedData &x);\ntemplate<> void load(InArchive  &ar, GriddedDataRectangular &x);\n\n/** @brief Write into a GriddedData file. */\nvoid writeFileGriddedData(const FileName &fileName, const GriddedData &x);\nvoid writeFileGriddedData(const FileName &fileName, const GriddedDataRectangular &x);\n\n/** @brief Read from a GriddedData file. */\nvoid readFileGriddedData(const FileName &fileName, GriddedData &x);\nvoid readFileGriddedData(const FileName &fileName, GriddedDataRectangular &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileGriddedDataTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file fileGriddedDataTimeSeries.cpp\n*\n* @brief Read/write time series of gridded values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-07-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_GriddedDataTimeSeries\n\n#include \"base/import.h\"\n#include \"base/basisSplines.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n\nGROOPS_REGISTER_FILEFORMAT(GriddedDataTimeSeries, FILE_GRIDDEDDATATIMESERIES_TYPE)\n\n/***********************************************/\n\nvoid InFileGriddedDataTimeSeries::open(const FileName &name)\n{\n  try\n  {\n    close();\n    if(!name.empty())\n    {\n      UInt epochCount;\n\n      file.open(name, FILE_GRIDDEDDATATIMESERIES_TYPE, FILE_GRIDDEDDATATIMESERIES_VERSION);\n      file>>nameValue(\"splineDegree\", splineDegree_);\n      file>>nameValue(\"timeCount\",    epochCount);\n      file>>nameValue(\"dataCount\",    dataCount_);\n      file>>nameValue(\"grid\",         grid_);\n      times_.resize(epochCount);\n      for(UInt i=0; i<times_.size(); i++)\n        file>>nameValue(\"time\", times_.at(i));\n\n      // If we have a binary file, we can efficiently seek to the needed position in the file.\n      if(file.canSeek())\n        seekStart = file.position();\n      seekSize = 0;\n\n      indexFile = 0;\n      indexData = nodeCount();\n      data_.resize(splineDegree_+1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nvoid InFileGriddedDataTimeSeries::close()\n{\n  file.close();\n  grid_ = GriddedData();\n  times_.clear();\n  dataCount_    = 0;\n  splineDegree_ = 0;\n}\n\n/***********************************************/\n\nMatrix InFileGriddedDataTimeSeries::data(UInt idNode) // points x data columns\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n\n    // must restart?\n    if(indexFile > idNode)\n    {\n      if(file.canSeek() && seekSize)\n        indexFile = 0;\n      else\n        open(file.fileName());\n    }\n\n    Matrix data(grid_.points.size(), dataCount_, Matrix::NOFILL);\n    while(indexFile <= idNode)\n    {\n      // Seek to appropriate interval.\n      if(file.canSeek() && seekSize)\n      {\n        file.seek(seekStart + static_cast<std::streamoff>(idNode * seekSize));\n        indexFile = idNode;\n      }\n\n      file>>beginGroup(\"node\");\n      for(UInt i=0; i<grid_.points.size(); i++)\n      {\n        file>>beginGroup(\"points\");\n        for(UInt k=0; k<dataCount_; k++)\n          file>>nameValue(\"value\", data(i, k));\n        file>>endGroup(\"points\");\n      }\n      file>>endGroup(\"node\");\n\n      if(file.canSeek() && (indexFile == 0))\n        seekSize = file.position() - seekStart;\n      indexFile++;\n    }\n\n    return data;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix InFileGriddedDataTimeSeries::data(const Time &time)\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n    if((time < times_.front()) || (time > times_.back()))\n      throw(Exception(time.dateTimeStr()+\" outside interval [\"+times_.front().dateTimeStr()+\", \"+times_.back().dateTimeStr()+\"] of <\"+file.fileName().str()+\">\"));\n\n    // find time interval and read missing nodes\n    const UInt idx   = std::min(static_cast<UInt>(std::distance(times_.begin(), std::upper_bound(times_.begin(), times_.end(), time))), times_.size()-1)-1;\n    const UInt start = (idx > indexData) ? std::max(idx, indexData+data_.size()) : idx;\n    const UInt end   = (idx > indexData) ? idx+data_.size() : std::min(idx+data_.size(), indexData);\n    for(UInt i=start; i<end; i++)\n      data_.at(i%data_.size()) = data(i);\n    indexData = idx;\n\n    // spline interploation in interval\n    const Double t     = (time-times_.at(idx)).mjd()/(times_.at(idx+1)-times_.at(idx)).mjd();\n    const Vector coeff = BasisSplines::compute(t, splineDegree_);\n    Matrix data = coeff(0) * data_.at(indexData%data_.size());\n    for(UInt i=1; i<coeff.rows(); i++)\n      axpy(coeff(i), data_.at((indexData+i)%data_.size()), data);\n    return data;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileGriddedDataTimeSeries(const FileName &fileName, UInt splineDegree, const std::vector<Time> &times,\n                                    const GriddedData &grid, const std::vector<Matrix> &data)\n{\n  try\n  {\n    if(!grid.isValid())\n      throw(Exception(\"GriddedData is not valid\"));\n    if(times.size()+splineDegree != data.size()+1)\n      throw(Exception(\"spline degree, times.size(), and data.size() not fit\"));\n    const UInt dataCount = (data.size() ? data.front().columns() : 0);\n\n    OutFileArchive file(fileName, FILE_GRIDDEDDATATIMESERIES_TYPE, FILE_GRIDDEDDATATIMESERIES_VERSION);\n    file<<nameValue(\"splineDegree\", splineDegree);\n    file<<nameValue(\"timeCount\",    times.size());\n    file<<nameValue(\"dataCount\",    dataCount);\n    file<<nameValue(\"grid\",         grid);\n    file.comment(\"times\");\n    file.comment(\"=====\");\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      file<<nameValue(\"time\", times.at(idEpoch));\n    for(UInt idEpoch=0; idEpoch<data.size(); idEpoch++)\n    {\n      file<<beginGroup(\"node\");\n\n      // comment\n      std::string str;\n      for(UInt i=0; i<dataCount; i++)\n      {\n        std::string str2 = \"data\"+i%\"%i\"s;\n        str += str2 + std::string(26-str2.size(), ' ');\n      }\n      file.comment(times.at(idEpoch).dateTimeStr());\n      file.comment(str);\n      file.comment(std::string(str.size(), '='));\n\n      for(UInt i=0; i<grid.points.size(); i++)\n      {\n        file<<beginGroup(\"points\");\n        for(UInt k=0; k<dataCount; k++)\n          file<<nameValue(\"value\", data.at(idEpoch)(i, k));\n        file<<endGroup(\"points\");\n      }\n      file<<endGroup(\"node\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileGriddedDataTimeSeries.h",
    "content": "/***********************************************/\n/**\n* @file fileGriddedDataTimeSeries.h\n*\n* @brief Read/write time series of gridded values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-07-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEGRIDDEDDATATIMESERIES__\n#define __GROOPS_FILEGRIDDEDDATATIMESERIES__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_GriddedDataTimeSeries\nstatic const char *docstringGriddedDataTimeSeries = R\"(\nTime series of data for arbitrarily distributed points defined by geographic coordinates and ellipsoidal\nheight. The data can be temporal interpolated by \\reference{basis splines}{fundamentals.basisSplines}.\nThe file format consists of a \\file{griddedData}{griddedData}, a time series, and\nfor each spatial point and spline node pair multiple values called \\verb|data0|, \\verb|data1|, \\ldots.\n\nA GriddedDataTimeSeries can be generated from individual \\file{griddedData}{griddedData} with the program\n\\program{GriddedData2GriddedDataTimeSeries}. Vice-versa, a GriddedDataTimeSeries can be evaluated at a\nspecific time stamp to obtain a \\file{griddedData}{griddedData} with \\program{GriddedDataTimeSeries2GriddedData}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/griddedData.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_GRIDDEDDATATIMESERIES_TYPE    = \"griddedDataTimeSeries\";\nconstexpr UInt    FILE_GRIDDEDDATATIMESERIES_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of gridded values. */\nclass InFileGriddedDataTimeSeries\n{\n  InFileArchive       file;\n  UInt                splineDegree_, dataCount_;\n  GriddedData         grid_;\n  std::vector<Time>   times_;\n  UInt                indexFile, indexData;\n  std::streampos      seekStart;\n  std::streamoff      seekSize;\n  std::vector<Matrix> data_;\n\npublic:\n  InFileGriddedDataTimeSeries() : splineDegree_(0), dataCount_(0) {}\n  InFileGriddedDataTimeSeries(const FileName &name) {open(name);}\n ~InFileGriddedDataTimeSeries() {close();}\n\n  void open(const FileName &name);\n  void close();\n\n  UInt splineDegree() const {return splineDegree_;}\n  UInt nodeCount()    const {return times_.size()+splineDegree_-1;}  //!< number of spline nodal points (agree with times().size() for spline degree 1)\n  UInt dataCount()    const {return dataCount_;}                     //!< number of data columns\n\n  const GriddedData       &grid()  const {return grid_;}\n  const std::vector<Time> &times() const {return times_;}\n\n  /// data(points x data columns) at spline nodal point\n  Matrix data(UInt idNode);\n\n  /// data(points x data columns) interpolated at @p time.\n  Matrix data(const Time &time);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a GriddedData time series file. */\nvoid writeFileGriddedDataTimeSeries(const FileName &fileName, UInt splineDegree, const std::vector<Time> &times,\n                                    const GriddedData &grid, const std::vector<Matrix> &data);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileInstrument.cpp",
    "content": "/***********************************************/\n/**\n* @file fileInstrument.cpp\n*\n* @brief Satellites instrument data organized in arcs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-29\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_Instrument\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\nGROOPS_REGISTER_FILEFORMAT(Instrument, FILE_INSTRUMENT_TYPE)\n\n/***********************************************/\n\nclass MiscValuesOldEpoch : public MiscValuesEpoch\n{\npublic:\n  MiscValuesOldEpoch() : MiscValuesEpoch(0) {}\n  virtual void load(InArchive  &ia) override;\n};\n\n/***********************************************/\n\nEpoch *Epoch::create(Type type)\n{\n  try\n  {\n    if(type > 0)\n      return new MiscValuesEpoch(type);\n    switch(type)\n    {\n      case Epoch::INSTRUMENTTIME:        return new InstrumentTimeEpoch();\n      case Epoch::MISCVALUE:             return new MiscValueEpoch();\n      case Epoch::VECTOR3D:              return new Vector3dEpoch();\n      case Epoch::COVARIANCE3D:          return new Covariance3dEpoch();\n      case Epoch::ORBIT:                 return new OrbitEpoch();\n      case Epoch::STARCAMERA:            return new StarCameraEpoch();\n      case Epoch::ACCELEROMETER:         return new AccelerometerEpoch();\n      case Epoch::SATELLITETRACKING:     return new SatelliteTrackingEpoch();\n      case Epoch::GRADIOMETER:           return new GradiometerEpoch();\n      case Epoch::GNSSRECEIVER:          return new GnssReceiverEpoch();\n      case Epoch::OBSERVATIONSIGMA:      return new ObservationSigmaEpoch();\n      case Epoch::MASS:                  return new MassEpoch();\n      case Epoch::THRUSTER:              return new ThrusterEpoch();\n      case Epoch::MAGNETOMETER:          return new MagnetometerEpoch();\n      case Epoch::ACCHOUSEKEEPING:       return new AccHousekeepingEpoch();\n      case Epoch::CLOCK:                 return new ClockEpoch();\n      case Epoch::STARCAMERA1A:          return new StarCamera1AEpoch();\n      case Epoch::ACCELEROMETER1A:       return new Accelerometer1AEpoch();\n      case Epoch::SATELLITELASERRANGING: return new SatelliteLaserRangingEpoch();\n      case Epoch::METEOROLOGICAL:        return new MeteorologicalEpoch();\n      case Epoch::MISCVALUESOLD:         return new MiscValuesOldEpoch();\n      case Epoch::MISCVALUES:            break;\n      case Epoch::EMPTY:                 break;\n    }\n\n    throw(Exception(\"unknown instrument type (\"+static_cast<Int>(type)%\"%i)\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string Epoch::getTypeName(Type type)\n{\n  try\n  {\n    if(type > 0)\n      return \"MISCVALUES(\"+static_cast<Double>(type)%\"%i)\"s;\n    switch(type)\n    {\n      case Epoch::MISCVALUE:             return \"MISCVALUE\";\n      case Epoch::INSTRUMENTTIME:        return \"INSTRUMENTTIME\";\n      case Epoch::VECTOR3D:              return \"VECTOR3D\";\n      case Epoch::COVARIANCE3D:          return \"COVARIANCE3D\";\n      case Epoch::ORBIT:                 return \"ORBIT\";\n      case Epoch::STARCAMERA:            return \"STARCAMERA\";\n      case Epoch::ACCELEROMETER:         return \"ACCELEROMETER\";\n      case Epoch::SATELLITETRACKING:     return \"SATELLITETRACKING\";\n      case Epoch::GRADIOMETER:           return \"GRADIOMETER\";\n      case Epoch::GNSSRECEIVER:          return \"GNSSRECEIVER\";\n      case Epoch::OBSERVATIONSIGMA:      return \"OBSERVATIONSIGMA\";\n      case Epoch::MASS:                  return \"MASS\";\n      case Epoch::THRUSTER:              return \"THRUSTER\";\n      case Epoch::MAGNETOMETER:          return \"MAGNETOMETER\";\n      case Epoch::ACCHOUSEKEEPING:       return \"ACCHOUSEKEEPING\";\n      case Epoch::CLOCK:                 return \"CLOCK\";\n      case Epoch::STARCAMERA1A:          return \"STARCAMERA1A\";\n      case Epoch::ACCELEROMETER1A:       return \"ACCELEROMETER1A\";\n      case Epoch::SATELLITELASERRANGING: return \"SATELLITELASERRANGING\";\n      case Epoch::METEOROLOGICAL:        return \"METEOROLOGICAL\";\n      case Epoch::MISCVALUESOLD:         return \"MISCVALUES\";\n      case Epoch::MISCVALUES:            return \"MISCVALUES(0)\";\n      case Epoch::EMPTY:                 return \"EMPTY\";\n    }\n    return \"unknown\";\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string Epoch::fileFormatString(Type type)\n{\n  try\n  {\n    if(type > 0) // MISCVALUES\n    {\n      std::string str = \"Time [MJD]             \";\n      for(Int i=0; i<type; i++)\n      {\n        std::string str2 = \"  data\"+i%\"%i\"s;\n        str += str2 + std::string(26-str2.size(), ' ');\n      }\n      return str;\n    }\n\n    switch(type)\n    {                                       // \"Time [MJD]             |                         |                         |                         |                         |                         |                         |                         |                         |                         |\n      case Epoch::MISCVALUE:             return \"Time [MJD]               data0                   \";\n      case Epoch::INSTRUMENTTIME:        return \"Time [MJD]             \";\n      case Epoch::VECTOR3D:              return \"Time [MJD]               data0: x                  data1: y                  data2: z                \";\n      case Epoch::COVARIANCE3D:          return \"Time [MJD]               data0: xx                 data1: yy                 data2: zz                 data3: xy                 data4: xz                 data5: yz               \";\n      case Epoch::ORBIT:                 return \"Time [MJD]               data0: pos x [m]          data1: pos y [m]          data2: pos z [m]          data3: vel x [m/s]        data4: vel y [m/s]        data5: vel z [m/s]        data6: acc x [m/s^2]      data7: acc y [m/s^2]      data8: acc z [m/s^2]    \";\n      case Epoch::STARCAMERA:            return \"Time [MJD]               data0: quaternion 0       data1: quaternion x       data2: quaternion y       data3: quaternion z     \";\n      case Epoch::ACCELEROMETER:         return \"Time [MJD]               data0: x [m/s^2]          data1: y [m/s^2]          data2: z [m/s^2]        \";\n      case Epoch::SATELLITETRACKING:     return \"Time [MJD]               data0: range [m]          data1: range-rate [m/s]   data2: range-acc [m/s^2]\";\n      case Epoch::GRADIOMETER:           return \"Time [MJD]               data0: xx [1/s^2]         data1: yy [1/s^2]         data2: zz [1/s^2]         data3: xy [1/s^2]         data4: xz [1/s^2]         data5: yz [1/s^2]       \";\n      case Epoch::GNSSRECEIVER:          return \"\";\n      case Epoch::OBSERVATIONSIGMA:      return \"Time [MJD]               data0: sigma            \";\n      case Epoch::SATELLITELASERRANGING: return \"Time [MJD]               data0: range [m]          data1: accuracy [m]       data2: redundancy         data3: window [s]         data4: wavelength [m]     data5: azmiuth [rad]      data6: elevation [rad]  \";\n      case Epoch::METEOROLOGICAL:        return \"Time [MJD]               data0: temperature [K]    data1: pressure [Pa]      data2: humidity [%]       data3: windSpeed [m/s]    data4: radiation [W/m^2]  data5: precip. [mm/d]   \";\n      default:                           return \"\";\n//       case Epoch::MASS:                 return \"MASS\";\n//       case Epoch::THRUSTER:             return \"THRUSTER\";\n//       case Epoch::MAGNETOMETER:         return \"MAGNETOMETER\";\n//       case Epoch::ACCHOUSEKEEPING:      return \"ACCHOUSEKEEPING\";\n//       case Epoch::CLOCK:                return \"CLOCK\";\n//       case Epoch::STARCAMERA1A:         return \"STARCAMERA1A\";\n//       case Epoch::ACCELEROMETER1A:      return \"ACCELEROMETER1A\";\n//       case Epoch::MISCVALUESOLD:        return \"MISCVALUES\";\n//       case Epoch::EMPTY:                return \"EMPTY\";\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt Epoch::dataCount(Type type, Bool mustDefined)\n{\n  try\n  {\n    if(type > 0)\n      return static_cast<UInt>(type);\n    switch(type)\n    {\n      case Epoch::INSTRUMENTTIME:        return 0;\n      case Epoch::MISCVALUE:             return 1;\n      case Epoch::VECTOR3D:              return 3;\n      case Epoch::COVARIANCE3D:          return 6;\n      case Epoch::ORBIT:                 return 9;\n      case Epoch::STARCAMERA:            return 4;\n      case Epoch::ACCELEROMETER:         return 3;\n      case Epoch::SATELLITETRACKING:     return 3;\n      case Epoch::GRADIOMETER:           return 6;\n      case Epoch::OBSERVATIONSIGMA:      return 1;\n      case Epoch::MASS:                  return 2;\n      case Epoch::THRUSTER:              return 14;\n      case Epoch::MAGNETOMETER:          return 13;\n      case Epoch::ACCHOUSEKEEPING:       return 13;\n      case Epoch::CLOCK:                 return 6;\n      case Epoch::STARCAMERA1A:          return 9;\n      case Epoch::ACCELEROMETER1A:       return 5;\n      case Epoch::SATELLITELASERRANGING: return 7;\n      case Epoch::METEOROLOGICAL:        return 6;\n      case Epoch::GNSSRECEIVER:          if(mustDefined) throw(Exception(\"GNSSRECEIVER: Data columns not defined.\")); return NULLINDEX;\n      case Epoch::MISCVALUESOLD:         if(mustDefined) throw(Exception(\"Cannot determine the number of data columns of old file format (use FileConvert)\")); return NULLINDEX;\n      case Epoch::MISCVALUES:            if(mustDefined) throw(Exception(\"EMPTY: Cannot determine the number of data columns.\")); return NULLINDEX;\n      case Epoch::EMPTY:                 if(mustDefined) throw(Exception(\"EMPTY: Cannot determine the number of data columns.\")); return NULLINDEX;\n    }\n    throw(Exception(\"unknown instrument type (\"+static_cast<Int>(type)%\"%i)\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nArc::Arc(const Arc &x) : epoch(x.epoch.size())\n{\n  try\n  {\n    for(UInt i=0; i<epoch.size(); i++)\n      epoch.at(i) = std::unique_ptr<Epoch>(x.epoch.at(i)->clone());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nArc::Arc(const_MatrixSliceRef A, Epoch::Type type)\n{\n  try\n  {\n    if(type == Epoch::EMPTY)\n    {\n      if(A.columns() == 1) type = Epoch::INSTRUMENTTIME;\n      if(A.columns() == 2) type = Epoch::MISCVALUE;\n      if(A.columns() >= 3) type = static_cast<Epoch::Type>(A.columns()-1);\n    }\n\n    epoch.resize(A.rows());\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      epoch.at(i) = std::unique_ptr<Epoch>(Epoch::create(type));\n      epoch.at(i)->time = mjd2time(A(i,0));\n      if(A.columns() > 1)\n        epoch.at(i)->setData(A.slice(i,1,1,A.columns()-1).trans());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nArc::Arc(const std::vector<Time> &times, const_MatrixSliceRef A, Epoch::Type type) : Arc(A, type)\n{\n  try\n  {\n    if(times.size() != A.rows())\n      throw(Exception(\"Dimension error: times.size = \"+times.size()%\"%i, A(\"s+A.rows()%\"%i x \"s+A.columns()%\"%i)\"s));\n    for(UInt i=0; i<size(); i++)\n      at(i).time = times.at(i);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nArc &Arc::operator=(const Arc &x)\n{\n  try\n  {\n    epoch.resize(x.epoch.size());\n    for(UInt i=0; i<x.epoch.size(); i++)\n      epoch.at(i) = std::unique_ptr<Epoch>(x.epoch.at(i)->clone());\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::sort()\n{\n  try\n  {\n    std::stable_sort(epoch.begin(), epoch.end(), [](const std::unique_ptr<Epoch> &x, const std::unique_ptr<Epoch> &y) {return x->time < y->time;});\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::removeDuplicateEpochs(Bool keepFirst, Double margin)\n{\n  try\n  {\n    if(keepFirst)\n    {\n      auto new_end = std::unique(epoch.begin(), epoch.end(), [&](const std::unique_ptr<Epoch> &x, const std::unique_ptr<Epoch> &y) {return std::fabs((x->time-y->time).seconds()) < margin;});\n      epoch.erase(new_end, epoch.end());\n    }\n    else\n    {\n      auto new_end = std::unique(epoch.rbegin(), epoch.rend(), [&](const std::unique_ptr<Epoch> &x, const std::unique_ptr<Epoch> &y) {return std::fabs((x->time-y->time).seconds()) < margin;});\n      epoch.erase(epoch.begin(), new_end.base());\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nArc Arc::subArc(UInt start, UInt len) const\n{\n  try\n  {\n    if(len==0)\n      return Arc();\n    if((start+len)>size())\n      throw(Exception(\"Length of sub-arc (\"+len%\"%i) starting at (\"s+start%\"%i) exceeds arc length (\"s+size()%\"%i).\"s));\n\n    Arc arc;\n    arc.epoch.resize(len);\n    for(UInt i=0; i<len; i++)\n      arc.epoch.at(i) = std::unique_ptr<Epoch>(epoch.at(start+i)->clone());\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::remove(UInt start, UInt len)\n{\n  try\n  {\n    if(len==0)\n      return;\n    if(start+len>size())\n      throw(Exception(\"Length of sub-arc (\"+len%\"%i) starting at (\"s+start%\"%i) exceeds arc length (\"s+size()%\"%i).\"s));\n    epoch.erase(epoch.begin()+start, epoch.begin()+(start+len));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::append(const Arc &arc)\n{\n  try\n  {\n    if(&arc==this)\n      throw(Exception(\"append same arc: not implemented\"));\n    if(arc.size() == 0)\n      return;\n    checkType(arc.getType());\n\n    const UInt index = size();\n    epoch.resize(index+arc.size());\n    for(UInt i=0; i<arc.size(); i++)\n      epoch.at(i+index) = std::unique_ptr<Epoch>(arc.epoch.at(i)->clone());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::synchronize(const std::vector<Time> &time, Double margin)\n{\n  try\n  {\n    if(size() == 0)\n      return;\n    UInt idxT=0, idxE=0, idxW = 0;\n    for(;;)\n    {\n      if(idxE>=epoch.size())\n        break;\n      while((idxT<time.size())  && ((time.at(idxT)-epoch.at(idxE)->time).seconds() < -margin))\n        idxT++;\n      if(idxT>=time.size())\n        break;\n      while((idxE<epoch.size()) && ((time.at(idxT)-epoch.at(idxE)->time).seconds() > +margin))\n        idxE++;\n      if(idxE>=epoch.size())\n        break;\n      if(std::fabs((time.at(idxT)-epoch.at(idxE)->time).seconds()) > margin)\n        break;\n      epoch.at(idxW++) = std::move(epoch.at(idxE++));\n    }\n    epoch.resize(idxW);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::divide(const Time &minGap, UInt minArcLen, std::vector<Arc> &arcList) const\n{\n  try\n  {\n    if(size() == 0)\n      return;\n\n    // quick return possible?\n    if((minGap == Time()) && (size() >= minArcLen))\n    {\n      arcList.push_back(*this);\n      return;\n    }\n\n    UInt index = 0;\n    while(index<size())\n    {\n      // find time gap\n      UInt len = 1;\n      while((index+len<size()) && ((epoch.at(index+len)->time-epoch.at(index+len-1)->time) < minGap))\n        len++;\n      if(len>=minArcLen)\n        arcList.push_back(subArc(index,len));\n      index += len;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::insert(UInt index, const Epoch &e)\n{\n  try\n  {\n    checkType(e.getType());\n    epoch.insert(epoch.begin()+index, std::unique_ptr<Epoch>(e.clone()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::push_back(const Epoch &e)\n{\n  try\n  {\n    checkType(e.getType());\n    epoch.push_back(std::unique_ptr<Epoch>(e.clone()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Time> Arc::times() const\n{\n  std::vector<Time> time(epoch.size());\n  for(UInt i=0; i<epoch.size(); i++)\n    time.at(i) = epoch.at(i)->time;\n  return time;\n}\n\n/***********************************************/\n\nMatrix Arc::matrix() const\n{\n  try\n  {\n    if(!size())\n      return Matrix();\n    Matrix A(size(), 1+at(0).data().rows(), Matrix::NOFILL);\n    for(UInt i=0; i<size(); i++)\n      A(i,0) = at(i).time.mjd();\n\n    if(A.columns()>1)\n      for(UInt i=0; i<size(); i++)\n        copy(at(i).data().trans(), A.slice(i,1,1,A.columns()-1));\n\n    if(getType() == Epoch::STARCAMERA)\n      for(UInt i=1; i<size(); i++)\n        if(inner(A.slice(i-1,1,1,4), A.slice(i,1,1,4))<0)\n         A.slice(i,1,1,4) *= -1.;\n\n    return A;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::checkSynchronized(const std::vector<std::reference_wrapper<const Arc>> &arcList)\n{\n  std::vector<Time> timesOld;\n  for(const Arc &arc : arcList)\n  {\n    const std::vector<Time> times = arc.times();\n    if(!timesOld.size())\n      timesOld = times;\n    if(times.size() && timesOld.size() && (times != timesOld))\n      throw(Exception(\"instrument arc \"+arc.getTypeName()+\" is not synchronous with the other arcs\"));\n  }\n}\n\n/***********************************************/\n\nvoid Arc::printStatistics(const Arc &arc)\n{\n  printStatistics(std::vector<Arc>(1, arc));\n}\n\n/***********************************************/\n\nvoid Arc::printStatistics(const std::vector<Arc> &arcList)\n{\n  try\n  {\n    // number of epochs\n    // ----------------\n    UInt epochCount = 0;\n    for(UInt arcNo=0; arcNo<arcList.size(); arcNo++)\n      epochCount += arcList.at(arcNo).size();\n\n    if(epochCount == 0)\n    {\n      logInfo<<\"  arc count: \"<<arcList.size()<<Log::endl;\n      logInfo<<\"  epochs:    \"<<epochCount<<Log::endl;\n      return;\n    }\n\n    // test times\n    // ----------\n    Bool notSorted = FALSE;\n    UInt duplicateCount = 0;\n    Time timeStart = date2time(9999,1,1), timeEnd, timeLast = date2time(-9999,1,1);\n    for(UInt arcNo=0; arcNo<arcList.size(); arcNo++)\n      for(UInt i=0; i<arcList.at(arcNo).size(); i++)\n      {\n        if(arcList.at(arcNo).at(i).time == timeLast)\n          duplicateCount++;\n        if(arcList.at(arcNo).at(i).time < timeLast)\n          notSorted = TRUE;\n        timeLast  = arcList.at(arcNo).at(i).time;\n        timeStart = std::min(timeStart, timeLast);\n        timeEnd   = std::max(timeEnd,   timeLast);\n      }\n\n    logInfo<<\"  time start:      \"<<timeStart.dateTimeStr()<<Log::endl;\n    logInfo<<\"  time end:        \"<<timeEnd.dateTimeStr()<<Log::endl;\n    logInfo<<\"  epochs:          \"<<epochCount<<Log::endl;\n    if(notSorted)\n    {\n      logWarning<<\"  epochs are not sorted!\"<<Log::endl;\n      return;\n    }\n    if(duplicateCount)\n      logInfo<<\"  duplicates:      \"<<duplicateCount<<Log::endl;\n\n    // median sampling\n    // ---------------\n    std::vector<Time> times;\n    for(const Arc &arc : arcList)\n    {\n      auto arcTimes = arc.times();\n      times.insert(times.end(), arcTimes.begin(), arcTimes.end());\n    }\n    const Double sampling = medianSampling(times).seconds();\n    logInfo<<\"  median sampling: \"<<sampling<<\" seconds\"<<Log::endl;\n\n    // arc statistics\n    // --------------\n    if(arcList.size() == 1)\n    {\n      UInt countGaps = 0;\n      for(UInt i=1; i<arcList.at(0).size(); i++)\n        if((arcList.at(0).at(i).time-arcList.at(0).at(i-1).time).seconds() > 1.5*sampling)\n          countGaps++;\n      logInfo<<\"  gaps:            \"<<countGaps<<Log::endl;\n    }\n    else\n    {\n      Double  meanLen  = 0;\n      UInt    maxLen   = 0;\n      UInt    minLen   = MAX_UINT;\n      Time    maxTime;\n      Time    minTime = seconds2time(100*365*86400.);\n      Time    meanTime;\n\n      for(UInt arcNo=0; arcNo<arcList.size(); arcNo++)\n      {\n        UInt size = arcList.at(arcNo).size();\n        if(size==0)\n          continue;\n        Time time = arcList.at(arcNo).at(size-1).time - arcList.at(arcNo).at(0).time;\n\n        maxLen   = std::max(maxLen, size);\n        minLen   = std::min(minLen, size);\n        meanLen += size;\n\n        maxTime   = std::max(maxTime, time);\n        minTime   = std::min(minTime, time);\n        meanTime += time;\n      }\n\n      UInt minCount = 0;\n      UInt maxCount = 0;\n      for(UInt arcNo=0; arcNo<arcList.size(); arcNo++)\n      {\n        if(maxLen == arcList.at(arcNo).size()) maxCount++;\n        if(minLen == arcList.at(arcNo).size()) minCount++;\n      }\n\n      meanLen  *= 1./arcList.size();\n      meanTime *= 1./arcList.size();\n\n      logInfo<<\"  arc count:       \"<<arcList.size()<<Log::endl;\n      logInfo<<\"  max. arc length: \"<<maxTime.str() <<\" with \"<<maxLen <<\" epochs\\t (\"<<maxCount<<\" arcs)\"<<Log::endl;\n      logInfo<<\"  min. arc length: \"<<minTime.str() <<\" with \"<<minLen <<\" epochs\\t (\"<<minCount<<\" arcs)\"<<Log::endl;\n      logInfo<<\"  mean arc length: \"<<meanTime.str()<<\" with \"<<meanLen<<\" epochs\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Arc::load(InArchive  &ia)\n{\n  try\n  {\n    UInt typeInt, count;\n    ia>>nameValue(\"type\",       typeInt);\n    ia>>nameValue(\"pointCount\", count);\n    epoch.resize(count);\n    for(UInt i=0; i<count; i++)\n    {\n      ia>>beginGroup(\"epoch\");\n      epoch.at(i) = std::unique_ptr<Epoch>(Epoch::create(static_cast<Epoch::Type>(typeInt)));\n      epoch.at(i)->load(ia);\n      ia>>endGroup(\"epoch\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Arc::save(OutArchive &oa) const\n{\n  oa<<nameValue(\"type\",       static_cast<Int>(getType()));\n  oa<<nameValue(\"pointCount\", size());\n  std::string comment = Epoch::fileFormatString(getType());\n  oa.comment(comment);\n  oa.comment(std::string(comment.size(), '='));\n  for(UInt i=0; i<size(); i++)\n  {\n    oa<<beginGroup(\"epoch\");\n    epoch.at(i)->save(oa);\n    oa<<endGroup(\"epoch\");\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid InstrumentFile::open(const FileName &name)\n{\n  try\n  {\n    close();\n    if(!name.empty())\n    {\n      file.open(name, \"\"/*arbitrary type*/, std::max(FILE_INSTRUMENT_VERSION, FILE_MATRIX_VERSION));\n      fileName = name;\n      index = 0;\n      if(file.type() == FILE_INSTRUMENT_TYPE)\n      {\n        if(file.version() < 20200123)\n        {\n          UInt typeInt;\n          file>>nameValue(\"satelliteType\", typeInt);\n          switch(typeInt)\n          {\n            case  0: type = Epoch::EMPTY;                break;\n            case 23: type = Epoch::MISCVALUESOLD;        break;\n            case 15: type = Epoch::INSTRUMENTTIME;       break;\n            case 22: type = Epoch::MISCVALUE;            break;\n            case 24: type = Epoch::VECTOR3D;             break;\n            case  8: type = Epoch::COVARIANCE3D;         break;\n            case  1: type = Epoch::ORBIT;                break;\n            case  2: type = Epoch::STARCAMERA;           break;\n            case  3: type = Epoch::ACCELEROMETER;        break;\n            case  5: type = Epoch::SATELLITETRACKING;    break;\n            case  4: type = Epoch::GRADIOMETER;          break;\n            case 13: type = Epoch::GNSSRECEIVER;         break;\n            case 20: type = Epoch::OBSERVATIONSIGMA;     break;\n            case 19: type = Epoch::MASS;                 break;\n            case 17: type = Epoch::THRUSTER;             break;\n            case 18: type = Epoch::MAGNETOMETER;         break;\n            case 21: type = Epoch::ACCHOUSEKEEPING;      break;\n            case 26: type = Epoch::CLOCK;                break;\n            case 25: type = Epoch::STARCAMERA1A;         break;\n            case 27: type = Epoch::ACCELEROMETER1A;      break;\n            default: throw(Exception(\"unsupported old instrument type\"));\n          }\n        }\n        else\n        {\n          Int typeInt;\n          file>>nameValue(\"satelliteType\", typeInt);\n          type = static_cast<Epoch::Type>(typeInt);\n        }\n        file>>nameValue(\"arcCount\", arcCount_);\n      }\n      else if(file.type().empty() || (file.type() == FILE_MATRIX_TYPE))\n      {\n        arcCount_ = 1;\n        file>>nameValue(\"matrix\", A);\n        if(A.columns() == 0) type = Epoch::EMPTY;\n        if(A.columns() == 1) type = Epoch::INSTRUMENTTIME;\n        if(A.columns() == 2) type = Epoch::MISCVALUE;\n        if(A.columns() >= 3) type = static_cast<Epoch::Type>(A.columns()-1);\n      }\n      else\n        throw(Exception(\"file type is '\"+file.type()+\"' but must be '\"+FILE_INSTRUMENT_TYPE+\"' or '\"+FILE_MATRIX_TYPE+\"'\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentFile::close()\n{\n  if(!fileName.empty())\n    file.close();\n  fileName  = FileName();\n  arcCount_ = 0;\n  type      = Epoch::EMPTY;\n}\n\n/***********************************************/\n\nArc InstrumentFile::readArc(UInt i)\n{\n  try\n  {\n    if(fileName.empty())\n      return Arc();\n\n    if(i>=arcCount_)\n      throw(Exception(\"index >= arcCount\"));\n\n    // behind arc in file -> restart at beginning\n    if(i<index)\n      open(FileName(fileName));\n\n    // special case: convert matrix to instrument arc\n    if(file.type().empty() || (file.type() == FILE_MATRIX_TYPE))\n    {\n      Matrix B;\n      std::swap(A, B);\n      index++;\n      return Arc(B, type);\n    }\n\n    Arc arc;\n    std::unique_ptr<Epoch> epoch;\n    while(index <= i)\n    {\n      arc = Arc();\n      UInt count;\n      file>>beginGroup(\"arc\");\n      file>>nameValue(\"pointCount\", count);\n      for(UInt i=0; i<count; i++)\n      {\n        if(!epoch)\n          epoch = std::unique_ptr<Epoch>(Epoch::create(type));\n        file>>nameValue(\"epoch\", *epoch);\n        arc.push_back(*epoch);\n      }\n      file>>endGroup(\"arc\");\n      index++;\n    }\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nArc InstrumentFile::read(const FileName &name)\n{\n  try\n  {\n    InstrumentFile file(name);\n    Arc arc;\n    for(UInt arcNo=0; arcNo<file.arcCount(); arcNo++)\n      arc.append(file.readArc(arcNo));\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentFile::checkArcCount(const std::vector<std::reference_wrapper<const InstrumentFile>> &fileList)\n{\n  UInt arcCountOld = 0;\n  for(const InstrumentFile &file : fileList)\n  {\n    if(!arcCountOld)\n      arcCountOld = file.arcCount();\n    if(arcCountOld && file.arcCount() && (file.arcCount() != arcCountOld))\n      throw(Exception(\"number of arcs (\"+file.arcCount()%\"%i) of instrument file <\"s+file.fileName.str()+\"> is different compared to the other arcs (\"+arcCountOld%\"%i)\"s));\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MiscValuesOldEpoch::load(InArchive &ia)\n{\n  if(ia.version() < 20170920)\n  {\n    ia >> nameValue (\"time\",   time);\n    ia >> nameValue (\"values\", values);\n    return;\n  }\n  UInt count;\n  ia >> nameValue (\"time\",  time);\n  ia >> nameValue (\"count\", count);\n  values = Vector(count);\n  for(UInt i=0; i<count; i++)\n    ia >> nameValue (\"value\", values(i));\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MiscValuesEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\", time);\n  for(UInt i=0; i<values.rows(); i++)\n    oa << nameValue (\"value\", values(i));\n}\n\n/***********************************************/\n\nvoid MiscValuesEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\", time);\n  for(UInt i=0; i<values.size(); i++)\n    ia >> nameValue (\"value\", values(i));\n}\n\n/***********************************************/\n\nVector MiscValuesEpoch::data() const\n{\n  return values;\n}\n\n/***********************************************/\n\nvoid MiscValuesEpoch::setData(const Vector &x)\n{\n  values = x;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid InstrumentTimeEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\", time);\n}\n\n/***********************************************/\n\nvoid InstrumentTimeEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\", time);\n}\n\n/***********************************************/\n\nVector InstrumentTimeEpoch::data() const\n{\n  return Vector(0);\n}\n\n/***********************************************/\n\nvoid InstrumentTimeEpoch::setData(const Vector &/*x*/)\n{\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MiscValueEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",  time);\n  oa << nameValue (\"value\", value);\n}\n\n/***********************************************/\n\nvoid MiscValueEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",  time);\n  ia >> nameValue (\"value\", value);\n}\n\n/***********************************************/\n\nVector MiscValueEpoch::data() const\n{\n  Vector x(1);\n  x(0) = value;\n  return x;\n}\n\n/***********************************************/\n\nvoid MiscValueEpoch::setData(const Vector &x)\n{\n  value = x(0);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Vector3dEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",     time);\n  oa << nameValue (\"vector3d\", vector3d);\n}\n\n/***********************************************/\n\nvoid Vector3dEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",     time);\n  ia >> nameValue (\"vector3d\", vector3d);\n}\n\n/***********************************************/\n\nVector Vector3dEpoch::data() const\n{\n  return vector3d.vector();\n}\n\n/***********************************************/\n\nvoid Vector3dEpoch::setData(const Vector &x)\n{\n  vector3d.x() = x(0);\n  vector3d.y() = x(1);\n  vector3d.z() = x(2);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Covariance3dEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",       time);\n  oa << nameValue (\"covariance\", covariance);\n}\n\n/***********************************************/\n\nvoid Covariance3dEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",       time);\n  ia >> nameValue (\"covariance\", covariance);\n}\n\n/***********************************************/\n\nVector Covariance3dEpoch::data() const\n{\n  Vector x(6);\n  x(0) = covariance.xx();\n  x(1) = covariance.yy();\n  x(2) = covariance.zz();\n  x(3) = covariance.xy();\n  x(4) = covariance.xz();\n  x(5) = covariance.yz();\n  return x;\n}\n\n/***********************************************/\n\nvoid Covariance3dEpoch::setData(const Vector &x)\n{\n  covariance.xx() = x(0);\n  covariance.yy() = x(1);\n  covariance.zz() = x(2);\n  covariance.xy() = x(3);\n  covariance.xz() = x(4);\n  covariance.yz() = x(5);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OrbitEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",         time);\n  oa << nameValue (\"position\",     position);\n  oa << nameValue (\"velocity\",     velocity);\n  oa << nameValue (\"acceleration\", acceleration);\n}\n\n/***********************************************/\n\nvoid OrbitEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",         time);\n  ia >> nameValue (\"position\",     position);\n  ia >> nameValue (\"velocity\",     velocity);\n  ia >> nameValue (\"acceleration\", acceleration);\n}\n\n/***********************************************/\n\nVector OrbitEpoch::data() const\n{\n  Vector x(9);\n  x(0) = position.x();\n  x(1) = position.y();\n  x(2) = position.z();\n  x(3) = velocity.x();\n  x(4) = velocity.y();\n  x(5) = velocity.z();\n  x(6) = acceleration.x();\n  x(7) = acceleration.y();\n  x(8) = acceleration.z();\n  return x;\n}\n\n/***********************************************/\n\nvoid OrbitEpoch::setData(const Vector &x)\n{\n  position.x()     = x(0);\n  position.y()     = x(1);\n  position.z()     = x(2);\n  velocity.x()     = x(3);\n  velocity.y()     = x(4);\n  velocity.z()     = x(5);\n  acceleration.x() = x(6);\n  acceleration.y() = x(7);\n  acceleration.z() = x(8);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid StarCameraEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",   time);\n  oa << nameValue (\"rotary\", rotary);\n}\n\n/***********************************************/\n\nvoid StarCameraEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",   time);\n  ia >> nameValue (\"rotary\", rotary);\n}\n\n/***********************************************/\n\nVector StarCameraEpoch::data() const\n{\n  return rotary.quaternion();\n}\n\n/***********************************************/\n\nvoid StarCameraEpoch::setData(const Vector &x)\n{\n  rotary = Rotary3d(1./norm(x)*x);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid AccelerometerEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",         time);\n  oa << nameValue (\"acceleration\", acceleration);\n}\n\n/***********************************************/\n\nvoid AccelerometerEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",         time);\n  ia >> nameValue (\"acceleration\", acceleration);\n}\n\n/***********************************************/\n\nVector AccelerometerEpoch::data() const\n{\n  Vector x(3);\n  x(0) = acceleration.x();\n  x(1) = acceleration.y();\n  x(2) = acceleration.z();\n  return x;\n}\n\n/***********************************************/\n\nvoid AccelerometerEpoch::setData(const Vector &x)\n{\n  acceleration.x() = x(0);\n  acceleration.y() = x(1);\n  acceleration.z() = x(2);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SatelliteTrackingEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",       time);\n  oa << nameValue (\"range\",      range);\n  oa << nameValue (\"rangeRate\",  rangeRate);\n  oa << nameValue (\"rangeAcceleration\", rangeAcceleration);\n}\n\n/***********************************************/\n\nvoid SatelliteTrackingEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",       time);\n  ia >> nameValue (\"range\",      range);\n  ia >> nameValue (\"rangeRate\",  rangeRate);\n  ia >> nameValue (\"rangeAcceleration\", rangeAcceleration);\n  if(ia.version() < 20200123)\n  {\n    UInt phaseIndex;\n    ia >> nameValue (\"phaseIndex\", phaseIndex);\n  }\n}\n\n/***********************************************/\n\nVector SatelliteTrackingEpoch::data() const\n{\n  Vector x(3);\n  x(0) = range;\n  x(1) = rangeRate;\n  x(2) = rangeAcceleration;\n  return x;\n}\n\n/***********************************************/\n\nvoid SatelliteTrackingEpoch::setData(const Vector &x)\n{\n  range             = x(0);\n  rangeRate         = x(1);\n  rangeAcceleration = x(2);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid GradiometerEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",            time);\n  oa << nameValue (\"gravityGradient\", gravityGradient);\n}\n\n/***********************************************/\n\nvoid GradiometerEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",            time);\n  ia >> nameValue (\"gravityGradient\", gravityGradient);\n}\n\n/***********************************************/\n\nVector GradiometerEpoch::data() const\n{\n  Vector x(6);\n  x(0) = gravityGradient.xx();\n  x(1) = gravityGradient.yy();\n  x(2) = gravityGradient.zz();\n  x(3) = gravityGradient.xy();\n  x(4) = gravityGradient.xz();\n  x(5) = gravityGradient.yz();\n  return x;\n}\n\n/***********************************************/\n\nvoid GradiometerEpoch::setData(const Vector &x)\n{\n  gravityGradient.xx() = x(0);\n  gravityGradient.yy() = x(1);\n  gravityGradient.zz() = x(2);\n  gravityGradient.xy() = x(3);\n  gravityGradient.xz() = x(4);\n  gravityGradient.yz() = x(5);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid GnssReceiverEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",        time);\n  oa << nameValue (\"type\",        obsType);\n  oa << nameValue (\"satellite\",   satellite);\n  oa << nameValue (\"observation\", observation);\n  oa << nameValue (\"clockError\",  clockError);\n}\n\n/***********************************************/\n\nvoid GnssReceiverEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",        time);\n  ia >> nameValue (\"type\",        obsType);\n  ia >> nameValue (\"satellite\",   satellite);\n  ia >> nameValue (\"observation\", observation);\n  ia >> nameValue (\"clockError\",  clockError);\n}\n\n/***********************************************/\n\nVector GnssReceiverEpoch::data() const\n{\n  try\n  {\n    throw(Exception(\"not implemented yet\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverEpoch::setData(const Vector& /*data*/)\n{\n  try\n  {\n    throw(Exception(\"not implemented yet\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid ObservationSigmaEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",  time);\n  oa << nameValue (\"sigma\", sigma);\n}\n\n/***********************************************/\n\nvoid ObservationSigmaEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",  time);\n  ia >> nameValue (\"sigma\", sigma);\n}\n\n/***********************************************/\n\nVector ObservationSigmaEpoch::data() const\n{\n  Vector x(1);\n  x(0) = sigma;\n  return x;\n}\n\n/***********************************************/\n\nvoid ObservationSigmaEpoch::setData(const Vector &x)\n{\n  sigma = x(0);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MassEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",         time);\n  oa << nameValue (\"massThruster\", massThr);\n  oa << nameValue (\"massTank\",     massTank);\n}\n\n/***********************************************/\n\nvoid MassEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",         time);\n  ia >> nameValue (\"massThruster\", massThr);\n  ia >> nameValue (\"massTank\",     massTank);\n}\n\n/***********************************************/\n\nVector MassEpoch::data() const\n{\n  Vector x(2);\n  x(0) = massThr;\n  x(1) = massTank;\n  return x;\n}\n\n/***********************************************/\n\nvoid MassEpoch::setData(const Vector &x)\n{\n  massThr  = x(0);\n  massTank = x(1);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid ThrusterEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",     time);\n  oa << nameValue (\"onTime1\",  onTime1);\n  oa << nameValue (\"onTime2\",  onTime2);\n  oa << nameValue (\"onTime3\",  onTime3);\n  oa << nameValue (\"onTime4\",  onTime4);\n  oa << nameValue (\"onTime5\",  onTime5);\n  oa << nameValue (\"onTime6\",  onTime6);\n  oa << nameValue (\"onTime7\",  onTime7);\n  oa << nameValue (\"onTime8\",  onTime8);\n  oa << nameValue (\"onTime9\",  onTime9);\n  oa << nameValue (\"onTime10\", onTime10);\n  oa << nameValue (\"onTime11\", onTime11);\n  oa << nameValue (\"onTime12\", onTime12);\n  oa << nameValue (\"onTime13\", onTime13);\n  oa << nameValue (\"onTime14\", onTime14);\n}\n\n/***********************************************/\n\nvoid ThrusterEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",     time);\n  ia >> nameValue (\"onTime1\",  onTime1);\n  ia >> nameValue (\"onTime2\",  onTime2);\n  ia >> nameValue (\"onTime3\",  onTime3);\n  ia >> nameValue (\"onTime4\",  onTime4);\n  ia >> nameValue (\"onTime5\",  onTime5);\n  ia >> nameValue (\"onTime6\",  onTime6);\n  ia >> nameValue (\"onTime7\",  onTime7);\n  ia >> nameValue (\"onTime8\",  onTime8);\n  ia >> nameValue (\"onTime9\",  onTime9);\n  ia >> nameValue (\"onTime10\", onTime10);\n  ia >> nameValue (\"onTime11\", onTime11);\n  ia >> nameValue (\"onTime12\", onTime12);\n  ia >> nameValue (\"onTime13\", onTime13);\n  ia >> nameValue (\"onTime14\", onTime14);\n}\n\n/***********************************************/\n\nVector ThrusterEpoch::data() const\n{\n  Vector x(14);\n  x(0)  = onTime1;\n  x(1)  = onTime2;\n  x(2)  = onTime3;\n  x(3)  = onTime4;\n  x(4)  = onTime5;\n  x(5)  = onTime6;\n  x(6)  = onTime7;\n  x(7)  = onTime8;\n  x(8)  = onTime9;\n  x(9)  = onTime10;\n  x(10) = onTime11;\n  x(11) = onTime12;\n  x(12) = onTime13;\n  x(13) = onTime14;\n  return x;\n}\n\n/***********************************************/\n\nvoid ThrusterEpoch::setData(const Vector &x)\n{\n  onTime1  = x(0);\n  onTime2  = x(1);\n  onTime3  = x(2);\n  onTime4  = x(3);\n  onTime5  = x(4);\n  onTime6  = x(5);\n  onTime7  = x(6);\n  onTime8  = x(7);\n  onTime9  = x(8);\n  onTime10 = x(9);\n  onTime11 = x(10);\n  onTime12 = x(11);\n  onTime13 = x(12);\n  onTime14 = x(13);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MagnetometerEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",                     time);\n  oa << nameValue (\"magneticField\",            magneticField);\n  oa << nameValue (\"torquerA\",                 torquerA);\n  oa << nameValue (\"torquerB\",                 torquerB);\n  oa << nameValue (\"magneticFieldCalibration\", magneticFieldCalibration);\n  oa << nameValue (\"torquerCalibration\",       torquerCalibration);\n}\n\n/***********************************************/\n\nvoid MagnetometerEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",                     time);\n  ia >> nameValue (\"magneticField\",            magneticField);\n  ia >> nameValue (\"torquerA\",                 torquerA);\n  ia >> nameValue (\"torquerB\",                 torquerB);\n  ia >> nameValue (\"magneticFieldCalibration\", magneticFieldCalibration);\n  ia >> nameValue (\"torquerCalibration\",       torquerCalibration);\n}\n\n/***********************************************/\n\nVector MagnetometerEpoch::data() const\n{\n  Vector x(13);\n  x(0)   = magneticField.x();\n  x(1)   = magneticField.y();\n  x(2)   = magneticField.z();\n  x(3)   = torquerA.x();\n  x(4)   = torquerA.y();\n  x(5)   = torquerA.z();\n  x(6)   = torquerB.x();\n  x(7)   = torquerB.y();\n  x(8)   = torquerB.z();\n  x(9)   = magneticFieldCalibration.x();\n  x(10)  = magneticFieldCalibration.y();\n  x(11)  = magneticFieldCalibration.z();\n  x(12)  = torquerCalibration;\n  return x;\n}\n\n/***********************************************/\n\nvoid MagnetometerEpoch::setData(const Vector &x)\n{\n  magneticField.x()            = x(0);\n  magneticField.y()            = x(1);\n  magneticField.z()            = x(2);\n  torquerA.x()                 = x(3);\n  torquerA.y()                 = x(4);\n  torquerA.z()                 = x(5);\n  torquerB.x()                 = x(6);\n  torquerB.y()                 = x(7);\n  torquerB.z()                 = x(8);\n  magneticFieldCalibration.x() = x(9);\n  magneticFieldCalibration.y() = x(10);\n  magneticFieldCalibration.z() = x(11);\n  torquerCalibration           = x(12);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid AccHousekeepingEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",               time);\n  oa << nameValue (\"biasVoltage\",        biasVoltage);\n  oa << nameValue (\"vd\",                 vd);\n  oa << nameValue (\"xOut\",               xOut);\n  oa << nameValue (\"yOut\",               yOut);\n  oa << nameValue (\"temperatureSU\",      tempSU);\n  oa << nameValue (\"temperatureICU\",     tempICU);\n  oa << nameValue (\"temperatureCore\",    tempCore);\n  oa << nameValue (\"temperatureICUConv\", tempICUConv);\n  oa << nameValue (\"blockNumber\",        blkNrICU);\n}\n\n/***********************************************/\n\nvoid AccHousekeepingEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",               time);\n  ia >> nameValue (\"biasVoltage\",        biasVoltage);\n  ia >> nameValue (\"vd\",                 vd);\n  ia >> nameValue (\"xOut\",               xOut);\n  ia >> nameValue (\"yOut\",               yOut);\n  ia >> nameValue (\"temperatureSU\",      tempSU);\n  ia >> nameValue (\"temperatureICU\",     tempICU);\n  ia >> nameValue (\"temperatureCore\",    tempCore);\n  ia >> nameValue (\"temperatureICUConv\", tempICUConv);\n  ia >> nameValue (\"blockNumber\",        blkNrICU);\n}\n\n/***********************************************/\n\nVector AccHousekeepingEpoch::data() const\n{\n  Vector x(13);\n  x(0)  = biasVoltage;\n  x(1)  = vd;\n  x(2)  = xOut.x();\n  x(3)  = xOut.y();\n  x(4)  = xOut.z();\n  x(5)  = yOut.x();\n  x(6)  = yOut.y();\n  x(7)  = yOut.z();\n  x(8)  = tempSU;\n  x(9)  = tempICU;\n  x(10) = tempCore;\n  x(11) = tempICUConv;\n  x(12) = blkNrICU;\n  return x;\n}\n\n/***********************************************/\n\nvoid AccHousekeepingEpoch::setData(const Vector &x)\n{\n  biasVoltage = x(0);\n  vd          = x(1);\n  xOut.x()    = x(2);\n  xOut.y()    = x(3);\n  xOut.z()    = x(4);\n  yOut.x()    = x(5);\n  yOut.y()    = x(6);\n  yOut.z()    = x(7);\n  tempSU      = x(8);\n  tempICU     = x(9);\n  tempCore    = x(10);\n  tempICUConv = x(11);\n  blkNrICU    = x(12);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid ClockEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",        time);\n  oa << nameValue (\"rcvTime\",     rcvTime);\n  oa << nameValue (\"epsTime\",     epsTime);\n  oa << nameValue (\"epsError\",    epsError);\n  oa << nameValue (\"epsDrift\",    epsDrift);\n  oa << nameValue (\"driftError\",  driftError);\n  oa << nameValue (\"qualityFlag\", qualityFlag);\n}\n\n/***********************************************/\n\nvoid ClockEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",        time);\n  ia >> nameValue (\"rcvTime\",     rcvTime);\n  ia >> nameValue (\"epsTime\",     epsTime);\n  ia >> nameValue (\"epsError\",    epsError);\n  ia >> nameValue (\"epsDrift\",    epsDrift);\n  ia >> nameValue (\"driftError\",  driftError);\n  ia >> nameValue (\"qualityFlag\", qualityFlag);\n}\n\n/***********************************************/\n\nVector ClockEpoch::data() const\n{\n  Vector x(6);\n  x(0)  = rcvTime;\n  x(1)  = epsTime;\n  x(2)  = epsError;\n  x(3)  = epsDrift;\n  x(4)  = driftError;\n  x(5)  = qualityFlag;\n  return x;\n}\n\n/***********************************************/\n\nvoid ClockEpoch::setData(const Vector &x)\n{\n  rcvTime     = x(0);\n  epsTime     = x(1);\n  epsError    = x(2);\n  epsDrift    = x(3);\n  driftError  = x(4);\n  qualityFlag = x(5);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid StarCamera1AEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",      time);\n  oa << nameValue (\"rcvTime\",   rcvTime);\n  oa << nameValue (\"epsTime\",   epsTime);\n  oa << nameValue (\"scaDesign\", scaDesign);\n  oa << nameValue (\"q0\",        q0);\n  oa << nameValue (\"q1\",        q1);\n  oa << nameValue (\"q2\",        q2);\n  oa << nameValue (\"q3\",        q3);\n  oa << nameValue (\"nLocks\",    nLocks);\n  oa << nameValue (\"nStars\",    nStars);\n}\n\n/***********************************************/\n\nvoid StarCamera1AEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",      time);\n  ia >> nameValue (\"rcvTime\",   rcvTime);\n  ia >> nameValue (\"epsTime\",   epsTime);\n  ia >> nameValue (\"scaDesgin\", scaDesign);\n  ia >> nameValue (\"q0\",        q0);\n  ia >> nameValue (\"q1\",        q1);\n  ia >> nameValue (\"q2\",        q2);\n  ia >> nameValue (\"q3\",        q3);\n  ia >> nameValue (\"nLocks\",    nLocks);\n  ia >> nameValue (\"nStars\",    nStars);\n}\n\n/***********************************************/\n\nVector StarCamera1AEpoch::data() const\n{\n  Vector x(9);\n  x(0) = rcvTime;\n  x(1) = epsTime;\n  x(2) = scaDesign;\n  x(3) = q0;\n  x(4) = q1;\n  x(5) = q2;\n  x(6) = q3;\n  x(7) = nLocks;\n  x(8) = nStars;\n  return x;\n}\n\n/***********************************************/\n\nvoid StarCamera1AEpoch::setData(const Vector &x)\n{\n  rcvTime   = x(0);\n  epsTime   = x(1);\n  scaDesign = x(2);\n  q0        = x(3);\n  q1        = x(4);\n  q2        = x(5);\n  q3        = x(6);\n  nLocks    = x(7);\n  nStars    = x(8);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid Accelerometer1AEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",         time);\n  oa << nameValue (\"rcvTimeInt\",   rcvTimeInt);\n  oa << nameValue (\"rcvTimeFrac\",  rcvTimeFrac);\n  oa << nameValue (\"acceleration\", acceleration);\n}\n\n/***********************************************/\n\nvoid Accelerometer1AEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",         time);\n  ia >> nameValue (\"rcvTimeInt\",   rcvTimeInt);\n  ia >> nameValue (\"rcvTimeFrac\",  rcvTimeFrac);\n  ia >> nameValue (\"acceleration\", acceleration);\n}\n\n/***********************************************/\n\nVector Accelerometer1AEpoch::data() const\n{\n  Vector x(5);\n  x(0) = rcvTimeInt;\n  x(1) = rcvTimeFrac;\n  x(2) = acceleration.x();\n  x(3) = acceleration.y();\n  x(4) = acceleration.z();\n  return x;\n}\n\n/***********************************************/\n\nvoid Accelerometer1AEpoch::setData(const Vector &x)\n{\n  rcvTimeInt       = x(0);\n  rcvTimeFrac      = x(1);\n  acceleration.x() = x(2);\n  acceleration.y() = x(3);\n  acceleration.z() = x(4);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SatelliteLaserRangingEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",        time);\n  oa << nameValue (\"range\",       range);\n  oa << nameValue (\"accuracy\",    accuracy);\n  oa << nameValue (\"redundancy\",  redundancy);\n  oa << nameValue (\"window\",      window);\n  oa << nameValue (\"wavelength\",  wavelength);\n  oa << nameValue (\"azmiuth\",     azmiuth);\n  oa << nameValue (\"elevation\",   elevation);\n}\n\n/***********************************************/\n\nvoid SatelliteLaserRangingEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",       time);\n  ia >> nameValue (\"range\",      range);\n  ia >> nameValue (\"accuracy\",   accuracy);\n  ia >> nameValue (\"redundancy\", redundancy);\n  ia >> nameValue (\"window\",     window);\n  ia >> nameValue (\"wavelength\", wavelength);\n  ia >> nameValue (\"azmiuth\",    azmiuth);\n  ia >> nameValue (\"elevation\",  elevation);\n}\n\n/***********************************************/\n\nVector SatelliteLaserRangingEpoch::data() const\n{\n  Vector x(7);\n  x(0) = range;\n  x(1) = accuracy;\n  x(2) = redundancy;\n  x(3) = window;\n  x(4) = wavelength;\n  x(5) = azmiuth;\n  x(6) = elevation;\n  return x;\n}\n\n/***********************************************/\n\nvoid SatelliteLaserRangingEpoch::setData(const Vector &x)\n{\n  range      = x(0);\n  accuracy   = x(1);\n  redundancy = x(2);\n  window     = x(3);\n  wavelength = x(4);\n  azmiuth    = x(5);\n  elevation  = x(6);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MeteorologicalEpoch::save(OutArchive &oa) const\n{\n  oa << nameValue (\"time\",           time);\n  oa << nameValue (\"temperature\",    temperature);\n  oa << nameValue (\"pressure\",       pressure);\n  oa << nameValue (\"humidity\",       humidity);\n  oa << nameValue (\"windSpeed\",      windSpeed);\n  oa << nameValue (\"solarRadiation\", solarRadiation);\n  oa << nameValue (\"precipitation\",  precipitation);\n}\n\n/***********************************************/\n\nvoid MeteorologicalEpoch::load(InArchive &ia)\n{\n  ia >> nameValue (\"time\",           time);\n  ia >> nameValue (\"temperature\",    temperature);\n  ia >> nameValue (\"pressure\",       pressure);\n  ia >> nameValue (\"humidity\",       humidity);\n  ia >> nameValue (\"windSpeed\",      windSpeed);\n  ia >> nameValue (\"solarRadiation\", solarRadiation);\n  ia >> nameValue (\"precipitation\",  precipitation);\n}\n\n/***********************************************/\n\nVector MeteorologicalEpoch::data() const\n{\n  Vector x(6);\n  x(0) = temperature;\n  x(1) = pressure;\n  x(2) = humidity;\n  x(3) = windSpeed;\n  x(4) = solarRadiation;\n  x(5) = precipitation;\n  return x;\n}\n\n/***********************************************/\n\nvoid MeteorologicalEpoch::setData(const Vector &x)\n{\n  temperature    = x(0);\n  pressure       = x(1);\n  humidity       = x(2);\n  windSpeed      = x(3);\n  solarRadiation = x(4);\n  precipitation  = x(5);\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileInstrument.h",
    "content": "/***********************************************/\n/**\n* @file fileInstrument.h\n*\n* @brief Satellites instrument data organized in arcs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEINSTRUMENT__\n#define __GROOPS_FILEINSTRUMENT__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_Instrument\nstatic const char *docstringInstrument = R\"(\nThis template file format can store different observations in a epoch wise manner. Each epoch consists of a time and\nadditional data, e.g orbits, accelerometer data, star camera quaternions (see \\configClass{InstrumentType}{instrumentTypeType}).\nThe time series can be divided in several arcs (see \\program{InstrumentSynchronize}).\n\nAlso a \\file{matrix}{matrix} file is allowed as one single arc. The first column must contain times [MJD]. Without any extra column\nthe instrument type is INSTRUMENTTIME, with one additional column the type is MISCVALUE, and for more columns the type\nMISCVALUES is used.\n\n\\begin{verbatim}\ngroops instrument version=20200123\n# SATELLITETRACKING\n         -9         60  # instrument type, number of arcs\n# Time [MJD]               data0: range [m]          data1: range-rate [m/s]   data2: range-acc [m/s^2]\n# =====================================================================================================\n         12 # number of epochs of 1. arc\n 54588.000000000000000000 -5.074649470097549492e+05  5.755440207134928654e-01  1.877605261528093308e-03\n 54588.000057870370255841 -5.074620458130163024e+05  5.849357691551860805e-01  1.878948916234051596e-03\n 54588.000115740740966430 -5.074590976427756250e+05  5.943331739937073310e-01  1.879937220634776869e-03\n 54588.000173611111222272 -5.074561024756557308e+05  6.037340169611068452e-01  1.880370529387525701e-03\n 54588.000231481481478113 -5.074530602992626373e+05  6.131368121270999172e-01  1.880680632122925426e-03\n 54588.000289351851733954 -5.074499711071007187e+05  6.225398878861636565e-01  1.880495369480403561e-03\n 54588.000347222222444543 -5.074468349029610981e+05  6.319414138081351773e-01  1.880073731783055927e-03\n 54588.000405092592700385 -5.074436516971451929e+05  6.413404243585696385e-01  1.879464843086203459e-03\n 54588.000462962962956226 -5.074404215058300761e+05  6.507353310092597320e-01  1.878578987216372124e-03\n 54588.000520833333212067 -5.074371443491023383e+05  6.601267978060636477e-01  1.877878184949659246e-03\n 54588.000578703703922656 -5.074338202460713219e+05  6.695136489207137442e-01  1.876962042758626532e-03\n 54588.000636574074178498 -5.074304492190054734e+05  6.788964444122400632e-01  1.876091925462087043e-03\n         12 # number of epochs of 2. arc\n 54588.000694444444434339 -5.074270312892858055e+05  6.882748400534359767e-01  1.875376456928801432e-03\n 54588.000752314814690180 -5.074235664742725785e+05  6.976508178537534910e-01  1.874929898412159559e-03\n 54588.000810185185400769 -5.074200547868391732e+05  7.070236200716006891e-01  1.874312324351668077e-03\n 54588.000868055555656611 -5.074164962409950094e+05  7.163943828291452487e-01  1.873924188388115340e-03\n 54588.000925925925912452 -5.074128908454515622e+05  7.257639682023964145e-01  1.874025826380292404e-03\n 54588.000983796296168293 -5.074092386012640782e+05  7.351333608427884636e-01  1.873680487441316657e-03\n 54588.001041666666878882 -5.074055395130896359e+05  7.445020815182646912e-01  1.873849502509668122e-03\n 54588.001099537037134724 -5.074017935789784533e+05  7.538716732272922050e-01  1.873971633320137753e-03\n 54588.001157407407390565 -5.073980007962241652e+05  7.632414098560330595e-01  1.873984767500571974e-03\n 54588.001215277777646406 -5.073941611626467784e+05  7.726123093411200182e-01  1.874295246964456478e-03\n 54588.001273148148356995 -5.073902746728868224e+05  7.819835205798950639e-01  1.874226146744964808e-03\n 54588.001331018518612836 -5.073863413272026228e+05  7.913547196412918927e-01  1.874173804634685515e-03\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/gnssType.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/**\n* @defgroup fileInstrumentGroup FileInstrument\n* @brief Satellite Instrument data.\n* @ingroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_INSTRUMENT_TYPE = \"instrument\";\nconstexpr UInt    FILE_INSTRUMENT_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Epoch with satellite instrument data.\n* An Epoch contain instrument data given at a specific @a time.\n* This is an abstract class. */\nclass Epoch\n{\npublic:\n  /// Instrument data type (type > 0: MISCVALUES where type is the number of data columns).\n  enum Type : Int  {EMPTY                 =  0,\n                    MISCVALUESOLD         = -9999,\n                    MISCVALUES            = -1, // MISCVALUES with unknown or zero size\n                    INSTRUMENTTIME        = -2,\n                    MISCVALUE             = -3,\n                    VECTOR3D              = -4,\n                    COVARIANCE3D          = -5,\n                    ORBIT                 = -6,\n                    STARCAMERA            = -7,\n                    ACCELEROMETER         = -8,\n                    SATELLITETRACKING     = -9,\n                    GRADIOMETER           = -10,\n                    GNSSRECEIVER          = -11,\n                    OBSERVATIONSIGMA      = -12,\n                    MASS                  = -16,\n                    THRUSTER              = -17,\n                    MAGNETOMETER          = -18,\n                    ACCHOUSEKEEPING       = -19,\n                    CLOCK                 = -20,\n                    STARCAMERA1A          = -21,\n                    ACCELEROMETER1A       = -22,\n                    SATELLITELASERRANGING = -23,\n                    METEOROLOGICAL        = -24};\n\n  Time time; //!< Time of Epoch.\n\n  Epoch()                         = default; //!< Constructor\n  Epoch(const Epoch &)            = default; //!< Copy constructor\n  Epoch(Epoch &&)                 = default; //!< Move constructor\n  virtual ~Epoch()                = default; //!< Destructor.\n  Epoch &operator=(const Epoch &) = default; //!< Assignement\n  Epoch &operator=(Epoch &&)      = default; //!< Move assignment\n\n  /** @brief Create an epoch of given type (with new). */\n  static Epoch *create(Type type);\n\n  /** @brief Data type (e.g. ORBIT, ACCELEROMETER). */\n  virtual Type getType() const = 0;\n\n  /** @brief Name of data type (e.g. ORBIT, ACCELEROMETER). */\n  std::string getTypeName() const {return getTypeName(getType());}\n\n  /** @brief Name of data type (e.g. ORBIT, ACCELEROMETER). */\n  static std::string getTypeName(Type type);\n\n  /** @brief Description of  data type (e.g. ORBIT, ACCELEROMETER). */\n  static std::string fileFormatString(Type type);\n\n  /** @brief Number of data columns\n  * If undefined NULLINDEX is returned\n  * and if additionally @p mustDefined==TRUE, an Exception is thrown. */\n  static UInt dataCount(Type type, Bool mustDefined=FALSE);\n\n  /** @brief The data as as list of Doubles.\n  * Without time. */\n  virtual Vector data() const = 0; // data without time\n\n  /** @brief set data from a list of Doubles.\n  * Without time. */\n  virtual void setData(const Vector &x) = 0; // data without time\n\n  /** @brief A copy is created with new.\n  * The user has to delete the new Epoch. */\n  virtual Epoch *clone() const = 0;\n\n  virtual void save(OutArchive &oa) const = 0;\n  virtual void load(InArchive  &ia) = 0;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Arc with satellite instrument data.\n* An Arc consists of a list of Epochs of an arbitrary instrument. */\nclass Arc\n{\nprotected:\n  std::vector<std::unique_ptr<Epoch>> epoch;\n\n  virtual void checkType(Epoch::Type type)\n  {\n    if((type != Epoch::EMPTY) && (getType() != Epoch::EMPTY) && (type != getType()))\n      throw(Exception(\"In Arc<\"+Epoch::getTypeName(getType())+\">: assignment of wrong data type: \"+Epoch::getTypeName(type)));\n  }\n\n  /** @brief Random access iterator with implicit double dereferencing to directly access epochs of type @a T.\n   * Constness of iterator is defined via template parameter @a isConstIterator. */\n  template<typename T, bool isConstIterator>\n  class Iterator : public std::conditional<isConstIterator, std::vector<std::unique_ptr<Epoch>>::const_iterator, std::vector<std::unique_ptr<Epoch>>::iterator>::type\n  {\n    using BaseIterator  = typename std::conditional<isConstIterator, std::vector<std::unique_ptr<Epoch>>::const_iterator, std::vector<std::unique_ptr<Epoch>>::iterator>::type;\n    using PointerType   = typename std::conditional<isConstIterator, const T*, T*>::type;\n    using ReferenceType = typename std::conditional<isConstIterator, const T&, T&>::type;\n\n  public:\n    using iterator_category = typename BaseIterator::iterator_category;\n    using difference_type   = typename BaseIterator::difference_type;\n    using value_type        = T;\n    using pointer           = PointerType;\n    using reference         = ReferenceType;\n\n    Iterator() : BaseIterator() {}                           /// Default constructor\n    Iterator(const BaseIterator &it) : BaseIterator(it) {}   /// Base constructor\n\n    PointerType operator->() const { return dynamic_cast<PointerType>(BaseIterator::operator*().get()); }                           // double dereferencing\n    ReferenceType operator*() const { return *this->operator->(); }                                                                 // double dereferencing\n    ReferenceType operator[](difference_type rhs) const { return *dynamic_cast<PointerType>(BaseIterator::operator[](rhs).get()); } // double dereferencing\n    Iterator& operator+=(difference_type rhs)           { BaseIterator::operator+=(rhs); return *this; }\n    Iterator& operator-=(difference_type rhs)           { BaseIterator::operator-=(rhs); return *this; }\n    Iterator& operator++()                              { BaseIterator::operator++(); return *this; }\n    Iterator& operator--()                              { BaseIterator::operator--(); return *this; }\n    Iterator operator++(int rhs)                        { return BaseIterator::operator++(rhs); }\n    Iterator operator--(int rhs)                        { return BaseIterator::operator--(rhs); }\n    Iterator operator+(difference_type rhs) const       { return BaseIterator::operator+(rhs); }\n    Iterator operator-(difference_type rhs) const       { return BaseIterator::operator-(rhs); }\n    friend Iterator operator+(difference_type lhs, const Iterator &rhs) { return lhs+BaseIterator(rhs); }\n  };\n\npublic:\n  using iterator               = Iterator<Epoch, false>;\n  using const_iterator         = Iterator<Epoch, true>;\n  using reverse_iterator       = typename std::reverse_iterator<iterator>;\n  using const_reverse_iterator = typename std::reverse_iterator<const_iterator>;\n\n  iterator begin()                       { return epoch.begin(); }\n  iterator end()                         { return epoch.end(); }\n  const_iterator begin()           const { return epoch.cbegin(); }\n  const_iterator end()             const { return epoch.cend(); }\n  const_iterator cbegin()          const { return epoch.cbegin(); }\n  const_iterator cend()            const { return epoch.cend(); }\n  reverse_iterator rbegin()              { return reverse_iterator(this->end()); }\n  reverse_iterator rend()                { return reverse_iterator(this->begin()); }\n  const_reverse_iterator rbegin()  const { return const_reverse_iterator(this->cend()); }\n  const_reverse_iterator rend()    const { return const_reverse_iterator(this->cbegin()); }\n  const_reverse_iterator crbegin() const { return const_reverse_iterator(this->cend()); }\n  const_reverse_iterator crend()   const { return const_reverse_iterator(this->cbegin()); }\n\npublic:\n  Arc() = default;          //!< Default Constructor\n  Arc(const Arc &arc);      //!< Copy constructor\n  Arc(Arc &&) = default;    //!< Move constructor\n  virtual ~Arc() = default; //!< Destructor\n\n  /// Constructor from matrix (first column is MJD)\n  explicit Arc(const_MatrixSliceRef A, Epoch::Type type=Epoch::EMPTY);\n\n  /** @brief Constructor from matrix (first column is MJD)\n  First columns of @a A is ignored, instead @a times is used. */\n  explicit Arc(const std::vector<Time> &times, const_MatrixSliceRef A, Epoch::Type type=Epoch::EMPTY);\n\n  Arc &operator=(const Arc &x);     //!< Assignement\n  Arc &operator=(Arc &&) = default; //!< Move assignment\n\n  /** @brief Epoch at index @a i. */\n  const Epoch &at(UInt i) const {return *epoch.at(i);}\n\n  /** @brief Writeable reference to epoch at index @a i. */\n  Epoch &at(UInt i) {return *epoch.at(i);}\n\n  /** @brief First epoch in arc */\n  const Epoch &front() const {return at(0);}\n        Epoch &front()       {return at(0);}\n\n  /** @brief Last epoch in arc */\n  const Epoch &back() const {return at(size()-1);}\n        Epoch &back()       {return at(size()-1);}\n\n  /** @brief Number of epochs. */\n  UInt size() const {return epoch.size();}\n\n  /** @brief Data type (e.g. ORBIT, ACCELEROMETER). */\n  Epoch::Type getType() const {return epoch.size() ? front().getType() : Epoch::EMPTY;}\n\n  /** @brief Name of data type (e.g. ORBIT, ACCELEROMETER). */\n  std::string getTypeName() const {return Epoch::getTypeName(getType());}\n\n  /** @brief Sort epochs in ascending temporal order. */\n  void sort();\n\n  /** @brief Remove consecutive epochs with equal time stamps. */\n  void removeDuplicateEpochs(Bool keepFirst = TRUE, Double margin=1e-5);\n\n  /** @brief Creates a new arc with @a len epochs starting at index @a start. */\n  Arc subArc(UInt start, UInt len) const;\n\n  /** @brief Removes @a len epochs starting at index @a index. */\n  void remove(UInt index, UInt len=1);\n\n  /** @brief Append another arc. */\n  void append(const Arc &arc);\n\n  /** @brief Synchronize all epochs with a given time list.\n  * All epochs are removed which are not in the time list.\n  * @param time list of valid points in time (all other epochs will be removed)\n  * @param margin time interval around the given @a time in which epochs are valid [seconds] */\n  void synchronize(const std::vector<Time> &time, Double margin=1e-5);\n\n  /** @brief Divide arc at time gaps and append new sub arcs to @a arcList.\n  * @param minGap minimal time span for a gap.\n  * @param minArcLen arcs shorter than minArcLen are dropped\n  * @param arcList divided arcs are appended to this list. */\n  void divide(const Time &minGap, UInt minArcLen, std::vector<Arc> &arcList) const;\n\n  /** @brief Insert a copy of @a epoch at @a index. */\n  void insert(UInt index, const Epoch &epoch);\n\n  /** @brief Append a copy of @a epoch to the arc. */\n  void push_back(const Epoch &epoch);\n\n  /** @brief Time series of epochs. */\n  std::vector<Time> times() const;\n\n  /** @brief Time series of data as matrix (first column is MJD). */\n  Matrix matrix() const;\n\n  void load(InArchive  &ia);\n  void save(OutArchive &oa) const;\n\n  template<typename T>\n  static Epoch::Type getType(const T &arcList)\n  {\n    // determine type\n    Epoch::Type type = Epoch::EMPTY;\n    for(const Arc &arc : arcList)\n      if(arc.size())\n      {\n        if((type != Epoch::EMPTY) && (type != arc.getType()))\n          throw(Exception(\"arcList contain different instruments types \"+Epoch::getTypeName(type)+\", \"+arc.getTypeName()));\n        type = arc.getType();\n      }\n    return type;\n  }\n\n  /** @brief Test of synchronicity of multiple arcs.\n  * If the arcs are not synchronous an expection is thrown.\n  * Empty arcs are ignored. */\n  static void checkSynchronized(const std::vector<std::reference_wrapper<const Arc>> &arc);\n\n  /** @brief Log information about arc size, number of epochs and so on. */\n  static void printStatistics(const Arc &arc);\n\n  /** @brief Log information about arc size, number of epochs and so on. */\n  static void printStatistics(const std::vector<Arc> &arcList);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Arc with specific satellite instrument data.\n* An Arc consists of a list of Epoch of specific instrument data. */\ntemplate<class EpochType>\nclass ArcTemplate : public Arc\n{\n  void checkType(Epoch::Type type) override\n  {\n    Arc::checkType(type);\n    if((type != Epoch::EMPTY) && (type != EpochType::type) && !((EpochType::type == Epoch::MISCVALUES) && (static_cast<Int>(type) > 0)))\n      throw(Exception(\"In Arc<\"+Epoch::getTypeName(EpochType::type)+\">: assignment of wrong data type: \"+Epoch::getTypeName(type)));\n  }\n\npublic:\n  using iterator               = Iterator<EpochType, false>;\n  using const_iterator         = Iterator<EpochType, true>;\n  using reverse_iterator       = typename std::reverse_iterator<iterator>;\n  using const_reverse_iterator = typename std::reverse_iterator<const_iterator>;\n\n  iterator begin()                       { return epoch.begin(); }\n  iterator end()                         { return epoch.end(); }\n  const_iterator begin()           const { return epoch.cbegin(); }\n  const_iterator end()             const { return epoch.cend(); }\n  const_iterator cbegin()          const { return epoch.cbegin(); }\n  const_iterator cend()            const { return epoch.cend(); }\n  reverse_iterator rbegin()              { return reverse_iterator(this->end()); }\n  reverse_iterator rend()                { return reverse_iterator(this->begin()); }\n  const_reverse_iterator rbegin()  const { return const_reverse_iterator(this->cend()); }\n  const_reverse_iterator rend()    const { return const_reverse_iterator(this->cbegin()); }\n  const_reverse_iterator crbegin() const { return const_reverse_iterator(this->cend()); }\n  const_reverse_iterator crend()   const { return const_reverse_iterator(this->cbegin()); }\n\npublic:\n  ArcTemplate() = default;                                             //!< Default Constructor\n  ArcTemplate(const ArcTemplate<EpochType> &arc) = default;            //!< Copy constructor\n  ArcTemplate(const Arc &arc) : Arc(arc) {checkType(getType());}       //!< Copy constructor\n  ArcTemplate(ArcTemplate<EpochType> &&arc) = default;                 //!< Move constructor\n  ArcTemplate(Arc &&arc) : Arc(std::move(arc)) {checkType(getType());} //!< Move constructor\n\n  ArcTemplate &operator=(const ArcTemplate<EpochType> &arc) {Arc::operator=(arc); return *this;}                                  //!< Assignement\n  ArcTemplate &operator=(const Arc &arc)                    {Arc::operator=(arc); checkType(getType()); return *this;}            //!< Assignement\n  ArcTemplate &operator=(ArcTemplate<EpochType> &&arc)      {Arc::operator=(std::move(arc)); return *this;}                       //!< Move assignment\n  ArcTemplate &operator=(Arc &&arc)                         {Arc::operator=(std::move(arc)); checkType(getType()); return *this;} //!< Move assignment\n\n  /** @brief Instrument specific epoch at index @a i. */\n  const EpochType &at(UInt i) const  {return *dynamic_cast<EpochType*>(epoch.at(i).get());}\n\n  /** @brief Instrument specific writable epoch at index @a i. */\n  EpochType &at(UInt i) {return *dynamic_cast<EpochType*>(epoch.at(i).get());}\n\n  /** @brief First epoch in arc */\n  const EpochType &front() const {return at(0);}\n        EpochType &front()       {return at(0);}\n\n  /** @brief Last epoch in arc */\n  const EpochType &back() const {return at(size()-1);}\n        EpochType &back()       {return at(size()-1);}\n};\n\n/***** TYPES ***********************************/\n\nclass InstrumentFile;\ntypedef std::shared_ptr<InstrumentFile> InstrumentFilePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief File with arbitrary satellite instrument data.\n* A File consists of a list of arcs (Arc).\n* Each arc consists of a list of Epoch of a specific instrument\n* (Only one instrument type per file is allowed).\n* The file is not read at once, but only read arc by arc.\n*\n* @code\n* InstrumentFile file(FileName(\"grace_satelliteTracking.dat\"));\n* UInt arcCount = file.arcCount();\n* for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n* {\n*   SatelliteTrackingrArc sstArc = file.readArc(arcNo); // read arc\n*   for(UInt i=0; i<sstArc.size(); i++)\n*     logInfo<<arc.at(i).time<<\": \"<<arc.at(i).range<<Log::endl; // access to Epoch with .at(i)\n* }\n* @endcode\n*/\nclass InstrumentFile\n{\n  InFileArchive file;\n  FileName      fileName;\n  Epoch::Type   type;\n  UInt          arcCount_;\n  UInt          index;\n  Matrix        A; // if a matrix file is open\n\npublic:\n  InstrumentFile() : type(Epoch::EMPTY), arcCount_(0) {}       //!< Default constructor.\n  explicit InstrumentFile(const FileName &name) {open(name);}  //!< Constructor.\n  InstrumentFile(const InstrumentFile &) = delete;             //!< Disallow copy constructor\n  InstrumentFile &operator=(const InstrumentFile &x) = delete; //!< Disallow copying\n ~InstrumentFile() {close();}                                  //!< Destructor.\n\n  /** @brief Open a new file.\n  * Old open file is closed before. */\n  void  open(const FileName &name);\n\n  /** @brief Close the file. */\n  void  close();\n\n  /** @brief Number of Arc in file. */\n  UInt arcCount() const {return arcCount_;}\n\n  /** @brief Instrument type. */\n  Epoch::Type getType()  const {return type;}\n\n  /** @brief Name of data type (e.g. ORBIT, ACCELEROMETER). */\n  std::string getTypeName() const {return Epoch::getTypeName(getType());}\n\n  /** @brief Number of data columns.\n  * If undefined NULLINDEX is returned\n  * and if additionally @p mustDefined==TRUE, an Exception is thrown. */\n  UInt dataCount(Bool mustDefined=FALSE) const {return Epoch::dataCount(getType(), mustDefined);}\n\n  /** @brief Read a single Arc.\n  * The operation is faster, if the arcs in read in increasing order.\n  * If the file is not open, a empty Arc is returned. */\n  Arc readArc(UInt arcNo);\n\n  /** @brief Test number of arcs of multiple files.\n  * Test whether files are divided into the same number of arcs otherwise an expection is thrown.\n  * Files which are not open are ignored. */\n  static void checkArcCount(const std::vector<std::reference_wrapper<const InstrumentFile>> &fileList);\n\n  /** @brief Read all arcs and concatenate to one arc. */\n  static Arc read(const FileName &name);\n\n  /** @brief Write an Arc to file. */\n  static void write(const FileName &name, const Arc &arc) {write(name, std::vector<Arc>(1, arc));}\n\n  /** @brief Write an Arc to file. */\n  template<typename T>\n  static void write(const FileName &name, const ArcTemplate<T> &arc) {write(name, std::vector<Arc>(1, arc));}\n\n  /** @brief Write a list of Arc to file. */\n  template<typename Container>\n  static void write(const FileName &name, const Container &arcList)\n  {\n    try\n    {\n      OutFileArchive file(name, FILE_INSTRUMENT_TYPE, FILE_INSTRUMENT_VERSION);\n      Epoch::Type type = Arc::getType(arcList);\n      file.comment(Epoch::getTypeName(type));\n      file<<nameValue(\"satelliteType\", static_cast<Int>(type));\n      file<<nameValue(\"arcCount\",      arcList.size());\n      const std::string comment = Epoch::fileFormatString(type);\n      file.comment(comment);\n      file.comment(std::string(comment.size(), '='));\n      for(const Arc &arc : arcList)\n      {\n        file<<beginGroup(\"arc\");\n        file<<nameValue(\"pointCount\", arc.size());\n        for(UInt i=0; i<arc.size(); i++)\n        {\n          file<<beginGroup(\"epoch\");\n          arc.at(i).save(file.outArchive());\n          file<<endGroup(\"epoch\");\n        }\n        file<<endGroup(\"arc\");\n      }\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n\n  /** @brief Factory for Instrument file. */\n  static InstrumentFilePtr newFile(const std::string &name=\"\") {return std::make_shared<InstrumentFile>(name);}\n};\n\n/***********************************************/\n\n/** @brief Write into an Instrument file. */\ninline void writeFileInstrument(const FileName &name, const Arc &arc) {InstrumentFile::write(name, arc);}\ntemplate<typename T> inline void writeFileInstrument(const FileName &name, ArcTemplate<T> &arc) {InstrumentFile::write(name, arc);}\ntemplate<typename Container> inline void writeFileInstrument(const FileName &name, const Container &arcList) {InstrumentFile::write(name, arcList);}\n\n/***********************************************/\n/***** Derived data types **********************/\n/***********************************************/\n// implementation of a new data\n// 1. define new enum in Epoch (see top)\n// 2. expand Epoch::create(Type type) in fileSatellite.cpp\n// 3. expand Epoch::getTypeName(Type type) in fileSatellite.cpp\n// 4. expand Epoch::dataCount(Type type) in fileSatellite.cpp\n// 5. implement load, save, data, and setData in fileSatellite.cpp\n/***********************************************/\n\n/** @brief Epoch with a vector of values. */\nclass MiscValuesEpoch : public Epoch\n{\npublic:\n  Vector values;\n\n  MiscValuesEpoch(UInt size) : values(size) {}\n\n  static constexpr Type type = MISCVALUES;\n  virtual Type   getType() const {return values.size() ? static_cast<Type>(values.size()) : MISCVALUES;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new MiscValuesEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<MiscValuesEpoch> MiscValuesArc;\n\n/***********************************************/\n\n/** @brief Epoch with time data only. */\nclass InstrumentTimeEpoch : public Epoch\n{\npublic:\n  static constexpr Type type = INSTRUMENTTIME;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new InstrumentTimeEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<InstrumentTimeEpoch> InstrumentTimeArc;\n\n/***********************************************/\n\n/** @brief Epoch with a single value. */\nclass MiscValueEpoch : public Epoch\n{\npublic:\n  Double value;\n\n  MiscValueEpoch() : value(0) {}\n\n  static constexpr Type type = MISCVALUE;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new MiscValueEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<MiscValueEpoch> MiscValueArc;\n\n/***********************************************/\n\n/** @brief Epoch with a vector of values. */\nclass Vector3dEpoch : public Epoch\n{\npublic:\n  Vector3d vector3d;\n\n  static constexpr Type type = VECTOR3D;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new Vector3dEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<Vector3dEpoch> Vector3dArc;\n\n/***********************************************/\n\n/** @brief Epoch with 3x3 covariance matrix of Vector3d data. */\nclass Covariance3dEpoch : public Epoch\n{\npublic:\n  Tensor3d covariance;\n\n  static constexpr Type type = COVARIANCE3D;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new Covariance3dEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<Covariance3dEpoch> Covariance3dArc;\n\n/***********************************************/\n\n/** @brief Epoch with orbit data. */\nclass OrbitEpoch : public Epoch\n{\npublic:\n  Vector3d position;\n  Vector3d velocity;\n  Vector3d acceleration;\n\n  static constexpr Type type = ORBIT;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new OrbitEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<OrbitEpoch> OrbitArc;\n\n/***********************************************/\n\n/** @brief Epoch with star camera data (rotation). */\nclass StarCameraEpoch : public Epoch\n{\npublic:\n  Rotary3d rotary;\n\n  static constexpr Type type = STARCAMERA;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new StarCameraEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<StarCameraEpoch> StarCameraArc;\n\n/***********************************************/\n\n/** @brief Epoch with accelerometer data (accelerations). */\nclass AccelerometerEpoch : public Epoch\n{\npublic:\n  Vector3d acceleration;\n\n  static constexpr Type type = ACCELEROMETER;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new AccelerometerEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<AccelerometerEpoch> AccelerometerArc;\n\n/***********************************************/\n\n/** @brief Epoch with (low-low) satellite tracking data. */\nclass SatelliteTrackingEpoch : public Epoch\n{\npublic:\n  Double range;\n  Double rangeRate;\n  Double rangeAcceleration;\n\n  SatelliteTrackingEpoch() : range(0), rangeRate(0), rangeAcceleration(0) {}\n\n  static constexpr Type type = SATELLITETRACKING;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new SatelliteTrackingEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<SatelliteTrackingEpoch> SatelliteTrackingArc;\n\n/***********************************************/\n\n/** @brief Epoch with gradiometer data (gravity gradients). */\nclass GradiometerEpoch : public Epoch\n{\npublic:\n  Tensor3d gravityGradient;\n\n  static constexpr Type type = GRADIOMETER;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new GradiometerEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<GradiometerEpoch> GradiometerArc;\n\n/***********************************************/\n\n/** @brief Epoch with GNSS receiver observations. */\nclass GnssReceiverEpoch : public Epoch\n{\npublic:\n  std::vector<GnssType> obsType;\n  std::vector<GnssType> satellite;\n  std::vector<Double>   observation;\n  Double                clockError;\n\n  GnssReceiverEpoch() : clockError(0.) {}\n\n  static constexpr Type type = GNSSRECEIVER;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new GnssReceiverEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<GnssReceiverEpoch> GnssReceiverArc;\n\n/***********************************************/\n/***********************************************/\n\n/** @brief Epoch with observations sigma. */\nclass ObservationSigmaEpoch : public Epoch\n{\npublic:\n  Double sigma;\n\n  ObservationSigmaEpoch() : sigma(0) {}\n\n  static constexpr Type type = OBSERVATIONSIGMA;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new ObservationSigmaEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<ObservationSigmaEpoch> ObservationSigmaArc;\n\n/***********************************************/\n\n/** @brief Epoch with mass data. */\nclass MassEpoch : public Epoch\n{\npublic:\n  Double massThr;\n  Double massTank;\n\n  static constexpr Type type = MASS;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new MassEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<MassEpoch> MassArc;\n\n/***********************************************/\n\n/** @brief Epoch with thruster data. */\nclass ThrusterEpoch : public Epoch\n{\npublic:\n  UInt onTime1, onTime2, onTime3,  onTime4,  onTime5,  onTime6,  onTime7,\n         onTime8, onTime9, onTime10, onTime11, onTime12, onTime13, onTime14;\n\n  static constexpr Type type = THRUSTER;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new ThrusterEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<ThrusterEpoch> ThrusterArc;\n\n/***********************************************/\n\n/** @brief Epoch with magnetometer data. */\nclass MagnetometerEpoch : public Epoch\n{\npublic:\n  Vector3d magneticField;\n  Vector3d torquerA;\n  Vector3d torquerB;\n  Vector3d magneticFieldCalibration;\n  Double   torquerCalibration;\n\n  static constexpr Type type = MAGNETOMETER;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new MagnetometerEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<MagnetometerEpoch> MagnetometerArc;\n\n/***********************************************/\n\n/** @brief Epoch with IPU housekeeping data. */\nclass AccHousekeepingEpoch : public Epoch\n{\npublic:\n  Double   biasVoltage; // proof mass bias voltage (averaged) [V]\n  Double   vd;          // amplitude of the AC voltages that operates the position sensors [Vrms]\n  Vector3d xOut;        // displacement of capacitive sensor X1, X2, X3 [m]\n  Vector3d yOut;        // displacement of capacitive sensor Y2, Y2, Z1 [m]\n  Double   tempSU;      // temperature of SU electronics          [°C]\n  Double   tempICU;     // temperature of ICU power supply board  [°C]\n  Double   tempCore;    // temperature of internal core           [°C]\n  Double   tempICUConv; // temperature of ICU A/D converter board [°C]\n  UInt     blkNrICU;    // ICU block number\n\n  static constexpr Type type = ACCHOUSEKEEPING;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new AccHousekeepingEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<AccHousekeepingEpoch> AccHousekeepingArc;\n\n/***********************************************/\n\n/** @brief Epoch with clock data. */\nclass ClockEpoch : public Epoch\n{\npublic:\n  Int    rcvTime;\n  Double epsTime;\n  Double epsError, epsDrift, driftError;\n  UInt   qualityFlag;\n\n  static constexpr Type type = CLOCK;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new ClockEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<ClockEpoch> ClockArc;\n\n/***********************************************/\n\n/** @brief Epoch with Level-1A star camera data (quaternions). */\nclass StarCamera1AEpoch : public Epoch\n{\npublic:\n  Int    rcvTime;\n  Double epsTime;\n  UInt   scaDesign; // 1 = primary SCA, 2 = secondary SCA\n  Double q0, q1, q2, q3;\n  UInt   nLocks;\n  UInt   nStars;\n\n  static constexpr Type type = STARCAMERA1A;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new StarCamera1AEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<StarCamera1AEpoch> StarCamera1AArc;\n\n/***********************************************/\n\n/** @brief Epoch with Level-1A accelerometer data (accelerations). */\nclass Accelerometer1AEpoch : public Epoch\n{\npublic:\n  Int      rcvTimeInt;\n  Double   rcvTimeFrac;\n  Vector3d acceleration;\n\n  static constexpr Type type = ACCELEROMETER1A;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new Accelerometer1AEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<Accelerometer1AEpoch> Accelerometer1AArc;\n\n/***********************************************/\n\n/** @brief Epoch with SLR normal point data. */\nclass SatelliteLaserRangingEpoch : public Epoch\n{\npublic:\n  Double range;              // One way range [m]\n  Double accuracy;           // Accuracy of one-way normal point [m]\n  Double redundancy;         // Number of raw ranges (after editing) compressed into the normal point\n  Double window;             // Normal point window length [s]\n  Double wavelength;         // Laser transmit wavelength [m]\n  Double azmiuth, elevation; // In local system towards satellite [rad]\n\n  static constexpr Type type = SATELLITELASERRANGING;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new SatelliteLaserRangingEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<SatelliteLaserRangingEpoch> SatelliteLaserRangingArc;\n\n/***********************************************/\n\n/** @brief Epoch with meteorological data. */\nclass MeteorologicalEpoch : public Epoch\n{\npublic:\n  Double temperature;    // [K]\n  Double pressure;       // [Pa]\n  Double humidity;       // [%]\n  Double windSpeed;      // [m/s]\n  Double solarRadiation; // [W/m^2]\n  Double precipitation;  // [mm/d]\n\n  static constexpr Type type = METEOROLOGICAL;\n  virtual Type   getType() const {return type;}\n  virtual Vector data()    const; // data without time\n  virtual void   setData(const Vector &x);\n  virtual Epoch *clone()   const {return new MeteorologicalEpoch(*this);}\n  virtual void   save(OutArchive &oa) const;\n  virtual void   load(InArchive  &ia);\n};\n\ntypedef ArcTemplate<MeteorologicalEpoch> MeteorologicalArc;\n\n/***********************************************/\n\n/// @}\n\n#endif // __GROOPS_FILESATELLITE__\n"
  },
  {
    "path": "source/files/fileMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file fileMatrix.cpp\n*\n* @brief Read/write Matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-07\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_Matrix\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n\nGROOPS_REGISTER_FILEFORMAT(Matrix, FILE_MATRIX_TYPE)\n\n/***********************************************/\n\nvoid writeFileMatrix(const FileName &fileName, const const_MatrixSlice &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_MATRIX_TYPE, FILE_MATRIX_VERSION);\n    file<<nameValue(\"matrix\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileMatrix(const FileName &fileName, Matrix &x)\n{\n  try\n  {\n    InFileArchive file(fileName, \"\"/*arbitrary type*/, std::max(FILE_MATRIX_VERSION, FILE_INSTRUMENT_VERSION));\n    if(file.type().empty() || (file.type() == FILE_MATRIX_TYPE))\n      file>>nameValue(\"matrix\", x);\n    else if(file.type() == FILE_INSTRUMENT_TYPE)\n      x = InstrumentFile::read(fileName).matrix();\n    else\n      throw(Exception(\"file type is '\"+file.type()+\"' but must be '\"+FILE_MATRIX_TYPE+\"' or '\"+FILE_INSTRUMENT_TYPE+\"'\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileMatrix.h",
    "content": "/***********************************************/\n/**\n* @file fileMatrix.h\n*\n* @brief Read/write Matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-02-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEMATRIX__\n#define __GROOPS_FILEMATRIX__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_Matrix\nstatic const char *docstringMatrix = R\"(\nStores matrices and vectors. Only one triangle is written for symmetric or triangular matrices.\n\nThe header (the matrix definition) is optional.\nTherefore a pure text with only numbers in columns are also allowed.\nThis simplifies the handling of external data.\n\nInstead of a matrix file also an \\file{instrument}{instrument} file is allowed.\nThe first column is the time [MJD], the other columns depends on the instrument type.\n\n\\begin{verbatim}\ngroops matrix version=20200123\nLowerSymmetricMatrix( 4 x 4 )\n  1.000000000000000000e+00\n  0.000000000000000000e+00  1.000000000000000000e+00\n  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00\n  0.000000000000000000e+00  0.000000000000000000e+00  0.000000000000000000e+00  1.000000000000000000e+00\n\\end{verbatim}\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/matrix.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_MATRIX_TYPE    = \"matrix\";\nconstexpr UInt    FILE_MATRIX_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a Matrix file. */\nvoid writeFileMatrix(const FileName &fileName, const const_MatrixSlice &x);\n\n/** @brief Read from a Matrix file. */\nvoid readFileMatrix(const FileName &fileName, Matrix &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileMeanPolarMotion.cpp",
    "content": "/***********************************************/\n/**\n* @file fileMeanPolarMotion.cpp\n*\n* @brief Read/write MeanPolarMotion.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_MeanPolarMotion\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileMeanPolarMotion.h\"\n\nGROOPS_REGISTER_FILEFORMAT(MeanPolarMotion, FILE_MEANPOLARMOTION_TYPE)\n\n/***********************************************/\n\nvoid MeanPolarMotion::compute(const Time &time, Double &xBar, Double &yBar) const\n{\n  try\n  {\n    xBar = 0;\n    yBar = 0;\n    if(timeStart.size() == 0)\n      return;\n\n    // find correct interval\n    if(time<timeStart.at(0))\n      throw(Exception(\"mean pole model is not valid before \"+timeStart.at(0).dateTimeStr()));\n    UInt idxInterval = 0;\n    while((idxInterval+1 < timeStart.size()) && (time >= timeStart.at(idxInterval+1)))\n      idxInterval++;\n\n    // mean pole (IERS2010, eq. (7.25))\n    Double tn   = 1;\n    const Double t = (time.mjd()-J2000)/365.25; // years after J2000\n    for(UInt n=0; n<=degree.at(idxInterval); n++)\n    {\n      xBar += tn * xp.at(idxInterval)(n);\n      yBar += tn * yp.at(idxInterval)(n);\n      tn *= t;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const MeanPolarMotion &x)\n{\n  const UInt intervalCount = x.timeStart.size();\n  ar<<nameValue(\"intervalCount\", intervalCount);\n  if(!intervalCount)\n    return;\n\n  //comment\n  const UInt maxDegree = *std::max_element(x.degree.begin(), x.degree.end());\n  std::string str = \"start time [MJD]            degree\";\n  for(UInt n=0; n<=maxDegree; n++)\n    str += \"  xp [arcsec/year^\"+n%\"%i\"s+\"]      \";\n  for(UInt n=0; n<=maxDegree; n++)\n    str += \"  yp [arcsec/year^\"+n%\"%i\"s+\"]      \";\n  ar.comment(str);\n  ar.comment(std::string(str.size(), '='));\n\n  for(UInt idxInterval=0; idxInterval<intervalCount; idxInterval++)\n  {\n    ar<<beginGroup(\"interval\");\n    ar<<nameValue(\"timeStart\", x.timeStart.at(idxInterval));\n    ar<<nameValue(\"degree\",    x.degree.at(idxInterval));\n    for(UInt n=0; n<=x.degree.at(idxInterval); n++)\n      ar<<nameValue(\"xp\", x.xp.at(idxInterval)(n));\n    for(UInt n=0; n<=x.degree.at(idxInterval); n++)\n      ar<<nameValue(\"yp\", x.yp.at(idxInterval)(n));\n    ar<<endGroup(\"interval\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, MeanPolarMotion &x)\n{\n  UInt intervalCount;\n  ar>>nameValue(\"intervalCount\", intervalCount);\n  x.timeStart.resize(intervalCount);\n  x.degree.resize(intervalCount);\n  x.xp.resize(intervalCount);\n  x.yp.resize(intervalCount);\n  for(UInt idxInterval=0; idxInterval<intervalCount; idxInterval++)\n  {\n    ar>>beginGroup(\"interval\");\n    ar>>nameValue(\"timeStart\", x.timeStart.at(idxInterval));\n    ar>>nameValue(\"degree\",    x.degree.at(idxInterval));\n    x.xp.at(idxInterval) = Vector(x.degree.at(idxInterval)+1);\n    x.yp.at(idxInterval) = Vector(x.degree.at(idxInterval)+1);\n    for(UInt n=0; n<=x.degree.at(idxInterval); n++)\n      ar>>nameValue(\"xp\", x.xp.at(idxInterval)(n));\n    for(UInt n=0; n<=x.degree.at(idxInterval); n++)\n      ar>>nameValue(\"yp\", x.yp.at(idxInterval)(n));\n    ar>>endGroup(\"interval\");\n  }\n}\n\n/***********************************************/\n\nvoid writeFileMeanPolarMotion(const FileName &fileName, const MeanPolarMotion &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_MEANPOLARMOTION_TYPE, FILE_MEANPOLARMOTION_VERSION);\n    file<<nameValue(\"meanPolarMotion\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileMeanPolarMotion(const FileName &fileName, MeanPolarMotion &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_MEANPOLARMOTION_TYPE, FILE_MEANPOLARMOTION_VERSION);\n    file>>nameValue(\"meanPolarMotion\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileMeanPolarMotion.h",
    "content": "/***********************************************/\n/**\n* @file fileMeanPolarMotion.h\n*\n* @brief Read/write MeanPolarMotion.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEMEANPOLARMOTION__\n#define __GROOPS_FILEMEANPOLARMOTION__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_MeanPolarMotion\nstatic const char *docstringMeanPolarMotion = R\"(\nThe mean pole of the Earth rotation is represented by a polynomial in a time interval.\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"meanPolarMotion\" version=\"20200123\">\n  <meanPolarMotion>\n    <intervalCount>2</intervalCount>\n    <interval>\n      <timeStart>42778.0000000000000000</timeStart>\n      <degree>3</degree>\n      <xp>5.59741000000000e-02</xp>\n      <xp>1.82430000000000e-03</xp>\n      <xp>1.84130000000000e-04</xp>\n      <xp>7.02400000000000e-06</xp>\n      <yp>3.46346000000000e-01</yp>\n      <yp>1.78960000000000e-03</yp>\n      <yp>-1.07290000000000e-04</yp>\n      <yp>-9.08000000000000e-07</yp>\n    </interval>\n    <interval>\n      <timeStart>55197.0000000000000000</timeStart>\n      <degree>1</degree>\n      <xp>2.35130000000000e-02</xp>\n      <xp>7.61410000000000e-03</xp>\n      <yp>3.58891000000000e-01</yp>\n      <yp>-6.28700000000000e-04</yp>\n    </interval>\n  </meanPolarMotion>\n</groops>\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_MEANPOLARMOTION_TYPE    = \"meanPolarMotion\";\nconstexpr UInt    FILE_MEANPOLARMOTION_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief MeanPolarMotions.\n* The mean polar motion is described as polynomials in time intervals. */\nclass MeanPolarMotion\n{\npublic:\n  std::vector<Time>   timeStart;\n  std::vector<UInt>   degree;\n  std::vector<Vector> xp, yp;\n\n  void compute(const Time &time, Double &xBar, Double &yBar) const;\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const MeanPolarMotion &x);\ntemplate<> void load(InArchive  &ar, MeanPolarMotion &x);\n\n/** @brief Write into a MeanPolarMotion file. */\nvoid writeFileMeanPolarMotion(const FileName &fileName, const MeanPolarMotion &x);\n\n/** @brief Read from a MeanPolarMotion file. */\nvoid readFileMeanPolarMotion(const FileName &fileName, MeanPolarMotion &x);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/files/fileNormalEquation.cpp",
    "content": "/***********************************************/\n/**\n* @file fileNormalEquation.cpp\n*\n* @brief Read/write a system of normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-05-27\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_NormalEquation\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"files/fileNormalEquation.h\"\n\nGROOPS_REGISTER_FILEFORMAT(NormalEquation, FILE_NORMALEQUATION_TYPE)\n\n/***********************************************/\n\nstatic void writeInfoFile(const FileName &name, const NormalEquationInfo &info, const Matrix &n)\n{\n  try\n  {\n    if((info.blockIndex.back() != n.rows()) || (info.lPl.rows() != n.columns()) || (info.parameterName.size() != n.rows()))\n      throw(Exception(\"<\"+name.str()+\"> dimension error\"));\n    if(n.rows() && !info.usedBlocks.size())\n      throw(Exception(\"no used blocks defined\"));\n\n    FileName nameInfo(name.replaceFullExtension(\".info.xml\"));\n    OutFileArchive file(nameInfo, FILE_NORMALEQUATION_TYPE, FILE_NORMALEQUATION_VERSION);\n    file<<nameValue(\"observationCount\",   info.observationCount);\n    file<<nameValue(\"parameterCount\",     info.blockIndex.back());\n    file<<nameValue(\"rightHandSideCount\", info.lPl.rows());\n    for(UInt i=0; i<info.lPl.rows(); i++)\n      file<<nameValue(\"lPl\", info.lPl(i));\n    file<<nameValue(\"blockCount\", info.blockIndex.size()-1);\n    for(UInt i=0; i<info.blockIndex.size()-1; i++)\n      file<<nameValue(\"blockSize\", info.blockIndex.at(i+1)-info.blockIndex.at(i));\n//     file<<nameValue(\"extension\",  name.extension().str());\n    file<<nameValue(\"usedBlocks\", info.usedBlocks);\n\n    // parameter name file\n    writeFileParameterName(name.replaceFullExtension(\".parameterNames.txt\"), info.parameterName);\n\n    // right hand side\n    writeFileMatrix(name.appendBaseName(\".rightHandSide\"), n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const Matrix &N, const Matrix &n)\n{\n  try\n  {\n    Bool writeBlock = !isStrictlyZero(N);\n    // info file\n    info.blockIndex = {0, N.rows()};\n    info.usedBlocks = identityMatrix(writeBlock ? 1 : 0);\n    writeInfoFile(name, info, n);\n\n    // normal matrix\n    if(writeBlock)\n      writeFileMatrix(name, N);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const std::vector<std::vector<Matrix>> &N, const Matrix &n)\n{\n  try\n  {\n    const UInt blockCount = N.size();\n    info.blockIndex = std::vector<UInt>(blockCount+1, 0);\n    for(UInt i=0; i<blockCount; i++)\n      info.blockIndex.at(i+1) = info.blockIndex.at(i) + N.at(i).at(i).rows();\n\n    info.usedBlocks = Matrix(blockCount, Matrix::SYMMETRIC);\n    for(UInt i=0; i<blockCount; i++)\n      for(UInt k=i; k<blockCount; k++)\n        if(N.at(i).at(k).size() && !isStrictlyZero(N.at(i).at(k)))\n          info.usedBlocks(i,k) = 1;\n\n    // info file\n    writeInfoFile(name, info, n);\n\n    // normal matrix\n    for(UInt i=0; i<blockCount; i++)\n      for(UInt k=i; k<blockCount; k++)\n        if(info.usedBlocks(i,k) > 0)\n          writeFileMatrix(name.appendBaseName((blockCount>1) ? \".\"+i%\"%02i-\"s+k%\"%02i\"s : \"\"s), N.at(i).at(k));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const MatrixDistributed &normal, const Matrix &n)\n{\n  try\n  {\n    info.blockIndex = normal.blockIndex();\n    info.usedBlocks = Matrix(normal.blockCount(), Matrix::SYMMETRIC);\n    for(UInt i=0; i<normal.blockCount(); i++)\n      for(UInt k=i; k<normal.blockCount(); k++)\n        if(normal.isMyRank(i,k))\n          info.usedBlocks(i,k) = isStrictlyZero(normal.N(i, k)) ? 0 : 1;\n    Parallel::reduceSum(info.usedBlocks, 0, normal.communicator());\n\n    // info file\n    if(Parallel::isMaster(normal.communicator()))\n      writeInfoFile(name, info, n);\n\n    // normal matrix\n    for(UInt i=0; i<normal.blockCount(); i++)\n      for(UInt k=i; k<normal.blockCount(); k++)\n        if(normal.isMyRank(i,k) && !isStrictlyZero(normal.N(i, k)))\n          writeFileMatrix(name.appendBaseName((normal.blockCount()>1) ? \".\"+i%\"%02i-\"s+k%\"%02i\"s : \"\"s), normal.N(i, k));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const Matrix &n)\n{\n  try\n  {\n    writeInfoFile(name, info, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic void readInfoFile(const FileName &name, NormalEquationInfo &info, Matrix &n)\n{\n  try\n  {\n    info.blockIndex.clear();\n    info.blockIndex.push_back(0);\n\n    FileName nameInfo(name.replaceFullExtension(\".info.xml\"));\n    InFileArchive file(nameInfo, FILE_NORMALEQUATION_TYPE, FILE_NORMALEQUATION_VERSION);\n    UInt paramCount, rhsCount, blockCount;\n    file>>nameValue(\"observationCount\",   info.observationCount);\n    file>>nameValue(\"parameterCount\",     paramCount);\n    file>>nameValue(\"rightHandSideCount\", rhsCount);\n    // old version\n    if(file.version() == 1)\n    {\n      logWarning<<\"file <\"<<name<<\"> is saved as an old version, please save as new version\"<<Log::endl;\n      file>>nameValue(\"lPl\", info.lPl);\n      info.blockIndex.push_back(info.blockIndex.back() + paramCount);\n      blockCount = 1;\n    }\n    else // new version\n    {\n      info.lPl = Vector(rhsCount);\n      for(UInt i=0; i<rhsCount; i++)\n        file>>nameValue(\"lPl\", info.lPl(i));\n      file>>nameValue(\"blockCount\", blockCount);\n      UInt size;\n      for(UInt i=0; i<blockCount; i++)\n      {\n        file>>nameValue(\"blockSize\", size);\n        info.blockIndex.push_back(info.blockIndex.back() + size);\n      }\n//     file>>nameValue(\"extension\", name.stripExtension());\n    }\n\n    try\n    {\n      file>>nameValue(\"usedBlocks\", info.usedBlocks);\n    }\n    catch(std::exception &/*e*/)\n    {\n      info.usedBlocks = Matrix(blockCount, Matrix::SYMMETRIC);\n      for(UInt i=0; i<blockCount; i++)\n        for(UInt k=i; k<blockCount; k++)\n          info.usedBlocks(i,k) = 1;\n    }\n\n    // read parameter name file\n    // ------------------------\n    info.parameterName.clear();\n    FileName fileNameParameterNames(name.replaceFullExtension(\".parameterNames.txt\"));\n    try\n    {\n      readFileParameterName(fileNameParameterNames, info.parameterName);\n    }\n    catch(std::exception &/*e*/)\n    {\n      info.parameterName.clear();\n      info.parameterName.resize(paramCount);\n    }\n\n    // read ride hand side\n    // ------------------------\n    readFileMatrix(name.appendBaseName(\".rightHandSide\"), n);\n    if((n.columns() != info.lPl.rows()) || (n.rows() != info.blockIndex.back()))\n      throw(Exception(\"dimension error\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileNormalEquation(const FileName &name, NormalEquationInfo &info, Matrix &N, Matrix &n)\n{\n  try\n  {\n    readInfoFile(name, info, n);\n    const std::vector<UInt> *blockIndex = &info.blockIndex; // just for readability\n\n    // read normal equation\n    if(blockIndex->size() == 2)\n    {\n      readFileMatrix(name, N);\n      if(N.rows() != blockIndex->back())\n        throw(Exception(\"<\"+name.str()+\"> dimension error\"));\n    }\n    else\n    {\n      N = Matrix(blockIndex->back(), Matrix::SYMMETRIC);\n      for(UInt i=0; i<blockIndex->size()-1; i++)\n        for(UInt k=i; k<blockIndex->size()-1; k++)\n          if(!info.usedBlocks.size() || (info.usedBlocks.size() && info.usedBlocks(i,k) > 0))\n          {\n            Matrix M;\n            readFileMatrix(name.appendBaseName(\".\"+i%\"%02i-\"s+k%\"%02i\"s), M);\n            copy(M, N.slice(blockIndex->at(i), blockIndex->at(k), blockIndex->at(i+1)-blockIndex->at(i), blockIndex->at(k+1)-blockIndex->at(k)));\n          }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileNormalEquation(const FileName &name, NormalEquationInfo &info, MatrixDistributed &normal, Matrix &n, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    readInfoFile(name, info, n);\n\n    // read normal equation\n    normal.initEmpty(info.blockIndex, comm);\n    for(UInt i=0; i<normal.blockCount(); i++)\n      for(UInt k=i; k<normal.blockCount(); k++)\n      {\n        if((!info.usedBlocks.size() || (info.usedBlocks.size() && info.usedBlocks(i,k) > 0)))\n        {\n          normal.setBlock(i, k);\n          if(normal.isMyRank(i,k))\n            readFileMatrix(name.appendBaseName((normal.blockCount()>1) ? \".\"+i%\"%02i-\"s+k%\"%02i\"s : \"\"s), normal.N(i,k));\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileNormalEquation(const FileName &name, NormalEquationInfo &info, Matrix &n)\n{\n  try\n  {\n    readInfoFile(name, info, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileNormalEquation.h",
    "content": "/***********************************************/\n/**\n* @file fileNormalEquation.h\n*\n* @brief Read/write a system of normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-05-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILENORMALEQUATION__\n#define __GROOPS_FILENORMALEQUATION__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_NormalEquation\nstatic const char *docstringNormalEquation = R\"(\nStores a \\reference{system of normal equations}{normalEquationType}\n\\begin{equation}\n  \\M N \\hat{\\M x} = \\M n.\n\\end{equation}.\nThis file format consists of multiple files.\nThe file name \\verb|normals.dat.gz| corresponds to the following files:\n\\begin{itemize}\n\\item \\verb|normals.dat.gz| or \\verb|normals.00.00.dat.gz| ... \\verb|normals.0n.0n.dat.gz|:\n      the normal matrix $\\M N$ as \\file{matrix}{matrix},\n\\item \\verb|normals.rightHandSide.dat.gz|:\n      the right hand side(s) $\\M n$ as \\file{matrix}{matrix},\n\\item \\verb|normals.parameterNames.txt|: \\file{parameter names}{parameterName},\n\\item \\verb|normals.info.xml|:\n\\     u.a. containing the number of observations and the quadratic sum of (reduced) observations $\\M l^T\\M P\\M l$.\n\\end{itemize}\nA large normal matrix may be splitted into blocks and stored in multiple files.\nThe block row/column number is indicated in the file name.\nOnly the upper blocks of the sysmmetric matrix are considered.\nMatrix in blocks can be distributed on muliple nodes in parallel mode to efficiently use distributed memory.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/parameterName.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileMatrix.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_NORMALEQUATION_TYPE    = \"normalEquation\";\nconstexpr UInt    FILE_NORMALEQUATION_VERSION = std::max(std::max(UInt(20200123), FILE_MATRIX_VERSION), FILE_BASE_VERSION);\n\n/***** CLASSES **********************************/\n\nclass NormalEquationInfo\n{\npublic:\n  std::vector<ParameterName> parameterName;\n  Vector lPl;\n  UInt observationCount;\n  std::vector<UInt> blockIndex;\n  Matrix usedBlocks;\n\n  NormalEquationInfo(UInt rhsCount = 1) : lPl(rhsCount), observationCount(0) {}\n  NormalEquationInfo(const std::vector<ParameterName> &parameterName_, const Vector &lPl_ = Vector(1), UInt observationCount_ = 0)\n    : parameterName(parameterName_), lPl(lPl_), observationCount(observationCount_) {}\n};\n\n/***** FUNCTIONS ********************************/\n\n/** @brief Write a system of normal equations. */\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const Matrix &N, const Matrix &n);\n\n/** @brief Write a system of normal equations. */\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const std::vector<std::vector<Matrix>> &N, const Matrix &n);\n\nclass MatrixDistributed;\n/** @brief Write a system of normal equations.\n* Must be called on every process.\n* Only at master needed: @a parameterName, @a n, @a lPl, @a observationCount. */\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const MatrixDistributed &N, const Matrix &n);\n\n/** @brief Write a system of normal equations.\n* Only the information file, parameter name file and the right hand sides are written. */\nvoid writeFileNormalEquation(const FileName &name, NormalEquationInfo info, const Matrix &n);\n\n/***********************************************/\n\n/** @brief Read a system of normal equations. */\nvoid readFileNormalEquation(const FileName &name, NormalEquationInfo &info, Matrix &N, Matrix &n);\n\n/** @brief Write a system of normal equations.\n* Must be called on every process in @p comm. */\nvoid readFileNormalEquation(const FileName &name, NormalEquationInfo &info, MatrixDistributed &normal, Matrix &n, Parallel::CommunicatorPtr comm);\n\n/** @brief Read a system of normal equations.\n* Only the information file, parameter name file and the right hand sides are read. */\nvoid readFileNormalEquation(const FileName &name, NormalEquationInfo &info, Matrix &n);\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileOceanPoleTide.cpp",
    "content": "/***********************************************/\n/**\n* @file fileOceanPoleTide.cpp\n*\n* @brief Read/write OceanPoleTide.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_OceanPoleTide\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileOceanPoleTide.h\"\n\nGROOPS_REGISTER_FILEFORMAT(OceanPoleTide, FILE_OCEANPOLETIDE_TYPE)\n\n/***********************************************/\n\nvoid writeFileOceanPoleTide(const FileName &fileName, const SphericalHarmonics &harmReal, const SphericalHarmonics &harmImag)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_OCEANPOLETIDE_TYPE, FILE_OCEANPOLETIDE_VERSION);\n    file<<nameValue(\"harmonicsReal\",      harmReal);\n    file<<nameValue(\"harmonicsImaginary\", harmImag);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileOceanPoleTide(const FileName &fileName, SphericalHarmonics &harmReal, SphericalHarmonics &harmImag)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_OCEANPOLETIDE_TYPE, FILE_OCEANPOLETIDE_VERSION);\n    file>>nameValue(\"harmonicsReal\",      harmReal);\n    file>>nameValue(\"harmonicsImaginary\", harmImag);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileOceanPoleTide.h",
    "content": "/***********************************************/\n/**\n* @file fileOceanPoleTide.h\n*\n* @brief Read/write OceanPoleTide.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-09\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEOCEANPOLETIDE__\n#define __GROOPS_FILEOCEANPOLETIDE__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_OceanPoleTide\nstatic const char *docstringOceanPoleTide = R\"(\nDescribes the reaction of the ocean mass to the change\nof the centrifugal potential (polar wobble) in terms spherical harmonics.\n\nSee also \\program{Iers2OceanPoleTide}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/sphericalHarmonics.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_OCEANPOLETIDE_TYPE    = \"oceanPoleTide\";\nconstexpr UInt    FILE_OCEANPOLETIDE_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a OceanPoleTide file. */\nvoid writeFileOceanPoleTide(const FileName &fileName, const SphericalHarmonics &harmReal, const SphericalHarmonics &harmImag);\n\n\n/** @brief Read from a OceanPoleTide file. */\nvoid readFileOceanPoleTide(const FileName &fileName, SphericalHarmonics &harmReal, SphericalHarmonics &harmImag);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileParameterName.cpp",
    "content": "/***********************************************/\n/**\n* @file fileParameterName.cpp\n*\n* @brief Read/write ParameterName.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-07-31\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_ParameterName\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileParameterName.h\"\n\nGROOPS_REGISTER_FILEFORMAT(ParameterName, FILE_PARAMETERNAME_TYPE)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const ParameterName &x)\n{\n  save(ar, x.str());\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, ParameterName &x)\n{\n  std::string str;\n  load(ar, str);\n  x = ParameterName::fromStr(str);\n}\n\n/***********************************************/\n\nvoid writeFileParameterName(const FileName &fileName, const std::vector<ParameterName> &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_PARAMETERNAME_TYPE, FILE_PARAMETERNAME_VERSION);\n    file.comment(\"object:type:temporal:interval\");\n    file.comment(\"=============================\");\n    file<<nameValue(\"parameterName\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileParameterName(const FileName &fileName, std::vector<ParameterName> &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_PARAMETERNAME_TYPE, FILE_PARAMETERNAME_VERSION);\n    file>>nameValue(\"parameterName\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileParameterName.h",
    "content": "/***********************************************/\n/**\n* @file fileParameterName.h\n*\n* @brief Read/write ParameterName.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-07-31\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEPARAMETERNAME__\n#define __GROOPS_FILEPARAMETERNAME__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_ParameterName\nstatic const char *docstringParameterName = R\"(\nName of parameters of a system of \\file{normal equations}{normalEquation} or \\file{solution vector}{matrix}.\n\nA parameter name is a string \\verb|<object>:<type>:<temporal>:<interval>| containg four parts divided by \\verb|:|\n\\begin{enumerate}\n\\item object: Object this parameter refers to, e.g. \\verb|graceA|, \\verb|G023|, \\verb|earth|, \\ldots\n\\item type: Type of this parameter, e.g. \\verb|accBias|, \\verb|position.x|, \\ldots\n\\item temporal: Temporal representation of this parameter, e.g. \\verb|trend|, \\verb|polynomial.degree1|, \\ldots\n\\item interval: Interval/epoch this parameter represents, e.g. \\verb|2017-01-01_00-00-00_2017-01-02_00-00-00|, \\verb|2018-01-01_00-00-00|.\n\\end{enumerate}\nIn the documentation a star (\\verb|*|) in the name means this part is untouched and useally set by other classes.\nTimes are written as \\verb|yyyy-mm-dd_hh-mm-ss| and intervals (if not empty) as \\verb|<timeStart>_<timeEnd>|.\n\nSee \\program{ParameterNamesCreate}.\n\n\\begin{verbatim}\ngroops parameterName version=20200123\n# object:type:temporal:interval\n# =============================\n      10080 # number of parameters\n karr:position.x::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:position.y::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:position.z::2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_02-00-00\n karr:troposphereWet:spline.n1:2018-06-01_00-00-00_2018-06-01_04-00-00\n karr:troposphereWet:spline.n1:2018-06-01_02-00-00_2018-06-01_06-00-00\n karr:troposphereWet:spline.n1:2018-06-01_04-00-00_2018-06-01_08-00-00\n karr:troposphereWet:spline.n1:2018-06-01_06-00-00_2018-06-01_10-00-00\n karr:troposphereWet:spline.n1:2018-06-01_08-00-00_2018-06-01_12-00-00\n karr:troposphereWet:spline.n1:2018-06-01_10-00-00_2018-06-01_14-00-00\n karr:troposphereWet:spline.n1:2018-06-01_12-00-00_2018-06-01_16-00-00\n karr:troposphereWet:spline.n1:2018-06-01_14-00-00_2018-06-01_18-00-00\n karr:troposphereWet:spline.n1:2018-06-01_16-00-00_2018-06-01_20-00-00\n karr:troposphereWet:spline.n1:2018-06-01_18-00-00_2018-06-01_22-00-00\n karr:troposphereWet:spline.n1:2018-06-01_20-00-00_2018-06-02_00-00-00\n karr:troposphereWet:spline.n1:2018-06-01_22-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.x:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:troposphereGradient.y:spline.n1:2018-06-01_00-00-00_2018-06-02_00-00-00\n karr:signalBias01(+1.00L1CG**)::\n karr:signalBias02(+1.00L2WG**)::\n karr:signalBias03(+1.00L2XG**)::\n G01:solarRadiationPressure.ECOM.D0::\n G01:solarRadiationPressure.ECOM.DC2::\n G01:solarRadiationPressure.ECOM.DS2::\n G01:solarRadiationPressure.ECOM.Y0::\n G01:solarRadiationPressure.ECOM.B0::\n G01:solarRadiationPressure.ECOM.BC1::\n G01:solarRadiationPressure.ECOM.BS1::\n G01:stochasticPulse.x::2018-06-01_12-00-00\n G01:stochasticPulse.y::2018-06-01_12-00-00\n G01:stochasticPulse.z::2018-06-01_12-00-00\n G01:arc0.position0.x::\n G01:arc0.position0.y::\n G01:arc0.position0.z::\n G01:arc0.velocity0.x::\n G01:arc0.velocity0.y::\n G01:arc0.velocity0.z::\n G01:signalBias01(-1.00C1CG01)::\n G01:signalBias02(+1.00L1*G01)::\n G01:signalBias03(+1.00L2*G01)::\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/parameterName.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_PARAMETERNAME_TYPE    = \"parameterName\";\nconstexpr UInt    FILE_PARAMETERNAME_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const ParameterName &x);\ntemplate<> void load(InArchive  &ar, ParameterName &x);\n\n/** @brief Write into a ParameterName file. */\nvoid writeFileParameterName(const FileName &fileName, const std::vector<ParameterName> &x);\n\n/** @brief Read from a ParameterName file. */\nvoid readFileParameterName(const FileName &fileName, std::vector<ParameterName> &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/filePlatform.cpp",
    "content": "/***********************************************/\n/**\n* @file filePlatform.cpp\n*\n* @brief Platform equipped with instruments.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-11-07\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_Platform\n\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n#include \"files/filePlatform.h\"\n\nGROOPS_REGISTER_FILEFORMAT(Platform, \"platform\")\n\n/***********************************************/\n\nVector3d Platform::referencePoint(const Time &time) const\n{\n  try\n  {\n    if(!referencePoints.size())\n      return Vector3d(0,0,0);\n\n    auto iter = std::lower_bound(referencePoints.begin(), referencePoints.end(), time,\n                                 [](const auto &x, const Time &time) {return x.timeEnd <= time;});\n    if((iter == referencePoints.end()) || (iter->timeStart > time))\n      throw(Exception(markerName+\".\"+markerNumber+\": no reference point found at \"+time.dateTimeStr()));\n\n    // linear interpolation\n    const Double tau = (time-iter->timeStart).mjd()/(iter->timeEnd-iter->timeStart).mjd();\n    return (1-tau) * iter->pointStart + tau * iter->pointEnd;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Platform::fillGnssAntennaDefinition(const std::vector<GnssAntennaDefinitionPtr> &antennaList)\n{\n  try\n  {\n    for(const auto &eq : equipments)\n    {\n      auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(eq);\n      if(antenna)\n        antenna->antennaDef = GnssAntennaDefinition::find(antennaList, antenna->name, antenna->serial, antenna->radome);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Platform::fillGnssAccuracyDefinition(const std::vector<GnssAntennaDefinitionPtr> &antennaList)\n{\n  try\n  {\n    for(const auto &eq : equipments)\n    {\n      auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(eq);\n      if(antenna)\n        antenna->accuracyDef = GnssAntennaDefinition::find(antennaList, antenna->name, antenna->serial, antenna->radome);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Platform::fillGnssReceiverDefinition(const std::vector<GnssReceiverDefinitionPtr> &receiverList)\n{\n  try\n  {\n    for(const auto &eq : equipments)\n    {\n      auto receiver = std::dynamic_pointer_cast<PlatformGnssReceiver>(eq);\n      if(receiver)\n        receiver->receiverDef = GnssReceiverDefinition::find(receiverList, receiver->name, receiver->serial, receiver->version);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nPlatformEquipmentPtr PlatformEquipment::create(Type type)\n{\n  try\n  {\n    switch(type)\n    {\n      case OTHER:               return std::make_shared<PlatformEquipment>();\n      case GNSSANTENNA:         return std::make_shared<PlatformGnssAntenna>();\n      case GNSSRECEIVER:        return std::make_shared<PlatformGnssReceiver>();\n      case SLRSTATION:          return std::make_shared<PlatformSlrStation>();\n      case LASERRETROREFLECTOR: return std::make_shared<PlatformLaserRetroReflector>();\n      case SATELLITEIDENTIFIER: return std::make_shared<PlatformSatelliteIdentifier>();\n      case UNDEFINED:           break;\n    }\n\n    throw(Exception(\"unknown equipment type (\"+static_cast<Int>(type)%\"%i)\"s));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlatformEquipment::save(OutArchive &/*ar*/) const {}\nvoid PlatformEquipment::load(InArchive &/*ar*/) {}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlatformGnssAntenna::save(OutArchive &ar) const\n{\n  ar<<nameValue(\"radome\",             radome);\n  ar<<nameValue(\"local2antennaFrame\", local2antennaFrame);\n}\n\n/***********************************************/\n\nvoid PlatformGnssAntenna::load(InArchive &ar)\n{\n  ar>>nameValue(\"radome\",             radome);\n  ar>>nameValue(\"local2antennaFrame\", local2antennaFrame);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlatformGnssReceiver::save(OutArchive &ar) const\n{\n  ar<<nameValue(\"version\", version);\n}\n\n/***********************************************/\n\nvoid PlatformGnssReceiver::load(InArchive &ar)\n{\n  ar>>nameValue(\"version\", version);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlatformSlrStation::save(OutArchive &/*ar*/) const\n{\n}\n\n/***********************************************/\n\nvoid PlatformSlrStation::load(InArchive &/*ar*/)\n{\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlatformLaserRetroReflector::save(OutArchive &ar) const\n{\n  ar<<nameValue(\"platform2reflectorFrame\", platform2reflectorFrame);\n  ar<<nameValue(\"dZenit\",                  dZenit);\n  ar<<nameValue(\"range\",                   range);\n}\n\n/***********************************************/\n\nvoid PlatformLaserRetroReflector::load(InArchive &ar)\n{\n  ar>>nameValue(\"platform2reflectorFrame\", platform2reflectorFrame);\n  ar>>nameValue(\"dZenit\",                  dZenit);\n  ar>>nameValue(\"range\",                   range);\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlatformSatelliteIdentifier::save(OutArchive &ar) const\n{\n  ar<<nameValue(\"cospar\", cospar);\n  ar<<nameValue(\"norad\",  norad);\n  ar<<nameValue(\"sic\",    sic);\n  ar<<nameValue(\"sp3\",    sp3);\n}\n\n/***********************************************/\n\nvoid PlatformSatelliteIdentifier::load(InArchive &ar)\n{\n  ar>>nameValue(\"cospar\", cospar);\n  ar>>nameValue(\"norad\",  norad);\n  ar>>nameValue(\"sic\",    sic);\n  ar>>nameValue(\"sp3\",    sp3);\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const Platform &x)\n{\n  try\n  {\n    ar<<nameValue(\"markerName\",     x.markerName);\n    ar<<nameValue(\"markerNumber\",   x.markerNumber);\n    ar<<nameValue(\"comment\",        x.comment);\n    ar<<nameValue(\"approxPosition\", x.approxPosition);\n\n    ar<<nameValue(\"equipmentCount\", x.equipments.size());\n    for(UInt i=0; i<x.equipments.size(); i++)\n    {\n      ar<<beginGroup(\"equipment\");\n      ar<<nameValue(\"type\", static_cast<Int>(x.equipments.at(i)->getType()));\n      ar<<nameValue(\"comment\",   x.equipments.at(i)->comment);\n      ar<<nameValue(\"name\",      x.equipments.at(i)->name);\n      ar<<nameValue(\"serial\",    x.equipments.at(i)->serial);\n      ar<<nameValue(\"timeStart\", x.equipments.at(i)->timeStart);\n      ar<<nameValue(\"timeEnd\",   x.equipments.at(i)->timeEnd);\n      ar<<nameValue(\"position\",  x.equipments.at(i)->position);\n      x.equipments.at(i)->save(ar);\n      ar<<endGroup(\"equipment\");\n    }\n\n    ar<<nameValue(\"referencePointCount\", x.referencePoints.size());\n    for(UInt i=0; i<x.referencePoints.size(); i++)\n    {\n      ar<<beginGroup(\"referencePoint\");\n      ar<<nameValue(\"comment\",    x.referencePoints.at(i).comment);\n      ar<<nameValue(\"timeStart\",  x.referencePoints.at(i).timeStart);\n      ar<<nameValue(\"timeEnd\",    x.referencePoints.at(i).timeEnd);\n      ar<<nameValue(\"pointStart\", x.referencePoints.at(i).pointStart);\n      ar<<nameValue(\"pointEnd\",   x.referencePoints.at(i).pointEnd);\n      ar<<endGroup(\"referencePoint\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, Platform &x)\n{\n  try\n  {\n    ar>>nameValue(\"markerName\",     x.markerName);\n    ar>>nameValue(\"markerNumber\",   x.markerNumber);\n    ar>>nameValue(\"comment\",        x.comment);\n    ar>>nameValue(\"approxPosition\", x.approxPosition);\n\n    UInt equipmentCount;\n    ar>>nameValue(\"equipmentCount\", equipmentCount);\n    x.equipments.resize(equipmentCount);\n    for(UInt i=0; i<equipmentCount; i++)\n    {\n      Int typeInt;\n      ar>>beginGroup(\"equipment\");\n      ar>>nameValue(\"type\", typeInt);\n      x.equipments.at(i) = PlatformEquipment::create(static_cast<PlatformEquipment::Type>(typeInt));\n      ar>>nameValue(\"comment\",   x.equipments.at(i)->comment);\n      ar>>nameValue(\"name\",      x.equipments.at(i)->name);\n      ar>>nameValue(\"serial\",    x.equipments.at(i)->serial);\n      ar>>nameValue(\"timeStart\", x.equipments.at(i)->timeStart);\n      ar>>nameValue(\"timeEnd\",   x.equipments.at(i)->timeEnd);\n      ar>>nameValue(\"position\",  x.equipments.at(i)->position);\n      x.equipments.at(i)->load(ar);\n      ar>>endGroup(\"equipment\");\n    }\n\n    UInt referencePointCount;\n    ar>>nameValue(\"referencePointCount\", referencePointCount);\n    x.referencePoints.resize(referencePointCount);\n    for(UInt i=0; i<referencePointCount; i++)\n    {\n      ar>>beginGroup(\"referencePoint\");\n      ar>>nameValue(\"comment\",    x.referencePoints.at(i).comment);\n      ar>>nameValue(\"timeStart\",  x.referencePoints.at(i).timeStart);\n      ar>>nameValue(\"timeEnd\",    x.referencePoints.at(i).timeEnd);\n      ar>>nameValue(\"pointStart\", x.referencePoints.at(i).pointStart);\n      ar>>nameValue(\"pointEnd\",   x.referencePoints.at(i).pointEnd);\n      ar>>endGroup(\"referencePoint\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFilePlatform(const FileName &fileName, const Platform &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_PLATFORM_TYPE, FILE_PLATFORM_VERSION);\n    file<<nameValue(\"platform\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFilePlatform(const FileName &fileName, Platform &x)\n{\n  try\n  {\n    InFileArchive file(fileName, \"\"/*arbitrary type*/, FILE_PLATFORM_VERSION);\n    if(file.type() == FILE_PLATFORM_TYPE)\n      file>>nameValue(\"platform\", x);\n    else if(file.type() == \"stationInfo\") // old deprecated file format\n    {\n      UInt count;\n      file>>nameValue(\"stationCount\", count);\n      if(count>1)\n        logWarning<<fileName<<\" contain more than one station, only the first is used\"<<Log::endl;\n      file>>beginGroup(\"station\");\n      file>>nameValue(\"markerName\",     x.markerName);\n      file>>nameValue(\"markerNumber\",   x.markerNumber);\n      file>>nameValue(\"comment\",        x.comment);\n      file>>nameValue(\"approxPosition\", x.approxPosition);\n      file>>beginGroup(\"antenna\");\n      {\n        UInt count;\n        file>>nameValue(\"count\", count);\n        for(UInt i=0; i<count; i++)\n        {\n          auto var = std::make_shared<PlatformGnssAntenna>();\n          file>>beginGroup(\"cell\");\n          file>>nameValue(\"name\",               var->name);\n          file>>nameValue(\"serial\",             var->serial);\n          file>>nameValue(\"radome\",             var->radome);\n          file>>nameValue(\"comment\",            var->comment);\n          file>>nameValue(\"timeStart\",          var->timeStart);\n          file>>nameValue(\"timeEnd\",            var->timeEnd);\n          file>>nameValue(\"position\",           var->position);\n          file>>nameValue(\"local2antennaFrame\", var->local2antennaFrame);\n          file>>endGroup(\"cell\");\n          x.equipments.push_back(var);\n        }\n      }\n      file>>endGroup(\"antenna\");\n      file>>beginGroup(\"receiver\");\n      {\n        UInt count;\n        file>>nameValue(\"count\", count);\n        for(UInt i=0; i<count; i++)\n        {\n          auto var = std::make_shared<PlatformGnssReceiver>();\n          file>>beginGroup(\"cell\");\n          file>>nameValue(\"name\",      var->name);\n          file>>nameValue(\"serial\",    var->serial);\n          file>>nameValue(\"version\",   var->version);\n          file>>nameValue(\"comment\",   var->comment);\n          file>>nameValue(\"timeStart\", var->timeStart);\n          file>>nameValue(\"timeEnd\",   var->timeEnd);\n          file>>endGroup(\"cell\");\n          x.equipments.push_back(var);\n        }\n      }\n      file>>endGroup(\"receiver\");\n      file>>beginGroup(\"referencePoint\");\n      {\n        UInt count;\n        file>>nameValue(\"count\", count);\n        x.referencePoints.resize(count);\n        for(UInt i=0; i<count; i++)\n        {\n          file>>beginGroup(\"cell\");\n          file>>nameValue(\"comment\",    x.referencePoints.at(i).comment);\n          file>>nameValue(\"pointStart\", x.referencePoints.at(i).pointStart);\n          file>>nameValue(\"pointEnd\",   x.referencePoints.at(i).pointEnd);\n          file>>nameValue(\"timeStart\",  x.referencePoints.at(i).timeStart);\n          file>>nameValue(\"timeEnd\",    x.referencePoints.at(i).timeEnd);\n          file>>endGroup(\"cell\");\n        }\n      }\n      file>>endGroup(\"referencePoint\");\n      file>>endGroup(\"station\");\n    }\n    else\n      throw(Exception(\"file type is '\"+file.type()+\"' but must be '\"+FILE_PLATFORM_TYPE+\"' or 'stationInfo'\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/filePlatform.h",
    "content": "/***********************************************/\n/**\n* @file filePlatform.h\n*\n* @brief Platform equipped with instruments.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-11-07\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEPLATFORM__\n#define __GROOPS_FILEPLATFORM__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_Platform\nstatic const char *docstringPlatform = R\"(\nDefines a platform with a local coordinate frame equipped with instruments.\nThe platform might be a reference station, a low Earth satellite,\nor a transmitting GNSS satellite and is referenced by a marker name and number.\nThe reference point (marker or center of mass (CoM)) can change in time\nrelative to the local frame.\n\nEach equipped instrument is described at least by the following information\n\\begin{itemize}\n\\item name\n\\item serial number\n\\item coordinates in the local frame\n\\item a time interval in which the instrument was active\n\\item the orientation for antennas and reflectors.\n\\end{itemize}\n\nFor GNSS satellites the platform defines the PRN. The different assigned SVNs\nare defined by the transmitting antennas.\n\nPlatforms for GNSS stations can be created from station log files with\n\\program{GnssStationLog2Platform}. Platforms for GNSS satellites\ncan be created from an ANTEX file with \\program{GnssAntex2AntennaDefinition}.\n\nSee also \\program{PlatformCreate}.\n\n\\fig{!hb}{0.8}{fileFormatPlatform}{fig:fileFormatPlatform}{Platform for stations, LEOs, and GNSS satellites.}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_PLATFORM_TYPE    = \"platform\";\nconstexpr UInt    FILE_PLATFORM_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** TYPES ***********************************/\n\nclass Platform;\nclass PlatformEquipment;\ntypedef std::shared_ptr<PlatformEquipment> PlatformEquipmentPtr;\n\nclass GnssAntennaDefinition;\nclass GnssReceiverDefinition;\ntypedef std::shared_ptr<GnssAntennaDefinition>  GnssAntennaDefinitionPtr;\ntypedef std::shared_ptr<GnssReceiverDefinition> GnssReceiverDefinitionPtr;\n\n/***** CLASS ***********************************/\n\nclass Platform\n{\npublic:\n  class ReferencePoint\n  {\n  public:\n    std::string comment;\n    Vector3d    pointStart, pointEnd;\n    Time        timeStart, timeEnd;\n  };\n\n  std::string                       name;\n  std::string                       markerName, markerNumber;\n  std::string                       comment;\n  Vector3d                          approxPosition;\n  std::vector<ReferencePoint>       referencePoints; ///< time sorted list of referencePoint\n  std::vector<PlatformEquipmentPtr> equipments;\n\n  /** @brief reference point in local frame.\n  * Center of mass (CoM) for satellites. */\n  Vector3d referencePoint(const Time &time) const;\n\n  template<typename T> std::shared_ptr<T> findEquipment(const Time &time) const;\n\n  void fillGnssAntennaDefinition (const std::vector<GnssAntennaDefinitionPtr> &antennaList);\n  void fillGnssAccuracyDefinition(const std::vector<GnssAntennaDefinitionPtr> &antennaList);\n  void fillGnssReceiverDefinition(const std::vector<GnssReceiverDefinitionPtr> &receiverList);\n};\n\n/***** CLASS ***********************************/\n\nclass PlatformEquipment\n{\npublic:\n  enum Type : Int {UNDEFINED           = 0,\n                   OTHER               = 1,\n                   GNSSANTENNA         = 2,\n                   GNSSRECEIVER        = 3,\n                   SLRSTATION          = 4,\n                   LASERRETROREFLECTOR = 5,\n                   SATELLITEIDENTIFIER = 6};\n\n  static constexpr Type TYPE = OTHER;\n  std::string comment;\n  std::string name, serial;\n  Time        timeStart, timeEnd;\n  Vector3d    position;   // position of instrument in north, east, up or vehicle system\n\n  virtual ~PlatformEquipment() {}\n\n  /** @brief Create Equipment of given type (as shared_ptr). */\n  static PlatformEquipmentPtr create(Type type);\n\n  /** @brief Data type (e.g. GNSSANTENNA, SLRREFLECTOR). */\n  virtual Type getType() const {return TYPE;}\n\n  virtual std::string str() const {return name+\"|\"+serial;};\n\n  virtual void save(OutArchive &oa) const;\n  virtual void load(InArchive  &ia);\n};\n\n/***** CLASS ***********************************/\n\nclass PlatformGnssAntenna : public PlatformEquipment\n{\npublic:\n  static constexpr Type TYPE = GNSSANTENNA;\n  std::string              radome;\n  Transform3d              local2antennaFrame;  // north, east, up or vehicle system -> antenna system\n  GnssAntennaDefinitionPtr antennaDef;\n  GnssAntennaDefinitionPtr accuracyDef;\n\n  Type getType() const override {return TYPE;}\n  std::string str() const override {return GnssAntennaDefinition::str(name, serial, radome);}\n  void save(OutArchive &oa) const override;\n  void load(InArchive  &ia) override;\n};\n\n/***** CLASS ***********************************/\n\nclass PlatformGnssReceiver : public PlatformEquipment\n{\npublic:\n  static constexpr Type TYPE = GNSSRECEIVER;\n  std::string               version; // software version\n  GnssReceiverDefinitionPtr receiverDef;\n\n  Type getType() const override {return TYPE;}\n  std::string str() const override {return GnssReceiverDefinition::str(name, serial, version);}\n  void save(OutArchive &oa) const override;\n  void load(InArchive  &ia) override;\n};\n\n/***** CLASS ***********************************/\n\nclass PlatformSlrStation : public PlatformEquipment\n{\npublic:\n  static constexpr Type TYPE = SLRSTATION;\n  Type getType() const override {return TYPE;}\n  std::string str() const override {return name;}\n  void save(OutArchive &oa) const override;\n  void load(InArchive  &ia) override;\n};\n\n/***** CLASS ***********************************/\n\nclass PlatformLaserRetroReflector : public PlatformEquipment\n{\npublic:\n  static constexpr Type TYPE = LASERRETROREFLECTOR;\n  Transform3d platform2reflectorFrame; // satellite system -> reflector system\n  Angle       dZenit;\n  Matrix      range;                   // range variations (azimut(0..360) x zenit(0..dZenit*rows))\n\n  Type getType() const override {return TYPE;}\n  std::string str() const override {return name;}\n  void save(OutArchive &oa) const override;\n  void load(InArchive  &ia) override;\n};\n\n/***** CLASS ***********************************/\n\nclass PlatformSatelliteIdentifier : public PlatformEquipment\n{\npublic:\n  static constexpr Type TYPE = SATELLITEIDENTIFIER;\n  std::string cospar, norad, sic, sp3;\n\n  Type getType() const override {return TYPE;}\n  std::string str() const override {return name;}\n  void save(OutArchive &oa) const override;\n  void load(InArchive  &ia) override;\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const Platform &x);\ntemplate<> void load(InArchive  &ar, Platform &x);\n\n/** @brief Write into a Platform file. */\nvoid writeFilePlatform(const FileName &fileName, const Platform &x);\n\n/** @brief Read from a Platform file. */\nvoid readFilePlatform(const FileName &fileName, Platform &x);\n\n/***********************************************/\n/***** INLINES   *******************************/\n/***********************************************/\n\ntemplate<typename T> inline std::shared_ptr<T> Platform::findEquipment(const Time &time) const\n{\n  try\n  {\n    auto iter = std::find_if(equipments.begin(), equipments.end(), [&](const auto &x)\n                            {return (x->getType() == T::TYPE) && (x->timeStart <= time) && (time < x->timeEnd);});\n    if(iter == equipments.end())\n      return std::shared_ptr<T>(nullptr);\n    return std::dynamic_pointer_cast<T>(*iter);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/files/filePolygon.cpp",
    "content": "/***********************************************/\n/**\n* @file filePolygon.cpp\n*\n* @brief Polygons on Earth's surface.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_Polygon\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/filePolygon.h\"\n\nGROOPS_REGISTER_FILEFORMAT(Polygon, FILE_POLYGON_TYPE)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const std::vector<Polygon> &polygon)\n{\n  UInt polygonCount = polygon.size();\n  ar<<nameValue(\"polygonCount\", polygonCount);\n  for(UInt i=0; i<polygonCount; i++)\n  {\n    ar<<beginGroup(\"polygon\");\n    UInt pointCount = polygon.at(i).L.rows();\n    ar<<nameValue(\"pointCount\", pointCount);\n    ar.comment(\"longitude [deg]           latitude [deg]          \");\n    ar.comment(\"==================================================\");\n    for(UInt k=0; k<pointCount; k++)\n    {\n      Angle L(polygon.at(i).L(k));\n      Angle B(polygon.at(i).B(k));\n      ar<<beginGroup(\"point\");\n      ar<<nameValue(\"longitude\", L);\n      ar<<nameValue(\"latitude\",  B);\n      ar<<endGroup(\"point\");\n    }\n    ar<<endGroup(\"polygon\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, std::vector<Polygon> &polygon)\n{\n  UInt polygonCount;\n  ar>>nameValue(\"polygonCount\", polygonCount);\n  polygon.resize(polygonCount);\n  for(UInt i=0; i<polygonCount; i++)\n  {\n    ar>>beginGroup(\"polygon\");\n    UInt pointCount;\n    ar>>nameValue(\"pointCount\", pointCount);\n    polygon.at(i) = Polygon(pointCount);\n    for(UInt k=0; k<pointCount; k++)\n    {\n      Angle L,B;\n      ar>>beginGroup(\"point\");\n      ar>>nameValue(\"longitude\", L);\n      ar>>nameValue(\"latitude\",  B);\n      ar>>endGroup(\"point\");\n      polygon.at(i).L(k) = L;\n      polygon.at(i).B(k) = B;\n    }\n    ar>>endGroup(\"polygon\");\n  }\n}\n\n/***********************************************/\n\nvoid writeFilePolygon(const FileName &fileName, const std::vector<Polygon> &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_POLYGON_TYPE, FILE_POLYGON_VERSION);\n    file<<nameValue(\"polygonList\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFilePolygon(const FileName &fileName, std::vector<Polygon> &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_POLYGON_TYPE, FILE_POLYGON_VERSION);\n    file>>nameValue(\"polygonList\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/filePolygon.h",
    "content": "/***********************************************/\n/**\n* @file filePolygon.h\n*\n* @brief Polygons on Earth's surface.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEPOLYGON__\n#define __GROOPS_FILEPOLYGON__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_Polygon\nstatic const char *docstringPolygon = R\"(\nList of longitude and latitudes to describe borders, e.g. river basins or continents.\nIt is used in \\configClass{border:polygon}{borderType:polygon}.\n\n\\begin{verbatim}\ngroops polygon version=20200123\n          2  # number of polygons\n          6  # number of points (1. polygon)\n# longitude [deg]           latitude [deg]\n# ==================================================\n -1.598200000000000216e+02  2.203000000000000114e+01\n -1.596200000000000045e+02  2.189999999999999858e+01\n -1.593799999999999955e+02  2.189999999999999858e+01\n -1.593000000000000114e+02  2.221999999999999886e+01\n -1.595800000000000125e+02  2.221999999999999886e+01\n -1.598200000000000216e+02  2.203000000000000114e+01\n          5  # number of points (2. polygon)\n# longitude [deg]           latitude [deg]\n# ==================================================\n -7.900000000000000000e+01  2.669999999999999929e+01\n -7.870000000000000284e+01  2.650000000000000000e+01\n -7.823000000000000398e+01  2.667000000000000171e+01\n -7.793000000000000682e+01  2.667000000000000171e+01\n -7.779999999999999716e+01  2.646999999999999886e+01\n\\end{verbatim}\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_POLYGON_TYPE    = \"polygon\";\nconstexpr UInt    FILE_POLYGON_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Polygons on Earth's surface.\n* The Polygon is described as clockwise list of points (latitude, longitude). */\nclass Polygon\n{\npublic:\n  Vector L,B;\n\n  Polygon() {}\n  Polygon(UInt size) : L(size), B(size) {}\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const std::vector<Polygon> &x);\ntemplate<> void load(InArchive  &ar, std::vector<Polygon> &x);\n\n/** @brief Write into a Polygon file. */\nvoid writeFilePolygon(const FileName &fileName, const std::vector<Polygon> &x);\n\n/** @brief Read from a Polygon file. */\nvoid readFilePolygon(const FileName &fileName, std::vector<Polygon> &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_FILEPOLYGON__ */\n"
  },
  {
    "path": "source/files/fileSatelliteModel.cpp",
    "content": "/***********************************************/\n/**\n* @file fileSatelliteModel.cpp\n*\n* @brief Satellite model.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2015-05-25\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_SatelliteModel\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileSatelliteModel.h\"\n\nGROOPS_REGISTER_FILEFORMAT(SatelliteModel, FILE_SATELLITEMODEL_TYPE)\n\n/***********************************************/\n\nSatelliteModelModulePtr SatelliteModelModule::create(SatelliteModelModule::Type type)\n{\n  try\n  {\n    switch(type)\n    {\n      case SatelliteModelModule::SOLARPANEL:           return SatelliteModelModulePtr(new SatelliteModelModuleSolarPanel());\n      case SatelliteModelModule::ANTENNATHRUST:        return SatelliteModelModulePtr(new SatelliteModelModuleAntennaThrust());\n      case SatelliteModelModule::MASSCHANGE:           return SatelliteModelModulePtr(new SatelliteModelModuleMassChange());\n      case SatelliteModelModule::SPECIFICHEATCAPACITY: return SatelliteModelModulePtr(new SatelliteModelModuleSetSpecificHeatCapacity());\n    }\n\n    std::stringstream ss;\n    ss<<\"unknown satellite module type (\"<<type<<\")\";\n    throw(Exception(ss.str()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SatelliteModelModuleSolarPanel::changeState(SatelliteModel &satellite, const Time &/*time*/,\n                                                 const Vector3d &position, const Vector3d &/*velocity*/,\n                                                 const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &/*rotEarth*/)\n{\n  try\n  {\n    if(positionSun.r() == 0.)\n      throw(Exception(\"Need position of the sun\"));\n    const Vector3d posSun = rotSat.inverseRotate(positionSun-position); // in SRF\n    const Rotary3d rot = Rotary3d(rotationAxis, posSun)\n                       * inverse(Rotary3d(rotationAxis, normal)); // from old to new orientation\n    normal = rot.rotate(normal);\n    for(UInt i=0; i<indexSurface.size(); i++)\n      satellite.surfaces.at(indexSurface.at(i)).normal = rot.rotate(satellite.surfaces.at(indexSurface.at(i)).normal);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleSolarPanel::save(OutArchive &ar) const\n{\n  try\n  {\n    ar<<nameValue(\"rotationAxis\", rotationAxis);\n    ar<<nameValue(\"normal\",       normal);\n    ar<<nameValue(\"surface\",      indexSurface);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleSolarPanel::load(InArchive  &ar)\n{\n  try\n  {\n    ar>>nameValue(\"rotationAxis\", rotationAxis);\n    ar>>nameValue(\"normal\",       normal);\n    ar>>nameValue(\"surface\",      indexSurface);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SatelliteModelModuleAntennaThrust::changeState(SatelliteModel &satellite, const Time &/*time*/,\n                                                    const Vector3d &/*position*/, const Vector3d &/*velocity*/,\n                                                    const Vector3d &/*positionSun*/, const Rotary3d &/*rotSat*/, const Rotary3d &/*rotEarth*/)\n{\n  if(!applied)\n    satellite.thrustPower += thrust;\n  applied = TRUE;\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleAntennaThrust::save(OutArchive &ar) const\n{\n  ar<<nameValue(\"antennaThrust\", thrust);\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleAntennaThrust::load(InArchive  &ar)\n{\n  ar>>nameValue(\"antennaThrust\", thrust);\n  applied = FALSE;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SatelliteModelModuleMassChange::changeState(SatelliteModel &satellite, const Time &time,\n                                                 const Vector3d &/*position*/, const Vector3d &/*velocity*/,\n                                                 const Vector3d &/*positionSun*/, const Rotary3d &/*rotSat*/, const Rotary3d &/*rotEarth*/)\n{\n  try\n  {\n    if((times.size()==0)||(time<times.at(0)))\n      return;\n\n    if(time>=times.back())\n    {\n      satellite.mass = mass.back();\n      return;\n    }\n\n    // linear interpolation\n    UInt idx = 0;\n    while((idx+1<times.size()) && (times.at(idx+1)<=time))\n      idx++;\n    const Double tau = (time-times.at(idx)).mjd()/(times.at(idx+1)-times.at(idx)).mjd();\n    satellite.mass = (1-tau)*mass.at(idx) + tau*mass.at(idx+1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleMassChange::save(OutArchive &ar) const\n{\n  try\n  {\n    ar<<nameValue(\"epochCount\", times.size());\n    for(UInt i=0; i<times.size(); i++)\n    {\n      ar<<beginGroup(\"epoch\");\n      ar<<nameValue(\"time\", times.at(i));\n      ar<<nameValue(\"mass\", mass.at(i));\n      ar<<endGroup(\"epoch\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleMassChange::load(InArchive &ar)\n{\n  try\n  {\n    UInt count;\n    ar>>nameValue(\"epochCount\", count);\n    times.resize(count);\n    mass.resize(count);\n    for(UInt i=0; i<times.size(); i++)\n    {\n      ar>>beginGroup(\"epoch\");\n      ar>>nameValue(\"time\", times.at(i));\n      ar>>nameValue(\"mass\", mass.at(i));\n      ar>>endGroup(\"epoch\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SatelliteModelModuleSetSpecificHeatCapacity::changeState(SatelliteModel &satellite, const Time &/*time*/,\n                                                              const Vector3d &/*position*/, const Vector3d &/*velocity*/,\n                                                              const Vector3d &/*positionSun*/, const Rotary3d &/*rotSat*/, const Rotary3d &/*rotEarth*/)\n{\n  try\n  {\n    for(UInt i=0; i<indexSurface.size(); i++)\n      satellite.surfaces.at(indexSurface.at(i)).specificHeatCapacity = specificHeatCapacity.at(i);\n    applied = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleSetSpecificHeatCapacity::save(OutArchive &ar) const\n{\n  try\n  {\n    ar<<nameValue(\"specificHeatCapacity\", specificHeatCapacity);\n    ar<<nameValue(\"surface\",              indexSurface);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelModuleSetSpecificHeatCapacity::load(InArchive  &ar)\n{\n  try\n  {\n    ar>>nameValue(\"specificHeatCapacity\", specificHeatCapacity);\n    ar>>nameValue(\"surface\",              indexSurface);\n    applied = FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSatelliteModel::Surface::Surface() :\n  type(PLATE), area(0),\n  absorptionVisible(0), absorptionInfrared(0),\n  diffusionVisible(0),  diffusionInfrared(0),\n  reflexionVisible(0),  reflexionInfrared(0),\n  specificHeatCapacity(0)\n{\n}\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const SatelliteModel::Surface &x)\n{\n  try\n  {\n    ar<<nameValue(\"type\",                 static_cast<UInt>(x.type));\n    ar<<nameValue(\"normal\",               x.normal);\n    ar<<nameValue(\"area\",                 x.area);\n    ar<<nameValue(\"reflexionVisible\",     x.reflexionVisible);\n    ar<<nameValue(\"diffusionVisible\",     x.diffusionVisible);\n    ar<<nameValue(\"absorptionVisible\",    x.absorptionVisible);\n    ar<<nameValue(\"reflexionInfrared\",    x.reflexionInfrared);\n    ar<<nameValue(\"diffusionInfrared\",    x.diffusionInfrared);\n    ar<<nameValue(\"absorptionInfrared\",   x.absorptionInfrared);\n    ar<<nameValue(\"hasThermalReemission\", (x.specificHeatCapacity != 0));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, SatelliteModel::Surface &x)\n{\n  try\n  {\n    UInt type;\n    ar>>nameValue(\"type\",               type);\n    x.type = static_cast<SatelliteModel::Surface::Type>(type);\n    ar>>nameValue(\"normal\",             x.normal);\n    ar>>nameValue(\"area\",               x.area);\n    ar>>nameValue(\"reflexionVisible\",   x.reflexionVisible);\n    ar>>nameValue(\"diffusionVisible\",   x.diffusionVisible);\n    ar>>nameValue(\"absorptionVisible\",  x.absorptionVisible);\n    ar>>nameValue(\"reflexionInfrared\",  x.reflexionInfrared);\n    ar>>nameValue(\"diffusionInfrared\",  x.diffusionInfrared);\n    ar>>nameValue(\"absorptionInfrared\", x.absorptionInfrared);\n\n    x.specificHeatCapacity = 0;\n    if(ar.version() >= 20190429)\n    {\n      Bool hasThermalReemission;\n      ar>>nameValue(\"hasThermalReemission\", hasThermalReemission);\n      x.specificHeatCapacity = (hasThermalReemission ? -1. : 0.);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSatelliteModel::SatelliteModel() : satelliteName(\"NULL\"), mass(0), coefficientDrag(0)\n{\n}\n\n/***********************************************/\n\nSatelliteModel::~SatelliteModel()\n{\n}\n\n/***********************************************/\n\nvoid SatelliteModel::changeState(const Time &time, const Vector3d &position, const Vector3d &velocity,\n                                 const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &rotEarth)\n{\n  for(auto module : modules)\n    module ->changeState(*this, time, position, velocity, positionSun, rotSat, rotEarth);\n}\n\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const SatelliteModelPtr &x)\n{\n  try\n  {\n    if((x==nullptr) || (x->satelliteName==\"NULL\"))\n    {\n      ar<<nameValue(\"satelliteName\", std::string(\"NULL\"));\n      return;\n    }\n\n    ar<<nameValue(\"satelliteName\",   x->satelliteName);\n    ar<<nameValue(\"mass\",            x->mass);\n    ar<<nameValue(\"coefficientDrag\", x->coefficientDrag);\n    ar<<nameValue(\"surfaceCount\",    x->surfaces.size());\n    ar.endLine();\n    for(UInt i=0; i<x->surfaces.size(); i++)\n    {\n      ar<<nameValue(\"surface\", x->surfaces.at(i));\n      ar.endLine();\n    }\n    ar<<nameValue(\"modulCount\", x->modules.size());\n    for(UInt i=0; i<x->modules.size(); i++)\n    {\n      ar<<beginGroup(\"modul\");\n      ar<<nameValue(\"type\", static_cast<UInt>(x->modules.at(i)->type()));\n      x->modules.at(i)->save(ar);\n      ar<<endGroup(\"modul\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, SatelliteModelPtr &x)\n{\n  try\n  {\n    std::string satelliteName;\n    ar>>nameValue(\"satelliteName\", satelliteName);\n    if(satelliteName==\"NULL\")\n    {\n      x = SatelliteModelPtr(nullptr);\n      return;\n    }\n\n    x = SatelliteModelPtr(new SatelliteModel);\n    x->satelliteName = satelliteName;\n\n    UInt count, type;\n    ar>>nameValue(\"mass\",            x->mass);\n    ar>>nameValue(\"coefficientDrag\", x->coefficientDrag);\n    ar>>nameValue(\"surfaceCount\",    count);\n    x->surfaces.resize(count);\n    for(UInt i=0; i<x->surfaces.size(); i++)\n      ar>>nameValue(\"surface\", x->surfaces.at(i));\n    ar>>nameValue(\"modulCount\",      count);\n    x->modules.resize(count);\n    for(UInt i=0; i<x->modules.size(); i++)\n    {\n      ar>>beginGroup(\"modul\");\n      ar>>nameValue(\"type\", type);\n      x->modules.at(i) = SatelliteModelModule::create(static_cast<SatelliteModelModule::Type>(type));\n      x->modules.at(i)->load(ar);\n      ar>>endGroup(\"modul\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileSatelliteModel(const FileName &fileName, const SatelliteModelPtr &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_SATELLITEMODEL_TYPE, FILE_SATELLITEMODEL_VERSION);\n    file<<nameValue(\"satelliteCount\", 1);\n    file<<nameValue(\"satellite\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileSatelliteModel(const FileName &fileName, const std::vector<SatelliteModelPtr> &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_SATELLITEMODEL_TYPE, FILE_SATELLITEMODEL_VERSION);\n    file<<nameValue(\"satelliteCount\", x.size());\n    for(UInt i=0; i<x.size(); i++)\n      file<<nameValue(\"satellite\", x.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileSatelliteModel(const FileName &fileName, SatelliteModelPtr &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_SATELLITEMODEL_TYPE, FILE_SATELLITEMODEL_VERSION);\n    UInt count;\n    file>>nameValue(\"satelliteCount\", count);\n    if(count>1)\n      logWarning<<fileName<<\" contain more than one satellite, only the first is used\"<<Log::endl;\n    file>>nameValue(\"satellite\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileSatelliteModel(const FileName &fileName, std::vector<SatelliteModelPtr> &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_SATELLITEMODEL_TYPE, FILE_SATELLITEMODEL_VERSION);\n    UInt count;\n    file>>nameValue(\"satelliteCount\", count);\n    x.resize(count);\n    for(UInt i=0; i<x.size(); i++)\n      file>>nameValue(\"satellite\", x.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileSatelliteModel.h",
    "content": "/***********************************************/\n/**\n* @file fileSatelliteModel.h\n*\n* @brief Satellite model.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2015-05-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILESATELLITEMODEL__\n#define __GROOPS_FILESATELLITEMODEL__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_SatelliteModel\nstatic const char *docstringSatelliteModel = R\"(\nProperties of a satellite to model non-conservative forces (e.g. \\configClass{miscAccelerations}{miscAccelerationsType}).\nThe file may contain surface properties, mass, drag coefficients, and antenna thrust values.\n\nSee \\program{SatelliteModelCreate} and \\program{SinexMetadata2SatelliteModel}.\n\n\\begin{verbatim}\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<groops type=\"satelliteModel\" version=\"20190429\">\n   <satelliteCount>1</satelliteCount>\n   <satellite>\n       <satelliteName>GALILEO-2</satelliteName>\n       <mass>7.00000000000000e+02</mass>\n       <coefficientDrag>0.00000000000000e+00</coefficientDrag>\n       <surfaceCount>15</surfaceCount>\n       <surface>\n           <type>0</type>\n           <normal>\n               <x>-1.00000000000000e+00</x>\n               <y>0.00000000000000e+00</y>\n               <z>0.00000000000000e+00</z>\n           </normal>\n           <area>4.40000000000000e-01</area>\n           <reflexionVisible>0.00000000000000e+00</reflexionVisible>\n           <diffusionVisible>7.00000000000000e-02</diffusionVisible>\n           <absorptionVisible>9.30000000000000e-01</absorptionVisible>\n           <reflexionInfrared>1.00000000000000e-01</reflexionInfrared>\n           <diffusionInfrared>1.00000000000000e-01</diffusionInfrared>\n           <absorptionInfrared>8.00000000000000e-01</absorptionInfrared>\n           <hasThermalReemission>1</hasThermalReemission>\n       </surface>\n       ...\n       <modulCount>2</modulCount>\n       <modul>\n           <type>1</type>\n           <rotationAxis>\n               <x>0.00000000000000e+00</x>\n               <y>1.00000000000000e+00</y>\n               <z>0.00000000000000e+00</z>\n           </rotationAxis>\n           <normal>\n               <x>0.00000000000000e+00</x>\n               <y>0.00000000000000e+00</y>\n               <z>1.00000000000000e+00</z>\n           </normal>\n           <surface>\n               <count>4</count>\n               <cell>11</cell>\n               <cell>12</cell>\n               <cell>13</cell>\n               <cell>14</cell>\n           </surface>\n       </modul>\n       <modul>\n           <type>2</type>\n           <antennaThrust>\n               <x>0.00000000000000e+00</x>\n               <y>0.00000000000000e+00</y>\n               <z>2.65000000000000e+02</z>\n           </antennaThrust>\n       </modul>\n   </satellite>\n</groops>\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"inputOutput/logging.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_SATELLITEMODEL_TYPE    = \"satelliteModel\";\nconstexpr UInt    FILE_SATELLITEMODEL_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** TYPES ***********************************/\n\nclass SatelliteModel;\nclass SatelliteModelModule;\ntypedef std::shared_ptr<SatelliteModel> SatelliteModelPtr;\ntypedef std::shared_ptr<SatelliteModelModule> SatelliteModelModulePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite model. */\nclass SatelliteModel\n{\npublic:\n  class Surface\n  {\n  public:\n    enum Type {PLATE=0, SPHERE=1, CYLINDER=2, GRACESHADOW=3};\n    Type     type;\n    Vector3d normal;\n    Double   area;\n    Double   absorptionVisible, absorptionInfrared;\n    Double   diffusionVisible,  diffusionInfrared;\n    Double   reflexionVisible,  reflexionInfrared;\n    Double   specificHeatCapacity;   //!< 0: no thermal radiation, -1: spontaneous reemission of absorbed radiation [Ws/K/m^2]\n\n    Surface();\n  };\n\n  SatelliteModel();                                            //!< Constructor.\n ~SatelliteModel();                                            //!< Destructor.\n  SatelliteModel &operator=(const SatelliteModel &x) = delete; //!< Disallow copying.\n  SatelliteModel(const SatelliteModel &x) = delete;            //!< Disallow copy constructor.\n\n  std::string                          satelliteName;      //!< Name of satellite.\n  Double                               mass;\n  Double                               coefficientDrag;\n  Vector3d                             thrustPower;        //!< e.g. of GNSS transmitting antenna in SRF [W].\n  std::vector<Surface>                 surfaces;\n  std::vector<SatelliteModelModulePtr> modules;            //!< Adjust the state of satellite.\n\n  /** @brief Compute new state of satellite.\n  * E.g. Move parts of satellite surfaces, update mass.\n  * @param time Time.\n  * @param position in CRF [m].\n  * @param velocity in CRF [m/s].\n  * @param positionSun in CRF [m].\n  * @param rotSat   Sat -> CRF\n  * @param rotEarth CRF -> TRF */\n  void changeState(const Time &time, const Vector3d &position, const Vector3d &velocity,\n                   const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &rotEarth);\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const SatelliteModelPtr &x);\ntemplate<> void load(InArchive  &ar, SatelliteModelPtr &x);\n\n/** @brief Write into a SatelliteModel file. */\nvoid writeFileSatelliteModel(const FileName &fileName, const SatelliteModelPtr &x);\n\n/** @brief Write into a SatelliteModel file. */\nvoid writeFileSatelliteModel(const FileName &fileName, const std::vector<SatelliteModelPtr> &x);\n\n/** @brief Read from a SatelliteModel file. */\nvoid readFileSatelliteModel(const FileName &fileName, SatelliteModelPtr &x);\n\n/** @brief Read from a SatelliteModel file. */\nvoid readFileSatelliteModel(const FileName &fileName, std::vector<SatelliteModelPtr> &x);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass SatelliteModelModule\n{\npublic:\n  enum Type {SOLARPANEL = 1, ANTENNATHRUST = 2, MASSCHANGE = 3, SPECIFICHEATCAPACITY = 4};\n\n  virtual ~SatelliteModelModule() {}\n  virtual Type type() const = 0;\n  virtual void changeState(SatelliteModel &/*satellite*/, const Time &/*time*/, const Vector3d &/*position*/, const Vector3d &/*velocity*/,\n                           const Vector3d &/*positionSun*/, const Rotary3d &/*rotSat*/, const Rotary3d &/*rotEarth*/) {}\n  virtual void save(OutArchive &ar) const = 0;\n  virtual void load(InArchive  &ar) = 0;\n\n  /** @brief Create an epoch of given type (with new). */\n  static SatelliteModelModulePtr create(Type type);\n};\n\n/***********************************************/\n\nclass SatelliteModelModuleSolarPanel : public SatelliteModelModule\n{\npublic:\n  Vector3d          rotationAxis;\n  Vector3d          normal;\n  std::vector<UInt> indexSurface;\n\n  Type type() const {return SOLARPANEL;}\n  void changeState(SatelliteModel &satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                   const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &rotEarth);\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***********************************************/\n\nclass SatelliteModelModuleAntennaThrust : public SatelliteModelModule\n{\npublic:\n  Bool     applied;\n  Vector3d thrust;\n\n  Type type() const {return ANTENNATHRUST;}\n  void changeState(SatelliteModel &satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                   const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &rotEarth);\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***********************************************/\n\nclass SatelliteModelModuleMassChange : public SatelliteModelModule\n{\npublic:\n  std::vector<Time>   times;\n  std::vector<Double> mass;\n\n  Type type() const {return MASSCHANGE;}\n  void changeState(SatelliteModel &satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                   const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &rotEarth);\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***********************************************/\n\nclass SatelliteModelModuleSetSpecificHeatCapacity : public SatelliteModelModule\n{\npublic:\n  Bool                applied;\n  std::vector<Double> specificHeatCapacity;\n  std::vector<UInt>   indexSurface;\n\n  Type type() const {return SPECIFICHEATCAPACITY;}\n  void changeState(SatelliteModel &satellite, const Time &time, const Vector3d &position, const Vector3d &velocity,\n                   const Vector3d &positionSun, const Rotary3d &rotSat, const Rotary3d &rotEarth);\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileSphericalHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file fileSphericalHarmonics.cpp\n*\n* @brief Read/write SphericalHarmonics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_PotentialCoefficients\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileSphericalHarmonics.h\"\n\nGROOPS_REGISTER_FILEFORMAT(PotentialCoefficients, FILE_POTENTIALCOEFFICIENTS_TYPE)\n\n/***********************************************/\n\nvoid writeFileSphericalHarmonics(const FileName &fileName, const SphericalHarmonics &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_POTENTIALCOEFFICIENTS_TYPE, FILE_POTENTIALCOEFFICIENTS_VERSION);\n    file<<nameValue(\"potentialCoefficients\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileSphericalHarmonics(const FileName &fileName, SphericalHarmonics &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_POTENTIALCOEFFICIENTS_TYPE, FILE_POTENTIALCOEFFICIENTS_VERSION);\n    file>>nameValue(\"potentialCoefficients\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileSphericalHarmonics.h",
    "content": "/***********************************************/\n/**\n* @file fileSphericalHarmonics.h\n*\n* @brief Read/write SphericalHarmonics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILESPHERICALHARMONICS__\n#define __GROOPS_FILESPHERICALHARMONICS__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_PotentialCoefficients\nstatic const char *docstringPotentialCoefficients = R\"(\nThe standard \\verb|.gfc| format as defined by the ICGEM is used in ASCII the format.\nOnly the static part is used and temporal variations (e.g. trend) are ignored.\nTo write additional information and temporal variations use \\program{PotentialCoefficients2Icgem}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_POTENTIALCOEFFICIENTS_TYPE    = \"potentialCoefficients\";\nconstexpr UInt    FILE_POTENTIALCOEFFICIENTS_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a SphericalHarmonics file. */\nvoid writeFileSphericalHarmonics(const FileName &fileName, const SphericalHarmonics &x);\n\n/** @brief Read from a SphericalHarmonics file. */\nvoid readFileSphericalHarmonics(const FileName &fileName, SphericalHarmonics &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileStringTable.cpp",
    "content": "/***********************************************/\n/**\n* @file fileStringTable.cpp\n*\n* @brief Read/write table of strings.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-03\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_StringList\n#define DOCSTRING_FILEFORMAT_StringTable\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"fileStringTable.h\"\n\nGROOPS_REGISTER_FILEFORMAT(StringList,  \"stringList\")\nGROOPS_REGISTER_FILEFORMAT(StringTable, \"stringTable\")\n\n/***********************************************/\n\nstatic Bool stripComments(std::istream &stream)\n{\n  try\n  {\n    char c;\n    if(!(stream>>c))\n      return FALSE;\n    stream.putback(c);\n    if(c != '#')\n      return TRUE;\n    std::string line;\n    std::getline(stream, line); // skip rest of line\n    return stripComments(stream);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileStringTable(const FileName &fileName, std::vector<std::vector<std::string>> &x)\n{\n  try\n  {\n    InFile file(fileName);\n\n    while(stripComments(file))\n    {\n      std::string line;\n      std::getline(file, line);\n      std::stringstream ss(line);\n\n      std::vector<std::string> dataLine;\n      while(stripComments(ss))\n      {\n        std::string data;\n        ss>>std::quoted(data);\n        dataLine.push_back(data);\n      }\n\n      if(dataLine.size())\n        x.push_back(dataLine);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileStringTable(const FileName &fileName, const std::vector<std::vector<std::string>> &x)\n{\n  try\n  {\n    OutFile file(fileName);\n    for(const auto &line : x)\n    {\n      for(UInt i=0; i<line.size(); i++)\n      {\n        if((!line.at(i).empty()) && (line.at(i).find_first_of(\" \\t\\n\\\"#\") == std::string::npos))\n          file<<line.at(i);              // string without special characters\n        else\n          file<<std::quoted(line.at(i)); // string in quotes\n        if(i < line.size()-1)            // no space at the end of a line\n          file<<\" \";\n      }\n      file<<std::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileStringTable.h",
    "content": "/***********************************************/\n/**\n* @file fileStringTable.h\n*\n* @brief Read/write table of strings.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILESTRINGTABLE__\n#define __GROOPS_FILESTRINGTABLE__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_StringList\nstatic const char *docstringStringList = R\"(\nWhite space separated list of strings.\nComments are allowed and all the text from the character '\\verb|#|' to the end of the line is ignored.\nStrings containing white spaces or the '\\verb|#|' character must be set in quotes ('\\verb|\"\"|').\n\n\\begin{verbatim}\n# IGSR3 stations\nabmf\nabpo\nade1\nadis\najac\nalbh\nalgo\nalic\nalrt\namc2\naoml\nareq\narev\nartu\nasc1\n\\end{verbatim}\n)\";\n#endif\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_StringTable\nstatic const char *docstringStringTable = R\"(\nWhite space separated table of strings in row and columns.\nAdditional columns in a row may represent alternatives, e.g. for core stations in a GNSS network.\nComments are allowed and all the text from the character '\\verb|#|' to the end of the line is ignored.\nStrings containing white spaces or the '\\verb|#|' character must be set in quotes  ('\\verb|\"\"|').\n\n\\begin{verbatim}\n# core network with alternative stations\nartu mdvj mdvo nril\nasc1 sthl\nbahr bhr1 yibl nama\nchat chti auck\nchpi braz ufpr savo\nckis nium\ncoco xmis dgar dgav\ncro1 scub abmf lmmf aoml\ndaej taej suwn osn1\ndarw kat1 tow2 alic\ndav1 maw1\ndrao albh will holb nano\nfair whit\nglps guat\ngode godz usno usn3\ngoug\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"inputOutput/fileName.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write into a stringList file. */\ninline void writeFileStringList(const FileName &fileName, const std::vector<std::string> &x);\n\n/** @brief Write into a stringTable file. */\nvoid writeFileStringTable(const FileName &fileName, const std::vector<std::vector<std::string>> &x);\n\n/** @brief Read from a stringList file. */\ninline void readFileStringList(const FileName &fileName, std::vector<std::string> &x);\n\n/** @brief Read from a stringTable file. */\nvoid readFileStringTable(const FileName &fileName, std::vector<std::vector<std::string>> &x);\n\n/// @}\n\n/***********************************************/\n/***** INLINES ********************************/\n/***********************************************/\n\ninline void writeFileStringList(const FileName &fileName, const std::vector<std::string> &x)\n{\n  try\n  {\n    std::vector<std::vector<std::string>> table(x.size());\n    for(UInt i=0; i<x.size(); i++)\n      table.at(i) = {x.at(i)};\n    writeFileStringTable(fileName, table);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void readFileStringList(const FileName &fileName, std::vector<std::string> &x)\n{\n  try\n  {\n    std::vector<std::vector<std::string>> table;\n    readFileStringTable(fileName, table);\n    for(const auto &line : table)\n      x.insert(x.end(), line.begin(), line.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/files/fileTideGeneratingPotential.cpp",
    "content": "/***********************************************/\n/**\n* @file fileTideGeneratingPotential.cpp\n*\n* @brief Read/write tide genearting potential.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_TideGeneratingPotential\n\n#include \"base/import.h\"\n#include \"base/tideGeneratingPotential.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n\nGROOPS_REGISTER_FILEFORMAT(TideGeneratingPotential, FILE_TIDEGENERATINGPOTENTIAL_TYPE)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const TideGeneratingPotential &x)\n{\n  const UInt constituentsCount = x.size();\n  ar<<nameValue(\"constituentsCount\", constituentsCount);\n  ar.comment(\"Degree    Dood.    cos                       sin                      name\");\n  ar.comment(\"==========================================================================\");\n  for(UInt i=0; i<constituentsCount; i++)\n  {\n    std::string name = (x.at(i).name() != x.at(i).code()) ? x.at(i).name() : \"\";\n    ar<<beginGroup(\"constituent\");\n    ar<<nameValue(\"degree\",  x.at(i).degree);\n    ar<<nameValue(\"doodson\", *dynamic_cast<const Doodson*>(&x.at(i)));\n    ar<<nameValue(\"c\",       x.at(i).c);\n    ar<<nameValue(\"s\",       x.at(i).s);\n    ar<<nameValue(\"name\",    name);\n    ar<<endGroup(\"constituent\");\n  }\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive &ar, TideGeneratingPotential &x)\n{\n  UInt constituentsCount;\n  ar>>nameValue(\"constituentsCount\", constituentsCount);\n  x.resize(constituentsCount);\n  for(UInt i=0; i<constituentsCount; i++)\n  {\n    ar>>beginGroup(\"constituent\");\n    UInt        degree = 2;\n    Doodson     dood;\n    Double      c, s;\n    std::string name;\n    if(ar.version() >= 20241108)\n      ar>>nameValue(\"degree\",  degree);\n    ar>>nameValue(\"doodson\", dood);\n    ar>>nameValue(\"c\",       c);\n    ar>>nameValue(\"s\",       s);\n    ar>>nameValue(\"name\",    name);\n    x.at(i) = TideGeneratingConstituent(dood, degree, c, s);\n    ar>>endGroup(\"constituent\");\n  }\n}\n\n/***********************************************/\n\nvoid writeFileTideGeneratingPotential(const FileName &fileName, const TideGeneratingPotential &x)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_TIDEGENERATINGPOTENTIAL_TYPE, FILE_TIDEGENERATINGPOTENTIAL_VERSION);\n    file<<nameValue(\"tideGeneratingPotential\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileTideGeneratingPotential(const FileName &fileName, TideGeneratingPotential &x)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_TIDEGENERATINGPOTENTIAL_TYPE, FILE_TIDEGENERATINGPOTENTIAL_VERSION);\n    file>>nameValue(\"tideGeneratingPotential\", x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileTideGeneratingPotential.h",
    "content": "/***********************************************/\n/**\n* @file fileTideGeneratingPotential.h\n*\n* @brief Read/write tide genearting potential.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILETIDEGENERATINGPOTENTIAL__\n#define __GROOPS_FILETIDEGENERATINGPOTENTIAL__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_TideGeneratingPotential\nstatic const char *docstringTideGeneratingPotential = R\"(\n\n\\begin{verbatim}\ngroops tideGeneratingPotential version=20200123\n       7160\n# Degree    Dood.    cos                       sin                      name\n# ==========================================================================\n          3 055.556  0.000000000000000000e+00 -6.569000000000000125e-07 \"\"\n          3 055.635  0.000000000000000000e+00 -2.842000000000000170e-07 \"\"\n          3 055.561  0.000000000000000000e+00 -6.360000000000000040e-08 \"\"\n          2 055.563 -3.122600001000726621e-06  0.000000000000000000e+00 \"\"\n          2 055.565  7.719644799947265879e-02  0.000000000000000000e+00 om1\n          3 055.645  0.000000000000000000e+00  2.921429999971616515e-05 \"\"\n          2 055.573  1.975999999999999959e-07  0.000000000000000000e+00 \"\"\n          2 055.575 -7.535264999889109729e-04  0.000000000000000000e+00 om2\n\\end{verbatim}\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/exception.h\"\n#include \"base/tideGeneratingPotential.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_TIDEGENERATINGPOTENTIAL_TYPE    = \"tideGeneratingPotential\";\nconstexpr UInt    FILE_TIDEGENERATINGPOTENTIAL_VERSION = std::max(UInt(20241108), FILE_BASE_VERSION);\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> void save(OutArchive &ar, const TideGeneratingPotential &x);\ntemplate<> void load(InArchive  &ar, TideGeneratingPotential &x);\n\n/** @brief Write into a TideGeneratingPotential file. */\nvoid writeFileTideGeneratingPotential(const FileName &fileName, const TideGeneratingPotential &x);\n\n/** @brief Read from a TideGeneratingPotential file. */\nvoid readFileTideGeneratingPotential(const FileName &fileName, TideGeneratingPotential &x);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_FILEGENERATINGTIDE__ */\n"
  },
  {
    "path": "source/files/fileTimeSplinesGravityfield.cpp",
    "content": "/***********************************************/\n/**\n* @file fileTimeSplinesGravityfield.cpp\n*\n* @brief time variable gravity field represented by splines in time domain.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-29\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_TimeSplinesGravityField\n#define DOCSTRING_FILEFORMAT_TimeSplinesCovariance\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/basisSplines.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n\nGROOPS_REGISTER_FILEFORMAT(TimeSplinesGravityField, FILE_TIMESPLINESGRAVITYFIELD_TYPE)\nGROOPS_REGISTER_FILEFORMAT(TimeSplinesCovariance,   FILE_TIMESPLINESCOVARIANCE_TYPE)\n\n/***** FUNCTIONS *******************************/\n\nvoid InFileTimeSplinesGravityfield::open(const FileName &name, UInt maxDegree, UInt minDegree)\n{\n  try\n  {\n    maxDegree_ = maxDegree;\n    minDegree_ = minDegree;\n\n    close();\n    if(!name.empty())\n    {\n      UInt epochCount;\n      file.open(name, FILE_TIMESPLINESGRAVITYFIELD_TYPE, FILE_TIMESPLINESGRAVITYFIELD_VERSION);\n      file>>nameValue(\"GM\",        GM);\n      file>>nameValue(\"R\",         R);\n      file>>nameValue(\"degree\",    splineDegree_);\n      file>>nameValue(\"timeCount\", epochCount);\n      times_.resize(epochCount);\n      for(UInt i=0; i<times_.size(); i++)\n        file>>nameValue(\"time\", times_.at(i));\n\n      // If we have a binary file, we can efficiently seek to the needed position in the file.\n      if(file.canSeek())\n        seekStart = file.position();\n      seekSize = 0;\n\n      indexFile = 0;\n      indexData = nodeCount();\n      harmonics.resize(splineDegree_+1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InFileTimeSplinesGravityfield::close()\n{\n  file.close();\n  times_.clear();\n  splineDegree_ = 0;\n}\n\n/***********************************************/\n\nSphericalHarmonics InFileTimeSplinesGravityfield::sphericalHarmonics(UInt idNode)\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n\n    // must restart?\n    if(indexFile > idNode)\n    {\n      if(file.canSeek() && seekSize)\n        indexFile = 0;\n      else\n        open(file.fileName());\n    }\n\n    SphericalHarmonics harmonics;\n    while(indexFile <= idNode)\n    {\n      // Seek to appropriate interval.\n      if(file.canSeek() && seekSize)\n      {\n        file.seek(seekStart + static_cast<std::streamoff>(idNode * seekSize));\n        indexFile = idNode;\n      }\n\n      Matrix cnm, snm;\n      file>>beginGroup(\"node\");\n      file>>nameValue(\"cnm\", cnm);\n      file>>nameValue(\"snm\", snm);\n      file>>endGroup(\"node\");\n      harmonics = SphericalHarmonics(GM, R, cnm, snm).get(maxDegree_, minDegree_);\n\n      if(file.canSeek() && (indexFile == 0))\n        seekSize = file.position() - seekStart;\n      indexFile++;\n    }\n\n    return harmonics;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics InFileTimeSplinesGravityfield::sphericalHarmonics(const Time &time, Double factor)\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n    if((time < times_.front()) || (time > times_.back()))\n      throw(Exception(time.dateTimeStr()+\" outside interval [\"+times_.front().dateTimeStr()+\", \"+times_.back().dateTimeStr()+\"] of <\"+file.fileName().str()+\">\"));\n\n    // find time interval and read missing nodes\n    const UInt idx   = std::min(static_cast<UInt>(std::distance(times_.begin(), std::upper_bound(times_.begin(), times_.end(), time))), times_.size()-1)-1;\n    const UInt start = (idx > indexData) ? std::max(idx, indexData+harmonics.size()) : idx;\n    const UInt end   = (idx > indexData) ? idx+harmonics.size() : std::min(idx+harmonics.size(), indexData);\n    for(UInt i=start; i<end; i++)\n      harmonics.at(i%harmonics.size()) = sphericalHarmonics(i);\n    indexData = idx;\n\n    // spline interpolation in interval\n    const Double       t     = (time-times_.at(idx)).mjd()/(times_.at(idx+1)-times_.at(idx)).mjd();\n    const Vector       coeff = BasisSplines::compute(t, splineDegree_);\n    SphericalHarmonics harm  = factor * coeff(0) * harmonics.at(indexData%harmonics.size());\n    for(UInt i=1; i<coeff.rows(); i++)\n      harm += factor * coeff(i) * harmonics.at((indexData+i)%harmonics.size());\n    return harm;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileTimeSplinesGravityfield(const FileName &fileName,\n                                      Double GM, Double R, UInt splineDegree,\n                                      const std::vector<Time> &times,\n                                      const std::vector<Matrix> &cnm,\n                                      const std::vector<Matrix> &snm)\n{\n  try\n  {\n    UInt nodeCount = times.size()+splineDegree-1;\n    if((nodeCount != cnm.size()) || (nodeCount != snm.size()))\n      throw(Exception(\"size of series of cnm,snm does not mach to number of times.\"));\n\n    OutFileArchive file(fileName, FILE_TIMESPLINESGRAVITYFIELD_TYPE, FILE_TIMESPLINESGRAVITYFIELD_VERSION);\n    file<<nameValue(\"GM\",        GM);\n    file<<nameValue(\"R\",         R);\n    file<<nameValue(\"degree\",    splineDegree);\n    file<<nameValue(\"timeCount\", times.size());\n    for(UInt i=0; i<times.size(); i++)\n      file<<nameValue(\"time\", times.at(i));\n    for(UInt i=0; i<nodeCount; i++)\n    {\n      file<<beginGroup(\"node\");\n      file<<nameValue(\"cnm\", cnm.at(i));\n      file<<nameValue(\"snm\", snm.at(i));\n      file<<endGroup(\"node\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileTimeSplinesGravityfield(const FileName &fileName,\n                                     Double &GM, Double &R, UInt &splineDegree,\n                                     std::vector<Time> &times,\n                                     std::vector<Matrix> &cnm,\n                                     std::vector<Matrix> &snm)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_TIMESPLINESGRAVITYFIELD_TYPE, FILE_TIMESPLINESGRAVITYFIELD_VERSION);\n    file>>nameValue(\"GM\",        GM);\n    file>>nameValue(\"R\",         R);\n    file>>nameValue(\"degree\",    splineDegree);\n    UInt timeCount;\n    file>>nameValue(\"timeCount\", timeCount);\n    times.resize(timeCount);\n    for(UInt i=0; i<timeCount; i++)\n      file>>nameValue(\"time\", times.at(i));\n    const UInt nodeCount = timeCount+splineDegree-1;\n    cnm.resize(nodeCount);\n    snm.resize(nodeCount);\n    for(UInt i=0; i<nodeCount; i++)\n    {\n      file>>beginGroup(\"node\");\n      file>>nameValue(\"cnm\", cnm.at(i));\n      file>>nameValue(\"snm\", snm.at(i));\n      file>>endGroup(\"node\");\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid InFileTimeSplinesCovariance::open(const FileName &name, UInt maxDegree, UInt minDegree)\n{\n  try\n  {\n    close();\n    if(!name.empty())\n    {\n      UInt epochCount;\n      file.open(name, FILE_TIMESPLINESCOVARIANCE_TYPE, FILE_TIMESPLINESCOVARIANCE_VERSION);\n      file>>nameValue(\"GM\",        GM_);\n      file>>nameValue(\"R\",         R_);\n      file>>nameValue(\"minDegree\", minDegree_);\n      file>>nameValue(\"maxDegree\", maxDegree_);\n      file>>nameValue(\"degree\",    splineDegree_);\n      file>>nameValue(\"timeCount\", epochCount);\n      times_.resize(epochCount);\n      for(UInt i=0; i<times_.size(); i++)\n        file>>nameValue(\"time\", times_.at(i));\n\n      mustCut    = (maxDegree < maxDegree_);\n      maxDegree_ = std::min(maxDegree, maxDegree_);\n      minDegree_ = std::max(minDegree, minDegree_);\n\n      // If we have a binary file, we can efficiently seek to the needed position in the file.\n      if(file.canSeek())\n        seekStart = file.position();\n      seekSize = 0;\n\n      indexFile = 0;\n      indexData = nodeCount();;\n      cov.resize(splineDegree_+1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InFileTimeSplinesCovariance::close()\n{\n  file.close();\n  times_.clear();\n  splineDegree_ = 0;\n}\n\n/***********************************************/\n\nMatrix InFileTimeSplinesCovariance::covariance(UInt idNode)\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n\n    // must restart?\n    if(indexFile > idNode)\n    {\n      if(file.canSeek() && seekSize)\n        indexFile = 0;\n      else\n        open(file.fileName(), maxDegree(), minDegree());\n    }\n\n    Matrix C;\n    while(indexFile <= idNode)\n    {\n      // Seek to appropriate interval.\n      if(file.canSeek() && seekSize)\n      {\n        file.seek(seekStart + static_cast<std::streamoff>(idNode * seekSize));\n        indexFile = idNode;\n      }\n\n      file>>nameValue(\"node\", C);\n      if(mustCut)\n      {\n        if(C.getType() == Matrix::SYMMETRIC) // full covariance matrix?\n          C = C.slice(0,0,(maxDegree_+1)*(maxDegree_+1),(maxDegree_+1)*(maxDegree_+1));\n        else\n          C = C.row(0,(maxDegree_+1)*(maxDegree_+1));\n      }\n\n      if(file.canSeek() && (indexFile == 0))\n        seekSize = file.position() - seekStart;\n      indexFile++;\n    }\n\n    return C;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix InFileTimeSplinesCovariance::covariance(const Time &time, Double factor, UInt maxDegree, UInt minDegree, Double GM, Double R)\n{\n  try\n  {\n    if(file.fileName().empty())\n      throw(Exception(\"no file open\"));\n    if((time < times_.front()) || (time > times_.back()))\n      throw(Exception(time.dateTimeStr()+\" outside interval [\"+times_.front().dateTimeStr()+\", \"+times_.back().dateTimeStr()+\"] of <\"+file.fileName().str()+\">\"));\n\n    // find time interval and read missing nodes\n    const UInt idx   = std::min(static_cast<UInt>(std::distance(times_.begin(), std::upper_bound(times_.begin(), times_.end(), time))), times_.size()-1)-1;\n    const UInt start = (idx > indexData) ? std::max(idx, indexData+cov.size()) : idx;\n    const UInt end   = (idx > indexData) ? idx+cov.size() : std::min(idx+cov.size(), indexData);\n    for(UInt i=start; i<end; i++)\n      cov.at(i%cov.size()) = covariance(i);\n    indexData = idx;\n\n    // spline interpolation in interval\n    const Double  t     = (time-times_.at(idx)).mjd()/(times_.at(idx+1)-times_.at(idx)).mjd();\n    const Vector  coeff = BasisSplines::compute(t, splineDegree_);\n    Matrix        C     = factor * coeff(0) * cov.at(indexData%cov.size());\n    for(UInt i=1; i<coeff.rows(); i++)\n      axpy(factor * coeff(i), cov.at((indexData+i)%cov.size()), C);\n\n    if(GM <= 0)  GM = GM_;\n    if(R  <= 0)  R  = R_;\n    if(maxDegree == INFINITYDEGREE) maxDegree = maxDegree_;\n    minDegree = std::min(minDegree, maxDegree);\n\n    if(GM_/GM*factor != 1.0)\n      C *= std::pow(GM_/GM*factor, 2);\n\n    // minDegree\n    // ---------\n    if(C.getType() == Matrix::SYMMETRIC) // full covariance matrix?\n    {\n      for(UInt idx=0; idx<std::pow(std::max(minDegree_, minDegree),2); idx++)\n      {\n        C.row(idx)    *= 0;\n        C.column(idx) *= 0;\n      }\n    }\n    else\n      for(UInt idx=0; idx<std::pow(std::max(minDegree_, minDegree),2); idx++)\n        C.row(idx) *= 0;\n\n    // Quick return possible?\n    // ----------------------\n    if((R == R_) && (maxDegree == maxDegree_))\n      return C;\n\n    // full covariance matrix?\n    // -----------------------\n    if(C.getType() == Matrix::SYMMETRIC)\n    {\n      if(maxDegree < maxDegree_)\n        C = C.slice(0, 0, (maxDegree+1)*(maxDegree+1), (maxDegree+1)*(maxDegree+1));\n      else if(maxDegree>maxDegree_)\n      {\n        Matrix tmp = C;\n        C = Matrix((maxDegree+1)*(maxDegree+1), Matrix::SYMMETRIC);\n        copy(tmp, C.slice(0, 0, tmp.rows(), tmp.columns()));\n      }\n\n      if(R != R_)\n      {\n        Double factor = R_/R;\n        UInt idx = 0;\n        for(UInt n=0; n<=maxDegree; n++)\n        {\n          for(UInt m=0; m<2*n+1; m++)\n          {\n            C.row(idx)    *= factor;\n            C.column(idx) *= factor;\n            idx++;\n          }\n          factor *= R_/R;\n        }\n      } // (R!=R_)\n\n      return C;\n    }\n\n    // only variances\n    // --------------\n    if(maxDegree < maxDegree_)\n      C = C.row(0, (maxDegree+1)*(maxDegree+1));\n    else if(maxDegree > maxDegree_)\n    {\n      Matrix tmp = C;\n      C = Matrix((maxDegree+1)*(maxDegree+1), tmp.columns());\n      copy(tmp, C.row(0, tmp.rows()));\n    }\n\n    if(R != R_)\n    {\n      Double factor = R_/R;\n      UInt idx = 0;\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        for(UInt m=0; m<2*n+1; m++)\n          C.row(idx++) *= std::pow(factor, 2);\n        factor *= R_/R;\n      }\n    } // (R!=R_)\n\n    return C;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileTimeSplinesCovariance(const FileName &fileName,\n                                    Double GM, Double R, UInt minDegree, UInt maxDegree, UInt splineDegree,\n                                    const std::vector<Time> &times,\n                                    const std::vector<Matrix> &sigma2)\n{\n  try\n  {\n    UInt nodeCount = times.size()+splineDegree-1;\n    if(nodeCount != sigma2.size())\n      throw(Exception(\"size of series of sigma2 does not mach to number of times.\"));\n\n    OutFileArchive file(fileName, FILE_TIMESPLINESCOVARIANCE_TYPE, FILE_TIMESPLINESCOVARIANCE_VERSION);\n    file<<nameValue(\"GM\",        GM);\n    file<<nameValue(\"R\",         R);\n    file<<nameValue(\"minDegree\", minDegree);\n    file<<nameValue(\"maxDegree\", maxDegree);\n    file<<nameValue(\"degree\",    splineDegree);\n    file<<nameValue(\"timeCount\", times.size());\n    for(UInt i=0; i<times.size(); i++)\n      file<<nameValue(\"time\", times.at(i));\n    for(UInt i=0; i<nodeCount; i++)\n      file<<nameValue(\"node\", sigma2.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileTimeSplinesCovariance(const FileName &fileName,\n                                   Double &GM, Double &R, UInt &minDegree, UInt &maxDegree, UInt &splineDegree,\n                                   std::vector<Time> &times,\n                                   std::vector<Matrix> &sigma2)\n{\n  try\n  {\n    InFileArchive file(fileName, FILE_TIMESPLINESCOVARIANCE_TYPE, FILE_TIMESPLINESCOVARIANCE_VERSION);\n    file>>nameValue(\"GM\",        GM);\n    file>>nameValue(\"R\",         R);\n    file>>nameValue(\"minDegree\", minDegree);\n    file>>nameValue(\"maxDegree\", maxDegree);\n    file>>nameValue(\"degree\",    splineDegree);\n    UInt timeCount;\n    file>>nameValue(\"timeCount\", timeCount);\n    times.resize(timeCount);\n    for(UInt i=0; i<timeCount; i++)\n      file>>nameValue(\"time\", times.at(i));\n    const UInt nodeCount = timeCount+splineDegree-1;\n    sigma2.resize(nodeCount);\n    for(UInt i=0; i<nodeCount; i++)\n      file>>nameValue(\"node\", sigma2.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileTimeSplinesGravityfield.h",
    "content": "/***********************************************/\n/**\n* @file fileTimeSplinesGravityfield.h\n*\n* @brief time variable gravity field represented by splines in time domain.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILETIMESPLINESGRAVITYFIELD__\n#define __GROOPS_FILETIMESPLINESGRAVITYFIELD__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_TimeSplinesGravityField\nstatic const char *docstringTimeSplinesGravityField = R\"(\nTemporal changing gravity field, parametrized as spherical harmonics in the spatial domain and\nparametrized as basis splines in the time domain (see~\\reference{basis splines}{fundamentals.basisSplines}).\nIt is evaluated with \\configClass{gravityfield:timeSplines}{gravityfieldType:timeSplines}.\n\nSee also: \\program{Gravityfield2TimeSplines}, \\program{PotentialCoefficients2BlockMeanTimeSplines}.\n)\";\n#endif\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_TimeSplinesCovariance\nstatic const char *docstringTimeSplinesCovariance = R\"(\nStores covariance information for \\file{TimeSplinesGravityField}{timeSplinesGravityField}.\nIt can be the variances of the potential coefficients or the full covariance matrix for each\ntemporal nodal point.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_TIMESPLINESGRAVITYFIELD_TYPE    = \"timeSplinesGravityField\";\nconst char *const FILE_TIMESPLINESCOVARIANCE_TYPE      = \"timeSplinesCovariance\";\nconstexpr UInt    FILE_TIMESPLINESGRAVITYFIELD_VERSION = std::max(UInt(20200123), FILE_BASE_VERSION);\nconstexpr UInt    FILE_TIMESPLINESCOVARIANCE_VERSION   = std::max(UInt(20200123), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Time variable gravity field represented by splines in time domain. */\nclass InFileTimeSplinesGravityfield\n{\n  InFileArchive       file;\n  UInt                splineDegree_;\n  std::vector<Time>   times_;\n  Double              GM, R;\n  UInt                maxDegree_, minDegree_;\n  UInt                indexFile, indexData;\n  std::streampos      seekStart;\n  std::streamoff      seekSize;\n  std::vector<SphericalHarmonics> harmonics;\n\npublic:\n  InFileTimeSplinesGravityfield() {}\n  InFileTimeSplinesGravityfield(const FileName &name, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) {open(name, maxDegree, minDegree);}\n ~InFileTimeSplinesGravityfield() {close();}\n\n  void  open(const FileName &name, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0);\n  void  close();\n\n  UInt splineDegree() const {return splineDegree_;}\n  UInt nodeCount()    const {return times_.size()+splineDegree_-1;}  //!< number of spline nodal points (agree with times().size() for spline degree 1)\n  const std::vector<Time> &times() const {return times_;}\n\n  /// at spline nodal point\n  SphericalHarmonics sphericalHarmonics(UInt idNode);\n\n  /// interpolated at @p time.\n  SphericalHarmonics sphericalHarmonics(const Time &time, Double factor=1.0);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write a TimeSplinesGravityfieldFile. */\nvoid writeFileTimeSplinesGravityfield(const FileName &fileName,\n                                      Double GM, Double R, UInt splineDegree,\n                                      const std::vector<Time> &times,\n                                      const std::vector<Matrix> &cnm,\n                                      const std::vector<Matrix> &snm);\n\n/** @brief Read a TimeSplinesGravityfieldFile. */\nvoid readFileTimeSplinesGravityfield(const FileName &fileName,\n                                     Double &GM, Double &R, UInt &splineDegree,\n                                     std::vector<Time> &times,\n                                     std::vector<Matrix> &cnm,\n                                     std::vector<Matrix> &snm);\n\n/***** CLASS ***********************************/\n\n/** @brief Time variable covariances represented by splines in time domain. */\nclass InFileTimeSplinesCovariance\n{\n  InFileArchive       file;\n  UInt                splineDegree_;\n  std::vector<Time>   times_;\n  Double              GM_, R_;\n  Bool                mustCut;\n  UInt                maxDegree_, minDegree_;\n  UInt                indexFile, indexData;\n  std::streampos      seekStart;\n  std::streamoff      seekSize;\n  std::vector<Matrix> cov;\n\npublic:\n  InFileTimeSplinesCovariance() {}\n  InFileTimeSplinesCovariance(const FileName &name, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0) {open(name, maxDegree, minDegree);}\n ~InFileTimeSplinesCovariance() {close();}\n\n  void  open(const FileName &name, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0);\n  void  close();\n\n  UInt   splineDegree() const {return splineDegree_;}\n  UInt   nodeCount()    const {return times_.size()+splineDegree_-1;}  //!< number of spline nodal points (agree with times().size() for spline degree 1)\n  Double GM()           const {return GM_;}\n  Double R()            const {return R_;}\n  UInt   maxDegree()    const {return maxDegree_;}\n  UInt   minDegree()    const {return minDegree_;}\n  const std::vector<Time> &times() const {return times_;}\n\n  /// at spline nodal point\n  Matrix covariance(UInt idNode);\n\n  /** @brief interpolated covariances at time t.\n  * The result is a full covariance matrix or a vector containing only the variances\n  * of a spherical harmonics expansion.\n  * The coefficients are given in a degree wise sequence with alternating sin, cos:\n  * ..., c20,c21,s21,c22,s22,..., beginning with c00.  */\n  Matrix covariance(const Time &time, Double factor, UInt maxDegree=INFINITYDEGREE, UInt minDegree=0, Double GM=0.0, Double R=0.0);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write a TimeSplinesCovarianceFile. */\nvoid writeFileTimeSplinesCovariance(const FileName &fileName,\n                                    Double GM, Double R, UInt minDegree, UInt maxDegree, UInt splineDegree,\n                                    const std::vector<Time> &times,\n                                    const std::vector<Matrix> &sigma2);\n\n\n/** @brief Read a TimeSplinesCovarianceFile. */\nvoid readFileTimeSplinesCovariance(const FileName &fileName,\n                                   Double &GM, Double &R, UInt &minDegree, UInt &maxDegree, UInt &splineDegree,\n                                   std::vector<Time> &times,\n                                   std::vector<Matrix> &sigma2);\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS TIMESPLINESGRAVITYFIELD */\n"
  },
  {
    "path": "source/files/fileVariationalEquation.cpp",
    "content": "/***********************************************/\n/**\n* @file fileVariationalEquation.cpp\n*\n* @brief Variational equation arcs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-22\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_FILEFORMAT_VariationalEquation\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileFormatRegister.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"files/fileVariationalEquation.h\"\n\nGROOPS_REGISTER_FILEFORMAT(VariationalEquation, FILE_VARIATIONALEQUATION_TYPE)\n\n/***********************************************/\n\nOrbitArc VariationalEquationArc::orbitArc() const\n{\n  try\n  {\n    OrbitArc orbit;\n    OrbitEpoch epoch;\n    for(UInt i=0; i<times.size(); i++)\n    {\n      epoch.time         = times.at(i);\n      epoch.position     = Vector3d(pos0(3*i+0,0), pos0(3*i+1,0), pos0(3*i+2,0));\n      epoch.velocity     = Vector3d(vel0(3*i+0,0), vel0(3*i+1,0), vel0(3*i+2,0));\n      orbit.push_back(epoch);\n    }\n    return orbit;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid FileVariationalEquation::open(const FileName &fileName)\n{\n  try\n  {\n    close();\n    if(!fileName.empty())\n    {\n      _file.open(fileName, FILE_VARIATIONALEQUATION_TYPE, FILE_VARIATIONALEQUATION_VERSION);\n      // check for old version\n      if(_file.version() < 20150524)\n        throw(Exception(\"version of <\"+fileName.str()+\"> is not supported anymore. Please recompute.\"));\n      _file>>nameValue(\"satellite\", _satellite);\n      _file>>nameValue(\"arcCount\",  _arcCount);\n      _fileName = fileName;\n      _index = 0;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid FileVariationalEquation::close()\n{\n  if(!_fileName.empty())\n    _file.close();\n  _fileName = FileName();\n  _arcCount = 0;\n}\n\n/***********************************************/\n\nVariationalEquationArc FileVariationalEquation::readArc(UInt arcNo)\n{\n  try\n  {\n    if(_fileName.empty())\n      return VariationalEquationArc();\n\n    if(arcNo>=_arcCount)\n      throw(Exception(\"arcNo >= arcCount\"));\n\n    // arc already read -> restart\n    if(arcNo<_index)\n      open(FileName(_fileName));\n\n    VariationalEquationArc arc;\n    while(_index <= arcNo)\n    {\n      _file>>nameValue(\"arc\", arc);\n      _index++;\n    }\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileVariationalEquation(const FileName &fileName, SatelliteModelPtr satellite, VariationalEquationArc arc)\n{\n  writeFileVariationalEquation(fileName, satellite, std::vector<VariationalEquationArc>(1, arc));\n}\n\n/***********************************************/\n\nvoid writeFileVariationalEquation(const FileName &fileName, SatelliteModelPtr satellite, std::vector<VariationalEquationArc> arcList)\n{\n  try\n  {\n    OutFileArchive file(fileName, FILE_VARIATIONALEQUATION_TYPE, FILE_VARIATIONALEQUATION_VERSION);\n    file<<nameValue(\"satellite\", satellite);\n    file<<nameValue(\"arcCount\", arcList.size());\n    for(auto iter=arcList.begin(); iter!=arcList.end(); iter++)\n      file<<nameValue(\"arc\", *iter);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid VariationalEquationArc::save(OutArchive &oa) const\n{\n  oa << nameValue(\"times\",    times);\n  oa << nameValue(\"pos0\",     pos0);\n  oa << nameValue(\"vel0\",     vel0);\n  oa << nameValue(\"PosState\", PosState);\n  oa << nameValue(\"VelState\", VelState);\n  oa << nameValue(\"rotEarth\", rotEarth);\n  oa << nameValue(\"rotSat\",   rotSat);\n}\n\n/***********************************************/\n\nvoid VariationalEquationArc::load(InArchive  &ia)\n{\n  ia >> nameValue(\"times\",    times);\n  ia >> nameValue(\"pos0\",     pos0);\n  ia >> nameValue(\"vel0\",     vel0);\n  ia >> nameValue(\"PosState\", PosState);\n  ia >> nameValue(\"VelState\", VelState);\n  ia >> nameValue(\"rotEarth\", rotEarth);\n  ia >> nameValue(\"rotSat\",   rotSat);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/files/fileVariationalEquation.h",
    "content": "/***********************************************/\n/**\n* @file fileVariationalEquation.h\n*\n* @brief Variational equation arcs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEVARIATIONALEQUATION__\n#define __GROOPS_FILEVARIATIONALEQUATION__\n\n// Latex documentation\n#ifdef DOCSTRING_FILEFORMAT_VariationalEquation\nstatic const char *docstringVariationalEquation = R\"(\nArcs with reference orbit and state transition matrices.\n\nThe file contains a reference orbit (position and velocity),\nthe derivatives of the orbit with respect to the satellite state vector for each arc,\ntransformations (rotations) between the satellite, celestial, and terrestrial frame\nand a satellite macro model (see \\file{SatelliteModel}{satelliteModel}).\n\nThe reference orbit can be extracted with \\program{Variational2OrbitAndStarCamera}.\n\nSee also: \\program{PreprocessingVariationalEquation}.\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n\n/** @addtogroup filesGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconst char *const FILE_VARIATIONALEQUATION_TYPE    = \"variationalEquation\";\nconstexpr UInt    FILE_VARIATIONALEQUATION_VERSION = std::max(std::max(UInt(20200123), FILE_SATELLITEMODEL_VERSION), FILE_BASE_VERSION);\n\n/***** CLASS ***********************************/\n\n/** @brief Variational equation arc. */\nclass VariationalEquationArc\n{\n  public:\n  std::vector<Time>     times;\n  Matrix                pos0, PosState;\n  Matrix                vel0, VelState;\n  std::vector<Rotary3d> rotSat;   //!< Sat -> CRF\n  std::vector<Rotary3d> rotEarth; //!< CRF -> TRF\n\n  OrbitArc orbitArc() const;\n\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Variational equation arcs. */\nclass FileVariationalEquation\n{\n  FileName          _fileName;\n  InFileArchive     _file;\n  SatelliteModelPtr _satellite;\n  UInt              _arcCount;\n  UInt              _index;\n\npublic:\n  /// Default Constructor.\n  FileVariationalEquation() : _arcCount(0) {}\n\n  /// Constructor.\n  FileVariationalEquation(const FileName &fileName) {open(fileName);}\n\n  /// Destructor.\n  ~FileVariationalEquation() {close();}\n\n  /** @brief Open a new file.\n  * Old open file is closed before. */\n  void  open(const FileName &fileName);\n\n  /** @brief Close the file. */\n  void  close();\n\n  /** @brief Number of Arc in file. */\n  UInt arcCount() const {return _arcCount;}\n\n  /** @brief Satellite model. */\n  SatelliteModelPtr satellite() const {return _satellite;}\n\n  /** @brief Read a single Arc.\n  * The operation is faster, if the arcs is read in increasing order. */\n  VariationalEquationArc readArc(UInt arcNo);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Write a variational equation file. */\nvoid writeFileVariationalEquation(const FileName &fileName, SatelliteModelPtr satellite, VariationalEquationArc arc);\n\n/** @brief Write a variational equation file. */\nvoid writeFileVariationalEquation(const FileName &fileName, SatelliteModelPtr satellite, std::vector<VariationalEquationArc> arcs);\n\n/***********************************************/\n\n/// @}\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnss.cpp",
    "content": "/***********************************************/\n/**\n* @file gnss.cpp\n*\n* @brief global navigation satellite system.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-08-03\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss.h\"\n#include \"gnss/gnssObservation.h\"\n#include \"gnss/gnssDesignMatrix.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n\n/***********************************************/\n\nvoid Gnss::init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n                GnssTransmitterGeneratorPtr transmitterGenerator, GnssReceiverGeneratorPtr receiverGenerator,\n                EarthRotationPtr earthRotation, GnssParametrizationPtr parametrization, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->times = times;\n\n    // init earth rotation\n    // -------------------\n    eop = Matrix(times.size(), 8); // Matrix eop columns: xp, yp, sp, deltaUT, LOD, X, Y, S\n    for(UInt i=0; i<times.size(); i++)\n      earthRotation->earthOrientationParameter(times.at(i), eop(i,0), eop(i,1), eop(i,2), eop(i,3), eop(i,4), eop(i,5), eop(i,6), eop(i,7));\n    // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n    for(UInt i=0; i<times.size(); i++)\n      eop(i,3) -= (times.at(i)-timeGPS2UTC(times.at(i))).seconds();\n\n    funcRotationCrf2Trf = std::bind(&Gnss::rotationCrf2Trf, this, std::placeholders::_1);\n\n    // init transmitters\n    // -----------------\n    transmitters = transmitterGenerator->transmitters(times);\n    for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n      transmitters.at(idTrans)->id_ = idTrans;\n\n    // init receivers\n    // --------------\n    receivers = receiverGenerator->receivers(simulationTypes, times, timeMargin, transmitters, earthRotation, comm);\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      receivers.at(idRecv)->id_ = idRecv;\n    synchronizeTransceivers(comm);\n\n    // init parametrization\n    // --------------------\n    this->parametrization = parametrization;\n    if(parametrization)\n    {\n      parametrization->init(this, comm);\n      funcReduceModels = std::bind(&GnssParametrization::observationCorrections, parametrization, std::placeholders::_1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d Gnss::rotationCrf2Trf(const Time &time) const\n{\n  try\n  {\n    const UInt idx = std::min((times.size()-1), static_cast<UInt>(std::distance(times.begin(),\n                     std::upper_bound(times.begin(), times.end(), time, [](const Time &t, const Time &s) {return (t-s).seconds() < 0.5;}))));\n    const Double xp      = eop(idx, 0);\n    const Double yp      = eop(idx, 1);\n    const Double sp      = eop(idx, 2);\n    const Double deltaUT = eop(idx, 3) + (time-timeGPS2UTC(time)).seconds();\n    const Double X       = eop(idx, 5);\n    const Double Y       = eop(idx, 6);\n    const Double S       = eop(idx, 7);\n\n    const Double ERA = Planets::ERA(timeGPS2UTC(time) + seconds2time(deltaUT));\n    const Double r2  = X*X + Y*Y;\n    const Double E   = (r2!=0.) ? std::atan2(Y, X) : 0.;\n    const Double D   = std::atan(std::sqrt(r2/(1-r2)));\n\n    return  rotaryX(Angle(-yp)) * rotaryY(Angle(-xp)) *\n            rotaryZ(Angle(sp+ERA-S-E)) *\n            rotaryY(Angle(D)) * rotaryZ(Angle(E));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::synchronizeTransceivers(Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    // distribute process id of receivers\n    // ----------------------------------\n    Vector recvProcess(receivers.size());\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      if(receivers.at(idRecv)->isMyRank())\n        recvProcess(idRecv) = Parallel::myRank(comm)+1;\n    Parallel::reduceSum(recvProcess, 0, comm);\n    Parallel::broadCast(recvProcess, 0, comm);\n\n    // synchronize transceivers\n    // ------------------------\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      if(recvProcess(idRecv))\n        Parallel::broadCast(static_cast<GnssTransceiver&>(*receivers.at(idRecv)), static_cast<UInt>(recvProcess(idRecv)-1), comm);\n      else if(receivers.at(idRecv)->useable())\n        receivers.at(idRecv)->disable(\"\");\n\n    // collect observation types\n    // -------------------------\n    typesRecvTrans.clear();\n    typesRecvTrans.resize(receivers.size(), std::vector<std::vector<GnssType>>(transmitters.size()));\n    for(auto recv : receivers)\n    {\n      if(recv->isMyRank())\n        for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n        {\n          for(UInt idEpoch=0; idEpoch<recv->idEpochSize(); idEpoch++)\n          {\n            auto obs = recv->observation(idTrans, idEpoch);\n            if(obs)\n              for(UInt idType=0; idType<obs->size(); idType++)\n                if(!obs->at(idType).type.isInList(typesRecvTrans.at(recv->idRecv()).at(idTrans)))\n                  typesRecvTrans.at(recv->idRecv()).at(idTrans).push_back(obs->at(idType).type);\n          }\n          std::sort(typesRecvTrans.at(recv->idRecv()).at(idTrans).begin(), typesRecvTrans.at(recv->idRecv()).at(idTrans).end());\n        }\n      if(recv->useable())\n        Parallel::broadCast(typesRecvTrans.at(recv->idRecv()), static_cast<UInt>(recvProcess(recv->idRecv())-1), comm);\n    }\n\n    // adjust signal biases to available observation types\n    // ---------------------------------------------------\n    for(auto trans : transmitters)\n    {\n      std::vector<GnssType> types;\n      for(auto &typesTrans : typesRecvTrans)\n        for(GnssType type : typesTrans.at(trans->idTrans()))\n          if((type == GnssType::PHASE) || (type == GnssType::RANGE))\n            if(!type.isInList(types))\n              types.push_back(type + trans->PRN());\n      types = GnssType::replaceCompositeSignals(types);\n\n      if(types.size())\n      {\n        trans->signalBias.biases = trans->signalBias.compute(types); // apriori signal bias\n        trans->signalBias.types  = types;\n      }\n    }\n\n    for(auto recv : receivers)\n    {\n      std::vector<GnssType> types;\n      for(auto &typesTrans : typesRecvTrans.at(recv->idRecv()))\n        for(GnssType type : typesTrans)\n          if((type == GnssType::PHASE) || (type == GnssType::RANGE))\n            if(!type.isInList(types))\n              types.push_back(type & ~GnssType::PRN);\n      std::sort(types.begin(), types.end());\n\n      if(types.size())\n      {\n        recv->signalBias.biases = recv->signalBias.compute(types); // apriori signal bias\n        recv->signalBias.types  = types;\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    logStatus<<\"setup parameters\"<<Log::endl;\n    if(!parametrization)\n      throw(Exception(\"no parametrization given\"));\n\n    // disable unuseable transmitters/receivers/epochs\n    // -----------------------------------------------\n    // check number of required observations\n    std::vector<UInt> transCount(transmitters.size(), 0), transCountEpoch(transmitters.size(), 0);\n    std::vector<UInt> recvCount(receivers.size(), 0),     recvCountEpoch(receivers.size(), 0);\n    parametrization->requirements(normalEquationInfo, transCount, transCountEpoch, recvCount, recvCountEpoch);\n    UInt disabledEpochsTrans = 0;\n    UInt disabledEpochsRecv = 0;\n    for(;;)\n    {\n      UInt mustSync = 0;\n\n      // disable transmitters\n      for(auto trans : transmitters)\n        if(trans->useable() && (transCount.at(trans->idTrans()) || transCountEpoch.at(trans->idTrans())))\n        {\n          Vector countEpoch(times.size());\n          for(const auto &recv : receivers)\n            if(normalEquationInfo.estimateReceiver.at(recv->idRecv()) && recv->isMyRank())\n              for(UInt idEpoch : normalEquationInfo.idEpochs)\n                if(trans->useable(idEpoch) && recv->useable(idEpoch) && recv->observation(trans->idTrans(), idEpoch))\n                  countEpoch(idEpoch)++;\n          Parallel::reduceSum(countEpoch, 0, normalEquationInfo.comm);\n          Parallel::broadCast(countEpoch, 0, normalEquationInfo.comm);\n\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(trans->useable(idEpoch) && (countEpoch(idEpoch) < transCountEpoch.at(trans->idTrans())))\n            {\n              // logWarningOnce<<trans->name()<<\" disabled epoch \"<<times.at(idEpoch).dateTimeStr()<<Log::endl;\n              disabledEpochsTrans++;\n              trans->disable(idEpoch, \"failed parametrization requirements\");\n              mustSync = TRUE;\n              for(const auto &recv : receivers)\n                if(recv->isMyRank() && recv->observation(trans->idTrans(), idEpoch))\n                  recv->deleteObservation(trans->idTrans(), idEpoch);\n            }\n\n          UInt epochCount = 0;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(countEpoch(idEpoch) > transCountEpoch.at(trans->idTrans()))\n              epochCount++;\n          if(epochCount < transCount.at(trans->idTrans()))\n          {\n            logWarningOnce<<trans->name()<<\" disabled: not enough estimable epochs (\"<<epochCount<<\")\"<<Log::endl;\n            trans->disable(\"not enough estimable epochs (\"+epochCount%\"%i)\"s);\n            mustSync = TRUE;\n            for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n              for(const auto &recv : receivers)\n                if(recv->isMyRank() && recv->observation(trans->idTrans(), idEpoch))\n                  recv->deleteObservation(trans->idTrans(), idEpoch);\n          }\n        }\n\n      // disable receivers\n      for(auto recv : receivers)\n        if(normalEquationInfo.estimateReceiver.at(recv->idRecv()) && recv->isMyRank() && (recvCount.at(recv->idRecv()) || recvCountEpoch.at(recv->idRecv())))\n        {\n          UInt epochCount = 0;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(recv->useable(idEpoch))\n            {\n              UInt count = 0;\n              for(auto trans : transmitters)\n                if(trans->useable(idEpoch) && recv->observation(trans->idTrans(), idEpoch))\n                  count++;\n              if(count < recvCountEpoch.at(recv->idRecv()))\n              {\n                // logWarning<<recv->name()<<\" disabled epoch \"<<times.at(idEpoch).dateTimeStr()<<Log::endl;\n                disabledEpochsRecv++;\n                recv->disable(idEpoch, \"failed parametrization requirements\");\n                mustSync = TRUE;\n              }\n              else if(count > recvCountEpoch.at(recv->idRecv()))\n                epochCount++;\n            }\n\n          if(epochCount < recvCount.at(recv->idRecv()))\n          {\n            logWarning<<recv->name()<<\" disabled: not enough estimable epochs (\"<<epochCount<<\")\"<<Log::endl;\n            recv->disable(\"not enough estimable epochs (\"+epochCount%\"%i)\"s);\n            mustSync = TRUE;\n          }\n        }\n\n      // is something disabled?\n      Parallel::reduceSum(mustSync, 0, normalEquationInfo.comm);\n      Parallel::broadCast(mustSync, 0, normalEquationInfo.comm);\n      if(!mustSync)\n        break;\n\n      // synchronize transceivers\n      synchronizeTransceivers(normalEquationInfo.comm);\n      Parallel::reduceSum(disabledEpochsRecv, 0, normalEquationInfo.comm);\n      if(!Parallel::isMaster(normalEquationInfo.comm))\n        disabledEpochsRecv = 0;\n    } // for(;;)\n\n    if(disabledEpochsTrans) logWarningOnce<<disabledEpochsTrans<<\" disabled transmitter epochs\"<<Log::endl;\n    if(disabledEpochsRecv)  logWarningOnce<<disabledEpochsRecv <<\" disabled receiver epochs\"<<Log::endl;\n\n    for(auto recv : receivers)\n      if(!recv->useable())\n        normalEquationInfo.estimateReceiver.at(recv->idRecv()) = FALSE;\n\n    // distribute process id of receivers\n    // ----------------------------------\n    Vector recvProcess(receivers.size());\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      if(receivers.at(idRecv)->isMyRank())\n        recvProcess(idRecv) = Parallel::myRank(normalEquationInfo.comm)+1;\n    Parallel::reduceSum(recvProcess, 0, normalEquationInfo.comm);\n    Parallel::broadCast(recvProcess, 0, normalEquationInfo.comm);\n\n    // init parameters\n    // ---------------\n    normalEquationInfo.initNewParameterNames();\n    parametrization->initParameter(normalEquationInfo);\n    normalEquationInfo.calculateIndex(recvProcess);\n    logInfo<<\"+ =======\"<<Log::endl;\n    logInfo<<normalEquationInfo.parameterCount()%\"%9i parameters in \"s<<normalEquationInfo.blockCount()<<\" normal equation matrix blocks\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Gnss::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo) const\n{\n  try\n  {\n    Vector x0 = parametrization->aprioriParameter(normalEquationInfo);\n    Parallel::reduceSum(x0, 0, normalEquationInfo.comm);\n    return x0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool Gnss::basicObservationEquations(const GnssNormalEquationInfo &/*normalEquationInfo*/, UInt idRecv, UInt idTrans, UInt idEpoch, GnssObservationEquation &eqn) const\n{\n  try\n  {\n    std::vector<GnssType> type;\n    if(!receivers.at(idRecv)->observation(idTrans, idEpoch) ||\n       !receivers.at(idRecv)->observation(idTrans, idEpoch)->observationList(GnssObservation::RANGE | GnssObservation::PHASE, type))\n      return FALSE;\n    eqn.compute(*receivers.at(idRecv)->observation(idTrans, idEpoch), *receivers.at(idRecv), *transmitters.at(idTrans),\n                funcRotationCrf2Trf, funcReduceModels, idEpoch, TRUE, type);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    if(eqn.l.rows())\n      parametrization->designMatrix(normalEquationInfo, eqn, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    parametrization->constraintsEpoch(normalEquationInfo, idEpoch, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    parametrization->constraints(normalEquationInfo, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Gnss::ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                              const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                              const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger)\n{\n  try\n  {\n    return parametrization->ambiguityResolve(normalEquationInfo, normals, n, lPl, obsCount,\n                                             selectedTransmitters, selectedReceivers, searchInteger);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Gnss::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    return parametrization->updateParameter(normalEquationInfo, x, Wz);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    parametrization->updateCovariance(normalEquationInfo, covariance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix)\n{\n  try\n  {\n    parametrization->writeResults(normalEquationInfo, suffix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<GnssType> Gnss::types(const GnssType mask) const\n{\n  try\n  {\n    std::vector<GnssType> types;\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n        for(GnssType type : typesRecvTrans.at(idRecv).at(idTrans))\n          if(!type.isInList(types))\n             types.push_back(type & mask);\n    std::sort(types.begin(), types.end());\n    return types;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<Byte> Gnss::selectTransmitters(PlatformSelectorPtr selector)\n{\n  try\n  {\n    std::vector<const Platform*> platforms(transmitters.size(), nullptr);\n    for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n      if(transmitters.at(idTrans)->useable())\n        platforms.at(idTrans) = &transmitters.at(idTrans)->platform;\n    return selector->select(times.front(), times.back(), platforms);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Byte> Gnss::selectReceivers(PlatformSelectorPtr selector)\n{\n  try\n  {\n    std::vector<const Platform*> platforms(receivers.size(), nullptr);\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      if(receivers.at(idRecv)->useable())\n        platforms.at(idRecv) = &receivers.at(idRecv)->platform;\n    return selector->select(times.front(), times.back(), platforms);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nBool Gnss::InfoParameterChange::update(Double change)\n{\n  try\n  {\n    count++;\n    rms += change*change;\n    if(std::fabs(change) > std::fabs(maxChange))\n    {\n      maxChange = change;\n      return TRUE;\n    }\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Gnss::InfoParameterChange::synchronizeAndPrint(Parallel::CommunicatorPtr comm, Double convertToMeter, Double &maxChangeTotal)\n{\n  try\n  {\n    Vector change(Parallel::size(comm));\n    change(Parallel::myRank(comm)) = maxChange;\n    Parallel::reduceSum(change, 0, comm);\n    Parallel::broadCast(change, 0, comm);\n    UInt idProcess = 0;\n    maxChange = 0;\n    for(UInt i=0; i<change.rows(); i++)\n      if(std::fabs(change(i)) > std::fabs(maxChange))\n      {\n        maxChange = change(i);\n        idProcess = i;\n      }\n    maxChangeTotal = std::max(maxChangeTotal, std::fabs(convertToMeter*maxChange));\n\n    Parallel::reduceSum(count, 0, comm);\n    Parallel::reduceSum(rms,   0, comm);\n\n    if((idProcess != 0) && (idProcess == Parallel::myRank(comm)))\n      Parallel::send(info, 0, comm);\n    else if(Parallel::isMaster(comm))\n    {\n      if(idProcess != 0)\n        Parallel::receive(info, idProcess, comm);\n      rms = std::sqrt(rms/count);\n      if(!info.empty())\n      {\n        std::string space(5-std::min(unit.size(), std::size_t(4)), ' ');\n        logInfo<<\"  rms =\"<<rms%\"%7.1f \"s<<unit<<\",\"<<space<<\"max =\"<<maxChange%\"%8.1f \"s<<unit<<\",\"<<space<<info<<Log::endl;\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnss.h",
    "content": "/***********************************************/\n/**\n* @file gnss.h\n*\n* @brief global navigation satellite system classes.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-08-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSS__\n#define __GROOPS_GNSS__\n\n#include \"parallel/parallel.h\"\n#include \"base/gnssType.h\"\n#include \"base/parameterName.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"gnss/gnssObservation.h\"\n#include \"gnss/gnssDesignMatrix.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssNormalEquationInfo.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Gnss;\ntypedef std::shared_ptr<Gnss> GnssPtr;\n\nclass MatrixDistributed;\nclass GnssTransmitterGenerator;\nclass GnssReceiverGenerator;\nclass GnssParametrization;\nclass EarthRotation;\nclass PlatformSelector;\ntypedef std::shared_ptr<GnssTransmitterGenerator> GnssTransmitterGeneratorPtr;\ntypedef std::shared_ptr<GnssReceiverGenerator>    GnssReceiverGeneratorPtr;\ntypedef std::shared_ptr<GnssParametrization>      GnssParametrizationPtr;\ntypedef std::shared_ptr<EarthRotation>            EarthRotationPtr;\ntypedef std::shared_ptr<PlatformSelector>         PlatformSelectorPtr;\n\n/***** CLASS ***********************************/\n\nclass Gnss\n{\npublic:\n  std::vector<Time>               times;           // Epochs\n  std::vector<GnssTransmitterPtr> transmitters;    // GNSS satellites\n  std::vector<GnssReceiverPtr>    receivers;       // stations & LEOs\n  GnssParametrizationPtr          parametrization; // parameters\n  std::function<void(GnssObservationEquation &eqn)> funcReduceModels;\n  std::function<Rotary3d(const Time &time)>         funcRotationCrf2Trf;\n  Matrix                          eop;             // Matrix eop columns: xp, yp, sp, deltaUT, LOD, X, Y, S\n  std::vector<std::vector<std::vector<GnssType>>> typesRecvTrans; // for each receiver and transmitter: used types (receiver types)\n\n  void init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n            GnssTransmitterGeneratorPtr transmitterGenerator, GnssReceiverGeneratorPtr receiverGenerator,\n            EarthRotationPtr earthRotation, GnssParametrizationPtr parametrization, Parallel::CommunicatorPtr comm);\n\n  Rotary3d rotationCrf2Trf(const Time &time) const; // Inertial system (CRF) -> earth fixed system (TRF).\n  void     synchronizeTransceivers(Parallel::CommunicatorPtr comm);\n\n  void   initParameter            (GnssNormalEquationInfo &normalEquationInfo);\n  Vector aprioriParameter         (const GnssNormalEquationInfo &normalEquationInfo) const;\n  Bool   basicObservationEquations(const GnssNormalEquationInfo &normalEquationInfo, UInt idRecv, UInt idTrans, UInt idEpoch, GnssObservationEquation &eqn) const;\n  void   designMatrix             (const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const;\n  void   constraintsEpoch         (const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const;\n  void   constraints              (const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const;\n  Double ambiguityResolve         (const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                                   const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                                   const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger);\n  Double updateParameter          (const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz);\n  void   updateCovariance         (const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance);\n  void   writeResults             (const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix=\"\");\n\n  /** @brief sorted list of used types. */\n  std::vector<GnssType> types(const GnssType mask=GnssType::ALL) const;\n\n  std::vector<Byte> selectTransmitters(PlatformSelectorPtr selector);\n  std::vector<Byte> selectReceivers(PlatformSelectorPtr selector);\n\n  class InfoParameterChange\n  {\n  public:\n    std::string unit;\n    UInt        count;\n    Double      rms;\n    Double      maxChange;\n    std::string info;\n\n    InfoParameterChange(const std::string &unit) : unit(unit), count(0), rms(0), maxChange(0) {}\n    Bool update(Double change);\n    void synchronizeAndPrint(Parallel::CommunicatorPtr comm, Double convertToMeter, Double &maxChangeTotal);\n  };\n};\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssDesignMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssDesignMatrix.cpp\n*\n* @brief Management of sparse design matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-04-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"gnss/gnssNormalEquationInfo.h\"\n#include \"gnssDesignMatrix.h\"\n\n/***********************************************/\n\nGnssDesignMatrix::GnssDesignMatrix(const GnssNormalEquationInfo &normalEquationInfo_, UInt rows_) :\n      normalEquationInfo(normalEquationInfo_),\n      blockIndices(normalEquationInfo.blockIndices()),\n      indexUsedParameter(normalEquationInfo.blockCount()),\n      countUsedParameter(normalEquationInfo.blockCount()),\n      row(0),\n      rows(rows_),\n      A(rows_, normalEquationInfo.parameterCount())\n{\n}\n\n/***********************************************/\n\nvoid GnssDesignMatrix::init(UInt rows_)\n{\n  try\n  {\n    if(A.rows() < rows_)\n      A = Matrix(rows_, blockIndices.back());\n    row  = 0;\n    rows = rows_;\n\n    for(UInt i : indexUsedBlock)\n    {\n      for(UInt k=0; k<indexUsedParameter[i].size(); k++)\n        A.column(blockIndices[i]+indexUsedParameter[i][k], countUsedParameter[i][k]).setNull();\n      indexUsedParameter[i].clear();\n      countUsedParameter[i].clear();\n    }\n\n    indexUsedBlock.clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssDesignMatrix &GnssDesignMatrix::selectRows(UInt row_, UInt rows_)\n{\n  try\n  {\n    row  = row_;\n    rows = rows_;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSlice GnssDesignMatrix::column(const GnssParameterIndex &index)\n{\n  try\n  {\n    const UInt block = normalEquationInfo.block(index);\n    const UInt col   = normalEquationInfo.index(index) - normalEquationInfo.blockIndex(block);\n    const UInt cols  = normalEquationInfo.count(index);\n    return column(block, col, cols);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSlice GnssDesignMatrix::column(UInt block, UInt col, UInt cols)\n{\n  try\n  {\n    const auto iter = std::lower_bound(indexUsedBlock.begin(), indexUsedBlock.end(), block);\n    if(iter == indexUsedBlock.end() || block < *iter)\n      indexUsedBlock.insert(iter, block);\n\n    constexpr UInt gap = 32;\n    UInt idx = 0;\n    while((idx < indexUsedParameter[block].size()) && (indexUsedParameter[block][idx]+countUsedParameter[block][idx]+gap < col))\n      idx++;\n    if((idx >= indexUsedParameter[block].size()) || (col+cols+gap < indexUsedParameter[block][idx]))\n    {\n      indexUsedParameter[block].insert(indexUsedParameter[block].begin()+idx, col);\n      countUsedParameter[block].insert(countUsedParameter[block].begin()+idx, cols);\n    }\n    else // merge\n    {\n      const UInt end = std::max(col+cols, indexUsedParameter[block][idx]+countUsedParameter[block][idx]);\n      indexUsedParameter[block][idx] = std::min(col, indexUsedParameter[block][idx]);\n      countUsedParameter[block][idx] = end - indexUsedParameter[block][idx];\n      // merge with following parameter group?\n      while((idx+1 < indexUsedParameter[block].size()) && (indexUsedParameter[block][idx]+countUsedParameter[block][idx]+gap >= indexUsedParameter[block][idx+1]))\n      {\n        countUsedParameter[block][idx] = std::max(countUsedParameter[block][idx], indexUsedParameter[block][idx+1]+countUsedParameter[block][idx+1]-indexUsedParameter[block][idx]);\n        indexUsedParameter[block].erase(indexUsedParameter[block].begin()+idx+1);\n        countUsedParameter[block].erase(countUsedParameter[block].begin()+idx+1);\n      }\n    }\n\n    return A.slice(row, blockIndices[block]+col, rows, cols);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GnssDesignMatrix::mult(const_MatrixSliceRef x)\n{\n  try\n  {\n    Matrix y(rows, x.columns());\n\n    for(UInt block : indexUsedBlock)\n      for(UInt k=0; k<indexUsedParameter[block].size(); k++)\n      {\n        const UInt index = blockIndices[block]+indexUsedParameter[block][k];\n        const UInt count = countUsedParameter[block][k];\n        matMult(1., A.slice(row, index, rows, count), x.row(index, count), y);\n      }\n\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GnssDesignMatrix::mult(const std::vector<Matrix> &x, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    Matrix y(rows, x.at(startBlock).columns());\n    for(UInt block : indexUsedBlock)\n      if((startBlock <= block) && (block < startBlock+countBlock))\n        for(UInt k=0; k<indexUsedParameter[block].size(); k++)\n        {\n          const UInt index = blockIndices[block]+indexUsedParameter[block][k];\n          const UInt count = countUsedParameter[block][k];\n          matMult(1., A.slice(row, index, rows, count), x.at(block).row(indexUsedParameter[block][k], count), y);\n        }\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssDesignMatrix::transMult(const_MatrixSliceRef l, std::vector<Matrix> &x, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    for(UInt block : indexUsedBlock)\n      if((startBlock <= block) && (block < startBlock+countBlock))\n        for(UInt k=0; k<indexUsedParameter[block].size(); k++)\n        {\n          const UInt index = blockIndices[block]+indexUsedParameter[block][k];\n          const UInt count = countUsedParameter[block][k];\n          matMult(1., A.slice(row, index, rows, count).trans(), l, x.at(block).row(indexUsedParameter[block][k], count));\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssDesignMatrix::accumulateNormals(const GnssDesignMatrix &A, const_MatrixSliceRef l, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount)\n{\n  try\n  {\n    for(UInt ii=0; ii<A.indexUsedBlock.size(); ii++)\n    {\n      const UInt blocki = A.indexUsedBlock[ii];\n      normals.setBlock(blocki, blocki);\n      if(!normals.N(blocki, blocki).size())\n        normals.N(blocki, blocki) = Matrix(normals.blockSize(blocki), Matrix::SYMMETRIC);\n\n      for(UInt kk=ii+1; kk<A.indexUsedBlock.size(); kk++)\n      {\n        const UInt blockk = A.indexUsedBlock[kk];\n        normals.setBlock(blocki, blockk);\n        if(!normals.N(blocki, blockk).size())\n          normals.N(blocki, blockk) = Matrix(normals.blockSize(blocki), normals.blockSize(blockk));\n      }\n\n      for(UInt i=0; i<A.indexUsedParameter[blocki].size(); i++)\n      {\n        const UInt index = A.indexUsedParameter[blocki][i];\n        const UInt count = A.countUsedParameter[blocki][i];\n        const const_MatrixSlice Ai(A.A.slice(A.row, A.blockIndices[blocki]+index, A.rows, count).trans());\n\n        // right hand side\n        matMult(1., Ai, l, n.at(blocki).row(index, count));\n\n        // diagonal block\n        rankKUpdate(1., Ai.trans(), normals.N(blocki, blocki).slice(index, index, count, count));\n        for(UInt k=i+1; k<A.indexUsedParameter[blocki].size(); k++)\n          matMult(1., Ai, A.A.slice(A.row, A.blockIndices[blocki]+A.indexUsedParameter[blocki][k], A.rows, A.countUsedParameter[blocki][k]),\n                  normals.N(blocki, blocki).slice(index, A.indexUsedParameter[blocki][k], count, A.countUsedParameter[blocki][k]));\n\n        // other blocks\n        for(UInt kk=ii+1; kk<A.indexUsedBlock.size(); kk++)\n        {\n          const UInt blockk = A.indexUsedBlock[kk];\n          for(UInt k=0; k<A.indexUsedParameter[blockk].size(); k++)\n            matMult(1., Ai, A.A.slice(A.row, A.blockIndices[blockk]+A.indexUsedParameter[blockk][k], A.rows, A.countUsedParameter[blockk][k]),\n                    normals.N(blocki, blockk).slice(index, A.indexUsedParameter[blockk][k], count, A.countUsedParameter[blockk][k]));\n        }\n      }\n    }\n\n    // accumulate right hand side\n    obsCount += l.rows();\n    lPl      += quadsum(l);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssDesignMatrix::axpy(const std::vector<UInt> &rowInA, const std::vector<Double> &factors, const GnssDesignMatrix &B, GnssDesignMatrix &A)\n{\n  try\n  {\n    UInt idxUsedBlock = 0;\n    for(UInt block : B.indexUsedBlock)\n    {\n      while((idxUsedBlock < A.indexUsedBlock.size()) && (A.indexUsedBlock[idxUsedBlock] < block))\n        idxUsedBlock++;\n      if((idxUsedBlock >= A.indexUsedBlock.size()) || block < A.indexUsedBlock[idxUsedBlock])\n        A.indexUsedBlock.insert(A.indexUsedBlock.begin()+idxUsedBlock, block);\n\n      UInt idx = 0;\n      for(UInt k=0; k<B.indexUsedParameter[block].size(); k++)\n      {\n        const UInt col  = B.indexUsedParameter[block][k];\n        const UInt cols = B.countUsedParameter[block][k];\n        {\n          while((idx < A.indexUsedParameter[block].size()) && (A.indexUsedParameter[block][idx]+A.countUsedParameter[block][idx] < col))\n            idx++;\n          if((idx >= A.indexUsedParameter[block].size()) || (col+cols < A.indexUsedParameter[block][idx])) // new block\n          {\n            A.indexUsedParameter[block].insert(A.indexUsedParameter[block].begin()+idx, col);\n            A.countUsedParameter[block].insert(A.countUsedParameter[block].begin()+idx, cols);\n          }\n          else if((A.indexUsedParameter[block][idx] != col) || (A.countUsedParameter[block][idx] != cols)) // merge\n          {\n            const UInt end = std::max(col+cols, A.indexUsedParameter[block][idx]+A.countUsedParameter[block][idx]);\n            A.indexUsedParameter[block][idx] = std::min(col, A.indexUsedParameter[block][idx]);\n            A.countUsedParameter[block][idx] = end - A.indexUsedParameter[block][idx];\n            // merge with following parameter group?\n            while((idx+1 < A.indexUsedParameter[block].size()) && (A.indexUsedParameter[block][idx]+A.countUsedParameter[block][idx] >= A.indexUsedParameter[block][idx+1]))\n            {\n              A.countUsedParameter[block][idx] = std::max(A.countUsedParameter[block][idx], A.indexUsedParameter[block][idx+1]+A.countUsedParameter[block][idx+1]-A.indexUsedParameter[block][idx]);\n              A.indexUsedParameter[block].erase(A.indexUsedParameter[block].begin()+idx+1);\n              A.countUsedParameter[block].erase(A.countUsedParameter[block].begin()+idx+1);\n            }\n          }\n        }\n        MatrixSlice       As(A.A.slice(A.row, A.blockIndices[block]+col, A.rows, cols));\n        const_MatrixSlice Bs(B.A.slice(B.row, B.blockIndices[block]+col, B.rows, cols));\n        for(UInt i=0; i<rowInA.size(); i++)\n          if(rowInA.at(i) != NULLINDEX)\n            ::axpy(factors.at(i), Bs.row(i), As.row(rowInA.at(i)));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssDesignMatrix.h",
    "content": "/***********************************************/\n/**\n* @file gnssDesignMatrix.h\n*\n* @brief Management of sparse design matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-04-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSDESIGNMATRIX__\n#define __GROOPS_GNSSDESIGNMATRIX__\n\n#include \"parallel/matrixDistributed.h\"\n#include \"gnss/gnssNormalEquationInfo.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Management of sparse design matrix. */\nclass GnssDesignMatrix\n{\n  const GnssNormalEquationInfo  &normalEquationInfo;\n  std::vector<UInt>              blockIndices;\n  std::vector<UInt>              indexUsedBlock;\n  std::vector<std::vector<UInt>> indexUsedParameter;\n  std::vector<std::vector<UInt>> countUsedParameter;\n  UInt                           row, rows;\n  Matrix                         A;\n\npublic:\n  GnssDesignMatrix(const GnssNormalEquationInfo &normalEquationInfo, UInt rows=0);\n ~GnssDesignMatrix() {}\n\n  void              init(UInt rows);\n  GnssDesignMatrix &selectRows(UInt row, UInt rows);\n  MatrixSlice       column(const GnssParameterIndex &index);\n  MatrixSlice       column(UInt block, UInt col, UInt cols);\n  Matrix            mult(const_MatrixSliceRef x);\n  Matrix            mult(const std::vector<Matrix> &x, UInt startBlock, UInt countBlock);\n  void              transMult(const_MatrixSliceRef l, std::vector<Matrix> &x, UInt startBlock, UInt countBlock);\n  static void       accumulateNormals(const GnssDesignMatrix &A, const_MatrixSliceRef l, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount);\n  static void       axpy(const std::vector<UInt> &rowInA, const std::vector<Double> &factors, const GnssDesignMatrix &B, GnssDesignMatrix &A);\n};\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssLambda.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssLambda.cpp\n*\n* @brief LAMBDA - Least-squares AMBiguity Decorrelation Adjustment.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-06-24\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"gnssLambda.h\"\n\n/***********************************************/\n\nMatrix GnssLambda::phaseDecorrelation(const std::vector<GnssType> &types, Double wavelengthFactor, Double weightRange)\n{\n  try\n  {\n    if(types.size() == 0)\n      return Matrix();\n    if(types.size() == 1)\n      return Matrix(1, 1, wavelengthFactor*types.at(0).wavelength());\n\n    // design matrix\n    // assume for every phase observation an additional range observation\n    // parameters: range, TEC, ambiguities\n    const UInt dim = types.size();\n    Matrix A(2*dim+1, 2+dim);\n    for(UInt i=0; i<dim; i++)\n    {\n      // phase observations:\n      A(i, 0)   = 1.;                                        // range\n      A(i, 1)   = types.at(i).ionosphericFactor();           // TEC\n      A(i, 2+i) = wavelengthFactor*types.at(i).wavelength(); // ambiguity\n      // range observations (100 times less accurate):\n      A(i+dim, 0) = 1./100.;       // range\n      A(i+dim, 1) = -A(i, 1)/100.; // TEC\n    }\n    A(2*dim, 0) = weightRange; // range is determined by geometry\n\n    // solve & decorrelate\n    QR_decomposition(A);\n    inverse(A.slice(2, 2, dim, dim));\n    Transformation Z(dim);\n    choleskyTransform(A.slice(2, 2, dim, dim), Z, FALSE/*timing*/);\n\n    // Transformation matrix cycles -> meter\n    Matrix T = Z.transformBack(identityMatrix(types.size()));\n    for(UInt idType=0; idType<types.size(); idType++)\n      T.row(idType) *= wavelengthFactor*types.at(idType).wavelength();\n\n    return T;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt GnssLambda::choleskyReversePivot(Matrix &N, Transformation &Z, UInt index0Z, Double tolerance, Bool timing)\n{\n  try\n  {\n    UInt rank = N.rows();\n    const UInt blockSize = 64;\n    Log::Timer timer(N.rows(), 1, timing);\n    for(UInt block=0; block<N.rows(); block+=blockSize)\n    {\n      const UInt blockEnd = std::min(block+blockSize, N.rows());\n      Vector tmp(N.rows());\n      for(UInt i=block; i<blockEnd; i++)\n      {\n        timer.loopStep(i);\n\n        // find minimium\n        UInt   k    = NULLINDEX;\n        Double minN = std::numeric_limits<Double>::infinity();\n        for(UInt j=i; j<N.rows(); j++)\n          if((N(j, j)-tmp(j) < minN) && (N(j, j)-tmp(j) > tolerance))\n          {\n            k    = j;\n            minN = N(k, k)-tmp(k);\n          }\n        if(k == NULLINDEX) {rank = i; break;} // rank deficit\n        // swap\n        if(i != k)\n        {\n          Z.swap(index0Z+i, index0Z+k);\n          std::swap(tmp(i), tmp(k));\n          std::swap(N(i,i), N(k,k));\n          if(i>0)          swap(N.slice(0, i,i, 1),               N.slice(0,   k,   i,     1));\n          if(k<N.rows()-1) swap(N.slice(i, k+1, 1, N.rows()-k-1), N.slice(k,   k+1, 1,     N.rows()-k-1));\n          if(k>i+1)        swap(N.slice(i, i+1, 1, k-i-1),        N.slice(i+1, k,   k-i-1, 1).trans());\n        }\n        // cholesky\n        N(i, i) -= tmp(i);\n        N(i, i)  = std::sqrt(N(i, i));\n        if(i > block)\n          matMult(-1., N.slice(block, i, i-block, 1).trans(), N.slice(block, i+1, i-block, N.rows()-1-i),\n                  N.slice(i, i+1, 1, N.rows()-1-i));\n        N.slice(i, i+1, 1, N.rows()-1-i) *= 1./N(i, i);\n        for(UInt k=i+1; k<N.rows(); k++)\n          tmp(k) += std::pow(N(i, k), 2);\n      }\n      if(rank != N.rows())\n        break;\n      if(blockEnd < N.rows())\n        rankKUpdate(-1., N.slice(block, blockEnd, blockEnd-block, N.rows()-blockEnd),\n                    N.slice(blockEnd, blockEnd, N.rows()-blockEnd, N.rows()-blockEnd));\n    }\n    timer.loopEnd();\n    N.setType(Matrix::TRIANGULAR);\n    return rank;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// reduce element (i, k) (reduce row k from i)\ninline Bool GnssLambda::choleskyReduce(UInt i, UInt k, MatrixSliceRef W, Transformation &Z)\n{\n  try\n  {\n    const Double alpha = std::round(W(i,k));\n    if(alpha == 0.)\n      return FALSE;\n    axpy(-alpha, W.slice(k,k,1,W.rows()-k), W.slice(i,k,1,W.rows()-k));\n    Z.reduce(alpha, k, i);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector GnssLambda::choleskyTransform(MatrixSliceRef W, Transformation &Z, Bool timing)\n{\n  try\n  {\n    const UInt dim = W.rows();\n\n    // Covariance = W D W^T\n    // D: diagonal matrix, W: upper triangular\n    std::vector<Double> d(dim);\n    for(UInt i=0; i<dim; i++)\n      d[i] = W(i,i)*W(i,i);\n    for(UInt i=0; i<dim; i++)\n      W.column(i) *= 1./W(i,i);\n\n    // decorrelate\n    for(UInt i=dim; i-->0;)\n      for(UInt k=i+1; k<dim; k++)\n        choleskyReduce(i, k, W, Z);\n\n    std::vector<Double> delta(dim-1);\n    for(UInt i=0; i<dim-1; i++)\n      delta[i] = d[i] + std::pow(W(i,i+1), 2) * d[i+1];\n\n    std::multimap<Double, UInt> ratio;\n    for(UInt i=0; i<dim-1; i++)\n      if(delta[i] < d[i+1])\n        ratio.insert(std::make_pair(delta[i]/d[i+1], i));\n\n    Log::Timer timer(1, 1, timing);\n    UInt iter = 0;\n    while(!ratio.empty())\n    {\n      timer.loopStep(iter);\n      iter++;\n\n      // find maximum change\n      const UInt k = ratio.begin()->second;\n\n      // erase ratios that will be changed\n      ratio.erase(ratio.begin());\n      if((k > 0) && (delta[k-1] < d[k]))\n      {\n        auto iterpair = ratio.equal_range(delta[k-1]/d[k]);\n        ratio.erase(std::find_if(iterpair.first, iterpair.second, [k](const std::pair<Double, UInt> &x){return x.second == k-1;}));\n      }\n      if((k+1 < dim-1) && (delta[k+1] < d[k+2]))\n      {\n        auto iterpair = ratio.equal_range(delta[k+1]/d[k+2]);\n        ratio.erase(std::find_if(iterpair.first, iterpair.second, [k](const std::pair<Double, UInt> &x){return x.second == k+1;}));\n      }\n\n      // swap k and k+1\n      const Double eta    = d[k]/delta[k];\n      const Double lambda = d[k+1]*W(k,k+1)/delta[k];\n      d[k]   = eta*d[k+1];\n      d[k+1] = delta[k];\n\n      if(k>0)\n        copy(W.slice(0,k,k,2)*Matrix({{-W(k,k+1),  eta}, {1., lambda}}), W.slice(0,k,k,2)); // upper columns\n      W(k,k+1) = lambda;\n      if(k+2<W.rows())\n        swap(W.slice(k,k+2,1,dim-2-k), W.slice(k+1,k+2,1,dim-2-k)); // swap row k and k+1\n      Z.swap(k, k+1); // store applied transformation\n\n      // decorrelate, update delta and ratio\n      for(UInt i=std::min(k+2,dim-1); i-->std::max(k,UInt(1))-1;)\n      {\n        // mathematically only choleskyReduce(i, i+1, W, Z) is needed\n        if(choleskyReduce(i, i+1, W, Z))\n          for(UInt k=i+2; k<dim; k++)\n            choleskyReduce(i, k, W, Z);\n        delta[i] = d[i] + std::pow(W(i,i+1), 2) * d[i+1];\n        if(delta[i] < d[i+1])\n          ratio.insert(std::make_pair(delta[i]/d[i+1], i));\n      }\n    }\n    timer.loopEnd();\n\n    // decorrelate rest of the triangle\n    for(UInt i=dim; i-->0;)\n      for(UInt k=i+1; k<dim; k++)\n        choleskyReduce(i, k, W, Z);\n\n    return d;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssLambda::searchInteger(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d,\n                               UInt maxSearchSteps, Vector &solution, Double &minNorm)\n{\n  try\n  {\n    const UInt dim = W.rows();\n    std::vector<Double> xInt(dim, 0);\n    std::vector<Double> norm(dim, 0);\n    std::vector<Double> step(dim, 0);\n    std::vector<Double> dx  (dim, 0);\n\n    // store xBar in lower triangle of W\n    // xBar vector of step i starts at W(dim-1-i, dim-1-i), reverse order\n    MatrixSlice xBar(W);\n    copy(xFloat, xBar.column(0));\n\n    UInt i  = dim-1;\n    xInt[i] = std::round(xBar(dim-1, dim-1-i));\n    dx[i]   = xInt[i] - xBar(dim-1, dim-1-i);\n    step[i] = (dx[i] < 0) ? 1 : -1;\n    minNorm = 1e99;\n    Double newNorm = dx[i]*dx[i]/d(i,0);\n\n    UInt iter=0;\n    for(; iter<maxSearchSteps; iter++)\n    {\n      // move down\n      const UInt lastValidXBar = i;\n      while((newNorm < minNorm) && (i-- > 0))\n      {\n        // compute new xBar\n        for(UInt k=lastValidXBar; k-->i;)\n          xBar(i+dim-1-k, dim-1-k) = xBar(i+dim-2-k, dim-2-k) + dx[k+1] * W(i,k+1);\n\n        xInt[i]  = std::round(xBar(dim-1, dim-1-i));\n        dx[i]    = xInt[i] - xBar(dim-1, dim-1-i);\n        step[i]  = (dx[i] < 0) ? 1 : -1;\n        norm[i]  = newNorm;\n        newNorm += dx[i]*dx[i]/d(i,0);\n      }\n\n      // new solution?\n      if(newNorm < minNorm)\n      {\n        i = 0;\n        solution = Vector(xInt);\n        minNorm  = newNorm;\n        newNorm  = 2e99;\n      }\n\n      // move up\n      while((newNorm >= minNorm) && (i++ < dim-1))\n      {\n        xInt[i] += step[i];\n        dx[i]   += step[i];\n        step[i]  = (step[i]>0) ? (-step[i]-1) : (-step[i]+1); // zig-zag search\n        newNorm  = norm[i] + dx[i]*dx[i]/d(i,0);\n      }\n\n      if(newNorm >= minNorm)\n        break;\n    } // for(iter)\n\n    // restore diagonal\n    for(UInt i=0; i<dim; i++)\n      W(i,i) = 1.;\n\n    return (iter < maxSearchSteps);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector GnssLambda::searchIntegerBlocked(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d,\n                                      Double sigmaMaxResolve, UInt searchBlockSize, UInt maxSearchSteps, IncompleteAction incompleteAction, Bool timing,\n                                      Vector &isNotFixed, Double &sigma, Matrix &solutionSteps)\n{\n  try\n  {\n    const UInt dim = W.rows();\n    Vector xInt(dim);\n    isNotFixed     = Vector(dim, 1.);\n    solutionSteps  = Matrix();\n    sigma          = 0.;\n\n    // find values to be solved\n    UInt minIndex = dim;\n    while((minIndex>0) && (d(minIndex-1,0) < sigmaMaxResolve*sigmaMaxResolve))\n      minIndex--;\n    if(minIndex >= dim)\n      return xInt;\n    UInt idxSolved = dim;\n\n    // float solution\n    std::vector<Vector> solutions(1, d);\n    auto storeSolution = [&](Vector xBar, UInt idxSolved)\n    {\n      for(UInt i=dim; i-->idxSolved;)\n        axpy(-xBar(i), W.slice(0,i,i,1), xBar.row(0,i));\n      for(UInt i=0; i<idxSolved; i++)\n        xBar(i) = std::fabs(std::remainder(xBar(i), 1));\n      for(UInt i=idxSolved; i<dim; i++)\n        xBar(i) = -std::fabs(xBar(i));\n      solutions.push_back(xBar);\n    };\n    storeSolution(xFloat, idxSolved);\n\n    UInt defaultBlockSize = std::min(dim-minIndex, searchBlockSize);\n    UInt blockSize     = defaultBlockSize;\n    UInt blockStart    = dim-blockSize;\n    UInt blockStartOld = dim;\n    UInt iter=0;\n    Log::Timer timer((dim-minIndex)/(defaultBlockSize/2), 1, timing);\n    for(;;)\n    {\n      timer.loopStep(iter++);\n\n      // compute xBar for found solution so far\n      Vector xBar = xFloat-xInt;\n      for(UInt i=dim; i-->blockStart+blockSize;)\n        axpy(-xBar(i), W.slice(0,i,i,1), xBar.row(0,i));\n\n      Vector dxInt;\n      Double ePe;\n      Bool completed = searchInteger(xBar.row(blockStart, blockSize),\n                                     W.slice(blockStart, blockStart, blockSize, blockSize),\n                                     d.row(blockStart, blockSize), maxSearchSteps, dxInt, ePe);\n      axpy(1., dxInt, xInt.row(blockStart, blockSize));\n      copy(Vector(blockSize, 0), isNotFixed.row(blockStart, blockSize));\n      idxSolved = blockStart;\n\n      if(!completed)\n      {\n        if(incompleteAction == IncompleteAction::STOP)\n        {\n          if(timing) logWarning<<\"searchInteger(\"<<dim<<\").slice(\"<<blockStart<<\", \"<<blockSize<<\"): cannot find a solution -> stop searching\"<<Log::endl;\n          idxSolved = blockStart+blockSize;\n          break;\n        }\n        else if(incompleteAction == IncompleteAction::SHRINKBLOCKSIZE)\n        {\n          if(timing) logWarning<<\"searchInteger(\"<<dim<<\").slice(\"<<blockStart<<\", \"<<blockSize<<\"): cannot find a solution -> restart with smaller block size\"<<Log::endl;\n          defaultBlockSize = (defaultBlockSize+1)/2;\n          blockStart = std::min(blockStartOld, blockStart+(blockSize+1)/2);\n          blockSize -= (blockSize+1)/2;\n          iter--;\n          continue;\n        }\n        else if(incompleteAction == IncompleteAction::EXCEPTION)\n        {\n          throw(Exception(\"Ambiguity resolution failed.\"));\n        }\n        // incompleteAction == IncompleteAction::IGNORE)\n      }\n\n      storeSolution(xFloat-xInt, idxSolved);\n\n      // check consistence with solution of old block, if not restart with larger block\n      if(quadsum(dxInt.row(blockStartOld-blockStart, blockStart+blockSize-blockStartOld)))\n      {\n        if(timing) logWarning<<\"searchInteger(\"<<dim<<\").slice(\"<<blockStart<<\", \"<<blockSize<<\"): not consistent -> restart\"<<Log::endl;\n        blockStartOld = blockStart+blockSize;\n        blockSize    += std::min(defaultBlockSize/2, dim-blockStart-blockSize);\n        iter--;\n        continue;\n      }\n\n      blockStartOld = blockStart;\n      blockSize     = defaultBlockSize;\n      if(blockStart == minIndex) // at beginning?\n        break;\n      blockStart = std::max(blockStart, minIndex+defaultBlockSize/2) - defaultBlockSize/2;\n    } // for(blocks)\n    timer.loopEnd();\n\n    xInt.row(0, idxSolved).fill(0);\n    isNotFixed.row(0, idxSolved).fill(1);\n\n    // compute norm\n    Vector xBar = xFloat - xInt;\n    triangularSolve(1., W, xBar);\n    sigma = 0;\n    for(UInt i=idxSolved; i<dim; i++)\n      sigma += xBar(i)*xBar(i)/d(i,0);\n    sigma = std::sqrt(sigma/(dim-idxSolved));\n\n    // copy solutions into one matrix\n    solutionSteps = Matrix(dim, solutions.size());\n    for(UInt i=0; i<solutions.size(); i++)\n      copy(solutions.at(i), solutionSteps.column(i));\n\n    return xInt;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGnssLambda::Transformation::Transformation(UInt dim) : columnForward(dim), columnBackward(dim)\n{\n  try\n  {\n    // unity matrix in both directions\n    for(UInt i=0; i<dim; i++)\n    {\n      columnForward[i].insert (std::make_pair(i, 1.0));\n      columnBackward[i].insert(std::make_pair(i, 1.0));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// row(k) -= alpha * row(i)\ninline void GnssLambda::Transformation::reduce(Double alpha, UInt i, UInt k)\n{\n  try\n  {\n    if(alpha == 0.)\n      return;\n\n    // --- lambda ---\n    auto reduce = [](Double alpha, std::map<UInt, Double> &column1, std::map<UInt, Double> &column2)\n    {\n      for(auto &col : column1)\n      {\n        auto element = column2.find(col.first);\n        if(element != column2.end())\n        {\n          element->second -= alpha * col.second;\n          if(std::fabs(element->second) < 1e-9)\n            column2.erase(element);\n        }\n        else\n          column2.insert(std::make_pair(col.first, -alpha * col.second));\n      }\n    };\n    // -----------\n\n    reduce(+alpha, columnForward[i],  columnForward[k]);\n    reduce(-alpha, columnBackward[k], columnBackward[i]);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssLambda::Transformation::swap(UInt i, UInt k)\n{\n  std::swap(columnForward.at(i),  columnForward.at(k));\n  std::swap(columnBackward.at(i), columnBackward.at(k));\n}\n\n/***********************************************/\n\nMatrix GnssLambda::Transformation::transform(const_MatrixSliceRef x) const\n{\n  try\n  {\n    if(x.rows() != columnForward.size())\n      throw(Exception(\"Dimension error\"));\n\n    Matrix y(x.rows(), x.columns());\n    for(UInt i=0; i<columnForward.size(); i++)\n      for(const auto &col : columnForward[i])\n        axpy(col.second, x.row(col.first), y.row(i));\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GnssLambda::Transformation::transformBack(const_MatrixSliceRef x) const\n{\n  try\n  {\n    Matrix y(x.rows(), x.columns());\n    for(UInt i=0; i<columnBackward.size(); i++)\n      for(const auto &col : columnBackward[i])\n        axpy(col.second, x.row(i), y.row(col.first));\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GnssLambda::Transformation::distributeBack(const_MatrixSliceRef x) const\n{\n  try\n  {\n    Matrix y(x.rows(), x.columns());\n    for(UInt i=0; i<columnBackward.size(); i++)\n      for(UInt k=0; k<x.columns(); k++)\n        if(x(i, k))\n          for(const auto &col : columnBackward[i])\n            y(col.first, k) = 1.;\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssLambda.h",
    "content": "/***********************************************/\n/**\n* @file gnssLambda.h\n*\n* @brief LAMBDA - Least-squares AMBiguity Decorrelation Adjustment.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-06-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSLAMBDA__\n#define __GROOPS_GNSSLAMBDA__\n\n/***********************************************/\n\n#include <map>\n#include \"base/import.h\"\n#include \"base/gnssType.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief LAMBDA - Least-squares AMBiguity Decorrelation Adjustment.\n* @ingroup gnssGroup */\nnamespace GnssLambda\n{\n  /** @brief Sparse transformation matrix.\n  * In both directions: direct and back.\n  * Created by elementary transformations (swap and reduce) */\n  class Transformation\n  {\n    std::vector<std::map<UInt, Double>> columnForward, columnBackward; // for each row a column with a factor\n\n  public:\n    Transformation(UInt dim=0);\n   ~Transformation() {}\n\n    void reduce(Double alpha, UInt i, UInt k); // row(k) -= alpha * row(i)\n    void swap(UInt i, UInt k);\n\n    Matrix transform(const_MatrixSliceRef x) const;\n    Matrix transformBack(const_MatrixSliceRef x)  const;\n    Matrix distributeBack(const_MatrixSliceRef x) const;\n  };\n\n  // ======================\n\n  enum class IncompleteAction {STOP, SHRINKBLOCKSIZE, IGNORE, EXCEPTION};\n\n  /** @brief Decorrelate ambiguities (Melbourne Wuebbena like linear combinations).\n  * @param types list of phase observations.\n  * @param wavelengthFactor 0.5 for old receivers using squaring technology.\n  * @param weightRange weight of range obersvation (relative ro phase observation).\n  * @return Transformation matrix from decorrelated ambiguities to phase observations [cycles]->[m]. */\n  Matrix phaseDecorrelation(const std::vector<GnssType> &types, Double wavelengthFactor, Double weightRange=0.0);\n\n  // LAMBDA method\n  UInt   choleskyReversePivot(Matrix &N, Transformation &Z, UInt index0Z, Double tolerance, Bool timing);\n  Bool   choleskyReduce(UInt i, UInt k, MatrixSliceRef W, Transformation &transformation);\n  Vector choleskyTransform(MatrixSliceRef W, Transformation &transformation, Bool timing);\n  Bool   searchInteger(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, UInt maxSearchSteps, Vector &solution, Double &minNorm);\n  Vector searchIntegerBlocked(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d,\n                              Double sigmaMaxResolve, UInt searchBlockSize, UInt maxSearchSteps, IncompleteAction incompleteAction, Bool timing,\n                              Vector &isNotFixed, Double &sigma, Matrix &solutionSteps);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssNormalEquationInfo.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssNormalEquationInfo.cpp\n*\n* @brief GNSS normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-08-03\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"base/parameterName.h\"\n#include \"gnssNormalEquationInfo.h\"\n\n/***********************************************/\n\nGnssNormalEquationInfo::GnssNormalEquationInfo(UInt countEpoch, UInt countReceiver, UInt /*countTransmitter*/, Parallel::CommunicatorPtr comm_) :\n    comm(comm_),\n    isEachReceiverSeparately(FALSE),\n    estimateReceiver(countReceiver, TRUE),\n    idEpochs(countEpoch),\n    defaultBlockSizeEpoch(0),\n    defaultBlockSizeInterval(64),\n    defaultBlockSizeAmbiguity(64),\n    defaultBlockReceiverCount(0),\n    defaultBlockCountReduction(32),\n    keepEpochNormalsInMemory(TRUE),\n    accumulateEpochObservations(FALSE),\n    blockCountEpoch_(countEpoch, 0)\n{\n  std::iota(idEpochs.begin(), idEpochs.end(), 0);\n}\n\n/***********************************************/\n\nvoid GnssNormalEquationInfo::initNewParameterNames()\n{\n  try\n  {\n    parameters.clear();\n    block_.clear();\n    index_.clear();\n    count_.clear();\n    parameterNames_.clear();\n    blockIndices_.clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParameterIndex GnssNormalEquationInfo::addParameters(UInt idEpoch, UInt idRecv, UInt idTrans, const std::vector<ParameterName> &parameterNames)\n{\n  if(!parameterNames.size())\n    return GnssParameterIndex(NULLINDEX);\n  const UInt idx = parameters.size();\n  parameters.push_back(Parameter{idEpoch, idRecv, idTrans, NULLINDEX, idx, parameterNames});\n  return GnssParameterIndex(parameters.back().idx);\n}\n\n/***********************************************/\n\nvoid GnssNormalEquationInfo::calculateIndex(const Vector &recvProcess)\n{\n  try\n  {\n    // ------------------\n    auto newBlock = [&]()\n    {\n      const UInt parameterCount = this->parameterCount();\n      if(blockSize(blockCount()-1))\n      {\n        blockIndices_.push_back(parameterCount);\n        blockRank_.push_back(NULLINDEX);\n      }\n    };\n    // ------------------\n\n    // ------------------\n    auto insert = [&](auto iter, UInt defaultBlockSize)\n    {\n      if((defaultBlockSize > 0) && (blockSize(blockCount()-1) >= defaultBlockSize))\n        newBlock();\n      const UInt idx   = iter->idx;\n      index_.at(idx)   = blockIndices_.back();\n      block_.at(idx)   = blockCount()-1;\n      count_.at(idx)   = iter->names.size();\n      parameterNames_.insert(parameterNames_.end(), iter->names.begin(), iter->names.end());\n      blockIndices_.back() += iter->names.size();\n      blockRank_.back() = iter->rank;\n    };\n    // ------------------\n\n    block_.resize(parameters.size(), NULLINDEX);\n    index_.resize(parameters.size(), NULLINDEX);\n    count_.resize(parameters.size(), 0);\n    blockIndices_ = {0, 0};\n    blockRank_    = {NULLINDEX};\n    parameterNames_.reserve(std::accumulate(parameters.begin(), parameters.end(), UInt(0), [](UInt count, const auto &p){return count+p.names.size();}));\n\n    // set process rank of receivers\n    for(auto &p : parameters)\n      if((p.idRecv != NULLINDEX) && (p.idTrans == NULLINDEX) && recvProcess(p.idRecv))\n        p.rank = recvProcess(p.idRecv)-1;\n\n    parameters.sort([](auto &p1, auto &p2)\n                    {\n                      const Bool isAmbi1 = (p1.idRecv != NULLINDEX) && (p1.idTrans != NULLINDEX);\n                      const Bool isAmbi2 = (p2.idRecv != NULLINDEX) && (p2.idTrans != NULLINDEX);\n                      if(isAmbi1 != isAmbi2) return isAmbi2;                         // ambiguities always at end\n                      if(p1.idEpoch != p2.idEpoch) return (p1.idEpoch < p2.idEpoch); // epoch\n                      if(p1.rank    != p2.rank)    return (p1.rank    < p2.rank);    // process rank\n                      if(p1.idRecv  != p2.idRecv)  return (p1.idRecv  < p2.idRecv);  // idRecv\n                      return (p1.idTrans < p2.idTrans);                              // idTrans\n                    });\n    auto iter = parameters.begin();\n\n    // epoch parameters\n    std::fill(blockCountEpoch_.begin(), blockCountEpoch_.end(), 0);\n    for(UInt idEpoch : idEpochs)\n    {\n      newBlock();\n      UInt blockEpochStart = blockIndices_.size();\n      UInt idRecv = NULLINDEX;\n      UInt countStation = 0;\n      while((iter != parameters.end()) && (iter->idEpoch == idEpoch) && ((iter->idRecv == NULLINDEX) || (iter->idTrans == NULLINDEX)))\n      {\n        if(iter->idRecv != idRecv) // next receiver?\n          if(defaultBlockReceiverCount && ((iter->idRecv == NULLINDEX) || ((countStation++ % defaultBlockReceiverCount) == 0)))\n            newBlock();\n        idRecv = iter->idRecv;\n\n        insert(iter++, defaultBlockSizeEpoch);\n      }\n      blockCountEpoch_.at(idEpoch) = blockIndices_.size() - blockEpochStart + (blockSize(blockCount()-1) ? 1 : 0);\n    }\n\n    // receiver interval parameters\n    newBlock();\n    blockInterval_ = blockCount()-1;\n    UInt countStation = 0;\n    while((iter != parameters.end()) && (iter->idEpoch == NULLINDEX) && (iter->idRecv != NULLINDEX) && (iter->idTrans == NULLINDEX))\n    {\n      const UInt idRecv = iter->idRecv;\n      if(defaultBlockReceiverCount && ((countStation++ % defaultBlockReceiverCount) == 0))\n        newBlock();\n\n      Bool firstBlock = TRUE;\n      while((iter != parameters.end()) && (iter->idEpoch == NULLINDEX) && (iter->idRecv == idRecv) && (iter->idTrans == NULLINDEX))\n      {\n        insert(iter++, firstBlock ? defaultBlockSizeInterval : 0); // do not split parameters of a receiver\n        firstBlock = FALSE;\n      }\n    }\n\n    // transmitter interval parameters\n    newBlock();\n    while((iter != parameters.end()) && (iter->idEpoch == NULLINDEX) && (iter->idRecv == NULLINDEX) && (iter->idTrans != NULLINDEX))\n    {\n      const UInt idTrans = iter->idTrans;\n      Bool firstBlock = TRUE;\n      while((iter != parameters.end()) && (iter->idEpoch == NULLINDEX) && (iter->idRecv == NULLINDEX) && (iter->idTrans == idTrans))\n      {\n        insert(iter++, firstBlock ? defaultBlockSizeInterval : 0); // do not split parameters of a transmitter\n        firstBlock = FALSE;\n      }\n    }\n\n    // other interval parameters\n    newBlock();\n    while((iter != parameters.end()) && (iter->idEpoch == NULLINDEX) && (iter->idRecv == NULLINDEX) && (iter->idTrans == NULLINDEX))\n      insert(iter++, defaultBlockSizeInterval);\n\n    // ambiguity parameters\n    newBlock();\n    blockAmbiguity_ = blockCount()-1;\n    while((iter != parameters.end()) && (iter->idRecv != NULLINDEX) && (iter->idTrans != NULLINDEX))\n      insert(iter++, defaultBlockSizeAmbiguity);\n\n    // remove possible last empty block\n    if(blockCount() && !blockSize(blockCount()-1))\n      blockIndices_.pop_back();\n\n    parameters.clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt GnssNormalEquationInfo::normalsBlockRank(UInt i, UInt k, UInt commSize)\n{\n  try\n  {\n    // if(blockRank_.at(i) != NULLINDEX) return blockRank_.at(i);\n    // if(blockRank_.at(k) != NULLINDEX) return blockRank_.at(k);\n\n    // find optimal process grid (nearly quadratic)\n    UInt pRows = static_cast<UInt>(std::floor(std::sqrt(commSize)));\n    while(commSize % pRows)\n      pRows++;\n    const UInt pCols = commSize/pRows;\n\n    return (i%pRows)*pCols+(k%pCols);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssNormalEquationInfo.h",
    "content": "/***********************************************/\n/**\n* @file gnssNormalEquationInfo.h\n*\n* @brief GNSS normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-08-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSNORMALEQUATIONINFO__\n#define __GROOPS_GNSSNORMALEQUATIONINFO__\n\n#include <regex>\n#include \"parallel/parallel.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"base/parameterName.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\nclass GnssParameterIndex\n{\n  UInt index;\npublic:\n  GnssParameterIndex(UInt idx=NULLINDEX) : index(idx) {}\n  explicit operator bool() const {return index != NULLINDEX;}\n\n  friend class GnssNormalEquationInfo;\n  friend class GnssDesignMatrix;\n};\n\n/***** CLASS ***********************************/\n\nclass GnssNormalEquationInfo\n{\npublic:\n  Parallel::CommunicatorPtr comm;\n  std::vector<std::pair<std::regex, Bool>> enableParametrizations; // wildcard matching, enable/disable\n  Bool                      isEachReceiverSeparately; // only receiver parameters are allowed\n  std::vector<Byte>         estimateReceiver;         // subset of observations\n  std::vector<UInt>         idEpochs;                 // epochs to estimate\n  UInt                      defaultBlockSizeEpoch;\n  UInt                      defaultBlockSizeInterval;\n  UInt                      defaultBlockSizeAmbiguity;\n  UInt                      defaultBlockReceiverCount;\n  UInt                      defaultBlockCountReduction;\n  Bool                      keepEpochNormalsInMemory;\n  Bool                      accumulateEpochObservations;\n\n  GnssNormalEquationInfo(UInt countEpoch, UInt countReceiver, UInt countTransmitter, Parallel::CommunicatorPtr comm);\n\n  void initNewParameterNames();\n  GnssParameterIndex parameterNamesEpochReceiver   (UInt idEpoch, UInt idRecv,  const std::vector<ParameterName> &parameterNames)              {return addParameters(idEpoch,   idRecv,    NULLINDEX, parameterNames);}\n  GnssParameterIndex parameterNamesEpochTransmitter(UInt idEpoch, UInt idTrans, const std::vector<ParameterName> &parameterNames)              {return addParameters(idEpoch,   NULLINDEX, idTrans,   parameterNames);}\n  GnssParameterIndex parameterNamesEpochOther      (UInt idEpoch, const std::vector<ParameterName> &parameterNames)                            {return addParameters(idEpoch,   NULLINDEX, NULLINDEX, parameterNames);}\n  GnssParameterIndex parameterNamesReceiver        (UInt idRecv,  const std::vector<ParameterName> &parameterNames)                            {return addParameters(NULLINDEX, idRecv,    NULLINDEX, parameterNames);}\n  GnssParameterIndex parameterNamesTransmitter     (UInt idTrans, const std::vector<ParameterName> &parameterNames)                            {return addParameters(NULLINDEX, NULLINDEX, idTrans,   parameterNames);}\n  GnssParameterIndex parameterNamesOther           (const std::vector<ParameterName> &parameterNames)                                          {return addParameters(NULLINDEX, NULLINDEX, NULLINDEX, parameterNames);}\n  GnssParameterIndex parameterNamesAmbiguity       (UInt idEpoch, UInt idRecv, UInt idTrans, const std::vector<ParameterName> &parameterNames) {return addParameters(idEpoch,   idRecv,    idTrans,   parameterNames);}\n  void calculateIndex(const Vector &recvProcess);\n\n  UInt block(const GnssParameterIndex &index) const {return block_.at(index.index);}\n  UInt index(const GnssParameterIndex &index) const {return index_.at(index.index);}\n  UInt count(const GnssParameterIndex &index) const {return count_.at(index.index);}\n\n  const std::vector<ParameterName> &parameterNames() const {return parameterNames_;}\n  const std::vector<UInt>          &blockIndices()   const {return blockIndices_;}\n\n  UInt parameterCount()   const {return blockIndices_.back();}                      //!< Number of rows/columns (dimension) of distributed matrix\n  UInt blockIndex(UInt i) const {return blockIndices_.at(i);}                       //!< Start index of block @a i\n  UInt blockSize(UInt i)  const {return blockIndices_.at(i+1)-blockIndices_.at(i);} //!< Size of block @a i\n  UInt blockCount()       const {return blockIndices_.size()-1;}                    //!< Number of block rows/columns\n\n  UInt blockCountEpoch(UInt idEpoch) const {return blockCountEpoch_.at(idEpoch);}\n  UInt blockInterval()  const {return blockInterval_;}\n  UInt blockAmbiguity() const {return blockAmbiguity_;}\n\n  UInt normalsBlockRank(UInt i, UInt k, UInt commSize);\n\nprivate:\n  class Parameter\n  {\n  public:\n    UInt idEpoch, idRecv, idTrans, rank, idx;\n    std::vector<ParameterName> names;\n  };\n\n  std::list<Parameter>       parameters;\n  std::vector<UInt>          block_, index_, count_;  // for each parameter index\n  std::vector<ParameterName> parameterNames_;\n  std::vector<UInt>          blockIndices_;           // for each block\n  std::vector<UInt>          blockRank_;              // for each block\n  std::vector<UInt>          blockCountEpoch_;        // for each epoch\n  UInt                       blockInterval_, blockAmbiguity_;\n\n  GnssParameterIndex addParameters(UInt idEpoch, UInt idRecv, UInt idTrans, const std::vector<ParameterName> &parameterNames);\n};\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssObservation.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssObservation.cpp\n*\n* @brief Code & Phase observations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-04-18\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssObservation.h\"\n\n/***********************************************/\n\nstatic void positionVelocityTime(const GnssReceiver &receiver, const GnssTransmitter &transmitter, const Rotary3d &rotCrf2Trf, UInt idEpoch,\n                                 Time &timeRecv,  Vector3d &posRecv,  Vector3d &velRecv,  Angle &azimutRecv,  Angle &elevationRecv,\n                                 Time &timeTrans, Vector3d &posTrans, Vector3d &velTrans, Angle &azimutTrans, Angle &elevationTrans,\n                                 Vector3d &k, Vector3d &kRecv, Vector3d &kTrans)\n{\n  try\n  {\n    // receiver in celestial reference frame\n    timeRecv = receiver.timeCorrected(idEpoch);\n    posRecv  = rotCrf2Trf.inverseRotate(receiver.position(idEpoch));\n    velRecv  = rotCrf2Trf.inverseRotate(receiver.velocity(idEpoch));\n    if(receiver.isEarthFixed())\n      velRecv += crossProduct(Vector3d(0., 0., 7.29211585531e-5), posRecv);\n\n    // transmitter position and time\n    posTrans = transmitter.position(idEpoch, timeRecv-seconds2time(20200e3/LIGHT_VELOCITY));\n    Vector3d posOld;\n    for(UInt i=0; (i<10) && ((posTrans-posOld).r() > 0.0001); i++) // iteration\n    {\n      timeTrans = timeRecv - seconds2time((posTrans-posRecv).r()/LIGHT_VELOCITY);\n      posOld    = posTrans;\n      posTrans  = transmitter.position(idEpoch, timeTrans);\n    }\n    velTrans = transmitter.velocity(timeTrans);\n\n    // line of sight from transmitter to receiver\n    k              = normalize(posRecv - posTrans);\n    kRecv          = receiver.global2antennaFrame(idEpoch).transform(rotCrf2Trf.rotate(-k)); // line of sight in receiver antenna system (north, east, up)\n    azimutRecv     = kRecv.lambda();\n    elevationRecv  = kRecv.phi();\n    kTrans         = transmitter.celestial2antennaFrame(idEpoch, timeTrans).transform(k);\n    azimutTrans    = kTrans.lambda();\n    elevationTrans = kTrans.phi();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nBool GnssObservation::init(const GnssReceiver &receiver, const GnssTransmitter &transmitter, const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                           UInt idEpoch, Angle elevationCutOff, Double &phaseWindupOld)\n{\n  try\n  {\n    if((!receiver.useable(idEpoch)) || (!transmitter.useable(idEpoch)))\n      return FALSE;\n\n    // position, time of transmitter & receiver\n    // ----------------------------------------\n    Time     timeRecv, timeTrans;\n    Vector3d posRecv,  velRecv, posTrans, velTrans, k, kRecv, kTrans;\n    Angle    azimutRecv, elevationRecv, azimutTrans, elevationTrans;\n    Rotary3d rotCrf2Trf;\n    if(receiver.isEarthFixed())\n      rotCrf2Trf = rotationCrf2Trf(receiver.timeCorrected(idEpoch));\n    positionVelocityTime(receiver, transmitter, rotCrf2Trf, idEpoch,\n                         timeRecv, posRecv, velRecv, azimutRecv, elevationRecv,\n                         timeTrans, posTrans, velTrans, azimutTrans, elevationTrans,\n                         k, kRecv, kTrans);\n\n    if(elevationRecv < elevationCutOff)\n      return FALSE;\n\n    std::vector<GnssType> types(size());\n    for(UInt i=0; i<size(); i++)\n      types.at(i) = at(i).type;\n\n    // Composed signals (e.g. C2DG)\n    std::vector<GnssType> typesTransmitted;\n    Matrix T;\n    receiver.signalComposition(idEpoch, types, typesTransmitted, T);\n    if(!T.size())\n      return FALSE;\n\n    // Accuracies and antenna pattern check\n    // ------------------------------------\n    const Vector sigma0   = receiver.accuracy(timeRecv, azimutRecv, elevationRecv, types);\n    const Vector acvRecv  = receiver.antennaVariations(timeRecv, azimutRecv, elevationRecv, types);\n    const Vector acvTrans = transmitter.antennaVariations(timeTrans, azimutTrans, elevationTrans, typesTransmitted);\n    for(UInt i=0; i<size(); i++)\n    {\n      at(i).sigma0 = sigma0(i);\n      at(i).sigma  = acvRecv(i); // temporarily misuse sigma for ACV pattern nan check\n      for(UInt k=0; k<T.columns(); k++)\n        if(T(i,k))\n          at(i).sigma  += T(i,k) * acvTrans(k);\n    }\n    obs.erase(std::remove_if(obs.begin(), obs.end(), [](const auto &x)\n    {\n      if(((x.type == GnssType::PHASE) || (x.type == GnssType::RANGE)) && (x.sigma0 <= 0)) return TRUE; // remove Phase/Range for sigma <= 0\n      return std::isnan(x.sigma0) || std::isnan(x.sigma);                                              // remove all NAN values\n    }), obs.end());\n    obs.shrink_to_fit();\n    if(size()==0)\n      return FALSE;\n\n    for(UInt i=0; i<size(); i++)\n      at(i).sigma = at(i).sigma0;\n    for(UInt i=0; i<size(); i++)\n      at(i).residuals = at(i).redundancy = 0.;\n\n    std::sort(obs.begin(), obs.end(), [](const GnssSingleObservation &obs1, const GnssSingleObservation &obs2) {return (obs1.type < obs2.type);});\n\n    // phase wind-up\n    // Carrier phase wind-up in GPS reflectometry, Georg Beyerle, Springer Verlag 2008\n    // -------------------------------------------------------------------------------\n    const Transform3d crf2arfRecv  = receiver.global2antennaFrame(idEpoch) * rotCrf2Trf;\n    const Transform3d crf2arfTrans = transmitter.celestial2antennaFrame(idEpoch, timeTrans);\n    const Vector3d Tx = crf2arfRecv.transform(crossProduct(crossProduct(k, crf2arfTrans.inverseTransform(Vector3d(1,0,0))), k));\n    const Vector3d Ty = crf2arfRecv.transform(crossProduct(crossProduct(k, crf2arfTrans.inverseTransform(Vector3d(0,1,0))), k));\n    Double phaseWindup = atan2(Tx.y()+Ty.x(), Ty.y()-Tx.x()); // both left-handed systems\n    phaseWindup -= PI/2; // to be consistent with Wu et al. (1993) and Kouba (2009) definition\n    while((phaseWindupOld-phaseWindup)>PI)\n      phaseWindup += 2*PI;\n    while((phaseWindupOld-phaseWindup)<-PI)\n      phaseWindup -= 2*PI;\n    phaseWindupOld = phaseWindup;\n    for(UInt i=0; i<size(); i++)\n      if(at(i).type == GnssType::PHASE)\n        at(i).observation -= phaseWindup/(2*PI) * (at(i).type.wavelength());\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt GnssObservation::index(GnssType type) const\n{\n  for(UInt i=0; i<size(); i++)\n    if(at(i).type == type)\n      return i;\n  return NULLINDEX;\n}\n\n/***********************************************/\n\nBool GnssObservation::observationList(GnssObservation::Group group, std::vector<GnssType> &types) const\n{\n  try\n  {\n    types.clear();\n\n    // code observations\n    if(group & RANGE)\n    {\n      // need obs at two frequencies\n      std::set<GnssType> typeFrequencies;\n      for(UInt i=0; i<size(); i++)\n        if((at(i).type == GnssType::RANGE) && (at(i).sigma > 0))\n          typeFrequencies.insert(at(i).type & GnssType::FREQUENCY);\n      if(typeFrequencies.size() < 2)\n        return FALSE;\n\n      for(UInt i=0; i<size(); i++)\n        if(at(i).sigma>0)\n          if(at(i).type == GnssType::RANGE)\n            types.push_back( at(i).type );\n    }\n\n    // phase observations\n    if(group & PHASE)\n    {\n      // need obs at two frequencies\n      std::set<GnssType> typeFrequencies;\n      for(UInt i=0; i<size(); i++)\n        if((at(i).type == GnssType::PHASE) && (at(i).sigma > 0))\n          typeFrequencies.insert(at(i).type & GnssType::FREQUENCY);\n      if(typeFrequencies.size() < 2)\n        return FALSE;\n\n      for(UInt i=0; i<size(); i++)\n        if(at(i).sigma>0)\n          if(at(i).type == GnssType::PHASE)\n            types.push_back( at(i).type );\n    }\n\n    // ionospheric delay as pseudo observations\n    if(group & IONO)\n    {\n      for(UInt i=0; i<size(); i++)\n        if((at(i).type == GnssType::IONODELAY) && (at(i).sigma > 0))\n          types.push_back( at(i).type );\n    }\n\n    return (types.size() != 0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssObservation::setHomogenizedResiduals(const std::vector<GnssType> &types, const_MatrixSliceRef residuals, const_MatrixSliceRef redundancy)\n{\n  try\n  {\n    for(UInt i=0; i<types.size(); i++)\n    {\n      const UInt idx = index(types.at(i));\n      at(idx).residuals  = residuals(i,0) * at(idx).sigma;\n      at(idx).redundancy = redundancy(i,0);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssObservation::updateParameter(const_MatrixSliceRef x, const_MatrixSliceRef /*covariance*/)\n{\n  try\n  {\n    STEC  += x(0,0);\n    dSTEC += x(0,0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid GnssObservationEquation::compute(const GnssObservation &observation, const GnssReceiver &receiver_, const GnssTransmitter &transmitter_,\n                                      const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                                      UInt idEpoch_, Bool homogenize, const std::vector<GnssType> &types_)\n{\n  try\n  {\n    const UInt obsCount = types_.size();\n    idEpoch     = idEpoch_;\n    receiver    = &receiver_;\n    transmitter = &transmitter_;\n    track       = observation.track;\n    STEC        = observation.STEC;\n    dSTEC       = observation.dSTEC;\n    sigmaSTEC   = observation.sigmaSTEC;\n    types       = types_;\n    rankDeficit = 0;\n    l           = Vector(obsCount);\n    sigma       = Vector(obsCount);\n    sigma0      = Vector(obsCount);\n\n    // position, time of transmitter & receiver\n    // ----------------------------------------\n    Vector3d k, kRecvAnt, kTrans;\n    Rotary3d rotCrf2Trf;\n    if(receiver_.isEarthFixed())\n      rotCrf2Trf = rotationCrf2Trf(receiver_.timeCorrected(idEpoch));\n    positionVelocityTime(receiver_, transmitter_, rotCrf2Trf, idEpoch_,\n                         timeRecv,  posRecv,  velocityRecv,  azimutRecvAnt, elevationRecvAnt,\n                         timeTrans, posTrans, velocityTrans, azimutTrans,   elevationTrans,\n                         k, kRecvAnt, kTrans);\n    const Double   rDotTrans  = inner(k, velocityTrans)/LIGHT_VELOCITY;\n    const Double   rDotRecv   = inner(k, velocityRecv) /LIGHT_VELOCITY;\n    const Vector3d kRecvLocal = receiver_.global2localFrame(idEpoch).transform(rotCrf2Trf.rotate(-k));\n    azimutRecvLocal    = kRecvLocal.lambda();\n    elevationRecvLocal = kRecvLocal.phi();\n\n    if(!obsCount)\n      return;\n\n    // observations\n    // ------------\n    for(UInt i=0; i<obsCount; i++)\n    {\n      const UInt idx = observation.index(types.at(i));\n      if(idx == NULLINDEX)\n        continue;\n      types.at(i) = observation.at(idx).type;\n      l(i)        = observation.at(idx).observation;\n      sigma(i)    = observation.at(idx).sigma;\n      sigma0(i)   = observation.at(idx).sigma0;\n    }\n\n    // Corrected range\n    // ---------------\n    const Double r1  = posTrans.r();\n    const Double r2  = posRecv.r();\n    Double       r12 = (posRecv - posTrans).r();\n    r12 += 2*DEFAULT_GM/pow(LIGHT_VELOCITY,2)*log((r1+r2+r12)/(r1+r2-r12)); // curved space-time\n    r12 += 2*inner(posTrans, velocityTrans)/LIGHT_VELOCITY;                 // relativistic clock correction\n    r12 -= LIGHT_VELOCITY * transmitter->clockError(idEpoch);\n    r12 += LIGHT_VELOCITY * receiver->clockError(idEpoch);\n    r12 *= transmitter->scaleFactor(idEpoch);\n\n    for(UInt i=0; i<obsCount; i++)\n      if((types.at(i) == GnssType::RANGE) || (types.at(i) == GnssType::PHASE))\n        l(i) -= r12;\n\n    // Composed signals (e.g. C2DG)\n    Matrix T;\n    receiver->signalComposition(idEpoch, types, typesTransmitted, T);\n\n    // design matrix\n    // -------------\n    A = Matrix(obsCount, 10 + obsCount + T.columns());\n    B = Matrix();\n    for(UInt i=0; i<obsCount; i++)\n    {\n      if((types.at(i) == GnssType::RANGE) || (types.at(i) == GnssType::PHASE))\n      {\n        A(i, idxPosRecv+0)  = k.x() * (1+rDotTrans);   // receiver coord x\n        A(i, idxPosRecv+1)  = k.y() * (1+rDotTrans);   // receiver coord y\n        A(i, idxPosRecv+2)  = k.z() * (1+rDotTrans);   // receiver coord z\n        A(i, idxClockRecv)  = 1.0+rDotTrans-rDotRecv;  // receiver clock correction\n        A(i, idxPosTrans+0) = k.x() * (-1+rDotTrans);  // transmitter coord x\n        A(i, idxPosTrans+1) = k.y() * (-1+rDotTrans);  // transmitter coord y\n        A(i, idxPosTrans+2) = k.z() * (-1+rDotTrans);  // transmitter coord z\n        A(i, idxClockTrans) = -1.0;                    // transmitter clock correction\n        A(i, idxRange)      =  1.0;                    // range correction (troposphere, ...)\n        A(i, idxSTEC)       = types.at(i).ionosphericFactor();\n      }\n\n      A(i, idxUnit+i) = 1.0; // unit matrix\n    }  // for(i=0..obsCount)\n    copy(T, A.column(idxUnit + obsCount, T.columns()));\n\n    // antenna correction and other corrections\n    // ----------------------------------------\n    l -= receiver->antennaVariations(timeRecv, azimutRecvAnt,  elevationRecvAnt,  types);\n    l -= T * transmitter->antennaVariations(timeTrans, azimutTrans, elevationTrans, typesTransmitted);\n    if(track && track->ambiguity)\n      l -= track->ambiguity->ambiguities(types);     // reduce ambiguities\n    if(reduceModels)\n      reduceModels(*this);\n\n    // Homogenize\n    // ----------\n    if(homogenize)\n      for(UInt i=0; i<obsCount; i++)\n      {\n        if(l.size()) l.row(i) *= 1/sigma(i);\n        if(A.size()) A.row(i) *= 1/sigma(i);\n        if(B.size()) B.row(i) *= 1/sigma(i);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssObservationEquation::eliminateGroupParameters(Bool removeRows)\n{\n  try\n  {\n    if(!B.size())\n      return;\n    const Vector tau = QR_decomposition(B);\n    if(!removeRows)\n      rankDeficit += B.columns();\n    for(Matrix &A : std::vector<std::reference_wrapper<Matrix>>{A, l})\n      if(A.size())\n      {\n        QTransMult(B, tau, A);\n        if(removeRows)\n          A = A.row(B.columns(), A.rows()-B.columns());\n        else\n        {\n          A.row(0, B.columns()).setNull();\n          QMult(B, tau, A);\n        }\n      }\n    B = Matrix();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssObservation.h",
    "content": "/***********************************************/\n/**\n* @file gnssObservation.h\n*\n* @brief Code & Phase observations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-04-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSOBSERVATION__\n#define __GROOPS_GNSSOBSERVATION__\n\n#include \"base/gnssType.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass GnssTrack;\nclass GnssReceiver;\nclass GnssTransmitter;\n\n/***** CLASS ***********************************/\n\n/** @brief Single observation. */\nclass GnssSingleObservation\n{\npublic:\n  GnssType type;        ///< measurement types (phases, pseudo ranges, ...)\n  Double   observation; ///< original observations\n  Double   residuals;   ///< estimated postfit residuals\n  Double   redundancy;  ///< partial redundancies of the least squares adjustment\n  Double   sigma0;      ///< expected (apriori) accuracies\n  Double   sigma;       ///< modified accuracies (downweighted outliers)\n\n  GnssSingleObservation() {}\n  GnssSingleObservation(GnssType _type, Double _observation=0., Double _residuals=0., Double _redundancy=0., Double _sigma0=0., Double _sigma=0.)\n    : type(_type), observation(_observation), residuals(_residuals), redundancy(_redundancy), sigma0(_sigma0), sigma(_sigma) {}\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Observations.\n* Between one receiver and one transmitter at one epoch. */\nclass GnssObservation\n{\n  std::vector<GnssSingleObservation> obs;\n\npublic:\n  typedef UInt Group;\n  constexpr static Group RANGE = 1<<0; // use code observations only\n  constexpr static Group PHASE = 1<<1;\n  constexpr static Group IONO  = 1<<2;\n  constexpr static Group ALL   = ~0;   // all bits set: use all available observations as they are\n\n  GnssTrack *track; ///< phase ambiguities\n  Double     STEC, dSTEC;  ///< total ionosphere slant TEC along the path and estimated part of STEC\n  Double     sigmaSTEC;\n\n\n  GnssObservation() : track(nullptr), STEC(0.), dSTEC(0.), sigmaSTEC(0.) {}\n\n  UInt size() const                                      {return obs.size();}\n  GnssSingleObservation       &at(UInt idType)           {return obs.at(idType);}\n  const GnssSingleObservation &at(UInt idType) const     {return obs.at(idType);}\n  GnssSingleObservation       &at(GnssType type)         {return obs.at(index(type));}\n  const GnssSingleObservation &at(GnssType type) const   {return obs.at(index(type));}\n  UInt index(GnssType type) const;\n  void push_back(const GnssSingleObservation &singleObs) {obs.push_back(singleObs);}\n  void erase(UInt idType)                                {obs.erase(obs.begin()+idType); obs.shrink_to_fit();}\n  void shrink_to_fit()                                   {obs.shrink_to_fit();}\n  void sort()                                            {std::sort(obs.begin(), obs.end(), [](auto &a, auto &b){return a.type < b.type;});}\n\n\n  Bool init(const GnssReceiver &receiver, const GnssTransmitter &transmitter, const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n            UInt idEpoch, Angle elevationCutOff, Double &phaseWindupOld);\n\n  /** @brief Returns true if observation types required by @a analysisType are available, @a type contains list of these observations. */\n  Bool observationList        (Group group, std::vector<GnssType> &types) const;\n  void setHomogenizedResiduals(const std::vector<GnssType> &types, const_MatrixSliceRef residuals, const_MatrixSliceRef redundancy);\n  void updateParameter        (const_MatrixSliceRef x, const_MatrixSliceRef covariance=Matrix());\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Reduced observations (obs - computed) and design matrix.\n* Between one receiver and one transmitter at one epoch. */\nclass GnssObservationEquation\n{\npublic:\n  enum {idxPosRecv    = 0, // x,y,z (CRF)\n        idxClockRecv  = 3,\n        idxPosTrans   = 4, // x,y,z (CRF)\n        idxClockTrans = 7,\n        idxRange      = 8,\n        idxSTEC       = 9,\n        idxUnit       = 10};\n\n  UInt  idEpoch;\n  const GnssTrack       *track; // phase ambiguities\n  const GnssReceiver    *receiver;\n  const GnssTransmitter *transmitter;\n\n  // weighted observations (with 1/sigma)\n  std::vector<GnssType> types;            ///< observed types (inclusive composed signals)\n  std::vector<GnssType> typesTransmitted; ///< original transmitted signals (C2XG -> C2LG + C2SG), phases without attribute\n  UInt   rankDeficit;  ///< from eliminated group parameters\n  Vector l;            ///< weighted reduced observations\n  Vector sigma;\n  Vector sigma0;\n\n  // design matrix\n  Matrix A;      ///< columns: dl/dx, dl/dy, dl/dz, dl/dClock, unit matrix, transformation matrix (typesTransmitter->types)\n  Matrix B;      ///< ionosphere, ...\n\n  // approximate values (Taylor point)\n  Time     timeRecv, timeTrans;\n  Vector3d posRecv,  posTrans;\n  Vector3d velocityRecv, velocityTrans;\n  Angle    azimutRecvLocal, elevationRecvLocal;\n  Angle    azimutRecvAnt,   elevationRecvAnt;\n  Angle    azimutTrans,     elevationTrans;\n  Double   STEC, dSTEC;\n  Double   sigmaSTEC;\n\n  GnssObservationEquation() : idEpoch(NULLINDEX), track(nullptr), receiver(nullptr), transmitter(nullptr), rankDeficit(0), STEC(0), dSTEC(0), sigmaSTEC(0) {}\n\n  GnssObservationEquation(const GnssObservation &observation, const GnssReceiver &receiver, const GnssTransmitter &transmitter,\n                          const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                          UInt idEpoch, Bool homogenize, const std::vector<GnssType> &types)\n    {compute(observation, receiver, transmitter, rotationCrf2Trf, reduceModels, idEpoch, homogenize, types);}\n\n  void compute(const GnssObservation &observation, const GnssReceiver &receiver, const GnssTransmitter &transmitter,\n               const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n               UInt idEpoch, Bool homogenize, const std::vector<GnssType> &types);\n\n  void eliminateGroupParameters(Bool removeRows=TRUE);\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrization.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrization.cpp\n*\n* @brief Parametrization of GNSS observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_GnssParametrization\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationIonosphereSTEC.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationIonosphereVTEC.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationIonosphereMap.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationClocks.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationClocksModel.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationSignalBiases.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationAmbiguities.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationCodeBiases.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTecBiases.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTemporalBias.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationStaticPositions.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationKinematicPositions.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationLeoDynamicOrbits.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTransmitterDynamicOrbits.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTroposphere.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationEarthRotation.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationReceiverAntennas.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTransmitterAntennas.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationConstraints.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationGroup.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(GnssParametrization, \"gnssParametrizationType\",\n                      GnssParametrizationIonosphereSTEC,\n                      GnssParametrizationIonosphereVTEC,\n                      GnssParametrizationIonosphereMap,\n                      GnssParametrizationClocks,\n                      GnssParametrizationClocksModel,\n                      GnssParametrizationSignalBiases,\n                      GnssParametrizationAmbiguities,\n                      GnssParametrizationCodeBiases,\n                      GnssParametrizationTecBiases,\n                      GnssParametrizationTemporalBias,\n                      GnssParametrizationStaticPositions,\n                      GnssParametrizationKinematicPositions,\n                      GnssParametrizationLeoDynamicOrbits,\n                      GnssParametrizationTransmitterDynamicOrbits,\n                      GnssParametrizationTroposphere,\n                      GnssParametrizationEarthRotation,\n                      GnssParametrizationReceiverAntennas,\n                      GnssParametrizationTransmitterAntennas,\n                      GnssParametrizationConstraints,\n                      GnssParametrizationGroup)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(GnssParametrization, \"gnssParametrizationType\")\n\n/***********************************************/\n\nGnssParametrization::GnssParametrization(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"parametrization of GNSS observations\"))\n    {\n      if(readConfigChoiceElement(config, \"ionosphereSTEC\",           type, \"ionospheric slant delays\"))\n        base.push_back(new GnssParametrizationIonosphereSTEC(config));\n      if(readConfigChoiceElement(config, \"ionosphereVTEC\",           type, \"ionospheric verical delays\"))\n        base.push_back(new GnssParametrizationIonosphereVTEC(config));\n      if(readConfigChoiceElement(config, \"ionosphereMap\",            type, \"ionospheric verical delays\"))\n        base.push_back(new GnssParametrizationIonosphereMap(config));\n      if(readConfigChoiceElement(config, \"clocks\",                   type, \"clock errors\"))\n        base.push_back(new GnssParametrizationClocks(config));\n      if(readConfigChoiceElement(config, \"clocksModel\",              type, \"clock errors with AR1 process model\"))\n        base.push_back(new GnssParametrizationClocksModel(config));\n      if(readConfigChoiceElement(config, \"signalBiases\",             type, \"apriori values of signal biases (code/phase)\"))\n        base.push_back(new GnssParametrizationSignalBiases(config));\n      if(readConfigChoiceElement(config, \"ambiguities\",              type, \"integer and float ambiguities\"))\n        base.push_back(new GnssParametrizationAmbiguities(config));\n      if(readConfigChoiceElement(config, \"codeBiases\",               type, \"biases of code signals\"))\n        base.push_back(new GnssParametrizationCodeBiases(config));\n      if(readConfigChoiceElement(config, \"tecBiases\",                type, \"biases of signals which changes the estimated TEC\"))\n        base.push_back(new GnssParametrizationTecBiases(config));\n      if(readConfigChoiceElement(config, \"temporalBias\",             type, \"temporal changing signal bias\"))\n        base.push_back(new GnssParametrizationTemporalBias(config));\n      if(readConfigChoiceElement(config, \"staticPositions\",          type, \"static positions with no-net constraints\"))\n        base.push_back(new GnssParametrizationStaticPositions(config));\n      if(readConfigChoiceElement(config, \"kinematicPositions\",       type, \"position each epoch\"))\n        base.push_back(new GnssParametrizationKinematicPositions(config));\n      if(readConfigChoiceElement(config, \"leoDynamicOrbits\",          type, \"LEO orbits by variational equations\"))\n        base.push_back(new GnssParametrizationLeoDynamicOrbits(config));\n      if(readConfigChoiceElement(config, \"transmitterDynamicOrbits\", type, \"GNSS satellite orbits by variational equations\"))\n        base.push_back(new GnssParametrizationTransmitterDynamicOrbits(config));\n      if(readConfigChoiceElement(config, \"troposphere\",              type, \"tropospheric delays\"))\n        base.push_back(new GnssParametrizationTroposphere(config));\n      if(readConfigChoiceElement(config, \"earthRotation\",            type, \"Earth rotation\"))\n        base.push_back(new GnssParametrizationEarthRotation(config));\n      if(readConfigChoiceElement(config, \"receiverAntennas\",         type, \"antenna center variations\"))\n        base.push_back(new GnssParametrizationReceiverAntennas(config));\n      if(readConfigChoiceElement(config, \"transmitterAntennas\",      type, \"antenna center variations\"))\n        base.push_back(new GnssParametrizationTransmitterAntennas(config));\n      if(readConfigChoiceElement(config, \"constraints\",              type, \"parameter constraints\"))\n        base.push_back(new GnssParametrizationConstraints(config));\n      if(readConfigChoiceElement(config, \"group\",                    type, \"grouping parametrizations\"))\n        base.push_back(new GnssParametrizationGroup(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrization::~GnssParametrization()\n{\n  for(auto b : base)\n    delete b;\n}\n\n/***********************************************/\n\nvoid GnssParametrization::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    for(auto b : base)\n      b->init(gnss, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::observationCorrections(GnssObservationEquation &eqn) const\n{\n  try\n  {\n    for(auto b : base)\n      b->observationCorrections(eqn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::requirements(GnssNormalEquationInfo &normalEquationInfo,\n                                       std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                                       std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch)\n{\n  try\n  {\n    for(auto b : base)\n      b->requirements(normalEquationInfo, transCount, transCountEpoch, recvCount, recvCountEpoch);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto b : base)\n      b->initParameter(normalEquationInfo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector GnssParametrization::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo) const\n{\n  try\n  {\n    Vector x0(normalEquationInfo.parameterCount());\n    for(auto b : base)\n      b->aprioriParameter(normalEquationInfo, x0);\n    return x0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    for(auto b : base)\n      b->designMatrix(normalEquationInfo, eqn, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    for(auto b : base)\n      b->constraintsEpoch(normalEquationInfo, idEpoch, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    for(auto b : base)\n      b->constraints(normalEquationInfo, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrization::ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                                             const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                                             const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger)\n{\n  try\n  {\n    Double sigmaFloat = 0;\n    for(auto b : base)\n      sigmaFloat = std::max(sigmaFloat, b->ambiguityResolve(normalEquationInfo, normals, n, lPl, obsCount,\n                                                            selectedTransmitters, selectedReceivers, searchInteger));\n    return sigmaFloat;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nDouble GnssParametrization::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    Double change = 0;\n    for(auto b : base)\n      change = std::max(change, b->updateParameter(normalEquationInfo, x, Wz));\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    for(auto b : base)\n      b->updateCovariance(normalEquationInfo, covariance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrization::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    for(auto b : base)\n      b->writeResults(normalEquationInfo, suffix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nBool GnssParametrizationBase::isEnabled(const GnssNormalEquationInfo &normalEquationInfo, const std::string &name)\n{\n  try\n  {\n    Bool enabled = TRUE;\n    for(const auto &pattern : normalEquationInfo.enableParametrizations)\n      if(std::regex_match(name, pattern.first))\n        enabled = pattern.second;\n    return enabled;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrization.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrization.h\n*\n* @brief Parametrization of GNSS observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSSPARAMETRIZATION__\n#define __GROOPS_GNSSSPARAMETRIZATION__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrization = R\"(\n\\section{GnssParametrization}\\label{gnssParametrizationType}\nThis class defines the models and parameters of the linearized observation equations\nfor all phase and code measurements (see \\program{GnssProcessing})\n\\begin{equation}\\label{gnssParametrizationType:model}\n  \\M l - \\M f(\\M x_0) = \\left.\\frac{\\partial \\M f(\\M x)}{\\partial \\M x}\\right|_{\\M x_0} \\Delta\\M x + \\M\\epsilon,\n\\end{equation}\nwhere the left side is the observation vector minus the effects computed from the a priori models.\nAfter each least squares adjustment\n(see \\configClass{GnssProcessing:processingStep:estimate}{gnssProcessingStepType:estimate})\nthe a priori parameters are updated\n\\begin{equation}\\label{gnssParametrizationType:update}\n  \\M x_0 := \\M x_0 + \\Delta\\hat{\\M x}.\n\\end{equation}\nThe vector $\\M x_0$ can be written with\n\\configClass{GnssProcessing:processingStep:writeAprioriSolution}{gnssProcessingStepType:writeAprioriSolution}.\nAny \\config{outputfiles} defined in the parametrizations are written with\n\\configClass{GnssProcessing:processingStep:writeResults}{gnssProcessingStepType:writeResults}.\n\nEach parametrization (and possible constraint equations) has a \\config{name} which enables\nactivating/deactivating the estimation of subsets of $\\Delta\\M x$ with\n\\configClass{GnssProcessing:processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations}.\nThe a priori model $\\M f(\\M x_0)$ is unaffected and is always reduced.\n\nThe model for the different observation types can be described as\n\\begin{equation}\\label{gnssParametrizationType:gnssFullModel}\n\\begin{split}\n  f[\\tau\\nu a]_r^s(\\M x) &= \\text{geometry}(\\M r_r^s) + \\text{clock}^s(t) + \\text{clock}_r(t) \\\\\n               &+ \\text{ionosphere}([\\tau\\nu],t,\\M r_r^s) + \\text{troposphere}(t,\\M r_r^s) \\\\\n               &+ \\text{antenna}[\\tau\\nu a]^s  + \\text{antenna}[\\tau\\nu a]_r \\\\\n               &+ \\text{bias}[\\tau\\nu a]^s + \\text{bias}[\\tau\\nu a]_r\n               + \\lambda[L\\nu] N[L\\nu a]_r^s + \\text{other}(\\ldots) + \\epsilon[\\tau\\nu a]_r^s\n\\end{split}\n\\end{equation}\nThe notation $[\\tau\\nu a]_r^s$ describes the\nattribution to a signal type $\\tau$ (i.e., C or L), frequency $\\nu$,\nsignal attribute $a$ (e.g., C, W, Q, X), transmitting satellite $s$, and observing receiver $r$.\nIt follows the \\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition},\nsee \\reference{GnssType}{gnssType}.\n\nSee also \\program{GnssProcessing}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssObservation.h\"\n#include \"gnss/gnssDesignMatrix.h\"\n#include \"gnss/gnssNormalEquationInfo.h\"\n\n\n/**\n* @defgroup gnssParametrizationGroup GnssParametrization\n* @brief Parametrization of GNSS observations.\n* @ingroup classesGroup\n* The interface is given by @ref GnssParametrization. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass GnssParametrization;\nclass GnssParametrizationBase;\ntypedef std::shared_ptr<GnssParametrization> GnssParametrizationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Parametrization of GNSS observations.\n* An instance of this class can be created with @ref readConfig. */\nclass GnssParametrization\n{\n  std::vector<GnssParametrizationBase*> base;\n\npublic:\n  /// Constructor.\n  GnssParametrization(Config &config, const std::string &name);\n\n ~GnssParametrization();\n\n  /** @brief init base on transmitters and receivers in @p gnss. */\n  void init(Gnss *gnss, Parallel::CommunicatorPtr comm);\n\n  /** @brief How many observations are needed to estimate parameters? */\n  void requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                    std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch);\n\n  /** @brief Register parameters in @p normalEquationInfo. */\n  void initParameter(GnssNormalEquationInfo &normalEquationInfo);\n\n  /** @brief Correct observation equations/apply models. */\n  void observationCorrections(GnssObservationEquation &eqn) const;\n\n  /** @brief Total parameter vector used as priori Taylor point. */\n  Vector aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo) const;\n\n  /** @brief Design matrix for the basic observation equations @p eqn. */\n  void designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const;\n\n  /** @brief Add additional (pseudo-) observations equations to the normals for @p idEpoch. */\n  void constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const;\n\n  /** @brief Add additional (pseudo-) observations equations to the normals. */\n  void constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const;\n\n  /** @brief Resolve ambiguities to integer. */\n  Double ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                          const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                          const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger);\n\n  /** @brief Update the values based on the passed estimated dx. */\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz);\n\n  /** @brief Update the covariance information passed by @p covariance matrix. */\n  void updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance);\n\n  /** @brief Write the output files defined in the parametrizations. */\n  void writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const;\n\n  /** @brief creates an derived instance of this class. */\n  static GnssParametrizationPtr create(Config &config, const std::string &name) {return GnssParametrizationPtr(new GnssParametrization(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class GnssParametrization.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and an class without points is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates GnssParametrization */\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssParametrizationPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass GnssParametrizationBase\n{\npublic:\n  virtual ~GnssParametrizationBase() {}\n\n  static Bool isEnabled(const GnssNormalEquationInfo &normalEquationInfo, const std::string &name);\n\n  virtual void   init(Gnss */*gnss*/, Parallel::CommunicatorPtr /*comm*/) {}\n  virtual void   requirements(GnssNormalEquationInfo &/*normalEquationInfo*/, std::vector<UInt> &/*transCount*/, std::vector<UInt> &/*transCountEpoch*/,\n                              std::vector<UInt> &/*recvCount*/, std::vector<UInt> &/*recvCountEpoch*/) {}\n  virtual void   initParameter(GnssNormalEquationInfo &/*normalEquationInfo*/) {}\n  virtual void   observationCorrections(GnssObservationEquation &/*eqn*/) const {}\n  virtual void   aprioriParameter(const GnssNormalEquationInfo &/*normalEquationInfo*/, MatrixSliceRef /*x0*/) const {}\n  virtual void   designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &/*eqn*/, GnssDesignMatrix &/*A*/) const {}\n  virtual void   constraintsEpoch(const GnssNormalEquationInfo &/*normalEquationInfo*/, UInt /*idEpoch*/, MatrixDistributed &/*normals*/, std::vector<Matrix> &/*n*/, Double &/*lPl*/, UInt &/*obsCount*/) const {}\n  virtual void   constraints(const GnssNormalEquationInfo &/*normalEquationInfo*/, MatrixDistributed &/*normals*/, std::vector<Matrix> &/*n*/, Double &/*lPl*/, UInt &/*obsCount*/) const {}\n  virtual Double ambiguityResolve(const GnssNormalEquationInfo &/*normalEquationInfo*/, MatrixDistributed &/*normals*/, std::vector<Matrix> &/*n*/, Double &/*lPl*/, UInt &/*obsCount*/,\n                                  const std::vector<Byte> &/*selectedTransmitters*/, const std::vector<Byte> &/*selectedReceivers*/,\n                                  const std::function<Vector(const_MatrixSliceRef, MatrixSliceRef, const_MatrixSliceRef, Vector &, Double &)> &) {return 0;}\n  virtual Double updateParameter(const GnssNormalEquationInfo &/*normalEquationInfo*/, const_MatrixSliceRef /*x*/, const_MatrixSliceRef /*Wz*/) {return 0;}\n  virtual void   updateCovariance(const GnssNormalEquationInfo &/*normalEquationInfo*/, const MatrixDistributed &/*covariance*/) {}\n  virtual void   writeResults(const GnssNormalEquationInfo &/*normalEquationInfo*/, const std::string &/*suffix*/) const {}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationAmbiguities.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationAmbiguities.cpp\n*\n* @brief integer and float ambiguities.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2013-06-24\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileMatrix.h\"\n#include \"gnss/gnssLambda.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationAmbiguities.h\"\n\n\n/***********************************************/\n\nGnssParametrizationAmbiguities::GnssParametrizationAmbiguities(Config &config)\n{\n  try\n  {\n    std::string choice;\n\n    readConfig(config, \"name\",                           name,                    Config::OPTIONAL, \"parameter.ambiguities\", \"used for parameter selection\");\n    readConfig(config, \"estimateTransmitterPhaseBias\",   selectTransmitters,      Config::DEFAULT,  \"[\\\"all\\\"]\", \"\");\n    readConfig(config, \"estimateReceiverPhaseBias\",      selectReceivers,         Config::DEFAULT,  \"[\\\"all\\\"]\", \"\");\n    readConfig(config, \"linearGlonassBias\",              isLinearBias,            Config::DEFAULT,  \"0\", \"bias depends linear on frequency channel number\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationAmbiguities::~GnssParametrizationAmbiguities()\n{\n  for(auto para : paraTrans)\n    delete para;\n  for(auto para : paraRecv)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationAmbiguities::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n\n    // float bias at transmitter\n    auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n    paraTrans.resize(gnss->transmitters.size(), nullptr);\n    for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n      if(selectedTransmitters.at(idTrans) && gnss->transmitters.at(idTrans)->useable())\n      {\n        auto para = new ParameterTrans();\n        paraTrans.at(idTrans) = para;\n        para->trans = gnss->transmitters.at(idTrans);\n      }\n\n    // float bias at receiver\n    auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n    paraRecv.resize(gnss->receivers.size(), nullptr);\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedReceivers.at(idRecv) && gnss->receivers.at(idRecv)->useable())\n      {\n        auto para = new ParameterRecv();\n        paraRecv.at(idRecv) = para;\n        para->recv = gnss->receivers.at(idRecv);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<GnssParametrizationAmbiguities::Ambiguity*> GnssParametrizationAmbiguities::getAmbiguities() const\n{\n  try\n  {\n    std::vector<Ambiguity*> ambiguities;\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n        for(auto &track : recv->tracks)\n          if(track->ambiguity)\n            ambiguities.push_back(dynamic_cast<Ambiguity*>(track->ambiguity));\n    return ambiguities;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// to share information between processes\nclass GnssParametrizationAmbiguities::AmbiguityInfo\n{\npublic:\n  Ambiguity            *ambi;\n  UInt                  idRecv, idTrans;\n  UInt                  idEpochStart, idEpochEnd;\n  UInt                  parameterCount;\n  std::vector<GnssType> typesAmbiguity, typesTrack;\n  std::vector<GnssType> typesFreqSys, typesNew;\n  UInt                  idxTrans, idxAmbi;\n  std::vector<UInt>     idxRecv;\n\n  AmbiguityInfo() : ambi(nullptr) {}\n\n  AmbiguityInfo(Ambiguity *ambi) :\n    ambi(ambi), idRecv(ambi->track->receiver->idRecv()), idTrans(ambi->track->transmitter->idTrans()),\n    idEpochStart(ambi->track->idEpochStart), idEpochEnd(ambi->track->idEpochEnd),\n    parameterCount(ambi->value.rows()), typesAmbiguity(ambi->types)\n  {\n    std::copy_if(ambi->track->types.begin(), ambi->track->types.end(), std::back_inserter(typesTrack),\n                 [](auto type) {return type == GnssType::PHASE;});\n  }\n\n  void save(OutArchive &oa) const\n  {\n    oa<<nameValue(\"idRecv\",         idRecv);\n    oa<<nameValue(\"idTrans\",        idTrans);\n    oa<<nameValue(\"idEpochStart\",   idEpochStart);\n    oa<<nameValue(\"idEpochEnd\",     idEpochEnd);\n    oa<<nameValue(\"parameterCount\", parameterCount);\n    oa<<nameValue(\"typesAmbiguity\", typesAmbiguity);\n    oa<<nameValue(\"typesTrack\",     typesTrack);\n  }\n\n  void load(InArchive  &ia)\n  {\n    ia>>nameValue(\"idRecv\",         idRecv);\n    ia>>nameValue(\"idTrans\",        idTrans);\n    ia>>nameValue(\"idEpochStart\",   idEpochStart);\n    ia>>nameValue(\"idEpochEnd\",     idEpochEnd);\n    ia>>nameValue(\"parameterCount\", parameterCount);\n    ia>>nameValue(\"typesAmbiguity\", typesAmbiguity);\n    ia>>nameValue(\"typesTrack\",     typesTrack);\n  }\n};\n\n/***********************************************/\n/***********************************************/\n\nvoid GnssParametrizationAmbiguities::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    // setup new ambiguities\n    // ---------------------\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n      {\n        recv->deleteEmptyTracks();\n        for(auto &track : recv->tracks)\n          if(!track->ambiguity)\n            new Ambiguity(track.get()); // track is owner of ambiguity\n      }\n\n    // reset parameter indices\n    // -----------------------\n    for(auto para : paraTrans)\n      if(para)\n      {\n        para->index = GnssParameterIndex();\n        para->types.clear();\n      }\n    for(auto para : paraRecv)\n      if(para)\n      {\n        para->index = GnssParameterIndex();\n        para->types.clear();\n      }\n    for(auto ambi : getAmbiguities())\n      ambi->index = GnssParameterIndex();\n\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    // distribute ambiguities to all nodes\n    // -----------------------------------\n    std::vector<AmbiguityInfo> ambiguityInfos;\n    for(UInt idProcess=0; idProcess<Parallel::size(normalEquationInfo.comm); idProcess++)\n    {\n      std::vector<AmbiguityInfo> ambiguityInfosLocal;\n      if(Parallel::myRank(normalEquationInfo.comm) == idProcess)\n        for(auto ambi : getAmbiguities())\n          if(ambi->track->receiver->useable() && normalEquationInfo.estimateReceiver.at(ambi->track->receiver->idRecv()))\n            ambiguityInfosLocal.emplace_back(ambi);\n      // synchronize information between processes\n      Parallel::broadCast(ambiguityInfosLocal, idProcess, normalEquationInfo.comm);\n      ambiguityInfos.insert(ambiguityInfos.end(), ambiguityInfosLocal.begin(), ambiguityInfosLocal.end());\n    }\n\n    // sort with decreasing track length\n    std::stable_sort(ambiguityInfos.begin(), ambiguityInfos.end(), [](const AmbiguityInfo &a, const AmbiguityInfo &b)\n                    {return (a.idEpochEnd-a.idEpochStart) > (b.idEpochEnd-b.idEpochStart);});\n\n    // =================================\n\n    // float biases at receivers\n    // -------------------------\n    for(auto &info : ambiguityInfos)\n      for(GnssType &type : info.typesTrack)\n        if(paraRecv.at(info.idRecv) && !type.isInList(paraRecv.at(info.idRecv)->types))\n          paraRecv.at(info.idRecv)->types.push_back(type & ~GnssType::PRN);\n\n    std::vector<std::vector<GnssType>> typesRecv(paraRecv.size()); // float ambiguity at receiver\n    UInt countParaRecv = 0;\n    for(auto para : paraRecv)\n      if(para)\n      {\n        auto &types = para->types;\n        std::sort(types.begin(), types.end());\n        std::vector<GnssType> typesBias;\n        std::vector<GnssType> typesTrend;\n        for(UInt idType=0; idType<types.size(); idType++)\n        {\n          // count same types with different frequency numbers\n          UInt count = 1;\n          while((idType+count < types.size()) && ((types.at(idType+count) & ~GnssType::FREQ_NO) == types.at(idType)))\n            count++;\n          // can type be represented by a trend? (need two adjacent freq. numbers)\n          Bool isTrend = FALSE;\n          if(isLinearBias && (count > 2))\n            for(UInt i=0; i<count-1; i++)\n              if((types.at(idType+i+1).frequencyNumber() - types.at(idType+i).frequencyNumber()) == 1)\n              {\n                isTrend = TRUE;\n                typesRecv.at(para->recv->idRecv()).push_back(types.at(idType+i));\n                typesRecv.at(para->recv->idRecv()).push_back(types.at(idType+i+1));\n                break;\n              }\n          if(isTrend)\n          {\n            typesBias.push_back (types.at(idType) & ~GnssType::FREQ_NO);\n            if(!types.at(idType).isInList(typesTrend))\n              typesTrend.push_back(types.at(idType) & ~(GnssType::ATTRIBUTE+GnssType::FREQ_NO));\n          }\n          else\n            for(UInt i=0; i<count; i++)\n            {\n              typesBias.push_back(types.at(idType+i));\n              typesRecv.at(para->recv->idRecv()).push_back(types.at(idType+i));\n            }\n          idType += count-1;\n        } // for(idType)\n\n        // transformation matrix\n        para->Bias = Matrix(types.size(), typesBias.size()+typesTrend.size());\n        UInt idx;\n        for(UInt i=0; i<types.size(); i++)\n          para->Bias(i, GnssType::index(typesBias, types.at(i))) = types.at(i).wavelength();\n        std::sort(typesTrend.begin(), typesTrend.end());\n        for(UInt i=0; i<types.size(); i++)\n          if(types.at(i).isInList(typesTrend, idx))\n            para->Bias(i, typesBias.size()+idx) = types.at(i).wavelength() * types.at(i).frequencyNumber();\n\n        // parameter names\n        std::vector<ParameterName> parameterNames(typesBias.size()+typesTrend.size());\n        for(UInt i=0; i<typesBias.size(); i++)\n          parameterNames.at(i) = ParameterName(para->recv->name(), \"phaseBias(\"+typesBias.at(i).str()+\")\");\n        for(UInt i=0; i<typesTrend.size(); i++)\n          parameterNames.at(typesBias.size()+i) = ParameterName(para->recv->name(), \"phaseBiasTrend(\"+typesTrend.at(i).str()+\")\");\n        para->index = normalEquationInfo.parameterNamesReceiver(para->recv->idRecv(), parameterNames);\n        countParaRecv += parameterNames.size();\n      } // for(paraRecv)\n\n    // =================================\n\n    // determine estimable transmitter bias and integer ambiguities\n    // setup simpified normal matrix and determine rank deficit via piviot cholesky\n    // ----------------------------------------------------------------------------\n    std::vector<GnssType> typesFreqSys; // for each system & frequency\n    for(auto &info : ambiguityInfos)\n      for(GnssType &type : info.typesTrack)\n        if(!type.isInList(typesFreqSys))\n          typesFreqSys.push_back(type & ~(GnssType::ATTRIBUTE + GnssType::PRN + GnssType::FREQ_NO));\n\n    for(GnssType typeFreqSys : typesFreqSys)\n    {\n      // setup parameter indices\n      // -----------------------\n      std::vector<std::pair<UInt, std::vector<GnssType>>> idTypeAmbi;  // idRecv,   GnssTypes\n      std::vector<std::pair<UInt, GnssType>>              idTypeRecv;  // idRecv,   GnssType w/o PRN\n      std::vector<std::pair<UInt, GnssType>>              idTypeTrans; // idRTrans, GnssType w/o ATTRIBUTE\n      for(auto &info : ambiguityInfos)\n      {\n        // reset indices\n        info.typesFreqSys.clear();\n        for(GnssType &type : info.typesTrack)\n          if((type == typeFreqSys) && !type.isInList(info.typesFreqSys))\n            info.typesFreqSys.push_back(type);\n        info.idxTrans = info.idxAmbi = NULLINDEX;\n        info.idxRecv = std::vector<UInt>(info.typesFreqSys.size(), NULLINDEX);\n        if(!info.typesFreqSys.size())\n          continue;\n\n        // integer ambiguities\n        const std::pair<UInt, std::vector<GnssType>> idType(info.idRecv, info.typesFreqSys);\n        if(std::find(idTypeAmbi.begin(), idTypeAmbi.end(), idType) == idTypeAmbi.end())\n        {\n          info.idxAmbi = idTypeAmbi.size();\n          idTypeAmbi.push_back(idType);\n        }\n        else\n        {\n          // following tracks with same types can directly setup as integer ambiguities\n          info.typesNew.push_back(info.typesFreqSys.front() & ~GnssType::ATTRIBUTE);\n          info.typesFreqSys.clear();\n          continue;\n        }\n\n        // float biases at receivers\n        if(paraRecv.at(info.idRecv))\n         for(UInt i=0; i<info.typesFreqSys.size(); i++)\n           if(info.typesFreqSys.at(i).isInList(typesRecv.at(info.idRecv)))\n           {\n             const std::pair<UInt, GnssType> idType(info.idRecv, info.typesFreqSys.at(i) & ~GnssType::PRN);\n             info.idxRecv.at(i) = std::distance(idTypeRecv.begin(), std::find(idTypeRecv.begin(), idTypeRecv.end(), idType));\n             if(info.idxRecv.at(i) == idTypeRecv.size())\n               idTypeRecv.push_back(idType);\n           }\n\n        // float biases at transmitters\n        if(!normalEquationInfo.isEachReceiverSeparately && paraTrans.at(info.idTrans))\n        {\n          const std::pair<UInt, GnssType> idType(info.idTrans, info.typesFreqSys.front() & ~GnssType::ATTRIBUTE);\n          info.idxTrans = std::distance(idTypeTrans.begin(), std::find(idTypeTrans.begin(), idTypeTrans.end(), idType));\n          if(info.idxTrans == idTypeTrans.size())\n            idTypeTrans.push_back(idType);\n        }\n      } // for(ambiguityInfos)\n\n      // system of normal equations\n      // --------------------------\n      Vector isTrans, isAmbi;\n      if(Parallel::isMaster(normalEquationInfo.comm))\n      {\n        // block normal matrix (upper triangle)\n        Vector Nrr(idTypeRecv.size());                      // recv  x recv (diagonal)\n        Matrix Nrt(idTypeRecv.size(),  idTypeTrans.size()); // recv  x trans\n        Matrix Nra(idTypeRecv.size(),  idTypeAmbi.size());  // recv  x ambiguities\n        Matrix Ntt(idTypeTrans.size(), Matrix::SYMMETRIC);  // trans x trans\n        Matrix Nta(idTypeTrans.size(), idTypeAmbi.size());  // trans x ambiguities\n        Matrix Naa(idTypeAmbi.size(),  Matrix::SYMMETRIC);  // ambiguities x ambiguities\n\n        // pseudo observation equations n = bias_r + bias^t + N_r^t\n        for(auto &info : ambiguityInfos)\n        {\n          const Double w = info.idEpochEnd-info.idEpochStart+1;\n          for(UInt i=0; i<info.typesFreqSys.size(); i++)\n          {\n            if(info.idxRecv.at(i) != NULLINDEX)\n            {\n              Nrr(info.idxRecv.at(i)) += w;\n              if(info.idxTrans != NULLINDEX) Nrt(info.idxRecv.at(i), info.idxTrans) += w;\n              if(info.idxAmbi  != NULLINDEX) Nra(info.idxRecv.at(i), info.idxAmbi)  += w;\n            }\n            if(info.idxTrans != NULLINDEX)\n            {\n              Ntt(info.idxTrans, info.idxTrans) += w;\n              if(info.idxAmbi != NULLINDEX) Nta(info.idxTrans, info.idxAmbi) += w;\n            }\n            if(info.idxAmbi != NULLINDEX) Naa(info.idxAmbi, info.idxAmbi) += w;\n          }\n        }\n\n        // block wise cholesky\n        // -------------------\n        if(Nrr.size()) // receiver bias\n        {\n          if(Ntt.size())\n          {\n            for(UInt i=0; i<Nrr.rows(); i++)\n              Nrt.row(i) *= 1/std::sqrt(Nrr(i));\n            rankKUpdate(-1, Nrt, Ntt);\n          }\n          if(Naa.size())\n          {\n            for(UInt i=0; i<Nrr.rows(); i++)\n              Nra.row(i) *= 1/std::sqrt(Nrr(i));\n            rankKUpdate(-1, Nra, Naa);\n          }\n          if(Ntt.size() && Naa.size())\n            matMult(-1, Nrt.trans(), Nra, Nta);\n        }\n        if(Ntt.size()) // transmitter bias\n        {\n          Double tolerance = 0;\n          for(UInt i=0; i<Ntt.rows(); i++)\n            tolerance = std::max(tolerance, std::fabs(Ntt(i,i)));\n          GnssLambda::Transformation Z(Ntt.rows());\n          UInt rank = GnssLambda::choleskyReversePivot(Ntt, Z, 0, 1e-8*Ntt.rows()*tolerance, FALSE/*timing*/);\n          isTrans = Vector(Ntt.rows());\n          isTrans.row(0, rank).fill(1.);\n          isTrans = Z.transformBack(isTrans);\n          if(Naa.size() && rank)\n          {\n            Nta = Z.transform(Nta);\n            triangularSolve(1., Ntt.slice(0, 0, rank, rank).trans(), Nta.row(0, rank));\n            rankKUpdate(-1, Nta.row(0, rank), Naa);\n          }\n        }\n        if(Naa.size()) // ambiguites\n        {\n          Double tolerance = 0;\n          for(UInt i=0; i<Naa.rows(); i++)\n            tolerance = std::max(tolerance, std::fabs(Naa(i,i)));\n          GnssLambda::Transformation Z(Naa.rows());\n          UInt rank = GnssLambda::choleskyReversePivot(Naa, Z, 0, 1e-8*Naa.rows()*tolerance, FALSE/*timing*/);\n          isAmbi = Vector(Naa.rows());\n          isAmbi.row(0, rank).fill(1.);\n          isAmbi = Z.transformBack(isAmbi);\n        }\n      } // if(isMaster)\n      Parallel::broadCast(isTrans, 0, normalEquationInfo.comm);\n      Parallel::broadCast(isAmbi,  0, normalEquationInfo.comm);\n\n      // store estimable float biases at transmitters\n      // --------------------------------------------\n      for(UInt i=0; i<idTypeTrans.size(); i++)\n        if(isTrans(i))\n          paraTrans.at(idTypeTrans.at(i).first)->types.push_back(idTypeTrans.at(i).second);\n\n      // store estimable ambiguities\n      // ---------------------------\n      for(auto &info : ambiguityInfos)\n        if((info.idxAmbi != NULLINDEX) && isAmbi(info.idxAmbi))\n          info.typesNew.push_back(info.typesFreqSys.front() & ~GnssType::ATTRIBUTE);\n    } // for(typeFreqSys)\n\n    // parameters names of float biases at transmitters\n    // ------------------------------------------------\n    UInt countParaTrans = 0;\n    for(auto para : paraTrans)\n      if(para && para->types.size())\n      {\n        std::sort(para->types.begin(), para->types.end());\n        para->Bias = Matrix(para->types.size(), para->types.size());\n        for(UInt i=0; i<para->types.size(); i++)\n          para->Bias(i, i) = para->types.at(i).wavelength();\n        std::vector<ParameterName> parameterNames(para->types.size());\n        for(UInt i=0; i<para->types.size(); i++)\n          parameterNames.at(i) = ParameterName(para->trans->name(), \"phaseBias(\"+para->types.at(i).str()+\")\");\n        para->index = normalEquationInfo.parameterNamesTransmitter(para->trans->idTrans(), parameterNames);\n        countParaTrans += parameterNames.size();\n      }\n\n    // ambiguity parameters names\n    // --------------------------\n    // sort in temporal order\n    std::stable_sort(ambiguityInfos.begin(), ambiguityInfos.end(), [](const AmbiguityInfo &a, const AmbiguityInfo &b) {return (a.idEpochStart+a.idEpochEnd) < (b.idEpochStart+b.idEpochEnd);});\n    UInt countParaAmbi = 0;\n    for(auto &info : ambiguityInfos)\n    {\n      std::sort(info.typesNew.begin(), info.typesNew.end());\n      if(info.typesNew != info.typesAmbiguity)\n        info.parameterCount = info.typesNew.size();\n\n      // parameter names\n      std::vector<ParameterName> parameterNames;\n      ParameterName name(gnss->receivers.at(info.idRecv)->name()+\".\"+gnss->transmitters.at(info.idTrans)->name(),\n                         \"ambiguity\", \"\", gnss->times.at(info.idEpochStart), gnss->times.at(info.idEpochEnd));\n      std::string typeStr;\n      for(auto type : info.typesNew)\n        typeStr += type.str().substr(0,2);\n      for(UInt i=0; i<info.parameterCount; i++)\n        parameterNames.push_back(ParameterName(name.object, name.type+(i+1)%\"%iof\"s+info.parameterCount%\"%i(\"s+typeStr+\")\", name.temporal, name.interval));\n      GnssParameterIndex index = normalEquationInfo.parameterNamesAmbiguity((info.idEpochStart+info.idEpochEnd)/2, info.idRecv, info.idTrans, parameterNames);\n      countParaAmbi += parameterNames.size();\n\n      if(info.ambi)\n      {\n        info.ambi->index     = index;\n        info.ambi->isInteger = gnss->receivers.at(info.idRecv)->integerAmbiguities;\n        if(info.ambi->types != info.typesNew)\n        {\n          info.ambi->types = info.typesNew;\n          info.ambi->T     = GnssLambda::phaseDecorrelation(info.ambi->types, gnss->receivers.at(info.idRecv)->wavelengthFactor, 1.);\n          info.ambi->value = Vector(info.ambi->T.columns());\n        }\n      }\n    }\n\n    if(countParaTrans) logInfo<<countParaTrans%\"%9i transmitter phase bias parameters\"s<<Log::endl;\n    if(countParaRecv)  logInfo<<countParaRecv% \"%9i receiver phase bias parameters\"s<<Log::endl;\n    if(countParaAmbi)  logInfo<<countParaAmbi% \"%9i ambiguity parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationAmbiguities::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    // float bias at transmitter\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(auto para : paraTrans)\n        if(para && para->index)\n          copy(leastSquares(Matrix(para->Bias), para->trans->signalBias.compute(para->types)), x0.row(normalEquationInfo.index(para->index), para->Bias.columns()));\n\n    // float bias at receiver\n    for(auto para : paraRecv)\n      if(para && para->index && para->recv->isMyRank())\n        copy(leastSquares(Matrix(para->Bias), para->recv->signalBias.compute(para->types)), x0.row(normalEquationInfo.index(para->index), para->Bias.columns()));\n\n    // ambiguities\n    for(auto ambi : getAmbiguities())\n      if(ambi->index)\n        copy(ambi->value, x0.row(normalEquationInfo.index(ambi->index), ambi->value.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationAmbiguities::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    // float bias at transmitter\n    auto paraTrans = this->paraTrans.at(eqn.transmitter->idTrans());\n    if(paraTrans && paraTrans->index)\n    {\n      UInt idx;\n      MatrixSlice Design(A.column(paraTrans->index));\n      for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n        if(eqn.typesTransmitted.at(idType).isInList(paraTrans->types, idx))\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit+ eqn.types.size() + idType), paraTrans->Bias.row(idx), Design);\n    }\n\n    // float bias at receiver\n    auto paraRecv = this->paraRecv.at(eqn.receiver->idRecv());\n    if(paraRecv && paraRecv->index)\n    {\n      UInt idx;\n      MatrixSlice Design(A.column(paraRecv->index));\n      for(UInt idType=0; idType<eqn.types.size(); idType++)\n        if(eqn.types.at(idType).isInList(paraRecv->types, idx))\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + idType), paraRecv->Bias.row(idx), Design);\n    }\n\n    // ambiguities\n    if(eqn.track && eqn.track->ambiguity)\n    {\n      const Ambiguity *ambiguity = dynamic_cast<Ambiguity*>(eqn.track->ambiguity);\n      if(ambiguity->index)\n      {\n        UInt idx;\n        MatrixSlice Design(A.column(ambiguity->index));\n        for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n          if(eqn.typesTransmitted.at(idType).isInList(ambiguity->types, idx))\n            matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + eqn.types.size() + idType), ambiguity->T.row(idx), Design);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationAmbiguities::ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals,\n                                                        std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                                                        const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                                                        const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &isNotFixed, Double &sigma)> &searchInteger)\n{\n  try\n  {\n    const UInt block0 = normalEquationInfo.blockAmbiguity();\n    const UInt index0 = normalEquationInfo.blockIndex(block0);\n    const UInt dim    = normalEquationInfo.parameterCount()-index0;\n    Double sigmaFloat = sqrt(lPl/obsCount);\n    if(dim == 0)\n      return sigmaFloat;\n\n    // apriori float ambiguities x0\n    // ----------------------------\n    Vector x0(dim);\n    Vector isInteger(dim);\n    for(auto ambi : getAmbiguities())\n      if(ambi->index && ambi->value.size())\n      {\n        const UInt index = normalEquationInfo.index(ambi->index) - index0;\n        copy(ambi->value, x0.row(index, ambi->value.rows()));\n        if(ambi->isInteger &&\n           selectedTransmitters.at(ambi->track->transmitter->idTrans()) &&\n           selectedReceivers.at(ambi->track->receiver->idRecv()))\n          isInteger.row(index, ambi->value.rows()).fill(1);\n      }\n    Parallel::reduceSum(x0,        0, normalEquationInfo.comm);\n    Parallel::reduceSum(isInteger, 0, normalEquationInfo.comm);\n    Parallel::broadCast(isInteger, 0, normalEquationInfo.comm);\n\n    Vector isNotResolved(dim, 1.);\n    if(!isStrictlyZero(isInteger))\n    {\n      // right hand side and diagonal\n      Vector rhs(dim);\n      Vector diagonal(dim);\n      for(UInt i=block0; i<normals.blockCount(); i++)\n      {\n        copy(n.at(i), rhs.row(normals.blockIndex(i)-index0, normals.blockSize(i)));\n        if(normals.isMyRank(i,i))\n        {\n          Matrix &N = normals.N(i,i);\n          for(UInt k=0; k<N.rows(); k++)\n            diagonal(normals.blockIndex(i)-index0+k) = isInteger(normals.blockIndex(i)-index0+k) ? N(k,k) : 0;\n        }\n      }\n      Parallel::reduceSum(diagonal, 0, normalEquationInfo.comm);\n      Parallel::broadCast(diagonal, 0, normalEquationInfo.comm);\n\n      // sort float ambiguites to begin and accurate integer ambiguities to end\n      // ----------------------------------------------------------------------\n      GnssLambda::Transformation Z(dim);\n      std::vector<UInt> index(dim);\n      std::iota(index.begin(), index.end(), 0);\n      for(UInt i=0; i<dim; i++)\n        if(isInteger(i))\n        {\n          UInt idxMin = i;\n          for(UInt k=i+1; k<dim; k++)\n            if(diagonal(k) < diagonal(idxMin))\n              idxMin = k;\n          if(i == idxMin)\n            continue;\n          std::swap(diagonal(i),  diagonal(idxMin));\n          std::swap(isInteger(i), isInteger(idxMin));\n          std::swap(index.at(i),  index.at(idxMin));\n          Z.swap(i, idxMin);\n        }\n\n      logStatus<<\"- reorder normals of integer part\"<<Log::endl;\n      const UInt countInteger = static_cast<UInt>(sum(isInteger));\n      const UInt startInteger = dim - countInteger;\n      MatrixDistributed normalsAmbi = normals;\n      normalsAmbi.eraseBlocks(0, block0);\n      normalsAmbi.reorder(index, {0, startInteger, dim}, /*rank*/[](UInt, UInt, UInt){return 0;});\n\n      // perform cholesky for float part of the normals\n      // ----------------------------------------------\n      logStatus<<\"- cholesky normals of integer part\"<<Log::endl;\n      if(startInteger > 0)\n        normalsAmbi.cholesky(FALSE/*timing*/, 0, 1, TRUE/*collect*/);\n      if(normalsAmbi.isMyRank(1,1))\n        GnssLambda::choleskyReversePivot(normalsAmbi.N(1,1), Z, startInteger, 0., TRUE/*timing*/);  // Z is now only valid at master\n      // permuted normals: Nx=rhs => (Z^-T W^T W Z^-1) Zx = Z^-T*rhs with the orthogonal permutation matrix Z = Z^-T\n\n      // float solution\n      // --------------\n      rhs = Z.transform(rhs);  // only valid at master (Z = Z^-T)\n      x0  = Z.transform(x0);   // only valid at master\n      normalsAmbi.triangularTransSolve(rhs);\n      Vector dxFloat = rhs;\n      sigmaFloat = std::sqrt((lPl-quadsum(rhs))/(obsCount-dim));\n      normalsAmbi.triangularSolve(dxFloat);\n\n      // inverse of cholesky\n      // -------------------\n      normalsAmbi.choleskyInverse(FALSE/*timing*/, 1, normalsAmbi.blockCount()-1);\n\n      // xInteger = LAMBDA(W, xFloat)\n      // ============================\n      Vector dxInteger(dim);\n      if(Parallel::isMaster(normalEquationInfo.comm))\n      {\n        // decorrelate integer ambiguities (may take a while)\n        // -------------------------------------------------\n        logStatus<<\"- decorrelate ambiguities (may take a while)\"<<Log::endl;\n        Matrix &W(normalsAmbi.N(1,1));\n        GnssLambda::Transformation T(W.rows());\n        const Vector d = GnssLambda::choleskyTransform(W, T, TRUE/*timing*/);\n\n        // check for NANs\n        for(UInt i=0; i<W.rows(); i++)\n          for(UInt k=i; k<W.rows(); k++)\n            if(std::isnan(W(i,k)))\n              throw(Exception(\"Cholesky matrix contains NANs\"));\n        for(UInt i=0; i<d.rows(); i++)\n          if(std::isnan(d(i)))\n            throw(Exception(\"diagonal vector d contains NANs\"));\n\n        // resolve ambiguities\n        // -------------------\n        logStatus<<\"- search integer (blocked algorithm)\"<<Log::endl;\n        Vector notResolved;\n        Double sigma;\n        Vector xInteger = searchInteger(T.transform((dxFloat+x0).row(startInteger, countInteger)), W, d, notResolved, sigma);\n        logInfo<<\"  Ambiguity fixing norm = \"<<sigma%\"%3.2f\"s<<Log::endl;\n        logInfo<<\"  \"<<sum(notResolved)%\"%4i of \"s<<notResolved.rows()%\"%i transformed ambiguities not resolved (\"s<<(100.*sum(notResolved)/notResolved.rows())%\"%.1f%%)\"s<<Log::endl;\n        logInfo<<\"  \"<<sum(T.distributeBack(notResolved))%\"%4i remaining float ambiguities\"s<<Log::endl;\n\n        copy(T.distributeBack(notResolved), isNotResolved.row(startInteger, countInteger));\n        copy(T.transformBack(xInteger) - x0.row(startInteger, countInteger), dxInteger.row(startInteger, countInteger));\n        for(UInt i=0; i<dxInteger.rows(); i++)\n          if(isNotResolved(i))\n            dxInteger(i) = 0.;\n      } // if(isMaster)\n      // =================================================\n\n      dxInteger     = Z.transformBack(dxInteger);\n      isNotResolved = Z.distributeBack(isNotResolved);\n      Parallel::broadCast(dxInteger,     0, normalEquationInfo.comm);\n      Parallel::broadCast(isNotResolved, 0, normalEquationInfo.comm);\n\n      // mark resolved ambiguities\n      for(auto ambi : getAmbiguities())\n        if(ambi->index && ambi->value.size() && ambi->isInteger)\n        {\n          ambi->resolved = Vector(ambi->value.rows(), 1.);\n          const UInt index = normalEquationInfo.index(ambi->index) - index0;\n          for(UInt i=0; i<ambi->resolved.rows(); i++)\n            if(isNotResolved(index+i))\n              ambi->resolved(i) = 0;\n        }\n\n      // Remove solved integer ambiguities from the right hand side n -= N*(x_integer-x0)\n      // --------------------------------------------------------------------------------\n      Vector dn(dxInteger.rows());\n      for(UInt i=block0; i<normals.blockCount(); i++)\n        if(normals.isMyRank(i,i))\n          matMult(1., normals.N(i,i), dxInteger.row(normals.blockIndex(i)-index0, normals.blockSize(i)), dn.row(normals.blockIndex(i)-index0, normals.blockSize(i)));\n      for(UInt i=block0; i<normals.blockCount(); i++)\n        for(UInt k=i+1; k<normals.blockCount(); k++)\n          if(normals.isMyRank(i,k))\n          {\n            matMult(1., normals.N(i,k),         dxInteger.row(normals.blockIndex(k)-index0, normals.blockSize(k)), dn.row(normals.blockIndex(i)-index0, normals.blockSize(i)));\n            matMult(1., normals.N(i,k).trans(), dxInteger.row(normals.blockIndex(i)-index0, normals.blockSize(i)), dn.row(normals.blockIndex(k)-index0, normals.blockSize(k)));\n          }\n      Parallel::reduceSum(dn, 0, normalEquationInfo.comm);\n      if(Parallel::isMaster(normalEquationInfo.comm))\n        for(UInt i=block0; i<normals.blockCount(); i++)\n        {\n          lPl     += inner(dxInteger.row(normals.blockIndex(i)-index0, normals.blockSize(i)), dn.row(normals.blockIndex(i)-index0, normals.blockSize(i)))\n                     -2.*inner(dxInteger.row(normals.blockIndex(i)-index0, normals.blockSize(i)), n.at(i));\n          n.at(i) -= dn.row(normals.blockIndex(i)-index0, normals.blockSize(i));\n        }\n\n      // Integer ambiguities are estimated independently with high weight\n      // ----------------------------------------------------------------\n      const Double weightInteger = std::pow(1./0.001, 2); // [1/cycles^2]\n      for(UInt i=block0; i<normals.blockCount(); i++)\n        for(UInt z=0; z<normals.blockSize(i); z++)\n          if(isNotResolved(normals.blockIndex(i)+z-index0) == 0.)\n          {\n            for(UInt k=block0; k<=i; k++)\n              if(normals.isMyRank(k,i))\n                normals.N(k,i).column(z).setNull(); // set column 0\n            for(UInt k=i; k<normals.blockCount(); k++)\n              if(normals.isMyRank(i,k))\n                normals.N(i,k).row(z).setNull();    // set row 0\n            if(normals.isMyRank(i,i))\n              normals.N(i,i)(z,z) = weightInteger;\n            if(Parallel::isMaster(normalEquationInfo.comm))\n              n.at(i)(z,0) = weightInteger * dxInteger(normals.blockIndex(i)+z-index0);\n          }\n    } // if(some resolvable)\n\n    // solve (forward step)\n    // --------------------\n    normals.cholesky(FALSE/*timing*/, block0, normals.blockCount()-block0, TRUE/*collect*/);\n    normals.triangularTransSolve(n, block0, normals.blockCount()-block0, TRUE/*collect*/); // forward step\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(UInt i=block0; i<normals.blockCount(); i++)\n        for(UInt z=0; z<normals.blockSize(i); z++)\n          if(isNotResolved(normals.blockIndex(i)+z-index0))\n          {\n            lPl      -= std::pow(n.at(i)(z,0), 2); // lPl = lPl - n1' N1^(-1) n1\n            obsCount -= 1;\n          }\n\n    return sigmaFloat;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationAmbiguities::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    // float bias at transmitter\n    // -------------------------\n    Double maxChange = 0;\n    Gnss::InfoParameterChange infoTrans(\"cyc\");\n    for(auto para : paraTrans)\n      if(para && para->index)\n      {\n        const Vector dx    = x.row(normalEquationInfo.index(para->index), para->types.size());\n        const Vector dBias = para->Bias * dx;\n        for(UInt idType=0; idType<para->types.size(); idType++)\n          para->trans->signalBias.biases.at(GnssType::index(para->trans->signalBias.types, para->types.at(idType))) += dBias(idType);\n        for(UInt k=0; k<dx.rows(); k++)\n          if(infoTrans.update(dx(k)))\n            infoTrans.info = \"phase bias transmitter (\"+normalEquationInfo.parameterNames().at(normalEquationInfo.index(para->index)+k).str()+\")\";\n      }\n    infoTrans.synchronizeAndPrint(normalEquationInfo.comm, 0.19, maxChange); // cycles -> meter\n\n    // float bias at receiver\n    // ----------------------\n    Gnss::InfoParameterChange infoRecv(\"cyc\");\n    for(auto para : paraRecv)\n      if(para && para->index)\n      {\n        const Vector dx    = x.row(normalEquationInfo.index(para->index), para->Bias.columns());\n        const Vector dBias = para->Bias * dx;\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          para->recv->signalBias.biases.at(GnssType::index(para->recv->signalBias.types, para->types.at(idType))) += dBias(idType);\n        for(UInt k=0; k<dx.rows(); k++)\n          if(infoRecv.update(dx(k)))\n            infoRecv.info = \"phase bias receiver (\"+normalEquationInfo.parameterNames().at(normalEquationInfo.index(para->index)+k).str()+\")\";\n      }\n    infoRecv.synchronizeAndPrint(normalEquationInfo.comm, 0.19, maxChange); // cycles -> meter\n\n    // ambiguities\n    // -----------\n    auto ambiguities = getAmbiguities();\n    Gnss::InfoParameterChange info(\"cyc\");\n    for(auto ambi : ambiguities)\n      if(ambi->index)\n      {\n        const Vector dx = x.row(normalEquationInfo.index(ambi->index), ambi->value.rows());\n        ambi->value += dx;\n        for(UInt k=0; k<dx.rows(); k++)\n          if(info.update(dx(k)))\n            info.info = \"ambiguity (\"+normalEquationInfo.parameterNames().at(normalEquationInfo.index(ambi->index)+k).str()+\")\";\n      }\n    info.synchronizeAndPrint(normalEquationInfo.comm, 0.19, maxChange); // cycles -> meter\n\n    // remove integer part from observations\n    // -------------------------------------\n    for(auto ambi : ambiguities)\n      if(ambi->value.size())\n      {\n        Vector x(ambi->value.rows());\n        for(UInt i=0; i<x.rows(); i++)\n          x(i) = std::round(ambi->value(i));\n        ambi->value -= x;\n        ambi->track->removeAmbiguitiesFromObservations(ambi->types, Vector(ambi->T*x));\n      }\n\n    // remove resolved ambiguities\n    // ---------------------------\n    for(auto ambi : ambiguities)\n      if(ambi->resolved.size())\n      {\n        const UInt remove = static_cast<UInt>(sum(ambi->resolved));\n        Matrix T(ambi->T.rows(), ambi->T.columns() - remove);\n        Vector value(ambi->value.rows() - remove);\n        UInt idx = 0;\n        for(UInt i=0; i<ambi->value.rows(); i++)\n          if(ambi->resolved(i) == 0.)\n          {\n            copy(ambi->T.column(i), T.column(idx));\n            value(idx) = ambi->value(i);\n            idx++;\n          }\n        ambi->T        = T;\n        ambi->value    = value;\n        ambi->resolved = Vector();\n      }\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVector GnssParametrizationAmbiguities::Ambiguity::ambiguities(const std::vector<GnssType> &types) const\n{\n  try\n  {\n    Vector value(types.size());\n    UInt idx;\n    if(this->value.size())\n      for(UInt idType=0; idType<types.size(); idType++)\n        if(types.at(idType).isInList(this->types, idx))\n          value(idType) = (T.row(idx) * this->value)(0,0);\n    return value;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationAmbiguities.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationAmbiguities.h\n*\n* @brief Integer and float ambiguities.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONAMBIGUITIES__\n#define __GROOPS_GNSSPARAMETRIZATIONAMBIGUITIES__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationAmbiguities = R\"(\n\\subsection{Ambiguities}\\label{gnssParametrizationType:ambiguities}\nSets up an ambiguity parameter for each track and phase observation type.\n\\begin{equation}\n  [L\\nu a]_r^s(t) = \\dots + \\text{bias}[L\\nu a]^s + \\text{bias}[L\\nu a]_r + \\lambda[L\\nu] N[L\\nu a]_r^s\n\\end{equation}\nAs the phase observations contain a float bias at transmitter/receiver level, not all ambiguities\nare resolvable to integer values. The number of resolvable ambiguities can be increased with\nknown phase biases read from file via \\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\nIn this case, \\configClass{estimateTransmitter/ReceiverPhaseBias}{platformSelectorType} should\nnot be used for the corresponding transmitters and receivers.\n\nIn case of GLONASS, the phase biases at receiver level differ between different frequency channels\n(frequency division multiple access, FDMA) and for each channel an extra float phase bias is estimated.\nWith \\config{linearGlonassBias} a linear relationship between bias and frequency channel is assumed,\nwhich reduces the number of float bias parameters and increases the number of resolvable integer ambiguities.\n\nThe integer ambiguities can be resolved and fixed in\n\\configClass{GnssProcessing:processingStep:resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}.\nResolved integer ambiguities are not estimated as unknown parameters in\n\\configClass{gnssProcessingStepType:estimate}{gnssProcessingStepType} anymore\nand are removed from the system of normal equations.\n\nThe estimated phase biases can be written to files in\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:phaseBias(<gnssType>)::|,\n\\item \\verb|<prn>:phaseBias(<gnssType>)::|,\n\\item \\verb|<station>.<prn>:ambiguity<index>of<count>(<GnssTypes>)::<track interval>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssLambda.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Integer and float ambiguities.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationAmbiguities : public GnssParametrizationBase\n{\n  // float phase biases\n  class ParameterRecv\n  {\n  public:\n    GnssReceiverPtr       recv;\n    GnssParameterIndex    index;\n    std::vector<GnssType> types;\n    Matrix                Bias;\n  };\n\n  class ParameterTrans\n  {\n  public:\n    GnssTransmitterPtr    trans;\n    GnssParameterIndex    index;\n    std::vector<GnssType> types;\n    Matrix                Bias;\n  };\n\n  class Ambiguity : public GnssAmbiguity\n  {\n  public:\n    std::vector<GnssType> types;\n    Matrix                T;          // Matrix to transform ambiguities to observations [cycles -> m]\n    Vector                value;      // ambiguities in cycles\n    GnssParameterIndex    index;      // index in the parameter vector\n    Vector                resolved;\n    Bool                  isInteger;\n\n    explicit Ambiguity(GnssTrack *track) : GnssAmbiguity(track) {}\n    Vector ambiguities(const std::vector<GnssType> &types) const override;\n  };\n\n  class AmbiguityInfo; // to share information between processes\n\n  Gnss                           *gnss;\n  std::string                     name;\n  PlatformSelectorPtr             selectTransmitters, selectReceivers;\n  std::vector<ParameterTrans*>    paraTrans;\n  std::vector<ParameterRecv*>     paraRecv;\n  Bool                            isLinearBias;\n\n  std::vector<Ambiguity*> getAmbiguities() const;\n\npublic:\n  GnssParametrizationAmbiguities(Config &config);\n ~GnssParametrizationAmbiguities();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                          const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                          const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger) override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationClocks.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationClocks.h\n*\n* @brief Clocks errors.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationClocks.h\"\n\n/***********************************************/\n\nGnssParametrizationClocks::GnssParametrizationClocks(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                       name,                       Config::OPTIONAL, \"parameter.clocks\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",         selectTransmitters,         Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectReceivers\",            selectReceivers,            Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileClockTransmitter\", fileNameTransmitter,        Config::OPTIONAL, \"\", \"variable {prn} available\");\n    readConfig(config, \"outputfileClockReceiver\",    fileNameReceiver,           Config::OPTIONAL, \"\", \"variable {station} available\");\n    readConfig(config, \"nameConstraint\",             nameConstraint,             Config::OPTIONAL, \"constraintEpoch.clocks\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmittersZeroMean\", selectTransmittersZeroMean, Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectReceiversZeroMean\",    selectReceiversZeroMean,    Config::DEFAULT,  \"\", \"\");\n    readConfig(config, \"sigmaZeroMeanConstraint\",    sigmaZeroMean,              Config::DEFAULT,  \"0.0001\", \"(0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->gnss                   = gnss;\n    selectedTransmitters         = gnss->selectTransmitters(selectTransmitters);\n    selectedReceivers            = gnss->selectReceivers(selectReceivers);\n    selectedTransmittersZeroMean = gnss->selectTransmitters(selectTransmittersZeroMean);\n    selectedReceiversZeroMean    = gnss->selectReceivers(selectReceiversZeroMean);\n\n    x0Trans.resize(gnss->transmitters.size());\n    if(Parallel::isMaster(comm))\n      for(auto trans : gnss->transmitters)\n      {\n        const UInt idTrans = trans->idTrans();\n        if(trans->useable() && selectedTransmittersZeroMean.at(idTrans))\n        {\n          x0Trans.at(idTrans).resize(gnss->times.size(), 0);\n          for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n            if(trans->useable(idEpoch))\n              x0Trans.at(idTrans).at(idEpoch) = LIGHT_VELOCITY * trans->clockError(idEpoch);\n        }\n      }\n\n    x0Recv.resize(gnss->receivers.size());\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->isMyRank() && selectedReceiversZeroMean.at(idRecv))\n      {\n        x0Recv.at(idRecv).resize(gnss->times.size(), 0);\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n          if(recv->useable(idEpoch))\n            x0Recv.at(idRecv).at(idEpoch) = LIGHT_VELOCITY * recv->clockError(idEpoch);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::requirements(GnssNormalEquationInfo &normalEquationInfo,\n                                             std::vector<UInt> &/*transCount*/, std::vector<UInt> &transCountEpoch,\n                                             std::vector<UInt> &/*recvCount*/,  std::vector<UInt> &recvCountEpoch)\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    // transmitter epochs\n    if(!normalEquationInfo.isEachReceiverSeparately)\n      for(auto trans : gnss->transmitters)\n        if(trans->useable() && selectedTransmitters.at(trans->idTrans()))\n          transCountEpoch.at(trans->idTrans())++;\n\n    // receiver clocks\n    for(auto recv : gnss->receivers)\n      if(recv->useable() && normalEquationInfo.estimateReceiver.at(recv->idRecv()) && selectedReceivers.at(recv->idRecv()))\n        recvCountEpoch.at(recv->idRecv())++;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    indexTrans.clear();\n    indexTrans.resize(gnss->transmitters.size());\n    indexRecv.clear();\n    indexRecv.resize(gnss->receivers.size());\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countParaTrans = 0;\n    if(!normalEquationInfo.isEachReceiverSeparately)\n      for(auto trans : gnss->transmitters)\n      {\n        const UInt idTrans = trans->idTrans();\n        if(trans->useable() && selectedTransmitters.at(idTrans))\n        {\n          indexTrans.at(idTrans).resize(gnss->times.size());\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(trans->useable(idEpoch))\n            {\n              indexTrans.at(idTrans).at(idEpoch) = normalEquationInfo.parameterNamesEpochTransmitter(idEpoch, idTrans, {ParameterName(trans->name(), \"clock\", \"\", gnss->times.at(idEpoch))});\n              countParaTrans++;\n            }\n        }\n      }\n    if(countParaTrans)\n      logInfo<<countParaTrans%\"%9i transmitter clock error parameters\"s<<Log::endl;\n\n    UInt countParaRecv = 0;\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->useable() && normalEquationInfo.estimateReceiver.at(idRecv) && selectedReceivers.at(idRecv))\n      {\n        indexRecv.at(idRecv).resize(gnss->times.size());\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(recv->useable(idEpoch))\n          {\n            indexRecv.at(idRecv).at(idEpoch) = normalEquationInfo.parameterNamesEpochReceiver(idEpoch, idRecv, {ParameterName(recv->name(), \"clock\", \"\", gnss->times.at(idEpoch))});\n            countParaRecv++;\n          }\n      }\n    }\n    if(countParaRecv)\n      logInfo<<countParaRecv%\"%9i receiver clock error parameters\"s<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && sigmaZeroMean\n                    && (countParaTrans+countParaRecv) &&  !normalEquationInfo.isEachReceiverSeparately;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(auto trans : gnss->transmitters)\n      {\n        const UInt idTrans = trans->idTrans();\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n            x0(normalEquationInfo.index(indexTrans.at(idTrans).at(idEpoch)), 0) = LIGHT_VELOCITY * trans->clockError(idEpoch);\n      }\n\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n      {\n        const UInt idRecv = recv->idRecv();\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n            x0(normalEquationInfo.index(indexRecv.at(idRecv).at(idEpoch)), 0) = LIGHT_VELOCITY * recv->clockError(idEpoch);\n      }\n    }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    // transmitter clock\n    if(indexTrans.at(eqn.transmitter->idTrans()).size() && indexTrans.at(eqn.transmitter->idTrans()).at(eqn.idEpoch))\n      copy(eqn.A.column(GnssObservationEquation::idxClockTrans,1), A.column(indexTrans.at(eqn.transmitter->idTrans()).at(eqn.idEpoch)));\n\n    // receiver clock\n    if(indexRecv.at(eqn.receiver->idRecv()).size() && indexRecv.at(eqn.receiver->idRecv()).at(eqn.idEpoch))\n      copy(eqn.A.column(GnssObservationEquation::idxClockRecv,1), A.column(indexRecv.at(eqn.receiver->idRecv()).at(eqn.idEpoch)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(!applyConstraint)\n      return;\n\n    // zero-mean constraint of clocks\n    // ------------------------------\n    UInt countTrans = 0, countRecv = 0;\n    for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n      if(selectedTransmittersZeroMean.at(idTrans) && indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n        countTrans++;\n    for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n      if(selectedReceiversZeroMean.at(idRecv) && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n        countRecv++;\n    UInt count = countTrans + countRecv;\n    if(!count)\n      return;\n\n    // collect apriori clock errors\n    Vector lRecvEpoch;\n    if(countRecv)\n    {\n      lRecvEpoch = Vector(gnss->receivers.size());\n      for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n        if(selectedReceiversZeroMean.at(idRecv) && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch) && gnss->receivers.at(idRecv)->isMyRank())\n          lRecvEpoch(idRecv) = x0Recv.at(idRecv).at(idEpoch) - LIGHT_VELOCITY*gnss->receivers.at(idRecv)->clockError(idEpoch);\n      Parallel::reduceSum(lRecvEpoch, 0, normalEquationInfo.comm);\n    }\n\n    if(Parallel::isMaster(normalEquationInfo.comm))\n    {\n      Vector           l(1);\n      GnssDesignMatrix A(normalEquationInfo, 1);\n      for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n        if(selectedTransmittersZeroMean.at(idTrans) && indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n        {\n          l(0) += (x0Trans.at(idTrans).at(idEpoch) - LIGHT_VELOCITY*gnss->transmitters.at(idTrans)->clockError(idEpoch))/count/sigmaZeroMean; // remove apriori value -> regularization towards 0\n          A.column(indexTrans.at(idTrans).at(idEpoch))(0,0) = 1./count/sigmaZeroMean;\n        }\n      for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n        if(selectedReceiversZeroMean.at(idRecv) && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n        {\n          l(0) += lRecvEpoch(idRecv)/count/sigmaZeroMean; // remove apriori value -> regularization towards 0\n          A.column(indexRecv.at(idRecv).at(idEpoch))(0,0) = 1./count/sigmaZeroMean;\n        }\n      GnssDesignMatrix::accumulateNormals(A, l, normals, n, lPl, obsCount);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationClocks::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange infoTrans(\"mm\");\n    for(auto trans : gnss->transmitters)\n    {\n      const UInt idTrans = trans->idTrans();\n      for(UInt idEpoch : normalEquationInfo.idEpochs)\n        if(indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n        {\n          const Double dClock = x(normalEquationInfo.index(indexTrans.at(idTrans).at(idEpoch)), 0);\n          trans->updateClockError(idEpoch, dClock/LIGHT_VELOCITY);\n          if(infoTrans.update(1e3*dClock))\n            infoTrans.info = \"clock transmitter (\"+trans->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n        }\n    }\n    infoTrans.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    Gnss::InfoParameterChange infoRecv(\"mm\");\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n      {\n        const UInt idRecv = recv->idRecv();\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n          {\n            const Double dClock = x(normalEquationInfo.index(indexRecv.at(idRecv).at(idEpoch)), 0);\n            recv->updateClockError(idEpoch, dClock/LIGHT_VELOCITY);\n            if(infoRecv.update(1e3*dClock))\n              infoRecv.info = \"clock receiver (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n          }\n      }\n    infoRecv.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocks::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameTransmitter.empty() && Parallel::isMaster(normalEquationInfo.comm))\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logStatus<<\"write transmitter clocks to files <\"<<fileNameTransmitter(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto trans : gnss->transmitters)\n      {\n        const UInt idTrans = trans->idTrans();\n        MiscValueArc arc;\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n          {\n            MiscValueEpoch epoch;\n            epoch.time  = gnss->times.at(idEpoch);\n            epoch.value = trans->clockError(idEpoch);\n            arc.push_back(epoch);\n          }\n        fileNameVariableList.setVariable(\"prn\", trans->name());\n        InstrumentFile::write(fileNameTransmitter(fileNameVariableList).appendBaseName(suffix), arc);\n      }\n    }\n\n    if(!fileNameReceiver.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write receiver clocks to files <\"<<fileNameReceiver(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto recv : gnss->receivers)\n        if(recv->isMyRank())\n        {\n          const UInt idRecv = recv->idRecv();\n          MiscValueArc arc;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n            {\n              MiscValueEpoch epoch;\n              epoch.time  = recv->times.at(idEpoch);\n              epoch.value = recv->clockError(idEpoch);\n              arc.push_back(epoch);\n            }\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          InstrumentFile::write(fileNameReceiver(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationClocks.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationClocks.h\n*\n* @brief Clocks errors.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONCLOCKS__\n#define __GROOPS_GNSSPARAMETRIZATIONCLOCKS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationClocks = R\"(\n\\subsection{Clocks}\\label{gnssParametrizationType:clocks}\nClock errors are estimated epoch-wise for each \\configClass{selectTransmitters/Receivers}{platformSelectorType}.\nNo clock errors are estimated if no valid observations are available (e.g. data gaps in the observations).\n\nIf all transmitters and receivers are selected by \\config{selectTransmitters} and \\config{selectReceivers} respectively,\nthese parameters will be lineary dependent which would lead to a rank deficiency in the normal equation\nmatrix. To circumvent this issue, the estimation requires an additional zero-mean constraint added in each epoch.\nThis is realized with an additional observation equation\n\\begin{equation}\n  0 = \\frac{1}{n_i + n_k} (\\sum_i \\Delta t^{s_i} + \\sum_k \\Delta t_{r_k})\n\\end{equation}\nsummed over all \\configClass{selectTransmitters/ReceiversZeroMean}{platformSelectorType}\nwith a standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:clock::<time>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Clocks errors.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationClocks : public GnssParametrizationBase\n{\n  Gnss                                        *gnss;\n  std::string                                  name, nameConstraint;\n  PlatformSelectorPtr                          selectTransmitters, selectReceivers;\n  PlatformSelectorPtr                          selectTransmittersZeroMean, selectReceiversZeroMean;\n  std::vector<Byte>                            selectedTransmitters, selectedReceivers;\n  std::vector<Byte>                            selectedTransmittersZeroMean, selectedReceiversZeroMean;\n  FileName                                     fileNameReceiver, fileNameTransmitter;\n  Bool                                         applyConstraint;\n  Double                                       sigmaZeroMean;\n  std::vector<std::vector<GnssParameterIndex>> indexTrans, indexRecv; // for each trans/recv and epoch\n  std::vector<std::vector<Double>>             x0Trans, x0Recv;       // for each trans/recv and epoch\n\npublic:\n  GnssParametrizationClocks(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                      std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n//***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationClocksModel.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationClocksModel.h\n*\n* @brief Clocks errors.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationClocksModel.h\"\n\n/***********************************************/\n\nGnssParametrizationClocksModel::GnssParametrizationClocksModel(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                       name,                       Config::OPTIONAL, \"parameter.clocks\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",         selectTransmitters,         Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectReceivers\",            selectReceivers,            Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileClockTransmitter\", fileNameTransmitter,        Config::OPTIONAL, \"\",    \"variable {prn} available\");\n    readConfig(config, \"outputfileClockReceiver\",    fileNameReceiver,           Config::OPTIONAL, \"\",    \"variable {station} available\");\n    readConfig(config, \"huber\",                      huber,                      Config::DEFAULT,  \"4\",   \"clock jumps > huber*sigma0 are downweighted\");\n    readConfig(config, \"huberPower\",                 huberPower,                 Config::DEFAULT,  \"1.5\", \"clock jumps > huber: sigma=(e/huber)^huberPower*sigma0\");\n    readConfig(config, \"nameConstraint\",             nameConstraint,             Config::OPTIONAL, \"constraintEpoch.clocksModel\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmittersZeroMean\", selectTransmittersZeroMean, Config::DEFAULT,  R\"([\"all\"])\", \"use these transmitters for zero-mean constraint\");\n    readConfig(config, \"selectReceiversZeroMean\",    selectReceiversZeroMean,    Config::DEFAULT,  \"\", \"use these receivers for zero-mean constraint\");\n    readConfig(config, \"sigmaZeroMeanConstraint\",    sigmaZeroMean,              Config::DEFAULT,  \"10\", \"(0 = unconstrained) sigma [m] for zero-mean constraint over all selected clocks\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->gnss                   = gnss;\n    selectedTransmitters         = gnss->selectTransmitters(selectTransmitters);\n    selectedReceivers            = gnss->selectReceivers(selectReceivers);\n    selectedTransmittersZeroMean = gnss->selectTransmitters(selectTransmittersZeroMean);\n    selectedReceiversZeroMean    = gnss->selectReceivers(selectReceiversZeroMean);\n\n    // determine apriori transmitter drift\n    // -----------------------------------\n    isMyRank     = Vector(gnss->transmitters.size());\n    clock0Trans  = Vector(gnss->transmitters.size());\n    drift0Trans  = Vector(gnss->transmitters.size());\n    sigma0Trans  = Vector(gnss->transmitters.size(), 0.02);\n    sigmaEpochTrans.resize(gnss->transmitters.size());\n    isFirstTrans.resize(gnss->transmitters.size(), TRUE);\n    for(auto trans : gnss->transmitters)\n    {\n      const UInt idTrans = trans->idTrans();\n      isMyRank(idTrans) = trans->useable() && ((idTrans % Parallel::size(comm)) == Parallel::myRank(comm));\n      if(isMyRank(idTrans))\n      {\n        sigmaEpochTrans.at(idTrans).resize(gnss->times.size(), 1.);\n\n        Vector l(gnss->times.size());\n        Matrix A(gnss->times.size(), 2);\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n          if(trans->useable(idEpoch))\n          {\n            l(idEpoch)    = LIGHT_VELOCITY * trans->clockError(idEpoch);\n            A(idEpoch, 0) = 1;\n            A(idEpoch, 1) = (gnss->times.at(idEpoch)-gnss->times.front()).seconds();\n          }\n        Vector x = leastSquares(Matrix(A), l);\n        clock0Trans(idTrans) = x(0);\n        drift0Trans(idTrans) = x(1);\n      }\n    }\n    driftTrans = drift0Trans;\n\n    // determine apriori receiver drift\n    // --------------------------------\n    clock0Recv = Vector(gnss->receivers.size());\n    drift0Recv  = Vector(gnss->receivers.size());\n    sigma0Recv = Vector(gnss->receivers.size(), 0.05*LIGHT_VELOCITY); // 50 ms\n    sigmaEpochRecv.resize(gnss->receivers.size());\n    isFirstRecv.resize(gnss->receivers.size(), TRUE);\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->isMyRank())\n      {\n        sigmaEpochRecv.at(idRecv).resize(gnss->times.size(), 1.);\n\n        Vector l(gnss->times.size());\n        Matrix A(gnss->times.size(), 2);\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n          if(recv->useable(idEpoch))\n          {\n            l(idEpoch)    = LIGHT_VELOCITY * recv->clockError(idEpoch);\n            A(idEpoch, 0) = 1;\n            A(idEpoch, 1) = (gnss->times.at(idEpoch)-gnss->times.front()).seconds();\n          }\n        Vector x = leastSquares(Matrix(A), l);\n        clock0Recv(idRecv) = x(0);\n        drift0Recv(idRecv) = x(1);\n      }\n    }\n    driftRecv = drift0Recv;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::requirements(GnssNormalEquationInfo &normalEquationInfo,\n                                                  std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                                                  std::vector<UInt> &recvCount,  std::vector<UInt> &recvCountEpoch)\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    // transmitter epochs\n    if(!normalEquationInfo.isEachReceiverSeparately)\n      for(auto trans : gnss->transmitters)\n        if(trans->useable() && selectedTransmitters.at(trans->idTrans()))\n        {\n          transCountEpoch.at(trans->idTrans())++;\n          transCount.at(trans->idTrans())++; // to determine the drift\n        }\n\n    // receiver clocks\n    for(auto recv : gnss->receivers)\n      if(recv->useable() && normalEquationInfo.estimateReceiver.at(recv->idRecv()) && selectedReceivers.at(recv->idRecv()))\n      {\n        recvCountEpoch.at(recv->idRecv())++;\n        recvCount.at(recv->idRecv())++; // to determine the drift\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    indexTrans.clear();      indexTrans.resize(gnss->transmitters.size());\n    indexDriftTrans.clear(); indexDriftTrans.resize(gnss->transmitters.size());\n    indexRecv.clear();       indexRecv.resize(gnss->receivers.size());\n    indexDriftRecv.clear();  indexDriftRecv.resize(gnss->receivers.size());\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countParaTrans = 0;\n    if(!normalEquationInfo.isEachReceiverSeparately)\n      for(auto trans : gnss->transmitters)\n      {\n        const UInt idTrans = trans->idTrans();\n        if(trans->useable() && selectedTransmitters.at(idTrans))\n        {\n          indexTrans.at(idTrans).resize(gnss->times.size());\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(trans->useable(idEpoch))\n            {\n              indexTrans.at(idTrans).at(idEpoch) = normalEquationInfo.parameterNamesEpochTransmitter(idEpoch, idTrans, {ParameterName(trans->name(), \"clock\", \"\", gnss->times.at(idEpoch))});\n              countParaTrans++;\n            }\n          indexDriftTrans.at(idTrans) = normalEquationInfo.parameterNamesTransmitter(idTrans, {ParameterName(trans->name(), \"clockDrift\")});\n          countParaTrans++;\n        }\n      }\n    if(countParaTrans)\n      logInfo<<countParaTrans%\"%9i modeled transmitter clock error and drift parameters\"s<<Log::endl;\n\n    UInt countParaRecv = 0;\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->useable() && normalEquationInfo.estimateReceiver.at(idRecv) && selectedReceivers.at(idRecv))\n      {\n        indexRecv.at(idRecv).resize(gnss->times.size());\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(recv->useable(idEpoch))\n          {\n            indexRecv.at(idRecv).at(idEpoch) = normalEquationInfo.parameterNamesEpochReceiver(idEpoch, idRecv, {ParameterName(recv->name(), \"clock\", \"\", gnss->times.at(idEpoch))});\n            countParaRecv++;\n          }\n        indexDriftRecv.at(idRecv) = normalEquationInfo.parameterNamesReceiver(idRecv, {ParameterName(recv->name(), \"clockDrift\")});\n        countParaRecv++;\n      }\n    }\n    if(countParaRecv)\n      logInfo<<countParaRecv%\"%9i modeled receiver clock error and drift parameters\"s<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && sigmaZeroMean\n                    && (countParaTrans+countParaRecv);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto trans : gnss->transmitters)\n      if(isMyRank(trans->idTrans()))\n      {\n        const UInt idTrans = trans->idTrans();\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n            x0(normalEquationInfo.index(indexTrans.at(idTrans).at(idEpoch)), 0) = LIGHT_VELOCITY * trans->clockError(idEpoch);\n        if(indexDriftTrans.at(idTrans))\n          x0(normalEquationInfo.index(indexDriftTrans.at(idTrans)), 0) = driftTrans(idTrans);\n      }\n\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n      {\n        const UInt idRecv = recv->idRecv();\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n            x0(normalEquationInfo.index(indexRecv.at(idRecv).at(idEpoch)), 0) = LIGHT_VELOCITY * recv->clockError(idEpoch);\n        if(indexDriftRecv.at(idRecv))\n          x0(normalEquationInfo.index(indexDriftRecv.at(idRecv)), 0) = driftRecv(idRecv);\n      }\n    }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    // transmitter clock\n    if(indexTrans.at(eqn.transmitter->idTrans()).size() && indexTrans.at(eqn.transmitter->idTrans()).at(eqn.idEpoch))\n      copy(eqn.A.column(GnssObservationEquation::idxClockTrans,1), A.column(indexTrans.at(eqn.transmitter->idTrans()).at(eqn.idEpoch)));\n\n    // receiver clock\n    if(indexRecv.at(eqn.receiver->idRecv()).size() && indexRecv.at(eqn.receiver->idRecv()).at(eqn.idEpoch))\n      copy(eqn.A.column(GnssObservationEquation::idxClockRecv,1), A.column(indexRecv.at(eqn.receiver->idRecv()).at(eqn.idEpoch)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    // find next epoch\n    auto iter = std::upper_bound(normalEquationInfo.idEpochs.begin(), normalEquationInfo.idEpochs.end(), idEpoch);\n    if(iter != normalEquationInfo.idEpochs.end())\n    {\n      const UInt idEpochNext = *iter;\n\n      // clock model\n      // -----------\n      auto clockModel = [&](const std::function<Double(UInt)> &clockError, Double drift,\n                            const std::vector<GnssParameterIndex> &indexEpoch, const GnssParameterIndex &indexDrift,\n                            Double sigma0, const std::vector<Double> &sigmaEpoch)\n      {\n        const Double p  = 1./sigma0/sigmaEpoch.at(idEpoch);\n        const Double dt = (gnss->times.at(idEpochNext)-gnss->times.at(idEpoch)).seconds();\n        Vector l(1);\n        l(0) = p * (LIGHT_VELOCITY * (clockError(idEpochNext)-clockError(idEpoch)) - drift*dt);\n        GnssDesignMatrix A(normalEquationInfo, 1);\n        A.column(indexEpoch.at(idEpochNext))(0,0) = -p;\n        A.column(indexEpoch.at(idEpoch))(0,0)     = +p;\n        A.column(indexDrift)(0,0)                 = +p*dt;\n        GnssDesignMatrix::accumulateNormals(A, l, normals, n, lPl, obsCount);\n      };\n\n      // transmitters\n      for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n        if(isMyRank(idTrans) && indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch) && indexTrans.at(idTrans).at(idEpochNext))\n          clockModel(std::bind(&GnssTransmitter::clockError, gnss->transmitters.at(idTrans), std::placeholders::_1),\n                     driftTrans(idTrans), indexTrans.at(idTrans), indexDriftTrans.at(idTrans),sigma0Trans(idTrans), sigmaEpochTrans.at(idTrans));\n\n      // receivers\n      for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n        if(gnss->receivers.at(idRecv)->isMyRank() && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch) && indexRecv.at(idRecv).at(idEpochNext))\n          clockModel(std::bind(&GnssReceiver::clockError, gnss->receivers.at(idRecv), std::placeholders::_1),\n                     driftRecv(idRecv), indexRecv.at(idRecv), indexDriftRecv.at(idRecv), sigma0Recv(idRecv), sigmaEpochRecv.at(idRecv));\n    }\n\n    // zero-mean constraint of clocks\n    // ------------------------------\n    if(!applyConstraint || normalEquationInfo.isEachReceiverSeparately)\n      return;\n\n    UInt count = 0;\n    for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n      if(selectedTransmittersZeroMean.at(idTrans) && indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n        count++;\n    for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n      if(selectedReceiversZeroMean.at(idRecv) && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n        count++;\n    if(!count)\n      return;\n\n    // collect apriori clock errors\n    Double meanApriori = 0;\n    for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n      if(selectedTransmittersZeroMean.at(idTrans) && indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch) && isMyRank(idTrans))\n        meanApriori += LIGHT_VELOCITY*gnss->transmitters.at(idTrans)->clockError(idEpoch)\n                    -  (clock0Trans(idTrans) + drift0Trans(idTrans) * (gnss->times.at(idEpoch)-gnss->times.front()).seconds());\n    for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n      if(selectedReceiversZeroMean.at(idRecv) && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch) && gnss->receivers.at(idRecv)->isMyRank())\n        meanApriori += LIGHT_VELOCITY*gnss->receivers.at(idRecv)->clockError(idEpoch)\n                    -  (clock0Recv(idRecv) + drift0Recv(idRecv) * (gnss->times.at(idEpoch)-gnss->times.front()).seconds());\n    Parallel::reduceSum(meanApriori, 0, normalEquationInfo.comm);\n\n    if(!Parallel::isMaster(normalEquationInfo.comm))\n      return;\n\n    const Double pSum = 1./count/sigmaZeroMean; // weight;\n    Vector l(1);\n    l(0) = -meanApriori * pSum;  // remove apriori value -> regularization towards 0\n    GnssDesignMatrix A(normalEquationInfo, 1);\n    for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n      if(selectedTransmittersZeroMean.at(idTrans) && indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n        A.column(indexTrans.at(idTrans).at(idEpoch))(0,0) = pSum;\n    for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n      if(selectedReceiversZeroMean.at(idRecv) && indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n        A.column(indexRecv.at(idRecv).at(idEpoch))(0,0) = pSum;\n    GnssDesignMatrix::accumulateNormals(A, l, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationClocksModel::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    Gnss::InfoParameterChange infoTrans(\"mm\");\n    for(auto trans : gnss->transmitters)\n      if(indexTrans.at(trans->idTrans()).size())\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexTrans.at(trans->idTrans()).at(idEpoch))\n          {\n            const Double dClock = x(normalEquationInfo.index(indexTrans.at(trans->idTrans()).at(idEpoch)), 0);\n            trans->updateClockError(idEpoch, dClock/LIGHT_VELOCITY);\n            if(trans->useable(idEpoch) && infoTrans.update(1e3*dClock))\n              infoTrans.info = \"clock transmitter (\"+trans->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n          }\n\n    Gnss::InfoParameterChange infoRecv(\"mm\");\n    for(auto recv : gnss->receivers)\n      if(indexRecv.at(recv->idRecv()).size() && recv->isMyRank())\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexRecv.at(recv->idRecv()).at(idEpoch))\n          {\n            const Double dClock = x(normalEquationInfo.index(indexRecv.at(recv->idRecv()).at(idEpoch)), 0);\n            recv->updateClockError(idEpoch, dClock/LIGHT_VELOCITY);\n            if(recv->useable(idEpoch) && infoRecv.update(1e3*dClock))\n              infoRecv.info = \"clock receiver (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n          }\n\n    // transmitter drifts\n    Gnss::InfoParameterChange infoDriftTrans(\"cm/d\");\n    for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n      if(indexDriftTrans.at(idTrans) && isMyRank(idTrans))\n      {\n        // update drift parameter\n        const Double dDrift = x(normalEquationInfo.index(indexDriftTrans.at(idTrans)), 0);\n        driftTrans(idTrans) += dDrift;\n        if(infoDriftTrans.update(1e2*86400.*dDrift))\n          infoDriftTrans.info = \"clock drift transmitter (\"+gnss->transmitters.at(idTrans)->name()+\")\";\n      }\n\n    // receivers drifts\n    Gnss::InfoParameterChange infoDriftRecv(\"cm/d\");\n    for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n      if(indexDriftRecv.at(idRecv) && gnss->receivers.at(idRecv)->isMyRank())\n      {\n        const auto recv = gnss->receivers.at(idRecv);\n        // update drift parameter\n        Double dDrift = x(normalEquationInfo.index(indexDriftRecv.at(idRecv)), 0);\n        if(isFirstRecv.at(idRecv))\n        {\n          UInt count = 0;\n          Vector dDrifts(normalEquationInfo.idEpochs.size()-1);\n          for(UInt i=0; i<normalEquationInfo.idEpochs.size()-1; i++)\n          {\n            const UInt idEpoch     = normalEquationInfo.idEpochs.at(i);\n            const UInt idEpochNext = normalEquationInfo.idEpochs.at(i+1);\n            if(indexRecv.at(recv->idRecv()).at(idEpoch) && indexRecv.at(recv->idRecv()).at(idEpochNext))\n              dDrifts(count++) = LIGHT_VELOCITY/(gnss->times.at(idEpochNext)-gnss->times.at(idEpoch)).seconds()\n                               * (recv->clockError(idEpochNext)-recv->clockError(idEpoch));\n          }\n          dDrift = median(dDrifts.row(0,count));\n        }\n        driftRecv(idRecv) += dDrift;\n        if((sigma0Recv(idRecv) < 1) && infoDriftRecv.update(1e2*86400.*dDrift))\n          infoDriftRecv.info = \"clock drift receiver (\"+recv->name()+\")\";\n      }\n\n\n    // =================================\n\n    // determine variance of models\n    // ----------------------------\n    auto calcVariance = [&](const std::function<Double(UInt)> &clockError, Double drift,\n                            const std::vector<GnssParameterIndex> &indexEpoch, const GnssParameterIndex &indexDrift,\n                            Bool isFirstTime, Double &sigma0, std::vector<Double> &sigmaEpoch)\n    {\n      // compute model residuals\n      Vector e(normalEquationInfo.idEpochs.size()-1);\n      Vector r(normalEquationInfo.idEpochs.size()-1);\n      Double ePe = 0;\n      for(UInt i=0; i<normalEquationInfo.idEpochs.size()-1; i++)\n      {\n        const UInt idEpoch     = normalEquationInfo.idEpochs.at(i);\n        const UInt idEpochNext = normalEquationInfo.idEpochs.at(i+1);\n        if(!indexEpoch.at(idEpoch) || !indexEpoch.at(idEpochNext))\n          continue;\n\n        // residuals\n        const Double dt = (gnss->times.at(idEpochNext)-gnss->times.at(idEpoch)).seconds();\n        e(i) = std::fabs(LIGHT_VELOCITY * (clockError(idEpochNext) - clockError(idEpoch)) - drift*dt);\n\n        // redundancy\n        const Double p  = 1./sigma0/sigmaEpoch.at(idEpoch);\n        Matrix AWz(1, Wz.columns());\n        axpy(-p,    Wz.row(normalEquationInfo.index(indexEpoch.at(idEpochNext))), AWz);\n        axpy(+p,    Wz.row(normalEquationInfo.index(indexEpoch.at(idEpoch))),     AWz);\n        axpy(+p*dt, Wz.row(normalEquationInfo.index(indexDrift)),                 AWz);\n        ePe  += std::pow(e(i)*p, 2);\n        r(i)  = std::max(1-quadsum(AWz), 0.2);\n        e(i) /= std::sqrt(r(i));\n      }\n\n      // determine variances\n      sigma0 *= Vce::standardDeviation(ePe, sum(r), huber, huberPower);\n      if(isFirstTime)\n        sigma0 = 1.4826 * median(e);\n\n      for(UInt i=0; i<normalEquationInfo.idEpochs.size()-1; i++)\n      {\n        const UInt idEpoch = normalEquationInfo.idEpochs.at(i);\n        sigmaEpoch.at(idEpoch) = 1.;\n        if(e(i) > sigma0*huber)\n          sigmaEpoch.at(idEpoch) *= std::pow(e(i)/sigma0/huber, huberPower);\n      }\n    };\n\n    // transmitters\n    for(UInt idTrans=0; idTrans<indexTrans.size(); idTrans++)\n      if(indexTrans.at(idTrans).size() && isMyRank(idTrans))\n      {\n        calcVariance(std::bind(&GnssTransmitter::clockError, gnss->transmitters.at(idTrans), std::placeholders::_1),\n                     driftTrans(idTrans), indexTrans.at(idTrans), indexDriftTrans.at(idTrans),\n                     isFirstTrans.at(idTrans), sigma0Trans(idTrans), sigmaEpochTrans.at(idTrans));\n        isFirstTrans.at(idTrans) = FALSE;\n      }\n\n    // receivers\n    for(UInt idRecv=0; idRecv<indexRecv.size(); idRecv++)\n      if(indexRecv.at(idRecv).size() && gnss->receivers.at(idRecv)->isMyRank())\n      {\n        calcVariance(std::bind(&GnssReceiver::clockError, gnss->receivers.at(idRecv), std::placeholders::_1),\n                     driftRecv(idRecv), indexRecv.at(idRecv), indexDriftRecv.at(idRecv),\n                     isFirstRecv.at(idRecv), sigma0Recv(idRecv), sigmaEpochRecv.at(idRecv));\n        isFirstRecv.at(idRecv) = FALSE;\n      }\n\n    // =================================\n\n    Double maxChange = 0;\n    infoTrans.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    infoDriftTrans.synchronizeAndPrint(normalEquationInfo.comm, 1e-2/86400., maxChange);\n    infoRecv.synchronizeAndPrint (normalEquationInfo.comm, 1e-3, maxChange);\n    infoDriftRecv.synchronizeAndPrint (normalEquationInfo.comm, 1e-2/86400., maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationClocksModel::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameTransmitter.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logStatus<<\"write transmitter clocks to files <\"<<fileNameTransmitter(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto trans : gnss->transmitters)\n        if(isMyRank(trans->idTrans()))\n        {\n          const UInt idTrans = trans->idTrans();\n          MiscValueArc arc;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(indexTrans.at(idTrans).size() && indexTrans.at(idTrans).at(idEpoch))\n            {\n              MiscValueEpoch epoch;\n              epoch.time  = gnss->times.at(idEpoch);\n              epoch.value = trans->clockError(idEpoch);\n              arc.push_back(epoch);\n            }\n          fileNameVariableList.setVariable(\"prn\", trans->name());\n          InstrumentFile::write(fileNameTransmitter(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n\n    if(!fileNameReceiver.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write receiver clocks to files <\"<<fileNameReceiver(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto recv : gnss->receivers)\n        if(recv->isMyRank())\n        {\n          const UInt idRecv = recv->idRecv();\n          MiscValueArc arc;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(indexRecv.at(idRecv).size() && indexRecv.at(idRecv).at(idEpoch))\n            {\n              MiscValueEpoch epoch;\n              epoch.time  = recv->times.at(idEpoch);\n              epoch.value = recv->clockError(idEpoch);\n              arc.push_back(epoch);\n            }\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          InstrumentFile::write(fileNameReceiver(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationClocksModel.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationClocksModel.h\n*\n* @brief Clock errors.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONCLOCKSMODEL__\n#define __GROOPS_GNSSPARAMETRIZATIONCLOCKSMODEL__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationClocksModel = R\"(\n\\subsection{ClocksModel}\\label{gnssParametrizationType:clocksModel}\nThis parametrization is an alternative to \\configClass{parametrization:clocks}{gnssParametrizationType:clocks}.\nClock errors are estimated epoch-wise for each \\configClass{selectTransmitters/Receivers}{platformSelectorType}\nand, opposed to \\configClass{parametrization:clocks}{gnssParametrizationType:clocks}, are also estimated for epochs\nthat have no valid observations available (e.g. data gaps).\n\nThe clock error of an epoch can be predicted by the clock error\nof the preceding epoch and an unknown clock drift\n\\begin{equation}\n  \\Delta t_{i+1} = \\Delta t_{i} + t_{drift} dt + \\epsilon_i.\n\\end{equation}\nThis equation is applied as an additional constraint equation in each epoch\n\\begin{equation}\n  0 = \\Delta t_{i+1} - \\Delta t_{i} - t_{drift} dt + \\epsilon_i.\n\\end{equation}\nThe variance $\\sigma^2(\\epsilon)$ is estimated iteratively by variance component estimation (VCE).\nClock jumps are treated as outliers and are automatically downweighted as described in\n\\configClass{GnssProcessing:processingStep:estimate}{gnssProcessingStepType:estimate}.\n\nThe absolute initial clock error and clock drift cannot be determined if all receiver\nand transmitter clocks are estimated together due to their linear dependency.\nThis linear dependency would lead to a rank deficiency in the normal equation matrix in the same\nmanner as described in \\configClass{parametrization:clocks}{gnssParametrizationType:clocks}.\nTo circumvent this issue, an additional zero-mean constraint is added in each epoch\nas observation equation\n\\begin{equation}\n  0 = \\frac{1}{n_i + n_k} (\\sum_i \\Delta t^{s_i} + \\sum_k \\Delta t_{r_k})\n\\end{equation}\nsummed over all \\configClass{selectTransmitters/ReceiversZeroMean}{platformSelectorType}.\nThis should be a loose constraint with a relatively large standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:clock::<time>|\nand \\verb|<station or prn>:clockDrift::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Clock errors.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationClocksModel : public GnssParametrizationBase\n{\n  Gnss                                        *gnss;\n  std::string                                  name, nameConstraint;\n  PlatformSelectorPtr                          selectTransmitters, selectReceivers;\n  PlatformSelectorPtr                          selectTransmittersZeroMean, selectReceiversZeroMean;\n  std::vector<Byte>                            selectedTransmitters, selectedReceivers;\n  std::vector<Byte>                            selectedTransmittersZeroMean, selectedReceiversZeroMean;\n  Double                                       huber, huberPower;\n  FileName                                     fileNameReceiver, fileNameTransmitter;\n  Bool                                         applyConstraint;\n  Double                                       sigmaZeroMean;\n  std::vector<std::vector<GnssParameterIndex>> indexTrans, indexRecv;                 // for each trans/recv and epoch\n  std::vector<GnssParameterIndex>              indexDriftTrans, indexDriftRecv;       // for each trans/recv\n  Vector                                       isMyRank;                              // for each trans\n  Vector                                       driftTrans, drift0Trans, clock0Trans;  // for each trans [m/s], [m/s], [m]\n  Vector                                       driftRecv,  drift0Recv,  clock0Recv;   // for each recv  [m/s], [m/s], [m]\n  Vector                                       sigma0Trans,     sigma0Recv;           // for each trans/recv  [m]\n  std::vector<std::vector<Double>>             sigmaEpochTrans, sigmaEpochRecv;       // for each trans/recv and epoch  [m]\n  std::vector<Bool>                            isFirstTrans,    isFirstRecv;          // for each trans/recv\n\npublic:\n  GnssParametrizationClocksModel(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                      std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n//***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationCodeBiases.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationCodeBiases.cpp\n*\n* @brief Code biases.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationCodeBiases.h\"\n\n/***********************************************/\n\nGnssParametrizationCodeBiases::GnssParametrizationCodeBiases(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                    name,               Config::OPTIONAL, \"parameter.codeBiases\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",      selectTransmitters, Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectReceivers\",         selectReceivers,    Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"linearGlonassBias\",       isLinearBias,       Config::DEFAULT,  \"0\", \"bias depends linear on frequency channel number\");\n    readConfig(config, \"typesClockDatum\",         typesClockDatum,    Config::OPTIONAL, R\"([\"C1WG\", \"C2WG\", \"C1CE\", \"C5QE\", \"C1PR\", \"C2PR\"])\", \"first two matching types define the ionosphere free transmitter clock (e.g. C1WG, C2WG)\");\n    readConfig(config, \"nameConstraint\",          nameConstraint,     Config::OPTIONAL, \"constraint.codeBiases\", \"used for parameter selection\");\n    readConfig(config, \"sigmaZeroMeanConstraint\", sigmaZeroMean,      Config::DEFAULT,  \"0.0001\", \"(0 = unconstrained) sigma [m] for null space constraint\");\n    if(isCreateSchema(config)) return;\n\n    // mimic behaviour of old GROOPS version\n    if(!typesClockDatum.size())\n      typesClockDatum = {GnssType::C1WG, GnssType::C2WG};\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationCodeBiases::~GnssParametrizationCodeBiases()\n{\n  for(auto para : paraTrans)\n    delete para;\n  for(auto para : paraRecv)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationCodeBiases::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n\n    auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n    paraTrans.resize(gnss->transmitters.size(), nullptr);\n    for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n      if(selectedTransmitters.at(idTrans) && gnss->transmitters.at(idTrans)->useable())\n      {\n        auto para = new Parameter();\n        paraTrans.at(idTrans) = para;\n        para->trans = gnss->transmitters.at(idTrans);\n      }\n\n    auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n    paraRecv.resize(gnss->receivers.size(), nullptr);\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedReceivers.at(idRecv) && gnss->receivers.at(idRecv)->useable())\n      {\n        auto para = new Parameter();\n        paraRecv.at(idRecv) = para;\n        para->recv = gnss->receivers.at(idRecv);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationCodeBiases::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : paraTrans)\n      if(para)\n        para->index = GnssParameterIndex();\n    for(auto para : paraRecv)\n      if(para)\n        para->index = GnssParameterIndex();\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n\n    auto nullSpace = [](Matrix &N, Bool remove)\n    {\n      Vector eigen = eigenValueDecomposition(N, TRUE);\n      eigen *= (eigen(eigen.rows()-1) > 1e-4) ? 1./eigen(eigen.rows()-1) : 0.;\n      UInt countZeros = 0;\n      while((countZeros < eigen.rows()) && (eigen(countZeros) < 1e-8))\n        countZeros++;\n      return (remove) ? N.column(countZeros, N.columns()-countZeros) : N.column(0, countZeros);\n    };\n\n    // transmitter parameters\n    // ----------------------\n    UInt countParaTrans = 0;\n    if(!normalEquationInfo.isEachReceiverSeparately)\n      for(auto para : paraTrans)\n        if(para && para->trans->useable())\n        {\n          std::vector<GnssType> biasTypes;\n          for(GnssType type : para->trans->signalBias.types)\n            if((type == GnssType::RANGE) && !type.isInList(biasTypes))\n              biasTypes.push_back(type);\n          if(biasTypes.size() <= 2)\n            continue;\n\n          // transformation matrix\n          Matrix T(para->trans->signalBias.types.size(), biasTypes.size());\n          for(UInt i=0; i<para->trans->signalBias.types.size(); i++)\n            for(UInt k=0; k<biasTypes.size(); k++)\n              if(para->trans->signalBias.types.at(i) == biasTypes.at(k))\n                T(i, k) = 1.;\n\n          // eliminate two biases which defines the clock\n          UInt idx;\n          GnssType firstFreq = GnssType::FREQUENCY;\n          for(UInt i=0; i<typesClockDatum.size(); i++)\n            if(typesClockDatum.at(i).isInList(biasTypes, idx) && (typesClockDatum.at(i) != firstFreq))\n            {\n              T(GnssType::index(para->trans->signalBias.types, typesClockDatum.at(i)), idx) = 0;\n              if(firstFreq != GnssType::FREQUENCY)\n                break; // found a second type\n              firstFreq = typesClockDatum.at(i) & GnssType::FREQUENCY;\n            }\n\n          // determine nullspace\n          Matrix N(1+T.columns(), Matrix::SYMMETRIC);\n          for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n          {\n            std::vector<GnssType> types;\n            for(GnssType type : gnss->typesRecvTrans.at(idRecv).at(para->trans->idTrans()))\n              if((type == GnssType::RANGE) && !type.isInList(types))\n                types.push_back(type);\n            if(!types.size())\n              continue;\n\n            // Composed signals (e.g. C2DG)\n            std::vector<GnssType> typesTrans;\n            Matrix Compose;\n            gnss->receivers.at(idRecv)->signalComposition(NULLINDEX, types, typesTrans, Compose);\n\n            Matrix A(types.size(), 1+T.columns());\n            for(UInt i=0; i<types.size(); i++)\n              if(types.at(i) == GnssType::RANGE)\n                A(i, 0) = -1.;  // clock\n            UInt idx;\n            for(UInt i=0; i<typesTrans.size(); i++)\n              if(typesTrans.at(i).isInList(para->trans->signalBias.types, idx))\n                matMult(1., Compose.column(i), T.row(idx), A.column(1, T.columns()));\n            Vector STEC(types.size());\n            for(UInt i=0; i<types.size(); i++)\n              STEC(i) = types.at(i).ionosphericFactor();\n            eliminationParameter(STEC, {A});\n            rankKUpdate(1., A, N);\n          }\n\n          // eliminate clock\n          rankKUpdate(-1./N(0,0), N.slice(0, 1, 1, N.rows()-1), N.slice(1, 1, N.rows()-1, N.rows()-1));\n          N = N.slice(1, 1, N.rows()-1, N.rows()-1); // without clock\n\n          para->Bias = T * nullSpace(N, TRUE);\n          Parallel::broadCast(para->Bias, 0, normalEquationInfo.comm); // to ensure that all nodes use the same matrix\n          if(!para->Bias.size())\n            continue;\n\n          // determine parameter names\n          std::vector<ParameterName> parameterNames;\n          for(UInt i=0; i<para->Bias.columns(); i++)\n          {\n            std::string typeStr;\n            for(UInt idType=0; idType<para->Bias.rows(); idType++)\n              if(std::fabs(para->Bias(idType, i)) > 1e-4)\n                typeStr += ((para->Bias(idType, i) > 0) ? \"+\" : \"\") + para->Bias(idType, i)%\"%.2f\"s + para->trans->signalBias.types.at(idType).str();\n            parameterNames.push_back(ParameterName(para->trans->name(), \"codeBias\"+(i+1)%\"%02i(\"s+typeStr+\")\"));\n          }\n          para->index = normalEquationInfo.parameterNamesTransmitter(para->trans->idTrans(), parameterNames);\n          countParaTrans += parameterNames.size();\n        }\n    if(countParaTrans)\n      logInfo<<countParaTrans%\"%9i transmitter code bias parameters\"s<<Log::endl;\n\n    // receiver parameters\n    // -------------------\n    UInt countParaRecv = 0;\n    for(auto para : paraRecv)\n      if(para && para->recv->useable() && normalEquationInfo.estimateReceiver.at(para->recv->idRecv()))\n      {\n        std::vector<GnssType> biasTypes;\n        std::vector<GnssType> trendTypes;\n        for(GnssType type : para->recv->signalBias.types)\n          if(type == GnssType::RANGE)\n          {\n            if(!type.isInList(biasTypes))\n              biasTypes.push_back(type & (isLinearBias ? ~GnssType::FREQ_NO : GnssType::ALL));\n            else if(!type.isInList(trendTypes))\n              trendTypes.push_back(type & ~GnssType::FREQ_NO);\n          }\n        if(biasTypes.size() <= 2)\n          continue;\n\n        // transformation matrix\n        Matrix T(para->recv->signalBias.types.size(), biasTypes.size()+trendTypes.size());\n        UInt idx;\n        for(UInt i=0; i<para->recv->signalBias.types.size(); i++)\n          if(para->recv->signalBias.types.at(i).isInList(biasTypes, idx))\n            T(i, idx) = 1.;\n        for(UInt i=0; i<para->recv->signalBias.types.size(); i++)\n          if(para->recv->signalBias.types.at(i).isInList(trendTypes, idx))\n            T(i, biasTypes.size()+idx) = para->recv->signalBias.types.at(i).frequencyNumber();\n\n        // determine nullspace\n        Matrix N(1+T.columns(), Matrix::SYMMETRIC);\n        for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n        {\n          std::vector<GnssType> types;\n          for(GnssType type : gnss->typesRecvTrans.at(para->recv->idRecv()).at(idTrans))\n            if((type == GnssType::RANGE) && !type.isInList(types))\n              types.push_back(type);\n          if(!types.size())\n            continue;\n\n          Matrix A(types.size(), 1+T.columns());\n          for(UInt i=0; i<types.size(); i++)\n            if(types.at(i) == GnssType::RANGE)\n              A(i, 0) = 1.;  // clock\n          for(UInt i=0; i<types.size(); i++)\n            copy(T.row(GnssType::index(para->recv->signalBias.types, types.at(i))), A.slice(i, 1, 1, T.columns()));\n          Vector STEC(types.size());\n          for(UInt i=0; i<types.size(); i++)\n            STEC(i) = types.at(i).ionosphericFactor();\n          eliminationParameter(STEC, {A});\n          rankKUpdate(1., A, N);\n        }\n\n        // eliminate clock\n        rankKUpdate(-1./N(0,0), N.slice(0, 1, 1, N.rows()-1), N.slice(1, 1, N.rows()-1, N.rows()-1));\n        N = N.slice(1, 1, N.rows()-1, N.rows()-1); // without clock\n\n        para->Bias = T * nullSpace(N, TRUE);\n        Parallel::broadCast(para->Bias, 0, normalEquationInfo.comm); // to ensure that all nodes use the same matrix\n        if(!para->Bias.size())\n          continue;\n\n        // determine parameter names\n        std::vector<ParameterName> parameterNames;\n        for(UInt i=0; i<para->Bias.columns(); i++)\n        {\n          std::string typeStr;\n          for(UInt idType=0; idType<para->Bias.rows(); idType++)\n            if(std::fabs(para->Bias(idType, i)) > 1e-4)\n              typeStr += ((para->Bias(idType, i) > 0) ? \"+\" : \"\") + para->Bias(idType, i)%\"%.2f\"s + para->recv->signalBias.types.at(idType).str();\n          parameterNames.push_back(ParameterName(para->recv->name(), \"codeBias\"+(i+1)%\"%02i(\"s+typeStr+\")\"));\n        }\n        para->index = normalEquationInfo.parameterNamesReceiver(para->recv->idRecv(), parameterNames);\n        countParaRecv += parameterNames.size();\n      }\n    if(countParaRecv)\n      logInfo<<countParaRecv%\"%9i receiver code bias parameters\"s<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && sigmaZeroMean\n                    && (countParaTrans+countParaRecv) &&  !normalEquationInfo.isEachReceiverSeparately;\n\n\n    // calculate constraint equations (zero mean of signal biases)\n    // -----------------------------------------------------------\n    if(applyConstraint)\n    {\n      // parameter indices\n      UInt parameterCount = 0;\n      // indices of transmitter biases\n      idxBiasTrans.clear();\n      idxBiasTrans.resize(gnss->transmitters.size(), NULLINDEX);\n      for(auto para : paraTrans)\n        if(para && para->index)\n        {\n          idxBiasTrans.at(para->trans->idTrans()) = parameterCount;\n          parameterCount += para->Bias.columns();\n        }\n      // indices of receiver biases\n      idxBiasRecv.clear();\n      idxBiasRecv.resize(gnss->receivers.size(), NULLINDEX);\n      std::vector<std::vector<std::vector<GnssType>>> typesRecvTrans(gnss->receivers.size()); // for each receiver and transmitter: used types (receiver types)\n      for(auto para : paraRecv)\n        if(para && para->index)\n        {\n          const UInt idRecvOld = std::distance(typesRecvTrans.begin(), std::find(typesRecvTrans.begin(), typesRecvTrans.end(), gnss->typesRecvTrans.at(para->recv->idRecv())));\n          if(idRecvOld >= typesRecvTrans.size())\n          {\n            typesRecvTrans.at(para->recv->idRecv()) = gnss->typesRecvTrans.at(para->recv->idRecv());\n            idxBiasRecv.at(para->recv->idRecv()) = parameterCount;\n            parameterCount += para->Bias.columns();\n          }\n          else\n            idxBiasRecv.at(para->recv->idRecv()) = idxBiasRecv.at(idRecvOld);\n        }\n\n      if(parameterCount)\n      {\n        UInt idxClocks = parameterCount;\n        // indicies of transmitter clocks\n        std::vector<UInt> idxClockTrans(gnss->transmitters.size(), NULLINDEX);\n        for(auto trans : gnss->transmitters)\n          if(trans->useable())\n            idxClockTrans.at(trans->idTrans()) = parameterCount++;\n        // indices of receiver clocks\n        std::vector<UInt> idxClockRecv(gnss->receivers.size(), NULLINDEX);\n        typesRecvTrans.clear();\n        typesRecvTrans.resize(gnss->receivers.size());\n        for(auto recv : gnss->receivers)\n          if(normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n          {\n            const UInt idRecvOld = std::distance(typesRecvTrans.begin(), std::find(typesRecvTrans.begin(), typesRecvTrans.end(), gnss->typesRecvTrans.at(recv->idRecv())));\n            if(idRecvOld >= typesRecvTrans.size())\n            {\n              typesRecvTrans.at(recv->idRecv()) = gnss->typesRecvTrans.at(recv->idRecv());\n              idxClockRecv.at(recv->idRecv())   = parameterCount++;\n            }\n            else\n              idxClockRecv.at(recv->idRecv()) = idxClockRecv.at(idRecvOld);\n          }\n\n        // normals of pseudo observations\n        Matrix N(parameterCount, Matrix::SYMMETRIC);\n        for(auto recv : gnss->receivers)\n          if(recv->isMyRank() && normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n            for(auto trans : gnss->transmitters)\n            {\n              // observation types\n              std::vector<GnssType> types;\n              for(GnssType type : gnss->typesRecvTrans.at(recv->idRecv()).at(trans->idTrans()))\n                if((type == GnssType::RANGE) && !type.isInList(types))\n                  types.push_back(type);\n              if(!types.size())\n                continue;\n\n              // transmitted types\n              std::vector<GnssType> typesTrans;\n              Matrix T;\n              recv->signalComposition(NULLINDEX/*idEpoch*/, types, typesTrans, T);\n\n              // design matrix\n              Matrix A(types.size(), parameterCount);\n              if(idxClockRecv.at(recv->idRecv()) != NULLINDEX)    // clock recv\n                for(UInt i=0; i<types.size(); i++)\n                  A(i, idxClockRecv.at(recv->idRecv())) = 1.;\n              if(idxClockTrans.at(trans->idTrans()) != NULLINDEX) // clock trans\n                for(UInt i=0; i<types.size(); i++)\n                  A(i, idxClockTrans.at(trans->idTrans())) = -1.;\n              if(idxBiasRecv.at(recv->idRecv()) != NULLINDEX)     // bias recv\n                for(UInt i=0; i<types.size(); i++)\n                  copy(paraRecv.at(recv->idRecv())->Bias.row(GnssType::index(recv->signalBias.types, types.at(i))),\n                      A.slice(i, idxBiasRecv.at(recv->idRecv()), 1, paraRecv.at(recv->idRecv())->Bias.columns()));\n              if(idxBiasTrans.at(trans->idTrans()) != NULLINDEX)  // bias trans\n                for(UInt k=0; k<typesTrans.size(); k++)\n                  matMult(1., T.column(k), paraTrans.at(trans->idTrans())->Bias.row(GnssType::index(trans->signalBias.types, typesTrans.at(k))),\n                          A.column(idxBiasTrans.at(trans->idTrans()), paraTrans.at(trans->idTrans())->Bias.columns()));\n              // eliminate STEC\n              Vector STEC(types.size());\n              for(UInt i=0; i<types.size(); i++)\n                STEC(i) = types.at(i).ionosphericFactor();\n              eliminationParameter(STEC, {A});\n              rankKUpdate(1., A, N);\n            }\n        Parallel::reduceSum(N, 0, normalEquationInfo.comm);\n\n        if(Parallel::isMaster(normalEquationInfo.comm))\n        {\n          // add zero mean of clocks and eliminate clocks\n          Matrix N11 = N.slice(idxClocks, idxClocks, parameterCount-idxClocks, parameterCount-idxClocks);\n          for(UInt i=0; i<N11.rows(); i++)\n            if(N11(i,i) == 0)\n              N11(i,i) = 1.;\n          rankKUpdate(1., Matrix(1, N11.rows(), 1.), N11); // add zero mean\n          cholesky(N11);\n          triangularSolve(1., N11.trans(), N.slice(0, idxClocks, idxClocks, N11.rows()).trans());\n          rankKUpdate(-1., N.slice(0, idxClocks, idxClocks, N11.rows()).trans(), N.slice(0, 0, idxClocks, idxClocks));\n          N = N.slice(0, 0, idxClocks, idxClocks);\n\n          zeroMeanDesign = nullSpace(N, FALSE).trans(); // null space defines the constraint equations\n        }\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationCodeBiases::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(auto para : paraTrans)\n        if(para && para->index)\n          copy(leastSquares(Matrix(para->Bias), Vector(para->trans->signalBias.biases)), x0.row(normalEquationInfo.index(para->index), para->Bias.columns()));\n\n    for(auto para : paraRecv)\n      if(para && para->index && para->recv->isMyRank())\n        copy(leastSquares(Matrix(para->Bias), Vector(para->recv->signalBias.biases)), x0.row(normalEquationInfo.index(para->index), para->Bias.columns()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationCodeBiases::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    auto paraTrans = this->paraTrans.at(eqn.transmitter->idTrans());\n    if(paraTrans && paraTrans->index)\n    {\n      UInt idx;\n      MatrixSlice Design(A.column(paraTrans->index));\n      for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n        if((eqn.typesTransmitted.at(idType) == GnssType::RANGE) && eqn.typesTransmitted.at(idType).isInList(eqn.transmitter->signalBias.types, idx))\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + eqn.types.size() + idType), paraTrans->Bias.row(idx), Design);\n    }\n\n    auto paraRecv = this->paraRecv.at(eqn.receiver->idRecv());\n    if(paraRecv && paraRecv->index)\n    {\n      UInt idx;\n      MatrixSlice Design(A.column(paraRecv->index));\n      for(UInt idType=0; idType<eqn.types.size(); idType++)\n        if((eqn.types.at(idType) == GnssType::RANGE) && eqn.types.at(idType).isInList(eqn.receiver->signalBias.types, idx))\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + idType), paraRecv->Bias.row(idx), Design);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationCodeBiases::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm) && applyConstraint)\n    {\n      logStatus<<\"apply \"<<zeroMeanDesign.rows()<<\" zero mean equations for code bias parameters\"<<Log::endl;\n      if(zeroMeanDesign.size())\n      {\n        GnssDesignMatrix A(normalEquationInfo, zeroMeanDesign.rows());\n        for(auto para : paraTrans)\n          if(para && para->index && (idxBiasTrans.at(para->trans->idTrans()) != NULLINDEX))\n            axpy(1./sigmaZeroMean, zeroMeanDesign.column(idxBiasTrans.at(para->trans->idTrans()), para->Bias.columns()), A.column(para->index));\n        for(auto para : paraRecv)\n          if(para && para->index && (idxBiasRecv.at(para->recv->idRecv()) != NULLINDEX))\n            axpy(1./sigmaZeroMean, zeroMeanDesign.column(idxBiasRecv.at(para->recv->idRecv()), para->Bias.columns()), A.column(para->index));\n        GnssDesignMatrix::accumulateNormals(A, Vector(zeroMeanDesign.rows()), normals, n, lPl, obsCount);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationCodeBiases::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange infoTrans(\"mm\");\n    for(auto para : paraTrans)\n      if(para && para->index)\n      {\n        const Vector dBias = para->Bias * x.row(normalEquationInfo.index(para->index), para->Bias.columns());\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          para->trans->signalBias.biases.at(idType) += dBias(idType);\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          if(infoTrans.update(1e3*dBias(idType)))\n            infoTrans.info = \"code bias transmitter (\"+para->trans->signalBias.types.at(idType).str()+\")\";\n      }\n    infoTrans.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    Gnss::InfoParameterChange infoRecv(\"mm\");\n    for(auto para : paraRecv)\n      if(para && para->index)\n      {\n        const Vector dBias = para->Bias * x.row(normalEquationInfo.index(para->index), para->Bias.columns());\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          para->recv->signalBias.biases.at(idType) += dBias(idType);\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          if(infoRecv.update(1e3*dBias(idType)))\n            infoRecv.info = \"code bias receiver (\"+para->recv->name()+\", \"+para->recv->signalBias.types.at(idType).str()+\")\";\n      }\n    infoRecv.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationCodeBiases.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationCodeBiases.h\n*\n* @brief Code biases.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONCODEBIASES__\n#define __GROOPS_GNSSPARAMETRIZATIONCODEBIASES__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationCodeBiases = R\"(\n\\subsection{CodeBiases}\\label{gnssParametrizationType:codeBiases}\nEach code observation (e.g \\verb|C1C| or \\verb|C2W|) contains a bias at transmitter/receiver level\n\\begin{equation}\n  [C\\nu a]_r^s(t) = \\dots + \\text{bias}[C\\nu a]^s + \\text{bias}[C\\nu a]_r + \\dots\n\\end{equation}\nThe code biases cannot be estimated together with clock errors and ionospheric delays in an absolute sense\nas rank deficiencies will occur in the system of normal equations. Therefore, the biases are not initialized and set up\nas parameters directly but only estimable linear combinations are parametrized.\n\nThe basic idea is to set up simplified normal equations with the biases,\nclock and STEC parameters of one single receiver or transmitter,\neliminate clock and STEC parameters and perform an eigen value decomposition\nof the normal equation matrix\n\\begin{equation}\n  \\M N = \\M Q \\M\\Lambda \\M Q^T.\n\\end{equation}\nInstead of estimating the original bias parameter $\\M x$ a transformed set $\\bar{\\M x}$\nis introduced:\n\\begin{equation}\n  \\bar{\\M x} = \\M Q^T \\M x.\n\\end{equation}\nThe new parameters corresponding to eigen values $\\lambda>0$ are estimable,\nthe others are left out (set to zero). The behavior can be controlled by explicitly setting up to two bias types\nwith \\configClass{typesClockDatum}{gnssType} for each transmitter to zero. These then define the ionosphere-free clock datum\nof the transmitter. The missing linear combinations,\nwhich depend on the STEC parameters, can be added with\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases}.\n\nAdditional rank deficiencies may also occur when biases of transmitters and receivers are estimated together.\nThe minimum norm nullspace (also via eigen value decomposition)\nis formulated as zero constraint equations and added with a standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nIn case of GLONASS the code biases at receiver level can differ between different frequency channels\n(frequency division multiple access, FDMA) and for each channel an extra code bias is estimated.\nWith \\config{linearGlonassBias} a linear relationship between bias and frequency channel is assumed,\nwhich reduces the number of bias parameters.\n\nThe estimated biases can be written to files in\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:codeBias0<index><combi of gnssTypes>::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Code biases.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationCodeBiases : public GnssParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    GnssTransmitterPtr trans;\n    GnssReceiverPtr    recv;\n    GnssParameterIndex index;\n    Matrix             Bias;\n  };\n\n  Gnss                      *gnss;\n  std::string                name, nameConstraint;\n  PlatformSelectorPtr        selectTransmitters, selectReceivers;\n  Bool                       isLinearBias;\n  Bool                       applyConstraint;\n  Double                     sigmaZeroMean;\n  std::vector<Parameter*>    paraTrans, paraRecv;\n  std::vector<UInt>          idxBiasTrans, idxBiasRecv; // indices in zeroMean matrix\n  std::vector<GnssType>      typesClockDatum;\n  Matrix                     zeroMeanDesign;            // zero mean observation equations\n\npublic:\n  GnssParametrizationCodeBiases(Config &config);\n ~GnssParametrizationCodeBiases();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationConstraints.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationConstraints.h\n*\n* @brief Parameter constraints.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONCONSTRAINTS__\n#define __GROOPS_GNSSPARAMETRIZATIONCONSTRAINTS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationConstraints = R\"(\n\\subsection{Constraints}\\label{gnssParametrizationType:constraints}\nAdd a pseudo observation equation (constraint)\nfor each selected \\configClass{parameters}{parameterSelectorType}\n\\begin{equation}\n  b-x_0 = 1 \\cdot dx + \\epsilon,\n\\end{equation}\nwhere $b$ is the \\config{bias} and $x_0$ is the a priori value of the parameter\nif \\config{relativeToApriori} is not set.\nThe standard deviation \\config{sigma} is used to weight the observation equations.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter constraints.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationConstraints : public GnssParametrizationBase\n{\n  std::string          name;\n  ParameterSelectorPtr parameterSelector;\n  Double               sigma;\n  Double               bias;\n  Bool                 relativeToApriori;\n  Gnss                *gnss;\n\npublic:\n  GnssParametrizationConstraints(Config &config);\n\n  void init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/) override {this->gnss = gnss;}\n  void constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n};\n\n/***********************************************/\n\ninline GnssParametrizationConstraints::GnssParametrizationConstraints(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",              name,              Config::OPTIONAL, \"constraint.name\",  \"\");\n    readConfig(config, \"parameters\",        parameterSelector, Config::MUSTSET,  \"\",  \"parameter to constrain\");\n    readConfig(config, \"sigma\",             sigma,             Config::MUSTSET,  \"\",  \"sigma of the constraint (same unit as parameter)\");\n    readConfig(config, \"bias\",              bias,              Config::DEFAULT,  \"0\", \"constrain all selected parameters towards this value\");\n    readConfig(config, \"relativeToApriori\", relativeToApriori, Config::DEFAULT,  \"0\", \"constrain only dx and not full x=dx+x0\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationConstraints::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    Vector x0 = Vector(normalEquationInfo.parameterCount());\n    if(!relativeToApriori)\n      x0 = gnss->aprioriParameter(normalEquationInfo);\n\n    const Double weight = 1./std::pow(sigma, 2);\n    const std::vector<UInt> indices = parameterSelector->indexVector(normalEquationInfo.parameterNames());\n    UInt count = 0;\n    for(UInt index : indices)\n      if(index != NULLINDEX)\n      {\n        const UInt idBlock    = normals.index2block(index);\n        const UInt blockIndex = normals.blockIndex(idBlock);\n        normals.setBlock(idBlock, idBlock);\n        if(normals.isMyRank(idBlock, idBlock))\n          normals.N(idBlock, idBlock)(index-blockIndex, index-blockIndex) += weight;\n        if(Parallel::isMaster(normalEquationInfo.comm))\n        {\n          n.at(idBlock)(index-blockIndex, 0) += weight * (bias - x0.at(index));\n          lPl += weight * std::pow(bias - x0.at(index), 2);\n          obsCount++;\n        }\n        count++;\n      }\n\n    if(count)\n      logStatus<<\"constrain \"<<name<<\" (\"<<count<<\" parameters)\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationEarthRotation.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationEarthRotation.cpp\n*\n* @brief EarthRotation.\n* @see GnssParametrization\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"base/planets.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationEarthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief EarthRotation.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\n\n/***********************************************/\n\nGnssParametrizationEarthRotation::GnssParametrizationEarthRotation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",             name,                    Config::OPTIONAL, \"parameter.earthRotation\", \"used for parameter selection\");\n    readConfig(config, \"outputfileEOP\",    fileNameEOP,             Config::OPTIONAL, \"\", \"EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)\");\n    readConfig(config, \"estimatePole\",     parametrizationPole,     Config::DEFAULT,  \"\", \"xp, yp [mas]\");\n    readConfig(config, \"estimateUT1\",      parametrizationUT1,      Config::DEFAULT,  \"\", \"rotation angle [ms]\");\n    readConfig(config, \"estimateNutation\", parametrizationNutation, Config::DEFAULT,  \"\", \"dX, dY [mas]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationEarthRotation::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    xPole     = Vector(2*parametrizationPole->parameterCount());\n    xUT1      = Vector(parametrizationUT1->parameterCount());\n    xNutation = Vector(2*parametrizationNutation->parameterCount());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationEarthRotation::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    indexParameterPole     = GnssParameterIndex();\n    indexParameterUT1      = GnssParameterIndex();\n    indexParameterNutation = GnssParameterIndex();\n\n    if(!isEnabled(normalEquationInfo, name) || normalEquationInfo.isEachReceiverSeparately)\n      return;\n    UInt countPara = 0;\n\n    // Polar motion\n    if(parametrizationPole->parameterCount())\n    {\n      std::vector<ParameterName> parameterNames;\n      parametrizationPole->parameterName({ParameterName(\"earth\", \"polarMotion.xp\"), ParameterName(\"earth\", \"polarMotion.yp\")}, parameterNames);\n      indexParameterPole = normalEquationInfo.parameterNamesOther(parameterNames);\n      countPara += parameterNames.size();\n    }\n\n    // Earth rotation angle (UT1)\n    if(parametrizationUT1->parameterCount())\n    {\n      std::vector<ParameterName> parameterNames;\n      parametrizationUT1->parameterName({ParameterName(\"earth\", \"UT1\")}, parameterNames);\n      indexParameterUT1 = normalEquationInfo.parameterNamesOther(parameterNames);\n      countPara += parameterNames.size();\n    }\n\n    // Nutation\n    if(parametrizationNutation->parameterCount())\n    {\n      std::vector<ParameterName> parameterNames;\n      parametrizationNutation->parameterName({ParameterName(\"earth\", \"nutation.X\"), ParameterName(\"earth\", \"nutation.Y\")}, parameterNames);\n      indexParameterNutation = normalEquationInfo.parameterNamesOther(parameterNames);\n      countPara += parameterNames.size();\n    }\n\n    if(countPara)\n      logInfo<<countPara%\"%9i Earth rotation parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationEarthRotation::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(!Parallel::isMaster(normalEquationInfo.comm))\n      return;\n    if(indexParameterPole)\n      copy(xPole, x0.row(normalEquationInfo.index(indexParameterPole), xPole.rows()));\n    if(indexParameterUT1)\n      copy(xUT1, x0.row(normalEquationInfo.index(indexParameterUT1), xUT1.rows()));\n    if(indexParameterNutation)\n      copy(xNutation, x0.row(normalEquationInfo.index(indexParameterNutation), xNutation.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationEarthRotation::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    if(!eqn.receiver->isEarthFixed())\n      return;\n    if(!(indexParameterPole || indexParameterUT1 || indexParameterNutation))\n      return;\n\n    const Double xp      = gnss->eop(eqn.idEpoch, 0);\n    const Double yp      = gnss->eop(eqn.idEpoch, 1);\n    const Double sp      = gnss->eop(eqn.idEpoch, 2);\n    const Double deltaUT = gnss->eop(eqn.idEpoch, 3) + (eqn.timeRecv-timeGPS2UTC(eqn.timeRecv)).seconds();\n    const Double X       = gnss->eop(eqn.idEpoch, 5);\n    const Double Y       = gnss->eop(eqn.idEpoch, 6);\n    const Double S       = gnss->eop(eqn.idEpoch, 7);\n    const Double ERA     = Planets::ERA(timeGPS2UTC(eqn.timeRecv) + seconds2time(deltaUT));\n\n    const Matrix rotW   = (rotaryY(Angle(xp)) * rotaryX(Angle(yp))).matrix(); // Polar motion rotation matrix\n    const Matrix rotERA = rotaryZ(Angle(S-ERA-sp)).matrix();   // Earth rotation angle rotation matrix\n    const Double a      = 0.5 + 0.125*(X*X+Y*Y);\n    const Double X2     = X*X;\n    const Double Y2     = Y*Y;\n    const Matrix rotQ({{1.-a*X2,   -a*X*Y,             X},    // Precession & nutation rotation matrix\n                       {  -a*X*Y, 1.-a*Y2,             Y},\n                       {      -X,      -Y, 1.-a*(X2+Y2)}});\n\n    const Vector posEarth     = gnss->rotationCrf2Trf(eqn.timeRecv).rotate(eqn.posRecv).vector();\n    const Time   timeTemporal = std::max(eqn.timeRecv, gnss->times.at(0));\n\n    // temporal parametrization\n    auto designMatrixTemporal = [&](ParametrizationTemporalPtr parametrization, const_MatrixSliceRef B, const GnssParameterIndex &index)\n    {\n      std::vector<UInt>   idx;\n      std::vector<Double> factor;\n      parametrization->factors(timeTemporal, idx, factor);\n      MatrixSlice Design(A.column(index));\n      for(UInt i=0; i<factor.size(); i++)\n        axpy(factor.at(i), B, Design.column(B.columns()*idx.at(i), B.columns()));\n    };\n\n    // Polar motion\n    // ------------\n    if(indexParameterPole)\n    {\n      // partial derivatives of position(CRF) with respect to xp, yp\n      Matrix partWxp(3,3), partWyp(3,3);\n      partWxp(0,2) = partWyp(2,1) = -1;\n      partWxp(2,0) = partWyp(1,2) =  1;\n\n      Matrix B(3,2);\n      matMult(DEG2RAD/3600e3, partWxp, posEarth, B.column(0));\n      matMult(DEG2RAD/3600e3, partWyp, posEarth, B.column(1));\n      B = eqn.A.column(GnssObservationEquation::idxPosRecv,3) * (rotQ * (rotERA * B));\n      designMatrixTemporal(parametrizationPole, B, indexParameterPole);\n    }\n\n    // Earth rotation angle (UT1)\n    // --------------------------\n    if(indexParameterUT1)\n    {\n      // partial derivatives of position(CRF) with respect to UT1\n      Matrix partERA({{std::sin(S-ERA-sp), -std::cos(S-ERA-sp),  0},\n                      {std::cos(S-ERA-sp),  std::sin(S-ERA-sp),  0},\n                      {                 0,                   0,  0}});\n\n      Matrix B = 1e-3 * 2*PI*1.00273781191135448/86400. * (eqn.A.column(GnssObservationEquation::idxPosRecv,3) * (rotQ * (partERA * (rotW * posEarth))));\n      designMatrixTemporal(parametrizationUT1, B, indexParameterUT1);\n    }\n\n    // Nutation\n    // --------\n    if(indexParameterNutation)\n    {\n      // partial derivatives of position(CRF) with respect to X, Y\n      Matrix partQX({{-2*X*a-X2*X/4,   -Y*a-Y*X2/4,                  1},\n                     {  -Y*a-X2*Y/4,       -X*Y2/4,                  0},\n                     {           -1,             0, -2*X*a-X*(X2+Y2)/4}});\n      Matrix partQY({{      -X2*Y/4,   -X*a-X*Y2/4,                  0},\n                     {  -X*a-X*Y2/4, -2*Y*a-Y*Y2/4,                  1},\n                     {            0,            -1, -2*Y*a-Y*(X2+Y2)/4}});\n\n      Matrix B(3,2);\n      Matrix p = rotERA * (rotW * posEarth);\n      matMult(DEG2RAD/3600e3, partQX, p, B.column(0));\n      matMult(DEG2RAD/3600e3, partQY, p, B.column(1));\n      B = eqn.A.column(GnssObservationEquation::idxPosRecv,3) * B;\n      designMatrixTemporal(parametrizationNutation, B, indexParameterNutation);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationEarthRotation::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n\n    // Polar motion\n    // ------------\n    if(indexParameterPole)\n    {\n      Gnss::InfoParameterChange info(\"mm\");\n      const Vector dx = x.row(normalEquationInfo.index(indexParameterPole), 2*parametrizationPole->parameterCount());\n      xPole += dx;\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n      {\n        parametrizationPole->factors(gnss->times.at(idEpoch), index, factor);\n        Vector p(2);\n        for(UInt k=0; k<factor.size(); k++)\n          axpy(DEG2RAD/3600e3 * factor.at(k), dx.row(2*index.at(k),2), p);\n\n        // update xp,yp\n        gnss->eop(idEpoch, 0) += p(0);\n        gnss->eop(idEpoch, 1) += p(1);\n        if(info.update(1e3*DEFAULT_R*norm(p)))\n          info.info = \"earth rotation (pole)\";\n      } // for(idEpoch)\n      info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    } // if(ParameterPole)\n\n    // Earth Rotation Angle (UT1)\n    // --------------------------\n    if(indexParameterUT1)\n    {\n      Gnss::InfoParameterChange info(\"mm\");\n      const Vector dx = x.row(normalEquationInfo.index(indexParameterUT1), parametrizationUT1->parameterCount());\n      xUT1 += dx;\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n      {\n        parametrizationUT1->factors(gnss->times.at(idEpoch), index, factor);\n        Double p = 0;\n        for(UInt k=0; k<factor.size(); k++)\n          p += 1e-3 * factor.at(k) * dx(index.at(k));\n\n        gnss->eop(idEpoch, 3) += p;\n        if(info.update(1e3*DEFAULT_R*2*PI*1.00273781191135448/86400*p))\n          info.info = \"earth rotation (UT1)\";\n      } // for(idEpoch)\n      info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    } // if(ParameterUT1)\n\n    // Nutation\n    // --------\n    if(indexParameterNutation)\n    {\n      Gnss::InfoParameterChange info(\"mm\");\n      const Vector dx = x.row(normalEquationInfo.index(indexParameterNutation), 2*parametrizationNutation->parameterCount());\n      xNutation += dx;\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n      {\n        parametrizationNutation->factors(gnss->times.at(idEpoch), index, factor);\n        Vector p(2);\n        for(UInt k=0; k<factor.size(); k++)\n          axpy(DEG2RAD/3600e3 * factor.at(k), dx.row(2*index.at(k),2), p);\n\n        // update X,Y\n        gnss->eop(idEpoch, 5) += p(0);\n        gnss->eop(idEpoch, 6) += p(1);\n        if(info.update(1e3*DEFAULT_R*norm(p)))\n          info.info = \"earth rotation (XY)\";\n      } // for(idEpoch)\n      info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    } // if(ParameterNutation)\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationEarthRotation::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name) || !Parallel::isMaster(normalEquationInfo.comm))\n      return;\n\n    if(!fileNameEOP.empty())\n    {\n      logStatus<<\"write EOP to files <\"<<fileNameEOP.appendBaseName(suffix)<<\">\"<<Log::endl;\n      std::vector<Time> times;\n      Matrix A(normalEquationInfo.idEpochs.size(), 9);\n      for(UInt i=0; i<normalEquationInfo.idEpochs.size(); i++)\n      {\n        const UInt idEpoch = normalEquationInfo.idEpochs.at(i);\n        times.push_back(gnss->times.at(idEpoch));\n        copy(gnss->eop.row(idEpoch), A.slice(i, 1, 1, 8));\n        A(i, 4) += (gnss->times.at(idEpoch)-timeGPS2UTC(gnss->times.at(idEpoch))).seconds(); // UT1-GPS => UT1-UTC\n      }\n      InstrumentFile::write(fileNameEOP.appendBaseName(suffix), Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationEarthRotation.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationEarthRotation.h\n*\n* @brief EarthRotation.\n* @see GnssParametrization\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONEARTHROTATION__\n#define __GROOPS_GNSSPARAMETRIZATIONEARTHROTATION__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationEarthRotation = R\"(\n\\subsection{EarthRotation}\\label{gnssParametrizationType:earthRotation}\nEarth rotation parameters (ERPs) can be estimated by defining\n\\config{estimatePole} ($x_p$, $y_p\\, [mas]$) and \\config{estimateUT1} ($dUT1\\, [ms], LOD$).\n\nEstimating length of day (LOD) with the sign according to IGS conventions requires a negative\nvalue in \\configClass{parametrizationTemporal:trend:timeStep}{parametrizationTemporalType:trend}.\n\nConstraints on the defined parameters can be added via\n\\configClass{parametrization:constraints}{gnssParametrizationType:constraints}.\nAn example would be to set up \\configClass{estimateUT1:constant}{parametrizationTemporalType:constant}\nso the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be\ndetermined by GNSS, a hard constraint to its a priori value can then be added.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|earth:polarMotion.xp:<temporal>:<interval>|,\n\\item \\verb|earth:polarMotion.yp:<temporal>:<interval>|,\n\\item \\verb|earth:UT1:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.X:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.Y:<temporal>:<interval>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief EarthRotation.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationEarthRotation : public GnssParametrizationBase\n{\n  Gnss                      *gnss;\n  std::string                name;\n  FileName                   fileNameEOP;\n  ParametrizationTemporalPtr parametrizationPole, parametrizationUT1, parametrizationNutation;\n  GnssParameterIndex         indexParameterPole,  indexParameterUT1, indexParameterNutation;\n  Vector                     xPole, xUT1, xNutation;\n\npublic:\n  GnssParametrizationEarthRotation(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationGroup.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationGroup.h\n*\n* @brief Group.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONGROUP__\n#define __GROOPS_GNSSPARAMETRIZATIONGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationGroup = R\"(\n\\subsection{Group}\\label{gnssParametrizationType:group}\nGroups a set of parameters. This class can be used to structure complex parametrizations\nand has no further effect itself.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Group.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationGroup : public GnssParametrizationBase\n{\n  GnssParametrizationPtr base;\n\npublic:\n  GnssParametrizationGroup(Config &config);\n ~GnssParametrizationGroup() {}\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                      std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   observationCorrections(GnssObservationEquation &eqn) const override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  void   constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                          const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                          const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger) override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\ninline GnssParametrizationGroup::GnssParametrizationGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"parametrization\", base, Config::MUSTSET, \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    base->init(gnss, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                                                   std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch)\n{\n  try\n  {\n    base->requirements(normalEquationInfo, transCount, transCountEpoch, recvCount, recvCountEpoch);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    base->initParameter(normalEquationInfo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::observationCorrections(GnssObservationEquation &eqn) const\n{\n  try\n  {\n    base->observationCorrections(eqn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    x0 += base->aprioriParameter(normalEquationInfo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    base->designMatrix(normalEquationInfo, eqn, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::constraintsEpoch(const GnssNormalEquationInfo &normalEquationInfo, UInt idEpoch, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    base->constraintsEpoch(normalEquationInfo, idEpoch, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    base->constraints(normalEquationInfo, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double GnssParametrizationGroup::ambiguityResolve(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount,\n                                                         const std::vector<Byte> &selectedTransmitters, const std::vector<Byte> &selectedReceivers,\n                                                         const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger)\n{\n  try\n  {\n    return base->ambiguityResolve(normalEquationInfo, normals, n, lPl, obsCount,\n                                  selectedTransmitters, selectedReceivers, searchInteger);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double GnssParametrizationGroup::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    return base->updateParameter(normalEquationInfo, x, Wz);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    base->updateCovariance(normalEquationInfo, covariance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssParametrizationGroup::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    base->writeResults(normalEquationInfo, suffix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationIonosphereMap.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationIonosphereMap.cpp\n*\n* @brief IonosphereMap.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/basisSplines.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"config/config.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationIonosphereMap.h\"\n\n/***********************************************/\n\nGnssParametrizationIonosphereMap::GnssParametrizationIonosphereMap(Config &config)\n{\n  try\n  {\n    GridPtr       gridPtr;\n    TimeSeriesPtr timeSeriesPtr;\n\n    readConfig(config, \"name\",                            name,            Config::OPTIONAL, \"parameter.mapVTEC\", \"\");\n    readConfig(config, \"selectReceivers\",                 selectReceivers, Config::MUSTSET,  R\"([\"all\"])\",        \"\");\n    readConfig(config, \"outputfileGriddedDataTimeSeries\", fileNameOut,     Config::OPTIONAL, \"\",                  \"single layer VTEC [TECU]\");\n    readConfig(config, \"outputGrid\",                      gridPtr,         Config::DEFAULT,  R\"({\"geograph\":{\"deltaLambda\":\"5\",\"deltaPhi\":\"2.5\",\"height\":\"450e3\",\"R\":\"6371e3\",\"inverseFlattening\":0}})\", \"\");\n    readConfig(config, \"outputTimeSeries\",                timeSeriesPtr,   Config::DEFAULT,  R\"({\"uniformSampling\":{\"sampling\":\"2/24\"}})\", \"\");\n    readConfig(config, \"inputfileGriddedDataTimeSeries\",  fileNameIn,      Config::OPTIONAL, \"\",                  \"single layer VTEC [TECU]\");\n    readConfig(config, \"maxDegree\",                       maxDegree,       Config::MUSTSET,  \"15\",                \"spherical harmonics parametrization\");\n    readConfig(config, \"temporal\",                        temporal,        Config::DEFAULT,  \"\",                  \"temporal evolution of VTEC values\");\n    readConfig(config, \"radiusIonosphericLayer\",          radiusIono,      Config::DEFAULT,  \"6371e3+450e3\",      \"[m] radius of ionospheric single layer\");\n    readConfig(config, \"mapR\",                            mapR,            Config::DEFAULT,  \"6371e3\",            \"[m] constant of MSLM mapping function\");\n    readConfig(config, \"mapH\",                            mapH,            Config::DEFAULT,  \"506.7e3\",           \"[m] constant of MSLM mapping function\");\n    readConfig(config, \"mapAlpha\",                        mapAlpha,        Config::DEFAULT,  \"0.9782\",            \"constant of MSLM mapping function\");\n    readConfig(config, \"magnetosphere\",                   magnetosphere,   Config::MUSTSET,  \"\",                  \"\");\n    if(isCreateSchema(config)) return;\n\n    gridOut  = GriddedData(Ellipsoid(mapR, 0), gridPtr->points(), gridPtr->areas(), {});\n    timesOut = timeSeriesPtr->times();\n    if(!fileNameOut.empty() && !(gridOut.points.size() && timesOut.size()))\n      throw(Exception(\"outputfileGriddedDataTimeSeries needs outputGrid and outputTimeSeries\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic Double interpolateGrid(const Vector3d &point, const GriddedDataRectangular &grid, const Vector &data)\n{\n  try\n  {\n    // latitude\n    Double tauLat  = Double(point.phi()-grid.latitudes.at(0))/Double(grid.latitudes.at(1)-grid.latitudes.at(0));\n    const UInt idxLat1 = std::min(static_cast<UInt>(std::max(std::floor(tauLat), 0.)), grid.latitudes.size()-1);\n    const UInt idxLat2 = std::min(idxLat1+1, grid.latitudes.size()-1);\n    tauLat -= std::floor(tauLat);\n    // longitude\n    Double tauLon  = Double(point.lambda()-grid.longitudes.at(0))/Double(grid.longitudes.at(1)-grid.longitudes.at(0));\n    const UInt idxLon1 = static_cast<UInt>(std::floor(tauLon)+grid.longitudes.size())%grid.longitudes.size();\n    const UInt idxLon2 = (idxLon1+1)%grid.longitudes.size();\n    tauLon -= std::floor(tauLon);\n\n    return (1-tauLon) * (1-tauLat) * data(idxLon1 + grid.longitudes.size() * idxLat1)\n         + (1-tauLon) *  (tauLat)  * data(idxLon1 + grid.longitudes.size() * idxLat2)\n         +  (tauLon)  * (1-tauLat) * data(idxLon2 + grid.longitudes.size() * idxLat1)\n         +  (tauLon)  *  (tauLat)  * data(idxLon2 + grid.longitudes.size() * idxLat2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereMap::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->gnss = gnss;\n    selectedReceivers = gnss->selectReceivers(selectReceivers);\n    x.resize(temporal->parameterCount(), Vector((maxDegree+1)*(maxDegree+1)));\n\n    // apriori model\n    // -------------\n    if(!fileNameIn.empty())\n    {\n      logStatus<<\"read apriori ionosphere <\"<<fileNameIn<<\">\"<<Log::endl;\n      InFileGriddedDataTimeSeries file(fileNameIn);\n      GriddedDataRectangular grid;\n      if(!grid.init(file.grid()))\n        throw(Exception(fileNameIn.str()+\" must contain a rectangular grid\"));\n      if((gnss->times.front() < file.times().front()) || (gnss->times.back() > file.times().back()))\n        throw(Exception(\"wrong time interval [\"+file.times().front().dateTimeStr()+\", \"+file.times().back().dateTimeStr()+\"] in <\"+fileNameIn.str()+\">\"));\n\n      UInt indexData = file.nodeCount();\n      std::vector<Vector>   griddedVTEC(file.splineDegree()+1);\n      std::vector<Rotary3d> rotSmf2Trf(file.splineDegree()+1); // SolarGeomagneticFrame ->  Terrestrial\n\n      Log::Timer timer(gnss->times.size());\n      for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n      {\n        timer.loopStep(idEpoch);\n\n        // find time interval and read missing nodes\n        const UInt idx = std::min(static_cast<UInt>(std::distance(file.times().begin(),\n                                                                  std::upper_bound(file.times().begin(), file.times().end(), gnss->times.at(idEpoch)))), file.times().size()-1)-1;\n        const UInt start = (idx > indexData) ? std::max(idx, indexData+griddedVTEC.size()) : idx;\n        const UInt end   = (idx > indexData) ? idx+griddedVTEC.size() : std::min(idx+griddedVTEC.size(), indexData);\n        for(UInt i=start; i<end; i++)\n        {\n          griddedVTEC.at(i%griddedVTEC.size()) = file.data(i).column(0);\n          rotSmf2Trf.at(i%griddedVTEC.size())  = gnss->rotationCrf2Trf(file.times().at(i)) * inverse(magnetosphere->rotaryCelestial2SolarGeomagneticFrame(file.times().at(i)));\n        }\n        indexData = idx;\n\n        // prepare spline interpolation\n        const Double t     = (gnss->times.at(idEpoch)-file.times().at(idx)).mjd()/(file.times().at(idx+1)-file.times().at(idx)).mjd();\n        const Vector coeff = BasisSplines::compute(t, file.splineDegree());\n\n        // Celestial -> SolarGeomagneticFrame\n        const Rotary3d rotCrf2Smf = magnetosphere->rotaryCelestial2SolarGeomagneticFrame(gnss->times.at(idEpoch));\n\n        for(auto recv : gnss->receivers)\n          if(recv->isMyRank() && recv->useable(idEpoch) && selectedReceivers.at(recv->idRecv()))\n            for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n              if(recv->observation(idTrans, idEpoch))\n              {\n\n                GnssObservationEquation eqn(*recv->observation(idTrans, idEpoch), *recv, *gnss->transmitters.at(idTrans), gnss->funcRotationCrf2Trf,\n                                            nullptr/*reduceModels*/, idEpoch, FALSE/*homogenize*/, {}/*types*/);\n                // pierce point in SolarGeomagneticFrame\n                const Vector3d point = rotCrf2Smf.rotate(intersection(radiusIono, eqn.posRecv, eqn.posTrans));\n                // spline interpolation\n                Double VTEC = 0;\n                for(UInt i=0; i<coeff.rows(); i++)\n                  VTEC += coeff(i) * interpolateGrid(rotSmf2Trf.at((indexData+i)%griddedVTEC.size()).rotate(point), grid, griddedVTEC.at((indexData+i)%griddedVTEC.size()));\n                // mapping VTEC -> STEC\n                recv->observation(idTrans, idEpoch)->STEC += mapping(eqn.elevationRecvLocal) * VTEC;\n              } // for(recv, trans)\n      } // for(idEpoch)\n      Parallel::barrier(comm);\n      timer.loopEnd();\n    } // if(fileNameIn)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereMap::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    index.clear();\n    if(!isEnabled(normalEquationInfo, name) || normalEquationInfo.isEachReceiverSeparately)\n      return;\n\n    std::vector<ParameterName> baseNames;\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      baseNames.push_back(ParameterName(\"VTEC\", \"sphericalHarmonics.c_\"+n%\"%i\"s+\"_\"+0%\"%i\"s));\n      for(UInt m=1; m<=n; m++)\n      {\n        baseNames.push_back(ParameterName(\"VTEC\", \"sphericalHarmonics.c_\"+n%\"%i\"s+\"_\"+m%\"%i\"s));\n        baseNames.push_back(ParameterName(\"VTEC\", \"sphericalHarmonics.s_\"+n%\"%i\"s+\"_\"+m%\"%i\"s));\n      }\n    }\n\n    std::vector<ParameterName> temporalNames;\n    temporal->parameterName(temporalNames);\n    for(UInt i=0; i<temporalNames.size(); i++)\n    {\n      std::vector<ParameterName> parameterNames = baseNames;\n      for(ParameterName &name : parameterNames)\n        name.combine(temporalNames.at(i));\n      index.push_back(normalEquationInfo.parameterNamesOther(parameterNames));\n    }\n\n    if(temporalNames.size() && baseNames.size())\n      logInfo<<(temporalNames.size()*baseNames.size())%\"%9i VTEC map parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereMap::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(UInt i=0; i<index.size(); i++)\n        copy(x.at(i), x0.row(normalEquationInfo.index(index.at(i)), x.at(i).rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// intersection point in ionosphere height\nVector3d GnssParametrizationIonosphereMap::intersection(const Double radiusIono, const Vector3d &posRecv, const Vector3d &posTrans) const\n{\n  try\n  {\n    const Double   rRecv = std::min(posRecv.r(), radiusIono); // LEO satellites flying possibly higher\n    const Vector3d k     = normalize(posRecv-posTrans);       // direction from transmitter\n    const Double   rk    = inner(posRecv, k);\n    return posRecv - (std::sqrt(rk*rk+radiusIono*radiusIono-rRecv*rRecv)+rk) * k;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationIonosphereMap::mapping(Angle elevation) const\n{\n  return 1./std::cos(std::asin(mapR/(mapR+mapH) * std::sin(mapAlpha*(PI/2-elevation))));\n}\n\n/***********************************************/\n\nDouble GnssParametrizationIonosphereMap::sphericalHarmonicSynthesis(const Vector3d &point, const Vector &x) const\n{\n  try\n  {\n    Matrix Cnm, Snm;\n    SphericalHarmonics::CnmSnm(normalize(point), maxDegree, Cnm, Snm);\n    Double VTEC  = 0;\n    UInt   count = 0;\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      VTEC += Cnm(n,0) * x(count++);\n      for(UInt m=1; m<=n; m++)\n      {\n        VTEC += Cnm(n,m) * x(count++);\n        VTEC += Snm(n,m) * x(count++);\n      }\n    }\n    return VTEC;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereMap::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    if(!index.size() || !selectedReceivers.at(eqn.receiver->idRecv()))\n      return;\n\n    // spatial representation\n    Matrix Cnm, Snm;\n    const Rotary3d rot   = magnetosphere->rotaryCelestial2SolarGeomagneticFrame(eqn.timeRecv);\n    const Vector3d point = rot.rotate(intersection(radiusIono, eqn.posRecv, eqn.posTrans));\n    SphericalHarmonics::CnmSnm(normalize(point), maxDegree, Cnm, Snm);\n    Matrix Ynm(1, (maxDegree+1)*(maxDegree+1));\n    UInt count = 0;\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      Ynm(0, count++) = Cnm(n,0);\n      for(UInt m=1; m<=n; m++)\n      {\n        Ynm(0, count++) = Cnm(n,m);\n        Ynm(0, count++) = Snm(n,m);\n      }\n    }\n\n    // VTEC -> STEC\n    Matrix B(eqn.l.rows(), Ynm.columns());\n    matMult(mapping(eqn.elevationRecvLocal), eqn.A.column(GnssObservationEquation::idxSTEC), Ynm, B);\n\n    // temporal representation\n    std::vector<UInt>   idx;\n    std::vector<Double> factor;\n    temporal->factors(eqn.timeRecv, idx, factor);\n    for(UInt i=0; i<factor.size(); i++)\n      axpy(factor.at(i), B, A.column(index.at(idx.at(i))));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationIonosphereMap::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    if(!index.size())\n      return 0;\n\n    // update parameters\n    // -----------------\n    for(UInt i=0; i<index.size(); i++)\n      this->x.at(i) += x.row(normalEquationInfo.index(index.at(i)), this->x.at(i).rows());\n\n    // update STEC\n    // -----------\n    Gnss::InfoParameterChange info(\"tec\");\n    for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n    {\n      // temporal representation\n      std::vector<UInt>   idx;\n      std::vector<Double> factor;\n      Vector dx((maxDegree+1)*(maxDegree+1));\n      temporal->factors(gnss->times.at(idEpoch), idx, factor);\n      for(UInt i=0; i<factor.size(); i++)\n        axpy(factor.at(i), x.row(normalEquationInfo.index(index.at(idx.at(i))), dx.rows()), dx);\n\n      for(auto recv : gnss->receivers)\n        if(recv->isMyRank() && recv->useable(idEpoch) && selectedReceivers.at(recv->idRecv()) && normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n          for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n            if(recv->observation(idTrans, idEpoch))\n            {\n              GnssObservationEquation eqn(*recv->observation(idTrans, idEpoch), *recv, *gnss->transmitters.at(idTrans), gnss->funcRotationCrf2Trf,\n                                          nullptr/*reduceModels*/, idEpoch, FALSE/*homogenize*/, {}/*types*/);\n              // spatial representation\n              const Rotary3d rot   = magnetosphere->rotaryCelestial2SolarGeomagneticFrame(eqn.timeRecv);\n              const Double   dVTEC = sphericalHarmonicSynthesis(rot.rotate(intersection(radiusIono, eqn.posRecv, eqn.posTrans)), dx);\n              recv->observation(idTrans, idEpoch)->STEC += mapping(eqn.elevationRecvLocal) * dVTEC;\n              if(info.update(dVTEC))\n                info.info = \"VTEC map (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n            } // for(recv, trans)\n    } // for(idEpoch)\n\n    Double maxChange = 0;\n    info.synchronizeAndPrint(normalEquationInfo.comm, 0, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereMap::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name) || !Parallel::isMaster(normalEquationInfo.comm) || fileNameOut.empty())\n      return;\n\n    logStatus<<\"write ionosphere gridded time series to file <\"<<fileNameOut.appendBaseName(suffix)<<\">\"<<Log::endl;\n    std::vector<Matrix> data(timesOut.size(), Vector(gridOut.points.size()));\n\n    // apriori model\n    // -------------\n    if(!fileNameIn.empty())\n    {\n      InFileGriddedDataTimeSeries file(fileNameIn);\n      GriddedDataRectangular gridFile;\n      if(!gridFile.init(file.grid()))\n        throw(Exception(fileNameIn.str()+\" must contain a rectangular grid\"));\n      if((timesOut.front() < file.times().front()) || (timesOut.back() > file.times().back()))\n        throw(Exception(\"wrong time interval [\"+file.times().front().dateTimeStr()+\", \"+file.times().back().dateTimeStr()+\"] in <\"+fileNameIn.str()+\">\"));\n\n      UInt indexData = file.nodeCount();\n      std::vector<Vector>   griddedVTEC(file.splineDegree()+1);\n      std::vector<Rotary3d> rotSmf2Trf(file.splineDegree()+1); // SolarGeomagneticFrame -> Terrestrial\n\n      for(UInt idEpoch=0; idEpoch<timesOut.size(); idEpoch++)\n      {\n        // find time interval and read missing nodes\n        const UInt idx = std::min(static_cast<UInt>(std::distance(file.times().begin(),\n                                                                  std::upper_bound(file.times().begin(), file.times().end(), timesOut.at(idEpoch)))), file.times().size()-1)-1;\n        const UInt start = (idx > indexData) ? std::max(idx, indexData+griddedVTEC.size()) : idx;\n        const UInt end   = (idx > indexData) ? idx+griddedVTEC.size() : std::min(idx+griddedVTEC.size(), indexData);\n        for(UInt i=start; i<end; i++)\n        {\n          griddedVTEC.at(i%griddedVTEC.size()) = file.data(i).column(0);\n          rotSmf2Trf.at(i%griddedVTEC.size())  = gnss->rotationCrf2Trf(file.times().at(i)) * inverse(magnetosphere->rotaryCelestial2SolarGeomagneticFrame(file.times().at(i)));\n        }\n        indexData = idx;\n\n        // prepare spline interpolation\n        const Double t     = (timesOut.at(idEpoch)-file.times().at(idx)).mjd()/(file.times().at(idx+1)-file.times().at(idx)).mjd();\n        const Vector coeff = BasisSplines::compute(t, file.splineDegree());\n\n        // Terrestrial -> SolarGeomagneticFrame\n        const Rotary3d rotTrf2Smf = magnetosphere->rotaryCelestial2SolarGeomagneticFrame(timesOut.at(idEpoch)) * inverse(gnss->rotationCrf2Trf(timesOut.at(idEpoch)));\n\n        for(UInt i=0; i<gridOut.points.size(); i++)\n        {\n          Vector3d point = rotTrf2Smf.rotate(gridOut.points.at(i));\n          Double VTEC = 0;\n          for(UInt i=0; i<coeff.rows(); i++)\n            VTEC += coeff(i) * interpolateGrid(rotSmf2Trf.at((indexData+i)%griddedVTEC.size()).rotate(point), gridFile, griddedVTEC.at((indexData+i)%griddedVTEC.size()));\n          data.at(idEpoch)(i, 0) += VTEC;\n        }\n      }\n    } // if(!fileNameIn.empty())\n\n    // estimated VTEC maps\n    // -------------------\n    if(x.size())\n      for(UInt idEpoch=0; idEpoch<timesOut.size(); idEpoch++)\n      {\n        // temporal representation\n        std::vector<UInt>   idx;\n        std::vector<Double> factor;\n        Vector xt((maxDegree+1)*(maxDegree+1));\n        temporal->factors(timesOut.at(idEpoch), idx, factor);\n        for(UInt i=0; i<factor.size(); i++)\n          axpy(factor.at(i), x.at(idx.at(i)), xt);\n        const Rotary3d rot = magnetosphere->rotaryCelestial2SolarGeomagneticFrame(timesOut.at(idEpoch))\n                           * inverse(gnss->rotationCrf2Trf(timesOut.at(idEpoch))); // mag frame -> TRF\n        for(UInt i=0; i<gridOut.points.size(); i++)\n          data.at(idEpoch)(i, 0) += sphericalHarmonicSynthesis(rot.rotate(gridOut.points.at(i)), xt);\n      } // for(idEpoch)\n\n    writeFileGriddedDataTimeSeries(fileNameOut.appendBaseName(suffix), 1, timesOut, gridOut, data);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationIonosphereMap.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationIonosphereMap.h\n*\n* @brief IonosphereMap.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONIONOSPHEREMAP__\n#define __GROOPS_GNSSPARAMETRIZATIONIONOSPHEREMAP__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationIonosphereMap = R\"(\n\\subsection{IonosphereMap}\\label{gnssParametrizationType:ionosphereMap}\nApriori VTEC maps can be removed from the observations with\n\\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\n(e.g. from \\program{GnssIonex2GriddedDataTimeSeries}).\n\nThe ionosphere is parametrized in terms of $[TECU]$ in a single layer sphere with\n\\config{radiusIonosphericLayer} as a \\configClass{temporal}{parametrizationTemporalType}ly\nchanging (e.g. hourly linear splines) spherical harmonics expansion\n\\begin{equation}\n  VTEC(\\lambda,\\theta,t) = \\sum_{n=0}^{n_{max}} \\sum_{m=0}^n c_{nm}(t)C_{nm}(\\lambda,\\theta)+s_{nm}(t)S_{nm}(\\lambda,\\theta)\n\\end{equation}\nup to \\config{maxDegree}=\\verb|15| in a solar-geomagentic frame defined\nby \\configClass{magnetosphere}{magnetosphereType}. The VTEC values are mapped to STEC values\nin the observation equations via eq.~\\eqref{gnssParametrizationType:IonosphereVTEC:STEC}.\n\nThe estimated VTEC inclusive the apriori \\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\ncan be written to \\configFile{outputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nevaluated at \\configClass{outputGrid}{gridType} and \\configClass{outputTimeSeries}{timeSeriesType}.\n\nLocal and short-term scintillations should be considered by adding constrained\n\\configClass{parametrization:ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}.\nTo account for signal biases add\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|VTEC:sphericalHarmonics.c_<degree>_<order>:<temporal>:<interval>|,\n\\item \\verb|VTEC:sphericalHarmonics.s_<degree>_<order>:<temporal>:<interval>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/griddedData.h\"\n#include \"config/config.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief IonosphereMap.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationIonosphereMap : public GnssParametrizationBase\n{\n  Gnss                           *gnss;\n  std::string                     name;\n  PlatformSelectorPtr             selectReceivers;\n  std::vector<Byte>               selectedReceivers;\n  FileName                        fileNameIn, fileNameOut;\n  GriddedData                     gridOut;\n  std::vector<Time>               timesOut;\n  UInt                            maxDegree;\n  ParametrizationTemporalPtr      temporal;\n  Double                          radiusIono, mapR, mapH, mapAlpha;\n  MagnetospherePtr                magnetosphere;\n  std::vector<Vector>             x;\n  std::vector<GnssParameterIndex> index;\n\n  Vector3d intersection(const Double radiusIono, const Vector3d &posRecv, const Vector3d &posTrans) const;\n  Double   mapping(Angle elevation) const;\n  Double   sphericalHarmonicSynthesis(const Vector3d &point, const Vector &x) const;\n\npublic:\n  GnssParametrizationIonosphereMap(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationIonosphereSTEC.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationIonosphereSTEC.cpp\n*\n* @brief IonosphereSTEC.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationIonosphereSTEC.h\"\n\n/***********************************************/\n\nGnssParametrizationIonosphereSTEC::GnssParametrizationIonosphereSTEC(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                    name,              Config::OPTIONAL, \"parameter.STEC\", \"used for parameter selection\");\n    readConfig(config, \"apply2ndOrderCorrection\", apply2ndOrder,     Config::DEFAULT,  \"1\", \"apply ionospheric correction\");\n    readConfig(config, \"apply3rdOrderCorrection\", apply3rdOrder,     Config::DEFAULT,  \"1\", \"apply ionospheric correction\");\n    readConfig(config, \"applyBendingCorrection\",  applyBending,      Config::DEFAULT,  \"1\", \"apply ionospheric correction\");\n    readConfig(config, \"magnetosphere\",           magnetosphere,     Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"nameConstraint\",          nameConstraint,    Config::OPTIONAL, \"constraint.STEC\", \"used for parameter selection\");\n    readConfig(config, \"sigmaSTEC\",               exprSigmaSTEC,     Config::DEFAULT,  \"0\",  \"expr. for sigma [TECU] for STEC constraint, variable E (elevation) available\");\n    if(isCreateSchema(config)) return;\n\n    apply1stOrder = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereSTEC::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->gnss = gnss;\n    estimateSTEC    = TRUE;\n    applyConstraint = FALSE;\n\n    // can exprSigmaSTEC be evaluated to a constant?\n    // ---------------------------------------------\n    isSigmaSTEC = FALSE;\n    VariableList varList;\n    varList.undefineVariable(\"E\");\n    exprSigmaSTEC->simplify(varList);\n    try\n    {\n      // can evaluate? -> sigmaSTEC is constant -> fast version\n      const Double sigmaSTEC = exprSigmaSTEC->evaluate(varList);\n      isSigmaSTEC = (sigmaSTEC > 0);\n      exprSigmaSTEC = nullptr;\n\n      for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n        for(auto recv : gnss->receivers)\n          if(recv->isMyRank() && recv->useable(idEpoch))\n            for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n              if(recv->observation(idTrans, idEpoch))\n                recv->observation(idTrans, idEpoch)->sigmaSTEC = sigmaSTEC;\n    }\n    catch(std::exception &/*e*/)\n    {\n    }\n\n    // sigmaSTEC is still an expression\n    if(exprSigmaSTEC)\n    {\n      logStatus<<\"compute STEC accuracy\"<<Log::endl;\n      isSigmaSTEC = TRUE;\n      VariableList varList;\n      Log::Timer timer(gnss->times.size());\n      for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n      {\n        timer.loopStep(idEpoch);\n        for(auto recv : gnss->receivers)\n          if(recv->isMyRank() && recv->useable(idEpoch))\n            for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n              if(recv->observation(idTrans, idEpoch))\n              {\n                GnssObservationEquation eqn(*recv->observation(idTrans, idEpoch), *recv, *gnss->transmitters.at(idTrans), gnss->funcRotationCrf2Trf,\n                                            nullptr/*reduceModels*/, idEpoch, FALSE/*homogenize*/, {}/*types*/);\n                varList.setVariable(\"E\", eqn.elevationRecvLocal);\n                recv->observation(idTrans, idEpoch)->sigmaSTEC = exprSigmaSTEC->evaluate(varList);\n              } // for(recv, trans)\n      } // for(idEpoch)\n      Parallel::barrier(comm);\n      timer.loopEnd();\n    } // if(isSigmaSTEC)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereSTEC::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    estimateSTEC    = isEnabled(normalEquationInfo, name);\n    applyConstraint = FALSE;\n    if(!estimateSTEC)\n      return;\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && isSigmaSTEC;\n\n    UInt count = 0;\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n            if(recv->observation(idTrans, idEpoch))\n              count++;\n    Parallel::reduceSum(count, 0, normalEquationInfo.comm);\n    logInfo<<count%\"%9i \"s<<(applyConstraint ? \"constrained \" : \"\")<<\"STEC parameters (preeliminated)\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereSTEC::observationCorrections(GnssObservationEquation &eqn) const\n{\n  try\n  {\n    const Double STEC = eqn.STEC;\n\n    // ionospheric correction, notation see:\n    // Fritsche, M., R. Dietrich, C. Knoefel, A. Ruelke, S. Vey, M. Rothacher, and P. Steigenberger (2005),\n    // Impact of higher-order ionospheric terms on GPS estimates,\n    // Geophys. Res. Lett., 32, L23311, doi:10.1029/2005GL024342.\n    // ----------------------------------------------------------\n    // second order magentic effect\n    constexpr Double   radiusIono  = 6371e3+450e3;                          // single layer ionosphere in 450 km\n    const     Double   rRecv       = std::min(eqn.posRecv.r(), radiusIono); // LEO satellites flying possibly higher\n    const     Vector3d k           = normalize(eqn.posRecv-eqn.posTrans);   // direction from transmitter\n    const     Double   rk          = inner(eqn.posRecv, k);\n    const     Vector3d piercePoint = eqn.posRecv - (std::sqrt(rk*rk+radiusIono*radiusIono-rRecv*rRecv)+rk) * k;\n    const     Rotary3d rotEarth    = Planets::celestial2TerrestrialFrame(eqn.timeRecv);\n    const     Vector3d b           = rotEarth.inverseRotate(magnetosphere->magenticFieldVector(eqn.timeRecv, rotEarth.rotate(piercePoint))); // magentic field vector in CRF\n    const     Double   s           = 1e16*7527.*LIGHT_VELOCITY*inner(b, k);\n    // third order\n    constexpr Double r = 1e16*(2437 * 0.66 * (20.-6.)/(4.55-1.38)*1e-6) * 1e16;\n    // bending\n    constexpr Double HF2     = 70;                                                                           // F2 layer scale height\n    const     Double hmF2    = std::max(350e3, eqn.posRecv.r() - DEFAULT_R + 50e3)/1000;                     // single layer ionosphere in 350 km or 50 km above satellite\n    const     Double bending =  7.5*1e31*std::exp(-2.13*eqn.elevationRecvLocal)/(HF2*std::pow(hmF2, 0.125))  // Bending, Hoque and Jakowski 2008, approx formula\n                             + -Ionosphere::Ap*0.1108*1e16*std::exp(-2.1844*eqn.elevationRecvLocal)/(HF2*std::pow(hmF2, 0.3));  // + TEC difference bending effect, Hoque and Jakowski 2008\n\n    eqn.B = Vector(eqn.types.size());\n    for(UInt i=0; i<eqn.types.size(); i++)\n    {\n      const Double f1 = eqn.types.at(i).frequency();\n      const Double f2 = f1*f1;\n      const Double f3 = f1*f2;\n      const Double f4 = f1*f3;\n\n      // phase observations\n      if(eqn.types.at(i) == GnssType::PHASE)\n      {\n        if(apply1stOrder) eqn.l(i)   -= -Ionosphere::Ap/f2 * STEC;     // 1. order ionosphere correction (in terms of TEC)\n        if(apply1stOrder) eqn.B(i,0) += -Ionosphere::Ap/f2;\n        if(apply2ndOrder) eqn.l(i)   -= -s/2/f3 * STEC;                // 2. order ionosphere correction (in terms of TEC)\n        if(apply2ndOrder) eqn.B(i,0) += -s/2/f3;\n        if(apply3rdOrder) eqn.l(i)   -= -r/3/f4 * std::pow(STEC, 2);   // 3. order ionosphere correction (in terms of TEC)\n        if(apply3rdOrder) eqn.B(i,0) += -r/3/f4 * 2*STEC;\n        if(applyBending)  eqn.l(i)   -=  bending/f4*std::pow(STEC, 2); // Bending, Hoque and Jakowski 2008, approx formula\n        if(applyBending)  eqn.B(i,0) +=  bending/f4 * 2*STEC;\n      }\n\n      // range observations\n      if(eqn.types.at(i) == GnssType::RANGE)\n      {\n        if(apply1stOrder) eqn.l(i)   -= Ionosphere::Ap/f2 * STEC; // 1. order ionosphere correction (in terms of TEC)\n        if(apply1stOrder) eqn.B(i,0) += Ionosphere::Ap/f2;\n        if(apply2ndOrder) eqn.l(i)   -= s/f3  * STEC;             // 2. order ionosphere correction (in terms of TEC)\n        if(apply2ndOrder) eqn.B(i,0) += s/f3;\n        if(apply3rdOrder) eqn.l(i)   -= r/f4 * std::pow(STEC, 2); // 3. order ionosphere correction (in terms of TEC)\n        if(apply3rdOrder) eqn.B(i,0) += r/f4 * 2*STEC;\n      }\n    }\n    copy(eqn.B, eqn.A.column(GnssObservationEquation::idxSTEC));\n    if(!estimateSTEC)\n      eqn.B = Vector();\n\n    // add additional constraining equation\n    // ------------------------------------\n    if(applyConstraint && (eqn.sigmaSTEC > 0) && !std::isnan(eqn.sigmaSTEC))\n    {\n      // extend l, A, and B by one row\n      for(Matrix &A : std::vector<std::reference_wrapper<Matrix>>{eqn.l, eqn.A, eqn.B})\n      {\n        const Matrix A0 = A;\n        A = Matrix(A0.rows()+1, A0.columns());\n        copy(A0, A.row(0, A0.rows()));\n      }\n\n      // constrain STEC;\n      eqn.l(eqn.l.rows()-1)    = -eqn.dSTEC/eqn.sigmaSTEC; // constrain towards zero (0-f(x0))\n      eqn.B(eqn.B.rows()-1, 0) =  1./eqn.sigmaSTEC;        // in TECU\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationIonosphereSTEC.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationIonosphereSTEC.h\n*\n* @brief IonosphereSTEC.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONIONOSPHERESTEC__\n#define __GROOPS_GNSSPARAMETRIZATIONIONOSPHERESTEC__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationIonosphereSTEC = R\"(\n\\subsection{IonosphereSTEC}\\label{gnssParametrizationType:ionosphereSTEC}\nThe influence of the ionosphere is modelled by a STEC parameter (slant total electron content)\nin terms of $[TECU]$ between each transmitter and receiver at each epoch. These parameters are pre-eliminated\nfrom the observation equations before accumulating the normal equations.\nThis is similar to using the ionosphere-free linear combination as observations\nbut only one STEC parameter is needed for an arbitrary number of observation types.\n\nThe influence on the code and phase observation is modeled as\n\\begin{equation}\\label{gnssParametrizationType:IonosphereSTEC:STEC}\n\\begin{split}\n\\text{ionosphere}([C\\nu], STEC) &=  \\frac{40.3}{f_{\\nu}^2}STEC + \\frac{7525\\M b^T\\M k}{f_{\\nu}^3}STEC +  \\frac{r}{f_{\\nu}^4}STEC^2 \\\\\n\\text{ionosphere}([L\\nu], STEC) &= -\\frac{40.3}{f_{\\nu}^2}STEC - \\frac{7525\\M b^T\\M k}{2f_{\\nu}^3}STEC - \\frac{r}{3f_{\\nu}^4}STEC^2 + \\text{bending}(E)STEC^2\n\\end{split}\n\\end{equation}\nThe second order term depends on the \\configClass{magnetosphere}{magnetosphereType} $\\M b$\nand the direction of the signal $\\M k$.\n\nIf further information about the ionosphere is available\n(in the form of a prior model or as additional parametrizations\nsuch as \\configClass{parametrization:ionosphereMap}{gnssParametrizationType:ionosphereMap} or\n\\configClass{parametrization:ionosphereVTEC}{gnssParametrizationType:ionosphereVTEC}) the STEC\nparameters describe local and short–term scintillations. The STEC parameters are estimated\nas additions to the model and it is advised to constrain them towards zero\nwith a standard deviation of \\config{sigmaSTEC}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief IonosphereSTEC.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationIonosphereSTEC : public GnssParametrizationBase\n{\n  Gnss                 *gnss;\n  std::string           name, nameConstraint;\n  Bool                  apply1stOrder, apply2ndOrder, apply3rdOrder, applyBending;\n  MagnetospherePtr      magnetosphere;\n  Bool                  estimateSTEC, applyConstraint, isSigmaSTEC;\n  ExpressionVariablePtr exprSigmaSTEC;\n\npublic:\n  GnssParametrizationIonosphereSTEC(Config &config);\n\n  void init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void observationCorrections(GnssObservationEquation &eqn) const override;\n  void initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationIonosphereVTEC.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationIonosphereVTEC.cpp\n*\n* @brief IonosphereVTEC.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationIonosphereVTEC.h\"\n\n/***********************************************/\n\nGnssParametrizationIonosphereVTEC::GnssParametrizationIonosphereVTEC(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",            name,                    Config::OPTIONAL, \"parameter.VTEC\", \"\");\n    readConfig(config, \"selectReceivers\", selectReceivers,         Config::MUSTSET,   R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileVTEC\",  fileNameVTEC,            Config::OPTIONAL, \"output/vtec_{loopTime:%D}.{station}.dat\", \"variable {station} available, columns: MJD, VTEC, north gradient, east gradient\");\n    readConfig(config, \"mapR\",            mapR,                    Config::DEFAULT,  \"6371e3\",     \"constant of MSLM mapping function\");\n    readConfig(config, \"mapH\",            mapH,                    Config::DEFAULT,  \"506.7e3\",    \"constant of MSLM mapping function\");\n    readConfig(config, \"mapAlpha\",        mapAlpha,                Config::DEFAULT,  \"0.9782\",     \"constant of MSLM mapping function\");\n    readConfig(config, \"gradient\",        parametrizationGradient, Config::DEFAULT,  \"\",           \"parametrization of north and east gradients\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereVTEC::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    selectedReceivers = gnss->selectReceivers(selectReceivers);\n    indexVTEC.resize(gnss->receivers.size());\n    VTEC.resize(gnss->receivers.size());\n\n    indexGradient.resize(gnss->receivers.size());\n    xGradient.resize(gnss->receivers.size());\n    gradientX.resize(gnss->receivers.size());\n    gradientY.resize(gnss->receivers.size());\n\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->useable() && recv->isMyRank())\n      {\n        VTEC.at(idRecv).resize(gnss->times.size(), 0);\n        xGradient.at(idRecv) = Vector(2*parametrizationGradient->parameterCount());\n        gradientX.at(idRecv).resize(gnss->times.size(), 0);\n        gradientY.at(idRecv).resize(gnss->times.size(), 0);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereVTEC::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    indexVTEC.clear();\n    indexVTEC.resize(gnss->receivers.size());\n    indexGradient.clear();\n    indexGradient.resize(gnss->receivers.size(),GnssParameterIndex());\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->useable() && normalEquationInfo.estimateReceiver.at(idRecv) && selectedReceivers.at(idRecv))\n      {\n        indexVTEC.at(idRecv).resize(gnss->times.size());\n        if(recv->isMyRank())\n          VTEC.at(idRecv).resize(gnss->times.size(), 0);\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(recv->useable(idEpoch))\n          {\n            indexVTEC.at(idRecv).at(idEpoch) = normalEquationInfo.parameterNamesEpochReceiver(idEpoch, idRecv, {ParameterName(recv->name(), \"VTEC\", \"\", gnss->times.at(idEpoch))});\n            countPara++;\n          }\n      }\n    }\n    if(countPara)\n      logInfo<<countPara%\"%9i VTEC epoch parameters\"s<<Log::endl;\n\n    // VTEC gradient\n    UInt countParaGradient = 0;\n    if(parametrizationGradient->parameterCount())\n      for(auto recv : gnss->receivers)\n      {\n        const UInt idRecv = recv->idRecv();\n        if(recv->useable() && normalEquationInfo.estimateReceiver.at(idRecv) && selectedReceivers.at(idRecv))\n        {\n          std::vector<ParameterName> parameterNames;\n          std::vector<ParameterName> name({{gnss->receivers.at(idRecv)->name(), \"VTECGradient.x\"}, {gnss->receivers.at(idRecv)->name(), \"VTECGradient.y\"}});\n          parametrizationGradient->parameterName(name, parameterNames);\n          indexGradient.at(idRecv) = normalEquationInfo.parameterNamesReceiver(idRecv, parameterNames);\n          countParaGradient += parameterNames.size();\n        }\n      }\n    if(countParaGradient)\n      logInfo<<countParaGradient%\"%9i VTEC gradient parameters\"s<<Log::endl;\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereVTEC::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n      {\n        const UInt idRecv = recv->idRecv();\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(indexVTEC.at(idRecv).size() && indexVTEC.at(idRecv).at(idEpoch))\n            x0(normalEquationInfo.index(indexVTEC.at(idRecv).at(idEpoch)), 0) = VTEC.at(idRecv).at(idEpoch);\n        if(indexGradient.at(idRecv))\n          copy(xGradient.at(idRecv), x0.row(normalEquationInfo.index(indexGradient.at(idRecv)), xGradient.at(idRecv).rows()));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Mapping function\nDouble GnssParametrizationIonosphereVTEC::mapping(Angle elevation) const\n{\n  return 1./std::cos(std::asin(mapR/(mapR+mapH) * std::sin(mapAlpha*(PI/2-elevation))));\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereVTEC::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    const Double map = mapping(eqn.elevationRecvLocal);\n\n    // VTEC at station per epoch\n    if(indexVTEC.at(eqn.receiver->idRecv()).size() && indexVTEC.at(eqn.receiver->idRecv()).at(eqn.idEpoch))\n      axpy(map, eqn.A.column(GnssObservationEquation::idxSTEC), A.column(indexVTEC.at(eqn.receiver->idRecv()).at(eqn.idEpoch)));\n\n    // VTEC gradient at station\n    if(indexGradient.at(eqn.receiver->idRecv()))\n    {\n      Matrix B(eqn.A.rows(), 2);\n      axpy(map*std::cos(eqn.azimutRecvLocal), eqn.A.column(GnssObservationEquation::idxSTEC), B.column(0));\n      axpy(map*std::sin(eqn.azimutRecvLocal), eqn.A.column(GnssObservationEquation::idxSTEC), B.column(1));\n      // temporal parametrization\n      std::vector<UInt>   idx;\n      std::vector<Double> factor;\n      parametrizationGradient->factors(std::max(eqn.timeRecv, gnss->times.at(0)), idx, factor);\n      MatrixSlice Design(A.column(indexGradient.at(eqn.receiver->idRecv())));\n      for(UInt i=0; i<factor.size(); i++)\n        axpy(factor.at(i), B, Design.column(B.columns()*idx.at(i), B.columns()));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationIonosphereVTEC::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return 0;\n\n    Double minVTEC   = 1e+99;\n    Double maxVTEC   = 1e-99;\n    Double meanVTEC  = 0;\n    Double stdVTEC   = 0;\n    UInt   countVTEC = 0;\n\n    Gnss::InfoParameterChange infoVTEC(\"tec\");\n    Gnss::InfoParameterChange infoGradient(\"tec\");\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n      {\n        const UInt idRecv = recv->idRecv();\n        Vector dxGradient;\n        if(indexGradient.at(idRecv))\n        {\n          dxGradient = x.row(normalEquationInfo.index(indexGradient.at(idRecv)), 2*parametrizationGradient->parameterCount());\n          xGradient.at(idRecv) += dxGradient;\n        }\n\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n        {\n          // update VTEC\n          Double dVTEC = 0;\n          if(indexVTEC.at(idRecv).size() && indexVTEC.at(idRecv).at(idEpoch))\n          {\n            dVTEC = x(normalEquationInfo.index(indexVTEC.at(idRecv).at(idEpoch)), 0);\n            VTEC.at(idRecv).at(idEpoch) += dVTEC;\n            if(infoVTEC.update(dVTEC))\n              infoVTEC.info = \"VTEC (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n\n            minVTEC   = std::min(VTEC.at(idRecv).at(idEpoch), minVTEC);\n            maxVTEC   = std::max(VTEC.at(idRecv).at(idEpoch), maxVTEC);\n            meanVTEC += VTEC.at(idRecv).at(idEpoch);\n            stdVTEC  += VTEC.at(idRecv).at(idEpoch)*VTEC.at(idRecv).at(idEpoch);\n            countVTEC++;\n          }\n\n          // update gradient\n          Double dgx=0, dgy=0;\n          if(indexGradient.at(idRecv))\n          {\n            std::vector<UInt>   index;\n            std::vector<Double> factor;\n            parametrizationGradient->factors(std::max(recv->timeCorrected(idEpoch), gnss->times.at(0)), index, factor);\n            for(UInt k=0; k<factor.size(); k++)\n            {\n              dgx += factor.at(k) * dxGradient(2*index.at(k)+0);\n              dgy += factor.at(k) * dxGradient(2*index.at(k)+1);\n            }\n            gradientX.at(idRecv).at(idEpoch) += dgx;\n            gradientY.at(idRecv).at(idEpoch) += dgy;\n            if(infoGradient.update(std::sqrt(dgx*dgx+dgy*dgy)))\n              infoGradient.info = \"VTEC gradient (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n          }\n\n          // update STEC\n          if(dVTEC || dgx || dgy)\n            for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n              if(recv->observation(idTrans, idEpoch))\n              {\n                GnssObservationEquation eqn(*recv->observation(idTrans, idEpoch), *recv, *gnss->transmitters.at(idTrans), gnss->funcRotationCrf2Trf,\n                                            nullptr/*reduceModels*/, idEpoch, FALSE/*homogenize*/, {}/*types*/);\n                recv->observation(idTrans, idEpoch)->STEC += mapping(eqn.elevationRecvLocal) * (dVTEC + std::cos(eqn.azimutRecvLocal)*dgx + std::sin(eqn.azimutRecvLocal)*dgy);\n              }\n        } // for(idEpoch)\n      } // for(recv)\n\n    // VTEC statistics\n    Parallel::reduceMin(minVTEC,   0, normalEquationInfo.comm);\n    Parallel::reduceMax(maxVTEC,   0, normalEquationInfo.comm);\n    Parallel::reduceSum(meanVTEC,  0, normalEquationInfo.comm);\n    Parallel::reduceSum(stdVTEC,   0, normalEquationInfo.comm);\n    Parallel::reduceSum(countVTEC, 0, normalEquationInfo.comm);\n    stdVTEC   = std::sqrt((stdVTEC-meanVTEC*meanVTEC/countVTEC)/(countVTEC-1));\n    meanVTEC /= countVTEC;\n    std::string infoStr = \" (total: \"+meanVTEC%\"%.2f +- \"s+stdVTEC%\"%.2f [\"s+minVTEC%\"%.2f -- \"s+maxVTEC%\"%.2f])\"s;\n    Parallel::broadCast(infoStr, 0, normalEquationInfo.comm);\n    infoVTEC.info += infoStr;\n\n    Double maxChange = 0;\n    infoVTEC.synchronizeAndPrint    (normalEquationInfo.comm, 0, maxChange);\n    infoGradient.synchronizeAndPrint(normalEquationInfo.comm, 0, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationIonosphereVTEC::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameVTEC.empty() && VTEC.size())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write VTEC to files <\"<<fileNameVTEC(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n\n      for(auto &recv : gnss->receivers)\n        if(normalEquationInfo.estimateReceiver.at(recv->idRecv()) && recv->isMyRank())\n        {\n          MiscValuesArc arc;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n          {\n            if(indexVTEC.at(recv->idRecv()).size() && indexVTEC.at(recv->idRecv()).at(idEpoch))\n            {\n              MiscValuesEpoch epoch(3);\n              epoch.time      = gnss->times.at(idEpoch);\n              epoch.values(0) = VTEC.at(recv->idRecv()).at(idEpoch);\n              epoch.values(1) = gradientX.at(recv->idRecv()).at(idEpoch);\n              epoch.values(2) = gradientY.at(recv->idRecv()).at(idEpoch);\n              arc.push_back(epoch);\n            }\n          }\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          if(arc.size())\n            InstrumentFile::write(fileNameVTEC(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationIonosphereVTEC.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationIonosphereVTEC.h\n*\n* @brief IonosphereVTEC.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONIONOSPHEREVTEC__\n#define __GROOPS_GNSSPARAMETRIZATIONIONOSPHEREVTEC__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationIonosphereVTEC = R\"(\n\\subsection{IonosphereVTEC}\\label{gnssParametrizationType:ionosphereVTEC}\nThe influence of the ionosphere is modelled by a VTEC parameter (vertical total electron content)\nin terms of $[TECU]$ for every selected receiver at each epoch. Optionally, VTEC gradients in the\nNorth (x) and East (y) direction can be estimated via \\configClass{gradient}{parametrizationTemporalType}.\nThe slant TEC is computed based on the VTEC and the optional North and East gradients $\\Delta V_x$ and $\\Delta V_y$\nusing the elevation-dependent Modified Single-Layer Model (MSLM) mapping function\n\\begin{equation}\\label{gnssParametrizationType:IonosphereVTEC:STEC}\n  STEC = \\frac{VTEC + \\cos(A) \\Delta V_x + \\sin(A) \\Delta V_y}{\\cos z'}\n  \\qquad\\text{with}\\qquad\n  \\sin z'= \\left(\\frac{R}{R+H}\\right)\\sin\\left(\\alpha(\\pi/2-E)\\right)\n\\end{equation}\ninserted into eq.~\\eqref{gnssParametrizationType:IonosphereSTEC:STEC},\nwhere $A$ is the azimuth angle and $E$ is the elevation angle.\n\nThe result is written as a \\file{times series file}{instrument} at epochs with observations\ndepending on \\configClass{GnssProcessing:processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}.\n\nThis class provides a simplified model of the ionosphere for single receivers\nand enables the separation of the TEC and signal biases, meaning\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases} becomes estimable.\nLocal and short-term scintillations should be considered by adding loosely constrained\n\\configClass{parametrization:ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:VTEC::<time>|,\n\\item \\verb|<station>:VTECGradient.x:<temporal>:<interval>|,\n\\item \\verb|<station>:VTECGradient.y:<temporal>:<interval>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief IonosphereVTEC.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationIonosphereVTEC : public GnssParametrizationBase\n{\n  Gnss                                        *gnss;\n  std::string                                  name;\n  PlatformSelectorPtr                          selectReceivers;\n  std::vector<Byte>                            selectedReceivers;\n  FileName                                     fileNameVTEC;\n  Double                                       mapR, mapH, mapAlpha;\n  std::vector<std::vector<GnssParameterIndex>> indexVTEC; // for each receiver, for each epoch\n  std::vector<std::vector<Double>>             VTEC;\n\n  ParametrizationTemporalPtr                   parametrizationGradient;\n  std::vector<GnssParameterIndex>              indexGradient; // for each receiver\n  std::vector<Vector>                          xGradient;\n  std::vector<std::vector<Double>>             gradientX, gradientY;\n\n  Double mapping(Angle elevation) const;\n\npublic:\n  GnssParametrizationIonosphereVTEC(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationKinematicPositions.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationKinematicPositions.cpp\n*\n* @brief Position estimation each epoch.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationKinematicPositions.h\"\n\n/***********************************************/\n\nGnssParametrizationKinematicPositions::GnssParametrizationKinematicPositions(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                      name,               Config::OPTIONAL, \"parameter.kinematicPositions\", \"used for parameter selection\");\n    readConfig(config, \"selectReceivers\",           selectReceivers,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfilePositions\",       fileNamePositions,  Config::OPTIONAL, \"output/positions_{loopTime:%D}.{station}.dat\",          \"variable {station} available, estimated kinematic positions/orbit\");\n    readConfig(config, \"outputfileCovarianceEpoch\", fileNameCovariance, Config::OPTIONAL, \"output/covariance3x3Epoch_{loopTime:%D}.{station}.dat\", \"variable {station} available, 3x3 epoch covariances\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    selectedReceivers = gnss->selectReceivers(selectReceivers);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::requirements(GnssNormalEquationInfo &normalEquationInfo,\n                                                         std::vector<UInt> &/*transCount*/, std::vector<UInt> &/*transCountEpoch*/,\n                                                         std::vector<UInt> &/*recvCount*/,  std::vector<UInt> &recvCountEpoch)\n{\n  try\n  {\n    if(isEnabled(normalEquationInfo, name))\n      for(auto recv : gnss->receivers)\n        if(normalEquationInfo.estimateReceiver.at(recv->idRecv()) && selectedReceivers.at(recv->idRecv()))\n          recvCountEpoch.at(recv->idRecv()) += 3;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    index.clear();\n    index.resize(gnss->receivers.size());\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto recv : gnss->receivers)\n    {\n      const UInt idRecv = recv->idRecv();\n      if(recv->useable() && selectedReceivers.at(idRecv) && normalEquationInfo.estimateReceiver.at(idRecv))\n      {\n        index.at(idRecv).resize(gnss->times.size());\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(recv->useable(idEpoch))\n          {\n            std::vector<ParameterName> parameterNames;\n            parameterNames.push_back(ParameterName(recv->name(), \"position.x\", \"\", gnss->times.at(idEpoch)));\n            parameterNames.push_back(ParameterName(recv->name(), \"position.y\", \"\", gnss->times.at(idEpoch)));\n            parameterNames.push_back(ParameterName(recv->name(), \"position.z\", \"\", gnss->times.at(idEpoch)));\n            index.at(idRecv).at(idEpoch) = normalEquationInfo.parameterNamesEpochReceiver(idEpoch, idRecv, parameterNames);\n            countPara += parameterNames.size();\n          }\n      }\n    }\n    if(countPara)\n      logInfo<<countPara%\"%9i kinematic position parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n      if(gnss->receivers.at(idRecv)->isMyRank())\n        for(UInt idEpoch=0; idEpoch<index.at(idRecv).size(); idEpoch++)\n          if(index.at(idRecv).at(idEpoch))\n            copy(gnss->receivers.at(idRecv)->pos.at(idEpoch).vector(), x0.row(normalEquationInfo.index(index.at(idRecv).at(idEpoch)), 3));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    if(index.at(eqn.receiver->idRecv()).size() && index.at(eqn.receiver->idRecv()).at(eqn.idEpoch))\n    {\n      if(eqn.receiver->isEarthFixed())\n        matMult(1., eqn.A.column(GnssObservationEquation::idxPosRecv, 3),\n                gnss->rotationCrf2Trf(eqn.timeRecv).matrix().trans(),\n                A.column(index.at(eqn.receiver->idRecv()).at(eqn.idEpoch)));\n      else\n        copy(eqn.A.column(GnssObservationEquation::idxPosRecv, 3), A.column(index.at(eqn.receiver->idRecv()).at(eqn.idEpoch)));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationKinematicPositions::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange info(\"mm\");\n    for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n      if(gnss->receivers.at(idRecv)->isMyRank())\n        for(UInt idEpoch=0; idEpoch<index.at(idRecv).size(); idEpoch++)\n          if(index.at(idRecv).at(idEpoch))\n          {\n            const Vector3d dp(x.row(normalEquationInfo.index(index.at(idRecv).at(idEpoch)), 3));\n            gnss->receivers.at(idRecv)->pos.at(idEpoch) += dp;\n            if(info.update(1e3*dp.r()))\n              info.info = \"kinematic position (\"+gnss->receivers.at(idRecv)->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n          }\n    info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    // 3x3 epoch covariance matrix\n    // ---------------------------\n    cov.resize(index.size());\n    for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n      if(gnss->receivers.at(idRecv)->isMyRank())\n      {\n        cov.at(idRecv).resize(index.at(idRecv).size());\n        for(UInt idEpoch=0; idEpoch<index.at(idRecv).size(); idEpoch++)\n          if(index.at(idRecv).at(idEpoch))\n          {\n            const UInt idBlock = normalEquationInfo.block(index.at(idRecv).at(idEpoch));\n            const UInt idx     = normalEquationInfo.index(index.at(idRecv).at(idEpoch)) - covariance.blockIndex(idBlock);\n            cov.at(idRecv).at(idEpoch).xx() = covariance.N(idBlock, idBlock)(idx+0, idx+0);\n            cov.at(idRecv).at(idEpoch).yy() = covariance.N(idBlock, idBlock)(idx+1, idx+1);\n            cov.at(idRecv).at(idEpoch).zz() = covariance.N(idBlock, idBlock)(idx+2, idx+2);\n            cov.at(idRecv).at(idEpoch).xy() = covariance.N(idBlock, idBlock)(idx+0, idx+1);\n            cov.at(idRecv).at(idEpoch).xz() = covariance.N(idBlock, idBlock)(idx+0, idx+2);\n            cov.at(idRecv).at(idEpoch).yz() = covariance.N(idBlock, idBlock)(idx+1, idx+2);\n          }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationKinematicPositions::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    VariableList fileNameVariableList;\n\n    // write kinematic orbits\n    // ----------------------\n    if(!fileNamePositions.empty())\n    {\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write kinematic position data <\"<<fileNamePositions(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n        if(gnss->receivers.at(idRecv)->isMyRank())\n        {\n          Arc arc;\n          for(UInt idEpoch=0; idEpoch<index.at(idRecv).size(); idEpoch++)\n            if(index.at(idRecv).at(idEpoch))\n            {\n              if(gnss->receivers.at(idRecv)->isEarthFixed())\n              {\n                Vector3dEpoch epoch;\n                epoch.time     = gnss->receivers.at(idRecv)->timeCorrected(idEpoch);\n                epoch.vector3d = gnss->receivers.at(idRecv)->pos.at(idEpoch);\n                arc.push_back(epoch);\n              }\n              else\n              {\n                OrbitEpoch epoch;\n                epoch.time     = gnss->receivers.at(idRecv)->timeCorrected(idEpoch);\n                epoch.position = gnss->receivers.at(idRecv)->pos.at(idEpoch);\n                arc.push_back(epoch);\n              }\n            }\n          fileNameVariableList.setVariable(\"station\", gnss->receivers.at(idRecv)->name());\n          InstrumentFile::write(fileNamePositions(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n\n    // write epoch covariance\n    // ----------------------\n    if(!fileNameCovariance.empty() && cov.size())\n    {\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write epoch covariance data <\"<<fileNameCovariance(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n       for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n        if(gnss->receivers.at(idRecv)->isMyRank() && cov.at(idRecv).size())\n        {\n          Covariance3dArc arc;\n          for(UInt idEpoch=0; idEpoch<index.at(idRecv).size(); idEpoch++)\n            if(index.at(idRecv).at(idEpoch))\n            {\n              Covariance3dEpoch epoch;\n              epoch.time       = gnss->receivers.at(idRecv)->timeCorrected(idEpoch);\n              epoch.covariance = cov.at(idRecv).at(idEpoch);\n              arc.push_back(epoch);\n            }\n          fileNameVariableList.setVariable(\"station\", gnss->receivers.at(idRecv)->name());\n          InstrumentFile::write(fileNameCovariance(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationKinematicPositions.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationKinematicPositions.h\n*\n* @brief Position estimation each epoch.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONKINEMATICPOSITIONS__\n#define __GROOPS_GNSSPARAMETRIZATIONKINEMATICPOSITIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationKinematicPositions = R\"(\n\\subsection{KinematicPositions}\\label{gnssParametrizationType:kinematicPositions}\nEstimates the epoch-wise \\configFile{outputfilePositions}{instrument}\nin an Earth-fixed frame (or in case of LEO satellites in an intertial frame).\n\nThe $3\\times3$ epoch wise \\configFile{outputfileCovarianceEpoch}{instrument}\nare computed within\n\\configClass{GnssProcessing:processingStep:computeCovarianceMatrix}{gnssProcessingStepType:computeCovarianceMatrix}\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:position.x::<time>|,\n\\item \\verb|<station>:position.y::<time>|,\n\\item \\verb|<station>:position.z::<time>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Position estimation each epoch.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationKinematicPositions : public GnssParametrizationBase\n{\n  Gnss                                        *gnss;\n  std::string                                  name;\n  PlatformSelectorPtr                          selectReceivers;\n  std::vector<Byte>                            selectedReceivers;\n  FileName                                     fileNamePositions, fileNameCovariance;\n  std::vector<std::vector<GnssParameterIndex>> index; // for each receiver, each epoch\n  std::vector<std::vector<Tensor3d>>           cov;\n\npublic:\n  GnssParametrizationKinematicPositions(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                      std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   updateCovariance(const GnssNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationLeoDynamicOrbits.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationLeoDynamicOrbits.cpp\n*\n* @brief Orbits by variational equations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationLeoDynamicOrbits.h\"\n\n/***********************************************/\n\nGnssParametrizationLeoDynamicOrbits::GnssParametrizationLeoDynamicOrbits(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr stochasticPulse;\n\n    readConfig(config, \"name\",                        name,                        Config::OPTIONAL, \"parameter.dynamicOrbits\", \"used for parameter selection\");\n    readConfig(config, \"selectReceivers\",             selectReceivers,             Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"outputfileOrbit\",             fileNameOrbit,               Config::OPTIONAL, \"\",     \"variable {station} available\");\n    readConfig(config, \"outputfileParameters\",        fileNameParameter,           Config::OPTIONAL, \"\",     \"variable {station} available\");\n    readConfig(config, \"inputfileVariational\",        fileNameVariational,         Config::MUSTSET,  \"variational_{loopTime:%D}.{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"stochasticPulse\",             stochasticPulse,             Config::DEFAULT,  \"\",     \"[mu/s] parametrization of stochastic pulses\");\n    readConfig(config, \"parametrizationAcceleration\", parametrizationAcceleration, Config::DEFAULT,  \"\",     \"orbit force parameters\");\n    readConfig(config, \"ephemerides\",                 ephemerides,                 Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"minEstimableEpochsRatio\",     minEstimableEpochsRatio,     Config::DEFAULT,  \"0.75\", \"drop satellites with lower ratio of estimable epochs to total epochs\");\n    readConfig(config, \"integrationDegree\",           integrationDegree,           Config::DEFAULT,  \"7\",    \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,         Config::DEFAULT,  \"7\",    \"for orbit interpolation and velocity calculation\");\n    if(isCreateSchema(config)) return;\n\n    pulses = stochasticPulse->times();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationLeoDynamicOrbits::~GnssParametrizationLeoDynamicOrbits()\n{\n  for(Parameter *para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationLeoDynamicOrbits::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->gnss = gnss;\n    auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(\"station\", \"****\");\n    parameters.resize(gnss->receivers.size(), nullptr);\n    Vector recvProcess(gnss->receivers.size());\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedReceivers.at(idRecv) && gnss->receivers.at(idRecv)->useable())\n      {\n        recvProcess(idRecv) = Parallel::myRank(comm)+1;\n        auto para = new Parameter();\n        parameters.at(idRecv) = para;\n        para->recv = gnss->receivers.at(idRecv);\n\n        if(!para->recv->isMyRank())\n          continue;\n\n        // find first and last valid epoch\n        Time timeStart, timeEnd;\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n          if(para->recv->useable(idEpoch))\n          {\n            timeStart = gnss->times.at(idEpoch);\n            break;\n          }\n        for(UInt idEpoch=gnss->times.size(); idEpoch-->0;)\n          if(para->recv->useable(idEpoch))\n          {\n            timeEnd = gnss->times.at(idEpoch);\n            break;\n          }\n\n        // stochastic pulses in interval\n        std::vector<Time> pulsesInterval;\n        std::copy_if(pulses.begin(), pulses.end(), std::back_inserter(pulsesInterval), [&](auto &p) {return (timeStart < p) && (p < timeEnd);});\n\n        fileNameVariableList.setVariable(\"station\", para->recv->name());\n        VariationalEquationFromFile file;\n        file.open(fileNameVariational(fileNameVariableList), nullptr/*parametrizationGravity*/, parametrizationAcceleration, pulsesInterval, ephemerides, integrationDegree);\n        para->x = Vector(file.parameterCount());\n\n        // parameter names\n        file.parameterNameSatellite(para->parameterNames);\n        file.parameterNameSatelliteArc(para->parameterNames);\n        for(auto &name : para->parameterNames)\n          name.object = para->recv->name();\n\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n          if(para->recv->useable(idEpoch))\n          {\n            const VariationalEquationArc &arc = file.getArc(gnss->times.at(idEpoch));\n\n            para->startEpoch.push_back(idEpoch);\n            while((idEpoch+1 < gnss->times.size()) && (gnss->times.at(idEpoch+1) <= arc.times.back()))\n              idEpoch++;\n            while(!para->recv->useable(idEpoch)) // go back to the last valid epoch\n              idEpoch--;\n            para->endEpoch.push_back(idEpoch);\n\n            auto variationalEquation = file.integrateArc(arc.times.front(), arc.times.back(), TRUE/*computePosition*/, TRUE/*computeVelocity*/);\n            para->times.emplace_back(variationalEquation.times);\n            para->PosDesign.emplace_back(variationalEquation.PosDesign);\n            para->VelDesign.emplace_back(variationalEquation.VelDesign);\n            para->pos.emplace_back(variationalEquation.pos0);\n            para->vel.emplace_back(variationalEquation.vel0);\n            para->polynomial.emplace_back(para->times.back(), interpolationDegree, TRUE/*throwException*/, FALSE/*leastSquares*/, -(interpolationDegree+1.1), -1.1, 1e-7);\n\n            std::vector<Time> times;\n            for(UInt idEpoch=para->startEpoch.back(); idEpoch<=para->endEpoch.back(); idEpoch++)\n              if(para->recv->useable(idEpoch))\n                times.push_back(para->recv->timeCorrected(idEpoch));\n\n            const Vector pos = para->polynomial.back().interpolate(times, para->pos.back(), 3);\n            const Vector vel = para->polynomial.back().interpolate(times, para->vel.back(), 3);\n            UInt i=0;\n            for(UInt idEpoch=para->startEpoch.back(); idEpoch<=para->endEpoch.back(); idEpoch++)\n              if(para->recv->useable(idEpoch))\n              {\n                para->recv->pos.at(idEpoch) = Vector3d(pos.row(3*i, 3));\n                para->recv->vel.at(idEpoch) = Vector3d(vel.row(3*i, 3));\n                i++;\n              }\n          } // for(idEpoch)\n      } // for(idRecv)\n\n    // distribute process id of receivers\n    Parallel::reduceSum(recvProcess, 0, comm);\n    Parallel::broadCast(recvProcess, 0, comm);\n\n    // synchronize parameter names\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(recvProcess(idRecv))\n        Parallel::broadCast(parameters.at(idRecv)->parameterNames, static_cast<UInt>(recvProcess(idRecv)-1), comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationLeoDynamicOrbits::requirements(GnssNormalEquationInfo &normalEquationInfo,\n                                                       std::vector<UInt> &/*transCount*/, std::vector<UInt> &/*transCountEpoch*/,\n                                                       std::vector<UInt> &recvCount,  std::vector<UInt> &/*recvCountEpoch*/)\n{\n  try\n  {\n    if(isEnabled(normalEquationInfo, name))\n      for(auto para : parameters)\n        if(para && para->recv->isMyRank())\n         recvCount.at(para->recv->idRecv()) += static_cast<UInt>(minEstimableEpochsRatio * normalEquationInfo.idEpochs.size());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationLeoDynamicOrbits::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n   for(auto para : parameters)\n      if(para)\n        para->index = GnssParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto para : parameters)\n      if(para && para->recv->useable() && normalEquationInfo.estimateReceiver.at(para->recv->idRecv()))\n      {\n        para->index = normalEquationInfo.parameterNamesReceiver(para->recv->idRecv(), para->parameterNames);\n        countPara += para->parameterNames.size();\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i dynamic orbit parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationLeoDynamicOrbits::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para && para->index && para->recv->isMyRank())\n        copy(para->x, x0.row(normalEquationInfo.index(para->index), para->x.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationLeoDynamicOrbits::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.receiver->idRecv());\n    if(para && para->index)\n    {\n      const UInt arcNo = std::distance(para->endEpoch.begin(), std::upper_bound(para->endEpoch.begin(), para->endEpoch.end(), eqn.idEpoch,\n                                       [&](UInt idEpoch, UInt end) {return idEpoch <= end;}));\n      matMult(1., eqn.A.column(GnssObservationEquation::idxPosRecv, 3),\n              para->polynomial.at(arcNo).interpolate({eqn.timeRecv}, para->PosDesign.at(arcNo), 3), A.column(para->index));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationLeoDynamicOrbits::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange info(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index && para->recv->isMyRank())\n      {\n        const Vector dx = x.row(normalEquationInfo.index(para->index), para->x.rows());\n        para->x += dx;\n\n        for(UInt arcNo=0; arcNo<para->times.size(); arcNo++)\n        {\n          para->pos.at(arcNo) += para->PosDesign.at(arcNo) * dx;\n          para->vel.at(arcNo) += para->VelDesign.at(arcNo) * dx;\n\n          std::vector<Time> times;\n          for(UInt idEpoch=para->startEpoch.at(arcNo); idEpoch<=para->endEpoch.at(arcNo); idEpoch++)\n            if(para->recv->useable(idEpoch))\n              times.push_back(para->recv->timeCorrected(idEpoch));\n\n          const Vector pos = para->polynomial.at(arcNo).interpolate(times, para->pos.at(arcNo), 3);\n          const Vector vel = para->polynomial.at(arcNo).interpolate(times, para->vel.at(arcNo), 3);\n          UInt i=0;\n          for(UInt idEpoch=para->startEpoch.at(arcNo); idEpoch<=para->endEpoch.at(arcNo); idEpoch++)\n            if(para->recv->useable(idEpoch))\n            {\n              const Vector3d dpos = Vector3d(pos.row(3*i, 3)) - para->recv->pos.at(idEpoch);\n              para->recv->pos.at(idEpoch) = Vector3d(pos.row(3*i, 3));\n              para->recv->vel.at(idEpoch) = Vector3d(vel.row(3*i, 3));\n              if(info.update(1e3*dpos.r()))\n                info.info = \"position receiver (\"+para->recv->name()+\", \"+times.at(i).dateTimeStr()+\")\";\n              i++;\n            }\n        }\n      }\n    info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationLeoDynamicOrbits::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameOrbit.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"***\");\n      logStatus<<\"write receiver orbits to files <\"<<fileNameOrbit(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index && para->recv->isMyRank())\n        {\n          std::vector<OrbitArc> arcList;\n          for(UInt arcNo=0; arcNo<para->times.size(); arcNo++)\n          {\n            OrbitArc arc;\n            for(UInt idEpoch=0; idEpoch<para->times.at(arcNo).size(); idEpoch++)\n            {\n              OrbitEpoch epoch;\n              epoch.time     = para->times.at(arcNo).at(idEpoch);\n              epoch.position = Vector3d(para->pos.at(arcNo).row(3*idEpoch, 3));\n              epoch.velocity = Vector3d(para->vel.at(arcNo).row(3*idEpoch, 3));\n              arc.push_back(epoch);\n            }\n            arcList.push_back(arc);\n          }\n          fileNameVariableList.setVariable(\"station\", para->recv->name());\n          InstrumentFile::write(fileNameOrbit(fileNameVariableList).appendBaseName(suffix), arcList);\n        }\n    }\n\n    if(!fileNameParameter.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"***\");\n      logStatus<<\"write estimated receiver parameters to files <\"<<fileNameParameter(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index && para->recv->isMyRank())\n        {\n          fileNameVariableList.setVariable(\"station\", para->recv->name());\n          writeFileMatrix(fileNameParameter(fileNameVariableList).appendBaseName(suffix), para->x);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationLeoDynamicOrbits.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationLeoDynamicOrbits.h\n*\n* @brief Orbits by variational equations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONLEODYNAMICORBITS__\n#define __GROOPS_GNSSPARAMETRIZATIONLEODYNAMICORBITS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationLeoDynamicOrbits = R\"(\n\\subsection{LeoDynamicOrbits}\\label{gnssParametrizationType:leoDynamicOrbits}\nThe estimation of (reduced) dynamic orbits is formulated as variational equations.\nIt is based on \\configFile{inputfileVariational}{variationalEquation} calculated with \\program{PreprocessingVariationalEquation}.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree \\config{integrationDegree}.\nThe \\configClass{parametrizationAcceleration}{parametrizationAccelerationType} must include at least those\nparameters that were estimated in \\program{PreprocessingVariationalEquationOrbitFit}.\nAdditional \\configClass{stochasticPulse}{timeSeriesType} parameters can be set up to reduce orbit mismodeling.\nIf not enough epochs with observations are available (\\config{minEstimableEpochsRatio}) the LEO satellite is disabled.\n\nThe parameters and \\file{parameter names}{parameterName} are divided into global\n\\begin{itemize}\n\\item \\verb|<station>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<station>:stochasticPulse.x::<time>|,\n\\item \\verb|<station>:stochasticPulse.y::<time>|,\n\\item \\verb|<station>:stochasticPulse.z::<time>|,\n\\end{itemize}\nand arc related parameters\n\\begin{itemize}\n\\item \\verb|<station>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<station>:arc<no>.position0.x::|,\n\\item \\verb|<station>:arc<no>.position0.y::|,\n\\item \\verb|<station>:arc<no>.position0.z::|.\n\\item \\verb|<station>:arc<no>.velocity0.x::|,\n\\item \\verb|<station>:arc<no>.velocity0.y::|,\n\\item \\verb|<station>:arc<no>.velocity0.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Orbits by variational equations.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationLeoDynamicOrbits : public GnssParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    GnssReceiverPtr                recv;\n    GnssParameterIndex             index;\n    std::vector<ParameterName>     parameterNames;\n    Vector                         x;\n    // for each arc:\n    std::vector<UInt>              startEpoch, endEpoch;\n    std::vector<std::vector<Time>> times;\n    std::vector<Matrix>            PosDesign, VelDesign;\n    std::vector<Vector>            pos, vel;\n    std::vector<Polynomial>        polynomial;\n  };\n\n  Gnss                          *gnss;\n  std::string                    name;\n  PlatformSelectorPtr            selectReceivers;\n  FileName                       fileNameOrbit, fileNameParameter, fileNameVariational;\n  std::vector<Time>              pulses;\n  ParametrizationAccelerationPtr parametrizationAcceleration;\n  EphemeridesPtr                 ephemerides;\n  Double                         minEstimableEpochsRatio;\n  UInt                           integrationDegree, interpolationDegree;\n  std::vector<Parameter*>        parameters; // for each receiver\n\npublic:\n  GnssParametrizationLeoDynamicOrbits(Config &config);\n ~GnssParametrizationLeoDynamicOrbits();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                      std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationReceiverAntennas.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationReceiverAntennas.cpp\n*\n* @brief Antenna center variations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationReceiverAntennas.h\"\n\n/***********************************************/\n\nGnssParametrizationReceiverAntennas::GnssParametrizationReceiverAntennas(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                    name,                Config::OPTIONAL, \"parameter.receiverAntenna\", \"used for parameter selection\");\n    readConfig(config, \"selectReceivers\",         selectReceivers,     Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"antennaCenterVariations\", parametrization,     Config::MUSTSET,  \"\",  \"estimate antenna center variations\");\n    readConfig(config, \"patternTypes\",            typesPattern,        Config::OPTIONAL, \"\",  \"gnssType for each pattern (first match is used)\");\n    readConfig(config, \"addNonMatchingTypes\",     addNonMatchingTypes, Config::DEFAULT,  \"1\", \"add patterns for additional observed gnssTypes that don't match any of the above\");\n    readConfig(config, \"groupAntennas\",           ignoreSerial,        Config::DEFAULT,  \"0\", \"common ACVs for same antenna build types (ignores antenna serial number)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationReceiverAntennas::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    receiver2antenna.resize(gnss->receivers.size(), NULLINDEX);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n\nvoid GnssParametrizationReceiverAntennas::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    index.clear();\n    types.clear();\n    std::fill(receiver2antenna.begin(), receiver2antenna.end(), NULLINDEX);\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    std::vector<std::string> antennaNames;\n    auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n    for(auto recv : gnss->receivers)\n      if(recv->useable() && selectedReceivers.at(recv->idRecv()) && normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n      {\n        Bool found = FALSE;\n        for(const auto &instrument : recv->platform.equipments)\n        {\n          auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n          if(antenna && (antenna->timeEnd > gnss->times.front()) && (antenna->timeStart <= gnss->times.back()))\n          {\n            if(found)\n            {\n              logWarning<<recv->name()<<\" has multiple antennas in interval -> only first one is used for parametrization/estimation\"<<Log::endl;\n              continue;\n            }\n            found = TRUE;\n\n            // not already in list?\n            const std::string name = GnssAntennaDefinition::str(antenna->name, ignoreSerial ? \"\"s : antenna->serial, antenna->radome);\n            const UInt idAnt = std::distance(antennaNames.begin(), std::find(antennaNames.begin(), antennaNames.end(), name));\n            if(idAnt >= antennaNames.size())\n            {\n              antennaNames.push_back(name);\n              types.resize(antennaNames.size());\n            }\n            receiver2antenna.at(recv->idRecv()) = idAnt;\n\n            // add observed types\n            for(const auto &typesRecv : gnss->typesRecvTrans.at(recv->idRecv()))\n              for(GnssType typeObs : typesRecv)\n                if(!typeObs.isInList(types.at(idAnt)))\n                {\n                  UInt idx;\n                  if(typeObs.isInList(typesPattern, idx))\n                    types.at(idAnt).push_back(typesPattern.at(idx));\n                  else if(addNonMatchingTypes)\n                    types.at(idAnt).push_back(typeObs & ~GnssType::PRN);\n                }\n          } // for(antenna)\n        }\n      } // for(recv)\n\n    // setup parameters\n    // ----------------\n    UInt countPara = 0;\n    std::vector<ParameterName> baseNames;\n    parametrization->parameterName(baseNames);\n    index.resize(antennaNames.size());\n    for(UInt idAnt=0; idAnt<antennaNames.size(); idAnt++)\n      if(types.at(idAnt).size())\n      {\n        std::sort(types.at(idAnt).begin(), types.at(idAnt).end());\n        for(GnssType type : types.at(idAnt))\n        {\n          std::string typeStr = \".\" + type.str();\n          std::vector<ParameterName> parameterNames;\n          for(const auto &base : baseNames)\n            parameterNames.push_back(ParameterName(antennaNames.at(idAnt), base.type + typeStr, base.temporal, base.interval));\n          index.at(idAnt).push_back(normalEquationInfo.parameterNamesOther(parameterNames));\n          countPara += parameterNames.size();\n        }\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i receiver antenna parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationReceiverAntennas::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    const UInt idAnt = receiver2antenna.at(eqn.receiver->idRecv());\n    if((idAnt >= index.size()) || !index.at(idAnt).size())\n      return;\n\n    Matrix B(eqn.l.rows(), types.at(idAnt).size());\n    std::vector<Bool> used(types.at(idAnt).size(), FALSE);\n    UInt idPattern;\n    for(UInt idType=0; idType<eqn.types.size(); idType++)\n      if(eqn.types.at(idType).isInList(types.at(idAnt), idPattern))\n      {\n        axpy(1., eqn.A.column(GnssObservationEquation::idxUnit + idType), B.column(idPattern));\n        used.at(idPattern) = TRUE;\n      }\n    if(!std::any_of(used.begin(), used.end(), [](Bool x){return x;}))\n      return;\n\n    const Matrix Acv = parametrization->designMatrix(eqn.azimutRecvAnt, eqn.elevationRecvAnt);\n    for(UInt idPattern=0; idPattern<types.at(idAnt).size(); idPattern++)\n      if(used.at(idPattern))\n        matMult(1., B.column(idPattern), Acv, A.column(index.at(idAnt).at(idPattern)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationReceiverAntennas.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationReceiverAntennas.h\n*\n* @brief Antenna center variations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONRECEIVERANTENNAS__\n#define __GROOPS_GNSSPARAMETRIZATIONRECEIVERANTENNAS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationReceiverAntennas = R\"(\n\\subsection{ReceiverAntennas}\\label{gnssParametrizationType:receiverAntennas}\nThis class is for parametrization the antenna for their antenna center offsets (ACO) and\nantenna center variations (ACV) by \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}.\nThe receivers to be estimated can be selected by \\configClass{selectReceivers}{platformSelectorType}.\n\nThe amount of patterns to be estimated is configurable with a list of \\configClass{patternTypes}{gnssType}.\nFor each added \\configClass{patternTypes}{gnssType} a set of parameters will be evaluated. The observations\nwill be assigned to the first \\configClass{patternTypes}{gnssType} that matches their own.\nE.g. having the patterns: \\verb|***G| and \\verb|L1*| would lead to all GPS observations be assigned\nto the observation equations of the first pattern. The pattern type \\verb|L1*| would then consist\nof all other GNSS L1 phase observations. \\config{addNonMatchingTypes} will, if activated, create automatically patterns\nfor \\configClass{observations}{gnssType} that are not selected within the list \\configClass{patternTypes}{gnssType}.\nFurthermore, it is possible to group same antenna build types from different receivers by \\config{groupAntennas}.\nThe grouping by same antenna build ignores antenna serial numbers.\n\nTo estimate the antenna variation parameters, a longer period of observations might be necessary\nfor accurate estimations. Hence one should use this parametrization by\naccumulating normal equations from several epochs.\nThis can be accomplished as the last steps in the \\configClass{processing steps}{gnssProcessingStepType}\n by adding \\configClass{ReceiverAntennas}{gnssParametrizationType:receiverAntennas}\nto current selected parameters with \\configClass{GnssProcessing:processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations}\nand write the normal equation matrix with \\configClass{GnssProcessing:processingStep:writeNormalEquations}{gnssProcessingStepType:writeNormalEquations}.\nThe written normal equations can then be accumulated with \\program{NormalsAccumulate} and solved by \\program{NormalsSolverVCE}.\nFurther, one should apply constraints to the normal equations by \\program{GnssAntennaNormalsConstraint} since the estimation\n of ACO and ACV can lead to rank deficiencies in the normal equation matrix.\nLast the solved normal equation can be parsed to a \\file{antenna definition file}{gnssAntennaDefinition}\n with the program \\program{ParameterVector2GnssAntennaDefinition}.\n\nAs example referring to the cookbook \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork},\none could add additionally \\configClass{receiverAntennas}{gnssParametrizationType:receiverAntennas} as parametrization.\nSince the estimations are done on a daily basis for each receiver we add an additional\n\\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations} which\ndisables \\verb|parameter.receiverAntenna|. After all stations are processed together with all parameters, one\nadds \\verb|parameter.receiverAntenna| with \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}\n to the current selected parametrizations.\nThe last \\configClass{processingStep}{gnssProcessingStepType} is \\configClass{GnssProcessing:processingStep:writeNormalEquations}{gnssProcessingStepType:writeNormalEquations}\nto write the daily normal equations including the parametrization \\configClass{receiverAntennas}{gnssParametrizationType:receiverAntennas} into files.\nThese normal equation files are then processed with the programs:\n\n\\begin{itemize}\n  \\item \\program{NormalsAccumulate}: accumulates normal equations.\n  \\item \\program{GnssAntennaNormalsConstraint}: apply constraint to the normal equations.\n  \\item \\program{NormalsSolverVCE}: solves the normal equations.\n  \\item \\program{ParameterVector2GnssAntennaDefinition}: writes the solution into a \\file{antenna definition file}{gnssAntennaDefinition}\n\\end{itemize}\n\nNote that the apriori value $\\M x_0$ for this parametrization is always zero and never updated\naccording to eq.~\\eqref{gnssParametrizationType:update}.\n\nThe \\file{parameter names}{parameterName} are\n\\verb|<antennaName>:<antennaCenterVariations>.<gnssType>::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Antenna center variations.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationReceiverAntennas : public GnssParametrizationBase\n{\n  Gnss                                        *gnss;\n  std::string                                  name;\n  PlatformSelectorPtr                          selectReceivers;\n  ParametrizationGnssAntennaPtr                parametrization;\n  std::vector<GnssType>                        typesPattern;\n  Bool                                         addNonMatchingTypes;\n  Bool                                         ignoreSerial;\n  std::vector<UInt>                            receiver2antenna;\n  std::vector<std::vector<GnssParameterIndex>> index; // for each antenna and pattern\n  std::vector<std::vector<GnssType>>           types; // for each antenna and pattern\n\npublic:\n  GnssParametrizationReceiverAntennas(Config &config);\n\n  void init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationSignalBiases.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationSignalBiases.cpp\n*\n* @brief Signal biases.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationSignalBiases.h\"\n\n/***********************************************/\n\nGnssParametrizationSignalBiases::GnssParametrizationSignalBiases(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                            name,                   Config::OPTIONAL, \"parameter.signalBiases\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",              selectTransmitters,     Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectReceivers\",                 selectReceivers,        Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileSignalBiasTransmitter\", fileNameOutTransmitter, Config::OPTIONAL, \"\", \"variable {prn} available\");\n    readConfig(config, \"outputfileSignalBiasReceiver\",    fileNameOutReceiver,    Config::OPTIONAL, \"\", \"variable {station} available\");\n    readConfig(config, \"inputfileSignalBiasTransmitter\",  fileNameInTransmitter,  Config::OPTIONAL, \"\", \"variable {prn} available\");\n    readConfig(config, \"inputfileSignalBiasReceiver\",     fileNameInReceiver,     Config::OPTIONAL, \"\", \"variable {station} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationSignalBiases::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n\n    if(!fileNameInTransmitter.empty())\n    {\n      VariableList fileNameVariableList;\n      auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n      for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n        if(selectedTransmitters.at(idTrans) && gnss->transmitters.at(idTrans)->useable())\n        {\n          fileNameVariableList.setVariable(\"prn\", gnss->transmitters.at(idTrans)->name());\n          try\n          {\n            readFileGnssSignalBias(fileNameInTransmitter(fileNameVariableList), gnss->transmitters.at(idTrans)->signalBias);\n          }\n          catch(std::exception &/*e*/)\n          {\n            logWarningOnce<<\"Unable to read signal bias file <\"<<fileNameInTransmitter(fileNameVariableList)<<\">, disabling transmitter.\"<<Log::endl;\n            gnss->transmitters.at(idTrans)->disable(\"Unable to read signal bias file <\"+fileNameInTransmitter(fileNameVariableList).str()+\">\");\n          }\n        }\n    }\n\n    if(!fileNameInReceiver.empty())\n    {\n      VariableList fileNameVariableList;\n      auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n      for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n        if(selectedReceivers.at(idRecv) && gnss->receivers.at(idRecv)->useable())\n        {\n          fileNameVariableList.setVariable(\"station\", gnss->receivers.at(idRecv)->name());\n          try\n          {\n            readFileGnssSignalBias(fileNameInReceiver(fileNameVariableList), gnss->receivers.at(idRecv)->signalBias);\n          }\n          catch(std::exception &/*e*/)\n          {\n            logWarningOnce<<\"Unable to read signal bias file <\"<<fileNameInReceiver(fileNameVariableList)<<\">, disabling receiver.\"<<Log::endl;\n            gnss->receivers.at(idRecv)->disable(\"Unable to read signal bias file <\"+fileNameInReceiver(fileNameVariableList).str()+\">\");\n          }\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationSignalBiases::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameOutTransmitter.empty() && !normalEquationInfo.isEachReceiverSeparately && Parallel::isMaster(normalEquationInfo.comm))\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logStatus<<\"write transmitter signal biases to files <\"<<fileNameOutTransmitter(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n      for(auto trans : gnss->transmitters)\n        if(trans->useable() && selectedTransmitters.at(trans->idTrans()))\n        {\n          GnssSignalBias signalBias = trans->signalBias;\n          for(UInt idType=0; idType<signalBias.types.size(); idType++)\n            if(signalBias.types.at(idType) == GnssType::PHASE)\n              signalBias.biases.at(idType) = std::remainder(signalBias.biases.at(idType), signalBias.types.at(idType).wavelength());\n          fileNameVariableList.setVariable(\"prn\", trans->name());\n          writeFileGnssSignalBias(fileNameOutTransmitter(fileNameVariableList).appendBaseName(suffix), signalBias);\n        }\n    }\n\n    if(!fileNameOutReceiver.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write receiver signal biases to files <\"<<fileNameOutReceiver(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n      for(auto recv : gnss->receivers)\n        if(recv->isMyRank() && selectedReceivers.at(recv->idRecv()) && normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n        {\n          GnssSignalBias signalBias = recv->signalBias;\n          for(UInt idType=0; idType<signalBias.types.size(); idType++)\n            if(signalBias.types.at(idType) == GnssType::PHASE)\n              signalBias.biases.at(idType) = std::remainder(signalBias.biases.at(idType), signalBias.types.at(idType).wavelength());\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          writeFileGnssSignalBias(fileNameOutReceiver(fileNameVariableList).appendBaseName(suffix), signalBias);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationSignalBiases.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationSignalBiases.h\n*\n* @brief Signal biases.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONSIGNALBIASES__\n#define __GROOPS_GNSSPARAMETRIZATIONSIGNALBIASES__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationSignalBiases = R\"(\n\\subsection{SignalBiases}\\label{gnssParametrizationType:signalBiases}\nEach code and phase observation (e.g \\verb|C1C| or \\verb|L2W|) contains a bias at transmitter/receiver level\n\\begin{equation}\n  [\\tau\\nu a]_r^s(t) = \\dots + \\text{bias}[\\tau\\nu a]^s + \\text{bias}[\\tau\\nu a]_r + \\dots\n\\end{equation}\nThis class provides the apriori model $\\M f(\\M x_0)$ of eq. \\eqref{gnssParametrizationType:model} only.\n\nThe \\configFile{inputfileSignalBiasTransmitter/Receiver}{gnssSignalBias} are read\nfor each transmitter and receiver. Those file names are interpreted as a template with\nthe variable \\verb|{prn}| or \\verb|{station}| being replaced by transmitter PRNs or receiver station names, respectively.\n(Infos regarding the variables \\verb|{prn}| and \\verb|{station}| can be found in\n\\configClass{gnssTransmitterGeneratorType}{gnssTransmitterGeneratorType} and\n\\configClass{gnssReceiverGeneratorType}{gnssReceiverGeneratorType} respectively). Those files can\nbe converted with \\program{GnssSinexBias2SignalBias}.\n\nThe estimation of the biases is complex due to different linear dependencies, which\nresult in rank deficiencies in the system of normal equations.\nFor simplification the parametrization for $\\Delta\\M x$ has been split into:\n\\configClass{parametrization:codeBiases}{gnssParametrizationType:codeBiases},\n\\configClass{parametrization:tecBiases}{gnssParametrizationType:tecBiases}, and\n\\configClass{parametrization:ambiguities}{gnssParametrizationType:ambiguities} (including phase biases).\nThe file handling on the other hand still remains within this class. Any prior\nvalues for the transmitter/receiver biases are read with the respective \\config{inputfileSignalBiasTransmitter/Receiver}.\nAll biases for a transmitter/receiver are accumulated and written to the respective \\config{outputfileSignalBiasTransmitter/Receiver}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Signal biases.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationSignalBiases : public GnssParametrizationBase\n{\n  Gnss                *gnss;\n  std::string          name;\n  PlatformSelectorPtr  selectTransmitters, selectReceivers;\n  FileName             fileNameOutTransmitter, fileNameOutReceiver;\n  FileName             fileNameInTransmitter, fileNameInReceiver;\n\npublic:\n  GnssParametrizationSignalBiases(Config &config);\n\n  void init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationStaticPositions.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationStaticPositions.cpp\n*\n* @brief Position estimation with no-net constraints.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @author HongzhanZhao\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/system.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationStaticPositions.h\"\n\n/***********************************************/\n\nGnssParametrizationStaticPositions::GnssParametrizationStaticPositions(Config &config)\n{\n  try\n  {\n    sigmaNoNetTranslation = sigmaNoNetRotation = sigmaNoNetScale = 0;\n    huber = 1e99; huberPower = 0;\n\n    readConfig(config, \"name\",                      name,                   Config::OPTIONAL, \"parameter.staticPositions\", \"used for parameter selection\");\n    readConfig(config, \"selectReceivers\",           selectReceivers,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileGriddedPosition\", fileNameGrid,           Config::OPTIONAL, \"output/gridPosition_{loopTime:%D}.dat\",              \"delta north east up for all stations\");\n    readConfig(config, \"outputfilePosition\",        fileNamePosition,       Config::OPTIONAL, \"output/stationPosition_{loopTime:%D}.{station}.dat\", \"variable {station} available, full estimated coordinates (in TRF)\");\n    readConfig(config, \"nameConstraint\",            nameConstraint,         Config::OPTIONAL, \"constraint.staticPositions\", \"used for parameter selection\");\n    readConfig(config, \"selectNoNetReceivers\",      selectNoNetReceivers,   Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"inputfileNoNetPositions\",   fileNameNoNetPositions, Config::OPTIONAL, \"{groopsDataDir}/gnss/receiverStation/position/igs/igs20/stationPosition.{station}.dat\", \"variable {station} available, precise coordinates used for no-net constraints (in TRF)\");\n    readConfig(config, \"noNetTranslationSigma\",     sigmaNoNetTranslation,  Config::OPTIONAL, \"0.01\",  \"(0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates\");\n    readConfig(config, \"noNetRotationSigma\",        sigmaNoNetRotation,     Config::OPTIONAL, \"0.001\", \"(0 = unconstrained) sigma [m] at Earth's surface for no-net rotation constraint on station coordinates\");\n    readConfig(config, \"noNetScaleSigma\",           sigmaNoNetScale,        Config::OPTIONAL, \"0\",     \"(0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates\");\n    readConfig(config, \"huber\",                     huber,                  Config::OPTIONAL, \"2.5\",   \"stations > huber*sigma0 are downweighted in no-net constraint\");\n    readConfig(config, \"huberPower\",                huberPower,             Config::OPTIONAL, \"1.5\",   \"stations > huber: sigma=(e/huber)^huberPower*sigma0\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationStaticPositions::init(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    this->gnss  = gnss;\n    index.resize(gnss->receivers.size());\n    selectedReceivers = gnss->selectReceivers(selectReceivers);\n\n    // apriori positions\n    pos0.resize(gnss->receivers.size());\n    for(auto recv : gnss->receivers)\n      if(selectedReceivers.at(recv->idRecv()) && recv->useable())\n      {\n        if(!recv->isEarthFixed())\n          throw(Exception(recv->name()+\" must be given in an Earth fixed frame\"));\n        Vector p(3);\n        if(recv->isMyRank())\n        {\n          UInt count = 0;\n          for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n            if(recv->useable(idEpoch))\n            {\n              p += recv->pos.at(idEpoch).vector();\n              count++;\n            }\n          p *= 1./count;\n        }\n        Parallel::reduceSum(p, 0, comm);\n        Parallel::broadCast(p, 0, comm);\n        pos0.at(recv->idRecv()) = Vector3d(p);\n      }\n\n    // no net-positions\n    // ----------------\n    if(sigmaNoNetRotation || sigmaNoNetTranslation || sigmaNoNetScale)\n    {\n      std::vector<const Platform*> platforms(gnss->receivers.size(), nullptr);\n      for(auto recv : gnss->receivers)\n        if(selectedReceivers.at(recv->idRecv()) && recv->useable())\n          platforms.at(recv->idRecv()) = &recv->platform;\n\n      // no net positions\n      noNetPos = pos0;\n      if(!fileNameNoNetPositions.empty())\n      {\n        noNetPos = std::vector<Vector3d>(pos0.size(), Vector3d(NAN_EXPR, NAN_EXPR, NAN_EXPR));\n        Bool someDisabled = FALSE;\n        do\n        {\n          someDisabled = FALSE;\n          selectedNoNetReceivers = selectNoNetReceivers->select(gnss->times.front(), gnss->times.back(), platforms);\n          for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n            if(selectedNoNetReceivers.at(idRecv) && std::isnan(noNetPos.at(idRecv).r()))\n            {\n              try\n              {\n                VariableList fileNameVariableList;\n                fileNameVariableList.setVariable(\"station\", gnss->receivers.at(idRecv)->name());\n                if(!System::exists(fileNameNoNetPositions(fileNameVariableList)))\n                  throw(Exception(\"file <\"+fileNameNoNetPositions(fileNameVariableList).str()+\"> not exist\"));\n                const Time timesMid = 0.5*(gnss->times.front()+gnss->times.back());\n                Vector3dArc arc = InstrumentFile::read(fileNameNoNetPositions(fileNameVariableList));\n                auto iter = std::min_element(arc.begin(), arc.end(), [&](const Epoch &e1, const Epoch &e2)\n                                            {return std::fabs((e1.time-timesMid).mjd()) < std::fabs((e2.time-timesMid).mjd());});\n                if(!arc.size() || ((arc.size() > 1) && (std::fabs((iter->time-timesMid).mjd()) > 0.5*medianSampling(arc.times()).mjd())))\n                  throw(Exception(\"No a-priori position found\"));\n                noNetPos.at(idRecv) = iter->vector3d;\n              }\n              catch(std::exception &e)\n              {\n                logWarningOnce<<gnss->receivers.at(idRecv)->name()<<\": \"<<e.what()<<\" -> not used for computation of net translation/rotation/scale\"<<Log::endl;\n                platforms.at(idRecv) = nullptr;\n                someDisabled = TRUE;\n              }\n            }\n        }\n        while(someDisabled);\n      } // if(!fileNameNoNetPositions.empty())\n\n      selectedNoNetReceivers = selectNoNetReceivers->select(gnss->times.front(), gnss->times.back(), platforms);\n      const UInt countStation = std::count(selectedNoNetReceivers.begin(), selectedNoNetReceivers.end(), TRUE);\n      logInfo<<\"  \"<<countStation<<\" stations contribute to the computation of net translation/rotation/scale\"<<Log::endl;\n      if(!countStation)\n        throw(Exception(\"no stations contribute to the computation of net translation/rotation/scale\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationStaticPositions::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    std::fill(index.begin(), index.end(), GnssParameterIndex());\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto recv : gnss->receivers)\n      if(recv->useable() && selectedReceivers.at(recv->idRecv()) && normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n      {\n        std::vector<ParameterName> parameterNames({{recv->name(), \"position.x\"}, {recv->name(), \"position.y\"}, {recv->name(), \"position.z\"}});\n        index.at(recv->idRecv()) = normalEquationInfo.parameterNamesReceiver(recv->idRecv(), parameterNames);\n        countPara += parameterNames.size();\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i receiver static position parameters\"s<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && !normalEquationInfo.isEachReceiverSeparately\n                    && (sigmaNoNetRotation || sigmaNoNetTranslation || sigmaNoNetScale) && countPara;\n\n    // synchronize positions\n    pos.resize(gnss->receivers.size());\n    for(auto recv : gnss->receivers)\n      if(index.at(recv->idRecv()))\n      {\n        Vector p(3);\n        if(recv->isMyRank())\n        {\n          UInt count = 0;\n          for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n            if(recv->useable(idEpoch))\n            {\n              p += recv->pos.at(idEpoch).vector();\n              count++;\n            }\n          p *= 1./count;\n        }\n        Parallel::reduceSum(p, 0, normalEquationInfo.comm);\n        Parallel::broadCast(p, 0, normalEquationInfo.comm);\n        pos.at(recv->idRecv()) = Vector3d(p);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationStaticPositions::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n        if(index.at(idRecv))\n          copy(pos.at(idRecv).vector(), x0.row(normalEquationInfo.index(index.at(idRecv)), 3));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationStaticPositions::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    if(index.at(eqn.receiver->idRecv()))\n      matMult(1., eqn.A.column(GnssObservationEquation::idxPosRecv, 3),\n              gnss->rotationCrf2Trf(eqn.timeRecv).matrix().trans(),\n              A.column(index.at(eqn.receiver->idRecv())));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationStaticPositions::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(!Parallel::isMaster(normalEquationInfo.comm) || !applyConstraint)\n      return;\n\n    UInt noNetCount = 0;\n    const UInt idxNNT = noNetCount; if(sigmaNoNetTranslation) noNetCount += 3;\n    const UInt idxNNR = noNetCount; if(sigmaNoNetRotation)    noNetCount += 3;\n    const UInt idxNNS = noNetCount; if(sigmaNoNetScale)       noNetCount += 1;\n\n    UInt stationCount = 0;\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedNoNetReceivers.at(idRecv) && index.at(idRecv))\n        stationCount++;\n\n    // observation equations\n    Vector l(3*stationCount);\n    Matrix A(l.rows(), noNetCount);\n    UInt i = 0;\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedNoNetReceivers.at(idRecv) && index.at(idRecv))\n      {\n        copy((noNetPos.at(idRecv)-pos.at(idRecv)).vector(), l.row(3*i, 3));\n        if(sigmaNoNetTranslation)\n          copy(identityMatrix(3), A.slice(3*i, idxNNT, 3, 3));\n        if(sigmaNoNetRotation)\n        {\n          const Vector3d pos = noNetPos.at(idRecv)/DEFAULT_R;\n          A(3*i+0, idxNNR+1) =  pos.z(); A(3*i+0, idxNNR+2) = -pos.y();\n          A(3*i+1, idxNNR+0) = -pos.z(); A(3*i+1, idxNNR+2) =  pos.x();\n          A(3*i+2, idxNNR+0) =  pos.y(); A(3*i+2, idxNNR+1) = -pos.x();\n        }\n        if(sigmaNoNetScale)\n        {\n          const Vector3d posForScale = noNetPos.at(idRecv)/DEFAULT_R;\n          A(3*i+0, idxNNS+0) = posForScale.x();\n          A(3*i+1, idxNNS+0) = posForScale.y();\n          A(3*i+2, idxNNS+0) = posForScale.z();\n        }\n        i++;\n      }\n\n    // compute station weights for no-net constraint\n    Vector x(A.columns()), sigma;\n    if(rootMeanSquare(l) > 1e-4)\n      x = Vce::robustLeastSquares(A, l, 3, huber, huberPower, 30, sigma);\n\n    // compute noNetEstimator = (A'PA)^(-1) A'P\n    for(UInt i=0; i<sigma.rows(); i++)\n      A.row(3*i, 3) *= 1./sigma(i);\n    const Vector tau = QR_decomposition(A);\n    const Matrix W = A.row(0, noNetCount);\n    generateQ(A, tau);\n    triangularSolve(1., W, A.trans());\n    for(UInt i=0; i<sigma.rows(); i++)\n      A.row(3*i, 3) *= 1./sigma(i);\n    noNetEstimator = A.trans();\n\n    if(sigmaNoNetTranslation) logStatus<<\"apply no-net translation to receiver positions, apriori (\"<<1e3*x(idxNNT+0)%\"%.1f, \"s<<1e3*x(idxNNT+1)%\"%.1f, \"s<<1e3*x(idxNNT+2)%\"%.1f) mm\"s<<Log::endl;\n    if(sigmaNoNetRotation)    logStatus<<\"apply no-net rotation to receiver positions,    apriori (\"<<1e3*x(idxNNR+0)%\"%.1f, \"s<<1e3*x(idxNNR+1)%\"%.1f, \"s<<1e3*x(idxNNR+2)%\"%.1f) mm\"s<<Log::endl;\n    if(sigmaNoNetScale)       logStatus<<\"apply no-net scale to receiver positions,       apriori (\"<<1e3*x(idxNNS+0)%\"%.1f) mm\"s<<Log::endl;\n    if(sigmaNoNetRotation || sigmaNoNetTranslation || sigmaNoNetScale)\n    {\n      logStatus<<\"  no-net coordinate residuals rms = \"<<1e3*rootMeanSquare(l-A*x)%\"%.1f mm, \"s<<Log::endl;\n      UInt i = 0;\n      if(sigma.size())\n        for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n          if(selectedNoNetReceivers.at(idRecv) && index.at(idRecv))\n          {\n            if(sigma(i) > std::pow(3./huber, huberPower))\n              logWarning<<\"  \"<<gnss->receivers.at(idRecv)->name()<<\" outlier sigma = \"<<sigma(i)%\"%.2f\"s<<Log::endl;\n            i++;\n          }\n    }\n\n    // weighted no-net constraints\n    GnssDesignMatrix Design(normalEquationInfo, x.rows());\n    if(sigmaNoNetTranslation) x.row(idxNNT, 3)         *= 1./sigmaNoNetTranslation;\n    if(sigmaNoNetRotation)    x.row(idxNNR, 3)         *= 1./sigmaNoNetRotation;\n    if(sigmaNoNetScale)       x.row(idxNNS, 1)         *= 1./sigmaNoNetScale;\n    if(sigmaNoNetTranslation) A.trans().row(idxNNT, 3) *= 1./sigmaNoNetTranslation;\n    if(sigmaNoNetRotation)    A.trans().row(idxNNR, 3) *= 1./sigmaNoNetRotation;\n    if(sigmaNoNetScale)       A.trans().row(idxNNS, 1) *= 1./sigmaNoNetScale;\n    i = 0;\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedNoNetReceivers.at(idRecv) && index.at(idRecv))\n        copy(A.row(3*i++,3).trans(), Design.column(index.at(idRecv)));\n    GnssDesignMatrix::accumulateNormals(Design, x, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationStaticPositions::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return 0;\n\n    // compute no-net translation and not-net rotation\n    std::string infoNoNet;\n    if(applyConstraint)\n    {\n      Parallel::broadCast(noNetEstimator, 0, normalEquationInfo.comm);\n      UInt noNetCount = 0;\n      const UInt idxNNT = noNetCount; if(sigmaNoNetTranslation) noNetCount += 3;\n      const UInt idxNNR = noNetCount; if(sigmaNoNetRotation)    noNetCount += 3;\n      const UInt idxNNS = noNetCount; if(sigmaNoNetScale)       noNetCount += 1;\n      Vector noNetPara(noNetCount);\n      UInt i=0;\n      for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n        if(selectedNoNetReceivers.at(idRecv) && index.at(idRecv))\n        {\n          Vector dpos = (pos.at(idRecv)-noNetPos.at(idRecv)).vector();\n          dpos += x.row(normalEquationInfo.index(index.at(idRecv)), 3);\n          matMult(1., noNetEstimator.column(3*i++, 3), dpos, noNetPara);\n        }\n      if(sigmaNoNetTranslation) infoNoNet += \", netTranslation (\"+1e3*noNetPara(idxNNT+0)%\"%.1f, \"s+1e3*noNetPara(idxNNT+1)%\"%.1f, \"s+1e3*noNetPara(idxNNT+2)%\"%.1f) mm\"s;\n      if(sigmaNoNetRotation)    infoNoNet += \", netRotation (\"   +1e3*noNetPara(idxNNR+0)%\"%.1f, \"s+1e3*noNetPara(idxNNR+1)%\"%.1f, \"s+1e3*noNetPara(idxNNR+2)%\"%.1f) mm\"s;\n      if(sigmaNoNetScale)       infoNoNet += \", netScale (\"      +1e3*noNetPara(idxNNS+0)%\"%.1f) mm\"s;\n    }\n\n    // update positions\n    Double maxChange = 0;\n    Gnss::InfoParameterChange info(\"mm\");\n    for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n      if(index.at(idRecv))\n      {\n        const Vector3d dpos(x.row(normalEquationInfo.index(index.at(idRecv)), 3));\n        pos.at(idRecv) += dpos;\n        if(gnss->receivers.at(idRecv)->isMyRank())\n          for(UInt idEpoch=0; idEpoch<gnss->receivers.at(idRecv)->times.size(); idEpoch++)\n            gnss->receivers.at(idRecv)->pos.at(idEpoch) += dpos;\n        if(info.update(1e3*dpos.r()))\n          info.info = \"position receiver (\"+gnss->receivers.at(idRecv)->name()+\")\"+infoNoNet;\n      }\n    info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationStaticPositions::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameGrid.empty())\n    {\n      // collect positions\n      Matrix data(gnss->receivers.size(), 6); // x, y, z , dx, dy, dz\n      for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n        if(index.at(idRecv) && gnss->receivers.at(idRecv)->isMyRank())\n        {\n          // find first valid Epoch\n          Transform3d trf2local;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(gnss->receivers.at(idRecv)->useable(idEpoch))\n            {\n              trf2local = gnss->receivers.at(idRecv)->global2localFrame(idEpoch);\n              break;\n            }\n          copy(pos.at(idRecv).vector().trans(), data.slice(idRecv, 0, 1, 3));\n          copy(trf2local.transform(pos.at(idRecv)-pos0.at(idRecv)).vector().trans(), data.slice(idRecv, 3, 1, 3)); // dpos in NEU (north, east, up) system\n        }\n      Parallel::reduceSum(data, 0, normalEquationInfo.comm);\n\n      if(Parallel::isMaster(normalEquationInfo.comm))\n      {\n        logStatus<<\"write receiver grid file <\"<<fileNameGrid.appendBaseName(suffix)<<\">\"<<Log::endl;\n        std::vector<Vector3d>            point;\n        std::vector<std::vector<Double>> value(3);\n        for(UInt idRecv=0; idRecv<data.rows(); idRecv++)\n          if(index.at(idRecv))\n          {\n            point.push_back(Vector3d(data.slice(idRecv, 0, 1, 3)));\n            value.at(0).push_back(data(idRecv, 3)); // north\n            value.at(1).push_back(data(idRecv, 4)); // east\n            value.at(2).push_back(data(idRecv, 5)); // up\n          }\n        writeFileGriddedData(fileNameGrid.appendBaseName(suffix), GriddedData(Ellipsoid(), point, std::vector<Double>(point.size(), 1.), value));\n      }\n    }\n\n    if(!fileNamePosition.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write positions to files <\"<<fileNamePosition(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(UInt idRecv=0; idRecv<index.size(); idRecv++)\n        if(index.at(idRecv) && gnss->receivers.at(idRecv)->isMyRank())\n        {\n          Vector3dEpoch epoch;\n          epoch.time     = gnss->times.at(static_cast<UInt>(std::floor(0.5*gnss->times.size())));\n          epoch.vector3d = pos.at(idRecv);\n          Vector3dArc arc;\n          arc.push_back(epoch);\n          fileNameVariableList.setVariable(\"station\", gnss->receivers.at(idRecv)->name());\n          InstrumentFile::write(fileNamePosition(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationStaticPositions.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationStaticPositions.h\n*\n* @brief Position estimation with no-net constraints.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @author HongzhanZhao\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONSTATICPOSITIONS__\n#define __GROOPS_GNSSPARAMETRIZATIONSTATICPOSITIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationStaticPositions = R\"(\n\\subsection{StaticPositions}\\label{gnssParametrizationType:staticPositions}\nEstimates a static position for all\n\\configClass{selectReceivers}{platformSelectorType} in the terrestrial frame.\n\nNo-net constraints can be applied for a subset of stations,\n\\configClass{selectNoNetReceivers}{platformSelectorType}, with a\nstandard deviation of \\config{noNetTranslationSigma} and \\config{noNetRotationSigma} and \\config{noNetScaleSigma}.\nIf the template \\configFile{inputfileNoNetPositions}{stringList} is provided\nthe constraints are applied relatively to these positions. Only stations with an existing position file\nare considered. Without \\configFile{inputfileNoNetPositions}{stringList}\nthe constraints are applied towards the apriori values from\n\\configClass{GnssProcessing:receiver}{gnssReceiverGeneratorType}.\nAs a single corrupted station position can disturb the no-net conditions,\nthe rotation/translation parameters are estimated in a\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}\nbeforehand. The computed weight matrix is used to downweight corrupted stations\nin the constraint equations.\n\nIn case you want to align to an ITRF/IGS reference frame, precise coordinates can be\ngenerated with \\program{Sinex2StationPositions}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:position.x::|,\n\\item \\verb|<station>:position.y::|,\n\\item \\verb|<station>:position.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Position estimation with no-net constraints.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationStaticPositions : public GnssParametrizationBase\n{\n  Gnss                           *gnss;\n  std::string                     name, nameConstraint;\n  PlatformSelectorPtr             selectReceivers, selectNoNetReceivers;\n  std::vector<Byte>               selectedReceivers, selectedNoNetReceivers;\n  FileName                        fileNameGrid, fileNamePosition, fileNameNoNetPositions;\n  Bool                            applyConstraint;\n  Double                          sigmaNoNetTranslation, sigmaNoNetRotation, sigmaNoNetScale;\n  Double                          huber, huberPower;\n  std::vector<GnssParameterIndex> index; // for each receiver\n  std::vector<Vector3d>           pos, pos0, noNetPos;\n  mutable Matrix                  noNetEstimator;\n\npublic:\n  GnssParametrizationStaticPositions(Config &config);\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTecBiases.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTecBiases.cpp\n*\n* @brief Code biases.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTecBiases.h\"\n\n/***********************************************/\n\nGnssParametrizationTecBiases::GnssParametrizationTecBiases(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                    name,               Config::OPTIONAL, \"parameter.tecBiases\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",      selectTransmitters, Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectReceivers\",         selectReceivers,    Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"linearGlonassBias\",       isLinearBias,       Config::DEFAULT,  \"0\", \"phase or code biases depend linear on frequency channel number\");\n    readConfig(config, \"nameConstraint\",          nameConstraint,     Config::OPTIONAL, \"constraint.tecBiases\", \"used for parameter selection\");\n    readConfig(config, \"sigmaZeroMeanConstraint\", sigmaZeroMean,      Config::DEFAULT,  \"0.0001\", \"(0 = unconstrained) sigma [m] for null space constraint\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationTecBiases::~GnssParametrizationTecBiases()\n{\n  for(auto para : paraTrans)\n    delete para;\n  for(auto para : paraRecv)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTecBiases::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n\n    auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n    paraTrans.resize(gnss->transmitters.size(), nullptr);\n    for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n      if(selectedTransmitters.at(idTrans) && gnss->transmitters.at(idTrans)->useable())\n      {\n        auto para = new Parameter();\n        paraTrans.at(idTrans) = para;\n        para->trans = gnss->transmitters.at(idTrans);\n      }\n\n    auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n    paraRecv.resize(gnss->receivers.size(), nullptr);\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedReceivers.at(idRecv) && gnss->receivers.at(idRecv)->useable())\n      {\n        auto para = new Parameter();\n        paraRecv.at(idRecv) = para;\n        para->recv = gnss->receivers.at(idRecv);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTecBiases::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : paraTrans)\n      if(para)\n        para->index = GnssParameterIndex();\n    for(auto para : paraRecv)\n      if(para)\n        para->index = GnssParameterIndex();\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    // transmitter parameters\n    // ----------------------\n    UInt countParaTrans = 0;\n    if(!normalEquationInfo.isEachReceiverSeparately)\n      for(auto para : paraTrans)\n        if(para && para->trans->useable())\n        {\n          // determine nullspace\n          Matrix N(para->trans->signalBias.types.size(), Matrix::SYMMETRIC);\n          for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n          {\n            std::vector<GnssType> types;\n            for(GnssType type : gnss->typesRecvTrans.at(idRecv).at(para->trans->idTrans()))\n              if(((type == GnssType::PHASE) || (type == GnssType::RANGE)) && !type.isInList(types))\n                types.push_back(type);\n            if(!types.size())\n              continue;\n\n            // Composed signals (e.g. C2DG)\n            std::vector<GnssType> typesTrans;\n            Matrix T;\n            gnss->receivers.at(idRecv)->signalComposition(NULLINDEX, types, typesTrans, T);\n\n            Matrix A(types.size(), para->trans->signalBias.types.size());\n            UInt idx;\n            for(UInt i=0; i<typesTrans.size(); i++)\n              if(typesTrans.at(i).isInList(para->trans->signalBias.types, idx))\n                axpy(1., T.column(i), A.column(idx));\n            Vector STEC(types.size());\n            for(UInt i=0; i<types.size(); i++)\n              STEC(i) = types.at(i).ionosphericFactor();\n            eliminationParameter(STEC, {A});\n            rankKUpdate(1., A, N);\n          }\n\n          // determine eigen values\n          Vector eigen = eigenValueDecomposition(N, TRUE);\n          eigen *= (eigen(eigen.rows()-1) > 1e-4) ? 1./eigen(eigen.rows()-1) : 0.;\n          UInt countZeros = 0;\n          while((countZeros < eigen.rows()) && (eigen(countZeros) < 1e-8))\n            countZeros++;\n          para->Bias = N.column(0, countZeros);\n          Parallel::broadCast(para->Bias, 0, normalEquationInfo.comm); // to ensure that all nodes use the same matrix\n          if(!para->Bias.size())\n            continue;\n\n          // determine parameter names\n          std::vector<ParameterName> parameterNames;\n          for(UInt i=0; i<para->Bias.columns(); i++)\n          {\n            std::string typeStr;\n            for(UInt idType=0; idType<para->Bias.rows(); idType++)\n              if(std::fabs(para->Bias(idType, i)) > 1e-4)\n                typeStr += ((para->Bias(idType, i) > 0) ? \"+\" : \"\") + para->Bias(idType, i)%\"%.2f\"s + para->trans->signalBias.types.at(idType).str();\n            parameterNames.push_back(ParameterName(para->trans->name(), \"tecBias\"+(i+1)%\"%02i(\"s+typeStr+\")\"));\n          }\n          para->index = normalEquationInfo.parameterNamesTransmitter(para->trans->idTrans(), parameterNames);\n          countParaTrans += parameterNames.size();\n        }\n    if(countParaTrans)\n      logInfo<<countParaTrans%\"%9i transmitter TEC bias parameters\"s<<Log::endl;\n\n    // receiver parameters\n    // -------------------\n    UInt countParaRecv = 0;\n    for(auto para : paraRecv)\n      if(para && para->recv->useable() && normalEquationInfo.estimateReceiver.at(para->recv->idRecv()))\n      {\n        std::vector<GnssType> biasTypes;\n        std::vector<GnssType> trendTypes;\n        for(GnssType type : para->recv->signalBias.types)\n          if((type == GnssType::RANGE) || (type == GnssType::PHASE))\n          {\n            if(!type.isInList(biasTypes))\n              biasTypes.push_back(type & (isLinearBias ? ~GnssType::FREQ_NO : GnssType::ALL));\n            else if(!type.isInList(trendTypes))\n              trendTypes.push_back(type & ~GnssType::FREQ_NO);\n          }\n\n        // transformation matrix\n        Matrix T(para->recv->signalBias.types.size(), biasTypes.size()+trendTypes.size());\n        UInt idx;\n        for(UInt i=0; i<para->recv->signalBias.types.size(); i++)\n          if(para->recv->signalBias.types.at(i).isInList(biasTypes, idx))\n            T(i, idx) = 1.;\n        for(UInt i=0; i<para->recv->signalBias.types.size(); i++)\n          if(para->recv->signalBias.types.at(i).isInList(trendTypes, idx))\n            T(i, biasTypes.size()+idx) = para->recv->signalBias.types.at(i).frequencyNumber();\n\n        // determine nullspace\n        Matrix N(T.columns(), Matrix::SYMMETRIC);\n        for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n        {\n          std::vector<GnssType> types;\n          for(GnssType type : gnss->typesRecvTrans.at(para->recv->idRecv()).at(idTrans))\n            if(((type == GnssType::PHASE) || (type == GnssType::RANGE)) && !type.isInList(types))\n              types.push_back(type);\n          if(!types.size())\n            continue;\n\n          Matrix A(types.size(), T.columns());\n          for(UInt i=0; i<types.size(); i++)\n            copy(T.row(GnssType::index(para->recv->signalBias.types, types.at(i))), A.row(i));\n          Vector STEC(types.size());\n          for(UInt i=0; i<types.size(); i++)\n            STEC(i) = types.at(i).ionosphericFactor();\n          eliminationParameter(STEC, {A});\n          rankKUpdate(1., A, N);\n        }\n\n        // determine eigen values\n        Vector eigen = eigenValueDecomposition(N, TRUE);\n        eigen *= (eigen(eigen.rows()-1) > 1e-4) ? 1./eigen(eigen.rows()-1) : 0.;\n        UInt countZeros = 0;\n        while((countZeros < eigen.rows()) && (eigen(countZeros) < 1e-8))\n          countZeros++;\n        para->Bias = T * N.column(0, countZeros);\n        Parallel::broadCast(para->Bias, 0, normalEquationInfo.comm); // to ensure that all nodes use the same matrix\n        if(!para->Bias.size())\n          continue;\n\n        // determine parameter names\n        std::vector<ParameterName> parameterNames;\n        for(UInt i=0; i<para->Bias.columns(); i++)\n        {\n          std::string typeStr;\n          for(UInt idType=0; idType<para->Bias.rows(); idType++)\n            if(std::fabs(para->Bias(idType, i)) > 1e-4)\n              typeStr += ((para->Bias(idType, i) > 0) ? \"+\" : \"\") + para->Bias(idType, i)%\"%.2f\"s + para->recv->signalBias.types.at(idType).str();\n          parameterNames.push_back(ParameterName(para->recv->name(), \"tecBias\"+(i+1)%\"%02i(\"s+typeStr+\")\"));\n        }\n        para->index = normalEquationInfo.parameterNamesReceiver(para->recv->idRecv(), parameterNames);\n        countParaRecv += parameterNames.size();\n      }\n    if(countParaRecv)\n      logInfo<<countParaRecv%\"%9i receiver TEC bias parameters\"s<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && sigmaZeroMean\n                    && (countParaTrans+countParaRecv) &&  !normalEquationInfo.isEachReceiverSeparately;\n\n    // calculate constraint equations (zero mean of signal biases)\n    // -----------------------------------------------------------\n    if(applyConstraint)\n    {\n      UInt parameterCount = 0;\n      // indices of transmitter biases\n      idxBiasTrans.clear();\n      idxBiasTrans.resize(gnss->transmitters.size(), NULLINDEX);\n      for(auto para : paraTrans)\n        if(para && para->index)\n        {\n          idxBiasTrans.at(para->trans->idTrans()) = parameterCount;\n          parameterCount += para->Bias.columns();\n        }\n      // indices of receiver biases\n      idxBiasRecv.clear();\n      idxBiasRecv.resize(gnss->receivers.size(), NULLINDEX);\n      std::vector<std::vector<std::vector<GnssType>>> typesRecvTrans(gnss->receivers.size()); // for each receiver and transmitter: used types (receiver types)\n      for(auto para : paraRecv)\n        if(para && para->index)\n        {\n          const UInt idRecvOld = std::distance(typesRecvTrans.begin(), std::find(typesRecvTrans.begin(), typesRecvTrans.end(), gnss->typesRecvTrans.at(para->recv->idRecv())));\n          if(idRecvOld >= typesRecvTrans.size())\n          {\n            typesRecvTrans.at(para->recv->idRecv()) = gnss->typesRecvTrans.at(para->recv->idRecv());\n            idxBiasRecv.at(para->recv->idRecv()) = parameterCount;\n            parameterCount += para->Bias.columns();\n          }\n          else\n            idxBiasRecv.at(para->recv->idRecv()) = idxBiasRecv.at(idRecvOld);\n        }\n\n      if(parameterCount)\n      {\n        // normals of pseudo observations\n        Matrix N(parameterCount, Matrix::SYMMETRIC);\n        for(auto recv : gnss->receivers)\n          if(recv->isMyRank() && normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n            for(auto trans : gnss->transmitters)\n            {\n              // observation types\n              std::vector<GnssType> types;\n              for(GnssType type : gnss->typesRecvTrans.at(recv->idRecv()).at(trans->idTrans()))\n                if((type == GnssType::RANGE) && !type.isInList(types))\n                  types.push_back(type);\n              if(!types.size())\n                continue;\n\n              // transmitted types\n              std::vector<GnssType> typesTrans;\n              Matrix T;\n              recv->signalComposition(NULLINDEX/*idEpoch*/, types, typesTrans, T);\n\n              // design matrix\n              Matrix A(types.size(), parameterCount);\n              if(idxBiasRecv.at(recv->idRecv()) != NULLINDEX)     // bias recv\n                for(UInt i=0; i<types.size(); i++)\n                  copy(paraRecv.at(recv->idRecv())->Bias.row(GnssType::index(recv->signalBias.types, types.at(i))),\n                      A.slice(i, idxBiasRecv.at(recv->idRecv()), 1, paraRecv.at(recv->idRecv())->Bias.columns()));\n              if(idxBiasTrans.at(trans->idTrans()) != NULLINDEX)  // bias recv\n                for(UInt k=0; k<typesTrans.size(); k++)\n                  matMult(1., T.column(k), paraTrans.at(trans->idTrans())->Bias.row(GnssType::index(trans->signalBias.types, typesTrans.at(k))),\n                          A.column(idxBiasTrans.at(trans->idTrans()), paraTrans.at(trans->idTrans())->Bias.columns()));\n              rankKUpdate(1., A, N);\n            }\n        Parallel::reduceSum(N, 0, normalEquationInfo.comm);\n\n        if(Parallel::isMaster(normalEquationInfo.comm))\n        {\n          // determine eigen values\n          Vector eigen = eigenValueDecomposition(N, TRUE);\n          eigen *= (eigen(eigen.rows()-1) > 1e-4) ? 1./eigen(eigen.rows()-1) : 0.;\n          UInt countZeros = 0;\n          while((countZeros < eigen.rows()) && (eigen(countZeros) < 1e-8))\n            countZeros++;\n          zeroMeanDesign = N.column(0, countZeros).trans(); // null space defines the constraint equations\n        }\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTecBiases::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(auto para : paraTrans)\n        if(para && para->index)\n          copy(leastSquares(Matrix(para->Bias), Vector(para->trans->signalBias.biases)), x0.row(normalEquationInfo.index(para->index), para->Bias.columns()));\n\n    for(auto para : paraRecv)\n      if(para && para->index && para->recv->isMyRank())\n        copy(leastSquares(Matrix(para->Bias), Vector(para->recv->signalBias.biases)), x0.row(normalEquationInfo.index(para->index), para->Bias.columns()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTecBiases::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    auto paraTrans = this->paraTrans.at(eqn.transmitter->idTrans());\n    if(paraTrans && paraTrans->index)\n    {\n      MatrixSlice Design(A.column(paraTrans->index));\n      UInt idx;\n      for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n        if(eqn.typesTransmitted.at(idType).isInList(eqn.transmitter->signalBias.types, idx))\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + eqn.types.size() + idType), paraTrans->Bias.row(idx), Design);\n    }\n\n    auto paraRecv = this->paraRecv.at(eqn.receiver->idRecv());\n    if(paraRecv && paraRecv->index)\n    {\n      MatrixSlice Design(A.column(paraRecv->index));\n      UInt idx;\n      for(UInt idType=0; idType<eqn.types.size(); idType++)\n        if(eqn.types.at(idType).isInList(eqn.receiver->signalBias.types, idx))\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + idType), paraRecv->Bias.row(idx), Design);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTecBiases::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm) && applyConstraint)\n    {\n      logStatus<<\"apply \"<<zeroMeanDesign.rows()<<\" zero mean equations for tec bias parameters\"<<Log::endl;\n      if(zeroMeanDesign.rows())\n      {\n        GnssDesignMatrix A(normalEquationInfo, zeroMeanDesign.rows());\n        for(auto para : paraTrans)\n          if(para && para->index && (idxBiasTrans.at(para->trans->idTrans()) != NULLINDEX))\n            axpy(1./sigmaZeroMean, zeroMeanDesign.column(idxBiasTrans.at(para->trans->idTrans()), para->Bias.columns()), A.column(para->index));\n        for(auto para : paraRecv)\n          if(para && para->index && (idxBiasRecv.at(para->recv->idRecv()) != NULLINDEX))\n            axpy(1./sigmaZeroMean, zeroMeanDesign.column(idxBiasRecv.at(para->recv->idRecv()), para->Bias.columns()), A.column(para->index));\n        GnssDesignMatrix::accumulateNormals(A, Vector(zeroMeanDesign.rows()), normals, n, lPl, obsCount);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationTecBiases::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange infoTrans(\"mm\");\n    for(auto para : paraTrans)\n      if(para && para->index)\n      {\n        const Vector dBias = para->Bias * x.row(normalEquationInfo.index(para->index), para->Bias.columns());\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          para->trans->signalBias.biases.at(idType) += dBias(idType);\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          if(infoTrans.update(1e3*dBias(idType)))\n            infoTrans.info = \"tec bias transmitter (\"+para->trans->signalBias.types.at(idType).str()+\")\";\n      }\n    infoTrans.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    Gnss::InfoParameterChange infoRecv(\"mm\");\n    for(auto para : paraRecv)\n      if(para && para->index)\n      {\n        const Vector dBias = para->Bias * x.row(normalEquationInfo.index(para->index), para->Bias.columns());\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          para->recv->signalBias.biases.at(idType) += dBias(idType);\n        for(UInt idType=0; idType<dBias.size(); idType++)\n          if(infoRecv.update(1e3*dBias(idType)))\n            infoRecv.info = \"tec bias receiver (\"+para->recv->name()+\", \"+para->recv->signalBias.types.at(idType).str()+\")\";\n      }\n    infoRecv.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTecBiases.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTecBiases.h\n*\n* @brief TEC biases.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONTECBIASES__\n#define __GROOPS_GNSSPARAMETRIZATIONTECBIASES__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationTecBiases = R\"(\n\\subsection{TecBiases}\\label{gnssParametrizationType:tecBiases}\nEach code observation (e.g \\verb|C1C| or \\verb|C2W|) contains a bias at transmitter/receiver level\n\\begin{equation}\n  [C\\nu a]_r^s(t) = \\dots + \\text{bias}[C\\nu a]^s + \\text{bias}[C\\nu a]_r + \\ldots\n\\end{equation}\nThis parametrization represents the linear combination of signal biases\nwhich completely depend on the STEC parameters. Ignoring these bias combinations would result\nin a biased STEC estimation (all other parameters are nearly unaffected).\nTo determine this part of the signal biases\nthe \\configClass{parametrization:ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC} should be constrained.\nFurthermore, additional information about the ionosphere is required from\n\\configClass{parametrization:ionosphereVTEC}{gnssParametrizationType:ionosphereVTEC} or\n\\configClass{parametrization:ionosphereMap}{gnssParametrizationType:ionosphereMap}.\n\nRank deficiencies due to the signal bias parameters may occur if biases of\ntransmitters and receivers are estimated together.\nThe minimum norm nullspace is formulated as zero constraint equations and added with\na standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe accumulated estimated result can be written to files in\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station or prn>:tecBias0<index><combi of gnssTypes>::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief TEC biases.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationTecBiases : public GnssParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    GnssTransmitterPtr trans;\n    GnssReceiverPtr    recv;\n    GnssParameterIndex index;\n    Matrix             Bias;\n  };\n\n  Gnss                    *gnss;\n  std::string              name, nameConstraint;\n  PlatformSelectorPtr      selectTransmitters, selectReceivers;\n  FileName                 fileNameTransmitter, fileNameReceiver;\n  Bool                     isLinearBias;\n  Bool                     applyConstraint;\n  Double                   sigmaZeroMean;\n  std::vector<Parameter*>  paraTrans, paraRecv;\n  std::vector<UInt>        idxBiasTrans, idxBiasRecv; // indices in zeroMean matrix\n  Matrix                   zeroMeanDesign;            // zero mean observation equations\n\npublic:\n  GnssParametrizationTecBiases(Config &config);\n ~GnssParametrizationTecBiases();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTemporalBias.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTemporalBias.cpp\n*\n* @brief Temporal changing signal bias.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTemporalBias.h\"\n\n/***********************************************/\n\nGnssParametrizationTemporalBias::GnssParametrizationTemporalBias(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                     name,               Config::OPTIONAL, \"parameter.temporalBias\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",       selectTransmitters, Config::MUSTSET,  \"\",       \"\");\n    readConfig(config, \"outputfileBiasTimeSeries\", fileNameOut,        Config::OPTIONAL, \"\",       \"variable {prn} available\");\n    readConfig(config, \"inputfileBiasTimeSeries\",  fileNameIn,         Config::OPTIONAL, \"\",       \"variable {prn} available\");\n    readConfig(config, \"type\",                     type,               Config::MUSTSET,  \"L5*G\",   \"\");\n    readConfig(config, \"parametrizationTemporal\",  temporal,           Config::DEFAULT,  \"\",       \"\");\n    readConfig(config, \"nameConstraint\",           nameConstraint,     Config::OPTIONAL, \"constraint.temporalBias\", \"used for parameter selection\");\n    readConfig(config, \"sigmaZeroMeanConstraint\",  sigmaZeroMean,      Config::DEFAULT,  \"0.0001\", \"(0 = unconstrained) sigma [m] for temporal zero-mean constraint\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationTemporalBias::~GnssParametrizationTemporalBias()\n{\n  for(Parameter *para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(\"prn\", \"***\");\n    Bool foundAnyFile = FALSE;\n    parameters.resize(gnss->transmitters.size(), nullptr);\n    for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n      if(selectedTransmitters.at(idTrans) && gnss->transmitters.at(idTrans)->useable())\n      {\n        auto para = new Parameter();\n        parameters.at(idTrans) = para;\n        para->trans = gnss->transmitters.at(idTrans);\n\n        para->bias = Vector(gnss->times.size());\n        if(!fileNameIn.empty())\n        {\n          fileNameVariableList.setVariable(\"prn\", para->trans->name());\n          MiscValueArc arc;\n          try\n          {\n            arc = InstrumentFile::read(fileNameIn(fileNameVariableList));\n            foundAnyFile = TRUE;\n          }\n          catch(std::exception &/*e*/)\n          {\n          }\n\n          if(arc.size())\n          {\n            Polynomial polynomial(arc.times(), 1, FALSE/*throwException*/); // linear interpolation\n            para->bias = polynomial.interpolate(gnss->times, arc.matrix().column(1));\n            for(UInt idEpoch=0; idEpoch<para->bias.size(); idEpoch++)\n              if(std::isnan(para->bias.at(idEpoch)))\n                gnss->transmitters.at(idTrans)->disable(idEpoch, \"no a priori temporalBias for \"+type.str());\n          }\n        }\n\n        if(temporal->parameterCount())\n        {\n          Vector l(gnss->times.size()+temporal->parameterCount());\n          Matrix A(gnss->times.size()+temporal->parameterCount(), temporal->parameterCount());\n          axpy(1e-6, identityMatrix(temporal->parameterCount()), A.row(gnss->times.size(), temporal->parameterCount())); // loose regularization\n          for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n            if(gnss->transmitters.at(idTrans)->useable(idEpoch))\n            {\n              copy(temporal->factors(gnss->times.at(idEpoch)).trans(), A.row(idEpoch));\n              l(idEpoch) = para->bias(idEpoch);\n            }\n          para->x = leastSquares(A, l);\n        }\n      }\n\n    if(!fileNameIn.empty() && !foundAnyFile)\n      logWarningOnce<<\"time-variable signal bias files for \"<<type.str()<<\" not found for any transmitter.\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::observationCorrections(GnssObservationEquation &eqn) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.transmitter->idTrans());\n    if(para)\n      for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n        if(eqn.typesTransmitted.at(idType) == type)\n          axpy(-para->bias(eqn.idEpoch), eqn.A.column(GnssObservationEquation::idxUnit + eqn.types.size() + idType), eqn.l);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para)\n        para->index = GnssParameterIndex();\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name) || normalEquationInfo.isEachReceiverSeparately)\n      return;\n\n    UInt countPara = 0;\n    std::vector<GnssType> types = GnssType::replaceCompositeSignals(gnss->types());\n    std::vector<ParameterName> parameterNames;\n    temporal->parameterName({ParameterName(\"\", \"signalBias.\"+type.str())}, parameterNames);\n    for(auto para : parameters)\n      if(para && para->trans->useable() && (para->trans->PRN() == type) && (GnssType::index(types, para->trans->PRN()+type) != NULLINDEX))\n      {\n        for(auto &name : parameterNames)\n          name.object = para->trans->name();\n        para->index = normalEquationInfo.parameterNamesTransmitter(para->trans->idTrans(), parameterNames);\n        countPara += parameterNames.size();\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i temporal bias (\"s<<type.str()<<\") parameters\"<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint)  && sigmaZeroMean && countPara;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(auto para : parameters)\n        if(para && para->index)\n          copy(para->x, x0.row(normalEquationInfo.index(para->index), para->x.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.transmitter->idTrans());\n    if(para && para->index)\n    {\n      MatrixSlice Design(A.column(para->index));\n      for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n        if(eqn.typesTransmitted.at(idType) == type)\n          matMult(1., eqn.A.column(GnssObservationEquation::idxUnit + eqn.types.size() + idType),\n                  temporal->factors(std::max(eqn.timeTrans, gnss->times.at(0))).trans(), Design);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(!Parallel::isMaster(normalEquationInfo.comm) || !applyConstraint)\n      return;\n\n    logStatus<<\"apply temporal zero mean of temporal signal bias of \"<<type.str()<<Log::endl;\n    Vector mean(temporal->parameterCount());\n    for(const Time &time : gnss->times)\n      mean += temporal->factors(time);\n\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        Vector l = -1./sigmaZeroMean/gnss->times.size() * mean.trans() * para->x;\n        GnssDesignMatrix A(normalEquationInfo, l.rows()); // constrain towards zero (0-x0)\n        axpy(1./sigmaZeroMean/gnss->times.size(), mean.trans(), A.column(para->index));\n        GnssDesignMatrix::accumulateNormals(A, l, normals, n, lPl, obsCount);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationTemporalBias::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange info(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        const Vector dx = x.row(normalEquationInfo.index(para->index), para->x.rows());\n        para->x += dx;\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n        {\n          const Double dBias = inner(temporal->factors(gnss->times.at(idEpoch)), dx);\n          para->bias(idEpoch) += dBias;\n          if(info.update(1e3*dBias))\n            info.info = \"temporal signal bias (\"+type.str()+\")\";\n        }\n      }\n    info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTemporalBias::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name) || !Parallel::isMaster(normalEquationInfo.comm))\n      return;\n\n    if(!fileNameOut.empty() && std::any_of(parameters.begin(), parameters.end(), [](const Parameter *p){return p && p->index;}))\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logStatus<<\"write transmitter time variable bias to files <\"<<fileNameOut(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n          MiscValueArc arc;\n          for(UInt idEpoch : normalEquationInfo.idEpochs)\n            if(para->trans->useable(idEpoch))\n            {\n              MiscValueEpoch epoch;\n              epoch.time  = gnss->times.at(idEpoch);\n              epoch.value = para->bias(idEpoch);\n              arc.push_back(epoch);\n            }\n          fileNameVariableList.setVariable(\"prn\", para->trans->name());\n          InstrumentFile::write(fileNameOut(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTemporalBias.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTemporalBias.h\n*\n* @brief Temporal changing signal bias.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONTEMPORALBIAS__\n#define __GROOPS_GNSSPARAMETRIZATIONTEMPORALBIAS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationTemporalBias = R\"(\n\\subsection{TemporalBias}\\label{gnssParametrizationType:temporalBias}\nThis parametrization resolves the issue of some phase observations suffering from time-variable biases.\nSuch a phenomenon has been found to affect GPS block IIF satellites on the L5 phase measurements\n(see Montenbruck et al. 2011, DOI: \\href{https://doi.org/10.1007/s10291-011-0232-x}{10.1007/s10291-011-0232-x}).\n\nFor these time-variable biases an appropriate temporal representation has to be defined in\n\\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nFor example, time-variable biases for GPS block IIF L5 phase observations (\\configClass{type}{gnssType}=\\verb|L5*G|)\ncan be represented by a cubic spline with a nodal distance of one hour.\n\nThe result is written as a \\file{times series file}{instrument} at the processing sampling\nor the sampling set by \\configClass{GnssProcessing:processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}).\n\nThis parametrization should be set up in addition to the constant\n\\configClass{parametrization:signalBiases}{gnssParametrizationType:signalBiases}.\nDepending on the temporal representation a temporal zero-mean constraint is needed\nto separate this parametrization from the constant component. The constraint equations are added with\na standard deviation of \\config{sigmaZeroMeanConstraint}.\n\nThe \\file{parameter names}{parameterName} are\n\\verb|<prn>:signalBias.<gnssType>:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Temporal changing signal bias.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationTemporalBias : public GnssParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    GnssTransmitterPtr trans;\n    GnssParameterIndex index;\n    Vector             x;\n    Vector             bias;\n  };\n\n  Gnss                      *gnss;\n  std::string                name, nameConstraint;\n  PlatformSelectorPtr        selectTransmitters;\n  FileName                   fileNameOut, fileNameIn;\n  GnssType                   type;\n  ParametrizationTemporalPtr temporal;\n  Bool                       applyConstraint;\n  Double                     sigmaZeroMean;\n  std::vector<Parameter*>    parameters;\n\npublic:\n  GnssParametrizationTemporalBias(Config &config);\n ~GnssParametrizationTemporalBias();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   observationCorrections(GnssObservationEquation &eqn) const override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  void   constraints(const GnssNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTransmitterAntennas.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTransmitterAntennas.cpp\n*\n* @brief Antenna center variations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTransmitterAntennas.h\"\n\n/***********************************************/\n\nGnssParametrizationTransmitterAntennas::GnssParametrizationTransmitterAntennas(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                    name,                Config::OPTIONAL, \"parameter.transmitterAntenna\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",      selectTransmitters,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"antennaCenterVariations\", parametrization,     Config::MUSTSET,  \"\",  \"estimate antenna center variations\");\n    readConfig(config, \"patternTypes\",            typesPattern,        Config::OPTIONAL, \"\",  \"gnssType for each pattern (first match is used)\");\n    readConfig(config, \"addNonMatchingTypes\",     addNonMatchingTypes, Config::DEFAULT,  \"1\", \"add patterns for additional observed gnssTypes that don't match any of the above\");\n    readConfig(config, \"groupAntennas\",           ignoreSerial,        Config::DEFAULT,  \"0\", \"common ACVs for same antenna build types (ignores antenna serial number)\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterAntennas::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    transmitter2antenna.resize(gnss->transmitters.size(), NULLINDEX);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n\nvoid GnssParametrizationTransmitterAntennas::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    index.clear();\n    types.clear();\n    std::fill(transmitter2antenna.begin(), transmitter2antenna.end(), NULLINDEX);\n    if(!isEnabled(normalEquationInfo, name) || normalEquationInfo.isEachReceiverSeparately)\n      return;\n\n    std::vector<std::string> antennaNames;\n    auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n    for(auto trans : gnss->transmitters)\n      if(trans->useable() && selectedTransmitters.at(trans->idTrans()))\n      {\n        Bool found = FALSE;\n        for(const auto &instrument : trans->platform.equipments)\n        {\n          auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n          if(antenna && (antenna->timeEnd > gnss->times.front()) && (antenna->timeStart <= gnss->times.back()))\n          {\n            if(found)\n            {\n              logWarning<<trans->name()<<\" has multiple antennas in interval -> only first one is used for parametrization/estimation\"<<Log::endl;\n              continue;\n            }\n            found = TRUE;\n\n            // not already in list?\n            const std::string name = GnssAntennaDefinition::str(antenna->name, ignoreSerial ? \"\"s : antenna->serial, antenna->radome);\n            const UInt idAnt = std::distance(antennaNames.begin(), std::find(antennaNames.begin(), antennaNames.end(), name));\n            if(idAnt >= antennaNames.size())\n            {\n              antennaNames.push_back(name);\n              types.resize(antennaNames.size());\n            }\n            transmitter2antenna.at(trans->idTrans()) = idAnt;\n\n            // add observed types\n            for(const auto &typesRecv : gnss->typesRecvTrans)\n              for(GnssType typeObs : GnssType::replaceCompositeSignals(typesRecv.at(trans->idTrans())))\n                if(!typeObs.isInList(types.at(idAnt)))\n                {\n                  UInt idx;\n                  if(typeObs.isInList(typesPattern, idx))\n                    types.at(idAnt).push_back(typesPattern.at(idx));\n                  else if(addNonMatchingTypes)\n                    types.at(idAnt).push_back(typeObs);\n                }\n          } // for(antenna)\n        }\n      } // for(trans)\n\n    // setup parameters\n    // ----------------\n    UInt countPara = 0;\n    std::vector<ParameterName> baseNames;\n    parametrization->parameterName(baseNames);\n    index.resize(antennaNames.size());\n    for(UInt idAnt=0; idAnt<antennaNames.size(); idAnt++)\n      if(types.at(idAnt).size())\n      {\n        std::sort(types.at(idAnt).begin(), types.at(idAnt).end());\n        for(GnssType type : types.at(idAnt))\n        {\n          std::string typeStr = \".\" + type.str();\n          std::vector<ParameterName> parameterNames;\n          for(const auto &base : baseNames)\n            parameterNames.push_back(ParameterName(antennaNames.at(idAnt), base.type + typeStr, base.temporal, base.interval));\n          index.at(idAnt).push_back(normalEquationInfo.parameterNamesOther(parameterNames));\n          countPara += parameterNames.size();\n        }\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i transmitter antenna parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterAntennas::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    const UInt idAnt = transmitter2antenna.at(eqn.transmitter->idTrans());\n    if((idAnt >= index.size()) || !index.at(idAnt).size())\n      return;\n\n    Matrix B(eqn.l.rows(), types.at(idAnt).size());\n    std::vector<Bool> used(types.at(idAnt).size(), FALSE);\n    UInt idPattern;\n    for(UInt idType=0; idType<eqn.typesTransmitted.size(); idType++)\n      if(eqn.typesTransmitted.at(idType).isInList(types.at(idAnt), idPattern))\n      {\n        axpy(1., eqn.A.column(GnssObservationEquation::idxUnit + eqn.types.size() + idType), B.column(idPattern));\n        used.at(idPattern) = TRUE;\n      }\n    if(!std::any_of(used.begin(), used.end(), [](Bool x){return x;}))\n      return;\n\n    const Matrix Acv = parametrization->designMatrix(eqn.azimutTrans, eqn.elevationTrans);\n    for(UInt idPattern=0; idPattern<types.at(idAnt).size(); idPattern++)\n      if(used.at(idPattern))\n        matMult(1., B.column(idPattern), Acv, A.column(index.at(idAnt).at(idPattern)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTransmitterAntennas.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTransmitterAntennas.h\n*\n* @brief Antenna center variations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONTRANSMITTERANTENNAS__\n#define __GROOPS_GNSSPARAMETRIZATIONTRANSMITTERANTENNAS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationTransmitterAntennas = R\"(\n\\subsection{TransmitterAntennas}\\label{gnssParametrizationType:transmitterAntennas}\nSame as \\configClass{receiverAntennas}{gnssParametrizationType:receiverAntennas} but\nfor transmitting antennas (GNSS satellites).\n\nThe \\file{parameter names}{parameterName} are\n\\verb|<antennaName>:<antennaCenterVariations>.<gnssType>::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Antenna center variations.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationTransmitterAntennas : public GnssParametrizationBase\n{\n  Gnss                                        *gnss;\n  std::string                                  name;\n  PlatformSelectorPtr                          selectTransmitters;\n  ParametrizationGnssAntennaPtr                parametrization;\n  std::vector<GnssType>                        typesPattern;\n  Bool                                         addNonMatchingTypes;\n  Bool                                         ignoreSerial;\n  std::vector<UInt>                            transmitter2antenna;\n  std::vector<std::vector<GnssParameterIndex>> index; // for each antenna and pattern\n  std::vector<std::vector<GnssType>>           types; // for each antenna and pattern\n\npublic:\n  GnssParametrizationTransmitterAntennas(Config &config);\n\n  void init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTransmitterDynamicOrbits.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTransmitterDynamicOrbits.cpp\n*\n* @brief Orbits by variational equations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTransmitterDynamicOrbits.h\"\n\n/***********************************************/\n\nGnssParametrizationTransmitterDynamicOrbits::GnssParametrizationTransmitterDynamicOrbits(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr stochasticPulse;\n\n    readConfig(config, \"name\",                        name,                        Config::OPTIONAL, \"parameter.transmitterDynamicOrbits\", \"used for parameter selection\");\n    readConfig(config, \"selectTransmitters\",          selectTransmitters,          Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"outputfileOrbit\",             fileNameOrbit,               Config::OPTIONAL, \"\",     \"variable {prn} available\");\n    readConfig(config, \"outputfileParameters\",        fileNameParameter,           Config::OPTIONAL, \"\",     \"variable {prn} available\");\n    readConfig(config, \"inputfileVariational\",        fileNameVariational,         Config::MUSTSET,  \"variational_{loopTime:%D}.{prn}.dat\", \"variable {prn} available\");\n    readConfig(config, \"stochasticPulse\",             stochasticPulse,             Config::DEFAULT,  \"\",     \"[mu/s] parametrization of stochastic pulses\");\n    readConfig(config, \"parametrizationAcceleration\", parametrizationAcceleration, Config::DEFAULT,  \"\",     \"orbit force parameters\");\n    readConfig(config, \"ephemerides\",                 ephemerides,                 Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"minEstimableEpochsRatio\",     minEstimableEpochsRatio,     Config::DEFAULT,  \"0.75\", \"drop satellites with lower ratio of estimable epochs to total epochs\");\n    readConfig(config, \"integrationDegree\",           integrationDegree,           Config::DEFAULT,  \"7\",    \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,         Config::DEFAULT,  \"7\",    \"for orbit interpolation and velocity calculation\");\n    if(isCreateSchema(config)) return;\n\n    pulses = stochasticPulse->times();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationTransmitterDynamicOrbits::~GnssParametrizationTransmitterDynamicOrbits()\n{\n  for(Parameter *para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterDynamicOrbits::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    auto selectedTransmitters = gnss->selectTransmitters(selectTransmitters);\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(\"prn\", \"***\");\n    parameters.resize(gnss->transmitters.size(), nullptr);\n    for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n      if(selectedTransmitters.at(idTrans) && gnss->transmitters.at(idTrans)->useable())\n      {\n        auto para = new Parameter();\n        parameters.at(idTrans) = para;\n        para->trans = gnss->transmitters.at(idTrans);\n\n        // find first and last valid epoch\n        const Time timeStart = para->trans->timesPosVel.front();\n        const Time timeEnd   = para->trans->timesPosVel.back();\n\n        // stochastic pulses in interval\n        std::vector<Time> pulsesInterval;\n        std::copy_if(pulses.begin(), pulses.end(), std::back_inserter(pulsesInterval), [&](auto &p) {return (timeStart < p) && (p < timeEnd);});\n\n        fileNameVariableList.setVariable(\"prn\", para->trans->name());\n        VariationalEquationFromFile file;\n        file.open(fileNameVariational(fileNameVariableList), nullptr/*parametrizationGravity*/, parametrizationAcceleration, pulsesInterval, ephemerides, integrationDegree);\n\n        auto variationalEquation = file.integrateArc(timeStart, timeEnd, TRUE/*computePosition*/, TRUE/*computeVelocity*/);\n        para->times     = variationalEquation.times;\n        para->PosDesign = variationalEquation.PosDesign;\n        para->VelDesign = variationalEquation.VelDesign;\n        para->x         = Vector(para->PosDesign.columns());\n        para->polynomial.init(para->times, interpolationDegree, TRUE/*throwException*/, FALSE/*leastSquares*/, -(interpolationDegree+1.1), -1.1, 1e-7);\n\n        // parameter names\n        file.parameterNameSatellite(para->parameterNames);\n        file.parameterNameSatelliteArc(para->parameterNames);\n        for(auto &name : para->parameterNames)\n          name.object = para->trans->name();\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterDynamicOrbits::requirements(GnssNormalEquationInfo &normalEquationInfo,\n                                                               std::vector<UInt> &transCount, std::vector<UInt> &/*transCountEpoch*/,\n                                                               std::vector<UInt> &/*recvCount*/,  std::vector<UInt> &/*recvCountEpoch*/)\n{\n  try\n  {\n    if(isEnabled(normalEquationInfo, name) && !normalEquationInfo.isEachReceiverSeparately)\n      for(auto para : parameters)\n        if(para && para->trans->useable())\n         transCount.at(para->trans->idTrans()) += static_cast<UInt>(minEstimableEpochsRatio * normalEquationInfo.idEpochs.size());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterDynamicOrbits::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n   for(auto para : parameters)\n      if(para)\n        para->index = GnssParameterIndex();\n    if(!isEnabled(normalEquationInfo, name) || normalEquationInfo.isEachReceiverSeparately)\n      return;\n\n    UInt countPara = 0;\n    for(auto para : parameters)\n      if(para && para->trans->useable())\n      {\n        para->index = normalEquationInfo.parameterNamesTransmitter(para->trans->idTrans(), para->parameterNames);\n        countPara += para->parameterNames.size();\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i transmitter dynamic orbit parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterDynamicOrbits::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(auto para : parameters)\n        if(para && para->index)\n          copy(para->x, x0.row(normalEquationInfo.index(para->index), para->x.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterDynamicOrbits::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.transmitter->idTrans());\n    if(para && para->index)\n      matMult(1., eqn.A.column(GnssObservationEquation::idxPosTrans, 3),\n              para->polynomial.interpolate({eqn.timeTrans}, para->PosDesign, 3),\n              A.column(para->index));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationTransmitterDynamicOrbits::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Gnss::InfoParameterChange info(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        const Vector dx = x.row(normalEquationInfo.index(para->index), para->x.rows());\n        para->x += dx;\n        const Vector dpos = para->polynomial.interpolate(para->trans->timesPosVel, para->PosDesign * dx, 3);\n        const Vector dvel = para->polynomial.interpolate(para->trans->timesPosVel, para->VelDesign * dx, 3);\n        para->trans->pos += reshape(dpos, 3, para->trans->pos.rows()).trans();\n        para->trans->vel += reshape(dvel, 3, para->trans->vel.rows()).trans();\n\n        for(UInt i=0; i<para->trans->timesPosVel.size(); i++)\n          if(info.update(1e3*norm(dpos.row(3*i, 3))))\n            info.info = \"position transmitter (\"+para->trans->name()+\", \"+para->trans->timesPosVel.at(i).dateTimeStr()+\")\";\n      }\n    info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTransmitterDynamicOrbits::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name) || !Parallel::isMaster(normalEquationInfo.comm))\n      return;\n\n    if(!fileNameOrbit.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logStatus<<\"write transmitter orbits to files <\"<<fileNameOrbit(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n          OrbitArc arc;\n          for(UInt idEpoch=0; idEpoch<para->times.size(); idEpoch++)\n          {\n            OrbitEpoch epoch;\n            epoch.time     = para->times.at(idEpoch);\n            epoch.position = para->trans->positionCoM(para->times.at(idEpoch));\n            epoch.velocity = para->trans->velocity(para->times.at(idEpoch));\n            arc.push_back(epoch);\n          }\n          fileNameVariableList.setVariable(\"prn\", para->trans->name());\n          InstrumentFile::write(fileNameOrbit(fileNameVariableList).appendBaseName(suffix), arc);\n        }\n    }\n\n    if(!fileNameParameter.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logStatus<<\"write estimated transmitter parameters to files <\"<<fileNameParameter(fileNameVariableList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n          fileNameVariableList.setVariable(\"prn\", para->trans->name());\n          writeFileMatrix(fileNameParameter(fileNameVariableList).appendBaseName(suffix), para->x);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTransmitterDynamicOrbits.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTransmitterDynamicOrbits.h\n*\n* @brief Orbits by variational equations.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONTRANSMITTERDYNAMICORBITS__\n#define __GROOPS_GNSSPARAMETRIZATIONTRANSMITTERDYNAMICORBITS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationTransmitterDynamicOrbits = R\"(\n\\subsection{TransmitterDynamicOrbits}\\label{gnssParametrizationType:transmitterDynamicOrbits}\nSame as \\configClass{leoDynamicOrbits}{gnssParametrizationType:leoDynamicOrbits} but\nfor transmitting GNSS satellites.\nFor more details see \\reference{orbit integration}{cookbook.gnssNetwork:orbitIntegration}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Orbits by variational equations.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationTransmitterDynamicOrbits : public GnssParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    GnssTransmitterPtr         trans;\n    GnssParameterIndex         index;\n    std::vector<ParameterName> parameterNames;\n    std::vector<Time>          times;\n    Matrix                     PosDesign, VelDesign;\n    Vector                     x;\n    Polynomial                 polynomial;\n  };\n\n  Gnss                          *gnss;\n  std::string                    name;\n  PlatformSelectorPtr            selectTransmitters;\n  FileName                       fileNameOrbit, fileNameParameter, fileNameVariational;\n  std::vector<Time>              pulses;\n  ParametrizationAccelerationPtr parametrizationAcceleration;\n  EphemeridesPtr                 ephemerides;\n  Double                         minEstimableEpochsRatio;\n  UInt                           integrationDegree, interpolationDegree;\n  std::vector<Parameter*>        parameters;\n\npublic:\n  GnssParametrizationTransmitterDynamicOrbits(Config &config);\n ~GnssParametrizationTransmitterDynamicOrbits();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   requirements(GnssNormalEquationInfo &normalEquationInfo, std::vector<UInt> &transCount, std::vector<UInt> &transCountEpoch,\n                      std::vector<UInt> &recvCount, std::vector<UInt> &recvCountEpoch) override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTroposphere.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTroposphere.cpp\n*\n* @brief Troposphere.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/troposphere/troposphere.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrizationTroposphere.h\"\n\n/***********************************************/\n\nGnssParametrizationTroposphere::GnssParametrizationTroposphere(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                          name,                    Config::OPTIONAL, \"parameter.troposphere\", \"used for parameter selection\");\n    readConfig(config, \"selectReceivers\",               selectReceivers,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"outputfileTroposphere\",         fileNameTropo,           Config::OPTIONAL, \"output/troposphere_{loopTime:%D}.{station}.txt\", \"columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient, ...\");\n    readConfig(config, \"troposphere\",                   troposphere,             Config::MUSTSET,  \"\",  \"a priori troposphere model\");\n    readConfig(config, \"troposphereWetEstimation\",      parametrizationWet,      Config::DEFAULT,  \"\",  \"[m] parametrization of zenith wet delays\");\n    readConfig(config, \"troposphereGradientEstimation\", parametrizationGradient, Config::DEFAULT,  \"\",  \"[degree] parametrization of north and east gradients\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssParametrizationTroposphere::~GnssParametrizationTroposphere()\n{\n  for(Parameter *para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTroposphere::init(Gnss *gnss, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    this->gnss = gnss;\n    auto selectedReceivers = gnss->selectReceivers(selectReceivers);\n    parameters.resize(gnss->receivers.size(), nullptr);\n    UInt idTropo = 0;\n    std::vector<std::string> names;\n    std::vector<Vector3d>    positions;\n    for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n      if(selectedReceivers.at(idRecv) && gnss->receivers.at(idRecv)->useable())\n      {\n        auto para = new Parameter();\n        parameters.at(idRecv) = para;\n        para->idRecv = idRecv;\n        if(gnss->receivers.at(idRecv)->isMyRank())\n        {\n          names.push_back(gnss->receivers.at(idRecv)->name());\n          positions.push_back(gnss->receivers.at(idRecv)->position(0));\n          para->idTropo   = idTropo++;\n          para->xWet      = Vector(parametrizationWet->parameterCount());\n          para->xGradient = Vector(2*parametrizationGradient->parameterCount());\n          para->zenitDelayWet.resize(gnss->times.size(), 0);\n          para->gradientX.resize(gnss->times.size(), 0);\n          para->gradientY.resize(gnss->times.size(), 0);\n        }\n      }\n\n    troposphere->init(names, positions);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTroposphere::initParameter(GnssNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para)\n        para->indexWet = para->indexGradient = GnssParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    // wet troposphere\n    UInt countParaWet = 0;\n    if(parametrizationWet->parameterCount())\n      for(auto para : parameters)\n        if(para && normalEquationInfo.estimateReceiver.at(para->idRecv))\n        {\n          std::vector<ParameterName> parameterNames;\n          parametrizationWet->parameterName({ParameterName(gnss->receivers.at(para->idRecv)->name(), \"troposphereWet\")}, parameterNames);\n          para->indexWet = normalEquationInfo.parameterNamesReceiver(para->idRecv, parameterNames);\n          countParaWet += parameterNames.size();\n        }\n    if(countParaWet)\n      logInfo<<countParaWet%\"%9i troposphere wet parameters\"s<<Log::endl;\n\n    // troposphere gradient\n    UInt countParaGradient = 0;\n    if(parametrizationGradient->parameterCount())\n      for(auto para : parameters)\n        if(para && normalEquationInfo.estimateReceiver.at(para->idRecv))\n        {\n          std::vector<ParameterName> parameterNames;\n          std::vector<ParameterName> name({{gnss->receivers.at(para->idRecv)->name(), \"troposphereGradient.x\"}, {gnss->receivers.at(para->idRecv)->name(), \"troposphereGradient.y\"}});\n          parametrizationGradient->parameterName(name, parameterNames);\n          para->indexGradient = normalEquationInfo.parameterNamesReceiver(para->idRecv, parameterNames);\n          countParaGradient += parameterNames.size();\n        }\n    if(countParaGradient)\n      logInfo<<countParaGradient%\"%9i troposphere gradient parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTroposphere::observationCorrections(GnssObservationEquation &eqn) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.receiver->idRecv());\n    if(!para)\n      return;\n\n    const Time t = std::max(eqn.timeRecv, gnss->times.at(0));\n    // apriori value\n    Double delay = troposphere->slantDelay(para->idTropo, t, GnssType::L2_G.frequency(), eqn.azimutRecvLocal, eqn.elevationRecvLocal);\n    // estimated wet effect\n    delay += troposphere->mappingFunctionWet(para->idTropo, t, GnssType::L2_G.frequency(), eqn.azimutRecvLocal, eqn.elevationRecvLocal) * para->zenitDelayWet.at(eqn.idEpoch);\n    // estimated gradient\n    Double dx, dy;\n    troposphere->mappingFunctionGradient(para->idTropo, t, GnssType::L2_G.frequency(), eqn.azimutRecvLocal, eqn.elevationRecvLocal, dx, dy);\n    delay += dx * para->gradientX.at(eqn.idEpoch) + dy * para->gradientY.at(eqn.idEpoch);\n\n    for(UInt i=0; i<eqn.types.size(); i++)\n      if((eqn.types.at(i) == GnssType::RANGE) || (eqn.types.at(i) == GnssType::PHASE))\n        eqn.l(i) -= delay;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTroposphere::aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    // update wet troposphere\n    for(auto para : parameters)\n      if(para && para->indexWet && gnss->receivers.at(para->idRecv)->isMyRank())\n        copy(para->xWet, x0.row(normalEquationInfo.index(para->indexWet), para->xWet.rows()));\n\n    // update troposphere gradient\n    for(auto para : parameters)\n      if(para && para->indexGradient && gnss->receivers.at(para->idRecv)->isMyRank())\n        copy(para->xGradient, x0.row(normalEquationInfo.index(para->indexGradient), para->xGradient.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTroposphere::designMatrix(const GnssNormalEquationInfo &/*normalEquationInfo*/, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.receiver->idRecv());\n    if(!para)\n      return;\n\n    // temporal parametrization\n    auto designMatrixTemporal = [&](ParametrizationTemporalPtr parametrization, const_MatrixSliceRef B, const GnssParameterIndex &index)\n    {\n      std::vector<UInt>   idx;\n      std::vector<Double> factor;\n      parametrization->factors(std::max(eqn.timeRecv, gnss->times.at(0)), idx, factor);\n      MatrixSlice Design(A.column(index));\n      for(UInt i=0; i<factor.size(); i++)\n        axpy(factor.at(i), B, Design.column(B.columns()*idx.at(i), B.columns()));\n    };\n\n    // troposphere wet\n    if(para->indexWet)\n    {\n      const Double mappingFunctionWet = troposphere->mappingFunctionWet(para->idTropo, std::max(eqn.timeRecv, gnss->times.at(0)), GnssType::L2_G.frequency(), eqn.azimutRecvLocal, eqn.elevationRecvLocal);\n      const Matrix B = mappingFunctionWet * eqn.A.column(GnssObservationEquation::idxRange,1);\n      designMatrixTemporal(parametrizationWet, B, para->indexWet);\n    }\n\n    // troposphere gradient\n    if(para->indexGradient)\n    {\n      Double dx, dy;\n      troposphere->mappingFunctionGradient(para->idTropo, std::max(eqn.timeRecv, gnss->times.at(0)), GnssType::L2_G.frequency(), eqn.azimutRecvLocal, eqn.elevationRecvLocal, dx, dy);\n      Matrix B(eqn.A.rows(), 2);\n      axpy(dx, eqn.A.column(GnssObservationEquation::idxRange,1), B.column(0));\n      axpy(dy, eqn.A.column(GnssObservationEquation::idxRange,1), B.column(1));\n      designMatrixTemporal(parametrizationGradient, B, para->indexGradient);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssParametrizationTroposphere::updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    // update wet troposphere\n    Double maxChange = 0;\n    Gnss::InfoParameterChange infoWet(\"mm\");\n    for(auto para : parameters)\n      if(para && para->indexWet && gnss->receivers.at(para->idRecv)->isMyRank())\n      {\n        auto recv = gnss->receivers.at(para->idRecv);\n        para->xWet += x.row(normalEquationInfo.index(para->indexWet), parametrizationWet->parameterCount());\n        std::vector<UInt>   index;\n        std::vector<Double> factor;\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n        {\n          parametrizationWet->factors(std::max(recv->timeCorrected(idEpoch), gnss->times.at(0)), index, factor);\n          Double z = 0;\n          for(UInt k=0; k<factor.size(); k++)\n            z += factor.at(k) * para->xWet(index.at(k));\n          const Double zOld = para->zenitDelayWet.at(idEpoch);\n          para->zenitDelayWet.at(idEpoch) = z;\n          if(infoWet.update(1e3*(z-zOld)))\n            infoWet.info = \"troposphere wet (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n        }\n      }\n    infoWet.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    // update troposphere gradient\n    Gnss::InfoParameterChange infoGradient(\"mm\");\n    for(auto para : parameters)\n      if(para && para->indexGradient && gnss->receivers.at(para->idRecv)->isMyRank())\n      {\n        auto recv = gnss->receivers.at(para->idRecv);\n        para->xGradient += x.row(normalEquationInfo.index(para->indexGradient), 2*parametrizationGradient->parameterCount());\n        std::vector<UInt>   index;\n        std::vector<Double> factor;\n        for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n        {\n          parametrizationGradient->factors(std::max(recv->timeCorrected(idEpoch), gnss->times.at(0)), index, factor);\n          Double gx=0, gy=0;\n          for(UInt k=0; k<factor.size(); k++)\n          {\n            gx += factor.at(k) * para->xGradient(2*index.at(k)+0);\n            gy += factor.at(k) * para->xGradient(2*index.at(k)+1);\n          }\n          const Double dx = gx - para->gradientX.at(idEpoch);\n          const Double dy = gy - para->gradientY.at(idEpoch);\n          para->gradientX.at(idEpoch) = gx;\n          para->gradientY.at(idEpoch) = gy;\n          const Double dxdy = std::sqrt(dx*dx+dy*dy);\n          if(infoGradient.update(1e3*dxdy))\n            infoGradient.info = \"troposphere gradient (\"+recv->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n        }\n      }\n    infoGradient.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssParametrizationTroposphere::writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name) || fileNameTropo.empty())\n      return;\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(\"station\", \"****\");\n    fileNameVariableList.setVariable(\"station\", \"****\");\n    for(auto para : parameters)\n      if(para && normalEquationInfo.estimateReceiver.at(para->idRecv) && gnss->receivers.at(para->idRecv)->isMyRank())\n      {\n        Matrix A(normalEquationInfo.idEpochs.size(), 12);\n        std::vector<Time> times;\n        for(UInt i=0; i<normalEquationInfo.idEpochs.size(); i++)\n        {\n          const UInt idEpoch = normalEquationInfo.idEpochs.at(i);\n          Double zenithWetDelay, zenithDryDelay, gradientWetNorth, gradientDryNorth, gradientWetEast, gradientDryEast, aDry, aWet;\n          troposphere->getAprioriValues(para->idTropo, gnss->times.at(idEpoch), GnssType::L2_G.frequency(),\n                                        zenithDryDelay, zenithWetDelay, gradientDryNorth, gradientWetNorth, gradientDryEast, gradientWetEast, aDry, aWet);\n          times.push_back(gnss->times.at(idEpoch));\n          A(i,  0) = gnss->times.at(idEpoch).mjd();\n          A(i,  1) = zenithDryDelay;                                     // tropospheric zenith dry delay [m] (only from model)\n          A(i,  2) = zenithWetDelay   + para->zenitDelayWet.at(idEpoch); // tropospheric zenith wet delay [m] (model + delta estimate)\n          A(i,  3) = gradientDryNorth + para->gradientX.at(idEpoch);     // tropospheric dry gradient - north direction [m] (model + delta estimate, due to same mapping function)\n          A(i,  4) = gradientWetNorth;                                   // tropospheric wet gradient - north direction [m] (only from model)\n          A(i,  5) = gradientDryEast  + para->gradientY.at(idEpoch);     // tropospheric dry gradient - east component [m] (model + delta estimate, due to same mapping function)\n          A(i,  6) = gradientWetEast;                                    // tropospheric wet gradient - east component [m] (only from model)\n          A(i,  7) = para->zenitDelayWet.at(idEpoch);                    // tropospheric zenith wet delay [m] (delta estimate)\n          A(i,  8) = para->gradientX.at(idEpoch);                        // tropospheric gradient - north [m] (delta estimate)\n          A(i,  9) = para->gradientY.at(idEpoch);                        // tropospheric gradient - east  [m] (delta estimate)\n          A(i, 10) = aDry;                                               // dry mapping function coefficient a []\n          A(i, 11) = aWet;                                               // wet mapping function coefficient a []\n        }\n\n        fileNameVariableList.setVariable(\"station\", gnss->receivers.at(para->idRecv)->name());\n        InstrumentFile::write(fileNameTropo(fileNameVariableList).appendBaseName(suffix), Arc(times, A));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssParametrization/gnssParametrizationTroposphere.h",
    "content": "/***********************************************/\n/**\n* @file gnssParametrizationTroposphere.h\n*\n* @brief Troposphere.\n* @see GnssParametrization\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-01-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPARAMETRIZATIONTROPOSPHERE__\n#define __GROOPS_GNSSPARAMETRIZATIONTROPOSPHERE__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssParametrization\nstatic const char *docstringGnssParametrizationTroposphere = R\"(\n\\subsection{Troposphere}\\label{gnssParametrizationType:troposphere}\nA priori tropospheric correction is handled by a \\configClass{troposphere}{troposphereType} model (e.g. Vienna Mapping Functions 3).\nAdditional parameters in $[m]$ for zenith wet delay and gradients can be set up via\n\\configClass{troposphereWetEstimation}{parametrizationTemporalType} (usually 2-hourly linear splines)\nand \\configClass{troposphereGradientEstimation}{parametrizationTemporalType} (usually a daily trend).\nThese parameters can be soft-constrained using\n\\configClass{parametrization:constraints}{gnssParametrizationType:constraints}\nto avoid an unsolvable system of normal equations in case of data gaps.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:troposphereWet:<temporal>:<interval>|,\n\\item \\verb|<station>:troposphereGradient.x:<temporal>:<interval>|,\n\\item \\verb|<station>:troposphereGradient.y:<temporal>:<interval>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"gnss/gnss.h\"\n#include \"classes/troposphere/troposphere.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Troposphere.\n* @ingroup gnssParametrizationGroup\n* @see GnssParametrization */\nclass GnssParametrizationTroposphere : public GnssParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    UInt                idRecv, idTropo;\n    GnssParameterIndex  indexWet, indexGradient;\n    Vector              xWet, xGradient;\n    std::vector<Double> zenitDelayWet, gradientX, gradientY;\n  };\n\n  Gnss                      *gnss;\n  std::string                name;\n  PlatformSelectorPtr        selectReceivers;\n  FileName                   fileNameTropo;\n  TropospherePtr             troposphere;\n  ParametrizationTemporalPtr parametrizationWet;\n  ParametrizationTemporalPtr parametrizationGradient;\n  std::vector<Parameter*>    parameters;\n\n\npublic:\n  GnssParametrizationTroposphere(Config &config);\n ~GnssParametrizationTroposphere();\n\n  void   init(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n  void   observationCorrections(GnssObservationEquation &eqn) const override;\n  void   initParameter(GnssNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const GnssNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const GnssNormalEquationInfo &normalEquationInfo, const GnssObservationEquation &eqn, GnssDesignMatrix &A) const override;\n  Double updateParameter(const GnssNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const GnssNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStep.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStep.cpp\n*\n* @brief Processing steps for GNSS normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_GnssProcessingStep\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"config/configRegister.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepEstimate.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepResolveAmbiguities.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepComputeCovarianceMatrix.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepWriteResults.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepWriteNormalEquations.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepWriteAprioriSolution.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepWriteResiduals.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepWriteUsedStationList.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepWriteUsedTransmitterList.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepPrintResidualStatistics.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepSelectParametrizations.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepSelectEpochs.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepSelectNormalsBlockStructure.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepSelectReceivers.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepForEachReceiverSeparately.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepGroup.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStepDisableTransmitterShadowEpochs.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(GnssProcessingStep, \"gnssProcessingStepType\",\n                      GnssProcessingStepEstimate,\n                      GnssProcessingStepResolveAmbiguities,\n                      GnssProcessingStepComputeCovarianceMatrix,\n                      GnssProcessingStepWriteResults,\n                      GnssProcessingStepWriteNormalEquations,\n                      GnssProcessingStepWriteAprioriSolution,\n                      GnssProcessingStepWriteResiduals,\n                      GnssProcessingStepWriteUsedStationList,\n                      GnssProcessingStepWriteUsedTransmitterList,\n                      GnssProcessingStepPrintResidualStatistics,\n                      GnssProcessingStepSelectParametrizations,\n                      GnssProcessingStepSelectEpochs,\n                      GnssProcessingStepSelectNormalsBlockStructure,\n                      GnssProcessingStepSelectReceivers,\n                      GnssProcessingStepForEachReceiverSeparately,\n                      GnssProcessingStepGroup,\n                      GnssProcessingStepDisableTransmitterShadowEpochs)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(GnssProcessingStep, \"gnssProcessingStepType\")\n\n/***********************************************/\n\nGnssProcessingStep::GnssProcessingStep(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"estimate\",                       type, \"least squares adjustment\"))\n        bases.push_back(new GnssProcessingStepEstimate(config));\n      if(readConfigChoiceElement(config, \"resolveAmbiguities\",             type, \"resolve integer ambiguities\"))\n        bases.push_back(new GnssProcessingStepResolveAmbiguities(config));\n      if(readConfigChoiceElement(config, \"computeCovarianceMatrix\",        type, \"compute covariance matrix\"))\n        bases.push_back(new GnssProcessingStepComputeCovarianceMatrix(config));\n      if(readConfigChoiceElement(config, \"writeResults\",                   type, \"write all estimated parameters\"))\n        bases.push_back(new GnssProcessingStepWriteResults(config));\n      if(readConfigChoiceElement(config, \"writeNormalEquations\",           type, \"write unconstrained and constraint normal equations\"))\n        bases.push_back(new GnssProcessingStepWriteNormalEquations(config));\n      if(readConfigChoiceElement(config, \"writeAprioriSolution\",           type, \"write apriori solution vector\"))\n        bases.push_back(new GnssProcessingStepWriteAprioriSolution(config));\n      if(readConfigChoiceElement(config, \"writeResiduals\",                 type, \"write observation residuals\"))\n        bases.push_back(new GnssProcessingStepWriteResiduals(config));\n      if(readConfigChoiceElement(config, \"writeUsedStationList\",           type, \"write used stations\"))\n        bases.push_back(new GnssProcessingStepWriteUsedStationList(config));\n      if(readConfigChoiceElement(config, \"writeUsedTransmitterList\",       type, \"write used transmitters\"))\n        bases.push_back(new GnssProcessingStepWriteUsedTransmitterList(config));\n      if(readConfigChoiceElement(config, \"printResidualStatistics\",        type, \"print residual statistics\"))\n        bases.push_back(new GnssProcessingStepPrintResidualStatistics(config));\n      if(readConfigChoiceElement(config, \"selectParametrizations\",         type, \"select parametrizations for all subsequent processing steps\"))\n        bases.push_back(new GnssProcessingStepSelectParametrizations(config));\n      if(readConfigChoiceElement(config, \"selectEpochs\",                   type, \"select epochs to be used in all subsequent processing steps\"))\n        bases.push_back(new GnssProcessingStepSelectEpochs(config));\n      if(readConfigChoiceElement(config, \"selectNormalsBlockStructure\",    type, \"select block structure of the distributed normal equation matrix for all subsequent processing steps\"))\n        bases.push_back(new GnssProcessingStepSelectNormalsBlockStructure(config));\n      if(readConfigChoiceElement(config, \"selectReceivers\",                type, \"use this subset of stations in all subsequent processing steps\"))\n        bases.push_back(new GnssProcessingStepSelectReceivers(config));\n      if(readConfigChoiceElement(config, \"forEachReceiverSeparately\",      type, \"process receiver by receiver, transmitter parameters disabled\"))\n        bases.push_back(new GnssProcessingStepForEachReceiverSeparately(config));\n      if(readConfigChoiceElement(config, \"group\",                          type, \"group processing steps\"))\n        bases.push_back(new GnssProcessingStepGroup(config));\n      if(readConfigChoiceElement(config, \"disableTransmitterShadowEpochs\", type, \"disable transmitter epochs in eclipse\"))\n        bases.push_back(new GnssProcessingStepDisableTransmitterShadowEpochs(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssProcessingStep::~GnssProcessingStep()\n{\n  for(auto base : bases)\n    delete base;\n}\n\n/***********************************************/\n\nvoid GnssProcessingStep::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    for(auto base : bases)\n    {\n      Parallel::peek(state.normalEquationInfo.comm);\n      if(base->expectInitializedParameters() && state.changedNormalEquationInfo)\n      {\n        state.gnss->initParameter(state.normalEquationInfo);\n        state.changedNormalEquationInfo = FALSE;\n      }\n      base->process(state);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGnssProcessingStep::State::State(GnssPtr gnss, Parallel::CommunicatorPtr comm) :\n  gnss(gnss), normalEquationInfo(gnss->times.size(), gnss->receivers.size(), gnss->transmitters.size(), comm),\n  changedNormalEquationInfo(TRUE), stations(gnss->receivers.size()) {}\n\n/***********************************************/\n\nvoid GnssProcessingStep::State::decorrelatedDesignMatrix(GnssObservationEquation &eqn, GnssDesignMatrix &B, GnssDesignMatrix &A)\n{\n  try\n  {\n    auto &station = stations.at(eqn.receiver->idRecv());\n    if(!station.arOrder)\n    {\n      gnss->designMatrix(normalEquationInfo, eqn, A);\n      return;\n    }\n\n    // TODO: consider stations with lower sampling!\n    // find future epochs of same track\n    std::vector<UInt> idEpochs(1, eqn.idEpoch);\n    auto iterIdEpoch = std::upper_bound(normalEquationInfo.idEpochs.begin(), normalEquationInfo.idEpochs.end(), idEpochs.back());\n    for(UInt lag=1; (lag <= station.arOrder) && (iterIdEpoch != normalEquationInfo.idEpochs.end()); lag++, iterIdEpoch++)\n    {\n      const GnssObservation *obs = eqn.receiver->observation(eqn.transmitter->idTrans(), *iterIdEpoch);\n      if(!obs || (obs->track != eqn.track))\n        break;\n      idEpochs.push_back(*iterIdEpoch); // store epoch\n    }\n\n    if(idEpochs.size() == 1)\n    {\n      gnss->designMatrix(normalEquationInfo, eqn, A);\n      return;\n    }\n\n    const UInt obsCount = eqn.types.size();\n    const UInt order    = idEpochs.size()-1;\n    std::vector<Double> factors(obsCount);\n    std::vector<UInt>   rowInA(obsCount);\n    std::vector<UInt>   idxType(obsCount);\n    std::iota(rowInA.begin(), rowInA.end(), 0);\n    for(UInt i=0; i<obsCount; i++)\n      idxType.at(i) = GnssType::index(station.arTypes, eqn.types.at(i));\n\n    // lag 0\n    for(UInt i=0; i<obsCount; i++)\n    {\n      eqn.l.row(i) *= station.arProcesses.at(idxType.at(i)).at(order).at(0);\n      eqn.A.row(i) *= station.arProcesses.at(idxType.at(i)).at(order).at(0);\n    }\n    gnss->designMatrix(normalEquationInfo, eqn, A);\n\n    // other lags\n    for(UInt k=1; k<idEpochs.size(); k++)\n    {\n      const GnssObservation *obs = eqn.receiver->observation(eqn.transmitter->idTrans(), idEpochs.at(k));\n      GnssObservationEquation eqnB(*obs, *eqn.receiver, *eqn.transmitter,\n                                   gnss->funcRotationCrf2Trf, gnss->funcReduceModels, idEpochs.at(k), TRUE, eqn.types);\n      eqnB.eliminateGroupParameters(FALSE);\n      B.init(eqnB.l.rows());\n      gnss->designMatrix(normalEquationInfo, eqnB, B);\n      for(UInt i=0; i<obsCount; i++)\n        factors.at(i) = station.arProcesses.at(idxType.at(i)).at(order).at(k);\n      GnssDesignMatrix::axpy(rowInA, factors, B, A);\n      for(UInt i=0; i<obsCount; i++)\n        eqn.l(i) += factors.at(i) * eqnB.l(i);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssProcessingStep::State::regularizeNotUsedParameters(UInt blockStart, UInt blockCount, const std::vector<ParameterName> &parameterNames)\n{\n  try\n  {\n    UInt countZeros = 0;\n    for(UInt i=blockStart; i<blockStart+blockCount; i++)\n      if(normals.isMyRank(i,i))\n      {\n        Matrix &N = normals.N(i,i);\n        for(UInt k=0; k<N.rows(); k++)\n          if(N(k,k)==0.)\n          {\n            N(k,k) += 1.0;\n            countZeros++;\n            logWarning<<\"    \"<<parameterNames.at(normals.blockIndex(i)+k).str()<<\" has zero diagonal element\"<<Log::endl;\n          }\n      }\n    Parallel::reduceSum(countZeros, 0, normals.communicator());\n    if(countZeros && Parallel::isMaster(normals.communicator()))\n    {\n      logWarning<<\"  \"<<countZeros<<\" parameters have zero diagonal elements -> set to one\"<<Log::endl;\n      obsCount -= countZeros;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssProcessingStep::State::collectNormalsBlocks(UInt blockStart, UInt blockCount)\n{\n  try\n  {\n    if(Parallel::size(normals.communicator()) <= 1)\n      return;\n\n    auto countBlocks = [&]()\n    {\n      UInt countBlocks = 0;\n      for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n        normals.loopBlockRow(idBlock, {idBlock, normals.blockCount()}, [&](UInt /*k*/, UInt /*ik*/) {countBlocks++;});\n      return countBlocks;\n    };\n\n    // synchronize used blocks\n    for(UInt idProcess=0; idProcess<Parallel::size(normals.communicator()); idProcess++)\n    {\n      Matrix rowColRank(countBlocks(), 3);\n      UInt i = 0;\n      for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n        normals.loopBlockRow(idBlock, {idBlock, normals.blockCount()}, [&](UInt k, UInt ik)\n        {\n          rowColRank(i, 0) = idBlock;\n          rowColRank(i, 1) = k;\n          rowColRank(i, 2) = normals._rank[ik];\n          i++;\n        });\n\n      Parallel::broadCast(rowColRank, idProcess, normals.communicator());\n      for(UInt i=0; i<rowColRank.rows(); i++)\n        normals.setBlock(static_cast<UInt>(rowColRank(i,0)), static_cast<UInt>(rowColRank(i,1)), static_cast<UInt>(rowColRank(i,2)));\n    }\n\n    // for each block x which process contains\n    Matrix usedRanks(countBlocks(), Parallel::size(normals.communicator()));\n    UInt i = 0;\n    for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n      normals.loopBlockRow(idBlock, {idBlock, normals.blockCount()}, [&](UInt /*k*/, UInt ik)\n      {\n        if(normals._N[ik].size())\n          usedRanks(i, Parallel::myRank(normals.communicator())) = 1.;\n        i++;\n      });\n    Parallel::reduceSum(usedRanks, 0, normals.communicator());\n    Parallel::broadCast(usedRanks, 0, normals.communicator());\n\n    // reduce sum normals\n    i = 0;\n    for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n      normals.loopBlockRow(idBlock, {idBlock, normals.blockCount()}, [&](UInt /*k*/, UInt ik)\n      {\n        std::vector<Bool> usedRank(usedRanks.columns());\n        for(UInt idProcess=0; idProcess<usedRank.size(); idProcess++)\n          usedRank[idProcess] = usedRanks(i, idProcess);\n        normals.reduceSum(normals._N[ik], ik, usedRank, TRUE/*free*/);\n        i++;\n      });\n\n    // right hand side\n    for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n    {\n      Parallel::reduceSum(n.at(idBlock), 0, normals.comm);\n      if(!Parallel::isMaster(normals.comm))\n        n.at(idBlock).setNull();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssProcessingStep::State::buildNormals(Bool constraintsOnly, Bool solveEpochParameters)\n{\n  try\n  {\n    normals.initEmpty(normalEquationInfo.blockIndices(), normalEquationInfo.comm,\n                      std::bind(&GnssNormalEquationInfo::normalsBlockRank, &normalEquationInfo, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));\n    n.resize(normals.blockCount());\n    for(UInt i=0; i<normals.blockCount(); i++)\n      n.at(i) = Vector(normals.blockSize(i));\n    lPl = Vector(1);\n    obsCount = 0;\n\n    // Loop over all epochs\n    // --------------------\n    Parallel::barrier(normalEquationInfo.comm);\n    logStatus<<\"accumulate normals\"<<Log::endl;\n    GnssDesignMatrix A(normalEquationInfo), B(normalEquationInfo);\n    UInt blockStart = 0; // first block, which is not regularized and reduced\n    UInt blockCount = 0;\n    UInt idLoop     = 0;\n    Log::Timer timer(normalEquationInfo.idEpochs.size());\n    for(UInt idEpoch : normalEquationInfo.idEpochs)\n    {\n      timer.loopStep(idLoop++);\n\n      gnss->constraintsEpoch(normalEquationInfo, idEpoch, normals, n, lPl(0), obsCount);\n\n      // loop over all receivers\n      if(!constraintsOnly)\n        for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n          if(normalEquationInfo.estimateReceiver.at(idRecv) && gnss->receivers.at(idRecv)->isMyRank())\n          {\n            if(!normalEquationInfo.accumulateEpochObservations)\n            {\n              GnssObservationEquation eqn;\n              for(UInt idTrans=0; idTrans<gnss->receivers.at(idRecv)->idTransmitterSize(idEpoch); idTrans++)\n                if(gnss->basicObservationEquations(normalEquationInfo, idRecv, idTrans, idEpoch, eqn))\n                {\n                  eqn.eliminateGroupParameters(!stations.at(idRecv).arOrder);\n                  A.init(eqn.l.rows());\n                  decorrelatedDesignMatrix(eqn, B, A);\n                  GnssDesignMatrix::accumulateNormals(A, eqn.l, normals, n, lPl(0), obsCount);\n                  obsCount -= eqn.rankDeficit;\n                }\n            }\n            else // accumulateEpochObservations\n            {\n              // all observation equations for this epoch\n              std::vector<GnssObservationEquation> eqns(gnss->transmitters.size());\n              UInt countEqn = 0;\n              for(UInt idTrans=0; idTrans<gnss->receivers.at(idRecv)->idTransmitterSize(idEpoch); idTrans++)\n                if(gnss->basicObservationEquations(normalEquationInfo, idRecv, idTrans, idEpoch, eqns.at(countEqn)))\n                  eqns.at(countEqn++).eliminateGroupParameters(!stations.at(idRecv).arOrder);\n              // copy all observations to a single vector\n              Vector l(std::accumulate(eqns.begin(), eqns.begin()+countEqn, UInt(0), [](UInt count, auto &eqn) {return count+eqn.l.rows();}));\n              A.init(l.rows());\n              UInt idx=0;\n              for(UInt i=0; i<countEqn; i++)\n              {\n                copy(eqns.at(i).l, l.row(idx, eqns.at(i).l.rows()));\n                decorrelatedDesignMatrix(eqns.at(i), B, A.selectRows(idx, eqns.at(i).l.rows()));\n                idx += eqns.at(i).l.rows();\n              }\n              GnssDesignMatrix::accumulateNormals(A.selectRows(0, l.rows()), l, normals, n, lPl(0), obsCount);\n              obsCount -= std::accumulate(eqns.begin(), eqns.begin()+countEqn, UInt(0), [](UInt count, auto &eqn) {return count+eqn.rankDeficit;});\n            }\n          } // for(idRecv)\n\n      // perform following steps not every epoch\n      blockCount += normalEquationInfo.blockCountEpoch(idEpoch);\n      if((blockCount < normalEquationInfo.defaultBlockCountReduction) && (idEpoch != normalEquationInfo.idEpochs.back()))\n        continue;\n\n      collectNormalsBlocks(blockStart, blockCount);\n\n      if(solveEpochParameters && !constraintsOnly)\n      {\n        regularizeNotUsedParameters(blockStart, blockCount, normalEquationInfo.parameterNames());\n        normals.cholesky(FALSE, blockStart, blockCount, FALSE);\n        normals.triangularTransSolve(n, blockStart, blockCount, FALSE);\n        if(Parallel::isMaster(normalEquationInfo.comm))\n          for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n          {\n            lPl(0)   -= quadsum(n.at(idBlock)); // lPl = lPl - n1' N1^(-1) n1\n            obsCount -= normals.blockSize(idBlock);\n          }\n      }\n\n      if(solveEpochParameters)\n      {\n        // remove N12 (epoch <-> other parameters)\n        for(UInt idBlock=blockStart; idBlock<blockStart+blockCount; idBlock++)\n          normals.loopBlockRow(idBlock, {normalEquationInfo.blockInterval(), normals.blockCount()}, [&](UInt /*k*/, UInt ik)\n          {\n            if(normals._N[ik].size())\n              normals._N[ik] = Matrix();\n          });\n      }\n\n      blockStart += blockCount;\n      blockCount  = 0;\n    } // for(idEpoch)\n    Parallel::barrier(normalEquationInfo.comm);\n    timer.loopEnd();\n\n    // other observations and constraints\n    // ----------------------------------\n    gnss->constraints(normalEquationInfo, normals, n, lPl(0), obsCount);\n\n    // collect normal equations\n    // ------------------------\n    if(Parallel::size(normals.comm)>1)\n    {\n      logStatus<<\"collect normal equations\"<<Log::endl;\n      collectNormalsBlocks(blockStart, normals.blockCount()-blockStart);\n      Parallel::reduceSum(lPl,      0, normalEquationInfo.comm);\n      Parallel::reduceSum(obsCount, 0, normalEquationInfo.comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble GnssProcessingStep::State::estimateSolution(const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger,\n                                                   const std::vector<Byte> &ambiguityTransmitters, const std::vector<Byte> &ambiguityReceivers,\n                                                   Bool computeResiduals, Bool computeWeights, Bool adjustSigma0, Double huber, Double huberPower)\n{\n  try\n  {\n    // setup normal equations\n    const Bool solveEpochParameters = !normalEquationInfo.keepEpochNormalsInMemory && (normalEquationInfo.blockInterval() < normalEquationInfo.blockCount());\n    buildNormals(FALSE/*constraintsOnly*/, solveEpochParameters);\n\n    // eliminate all other parameters from the ambiguity normals\n    // ---------------------------------------------------------\n    Parallel::barrier(normalEquationInfo.comm);\n    logStatus<<\"solve\"<<Log::endl;\n    const UInt blockStart = (solveEpochParameters) ? normalEquationInfo.blockInterval() : 0; // epoch parameters already eliminated?\n    const UInt blockCount = ((searchInteger) ? normalEquationInfo.blockAmbiguity() : normals.blockCount()) - blockStart;\n    regularizeNotUsedParameters(blockStart, normals.blockCount()-blockStart, normalEquationInfo.parameterNames());\n    normals.cholesky(TRUE/*timing*/, blockStart, blockCount, TRUE/*collect*/);\n    normals.triangularTransSolve(n, blockStart, blockCount, TRUE/*collect*/); // forward step\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(UInt z=blockStart; z<blockStart+blockCount; z++)\n      {\n        lPl(0)   -= quadsum(n.at(z)); // lPl = lPl - n1' N1^(-1) n1\n        obsCount -= normals.blockSize(z);\n      }\n\n    // resolve integer ambiguities\n    // ---------------------------\n    if(searchInteger)\n    {\n      logStatus<<\"Resolve integer ambiguities (may take a while)\"<<Log::endl;\n      Double sigmaFloat = gnss->ambiguityResolve(normalEquationInfo, normals, n, lPl(0), obsCount,\n                                                 ambiguityTransmitters, ambiguityReceivers, searchInteger);\n      logInfo<<\"  sigma(float) = \"<<sigmaFloat%\"%.2f\"s<<Log::endl;\n      logInfo<<\"  sigma(fixed) = \"<<std::sqrt(lPl(0)/obsCount)%\"%.2f\"s<<Log::endl;\n      Parallel::barrier(normalEquationInfo.comm);\n    } // if(parameterCountAmbiguities)\n\n    // Compute sigma\n    // -------------\n    if(Parallel::isMaster(normalEquationInfo.comm))\n    {\n      const Double sigma = Vce::standardDeviation(lPl(0), obsCount, huber, huberPower);\n      logInfo<<\"  sigma = \"<<sigma%\"%.2f\"s<<Log::endl;\n      if((sigma!=sigma) || (sigma<=0))\n        logWarning<<\"  Cannot compute sigma = sqrt(\"<<lPl(0)%\"%f/\"s<<obsCount<<\")\"<<Log::endl;\n    }\n\n    constexpr UInt monteCarloColumns = 100;\n    std::vector<Matrix> monteCarlo; // Monte Carlo Vector for redundancy computation\n\n    // ========================================================================================\n\n    // solve (Backward step)\n    // ---------------------\n    normals.triangularSolve(n, blockStart, normals.blockCount()-blockStart);\n    if(computeResiduals)\n    {\n      monteCarlo.resize(normals.blockCount());\n      for(UInt i=blockStart; i<normals.blockCount(); i++)\n        monteCarlo.at(i) = Matrix(normals.blockSize(i), monteCarloColumns);\n      if(Parallel::isMaster(normalEquationInfo.comm))\n        for(UInt i=blockStart; i<blockStart+blockCount; i++) // possible without resolved ambiguity parameters\n          monteCarlo.at(i) = Vce::monteCarlo(monteCarlo.at(i).rows(), monteCarlo.at(i).columns());\n      normals.triangularSolve(monteCarlo, blockStart, blockCount);\n    }\n\n    // ========================================================================================\n\n    // Reconstruct epoch parameters\n    // ----------------------------\n    if(solveEpochParameters)\n    {\n      logStatus<<\"Reconstruct epoch parameters\"<<Log::endl;\n      normals.eraseBlocks(blockStart, normals.blockCount()-blockStart); // free N12, N22\n\n      // broadcast n, Wz\n      // ---------------\n      for(UInt i=0; i<blockStart; i++)\n        n.at(i).setNull();\n      for(UInt i=blockStart; i<normalEquationInfo.blockCount(); i++)\n        Parallel::broadCast(n.at(i), 0, normalEquationInfo.comm);\n      if(computeResiduals)\n      {\n        for(UInt i=0; i<blockStart; i++)\n          monteCarlo.at(i) = Matrix(normalEquationInfo.blockSize(i), monteCarloColumns);\n        for(UInt i=blockStart; i<blockStart+blockCount; i++)\n          Parallel::broadCast(monteCarlo.at(i), 0, normalEquationInfo.comm);\n      }\n\n      // reconstruct N12\n      // ---------------\n      GnssDesignMatrix A(normalEquationInfo), B(normalEquationInfo);\n      UInt idLoop = 0;\n      Log::Timer timer(normalEquationInfo.idEpochs.size());;\n      for(UInt idEpoch : normalEquationInfo.idEpochs)\n      {\n        timer.loopStep(idLoop++);\n\n        // loop over all receivers\n        GnssObservationEquation eqn;\n        for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n          if(normalEquationInfo.estimateReceiver.at(idRecv) && gnss->receivers.at(idRecv)->isMyRank())\n            for(UInt idTrans=0; idTrans<gnss->receivers.at(idRecv)->idTransmitterSize(idEpoch); idTrans++)\n              if(gnss->basicObservationEquations(normalEquationInfo, idRecv, idTrans, idEpoch, eqn))\n              {\n                eqn.eliminateGroupParameters(!stations.at(idRecv).arOrder);\n                A.init(eqn.l.rows());\n                decorrelatedDesignMatrix(eqn, B, A);\n                A.transMult(eqn.l-A.mult(n, blockStart, normalEquationInfo.blockCount()-blockStart), n, 0, blockStart);\n                A.transMult(-A.mult(monteCarlo, blockStart, blockCount), monteCarlo, 0, blockStart);\n              }\n      } // for(idEpoch)\n      Parallel::barrier(normalEquationInfo.comm);\n      timer.loopEnd();\n\n      // collect\n      // -------\n      auto collect = [&](std::vector<Matrix> &n, UInt columns)\n      {\n        Matrix tmp(normalEquationInfo.blockIndex(blockStart), columns);\n        for(UInt i=0; i<blockStart; i++) // copy to one block (better performance of reduceSum)\n          if(normalEquationInfo.blockSize(i))\n            copy(n.at(i), tmp.row(normalEquationInfo.blockIndex(i), normalEquationInfo.blockSize(i)));\n        Parallel::reduceSum(tmp, 0, normalEquationInfo.comm);\n        if(Parallel::isMaster(normalEquationInfo.comm))\n          for(UInt i=0; i<blockStart; i++)\n            if(normalEquationInfo.blockSize(i))\n              copy(tmp.row(normalEquationInfo.blockIndex(i), normalEquationInfo.blockSize(i)), n.at(i));\n        if(!Parallel::isMaster(normalEquationInfo.comm))\n          for(UInt i=0; i<blockStart; i++)\n            n.at(i).setNull();\n      };\n\n      collect(n, 1);\n      if(computeResiduals)\n        collect(monteCarlo, monteCarloColumns);\n\n      // solve epoch (Forward step)\n      // --------------------------\n      normals.triangularTransSolve(n, 0, blockStart, FALSE);\n      if(computeResiduals)\n      {\n        normals.triangularTransSolve(monteCarlo, 0, blockStart, FALSE);\n        if(Parallel::isMaster(normalEquationInfo.comm))\n          for(UInt i=0; i<blockStart; i++)\n            axpy(1, Vce::monteCarlo(monteCarlo.at(i).rows(), monteCarlo.at(i).columns()), monteCarlo.at(i));\n      }\n\n      // solve epoch (Backward step)\n      // ---------------------------\n      normals.triangularSolve(n, 0, blockStart);\n      if(computeResiduals)\n        normals.triangularSolve(monteCarlo, 0, blockStart);\n    }\n\n    // ========================================================================================\n\n    // free memory\n    normals.initEmpty(normals.blockIndex(), normals.communicator());\n\n    // copy solution to one vector\n    // ---------------------------\n    Vector x;\n    if(Parallel::isMaster(normalEquationInfo.comm))\n    {\n      x = Vector(normalEquationInfo.parameterCount());\n      for(UInt i=0; i<normalEquationInfo.blockCount(); i++)\n        if(normalEquationInfo.blockSize(i))\n          copy(n.at(i), x.row(normalEquationInfo.blockIndex(i), normalEquationInfo.blockSize(i)));\n    }\n    n.clear();\n    n.shrink_to_fit();\n    Parallel::broadCast(x, 0, normalEquationInfo.comm);\n    if(!computeResiduals)\n    {\n      logInfo<<\"Parameter changes\"<<Log::endl;\n      return gnss->updateParameter(normalEquationInfo, x, Matrix());\n    }\n\n    // copy monte carlo to one vector\n    // ------------------------------\n    Matrix Wz;\n    if(Parallel::isMaster(normalEquationInfo.comm))\n    {\n      Wz = Matrix(normalEquationInfo.parameterCount(), monteCarloColumns);\n      for(UInt i=0; i<normalEquationInfo.blockCount(); i++)\n        if(normalEquationInfo.blockSize(i))\n          copy(monteCarlo.at(i), Wz.row(normalEquationInfo.blockIndex(i), normalEquationInfo.blockSize(i)));\n    }\n    monteCarlo.clear();\n    monteCarlo.shrink_to_fit();\n    Parallel::broadCast(Wz, 0, normalEquationInfo.comm);\n\n    // Residual tracking\n    // -----------------\n    Gnss::InfoParameterChange infoTec(\"tec\");\n    std::vector<GnssType>     typesResiduals = gnss->types(~(GnssType::PRN + GnssType::FREQ_NO));\n    std::vector<Gnss::InfoParameterChange> infosResiduals(typesResiduals.size(), Gnss::InfoParameterChange(\"mm\"));\n\n    Double minSTEC   =  std::numeric_limits<Double>::infinity();\n    Double maxSTEC   = -std::numeric_limits<Double>::infinity();\n    Double meanSTEC  = 0;\n    Double stdSTEC   = 0;\n    UInt   countSTEC = 0;\n\n    Parallel::barrier(normalEquationInfo.comm);\n    logStatus<<\"Compute residuals\"<<Log::endl;\n    GnssDesignMatrix A(normalEquationInfo);\n    UInt idLoop = 0;\n    Log::Timer timer(normalEquationInfo.idEpochs.size());\n    for(UInt idEpoch : normalEquationInfo.idEpochs)\n    {\n      timer.loopStep(idLoop++);\n\n      // loop over all receivers\n      for(UInt idRecv=0; idRecv<gnss->receivers.size(); idRecv++)\n        if(normalEquationInfo.estimateReceiver.at(idRecv) && gnss->receivers.at(idRecv)->isMyRank())\n        {\n          GnssObservationEquation eqn;\n          for(UInt idTrans=0; idTrans<gnss->receivers.at(idRecv)->idTransmitterSize(idEpoch); idTrans++)\n            if(gnss->basicObservationEquations(normalEquationInfo, idRecv, idTrans, idEpoch, eqn))\n            {\n              // setup observation equations\n              A.init(eqn.l.rows());\n              gnss->designMatrix(normalEquationInfo, eqn, A);\n              Vector We  = eqn.l - A.mult(x); // homogenized residuals\n              Matrix AWz = A.mult(Wz);        // redundancies\n\n              // estimate & reduce B parameters (ionosphere)\n              // -------------------------------------------\n              if(eqn.B.size())\n              {\n                // estimate and eliminate STEC parameter\n                Matrix B = eqn.B;\n                Vector tau = QR_decomposition(B);\n                QTransMult(B, tau, We);\n                triangularSolve(1., B.row(0, B.columns()), We.row(0, B.columns()));\n                eqn.receiver->observation(eqn.transmitter->idTrans(), eqn.idEpoch)->updateParameter(We.row(0,B.columns())); // ionosphere parameter\n\n                if((norm(eqn.sigma-eqn.sigma0) < 1e-8) && infoTec.update(We(0)))\n                  infoTec.info = \"STEC (\"+eqn.receiver->name()+\", \"+eqn.transmitter->name()+\", \"+eqn.timeRecv.dateTimeStr()+\")\";\n\n                // STEC statistics\n                const Double STEC = gnss->receivers.at(idRecv)->observation(idTrans, idEpoch)->dSTEC;\n                minSTEC   = std::min(STEC, minSTEC);\n                maxSTEC   = std::max(STEC, maxSTEC);\n                meanSTEC += STEC;\n                stdSTEC  += STEC*STEC;\n                countSTEC++;\n\n                // remove STEC from residuals\n                We.row(0, B.columns()).setNull();\n                QMult(B, tau, We);\n\n                // influence of B parameters = B(B'B)^(-1)B'\n                QTransMult(B, tau, AWz);\n                copy(Vce::monteCarlo(B.columns(), AWz.columns()), AWz.row(0, B.columns()));\n                QMult(B, tau, AWz);\n              }\n\n              // redundancies\n              // ------------\n              Vector r(We.rows());\n              for(UInt i=0; i<We.rows(); i++)\n                r(i) = 1. - quadsum(AWz.row(i));\n\n              // find max. residual (for statistics)\n              // -----------------------------------\n              if(norm(eqn.sigma-eqn.sigma0) < 1e-8) // without outlier\n                for(UInt k=0; k<eqn.types.size(); k++)\n                {\n                  const UInt idType = GnssType::index(typesResiduals, eqn.types.at(k));\n                  if(infosResiduals.at(idType).update(1e3*(We(k)*eqn.sigma(k) - gnss->receivers.at(idRecv)->observation(idTrans, idEpoch)->at(eqn.types.at(k)).residuals)))\n                    infosResiduals.at(idType).info = (typesResiduals.at(idType)+eqn.transmitter->PRN()).str()+\", (\"+ eqn.receiver->name()+\", \"+gnss->times.at(idEpoch).dateTimeStr()+\")\";\n                } // for(k)\n\n              gnss->receivers.at(idRecv)->observation(idTrans, idEpoch)->setHomogenizedResiduals(eqn.types, We, r);\n            } // for(idTrans)\n        } // for(idRecv)\n    } // for(idEpoch)\n    Parallel::barrier(normalEquationInfo.comm);\n    timer.loopEnd();\n\n    // new weights\n    // -----------\n    if(computeWeights || adjustSigma0)\n    {\n      if(computeWeights) logStatus<<\"Downweight outliers\"<<Log::endl;\n      if(adjustSigma0)   logStatus<<\"Estimate variance factors\"<<Log::endl;\n      for(auto recv : gnss->receivers)\n        if(normalEquationInfo.estimateReceiver.at(recv->idRecv()) && recv->isMyRank())\n          for(UInt iter=0; iter<10; iter++)\n          {\n            // --- lambda -------------------------------------\n            auto getResiduals = [&](UInt idEpoch, UInt idTrans, Bool useSigma0, std::vector<GnssType> &types, std::vector<Double> &ePe, std::vector<Double> &redundancy)\n            {\n              GnssObservation &obs = *(recv->observation(idTrans, idEpoch));\n              for(UInt idType=0; idType<obs.size(); idType++)\n                if((obs.at(idType).sigma0 > 0) && (obs.at(idType).redundancy > 0))\n                {\n                  UInt idx = GnssType::index(types, obs.at(idType).type);\n                  if(idx == NULLINDEX) // new type?\n                  {\n                    idx = types.size();\n                    if(obs.at(idType).type == GnssType::PHASE)\n                      types.push_back(obs.at(idType).type & (GnssType::TYPE + GnssType::SYSTEM)); // only PHASE and System\n                    else\n                      types.push_back(obs.at(idType).type & (GnssType::TYPE + GnssType::FREQUENCY + GnssType::ATTRIBUTE + GnssType::SYSTEM));\n                    ePe.push_back(0);\n                    redundancy.push_back(0);\n                  }\n                  ePe.at(idx)        += std::pow(obs.at(idType).residuals/(useSigma0 ? obs.at(idType).sigma0 : obs.at(idType).sigma), 2);\n                  redundancy.at(idx) += obs.at(idType).redundancy;\n                }\n            };\n            // ------------------------------------------------\n\n            if(adjustSigma0)\n            {\n              std::vector<GnssType> types;\n              std::vector<Double>   ePe, redundancy;\n              for(UInt idEpoch : normalEquationInfo.idEpochs)\n                if(recv->useable(idEpoch))\n                  for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n                    if(recv->observation(idTrans, idEpoch))\n                      getResiduals(idEpoch, idTrans, FALSE/*useSigma0*/, types, ePe, redundancy);\n\n              std::vector<Double> factors(types.size(), 1.);\n              for(UInt idType=0; idType<types.size(); idType++)\n                if(redundancy.at(idType) > 3)\n                  factors.at(idType) = Vce::standardDeviation(ePe.at(idType), redundancy.at(idType), huber, huberPower);\n\n              // adjust sigma and sigma0\n              UInt idx;\n              for(UInt idEpoch=0; idEpoch<recv->idEpochSize(); idEpoch++)\n                for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n                  if(recv->observation(idTrans, idEpoch))\n                  {\n                    GnssObservation &obs = *(recv->observation(idTrans, idEpoch));\n                    for(UInt idType=0; idType<obs.size(); idType++)\n                      if((obs.at(idType).sigma0 > 0) && obs.at(idType).type.isInList(types, idx))\n                      {\n                        obs.at(idType).sigma0 *= factors.at(idx);\n                        obs.at(idType).sigma  *= factors.at(idx);\n                      } // for(idType)\n                  } // for(idTrans, idEpoch)\n\n              // apply old factors to store total factor\n              for(UInt idType=0; idType<types.size(); idType++)\n                if(types.at(idType).isInList(stations.at(recv->idRecv()).sigmaTypes, idx))\n                  factors.at(idType) *= stations.at(recv->idRecv()).sigmaFactors.at(idx);\n              stations.at(recv->idRecv()).sigmaTypes   = std::move(types);\n              stations.at(recv->idRecv()).sigmaFactors = std::move(factors);\n            } // if(adjustSigma0)\n\n            if(computeWeights)\n            {\n              for(UInt idEpoch : normalEquationInfo.idEpochs)\n                if(recv->useable(idEpoch))\n                  for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n                    if(recv->observation(idTrans, idEpoch))\n                    {\n                      std::vector<GnssType> types;\n                      std::vector<Double> ePe, redundancy;\n                      getResiduals(idEpoch, idTrans, TRUE/*useSigma0*/, types, ePe, redundancy);\n\n                      Vector factors(types.size(), 1.);\n                      for(UInt i=0; i<types.size(); i++)\n                        if(redundancy.at(i) > 0.1)\n                        {\n                          const Double s = std::sqrt(ePe.at(i)/redundancy.at(i));\n                          factors(i) = ((s > huber) ? std::pow(s/huber, huberPower) : 1.);\n                        }\n\n                      GnssObservation &obs = *(recv->observation(idTrans, idEpoch));\n                      UInt idx;\n                      for(UInt idType=0; idType<obs.size(); idType++)\n                        if(obs.at(idType).type.isInList(types, idx))\n                          obs.at(idType).sigma = obs.at(idType).sigma0 * factors(idx);\n                    }\n            } // if(computeWeights)\n\n            if(!(computeWeights && adjustSigma0))\n              break; // iteration not needed\n          } // for(recv, iter)\n    } // if(computeWeights || adjustSigma0)\n\n    // residual analysis\n    // -----------------\n    std::vector<GnssType> types = typesResiduals;\n    std::vector<Double>   ePe(types.size(), 0), redundancy(types.size(), 0);\n    std::vector<UInt>     obsCount(types.size(), 0), outlierCount(types.size(), 0);\n    residualsStatistics(NULLINDEX/*idRecv*/, NULLINDEX/*idTrans*/, types, ePe, redundancy, obsCount, outlierCount);\n    if(Parallel::isMaster(normalEquationInfo.comm))\n      for(UInt i=0; i<types.size(); i++)\n        if(obsCount.at(i))\n        {\n          logInfo<<\"  \"<<types.at(i).str()\n                <<\": sigma0 = \"    <<Vce::standardDeviation(ePe.at(i), redundancy.at(i), huber, huberPower)%\"%4.2f\"s\n                <<\", redundancy = \"<<(redundancy.at(i)/obsCount.at(i))%\"%4.2f\"s\n                <<\", count = \"     <<obsCount.at(i)%\"%7i\"s\n                <<\", outliers = \"  <<outlierCount.at(i)%\"%6i\"s<<\" (\"<<(100.*outlierCount.at(i)/obsCount.at(i))%\"%4.2f\"s<<\" %)\"\n                <<Log::endl;\n        }\n    logInfo<<\"Residuals changes (without outliers)\"<<Log::endl;\n    Double maxChange = 0;\n    for(auto &info : infosResiduals)\n      info.synchronizeAndPrint(normalEquationInfo.comm, 1e-3, maxChange);\n\n    logInfo<<\"Parameter changes\"<<Log::endl;\n\n    // STEC analysis\n    // -------------\n    Parallel::reduceSum(countSTEC, 0, normalEquationInfo.comm);\n    Parallel::broadCast(countSTEC, 0, normalEquationInfo.comm);\n    if(countSTEC)\n    {\n      Parallel::reduceMin(minSTEC,   0, normalEquationInfo.comm);\n      Parallel::reduceMax(maxSTEC,   0, normalEquationInfo.comm);\n      Parallel::reduceSum(meanSTEC,  0, normalEquationInfo.comm);\n      Parallel::reduceSum(stdSTEC,   0, normalEquationInfo.comm);\n      stdSTEC   = std::sqrt((stdSTEC-meanSTEC*meanSTEC/countSTEC)/(countSTEC-1));\n      meanSTEC /= countSTEC;\n      std::string infoTecStr = \" (total: \"+meanSTEC%\"%.2f +- \"s+stdSTEC%\"%.2f [\"s+minSTEC%\"%.2f -- \"s+maxSTEC%\"%.2f])\"s;\n      Parallel::broadCast(infoTecStr, 0, normalEquationInfo.comm);\n      infoTec.info += infoTecStr;\n      infoTec.synchronizeAndPrint(normalEquationInfo.comm, 0, maxChange);\n    }\n\n    return gnss->updateParameter(normalEquationInfo, x, Wz);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssProcessingStep::State::residualsStatistics(UInt idRecv, UInt idTrans,\n                                                    std::vector<GnssType> &types, std::vector<Double> &ePe, std::vector<Double> &redundancy,\n                                                    std::vector<UInt> &obsCount, std::vector<UInt> &outlierCount)\n{\n  try\n  {\n    const UInt idTransStart = ((idTrans!=NULLINDEX) ? idTrans : 0);\n    const UInt idTransEnd   = ((idTrans!=NULLINDEX) ? idTrans : MAX_UINT);\n    for(auto recv : gnss->receivers)\n      if(normalEquationInfo.estimateReceiver.at(recv->idRecv()) && recv->isMyRank() && ((idRecv == NULLINDEX) || (idRecv == recv->idRecv())))\n        for(UInt idEpoch : normalEquationInfo.idEpochs)\n          if(recv->useable(idEpoch))\n            for(UInt idTrans=idTransStart; (idTrans<=idTransEnd) && (idTrans<recv->idTransmitterSize(idEpoch)); idTrans++)\n              if(recv->observation(idTrans, idEpoch))\n              {\n                const GnssObservation &obs = *recv->observation(idTrans, idEpoch);\n                UInt idx;\n                for(UInt idType=0; idType<obs.size(); idType++)\n                  if((obs.at(idType).sigma0 > 0) && (obs.at(idType).type.isInList(types, idx)))\n                  {\n                    ePe.at(idx)        += std::pow(obs.at(idType).residuals/obs.at(idType).sigma, 2);\n                    redundancy.at(idx) += obs.at(idType).redundancy;\n                    obsCount.at(idx)++;\n                    if(obs.at(idType).sigma > obs.at(idType).sigma0)\n                      outlierCount.at(idx)++;\n                  }\n              } // for(idTrans, idEpoch)\n\n    for(UInt i=0; i<types.size(); i++)\n    {\n      Parallel::reduceSum(ePe.at(i),          0, normalEquationInfo.comm);\n      Parallel::reduceSum(redundancy.at(i),   0, normalEquationInfo.comm);\n      Parallel::reduceSum(obsCount.at(i),     0, normalEquationInfo.comm);\n      Parallel::reduceSum(outlierCount.at(i), 0, normalEquationInfo.comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStep.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStep.h\n*\n* @brief Processing steps for GNSS normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEP__\n#define __GROOPS_GNSSPROCESSINGSTEP__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStep = R\"(\n\\section{GnssProcessingStep}\\label{gnssProcessingStepType}\nProcessing step in \\program{GnssProcessing}.\n\nProcessing steps enable a dynamic definition of the consecutive steps performed during any kind of GNSS processing.\nThe most common steps are \\configClass{estimate}{gnssProcessingStepType:estimate}, which performs an iterative least\nsquares adjustment, and \\configClass{writeResults}{gnssProcessingStepType:writeResults}, which writes all output files\ndefined in \\program{GnssProcessing} and is usually the last step.\nSome steps such as \\configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations},\n\\configClass{selectEpochs}{gnssProcessingStepType:selectEpochs},\n\\configClass{selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure}, and\n\\configClass{selectReceivers}{gnssProcessingStepType:selectReceivers} affect all subsequent steps.\nIn case these steps are used within a \\configClass{group}{gnssProcessingStepType:group} or\n\\configClass{forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately} step,\nthey only affect the steps within this level.\n\nFor usage examples see cookbooks on \\reference{GNSS satellite orbit determination and network analysis}{cookbook.gnssNetwork:processing}\nor \\reference{Kinematic orbit determination of LEO satellites}{cookbook.kinematicOrbit}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"gnss/gnss.h\"\n\n/**\n* @defgroup gnssProcessingStepGroup GnssProcessingStep\n* @brief Processing steps in @ref GnssProcessing.\n* @ingroup gnssGroup\n* The interface is given by @ref GnssProcessingStep. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Gnss;\nclass GnssProcessingStep;\nclass GnssProcessingStepBase;\ntypedef std::shared_ptr<GnssProcessingStep> GnssProcessingStepPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of receivers.\n* An instance of this class can be created by @ref readConfig. */\nclass GnssProcessingStep\n{\n  std::vector<GnssProcessingStepBase*> bases;\n\npublic:\n  class State\n  {\n  public:\n    class StationStatistics\n    {\n    public:\n      std::vector<GnssType> sigmaTypes;\n      std::vector<Double>   sigmaFactors; // for each type\n      UInt                  arOrder;\n      std::vector<GnssType> arTypes;\n      std::vector<std::vector<std::vector<Double>>> arProcesses; // for each type, order, order\n\n      StationStatistics() : arOrder(0) {}\n    };\n\n    GnssPtr                        gnss;\n    GnssNormalEquationInfo         normalEquationInfo;\n    Bool                           changedNormalEquationInfo;\n    MatrixDistributed              normals;\n    std::vector<Matrix>            n;        // at master (after solve)\n    Vector                         lPl;      // at master (after solve)\n    UInt                           obsCount; // at master (after solve)\n    std::vector<StationStatistics> stations;\n\n    /** @brief Constructor. */\n    State(GnssPtr gnss, Parallel::CommunicatorPtr comm);\n\n    void regularizeNotUsedParameters(UInt blockStart, UInt blockCount, const std::vector<ParameterName> &parameterNames);\n    void collectNormalsBlocks       (UInt blockStart, UInt blockCount);\n    void decorrelatedDesignMatrix   (GnssObservationEquation &eqn, GnssDesignMatrix &B, GnssDesignMatrix &A);\n    void buildNormals               (Bool constraintsOnly, Bool solveEpochParameters);\n    Double estimateSolution         (const std::function<Vector(const_MatrixSliceRef xFloat, MatrixSliceRef W, const_MatrixSliceRef d, Vector &xInt, Double &sigma)> &searchInteger,\n                                     const std::vector<Byte> &ambiguityTransmitters, const std::vector<Byte> &ambiguityReceivers,\n                                     Bool computeResiduals,  Bool computeWeights, Bool adjustSigma0, Double huber, Double huberPower);\n    void residualsStatistics        (UInt idRecv, UInt idTrans,\n                                     std::vector<GnssType> &types, std::vector<Double> &ePe, std::vector<Double> &redundancy,\n                                     std::vector<UInt> &obsCount, std::vector<UInt> &outlierCount);\n  };\n\n  /** @brief Constructor from config. */\n  GnssProcessingStep(Config &config, const std::string &name);\n\n  /// Destructor.\n ~GnssProcessingStep();\n\n  /** @brief Perform the processing steps. */\n  void process(State &state);\n\n  /** @brief creates a derived instance of this class. */\n  static GnssProcessingStepPtr create(Config &config, const std::string &name) {return GnssProcessingStepPtr(new GnssProcessingStep(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class GnssProcessingStep.\n* Search for a node with @a name in the Config node.\n* if @a name is not found, the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates GnssProcessingStep */\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssProcessingStepPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass GnssProcessingStepBase\n{\npublic:\n  virtual ~GnssProcessingStepBase() {}\n\n  /** @brief Execute the processing step. */\n  virtual void process(GnssProcessingStep::State &state) = 0;\n  virtual Bool expectInitializedParameters() const {return TRUE;}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepComputeCovarianceMatrix.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepComputeCovarianceMatrix.h\n*\n* @brief GNSS processing step: ComputeCovarianceMatrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPCOMPUTECOVARIANCEMATRIX__\n#define __GROOPS_GNSSPROCESSINGSTEPCOMPUTECOVARIANCEMATRIX__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepComputeCovarianceMatrix = R\"(\n\\subsection{ComputeCovarianceMatrix}\\label{gnssProcessingStepType:computeCovarianceMatrix}\nAccumulates the normal equations and computes the covariance matrix as inverse of the normal matrix.\nIt is not the full inverse but only the elements which are set in the normal matrix\n(see  \\configClass{gnssProcessingStep:selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure})\nare computed. The matrix is passed to the \\configClass{parametrizations}{gnssParametrizationType}.\nOnly used in \\configClass{parametrizations:kinematicPositions}{gnssParametrizationType:kinematicPositions}\nto get the epoch-wise covariance information at the moment.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: ComputeCovarianceMatrix.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepComputeCovarianceMatrix : public GnssProcessingStepBase\n{\npublic:\n  GnssProcessingStepComputeCovarianceMatrix(Config &/*config*/) {}\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline void GnssProcessingStepComputeCovarianceMatrix::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== compute covariance matrix ===============================\"<<Log::endl;\n    state.buildNormals(FALSE/*constraintsOnly*/, FALSE/*solveEpochParameters*/);\n    logStatus<<\"cholesky\"<<Log::endl;\n    state.normals.cholesky(TRUE/*timing*/);\n    logStatus<<\"sparse inverse\"<<Log::endl;\n    state.normals.cholesky2SparseInverse();\n    state.gnss->updateCovariance(state.normalEquationInfo, state.normals);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepDisableTransmitterShadowEpochs.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepDisableTransmitterShadowEpochs.h\n*\n* @brief GNSS processing step: DisableTransmitterShadowEpochs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPDISABLETRANSMITTERSHADOWEPOCHS__\n#define __GROOPS_GNSSPROCESSINGSTEPDISABLETRANSMITTERSHADOWEPOCHS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepDisableTransmitterShadowEpochs = R\"(\n\\subsection{DisableTransmitterShadowEpochs}\\label{gnssProcessingStepType:disableTransmitterShadowEpochs}\nDisable transmitter epochs during eclipse.\nWith proper attitude modeling (see \\program{SimulateStarCameraGnss}) this is usually not necessary.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"base/kepler.h\"\n#include \"classes/eclipse/eclipse.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: DisableTransmitterShadowEpochs.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepDisableTransmitterShadowEpochs : public GnssProcessingStepBase\n{\n  PlatformSelectorPtr selectTransmitters;\n  Bool                disableShadowEpochs, disablePostShadowEpochs;\n  EphemeridesPtr      ephemerides;\n  EclipsePtr          eclipse;\n\npublic:\n  GnssProcessingStepDisableTransmitterShadowEpochs(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline GnssProcessingStepDisableTransmitterShadowEpochs::GnssProcessingStepDisableTransmitterShadowEpochs(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectTransmitters\",              selectTransmitters,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"disableShadowEpochs\",             disableShadowEpochs,     Config::DEFAULT,  \"1\", \"disable epochs if satellite is in Earth's/Moon's shadow\");\n    readConfig(config, \"disablePostShadowRecoveryEpochs\", disablePostShadowEpochs, Config::DEFAULT,  \"1\", \"disable epochs if satellite is in post-shadow recovery maneuver for GPS block IIA\");\n    readConfig(config, \"ephemerides\",                     ephemerides,             Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"eclipse\",                         eclipse,                 Config::MUSTSET,  \"\",  \"eclipse model used to determine if a satellite is in Earth's shadow\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepDisableTransmitterShadowEpochs::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== disable transmitter epochs in eclipse ===================\"<<Log::endl;\n    if(state.normalEquationInfo.isEachReceiverSeparately)\n    {\n      logWarning<<\"DisableTransmitterShadowEpochs is not allowed in single receiver loop\"<<Log::endl;\n      return;\n    }\n\n    UInt countEpochs = 0;\n    auto selectedTransmitters = state.gnss->selectTransmitters(selectTransmitters);\n    for(UInt idTrans=0; idTrans<state.gnss->transmitters.size(); idTrans++)\n      if(selectedTransmitters.at(idTrans) && state.gnss->transmitters.at(idTrans)->useable())\n      {\n        auto trans = state.gnss->transmitters.at(idTrans);\n\n        // 30 minute post-shadow recovery time for block IIA satellites\n        Time recoveryTime;\n        if(trans->platform.findEquipment<PlatformGnssAntenna>(state.gnss->times.at(0))->name.find(std::string(\"BLOCK IIA\")) != std::string::npos)\n          recoveryTime = seconds2time(30*60);\n\n        // Look for a potential shadow exit before the start of the interval that would result in the\n        // satellite already performing a post-shadow recovery maneuver at the start of the interval\n        Time timeShadowExit;\n        if(disablePostShadowEpochs && recoveryTime.seconds() > 0)\n        {\n          Kepler kepler(state.gnss->times.at(0), trans->positionCoM(state.gnss->times.at(0)), trans->velocity(state.gnss->times.at(0)));\n          for(UInt i=0; i<recoveryTime.seconds()/60; i++)\n          {\n            const Time time = state.gnss->times.at(0) - seconds2time(i*60.);\n            if(eclipse->factor(time, kepler.position(time), ephemerides) < 0.5)\n            {\n              timeShadowExit = time;\n              break;\n            }\n          }\n        }\n\n        Double factorPreviousEpoch = 1.0;\n        for(UInt idEpoch=0; idEpoch<state.gnss->times.size(); idEpoch++)\n          if(trans->useable(idEpoch))\n          {\n            const Double factor = eclipse->factor(state.gnss->times.at(idEpoch), trans->positionCoM(state.gnss->times.at(idEpoch)), ephemerides);\n            if((factorPreviousEpoch < 0.5) && (factor >= 0.5))\n              timeShadowExit = state.gnss->times.at(idEpoch);\n\n            // set satellite unusable during shadow crossing and post-shadow recovery maneuver\n            if((disableShadowEpochs && factor < 0.5) || (disablePostShadowEpochs && state.gnss->times.at(idEpoch) < timeShadowExit+recoveryTime))\n            {\n              trans->disable(idEpoch, \"during shadow crossing and post-shadow recovery maneuver\");\n              for(UInt idEpoch=0; idEpoch<state.gnss->times.size(); idEpoch++)\n                for(const auto &recv : state.gnss->receivers)\n                  if(recv->isMyRank() && recv->observation(trans->idTrans(), idEpoch))\n                    recv->deleteObservation(trans->idTrans(), idEpoch);\n              countEpochs++;\n            }\n\n            factorPreviousEpoch = factor;\n          } // for(idEpoch)\n      }\n\n    if(countEpochs)\n    {\n      state.gnss->synchronizeTransceivers(state.normalEquationInfo.comm);\n      state.changedNormalEquationInfo = TRUE;\n    }\n    logInfo<<\"  \"<<countEpochs<<\" disabled transmitter epochs\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepEstimate.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepEstimate.h\n*\n* @brief GNSS processing step: Estimate.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPESTIMATE__\n#define __GROOPS_GNSSPROCESSINGSTEPESTIMATE__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepEstimate = R\"(\n\\subsection{Estimate}\\label{gnssProcessingStepType:estimate}\nIterative non-linear least squares adjustment.\nIn every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters.\nThe estimated parameters serve as a priori values in the next iteration and the following processing steps.\nIterates until either every single parameter update (converted to an influence in meters)\nis below a \\config{convergenceThreshold} or \\config{maxIterationCount} is reached.\n\nWith \\config{computeResiduals} the observation equations are computed\nagain after each update to compute the observation residuals.\n\nThe overall standard deviation of a single observation used for the weighting\nis composed of several factors\n\\begin{equation}\n  \\hat{\\sigma}_i = \\hat{\\sigma}_i^{huber} \\hat{\\sigma}_{[\\tau\\nu a]}^{recv} \\sigma_{[\\tau\\nu a]}^{recv}(E,A),\n\\end{equation}\nwhere $[\\tau\\nu a]$ is the signal type, the azimuth and elevation dependent $\\sigma_{[\\tau\\nu a]}^{recv}(E,A)$ is given by\n\\configFile{receiver:inputfileAccuracyDefinition}{gnssAntennaDefinition} and the other factors are\nestimated iteratively from the residuals.\n\nWith \\config{computeWeights} a standardized variance $\\hat{s}_i^2$\nfor each residual $\\hat{\\epsilon}_i$ is computed\n\\begin{equation}\n  \\hat{s}_i^2 = \\frac{1}{\\hat{\\sigma}_{[\\tau\\nu a]}^{recv} \\sigma_{[\\tau\\nu a]}^{recv}(E,A)}\\frac{\\hat{\\epsilon}_i^2}{r_i}\n  \\qquad\\text{with}\\qquad\n  r_i = \\left(\\M A\\left(\\M A^T\\M A\\right)^{-1}\\M A^T\\right)_{ii}\n\\end{equation}\ntaking the redundancy $r_i$ into account. If $\\hat{s}_i$ is above a threshold \\config{huber}\nthe observation gets a higher standard deviation used for weighting according to\n\\begin{equation}\n  \\hat{\\sigma}_i^{huber} =\n  \\left\\{ \\begin{array}{ll}\n    1                              & s < huber,\\\\\n    (\\hat{s}_i/huber)^{huberPower} & s \\ge huber\n  \\end{array} \\right.,\n\\end{equation}\nsimilar to \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\nWith \\config{adjustSigma0} individual variance factors can be computed\nfor each station and all phases of a system and each code observation \\reference{type}{gnssType}\n(e.g. for each \\verb|L**G|, \\verb|L**E|, \\verb|C1CG|, \\verb|C2WG|, \\verb|C1CE|, \\ldots)\nseparately\n\\begin{equation}\n  \\hat{\\sigma}_{[\\tau\\nu a]}^{recv} = \\sqrt{\\frac{\\hat{\\M\\epsilon}^T\\M P\\hat{\\M\\epsilon}}{r}}.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: Estimate.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepEstimate : public GnssProcessingStepBase\n{\n  Bool   computeResiduals, adjustSigma0, computeWeights;\n  Double huber, huberPower;\n  Double convergenceThreshold;\n  UInt   iterCount;\n\npublic:\n  GnssProcessingStepEstimate(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepEstimate::GnssProcessingStepEstimate(Config &config)\n{\n  try\n  {\n    readConfig(config, \"computeResiduals\",     computeResiduals,     Config::DEFAULT, \"1\",    \"\");\n    readConfig(config, \"adjustSigma0\",         adjustSigma0,         Config::DEFAULT, \"1\",    \"adjust sigma0 by scale factor (per receiver and type)\");\n    readConfig(config, \"computeWeights\",       computeWeights,       Config::DEFAULT, \"1\",    \"downweight outliers\");\n    readConfig(config, \"huber\",                huber,                Config::DEFAULT, \"2.5\",  \"residuals > huber*sigma0 are downweighted\");\n    readConfig(config, \"huberPower\",           huberPower,           Config::DEFAULT, \"1.5\",  \"residuals > huber: sigma=(e/huber)^huberPower*sigma0\");\n    readConfig(config, \"convergenceThreshold\", convergenceThreshold, Config::DEFAULT, \"0.01\", \"[m] stop iteration once full convergence is reached\");\n    readConfig(config, \"maxIterationCount\",    iterCount,            Config::DEFAULT, \"3\",    \"maximum number of iterations\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepEstimate::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== estimate ================================================\"<<Log::endl;\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      logStatus<<iter+1<<\". iteration  --------------------------\"<<Log::endl;\n      if(convergenceThreshold > state.estimateSolution(nullptr/*resolveAmbiguities*/, {}, {}, computeResiduals, computeWeights, adjustSigma0, huber, huberPower))\n        break;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepForEachReceiverSeparately.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepForEachReceiverSeparately.h\n*\n* @brief GNSS processing step: ForEachReceiverSeparately.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPFOREACHRECEIVERSEPARATELY__\n#define __GROOPS_GNSSPROCESSINGSTEPFOREACHRECEIVERSEPARATELY__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepForEachReceiverSeparately = R\"(\n\\subsection{ForEachReceiverSeparately}\\label{gnssProcessingStepType:forEachReceiverSeparately}\nPerform these processing steps for each \\configClass{selectReceivers}{platformSelectorType} separately.\nAll non-receiver-related parameters parameters are disabled in these processing steps.\n\nThis step can be used for individual precise point positioning (PPP) of all stations.\nDuring \\reference{GNSS satellite orbit determination and network analysis}{cookbook.gnssNetwork:processing} this step is used after the\ninitial processing of the core network to process all other stations individually. In that case provide the same station list as\n\\configFile{inputfileExcludeStationList}{stringList} in this step that was used as \\configFile{inputfileStationList}{stringList} in the\n\\configClass{selectReceivers}{gnssProcessingStepType:selectReceivers} step where the core network was selected.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: ForEachReceiverSeparately.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepForEachReceiverSeparately : public GnssProcessingStepBase\n{\n  PlatformSelectorPtr selectReceivers;\n  std::string         variableReceiver;\n  Config              configProcessingSteps;\n\npublic:\n  GnssProcessingStepForEachReceiverSeparately(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline GnssProcessingStepForEachReceiverSeparately::GnssProcessingStepForEachReceiverSeparately(Config &config)\n{\n  try\n  {\n    GnssProcessingStepPtr processingSteps;\n\n    readConfig(config, \"selectReceivers\",  selectReceivers,  Config::MUSTSET,  \"\",        \"\");\n    readConfig(config, \"variableReceiver\", variableReceiver, Config::OPTIONAL, \"station\", \"variable is set for each receiver\");\n    readConfigLater(config, \"processingStep\", processingSteps, configProcessingSteps, Config::MUSTSET, \"\", \"steps are processed consecutively\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepForEachReceiverSeparately::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    Parallel::barrier(state.normalEquationInfo.comm);\n    logStatus<<\"=== for each receiver separately ============================\"<<Log::endl;\n    auto estimateSingleReceiver = state.gnss->selectReceivers(selectReceivers);\n    for(auto recv : state.gnss->receivers)\n      if(!recv->useable())\n        estimateSingleReceiver.at(recv->idRecv()) = FALSE;\n    logInfo<<\"  \"<<std::count(estimateSingleReceiver.begin(), estimateSingleReceiver.end(), TRUE)<<\" receivers selected\"<<Log::endl;\n    if(Parallel::size(state.normalEquationInfo.comm) > 1)\n      logInfo<<\"  Only results of a subset of stations are displayed in the following\"<<Log::endl;\n\n    // Save old state\n    auto normalEquationInfoOld = state.normalEquationInfo;\n\n    // self comm\n    state.normalEquationInfo.comm = Parallel::createCommunicator({Parallel::myRank(state.normalEquationInfo.comm)}, state.normalEquationInfo.comm);\n    state.normalEquationInfo.isEachReceiverSeparately = TRUE;\n\n    for(UInt idRecv=0; idRecv<state.gnss->receivers.size(); idRecv++)\n      if(estimateSingleReceiver.at(idRecv) && state.gnss->receivers.at(idRecv)->isMyRank())\n      {\n        logStatus<<\"=== select single receiver (\"<<state.gnss->receivers.at(idRecv)->name()<<\") ===========================\"<<Log::endl;\n        VariableList varList;\n        varList.setVariable(variableReceiver, state.gnss->receivers.at(idRecv)->name());\n\n        std::fill(state.normalEquationInfo.estimateReceiver.begin(), state.normalEquationInfo.estimateReceiver.end(), FALSE);\n        state.normalEquationInfo.estimateReceiver.at(idRecv) = TRUE;\n        state.changedNormalEquationInfo = TRUE;\n\n        try\n        {\n          GnssProcessingStepPtr processingSteps;\n          configProcessingSteps.read(processingSteps, varList);\n          processingSteps->process(state);\n        }\n        catch(std::exception &e)\n        {\n          logError<<state.gnss->receivers.at(idRecv)->name()<<\": disabled due to exception in single receiver loop:\"<<Log::endl;\n          logError<<e.what()<<Log::endl;\n          state.gnss->receivers.at(idRecv)->disable(e.what());\n        }\n      } // for(idRecv)\n\n    // restore old state\n    std::swap(state.normalEquationInfo, normalEquationInfoOld);\n    state.changedNormalEquationInfo = TRUE;\n\n    // synchronize transceivers\n    state.gnss->synchronizeTransceivers(state.normalEquationInfo.comm);\n\n    Parallel::barrier(state.normalEquationInfo.comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepGroup.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepGroup.h\n*\n* @brief GNSS processing step: Group.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPGROUP__\n#define __GROOPS_GNSSPROCESSINGSTEPGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepGroup = R\"(\n\\subsection{Group}\\label{gnssProcessingStepType:group}\nPerform these processing steps. This step can be used to structure complex processing flows.\nThe \\configClass{processingStep}{gnssProcessingStepType}s that affect the following steps\n(those beginning with Select) only have an effect until the end of the group.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: Group.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepGroup : public GnssProcessingStepBase\n{\n  GnssProcessingStepPtr processingSteps;\n\npublic:\n  GnssProcessingStepGroup(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline GnssProcessingStepGroup::GnssProcessingStepGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"processingStep\", processingSteps, Config::MUSTSET, \"\", \"steps are processed consecutively\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepGroup::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== process group ===========================================\"<<Log::endl;\n    GnssNormalEquationInfo normalEquationInfoOld = state.normalEquationInfo;\n    processingSteps->process(state);\n    std::swap(state.normalEquationInfo, normalEquationInfoOld);\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepPrintResidualStatistics.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepPrintResidualStatistics.h\n*\n* @brief GNSS processing step: PrintResidualStatistics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPPRINTRESIDUALSTATISTICS__\n#define __GROOPS_GNSSPROCESSINGSTEPPRINTRESIDUALSTATISTICS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepPrintResidualStatistics = R\"(\n\\subsection{PrintResidualStatistics}\\label{gnssProcessingStepType:printResidualStatistics}\nPrint residual statistics.\n\\begin{verbatim}\n  areq: C1CG**: factor =  0.64, sigma0 = 1.00, count =  2748, outliers =    48 (1.75 \\%)\n  areq: C1WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    43 (1.56 \\%)\n  areq: C2WG**: factor =  0.50, sigma0 = 1.00, count =  2748, outliers =    59 (2.15 \\%)\n  areq: C5XG**: factor =  0.46, sigma0 = 1.00, count =  1279, outliers =    23 (1.80 \\%)\n  areq: L1CG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 \\%)\n  areq: L1WG**: factor =  0.86, sigma0 = 1.02, count =  2748, outliers =    40 (1.46 \\%)\n  areq: L2WG**: factor =  0.86, sigma0 = 0.96, count =  2748, outliers =    40 (1.46 \\%)\n  areq: L5XG**: factor =  0.86, sigma0 = 1.30, count =  1279, outliers =    14 (1.09 \\%)\n  areq: C1PR**: factor =  0.48, sigma0 = 1.00, count =  1713, outliers =    53 (3.09 \\%)\n  areq: C2PR**: factor =  0.55, sigma0 = 1.00, count =  1713, outliers =    51 (2.98 \\%)\n  areq: L1PR**: factor =  0.85, sigma0 = 1.09, count =  1713, outliers =    29 (1.69 \\%)\n  areq: L2PR**: factor =  0.85, sigma0 = 0.88, count =  1713, outliers =    29 (1.69 \\%)\n  areq: C1XE**: factor =  0.44, sigma0 = 1.00, count =  1264, outliers =    21 (1.66 \\%)\n  areq: C5XE**: factor =  0.33, sigma0 = 1.00, count =  1264, outliers =    27 (2.14 \\%)\n  areq: C7XE**: factor =  0.28, sigma0 = 1.00, count =  1264, outliers =    41 (3.24 \\%)\n  areq: L1XE**: factor =  0.82, sigma0 = 1.14, count =  1264, outliers =    15 (1.19 \\%)\n  areq: L5XE**: factor =  0.82, sigma0 = 0.84, count =  1264, outliers =    15 (1.19 \\%)\n  areq: L7XE**: factor =  0.82, sigma0 = 0.94, count =  1264, outliers =    15 (1.19 \\%)\n  badg: C1CG**: factor =  1.25, sigma0 = 1.00, count =  2564, outliers =    47 (1.83 \\%)\n  ...\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: PrintResidualStatistics.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepPrintResidualStatistics : public GnssProcessingStepBase\n{\npublic:\n  GnssProcessingStepPrintResidualStatistics(Config &/*config*/) {}\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline void GnssProcessingStepPrintResidualStatistics::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== print residual statistics  ==============================\"<<Log::endl;\n    for(UInt idRecv=0; idRecv<state.gnss->receivers.size(); idRecv++)\n      if(state.normalEquationInfo.estimateReceiver.at(idRecv))\n      {\n        std::vector<GnssType> types = state.gnss->types(~(GnssType::PRN + GnssType::FREQ_NO));\n        std::vector<Double>   ePe(types.size(), 0), redundancy(types.size(), 0);\n        std::vector<UInt>     obsCount(types.size(), 0), outlierCount(types.size(), 0);\n        state.residualsStatistics(idRecv, NULLINDEX/*idTrans*/, types, ePe, redundancy, obsCount, outlierCount);\n        Vector factors(types.size());\n        for(UInt i=0; i<types.size(); i++)\n        {\n          const UInt idx = GnssType::index(state.stations.at(idRecv).sigmaTypes, types.at(i));\n          if(idx != NULLINDEX)\n            factors(i) = state.stations.at(idRecv).sigmaFactors.at(idx);\n        }\n        Parallel::reduceSum(factors, 0, state.normalEquationInfo.comm);\n        if(Parallel::isMaster(state.normalEquationInfo.comm))\n          for(UInt i=0; i<types.size(); i++)\n            if(obsCount.at(i))\n            {\n              logInfo<<\"  \"<<state.gnss->receivers.at(idRecv)->name()<<\": \"<<types.at(i).str()\n                    <<\": factor = \"    <<factors(i)%\"%5.2f\"s\n                    <<\", sigma0 = \"    <<Vce::standardDeviation(ePe.at(i), redundancy.at(i), 2.5/*huber*/, 1.5/*huberPower*/)%\"%4.2f\"s\n                    <<\", count = \"     <<obsCount.at(i)%\"%5i\"s\n                    <<\", outliers = \"  <<outlierCount.at(i)%\"%5i\"s<<\" (\"<<(100.*outlierCount.at(i)/obsCount.at(i))%\"%4.2f\"s<<\" %)\"<<Log::endl;\n            }\n      } // for(idRecv)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepResolveAmbiguities.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepResolveAmbiguities.h\n*\n* @brief GNSS processing step: ResolveAmbiguities.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPRESOLVEAMBIGUITIES__\n#define __GROOPS_GNSSPROCESSINGSTEPRESOLVEAMBIGUITIES__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepResolveAmbiguities = R\"(\n\\subsection{ResolveAmbiguities}\\label{gnssProcessingStepType:resolveAmbiguities}\nPerforms a least squares adjustment like \\configClass{processingStep:estimate}{gnssProcessingStepType:estimate}\nbut with additional integer phase ambiguity resolution.\nAfter this step all resolved ambiguities are removed from the normal equation system.\nOnly ambiguities involving \\configClass{selectTransmitters/Receivers}{platformSelectorType} are resolved.\nIf \\configClass{selectTransmitters/Receivers}{platformSelectorType} is not set, all usable transmitters and/or \nreceivers are selected for ambiguity resolution.\n\nInteger ambiguity resolution is performed based on the least squares ambiguity decorrelation adjustment\n(LAMBDA) method (Teunissen 1995, DOI \\href{https://doi.org/10.1007/BF00863419}{10.1007/BF00863419}), specifically\nthe modified algorithm (MLAMBDA) by Chang et al. (2005, DOI \\href{https://doi.org/10.1007/s00190-005-0004-x}{10.1007/s00190-005-0004-x}).\nFirst the covariance matrix of the integer ambiguity parameters is computed by eliminating all but those parameters\nfrom the full normal equation matrix and inverting it. Then, a Z-transformation is performed as described by\nChang et al. (2005) to decorrelate the ambiguity parameters without losing their integer nature.\n\nThe search process follows MLAMBDA and uses integer minimization of the weighted sum of squared residuals.\nIt is computationally infeasible to search a hyper-ellipsoid with a dimension of ten thousand or more.\nInstead, a blocked search algorithm is performed by moving a window with a length of, for example,\n\\config{searchBlockSize}=\\verb|200| parameters over the decorrelated ambiguities, starting from the most accurate.\nIn each step, the window is moved by half of its length and the overlapping parts are compared to each other.\nIf all fixed ambiguities in the overlap agree, the algorithm continues.\nOtherwise, both windows are combined and the search is repeated using the combined window, again comparing with the overlapping\npart of the preceding window. If not all solutions could be checked for a block after \\config{maxSearchSteps},\nthe selected \\config{incompleteAction} is performed.\nIf the algorithm reaches ambiguities with a standard deviation higher than \\config{sigmaMaxResolve},\nambiguity resolution stops and the remaining ambiguities are left as float values.\nOtherwise, all ambiguity parameters are fixed to integer values.\n\nIn contrast to an integer least squares solution over the full ambiguity vector, it is not guaranteed that the resulting solution\nis optimal in the sense of minimal variance with given covariance.\nThis trade-off is necessary to cope with large numbers of ambiguities.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssLambda.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: ResolveAmbiguities.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepResolveAmbiguities : public GnssProcessingStepBase\n{\n  FileName                      fileNameAmbiguities;\n  PlatformSelectorPtr           selectTransmitters, selectReceivers;\n  Double                        sigmaMaxResolve;\n  UInt                          searchBlockSize, maxSearchSteps;\n  GnssLambda::IncompleteAction  incompleteAction;\n  Bool                          computeResiduals, adjustSigma0, computeWeights;\n  Double                        huber, huberPower;\n\npublic:\n  GnssProcessingStepResolveAmbiguities(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepResolveAmbiguities::GnssProcessingStepResolveAmbiguities(Config &config)\n{\n  try\n  {\n    std::string choice;\n\n    readConfig(config, \"outputfileAmbiguities\", fileNameAmbiguities, Config::OPTIONAL, \"\",              \"resolved ambiguities\");\n    readConfig(config, \"selectTransmitters\" ,   selectTransmitters,  Config::OPTIONAL, R\"([{\"all\":{}}])\", \"only resolve ambiguities with these participating transmitters\");\n    readConfig(config, \"selectReceivers\",       selectReceivers,     Config::OPTIONAL, R\"([{\"all\":{}}])\", \"only resolve ambiguities with these participating receivers\");\n    readConfig(config, \"sigmaMaxResolve\",       sigmaMaxResolve,     Config::OPTIONAL, \"0.2\",           \"max. allowed std. dev. of ambiguity to resolve [cycles]\");\n    readConfig(config, \"searchBlockSize\",       searchBlockSize,     Config::DEFAULT,  \"200\",           \"block size for blocked integer search\");\n    readConfig(config, \"maxSearchSteps\",        maxSearchSteps,      Config::OPTIONAL, \"200000000\",     \"max. steps of integer search for each block\");\n    if(readConfigChoice(config, \"incompleteAction\", choice, Config::MUSTSET, \"shrinkBlockSize\", \"if not all solutions tested after maxSearchSteps\"))\n    {\n      if(readConfigChoiceElement(config, \"stop\",            choice, \"stop searching, ambiguities remain float in this block\")) incompleteAction = GnssLambda::IncompleteAction::STOP;\n      if(readConfigChoiceElement(config, \"resolve\",         choice, \"use best integer solution found so far\"))                 incompleteAction = GnssLambda::IncompleteAction::IGNORE;\n      if(readConfigChoiceElement(config, \"shrinkBlockSize\", choice, \"try again with half block size\"))                         incompleteAction = GnssLambda::IncompleteAction::SHRINKBLOCKSIZE;\n      if(readConfigChoiceElement(config, \"throwException\",  choice, \"stop and throw an exception\"))                            incompleteAction = GnssLambda::IncompleteAction::EXCEPTION;\n      endChoice(config);\n    }\n    readConfig(config, \"computeResiduals\",      computeResiduals,    Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"adjustSigma0\",          adjustSigma0,        Config::DEFAULT,  \"1\",   \"adjust sigma0 by scale factor (per receiver and type)\");\n    readConfig(config, \"computeWeights\",        computeWeights,      Config::DEFAULT,  \"1\",   \"downweight outliers\");\n    readConfig(config, \"huber\",                 huber,               Config::DEFAULT,  \"2.5\", \"residuals > huber*sigma0 are downweighted\");\n    readConfig(config, \"huberPower\",            huberPower,          Config::DEFAULT,  \"1.5\", \"residuals > huber: sigma=(e/huber)^huberPower*sigma0\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepResolveAmbiguities::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== resolve ambiguities  ====================================\"<<Log::endl;\n    std::vector<Byte> selectedTransmitters(state.gnss->transmitters.size());\n    if(!selectTransmitters) // if no selector is given, assume all usable\n      std::transform(state.gnss->transmitters.begin(), state.gnss->transmitters.end(), selectedTransmitters.begin(), [](const auto t){return t->useable();});\n    else\n      selectedTransmitters = state.gnss->selectTransmitters(selectTransmitters);\n\n    std::vector<Byte> selectedReceivers(state.gnss->receivers.size());\n    if(!selectReceivers) // if no selector is given, assume all usable\n      std::transform(state.gnss->receivers.begin(), state.gnss->receivers.end(), selectedReceivers.begin(), [](const auto r){return r->useable();});\n    else\n      selectedReceivers = state.gnss->selectReceivers(selectReceivers);\n\n    Matrix solutionSteps;\n    state.estimateSolution(std::bind(&GnssLambda::searchIntegerBlocked, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,\n                                     sigmaMaxResolve, searchBlockSize, maxSearchSteps, incompleteAction, TRUE/*timing*/,\n                                     std::placeholders::_4, std::placeholders::_5, std::ref(solutionSteps)),\n                           selectedTransmitters, selectedReceivers,\n                           computeResiduals, computeWeights, adjustSigma0, huber, huberPower);\n    state.changedNormalEquationInfo = TRUE;\n\n    if(!fileNameAmbiguities.empty() && Parallel::isMaster(state.normalEquationInfo.comm))\n    {\n      logStatus<<\"write ambiguities to file(s) <\"<<fileNameAmbiguities<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameAmbiguities, solutionSteps);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepSelectEpochs.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepSelectEpochs.h\n*\n* @brief GNSS processing step: SelectEpochs.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPSELECTEPOCHS__\n#define __GROOPS_GNSSPROCESSINGSTEPSELECTEPOCHS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepSelectEpochs = R\"(\n\\subsection{SelectEpochs}\\label{gnssProcessingStepType:selectEpochs}\nSelect epochs for subsequent steps. This step can be used to reduce the processing sampling\nwhile keeping the original observation sampling for all preprocessing steps (e.g. outlier and cycle slip detection).\nAnother example is to process at a 5-minute sampling by setting \\config{nthEpoch}=\\verb|10| and then\nat the end to densify only the clock parameters to the full 30-second observation sampling by\nsetting \\config{nthEpoch}=\\verb|1| while keeping all other parameters fixed\nwith \\configClass{processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: SelectEpochs.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepSelectEpochs : public GnssProcessingStepBase\n{\n  UInt nthEpoch;\n\npublic:\n  GnssProcessingStepSelectEpochs(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline GnssProcessingStepSelectEpochs::GnssProcessingStepSelectEpochs(Config &config)\n{\n  try\n  {\n    readConfig(config, \"nthEpoch\", nthEpoch, Config::MUSTSET, \"1\", \"use only every nth epoch in all subsequent processing steps\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepSelectEpochs::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select epochs ===========================================\"<<Log::endl;\n    auto oldEpochs = state.normalEquationInfo.idEpochs;\n    state.normalEquationInfo.idEpochs.clear();\n    for(UInt idEpoch=0; idEpoch<state.gnss->times.size(); idEpoch+=nthEpoch)\n      state.normalEquationInfo.idEpochs.push_back(idEpoch);\n    logInfo<<\"  \"<<state.normalEquationInfo.idEpochs.size()<<\" of \"<<state.gnss->times.size()<<\" epochs selected\"<<Log::endl;\n    if((oldEpochs != state.normalEquationInfo.idEpochs) && std::any_of(state.stations.begin(), state.stations.end(), [](auto &s){return s.arOrder;}))\n      logWarningOnce<<\"estimated decorrelation AR process has been reset because the select epochs have changed\"<<Log::endl;\n    std::for_each(state.stations.begin(), state.stations.end(), [](auto &s){s.arOrder = 0;});\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepSelectNormalsBlockStructure.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepSelectNormalsBlockStructure.h\n*\n* @brief GNSS processing step: SelectNormalsBlockStructure.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPSELECTNORMALSBLOCKSTRUCTURE__\n#define __GROOPS_GNSSPROCESSINGSTEPSELECTNORMALSBLOCKSTRUCTURE__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepSelectNormalsBlockStructure = R\"(\n\\subsection{SelectNormalsBlockStructure}\\label{gnssProcessingStepType:selectNormalsBlockStructure}\nSelect block structure of sparse normal equations for subsequent steps.\n\nThis step can be used to define the structure of the different parts of the normal equation system,\nwhich can have a major impact on computing performance and memory consumption depending on the processing setup.\n\n\\fig{!hb}{0.4}{gnss_normals_structure}{fig:gnss_normals_structure}{Structure of normal equations in GNSS processing}\n\nThe normal equation system is divided into three parts for epoch, interval, and ambiguity parameters.\nThe epoch part is subdivided further into one subpart per epoch. Each part is divided into blocks and only non-zero\nblocks are stored in memory to reduce memory consumption and to prevent unnecessary matrix computations.\n\\config{defaultBlockSizeEpoch}, \\config{defaultBlockSizeInterval}, and \\config{defaultBlockSizeAmbiguity} control\nthe size of the blocks within each part of the normal equations. \\config{defaultBlockReceiverCount} can be set to group\na number of receivers into one block within the epoch and interval parts.\n\nIf \\config{keepEpochNormalsInMemory}=\\verb|no| epoch blocks are eliminated after they are set up to reduce the number\nof parameters in the normal equation system. \\config{defaultBlockCountReduction} controls after how many epoch blocks\nan elimination step is performed. For larger processing setups or high sampling rates epoch block elimination is recommended\nas the large number of clock parameters require a lot of memory.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: SelectNormalsBlockStructure.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepSelectNormalsBlockStructure : public GnssProcessingStepBase\n{\n  UInt defaultBlockSizeEpoch, defaultBlockSizeInterval, defaultBlockSizeAmbiguity;\n  UInt defaultBlockReceiverCount;\n  UInt defaultBlockCountReduction;\n  Bool keepEpochNormalsInMemory;\n  Bool accumulateEpochObservations;\n\npublic:\n  GnssProcessingStepSelectNormalsBlockStructure(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline GnssProcessingStepSelectNormalsBlockStructure::GnssProcessingStepSelectNormalsBlockStructure(Config &config)\n{\n  try\n  {\n    readConfig(config, \"defaultBlockSizeEpoch\",       defaultBlockSizeEpoch,       Config::DEFAULT,  \"0\",  \"block size of epoch parameters, 0: one block\");\n    readConfig(config, \"defaultBlockSizeInterval\",    defaultBlockSizeInterval,    Config::DEFAULT,  \"64\", \"block size of interval parameters, 0: one block\");\n    readConfig(config, \"defaultBlockSizeAmbiguity\",   defaultBlockSizeAmbiguity,   Config::DEFAULT,  \"64\", \"block size of ambiguity parameters, 0: one block\");\n    readConfig(config, \"defaultBlockReceiverCount\",   defaultBlockReceiverCount,   Config::DEFAULT,  \"0\",  \"number of receivers to group into one block for epoch and interval\");\n    readConfig(config, \"defaultBlockCountReduction\",  defaultBlockCountReduction,  Config::DEFAULT,  \"32\", \"minimum number of blocks for epoch reduction\");\n    readConfig(config, \"keepEpochNormalsInMemory\",    keepEpochNormalsInMemory,    Config::DEFAULT,  \"1\",  \"speeds up processing but uses much more memory\");\n    readConfig(config, \"accumulateEpochObservations\", accumulateEpochObservations, Config::DEFAULT,  \"0\",  \"set up all observations per epoch and receiver at once\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepSelectNormalsBlockStructure::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select block structure ==================================\"<<Log::endl;\n    state.normalEquationInfo.defaultBlockSizeEpoch       = defaultBlockSizeEpoch;\n    state.normalEquationInfo.defaultBlockSizeInterval    = defaultBlockSizeInterval;\n    state.normalEquationInfo.defaultBlockSizeAmbiguity   = defaultBlockSizeAmbiguity;\n    state.normalEquationInfo.defaultBlockReceiverCount   = defaultBlockReceiverCount;\n    state.normalEquationInfo.defaultBlockCountReduction  = defaultBlockCountReduction;\n    state.normalEquationInfo.keepEpochNormalsInMemory    = keepEpochNormalsInMemory;\n    state.normalEquationInfo.accumulateEpochObservations = accumulateEpochObservations;\n    logInfo<<\"  blockSizeEpoch              = \"<<state.normalEquationInfo.defaultBlockSizeEpoch    <<Log::endl;\n    logInfo<<\"  blockSizeInterval           = \"<<state.normalEquationInfo.defaultBlockSizeInterval <<Log::endl;\n    logInfo<<\"  blockSizeAmbiguity          = \"<<state.normalEquationInfo.defaultBlockSizeAmbiguity <<Log::endl;\n    logInfo<<\"  blockReceiverCount          = \"<<state.normalEquationInfo.defaultBlockReceiverCount<<Log::endl;\n    logInfo<<\"  blockCountReduction         = \"<<state.normalEquationInfo.defaultBlockCountReduction<<Log::endl;\n    logInfo<<\"  keepEpochNormalsInMemory    = \"<<(state.normalEquationInfo.keepEpochNormalsInMemory ? \"yes\" : \"no\")<<Log::endl;\n    logInfo<<\"  accumulateEpochObservations = \"<<(state.normalEquationInfo.accumulateEpochObservations ? \"yes\" : \"no\")<<Log::endl;\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepSelectParametrizations.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepSelectParametrizations.h\n*\n* @brief GNSS processing step: SelectParametrizations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPSELECTPARAMETRIZATIONS__\n#define __GROOPS_GNSSPROCESSINGSTEPSELECTPARAMETRIZATIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepSelectParametrizations = R\"(\n\\subsection{SelectParametrizations}\\label{gnssProcessingStepType:selectParametrizations}\nEnable/disable parameter groups and constraint groups for subsequent steps,\ne.g. \\configClass{processingStep:estimate}{gnssProcessingStepType:estimate} or\n\\configClass{processingStep:writeResults}{gnssProcessingStepType:writeResults}.\nThe \\config{name} and \\config{nameConstraint} of these groups\nare defined in \\configClass{parametrizations}{gnssParametrizationType}.\nPrior models or previously estimated parameters used as new apriori $\\M x_0$ values are unaffected\nand they are always reduced from the observations. This means all unselected parameters are kept fixed\nto their last result.\n\nAn example would be to process at a 5-minute sampling using\n\\configClass{processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}\nand then at the end to densify the clock parameters to the full 30-second observation sampling\nwhile keeping all other parameters fixed\n(\\config{disable}=\\verb|*|, \\config{enable}=\\verb|*.clock*|, \\config{enable}=\\verb|parameter.STEC|).\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"base/string.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: SelectParametrizations.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepSelectParametrizations : public GnssProcessingStepBase\n{\npublic:\n  class EnableDisable\n  {\n  public:\n    Bool enable;\n    std::vector<std::string> wildcards;\n  };\n\n  std::vector<EnableDisable> patterns;\n\n  GnssProcessingStepSelectParametrizations(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ntemplate<> inline Bool readConfig(Config &config, const std::string &name, GnssProcessingStepSelectParametrizations::EnableDisable &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    std::string choice;\n    if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n      return FALSE;\n    if(readConfigChoiceElement(config, \"enable\", choice, \"\"))\n    {\n      var.enable = TRUE;\n      readConfig(config, \"name\", var.wildcards, Config::MUSTSET, \"*\", \"wildcards: * and ?\");\n    }\n    if(readConfigChoiceElement(config, \"disable\", choice, \"\"))\n    {\n      var.enable = FALSE;\n      readConfig(config, \"name\", var.wildcards, Config::MUSTSET, \"*\", \"wildcards: * and ?\");\n    }\n    endChoice(config);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline GnssProcessingStepSelectParametrizations::GnssProcessingStepSelectParametrizations(Config &config)\n{\n  try\n  {\n    readConfig(config, \"parametrization\", patterns, Config::MUSTSET, \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepSelectParametrizations::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select parametrization =======================================\"<<Log::endl;\n    state.changedNormalEquationInfo = TRUE;\n    for(const auto &pattern : patterns)\n      for(const auto &wildcard: pattern.wildcards)\n      {\n        state.normalEquationInfo.enableParametrizations.emplace_back(String::wildcard2regex(wildcard), pattern.enable);\n        logInfo<<\"  \"<<(pattern.enable ? \"enable \" : \"disable\")<<\" parametrization: \"<<wildcard<<Log::endl;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepSelectReceivers.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepSelectReceivers.h\n*\n* @brief GNSS processing step: SelectReceivers.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPSELECTRECEIVERS__\n#define __GROOPS_GNSSPROCESSINGSTEPSELECTRECEIVERS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepSelectReceivers = R\"(\n\\subsection{SelectReceivers}\\label{gnssProcessingStepType:selectReceivers}\nThis step can be used to process only a subset of stations in subsequent processing steps.\nThe most common use is to start the processing with a well-distributed network of core stations as seen in\n\\reference{GNSS satellite orbit determination and network analysis}{cookbook.gnssNetwork:processing}.\nTo later process all other stations individually, use the processing step\n\\configClass{processingStep:forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately}\nand select all stations excluding the core stations in that step.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: SelectReceivers.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepSelectReceivers : public GnssProcessingStepBase\n{\n  PlatformSelectorPtr selectReceivers;\n\npublic:\n  GnssProcessingStepSelectReceivers(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline GnssProcessingStepSelectReceivers::GnssProcessingStepSelectReceivers(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectReceivers\", selectReceivers, Config::MUSTSET,  \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepSelectReceivers::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select receivers ========================================\"<<Log::endl;\n    if(state.normalEquationInfo.isEachReceiverSeparately)\n    {\n      logWarning<<\"SelectReceivers is not allowed in single receiver loop\"<<Log::endl;\n      return;\n    }\n    state.normalEquationInfo.estimateReceiver = state.gnss->selectReceivers(selectReceivers);\n    for(auto recv : state.gnss->receivers)\n      if(!recv->useable())\n        state.normalEquationInfo.estimateReceiver.at(recv->idRecv()) = FALSE;\n    logInfo<<\"  \"<<std::count(state.normalEquationInfo.estimateReceiver.begin(), state.normalEquationInfo.estimateReceiver.end(), TRUE)<<\" receivers selected\"<<Log::endl;\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepWriteAprioriSolution.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepWriteAprioriSolution.h\n*\n* @brief GNSS processing step: WriteAprioriSolution.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPWRITEAPRIORISOLUTION__\n#define __GROOPS_GNSSPROCESSINGSTEPWRITEAPRIORISOLUTION__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepWriteAprioriSolution = R\"(\n\\subsection{WriteAprioriSolution}\\label{gnssProcessingStepType:writeAprioriSolution}\nWrites the current apriori vector $\\M x_0$\n(see \\configClass{parametrizations}{gnssParametrizationType}).\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: WriteAprioriSolution.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepWriteAprioriSolution : public GnssProcessingStepBase\n{\n  FileName             fileNameApriori, fileNameParameterNames;\n  ParameterSelectorPtr parameterSelector;\n\npublic:\n  GnssProcessingStepWriteAprioriSolution(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepWriteAprioriSolution::GnssProcessingStepWriteAprioriSolution(Config &config)\n{\n  try\n  {\n    readConfig(config, \"outputfileAprioriSolution\", fileNameApriori,        Config::OPTIONAL, \"output/x0_{loopTime:%D}.txt\",            \"a priori parameters\");\n    readConfig(config, \"outputfileParameterNames\",  fileNameParameterNames, Config::OPTIONAL, \"output/parameterNames_{loopTime:%D}.txt\", \"parameter names\");\n    readConfig(config, \"remainingParameters\",       parameterSelector,      Config::OPTIONAL, \"\",  \"parameter order/selection of output normal equations\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepWriteAprioriSolution::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    std::vector<UInt> indexVector(state.normalEquationInfo.parameterCount());\n    if(parameterSelector)\n      indexVector = parameterSelector->indexVector(state.normalEquationInfo.parameterNames());\n    else\n      std::iota(indexVector.begin(), indexVector.end(), 0);\n\n    if(!fileNameApriori.empty())\n    {\n      logStatus<<\"write apriori solution to <\"<<fileNameApriori<<\">\"<<Log::endl;\n      const Vector x0 = reorder(state.gnss->aprioriParameter(state.normalEquationInfo), indexVector);\n      if(Parallel::isMaster(state.normalEquationInfo.comm))\n        writeFileMatrix(fileNameApriori, x0);\n    }\n\n    if(!fileNameParameterNames.empty() && Parallel::isMaster(state.normalEquationInfo.comm))\n    {\n      logStatus<<\"write parameter name file <\"<<fileNameParameterNames<<\">\"<<Log::endl;\n      std::vector<ParameterName> parameterNames;\n      for(UInt i=0; i<indexVector.size(); i++)\n        parameterNames.push_back((indexVector.at(i) != NULLINDEX) ? state.normalEquationInfo.parameterNames().at(indexVector.at(i)) : ParameterName());\n      writeFileParameterName(fileNameParameterNames, parameterNames);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepWriteNormalEquations.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepWriteNormalEquations.h\n*\n* @brief GNSS processing step: WriteNormalEquations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPWRITENORMALEQUATIONS__\n#define __GROOPS_GNSSPROCESSINGSTEPWRITENORMALEQUATIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepWriteNormalEquations = R\"(\n\\subsection{WriteNormalEquations}\\label{gnssProcessingStepType:writeNormalEquations}\nAccumulates the normal equations matrix and writes it.\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written to the normal equations\nand all other parameters are eliminated beforehand (implicitly solved).\n\nThe solution of the normals would result in $\\Delta\\M x$\n(see \\configClass{parametrizations}{gnssParametrizationType}). To write the\nappropriate apriori vector $\\M x_0$ use\n\\configClass{processingStep:writeAprioriSolution}{gnssProcessingStepType:writeAprioriSolution}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"gnss/gnssNormalEquationInfo.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: WriteNormalEquations.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepWriteNormalEquations : public GnssProcessingStepBase\n{\n  FileName             fileNameNormals;\n  ParameterSelectorPtr parameterSelector;\n  Bool                 constraintsOnly;\n  UInt                 defaultBlockSize;\n\npublic:\n  GnssProcessingStepWriteNormalEquations(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepWriteNormalEquations::GnssProcessingStepWriteNormalEquations(Config &config)\n{\n  try\n  {\n    defaultBlockSize = NULLINDEX;\n    readConfig(config, \"outputfileNormalEquations\", fileNameNormals,   Config::MUSTSET,  \"output/normals_{loopTime:%D}.dat\", \"normals\");\n    readConfig(config, \"remainingParameters\",       parameterSelector, Config::OPTIONAL, \"\",  \"parameter order/selection of output normal equations\");\n    readConfig(config, \"constraintsOnly\",           constraintsOnly,   Config::DEFAULT,  \"0\", \"write only normals of constraints without observations\");\n    readConfig(config, \"defaultNormalsBlockSize\",   defaultBlockSize,  Config::OPTIONAL, \"\",  \"block size for distributing the normal equations, 0: one block, empty: original block size\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepWriteNormalEquations::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== write normal equations ==================================\"<<Log::endl;\n    if(!state.normalEquationInfo.parameterCount())\n    {\n      logWarningOnce<<\"Empty normal equations matrix\"<<Log::endl;\n      return;\n    }\n    Bool eliminateEpochParameters = FALSE;\n    std::vector<UInt> blockIndex, indexVector(state.normalEquationInfo.parameterCount());\n    std::iota(indexVector.begin(), indexVector.end(), 0);\n\n    // compute index vectors and block structure for remaining parameters\n    UInt eliminationBlocks = 0, eliminationCount = 0;\n    if(parameterSelector)\n    {\n      indexVector = parameterSelector->indexVector(state.normalEquationInfo.parameterNames());\n      if(!indexVector.size())\n      {\n        logWarningOnce<<\"No matching parameters selected\"<<Log::endl;\n        return;\n      }\n\n      const UInt countEpochParameter = state.normalEquationInfo.blockIndex(state.normalEquationInfo.blockInterval());\n      eliminateEpochParameters = (*std::min_element(indexVector.begin(), indexVector.end()) >= countEpochParameter);\n      std::vector<UInt> eliminationIndexVector = ParameterSelector::indexVectorComplement(indexVector, state.normalEquationInfo.parameterCount());\n      if(eliminateEpochParameters)\n        eliminationIndexVector.erase(std::remove_if(eliminationIndexVector.begin(), eliminationIndexVector.end(),\n                                                    [&](UInt x){return x < countEpochParameter;}), eliminationIndexVector.end());\n      eliminationCount = eliminationIndexVector.size();\n      indexVector.insert(indexVector.begin(), eliminationIndexVector.begin(), eliminationIndexVector.end());\n\n      blockIndex = MatrixDistributed::computeBlockIndex(eliminationCount, 2048);\n      eliminationBlocks = blockIndex.size()-1;\n      if(defaultBlockSize == 0)\n        blockIndex.push_back(indexVector.size());\n      else\n        while(blockIndex.back() < indexVector.size())\n          blockIndex.push_back(std::min(blockIndex.back()+((defaultBlockSize == NULLINDEX) ? 2048 : defaultBlockSize), indexVector.size()));\n    }\n    else if(defaultBlockSize != NULLINDEX)\n      blockIndex = MatrixDistributed::computeBlockIndex(state.normalEquationInfo.parameterCount(), defaultBlockSize);\n\n    // accumulate normals\n    state.buildNormals(constraintsOnly, eliminateEpochParameters);\n    // merge right hand side to one matrix\n    Matrix rhs(state.normals.parameterCount(), state.lPl.rows());\n    if(Parallel::isMaster(state.normalEquationInfo.comm))\n      for(UInt i=0; i<state.normals.blockCount(); i++)\n        copy(state.n.at(i), rhs.row(state.normals.blockIndex(i), state.normals.blockSize(i)));\n\n    // reorder normals\n    if((defaultBlockSize != NULLINDEX) || parameterSelector)\n    {\n      state.normals.reorder(indexVector, blockIndex);\n      rhs = reorder(rhs, indexVector);\n\n      if((eliminationCount > 0) && !constraintsOnly)\n      {\n        std::vector<ParameterName> parameterNames;\n        for(UInt i=0; i<eliminationCount; i++)\n          parameterNames.push_back((indexVector.at(i) != NULLINDEX) ? state.normalEquationInfo.parameterNames().at(indexVector.at(i)) : ParameterName());\n        state.regularizeNotUsedParameters(0, eliminationBlocks, parameterNames);\n        state.normals.cholesky(TRUE, 0, eliminationBlocks, TRUE);\n        state.normals.triangularTransSolve(rhs, 0, eliminationBlocks);\n        state.obsCount -= eliminationCount;\n        for(UInt i=0; i<state.lPl.rows(); i++)\n          state.lPl(i) -= quadsum(rhs.slice(0, i, eliminationCount, 1)); // lPl = lPl - n1' N1^(-1) n1\n      }\n      state.normals.eraseBlocks(0, eliminationBlocks);\n      rhs = rhs.row(eliminationCount, rhs.rows()-eliminationCount);\n    }\n\n    // parameter names\n    std::vector<ParameterName> parameterNames;\n    for(UInt i=eliminationCount; i<indexVector.size(); i++)\n      parameterNames.push_back((indexVector.at(i) != NULLINDEX) ? state.normalEquationInfo.parameterNames().at(indexVector.at(i)) : ParameterName());\n\n    logStatus<<\"write normal equations to <\"<<fileNameNormals<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameNormals, NormalEquationInfo(parameterNames, state.lPl, state.obsCount), state.normals, rhs);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepWriteResiduals.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepWriteResiduals.h\n*\n* @brief GNSS processing step: WriteResiduals.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPWRITERESIDUALS__\n#define __GROOPS_GNSSPROCESSINGSTEPWRITERESIDUALS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepWriteResiduals = R\"(\n\\subsection{WriteResiduals}\\label{gnssProcessingStepType:writeResiduals}\nWrites the \\file{observation residuals}{instrument} for all\n\\configClass{selectReceivers}{platformSelectorType}.\nFor each station a file is written. The file name is interpreted as\na template with the variable \\verb|{station}| being replaced by the station name.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: WriteResiduals.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepWriteResiduals : public GnssProcessingStepBase\n{\n  PlatformSelectorPtr selectReceivers;\n  FileName            fileNameResiduals;\n\npublic:\n  GnssProcessingStepWriteResiduals(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepWriteResiduals::GnssProcessingStepWriteResiduals(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectReceivers\",     selectReceivers,   Config::MUSTSET, \"\", \"subset of used stations\");\n    readConfig(config, \"outputfileResiduals\", fileNameResiduals, Config::MUSTSET, \"output/residuals_{loopTime:%D}.{station}.dat\", \"variable {station} available\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepWriteResiduals::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    auto selectedReceivers = state.gnss->selectReceivers(selectReceivers);\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(\"station\", \"****\");\n    logStatus<<\"write residuals to file <\"<<fileNameResiduals(fileNameVariableList)<<\">\"<<Log::endl;\n    for(auto recv : state.gnss->receivers)\n      if(selectedReceivers.at(recv->idRecv()) && state.normalEquationInfo.estimateReceiver.at(recv->idRecv()) && recv->isMyRank())\n      {\n        GnssReceiverArc arc;\n        for(UInt idEpoch : state.normalEquationInfo.idEpochs)\n          if(recv->useable(idEpoch))\n          {\n            // get types\n            std::vector<GnssType> types;\n            for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n              if(recv->observation(idTrans, idEpoch) && state.gnss->transmitters.at(idTrans)->useable(idEpoch))\n                for(UInt idType=0; idType<recv->observation(idTrans, idEpoch)->size(); idType++)\n                  if(!recv->observation(idTrans, idEpoch)->at(idType).type.isInList(types))\n                    types.push_back(recv->observation(idTrans, idEpoch)->at(idType).type & ~(GnssType::PRN+GnssType::FREQ_NO));\n            std::sort(types.begin(), types.end());\n            if(!types.size())\n              continue;\n\n            GnssReceiverEpoch epoch;\n            GnssType system = GnssType::SYSTEM;\n            for(UInt idType=0; idType<types.size(); idType++)\n            {\n              if(types.at(idType) != system)\n              {\n                system = types.at(idType) & GnssType::SYSTEM;\n                epoch.obsType.push_back( GnssType::AZIMUT    + GnssType::L1 + system );\n                epoch.obsType.push_back( GnssType::ELEVATION + GnssType::L1 + system );\n                epoch.obsType.push_back( GnssType::AZIMUT    + GnssType::L2 + system );\n                epoch.obsType.push_back( GnssType::ELEVATION + GnssType::L2 + system );\n                epoch.obsType.push_back( GnssType::IONODELAY + system );\n              }\n              // residuals, redundancy, sigma\n              epoch.obsType.insert(epoch.obsType.end(), {types.at(idType), types.at(idType), types.at(idType)});\n            }\n\n            for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n              if(recv->observation(idTrans, idEpoch) && state.gnss->transmitters.at(idTrans)->useable(idEpoch))\n              {\n                const GnssObservation &obs = *recv->observation(idTrans, idEpoch);\n                const GnssObservationEquation eqn(obs, *recv, *state.gnss->transmitters.at(idTrans),\n                                                  state.gnss->funcRotationCrf2Trf, state.gnss->funcReduceModels, idEpoch, FALSE, {});\n                const GnssType prn = obs.at(0).type & (GnssType::SYSTEM + GnssType::PRN + GnssType::FREQ_NO);\n                UInt idType = std::distance(epoch.obsType.begin(), std::find(epoch.obsType.begin(), epoch.obsType.end(), prn));\n                if(idType >= epoch.obsType.size())\n                  continue;\n\n                epoch.time = eqn.timeRecv;\n                epoch.satellite.push_back(prn);\n                epoch.observation.insert(epoch.observation.end(), {eqn.azimutRecvAnt, eqn.elevationRecvAnt, eqn.azimutTrans, eqn.elevationTrans, obs.STEC});\n                idType += 5;\n\n                for(; (idType<epoch.obsType.size()) && (epoch.obsType.at(idType) == prn); idType+=3)\n                {\n                  epoch.observation.insert(epoch.observation.end(), {0., 0., 1.});\n                  for(UInt i=0; i<obs.size(); i++)\n                    if(obs.at(i).type == epoch.obsType.at(idType))\n                    {\n                      epoch.observation.at(epoch.observation.size()-3) = obs.at(i).residuals;\n                      epoch.observation.at(epoch.observation.size()-2) = obs.at(i).redundancy;\n                      epoch.observation.at(epoch.observation.size()-1) = obs.at(i).sigma/obs.at(i).sigma0;\n                      break;\n                    }\n                }\n              } // for(idTrans)\n\n            if(epoch.satellite.size())\n              arc.push_back(epoch);\n          } // for(idEpoch)\n\n        VariableList fileNameVariableList;\n        fileNameVariableList.setVariable(\"station\", recv->name());\n        InstrumentFile::write(fileNameResiduals(fileNameVariableList), arc);\n      } // for(recv)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepWriteResults.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepWriteResults.h\n*\n* @brief GNSS processing step: WriteResults.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPWRITERESULTS__\n#define __GROOPS_GNSSPROCESSINGSTEPWRITERESULTS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepWriteResults = R\"(\n\\subsection{WriteResults}\\label{gnssProcessingStepType:writeResults}\nIn this step all \\config{outputfiles} defined in \\configClass{parametrizations}{gnssParametrizationType}\nare written. It considers the settings of\n\\configClass{processingStep:selectParametrizations}{gnssProcessingStepType:selectParametrizations},\n\\configClass{processingStep:selectEpochs}{gnssProcessingStepType:selectEpochs}, and\n\\configClass{processingStep:selectReceivers}{gnssProcessingStepType:selectReceivers}.\n\nIt is usually the last processing step, but can also be used at other points in the\nprocessing in combination with \\config{suffix} to write intermediate results, for example\nbefore \\configClass{gnssProcessingStep:resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities} to\noutput the float solution.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: WriteResults.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepWriteResults : public GnssProcessingStepBase\n{\n  std::string suffix;\n\npublic:\n  GnssProcessingStepWriteResults(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepWriteResults::GnssProcessingStepWriteResults(Config &config)\n{\n  readConfig(config, \"suffix\", suffix, Config::OPTIONAL, \"\", \"appended to every output file name (e.g. orbit.G01.suffix.dat)\");\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepWriteResults::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== write results  ==========================================\"<<Log::endl;\n    state.gnss->writeResults(state.normalEquationInfo, !suffix.empty() ? \".\"+suffix : \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepWriteUsedStationList.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepWriteUsedStationList.h\n*\n* @brief GNSS processing step: WriteUsedStationList.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPWRITEUSEDSTATIONLIST__\n#define __GROOPS_GNSSPROCESSINGSTEPWRITEUSEDSTATIONLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepWriteUsedStationList = R\"(\n\\subsection{WriteUsedStationList}\\label{gnssProcessingStepType:writeUsedStationList}\nWrites a \\file{list}{stringList} of receivers (stations) which are used in the last step and\nselected by \\configClass{selectReceivers}{platformSelectorType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: WriteUsedStationList.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepWriteUsedStationList : public GnssProcessingStepBase\n{\n  PlatformSelectorPtr selectReceivers;\n  FileName            fileNameUsedStationList;\n\npublic:\n  GnssProcessingStepWriteUsedStationList(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepWriteUsedStationList::GnssProcessingStepWriteUsedStationList(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectReceivers\",           selectReceivers,         Config::MUSTSET, \"\", \"subset of used stations\");\n    readConfig(config, \"outputfileUsedStationList\", fileNameUsedStationList, Config::MUSTSET, \"\", \"ascii file with names of used stations\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepWriteUsedStationList::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    if(!Parallel::isMaster(state.normalEquationInfo.comm))\n      return;\n    auto selectedReceivers = state.gnss->selectReceivers(selectReceivers);\n    logStatus<<\"write used station list to file <\"<<fileNameUsedStationList<<\">\"<<Log::endl;\n    std::vector<std::string> usedStationList;\n    for(auto recv : state.gnss->receivers)\n      if(selectedReceivers.at(recv->idRecv()) && state.normalEquationInfo.estimateReceiver.at(recv->idRecv()))\n        usedStationList.push_back(recv->name());\n    writeFileStringList(fileNameUsedStationList, usedStationList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssProcessingStep/gnssProcessingStepWriteUsedTransmitterList.h",
    "content": "/***********************************************/\n/**\n* @file gnssProcessingStepWriteUsedTransmitterList.h\n*\n* @brief GNSS processing step: WriteUsedTransmitterList.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-05\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSPROCESSINGSTEPWRITEUSEDTRANSMITTERLIST__\n#define __GROOPS_GNSSPROCESSINGSTEPWRITEUSEDTRANSMITTERLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssProcessingStep\nstatic const char *docstringGnssProcessingStepWriteUsedTransmitterList = R\"(\n\\subsection{WriteUsedTransmitterList}\\label{gnssProcessingStepType:writeUsedTransmitterList}\nWrites a \\file{list}{stringList} of transmitters which are used in the last step and\nselected by \\configClass{selectTransmitters}{platformSelectorType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS processing step: WriteUsedTransmitterList.\n* @ingroup gnssProcessingStepGroup\n* @see GnssProcessingStep */\nclass GnssProcessingStepWriteUsedTransmitterList : public GnssProcessingStepBase\n{\n  PlatformSelectorPtr selectTransmitters;\n  FileName            fileNameOutTransmitterList;\n\npublic:\n  GnssProcessingStepWriteUsedTransmitterList(Config &config);\n  void process(GnssProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline GnssProcessingStepWriteUsedTransmitterList::GnssProcessingStepWriteUsedTransmitterList(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectTransmitters\",            selectTransmitters,         Config::MUSTSET, \"\", \"subset of used transmitters\");\n    readConfig(config, \"outputfileUsedTransmitterList\", fileNameOutTransmitterList, Config::MUSTSET, \"\", \"ascii file with PRNs\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssProcessingStepWriteUsedTransmitterList::process(GnssProcessingStep::State &state)\n{\n  try\n  {\n    if(!Parallel::isMaster(state.normalEquationInfo.comm))\n      return;\n    auto selectedTransmitters = state.gnss->selectTransmitters(selectTransmitters);\n    logStatus<<\"write used transmitter list to file <\"<<fileNameOutTransmitterList<<\">\"<<Log::endl;\n    std::vector<std::string> usedTransmitterList;\n    for(auto trans : state.gnss->transmitters)\n      if(selectedTransmitters.at(trans->idTrans()) && trans->useable())\n        usedTransmitterList.push_back(trans->name());\n    writeFileStringList(fileNameOutTransmitterList, usedTransmitterList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssReceiver.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssReceiver.cpp\n*\n* @brief GNSS receiver.\n*\n* @author Torsten Mayer-Guerr\n* @author Norbert Zehentner\n* @author Sebastian Strasser\n* @date 2013-06-28\n*\n*/\n/***********************************************/\n\n#include <random>\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"parser/expressionParser.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"inputOutput/logging.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"gnss/gnssLambda.h\"\n#include \"gnss/gnssObservation.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiver.h\"\n\n/***********************************************/\n\nGnssReceiver::GnssReceiver(Bool isMyRank, Bool isEarthFixed, const Platform &platform,\n                           GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction, const Vector &useableEpochs,\n                           Bool integerAmbiguities, Double wavelengthFactor)\n  : GnssTransceiver(platform, noPatternFoundAction, useableEpochs), isMyRank_(isMyRank),\n    isEarthFixed_(isEarthFixed), integerAmbiguities(integerAmbiguities), wavelengthFactor(wavelengthFactor)\n{\n}\n\n/***********************************************/\n\n// this seems to improve the performance\nvoid GnssReceiver::copyObservations2ContinuousMemoryBlock()\n{\n  try\n  {\n    UInt count = 0;\n    for(const auto &obsEpoch : observations_)\n      for(const GnssObservation *obs : obsEpoch)\n        if(obs)\n          count++;\n    obsMem.resize(count);\n    obsMem.shrink_to_fit();\n    // copy\n    count = 0;\n    for(auto &obsEpoch : observations_)\n      for(GnssObservation *&obs : obsEpoch)\n        if(obs)\n        {\n          obsMem.at(count) = *obs;\n          obsMem.at(count).shrink_to_fit();\n          delete obs;\n          obs = &obsMem.at(count++);\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::disable(UInt idEpoch, const std::string &reason)\n{\n  try\n  {\n    GnssTransceiver::disable(idEpoch, reason);\n    if(idEpoch < observations_.size())\n      observations_.at(idEpoch).clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::disable(const std::string &reason)\n{\n  try\n  {\n    GnssTransceiver::disable(reason);\n    if(!reason.empty() && isMyRank())\n      disableReason = reason;\n    isMyRank_ = FALSE;\n    obsMem.clear();\n    obsMem.shrink_to_fit();\n    observations_.clear();\n    observations_.shrink_to_fit();\n    tracks.clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssObservation *GnssReceiver::observation(UInt idTrans, UInt idEpoch) const\n{\n  if((idEpoch < observations_.size()) && (idTrans < observations_.at(idEpoch).size()))\n    return observations_[idEpoch][idTrans];\n  return nullptr;\n}\n\n/***********************************************/\n\nvoid GnssReceiver::deleteObservation(UInt idTrans, UInt idEpoch)\n{\n  try\n  {\n    if(!observation(idTrans, idEpoch))\n      return;\n    observations_[idEpoch][idTrans] = nullptr;\n    if(std::all_of(observations_[idEpoch].begin(), observations_[idEpoch].end(), [](auto obs) {return obs == nullptr;}))\n      disable(idEpoch, \"no valid epochs left\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::signalComposition(UInt /*idEpoch*/, const std::vector<GnssType> &types, std::vector<GnssType> &typesTrans, Matrix &A) const\n{\n  try\n  {\n    // composed type = factor1 * type1 + factor2 * type2\n    static const std::vector<std::tuple<GnssType, GnssType, GnssType, Double, Double>> composites =\n      {{GnssType::C1XG,  GnssType::C1SG, GnssType::C1LG, 0.5, 0.5},\n       {GnssType::C2XG,  GnssType::C2SG, GnssType::C2LG, 0.5, 0.5},\n       {GnssType::C5XG,  GnssType::C5IG, GnssType::C5QG, 0.5, 0.5},\n\n       {GnssType::C4XR,  GnssType::C4AR, GnssType::C4BR, 0.5, 0.5},\n       {GnssType::C6XR,  GnssType::C6AR, GnssType::C6BR, 0.5, 0.5},\n       {GnssType::C3XR,  GnssType::C3IR, GnssType::C3QR, 0.5, 0.5},\n\n       {GnssType::C1XE,  GnssType::C1BE, GnssType::C1CE, 0.5, 0.5},\n       {GnssType::C5XE,  GnssType::C5IE, GnssType::C5QE, 0.5, 0.5},\n       {GnssType::C7XE,  GnssType::C7IE, GnssType::C7QE, 0.5, 0.5},\n       {GnssType::C8XE,  GnssType::C8IE, GnssType::C8QE, 0.5, 0.5},\n       {GnssType::C6XE,  GnssType::C6BE, GnssType::C6CE, 0.5, 0.5},\n\n       {GnssType::C2XC,  GnssType::C2IC, GnssType::C2QC, 0.5, 0.5},\n       {GnssType::C1XC,  GnssType::C1DC, GnssType::C1PC, 0.5, 0.5},\n       {GnssType::C1ZC,  GnssType::C1SC, GnssType::C1LC, 0.5, 0.5},\n       {GnssType::C5XC,  GnssType::C5DC, GnssType::C5PC, 0.5, 0.5},\n       {GnssType::C7XC,  GnssType::C7IC, GnssType::C7QC, 0.5, 0.5},\n       {GnssType::C7ZC,  GnssType::C7DC, GnssType::C7PC, 0.5, 0.5},\n       {GnssType::C8XC,  GnssType::C8DC, GnssType::C8PC, 0.5, 0.5},\n       {GnssType::C6XC,  GnssType::C6IC, GnssType::C6QC, 0.5, 0.5},\n       {GnssType::C6ZC,  GnssType::C6DC, GnssType::C6PC, 0.5, 0.5},\n\n       {GnssType::C1XJ,  GnssType::C1SJ, GnssType::C1LJ, 0.5, 0.5},\n       {GnssType::C2XJ,  GnssType::C2SJ, GnssType::C2LJ, 0.5, 0.5},\n       {GnssType::C5XJ,  GnssType::C5IJ, GnssType::C5QJ, 0.5, 0.5},\n       {GnssType::C5ZJ,  GnssType::C5DJ, GnssType::C5PJ, 0.5, 0.5},\n       {GnssType::C6XJ,  GnssType::C6SJ, GnssType::C6LJ, 0.5, 0.5},\n       {GnssType::C6ZJ,  GnssType::C6SJ, GnssType::C6EJ, 0.5, 0.5},\n\n       // unknown attributes\n       {GnssType::C2UG,  GnssType::C2SG, GnssType::C2LG, 0.5, 0.5},\n       {GnssType::C5UG,  GnssType::C5IG, GnssType::C5QG, 0.5, 0.5},\n       {GnssType::C1UE,  GnssType::C1BE, GnssType::C1CE, 0.5, 0.5},\n       {GnssType::C5UE,  GnssType::C5IE, GnssType::C5QE, 0.5, 0.5},\n       {GnssType::C7UE,  GnssType::C7IE, GnssType::C7QE, 0.5, 0.5},\n       {GnssType::C8UE,  GnssType::C8IE, GnssType::C8QE, 0.5, 0.5},\n       {GnssType::C6UE,  GnssType::C6BE, GnssType::C6CE, 0.5, 0.5}};\n\n    typesTrans = GnssType::replaceCompositeSignals(types);\n\n    A = Matrix(types.size(), typesTrans.size());\n    for(UInt idType=0; idType<types.size(); idType++)\n      if((types.at(idType) == GnssType::PHASE) || (types.at(idType) == GnssType::RANGE)) // only phase and code signals are transmitted (what about doppler?)\n      {\n        GnssType type = types.at(idType);\n\n        UInt idx;\n        if(type.isInList(typesTrans, idx))\n        {\n          A(idType, idx) = 1.; // signal observed directly\n          continue;\n        }\n\n        if(type == GnssType::C2DG)\n        {\n          A(idType, GnssType::index(typesTrans, GnssType::C1CG)) = +1.;\n          A(idType, GnssType::index(typesTrans, GnssType::C1WG)) = -1.;\n          A(idType, GnssType::index(typesTrans, GnssType::C2WG)) = +1.;\n          continue;\n        }\n\n        const auto composite = std::find_if(composites.begin(), composites.end(), [&](const auto &composite) {return (std::get<0>(composite) == type);});\n        if(composite != composites.end())\n        {\n          A(idType, GnssType::index(typesTrans, std::get<1>(*composite))) = std::get<3>(*composite);\n          A(idType, GnssType::index(typesTrans, std::get<2>(*composite))) = std::get<4>(*composite);\n          continue;\n        }\n\n        throw(Exception(\"composite signal not implemented: \"+type.str()));\n      } // for(idType)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGnssReceiver::ObservationEquationList::ObservationEquationList(const GnssReceiver &receiver, const std::vector<GnssTransmitterPtr> &transmitters,\n                                                               const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                                                               const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                                                               GnssObservation::Group group)\n{\n  try\n  {\n    eqn.resize(receiver.idEpochSize());\n    for(UInt idEpoch=0; idEpoch<eqn.size(); idEpoch++)\n    {\n      eqn.at(idEpoch).resize(receiver.idTransmitterSize(idEpoch));\n      for(UInt idTrans=0; idTrans<eqn.at(idEpoch).size(); idTrans++)\n      {\n        GnssObservation *obs = receiver.observation(idTrans, idEpoch);\n        std::vector<GnssType> types;\n        if(obs && obs->observationList(group, types))\n        {\n          auto e = new GnssObservationEquation(*obs, receiver, *transmitters.at(idTrans), rotationCrf2Trf, reduceModels, idEpoch, FALSE, types);\n          eqn.at(idEpoch).at(idTrans) = std::unique_ptr<GnssObservationEquation>(e);\n        }\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssObservationEquation *GnssReceiver::ObservationEquationList::operator()(UInt idTrans, UInt idEpoch) const\n{\n  if((idEpoch < eqn.size()) && (idTrans < eqn.at(idEpoch).size()))\n    return eqn[idEpoch][idTrans].get();\n  return nullptr;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid GnssReceiver::preprocessingInfo(const std::string &info, UInt countEpochs, UInt countObservations, UInt countTracks)\n{\n  try\n  {\n    if(countEpochs == NULLINDEX)\n    {\n      countEpochs = 0;\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        if(useable(idEpoch))\n          countEpochs++;\n    }\n\n    if(countObservations == NULLINDEX)\n    {\n      countObservations = 0;\n      for(UInt idEpoch=0; idEpoch<observations_.size(); idEpoch++)\n        for(UInt idTrans=0; idTrans<observations_.at(idEpoch).size(); idTrans++)\n          if(observations_[idEpoch][idTrans])\n            countObservations++;\n    }\n\n    if(countTracks == NULLINDEX)\n      countTracks = tracks.size();\n\n    preprocessingInfos.push_back(countEpochs%\"%6i epochs,\"s+countObservations%\"%7i observations,\"s+countTracks%\"%4i tracks: \"s+info);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::readObservations(const FileName &fileName, const std::vector<GnssTransmitterPtr> &transmitters,\n                                    const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, const Time &timeMargin, Angle elevationCutOff,\n                                    const std::vector<GnssType> &useType, const std::vector<GnssType> &ignoreType, GnssObservation::Group group)\n{\n  try\n  {\n    GnssReceiverArc arc = InstrumentFile::read(fileName);\n    preprocessingInfo(\"in file <\"+fileName.str()+\">\", arc.size(),\n                      std::accumulate(arc.begin(), arc.end(), UInt(0), [](UInt count, const auto &e){return count+e.satellite.size();}), 0);\n\n    std::vector<Time> observationTimes;\n    Vector phaseWindup(transmitters.size());\n    std::map<GnssType, UInt> removedTypes;\n\n    UInt idEpoch = 0;\n    for(UInt arcEpoch=0; arcEpoch<arc.size(); arcEpoch++)\n    {\n      // search time slot\n      while((idEpoch < times.size()) && (times.at(idEpoch)+timeMargin < arc.at(arcEpoch).time))\n        disable(idEpoch++, \"missing epochs in file\");\n      if(idEpoch >= times.size())\n        break;\n      if((arc.at(arcEpoch).time+timeMargin < times.at(idEpoch)) || !useable(idEpoch))\n        continue;\n      times.at(idEpoch) = arc.at(arcEpoch).time;\n//    clk.at(idEpoch)   = arc.at(arcEpoch).clockError;\n      observationTimes.push_back(arc.at(arcEpoch).time);\n\n      const std::vector<GnssType> receiverTypes = definedTypes(times.at(idEpoch));\n\n      // create observation class for each satellite\n      UInt idObs  = 0;\n      for(UInt k=0; k<arc.at(arcEpoch).satellite.size(); k++)\n      {\n        // find list of observation types for this satellite\n        GnssType satType = arc.at(arcEpoch).satellite.at(k);\n        UInt idType = 0;\n        while(arc.at(arcEpoch).obsType.at(idType) != satType)\n          idType++;\n\n        // search transmitter index for satellite number (PRN)\n        const UInt idTrans = std::distance(transmitters.begin(), std::find_if(transmitters.begin(), transmitters.end(),\n                                                                              [&](auto t) {return t->PRN() == satType;}));\n        std::vector<GnssType> transmitterTypes;\n        if(idTrans < transmitters.size())\n          transmitterTypes = transmitters.at(idTrans)->definedTypes(times.at(idEpoch));\n\n        // repair GLONASS frequency number\n        if((satType == GnssType::GLONASS) && transmitterTypes.size() && (transmitterTypes.front().frequencyNumber() != 9999))\n          satType.setFrequencyNumber(transmitterTypes.front().frequencyNumber());\n\n        GnssObservation *obs = new GnssObservation();\n        for(; (idType<arc.at(arcEpoch).obsType.size()) && (arc.at(arcEpoch).obsType.at(idType)==satType); idType++, idObs++)\n          if((idTrans < transmitters.size()) && arc.at(arcEpoch).observation.at(idObs)  && !std::isnan(arc.at(arcEpoch).observation.at(idObs)))\n          {\n            GnssType type = arc.at(arcEpoch).obsType.at(idType) + satType;\n            // remove GLONASS frequency number\n            if((type == GnssType::GLONASS) && !((type == GnssType::G1) || (type == GnssType::G2)))\n              type.setFrequencyNumber(9999);\n\n            // check completeness\n            if(type.hasWildcard(GnssType::TYPE + GnssType::FREQUENCY + GnssType::SYSTEM + GnssType::PRN))\n            {\n              logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": \"<<type.str()<<\" is not complete\"<<Log::endl;\n              continue;\n            }\n            if((type.frequencyNumber() == 9999) && (type == GnssType::GLONASS) && ((type == GnssType::G1) || (type == GnssType::G2)))\n            {\n              logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": \"<<type.str()<<\": GLONASS frequency number not set\"<<Log::endl;\n              continue;\n            }\n            if((type.frequencyNumber() != 9999) && !((type == GnssType::GLONASS) && ((type == GnssType::G1) || (type == GnssType::G2))))\n            {\n              logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": \"<<type.str()<<\": GLONASS frequency number is set\"<<Log::endl;\n              continue;\n            }\n\n            // check useType and ignoreType\n            Bool use = (useType.size()==0) ? TRUE : FALSE;\n            if(type.isInList(useType))\n              use = TRUE;\n            if(type.isInList(ignoreType))\n              use = FALSE;\n\n            // check against receiver and transmitter types\n            if(use && receiverTypes.size() && !type.isInList(receiverTypes))\n            {\n              use = FALSE;\n              removedTypes[type]++;\n            }\n            if(use && transmitterTypes.size())\n              for(const GnssType &typeTrans : GnssType::replaceCompositeSignals({type}))\n                if(!typeTrans.isInList(transmitterTypes))\n                {\n                  use = FALSE;\n                  removedTypes[type]++;\n                }\n\n            if(use)\n              obs->push_back(GnssSingleObservation(type, arc.at(arcEpoch).observation.at(idObs)));\n          }\n\n        std::vector<GnssType> types;\n        if((obs->size() == 0) || (idTrans >= transmitters.size()) ||\n           !obs->init(*this, *transmitters.at(idTrans), rotationCrf2Trf, idEpoch, elevationCutOff, phaseWindup(idTrans)) ||\n           !obs->observationList(group, types))\n        {\n          delete obs;\n          continue;\n        }\n\n        if(observations_.size() <= idEpoch)\n          observations_.resize(idEpoch+1);\n        if(observations_.at(idEpoch).size() <= idTrans)\n          observations_.at(idEpoch).resize(idTrans+1, nullptr);\n        if(observations_[idEpoch][idTrans])\n          logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": observation already exists\"<<Log::endl;\n        obs->sort();\n        std::swap(observations_[idEpoch][idTrans], obs);\n        delete obs;\n      } // for(satellite)\n\n      if((observations_.size() <= idEpoch) || (observations_[idEpoch].size() == 0))\n        disable(idEpoch, \"no useable observations found (elevationCutOff, use/ignoreTypes, defined receiver/transmitter types, missing antenna patterns)\");\n      idEpoch++;\n    } // for(arcEpoch)\n\n    for(UInt idEpoch=observations_.size(); idEpoch<times.size(); idEpoch++)\n      disable(idEpoch, \"missing epochs in file\");\n\n    if(removedTypes.size())\n    {\n      std::stringstream ss;\n      for(const auto &type : removedTypes)\n        ss<<\"  \"<<type.first.str()<<\"=\"<<type.second;\n      logWarning<<name()<<\": removed undefined observations\"<<ss.str()<<Log::endl;\n    }\n\n    observationSampling = medianSampling(observationTimes).seconds();\n    copyObservations2ContinuousMemoryBlock();\n    preprocessingInfo(\"readObservations()\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::simulateZeroObservations(const std::vector<GnssType> &types,\n                                            const std::vector<GnssTransmitterPtr> &transmitters,\n                                            const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, Angle elevationCutOff,\n                                            const std::vector<GnssType> &useType, const std::vector<GnssType> &ignoreType, GnssObservation::Group group)\n{\n  try\n  {\n    Vector phaseWindup(transmitters.size());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      const std::vector<GnssType> receiverTypes = definedTypes(times.at(idEpoch));\n\n      // create observation class for each satellite\n      for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n      {\n        // find list of observation types for this satellite\n        GnssType satType = transmitters.at(idTrans)->PRN();\n        std::vector<GnssType> transmitterTypes;\n        if(idTrans < transmitters.size())\n          transmitterTypes = transmitters.at(idTrans)->definedTypes(times.at(idEpoch));\n\n        // repair GLONASS frequency number\n        if((satType == GnssType::GLONASS) && transmitterTypes.size() && (transmitterTypes.front().frequencyNumber() != 9999))\n          satType.setFrequencyNumber(transmitterTypes.front().frequencyNumber());\n\n        GnssObservation *obs = new GnssObservation();\n        for(UInt idType=0; idType<types.size(); idType++)\n          if(types.at(idType) == satType)\n          {\n            GnssType type = types.at(idType) + satType;\n            // remove GLONASS frequency number\n            if((type == GnssType::GLONASS) && !((type == GnssType::G1) || (type == GnssType::G2)))\n              type.setFrequencyNumber(9999);\n\n            // check completeness\n            if(type.hasWildcard(GnssType::TYPE + GnssType::FREQUENCY + GnssType::SYSTEM + GnssType::PRN))\n            {\n              logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": \"<<type.str()<<\" is not complete\"<<Log::endl;\n              continue;\n            }\n            if((type.frequencyNumber() == 9999) && (type == GnssType::GLONASS) && ((type == GnssType::G1) || (type == GnssType::G2)))\n            {\n              logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": \"<<type.str()<<\": GLONASS frequency number not set\"<<Log::endl;\n              continue;\n            }\n            if((type.frequencyNumber() != 9999) && !((type == GnssType::GLONASS) && ((type == GnssType::G1) || (type == GnssType::G2))))\n            {\n              logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": \"<<type.str()<<\": GLONASS frequency number is set\"<<Log::endl;\n              continue;\n            }\n\n            // check useType and ignoreType\n            Bool use = (useType.size()==0) ? TRUE : FALSE;\n            if(type.isInList(useType))\n              use = TRUE;\n            if(type.isInList(ignoreType))\n              use = FALSE;\n\n            // check against receiver and transmitter types\n            if(use && receiverTypes.size() && !type.isInList(receiverTypes))\n              use = FALSE;\n            if(use && transmitterTypes.size())\n            {\n              GnssType typeComposed = type;\n              if(typeComposed == GnssType::PHASE) // phase can only be measured, if RANGE with is available\n                typeComposed = (typeComposed & ~GnssType::TYPE) + GnssType::RANGE; // replace PHASE by RANGE (to preserve ATTRIBUTE)\n              for(const GnssType &typeTrans : GnssType::replaceCompositeSignals({typeComposed}))\n                if(!typeTrans.isInList(transmitterTypes))\n                  use = FALSE;\n            }\n            if(!use)\n              continue;\n\n            obs->push_back(GnssSingleObservation(type, 0.0));\n          }\n\n        std::vector<GnssType> types;\n        if((obs->size() == 0) || (idTrans >= transmitters.size()) ||\n           !obs->init(*this, *transmitters.at(idTrans), rotationCrf2Trf, idEpoch, elevationCutOff, phaseWindup(idTrans)) ||\n           !obs->observationList(group, types))\n        {\n          delete obs;\n          continue;\n        }\n\n        if(observations_.size() <= idEpoch)\n          observations_.resize(idEpoch+1);\n        if(observations_.at(idEpoch).size() <= idTrans)\n          observations_.at(idEpoch).resize(idTrans+1, nullptr);\n        if(observations_[idEpoch][idTrans])\n          logWarning<<name()<<\" -> \"<<transmitters.at(idTrans)->name()<<\" at \"<<times.at(idEpoch).dateTimeStr()<<\": observation already exists\"<<Log::endl;\n        obs->sort();\n        std::swap(observations_[idEpoch][idTrans], obs);\n        delete obs;\n      } // for(satellite)\n\n      if((observations_.size() <= idEpoch) || (observations_[idEpoch].size() == 0))\n        disable(idEpoch, \"no observations simulated (elevationCutOff, use/ignoreTypes, defined receiver/transmitter types, missing antenna patterns)\");\n    } // for(arcEpoch)\n\n    observationSampling = medianSampling(times).seconds();\n    copyObservations2ContinuousMemoryBlock();\n    preprocessingInfo(\"simulateObservations()\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::simulateObservations(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                                        const std::vector<GnssTransmitterPtr> &transmitters,\n                                        const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                                        const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                                        UInt minObsCountPerTrack, Angle elevationTrackMinimum, GnssObservation::Group group)\n{\n  try\n  {\n    // Simulate clock error\n    // --------------------\n    Vector clock = noiseClock->noise(times.size());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      if(useable(idEpoch))\n        updateClockError(idEpoch, clock(idEpoch)/LIGHT_VELOCITY);\n\n    // ambiguities\n    // -----------\n    class Ambiguity : public GnssAmbiguity\n    {\n    public:\n      std::vector<GnssType> types;\n      Vector                value; // ambiguities in meter\n\n      explicit Ambiguity(GnssTrack *track, const Vector &value) : GnssAmbiguity(track), types(track->types), value(value) {}\n\n      Vector ambiguities(const std::vector<GnssType> &types) const override\n      {\n        Vector value(types.size());\n        UInt idx;\n        for(UInt idType=0; idType<types.size(); idType++)\n          if(types.at(idType).isInList(this->types, idx))\n            value(idType) = this->value(idx);\n        return value;\n      }\n    };\n\n    // init random phase ambiguities\n    std::random_device randomDevice;\n    std::mt19937_64 generator; // for ambiguities\n    generator.seed(randomDevice());\n    auto ambiguityRandom = std::uniform_int_distribution<Int>(-10000, 10000);\n\n    createTracks(transmitters, minObsCountPerTrack, {});\n    for(auto &track : tracks)\n    {\n      Vector value(track->types.size());\n      for(UInt i=0; i<value.size(); i++)\n        if(track->types.at(i) == GnssType::PHASE)\n          value(i) = wavelengthFactor*track->types.at(i).wavelength() * ambiguityRandom(generator); // cycles to meter\n      new Ambiguity(track.get(), value); // track is owner of ambiguity\n    }\n\n    // reduced observations\n    // --------------------\n    ObservationEquationList eqnList(*this, transmitters, rotationCrf2Trf, reduceModels, group);\n    removeLowElevationTracks(eqnList, elevationTrackMinimum);\n\n    for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n    {\n      std::vector<GnssType> typesTrans;\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      {\n        auto obs = observation(idTrans, idEpoch);\n        if(obs)\n          for(UInt idType=0; idType<obs->size(); idType++)\n            if(!obs->at(idType).type.isInList(typesTrans))\n              typesTrans.push_back(obs->at(idType).type);\n      }\n      if(!typesTrans.size())\n        continue;\n\n      const Matrix eps = noiseObs->noise(times.size(), typesTrans.size()); // obs noise\n      UInt idx;\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        if(observation(idTrans, idEpoch))\n        {\n          const GnssObservationEquation &eqn = *eqnList(idTrans, idEpoch);\n          GnssObservation *obs = observation(idTrans, idEpoch);\n          for(UInt idType=0; idType<obs->size(); idType++)\n            if(obs->at(idType).type.isInList(eqn.types, idx))\n              obs->at(idType).observation = -eqn.l(idx) + eqn.sigma(idx) * eps(idEpoch, GnssType::index(typesTrans, obs->at(idType).type));\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Vector3d> GnssReceiver::estimateInitialClockErrorFromCodeObservations(const std::vector<GnssTransmitterPtr> &transmitters,\n                                                                                  const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                                                                                  const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                                                                                  Double huber, Double huberPower, Bool estimateKinematicPosition)\n{\n  try\n  {\n    // count systems\n    std::vector<GnssType> systems, types;\n    for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n      for(UInt idEpoch=0; idEpoch<idEpochSize(); idEpoch++)\n        if(useable(idEpoch) && observation(idTrans, idEpoch) && observation(idTrans, idEpoch)->observationList(GnssObservation::RANGE, types))\n        {\n          if(!types.at(0).isInList(systems))\n            systems.push_back(types.at(0) & GnssType::SYSTEM);\n          break;\n        }\n\n    std::vector<Vector3d> posOld = pos;\n\n    const UInt countStaticParameters = (estimateKinematicPosition ? 0 : 3) + systems.size()-1; // pos + inter clock biases\n    const UInt countEpochParameters  = (estimateKinematicPosition ? 3 : 0) + 1; // pos + clock error\n\n    for(UInt iter=0; iter<10; iter++)\n    {\n      // setup observation equations: position, clock\n      // --------------------------------------------\n      std::vector<Matrix> listl, listA;\n      std::vector<Matrix> listlFull, listAFull, listBFull;\n      std::vector<UInt>   listEpoch;\n      std::vector<std::vector<UInt>> listIndexFull;\n      UInt maxSat = 0;\n      for(UInt idEpoch=0; idEpoch<idEpochSize(); idEpoch++)\n        if(useable(idEpoch))\n        {\n          // count observations and setup observation equations for each transmitter\n          UInt                                 obsCount = 0;\n          std::vector<GnssObservationEquation> eqnList;\n          for(UInt idTrans=0; idTrans<idTransmitterSize(idEpoch); idTrans++)\n          {\n            const GnssObservation *obs = observation(idTrans, idEpoch);\n            std::vector<GnssType> types;\n            if(obs && obs->observationList(GnssObservation::RANGE, types))\n            {\n              eqnList.emplace_back(*obs, *this, *transmitters.at(idTrans), rotationCrf2Trf, reduceModels, idEpoch, TRUE, types);\n              eqnList.back().eliminateGroupParameters(); // eliminate STEC\n              obsCount += eqnList.back().l.rows();\n            }\n          }\n\n          if(!obsCount || (eqnList.size() <= countEpochParameters)) // if not enough observations -> delete epoch\n          {\n            disable(idEpoch, \"not enough observations to estimate clock errors\");\n            continue;\n          }\n\n          // setup combined observation equations\n          Vector l(obsCount);\n          Matrix A(obsCount, countStaticParameters); // pos (if static) + intersystem clock bias (per system)\n          Matrix B(obsCount, countEpochParameters);  // epoch: clock + pos (if kinematic)\n\n          listIndexFull.push_back({0});\n          UInt idx = 0;\n          for(const auto &eqn : eqnList)\n          {\n            const UInt count = eqn.l.rows();\n            copy(eqn.l, l.row(idx, count));\n            copy(eqn.A.column(GnssObservationEquation::idxClockRecv),  B.slice(idx, 0, count, 1)); // clock\n            MatrixSlice Apos(estimateKinematicPosition ? B.slice(idx, 1, count, 3) : A.slice(idx, 0, count, 3));\n            if(isEarthFixed())\n              matMult(1., eqn.A.column(GnssObservationEquation::idxPosRecv, 3), rotationCrf2Trf(eqn.timeRecv).matrix().trans(), Apos);\n            else\n              copy(eqn.A.column(GnssObservationEquation::idxPosRecv, 3), Apos);\n            // intersystem clock shift\n            const UInt idxSys = GnssType::index(systems, eqn.types.front());\n            if(idxSys > 0)\n              copy(eqn.A.column(GnssObservationEquation::idxClockTrans),  A.slice(idx, estimateKinematicPosition ? (idxSys-1) : (3+idxSys-1), count, 1)); // clock bias\n            idx += count;\n            listIndexFull.back().push_back(idx);\n          }\n\n          listEpoch.push_back(idEpoch);\n          listlFull.push_back(l);\n          listBFull.push_back(B);\n          maxSat = std::max(maxSat, eqnList.size());\n\n          if(A.size())\n          {\n            listAFull.push_back(A);\n            eliminationParameter(B, {A, l});\n            listl.push_back(l);\n            listA.push_back(A);\n          }\n        } // for(idEpoch)\n\n      if(!listEpoch.size() || (maxSat < countStaticParameters+countEpochParameters))\n      {\n       disable(\"only \"+maxSat%\"%i satellites tracked\"s);\n       return posOld;\n      }\n\n      // estimate static parameters\n      // --------------------------\n      Double maxPosDiff = 0;\n      if(countStaticParameters)\n      {\n        // copy equations in one system\n        const UInt count = std::accumulate(listl.begin(), listl.end(), UInt(0), [](UInt sum, const auto &x) {return sum+x.size();});\n        Vector l(count);\n        Matrix A(count, countStaticParameters);\n        std::vector<UInt> index({0});\n        Vector sigma;\n        for(UInt i=0; i<listl.size(); i++)\n        {\n          const UInt idx = index.back();\n          copy(listl.at(i), l.row(idx, listl.at(i).rows()));\n          copy(listA.at(i), A.row(idx, listA.at(i).rows()));\n          index.push_back(idx+listA.at(i).rows());\n        }\n        const Vector dx = Vce::robustLeastSquares(A, l, index, huber, huberPower, 30, sigma);\n        for(UInt i=0; i<listEpoch.size(); i++)               // update with static parameters\n          matMult(-1, listAFull.at(i), dx, listlFull.at(i));\n        if(!estimateKinematicPosition)                       // udpate static position\n        {\n          const Vector3d dpos(dx.row(0, 3));\n          maxPosDiff = dpos.r();\n          for(UInt i=0; i<listEpoch.size(); i++)\n            pos.at(listEpoch.at(i)) += dpos;\n        }\n      }\n\n      // reconstruct epoch parameters\n      // ----------------------------\n      for(UInt i=0; i<listEpoch.size(); i++)\n      {\n        Vector sigma;\n        const Vector y = Vce::robustLeastSquares(listBFull.at(i), listlFull.at(i), listIndexFull.at(i), huber, huberPower, 10, sigma);\n        matMult(-1, listBFull.at(i), y, listlFull.at(i)); // compute residuals\n        updateClockError(listEpoch.at(i), y(0)/LIGHT_VELOCITY);\n        if(estimateKinematicPosition)\n        {\n          pos.at(listEpoch.at(i)) += Vector3d(y.row(1, 3));\n          maxPosDiff = std::max(maxPosDiff, norm(y.row(1, 3)));\n        }\n      }\n\n      // check convergence\n      // -----------------\n      if(maxPosDiff < 5.0) // pos change smaller than 5 m\n        break;\n    } // for(iter)\n\n    preprocessingInfo(\"estimateInitialClockErrorFromCodeObservations()\");\n\n    // restore apriori positions and return new positions\n    std::swap(pos, posOld);\n    return posOld;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::disableEpochsWithGrossCodeObservationOutliers(ObservationEquationList &eqnList, Double threshold, Double outlierRatio)\n{\n  try\n  {\n    for(UInt idEpoch=0; idEpoch<idEpochSize(); idEpoch++)\n      if(useable(idEpoch))\n      {\n        // delete all observations to a satellite at epoch if they contain a gross code outlier\n        UInt outlierCount = 0;\n        UInt count   = 0;\n        for(UInt idTrans=0; idTrans<idTransmitterSize(idEpoch); idTrans++)\n          if(observation(idTrans, idEpoch))\n          {\n            const GnssObservationEquation &eqn = *eqnList(idTrans, idEpoch);\n            for(UInt idType=0; idType<eqn.types.size(); idType++)\n              if((eqn.types.at(idType) == GnssType::RANGE) && (std::fabs(eqn.l.at(idType)) >= threshold))\n              {\n                deleteObservation(idTrans, idEpoch);\n                outlierCount++;\n                break;\n              }\n            count++;\n          }\n\n        // disable epoch if outlierRatio or more of the observed satellites have gross code outliers\n        if(outlierCount >= outlierRatio * count)\n          disable(idEpoch, \"too many gross code outliers\");\n      }\n\n    preprocessingInfo(\"disableEpochsWithGrossCodeObservationOutliers()\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::createTracks(const std::vector<GnssTransmitterPtr> &transmitters, UInt minObsCountPerTrack, const std::vector<GnssType> &extraTypes)\n{\n  try\n  {\n    tracks.clear();\n    for(UInt idTrans=0; idTrans<transmitters.size(); idTrans++)\n    {\n      UInt idEpochStart = 0;\n      for(;;)\n      {\n        // find continuous track\n        // ---------------------\n        // find first epoch of the track\n        while((idEpochStart < idEpochSize()) && !observation(idTrans, idEpochStart))\n          idEpochStart++;\n\n        GnssObservation *obs = observation(idTrans, idEpochStart);\n        if(!obs) // at end?\n          break;\n\n        // phase and range types of start epoch\n        std::vector<GnssType> types;\n        for(UInt idType= 0; idType <obs->size(); idType++)\n          if((obs->at(idType).type == GnssType::PHASE) || (obs->at(idType).type == GnssType::RANGE))\n            types.push_back(obs->at(idType).type);\n        std::sort(types.begin(), types.end());\n\n        // find last epoch of the track\n        UInt countEpoch = 1;\n        UInt idEpochEnd = idEpochStart;\n        for(UInt idEpoch=idEpochStart+1; idEpoch<idEpochSize(); idEpoch++)\n        {\n          GnssObservation *obs = observation(idTrans, idEpoch);\n          if(obs)\n          {\n            if((times.at(idEpoch)-times.at(idEpochEnd)).seconds() > 1.5*observationSampling)\n              break;\n\n            // test types\n            std::vector<GnssType> typesNew;\n            for(UInt idType=0; idType<obs->size(); idType++)\n              if((obs->at(idType).type == GnssType::PHASE) || (obs->at(idType).type == GnssType::RANGE))\n                typesNew.push_back(obs->at(idType).type);\n            if(!GnssType::allEqual(types, typesNew))\n              break;\n\n            idEpochEnd = idEpoch;\n            countEpoch++;\n          }\n        } // for(idEpoch)\n\n        // need phases at two frequencies (additional to extraTypes)\n        std::vector<GnssType> typeFrequencies;\n        for(GnssType type : types)\n          if((type == GnssType::PHASE) && !type.isInList(extraTypes) && !type.isInList(typeFrequencies))\n            typeFrequencies.push_back(type & GnssType::FREQUENCY);\n\n        // define track\n        if((countEpoch >= minObsCountPerTrack) && (typeFrequencies.size() >= 2))\n        {\n          tracks.push_back(std::make_shared<GnssTrack>(this, transmitters.at(idTrans).get(), idEpochStart, idEpochEnd, types));\n          for(UInt idEpoch=idEpochStart; idEpoch<=idEpochEnd; idEpoch++)\n            if(observation(idTrans, idEpoch))\n              observation(idTrans, idEpoch)->track = tracks.back().get();\n        }\n        else\n        {\n          for(UInt idEpoch=idEpochStart; idEpoch<=idEpochEnd; idEpoch++)\n            deleteObservation(idTrans, idEpoch);\n        }\n\n        idEpochStart = idEpochEnd + 1;\n      } // for(;;)\n    } // for(idTrans)\n\n    preprocessingInfo(\"createTracks()\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::deleteTrack(UInt idTrack)\n{\n  try\n  {\n    for(UInt idEpoch=tracks.at(idTrack)->idEpochStart; idEpoch<=tracks.at(idTrack)->idEpochEnd; idEpoch++)\n    {\n      deleteObservation(tracks.at(idTrack)->transmitter->idTrans(), idEpoch); // possibly disables receiver and clears all tracks\n      if(!useable())\n        return;\n    }\n    tracks.erase(tracks.begin()+idTrack);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::deleteEmptyTracks()\n{\n  try\n  {\n    auto isEmpty = [](GnssTrackPtr t)\n    {\n      for(UInt idEpoch=t->idEpochStart; idEpoch<=t->idEpochEnd; idEpoch++)\n        if(t->transmitter->useable(idEpoch) && t->receiver->observation(t->transmitter->idTrans(), idEpoch))\n          return FALSE;\n      return TRUE;\n    };\n\n    tracks.erase(std::remove_if(tracks.begin(), tracks.end(), isEmpty), tracks.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::removeLowElevationTracks(ObservationEquationList &eqnList, Angle minElevation)\n{\n  try\n  {\n    for(UInt idTrack=tracks.size(); idTrack-->0;)\n    {\n      const UInt idTrans = tracks.at(idTrack)->transmitter->idTrans();\n      Bool removeTrack = TRUE;\n      for(UInt idEpoch=tracks.at(idTrack)->idEpochStart; idEpoch<=tracks.at(idTrack)->idEpochEnd; idEpoch++)\n        if(eqnList(idTrans, idEpoch) && (eqnList(idTrans, idEpoch)->elevationRecvAnt >= minElevation))\n        {\n          removeTrack = FALSE;\n          break;\n        }\n\n      if(removeTrack)\n        deleteTrack(idTrack);\n    }\n\n    preprocessingInfo(\"removeLowElevationTracks()\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssTrackPtr GnssReceiver::splitTrack(ObservationEquationList &eqnList, GnssTrackPtr track, UInt idEpochSplit)\n{\n  try\n  {\n    // new track\n    const UInt idTrans = track->transmitter->idTrans();\n    GnssTrackPtr trackNew = std::make_shared<GnssTrack>(track->receiver, track->transmitter, idEpochSplit, track->idEpochEnd, track->types);\n    tracks.push_back(trackNew);\n\n    // shorten old track\n    track->idEpochEnd = idEpochSplit-1;\n\n    // connect observations to new track\n    for(UInt idEpoch=trackNew->idEpochStart; idEpoch<=trackNew->idEpochEnd; idEpoch++)\n      if(observation(idTrans, idEpoch))\n        observation(idTrans, idEpoch)->track = trackNew.get();\n\n    // connect observation equations to new track\n    for(UInt idEpoch=trackNew->idEpochStart; idEpoch<=trackNew->idEpochEnd; idEpoch++)\n      if(observation(idTrans, idEpoch))\n        eqnList(idTrans, idEpoch)->track = trackNew.get();\n\n    return trackNew;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// determine Melbourne-Wuebbena-like linear combinations\nvoid GnssReceiver::linearCombinations(ObservationEquationList &eqnList, GnssTrackPtr track, const std::vector<GnssType> &extraTypes,\n                                      std::vector<GnssType> &typesPhase, std::vector<UInt> &idEpochs, Matrix &combinations, Double &cycles2tecu) const\n{\n  try\n  {\n    // available observations for this track\n    typesPhase.clear();\n    idEpochs.clear();\n    for(UInt idEpoch=track->idEpochStart; idEpoch<=track->idEpochEnd; idEpoch++)\n      if(eqnList(track->transmitter->idTrans(), idEpoch) && observation(track->transmitter->idTrans(), idEpoch))\n      {\n        idEpochs.push_back(idEpoch);\n        for(GnssType type : eqnList(track->transmitter->idTrans(), idEpoch)->types)\n          if((type == GnssType::PHASE) && !type.isInList(typesPhase) && !type.isInList(extraTypes)) // ignore time variable GPS L5 signals\n            typesPhase.push_back(type);\n      }\n\n    const Matrix Bias = GnssLambda::phaseDecorrelation(typesPhase, wavelengthFactor);\n    combinations = Matrix(idEpochs.size(), Bias.columns()-1);\n    UInt row = 0;\n    for(UInt idEpoch : idEpochs)\n    {\n      const GnssObservationEquation &eqn = *eqnList(track->transmitter->idTrans(), idEpoch);\n      Vector l = eqn.l;\n      Matrix A(l.rows(), Bias.columns()+2);\n      UInt idx;\n      for(UInt idType=0; idType<eqn.types.size(); idType++) // ambiguities\n        if(eqn.types.at(idType).isInList(typesPhase, idx) || (eqn.types.at(idType) == GnssType::RANGE))\n        {\n          l(idType) = eqn.l(idType)/eqn.sigma0(idType);\n          A(idType, 0) = 1.; // range\n          A(idType, 1) = eqn.types.at(idType).ionosphericFactor(); // TEC\n          if(idx != NULLINDEX)\n            copy(Bias.row(idx), A.slice(idType, 2, 1, Bias.columns()));\n          A.row(idType) *= 1./eqn.sigma0(idType);\n        }\n\n      // skip the first, inaccurate one\n      copy(leastSquares(A, l).row(2+1, Bias.columns()-1).trans(), combinations.row(row++));\n    }\n\n    // determine cycle slip size in terms of TEC\n    Vector l = Bias.column(0); // cycle slips can only occur in this linear combination anymore\n    Matrix A(typesPhase.size(), 2, 1.); // first column range\n    for(UInt idType=0; idType<typesPhase.size(); idType++)\n      A(idType, 1) = typesPhase.at(idType).ionosphericFactor(); // TEC\n    cycles2tecu = std::fabs(leastSquares(A, l)(1,0)); // one cycle slip in terms of TEC\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// determine range & TEC based on phase observations only\nvoid GnssReceiver::rangeAndTec(ObservationEquationList &eqnList, UInt idTrans, const std::vector<UInt> &idEpochs,\n                               const std::vector<GnssType> &typesPhase, Vector &range, Vector &tec) const\n{\n  try\n  {\n    Matrix A(typesPhase.size(), 2, 1.);\n    for(UInt k=0; k<A.rows(); k++)\n      A(k, 1) = typesPhase.at(k).ionosphericFactor();\n\n    Matrix L(typesPhase.size(), idEpochs.size());\n    for(UInt i=0; i<idEpochs.size(); i++)\n      for(UInt k=0; k<L.rows(); k++)\n        L(k, i) = eqnList(idTrans, idEpochs.at(i))->l(GnssType::index(eqnList(idTrans, idEpochs.at(i))->types, typesPhase.at(k)));\n\n    const Matrix x = leastSquares(A, L);\n    range = x.row(0).trans();\n    tec   = x.row(1).trans();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic Double computeBias(const Vector &data, Double maxRange)\n{\n  try\n  {\n    std::vector<Double> x = data;\n    std::sort(x.begin(), x.end());\n\n    // find max length interval with data within maxRange\n    auto iStartMax = x.begin();\n    auto iEndMax   = x.begin();\n    auto iEnd      = x.begin();\n    for(auto iStart=x.begin(); iStart!=x.end(); iStart++)\n    {\n      while((iEnd!=x.end()) && ((*iEnd)-(*iStart) < maxRange))\n        iEnd++;\n      if(std::distance(iStart, iEnd) > std::distance(iStartMax, iEndMax))\n      {\n        iStartMax = iStart;\n        iEndMax   = iEnd;\n      }\n    }\n\n    //  mean of this interval\n    return std::accumulate(iStartMax, iEndMax, 0.)/std::distance(iStartMax, iEndMax);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::writeTracks(const FileName &fileName, ObservationEquationList &eqnList, const std::vector<GnssType> &extraTypes) const\n{\n  try\n  {\n    if(fileName.empty())\n      return;\n\n    for(const auto &track : tracks)\n      if(track->countObservations())\n      {\n        std::vector<GnssType> typesPhase;\n        std::vector<UInt>     idEpochs;\n        Matrix                combinations;\n        Double                cycles2tecu;\n        Vector                range, tec;\n        linearCombinations(eqnList, track, extraTypes, typesPhase, idEpochs, combinations, cycles2tecu);\n        rangeAndTec(eqnList, track->transmitter->idTrans(), idEpochs, typesPhase, range, tec);\n\n        Matrix A(idEpochs.size(), 2+combinations.columns());\n        axpy(1./cycles2tecu, tec, A.column(1));\n        copy(combinations, A.column(2, combinations.columns()));\n\n        std::vector<Time> timesTrack;\n        for(UInt idEpoch : idEpochs)\n          timesTrack.push_back(times.at(idEpoch));\n        for(UInt i=1; i<A.columns(); i++)\n          A.column(i) -= median(A.column(i));\n\n        std::string typeStr;\n        for(GnssType type : typesPhase)\n          typeStr += type.str().substr(0, 3);\n        typeStr = String::replaceAll(typeStr, \"?\", \"\");\n        VariableList varList;\n        varList.setVariable(\"station\",        name());\n        varList.setVariable(\"prn\",            track->transmitter->name());\n        varList.setVariable(\"trackTimeStart\", timesTrack.front().mjd());\n        varList.setVariable(\"trackTimeEnd\",   timesTrack.back().mjd());\n        varList.setVariable(\"types\",          typeStr);\n        InstrumentFile::write(fileName(varList), Arc(timesTrack, A));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::cycleSlipsDetection(ObservationEquationList &eqnList, UInt minObsCountPerTrack, Double lambda, UInt windowSize, Double tecSigmaFactor, const std::vector<GnssType> &extraTypes)\n{\n  try\n  {\n    for(UInt idTrack=0; idTrack<tracks.size(); idTrack++)\n    {\n      if(tracks.at(idTrack)->countObservations() >= std::max(minObsCountPerTrack, windowSize))\n        cycleSlipsDetection(eqnList, tracks.at(idTrack), lambda, windowSize, tecSigmaFactor, extraTypes);\n      if(tracks.at(idTrack)->countObservations() < minObsCountPerTrack)\n        deleteTrack(idTrack--);\n    }\n\n    preprocessingInfo(\"cycleSlipsDetection()\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::cycleSlipsDetection(ObservationEquationList &eqnList, GnssTrackPtr track, Double lambda, UInt windowSize, Double tecSigmaFactor, const std::vector<GnssType> &extraTypes)\n{\n  try\n  {\n    // determine Melbourne-Wuebbena-like linear combinations\n    // -----------------------------------------------------\n    std::vector<GnssType> typesPhase;\n    std::vector<UInt>     idEpochs;\n    Matrix                combinations;\n    Double                cycles2tecu;\n    linearCombinations(eqnList, track, extraTypes, typesPhase, idEpochs, combinations, cycles2tecu);\n    Vector slips(idEpochs.size());\n    for(UInt k=0; k<combinations.columns(); k++)\n    {\n      const Vector smoothed = totalVariationDenoising(combinations.column(k), lambda);\n      const Double bias     = computeBias(smoothed, 0.01);\n      for(UInt i=1; i<idEpochs.size(); i++) // cycle slip if denoised difference exceeds 3/4 cycle\n        if(std::fabs(std::round(smoothed(i)-bias) - std::round(smoothed(i-1)-bias)) > 0.75)\n          slips(i) = TRUE;\n    }\n\n    for(UInt i=slips.rows(); i-->0;)\n      if(slips(i))\n      {\n        splitTrack(eqnList, track, idEpochs.at(i));\n        idEpochs.resize(i); // shorten data to new track length\n      }\n\n    // find cycle slips in TEC based on moving window over autoregressive model residuals\n    // ----------------------------------------------------------------------------------\n    Vector range, tec;\n    rangeAndTec(eqnList, track->transmitter->idTrans(), idEpochs, typesPhase, range, tec);\n\n    const UInt order = 3; // AR model order\n    if(windowSize && (tec.size() >= order+windowSize+1))\n    {\n      // Estimate AR process with Burg\n      // Code mostly from books such as TimeSeriesAnalysis by James Hamilton,\n      // Introduction to TimeSeries and Forecasting by brockwell and Davis,\n      // and statsmodels implementaiton which seems to be the easiest way todo imo by using burg->lev\n\n      // Compute first diff and convert to cycles\n      // First diff is used to get rid of any additional issues within the tec\n      // also to make sure the timeseries is stationary as possible for AR estimation\n      // basically an ARIMA(3,1,0) model is used for the jump detection\n      Vector x(tec.rows()-1, 0.);\n      for(UInt i=1; i<tec.rows(); i++)\n        x(i-1) = (tec(i) - tec(i-1))/cycles2tecu;\n      x -= mean(x);\n\n      // Burg algorithm to compute the partial autocorrelations\n      Vector d(order+1, 0.);\n      d(0) = 2 * quadsum(x);\n      Vector pacf(order+1, 0.);\n      Vector u (x.rows());\n      Vector v (x.rows());\n\n      for(UInt i=1; i<=x.rows(); i++)\n      {\n        u(i-1) = x(x.rows()-i);\n        v(i-1) = x(x.rows()-i);\n      }\n\n      d(1) = inner(u.slice(0, u.rows()-1), u.slice(0, u.rows()-1)) + inner(v.slice(1, v.rows()-1), v.slice(1, v.rows()-1));\n      pacf(1) = 2./d(1) * inner(v.slice(1, v.rows()-1), u.slice(0, u.rows()-1));\n\n      Vector last_u(u.rows());\n      Vector last_v(u.rows());\n      for(UInt i=1; i<order; i++)\n      {\n        swap(u, last_u);\n        swap(v, last_v);\n        copy(last_u.slice(0, last_u.rows()-1) - pacf(i) * last_v.slice(1, last_v.rows()-1), u.slice(1, u.rows()-1));\n        copy(last_v.slice(1, last_v.rows()-1) - pacf(i) * last_u.slice(0, last_u.rows()-1), v.slice(1, v.rows()-1));\n        d(i+1)    = (1 - pacf(i)*pacf(i)) * d(i) - v(i)*v(i) - u(u.rows()-1)*u(u.rows()-1);\n        pacf(i+1) = 2/d(i+1) * inner(v.slice(i+1, v.rows()-i-1), u.slice(i, u.rows()-i-1));\n      }\n      // Solve coefficients with levinson\n      // first coefficient of pacf is always 1 and not necessary\n      pacf = pacf.slice(1, pacf.rows()-1);\n\n      Vector arCoeffs = pacf;\n      for(UInt i=1; i<order; i++)\n      {\n        Vector prev = arCoeffs.slice(0, arCoeffs.rows() - (order-i));\n        std::vector<UInt> prevIdx(prev.rows());\n        std::iota(prevIdx.begin(), prevIdx.end(), 0);\n        std::reverse(prevIdx.begin(), prevIdx.end());\n        Vector prevReverse = reorder(prev, prevIdx);\n        Vector temp = prev;\n        temp -= arCoeffs(i) * prevReverse;\n        copy(temp, arCoeffs.slice(0, arCoeffs.rows()-(order-i)));\n      }\n\n      // compute forward/backwards prediction error\n      // could also be done with slicing stuff but I think this is\n      // easier to understand\n      // Formula: x(t) - phi_1*x(t-1) - phi_2*x(t-2) - phi_3*x(t-3) = e_forward\n      //          x(t-3) - phi_1*x(t-2) - phi_2*x(t-1) - phi_3*x(t) = e_backward\n      // AR coefficients should be the same according to a lot of conditions which\n      // would theoretically need to be checked but honestly its not necessary\n      // for this scenarios.\n      Vector eForward(x.rows()-order);\n      Vector eBackward(x.rows()-order);\n      for(UInt i=0; i<x.rows()-order; i++)\n      {\n        eForward(i)  = x(i+order);\n        eBackward(i) = x(x.rows()-order-i-1);\n        for(UInt k=1; k<=order; k++)\n        {\n          eForward(i)  += (-1. * arCoeffs(k-1) * x(i+order-k));\n          eBackward(i) += (-1. * arCoeffs(k-1) * x(x.rows()-i-order-1+k));\n        }\n      }\n\n      std::vector<UInt> reverseIdx(eBackward.rows());\n      std::iota(reverseIdx.begin(), reverseIdx.end(), 0);\n      std::reverse(reverseIdx.begin(), reverseIdx.end());\n      eBackward = reorder(eBackward, reverseIdx);\n\n      // peak deteciton with the forward/backward prediction error.\n      // automatic threshold scaling via MAD is used to prevent excessive\n      // splitting during periods with high ionospheric variations/scintillations\n      // Only if a jump in forward and backward occur a jump is decided to be true\n      // in case of the first n-th windowsize samples only the backwards error decides\n      // in case of the last n-th windowsize samples on the forward error decides\n      // this is due to the median and MAD otherwise loosing p-order values for the MAD etc\n      // Also this enables to check all values for a cycleslip except the first and last value in the ts\n      // slipsdetect contain the detection value for each epoch of the obs.\n      // incase a jump in forward or backward is detected will add +1 ont hat respective idx\n      // Jump is concluded to be a real jump incase forward nad backward detect a jump and the reuslt is 3\n      std::vector<UInt> slipsDetect(eForward.rows() + order + 1, 0);\n      for(UInt i=0; i<eForward.size(); i++)\n      {\n        MatrixSlice currentWindowForward  = eForward.row (std::min(std::max(i, windowSize/2)-windowSize/2, eForward.rows()-windowSize), windowSize);\n        MatrixSlice currentWindowBackward = eBackward.row(std::min(std::max(i, windowSize/2)-windowSize/2, eForward.rows()-windowSize), windowSize);\n        const Double medForw = median(currentWindowForward);\n        const Double medBack = median(currentWindowBackward);\n        const Double MADForw = tecSigmaFactor*1.4826*medianAbsoluteDeviation(currentWindowForward);\n        const Double MADBack = tecSigmaFactor*1.4826*medianAbsoluteDeviation(currentWindowBackward);\n        const UInt   idxForw = i+order+1; // These decribe the idx of the undifferenced timeseries btw\n        const UInt   idxBack = i;\n\n        // 2 different ifs required since the forward idx is not the same as the backwards idx\n        if((std::abs(eForward(i)-medForw) > 0.9) && (std::abs(eForward(i)-medForw) > MADForw))\n        {\n          // In case we are in the last window size only use forward prediction error as slip detection\n          // doing this since the MAD is worse estimated for backwards prediction error due to missing values\n          if(idxForw > slips.size()-windowSize)\n            slipsDetect.at(idxForw) += 3;\n\n          if((idxForw >= windowSize) && (idxForw <= slips.size()-windowSize))\n            slipsDetect.at(idxForw) += 2;\n        }\n        // Since this goes backwards add +1 to the idxBack to be consistent with the jump idx from forward\n        if((std::abs(eBackward(i)-medBack) > 0.9) && (std::abs(eBackward(i)-medBack) > MADBack))\n        {\n          // in case we are in the first window size only use backward prediction error as slip detection\n          if(idxBack < windowSize)\n            slipsDetect.at(idxBack+1) += 3;\n\n          if((idxBack >= windowSize) && (idxBack <= slips.size()-windowSize))\n            slipsDetect.at(idxBack+1) += 1;\n        }\n      }\n\n      std::vector<UInt> slips;\n      for(UInt i = 0; i < slipsDetect.size(); i++)\n        if(slipsDetect.at(i) == 3)\n          slips.push_back(i);\n\n      for(UInt i=slips.size(); i-->0;)\n      {\n        splitTrack(eqnList, track, idEpochs.at(slips.at(i)));\n        idEpochs.resize(slips.at(i)); // shorten data to new track length\n      }\n    }\n\n    // repair GPS L5 cycle slips\n    // -------------------------\n    for(GnssType type : extraTypes)\n    {\n      const UInt   idTrans    = track->transmitter->idTrans();\n      const Double wavelength = wavelengthFactor * type.wavelength();\n      const Double TEC        = type.ionosphericFactor();\n      for(UInt idType=0; idType<track->types.size(); idType++)\n        if(track->types.at(idType) == type)\n        {\n          // reduce l by estimated range and tec\n          Vector l(idEpochs.size());\n          for(UInt i=0; i<idEpochs.size(); i++)\n            l(i) = eqnList(idTrans, idEpochs.at(i))->l(GnssType::index(eqnList(idTrans, idEpochs.at(i))->types, track->types.at(idType))) - range(i) - TEC * tec(i);\n\n          // fix jumps\n          Double jump = 0;\n          for(UInt i=1; i<l.rows(); i++)\n          {\n            jump += wavelength * std::round((l(i)-l(i-1))/wavelength);\n            eqnList(idTrans, idEpochs.at(i))->l(GnssType::index(eqnList(idTrans, idEpochs.at(i))->types, track->types.at(idType))) -= jump;\n            observation(idTrans, idEpochs.at(i))->at(track->types.at(idType)).observation -= jump;\n          }\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::cycleSlipsRepairAtSameFrequency(ObservationEquationList &eqnList)\n{\n  try\n  {\n    // get all phase types\n    std::vector<GnssType> types;\n    for(const auto &track : tracks)\n      for(GnssType type : track->types)\n        if((type == GnssType::PHASE) && !type.isInList(types))\n          types.push_back(type & ~GnssType::PRN);\n    std::sort(types.begin(), types.end());\n\n    // find two phase observations with same system and frequency\n    for(UInt idType=1; idType<types.size(); idType++)\n      for(UInt idType1=0; idType1<idType; idType1++)\n        if(types.at(idType) == (types.at(idType1) & ~GnssType::ATTRIBUTE))\n        {\n          const Double wavelength = types.at(idType).wavelength();\n          // compute difference\n          std::vector<UInt>   idxTrans, idxEpoch;\n          std::vector<Double> values;\n          for(UInt idEpoch=0; idEpoch<idEpochSize(); idEpoch++)\n            for(UInt idTrans=0; idTrans<idTransmitterSize(idEpoch); idTrans++)\n              if(observation(idTrans, idEpoch))\n              {\n                const GnssObservationEquation &eqn = *eqnList(idTrans, idEpoch);\n                UInt idx, idx1;\n                if(!types.at(idType).isInList(eqn.types, idx) || !types.at(idType1).isInList(eqn.types, idx1))\n                  continue;\n                idxTrans.push_back(idTrans);\n                idxEpoch.push_back(idEpoch);\n                values.push_back((eqn.l(idx)-eqn.l(idx1))/wavelength); // diff in cycles\n              }\n\n          if(!values.size())\n            continue;\n\n          // consider bias (e.g. quarter cycles)\n          Vector v0s(values.size());\n          for(UInt i=0; i<values.size(); i++)\n            v0s(i) = values.at(i)-std::round(values.at(i));\n          const Double v0 = computeBias(v0s, 0.05);\n\n          // fix jumps\n          for(UInt i=0; i<values.size(); i++)\n          {\n            const Double v = wavelength * std::round(values.at(i) - v0);\n            GnssObservationEquation &eqn = *eqnList(idxTrans.at(i), idxEpoch.at(i));\n            eqn.l(GnssType::index(eqn.types, types.at(idType))) -= v;\n            observation(idxTrans.at(i), idxEpoch.at(i))->at(types.at(idType)).observation -= v;\n          }\n        } // for(idType)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiver::trackOutlierDetection(const ObservationEquationList &eqnList, const std::vector<GnssType> &ignoreTypes, Double huber, Double huberPower)\n{\n  try\n  {\n    for(auto track : tracks)\n    {\n      const UInt idTrans      = track->transmitter->idTrans();\n      const UInt idEpochStart = track->idEpochStart;\n      const UInt idEpochEnd   = track->idEpochEnd;\n\n      // available observations for this track\n      std::vector<GnssType> types;\n      for(UInt idEpoch=idEpochStart; idEpoch<=idEpochEnd; idEpoch++)\n        if(observation(idTrans, idEpoch))\n          for(const GnssType &type : eqnList(idTrans, idEpoch)->types)\n            if(!type.isInList(types))\n              types.push_back(type);\n\n      // determine estimable biases (reduced by range and TEC)\n      Matrix Bias = identityMatrix(types.size());\n      Matrix B(types.size(), 2);\n      for(UInt idType=0; idType<types.size(); idType++)\n        if(types.at(idType) == GnssType::RANGE)\n        {\n          B(idType, 0) = 1.; //range\n          B(idType, 1) = types.at(idType).ionosphericFactor(); // TEC\n        }\n      const Vector tau = QR_decomposition(B);\n      QMult(B, tau, Bias);\n      Bias = Bias.column(B.columns(), Bias.rows()-B.columns());\n\n      // setup observation equations: range, TEC, ambiguities\n      // ----------------------------------------------------\n      std::vector<Matrix> listl, listA;\n      std::vector<UInt>   listEpoch;\n      for(UInt idEpoch=idEpochStart; idEpoch<=idEpochEnd; idEpoch++)\n        if(observation(idTrans, idEpoch))\n        {\n          const GnssObservationEquation &eqn = *eqnList(idTrans, idEpoch);\n\n          // observations\n          Vector l = eqn.l;\n\n          // distance and TEC\n          Matrix B(l.rows(), 2);\n          copy(eqn.A.column(GnssObservationEquation::idxRange), B.column(0));\n          copy(eqn.A.column(GnssObservationEquation::idxSTEC),  B.column(1));\n\n          // signal biases (includes ambiguities)\n          UInt idx;\n          Matrix A(l.rows(), Bias.columns());\n          for(UInt idType=0; idType<eqn.types.size(); idType++)\n            if(eqn.types.at(idType).isInList(types, idx))\n              matMult(1., eqn.A.column(GnssObservationEquation::idxUnit+idType), Bias.row(idx), A);\n\n          // homogenize\n          for(UInt i=0; i<l.rows(); i++)\n          {\n            l(i)     *= 1./eqn.sigma(i);\n            A.row(i) *= 1./eqn.sigma(i);\n            B.row(i) *= 1./eqn.sigma(i);\n          }\n\n          // downweight ignored types\n          for(UInt idType=0; idType<eqn.types.size(); idType++)\n            if(eqn.types.at(idType).isInList(ignoreTypes))\n            {\n              l(idType)     *= 1e-3;\n              A.row(idType) *= 1e-3;\n              B.row(idType) *= 1e-3;\n            }\n\n          eliminationParameter(B, A, l);\n          listEpoch.push_back(idEpoch);\n          listl.push_back(l);\n          listA.push_back(A);\n        } // for(idEpoch)\n\n      // copy equations in one system\n      // ----------------------------\n      const UInt count = std::accumulate(listl.begin(), listl.end(), UInt(0), [](UInt sum, const auto &x) {return sum+x.size();});\n      Vector l(count);\n      Matrix A(count, Bias.columns());\n      std::vector<UInt> index({0});\n      for(UInt i=0; i<listl.size(); i++)\n      {\n        const UInt idx = index.back();\n        copy(listl.at(i), l.row(idx, listl.at(i).rows()));\n        copy(listA.at(i), A.row(idx, listA.at(i).rows()));\n        index.push_back(idx+listA.at(i).rows());\n      }\n\n      // estimate solution\n      // -----------------\n      Vector sigma;\n      Vector x = Vce::robustLeastSquares(A, l, index, huber, huberPower, 30, sigma);\n\n      // downweight outliers\n      // -------------------\n      for(UInt i=0; i<listEpoch.size(); i++)\n      {\n        const GnssObservationEquation &eqn = *eqnList(idTrans, listEpoch.at(i));\n        GnssObservation &obs = *observation(idTrans, listEpoch.at(i));\n        for(UInt idType=0; idType<eqn.types.size(); idType++)\n          obs.at(eqn.types.at(idType)).sigma *= sigma(i);\n      }\n\n      // reduce integer ambiguities\n      // --------------------------\n      Vector b = Bias * x;\n      for(UInt idType=0; idType<types.size(); idType++)\n        if(types.at(idType) == GnssType::PHASE)\n        {\n          const Double lambda = types.at(idType).wavelength();\n          b(idType) = lambda * std::round(b(idType)/lambda);\n          for(UInt i=0; i<listEpoch.size(); i++)\n          {\n            eqnList(idTrans, listEpoch.at(i))->l(GnssType::index(eqnList(idTrans, listEpoch.at(i))->types, types.at(idType))) -= b(idType);\n            observation(idTrans, listEpoch.at(i))->at(types.at(idType)).observation -= b(idType);\n          }\n        }\n    } // for(track)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Total variation denoising algorithm source:\n// Laurent Condat. A Direct Algorithm for 1D Total Variation Denoising. IEEE Signal Processing Letters,\n// Institute of Electrical and Electronics Engineers, 2013, 20 (11), pp.1054-1057. DOI: 10.1109/LSP.2013.2278339.\nMatrix GnssReceiver::totalVariationDenoising(const_MatrixSliceRef y, Double lambda)\n{\n  try\n  {\n    Matrix x(y.rows(), y.columns());\n    for(UInt col=0; col<y.columns(); col++)\n    {\n      // initialize total variation denoising algorithm\n      UInt N = y.rows()-1;\n      UInt k  = 0;                      // current sample location\n      UInt k0 = 0;                      // beginning of current segment\n      UInt km = 0;                      // last position where umax = -lambda\n      UInt kp = 0;                      // last position where umin =  lambda\n      Double vMin = y(0, col) - lambda; // lower bound for the segment's value\n      Double vMax = y(0, col) + lambda; // upper bound for the segment's value\n      Double uMin =  lambda;            // u is the dual variable\n      Double uMax = -lambda;            // u is the dual variable\n\n      // total variation denoising algorithm\n      for(;;)\n      {\n        if(k == N)\n        {\n          x(N, col) = vMin + uMin;\n          break;\n        }\n\n        if(y(k+1, col) + uMin < vMin - lambda)      // negative jump necessary\n        {\n          for(UInt i=k0; i<=km; i++)\n            x(i, col) = vMin;\n          k = k0 = km = kp = km+1;\n          vMin = y(k, col);\n          vMax = y(k, col) + 2*lambda;\n          uMin =  lambda;\n          uMax = -lambda;\n        }\n        else if(y(k+1, col) + uMax > vMax + lambda) // positive jump necessary\n        {\n          for(UInt i=k0; i<=kp; i++)\n            x(i, col) = vMax;\n          k = k0 = km = kp = kp+1;\n          vMin = y(k, col) - 2*lambda;\n          vMax = y(k, col);\n          uMin =  lambda;\n          uMax = -lambda;\n        }\n        else  // no jump necessary\n        {\n          k = k+1;\n          uMin = uMin + y(k, col) - vMin;\n          uMax = uMax + y(k, col) - vMax;\n          if(uMin >= lambda)  // update of vMin\n          {\n            vMin = vMin + (uMin-lambda)/(k-k0+1);\n            uMin = lambda;\n            km = k;\n          }\n          if(uMax <= -lambda) // update of vMax\n          {\n            vMax = vMax + (uMax+lambda)/(k-k0+1);\n            uMax = -lambda;\n            kp = k;\n          }\n        }\n\n        if(k < N)\n          continue;\n\n        if(uMin < 0.)       // vMin is too high ==> negative jump necessary\n        {\n          for(UInt i=k0; i<=km; i++)\n            x(i, col) = vMin;\n          k = k0 = km = km+1;\n          vMin = y(k, col);\n          uMin = lambda;\n          uMax = y(k, col) + lambda - vMax;\n          continue;\n        }\n        else if(uMax > 0.)  // vMax is too low ==> positive jump necessary\n        {\n          for(UInt i=k0; i<=kp; i++)\n            x(i, col) = vMax;\n          k = k0 = kp = kp+1;\n          vMax = y(k, col);\n          uMax = -lambda;\n          uMin = y(k, col) - lambda - vMin;\n          continue;\n        }\n        else\n        {\n          for(UInt i=k0; i<=N; i++)\n            x(i, col) = vMin + uMin/(k-k0+1);\n          break;\n        }\n      }\n    }\n\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGnssTrack::GnssTrack(GnssReceiver *_receiver, GnssTransmitter *_transmitter, UInt _idEpochStart, UInt _idEpochEnd, const std::vector<GnssType> &_types) :\n    receiver(_receiver), transmitter(_transmitter), idEpochStart(_idEpochStart), idEpochEnd(_idEpochEnd), types(_types), ambiguity(nullptr)\n{\n}\n\n/***********************************************/\n\nGnssTrack::~GnssTrack()\n{\n  delete ambiguity;\n}\n\n/***********************************************/\n\nUInt GnssTrack::countObservations() const\n{\n  try\n  {\n    UInt count = 0;\n    for(UInt idEpoch=idEpochStart; idEpoch<=idEpochEnd; idEpoch++)\n      if(transmitter->useable(idEpoch) && receiver->observation(transmitter->idTrans(), idEpoch))\n        count++;\n    return count;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssTrack::removeAmbiguitiesFromObservations(const std::vector<GnssType> &types, const std::vector<Double> &value)\n{\n  try\n  {\n    for(UInt idEpoch=idEpochStart; idEpoch<=idEpochEnd; idEpoch++)\n      if(receiver->observation(transmitter->idTrans(), idEpoch))\n      {\n        GnssObservation &obs = *receiver->observation(transmitter->idTrans(), idEpoch);\n        UInt idx;\n        for(UInt idType=0; idType<obs.size(); idType++)\n          if(obs.at(idType).type.isInList(types, idx))\n            obs.at(idType).observation -= value.at(idx);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssReceiver.h",
    "content": "/***********************************************/\n/**\n* @file gnssReceiver.h\n*\n* @brief GNSS receiver.\n*\n* @author Torsten Mayer-Guerr\n* @author Norbert Zehentner\n* @author Sebastian Strasser\n* @date 2013-06-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSRECEIVER__\n#define __GROOPS_GNSSRECEIVER__\n\n#include \"files/fileInstrument.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"gnss/gnssObservation.h\"\n#include \"gnss/gnssTransceiver.h\"\n#include \"gnss/gnssTransmitter.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass GnssReceiver;\nclass GnssTrack;\ntypedef std::shared_ptr<GnssReceiver> GnssReceiverPtr;\ntypedef std::shared_ptr<GnssTrack>    GnssTrackPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for GNSS receiver.\n* eg. permanent stations or LEOs. */\nclass GnssReceiver : public GnssTransceiver\n{\n  std::vector<GnssObservation> obsMem;\n  std::vector<std::vector<GnssObservation*>> observations_; // observations at receiver (for each epoch, for each transmitter)\n\n  void copyObservations2ContinuousMemoryBlock();\n\npublic:\n  // public variables\n  // ----------------\n  Bool                      isMyRank_, isEarthFixed_;\n  std::vector<Time>         times;\n  std::vector<Double>       clk;\n  std::vector<Vector3d>     pos, vel;  // regularized marker pos in global system\n  std::vector<Vector3d>     offset;    // pos to ARF in local system\n  std::vector<Transform3d>  global2local, global2antenna;\n  std::vector<GnssTrackPtr> tracks;   // tracking phase observations\n  Double                    observationSampling;\n  Bool                      integerAmbiguities;\n  Double                    wavelengthFactor; // Factor to account for half-wavelength observations (collected by codeless squaring techniques).\n  std::vector<std::string>  preprocessingInfos;\n  std::string               disableReason;\n\n  GnssReceiver(Bool isMyRank, Bool isEarthFixed, const Platform &platform,\n               GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction, const Vector &useableEpochs,\n               Bool integerAmbiguities, Double wavelengthFactor);\n\n  /// Destructor.\n ~GnssReceiver() {}\n\n  /** @brief Identify number in the GNSS system. */\n  UInt  idRecv() const {return id_;}\n\n  /** @brief Disable given epoch (or all epochs). */\n  void disable(UInt idEpoch, const std::string &reason) override;\n\n  /** @brief Disable receiver completely. */\n  void disable(const std::string &reason) override;\n\n  Bool isMyRank() const {return isMyRank_;}\n\n  /** @brief Clock error.\n  * error = clock time - system time [s] */\n  Double clockError(UInt idEpoch) const {return clk.at(idEpoch);}\n\n  /** @brief set clock error.\n  * error = observed clock time - system time [s] */\n  void updateClockError(UInt idEpoch, Double deltaClock) {clk.at(idEpoch) += deltaClock;}\n\n  /** @brief Estimated system time of received signals.\n  * (receiver clock time - clock error) */\n  Time timeCorrected(UInt idEpoch) const {return times.at(idEpoch) - seconds2time(clockError(idEpoch));}\n\n  /** @brief Positions, velocities and orientations are given in the terrestrial reference frame. */\n  Bool isEarthFixed() const {return isEarthFixed_;}\n\n  /** @brief antenna reference point in TRF or CRF. */\n  Vector3d position(UInt idEpoch) const {return pos.at(idEpoch) + global2local.at(idEpoch).inverseTransform(offset.at(idEpoch));}\n\n  /** @brief velocity in TRF or CRF [m/s]. */\n  Vector3d velocity(UInt idEpoch) const {return vel.at(idEpoch);}\n\n  /** @brief Rotation from terrestrial reference frame (TRF) or celestial reference frame (CRF) to local horizont system (north, east, up). */\n  Transform3d global2localFrame(UInt idEpoch) const {return global2local.at(idEpoch);}\n\n  /** @brief Rotation from terrestrial reference frame (TRF) or celestial reference frame (CRF) to left-handed antenna system (usually north, east, up). */\n  Transform3d global2antennaFrame(UInt idEpoch) const {return global2antenna.at(idEpoch);}\n\n  /** @brief Transformation matrix for observed (composed) types from original transmitted types.\n  * E.g. C2DG = C1CG - C1WG + C2WG.\n  * Returns the @a typesTrans and the transformation matrix @a A (dimension: types.size() times typesTrans.size()). */\n  virtual void signalComposition(UInt /*idEpoch*/, const std::vector<GnssType> &types, std::vector<GnssType> &typesTrans, Matrix &A) const;\n\n  /** @brief All observations between receiver and transmitter at one epoch. */\n  GnssObservation *observation(UInt idTrans, UInt idEpoch) const;\n\n  /** @brief Max. observed epoch id +1. */\n  UInt idEpochSize() const {return observations_.size();}\n\n  /** @brief Max. observed transmitter id+1 at @a idEpoch. */\n  UInt idTransmitterSize(UInt idEpoch) const {return (idEpoch < observations_.size()) ? observations_.at(idEpoch).size() : 0;}\n\n  /** @brief Delete observation. */\n  void deleteObservation(UInt idTrans, UInt idEpoch);\n\n  /** @brief Delete all empty tracks (and ambiguities). */\n  void deleteEmptyTracks();\n\n  // Preprocessing\n  // -------------\n  /** @brief Compute observation equations (reduced observations). */\n  class ObservationEquationList\n  {\n    std::vector<std::vector<std::unique_ptr<GnssObservationEquation>>> eqn;\n\n  public:\n    ObservationEquationList() {}\n    ObservationEquationList(const GnssReceiver &receiver, const std::vector<GnssTransmitterPtr> &transmitters,\n                            const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                            const std::function<void(GnssObservationEquation &eqn)> &reduceModels, GnssObservation::Group group);\n\n    GnssObservationEquation *operator()(UInt idTrans, UInt idEpoch) const;\n  };\n\n  void preprocessingInfo(const std::string &info, UInt countEpochs=NULLINDEX, UInt countObservations=NULLINDEX, UInt countTracks=NULLINDEX);\n\n  /** @brief Reads observations from a file. Member variable @a times must be set.\n  * Initializes observations. Receiver and Transmitter positions, orientations, ... must be initialized beforehand.\n  * Delete observations that don't match the types from receiver and transmitter definition. */\n  void readObservations(const FileName &fileName, const std::vector<GnssTransmitterPtr> &transmitters, const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                        const Time &timeMargin, Angle elevationCutOff, const std::vector<GnssType> &useType, const std::vector<GnssType> &ignoreType, GnssObservation::Group group);\n\n  /** @brief Simulate observations. Member variable @a times must be set.\n  * Receiver and Transmitter positions, orientations, ... must be initialized beforehand.\n  * Delete observations that don't match the types from receiver and transmitter definition. */\n  void simulateZeroObservations(const std::vector<GnssType> &types,\n                                const std::vector<GnssTransmitterPtr> &transmitters,\n                                const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, Angle elevationCutOff,\n                                const std::vector<GnssType> &useType, const std::vector<GnssType> &ignoreType, GnssObservation::Group group);\n\n  /** @brief Simulate observations. Member variable @a times must be set.\n  * Receiver and Transmitter positions, orientations, ... must be initialized beforehand.\n  * Delete observations that don't match the types from receiver and transmitter definition. */\n  void simulateObservations(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                            const std::vector<GnssTransmitterPtr> &transmitters,\n                            const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                            const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                            UInt minObsCountPerTrack, Angle elevationTrackMinimum, GnssObservation::Group group);\n\n  /** @brief Estimate coarse receiver clock errors from a Precise Point Positioning (PPP) code solution.\n  * If @p estimateKinematicPosition is TRUE, the receiver position is estimated at each epoch, otherwise it is estimated once for all epochs.*/\n  std::vector<Vector3d> estimateInitialClockErrorFromCodeObservations(const std::vector<GnssTransmitterPtr> &transmitters,\n                                                                      const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                                                                      const std::function<void(GnssObservationEquation &eqn)> &reduceModels,\n                                                                      Double huber, Double huberPower, Bool estimateKinematicPosition);\n\n  /** @brief Disable epochs if reduced code observations @p eqn exceed @p threshold (e.g. 100+ km for code cycle slips).\n  * Disable receiver at epoch if @p outlierRatio or more of the observed satellites have gross code outliers. */\n  void disableEpochsWithGrossCodeObservationOutliers(ObservationEquationList &eqn, Double threshold, Double outlierRatio=0.5);\n\n  /** @brief Create tracks with continuously identical phase observations.\n  * Tracks may contain gaps but must contain observations in at least @p minObsCountPerTrack epochs.\n  * Extra types are included (e.g. L5*G), but tracks must have at least two others phases at different frequencies.*/\n  void createTracks(const std::vector<GnssTransmitterPtr> &transmitters, UInt minObsCountPerTrack, const std::vector<GnssType> &extraTypes={});\n\n  /** @brief delete track and all related observations. */\n  void deleteTrack(UInt idTrack);\n\n  /** @brief Removes tracks that never exceed @p minElevation (in radian). */\n  void removeLowElevationTracks(ObservationEquationList &eqn, Angle minElevation);\n\n  /** @brief Split a @p track at @p idEpochSplit into two new tracks.\n  * Shortens the old track and returns the new track. Updates observation and observation equation @p eqn track assignments. */\n  GnssTrackPtr splitTrack(ObservationEquationList &eqn, GnssTrackPtr track, UInt idEpochSplit);\n\n  void linearCombinations(ObservationEquationList &eqnList, GnssTrackPtr track, const std::vector<GnssType> &extraTypes,\n                          std::vector<GnssType> &typesPhase, std::vector<UInt> &idEpochs, Matrix &combinations, Double &cycles2tecu) const;\n\n  void rangeAndTec(ObservationEquationList &eqnList, UInt idTrans, const std::vector<UInt> &idEpochs,\n                   const std::vector<GnssType> &typesPhase, Vector &range, Vector &tec) const;\n\n  void writeTracks(const FileName &fileName, ObservationEquationList &eqnList, const std::vector<GnssType> &extraTypes) const;\n\n  /** @brief Splits tracks at detected cycle slips.\n  * Based on all Melbourne-Wuebbena like combinations.\n  * Solves the total variation regularized least-squares problem (total variation denoising).\n  * In a second step smoothness of TEC is evaluated using a moving window peak/outlier detection based on AR model residuals.\n  * @param eqnList Observation equations (reduced observations).\n  * @param minObsCountPerTrack Removes tracks that don't have enough observations.\n  * @param lambda Regularization parameter (@see @a totalVariationDenoising) (e.g. @p lambda = 5 for GPS ground stations).\n  * @param windowSize Size of the moving window used for the TEC smoothness evaluation. If 0, TEC is not analyzed.\n  * @param tecSigmaFactor Factor applied to moving standard deviation of AR model residuals to determine threshold for peak/outlier detection.\n  * @param extraTypes GPS L5 observations are handled separately due to temporal changing bias.*/\n  void cycleSlipsDetection(ObservationEquationList &eqnList, UInt minObsCountPerTrack, Double lambda, UInt windowSize, Double tecSigmaFactor, const std::vector<GnssType> &extraTypes={});\n  void cycleSlipsDetection(ObservationEquationList &eqnList, GnssTrackPtr track, Double lambda, UInt windowSize, Double tecSigmaFactor, const std::vector<GnssType> &extraTypes);\n\n  /** @brief repair cycle slip differences at same frequencies (e.g. between L1CG and L1WG).\n  * Allows to reduce the number of integer ambiguities.\n  * @param eqnList Observation equations (reduced observations). */\n  void cycleSlipsRepairAtSameFrequency(ObservationEquationList &eqnList);\n\n  /** @brief Track outlier detection based on robust least squares estimation.\n  * Downweights outliers and prereduces observations by estimated integer ambiguities. */\n  void trackOutlierDetection(const ObservationEquationList &eqn, const std::vector<GnssType> &ignoreTypes, Double huber, Double huberPower);\n\n  /** @brief Total variation denoising.\n  * Solves the total variation regularized least-squares problem.\n  * Laurent Condat. A Direct Algorithm for 1D Total Variation Denoising. IEEE Signal Processing Letters,\n  * Institute of Electrical and Electronics Engineers, 2013, 20 (11), pp.1054-1057. DOI: 10.1109/LSP.2013.2278339.\n  * @param y noisy input time series.\n  * @param lambda Regularization parameter.\n  * @return denoised time series. */\n  static Matrix totalVariationDenoising(const_MatrixSliceRef y, Double lambda);\n}; //class GnssReceiver\n\n/***** CLASS ***********************************/\n\nclass GnssAmbiguity;\n\n/** @brief Class for tracking phases and ranges along epochs. */\nclass GnssTrack\n{\npublic:\n  GnssReceiver         *receiver;\n  GnssTransmitter      *transmitter;\n  UInt                  idEpochStart, idEpochEnd;\n  std::vector<GnssType> types;\n  GnssAmbiguity        *ambiguity;\n\n  GnssTrack(GnssReceiver *_receiver, GnssTransmitter *_transmitter, UInt _idEpochStart, UInt _idEpochEnd, const std::vector<GnssType> &_types);\n ~GnssTrack();\n\n  UInt countObservations() const;\n  void removeAmbiguitiesFromObservations(const std::vector<GnssType> &type, const std::vector<Double> &value);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for ambiguities.\n* @a track is owns this class and delete ambiguity when destructed. */\nclass GnssAmbiguity\n{\npublic:\n  GnssTrack *track;\n\n  explicit GnssAmbiguity(GnssTrack *track) : track(track) {track->ambiguity = this;}\n  virtual ~GnssAmbiguity() {}\n  virtual Vector ambiguities(const std::vector<GnssType> &type) const = 0;\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssReceiverGenerator/gnssReceiverGenerator.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverGenerator.cpp\n*\n* @brief Provides a list of receivers.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_GnssReceiverGenerator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGeneratorStationNetwork.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGeneratorLowEarthOrbiter.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(GnssReceiverGenerator, \"gnssReceiverGeneratorType\",\n                      GnssReceiverGeneratorStationNetwork,\n                      GnssReceiverGeneratorLowEarthOrbiter)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(GnssReceiverGenerator, \"gnssReceiverGeneratorType\")\n\n/***********************************************/\n\nGnssReceiverGenerator::GnssReceiverGenerator(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"stationNetwork\", type, \"\"))\n        base.push_back(new GnssReceiverGeneratorStationNetwork(config));\n      if(readConfigChoiceElement(config, \"lowEarthOrbiter\", type, \"\"))\n        base.push_back(new GnssReceiverGeneratorLowEarthOrbiter(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssReceiverGenerator::~GnssReceiverGenerator()\n{\n  for(UInt i=0; i<base.size(); i++)\n    delete base.at(i);\n}\n\n/***********************************************/\n\nstd::vector<GnssReceiverPtr> GnssReceiverGenerator::receivers(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n                                                              const std::vector<GnssTransmitterPtr> &transmitters,\n                                                              EarthRotationPtr earthRotation, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<GnssReceiverPtr> receivers;\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->init(simulationTypes, times, timeMargin, transmitters, earthRotation, comm, receivers);\n    return receivers;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGenerator::preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->preprocessing(gnss, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGenerator::simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                                       Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->simulation(noiseClock, noiseObs, gnss, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid GnssReceiverGeneratorBase::printPreprocessingInfos(const std::string &header, const std::vector<GnssReceiverPtr> &receivers,\n                                                        Bool disabledOnly, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    // distribute process id of receivers\n    // ----------------------------------\n    Vector recvProcess(receivers.size());\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      if(receivers.at(idRecv)->isMyRank() || !receivers.at(idRecv)->disableReason.empty())\n        recvProcess(idRecv) = Parallel::myRank(comm)+1;\n    Parallel::reduceSum(recvProcess, 0, comm);\n    Parallel::broadCast(recvProcess, 0, comm);\n\n    // preprocessing infos\n    // -------------------\n    for(UInt idRecv=0; idRecv<receivers.size(); idRecv++)\n      if(recvProcess(idRecv))\n      {\n        std::string              reason = receivers.at(idRecv)->disableReason;\n        std::vector<std::string> infos  = receivers.at(idRecv)->preprocessingInfos;\n        if(recvProcess(idRecv) > 1)\n        {\n          if(recvProcess(idRecv)-1 == Parallel::myRank(comm))\n          {\n            Parallel::send(reason, 0, comm);\n            Parallel::send(infos,  0, comm);\n          }\n          if(Parallel::isMaster(comm))\n          {\n            Parallel::receive(reason, static_cast<UInt>(recvProcess(idRecv)-1), comm);\n            Parallel::receive(infos,  static_cast<UInt>(recvProcess(idRecv)-1), comm);\n          }\n        }\n\n        if(Parallel::isMaster(comm) && !(disabledOnly && reason.empty()))\n        {\n          logInfo<<receivers.at(idRecv)->name()<<\": \"<<header<<Log::endl;\n          if(!reason.empty())\n            logWarning<<receivers.at(idRecv)->name()<<\" disabled: \"<<reason<<Log::endl;\n          for(auto &info : infos)\n            logInfo<<\"  \"<<info<<Log::endl;\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssReceiverGenerator/gnssReceiverGenerator.h",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverGenerator.h\n*\n* @brief Provides a list of receivers.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSRECEIVERGENERATOR__\n#define __GROOPS_GNSSRECEIVERGENERATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssReceiverGenerator\nstatic const char *docstringGnssReceiverGenerator = R\"(\n\\section{GnssReceiverGenerator}\\label{gnssReceiverGeneratorType}\nDefinition and basic information of GNSS receivers.\n\nMost of the input files are provided in GROOPS file formats at\n\\url{https://ftp.tugraz.at/pub/ITSG/groops} (marked with \\textbf{*} below).\nThese files are regularly updated.\n\\begin{itemize}\n  \\item \\configFile{inputfileStationInfo}{platform}\\textbf{*}:\n        Antenna and receiver information, antenna reference point offsets, antenna orientations.\n        Created via \\program{GnssStationLog2Platform} or \\program{PlatformCreate}.\n  \\item \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\\textbf{*}:\n        Antenna center offsets and variations.\n        Created via \\program{GnssAntex2AntennaDefinition} or \\program{GnssAntennaDefinitionCreate}.\n  \\item \\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition}:\n        Observed signal types (optional).\n        Created via \\program{GnssReceiverDefinitionCreate} in case you want to define which signal\n        types a receiver model can observe.\n  \\item \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition}\\textbf{*}:\n        Elevation and azimuth dependent accuracy.\n        Created via \\program{GnssAntennaDefinitionCreate}.\n  \\item \\configFile{inputfileObservation}{instrument}:\n        Converted from RINEX observation files via \\program{RinexObservation2GnssReceiver}.\n\\end{itemize}\n\nIt is possible to limit the observation types to be used in the processing by a list of \\configClass{useType}{gnssType}\nand any observation types not defined within the list are ignored and discarded.\nSimilarly observations defined in the list of \\configClass{ignoreType}{gnssType} are ignored and discarded.\nThe codes used follow the \\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition}.\n\nEach receiver goes through a \\config{preprocessing} step individually, where observation outliers are removed or downweighted,\ncontinuous tracks of phase observations are defined for ambiguity parametrization, cycle slips are detected, and receivers are\ndisabled if they do not fulfill certain requirements. The preprocessing step consists of an initial PPP estimation done by\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares} and checks whether the position error\nof the solutions exceeds \\config{codeMaxPositionDiff}. If the error exceeds the threshold the receiver will be discarded.\nThe preprocessing also sets initial clock error values and removes tracks that stay below a certain elevation mask (\\config{elevationTrackMinimum}).\n\nSee also \\program{GnssProcessing} and \\program{GnssSimulateReceiver}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssTransmitter.h\"\n\n/**\n* @defgroup gnssReceiverGeneratorGroup GnssReceiverGenerator\n* @brief Provides a list of receivers.\n* @ingroup classesGroup\n* The interface is given by @ref GnssReceiverGenerator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Gnss;\nclass GnssReceiverGenerator;\nclass GnssReceiverGeneratorBase;\ntypedef std::shared_ptr<GnssReceiverGenerator> GnssReceiverGeneratorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of receivers.\n* An Instance of this class can be created by @ref readConfig. */\nclass GnssReceiverGenerator\n{\n  std::vector<GnssReceiverGeneratorBase*> base;\n\npublic:\n  /** @brief Constructor from config. */\n  GnssReceiverGenerator(Config &config, const std::string &name);\n\n  /// Destructor.\n ~GnssReceiverGenerator();\n\n  /** @brief Iniatialize and returns a vector of receivers. */\n  std::vector<GnssReceiverPtr> receivers(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n                                         const std::vector<GnssTransmitterPtr> &transmitters, EarthRotationPtr earthRotation,\n                                         Parallel::CommunicatorPtr comm);\n\n  /** @brief preprocess the observations of receivers. */\n  void preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm);\n\n  /** @brief simulate the observations of receivers. */\n  void simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                  Gnss *gnss, Parallel::CommunicatorPtr comm);\n\n  /** @brief creates an derived instance of this class. */\n  static GnssReceiverGeneratorPtr create(Config &config, const std::string &name) {return GnssReceiverGeneratorPtr(new GnssReceiverGenerator(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class GnssReceiverGenerator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates GnssReceiverGenerator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssReceiverGeneratorPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass GnssReceiverGeneratorBase\n{\npublic:\n  virtual ~GnssReceiverGeneratorBase() {}\n\n  virtual void init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n                    const std::vector<GnssTransmitterPtr> &transmitters, EarthRotationPtr earthRotation,\n                    Parallel::CommunicatorPtr comm, std::vector<GnssReceiverPtr> &receivers) = 0;\n\n  virtual void preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm) = 0;\n\n  virtual void simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                          Gnss *gnss, Parallel::CommunicatorPtr comm) = 0;\n\n  static void printPreprocessingInfos(const std::string &header, const std::vector<GnssReceiverPtr> &receivers,\n                                      Bool disabledOnly, Parallel::CommunicatorPtr comm);\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssReceiverGenerator/gnssReceiverGeneratorLowEarthOrbiter.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverGeneratorLowEarthOrbiter.cpp\n*\n* @brief GNSS for Low Earth Orbiter (LEO).\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGeneratorLowEarthOrbiter.h\"\n\n/***********************************************/\n\nGnssReceiverGeneratorLowEarthOrbiter::GnssReceiverGeneratorLowEarthOrbiter(Config &config)\n{\n  try\n  {\n    std::string choice;\n\n    readConfig(config, \"inputfileStationInfo\",         fileNameStationInfo,     Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\", \"satellite metadata (antenna, receiver, ...)\");\n    readConfig(config, \"inputfileAntennaDefinition\",   fileNameAntennaDef,      Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\", \"antenna center offsets and variations\");\n    if(readConfigChoice(config, \"noAntennaPatternFound\", choice, Config::MUSTSET, \"ignoreObservation\", \"what should happen if no antenna pattern is found for an observation\"))\n    {\n      if(readConfigChoiceElement(config, \"ignoreObservation\",   choice, \"ignore observation if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::IGNORE_OBSERVATION;\n      if(readConfigChoiceElement(config, \"useNearestFrequency\", choice, \"use pattern of nearest frequency if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::USE_NEAREST_FREQUENCY;\n      if(readConfigChoiceElement(config, \"throwException\",      choice, \"throw exception if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::THROW_EXCEPTION;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileReceiverDefinition\",  fileNameReceiverDef,     Config::OPTIONAL, \"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\", \"observed signal types\");\n    readConfig(config, \"inputfileAccuracyDefinition\",  fileNameAccuracyDef,     Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverLowEarthOrbiter/\", \"elevation and azimut dependent accuracy\");\n    readConfig(config, \"inputfileObservations\",        fileNameObs,             Config::OPTIONAL,  \"gnssReceiver_{loopTime:%D}.dat\", \"\");\n    readConfig(config, \"inputfileOrbit\",               fileNameOrbit,           Config::MUSTSET,  \"\",     \"approximate positions\");\n    readConfig(config, \"inputfileStarCamera\",          fileNameStarCamera,      Config::MUSTSET,  \"\",     \"satellite attitude\");\n    readConfig(config, \"sigmaFactorPhase\",             exprSigmaPhase,          Config::OPTIONAL, \"\",     \"PHASE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)\");\n    readConfig(config, \"sigmaFactorCode\",              exprSigmaCode,           Config::OPTIONAL, \"\",     \"CODE: factor = f(FREQ, ELE, SNR, ROTI, dTEc, IONOINDEX)\");\n    readConfig(config, \"supportsIntegerAmbiguities\",   integerAmbiguities,      Config::DEFAULT,  \"1\",    \"receiver tracks full cycle integer ambiguities\");\n    readConfig(config, \"wavelengthFactor\",             wavelengthFactor,        Config::DEFAULT,  \"1.\",   \"factor to account for half-wavelength observations (collected by codeless squaring techniques)\");\n    readConfig(config, \"useType\",                      useType,                 Config::OPTIONAL, \"\",     \"only use observations that match any of these patterns\");\n    readConfig(config, \"ignoreType\",                   ignoreType,              Config::OPTIONAL, \"\",     \"ignore observations that match any of these patterns\");\n    readConfig(config, \"elevationCutOff\",              elevationCutOff,         Config::DEFAULT,  \"0\",    \"[degree] ignore observations below cutoff\");\n    readConfig(config, \"minObsCountPerTrack\",          minObsCountPerTrack,     Config::DEFAULT,  \"20\",   \"tracks with less number of epochs with observations are dropped\");\n    if(readConfigSequence(config, \"preprocessing\", Config::MUSTSET, \"\", \"settings for preprocessing of observations/stations\"))\n    {\n      readConfig(config, \"printStatistics\",              printInfo,               Config::DEFAULT,  \"1\",    \"print preprocesssing statistics for all receivers\");\n      readConfig(config, \"huber\",                        huber,                   Config::DEFAULT,  \"2.5\",  \"residuals > huber*sigma0 are downweighted\");\n      readConfig(config, \"huberPower\",                   huberPower,              Config::DEFAULT,  \"1.5\",  \"residuals > huber: sigma=(e/huber)^huberPower*sigma0\");\n      readConfig(config, \"codeMaxPositionDiff\",          codeMaxPosDiff,          Config::DEFAULT,  \"100\",  \"[m] max. allowed position error by PPP code only clock error estimation\");\n      readConfig(config, \"denoisingLambda\",              denoisingLambda,         Config::DEFAULT,  \"5\",    \"regularization parameter for total variation denoising used in cylce slip detection\");\n      readConfig(config, \"tecWindowSize\",                tecWindowSize,           Config::DEFAULT,  \"15\",   \"(0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection\");\n      readConfig(config, \"tecSigmaFactor\",               tecSigmaFactor,          Config::DEFAULT,  \"3.5\",  \"factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection\");\n      readConfig(config, \"outputfileTrackBefore\",        fileNameTrackBefore,     Config::OPTIONAL, \"\",     \"variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection\");\n      readConfig(config, \"outputfileTrackAfter\",         fileNameTrackAfter,      Config::OPTIONAL, \"\",     \"variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection\");\n      endSequence(config);\n    } // readConfigSequence(preprocessing)\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGeneratorLowEarthOrbiter::init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n                                                const std::vector<GnssTransmitterPtr> &transmitters, EarthRotationPtr earthRotation,\n                                                Parallel::CommunicatorPtr comm, std::vector<GnssReceiverPtr> &receivers)\n{\n  try\n  {\n    logStatus<<\"init Low Earth Orbiter\"<<Log::endl;\n    Bool isSimulation = simulationTypes.size();\n    if(isSimulation && !fileNameObs.empty())\n      logWarningOnce<<\"ignoring observation file <\"<<fileNameObs<<\">\"<<Log::endl;\n\n    std::vector<GnssAntennaDefinitionPtr> antennaDefList;\n    if(!fileNameAntennaDef.empty())\n      readFileGnssAntennaDefinition(fileNameAntennaDef, antennaDefList);\n\n    std::vector<GnssReceiverDefinitionPtr> receiverDefList;\n    if(!fileNameReceiverDef.empty())\n      readFileGnssReceiverDefinition(fileNameReceiverDef, receiverDefList);\n\n    std::vector<GnssAntennaDefinitionPtr> accuracyDefList;\n    if(!fileNameAccuracyDef.empty())\n      readFileGnssAntennaDefinition(fileNameAccuracyDef, accuracyDefList);\n\n    Platform platform;\n    readFilePlatform(fileNameStationInfo, platform);\n    platform.name = platform.markerName;\n    platform.fillGnssAntennaDefinition(antennaDefList);\n    platform.fillGnssReceiverDefinition(receiverDefList);\n    platform.fillGnssAccuracyDefinition(accuracyDefList);\n\n    // test completeness of antennas\n    for(const auto &instrument : platform.equipments)\n    {\n      auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n      if(antenna && antenna->timeEnd > times.front() && antenna->timeStart <= times.back() && (!antenna->antennaDef || !antenna->accuracyDef))\n        logWarningOnce<<platform.markerName<<\".\"<<platform.markerNumber<<\": No \"<<(!antenna->antennaDef ? \"antenna\" : \"accuracy\")<<\" definition found for \"<<antenna->str()<<Log::endl;\n    }\n\n    recv = std::make_shared<GnssReceiver>(Parallel::isMaster(comm), FALSE/*isEarthFixed*/, platform,\n                                          noPatternFoundAction, Vector(times.size(), TRUE)/*useableEpochs*/,\n                                          integerAmbiguities, wavelengthFactor);\n    receivers.push_back(recv);\n\n    if(Parallel::isMaster(comm))\n    {\n      try\n      {\n        recv->times = times;\n        recv->clk.resize(times.size(), 0);\n        recv->pos.resize(times.size());\n        recv->vel.resize(times.size());\n        recv->offset.resize(times.size());\n        recv->global2local.resize(times.size());\n        recv->global2antenna.resize(times.size());\n\n        OrbitArc      orbit      = InstrumentFile::read(fileNameOrbit);\n        StarCameraArc starCamera = InstrumentFile::read(fileNameStarCamera);\n        Arc::checkSynchronized({orbit, starCamera});\n\n        UInt i=0;\n        for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        {\n          while((i < orbit.size()) && (orbit.at(i).time < times.at(idEpoch)-timeMargin))\n            i++;\n          if((i >= orbit.size()) || (orbit.at(i).time > times.at(idEpoch)+timeMargin))\n          {\n            recv->disable(idEpoch, \"due to missing orbit/attitude data\");\n            continue;\n          }\n\n          auto antenna = platform.findEquipment<PlatformGnssAntenna>(times.at(idEpoch));\n          if(!antenna || !antenna->antennaDef || !antenna->accuracyDef)\n          {\n            recv->disable(idEpoch, \"missing antenna/accuracy patterns\");\n            continue;\n          }\n\n          recv->pos.at(idEpoch)            = orbit.at(i).position;\n          recv->vel.at(idEpoch)            = orbit.at(i).velocity;\n          recv->global2local.at(idEpoch)   = inverse(localNorthEastUp(recv->pos.at(idEpoch), Ellipsoid()));\n          recv->global2antenna.at(idEpoch) = antenna->local2antennaFrame * inverse(starCamera.at(i).rotary);\n          recv->offset.at(idEpoch)         = recv->global2local.at(idEpoch).transform(starCamera.at(i).rotary.rotate(antenna->position - platform.referencePoint(times.at(idEpoch))));\n        }\n        recv->preprocessingInfo(\"init()\");\n\n        logStatus<<\"read observations\"<<Log::endl;\n        auto rotationCrf2Trf = std::bind(&EarthRotation::rotaryMatrix, earthRotation, std::placeholders::_1);\n        if(isSimulation)\n        {\n          recv->simulateZeroObservations(simulationTypes, transmitters, rotationCrf2Trf, elevationCutOff,\n                                         useType, ignoreType, GnssObservation::RANGE | GnssObservation::PHASE);\n        }\n        else\n        {\n          recv->readObservations(fileNameObs, transmitters,  rotationCrf2Trf, timeMargin, elevationCutOff,\n                                 useType, ignoreType, GnssObservation::RANGE | GnssObservation::PHASE);\n        }\n      }\n      catch(std::exception &e)\n      {\n        recv->disable(e.what());\n      }\n    } // if(isMaster())\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGeneratorLowEarthOrbiter::preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    if(fileNameObs.empty())\n      return;\n\n    logStatus<<\"init observations\"<<Log::endl;\n    if(recv->isMyRank())\n    {\n      try\n      {\n        recv->createTracks(gnss->transmitters, minObsCountPerTrack, {GnssType::L5_G});\n        std::vector<Vector3d> posApriori = recv->pos;\n        recv->pos = recv->estimateInitialClockErrorFromCodeObservations(gnss->transmitters, gnss->funcRotationCrf2Trf, gnss->funcReduceModels, huber, huberPower, TRUE/*estimateKinematicPosition*/);\n        // observation equations based on positions from code observations\n        GnssReceiver::ObservationEquationList eqn(*recv, gnss->transmitters, gnss->funcRotationCrf2Trf, gnss->funcReduceModels, GnssObservation::RANGE | GnssObservation::PHASE);\n        recv->pos = std::move(posApriori); // restore apriori positions\n\n        recv->disableEpochsWithGrossCodeObservationOutliers(eqn, codeMaxPosDiff, 0.5);\n        recv->writeTracks(fileNameTrackBefore, eqn, {GnssType::L5_G});\n        recv->cycleSlipsDetection(eqn, minObsCountPerTrack, denoisingLambda, tecWindowSize, tecSigmaFactor, {GnssType::L5_G});\n        recv->trackOutlierDetection(eqn, {GnssType::L5_G}, huber, huberPower);\n        recv->cycleSlipsRepairAtSameFrequency(eqn);\n        recv->writeTracks(fileNameTrackAfter, eqn, {GnssType::L5_G});\n\n        // apply factors for accuracies from expressions\n        if(exprSigmaPhase || exprSigmaCode)\n        {\n          for(UInt idTrans=0; idTrans<gnss->transmitters.size(); idTrans++)\n            for(UInt idEpoch=0; idEpoch<recv->idEpochSize(); idEpoch++)\n            {\n              GnssObservation *obs = recv->observation(idTrans, idEpoch);\n              if(obs)\n              {\n                VariableList varList;\n                varList.setVariable(\"ROTI\", 0);\n                const UInt idx = obs->index(GnssType::ROTI);\n                if(idx != NULLINDEX)\n                  varList.setVariable(\"ROTI\", obs->at(idx).observation);\n\n                for(UInt idType=0; idType<obs->size(); idType++)\n                  if((obs->at(idType).type == GnssType::RANGE) || (obs->at(idType).type == GnssType::PHASE))\n                  {\n                    varList.setVariable(\"FREQ\",  obs->at(idType).type.frequency() );\n                    varList.setVariable(\"SNR\", 0);\n                    const UInt idx = obs->index(GnssType::SNR + (obs->at(idType).type & GnssType::FREQUENCY));\n                    if(idx != NULLINDEX)\n                      varList.setVariable(\"SNR\", obs->at(idx).observation);\n\n                    if(exprSigmaPhase && (obs->at(idType).type == GnssType::PHASE))\n                    {\n                      const Double factor = exprSigmaPhase->evaluate(varList);\n                      obs->at(idType).sigma0 *= factor;\n                      obs->at(idType).sigma  *= factor;\n                    }\n\n                    if(exprSigmaCode && (obs->at(idType).type == GnssType::RANGE))\n                    {\n                      const Double factor = exprSigmaCode->evaluate(varList);\n                      obs->at(idType).sigma0 *= factor;\n                      obs->at(idType).sigma  *= factor;\n                    }\n                  } // for(idType)\n              } // if(obs)\n            } // for(idTrans, idEpoch)\n        } // if(exprSigmaPhase || exprSigmaCode)\n      }\n      catch(std::exception &e)\n      {\n        recv->disable(e.what());\n      }\n    } // if(recv->isMyRank())\n\n    printPreprocessingInfos(\"preprocessing statistics after each step\", {recv}, !printInfo/*disabledOnly*/, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGeneratorLowEarthOrbiter::simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                                                      Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    logStatus<<\"simulate observations\"<<Log::endl;\n    if(recv->isMyRank())\n    {\n      try\n      {\n        recv->simulateObservations(noiseClock, noiseObs, gnss->transmitters,\n                                   gnss->funcRotationCrf2Trf, gnss->funcReduceModels,\n                                   minObsCountPerTrack, Angle(0), GnssObservation::RANGE | GnssObservation::PHASE);\n      }\n      catch(std::exception &e)\n      {\n        recv->disable(e.what());\n      }\n    } // if(isMaster())\n\n    printPreprocessingInfos(\"simulation statistics after each step\", {recv}, !printInfo/*disabledOnly*/, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssReceiverGenerator/gnssReceiverGeneratorLowEarthOrbiter.h",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverGeneratorLowEarthOrbiter.h\n*\n* @brief GNSS for Low Earth Orbiter (LEO).\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSRECEIVERGENERATORLOWEARTHORBITER__\n#define __GROOPS_GNSSRECEIVERGENERATORLOWEARTHORBITER__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssReceiverGenerator\nstatic const char *docstringGnssReceiverGeneratorLowEarthOrbiter = R\"(\n\\subsection{LowEarthOrbiter}\\label{gnssReceiverGeneratorType:lowEarthOrbiter}\nA single low-Earth orbiting (LEO) satellite with an onboard GNSS receiver.\nAn apriori orbit is needed as \\configFile{inputfileOrbit}{instrument}.\nAttitude data must be provided via \\configFile{inputfileStarCamera}{instrument}.\nIf no attitude data is available from the satellite operator,\nthe star camera data can be simulated by using \\program{SimulateStarCamera}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS for Low Earth Orbiter (LEO).\n* @ingroup gnssReceiverGeneratorGroup\n* @see GnssReceiverGenerator */\nclass GnssReceiverGeneratorLowEarthOrbiter : public GnssReceiverGeneratorBase\n{\n  FileName              fileNameStationInfo;\n  FileName              fileNameAntennaDef, fileNameReceiverDef, fileNameAccuracyDef;\n  FileName              fileNameObs, fileNameOrbit, fileNameStarCamera;\n  ExpressionVariablePtr exprSigmaPhase, exprSigmaCode;\n  Bool                  integerAmbiguities;\n  Double                wavelengthFactor;\n  Angle                 elevationCutOff;\n  std::vector<GnssType> useType, ignoreType;\n  GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction;\n  Bool                  printInfo;\n  Double                huber, huberPower;\n  Double                codeMaxPosDiff;\n  UInt                  minObsCountPerTrack;\n  Double                denoisingLambda;\n  UInt                  tecWindowSize;\n  Double                tecSigmaFactor;\n  FileName              fileNameTrackBefore, fileNameTrackAfter;\n  GnssReceiverPtr       recv;\n\npublic:\n  GnssReceiverGeneratorLowEarthOrbiter(Config &config);\n\n  void init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n            const std::vector<GnssTransmitterPtr> &transmitters, EarthRotationPtr earthRotation,\n            Parallel::CommunicatorPtr comm, std::vector<GnssReceiverPtr> &receivers) override;\n\n  void preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n\n  void simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                  Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssReceiverGenerator/gnssReceiverGeneratorStationNetwork.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverGeneratorStationNetwork.cpp\n*\n* @brief GNSS ground station network.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/system.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/tides/tides.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssReceiver.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGeneratorStationNetwork.h\"\n\n/***********************************************/\n\nGnssReceiverGeneratorStationNetwork::GnssReceiverGeneratorStationNetwork(Config &config)\n{\n  try\n  {\n    std::string choice;\n    maxStationCount = MAX_UINT;\n\n    readConfig(config, \"inputfileStationList\",               fileNameStationList,     Config::MUSTSET,  \"\", \"ascii file with station names\");\n    readConfig(config, \"maxStationCount\",                    maxStationCount,         Config::OPTIONAL, \"\", \"maximum number of stations to be used\");\n    readConfig(config, \"inputfileStationInfo\",               fileNameStationInfo,     Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/stationInfo/igs/stationInfo.{station}.xml\", \"variable {station} available. station metadata (antennas, receivers, ...)\");\n    readConfig(config, \"inputfileAntennaDefinition\",         fileNameAntennaDef,      Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\", \"antenna center offsets and variations\");\n    if(readConfigChoice(config, \"noAntennaPatternFound\", choice, Config::MUSTSET, \"ignoreObservation\", \"what should happen if no antenna pattern is found for an observation\"))\n    {\n      if(readConfigChoiceElement(config, \"ignoreObservation\",   choice, \"ignore observation if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::IGNORE_OBSERVATION;\n      if(readConfigChoiceElement(config, \"useNearestFrequency\", choice, \"use pattern of nearest frequency if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::USE_NEAREST_FREQUENCY;\n      if(readConfigChoiceElement(config, \"throwException\",      choice, \"throw exception if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::THROW_EXCEPTION;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileReceiverDefinition\",        fileNameReceiverDef,     Config::OPTIONAL, \"\", \"observed signal types\");\n    readConfig(config, \"inputfileAccuracyDefinition\",        fileNameAccuracyDef,     Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/accuracyDefinition/accuracyDefinition.xml\", \"elevation and azimuth dependent accuracy\");\n    readConfig(config, \"inputfileStationPosition\",           fileNameStationPosition, Config::OPTIONAL, \"{groopsDataDir}/gnss/receiverStation/position/igs/igs20/stationPosition.{station}.dat\", \"variable {station} available.\");\n    readConfig(config, \"disableStationWithoutPosition\",      disableWithoutPosition,  Config::DEFAULT,  \"0\",    \"drop stations without apriori position\");\n    readConfig(config, \"inputfileClock\",                     fileNameClock,           Config::OPTIONAL, \"\",     \"variable {station} available\");\n    readConfig(config, \"inputfileObservations\",              fileNameObs,             Config::OPTIONAL, \"gnssReceiver_{loopTime:%D}.{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"loadingDisplacement\",                gravityfield,            Config::DEFAULT,  \"\",     \"loading deformation\");\n    readConfig(config, \"tidalDisplacement\",                  tides,                   Config::DEFAULT,  \"\",     \"tidal deformation\");\n    readConfig(config, \"ephemerides\",                        ephemerides,             Config::OPTIONAL, \"jpl\",  \"for tidal deformation\");\n    readConfig(config, \"inputfileDeformationLoadLoveNumber\", deformationName,         Config::MUSTSET,  \"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\", \"\");\n    readConfig(config, \"inputfilePotentialLoadLoveNumber\",   potentialName,           Config::OPTIONAL, \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"if full potential is given and not only loading potential\");\n    readConfig(config, \"useType\",                            useType,                 Config::OPTIONAL, \"\",     \"only use observations that match any of these patterns\");\n    readConfig(config, \"ignoreType\",                         ignoreType,              Config::OPTIONAL, \"\",     \"ignore observations that match any of these patterns\");\n    readConfig(config, \"elevationCutOff\",                    elevationCutOff,         Config::DEFAULT,  \"5\",    \"[degree] ignore observations below cutoff\");\n    readConfig(config, \"elevationTrackMinimum\",              elevationTrackMinimum,   Config::DEFAULT,  \"15\",   \"[degree] ignore tracks that never exceed minimum elevation\");\n    readConfig(config, \"minObsCountPerTrack\",                minObsCountPerTrack,     Config::DEFAULT,  \"60\",   \"tracks with less number of epochs with observations are dropped\");\n    readConfig(config, \"minEstimableEpochsRatio\",            minEstimableEpochsRatio, Config::DEFAULT,  \"0.75\", \"[0,1] drop stations with lower ratio of estimable epochs to total epochs\");\n    if(readConfigSequence(config, \"preprocessing\", Config::MUSTSET, \"\", \"settings for preprocessing of observations/stations\"))\n    {\n      readConfig(config, \"printStatistics\",       printInfo,           Config::DEFAULT,  \"0\",    \"print preprocesssing statistics for all receivers\");\n      readConfig(config, \"huber\",                 huber,               Config::DEFAULT,  \"2.5\",  \"residuals > huber*sigma0 are downweighted\");\n      readConfig(config, \"huberPower\",            huberPower,          Config::DEFAULT,  \"1.5\",  \"residuals > huber: sigma=(e/huber)^huberPower*sigma0\");\n      readConfig(config, \"codeMaxPositionDiff\",   codeMaxPosDiff,      Config::DEFAULT,  \"100\",  \"[m] max. allowed position error by PPP code only clock error estimation\");\n      readConfig(config, \"denoisingLambda\",       denoisingLambda,     Config::DEFAULT,  \"5\",    \"regularization parameter for total variation denoising used in cylce slip detection\");\n      readConfig(config, \"tecWindowSize\",         tecWindowSize,       Config::DEFAULT,  \"15\",   \"(0 = disabled) window size for TEC smoothness evaluation used in cycle slip detection\");\n      readConfig(config, \"tecSigmaFactor\",        tecSigmaFactor,      Config::DEFAULT,  \"3.5\",  \"factor applied to moving standard deviation used as threshold in TEC smoothness evaluation during cycle slip detection\");\n      readConfig(config, \"outputfileTrackBefore\", fileNameTrackBefore, Config::OPTIONAL, \"\",     \"variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track before cycle slip detection\");\n      readConfig(config, \"outputfileTrackAfter\",  fileNameTrackAfter,  Config::OPTIONAL, \"\",     \"variables {station}, {prn}, {trackTimeStart}, {trackTimeEnd}, {types}, TEC and MW-like combinations in cycles for each track after cycle slip detection\");\n      endSequence(config);\n    } // readConfigSequence(preprocessing)\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGeneratorStationNetwork::init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n                                               const std::vector<GnssTransmitterPtr> &transmitters, EarthRotationPtr earthRotation,\n                                               Parallel::CommunicatorPtr comm, std::vector<GnssReceiverPtr> &receiversAll)\n{\n  try\n  {\n    logStatus<<\"init station network\"<<Log::endl;\n    Bool isSimulation = simulationTypes.size();\n    if(isSimulation && !fileNameObs.empty())\n      logWarningOnce<<\"ignoring inputfileObservations\"<<Log::endl;\n\n    std::vector<GnssAntennaDefinitionPtr> antennaDefList;\n    if(!fileNameAntennaDef.empty())\n      readFileGnssAntennaDefinition(fileNameAntennaDef, antennaDefList);\n\n    std::vector<GnssReceiverDefinitionPtr> receiverDefList;\n    if(!fileNameReceiverDef.empty())\n      readFileGnssReceiverDefinition(fileNameReceiverDef, receiverDefList);\n\n    std::vector<GnssAntennaDefinitionPtr> accuracyDefList;\n    if(!fileNameAccuracyDef.empty())\n      readFileGnssAntennaDefinition(fileNameAccuracyDef, accuracyDefList);\n\n    std::vector<std::vector<std::string>> stationName;\n    readFileStringTable(fileNameStationList, stationName);\n    VariableList fileNameVariableList;\n    std::vector<std::vector<GnssReceiverPtr>> receiversWithAlternatives(stationName.size());\n    for(UInt i=0; i<stationName.size(); i++)\n      for(UInt k=0; k<stationName.at(i).size(); k++) // alternatives\n      {\n        try\n        {\n          fileNameVariableList.setVariable(\"station\", stationName.at(i).at(k));\n          if(!isSimulation && !System::exists(fileNameObs(fileNameVariableList)))\n            continue;\n\n          Platform platform;\n          readFilePlatform(fileNameStationInfo(fileNameVariableList), platform);\n          platform.name = stationName.at(i).at(k);\n          platform.fillGnssAntennaDefinition(antennaDefList);\n          platform.fillGnssReceiverDefinition(receiverDefList);\n          platform.fillGnssAccuracyDefinition(accuracyDefList);\n\n          // approximate station position\n          if(!fileNameStationPosition.empty())\n          {\n            try\n            {\n              if(!System::exists(fileNameStationPosition(fileNameVariableList)))\n                throw(Exception(\"file <\"+fileNameStationPosition(fileNameVariableList).str()+\"> not exist\"));\n              const Time timesMid = 0.5*(times.front()+times.back());\n              Vector3dArc arc = InstrumentFile::read(fileNameStationPosition(fileNameVariableList));\n              auto iter = std::min_element(arc.begin(), arc.end(), [&](const Epoch &e1, const Epoch &e2)\n                                          {return std::fabs((e1.time-timesMid).mjd()) < std::fabs((e2.time-timesMid).mjd());});\n              if(!arc.size() || ((arc.size() > 1) && (std::fabs((iter->time-timesMid).mjd()) > 0.5*medianSampling(arc.times()).mjd())))\n                throw(Exception(\"No a-priori position found\"));\n              platform.approxPosition = iter->vector3d;\n            }\n            catch(std::exception &e)\n            {\n              if(disableWithoutPosition)\n                throw;\n            }\n          }\n\n          // test completeness of antennas\n          for(const auto &instrument : platform.equipments)\n          {\n            auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n            if(antenna && antenna->timeEnd > times.front() && antenna->timeStart <= times.back() && (!antenna->antennaDef || !antenna->accuracyDef))\n              logWarningOnce<<platform.markerName<<\".\"<<platform.markerNumber<<\": No \"<<(!antenna->antennaDef ? \"antenna\" : \"accuracy\")<<\" definition found for \"<<antenna->str()<<Log::endl;\n          }\n\n          GnssReceiverPtr recv = std::make_shared<GnssReceiver>(FALSE, TRUE, platform, noPatternFoundAction, Vector(times.size(), TRUE), TRUE, 1.);\n          receiversWithAlternatives.at(i).push_back(recv);\n        }\n        catch(std::exception &e)\n        {\n          logWarningOnce<<stationName.at(i).at(k)<<\" disabled: \"<<e.what()<<Log::endl;\n        }\n      }\n\n    // remove empty stations\n    receiversWithAlternatives.erase(std::remove_if(receiversWithAlternatives.begin(), receiversWithAlternatives.end(),\n                                                   [](auto x) {return !x.size();}), receiversWithAlternatives.end());\n\n    // read observations at single nodes\n    // ---------------------------------\n    logStatus<<\"read observations\"<<Log::endl;\n    Vector receiverAlternative(receiversWithAlternatives.size());\n    Log::Timer timer(receiversWithAlternatives.size());\n    for(UInt i=0; i<receiversWithAlternatives.size(); i++)\n      if(i%Parallel::size(comm) == Parallel::myRank(comm)) // distribute to nodes\n      {\n        timer.loopStep(i);\n        for(UInt k=0; k<receiversWithAlternatives.at(i).size(); k++) // test alternatives\n        {\n          try\n          {\n            fileNameVariableList.setVariable(\"station\", receiversWithAlternatives.at(i).at(k)->name());\n            GnssReceiverPtr recv = receiversWithAlternatives.at(i).at(k);\n            recv->isMyRank_ = TRUE;\n\n            recv->times = times;\n            recv->clk.resize(times.size(), 0);\n            recv->pos.resize(times.size(), recv->platform.approxPosition);\n            recv->vel.resize(times.size());\n            recv->offset.resize(times.size());\n            recv->global2local.resize(times.size(), inverse(localNorthEastUp(recv->platform.approxPosition, Ellipsoid())));\n            recv->global2antenna.resize(times.size());\n            for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n            {\n              auto antenna = recv->platform.findEquipment<PlatformGnssAntenna>(times.at(idEpoch));\n              if(antenna && antenna->antennaDef && antenna->accuracyDef)\n              {\n                recv->offset.at(idEpoch)         = antenna->position - recv->platform.referencePoint(times.at(idEpoch));\n                recv->global2antenna.at(idEpoch) = antenna->local2antennaFrame * recv->global2local.at(idEpoch);\n              }\n              else\n                recv->disable(idEpoch, \"missing antenna/accuracy patterns\");\n            }\n\n            recv->preprocessingInfo(\"init()\");\n\n            auto rotationCrf2Trf = std::bind(&EarthRotation::rotaryMatrix, earthRotation, std::placeholders::_1);\n            if(isSimulation)\n            {\n              recv->simulateZeroObservations(simulationTypes, transmitters, rotationCrf2Trf, elevationCutOff,\n                                             useType, ignoreType, GnssObservation::RANGE | GnssObservation::PHASE);\n            }\n            else\n            {\n              recv->readObservations(fileNameObs(fileNameVariableList), transmitters, rotationCrf2Trf, timeMargin, elevationCutOff,\n                                     useType, ignoreType, GnssObservation::RANGE | GnssObservation::PHASE);\n            }\n\n            auto enoughEpochs = [&]()\n            {\n              // count epochs with observations\n              UInt countEpochs = 0;\n              for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n                if(recv->useable(idEpoch))\n                  countEpochs++;\n              return (countEpochs*recv->observationSampling >= minEstimableEpochsRatio*times.size()*medianSampling(times).seconds());\n            };\n\n            if(!enoughEpochs())\n              continue;\n\n            // clock file\n            // ----------\n            if(!fileNameClock.empty())\n            {\n              try\n              {\n                MiscValueArc arc = InstrumentFile::read(fileNameClock(fileNameVariableList));\n                UInt idEpoch = 0;\n                for(UInt arcEpoch=0; arcEpoch<arc.size(); arcEpoch++)\n                {\n                  while((idEpoch < recv->times.size()) && (recv->times.at(idEpoch)+timeMargin < arc.at(arcEpoch).time))\n                    recv->disable(idEpoch++, \"missing clock data in file\");\n                  if(idEpoch >= recv->times.size())\n                    break;\n                  if((arc.at(arcEpoch).time+timeMargin < recv->times.at(idEpoch)) || !recv->useable(idEpoch))\n                    continue;\n                  recv->clk.at(idEpoch++) = arc.at(arcEpoch).value;\n                }\n                for(; idEpoch<times.size(); idEpoch++)\n                  recv->disable(idEpoch, \"missing clock data in file\");\n\n                recv->preprocessingInfo(\"readClockFile()\");\n                if(!enoughEpochs())\n                {\n                  logWarning<<\"Not enough valid epochs in clock file <\"<<fileNameClock(fileNameVariableList)<<\">, disabling receiver.\"<<Log::endl;\n                  continue;\n                }\n              }\n              catch(std::exception &/*e*/)\n              {\n                logWarning<<\"Unable to read clock file <\"<<fileNameClock(fileNameVariableList)<<\">, disabling receiver.\"<<Log::endl;\n                continue;\n              }\n            }\n\n            // found valid station\n            receiverAlternative(i) = k+1;\n            break;\n          }\n          catch(std::exception &e)\n          {\n            logWarning<<receiversWithAlternatives.at(i).at(k)->name()<<\" disabled: \"<<e.what()<<Log::endl;\n          }\n        }\n      }\n    Parallel::barrier(comm);\n    timer.loopEnd();\n    Parallel::reduceSum(receiverAlternative, 0, comm);\n    Parallel::broadCast(receiverAlternative, 0, comm);\n\n    // store valid receivers\n    // ---------------------\n    for(UInt i=0; i<receiversWithAlternatives.size(); i++)\n      if(receiverAlternative(i) > 0)\n      {\n        receivers.push_back(receiversWithAlternatives.at(i).at(receiverAlternative(i)-1));\n        if(receivers.size() >= maxStationCount)\n          break;\n      }\n    receiversAll.insert(receiversAll.end(), receivers.begin(), receivers.end());\n    logInfo<<\"  \"<<receivers.size()<<\" of \"<<stationName.size()<<\" stations used\"<<Log::endl;\n\n    // tides & loading\n    // ---------------\n    logStatus<<\"compute tides & loading\"<<Log::endl;\n    Vector hn, ln;\n    if(!deformationName.empty())\n    {\n      Matrix love;\n      readFileMatrix(deformationName, love);\n      hn = love.column(0);\n      ln = love.column(1);\n\n      // models contain the total mass (loading mass & deformation mass effect)\n      if(!potentialName.empty())\n      {\n        Vector kn;\n        readFileMatrix(potentialName, kn);\n        for(UInt n=2; n<std::min(kn.rows(), hn.rows()); n++)\n          hn(n) /= (1.+kn(n));\n        for(UInt n=2; n<std::min(kn.rows(), ln.rows()); n++)\n          ln(n) /= (1.+kn(n));\n      }\n    }\n\n    std::vector<Vector3d> positions;\n    for(auto &recv : receivers)\n      if(recv->isMyRank())\n        positions.push_back(recv->position(0));\n\n    Vector gravity(positions.size()); // normal gravity\n    for(UInt i=0; i<gravity.size(); i++)\n      gravity(i) = Planets::normalGravity(positions.at(i));\n\n    std::vector<Rotary3d> rotEarth(times.size());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      rotEarth.at(idEpoch) = earthRotation->rotaryMatrix(times.at(idEpoch));\n\n    std::vector<std::vector<Vector3d>> disp(positions.size(), std::vector<Vector3d>(times.size()));\n    tides->deformation(times, positions, rotEarth, earthRotation, ephemerides, gravity, hn, ln, disp);\n    gravityfield->deformation(times, positions, gravity, hn, ln, disp);\n    tides        = nullptr;\n    gravityfield = nullptr;\n\n    // add displacements\n    UInt idx = 0;\n    for(auto &recv : receivers)\n      if(recv->isMyRank())\n      {\n        for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n          recv->offset.at(idEpoch) += recv->global2localFrame(idEpoch).transform(disp.at(idx).at(idEpoch));\n        idx++;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGeneratorStationNetwork::preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    logStatus<<\"init observations\"<<Log::endl;\n    VariableList fileNameVariableList;\n    Single::forEach(receivers.size(), [&](UInt idRecv)\n    {\n      Parallel::peek(comm);\n      if(receivers.at(idRecv)->isMyRank())\n      {\n        try\n        {\n          auto recv = receivers.at(idRecv);\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          std::vector<Vector3d> posApriori = recv->pos;\n          if(fileNameClock.empty())\n          {\n            recv->pos = recv->estimateInitialClockErrorFromCodeObservations(gnss->transmitters, gnss->funcRotationCrf2Trf, gnss->funcReduceModels, huber, huberPower, FALSE/*estimateKinematicPosition*/);\n\n            Double maxDiff = 0.;\n            for(UInt i=0; i<posApriori.size(); i++)\n              maxDiff = std::max(maxDiff, (recv->pos.at(i)-posApriori.at(i)).r());\n            if(maxDiff > 10.0)\n              logWarning<<recv->name()<<\": estimated code based position differ from apriori position by \"<<maxDiff%\"%.2f m\"s<<Log::endl;\n          }\n          // observation equations based on positions from code observations\n          GnssReceiver::ObservationEquationList eqn(*recv, gnss->transmitters, gnss->funcRotationCrf2Trf, gnss->funcReduceModels, GnssObservation::RANGE | GnssObservation::PHASE);\n          recv->pos = std::move(posApriori); // restore apriori positions\n\n          recv->disableEpochsWithGrossCodeObservationOutliers(eqn, codeMaxPosDiff, 0.5);\n          recv->createTracks(gnss->transmitters, minObsCountPerTrack, {GnssType::L5_G});\n          recv->writeTracks(fileNameTrackBefore, eqn, {GnssType::L5_G});\n          recv->cycleSlipsDetection(eqn, minObsCountPerTrack, denoisingLambda, tecWindowSize, tecSigmaFactor, {GnssType::L5_G});\n          recv->removeLowElevationTracks(eqn, elevationTrackMinimum);\n          recv->trackOutlierDetection(eqn, {GnssType::L5_G}, huber, huberPower);\n          recv->cycleSlipsRepairAtSameFrequency(eqn);\n          recv->writeTracks(fileNameTrackAfter, eqn, {GnssType::L5_G});\n\n          // count epochs with observations\n          UInt countEpochs = 0;\n          for(UInt idEpoch=0; idEpoch<gnss->times.size(); idEpoch++)\n            if(recv->useable(idEpoch))\n              countEpochs++;\n          if(countEpochs*recv->observationSampling < minEstimableEpochsRatio*gnss->times.size()*medianSampling(gnss->times).seconds())\n            recv->disable(\"not enough epochs (< minEstimableEpochsRatio)\");\n        }\n        catch(std::exception &e)\n        {\n          receivers.at(idRecv)->disable(e.what());\n        }\n      }\n    });\n\n    printPreprocessingInfos(\"preprocessing statistics after each step\", receivers, !printInfo/*disabledOnly*/, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverGeneratorStationNetwork::simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                                                     Gnss *gnss, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    logStatus<<\"simulate observations\"<<Log::endl;\n    Single::forEach(receivers.size(), [&](UInt idRecv)\n    {\n      Parallel::peek(comm);\n      if(receivers.at(idRecv)->isMyRank())\n      {\n        try\n        {\n          receivers.at(idRecv)->simulateObservations(noiseClock, noiseObs, gnss->transmitters,\n                                                     gnss->funcRotationCrf2Trf, gnss->funcReduceModels,\n                                                     minObsCountPerTrack, elevationTrackMinimum,\n                                                     GnssObservation::RANGE | GnssObservation::PHASE);\n        }\n        catch(std::exception &e)\n        {\n          receivers.at(idRecv)->disable(e.what());\n        }\n      }\n    });\n\n    printPreprocessingInfos(\"simulation statistics after each step\", receivers, !printInfo/*disabledOnly*/, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssReceiverGenerator/gnssReceiverGeneratorStationNetwork.h",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverGeneratorStationNetwork.h\n*\n* @brief GNSS ground station network.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSRECEIVERGENERATORSTATIONNETWORK__\n#define __GROOPS_GNSSRECEIVERGENERATORSTATIONNETWORK__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssReceiverGenerator\nstatic const char *docstringGnssReceiverGeneratorStationNetwork = R\"(\n\\subsection{StationNetwork}\\label{gnssReceiverGeneratorType:stationNetwork}\nA network of GNSS ground stations is defined via \\configFile{inputfileStationList}{stringTable}.\nEach line can contain more than one station. The first station in each line for which \\configFile{inputfileObservations}{instrument}\nexists and contains enough observations is used for the processing.\nAll input files except \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition},\n\\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition}, and\n\\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} are read for each station.\nThe file name is interpreted as a template with the variable \\verb|{station}| being replaced by the station name.\n\nThe effects of loading and tidal deformation on station positions can be corrected for\nvia \\configClass{loadingDisplacement}{gravityfieldType} and\n\\configClass{tidalDisplacement}{tidesType}, respectively.\nTidal deformations typically include:\n\\begin{itemize}\n  \\item \\configClass{earthTide}{tidesType:earthTide}: Earth tidal deformations (IERS conventions)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tidal deformations\n        (e.g. fes2014b\\_n720, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: atmospheric tidal deformation\n        (e.g. AOD1B RL06, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{poleTide}{tidesType:poleTide}: pole tidal deformations (IERS conventions)\n  \\item \\configClass{poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tidal deformations (IERS conventions)\n\\end{itemize}\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS ground station network.\n* @ingroup gnssReceiverGeneratorGroup\n* @see GnssReceiverGenerator */\nclass GnssReceiverGeneratorStationNetwork : public GnssReceiverGeneratorBase\n{\n  FileName              fileNameStationList, fileNameStationInfo;\n  FileName              fileNameAntennaDef, fileNameReceiverDef, fileNameAccuracyDef;\n  FileName              fileNameStationPosition, fileNameClock, fileNameObs;\n  UInt                  maxStationCount;\n  Bool                  disableWithoutPosition;\n  GravityfieldPtr       gravityfield;\n  TidesPtr              tides;\n  EphemeridesPtr        ephemerides;\n  FileName              deformationName, potentialName;\n  std::vector<GnssType> useType, ignoreType;\n  GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction;\n  Angle                 elevationCutOff;\n  Bool                  printInfo;\n  UInt                  minObsCountPerTrack;\n  Angle                 elevationTrackMinimum;\n  Double                minEstimableEpochsRatio;\n  Double                huber, huberPower;\n  Double                codeMaxPosDiff;\n  Double                denoisingLambda;\n  UInt                  tecWindowSize;\n  Double                tecSigmaFactor;\n  FileName              fileNameTrackBefore, fileNameTrackAfter;\n  std::vector<GnssReceiverPtr> receivers;\n\npublic:\n  GnssReceiverGeneratorStationNetwork(Config &config);\n\n  void init(std::vector<GnssType> simulationTypes, const std::vector<Time> &times, const Time &timeMargin,\n            const std::vector<GnssTransmitterPtr> &transmitters, EarthRotationPtr earthRotation,\n            Parallel::CommunicatorPtr comm, std::vector<GnssReceiverPtr> &receivers) override;\n\n  void preprocessing(Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n\n  void simulation(NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n                  Gnss *gnss, Parallel::CommunicatorPtr comm) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/gnss/gnssTransceiver.h",
    "content": "/***********************************************/\n/**\n* @file gnssTransceiver.h\n*\n* @brief GNSS receiver or transmitter.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-01-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSTRANSCEIVER__\n#define __GROOPS_GNSSTRANSCEIVER__\n\n#include \"base/gnssType.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/filePlatform.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass GnssTransceiver;\ntypedef std::shared_ptr<GnssTransceiver> GnssTransceiverPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for GNSS receiver or transmitter.\n* eg. GPS satellites. */\nclass GnssTransceiver\n{\n   Vector      useableEpochs;\n   UInt        countUseableEpochs;\n   GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction;\n\npublic:\n   UInt           id_; // set by Gnss::init()\n   Platform       platform;\n   GnssSignalBias signalBias;\n\npublic:\n  /// Constructor.\n  GnssTransceiver(const Platform &platform, GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction, const Vector &useableEpochs);\n\n  /// Destructor.\n  virtual ~GnssTransceiver() {}\n\n  /** @brief name. */\n  std::string name() const {return platform.name;}\n\n  /** @brief Is the platform usable at given epoch (or all epochs). */\n  Bool useable(UInt idEpoch=NULLINDEX) const {return countUseableEpochs && ((idEpoch == NULLINDEX) || useableEpochs(idEpoch));}\n\n  /** @brief Disable given epoch. */\n  virtual void disable(UInt idEpoch, const std::string &reason);\n\n  /** @brief Disable transceiver. */\n  virtual void disable(const std::string &reason);\n\n  /** @brief Allowed signal types. Empty if no  definition was provided. */\n  std::vector<GnssType> definedTypes(const Time &time) const;\n\n  /** @brief Direction dependent corrections.\n  * observed range = range (ARPs of transmitter and receiver) + antennaVariations. */\n  Vector antennaVariations(const Time &time, Angle azimut, Angle elevation, const std::vector<GnssType> &type) const;\n\n  /** @brief Direction (and other parameters) dependent standard deviation.\n  * @a azmiut and @a elevation must be given in the antenna frame (left-handed). */\n  Vector accuracy(const Time &time, Angle azimut, Angle elevation, const std::vector<GnssType> &type) const;\n\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***********************************************/\n\ninline GnssTransceiver::GnssTransceiver(const Platform &platform, GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction, const Vector &useableEpochs)\n  : useableEpochs(useableEpochs), countUseableEpochs(sum(useableEpochs)), noPatternFoundAction(noPatternFoundAction), platform(platform) {}\n\n/***********************************************/\n\ninline void GnssTransceiver::disable(UInt idEpoch, const std::string &reason)\n{\n  try\n  {\n    if(useableEpochs(idEpoch))\n      countUseableEpochs--;\n    useableEpochs(idEpoch) = FALSE;\n    if(countUseableEpochs == 0)\n      disable(reason);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssTransceiver::disable(const std::string &/*reason*/)\n{\n  try\n  {\n    countUseableEpochs = 0;\n    useableEpochs.setNull();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline std::vector<GnssType> GnssTransceiver::definedTypes(const Time &time) const\n{\n  try\n  {\n    auto receiver = platform.findEquipment<PlatformGnssReceiver>(time);\n    if(!receiver || !receiver->receiverDef)\n      return std::vector<GnssType>();\n    return receiver->receiverDef->types;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector GnssTransceiver::antennaVariations(const Time &time, Angle azimut, Angle elevation, const std::vector<GnssType> &types) const\n{\n  try\n  {\n    Vector corr(types.size());\n    corr += signalBias.compute(types);\n\n    auto antenna = platform.findEquipment<PlatformGnssAntenna>(time);\n    if(!antenna)\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": no antenna definition found at \"+time.dateTimeStr()));\n    if(!antenna->antennaDef)\n      throw(Exception(\"no antenna definition for \"+antenna->str()));\n    corr += antenna->antennaDef->antennaVariations(azimut, elevation, types, noPatternFoundAction);\n\n    return corr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector GnssTransceiver::accuracy(const Time &time, Angle azimut, Angle elevation, const std::vector<GnssType> &types) const\n{\n  try\n  {\n    auto antenna = platform.findEquipment<PlatformGnssAntenna>(time);\n    if(!antenna)\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": no antenna accuracy found at \"+time.dateTimeStr()));\n    if(!antenna->accuracyDef)\n      throw(Exception(\"no accuracy definition for \"+antenna->str()));\n    return antenna->accuracyDef->antennaVariations(azimut, elevation, types, noPatternFoundAction);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void GnssTransceiver::save(OutArchive &oa) const\n{\n  oa<<nameValue(\"useableEpochs\",      useableEpochs);\n  oa<<nameValue(\"countUseableEpochs\", countUseableEpochs);\n  oa<<nameValue(\"signalBias\",         signalBias);\n}\n\n/***********************************************/\n\ninline void GnssTransceiver::load(InArchive  &ia)\n{\n  ia>>nameValue(\"useableEpochs\",      useableEpochs);\n  ia>>nameValue(\"countUseableEpochs\", countUseableEpochs);\n  ia>>nameValue(\"signalBias\",         signalBias);\n}\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssTransmitter.h",
    "content": "/***********************************************/\n/**\n* @file gnssTransmitter.h\n*\n* @brief GNSS transmitter.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2013-06-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSTRANSMITTER__\n#define __GROOPS_GNSSTRANSMITTER__\n\n#include \"base/polynomial.h\"\n#include \"base/gnssType.h\"\n#include \"gnss/gnssTransceiver.h\"\n\n/** @addtogroup gnssGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass GnssTransmitter;\ntypedef std::shared_ptr<GnssTransmitter> GnssTransmitterPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for GNSS transmitter.\n* eg. GPS satellites. */\nclass GnssTransmitter : public GnssTransceiver\n{\n  GnssType                 type; // system + PRN\n  Polynomial               polynomial;\n  std::vector<Double>      clk, scale;\n  std::vector<Vector3d>    offset;   // between CoM and ARF in SRF\n  std::vector<Transform3d> crf2srf, srf2arf;\n\npublic:\n  std::vector<Time> timesPosVel;\n  Matrix            pos, vel; // CoM in CRF (epoch times (x,y,z))\n\n  GnssTransmitter(GnssType prn, const Platform &platform,\n                  GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction,\n                  const Vector &useableEpochs, const std::vector<Double> &clock, const std::vector<Double> &scale, const std::vector<Vector3d> &offset,\n                  const std::vector<Transform3d> &crf2srf, const std::vector<Transform3d> &srf2arf,\n                  const std::vector<Time> &timesPosVel, const_MatrixSliceRef position, const_MatrixSliceRef velocity, UInt interpolationDegree)\n  : GnssTransceiver(platform, noPatternFoundAction, useableEpochs),\n    type(prn), polynomial(timesPosVel, interpolationDegree, TRUE/*throwException*/, FALSE/*leastSquares*/, -(interpolationDegree+1.1), -1.1, 1e-7),\n    clk(clock), scale(scale), offset(offset), crf2srf(crf2srf), srf2arf(srf2arf), timesPosVel(timesPosVel), pos(position), vel(velocity) {}\n\n  /// Destructor.\n  virtual ~GnssTransmitter() {}\n\n  /** @brief Identify number in the GNSS system. */\n  UInt idTrans() const {return id_;}\n\n  /** @brief PRN number of satellite.\n  *  = prn + GnssType::SYSTEM. */\n  GnssType PRN() const {return type;}\n\n  /** @brief Clock error.\n  * error = clock time - system time [s] */\n  Double clockError(UInt idEpoch) const {return clk.at(idEpoch);}\n\n  /** @brief scale due to frequency offset/clock drift.\n  * observed = scaleFactor * true_range */\n  Double scaleFactor(UInt idEpoch) const {return scale.at(idEpoch);}\n\n  /** @brief set clock error.\n  * error = observed clock time - system time [s] */\n  void updateClockError(UInt idEpoch, Double deltaClock) {clk.at(idEpoch) += deltaClock;}\n\n  /** @brief center of mass in celestial reference frame (CRF). */\n  Vector3d positionCoM(const Time &time) const;\n\n  /** @brief antenna reference point in celestial reference frame (CRF). */\n  Vector3d position(UInt idEpoch, const Time &time) const {return positionCoM(time) + crf2srf.at(idEpoch).inverseTransform(offset.at(idEpoch));}\n\n  /** @brief velocity in CRF [m/s]. */\n  Vector3d velocity(const Time &time) const;\n\n  /** @brief Rotation from celestial reference frame (CRF) to left-handed antenna system. */\n  Transform3d celestial2antennaFrame(UInt idEpoch, const Time &/*time*/) const {return srf2arf.at(idEpoch) * crf2srf.at(idEpoch);}\n};\n\n/***********************************************/\n\ninline Vector3d GnssTransmitter::positionCoM(const Time &time) const\n{\n  try\n  {\n    return Vector3d(polynomial.interpolate({time}, pos));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d GnssTransmitter::velocity(const Time &time) const\n{\n  try\n  {\n    return Vector3d(polynomial.interpolate({time}, vel));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssTransmitterGenerator.cpp\n*\n* @brief Provides a list of transmitters.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_GnssTransmitterGenerator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"config/config.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGeneratorGnss.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(GnssTransmitterGenerator, \"gnssTransmitterGeneratorType\",\n                      GnssTransmitterGeneratorGnss)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(GnssTransmitterGenerator, \"gnssTransmitterGeneratorType\")\n\n/***********************************************/\n\nGnssTransmitterGenerator::GnssTransmitterGenerator(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"GNSS\", type, \"\"))\n        base.push_back(new GnssTransmitterGeneratorGnss(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGnssTransmitterGenerator::~GnssTransmitterGenerator()\n{\n  for(UInt i=0; i<base.size(); i++)\n    delete base.at(i);\n}\n\n/***********************************************/\n\nstd::vector<GnssTransmitterPtr> GnssTransmitterGenerator::transmitters(const std::vector<Time> &times)\n{\n  try\n  {\n    std::vector<GnssTransmitterPtr> transmitters;\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->init(times, transmitters);\n    return transmitters;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.h",
    "content": "/***********************************************/\n/**\n* @file gnssTransmitterGenerator.h\n*\n* @brief Provides a list of transmitters.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSTRANSMITTERGENERATOR__\n#define __GROOPS_GNSSTRANSMITTERGENERATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssTransmitterGenerator\nstatic const char *docstringGnssTransmitterGenerator = R\"(\n\\section{GnssTransmitterGenerator}\\label{gnssTransmitterGeneratorType}\nDefinition and basic information of GNSS transmitters.\n\nSee also \\program{GnssProcessing} and \\program{GnssSimulateReceiver}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"gnss/gnssTransmitter.h\"\n\n/**\n* @defgroup gnssTransmitterGeneratorGroup GnssTransmitterGenerator\n* @brief Provides a list of transmitters.\n* @ingroup classesGroup\n* The interface is given by @ref GnssTransmitterGenerator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass GnssTransmitterGenerator;\nclass GnssTransmitterGeneratorBase;\ntypedef std::shared_ptr<GnssTransmitterGenerator> GnssTransmitterGeneratorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of transmitters.\n* An Instance of this class can be created by @ref readConfig. */\nclass GnssTransmitterGenerator\n{\n  std::vector<GnssTransmitterGeneratorBase*> base;\n\npublic:\n  /** @brief Constructor from config. */\n  GnssTransmitterGenerator(Config &config, const std::string &name);\n\n  /// Destructor.\n ~GnssTransmitterGenerator();\n\n  /** @brief Iniatialize and returns a vector of transmitters. */\n  std::vector<GnssTransmitterPtr> transmitters(const std::vector<Time> &times);\n\n  /** @brief creates an derived instance of this class. */\n  static GnssTransmitterGeneratorPtr create(Config &config, const std::string &name) {return GnssTransmitterGeneratorPtr(new GnssTransmitterGenerator(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class GnssTransmitterGenerator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates GnssTransmitterGenerator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssTransmitterGeneratorPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass GnssTransmitterGeneratorBase\n{\npublic:\n  virtual ~GnssTransmitterGeneratorBase() {}\n  virtual void init(const std::vector<Time> &times, std::vector<GnssTransmitterPtr> &transmitters) = 0;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/gnss/gnssTransmitterGenerator/gnssTransmitterGeneratorGnss.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssTransmitterGeneratorGnss.cpp\n*\n* @brief Provides a list of GNSS transmitters.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileStringTable.h\"\n#include \"gnss/gnssTransmitter.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGeneratorGnss.h\"\n\n/***********************************************/\n\nGnssTransmitterGeneratorGnss::GnssTransmitterGeneratorGnss(Config &config)\n{\n  try\n  {\n    std::string choice;\n\n    readConfig(config, \"inputfileTransmitterList\",  fileNamesTransmitterList, Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/transmitterList.gps.txt\", \"ascii file with transmitter PRNs, used to loop variable {prn}\");\n    readConfig(config, \"inputfileTransmitterInfo\",  fileNameTransmitterInfo,  Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\", \"variable {prn} available\");\n    readConfig(config, \"inputfileAntennaDefintion\", fileNameAntennaDef,       Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\", \"phase centers and variations (ANTEX like)\");\n    if(readConfigChoice(config, \"noAntennaPatternFound\", choice, Config::MUSTSET, \"useNearestFrequency\", \"what should happen is no antenna pattern is found for an observation\"))\n    {\n      if(readConfigChoiceElement(config, \"ignoreObservation\",   choice, \"ignore observation if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::IGNORE_OBSERVATION;\n      if(readConfigChoiceElement(config, \"useNearestFrequency\", choice, \"use pattern of nearest frequency if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::USE_NEAREST_FREQUENCY;\n      if(readConfigChoiceElement(config, \"throwException\",      choice, \"throw exception if no matching pattern is found\"))\n        noPatternFoundAction = GnssAntennaDefinition::NoPatternFoundAction::THROW_EXCEPTION;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileSignalDefintion\",     fileNameSignalDef,   Config::OPTIONAL, \"{groopsDataDir}/gnss/transmitter/signalDefinition/signalDefinition.xml\", \"transmitted signal types\");\n    readConfig(config, \"inputfileClockFrequencyScale\", fileNameScale,       Config::OPTIONAL, \"\",                                 \"variable {prn} available\");\n    readConfig(config, \"inputfileOrbit\",               fileNameOrbit,       Config::MUSTSET,  \"orbit_{loopTime:%D}.{prn}.dat\",    \"variable {prn} available\");\n    readConfig(config, \"inputfileAttitude\",            fileNameAttitude,    Config::MUSTSET,  \"attitude_{loopTime:%D}.{prn}.dat\", \"variable {prn} available\");\n    readConfig(config, \"inputfileClock\",               fileNameClock,       Config::MUSTSET,  \"clock_{loopTime:%D}.{prn}.dat\",    \"variable {prn} available\");\n    readConfig(config, \"interpolateClock\",             interpolateClock,    Config::DEFAULT,  \"1\", \"linear interpolation of missing epochs\");\n    readConfig(config, \"interpolationDegree\",          interpolationDegree, Config::DEFAULT,  \"7\", \"for orbit interpolation and velocity calculation\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssTransmitterGeneratorGnss::init(const std::vector<Time> &times, std::vector<GnssTransmitterPtr> &transmitters)\n{\n  try\n  {\n    logStatus<<\"init transmitters\"<<Log::endl;\n\n    // read antenna definition\n    std::vector<GnssAntennaDefinitionPtr> antennaDefList;\n    readFileGnssAntennaDefinition(fileNameAntennaDef, antennaDefList);\n\n    // read receiver definition\n    std::vector<GnssReceiverDefinitionPtr> signalDefList;\n    if(!fileNameSignalDef.empty())\n      readFileGnssReceiverDefinition(fileNameSignalDef, signalDefList);\n\n    std::vector<std::string> transmitterList;\n    for(const auto &fileNameTransmitterList : fileNamesTransmitterList)\n    {\n      std::vector<std::string> list;\n      readFileStringList(fileNameTransmitterList, list);\n      transmitterList.insert(transmitterList.end(), list.begin(), list.end());\n    }\n    VariableList fileNameVariableList;\n    UInt countTrans = 0;\n    for(const std::string &prn : transmitterList)\n    {\n      try\n      {\n        fileNameVariableList.setVariable(\"prn\", prn);\n\n        Platform platform;\n        readFilePlatform(fileNameTransmitterInfo(fileNameVariableList), platform);\n        platform.name = prn;\n        platform.fillGnssAntennaDefinition(antennaDefList);\n        platform.fillGnssReceiverDefinition(signalDefList);\n        Vector useableEpochs(times.size(), TRUE);\n\n        // read orbit\n        // ----------\n        std::vector<Time> timesPosVel;\n        Matrix            pos, vel;\n        try\n        {\n          const OrbitArc arc = InstrumentFile::read(fileNameOrbit(fileNameVariableList));\n          timesPosVel = arc.times();\n          const Matrix data = arc.matrix();\n          pos = data.column(1, 3);\n          vel = data.column(4, 3);\n          // check possible data gaps\n          Polynomial polynomial(timesPosVel, interpolationDegree, FALSE/*throwException*/);\n          const Vector useable = polynomial.interpolate(times, Vector(pos.rows()));\n          for(UInt idEpoch=0; idEpoch<useable.rows(); idEpoch++)\n            if(std::isnan(useable(idEpoch)))\n              useableEpochs(idEpoch) = FALSE;\n        }\n        catch(std::exception &/*e*/)\n        {\n          logWarningOnce<<\"Unable to read orbit file <\"<<fileNameOrbit(fileNameVariableList)<<\">, disabling transmitter.\"<<Log::endl;\n          continue;\n        }\n\n        // read attitude\n        // -------------\n        std::vector<Transform3d> crf2srf(times.size());\n        try\n        {\n          const StarCameraArc arc = InstrumentFile::read(fileNameAttitude(fileNameVariableList));\n          Polynomial polynomial(arc.times(), interpolationDegree, FALSE/*throwException*/);\n          const Matrix quaternion = polynomial.interpolate(times, arc.matrix().column(1, 4));\n          for(UInt idEpoch=0; idEpoch<quaternion.rows(); idEpoch++)\n            if(!std::isnan(quaternion(idEpoch,0)))\n              crf2srf.at(idEpoch) = inverse(Rotary3d(quaternion.row(idEpoch).trans()/norm(quaternion.row(idEpoch))));\n            else\n              useableEpochs(idEpoch) = FALSE;\n        }\n        catch(std::exception &/*e*/)\n        {\n          logWarningOnce<<\"Unable to read attitude file <\"<<fileNameAttitude(fileNameVariableList)<<\">, disabling transmitter.\"<<Log::endl;\n          continue;\n        }\n\n        // satellite clocks\n        // ----------------\n        std::vector<Double> clock;\n        try\n        {\n          const MiscValueArc arc = InstrumentFile::read(fileNameClock(fileNameVariableList));\n          Polynomial polynomial(arc.times(), 1, FALSE/*throwException*/); // linear interpolation\n          if(!interpolateClock)\n            polynomial.init(arc.times(), 0, FALSE/*throwException*/, FALSE/*leastSquares*/, -1, 0);\n          clock = Vector(polynomial.interpolate(times, arc.matrix().column(1)));\n          for(UInt idEpoch=0; idEpoch<clock.size(); idEpoch++)\n            if(std::isnan(clock.at(idEpoch)))\n            {\n              useableEpochs(idEpoch) = FALSE;\n              clock.at(idEpoch) = 0.; // to prevent NAN propagation when using parametrization clocksModel\n            }\n        }\n        catch(std::exception &/*e*/)\n        {\n          logWarningOnce<<\"Unable to read clock file <\"<<fileNameClock(fileNameVariableList)<<\">, disabling transmitter.\"<<Log::endl;\n          continue;\n        }\n\n        // scale factor\n        // ------------\n        std::vector<Double> scale(times.size(), 1.);\n        if(!fileNameScale.empty())\n        {\n          try\n          {\n            const MiscValueArc arc = InstrumentFile::read(fileNameScale(fileNameVariableList));\n            Polynomial polynomial(arc.times(), 1, FALSE/*throwException*/); // linear interpolation\n            scale = Vector(polynomial.interpolate(times, arc.matrix().column(1)));\n            for(UInt idEpoch=0; idEpoch<scale.size(); idEpoch++)\n              if(std::isnan(scale.at(idEpoch)))\n                scale.at(idEpoch) = 1.; // to prevent NAN propagation when using parametrization clocksModel\n          }\n          catch(std::exception &/*e*/)\n          {\n            logWarningOnce<<\"Unable to read scale file <\"<<fileNameScale(fileNameVariableList)<<\">, ignoring.\"<<Log::endl;\n            scale = std::vector<Double>(times.size(), 1.);\n          }\n        }\n\n        // test completeness of antennas\n        for(const auto &instrument : platform.equipments)\n        {\n          auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n          if(antenna && antenna->timeEnd >= times.front() && antenna->timeStart < times.back() && !antenna->antennaDef)\n            logWarningOnce<<platform.markerName<<\".\"<<platform.markerNumber<<\": No antenna definition found for \"<<antenna->str()<<Log::endl;\n        }\n\n        std::vector<Vector3d>    offset(times.size());\n        std::vector<Transform3d> srf2arf(times.size());\n        for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n          if(useableEpochs(idEpoch))\n          {\n            auto antenna = platform.findEquipment<PlatformGnssAntenna>(times.at(idEpoch));\n            if(antenna && antenna->antennaDef)\n            {\n              offset.at(idEpoch)  = antenna->position - platform.referencePoint(times.at(idEpoch));\n              srf2arf.at(idEpoch) = antenna->local2antennaFrame;\n            }\n            else\n              useableEpochs(idEpoch) = FALSE;\n          }\n\n        // test useable\n        // ------------\n        const UInt countUseableEpochs = static_cast<UInt>(sum(useableEpochs));\n        if(!countUseableEpochs)\n        {\n          logWarningOnce<<platform.markerName<<\".\"<<platform.markerNumber<<\": No usable epochs, disabling transmitter.\"<<Log::endl;\n          continue;\n        }\n        if(countUseableEpochs < useableEpochs.rows())\n          logWarningOnce<<platform.markerName<<\".\"<<platform.markerNumber<<\": \"<<useableEpochs.rows()-countUseableEpochs<<\" epochs disabled due to missing orbit/attitude/clock data\"<<Log::endl;\n\n        transmitters.push_back(std::make_shared<GnssTransmitter>(GnssType(\"***\"+platform.markerNumber), platform, noPatternFoundAction,\n                                                                 useableEpochs, clock, scale, offset, crf2srf, srf2arf, timesPosVel, pos, vel, interpolationDegree));\n        countTrans++;\n      }\n      catch(std::exception &e)\n      {\n        logWarningOnce<<\"Unable to initialize satellite: \"<<e.what()<<Log::endl;\n      }\n    } // for(idTrans)\n\n    if(!countTrans)\n    {\n      fileNameVariableList.setVariable(\"prn\", \"***\");\n      logWarningOnce<<\"Initialization of all satellites failed. Wrong file name <\"<<fileNameOrbit(fileNameVariableList)<<\">?\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/gnss/gnssTransmitterGenerator/gnssTransmitterGeneratorGnss.h",
    "content": "/***********************************************/\n/**\n* @file gnssTransmitterGeneratorGnss.h\n*\n* @brief Provides a list of GNSS transmitters.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2021-02-25\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GNSSGNSSTRANSMITTERGENERATORGNSS__\n#define __GROOPS_GNSSGNSSTRANSMITTERGENERATORGNSS__\n\n// Latex documentation\n#ifdef DOCSTRING_GnssTransmitterGenerator\nstatic const char *docstringGnssTransmitterGeneratorGnss = R\"(\n\\subsection{GNSS}\\label{gnssTransmitterGeneratorType:gnss}\nA list of satellite PRNs (i.e for GPS: G01, G02, G03, ...) must be provided via\n\\configFile{inputfileTransmitterList}{stringList}. Satellite system codes follow the\n\\href{https://files.igs.org/pub/data/format/rinex305.pdf}{RINEX 3 definition}, see \\reference{GnssType}{gnssType}.\nAll input files except \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition},\nand \\configFile{inputfileReceiverDefinition}{gnssReceiverDefinition} are read for each satellite.\nThe file name is interpreted as a template with the variable \\verb|{prn}| being replaced by the satellite PRN.\n\nMetadata input files (marked with \\textbf{*} below) are provided in GROOPS file formats at\n\\url{https://ftp.tugraz.at/pub/ITSG/groops}. These files are regularly updated.\n\\begin{itemize}\n  \\item \\configFile{inputfileTransmitterInfo}{platform}\\textbf{*}:\n        PRN-SVN mapping, antenna offsets and orientations.\n        Created via \\program{GnssAntex2AntennaDefinition} or \\program{PlatformCreate}.\n  \\item \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\\textbf{*}:\n        Antenna center variations.\n        Created via \\program{GnssAntex2AntennaDefinition} or \\program{GnssAntennaDefinitionCreate}.\n  \\item \\configFile{inputfileSignalDefintion}{gnssReceiverDefinition}\\textbf{*}:\n        Transmitted signal types.\n        Created via \\program{GnssReceiverDefinitionCreate} in case you want to define which signal\n        types a satellite transmits.\n  \\item \\configFile{inputfileClockFrequencyScale}{instrument}\\textbf{*}:\n        Scale factor of transmitted signals due to frequency offset/clock drift.\n        Can be dreived from broadcast clocks drifts.\n  \\item \\configFile{inputfileOrbit}{instrument}: Converted via \\program{Sp3Format2Orbit} or\n        output of \\program{GnssProcessing}.\n  \\item \\configFile{inputfileAttitude}{instrument}:\n        Rotation from body frame to CRF. Created via \\program{SimulateStarCameraGnss} or converted via \\program{GnssOrbex2StarCamera}.\n  \\item \\configFile{inputfileClock}{instrument}:\n        Converted via \\program{GnssClockRinex2InstrumentClock} or \\program{GnssRinexNavigation2OrbitClock} or\n        output of \\program{GnssProcessing}.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of GNSS transmitters.\n* @ingroup gnssTransmitterGeneratorGroup\n* @see GnssTransmitterGenerator */\nclass GnssTransmitterGeneratorGnss : public GnssTransmitterGeneratorBase\n{\n  std::vector<FileName> fileNamesTransmitterList;\n  FileName              fileNameTransmitterInfo, fileNameAntennaDef, fileNameSignalDef;\n  FileName              fileNameOrbit, fileNameAttitude, fileNameClock, fileNameScale;\n  Bool                  interpolateClock;\n  UInt                  interpolationDegree;\n  GnssAntennaDefinition::NoPatternFoundAction noPatternFoundAction;\n\npublic:\n  GnssTransmitterGeneratorGnss(Config &config);\n  void init(const std::vector<Time> &times, std::vector<GnssTransmitterPtr> &transmitters) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/groops.cpp",
    "content": "/***********************************************/\n/**\n* @file groops.cpp\n*\n* @brief main.\n*\n* @author Torsten Mayer-Guerr\n* @date 2007\n*\n*/\n/***********************************************/\n\n/**\n* @mainpage\n*\n@verbatim\nGravity Recovery Object Oriented Programming System (GROOPS)\nUsage: groops [--log <logfile.txt>] [--settings <groopsDefaults.xml>] [--silent] [--global name=value] <configfile.xml>\n       groops --write-settings <groopsDefaults.xml>\n       groops --xsd <schemafile.xsd>\n       groops --doc <documentation/>\n\n-h, --help           this text\n-l, --log            append messages to logfile. If a directory is given, one time-stamped logfile will be created inside for each groops script.\n-g, --global         pass a global variable to config files as name=value pair\n-c, --settings       read constants from file (default search: groopsDefaults.xml)\n-s, --silent         runs silently\n-d, --doc            generate documentation files (latex/html/...) within the given directory\n-x, --xsd            write xsd-schema of xml-configfile options\n-C, --write-settings write the users current settings to file\n\nGitHub repository: https://github.com/groops-devs/groops\n@endverbatim\n*/\n\n/** @defgroup base Base\n* @brief Basic functions and classes. */\n\n/** @defgroup parserGroup Parser\n* @brief XML, mathematical expression and string parser. */\n\n/** @defgroup inputOutputGroup Input/Output\n* @brief Low level input/output. */\n\n/** @defgroup parallelGroup Parallel\n* @brief Wrapper for Message Passing Interface (MPI). */\n\n/** @defgroup filesGroup File formats\n* @brief Definition of groops file formats. */\n\n/** @defgroup configGroup Config\n* @brief Config and documentation. */\n\n/** @defgroup classesGroup Classes\n* @brief Abstract interfaces. */\n\n/** @defgroup gnssGroup GNSS\n* @brief Global Navigation Satellite Systems. */\n\n/** @defgroup slrGroup SLR\n* @brief Satellite Laser Ranging. */\n\n/** @defgroup plotGroup Plots\n* @brief Classes and functions for plotting. */\n\n/** @defgroup miscGroup Misc\n* @brief Classes and functions which do not fit into other groups. */\n\n/** @defgroup programsGroup Programs\n* @brief The Apps. */\n\n/** @defgroup programsConversionGroup Programs/conversion\n* @ingroup programsGroup\n* @brief Programs for conversion of strange formats. */\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/settings.h\"\n#include \"inputOutput/system.h\"\n#include \"config/generateDocumentation.h\"\n\n/***********************************************/\n\nstatic void groopsHelp(const std::string &progName, Parallel::CommunicatorPtr comm)\n{\n  if(Parallel::isMaster(comm))\n  {\n    std::cout<<\"Gravity Recovery Object Oriented Programming System (GROOPS)\"<<std::endl;\n    std::cout<<\"Usage: \"<<progName<<\" [--log <logfile.txt>] [--settings <groopsDefaults.xml>] [--silent] [--global name=value] <configfile.xml>\"<<std::endl;\n    std::cout<<\"       \"<<progName<<\" --write-settings <groopsDefaults.xml>\"<<std::endl;\n    std::cout<<\"       \"<<progName<<\" --xsd <schemafile.xsd>\"<<std::endl;\n    std::cout<<\"       \"<<progName<<\" --doc <documentation/>\"<<std::endl;\n    std::cout<<std::endl;\n    std::cout<<\" -h, --help           this text\"<<std::endl;\n    std::cout<<\" -l, --log            append messages to logfile. If a directory is given, one time-stamped logfile will be created inside for each groops script.\"<<std::endl;\n    std::cout<<\" -g, --global         pass a global variable to config files as name=value pair\"<<std::endl;\n    std::cout<<\" -c, --settings       read constants from file (default search: groopsDefaults.xml)\"<<std::endl;\n    std::cout<<\" -s, --silent         runs silently\"<<std::endl;\n    std::cout<<\" -d, --doc            generate documentation files (latex/html/...)\"<<std::endl;\n    std::cout<<\" -x, --xsd            write xsd-schema of xml-configfile options\"<<std::endl;\n    std::cout<<\" -C, --write-settings write the users current settings to file\"<<std::endl;\n    std::cout<<\"\"<<std::endl;\n    std::cout<<\"GitHub repository: https://github.com/groops-devs/groops\"<<std::endl;\n    std::cout<<\"(Compiled: \"<<__DATE__<<\" \"<<__TIME__<<\")\"<<std::endl;\n  }\n  exit(EXIT_FAILURE);\n}\n\n/***********************************************/\n\nint main(int argc, char *argv[])\n{\n  Parallel::CommunicatorPtr comm = Parallel::init(argc, argv);\n  // init parallel logging\n  Log::init(Parallel::myRank(comm), Parallel::size(comm), Parallel::addChannel(Log::getReceive(), comm));\n  Log::GroupPtr groupPtr;\n\n  try\n  {\n    Parallel::broadCastExceptions(comm, [&](Parallel::CommunicatorPtr comm)\n    {\n      // handle commandline options\n      // --------------------------\n      FileName logFileName;\n      FileName schemaFileName;\n      FileName docFileName;\n      FileName settingsFileName;\n      FileName writeSettingsFileName;\n      Bool     silent   = FALSE;\n      Bool     workDone = FALSE;\n      std::map<std::string, std::string> commandlineGlobals;\n      std::vector<FileName> configFileNames;\n\n      for(int i=1; i<argc; i++)\n      {\n        auto optArg = [&]()\n        {\n          if((i+1 >= argc) || (argv[i+1][0] == '-'))\n          {\n            logWarningOnce<<\"Expected argument for: '\"<<argv[i]<<\"'\"<<Log::endl;\n            groopsHelp(argv[0], comm);\n            return std::string();\n          }\n          return std::string(argv[++i]);\n        };\n\n        const std::string opt(argv[i]);\n        if     ((opt == \"-l\") || (opt == \"--log\"))            {logFileName           = FileName(optArg());}\n        else if((opt == \"-x\") || (opt == \"--xsd\"))            {schemaFileName        = FileName(optArg());}\n        else if((opt == \"-d\") || (opt == \"--doc\"))            {docFileName           = FileName(optArg());}\n        else if((opt == \"-c\") || (opt == \"--settings\"))       {settingsFileName      = FileName(optArg());}\n        else if((opt == \"-C\") || (opt == \"--write-settings\")) {writeSettingsFileName = FileName(optArg());}\n        else if((opt == \"-s\") || (opt == \"--silent\"))         {silent = TRUE;}\n        else if((opt == \"-h\") || (opt == \"--help\"))           {groopsHelp(argv[0], comm);}\n        else if((opt == \"-g\") || (opt == \"--global\"))\n        {\n          std::string keyVal(optArg());\n          std::size_t delim = keyVal.find(\"=\");\n          if(delim == std::string::npos || delim+1 == keyVal.size())\n          {\n            logWarningOnce<<\"Unable to parse key-value pair <\"<<keyVal<<\"> for option '-g'.\"<<Log::endl;\n            groopsHelp(argv[0], comm);\n          }\n          else\n            commandlineGlobals[keyVal.substr(0, delim)] = keyVal.substr(delim+1);\n        }\n        else if(opt[0] == '-')\n        {\n          logWarningOnce<<\"Unknown option: '\"<<opt<<\"'\"<<Log::endl;\n          groopsHelp(argv[0], comm);\n        }\n        else\n        {\n          configFileNames.push_back(FileName(opt));\n        }\n      }\n\n      // ============================================\n\n      // start logging\n      // -------------\n      groupPtr = Log::group(Parallel::isMaster(comm), silent);\n      if(!System::isDirectory(logFileName))\n        Log::setLogFile(logFileName);\n      if(Parallel::size(comm) > 1)\n        logStatus<<\"=== Starting GROOPS with \"<<Parallel::size(comm)<<\" processes ===\"<<Log::endl;\n      else\n        logStatus<<\"=== Starting GROOPS ===\"<<Log::endl;\n\n      // read default settings and constants\n      // -----------------------------------\n      if(!settingsFileName.empty())\n      {\n        logInfo<<\"settings: <\"<<settingsFileName<<\">\"<<Log::endl;\n        readFileSettings(settingsFileName);\n      }\n      else // exists groopsDefaults.xml?\n      {\n        settingsFileName = \"groopsDefaults.xml\";\n        if(System::exists(settingsFileName))\n        {\n          logInfo<<\"settings: <\"<<settingsFileName<<\">\"<<Log::endl;\n          readFileSettings(settingsFileName);\n        }\n      }\n\n      // writing xsd schema file\n      // ------------------------\n      if(!schemaFileName.empty())\n      {\n        workDone = TRUE;\n        logStatus<<\"writing xsd schema file: <\"<<schemaFileName<<\">\"<<Log::endl;\n        if(Parallel::isMaster(comm))\n          Config::writeSchema(schemaFileName);\n      }\n\n      // generate documentation\n      // ----------------------\n      if(!docFileName.empty())\n      {\n        workDone = TRUE;\n        logStatus<<\"generate documentation files in <\"<<docFileName<<\">\"<<Log::endl;\n        if(Parallel::isMaster(comm))\n          Documentation::write(docFileName);\n      }\n\n      // write settings\n      // --------------\n      if(!writeSettingsFileName.empty())\n      {\n        workDone = TRUE;\n        logStatus<<\"writing settings file: <\"<<writeSettingsFileName<<\">\"<<Log::endl;\n        if(Parallel::isMaster(comm))\n          writeFileSettings(writeSettingsFileName);\n      }\n\n      // Starting Programs\n      // -----------------\n      for(auto &configFileName : configFileNames)\n      {\n        // If the user specifies a directory as the logging target,\n        // a time-stamped log file is created under that directory for each groops script,\n        // and log output for that script is redirected there.\n        if(System::isDirectory(logFileName))\n        {\n          FileName thisLogFileName = logFileName.append(configFileName.stripDirectory().str()+\"_\"+System::now().dateTimeStr()+\".log\");\n          logInfo<<\"Future logs are written to file <\"<<thisLogFileName<<\">\"<<Log::endl;\n          Log::setLogFile(thisLogFileName);\n        }\n\n        logInfo<<\"Config file: <\"<<configFileName<<\">\"<<Log::endl;\n        Config config(configFileName, commandlineGlobals);\n        ProgramConfig programs;\n        readConfig(config, \"program\", programs, Config::OPTIONAL, \"\", \"\");\n        VariableList varList;\n        programs.run(varList, comm);\n        workDone = TRUE;\n      }\n\n      // ============================================\n\n      if(!workDone)\n        groopsHelp(argv[0], comm);\n\n      Parallel::barrier(comm);\n      logStatus<<\"=== Finished GROOPS ===\"<<Log::endl;\n      Parallel::barrier(comm);\n    }); // Parallel::broadCastExceptions()\n  }\n  catch(std::exception &e)\n  {\n    if(Parallel::isMaster(comm))\n    {\n      logError<<\"****** Error ******\"<<Log::endl;\n      logError<<e.what()<<Log::endl;\n      logStatus<<\"=== Finished GROOPS with error ===\"<<Log::endl;\n    }\n    return EXIT_FAILURE;\n  }\n\n  return EXIT_SUCCESS;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/archive.cpp",
    "content": "/***********************************************/\n/**\n* @file archive.cpp\n*\n* @brief Interface for streaming of data in different formats.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-01\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"base/vector3d.h\"\n#include \"base/tensor3d.h\"\n#include \"base/rotary3d.h\"\n#include \"base/transform3d.h\"\n#include \"base/ellipsoid.h\"\n#include \"archive.h\"\n\n/***********************************************/\n\nUInt InArchive::versionStr2version(const std::string &str)\n{\n  if(str.empty())\n    return 0;\n  if(str == \"1.1\")\n    return 1;\n  if(str == \"1.2\")\n    return 2;\n  std::stringstream ss(str);\n  UInt v;\n  ss>>v;\n  return v;\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const Vector3d &x)\n{\n  ar<<nameValue(\"x\", x.x())<<nameValue(\"y\", x.y())<<nameValue(\"z\", x.z());\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, Vector3d &x)\n{\n  ar>>nameValue(\"x\", x.x())>>nameValue(\"y\", x.y())>>nameValue(\"z\", x.z());\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const Tensor3d &x)\n{\n  ar<<nameValue(\"xx\", x.xx())<<nameValue(\"yy\", x.yy())<<nameValue(\"zz\", x.zz());\n  ar<<nameValue(\"xy\", x.xy())<<nameValue(\"xz\", x.xz())<<nameValue(\"yz\", x.yz());\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, Tensor3d &x)\n{\n  if(ar.version() < 20170920)\n  {\n    ar>>nameValue(\"xx\", x.xx())>>nameValue(\"xy\", x.xy())>>nameValue(\"xz\", x.xz());\n    ar>>nameValue(\"yy\", x.yy())>>nameValue(\"yz\", x.yz());\n    ar>>nameValue(\"zz\", x.zz());\n    return;\n  }\n\n  ar>>nameValue(\"xx\", x.xx())>>nameValue(\"yy\", x.yy())>>nameValue(\"zz\", x.zz());\n  ar>>nameValue(\"xy\", x.xy())>>nameValue(\"xz\", x.xz())>>nameValue(\"yz\", x.yz());\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const Rotary3d &x)\n{\n  Vector q = x.quaternion();\n  ar<<nameValue(\"q0\", q(0));\n  ar<<nameValue(\"qx\", q(1));\n  ar<<nameValue(\"qy\", q(2));\n  ar<<nameValue(\"qz\", q(3));\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, Rotary3d &x)\n{\n  if(ar.version() < 20170920)\n  {\n    Matrix R(3, 3, Matrix::NOFILL);\n    ar>>nameValue(\"xx\", R(0,0))>>nameValue(\"xy\", R(0,1))>>nameValue(\"xz\", R(0,2));\n    ar>>nameValue(\"yx\", R(1,0))>>nameValue(\"yy\", R(1,1))>>nameValue(\"yz\", R(1,2));\n    ar>>nameValue(\"zx\", R(2,0))>>nameValue(\"zy\", R(2,1))>>nameValue(\"zz\", R(2,2));\n    x = Rotary3d(R);\n    return;\n  }\n\n  Vector q(4);\n  ar>>nameValue(\"q0\", q(0));\n  ar>>nameValue(\"qx\", q(1));\n  ar>>nameValue(\"qy\", q(2));\n  ar>>nameValue(\"qz\", q(3));\n  x = Rotary3d(q);\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const Transform3d &x)\n{\n  Matrix R = x.matrix();\n  ar<<nameValue(\"xx\", R(0,0))<<nameValue(\"xy\", R(0,1))<<nameValue(\"xz\", R(0,2));\n  ar<<nameValue(\"yx\", R(1,0))<<nameValue(\"yy\", R(1,1))<<nameValue(\"yz\", R(1,2));\n  ar<<nameValue(\"zx\", R(2,0))<<nameValue(\"zy\", R(2,1))<<nameValue(\"zz\", R(2,2));\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, Transform3d &x)\n{\n  std::array<std::array<Double,3>,3> T;\n  ar>>nameValue(\"xx\", T[0][0])>>nameValue(\"xy\", T[0][1])>>nameValue(\"xz\", T[0][2]);\n  ar>>nameValue(\"yx\", T[1][0])>>nameValue(\"yy\", T[1][1])>>nameValue(\"yz\", T[1][2]);\n  ar>>nameValue(\"zx\", T[2][0])>>nameValue(\"zy\", T[2][1])>>nameValue(\"zz\", T[2][2]);\n  x = Transform3d(T);\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<> void save(OutArchive &ar, const Ellipsoid &x)\n{\n  ar<<nameValue(\"a\", x.a())<<nameValue(\"b\", x.b());\n}\n\n/***********************************************/\n\ntemplate<> void load(InArchive  &ar, Ellipsoid &x)\n{\n  Double a,b;\n  ar>>nameValue(\"a\", a)>>nameValue(\"b\", b);\n  x = Ellipsoid(a, ((a-b)!=0.) ? a/(a-b) : 0.0);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/archive.h",
    "content": "/***********************************************/\n/**\n* @file archive.h\n*\n* @brief Interface for streaming of data in different formats.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ARCHIVE__\n#define __GROOPS_ARCHIVE__\n\n#include \"base/importStd.h\"\n\n/** @defgroup archiveGroup Archive\n* @brief Streaming of data in different formats.\n* @ingroup inputOutputGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Time;\nclass Angle;\nclass Vector;\nclass Matrix;\nclass MatrixSlice;\nclass const_MatrixSlice;\nclass SphericalHarmonics;\nclass Doodson;\nclass GnssType;\nclass Vector3d;\nclass Tensor3d;\nclass Rotary3d;\nclass Transform3d;\nclass Ellipsoid;\n\n/***** CLASS ***********************************/\n\n/** @brief Identifier for values in archives.\n* Values need an identifier in xml format. */\ntemplate<typename T> class const_NameValue\n{\n  const char *_name;\n  const T    *_value;\npublic:\n  const_NameValue(const char *name, const T &value) : _name(name), _value(&value) {} //!< Constructor\n  const char *name()  const {return _name;}   //!< name\n  const T    &value() const {return *_value;} //!< value\n};\n\n/** @brief Adapter for const_NameValue. */\ntemplate<typename T>\ninline const const_NameValue<T> nameValue(const char *name, const T &x) {return const_NameValue<T>(name,x);}\n\n/***** CLASS ***********************************/\n\n/** @brief Identifier for values in archives.\n* Values need an identifier in xml format. */\ntemplate<typename T> class NameValue\n{\n  const char *_name;\n  T          *_value;\npublic:\n  NameValue(const char *name, T &value) : _name(name), _value(&value) {} //!< Constructor\n  const char *name()  const {return _name;}   //!< name\n  T          &value() const {return *_value;} //!< value\n};\n\n/** @brief Adapter for NameValue. */\ntemplate<typename T>\ninline const NameValue<T> nameValue(const char *name, T &x) {return NameValue<T>(name,x);}\n\n\n/***** CLASS ***********************************/\n\n/** @brief Grouping values in archives.\n* It is used in xml format. */\nclass BeginGroup\n{\npublic:\n  const char *name; //!< name\n  BeginGroup(const char *_name) : name(_name) {} //!< Constructor\n};\n\n/** @brief Adapter for BeginGroup. */\ninline const BeginGroup beginGroup(const char *name) {return BeginGroup(name);}\n\n/***** CLASS ***********************************/\n\n/** @brief Grouping values in archives.\n* It is used in xml format. */\nclass EndGroup\n{\npublic:\n  const char *name; //!< name\n  EndGroup(const char *_name) : name(_name) {} //!< Constructor\n};\n\n/** @brief Adapter for EndGroup. */\ninline const EndGroup endGroup(const char *name) {return EndGroup(name);}\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n/** @brief Abstract interface for output archives. */\nclass OutArchive\n{\npublic:\n  virtual ~OutArchive() {}\n\n  enum ArchiveType {ASCII, XML, JSON, BINARY};\n  virtual ArchiveType archiveType() const = 0;\n\n  template<typename T> OutArchive &operator<<(const NameValue<T> &nv);\n  template<typename T> OutArchive &operator<<(const const_NameValue<T> &nv);\n  OutArchive &operator<<(const BeginGroup   &gr);\n  OutArchive &operator<<(const EndGroup     &gr);\n\n  virtual void save(const std::string &x) = 0;\n  virtual void save(const Int      &x) = 0;\n  virtual void save(const UInt     &x) = 0;\n  virtual void save(const Double   &x) = 0;\n  virtual void save(const Bool     &x) = 0;\n  virtual void save(const Time     &x) = 0;\n  virtual void save(const Angle    &x) = 0;\n  virtual void save(const Vector   &x) = 0;\n  virtual void save(const const_MatrixSlice  &x) = 0;\n  virtual void save(const SphericalHarmonics &x) = 0;\n  virtual void save(const Doodson  &x) = 0;\n  virtual void save(const GnssType &x) = 0;\n\n  virtual void startTag(const std::string &/*name*/) {}\n  virtual void endTag  (const std::string &/*name*/) {}\n  virtual void endLine() {}\n  virtual void comment(const std::string &/*text*/) {}\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract interface for input archives. */\nclass InArchive\n{\nprotected:\n  static UInt versionStr2version(const std::string &str);\n\npublic:\n  virtual ~InArchive() {}\n\n  template<typename T>\n  InArchive &operator>>(const NameValue<T> &nv);\n  InArchive &operator>>(const BeginGroup   &gr);\n  InArchive &operator>>(const EndGroup     &gr);\n\n  enum ArchiveType {ASCII, XML, JSON, BINARY};\n  virtual ArchiveType archiveType() const = 0;\n  virtual std::string type()        const = 0;\n  virtual UInt        version()     const = 0;\n\n  virtual void startTag(const std::string &/*name*/) {}\n  virtual void endTag  (const std::string &/*name*/) {}\n\n  virtual void load(std::string &x) = 0;\n  virtual void load(Int      &x) = 0;\n  virtual void load(UInt     &x) = 0;\n  virtual void load(Double   &x) = 0;\n  virtual void load(Bool     &x) = 0;\n  virtual void load(Time     &x) = 0;\n  virtual void load(Angle    &x) = 0;\n  virtual void load(Vector   &x) = 0;\n  virtual void load(Matrix   &x) = 0;\n  virtual void load(SphericalHarmonics &x) = 0;\n  virtual void load(Doodson  &x) = 0;\n  virtual void load(GnssType &x) = 0;\n};\n\n/***** FUNCTIONS *******************************/\n\ntemplate<typename T> void save(OutArchive &ar, const std::vector<T> &x);\ntemplate<typename T> inline void save(OutArchive &ar, const T &x)        {x.save(ar);}\ntemplate<> inline void save(OutArchive &ar, const std::string &x)        {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Int     &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const UInt    &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Double  &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Bool    &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Time    &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Angle   &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Vector  &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Matrix  &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const MatrixSlice  &x)       {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const const_MatrixSlice  &x) {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const SphericalHarmonics &x) {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const Doodson &x)            {ar.save(x);}\ntemplate<> inline void save(OutArchive &ar, const GnssType &x)           {ar.save(x);}\ntemplate<> void save(OutArchive &ar, const Vector3d &x);\ntemplate<> void save(OutArchive &ar, const Tensor3d &x);\ntemplate<> void save(OutArchive &ar, const Rotary3d &x);\ntemplate<> void save(OutArchive &ar, const Transform3d &x);\ntemplate<> void save(OutArchive &ar, const Ellipsoid &x);\n\ntemplate<typename T> void load(InArchive  &ar, std::vector<T> &x);\ntemplate<typename T> inline void load(InArchive &ar, T &x)               {x.load(ar);}\ntemplate<> inline void load(InArchive  &ar, std::string &x)              {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Int     &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, UInt    &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Double  &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Bool    &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Time    &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Angle   &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Vector  &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Matrix  &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, SphericalHarmonics &x)       {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, Doodson &x)                  {ar.load(x);}\ntemplate<> inline void load(InArchive  &ar, GnssType &x)                 {ar.load(x);}\ntemplate<> void load(InArchive  &ar, Vector3d  &x);\ntemplate<> void load(InArchive  &ar, Tensor3d  &x);\ntemplate<> void load(InArchive  &ar, Rotary3d  &x);\ntemplate<> void load(InArchive  &ar, Transform3d &x);\ntemplate<> void load(InArchive  &ar, Ellipsoid &x);\n\n/// @}\n\n/***********************************************/\n/***** INLINES ***********************************/\n/***********************************************/\n\ntemplate<typename T> void save(OutArchive &ar, const std::vector<T> &x)\n{\n  UInt size = x.size();\n  ar<<nameValue(\"count\", size);\n  ar.endLine();\n  for(UInt i=0; i<size; i++)\n  {\n    ar<<nameValue(\"cell\", const_cast<std::vector<T>&>(x).at(i));\n    ar.endLine();\n  }\n}\n\n/***********************************************/\n\ntemplate<typename T> void load(InArchive  &ar, std::vector<T> &x)\n{\n  UInt size;\n  ar>>nameValue(\"count\", size);\n  x.resize(size);\n  for(UInt i=0; i<size; i++)\n    ar>>nameValue(\"cell\", x.at(i));\n}\n\n/***********************************************/\n/***********************************************/\n\ninline OutArchive &OutArchive::operator<<(const BeginGroup &gr)\n{\n  startTag(gr.name);\n  endLine();\n  return *this;\n}\n\n/***********************************************/\n\ninline InArchive &InArchive::operator>>(const BeginGroup &gr)\n{\n  startTag(gr.name);\n  return *this;\n}\n\n/***********************************************/\n\ninline OutArchive &OutArchive::operator<<(const EndGroup &gr)\n{\n  endTag(gr.name);\n  endLine();\n  return *this;\n}\n\n/***********************************************/\n\ninline InArchive &InArchive::operator>>(const EndGroup &gr)\n{\n  endTag(gr.name);\n  return *this;\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline OutArchive &OutArchive::operator<<(const const_NameValue<T> &nv)\n{\n  startTag(nv.name());\n  ::save(*this,nv.value());\n  endTag(nv.name());\n  return *this;\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline OutArchive &OutArchive::operator<<(const NameValue<T> &nv)\n{\n  startTag(nv.name());\n  ::save(*this,nv.value());\n  endTag(nv.name());\n  return *this;\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline InArchive &InArchive::operator>>(const NameValue<T> &nv)\n{\n  startTag(nv.name());\n  ::load(*this,nv.value());\n  endTag(nv.name());\n  return *this;\n}\n\n/***********************************************/\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/inputOutput/archiveAscii.cpp",
    "content": "/***********************************************/\n/**\n* @file archiveAscii.cpp\n*\n* @brief Write/read archives in ASCII format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-11-12\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/doodson.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/gnssType.h\"\n#include \"archive.h\"\n#include \"archiveAscii.h\"\n\n/***********************************************/\n\nOutArchiveAscii::OutArchiveAscii(std::ostream &_stream, const std::string &type, UInt version) : stream(_stream)\n{\n  i_width = 10;\n  isNewLine = TRUE;\n\n  stream<<\"groops\";\n  if(!type.empty())\n    stream<<\" \"<<type;\n  if(version)\n    stream<<\" version=\"<<version;\n  stream<<std::endl;\n}\n\n/***********************************************/\n\nvoid OutArchiveAscii::endLine()\n{\n  if(!isNewLine)\n    stream<<std::endl;\n  isNewLine = TRUE;\n}\n\n/***********************************************/\n\nvoid OutArchiveAscii::comment(const std::string &text)\n{\n  if(text.empty())\n    return;\n  endLine();\n  stream<<\"# \"<<text<<std::endl;\n}\n\n/***********************************************/\n\nvoid OutArchiveAscii::saveDouble(Double x, Int width, Int precision, Bool science)\n{\n  if(science)\n    stream.setf(std::ios::scientific,std::ios::floatfield);\n  else\n    stream.setf(std::ios::fixed,std::ios::floatfield);\n  stream.width(width);\n  stream.precision(precision);\n  stream<<x;\n}\n\n/***********************************************/\n/***********************************************/\n\nInArchiveAscii::InArchiveAscii(std::istream &_stream) : stream(_stream), _version(0)\n{\n  stripComments();\n\n  char c;\n  stream>>c;\n  stream.putback(c);\n  if(c!='g')\n    return;\n\n  // headerline\n  std::string line;\n  std::getline(stream, line);\n  if(stream.fail() || line.empty())\n    return;\n  std::stringstream ss(line);\n  std::string text;\n  ss>>text;\n  if(text!=\"groops\")\n    throw(Exception(\"in InArchiveAscii: 'groops' expected\"));\n\n  // type\n  ss>>text;\n  if(ss.fail())\n    return;\n  if(text.find(\"version=\")==std::string::npos)\n  {\n    typeStr = text;\n    ss>>text;\n    if(ss.fail())\n      return;\n  }\n\n  // text contains now version\n  if(text.find(\"version=\")==std::string::npos)\n    throw(Exception(\"in InArchiveAscii: 'version=' expected:\"+text));\n  _version = versionStr2version(text.substr(8));\n}\n\n/***********************************************/\n\nvoid InArchiveAscii::stripComments()\n{\n  try\n  {\n    char c;\n    stream>>c;\n    stream.putback(c);\n    if(c!='#')\n      return;\n    std::string s;\n    std::getline(stream, s); // skip rest of line\n    stripComments();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble InArchiveAscii::readDouble(std::istream &stream_)\n{\n  try\n  {\n    std::string dummy;\n    stream_>>dummy;\n\n    auto dpos = dummy.find_first_of(\"Dd\");\n    if(dpos != std::string::npos)\n      dummy[dpos] = 'e';\n\n    try\n    {\n      return std::stod(dummy);\n    }\n    catch(std::invalid_argument &)\n    {\n      throw(Exception(\"cannot read number: \"+dummy));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nvoid OutArchiveAscii::save(const Int      &x) {stream<<' '<<std::setw(i_width)<<x; isNewLine = FALSE;}\nvoid OutArchiveAscii::save(const UInt     &x) {stream<<' '<<std::setw(i_width)<<x; isNewLine = FALSE;}\nvoid OutArchiveAscii::save(const Double   &x) {saveDouble(x);                      isNewLine = FALSE;}\nvoid OutArchiveAscii::save(const Bool     &x) {stream<<' '<<x;                     isNewLine = FALSE;}\nvoid OutArchiveAscii::save(const Angle    &x) {saveDouble(x*RAD2DEG);              isNewLine = FALSE;}\nvoid OutArchiveAscii::save(const Doodson  &x) {stream<<' '<<x.code();              isNewLine = FALSE;}\nvoid OutArchiveAscii::save(const GnssType &x) {stream<<' '<<x.str();               isNewLine = FALSE;}\n\n/***********************************************/\n\nvoid InArchiveAscii::load(std::string &x) {stripComments(); stream>>std::quoted(x);}\nvoid InArchiveAscii::load(Int         &x) {stripComments(); stream>>x;}\nvoid InArchiveAscii::load(UInt        &x) {stripComments(); stream>>x;}\nvoid InArchiveAscii::load(Double      &x) {stripComments(); x = readDouble(stream);}\nvoid InArchiveAscii::load(Bool        &x) {stripComments(); stream>>x;}\nvoid InArchiveAscii::load(Angle       &x) {stripComments(); Double w = readDouble(stream); x = Angle(w*DEG2RAD);}\nvoid InArchiveAscii::load(Doodson     &x) {stripComments(); std::string s; stream>>s; x = Doodson(s);}\nvoid InArchiveAscii::load(GnssType    &x) {stripComments(); std::string s; stream>>s; x = GnssType(s);}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveAscii::save(const std::string &x)\n{\n  try\n  {\n    stream<<' ';\n    if((!x.empty()) && (x.find_first_of(\" \\t\\n\\\"#\") == std::string::npos))\n      stream<<x; // string without special characters\n    else\n      stream<<std::quoted(x);\n    isNewLine = FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid OutArchiveAscii::save(const Time &x)\n{\n  try\n  {\n    isNewLine = FALSE;\n\n    LongDouble mjd = x.mjdMod();\n    mjd += x.mjdInt();\n\n    stream<<' ';\n    stream.setf(std::ios::fixed,std::ios::floatfield);\n    stream.width(5+1+18);\n    stream.precision(18);\n    stream<<mjd;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveAscii::load(Time &x)\n{\n  try\n  {\n    stripComments();\n    LongDouble mjd;\n    stream>>mjd;\n\n    Int mjdInt = static_cast<Int>(std::floor(mjd));\n    x = Time(mjdInt, static_cast<Double>(mjd-mjdInt));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveAscii::save(const Vector &x)\n{\n  Matrix A = x;\n  save(A);\n}\n\n/***********************************************/\n\nvoid InArchiveAscii::load(Vector &x)\n{\n  Matrix A;\n  load(A);\n  x = A;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveAscii::save(const const_MatrixSlice &A)\n{\n  try\n  {\n    endLine();\n\n    if(A.getType()==Matrix::GENERAL)\n    {\n      stream<<\"Matrix( \"<<A.rows()<<\" x \"<<A.columns()<<\" )\"<<std::endl;\n      for(UInt i=0; i<A.rows(); i++)\n      {\n        for(UInt k=0; k<A.columns(); k++)\n          saveDouble(A(i,k));\n        stream<<std::endl;\n      }\n      stream<<std::endl;\n      return;\n    }\n\n    if(A.isUpper())\n      stream<<\"Upper\";\n    else\n      stream<<\"Lower\";\n    if(A.getType()==Matrix::TRIANGULAR)\n      stream<<\"TriangularMatrix\";\n    else if(A.getType()==Matrix::SYMMETRIC)\n      stream<<\"SymmetricMatrix\";\n    stream<<\"( \"<<A.rows()<<\" x \"<<A.columns()<<\" )\"<<std::endl;\n\n    if(A.isUpper())\n    {\n      for(UInt i=0; i<A.rows(); i++)\n      {\n        for(UInt k=i; k<A.columns(); k++)\n          saveDouble(A(i,k));\n        stream<<std::endl;\n      }\n    }\n    else\n    {\n      for(UInt i=0; i<A.rows(); i++)\n      {\n        for(UInt k=0; k<=i; k++)\n          saveDouble(A(i,k));\n        stream<<std::endl;\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveAscii::load(Matrix &A)\n{\n  try\n  {\n    stripComments();\n\n    char c;\n    stream>>c;\n    stream.putback(c);\n    if(!isalpha(c) || (c == 'n') || (c == 'N')) // check for Nan\n    {\n      std::vector< std::vector<Double> > values;\n      for(UInt i=0; ; i++)\n      {\n        std::string line;\n        try\n        {\n          stripComments();\n          std::getline(stream, line);\n        }\n        catch(std::exception &e)\n        {\n          if(stream.eof())\n            break;\n          GROOPS_RETHROW(e)\n        }\n        if(line.empty())\n          break;\n        values.resize(i+1);\n        std::stringstream ss(line);\n        for(;;)\n        {\n          std::string dummy;\n          ss>>dummy;\n          if(ss.fail() || ss.bad() || (dummy.at(0) == '#'))\n            break;\n          values.at(i).push_back(std::stod(dummy));\n        }\n      }\n      A = Matrix(values.size(), values.at(0).size(), Matrix::NOFILL);\n      for(UInt i=0; i<A.rows(); i++)\n        for(UInt k=0; k<A.columns(); k++)\n          A(i,k) = values.at(i).at(k);\n      return;\n    }\n\n    std::string type;\n    UInt rows, columns;\n    stream>>type>>rows>>c>>columns>>c;\n    if(type==\"Matrix(\")\n    {\n      A = Matrix(rows, columns, Matrix::NOFILL);\n      for(UInt i=0; i<A.rows(); i++)\n        for(UInt k=0; k<A.columns(); k++)\n          A(i,k) = readDouble(stream);\n      return;\n    }\n\n    if(type==\"UpperTriangularMatrix(\")\n      A = Matrix(rows, Matrix::TRIANGULAR, Matrix::UPPER);\n    else if(type==\"LowerTriangularMatrix(\")\n      A = Matrix(rows, Matrix::TRIANGULAR, Matrix::LOWER);\n    else if(type==\"UpperSymmetricMatrix(\")\n      A = Matrix(rows, Matrix::SYMMETRIC, Matrix::UPPER);\n    else if(type==\"LowerSymmetricMatrix(\")\n      A = Matrix(rows, Matrix::SYMMETRIC, Matrix::LOWER);\n    else\n      throw(Exception(\"unknown matrix type: \"+type));\n\n    if(A.isUpper())\n      for(UInt i=0; i<A.rows(); i++)\n        for(UInt k=i; k<A.columns(); k++)\n          A(i,k) = readDouble(stream);\n    else\n      for(UInt i=0; i<A.rows(); i++)\n        for(UInt k=0; k<=i; k++)\n          A(i,k) = readDouble(stream);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveAscii::save(const SphericalHarmonics &harm)\n{\n  try\n  {\n    endLine();\n\n    const Bool hasErrors = harm.sigma2cnm().size();\n\n    stream<<\"modelname              GROOPS\"<<std::endl;\n    stream<<\"product_type           gravity_field\"<<std::endl;\n    stream<<\"earth_gravity_constant \"; saveDouble(harm.GM(),16,10,TRUE); stream<<std::endl;\n    stream<<\"radius                 \"; saveDouble(harm.R(), 16,10,TRUE); stream<<std::endl;\n    stream<<\"max_degree             \"<<std::setw(0)<<harm.maxDegree()<<std::endl;\n    stream<<\"norm                   fully_normalized\"<<std::endl;\n    //stream<<\"tide_system            zero_tide\"<<std::endl;\n    stream<<\"errors                 \"<<(hasErrors ? \"formal\" : \"no\")<<std::endl;\n    stream<<std::endl;\n    if(harm.sigma2cnm().size())\n    {\n      stream<<\"key   L   M       C                   S                   sigma C             sigma S\"<<std::endl;\n      stream<<\"end_of_head ================================================================================\"<<std::endl;\n    }\n    else\n    {\n      stream<<\"key   L   M       C                   S\"<<std::endl;\n      stream<<\"end_of_head ==========================================\"<<std::endl;\n    }\n    for(UInt n=0; n<=harm.maxDegree(); n++)\n      for(UInt m=0; m<=n; m++)\n      {\n        // RR: changed setw(4) to setw(5)\n        stream<<\"gfc \"<<std::setw(5)<<n<<std::setw(5)<<m;\n        saveDouble(harm.cnm()(n,m),20,12,TRUE);\n        saveDouble(harm.snm()(n,m),20,12,TRUE);\n        if(hasErrors) saveDouble(sqrt(harm.sigma2cnm()(n,m)),20,12,TRUE);\n        if(hasErrors) saveDouble(sqrt(harm.sigma2snm()(n,m)),20,12,TRUE);\n        stream<<std::endl;\n      }\n    stream<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveAscii::load(SphericalHarmonics &harm)\n{\n  try\n  {\n    stripComments();\n\n    Double GM=0, R=0;\n    UInt   maxDegree=0;\n    Bool   hasErrors = FALSE;\n\n    // Header einlesen\n    std::string line;\n    for(;;)\n    {\n      std::getline(stream, line);\n      std::stringstream ss(line);\n      std::string tag;\n      ss>>tag;\n\n      if(tag == \"earth_gravity_constant\")\n        GM = readDouble(ss);\n      if(tag == \"radius\")\n        R = readDouble(ss);\n      if(tag == \"max_degree\")\n        ss>>maxDegree;\n      if(tag == \"errors\")\n      {\n        std::string no;\n        ss>>no;\n        if(no.rfind(\"no\", 0) != 0)\n          hasErrors = TRUE;\n      }\n      // Header fertig ?\n      if(tag == \"end_of_head\")\n        break;\n    }\n\n    Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(;;)\n    {\n      try\n      {\n        std::getline(stream, line);\n      }\n      catch(std::exception &e)\n      {\n        if(stream.eof())\n          break;\n        GROOPS_RETHROW(e)\n      }\n      if(line.empty())\n        break;\n      std::stringstream ss(line);\n      ss.exceptions(std::ios::badbit|std::ios::failbit);\n      std::string tag;\n      ss>>tag;\n      if((tag != \"gfc\")&&(tag != \"gfct\"))\n        continue;\n      UInt n,m;\n      ss>>n>>m;\n      cnm(n,m) = readDouble(ss);\n      snm(n,m) = readDouble(ss);\n      if(hasErrors)\n      {\n        sigma2cnm(n,m) = std::pow(readDouble(ss), 2);\n        sigma2snm(n,m) = std::pow(readDouble(ss), 2);\n      }\n    }\n\n    if(hasErrors)\n      harm = SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm);\n    else\n      harm = SphericalHarmonics(GM, R, cnm, snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/archiveAscii.h",
    "content": "/***********************************************/\n/**\n* @file archiveAscii.h\n*\n* @brief Write/read archives in ASCII format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-11-12\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ARCHIVEASCII__\n#define __GROOPS_ARCHIVEASCII__\n\n#include \"archive.h\"\n\n/** @addtogroup archiveGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Write archive files in ASCII format. */\nclass OutArchiveAscii : public OutArchive\n{\npublic:\n  OutArchiveAscii(std::ostream &_stream, const std::string &type, UInt version);\n ~OutArchiveAscii(){}\n\n  OutArchiveAscii() = delete;\n  OutArchiveAscii(const OutArchiveAscii &) = delete;\n  OutArchiveAscii &operator=(const OutArchiveAscii &) = delete;\n\n  ArchiveType archiveType() const override {return ASCII;}\n\nprotected:\n  void endLine() override;\n  void comment(const std::string &text) override;\n\n  void save(const std::string &x) override;\n  void save(const Int         &x) override;\n  void save(const UInt        &x) override;\n  void save(const Double      &x) override;\n  void save(const Bool        &x) override;\n  void save(const Time        &x) override;\n  void save(const Angle       &x) override;\n  void save(const Vector      &x) override;\n  void save(const const_MatrixSlice  &x) override;\n  void save(const SphericalHarmonics &x) override;\n  void save(const Doodson     &x) override;\n  void save(const GnssType    &x) override;\n\nprivate:\n  void saveDouble(Double x, Int width=26, Int precision=18, Bool science=TRUE);\n\n  std::ostream &stream;\n  Int  i_width; // Fuer die formatierte Int Ausgabe\n  Bool isNewLine;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Read archive files in ASCII format. */\nclass InArchiveAscii : public InArchive\n{\n  std::istream &stream;\n  std::string  typeStr;\n  UInt        _version;\n\n  void stripComments();\n  Double readDouble(std::istream &stream);\n\npublic:\n  InArchiveAscii(std::istream &_stream);\n ~InArchiveAscii() {}\n\n  ArchiveType archiveType() const override {return ASCII;}\n  std::string type()        const override {return typeStr;}\n  UInt        version()     const override {return _version;}\n\nprotected:\n  void load(std::string &x) override;\n  void load(Int      &x) override;\n  void load(UInt     &x) override;\n  void load(Double   &x) override;\n  void load(Bool     &x) override;\n  void load(Time     &x) override;\n  void load(Angle    &x) override;\n  void load(Vector   &x) override;\n  void load(Matrix   &x) override;\n  void load(SphericalHarmonics &x) override;\n  void load(Doodson  &x) override;\n  void load(GnssType &x) override;\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/inputOutput/archiveBinary.cpp",
    "content": "/***********************************************/\n/**\n* @file archiveBinary.cpp\n*\n* @brief Read/write archive files in binary format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-11\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/doodson.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/gnssType.h\"\n#include \"archive.h\"\n#include \"archiveBinary.h\"\n\n/***********************************************/\n\nOutArchiveBinary::OutArchiveBinary(std::ostream &_stream, const std::string &type, UInt version) : stream(_stream)\n{\n  stream<<\"B\";\n  save(type);\n\n  std::stringstream ss;\n  ss<<version;\n  save(ss.str());\n\n  // padding to 64 bit\n  // size computation is probably wrong, but we keep it for compatibility reasons.\n  std::string empty((1+type.size()+ss.str().size())%8, ' ');\n  if(empty.size())\n    stream.write(&empty.at(0), empty.size()*sizeof(char));\n}\n\n/***********************************************/\n\nInArchiveBinary::InArchiveBinary(std::istream &_stream) : stream(_stream), _version(0)\n{\n  char c;\n  stream>>c;\n  if(c=='b')\n  {\n    oldVersion = TRUE;\n    return; // old version\n  }\n  if(c!='B')\n    throw(Exception(\"in InArchiveBinary: magic byte expected\"));\n  oldVersion = FALSE;\n\n  std::string _versionStr;\n  load(typeStr);\n  load(_versionStr);\n  _version = versionStr2version(_versionStr);\n\n  // padding to 64 bit\n  // size computation is probably wrong, but we keep it for compatibility reasons.\n  std::string empty((1+typeStr.size()+_versionStr.size())%8, ' ');\n  if(empty.size())\n    stream.read(&empty.at(0), empty.size()*sizeof(char));\n}\n\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Double &x){stream.write(reinterpret_cast<const char*>(&x), sizeof(Double));}\nvoid InArchiveBinary::load(Double &x)       {stream.read(reinterpret_cast<char*>(&x), sizeof(Double));}\n\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Angle &x) {save(static_cast<Double>(x));}\nvoid InArchiveBinary::load(Angle &x)        {Double w; load(w); x=Angle(w);}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Int &x)\n{\n  Int64 y = static_cast<Int64>(x);\n  stream.write(reinterpret_cast<const char*>(&y), sizeof(Int64));\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(Int &x)\n{\n  if(oldVersion)\n  {\n    Int32 y;\n    stream.read(reinterpret_cast<char*>(&y), sizeof(Int32));\n    x = static_cast<Int>(y);\n  }\n  else\n  {\n    Int64 y;\n    stream.read(reinterpret_cast<char*>(&y), sizeof(Int64));\n    x = static_cast<Int>(y);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const UInt &x)\n{\n  UInt64 y = static_cast<UInt64>(x);\n  stream.write(reinterpret_cast<const char*>(&y), sizeof(UInt64));\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(UInt &x)\n{\n  if(oldVersion)\n  {\n    UInt32 y;\n    stream.read(reinterpret_cast<char*>(&y), sizeof(UInt32));\n    x = static_cast<UInt>(y);\n  }\n  else\n  {\n    UInt64 y;\n    stream.read(reinterpret_cast<char*>(&y), sizeof(UInt64));\n    x = static_cast<UInt>(y);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Bool &x)\n{\n  UInt64 y = static_cast<UInt64>(x);\n  stream.write(reinterpret_cast<const char*>(&y), sizeof(UInt64));\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(Bool &x)\n{\n  if(oldVersion)\n    stream.read(reinterpret_cast<char*>(&x), sizeof(Bool));\n  else\n  {\n    UInt64 y;\n    stream.read(reinterpret_cast<char*>(&y), sizeof(UInt64));\n    x = static_cast<Bool>(y);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const std::string &x)\n{\n  save(static_cast<UInt>(x.size()));\n  if(x.size())\n    stream.write(&x.at(0), x.size()*sizeof(char));\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(std::string &x)\n{\n  UInt size;\n  load(size);\n  x.resize(size);\n  if(x.size())\n    stream.read(&x.at(0), size*sizeof(char));\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Time &x)\n{\n  save(x.mjdInt());\n  save(x.mjdMod());\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(Time &x)\n{\n  if(oldVersion)\n  {\n    Int mjd, milli;\n    load(mjd);\n    load(milli);\n    x = Time(mjd,milli/(1000.*60*60*24));\n  }\n  else\n  {\n    Int    mjdInt;\n    Double mjdMod;\n    load(mjdInt);\n    load(mjdMod);\n    x = Time(mjdInt, mjdMod);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Doodson &x)\n{\n  for(UInt i=0; i<6; i++)\n    save(x.d[i]);\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(Doodson &x)\n{\n  if(oldVersion)\n  {\n    throw(Exception(\"Old GROOPS binary file is not supported anymore.\"));\n  }\n  else\n  {\n    for(UInt i=0; i<6; i++)\n      load(x.d[i]);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const GnssType &x)\n{\n  UInt64 y = static_cast<UInt64>(x.type);\n  stream.write(reinterpret_cast<const char*>(&y), sizeof(UInt64));\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(GnssType &x)\n{\n  UInt64 y;\n  stream.read(reinterpret_cast<char*>(&y), sizeof(UInt64));\n  x.type = y;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const Vector &x)\n{\n  Matrix A = x;\n  save(A);\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(Vector &x)\n{\n  if(oldVersion)\n  {\n    UInt rows;\n    load(rows);\n    x = Vector(rows);\n    if(x.rows()!=0)\n      stream.read(reinterpret_cast<char*>(x.field()), x.size()*sizeof(Double));\n  }\n  else\n  {\n    Matrix A;\n    load(A);\n    x = A;\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const const_MatrixSlice &x)\n{\n  save(static_cast<UInt>(x.getType()));\n  if(x.getType()==Matrix::GENERAL)\n  {\n    save(x.rows()); save(x.columns());\n    if(x.size()==0)\n      return;\n    if((!x.isRowMajorOrder()) && (x.rows()==x.ld()))\n      stream.write(reinterpret_cast<const char*>(x.const_field()), x.size()*sizeof(Double));\n    else if(!x.isRowMajorOrder())\n      for(UInt s=0; s<x.columns(); s++)\n        stream.write(reinterpret_cast<const char*>(x.const_field()+s*x.ld()), x.rows()*sizeof(Double));\n    else\n      for(UInt s=0; s<x.columns(); s++)\n        for(UInt z=0; z<x.rows(); z++)\n          save(x(z,s));\n  }\n  else\n  {\n    UInt uplo = (x.isUpper()) ? 0 : 1; // compability to old version\n    save(uplo); save(x.rows());\n    if(x.size()==0)\n      return;\n    if(!x.isRowMajorOrder())\n    {\n      if(x.isUpper())\n        for(UInt s=0; s<x.columns(); s++)\n          stream.write(reinterpret_cast<const char*>(x.const_field()+s*x.ld()), (s+1)*sizeof(Double));\n      else\n        for(UInt s=0; s<x.columns(); s++)\n          stream.write(reinterpret_cast<const char*>(x.const_field()+(s*x.ld()+s)), (x.rows()-s)*sizeof(Double));\n    }\n    else\n    {\n      if(x.isUpper())\n        for(UInt s=0; s<x.columns(); s++)\n          for(UInt z=0; z<=s; z++)\n            save(x(z,s));\n      else\n        for(UInt s=0; s<x.columns(); s++)\n          for(UInt z=s; z<x.rows(); z++)\n            save(x(z,s));\n    }\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(Matrix &x)\n{\n  UInt type;\n  load(type);\n  if(static_cast<Matrix::Type>(type)==Matrix::GENERAL)\n  {\n    UInt rows, columns;\n    load(rows); load(columns);\n    x = Matrix(rows, columns, Matrix::NOFILL);\n    if(x.size()==0)\n      return;\n    stream.read(reinterpret_cast<char*>(x.field()), x.size()*sizeof(Double));\n  }\n  else\n  {\n    UInt dim, uplo;\n    load(uplo); load(dim);\n    x = Matrix(dim, static_cast<Matrix::Type>(type), ((uplo==1) ? Matrix::LOWER : Matrix::UPPER));\n    if(x.size()==0)\n      return;\n\n    if(uplo==0)\n    {\n      for(UInt s=0; s<x.columns(); s++)\n        stream.read(reinterpret_cast<char*>(&x(0,s)), (s+1)*sizeof(Double));\n    }\n    else\n    {\n      for(UInt s=0; s<x.columns(); s++)\n        stream.read(reinterpret_cast<char*>(&x(s,s)), (x.rows()-s)*sizeof(Double));\n    }\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveBinary::save(const SphericalHarmonics &harm)\n{\n  save(harm.GM());\n  save(harm.R());\n  save(harm.cnm());\n  save(harm.snm());\n  save(harm.sigma2cnm());\n  save(harm.sigma2snm());\n}\n\n/***********************************************/\n\nvoid InArchiveBinary::load(SphericalHarmonics &harm)\n{\n  Double GM, R;\n  Matrix cnm, snm, sigma2cnm, sigma2snm;\n\n  load(GM);\n  load(R);\n  load(cnm);\n  load(snm);\n  load(sigma2cnm);\n  load(sigma2snm);\n\n  harm = SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/archiveBinary.h",
    "content": "/***********************************************/\n/**\n* @file archiveBinary.h\n*\n* @brief Read/write archive files in binary format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-11\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ARCHIVEBINARY__\n#define __GROOPS_ARCHIVEBINARY__\n\n#include \"archive.h\"\n\n/** @addtogroup archiveGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Write archive files in binary format. */\nclass OutArchiveBinary : public OutArchive\n{\npublic:\n  OutArchiveBinary(std::ostream &_stream, const std::string &type, UInt version);\n ~OutArchiveBinary() {}\n\n  OutArchiveBinary() = delete;\n  OutArchiveBinary(const OutArchiveBinary &) = delete;\n  OutArchiveBinary &operator=(const OutArchiveBinary &) = delete;\n\n  ArchiveType archiveType() const override {return BINARY;}\n\nprotected:\n  void save(const std::string &x) override;\n  void save(const Int         &x) override;\n  void save(const UInt        &x) override;\n  void save(const Double      &x) override;\n  void save(const Bool        &x) override;\n  void save(const Time        &x) override;\n  void save(const Angle       &x) override;\n  void save(const Vector      &x) override;\n  void save(const const_MatrixSlice  &x) override;\n  void save(const SphericalHarmonics &x) override;\n  void save(const Doodson     &x) override;\n  void save(const GnssType    &x) override;\n\nprivate:\n  std::ostream &stream;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Read archive files in binary format. */\nclass InArchiveBinary : public InArchive\n{\n  std::istream &stream;\n  std::string  typeStr;\n  UInt         _version;\n  Bool         oldVersion;\n\npublic:\n  InArchiveBinary(std::istream &_stream);\n ~InArchiveBinary() {}\n\n  ArchiveType archiveType() const override {return BINARY;}\n  std::string type()        const override {return typeStr;}\n  UInt        version()     const override {return _version;}\n\nprotected:\n  void load(std::string &x) override;\n  void load(Int      &x) override;\n  void load(UInt     &x) override;\n  void load(Double   &x) override;\n  void load(Bool     &x) override;\n  void load(Time     &x) override;\n  void load(Angle    &x) override;\n  void load(Vector   &x) override;\n  void load(Matrix   &x) override;\n  void load(SphericalHarmonics &x) override;\n  void load(Doodson  &x) override;\n  void load(GnssType &x) override;\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS_ARCHIVEBINARY__ */\n"
  },
  {
    "path": "source/inputOutput/archiveJson.cpp",
    "content": "/***********************************************/\n/**\n* @file archiveJson.cpp\n*\n* @brief Read/write archive files in JSON format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2025-01-22\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/string.h\"\n#include \"base/doodson.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/gnssType.h\"\n#include \"parser/xml.h\"\n#include \"archive.h\"\n#include \"archiveJson.h\"\n\n/***********************************************/\n\nstatic std::string quoted(const std::string &str)\n{\n  if(str.empty())\n    return str;\n  std::stringstream ss;\n  ss<<std::quoted(str);\n  return ss.str();\n}\n\n/***********************************************/\n\nstatic void writeJsonData(std::ostream &stream, XmlNodePtr xmlNode, UInt depth)\n{\n  // has children -> struct\n  if(xmlNode->hasChildren())\n  {\n    stream<<\"{\"<<std::endl;\n    while(xmlNode->hasChildren())\n    {\n      XmlNodePtr child = xmlNode->getNextChild();\n      stream<<std::string(depth, '\\t')<<std::quoted(child->getName())<<\": \";\n      // is array?\n      if(xmlNode->findChild(child->getName()))\n      {\n        stream<<\"[\";\n        while(child)\n        {\n          writeJsonData(stream, child, depth+1);\n          child = xmlNode->getChild(child->getName());\n          if(child)\n            stream<<\", \";\n        }\n        stream<<\"]\";\n      }\n      else\n        writeJsonData(stream, child, depth+1);\n      if(xmlNode->hasChildren())\n        stream<<\",\"<<std::endl;\n    }\n    stream<<std::endl<<std::string(depth-1, '\\t')<<\"}\";\n  }\n  else if(!xmlNode->getText().empty()) // value\n  {\n    stream<<xmlNode->getText();\n  }\n  else // empty\n    stream<<\"null\";\n}\n\n/***********************************************/\n\nOutArchiveJson::OutArchiveJson(std::ostream &_stream, const std::string &type, UInt version) : stream(_stream)\n{\n  XmlNodePtr xmlNode = XmlNode::create(\"groops\");\n  writeXml(xmlNode, \"fileType\",    quoted(type));\n  writeXml(xmlNode, \"fileVersion\", version);\n  stack.push(xmlNode);\n}\n\n/***********************************************/\n\nOutArchiveJson::~OutArchiveJson()\n{\n  XmlNodePtr xmlNode = stack.top();\n  writeJsonData(stream, xmlNode, 1);\n}\n\n/***********************************************/\n\nvoid OutArchiveJson::startTag(const std::string &name)\n{\n  stack.push(createXmlNode(stack.top(), name));\n}\n\n/***********************************************/\n\nvoid OutArchiveJson::endTag(const std::string &/*name*/)\n{\n  stack.top() = XmlNodePtr();\n  stack.pop();\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic void readObject(std::istream &stream, XmlNodePtr parent);\n\nstatic void readData(std::istream &stream, XmlNodePtr xmlNode)\n{\n  char c;\n  stream>>c;\n  if(c == '{')\n  {\n    do\n    {\n      readObject(stream, xmlNode);\n      stream>>c;\n    }\n    while(c == ',');\n    if(c != '}')\n      throw(Exception(\"json parser error in '\"+xmlNode->getName()+\"': '}' expected\"));\n    return;\n  }\n\n  stream.putback(c);\n  std::string value;\n  if(c == '\"')\n  {\n    stream>>std::quoted(value);\n    xmlNode->setValue(value);\n  }\n  else\n  {\n    // read until delimiter (,]} or white space)\n    while(std::string(\",]} \\n\\t\").find_first_of((c = stream.get())) == std::string::npos)\n      value.push_back(c);\n    stream.putback(c);\n    if(value == \"true\")\n      xmlNode->setValue(1);\n    else if(value == \"false\")\n      xmlNode->setValue(0);\n    else if(value != \"null\")\n      xmlNode->setValue(value);\n  }\n}\n\n/***********************************************/\n\nstatic void readObject(std::istream &stream, XmlNodePtr parent)\n{\n  std::string name;\n  stream>>std::quoted(name);\n  XmlNodePtr xmlNode = createXmlNode(parent, name);\n\n  char c;\n  stream>>c; // \":\"\n  if(c != ':')\n    throw(Exception(\"json parser error in '\"+name+\"': ':' expected\"));\n\n  // content\n  stream>>c;\n  if(c == '[') // array\n  {\n    for(;;)\n    {\n      readData(stream, xmlNode);\n      stream>>c;\n      if(c != ',')\n        break;\n      xmlNode = createXmlNode(parent, name);\n    }\n    if(c != ']')\n      throw(Exception(\"json parser error in '\"+name+\"': ']' expected\"));\n    return;\n  }\n\n  stream.putback(c);\n  readData(stream, xmlNode);\n}\n\n/***********************************************/\n\nInArchiveJson::InArchiveJson(std::istream &stream) : _version(0)\n{\n  XmlNodePtr xmlNode = XmlNode::create(\"groops\");\n  stack.push(xmlNode);\n  readData(stream, xmlNode);\n  readXml(xmlNode, \"fileType\",    typeStr);\n  readXml(xmlNode, \"fileVersion\", _version);\n}\n\n/***********************************************/\n\nInArchiveJson::~InArchiveJson()\n{\n  while(!stack.empty())\n    stack.pop();\n}\n\n/***********************************************/\n\nvoid InArchiveJson::startTag(const std::string &name)\n{\n  stack.push(getChild(stack.top(), name, TRUE));\n}\n\n/***********************************************/\n\nvoid InArchiveJson::endTag(const std::string &/*name*/)\n{\n  stack.pop();\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveJson::save(const Int         &x) {stack.top()->setValue(x);}\nvoid OutArchiveJson::save(const UInt        &x) {stack.top()->setValue(x);}\nvoid OutArchiveJson::save(const Double      &x) {stack.top()->setValue(x);}\nvoid OutArchiveJson::save(const Bool        &x) {stack.top()->setValue(x ? \"true\" : \"false\");}\nvoid OutArchiveJson::save(const std::string &x) {stack.top()->setValue(quoted(x));}\nvoid OutArchiveJson::save(const Angle       &x) {stack.top()->setValue(x);}\nvoid OutArchiveJson::save(const Doodson     &x) {stack.top()->setValue(quoted(x.code()));}\nvoid OutArchiveJson::save(const GnssType    &x) {stack.top()->setValue(quoted(x.str()));}\n\n/***********************************************/\n\nvoid InArchiveJson::load(Int         &x) {stack.top()->getValue(x);}\nvoid InArchiveJson::load(UInt        &x) {stack.top()->getValue(x);}\nvoid InArchiveJson::load(Double      &x) {stack.top()->getValue(x);}\nvoid InArchiveJson::load(Bool        &x) {stack.top()->getValue(x);}\nvoid InArchiveJson::load(std::string &x) {stack.top()->getValue(x);}\nvoid InArchiveJson::load(Angle       &x) {stack.top()->getValue(x);}\nvoid InArchiveJson::load(Doodson     &x) {std::string str; stack.top()->getValue(str); x = Doodson(str);}\nvoid InArchiveJson::load(GnssType    &x) {std::string str; stack.top()->getValue(str); x = GnssType(str);}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveJson::save(const Time &x)\n{\n  try\n  {\n    LongDouble mjd = x.mjdMod();\n    mjd += x.mjdInt();\n\n    std::stringstream stream_;\n    stream_.setf(std::ios::fixed,std::ios::floatfield);\n    stream_.precision(16);\n    stream_<<mjd;\n\n    stack.top()->setValue(stream_.str());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveJson::load(Time &x)\n{\n  LongDouble mjd;\n  stack.top()->getValue(mjd);\n  Int mjdInt = static_cast<Int>(std::floor(mjd));\n  x = Time(mjdInt, static_cast<Double>(mjd-mjdInt));\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveJson::save(const Vector &x)\n{\n  Matrix A = x;\n  save(A);\n}\n\n/***********************************************/\n\nvoid InArchiveJson::load(Vector &x)\n{\n  Matrix A;\n  load(A);\n  x = A;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveJson::save(const const_MatrixSlice &A)\n{\n  XmlNodePtr xmlNode = stack.top();\n\n  std::string type;\n  if(A.getType()==Matrix::GENERAL)\n    type = \"general\";\n  else\n  {\n    type = (A.isUpper() ? \"upper\" : \"lower\");\n    if(A.getType()==Matrix::TRIANGULAR)\n      type += \"TriangularMatrix\";\n    else if(A.getType()==Matrix::SYMMETRIC)\n      type += \"SymmetricMatrix\";\n  }\n\n  std::stringstream ss;\n  ss.setf(std::ios::scientific,std::ios::floatfield);\n  ss.precision(18);\n  UInt minCol = 0, maxCol = A.columns();\n  ss<<std::endl<<\"[\";\n  for(UInt i=0; i<A.rows(); i++)\n  {\n    if((A.getType() != Matrix::GENERAL) &&  A.isUpper()) minCol = i;\n    if((A.getType() != Matrix::GENERAL) && !A.isUpper()) maxCol = i+1;\n    ss<<\"[\";\n    for(UInt k=minCol; k<maxCol; k++)\n      ss<<A(i,k)<<((k<maxCol-1) ? \", \" : \"]\");\n    ss<<((i < A.rows()-1) ? \",\\n \" : \"]\");\n  }\n\n  writeXml(xmlNode, \"type\",    quoted(type));\n  writeXml(xmlNode, \"rows\",    A.rows());\n  writeXml(xmlNode, \"columns\", A.columns());\n  if(A.size())\n    writeXml(xmlNode, \"data\",  ss.str());\n  else\n    writeXml(xmlNode, \"data\",  \"[]\");\n}\n\n/***********************************************/\n\nvoid InArchiveJson::load(Matrix &A)\n{\n  XmlNodePtr xmlNode = stack.top();\n\n  std::string type;\n  UInt rows, columns = 1;\n  readXml(xmlNode, \"type\",    type, TRUE);\n  readXml(xmlNode, \"rows\",    rows, TRUE);\n  readXml(xmlNode, \"columns\", columns);\n\n  if(type == \"general\")\n    A = Matrix(rows, columns, Matrix::NOFILL);\n  else if(type == \"upperTriangularMatrix\")\n    A = Matrix(rows, Matrix::TRIANGULAR, Matrix::UPPER);\n  else if(type == \"lowerTriangularMatrix\")\n    A = Matrix(rows, Matrix::TRIANGULAR, Matrix::LOWER);\n  else if(type == \"upperSymmetricMatrix\")\n    A = Matrix(rows, Matrix::SYMMETRIC, Matrix::UPPER);\n  else if(type == \"lowerSymmetricMatrix\")\n    A = Matrix(rows, Matrix::SYMMETRIC, Matrix::LOWER);\n  else\n    throw(Exception(\"unknown matrix type: \"+type));\n\n  UInt minCol = 0, maxCol = A.columns();\n  for(UInt i=0; i<A.rows(); i++)\n  {\n    if((A.getType() != Matrix::GENERAL) &&  A.isUpper()) minCol = i;\n    if((A.getType() != Matrix::GENERAL) && !A.isUpper()) maxCol = i+1;\n    for(UInt k=minCol; k<maxCol; k++)\n      readXml(xmlNode, \"data\", A(i,k), TRUE);\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveJson::save(const SphericalHarmonics &harm)\n{\n  XmlNodePtr xmlNode = stack.top();\n  writeXml(xmlNode, \"GM\",        harm.GM());\n  writeXml(xmlNode, \"R\",         harm.R());\n  writeXml(xmlNode, \"maxDegree\", harm.maxDegree());\n  for(UInt n=0; n<=harm.maxDegree(); n++)\n    for(UInt m=0; m<=n; m++)\n    {\n      writeXml(xmlNode, \"cnm\", harm.cnm()(n,m));\n      writeXml(xmlNode, \"snm\", harm.snm()(n,m));\n      if(harm.sigma2cnm().size())\n      {\n        writeXml(xmlNode, \"sigmacnm\", std::sqrt(harm.sigma2cnm()(n,m)));\n        writeXml(xmlNode, \"sigmasnm\", std::sqrt(harm.sigma2snm()(n,m)));\n      }\n    }\n}\n\n/***********************************************/\n\nvoid InArchiveJson::load(SphericalHarmonics &harm)\n{\n  XmlNodePtr xmlNode = stack.top();\n  UInt   maxDegree;\n  Double GM = DEFAULT_GM;\n  Double R  = DEFAULT_R;\n\n  readXml(xmlNode, \"GM\", GM);\n  readXml(xmlNode, \"R\",  R);\n  readXml(xmlNode, \"maxDegree\", maxDegree, TRUE);\n\n  Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n  for(UInt n=0; n<=maxDegree; n++)\n    for(UInt m=0; m<=n; m++)\n    {\n      readXml(xmlNode, \"cnm\", cnm(n,m), TRUE);\n      readXml(xmlNode, \"snm\", snm(n,m), TRUE);\n      readXml(xmlNode, \"sigmacnm\", sigma2cnm(n,m));\n      readXml(xmlNode, \"sigmasnm\", sigma2snm(n,m));\n      sigma2cnm(n,m) *= sigma2cnm(n,m);\n      sigma2snm(n,m) *= sigma2snm(n,m);\n    }\n\n  if(isStrictlyZero(sigma2cnm))\n    harm = SphericalHarmonics(GM, R, cnm, snm);\n  else\n    harm = SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/archiveJson.h",
    "content": "/***********************************************/\n/**\n* @file archiveJson.h\n*\n* @brief Read/write archive files in JSON format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2025-01-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ARCHIVEJSON__\n#define __GROOPS_ARCHIVEJSON__\n\n#include \"archive.h\"\n#include \"parser/xml.h\"\n\n/** @addtogroup archiveGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Write archive files in JSON format. */\nclass OutArchiveJson : public OutArchive\n{\npublic:\n  OutArchiveJson(std::ostream &_stream, const std::string &type, UInt version);\n ~OutArchiveJson();\n\n  OutArchiveJson() = delete;\n  OutArchiveJson(const OutArchiveJson &) = delete;\n  OutArchiveJson &operator=(const OutArchiveJson &) = delete;\n\n  ArchiveType archiveType() const override {return JSON;}\n\nprotected:\n  void startTag(const std::string &name) override;\n  void endTag  (const std::string &name) override;\n\n  void save(const std::string &x) override;\n  void save(const Int         &x) override;\n  void save(const UInt        &x) override;\n  void save(const Double      &x) override;\n  void save(const Bool        &x) override;\n  void save(const Time        &x) override;\n  void save(const Angle       &x) override;\n  void save(const Vector      &x) override;\n  void save(const const_MatrixSlice  &x) override;\n  void save(const SphericalHarmonics &x) override;\n  void save(const Doodson     &x) override;\n  void save(const GnssType    &x) override;\n\nprivate:\n  std::ostream           &stream;\n  std::stack<XmlNodePtr> stack;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Read archive files in JSON format. */\nclass InArchiveJson : public InArchive\n{\n  std::stack<XmlNodePtr> stack;\n  std::string typeStr;\n  UInt       _version;\n\npublic:\n  InArchiveJson(std::istream &stream);\n ~InArchiveJson();\n\n  ArchiveType archiveType() const override {return JSON;}\n  std::string type()        const override {return typeStr;}\n  UInt        version()     const override {return _version;}\n\nprotected:\n  void startTag(const std::string &name) override;\n  void endTag  (const std::string &name) override;\n\n  void load(std::string &x) override;\n  void load(Int      &x) override;\n  void load(UInt     &x) override;\n  void load(Double   &x) override;\n  void load(Bool     &x) override;\n  void load(Time     &x) override;\n  void load(Angle    &x) override;\n  void load(Vector   &x) override;\n  void load(Matrix   &x) override;\n  void load(SphericalHarmonics &x) override;\n  void load(Doodson  &x) override;\n  void load(GnssType &x) override;\n};\n\n/***********************************************/\n\n/// @}\n\n#endif\n"
  },
  {
    "path": "source/inputOutput/archiveXml.cpp",
    "content": "/***********************************************/\n/**\n* @file archiveXml.cpp\n*\n* @brief Read/write archive files in XML format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-01\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/doodson.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/gnssType.h\"\n#include \"parser/xml.h\"\n#include \"archive.h\"\n#include \"archiveXml.h\"\n\n/***********************************************/\n\nOutArchiveXml::OutArchiveXml(std::ostream &_stream, const std::string &type, UInt version) : stream(_stream)\n{\n  XmlNodePtr xmlNode = XmlNode::create(\"groops\");\n  if(!type.empty())\n    writeAttribute(xmlNode, \"type\", type);\n  if(version)\n    writeAttribute(xmlNode, \"version\", version);\n  stack.push(xmlNode);\n}\n\n/***********************************************/\n\nOutArchiveXml::~OutArchiveXml()\n{\n  XmlNodePtr xmlNode = stack.top();\n  XmlNode::write(stream, xmlNode);\n}\n\n/***********************************************/\n\nvoid OutArchiveXml::startTag(const std::string &name)\n{\n  stack.push(createXmlNode(stack.top(), name));\n}\n\n/***********************************************/\n\nvoid OutArchiveXml::endTag(const std::string &/*name*/)\n{\n  stack.top() = XmlNodePtr();\n  stack.pop();\n}\n\n/***********************************************/\n/***********************************************/\n\nInArchiveXml::InArchiveXml(std::istream &stream) : _version(0)\n{\n  XmlNodePtr xmlNode = XmlNode::read(stream);\n\n  XmlAttrPtr attr = xmlNode->getAttribute(\"type\");\n  if(attr)\n    typeStr = attr->getText();\n\n  attr = xmlNode->getAttribute(\"version\");\n  if(attr)\n    _version = versionStr2version(attr->getText());\n\n  stack.push(xmlNode);\n}\n\n/***********************************************/\n\nInArchiveXml::~InArchiveXml()\n{\n  while(!stack.empty())\n    stack.pop();\n}\n\n/***********************************************/\n\nvoid InArchiveXml::startTag(const std::string &name)\n{\n  stack.push(getChild(stack.top(), name, TRUE));\n}\n\n/***********************************************/\n\nvoid InArchiveXml::endTag(const std::string &/*name*/)\n{\n  stack.pop();\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveXml::save(const Int         &x) {stack.top()->setValue(x);}\nvoid OutArchiveXml::save(const UInt        &x) {stack.top()->setValue(x);}\nvoid OutArchiveXml::save(const Double      &x) {stack.top()->setValue(x);}\nvoid OutArchiveXml::save(const Bool        &x) {stack.top()->setValue(x);}\nvoid OutArchiveXml::save(const std::string &x) {stack.top()->setValue(x);}\nvoid OutArchiveXml::save(const Angle       &x) {stack.top()->setValue(x);}\nvoid OutArchiveXml::save(const Doodson     &x) {stack.top()->setValue(x.code());}\nvoid OutArchiveXml::save(const GnssType    &x) {stack.top()->setValue(x.str());}\n\n/***********************************************/\n\nvoid InArchiveXml::load(Int         &x) {stack.top()->getValue(x);}\nvoid InArchiveXml::load(UInt        &x) {stack.top()->getValue(x);}\nvoid InArchiveXml::load(Double      &x) {stack.top()->getValue(x);}\nvoid InArchiveXml::load(Bool        &x) {stack.top()->getValue(x);}\nvoid InArchiveXml::load(std::string &x) {stack.top()->getValue(x);}\nvoid InArchiveXml::load(Angle       &x) {stack.top()->getValue(x);}\nvoid InArchiveXml::load(Doodson     &x) {std::string str; stack.top()->getValue(str); x = Doodson(str);}\nvoid InArchiveXml::load(GnssType    &x) {std::string str; stack.top()->getValue(str); x = GnssType(str);}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveXml::save(const Time &x)\n{\n  try\n  {\n    LongDouble mjd = x.mjdMod();\n    mjd += x.mjdInt();\n\n    std::stringstream stream_;\n    stream_.setf(std::ios::fixed,std::ios::floatfield);\n    stream_.precision(18);\n    stream_<<mjd;\n\n    stack.top()->setValue(stream_.str());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveXml::load(Time &x)\n{\n  LongDouble mjd;\n  stack.top()->getValue(mjd);\n  Int mjdInt = static_cast<Int>(std::floor(mjd));\n  x = Time(mjdInt, static_cast<Double>(mjd-mjdInt));\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveXml::save(const Vector &x)\n{\n  Matrix A = x;\n  save(A);\n}\n\n/***********************************************/\n\nvoid InArchiveXml::load(Vector &x)\n{\n  Matrix A;\n  load(A);\n  x = A;\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveXml::save(const const_MatrixSlice &x)\n{\n  XmlNodePtr xmlNode = stack.top();\n  writeXml(xmlNode, \"type\", x.getType());\n\n  if(x.getType()==Matrix::GENERAL)\n  {\n    writeXml(xmlNode, \"rows\",    x.rows());\n    writeXml(xmlNode, \"columns\", x.columns());\n    for(UInt s=0; s<x.columns(); s++)\n      for(UInt z=0; z<x.rows(); z++)\n      {\n        if(x(z,s)==0.0) continue;\n        XmlNodePtr xmlNode2 = writeXml(xmlNode, \"cell\", x(z,s));\n        writeAttribute(xmlNode2, \"row\", z);\n        writeAttribute(xmlNode2, \"col\", s);\n      }\n  }\n  else\n  {\n    writeXml(xmlNode, \"upper\", x.isUpper());\n    writeXml(xmlNode, \"dimension\", x.rows());\n    if(x.isUpper())\n    {\n      for(UInt s=0; s<x.columns(); s++)\n        for(UInt z=0; z<=s; z++)\n        {\n          if(x(z,s)==0.0) continue;\n          XmlNodePtr xmlNode2 = writeXml(xmlNode, \"cell\",x(z,s));\n          writeAttribute(xmlNode2, \"row\", z);\n          writeAttribute(xmlNode2, \"col\", s);\n        }\n    }\n    else\n    {\n      for(UInt s=0; s<x.columns(); s++)\n        for(UInt z=s; z<x.rows(); z++)\n        {\n          if(x(z,s)==0.0) continue;\n          XmlNodePtr xmlNode2 = writeXml(xmlNode, \"cell\", x(z,s));\n          writeAttribute(xmlNode2, \"row\", z);\n          writeAttribute(xmlNode2, \"col\", s);\n        }\n    }\n  }\n}\n\n/***********************************************/\n\nvoid InArchiveXml::load(Matrix &x)\n{\n  XmlNodePtr xmlNode = stack.top();\n\n  Int  type = Matrix::GENERAL;\n  readXml(xmlNode, \"type\", type);\n\n  if(type==Matrix::GENERAL)\n  {\n    UInt rows, columns = 1;\n    readXml(xmlNode, \"rows\",    rows, TRUE);\n    readXml(xmlNode, \"columns\", columns);\n    x = Matrix(rows, columns);\n  }\n  else\n  {\n    UInt dimension;\n    Bool upper;\n    readXml(xmlNode, \"upper\", upper);\n    readXml(xmlNode, \"dimension\", dimension);\n    x = Matrix(dimension, static_cast<Matrix::Type>(type), ((upper) ? Matrix::UPPER : Matrix::LOWER));\n  }\n\n  UInt  count = childCount(xmlNode, \"cell\");\n  for(UInt i=0; i<count; i++)\n  {\n    Double a = 0;\n    UInt n = 0, m = 0;\n    XmlNodePtr xmlNode2 = readXml(xmlNode, \"cell\", a, TRUE);\n    readAttribute(xmlNode2, \"row\", n, TRUE);\n    readAttribute(xmlNode2, \"col\", m, FALSE);\n    x(n,m) = a;\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid OutArchiveXml::save(const SphericalHarmonics &harm)\n{\n  XmlNodePtr xmlNode = stack.top();\n  writeXml(xmlNode, \"GM\", harm.GM());\n  writeXml(xmlNode, \"R\", harm.R());\n  writeXml(xmlNode, \"maxDegree\", harm.maxDegree());\n\n  for(UInt n=0; n<=harm.maxDegree(); n++)\n    for(UInt m=0; m<=n; m++)\n    {\n      if(harm.cnm()(n,m)!=0.0)\n      {\n        XmlNodePtr xmlNode2 = writeXml(xmlNode, \"cnm\", harm.cnm()(n,m));\n        writeAttribute(xmlNode2, \"degree\", n);\n        writeAttribute(xmlNode2, \"order\",  m);\n      }\n      if(harm.snm()(n,m)!=0.0)\n      {\n        XmlNodePtr xmlNode2 = writeXml(xmlNode, \"snm\", harm.snm()(n,m));\n        writeAttribute(xmlNode2, \"degree\", n);\n        writeAttribute(xmlNode2, \"order\",  m);\n      }\n      if(harm.sigma2cnm().size() && harm.sigma2cnm()(n,m)!=0.0)\n      {\n        XmlNodePtr xmlNode2 = writeXml(xmlNode, \"sigmacnm\", sqrt(harm.sigma2cnm()(n,m)));\n        writeAttribute(xmlNode2, \"degree\", n);\n        writeAttribute(xmlNode2, \"order\",  m);\n      }\n      if(harm.sigma2snm().size() && harm.sigma2snm()(n,m)!=0.0)\n      {\n        XmlNodePtr xmlNode2 = writeXml(xmlNode, \"sigmasnm\", sqrt(harm.sigma2snm()(n,m)));\n        writeAttribute(xmlNode2, \"degree\", n);\n        writeAttribute(xmlNode2, \"order\",  m);\n      }\n    }\n}\n\n/***********************************************/\n\nvoid InArchiveXml::load(SphericalHarmonics &harm)\n{\n  XmlNodePtr xmlNode = stack.top();\n  UInt   n,m;\n  UInt   maxDegree;\n  Double GM = DEFAULT_GM;\n  Double R  = DEFAULT_R;\n\n  readXml(xmlNode, \"GM\", GM);\n  readXml(xmlNode, \"R\",  R);\n  readXml(xmlNode, \"maxDegree\", maxDegree, TRUE);\n\n  Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n  Bool hasSigma = FALSE;\n\n  std::string name;\n  while(xmlNode->hasChildren())\n  {\n    XmlNodePtr xmlNode2 = getNextChild(xmlNode, name);\n    if(name==\"cnm\")\n    {\n      readAttribute(xmlNode2, \"degree\", n, TRUE);\n      readAttribute(xmlNode2, \"order\",  m, TRUE);\n      xmlNode2->getValue(cnm(n,m));\n    }\n    else if(name==\"snm\")\n    {\n      readAttribute(xmlNode2, \"degree\", n, TRUE);\n      readAttribute(xmlNode2, \"order\",  m, TRUE);\n      xmlNode2->getValue(snm(n,m));\n    }\n    else if(name==\"sigmacnm\")\n    {\n      readAttribute(xmlNode2, \"degree\", n, TRUE);\n      readAttribute(xmlNode2, \"order\",  m, TRUE);\n      xmlNode2->getValue(sigma2cnm(n,m));\n      sigma2cnm(n,m) *= sigma2cnm(n,m);\n      hasSigma = TRUE;\n    }\n    else if(name==\"sigmasnm\")\n    {\n      readAttribute(xmlNode2, \"degree\", n, TRUE);\n      readAttribute(xmlNode2, \"order\",  m, TRUE);\n      xmlNode2->getValue(sigma2snm(n,m));\n      sigma2snm(n,m) *= sigma2snm(n,m);\n      hasSigma = TRUE;\n    }\n  }\n\n  if(hasSigma)\n    harm = SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm);\n  else\n    harm = SphericalHarmonics(GM, R, cnm, snm);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/archiveXml.h",
    "content": "/***********************************************/\n/**\n* @file archiveXml.h\n*\n* @brief Read/write archive files in XML format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_ARCHIVEXML__\n#define __GROOPS_ARCHIVEXML__\n\n#include \"archive.h\"\n#include \"parser/xml.h\"\n\n/** @addtogroup archiveGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Write archive files in XML format. */\nclass OutArchiveXml : public OutArchive\n{\npublic:\n  OutArchiveXml(std::ostream &_stream, const std::string &type, UInt version);\n ~OutArchiveXml();\n\n  OutArchiveXml() = delete;\n  OutArchiveXml(const OutArchiveXml &) = delete;\n  OutArchiveXml &operator=(const OutArchiveXml &) = delete;\n\n  ArchiveType archiveType() const override {return XML;}\n\nprotected:\n  void startTag(const std::string &name) override;\n  void endTag  (const std::string &name) override;\n\n  void save(const std::string &x) override;\n  void save(const Int         &x) override;\n  void save(const UInt        &x) override;\n  void save(const Double      &x) override;\n  void save(const Bool        &x) override;\n  void save(const Time        &x) override;\n  void save(const Angle       &x) override;\n  void save(const Vector      &x) override;\n  void save(const const_MatrixSlice  &x) override;\n  void save(const SphericalHarmonics &x) override;\n  void save(const Doodson     &x) override;\n  void save(const GnssType    &x) override;\n\nprivate:\n  std::ostream           &stream;\n  std::stack<XmlNodePtr> stack;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Read archive files in XML format. */\nclass InArchiveXml : public InArchive\n{\n  std::stack<XmlNodePtr> stack;\n  std::string typeStr;\n  UInt       _version;\n\npublic:\n  InArchiveXml(std::istream &stream);\n ~InArchiveXml();\n\n  ArchiveType archiveType() const override {return XML;}\n  std::string type()        const override {return typeStr;}\n  UInt        version()     const override {return _version;}\n\nprotected:\n  void startTag(const std::string &name) override;\n  void endTag  (const std::string &name) override;\n\n  void load(std::string &x) override;\n  void load(Int      &x) override;\n  void load(UInt     &x) override;\n  void load(Double   &x) override;\n  void load(Bool     &x) override;\n  void load(Time     &x) override;\n  void load(Angle    &x) override;\n  void load(Vector   &x) override;\n  void load(Matrix   &x) override;\n  void load(SphericalHarmonics &x) override;\n  void load(Doodson  &x) override;\n  void load(GnssType &x) override;\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS_ARCHIVEXML__ */\n"
  },
  {
    "path": "source/inputOutput/file.cpp",
    "content": "/***********************************************/\n/**\n* @file file.cpp\n*\n* read and write files.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-06\n*\n*/\n/***********************************************/\n\n#include <cstring>\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/string.h\"\n#include \"external/compress.h\"\n#include \"file.h\"\n\n/***** CLASS ***********************************/\n\n#ifdef GROOPS_DISABLE_Z\n#else\n\nnamespace zlib\n{\n#include <zlib.h>\n}\n\n// This is a reimplementation of gzstream (Deepak Bandyopadhyay, Lutz Kettner)\nclass StreambufGZ : public std::streambuf\n{\nprivate:\n  static constexpr int bufferSize = 47+256;    // size of data buff\n  // totals 512 bytes under g++ for igzstream at the end.\n\n  zlib::gzFile       file;               // file handle for compressed file\n  char               buffer[bufferSize]; // data buffer\n  Bool               opened;             // open/close state of stream\n  std::ios::openmode mode;               // I/O mode\n\n  StreambufGZ::int_type flush_buffer();\n\npublic:\n  StreambufGZ();\n ~StreambufGZ() {close();}\n\n  bool is_open() const {return opened;}\n\n  StreambufGZ *open(const FileName &fileName, std::ios::openmode openMode);\n  StreambufGZ *close();\n\n  virtual StreambufGZ::int_type underflow() override;\n  virtual StreambufGZ::int_type overflow(StreambufGZ::int_type c) override;\n  virtual StreambufGZ::int_type sync() override;\n};\n\n/***********************************************/\n\n// Separate the writing of the buffer from overflow() and sync() operation.\nStreambufGZ::int_type StreambufGZ::flush_buffer()\n{\n  auto w = pptr() - pbase();\n  if(zlib::gzwrite(file, pbase(), w) != w)\n    return traits_type::eof();\n  pbump(-w);\n  return w;\n}\n\n/***********************************************/\n\nStreambufGZ::StreambufGZ() : opened(FALSE)\n{\n  setp(buffer, buffer+(bufferSize-1));\n  setg(buffer+4, buffer+4, buffer+4); // beginning of putback area, read position, end position\n  // ASSERT: both input & output capabilities will not be used together\n}\n\n/***********************************************/\n\nStreambufGZ *StreambufGZ::open(const FileName &fileName, std::ios::openmode openMode)\n{\n  if(is_open())\n    return nullptr;\n  mode = openMode;\n  // no append nor read/write mode\n  if((mode & std::ios::ate) || (mode & std::ios::app) || ((mode & std::ios::in) && (mode & std::ios::out)))\n    throw(Exception(\"openMode combination not allowed for .gz files\"));\n  file = zlib::gzopen(fileName.c_str(), (mode & std::ios::out) ? \"wb\" : \"rb\");\n  if(!file)\n    return nullptr;\n  opened = TRUE;\n  return this;\n}\n\n/***********************************************/\n\nStreambufGZ *StreambufGZ::close()\n{\n  if(is_open())\n  {\n    sync();\n    opened = FALSE;\n    if(zlib::gzclose(file) == Z_OK)\n      return this;\n  }\n  return nullptr;\n}\n\n/***********************************************/\n\n// used for input buffer only\nStreambufGZ::int_type StreambufGZ::underflow()\n{\n  if(gptr() && (gptr() < egptr()))\n    return traits_type::to_int_type(*gptr());\n\n  if(!(mode & std::ios::in) || !opened)\n    return traits_type::eof();\n\n  // Josuttis' implementation of inbuf\n  auto n_putback = gptr() - eback();\n  if(n_putback > 4)\n    n_putback = 4;\n  memcpy(buffer+(4-n_putback), gptr()-n_putback, n_putback);\n\n  auto num = zlib::gzread(file, buffer+4, bufferSize-4);\n  if(num <= 0) // ERROR or EOF\n    return traits_type::eof();\n\n  // reset buffer pointers\n  setg(buffer+(4-n_putback), buffer+4, buffer+4+num); // beginning of putback area, read position, end of buffer\n\n  return traits_type::to_int_type(*gptr()); // return next character\n}\n\n/***********************************************/\n\n// used for output buffer only\nStreambufGZ::int_type StreambufGZ::overflow(StreambufGZ::int_type c)\n{\n  if(!(mode & std::ios::out) || !opened)\n    return traits_type::eof();\n  if(c != traits_type::eof())\n  {\n    *pptr() = c;\n    pbump(1);\n  }\n  if(flush_buffer() == traits_type::eof())\n    return traits_type::eof();\n  return c;\n}\n\n/***********************************************/\n\nStreambufGZ::int_type StreambufGZ::sync()\n{\n  if(pptr() && (pptr() > pbase()) && (flush_buffer() == traits_type::eof()))\n    return -1;\n  return 0;\n}\n\n#endif // LIB_Z\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\nStreamBase::StreamBase() : buffer(nullptr), canSeek_(FALSE) {}\nStreamBase::~StreamBase() {close();}\n\n/***********************************************/\n\nvoid StreamBase::open(const FileName &fileName, std::ios::openmode openMode)\n{\n  try\n  {\n    close();\n    if(fileName.empty())\n      return;\n    this->fileName_ = fileName;\n    this->canSeek_  = TRUE;\n\n    // determine format from extension\n    std::string fileFormat = String::upperCase(fileName.packExtension());\n\n    // determine format from magic bytes if possible\n    if(openMode == std::ios::in)\n    {\n      std::ifstream file(fileName.c_str(), std::ios::binary);\n      unsigned char magic[2] = {0};\n      file.read(reinterpret_cast<char*>(magic), sizeof(magic));\n      const unsigned char magicCompress[2] = {0x1f, 0x9d};\n      const unsigned char magicZlib[2]     = {0x1f, 0x8b};\n      if(std::memcmp(magic, magicZlib, sizeof(magic)) == 0)\n        fileFormat = \"GZ\";\n      else if(std::memcmp(magic, magicCompress, sizeof(magic)) == 0)\n        fileFormat = \"Z\";\n    }\n\n    if(fileFormat == \"GZ\")\n    {\n#ifdef GROOPS_DISABLE_Z\n      throw(Exception(\"compiled without Z library\"));\n#else\n      buffer = new StreambufGZ();\n      std::ios::init(buffer);\n      if(!static_cast<StreambufGZ*>(buffer)->open(fileName, openMode))\n        clear(rdstate() | std::ios::badbit);\n      canSeek_ = FALSE;\n#endif\n    }\n    else if(fileFormat == \"Z\")\n    {\n      if(openMode != std::ios::in)\n        throw(Exception(\"old .Z compress implemented for input only\"));\n\n      buffer = new std::stringbuf(decompress_file(fileName.c_str()));\n      std::ios::init(buffer);\n    }\n    else\n    {\n      buffer = new std::filebuf();\n      std::ios::init(buffer);\n      if(!static_cast<std::filebuf*>(buffer)->open(fileName.str(), openMode))\n        clear(rdstate() | std::ios::badbit);\n    }\n\n    if(!good())\n      throw(Exception(\"error by opening file\"));\n    exceptions(std::ios::badbit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid StreamBase::close()\n{\n  try\n  {\n    if(buffer)\n    {\n      delete buffer;\n      buffer = nullptr;\n      std::ios::init(nullptr);\n    }\n    fileName_ = FileName();\n    canSeek_  = FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName_.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/file.h",
    "content": "/***********************************************/\n/**\n* @file file.h\n*\n* read and write files.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILE__\n#define __GROOPS_FILE__\n\n#include \"base/exception.h\"\n#include \"inputOutput/fileName.h\"\n\n/** @addtogroup inputOutputGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass StreamBase : virtual public std::ios\n{\nprotected:\n  std::streambuf *buffer;\n  FileName        fileName_;\n  Bool            canSeek_;\n\npublic:\n  StreamBase();\n ~StreamBase();\n\n  StreamBase(const StreamBase &) = delete;\n  StreamBase &operator=(const StreamBase &) = delete;\n\n  void open(const FileName &fileName, std::ios::openmode openMode);\n  void close();\n\n  FileName fileName() const {return fileName_;}\n  Bool     canSeek()  const {return canSeek_;}\n};\n\n/***** CLASS ***********************************/\n\nclass OutFile : public StreamBase, public std::ostream\n{\npublic:\n  OutFile() : std::ostream(nullptr) {}\n  OutFile(const FileName &fileName, std::ios::openmode openMode=std::ios::out) : std::ostream(nullptr) {open(fileName, openMode);}\n ~OutFile() {}\n\n  OutFile(const OutFile &) = delete;\n  OutFile &operator=(const OutFile &) = delete;\n\n  void open(const FileName &fileName, std::ios::openmode openMode=std::ios::out) {StreamBase::open(fileName, openMode);}\n  void close() {StreamBase::close();}\n\n  OutFile &operator<<(std::ostream  &(*pf)(std::ostream  &)) {pf(*this); return *this;}\n  OutFile &operator<<(std::ios      &(*pf)(std::ios      &)) {pf(*this); return *this;}\n  OutFile &operator<<(std::ios_base &(*pf)(std::ios_base &)) {pf(*this); return *this;}\n  template<typename T> inline OutFile &operator<<(const T &x);\n};\n\n/***** CLASS ***********************************/\n\nclass InFile : public StreamBase, public std::istream\n{\npublic:\n  InFile() : std::istream(nullptr) {}\n  InFile(const FileName &fileName, std::ios::openmode openMode=std::ios::in) : std::istream(nullptr) {open(fileName, openMode);}\n ~InFile() {}\n\n  InFile(const InFile &) = delete;\n  InFile &operator=(const InFile &) = delete;\n\n  void open(const FileName &fileName, std::ios::openmode openMode=std::ios::in) {StreamBase::open(fileName, openMode);}\n  void close() {StreamBase::close();}\n\n  InFile &operator>>(std::istream  &(*pf)(std::istream  &)) {pf(*this); return *this;}\n  InFile &operator>>(std::ios      &(*pf)(std::ios      &)) {pf(*this); return *this;}\n  InFile &operator>>(std::ios_base &(*pf)(std::ios_base &)) {pf(*this); return *this;}\n  template<typename T> inline InFile &operator>>(T &x);\n};\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ntemplate<typename T> inline OutFile &OutFile::operator<<(const T &x)\n{\n  try\n  {\n    if(fileName_.empty())\n      throw(Exception(\"no file open\"));\n    static_cast<std::ostream&>(*this)<<x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName_.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline InFile &InFile::operator>>(T &x)\n{\n  try\n  {\n    if(fileName_.empty())\n      throw(Exception(\"no file open\"));\n    static_cast<std::istream&>(*this)>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName_.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/inputOutput/fileArchive.cpp",
    "content": "/***********************************************/\n/**\n* @file fileArchive.cpp\n*\n* @brief Read and write archives files.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-01\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/archive.h\"\n#include \"inputOutput/archiveXml.h\"\n#include \"inputOutput/archiveJson.h\"\n#include \"inputOutput/archiveBinary.h\"\n#include \"inputOutput/archiveAscii.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/fileArchive.h\"\n\n/***** FUNCTIONS *******************************/\n\nOutFileArchive::OutFileArchive(const FileName &fileName, const std::string &type, UInt version) : archive(nullptr)\n{\n  open(fileName, type, version);\n}\n\n/***********************************************/\n\nOutFileArchive::~OutFileArchive()\n{\n  close();\n}\n\n/***********************************************/\n\nvoid OutFileArchive::open(const FileName &fileName, const std::string &type, UInt version)\n{\n  try\n  {\n    close();\n    if(fileName.empty())\n      return;\n\n    // determine format from extension\n    const std::string extension = String::upperCase(fileName.typeExtension());\n    if(extension == \"XML\")\n    {\n      file.open(fileName);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      archive = new OutArchiveXml(file, type, version);\n    }\n    else if(extension == \"JSON\")\n    {\n      file.open(fileName);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      archive = new OutArchiveJson(file, type, version);\n    }\n    else if(extension == \"DAT\")\n    {\n      file.open(fileName, std::ios::binary | std::ios::out);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      archive = new OutArchiveBinary(file, type, version);\n    }\n    else\n    {\n      file.open(fileName);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      archive = new OutArchiveAscii(file, type, version);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid OutFileArchive::close()\n{\n  if(archive)\n  {\n    delete archive;\n    archive = nullptr;\n  }\n  file.close();\n}\n\n/***********************************************/\n\nvoid OutFileArchive::comment(const std::string &text)\n{\n  if(archive)\n    archive->comment(text);\n}\n\n/***********************************************/\n/***********************************************/\n\nInFileArchive::InFileArchive(const FileName &fileName, const std::string &type, UInt version) : archive(nullptr)\n{\n  open(fileName, type, version);\n}\n\n/***********************************************/\n\nInFileArchive::~InFileArchive()\n{\n  close();\n}\n\n/***********************************************/\n\nvoid InFileArchive::open(const FileName &fileName, const std::string &typeStr, UInt version)\n{\n  try\n  {\n    close();\n    if(fileName.empty())\n      return;\n\n    // determine format from extension\n    const std::string extension = String::upperCase(fileName.typeExtension());\n    if(extension==\"XML\")\n    {\n      file.open(fileName);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      char c;\n      file>>c;\n      file.putback(c);\n      if(c!='<')\n        throw(Exception(\"Seems not to be a valid XML file.\"));\n      archive = new InArchiveXml(file);\n    }\n    else if(extension==\"JSON\")\n    {\n      file.open(fileName);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      char c;\n      file>>c;\n      file.putback(c);\n      if(c!='{')\n        throw(Exception(\"Seems not to be a valid JSON file.\"));\n      archive = new InArchiveJson(file);\n    }\n    else if(extension==\"DAT\")\n    {\n      file.open(fileName, std::ios::binary | std::ios::in);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      char c;\n      file>>c;\n      file.putback(c);\n      if((c!='b') && (c!='B'))\n        throw(Exception(\"Seems not to be a groops binary file.\"));\n      if(c=='b')\n        logWarning<<\"File <\"<<fileName<<\"> is a rather old GROOPS binary file: will not be supported in future\"<<Log::endl;\n      archive = new InArchiveBinary(file);\n    }\n    else\n    {\n      file.open(fileName);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n      archive = new InArchiveAscii(file);\n    }\n\n    // check type\n    if((!typeStr.empty()) && (!type().empty()) && (type()!=typeStr))\n      throw(Exception(\"file type is '\"+type()+\"' but must be '\"+typeStr+\"'\"));\n\n    // check version\n    if(this->version() > version)\n      logWarning<<\"File <\"<<fileName<<\"> is created with a newer version (\"<<this->version()<<\") of GROOPS (\"<<version<<\"). \"\n                <<\"This may causes problems. You should update your GROOPS software.\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+fileName.str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\nvoid InFileArchive::close()\n{\n  if(archive)\n  {\n    delete archive;\n    archive = nullptr;\n  }\n  file.close();\n}\n\n/***********************************************/\n\nstd::string InFileArchive::type() const\n{\n  if(!archive)\n    throw(Exception(\"In InFileArchive::type: no file open\"));\n  return archive->type();\n}\n\n/***********************************************/\n\nUInt InFileArchive::version() const\n{\n  if(!archive)\n    throw(Exception(\"InFileArchive::version: no file open\"));\n  return archive->version();\n}\n\n/***********************************************/\n\nBool InFileArchive::canSeek() const\n{\n  if(!archive || (archive->archiveType() != InArchive::BINARY))\n    return FALSE;\n  return file.canSeek();\n}\n\n/***********************************************/\n\nstd::streampos InFileArchive::position()\n{\n  if(!archive)\n    throw(Exception(\"InFileArchive::position: no file open\"));\n  return file.tellg();\n}\n\n/***********************************************/\n\nvoid InFileArchive::seek(std::streampos pos)\n{\n  if(!archive)\n    throw(Exception(\"InFileArchive::seek: no file open\"));\n  file.seekg(pos);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/fileArchive.h",
    "content": "/***********************************************/\n/**\n* @file fileArchive.h\n*\n* read and write archives files.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEARCHIVE__\n#define __GROOPS_FILEARCHIVE__\n\n#include \"base/exception.h\"\n#include \"inputOutput/archive.h\"\n#include \"inputOutput/file.h\"\n\n/** @addtogroup archiveGroup */\n/// @{\n\n/***** CONSTANTS ********************************/\n\nconstexpr UInt FILE_BASE_VERSION = 20200123;    // date of last change (ArcList, InstrumentFile restructured)\n// constexpr UInt FILE_BASE_VERSION = 20190429; // date of last change (SatelliteModel Surface hasThermalReemission)\n// constexpr UInt FILE_BASE_VERSION = 20190304; // date of last change (GnssStationInfo)\n// constexpr UInt FILE_BASE_VERSION = 20170920; // date of last change\n// constexpr UInt FILE_BASE_VERSION = 20150524; // date of last change\n\n/***** CLASS ***********************************/\n\nclass OutFileArchive\n{\n  OutFile     file;\n  OutArchive *archive;\n\npublic:\n  OutFileArchive() : archive(nullptr)  {}\n  OutFileArchive(const FileName &fileName, const std::string &type, UInt version);\n ~OutFileArchive();\n\n  OutFileArchive(const InFile &) = delete;\n  OutFileArchive &operator=(const InFile &) = delete;\n\n  void open(const FileName &fileName, const std::string &type, UInt version);\n  void close();\n\n  FileName fileName() const {return file.fileName();}\n\n  OutArchive &outArchive() {return *archive;}\n  void comment(const std::string &text);\n\n  template<typename T> inline OutFileArchive &operator<<(const T &x);\n};\n\n/***** CLASS ***********************************/\n\nclass InFileArchive\n{\n  InFile     file;\n  InArchive *archive;\n\npublic:\n  InFileArchive() : archive(nullptr) {}\n  InFileArchive(const FileName &fileName, const std::string &type, UInt version);\n ~InFileArchive();\n\n  InFileArchive(const InFile &) = delete;\n  InFileArchive &operator=(const InFile &) = delete;\n\n  void open(const FileName &fileName, const std::string &type, UInt version);\n  void close();\n\n  FileName    fileName() const {return file.fileName();}\n  std::string type()     const;\n  UInt        version()  const;\n\n  Bool           canSeek() const;\n  std::streampos position();\n  void           seek(std::streampos pos);\n\n  template<typename T> inline InFileArchive &operator>>(T &x);\n  template<typename T> inline InFileArchive &operator>>(const T &x);\n};\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ntemplate<typename T>\ninline OutFileArchive &OutFileArchive::operator<<(const T &x)\n{\n  try\n  {\n    if(!archive)\n      throw(Exception(\"no file open\"));\n    (*archive)<<x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+file.fileName().str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline InFileArchive &InFileArchive::operator>>(T &x)\n{\n  try\n  {\n    if(!archive)\n      throw(Exception(\"no file open\"));\n    (*archive)>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+file.fileName().str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline InFileArchive &InFileArchive::operator>>(const T &x)\n{\n  try\n  {\n    if(!archive)\n      throw(Exception(\"no file open\"));\n    (*archive)>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"filename=<\"+file.fileName().str()+\">\", e)\n  }\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/inputOutput/fileName.cpp",
    "content": "/***********************************************/\n/**\n* @file fileName.cpp\n*\n* @brief File names\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-07-28\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/string.h\"\n#include \"parser/stringParser.h\"\n#include \"fileName.h\"\n\n/*************************************************/\n\nFileName::FileName() : resolved(TRUE) {}\n\n/*************************************************/\n\nFileName::FileName(const std::string &name)\n  : nameUnparsed(name), nameParsed(name), resolved(TRUE) {}\n\n/*************************************************/\n\nFileName::FileName(const std::string &name, const VariableList &varList)\n  : nameUnparsed(name), resolved(FALSE), varList(varList) {}\n\n/*************************************************/\n\nvoid FileName::resolve() const\n{\n  try\n  {\n    if(resolved)\n      return;\n    nameParsed = StringParser::parse(nameUnparsed, varList);\n    resolved = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/*************************************************/\n\nFileName FileName::append(const FileName &fileName) const\n{\n  resolve();\n  if(empty())\n    return fileName;\n  std::string separator;\n  if((nameParsed.back() != '/') && (nameParsed.back() != '\\\\'))\n#ifdef _WIN32\n    separator = '\\\\'; // = std::filesystem::path::preferred_separator;\n#else\n    separator = '/';\n#endif\n  return FileName(nameParsed+separator+fileName.str());\n}\n\n/*************************************************/\n\nFileName FileName::fullExtension() const\n{\n  resolve();\n  auto pos = nameParsed.rfind('.');\n  if((pos == std::string::npos) || (pos+1 == nameParsed.size()))\n    return FileName();\n  std::string ext = String::upperCase(nameParsed.substr(pos+1));\n  if((pos > 0) && (ext == \"GZ\" || ext == \"Z\"))\n  {\n    auto posNew = nameParsed.rfind('.', pos-1);\n    if(posNew != std::string::npos)\n      pos = posNew;\n  }\n  return FileName(nameParsed.substr(pos+1));\n}\n\n/*************************************************/\n\nFileName FileName::typeExtension() const\n{\n  resolve();\n  std::string ext = fullExtension();\n  return FileName(ext.substr(0, ext.find('.')));\n}\n\n/*************************************************/\n\nFileName FileName::packExtension() const\n{\n  resolve();\n  std::string ext = fullExtension();\n  auto pos = ext.find('.');\n  if(pos == std::string::npos)\n    return FileName();\n  return FileName(ext.substr(pos+1));\n}\n\n/*************************************************/\n\nFileName FileName::stripFullExtension() const\n{\n  resolve();\n  auto pos = nameParsed.rfind(\".\"+fullExtension().str());\n  if(pos == std::string::npos)\n    return *this;\n  return FileName(nameParsed.substr(0, pos));\n}\n\n/*************************************************/\n\nFileName FileName::replaceFullExtension(const std::string &text) const\n{\n  resolve();\n  return FileName(stripFullExtension().str() + ((text.empty() || String::startsWith(text, \".\")) ? \"\" : \".\") + text);\n}\n\n/*************************************************/\n\nFileName FileName::directory() const\n{\n  resolve();\n  auto pos = nameParsed.find_last_of(\"/\\\\\");\n  if(pos == std::string::npos)\n    return FileName();\n  return FileName(nameParsed.substr(0, pos+1));\n}\n\n/*************************************************/\n\nFileName FileName::stripDirectory() const\n{\n  resolve();\n  std::string::size_type pos = nameParsed.find_last_of(\"/\\\\\");\n  if(pos == std::string::npos)\n    return *this;\n  return FileName(nameParsed.substr(pos+1));\n}\n\n/*************************************************/\n\nFileName FileName::appendBaseName(const std::string &text) const\n{\n  resolve();\n  auto pos = nameParsed.rfind(\".\"+fullExtension().str());\n  if(pos == std::string::npos)\n    return FileName(nameParsed+text);\n  std::string tmp = nameParsed;\n  return FileName(tmp.insert(pos, text));\n}\n\n/*************************************************/\n\nFileName FileName::operator()(const VariableList &varList) const\n{\n  try\n  {\n    if(resolved)\n      return FileName(nameParsed);\n    VariableList varList2 = this->varList;\n    varList2 += varList;\n    return FileName(StringParser::parse(nameUnparsed, varList2));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/*************************************************/\n"
  },
  {
    "path": "source/inputOutput/fileName.h",
    "content": "/***********************************************/\n/**\n* @file fileName.h\n*\n* @brief File names\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-07-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILENAME__\n#define __GROOPS_FILENAME__\n\n#include \"base/importStd.h\"\n#include \"parser/expressionParser.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief File names.\n* @ingroup inputOutputGroup */\nclass FileName\n{\n  std::string         nameUnparsed;\n  mutable std::string nameParsed;\n  mutable Bool        resolved;\n  VariableList        varList;\n\n  void resolve() const;\n\npublic:\n  FileName();                                                     //!< Constructor.\n  FileName(const FileName &) = default;                           //!< Copy constructor.\n  FileName(const std::string &name);                              //!< Constructor.\n  FileName(const char *name) : FileName(std::string(name)) {}     //!< Constructor.\n  FileName(const std::string &name, const VariableList &varList); //!< Constructor with parsing.\n  FileName &operator=(const FileName &) = default;                //!< Assignment.\n\n  operator const std::string&() const {resolve(); return nameParsed;}         //!< Cast to  string.\n  operator const char *()       const {resolve(); return nameParsed.c_str();} //!< Cast to old C type string.\n  const char *c_str()           const {resolve(); return nameParsed.c_str();} //!< Old C type string.\n  const std::string &str()      const {resolve(); return nameParsed;}         //!< String.\n\n  /** @brief Is FileName empty? */\n  Bool empty() const {return nameUnparsed.empty();}\n\n  /** @brief Append a fileName to a directory.\n  * Directory and file will be separated by the directory separator (e.g. '/') if needed. */\n  FileName append(const FileName& fileName) const;\n\n  /** @brief Extension.\n  * Returns the string of all characters in the FileName\n  * after (but not including) the last '.' character plus an additional \".gz\" or \".z\".\n  * Example: FileName(\"name.txt.gz\").typeExtension() returns \"txt.gz\". */\n  FileName fullExtension() const;\n\n  /** @brief Extension.\n  * Returns the string of all characters in the FileName\n  * after (but not including) the last '.' character without an additional \".gz\" or \".z\".\n  * Example: FileName(\"name.txt.gz\").typeExtension() returns \"txt\". */\n  FileName typeExtension() const;\n\n  /** @brief Extension.\n  * Example: FileName(\"name.txt.gz\").typeExtension() returns \"gz\". */\n  FileName packExtension() const;\n\n  /** @brief File name without extension.\n  * Returns the string of all characters in the FileName\n  * before (but not including) the last '.' character. */\n  FileName stripFullExtension() const;\n\n  /** @brief Replaces the extension with text.\n  * Firstly, if this path has an extension(), it is removed.\n  * Then, a dot character is appended if text is not empty or does not begin with a dot character.\n  * Then text is appended to the path. */\n  FileName replaceFullExtension(const std::string &text) const;\n\n  /** @brief Directory name of file.\n  * Returns the string of all characters in the FileName\n  * name before the last '/' character. */\n  FileName directory() const;\n\n  /** @brief File name without directory.\n  * Returns the string of all characters in the FileName\n  * name after (but not including) the last '/' character. */\n  FileName stripDirectory() const;\n\n  /** @brief File name without directory and extension.\n  * Returns (*this).stripDirectory().stripFullExtension(). */\n  FileName baseName() const {return stripDirectory().stripFullExtension();}\n\n  /** @brief Extent the baseName.\n  * Returns a FileName with appending text before '.'+extension(). */\n  FileName appendBaseName(const std::string &text) const;\n\n  /** Returns a FileName with replaced variable {name} names. */\n  FileName operator()(const VariableList &varList) const;\n\n  /** @brief 'Less than' operator, required for sorting. */\n  Bool operator< (const FileName &fileName) const {resolve(); return nameParsed < fileName.nameParsed;}\n};\n\n/*************************************************/\n\n#endif /* __GROOPS__ */\n\n\n"
  },
  {
    "path": "source/inputOutput/fileNetCdf.cpp",
    "content": "/***********************************************/\n/**\n* @file fileNetCdf.cpp\n*\n* @brief Input/output of netCDF files.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2018-05-15\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"fileNetCdf.h\"\n\n#ifdef GROOPS_DISABLE_NETCDF\n#else\n#include <netcdf.h>\n\n/***********************************************/\n\ntemplate<typename T> static void convert(const Vector &values, std::vector<T> &tmp)\n{\n  tmp.resize(values.rows());\n  for(UInt i=0; i<values.rows(); i++)\n    tmp.at(i) = static_cast<T>(values(i));\n}\n\n/***********************************************/\n\ntemplate<typename T> static Vector convert(const std::vector<T> &tmp)\n{\n  Vector values(tmp.size());\n  for(UInt i=0; i<values.rows(); i++)\n    values(i) = static_cast<Double>(tmp.at(i));\n  return values;\n}\n\n/***********************************************/\n/***********************************************/\n\nNetCdf::Dimension NetCdf::Group::addDimension(const std::string &name, UInt length)\n{\n  if(length == MAX_UINT)\n    length = NC_UNLIMITED;\n\n  Int dimId = 0;\n  nc_def_dim(groupId, name.c_str(), length, &dimId);\n\n  return Dimension(groupId, dimId);\n}\n\n/***********************************************/\n\nstd::vector<NetCdf::Dimension> NetCdf::Group::dimensions() const\n{\n  Int countDimensions = 0;\n  nc_inq_ndims(groupId, &countDimensions);\n  std::vector<Dimension> dims;\n  for(Int dimId=0; dimId<countDimensions; dimId++)\n    dims.push_back(NetCdf::Dimension(groupId, dimId));\n  return dims;\n}\n\n/***********************************************/\n\nNetCdf::Variable NetCdf::Group::addVariable(const std::string &name, DataType dtype, const std::vector<NetCdf::Dimension> &dims)\n{\n  std::vector<Int> dimIds(dims.size());\n  for(UInt i=0; i<dims.size(); i++)\n    dimIds.at(i) = dims.at(i).dimId;\n\n  nc_type ncType = NC_DOUBLE;\n  switch(dtype)\n  {\n    case BYTE:   ncType = NC_BYTE;   break;\n    case CHAR:   ncType = NC_CHAR;   break;\n    case SHORT:  ncType = NC_SHORT;  break;\n    case INT:    ncType = NC_INT;    break;\n    case FLOAT:  ncType = NC_FLOAT;  break;\n    case DOUBLE: ncType = NC_DOUBLE; break;\n  }\n\n  Int varId = 0;\n  nc_def_var(groupId, name.c_str(), ncType, dimIds.size(), dimIds.data(), &varId);\n\n  return Variable(groupId, varId);\n}\n\n/***********************************************/\n\nstd::vector<NetCdf::Variable> NetCdf::Group::variables() const\n{\n  std::vector<Variable> vars;\n\n  Int countVariables = 0;\n  nc_inq_nvars(groupId, &countVariables);\n  std::vector<Int> varIds(countVariables);\n  nc_inq_varids(groupId, &countVariables, varIds.data());\n\n  for(Int varId : varIds)\n    vars.push_back(Variable(groupId, varId));\n\n  return vars;\n}\n\n/***********************************************/\n\nBool NetCdf::Group::hasVariable(const std::string &name) const\n{\n  Int varId;\n  return (nc_inq_varid(groupId, name.c_str(), &varId) == NC_NOERR);\n}\n\n/***********************************************/\n\nNetCdf::Variable NetCdf::Group::variable(const std::string &name) const\n{\n  try\n  {\n    Int varId;\n    if(nc_inq_varid(groupId, name.c_str(), &varId) != NC_NOERR)\n      throw(Exception(\"Variable <\"+name+\"> not found in group\"));\n    return Variable(groupId, varId);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nNetCdf::Attribute NetCdf::Group::addAttribute(const std::string &name, const std::string &value)\n{\n  nc_put_att_text(groupId, NC_GLOBAL, name.c_str(), value.size(), value.c_str());\n  return Attribute(groupId, NC_GLOBAL, name);\n}\n\n/***********************************************/\n\nNetCdf::Attribute NetCdf::Group::addAttribute(const std::string &name, DataType dtype, const Vector &val)\n{\n  switch(dtype)\n  {\n    case BYTE:   {std::vector<Byte>  tmp; convert(val, tmp); nc_put_att      (groupId, NC_GLOBAL, name.c_str(), NC_BYTE,  tmp.size(), reinterpret_cast<void*>(tmp.data())); break;}\n    case CHAR:   {std::vector<char>  tmp; convert(val, tmp); nc_put_att_text (groupId, NC_GLOBAL, name.c_str(), tmp.size(), tmp.data());  break;}\n    case SHORT:  {std::vector<short> tmp; convert(val, tmp); nc_put_att_short(groupId, NC_GLOBAL, name.c_str(), NC_SHORT, tmp.size(), tmp.data());  break;}\n    case INT:    {std::vector<int>   tmp; convert(val, tmp); nc_put_att_int  (groupId, NC_GLOBAL, name.c_str(), NC_INT,   tmp.size(), tmp.data());  break;}\n    case FLOAT:  {std::vector<float> tmp; convert(val, tmp); nc_put_att_float(groupId, NC_GLOBAL, name.c_str(), NC_FLOAT, tmp.size(), tmp.data());  break;}\n    case DOUBLE: {nc_put_att_double(groupId, NC_GLOBAL, name.c_str(), NC_DOUBLE, val.size(), val.field()); break;}\n  }\n  return Attribute(groupId, NC_GLOBAL, name);\n}\n\n/***********************************************/\n\nstd::vector<NetCdf::Attribute> NetCdf::Group::attributes() const\n{\n  Int countAttributes = 0;\n  nc_inq_natts(groupId, &countAttributes);\n\n  std::vector<Attribute> atts;\n  for(Int attrId=0; attrId<countAttributes; attrId++)\n  {\n    char name[NC_MAX_NAME+1];\n    nc_inq_attname(groupId, NC_GLOBAL, attrId, name);\n    atts.push_back(Attribute(groupId, NC_GLOBAL, std::string(name)));\n  }\n\n  return atts;\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::string NetCdf::Dimension::name() const\n{\n  char dimName[NC_MAX_NAME+1];\n  nc_inq_dimname(groupId, dimId, dimName);\n  return std::string(dimName);\n}\n\n/***********************************************/\n\nUInt NetCdf::Dimension::length() const\n{\n  UInt len = 0;\n  nc_inq_dimlen(groupId, dimId, &len);\n  return len;\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::string NetCdf::Variable::name() const\n{\n  char varName[NC_MAX_NAME+1];\n  nc_inq_varname(groupId, varId, varName);\n  return std::string(varName);\n}\n\n/***********************************************/\n\nstd::vector<NetCdf::Dimension> NetCdf::Variable::dimensions() const\n{\n  Int ndims = 0;\n  nc_inq_varndims(groupId, varId, &ndims);\n\n  std::vector<Int> dimIds(ndims);\n  nc_inq_vardimid(groupId, varId, dimIds.data());\n\n  std::vector<Dimension> dims;\n  for(Int dimId : dimIds)\n    dims.push_back(NetCdf::Dimension(groupId, dimId));\n  return dims;\n}\n\n/***********************************************/\n\nNetCdf::Attribute NetCdf::Variable::addAttribute(const std::string &name, const std::string &value)\n{\n  nc_put_att_text(groupId, varId, name.c_str(), value.size(), value.c_str());\n  return Attribute(groupId, varId, name);\n}\n\n/***********************************************/\n\nNetCdf::Attribute NetCdf::Variable::addAttribute(const std::string &name, DataType dtype, const Vector &val)\n{\n  switch(dtype)\n  {\n    case BYTE:   {std::vector<Byte>  tmp; convert(val, tmp); nc_put_att      (groupId, varId, name.c_str(), NC_BYTE,  tmp.size(), reinterpret_cast<void*>(tmp.data())); break;}\n    case CHAR:   {std::vector<char>  tmp; convert(val, tmp); nc_put_att_text (groupId, varId, name.c_str(),           tmp.size(), tmp.data());  break;}\n    case SHORT:  {std::vector<short> tmp; convert(val, tmp); nc_put_att_short(groupId, varId, name.c_str(), NC_SHORT, tmp.size(), tmp.data());  break;}\n    case INT:    {std::vector<int>   tmp; convert(val, tmp); nc_put_att_int  (groupId, varId, name.c_str(), NC_INT,   tmp.size(), tmp.data());  break;}\n    case FLOAT:  {std::vector<float> tmp; convert(val, tmp); nc_put_att_float(groupId, varId, name.c_str(), NC_FLOAT, tmp.size(), tmp.data());  break;}\n    case DOUBLE: {nc_put_att_double(groupId, varId, name.c_str(), NC_DOUBLE, val.size(), val.field()); break;}\n  }\n  return Attribute(groupId, varId, name);\n}\n\n/***********************************************/\n\nstd::vector<NetCdf::Attribute> NetCdf::Variable::attributes() const\n{\n  Int countAttributes = 0;\n  nc_inq_varnatts(groupId, varId, &countAttributes);\n\n  std::vector<Attribute> atts;\n  for(Int attrId=0; attrId<countAttributes; attrId++)\n  {\n    char name[NC_MAX_NAME+1];\n    nc_inq_attname(groupId, varId, attrId, name);\n    atts.push_back(Attribute(groupId, varId, std::string(name)));\n  }\n\n  return atts;\n}\n\n/***********************************************/\n\nNetCdf::Attribute NetCdf::Variable::attribute(const std::string &name) const\n{\n  try\n  {\n    std::vector<Attribute> attr = attributes();\n    auto iter = std::find_if(attr.begin(), attr.end(), [&name](const Attribute &attr) {return attr.name() == name;});\n    if(iter == attr.end())\n      throw(Exception(\"Attribute <\"+name+\"> not found in variable <\"+this->name()+\">\"));\n    return *iter;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NetCdf::Variable::setValues(const std::vector<UInt> &start, const std::vector<UInt> &count, const Vector &val) const\n{\n  nc_type ncType = 0;\n  nc_inq_vartype(groupId, varId, &ncType);\n\n  switch(ncType)\n  {\n    case NC_BYTE:   {std::vector<Byte>  tmp; convert(val, tmp); nc_put_vara      (groupId, varId, start.data(), count.data(), reinterpret_cast<void*>(tmp.data()));  break;}\n    case NC_CHAR:   {std::vector<char>  tmp; convert(val, tmp); nc_put_vara_text (groupId, varId, start.data(), count.data(), tmp.data());  break;}\n    case NC_SHORT:  {std::vector<short> tmp; convert(val, tmp); nc_put_vara_short(groupId, varId, start.data(), count.data(), tmp.data());  break;}\n    case NC_INT:    {std::vector<int>   tmp; convert(val, tmp); nc_put_vara_int  (groupId, varId, start.data(), count.data(), tmp.data());  break;}\n    case NC_FLOAT:  {std::vector<float> tmp; convert(val, tmp); nc_put_vara_float(groupId, varId, start.data(), count.data(), tmp.data());  break;}\n    case NC_DOUBLE: {nc_put_vara_double(groupId, varId, start.data(), count.data(), val.field()); break;}\n    default: throw(Exception(\"Unsupported data type.\"));\n  }\n}\n\n/***********************************************/\n\nvoid NetCdf::Variable::setValues(const Vector &val) const\n{\n  std::vector<Dimension> dims = dimensions();\n  std::vector<UInt> count;\n  for(auto &dim : dims)\n    count.push_back(dim.length());\n  setValues(std::vector<UInt>(dims.size(), 0), count, val);\n}\n\n/***********************************************/\n\nVector NetCdf::Variable::values(const std::vector<UInt> &start, const std::vector<UInt> &count) const\n{\n  try\n  {\n    UInt countElements = 1;\n    for(UInt c : count)\n      countElements *= c;\n\n    Vector values(countElements);\n    nc_get_vara_double(groupId, varId, start.data(), count.data(), values.field());\n    return values;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NetCdf::Variable::values() const\n{\n  std::vector<Dimension> dims = dimensions();\n  std::vector<UInt> count;\n  for(auto &dim : dims)\n    count.push_back(dim.length());\n  return values(std::vector<UInt>(dims.size(), 0), count);\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::string NetCdf::Attribute::value() const\n{\n  try\n  {\n    UInt len = 0;\n    nc_inq_attlen(groupId, varId, name_.c_str(), &len);\n    if(len == 0)\n      return std::string();\n\n    nc_type ncType = 0;\n    nc_inq_atttype(groupId, varId, name_.c_str(), &ncType);\n\n    Vector data;\n    switch(ncType)\n    {\n      case NC_CHAR:   {std::vector<char>   tmp(len); nc_get_att_text  (groupId, varId, name_.c_str(), tmp.data()); return std::string(tmp.begin(), tmp.end());}\n      case NC_SHORT:  {std::vector<short>  tmp(len); nc_get_att_short (groupId, varId, name_.c_str(), tmp.data()); data = convert(tmp); break;}\n      case NC_INT:    {std::vector<int>    tmp(len); nc_get_att_int   (groupId, varId, name_.c_str(), tmp.data()); data = convert(tmp); break;}\n      case NC_FLOAT:  {std::vector<float>  tmp(len); nc_get_att_float (groupId, varId, name_.c_str(), tmp.data()); data = convert(tmp); break;}\n      case NC_DOUBLE: {std::vector<double> tmp(len); nc_get_att_double(groupId, varId, name_.c_str(), tmp.data()); data = convert(tmp); break;}\n      case NC_STRING:\n      {\n        std::size_t attlen = 0;\n        nc_inq_attlen(groupId, varId, name_.c_str(), &attlen);\n        std::vector<char*> strings(attlen, nullptr);\n        nc_get_att_string(groupId, varId, name_.c_str(), strings.data());\n        std::stringstream ss;\n        ss<<strings.at(0);\n        for(UInt i=1; i<data.rows(); i++)\n          ss<<\", \"<<strings.at(i);\n        nc_free_string(attlen, strings.data());\n        return ss.str();\n      }\n      default:\n        return \"Unsupported data type.\";\n    }\n\n    std::stringstream ss;\n    ss<<data(0);\n    for(UInt i=1; i<data.rows(); i++)\n      ss<<\", \"<<data(i);\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nNetCdf::InFile::InFile(const FileName &fileName)\n{\n  if(nc_open(fileName.c_str(), NC_NOWRITE, &groupId) != NC_NOERR)\n    throw(Exception(\"Error opening NetCDF file <\"+fileName.str()+\">\"));\n}\n\n/***********************************************/\n\nNetCdf::InFile::~InFile()\n{\n  nc_close(groupId);\n}\n\n/***********************************************/\n\nNetCdf::OutFile::OutFile(const FileName &fileName)\n{\n  if(nc_create(fileName.c_str(), NC_NETCDF4 | NC_SHARE, &groupId) != NC_NOERR)\n    throw(Exception(\"Error opening NetCDF file <\"+fileName.str()+\">\"));\n}\n\n/***********************************************/\n\nNetCdf::OutFile::~OutFile()\n{\n  nc_close(groupId);\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<Time> NetCdf::convertTimes(const_MatrixSliceRef values, const std::string &unitString)\n{\n  try\n  {\n// if you want to use uduinits2 library instead:\n//   ut_set_error_message_handler(ut_ignore);\n//   ut_system    *usys       = ut_read_xml(nullptr);\n//   ut_unit      *timeUnit   = ut_parse(usys, unitString.c_str(), UT_ASCII);\n//   ut_unit      *targetUnit = ut_parse(usys, \"days since 1858-11-17 00:00:00\", UT_ASCII);\n//   cv_converter *converter  = ut_get_converter(timeUnit, targetUnit);\n//   std::vector<Time> times;\n//   times.reserve(values.size());\n//   for(UInt i=0; i<values.size(); i++)\n//     times.push_back(mjd2time(cv_convert_double(converter, values.at(i))));\n//   cv_free(converter);\n//   ut_free(targetUnit);\n//   ut_free(timeUnit);\n//   ut_free_system(usys);\n//   return times;\n\n    std::vector<std::string> parts;\n    for(const std::string &part : String::split(unitString, \" \\t\\n\"))\n      if(!part.empty())\n        parts.push_back(String::lowerCase(part));\n\n    if((parts.size() < 3) || ((parts.at(1) != \"since\") && (parts.at(1) != \"from\") && (parts.at(1) != \"ref\")))\n      throw(Exception(\"Cannot interpret time units: '\"+unitString+\"'\"));\n\n    // time unit\n    // ---------\n    Double factor = 1.;\n    if(String::startsWith(parts.at(0), \"ms\"))      factor = 1e-3/(24*60*60);          // milliseconds\n    else if(String::startsWith(parts.at(0), \"mo\")) factor = 3.15569259747e7/86400/12; // month\n    else if(String::startsWith(parts.at(0), \"y\"))  factor = 3.15569259747e7/86400;    // year\n    else if(String::startsWith(parts.at(0), \"s\"))  factor = 1./(24*60*60);            // seconds\n    else if(String::startsWith(parts.at(0), \"m\"))  factor = 1./(24*60);               // minutes\n    else if(String::startsWith(parts.at(0), \"h\"))  factor = 1./24.;                   // hours\n    else if(String::startsWith(parts.at(0), \"d\"))  factor = 1.;                       // days\n    else if(String::startsWith(parts.at(0), \"w\"))  factor = 7.;                       // weeks\n    else throw(Exception(\"Cannot interpret units: '\"+unitString+\"'\"));\n\n    // reference time\n    // --------------\n    UInt   year=0, month=1, day=1, hour=0, minute=0;\n    Double second=0;\n\n    std::vector<std::string> dateParts = String::split(parts.at(2), 't'); // format yyyy-MM-ddTHH:mm:ss.SSS\n    if(dateParts.size() > 1)\n      parts.insert(parts.begin()+3, dateParts.at(1));\n    // date\n    if(dateParts.at(0).find('-') == std::string::npos)\n    {\n      year  = static_cast<UInt>(String::toInt(dateParts.at(0).substr(0, 4)));\n      if(dateParts.at(0).size() > 4) month = static_cast<UInt>(String::toInt(dateParts.at(0).substr(4, 2)));\n      if(dateParts.at(0).size() > 6) day   = static_cast<UInt>(String::toInt(dateParts.at(0).substr(6, 2)));\n    }\n    else\n    {\n      Char c;\n      std::stringstream ss(parts.at(2));\n      ss>>year>>c>>month>>c>>day;\n    }\n    // time\n    if(parts.size() > 3)\n    {\n      if(parts.at(3).find(':') == std::string::npos)\n      {\n        hour   = static_cast<UInt>(String::toInt(parts.at(3).substr(0, 4)));\n        if(parts.at(3).size() > 4) minute = static_cast<UInt>(String::toInt(parts.at(3).substr(4, 2)));\n        if(parts.at(3).size() > 6) second = String::toDouble(parts.at(3).substr(6));\n      }\n      else\n      {\n        Char c;\n        std::stringstream ss(parts.at(3));\n        ss>>hour>>c>>minute>>c>>second;\n      }\n    }\n    Time time0 = date2time(year, month, day, hour, minute, second);\n\n    std::vector<Time> times;\n    times.reserve(values.size());\n    for(UInt i=0; i<values.size(); i++)\n      times.push_back(mjd2time(factor*values(i,0)) + time0);\n\n    return times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Angle> NetCdf::convertAngles(const_MatrixSliceRef values)\n{\n  std::vector<Angle> lonLat;\n  lonLat.reserve(values.size());\n  for(UInt i=0; i<values.size(); i++)\n    lonLat.push_back(Angle(DEG2RAD * values(i,0)));\n  return lonLat;\n}\n\n/***********************************************/\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/inputOutput/fileNetCdf.h",
    "content": "/***********************************************/\n/**\n* @file fileNetCdf.h\n*\n* @brief Input/output of netCDF files.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2018-05-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILENETCDF__\n#define __GROOPS_FILENETCDF__\n\n#include \"base/import.h\"\n#include \"inputOutput/fileName.h\"\n\n/** @brief GROOPS relevant subset of NetCDF data model */\nnamespace NetCdf\n{\n  enum DataType {BYTE, CHAR, SHORT, INT, FLOAT, DOUBLE};\n\n  class Attribute;\n  class Dimension;\n  class Variable;\n\n  /***** CLASS ***********************************/\n\n  /** @brief netCDF Group representation. */\n  class Group\n  {\n  protected:\n    Int groupId; // netCDF Group ID\n\n  public:\n    /// Constructor from netCDF group ID\n    Group(Int groupId=-1) : groupId(groupId) {}\n\n    /// Adds a new dimension\n    Dimension addDimension(const std::string &name, UInt length = MAX_UINT);\n\n    /// Return all dimensions available in this group.\n    std::vector<Dimension> dimensions() const;\n\n    // -------------------\n\n    /// Adds a new variable\n    Variable addVariable(const std::string &name, DataType dtype, const std::vector<Dimension> &dims);\n\n    /// Return all variables of this groups\n    std::vector<Variable> variables() const;\n\n    /// Exists the variable with name @a name?\n    Bool hasVariable(const std::string &name) const;\n\n    /// Returns the variable with name @a name.\n    Variable variable(const std::string &name) const;\n\n    // -------------------\n\n    /// Add string attribute @a name\n    Attribute addAttribute(const std::string &name, const std::string &val);\n\n    /// Add value attribute @a name\n    Attribute addAttribute(const std::string &name, DataType dtype, const Vector &val);\n\n    /// Return all attributes of this group.\n    std::vector<Attribute> attributes() const;\n  };\n\n  /***** CLASS ***********************************/\n\n  /** @brief netCDF Dimension representation. */\n  class Dimension\n  {\n    Int groupId; // containing group ID\n    Int dimId;   // dimension ID\n\n  public:\n    /// Constructor from dimension id and group id\n    Dimension(Int groupId=-1, Int dimId=-1) : groupId(groupId), dimId(dimId) {}\n\n    /// Return the name of the dimension\n    std::string name() const;\n\n    /// Return the current length of the dimension\n    UInt length() const;\n\n    Bool operator==(const Dimension &x) const {return (groupId == x.groupId) && (dimId == x.dimId);}\n    Bool operator!=(const Dimension &x) const {return !(*this == x);}\n\n    friend class Group;\n  };\n\n  /***** CLASS ***********************************/\n\n  /** @brief netCDF variable representation. */\n  class Variable\n  {\n    Int groupId; // ID of containing group\n    Int varId;   // variable ID\n\n  public:\n    /// Constructor from variable ID and group ID\n    Variable(Int groupId=-1, Int varId=-1) : groupId(groupId), varId(varId) {}\n\n    /// Return the name (string identifier) of the variable\n    std::string name() const;\n\n    /// Return all dimensions of the variable\n    std::vector<Dimension> dimensions() const;\n\n    // -------------------\n\n    /// Add string attribute @a name\n    Attribute addAttribute(const std::string &name, const std::string &text);\n\n    /// Add value attribute @a name\n    Attribute addAttribute(const std::string &name, DataType dtype, const Vector &val);\n\n    /// Return all attributes of the variable\n    std::vector<Attribute> attributes() const;\n\n    /// Return the attribute with string identifier name\n    Attribute attribute(const std::string &name) const;\n\n    // -------------------\n\n    /** @brief Write a slice of data values to the variable.\n    * Double values will be cast to the data type of the variable.\n    * @param start start index of the data point (must be of size @a dimensionCount)\n    * @param count number of elements to be retrieved along each dimension\n    * @param val data. */\n    void setValues(const std::vector<UInt> &start, const std::vector<UInt> &count, const Vector &val) const;\n\n    /** @brief Write a slice of data values to a 1D variable.\n    * Double values will be cast to the data type of the variable.\n    * @param val to a @a Vector which will hold the resulting data slice a contiguous chunk in memory. */\n    void setValues(const Vector &val) const;\n\n    /** @brief Retrieve a slice of data values from the variable.\n    * All numeric data types will be cast to Double.\n    * @param start start index of the data point (must be of size @a dimensionCount)\n    * @param count number of elements to be retrieved along each dimension\n    * @return Vector which will hold the resulting data slice a contiguous chunk in memory. */\n    Vector values(const std::vector<std::size_t> &start, const std::vector<std::size_t> &count) const;\n\n    /// Convenience function for 1D/2D variables which retrieves the whole data (useful for dimensions)\n    Vector values() const;\n  };\n\n  /***** CLASS ***********************************/\n\n  /** @brief netCDF Attribute representation. */\n  class Attribute\n  {\n    Int groupId;        // ID of containing group\n    Int varId;          // id of the associated variable\n    std::string name_;  // name of the attribute\n\n  public:\n    /// Constructor from attribute name, group id and variable id\n    Attribute(Int groupId, Int varId, const std::string &name) : groupId(groupId), varId(varId), name_(name) {}\n\n    /// Return a readable reference to the name of the attribute\n    const std::string &name() const {return name_;}\n\n    /// Convenience function for string attributes\n    std::string value() const;\n  };\n\n  /***** CLASS ***********************************/\n\n  /** @brief File input entry point for netCDF data model. */\n  class InFile : public Group\n  {\n  public:\n    /// Constructor from file name. The specified netCDF file is immediately opened.\n    InFile(const FileName &fileName);\n\n    /// Destructor\n   ~InFile();\n  };\n\n  /***** CLASS ***********************************/\n\n  /** @brief File output entry point for netCDF data model. */\n  class OutFile : public Group\n  {\n  public:\n    /// Constructor from file name. The specified netCDF file is immediately opened.\n    OutFile(const FileName &fileName);\n\n    /// Destructor\n   ~OutFile();\n  };\n\n\n  /***** FUNCTIONS ***********************************/\n\n  /// convert a vector of generic dates/times to Time objects\n  std::vector<Time> convertTimes(const_MatrixSliceRef values, const std::string &unitString);\n\n  /// convert a vector of angles in arbitrary units to Angle objects\n  std::vector<Angle> convertAngles(const_MatrixSliceRef values);\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/inputOutput/fileSinex.cpp",
    "content": "/***********************************************/\n/**\n* @file fileSinex.cpp\n*\n* @brief SINEX file representation.\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2017-05-15\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/system.h\"\n#include \"config/config.h\"\n#include \"fileSinex.h\"\n\n/***********************************************/\n\nSinexBlockPtr Sinex::addBlock(const std::string &label)\n{\n  try\n  {\n    SinexBlockPtr block = std::make_shared<SinexBlock>();\n    block->label = label;\n    blocks.push_back(block);\n    return block;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSinexBlockPtr Sinex::findBlock(const std::string &label)\n{\n  try\n  {\n    auto iter = std::find_if(blocks.begin(), blocks.end(), [&](const auto &b) {return b->label == label;});\n    if(iter == blocks.end())\n      throw(Exception(\"SINEX block not found: \"+label));\n    return *iter;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string Sinex::format(Double value, UInt length, UInt precision)\n{\n  try\n  {\n    std::string s = value%(\"%\"+length%\"%i\"s+\".\"+precision%\"%i\"s+\"f\");\n    if(s.size() > length && s.substr(0,3) == \"-0.\")\n      return \"-.\" + s.substr(3, s.size());\n    return s;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string Sinex::time2str(Time time, Bool fourDigitYear)\n{\n  try\n  {\n    if(time == Time() || time >= date2time(2500, 1, 1))\n      return (fourDigitYear ? \"0000\" : \"00\") + \":000:00000\"s;\n\n    // round to full second including rollover\n    UInt   year, month, day, hour, minute;\n    Double second;\n    time.date(year, month, day, hour, minute, second);\n    time = date2time(year, month, day, hour, minute, std::round(second)+0.1);\n    time.date(year, month, day, hour, minute, second);\n\n    std::stringstream ss;\n    if(fourDigitYear)\n      ss<<year%\"%04i\"s<<\":\";\n    else\n      ss<<(year%100)%\"%02i\"s<<\":\";\n    ss<<time.dayOfYear()%\"%03i\"s<<\":\";\n    ss<<std::round(time.mjdMod()*86400)%\"%05i\"s;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTime Sinex::str2time(const std::string &line, std::size_t pos, Bool zeroIsMaxTime, Bool fourDigitYear)\n{\n  try\n  {\n    UInt posOffset = fourDigitYear ? 2 : 0;\n    UInt year = static_cast<UInt>(String::toInt(line.substr(pos+0, 2+posOffset)));\n    UInt day  = static_cast<UInt>(String::toInt(line.substr(pos+3+posOffset, 3)));\n    UInt sec  = static_cast<UInt>(String::toInt(line.substr(pos+7+posOffset, 5)));\n    if((year == 0) && (day == 0) && (sec == 0))\n      return zeroIsMaxTime ? date2time(2500, 1, 1) : Time();\n    if(!fourDigitYear)\n      year += (year <= 50) ? 2000 : 1900;\n    return date2time(year,1,1) + mjd2time(day-1.) + seconds2time(static_cast<Double>(sec));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid writeFileSinex(const FileName &fileName, const Sinex &sinex)\n{\n  try\n  {\n    OutFile file(fileName);\n    file<<sinex.header<<std::endl;\n    file<<\"*\"<<std::string(79, '-')<<std::endl;\n    for(const auto &block : sinex.blocks)\n    {\n      file<<\"+\"<<block->label<<std::endl;\n      file<<block->ss.str();\n      file<<\"-\"<<block->label<<std::endl;\n      file<<\"*\"<<std::string(79, '-')<<std::endl;\n    }\n    file<<sinex.footer<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid readFileSinex(const FileName &fileName, Sinex &sinex)\n{\n  try\n  {\n    InFile file(fileName);\n\n    std::string line;\n    if(file.peek() == '%')\n      std::getline(file, sinex.header);\n    else\n      logWarning<<\"mandatory header in first line (starting with %) is missing\"<<Log::endl;\n\n    SinexBlockPtr block;\n    while(std::getline(file, line))\n    {\n      line = String::trimRight(line); // trim from end\n      if(line.empty() || (line.at(0) == '*')) // skip comments\n        continue;\n      else if(line.at(0) == '%')              // %ENDSNX\n        break;\n      else if(line.at(0) == '+')              // start data block\n      {\n        if(block && (block->label == \"FILE/COMMENT\"))\n          continue;\n        if(block)\n          throw(Exception(\"New SINEX block starts unexpectedly: '\"+line+\"' in block '\"+block->label+\"'\"));\n        block = sinex.addBlock(String::trim(line.substr(1)));\n      }\n      else if(line.at(0) == '-') // end data block\n      {\n        // Do not close the FILE/COMMENT block in case of comment lines starting incorrectly with \"-\"\n        if(block && (block->label == \"FILE/COMMENT\") && (block->label != String::trim(line.substr(1))))\n          continue;\n        if(!block || (block->label != String::trim(line.substr(1))))\n          throw(Exception(\"SINEX block ends unexpectedly: '\"+line+\"'\"));\n        block = nullptr;\n      }\n      else if(!block || (line.at(0) != ' ')) // unknown line\n      {\n        if(!block || (block->label != \"FILE/COMMENT\"))\n          logWarning<<\"Unknown line identifier: '\"<<line<<\"'\"<<Log::endl;\n      }\n      else\n        block->lines.push_back(String::trimRight(line));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, Sinex &sinex, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    Time                     timeStart, timeEnd;\n    std::string              agencyCode, observationCode, constraintCode, solutionContent;\n    std::string              description, output, contact, software, hardware, input;\n    std::vector<std::string> comments;\n    FileName                 fileNameComment;\n\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n    readConfig(config, \"agencyCode\",       agencyCode,       Config::OPTIONAL, \"TUG\",    \"identify the agency providing the data\");\n    readConfig(config, \"timeStart\",        timeStart,        Config::OPTIONAL, \"\",       \"start time of the data\");\n    readConfig(config, \"timeEnd\",          timeEnd,          Config::OPTIONAL, \"\",       \"end time of the data \");\n    readConfig(config, \"observationCode\",  observationCode,  Config::OPTIONAL, \"C\",      \"technique used to generate the SINEX solution\");\n    readConfig(config, \"constraintCode\",   constraintCode,   Config::OPTIONAL, \"2\",      \"0: tight constraint, 1: siginficant constraint, 2: unconstrained\");\n    readConfig(config, \"solutionContent\",  solutionContent,  Config::OPTIONAL, \"\",       \"solution types contained in the SINEX solution (S O E T C A)\");\n    readConfig(config, \"description\",      description,      Config::OPTIONAL, \"\",       \"organizitions gathering/alerting the file contents\");\n    readConfig(config, \"contact\",          contact,          Config::OPTIONAL, \"\",       \"Address of the relevant contact. e-mail\");\n    readConfig(config, \"output\",           output,           Config::OPTIONAL, \"\",       \"Description of the file contents\");\n    readConfig(config, \"input\",            input,            Config::OPTIONAL, \"\",       \"Brief description of the input used to generate this solution\");\n    readConfig(config, \"software\",         software,         Config::OPTIONAL, \"GROOPS (https://github.com/groops-devs/groops)\", \"Software used to generate the file\");\n    readConfig(config, \"hardware\",         hardware,         Config::OPTIONAL, \"\",       \"Computer hardware on which above software was run\");\n    readConfig(config, \"inputfileComment\", fileNameComment,  Config::OPTIONAL, \"\",       \"comments in the comment block from a file (truncated at 80 characters)\");\n    readConfig(config, \"comment\",          comments,         Config::OPTIONAL, \"\",       \"comments in the comment block\");\n    endSequence(config);\n    if(isCreateSchema(config))\n      return TRUE;\n\n    // header line\n    std::stringstream ss;\n    ss<<\"%=SNX 2.02 \"<<Sinex::resize(agencyCode.substr(0,3),3)<<\" \"<<Sinex::time2str(System::now())<<\" \"<<Sinex::resize(agencyCode.substr(0,3),3);\n    ss<<\" \"<<Sinex::time2str(timeStart)<<\" \"<<Sinex::time2str(timeEnd)<<\" \"<<Sinex::resize(observationCode.substr(0,1),1)<<\" 00000\";\n    ss<<\" \"<<Sinex::resize(constraintCode.substr(0,1),1)<<\" \"<<solutionContent;\n    sinex.header = ss.str();\n\n    {\n      SinexBlockPtr block = sinex.addBlock(\"FILE/REFERENCE\");\n      *block<<\"*INFO_TYPE_________ INFO________________________________________________________\"<<std::endl;\n      if(!description.empty()) *block<<\" DESCRIPTION        \"<<description<<std::endl;\n      if(!output.empty())      *block<<\" OUTPUT             \"<<output<<std::endl;\n      if(!contact.empty())     *block<<\" CONTACT            \"<<contact<<std::endl;\n      if(!software.empty())    *block<<\" SOFTWARE           \"<<software<<std::endl;\n      if(!hardware.empty())    *block<<\" HARDWARE           \"<<hardware<<std::endl;\n      if(!input.empty())       *block<<\" INPUT              \"<<input<<std::endl;\n    }\n\n    // comment block\n    if(!fileNameComment.empty() || comments.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"FILE/COMMENT\");\n      if(!fileNameComment.empty())\n      {\n        InFile commentFile(fileNameComment);\n        std::string line;\n        while(std::getline(commentFile, line))\n          *block<<\" \"<<line<<std::endl;\n      }\n      for(const auto &line : comments)\n        *block<<\" \"<<line<<std::endl;\n    }\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/fileSinex.h",
    "content": "/***********************************************/\n/**\n* @file fileSinex.h\n*\n* @brief SINEX file representation.\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2017-05-15\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILESINEX__\n#define __GROOPS_FILESINEX__\n\n#include \"base/import.h\"\n#include \"base/parameterName.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/logging.h\"\n#include \"config/config.h\"\n\n/***** TYPES ***********************************/\n\nclass SinexBlock;\ntypedef std::shared_ptr<SinexBlock> SinexBlockPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief SINEX file representation. */\nclass Sinex\n{\npublic:\n  std::string              header; /// SINEX file header line\n  std::string              footer; /// SINEX file footer line\n  std::list<SinexBlockPtr> blocks; /// SINEX blocks\n\n  Sinex() : header(\"%=SNX 2.02\"), footer(\"%ENDSNX\") {}\n\n  SinexBlockPtr findBlock(const std::string &label);\n  SinexBlockPtr addBlock(const std::string &label);\n\n  // conversion\n  static std::string resize(std::string str, UInt length) {str.resize(length, ' '); return str;}\n  static std::string format(Double value, UInt length=6, UInt precision=4);\n  static std::string time2str(Time time, Bool fourDigitYear=FALSE);\n  static Time        str2time(const std::string &line, UInt pos, Bool zeroIsMaxTime, Bool fourDigitYear=FALSE);\n};\n\n/***********************************************/\n\n/** @brief SINEX base block representation. */\nclass SinexBlock\n{\npublic:\n  std::string              label;\n  std::vector<std::string> lines; // from file\n  std::stringstream        ss;    // to file\n\n  std::ostream &operator<<(std::ostream  &(*pf)(std::ostream  &)) {pf(ss); return ss;} // sinex<<std::endl;\n  template<typename T> std::ostream &operator<<(const T &t) {return ss<<t;}\n};\n\n/***** FUNCTIONS *******************************/\n\nvoid writeFileSinex(const FileName &fileName, const Sinex &sinex);\nvoid readFileSinex(const FileName &fileName, Sinex &sinex);\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, Sinex &sinex, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/inputOutput/logging.cpp",
    "content": "/***********************************************/\n/**\n* @file logging.cpp\n*\n* @brief Screen and log file output.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2007-10-03\n*\n*/\n/***********************************************/\n\n#include <cassert>\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"inputOutput/system.h\"\n#include \"inputOutput/file.h\"\n#include \"logging.h\"\n\n/***** CLASS ***********************************/\n\nclass Logging\n{\npublic:\n  enum Type : UInt {STATUS, INFO, WARNINGONCE, WARNING, ERROR,\n                    GROUP, REMOVEGROUP, LOGFILE, LOGFILESONLY, CURRENTLOGFILEONLY};\n\nprivate:\n  struct GroupLocal\n  {\n    Bool isMain, mustSend;\n    GroupLocal(Bool isMain, Bool mustSend) : isMain(isMain), mustSend(mustSend) {}\n  };\n\n  // variables at process nodes\n  Type                  type;\n  std::stringstream     ss;\n  std::list<GroupLocal> groupsLocal;\n  std::function<void(UInt type, const std::string &str)> send;\n\n  struct Group\n  {\n    Bool isMain, onScreen, onFile;\n    Bool logFilesOnly, currentLogFileOnly;\n    std::shared_ptr<OutFile> file;\n    Group(Bool isMain, Bool onScreen, Bool onFile) : isMain(isMain), onScreen(onScreen), onFile(onFile), logFilesOnly(FALSE), currentLogFileOnly(FALSE) {}\n  };\n\n  // variables at main process\n  UInt rank, size;\n  Bool newLine;\n  std::vector<std::list<Group>> groups; // for each rank/process\n\n  void fatalError(const std::string &str) const;\n\npublic:\n  Logging();\n ~Logging();\n\n  void init(UInt rank_, UInt size_, const std::function<void(UInt type, const std::string &str)> &send_);\n\n  Log::GroupPtr group(Bool isMain, Bool silently);\n  void removeGroup();\n  void setLogFile(const std::string &name);\n  void logFilesOnly(Bool enable);\n  void currentLogFileOnly(Bool enable);\n\n  std::ostream &startLine(Type type);\n  std::ostream &endLine(std::ostream &stream);\n  void receive(UInt rank, UInt type, const std::string &str);\n\n  friend class Log::Timer;\n};\n\nstatic Logging logging;\n\n/***********************************************/\n\nLogging::Logging() : type(STATUS), groupsLocal({GroupLocal(TRUE, TRUE)}),\n                     rank(0), size(1), newLine(FALSE), groups({std::list<Group>({Group(TRUE, TRUE, TRUE)})})\n{\n  send = std::bind(&Logging::receive, this, 0, std::placeholders::_1, std::placeholders::_2);\n}\n\n/***********************************************/\n\nLogging::~Logging()\n{\n  if(!ss.str().empty())\n  {\n    endLine(ss);\n    std::cerr<<\"WARNING: last log line does not end with with Log::endl\"<<std::endl;\n    std::cerr<<\"line = '\"<<ss.str()<<\"'\"<<std::endl;\n  }\n}\n\n/***********************************************/\n\nvoid Logging::init(UInt rank_, UInt size_, const std::function<void(UInt type, const std::string &str)> &send_)\n{\n  try\n  {\n    rank = rank_;\n    size = size_;\n    send = send_;\n\n    groupsLocal.clear();\n    groupsLocal.emplace_front((rank == 0), TRUE);\n\n    groups.clear();\n    if(rank == 0)\n      groups.resize(size, std::list<Group>({Group((rank == 0), TRUE, TRUE)}));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nclass Log::Group\n{\npublic:\n  Group() {}\n ~Group() {logging.removeGroup();}\n};\n\n/***********************************************/\n\nLog::GroupPtr Logging::group(Bool isMain, Bool silently)\n{\n  try\n  {\n    assert(groupsLocal.size());\n    send(GROUP, (isMain ? \"1\"s : \"0\"s) + (!silently ? \"1\"s : \"0\"s));\n    const Bool mustSendBefore = groupsLocal.front().mustSend;\n    groupsLocal.emplace_front(isMain, !silently && mustSendBefore);\n    return std::make_shared<Log::Group>();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Logging::removeGroup()\n{\n  try\n  {\n    assert(groupsLocal.size());\n    send(REMOVEGROUP, \"\");\n    groupsLocal.pop_front();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Logging::setLogFile(const std::string &name)\n{\n  try\n  {\n    if(name.empty())\n      return;\n    assert(groupsLocal.size());\n    send(LOGFILE, name);\n    groupsLocal.front().mustSend = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Logging::logFilesOnly(Bool enable)\n{\n  try\n  {\n    send(LOGFILESONLY, enable ? \"1\" : \"0\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Logging::currentLogFileOnly(Bool enable)\n{\n  try\n  {\n    send(CURRENTLOGFILEONLY, enable ? \"1\" : \"0\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::ostream &Logging::startLine(Type type_)\n{\n  try\n  {\n    if(!ss.str().empty())\n    {\n      endLine(ss);\n      std::cerr<<\"WARNING: last log line does not end with with Log::endl\"<<std::endl;\n      std::cerr<<\"line = '\"<<ss.str()<<\"'\"<<std::endl;\n    }\n\n    type = type_;\n    return ss;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::ostream &Logging::endLine(std::ostream &stream)\n{\n  try\n  {\n    if(&stream != &ss)\n      throw(Exception(\"Log::endl used with other ostream than log\"));\n\n    // send log line to main process\n    assert(groupsLocal.size());\n    if((groupsLocal.front().isMain && (groupsLocal.front().mustSend || (type == WARNINGONCE))) || (type == WARNING) || (type == ERROR))\n      for(const std::string &str :  String::split(ss.str(), '\\n'))\n        send(type, str);\n\n    ss.str(\"\");\n    return stream;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// received log line at main node\nvoid Logging::receive(UInt rank, UInt type, const std::string &str)\n{\n  try\n  {\n    assert(groups.size() && groups.at(rank).size());\n\n    if(type == GROUP)\n    {\n      const Bool onScreen = groups.at(rank).front().onScreen;\n      groups.at(rank).emplace_front(str.at(0) == '1', (str.at(1) == '1') && onScreen, (str.at(1) == '1'));\n      return;\n    }\n\n    if(type == REMOVEGROUP)\n    {\n      groups.at(rank).pop_front();\n      return;\n    }\n\n    if(type == LOGFILE)\n    {\n      // already open?\n      for(auto &groupsRank : groups)\n        for(auto &group : groupsRank)\n          if(group.file && (group.file->fileName().str() == str))\n          {\n            groups.at(rank).front().file = group.file;\n            return;\n          }\n      groups.at(rank).front().file = std::make_shared<OutFile>(str);\n      return;\n    }\n\n    if(type == LOGFILESONLY)\n    {\n      groups.at(rank).front().logFilesOnly = (str == \"1\");\n      return;\n    }\n\n    if(type == CURRENTLOGFILEONLY)\n    {\n      groups.at(rank).front().currentLogFileOnly = (str == \"1\");\n      return;\n    }\n\n    // screen\n    // ------\n    if(!groups.at(rank).front().logFilesOnly && !groups.at(rank).front().currentLogFileOnly)\n      if((groups.at(rank).front().isMain && (groups.at(rank).front().onScreen || (type == WARNINGONCE))) || (type == WARNING) || (type == ERROR))\n      {\n        if(newLine)\n          std::cout<<std::endl<<std::flush;\n        newLine = FALSE;\n        if((type == STATUS) || (type == INFO))\n          std::cout<<(rank ? rank%\"(process%3i) \"s : \"\"s)<<str<<std::endl<<std::flush;\n        else\n#ifdef _WIN32\n          std::cerr<<(rank ? rank%\"(process%3i) \"s : \"\"s)<<str<<std::endl<<std::flush;\n#else\n          std::cerr<<\"\\033[1;31m\"<<(rank ? rank%\"(process%3i) \"s : \"\"s)<<str<<\"\\033[0m\"<<std::endl<<std::flush; // ANSI escape sequence: red and bold\n#endif\n      }\n\n    // log files\n    // ---------\n    for(auto &group : groups.at(rank))\n    {\n      if(group.file)\n        switch(type)\n        {\n          case STATUS:      *(group.file)<<System::now()%\"%y-%m-%d %H:%M:%S\"s<<\" Status  \"<<(group.isMain ? \"\"s : rank%\"(process%3i) \"s)<<str<<std::endl; break;\n          case INFO:        *(group.file)<<System::now()%\"%y-%m-%d %H:%M:%S\"s<<\" Info    \"<<(group.isMain ? \"\"s : rank%\"(process%3i) \"s)<<str<<std::endl; break;\n          case WARNINGONCE: *(group.file)<<System::now()%\"%y-%m-%d %H:%M:%S\"s<<\" WARNING \"<<(group.isMain ? \"\"s : rank%\"(process%3i) \"s)<<str<<std::endl; break;\n          case WARNING:     *(group.file)<<System::now()%\"%y-%m-%d %H:%M:%S\"s<<\" WARNING \"<<(group.isMain ? \"\"s : rank%\"(process%3i) \"s)<<str<<std::endl; break;\n          case ERROR:       *(group.file)<<System::now()%\"%y-%m-%d %H:%M:%S\"s<<\" ERROR   \"<<(group.isMain ? \"\"s : rank%\"(process%3i) \"s)<<str<<std::endl; break;\n        }\n      // send to logfile in higher level?\n      if(group.currentLogFileOnly)\n        break;\n      if(!(group.isMain && (group.onFile || (type == WARNINGONCE))) && (type != WARNING) && (type != ERROR))\n        break;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nLog::Timer::Timer() : start(System::now()), count(0), processCount(1), use(TRUE) {}\n\n/***********************************************/\n\nLog::Timer::Timer(UInt count, UInt processCount, Bool use) : start(System::now()), count(count), processCount(processCount), use(use) {}\n\n/***********************************************/\n\nvoid Log::Timer::loopStep(UInt idx)\n{\n  try\n  {\n    assert((logging.rank > 0) || (logging.groups.size() && logging.groups.at(0).size()));\n    if(!use || (count == 0) || (logging.rank != 0) || !logging.groups.at(0).front().onScreen)\n      return;\n\n    if(idx >= 5000)\n    {\n      const UInt digits = static_cast<UInt>(std::log10(idx+1)) + 1;\n      if((idx+1) % static_cast<UInt>(std::pow(10, digits-3)))\n        return;\n    }\n\n    count = std::max(count, idx+1);\n    const Double diff    = (System::now()-start).mjd();\n    const Double perStep = (idx >= processCount) ? diff/(idx/processCount) : 0.;\n    const Double left    = ((count+processCount-1)/processCount - idx/processCount) * perStep;\n\n    const std::string countStr = count%\"%i\"s;\n    std::cout<<\"\\r  \"<<std::setw(countStr.size())<<idx+1<<\" of \"<<countStr<<\" (time: \"<<diff%\"%H:%M:%S, remaining: \"s<<left%\"%H:%M:%S) \"s<<std::flush;\n    logging.newLine = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Log::Timer::loopEnd() const\n{\n  try\n  {\n    if(!use)\n      return;\n\n    assert((logging.rank > 0) || (logging.groups.size() && logging.groups.at(0).size()));\n    if((logging.rank == 0) && logging.groups.at(0).front().onScreen)\n    {\n      std::cout<<\"\\r  \"<<count<<\" of \"<<count<<\" (time: \"<<(System::now()-start)%\"%H:%M:%S, remaining: \"s<<0.%\"%H:%M:%S) \"s<<std::endl<<std::flush;\n      logging.newLine = FALSE;\n    }\n    // to log file(s)\n    logFilesOnly(TRUE);\n    logStatus<<count<<\" loops in time \"<<(System::now()-start)%\"%H:%M:%S\"s<<Log::endl;\n    logFilesOnly(FALSE);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::function<void(UInt rank, UInt type, const std::string &str)> Log::getReceive() {return std::bind(&Logging::receive, &logging, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);}\nvoid Log::init(UInt rank, UInt size, const std::function<void(UInt type, const std::string &str)> &send) {logging.init(rank, size, send);}\nLog::GroupPtr Log::group(Bool isMain, Bool silently) {return logging.group(isMain, silently);}\nvoid Log::setLogFile(const std::string &name)        {logging.setLogFile(name);}\nvoid Log::logFilesOnly(Bool enable)                  {logging.logFilesOnly(enable);}\nvoid Log::currentLogFileOnly(Bool enable)            {logging.currentLogFileOnly(enable);}\nstd::ostream &Log::status()                          {return logging.startLine(Logging::STATUS);}\nstd::ostream &Log::info()                            {return logging.startLine(Logging::INFO);}\nstd::ostream &Log::warningOnce()                     {return logging.startLine(Logging::WARNINGONCE);}\nstd::ostream &Log::warning()                         {return logging.startLine(Logging::WARNING);}\nstd::ostream &Log::error()                           {return logging.startLine(Logging::ERROR);}\nstd::ostream &Log::endl(std::ostream &stream)        {return logging.endLine(stream);}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/logging.h",
    "content": "/***********************************************/\n/**\n* @file logging.h\n*\n* @brief Screen and log file output.\n*\n* Calling logStatus<<\"Text\"<<Log::endl;\n* outputs \"Text\" on the screen\n* and \"2007-10-03 11:49:35 Status Text\" in the log file.\n* Only outputs from the main process are printed.\n* Next to logStatus there are also logInfo, logWarning, logError.\n* IMPORTANT: Each output must end with Log::endl.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2007-10-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_LOGGING__\n#define __GROOPS_LOGGING__\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n\n/** @addtogroup inputOutputGroup */\n/// @{\n\n/***** DEFINES *********************************/\n\n#define logStatus      Log::status()\n#define logInfo        Log::info()\n#define logWarning     Log::warning()\n#define logWarningOnce Log::warningOnce()\n#define logError       Log::error()\n\n/***********************************************/\n\nnamespace Log\n{\n  class Group;\n  typedef std::shared_ptr<Group> GroupPtr;\n\n  std::function<void(UInt rank, UInt type, const std::string &str)> getReceive();\n  void init(UInt rank, UInt size, const std::function<void(UInt type, const std::string &str)> &send);\n\n  GroupPtr group(Bool isMain, Bool silently);  // sub groups of parallel processes\n  void setLogFile(const std::string &name);    // set log file for current group (must be called by every process in group)\n  void logFilesOnly(Bool enable);              // write only to log file(s) (must be called by every process in group)\n  void currentLogFileOnly(Bool enable);        // write only to the current log file in this group (must be called by every process in group)\n\n  std::ostream &status();\n  std::ostream &info();\n  std::ostream &warningOnce();\n  std::ostream &warning();\n  std::ostream &error();\n  std::ostream &endl(std::ostream &stream);\n\n  class Timer\n  {\n    Time start;\n    UInt count, processCount;\n    Bool use;\n\n  public:\n    Timer();\n    Timer(UInt count, UInt processCount=1, Bool use=TRUE);\n    void loopStep(UInt idx);\n    void loopEnd() const;\n  };\n}\n\n/***********************************************/\n\n/// @}\n\n#endif\n"
  },
  {
    "path": "source/inputOutput/settings.cpp",
    "content": "/***********************************************/\n/**\n* @file settings.cpp\n*\n* @brief Read/write constants.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/time.h\"\n#include \"parser/xml.h\"\n#include \"inputOutput/fileName.h\"\n#include \"inputOutput/file.h\"\n#include \"settings.h\"\n\n/***** FUNCTIONS *******************************/\n\nvoid readFileSettings(const FileName &fileName)\n{\n  try\n  {\n    InFile stream(fileName);\n    XmlNodePtr xmlNode = XmlNode::read(stream);\n\n    readXml(xmlNode, \"LIGHT_VELOCITY\", LIGHT_VELOCITY);\n    readXml(xmlNode, \"DEFAULT_GM\",     STRING_DEFAULT_GM);\n    readXml(xmlNode, \"DEFAULT_R\",      STRING_DEFAULT_R);\n    readXml(xmlNode, \"GRS80_a\",        STRING_DEFAULT_GRS80_a);\n    readXml(xmlNode, \"GRS80_f\",        STRING_DEFAULT_GRS80_f);\n    DEFAULT_GM      = std::atof(STRING_DEFAULT_GM.c_str());\n    DEFAULT_R       = std::atof(STRING_DEFAULT_R.c_str());\n    DEFAULT_GRS80_a = std::atof(STRING_DEFAULT_GRS80_a.c_str());\n    DEFAULT_GRS80_f = std::atof(STRING_DEFAULT_GRS80_f.c_str());\n    readXml(xmlNode, \"GRAVITATIONALCONSTANT\", GRAVITATIONALCONSTANT);\n    readXml(xmlNode, \"R_Earth\",       R_Earth);\n    readXml(xmlNode, \"R_Moon\",        R_Moon);\n    readXml(xmlNode, \"GM_Earth\",      GM_Earth);\n    readXml(xmlNode, \"GM_Sun\",        GM_Sun);\n    readXml(xmlNode, \"GM_Moon\",       GM_Moon);\n    readXml(xmlNode, \"GM_MERCURY\",    GM_MERCURY);\n    readXml(xmlNode, \"GM_VENUS\",      GM_VENUS);\n    readXml(xmlNode, \"GM_MARS\",       GM_MARS);\n    readXml(xmlNode, \"GM_JUPITER\",    GM_JUPITER);\n    readXml(xmlNode, \"GM_SATURN\",     GM_SATURN);\n    readXml(xmlNode, \"TIME_EPSILON\",  TIME_EPSILON);\n    readXml(xmlNode, \"DELTA_TAI_GPS\", DELTA_TAI_GPS);\n    readXml(xmlNode, \"DELTA_TT_GPS\",  DELTA_TT_GPS);\n    readXml(xmlNode, \"J2000\",         STRING_J2000);\n    J2000 = atof(STRING_J2000.c_str());\n\n    // read leap seconds\n    UInt count = xmlNode->getChildCount(\"leapSecond\");\n    MJD_UTC_GPS.resize(count);\n    DELTA_UTC_GPS.resize(count);\n    for(UInt i=0; i<count; i++)\n    {\n      XmlNodePtr xmlNode2 = getChild(xmlNode, \"leapSecond\");\n      readXml(xmlNode2, \"MJD\",            MJD_UTC_GPS.at(i));\n      readXml(xmlNode2, \"DELTA_UTC_GPS\",  DELTA_UTC_GPS.at(i));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid writeFileSettings(const FileName &fileName)\n{\n  try\n  {\n    XmlNodePtr xmlNode = XmlNode::create(\"groops\");\n\n    writeXml(xmlNode, \"LIGHT_VELOCITY\", LIGHT_VELOCITY);\n    writeXml(xmlNode, \"DEFAULT_GM\",     STRING_DEFAULT_GM);\n    writeXml(xmlNode, \"DEFAULT_R\",      STRING_DEFAULT_R);\n    writeXml(xmlNode, \"GRS80_a\",        STRING_DEFAULT_GRS80_a);\n    writeXml(xmlNode, \"GRS80_f\",        STRING_DEFAULT_GRS80_f);\n    writeXml(xmlNode, \"GRAVITATIONALCONSTANT\", GRAVITATIONALCONSTANT);\n    writeXml(xmlNode, \"R_Earth\",        R_Earth);\n    writeXml(xmlNode, \"R_Moon\",         R_Moon);\n    writeXml(xmlNode, \"GM_Earth\",       GM_Earth);\n    writeXml(xmlNode, \"GM_Sun\",         GM_Sun);\n    writeXml(xmlNode, \"GM_Moon\",        GM_Moon);\n    writeXml(xmlNode, \"GM_MERCURY\",     GM_MERCURY);\n    writeXml(xmlNode, \"GM_VENUS\",       GM_VENUS);\n    writeXml(xmlNode, \"GM_MARS\",        GM_MARS);\n    writeXml(xmlNode, \"GM_JUPITER\",     GM_JUPITER);\n    writeXml(xmlNode, \"GM_SATURN\",      GM_SATURN);\n    writeXml(xmlNode, \"TIME_EPSILON\",   TIME_EPSILON);\n    writeXml(xmlNode, \"DELTA_TAI_GPS\",  DELTA_TAI_GPS);\n    writeXml(xmlNode, \"DELTA_TT_GPS\",   DELTA_TT_GPS);\n    writeXml(xmlNode, \"J2000\",          STRING_J2000);\n\n    for(UInt i=0; i<DELTA_UTC_GPS.size(); i++)\n    {\n      XmlNodePtr xmlNode2 = createXmlNode(xmlNode, \"leapSecond\");\n      writeXml(xmlNode2, \"MJD\",            MJD_UTC_GPS.at(i));\n      writeXml(xmlNode2, \"DELTA_UTC_GPS\",  DELTA_UTC_GPS.at(i));\n    }\n\n    OutFile file(fileName);\n    XmlNode::write(file, xmlNode);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/settings.h",
    "content": "/***********************************************/\n/**\n* @file settings.h\n*\n* @brief Read/write constants.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-03-01\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SETTINGS__\n#define __GROOPS_SETTINGS__\n\n#include \"inputOutput/fileName.h\"\n\n/***** FUNCTIONS *******************************/\n\n/// @{\n\n/** @brief Read constants to file.\n* @ingroup inputOutputGroup\n* The default values are overwritten. */\nvoid readFileSettings(const FileName &fileName);\n\n/** @brief Write the currently used constants to file.\n* @ingroup inputOutputGroup\n@verbatim\ngroops --write-settings <fileName.xml>\n@endverbatim */\nvoid writeFileSettings(const FileName &fileName);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/inputOutput/system.cpp",
    "content": "/***********************************************/\n/**\n* @file system.cpp\n*\n* @brief Operating system related functions.\n*\n* @author Andreas Kvas\n* @date 2017-03-21\n*\n*/\n/***********************************************/\n\n#ifdef _WIN32\n  #define popen  _popen\n  #define pclose _pclose\n#endif\n\n#include <ctime>\n#include <filesystem>\n#include \"base/importStd.h\"\n#include \"base/string.h\"\n#include \"base/time.h\"\n#include \"system.h\"\n\n/***********************************************/\n\nBool System::exec(const std::string &command, std::vector<std::string> &output)\n{\n  try\n  {\n    std::FILE *pipe = popen(command.c_str(), \"r\");\n    if(!pipe)\n      throw(Exception(\"Cannot open pipe\"));\n\n    char buffer[1024];\n    while(std::fgets(buffer, sizeof(buffer), pipe) != nullptr)\n    {\n      std::string line(buffer);\n      output.push_back(line.substr(0, line.find_last_of('\\n')));\n    }\n\n    return (pclose(pipe) == 0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool System::exec(const std::string &command)\n{\n  std::vector<std::string> output;\n  return exec(command, output);\n}\n\n/***********************************************/\n/***********************************************/\n\nBool System::createDirectories(const FileName &fileName)\n{\n  if(isDirectory(fileName))\n    return TRUE;\n  return std::filesystem::create_directories(fileName.str());\n}\n\n/***********************************************/\n\nBool System::remove(const FileName &fileName)\n{\n  return (std::filesystem::remove_all(fileName.str()) != 0);\n}\n\n/***********************************************/\n\nBool System::move(const FileName &fileNameOld, const FileName &fileNameNew)\n{\n  try\n  {\n    if(!exists(fileNameOld))\n      return FALSE;\n    if(isDirectory(fileNameNew))\n      std::filesystem::rename(fileNameOld.str(), fileNameNew.append(fileNameOld.stripDirectory()).str());\n    else\n      std::filesystem::rename(fileNameOld.str(), fileNameNew.str());\n    return TRUE;\n  }\n  catch(std::exception &/*e*/)\n  {\n    return FALSE;\n  }\n}\n\n/***********************************************/\n\nBool System::exists(const FileName &fileName)\n{\n  try\n  {\n    return fileList(fileName).size();\n  }\n  catch(std::exception &/*e*/)\n  {\n    return FALSE;\n  }\n}\n\n/***********************************************/\n\nstd::vector<FileName> System::fileList(const FileName &fileName)\n{\n  try\n  {\n    // contains no wildcards?\n    if(fileName.str().find_first_of(\"*?\") == std::string::npos)\n      return (std::filesystem::exists(fileName.str()) ? std::vector<FileName>{fileName} : std::vector<FileName>{});\n\n    // split path into parts\n    std::vector<std::string> parts = String::split(fileName.str(), \"/\\\\\");\n\n    // deepest directory without wildcards\n    std::string path;\n    UInt level = 0;\n    while((level<parts.size()-1) && (parts.at(level).find_first_of(\"*?\") == std::string::npos))\n      path += parts.at(level++) + \"/\";\n    if(path.empty())\n      path = currentWorkingDirectory().str() + \"/\";\n    if(!std::filesystem::exists(path))\n      return std::vector<FileName>{};\n\n    // search directory for matching entries\n    std::vector<FileName> list;\n    const std::regex pattern = String::wildcard2regex(parts.at(level));\n    for(auto const &entry : std::filesystem::directory_iterator{path})\n      if(std::regex_match(entry.path().filename().string(), pattern))\n      {\n        if(level == parts.size()-1)\n          list.push_back(path+entry.path().filename().string());\n        else if(std::filesystem::is_directory(entry))\n        {\n          // replace pattern by current entry\n          std::string path2 = path + entry.path().filename().string() + \"/\";\n          for(UInt i=level+1; i<parts.size()-1; i++)\n            path2 += parts.at(i) + \"/\";\n          std::vector<FileName> list2 = fileList(path2+parts.back());\n          list.insert(list.end(), list2.begin(), list2.end());\n        }\n      }\n\n    return list;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt System::fileSize(const FileName &fileName)\n{\n  try\n  {\n    return std::filesystem::file_size(fileName.str());\n  }\n  catch(std::exception &/*e*/)\n  {\n    return 0;\n  }\n}\n\n/***********************************************/\n\nBool System::isDirectory(const FileName &fileName)\n{\n  return std::filesystem::is_directory(fileName.str());\n}\n\n/***********************************************/\n\nFileName System::currentWorkingDirectory()\n{\n  return FileName(std::filesystem::current_path().string());\n}\n\n/***********************************************/\n\nstd::vector<FileName> System::directoryListing(const FileName &path, const std::regex &pattern)\n{\n  try\n  {\n    std::vector<FileName> files;\n    for(auto const &entry : std::filesystem::directory_iterator{path.str()})\n      if(std::filesystem::is_regular_file(entry) && std::regex_match(entry.path().filename().string(), pattern))\n        files.push_back(FileName(entry.path().filename().string()));\n    return files;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nTime System::now()\n{\n  std::time_t tt = std::time(nullptr);\n  std::tm     t  = *std::localtime(&tt);\n  return date2time(t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/inputOutput/system.h",
    "content": "/***********************************************/\n/**\n* @file system.h\n*\n* @brief Operating system related functions.\n*\n* @author Andreas Kvas\n* @date 2017-03-21\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SYSTEM__\n#define __GROOPS_SYSTEM__\n\n#include \"base/importStd.h\"\n#include \"inputOutput/fileName.h\"\n#include <regex>\n\n/** @brief System operations.\n* @ingroup inputOutputGroup */\nnamespace System\n{\n  /** @brief Execute a command using the system shell.\n  * @param command command to be executed as string.\n  * @param[out] output command output is appended line by line (without newline).\n  * @return success if executed command returns without error.  */\n  Bool exec(const std::string &command, std::vector<std::string> &output);\n\n  /** @brief Execute a command using the system shell.\n  * @param command command to be executed as string\n  * @return success if executed command returns without error.  */\n  Bool exec(const std::string &command);\n\n  /** @brief Creates the directory and parent directories as needed.\n  * @param fileName file to be created.\n  * @return TRUE if a directory was created or exists already. */\n  Bool createDirectories(const FileName &fileName);\n\n  /** @brief Remove a file or directory.\n  * Deletes also the content recursivley if @a fileName is a directory.\n  * @param fileName file to be removed.\n  * @return TRUE if the file was deleted. */\n  Bool remove(const FileName &fileName);\n\n  /** @brief moves a file or directory.\n  * @param fileNameOld file to be moved.\n  * @param fileNameNew target path for the move/rename operation.\n  * @return TRUE if the file was moved. */\n  Bool move(const FileName &fileNameOld, const FileName &fileNameNew);\n\n  /** @brief Checks if the given file or path corresponds to an existing file or directory.\n  * Supports wildcards: * and ?. */\n  Bool exists(const FileName &fileName);\n\n  /** @brief List of files and directories that match the wildcard (* and ?). */\n  std::vector<FileName> fileList(const FileName &fileName);\n\n  /** @brief Returns size (in byte) of a given file*/\n  UInt fileSize(const FileName &fileName);\n\n  /** @brief Check whether fileName is an existing directory */\n  Bool isDirectory(const FileName &fileName);\n\n  /** @brief Current working directory as FileName. */\n  FileName currentWorkingDirectory();\n\n  /** @brief returns the file names of a directory that match the regex pattern. */\n  std::vector<FileName> directoryListing(const FileName &path, const std::regex &pattern);\n\n  /** @brief Current time as used by the file system. */\n  Time now();\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/grace/graceKBandGeometry.cpp",
    "content": "/***********************************************/\n/**\n* @file graceKBandGeometry.cpp\n*\n* @brief Compute quantities derived from the specific GRACE K-Band ranging instrument observation geometry.\n*\n* @author Matthias Ellmer\n* @date 2017-11-13\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"graceKBandGeometry.h\"\n\n/***********************************************/\n\nSatelliteTrackingArc GraceKBandGeometry::antennaCenterCorrection(const OrbitArc &orbit1, const OrbitArc &orbit2,\n                                                                 const StarCameraArc &starCamera1, const StarCameraArc &starCamera2,\n                                                                 const Vector3d &center1, const Vector3d &center2, UInt degree)\n{\n  try\n  {\n    Matrix A(orbit1.size(), 4);\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      const Vector3d u = (orbit2.at(i).position - orbit1.at(i).position);                                       // center of mass vector\n      const Vector3d v = (starCamera2.at(i).rotary.rotate(center2) - starCamera1.at(i).rotary.rotate(center1)); // combined antenna offset vector\n      A(i,1) = u.r() - (u+v).r();  // COM - ANT -> AOC\n    }\n\n    const std::vector<Time> times = orbit1.times();\n    Polynomial p(times, degree);\n    copy(p.derivative(   times, A.column(1)), A.column(2));\n    copy(p.derivative2nd(times, A.column(1)), A.column(3));\n\n    return Arc(times, A, Epoch::Type::SATELLITETRACKING);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GraceKBandGeometry::partialOfAntennaCenterCorrectionWrtRollPitchYaw(const OrbitArc &pos1, const OrbitArc &pos2, const StarCameraArc &rotSat1, const StarCameraArc &rotSat2,\n                                                                         const Vector3d &center1, const Vector3d &center2,\n                                                                         Matrix &SparseJacobian1, Matrix &SparseJacobian2)\n{\n  try\n  {\n    Arc::checkSynchronized({pos1, pos2, rotSat1, rotSat2});\n    const UInt epochCount = pos1.size();\n\n    // Really the partials are size epochCount x 3 * epochCount\n    // However, for ranges, which we are computing here, all partials\n    // outside of the current epoch are 0, so we save some memory\n    // by only storing the fields that contain data.\n    SparseJacobian1 = Matrix(epochCount, 3); ///< size epochCount x 3\n    SparseJacobian2 = Matrix(epochCount, 3); ///< size epochCount x 3\n\n    /*\n     * Model:\n     * S: SRF\n     * C: CRF\n     * N: Nominal (SRF is such that K-Frame is aligned to Line of Sight)\n     * Roll/Pitch/Yaw are differential rotations between N and S\n     * aoc = [R(S->C) c(S)] \\cdot [u(C)]\n     * We write the first rotary as a combination of two rotaries:\n     * aoc = [R(N->C) R(S->N) c(S)] \\cdot [u(C)]\n     * R(N->C) is large rotations, exactly known (from orbit and satellite geometry) and error free\n     * R(S->N) is small angles with observation errors (S is observed by SCA) and covariance from fusion\n     * Re-write inner product\n     * aoc = [R(N->C) R(S->N) c(S)] \\cdot [u(C)]\n     *     = [R(N->C) R(S->N) c(S)]^T [u(C)]\n     *     = c(S)^T R(S->N)^T R(N->C)^T u(C)\n     *     = c(S)^T R(S->N)^T [R(C->N) u(C)]\n     * Now, the last term [R(N->C)^T u(C)] is the orientation of the baseline in the Nominal system.\n     * Per definition, this is exactly the direction of the K-Band Phase center, so the equation is\n     * aoc = c(S)^T R(N->S)^T c(S)/norm(c(S))\n     * We can then take the derivative of this equation wrt roll/pitch/yaw in R(N->S)^T using the\n     * chain rule\n     * d aoc/ d rpy = (d aoc / d R) * (d R / d rpy)\n     */\n\n    // partial derivatives\n    // -------------------\n    auto daoc_dR = [](Vector3d c)\n    {\n      return 1./c.norm() * Matrix({{c.x()*c.x(), c.x()*c.y(), c.x()*c.z(),\n                                    c.y()*c.x(), c.y()*c.y(), c.y()*c.z(),\n                                    c.z()*c.x(), c.z()*c.y(), c.z()*c.z()}}); ///< size 1x9\n    };\n\n    // these are constant throughout the arc\n    const auto daoc_dR1 = daoc_dR(center1); ///< size 1x9\n    const auto daoc_dR2 = daoc_dR(center2); ///< size 1x9\n\n    // this changes from epoch to epoch\n    auto dR_drpy = [](Rotary3d R){\n      Angle roll, pitch, yaw;\n      R.cardan(roll, pitch, yaw);\n\n      const Double cr = std::cos(roll);\n      const Double sr = std::sin(roll);\n\n      const Double cp = std::cos(pitch);\n      const Double sp = std::sin(pitch);\n\n      const Double cy = std::cos(yaw);\n      const Double sy = std::sin(yaw);\n\n      // roll\n      Matrix dR_dr = {{0,  sp*cr*cy - sr*sy,  sp*sr*cy + sy*cr},\n                      {0, -sp*sy*cr - sr*cy, -sp*sr*sy + cr*cy},\n                      {0, -cp*cr,            -sr*cp           }};\n\n      // pitch\n      Matrix dR_dp = {{-sp*cy,  sr*cp*cy, -cp*cr*cy},\n                      { sp*sy, -sr*sy*cp,  sy*cp*cr},\n                      { cp,     sp*sr,    -sp*cr   }};\n      // yaw\n      Matrix dR_dy = {{-sy*cp, -sp*sr*sy + cr*cy, sp*sy*cr + sr*cy},\n                      {-cp*cy, -sp*sr*cy - sy*cr, sp*cr*cy - sr*sy},\n                      { 0,      0,                0               }};\n\n      Matrix dR_drpy(9,3);\n      copy(flatten(dR_dr), dR_drpy.column(0));\n      copy(flatten(dR_dp), dR_drpy.column(1));\n      copy(flatten(dR_dy), dR_drpy.column(2));\n      return dR_drpy;\n    };\n\n    // Rotation from SRF -> K-Band frame\n    const Rotary3d rotKFrame1 = inverse(Rotary3d(center1, Vector3d(0,1,0)));\n    const Rotary3d rotKFrame2 = inverse(Rotary3d(center2, Vector3d(0,1,0)));\n\n    // variance propagation\n    // --------------------\n    for (UInt i = 0; i < epochCount; i++)\n    {\n      // u is center of mass vector\n      Vector3d u = pos2.at(i).position - pos1.at(i).position;\n      u.normalize();\n\n      // Nominal rotation CRF -> SRF. Nominal orientation of the SRF is so that the K-Frame is aligned to the line-of sight axis\n      const Rotary3d rotSat1Nominal = Rotary3d( u, crossProduct( u, pos1.at(i).position)) * rotKFrame1;\n      const Rotary3d rotSat2Nominal = Rotary3d(-u, crossProduct(-u, pos2.at(i).position)) * rotKFrame2;\n\n      // Differential rotation (roll/pitch/yaw) about the nominal orientation (towards other satellite)\n      const Rotary3d rotSat1observed = inverse(inverse(rotSat1Nominal) * rotSat1.at(i).rotary);\n      const Rotary3d rotSat2observed = inverse(inverse(rotSat2Nominal) * rotSat2.at(i).rotary);\n\n      matMult(1.0, daoc_dR1, dR_drpy(rotSat1observed), SparseJacobian1.row(i));\n      matMult(1.0, daoc_dR2, dR_drpy(rotSat2observed), SparseJacobian2.row(i));\n    } // for arc.epochCount\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GraceKBandGeometry::sstResidual2RPYresidualProjector(const_MatrixSliceRef SparseJacobian, const_MatrixSliceRef CovarianceSca,\n                                                            const std::vector<Time> &times, const UInt sstType, const UInt degree)\n{\n  try\n  {\n    // Each 3x3 block in CovarianceSca is Q_ij\n    // Each 1x3 row in partialGrace is P_i\n    // Each 3x1 block in I_ij := -1 * Q_ij * P_j.T\n    const UInt epochCount = SparseJacobian.rows();\n    Matrix A(3*epochCount, epochCount);\n    for(UInt i=0; i<epochCount; i++)\n      for(UInt j=0; j<epochCount; j++)\n        matMult(1.0, CovarianceSca.slice(i*3,j*3,3,3), SparseJacobian.row(j).trans(), A.slice(3*i,j,3,1));\n\n    // Derivative\n    // ----------\n    if(sstType == 0)\n      return A;\n    Polynomial p(times, degree);\n    if(sstType == 1) // range rate\n      return p.derivative(times, A.trans()).trans();\n    if(sstType == 2) // range rangeAcceleration\n      return p.derivative2nd(times, A.trans()).trans();\n    throw(Exception(\"Unknown sst type\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix GraceKBandGeometry::variancePropagationStarCamera2SatelliteRanging(const_MatrixSliceRef SparseJacobian, const_MatrixSliceRef CovarianceSca,\n                                                                          const std::vector<Time> &times, const UInt sstType, const UInt degree)\n{\n  try\n  {\n    // Variance propagation but the Jacobian of the range wrt. the quaternion elements is just the sparse representation\n    const UInt epochCount = SparseJacobian.rows();\n\n    // Each 3x3 block in CovarianceSca is Q_ij\n    // Each 1x3 row in SparseJacobian is P_i\n    // Variance propagation is C = P * Q * P.T\n    // Each 1x1 block in C_ij := P_i * Q_ij * P_j.T\n    Matrix Covariance(epochCount, Matrix::SYMMETRIC, Matrix::UPPER);\n    for(UInt i=0; i<epochCount; i++)\n      for(UInt j=i; j<epochCount; j++)\n        Covariance(i,j) = inner(SparseJacobian.row(i).trans(), CovarianceSca.slice(i*3,j*3,3,3) * SparseJacobian.row(j).trans());\n\n    // Derivative\n    // ----------\n    if(sstType == 0)\n      return Covariance;\n\n    Polynomial p(times, degree);\n    fillSymmetric(Covariance);\n    if(sstType == 1) // range rate\n    {\n      Covariance = p.derivative(times, Covariance);\n      Covariance = p.derivative(times, Covariance.trans());\n    }\n    else if(sstType == 2) // range acceleration\n    {\n      Covariance = p.derivative2nd(times, Covariance);\n      Covariance = p.derivative2nd(times, Covariance.trans());\n    }\n    else\n      throw(Exception(\"Unknown sst type\"));\n    Covariance.setType(Matrix::SYMMETRIC);\n    return Covariance;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector GraceKBandGeometry::orientationResidual2rangingCorrection(const_MatrixSliceRef SparseJacobian, const_MatrixSliceRef deltaRpy,\n                                                                 const std::vector<Time> &times, const UInt sstType, const UInt degree)\n{\n  try\n  {\n    // Observation corrections. The Jacobian of the range wrt. the quaternion elements is just the sparse representation\n    // Correction is c = Jacobian * deltaRpy\n    Vector correction(SparseJacobian.rows());\n    for(UInt i=0; i<correction.rows(); i++)\n      correction(i) = inner(SparseJacobian.row(i).trans(), deltaRpy.row(i*3,3));\n\n    // Derivative\n    // ----------\n    if(sstType == 0)\n      return correction;\n    Polynomial p(times, degree);\n    if(sstType == 1) // range rate\n      return p.derivative(times, correction);\n    if(sstType == 2) // range rangeAcceleration\n      return p.derivative2nd(times, correction);\n    throw(Exception(\"Unknown sst type\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/misc/grace/graceKBandGeometry.h",
    "content": "/***********************************************/\n/**\n* @file graceKBandGeometry.h\n*\n* @brief Compute quantities derived from the specific GRACE K-Band ranging instrument observation geometry.\n*\n* @author Matthias Ellmer\n* @date 2017-11-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_GRACEKBANDGEOMETRY__\n#define __GROOPS_GRACEKBANDGEOMETRY__\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n\n/***********************************************/\n\n/** @brief GRACE K Band Geometry\n* Compute quantities derived from the specific GRACE K-Band ranging instrument observation geometry.\n* @ingroup miscGroup */\nnamespace GraceKBandGeometry\n{\n  /** @brief Computes the antenna offset correction.\n  * @param orbit1 Orbit of the first satellite\n  * @param orbit2 Orbit of the second satellite\n  * @param starCamera1 rotation SRF->CRF\n  * @param starCamera2 rotation SRF->CRF\n  * @param center1 APC vector in SRF of first satellite\n  * @param center2 APC vector in SRF of second satellite\n  * @param degree for polynomial differentiation for range rates and range accelerations.\n  * @return SatelliteTrackingArc with AOC in ranges, range rates, and range accelerations */\n  SatelliteTrackingArc antennaCenterCorrection(const OrbitArc &orbit1, const OrbitArc &orbit2,\n                                               const StarCameraArc &starCamera1, const StarCameraArc &starCamera2,\n                                               const Vector3d &center1, const Vector3d &center2, UInt degree);\n\n  /** @brief Computes partials of the Antenna Offset Correction with regard to roll/pitch/yaw of the satellites\n  * @param pos1 Orbit of the first satellite\n  * @param pos2 Orbit of the second satellite\n  * @param rotSat1 rotation SRF->CRF\n  * @param rotSat2 rotation SRF->CRF\n  * @param center1 Taylor point for APC vector in SRF of first satellite\n  * @param center2 Taylor point for APC vector in SRF of second satellite\n  * @param[out] SparseJacobian1 epochCountx3 Matrix with partials of the aoc with regard to r/p/y of the first satellite\n  * @param[out] SparseJacobian2 epochCountx3 Matrix with partials of the aoc with regard to r/p/y of the second satellite\n  * @attention The Jacobians really have size [epochCount x 3 * epochCount]. However, for ranges, which we are computing\n  * here, all partials outside of the current epoch are 0, so we save some memory by only storing the fields that contain data.  */\n  void partialOfAntennaCenterCorrectionWrtRollPitchYaw(const OrbitArc &pos1, const OrbitArc &pos2, const StarCameraArc &rotSat1, const StarCameraArc &rotSat2,\n                                                       const Vector3d &center1, const Vector3d &center2, Matrix &SparseJacobian1, Matrix &SparseJacobian2);\n\n  /** @brief Computes the matrix to project SST residuals into residuals of roll/pitch/yaw angles\n  * @see partialOfAntennaCenterCorrectionWrtRollPitchYaw() for the jacobian.\n  * @param SparseJacobian epochCountx3 Matrix with partials of the aoc with regard to r/p/y of the first satellite\n  * @param CovarianceSca  epochCount*3xepochCountx3 SCA covariance matrix in the SRF\n  * @param times epochs of the arc\n  * @param sstType 0: range, 1: rangeRate, 2: rangeAcceleration\n  * @param degree for polynomial differentiation for range rates and range accelerations.\n  * @note If arguments following dt are not given, ranges are returned.\n  * @returns 3*epochCount x epochCount. To be pre-multiplied with WWe. Returned in range domain.  */\n  Matrix sstResidual2RPYresidualProjector(const_MatrixSliceRef SparseJacobian, const_MatrixSliceRef CovarianceSca,\n                                          const std::vector<Time> &times, const UInt sstType, const UInt degree);\n\n  /** @brief Computes AOC covariance matrix for one satellite\n  * @see partialOfAntennaCenterCorrectionWrtRollPitchYaw() for the jacobian.\n  * @param SparseJacobian epochCountx3 Matrix with partials of the aoc with regard to r/p/y of the first satellite\n  * @param CovarianceSca  epochCount*3xepochCountx3 SCA covariance matrix in the SRF\n  * @param times epochs of the arc\n  * @param sstType 0: range, 1: rangeRate, 2: rangeAcceleration\n  * @param degree for polynomial differentiation for range rates and range accelerations.\n  * @note If arguments after CovarianceSca are not given, ranges are returned.\n  * @returns epochCount x epochCount AOC covariance matrix in the requested domain.  */\n  Matrix variancePropagationStarCamera2SatelliteRanging(const_MatrixSliceRef SparseJacobian, const_MatrixSliceRef CovarianceSca,\n                                                        const std::vector<Time> &times, const UInt sstType, const UInt degree);\n\n  /** @brief Computes TLS observation correction due to orientation residuals\n  * @see partialOfAntennaCenterCorrectionWrtRollPitchYaw() for the jacobian.\n  * @param SparseJacobian epochCountx3 Matrix with partials of the aoc with regard to r/p/y of the first satellite\n  * @param deltaRpy  epochCount*3 vector of updates to orientation\n  * @param times epochs of the arc\n  * @param sstType 0: range, 1: rangeRate, 2: rangeAcceleration\n  * @param degree for polynomial differentiation for range rates and range accelerations.\n  * @note If arguments after deltaRpy are not given, ranges are returned.\n  * @returns epochCount vector with observation corrections in the requested domain. */\n  Vector orientationResidual2rangingCorrection(const_MatrixSliceRef SparseJacobian, const_MatrixSliceRef deltaRpy,\n                                               const std::vector<Time> &times, const UInt sstType, const UInt degree);\n}\n\n/***********************************************/\n\n#endif // __GROOPS_GRACEKBANDGEOMETRY__\n"
  },
  {
    "path": "source/misc/kalmanProcessing.cpp",
    "content": "/***********************************************/\n/**\n* @file kalmanProcessing.cpp\n*\n* @brief Miscellaneous functions for Kalman filter applications\n*\n* @author Andreas Kvas\n* @date 2016-12-26\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_AutoregressiveModelSequence\n\n#include \"kalmanProcessing.h\"\n#include \"config/config.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileMatrix.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(AutoregressiveModelSequence, \"autoregressiveModelSequenceType\")\nGROOPS_READCONFIG_CLASS(AutoregressiveModelSequence, \"autoregressiveModelSequenceType\")\n\n/***********************************************/\n\nvoid AutoregressiveModel::computeNormalEquation()\n{\n  Matrix N_epoch(_model.columns(), Matrix::SYMMETRIC, Matrix::UPPER);\n  rankKUpdate(1.0, _model, N_epoch);\n  fillSymmetric(N_epoch);\n\n  const UInt order = this->order();\n  const UInt dim = this->dimension();\n\n  N.resize(order+1, std::vector<Matrix>(order+1));\n  for(UInt r = 0; r < N.size(); r++)\n    for(UInt c = r; c < N.size(); c++)\n      N.at(r).at(c) = N_epoch.slice(r*dim, c*dim, dim, dim);\n\n  hasNormals = TRUE;\n}\n\n/***********************************************/\n\nvoid AutoregressiveModel::distributedNormalsBlock(UInt epochCount, UInt row, UInt column, Matrix &X)\n{\n  if(row > column)\n    throw(Exception(\"Process normals only implemented for upper triangular matrices!\"));\n\n  if(!hasNormals)\n    this->computeNormalEquation();\n\n  for(UInt l = 0; l<epochCount-this->order(); l++)\n    if( (row>=l) && (column<=this->order()+l) )\n      axpy(1.0, N.at(row-l).at(column-l), X);\n}\n\n/***********************************************/\n\nMatrix AutoregressiveModel::distributedNormalsBlock(UInt epochCount, UInt row, UInt column)\n{\n  if(row > column)\n    throw(Exception(\"Process normals only implemented for upper triangular matrices!\"));\n\n  Matrix X;\n  if(row == column)\n    X = Matrix(this->dimension(), Matrix::SYMMETRIC, Matrix::UPPER);\n  else\n    X = Matrix(this->dimension(), this->dimension());\n\n  this->distributedNormalsBlock(epochCount, row, column, X);\n\n  return X;\n}\n\n/***********************************************/\n\nstd::vector<Matrix> AutoregressiveModel::coefficients() const\n{\n  Matrix W = pseudoInverse(_model.column(order()*dimension(), dimension()));\n\n  std::vector<Matrix> B;\n  for(UInt k = 0; k<order(); k++)\n    B.insert(B.begin(), -1.0*W*_model.column(k*dimension(), dimension())); // B_k = -sqrt(Q)*A_k\n\n  return B;\n}\n\n/***********************************************/\n\nMatrix AutoregressiveModel::whiteNoiseCovariance() const\n{\n  Matrix W = pseudoInverse(_model.column(order()*dimension(), dimension()));\n\n  Matrix Q(dimension(), Matrix::SYMMETRIC);\n  rankKUpdate(1.0, W.trans(), Q); // Q = W W^T\n\n  return Q;\n}\n\n/***********************************************/\n\nvoid AutoregressiveModel::orderOneRepresentation(Matrix &B, Matrix &Q) const\n{\n  std::vector<Matrix> B_tmp = this->coefficients();\n  Matrix Q_tmp = this->whiteNoiseCovariance();\n\n  if(order() == 1)\n  {\n    B = B_tmp.front();\n    Q = Q_tmp;\n  }\n  else\n  {\n    B = Matrix(order()*dimension(), order()*dimension());\n    for(UInt k = 0; k<order(); k++)\n      copy(B_tmp.at(k), B.slice(0, k*dimension(), dimension(), dimension()));\n\n    for(UInt i = 0; i<dimension()*(order()-1); i++)\n      B(i+dimension(), i) = 1.0;\n\n    Q = Matrix(order()*dimension(), Matrix::SYMMETRIC);\n    copy(Q_tmp, Q.slice(0,0, dimension(), dimension()));\n  }\n}\n\n/***********************************************/\n\nstd::vector< std::pair<UInt, UInt> > AutoregressiveModel::distributedNormalsBlockIndex(UInt blockCount) const\n{\n  std::vector< std::pair<UInt, UInt> > index;\n  for(UInt row = 0; row<blockCount; row++)\n  {\n    for(UInt column = row; column<std::min(row+this->order()+1, blockCount); column++)\n      index.push_back( std::pair<UInt, UInt>(row, column));\n  }\n\n  return index;\n}\n\n/***********************************************/\n\nvoid AutoregressiveModel::updatePredictionErrorCovariance(const Matrix& Q_new)\n{\n  if(Q_new.rows() != this->dimension())\n    throw(Exception(\"Size of new prediction error covariance does not match.\"));\n\n  Matrix W = pseudoInverse(_model.column(order()*dimension(), dimension()));\n  Matrix W_new = matrixSquareRootInverse(Q_new);\n\n  _model = (W_new*W)*_model;\n}\n\n/***********************************************/\n\nVector AutoregressiveModel::decorrelate(const Vector& x) const\n{\n  if( (x.rows() % dimension()) != 0 )\n    throw(Exception(\"Size of solution vector does not match model dimension.\"));\n\n  const UInt epochCount = x.rows()/dimension();\n\n  Matrix X((order()+1)*dimension(), epochCount-order());\n  for(UInt k = 0; k<epochCount-order(); k++)\n    copy(x.row(k*dimension(), X.rows()), X.column(k));\n\n  Matrix U(dimension(), epochCount-order());\n  matMult(-1.0, _model, X, U);\n\n  return flatten(U);\n}\n\n/***********************************************/\n\nvoid AutoregressiveModel::rotate(const_MatrixSliceRef F)\n{\n  if(F.rows() != dimension())\n    throw(Exception(\"Dimensions of rotation matrix and model do not match (<\" + F.rows()%\"%i\"s + \"> vs. <\"+dimension()%\"%i\"s+\">).\"));\n\n  Matrix G = pseudoInverse(_model.column(order()*dimension(), dimension())*F); // G = F^+ * W^0.5\n\n  Matrix Q(F.columns(), Matrix::SYMMETRIC);\n  rankKUpdate(1.0, G.trans(), Q);\n  Matrix V = matrixSquareRootInverse(Q);\n\n  G = V*G; // apply decorrelation to G, G := Q^-0.5 * F^+ * W^0.5\n\n  Matrix B(F.columns(), F.columns()*(order()+1)); // new model\n\n  for(UInt k = 0; k<order(); k++)\n    copy(G*_model.column(k*dimension(), dimension())*F, B.column(k*F.columns(), F.columns()));\n  copy(V, B.column(order()*F.columns(), F.columns()));\n\n  _model = B;\n}\n\n/***********************************************/\n/***********************************************/\n\nAutoregressiveModelSequencePtr AutoregressiveModelSequence::create(Config &config, const std::string &name)\n{\n  try\n  {\n    AutoregressiveModelSequencePtr arSequence;\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    arSequence = AutoregressiveModelSequencePtr(new AutoregressiveModelSequence(config));\n    endSequence(config);\n    return arSequence;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nAutoregressiveModelSequence::AutoregressiveModelSequence(Config &config)\n{\n  std::vector<FileName> fileNameArModel;\n  Double sigma0 = 1.0;\n\n  readConfig(config, \"inputfileAutoregressiveModel\", fileNameArModel, Config::MUSTSET,  \"\",    \"matrix file containing an AR model\");\n  readConfig(config, \"sigma0\",                       sigma0,          Config::DEFAULT,  \"1.0\", \"a-priori sigma for white noise covariance\");\n  if(isCreateSchema(config)) return;\n\n  std::set<UInt> dimensions;\n  for(auto &fileName : fileNameArModel)\n  {\n    Matrix tmp;\n    readFileMatrix(fileName, tmp);\n    tmp*=(1.0/sigma0);\n    _arModels.push_back(AutoregressiveModel(tmp));\n\n    dimensions.insert(_arModels.back().dimension());\n  }\n\n  if(dimensions.size() != 1)\n    throw(Exception(\"Autoregressive models must have same dimension.\"));\n\n  for(UInt order = 0; order<_arModels.size(); order++)\n    if(order != _arModels.at(order).order())\n      throw(Exception(\"Autoregressive models must be given in increasing and consecutive order.\"));\n}\n\n/***********************************************/\n\nvoid AutoregressiveModelSequence::distributedNormalsBlock(UInt epochCount, UInt row, UInt column, Matrix &X)\n{\n  _arModels.back().distributedNormalsBlock(epochCount, row, column, X);  // last model constrains all parameters\n\n  for(UInt order = 0; order<maximumOrder(); order++) // other models constrain the first maxOrder-1 blocks\n    if(row<=order && column<=order)\n      axpy(1.0, _arModels.at(order).normalEquation().at(row).at(column), X);\n}\n\n/***********************************************/\n\nMatrix AutoregressiveModelSequence::distributedNormalsBlock(UInt epochCount, UInt row, UInt column)\n{\n  if(row > column)\n    throw(Exception(\"Process normals only implemented for upper triangular matrices!\"));\n\n  Matrix X;\n  if(row == column)\n    X = Matrix(this->dimension(), Matrix::SYMMETRIC, Matrix::UPPER);\n  else\n    X = Matrix(this->dimension(), this->dimension());\n\n  this->distributedNormalsBlock(epochCount, row, column, X);\n\n  return X;\n}\n\n\n/***********************************************/\n\nstd::vector< std::vector< std::vector<Matrix> > > AutoregressiveModelSequence::normalEquationSequence()\n{\n  std::vector< std::vector< std::vector<Matrix> > > N;\n  for(AutoregressiveModel &model : _arModels)\n    N.push_back(model.normalEquation());\n\n  return N;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/kalmanProcessing.h",
    "content": "/***********************************************/\n/**\n* @file kalmanProcessing.h\n*\n* @brief Miscellaneous functions for Kalman filter applications\n*\n* @author Andreas Kvas\n* @date 2016-12-26\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_KALMANPROCESSING__\n#define __GROOPS_KALMANPROCESSING__\n\n// Latex documentation\n#ifdef DOCSTRING_AutoregressiveModelSequence\nstatic const char *docstringAutoregressiveModelSequence = R\"(\n\\section{AutoregressiveModelSequence}\\label{autoregressiveModelSequenceType}\nRepresents a sequence of multivariate autoregressive (AR) models with increasing order $p$.\nThe AR models should be stored as \\file{matrix file}{matrix} in the \\reference{GROOPS definition of\nAR models}{fundamentals.autoregressiveModel}.\nThe required AR models can be computed with \\program{CovarianceMatrix2AutoregressiveModel},\nand passed to this class through\n\\config{inputfileAutoregressiveModel} in increasing order.\n\nThe main purpose of AutoregressiveModelSequence is to use AR models of the form\n\\begin{equation}\n  \\label{eq:ar-model}\n  \\mathbf{y}_e(t_i) = \\sum_{k=1}^p \\mathbf{\\Phi}^{(p)}_k\\mathbf{y}_e(t_{i-k}) + \\mathbf{w}(t_i),\n  \\hspace{5pt} \\mathbf{w}(t_i) \\sim \\mathcal{N}(0, \\mathbf{\\Sigma}^{(p)}_\\mathbf{w}),\n\\end{equation}\nto create pseudo-observation equations\n\\begin{equation}\n  \\label{eq:pseudo-observations-transformed}\n  0 = \\bar{\\mathbf{\\Phi}} \\Delta\\mathbf{y} + \\bar{\\mathbf{w}}, \\hspace{5pt} \\bar{\\mathbf{w}} \\sim\n  \\mathcal{N}(0, \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}}),\n\\end{equation}\nwith\n\\begin{equation}\n  \\label{eq:pseudo-observations-ar}\n  \\bar{\\mathbf{\\Phi}} =\n  \\begin{bmatrix}\n    \\mathbf{I} & & & & & \\\\\n    -\\mathbf{\\Phi}^{(1)}_1 & \\mathbf{I} & & & &  \\\\\n    -\\mathbf{\\Phi}^{(2)}_2 & -\\mathbf{\\Phi}^{(2)}_1 & \\mathbf{I} & & & \\\\\n    -\\mathbf{\\Phi}^{(3)}_3 & -\\mathbf{\\Phi}^ {(3)}_2 & -\\mathbf{\\Phi}^ {(3)}_1 & \\mathbf{I} & &  \\\\\n    & -\\mathbf{\\Phi}^{(3)}_3 & -\\mathbf{\\Phi}^ {(3)}_2 & -\\mathbf{\\Phi}^ {(3)}_1 & \\mathbf{I} &  \\\\\n    & & \\ddots & \\ddots & \\ddots & \\ddots  \\\\\n  \\end{bmatrix},\n  \\hspace{15pt}\n  \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}} =\n  \\bar{\\mathbf{\\Sigma}}_{\\bar{\\mathbf{w}}} =\n  \\begin{bmatrix}\n    \\mathbf{\\Sigma}^{(0)}_{\\mathbf{w}} & & & & & \\\\\n    & \\mathbf{\\Sigma}^{(1)}_{\\mathbf{w}} & & & & \\\\\n    & & \\mathbf{\\Sigma}^{(2)}_{\\mathbf{w}} & & & \\\\\n    & & & \\mathbf{\\Sigma}^{(3)}_{\\mathbf{w}} & & \\\\\n    & & & & \\mathbf{\\Sigma}^{(3)}_{\\mathbf{w}} &  \\\\\n    & & & & & \\ddots \\\\\n  \\end{bmatrix}.\n\\end{equation}\nused to constrain high-frequency temporal gravity field variations (see\n\\program{KalmanSmootherLeastSquares}, \\program{NormalsBuildShortTimeStaticLongTime},\n\\program{PreprocessingSst}).\n\nThe corresponding normal equation coefficient matrix is given by\n\\begin{equation}\n  \\label{eq:ar-normals}\n  \\bar{\\mathbf{\\Phi}}^T\\bar{\\mathbf{\\Sigma}}^{-1}_{\\bar{\\mathbf{w}}}\\bar{\\mathbf{\\Phi}}\n\\end{equation}\nand if all AR models are estimated from the same sample its inverse is a block-Toeplitz covariance matrix\n\\begin{equation}\n  (\\mathbf{\\Sigma}_{\\mathbf{y}_m})_{ij} =\n  \\begin{cases}\n \\mathbf{\\Sigma}(|j-i|) & \\text{for } i \\leq j \\\\\n \\mathbf{\\Sigma}(|j-i|))^T & \\text{otherwise}\n \\end{cases},\n\\end{equation}\nwhich can be computed using \\program{AutoregressiveModel2CovarianceMatrix}.\n\nA detailed description with applications can be found in:\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). \\url{https://doi.org/10.1007/s00190-019-01314-1}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/matrix.h\"\n#include \"config/config.h\"\n\n/***** CLASS ***********************************/\n\nclass AutoregressiveModel\n{\nprivate:\n  std::vector< std::vector<Matrix> > N; // normalEquations\n  Bool hasNormals;\n  Matrix _model;\n\n  /** @brief Normal equations from a multivariate AR Model\n  * The AR model of order p \\f$ x_t = B.at(0) x_{t-1} + B.at(1) x_{t-2} + ...\n  * + B.at(p-1) + w \\f$ with \\f$ w \\sim Q \\f$ represents a constraint in\n  * time domain. The corresponding observation equation reads:\n  * \\f$ 0 = [ B.at(p-1) B.at(p-2) ... B.at(0) -I] + w \\f$ with \\f$ w \\sim Q\\f$.\n  * This function computes the upper triangle of the resulting normal equation. */\n  void computeNormalEquation();\n\npublic:\n  /** @brief Constructor. */\n  AutoregressiveModel(const_MatrixSliceRef B) : hasNormals(FALSE), _model(B) {}\n\n  /** @brief Return the normal equations for a single epoch as block matrix. */\n  std::vector< std::vector<Matrix> > normalEquation() { if(!hasNormals) this->computeNormalEquation(); return N; }\n\n  /** @brief Return the normal equation block (row, column) in a matrix with blockCount blocks. */\n  Matrix distributedNormalsBlock(UInt blockCount, UInt row, UInt column);\n\n  /** @brief Return the normal equation block (row, column) in a matrix with blockCount blocks. */\n  void distributedNormalsBlock(UInt blockCount, UInt row, UInt column, Matrix &N);\n\n  /** @brief Dimension (number of parameters) of the model. */\n  UInt dimension() const { return _model.rows(); }\n\n  /** @brief Model order (number of coefficients). */\n  UInt order() const { return _model.columns()/_model.rows()-1; }\n\n  /** @brief Return pseudo observation equation of the AR(p) model */\n  Matrix pseudoObservationEquation() const { return _model; }\n\n  /** @brief Assign a new prediction error covariance to the AR model. */\n  void updatePredictionErrorCovariance(const Matrix &Q);\n\n  /** @brief Compute the process residuals (e.g. Bx_t - x_t+1) from a solution vector. */\n  Vector decorrelate(const Vector& x) const;\n\n  /** @brief Return AR coefficients as std::vector */\n  std::vector<Matrix> coefficients() const;\n\n  /** @brief Return autocovariance of process noise as Matrix */\n  Matrix whiteNoiseCovariance() const;\n\n  /** @brief Return the AR(1) representatation of the AR model */\n  void orderOneRepresentation(Matrix &B, Matrix &Q) const;\n\n  /** @brief list of row, column pairs for each distributed normals block that will be filled. */\n  std::vector<std::pair<UInt, UInt>> distributedNormalsBlockIndex(UInt epochCount) const;\n\n  /** @brief Change the state representation of the AR model. */\n  void rotate(const_MatrixSliceRef F);\n};\n\n/***** CLASS ***********************************/\n\nclass AutoregressiveModelSequence;\ntypedef std::shared_ptr<AutoregressiveModelSequence> AutoregressiveModelSequencePtr;\n\nclass AutoregressiveModelSequence\n{\nprivate:\n  std::vector<AutoregressiveModel> _arModels;\n\npublic:\n  AutoregressiveModelSequence(Config &config);\n\n  /** @brief Maxmimum order of the AR models in the sequence. */\n  UInt maximumOrder() const { return _arModels.back().order(); }\n\n  /** @brief Dimension (number of parameters) of the model. */\n  UInt dimension() const { return _arModels.front().dimension(); }\n\n  /** @brief Return the normal equation block (row, column) in a matrix with blockCount blocks. */\n  Matrix distributedNormalsBlock(UInt blockCount, UInt row, UInt column);\n\n  /** @brief Return the normal equation block (row, column) in a matrix with blockCount blocks. */\n  void distributedNormalsBlock(UInt blockCount, UInt row, UInt column, Matrix &N);\n\n  /** @brief list of row, column pairs for each distributed normals block that will be filled. */\n  std::vector<std::pair<UInt, UInt>> distributedNormalsBlockIndex(UInt epochCount) const { return _arModels.back().distributedNormalsBlockIndex(epochCount); }\n\n  /** @brief Return blocked normal equations for each AR model as vector */\n  std::vector< std::vector< std::vector<Matrix> > > normalEquationSequence();\n\n  /** @brief creates an derived instance of this class. */\n  static AutoregressiveModelSequencePtr create(Config &config, const std::string &name);\n};\n\n/** @brief Creates an instance of the class AutoregressiveModelSequence. */\ntemplate<> Bool readConfig(Config &config, const std::string &name, AutoregressiveModelSequence &arModelSequence, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***********************************************/\n\n#endif /* __GROOPS_KALMANPROCESSING__ */\n"
  },
  {
    "path": "source/misc/miscGriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file miscGriddedData.cpp\n*\n* @brief Misc functions for values on grid.\n*\n* @author Torsten Mayer-Guerr\n* @author Christian Pock\n* @date 2008-08-06\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"miscGriddedData.h\"\n\n/***********************************************/\n\nnamespace MiscGriddedData\n{\n\n/***********************************************/\n\nvoid statistics(const std::vector<Double> &values, const std::vector<Double> &weights,\n                Double &rms, Double &avg, Double &vmin, Double &vmax, Double &mean)\n{\n  try\n  {\n    mean = 0.;\n    avg  = 0.;\n    rms  = 0.;\n    vmin = NAN_EXPR;\n    vmax = NAN_EXPR;\n    if(!values.size())\n      return;\n\n    const Double sumWeight = std::accumulate(weights.begin(), weights.end(), Double(0.));\n    for(UInt i=0; i<values.size(); i++)\n    {\n      const Double w = (sumWeight) ? (weights.at(i)/sumWeight) : (1./values.size());\n      const Double v = values.at(i);\n      mean += w * v;\n      avg  += w * std::fabs(v);\n      rms  += w * v*v;\n    }\n    rms  = std::sqrt(rms);\n    vmin = *std::min_element(values.begin(), values.end());\n    vmax = *std::max_element(values.begin(), values.end());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic void statistics(const std::vector<std::vector<Double>> &values, const std::vector<Double> &weights,\n                       Vector &rms, Vector &avg, Vector &vmin, Vector &vmax, Vector &mean)\n{\n  try\n  {\n    rms = avg = vmin = vmax = mean = Vector(values.size());\n    for(UInt i=0; i<values.size(); i++)\n      statistics(values.at(i), weights, rms(i), avg(i), vmin(i), vmax(i), mean(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic void printStatistics(const Vector &rms, const Vector &avg, const Vector &vmin, const Vector &vmax, const Vector &mean)\n{\n  try\n  {\n    if(rms.rows() == 0)\n      return;\n\n    const UInt width = 13;\n    auto line = [&](const std::string &str, const Vector &x)\n    {\n      std::stringstream ss;\n      for(UInt i=0; i<rms.rows(); i++)\n        ss<<std::setw(width)<<std::left<<x(i);\n      logInfo<<\"  \"<<str<<ss.str()<<Log::endl;\n    };\n\n    logInfo<<\"data statistics\"<<Log::endl;\n    if(rms.rows()>1)\n    {\n      std::stringstream ss;\n      for(UInt i=0; i<rms.rows(); i++)\n        ss<<\"data\"<<std::setw(width-4)<<std::left<<(i);\n      logInfo<<\"        \"<<ss.str()<<Log::endl;\n    }\n\n    line(\"rms:  \", rms);\n    line(\"avg:  \", avg);\n    line(\"min:  \", vmin);\n    line(\"max:  \", vmax);\n    line(\"mean: \", mean);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid printStatistics(const GriddedData &grid)\n{\n  try\n  {\n    const Double totalArea = std::accumulate(grid.areas.begin(), grid.areas.end(), Double(0.));\n\n    logInfo<<\"grid statistics\"<<Log::endl;\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius;\n    if(grid.isRectangle(lambda, phi, radius))\n    {\n      Angle  lon1, lon2, lat1, lat2;\n      Double h1, h2;\n      grid.ellipsoid(grid.points.front(), lon1, lat1, h1);\n      grid.ellipsoid(grid.points.back(),  lon2, lat2, h2);\n      logInfo<<\"  regular grid (\"<<phi.size()<<\" x \"<<lambda.size()<<\") = \"<<grid.points.size()<<Log::endl;\n      logInfo<<\"  longitude: \"<<lon1*RAD2DEG<<\"° -- \"<<lon2*RAD2DEG<<\"°\"<<Log::endl;\n      logInfo<<\"  latitude:  \"<<lat1*RAD2DEG<<\"° -- \"<<lat2*RAD2DEG<<\"°\"<<Log::endl;\n      logInfo<<\"  area:      \"<<totalArea/(4*PI)*100<<\"% of Earth's surface (\"<<totalArea*std::pow(DEFAULT_R/1000,2)<<\" km^2)\"<<Log::endl;\n    }\n    else\n    {\n      logInfo<<\"  count: \"<<grid.points.size()<<Log::endl;\n      logInfo<<\"  area:  \"<<totalArea/(4*PI)*100<<\"% of Earth's surface (\"<<totalArea*pow(DEFAULT_R/1000,2)<<\" km^2)\"<<Log::endl;\n    }\n\n    if(grid.values.size() && grid.points.size())\n    {\n      Vector rms, avg, vmin, vmax, mean;\n      statistics(grid.values, grid.areas, rms, avg, vmin, vmax, mean);\n      printStatistics(rms, avg, vmin, vmax, mean);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid printStatistics(const GriddedDataRectangular &grid)\n{\n  try\n  {\n    if(!grid.isValid())\n    {\n      logInfo<<\"grid is not valid\"<<Log::endl;\n      return;\n    }\n\n    std::vector<Double> dLambda, dPhi;\n    const Double totalArea = grid.areaElements(dLambda, dPhi);\n    const UInt   rows      = grid.latitudes.size();\n    const UInt   cols      = grid.longitudes.size();\n\n    logInfo<<\"grid statistics\"<<Log::endl;\n    logInfo<<\"  regular grid (\"<<rows<<\" x \"<<cols<<\") = \"<<rows*cols<<Log::endl;\n    logInfo<<\"  longitude: \"<<grid.longitudes.at(0)*RAD2DEG<<\"° -- \"<<grid.longitudes.back()*RAD2DEG<<\"°\"<<Log::endl;\n    logInfo<<\"  latitude:  \"<<grid.latitudes.at(0) *RAD2DEG<<\"° -- \"<<grid.latitudes.back() *RAD2DEG<<\"°\"<<Log::endl;\n    logInfo<<\"  area:      \"<<totalArea/(4*PI)*100<<\"% of Earth's surface (\"<<totalArea*std::pow(DEFAULT_R/1000,2)<<\" km^2)\"<<Log::endl;\n\n    if(!grid.values.size())\n      return;\n\n    Vector mean(grid.values.size());\n    Vector vmin(grid.values.size()), vmax(grid.values.size());\n    Vector avg(grid.values.size()),  rms(grid.values.size());\n    for(UInt idx=0; idx<grid.values.size(); idx++)\n    {\n      for(UInt i=0; i<rows; i++)\n        for(UInt k=0; k<cols; k++)\n        {\n          const Double w = dLambda[k]*dPhi[i]/totalArea;\n          const Double v = grid.values[idx](i,k);\n          mean(idx) += w * v;\n          avg(idx)  += w * std::fabs(v);\n          rms(idx)  += w * v * v;\n        }\n      vmin(idx) = min(grid.values[idx]);\n      vmax(idx) = max(grid.values[idx]);\n      rms(idx)  = std::sqrt(rms(idx));\n    }\n\n    printStatistics(rms, avg, vmin, vmax, mean);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<Double> synthesisSphericalHarmonics(const SphericalHarmonics &harm, const std::vector<Vector3d> &points, KernelPtr kernel, Parallel::CommunicatorPtr comm, Bool timing)\n{\n  try\n  {\n    std::vector<Double>   field(points.size(), 0.);\n    std::vector<Angle>    lambda, phi;\n    std::vector<Double>   r;\n\n    // spherical harmonics with recatangular grid\n    if(GriddedData(Ellipsoid(), points, std::vector<Double>(), std::vector<std::vector<Double>>()).isRectangle(lambda, phi, r))\n    {\n      Matrix cossinm(lambda.size(), 2*harm.maxDegree()+1);\n      for(UInt i=0; i<lambda.size(); i++)\n      {\n        cossinm(i,0) = 1.;\n        for(UInt m=1; m<=harm.maxDegree(); m++)\n        {\n          cossinm(i,2*m-1) = cos(m*static_cast<Double>(lambda.at(i)));\n          cossinm(i,2*m+0) = sin(m*static_cast<Double>(lambda.at(i)));\n        }\n      }\n\n      // Compute Legendre functions for each phi (row)\n      Parallel::forEach(phi.size(), [&](UInt i)\n      {\n        const Vector3d p  = polar(lambda.at(0), phi.at(i), r.at(i));\n        const Vector   kn = kernel->inverseCoefficients(p, harm.maxDegree(), harm.isInterior());\n\n        Matrix Pnm = SphericalHarmonics::Pnm(Angle(PI/2-phi.at(i)), r.at(i)/harm.R(), harm.maxDegree(), harm.isInterior());\n        for(UInt n=0; n<=harm.maxDegree(); n++)\n          Pnm.slice(n,0,1,n+1) *= harm.GM()/harm.R()*kn(n);\n\n        Vector sum(2*harm.maxDegree()+1);\n        sum(0) = inner(harm.cnm().column(0), Pnm.column(0));\n        for(UInt m=1; m<=harm.maxDegree(); m++)\n        {\n          sum(2*m-1) = inner(harm.cnm().slice(m,m,harm.maxDegree()-m+1,1), Pnm.slice(m,m,harm.maxDegree()-m+1,1));\n          sum(2*m+0) = inner(harm.snm().slice(m,m,harm.maxDegree()-m+1,1), Pnm.slice(m,m,harm.maxDegree()-m+1,1));\n        }\n        Vector row = cossinm * sum;\n        for(UInt k=0; k<lambda.size(); k++)\n          field.at(i*lambda.size()+k) = row(k);\n      }, comm, timing);\n      Parallel::reduceSum(field, 0, comm);\n      return field;\n    } // if(isRectangle)\n\n    // spherical harmonics with arbitrary point distribution\n    Parallel::forEach(field, [&](UInt i)\n                      {return inner(kernel->inverseCoefficients(points.at(i), harm.maxDegree(), harm.isInterior()),\n                                    harm.Yn(points.at(i), harm.maxDegree()));}, comm, timing);\n    return field;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix synthesisSphericalHarmonicsMatrix(UInt maxDegree, Double GM, Double R, const std::vector<Vector3d> &points, KernelPtr kernel, Bool isInterior)\n{\n  try\n  {\n    Matrix A = Matrix(points.size(), (maxDegree+1)*(maxDegree+1));\n    for(UInt k=0; k<points.size(); k++)\n    {\n      Matrix Cnm, Snm;\n      SphericalHarmonics::CnmSnm(1./R * points.at(k), maxDegree, Cnm, Snm, isInterior);\n      Vector kn = kernel->inverseCoefficients(points.at(k), maxDegree, isInterior);\n      UInt idx = 0;\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        A(k,idx++) =  kn(n) * GM/R * Cnm(n,0);\n        for(UInt m=1; m<=n; m++)\n        {\n          A(k,idx++) = kn(n) * GM/R * Cnm(n,m);\n          A(k,idx++) = kn(n) * GM/R * Snm(n,m);\n        }\n      }\n    }\n\n    return A;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<SphericalHarmonics> analysisSphericalHarmonics(const GriddedData &grid, KernelPtr kernel, UInt minDegree, UInt maxDegree, Double GM, Double R,\n                                                           Bool useLeastSquares, Parallel::CommunicatorPtr comm, Bool timing)\n{\n  try\n  {\n    // test rectangular grid\n    // ---------------------\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius;\n    const Bool isRectangle = grid.isRectangle(lambda, phi, radius);\n    // precompute cos(m*lambda), sin(m*lambda)\n    Matrix cosml, sinml;\n    if(isRectangle)\n    {\n      cosml = sinml = Matrix(lambda.size(), maxDegree+1);\n      for(UInt m=0; m<=maxDegree; m++)\n        for(UInt k=0; k<lambda.size(); k++)\n        {\n          cosml(k, m) = std::cos(m*static_cast<Double>(lambda.at(k)));\n          sinml(k, m) = std::sin(m*static_cast<Double>(lambda.at(k)));\n        }\n    }\n\n    // quadrature formular\n    // -------------------\n    if(!useLeastSquares)\n    {\n      if(timing) logStatus<<\"computing quadrature formular\"<<Log::endl;\n      std::vector<Matrix> cnm(grid.values.size(), Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n      std::vector<Matrix> snm(grid.values.size(), Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n\n      if(isRectangle)\n      {\n        Parallel::forEach(phi.size(), [&](UInt i)\n        {\n          // legendre functions with kernel coefficients\n          Matrix Pnm = SphericalHarmonics::Pnm(Angle(0.5*PI-phi.at(i)), radius.at(i)/R, maxDegree, TRUE);\n          Vector kn  = kernel->coefficients(polar(Angle(0.), phi.at(i), radius.at(i)), maxDegree);\n          for(UInt n=0; n<=maxDegree; n++)\n            Pnm.slice(n, 0, 1, n+1) *= kn(n) * radius.at(i)/(4*PI*GM);\n\n          for(UInt idx=0; idx<grid.values.size(); idx++)\n            for(UInt k=0; k<lambda.size(); k++)\n            {\n              const Double f = grid.values.at(idx).at(i*lambda.size()+k) * grid.areas.at(i*lambda.size()+k);\n              for(UInt m=0; m<=maxDegree; m++)\n              {\n                axpy(f * cosml(k, m), Pnm.column(m), cnm.at(idx).column(m));\n                axpy(f * sinml(k, m), Pnm.column(m), snm.at(idx).column(m));\n              }\n            }\n        }, comm, timing);\n      }\n      else\n      {\n        Parallel::forEach(grid.points.size(), [&](UInt i)\n        {\n          const Vector kn = kernel->coefficients(grid.points.at(i), maxDegree);\n          const Double f = grid.points.at(i).r()/(4*PI*GM) * grid.areas.at(i);\n          Matrix Cnm, Snm;\n          SphericalHarmonics::CnmSnm((1./R) * grid.points.at(i), maxDegree, Cnm, Snm, TRUE);\n          for(UInt idx=0; idx<grid.values.size(); idx++)\n            for(UInt n=minDegree; n<=maxDegree; n++)\n            {\n              axpy(f*kn(n)*grid.values.at(idx).at(i), Cnm.row(n), cnm.at(idx).row(n));\n              axpy(f*kn(n)*grid.values.at(idx).at(i), Snm.row(n), snm.at(idx).row(n));\n            }\n        }, comm, timing);\n      }\n\n      std::vector<SphericalHarmonics> harm(grid.values.size());\n      for(UInt idx=0; idx<grid.values.size(); idx++)\n      {\n        Parallel::reduceSum(cnm.at(idx), 0, comm);\n        Parallel::reduceSum(snm.at(idx), 0, comm);\n        harm.at(idx) = SphericalHarmonics(GM, R, cnm.at(idx), snm.at(idx)).get(maxDegree, minDegree);\n      }\n\n      return harm;\n    }\n\n    // least squares adjustment order by order\n    // ---------------------------------------\n    if(timing) logStatus<<\"least squares adjustment (order by order)\"<<Log::endl;\n    if(!isRectangle)\n      throw(Exception(\"GriddedData must be a rectangle grid\"));\n    // check assumption: same area for all longitudes\n    Bool failed = FALSE;\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=1; k<lambda.size(); k++)\n        if(!failed && (std::fabs(grid.areas.at(i*lambda.size()+k-1)-grid.areas.at(i*lambda.size()+k)) > 1e-3*std::fabs(grid.areas.at(i*lambda.size()+k))))\n        {\n          logWarningOnce<<\"assumption of the same area/weight for all longitudes not fulfilled\"<<Log::endl;\n          failed = TRUE;\n        }\n\n    // system of normal equations (order by order)\n    std::vector<Matrix> N, n;\n    N.push_back(Matrix(maxDegree+1, Matrix::SYMMETRIC));\n    n.push_back(Matrix(maxDegree+1, grid.values.size()));\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      N.push_back(Matrix(2*(maxDegree+1-m), Matrix::SYMMETRIC));\n      n.push_back(Matrix(2*(maxDegree+1-m), grid.values.size()));\n    }\n\n    Vector lPl(grid.values.size());\n    for(UInt idx=0; idx<grid.values.size(); idx++)\n      for(UInt i=0; i<grid.points.size(); i++)\n        lPl(idx) += grid.values.at(idx).at(i) * grid.areas.at(i)/(4*PI) * grid.values.at(idx).at(i);\n\n    if(timing) logStatus<<\"accumulate normal equations\"<<Log::endl;\n    Parallel::forEach(phi.size(), [&](UInt i)\n    {\n      Matrix l(lambda.size(), grid.values.size());\n      for(UInt idx=0; idx<grid.values.size(); idx++)\n        for(UInt k=0; k<lambda.size(); k++)\n          l(k, idx) = grid.values.at(idx).at(i*lambda.size()+k);\n\n      // legendre functions with kernel coefficients\n      Matrix Pnm = SphericalHarmonics::Pnm(Angle(0.5*PI-phi.at(i)), radius.at(i)/R, maxDegree);\n      Vector kn  = kernel->inverseCoefficients(polar(Angle(0.), phi.at(i), radius.at(i)), maxDegree);\n      for(UInt n=0; n<=maxDegree; n++)\n        Pnm.slice(n, 0, 1, n+1) *= GM/R * kn(n);\n\n      const Double weight = grid.areas.at(i*lambda.size())/(4*PI); // assume same area for all longitudes\n      Matrix A = cosml.column(0) * Pnm.column(0).trans();\n      rankKUpdate(weight, A, N.at(0));\n      matMult(weight, A.trans(), l, n.at(0));\n      for(UInt m=1; m<=maxDegree; m++)\n      {\n        Matrix A(lambda.size(), 2*(maxDegree+1-m));\n        matMult(1.0, cosml.column(m), Pnm.slice(m, m, maxDegree+1-m, 1).trans(), A.column(0, maxDegree+1-m));\n        matMult(1.0, sinml.column(m), Pnm.slice(m, m, maxDegree+1-m, 1).trans(), A.column(maxDegree+1-m, maxDegree+1-m));\n        rankKUpdate(weight, A, N.at(m));\n        matMult(weight, A.trans(), l, n.at(m));\n      }\n    }, comm, timing);\n\n    for(UInt m=0; m<=maxDegree; m++)\n    {\n      Parallel::reduceSum(N.at(m), 0, comm);\n      Parallel::reduceSum(n.at(m), 0, comm);\n    }\n\n    // solve normals\n    // -------------\n    std::vector<SphericalHarmonics> harm(grid.values.size());\n    if(Parallel::isMaster(comm))\n    {\n      if(timing) logStatus<<\"solve the system of equations\"<<Log::endl;\n      std::vector<Matrix> x(maxDegree+1);\n      std::vector<Vector> sigma2x(maxDegree+1);\n      UInt parameterCount = 0;\n      for(UInt m=0; m<=maxDegree; m++)\n      {\n        parameterCount += n.at(m).rows();\n        for(UInt k=0; k<N.at(m).rows(); k++)\n          if(N.at(m)(k, k) == 0.)\n          {\n            N.at(m)(k, k) = 1;\n            parameterCount--;\n            // logWarning<<k<<\". parameter has zero diagonal element -> set to one\"<<Log::endl;\n          }\n        x.at(m) = solve(N.at(m), n.at(m));\n        inverse(N.at(m));               // inverse of the cholesky matrix\n        sigma2x.at(m) = Vector(x.at(m).rows());\n        for(UInt k=0; k<N.at(m).rows(); k++)\n          sigma2x.at(m)(k) = quadsum(N.at(m).slice(k, k, 1, N.at(m).columns()-k));\n      }\n\n      // aposteriori sigma\n      Vector sigma2(grid.values.size());\n      for(UInt idx=0; idx<grid.values.size(); idx++)\n      {\n        Double ePe = lPl(idx);\n        for(UInt m=0; m<=maxDegree; m++)\n          ePe -= inner(x.at(m).column(idx), n.at(m).column(idx));\n        sigma2(idx) = std::max(ePe/(grid.points.size()-parameterCount), 0.);\n      }\n\n      // potential coefficients\n      Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      for(UInt idx=0; idx<grid.values.size(); idx++)\n      {\n        copy(x.at(0).column(idx), cnm.column(0));\n        copy(sigma2x.at(0), sigma2cnm.column(0));\n        for(UInt m=1; m<=maxDegree; m++)\n        {\n          copy(x.at(m).slice(0,             idx, maxDegree+1-m, 1),    cnm.slice(m, m, maxDegree+1-m, 1));\n          copy(x.at(m).slice(maxDegree+1-m, idx, maxDegree+1-m, 1),    snm.slice(m, m, maxDegree+1-m, 1));\n          copy(sigma2x.at(m).row(0,              maxDegree+1-m), sigma2cnm.slice(m, m, maxDegree+1-m, 1));\n          copy(sigma2x.at(m).row(maxDegree+1-m,  maxDegree+1-m), sigma2snm.slice(m, m, maxDegree+1-m, 1));\n        }\n        harm.at(idx) = SphericalHarmonics(GM, R, cnm, snm, sigma2(idx)*sigma2cnm, sigma2(idx)*sigma2snm).get(maxDegree, minDegree);\n      }\n    } // if(Parallel::isMaster(comm))\n\n    return harm;\n }\n catch(std::exception &e)\n {\n   GROOPS_RETHROW(e)\n }\n}\n\n/***********************************************/\n\n} // end namespace GriddedData\n"
  },
  {
    "path": "source/misc/miscGriddedData.h",
    "content": "/***********************************************/\n/**\n* @file miscGriddedData.h\n*\n* @brief Misc functions for values on grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-06\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MISCGRIDDEDDATA__\n#define __GROOPS_MISCGRIDDEDDATA__\n\n#include \"base/vector3d.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/griddedData.h\"\n#include \"parallel/parallel.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***********************************************/\n\n/** @brief Functions for values on grid.\n* @ingroup miscGroup */\nnamespace MiscGriddedData\n{\n  /** @brief Compute some statistics (rms, mean, max...). */\n  void statistics(const std::vector<Double> &values, const std::vector<Double> &weights,\n                  Double &rms, Double &avg, Double &vmin, Double &vmax, Double &mean);\n\n  /** @brief Prints out some statistics (rms, mean, max...).\n  * (only at master node, calls from clients will be ignored). */\n  void printStatistics(const GriddedData &grid);\n\n  /** @brief Prints out some statistics (rms, mean, max...).\n  * (only at master node, calls from clients will be ignored). */\n  void printStatistics(const GriddedDataRectangular &grid);\n\n  /** @brief Generates functionals of a spherical harmonics expansion on a grid.\n  * Must be called from every node in parallel computations.\n  * @param harmonic spherical harmonics expansion\n  * @param points harm is evaluated at these points (fast on rectangular grid)\n  * @param kernel define the ouput functional.\n  * @param comm   communicator for parallel computation.\n  * @param timing start a loop timer for all grid points (only relevant for non-rectangular grids).\n  * @return values at @a points (only valid at master). */\n  std::vector<Double> synthesisSphericalHarmonics(const SphericalHarmonics &harmonic, const std::vector<Vector3d> &points, KernelPtr kernel,\n                                                  Parallel::CommunicatorPtr comm, Bool timing = TRUE);\n\n  /** @brief Generates a linear functional for the synthesis of spherical harmonics coefficients on a grid.\n  * This function generates a matrix A which represents the synthesis of a spherical harmonics vector x by matrix multiplication (y = Ax).\n  * The columns of A start at degree zero are sorted degreewise.\n  * @param maxDegree maximum expansion degree\n  * @param GM geocentric gravitational constant\n  * @param R reference radius\n  * @param points evaluation points\n  * @param kernel define the ouput functional.\n  * @param isInterior flag whether interior of the sphere is requested\n  * @return Matrix A. */\n  Matrix synthesisSphericalHarmonicsMatrix(UInt maxDegree, Double GM, Double R, const std::vector<Vector3d> &points, KernelPtr kernel, Bool isInterior=FALSE);\n\n\n  /** @brief Estimate spherical harmonics for each grid data column.\n  * Must be called from every node in parallel computations.\n  * @param grid points, areas (used as weights), data columns.\n  * @param kernel define the input functional.\n  * @param minDegree minumum expansion degree\n  * @param maxDegree maximum expansion degree\n  * @param GM geocentric gravitational constant\n  * @param R reference radius\n  * @param useLeastSquares least suqares adjustment, otherwise simple quadrature formular.\n  * @param comm   communicator for parallel computation.\n  * @param timing start a loop timer for all grid points (only relevant for non-rectangular grids). */\n  std::vector<SphericalHarmonics> analysisSphericalHarmonics(const GriddedData &grid, KernelPtr kernel, UInt minDegree, UInt maxDegree, Double GM, Double R,\n                                                             Bool useLeastSquares, Parallel::CommunicatorPtr comm, Bool timing = TRUE);\n\n} // namespace GriddedData\n\n/***********************************************/\n\n#endif /* __GROOPS_GRIDDEDDATA__ */\n"
  },
  {
    "path": "source/misc/normalsShortTimeStaticLongTime.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsShortTimeStaticLongTime.cpp\n*\n* @brief Normal equations with short and long time gravity variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-11-29\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"normalsShortTimeStaticLongTime.h\"\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::init(ObservationPtr observation, const std::vector<Time> &timesInterval,\n                                          UInt defaultBlockSize, Parallel::CommunicatorPtr comm, Bool sortOtherParametersBeforeGravityParameters,\n                                          UInt countShortTimeParameters, ParameterSelectorPtr parameterShortTime,\n                                          ParametrizationTemporalPtr temporal, ParameterSelectorPtr parameterTemporal)\n{\n  try\n  {\n    // parameter names\n    // ---------------\n    std::vector<ParameterName> paraNameAll;\n    observation->parameterName(paraNameAll);\n\n    // examine intervals\n    // -----------------\n    std::vector<UInt> minInterval(paraNameAll.size(), timesInterval.size());\n    std::vector<UInt> maxInterval(paraNameAll.size(), 0);\n    std::vector<std::vector<UInt>> indexDesign(timesInterval.size()-1, std::vector<UInt>(paraNameAll.size(), NULLINDEX));\n\n    for(UInt idInterval=0; idInterval+1<timesInterval.size(); idInterval++)\n    {\n      std::vector<ParameterName> paraNameInterval;\n      observation->setInterval(timesInterval.at(idInterval), timesInterval.at(idInterval+1));\n      observation->parameterName(paraNameInterval);\n\n      auto iter = paraNameAll.begin();\n      for(UInt k=0; k<paraNameInterval.size(); k++)\n      {\n        iter = std::find(iter, paraNameAll.end(), paraNameInterval.at(k));\n        const UInt i = std::distance(paraNameAll.begin(), iter);\n        indexDesign.at(idInterval).at(i) = k;\n        minInterval.at(i) = std::min(minInterval.at(i), idInterval);\n        maxInterval.at(i) = std::max(maxInterval.at(i), idInterval);\n      }\n    }\n    observation->setInterval(timesInterval.front(), timesInterval.back());\n\n    // --- lambda -------------------\n    auto testSelectedParameters = [&](const std::string &text, std::vector<UInt>::const_iterator begin, std::vector<UInt>::const_iterator end)\n    {\n      if(begin == end)\n        throw(Exception(text+\": no parameters selected\"));\n      if(!std::is_sorted(begin, end) || ((*(end-1)-*begin+1) != static_cast<UInt>(std::distance(begin, end))))\n        throw(Exception(text+\": selected parameters must be in consecutive order\"));\n      if(!std::all_of(begin, end, [&](UInt i) {return (minInterval.at(i) == minInterval.at(*begin)) && (maxInterval.at(i) == maxInterval.at(*begin));}))\n        throw(Exception(text+\": all selected parameters must be in the same time interval\"));\n    };\n    // ------------------------------\n\n    // add short time gravity parameters\n    // ---------------------------------\n    if(countShortTimeParameters && parameterShortTime)\n    {\n      std::vector<UInt> index = parameterShortTime->indexVector(paraNameAll);\n      if(index.size() % countShortTimeParameters)\n        throw(Exception(\"Number of selected short time parameters disagree with dimension of AR model\"));\n\n      // is only one static block? -> copy static parameters for each interval\n      if(index.size() == countShortTimeParameters)\n      {\n        testSelectedParameters(\"short time variations\", index.begin(), index.end());\n        paraNameAll.reserve(paraNameAll.size() + index.size() * (timesInterval.size()-1));\n        minInterval.reserve(paraNameAll.size() + index.size() * (timesInterval.size()-1));\n        maxInterval.reserve(paraNameAll.size() + index.size() * (timesInterval.size()-1));\n\n        for(UInt idInterval=0; idInterval+1<timesInterval.size(); idInterval++)\n        {\n          blockIndexShortTime.push_back(paraNameAll.size());\n          indexDesign.at(idInterval).reserve(paraNameAll.size() + index.size() * (timesInterval.size()-1));\n          const ParameterName paraNameInterval(\"\", \"\", \"\", timesInterval.at(idInterval), timesInterval.at(idInterval+1));\n          for(UInt i=0; i<index.size(); i++)\n          {\n            paraNameAll.push_back(paraNameAll.at(index.at(i)));\n            paraNameAll.back().combine(paraNameInterval);\n            for(UInt idInterval2=0; idInterval2+1<timesInterval.size(); idInterval2++)\n              indexDesign.at(idInterval2).push_back((idInterval == idInterval2) ? indexDesign.at(idInterval).at(index.at(i)) : NULLINDEX);\n            minInterval.push_back(idInterval);\n            maxInterval.push_back(idInterval);\n          }\n        }\n      }\n      else\n        for(UInt i=0; i<index.size(); i+=countShortTimeParameters)\n        {\n          testSelectedParameters(\"short time variations\", index.begin()+i, index.begin()+(i+countShortTimeParameters));\n          blockIndexShortTime.push_back(index.at(i));\n        }\n    }\n\n    // add long time gravity parameters\n    // --------------------------------\n    UInt countTemporalParameters = 0;\n    if(temporal && parameterTemporal)\n    {\n      std::vector<UInt> index = parameterTemporal->indexVector(paraNameAll);\n      testSelectedParameters(\"long time variations\", index.begin(), index.end());\n      countTemporalParameters = index.size();\n\n      blockIndexTemporal = {index.at(0)}; // static\n      for(UInt k=0; k<temporal->parameterCount(); k++)\n        blockIndexTemporal.push_back(paraNameAll.size()+k*index.size());\n\n      minInterval.resize(paraNameAll.size()+index.size()*temporal->parameterCount(), 0);\n      maxInterval.resize(paraNameAll.size()+index.size()*temporal->parameterCount(), timesInterval.size()-2);\n      for(UInt idInterval=0; idInterval+1<timesInterval.size(); idInterval++)\n        indexDesign.at(idInterval).resize(paraNameAll.size()+index.size()*temporal->parameterCount(), NULLINDEX);\n\n      std::vector<ParameterName> parameterNameBase(index.size());\n      for(UInt i=0; i<index.size(); i++)\n        parameterNameBase.at(i) = paraNameAll.at(index.at(i));\n      temporal->parameterName(parameterNameBase, paraNameAll);\n\n      factorTemporal.resize(1+temporal->parameterCount(), std::vector<Double>(timesInterval.size()-1)); // static + temporal\n      for(UInt idInterval=0; idInterval<timesInterval.size()-1; idInterval++)\n      {\n        const Vector f = temporal->factors(0.5*(timesInterval.at(idInterval)+timesInterval.at(idInterval+1)));\n        factorTemporal.at(0).at(idInterval) = 1.; // static\n        for(UInt k=0; k<f.rows(); k++)\n          factorTemporal.at(1+k).at(idInterval) = f(k);\n      }\n    }\n\n    // sort parameters: interval parameters first\n    // ------------------------------------------\n    std::vector<UInt> sortIndex(paraNameAll.size());\n    std::iota(sortIndex.begin(), sortIndex.end(), 0);\n    blockIndexStatic = std::distance(sortIndex.begin(), std::find_if(sortIndex.begin(), sortIndex.end(), [&](UInt i)\n                                                                     {return (minInterval.at(i) == 0) && (maxInterval.at(i) == timesInterval.size()-2);}));\n    std::stable_sort(sortIndex.begin(), sortIndex.end(), [&] (UInt i, UInt k)\n    {\n      Bool firstIsStatic = minInterval.at(i) == 0 && maxInterval.at(i) == timesInterval.size() - 2; // first parameter is static\n      Bool secondIsStatic = minInterval.at(k) == 0 && maxInterval.at(k) == timesInterval.size() - 2;  // other parameter is static\n      if((firstIsStatic && secondIsStatic) && sortOtherParametersBeforeGravityParameters)\n      {\n        if(((observation->gravityParameterCount() <= i) && (i < observation->parameterCount())) && // is state parameter?\n          !((observation->gravityParameterCount() <= k) && (k < observation->parameterCount())))   // is not state parameter?\n        return TRUE;\n      }\n      else if(firstIsStatic)\n        return FALSE;\n      else if(secondIsStatic)\n        return TRUE;\n\n      if(maxInterval.at(i) != maxInterval.at(k)) return (maxInterval.at(i) < maxInterval.at(k));\n      if(minInterval.at(i) != minInterval.at(k)) return (minInterval.at(i) < minInterval.at(k));\n\n      return FALSE;\n    });\n\n    parameterNames.clear(); parameterNames.reserve(paraNameAll.size());\n    for(UInt i=0; i<sortIndex.size(); i++)\n      parameterNames.push_back(paraNameAll.at(sortIndex.at(i)));\n\n    // divide into blocks\n    // ------------------\n    std::vector<UInt> blockIndex(1, 0);\n    while(blockIndex.back() < paraNameAll.size())\n    {\n      // ---------------------\n      auto mustSplit = [&](UInt i, UInt k)\n      {\n        for(UInt idInterval=0; idInterval+1<timesInterval.size(); idInterval++)\n          if((indexDesign.at(idInterval).at(i) != NULLINDEX) || (indexDesign.at(idInterval).at(k) != NULLINDEX))\n            if((indexDesign.at(idInterval).at(i) == NULLINDEX) || (indexDesign.at(idInterval).at(k) == NULLINDEX) || (indexDesign.at(idInterval).at(i) != indexDesign.at(idInterval).at(k)-1))\n              return TRUE;\n        if(std::find_if(blockIndexShortTime.begin(), blockIndexShortTime.end(), [&](UInt idx) {return (idx == k) || (idx+countShortTimeParameters-1 == i);}) != blockIndexShortTime.end())\n          return TRUE;\n        if(std::find_if(blockIndexTemporal.begin(), blockIndexTemporal.end(), [&](UInt idx) {return (idx == k) || (idx+countTemporalParameters-1 == i);}) != blockIndexTemporal.end())\n          return TRUE;\n        return FALSE;\n      };\n      // ---------------------\n\n      blockIndex.push_back(blockIndex.back()+1);\n      while((blockIndex.back() < paraNameAll.size()) && !mustSplit(sortIndex.at(blockIndex.back()-1), sortIndex.at(blockIndex.back())))\n        blockIndex.back()++;\n    }\n\n    // divide blocks according to defaultBlockSize (if not a high frequency block)\n    if(defaultBlockSize > 0)\n      for(UInt i=0; i<blockIndex.size()-1; i++)\n        if((blockIndex.at(i+1)-blockIndex.at(i) > defaultBlockSize*3/2) &&\n           (std::find(blockIndexShortTime.begin(), blockIndexShortTime.end(), sortIndex.at(blockIndex.at(i))) == blockIndexShortTime.end()))\n          blockIndex.insert(blockIndex.begin()+(i+1), blockIndex.at(i)+defaultBlockSize);\n\n    // Init normal equations\n    // ---------------------\n    initEmpty(blockIndex, comm);\n    n        = Matrix(parameterCount(), observation->rightSideCount());\n    lPl      = Vector(observation->rightSideCount());\n    obsCount = 0;\n    if(countTemporalParameters)\n    {\n      normalsTemporal.resize(timesInterval.size()-1);\n      for(UInt idInterval=0; idInterval<timesInterval.size()-1; idInterval++)\n        normalsTemporal.at(idInterval).initEmpty(blockIndex, comm);\n      nTemporal.clear();\n      nTemporal.resize(timesInterval.size()-1, Matrix(parameterCount(), observation->rightSideCount()));\n    }\n\n    // compute correct block indices\n    // -----------------------------\n    blockIndexStatic = index2block(std::distance(sortIndex.begin(), std::find(sortIndex.begin(), sortIndex.end(), blockIndexStatic)));\n    for(UInt &idx : blockIndexShortTime)\n      idx = index2block(std::distance(sortIndex.begin(), std::find(sortIndex.begin(), sortIndex.end(), idx)));\n    for(UInt &idx : blockIndexTemporal)\n      idx = index2block(std::distance(sortIndex.begin(), std::find(sortIndex.begin(), sortIndex.end(), idx)));\n\n    blockCountTemporal = 0;\n    if(blockIndexTemporal.size())\n      blockCountTemporal = index2block(blockIndex.at(blockIndexTemporal.at(0))+countTemporalParameters) - blockIndexTemporal.at(0);\n\n    // index for each block in design matrix\n    // -------------------------------------\n    indexN.clear(); indexN.resize(timesInterval.size()-1);\n    indexA.clear(); indexA.resize(timesInterval.size()-1);\n    for(UInt idBlock=0; idBlock<blockIndex.size()-1; idBlock++)\n    {\n      const UInt idx = blockIndex.at(idBlock);\n      for(UInt idInterval=0; idInterval+1<timesInterval.size(); idInterval++)\n        if(indexDesign.at(idInterval).at(sortIndex.at(idx)) != NULLINDEX)\n        {\n          indexN.at(idInterval).push_back(idBlock);\n          indexA.at(idInterval).push_back(indexDesign.at(idInterval).at(sortIndex.at(idx)));\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::setBlocks(const std::vector<UInt> &arcsInterval)\n{\n  try\n  {\n    for(UInt idInterval=0; idInterval+1<arcsInterval.size(); idInterval++)\n      if(arcsInterval.at(idInterval+1)-arcsInterval.at(idInterval) > 0)\n        for(UInt i=0; i<indexN.at(idInterval).size(); i++)\n          for(UInt k=i; k<indexN.at(idInterval).size(); k++)\n          {\n            const Bool isTemporal1 = blockCountTemporal && (blockIndexTemporal.at(0) <= indexN.at(idInterval).at(i)) && (indexN.at(idInterval).at(i) < blockIndexTemporal.at(0)+blockCountTemporal);\n            const Bool isTemporal2 = blockCountTemporal && (blockIndexTemporal.at(0) <= indexN.at(idInterval).at(k)) && (indexN.at(idInterval).at(k) < blockIndexTemporal.at(0)+blockCountTemporal);\n            if(isTemporal1 || isTemporal2)\n            {\n              normalsTemporal.at(idInterval).setBlock(indexN.at(idInterval).at(i), indexN.at(idInterval).at(k));\n              normalsTemporal.at(idInterval).N(indexN.at(idInterval).at(i), indexN.at(idInterval).at(k)) = Matrix();\n            }\n            else\n            {\n              setBlock(indexN.at(idInterval).at(i), indexN.at(idInterval).at(k));\n              N(indexN.at(idInterval).at(i), indexN.at(idInterval).at(k)) = Matrix();\n            }\n          }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::setNull()\n{\n  try\n  {\n    MatrixDistributed::setNull();\n    n.setNull();\n    lPl.setNull();\n    obsCount = 0;\n    for(UInt idInterval=0; idInterval+1<normalsTemporal.size(); idInterval++)\n      normalsTemporal.at(idInterval).setNull();\n    for(UInt idInterval=0; idInterval+1<nTemporal.size(); idInterval++)\n      nTemporal.at(idInterval).setNull();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::accumulate(UInt idInterval, Matrix &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    // if equations are orthogonaly transformed\n    // additional residuals are appended to l\n    Matrix l2;\n    if(l.rows() > A.rows())\n    {\n      l2 = l.row(A.rows(), l.rows()-A.rows());\n      l  = l.row(0, A.rows());\n    }\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    Vector tau;\n    if(B.size())\n    {\n      tau = QR_decomposition(B);\n      QTransMult(B, tau, l); // transform observations: l:= Q'l\n      QTransMult(B, tau, A); // transform design matrix A:=Q'A\n    }\n    // use only nullspace of design matrix B\n    MatrixSlice A_bar( A.row(B.columns(), A.rows()-B.columns()) );\n    MatrixSlice l_bar( l.row(B.columns(), l.rows()-B.columns()) );\n\n    // build normals\n    // -------------\n    obsCount += l_bar.rows();\n    for(UInt i=0; i<l_bar.columns(); i++)\n      lPl(i) += quadsum(l_bar.column(i)) + quadsum(l2.column(i));\n    for(UInt i=0; i<indexA.at(idInterval).size(); i++)\n    {\n      const UInt idxN1 = indexN.at(idInterval).at(i);\n      const UInt idxA1 = indexA.at(idInterval).at(i);\n      const Bool isTemporal1 = blockCountTemporal && (blockIndexTemporal.at(0) <= idxN1) && (idxN1 < blockIndexTemporal.at(0)+blockCountTemporal);\n\n      // right hand sides\n      Matrix &n2 = (isTemporal1) ? nTemporal.at(idInterval) : n;\n      matMult(1., A_bar.column(idxA1, blockSize(idxN1)).trans(), l_bar, n2.row(blockIndex(idxN1), blockSize(idxN1)));\n\n      // normal matrix diagonal block\n      Matrix &N2 = (isTemporal1) ? normalsTemporal.at(idInterval).N(idxN1, idxN1) : N(idxN1, idxN1);\n      if(N2.size() == 0)\n        N2 = Matrix(blockSize(idxN1), Matrix::SYMMETRIC);\n      rankKUpdate(1.0, A_bar.column(idxA1, blockSize(idxN1)), N2);\n\n      // normal matrix, other blocks\n      for(UInt k=i+1; k<indexA.at(idInterval).size(); k++)\n      {\n        const UInt idxN2 = indexN.at(idInterval).at(k);\n        const UInt idxA2 = indexA.at(idInterval).at(k);\n        const Bool isTemporal2 = blockCountTemporal && (blockIndexTemporal.at(0) <= idxN2) && (idxN2 < blockIndexTemporal.at(0)+blockCountTemporal);\n        Matrix &N2 = (isTemporal1 || isTemporal2) ? normalsTemporal.at(idInterval).N(idxN1, idxN2) : N(idxN1, idxN2);\n        if(N2.size() == 0)\n          N2 = Matrix(blockSize(idxN1), blockSize(idxN2));\n        matMult(1.0, A_bar.column(idxA1, blockSize(idxN1)).trans(), A_bar.column(idxA2, blockSize(idxN2)), N2);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::reduceSum(Bool timing)\n{\n  try\n  {\n    Parallel::reduceSum(n,        0, communicator());\n    Parallel::reduceSum(obsCount, 0, communicator());\n    Parallel::reduceSum(lPl,      0, communicator());\n    MatrixDistributed::reduceSum(timing);\n\n    if(blockCountTemporal == 0)\n      return;\n    if(timing) logStatus<<\"setup long time normal equations\"<<Log::endl;\n\n    // right hand side\n    for(UInt idInterval=0; idInterval<nTemporal.size(); idInterval++)\n      Parallel::reduceSum(nTemporal.at(idInterval), 0, communicator());\n\n    if(Parallel::isMaster(communicator()))\n      for(UInt blockRow=0; blockRow<blockCountTemporal; blockRow++)\n        for(UInt k=0; k<blockIndexTemporal.size(); k++)\n           for(UInt idInterval=0; idInterval<nTemporal.size(); idInterval++)\n             axpy(factorTemporal.at(k).at(idInterval),\n                  nTemporal.at(idInterval).row(blockIndex(blockRow+blockIndexTemporal.at(0)), blockSize(blockRow+blockIndexTemporal.at(k))),\n                  n.row(blockIndex(blockRow+blockIndexTemporal.at(k)), blockSize(blockRow+blockIndexTemporal.at(k))));\n\n    for(UInt idInterval=0; idInterval<normalsTemporal.size(); idInterval++)\n      normalsTemporal.at(idInterval).reduceSum(FALSE);\n\n    // --- lambda -------------------\n    auto send = [&](Matrix &N, UInt rankSource, UInt rankDest)\n    {\n      if(rankSource == rankDest)\n        return;\n      if(Parallel::myRank(communicator()) == rankSource)\n        Parallel::send(N, rankDest, communicator());\n      if(Parallel::myRank(communicator()) == rankDest)\n        Parallel::receive(N, rankSource, communicator());\n    };\n    // ------------------------------\n\n    for(UInt blockRow=0; blockRow<blockIndexTemporal.at(1); blockRow++)\n      for(UInt blockCol=blockRow; blockCol<blockIndexTemporal.at(1); blockCol++)\n      {\n        // --- lambda -------------------\n        auto reduceTemporal = [&](const std::vector<Double> &factor, Bool trans, UInt blocki, UInt blockk)\n        {\n          setBlock(blocki, blockk);\n          Matrix N2;\n          if(isMyRank(blockRow, blockCol))\n          {\n            N2 = Matrix(blockSize(blockRow), blockSize(blockCol));\n            for(UInt idInterval=0; idInterval<normalsTemporal.size(); idInterval++)\n              if(normalsTemporal.at(idInterval).isMyRank(blockRow, blockCol))\n                axpy(factor.at(idInterval), normalsTemporal.at(idInterval).N(blockRow, blockCol), N2);\n          }\n          send(N2, rank(blockRow, blockCol), rank(blocki, blockk));\n          if(isMyRank(blocki, blockk))\n          {\n            if(blockRow == blockCol)\n              N2.setType(Matrix::SYMMETRIC);\n            if((blockRow == blockCol) && (blocki != blockk))\n            {\n              fillSymmetric(N2);\n              N2.setType(Matrix::GENERAL);\n            }\n            N(blocki, blockk) = (trans) ? N2.trans() : N2;\n          }\n        };\n        // ------------------------------\n\n        // upper blocks\n        // ------------\n        if((blockRow < blockIndexTemporal.at(0)) &&\n           (blockIndexTemporal.at(0) <= blockCol) && (blockCol < blockIndexTemporal.at(0)+blockCountTemporal))\n        {\n          for(UInt k=0; k<blockIndexTemporal.size(); k++)\n            reduceTemporal(factorTemporal.at(k), FALSE, blockRow, blockCol-blockIndexTemporal.at(0)+blockIndexTemporal.at(k));\n        }\n\n        // temporal blocks\n        // ---------------\n        if((blockIndexTemporal.at(0) <= blockRow) && (blockRow < blockIndexTemporal.at(0)+blockCountTemporal) &&\n           (blockIndexTemporal.at(0) <= blockCol) && (blockCol < blockIndexTemporal.at(0)+blockCountTemporal))\n        {\n          for(UInt k=0; k<blockIndexTemporal.size(); k++)\n            for(UInt l=k; l<blockIndexTemporal.size(); l++)\n            {\n              std::vector<Double> factor(factorTemporal.at(0).size());\n              std::transform(factorTemporal.at(k).begin(), factorTemporal.at(k).end(), factorTemporal.at(l).begin(), factor.begin(), std::multiplies<Double>());\n              reduceTemporal(factor, FALSE,\n                             blockRow-blockIndexTemporal.at(0)+blockIndexTemporal.at(k),\n                             blockCol-blockIndexTemporal.at(0)+blockIndexTemporal.at(l));\n            }\n        }\n\n        // right side blocks\n        // -----------------\n        if((blockIndexTemporal.at(0) <= blockRow) && (blockRow < blockIndexTemporal.at(0)+blockCountTemporal) &&\n           (blockIndexTemporal.at(0)+blockCountTemporal <= blockCol))\n        {\n          reduceTemporal(factorTemporal.at(0), FALSE, blockRow, blockCol);\n          for(UInt k=1; k<blockIndexTemporal.size(); k++)\n            reduceTemporal(factorTemporal.at(k), TRUE, blockCol, blockRow-blockIndexTemporal.at(0)+blockIndexTemporal.at(k));\n        }\n\n        // free memory\n        for(UInt idInterval=0; idInterval<normalsTemporal.size(); idInterval++)\n          if(normalsTemporal.at(idInterval).isBlockUsed(blockRow, blockCol))\n            normalsTemporal.at(idInterval).N(blockRow, blockCol) = Matrix();\n      }\n\n    // fill symmetric\n    // --------------\n    for(UInt k=0; k<blockIndexTemporal.size(); k++)\n      for(UInt l=k+1; l<blockIndexTemporal.size(); l++)\n         for(UInt blockRow=0; blockRow<blockCountTemporal; blockRow++)\n           for(UInt blockCol=blockRow+1; blockCol<blockCountTemporal; blockCol++)\n           {\n             const UInt rowSource = blockIndexTemporal.at(k)+blockRow;\n             const UInt colSource = blockIndexTemporal.at(l)+blockCol;\n             const UInt rowDest   = blockIndexTemporal.at(k)+blockCol;\n             const UInt colDest   = blockIndexTemporal.at(l)+blockRow;\n\n             Matrix N2 = N(rowSource, colSource).trans();\n             setBlock(rowDest, colDest);\n             send(N2, rank(rowSource, colSource), rank(rowDest, colDest));\n             if(isMyRank(rowDest, colDest))\n               N(rowDest, colDest) = N2;\n           }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::addShortTimeNormals(Double sigma2, const std::vector<std::vector<std::vector<Matrix>>> &normalsShortTime)\n{\n  try\n  {\n    if(!blockIndexShortTime.size())\n      return;\n\n    if(Parallel::isMaster(communicator()))\n      obsCount += normalsShortTime.at(0).at(0).at(0).rows() * blockIndexShortTime.size();\n    for(UInt id=0; id<blockIndexShortTime.size(); id++)\n    {\n      const UInt idx = std::min(id, normalsShortTime.size()-1);\n      for(UInt i=0; i<normalsShortTime.at(idx).size(); i++)\n        for(UInt k=i; k<normalsShortTime.at(idx).at(i).size(); k++)\n        {\n          setBlock(blockIndexShortTime.at(id+i-idx), blockIndexShortTime.at(id+k-idx));\n          if(isMyRank(blockIndexShortTime.at(id+i-idx), blockIndexShortTime.at(id+k-idx)))\n            axpy(1./sigma2, normalsShortTime.at(idx).at(i).at(k), N(blockIndexShortTime.at(id+i-idx), blockIndexShortTime.at(id+k-idx)));\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::regularizeUnusedParameters(UInt countBlock)\n{\n  try\n  {\n    UInt additionalObservations = 0;\n    for(UInt i=0; i<countBlock; i++)\n    {\n      setBlock(i, i);\n      if(isMyRank(i,i))\n      {\n        Matrix &N2 = N(i,i);\n        for(UInt k=0; k<N2.rows(); k++)\n          if(N2(k,k) == 0)\n          {\n            N2(k,k) = 1.;\n            additionalObservations++;\n            logWarning<<\" parameters is not used: \"<<parameterNames.at(blockIndex(i)+k).str()<<Log::endl;\n          }\n      }\n    }\n    Parallel::reduceSum(additionalObservations, 0, communicator());\n    if(Parallel::isMaster(communicator()))\n      obsCount += additionalObservations;\n    Parallel::barrier(communicator());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble NormalsShortTimeStaticLongTime::solve(Matrix &x, Matrix &Wz)\n{\n  try\n  {\n    regularizeUnusedParameters(blockCount());\n    x = MatrixDistributed::solve(n, TRUE/*timing*/);\n    Parallel::broadCast(x, 0, communicator());\n\n    // N contains now the cholesky decomposition\n    Wz = Vce::monteCarlo(parameterCount(), 100); // monte carlo vector for VCE\n    triangularSolve(Wz);\n    Parallel::broadCast(Wz, 0, communicator());\n\n    return std::sqrt((lPl(0)-inner(x.column(0), n.column(0)))/(obsCount-parameterCount()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector NormalsShortTimeStaticLongTime::parameterStandardDeviation()\n{\n  try\n  {\n    cholesky2SparseInverse();\n\n    Vector diagonal = Vector(dimension());\n    for(UInt i=0; i<blockCount(); i++)\n      if(isMyRank(i,i))\n      {\n        Matrix &N2 = N(i,i);\n        for(UInt z=0; z<N2.rows(); z++)\n          diagonal(blockIndex(i)+z) = std::sqrt(N2(z,z));\n      }\n\n    Parallel::reduceSum(diagonal, 0, communicator());\n    return diagonal;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble NormalsShortTimeStaticLongTime::estimateShortTimeNormalsVariance(Double sigma2, const std::vector<std::vector<std::vector<Matrix>>> &normalsShortTime,\n                                                                        const_MatrixSliceRef x, const_MatrixSliceRef Wz) const\n{\n  try\n  {\n    const UInt count = blockSize(blockIndexShortTime.at(0));\n    Matrix Nx(x.rows(), x.columns());\n    Matrix NWz(Wz.rows(), Wz.columns());\n    for(UInt id=0; id<blockIndexShortTime.size(); id++)\n    {\n      const UInt idx = std::min(id, normalsShortTime.size()-1);\n      for(UInt i=0; i<normalsShortTime.at(idx).size(); i++)\n        for(UInt k=i; k<normalsShortTime.at(idx).at(i).size(); k++)\n          if(isMyRank(blockIndexShortTime.at(id+i-idx), blockIndexShortTime.at(id+k-idx)))\n          {\n            const UInt idxi = blockIndex(blockIndexShortTime.at(id+i-idx));\n            const UInt idxk = blockIndex(blockIndexShortTime.at(id+k-idx));\n            matMult(1., normalsShortTime.at(idx).at(i).at(k),  x.row(idxk, count),  Nx.row(idxi, count));\n            matMult(1., normalsShortTime.at(idx).at(i).at(k), Wz.row(idxk, count), NWz.row(idxi, count));\n            if(k > i) // extend symmetric\n            {\n              matMult(1., normalsShortTime.at(idx).at(i).at(k).trans(),  x.row(idxi, count),  Nx.row(idxk, count));\n              matMult(1., normalsShortTime.at(idx).at(i).at(k).trans(), Wz.row(idxi, count), NWz.row(idxk, count));\n            }\n          }\n    } // for(id)\n    Parallel::reduceSum(Nx,  0, communicator());\n    Parallel::reduceSum(NWz, 0, communicator());\n\n    const Double ePe = inner(x.column(0), Nx.column(0));\n    const Double r   = count*blockIndexShortTime.size() - 1./sigma2*inner(Wz, NWz);\n    Double s2  = ePe/r;\n    Parallel::broadCast(s2, 0, communicator());\n    return s2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid NormalsShortTimeStaticLongTime::designMatMult(UInt idInterval, Double factor, const_MatrixSliceRef A, const_MatrixSliceRef x, MatrixSliceRef Ax)\n{\n  try\n  {\n    for(UInt i=0; i<indexA.at(idInterval).size(); i++)\n    {\n      const UInt idxN = indexN.at(idInterval).at(i);\n      const UInt idxA = indexA.at(idInterval).at(i);\n      matMult(factor, A.column(idxA, blockSize(idxN)), x.row(blockIndex(idxN), blockSize(idxN)), Ax);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/normalsShortTimeStaticLongTime.h",
    "content": "/***********************************************/\n/**\n* @file normalsShortTimeStaticLongTime.h\n*\n* @brief Normal equations with short and long time gravity variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-11-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_NORMALSSHORTTIMESTATICLONGTIME__\n#define __GROOPS_NORMALSSHORTTIMESTATICLONGTIME__\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"classes/observation/observation.h\"\n\n/***** TYPES ***********************************/\n\nclass ParameterSelector;\nclass ParametrizationTemporal;\ntypedef std::shared_ptr<ParameterSelector>       ParameterSelectorPtr;\ntypedef std::shared_ptr<ParametrizationTemporal> ParametrizationTemporalPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Normal equations with short and long time gravity variations.\n* @ingroup miscGroup */\nclass NormalsShortTimeStaticLongTime : public MatrixDistributed\n{\npublic:\n  Matrix n;         // right hand sides\n  Vector lPl;       // =l'Pl, weighted norm of the observations\n  UInt   obsCount;  // number of observations\n\n  std::vector<ParameterName>       parameterNames;\n  std::vector<std::vector<UInt>>   indexA; // for each interval\n  std::vector<std::vector<UInt>>   indexN; // for each interval\n  UInt                             blockIndexStatic;\n  std::vector<UInt>                blockIndexShortTime;\n  UInt                             blockCountTemporal;\n  std::vector<UInt>                blockIndexTemporal; // static + for each temporal\n  std::vector<MatrixDistributed>   normalsTemporal;\n  std::vector<Matrix>              nTemporal;\n  std::vector<std::vector<Double>> factorTemporal;\n\n  void init(ObservationPtr observation, const std::vector<Time> &timesInterval,\n            UInt defaultBlockSize, Parallel::CommunicatorPtr comm, Bool sortStateBeforeGravityParameter,\n            UInt countShortTimeParameters, ParameterSelectorPtr parameterShortTime,\n            ParametrizationTemporalPtr temporal=nullptr, ParameterSelectorPtr parameterTemporal=nullptr);\n\n  /// Allocate memory of matrix blocks.\n  void setBlocks(const std::vector<UInt> &arcsInterval);\n\n  /// Fill all matrix blocks with zero.\n  void setNull();\n\n  /** @brief Add observation equations to the normal system.\n  * The design matrix @p A must contain only parameters valid in interval @p idInterval\n  * (Computed with @a setInterval()).\n  * The input matrices @p l, @p A, and @p B might be destroyed. */\n  void accumulate(UInt idInterval, Matrix &l, Matrix &A, Matrix &B);\n\n  /// Reduce the system of normal equations.\n  void reduceSum(Bool timing=TRUE);\n\n  void addShortTimeNormals(Double sigma2, const std::vector<std::vector<std::vector<Matrix>>> &normalsShortTime);\n\n  void regularizeUnusedParameters(UInt countBlock);\n\n  Double solve(Matrix &x, Matrix &Wz);\n\n  /** @brief Compute the standard devitiations of the parameter vector.\n  * (The sqrt of the diagonals of inverse normal matrix). The normals must be given as cholesky decomposition (with @a solve).\n  * On oputput the normal matrix contains the inverse of cholesky matrix. */\n  Vector parameterStandardDeviation();\n\n  Double estimateShortTimeNormalsVariance(Double sigma2, const std::vector<std::vector<std::vector<Matrix>>> &normalsShortTime,\n                                          const_MatrixSliceRef x, const_MatrixSliceRef Wz) const;\n  /** @brief Computes Ax = factor*A*x.\n  * The design matrix @p A contains only parameters valid in interval @p idInterval. */\n  void designMatMult(UInt idInterval, Double factor, const_MatrixSliceRef A, const_MatrixSliceRef x, MatrixSliceRef Ax);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/observation/covariancePod.cpp",
    "content": "/***********************************************/\n/**\n* @file covariancePod.cpp\n*\n* @brief Covariance matrix of kinematic orbits.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-07-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_CovariancePod\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"covariancePod.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(CovariancePod, \"covariancePodType\")\nGROOPS_READCONFIG_CLASS(CovariancePod, \"covariancePodType\")\n\n/***********************************************/\n\nCovariancePod::CovariancePod(Config &config, const std::string &name)\n{\n  try\n  {\n    FileName fileNameSigmaArc, fileNameSigmaEpoch, fileNameCovPodEpoch, fileNameCovFunc;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"sigma\",                        sigma,               Config::DEFAULT,  \"1\", \"general variance factor\");\n    readConfig(config, \"inputfileSigmasPerArc\",        fileNameSigmaArc,    Config::OPTIONAL, \"\",  \"different accuracies for each arc (multiplied with sigma)\");\n    readConfig(config, \"inputfileSigmasPerEpoch\",      fileNameSigmaEpoch,  Config::OPTIONAL, \"\",  \"different accuracies for each epoch (added)\");\n    readConfig(config, \"inputfileCovarianceFunction\",  fileNameCovFunc,     Config::OPTIONAL, \"\",  \"covariances in time for along, cross, and radial direction\");\n    readConfig(config, \"inputfileCovariancePodEpoch\",  fileNameCovPodEpoch, Config::OPTIONAL, \"\",  \"3x3 epoch-wise covariances\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    if(!fileNameSigmaArc.empty())\n      readFileMatrix(fileNameSigmaArc, sigmaArc);\n\n    if(!fileNameSigmaEpoch.empty())\n      fileSigmaEpoch.open(fileNameSigmaEpoch);\n\n    if(!fileNameCovPodEpoch.empty())\n      fileCovPodEpoch.open(fileNameCovPodEpoch);\n\n    if(!fileNameCovFunc.empty())\n      readFileMatrix(fileNameCovFunc, covFunction);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid CovariancePod::testInput(const OrbitArc &pod, const ObservationSigmaArc &sigmaEpoch, const Covariance3dArc &covPod, const_MatrixSliceRef covFunction)\n{\n  if(sigmaEpoch.size() && (sigmaEpoch.size() != pod.size()))\n    throw(Exception(\"sigma per epoch not compatible with this arc number\"));\n  if((covPod.size() != 0) && (covPod.size() != pod.size()))\n    throw(Exception(\"orbit and CovariancePodEpoch are not compatible\"));\n  if(covFunction.size() && (covFunction.rows()<pod.size()))\n    throw(Exception(\"covariance function to short for this arc\"));\n}\n\n/***********************************************/\n\nMatrix CovariancePod::covariance(UInt arcNo, const OrbitArc &pod)\n{\n  try\n  {\n    ObservationSigmaArc sigmaEpoch = fileSigmaEpoch.readArc(arcNo);\n    Covariance3dArc     covPod     = fileCovPodEpoch.readArc(arcNo);\n    testInput(pod, sigmaEpoch, covPod, covFunction);\n    if(sigmaArc.size() && (arcNo>=sigmaArc.size()))\n      throw(Exception(\"sigmasPerArc contain not enough rows for this arc number\"));\n\n    Double sigma2 = pow(this->sigma, 2);\n    if(sigmaArc.size())\n      sigma2 *= pow(this->sigmaArc(arcNo), 2);\n\n    Matrix C(3*pod.size(), Matrix::TRIANGULAR);\n    for(UInt i=0; i<sigmaEpoch.size(); i++)\n      for(UInt k=0; k<3; k++)\n        C(3*i+k,3*i+k) += pow(sigmaEpoch.at(i).sigma, 2);\n\n    // special case 1: diagonal matrix\n    // -------------------------------\n    if((covPod.size()==0) && (covFunction.size()==0))\n    {\n      for(UInt i=0; i<C.rows(); i++)\n        C(i,i) += sigma2;\n      return C;\n    }\n\n    // special case 2: epoch block diagonal matrix\n    // -------------------------------------------\n    if(covPod.size() && (covFunction.size()==0))\n    {\n      for(UInt i=0; i<pod.size(); i++)\n      {\n        Matrix C3x3 = covPod.at(i).covariance.matrix();\n        axpy(sigma2, C3x3, C.slice(3*i,3*i,3,3));\n      }\n      return C;\n    }\n\n    // covariance function in orbit system\n    // -----------------------------------\n    const Double sampling = covFunction(1,0)-covFunction(0,0);\n    for(UInt z=0; z<pod.size(); z++)\n      for(UInt s=z; s<pod.size(); s++)\n      {\n        UInt idx = static_cast<UInt>(round((pod.at(s).time-pod.at(z).time).seconds()/sampling));\n        C(3*z+0, 3*s+0) += sigma2 * covFunction(idx, 1+0);\n        C(3*z+1, 3*s+1) += sigma2 * covFunction(idx, 1+1);\n        C(3*z+2, 3*s+2) += sigma2 * covFunction(idx, 1+2);\n      }\n    fillSymmetric(C);\n\n    // rotate and decorrelate epoch wise residuals\n    // -------------------------------------------\n    for(UInt i=0; i<pod.size(); i++)\n    {\n      // orbit system: z: radial, x: along, y: cross\n      Vector3d x;\n      if(i==0)\n        x = pod.at(i+1).position - pod.at(i).position;\n      else\n        x = pod.at(i).position - pod.at(i-1).position;\n      Vector3d z = normalize(pod.at(i).position);\n      Vector3d y = normalize(crossProduct(z, x));\n      x = crossProduct(y, z);\n      Matrix D = Rotary3d(x,y).matrix().trans(); // Rot from CRF to SRF\n\n      // epoch wise decorrelation\n      if(covPod.size()!=0)\n      {\n        Matrix V = covPod.at(i).covariance.matrix();    // 3x3 Epoch covariance\n        V.setType(Matrix::SYMMETRIC, Matrix::UPPER);\n        Vector eigen = eigenValueDecomposition(V);\n        Matrix V1 = V;\n        V1.column(0) *= std::sqrt(eigen(0));\n        V1.column(1) *= std::sqrt(eigen(1));\n        V1.column(2) *= std::sqrt(eigen(2));\n        D = D*V1*V.trans();           // W^-T im LORF\n      }\n\n      copy(D.trans() * C.row(3*i,3), C.row(3*i,3));\n      copy(C.column(3*i,3) * D,      C.column(3*i,3));\n    }\n\n    return C;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid CovariancePod::decorrelate(UInt arcNo, const OrbitArc &pod, const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    ObservationSigmaArc sigmaEpoch = fileSigmaEpoch.readArc(arcNo);\n    Covariance3dArc     covPod     = fileCovPodEpoch.readArc(arcNo);\n    testInput(pod, sigmaEpoch, covPod, covFunction);\n    if(sigmaArc.size() && (arcNo>=sigmaArc.size()))\n      throw(Exception(\"sigmasPerArc contain not enough rows for this arc number\"));\n\n    Double weight = 1./this->sigma;\n    if(sigmaArc.size() != 0)\n      weight *= 1./this->sigmaArc(arcNo);\n\n    // special case 1: diagonal matrix\n    // -------------------------------\n    if((covPod.size()==0) && (sigmaEpoch.size()==0) && (covFunction.size()==0))\n    {\n      for(MatrixSliceRef WA : A)\n        if(WA.size()) WA *= weight;\n      return;\n    }\n\n    // special case 2: epoch block diagonal matrix\n    // -------------------------------------------\n    if(covPod.size() && (covFunction.size()==0))\n    {\n      for(UInt i=0; i<pod.size(); i++)\n      {\n        Matrix W = covPod.at(i).covariance.matrix();\n        W.setType(Matrix::SYMMETRIC);\n\n        if(sigmaEpoch.size())\n        {\n          W(0,0) += sigmaEpoch.at(i).sigma;\n          W(1,1) += sigmaEpoch.at(i).sigma;\n          W(2,2) += sigmaEpoch.at(i).sigma;\n        }\n\n        cholesky(W);\n        for(MatrixSliceRef WA : A)\n          if(WA.size())\n            triangularSolve(weight, W.trans(), WA.row(3*i,3));\n      }\n      return;\n    }\n\n    decorrelate(pod, 1/weight, sigmaEpoch, covPod, covFunction, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix CovariancePod::decorrelate(const OrbitArc &pod, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                                  const Covariance3dArc &covPod, const_MatrixSliceRef covFunction,\n                                  const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    testInput(pod, sigmaEpoch, covPod, covFunction);\n\n    // rotate and decorrelate epoch wise residuals\n    // -------------------------------------------\n    for(UInt i=0; i<pod.size(); i++)\n    {\n      // orbit system: z: radial, x: along, y: cross\n      Vector3d x;\n      if(i==0)\n        x = pod.at(i+1).position - pod.at(i).position;\n      else\n        x = pod.at(i).position - pod.at(i-1).position;\n      Vector3d z = normalize(pod.at(i).position);\n      Vector3d y = normalize(crossProduct(z, x));\n      x = crossProduct(y, z);\n      Matrix D = Rotary3d(x,y).matrix().trans(); // Rot from CRF to SRF\n\n      // epoch wise decorrelation\n      if(covPod.size()!=0)\n      {\n        Matrix V = covPod.at(i).covariance.matrix(); // 3x3 Epoch covariance\n        V.setType(Matrix::SYMMETRIC, Matrix::UPPER);\n        Vector eigen = eigenValueDecomposition(V);\n        Matrix V1 = V;\n        V1.column(0) *= 1./sqrt(eigen(0));\n        V1.column(1) *= 1./sqrt(eigen(1));\n        V1.column(2) *= 1./sqrt(eigen(2));\n        D = D*V1*V.trans();           // W^-T im LORF\n      }\n\n      for(MatrixSliceRef WA : A)\n        if(WA.size())\n          copy(D * WA.row(3*i,3), WA.row(3*i,3));\n    }\n\n    // covariance function in orbit system\n    // -----------------------------------\n    Matrix W(3*pod.size(), Matrix::SYMMETRIC, Matrix::UPPER);\n    if(covFunction.size())\n    {\n      const Double sampling = covFunction(1,0)-covFunction(0,0);\n      for(UInt z=0; z<pod.size(); z++)\n        for(UInt s=z; s<pod.size(); s++)\n        {\n          UInt idx = static_cast<UInt>(round((pod.at(s).time-pod.at(z).time).seconds()/sampling));\n          W(3*z+0, 3*s+0) = sigmaArc*sigmaArc * covFunction(idx, 1+0);\n          W(3*z+1, 3*s+1) = sigmaArc*sigmaArc * covFunction(idx, 1+1);\n          W(3*z+2, 3*s+2) = sigmaArc*sigmaArc * covFunction(idx, 1+2);\n        }\n    }\n\n    for(UInt i=0; i<sigmaEpoch.size(); i++)\n      for(UInt k=0; k<3; k++)\n        W(3*i+k,3*i+k) += pow(sigmaEpoch.at(i).sigma, 2);\n\n    cholesky(W);\n    for(MatrixSliceRef WA : A)\n      if(WA.size())\n        triangularSolve(1., W.trans(), WA);\n\n    return W;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/covariancePod.h",
    "content": "/***********************************************/\n/**\n* @file covariancePod.h\n*\n* @brief Covariance matrix of kinematic orbits.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-07-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_COVARIANCEPOD__\n#define __GROOPS_COVARIANCEPOD__\n\n// Latex documentation\n#ifdef DOCSTRING_CovariancePod\nstatic const char *docstringCovariancePod = R\"(\n\\section{CovariancePod}\\label{covariancePodType}\nProvides arc-wise covariance matrices for precise orbit data.\nTemporal correlations are modeled in the orbit system (along, cross, radial).\nThe \\configFile{inputfileCovarianceFunction}{matrix} provides temporal covariance functions for each axis.\nFrom the diagonal matrix for each time step\n\\begin{equation}\n  Cov_{3\\times3}(t) = \\text{diag}(cov_x(t), cov_y(t), cov_z(t))\n\\end{equation}\nthe Toeplitz covariance matrix for an arc is constructed\n\\begin{equation}\n  \\M C = \\begin{pmatrix}\n    Cov(t_0) & Cov(t_1) & \\cdots   &          &        &        \\\\\n    Cov(t_1) & Cov(t_0) & Cov(t_1) & \\cdots   &        &        \\\\\n    \\cdots   & Cov(t_1) & Cov(t_0) & Cov(t_1) & \\cdots &        \\\\\n             & \\cdots   & \\ddots   & \\ddots   & \\ddots & \\cdots \\\\\n  \\end{pmatrix}\n\\end{equation}\n\nThe epoch-wise $3\\times3$ covariance matrices given by \\configFile{inputfileCovariancePodEpoch}{instrument}\nare eigenvalue-decomposed\n\\begin{equation}\n  \\M C_{3\\times3}(t_i) = \\M Q \\M\\Lambda \\M Q^T,\n\\end{equation}\nwhere $\\M Q$ is an orthogonal matrix and $\\M\\Lambda$ diagonal.\nThis is used to split the covariances matrices\n\\begin{equation}\n  \\M C_{3\\times3}(t_i) = \\M D(t_i) \\M D(t_i)^T = (\\M Q \\M\\Lambda^{1/2} \\M Q^T)(\\M Q \\M\\Lambda^{1/2} \\M Q^T)^T,\n\\end{equation}\nand to compose a block diagonal matrix for an arc\n\\begin{equation}\n  \\M D = \\text{diag}(\\M D(t_1), \\M D(t_2), \\ldots, \\M D(t_2)).\n\\end{equation}\n\nThe complete covariance matrix of an arc is given by\n\\begin{equation}\n  \\M C_{arc} = \\sigma_0^2 \\sigma_{arc}^2 \\M D \\M C \\M D^T +\n  \\text{diag}(\\sigma_1^2\\M I_{3\\times3}, \\sigma_2^2\\M I_{3\\times3}, \\ldots, \\sigma_n^2\\M I_{3\\times3})\n\\end{equation}\nwhere \\config{sigma}~$\\sigma_0$ is an overall factor\nand the arc specific factors $\\sigma_{arc}$ can be provided with \\configFile{inputfileSigmasPerArc}{matrix}.\nThe last matrix can be used to downweight outliers in single epochs and will be added if\n\\configFile{inputfileSigmasPerEpoch}{instrument} is provided.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n\n/**\n* @defgroup CovariancePodGroup CovariancePod\n* @brief Covariance function to decorrelate observation equations.\n* @ingroup miscGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass CovariancePod;\ntypedef std::shared_ptr<CovariancePod> CovariancePodPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Covariance matrix of kinematic orbit observations. */\nclass CovariancePod\n{\n  Double         sigma;\n  Vector         sigmaArc;\n  InstrumentFile fileSigmaEpoch;\n  InstrumentFile fileCovPodEpoch;\n  Matrix         covFunction;\n\n  static void testInput(const OrbitArc &pod, const ObservationSigmaArc &sigmaEpoch, const Covariance3dArc &covPod, const_MatrixSliceRef covFunction);\n\npublic:\n  /// Constructor\n  CovariancePod() : sigma(1.0) {}\n\n  /// Constructor\n  CovariancePod(Config &config, const std::string &name);\n\n  /// Destructor.\n  virtual ~CovariancePod() {}\n\n  /** @brief Full variance covariance matrix.\n  * The matrix is related to observations given as x,y,z per epoch in CRF [m]. */\n  Matrix covariance(UInt arcNo, const OrbitArc &pod);\n\n  /** @brief Decorrelates observation equations.\n  * The observations must be given as x,y,z per epoch in CRF [m].\n  * The list of observation vector and design matrices are decorrelated. */\n  void decorrelate(UInt arcNo, const OrbitArc &pod, const std::list<MatrixSlice> &A);\n\n  /** @brief Decorrelates observation equations.\n  * The observations must be given as x,y,z per epoch in CRF [m].\n  * The list of observation vector and design matrices are decorrelated.\n  * @return Cholesky decomposition of the covariance matrix (without orbit rotation and epoch-wise covariance matrix). */\n  static Matrix decorrelate(const OrbitArc &pod, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                            const Covariance3dArc &covPod, const_MatrixSliceRef covFunction,\n                            const std::list<MatrixSlice> &A);\n\n  /** @brief creates a derived instance of this class. */\n  static CovariancePodPtr create(Config &config, const std::string &name) {return std::make_shared<CovariancePod>(config, name);}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class CovariancePod.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates CovariancePod */\ntemplate<> Bool readConfig(Config &config, const std::string &name, CovariancePodPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/observation/covarianceSst.cpp",
    "content": "/***********************************************/\n/**\n* @file covarianceSst.cpp\n*\n* @brief Covariance matrix of satellite to satellite tracking observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-07-18\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_CovarianceSst\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"covarianceSst.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(CovarianceSst, \"covarianceSstType\")\nGROOPS_READCONFIG_CLASS(CovarianceSst, \"covarianceSstType\")\n\n/***********************************************/\n\nCovarianceSst::CovarianceSst(Config &config, const std::string &name)\n{\n  try\n  {\n    FileName fileNameSigmaArc;\n    FileName fileNameSigmaEpoch;\n    FileName fileNameCovFunc;\n    FileName fileNameCovMatrixSigmas;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"sigma\",                        sigma,                     Config::DEFAULT,  \"1\", \"general variance factor\");\n    readConfig(config, \"inputfileSigmasPerArc\",        fileNameSigmaArc,          Config::OPTIONAL, \"\",  \"different accuaries for each arc (multplicated with sigma)\");\n    readConfig(config, \"inputfileSigmasPerEpoch\",      fileNameSigmaEpoch,        Config::OPTIONAL, \"\",  \"different accuaries for each epoch (added)\");\n    readConfig(config, \"inputfileCovarianceFunction\",  fileNameCovFunc,           Config::OPTIONAL, \"\",  \"covariance function in time\");\n    readConfig(config, \"inputfileCovarianceMatrixArc\", fileNamesCovarianceMatrix, Config::OPTIONAL, \"\",  \"one matrix file per arc. Use {arcNo} as template\");\n    readConfig(config, \"sigmasCovarianceMatrixArc\",    fileNameCovMatrixSigmas,   Config::OPTIONAL, \"\",  \"vector with one sigma for each covarianceMatrixArc\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    if(!fileNameSigmaArc.empty())\n      readFileMatrix(fileNameSigmaArc, sigmaArc);\n\n    if(!fileNameSigmaEpoch.empty())\n      fileSigmaEpoch.open(fileNameSigmaEpoch);\n\n    if(!fileNameCovFunc.empty())\n      readFileMatrix(fileNameCovFunc, covFunction);\n\n    if(!fileNameCovMatrixSigmas.empty())\n    {\n      readFileMatrix(fileNameCovMatrixSigmas, covMatrixSigmas);\n      if(covMatrixSigmas.rows() != fileNamesCovarianceMatrix.size())\n        throw(Exception(\"Number of sigmas not compatible with number of given arc-wise SST covariance matrices\"));\n    }\n    else if(!fileNamesCovarianceMatrix.empty())\n    {\n      covMatrixSigmas = Vector(fileNamesCovarianceMatrix.size());\n      for(UInt i=0; i<covMatrixSigmas.rows(); i++)\n        covMatrixSigmas(i) = 1.0;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid CovarianceSst::testInput(const std::vector<Time> &times, const ObservationSigmaArc &sigmaEpoch, const_MatrixSliceRef covFunction, const_MatrixSliceRef W)\n{\n  if(sigmaEpoch.size() && (sigmaEpoch.size() != times.size()))\n    throw(Exception(\"sigma per epoch not compatible with this arc number\"));\n  if(covFunction.size() && (covFunction.rows()<times.size()))\n    throw(Exception(\"covariance function to short for this arc\"));\n  if(W.size() && ((W.rows() != times.size()) || (W.columns() != times.size())) )\n    throw(Exception(\"covariance matrix W wrong size\"));\n}\n\n/***********************************************/\n\nMatrix CovarianceSst::covariance(UInt arcNo, const std::vector<Time> &times)\n{\n  try\n  {\n    Matrix C(times.size(), Matrix::SYMMETRIC, Matrix::UPPER);\n\n    for(UInt i=0; i<fileNamesCovarianceMatrix.size(); i++)\n    {\n      Matrix M;\n      FileName thisFile = fileNamesCovarianceMatrix.at(i).appendBaseName(\".arc\"+arcNo%\"%03i\"s);\n      readFileMatrix(thisFile, M);\n      if((M.rows() != C.rows()) || (M.columns() != C.columns()))\n        throw(Exception(\"Arc-Wise SST covariance matrix <\"+thisFile.str()+\"> wrong size for arc.\"));\n      axpy(std::pow(covMatrixSigmas(i), 2), M, C);\n    }\n\n    return covariance(times, (sigmaArc.size() ? sigmaArc(arcNo) : 1.), fileSigmaEpoch.readArc(arcNo), covFunction, C);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid CovarianceSst::decorrelate(UInt arcNo, const std::vector<Time> &times, const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    Double weight = 1./this->sigma;\n    if(sigmaArc.size() != 0)\n      weight *= 1./this->sigmaArc(arcNo);\n\n    // special case 1: diagonal matrix\n    // -------------------------------\n    if(fileNamesCovarianceMatrix.empty() && !covFunction.size() && !fileSigmaEpoch.arcCount())\n    {\n      for(MatrixSliceRef WA : A)\n        if(WA.size()) WA *= weight;\n      return;\n    }\n\n    // special case 2: diagonal matrix\n    // -------------------------------\n    if(fileNamesCovarianceMatrix.empty() && !covFunction.size())\n    {\n      ObservationSigmaArc sigmaEpoch = fileSigmaEpoch.readArc(arcNo);\n      for(UInt i=0; i<sigmaEpoch.size(); i++)\n        for(MatrixSliceRef WA : A)\n          if(WA.size()) WA.row(i) *= weight/sigmaEpoch.at(i).sigma;\n      return;\n    }\n\n    Matrix W = covariance(arcNo, times);\n    cholesky(W);\n\n    for(MatrixSliceRef WA : A)\n      if(WA.size())\n        triangularSolve(1., W.trans(), WA);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSliceRef CovarianceSst::covariance(const std::vector<Time> &times, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                                         const_MatrixSliceRef covFunction, Matrix &Cov)\n{\n  try\n  {\n    testInput(times, sigmaEpoch, covFunction, Cov);\n\n    if(!Cov.size())\n      Cov = Matrix(times.size(), Matrix::SYMMETRIC, Matrix::UPPER);\n\n    const Double sigma2 = pow(sigmaArc, 2);\n    if(covFunction.size())\n      for(UInt z=0; z<times.size(); z++)\n        for(UInt s=z; s<times.size(); s++)\n          Cov(z,s) += sigma2 * covFunction(s-z,1);\n\n    for(UInt i=0; i<sigmaEpoch.size(); i++)\n      Cov(i,i) += pow(sigmaEpoch.at(i).sigma,2);\n\n    return Cov;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSliceRef CovarianceSst::decorrelate(const std::vector<Time> &times, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                                          const_MatrixSliceRef covFunction, Matrix &W, const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    covariance(times, sigmaArc, sigmaEpoch, covFunction, W);\n    cholesky(W);\n\n    for(MatrixSliceRef WA : A)\n      if(WA.size())\n        triangularSolve(1., W.trans(), WA);\n\n    return W;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/covarianceSst.h",
    "content": "/***********************************************/\n/**\n* @file covarianceSst.h\n*\n* @brief Covariance matrix of satellite to satellite tracking observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-07-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_COVARIANCESST__\n#define __GROOPS_COVARIANCESST__\n\n// Latex documentation\n#ifdef DOCSTRING_CovarianceSst\nstatic const char *docstringCovarianceSst = R\"(\n\\section{CovarianceSst}\\label{covarianceSstType}\nProvides arc-wise covariance matrices for satellite-to-satellite observations (SST).\nThe \\configFile{inputfileCovarianceFunction}{matrix} provides a temporal covariance function.\nFrom it the Toeplitz covariance matrix is constructed\n\\begin{equation}\n  \\M C = \\begin{pmatrix}\n    cov(t_0) & cov(t_1) & \\cdots   &          &        &        \\\\\n    cov(t_1) & cov(t_0) & cov(t_1) & \\cdots   &        &        \\\\\n    \\cdots   & cov(t_1) & cov(t_0) & cov(t_1) & \\cdots &        \\\\\n             & \\cdots   & \\ddots   & \\ddots   & \\ddots & \\cdots \\\\\n  \\end{pmatrix} \\\\\n\\end{equation}\n\nThe complete covariance matrix of an arc is given by\n\\begin{equation}\n  \\M C_{arc} = \\sigma_0^2 \\sigma_{arc}^2 \\M C + \\sigma_{S,arc}^2 \\M S_{arc}+ \\text{diag}(\\sigma_1^2, \\sigma_2^2, \\ldots, \\sigma_n^2)\n\\end{equation}\nwhere \\config{sigma}~$\\sigma_0$ is an overall factor and the arc specific factors $\\sigma_{arc}$\ncan be provided with \\configFile{inputfileSigmasPerArc}{matrix}.\nThe second term describes general covariance matrices for each arc\n\\configFile{inputfileCovarianceMatrixArc}{matrix} together with the factors $\\sigma_{S,arc}$ from \\config{sigmasCovarianceMatrixArc}.\nThe last matrix can be used to downweight outliers in single epochs and will be added if\n\\configFile{inputfileSigmasPerEpoch}{instrument} is provided.\n\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n\n/**\n* @defgroup CovarianceSstGroup CovarianceSst\n* @brief Covariance function to decorrelate observation equations.\n* @ingroup miscGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass CovarianceSst;\ntypedef std::shared_ptr<CovarianceSst> CovarianceSstPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Covariance matrix of satellite to satellite observations. */\nclass CovarianceSst\n{\n  Double                sigma;\n  Vector                sigmaArc;\n  InstrumentFile        fileSigmaEpoch;\n  Matrix                covFunction;\n  std::vector<FileName> fileNamesCovarianceMatrix;\n  Vector                covMatrixSigmas;\n\n  static void testInput(const std::vector<Time> &times, const ObservationSigmaArc &sigmaEpoch, const_MatrixSliceRef covFunction, const_MatrixSliceRef W);\n\npublic:\n  /// Constructor\n  CovarianceSst() : sigma(1.0) {}\n\n  /// Constructor\n  CovarianceSst(Config &config, const std::string &name);\n\n  /// Destructor.\n  virtual ~CovarianceSst() {}\n\n  /** @brief Full variance covariance matrix. */\n  Matrix covariance(UInt arcNo, const std::vector<Time> &times);\n\n  /** @brief Decorrelates observation equations.\n  * The list of matrices, usually the observation vector and design matrices, are decorrelated. */\n  void decorrelate(UInt arcNo, const std::vector<Time> &times, const std::list<MatrixSlice> &A);\n\n  // --------------------\n\n  /** @brief Decorrelates observation equations.\n  * A list of matrices, usually the observation vector and design matrices, are decorrelated.\n  * additionally, the Cholesky decomposition of the complete covariance matrix is returned.\n  * @param times of the SST arcNo\n  * @param sigmaArc variance factor for the toeplitz covariance function of this arc\n  * @param sigmaEpoch Epoch-wise sigmas\n  * @param covFunction Toeplitz covariance function\n  * @param[in,out] Cov0 input: Empty or Non-Toeplitz covariance matrix for this arc. Output: Full covariance matrix.\n  * @return reference to @a Cov0 */\n  static MatrixSliceRef covariance(const std::vector<Time> &times, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                                   const_MatrixSliceRef covFunction, Matrix &Cov0);\n\n  /** @brief Decorrelates observation equations.\n  * A list of matrices, usually the observation vector and design matrices, are decorrelated.\n  * additionally, the Cholesky decomposition of the complete covariance matrix is returned.\n  * @param times of the SST arcNo\n  * @param sigmaArc variance factor for the toeplitz covariance function of this arc\n  * @param sigmaEpoch Epoch-wise sigmas\n  * @param covFunction Toeplitz covariance function\n  * @param[in,out] W input: Empty or Non-Toeplitz covariance matrix for this arc. Output: Cholesky decomposition of the full covariance matrix\n  * @param[in,out] A Matrices to be decorrelated\n  * @return reference to @a W */\n  static MatrixSliceRef decorrelate(const std::vector<Time> &times, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                                    const_MatrixSliceRef covFunction, Matrix &W, const std::list<MatrixSlice> &A);\n\n  /** @brief creates an derived instance of this class. */\n  static CovarianceSstPtr create(Config &config, const std::string &name) {return std::make_shared<CovarianceSst>(config, name);}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class CovarianceSst.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates CovarianceSst */\ntemplate<> Bool readConfig(Config &config, const std::string &name, CovarianceSstPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/observation/integralEquation.cpp",
    "content": "/***********************************************/\n/**\n* @file integralEquation.cpp\n*\n* @brief Functions for the (short arc) integral equation approach.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-02-24\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"integralEquation.h\"\n\n/***********************************************/\n\nIntegralEquation::IntegralEquation(UInt integrationDegree, UInt interpolationDegree)\n{\n  init(integrationDegree, interpolationDegree);\n}\n\n/***********************************************/\n\nvoid IntegralEquation::init(UInt integrationDegree, UInt interpolationDegree)\n{\n  try\n  {\n    this->interpolationDegree = interpolationDegree;\n    this->integrationDegree   = integrationDegree;\n    if(integrationDegree%2 == 0)\n      throw(Exception(\"polnomial degree for integration must be odd.\"));\n\n    // Es gibt grad Gleichungssysteme\n    // grad/2 am Anfang des Bahnbogens (es fehlen Punkte zum integrieren)\n    // grad/2 am Ende des Bahnbogens (es fehlen Punkte zum integrieren)\n    // 1 fuer den Rest des Bogens\n    W.resize(integrationDegree);\n\n    UInt half = (integrationDegree-1)/2;\n    for(UInt k=0; k<half; k++)\n    {\n      W.at(k) = Matrix(integrationDegree+1, integrationDegree+1);\n      for(UInt i=0; i<W.at(k).columns(); i++)\n        for(UInt n=0; n<W.at(k).rows(); n++)\n          W.at(k)(n,i) = ((n==0) ? 1.0 : pow(static_cast<Double>(i)-k, n));\n      inverse(W.at(k));\n    }\n\n    for(UInt k=0; k<=half; k++)\n    {\n      W.at(k+half) = Matrix(integrationDegree+1, integrationDegree+1);\n      for(UInt i=0; i<W.at(k+half).columns(); i++)\n        for(UInt n=0; n<W.at(k+half).rows(); n++)\n          W.at(k+half)(n,i) = ((n==0) ? 1.0 : pow(static_cast<Double>(i)-half-k, n));\n      inverse(W.at(k+half));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n/***********************************************/\n\nIntegralEquation::Arc  IntegralEquation::integrateArc(const OrbitArc &orbit, const std::vector<Rotary3d> &rotEarth, GravityfieldPtr gradientfield,\n                                                      const const_MatrixSlice &g, const const_MatrixSlice &accCalibration, Bool computeVelocity, Bool computeAcceleration) const\n{\n  try\n  {\n    UInt   posCount = orbit.size();\n    Double T        = (orbit.at(posCount-1).time - orbit.at(0).time).seconds();\n\n    // Gravitationsgradient = Tensor\n    // (im raumfesten System)\n    // -----------------------------\n    std::vector<Matrix> tensor(posCount);\n    for(UInt i=0; i<posCount; i++)\n    {\n      Time     time     = orbit.at(i).time;\n      Vector3d posEarth = rotEarth.at(i).rotate(orbit.at(i).position);\n      tensor.at(i)      = rotEarth.at(i).inverseRotate(gradientfield->gravityGradient(time, posEarth)).matrix();\n    }\n\n    Matrix A(3*posCount, 3*posCount + 6 + g.columns());\n    MatrixSlice VPos        (A.column(0,            3*posCount));\n    MatrixSlice VPosBoundary(A.column(3*posCount,   6));\n    MatrixSlice vPos        (A.column(3*posCount+6, g.columns()));\n\n    // Integral mit dem Kern K(tau, tau')\n    // und Drehung in das erdfeste System\n    // ----------------------------------\n    if(IntegrationPos.rows()!=3*posCount)\n      IntegrationPos = integrationMatrixPosition(T, posCount);\n    for(UInt i=0; i<posCount; i++)\n      matMult(1., IntegrationPos.slice(3, 3*i, 3*posCount-3, 3), rotEarth.at(i).matrix().trans(), VPos.slice(3, 3*i, 3*posCount-3, 3));\n\n    // Referenzpositionen und Randwerte\n    // --------------------------------\n    Vector   vBound(3*posCount);\n    Vector   vGpsPos(3*posCount);\n    Vector3d posStart = orbit.at(0).position;\n    Vector3d posEnd   = orbit.at(posCount-1).position;\n    for(UInt i=0; i<posCount; i++)\n    {\n      Double tau = static_cast<Double>(i)/(posCount-1.0);\n\n      vGpsPos(3*i+0) = orbit.at(i).position.x();\n      vGpsPos(3*i+1) = orbit.at(i).position.y();\n      vGpsPos(3*i+2) = orbit.at(i).position.z();\n\n      vBound(3*i+0) = (1-tau) * posStart.x() + tau * posEnd.x();\n      vBound(3*i+1) = (1-tau) * posStart.y() + tau * posEnd.y();\n      vBound(3*i+2) = (1-tau) * posStart.z() + tau * posEnd.z();\n    }\n\n    // Referenzbeschleunigungen integrieren\n    // Reference = (Gravity*g-(vPos-vBound))\n    // -------------------------------------\n    matMult(1., VPos, g, vPos);\n    vBound -= vGpsPos;\n    for(UInt j=0; j<g.columns(); j++)\n      vPos.column(j) += vBound;\n\n    // partielle Ableitungen nach den Randwerten berechnen (Boundary)\n    // --------------------------------------------------------------\n    for(UInt i=0; i<posCount; i++)\n    {\n      Double tau = i/(posCount-1.0);\n      VPosBoundary(3*i+0, 0) = VPosBoundary(3*i+1, 1) = VPosBoundary(3*i+2, 2) = (1-tau); // r_anf\n      VPosBoundary(3*i+0, 3) = VPosBoundary(3*i+1, 4) = VPosBoundary(3*i+2, 5) = tau;     // r_end\n    }\n\n    // Indirekten Effekt beruecksichtigen\n    // (Aenderung der Position aendert die Feldstaerke entlang der Bahn)\n    // (I-K*tensor)^-1\n    // ----------------------------\n    // Einheitsmatrix\n    Matrix Inv(3*posCount, 3*posCount);\n    for(UInt i=0; i<Inv.rows(); i++)\n      Inv(i,i) = 1.0;\n    // I +- K*Tensor\n    for(UInt i=0; i<posCount; i++)\n      matMult(-1., IntegrationPos.slice(3,3*i,3*posCount-3,3), tensor.at(i), Inv.slice(3,3*i,3*posCount-3,3));\n\n    // (I-K*tensor)^-1(Gravity*g+vBound-vPos)+pos\n    // wobei A = (Gravity, Boundary, Reference)\n    // und Reference = (IntegrationPos*g+Randwerte-pos)\n    // ------------------------------------------------\n    solveInPlace(Inv, A);\n\n    // Referenzpositionen\n    // Reference = (I-K*tensor)^-1(Gravity*g+vBound-vPos)+pos\n    // --------------------\n    Matrix vDeltaPos = vPos;\n    for(UInt j=0; j<vPos.columns(); j++)\n      vPos.column(j) += vGpsPos;\n\n    Arc arc;\n    arc.vPos         = vPos;\n    arc.VPos         = VPos;\n    arc.VPosBoundary = VPosBoundary;\n\n    // =============================================================================\n\n    // Beobachtungsgleichungen für Vektorielle Beschleunigungen aus Beschleunigungen\n    // -----------------------------------------------------------------------------\n    if(computeVelocity || computeAcceleration)\n    {\n      arc.VAcc = Matrix(3*posCount, 3*posCount);\n      // gedrehte Einheitsmatrix\n      for(UInt i=0; i<posCount; i++)\n        copy(rotEarth.at(i).matrix().trans(), arc.VAcc.slice(3*i,3*i,3,3));\n\n      // Referenzbeschleuigungen\n      // -----------------------\n      arc.vAcc = arc.VAcc * g;\n\n      // indirekter Effekt\n      for(UInt i=0; i<posCount; i++)\n        matMult(1., tensor.at(i), vDeltaPos.row(3*i,3), arc.vAcc.row(3*i,3));\n\n      // indirekter Effekt\n      // -----------------\n      for(UInt i=0; i<posCount; i++)\n        matMult(1., tensor.at(i), arc.VPos.row(3*i,3), arc.VAcc.row(3*i,3));\n\n      // Randwerte (nur indirekter Effekt)\n      // ---------------------------------\n      arc.VAccBoundary = Matrix(3*posCount, 6);\n      for(UInt i=0; i<posCount; i++)\n        matMult(1., tensor.at(i), arc.VPosBoundary.row(3*i,3), arc.VAccBoundary.row(3*i,3));\n    }\n\n    // =============================================================================\n\n    // Beobachtungsgleichungen für Vektorielle Geschwindigkeiten aus Beschleunigungen\n    // ------------------------------------------------------------------------------\n    if(computeVelocity)\n    {\n      // Integral mit dem Kern (d/dt K(tau, tau'))\n      if(IntegrationVel.rows()!=3*posCount)\n        IntegrationVel = integrationMatrixVelocity(T, posCount);\n      arc.VVel = IntegrationVel * arc.VAcc;\n\n      // Randwerte\n      // ---------\n      arc.VVelBoundary = Matrix(3*posCount, 6);\n      for(UInt i=0; i<posCount; i++)\n      {\n        arc.VVelBoundary(3*i+0, 0) = arc.VVelBoundary(3*i+1, 1) = arc.VVelBoundary(3*i+2, 2) = -1/T; // r_anf\n        arc.VVelBoundary(3*i+0, 3) = arc.VVelBoundary(3*i+1, 4) = arc.VVelBoundary(3*i+2, 5) =  1/T; // r_end\n      }\n\n      // indirekter Effekt\n      matMult(1., IntegrationVel, arc.VAccBoundary, arc.VVelBoundary);\n\n      // Referenzgeschwindigkeiten\n      // -------------------------\n      arc.vVel = IntegrationVel * arc.vAcc;\n\n        // Randwerte - pos\n      for(UInt i=0; i<posCount; i++)\n        for(UInt j=0; j<arc.vVel.columns(); j++)\n        {\n          arc.vVel(3*i+0,j) += (arc.vPos(3*posCount-3,j) - arc.vPos(0,j))/T; //(1/T) * pos1End.x() - (1/T) * pos1Start.x();\n          arc.vVel(3*i+1,j) += (arc.vPos(3*posCount-2,j) - arc.vPos(1,j))/T; //(1/T) * pos1End.y() - (1/T) * pos1Start.y();\n          arc.vVel(3*i+2,j) += (arc.vPos(3*posCount-1,j) - arc.vPos(2,j))/T; //(1/T) * pos1End.z() - (1/T) * pos1Start.z();\n        }\n    }\n\n    // =============================================================================\n\n    // Fit integrated orbit to given orbit\n    // -----------------------------------\n    Matrix B(3*posCount, 6+accCalibration.columns());\n    copy(VPosBoundary, B.column(0,6));\n    if(accCalibration.size())\n      matMult(1., VPos, accCalibration, B.column(6,accCalibration.columns()));\n    Vector x = leastSquares(B, vDeltaPos);\n\n    if(arc.vPos.size()) matMult(-1, arc.VPosBoundary, x.row(0,6), arc.vPos);\n    if(arc.vVel.size()) matMult(-1, arc.VVelBoundary, x.row(0,6), arc.vVel);\n    if(arc.vAcc.size()) matMult(-1, arc.VAccBoundary, x.row(0,6), arc.vAcc);\n\n    if(accCalibration.size())\n    {\n      Vector y = accCalibration*x.row(6,accCalibration.columns());\n      if(arc.vPos.size()) matMult(-1, arc.VPos, y, arc.vPos);\n      if(arc.vVel.size()) matMult(-1, arc.VVel, y, arc.vVel);\n      if(arc.vAcc.size()) matMult(-1, arc.VAcc, y, arc.vAcc);\n    }\n\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// interpolate to observations times\n// ---------------------------------\nvoid IntegralEquation::interpolateArc(const std::vector<OrbitArc> &pod, const OrbitArc &orbit, const Arc &arc, Matrix &l, Matrix &VPos, Matrix &VPosBoundary) const\n{\n  try\n  {\n    // observations\n    l = Matrix(3*pod.at(0).size(), arc.vPos.columns());\n    for(UInt j=0; j<l.columns(); j++)\n      for(UInt k=0; k<pod.at(j).size(); k++)\n      {\n        l(3*k+0,j) = pod.at(j).at(k).position.x();\n        l(3*k+1,j) = pod.at(j).at(k).position.y();\n        l(3*k+2,j) = pod.at(j).at(k).position.z();\n      }\n\n    Polynomial polynomial(orbit.times(), interpolationDegree);\n    auto timesPod = pod.at(0).times();\n    l            -= polynomial.interpolate(timesPod, arc.vPos,         3);\n    VPos          = polynomial.interpolate(timesPod, arc.VPos,         3);\n    VPosBoundary  = polynomial.interpolate(timesPod, arc.VPosBoundary, 3);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nMatrix IntegralEquation::integrationMatrixPosition(Double T, UInt posCount) const\n{\n  try\n  {\n    Matrix D(3*posCount, 3*posCount);\n    UInt   unt = posCount-1;    // Anzahl Integrationsintervalle\n    UInt   integrationDegree = W.size();\n\n    for(UInt i=1; i<posCount-1; i++)\n    {\n      Double tau = i/static_cast<Double>(unt);\n      Vector factor(posCount);\n\n      UInt nr        = 0;\n      UInt nullpunkt = 0;\n\n      for(UInt k=0; k<unt; k++)    // Integrationsintervall\n      {\n        for(UInt j=0; j<W.at(nr).columns(); j++) // Position im Interpolationspolynom\n          for(UInt n=0; n<W.at(nr).rows(); n++)  // Grad im Interpolationspolynoms\n            if(i>k)\n              factor(k+j-nullpunkt) += -T*T/(unt*unt) * (1-tau) * (1./(n+2.) + k /(n+1.))      * W.at(nr)(j,n);\n            else\n              factor(k+j-nullpunkt) +=  T*T/(unt*unt) *   tau *   (1./(n+2.) - (unt-k)/(n+1.)) * W.at(nr)(j,n);\n\n        // Polynommatrix auswaehlen\n        if(k<integrationDegree/2)\n          nr++, nullpunkt++;\n        if(k>=unt-integrationDegree/2-1)\n          nr++, nullpunkt++;\n      }\n\n      for(UInt k=0; k<posCount; k++)\n        D(3*i+0,3*k+0) = D(3*i+1,3*k+1) = D(3*i+2,3*k+2) = factor(k);\n    }\n    return D;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix IntegralEquation::integrationMatrixVelocity(Double T, UInt posCount) const\n{\n  try\n  {\n    Matrix D(3*posCount, 3*posCount);\n    UInt   unt = posCount-1;    // Anzahl Integrationsintervalle\n    UInt   integrationDegree = W.size();\n\n    for(UInt i=0; i<posCount; i++)\n    {\n      Vector factor(posCount);\n\n      UInt nr        = 0;\n      UInt nullpunkt = 0;\n\n      for(UInt k=0; k<unt; k++)    // Integrationsintervall\n      {\n        for(UInt j=0; j<W.at(nr).columns(); j++) // Position im Interpolationspolynom\n          for(UInt n=0; n<W.at(nr).rows(); n++)  // Grad im Interpolationspolynoms\n            if(i>k)\n              factor(k+j-nullpunkt) += T/(unt*unt) * (1./(n+2.) + k /(n+1.))      * W.at(nr)(j,n);\n            else\n              factor(k+j-nullpunkt) += T/(unt*unt) * (1./(n+2.) - (unt-k)/(n+1.)) * W.at(nr)(j,n);\n\n        // Polynommatrix auswaehlen\n        if(k<integrationDegree/2)\n          nr++, nullpunkt++;\n        if(k>=unt-integrationDegree/2-1)\n          nr++, nullpunkt++;\n      }\n\n      for(UInt k=0; k<posCount; k++)\n        D(3*i+0,3*k+0) = D(3*i+1,3*k+1) = D(3*i+2,3*k+2) = factor(k);\n    }\n    return D;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/integralEquation.h",
    "content": "/***********************************************/\n/**\n* @file integralEquation.h\n*\n* @brief Functions for the (short arc) integral equation approach.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-02-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_INTEGRALEQUATION__\n#define __GROOPS_INTEGRALEQUATION__\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Functions for the (short arc) integral equation approach.\n* @ingroup miscGroup */\nclass IntegralEquation\n{\n  UInt                integrationDegree, interpolationDegree;\n  std::vector<Matrix> W;\n  mutable Matrix      IntegrationPos;\n  mutable Matrix      IntegrationVel;\n\npublic:\n\n  /** @brief Linearized observation equations for an arc. */\n  class Arc\n  {\n    public:\n    Matrix vPos;         //!< Reference positions computed with a force model.\n    Matrix VPos;         //!< Design matrix, partial derivatives of positions with respect to specific forces in TRF.\n    Matrix VPosBoundary; //!< Design matrix, partial derivatives of positions with respect to satellite state (boundary values).\n\n    Matrix vVel;         //!< Reference velocities computed with a force model.\n    Matrix VVel;         //!< Design matrix, partial derivatives of velocities with respect to specific forces in TRF.\n    Matrix VVelBoundary; //!< Design matrix, partial derivatives of velocities with respect to satellite state (boundary values).\n\n    Matrix vAcc;         //!< Reference accelerations computed with a force model.\n    Matrix VAcc;         //!< Design matrix, partial derivatives of accelerations with respect to specific forces in TRF.\n    Matrix VAccBoundary; //!< Design matrix, partial derivatives of accelerations with respect to satellite state (boundary values).\n  };\n\n/** @brief Constructor.\n* @param integrationDegree Degree of polynomial used for integration.\n* @param interpolationDegree Degree of polynomial used for interpolation. */\nIntegralEquation(UInt integrationDegree=7, UInt interpolationDegree=7);\n\n/** @brief Initialization.\n* @param integrationDegree Degree of polynomial used for integration.\n* @param interpolationDegree Degree of polynomial used for interpolation. */\nvoid init(UInt integrationDegree=7, UInt interpolationDegree=7);\n\n/** @brief Observation equations for positions, velocities, and accelerations.\n* @param orbit Approximate positions.\n* @param rotEarth Rotation matricies CRF -> TRF at each epoch.\n* @param gradientfield Gravity field for indirect effect (gravity gradients)\n* @param g Approcimate specific forces along the orbit (x,y,z per position) in CRF; Multiple columns for multiple right hand sides are possible.\n* @param accCalibration Observation equations for emprical accealrations (Allowed to be empty).\n* @param computeVelocity Compute observation equations for velocities additionally to positions?\n* @param computeAcceleration Compute observation equations for accelerations additionally to positions? */\nArc integrateArc(const OrbitArc &orbit, const std::vector<Rotary3d> &rotEarth, GravityfieldPtr gradientfield,\n                 const const_MatrixSlice &g, const const_MatrixSlice &accCalibration, Bool computeVelocity=FALSE, Bool computeAcceleration=FALSE) const;\n\n/** @brief Interpolate arc at observation (pod) times.\n* @param pod         kinematic positions as pseudo observations (for each right hand side).\n* @param orbit       positions that be used to compute the arc with integrateArc.\n* @param arc         computed with integrateArc.\n* @param[out] l      reduced observation vector.\n* @param[out] VPos   design matrix of the unknown forces.\n* @param[out] VPosBoundary design matrix of the unknown satellite state. */\nvoid interpolateArc(const std::vector<OrbitArc> &pod, const OrbitArc &orbit, const Arc &arc, Matrix &l, Matrix &VPos, Matrix &VPosBoundary) const;\n\n/** @brief Partial derivatives of positions (in CRF) with respect to specific forces (in CRF).\n* Integration of forces with the integral kernel.\n* @param T Arc length in seconds.\n* @param posCount Number of positions (uniformly distributed). */\nMatrix integrationMatrixPosition(Double T, UInt posCount) const;\n\n/** @brief Partial derivatives of velocities (in CRF) with respect to specific forces (in CRF).\n* Integration of forces with the integral kernel.\n* @param T Arc length in seconds.\n* @param posCount Number of positions (uniformly distributed). */\nMatrix integrationMatrixVelocity(Double T, UInt posCount) const;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/observation/observationMisc.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMisc.cpp\n*\n* @brief Right hand sides and calibration parameter.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-07-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PodRightSide\n#define DOCSTRING_SstRightSide\n#define DOCSTRING_SggRightSide\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/miscAccelerations/miscAccelerations.h\"\n#include \"observationMisc.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(PodRightSide, \"podRightSideType\")\nGROOPS_READCONFIG_CLASS(PodRightSide, \"podRightSideType\")\n\nPodRightSide::PodRightSide(Config &config, const std::string &name)\n{\n  try\n  {\n    FileName orbitName, accName;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",         orbitName, Config::MUSTSET,  \"\", \"kinematic positions of satellite as observations\");\n    readConfig(config, \"inputfileAccelerometer\", accName,   Config::OPTIONAL, \"\", \"non-gravitational forces in satellite reference frame\");\n    readConfig(config, \"forces\",                 forces,    Config::MUSTSET,  \"\", \"\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    orbitFile         = InstrumentFile::newFile(orbitName);\n    accelerometerFile = InstrumentFile::newFile(accName);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(SstRightSide, \"sstRightSideType\")\nGROOPS_READCONFIG_CLASS(SstRightSide, \"sstRightSideType\")\n\nSstRightSide::SstRightSide(Config &config, const std::string &name)\n{\n  try\n  {\n    std::vector<FileName> sstName;\n    FileName              orbit1Name, acc1Name;\n    FileName              orbit2Name, acc2Name;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileSatelliteTracking\", sstName,      Config::OPTIONAL, \"\", \"ranging observations and corrections\");\n    readConfig(config, \"inputfileOrbit1\",            orbit1Name,   Config::OPTIONAL, \"\", \"kinematic positions of satellite A as observations\");\n    readConfig(config, \"inputfileOrbit2\",            orbit2Name,   Config::OPTIONAL, \"\", \"kinematic positions of satellite B as observations\");\n    readConfig(config, \"inputfileAccelerometer1\",    acc1Name,     Config::OPTIONAL, \"\", \"non-gravitational forces in satellite reference frame A\");\n    readConfig(config, \"inputfileAccelerometer2\",    acc2Name,     Config::OPTIONAL, \"\", \"non-gravitational forces in satellite reference frame B\");\n    readConfig(config, \"forces\",                     forces,       Config::MUSTSET,  \"\", \"\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    sstFile.resize(sstName.size());\n    for(UInt i=0; i<sstName.size(); i++)\n      sstFile.at(i) = InstrumentFile::newFile(sstName.at(i));\n    orbit1File = InstrumentFile::newFile(orbit1Name);\n    orbit2File = InstrumentFile::newFile(orbit2Name);\n    accelerometer1File  = InstrumentFile::newFile(acc1Name);\n    accelerometer2File  = InstrumentFile::newFile(acc2Name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(SggRightSide, \"sggRightSideType\")\nGROOPS_READCONFIG_CLASS(SggRightSide, \"sggRightSideType\")\n\nSggRightSide::SggRightSide(Config &config, const std::string &name)\n{\n  try\n  {\n    FileName              fileNameGradiometer;\n    std::vector<FileName> fileNameReference;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileGradiometer\",          fileNameGradiometer, Config::MUSTSET,  \"\", \"observed gravity gradients\");\n    readConfig(config, \"inputfileReferenceGradiometer\", fileNameReference,   Config::OPTIONAL, \"\", \"precomputed gradients at orbit positions\");\n    readConfig(config, \"referencefield\",                referencefield,      Config::DEFAULT,  \"\", \"\");\n    readConfig(config, \"tides\",                         tides,               Config::DEFAULT,  \"\", \"\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    gradiometerFile = InstrumentFile::newFile(fileNameGradiometer);\n    referenceFile.resize(fileNameReference.size());\n    for(UInt i=0; i<fileNameReference.size(); i++)\n      referenceFile.at(i) = InstrumentFile::newFile(fileNameReference.at(i));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMisc.h",
    "content": "/***********************************************/\n/**\n* @file observationMisc.h\n*\n* @brief Right hand sides.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-07-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMISC__\n#define __GROOPS_OBSERVATIONMISC__\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/forces/forces.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/** @addtogroup miscGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_PodRightSide\nstatic const char *docstringPodRightSide = R\"(\n\\section{PodRightSide}\\label{podRightSideType}\nObservation vector for precise orbit data (POD) of \\configClass{observation}{observationType}\nequations in a least squares adjustment. The observations are reduced by the effect of\n\\configFile{inputfileAccelerometer}{instrument} and \\configClass{forces}{forcesType}\n(observed minus computed).\n)\";\n#endif\n\nclass PodRightSide;\ntypedef std::shared_ptr<PodRightSide> PodRightSidePtr;\n\n/** @brief Input for observation vectors (precise orbit data, POD). */\nclass PodRightSide\n{\npublic:\n  InstrumentFilePtr orbitFile;\n  InstrumentFilePtr accelerometerFile;\n  ForcesPtr         forces;\n\n  /// Constructor\n  PodRightSide(Config &config, const std::string &name);\n\n  /** @brief creates an derived instance of this class. */\n  static PodRightSidePtr create(Config &config, const std::string &name) {return PodRightSidePtr(new PodRightSide(config, name));}\n};\n\n/** @brief Creates a class PodRightSide.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PodRightSide */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PodRightSidePtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_SstRightSide\nstatic const char *docstringSstRightSide = R\"(\n\\section{SstRightSide}\\label{sstRightSideType}\nObservation vector for GRACE like data (satellite-tracking and precise orbit data (POD))\nof \\configClass{observation}{observationType} equations in a least squares adjustment.\nThe observations are reduced by the effect of \\configFile{inputfileAccelerometer}{instrument}\nand \\configClass{forces}{forcesType} (observed minus computed).\n)\";\n#endif\n\nclass SstRightSide;\ntypedef std::shared_ptr<SstRightSide> SstRightSidePtr;\n\n/** @brief Input for observation vectors (GRACE POD and KBR data). */\nclass SstRightSide\n{\npublic:\n  std::vector<InstrumentFilePtr> sstFile;\n  InstrumentFilePtr              orbit1File, orbit2File;\n  InstrumentFilePtr              accelerometer1File, accelerometer2File;\n  ForcesPtr                      forces;\n\n  /// Constructor\n  SstRightSide(Config &config, const std::string &name);\n\n  /** @brief creates an derived instance of this class. */\n  static SstRightSidePtr create(Config &config, const std::string &name) {return SstRightSidePtr(new SstRightSide(config, name));}\n};\n\n/** @brief Creates a class SstRightSide.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SstRightSide */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SstRightSidePtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_SggRightSide\nstatic const char *docstringSggRightSide = R\"(\n\\section{SggRightSide}\\label{sggRightSideType}\nObservation vector for gradiometer data (satellite gravity gradiometry, SGG)\nof \\configClass{observation}{observationType} equations in a least squares adjustment.\nThe observations are reduced by an \\configFile{inputfileReferenceGradiometer}{instrument},\nthe effect of \\configClass{referencefield}{gravityfieldType}, and \\configClass{tides}{tidesType}\n(observed minus computed).\n\nThe reference gradiometer data can be precomputed with \\program{SimulateGradiometer}.\n)\";\n#endif\n\nclass SggRightSide;\ntypedef std::shared_ptr<SggRightSide> SggRightSidePtr;\n\n/** @brief Input for observation vectors (GOCE SGG). */\nclass SggRightSide\n{\npublic:\n  InstrumentFilePtr              gradiometerFile;\n  std::vector<InstrumentFilePtr> referenceFile;\n  GravityfieldPtr                referencefield;\n  TidesPtr                       tides;\n\n  /// Constructor\n  SggRightSide(Config &config, const std::string &name);\n\n  /** @brief creates an derived instance of this class. */\n  static SggRightSidePtr create(Config &config, const std::string &name) {return SggRightSidePtr(new SggRightSide(config, name));}\n};\n\n/** @brief Creates a class SggRightSide.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SggRightSide */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SggRightSidePtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_OBSERVATIONMISC__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscDualSstVariational.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscDualSstVariational.cpp\n*\n* @brief Satellite to satellite tracking (Variational equations).\n*\n* @author Andreas Kvas\n* @date 2019-11-22\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"misc/observation/variationalEquation.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"observationMiscDualSstVariational.h\"\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationMiscDualSstVariationalPtr &observation, Config::Appearance mustSet, const std::string &/*defaultValue*/, const std::string &/*annotation*/)\n{\n  try\n  {\n//     if(isCreateSchema(config))\n//     {\n//       config.xselement(name, ObservationMiscSst::typeName(), mustSet, Config::ONCE, \"\", annotation);\n//       return FALSE;\n//     }\n\n    if(!hasName(config, name, mustSet))\n      return FALSE;\n    observation = ObservationMiscDualSstVariational::create(config, name);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscDualSstVariationalPtr ObservationMiscDualSstVariational::create(Config &config, const std::string &name)\n{\n  try\n  {\n    ObservationMiscDualSstVariationalPtr observation;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"obervation equations (Sst)\");\n    if(readConfigChoiceElement(config, \"dualSstVariational\", type, \"two SST observations\"))\n      observation = ObservationMiscDualSstVariationalPtr(new ObservationMiscDualSstVariational(config));\n    endChoice(config);\n\n    return observation;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscDualSstVariational::ObservationMiscDualSstVariational(Config &config)\n{\n  try\n  {\n    std::vector<FileName> fileNameSst1, fileNameSst2;\n    FileName              fileNamePod1, fileNamePod2;\n    FileName              fileNameVariational1, fileNameVariational2;\n    UInt                  integrationDegree;\n    sstType = 1;\n\n    if(readConfigSequence(config, \"rightHandSide\", Config::MUSTSET, \"\", \"input for observation vectors\"))\n    {\n      readConfig(config, \"inputfileSatelliteTracking1\", fileNameSst1, Config::MUSTSET,  \"\", \"ranging observations and corrections\");\n      readConfig(config, \"inputfileSatelliteTracking2\", fileNameSst2, Config::MUSTSET,  \"\", \"ranging observations and corrections\");\n      readConfig(config, \"inputfileOrbit1\",             fileNamePod1, Config::OPTIONAL, \"\", \"kinematic positions of satellite A as observations\");\n      readConfig(config, \"inputfileOrbit2\",             fileNamePod2, Config::OPTIONAL, \"\", \"kinematic positions of satellite B as observations\");\n      endSequence(config);\n    }\n    std::string choice;\n    if(readConfigChoice(config, \"sstType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"range\",     choice, \"\")) sstType = 0;\n      if(readConfigChoiceElement(config, \"rangeRate\", choice, \"\")) sstType = 1;\n      if(readConfigChoiceElement(config, \"none\",      choice, \"\")) sstType = 99;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileVariational1\",        fileNameVariational1,   Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"inputfileVariational2\",        fileNameVariational2,   Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"ephemerides\",                  ephemerides,            Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationGravity\",       parameterGravity,       Config::DEFAULT,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration1\", parameterAcceleration1, Config::DEFAULT,  \"\",    \"orbit1 force parameters\");\n    readConfig(config, \"parametrizationAcceleration2\", parameterAcceleration2, Config::DEFAULT,  \"\",    \"orbit2 force parameters\");\n    readConfig(config, \"parametrizationSst1\",          parameterSst1,          Config::DEFAULT,  \"\",    \"satellite tracking parameter for first ranging observations\");\n    readConfig(config, \"parametrizationSst2\",          parameterSst2,          Config::DEFAULT,  \"\",    \"satellite tracking parameter for second ranging observations\");\n    readConfig(config, \"integrationDegree\",            integrationDegree,      Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",          interpolationDegree,    Config::DEFAULT,  \"7\",   \"orbit interpolation by polynomial approximation of degree n\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    // init\n    // ----\n    sst1File.resize(fileNameSst1.size());\n    for(UInt i=0; i<fileNameSst1.size(); i++)\n      sst1File.at(i) = InstrumentFile::newFile(fileNameSst1.at(i));\n    sst2File.resize(fileNameSst2.size());\n    for(UInt i=0; i<fileNameSst2.size(); i++)\n      sst2File.at(i) = InstrumentFile::newFile(fileNameSst2.at(i));\n    pod1File.open(fileNamePod1);\n    pod2File.open(fileNamePod2);\n\n    // test instrument files\n    // ---------------------\n    for(UInt i=1; i<sst1File.size(); i++)\n      InstrumentFile::checkArcCount({*sst1File.at(i), *sst1File.at(0)});\n    for(UInt i=0; i<sst2File.size(); i++)\n      InstrumentFile::checkArcCount({*sst2File.at(i), *sst1File.at(0)});\n    if(sst1File.size())\n      InstrumentFile::checkArcCount({pod1File, *sst1File.at(0)});\n    InstrumentFile::checkArcCount({pod2File, pod1File});\n\n    countArc = std::max(pod1File.arcCount(), pod2File.arcCount());\n    if(sst1File.size()) countArc = std::max(countArc, sst1File.at(0)->arcCount());\n    if(sst2File.size()) countArc = std::max(countArc, sst2File.at(0)->arcCount());\n    computeVelocity = (sstType==1);\n\n    variationalEquation1.open(fileNameVariational1, parameterGravity, parameterAcceleration1, std::vector<Time>(), ephemerides, integrationDegree);\n    variationalEquation2.open(fileNameVariational2, parameterGravity, parameterAcceleration2, std::vector<Time>(), ephemerides, integrationDegree);\n\n    // =======================\n\n    // count parameters\n    // ----------------\n    gravityCount = variationalEquation1.parameterCountGravity();\n    state1Count  = variationalEquation1.parameterCount() - gravityCount;\n    state2Count  = variationalEquation2.parameterCount() - gravityCount;\n\n    countAParameter = 0;\n    idxGravity  = countAParameter; countAParameter += gravityCount;\n    idxState1   = countAParameter; countAParameter += state1Count;\n    idxState2   = countAParameter; countAParameter += state2Count;\n    idxSst1Para = countAParameter; countAParameter += parameterSst1->parameterCount();\n    idxSst2Para = countAParameter; countAParameter += parameterSst2->parameterCount();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ObservationMiscDualSstVariational::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    change = parameterGravity->setInterval(timeStart, timeEnd)       || change;\n    change = parameterAcceleration1->setInterval(timeStart, timeEnd) || change;\n    change = parameterAcceleration2->setInterval(timeStart, timeEnd) || change;\n    change = parameterSst1->setInterval(timeStart, timeEnd)          || change;\n    change = parameterSst2->setInterval(timeStart, timeEnd)          || change;\n    if(!change)\n      return FALSE;\n    variationalEquation1.computeIndices();\n    variationalEquation2.computeIndices();\n\n    // count parameters\n    // ----------------\n    gravityCount = variationalEquation1.parameterCountGravity();\n    state1Count  = variationalEquation1.parameterCount() - gravityCount;\n    state2Count  = variationalEquation2.parameterCount() - gravityCount;\n\n    countAParameter = 0;\n    idxGravity  = countAParameter; countAParameter += gravityCount;\n    idxState1   = countAParameter; countAParameter += state1Count;\n    idxState2   = countAParameter; countAParameter += state2Count;\n    idxSst1Para = countAParameter; countAParameter += parameterSst1->parameterCount();\n    idxSst2Para = countAParameter; countAParameter += parameterSst2->parameterCount();\n\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscDualSstVariational::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    parameterGravity->parameterName(name);\n\n    std::vector<ParameterName> name1;\n    variationalEquation1.parameterName(name1);\n    const std::string satelliteName1 = variationalEquation1.satellite() ? variationalEquation1.satellite()->satelliteName : \"satellite1\";\n    for(UInt i=gravityCount; i<name1.size(); i++)\n    {\n      name1.at(i).object = satelliteName1;\n      name.push_back(name1.at(i));\n    }\n\n    std::vector<ParameterName> name2;\n    variationalEquation2.parameterName(name2);\n    const std::string satelliteName2 = variationalEquation2.satellite() ? variationalEquation2.satellite()->satelliteName : \"satellite2\";\n    for(UInt i=gravityCount; i<name2.size(); i++)\n    {\n      name2.at(i).object = satelliteName2;\n      name.push_back(name2.at(i));\n    }\n\n    parameterSst1->parameterName(name);\n    for(UInt i=name.size()-parameterSst1->parameterCount(); i<name.size(); i++)\n      name.at(i).object = satelliteName1+\".\"+satelliteName2;\n\n    parameterSst2->parameterName(name);\n    for(UInt i=name.size()-parameterSst2->parameterCount(); i<name.size(); i++)\n      name.at(i).object = satelliteName1+\".\"+satelliteName2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscDualSstVariational::Arc ObservationMiscDualSstVariational::computeArc(UInt arcNo, CovarianceSstPtr covSst1, CovarianceSstPtr covSst2, CovarianceSstPtr covAcc,\n                                                                                     CovariancePodPtr covPod1, CovariancePodPtr covPod2)\n{\n  try\n  {\n    // read SST observations\n    // ---------------------\n    std::vector<SatelliteTrackingArc> sst1(sst1File.size());\n    for(UInt k=0; k<sst1File.size(); k++)\n      sst1.at(k) = sst1File.at(k)->readArc(arcNo);\n    for(UInt k=1; k<sst1.size(); k++)\n      ::Arc::checkSynchronized({sst1.at(0), sst1.at(k)});\n    const std::vector<Time> timesSst1 = (sst1.size() && (sstType!=99)) ? sst1.at(0).times() : std::vector<Time>();\n\n    std::vector<SatelliteTrackingArc> sst2(sst2File.size());\n    for(UInt k=0; k<sst2File.size(); k++)\n      sst2.at(k) = sst2File.at(k)->readArc(arcNo);\n    for(UInt k=1; k<sst2.size(); k++)\n      ::Arc::checkSynchronized({sst2.at(0), sst2.at(k)});\n    const std::vector<Time> timesSst2 = (sst2.size() && (sstType!=99)) ? sst2.at(0).times() : std::vector<Time>();\n\n    // read POD observations\n    // ---------------------\n    OrbitArc pod1 = pod1File.readArc(arcNo);\n    OrbitArc pod2 = pod2File.readArc(arcNo);\n    const std::vector<Time> timesPod1 = pod1.times();\n    const std::vector<Time> timesPod2 = pod2.times();\n\n    // =============================================\n\n    // Init variational equations\n    // --------------------------\n    Time timeStart(std::numeric_limits<Int>::max(), 0), timeEnd;\n    if(timesSst1.size()) {timeStart = std::min(timeStart, timesSst1.front()); timeEnd = std::max(timeEnd, timesSst1.back());}\n    if(timesSst2.size()) {timeStart = std::min(timeStart, timesSst2.front()); timeEnd = std::max(timeEnd, timesSst2.back());}\n    if(timesPod1.size()) {timeStart = std::min(timeStart, timesPod1.front()); timeEnd = std::max(timeEnd, timesPod1.back());}\n    if(timesPod2.size()) {timeStart = std::min(timeStart, timesPod2.front()); timeEnd = std::max(timeEnd, timesPod2.back());}\n    const VariationalEquationArc &arc1 = variationalEquation1.getArc(timeStart);\n    const VariationalEquationArc &arc2 = variationalEquation2.getArc(timeStart);\n\n    if((arc1.times != arc2.times) || (timeStart < arc1.times.front()) || (arc1.times.back() < timeEnd))\n      throw(Exception(\"no variational arc found for [\"+timeStart.dateTimeStr()+\", \"+timeEnd.dateTimeStr()+\"]\"));\n\n    // integration times (and interpolation intervals inbetween)\n    auto iterStart = std::upper_bound(arc1.times.begin(), arc1.times.end(), timeStart)-1;\n    auto iterEnd   = std::lower_bound(arc1.times.begin(), arc1.times.end(), timeEnd)+1;\n    std::vector<Time> times;\n    std::copy(iterStart, iterEnd, std::back_inserter(times));\n\n    // count observations and calculate index\n    // --------------------------------------\n    UInt obsCount = 0;\n    const UInt idxSst1 = obsCount; obsCount += timesSst1.size();\n    const UInt idxSst2 = obsCount; obsCount += timesSst2.size();\n    const UInt idxPod1 = obsCount; obsCount += 3*timesPod1.size();\n    const UInt idxPod2 = obsCount; obsCount += 3*timesPod2.size();\n\n    // arc related parameters (in matrix B)\n    // ------------------------------------\n    if(timesSst1.size()) parameterSst1->setIntervalArc(timesSst1.front(), timesSst1.back()+medianSampling(timesSst1));\n    if(timesSst2.size()) parameterSst2->setIntervalArc(timesSst2.front(), timesSst2.back()+medianSampling(timesSst2));\n    UInt countBParameter = 0;\n    const UInt idxSst1ParaArc = countBParameter; countBParameter += parameterSst1->parameterCountArc();\n    const UInt idxSst2ParaArc = countBParameter; countBParameter += parameterSst2->parameterCountArc();\n    if(obsCount <= countBParameter)\n      return Arc();\n\n    Matrix l(obsCount, 1);\n    Matrix A(obsCount, countAParameter);\n    Matrix B(obsCount, countBParameter);\n\n    // needed for parameterSst\n    Vector sst1Computed(timesSst1.size()), sst2Computed(timesSst2.size());\n    Vector sst1Pos1(3*timesSst1.size()), sst1Pos2(3*timesSst1.size()), sst1Vel1(3*timesSst1.size()), sst1Vel2(3*timesSst1.size());\n    Vector sst2Pos1(3*timesSst2.size()), sst2Pos2(3*timesSst2.size()), sst2Vel1(3*timesSst2.size()), sst2Vel2(3*timesSst2.size());\n\n    // observation equations within each integration interval\n    // ------------------------------------------------------\n    UInt idEpochSst1=0, idEpochSst2=0, idEpochPod1=0, idEpochPod2=0;\n    std::vector<VariationalEquationFromFile::ObservationEquation> eqn1(interpolationDegree+1);\n    std::vector<VariationalEquationFromFile::ObservationEquation> eqn2(interpolationDegree+1);\n    for(UInt idInterval=0; idInterval<times.size()-1; idInterval++)\n    {\n      // integration of eqn1, eqn2  which are cyclicly updated\n      // -----------------------------------------------------\n      const UInt start = idInterval ? std::max(interpolationDegree, idInterval+(interpolationDegree+1)/2) : 0;\n      const UInt end   = std::min(std::max(idInterval+(interpolationDegree+1)/2+1, interpolationDegree+1), times.size());\n      for(UInt i=start; i<end; i++)\n      {\n        eqn1.at(i%eqn1.size()) = variationalEquation1.integrateArc(times.at(i), times.at(i), TRUE/*position*/, computeVelocity);\n        eqn2.at(i%eqn2.size()) = variationalEquation2.integrateArc(times.at(i), times.at(i), TRUE/*position*/, computeVelocity);\n      }\n\n      // satellite to satellite tracking\n      // -------------------------------\n      auto computeSst = [&](UInt idxSst, UInt &idEpochSst, const std::vector<SatelliteTrackingArc> &sst, const std::vector<Time> &timesSst,\n                            Vector &sstComputed, Vector &sstPos1, Vector &sstPos2, Vector &sstVel1, Vector &sstVel2)\n      {\n        for(; (idEpochSst < timesSst.size()) && (timesSst.at(idEpochSst) <= times.at(idInterval+1)); idEpochSst++)\n        {\n          Matrix pos1, vel1, PosDesign1, VelDesign1;\n          Matrix pos2, vel2, PosDesign2, VelDesign2;\n          interpolate(timesSst.at(idEpochSst), eqn1, pos1, vel1, PosDesign1, VelDesign1, computeVelocity, interpolationDegree);\n          interpolate(timesSst.at(idEpochSst), eqn2, pos2, vel2, PosDesign2, VelDesign2, computeVelocity, interpolationDegree);\n\n          copy(pos1, sstPos1.row(3*idEpochSst, 3));\n          copy(pos2, sstPos2.row(3*idEpochSst, 3));\n          if(computeVelocity)\n          {\n            copy(vel1, sstVel1.row(3*idEpochSst, 3));\n            copy(vel2, sstVel2.row(3*idEpochSst, 3));\n          }\n\n          if(sstType == 0) // range\n          {\n            Vector3d e12(pos2-pos1);\n            const Double rho = e12.normalize();\n\n            sstComputed(idEpochSst) = rho;\n            for(UInt k=0; k<sst.size(); k++)\n              l(idxSst+idEpochSst, 0) += (sst.at(k).at(idEpochSst).range - sst.at(k).at(0).range);\n            l(idxSst+idEpochSst, 0) -= (sstComputed(idEpochSst)-sstComputed(0));\n\n            // dRange/dPos12\n            Matrix e = e12.vector().trans();\n            if(gravityCount)\n              matMult( 1., e, PosDesign2.column(0, gravityCount)-PosDesign1.column(0, gravityCount), A.slice(idxSst+idEpochSst, idxGravity, 1, gravityCount));\n            matMult(-1., e, PosDesign1.column(gravityCount, state1Count),  A.slice(idxSst+idEpochSst, idxState1,  1, state1Count));\n            matMult( 1., e, PosDesign2.column(gravityCount, state2Count),  A.slice(idxSst+idEpochSst, idxState2,  1, state2Count));\n          }\n          else if(sstType == 1) // range rate\n          {\n            Vector3d e12(pos2-pos1);\n            const Double rho = e12.normalize();\n            Vector3d vel12(vel2-vel1);\n            const Double drho = inner(e12, vel12);\n\n            sstComputed(idEpochSst) = drho;\n            for(UInt k=0; k<sst.size(); k++)\n              l(idxSst+idEpochSst,0) += sst.at(k).at(idEpochSst).rangeRate;\n            l(idxSst+idEpochSst,0) -= sstComputed(idEpochSst);\n\n            // dRate/dPos12\n            Matrix e = ((1/rho)*vel12 - (drho/rho) * e12).vector().trans();\n            if(gravityCount)\n              matMult( 1., e, PosDesign2.column(0, gravityCount)-PosDesign1.column(0, gravityCount), A.slice(idxSst+idEpochSst, idxGravity, 1, gravityCount));\n            matMult(-1., e, PosDesign1.column(gravityCount, state1Count),  A.slice(idxSst+idEpochSst, idxState1,  1, state1Count));\n            matMult( 1., e, PosDesign2.column(gravityCount, state2Count),  A.slice(idxSst+idEpochSst, idxState2,  1, state2Count));\n\n            // dRate/dVel12 = e12\n            e = e12.vector().trans();\n            if(gravityCount)\n              matMult( 1., e, VelDesign2.column(0, gravityCount)-VelDesign1.column(0, gravityCount), A.slice(idxSst+idEpochSst, idxGravity, 1, gravityCount));\n            matMult(-1., e, VelDesign1.column(gravityCount, state1Count),  A.slice(idxSst+idEpochSst, idxState1,  1, state1Count));\n            matMult( 1., e, VelDesign2.column(gravityCount, state2Count),  A.slice(idxSst+idEpochSst, idxState2,  1, state2Count));\n          }\n        } // for(idEpochSst)\n      };\n\n      computeSst(idxSst1, idEpochSst1, sst1, timesSst1, sst1Computed, sst1Pos1, sst1Pos2, sst1Vel1, sst1Vel2);\n      computeSst(idxSst2, idEpochSst2, sst2, timesSst2, sst2Computed, sst2Pos1, sst2Pos2, sst2Vel1, sst2Vel2);\n\n      // POD 1\n      // -----\n      for(; (idEpochPod1 < timesPod1.size()) && (timesPod1.at(idEpochPod1) <= times.at(idInterval+1)); idEpochPod1++)\n      {\n        Matrix pos1, vel1, PosDesign1, VelDesign1;\n        interpolate(timesPod1.at(idEpochPod1), eqn1, pos1, vel1, PosDesign1, VelDesign1, FALSE, interpolationDegree);\n\n        l(idxPod1+3*idEpochPod1+0, 0) = pod1.at(idEpochPod1).position.x();\n        l(idxPod1+3*idEpochPod1+1, 0) = pod1.at(idEpochPod1).position.y();\n        l(idxPod1+3*idEpochPod1+2, 0) = pod1.at(idEpochPod1).position.z();\n        l.row(idxPod1+3*idEpochPod1, 3) -= pos1;\n\n        if(gravityCount)\n          copy(PosDesign1.column(0, gravityCount),         A.slice(idxPod1+3*idEpochPod1, idxGravity, 3, gravityCount));\n        copy(PosDesign1.column(gravityCount, state1Count), A.slice(idxPod1+3*idEpochPod1, idxState1,  3, state1Count));\n      } // for(idEpochPod1)\n\n      // POD 2\n      // -----\n      for(; (idEpochPod2 < timesPod2.size()) && (timesPod2.at(idEpochPod2) <= times.at(idInterval+1)); idEpochPod2++)\n      {\n        Matrix pos2, vel2, PosDesign2, VelDesign2;\n        interpolate(timesPod2.at(idEpochPod2), eqn2, pos2, vel2, PosDesign2, VelDesign2, FALSE, interpolationDegree);\n\n        l(idxPod2+3*idEpochPod2+0, 0) = pod2.at(idEpochPod2).position.x();\n        l(idxPod2+3*idEpochPod2+1, 0) = pod2.at(idEpochPod2).position.y();\n        l(idxPod2+3*idEpochPod2+2, 0) = pod2.at(idEpochPod2).position.z();\n        l.row(idxPod2+3*idEpochPod2, 3) -= pos2;\n\n        if(gravityCount)\n          copy(PosDesign2.column(0, gravityCount),         A.slice(idxPod2+3*idEpochPod2, idxGravity, 3, gravityCount));\n        copy(PosDesign2.column(gravityCount, state2Count), A.slice(idxPod2+3*idEpochPod2, idxState2,  3, state2Count));\n      } // for(idEpochPod2)\n    } // for(idInterval)\n\n\n    // =============================================\n\n    if(timesSst1.size())\n      parameterSst1->compute(sstType, timesSst1, sst1Computed, sst1Pos1, sst1Pos2, sst1Vel1, sst1Vel2,\n                             interpolateStarCamera(timesSst1, arc1.times, arc1.rotSat, 1),  // linear interpolation\n                             interpolateStarCamera(timesSst1, arc2.times, arc2.rotSat, 1),\n                             A.slice(idxSst1, idxSst1Para,    timesSst1.size(), parameterSst1->parameterCount()),\n                             B.slice(idxSst1, idxSst1ParaArc, timesSst1.size(), parameterSst1->parameterCountArc()));\n\n    if(timesSst2.size())\n      parameterSst2->compute(sstType, timesSst2, sst2Computed, sst2Pos1, sst2Pos2, sst2Vel1, sst2Vel2,\n                             interpolateStarCamera(timesSst2, arc1.times, arc1.rotSat, 1),  // linear interpolation\n                             interpolateStarCamera(timesSst2, arc2.times, arc2.rotSat, 1),\n                             A.slice(idxSst2, idxSst2Para,    timesSst2.size(), parameterSst2->parameterCount()),\n                             B.slice(idxSst2, idxSst2ParaArc, timesSst2.size(), parameterSst2->parameterCountArc()));\n\n    // =============================================\n\n    // decorrelation\n    // -------------\n    if((timesSst1.size() + timesSst2.size()) && (covSst1 || covSst2 || covAcc))\n    {\n      Matrix CovSst1, CovSst2, CovAcc;\n      if(covSst1) CovSst1 = covSst1->covariance(arcNo, timesSst1);\n      if(covSst2) CovSst2 = covSst2->covariance(arcNo, timesSst2);\n      if(covAcc)  CovAcc  = covAcc->covariance(arcNo, times);\n      const UInt count = timesSst1.size() + timesSst2.size();\n      decorrelate(timesSst1, timesSst2, times, CovSst1, CovSst2, CovAcc, interpolationDegree, {l.row(idxSst1, count), A.row(idxSst1, count), B.row(idxSst1, count)});\n    }\n    if(covPod1 && timesPod1.size()) covPod1->decorrelate(arcNo, pod1, {l.row(idxPod1, 3*timesPod1.size()), A.row(idxPod1, 3*timesPod1.size()), B.row(idxPod1, 3*timesPod1.size())});\n    if(covPod2 && timesPod2.size()) covPod2->decorrelate(arcNo, pod2, {l.row(idxPod2, 3*timesPod2.size()), A.row(idxPod2, 3*timesPod2.size()), B.row(idxPod2, 3*timesPod2.size())});\n\n   // =============================================\n\n    Arc observationArc;\n    observationArc.l     = l;\n    observationArc.A     = A;\n    observationArc.B     = B;\n    observationArc.times = {timesSst1, timesSst2, times, timesPod1, timesPod2};\n    observationArc.pod1  = pod1;\n    observationArc.pod2  = pod2;\n    return observationArc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscDualSstVariational::observation(UInt /*arcNo*/, Matrix &/*l*/, Matrix &/*A*/, Matrix &/*B*/)\n{\n  try\n  {\n    throw(Exception(\"Must not be called\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix ObservationMiscDualSstVariational::decorrelate(const std::vector<Time> &timesSst1, const std::vector<Time> &timesSst2, const std::vector<Time> &timesAcc,\n                                                      const_MatrixSliceRef CovSst1, const_MatrixSliceRef CovSst2, MatrixSliceRef CovAcc, UInt interpolationDegree,\n                                                      const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    const UInt count1 = CovSst1.rows();\n    const UInt count2 = CovSst2.rows();\n    Matrix W(count1+count2, Matrix::SYMMETRIC, Matrix::UPPER);\n    copy(CovSst1, W.slice(0,     0,       count1, count1));\n    copy(CovSst2, W.slice(count1, count1, count2, count2));\n    if(CovAcc.size())\n    {\n      fillSymmetric(CovAcc);\n      Polynomial polynomial(timesAcc, interpolationDegree);\n      const Matrix CovAcc1 = polynomial.interpolate(timesSst1, CovAcc.trans());  // = F1 * Cov * with interpolation matrix F to timeSst1\n      const Matrix CovAcc2 = polynomial.interpolate(timesSst2, CovAcc.trans());  // = F2 * Cov * with interpolation matrix F to timeSst2\n      axpy(1., polynomial.interpolate(timesSst1, CovAcc1.trans()), W.slice(0,      0,      count1, count1));\n      axpy(1., polynomial.interpolate(timesSst2, CovAcc2.trans()), W.slice(count1, count1, count2, count2));\n      copy(    polynomial.interpolate(timesSst1, CovAcc2.trans()), W.slice(0,      count1, count1, count2));\n    }\n\n    cholesky(W);\n    for(MatrixSliceRef WA : A)\n      if(WA.size())\n        triangularSolve(1., W.trans(), WA);\n\n    return W;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscDualSstVariational::interpolate(const Time &time, const std::vector<VariationalEquationFromFile::ObservationEquation> &eqn,\n                                                    Matrix &pos0, Matrix &vel0, Matrix &PosDesign, Matrix &VelDesign, Bool computeVelocity, UInt degree)\n{\n  try\n  {\n    // time matches? -> no interpolation needed\n    for(auto &e : eqn)\n      if(std::fabs((time-e.times.front()).seconds()) < 1e-9)\n      {\n        pos0      = e.pos0;\n        PosDesign = e.PosDesign;\n        if(computeVelocity) vel0      = e.vel0;\n        if(computeVelocity) VelDesign = e.VelDesign;\n        return;\n      }\n\n    // polynomial interpolation matrix\n    Matrix W(degree+1, degree+1);\n    for(UInt i=0; i<W.rows(); i++)\n    {\n      const Double dt = (eqn.at(i).times.front()-time).seconds();\n      W(i, 0) = 1.0;\n      for(UInt n=1; n<W.columns(); n++)\n        W(i, n) = dt * W(i, n-1);\n    }\n    inverse(W); // interpolation weights are the first line of W^-1, because a_0 is the first column\n\n    pos0      = W(0, 0) * eqn.front().pos0;\n    PosDesign = W(0, 0) * eqn.front().PosDesign;\n    if(computeVelocity) vel0      = W(0, 0) * eqn.front().vel0;\n    if(computeVelocity) VelDesign = W(0, 0) * eqn.front().VelDesign;\n    for(UInt k=1; k<eqn.size(); k++)\n    {\n      axpy(W(0, k), eqn.at(k).pos0,      pos0);\n      axpy(W(0, k), eqn.at(k).PosDesign, PosDesign);\n      if(computeVelocity) axpy(W(0, k), eqn.at(k).vel0,      vel0);\n      if(computeVelocity) axpy(W(0, k), eqn.at(k).VelDesign, VelDesign);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Rotary3d> ObservationMiscDualSstVariational::interpolateStarCamera(const std::vector<Time> &timesNew,\n                                                                               const std::vector<Time> &times, const std::vector<Rotary3d> &rot, UInt degree)\n{\n  try\n  {\n    Matrix A(4, rot.size());\n    for(UInt i=0; i<rot.size(); i++)\n      copy(rot.at(i).quaternion(), A.column(i));\n\n    for(UInt i=1; i<A.columns(); i++)\n      if(inner(A.column(i-1), A.column(i)) < 0)\n        A.column(i) *= -1.;\n\n    Polynomial polynomial(times, degree);\n    A = polynomial.interpolate(timesNew, A.trans()).trans();\n\n    std::vector<Rotary3d> rotNew(A.columns());\n    for(UInt i=0; i<rotNew.size(); i++)\n      rotNew.at(i) = Rotary3d(A.column(i)/norm(A.column(i)));\n\n    return rotNew;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscDualSstVariational.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscDualSstVariational.h\n*\n* @brief Satellite to satellite tracking (Variational equations).\n*\n* @author Andreas Kvas\n* @date 2019-11-22\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICDUALSSTVARIATIONAL__\n#define __GROOPS_OBSERVATIONMSICDUALSSTVARIATIONAL__\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscDualSstVariational;\ntypedef std::shared_ptr<ObservationMiscDualSstVariational> ObservationMiscDualSstVariationalPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite to satellite tracking (Variational equations).\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscDualSstVariational : public Observation\n{\npublic:\n  class Arc\n  {\n  public:\n    Matrix   l, A, B;\n    std::array<std::vector<Time>, 5> times; // SST1, SST2, ACC, POD1, POD2\n    OrbitArc pod1, pod2;\n  };\n\n  std::vector<InstrumentFilePtr>      sst1File, sst2File;\n  VariationalEquationFromFile         variationalEquation1, variationalEquation2;\n  InstrumentFile                      pod1File, pod2File;\n  UInt                                interpolationDegree;\n  UInt                                countArc;\n  UInt                                sstType; // 0: biased range, 1: range-rate\n  Bool                                computeVelocity;\n  EphemeridesPtr                      ephemerides;\n  ParametrizationGravityPtr           parameterGravity;\n  ParametrizationAccelerationPtr      parameterAcceleration1, parameterAcceleration2;\n  ParametrizationSatelliteTrackingPtr parameterSst1, parameterSst2;\n\n  // Indicies for design matrix A\n  UInt countAParameter;\n  UInt idxGravity,      gravityCount;\n  UInt idxState1,       state1Count;\n  UInt idxState2,       state2Count;\n  UInt idxSst1Para,     idxSst2Para;\n\n  static void interpolate(const Time &time, const std::vector<VariationalEquationFromFile::ObservationEquation> &eqn,\n                          Matrix &pos0, Matrix &vel0, Matrix &PosDesign, Matrix &VelDesign, Bool computeVelocity, UInt degree);\n\n  static std::vector<Rotary3d> interpolateStarCamera(const std::vector<Time> &timesNew,\n                                                     const std::vector<Time> &times, const std::vector<Rotary3d> &rot, UInt degree);\n\npublic:\n  ObservationMiscDualSstVariational(Config &config);\n ~ObservationMiscDualSstVariational() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount()          const override {return countAParameter;}\n  UInt gravityParameterCount()   const override {return gravityCount;}\n  UInt rightSideCount()          const override {return 1;}\n  UInt arcCount()                const override {return countArc;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  Arc computeArc(UInt arcNo, CovarianceSstPtr covSst1=nullptr, CovarianceSstPtr covSst2=nullptr, CovarianceSstPtr covAcc=nullptr,\n                 CovariancePodPtr covPod1=nullptr, CovariancePodPtr covPod2=nullptr);\n\n  void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) override;\n\n  static Matrix decorrelate(const std::vector<Time> &timesSst1, const std::vector<Time> &timesSst2, const std::vector<Time> &timesAcc,\n                            const_MatrixSliceRef CovSst1, const_MatrixSliceRef CovSst2, MatrixSliceRef CovAcc, UInt interpolationDegree,\n                            const std::list<MatrixSlice> &A);\n\n   /** @brief creates an derived instance of this class. */\n  static ObservationMiscDualSstVariationalPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ObservationMiscDualSst.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a observation is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] observation Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ObservationMiscDualSst */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationMiscDualSstVariationalPtr &observation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscPod.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscPod.cpp\n*\n* @brief Precise Orbit data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/observationMiscPodIntegral.h\"\n#include \"misc/observation/observationMiscPodVariational.h\"\n#include \"misc/observation/observationMiscPod.h\"\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationMiscPodPtr &observation, Config::Appearance mustSet, const std::string &/*defaultValue*/, const std::string &/*annotation*/)\n{\n  try\n  {\n//     if(isCreateSchema(config))\n//     {\n//       config.xselement(name, ObservationMiscPod::typeName(), mustSet, Config::ONCE, \"\", annotation);\n//       return FALSE;\n//     }\n\n    if(!hasName(config, name, mustSet))\n      return FALSE;\n    observation = ObservationMiscPod::create(config, name);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscPodPtr ObservationMiscPod::create(Config &config, const std::string &name)\n{\n  try\n  {\n    ObservationMiscPodPtr observation;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"obervation equations (POD)\");\n    if(readConfigChoiceElement(config, \"podIntegral\"        , type, \"precise orbit data (integral approach)\"))\n      observation = ObservationMiscPodPtr(new ObservationMiscPodIntegral(config));\n    if(readConfigChoiceElement(config, \"podVariational\"     , type, \"precise orbit data (variational equations)\"))\n      observation = ObservationMiscPodPtr(new ObservationMiscPodVariational(config));\n    endChoice(config);\n\n    return observation;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscPod::observation(UInt /*arcNo*/, Matrix &/*l*/, Matrix &/*A*/, Matrix &/*B*/)\n{\n  try\n  {\n    throw(Exception(\"Must not be called\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscPod.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscPod.h\n*\n* @brief Precise Orbit data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICPOD__\n#define __GROOPS_OBSERVATIONMSICPOD__\n\n/***********************************************/\n\n#include \"base/parameterName.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscPod;\ntypedef std::shared_ptr<ObservationMiscPod> ObservationMiscPodPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit data.\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscPod : public Observation\n{\npublic:\n  class Arc\n  {\n  public:\n    Matrix l, A, B;\n    std::vector<Time> times;\n    OrbitArc pod;\n  };\n\n  virtual ~ObservationMiscPod() {}\n\n  virtual Arc computeArc(UInt arcNo, CovariancePodPtr covPod=nullptr) = 0;\n\n  void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) override;\n\n  /** @brief creates an derived instance of this class. */\n  static ObservationMiscPodPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ObservationMiscPod.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a observation is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] observation Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ObservationMiscPod */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationMiscPodPtr &observation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscPodIntegral.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscPodIntegral.cpp\n*\n* @brief Precise Orbit data (Short Arc Integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"observationMiscPodIntegral.h\"\n\n/***********************************************/\n\nObservationMiscPodIntegral::ObservationMiscPodIntegral(Config &config)\n{\n  try\n  {\n    FileName fileNameSatellite;\n    FileName orbitName, starCameraName;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\",     date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",      date2time(2020, 6,  3));\n    renameDeprecatedConfig(config, \"parameter\",      \"parametrizationAcceleration\", date2time(2020, 6,  3));\n\n    readConfig(config, \"inputfileSatelliteModel\",     fileNameSatellite,     Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"rightHandSide\",               rhs,                   Config::MUSTSET,  \"\",    \"input for the reduced observation vector\");\n    readConfig(config, \"inputfileOrbit\",              orbitName,             Config::MUSTSET,  \"\",    \"used to evaluate the observation equations, not used as observations\");\n    readConfig(config, \"inputfileStarCamera\",         starCameraName,        Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"earthRotation\",               earthRotation,         Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",                 ephemerides,           Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"gradientfield\",               gradientfield,         Config::DEFAULT,  \"\",    \"low order field to estimate the change of the gravity by position adjustement\");\n    readConfig(config, \"parametrizationGravity\",      parameterGravity,      Config::DEFAULT,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration\", parameterAcceleration, Config::DEFAULT,  \"\",    \"orbit force parameters\");\n    readConfig(config, \"keepSatelliteStates\",         keepSatelliteStates,   Config::DEFAULT,  \"0\",   \"set boundary values of each arc global\");\n    readConfig(config, \"integrationDegree\",           integrationDegree,     Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,   Config::DEFAULT,  \"7\",   \"orbit interpolation by polynomial approximation of degree n\");\n    readConfig(config, \"accelerateComputation\",       accelerateComputation, Config::DEFAULT,  \"0\",   \"acceleration of computation by transforming the observations\");\n    if(isCreateSchema(config)) return;\n\n    if(integrationDegree%2 == 0)\n      throw(Exception(\"polnomial degree for integration must be odd.\"));\n\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    // test instrument files\n    // ---------------------\n    orbitFile.open(orbitName);\n    starCameraFile.open(starCameraName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n    for(UInt j=0; j<rhs.size(); j++)\n      InstrumentFile::checkArcCount({orbitFile, *(rhs.at(j)->accelerometerFile)});\n    for(UInt j=1; j<rhs.size(); j++)\n      InstrumentFile::checkArcCount({*(rhs.at(j)->orbitFile), *(rhs.at(0)->orbitFile)});\n\n    // init\n    // ----\n    countArc = orbitFile.arcCount();\n    integralEquation.init(integrationDegree, interpolationDegree);\n\n    // design matrix A\n    // ---------------\n    countAParameter = 0;\n    idxGravity = countAParameter; countAParameter += parameterGravity->parameterCount();\n    idxSat     = countAParameter; countAParameter += parameterAcceleration->parameterCount();\n    if(keepSatelliteStates)\n    {\n      idxBound = countAParameter;\n      countAParameter += 6*countArc; // 2 boundary pos. (x,y,z).\n    }\n\n    if(accelerateComputation && keepSatelliteStates)\n    {\n      accelerateComputation = FALSE;\n      logWarningOnce<<\"acceleration of computation is not possible, if keepSatelliteStates is set\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ObservationMiscPodIntegral::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    change = parameterGravity->setInterval(timeStart, timeEnd)      || change;\n    change = parameterAcceleration->setInterval(timeStart, timeEnd) || change;\n\n    // count parameters\n    // ----------------\n    countAParameter = 0;\n    idxGravity = countAParameter; countAParameter += parameterGravity->parameterCount();\n    idxSat     = countAParameter; countAParameter += parameterAcceleration->parameterCount();\n    if(keepSatelliteStates)\n    {\n      idxBound = countAParameter;\n      countAParameter += 6*countArc; // 2 boundary pos. (x,y,z).\n    }\n\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscPodIntegral::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    parameterGravity->parameterName(name);\n\n    const std::string satelliteName = satellite ? satellite->satelliteName : \"satellite\";\n    parameterAcceleration->parameterName(name);\n    for(UInt i = name.size(); i --> name.size()-parameterAcceleration->parameterCount(); )\n      name.at(i).object = satelliteName;\n\n    if(keepSatelliteStates)\n    {\n      for(UInt arcNo=0; arcNo<arcCount(); arcNo++)\n      {\n        const std::string str = \"arc\"+arcNo%\"%i\"s+\".position.\";\n        name.push_back(ParameterName(satelliteName, str+\"start.x\"));\n        name.push_back(ParameterName(satelliteName, str+\"start.y\"));\n        name.push_back(ParameterName(satelliteName, str+\"start.z\"));\n        name.push_back(ParameterName(satelliteName, str+\"end.x\"));\n        name.push_back(ParameterName(satelliteName, str+\"end.y\"));\n        name.push_back(ParameterName(satelliteName, str+\"end.z\"));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscPod::Arc ObservationMiscPodIntegral::computeArc(UInt arcNo, CovariancePodPtr covPod)\n{\n  try\n  {\n    OrbitArc      orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n    const UInt    rhsCount   = rhs.size();\n    const UInt    epochCount = orbit.size();\n\n    parameterAcceleration->setIntervalArc(orbit.at(0).time, orbit.back().time+medianSampling(orbit.times()));\n\n    // count arc related parameters (in matrix B)\n    // ------------------------------------------\n    UInt countBParameter = 0;\n    if(!keepSatelliteStates)\n    {\n      idxBound = countBParameter;\n      countBParameter += 6;  // 2 Randpos. je (x,y,z).\n    }\n    const UInt idxSatArc = countBParameter;\n    countBParameter += parameterAcceleration->parameterCountArc();\n\n    // read POD observations\n    // ---------------------\n    std::vector<OrbitArc> pod(rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n      pod.at(j) = rhs.at(j)->orbitFile->readArc(arcNo);\n\n    for(UInt j=1; j<rhsCount; j++)\n      for(UInt i=0; i<pod.at(j).size(); i++)\n        if(pod.at(j).at(i).time != pod.at(j-1).at(i).time)\n          throw(Exception(\"POD-Orbits on different rightHandSides differ in sampling\"));\n\n    const UInt podCount = pod.at(0).size();\n    if(3*podCount <= countBParameter)\n      return Arc();\n\n    // calculate earthrotation\n    // -----------------------\n    std::vector<Rotary3d> rotEarth(epochCount);\n    for(UInt k=0; k<epochCount; k++)\n      rotEarth.at(k) = earthRotation->rotaryMatrix(orbit.at(k).time);\n\n    // reference acceleration\n    // ----------------------\n    Matrix g(3*epochCount, rhsCount);\n    AccelerometerArc accelerometer;\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      AccelerometerArc accl = rhs.at(j)->accelerometerFile->readArc(arcNo);\n      if((accelerometer.size() == 0) && (accl.size() != 0))\n        accelerometer = accl;\n\n      for(UInt k=0; k<epochCount; k++)\n      {\n        Vector3d gv = rhs.at(j)->forces->acceleration(satellite, orbit.at(k).time, orbit.at(k).position, orbit.at(k).velocity,\n                                                      starCamera.at(k).rotary, rotEarth.at(k), earthRotation, ephemerides);\n        // accelerometer [-> TRF]\n        if(accl.size())\n          gv += rotEarth.at(k).rotate(starCamera.at(k).rotary.rotate(accl.at(k).acceleration));\n        // sort into vector\n        g(3*k+0, j) = gv.x();\n        g(3*k+1, j) = gv.y();\n        g(3*k+2, j) = gv.z();\n      }\n    }\n\n    // =============================================\n\n    // satellite parameters\n    // --------------------\n    Matrix Sat   (3*epochCount, parameterAcceleration->parameterCount());\n    Matrix SatArc(3*epochCount, parameterAcceleration->parameterCountArc());\n    for(UInt k=0; k<epochCount; k++)\n    {\n      parameterAcceleration->compute(satellite, orbit.at(k).time, orbit.at(k).position, orbit.at(k).velocity,\n                                  starCamera.at(k).rotary, rotEarth.at(k), ephemerides, Sat.row(3*k,3), SatArc.row(3*k,3));\n    }\n\n    // =============================================\n\n    // integral kernel\n    // ---------------\n    Matrix l;\n    Matrix VPos, VPosBoundary;\n    {\n      IntegralEquation::Arc arc = integralEquation.integrateArc(orbit, rotEarth, gradientfield, g, SatArc);\n      integralEquation.interpolateArc(pod, orbit, arc, l, VPos, VPosBoundary);\n    }\n\n    // =============================================\n\n    // decorrelation\n    // -------------\n    if(covPod)\n      covPod->decorrelate(arcNo, pod.at(0), {l, VPos, VPosBoundary});\n\n    // =============================================\n\n    // arc related parameters (satellite state + acceleration calibration)\n    // -------------------------------------------------------------------\n    Matrix B(3*podCount, countBParameter);\n    // satellite state vector\n    if(!keepSatelliteStates)\n      copy(VPosBoundary, B.column(idxBound, VPosBoundary.columns()));\n    // Accelerometer calibration\n    if(SatArc.columns() != 0)\n      matMult(1., VPos, SatArc, B.column(idxSatArc, SatArc.columns()));\n\n    // =============================================\n\n    if(accelerateComputation)\n    {\n      eliminationParameter(B, VPos, l);\n      B = Matrix();\n      if(VPos.rows() > VPos.columns())\n      {\n        Vector tau = QR_decomposition(VPos);\n        QTransMult(VPos, tau, l);\n        VPos = VPos.row(0,VPos.columns());\n        VPos.setType(Matrix::TRIANGULAR, Matrix::UPPER);\n      }\n    }\n\n    // =============================================\n\n    // Design matrix A (gravity)\n    // -------------------------\n    Matrix A(VPos.rows(), countAParameter);\n    // gravity field\n    if(parameterGravity->parameterCount())\n    {\n      Matrix G(3*epochCount, parameterGravity->parameterCount());\n      for(UInt k=0; k<epochCount; k++)\n        parameterGravity->gravity(orbit.at(k).time, rotEarth.at(k).rotate(orbit.at(k).position), G.row(3*k, 3));\n      matMult(1., VPos, G, A.column(idxGravity, G.columns()));\n    }\n    // Accelerometer calibration\n    if(Sat.columns() != 0)\n      matMult(1., VPos, Sat, A.column(idxSat, Sat.columns()));\n    // satellite state vector\n    if(keepSatelliteStates)\n      copy(VPosBoundary, A.column(idxBound+6*arcNo, VPosBoundary.columns()));\n\n    // =============================================\n\n    Arc observationArc;\n    observationArc.l     = l;\n    observationArc.A     = A;\n    observationArc.B     = B;\n    observationArc.times = pod.at(0).times();\n    observationArc.pod   = pod.at(0);\n    return observationArc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscPodIntegral.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscPodIntegral.h\n*\n* @brief Precise Orbit data (Short Arc Integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICPODINTEGRAL__\n#define __GROOPS_OBSERVATIONMSICPODINTEGRAL__\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"misc/observation/integralEquation.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"misc/observation/observationMiscPod.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscPodIntegral;\ntypedef std::shared_ptr<ObservationMiscPodIntegral> ObservationMiscPodIntegralPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit data (Short Arc Integral).\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscPodIntegral : public ObservationMiscPod\n{\n  SatelliteModelPtr              satellite;\n  std::vector<PodRightSidePtr>   rhs; // right hand sides\n  IntegralEquation               integralEquation;\n  Bool                           keepSatelliteStates;\n  Bool                           accelerateComputation;\n  InstrumentFile                 orbitFile;\n  InstrumentFile                 starCameraFile;\n  EarthRotationPtr               earthRotation;\n  EphemeridesPtr                 ephemerides;\n  GravityfieldPtr                gradientfield;\n  ParametrizationGravityPtr      parameterGravity;\n  ParametrizationAccelerationPtr parameterAcceleration;\n  UInt                           integrationDegree;\n  UInt                           interpolationDegree;\n  UInt                           countArc;\n\n  // Indicies for design matrix A\n  UInt countAParameter;\n  UInt idxGravity;\n  UInt idxBound;\n  UInt idxSat;\n\npublic:\n  ObservationMiscPodIntegral(Config &config);\n ~ObservationMiscPodIntegral() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount()          const override {return countAParameter;}\n  UInt gravityParameterCount()   const override {return parameterGravity->parameterCount();}\n  UInt rightSideCount()          const override {return rhs.size();}\n  UInt arcCount()                const override {return countArc;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  Arc computeArc(UInt arcNo, CovariancePodPtr covPod) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscPodVariational.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscPodVariational.cpp\n*\n* @brief Precise Orbit data (variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"observationMiscPodVariational.h\"\n\n/***********************************************/\n\nObservationMiscPodVariational::ObservationMiscPodVariational(Config &config)\n{\n  try\n  {\n    FileName              fileNamePod;\n    FileName              fileNameVariational;\n    UInt                  integrationDegree;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",      date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"parameter\",      \"parametrizationAcceleration\", date2time(2020, 6, 3));\n\n    if(readConfigSequence(config, \"rightHandSide\", Config::MUSTSET, \"\", \"input for observation vectors\"))\n    {\n      readConfig(config, \"inputfileOrbit\", fileNamePod, Config::MUSTSET, \"\", \"kinematic positions as observations\");\n      endSequence(config);\n    }\n    readConfig(config, \"inputfileVariational\",        fileNameVariational,   Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"ephemerides\",                 ephemerides,           Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationGravity\",      parameterGravity,      Config::DEFAULT,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration\", parameterAcceleration, Config::DEFAULT,  \"\",    \"orbit force parameters\");\n    readConfig(config, \"integrationDegree\",           integrationDegree,     Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,   Config::DEFAULT,  \"7\",   \"orbit interpolation by polynomial approximation of degree n\");\n    readConfig(config, \"accelerateComputation\",       accelerateComputation, Config::DEFAULT,  \"0\",   \"acceleration of computation by transforming the observations\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    // init\n    // ----\n    podFile.open(fileNamePod);\n    countArc = podFile.arcCount();\n    variationalEquation.open(fileNameVariational, parameterGravity, parameterAcceleration, std::vector<Time>(), ephemerides, integrationDegree);\n\n    // =======================\n\n    // count parameters\n    // ----------------\n    countAParameter = variationalEquation.parameterCount();\n    gravityCount    = variationalEquation.parameterCountGravity();\n    idxGravity      = 0;\n    idxState        = gravityCount;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ObservationMiscPodVariational::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    change = parameterGravity->setInterval(timeStart, timeEnd)      || change;\n    change = parameterAcceleration->setInterval(timeStart, timeEnd) || change;\n    if(!change)\n      return FALSE;\n    variationalEquation.computeIndices();\n\n    // count parameters\n    // ----------------\n    countAParameter = variationalEquation.parameterCount();\n    gravityCount    = variationalEquation.parameterCountGravity();\n    idxGravity      = 0;\n    idxState        = gravityCount;\n\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscPodVariational::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    variationalEquation.parameterName(name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscPod::Arc ObservationMiscPodVariational::computeArc(UInt arcNo, CovariancePodPtr covPod)\n{\n  try\n  {\n    // read POD observations\n    // ---------------------\n    OrbitArc pod = podFile.readArc(arcNo);\n\n    const UInt obsCount = 3*pod.size();\n    if(obsCount == 0)\n      return Arc();\n\n    const std::vector<Time> timePod = pod.times();\n    VariationalEquationFromFile::ObservationEquation eqn = variationalEquation.integrateArc(timePod.at(0), timePod.back(), TRUE/*position*/, FALSE/*velocity*/);\n    Polynomial polynomial(eqn.times, interpolationDegree);\n\n    // kinematic orbit observations\n    // ----------------------------\n    Matrix l(obsCount, 1);\n    for(UInt k=0; k<obsCount/3; k++)\n    {\n      l(3*k+0,0) = pod.at(k).position.x();\n      l(3*k+1,0) = pod.at(k).position.y();\n      l(3*k+2,0) = pod.at(k).position.z();\n    }\n    l -= polynomial.interpolate(timePod, eqn.pos0, 3);\n\n    // =============================================\n\n    Matrix A;\n    if(!accelerateComputation || (l.rows() <= eqn.PosDesign.rows()))\n    {\n      // design matrix\n      // -------------\n      A = polynomial.interpolate(timePod, eqn.PosDesign, 3);\n\n      // decorrelation\n      // -------------\n      if(covPod)\n        covPod->decorrelate(arcNo, pod, {l, A});\n    }\n    else\n    {\n      A = eqn.PosDesign;\n      Matrix B = polynomial.interpolate(timePod, identityMatrix(A.rows()), 3);\n      if(covPod)\n        covPod->decorrelate(arcNo, pod, {l, B});\n      const Vector tau = QR_decomposition(B);\n      QTransMult(B, tau, l);\n      triangularMult(1., B.row(0, B.columns()), A);\n    }\n\n    // =============================================\n\n    Arc observationArc;\n    observationArc.l     = l;\n    observationArc.A     = A;\n    observationArc.times = timePod;\n    observationArc.pod   = pod;\n    return observationArc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscPodVariational.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscPodVariational.h\n*\n* @brief Precise Orbit data (variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICPODVARIATIONAL__\n#define __GROOPS_OBSERVATIONMSICPODVARIATIONAL__\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"misc/observation/observationMiscPod.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscPodVariational;\ntypedef std::shared_ptr<ObservationMiscPodVariational> ObservationMiscPodVariationalPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Precise Orbit data (variational equations).\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscPodVariational : public ObservationMiscPod\n{\n  InstrumentFile                 podFile;\n  VariationalEquationFromFile    variationalEquation;\n  UInt                           interpolationDegree;\n  UInt                           countArc;\n  EphemeridesPtr                 ephemerides;\n  ParametrizationGravityPtr      parameterGravity;\n  ParametrizationAccelerationPtr parameterAcceleration;\n  Bool                           accelerateComputation;\n\n  // Indicies for design matrix A\n  UInt countAParameter;\n  UInt idxGravity, gravityCount;\n  UInt idxState;\n\npublic:\n  ObservationMiscPodVariational(Config &config);\n ~ObservationMiscPodVariational() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount()          const override {return countAParameter;}\n  UInt gravityParameterCount()   const override {return gravityCount;}\n  UInt rightSideCount()          const override {return 1;}\n  UInt arcCount()                const override {return countArc;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  Arc computeArc(UInt arcNo, CovariancePodPtr cov) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscSst.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscSst.cpp\n*\n* @brief Satellite to satellite tracking.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/observationMiscSstIntegral.h\"\n#include \"misc/observation/observationMiscSstVariational.h\"\n#include \"misc/observation/observationMiscSst.h\"\n\n/***** FUNCTIONS *******************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationMiscSstPtr &observation, Config::Appearance mustSet, const std::string &/*defaultValue*/, const std::string &/*annotation*/)\n{\n  try\n  {\n//     if(isCreateSchema(config))\n//     {\n//       config.xselement(name, ObservationMiscSst::typeName(), mustSet, Config::ONCE, \"\", annotation);\n//       return FALSE;\n//     }\n\n    if(!hasName(config, name, mustSet))\n      return FALSE;\n    observation = ObservationMiscSst::create(config, name);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscSstPtr ObservationMiscSst::create(Config &config, const std::string &name)\n{\n  try\n  {\n    ObservationMiscSstPtr observation;\n    std::string type;\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"obervation equations (Sst)\");\n    if(readConfigChoiceElement(config, \"sstIntegral\",    type, \"integral approach\"))\n      observation = ObservationMiscSstPtr(new ObservationMiscSstIntegral(config));\n    if(readConfigChoiceElement(config, \"sstVariational\", type, \"variational equations\"))\n      observation = ObservationMiscSstPtr(new ObservationMiscSstVariational(config));\n    endChoice(config);\n\n    return observation;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscSst::observation(UInt /*arcNo*/, Matrix &/*l*/, Matrix &/*A*/, Matrix &/*B*/)\n{\n  try\n  {\n    throw(Exception(\"Must not be called\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscSst.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscSst.h\n*\n* @brief Satellite to satellite tracking.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICSST__\n#define __GROOPS_OBSERVATIONMSICSST__\n\n/***********************************************/\n\n#include \"base/parameterName.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/observation/observation.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscSst;\ntypedef std::shared_ptr<ObservationMiscSst> ObservationMiscSstPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite to satellite tracking.\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscSst : public Observation\n{\npublic:\n  class Arc\n  {\n  public:\n    Matrix   l, A, B;\n    std::array<std::vector<Time>, 3> times; // SST, POD1, POD2\n    OrbitArc pod1, pod2;\n  };\n\n  virtual ~ObservationMiscSst() {}\n\n  virtual Arc computeArc(UInt arcNo,\n                         CovarianceSstPtr covSst =nullptr,\n                         CovariancePodPtr covPod1=nullptr,\n                         CovariancePodPtr covPod2=nullptr) = 0;\n\n  void observation(UInt arcNo, Matrix &l, Matrix &A, Matrix &B) override;\n\n  /** @brief creates an derived instance of this class. */\n  static ObservationMiscSstPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class ObservationMiscSst.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a observation is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] observation Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates ObservationMiscSst */\ntemplate<> Bool readConfig(Config &config, const std::string &name, ObservationMiscSstPtr &observation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscSstIntegral.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscSstIntegral.cpp\n*\n* @brief Satellite to satellite tracking (Short Arc Integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"misc/observation/integralEquation.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"observationMiscSstIntegral.h\"\n\n/***********************************************/\n\nObservationMiscSstIntegral::ObservationMiscSstIntegral(Config &config)\n{\n  try\n  {\n    sstType = 0;\n    std::string choice;\n    FileName    fileNameSatellite1, fileNameSatellite2;\n    FileName    orbit1Name, orbit2Name;\n    FileName    starCamera1Name, starCamera2Name;\n\n    renameDeprecatedConfig(config, \"satelliteModel1\", \"inputfileSatelliteModel1\",     date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"satelliteModel2\", \"inputfileSatelliteModel2\",     date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"representation\",  \"parametrizationGravity\",       date2time(2020, 6,  3));\n    renameDeprecatedConfig(config, \"parameter1\",      \"parametrizationAcceleration1\", date2time(2020, 6,  3));\n    renameDeprecatedConfig(config, \"parameter2\",      \"parametrizationAcceleration2\", date2time(2020, 6,  3));\n    renameDeprecatedConfig(config, \"parameterSst\",    \"parametrizationSst\",           date2time(2020, 6,  3));\n\n    readConfig(config, \"inputfileSatelliteModel1\", fileNameSatellite1,  Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"inputfileSatelliteModel2\", fileNameSatellite2,  Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"rightHandSide\",            rhs,                 Config::MUSTSET,  \"\", \"input for the reduced observation vector\");\n    if(readConfigChoice(config, \"sstType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"range\",             choice, \"\")) sstType = 0;\n      if(readConfigChoiceElement(config, \"rangeRate\",         choice, \"\")) sstType = 1;\n      if(readConfigChoiceElement(config, \"rangeAcceleration\", choice, \"\")) sstType = 2;\n      if(readConfigChoiceElement(config, \"none\",              choice, \"\")) sstType = 99;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileOrbit1\",              orbit1Name,             Config::MUSTSET,  \"\",    \"used to evaluate the observation equations, not used as observations\");\n    readConfig(config, \"inputfileOrbit2\",              orbit2Name,             Config::MUSTSET,  \"\",    \"used to evaluate the observation equations, not used as observations\");\n    readConfig(config, \"inputfileStarCamera1\",         starCamera1Name,        Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileStarCamera2\",         starCamera2Name,        Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"earthRotation\",                earthRotation,          Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",                  ephemerides,            Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"gradientfield\",                gradientfield,          Config::DEFAULT,  \"\",    \"low order field to estimate the change of the gravity by position adjustement\");\n    readConfig(config, \"parametrizationGravity\",       parameterGravity,       Config::DEFAULT,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration1\", parameterAcceleration1, Config::DEFAULT,  \"\",    \"orbit1 force parameters\");\n    readConfig(config, \"parametrizationAcceleration2\", parameterAcceleration2, Config::DEFAULT,  \"\",    \"orbit2 force parameters\");\n    readConfig(config, \"parametrizationSst\",           parameterSst,           Config::DEFAULT,  \"\",    \"satellite tracking parameter\");\n    readConfig(config, \"keepSatelliteStates\",          keepSatelliteStates,    Config::DEFAULT,  \"0\",   \"set boundary values of each arc global\");    // satellite tracking type\n    readConfig(config, \"integrationDegree\",            integrationDegree,      Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",          interpolationDegree,    Config::DEFAULT,  \"7\",   \"orbit interpolation by polynomial approximation of degree n\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    if(!fileNameSatellite1.empty()) readFileSatelliteModel(fileNameSatellite1, satellite1);\n    if(!fileNameSatellite2.empty()) readFileSatelliteModel(fileNameSatellite2, satellite2);\n\n    // =======================\n\n    // test instrument files\n    // ---------------------\n    orbit1File.open(orbit1Name);\n    orbit2File.open(orbit2Name);\n    starCamera1File.open(starCamera1Name);\n    starCamera2File.open(starCamera2Name);\n\n    std::vector<std::reference_wrapper<const InstrumentFile>> fileList{orbit1File, orbit2File, starCamera1File, starCamera2File};\n    for(UInt j=0; j<rhs.size(); j++)\n    {\n      for(UInt i=0; i<rhs.at(j)->sstFile.size(); i++)\n        fileList.push_back(*rhs.at(j)->sstFile.at(i));\n      fileList.push_back(*rhs.at(j)->accelerometer1File);\n      fileList.push_back(*rhs.at(j)->accelerometer2File);\n    }\n    InstrumentFile::checkArcCount(fileList);\n\n    for(UInt j=1; j<rhs.size(); j++)\n      InstrumentFile::checkArcCount({*rhs.at(j)->orbit1File, *rhs.at(0)->orbit1File});\n    for(UInt j=1; j<rhs.size(); j++)\n      InstrumentFile::checkArcCount({*rhs.at(j)->orbit2File, *rhs.at(0)->orbit2File});\n\n    // init\n    // ----\n    countArc = orbit1File.arcCount();\n    integralEquation.init(integrationDegree, interpolationDegree);\n\n    computeRange        = (sstType==0);\n    computeVelocity     = (sstType==1);\n    computeAcceleration = (sstType==2);\n\n    // =======================\n\n    // design matrix A\n    // ---------------\n    countAParameter = 0;\n    gravityCount = parameterGravity->parameterCount();\n    idxGravity   = countAParameter; countAParameter += gravityCount;\n    idxSat1      = countAParameter; countAParameter += parameterAcceleration1->parameterCount();\n    idxSat2      = countAParameter; countAParameter += parameterAcceleration2->parameterCount();\n    idxSstPara   = countAParameter; countAParameter += parameterSst->parameterCount();\n    if(keepSatelliteStates)\n    {\n      idxBound1 = countAParameter; countAParameter += 6*countArc; // 2 boundary pos. (x,y,z).\n      idxBound2 = countAParameter; countAParameter += 6*countArc; // 2 boundary pos. (x,y,z).\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ObservationMiscSstIntegral::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    change = parameterGravity->setInterval(timeStart, timeEnd)       || change;\n    change = parameterAcceleration1->setInterval(timeStart, timeEnd) || change;\n    change = parameterAcceleration2->setInterval(timeStart, timeEnd) || change;\n    change = parameterSst->setInterval(timeStart, timeEnd)           || change;\n    if(!change)\n      return FALSE;\n\n    // count parameters\n    // ----------------\n    countAParameter = 0;\n    gravityCount = parameterGravity->parameterCount();\n    idxGravity   = countAParameter; countAParameter += gravityCount;\n    idxSat1      = countAParameter; countAParameter += parameterAcceleration1->parameterCount();\n    idxSat2      = countAParameter; countAParameter += parameterAcceleration2->parameterCount();\n    idxSstPara   = countAParameter; countAParameter += parameterSst->parameterCount();\n    if(keepSatelliteStates)\n    {\n      idxBound1 = countAParameter; countAParameter += 6*countArc; // 2 boundary pos. (x,y,z).\n      idxBound2 = countAParameter; countAParameter += 6*countArc; // 2 boundary pos. (x,y,z).\n    }\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscSstIntegral::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    parameterGravity->parameterName(name);\n\n    const std::string satelliteName1 = satellite1 ? satellite1->satelliteName : \"satellite1\";\n    const std::string satelliteName2 = satellite2 ? satellite2->satelliteName : \"satellite2\";\n\n    parameterAcceleration1->parameterName(name);\n    for(UInt i=name.size()-parameterAcceleration1->parameterCount(); i<name.size(); i++)\n      name.at(i).object = satelliteName1;\n\n    parameterAcceleration2->parameterName(name);\n    for(UInt i=name.size()-parameterAcceleration2->parameterCount(); i<name.size(); i++)\n      name.at(i).object = satelliteName2;\n\n    if(parameterSst)\n    {\n      parameterSst->parameterName(name);\n      for(UInt i=name.size()-parameterSst->parameterCount(); i<name.size(); i++)\n        name.at(i).object = satelliteName1+\".\"+satelliteName2;\n    }\n\n    if(keepSatelliteStates)\n    {\n      for(UInt arcNo=0; arcNo<arcCount(); arcNo++)\n      {\n        const std::string str = \"arc\"+arcNo%\"%i\"s+\"position.\";\n        name.push_back(ParameterName(satelliteName1, str+\"start.x\"));\n        name.push_back(ParameterName(satelliteName1, str+\"start.y\"));\n        name.push_back(ParameterName(satelliteName1, str+\"start.z\"));\n        name.push_back(ParameterName(satelliteName1, str+\"end.x\"));\n        name.push_back(ParameterName(satelliteName1, str+\"end.y\"));\n        name.push_back(ParameterName(satelliteName1, str+\"end.z\"));\n      }\n      for(UInt arcNo=0; arcNo<arcCount(); arcNo++)\n      {\n        const std::string str = \"arc\"+arcNo%\"%i\"s+\"position.\";\n        name.push_back(ParameterName(satelliteName2, str+\"start.x\"));\n        name.push_back(ParameterName(satelliteName2, str+\"start.y\"));\n        name.push_back(ParameterName(satelliteName2, str+\"start.z\"));\n        name.push_back(ParameterName(satelliteName2, str+\"end.x\"));\n        name.push_back(ParameterName(satelliteName2, str+\"end.y\"));\n        name.push_back(ParameterName(satelliteName2, str+\"end.z\"));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscSst::Arc ObservationMiscSstIntegral::computeArc(UInt arcNo, CovarianceSstPtr covSst, CovariancePodPtr covPod1, CovariancePodPtr covPod2)\n{\n  try\n  {\n    OrbitArc      orbit1      = orbit1File.readArc(arcNo);\n    OrbitArc      orbit2      = orbit2File.readArc(arcNo);\n    StarCameraArc starCamera1 = starCamera1File.readArc(arcNo);\n    StarCameraArc starCamera2 = starCamera2File.readArc(arcNo);\n    ::Arc::checkSynchronized({orbit1, orbit2, starCamera1, starCamera2});\n    const UInt    rhsCount    = rhs.size();\n    const UInt    epochCount  = orbit1.size();\n\n    parameterAcceleration1->setIntervalArc(orbit1.at(0).time, orbit1.back().time+medianSampling(orbit1.times()));\n    parameterAcceleration2->setIntervalArc(orbit2.at(0).time, orbit2.back().time+medianSampling(orbit2.times()));\n    parameterSst->setIntervalArc(orbit1.at(0).time, orbit1.back().time+medianSampling(orbit1.times()));\n\n    // =============================================\n\n    // count arc related parameters (in matrix B)\n    // ------------------------------------\n    UInt countBParameter = 0;\n    if(!keepSatelliteStates)\n    {\n      idxBound1 = countBParameter; countBParameter += 6; // 2 Randpos. je (x,y,z).\n      idxBound2 = countBParameter; countBParameter += 6; // 2 Randpos. je (x,y,z).\n    }\n    const UInt idxSat1Arc    = countBParameter; countBParameter += parameterAcceleration1->parameterCountArc();\n    const UInt idxSat2Arc    = countBParameter; countBParameter += parameterAcceleration2->parameterCountArc();\n    const UInt idxSstParaArc = countBParameter; countBParameter += parameterSst->parameterCountArc();\n\n    // =============================================\n\n    // read SST observations\n    // ---------------------\n    std::vector<std::vector<SatelliteTrackingArc>> sst(rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      sst.at(j).resize(rhs.at(j)->sstFile.size());\n      for(UInt k=0; k<rhs.at(j)->sstFile.size(); k++)\n      {\n        sst.at(j).at(k) = rhs.at(j)->sstFile.at(k)->readArc(arcNo);\n        ::Arc::checkSynchronized({sst.at(j).at(k), orbit1});\n      }\n    }\n\n    // read POD observations\n    // ---------------------\n    std::vector<OrbitArc> pod1(rhsCount);\n    std::vector<OrbitArc> pod2(rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      pod1.at(j) = rhs.at(j)->orbit1File->readArc(arcNo);\n      pod2.at(j) = rhs.at(j)->orbit2File->readArc(arcNo);\n      ::Arc::checkSynchronized({pod1.at(j), pod1.at(0)});\n      ::Arc::checkSynchronized({pod2.at(j), pod2.at(0)});\n    }\n\n    // =============================================\n\n    // count observations\n    // ------------------\n    const UInt countSst  = (sst.at(0).size() && (sstType!=99)) ? sst.at(0).at(0).size() : 0;\n    const UInt countPod1 = 3*pod1.at(0).size();\n    const UInt countPod2 = 3*pod2.at(0).size();\n\n    UInt obsCount = 0;\n    const UInt idxSst   = obsCount; obsCount += countSst;\n    const UInt idxPod1  = obsCount; obsCount += countPod1;\n    const UInt idxPod2  = obsCount; obsCount += countPod2;\n\n    if(obsCount <= countBParameter)\n      return Arc();\n\n    // =============================================\n\n    // calculate earthrotation\n    // -----------------------\n    std::vector<Time> times = sst.at(0).at(0).times();\n    std::vector<Rotary3d> rotEarth(epochCount);\n    for(UInt k=0; k<epochCount; k++)\n      rotEarth.at(k) = earthRotation->rotaryMatrix(times.at(k));\n\n    // =============================================\n\n    // reference acceleration\n    // ----------------------\n    // satellite 1\n    Matrix g1(3*epochCount, rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      AccelerometerArc accelerometer = rhs.at(j)->accelerometer1File->readArc(arcNo);\n      for(UInt k=0; k<epochCount; k++)\n      {\n        Vector3d gv = rhs.at(j)->forces->acceleration(satellite1, orbit1.at(k).time, orbit1.at(k).position, orbit1.at(k).velocity,\n                                                     starCamera1.at(k).rotary, rotEarth.at(k), earthRotation, ephemerides);\n        // accelerometer [-> TRF]\n        if(accelerometer.size())\n          gv += rotEarth.at(k).rotate(starCamera1.at(k).rotary.rotate(accelerometer.at(k).acceleration));\n        // sort into vector\n        g1(3*k+0, j) = gv.x();\n        g1(3*k+1, j) = gv.y();\n        g1(3*k+2, j) = gv.z();\n      }\n    }\n\n    // satellite 2\n    Matrix g2(3*epochCount, rhsCount);\n    for(UInt j=0; j<rhsCount; j++)\n    {\n      AccelerometerArc accelerometer = rhs.at(j)->accelerometer2File->readArc(arcNo);\n      for(UInt k=0; k<epochCount; k++)\n      {\n        Vector3d gv = rhs.at(j)->forces->acceleration(satellite2, orbit2.at(k).time, orbit2.at(k).position, orbit2.at(k).velocity,\n                                                     starCamera2.at(k).rotary, rotEarth.at(k), earthRotation, ephemerides);\n        // accelerometer [-> TRF]\n        if(accelerometer.size())\n          gv += rotEarth.at(k).rotate(starCamera2.at(k).rotary.rotate(accelerometer.at(k).acceleration));\n        // sort into vector\n        g2(3*k+0, j) = gv.x();\n        g2(3*k+1, j) = gv.y();\n        g2(3*k+2, j) = gv.z();\n      }\n    }\n\n    // =============================================\n\n    // satellite parameters\n    // --------------------\n    Matrix Sat1   (3*epochCount, parameterAcceleration1->parameterCount());\n    Matrix Sat2   (3*epochCount, parameterAcceleration2->parameterCount());\n    Matrix Sat1Arc(3*epochCount, parameterAcceleration1->parameterCountArc());\n    Matrix Sat2Arc(3*epochCount, parameterAcceleration2->parameterCountArc());\n    for(UInt k=0; k<epochCount; k++)\n    {\n      parameterAcceleration1->compute(satellite1, times.at(k), orbit1.at(k).position, orbit1.at(k).velocity,\n                                   starCamera1.at(k).rotary, rotEarth.at(k), ephemerides, Sat1.row(3*k,3), Sat1Arc.row(3*k,3));\n      parameterAcceleration2->compute(satellite2, times.at(k), orbit2.at(k).position, orbit2.at(k).velocity,\n                                   starCamera2.at(k).rotary, rotEarth.at(k), ephemerides, Sat2.row(3*k,3), Sat2Arc.row(3*k,3));\n    }\n\n    // =============================================\n\n    IntegralEquation::Arc arc1 = integralEquation.integrateArc(orbit1, rotEarth, gradientfield, g1, Sat1Arc, computeVelocity || computeAcceleration, computeAcceleration);\n    IntegralEquation::Arc arc2 = integralEquation.integrateArc(orbit2, rotEarth, gradientfield, g2, Sat2Arc, computeVelocity || computeAcceleration, computeAcceleration);\n\n    // =============================================\n\n    Matrix lSst (countSst, rhsCount);\n    Matrix lSst0(countSst, rhsCount);\n    Matrix VSst (countSst, 6*epochCount);\n    Matrix VSstBoundary(countSst, 12);\n    Matrix SstPara(countSst, parameterSst->parameterCount());\n    Matrix SstParaArc(countSst, parameterSst->parameterCountArc());\n    std::vector<Rotary3d> rotSat1(countSst), rotSat2(countSst);\n\n    if(countSst)\n    {\n      // inter satellite vectors\n      std::vector< std::vector<Vector3d> > pos12(rhsCount);\n      std::vector< std::vector<Vector3d> > vel12(rhsCount);\n      std::vector< std::vector<Vector3d> > acc12(rhsCount);\n      std::vector< std::vector<Vector3d> > e12  (rhsCount);\n\n      for(UInt j=0; j<rhsCount; j++)\n      {\n        pos12.at(j).resize(epochCount);\n        vel12.at(j).resize(epochCount);\n        acc12.at(j).resize(epochCount);\n        e12.at(j).resize(epochCount);\n\n        for(UInt i=0; i<epochCount; i++)\n        {\n          pos12.at(j).at(i) = Vector3d(arc2.vPos(3*i+0,j)-arc1.vPos(3*i+0,j),\n                                       arc2.vPos(3*i+1,j)-arc1.vPos(3*i+1,j),\n                                       arc2.vPos(3*i+2,j)-arc1.vPos(3*i+2,j));\n          if(computeVelocity || computeAcceleration)\n          vel12.at(j).at(i) = Vector3d(arc2.vVel(3*i+0,j)-arc1.vVel(3*i+0,j),\n                                       arc2.vVel(3*i+1,j)-arc1.vVel(3*i+1,j),\n                                       arc2.vVel(3*i+2,j)-arc1.vVel(3*i+2,j));\n          if(computeAcceleration)\n          acc12.at(j).at(i) = Vector3d(arc2.vAcc(3*i+0,j)-arc1.vAcc(3*i+0,j),\n                                       arc2.vAcc(3*i+1,j)-arc1.vAcc(3*i+1,j),\n                                       arc2.vAcc(3*i+2,j)-arc1.vAcc(3*i+2,j));\n\n          e12.at(j).at(i) = normalize(pos12.at(j).at(i));\n        }\n      }\n\n      // =============================================\n\n      if(computeRange)\n      {\n        for(UInt i=0; i<epochCount; i++)\n        {\n          Matrix e = e12.at(0).at(i).vector().trans();\n          // dRange/dPos12\n          matMult(-1., e, arc1.VPos.row(3*i,3),         VSst.slice(i,0,1,3*epochCount));\n          matMult( 1., e, arc2.VPos.row(3*i,3),         VSst.slice(i,3*epochCount,1,3*epochCount));\n          matMult(-1., e, arc1.VPosBoundary.row(3*i,3), VSstBoundary.slice(i,0,1,6));\n          matMult( 1., e, arc2.VPosBoundary.row(3*i,3), VSstBoundary.slice(i,6,1,6));\n        }\n      }\n\n      if(computeVelocity)\n      {\n        for(UInt i=0; i<epochCount; i++)\n        {\n          const Double rho  = pos12.at(0).at(i).r();\n          const Double drho = inner(e12.at(0).at(i),vel12.at(0).at(i));\n\n          // dRate/dPos12\n          Matrix e = ((1/rho)*vel12.at(0).at(i) - (drho/rho) * e12.at(0).at(i)).vector().trans();\n          matMult(-1., e, arc1.VPos.row(3*i,3),         VSst.slice(i,0,1,3*epochCount));\n          matMult( 1., e, arc2.VPos.row(3*i,3),         VSst.slice(i,3*epochCount,1,3*epochCount));\n          matMult(-1., e, arc1.VPosBoundary.row(3*i,3), VSstBoundary.slice(i,0,1,6));\n          matMult( 1., e, arc2.VPosBoundary.row(3*i,3), VSstBoundary.slice(i,6,1,6));\n\n          // dRate/dVel12 = e12\n          e = e12.at(0).at(i).vector().trans();\n          matMult(-1., e, arc1.VVel.row(3*i,3),         VSst.slice(i,0,1,3*epochCount));\n          matMult( 1., e, arc2.VVel.row(3*i,3),         VSst.slice(i,3*epochCount,1,3*epochCount));\n          matMult(-1., e, arc1.VVelBoundary.row(3*i,3), VSstBoundary.slice(i,0,1,6));\n          matMult( 1., e, arc2.VVelBoundary.row(3*i,3), VSstBoundary.slice(i,6,1,6));\n        }\n      }\n\n      if(computeAcceleration)\n      {\n        for(UInt i=0; i<epochCount; i++)\n        {\n          const Double rho  = pos12.at(0).at(i).r();\n          const Double drho = inner(e12.at(0).at(i),vel12.at(0).at(i));\n\n          // dAccl/dPos12\n          Matrix e = ((1/rho) * acc12.at(0).at(i)\n                   - (2*drho/(rho*rho)) * vel12.at(0).at(i)\n                   + (3*drho*drho/(rho*rho) - vel12.at(0).at(i).quadsum()/(rho*rho)-inner(e12.at(0).at(i),acc12.at(0).at(i))/rho) * e12.at(0).at(i)).vector().trans();\n          matMult(-1., e, arc1.VPos.row(3*i,3),         VSst.slice(i,0,1,3*epochCount));\n          matMult( 1., e, arc2.VPos.row(3*i,3),         VSst.slice(i,3*epochCount,1,3*epochCount));\n          matMult(-1., e, arc1.VPosBoundary.row(3*i,3), VSstBoundary.slice(i,0,1,6));\n          matMult( 1., e, arc2.VPosBoundary.row(3*i,3), VSstBoundary.slice(i,6,1,6));\n\n          // dAccl/dVel12\n          e = ((2/rho) * vel12.at(0).at(i) - (2*drho/rho) * e12.at(0).at(i)).vector().trans();\n          matMult(-1., e, arc1.VVel.row(3*i,3),         VSst.slice(i,0,1,3*epochCount));\n          matMult( 1., e, arc2.VVel.row(3*i,3),         VSst.slice(i,3*epochCount,1,3*epochCount));\n          matMult(-1., e, arc1.VVelBoundary.row(3*i,3), VSstBoundary.slice(i,0,1,6));\n          matMult( 1., e, arc2.VVelBoundary.row(3*i,3), VSstBoundary.slice(i,6,1,6));\n\n          // dAccl/dAcc12 = e12\n          e = e12.at(0).at(i).vector().trans();\n          matMult(-1., e, arc1.VAcc.row(3*i,3),         VSst.slice(i,0,1,3*epochCount));\n          matMult( 1., e, arc2.VAcc.row(3*i,3),         VSst.slice(i,3*epochCount,1,3*epochCount));\n          matMult(-1., e, arc1.VAccBoundary.row(3*i,3), VSstBoundary.slice(i,0,1,6));\n          matMult( 1., e, arc2.VAccBoundary.row(3*i,3), VSstBoundary.slice(i,6,1,6));\n        }\n      }\n\n      // =============================================\n\n      // reference observations\n      // ----------------------\n      for(UInt j=0; j<rhsCount; j++)\n        for(UInt i=0; i<epochCount; i++)\n        {\n          const Double rho  = pos12.at(j).at(i).r();\n          const Double drho = inner(e12.at(j).at(i), vel12.at(j).at(i));\n\n          if(computeRange)        lSst0(i,j) = rho;\n          if(computeVelocity)     lSst0(i,j) = drho;\n          if(computeAcceleration) lSst0(i,j) = inner(e12.at(j).at(i),acc12.at(j).at(i)) + (1/rho) * (vel12.at(j).at(i).quadsum() - drho*drho);\n        }\n\n      // reduced observations\n      // ----------------------\n      for(UInt j=0; j<rhsCount; j++)\n        for(UInt k=0; k<sst.at(j).size(); k++)\n          for(UInt i=0; i<epochCount; i++)\n          {\n            if(computeRange)        lSst(i,j) += sst.at(j).at(k).at(i).range;\n            if(computeVelocity)     lSst(i,j) += sst.at(j).at(k).at(i).rangeRate;\n            if(computeAcceleration) lSst(i,j) += sst.at(j).at(k).at(i).rangeAcceleration;\n          }\n      lSst -= lSst0;\n\n      // =============================================\n\n      // satellite tracking parameter\n      // ----------------------------\n      for(UInt i=0; i<countSst; i++)\n        rotSat1.at(i) = starCamera1.at(i).rotary;\n      for(UInt i=0; i<countSst; i++)\n        rotSat2.at(i) = starCamera2.at(i).rotary;\n\n      parameterSst->compute(sstType, times, lSst0.column(0), arc1.vPos, arc2.vPos, arc1.vVel, arc2.vVel, rotSat1, rotSat2, SstPara, SstParaArc);\n    } // if(countSst)\n\n\n    // =============================================\n\n    Matrix lPos1, VPos1, VPosBoundary1;\n    Matrix lPos2, VPos2, VPosBoundary2;\n    integralEquation.interpolateArc(pod1, orbit1, arc1, lPos1, VPos1, VPosBoundary1);\n    integralEquation.interpolateArc(pod2, orbit2, arc2, lPos2, VPos2, VPosBoundary2);\n    arc1 = IntegralEquation::Arc();\n    arc2 = IntegralEquation::Arc();\n\n    // =============================================\n\n    // observation vector\n    // ------------------\n    Matrix l(obsCount, rhsCount);\n    if(countSst)  copy(lSst,  l.row(idxSst,  countSst));\n    if(countPod1) copy(lPos1, l.row(idxPod1, countPod1));\n    if(countPod2) copy(lPos2, l.row(idxPod2, countPod2));\n\n    // =============================================\n\n    // integration of accelerations to observations\n    // --------------------------------------------\n    Matrix V(obsCount, 6*epochCount);\n    if(countSst)  copy(VSst,  V.slice(idxSst,  0,            countSst,  6*epochCount));\n    if(countPod1) copy(VPos1, V.slice(idxPod1, 0,            countPod1, 3*epochCount));\n    if(countPod2) copy(VPos2, V.slice(idxPod2, 3*epochCount, countPod2, 3*epochCount));\n    VSst = VPos1 = VPos2 = Matrix();\n\n    // =============================================\n\n    // arc related parameters (satellite state + acceleration calibration)\n    // -------------------------------------------------------------------\n    Matrix B(obsCount, countBParameter); // 4 boundary pos. (x,y,z) + AccCal + CalKBandArc\n\n    // satellite parameters\n    if(Sat1Arc.size()) matMult(1., V.column(0,           3*epochCount), Sat1Arc, B.column(idxSat1Arc, Sat1Arc.columns()));\n    if(Sat2Arc.size()) matMult(1., V.column(3*epochCount,3*epochCount), Sat2Arc, B.column(idxSat2Arc, Sat2Arc.columns()));\n    Sat1Arc = Sat2Arc = Matrix();\n\n    // satellite tracking parameters\n    if(SstParaArc.size()) copy(SstParaArc, B.slice(idxSst, idxSstParaArc, countSst, SstParaArc.columns()));\n    SstParaArc = Matrix();\n\n    // boundaries (satellite state vector)\n    if(!keepSatelliteStates)\n    {\n      if(countSst)  copy(VSstBoundary.column(0,6), B.slice(idxSst,  idxBound1, countSst,  6));\n      if(countSst)  copy(VSstBoundary.column(6,6), B.slice(idxSst,  idxBound2, countSst,  6));\n      if(countPod1) copy(VPosBoundary1,            B.slice(idxPod1, idxBound1, countPod1, 6));\n      if(countPod2) copy(VPosBoundary2,            B.slice(idxPod2, idxBound2, countPod2, 6));\n      VSstBoundary = VPosBoundary1 = VPosBoundary2 = Matrix();\n    }\n\n    // =============================================\n\n    // Design matrix A (calibration part)\n    // ----------------------------------\n    Matrix A(obsCount, countAParameter);\n\n    // satellite parameters\n    if(Sat1.size()) matMult(1., V.column(0,           3*epochCount), Sat1, A.column(idxSat1, Sat1.columns()));\n    if(Sat2.size()) matMult(1., V.column(3*epochCount,3*epochCount), Sat2, A.column(idxSat2, Sat2.columns()));\n    Sat1 = Sat2 = Matrix();\n\n    // satellite tracking parameters\n    if(SstPara.size()) copy(SstPara, A.slice(idxSst, idxSstPara, countSst, SstPara.columns()));\n    SstPara = Matrix();\n\n    // boundaries (satellite state vector)\n    if(keepSatelliteStates)\n    {\n      if(countSst)  copy(VSstBoundary.column(0,6), A.slice(idxSst,  idxBound1+6*arcNo, countSst,  6));\n      if(countSst)  copy(VSstBoundary.column(6,6), A.slice(idxSst,  idxBound2+6*arcNo, countSst,  6));\n      if(countPod1) copy(VPosBoundary1,            A.slice(idxPod1, idxBound1+6*arcNo, countPod1, 6));\n      if(countPod2) copy(VPosBoundary2,            A.slice(idxPod2, idxBound2+6*arcNo, countPod2, 6));\n      VSstBoundary = VPosBoundary1 = VPosBoundary2 = Matrix();\n    }\n\n    // =============================================\n\n    // decorrelation\n    // -------------\n    if(covSst  && countSst)  covSst->decorrelate (arcNo, times,      {l.row(idxSst,  countSst),  V.row(idxSst,  countSst),  B.row(idxSst,  countSst),  A.slice(idxSst,  gravityCount, countSst,  countAParameter-gravityCount)});\n    if(covPod1 && countPod1) covPod1->decorrelate(arcNo, pod1.at(0), {l.row(idxPod1, countPod1), V.row(idxPod1, countPod1), B.row(idxPod1, countPod1), A.slice(idxPod1, gravityCount, countPod1, countAParameter-gravityCount)});\n    if(covPod2 && countPod2) covPod2->decorrelate(arcNo, pod2.at(0), {l.row(idxPod2, countPod2), V.row(idxPod2, countPod2), B.row(idxPod2, countPod2), A.slice(idxPod2, gravityCount, countPod2, countAParameter-gravityCount)});\n\n    // =============================================\n\n    // Design matrix A (gravity)\n    // -------------------------\n    if(gravityCount)\n    {\n      Matrix G(3*epochCount, gravityCount);\n      for(UInt k=0; k<epochCount; k++)\n        parameterGravity->gravity(orbit1.at(k).time, rotEarth.at(k).rotate(orbit1.at(k).position), G.row(3*k,3));\n      matMult(1., V.column(0,3*epochCount), G, A.column(idxGravity, gravityCount));\n\n      for(UInt k=0; k<epochCount; k++)\n        parameterGravity->gravity(orbit2.at(k).time, rotEarth.at(k).rotate(orbit2.at(k).position), G.row(3*k,3));\n      matMult(1., V.column(3*epochCount,3*epochCount), G, A.column(idxGravity, gravityCount));\n    }\n\n    // =============================================\n\n    Arc observationArc;\n    observationArc.l     = l;\n    observationArc.A     = A;\n    observationArc.B     = B;\n    observationArc.times = {times, pod1.front().times(), pod2.front().times()};\n    observationArc.pod1  = pod1.front();\n    observationArc.pod2  = pod2.front();\n    return observationArc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscSstIntegral.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscSstIntegral.h\n*\n* @brief Satellite to satellite tracking (Short Arc Integral).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICSSTINTEGRAL__\n#define __GROOPS_OBSERVATIONMSICSSTINTEGRAL__\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"misc/observation/integralEquation.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"misc/observation/observationMiscSst.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscSstIntegral;\ntypedef std::shared_ptr<ObservationMiscSstIntegral> ObservationMiscSstIntegralPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite to satellite tracking (Short Arc Integral).\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscSstIntegral : public ObservationMiscSst\n{\n  SatelliteModelPtr                   satellite1;\n  SatelliteModelPtr                   satellite2;\n  std::vector<SstRightSidePtr>        rhs; // right hand sides\n  IntegralEquation                    integralEquation;\n  Bool                                keepSatelliteStates;\n  InstrumentFile                      orbit1File, orbit2File;\n  InstrumentFile                      starCamera1File, starCamera2File;\n  EarthRotationPtr                    earthRotation;\n  EphemeridesPtr                      ephemerides;\n  GravityfieldPtr                     gradientfield;\n  ParametrizationGravityPtr           parameterGravity;\n  ParametrizationAccelerationPtr      parameterAcceleration1;\n  ParametrizationAccelerationPtr      parameterAcceleration2;\n  ParametrizationSatelliteTrackingPtr parameterSst;\n  UInt                                integrationDegree;\n  UInt                                interpolationDegree;\n  UInt                                countArc;\n  UInt                                sstType; // 0: biased range, 1: range-rate, 2: range-acceleration\n  Bool                                computeRange, computeVelocity, computeAcceleration;\n\n  // Indicies for design matrix A\n  UInt countAParameter;\n  UInt idxGravity, gravityCount;\n  UInt idxBound1,  idxBound2;\n  UInt idxSat1, idxSat2;\n  UInt idxSstPara;\n\npublic:\n  ObservationMiscSstIntegral(Config &config);\n ~ObservationMiscSstIntegral() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount()          const override {return countAParameter;}\n  UInt gravityParameterCount()   const override {return gravityCount;}\n  UInt rightSideCount()          const override {return rhs.size();}\n  UInt arcCount()                const override {return countArc;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  Arc computeArc(UInt arcNo, CovarianceSstPtr covSst, CovariancePodPtr covPod1, CovariancePodPtr covPod2) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/observationMiscSstVariational.cpp",
    "content": "/***********************************************/\n/**\n* @file observationMiscSstVariational.cpp\n*\n* @brief Satellite to satellite tracking (Variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"misc/observation/variationalEquation.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"observationMiscSstVariational.h\"\n\n/***********************************************/\n\nObservationMiscSstVariational::ObservationMiscSstVariational(Config &config)\n{\n  try\n  {\n    std::vector<FileName> fileNameSst;\n    FileName              fileNamePod1, fileNamePod2;\n    FileName              fileNameVariational1, fileNameVariational2;\n    UInt                  integrationDegree;\n    sstType = 0;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",       date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"parameter1\",     \"parametrizationAcceleration1\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"parameter2\",     \"parametrizationAcceleration2\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"parameterSst\",   \"parametrizationSst\",           date2time(2020, 6, 3));\n\n    if(readConfigSequence(config, \"rightHandSide\", Config::MUSTSET, \"\", \"input for observation vectors\"))\n    {\n      readConfig(config, \"inputfileSatelliteTracking\", fileNameSst,  Config::MUSTSET,  \"\", \"ranging observations and corrections\");\n      readConfig(config, \"inputfileOrbit1\",            fileNamePod1, Config::OPTIONAL, \"\", \"kinematic positions of satellite A as observations\");\n      readConfig(config, \"inputfileOrbit2\",            fileNamePod2, Config::OPTIONAL, \"\", \"kinematic positions of satellite B as observations\");\n      endSequence(config);\n    }\n    std::string choice;\n    if(readConfigChoice(config, \"sstType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"range\",     choice, \"\")) sstType = 0;\n      if(readConfigChoiceElement(config, \"rangeRate\", choice, \"\")) sstType = 1;\n      if(readConfigChoiceElement(config, \"none\",      choice, \"\")) sstType = 99;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileVariational1\",        fileNameVariational1,   Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"inputfileVariational2\",        fileNameVariational2,   Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"ephemerides\",                  ephemerides,            Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationGravity\",       parameterGravity,       Config::DEFAULT,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration1\", parameterAcceleration1, Config::DEFAULT,  \"\",    \"orbit1 force parameters\");\n    readConfig(config, \"parametrizationAcceleration2\", parameterAcceleration2, Config::DEFAULT,  \"\",    \"orbit2 force parameters\");\n    readConfig(config, \"parametrizationSst\",           parameterSst,           Config::DEFAULT,  \"\",    \"satellite tracking parameter\");\n    readConfig(config, \"integrationDegree\",            integrationDegree,      Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",          interpolationDegree,    Config::DEFAULT,  \"7\",   \"orbit interpolation by polynomial approximation of degree n\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    // init\n    // ----\n    sstFile.resize(fileNameSst.size());\n    for(UInt i=0; i<fileNameSst.size(); i++)\n      sstFile.at(i) = InstrumentFile::newFile(fileNameSst.at(i));\n    pod1File.open(fileNamePod1);\n    pod2File.open(fileNamePod2);\n\n    // test instrument files\n    // ---------------------\n    for(UInt i=1; i<sstFile.size(); i++)\n      InstrumentFile::checkArcCount({*sstFile.at(i), *sstFile.at(0)});\n    if(sstFile.size())\n      InstrumentFile::checkArcCount({pod1File, *sstFile.at(0)});\n    InstrumentFile::checkArcCount({pod2File, pod1File});\n\n    countArc = std::max(pod1File.arcCount(), pod2File.arcCount());\n    if(sstFile.size()) countArc = std::max(countArc, sstFile.at(0)->arcCount());\n    computeVelocity = (sstType==1);\n\n    variationalEquation1.open(fileNameVariational1, parameterGravity, parameterAcceleration1, std::vector<Time>(), ephemerides, integrationDegree);\n    variationalEquation2.open(fileNameVariational2, parameterGravity, parameterAcceleration2, std::vector<Time>(), ephemerides, integrationDegree);\n\n    // =======================\n\n    // count parameters\n    // ----------------\n    gravityCount = variationalEquation1.parameterCountGravity();\n    state1Count  = variationalEquation1.parameterCount() - gravityCount;\n    state2Count  = variationalEquation2.parameterCount() - gravityCount;\n\n    countAParameter = 0;\n    idxGravity  = countAParameter; countAParameter += gravityCount;\n    idxState1   = countAParameter; countAParameter += state1Count;\n    idxState2   = countAParameter; countAParameter += state2Count;\n    idxSstPara  = countAParameter; countAParameter += parameterSst->parameterCount();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool ObservationMiscSstVariational::setInterval(const Time &timeStart, const Time &timeEnd)\n{\n  try\n  {\n    Bool change = FALSE;\n    change = parameterGravity->setInterval(timeStart, timeEnd)       || change;\n    change = parameterAcceleration1->setInterval(timeStart, timeEnd) || change;\n    change = parameterAcceleration2->setInterval(timeStart, timeEnd) || change;\n    change = parameterSst->setInterval(timeStart, timeEnd)           || change;\n    if(!change)\n      return FALSE;\n    variationalEquation1.computeIndices();\n    variationalEquation2.computeIndices();\n\n    // count parameters\n    // ----------------\n    gravityCount = variationalEquation1.parameterCountGravity();\n    state1Count  = variationalEquation1.parameterCount() - gravityCount;\n    state2Count  = variationalEquation2.parameterCount() - gravityCount;\n\n    countAParameter = 0;\n    idxGravity  = countAParameter; countAParameter += gravityCount;\n    idxState1   = countAParameter; countAParameter += state1Count;\n    idxState2   = countAParameter; countAParameter += state2Count;\n    idxSstPara  = countAParameter; countAParameter += parameterSst->parameterCount();\n\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscSstVariational::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    parameterGravity->parameterName(name);\n\n    std::vector<ParameterName> name1;\n    variationalEquation1.parameterName(name1);\n    const std::string satelliteName1 = variationalEquation1.satellite() ? variationalEquation1.satellite()->satelliteName : \"satellite1\";\n    for(UInt i=gravityCount; i<name1.size(); i++)\n    {\n      name1.at(i).object = satelliteName1;\n      name.push_back(name1.at(i));\n    }\n\n    std::vector<ParameterName> name2;\n    variationalEquation2.parameterName(name2);\n    const std::string satelliteName2 = variationalEquation2.satellite() ? variationalEquation2.satellite()->satelliteName : \"satellite2\";\n    for(UInt i=gravityCount; i<name2.size(); i++)\n    {\n      name2.at(i).object = satelliteName2;\n      name.push_back(name2.at(i));\n    }\n\n    parameterSst->parameterName(name);\n    for(UInt i=name.size()-parameterSst->parameterCount(); i<name.size(); i++)\n      name.at(i).object = satelliteName1+\".\"+satelliteName2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationMiscSstVariational::Arc ObservationMiscSstVariational::computeArc(UInt arcNo, CovarianceSstPtr covSst, CovariancePodPtr covPod1, CovariancePodPtr covPod2)\n{\n  try\n  {\n    // read SST observations\n    // ---------------------\n    std::vector<SatelliteTrackingArc> sst(sstFile.size());\n    for(UInt k=0; k<sstFile.size(); k++)\n      sst.at(k) = sstFile.at(k)->readArc(arcNo);\n    for(UInt k=1; k<sst.size(); k++)\n      ::Arc::checkSynchronized({sst.at(0), sst.at(k)});\n    const std::vector<Time> timesSst = (sst.size() && (sstType!=99)) ? sst.at(0).times() : std::vector<Time>();\n\n    // read POD observations\n    // ---------------------\n    OrbitArc pod1 = pod1File.readArc(arcNo);\n    OrbitArc pod2 = pod2File.readArc(arcNo);\n    const std::vector<Time> timesPod1 = pod1.times();\n    const std::vector<Time> timesPod2 = pod2.times();\n\n    // Init variational equations\n    // --------------------------\n    Time timeStart(std::numeric_limits<Int>::max(), 0), timeEnd;\n    if(timesSst.size())  {timeStart = std::min(timeStart, timesSst.front());  timeEnd = std::max(timeEnd, timesSst.back());}\n    if(timesPod1.size()) {timeStart = std::min(timeStart, timesPod1.front()); timeEnd = std::max(timeEnd, timesPod1.back());}\n    if(timesPod2.size()) {timeStart = std::min(timeStart, timesPod2.front()); timeEnd = std::max(timeEnd, timesPod2.back());}\n    const VariationalEquationArc &arc1 = variationalEquation1.getArc(timeStart);\n    const VariationalEquationArc &arc2 = variationalEquation2.getArc(timeStart);\n\n    if((arc1.times != arc2.times) || (timeStart < arc1.times.front()) || (arc1.times.back() < timeEnd))\n      throw(Exception(\"no variational arc found for [\"+timeStart.dateTimeStr()+\", \"+timeEnd.dateTimeStr()+\"]\"));\n\n    // integration times (and interpolation intervals inbetween)\n    auto iterStart = std::upper_bound(arc1.times.begin(), arc1.times.end(), timeStart)-1;\n    auto iterEnd   = std::lower_bound(arc1.times.begin(), arc1.times.end(), timeEnd)+1;\n    std::vector<Time> times;\n    std::copy(iterStart, iterEnd, std::back_inserter(times));\n\n    // count observations and calculate index\n    // --------------------------------------\n    UInt obsCount = 0;\n    const UInt idxSst  = obsCount; obsCount += timesSst.size();\n    const UInt idxPod1 = obsCount; obsCount += 3*timesPod1.size();\n    const UInt idxPod2 = obsCount; obsCount += 3*timesPod2.size();\n\n    // arc related parameters (in matrix B)\n    // ------------------------------------\n    if(timesSst.size()) parameterSst->setIntervalArc(timesSst.front(), timesSst.back()+medianSampling(timesSst));\n    UInt countBParameter = 0;\n    const UInt idxSstParaArc = countBParameter; countBParameter += parameterSst->parameterCountArc();\n    if(obsCount <= countBParameter)\n      return Arc();\n\n    Matrix l(obsCount, 1);\n    Matrix A(obsCount, countAParameter);\n    Matrix B(obsCount, countBParameter);\n\n    // needed for parameterSst\n    Vector sstComputed(timesSst.size());\n    Vector sstPos1(3*timesSst.size()), sstPos2(3*timesSst.size());\n    Vector sstVel1(3*timesSst.size()), sstVel2(3*timesSst.size());\n\n    // observation equations within each integration interval\n    // ------------------------------------------------------\n    UInt idEpochSst=0, idEpochPod1=0, idEpochPod2=0;\n    std::vector<VariationalEquationFromFile::ObservationEquation> eqn1(interpolationDegree+1);\n    std::vector<VariationalEquationFromFile::ObservationEquation> eqn2(interpolationDegree+1);\n    for(UInt idInterval=0; idInterval<times.size()-1; idInterval++)\n    {\n      // integration of eqn1, eqn2  which are cyclicly updated\n      // -----------------------------------------------------\n      const UInt start = idInterval ? std::max(interpolationDegree+1, idInterval+(interpolationDegree+1)/2) : 0;\n      const UInt end   = std::min(std::max(idInterval+(interpolationDegree+1)/2+1, interpolationDegree+1), times.size());\n      for(UInt i=start; i<end; i++)\n      {\n        eqn1.at(i%eqn1.size()) = variationalEquation1.integrateArc(times.at(i), times.at(i), TRUE/*position*/, computeVelocity);\n        eqn2.at(i%eqn2.size()) = variationalEquation2.integrateArc(times.at(i), times.at(i), TRUE/*position*/, computeVelocity);\n      }\n\n      // satellite to satellite tracking\n      // -------------------------------\n      for(; (idEpochSst < timesSst.size()) && (timesSst.at(idEpochSst) <= times.at(idInterval+1)); idEpochSst++)\n      {\n        Matrix pos1, vel1, PosDesign1, VelDesign1;\n        Matrix pos2, vel2, PosDesign2, VelDesign2;\n        interpolate(timesSst.at(idEpochSst), eqn1, pos1, vel1, PosDesign1, VelDesign1, computeVelocity, interpolationDegree);\n        interpolate(timesSst.at(idEpochSst), eqn2, pos2, vel2, PosDesign2, VelDesign2, computeVelocity, interpolationDegree);\n\n        copy(pos1, sstPos1.row(3*idEpochSst, 3));\n        copy(pos2, sstPos2.row(3*idEpochSst, 3));\n        if(computeVelocity)\n        {\n          copy(vel1, sstVel1.row(3*idEpochSst, 3));\n          copy(vel2, sstVel2.row(3*idEpochSst, 3));\n        }\n\n        if(sstType == 0) // range\n        {\n          Vector3d e12(pos2-pos1);\n          const Double rho = e12.normalize();\n\n          sstComputed(idEpochSst) = rho;\n          for(UInt k=0; k<sst.size(); k++)\n            l(idxSst+idEpochSst, 0) += (sst.at(k).at(idEpochSst).range - sst.at(k).at(0).range);\n          l(idxSst+idEpochSst, 0) -= (sstComputed(idEpochSst)-sstComputed(0));\n\n          // dRange/dPos12\n          Matrix e = e12.vector().trans();\n          if(gravityCount)\n            matMult( 1., e, PosDesign2.column(0, gravityCount)-PosDesign1.column(0, gravityCount), A.slice(idxSst+idEpochSst, idxGravity, 1, gravityCount));\n          matMult(-1., e, PosDesign1.column(gravityCount, state1Count),  A.slice(idxSst+idEpochSst, idxState1,  1, state1Count));\n          matMult( 1., e, PosDesign2.column(gravityCount, state2Count),  A.slice(idxSst+idEpochSst, idxState2,  1, state2Count));\n        }\n        else if(sstType == 1) // range rate\n        {\n          Vector3d e12(pos2-pos1);\n          const Double rho = e12.normalize();\n          Vector3d vel12(vel2-vel1);\n          const Double drho = inner(e12, vel12);\n\n          sstComputed(idEpochSst) = drho;\n          for(UInt k=0; k<sst.size(); k++)\n            l(idxSst+idEpochSst,0) += sst.at(k).at(idEpochSst).rangeRate;\n          l(idxSst+idEpochSst,0) -= sstComputed(idEpochSst);\n\n          // dRate/dPos12\n          Matrix e = ((1/rho)*vel12 - (drho/rho) * e12).vector().trans();\n          if(gravityCount)\n            matMult( 1., e, PosDesign2.column(0, gravityCount)-PosDesign1.column(0, gravityCount), A.slice(idxSst+idEpochSst, idxGravity, 1, gravityCount));\n          matMult(-1., e, PosDesign1.column(gravityCount, state1Count),  A.slice(idxSst+idEpochSst, idxState1,  1, state1Count));\n          matMult( 1., e, PosDesign2.column(gravityCount, state2Count),  A.slice(idxSst+idEpochSst, idxState2,  1, state2Count));\n\n          // dRate/dVel12 = e12\n          e = e12.vector().trans();\n          if(gravityCount)\n            matMult( 1., e, VelDesign2.column(0, gravityCount)-VelDesign1.column(0, gravityCount), A.slice(idxSst+idEpochSst, idxGravity, 1, gravityCount));\n          matMult(-1., e, VelDesign1.column(gravityCount, state1Count),  A.slice(idxSst+idEpochSst, idxState1,  1, state1Count));\n          matMult( 1., e, VelDesign2.column(gravityCount, state2Count),  A.slice(idxSst+idEpochSst, idxState2,  1, state2Count));\n        }\n      } // for(idEpochSst)\n\n      // POD 1\n      // -----\n      for(; (idEpochPod1 < timesPod1.size()) && (timesPod1.at(idEpochPod1) <= times.at(idInterval+1)); idEpochPod1++)\n      {\n        Matrix pos1, vel1, PosDesign1, VelDesign1;\n        interpolate(timesPod1.at(idEpochPod1), eqn1, pos1, vel1, PosDesign1, VelDesign1, FALSE, interpolationDegree);\n\n        l(idxPod1+3*idEpochPod1+0, 0) = pod1.at(idEpochPod1).position.x();\n        l(idxPod1+3*idEpochPod1+1, 0) = pod1.at(idEpochPod1).position.y();\n        l(idxPod1+3*idEpochPod1+2, 0) = pod1.at(idEpochPod1).position.z();\n        l.row(idxPod1+3*idEpochPod1, 3) -= pos1;\n\n        if(gravityCount)\n          copy(PosDesign1.column(0, gravityCount),         A.slice(idxPod1+3*idEpochPod1, idxGravity, 3, gravityCount));\n        copy(PosDesign1.column(gravityCount, state1Count), A.slice(idxPod1+3*idEpochPod1, idxState1,  3, state1Count));\n      } // for(idEpochPod1)\n\n      // POD 2\n      // -----\n      for(; (idEpochPod2 < timesPod2.size()) && (timesPod2.at(idEpochPod2) <= times.at(idInterval+1)); idEpochPod2++)\n      {\n        Matrix pos2, vel2, PosDesign2, VelDesign2;\n        interpolate(timesPod2.at(idEpochPod2), eqn2, pos2, vel2, PosDesign2, VelDesign2, FALSE, interpolationDegree);\n\n        l(idxPod2+3*idEpochPod2+0, 0) = pod2.at(idEpochPod2).position.x();\n        l(idxPod2+3*idEpochPod2+1, 0) = pod2.at(idEpochPod2).position.y();\n        l(idxPod2+3*idEpochPod2+2, 0) = pod2.at(idEpochPod2).position.z();\n        l.row(idxPod2+3*idEpochPod2, 3) -= pos2;\n\n        if(gravityCount)\n          copy(PosDesign2.column(0, gravityCount),         A.slice(idxPod2+3*idEpochPod2, idxGravity, 3, gravityCount));\n        copy(PosDesign2.column(gravityCount, state2Count), A.slice(idxPod2+3*idEpochPod2, idxState2,  3, state2Count));\n      } // for(idEpochPod2)\n    } // for(idInterval)\n\n    // =============================================\n\n    if(parameterSst && timesSst.size())\n    {\n      parameterSst->compute(sstType, timesSst, sstComputed, sstPos1, sstPos2, sstVel1, sstVel2,\n                            interpolateStarCamera(timesSst, arc1.times, arc1.rotSat, 1),  // linear interpolation\n                            interpolateStarCamera(timesSst, arc2.times, arc2.rotSat, 1),\n                            A.slice(idxSst, idxSstPara,    timesSst.size(), parameterSst->parameterCount()),\n                            B.slice(idxSst, idxSstParaArc, timesSst.size(), parameterSst->parameterCountArc()));\n    }\n\n    // =============================================\n\n    // decorrelation\n    // -------------\n    if(covSst  && timesSst.size())  covSst->decorrelate (arcNo, timesSst, {l.row(idxSst,  timesSst.size()),    A.row(idxSst,  timesSst.size()),    B.row(idxSst,  timesSst.size())});\n    if(covPod1 && timesPod1.size()) covPod1->decorrelate(arcNo, pod1,     {l.row(idxPod1, 3*timesPod1.size()), A.row(idxPod1, 3*timesPod1.size()), B.row(idxPod1, 3*timesPod1.size())});\n    if(covPod2 && timesPod2.size()) covPod2->decorrelate(arcNo, pod2,     {l.row(idxPod2, 3*timesPod2.size()), A.row(idxPod2, 3*timesPod2.size()), B.row(idxPod2, 3*timesPod2.size())});\n\n   // =============================================\n\n    Arc observationArc;\n    observationArc.l     = l;\n    observationArc.A     = A;\n    observationArc.B     = B;\n    observationArc.times = {timesSst, timesPod1, timesPod2};\n    observationArc.pod1  = pod1;\n    observationArc.pod2  = pod2;\n    return observationArc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ObservationMiscSstVariational::interpolate(const Time &time, const std::vector<VariationalEquationFromFile::ObservationEquation> &eqn,\n                                                Matrix &pos0, Matrix &vel0, Matrix &PosDesign, Matrix &VelDesign, Bool computeVelocity, UInt degree)\n{\n  try\n  {\n    // time matches? -> no interpolation needed\n    for(auto &e : eqn)\n      if(std::fabs((time-e.times.front()).seconds()) < 1e-9)\n      {\n        pos0      = e.pos0;\n        PosDesign = e.PosDesign;\n        if(computeVelocity) vel0      = e.vel0;\n        if(computeVelocity) VelDesign = e.VelDesign;\n        return;\n      }\n\n    // time does not match, interpolation required\n    // -------------------------------------------\n    // polynomial interpolation matrix\n    Matrix W(degree+1, degree+1);\n    for(UInt i=0; i<W.rows(); i++)\n    {\n      const Double dt = (eqn.at(i).times.front()-time).seconds();\n      W(i, 0) = 1.0;\n      for(UInt n=1; n<W.columns(); n++)\n        W(i, n) = dt * W(i, n-1);\n    }\n    inverse(W); // interpolation weights are the first line of W^-1, because a_0 is the first column\n\n    pos0      = W(0, 0) * eqn.front().pos0;\n    PosDesign = W(0, 0) * eqn.front().PosDesign;\n    if(computeVelocity) vel0      = W(0, 0) * eqn.front().vel0;\n    if(computeVelocity) VelDesign = W(0, 0) * eqn.front().VelDesign;\n    for(UInt k=1; k<eqn.size(); k++)\n    {\n      axpy(W(0, k), eqn.at(k).pos0,      pos0);\n      axpy(W(0, k), eqn.at(k).PosDesign, PosDesign);\n      if(computeVelocity) axpy(W(0, k), eqn.at(k).vel0,      vel0);\n      if(computeVelocity) axpy(W(0, k), eqn.at(k).VelDesign, VelDesign);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Rotary3d> ObservationMiscSstVariational::interpolateStarCamera(const std::vector<Time> &timesNew, const std::vector<Time> &times, const std::vector<Rotary3d> &rot, UInt degree)\n{\n  try\n  {\n    Matrix A(4, rot.size());\n    for(UInt i=0; i<rot.size(); i++)\n      copy(rot.at(i).quaternion(), A.column(i));\n\n    for(UInt i=1; i<A.columns(); i++)\n      if(inner(A.column(i-1), A.column(i)) < 0)\n        A.column(i) *= -1.;\n\n    Polynomial polynomial(times, degree);\n    A = polynomial.interpolate(timesNew, A.trans()).trans();\n\n    std::vector<Rotary3d> rotNew(A.columns());\n    for(UInt i=0; i<rotNew.size(); i++)\n      rotNew.at(i) = Rotary3d(A.column(i)/norm(A.column(i)));\n\n    return rotNew;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/observationMiscSstVariational.h",
    "content": "/***********************************************/\n/**\n* @file observationMiscSstVariational.h\n*\n* @brief Satellite to satellite tracking (Variational equations).\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-06-02\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_OBSERVATIONMSICSSTVARIATIONAL__\n#define __GROOPS_OBSERVATIONMSICSSTVARIATIONAL__\n\n/***********************************************/\n\n#include \"files/fileInstrument.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/parametrizationSatelliteTracking/parametrizationSatelliteTracking.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"misc/observation/observationMiscSst.h\"\n\n/***** TYPES ***********************************/\n\nclass ObservationMiscSstVariational;\ntypedef std::shared_ptr<ObservationMiscSstVariational> ObservationMiscSstVariationalPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite to satellite tracking (Variational equations).\n* @ingroup miscGroup\n* @see Observation */\nclass ObservationMiscSstVariational : public ObservationMiscSst\n{\npublic:\n  std::vector<InstrumentFilePtr>      sstFile;\n  VariationalEquationFromFile         variationalEquation1, variationalEquation2;\n  InstrumentFile                      pod1File, pod2File;\n  UInt                                interpolationDegree;\n  UInt                                countArc;\n  UInt                                sstType; // 0: biased range, 1: range-rate\n  Bool                                computeVelocity;\n  EphemeridesPtr                      ephemerides;\n  ParametrizationGravityPtr           parameterGravity;\n  ParametrizationAccelerationPtr      parameterAcceleration1, parameterAcceleration2;\n  ParametrizationSatelliteTrackingPtr parameterSst;\n\n  // Indicies for design matrix A\n  UInt countAParameter;\n  UInt idxGravity,      gravityCount;\n  UInt idxState1,       state1Count;\n  UInt idxState2,       state2Count;\n  UInt idxSstPara;\n\n  static void interpolate(const Time &time, const std::vector<VariationalEquationFromFile::ObservationEquation> &eqn,\n                          Matrix &pos0, Matrix &vel0, Matrix &PosDesign, Matrix &VelDesign, Bool computeVelocity, UInt degree);\n\n  static std::vector<Rotary3d> interpolateStarCamera(const std::vector<Time> &timesNew,\n                                                     const std::vector<Time> &times, const std::vector<Rotary3d> &rot, UInt degree);\n\npublic:\n  ObservationMiscSstVariational(Config &config);\n ~ObservationMiscSstVariational() {}\n\n  Bool setInterval(const Time &timeStart, const Time &timeEnd) override;\n  UInt parameterCount()          const override {return countAParameter;}\n  UInt gravityParameterCount()   const override {return gravityCount;}\n  UInt rightSideCount()          const override {return 1;}\n  UInt arcCount()                const override {return countArc;}\n  void parameterName(std::vector<ParameterName> &name) const override;\n\n  Arc computeArc(UInt arcNo, CovarianceSstPtr covSst, CovariancePodPtr covPod1, CovariancePodPtr covPod2) override;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/misc/observation/variationalEquation.cpp",
    "content": "/***********************************************/\n/**\n* @file variationalEquation.cpp\n*\n* @brief Variational equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-05-29\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"variationalEquation.h\"\n\n/***********************************************/\n\nVariationalEquation::VariationalEquation() : parameterCount_(0), gravityCount(0), satCount(0), satArcCount(0)\n{\n}\n\n/***********************************************/\n\nvoid VariationalEquation::init(SatelliteModelPtr satellite, const std::vector<ParametrizationGravityPtr> &parametersGravity,\n                               ParametrizationAccelerationPtr parameterAcceleration, const std::vector<Time> &stochasticPulse,\n                               EphemeridesPtr ephemerides, UInt integrationDegree)\n{\n  try\n  {\n    this->satellite             = satellite;\n    this->parametersGravity     = parametersGravity;\n    this->parameterAcceleration = parameterAcceleration;\n    this->timePulse             = stochasticPulse;\n    this->ephemerides           = ephemerides;\n    this->integrationDegree     = integrationDegree;\n\n    // count parameters\n    // ----------------\n    computeIndices();\n\n    // integration in [idx,idx+1]\n    // --------------------------\n    if(coeffIntegral.size() != integrationDegree)\n    {\n      coeffIntegral.resize(integrationDegree);\n      for(UInt idx=0; idx<coeffIntegral.size(); idx++)\n      {\n        // polynomial matrix\n        Matrix W(integrationDegree+1, integrationDegree+1);\n        for(UInt i=0; i<W.columns(); i++)\n        {\n          W(i,0) = 1.;\n          for(UInt n=1; n<W.rows(); n++)\n            W(i,n) = (Double(i)-idx) * W(i,n-1);\n        }\n        inverse(W);\n\n        coeffIntegral.at(idx)  = Vector(W.rows());\n        for(UInt i=0; i<W.rows(); i++)\n          for(UInt n=0; n<W.columns(); n++)\n            coeffIntegral.at(idx)(i)  += 1./(n+1.) * W(n,i);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::computeIndices()\n{\n  try\n  {\n    parameterCount_ = 0;\n\n    idxGravity   = parameterCount_;\n    gravityCount = 0;\n    for(auto parameterGravity : parametersGravity)\n      if(parameterGravity)\n        gravityCount += parameterGravity->parameterCount();\n    parameterCount_ += gravityCount;\n\n    idxSat           = parameterCount_;\n    satCount         = (parameterAcceleration) ? parameterAcceleration->parameterCount() : 0;\n    idxPulse         = parameterCount_ + satCount;\n    satCount        += 3*timePulse.size();\n    parameterCount_ += satCount;\n\n    idxSatArc        = parameterCount_;\n    satArcCount      = (parameterAcceleration) ? parameterAcceleration->parameterCountArc() + 6 : 6; // inclusive state vector\n    parameterCount_ += satArcCount;\n\n    idEpochAlpha = NULLINDEX; // current arc is invalid\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::setArc(VariationalEquationArc &arc)\n{\n  try\n  {\n    arc_ = arc;\n    if(arc_.times.size() == 0)\n      throw(Exception(\"empty arc\"));\n\n    if(parameterAcceleration && parameterAcceleration->setIntervalArc(arc_.times.at(0), arc_.times.back()+medianSampling(arc_.times)))\n      computeIndices();\n\n    initIntegration();\n\n    // init pulses\n    // -----------\n    stochasticPulse.clear();\n    stochasticPulse.resize(timePulse.size());\n    for(UInt i=0; i<timePulse.size(); i++)\n    {\n      if(timePulse.at(i)>=arc_.times.back()) break;\n      if(timePulse.at(i)<=arc_.times.at(0))  continue;\n      UInt idEpoch = 0;\n      while(timePulse.at(i)>=arc_.times.at(idEpoch+1))\n        idEpoch++;\n      stochasticPulse.at(i) = Matrix(6, 3);\n      stochasticPulse.at(i)(3,0) = stochasticPulse.at(i)(4,1) = stochasticPulse.at(i)(5,2) = 1e-6; // [mum/s]\n      Matrix Z(6,6);\n      copy(arc_.PosState.row(3*idEpoch,3), Z.row(0,3));\n      copy(arc_.VelState.row(3*idEpoch,3), Z.row(3,3));\n      solveInPlace(Z, stochasticPulse.at(i));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::parameterName(std::vector<ParameterName> &name) const\n{\n  parameterNameGravity(name);\n  parameterNameSatellite(name);\n  parameterNameSatelliteArc(name);\n}\n\n/***********************************************/\n\nvoid VariationalEquation::parameterNameGravity(std::vector<ParameterName> &name) const\n{\n  for(auto parameterGravity : parametersGravity)\n    if(parameterGravity)\n      parameterGravity->parameterName(name);\n}\n\n/***********************************************/\n\nvoid VariationalEquation::parameterNameSatellite(std::vector<ParameterName> &name) const\n{\n  const std::string satelliteName = satellite ? satellite->satelliteName : \"satellite\";\n  if(parameterAcceleration)\n  {\n    parameterAcceleration->parameterName(name);\n    for(UInt i=name.size(); i-->name.size()-parameterAcceleration->parameterCount();)\n      name.at(i).object = satelliteName;\n  }\n\n  for(UInt i=0; i<timePulse.size(); i++)\n  {\n    name.push_back(ParameterName(satelliteName, \"stochasticPulse.x\", \"\", timePulse.at(i)));\n    name.push_back(ParameterName(satelliteName, \"stochasticPulse.y\", \"\", timePulse.at(i)));\n    name.push_back(ParameterName(satelliteName, \"stochasticPulse.z\", \"\", timePulse.at(i)));\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::parameterNameSatelliteArc(std::vector<ParameterName> &name) const\n{\n  const std::string satelliteName = satellite ? satellite->satelliteName : \"satellite\";\n  if(parameterAcceleration)\n  {\n    parameterAcceleration->parameterNameArc(name);\n    for(UInt i=name.size(); i-->name.size()-parameterAcceleration->parameterCountArc();)\n      name.at(i).object = satelliteName;\n  }\n\n  name.push_back(ParameterName(satelliteName, \"position0.x\"));\n  name.push_back(ParameterName(satelliteName, \"position0.y\"));\n  name.push_back(ParameterName(satelliteName, \"position0.z\"));\n  name.push_back(ParameterName(satelliteName, \"velocity0.x\"));\n  name.push_back(ParameterName(satelliteName, \"velocity0.y\"));\n  name.push_back(ParameterName(satelliteName, \"velocity0.z\"));\n}\n\n/***********************************************/\n\nvoid VariationalEquation::position(UInt idEpoch, MatrixSliceRef pos0, MatrixSliceRef PosDesign)\n{\n  try\n  {\n    if(arc_.times.size() == 0)\n      throw(Exception(\"no variational arc given\"));\n    if(idEpoch>=arc_.times.size())\n      throw(Exception(\"epoch outside arc\"));\n\n    computeAlpha(idEpoch);\n\n    // gravity and satellite parameters\n    // --------------------------------\n    if(gravityCount+satCount)\n      matMult(1., arc_.PosState.row(3*idEpoch,3), Alpha.column(0, gravityCount+satCount), PosDesign.column(0, gravityCount+satCount));\n\n    // stochastic pulses\n    // -----------------\n    for(UInt i=0; i<timePulse.size(); i++)\n    {\n      if(stochasticPulse.at(i).size()==0)\n        continue;\n      if(timePulse.at(i) > arc_.times.at(idEpoch))\n        break;\n      matMult(1., arc_.PosState.row(3*idEpoch,3), stochasticPulse.at(i), PosDesign.column(3*i+idxPulse, 3));\n    }\n\n    // arc related parameters\n    // ----------------------\n    if(satArcCount-6)\n      matMult(1., arc_.PosState.row(3*idEpoch,3), Alpha.column(gravityCount+satCount, satArcCount-6), PosDesign.column(idxSatArc, satArcCount-6));\n\n    // satellite state\n    // ---------------\n    copy(arc_.PosState.row(3*idEpoch,3), PosDesign.column(idxSatArc+satArcCount-6, 6));\n    copy(arc_.pos0.row(3*idEpoch,3), pos0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::velocity(UInt idEpoch, MatrixSliceRef vel0, MatrixSliceRef VelDesign)\n{\n  try\n  {\n    if(arc_.times.size() == 0)\n      throw(Exception(\"no variational arc given\"));\n    if(idEpoch>=arc_.times.size())\n      throw(Exception(\"epoch outside arc\"));\n\n    computeAlpha(idEpoch);\n\n    // gravity and satellite parameters\n    // --------------------------------\n    if(gravityCount+satCount)\n      matMult(1., arc_.VelState.row(3*idEpoch,3), Alpha.column(0, gravityCount+satCount), VelDesign.column(0, gravityCount+satCount));\n\n    // stochastic pulses\n    // -----------------\n    for(UInt i=0; i<timePulse.size(); i++)\n    {\n      if(stochasticPulse.at(i).size()==0)\n        continue;\n      if(timePulse.at(i) >  arc_.times.at(idEpoch))\n        break;\n      matMult(1., arc_.VelState.row(3*idEpoch,3), stochasticPulse.at(i), VelDesign.column(3*i+idxPulse, 3));\n    }\n\n    // arc related parameters\n    // ----------------------\n    if(satArcCount-6)\n      matMult(1., arc_.VelState.row(3*idEpoch,3), Alpha.column(gravityCount+satCount, satArcCount-6), VelDesign.column(idxSatArc, satArcCount-6));\n\n    // satellite state\n    // ---------------\n    copy(arc_.VelState.row(3*idEpoch,3), VelDesign.column(idxSatArc+satArcCount-6, 6));\n    copy(arc_.vel0.row(3*idEpoch,3), vel0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::initIntegration()\n{\n  try\n  {\n    Alpha        = Matrix(6, parameterCount_-6); // without satellite state\n    idEpochAlpha = 0;\n    idCoeff      = 0;\n    deltaT       = (arc_.times.at(1) - arc_.times.at(0)).seconds();\n    Integrand.resize(integrationDegree+1);\n    for(UInt i=0; i<Integrand.size(); i++)\n      Integrand.at(i) = computeIntegrand(i);\n    idIntegrand  = Integrand.size();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquation::computeAlpha(UInt idEpoch)\n{\n  try\n  {\n    if((idEpoch<idEpochAlpha) || (idEpochAlpha==NULLINDEX))\n      initIntegration(); // start integration at beginning\n\n    if(Alpha.size() == 0)\n      return;\n\n    while(idEpochAlpha < idEpoch)\n    {\n      idEpochAlpha++; // next epoch to integrate\n\n      // integration\n      for(UInt i=0; i<coeffIntegral.at(idCoeff).rows(); i++)\n        axpy(deltaT*coeffIntegral.at(idCoeff)(i), Integrand.at((idIntegrand+i)%Integrand.size()), Alpha);\n\n      if((idEpochAlpha<(integrationDegree+1)/2) || (idEpochAlpha+(integrationDegree+1)/2 >= arc_.times.size()))\n        idCoeff++; // select next integration interval within polynomial\n      else\n      {\n        // shift integration polynomial: replace oldest integrand\n        Integrand.at(idIntegrand % Integrand.size()) = computeIntegrand(idIntegrand);\n        idIntegrand++;\n      }\n    } // while(idEpochAlpha < idEpoch)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix VariationalEquation::computeIntegrand(UInt idEpoch)\n{\n  try\n  {\n    if(Alpha.columns()==0)\n      return Matrix(6,0);\n\n    Vector3d pos  = Vector3d(arc_.pos0(3*idEpoch+0,0),\n                             arc_.pos0(3*idEpoch+1,0),\n                             arc_.pos0(3*idEpoch+2,0));\n    Vector3d vel  = Vector3d(arc_.vel0(3*idEpoch+0,0),\n                             arc_.vel0(3*idEpoch+1,0),\n                             arc_.vel0(3*idEpoch+2,0));\n\n    Matrix F(6, Alpha.columns());\n    UInt col = 0;\n    for(auto parameterGravity : parametersGravity)\n      if(parameterGravity)\n      {\n        parameterGravity->gravity(arc_.times.at(idEpoch), arc_.rotEarth.at(idEpoch).rotate(pos), F.slice(3, idxGravity+col, 3, parameterGravity->parameterCount()));\n        col += parameterGravity->parameterCount();\n      }\n    if(satCount || satArcCount)\n    {\n      parameterAcceleration->compute(satellite, arc_.times.at(idEpoch), pos, vel, arc_.rotSat.at(idEpoch), arc_.rotEarth.at(idEpoch), ephemerides,\n                                     F.slice(3, idxSat, 3, satCount), F.slice(3, idxSatArc, 3, satArcCount-6));\n    }\n\n    Matrix Z(6,6);\n    matMult(1., arc_.rotEarth.at(idEpoch).matrix(), arc_.PosState.row(3*idEpoch,3), Z.row(0,3));\n    matMult(1., arc_.rotEarth.at(idEpoch).matrix(), arc_.VelState.row(3*idEpoch,3), Z.row(3,3));\n    solveInPlace(Z, F);\n\n    return F;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/variationalEquation.h",
    "content": "/***********************************************/\n/**\n* @file variationalEquation.h\n*\n* @brief Variational equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-05-29\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_VARIATIONALEQUATION__\n#define __GROOPS_VARIATIONALEQUATION__\n\n#include \"files/fileSatelliteModel.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Variational equations.\n* @ingroup miscGroup */\nclass VariationalEquation\n{\npublic:\n  VariationalEquation();\n\n  void init(SatelliteModelPtr satellite, const std::vector<ParametrizationGravityPtr> &parameterGravity,\n            ParametrizationAccelerationPtr parameterAcceleration, const std::vector<Time> &stochasticPulse,\n            EphemeridesPtr ephemerides, UInt integrationDegree);\n\n  void setArc(VariationalEquationArc &arc);\n\n  const VariationalEquationArc &arc() const {return arc_;}\n\n  /** @brief recompute parameter count.\n  * Must only be called if parameters in @a parameterGravity\n  * or @a parameterAcceleration are changed (via @a setInterval).\n  * Current arc becomes invalid and initArc must be called */\n  void computeIndices();\n\n  /** @brief Total number of unknown parameters.\n  * Design matrix (PosDesign, VelDesign) includes\n  * 1. gravity field parameters\n  * 2. satellite parameters\n  * 3. arc related parameters (inclusive 6 satellite state param). */\n  UInt parameterCount() const {return parameterCount_;}\n\n  /** @brief Number of gravity field parameters.\n  * The parameterCount of Representation.*/\n  UInt parameterCountGravity() const {return gravityCount;}\n\n  /** @brief Number of unknown satellite related parameters.\n  Includes stochastic pulses (x,y,z). */\n  UInt parameterCountSatellite() const {return satCount;}\n\n  /** @brief Number of unknown arc related parameters.\n  * Includes satellite state (6 parameter). */\n  UInt parameterCountSatelliteArc() const {return satArcCount;}\n\n  /** @brief Names of all parameters, includes\n  * 1. gravity field parameters)\n  * 2. satellite parameters\n  * 3. arc related parameters (inclusive 6 satellite state param).\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Names of gravity field parameters.\n  * The names are appended to @a name. */\n  void parameterNameGravity(std::vector<ParameterName> &name) const;\n\n  /** @brief Names of satellite related parameters.\n  * The names are appended to @a name. */\n  void parameterNameSatellite(std::vector<ParameterName> &name) const;\n\n  /** @brief Names of arc related parameters.\n  * The names are appended to @a name. */\n  void parameterNameSatelliteArc(std::vector<ParameterName> &name) const;\n\n  /** @brief Setup observation equations.\n  * @param idEpoch from VariationalEquationArc.\n  * @param[out] pos0 (3 x 1) reference position.\n  * @param[out] PosDesign (3 x parameterCount()) Design matrix. */\n  void position(UInt idEpoch, MatrixSliceRef pos0, MatrixSliceRef PosDesign);\n\n  /** @brief Setup observation equations.\n  * @param idEpoch from VariationalEquationArc.\n  * @param[out] vel0 (3 x 1) reference velocity.\n  * @param[out] VelDesign (3 x parameterCount()) design matrix. */\n  void velocity(UInt idEpoch, MatrixSliceRef vel0, MatrixSliceRef VelDesign);\n\nprivate:\n  SatelliteModelPtr                      satellite;\n  VariationalEquationArc                 arc_;\n  EphemeridesPtr                         ephemerides;\n  std::vector<ParametrizationGravityPtr> parametersGravity;\n  ParametrizationAccelerationPtr         parameterAcceleration;\n  std::vector<Time>                      timePulse;\n  std::vector<Matrix>                    stochasticPulse;\n\n\n  UInt  parameterCount_;\n  UInt  idxGravity, gravityCount;\n  UInt  idxSat,     satCount;\n  UInt  idxPulse;\n  UInt  idxSatArc,  satArcCount;\n\n  // integration\n  UInt                integrationDegree;\n  std::vector<Vector> coeffIntegral;\n  UInt                idCoeff;\n  Double              deltaT;\n  UInt                idEpochAlpha;\n  Matrix              Alpha;\n  UInt                idIntegrand;\n  std::vector<Matrix> Integrand;\n\n  void   initIntegration();\n  void   computeAlpha(UInt idEpoch);\n  Matrix computeIntegrand(UInt idEpoch);\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/observation/variationalEquationFromFile.cpp",
    "content": "/***********************************************/\n/**\n* @file variationalEquationFromFile.cpp\n*\n* @brief Variational equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-24\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"misc/observation/variationalEquation.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::open(const FileName &fileName, ParametrizationGravityPtr parameterGravity, ParametrizationAccelerationPtr parameterAcceleration,\n                                       const std::vector<Time> &stochasticPulse, EphemeridesPtr ephemerides, UInt integrationDegree)\n{\n  try\n  {\n    file.open(fileName);\n\n    variationalEquation.init(file.satellite(), {parameterGravity}, parameterAcceleration, stochasticPulse, ephemerides, integrationDegree);\n    arcNo = 0;\n    VariationalEquationArc arc = file.readArc(arcNo);\n    variationalEquation.setArc(arc);\n    computeIndices();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::close()\n{\n  try\n  {\n    file.close();\n    _parameterCount = 0;\n    gravityCount = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::computeIndices()\n{\n  try\n  {\n    variationalEquation.computeIndices();\n\n    _parameterCount  = 0;\n\n    idxGravity       = _parameterCount;\n    gravityCount     = variationalEquation.parameterCountGravity();\n    _parameterCount += gravityCount;\n\n    idxSat           = _parameterCount;\n    satCount         = variationalEquation.parameterCountSatellite();\n    _parameterCount += satCount;\n\n    idxSatArc        = _parameterCount;\n    satArcCount      = variationalEquation.parameterCountSatelliteArc();\n    _parameterCount += file.arcCount() * satArcCount;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::parameterName(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    parameterNameGravity(name);\n    parameterNameSatellite(name);\n    parameterNameSatelliteArc(name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::parameterNameGravity(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    variationalEquation.parameterNameGravity(name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::parameterNameSatellite(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    variationalEquation.parameterNameSatellite(name);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariationalEquationFromFile::parameterNameSatelliteArc(std::vector<ParameterName> &name) const\n{\n  try\n  {\n    std::vector<ParameterName> nameArc;\n    variationalEquation.parameterNameSatelliteArc(nameArc);\n    for(UInt arcNo=0; arcNo<arcCount(); arcNo++)\n    {\n      const std::string str = \"arc\"+arcNo%\"%i\"s+\".\";\n      for(UInt i=0; i<nameArc.size(); i++)\n      {\n        ParameterName param = nameArc.at(i);\n        param.type = str+param.type;\n        name.push_back(param);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVariationalEquationFromFile::ObservationEquation VariationalEquationFromFile::integrateArc(Time timeStart, Time timeEnd, Bool computePosition, Bool computeVelocity)\n{\n  try\n  {\n    const VariationalEquationArc &arc = getArc(timeStart);\n    if(timeEnd > arc.times.back())\n    {\n      timeEnd = arc.times.back();\n//       throw(Exception(\"cannot integrate over different variational arcs (\"+timeStart.dateTimeStr()+\" - \"+timeEnd.dateTimeStr()+\") vs. (\"+arc.times.at(0).dateTimeStr()+\" - \"+arc.times.back().dateTimeStr()+\")\"));\n    }\n\n    // find epoch interval\n    const UInt epochStart = std::distance(arc.times.begin(), std::upper_bound(arc.times.begin(), arc.times.end(), timeStart))-1;\n    const UInt epochEnd   = std::distance(arc.times.begin(), std::lower_bound(arc.times.begin(), arc.times.end(), timeEnd));\n    ObservationEquation eqn;\n    for(UInt idEpoch=epochStart; idEpoch<=epochEnd; idEpoch++)\n      eqn.times.push_back(arc.times.at(idEpoch));\n\n    if(computePosition)\n    {\n      eqn.pos0      = Vector(3*eqn.times.size());\n      eqn.PosDesign = Matrix(3*eqn.times.size(), parameterCount());\n    }\n    if(computeVelocity)\n    {\n      eqn.vel0      = Vector(3*eqn.times.size());\n      eqn.VelDesign = Matrix(3*eqn.times.size(), parameterCount());\n    }\n    eqn.rotSat.resize(eqn.times.size());\n    eqn.rotEarth.resize(eqn.times.size());\n\n    for(UInt i=0; i<eqn.times.size(); i++)\n    {\n      const UInt idEpoch = epochStart+i;\n\n      if(computePosition)\n      {\n        Matrix PosDesign(3, variationalEquation.parameterCount());\n        variationalEquation.position(idEpoch, eqn.pos0.row(3*i,3), PosDesign);\n        if(gravityCount+satCount)\n          copy(PosDesign.column(0, gravityCount+satCount), eqn.PosDesign.slice(3*i,0,3,gravityCount+satCount));\n        if(satArcCount)\n          copy(PosDesign.column(idxSatArc, satArcCount), eqn.PosDesign.slice(3*i,idxSatArc+arcNo*satArcCount,3,satArcCount));\n      }\n\n      if(computeVelocity)\n      {\n        Matrix VelDesign(3, variationalEquation.parameterCount());\n        variationalEquation.velocity(idEpoch, eqn.vel0.row(3*i,3), VelDesign);\n        if(gravityCount+satCount)\n          copy(VelDesign.column(0, gravityCount+satCount), eqn.VelDesign.slice(3*i,0,3,gravityCount+satCount));\n        if(satArcCount)\n          copy(VelDesign.column(idxSatArc, satArcCount), eqn.VelDesign.slice(3*i,idxSatArc+arcNo*satArcCount,3,satArcCount));\n      }\n\n      eqn.rotSat.at(i)   = arc.rotSat.at(idEpoch);\n      eqn.rotEarth.at(i) = arc.rotEarth.at(idEpoch);\n    } // for(i=times)\n\n    return eqn;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nconst VariationalEquationArc &VariationalEquationFromFile::getArc(const Time &time)\n{\n  try\n  {\n    if((variationalEquation.arc().times.front() <= time) && (time <= variationalEquation.arc().times.back()))\n      return variationalEquation.arc();\n\n    // restart file?\n    VariationalEquationArc arc = variationalEquation.arc();\n    if(time < arc.times.front())\n      arc = file.readArc(arcNo = 0);\n\n    // find arc\n    while((time > arc.times.back()) && (++arcNo < file.arcCount()))\n      arc = file.readArc(arcNo);\n\n    if((time > arc.times.back()) || (time < arc.times.front()))\n      throw(Exception(\"no variational arc found for \"+time.dateTimeStr()));\n\n    const UInt countOld = variationalEquation.parameterCountSatellite();\n    variationalEquation.setArc(arc);\n    if(variationalEquation.parameterCountSatellite() != countOld)\n      throw(Exception(\"size of arc related parameters changed from arc to arc.\"));\n\n    return variationalEquation.arc();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVariationalEquationArc VariationalEquationFromFile::refineVariationalEquationArc(UInt arcNo, const_MatrixSliceRef x)\n{\n  try\n  {\n    const UInt countOld = variationalEquation.parameterCountSatellite();\n    VariationalEquationArc arc = file.readArc(arcNo);\n    variationalEquation.setArc(arc);\n    if(variationalEquation.parameterCountSatellite() != countOld)\n      throw(Exception(\"size of arc related parameters changed from arc to arc.\"));\n\n    for(UInt idEpoch=0; idEpoch<arc.times.size(); idEpoch++)\n    {\n      Vector pos0(3);\n      Matrix PosDesign(3, variationalEquation.parameterCount());\n      variationalEquation.position(idEpoch, pos0, PosDesign);\n\n      Vector vel0(3);\n      Matrix VelDesign(3, variationalEquation.parameterCount());\n      variationalEquation.velocity(idEpoch, vel0, VelDesign);\n\n      if(gravityCount+satCount)\n      {\n        matMult(1, PosDesign.column(0, gravityCount+satCount), x.slice(0, 0, gravityCount+satCount, 1), arc.pos0.row(3*idEpoch,3));\n        matMult(1, VelDesign.column(0, gravityCount+satCount), x.slice(0, 0, gravityCount+satCount, 1), arc.vel0.row(3*idEpoch,3));\n      }\n\n      if(satArcCount)\n      {\n        matMult(1, PosDesign.column(idxSatArc, satArcCount), x.slice(idxSatArc+arcNo*satArcCount, 0, satArcCount, 1), arc.pos0.row(3*idEpoch,3));\n        matMult(1, VelDesign.column(idxSatArc, satArcCount), x.slice(idxSatArc+arcNo*satArcCount, 0, satArcCount, 1), arc.vel0.row(3*idEpoch,3));\n      }\n    } // for(idEpoch)\n\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/misc/observation/variationalEquationFromFile.h",
    "content": "/***********************************************/\n/**\n* @file variationalEquationFromFile.h\n*\n* @brief Variational equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-03-24\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_VARIATIONALEQUATIONFROMFILE__\n#define __GROOPS_VARIATIONALEQUATIONFROMFILE__\n\n#include \"files/fileVariationalEquation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"misc/observation/variationalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Variational equations.\n* @ingroup miscGroup */\nclass VariationalEquationFromFile\n{\npublic:\n  /** @brief Linearized observation equations. */\n  class ObservationEquation\n  {\n    public:\n    std::vector<Time> times;\n\n    Matrix pos0;      //!< Reference positions (Taylor point of linearization).\n    Matrix PosDesign; //!< Design matrix, partial derivatives of positions with respect to parameters.\n\n    Matrix vel0;      //!< Reference velocities (Taylor point of linearization).\n    Matrix VelDesign; //!< Design matrix, partial derivatives of velocities with respect to parameters.\n\n    std::vector<Rotary3d> rotSat;\n    std::vector<Rotary3d> rotEarth;\n  };\n\n  /// Default Constructor.\n  VariationalEquationFromFile() : _parameterCount(0), gravityCount(0) {}\n\n  /// Destructor.\n  ~VariationalEquationFromFile() {}\n\n  /** @brief Open a new file.\n  * Old open file is closed before. */\n  void open(const FileName &fileName, ParametrizationGravityPtr parameterGravity, ParametrizationAccelerationPtr parameterAcceleration,\n            const std::vector<Time> &stochasticPulse, EphemeridesPtr ephemerides, UInt integrationDegree);\n\n  /** @brief Close the file. */\n  void close();\n\n  /** @brief Number of Arc in file. */\n  UInt arcCount() const {return file.arcCount();}\n\n  /** @brief Satellite model. */\n  SatelliteModelPtr satellite() const {return file.satellite();}\n\n  /** @brief recompute parameter count.\n  * Must only be called if parameters in @a parameterGravity\n  * or @a parameterAcceleration are changed.\n  * Current arc becomes invalid. */\n  void computeIndices();\n\n  /** @brief Total number of unknown parameters.\n  * Design matrix (PosDesign, VelDesign) includes\n  * 1. gravity field parameters\n  * 2. satellite parameters\n  * 3. arc related parameters (inclusive 6 satellite state param). */\n  UInt parameterCount() const {return _parameterCount;}\n\n  /** @brief Number of gravity field parameters.\n  * The parameterCount of Representation.*/\n  UInt parameterCountGravity() const {return gravityCount;}\n\n  /** @brief Number of unknown satellite related parameters.\n  Includes stochastic pulses (x,y,z). */\n  UInt parameterCountSatellite() const {return satCount;}\n\n  /** @brief Number of unknown arc related parameters.\n  * Includes satellite state (6 parameter). */\n  UInt parameterCountSatelliteArc() const {return satArcCount;}\n\n  /** @brief Names of all parameters, includes\n  * 1. gravity field parameters\n  * 2. satellite parameters\n  * 3. arc related parameters (inclusive 6 satellite state param).\n  * The names are appended to @a name. */\n  void parameterName(std::vector<ParameterName> &name) const;\n\n  /** @brief Names of gravity field parameters.\n  * The names are appended to @a name. */\n  void parameterNameGravity(std::vector<ParameterName> &name) const;\n\n  /** @brief Names of satellite related parameters.\n  * The names are appended to @a name. */\n  void parameterNameSatellite(std::vector<ParameterName> &name) const;\n\n  /** @brief Names of arc related parameters.\n  * The names are appended to @a name. */\n  void parameterNameSatelliteArc(std::vector<ParameterName> &name) const;\n\n  /** @brief Setup observation equations. */\n  ObservationEquation integrateArc(Time timeStart, Time timeEnd, Bool computePosition, Bool computeVelocity);\n\n  VariationalEquationArc refineVariationalEquationArc(UInt arcNo, const_MatrixSliceRef x);\n\n  const VariationalEquationArc &getArc(const Time &time);\n\nprivate:\n  FileVariationalEquation file;\n  UInt                    arcNo;\n  VariationalEquation     variationalEquation;\n\n  UInt  _parameterCount;\n  UInt  idxGravity, gravityCount;\n  UInt  idxSat,     satCount;\n  UInt  idxSatArc,  satArcCount;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/misc/varianceComponentEstimation.cpp",
    "content": "/***********************************************/\n/**\n* @file varianceComponentEstimation.cpp\n*\n* @brief Variance Component Estimation (VCE).\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-10-17\n*\n*/\n/***********************************************/\n\n#include <random>\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/fileMatrix.h\"\n#include \"varianceComponentEstimation.h\"\n\n/***********************************************/\n\nMatrix Vce::monteCarlo(UInt rows, UInt columns)\n{\n  // init random generator\n  static std::mt19937_64 generator;\n  static Bool init = FALSE;\n  if(!init)\n  {\n   std::random_device randomDevice;\n   generator.seed(randomDevice());\n   init = TRUE;\n  }\n\n  Matrix e(rows, columns);\n  std::uniform_int_distribution<Int> binary(0,1);\n  for(UInt i=0; i<rows; i++)\n    for(UInt k=0; k<columns; k++)\n      e(i, k) = binary(generator) * 2 - 1;\n  return 1./std::sqrt(columns) * e;\n}\n\n/***********************************************/\n\nDouble Vce::standardDeviation(Double ePe, Double redundancy, Double huber, Double huberPower)\n{\n  static Double huber_      = NAN;\n  static Double huberPower_ = NAN;\n  static Double sum         = NAN;\n  if((huber_ == huber) && (huberPower_ == huberPower))\n    return std::sqrt(ePe/redundancy/sum);\n\n  constexpr Double dx = 1e-4;\n  huber_      = huber;\n  huberPower_ = huberPower;\n  sum         = 0;\n  Double x    = dx/2;\n\n  // variance of normal distribution\n  for(; x<std::min(huber, 10.); x+=dx)\n    sum += x*x * std::exp(-0.5*x*x) * dx;\n  // variance of downweighted normal distribution\n  for(; x<10.; x+=dx)\n    sum += x*x*std::pow(x/huber, -2*huberPower) * std::exp(-0.5*x*x) * dx;\n  sum *= 2./std::sqrt(2*PI);\n  return std::sqrt(ePe/redundancy/sum);\n}\n\n/***********************************************/\n\nMatrix Vce::robustLeastSquares(const_MatrixSliceRef A, const_MatrixSliceRef l, UInt countGroup,\n                               Double huber, Double huberPower, UInt maxIter, Vector &sigma)\n{\n  try\n  {\n    std::vector<UInt> indexGroup(l.rows()/countGroup+1);\n    indexGroup.at(0) = 0;\n    for(UInt i=1; i<indexGroup.size(); i++)\n      indexGroup.at(i) = indexGroup.at(i-1) + countGroup;\n    return robustLeastSquares(A, l, indexGroup, huber, huberPower, maxIter, sigma);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Vce::robustLeastSquares(const_MatrixSliceRef A, const_MatrixSliceRef l, const std::vector<UInt> &indexGroup,\n                               Double huber, Double huberPower, UInt maxIter, Vector &sigma)\n{\n  try\n  {\n    Matrix x;\n    UInt   countOutlier = 0;\n    Double sigma0 = 0;\n    sigma = Vector(indexGroup.size()-1, 1.);\n    for(UInt iter=0; iter<maxIter; iter++)\n    {\n      // weighting\n      Matrix Wl = l;\n      Matrix WA = A;\n      for(UInt i=0; i<sigma.rows(); i++)\n      {\n        Wl.row(indexGroup.at(i), indexGroup.at(i+1)-indexGroup.at(i)) *= 1./sigma(i);\n        WA.row(indexGroup.at(i), indexGroup.at(i+1)-indexGroup.at(i)) *= 1./sigma(i);\n      }\n\n      // QR decomposition\n      const Vector tau = QR_decomposition(WA);\n      QTransMult(WA, tau, Wl);           // transform observations: l:= Q'l\n      x = Wl.row(0, WA.columns());\n      triangularSolve(1., WA.row(0, WA.columns()), x);\n      Wl.row(0, WA.columns()).setNull(); // residuals: remove WB*x\n      QMult(WA, tau, Wl);                // back transformation\n      generateQ(WA, tau);                // for redundancies\n\n      if(sigma0 == 0.)\n        sigma0 = std::sqrt(quadsum(Wl)/(Wl.size()-x.size()));\n\n      // outlier detection\n      UInt   countOutlierNew = 0;\n      Double ePeSum = 0.;\n      Double rSum   = 0.;\n      for(UInt i=0; i<sigma.rows(); i++)\n      {\n        const Double ePe = quadsum(Wl.row(indexGroup.at(i), indexGroup.at(i+1)-indexGroup.at(i)))/Wl.columns();\n        const Double r   = indexGroup.at(i+1)-indexGroup.at(i) - quadsum(WA.row(indexGroup.at(i), indexGroup.at(i+1)-indexGroup.at(i)));\n        const Double s   = std::sqrt(ePe/r)*sigma(i)/sigma0;\n        ePeSum += ePe;\n        rSum   += r;\n        sigma(i) = 1.;\n        if((s > huber) && (r > 1e-4)) // redundancy: it is possible to estimate sigma?\n        {\n          sigma(i) = std::pow(s/huber, huberPower);\n          countOutlierNew++;\n        }\n      }\n\n      const Double sigma0New = standardDeviation(ePeSum, rSum, huber, huberPower);\n      if((countOutlierNew == 0) || ((countOutlier == countOutlierNew) && (std::fabs(sigma0New-sigma0)/sigma0 < 0.001)))\n        break;\n      sigma0       = sigma0New;\n      countOutlier = countOutlierNew;\n    } // for(iter)\n\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nMatrix Vce::cosTransform(UInt length)\n{\n  Matrix T(length, length);\n  if(!length)\n    return T;\n  for(UInt i=0; i<length; i++)\n    for(UInt k=0; k<length; k++)\n      T(i,k) = 2*std::cos(PI*i*k/(length-1));\n  T.column(0)        *= 0.5;\n  T.column(length-1) *= 0.5;\n  T *= 1./std::sqrt(2.*(length-1)); // normalize\n  return T;\n}\n\n/***********************************************/\n\nMatrix Vce::readCovarianceFunction(const FileName &name, UInt length, UInt columns, Double sampling)\n{\n  try\n  {\n    if(!name.empty())\n    {\n      Matrix covFunc;\n      readFileMatrix(name, covFunc);\n      if(covFunc.columns() != columns+1)\n        throw(Exception(\"input apriori covariance function <\"+name.str()+\"> seems not to be compatible\"));\n      if(covFunc.rows() < length)\n        throw(Exception(\"input apriori covariance function <\"+name.str()+\"> is too short\"));\n      if(covFunc.rows() && (std::fabs(covFunc(1,0)-covFunc(0,0)-sampling) > 1e-3)) // test sampling\n        throw(Exception(\"input apriori covariance function <\"+name.str()+\"> has wrong sampling\"));\n      return covFunc.row(0,length);\n    }\n\n    // default is white noise\n    Matrix covFunc(length, 1+columns);\n    for(UInt i=0; i<covFunc.rows(); i++)\n      covFunc(i,0) = i*sampling;\n    if(covFunc.rows())\n      for(UInt k=0; k<columns; k++)\n        covFunc(0,1+k) = 1.0;\n    return covFunc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Vce::redundancy(const_MatrixSliceRef W, const_MatrixSliceRef We, const_MatrixSliceRef WA, const_MatrixSliceRef WB,\n                     Matrix &R, Vector &WWe)\n{\n  try\n  {\n    // to compute e^T Sigma^-1 V_i Sigma^-1 e\n    // WWe = Sigma^-1 e with Sigma = W^T W\n    // (decorrelate again)\n    WWe = We;\n    triangularSolve(1., W, WWe);\n\n    // Compute redundancy\n    // R := Sigma^-1 - Sigma^-1 * (B A) * N^-1 * (B A)^T * Sigma^-1\n    //    = Sigma^-1 - W^(-1)*Q1*Q1^T*W^T - W^(-1)*Q2*WA*N^(-1)*N^T*WA^T*Q2^T*W^T\n    // ---------------------------------------------------------------------\n    R = W;\n    cholesky2Inverse(R);\n    if(WA.size())\n    {\n      Matrix WWA = WA;\n      triangularSolve(1., W, WWA);\n      rankKUpdate(-1., WWA.trans(), R);\n    }\n    if(WB.size())\n    {\n      Matrix WWB = WB;\n      triangularSolve(1., W, WWB);\n      rankKUpdate(-1., WWB.trans(), R);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Vce::matrix(const_MatrixSliceRef R, const_MatrixSliceRef WWe, const_MatrixSliceRef Cov,\n                 Double &ePe, Double &redundancy)\n{\n  try\n  {\n    Matrix CC = Cov;\n    Matrix RR = R;\n    fillSymmetric(RR);\n    fillSymmetric(CC);\n    ePe        += inner(WWe, CC * WWe); // e.T Sigma^-1 C Sigma^-1 e\n    redundancy += inner(CC, RR);        // trace(RC)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Vce::psd(const_MatrixSliceRef R, const_MatrixSliceRef WWe,\n              const std::vector<UInt> &index, Double sigma, const_MatrixSliceRef CosTransform, const_MatrixSliceRef Psd,\n              MatrixSliceRef ePe, MatrixSliceRef redundancy, Double &ePeSum, Double &redundancySum)\n{\n  try\n  {\n    const UInt countAxis = Psd.columns();\n    for(UInt idAxis=0; idAxis<countAxis; idAxis++)\n    {\n      Vector e(CosTransform.rows());\n      Vector r(CosTransform.rows());\n      for(UInt i=0; i<WWe.rows()/countAxis; i++)\n        for(UInt k=i; k<WWe.rows()/countAxis; k++)\n        {\n          e(index.at(k)-index.at(i)) += WWe(countAxis*i+idAxis,0)*WWe(countAxis*k+idAxis,0);\n          r(index.at(k)-index.at(i)) += R(countAxis*i+idAxis, countAxis*k+idAxis);\n        }\n      e.row(1, e.rows()-1) *= 2.; // consider lower triangular of matrix\n      r.row(1, r.rows()-1) *= 2.;\n\n      for(UInt idFreq=0; idFreq<Psd.rows(); idFreq++)\n      {\n        const_MatrixSliceRef cov(CosTransform.column(idFreq));\n        const Double ePeTmp        = pow(sigma,2) * Psd(idFreq, idAxis) * inner(e, cov);\n        const Double redundancyTmp = pow(sigma,2) * Psd(idFreq, idAxis) * inner(r, cov);\n        if((ePeTmp > 0) && !std::isnan(ePeTmp) && (redundancyTmp > 0) && !std::isnan(redundancyTmp))\n        {\n          ePe(idFreq, idAxis)        += ePeTmp;\n          redundancy(idFreq, idAxis) += redundancyTmp;\n          ePeSum                     += ePeTmp;\n          redundancySum              += redundancyTmp;\n        }\n      } // for(idFreq)\n    } // for(idAxis)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Vce::estimatePsd(MatrixSliceRef ePe, MatrixSliceRef redundancy, MatrixSliceRef Psd, Double &maxFactor, Bool jointZeroFrequency)\n{\n  try\n  {\n    if(!Psd.size())\n      return;\n\n    // freq=0, special case: mean is usually removed -> not estimable\n    // -> estimate first two frequencies together\n    if(jointZeroFrequency)\n    {\n      ePe.row(1)        += ePe.row(0);\n      redundancy.row(1) += redundancy.row(0);\n      copy(ePe.row(1),        ePe.row(0));\n      copy(redundancy.row(1), redundancy.row(0));\n    }\n\n    for(UInt idAxis=0; idAxis<Psd.columns(); idAxis++)\n      for(UInt idFreq=0; idFreq<Psd.rows(); idFreq++) // frequencies 0, 1,2,3 ...\n      {\n        Double factor = ePe(idFreq, idAxis)/redundancy(idFreq, idAxis);\n        if(std::isnan(factor) || (factor <= 0))\n        {\n          logWarning<<idFreq<<\". frequency, (idAxis=\"<<idAxis<<\") negative factor = \"<<ePe(idFreq, idAxis)<<\" / \"<<redundancy(idFreq, idAxis)<<Log::endl;\n          factor = 1;\n        }\n        Psd(idFreq, idAxis) *= factor;\n        maxFactor = std::max(maxFactor, sqrt(exp(fabs(log(factor)))));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Vce::meanSigma(const Vector &sigma)\n{\n  try\n  {\n    std::vector<Double> s = sigma;\n    std::sort(s.begin(), s.end());\n    s.erase(std::remove_if(s.begin(), s.end(), [](Double x){return x <= 0;}), s.end());\n    if(!s.size())\n      return 0;\n\n    const UInt begin  = s.size()/4;\n    const UInt end    = s.size()-s.size()/4;\n    Double     sigma0 = 0;\n    for(UInt i=begin; i<end; i++)\n      sigma0 += s.at(i)/(end-begin);\n    return sigma0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/misc/varianceComponentEstimation.h",
    "content": "/***********************************************/\n/**\n* @file varianceComponentEstimation.h\n*\n* @brief Variance Component Estimation (VCE).\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-10-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_VARIANCECOMPONENTESTIMATION__\n#define __GROOPS_VARIANCECOMPONENTESTIMATION__\n\n#include \"base/import.h\"\n#include \"inputOutput/fileName.h\"\n\n/***********************************************/\n\n/** @brief Variance Component Estimation (VCE).\n* @ingroup miscGroup */\nnamespace Vce\n{\n  /** @brief Random vector to estimate trace of a matrix\n  * The number of @p columns increases the reliability. */\n  Matrix monteCarlo(UInt rows, UInt columns);\n\n  /** @brief Estimates the standardDeviation in case of otuliers.\n  * The quadratic sum of residuals @p ePe and the @p redundancy are computed with downweigthed data. */\n  Double standardDeviation(Double ePe, Double redundancy, Double huber, Double huberPower);\n\n  /** @brief Robust least squares adjustment with multiple right hand sides.\n  * Each @p countGroup (e.g. 3 for x,y,z) of observations are down weighted\n  * if the estimated residuals are greater than @a huber times sigma0\n  * @f[ s = \\sqrt(e'Pe/r) > h\\sigma_0. @f] */\n  Matrix robustLeastSquares(const_MatrixSliceRef A, const_MatrixSliceRef l, UInt countGroup,\n                            Double huber, Double huberPower, UInt maxIter, Vector &sigma);\n\n  /** @brief Robust least squares adjustment with multiple right hand sides.\n  * Each group starting at @p indexGroup and size `indexGroup.at(i+1)-indexGroup.at(i)`\n  * (e.g. 3 for x,y,z) of observations are down weighted\n  * if the estimated residuals are greater than @a huber times sigma0\n  * @f[ s = \\sqrt(e'Pe/r) > h\\sigma_0. @f] */\n  Matrix robustLeastSquares(const_MatrixSliceRef A, const_MatrixSliceRef l, const std::vector<UInt> &indexGroup,\n                            Double huber, Double huberPower, UInt maxIter, Vector &sigma);\n\n  /** @brief Compute the cos transformation matrix.\n  * The matrix is normalized.\n  * Applying this matrix two times results in the original input.\n  * @code\n  *   Matrix A(length, length);\n  *   A(i,0) = 1/sqrt(2.*(length-1))\n  *   A(i,k) = 2*cos(PI*i*k/(length-1))/sqrt(2.*(length-1)) // for k=1..n-2\n  *   A(i,lenght-1) = (-1)**i/sqrt(2.*(length-1))\n  * @endcode */\n  Matrix cosTransform(UInt length);\n\n  /** @brief Read covariance function from file or construct default function.\n  * The covariance function must be saved as matrix.\n  * The first column contains the time steps in seconds.\n  * @param name file name (if empty a default cov function is contructed).\n  * @param length the length of the cov functions (number of epochs).\n  * @param columns number of expected covariance functions (e.g. 3 for orbits (along, cross, radial))\n  * @param sampling in seconds.\n  * @return columns number of covariance functions with length (plus sampling column). */\n  Matrix readCovarianceFunction(const FileName &name, UInt length, UInt columns, Double sampling);\n\n  /** @brief Compute redundancy matrix.\n  * This function is called for each arc with decorrelated observation equation (@a We, @a WA, @a WB).\n  * The covariance matrix @a W must be computed from @a CosTransform of the @a PSD.\n  @code                                                                                *\n  // covariance function for each axis.\n  UInt countAxis = PSD.columns(); // e.g. for orbits (along, cross, radial).\n  Matrix covFunc = CosTransform * PSD;\n\n  // Compute the covariance matrix from the covariance functions\n  Matrix Cov(index.size()*countAxis, Matrix::SYMMETRIC, Matrix::UPPER);\n  for(UInt i=0; i*countAxis < Cov.rows(); i++)\n    for(UInt k=i; k*countAxis < Cov.rows(); k++)\n      for(UInt idxAxis=0; idxAxis < countAxis; idxAxis++)\n        Cov(i*countAxis+idxAxis, k*countAxis+idxAxis) = cov(index.at(k)-index.at(i), idxAxis);\n  @endcode\n  The function returns the matrix of redundancies @a R and the weighted residuals @a WWe:\n  @code\n  WWe := Sigma^-1 e with Sigma = W^T W\n  R   := Sigma^-1 - Sigma^-1 * (B A) * N^-1 * (B A)^T * Sigma^-1\n        = Sigma^-1 - W^(-1)*Q1*Q1^T*W^T - W^(-1)*Q2*WA*N^(-1)*N^T*WA^T*Q2^T*W^T\n  @endcode\n  * @param W Cholesky decomposition of the covariance matrix.\n  * @param We Decorrelated residuals.\n  * @param WA Decorrelated design matrix.\n  * @param WB Decorrelated design matrix.\n  * @param[out] R Matrix of redundancies\n  * @param[out] WWe Sigma^-1 e\n  */\n  void redundancy(const_MatrixSliceRef W, const_MatrixSliceRef We,\n                  const_MatrixSliceRef WA, const_MatrixSliceRef WB,\n                  Matrix &R, Vector &WWe);\n\n  /** @brief Estimate frequency-wise variance factors for toeplitz covariance matrix.\n  * This function is called for each arc with the matrix of redundancies @a R and the\n  * weighted residuals @a WWe (see: computeRedundancy() ). This function computes the\n  * squared sum of residuals and the redundancy for each frequency (row of @a ePe) and\n  * component/axis (column).\n  * @param R Matrix of redundancies.\n  * @param WWe Weighted residuals Sigma^-1 e.\n  * @param index Index of observations in the covariance function.\n  * @param sigma Accuracy of the arc.\n  * @param CosTransform To transform PSD to covariance function.\n  * @param Psd Approximate PSD of the covariance function.\n  * @param[in,out] ePe Updated squared sum of residuals.\n  * @param[in,out] redundancy Updated for each axis (column) and frequency (row).\n  * @param[in,out] ePeSum The sum of @a ePe other all frequencies is added.\n  * @param[in,out] redundancySum The @a redundancy of ePe other all frequencies is added. */\n  void psd(const_MatrixSliceRef R, const_MatrixSliceRef WWe,\n           const std::vector<UInt> &index, Double sigma, const_MatrixSliceRef CosTransform, const_MatrixSliceRef Psd,\n           MatrixSliceRef ePe, MatrixSliceRef redundancy, Double &ePeSum, Double &redundancySum);\n\n  /** @brief Estimate variance factor for arbitrary covariance matrix.\n  * This function is called for each arc with the matrix of redundancies @a R and the\n  * weighted residuals @a WWe (see: computeRedundancy() ). This function computes the\n  * squared sum of residuals and the redundancy for an arbitrary covariance matrix @a Cov.\n  * @param R Matrix of redundancies.\n  * @param WWe Weighted residuals Sigma^-1 e.\n  * @param Cov Covariance matrix for which to determine variance factor.\n  * @param[in,out] ePe Square sum of residuals due to @a C is added.\n  * @param[in,out] redundancy Redundancy component due to @a C is added. */\n  void matrix(const_MatrixSliceRef R, const_MatrixSliceRef WWe, const_MatrixSliceRef Cov,\n              Double &ePe, Double &redundancy);\n\n  /** @brief Updates the PSD from residuals and redundancies.\n  * The PSD is updated by the factor ePe/redundancy for each axis (column) and frequency (row).\n  * The maximum change factor or 1/factor of all amplitudes is returned in @a maxFactor. */\n  void estimatePsd(MatrixSliceRef ePe, MatrixSliceRef redundancy, MatrixSliceRef Psd, Double &maxFactor, Bool jointZeroFrequency=TRUE);\n\n  /** @brief Robust estimation of the mean sigma.\n  * @a sigma contains the accuracy of each arc.\n  * Only 50% of the median values are used to compute the mean value. */\n  Double meanSigma(const Vector &sigma);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/parallel/matrixDistributed.cpp",
    "content": "/***********************************************/\n/**\n* @file matrixDistributed.cpp\n*\n* @brief Positve definte matrix in distributed memory.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2011-01-30\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"matrixDistributed.h\"\n\n/***********************************************/\n\nMatrixDistributed::MatrixDistributed() : _blockIndex{0}\n{\n  setCalculateRank(nullptr);\n}\n\n/***********************************************/\n\nMatrixDistributed::MatrixDistributed(const std::vector<UInt> &blockIndex, Parallel::CommunicatorPtr comm, const std::function<UInt(UInt, UInt, UInt)> &calcRank)\n{\n  init(blockIndex, comm, calcRank);\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::init(const std::vector<UInt> &blockIndex, Parallel::CommunicatorPtr comm, const std::function<UInt(UInt, UInt, UInt)> &calcRank)\n{\n  try\n  {\n    initEmpty(blockIndex, comm, calcRank);\n\n    for(UInt i=0; i<blockCount(); i++)\n      if(blockSize(i))\n        for(UInt k=i; k<blockCount(); k++)\n          if(blockSize(k))\n            setBlock(i, k);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::initEmpty(const std::vector<UInt> &blockIndex, Parallel::CommunicatorPtr comm, const std::function<UInt(UInt, UInt, UInt)> &calcRank)\n{\n  try\n  {\n    if(!std::is_sorted(blockIndex.begin(), blockIndex.end()))\n      throw(Exception(\"Block indices must be given in ascending order.\"));\n\n    if(blockIndex.front() != static_cast<UInt>(0))\n      throw(Exception(\"Block index must start with zero.\"));\n\n    this->comm  = comm;\n    _blockIndex = blockIndex;\n    _row        = std::vector<std::vector<std::pair<UInt, UInt>>>(blockCount());\n    _column     = std::vector<std::vector<std::pair<UInt, UInt>>>(blockCount());\n    _rank       = std::vector<UInt>();\n    _N          = std::vector<Matrix>();\n    setCalculateRank(calcRank);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nUInt MatrixDistributed::index(UInt row, UInt col) const\n{\n  if((row > blockCount()) || (col > blockCount()))\n    throw(Exception(\"Access to block (\"+row%\"%i\"s+\" x \"+col%\"%i\"s+\") out of range, matrix size (\"+blockCount()%\"%i\"s+\" x \"+blockCount()%\"%i\"s+\").\"));\n\n  const auto iter = std::lower_bound(_column[row].begin(), _column[row].end(), col, [](const auto &x, UInt col) {return x.first < col;});\n  if((iter != _column[row].end()) && (iter->first == col))\n    return iter->second;\n  return NULLINDEX;\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::loopBlockColumn(const std::array<UInt,2> &rows, UInt col, std::function<void(UInt, UInt)> block) const\n{\n  try\n  {\n    const auto &_row = this->_row.at(col);\n    for(UInt idx=0; idx<_row.size(); idx++)\n      if((rows[0] <= _row[idx].first) && (_row[idx].first < rows[1]))\n        block(_row[idx].first, _row[idx].second);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::loopBlockRow(UInt row, const std::array<UInt,2> &cols, std::function<void(UInt, UInt)> block) const\n{\n  try\n  {\n    const auto &_column = this->_column.at(row);\n    for(UInt idx=0; idx<_column.size(); idx++)\n      if((cols[0] <= _column[idx].first) && (_column[idx].first < cols[1]))\n        block(_column[idx].first, _column[idx].second);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstd::vector<Bool> MatrixDistributed::usedRanksInColumn(const std::array<UInt,2> &rows, UInt col) const\n{\n  try\n  {\n    std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n    loopBlockColumn(rows, col, [&](UInt /*row*/, UInt idx) {usedRank.at(_rank[idx]) = TRUE;});\n    return usedRank;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Bool> MatrixDistributed::usedRanksInRow(UInt row, const std::array<UInt,2> &cols) const\n{\n  try\n  {\n    std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n    loopBlockRow(row, cols, [&](UInt /*col*/, UInt idx) {usedRank.at(_rank[idx]) = TRUE;});\n    return usedRank;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::broadCast(Matrix &x, UInt idx, const std::vector<Bool> &usedRank)\n{\n  try\n  {\n    std::vector<UInt> ranks = {_rank[idx]};\n    for(UInt idProcess=0; idProcess<usedRank.size(); idProcess++)\n      if(usedRank.at(idProcess) && (idProcess != _rank[idx]))\n        ranks.push_back(idProcess);\n    if(ranks.size() < 2)\n      return;\n    Parallel::CommunicatorPtr commNew = Parallel::createCommunicator(ranks, comm);\n    if(commNew)\n      Parallel::broadCast(x, 0, commNew);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::reduceSum(Matrix &x, UInt idx, const std::vector<Bool> &usedRank, Bool free)\n{\n  try\n  {\n    std::vector<UInt> ranks = {_rank[idx]};\n    for(UInt idProcess=0; idProcess<usedRank.size(); idProcess++)\n      if(usedRank.at(idProcess) && (idProcess != _rank[idx]))\n        ranks.push_back(idProcess);\n    if(ranks.size() < 2)\n      return;\n    Parallel::CommunicatorPtr commNew = Parallel::createCommunicator(ranks, comm);\n    if(!commNew)\n      return;\n    Parallel::reduceSum(x, 0, commNew);\n    if(!isMyRank(idx))\n    {\n      if(free)\n        x = Matrix();\n      else\n        x.setNull();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nUInt MatrixDistributed::rank(UInt i, UInt k) const\n{\n  const UInt ik = index(i, k);\n  if(ik == NULLINDEX)\n    return NULLINDEX;\n  return _rank[ik];\n}\n\n/***********************************************/\n\nUInt MatrixDistributed::index2block(UInt i) const\n{\n  return std::distance(_blockIndex.begin(), std::upper_bound(_blockIndex.begin(), _blockIndex.end(), i))-1;\n}\n\n/***********************************************/\n\nMatrix &MatrixDistributed::N(UInt i, UInt k)\n{\n  const UInt ik = index(i, k);\n  if(ik == NULLINDEX)\n    throw(Exception(\"In MatrixDistributed::N(\"+i%\"%i, \"s+k%\"%i): block not exist\"s));\n  return _N[ik];\n}\n\n/***********************************************/\n\nconst Matrix &MatrixDistributed::N(UInt i, UInt k) const\n{\n  const UInt ik = index(i, k);\n  if(ik == NULLINDEX)\n    throw(Exception(\"In MatrixDistributed::N(\"+i%\"%i, \"s+k%\"%i): block not exist\"s));\n  return _N[ik];\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MatrixDistributed::setCalculateRank(const std::function<UInt(UInt, UInt, UInt)> &calcRank_)\n{\n  try\n  {\n    calcRank = calcRank_;\n    if(calcRank == nullptr)\n      calcRank = calculateRankBlockCyclic;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt MatrixDistributed::calculateRankBlockCyclic(UInt i, UInt k, UInt commSize)\n{\n  try\n  {\n    // find optimal process grid (nearly quadratic)\n    UInt pRows = static_cast<UInt>(std::floor(std::sqrt(commSize)));\n    while(commSize % pRows)\n      pRows++;\n    const UInt pCols = commSize/pRows;\n\n    return (i%pRows)*pCols+(k%pCols);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt MatrixDistributed::setBlock(UInt i, UInt k, UInt rank)\n{\n  try\n  {\n    if(rank == NULLINDEX)\n      rank = this->rank(i, k); // rank of used block\n    if(rank == NULLINDEX)\n      rank = calcRank(i, k, Parallel::size(comm)); // new block? => calculate new rank\n\n    UInt ik = index(i, k);\n    if(ik == NULLINDEX)\n    {\n      ik = _N.size();\n      _N.push_back(Matrix());\n      _rank.push_back(rank);\n\n      _column[i].insert(std::lower_bound(_column[i].begin(), _column[i].end(), k, [](const auto &x, UInt k) {return x.first < k;}), std::pair<UInt, UInt>(k, ik));\n      _row[k].insert   (std::lower_bound(_row[k].begin(),   _row[k].end(),     i, [](const auto &x, UInt i) {return x.first < i;}), std::pair<UInt, UInt>(i, ik));\n    }\n\n    _rank[ik] = rank;\n    if(isMyRank(ik) && (_N[ik].size() == 0))\n      _N[ik] = ((i==k) ? Matrix(blockSize(i), Matrix::SYMMETRIC) : Matrix(blockSize(i), blockSize(k)));\n    return ik;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::eraseBlocks(UInt start, UInt count)\n{\n  try\n  {\n    if(start+count > blockCount())\n      throw(Exception(\"Range of block rows/columns to remove (\"+start%\"%i\"s+\" to \"+(start+count-1)%\"%i\"s+\") exceeds the number of block rows/columns in the matrix (\"+blockCount()%\"%i\"s+\").\"));\n\n    std::vector<std::vector<std::pair<UInt, UInt>>> _rowNew(blockCount()-count);      // each column, used row -> idx to _N and _rank\n    std::vector<std::vector<std::pair<UInt, UInt>>> _columnNew(blockCount()-count);   // each row, used column -> idx to _N and _rank\n    std::vector<Matrix>               _NNew;                            // unorderd list of used blocks\n    std::vector<UInt>                 _rankNew;                         // unorderd list of rank of used blocks\n    for(UInt i=0; i<blockCount(); i++)\n      if((i < start) || (i >= start+count))\n        loopBlockRow(i, {0, blockCount()}, [&](UInt k, UInt ik)\n        {\n          if((k < start) || (k >= start+count))\n          {\n            _columnNew[(i < start) ? i : i-count].push_back(std::pair<UInt, UInt>((k < start) ? k : k-count, _NNew.size()));\n            _rowNew   [(k < start) ? k : k-count].push_back(std::pair<UInt, UInt>((i < start) ? i : i-count, _NNew.size()));\n            _NNew.push_back(_N[ik]);\n            _rankNew.push_back(_rank[ik]);\n          }\n        });\n\n    _row    = _rowNew;\n    _column = _columnNew;\n    _N      = _NNew;\n    _rank   = _rankNew;\n\n    // adjust block indices\n    const UInt erasedParameterCount = blockIndex(start+count) - blockIndex(start);\n    for(UInt i=start; i<blockCount(); i++)\n      _blockIndex[i+1] -= erasedParameterCount;\n    _blockIndex.erase(_blockIndex.begin() + start, _blockIndex.begin() + start+count);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MatrixDistributed::setNull()\n{\n  try\n  {\n    for(UInt i=0; i<blockCount(); i++)\n      loopBlockRow(i, {i, blockCount()}, [&](UInt k, UInt ik)\n      {\n        if(isMyRank(ik))\n        {\n          if(i == k)\n            _N[ik].setType(Matrix::SYMMETRIC, Matrix::UPPER);\n          _N[ik].setNull();\n        }\n      });\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::reduceSum(UInt i, UInt k)\n{\n  try\n  {\n    if(Parallel::size(comm)<=1)\n      return;\n\n    const UInt ik = index(i, k);\n    if(ik == NULLINDEX)\n      throw(Exception(\"N(\"+i%\"%i, \"s+k%\"%i): block not exist\"s));\n    if(isMyRank(ik) && (_N[ik].size() == 0))\n      _N[ik] = ((i==k) ? Matrix(blockSize(i), Matrix::SYMMETRIC) : Matrix(blockSize(i), blockSize(k)));\n    const UInt color = _N[ik].size()  ? k : NULLINDEX;\n    const UInt key   = isMyRank(ik) ? 0 : Parallel::myRank(comm)+1;\n    Parallel::CommunicatorPtr commNew = Parallel::splitCommunicator(color, key, comm);\n    if(commNew && (Parallel::size(commNew)>1))\n      Parallel::reduceSum(_N[ik], 0, commNew);\n    if(!isMyRank(ik))\n      _N[ik] = Matrix();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::reduceSum(Bool timing)\n{\n  try\n  {\n    if(Parallel::size(comm)<=1)\n      return;\n\n    Log::Timer timer(_N.size(), 1, timing);\n    UInt idxBlock = 0;\n    for(UInt i=0; i<blockCount(); i++)\n      loopBlockRow(i, {i, blockCount()}, [&](UInt k, UInt ik)\n      {\n        timer.loopStep(idxBlock++);\n        if(isMyRank(ik) && (_N[ik].size() == 0))\n          _N[ik] = ((i==k) ? Matrix(blockSize(i), Matrix::SYMMETRIC) : Matrix(blockSize(i), blockSize(k)));\n        UInt color = _N[ik].size()  ? idxBlock : NULLINDEX;\n        UInt key   = isMyRank(ik) ? 0 : Parallel::myRank(comm)+1;\n        Parallel::CommunicatorPtr commNew = Parallel::splitCommunicator(color, key, comm);\n        if(commNew && (Parallel::size(commNew)>1))\n          Parallel::reduceSum(_N[ik], 0, commNew);\n        if(!isMyRank(ik))\n          _N[ik] = Matrix();\n      });\n    Parallel::barrier(comm);\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nvoid MatrixDistributed::cholesky(Bool timing, UInt startBlock, UInt countBlock, Bool collect)\n{\n  UInt i=0;\n  try\n  {\n    Log::Timer timer(blockCount()-startBlock, 1, timing);\n    for(i=startBlock; i<blockCount(); i++)\n      if(blockSize(i))\n      {\n        timer.loopStep(i-startBlock);\n        UInt ii = index(i,i);\n        if((ii == NULLINDEX) && (i < startBlock+countBlock))\n          throw(Exception(\"Diagonal block (\"+i%\"%i, \"s+i%\"%i) is not set.\"s));\n\n        loopBlockColumn({startBlock, std::min(i, startBlock+countBlock)}, i, [&](UInt z, UInt zi)\n        {\n          if(ii == NULLINDEX)\n            ii = setBlock(i,i);\n\n          // column rank k update\n          if(isMyRank(zi))\n          {\n            if(_N[ii].size() == 0)\n              _N[ii] = Matrix(blockSize(i), Matrix::SYMMETRIC, Matrix::UPPER);\n            rankKUpdate(-1., _N[zi], _N[ii]);\n          }\n\n          // distribute top column to right hand side blocks\n          if(Parallel::size(comm) > 1)\n            broadCast(_N[zi], zi, usedRanksInRow(z, {i+1, blockCount()}));\n\n          // dgemm\n          loopBlockRow(z, {i+1, blockCount()}, [&](UInt s, UInt zs)\n          {\n            const UInt is = setBlock(i, s);\n            if(isMyRank(zs))\n            {\n              if(_N[is].size() == 0)\n                _N[is] = Matrix(blockSize(i), blockSize(s));\n              matMult(-1., _N[zi].trans(), _N[zs], _N[is]);\n            }\n          });\n\n          // free column\n          if(!isMyRank(zi) && _N[zi].size())\n            _N[zi] = Matrix();\n        }); // for(row z)\n\n        // collect right row elements from top block\n        if((i>0) && (Parallel::size(comm) > 1) && ((i < startBlock+countBlock) || collect))\n          loopBlockRow(i, {i, blockCount()}, [&](UInt s, UInt is)\n          {\n            std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n            loopBlockColumn({startBlock, std::min(i, startBlock+countBlock)}, i, [&](UInt z, UInt /*zi*/)\n            {\n              const UInt zs = index(z,s);\n              if(zs != NULLINDEX)\n                usedRank.at(_rank[zs]) = TRUE;\n            });\n            reduceSum(_N[is], is, usedRank);\n          });\n\n        if(i < startBlock+countBlock)\n        {\n          // cholesky\n          if(isMyRank(ii))\n            ::cholesky(_N[ii]);\n\n          // distribute diagonal element to row\n          if(Parallel::size(comm) > 1)\n            broadCast(_N[ii], ii, usedRanksInRow(i, {i+1, blockCount()}));\n\n          // triangularSolve to row\n          loopBlockRow(i, {i+1, blockCount()}, [&](UInt /*s*/, UInt is)\n          {\n            if(isMyRank(is))\n              ::triangularSolve(1., _N[ii].trans(), _N[is]);\n          });\n\n          // free diagonal\n          if(ii != NULLINDEX && !isMyRank(ii) && _N[ii].size())\n            _N[ii] = Matrix();\n        }\n      }\n    Parallel::barrier(comm);\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"In block row \"s+i%\"%i with parameter index \"s+blockIndex(i)%\"%i\"s, e)\n  }\n}\n\n/***********************************************/\n\nMatrix MatrixDistributed::solve(const_MatrixSliceRef n, Bool timing)\n{\n  try\n  {\n    cholesky(timing);\n\n    UInt rhsCount = n.columns();\n    Parallel::broadCast(rhsCount, 0, comm);\n\n    std::vector<Matrix> x(blockCount());\n    if(Parallel::isMaster(comm))\n      for(UInt i=0; i<blockCount(); i++)\n        x.at(i) = n.row(blockIndex(i), blockSize(i));\n    else\n      for(UInt i=0; i<blockCount(); i++)\n        x.at(i) = Matrix(blockSize(i), rhsCount);\n\n    triangularTransSolve(x);\n    triangularSolve(x);\n\n    Matrix x2(n.rows(), n.columns());\n    if(Parallel::isMaster(comm))\n      for(UInt i=0; i<blockCount(); i++)\n        copy(x.at(i), x2.row(blockIndex(i), blockSize(i)));\n\n    return x2;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::triangularSolve(MatrixSliceRef x2)\n{\n  try\n  {\n    UInt rhsCount = x2.columns();\n    Parallel::broadCast(rhsCount, 0, comm);\n\n    std::vector<Matrix> x(blockCount());\n    if(Parallel::isMaster(comm))\n      for(UInt i=0; i<blockCount(); i++)\n        x.at(i) = x2.row(blockIndex(i), blockSize(i));\n    else\n      for(UInt i=0; i<blockCount(); i++)\n        x.at(i) = Matrix(blockSize(i), rhsCount);\n\n    triangularSolve(x);\n\n    if(Parallel::isMaster(comm))\n      for(UInt i=0; i<blockCount(); i++)\n        copy(x.at(i), x2.row(blockIndex(i), blockSize(i)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::triangularSolve(std::vector<Matrix> &x, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    for(UInt i=startBlock+countBlock; i-->startBlock;)\n      if(blockSize(i))\n      {\n        const UInt ii = index(i,i);\n\n        // collect\n        if(Parallel::size(comm) > 1)\n        {\n          std::vector<Bool> usedRank = usedRanksInRow(i, {i, startBlock+countBlock});\n          usedRank.at(0) = TRUE; // master\n          reduceSum(x.at(i), ii, usedRank);\n        }\n\n        // solve\n        if(isMyRank(ii))\n          ::triangularSolve(1., _N[ii], x.at(i));\n\n        // distribute to top column\n        if(Parallel::size(comm) > 1)\n        {\n          std::vector<Bool> usedRank = usedRanksInColumn({startBlock, i}, i);\n          usedRank.at(0) = TRUE; // master\n          broadCast(x.at(i), ii, usedRank);\n        }\n\n        // reduce\n        loopBlockColumn({startBlock, i}, i, [&](UInt z, UInt zi)\n        {\n          if(isMyRank(zi))\n            matMult(-1., _N[zi], x.at(i), x.at(z));\n        });\n\n        // free\n        if(!Parallel::isMaster(comm))\n          x.at(i).setNull();\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::triangularTransSolve(MatrixSliceRef x2, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    UInt rhsCount = x2.columns();\n    Parallel::broadCast(rhsCount, 0, comm);\n\n    std::vector<Matrix> x(blockCount());\n    if(Parallel::isMaster(comm))\n      for(UInt i=0; i<blockCount(); i++)\n        x.at(i) = x2.row(blockIndex(i), blockSize(i));\n    else\n      for(UInt i=0; i<blockCount(); i++)\n        x.at(i) = Matrix(blockSize(i), rhsCount);\n\n    triangularTransSolve(x, startBlock, countBlock, TRUE);\n\n    if(Parallel::isMaster(comm))\n      for(UInt i=0; i<blockCount(); i++)\n        copy(x.at(i), x2.row(blockIndex(i), blockSize(i)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::triangularTransSolve(std::vector<Matrix> &x, UInt startBlock, UInt countBlock, Bool collect)\n{\n  try\n  {\n    for(UInt i=startBlock; i<startBlock+countBlock; i++)\n      if(blockSize(i))\n      {\n        const UInt ii = index(i,i);\n\n        // collect\n        if(Parallel::size(comm) > 1)\n        {\n          std::vector<Bool> usedRank = usedRanksInColumn({startBlock, i}, i);\n          usedRank.at(0) = TRUE; // master\n          reduceSum(x.at(i), ii, usedRank, collect);\n        }\n\n        // solve\n        if(isMyRank(ii))\n          ::triangularSolve(1., _N[ii].trans(), x.at(i));\n\n        // distribute to row\n        if(Parallel::size(comm) > 1)\n        {\n          std::vector<Bool> usedRank = usedRanksInRow(i, {i, blockCount()});\n          usedRank.at(0) = TRUE; // master\n          broadCast(x.at(i), ii, usedRank);\n        }\n\n        // reduce\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt s, UInt is)\n        {\n          if(isMyRank(is) && _N[is].size())\n            matMult(-1., _N[is].trans(), x.at(i), x.at(s));\n        });\n\n        // free\n        if(!Parallel::isMaster(comm))\n          x.at(i).setNull();\n      }\n\n    // reduce special block\n    // --------------------\n    if(collect && (Parallel::size(comm) > 1))\n      for(UInt i=startBlock+countBlock; i<blockCount(); i++)\n        if(blockSize(i))\n        {\n          std::vector<UInt> ranks = {0};\n          std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n          usedRank.at(0) = TRUE; // master\n          loopBlockColumn({startBlock, startBlock+countBlock}, i, [&](UInt /*z*/, UInt zi)\n          {\n            if(!usedRank.at(_rank[zi]))\n            {\n              usedRank.at(_rank[zi]) = TRUE;\n              ranks.push_back(_rank[zi]);\n            }\n          });\n          Parallel::CommunicatorPtr commNew = Parallel::createCommunicator(ranks, comm);\n          if(commNew)\n            Parallel::reduceSum(x.at(i), 0, commNew);\n          // free\n          if(!Parallel::isMaster(comm))\n            x.at(i).setNull();\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::choleskyInverse(Bool timing, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    Log::Timer timer(countBlock, 1, timing);\n    for(UInt i=startBlock; i<startBlock+countBlock; i++)\n      if(blockSize(i))\n      {\n        timer.loopStep(i-startBlock);\n        const UInt ii = index(i,i);\n\n        // distribute top column elements to left triangular\n        if(Parallel::size(comm) > 1)\n          loopBlockColumn({startBlock, i}, i, [&](UInt z, UInt zi)\n          {\n            broadCast(_N[zi], zi, usedRanksInColumn({0, z+1}, z));\n          });\n\n        // compute triangularMult\n        for(UInt z=startBlock; z<i; z++)\n        {\n          const UInt zz = index(z,z);\n          const UInt zi = index(z,i);\n          if(zi != NULLINDEX)\n          {\n            if((zz != NULLINDEX) && isMyRank(zz))\n              triangularMult(1., _N[zz], _N[zi]);\n            else if(isMyRank(zi))\n              _N[zi].setNull();\n            else if(_N[zi].size())\n              _N[zi] = Matrix();\n          }\n\n          loopBlockRow(z, {z+1, i}, [&](UInt s, UInt zs)\n          {\n            const UInt si = index(s,i);\n            if(si != NULLINDEX)\n            {\n              const UInt zi = setBlock(z, i);\n              if(isMyRank(zs))\n              {\n                if(_N[zi].size() == 0)\n                  _N[zi] = Matrix(blockSize(z), blockSize(i));\n                matMult(1.,  _N[zs],  _N[si], _N[zi]);\n              }\n            }\n          });\n        }\n\n        // reduceSum top column elements from left triangular\n        if(Parallel::size(comm) > 1)\n          loopBlockColumn({startBlock, i}, i, [&](UInt z, UInt zi)\n          {\n            std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n            loopBlockRow(z, {z, i}, [&](UInt s, UInt zs)\n            {\n              if(isBlockUsed(s, i))\n                usedRank.at(_rank[zs]) = TRUE;\n            });\n            if(usedRank.at(Parallel::myRank(comm)) && !_N[zi].size())\n              _N[zi] = Matrix(blockSize(z), blockSize(i));\n            reduceSum(_N[zi], zi, usedRank);\n          });\n\n        // distribute diagonal element to top column\n        if((i>startBlock) && (Parallel::size(comm) > 1))\n          broadCast(_N[ii], ii, usedRanksInColumn({startBlock, i+1}, i));\n\n        // triangularSolve to column\n        loopBlockColumn({startBlock, i}, i, [&](UInt /*z*/, UInt zi)\n        {\n          if(isMyRank(zi))\n            ::triangularSolve(-1., _N[ii].trans(), _N[zi].trans());\n        });\n\n        // free diagonal\n        if((!isMyRank(ii)) && _N[ii].size())\n          _N[ii] = Matrix();\n\n        // inverte triangular element\n        if(isMyRank(ii))\n          ::inverse(_N[ii]);\n      }\n    Parallel::barrier(comm);\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MatrixDistributed::choleskyProduct(Bool timing)\n{\n  try\n  {\n    Log::Timer timer(blockCount(), 1, timing);\n    for(UInt i=0; i<blockCount(); i++)\n      if(blockSize(i))\n      {\n        timer.loopStep(i);\n        const UInt ii = index(i,i);\n\n        // distribute diagonal element to top column\n        if((i>0) && (Parallel::size(comm) > 1))\n          broadCast(_N[ii], ii, usedRanksInColumn({0, i+1}, i));\n\n        // compute triangularMult\n        loopBlockColumn({0, i}, i, [&](UInt /*z*/, UInt zi)\n        {\n          if(isMyRank(zi))\n            triangularMult(1., _N[ii], _N[zi].trans());\n        });\n\n        // W'W\n        if(isMyRank(ii))\n          ::choleskyProduct(_N[ii]);\n        else if(_N[ii].size())\n          _N[ii] = Matrix(); // free diagonal\n\n        // distribute right row elements to top block\n        if((i>0) && (Parallel::size(comm) > 1))\n          loopBlockRow(i, {i+1, blockCount()}, [&](UInt s, UInt is)\n          {\n            broadCast(_N[is], is, usedRanksInColumn({0, i+1}, s));\n          });\n\n        // dgemm\n        for(UInt z=0; z<i; z++)\n          loopBlockRow(i, {i+1, blockCount()}, [&](UInt s, UInt is)\n          {\n            const UInt zs = index(z,s);\n            if((zs != NULLINDEX) && isMyRank(zs))\n            {\n              const UInt zi = setBlock(z, i);\n              if(!_N[zi].size())\n                _N[zi] = Matrix(blockSize(z), blockSize(i));\n              matMult(1., _N[zs], _N[is].trans(), _N[zi]);\n            }\n          });\n\n        // free row elements\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt /*s*/, UInt is)\n        {\n          if(!isMyRank(is) && _N[is].size())\n            _N[is] = Matrix();\n        });\n\n        // reduceSum column elements from right hand side block\n        if(Parallel::size(comm) > 1)\n          loopBlockColumn({0, i}, i, [&](UInt z, UInt zi)\n          {\n            std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n            loopBlockRow(z, {i+1, blockCount()}, [&](UInt s, UInt zs)\n            {\n              if(isBlockUsed(i, s))\n                usedRank.at(_rank[zs]) = TRUE;\n            });\n            reduceSum(_N[zi], zi, usedRank);\n          });\n\n        // row rank k update\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt /*s*/, UInt is)\n        {\n          if(isMyRank(is))\n          {\n            if(_N[ii].size() == 0)\n              _N[ii] = Matrix(blockSize(i), Matrix::SYMMETRIC, Matrix::UPPER);\n            rankKUpdate(1., _N[is].trans(), _N[ii]);\n          }\n        });\n\n        // reduceSum diagonal element from row\n        if(Parallel::size(comm) > 1)\n          reduceSum(_N[ii], ii, usedRanksInRow(i, {i+1, blockCount()}));\n\n        // free row elements\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt /*s*/, UInt is)\n        {\n          if((!isMyRank(is)) && _N[is].size())\n            _N[is] = Matrix();\n        });\n      }\n    Parallel::barrier(comm);\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid MatrixDistributed::cholesky2SparseInverse(Bool timing)\n{\n  try\n  {\n    Log::Timer timer(blockCount(), 1, timing);\n    for(UInt i=blockCount(); i-->0;)\n      if(blockSize(i))\n      {\n        timer.loopStep(blockCount()-1-i);\n\n        const UInt ii = index(i, i);\n\n        std::vector<Bool> rowRanks = usedRanksInRow(i, {i, blockCount()});\n        broadCast(_N[ii], ii, rowRanks); // broadcast diagonal(i,i) to whole row;\n\n        // update off diagonal blocks in row with inverse diagonal\n        // S_{i,j} = -W_{i,i}^{-1} * W_{i, i+1:n} * S_{i+1:n, j}\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt /*k*/, UInt ik)\n        {\n          if(isMyRank(ik))\n            ::triangularSolve(-1.0, _N[ii], _N[ik]);\n        });\n\n        if(isMyRank(ii))\n          cholesky2Inverse(_N[ii]);\n        else if(_N[ii].size())\n          _N[ii].setNull();\n\n        // distribute row to lower symmetric\n        if(Parallel::size(comm) > 1)\n          loopBlockRow(i, {i+1, blockCount()}, [&](UInt j, UInt ij)\n          {\n            std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n            loopBlockRow(i, {i+1, blockCount()}, [&](UInt k, UInt /*ik*/)\n            {\n              const UInt jk = index(std::min(j,k), std::max(j,k)); // upper triangle of symm.\n              if(jk != NULLINDEX)\n                usedRank.at(_rank[jk]) = TRUE;\n            });\n            broadCast(_N[ij], ij, usedRank);\n          });\n\n        // symm. matMult\n        std::vector<Matrix> Uij(blockCount());\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt j, UInt ij) // loop over columns\n        {\n          std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n          loopBlockRow(i, {i+1, blockCount()}, [&](UInt k, UInt ik) // loop over rows\n          {\n            const UInt jk = index(std::min(j,k), std::max(j,k)); // upper triangle of symm.\n            if(jk != NULLINDEX)\n            {\n              usedRank.at(_rank[jk]) = TRUE;\n              if(isMyRank(jk))\n              {\n                if(!Uij.at(j).size())\n                  Uij.at(j) = Matrix(blockSize(i), blockSize(j));\n                matMult(1., _N[ik], ((k>j) ? _N[jk].trans() : _N[jk]), Uij.at(j));\n              }\n            }\n          });\n          if(isMyRank(ij) && !Uij.at(j).size())\n            Uij.at(j) = Matrix(blockSize(i), blockSize(j));\n          reduceSum(Uij.at(j), ij, usedRank);\n        });\n\n        // free row elements\n        if(Parallel::size(comm) > 1)\n          loopBlockRow(i, {i+1, blockCount()}, [&](UInt /*j*/, UInt ij)\n          {\n            if((!isMyRank(ij)) && _N[ij].size())\n              _N[ij] = Matrix();\n          });\n\n        // update diagonal from row\n        // S_{i,i} = W_{i,i}^-1 W_{i,i}^-T - S_{i, i+1:n}*[ W_{i,i}^-1 W_{i,i+1:n}]\n        loopBlockRow(i, {i+1, blockCount()}, [&](UInt j, UInt ij) // loop over columns\n        {\n          if(isMyRank(ij))\n          {\n            _N[ii].setType(Matrix::GENERAL);\n            matMult(1.0, Uij.at(j), _N[ij].trans(), _N[ii]);\n            _N[ij] = Uij.at(j);\n          }\n        });\n\n        reduceSum(_N[ii], ii, rowRanks);\n        _N[ii].setType(Matrix::SYMMETRIC);\n      }\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid MatrixDistributed::reorder(const std::vector<UInt> &index, const std::vector<UInt> &blockIndexNew, const std::function<UInt(UInt, UInt, UInt)> &calcRank)\n{\n  try\n  {\n    if(index.size() != blockIndexNew.back())\n      throw(Exception(\"index and blockIndex do not match.\"));\n\n    MatrixDistributed matrixNew;\n    matrixNew.initEmpty(blockIndexNew, comm, calcRank);\n\n    // create new sort index {blockOld, indexOld, blockNew, indexNew}\n    std::vector<std::array<UInt,4>> idx;\n    idx.reserve(index.size());\n    for(UInt i=0; i<index.size(); i++)\n      if(index.at(i) != NULLINDEX)\n      {\n        const UInt blockOld = index2block(index.at(i));\n        const UInt blockNew = matrixNew.index2block(i);\n        idx.push_back({blockOld, index.at(i)-blockIndex(blockOld), blockNew, i-matrixNew.blockIndex(blockNew)});\n      }\n    std::sort(idx.begin(), idx.end(), [](const std::array<UInt,4> &a, const std::array<UInt,4> &b) {return (a[0] == b[0]) ? (a[1] < b[1]) : (a[0] < b[0]);});\n\n    // ----------------------------\n    auto continuousRange = [&](UInt start)\n    {\n      UInt i = start;\n      while((i < idx.size()) &&\n            (idx[i][0] == idx[start][0]) &&\n            (idx[i][1] == idx[start][1]+i-start) &&\n            (idx[i][2] == idx[start][2]) &&\n            (idx[i][3] == idx[start][3]+i-start))\n        i++;\n      return i-start;\n    };\n    // ----------------------------\n\n    UInt idxRowStart = 0;\n    UInt idxRowEnd   = 0;\n    for(UInt i=0; i<blockCount(); i++)   // loop over all block rows\n    {\n      idxRowStart = std::distance(idx.begin(), std::lower_bound(idx.begin()+idxRowEnd,   idx.end(), i, [](const std::array<UInt,4> &a, UInt i){return a[0] < i;}));\n      idxRowEnd   = std::distance(idx.begin(), std::upper_bound(idx.begin()+idxRowStart, idx.end(), i, [](UInt i, const std::array<UInt,4> &a){return i < a[0];}));\n\n      loopBlockRow(i, {i, blockCount()}, [&](UInt k, UInt ik)\n      {\n        const UInt idxColStart = std::distance(idx.begin(), std::lower_bound(idx.begin()+idxRowStart, idx.end(), k, [](const std::array<UInt,4> &a, UInt k){return a[0] < k;}));\n        const UInt idxColEnd   = std::distance(idx.begin(), std::upper_bound(idx.begin()+idxColStart, idx.end(), k, [](UInt k, const std::array<UInt,4> &a){return k < a[0];}));\n\n        // distribute block\n        std::vector<Bool> usedRank(Parallel::size(comm), FALSE);\n        for(UInt z=idxRowStart; z<idxRowEnd; z += continuousRange(z))\n          for(UInt s=((i==k) ? z : idxColStart); s<idxColEnd; s += continuousRange(s))\n          {\n            UInt iNew = idx.at(z)[2];\n            UInt kNew = idx.at(s)[2];\n            if(kNew < iNew)\n              std::swap(iNew, kNew);\n            const UInt ikNew = matrixNew.setBlock(iNew, kNew);\n            usedRank.at(matrixNew._rank[ikNew]) = TRUE;\n          }\n        broadCast(_N[ik], ik, usedRank);\n\n        // copy elements\n        UInt rows, cols;\n        if(usedRank.at(Parallel::myRank(comm)))\n          for(UInt z=idxRowStart; z<idxRowEnd; z+=rows)\n          {\n            UInt iNew = idx.at(z)[2];\n            UInt row  = idx.at(z)[3];\n            rows = continuousRange(z);\n            for(UInt s=((i==k) ? z : idxColStart); s<idxColEnd; s += cols)\n            {\n              UInt kNew = idx.at(s)[2];\n              UInt col  = idx.at(s)[3];\n              cols = continuousRange(s);\n              if((iNew > kNew) || ((iNew == kNew) && (row > col))) // transpose to access upper triangle?\n              {\n                const UInt kiNew = matrixNew.index(kNew, iNew);\n                if(matrixNew.isMyRank(kiNew))\n                  copy(_N[ik].slice(idx.at(z)[1], idx.at(s)[1], rows, cols), matrixNew._N[kiNew].trans().slice(row, col, rows, cols));\n              }\n              else\n              {\n                const UInt ikNew = matrixNew.index(iNew, kNew);\n                if(matrixNew.isMyRank(ikNew))\n                  copy(_N[ik].slice(idx.at(z)[1], idx.at(s)[1], rows, cols), matrixNew._N[ikNew].slice(row, col, rows, cols));\n              }\n            }\n          }\n\n        _N[ik] = Matrix();\n      }); // for(block[ik])\n    } // for(block row i)\n\n    *this = matrixNew;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<UInt> MatrixDistributed::computeBlockIndex(UInt parameterCount, UInt blockSize)\n{\n  if(parameterCount==0)\n    return {0};\n\n  if(blockSize==0)\n    return {0, parameterCount};\n\n  std::vector<UInt> blockIndex(1, 0);\n  while(blockIndex.back()<parameterCount)\n    blockIndex.push_back(std::min(blockIndex.back()+blockSize, parameterCount));\n\n  return blockIndex;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/parallel/matrixDistributed.h",
    "content": "/***********************************************/\n/**\n* @file matrixDistributed.h\n*\n* @brief Positve definte matrix in distributed memory.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2011-01-30\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_MATRIXDISTRIBUTED__\n#define __GROOPS_MATRIXDISTRIBUTED__\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"parallel/parallel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Representation of a positve definte matrix in distributed memory\n* All algorithms operate only on the upper triangle of the matrix.\n* @ingroup parallelGroup */\nclass MatrixDistributed\n{\n  Parallel::CommunicatorPtr             comm;\n  std::function<UInt(UInt, UInt, UInt)> calcRank;\n  std::vector<UInt>                    _blockIndex;\n\n  std::vector<std::vector<std::pair<UInt, UInt>>> _row;      // each column, used row -> idx to _N and _rank\n  std::vector<std::vector<std::pair<UInt, UInt>>> _column;   // each row, used column -> idx to _N and _rank\n  std::vector<Matrix>               _N;        // unorderd list of used blocks\n  std::vector<UInt>                 _rank;     // unorderd list of rank of used blocks\n\n  Bool isMyRank(UInt idx) const {return (Parallel::myRank(comm) == _rank[idx]);}\n  UInt index(UInt row, UInt col) const;        // NULLINDEX if not set\n  // call: loopBlockColumn({rowStart, rowPastEnd}, col, [&](UInt row, UInt idx) {_N[idx] == N(row,col)});\n  void loopBlockColumn(const std::array<UInt,2> &rows, UInt col, std::function<void(UInt, UInt)> block) const;\n  // call: loopBlockRow(row, {colStart, colPastEnd}, [&](UInt col, UInt idx) {_N[idx] == N(row,col)});\n  void loopBlockRow   (UInt row, const std::array<UInt,2> &cols, std::function<void(UInt, UInt)> block) const;\n\n  // parallel\n  // call: usedRanks = usedRanksInColumn({rowStart, rowPastEnd}, col);\n  std::vector<Bool> usedRanksInColumn(const std::array<UInt,2> &rows, UInt col) const;\n  // call: usedRanks = usedRanksInRow(row, {colStart, colPastEnd});\n  std::vector<Bool> usedRanksInRow(UInt row, const std::array<UInt,2> &cols) const;\n  void broadCast(Matrix &x, UInt idx, const std::vector<Bool> &usedRank);\n  void reduceSum(Matrix &x, UInt idx, const std::vector<Bool> &usedRank, Bool free=TRUE);\n\n\n  /* @brief Solve an triangular system of equations \\f$ \\mathbf{W}\\mathbf{y} = \\mathbf{x}\\f$\n  * The input must be initialized at all nodes.\n  * The sum other all nodes defines the input (reduceSum is called internally)\n  * Output is valid at master only. */\n  void triangularSolve(std::vector<Matrix> &x) {triangularSolve(x, 0, blockCount());}\n  void triangularSolve(std::vector<Matrix> &x, UInt startBlock, UInt countBlock);\n\n  /* @brief Solve a part of a triangular system of equations \\f$ \\mathbf{W}^T\\mathbf{y} = \\mathbf{x}\\f$\n  * This corresponds to the partly @a cholesky function.\n  * The input must be initialized at all nodes.\n  * The sum other all nodes defines the input (reduceSum is called internally)\n  * Output is valid at master only. */\n  void triangularTransSolve(std::vector<Matrix> &x) {triangularTransSolve(x, 0, blockCount(), TRUE);}\n  void triangularTransSolve(std::vector<Matrix> &x, UInt startBlock, UInt countBlock, Bool collect);\n\npublic:\n  /// Default constructor.\n  MatrixDistributed();\n\n  /** @brief Initialize matrix structure (number of blocks, block sizes, communicator, and rank calculation).\n  * The @a blockIndex is a vector of ascending indices starting with zero, where each adjacent pair of elements define the position and shape of the subblocks.\n  * Hence, all elements \\f$ n_{ij} \\f$  which satisfy \\f$ blockIndex[k] \\leq  i < blockIndex[k+1] \\land blockIndex[l] \\leq j < blockIndex[l+1] \\f$ are found in block (@a k, @a l).\n  * @param blockIndex: boundary indices of the sub-blocks.\n  * @param comm: Parallel communicator of the matrix (default: MPI_COMM_WORLD).\n  * @param calcRank: function handler to determine the process rank of block(i,k) (default: block cyclic distribution). */\n  explicit MatrixDistributed(const std::vector<UInt> &blockIndex, Parallel::CommunicatorPtr comm, const std::function<UInt(UInt, UInt, UInt)> &calcRank=nullptr);\n\n  /** @copydoc MatrixDistributed(const std::vector<UInt> &, Parallel::CommunicatorPtr, const std::function<UInt(UInt, UInt, UInt)> &)\n  * This method allocates the upper block triangle of a symmetric matrix with zero matrices. */\n  void init(const std::vector<UInt> &blockIndex, Parallel::CommunicatorPtr comm, const std::function<UInt(UInt, UInt, UInt)> &calcRank=nullptr);\n\n  /** @copydoc MatrixDistributed(const std::vector<UInt> &, Parallel::CommunicatorPtr, const std::function<UInt(UInt, UInt, UInt)> &)\n  * No memory is allocated. To assign blocks to processes and allocate memory, @a setBlock(UInt i, UInt k, UInt rank) has to be called. */\n  void initEmpty(const std::vector<UInt> &blockIndex, Parallel::CommunicatorPtr comm, const std::function<UInt(UInt, UInt, UInt)> &calcRank=nullptr);\n\n  // =========================================\n\n  /** @brief Set a new handler to calculate the rank of new blocks.\n  * If @p calcRank is nullptr a default block cyclic distribution is assumed.\n  * This function must be called by all processes within the communcator in the matrix! */\n  void setCalculateRank(const std::function<UInt(UInt, UInt, UInt)> &calcRank);\n\n  /** @brief returns the handler to calculate the rank of new blocks. */\n  const std::function<UInt(UInt, UInt, UInt)> &getCalculateRank() const {return calcRank;}\n\n  /** @brief The default calculateRank handler.\n  * Block cyclic distribution.\n  * This function must be called by all processes within the communcator in the matrix! */\n  static UInt calculateRankBlockCyclic(UInt i, UInt k, UInt commSize);\n\n  /** @brief Assigns block (@a i, @a k) to process @a rank and allocates memory (only at the parent process).\n  * If no rank is specified, the calculateRank handler is called for new blocks.\n  * This function must be called by all processes within the communcator in the matrix! */\n  UInt setBlock(UInt i, UInt k, UInt rank=NULLINDEX);\n\n  /** @brief Removes the block rows/columns.\n  * This function erases the block rows/columns containing the diagonal blocks @a startIndex to @a startIndex+count-1\n  * effectively reducing the size by blockSize[startIndex] + ... + blockSize[startIndex+count-1] elements.\n  * This function must be called by all processes within the communcator in the matrix!\n  * @param startIndex index of block row/column to remove\n  * @param count number of rows/columns to remove  */\n  void eraseBlocks(UInt startIndex, UInt count=1);\n\n  // =========================================\n\n  Parallel::CommunicatorPtr communicator() const {return comm;}\n  std::vector<UInt>         blockIndex()   const {return _blockIndex;}\n\n  UInt parameterCount()            const {return _blockIndex.at(blockCount());}          //!< Number of rows/columns (dimension) of distributed matrix\n  UInt dimension()                 const {return parameterCount();}                      //!< Number of rows/columns (dimension) of distributed matrix\n  UInt blockIndex(UInt i)          const {return _blockIndex.at(i);}                     //!< Start index of block @a i\n  UInt blockSize(UInt i)           const {return _blockIndex.at(i+1)-_blockIndex.at(i);} //!< Size of block @a i\n  UInt blockCount()                const {return _blockIndex.size()-1;}                  //!< Number of block rows/columns\n  UInt rank(UInt i, UInt k)        const;                                                //!< Rank of process holding block (@a i, @a k)\n  Bool isMyRank(UInt i, UInt k)    const {return (Parallel::myRank(comm) == rank(i,k));} //!< Returns TRUE if the calling process holds block (@a i, @a k) within the underlying communicator of the matrix\n  Bool isBlockUsed(UInt i, UInt k) const {return (rank(i,k) != NULLINDEX);}              //!< Returns TRUE if block (@a i, @a k) is assigned to a process\n  UInt index2block(UInt i)         const;                                                //!< Returns the index of the block which holds element @a i\n\n  Matrix       &N(UInt i, UInt k);       //!< Returns a writable reference to block (@a i, @a k). Throws an exception if the block is not assigned to a process.\n  const Matrix &N(UInt i, UInt k) const; //!< Returns a read only reference to block (@a i, @a k). Throws an exception if the block is not assigned to a process.\n\n  /// Fill all matrix blocks with zero.\n  void setNull();\n\n  /// Reduce block (@a i, @a k) on its parent process. After the operation, the memory on all other processes is freed.\n  void reduceSum(UInt i, UInt k);\n\n  /// Reduce all assigned blocks of the matrix on their parent processes. After the operation, the memory on all other processes is freed.\n  void reduceSum(Bool timing=TRUE);\n\n  // =========================================\n\n  /** @brief (In-place) Cholesky decomposition of the distributed matrix. */\n  void cholesky(Bool timing=TRUE) {cholesky(timing, 0, blockCount(), TRUE);}\n\n  /** @brief Performs a part of the Cholesky decomposition.\n  * The Cholesky decomposition must be already performed for the blocks before @p startBlock.\n  * The blocks after @p startBlock + @p countBlock contain at ouput the normal matrix where all parameters before\n  * are eliminated. If not @p collect, @a reduceSum must be called afterwards for these blocks. */\n  void cholesky(Bool timing, UInt startBlock, UInt countBlock, Bool collect);\n\n  /** @brief Solve the system of equations \\f$ \\mathbf{N}\\mathbf{x} = \\mathbf{n}\\f$\n  * Performs @a cholesky, @a triangularTransSolve, and @a triangularSolve.\n  * The input must be valid at master only. Output is valid at master only. */\n  Matrix solve(const_MatrixSliceRef n, Bool timing=TRUE);\n\n  /** @brief Solve a triangular system of equations \\f$ \\mathbf{W}\\mathbf{y} = \\mathbf{x}\\f$\n  * \\f$ \\mathbf{W} \\f$ is assumed to be an upper triangular matrix.\n  * The input must be valid at master only. Output is valid at master only. */\n  void triangularSolve(MatrixSliceRef x);\n\n  /** @brief Solve a triangular system of equations \\f$ \\mathbf{W}^T\\mathbf{y} = \\mathbf{x}\\f$\n  * \\f$ \\mathbf{W} \\f$ is assumed to be an upper triangular matrix.\n  * The input must be valid at master only. Output is valid at master only. */\n  void triangularTransSolve(MatrixSliceRef x) {triangularTransSolve(x, 0, blockCount());}\n  void triangularTransSolve(MatrixSliceRef x, UInt startBlock, UInt countBlock);\n\n  /** @brief Compute the inverse of the (upper triangular) Cholesky  factor \\f$ \\mathbf{W}\\f$ */\n  void choleskyInverse(Bool timing=TRUE) {choleskyInverse(timing, 0, blockCount());}\n  void choleskyInverse(Bool timing, UInt startBlock, UInt countBlock);\n\n  /** @brief Compute product \\f$ \\mathbf{U}\\mathbf{U}^T \\f$, where \\f$ \\mathbf{U} \\f$ is either a Cholesky factor or its inverse. */\n  void choleskyProduct(Bool timing=TRUE);\n\n  /** @brief Compute the sparse inverse of the matrix from the Cholesky  factor \\f$ \\mathbf{W}\\f$.\n  * Computes the upper triangle of the inverse of the symmetric matrix. The structure of the Cholesky factor is preserved.  */\n  void cholesky2SparseInverse(Bool timing=TRUE);\n\n  // =========================================\n\n  /** @brief Reorder parameters in a symmetric matrix.\n  * The parameter @a index contains the indices of the elements in the reordered matrix.\n  * Indices with NULLINDEX are inserted as zero elements into the new matrix.\n  * @param index: indices of the original matrix elements in the reordered matrix\n  * @param blockIndex: boundary indices of the sub-blocks.\n  * @param calcRank: function handler to determine the process rank of block(i,k) (default: block cyclic distribution). */\n  void reorder(const std::vector<UInt> &index, const std::vector<UInt> &blockIndex, const std::function<UInt(UInt, UInt, UInt)> &calcRank=nullptr);\n\n  // =========================================\n\n  /** @brief Compute boundary indices for distributed blocks from parameter count and block size.\n  * If blockSize is zero, the matrix consists of a single block. */\n  static std::vector<UInt> computeBlockIndex(UInt parameterCount, UInt blockSize=2048);\n\n  friend class GnssProcessingStep;\n  friend class GnssParametrizationAmbiguities;\n  friend class SlrProcessingStep;\n};\n\n//***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/parallel/parallel.h",
    "content": "/***********************************************/\n/**\n* @file parallel.h\n*\n* @brief Wrapper for Message Passing Interface (MPI).\n* All functions are empty statements in case\n* of the single processor version (parallelSingle.cpp).\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PARALLEL__\n#define __GROOPS_PARALLEL__\n\n#include \"base/import.h\"\n#include \"inputOutput/archiveBinary.h\"\n#include \"inputOutput/logging.h\"\n\n/***********************************************/\n\nclass GnssType;\n\n/***********************************************/\n\n/** @brief Wrapper for Message Passing Interface (MPI).\n* All functions are empty statements in case\n* of the single processor version (parallelSingle.cpp).\n* @ingroup parallelGroup */\nnamespace Parallel\n{\n  class Communicator;\n  typedef std::shared_ptr<Communicator> CommunicatorPtr;\n\n  /** @brief Must be called firstly in main.\n  * @return global communicator. */\n  CommunicatorPtr init(int argc, char *argv[]);\n\n  /** @brief Add an extra communcation channel to @p comm.\n  * @p receive is called on main process, if the returned send function is called by an arbitrary process.\n  * This function is used for the log.\n  * Must be called by every process in @a comm. */\n  std::function<void(UInt type, const std::string &str)> addChannel(const std::function<void(UInt rank, UInt type, const std::string &str)> &receive, CommunicatorPtr comm);\n\n  // =========================================================\n\n  /** @brief Creates new communicators.\n  * a new group is created for each different @a color.\n  * the ranks in the groups are sorted by the @a key. */\n  CommunicatorPtr splitCommunicator(UInt color, UInt key, CommunicatorPtr comm);\n\n  /** @brief Creates new communicators.\n  * Must be called by every process in @a comm. */\n  CommunicatorPtr createCommunicator(std::vector<UInt> ranks, CommunicatorPtr comm);\n\n  /** @brief The communicator that refers to the own process only. */\n  CommunicatorPtr selfCommunicator();\n\n  // =========================================================\n\n  /** @brief Number of processes. */\n  UInt size(CommunicatorPtr comm);\n\n  /** @brief Process index. */\n  UInt myRank(CommunicatorPtr comm);\n\n  /** @brief Is ths the master process (rank==0)? */\n  inline Bool isMaster(CommunicatorPtr comm) {return (myRank(comm) == 0);}\n\n  /** @brief Blocks until all process have reached this routine. */\n  void barrier(CommunicatorPtr comm);\n\n  /** @brief Non blocking check of extra channels. */\n  void peek(CommunicatorPtr comm);\n\n  /** @brief Distribute exceptions thrown in @p func by a single node to all nodes.\n  * Must be called by every process in @a comm.\n  * Exceptions causes memory leaks due to unfinished communications.\n  * Based on the idea: https://arxiv.org/abs/1804.04481 */\n  void broadCastExceptions(CommunicatorPtr comm, std::function<void(CommunicatorPtr)> func);\n\n  /** @brief Is @a broadCastExceptions interrupted by an external process? */\n  Bool isExternal(std::exception &e);\n\n  // =========================================================\n\n  /** @brief Send raw data @a x to process with rank @a process. */\n  void send(const Byte *x, UInt size, UInt process, CommunicatorPtr comm);\n\n  /** @brief receive raw data @a x from prozess with rank @a process.\n  * If @a process = NULLINDEX then receive from an arbitrary process. */\n  void receive(Byte *x, UInt size, UInt process, CommunicatorPtr comm);\n\n  /** @brief Distribute raw data @a x at @a process to all other processes. */\n  void broadCast(Byte *x, UInt size, UInt process, CommunicatorPtr comm);\n\n  // =========================================================\n\n  /** @brief Send @a x to process with rank @a process. */\n  ///@{\n  template<typename T> void send(const T &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const UInt     &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Double   &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Bool     &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Angle    &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Time     &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const GnssType &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Vector3d &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Vector   &x, UInt process, CommunicatorPtr comm);\n  template<> void send(const Matrix   &x, UInt process, CommunicatorPtr comm);\n  ///@}\n\n  /** @brief receive @a x from prozess with rank @a process.\n  * If @a process = NULLINDEX then receive from an arbitrary process. */\n  ///@{\n  template<typename T> void receive(T &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(UInt     &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Double   &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Bool     &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Angle    &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Time     &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(GnssType &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Vector3d &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Vector   &x, UInt process, CommunicatorPtr comm);\n  template<> void receive(Matrix   &x, UInt process, CommunicatorPtr comm);\n  ///@}\n\n  /** @brief Distribute @a x at @a process to all other processes. */\n  ///@{\n  template<typename T> void broadCast(T &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(UInt     &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Double   &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Bool     &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Angle    &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Time     &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(GnssType &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Vector3d &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Vector   &x, UInt process, CommunicatorPtr comm);\n  template<> void broadCast(Matrix   &x, UInt process, CommunicatorPtr comm);\n  ///@}\n\n  /** @brief Sum up @a x at all processes (also rank 0) and send the result to @a process. */\n  ///@{\n  void reduceSum(UInt                &x, UInt process, CommunicatorPtr comm);\n  void reduceSum(Double              &x, UInt process, CommunicatorPtr comm);\n  void reduceSum(Bool                &x, UInt process, CommunicatorPtr comm);\n  void reduceSum(Matrix              &x, UInt process, CommunicatorPtr comm);\n  void reduceSum(std::vector<Double> &x, UInt process, CommunicatorPtr comm);\n  ///@}\n\n  /** @brief Find min/max of @a x at all processes (also rank 0) and send the result to @a process. */\n  ///@{\n  void reduceMin(UInt   &x, UInt process, CommunicatorPtr comm);\n  void reduceMin(Double &x, UInt process, CommunicatorPtr comm);\n  void reduceMax(UInt   &x, UInt process, CommunicatorPtr comm);\n  void reduceMax(Double &x, UInt process, CommunicatorPtr comm);\n  ///@}\n\n  // =========================================================\n\n  /** @brief Parallelized loop.\n  * Calls @a func(i) for every @a i in [0,count).\n  * The different calls are distributed other the processes (without master).\n  * @return The process number for @a i is returned (valid at master). */\n  template<typename T> std::vector<UInt> forEach(UInt count, T func, CommunicatorPtr comm, Bool timing=TRUE);\n\n  /** @brief Parallelized loop.\n  * Calls @a vec[i]=func(i) for every @a i in [0,vec.size()).\n  * The different calls are distributed other the processes (without master).\n  * The result in @a vec is only valid at master.\n  * @return The process number for @a i is returned (valid at master). */\n  template<typename A, typename T> std::vector<UInt> forEach(std::vector<A> &vec, T func, CommunicatorPtr comm, Bool timing=TRUE);\n\n  /** @brief Parallelized loop.\n  * Calls @a func(i) for every @a i in [0,count).\n  * The different calls are distributed other the processes (without master).\n  * @return The process number for @a i is returned (valid at master). */\n  template<typename T> std::vector<UInt> forEachInterval(UInt count, const std::vector<UInt> &interval, T func, CommunicatorPtr comm, Bool timing=TRUE);\n\n  /** @brief Parallelized loop.\n  * Calls @a vec[i]=func(i) for every @a i in [0,vec.size()).\n  * The different calls are distributed other the processes (without master).\n  * The result in @a vec is only valid at master.\n  * @return The process number for @a i is returned (valid at master). */\n  template<typename A, typename T> std::vector<UInt> forEachInterval(std::vector<A> &vec, const std::vector<UInt> &interval, T func, CommunicatorPtr comm, Bool timing=TRUE);\n\n  /** @brief Parallelized loop.\n  * Calls @a func(i) for every @a i in [0,count).\n  * The different calls are distributed using @a processNo (without master).\n  * The result in @a vec is only valid at master. */\n  template<typename T> void forEachProcess(UInt count, T func, const std::vector<UInt> &processNo, CommunicatorPtr comm, Bool timing=TRUE);\n\n  /** @brief Parallelized loop.\n  * Calls @a vec[i]=func(i) for every @a i in [0,vec.size()).\n  * The different calls are distributed using @a processNo (without master).\n  * The result in @a vec is only valid at master. */\n  template<typename A, typename T> void forEachProcess(std::vector<A> &vec, T func, const std::vector<UInt> &processNo, CommunicatorPtr comm, Bool timing=TRUE);\n} // end namespace Parallel\n\n/***********************************************/\n\n/** @brief Loop with timing.\n* @ingroup parallelGroup */\nnamespace Single\n{\n  /** @brief loop with timing.\n  * Calls @a func(i) for every @a i in [0,count). */\n  template<typename T> void forEach(UInt count, T func, Bool timing=TRUE);\n} // end namespace Single\n\n/***********************************************/\n/***** INLINES ***********************************/\n/***********************************************/\n\ntemplate<typename T>\ninline void Parallel::send(const T &x, UInt process, CommunicatorPtr comm)\n{\n  if(size(comm)<=1)\n    return;\n  std::stringstream stream; //(std::ios::binary);\n  OutArchiveBinary oa(stream, \"\", MAX_UINT);\n  oa<<nameValue(\"xxx\", x);\n  std::string str = stream.str();\n  UInt size = str.size();\n  send(size, process, comm);\n  send(str.data(), size, process, comm);\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline void Parallel::receive(T &x, UInt process, CommunicatorPtr comm)\n{\n  if(size(comm)<=1)\n    return;\n  UInt size;\n  receive(size, process, comm);\n  Byte *str = new Byte[size+1];\n  receive(str, size, process, comm);\n  std::stringstream stream(std::string(str, size)); //, std::ios::binary);\n  InArchiveBinary ia(stream);\n  ia>>nameValue(\"xxx\", x);\n  delete[] str;\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline void Parallel::broadCast(T &x, UInt process, CommunicatorPtr comm)\n{\n  if(size(comm)<=1)\n    return;\n  if(Parallel::myRank(comm) == process)\n  {\n    std::stringstream stream(std::ios_base::out | std::ios::binary);\n    OutArchiveBinary oa(stream, \"\", MAX_UINT);\n    oa<<nameValue(\"xxx\", x);\n    std::string str = stream.str();\n    UInt size = str.size();\n    broadCast(size, process, comm);\n    broadCast(const_cast<Byte*>(str.data()), size, process, comm);\n  }\n  else\n  {\n    UInt size;\n    broadCast(size, process, comm);\n    Byte *str = new Byte[size+1];\n    broadCast(str, size, process, comm);\n    std::stringstream stream(std::string(str, size), std::ios_base::in | std::ios::binary);\n    InArchiveBinary ia(stream);\n    ia>>nameValue(\"xxx\", x);\n    delete[] str;\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<typename T>\ninline std::vector<UInt> Parallel::forEach(UInt count, T func, CommunicatorPtr comm, Bool timing)\n{\n  return forEachInterval(count, {0, count}, func, comm, timing);\n}\n\n/***********************************************/\n\ntemplate<typename A, typename T>\ninline std::vector<UInt> Parallel::forEach(std::vector<A> &vec, T func, CommunicatorPtr comm, Bool timing)\n{\n  return forEachInterval(vec, {0, vec.size()}, func, comm, timing);\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline std::vector<UInt> Parallel::forEachInterval(UInt count, const std::vector<UInt> &interval, T func, CommunicatorPtr comm, Bool timing)\n{\n  try\n  {\n    std::vector<UInt> processNo(count, 0);\n\n    // single process version\n    // ----------------------\n    if(size(comm) < 3)\n    {\n      // single process version\n      if(isMaster(comm))\n      {\n        Log::Timer timer(count, 1, timing);\n        for(UInt i=0; i<count; i++)\n        {\n          timer.loopStep(i);\n          func(i);\n        }\n        timer.loopEnd();\n      }\n      return processNo;\n    }\n\n    if(count!=interval.back())\n      throw(Exception(\"interval size and count differ\"));\n\n    // parallel version\n    // ----------------\n    if(isMaster(comm))\n    {\n      std::vector<UInt> countInInterval(interval.size()-1, 0);\n      std::vector<UInt> processedInterval(size(comm), NULLINDEX);\n\n      // master distributes the loop numbers\n      UInt process, index;\n      Log::Timer timer(count, size(comm)-1, timing);\n      for(UInt i=0; i<count; i++)\n      {\n        receive(process, NULLINDEX, comm); // which process needs work?\n        receive(index,   process, comm);  // loop numer be computed at process\n\n        // can we compute func in the same interval?\n        UInt idInterval = processedInterval.at(process);\n        if((idInterval==NULLINDEX) || (countInInterval.at(idInterval) >= interval.at(idInterval+1)-interval.at(idInterval)))\n        {\n          // search new interval to compute\n          UInt maxLeft = 0;\n          for(UInt k=0; k<countInInterval.size(); k++)\n          {\n            UInt left = interval.at(k+1)-interval.at(k)-countInInterval.at(k);\n            // interval not used?\n            if((countInInterval.at(k) == 0) && (left>0))\n            {\n              idInterval = k;\n              break;\n            }\n            if(left>maxLeft)\n            {\n              maxLeft = left;\n              idInterval = k;\n            }\n          }\n          processedInterval.at(process) = idInterval;\n        }\n\n        UInt id = interval.at(idInterval) + countInInterval.at(idInterval);\n        countInInterval.at(idInterval)++;\n        send(id, process, comm);       // send new loop number to be computed at process\n        processNo.at(id) = process;\n        timer.loopStep(i);\n      }\n      // send to all processes the end signal (NULLINDEX)\n      for(UInt i=1; i<size(comm); i++)\n      {\n        receive(process, NULLINDEX, comm); // which process needs work?\n        receive(index,   process, comm);  // loop numer be computed at process\n        send(NULLINDEX, process, comm);    // end signal\n      }\n      timer.loopEnd();\n    }\n    else // clients\n    {\n      send(myRank(comm), 0, comm);\n      send(NULLINDEX, 0, comm); // no results computed yet\n      for(;;)\n      {\n        UInt i;\n        receive(i,0, comm);\n        if(i==NULLINDEX)\n          break;\n        func(i);\n        send(myRank(comm), 0, comm);\n        send(i, 0, comm);\n      }\n    }\n\n    broadCast(processNo, 0, comm);\n    return processNo;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename A, typename T>\ninline std::vector<UInt> Parallel::forEachInterval(std::vector<A> &vec, const std::vector<UInt> &interval, T func, CommunicatorPtr comm, Bool timing)\n{\n  try\n  {\n    std::vector<UInt> processNo(vec.size(), 0);\n\n    // single process version\n    // ----------------------\n    if(size(comm) < 3)\n    {\n      // single process version\n      if(isMaster(comm))\n      {\n        Log::Timer timer(vec.size(), 1, timing);\n        for(UInt i=0; i<vec.size(); i++)\n        {\n          timer.loopStep(i);\n          vec[i] = func(i);\n        }\n        timer.loopEnd();\n      }\n      return processNo;\n    }\n\n    if(vec.size()!=interval.back())\n      throw(Exception(\"interval size and vec.size() differ\"));\n\n    // parallel version\n    // ----------------\n    if(isMaster(comm))\n    {\n      std::vector<UInt> countInInterval(interval.size()-1, 0);\n      std::vector<UInt> processedInterval(size(comm), NULLINDEX);\n\n      // master distributes the loop numbers\n      UInt process, index;\n      Log::Timer timer(vec.size(), size(comm)-1, timing);\n      for(UInt i=0; i<vec.size(); i++)\n      {\n        receive(process, NULLINDEX, comm); // which process needs work?\n        receive(index,   process, comm);  // loop numer be computed at process\n        if(index!=NULLINDEX)\n        {\n          receive(vec[index], process, comm); // receive result\n        }\n\n        // can we compute func in the same interval?\n        UInt idInterval = processedInterval.at(process);\n        if((idInterval==NULLINDEX) || (countInInterval.at(idInterval) >= interval.at(idInterval+1)-interval.at(idInterval)))\n        {\n          // search new interval to compute\n          UInt maxLeft = 0;\n          for(UInt k=0; k<countInInterval.size(); k++)\n          {\n            UInt left = interval.at(k+1)-interval.at(k)-countInInterval.at(k);\n            // interval not used?\n            if((countInInterval.at(k) == 0) && (left>0))\n            {\n              idInterval = k;\n              break;\n            }\n            if(left>maxLeft)\n            {\n              maxLeft = left;\n              idInterval = k;\n            }\n          }\n          processedInterval.at(process) = idInterval;\n        }\n\n        UInt id = interval.at(idInterval) + countInInterval.at(idInterval);\n        countInInterval.at(idInterval)++;\n        send(id, process, comm);           // send new loop number to be computed at process\n        processNo.at(id) = process;\n        timer.loopStep(i);\n      }\n      // send to all processes the end signal (NULLINDEX)\n      for(UInt i=1; i<size(comm); i++)\n      {\n        receive(process, NULLINDEX, comm);    // which process needs work?\n        receive(index,   process, comm);      // loop numer be computed at process\n        if(index!=NULLINDEX)\n          receive(vec[index], process, comm); // receive result\n        send(NULLINDEX, process, comm);       // end signal\n      }\n      timer.loopEnd();\n    }\n    else // clients\n    {\n      send(myRank(comm), 0, comm);\n      send(NULLINDEX, 0, comm); // no results computed yet\n      for(;;)\n      {\n        UInt i;\n        receive(i,0, comm);\n        if(i==NULLINDEX)\n          break;\n        vec[i] = func(i);\n        send(myRank(comm), 0, comm);\n        send(i, 0, comm);\n        send(vec[i], 0, comm);\n      }\n    }\n\n    broadCast(processNo, 0, comm);\n    return processNo;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename T>\ninline void Parallel::forEachProcess(UInt count, T func, const std::vector<UInt> &processNo, CommunicatorPtr comm, Bool timing)\n{\n  try\n  {\n    std::set<UInt> procs;\n    for(UInt p : processNo)\n      procs.insert(p);\n\n    UInt idx;\n    Log::Timer timer(count, procs.size(), timing);\n    for(UInt i=0; i<count; i++)\n    {\n      timer.loopStep(i);\n      if(myRank(comm) == processNo.at(i))\n      {\n        func(i);\n        if(!isMaster(comm)) send(i, 0, comm);\n      } // if(arcs.at(i))\n      else if(isMaster(comm))\n      {\n        receive(idx, NULLINDEX, comm);\n      }\n    } // for(i)\n    barrier(comm);\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<typename A, typename T>\ninline void Parallel::forEachProcess(std::vector<A> &vec, T func, const std::vector<UInt> &processNo, CommunicatorPtr comm, Bool timing)\n{\n  try\n  {\n    std::set<UInt> procs;\n    for(UInt p : processNo)\n      procs.insert(p);\n\n    UInt idx = 0;\n    Log::Timer timer(vec.size(), procs.size(), timing);\n    for(UInt i=0; i<vec.size(); i++)\n    {\n      timer.loopStep(i);\n      if(myRank(comm) == processNo.at(i))\n      {\n        vec[i] = func(i);\n        if(!isMaster(comm)) send(i, 0, comm);\n        if(!isMaster(comm)) send(vec[i], 0, comm);\n      } // if(arcs.at(i))\n      else if(isMaster(comm))\n      {\n        receive(idx, NULLINDEX, comm);\n        receive(vec[idx], processNo.at(idx), comm);\n      }\n    } // for(i)\n    barrier(comm);\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ntemplate<typename T>\ninline void Single::forEach(UInt count, T func, Bool timing)\n{\n{\n  try\n  {\n    Log::Timer timer(count, 1, timing);\n    for(UInt i=0; i<count; i++)\n    {\n      timer.loopStep(i);\n      func(i);\n    } // for(i)\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/parallel/parallelCluster.cpp",
    "content": "/***********************************************/\n/**\n* @file parallelCluster.cpp\n*\n* @brief Wrapper for Message Passing Interface (MPI).\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-13\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"base/gnssType.h\"\n#include \"parallel/parallel.h\"\n\n// #undef SEEK_SET\n// #undef SEEK_END\n// #undef SEEK_CUR\n#include <mpi.h>\n\n/***** FUNCTIONS *******************************/\n\nnamespace Parallel\n{\n\n/***********************************************/\n\ninline void check(int errorcode)\n{\n  if(errorcode != MPI_SUCCESS)\n  {\n    int  resultlen;\n    char errorStr[MPI_MAX_ERROR_STRING];\n    MPI_Error_string(errorcode, errorStr, &resultlen);\n    throw(Exception(\"MPI Error: \"+std::string(errorStr, resultlen)));\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Extra channels to communicate log messages and exceptions\nclass HiddenChannel\n{\npublic:\n  MPI_Comm    comm;\n  MPI_Request request;\n\n  HiddenChannel(MPI_Comm communicator)\n  {\n    try\n    {\n      request = MPI_REQUEST_NULL;\n      check(MPI_Comm_dup(communicator, &comm));\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n\n  virtual ~HiddenChannel()\n  {\n    int completed;\n    check(MPI_Test(&request, &completed, MPI_STATUS_IGNORE));\n    if(!completed)\n    {\n      check(MPI_Cancel(&request));\n      check(MPI_Request_free(&request));\n    }\n    check(MPI_Comm_free(&comm));\n  }\n\n  virtual void receivedSignal() = 0;\n};\n\n/***********************************************/\n/***********************************************/\n\nclass Mpi\n{\npublic:\n  std::vector<std::shared_ptr<HiddenChannel>> channels;\n\n  Mpi(int argc, char *argv[])\n  {\n    int provided;\n    MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided);\n  }\n\n ~Mpi()\n  {\n    channels.clear();\n    MPI_Finalize();\n  }\n};\n\n\n/***********************************************/\n/***********************************************/\n\nclass Communicator\n{\npublic:\n  std::shared_ptr<Mpi> mpi;\n  MPI_Comm             comm;\n\n  Communicator(CommunicatorPtr commParent, MPI_Comm comm_) : comm(comm_)\n  {\n    if(commParent)\n      mpi = commParent->mpi;\n  }\n\n ~Communicator()\n  {\n    if((comm != MPI_COMM_WORLD) && (comm != MPI_COMM_SELF) && (comm != MPI_COMM_NULL))\n      MPI_Comm_free(&comm);\n  }\n\n  void peek();\n  void wait(MPI_Request &request);\n};\n\n/***********************************************/\n\ninline void Communicator::peek()\n{\n  try\n  {\n    if(mpi)\n      for(auto &channel : mpi->channels)\n        if(channel->request != MPI_REQUEST_NULL)\n        {\n          int flag = 0;\n          check(MPI_Test(&(channel->request), &flag, MPI_STATUS_IGNORE));\n          if(flag)\n            channel->receivedSignal();\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void Communicator::wait(MPI_Request &request)\n{\n  try\n  {\n    if(request == MPI_REQUEST_NULL)\n    {\n      peek();\n      return;\n    }\n\n    // repeat until our request finished\n    for(;;)\n    {\n      std::vector<MPI_Request> requests(1, request);\n      if(mpi)\n        for(auto &channel : mpi->channels)\n          requests.push_back(channel->request);\n\n      int index = -1;\n      check(MPI_Waitany(requests.size(), requests.data(), &index, MPI_STATUS_IGNORE));\n      if((index == MPI_UNDEFINED) || (index < 0))\n        throw(Exception(\"no active handles\"));\n\n      // our is request finished\n      if(index == 0)\n      {\n        request = requests.at(0); // should be MPI_REQUEST_NULL\n        peek();\n        break;\n      }\n\n      // check extra channels\n      mpi->channels.at(index-1)->request = requests.at(index); // should be MPI_REQUEST_NULL\n      mpi->channels.at(index-1)->receivedSignal();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nCommunicatorPtr init(int argc, char *argv[])\n{\n  try\n  {\n    auto mpi = std::make_shared<Mpi>(argc, argv);\n    CommunicatorPtr comm = std::make_shared<Communicator>(nullptr, MPI_COMM_WORLD);\n    comm->mpi = mpi;\n    return comm;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nCommunicatorPtr splitCommunicator(UInt color, UInt key, CommunicatorPtr comm)\n{\n  try\n  {\n    barrier(comm); // check for possible exceptions\n    MPI_Comm commNew;\n    check(MPI_Comm_split(comm->comm, ((color==NULLINDEX) ? MPI_UNDEFINED : color), key, &commNew));\n    if(color==NULLINDEX)\n      return nullptr;\n    return std::make_shared<Communicator>(comm, commNew);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nCommunicatorPtr createCommunicator(std::vector<UInt> ranks, CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<int> mpiRanks(ranks.size());\n    for(UInt i=0; i<ranks.size(); i++)\n      mpiRanks.at(i) = static_cast<int>(ranks.at(i));\n\n    MPI_Group group, newgroup;\n    check(MPI_Comm_group(comm->comm, &group));\n    check(MPI_Group_incl(group, mpiRanks.size(), mpiRanks.data(), &newgroup));\n#if MPI_VERSION >= 3\n    // check for possible exceptions\n    UInt dummy = 0;\n    if(ranks.at(0) == myRank(comm))\n    {\n      for(UInt i=1; i<ranks.size(); i++)\n        receive(dummy, ranks.at(i), comm);\n      for(UInt i=1; i<ranks.size(); i++)\n        send(dummy, ranks.at(i), comm);\n    }\n    else\n      for(UInt i=1; i<ranks.size(); i++)\n        if(ranks.at(i) == myRank(comm))\n        {\n          send   (dummy, ranks.at(0), comm);\n          receive(dummy, ranks.at(0), comm);\n        }\n    MPI_Comm commNew;\n    check(MPI_Comm_create_group(comm->comm, newgroup, 99, &commNew));\n#else\n    barrier(comm); // check for possible exceptions\n    MPI_Comm commNew;\n    check(MPI_Comm_create(comm->comm, newgroup, &commNew));\n#endif\n    check(MPI_Group_free(&group));\n    check(MPI_Group_free(&newgroup));\n    if(commNew == MPI_COMM_NULL)\n      return nullptr;\n    return std::make_shared<Communicator>(comm, commNew);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nCommunicatorPtr selfCommunicator()\n{\n  try\n  {\n    return std::make_shared<Communicator>(nullptr, MPI_COMM_SELF);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nUInt myRank(CommunicatorPtr comm)\n{\n  int rank;\n  check(MPI_Comm_rank(comm->comm, &rank));\n  return static_cast<UInt>(rank);\n}\n\n/***********************************************/\n\nUInt size(CommunicatorPtr comm)\n{\n  int size;\n  check(MPI_Comm_size(comm->comm, &size));\n  return static_cast<UInt>(size);\n}\n\n/***********************************************/\n\nvoid barrier(CommunicatorPtr comm)\n{\n  try\n  {\n    MPI_Request request;\n    check(MPI_Ibarrier(comm->comm, &request));\n    comm->wait(request);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid peek(CommunicatorPtr comm)\n{\n  try\n  {\n    comm->peek();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass LogChannel : public HiddenChannel\n{\n  int                      rank, sendRank;\n  unsigned int             type, count;\n  std::vector<char>        data;\n  std::vector<MPI_Request> sendRequests;\n  std::function<void(UInt rank, UInt type, const std::string &str)> receive;\n\npublic:\n  LogChannel(MPI_Comm communicator, std::function<void(UInt rank, UInt type, const std::string &str)> recv);\n ~LogChannel();\n  void receivedSignal() override;\n  void sendSignal(UInt type, const std::string &str);\n};\n\n/***********************************************/\n\nLogChannel::LogChannel(MPI_Comm communicator, std::function<void(UInt rank, UInt type, const std::string &str)> recv) : HiddenChannel(communicator), sendRequests(4, MPI_REQUEST_NULL), receive(recv)\n{\n  try\n  {\n    check(MPI_Comm_rank(comm, &rank));\n    if(rank == 0)\n      check(MPI_Irecv(&sendRank, 1, MPI_INT, MPI_ANY_SOURCE, 111, comm, &request));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nLogChannel::~LogChannel()\n{\n  for(MPI_Request sendRequest : sendRequests)\n  {\n    int completed;\n    check(MPI_Test(&sendRequest, &completed, MPI_STATUS_IGNORE));\n    if(!completed)\n    {\n      check(MPI_Cancel(&sendRequest));\n      check(MPI_Request_free(&sendRequest));\n    }\n  }\n}\n\n/***********************************************/\n\nvoid LogChannel::sendSignal(UInt type_, const std::string &str)\n{\n  try\n  {\n    if(rank == 0)\n    {\n      receive(0, type_, str);\n      return;\n    }\n\n    // wait for pending sends\n    check(MPI_Waitall(sendRequests.size(), sendRequests.data(), MPI_STATUSES_IGNORE));\n\n    type  = static_cast<unsigned int>(type_);\n    count = str.size();\n    data.resize(count);\n    std::copy(str.begin(), str.end(), data.begin());\n\n    check(MPI_Isend(&rank,  1, MPI_INT,      0, 111, comm, &sendRequests.at(0)));\n    check(MPI_Isend(&type,  1, MPI_UNSIGNED, 0, 222, comm, &sendRequests.at(1)));\n    check(MPI_Isend(&count, 1, MPI_UNSIGNED, 0, 333, comm, &sendRequests.at(2)));\n    if(count)\n      check(MPI_Isend(data.data(), count, MPI_CHAR, 0, 444, comm, &sendRequests.at(3)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid LogChannel::receivedSignal()\n{\n  try\n  {\n    int completed = 0;\n    do\n    {\n      check(MPI_Recv(&type,  1, MPI_UNSIGNED, sendRank, 222, comm, MPI_STATUS_IGNORE));\n      check(MPI_Recv(&count, 1, MPI_UNSIGNED, sendRank, 333, comm, MPI_STATUS_IGNORE));\n      data.resize(count);\n      if(count)\n        check(MPI_Recv(data.data(), count, MPI_CHAR, sendRank, 444, comm, MPI_STATUS_IGNORE));\n      receive(static_cast<UInt>(sendRank), static_cast<UInt>(type), std::string(data.data(), count));\n      data.clear();\n      check(MPI_Irecv(&sendRank, 1, MPI_INT, MPI_ANY_SOURCE, 111, comm, &request));\n      check(MPI_Test(&request, &completed, MPI_STATUS_IGNORE));\n    }\n    while(completed);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::function<void(UInt type, const std::string &str)> addChannel(const std::function<void(UInt rank, UInt type, const std::string &str)> &receive, CommunicatorPtr comm)\n{\n  try\n  {\n    auto channel = std::make_shared<LogChannel>(MPI_COMM_WORLD, receive);\n    comm->mpi->channels.insert(comm->mpi->channels.begin(), channel); // handle logs before exceptions\n    return std::bind(&LogChannel::sendSignal, channel.get(), std::placeholders::_1, std::placeholders::_2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nclass ErrorChannel : public HiddenChannel\n{\n  std::shared_ptr<Mpi> mpi;\n  int                  code;\n  unsigned int         isExternalSignal;\n\npublic:\n  ErrorChannel(CommunicatorPtr comm);\n  void receivedSignal() override;\n  void broadCastException(const std::string &msg);\n  void synchronizeAndThrowException(const std::string &msg);\n};\n\n/***********************************************/\n\nclass BroadCastedException\n{\npublic:\n  std::string message;\n  BroadCastedException(const std::string &msg)  : message(msg) {}\n};\n\nstatic const std::string STRING_EXCEPTION_EXTERNAL(\"interrupted by exception from other process\");\n\n/***********************************************/\n\nErrorChannel::ErrorChannel(CommunicatorPtr comm)  : HiddenChannel(comm->comm), mpi(comm->mpi), code(0), isExternalSignal(0)\n{\n  try\n  {\n    check(MPI_Irecv(&code, 1, MPI_INT, MPI_ANY_SOURCE, 666, this->comm, &request));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ErrorChannel::receivedSignal()\n{\n  // mark all subgroups\n  Bool isSubGroup = FALSE;\n  auto iter = std::find_if(mpi->channels.begin(), mpi->channels.end(), [this](auto &x) {return x.get() == this;});\n  if(iter != mpi->channels.end())\n    while(++iter != mpi->channels.end())\n    {\n      if(dynamic_cast<ErrorChannel*>(iter->get()))\n        dynamic_cast<ErrorChannel*>(iter->get())->isExternalSignal = 1;\n      isSubGroup = TRUE;\n    }\n\n  if(isSubGroup)\n    throw(Exception(STRING_EXCEPTION_EXTERNAL)); // handle subgroup first\n\n  check(MPI_Barrier(comm));\n  synchronizeAndThrowException(std::string());\n}\n\n/***********************************************/\n\nvoid ErrorChannel::broadCastException(const std::string &msg)\n{\n  try\n  {\n    int rank, size;\n    check(MPI_Comm_rank(comm, &rank));\n    check(MPI_Comm_size(comm, &size));\n\n    // send signal to all other processes\n    int code;\n    std::vector<MPI_Request> requests(size, MPI_REQUEST_NULL);\n    for(int i=0; i<size; i++)\n      if(i != rank)\n        check(MPI_Issend(&code, 1, MPI_INT, i, 666, comm, &requests.at(i)));\n\n    // wait for all processed (corresponding barrier() in receivedSignal())\n    check(MPI_Barrier(comm));\n\n    // cleanup all pending requests\n    for(UInt i=0; i<requests.size(); i++)\n      if(requests.at(i) != MPI_REQUEST_NULL)\n      {\n        int completed = 0;\n        check(MPI_Test(&requests.at(i), &completed, MPI_STATUS_IGNORE));\n        if(completed)\n          continue;\n        check(MPI_Cancel(&requests.at(i)));\n        check(MPI_Request_free(&requests.at(i)));\n      }\n\n    synchronizeAndThrowException(msg);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid ErrorChannel::synchronizeAndThrowException(const std::string &msg)\n{\n  try\n  {\n    // complete remaining incoming messages\n    int completed = 1;\n    check(MPI_Test(&request, &completed, MPI_STATUS_IGNORE));\n    while(completed)\n    {\n      check(MPI_Irecv(&code, 1, MPI_INT, MPI_ANY_SOURCE, 666, comm, &request));\n      check(MPI_Test(&request, &completed, MPI_STATUS_IGNORE));\n    }\n\n    // check for any external signals\n    unsigned int isExternalSignalSum = 0;\n    check(MPI_Allreduce(&isExternalSignal, &isExternalSignalSum, 1, MPI_UNSIGNED, MPI_SUM, comm));\n    if(isExternalSignalSum)\n      throw(BroadCastedException(STRING_EXCEPTION_EXTERNAL));\n\n    int rank, size;\n    check(MPI_Comm_rank(comm, &rank));\n    check(MPI_Comm_size(comm, &size));\n\n    // collect and broadCast all messages\n    std::vector<std::pair<UInt, std::string>> msgs;\n    for(int process=0; process<size; process++)\n    {\n      unsigned int count = msg.size();\n      check(MPI_Bcast(&count, 1, MPI_UNSIGNED, process, comm));\n      if(!count)\n        continue;\n      std::vector<char> data(count);\n      if(process == rank)\n        std::copy(msg.begin(), msg.end(), data.begin());\n      check(MPI_Bcast(data.data(), count, MPI_CHAR, process, comm));\n      msgs.push_back(std::pair<UInt, std::string>(process, std::string(data.data(), count)));\n    }\n\n    // remove duplicates\n    std::sort(msgs.begin(), msgs.end(), [](const auto &x, const auto &y){return (x.second == y.second) ? (x.first<y.first) : (x.second<y.second);});\n    msgs.erase(std::unique(msgs.begin(), msgs.end(), [](const auto &x, const auto &y){return (x.second == y.second);}), msgs.end());\n    std::sort(msgs.begin(), msgs.end(), [](const auto &x, const auto &y){return (x.first<y.first);});\n\n    // collect messages\n    std::string completeMsg;\n    Bool newLine = FALSE;\n    for(auto &msg : msgs)\n      if(msg.second.find(STRING_EXCEPTION_EXTERNAL) == std::string::npos)\n      {\n        if(newLine)\n          completeMsg += \"\\n\";\n        newLine = TRUE;\n        if(msg.first)\n          completeMsg += \"in process \"+msg.first%\"%i of \"s+size%\"%i:\\n\"s;\n        completeMsg += msg.second;\n      }\n    if(completeMsg.empty())\n      throw(BroadCastedException(\"no message\"));\n    throw(BroadCastedException(completeMsg));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid broadCastExceptions(CommunicatorPtr commOld, std::function<void(CommunicatorPtr)> func)\n{\n  try // distributed exceptions\n  {\n    // duplicate communicator\n    // as comm might be unusable after exception due to unfinished communications\n    if(!commOld->mpi)\n      throw(Exception(\"self communicator not allowed\"));\n    MPI_Comm commDuplicate;\n    check(MPI_Comm_dup(commOld->comm, &commDuplicate));\n    CommunicatorPtr comm = std::make_shared<Communicator>(commOld, commDuplicate);\n\n    // and setup error channel\n    auto errorChannel = std::make_shared<ErrorChannel>(comm);\n    comm->mpi->channels.push_back(errorChannel);\n\n    try // local exceptions\n    {\n      func(comm);\n      barrier(comm);\n    }\n    catch(BroadCastedException &e)\n    {\n      throw;\n    }\n    catch(std::exception &e)\n    {\n      errorChannel->broadCastException(e.what());\n    }\n    catch(...)\n    {\n      errorChannel->broadCastException(\"Unknown ERROR\");\n    }\n\n    comm->mpi->channels.pop_back();\n  }\n  catch(BroadCastedException &e)\n  {\n    commOld->mpi->channels.pop_back();\n    throw(Exception(e.message));\n  }\n  catch(std::exception &e)\n  {\n    std::cerr<<\"\\033[1;31m\"<<\"****** Fatal error ******\"<<std::endl;\n    std::cerr<<e.what()<<\"\\033[0m\"<<std::endl;\n    MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);\n    exit(EXIT_FAILURE);\n  }\n  catch(...)\n  {\n    std::cerr<<\"\\033[1;31m\"<<\"****** Fatal unknown error ******\"<<\"\\033[0m\"<<std::endl;\n    MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);\n    exit(EXIT_FAILURE);\n  }\n}\n\n/***********************************************/\n\nBool isExternal(std::exception &e)\n{\n  return e.what() == STRING_EXCEPTION_EXTERNAL;\n}\n\n/***********************************************/\n/***********************************************/\n\ninline void send(const void *buffer, UInt count, MPI_Datatype datatype, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    MPI_Request request;\n    check(MPI_Isend(buffer, count, datatype, process, 17, comm->comm, &request));\n    comm->wait(request);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid send(const Byte *x, UInt size, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    send(x, size, MPI_CHAR, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const UInt &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y = static_cast<unsigned int>(x);\n    send(&y, 1, MPI_UNSIGNED, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Double &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    send(&x, 1, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Bool &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y = static_cast<unsigned int>(x);\n    send(&y, 1, MPI_UNSIGNED, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Angle &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    send(&x, 1, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Time &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    send(static_cast<Double>(x.mjdInt()), process, comm);\n    send(x.mjdMod(), process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const GnssType &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y = static_cast<unsigned int>(x.type);\n    send(&y, 1, MPI_UNSIGNED, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Vector3d &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    send(x.vector().field(), 3, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Vector &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    send(x.rows(), process, comm);\n    if(x.size()!=0)\n      send(x.field(), x.size(), MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void send(const Matrix &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    UInt type  = static_cast<UInt>(x.getType());\n    UInt upper = x.isUpper();\n    send(x.rows(),    process, comm);\n    send(x.columns(), process, comm);\n    send(type,        process, comm);\n    send(upper,       process, comm);\n    if(x.size()!=0)\n      send(x.field(), x.size(), MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ninline void receive(void *buffer, UInt count, MPI_Datatype datatype, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    MPI_Request request;\n    check(MPI_Irecv(buffer, count, datatype, ((process!=NULLINDEX) ? process : MPI_ANY_SOURCE), 17, comm->comm, &request));\n    comm->wait(request);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid receive(Byte *x, UInt size, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    receive(x, size, MPI_CHAR, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(UInt &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y;\n    receive(&y, 1, MPI_UNSIGNED, process, comm);\n    x = static_cast<UInt>(y);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Double &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    receive(&x, 1, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Bool &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y;\n    receive(&y, 1, MPI_UNSIGNED, process, comm);\n    x = static_cast<Bool>(y);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Angle &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    receive(&x, 1, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Time &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    Double mjdInt, mjdMod;\n    receive(mjdInt, process, comm);\n    receive(mjdMod, process, comm);\n    x = Time(static_cast<Int>(mjdInt), mjdMod);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Vector3d &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    Double v[3];\n    receive(v, 3, MPI_DOUBLE, process, comm);\n    x.x() = v[0];\n    x.y() = v[1];\n    x.z() = v[2];\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Vector &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    UInt rows;\n    receive(rows, process, comm);\n    x = Vector(rows);\n    if(x.size()!=0)\n      receive(x.field(), x.size(), MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(Matrix &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    UInt rows, columns;\n    UInt  type, upper;\n    receive(rows,    process, comm);\n    receive(columns, process, comm);\n    receive(type,    process, comm);\n    receive(upper,   process, comm);\n    x = Matrix(rows, columns);\n    x.setType(static_cast<Matrix::Type>(type), (upper) ? Matrix::UPPER : Matrix::LOWER);\n    if(x.size()!=0)\n      receive(x.field(), x.size(), MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void receive(GnssType &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y;\n    receive(&y, 1, MPI_UNSIGNED, process, comm);\n    x = GnssType(static_cast<UInt>(y));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ninline void broadCast(void *buffer, UInt count, MPI_Datatype datatype, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    MPI_Request request;\n    check(MPI_Ibcast(buffer, count, datatype, process, comm->comm, &request));\n    comm->wait(request);\n    barrier(comm); // prevents rare deadlocks when broadcast is called rapidly within loop, possibly MPI issue?\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid broadCast(Byte *x, UInt size, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    broadCast(x, size, MPI_CHAR, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(UInt &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y = static_cast<unsigned int>(x);\n    broadCast(&y, 1, MPI_UNSIGNED, process, comm);\n    x = static_cast<UInt>(y);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(Double &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    broadCast(&x, 1, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(Bool &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y = static_cast<unsigned int>(x);\n    broadCast(&y, 1, MPI_UNSIGNED, process, comm);\n    x = static_cast<Bool>(y);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(Angle &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    broadCast(&x, 1, MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(Time &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    Double mjdInt = x.mjdInt();\n    Double mjdMod = x.mjdMod();\n    broadCast(mjdInt, process, comm);\n    broadCast(mjdMod, process, comm);\n    x = Time(static_cast<Int>(mjdInt), mjdMod);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(GnssType &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    unsigned int y = static_cast<unsigned int>(x.type);\n    broadCast(&y, 1, MPI_UNSIGNED, process, comm);\n    x = GnssType(static_cast<UInt>(y));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(Vector &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    UInt rows = x.rows();\n    broadCast(rows, process, comm);\n    if(x.rows() != rows)\n      x = Vector(rows);\n    if(x.size()!=0)\n      broadCast(x.field(), x.size(), MPI_DOUBLE, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> void broadCast(Matrix &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    UInt rows = x.rows();\n    UInt cols = x.columns();\n    UInt type  = static_cast<UInt>(x.getType());\n    UInt upper = x.isUpper();\n\n    broadCast(rows,  process, comm);\n    broadCast(cols,  process, comm);\n    broadCast(type,  process, comm);\n    broadCast(upper, process, comm);\n\n    if((x.rows() != rows) || (x.columns() != cols))\n      x = Matrix(rows, cols);\n    x.setType(static_cast<Matrix::Type>(type), (upper) ? Matrix::UPPER : Matrix::LOWER);\n\n    constexpr UInt BLOCKSIZE = 200*1024*1024/sizeof(Double); // 200 Mb\n    UInt index = 0;\n    while(index<x.size())\n    {\n      const UInt size = std::min(x.size()-index, BLOCKSIZE);\n      broadCast(x.field()+index, size, MPI_DOUBLE, process, comm);\n      index += size;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\ninline void reduce(const void *sendbuf, void *recvbuf, UInt count, MPI_Datatype datatype,\n                   MPI_Op op, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    MPI_Request request;\n    check(MPI_Ireduce(sendbuf, recvbuf, count, datatype, op, process, comm->comm, &request));\n    comm->wait(request);\n    barrier(comm); // prevents rare deadlocks when reduce is called rapidly within loop, possibly MPI issue?\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceSum(UInt &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      unsigned int tmp = static_cast<unsigned int >(x);\n      unsigned int y = 0;\n      reduce(&tmp, &y, 1, MPI_UNSIGNED, MPI_SUM, process, comm);\n      x = static_cast<UInt>(y);\n    }\n    else\n    {\n      unsigned int y = static_cast<unsigned int>(x);\n      reduce(&y, nullptr, 1, MPI_UNSIGNED, MPI_SUM, process, comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceSum(Double &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      Double tmp = x;\n      x = 0;\n      reduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, process, comm);\n    }\n    else\n      reduce(&x, nullptr, 1, MPI_DOUBLE, MPI_SUM, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceSum(Bool &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      unsigned int tmp = static_cast<unsigned int >(x);\n      unsigned int y = 0;\n      reduce(&tmp, &y, 1, MPI_UNSIGNED, MPI_SUM, process, comm);\n      x = static_cast<Bool>(y);\n    }\n    else\n    {\n      unsigned int y = static_cast<unsigned int>(x);\n      reduce(&y, nullptr, 1, MPI_UNSIGNED, MPI_SUM, process, comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceSum(Matrix &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    constexpr UInt BLOCKSIZE = 50*1024*1024/sizeof(Double); // 50 Mb\n\n    UInt index = 0;\n    while(index<x.size())\n    {\n      const UInt size = std::min(x.size()-index, BLOCKSIZE);\n      if(myRank(comm) == process)\n      {\n        Vector tmp(size);\n        reduce(x.field()+index, tmp.field(), size, MPI_DOUBLE, MPI_SUM, process, comm);\n        std::copy_n(tmp.field(), size, x.field()+index);\n      }\n      else\n        reduce(x.field()+index, nullptr, size, MPI_DOUBLE, MPI_SUM, process, comm);\n\n      index += size;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceSum(std::vector<Double> &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      std::vector<Double> tmp(x.size(), 0.);\n      reduce(x.data(), tmp.data(), x.size(), MPI_DOUBLE, MPI_SUM, process, comm);\n      std::swap(tmp, x);\n    }\n    else\n      reduce(x.data(), nullptr, x.size(), MPI_DOUBLE, MPI_SUM, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid reduceMin(UInt &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      unsigned int tmp = static_cast<unsigned int>(x);\n      unsigned int y   = tmp;\n      reduce(&tmp, &y, 1, MPI_UNSIGNED, MPI_MIN, process, comm);\n      x = static_cast<UInt>(y);\n    }\n    else\n    {\n      unsigned int y = static_cast<unsigned int>(x);\n      reduce(&y, nullptr, 1, MPI_UNSIGNED, MPI_MIN, process, comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceMin(Double &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      Double tmp = x;\n      reduce(&tmp, &x, 1, MPI_DOUBLE, MPI_MIN, process, comm);\n    }\n    else\n      reduce(&x, nullptr, 1, MPI_DOUBLE, MPI_MIN, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceMax(UInt &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      unsigned int tmp = static_cast<unsigned int>(x);\n      unsigned int y   = tmp;\n      reduce(&tmp, &y, 1, MPI_UNSIGNED, MPI_MAX, process, comm);\n      x = static_cast<UInt>(y);\n    }\n    else\n    {\n      unsigned int y = static_cast<unsigned int>(x);\n      reduce(&y, nullptr, 1, MPI_UNSIGNED, MPI_MAX, process, comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid reduceMax(Double &x, UInt process, CommunicatorPtr comm)\n{\n  try\n  {\n    if(myRank(comm) == process)\n    {\n      Double tmp = x;\n      reduce(&tmp, &x, 1, MPI_DOUBLE, MPI_MAX, process, comm);\n    }\n    else\n      reduce(&x, nullptr, 1, MPI_DOUBLE, MPI_MAX, process, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n} // namespace Parallel\n"
  },
  {
    "path": "source/parallel/parallelSingle.cpp",
    "content": "/***********************************************/\n/**\n* @file parallelSingle.cpp\n*\n* @brief Wrapper for Message Passing Interface (MPI).\n* All functions are empty statements for single processor version.\n*\n* @author Torsten Mayer-Guerr\n* @date 2004-11-13\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/gnssType.h\"\n#include \"parallel/parallel.h\"\n\n/***** FUNCTIONS *******************************/\n\nnamespace Parallel\n{\n/***********************************************/\n\nCommunicatorPtr init(int /*argc*/, char */*argv*/[]) {return nullptr;}\nstd::function<void(UInt type, const std::string &str)> addChannel(const std::function<void(UInt rank, UInt type, const std::string &str)> &receive, CommunicatorPtr /*comm*/)\n{\n  return std::bind(receive, 0, std::placeholders::_1, std::placeholders::_2);\n}\nCommunicatorPtr splitCommunicator(UInt /*color*/, UInt /*key*/, CommunicatorPtr /*comm*/) {return nullptr;}\nCommunicatorPtr createCommunicator(std::vector<UInt> /*ranks*/, CommunicatorPtr /*comm*/) {return nullptr;}\nCommunicatorPtr selfCommunicator() {return nullptr;}\nUInt myRank(CommunicatorPtr /*comm*/) {return 0;}\nUInt size(CommunicatorPtr /*comm*/)   {return 1;}\nvoid barrier(CommunicatorPtr /*comm*/) {}\nvoid peek(CommunicatorPtr /*comm*/) {}\nvoid broadCastExceptions(CommunicatorPtr comm, std::function<void(CommunicatorPtr)> func) {func(comm);}\nBool isExternal(std::exception &/*e*/) {return FALSE;}\nvoid send(const Byte */*x*/, UInt /*size*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid receive  (Byte  */*x*/, UInt /*size*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid broadCast(Byte  */*x*/, UInt /*size*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const UInt     &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Double   &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Bool     &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Angle    &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Time     &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const GnssType &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Vector3d &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Vector   &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void send(const Matrix   &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(UInt        &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Double      &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Bool        &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Angle       &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Time        &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(GnssType    &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Vector3d    &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Vector      &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void receive(Matrix      &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(UInt      &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Double    &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Bool      &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Angle     &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Time      &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(GnssType  &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Vector3d  &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Vector    &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\ntemplate<> void broadCast(Matrix    &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceSum(UInt                 &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceSum(Double               &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceSum(Bool                 &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceSum(Matrix               &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceSum(std::vector<Double>  &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceMin(UInt                 &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceMin(Double               &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceMax(UInt                 &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\nvoid reduceMax(Double               &/*x*/, UInt /*process*/, CommunicatorPtr /*comm*/) {}\n\n/***********************************************/\n\n} // namespace Parallel\n"
  },
  {
    "path": "source/parser/dataVariables.cpp",
    "content": "/***********************************************/\n/**\n* @file dataVariables.cpp\n*\n* @brief Create variables to evaluate a matrix/grid/timeSeries.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-06-18\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/time.h\"\n#include \"base/griddedData.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/expressionParser.h\"\n#include \"parser/dataVariables.h\"\n\n/***********************************************/\n\nvoid addTimeVariables(VariableList &varList)\n{\n  try\n  {\n    varList.undefineVariable(\"loopTime\");\n    varList.undefineVariable(\"loopTimeStart\");\n    varList.undefineVariable(\"loopTimeEnd\");\n    varList.undefineVariable(\"index\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid evaluateTimeVariables(UInt index, const Time &timeStart, const Time &timeEnd, VariableList &varList)\n{\n  try\n  {\n    varList.setVariable(\"loopTime\", timeStart.mjd());\n    varList.setVariable(\"loopTimeStart\", timeStart.mjd());\n    varList.setVariable(\"loopTimeEnd\", timeEnd.mjd());\n    varList.setVariable(\"index\", static_cast<Double>(index));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic Double step(const_MatrixSliceRef data)\n{\n  if(data.size() < 2)\n    return NAN_EXPR;\n  std::vector<Double> tmp = flatten(data);\n  std::adjacent_difference(tmp.begin(), tmp.end(), tmp.begin());\n  std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](const Double &x) {return std::fabs(x);});\n  return *std::min_element(tmp.begin(), tmp.end());\n}\n\n/***********************************************/\n\nvoid addDataVariables(const std::string &prefix, const_MatrixSliceRef data, VariableList &varList)\n{\n  try\n  {\n    class Func : public ExpressionVariable::Func\n    {\n      MatrixSlice data;\n      Double (*f)(const_MatrixSliceRef);\n    public:\n      Func(const_MatrixSliceRef data, Double (*f)(const_MatrixSliceRef)) : data(data), f(f) {}\n      virtual ~Func() {}\n      Double operator()() const override {return f(data);}\n    };\n\n    varList.undefineVariable(prefix);\n    varList.setVariable(prefix+\"count\", static_cast<Double>(data.size()));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"min\",    std::make_shared<Func>(data, min)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"max\",    std::make_shared<Func>(data, max)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"sum\",    std::make_shared<Func>(data, sum)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"mean\",   std::make_shared<Func>(data, mean)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"rms\",    std::make_shared<Func>(data, rootMeanSquare)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"std\",    std::make_shared<Func>(data, standardDeviation)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"median\", std::make_shared<Func>(data, median)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"mad\",    std::make_shared<Func>(data, medianAbsoluteDeviation)));\n    varList.addVariable(std::make_shared<ExpressionVariable>(prefix+\"step\",   std::make_shared<Func>(data, step)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid addDataVariables(const std::string &prefix, const std::vector<Time> &times, VariableList &varList)\n{\n  try\n  {\n    Vector data(times.size());\n    for(UInt i=0; i<times.size(); i++)\n      data(i) = times.at(i).mjd();\n    addDataVariables(prefix, data, varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid addDataVariables(const std::string &prefix, const_MatrixSliceRef data, const_MatrixSliceRef weight, VariableList &varList)\n{\n  try\n  {\n    addDataVariables(prefix, data, varList);\n    if(!weight.size())\n      return;\n\n    Double w     = sum(weight);\n    Double wmean = inner(data, weight)/w;\n    Double wrms  = 0;\n    for(UInt i=0; i<data.rows(); i++)\n      for(UInt k=0; k<data.columns(); k++)\n        wrms += weight(i,k)/w * data(i,0) * data(i,k);\n\n    varList.setVariable(prefix+\"wmean\", wmean);\n    varList.setVariable(prefix+\"wrms\",  std::sqrt(wrms));\n    varList.setVariable(prefix+\"wstd\",  std::sqrt(data.size()/(data.size()-1.)*(wrms-wmean*wmean)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid addDataVariables(const_MatrixSliceRef data, VariableList &varList)\n{\n  try\n  {\n    varList.undefineVariable(\"index\");\n    for(UInt i=0; i<data.columns(); i++)\n      addDataVariables(\"data\"+i%\"%i\"s, data.column(i), varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid evaluateDataVariables(const_MatrixSliceRef data, UInt row, VariableList &varList)\n{\n  try\n  {\n    varList.setVariable(\"index\", static_cast<Double>(row)); // index\n    for(UInt i=0; i<data.columns(); i++)\n      varList.setVariable(\"data\"+i%\"%i\"s, data(row,i)); // \"data(i)\"\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid undefineDataVariables(const_MatrixSliceRef data, VariableList &varList)\n{\n  try\n  {\n    varList.undefineVariable(\"index\"); // index\n    for(UInt i=0; i<data.columns(); i++)\n      varList.undefineVariable(\"data\"+i%\"%i\"s); // \"data(i)\"\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid addDataVariables(const GriddedData &grid, VariableList &varList)\n{\n  try\n  {\n    varList.undefineVariable(\"longitude\");\n    varList.undefineVariable(\"latitude\");\n    varList.undefineVariable(\"height\");\n    varList.undefineVariable(\"cartesianX\");\n    varList.undefineVariable(\"cartesianY\");\n    varList.undefineVariable(\"cartesianZ\");\n    varList.undefineVariable(\"area\");\n    varList.undefineVariable(\"index\");\n    for(UInt i=0; i<grid.values.size(); i++)\n      addDataVariables(\"data\"+i%\"%i\"s, Vector(grid.values.at(i)), Vector(grid.areas), varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid evaluateDataVariables(const GriddedData &grid, UInt row, VariableList &varList)\n{\n  try\n  {\n    Angle  L, B;\n    Double h;\n    grid.ellipsoid(grid.points.at(row), L, B, h);\n    varList.setVariable(\"longitude\", Double(L)*RAD2DEG);\n    varList.setVariable(\"latitude\", Double(B)*RAD2DEG);\n    varList.setVariable(\"height\", h);\n    varList.setVariable(\"cartesianX\", grid.points.at(row).x());\n    varList.setVariable(\"cartesianY\", grid.points.at(row).y());\n    varList.setVariable(\"cartesianZ\", grid.points.at(row).z());\n    varList.setVariable(\"area\", (grid.areas.size() ? grid.areas.at(row) : 0));\n    varList.setVariable(\"index\", static_cast<Double>(row));\n    for(UInt i=0; i<grid.values.size(); i++)\n      varList.setVariable(\"data\"+i%\"%i\"s, grid.values.at(i).at(row));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid undefineDataVariables(const GriddedData &grid, VariableList &varList)\n{\n  try\n  {\n    varList.undefineVariable(\"longitude\");\n    varList.undefineVariable(\"latitude\");\n    varList.undefineVariable(\"height\");\n    varList.undefineVariable(\"cartesianX\");\n    varList.undefineVariable(\"cartesianY\");\n    varList.undefineVariable(\"cartesianZ\");\n    varList.undefineVariable(\"area\");\n    varList.undefineVariable(\"index\");\n    for(UInt i=0; i<grid.values.size(); i++)\n      varList.undefineVariable(\"data\"+i%\"%i\"s);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid addDataVariables(const GriddedDataRectangular &grid, VariableList &varList)\n{\n  try\n  {\n    std::vector<Double> dLambda, dPhi;\n    const Double totalArea = grid.areaElements(dLambda, dPhi);\n    const UInt   rows      = grid.latitudes.size();\n    const UInt   cols      = grid.longitudes.size();\n\n    varList.undefineVariable(\"longitude\");\n    varList.undefineVariable(\"latitude\");\n    varList.undefineVariable(\"height\");\n    varList.undefineVariable(\"cartesianX\");\n    varList.undefineVariable(\"cartesianY\");\n    varList.undefineVariable(\"cartesianZ\");\n    varList.undefineVariable(\"index\");\n    for(UInt idx=0; idx<grid.values.size(); idx++)\n    {\n      const std::string prefix = \"data\"+idx%\"%i\"s;\n      addDataVariables(prefix, grid.values.at(idx), varList);\n\n      Double wmean = 0;\n      Double wrms  = 0;\n      for(UInt i=0; i<rows; i++)\n        for(UInt k=0; k<cols; k++)\n        {\n          const Double w = dLambda.at(k)*dPhi.at(i)/totalArea;\n          wmean += w * grid.values.at(idx)(i,k);\n          wrms  += w * grid.values.at(idx)(i,k) * grid.values.at(idx)(i,k);\n        }\n\n      varList.setVariable(prefix+\"wmean\", wmean);\n      varList.setVariable(prefix+\"wrms\",  std::sqrt(wrms));\n      varList.setVariable(prefix+\"wstd\",  std::sqrt(rows*cols/(rows*cols-1.)*(wrms-wmean*wmean)));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid evaluateDataVariables(const GriddedDataRectangular &grid, UInt row, UInt col, VariableList &varList)\n{\n  try\n  {\n    // set values of data variables\n    const Vector3d p = grid.ellipsoid(grid.longitudes.at(col), grid.latitudes.at(row), grid.heights.at(row));\n    varList.setVariable(\"longitude\",  grid.longitudes.at(col)*RAD2DEG);\n    varList.setVariable(\"latitude\",   grid.latitudes.at(row) *RAD2DEG);\n    varList.setVariable(\"height\",     grid.heights.at(row));\n    varList.setVariable(\"cartesianX\", p.x());\n    varList.setVariable(\"cartesianY\", p.y());\n    varList.setVariable(\"cartesianZ\", p.z());\n    varList.setVariable(\"index\", static_cast<Double>(row*grid.longitudes.size()+col));\n    for(UInt idx=0; idx<grid.values.size(); idx++)\n      varList.setVariable(\"data\"+idx%\"%i\"s, grid.values.at(idx)(row,col)); // \"data(idx)\"\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid undefineDataVariables(const GriddedDataRectangular &grid, VariableList &varList)\n{\n  try\n  {\n    varList.undefineVariable(\"longitude\");\n    varList.undefineVariable(\"latitude\");\n    varList.undefineVariable(\"height\");\n    varList.undefineVariable(\"cartesianX\");\n    varList.undefineVariable(\"cartesianY\");\n    varList.undefineVariable(\"cartesianZ\");\n    varList.undefineVariable(\"index\");\n    for(UInt idx=0; idx<grid.values.size(); idx++)\n      varList.undefineVariable(\"data\"+idx%\"%i\"s); // \"data(idx)\"\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/parser/dataVariables.h",
    "content": "/***********************************************/\n/**\n* @file dataVariables.h\n*\n* @brief Create variables to evaluate a matrix/grid/timeSeries.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-06-18\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_DATAVARIABLES__\n#define __GROOPS_DATAVARIABLES__\n\n// Latex documentation\n#ifdef DOCSTRING_Parser\nstatic const char *docstringParserDataVariables = R\"(\n\\subsection{Variables for data}\\label{general.parser:dataVariables}\nSome programs (e.g. \\program{FunctionsCalculate}, \\program{InstrumentArcCalculate},\n\\program{GriddedDataCalculate}, or the plot programs)\nread data (\\file{matrix}{matrix}) or \\file{gridded data}{griddedData}\nand evaluate input/output expressions for each data row.\nFor these kind of expressions additional variables are automatically defined for each data column\n(\\verb|X| stands for the data column number: $0\\ldots n$):\n\\begin{itemize}\n\\item \\verb|index|: the row number, starting with zero\n\\item \\verb|dataX|: the value itself\n\\item \\verb|dataXcount|: number of rows\n\\item \\verb|dataXmin|\n\\item \\verb|dataXmax|\n\\item \\verb|dataXsum|\n\\item \\verb|dataXmean|\n\\item \\verb|dataXrms|: root mean square\n\\item \\verb|dataXstd|: standard deviation\n\\item \\verb|dataXmedian|\n\\item \\verb|dataXmad|: median absolute deviation\n\\item \\verb|dataXstep|: the minimal difference between two neighboring data points in the column\n\\end{itemize}\nFor \\file{gridded data}{griddedData} input the following variables are additionally defined for each data point:\n\\begin{itemize}\n\\item \\verb|longitude| in degrees\n\\item \\verb|latitude| in degrees\n\\item \\verb|height| in meters\n\\item \\verb|cartesianX| coordinate in meters\n\\item \\verb|cartesianY| coordinate in meters\n\\item \\verb|cartesianZ| coordinate in meters\n\\item \\verb|area| of the unit sphere\n\\item \\verb|dataXwmean|: area-weighted mean\n\\item \\verb|dataXwrms|: area-weighted root mean square\n\\item \\verb|dataXwstd|: area-weighted standard deviation\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/matrix.h\"\n#include \"expressionParser.h\"\n\n/** @addtogroup parserGroup */\n/// @{\n\n/***********************************************/\n\n/** @brief Create variables to loop over intervals.\n* @ingroup parserGroup\n* The following variable are created:\n* index, loopTime, loopTimeStart, loopTimeEnd. */\nvoid addTimeVariables(VariableList &varList);\n\n/** @brief Compute the values of the variables of a temporal loop.\n* @ingroup parserGroup */\nvoid evaluateTimeVariables(UInt index, const Time &timeStart, const Time &timeEnd, VariableList &varList);\n\n/***********************************************/\n\n/** @brief Create variables to evaluate a vector.\n* @ingroup parserGroup\n* The following variable are created:\n* prefix, prefixmean, prefixmedian, prefixrms, prefixstd, prefixmad, prefixmin, prefixmax, prefixstep\n* @param prefix to build parameter names.\n* @param data The vector for which the variables are created.\n* @param varList The @a VariableList to which the variables are added. */\nvoid addDataVariables(const std::string &prefix, const_MatrixSliceRef data, VariableList &varList);\n\nclass Time;\nvoid addDataVariables(const std::string &prefix, const std::vector<Time> &times, VariableList &varList);\n\nvoid addDataVariables(const std::string &prefix, const_MatrixSliceRef data, const_MatrixSliceRef weight, VariableList &varList);\n\n/** @brief Create variables to evaluate a matrix.\n* @ingroup parserGroup\n* The following variable are created if they occur in @a usedName\n* index,\n* data, data0, data1, ...\n* data0mean, data0median, data0rms, data0std, data0mad, data0min, data0max, data0step\n* data1mean, data1median, data1rms, data1std, data1mad, data1min, data1max, data1step\n* ...\n* @param data The matrix for which the variables are created.\n* @param varList The @a VariableList to which the variables are added. */\nvoid addDataVariables(const_MatrixSliceRef data, VariableList &varList);\n\n/** @brief Compute the values of the variables of a matrix.\n* @ingroup parserGroup */\nvoid evaluateDataVariables(const_MatrixSliceRef data, UInt row, VariableList &varList);\n\n/** @brief Set status to undefined of the variables of a matrix.\n* @ingroup parserGroup */\nvoid undefineDataVariables(const_MatrixSliceRef data, VariableList &varList);\n\n/***********************************************/\n\nclass GriddedData;\nclass GriddedDataRectangular;\n/** @brief Create variables to evaluate a grid.\n* @ingroup parserGroup\n* The following variable are created\n* longitude, latitude, height, area,\n* index,\n* data, data0, data1, ...\n* data0mean, data0rms, data0std, data0min, data0max,\n* data1mean, data1rms, data1std, data1min, data1max, ... */\nvoid addDataVariables(const GriddedData            &grid, VariableList &varList);\nvoid addDataVariables(const GriddedDataRectangular &grid, VariableList &varList);\n\n/** @brief Compute the values of the variables of a grid.\n* @ingroup parserGroup */\nvoid evaluateDataVariables(const GriddedData            &grid, UInt row, VariableList &varList);\nvoid evaluateDataVariables(const GriddedDataRectangular &grid, UInt row, UInt col, VariableList &varList);\n\n/** @brief Set status to undefined of the variables of a grid.\n* @ingroup parserGroup */\nvoid undefineDataVariables(const GriddedData            &grid, VariableList &varList);\nvoid undefineDataVariables(const GriddedDataRectangular &grid, VariableList &varList);\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS__ */\n\n"
  },
  {
    "path": "source/parser/expressionParser.cpp",
    "content": "/***********************************************/\n/**\n* @file expressionParser.cpp\n*\n* @brief mathemtical expression parser\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @author Andreas Kvas\n* @date 2009-05-17\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"base/time.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/expressionParser.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Mathematcial Expression\n * @ingroup parserGroup\n * Represented as a tree.\n * Can be created by the standard mathemtical operators.\n * Example:\n * @code ExpressionPtr expr = exprValue(5)+(sin(exprVar(x))^2); @endcode\n * expr->string() results in \"5+sin(x)^2\" */\nclass Expression\n{\npublic:\n  enum Priority : UInt {NONE, LOGICAL_OR, LOGICAL_AND, EQUALITY, RELATION, ADDITIVE, MULTIPLICATIVE, UNARY, EXPONENTIAL, FUNCTION, VALUE};\n\n  /// Destructor\n  virtual ~Expression() {}\n\n  Expression() = default;\n  Expression(const Expression &x) = delete;\n  Expression &operator=(const Expression &x) = delete;\n\n  /** @brief Parse an expression given as string.\n   * Example: \"3+5*sin(1.0)+x^2\".\n   * @return expression represented as a tree. */\n  static ExpressionPtr parse(const std::string &text);\n\n  /** @brief Simplifies expression.\n   * @param varList values of the variables contained in the expression.\n   * @param[out] resolved expression can be evaluated directly (is a constant value).\n   * @return Simplified expression. */\n  virtual ExpressionPtr simplify(VariableList &varList, Bool &resolved) const = 0;\n\n  /** @brief Calculate thep result of an expression.\n   * Example: \"5*x\" results in 10 if variable x=5 is given.\n   * @param varList values of the variables contained in the expression. */\n  virtual Double evaluate(const VariableList &varList) const = 0;\n\n  /** @brief Derivative of an expression.\n   * @param var derivative with respect to this variable. */\n  virtual ExpressionPtr derivative(const std::string &var) const = 0;\n\n  /** @brief Deep copy of an expression. */\n  virtual ExpressionPtr clone() const = 0;\n\n  /** @brief String representation of an expression. */\n  virtual std::string string() const = 0;\n\n  /// Internal.\n  std::string string(UInt aprio) const;\n\n  /// Internal.\n  virtual UInt priority() const = 0;\n};\n\n/***********************************************/\n\nExpressionPtr sqrt(const ExpressionPtr &ob);\nExpressionPtr exp (const ExpressionPtr &ob);\nExpressionPtr log (const ExpressionPtr &ob);\nExpressionPtr sin (const ExpressionPtr &ob);\nExpressionPtr cos (const ExpressionPtr &ob);\nExpressionPtr tan (const ExpressionPtr &ob);\nExpressionPtr asin(const ExpressionPtr &ob);\nExpressionPtr acos(const ExpressionPtr &ob);\nExpressionPtr atan(const ExpressionPtr &ob);\nExpressionPtr operator+(const ExpressionPtr &l, const ExpressionPtr &r);\nExpressionPtr operator-(const ExpressionPtr &l, const ExpressionPtr &r);\nExpressionPtr operator*(const ExpressionPtr &l, const ExpressionPtr &r);\nExpressionPtr operator/(const ExpressionPtr &l, const ExpressionPtr &r);\nExpressionPtr operator^(const ExpressionPtr &l, const ExpressionPtr &r);\nExpressionPtr operator-(const ExpressionPtr &ob);\n\n/***********************************************/\n\n// Generate named list of constants and functions with one, two or three parameters\nclass ExpressionFunction0;\nclass ExpressionFunction1;\nclass ExpressionFunction2;\nclass ExpressionFunction3;\n\nclass FunctionList\n{\npublic:\n  static std::vector<std::shared_ptr<ExpressionFunction0>> func0List;\n  static std::vector<std::shared_ptr<ExpressionFunction1>> func1List;\n  static std::vector<std::shared_ptr<ExpressionFunction2>> func2List;\n  static std::vector<std::shared_ptr<ExpressionFunction3>> func3List;\n};\n\nstd::vector<std::shared_ptr<ExpressionFunction0>> FunctionList::func0List;\nstd::vector<std::shared_ptr<ExpressionFunction1>> FunctionList::func1List;\nstd::vector<std::shared_ptr<ExpressionFunction2>> FunctionList::func2List;\nstd::vector<std::shared_ptr<ExpressionFunction3>> FunctionList::func3List;\n\n#define FUNCLIST0(_name) class FuncList##_name : public FunctionList\\\n{public: FuncList##_name() {func0List.push_back(std::make_shared<_name>());}};\\\nstatic FuncList##_name funcList##_name;\n\n#define FUNCLIST1(_name) class FuncList##_name : public FunctionList\\\n{public: FuncList##_name() {func1List.push_back(std::make_shared<_name>(ExpressionPtr()));}};\\\nstatic FuncList##_name funcList##_name;\n\n#define FUNCLIST2(_name) class FuncList##_name : public FunctionList\\\n{public: FuncList##_name() {func2List.push_back(std::make_shared<_name>(ExpressionPtr(), ExpressionPtr()));}};\\\nstatic FuncList##_name funcList##_name;\n\n#define FUNCLIST3(_name) class FuncList##_name : public FunctionList\\\n{public: FuncList##_name() {func3List.push_back(std::make_shared<_name>(ExpressionPtr(), ExpressionPtr(), ExpressionPtr()));}};\\\nstatic FuncList##_name funcList##_name;\n\n\n/***********************************************/\n\nclass ExpressionValue : public Expression\n{\n  Double value;\n\npublic:\n  explicit ExpressionValue(Double v) : value(v) {}\n  std::string   string() const override;\n  ExpressionPtr simplify(VariableList &/*varList*/, Bool &resolved) const override {resolved = TRUE; return clone();}\n  Double        evaluate(const VariableList &/*varList*/) const override {return value;}\n  ExpressionPtr derivative(const std::string &/*var*/) const override {return std::make_shared<ExpressionValue>(0);}\n  ExpressionPtr clone() const override {return std::make_shared<ExpressionValue>(value);}\n  UInt          priority() const override {return Expression::Priority::VALUE;}\n};\n\ninline ExpressionPtr exprValue(Double v) {return std::make_shared<ExpressionValue>(v);}\n\n/***********************************************/\n\nclass ExpressionVar : public Expression\n{\n  std::string name;\n\npublic:\n  explicit ExpressionVar(const std::string &_name) : name(_name) {}\n  std::string   string() const override {return name;}\n  ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  Double        evaluate(const VariableList &varList) const override;\n  ExpressionPtr derivative(const std::string &var) const override  {return exprValue((var == this->name) ? 1 : 0);}\n  ExpressionPtr clone() const override {return std::make_shared<ExpressionVar>(name);}\n  UInt          priority() const override {return Expression::Priority::VALUE;}\n};\n\ninline ExpressionPtr exprVar(const std::string &name) {return std::make_shared<ExpressionVar>(name);}\n\n/***********************************************/\n/***********************************************/\n\n// Template for constants\nclass ExpressionFunction0 : public Expression\n{\nprotected:\n  Double value;\n  ExpressionFunction0(Double v=0) : value(v) {}\n\npublic:\n  virtual ~ExpressionFunction0() {}\n  virtual std::string name() const = 0;\n  std::string   string() const override {return name()+\"()\";}\n  virtual ExpressionPtr create() const = 0;\n  ExpressionPtr simplify(VariableList &/*varList*/, Bool &resolved) const override {resolved = TRUE; return clone();}\n  Double        evaluate(const VariableList &/*varList*/) const override {return value;}\n  ExpressionPtr derivative(const std::string &/*var*/) const override {return exprValue(0);}\n  ExpressionPtr clone()  const override {return create();}\n  UInt          priority() const override {return Expression::Priority::FUNCTION;}\n};\n\n/***********************************************/\n\n// Template for functions with one argument\nclass ExpressionFunction1 : public Expression\n{\nprotected:\n  ExpressionPtr operand;\n  ExpressionFunction1(const ExpressionPtr &op) : operand(op) {}\n\npublic:\n  virtual ~ExpressionFunction1() {}\n  virtual std::string   name() const {return \"operator\";}\n  virtual std::string   string() const override {return name()+\"(\"+operand->string()+\")\";}\n  virtual ExpressionPtr create(const ExpressionPtr &ob) const = 0;\n  virtual ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  virtual ExpressionPtr derivative(const std::string &/*var*/) const override {throw(Exception(\"Derivative not defined for \\\"\"+name()+\"\\\".\"));}\n  virtual ExpressionPtr clone()  const override {return create(operand->clone());}\n  virtual UInt          priority() const override {return Expression::Priority::FUNCTION;}\n};\n\n/***********************************************/\n\n// Template for functions with two arguments\nclass ExpressionFunction2 : public Expression\n{\nprotected:\n  ExpressionPtr left, right;\n  ExpressionFunction2(const ExpressionPtr &l, const ExpressionPtr &r) : left(l), right(r) {}\n\npublic:\n  virtual ~ExpressionFunction2() {}\n  virtual std::string   name() const {return \"operator\";}\n  virtual std::string   string() const override {return name()+\"(\"+left->string()+\", \"+right->string()+\")\";}\n  virtual ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const = 0;\n  virtual ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  virtual ExpressionPtr derivative(const std::string &/*var*/) const override {throw(Exception(\"Derivative not defined for \\\"\"+name()+\"\\\".\"));}\n  virtual ExpressionPtr clone()  const override {return create(left->clone(), right->clone());}\n  virtual UInt priority() const override {return Expression::Priority::FUNCTION;}\n};\n\n/***********************************************/\n\n// Template for functions with three arguments\nclass ExpressionFunction3 : public Expression\n{\nprotected:\n  ExpressionPtr arg1, arg2, arg3;\n  ExpressionFunction3(const ExpressionPtr &a1, const ExpressionPtr &a2, const ExpressionPtr &a3) : arg1(a1), arg2(a2), arg3(a3) {}\n\npublic:\n  virtual ~ExpressionFunction3() {}\n  virtual std::string   name() const {return \"operator\";}\n  virtual std::string   string() const override {return name()+\"(\"+arg1->string()+\", \"+arg2->string()+\", \"+arg3->string()+\")\";}\n  virtual ExpressionPtr create(const ExpressionPtr &a1, const ExpressionPtr &a2, const ExpressionPtr &a3) const = 0;\n  virtual ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  virtual ExpressionPtr derivative(const std::string &/*var*/) const override {throw(Exception(\"Derivative not defined for \\\"\"+name()+\"\\\".\"));}\n  virtual ExpressionPtr clone()  const override {return create(arg1->clone(), arg2->clone(), arg3->clone());}\n  virtual UInt priority() const override {return Expression::Priority::FUNCTION;}\n};\n\n/***********************************************/\n/*** constants *********************************/\n/***********************************************/\n\nclass ExpressionPi : public ExpressionFunction0\n{\npublic:\n  ExpressionPi() : ExpressionFunction0(PI) {}\n  std::string   name()   const override {return \"pi\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionPi>();}\n};\nFUNCLIST0(ExpressionPi)\n\ninline ExpressionPtr exprPi() {return std::make_shared<ExpressionPi>();}\n\n/***********************************************/\n\nclass ExpressionRho : public ExpressionFunction0\n{\npublic:\n  ExpressionRho() : ExpressionFunction0(RAD2DEG) {}\n  std::string   name()   const override {return \"rho\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionRho>();}\n};\nFUNCLIST0(ExpressionRho)\n\ninline ExpressionPtr exprRho() {return std::make_shared<ExpressionRho>();}\n\n/***********************************************/\n\nclass ExpressionNan : public ExpressionFunction0\n{\npublic:\n  ExpressionNan() : ExpressionFunction0(NAN_EXPR) {}\n  std::string   name()   const override {return \"nan\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionNan>();}\n};\nFUNCLIST0(ExpressionNan)\n\ninline ExpressionPtr exprNan() {return std::make_shared<ExpressionNan>();}\n\n/***********************************************/\n\nclass ExpressionLightVelovity : public ExpressionFunction0\n{\npublic:\n  ExpressionLightVelovity() : ExpressionFunction0(LIGHT_VELOCITY) {}\n  std::string   name()   const override {return \"c\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionLightVelovity>();}\n};\nFUNCLIST0(ExpressionLightVelovity)\n\n/***********************************************/\n\nclass ExpressionGravitationalConstant : public ExpressionFunction0\n{\npublic:\n  ExpressionGravitationalConstant() : ExpressionFunction0(GRAVITATIONALCONSTANT) {}\n  std::string   name()   const override {return \"G\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionGravitationalConstant>();}\n};\nFUNCLIST0(ExpressionGravitationalConstant)\n\n/***********************************************/\n\nclass ExpressionGM : public ExpressionFunction0\n{\npublic:\n  ExpressionGM() : ExpressionFunction0(DEFAULT_GM) {}\n  std::string   name()   const override {return \"GM\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionGM>();}\n};\nFUNCLIST0(ExpressionGM)\n\n/***********************************************/\n\nclass ExpressionR : public ExpressionFunction0\n{\npublic:\n  ExpressionR() : ExpressionFunction0(DEFAULT_R) {}\n  std::string   name()   const override {return \"R\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionR>();}\n};\nFUNCLIST0(ExpressionR)\n\n/***********************************************/\n/*** basic arithmetic operations ***************/\n/***********************************************/\n\nclass ExpressionNegative : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionNegative(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   string() const override {return \"-\"+operand->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionNegative>(ob);}\n  Double        evaluate(const VariableList &v) const override {return -operand->evaluate(v);}\n  ExpressionPtr derivative(const std::string &var) const override {return -operand->derivative(var);}\n  UInt priority() const override {return Expression::Priority::UNARY;}\n};\n\ninline ExpressionPtr operator-(const ExpressionPtr &ob) {return std::make_shared<ExpressionNegative>(ob);}\n\n/***********************************************/\n\nclass ExpressionAdd : public ExpressionFunction2\n{\npublic:\n  ExpressionAdd(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l, r) {}\n  std::string   string() const override {return left->string(priority()) + \" + \" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionAdd>(l, r);}\n  ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  Double        evaluate(const VariableList &v) const override {return left->evaluate(v) + right->evaluate(v);}\n  ExpressionPtr derivative(const std::string &var) const override {return left->derivative(var) + right->derivative(var);}\n  UInt priority() const override {return Expression::Priority::ADDITIVE;}\n};\n\nExpressionPtr ExpressionAdd::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2;\n  ExpressionPtr l = left->simplify(varList, resolved1);\n  ExpressionPtr r = right->simplify(varList, resolved2);\n  resolved = resolved1 && resolved2;\n  if(resolved)                                  return exprValue(create(l, r)->evaluate(varList));\n  if(resolved1 && (l->evaluate(varList) == 0.)) return r;\n  if(resolved2 && (r->evaluate(varList) == 0.)) return l;\n  return create(l, r);\n}\n\ninline ExpressionPtr operator+(const ExpressionPtr &l, const ExpressionPtr &r) {return std::make_shared<ExpressionAdd>(l,r);}\n\n/***********************************************/\n\nclass ExpressionSub : public ExpressionFunction2\n{\npublic:\n  ExpressionSub(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l, r) {}\n  std::string   string() const override {return left->string(priority()) + \" - \" + right->string(priority()+1);}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionSub>(l, r);}\n  ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  Double        evaluate(const VariableList &v) const override {return left->evaluate(v) - right->evaluate(v);}\n  ExpressionPtr derivative(const std::string &var) const override {return left->derivative(var) - right->derivative(var);}\n  UInt priority() const override {return Expression::Priority::ADDITIVE;}\n};\n\nExpressionPtr ExpressionSub::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2;\n  ExpressionPtr l = left->simplify(varList, resolved1);\n  ExpressionPtr r = right->simplify(varList, resolved2);\n  resolved = resolved1 && resolved2;\n  if(resolved)                                  return exprValue(create(l, r)->evaluate(varList));\n  if(resolved1 && (l->evaluate(varList) == 0.)) return -r;\n  if(resolved2 && (r->evaluate(varList) == 0.)) return l;\n  return create(l, r);\n}\n\ninline ExpressionPtr operator-(const ExpressionPtr &l, const ExpressionPtr &r) {return std::make_shared<ExpressionSub>(l,r);}\n\n/***********************************************/\n\nclass ExpressionMult : public ExpressionFunction2\n{\npublic:\n  ExpressionMult(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l, r) {}\n  std::string   string() const override {return left->string(priority()) + \"*\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionMult>(l, r);}\n  ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  Double        evaluate(const VariableList &v) const override {return left->evaluate(v) * right->evaluate(v);}\n  ExpressionPtr derivative(const std::string &var) const override {return left->derivative(var)*right->clone() + left->clone()*right->derivative(var);}\n  UInt priority() const override {return Expression::Priority::MULTIPLICATIVE;}\n};\n\nExpressionPtr ExpressionMult::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2;\n  ExpressionPtr l = left->simplify(varList, resolved1);\n  ExpressionPtr r = right->simplify(varList, resolved2);\n  resolved = resolved1 && resolved2;\n  if(resolved)                                  return exprValue(create(l, r)->evaluate(varList));\n  if(resolved1 && (l->evaluate(varList) == 1.)) return r;\n  if(resolved1 && (l->evaluate(varList) == 0.)) {resolved = TRUE; return exprValue(0);}\n  if(resolved2 && (r->evaluate(varList) == 1.)) return l;\n  if(resolved2 && (r->evaluate(varList) == 0.)) {resolved = TRUE; return exprValue(0);}\n  return create(l, r);\n}\n\ninline ExpressionPtr operator*(const ExpressionPtr &l, const ExpressionPtr &r) {return std::make_shared<ExpressionMult>(l,r);}\n\n/***********************************************/\n\nclass ExpressionDiv : public ExpressionFunction2\n{\npublic:\n  ExpressionDiv(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l, r) {}\n  std::string   string() const override {return left->string(priority()) + \"/\" + right->string(priority()+1);}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionDiv>(l, r);}\n  ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  Double        evaluate(const VariableList &v) const override {return left->evaluate(v) / right->evaluate(v);}\n  ExpressionPtr derivative(const std::string &var) const override {return (left->derivative(var)*right->clone() - left->clone()*right->derivative(var))/(right->clone()^exprValue(2));}\n  UInt priority() const override {return Expression::Priority::MULTIPLICATIVE;}\n};\n\nExpressionPtr ExpressionDiv::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2;\n  ExpressionPtr l = left->simplify(varList, resolved1);\n  ExpressionPtr r = right->simplify(varList, resolved2);\n  resolved = resolved1 && resolved2;\n  if(resolved)                                  return exprValue(create(l, r)->evaluate(varList));\n  if(resolved1 && (l->evaluate(varList) == 0.)) {resolved = TRUE; return exprValue(0);}\n  if(resolved2 && (r->evaluate(varList) == 1.)) return l;\n  return create(l, r);\n}\n\ninline ExpressionPtr operator/(const ExpressionPtr &l, const ExpressionPtr &r) {return std::make_shared<ExpressionDiv>(l,r);}\n\n/***********************************************/\n\nclass ExpressionPow : public ExpressionFunction2\n{\npublic:\n  ExpressionPow(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l, r) {}\n  std::string   string() const override {return left->string(priority()) + \"^\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionPow>(l, r);}\n  ExpressionPtr simplify(VariableList &varList, Bool &resolved) const override;\n  Double        evaluate(const VariableList &v) const override {return pow(left->evaluate(v),right->evaluate(v));}\n  ExpressionPtr derivative(const std::string &var) const override {return left->derivative(var)*right->clone()/left->clone() * (left->clone()^(right->clone()-exprValue(1)));} // this derivative is not completly correct!!!!\n  UInt priority() const override {return Expression::Priority::EXPONENTIAL;}\n};\n\nExpressionPtr ExpressionPow::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2;\n  ExpressionPtr l = left->simplify(varList, resolved1);\n  ExpressionPtr r = right->simplify(varList, resolved2);\n  resolved = resolved1 && resolved2;\n  if(resolved)                                  return exprValue(create(l, r)->evaluate(varList));\n  if(resolved1 && (l->evaluate(varList) == 0.)) {resolved = TRUE; return exprValue(0);}\n  if(resolved2 && (r->evaluate(varList) == 1.)) return l;\n  return create(l, r);\n}\n\ninline ExpressionPtr operator^(const ExpressionPtr &l, const ExpressionPtr &r) {return std::make_shared<ExpressionPow>(l,r);}\n\n/***********************************************/\n/*** basic comparison operations ***************/\n/***********************************************/\n\nclass ExpressionLessThan : public ExpressionFunction2\n{\npublic:\n  ExpressionLessThan(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator<\";}\n  std::string   string() const override {return left->string(priority()) + \"<\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionLessThan>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return left->evaluate(varList) < right->evaluate(varList) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::RELATION;}\n};\n\n/***********************************************/\n\nclass ExpressionLessEqualThan : public ExpressionFunction2\n{\npublic:\n  ExpressionLessEqualThan(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator<=\";}\n  std::string   string() const override {return left->string(priority()) + \"<=\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionLessEqualThan>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return left->evaluate(varList) <= right->evaluate(varList) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::RELATION;}\n};\n\n/***********************************************/\n\nclass ExpressionGreaterThan : public ExpressionFunction2\n{\npublic:\n  ExpressionGreaterThan(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator>\";}\n  std::string   string() const override {return left->string(priority()) + \">\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionGreaterThan>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return left->evaluate(varList) > right->evaluate(varList) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::RELATION;}\n};\n\n/***********************************************/\n\nclass ExpressionGreaterEqualThan : public ExpressionFunction2\n{\npublic:\n  ExpressionGreaterEqualThan(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator>=\";}\n  std::string   string() const override {return left->string(priority()) + \">=\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionGreaterEqualThan>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return left->evaluate(varList) >= right->evaluate(varList) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::RELATION;}\n};\n\n/***********************************************/\n\nclass ExpressionEqual : public ExpressionFunction2\n{\npublic:\n  ExpressionEqual(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator==\";}\n  std::string   string() const override {return left->string(priority()) + \"==\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionEqual>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return left->evaluate(varList) == right->evaluate(varList) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::EQUALITY;}\n};\n\n/***********************************************/\n\nclass ExpressionNotEqual : public ExpressionFunction2\n{\npublic:\n  ExpressionNotEqual(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator!=\";}\n  std::string   string() const override {return left->string(priority()) + \"!=\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionNotEqual>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return left->evaluate(varList) != right->evaluate(varList) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::EQUALITY;}\n};\n\n/***********************************************/\n/*** logical operators *************************/\n/***********************************************/\n\nclass ExpressionLogicalNot : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionLogicalNot(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name()   const override {return \"operator!\";}\n  std::string   string() const override {return \"!\"+operand->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionLogicalNot>(ob);}\n  Double        evaluate(const VariableList &v) const override {return operand->evaluate(v) == 0.0 ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::UNARY;}\n};\n\n/***********************************************/\n\nclass ExpressionLogicalAnd : public ExpressionFunction2\n{\npublic:\n  ExpressionLogicalAnd(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator&&\";}\n  std::string   string() const override {return left->string(priority()) + \"&&\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionLogicalAnd>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return (left->evaluate(varList)!=0.0 &&  right->evaluate(varList)!=0.0) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::LOGICAL_AND;}\n};\n\n/***********************************************/\n\nclass ExpressionLogicalOr : public ExpressionFunction2\n{\npublic:\n  ExpressionLogicalOr(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name()   const override {return \"operator||\";}\n  std::string   string() const override {return left->string(priority()) + \"||\" + right->string(priority());}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionLogicalOr>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return (left->evaluate(varList)!=0.0 || right->evaluate(varList)!=0.0) ? 1.0 : 0.0;}\n  UInt priority() const override {return Expression::Priority::LOGICAL_OR;}\n};\n\n/***********************************************/\n\nclass ExpressionIfThenElse : public ExpressionFunction3\n{\npublic:\n  ExpressionIfThenElse(const ExpressionPtr &a1, const ExpressionPtr &a2, const ExpressionPtr &a3) : ExpressionFunction3(a1,a2,a3) {}\n  std::string   name() const override {return \"if\";}\n  ExpressionPtr create(const ExpressionPtr &a1, const ExpressionPtr &a2, const ExpressionPtr &a3) const override {return std::make_shared<ExpressionIfThenElse>(a1, a2, a3);}\n  Double        evaluate(const VariableList &varList) const override {return arg1->evaluate(varList) != 0.0 ? arg2->evaluate(varList) : arg3->evaluate(varList);}\n};\nFUNCLIST3(ExpressionIfThenElse)\n\n/***********************************************/\n\nclass ExpressionIsNan : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionIsNan(const ExpressionPtr &a1) : ExpressionFunction1(a1) {}\n  std::string   name() const override {return \"isnan\";}\n  ExpressionPtr create(const ExpressionPtr &a1) const override {return std::make_shared<ExpressionIsNan>(a1);}\n  Double        evaluate(const VariableList &varList) const override {return std::isnan(operand->evaluate(varList));}\n};\nFUNCLIST1(ExpressionIsNan)\n\n/***********************************************/\n/*** functions *********************************/\n/***********************************************/\n\nclass ExpressionSqrt : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionSqrt(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"sqrt\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionSqrt>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::sqrt(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)/(exprValue(2.0)*sqrt(operand->clone()));}\n};\nFUNCLIST1(ExpressionSqrt)\n\ninline ExpressionPtr sqrt(const ExpressionPtr &ob) {return std::make_shared<ExpressionSqrt>(ob);}\n\n/***********************************************/\n\nclass ExpressionExp : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionExp(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"exp\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionExp>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::exp(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)*exp(operand->clone());}\n};\nFUNCLIST1(ExpressionExp)\n\ninline ExpressionPtr exp(const ExpressionPtr &ob) {return std::make_shared<ExpressionExp>(ob);}\n\n/***********************************************/\n\nclass ExpressionLog : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionLog(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"log\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionLog>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::log(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)^exprValue(-1);}\n};\nFUNCLIST1(ExpressionLog)\n\ninline ExpressionPtr log(const ExpressionPtr &ob) {return std::make_shared<ExpressionLog>(ob);}\n\n/***********************************************/\n\nclass ExpressionSin : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionSin(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"sin\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionSin>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::sin(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)*cos(operand->clone());}\n};\nFUNCLIST1(ExpressionSin)\n\ninline ExpressionPtr sin(const ExpressionPtr &ob) {return std::make_shared<ExpressionSin>(ob);}\n\n/***********************************************/\n\nclass ExpressionCos : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionCos(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"cos\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionCos>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::cos(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return -operand->derivative(var)*sin(operand->clone());}\n};\nFUNCLIST1(ExpressionCos)\n\ninline ExpressionPtr cos(const ExpressionPtr &ob) {return std::make_shared<ExpressionCos>(ob);}\n\n/***********************************************/\n\nclass ExpressionTan : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionTan(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"tan\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionTan>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::tan(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)/(cos(operand->clone())^exprValue(2));}\n};\nFUNCLIST1(ExpressionTan)\n\ninline ExpressionPtr tan(const ExpressionPtr &ob) {return std::make_shared<ExpressionTan>(ob);}\n\n/***********************************************/\n\nclass ExpressionAsin : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionAsin(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"asin\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionAsin>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::asin(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)/sqrt(exprValue(1) - ((operand->clone())^exprValue(2)));}\n};\nFUNCLIST1(ExpressionAsin)\n\ninline ExpressionPtr asin(const ExpressionPtr &ob) {return std::make_shared<ExpressionAsin>(ob);}\n\n/***********************************************/\n\nclass ExpressionAcos : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionAcos(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"acos\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionAcos>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::acos(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return -operand->derivative(var)/sqrt(exprValue(1) - ((operand->clone())^exprValue(2)));}\n};\nFUNCLIST1(ExpressionAcos)\n\ninline ExpressionPtr acos(const ExpressionPtr &ob) {return std::make_shared<ExpressionAcos>(ob);}\n\n/***********************************************/\n\nclass ExpressionAtan : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionAtan(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"atan\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionAtan>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::atan(operand->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return operand->derivative(var)/(exprValue(1) + ((operand->clone())^exprValue(2)));}\n};\nFUNCLIST1(ExpressionAtan)\n\ninline ExpressionPtr atan(const ExpressionPtr &ob) {return std::make_shared<ExpressionAtan>(ob);}\n\n/***********************************************/\n\nclass ExpressionAbs : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionAbs(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"abs\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionAbs>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::fabs(operand->evaluate(varList));}\n};\nFUNCLIST1(ExpressionAbs)\n\n/***********************************************/\n\nclass ExpressionRound : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionRound(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"round\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionRound>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::round(operand->evaluate(varList));}\n};\nFUNCLIST1(ExpressionRound)\n\n/***********************************************/\n\nclass ExpressionCeil : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionCeil(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"ceil\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionCeil>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::ceil(operand->evaluate(varList));}\n};\nFUNCLIST1(ExpressionCeil)\n\n/***********************************************/\n\nclass ExpressionFloor : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionFloor(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"floor\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionFloor>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return std::floor(operand->evaluate(varList));}\n};\nFUNCLIST1(ExpressionFloor)\n\n/***********************************************/\n\nclass ExpressionDeg2Rad : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionDeg2Rad(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"deg2rad\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionDeg2Rad>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return DEG2RAD * operand->evaluate(varList);}\n};\nFUNCLIST1(ExpressionDeg2Rad)\n\n/***********************************************/\n\nclass ExpressionRad2Deg : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionRad2Deg(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"rad2deg\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionRad2Deg>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return RAD2DEG * operand->evaluate(varList);}\n};\nFUNCLIST1(ExpressionRad2Deg)\n\n/***********************************************/\n/***********************************************/\n\nclass ExpressionAtan2 : public ExpressionFunction2\n{\npublic:\n  ExpressionAtan2(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name() const override {return \"atan2\";}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionAtan2>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return std::atan2(left->evaluate(varList), right->evaluate(varList));}\n  ExpressionPtr derivative(const std::string &var) const override {return (left->derivative(var)*right->clone() - left->clone()*right->derivative(var))/((left->clone()^exprValue(2))+(right->clone()^exprValue(2)));}\n};\nFUNCLIST2(ExpressionAtan2)\n\n/***********************************************/\n\nclass ExpressionMin : public ExpressionFunction2\n{\npublic:\n  ExpressionMin(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name() const override {return \"min\";}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionMin>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return std::min(left->evaluate(varList), right->evaluate(varList));}\n};\nFUNCLIST2(ExpressionMin)\n\n/***********************************************/\n\nclass ExpressionMax : public ExpressionFunction2\n{\npublic:\n  ExpressionMax(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name() const override {return \"max\";}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionMax>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return std::max(left->evaluate(varList), right->evaluate(varList));}\n};\nFUNCLIST2(ExpressionMax)\n\n/***********************************************/\n\nclass ExpressionMod : public ExpressionFunction2\n{\npublic:\n  ExpressionMod(const ExpressionPtr &l, const ExpressionPtr &r) : ExpressionFunction2(l,r) {}\n  std::string   name() const override {return \"mod\";}\n  ExpressionPtr create(const ExpressionPtr &l, const ExpressionPtr &r) const override {return std::make_shared<ExpressionMod>(l, r);}\n  Double        evaluate(const VariableList &varList) const override {return std::fmod(left->evaluate(varList), right->evaluate(varList));}\n};\nFUNCLIST2(ExpressionMod)\n\n/***********************************************/\n/*** time conversions **************************/\n/***********************************************/\n\nclass ExpressionNow : public ExpressionFunction0\n{\npublic:\n  ExpressionNow()\n  {\n    std::time_t tt = std::time(nullptr);\n    std::tm     t  = *std::localtime(&tt);\n    value = date2time(t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec).mjd();\n  }\n  std::string   name()   const override {return \"now\";}\n  ExpressionPtr create() const override {return std::make_shared<ExpressionNow>();}\n};\nFUNCLIST0(ExpressionNow)\n\n/***********************************************/\n\nclass ExpressionDate2mjd : public ExpressionFunction3\n{\npublic:\n  ExpressionDate2mjd(const ExpressionPtr &a1, const ExpressionPtr &a2, const ExpressionPtr &a3) : ExpressionFunction3(a1,a2,a3) {}\n  std::string   name() const override {return \"date2mjd\";}\n  ExpressionPtr create(const ExpressionPtr &a1, const ExpressionPtr &a2, const ExpressionPtr &a3) const override {return std::make_shared<ExpressionDate2mjd>(a1, a2, a3);}\n  Double        evaluate(const VariableList &varList) const override {return date2time(static_cast<UInt>(arg1->evaluate(varList)), static_cast<UInt>(arg2->evaluate(varList)), static_cast<UInt>(arg3->evaluate(varList))).mjd();}\n};\nFUNCLIST3(ExpressionDate2mjd)\n\n/***********************************************/\n\nclass ExpressionGps2Utc : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionGps2Utc(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"gps2utc\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionGps2Utc>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return timeGPS2UTC(mjd2time(operand->evaluate(varList))).mjd();}\n};\nFUNCLIST1(ExpressionGps2Utc)\n\n/***********************************************/\n\nclass ExpressionUtc2Gps : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionUtc2Gps(const ExpressionPtr &ob) : ExpressionFunction1(ob) {}\n  std::string   name() const override {return \"utc2gps\";}\n  ExpressionPtr create(const ExpressionPtr &ob) const override {return std::make_shared<ExpressionUtc2Gps>(ob);}\n  Double        evaluate(const VariableList &varList) const override {return timeUTC2GPS(mjd2time(operand->evaluate(varList))).mjd();}\n};\nFUNCLIST1(ExpressionUtc2Gps)\n\n/***********************************************/\n\nclass ExpressionDayOfYear : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionDayOfYear(const ExpressionPtr &a1) : ExpressionFunction1(a1) {}\n  std::string   name() const override {return \"dayofyear\";}\n  ExpressionPtr create(const ExpressionPtr &a1) const override {return std::make_shared<ExpressionDayOfYear>(a1);}\n  Double        evaluate(const VariableList &varList) const override {return static_cast<Double>(mjd2time(operand->evaluate(varList)).dayOfYear());}\n};\nFUNCLIST1(ExpressionDayOfYear)\n\n/***********************************************/\n\nclass ExpressionDecimalYear : public ExpressionFunction1\n{\npublic:\n  explicit ExpressionDecimalYear(const ExpressionPtr &a1) : ExpressionFunction1(a1) {}\n  std::string   name() const override {return \"decimalyear\";}\n  ExpressionPtr create(const ExpressionPtr &a1) const override {return std::make_shared<ExpressionDecimalYear>(a1);}\n  Double        evaluate(const VariableList &varList) const override {return mjd2time(operand->evaluate(varList)).decimalYear();}\n};\nFUNCLIST1(ExpressionDecimalYear)\n\n/***********************************************/\n/***********************************************/\n/***********************************************/\n\nstd::string ExpressionValue::string() const\n{\n  std::stringstream ss;\n  ss<<value;\n  return ss.str();\n}\n\n/***********************************************/\n\nstd::string Expression::string(UInt aprio) const\n{\n  return (priority()<aprio) ? \"(\"+string()+\")\" : string();\n}\n\n/***********************************************/\n\nDouble ExpressionVar::evaluate(const VariableList &varList) const\n{\n  auto variable = varList.find(name);\n  if(!variable)\n  {\n    // Hack to read old constant definition without brackets\n    std::string name2 = name;\n    std::transform(name2.begin(), name2.end(), name2.begin(), [](auto c){return std::tolower(c);});\n    if(name2 == \"pi\")  return PI;\n    if(name2 == \"rho\") return RAD2DEG;\n    if(name2 == \"nan\") return NAN_EXPR;\n    throw(Exception(\"unknown variable: \"+name));\n  }\n  return variable->evaluate(varList);\n}\n\n/***********************************************/\n\nExpressionPtr ExpressionVar::simplify(VariableList &varList, Bool &resolved) const\n{\n  auto variable = varList.find(name);\n  if(!variable)\n  {\n    // Hack to read old constant definition without brackets\n    std::string name2 = name;\n    std::transform(name2.begin(), name2.end(), name2.begin(), [](auto c){return std::tolower(c);});\n    if(name2 == \"pi\")  return exprPi();\n    if(name2 == \"rho\") return exprRho();\n    if(name2 == \"nan\") return exprNan();\n    throw(Exception(\"unknown variable: \"+name));\n  }\n\n  try\n  {\n    resolved = TRUE;\n    return exprValue(variable->evaluate(varList));\n  }\n  catch(...)\n  {\n    resolved = FALSE;\n    return clone();\n  }\n}\n\n/***********************************************/\n\nExpressionPtr ExpressionFunction1::simplify(VariableList &varList, Bool &resolved) const\n{\n  ExpressionPtr expr = create(operand->simplify(varList, resolved));\n  if(resolved)\n    return exprValue(expr->evaluate(varList));\n  return expr;\n}\n\n/***********************************************/\n\nExpressionPtr ExpressionFunction2::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2;\n  ExpressionPtr expr = create(left->simplify(varList, resolved1), right->simplify(varList, resolved2));\n  resolved = resolved1 && resolved2;\n  if(resolved)\n    return exprValue(expr->evaluate(varList));\n  return expr;\n}\n\n/***********************************************/\n\nExpressionPtr ExpressionFunction3::simplify(VariableList &varList, Bool &resolved) const\n{\n  Bool resolved1, resolved2, resolved3;\n  ExpressionPtr expr = create(arg1->simplify(varList, resolved1), arg2->simplify(varList, resolved2), arg3->simplify(varList, resolved3));\n  resolved = (resolved1 && resolved2) && resolved3;\n  if(resolved)\n    return exprValue(expr->evaluate(varList));\n  return expr;\n}\n\n/***********************************************/\n/***********************************************/\n\nclass Tokenizer\n{\n  std::string text;\n  UInt pos, posStart;\n  Bool unused;\n\npublic:\n  enum Type   {END, SINGLE, VALUE, NAME, OPERATOR};\n  enum OperatorType   {NONE, ADD, SUB, MULT, DIV, POW, EQUAL, NOT_EQUAL, LESS, GREATER, LESS_EQUAL, GREATER_EQUAL, LOGICAL_AND, LOGICAL_OR};\n  Type        type;\n  OperatorType opType;\n  char        c;\n  Double      value;\n  std::string name;\n\n  explicit Tokenizer(const std::string &text);\n\n  void get();\n  void putBack() {unused = TRUE;}\n  std::string infoString(const std::string &info) const;\n};\n\n/***********************************************/\n\nTokenizer::Tokenizer(const std::string &txt) : text(txt), pos(0), posStart(0), unused(FALSE)\n{\n  get();\n  putBack();\n}\n\n/***********************************************/\n\nvoid Tokenizer::get()\n{\n  if(unused)\n  {\n    unused=FALSE;\n    return;\n  }\n\n  name.clear();\n  c     = ' ';\n  value = 0.0;\n  type  = Tokenizer::END;\n  opType = Tokenizer::NONE;\n\n  // eat whitespace\n  while((pos<text.size()) && isspace(text.at(pos)))\n    pos++;\n\n  if(pos>=text.size())\n  {\n    type = Tokenizer::END;\n    return;\n  }\n\n  posStart = pos;\n  c = text.at(pos);\n\n  // operator? (+,-,..)\n  if(!(isalnum(c)||(c=='_')))\n  {\n    type = Tokenizer::SINGLE;\n    if(c == '+') opType = Tokenizer::ADD;\n    if(c == '-') opType = Tokenizer::SUB;\n    if(c == '*') opType = Tokenizer::MULT;\n    if(c == '/') opType = Tokenizer::DIV;\n    if(c == '^') opType = Tokenizer::POW;\n    if(c == '>')\n    {\n      opType = Tokenizer::GREATER;\n      if(pos+1<text.size() && text.at(pos+1) == '=')\n      {\n        opType = Tokenizer::GREATER_EQUAL;\n        pos++;\n      }\n    }\n    if(c == '<')\n    {\n      opType = Tokenizer::LESS;\n      if(pos+1<text.size() && text.at(pos+1) == '=')\n      {\n        opType = Tokenizer::LESS_EQUAL;\n        pos++;\n      }\n    }\n    if((c == '=') && (pos+1<text.size() && text.at(pos+1) == '='))\n    {\n      opType = Tokenizer::EQUAL;\n      pos++;\n    }\n    if((c == '!') && (pos+1<text.size() && text.at(pos+1) == '='))\n    {\n      opType = Tokenizer::NOT_EQUAL;\n      pos++;\n    }\n    if((c == '&') && (pos+1<text.size() && text.at(pos+1) == '&'))\n    {\n      opType = Tokenizer::LOGICAL_AND;\n      pos++;\n    }\n    if((c == '|') && (pos+1<text.size() && text.at(pos+1) == '|'))\n    {\n      opType = Tokenizer::LOGICAL_OR;\n      pos++;\n    }\n    pos++;\n    return;\n  }\n\n  // number?\n  if(std::isdigit(c))\n  {\n    type  = Tokenizer::VALUE;\n    const char *ptr1 = text.c_str()+pos;\n    char *ptr2;\n    value = std::strtod(ptr1, &ptr2);\n    pos += ptr2-ptr1;\n    return;\n  }\n\n  // name\n  type  = Tokenizer::NAME;\n  while((pos<text.size()) && (isalnum(text.at(pos))||(text.at(pos)=='_')))\n    name.push_back(text.at(pos++));\n}\n\n/***********************************************/\n\nstd::string Tokenizer::infoString(const std::string &info) const\n{\n  std::stringstream ss;\n  ss<<\"'\"<<text<<\"', col=\"<<posStart<<\", \"<<info<<std::endl\n    <<std::setfill(' ')<<std::setw(posStart+2)<<std::right<<'^';\n  return ss.str();\n}\n\n/***********************************************/\n\nstatic ExpressionPtr parse(Tokenizer &token, UInt priority);\nstatic ExpressionPtr operand(Tokenizer &token);\n\n/***********************************************/\n\nExpressionPtr operand(Tokenizer &token)\n{\n  token.get();\n  if(token.type==Tokenizer::SINGLE)\n  {\n    switch(token.c)\n    {\n    case '+':\n      return  parse(token, Expression::Priority::UNARY);\n    case '-':\n      return -parse(token, Expression::Priority::UNARY);\n    case '!':\n      return std::make_shared<ExpressionLogicalNot>(parse(token, Expression::Priority::UNARY));\n    case '(':\n      ExpressionPtr expr = parse(token, 0);\n      token.get();\n      if((token.type!=Tokenizer::SINGLE)||(token.c!=')'))\n        throw(Exception(token.infoString(\"expected ')'\")));\n      return expr;\n    }\n    throw(Exception(token.infoString(\"unknown token\")));\n  }\n  else if(token.type==Tokenizer::VALUE)\n  {\n    return exprValue(token.value);\n  }\n  else if(token.type==Tokenizer::NAME)\n  {\n    const std::string name = token.name;\n    token.get();\n    if((token.type!=Tokenizer::SINGLE)||(token.c!='('))\n    {\n      token.putBack();\n      return exprVar(name); // new variable\n    }\n\n    // is function/constant without arguments?\n    for(UInt i=0; i<FunctionList::func0List.size(); i++)\n      if(name == FunctionList::func0List.at(i)->name())\n      {\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=')'))\n          throw(Exception(token.infoString(\"expected ')'\")));\n        return FunctionList::func0List.at(i)->create();\n      }\n\n    // is Function with one argument?\n    for(UInt i=0; i<FunctionList::func1List.size(); i++)\n      if(name == FunctionList::func1List.at(i)->name())\n      {\n        ExpressionPtr expr = FunctionList::func1List.at(i)->create(parse(token, 0));\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=')'))\n          throw(Exception(token.infoString(\"expected ')'\")));\n        return expr;\n      }\n\n    // is Function with two arguments?\n    for(UInt i=0; i<FunctionList::func2List.size(); i++)\n      if(name == FunctionList::func2List.at(i)->name())\n      {\n        ExpressionPtr ob1 = parse(token, 0);\n\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=','))\n          throw(Exception(token.infoString(\"expected ','\")));\n\n        ExpressionPtr ob2 = parse(token, 0);\n\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=')'))\n          throw(Exception(token.infoString(\"expected ')'\")));\n\n        return FunctionList::func2List.at(i)->create(ob1, ob2);\n      }\n\n    // is Function with three arguments?\n    for(UInt i=0; i<FunctionList::func3List.size(); i++)\n      if(name == FunctionList::func3List.at(i)->name())\n      {\n        ExpressionPtr ob1 = parse(token, 0);\n\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=','))\n          throw(Exception(token.infoString(\"expected ','\")));\n\n        ExpressionPtr ob2 = parse(token, 0);\n\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=','))\n          throw(Exception(token.infoString(\"expected ','\")));\n\n        ExpressionPtr ob3 = parse(token, 0);\n\n        token.get();\n        if((token.type!=Tokenizer::SINGLE)||(token.c!=')'))\n          throw(Exception(token.infoString(\"expected ')'\")));\n\n        return FunctionList::func3List.at(i)->create(ob1, ob2, ob3);\n      }\n\n    throw(Exception(token.infoString(\"unknown function\")));\n  }\n\n  throw(Exception(token.infoString(\"expected operand\")));\n}\n\n/***********************************************/\n\nExpressionPtr parse(Tokenizer &token, UInt priority)\n{\n  UInt priorityNew = Expression::Priority::NONE;\n  ExpressionPtr ob = operand(token);\n\n  do\n  {\n    token.get();\n    if(token.type != Tokenizer::SINGLE)\n      break;\n    switch(token.opType)\n    {\n    case Tokenizer::ADD:\n      priorityNew = Expression::Priority::ADDITIVE;\n      if(priorityNew > priority)\n        ob = ob + parse(token, priorityNew);\n      break;\n    case Tokenizer::SUB:\n      priorityNew = Expression::Priority::ADDITIVE;\n      if(priorityNew > priority)\n        ob = ob - parse(token, priorityNew);\n      break;\n    case Tokenizer::MULT:\n      priorityNew = Expression::Priority::MULTIPLICATIVE;\n      if(priorityNew > priority)\n        ob = ob * parse(token, priorityNew);\n      break;\n    case Tokenizer::DIV:\n      priorityNew = Expression::Priority::MULTIPLICATIVE;\n      if(priorityNew > priority)\n        ob = ob / parse(token, priorityNew);\n      break;\n    case Tokenizer::POW:\n      priorityNew = Expression::Priority::EXPONENTIAL;\n      if(priorityNew > priority)\n        ob = ob ^ parse(token, priorityNew);\n      break;\n    case Tokenizer::GREATER:\n      priorityNew = Expression::Priority::RELATION;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionGreaterThan>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::LESS:\n      priorityNew = Expression::Priority::RELATION;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionLessThan>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::LESS_EQUAL:\n      priorityNew = Expression::Priority::RELATION;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionLessEqualThan>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::GREATER_EQUAL:\n      priorityNew = Expression::Priority::RELATION;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionGreaterEqualThan>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::EQUAL:\n      priorityNew = Expression::Priority::EQUALITY;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionEqual>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::NOT_EQUAL:\n      priorityNew = Expression::Priority::EQUALITY;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionNotEqual>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::LOGICAL_AND:\n      priorityNew = Expression::Priority::LOGICAL_AND;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionLogicalAnd>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::LOGICAL_OR:\n      priorityNew = Expression::Priority::LOGICAL_OR;\n      if(priorityNew > priority)\n        ob = std::make_shared<ExpressionLogicalOr>(ob, parse(token, priorityNew));\n      break;\n    case Tokenizer::NONE:\n      priorityNew = Expression::Priority::NONE;\n      break;\n    }\n  }\n  while(priority<priorityNew);\n\n  token.putBack();\n  if(!ob)\n    throw(Exception(token.infoString(\"unknown error\")));\n  return ob;\n}\n\n/***********************************************/\n\nExpressionPtr Expression::parse(const std::string &text)\n{\n  try\n  {\n    Tokenizer token(text);\n    ExpressionPtr expr = ::parse(token, 0);\n    if(token.type!=Tokenizer::END)\n      throw(Exception(token.infoString(\"unknown token\")));\n    return expr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nDouble ExpressionVariable::parse(const std::string &text, const VariableList &varList)\n{\n  try\n  {\n    return Expression::parse(text)->evaluate(varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nExpressionVariable::ExpressionVariable(const std::string &name)\n  : _name(name), status(UNDEFINED), isSimplified(FALSE) {}\n\nExpressionVariable::ExpressionVariable(const std::string &name, Double _value)\n  : _name(name), status(VALUE), value(_value), isSimplified(FALSE) {}\n\nExpressionVariable::ExpressionVariable(const std::string &name, const std::string &_text)\n  : _name(name), status(TEXT), text(_text), isSimplified(FALSE) {}\n\nExpressionVariable::ExpressionVariable(const std::string &name, const std::string &_text, const VariableList &_varList)\n  : _name(name), status(TEXT), text(_text), varList(_varList), isSimplified(FALSE) {}\n\nExpressionVariable::ExpressionVariable(const std::string &name, ExpressionPtr _expr, const VariableList &_varList)\n  : _name(name), status(EXPRESSION), expr(_expr), varList(_varList), isSimplified(FALSE)\n{if(!expr) throw(Exception(\"ExpressionVariable: Null-Pointer.\"));}\n\nExpressionVariable::ExpressionVariable(const std::string &name, const std::shared_ptr<Func> &func)\n  : _name(name), status(FUNC), func(func), isSimplified(FALSE) {}\n\nExpressionVariable::ExpressionVariable(const ExpressionVariable &x)\n  : _name(x._name), status(x.status), text(x.text), value(x.value), varList(x.varList), func(x.func), isSimplified(x.isSimplified)\n{if(x.expr) expr = x.expr->clone();}\n\n/***********************************************/\n\nstd::string ExpressionVariable::getText() const\n{\n  try\n  {\n    if(status == VALUE)\n    {\n      std::stringstream ss;\n      ss<<value;\n      return ss.str();\n    }\n\n    if(status == EXPRESSION)\n      return expr->string();\n\n    if(status == FUNC)\n      return \"{func()}\";\n\n    if(status == UNDEFINED)\n      return \"{_undefined_}\";\n\n    // status == TEXT\n    return text;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Expression(\"+name()+\"')\", e)\n  }\n}\n\n/***********************************************/\n\nvoid ExpressionVariable::parseVariableName()\n{\n  try\n  {\n    if(status != TEXT)\n      throw(Exception(\"must contain a variable name ('name [= expr]')\"));\n\n    Bool resolved = TRUE;\n    auto text_ = StringParser::parse(name(), this->text, varList, resolved);\n\n    // parse variable name\n    auto pos     = text_.find('=');\n    auto nameStr = text_.substr(0, pos);\n    if(!resolved)\n    {\n      resolved = TRUE;\n      nameStr = StringParser::parse(name(), nameStr, varList, resolved);\n    }\n    if(!resolved)\n      throw(Exception(\"must contain a variable name ('name [= expr]')\"));\n    Tokenizer token(nameStr);\n    token.get();\n    if(token.type!=Tokenizer::NAME)\n      throw(Exception(\"must contain a variable name ('name [= expr]')\"));\n    _name = token.name; // set new name\n    token.get();\n    if(token.type != Tokenizer::END)\n      throw(Exception(token.infoString(\"unknown token\")));\n\n    if(pos == std::string::npos) // only variable name\n    {\n      status = VALUE;\n      value  = 0.;\n      return;\n    }\n\n    // expression after '='\n    this->text = text_.substr(pos+1, std::string::npos);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Expression(\"+name()+\" = '\"+getText()+\"')\", e)\n  }\n}\n\n/***********************************************/\n\nvoid ExpressionVariable::simplify(VariableList &varList)\n{\n  try\n  {\n    if(isSimplified)\n      return;\n    isSimplified = TRUE;\n\n    VariableList varList2 = this->varList;\n    varList2 += varList;\n\n    if(status == TEXT)\n    {\n      Bool resolved = TRUE;\n      std::string text_ = StringParser::parse(name(), this->text, varList2, resolved);\n      if(!resolved)\n        return;\n      expr   = Expression::parse(text_);\n      status = EXPRESSION;\n    }\n\n    if(status == EXPRESSION)\n    {\n      Bool resolved;\n      expr = expr->simplify(varList2, resolved);\n      if(resolved)\n      {\n        value  = expr->evaluate(varList2);\n        status = VALUE;\n        this->varList.map.clear();\n        expr = nullptr;\n        return;\n      }\n\n      // store only used variables\n      this->varList.map.clear();\n      for(auto &var : varList2.map)\n        if(!varList.find(var.first) && var.second->isSimplified)\n          this->varList.map[var.first] = var.second;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Expression(\"+name()+\" = '\"+getText()+\"')\", e)\n  }\n}\n\n/***********************************************/\n\nExpressionVariablePtr ExpressionVariable::derivative(const std::string &varName, const VariableList &varList) const\n{\n  try\n  {\n    if(status == CIRCULAR)\n      throw(Exception(\"circular expression\"));\n    if(status == UNDEFINED)\n      throw(Exception(\"undefined variable\"));\n    if((status == VALUE) || (status == FUNC))\n      return std::make_shared<ExpressionVariable>(name(), 0.0);\n    if(status == EXPRESSION)\n      return std::make_shared<ExpressionVariable>(name(), expr->derivative(varName), this->varList);\n    // status == TEXT\n    VariableList varList2 = this->varList;\n    varList2 += varList;\n    Bool resolved = TRUE;\n    std::string text_ = StringParser::parse(name(), this->text, varList2, resolved);\n    if(!resolved)\n      throw(Exception(\"unresolved variables\"));\n    return std::make_shared<ExpressionVariable>(name(), Expression::parse(text_)->derivative(varName), this->varList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Expression(\"+name()+\" = '\"+getText()+\"')\", e)\n  }\n}\n\n/***********************************************/\n\nDouble ExpressionVariable::evaluate(const VariableList &varList) const\n{\n  try\n  {\n    if(status == VALUE)\n      return value;\n\n    if(status == FUNC)\n    {\n      if(!func)\n        throw(Exception(\"nullptr function\"));\n      status = VALUE;\n      value  = (*func)();\n      func   = nullptr;\n      return value;\n    }\n\n    if(status == EXPRESSION)\n    {\n      if(this->varList.map.empty())\n        return expr->evaluate(varList);\n      VariableList varList2 = this->varList;\n      varList2 += varList;\n      return expr->evaluate(varList2);\n    }\n\n    if(status == TEXT)\n    {\n      VariableList varList2 = this->varList;\n      varList2 += varList;\n      Bool resolved = TRUE;\n      std::string text_ = StringParser::parse(name(), this->text, varList2, resolved);\n      if(!resolved)\n        throw(Exception(\"unresolved variables\"));\n\n      const Status stat = status;\n      status = CIRCULAR;  // prevent endless searching\n      Double d = Expression::parse(text_)->evaluate(varList2);\n      status = stat;\n      return d;\n    }\n\n    if(status == CIRCULAR)\n      throw(Exception(\"circular expression\"));\n\n    //if(status == UNDEFINED)\n    throw(Exception(\"undefined variable\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Expression(\"+name()+\" = '\"+getText()+\"')\", e)\n  }\n}\n\n/***********************************************/\n\nstd::string ExpressionVariable::getParsedText(const VariableList &varList, Bool &resolved) const\n{\n  try\n  {\n    if(status == TEXT)\n    {\n      status = CIRCULAR; // prevent endless searching\n      VariableList varList2 = this->varList;\n      varList2 += varList;\n      auto result = StringParser::parse(name(), text, varList2, resolved);\n      status = TEXT;\n      return result;\n    }\n\n    if(status == UNDEFINED)\n      return name();\n\n    if(status == FUNC)\n    {\n      if(!func)\n        throw(Exception(\"nullptr function\"));\n      status = VALUE;\n      value  = (*func)();\n      func   = nullptr;\n    }\n\n    if(status == VALUE)\n    {\n      std::stringstream ss;\n      ss<<std::setprecision(std::numeric_limits<decltype(value)>::digits10)<<value;\n      return ss.str();\n    }\n\n    if(status == EXPRESSION)\n      return expr->string();\n\n    //if(status == CIRCULAR)\n    throw(Exception(\"is circular defined\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW_EXTRA(\"Expression(\"+name()+\" = '\"+getText()+\"')\", e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nVariableList &VariableList::operator+=(const VariableList &x)\n{\n  for(const auto &var : x.map)\n    map[var.second->name()] = var.second;\n  return *this;\n}\n\n/***********************************************/\n\nstd::shared_ptr<const ExpressionVariable> VariableList::find(const std::string &name) const\n{\n  try\n  {\n    auto iter = map.find(name);\n    if(iter != map.end())\n      return iter->second;\n    return ExpressionVariablePtr(nullptr);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariableList::addVariable(ExpressionVariablePtr var)\n{\n  try\n  {\n    map[var->name()] = std::make_shared<ExpressionVariable>(*var);  // copy\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nExpressionVariablePtr VariableList::getVariable(const std::string &name)\n{\n  try\n  {\n    auto iter = map.find(name);\n    if(iter != map.end())\n    {\n      if(iter->second.use_count() > 1) // not threat save\n        iter->second = std::make_shared<ExpressionVariable>(*(iter->second)); // copy\n      return iter->second;\n    }\n    // new variable\n    ExpressionVariablePtr var = std::make_shared<ExpressionVariable>(name);\n    map[name] = var;\n    return var;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid VariableList::setVariable(const std::string &name, Double value)            {getVariable(name)->setValue(value);}\nvoid VariableList::setVariable(const std::string &name, const std::string &text) {getVariable(name)->setValue(text);}\nvoid VariableList::undefineVariable(const std::string &name)                     {getVariable(name)->setUndefined();}\n\n/***********************************************/\n"
  },
  {
    "path": "source/parser/expressionParser.h",
    "content": "/***********************************************/\n/**\n* @file expressionParser.h\n*\n* @brief Mathemtical expression parser\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @author Andreas Kvas\n* @date 2009-05-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_EXPRESSIONPARSER__\n#define __GROOPS_EXPRESSIONPARSER__\n\n// Latex documentation\n#ifdef DOCSTRING_Parser\nstatic const char *docstringParserExpression = R\"(\n\\subsection{Mathematical expression parser}\\label{general.parser:expression}\nIn all input fields that accept numbers (int, uint, double, angle, time) numerical\nexpressions are also allowed. Declared variables can be accessed via their name. The following\noperations and functions are defined:\n\\begin{itemize}\n\\item Constants:    \\verb|pi()|, \\verb|rho()=180/pi()|, \\verb|nan()|, \\verb|c()|: light velocity,\n                    \\verb|G()|: gravitational constant, \\verb|GM()|: gravitational constant of the Earth, \\verb|R()|: reference radius of the Earth\n\\item Mathematical: \\verb|+|, \\verb|-|, \\verb|*|, \\verb|/|, \\verb|^|\n\\item Comparison:   \\verb|==|, \\verb|!=|, \\verb|<|, \\verb|<=|, \\verb|>|, \\verb|>=|, result is 1 or 0\n\\item Logical:      not \\verb|!|, and \\verb|&&|, \\verb'||', or \\verb|isnan(x)|, result is 1 or 0\n\\item Functions:    \\verb|sqrt(x)|, \\verb|exp(x)|,\n                    \\verb|sin(x)|,  \\verb|cos(x)|, \\verb|tan(x)|,\n                    \\verb|asin(x)|,  \\verb|acos(x)|,  \\verb|atan(x)|,\n                    \\verb|abs(x)|,  \\verb|round(x)|,  \\verb|ceil(x)|,  \\verb|floor(x)|,\n                    \\verb|deg2rad(x)|, \\verb|rad2deg(x)|\n\\item Functions with 2 arguments: \\verb|atan2(y,x)|, \\verb|min(x,y)|, \\verb|max(x,y)|, \\verb|mod(x,y)|\n\\item Time functions: \\verb|now()|: local time in MJD, \\verb|date2mjd(year, month, day)|, \\verb|gps2utc(mjd)|, \\verb|utc2gps(mjd)|, \\verb|dayofyear(mjd)|, \\verb|decimalyear(mjd)|\n\\item Condition: \\verb|if(c,x,y)|: If the first argument is true (not 0), the second argument is evaluated, otherwise the third.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include <map>\n#include \"base/importStd.h\"\n\n/***** TYPES ***********************************/\n\nclass Expression;\nclass ExpressionVariable;\ntypedef std::shared_ptr<Expression> ExpressionPtr;\ntypedef std::shared_ptr<ExpressionVariable> ExpressionVariablePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief List of variables for expressions\n* With smart memmory management. The variables are only copied if needed (copy on write, late copy).\n* This is not threat save.\n* @ingroup parserGroup\n* @see ExpressionVariable */\nclass VariableList\n{\n  mutable std::map<std::string, ExpressionVariablePtr> map;\n\n  ExpressionVariablePtr getVariable(const std::string &name);\n\npublic:\n  VariableList() {}                                         //!< Constructor.\n  VariableList(const VariableList &) = default;             //!< Copy constructor.\n ~VariableList() {}                                         //!< Destructor\n  VariableList &operator=(const VariableList &) = default;  //!< Assignment.\n\n  /// Concatenate.\n  VariableList &operator+=(const VariableList &x);\n\n  void addVariable(ExpressionVariablePtr var);\n\n  /** @brief Set @a value of a variable with @a name. The variable is created when needed.*/\n  void setVariable(const std::string &name, Double value);\n\n  /** @brief Set @a text of a variable with @a name. The variable is created when needed.*/\n  void setVariable(const std::string &name, const std::string &text);\n\n  /** @brief Set status of a variable with @a name undefined. The variable is created when needed.*/\n  void undefineVariable(const std::string &name);\n\n  /** @brief Remove the variable with @a name.*/\n  void eraseVariable(const std::string &name) {map.erase(name);}\n\n  /** @brief Find variable with @a name.*/\n  std::shared_ptr<const ExpressionVariable> find(const std::string &name) const;\n\n  friend class ExpressionVariable;\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Variable for expressions\n* @ingroup parserGroup\n* Set a value to variable @a name to evaluate expressions.\n* @see Expression */\nclass ExpressionVariable\n{\npublic:\n  class Func\n  {\n  public:\n    virtual ~Func() {}\n    virtual Double operator()() const = 0;\n  };\n\nprivate:\n  enum Status {UNDEFINED, TEXT, EXPRESSION, VALUE, FUNC, CIRCULAR};\n\n  std::string    _name;\n  mutable Status status;\n  std::string    text;\n  mutable Double value;\n  ExpressionPtr  expr;\n  VariableList   varList;\n  mutable std::shared_ptr<Func> func;\n  Bool           isSimplified;\n\n  /** @brief The unparsed content of the variable. */\n  std::string getText() const;\n\npublic:\n  /** @brief Constructor: variable with undefined value. */\n  ExpressionVariable(const std::string &name);\n\n  /** @brief Constructor: variable with value. */\n  ExpressionVariable(const std::string &name, Double value);\n\n  /** @brief Constructor: variable with parseable expression text. */\n  ExpressionVariable(const std::string &name, const std::string &text);\n\n  /** @brief Constructor: variable with parseable expression text. */\n  ExpressionVariable(const std::string &name, const std::string &text, const VariableList &varList);\n\n  /** @brief Constructor: variable with expression. */\n  ExpressionVariable(const std::string &name, ExpressionPtr expr, const VariableList &varList);\n\n  /** @brief Constructor: variable value computed with @a func.\n  * The @a func is evaluated only if needed and only once. For computational expensive calculations. */\n  ExpressionVariable(const std::string &name, const std::shared_ptr<Func> &func);\n\n  /// Copy constructor.\n  ExpressionVariable(const ExpressionVariable &x);\n\n  ExpressionVariable &operator=(const ExpressionVariable &) = delete;\n\n  /** @brief Parse an expression given as string.\n   * Example: \"3+5*sin(1.0)+x^2\". */\n  static Double parse(const std::string &text, const VariableList &varList);\n\n  /** @brief Name of the variable. */\n  const std::string &name() const {return _name;}\n\n  /** @brief set value of this variable. */\n  void setValue(Double value_) {status = VALUE; value = value_;}\n\n  /** @brief set parseable expression text. */\n  void setValue(const std::string &text_) {status = TEXT; text = text_;}\n\n  /** @brief set status of this variable undefined. */\n  void setUndefined() {status = UNDEFINED;}\n\n  /** @brief Set the name of the variable from the expression text.\n  * The text of the variable must be given in the form 'name [= expr]'.\n  * The variable @a name is set to 'name' and removed from the text.\n  * The 'expr' is not evaluated. If 'expr' is not given the value is set to zero.\n  * The @a StringParser with the @a varList is called before. */\n  void parseVariableName();\n\n  /** @brief Evaluate as much as possible.\n  * The @a StringParser with the @a varList is called before and\n  * if not all variables {names} can be resolved an exception is thrown.\n  * Should be called before evaluation of the expression for long data lists\n  * to accelerate the computation. Variables which changes the value after\n  * this call (e.g. data0) must be undefined in the @a varList. */\n  void simplify(VariableList &varList);\n\n  /** @brief Derivative of an expression.\n  * The @a StringParser with the @a varList is called before and\n  * if not all variables {names} can be resolved an exception is thrown. */\n  ExpressionVariablePtr derivative(const std::string &varName, const VariableList &varList) const;\n\n  /** @brief Calculate thep result of an expression.\n  * Example: \"5*x\" results in 10 if variable x=5 is given.\n  * The @a StringParser with the @a varList is called before and\n  * if not all variables {names} can be resolved an exception is thrown.\n  * @param varList values of the variables contained in the expression. */\n  Double evaluate(const VariableList &varList) const;\n\n  /** @brief Returns the result of the @a StringParser.\n  * @a resolved is set to FALSE if not all variables defined. Untouched by success. */\n  std::string getParsedText(const VariableList &varList, Bool &resolved) const;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/parser/stringParser.cpp",
    "content": "/***********************************************/\n/**\n* @file stringParser.cpp\n*\n* @brief string manipulation parser\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2016-03-26\n*\n*/\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"base/constants.h\"\n#include \"stringParser.h\"\n#include \"expressionParser.h\"\n#include <regex>\n\n/***********************************************/\n\nstatic std::string parseUntil(const std::string &text, const char *search, const VariableList &varList, std::string::size_type &pos, Bool &resolved);\nstatic std::string parseVariable(const std::string &text, const VariableList &varList, std::string::size_type &pos, Bool &resolved);\n\n/***********************************************/\n\nstd::string parseUntil(const std::string &text, const char *search, const VariableList &varList, std::string::size_type &pos, Bool &resolved)\n{\n  std::string textPart;\n  for(;;)\n  {\n    std::string::size_type posOld = pos;\n    pos = text.find_first_of(search, pos);\n    textPart += text.substr(posOld, pos-posOld);\n    if((pos != std::string::npos) && (pos > 0) && (text.at(pos-1) == '#')) // escape '#' before?\n      textPart.back() = text.at(pos++);                                    // replace '#' by excapted character\n    else if((pos != std::string::npos) && (text.at(pos) == '{'))\n      textPart += parseVariable(text, varList, ++pos, resolved);\n    else\n      break;\n  }\n  return textPart;\n}\n\n/***********************************************/\n\n// parse after '{'\nstatic std::string parseVariable(const std::string &text, const VariableList &varList, std::string::size_type &pos, Bool &resolved)\n{\n  Bool resolvedVar = TRUE;\n  std::string textPart = parseUntil(text, \"{:/}\", varList, pos, resolvedVar);\n  if(pos == std::string::npos)\n    throw(Exception(\"missing closing '}'\"));\n  auto c = text.at(pos++);\n\n  // textPart is variable\n  // --------------------\n  if(c == '}')\n  {\n    auto variable = varList.find(textPart);\n    if(variable && resolvedVar)\n      return variable->getParsedText(varList, resolved);\n    resolved = FALSE;\n    return '{'+textPart+'}';\n  }\n\n  // textPart is {expression:format}\n  // -------------------------------\n  if(c == ':')\n  {\n    // format string\n    std::string format = parseUntil(text, \"{}\", varList, pos, resolvedVar);\n    if(pos++ == std::string::npos)\n      throw(Exception(\"missing closing '}' of {expression:format}\"));\n    if(resolvedVar)\n    {\n      try {return ExpressionVariable::parse(textPart, varList) % format;} // parse expression -> caluclate new result string\n      catch(std::exception &/*e*/) {}\n    }\n    resolved = FALSE;\n    return \"{\"+textPart+\":\"+format+\"}\";\n  }\n\n  // regex expression {text/regex/replace}\n  // -------------------------------------\n  if(c == '/')\n  {\n    std::string regexText = parseUntil(text, \"{/\", varList, pos, resolvedVar);\n    if(pos++ == std::string::npos)\n      throw(Exception(\"missing second '/' of {text/regex/replace}\"));\n    std::string replace = parseUntil(text, \"{}\", varList, pos, resolvedVar);\n    if(pos++ == std::string::npos)\n      throw(Exception(\"missing closing '}' of {text/regex/replace}\"));\n    if(!resolvedVar)\n    {\n      resolved = FALSE;\n      return '{'+textPart+'/'+regexText+'/'+replace+'}';\n    }\n\n    // Escape sequences\n    // \\l lowercase next char\n    // \\u uppercase next char\n    // \\L lowercase until \\E\n    // \\U uppercase until \\E\n    // \\Q quote (disable) pattern metacharacters until \\E\n    // \\E end either case modification or quoted section\n    std::regex regex(regexText);\n    std::string result;\n    std::string::size_type posReplace = 0;\n    Char c = 'E'; // end: normal mode\n    for(;;)\n    {\n      std::string::size_type posOld = posReplace;\n      posReplace = replace.find('\\\\', posOld);\n\n      if(c != 'Q')\n      {\n        std::string resultPart = std::regex_replace(textPart, regex, replace.substr(posOld, posReplace-posOld));\n        if(c == 'L') std::for_each(resultPart.begin(), resultPart.end(), [](auto &c){c=std::tolower(c);});\n        if(c == 'U') std::for_each(resultPart.begin(), resultPart.end(), [](auto &c){c=std::toupper(c);});\n        if(c == 'l' && !resultPart.empty()) resultPart.front() = std::tolower(resultPart.front());\n        if(c == 'u' && !resultPart.empty()) resultPart.front() = std::toupper(resultPart.front());\n        result += resultPart;\n      }\n      else\n        result += replace.substr(posOld, posReplace-posOld);\n\n      if(posReplace++ == std::string::npos) return result;      // end of string\n      auto cNew = (posReplace < replace.size()) ? replace.at(posReplace) : ' ';\n      if(((c != 'Q') && ((cNew == 'L') || (cNew == 'U') || (cNew == 'l') || (cNew == 'u') || (cNew == 'Q'))) || // not in quote mode  -> accept Q,L,U,l,u\n         ((c != 'E') && (cNew == 'E')))                                                                         // not in normal mode -> accept additionally E\n        c = replace.at(posReplace++);\n      else\n        result += \"\\\\\";\n    }\n\n   return result;\n  }\n\n  throw(Exception(\"unknown error\"));\n}\n\n/***********************************************/\n\nstd::string StringParser::parse(const std::string &name, const std::string &text, const VariableList &varList, Bool &resolved)\n{\n  std::string result;\n  std::string::size_type pos = 0;\n  try\n  {\n    return parseUntil(text, \"{\", varList, pos, resolved);\n  }\n  catch(std::exception &e)\n  {\n    throw(Exception(\"Parser error in (\"+name+\"='\"+text+\"'), column=\"+(pos%\"%i\"s)+\":\\n\"+e.what()));\n  }\n}\n\n/***********************************************/\n\nstd::string StringParser::parse(const std::string &text, const VariableList &varList)\n{\n  try\n  {\n    Bool resolved = TRUE;\n    std::string result = parse(\"(unknown)\", text, varList, resolved);\n    if(!resolved)\n      throw(Exception(\"unresolved variables\"));\n    return result;\n  }\n  catch(std::exception &e)\n  {\n    throw(Exception(\"Parser error in '\"+text+\"'\\n\"+e.what()));\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/parser/stringParser.h",
    "content": "/***********************************************/\n/**\n* @file stringParser.h\n*\n* @brief string manipulation parser\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2016-03-26\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_STRINGPARSER__\n#define __GROOPS_STRINGPARSER__\n\n// Latex documentation\n#ifdef DOCSTRING_Parser\nstatic const char *docstringParserText = R\"(\n\\subsection{Text parser}\\label{general.parser:text}\nBefore the mathematical expression parser evaluates the expression, a simple text parser is applied.\nThe text parser is used for all input fields (also file names). It scans the text for terms like\n\\verb|{variable}| and replaces it by the text content of the \\verb|variable|.\nA literal '\\verb|{|' character must be escaped with '\\verb|#{|'.\n\nThe text parser allows regex replacements in the form \\verb|{text/regex/replace}|.\nAll matches of \\verb|regex| in the \\verb|text| are replaced by \\verb|replace|.\nPossible \\verb|{variables}| in the three parts are evaluated beforehand.\nCapturing groups \\verb|()| can be accessed by \\verb|$1|, \\verb|$2|,\n\\ldots in the replacement (\\verb|$0| is the complete match). Additional escape sequences are:\n\\begin{itemize}\n\\item \\verb|\\l| lowercase next char,\n\\item \\verb|\\u| uppercase next char,\n\\item \\verb|\\L| lowercase until \\verb|\\E|,\n\\item \\verb|\\U| uppercase until \\verb|\\E|,\n\\item \\verb|\\Q| quote (disable) pattern metacharacters until \\verb|\\E|,\n\\item \\verb|\\E| end either case modification or quoted section.\n\\end{itemize}\n\nExamples:\n\\begin{itemize}\n\\item \\verb|{{variable}/test/text}| replaces all occurrences of \\verb|test| by \\verb|text|.\n\\item \\verb|{TEXT/.+/\\L$0}| converts text to lower case.\n\\item \\verb|{012345/.#{2}(.#{3}).*/$1}| extracts the substring at index 2 and length 3 resulting in \\verb|234|.\n      Note the escaping \\verb|#{|.\n\\end{itemize}\n\nThe text parser also evaluates terms in the form \\verb|{expression:format}| and replaces it by a formatted\noutput. In order not to get confused with the regex replacements, the '\\verb|/|' character must be escaped\nwith '\\verb|#/|' in the expression. The \\verb|format| contains the text to be written as output.\nIt can contain embedded format specifiers that are replaced by the value of the expression and formatted\nas requested (also multiple times). In the following, the resulting formatted output is given in the\nbrackets for an expression with the example value of 57493.8:\n\\begin{itemize}\n\\item \\verb|%i|: Integer [57494]\n\\item \\verb|%f|: Decimal floating point [57493.800000]\n\\item \\verb|%e|: Scientific notation [5.749380e+04]\n\\item \\verb|%g|: Use the shortest representation: \\verb|%e| or \\verb|%f| [57493.8]\n\\item \\verb|%c|: Interpret number as ASCII character\n\\item \\verb|%%|: Write a single literal \\verb|%| character\n\\end{itemize}\nThe following specifiers interpret the value of the expression as MJD (modified Julian date):\n\\begin{itemize}\n\\item \\verb|%y|: Four digit year [2016]\n\\item \\verb|%Y|: Two digit year [16]\n\\item \\verb|%m|: Month [04]\n\\item \\verb|%d|: Day of month [15]\n\\item \\verb|%H|: Hour [19]\n\\item \\verb|%M|: Minute [12]\n\\item \\verb|%S|: Second [00]\n\\item \\verb|%D|: Date (same as \\verb|%y-%m-%d|) [2016-04-15]\n\\item \\verb|%T|: Time (same as \\verb|%H-%M-%S|) [19-12-00]\n\\item \\verb|%W|: GPS week [1892]\n\\item \\verb|%w|: Day of GPS week (0..6) [5]\n\\item \\verb|%O|: Day of year (1..366)\n\\end{itemize}\nThe format can be specified further with \\verb|%[width][.precision]specifier|,\nwhere \\verb|[width]| is the minimum number of characters to be printed.\nIf the value to be printed is shorter than this number, the result is padded with blank spaces\n(or zeros if \\verb|[width]| starts with a zero).\nThe \\verb|[.precision]| defines the number of digits after the period (for \\verb|%g| the number of\nsignificant digits instead).\n\nExample:\nTwo variables \\config{time}=\\verb|57493+19/24+12/1440| and \\config{satellite}=\\verb|swarm| are\nset in the global section. The \\config{inputfile}=\\verb|data/{time:%y}/{satellite}_{time:%D}.dat|\nis expanded to \\verb|\"data/2016/swarm_2016-04-15.dat\"|.\n\nExample:\nThe variable \\config{x}=\\verb|3+5| is set in the global section.\nThe expression \\config{number}=\\verb|2*x| is evaluated by the expression parser to \\verb|=16|.\nIn contrast if we use brackets like in \\config{number}=\\verb|2*{x}| the expression is first evaluated\nby the text parser to \\verb|\"2*3+5\"| and the expression parser now gives the result \\verb|=11|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/importStd.h\"\n#include \"expressionParser.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief string manipulation.\n* @ingroup parserGroup */\nnamespace StringParser\n{\n  /** @brief string manipulation.\n  * @a resolved is set to FALSE if not all variables defined. Untouched by success.\n  * {variable} is replaced by the content of the variable list.\n  * {expression:format} is replaced by the format string. Before the expression is evaluated and\n  * the result is inserted and formatted at every format identifier:\n  * - %%: the single % character.\n  * - %c: character.\n  * - %i: integer.\n  * - %f, %e, %g: float.\n  * - %y, %m, %d: year, month, day.\n  * - %H, %M, %S: hour, minute, second.\n  * - %Y: two digit year.\n  * - %D: Date: yyyy-mm-dd.\n  * - %T: Time: hh-mm-ss.\n  * - %O: day of year.\n  * - %W, %w: GPS week, day of week.\n  *\n  * Example {51544.5:%D_T%T} -> '2000-01-01_T12-00-00'. */\n  std::string parse(const std::string &name, const std::string &text, const VariableList &varList, Bool &resolved);\n\n  /** @brief string manipulation.\n  * Convenience function.\n  * An expception is thrown if the string cannot resolved completly. */\n  std::string parse(const std::string &text, const VariableList &varList);\n}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/parser/xml.cpp",
    "content": "/***********************************************/\n/**\n* @file xml.cpp\n*\n* @brief Nodes of a XML tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2004-11-14\n*\n*/\n/***********************************************/\n\n#include <expat.h>\n#include \"base/importStd.h\"\n#include \"base/string.h\"\n#include \"base/angle.h\"\n#include \"base/time.h\"\n#include \"xml.h\"\n\n/***********************************************/\n\nXmlNodePtr XmlNode::clone() const\n{\n  XmlNodePtr ptr = create(name_);\n  ptr->text_ = text_;\n  for(auto attr : attribute)\n    ptr->addAttribute(std::make_shared<XmlAttribute>(*attr));\n  for(auto child : children)\n    ptr->addChild(child->clone());\n  return ptr;\n\n}\n\n/***********************************************/\n\nUInt XmlNode::getChildCount(const std::string &name)\n{\n  return std::count_if(children.begin(), children.end(), [&name](auto child) {return child->getName() == name;});\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::getChild(const std::string &name)\n{\n  auto iter = std::find_if(children.begin(), children.end(), [&name](auto child) {return child->getName() == name;});\n  if(iter == children.end())\n    return XmlNodePtr();\n  XmlNodePtr ptr = *iter;\n  children.erase(iter);\n  return ptr;\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::findChild(const std::string &name)\n{\n  auto iter = std::find_if(children.begin(), children.end(), [&name](auto child) {return child->getName() == name;});\n  return (iter != children.end()) ? *iter : XmlNodePtr();\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::getNextChild()\n{\n  XmlNodePtr ptr;\n  if(!children.empty())\n  {\n    ptr = children.front();\n    children.pop_front();\n  }\n  return ptr;\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::findNextChild()\n{\n  if(!children.empty())\n    return children.front();\n  return nullptr;\n}\n\n/***********************************************/\n/***********************************************/\n\nXmlAttrPtr XmlNode::getAttribute(const std::string &name)\n{\n  auto iter = std::find_if(attribute.begin(), attribute.end(), [&name](auto attr) {return attr->getName() == name;});\n  if(iter == attribute.end())\n    return XmlAttrPtr();\n  XmlAttrPtr ptr = *iter;\n  attribute.erase(iter);\n  return ptr;\n}\n\n/***********************************************/\n\nXmlAttrPtr XmlNode::findAttribute(const std::string &name)\n{\n  auto iter = std::find_if(attribute.begin(), attribute.end(), [&name](auto attr) {return attr->getName() == name;});\n  return (iter != attribute.end()) ? *iter : XmlAttrPtr();\n}\n\n\n/***********************************************/\n\nXmlAttrPtr XmlNode::getNextAttribute()\n{\n  XmlAttrPtr ptr;\n  if(!attribute.empty())\n  {\n    ptr = attribute.front();\n    attribute.pop_front();\n  }\n  return ptr;\n}\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\nclass XmlReadFile\n{\npublic:\n  XmlNodePtr    root;\n  std::stack<XmlNodePtr> stack; // XML-Knoten, die noch nicht vollstaendig bearbeitet wurden\n};\n\n/***********************************************/\n\n// StartHandler\nstatic void XmlNodeStartElement(XmlReadFile *file, const XML_Char *name, const XML_Char **atts)\n{\n  XmlNodePtr ptr = XmlNode::create(name);\n  if(file->stack.empty())\n    file->root = ptr;\n\n  // Attributes\n  Bool disabled = FALSE;\n  for(UInt i=0; atts[i]!=nullptr; i+=2)\n  {\n    if(atts[i]==std::string(\"disabled\"))\n    {\n      if(atts[i+1] == std::string(\"1\"))\n        disabled = TRUE;\n    }\n    else\n    {\n      XmlAttrPtr attr(new XmlAttribute());\n      attr->name = atts[i];\n      attr->text = atts[i+1];\n      ptr->addAttribute(attr);\n    }\n  }\n\n  if((!file->stack.empty()) && (!disabled))\n    file->stack.top()->addChild(ptr);\n  file->stack.push(ptr);\n\n}\n\n/***********************************************/\n\n// TextHandler\nstatic void XmlNodeTextElement(XmlReadFile *file, const XML_Char *s, int len)\n{\n  file->stack.top()->addText(std::string(s, len));\n}\n\n/***********************************************/\n\n// EndHandler\nstatic void XmlNodeEndElement(XmlReadFile *file, const XML_Char */*name*/)\n{\n  XmlNodePtr ptr = file->stack.top();\n  file->stack.top() = XmlNodePtr();\n  file->stack.pop();\n\n  // Remove white spaces at the beginning of text.\n  std::size_t pos = ptr->getText().find_first_not_of(\" \\n\\t\");\n  if(pos!=std::string::npos)\n    ptr->setText(ptr->getText().substr(pos));\n  else\n    ptr->setText(std::string());\n}\n\n/***********************************************/\n\nXmlNodePtr XmlNode::read(std::istream &stream)\n{\n  try\n  {\n    stream.exceptions(std::ios::badbit|std::ios::failbit);\n\n    // Init Parser\n    XML_Parser expatParser = XML_ParserCreate(nullptr);\n\n    // Set Handler\n    std::shared_ptr<XmlReadFile> file(new XmlReadFile);\n    XML_SetUserData(expatParser, file.get());\n    XML_SetElementHandler(expatParser, reinterpret_cast<XML_StartElementHandler>(XmlNodeStartElement), reinterpret_cast<XML_EndElementHandler>(XmlNodeEndElement));\n    XML_SetCharacterDataHandler(expatParser, reinterpret_cast<XML_CharacterDataHandler>(XmlNodeTextElement));\n\n    static const UInt BUFFERSIZE = 1024*1024;\n    Char *buffer = new Char[BUFFERSIZE];\n\n    do\n    {\n      stream.get(buffer, BUFFERSIZE, '\\0');\n      auto bufferCount = stream.gcount();\n      XML_Status status = XML_Parse(expatParser, buffer, bufferCount, stream.eof());\n\n      if(status!=XML_STATUS_OK)\n      {\n        std::stringstream ss;\n        ss<<\"Parser Error in row \"<<XML_GetCurrentLineNumber(expatParser);\n        ss<<\", column \"<<XML_GetCurrentColumnNumber(expatParser);\n        ss<<\": \"<<XML_ErrorString(XML_GetErrorCode(expatParser));\n        throw(Exception(ss.str()));\n      }\n    }\n    while(!stream.eof());\n\n    delete[] buffer;\n    XML_ParserFree(expatParser);\n\n    return file->root;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid XmlNode::write(std::ostream &stream, UInt depth)\n{\n  // start tag\n  stream<<std::string(depth, '\\t')<<\"<\"<<getName();\n\n  // Attribute\n  for(auto attr : attribute)\n    stream<<\" \"<<attr->getName()<<\"=\\\"\"<<sanitizeXML(attr->getText())<<\"\\\"\";\n\n  // short form?\n  if(getText().empty() && children.empty())\n  {\n    stream<<\"/>\"<<std::endl;;\n    return;\n  }\n\n  stream<<\">\"<<sanitizeXML(getText());\n\n  // children\n  if(!children.empty())\n  {\n    stream<<std::endl;\n    for(auto child : children)\n      child->write(stream, depth+1);\n    stream<<std::string(depth, '\\t');\n  }\n\n  // end tag\n  stream<<\"</\"<<getName()<<\">\"<<std::endl;\n}\n\n/***********************************************/\n\nvoid XmlNode::write(std::ostream &stream, const XmlNodePtr &root)\n{\n  try\n  {\n    stream.exceptions(std::ios::badbit|std::ios::failbit);\n    stream<<\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\"<<std::endl;\n    root->write(stream);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string XmlNode::sanitizeXML(const std::string &str)\n{\n  return String::replaceAll(str, {{\"&\", \"&amp;\"}, {\">\", \"&gt;\"}, {\"<\", \"&lt;\"}, {\"'\", \"&apos;\"}, {\"\\\"\", \"&quot;\"}});\n}\n\n/***********************************************/\n/***** FUNCTIONS *******************************/\n/***********************************************/\n\nXmlNodePtr getNextChild(const XmlNodePtr &ptr, std::string &name)\n{\n  XmlNodePtr child = ptr->getNextChild();\n  if(child)\n    name = child->getName();\n  return child;\n}\n\n/***********************************************/\n\nUInt childCount(const XmlNodePtr &parent, const std::string &name, Bool mustGreaterZero)\n{\n  UInt count = parent->getChildCount(name);\n  if((count==0) && mustGreaterZero)\n    throw(Exception(\"'\"+parent->getName()+\"' must contain '\"+name+\"'\"));\n  return count;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/parser/xml.h",
    "content": "/***********************************************/\n/**\n* @file xml.h\n*\n* @brief Nodes of a XML tree.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2004-11-14\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_XML__\n#define __GROOPS_XML__\n\n#include \"base/importStd.h\"\n#include \"base/angle.h\"\n#include \"base/time.h\"\n\n/** @addtogroup parserGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass   XmlAttribute;\nclass   XmlNode;\ntypedef std::shared_ptr<XmlNode>      XmlNodePtr;\ntypedef std::shared_ptr<XmlAttribute> XmlAttrPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Attribute of a XML-node.\n* @ingroup parserGroup\n* @see XmlNode */\nclass XmlAttribute\n{\npublic:\n  /// Name of Attribute.\n  std::string name;\n\n  /// Content of Attribute.\n  std::string text;\n\n  /// Name of Attribute.\n  const std::string &getName() const {return name;}\n\n  /// Content of Attribute.\n  const std::string &getText() const {return text;}\n\n  /** @brief Interpret content as type of @a var.\n  * @param[out] var is filled with the content of attribute. */\n  template<typename T> void getValue(T &var) const;\n\n  /** @brief Set content of attribute. */\n  template<typename T> void setValue(const T &var);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Node of a XML-tree.\n* @ingroup parserGroup\n* For simple XML files. This means only on block of text is allowed for each node.\n*\n* Der Baum wird beim auslesen direkt abgebaut,\n* so dass nur einmal auslesen moeglich ist.\n* Der Speicher wird mit std::shared_ptr verwaltet,\n* so dass man keinen Speicher freigeben muss. */\nclass XmlNode\n{\n  std::string           name_;\n  std::string           text_;\n  std::list<XmlNodePtr> children;\n  std::list<XmlAttrPtr> attribute;\n\n  void write(std::ostream &stream, UInt depth=0);\n\npublic:\n  /// Constructor.\n  explicit XmlNode(const std::string &name) : name_(name) {}\n\n  XmlNode(const XmlNode &node) = delete;\n  XmlNode &operator=(const XmlNode &node) = delete;\n\n  /** @brief Deep copy.\n  * Creates a copy of the node and of all children. */\n  XmlNodePtr clone() const;\n\n  /** @brief Name of the node. */\n  const std::string &getName() const {return name_;}\n\n  /** @brief Set name of the node. */\n  void setName(const std::string &name) {name_ = name;}\n\n  /** @brief Content of the node. */\n  const std::string &getText() const {return text_;}\n\n  /** @brief Set content of the node. */\n  void setText(const std::string &text) {text_ = text;}\n\n  /** @brief Append @a text to the content of the node. */\n  void addText(const std::string &text) {text_ += text;}\n\n  /** @brief Interpret content as type of @a var.\n  * @param[out] var is filled with the content of node. */\n  template<typename T> void getValue(T &var) const;\n\n  /** @brief Set content of node. */\n  template<typename T> void setValue(const T &var);\n\n  /** @brief Has the node children nodes? */\n  Bool hasChildren() const {return !children.empty();}\n\n  std::list<XmlNodePtr> &getChildren() {return children;}\n\n  /** @brief Number of children with @a name. */\n  UInt getChildCount(const std::string &name);\n\n  /** @brief Returns the the first child with @a name.\n  * The child is removed from tree. If child does not exist, a NULL pointer is returned. */\n  XmlNodePtr getChild(const std::string &name);\n\n  /** @brief Returns the the first child with @a name.\n  * The child is NOT removed from tree. If child does not exist, a NULL pointer is returned. */\n  XmlNodePtr findChild(const std::string &name);\n\n  /** @brief Append a new child.\n  * It is not allowed to have the same node multiple times in the tree.\n  * (Create a copy with @a clone() before). */\n  void addChild(const XmlNodePtr &child) {children.push_back(child);}\n\n  /** @brief Insert a new child at begin.\n  * It is not allowed to have the same node multiple times in the tree.\n  * (Create a copy with @a clone() before). */\n  void prependChild(const XmlNodePtr &child) {children.push_front(child);}\n\n  /** @brief Returns the next child.\n  * The child is removed from tree. If child not exists, a NULL pointer is returned. */\n  XmlNodePtr getNextChild();\n\n  /** @brief Returns the next child.\n  * The child is NOT removed from tree. If child not exists, a NULL pointer is returned. */\n  XmlNodePtr findNextChild();\n\n  /** @brief Has the node attributes? */\n  Bool hasAttribute() const {return !attribute.empty();}\n\n  /** @brief Returns the the first attribute with @a name.\n  * The attribute is removed from the node. If attribute does not exist, a NULL pointer is returned. */\n  XmlAttrPtr getAttribute(const std::string &name);\n\n  /** @brief Returns the the first attribute with @a name.\n  * The attribute is NOT removed from the node. If attribute does not exist, a NULL pointer is returned. */\n  XmlAttrPtr findAttribute(const std::string &name);\n\n  /** @brief Append a new attribute.\n  * It is not allowed to have the same attribute multiple times in the tree. */\n  void addAttribute(const XmlAttrPtr &attr) {attribute.push_back(attr);}\n\n  /** @brief Returns the next attribute.\n  * The attribute is removed from the node. If attribute does not exist, a NULL pointer is returned. */\n  XmlAttrPtr getNextAttribute();\n\n  /** @brief XmlNode factory. */\n  static XmlNodePtr create(const std::string &name);\n\n  /** @brief Read XML tree from stream.\n  * @param stream Input stream.\n  * @return Root node of the XML tree. */\n  static XmlNodePtr read(std::istream &stream);\n\n  /** @brief Write XML tree to stream.\n  * @param stream output stream.\n  * @param root Root node of the XML tree. */\n  static void write(std::ostream &stream, const XmlNodePtr &root);\n\n  /** @brief Replace characters with entity references\n  * @param in string to be parsed\n  * @return out string with character entitiy references\n  */\n  static std::string sanitizeXML(const std::string& in);\n};\n\n\n/***** FUNCTIONS ***********************************/\n\n/** @brief Anzahl der Kinder mit Namen @a name.\n* If @a mustSet==TRUE, an Exception is thrown.\n* @relates XmlNode */\nUInt childCount(const XmlNodePtr &parent, const std::string &name, Bool mustGreaterZero=FALSE);\n\n/** @brief Returns the next child.\n* In @a name the name of the child is returned.\n* If child not exists, a NULL pointer is returned.\n* @relates XmlNode */\nXmlNodePtr getNextChild(const XmlNodePtr &parent, std::string &name);\n\n/** @brief Returns the the first child with @a name.\n* The child is removed from tree. If child not exists and @a mustSet==TRUE,\n* an Exception is thrown otherwise a NULL pointer is returned.\n* @relates XmlNode */\nXmlNodePtr getChild(const XmlNodePtr &parent, const std::string &name, Bool mustSet=FALSE);\n\n/** @brief Reads a variable from XML.\n* Locking for child with @a name and interpret the content as type of @a var.\n* The child is removed from tree. If child not exists the @a var is untouched\n* and if additionally @a mustSet==TRUE, an Exception is thrown.\n* @relates XmlNode */\ntemplate<class T>\nXmlNodePtr readXml(const XmlNodePtr &parent, const std::string &name, T &var, Bool mustSet=FALSE);\n\n/** @brief Write a variable to a XML tree.\n* A XML child with @a name is created and is appended to @a parent.\n* The value of @a var is written as content of the child.\n* @relates XmlNode */\ntemplate<class T>\nXmlNodePtr writeXml(const XmlNodePtr &parent, const std::string &name, const T &var);\n\n/** @brief Reads a variable from XmlAttribute.\n* Locking for a attribute with @a name and interpret the content as type of @a var.\n* The attribute is removed from node. If attribute not exists the @a var is untouched\n* and if additionally @a mustSet==TRUE, an Exception is thrown.\n* @relates XmlNode */\ntemplate<class T>\nXmlAttrPtr readAttribute(const XmlNodePtr &node, const std::string &name, T &var, Bool mustSet=FALSE);\n\n/** @brief Write a variable as attribute to a XML node.\n* A XmlAttribute with @a name is created and is appended to @a node.\n* The value of @a var is written as content of the attribute.\n* @relates XmlNode */\ntemplate<class T>\nXmlAttrPtr writeAttribute(const XmlNodePtr &node, const std::string &name, const T &var);\n\n/** @brief XmlNode factory.\n* A XML child with @a name is created and is appended to @a parent.\n* @relates XmlNode */\nXmlNodePtr createXmlNode(const XmlNodePtr &parent, const std::string &name);\n\n/// @}\n\n/***********************************************/\n/***** INLINES *********************************/\n/***********************************************/\n\ntemplate<typename T> void XmlAttribute::getValue(T &var) const\n{\n  try\n  {\n    std::stringstream ss(text);\n    ss>>var;\n    if(!(ss.good()||ss.eof()))\n      throw Exception(\"stream error\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\ntemplate<> inline void XmlAttribute::getValue(std::string &var) const // Spezialization\n{\n  var = text;\n}\n\n/***********************************************/\n\ninline XmlNodePtr XmlNode::create(const std::string &name)\n{\n  return XmlNodePtr(new XmlNode(name));\n}\n\n/***********************************************/\n\ntemplate<typename T> void XmlAttribute::setValue(const T &var)\n{\n  try\n  {\n    std::stringstream ss;\n    ss.setf(std::ios::scientific,std::ios::floatfield);\n    ss.precision(18);\n    ss<<var; ss>>text;\n    if(!(ss.good()||ss.eof()))\n      throw Exception(\"stream error\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\ntemplate<> inline void XmlAttribute::setValue(const std::string &var) // Spezialization\n{\n  text = var;\n}\n\n/***********************************************/\n\ntemplate<typename T> void XmlNode::getValue(T &var) const\n{\n  try\n  {\n    std::stringstream ss(text_);\n    ss>>var;\n    if(!(ss.good()||ss.eof()))\n      throw Exception(\"stream error\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\ntemplate<> inline void XmlNode::getValue(Double &var) const // Spezialization\n{\n  try\n  {\n    var = std::stod(text_);\n  }\n  catch(std::invalid_argument &)\n  {\n    throw(Exception(\"cannot read number: \"+text_));\n  }\n}\n\ntemplate<> inline void XmlNode::getValue(Time &var) const // Spezialization\n{\n  Double mjd;\n  getValue(mjd);\n  var = mjd2time(mjd);\n}\n\ntemplate<> inline void XmlNode::getValue(Angle &var) const // Spezialization\n{\n  Double x;\n  getValue(x);\n  var = Angle(x*DEG2RAD);\n}\n\ntemplate<> inline void XmlNode::getValue(std::string &var) const\n{\n  var = getText();\n}\n\n/***********************************************/\n\ntemplate<typename T> void XmlNode::setValue(const T &var)\n{\n  try\n  {\n    std::stringstream ss;\n    ss.setf(std::ios::scientific,std::ios::floatfield);\n    ss.precision(18);\n    ss<<var; ss>>text_;\n    if(!(ss.good()||ss.eof()))\n      throw Exception(\"stream error\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\ntemplate<> inline void XmlNode::setValue(const Time  &var) // Spezialization\n{\n  setValue(var.mjd());\n}\n\ntemplate<> inline void XmlNode::setValue(const Angle &var) // Spezialization\n{\n  setValue(static_cast<Double>(var*RAD2DEG));\n}\n\ntemplate<> inline void XmlNode::setValue(const std::string &var) // Spezialization\n{\n  text_ = var;\n}\n\n/***********************************************/\n\ntemplate<class T> inline XmlNodePtr readXml(const XmlNodePtr &parent, const std::string &name, T &var, Bool mustSet)\n{\n  XmlNodePtr child = getChild(parent, name, mustSet);\n  if(child!=nullptr)\n    child->getValue(var);\n  return child;\n}\n\n/***********************************************/\n\ntemplate<class T> inline XmlNodePtr writeXml(const XmlNodePtr &parent, const std::string &name, const T &var)\n{\n  XmlNodePtr child = createXmlNode(parent, name);\n  child->setValue(var);\n  return child;\n}\n\n/***********************************************/\n\ninline XmlNodePtr getChild(const XmlNodePtr &parent, const std::string &name, Bool mustSet)\n{\n  try\n  {\n    XmlNodePtr child = parent->getChild(name);\n    if((child==nullptr) && mustSet)\n      throw(Exception(\"'\"+parent->getName()+\"' must contain '\"+name+\"'\"));\n    return child;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline XmlNodePtr createXmlNode(const XmlNodePtr &parent, const std::string &name)\n{\n  XmlNodePtr child = XmlNode::create(name);\n  parent->addChild(child);\n  return child;\n}\n\n/***********************************************/\n\ntemplate<class T>\ninline XmlAttrPtr readAttribute(const XmlNodePtr &node, const std::string &name, T &var, Bool mustSet)\n{\n  try\n  {\n    XmlAttrPtr attr = node->getAttribute(name);\n    if((attr==nullptr) && mustSet)\n      throw(Exception(\"'\"+node->getName()+\"' muss contain '\"+name+\"'\"));\n    if(attr!=nullptr)\n      attr->getValue(var);\n    return attr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<class T>\ninline XmlAttrPtr writeAttribute(const XmlNodePtr &node, const std::string &name, const T &var)\n{\n  XmlAttrPtr attr = XmlAttrPtr(new XmlAttribute());\n  attr->name = name;\n  attr->setValue(var);\n  node->addAttribute(attr);\n  return attr;\n}\n\n/***********************************************/\n/***********************************************/\n\n#endif /* __GROOPS_XML__ */\n"
  },
  {
    "path": "source/plot/plotAxis.cpp",
    "content": "/***********************************************/\n/**\n* @file plotAxis.cpp\n*\n* @brief Axis ticks, limits and labels.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2016-07-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotAxis\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"plot/plotMisc.h\"\n#include \"plotAxis.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/system.h\"\n\n/***********************************************/\n\nstatic const char *docstringPlotAxisStandard = R\"(\n\\subsection{Standard}\nGeneral axis for arbitrary input data.\n)\";\n\n/***** CLASS ***********************************/\n\nclass PlotAxisStandard : public PlotAxis\n{\n  Double      annotation, frame, grid;\n  std::string unit, label;\n  Bool        isLog;\n\npublic:\n  PlotAxisStandard(Config &config);\n  void        setAutoInterval(Double minAuto, Double maxAuto);\n  std::string axisModifier() const {return isLog ? \"l\" : \"\";}\n  std::string scriptEntry(const std::string &axis, Bool withGrid) const;\n  Bool        isLogarithmic() const {return isLog;}\n};\n\n/***********************************************/\n\nPlotAxisStandard::PlotAxisStandard(Config &config)\n{\n  try\n  {\n    vMin       = NAN_EXPR;\n    vMax       = NAN_EXPR;\n    annotation = NAN_EXPR;\n    frame      = NAN_EXPR;\n    grid       = NAN_EXPR;\n\n    renameDeprecatedConfig(config, \"annotation\", \"majorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frame\",      \"minorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"grid\",       \"gridLineSpacing\",  date2time(2020, 4, 23));\n\n    readConfig(config, \"min\",              vMin,            Config::OPTIONAL, \"\",  \"The minimum value of the axis. If no value is given, the minimum scale value is set automatically.\");\n    readConfig(config, \"max\",              vMax,            Config::OPTIONAL, \"\",  \"The maximum value of the axis. If no value is given, the maximum scale value is set automatically.\");\n    readConfig(config, \"majorTickSpacing\", annotation,      Config::OPTIONAL, \"\",  \"The boundary annotation.\");\n    readConfig(config, \"minorTickSpacing\", frame,           Config::OPTIONAL, \"\",  \"The spacing of the frame tick intervals.\");\n    readConfig(config, \"gridLineSpacing\",  grid,            Config::OPTIONAL, \"\",  \"The spacing of the grid line intervals\");\n    readConfig(config, \"gridLine\",         gridLine,        Config::OPTIONAL, R\"({\"solid\": {\"width\":\"0.25\", \"color\":\"gray\"}})\", \"The style of the grid lines.\");\n    readConfig(config, \"unit\",             unit,            Config::OPTIONAL, \"\",  \"Naming unit to append to the axis values.\");\n    readConfig(config, \"label\",            label,           Config::OPTIONAL, \"\",  \"The description of the axis.\");\n    readConfig(config, \"logarithmic\",      isLog,           Config::DEFAULT,  \"0\", \"If set to 'yes', a logarithmic scale is used for the axis.\");\n    readConfig(config, \"color\",            color,           Config::MUSTSET,  \"\",  \"Setting the color of the axis bars and labels.\");\n    readConfig(config, \"changeDirection\",  changeDirection, Config::DEFAULT,  \"0\", \"If set to 'yes', the directions right/up are changed to left/down.\");\n    if(isCreateSchema(config)) return;\n\n    margin = 0.5;\n    if(!label.empty())\n      margin += 0.3;\n\n    if(!gridLine)\n      grid = 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotAxisStandard::setAutoInterval(Double minAuto, Double maxAuto)\n{\n  try\n  {\n    if(std::isnan(vMin)) vMin = minAuto;\n    if(std::isnan(vMax)) vMax = maxAuto;\n\n    if(vMin == vMax)\n    {\n      vMin *= 0.9;\n      vMax *= 1.1;\n      if(vMin == 0.0)\n      {\n        vMin = -1.0;\n        vMax = +1.0;\n      }\n    }\n\n    if(vMin > vMax) std::swap(vMin, vMax);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotAxisStandard::scriptEntry(const std::string &axis, Bool withGrid) const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\" --MAP_DEFAULT_PEN=+\"<<color->str()<<\" --FONT_ANNOT_PRIMARY=\"<<color->str()<<\" --FONT_LABEL=\"<<color->str();\n    if(gridLine) ss<<\" --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str();\n    ss<<\" -B\"<<axis<<PlotBasics::axisTicks(isLog, vMin, vMax, annotation, frame, (withGrid) ? grid : 0, unit, label);\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotAxisTime = R\"(\n\\subsection{Time}\nThe input data are interpreted as MJD (modified Julian date).\nThe unit of the tick spacings should be appenend to the number and can be any of\n\\begin{itemize}\n\\item Y (year, plot with 4 digits)\n\\item y (year, plot with 2 digits)\n\\item O (month, plot using \\verb|FORMAT_DATE_MAP|)\n\\item o (month, plot with 2 digits)\n\\item U (ISO week, plot using \\verb|FORMAT_DATE_MAP|)\n\\item u (ISO week, plot using 2 digits)\n\\item r (Gregorian week, 7-day stride from start of week \\verb|TIME_WEEK_START|)\n\\item K (ISO weekday, plot name of day)\n\\item D (date, plot using \\verb|FORMAT_DATE_MAP|)\n\\item d (day, plot day of month 0-31 or year 1-366, via \\verb|FORMAT_DATE_MAP|)\n\\item R (day, same as d, aligned with \\verb|TIME_WEEK_START|)\n\\item H (hour, plot using \\verb|FORMAT_CLOCK_MAP|)\n\\item h (hour, plot with 2 digits)\n\\item M (minute, plot using \\verb|FORMAT_CLOCK_MAP|)\n\\item m (minute, plot with 2 digits)\n\\item S (second, plot using \\verb|FORMAT_CLOCK_MAP|)\n\\item s (second, plot with 2 digits).\n\\end{itemize}\n\nA secondary time axis can be added to specify larger intervals (e.g dates of hourly data).\n\nExamples: Settings for Fig.~\\ref{plotAxisType:plotAxisTime1}: \\config{majorTickSpacing}=\\verb|6H|, secondary: \\config{majorTickSpacing}=\\verb|1D|.\n\\fig{!hb}{1.0}{plotAxisTime1}{plotAxisType:plotAxisTime1}{Time axis for daily data.}\n\nSettings for Fig.~\\ref{plotAxisType:plotAxisTime2}: \\config{majorTickSpacing}=\\verb|2d|, secondary: \\config{majorTickSpacing}=\\verb|1O|, \\config{options}=\\verb|FORMAT_DATE_MAP=\"o yyyy\"|.\n\\fig{!hb}{1.0}{plotAxisTime2}{plotAxisType:plotAxisTime2}{Time axis for monthly data.}\n\nSettings for Fig.~\\ref{plotAxisType:plotAxisTime3}: \\config{majorTickSpacing}=\\verb|1o|, secondary: \\config{majorTickSpacing}=\\verb|1Y|, \\config{options}=\\verb|FORMAT_DATE_MAP=\"mm\"|.\n\\fig{!hb}{1.0}{plotAxisTime3}{plotAxisType:plotAxisTime3}{Time axis for yearly data.}\n\n)\";\n\n/***** CLASS ***********************************/\n\nclass PlotAxisTime : public PlotAxis\n{\n  std::string annotation,  grid,  frame;\n  std::string annotation2, grid2, frame2;\n  std::string optionsString;\n\npublic:\n  PlotAxisTime(Config &config);\n  void        setAutoInterval(Double minAuto, Double maxAuto);\n  std::string axisModifier() const {return \"t\";}\n  std::string scriptEntry(const std::string &axis, Bool withGrid) const;\n};\n\n/***********************************************/\n\nPlotAxisTime::PlotAxisTime(Config &config)\n{\n  try\n  {\n    Time minTime, maxTime;\n    std::vector<std::string> options;\n\n    renameDeprecatedConfig(config, \"annotation\", \"majorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frame\",      \"minorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"grid\",       \"gridLineSpacing\",  date2time(2020, 4, 23));\n\n    readConfig(config, \"min\",                minTime,       Config::OPTIONAL, \"\",   \"The minimum value of the time axis. If no value is given, the minimum scale value is set automatically.\");\n    readConfig(config, \"max\",                maxTime,       Config::OPTIONAL, \"\",   \"The maximum value of the time axis. If no value is given, the maximum scale value is set automatically.\");\n    readConfig(config, \"majorTickSpacing\",   annotation,    Config::OPTIONAL, \"2o\", \"Y: year, o: month\");\n    readConfig(config, \"minorTickSpacing\",   frame,         Config::OPTIONAL, \"1o\", \"D: date, d: day\");\n    readConfig(config, \"gridLineSpacing\",    grid,          Config::OPTIONAL, \"\",   \"H: clock, h: hour, m: minute, s: second\");\n    if(readConfigSequence(config, \"secondary\", Config::OPTIONAL, \"\", \"secondary time axis\"))\n    {\n      renameDeprecatedConfig(config, \"annotation\", \"majorTickSpacing\", date2time(2020, 4, 23));\n      renameDeprecatedConfig(config, \"frame\",      \"minorTickSpacing\", date2time(2020, 4, 23));\n      renameDeprecatedConfig(config, \"grid\",       \"gridLineSpacing\",  date2time(2020, 4, 23));\n\n      readConfig(config, \"majorTickSpacing\", annotation2, Config::OPTIONAL, \"1Y\", \"Y: year, o: month\");\n      readConfig(config, \"minorTickSpacing\", frame2,      Config::OPTIONAL, \"\",   \"D: date, d: day\");\n      readConfig(config, \"gridLineSpacing\",  grid2,       Config::OPTIONAL, \"1Y\", \"H: clock, h: hour, m: minute, s: second\");\n      endSequence(config);\n    }\n    readConfig(config, \"color\",           color,           Config::MUSTSET,  \"\",  \"color of axis bars and labels\");\n    readConfig(config, \"gridLine\",        gridLine,        Config::OPTIONAL, R\"({\"solid\": {\"width\":\"0.25\", \"color\":\"gray\"}})\", \"The style of the grid lines.\");\n    readConfig(config, \"changeDirection\", changeDirection, Config::DEFAULT,  \"0\", \"right->left / up->down\");\n    readConfig(config, \"options\",         options,         Config::OPTIONAL, R\"([\"FORMAT_DATE_MAP=yyyy-mm-dd\", \"FORMAT_CLOCK_MAP=hh:mm\"])\", \"adjust date format\");\n    if(isCreateSchema(config)) return;\n\n    vMin = NAN_EXPR;\n    vMax = NAN_EXPR;\n    if(maxTime != Time()) vMax = maxTime.mjd();\n    if(minTime != Time()) vMin = minTime.mjd();\n\n    for(UInt i=0; i<options.size(); i++)\n      if(!options.at(i).empty())\n        optionsString += \" --\"+options.at(i);\n\n    margin = 0.5;\n    if(!(annotation2.empty() && frame2.empty() && grid2.empty()))\n      margin +=0.3;\n\n    if(!gridLine)\n    {\n      grid  = \"\";\n      grid2 = \"\";\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotAxisTime::setAutoInterval(Double minAuto, Double maxAuto)\n{\n  try\n  {\n    if(std::isnan(vMin)) vMin = minAuto;\n    if(std::isnan(vMax)) vMax = maxAuto;\n    if(vMin > vMax) std::swap(vMin, vMax);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotAxisTime::scriptEntry(const std::string &axis, Bool withGrid) const\n{\n  try\n  {\n    std::string intervals;\n    {\n      std::stringstream ss;\n      if(!annotation.empty())       ss<<\"a\"<<annotation;\n      if(!frame.empty())            ss<<\"f\"<<frame;\n      if(!grid.empty() && withGrid) ss<<\"g\"<<grid;\n      intervals = ss.str();\n    }\n    std::string intervals2;\n    {\n      std::stringstream ss;\n      if(!annotation2.empty())       ss<<\"a\"<<annotation2;\n      if(!frame2.empty())            ss<<\"f\"<<frame2;\n      if(!grid2.empty() && withGrid) ss<<\"g\"<<grid2;\n      intervals2 = ss.str();\n    }\n\n    std::stringstream ss;\n    ss<<\" --MAP_DEFAULT_PEN=+\"<<color->str()<<\" --FONT_ANNOT_PRIMARY=\"<<color->str()<<\" --FONT_LABEL=\"<<color->str();\n    if(gridLine) ss<<\" --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str();\n    ss<<optionsString;\n    if(intervals2.empty())\n      ss<<\" -B\"<<axis<<intervals;\n    else\n      ss<<\" -Bp\"<<axis<<intervals<<\" -Bs\"<<axis<<intervals2;\n\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotAxisLabeled = R\"(\n\\subsection{Labeled}\nAxis with string labels. The coordinate system is based on the label indices (e.g. 0, 1, 2).\n)\";\n\n/***** CLASS ***********************************/\n\nclass PlotAxisLabeled : public PlotAxis\n{\n  std::vector<std::string> labels;\n  Double   annotation, frame, grid;\n  Bool     orthoLabels;\n  FileName dataFileName;\n\npublic:\n  PlotAxisLabeled(Config &config);\n  void        setAutoInterval(Double minAuto, Double maxAuto);\n  void        writeDataFile(const FileName &workingDirectory, const std::string &axis);\n  std::string axisModifier() const {return \"\";}\n  std::string scriptEntry(const std::string &axis, Bool withGrid) const;\n};\n\n/***********************************************/\n\nPlotAxisLabeled::PlotAxisLabeled(Config &config)\n{\n  try\n  {\n    ExpressionVariablePtr exprMin, exprMax, exprAnnotation, exprFrame, exprGrid;\n    vMin = vMax = NAN_EXPR;\n    annotation = 1;\n    frame      = 1;\n    grid       = 1;\n\n    readConfig(config, \"labels\",           labels,          Config::MUSTSET,  \"\",             \"tick labels (ticks are placed at their index. e.g. 0, 1, ..., 5)\");\n    readConfig(config, \"min\",              exprMin,         Config::OPTIONAL, \"0\",            \"minimum value of the axis\");\n    readConfig(config, \"max\",              exprMax,         Config::OPTIONAL, \"labelCount-1\", \"maximum values of the axis\");\n    readConfig(config, \"majorTickSpacing\", exprAnnotation,  Config::OPTIONAL, \"1\",            \"The boundary annotation.\");\n    readConfig(config, \"minorTickSpacing\", exprFrame,       Config::OPTIONAL, \"1\",            \"The spacing of the frame tick intervals.\");\n    readConfig(config, \"gridLineSpacing\",  exprGrid,        Config::OPTIONAL, \"1\",            \"The spacing of the grid line intervals\");\n    readConfig(config, \"gridLine\",         gridLine,        Config::OPTIONAL, R\"({\"solid\": {\"width\":\"0.25\", \"color\":\"gray\"}})\", \"The style of the grid lines.\");\n    readConfig(config, \"color\",            color,           Config::MUSTSET,  \"\",             \"set the color of the axis and labels\");\n    readConfig(config, \"orthogonalLabels\", orthoLabels,     Config::DEFAULT,  \"0\",            \"labels are oriented orthogonal to axis\");\n    readConfig(config, \"changeDirection\",  changeDirection, Config::DEFAULT,  \"0\",            \"If set to 'yes', the directions right/up are changed to left/down.\");\n    if(isCreateSchema(config)) return;\n\n    margin = 0.5;\n\n    VariableList variableList;\n    variableList.setVariable(\"labelCount\", static_cast<Double>(labels.size()));\n    if(exprMin)        vMin       = exprMin->evaluate(variableList) - 0.5;\n    if(exprMax)        vMax       = exprMax->evaluate(variableList) + 0.5;\n    if(exprAnnotation) annotation = exprAnnotation->evaluate(variableList);\n    if(exprFrame)      frame      = exprFrame->evaluate(variableList);\n    if(exprGrid)       grid       = exprGrid->evaluate(variableList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotAxisLabeled::setAutoInterval(Double minAuto, Double maxAuto)\n{\n  try\n  {\n    if(minAuto > maxAuto) std::swap(minAuto, maxAuto);\n    if(std::isnan(vMin)) vMin = minAuto;\n    if(std::isnan(vMax)) vMax = maxAuto;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotAxisLabeled::writeDataFile(const FileName &workingDirectory, const std::string &axis)\n{\n  try\n  {\n    std::vector<std::pair<Double, std::string>> lines;\n    for(UInt k=0; k<labels.size(); k++)\n      if((vMin <= k) && (k <= vMax) && (std::fmod(k, annotation) == 0))\n        lines.push_back(std::pair<Double, std::string>(k, \" a \"s+labels.at(k)));\n\n    if(frame > 0)\n      for(Double k=vMin-std::fmod(vMin, frame); k<=vMax; k+=frame)\n        lines.push_back(std::pair<Double, std::string>(k, \" f\"));\n\n    if(gridLine && (grid > 0))\n      for(Double k=vMin-std::fmod(vMin, grid); k<=vMax; k+=grid)\n        lines.push_back(std::pair<Double, std::string>(k, \" g\"));\n\n    std::sort(lines.begin(), lines.end(), [](auto &a, auto &b){return a.first < b.first;});\n    dataFileName = \"labels.\"+axis+\".txt\";\n    OutFile file(workingDirectory.append(dataFileName));\n    for(auto &line : lines)\n      file<<line.first<<line.second<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\nstd::string PlotAxisLabeled::scriptEntry(const std::string &axis, Bool /*withGrid*/) const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\" --MAP_DEFAULT_PEN=+\"<<color->str()<<\" --FONT_ANNOT_PRIMARY=\"<<color->str()<<\" --FONT_LABEL=\"<<color->str()<<\" -B\"<<axis<<\"c\"<<dataFileName;\n    if(gridLine) ss<<\" --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str();\n    if(orthoLabels)\n      ss<<\" --MAP_ANNOT_ORTHO=ns\";\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(PlotAxis, \"plotAxisType\",\n                      PlotAxisStandard,\n                      PlotAxisTime,\n                      PlotAxisLabeled)\n\nGROOPS_READCONFIG_CLASS(PlotAxis, \"plotAxisType\")\n\n/***********************************************/\n\nPlotAxisPtr PlotAxis::create(Config &config, const std::string &name)\n{\n  try\n  {\n    PlotAxisPtr plotAxis;\n    std::string  type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"axis limits, labels and annotation\");\n    if(readConfigChoiceElement(config, \"standard\", type, \"generic x/y axis\"))\n      plotAxis = PlotAxisPtr(new PlotAxisStandard(config));\n    if(readConfigChoiceElement(config, \"time\",     type, \"intepret x-values as MJD\"))\n      plotAxis = PlotAxisPtr(new PlotAxisTime(config));\n    if(readConfigChoiceElement(config, \"labeled\",  type, \"major ticks with string labels\"))\n      plotAxis = PlotAxisPtr(new PlotAxisLabeled(config));\n    endChoice(config);\n\n    return plotAxis;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotAxis.h",
    "content": "/***********************************************/\n/**\n* @file plotAxis.h\n*\n* @brief Axis ticks, limits and labels.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2016-07-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTAXIS__\n#define __GROOPS_PLOTAXIS__\n\n// Latex documentation\n#ifdef DOCSTRING_PlotAxis\nstatic const char *docstringPlotAxis = R\"(\n\\section{PlotAxis}\\label{plotAxisType}\nDefines the style of the axes of \\program{PlotGraph}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass PlotAxis;\ntypedef std::shared_ptr<PlotAxis> PlotAxisPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Axis ticks, limits and labels.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotAxis\n{\nprotected:\n  Double       vMin;\n  Double       vMax;\n  PlotColorPtr color;\n  PlotLinePtr  gridLine;\n  Double       margin;          // margin between label and ticks\n  Bool         changeDirection; // flag whether to reverse the axis\n\npublic:\n  virtual ~PlotAxis() {}\n\n  virtual void setAutoInterval(Double minAuto, Double maxAuto) = 0;\n\n  /** @brief Get minimum value for this axis. */\n  virtual Double getMin() const {return vMin;}\n\n  /** @brief Get maximum value for this axis. */\n  virtual Double getMax() const {return vMax;}\n\n  /** @brief return margin of this axis\n  * @return margin height/width in cm */\n  virtual Double getMargin() const {return margin;}\n\n  /** @brief direction of the axis (+1 or -1) */\n  virtual int direction() const {return changeDirection ? -1 : +1;}\n\n  /** @brief return if axis is in logarithmic spacing */\n  virtual Bool isLogarithmic() const {return FALSE;}\n\n  /** @brief GMT axis modifier (i.e. logarithmic, normal or time axis)\n  * @return modifier string representation of axis type */\n  virtual std::string axisModifier() const = 0;\n\n  /** @brief Create temporary files for axis plots. */\n  virtual void writeDataFile(const FileName &/*workingDirectory*/, const std::string &/*axis*/) {}\n\n  /** @brief GMT script line for axis object\n  * @return line GMT string representation of axis object */\n  virtual std::string scriptEntry(const std::string &axis, Bool withGrid=TRUE) const = 0;\n\n  /** @brief creates an derived instance of this class. */\n  static PlotAxisPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates a class PlotAxis.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotAxis is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotAxis Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotAxis */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotAxisPtr &plotAxis, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/plot/plotColorbar.cpp",
    "content": "/***********************************************/\n/**\n* @file plotColorbar.cpp\n*\n* @brief Colorbar.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2020-05-03\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotColorbar\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"plotMisc.h\"\n#include \"plotColorbar.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(PlotColorbar, \"plotColorbarType\")\nGROOPS_READCONFIG_CLASS(PlotColorbar, \"plotColorbarType\")\n\n/***********************************************/\n\nPlotColorbar::PlotColorbar(Config &config, const std::string &name)\n{\n  try\n  {\n    vMin       = NAN_EXPR;\n    vMax       = NAN_EXPR;\n    annotation = NAN_EXPR;\n    Bool reverse;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"min\",           vMin,          Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"max\",           vMax,          Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"annotation\",    annotation,    Config::OPTIONAL, \"\",    \"boundary annotation\");\n    readConfig(config, \"unit\",          unit,          Config::OPTIONAL, \"\",    \"appended to axis values\");\n    readConfig(config, \"label\",         label,         Config::OPTIONAL, \"\",    \"description of the axis\");\n    readConfig(config, \"logarithmic\",   isLog,         Config::DEFAULT,  \"0\",   \"use logarithmic scale\");\n    readConfig(config, \"triangleLeft\",  triangleLeft,  Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"triangleRight\", triangleRight, Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"illuminate\",    illuminate,    Config::DEFAULT,  \"0\",   \"illuminate\");\n    readConfig(config, \"vertical\",      vertical,      Config::DEFAULT,  \"0\",   \"plot vertical color bar on the right\");\n    readConfig(config, \"length\",        length,        Config::DEFAULT,  \"100\", \"length of colorbar in percent\");\n    readConfig(config, \"margin\",        margin,        Config::DEFAULT,  \"0.4\", \"between colorbar and figure [cm]\");\n    readConfig(config, \"colorTable\",    colorTable,    Config::DEFAULT,  \"haxby\", \"name of the color bar\");\n    readConfig(config, \"reverse\",       reverse,       Config::DEFAULT,  \"0\",   \"reverse direction\");\n    readConfig(config, \"showColorbar\",  isPlot,        Config::DEFAULT,  \"1\",   \"\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    if(reverse)\n      colorTable += \" -I\";\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotColorbar::setAutoInterval(Double minAuto, Double maxAuto)\n{\n  try\n  {\n    if(std::isnan(vMin)) vMin = minAuto;\n    if(std::isnan(vMax)) vMax = maxAuto;\n\n    if(vMin == vMax)\n    {\n      vMin *= 0.9;\n      vMax *= 1.1;\n      if(vMin == 0.0)\n      {\n        vMin = -1.0;\n        vMax = +1.0;\n      }\n    }\n\n    if(vMin > vMax) std::swap(vMin, vMax);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotColorbar::scriptColorTable() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt makecpt -D -Z -C\"<<((colorTable.empty()) ? \"haxby\" : colorTable)<<\" -T\"<<vMin<<\"/\"<<vMax<<\"/\";\n    if(isLog)\n      ss<<\"3 -Qo\";\n    else\n      ss<<((vMax-vMin)/9.)%\"%.10g\"s;\n    ss<<\" >groopsPlot.cpt \"<<PlotBasics::scriptError2Null()<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotColorbar::scriptEntry(Double width, Double height, Double marginX, Double marginY) const\n{\n  try\n  {\n    if(!isPlot)\n      return \"\";\n    std::stringstream ss;\n    ss<<\"gmt psscale -CgroopsPlot.cpt\";\n    if(!isLog)\n    {\n      ss<<\" -Ba\"; if(!std::isnan(annotation)) ss<<annotation;\n    }\n    else\n      ss<<\" -Q -Ba1pf3\";\n    if(!label.empty()) ss<<\"+l\\\"\"<<label<<\"\\\"\";\n    if(!unit.empty())  ss<<\"+u\\\"\"<<(unit==\"%\" ? \"\" : \" \")<<unit<<\"\\\"\";\n    if(illuminate)     ss<<\" -I\";\n\n    if(vertical)\n      ss<<\" -Dx\"<<width+marginX+margin<<\"c/\"<<height/2<<\"c+w\"<<(height-0.4)*length/100.<<\"c/0.4c+jLM\";\n    else\n      ss<<\" -Dx\"<<width/2<<\"c/\"<<-margin-marginY<<\"c+w\"<<(width-0.4)*length/100.<<\"c/0.4c+jCT+h\";\n    if(triangleLeft || triangleRight) ss<<\"+e\";\n    if(triangleLeft)   ss<<\"b\";\n    if(triangleRight)  ss<<\"f\";\n\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotColorbar.h",
    "content": "/***********************************************/\n/**\n* @file plotColorbar.h\n*\n* @brief Colorbar.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2020-05-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTCOLORBAR__\n#define __GROOPS_PLOTCOLORBAR__\n\n// Latex documentation\n#ifdef DOCSTRING_PlotColorbar\nstatic const char *docstringPlotColorbar = R\"(\n\\section{PlotColorbar}\\label{plotColorbarType}\nA colorbar as used in \\program{PlotMap}, \\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass PlotColorbar;\ntypedef std::shared_ptr<PlotColorbar> PlotColorbarPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief A Colorbar for GMT plots.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotColorbar\n{\n  Double      vMin, vMax;\n  std::string colorTable;\n  Double      annotation;\n  std::string label, unit;\n  Bool        isLog;\n  Bool        triangleLeft, triangleRight;\n  Bool        illuminate;\n  Bool        vertical;\n  Double      margin;\n  Double      length;\n  Bool        isPlot;\n\npublic:\n  /** @brief Constructor. */\n  PlotColorbar(Config &config, const std::string &name);\n\n  void setAutoInterval(Double minAuto, Double maxAuto);\n\n  /** @brief Get minimum value for this axis. */\n  Double getMin() const {return vMin;}\n\n  /** @brief Get maximum value for this axis. */\n  Double getMax() const {return vMax;}\n\n  Bool isLogarithmic() const {return isLog;}\n\n  std::string scriptColorTable() const;\n  std::string scriptEntry(Double width, Double height, Double marginX, Double marginY) const;\n\n  /** @brief creates an derived instance of this class. */\n  static PlotColorbarPtr create(Config &config, const std::string &name) {return PlotColorbarPtr(new PlotColorbar(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates a class PlotColorbar.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotColorbar is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotColorbar Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotColorbar */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotColorbarPtr &plotColorbar, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/plot/plotGraphLayer.cpp",
    "content": "/***********************************************/\n/**\n* @file plotGraphLayer.cpp\n*\n* @brief Lines, points and polygons in 2d plots.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2016-07-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotGraphLayer\n\n#include \"base/import.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/system.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"plot/plotMisc.h\"\n#include \"plotGraphLayer.h\"\n\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerLinesAndPoints = R\"(\n\\subsection{LinesAndPoints}\\label{plotGraphLayerType:linesAndPoints}\nDraws a \\configClass{line}{plotLineType} and/or points (\\configClass{symbol}{plotSymbolType})\nof xy data. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nIf no \\configClass{color}{plotColorType} of the \\configClass{symbol}{plotSymbolType}\nis given a \\configClass{colorbar}{plotColorbarType}\nis required and the color is determined by \\config{valueZ}.\nAdditionally a vertical error bar can be plotted at each data point with\nsize \\config{valueErrorBar}.\n\nSee \\program{Gravityfield2AreaMeanTimeSeries} for an example plot.\n)\";\n\nclass PlotGraphLayerLinesAndPoints : public PlotGraphLayer\n{\nprotected:\n  std::pair<std::string, VariableList> description;\n  PlotLinePtr   line;\n  PlotSymbolPtr symbol;\n  Bool          hasZValues, hasErrors;\n\npublic:\n  PlotGraphLayerLinesAndPoints(Config &config);\n  Bool requiresColorBar()   const override {return hasZValues;}\n  std::string scriptEntry() const override;\n  std::string legendEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerLinesAndPoints::PlotGraphLayerLinesAndPoints(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    ExpressionVariablePtr exprX, exprY, exprZ, exprError;\n\n    readConfig(config, \"inputfileMatrix\",  fileName,     Config::MUSTSET,  \"\",      \"each line contains x,y\");\n    readConfig(config, \"valueX\",           exprX,        Config::OPTIONAL, \"data0\", \"expression for x-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueY\",           exprY,        Config::MUSTSET,  \"data1\", \"expression for y-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueZ\",           exprZ,        Config::OPTIONAL, \"\",      \"expression for the colorbar\");\n    readConfig(config, \"valueErrorBar\",    exprError,    Config::OPTIONAL, \"\",      \"expression for error bars (input columns are named data0, data1, ...)\");\n    readConfig(config, \"description\",      description,  Config::OPTIONAL, \"\",      \"text of the legend\");\n    readConfig(config, \"line\",             line,         Config::OPTIONAL, \"solid\", \"\");\n    readConfig(config, \"symbol\",           symbol,       Config::OPTIONAL, \"\",      \"\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,  \"0\",     \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    hasZValues = symbol && symbol->requiresColorBar() && exprZ;\n    hasErrors  = (exprError != nullptr);\n\n    // tests\n    if(!line && !symbol)\n      throw(Exception(\"At least one of line and symbol must be set.\"));\n    if(symbol && symbol->requiresColorBar() && !exprZ)\n      throw(Exception(\"valueZ is needed to determine color of line/symbol\"));\n    if(!hasZValues)\n      exprZ = nullptr;\n\n    // check if file exists\n    // --------------------\n    if(!System::exists(fileName))\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (file not found)\";\n      logWarning<<\"file <\"<<fileName<<\"> not found!\"<<Log::endl;\n      return;\n    }\n\n    // read data\n    // ---------\n    Matrix A;\n    readFileMatrix(fileName, A);\n\n    if(!A.size())\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (empty file)\";\n      logWarning<<\"file <\"<<fileName<<\"> is empty!\"<<Log::endl;\n      return;\n    }\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(A, varList);\n    try {description.second += varList; description.first = StringParser::parse(description.first, description.second);} catch(std::exception &) {}\n    for(ExpressionVariablePtr expr : {exprX, exprY, exprZ, exprError})\n      if(expr) expr->simplify(varList);\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(A.rows(), 2+hasZValues+hasErrors);\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      UInt idx = 0;\n      evaluateDataVariables(A, i, varList);\n      if(!exprX)\n        data(i, idx++) = static_cast<Double>(i); // default: index\n      for(auto expression : {exprX, exprY, exprZ, exprError})\n        if(expression)\n          data(i, idx++) = expression->evaluate(varList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerLinesAndPoints::scriptEntry() const\n{\n  try\n  {\n    if(!data.size())\n      return std::string();\n\n    std::stringstream ss;\n    if(hasErrors)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -i0,1,\"<<(hasZValues ? 3 : 2)<<\" -Sc1p -Ey/1p -O -K >> groopsPlot.ps\"<<std::endl;\n    if(line)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -W\"<<line->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    if(symbol)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -S\"<<symbol->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerLinesAndPoints::legendEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    if(description.first.empty() || (!line && !symbol))\n      return ss.str();\n    if(line)\n      ss<<\"S 0.3c - 0.5c - \"<<line->str()<<\" 0.7c \" ;\n    if(symbol)\n    {\n      if(line)\n        ss<<std::endl<<\"G -1l\"<<std::endl;\n      ss<<\"S 0.3c \"<<symbol->legendStr()<<\"\\t0.7c\\t\";\n    }\n    ss<<description.first<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerErrorEnvelope = R\"(\n\\subsection{ErrorEnvelope}\nDraws a symmetrical envelope around \\config{valueY} as function of \\config{valueX}\nusing deviations \\config{valueErrors}.\nThe standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nThe data line itself is not plotted but must be added as extra\n\\configClass{layer:linesAndPoints}{plotGraphLayerType:linesAndPoints}.\n)\";\n\nclass PlotGraphLayerErrorEnvelope : public PlotGraphLayer\n{\nprotected:\n  std::pair<std::string, VariableList> description;\n  PlotColorPtr fillColor;\n  PlotLinePtr  edgeLine;\n\npublic:\n  PlotGraphLayerErrorEnvelope(Config &config);\n  std::string scriptEntry() const override;\n  std::string legendEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerErrorEnvelope::PlotGraphLayerErrorEnvelope(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    ExpressionVariablePtr exprX, exprY, exprErrors;\n\n    readConfig(config, \"inputfileMatrix\",  fileName,     Config::MUSTSET,  \"\",      \"each line contains x,y\");\n    readConfig(config, \"valueX\",           exprX,        Config::OPTIONAL, \"data0\", \"expression for x-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueY\",           exprY,        Config::MUSTSET,  \"data1\", \"expression for y-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueErrors\",      exprErrors,   Config::MUSTSET,  \"data2\", \"expression for error values\");\n    readConfig(config, \"description\",      description,  Config::OPTIONAL, \"\",      \"text of the legend\");\n    readConfig(config, \"fillColor\",        fillColor,    Config::OPTIONAL, \"gray\",  \"fill color of the envelope\");\n    readConfig(config, \"edgeLine\",         edgeLine,     Config::OPTIONAL, \"\",      \"edge line style of the envelope\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,  \"0\",     \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    if(!fillColor && !edgeLine)\n      throw(Exception(\"At least one of fillColor and edgeLine must be set.\"));\n\n    // check if file exists\n    // --------------------\n    if(!System::exists(fileName))\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (file not found)\";\n      logWarning<<\"file <\"<<fileName<<\"> not found!\"<<Log::endl;\n      return;\n    }\n\n    // read data\n    // ---------\n    Matrix A;\n    readFileMatrix(fileName, A);\n\n    if(!A.size())\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (empty file)\";\n      logWarning<<\"file <\"<<fileName<<\"> is empty!\"<<Log::endl;\n      return;\n    }\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(A, varList);\n    try {description.second += varList; description.first = StringParser::parse(description.first, description.second);} catch(std::exception &) {}\n\n    std::vector<ExpressionVariablePtr> expressions = {exprX, exprY, exprErrors};\n    for(ExpressionVariablePtr expr : expressions)\n      if(expr) expr->simplify(varList);\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(A.rows(), 3);\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      evaluateDataVariables(A, i, varList);\n      data(i, 0) = static_cast<Double>(i); // default: index\n      for(UInt k=0; k<expressions.size(); k++)\n        if(expressions.at(k))\n          data(i, k) = expressions.at(k)->evaluate(varList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerErrorEnvelope::scriptEntry() const\n{\n  try\n  {\n    if(!data.size())\n      return std::string();\n\n    std::stringstream ss;\n    ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -L+d\";\n    if(edgeLine)\n      ss<<\"+p\"<<edgeLine->str();\n    if(fillColor)\n      ss<<\" -G\"<<fillColor->str();\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerErrorEnvelope::legendEntry() const\n{\n  try\n  {\n    if(description.first.empty())\n      return std::string();\n\n    std::stringstream ss;\n    ss<<\"S 0.3c s 0.5c \"<<(fillColor ? fillColor->str() : \"-\"s)<<\" \";\n    if(edgeLine)\n      ss<<edgeLine->str();\n    else\n      ss<<\"0p,\"<<fillColor->str();\n    ss<<\"\\t0.7c\\t\"<<description.first<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerBars = R\"(\n\\subsection{Bars}\nCreates a bar plot with vertical or \\config{horizontal} bars out of the given\nx- and y-values. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nThe bars ranges from \\config{valueBase} (can be also an expression) to the \\config{valueY}.\nIf no \\configClass{color}{plotColorType} is given a \\configClass{colorbar}{plotColorbarType}\nis required and the color is determined by \\config{valueZ}.\n\nSee \\program{Instrument2Histogram} for an example plot.\n)\";\n\nclass PlotGraphLayerBars : public PlotGraphLayer\n{\nprivate:\n  Double       barWidth;\n  Bool         horizontal;\n  PlotColorPtr color;\n  PlotLinePtr  edgeLine;\n  std::pair<std::string, VariableList> description;\n\npublic:\n  PlotGraphLayerBars(Config &config);\n  std::string scriptEntry() const override;\n  std::string legendEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerBars::PlotGraphLayerBars(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    ExpressionVariablePtr exprX, exprY, exprZ, exprBase, exprWidth;\n\n    horizontal = FALSE;\n\n    readConfig(config, \"inputfileMatrix\",  fileName,     Config::MUSTSET,  \"\",      \"each line contains x,y\");\n    readConfig(config, \"valueX\",           exprX,        Config::OPTIONAL, \"data0\", \"expression for x-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueY\",           exprY,        Config::MUSTSET,  \"data1\", \"expression for y-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueZ\",           exprZ,        Config::OPTIONAL, \"\",      \"expression for the colorbar\");\n    readConfig(config, \"valueBase\",        exprBase,     Config::OPTIONAL, \"\",      \"base value of bars (default: minimum y-value)\");\n    readConfig(config, \"width\",            exprWidth,    Config::OPTIONAL, \"\",      \"width of bars (default: minimum x-gap)\");\n    readConfig(config, \"horizontal\",       horizontal,   Config::OPTIONAL, \"\",      \"draw horizontal bars instead of vertical\");\n    readConfig(config, \"description\",      description,  Config::OPTIONAL, \"\",      \"text of the legend\");\n    readConfig(config, \"color\",            color,        Config::OPTIONAL, \"black\", \"\");\n    readConfig(config, \"edgeLine\",         edgeLine,     Config::OPTIONAL, \"\",      \"line\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,  \"0\",     \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    // check if file exists\n    // --------------------\n    if(!System::exists(fileName))\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (file not found)\";\n      logWarning<<\"file <\"<<fileName<<\"> not found!\"<<Log::endl;\n      return;\n    }\n\n    // read data\n    // ---------\n    Matrix A;\n    readFileMatrix(fileName, A);\n\n    if(!A.size())\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (empty file)\";\n      logWarning<<\"file <\"<<fileName<<\"> is empty!\"<<Log::endl;\n      return;\n    }\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(A, varList);\n    try {description.second += varList; description.first = StringParser::parse(description.first, description.second);} catch(std::exception &) {}\n    for(ExpressionVariablePtr expr : {exprX, exprY, exprZ, exprBase, exprBase, exprWidth})\n      if(expr) expr->simplify(varList);\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(A.rows(), exprZ ? 4 : 3);\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      evaluateDataVariables(A, i, varList);\n      data(i, 0) = static_cast<Double>(i); // default: index\n      if(exprX)    data(i, 0) = exprX->evaluate(varList);\n      if(exprY)    data(i, 1) = exprY->evaluate(varList);\n      if(exprZ)    data(i, 2) = exprZ->evaluate(varList);\n      if(exprBase) data(i, exprZ ? 3 : 2) = exprBase->evaluate(varList);\n    }\n\n    // compute bar width\n    // -----------------\n    if(!exprWidth)\n    {\n      barWidth = std::numeric_limits<Double>::infinity();\n      for(UInt i=1; i<data.rows(); i++)\n        barWidth = std::min(barWidth, std::abs(data(i, horizontal ? 1 : 0) - (data(i-1, horizontal ? 1 : 0))));\n    }\n    else\n      barWidth = exprWidth->evaluate(varList);\n\n    // compute base value\n    // ------------------\n    if(!exprBase)\n      copy(Vector(data.rows(), min(data.column(horizontal ? 0 : 1))), data.column(2 +  (exprZ ? 1 : 0)));\n\n    // test z-values\n    // -------------\n    if(!color && !exprZ)\n      throw(Exception(\"valueZ is needed to determine color of line/symbol\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerBars::scriptEntry() const\n{\n  try\n  {\n    if(!data.size())\n      return std::string();\n\n    std::stringstream ss;\n    ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -S\"<<(horizontal ? \"B\" : \"b\")<<barWidth<<\"ub\";\n    if(edgeLine)\n      ss<<\" -W\"<<edgeLine->str();\n    if(color)\n      ss<<\" -G\"<<color->str();\n    else\n      ss<<\" -CgroopsPlot.cpt\";\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerBars::legendEntry() const\n{\n  try\n  {\n    if(description.first.empty())\n      return std::string();\n\n    if(!color)\n    {\n      logWarning<<\"No legend entry can be generated for bar layers when using <fromValue> as color.\"<<Log::endl;\n      return std::string();\n    }\n\n    std::stringstream ss;\n    ss<<\"S 0.3c r 5p \"<<color->str()<<\" \";\n    if(edgeLine) ss<<edgeLine->str();\n    else ss<<\"-\";\n    ss<<\"\\t0.7c\\t\"<<description.first<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerGridded = R\"(\n\\subsection{Gridded}\nCreates a regular grid of yxz values. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileMatrix}{matrix}.\nEmpty grid cells are not plotted. Cells with more than one value will be set to the mean value.\nThe grid spacing is determined by the median spacing of the input data or set by \\config{incrementX/Y}.\n\nSee \\program{Orbit2ArgumentOfLatitude} for an example plot.\n)\";\n\n/***** CLASS ***********************************/\n\nclass PlotGraphLayerGridded : public PlotGraphLayer\n{\n  Double incX, incY;\n\npublic:\n  PlotGraphLayerGridded(Config &config);\n  Bool requiresColorBar() const override {return TRUE;}\n  std::string scriptEntry() const override;\n  Double bufferX() const override {return 0.5 * incX;}\n  Double bufferY() const override {return 0.5 * incY;}\n};\n\n/***********************************************/\n\nPlotGraphLayerGridded::PlotGraphLayerGridded(Config &config)\n{\n  try\n  {\n    FileName    fileName;\n    std::string choice;\n    ExpressionVariablePtr exprX, exprY, exprZ;\n    incX = incY = NAN_EXPR;\n\n    readConfig(config, \"inputfileMatrix\",  fileName,     Config::MUSTSET,   \"\",      \"each line contains x,y,z\");\n    readConfig(config, \"valueX\",           exprX,        Config::OPTIONAL,  \"data0\", \"expression for x-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueY\",           exprY,        Config::MUSTSET,   \"data1\", \"expression for y-values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueZ\",           exprZ,        Config::MUSTSET,   \"data2\", \"expression for the colorbar\");\n    readConfig(config, \"incrementX\",       incX,         Config::OPTIONAL,  \"\",      \"the grid spacing\");\n    readConfig(config, \"incrementY\",       incY,         Config::OPTIONAL,  \"\",      \"the grid spacing\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,   \"0\",     \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    // check if file exists\n    // --------------------\n    if(!System::exists(fileName))\n    {\n      logWarning<<\"file <\"<<fileName<<\"> not found!\"<<Log::endl;\n      return;\n    }\n\n    // read data\n    // ---------\n    Matrix A;\n    readFileMatrix(fileName, A);\n\n    if(!A.size())\n    {\n      logWarning<<\"file <\"<<fileName<<\"> is empty!\"<<Log::endl;\n      return;\n    }\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(A, varList);\n\n    std::vector<ExpressionVariablePtr> expressions = {exprX, exprY, exprZ};\n    for(ExpressionVariablePtr expr : expressions)\n      if(expr) expr->simplify(varList);\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(A.rows(), (exprZ ? 3 : 2));\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      evaluateDataVariables(A, i, varList);\n      data(i, 0) = static_cast<Double>(i); // default: index\n      for(UInt k=0; k<expressions.size(); k++)\n        if(expressions.at(k))\n          data(i, k) = expressions.at(k)->evaluate(varList);\n    }\n\n    // determine sampling (median)\n    // ---------------------------\n    auto computeIncrement = [](std::vector<Double> x)\n    {\n      std::sort(x.begin(), x.end());\n      auto it = std::unique(x.begin(), x.end());\n      std::vector<Double> dx;\n      std::adjacent_difference(x.begin(), it, std::back_inserter(dx));\n      std::nth_element(dx.begin(), dx.begin()+dx.size()/2, dx.end());\n      return dx[dx.size()/2];\n    };\n\n    if(std::isnan(incX))\n      incX = computeIncrement(Vector(data.column(0)));\n    if(std::isnan(incY))\n      incY = computeIncrement(Vector(data.column(1)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerGridded::scriptEntry() const\n{\n  try\n  {\n    if(!data.size())\n      return std::string();\n\n    const Double minX = min(data.column(0)) - bufferX();\n    const Double maxX = max(data.column(0)) + bufferX();\n    const Double minY = min(data.column(1)) - bufferY();\n    const Double maxY = max(data.column(1)) + bufferY();\n\n    std::stringstream ss;\n    ss<<\"gmt xyz2grd \"<<dataFileName<<\" -bi3d -G\"<<dataFileName<<\".grd -Vn\";\n    ss<<\" -r -I\"<<incX<<\"=/\"<<incY<<\"= -R\"<<minX<<\"/\"<<maxX<<\"/\"<<minY<<\"/\"<<maxY<<std::endl;\n    ss<<\"gmt grdimage \"<<dataFileName<<\".grd -Q -J -R\"<<PlotBasics::scriptVariable(\"range\")<<\" -CgroopsPlot.cpt\";\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerRectangle = R\"(\n\\subsection{Rectangle}\nPlots a rectangle to highlight an area.\n)\";\n\n/***** CLASS ***********************************/\n\nclass PlotGraphLayerRectangle : public PlotGraphLayer\n{\n  PlotLinePtr  edgeLine;\n  PlotColorPtr fillColor;\n  std::string  description;\n\npublic:\n  PlotGraphLayerRectangle(Config &config);\n  void        writeDataFile(const FileName &workingDirectory, UInt idxLayer, Double minX, Double maxX, Double minY, Double maxY) override;\n  std::string scriptEntry() const override;\n  std::string legendEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerRectangle::PlotGraphLayerRectangle(Config &config)\n{\n  try\n  {\n    Double x1=NAN_EXPR, y1=NAN_EXPR, x2=NAN_EXPR, y2=NAN_EXPR;\n\n    readConfig(config, \"minX\",             x1,           Config::OPTIONAL, \"\",  \"empty: left\");\n    readConfig(config, \"maxX\",             x2,           Config::OPTIONAL, \"\",  \"empty: right\");\n    readConfig(config, \"minY\",             y1,           Config::OPTIONAL, \"\",  \"empty: bottom\");\n    readConfig(config, \"maxY\",             y2,           Config::OPTIONAL, \"\",  \"empty: top\");\n    readConfig(config, \"description\",      description,  Config::OPTIONAL, \"\",  \"text of the legend\");\n    readConfig(config, \"edgeLine\",         edgeLine,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"fillColor\",        fillColor,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,  \"0\", \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    if(!fillColor && !edgeLine)\n      throw(Exception(\"At least one of fillColor and edgeLine must be set.\"));\n\n    data = Matrix(4, 2);\n    copy(Vector({x1, x1, x2, x2}), data.column(0));\n    copy(Vector({y1, y2, y2, y1}), data.column(1));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotGraphLayerRectangle::writeDataFile(const FileName &workingDirectory, UInt idxLayer, Double minX, Double maxX, Double minY, Double maxY)\n{\n  try\n  {\n    if(std::isnan(data(0, 0))) data(0, 0) = data(1, 0) = minX;\n    if(std::isnan(data(2, 0))) data(2, 0) = data(3, 0) = maxX;\n    if(std::isnan(data(0, 1))) data(0, 1) = data(3, 1) = minY;\n    if(std::isnan(data(1, 1))) data(1, 1) = data(2, 1) = maxY;\n    PlotGraphLayer::writeDataFile(workingDirectory, idxLayer, minX, maxX, minY, maxY);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerRectangle::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt psclip \"<<dataFileName<<\" -bi2d -J -R -O -K >> groopsPlot.ps\"<<std::endl;\n    ss<<\"gmt psxy \"<<dataFileName<<\" -bi2d -A -L -J -R\";\n    if(fillColor) ss<<\" -G\"<<fillColor->str();\n    if(edgeLine) ss<<\" -W\"<<edgeLine->str();\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    ss<<\"gmt psclip -C -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerRectangle::legendEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    if(!description.empty())\n    {\n      ss<<\"S 0.3c s 0.5c \"<<(fillColor ? fillColor->str() : \"-\")<<\" \";\n      if(edgeLine)\n        ss<<edgeLine->str();\n      else\n        ss<<\"0p,\"<<fillColor->str();\n      ss<<\"\\t0.7c\\t\"<<description<<std::endl;\n    }\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerText = R\"(\n\\subsection{Text}\nWrites a \\config{text} at \\config{originX} and \\config{originY} position in the graph.\nWith \\config{clip} the text is cutted at the boundaries of the plotting area.\n)\";\n\nclass PlotGraphLayerText : public PlotGraphLayer\n{\n  Double       xOffset, yOffset;\n  Double       fontSize;\n  PlotColorPtr fontColor;\n  std::string  text;\n  std::string  alignment;\n  Bool         clip;\n\npublic:\n  PlotGraphLayerText(Config &config);\n  void writeDataFile(const FileName &, UInt, Double, Double, Double, Double) override;\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerText::PlotGraphLayerText(Config &config)\n{\n  try\n  {\n    data = Matrix(1, 2);\n    readConfig(config, \"text\",             text,         Config::MUSTSET, \"\",   \"\");\n    readConfig(config, \"originX\",          data(0, 0),   Config::MUSTSET, \"\",   \"\");\n    readConfig(config, \"originY\",          data(0, 1),   Config::MUSTSET, \"\",   \"\");\n    readConfig(config, \"offsetX\",          xOffset,      Config::DEFAULT, \"0\",  \"[cm] x-offset from origin\");\n    readConfig(config, \"offsetY\",          yOffset,      Config::DEFAULT, \"0\",  \"[cm] y-offset from origin\");\n    readConfig(config, \"alignment\",        alignment,    Config::DEFAULT, \"BL\", \"L, C, R (left, center, right) and T, M, B (top, middle, bottom)\");\n    readConfig(config, \"fontSize\",         fontSize,     Config::DEFAULT, \"10\", \"[pt]\");\n    readConfig(config, \"fontColor\",        fontColor,    Config::MUSTSET, \"\",   \"\");\n    readConfig(config, \"clip\",             clip,         Config::DEFAULT, \"1\",  \"clip at boundaries\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT, \"0\",  \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotGraphLayerText::writeDataFile(const FileName &workingDirectory, UInt idxLayer, Double /*minX*/, Double /*maxX*/, Double /*minY*/, Double /*maxY*/)\n{\n  try\n  {\n    dataFileName = \"text.\"+idxLayer%\"%i.txt\"s;\n    OutFile file(workingDirectory.append(dataFileName));\n    file<<data(0, 0)<<\" \"<<data(0, 1)<<\" \"<<text;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerText::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt pstext \"<<dataFileName<<\" -F+f\"<<fontSize<<\"p,,\"<<fontColor->str()<<\"+j\"<<alignment<<\" -D\"<<xOffset<<\"/\"<<yOffset<<\" -J -R \"<<(clip ? \"\" : \"-N\")<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerDegreeAmplitudes = R\"(\n\\subsection{DegreeAmplitudes}\\label{plotGraphLayerType:degreeAmplitudes}\nPlot degree amplitudes of potential coefficients computed by \\program{Gravityfield2DegreeAmplitudes}\nor \\program{PotentialCoefficients2DegreeAmplitudes}.\nThe standard \\reference{dataVariables}{general.parser:dataVariables} are available to select\nthe data columns of \\configFile{inputfileMatrix}{matrix}. It plots a solid line for the\n\\config{valueSignal} and a dotted line for the \\config{valueError} per default.\n)\";\n\nclass PlotGraphLayerDegreeAmplitudes : public PlotGraphLayer\n{\n  std::pair<std::string, VariableList> description;\n  PlotLinePtr lineSignal, lineErrors;\n\npublic:\n  PlotGraphLayerDegreeAmplitudes(Config &config);\n  std::string scriptEntry() const override;\n  std::string legendEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerDegreeAmplitudes::PlotGraphLayerDegreeAmplitudes(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    ExpressionVariablePtr exprDegree, exprSignal, exprErrors;\n\n    readConfig(config, \"inputfileMatrix\",  fileName,     Config::MUSTSET,  \"\",      \"degree amplitudes\");\n    readConfig(config, \"valueDegree\",      exprDegree,   Config::OPTIONAL, \"data0\", \"expression for x-values (degrees) (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueSignal\",      exprSignal,   Config::OPTIONAL, \"data1\", \"expression for y-values (signal) (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueErrors\",      exprErrors,   Config::OPTIONAL, \"data2\", \"expression for y-values (formal errors)\");\n    readConfig(config, \"description\",      description,  Config::OPTIONAL, \"\",      \"text of the legend\");\n    readConfig(config, \"lineSignal\",       lineSignal,   Config::OPTIONAL, \"solid\", \"\");\n    readConfig(config, \"lineErrors\",       lineErrors,   Config::OPTIONAL, R\"({\"custom\": {\"style\":\"5_2:0\"}})\", \"\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,  \"0\",     \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    // check if file exists\n    // --------------------\n    if(!System::exists(fileName))\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (file not found)\";\n      logWarning<<\"file <\"<<fileName<<\"> not found!\"<<Log::endl;\n      return;\n    }\n\n    // read data\n    // ---------\n    Matrix A;\n    readFileMatrix(fileName, A);\n\n    if(!A.size())\n    {\n      if(description.first.empty())\n        description.first = fileName.str();\n      description.first += \" (empty file)\";\n      logWarning<<\"file <\"<<fileName<<\"> is empty!\"<<Log::endl;\n      return;\n    }\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(A, varList);\n    try {description.second += varList; description.first = StringParser::parse(description.first, description.second);} catch(std::exception &) {}\n\n    std::vector<ExpressionVariablePtr> expressions = {exprDegree, exprSignal, exprErrors};\n    for(ExpressionVariablePtr expr : expressions)\n      if(expr) expr->simplify(varList);\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(A.rows(), 3, NAN_EXPR);\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      evaluateDataVariables(A, i, varList);\n      data(i, 0) = static_cast<Double>(i); // default: index\n      for(UInt k=0; k<expressions.size(); k++)\n        if(expressions.at(k))\n          data(i, k) = expressions.at(k)->evaluate(varList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerDegreeAmplitudes::scriptEntry() const\n{\n  try\n  {\n    if(!data.size())\n      return std::string();\n\n    std::stringstream ss;\n    if(lineSignal)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -i0,1 -W\"<<lineSignal->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    if(lineErrors)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -i0,2 -W\"<<lineErrors->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerDegreeAmplitudes::legendEntry() const\n{\n  try\n  {\n    if(description.first.empty() || (!lineErrors && !lineSignal))\n      return std::string();\n\n    std::stringstream ss;\n    ss<<\"S 0.3c - 0.5c - \"<<(lineSignal ? lineSignal->str() : lineErrors->str())<<\" 0.7c \"<<description.first<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotGraphLayerDegreeAmplitudesSimple = R\"(\n\\subsection{DegreeAmplitudesSimple}\\label{plotGraphLayerType:degreeAmplitudesSimple}\nPlot degree amplitudes from a \\configClass{gravityfield}{gravityfieldType}.\nThe coefficients can be converted to different functionals with \\configClass{kernel}{kernelType}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. It plots a solid line for the degree amplitude (signal)\nand a dotted line for the formal errors per default.\n\nThis is a simplified version of\n\\configClass{layer:degreeAmplitudes}{plotGraphLayerType:degreeAmplitudes}.\n)\";\n\nclass PlotGraphLayerDegreeAmplitudesSimple : public PlotGraphLayer\n{\n  std::string description;\n  PlotLinePtr lineSignal, lineErrors;\n\npublic:\n  PlotGraphLayerDegreeAmplitudesSimple(Config &config);\n  std::string scriptEntry() const override;\n  std::string legendEntry() const override;\n};\n\n/***********************************************/\n\nPlotGraphLayerDegreeAmplitudesSimple::PlotGraphLayerDegreeAmplitudesSimple(Config &config)\n{\n  try\n  {\n    enum DegreeType {RMS, CUMMULATE, MEDIAN};\n    DegreeType      degreeType = RMS;\n    UInt            minDegree, maxDegree = INFINITYDEGREE;\n    Time            time;\n    GravityfieldPtr gravityfield;\n    KernelPtr       kernel;\n\n    readConfig(config, \"gravityfield\",     gravityfield,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",           kernel,        Config::MUSTSET,  \"\", \"\");\n    std::string choice;\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"type of variances\"))\n    {\n      if(readConfigChoiceElement(config, \"rms\",          choice, \"degree amplitudes (square root of degree variances)\")) degreeType = RMS;\n      if(readConfigChoiceElement(config, \"accumulation\", choice, \"cumulate variances over degrees\"))                     degreeType = CUMMULATE;\n      if(readConfigChoiceElement(config, \"median\",       choice, \"median of absolute values per degree\"))                degreeType = MEDIAN;\n      endChoice(config);\n    }\n    readConfig(config, \"time\",             time,         Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"minDegree\",        minDegree,    Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",        maxDegree,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"description\",      description,  Config::OPTIONAL, \"\",  \"text of the legend\");\n    readConfig(config, \"lineSignal\",       lineSignal,   Config::OPTIONAL, \"solid\", \"\");\n    readConfig(config, \"lineErrors\",       lineErrors,   Config::OPTIONAL, R\"({\"custom\": {\"style\":\"5_2:0\"}})\", \"\");\n    readConfig(config, \"plotOnSecondAxis\", onSecondAxis, Config::DEFAULT,  \"0\",     \"draw dataset on a second Y-axis (if available).\");\n    if(isCreateSchema(config)) return;\n\n    // Create potential coefficients\n    // -----------------------------\n    SphericalHarmonics harm = gravityfield->sphericalHarmonics(time, maxDegree, minDegree);\n    maxDegree = harm.maxDegree();\n    const Vector kn     = kernel->inverseCoefficients(Vector3d(0, 0, harm.R()), maxDegree, harm.isInterior());\n    const Bool hasSigma = harm.sigma2cnm().size() || harm.sigma2snm().size();\n\n    std::vector<Double> x, y, sigma;\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      const Double factor = std::pow(harm.GM()/harm.R() * kn(n), 2);\n      std::vector<Double> coefficients, formalErrors;\n      for(UInt m=0; m<=n; m++)\n      {\n        coefficients.push_back(factor * std::pow(harm.cnm()(n, m),2));\n        coefficients.push_back(factor * std::pow(harm.snm()(n, m),2));\n        if(hasSigma) formalErrors.push_back(factor * harm.sigma2cnm()(n, m));\n        if(hasSigma) formalErrors.push_back(factor * harm.sigma2snm()(n, m));\n      }\n\n      // degree variances\n      // ----------------\n      x.push_back(n);\n      if((degreeType == RMS) || (degreeType == CUMMULATE))\n      {\n        y.push_back(std::sqrt(std::accumulate(coefficients.begin(), coefficients.end(), 0.)));\n        if(hasSigma)\n          sigma.push_back(std::sqrt(std::accumulate(formalErrors.begin(), formalErrors.end(), 0.)));\n      }\n      else if(degreeType == MEDIAN)\n      {\n        auto vectorMedian = [](std::vector<Double> &data)\n        {\n          std::partial_sort(data.begin(), data.begin()+data.size()/2+1, data.end());\n          return (data.size()%2) ? data.at(data.size()/2) : (0.5*(data.at(data.size()/2-1)+data.at(data.size()/2)));\n        };\n        y.push_back(std::sqrt((2*n+1)*vectorMedian(coefficients)));\n        if(hasSigma)\n          sigma.push_back(std::sqrt((2*n+1)*vectorMedian(formalErrors)));\n      }\n    } // for(n)\n\n    if(degreeType == CUMMULATE)\n    {\n      auto vectorAccumulate = [](std::vector<Double> &data)\n      {\n        std::for_each(data.begin(), data.end(), [](Double &v) {v = v*v;});\n        std::partial_sum(data.begin(), data.end(), data.begin());\n        std::for_each(data.begin(), data.end(), [](Double &v) {v = std::sqrt(v);});\n      };\n      vectorAccumulate(y);\n      if(hasSigma)\n        vectorAccumulate(sigma);\n    }\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(x.size(), 3, NAN_EXPR);\n    copy(Vector(x), data.column(0));\n    copy(Vector(y), data.column(1));\n    if(hasSigma) copy(Vector(sigma), data.column(2));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerDegreeAmplitudesSimple::scriptEntry() const\n{\n  try\n  {\n    if(!data.size())\n      return std::string();\n\n    std::stringstream ss;\n    if(lineSignal)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -i0,1 -W\"<<lineSignal->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    if(lineErrors)\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<data.columns()<<\"d -J -R -i0,2 -W\"<<lineErrors->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotGraphLayerDegreeAmplitudesSimple::legendEntry() const\n{\n  try\n  {\n    if(description.empty() || (!lineErrors && !lineSignal))\n      return std::string();\n\n    std::stringstream ss;\n    ss<<\"S 0.3c - 0.5c - \"<<(lineSignal ? lineSignal->str() : lineErrors->str())<<\" 0.7c \"<<description<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(PlotGraphLayer, \"plotGraphLayerType\",\n                      PlotGraphLayerLinesAndPoints,\n                      PlotGraphLayerErrorEnvelope,\n                      PlotGraphLayerBars,\n                      PlotGraphLayerGridded,\n                      PlotGraphLayerRectangle,\n                      PlotGraphLayerText,\n                      PlotGraphLayerDegreeAmplitudes,\n                      PlotGraphLayerDegreeAmplitudesSimple)\n\nGROOPS_READCONFIG_CLASS(PlotGraphLayer, \"plotGraphLayerType\")\n\n/***********************************************/\n\nPlotGraphLayerPtr PlotGraphLayer::create(Config &config, const std::string &name)\n{\n  try\n  {\n    PlotGraphLayerPtr plotGraphLayer;\n    std::string  type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"lines, points and polygons\");\n    if(readConfigChoiceElement(config, \"linesAndPoints\",   type, \"line/points\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerLinesAndPoints(config));\n    if(readConfigChoiceElement(config, \"errorEnvelope\",    type, \"error envelope for line plots\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerErrorEnvelope(config));\n    if(readConfigChoiceElement(config, \"bars\",             type, \"bar graph\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerBars(config));\n    if(readConfigChoiceElement(config, \"gridded\",          type, \"mesh data\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerGridded(config));\n    if(readConfigChoiceElement(config, \"rectangle\",        type, \"draw rectangle\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerRectangle(config));\n    if(readConfigChoiceElement(config, \"text\",             type, \"text\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerText(config));\n    if(readConfigChoiceElement(config, \"degreeAmplitudes\", type, \"degree amplitudes of a gravity field\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerDegreeAmplitudes(config));\n    if(readConfigChoiceElement(config, \"degreeAmplitudesSimple\", type, \"degree amplitudes of a gravity field\"))\n      plotGraphLayer = PlotGraphLayerPtr(new PlotGraphLayerDegreeAmplitudesSimple(config));\n    endChoice(config);\n\n    return plotGraphLayer;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotGraphLayer::getIntervalX(Bool isLogarithmic, Double &minX, Double &maxX) const\n{\n  try\n  {\n    for(UInt i=0; i<data.rows(); i++)\n      if(!std::isnan(data(i, 0)) && (!isLogarithmic || (data(i, 0) > 0)))\n      {\n        minX = std::min(minX, data(i, 0)-bufferX());\n        maxX = std::max(maxX, data(i, 0)+bufferX());\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotGraphLayer::getIntervalY(Bool isLogarithmic, Double minX, Double maxX, Double &minY, Double &maxY) const\n{\n  try\n  {\n    for(UInt i=0; i<data.rows(); i++)\n      if((minX <= data(i, 0)) && (data(i, 0) <= maxX))\n        if(!std::isnan(data(i, 1)) && (!isLogarithmic || (data(i, 1) > 0)))\n        {\n          minY = std::min(minY, data(i, 1)-bufferY());\n          maxY = std::max(maxY, data(i, 1)+bufferY());\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotGraphLayer::getIntervalZ(Bool isLogarithmic, Double minX, Double maxX, Double minY, Double maxY, Double &minZ, Double &maxZ) const\n{\n  try\n  {\n    if(!requiresColorBar())\n      return;\n\n    UInt   count =  0;\n    Double avg   =  0.;\n    for(UInt i=0; i<data.rows(); i++)\n      if((minX <= data(i, 0)) && (data(i, 0) <= maxX) && (minY <= data(i, 1)) && (data(i, 1) <= maxY))\n        if(!std::isnan(data(i, 2)) && (!isLogarithmic || (data(i, 2) > 0)))\n        {\n          minZ  = std::min(minZ, data(i, 2));\n          maxZ  = std::max(maxZ, data(i, 2));\n          avg  += std::fabs(data(i, 2));\n          count++;\n        }\n    avg /= count;\n\n    if(!isLogarithmic)\n    {\n      minZ = (minZ > 0) ? 0 : -3*avg;\n      maxZ = +3*avg;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotGraphLayer::writeDataFile(const FileName &workingDirectory, UInt idxLayer, Double /*minX*/, Double /*maxX*/, Double /*minY*/, Double /*maxY*/)\n{\n  try\n  {\n    dataFileName = \"data.\"+idxLayer%\"%i.dat\"s;\n    OutFile file(workingDirectory.append(dataFileName), std::ios::out | std::ios::binary);\n    for(UInt i=0; i<data.rows(); i++)\n      for(UInt k=0; k<data.columns(); k++)\n        file.write(reinterpret_cast<char *>(&data(i, k)), sizeof(Double));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotGraphLayer.h",
    "content": "/***********************************************/\n/**\n* @file plotGraphLayer.h\n*\n* @brief Lines, points in 2d plots.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2016-07-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTGRAPHLAYER__\n#define __GROOPS_PLOTGRAPHLAYER__\n\n// Latex documentation\n#ifdef DOCSTRING_PlotGraphLayer\nstatic const char *docstringPlotGraphLayer = R\"(\n\\section{PlotGraphLayer}\\label{plotGraphLayerType}\nDefines the content of an xy-plot of \\program{PlotGraph}.\nMultiple layers are are plotted sequentially. With \\config{plotOnSecondAxis}\nthe alternative y-axis on the right hand side can be selected if provided.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass PlotGraphLayer;\ntypedef std::shared_ptr<PlotGraphLayer> PlotGraphLayerPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Lines, points in 2d plots.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotGraphLayer\n{\nprotected:\n  FileName dataFileName;\n  Matrix   data;\n  Bool     onSecondAxis;\n\n  virtual Double bufferX() const {return 0;}\n  virtual Double bufferY() const {return 0;}\n\npublic:\n  virtual ~PlotGraphLayer() {}\n\n  Bool drawOnSecondAxis() const {return onSecondAxis;}\n  virtual Bool requiresColorBar() const {return FALSE;}\n  virtual void getIntervalX(Bool isLogarithmic, Double &minX, Double &maxX) const;\n  virtual void getIntervalY(Bool isLogarithmic, Double minX, Double maxX, Double &minY, Double &maxY) const;\n  virtual void getIntervalZ(Bool isLogarithmic, Double minX, Double maxX, Double minY, Double maxY, Double &minZ, Double &maxZ) const;\n  virtual void writeDataFile(const FileName &workingDirectory, UInt idxLayer, Double minX, Double maxX, Double minY, Double maxY);\n  virtual std::string scriptEntry() const = 0;\n  virtual std::string legendEntry() const {return std::string();}\n\n  /** @brief creates an derived instance of this class. */\n  static PlotGraphLayerPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates a class PlotGraphLayer.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotGraphLayer is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotGraphLayer Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotGraphLayer */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotGraphLayerPtr &plotGraphLayer, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/plot/plotLegend.cpp",
    "content": "/***********************************************/\n/**\n* @file plotLegend.cpp\n*\n* @brief Legend.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2020-05-03\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotLegend\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/file.h\"\n#include \"plot/plotMisc.h\"\n#include \"plotLegend.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(PlotLegend, \"plotLegendType\")\nGROOPS_READCONFIG_CLASS(PlotLegend, \"plotLegendType\")\n\n/***********************************************/\n\nPlotLegend::PlotLegend(Config &config, const std::string &name)\n{\n  try\n  {\n    height = 0;\n\n    readConfigSequence(config, name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"width\",       width,     Config::DEFAULT,  \"10\",   \"legend width [cm]\");\n    readConfig(config, \"height\",      height,    Config::OPTIONAL, \"\",     \"legend height [cm] (default: estimated)\");\n    readConfig(config, \"positionX\",   positionX, Config::DEFAULT,  \"1.05\", \"legend x-position in normalized (0-1) coordinates.\");\n    readConfig(config, \"positionY\",   positionY, Config::DEFAULT,  \"1.0\",  \"legend y-position in normalized (0-1) coordinates.\");\n    readConfig(config, \"anchorPoint\", anchor,    Config::DEFAULT,  \"TL\",   \"Two character combination of L, C, R (for left, center, or right) and T, M, B for top, middle, or bottom. e.g., TL for top left\");\n    readConfig(config, \"columns\",     ncolumns,  Config::DEFAULT,  \"1\",    \"number of columns in legend\");\n    readConfig(config, \"textColor\",   textColor, Config::OPTIONAL, \"\",     \"color of the legend text\");\n    readConfig(config, \"fillColor\",   fillColor, Config::OPTIONAL, \"\",     \"fill color of the legend box\");\n    readConfig(config, \"edgeLine\",    edgeLine,  Config::OPTIONAL, \"\",     \"style of the legend box edge\");\n    endSequence(config);\n    if(isCreateSchema(config)) return;\n\n    _hasEntries = FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotLegend::writeDataFile(const FileName &workingDirectory, const std::vector<std::string> &legendText)\n{\n  try\n  {\n    if(legendText.size()==0)\n      return;\n\n    _hasEntries = TRUE;\n    OutFile legendFile(workingDirectory.append(\"legend.txt\"));\n\n    if(textColor)\n      legendFile<<\"C \"<<textColor->str()<<std::endl;\n    legendFile<<\"N \"<<ncolumns<<std::endl;\n    for(UInt i=0; i<legendText.size(); i++)\n    {\n      std::vector<std::string> lines = String::split(legendText.at(i), '\\n');\n      for(const std::string &line : lines)\n        if(!line.empty())\n          legendFile<<line<<std::endl;\n    }\n  }\n  catch(const std::exception& e)\n  {\n    GROOPS_RETHROW(e)\n  }\n\n}\n\n/***********************************************/\n\nstd::string PlotLegend::scriptEntry() const\n{\n  try\n  {\n    if(!_hasEntries)\n      return \"\";\n\n    std::stringstream ss;\n    ss<<\"gmt pslegend legend.txt -R0/1/0/1 -JX\"<<PlotBasics::scriptVariable(\"width\")<<\"/\"<<PlotBasics::scriptVariable(\"height\");\n    ss<<\" -Dn\"<<positionX<<\"/\"<<positionY<<\"+w\"<<width<<\"c/\"<<height<<\"c+j\"<<anchor<<\"+l1.5\";\n    if(fillColor || edgeLine)\n    {\n      ss<<\" -F\";\n      if(fillColor)\n        ss<<\"+g\"<<fillColor->str();\n      if(edgeLine)\n        ss<<\"+p\"<<edgeLine->str();\n      else\n        ss<<\"+p0.0p,\"<<fillColor->str();\n    }\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotLegend.h",
    "content": "/***********************************************/\n/**\n* @file plotLegend.h\n*\n* @brief Legend.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2020-05-03\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTLEGEND__\n#define __GROOPS_PLOTLEGEND__\n\n// Latex documentation\n#ifdef DOCSTRING_PlotLegend\nstatic const char *docstringPlotLegend = R\"(\n\\section{PlotLegend}\\label{plotLegendType}\nPlot a legend of the descriptions provided in\n\\configClass{plotGraphLayer}{plotGraphLayerType} in \\program{PlotGraph}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"plot/plotMisc.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass PlotLegend;\ntypedef std::shared_ptr<PlotLegend> PlotLegendPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief A Legend for GMT plots.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotLegend\n{\n  Double       positionX, positionY;\n  UInt         ncolumns;\n  Double       width, height;\n  PlotLinePtr  edgeLine;\n  PlotColorPtr textColor, fillColor;\n  std::string  anchor;\n  Bool         _hasEntries;\n\npublic:\n  /** @brief Constructor. */\n  PlotLegend(Config &config, const std::string &name);\n\n  std::string scriptEntry() const;\n\n  void writeDataFile(const FileName &workingDirectory, const std::vector<std::string> &legendText);\n\n  /** @brief creates an derived instance of this class. */\n  static PlotLegendPtr create(Config &config, const std::string &name) {return PlotLegendPtr(new PlotLegend(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates a class PlotLegend.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotLegend is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotLegend Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotLegend */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotLegendPtr &plotLegend, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/plot/plotMapLayer.cpp",
    "content": "/***********************************************/\n/**\n* @file plotMapLayer.cpp\n*\n* @brief plot layers of maps.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2015-10-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotMapLayer\n\n#include \"base/import.h\"\n#include \"parser/dataVariables.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/system.h\"\n#include \"files/filePolygon.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"misc/miscGriddedData.h\"\n#include \"plot/plotMisc.h\"\n#include \"plotMapLayer.h\"\n\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerGrid = R\"(\n\\subsection{GriddedData}\nCreates a regular grid of xyz values. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data column of \\configFile{inputfileGriddedData}{griddedData}.\nEmpty grid cells are not plotted. Cells with more than one value will be set to the mean value.\nThe grid spacing can be determined automatically for regular rectangular grids otherwise\nit must be set with \\config{increment}. To get a better display together with some projections\nthe grid should be internally \\config{resample}d to higher resolution.\nIt is assumed that the points of \\configFile{inputfileGriddedData}{griddedData} represents centers of grid cells.\nThis assumption can be changed with \\config{gridlineRegistered} (e.g. if the data starts at the north pole).\n)\";\n\nclass PlotMapLayerGrid : public PlotMapLayer\n{\n  Angle  incrementLat, incrementLon;\n  Bool   illuminate;\n  Bool   isGridline;\n  Double intermediateDpi, threshold;\n  Char   interpolationMethod;\n  Bool   resample;\n\npublic:\n  PlotMapLayerGrid(Config &config);\n  Bool        requiresColorBar() const override {return TRUE;}\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerGrid::PlotMapLayerGrid(Config &config)\n{\n  try\n  {\n    FileName              fileNameGrid;\n    ExpressionVariablePtr exprValue;\n    std::string           choice;\n\n    resample = FALSE;\n\n    readConfig(config, \"inputfileGriddedData\", fileNameGrid, Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"value\",                exprValue,    Config::MUSTSET,  \"data0\", \"expression to compute values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"increment\",            incrementLon, Config::OPTIONAL, \"\",      \"the grid spacing [degrees]\");\n    readConfig(config, \"illuminate\",           illuminate,   Config::DEFAULT,  \"0\",     \"illuminate grid\");\n    if(readConfigSequence(config, \"resample\", Config::OPTIONAL, \"\", \"\"))\n    {\n      resample = TRUE;\n      readConfig(config, \"intermediateDpi\", intermediateDpi, Config::DEFAULT, \"100\", \"oversample grid for a smoother visual effect\");\n      if(readConfigChoice(config, \"interpolationMethod\",  choice, Config::MUSTSET, \"\", \"interpolation method for oversampling\"))\n      {\n        if(readConfigChoiceElement(config, \"bspline\",  choice, \"B-Spline interpolation\"))             interpolationMethod = 'b';\n        if(readConfigChoiceElement(config, \"bicubic\",  choice, \"bicubic interpolation\"))              interpolationMethod = 'c';\n        if(readConfigChoiceElement(config, \"bilinear\", choice, \"bilinear interpolation\"))             interpolationMethod = 'l';\n        if(readConfigChoiceElement(config, \"nearest\",  choice, \"nearest neighbour interpolation\"))    interpolationMethod = 'n';\n        endChoice(config);\n      }\n      readConfig(config, \"threshold\", threshold, Config::DEFAULT, \"0.5\", \"A threshold of 1.0 requires all (4 or 16) nodes involved in interpolation to be non-NaN. 0.5 will interpolate about half way from a non-NaN value; 0.1 will go about 90% of the way.\");\n      endSequence(config);\n    }\n    readConfig(config, \"gridlineRegistered\", isGridline, Config::DEFAULT,  \"0\", \"treat input as point values instead of cell means\");\n    if(isCreateSchema(config)) return;\n\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    points = grid.points;\n    areas  = grid.areas;\n\n    if(!points.size() || !grid.values.size())\n      throw(Exception(\"<\"+fileNameGrid.str()+\"> has no values.\"));\n\n    // try to define grid spacing\n    // --------------------------\n    incrementLat = incrementLon;\n    if(incrementLon <= 0)\n    {\n      std::vector<Angle>  lambda, phi;\n      std::vector<Double> radius;\n      if(!grid.isRectangle(lambda, phi, radius))\n         throw(Exception(\"'increment' must be set for non rectangular grids\"));\n\n      Vector dLambda(lambda.size()-1);\n      for(UInt k=0; k<dLambda.size(); k++)\n        dLambda(k) = std::fabs(std::remainder(lambda.at(k+1)-lambda.at(k), 2*PI));\n      incrementLon = mean(dLambda);\n\n      Angle  lon;\n      Double h;\n      for(UInt i=0; i<phi.size(); i++)\n        grid.ellipsoid(polar(Angle(0.), phi.at(i), radius.at(i)), lon, phi.at(i), h);  // geocentric -> ellipsoidal\n\n      Vector dPhi(phi.size()-1);\n      for(UInt i=0; i<dPhi.size(); i++)\n        dPhi(i) = std::fabs(phi.at(i+1)-phi.at(i));\n      incrementLat = mean(dPhi);\n    }\n\n    // evaluate expression\n    // -------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    exprValue->simplify(varList);\n\n    data = Matrix(points.size(), 1);\n    for(UInt i=0; i<points.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      data(i, 0) = exprValue->evaluate(varList);\n    }\n\n    if(!isGridline)\n    {\n      bufferLon = 0.5 * incrementLon;\n      bufferLat = 0.5 * incrementLat;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerGrid::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt xyz2grd -bi3d \"<<dataFileName<<\" -G\"<<dataFileName<<\".grd -Vn -I\"<<incrementLon*RAD2DEG*3600.<<\"s/\"<<incrementLat*RAD2DEG*3600.<<\"s -R\"<<PlotBasics::scriptVariable(\"region\")<<(isGridline ? \"\" : \" -r\")<<std::endl;\n    if(illuminate)\n      ss<<\"gmt grdgradient \"<<dataFileName<<\".grd -Nt0.8 -A45/315 -G\"<<dataFileName<<\".intense.grd\"<<std::endl;\n    ss<<\"gmt grdimage \"<<dataFileName<<\".grd\";\n    if(resample)\n      ss<<\" -E\"<<intermediateDpi<<\" -n\"<<interpolationMethod<<\"+bg+t\"<<threshold;\n    ss<<\" -Q -J -R -B -CgroopsPlot.cpt\";\n    if(illuminate)\n      ss<<\" -I\"<<dataFileName<<\".intense.grd\";\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerPoints = R\"(\n\\subsection{Points}\\label{plotMapLayerType:points}\nDraws points (\\configClass{symbol}{plotSymbolType}) and/or \\configClass{line}{plotLineType}s\nbetween the points. If no \\configClass{color}{plotColorType} of the \\configClass{symbol}{plotSymbolType}\nis given a \\configClass{colorbar}{plotColorbarType} is required and the color is determined\nby the \\config{value} expression. The standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data column of \\configFile{inputfileGriddedData}{griddedData}.\n)\";\n\nclass PlotMapLayerPoints : public PlotMapLayer\n{\n  PlotLinePtr   line;\n  PlotSymbolPtr symbol;\n  Bool greatCircle;\n\npublic:\n  PlotMapLayerPoints(Config &config);\n  Bool        requiresColorBar() const override {return data.columns();}\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerPoints::PlotMapLayerPoints(Config &config)\n{\n  try\n  {\n    FileName              fileNameGrid;\n    ExpressionVariablePtr exprValue;\n\n    readConfig(config, \"inputfileGriddedData\", fileNameGrid, Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"value\",                exprValue,    Config::OPTIONAL, \"data0\", \"expression to compute color (input columns are named data0, data1, ...)\");\n    readConfig(config, \"symbol\",               symbol,       Config::OPTIONAL, \"1\",     \"\");\n    readConfig(config, \"line\",                 line,         Config::OPTIONAL, \"\",      \"style of connecting lines\");\n    readConfig(config, \"drawLineAsGreatCircle\",greatCircle,  Config::DEFAULT,  \"1\",     \"draw connecting lines as great circles (otherwise, a straight line is drawn instead)\");\n    if(isCreateSchema(config)) return;\n\n    // tests\n    if(!line && !symbol)\n      throw(Exception(\"At least one of line and symbol must be set.\"));\n    if(symbol && symbol->requiresColorBar() && !exprValue)\n      throw(Exception(\"value is needed to determine color of line/symbol\"));\n    if(!symbol || !symbol->requiresColorBar())\n      exprValue = nullptr;\n\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    points = grid.points;\n\n    // evaluate expression\n    // -------------------\n    if(exprValue)\n    {\n      VariableList varList;\n      addDataVariables(grid, varList);\n      exprValue->simplify(varList);\n\n      data = Matrix(points.size(), 1);\n      for(UInt i=0; i<points.size(); i++)\n      {\n        evaluateDataVariables(grid, i, varList);\n        data(i, 0) = exprValue->evaluate(varList);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerPoints::scriptEntry() const\n{\n  try\n  {\n    if(!points.size())\n      return \"\";\n\n    std::stringstream ss;\n    if(line)\n    {\n      ss<<\"gmt psxy -bi\"<<2+data.columns()<<\"d \"<<dataFileName<<\" -J -R -W\"<<line->str();\n      if(!greatCircle) ss<<\" -A\";\n      ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    }\n    if(symbol)\n      ss<<\"gmt psxy -bi\"<<2+data.columns()<<\"d \"<<dataFileName<<\" -J -R -S\"<<symbol->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotMapLayerArrows = R\"(\n\\subsection{Arrows}\nDraws an arrow for each point in \\configFile{inputfileGriddedData}{griddedData}.\nThe arrows are defined by the expressions \\config{valueNorth/East}.\nThe standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the correspondent data columns of \\configFile{inputfileGriddedData}{griddedData}.\nThe \\config{scale} factor converts the input units to cm in the plot.\nIf no \\configClass{color}{plotColorType} is given a \\configClass{colorbar}{plotColorbarType} is required\nand the color is determined by the \\config{value} expression.\nWith \\config{scaleArrow} a reference arrow as legend can be plotted inside or outside the map.\n)\";\n\nclass PlotMapLayerArrows : public PlotMapLayer\n{\n  Double       scale;\n  Double       penSize;\n  Double       headSize;\n  PlotColorPtr penColor;\n  Double       scaleArrowOriginX;\n  Double       scaleArrowOriginY;\n  Double       scaleArrowLength;\n  std::string  scaleArrowUnit;\n  std::string  scaleArrowLabel;\n  Bool         drawScaleArrow;\n  Bool         hasZValues;\n\npublic:\n  PlotMapLayerArrows(Config &config);\n  Bool        requiresColorBar() const override {return hasZValues;}\n  std::string scriptEntry() const override;\n  std::string legendEntry(const FileName &workingDirectory, UInt idxLayer) const override;\n};\n\n/***********************************************/\n\nPlotMapLayerArrows::PlotMapLayerArrows(Config &config)\n{\n  try\n  {\n    drawScaleArrow = FALSE;\n\n    FileName fileNameGrid;\n    ExpressionVariablePtr exprValueNorth, exprValueEast, exprValue;\n\n    readConfig(config, \"inputfileGriddedData\", fileNameGrid,   Config::MUSTSET,  \"\",      \"grid file with north and east values for arrows\");\n    readConfig(config, \"valueNorth\",           exprValueNorth, Config::MUSTSET,  \"data0\", \"expression to compute north values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"valueEast\",            exprValueEast,  Config::MUSTSET,  \"data1\", \"expression to compute east values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"value\",                exprValue,      Config::OPTIONAL, \"\",      \"expression to compute arrow color (input columns are named data0, data1, ...)\");\n    readConfig(config, \"scale\",                scale,          Config::DEFAULT,  \"50\",    \"[cm per input unit] length scale factor\");\n    readConfig(config, \"penSize\",              penSize,        Config::MUSTSET,  \"1\",     \"[pt] width of arrow shaft\");\n    readConfig(config, \"headSize\",             headSize,       Config::MUSTSET,  \"5\",     \"[pt] size of arrow head, 0: no head, negative: reverse head\");\n    readConfig(config, \"color\",                penColor,       Config::OPTIONAL, \"\",      \"empty: from value\");\n    if(readConfigSequence(config, \"scaleArrow\", Config::OPTIONAL, \"1\", \"draw an arrow for scale reference\"))\n    {\n      readConfig(config, \"originX\", scaleArrowOriginX, Config::MUSTSET,  \"0.055\", \"[0-1] 0: left, 1: right\");\n      readConfig(config, \"originY\", scaleArrowOriginY, Config::MUSTSET,  \"0.065\", \"[0-1] 0: bottom, 1: top\");\n      readConfig(config, \"length\",  scaleArrowLength,  Config::MUSTSET,  \"\",      \"in same unit as valueNorth and valueEast\");\n      readConfig(config, \"unit\",    scaleArrowUnit,    Config::MUSTSET,  \"\",      \"displayed unit text (e.g. 1 cm)\");\n      readConfig(config, \"label\",   scaleArrowLabel,   Config::OPTIONAL, \"\",      \"description of the arrows\");\n      endSequence(config);\n      drawScaleArrow = TRUE;\n    }\n    if(isCreateSchema(config)) return;\n\n    // tests\n    hasZValues = !penColor && exprValue;\n    if(!penColor && !exprValue)\n      throw(Exception(\"value is needed to determine color of arrows\"));\n    if(!hasZValues)\n      exprValue = nullptr;\n\n    // read data\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    points = grid.points;\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n\n    std::vector<ExpressionVariablePtr> expressions = {exprValue, exprValueNorth, exprValueEast};\n    for(ExpressionVariablePtr expr : expressions)\n      if(expr) expr->simplify(varList);\n\n    // evaluate expressions\n    // --------------------\n    data = Matrix(points.size(), exprValue ? 3 : 2);\n    for(UInt i=0; i<points.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      UInt idx = 0;\n      for(auto expression : expressions)\n        if(expression)\n          data(i, idx++) = expression->evaluate(varList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerArrows::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n\n    // arrows from grid file\n    if(points.size())\n    {\n      ss<<\"gmt psxy \"<<dataFileName<<\" -bi\"<<2+data.columns()<<\"d -J -R -A -SV\"<<headSize<<\"p+ea+z\"<<scale<<\"c\";\n      if(hasZValues)\n        ss<<\" -W\"<<penSize<<\"p+cl -CgroopsPlot.cpt\";\n      else\n        ss<<\" -W\"<<penSize<<\"p,\"<<penColor->str()<<\" -G\"<<penColor->str();\n      ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    }\n\n    if(drawScaleArrow)\n    {\n      // scale arrow\n      ss<<\"echo \"<<scaleArrowOriginX<<\" \"<<scaleArrowOriginY<<\" 90 \"<<scale*scaleArrowLength<<\"c\";\n      ss<<\" | gmt psxy -JX\"<<PlotBasics::scriptVariable(\"width\")<<\"/\"<<PlotBasics::scriptVariable(\"height\")<<\" -R0/1/0/1 -A -SV\"<<headSize<<\"p+ea+jc\";\n      if(penColor)\n        ss<<\" -W\"<<penSize<<\"p,\"<<penColor->str()<<\" -G\"<<penColor->str();\n      else\n        ss<<\" -W\"<<penSize<<\"p,black -Gblack\";\n      ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n\n      // scale arrow labels\n      ss<<\"echo \"<<scaleArrowOriginX<<\" \"<<scaleArrowOriginY<<\" CT \"<<scaleArrowUnit<<\" | gmt pstext -F+j -Dj4p -J -R -N -O -K >> groopsPlot.ps\"<<std::endl;\n      if(!scaleArrowLabel.empty())\n        ss<<\"echo \"<<scaleArrowOriginX<<\" \"<<scaleArrowOriginY<<\" CB \"<<scaleArrowLabel<<\" | gmt pstext -F+j -Dj4p -J -R -N -O -K >> groopsPlot.ps\"<<std::endl;\n      ss<<\"gmt psbasemap -J\"<<PlotBasics::scriptVariable(\"projection\")<<\" -R\"<<PlotBasics::scriptVariable(\"region\")<<\" -B -O -K >> groopsPlot.ps\"<<std::endl;\n    }\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerArrows::legendEntry(const FileName &workingDirectory, UInt idxLayer) const\n{\n  try\n  {\n    if(!drawScaleArrow)\n      return \"\";\n\n    FileName arrowDataFileName(\"arrow\"+idxLayer%\"%i.txt\"s);\n    FileName arrowLabelFileName(\"arrowLabel\"+idxLayer%\"%i.txt\"s);\n\n    std::stringstream ss;\n\n    // scale arrow\n    OutFile arrowFile(workingDirectory.append(arrowDataFileName));\n    arrowFile<<scaleArrowOriginX<<\" \"<<scaleArrowOriginY<<\" 90 \"<<scale*scaleArrowLength<<\"c\";\n    ss<<\"gmt psxy \"<<arrowDataFileName<<\" -JX\"<<PlotBasics::scriptVariable(\"width\")<<\"/\"<<PlotBasics::scriptVariable(\"height\")<<\" -R0/1/0/1 -A -SV\"<<headSize<<\"p+ea+jc\";\n\n    if(penColor)\n      ss<<\" -W\"<<penSize<<\"p,\"<<penColor->str()<<\" -G\"<<penColor->str();\n    else\n      ss<<\" -W\"<<penSize<<\"p,black -Gblack\";\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n\n    // scale arrow labels\n    OutFile arrowLabelFile(workingDirectory.append(arrowLabelFileName));\n    arrowLabelFile<<scaleArrowOriginX<<\" \"<<scaleArrowOriginY<<\" CT \"<<scaleArrowUnit;\n    if(!scaleArrowLabel.empty())\n      arrowLabelFile<<std::endl<<scaleArrowOriginX<<\" \"<<scaleArrowOriginY<<\" CB \"<<scaleArrowLabel;\n\n    ss<<\"gmt pstext \"<<arrowLabelFileName<<\" -F+j -Dj4p -J -R -N -O -K >> groopsPlot.ps\"<<std::endl;\n\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerPolygon = R\"(\n\\subsection{Polygon}\nDraws a \\configFile{inputfilePolygon}{polygon}.\nIf \\configClass{fillColor}{plotColorType} is not set and a \\config{value}\nis given the fill color is taken from a \\configClass{colorbar}{plotColorbarType}.\n)\";\n\nclass PlotMapLayerPolygon : public PlotMapLayer\n{\n  std::vector<Polygon> polygons;\n  PlotLinePtr          line;\n  PlotColorPtr         fillColor;\n  Double               value;\n  Bool                 greatCircle;\n\npublic:\n  PlotMapLayerPolygon(Config &config);\n  void boundary(const Ellipsoid &ellipsoid, Angle &minL, Angle &maxL, Angle &minB, Angle &maxB) const override;\n  void writeDataFile(const Ellipsoid &ellipsoid, const FileName &workingDirectory, UInt idxLayer) override;\n  Bool requiresColorBar() const override {return !fillColor && !std::isnan(value);}\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerPolygon::PlotMapLayerPolygon(Config &config)\n{\n  try\n  {\n    FileName fileName;\n    value = NAN_EXPR;\n\n    readConfig(config, \"inputfilePolygon\", fileName,  Config::MUSTSET,  \"{groopsDataDir}/border/\", \"\");\n    readConfig(config, \"line\",             line,      Config::OPTIONAL, \"solid\", \"style of border lines\");\n    readConfig(config, \"fillColor\",        fillColor, Config::OPTIONAL, \"\", \"polygon fill color (no fill color: determine from value if given, else: no fill)\");\n    readConfig(config, \"value\",            value,     Config::OPTIONAL, \"\", \"value to compute fill color from a colorbar (ignored if a fillColor is given)\");\n    readConfig(config, \"drawLineAsGreatCircle\", greatCircle, Config::DEFAULT, \"1\", \"draw connecting lines as great circles (otherwise, a straight line is drawn instead)\");\n    if(isCreateSchema(config)) return;\n\n    // tests\n    if(!line && !(fillColor || !std::isnan(value)) )\n      throw(Exception(\"At least one of line, fillColor or value must be set.\"));\n\n    readFilePolygon(fileName, polygons);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayerPolygon::boundary(const Ellipsoid &/*ellipsoid*/, Angle &minL, Angle &maxL, Angle &minB, Angle &maxB) const\n{\n  try\n  {\n    for(auto &p : polygons)\n      for(UInt i=0; i<p.L.size(); i++)\n      {\n        minL = std::min(minL, Angle(p.L(i)));\n        maxL = std::max(maxL, Angle(p.L(i)));\n        minB = std::min(minB, Angle(p.B(i)));\n        maxB = std::max(maxB, Angle(p.B(i)));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayerPolygon::writeDataFile(const Ellipsoid &/*ellipsoid*/, const FileName &workingDirectory, UInt idxLayer)\n{\n  try\n  {\n    dataFileName = \"polygon.\"+idxLayer%\"%i.dat\"s;\n    OutFile file(workingDirectory.append(dataFileName));\n    if(!std::isnan(value)) file<<\">-Z\"<<value<<std::endl;\n    for(auto &p : polygons)\n    {\n      for(UInt i=0; i<p.L.size(); i++)\n        file<<p.L(i)*RAD2DEG<<\" \"<<p.B(i)*RAD2DEG<<std::endl;\n      file<<\">\"<<std::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerPolygon::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt psxy \"<<dataFileName<<\" -L -J -R\";\n    if(fillColor) ss<<\" -G\"<<fillColor->str();\n    else if(!std::isnan(value)) ss<<\" -CgroopsPlot.cpt\";\n    if(line)\n    {\n      ss<<\" -W\"<<line->str();\n      if(!greatCircle) ss<<\" -A\";\n    }\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerCoast = R\"(\n\\subsection{Coast}\nPlots coastlines. GMT provides them in different \\config{resolution}s.\nFeatures with an area smaller than \\config{minArea} in $km^2$ will not be plotted.\n)\";\n\nclass PlotMapLayerCoast : public PlotMapLayer\n{\n  std::string  resolution;\n  PlotLinePtr  line;\n  PlotColorPtr landColor;\n  PlotColorPtr oceanColor;\n  UInt         minArea;\n\npublic:\n  PlotMapLayerCoast(Config &config);\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerCoast::PlotMapLayerCoast(Config &config)\n{\n  try\n  {\n    std::string choice;\n    if(readConfigChoice(config, \"resolution\", choice, Config::MUSTSET, \"medium\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"crude\",  choice)) resolution = \"c\";\n      if(readConfigChoiceElement(config, \"low\",    choice)) resolution = \"l\";\n      if(readConfigChoiceElement(config, \"medium\", choice)) resolution = \"i\";\n      if(readConfigChoiceElement(config, \"high\",   choice)) resolution = \"h\";\n      if(readConfigChoiceElement(config, \"full\",   choice)) resolution = \"f\";\n      endChoice(config);\n    }\n    readConfig(config, \"line\",       line,       Config::OPTIONAL, R\"({\"solid\": {\"width\": \"1\"}})\", \"line style for coastlines\");\n    readConfig(config, \"landColor\",  landColor,  Config::OPTIONAL, \"\",      \"fill land area\");\n    readConfig(config, \"oceanColor\", oceanColor, Config::OPTIONAL, \"\",      \"fill ocean area\");\n    readConfig(config, \"minArea\",    minArea,    Config::DEFAULT,  \"5000\", \"[km^2] features with a smaller area than this are dropped\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerCoast::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt pscoast -J -R -D\"<<resolution<<\"+ -A\"<<minArea;\n    if(line)\n      ss<<\" -W\"<<line->str();\n    if(landColor)\n      ss<<\" -G\"<<landColor->str();\n    if(oceanColor)\n      ss<<\" -S\"<<oceanColor->str();\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerRivers = R\"(\n\\subsection{Rivers}\nPlots rivers and lakes. GMT provides different classes\n(\\url{https://docs.generic-mapping-tools.org/latest/coast.html}).\n)\";\n\nclass PlotMapLayerRivers : public PlotMapLayer\n{\n  std::vector<std::string> riverclass;\n  PlotLinePtr line;\n\npublic:\n  PlotMapLayerRivers(Config &config);\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerRivers::PlotMapLayerRivers(Config &config)\n{\n  try\n  {\n    std::string choice;\n    if(readConfigChoice(config, \"class\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"riversCanalsLakes\",     choice, \"\")) riverclass.push_back(\"a\");\n      if(readConfigChoiceElement(config, \"riversCanals\",          choice, \"\")) riverclass.push_back(\"A\");\n      if(readConfigChoiceElement(config, \"permanentRiversLakes\",  choice, \"\")) riverclass.push_back(\"r\");\n      if(readConfigChoiceElement(config, \"permanentRivers\",       choice, \"\")) riverclass.push_back(\"R\");\n      if(readConfigChoiceElement(config, \"intermittentRivers\",    choice, \"\")) riverclass.push_back(\"i\");\n      if(readConfigChoiceElement(config, \"canals\",                choice, \"\")) riverclass.push_back(\"c\");\n      if(readConfigChoiceElement(config, \"singleClass\",           choice, \"\"))\n      {\n        std::vector<UInt> types;\n        readConfig(config, \"class\", types, Config::MUSTSET, \"\", \"0-10. See GMT documentation\");\n\n        for(UInt k=0; k<types.size(); k++)\n          riverclass.push_back(types.at(k)%\"%i\"s);\n      }\n      endChoice(config);\n    }\n    readConfig(config, \"line\", line, Config::MUSTSET, R\"({\"solid\": {\"width\": \"1\"}})\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerRivers::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt pscoast -J -R\";\n    for(UInt k=0; k<riverclass.size(); k++)\n      ss<<\" -I\"<<riverclass.at(k)<<\"/\"<<line->str();\n    ss<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerPolitical = R\"(\n\\subsection{PoliticalBoundary}\nPlots national boundaries. GMT provides them in different \\config{resolution}s.\n)\";\n\nclass PlotMapLayerPolitical : public PlotMapLayer\n{\n  std::string resolution;\n  PlotLinePtr line;\n\npublic:\n  PlotMapLayerPolitical(Config &config);\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerPolitical::PlotMapLayerPolitical(Config &config)\n{\n  try\n  {\n    std::string choice;\n    if(readConfigChoice(config, \"resolution\", choice, Config::MUSTSET, \"medium\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"crude\",  choice, \"\")) resolution = \"c\";\n      if(readConfigChoiceElement(config, \"low\",    choice, \"\")) resolution = \"l\";\n      if(readConfigChoiceElement(config, \"medium\", choice, \"\")) resolution = \"i\";\n      if(readConfigChoiceElement(config, \"high\",   choice, \"\")) resolution = \"h\";\n      if(readConfigChoiceElement(config, \"full\",   choice, \"\")) resolution = \"f\";\n      endChoice(config);\n    }\n    readConfig(config, \"line\", line, Config::MUSTSET, R\"({\"solid\": {\"width\": \"0.25\"}})\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerPolitical::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt pscoast -J -R -N1/\"<<line->str()<<\" -D\"<<resolution<<\"+ -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerBlueMarble = R\"(\n\\subsection{BlueMarble}\nAn image of the Earth's surface as seen from outer space -\nthe image is known as \\emph{blue marble}. The directory of \\config{inputfileChannels}\ncontains several files in different resolutions representing the Earth's surface each\nmonth throughout a year.\n\n\\fig{!hb}{0.8}{blueMarble}{fig:blueMarbleMap}{The blue marble.}\n)\";\n\nclass PlotMapLayerBlueMarble : public PlotMapLayer\n{\n  FileName fileNameImage;\n  Double   brightness;\n\n  Bool     illuminate;\n  FileName fileNameTopography;\n  Angle    azimuth, elevation;\n  Double   amplitude;\n  Double   ambient, diffuse, specular, shine;\n\npublic:\n  PlotMapLayerBlueMarble(Config &config);\n  void        writeDataFile(const Ellipsoid &ellipsoid, const FileName &workingDirectory, UInt idxLayer) override;\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerBlueMarble::PlotMapLayerBlueMarble(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileImage\",    fileNameImage,    Config::MUSTSET, \"{groopsDataDir}/plot/bluemarble/1800x900/bluemarble.05.jpg\", \"Blue Marble image file\");\n    readConfig(config, \"brightness\",        brightness,       Config::DEFAULT, \"0.0\", \"brightness of bitmap [-1, 1]\");\n    if(readConfigSequence(config, \"illuminate\", Config::OPTIONAL, \"\", \"add hillshade based on topography\"))\n    {\n      readConfig(config, \"inputfileTopography\", fileNameTopography, Config::MUSTSET, \"{groopsDataDir}/plot/bluemarble/1800x900/bluemarble.topography.grd\", \"GMT grid file containing topography.\");\n      readConfig(config, \"azimuth\",             azimuth,            Config::DEFAULT, \"315\", \"direction of lighting source [deg]\");\n      readConfig(config, \"elevation\",           elevation,          Config::DEFAULT, \"45\",  \"direction of lighting source [deg]\");\n      readConfig(config, \"ambient\",             ambient,            Config::DEFAULT, \"0.1\", \"ambient lighting\");\n      readConfig(config, \"diffuse\",             diffuse,            Config::DEFAULT, \"0.6\", \"diffuse lighting\");\n      readConfig(config, \"specular\",            specular,           Config::DEFAULT, \"0.0\", \"specular reflection\");\n      readConfig(config, \"shine\",               shine,              Config::DEFAULT, \"0.0\", \"surface shine\");\n      readConfig(config, \"amplitude\",           amplitude,          Config::DEFAULT, \"0.1\", \"scale gradient by factor\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    illuminate = !fileNameTopography.empty();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayerBlueMarble::writeDataFile(const Ellipsoid &/*ellipsoid*/, const FileName &/*workingDirectory*/, UInt idxLayer)\n{\n  dataFileName = \"blueMarble.\"+idxLayer%\"%i.dat\"s;\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerBlueMarble::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    if(illuminate)\n    {\n      ss<<\"gmt grdgradient \"<<fileNameTopography<<\" -G\"<<dataFileName;\n      ss<<\" -Em\"<<azimuth*RAD2DEG<<\"/\"<<elevation*RAD2DEG<<\"+a\"<<ambient<<\"+d\"<<diffuse<<\"+p\"<<specular<<\"+s\"<<shine<<std::endl;\n      ss<<\"gmt grdmath \"<<dataFileName<<\" \"<<amplitude<<\" MUL = \"<<dataFileName<<std::endl;\n    }\n\n    ss<<\"gmt grdimage \"<<fileNameImage;\n    if(!illuminate)\n      ss<<\" -I\"<<brightness;\n    else\n      ss<<\" -I\"<<dataFileName;\n    ss<<\" -Q -J -R -O -K >> groopsPlot.ps\"<<std::endl;\n\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringPlotMapLayerText = R\"(\n\\subsection{Text}\nWrites a \\config{text} at \\config{originLongitude} and \\config{originLatitude} position in the map.\nWith \\config{clip} the text is cutted at the boundaries of the plotting area.\n)\";\n\nclass PlotMapLayerText : public PlotMapLayer\n{\n  Angle        lat, lon;\n  Double       xOffset, yOffset;\n  Double       fontSize;\n  PlotColorPtr fontColor;\n  std::string  text;\n  std::string  alignment;\n  Bool         clip;\n\npublic:\n  PlotMapLayerText(Config &config);\n  void        writeDataFile(const Ellipsoid &ellipsoid, const FileName &workingDirectory, UInt idxLayer) override;\n  std::string scriptEntry() const override;\n};\n\n/***********************************************/\n\nPlotMapLayerText::PlotMapLayerText(Config &config)\n{\n  try\n  {\n    readConfig(config, \"text\",            text,      Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"originLongitude\", lon,       Config::MUSTSET,  \"\",   \"[deg]\");\n    readConfig(config, \"originLatitude\",  lat,       Config::MUSTSET,  \"\",   \"[deg]\");\n    readConfig(config, \"offsetX\",         xOffset,   Config::DEFAULT,  \"0\",  \"[cm] x-offset from origin\");\n    readConfig(config, \"offsetY\",         yOffset,   Config::DEFAULT,  \"0\",  \"[cm] y-offset from origin\");\n    readConfig(config, \"alignment\",       alignment, Config::DEFAULT,  \"LB\", \"L, C, R (left, center, right) and T, M, B (top, middle, bottom)\");\n    readConfig(config, \"fontSize\",        fontSize,  Config::DEFAULT,  \"10\", \"\");\n    readConfig(config, \"fontColor\",       fontColor, Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"clip\",            clip,      Config::DEFAULT,  \"1\",  \"clip at boundaries\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayerText::writeDataFile(const Ellipsoid &/*ellipsoid*/, const FileName &workingDirectory, UInt idxLayer)\n{\n  dataFileName = \"text.\"+idxLayer%\"%i.txt\"s;\n  OutFile file(workingDirectory.append(dataFileName));\n\n  file<<lon*RAD2DEG<<\" \"<<lat*RAD2DEG<<\" \"<<text;\n}\n\n/***********************************************/\n\nstd::string PlotMapLayerText::scriptEntry() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt pstext \"<<dataFileName<<\" -F+f\"<<fontSize<<\"p,,\"<<fontColor->str()<<\"+j\"<<alignment<<\" -D\"<<xOffset<<\"/\"<<yOffset<<\" -J -R \"<<(clip?\"\":\"-N\")<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(PlotMapLayer, \"plotMapLayerType\",\n                      PlotMapLayerGrid,\n                      PlotMapLayerPoints,\n                      PlotMapLayerArrows,\n                      PlotMapLayerPolygon,\n                      PlotMapLayerCoast,\n                      PlotMapLayerRivers,\n                      PlotMapLayerPolitical,\n                      PlotMapLayerBlueMarble,\n                      PlotMapLayerText)\n\nGROOPS_READCONFIG_CLASS(PlotMapLayer, \"plotMapLayerType\")\n\n/***********************************************/\n\nPlotMapLayerPtr PlotMapLayer::create(Config &config, const std::string &name)\n{\n  try\n  {\n    PlotMapLayerPtr plotMapLayer;\n    std::string     type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"plot layers\");\n    if(readConfigChoiceElement(config, \"griddedData\",       type, \"data with regular sampling\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerGrid(config));\n    if(readConfigChoiceElement(config, \"points\",            type, \"colored points\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerPoints(config));\n    if(readConfigChoiceElement(config, \"arrows\",            type, \"colored arrows\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerArrows(config));\n    if(readConfigChoiceElement(config, \"polygon\",           type, \"boundaries\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerPolygon(config));\n    if(readConfigChoiceElement(config, \"coast\",             type, \"coast lines, ...\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerCoast(config));\n    if(readConfigChoiceElement(config, \"rivers\",            type, \"major rivers\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerRivers(config));\n    if(readConfigChoiceElement(config, \"politicalBoundary\", type, \"political boundaries\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerPolitical(config));\n    if(readConfigChoiceElement(config, \"blueMarble\",        type, \"blue marble\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerBlueMarble(config));\n    if(readConfigChoiceElement(config, \"text\",              type, \"text\"))\n      plotMapLayer = PlotMapLayerPtr(new PlotMapLayerText(config));\n    endChoice(config);\n\n    return plotMapLayer;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayer::boundary(const Ellipsoid &ellipsoid, Angle &minL, Angle &maxL, Angle &minB, Angle &maxB) const\n{\n  try\n  {\n    for(UInt k=0; k<points.size(); k++)\n    {\n      Angle  lon, lat;\n      Double h;\n      ellipsoid(points.at(k), lon, lat, h);\n      minL = std::min(minL, lon-bufferLon);\n      maxL = std::max(maxL, lon+bufferLon);\n      minB = std::min(minB, lat-bufferLat);\n      maxB = std::max(maxB, lat+bufferLat);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayer::getIntervalZ(Bool isLogarithmic, Double &minZ, Double &maxZ) const\n{\n  try\n  {\n    if(!requiresColorBar() || !data.size())\n      return;\n\n    UInt   count =  0;\n    Double avg   =  0.;\n    for(UInt i=0; i<data.rows(); i++)\n      if(!std::isnan(data(i, 0)) && (!isLogarithmic || (data(i, 0) > 0)))\n      {\n        minZ  = std::min(minZ, data(i, 0));\n        maxZ  = std::max(maxZ, data(i, 0));\n        avg  += std::fabs(data(i, 0));\n        count++;\n      }\n    avg /= count;\n\n    if(!isLogarithmic)\n    {\n      minZ = (minZ >= 0) ? 0 : -3*avg;\n      maxZ = +3*avg;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlotMapLayer::writeDataFile(const Ellipsoid &ellipsoid, const FileName &workingDirectory, UInt idxLayer)\n{\n  try\n  {\n    if(!points.size())\n      return;\n\n    dataFileName = \"data.\"+idxLayer%\"%i.dat\"s;\n    OutFile file(workingDirectory.append(dataFileName), std::ios::out | std::ios::binary);\n    for(UInt i=0; i<points.size(); i++)\n    {\n      Angle  lon, lat;\n      Double h;\n      ellipsoid(points.at(i), lon, lat, h);\n      std::vector<Double> line = {lon*RAD2DEG, lat*RAD2DEG};\n      file.write(reinterpret_cast<char*>(line.data()), line.size()*sizeof(Double));\n      for(UInt k=0; k<data.columns(); k++)\n        file.write(reinterpret_cast<char*>(&data(i, k)), sizeof(Double));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayer::scriptStatisticsInfo(UInt fontSize, Double width, const FileName &workingDirectory, UInt idxLayer) const\n{\n  try\n  {\n    if(!requiresColorBar())\n      return std::string();\n\n    Double rms, avg, vmin, vmax, mean;\n    MiscGriddedData::statistics(Vector(data.column(0)), areas, rms, avg, vmin, vmax, mean);\n\n    FileName fileNameStatistics(\"statistics\"+idxLayer%\"%i.txt\"s);\n\n    OutFile statisticsFile(workingDirectory.append(fileNameStatistics));\n    statisticsFile<<\"0.5 0.0 \"<<fontSize<<\"p CB min=\"<<vmin<<\", max=\"<<vmax<<\", mean=\"<<mean<<\", rms=\"<<rms;\n\n    std::stringstream ss;\n    ss<<\"gmt pstext \"<<fileNameStatistics<<\" -F+f+j -Y-\"<<fontSize<<\"p -JX\"<<width<<\"c/\"<<fontSize<<\"p -R0/1/0/1 -N -O -K >> groopsPlot.ps \"<<PlotBasics::scriptError2Null()<<std::endl;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotMapLayer::legendEntry(const FileName &/*workingDirectory*/, UInt /*idxLayer*/) const\n{\n  try\n  {\n    return \"\";\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotMapLayer.h",
    "content": "/***********************************************/\n/**\n* @file plotMapLayer.h\n*\n* @brief plot layers of maps.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2015-10-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTMAPLAYER__\n#define __GROOPS_PLOTMAPLAYER__\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_PlotMapLayer\nstatic const char *docstringPlotMapLayer = R\"(\n\\section{PlotMapLayer}\\label{plotMapLayerType}\nDefines the content of a map of \\program{PlotMap}. Multiple layers are are plotted sequentially.\n)\";\n#endif\n\n/***** TYPES ***********************************/\n\nclass PlotMapLayer;\ntypedef std::shared_ptr<PlotMapLayer> PlotMapLayerPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Layers for maps.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotMapLayer\n{\nprotected:\n  FileName              dataFileName;\n  std::vector<Vector3d> points;\n  std::vector<Double>   areas;\n  Matrix                data;\n  Angle                 bufferLon, bufferLat;\n\npublic:\n  virtual ~PlotMapLayer() {}\n\n  virtual Bool requiresColorBar() const {return FALSE;}\n  virtual void boundary(const Ellipsoid &ellipsoid, Angle &minL, Angle &maxL, Angle &minB, Angle &maxB) const;\n  virtual void getIntervalZ(Bool isLogarithmic, Double &minZ, Double &maxZ) const;\n  virtual void writeDataFile(const Ellipsoid &ellipsoid, const FileName &workingDirectory, UInt idxLayer);\n  virtual std::string scriptStatisticsInfo(UInt fontSize, Double width, const FileName &workingDirectory, UInt idxLayer) const;\n  virtual std::string scriptEntry() const = 0;\n  virtual std::string legendEntry(const FileName &workingDirectory, UInt idxLayer) const;\n\n  /** @brief creates an derived instance of this class. */\n  static PlotMapLayerPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates a class PlotMapLayer.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotMapLayer is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotMapLayer Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotMapLayer */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotMapLayerPtr &plotMapLayer, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n\n#endif /* __GROOPS__ */\n"
  },
  {
    "path": "source/plot/plotMapProjection.cpp",
    "content": "/***********************************************/\n/**\n* @file plotMapProjection.cpp\n*\n* @brief Map projections used for plotting.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2015-10-23\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotMapProjection\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"plotMapProjection.h\"\n#include \"plotMisc.h\"\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionRobinson = R\"(\n\\subsection{Robinson}\nThe Robinson projection, presented by Arthur H. Robinson in 1963,\nis a modified cylindrical projection that is neither conformal nor equal-area.\nCentral meridian and all parallels are straight lines; other meridians are curved.\nIt uses lookup tables rather than analytic expressions to make the world map look right.\n)\";\n\nclass PlotMapProjectionRobinson : public PlotMapProjection\n{\n  Angle L0;\n\npublic:\n  PlotMapProjectionRobinson(Config &config)\n  {\n    readConfig(config, \"centralMeridian\", L0, Config::DEFAULT, \"0\", \"central meridian [degree]\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JN\"<<L0*RAD2DEG<<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n\n  Double aspectRatio() const override {return (1+1./80.)/2;}\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionMollweide = R\"(\n\\subsection{Mollweide}\nThis pseudo-cylindrical, equal-area projection was developed by Mollweide in 1805. Parallels are unequally spaced straight\nlines with the meridians being equally spaced elliptical arcs. The scale is only true along latitudes 40$^{o}$44' north and south.\nThe projection is used mainly for global maps showing data distributions.\n)\";\n\nclass PlotMapProjectionMollweide : public PlotMapProjection\n{\n  Angle L0;\n\npublic:\n  PlotMapProjectionMollweide(Config &config)\n  {\n    readConfig(config, \"centralMeridian\", L0, Config::DEFAULT, \"0\", \"central meridian [degree]\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JW\"<<L0*RAD2DEG<<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n\n  Double aspectRatio() const override {return 0.5;}\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionOrthographic = R\"(\n\\subsection{Orthographic}\nThe orthographic azimuthal projection is a perspective projection from infinite distance.\nIt is therefore often used to give the appearance of a globe viewed from space.\n)\";\n\nclass PlotMapProjectionOrthographic : public PlotMapProjection\n{\n  Angle L0, B0;\n\npublic:\n  PlotMapProjectionOrthographic(Config &config)\n  {\n    readConfig(config, \"lambdaCenter\", L0, Config::DEFAULT, \"30\", \"central point [degree]\");\n    readConfig(config, \"phiCenter\",    B0, Config::DEFAULT, \"30\", \"central point [degree]\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JG\"<<L0*RAD2DEG<<\"/\"<<B0*RAD2DEG<<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionPerspectiveSphere = R\"(\n\\subsection{Perspective sphere}\nThe orthographic azimuthal projection is a perspective projection from infinite distance.\nIt is therefore often used to give the appearance of a globe viewed from space.\n)\";\n\nclass PlotMapProjectionPerspectiveSphere : public PlotMapProjection\n{\n  Angle  L0, B0;\n  Angle  azimuth, tilt;\n  Angle  viewpointTwist, viewpointWidth, viewpointHeight;\n  Double altitude;\n\npublic:\n  PlotMapProjectionPerspectiveSphere(Config &config)\n  {\n    readConfig(config, \"lambdaCenter\",    L0,              Config::DEFAULT,  \"10\",   \"longitude of central point in degrees\");\n    readConfig(config, \"phiCenter\",       B0,              Config::DEFAULT,  \"40\",   \"latitude of central point in degrees\");\n    readConfig(config, \"altitude\",        altitude,        Config::DEFAULT,  \"1500\", \"[km]\");\n    readConfig(config, \"azimuth\",         azimuth,         Config::DEFAULT,  \"0\",    \"to the east of north of view [degrees]\");\n    readConfig(config, \"tilt\",            tilt,            Config::DEFAULT,  \"0\",    \"upward tilt of the plane of projection, if negative, then the view is centered on the horizon [degrees]\");\n    readConfig(config, \"viewpointTwist\",  viewpointTwist,  Config::DEFAULT,  \"0\",    \"clockwise twist of the viewpoint [degrees]\");\n    readConfig(config, \"viewpointWidth\",  viewpointWidth,  Config::DEFAULT,  \"0\",    \"width of the viewpoint [degrees]\");\n    readConfig(config, \"viewpointHeight\", viewpointHeight, Config::DEFAULT,  \"0\",    \"height of the viewpoint [degrees]\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JG\"<<L0*RAD2DEG<<\"/\"<<B0*RAD2DEG<<\"/\"<<altitude<<\"/\"<<azimuth*RAD2DEG<<\"/\"<<tilt*RAD2DEG\n             <<\"/\"<<viewpointTwist*RAD2DEG<<\"/\"<<viewpointWidth*RAD2DEG<<\"/\"<<viewpointHeight*RAD2DEG\n             <<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionPolar = R\"(\n\\subsection{Polar}\nStereographic projection around given central point.\n)\";\n\nclass PlotMapProjectionPolar : public PlotMapProjection\n{\n  Angle L0, B0;\n\npublic:\n  PlotMapProjectionPolar(Config &config)\n  {\n   readConfig(config, \"lambdaCenter\", L0, Config::DEFAULT, \"0\",   \"longitude of central point in degrees\");\n   readConfig(config, \"phiCenter\",    B0, Config::DEFAULT, \"-90\", \"latitude of central point in degrees\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JS\"<<L0*RAD2DEG<<\"/\"<<B0*RAD2DEG<<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionSkyplot = R\"(\n\\subsection{Skyplot}\nSkyplot used to plot azimuth/elevation data as generated by\n\\program{GnssAntennaDefinition2Skyplot} or \\program{GnssResiduals2Skyplot}.\n)\";\n\nclass PlotMapProjectionSkyplot : public PlotMapProjection\n{\npublic:\n  PlotMapProjectionSkyplot(Config &/*config*/) {}\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    if(PlotBasics::gmtVersion() >= 610)\n      ss<<\"-JP\"<<width<<\"c+a+fe\";\n    else\n      ss<<\"-JPa\"<<width<<\"cr\";\n    return ss.str();\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionUtm = R\"(\n\\subsection{UTM}\nA particular subset of the transverse Mercator is the Universal Transverse Mercator (UTM)\nwhich was adopted by the US Army for large-scale military maps.\nHere, the globe is divided into 60 zones between 84$^{o}$S and 84$^{o}$N, most of which are 6$^{o}$ wide.\nEach of these UTM zones have their unique central meridian.\n)\";\n\nclass PlotMapProjectionUtm : public PlotMapProjection\n{\n  std::string zone;\n\npublic:\n  PlotMapProjectionUtm(Config &config)\n  {\n    readConfig(config, \"zone\", zone, Config::MUSTSET, \"\", \"UTM zone code (e.g. 33N)\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JU\"<<zone<<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n\n  virtual Double aspectRatio() const override {return 0;}\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionLambert = R\"(\n\\subsection{Lambert}\nThis conic projection was designed by Lambert (1772) and has been used extensively for mapping of regions with predominantly east-west orientation.\n)\";\n\nclass PlotMapProjectionLambert : public PlotMapProjection\n{\n  Angle L0, B0, par1, par2;\n\npublic:\n  PlotMapProjectionLambert(Config &config)\n  {\n    readConfig(config, \"lambda0\", L0,   Config::MUSTSET, \"\", \"longitude of projection center [deg]\");\n    readConfig(config, \"phi0\",    B0,   Config::MUSTSET, \"\", \"latitude of projection centert [deg]\");\n    readConfig(config, \"phi1\",    par1, Config::MUSTSET, \"\", \"latitude of first standard parallel [deg]\");\n    readConfig(config, \"phi2\",    par2, Config::MUSTSET, \"\", \"latitude of first standard parallel [deg]\");\n  }\n\n  std::string scriptEntry(Double width, Double /*height*/) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JL\"<<L0*RAD2DEG<<\"/\"<<B0*RAD2DEG<<\"/\"<<par1*RAD2DEG<<\"/\"<<par2*RAD2DEG<<\"/\"<<width<<\"c\";\n    return ss.str();\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotMapProjectionLinear = R\"(\n\\subsection{Linear}\nLinear mapping of longitude/latitude to x/y (Plate Caree).\n)\";\n\nclass PlotMapProjectionLinear : public PlotMapProjection\n{\npublic:\n  PlotMapProjectionLinear(Config &/*config*/) {}\n\n  std::string scriptEntry(Double width, Double height) const override\n  {\n    std::stringstream ss;\n    ss<<\"-JX\"<<width<<\"cd/\"<<height<<\"cd\";\n    return ss.str();\n  }\n\n  virtual Double aspectRatio() const override {return 0;}\n};\n\n/***********************************************/\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(PlotMapProjection, \"plotMapProjectionType\",\n                      PlotMapProjectionRobinson,\n                      PlotMapProjectionOrthographic,\n                      PlotMapProjectionPerspectiveSphere,\n                      PlotMapProjectionPolar,\n                      PlotMapProjectionSkyplot,\n                      PlotMapProjectionUtm,\n                      PlotMapProjectionLambert,\n                      PlotMapProjectionLinear,\n                      PlotMapProjectionMollweide)\n\nGROOPS_READCONFIG_CLASS(PlotMapProjection, \"plotMapProjectionType\")\n\n/***********************************************/\n\nPlotMapProjectionPtr PlotMapProjection::create(Config &config, const std::string &name)\n{\n  try\n  {\n    PlotMapProjectionPtr proj;\n    std::string  type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"plot layers\");\n    if(readConfigChoiceElement(config, \"robinson\",     type, \"robinson projection\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionRobinson(config));\n    if(readConfigChoiceElement(config, \"orthographic\", type, \"orthographic projection\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionOrthographic(config));\n    if(readConfigChoiceElement(config, \"perspective\",  type, \"perspective sphere\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionPerspectiveSphere(config));\n    if(readConfigChoiceElement(config, \"polar\",        type, \"polar stereographic\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionPolar(config));\n    if(readConfigChoiceElement(config, \"skyplot\",      type, \"skyplot\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionSkyplot(config));\n    if(readConfigChoiceElement(config, \"linear\",       type, \"linear (plate carree) projection\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionLinear(config));\n    if(readConfigChoiceElement(config, \"Utm\",          type, \"UTM projection\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionUtm(config));\n    if(readConfigChoiceElement(config, \"lambert\",      type, \"lambert conformal conic\"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionLambert(config));\n    if(readConfigChoiceElement(config, \"mollweide\",    type, \"mollweide projection \"))\n      proj = PlotMapProjectionPtr(new PlotMapProjectionMollweide(config));\n    endChoice(config);\n\n    return proj;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotMapProjection.h",
    "content": "/***********************************************/\n/**\n* @file plotMapProjection.h\n*\n* @brief Map projections used for plotting.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2015-10-23\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTMAPROJECTION__\n#define __GROOPS_PLOTMAPROJECTION__\n\n// Latex documentation\n#ifdef DOCSTRING_PlotMapProjection\nstatic const char *docstringPlotMapProjection = R\"(\n\\section{PlotMapProjection}\\label{plotMapProjectionType}\nSelects the underlying projection of \\program{PlotMap}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass PlotMapProjection;\ntypedef std::shared_ptr<PlotMapProjection> PlotMapProjectionPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Layers for maps.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotMapProjection\n{\npublic:\n  virtual ~PlotMapProjection() {}\n\n  virtual std::string scriptEntry(Double width, Double height) const = 0;\n\n  virtual Double aspectRatio() const {return 1;}\n\n  /** @brief creates an derived instance of this class. */\n  static PlotMapProjectionPtr create(Config &config, const std::string &name);\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates a class PlotMapProjection.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotMapProjection is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotMapProjection Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotMapProjection */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotMapProjectionPtr &plotMapProjection, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/plot/plotMisc.cpp",
    "content": "/***********************************************/\n/**\n* @file plotMisc.cpp\n*\n* @brief Miscellaneous classes for plots.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2010-01-13\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_PlotColor\n#define DOCSTRING_PlotLine\n#define DOCSTRING_PlotSymbol\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"config/configRegister.h\"\n#include \"inputOutput/system.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileStringTable.h\"\n#include \"plotMisc.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(PlotColor, \"plotColorType\")\nGROOPS_READCONFIG_CLASS(PlotColor, \"plotColorType\")\n\n/***********************************************/\n\nPlotColor::PlotColor(Config &config, const std::string &name)\n{\n  try\n  {\n    const std::vector<std::string> colorStrings = {\"black\", \"red\", \"blue\", \"forestgreen\", \"darkorange\", \"darkred\", \"yellow\", \"green\", \"gray\"};\n\n    std::string choice;\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"color\");\n    if(readConfigChoiceElement(config, \"black\",      choice)) colorStr = colorStrings.at(0);\n    if(readConfigChoiceElement(config, \"red\",        choice)) colorStr = colorStrings.at(1);\n    if(readConfigChoiceElement(config, \"blue\",       choice)) colorStr = colorStrings.at(2);\n    if(readConfigChoiceElement(config, \"green\",      choice)) colorStr = colorStrings.at(3);\n    if(readConfigChoiceElement(config, \"orange\",     choice)) colorStr = colorStrings.at(4);\n    if(readConfigChoiceElement(config, \"darkred\",    choice)) colorStr = colorStrings.at(5);\n    if(readConfigChoiceElement(config, \"yellow\",     choice)) colorStr = colorStrings.at(6);\n    if(readConfigChoiceElement(config, \"lightgreen\", choice)) colorStr = colorStrings.at(7);\n    if(readConfigChoiceElement(config, \"gray\",       choice)) colorStr = colorStrings.at(8);\n    if(readConfigChoiceElement(config, \"rgb\", choice))\n    {\n      UInt r,g,b;\n      readConfig(config, \"red\",   r, Config::MUSTSET, \"\", \"0..255\");\n      readConfig(config, \"green\", g, Config::MUSTSET, \"\", \"0..255\");\n      readConfig(config, \"blue\",  b, Config::MUSTSET, \"\", \"0..255\");\n      std::stringstream ss;\n      ss<<\"#\"<<std::setfill('0')<<std::hex<<std::setw(2)<<r<<std::setw(2)<<g<<std::setw(2)<<b;\n      colorStr = ss.str();\n    }\n    if(readConfigChoiceElement(config, \"grayscale\", choice))\n    {\n      UInt value;\n      readConfig(config, \"value\",   value , Config::MUSTSET, \"\", \"0..255\");\n      std::stringstream ss;\n      ss<<\"#\"<<std::setfill('0')<<std::hex<<std::setw(2)<<value<<std::setw(2)<<value<<std::setw(2)<<value;\n      colorStr = ss.str();\n    }\n    if(readConfigChoiceElement(config, \"namedColor\", choice))\n      readConfig(config, \"colorName\", colorStr, Config::MUSTSET, \"\", \"name after GMT definition\");\n    if(readConfigChoiceElement(config, \"cycler\", choice))\n    {\n      UInt     index;\n      FileName fileNameColor;\n      readConfig(config, \"index\",              index,         Config::MUSTSET,  \"0\", \"pick color based on index expression\");\n      readConfig(config, \"inputfileColorList\", fileNameColor, Config::OPTIONAL, \"{groopsDataDir}/plot/colors.conf\", \"list of colors as defined by GMT\");\n\n      if(!isCreateSchema(config))\n      {\n        colorStr = colorStrings.at(1  + (index % (colorStrings.size()-1))); // exclude black\n        if(!fileNameColor.empty())\n        {\n          std::vector<std::string> customColors;\n          readFileStringList(fileNameColor, customColors);\n          if(customColors.size() == 0)\n            throw(Exception(\"File <\" + fileNameColor.str() + \"> does not contain any colors.\"));\n          colorStr = customColors.at(index % customColors.size());\n        }\n      }\n    }\n    endChoice(config);\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nstatic const char *docstringPlotLineSolid = R\"(\n\\subsection{Solid}\nDraws a solid line.\n)\";\n\nclass PlotLineSolid : public PlotLine\n{\npublic:\n  PlotLineSolid(Config &config)\n  {\n    style = \"solid\";\n    readConfig(config, \"width\", width, Config::DEFAULT, \"1.5\", \"line width [p]\");\n    readConfig(config, \"color\", color, Config::MUSTSET, \"\",    \"\");\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotLineDashed = R\"(\n\\subsection{Dashed}\nDraws a dashed line.\n)\";\n\nclass PlotLineDashed : public PlotLine\n{\npublic:\n  PlotLineDashed(Config &config)\n  {\n    style = \"dashed\";\n    readConfig(config, \"width\", width, Config::DEFAULT, \"1.5\", \"line width [p]\");\n    readConfig(config, \"color\", color, Config::MUSTSET, \"\",    \"\");\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotLineDotted = R\"(\n\\subsection{Dotted}\nDraws a dotted line.\n)\";\n\nclass PlotLineDotted : public PlotLine\n{\npublic:\n  PlotLineDotted(Config &config)\n  {\n    style = \"dotted\";\n    readConfig(config, \"width\", width, Config::DEFAULT, \"1.5\", \"line width [p]\");\n    readConfig(config, \"color\", color, Config::MUSTSET, \"\", \"  \");\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringPlotLineCustom = R\"(\n\\subsection{Custom}\nDraws a custom line. The line \\config{style} code is described in\n\\url{https://docs.generic-mapping-tools.org/latest/cookbook/features.html#specifying-pen-attributes}.\n)\";\n\nclass PlotLineCustom : public PlotLine\n{\npublic:\n  PlotLineCustom(Config &config)\n  {\n    readConfig(config, \"style\", style, Config::MUSTSET, \".-\",  \"line style code\");\n    readConfig(config, \"width\", width, Config::DEFAULT, \"1.5\", \"line width [p]\");\n    readConfig(config, \"color\", color, Config::MUSTSET, \"\",    \"\");\n  }\n};\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(PlotLine, \"plotLineType\",\n                      PlotLineSolid,\n                      PlotLineDashed,\n                      PlotLineDotted,\n                      PlotLineCustom)\n\nGROOPS_READCONFIG_CLASS(PlotLine, \"plotLineType\")\n\n/***********************************************/\n\nPlotLinePtr PlotLine::create(Config &config, const std::string &name)\n{\n  try\n  {\n    PlotLinePtr line;\n    std::string  type;\n\n    readConfigChoice(config, name, type, Config::MUSTSET, \"\", \"line style\");\n    if(readConfigChoiceElement(config, \"solid\",   type, \"solid line\"))\n      line = PlotLinePtr(new PlotLineSolid(config));\n    if(readConfigChoiceElement(config, \"dashed\",  type, \"dashed line\"))\n      line = PlotLinePtr(new PlotLineDashed(config));\n    if(readConfigChoiceElement(config, \"dotted\",  type, \"dotted line\"))\n      line = PlotLinePtr(new PlotLineDotted(config));\n    if(readConfigChoiceElement(config, \"custom\",  type, \"custom line (e.g. dash-dot)\"))\n      line = PlotLinePtr(new PlotLineCustom(config));\n    endChoice(config);\n\n    return line;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotLine::str() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<width<<\"p,\"<<color->str()<<\",\"<<style;\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nGROOPS_REGISTER_CLASS_WITHOUT_SUBS(PlotSymbol, \"plotSymbolType\")\nGROOPS_READCONFIG_CLASS(PlotSymbol, \"plotSymbolType\")\n\n/***********************************************/\n\nPlotSymbol::PlotSymbol(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string  symbol;\n    PlotColorPtr color;\n    Double       size = 3;\n    Bool         contour = 0;\n    std::string  choice;\n\n    const std::vector<std::pair<std::string, std::string>> symbols =\n      {{\"circle\", \"c\"},{\"star\", \"a\"}, {\"cross\", \"x\"}, {\"square\", \"s\"}, {\"triangle\", \"t\"}, {\"diamond\",  \"d\"}, {\"dash\", \"-\"}};\n\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"symbol\");\n    for(auto &s : symbols)\n      if(readConfigChoiceElement(config, s.first, choice))\n      {\n        readConfig(config, \"color\",        color,   Config::OPTIONAL, \"black\", \"empty: determined from value\");\n        readConfig(config, \"size\",         size,    Config::DEFAULT,  \"3\",     \"size of symbol [point]\");\n        readConfig(config, \"blackContour\", contour, Config::DEFAULT,  \"0\",     \"\");\n        symbol = s.second;\n      }\n    endChoice(config);\n    if(isCreateSchema(config)) return;\n\n    colorFromValue_ = (color == nullptr);\n\n    {\n      std::stringstream ss;\n      ss<<symbol<<size<<\"p \";\n      if(contour)\n        ss<<\"-W\"<<size/6.<<\"p,black\";\n      if(color)\n        ss<<\" -G\"<<color->str();\n      else\n        ss<<\" -CgroopsPlot.cpt\";\n      scriptLine = ss.str();\n    }\n\n    {\n      std::stringstream ss;\n      ss<<symbol<<\" \"<<std::max(size, 3.)<<\"p \"<<(color ? color->str() : \"white\");\n      if(contour || !color)\n        ss<<\" \"<<size/6.<<\"p,black\";\n      else\n        ss<<\" -\";\n      legendLine = ss.str();\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid PlotBasics::read(Config &config, const std::string &nameProgram_, const FileName &fileNamePlot_, const std::string &title_,\n                      const std::string &defaultWidth, const std::string &defaultHeight, const std::vector<std::string> &optionsDefault)\n{\n  try\n  {\n    std::vector<std::string> options;\n    std::string optionsDefaultStr = R\"([\"FONT_ANNOT_PRIMARY=10p\", \"MAP_ANNOT_OFFSET_PRIMARY=0.1c\", \"FONT_LABEL=10p\", \"MAP_LABEL_OFFSET=0.1c\", \"FONT_ANNOT_SECONDARY=10p\")\";\n    for(const std::string &str : optionsDefault)\n      optionsDefaultStr += \", \\\"\"+str+\"\\\"\";\n    optionsDefaultStr += \"]\";\n\n    height = NAN_EXPR;\n\n    if(readConfigSequence(config, \"options\", Config::MUSTSET,  \"\", \"further options...\"))\n    {\n      readConfig(config, \"width\",          width,          Config::DEFAULT,  defaultWidth,  \"in cm\");\n      readConfig(config, \"height\",         height,         Config::OPTIONAL, defaultHeight, \"in cm\");\n      readConfig(config, \"titleFontSize\",  titleSize,      Config::DEFAULT,  \"12\",  \"in pt\");\n      readConfig(config, \"marginTitle\",    marginTitle,    Config::DEFAULT,  \"0.4\", \"between title and figure [cm]\");\n      readConfig(config, \"drawGridOnTop\",  drawGridOnTop,  Config::DEFAULT,  \"0\",   \"grid lines above all other lines/points\");\n      readConfig(config, \"options\",        options,        Config::OPTIONAL, optionsDefaultStr, \"\");\n      readConfig(config, \"transparent\",    transparent,    Config::DEFAULT,  \"1\",   \"make background transparent\");\n      readConfig(config, \"dpi\",            dpi,            Config::DEFAULT,  \"300\", \"use this resolution when rasterizing postscript file\");\n      readConfig(config, \"removeFiles\",    removeFiles,    Config::DEFAULT,  \"1\",   \"remove .gmt and script files\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config))\n      return;\n\n    for(UInt i=0; i<options.size(); i++)\n      if(!options.at(i).empty())\n        optionsString += options.at(i)+\" \";\n\n    nameProgram  = nameProgram_;\n    fileNamePlot = fileNamePlot_;\n    title        = title_;\n\n    baseDirectory = fileNamePlot.directory();\n    if(std::getenv(\"GROOPS_PLOTDIR\") && removeFiles)\n      baseDirectory = FileName(std::getenv(\"GROOPS_PLOTDIR\"));\n\n    workingDirectory = baseDirectory.append(\"groopsPlot_\"+fileNamePlot.baseName().str());\n    System::createDirectories(workingDirectory);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileName PlotBasics::fileNameScript() const\n{\n#ifdef _WIN32\n  return workingDirectory.append(\"groopsPlot.bat\");\n#else\n  return workingDirectory.append(\"groopsPlot.sh\");\n#endif\n}\n\n/***********************************************/\n\nstd::string PlotBasics::scriptHeader() const\n{\n  std::stringstream ss;\n#ifdef _WIN32\n  ss<<\"@echo off\"<<std::endl;\n  ss<<\"REM automatically generated by groops::\"<<nameProgram<<std::endl;\n#else\n  ss<<\"#!/bin/bash\"<<std::endl;\n  ss<<\"# automatically generated by groops::\"<<nameProgram<<std::endl;\n#endif\n  ss<<scriptSetVariable(\"width\",  width%\"%gc\"s)<<std::endl;\n  ss<<scriptSetVariable(\"height\", height%\"%gc\"s)<<std::endl;\n  ss<<std::endl;\n  ss<<\"gmt set PS_MEDIA=a0 PS_PAGE_ORIENTATION=portrait\"<<std::endl;\n  ss<<\"gmt set \"<<optionsString<<std::endl;\n  ss<<\"gmt psxy -Y60c -X40c -JX1c/1c -R0/1/0/1 -K -T > groopsPlot.ps\"<<std::endl; // starts upper left\n\n  OutFile titleFile(workingDirectory.append(\"title.txt\"));\n  titleFile<<\"0.5 0.0 \"<<title;\n  ss<<\"gmt pstext title.txt -F+f\"<<titleSize<<\"p+jCB -Y-\"<<titleSize<<\"p -JX\"<<width<<\"c/\"<<titleSize<<\"p -R0/1/0/1 -N -O -K >> groopsPlot.ps \"<<PlotBasics::scriptError2Null()<<std::endl;\n  return ss.str();\n}\n\n/***********************************************/\n\nstd::string PlotBasics::scriptTrailer() const\n{\n  try\n  {\n    std::stringstream ss;\n    ss<<\"gmt psxy -R -J -O -T >> groopsPlot.ps\"<<std::endl;\n\n    // convert\n    const std::string extension = String::lowerCase(fileNamePlot.fullExtension());\n    if(extension != \"ps\")\n    {\n      const std::map<std::string, Char> extensionMapping = {{\"bmp\", 'b'}, {\"eps\", 'e'}, {\"pdf\", 'f'}, {\"jpg\", 'j'}, {\"png\", 'g'}, {\"tif\", 't'}, {\"ppm\", 'm'}};\n      if(extensionMapping.find(extension) == extensionMapping.end())\n        throw(Exception(\"Unsupported image format <\"+extension+\">.\"));\n      Char outputFormat = extensionMapping.at(extension);\n      if(outputFormat == 'g' && transparent)\n        outputFormat = 'G';\n      ss<<\"gmt psconvert groopsPlot.ps -Z -A1p -E\"<<dpi<<\" -Qg1 -Qt4 -T\"<<outputFormat<<std::endl;\n    }\n\n    // copy plot to destination\n#ifdef _WIN32\n    std::string cp = \"copy\";\n#else\n    std::string cp = \"cp\";\n#endif\n    if(baseDirectory.str() == fileNamePlot.directory().str())\n      ss<<cp<<\" groopsPlot.\"<<extension<<\" \"<<FileName(\"..\").append(fileNamePlot.stripDirectory())<<std::endl;\n    else\n    {\n      ss<<\"cd \\\"\"<<System::currentWorkingDirectory()<<\"\\\" && \";\n      ss<<cp<<\" \\\"\"<<fileNameScript().directory().append(\"groopsPlot.\"+extension)<<\"\\\" \\\"\"<<fileNamePlot<<\"\\\"\"<<std::endl;\n    }\n\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool PlotBasics::runScript() const\n{\n  try\n  {\n    std::stringstream ss;\n    if(!fileNameScript().directory().empty())\n      ss<<\"cd \\\"\"<<fileNameScript().directory()<<\"\\\" && \";\n#ifndef _WIN32\n    ss<<\"bash \";\n#endif\n    ss<<fileNameScript().stripDirectory();\n    System::exec(ss.str());\n\n    if(removeFiles)\n      System::remove(fileNameScript().directory());\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotBasics::axisTicks(Bool isLog, Double /*vmin*/, Double /*vmax*/, Double annotation, Double frame, Double grid, const std::string &unit, const std::string &label)\n{\n  try\n  {\n    if(isLog)\n    {\n      if(std::isnan(annotation)) annotation = 1;\n      if(std::isnan(frame))      frame      = 3;\n      if(std::isnan(grid))       grid       = 3;\n    }\n\n    std::stringstream ss;\n    if(annotation != 0.) {ss<<\"a\"; if(!std::isnan(annotation)) ss<<annotation; if(isLog) ss<<\"p\";} // major ticks\n    if(frame      != 0.) {ss<<\"f\"; if(!std::isnan(frame))      ss<<frame;}      // minor ticks\n    if(grid       != 0.) {ss<<\"g\"; if(!std::isnan(grid))       ss<<grid;}       // grid line spacing\n    if(!unit.empty())  ss<<\"+u\\\"\"<<(unit==\"%\" ? \"\" : \" \")<<unit<<\"\\\"\";\n    if(!label.empty()) ss<<\"+l\\\"\"<<label<<\"\\\"\";\n    return ss.str();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string PlotBasics::scriptSetVariable(const std::string &var, const std::string &value)\n{\n#ifdef _WIN32\n  return \"set \"+var+\"=\"+value;\n#else\n  return var+\"=\"+value;\n#endif\n}\n\n/***********************************************/\n\nstd::string PlotBasics::scriptVariable(const std::string &var)\n{\n#ifdef _WIN32\n  return \"%\"+var+\"%\";\n#else\n  return \"$\"+var;\n#endif\n}\n\n/***********************************************/\n\nstd::string PlotBasics::scriptError2Null()\n{\n#ifdef _WIN32\n  return \"2>nul\";\n#else\n  return \"2>/dev/null\";\n#endif\n}\n\n/***********************************************/\n\nUInt PlotBasics::gmtVersion()\n{\n  try\n  {\n    std::vector<std::string> output;\n    if(!System::exec(\"gmt --version\", output) || (output.size() == 0))\n      return MAX_UINT; // GMT does not seem to be installed -> use always latest version\n\n    const UInt version = std::stoul(output.at(0).substr(0,1))*100 + std::stoul(output.at(0).substr(2,1))*10 + std::stoul(output.at(0).substr(4,1));\n    return version;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/plot/plotMisc.h",
    "content": "/***********************************************/\n/**\n* @file plotMisc.h\n*\n* @brief Miscellaneous classes for plots.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2010-01-13\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PLOTMISC__\n#define __GROOPS_PLOTMISC__\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n\n/** @addtogroup plotGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_PlotColor\nstatic const char *docstringPlotColor = R\"(\n\\section{PlotColor}\\label{plotColorType}\nSelects a color.\nUsed in \\program{PlotDegreeAmplitudes}, \\program{PlotGraph}, \\program{PlotMap},\n\\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n\n)\";\n#endif\n\nclass PlotColor;\ntypedef std::shared_ptr<PlotColor> PlotColorPtr;\n\n/** @brief Color options for GMT plots.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotColor\n{\n  std::string colorStr; //!< color string needed by GMT\n\npublic:\n  /// Constructor.\n  PlotColor(Config &config, const std::string &name);\n\n  std::string str() const {return colorStr;}\n\n  /** @brief creates an derived instance of this class. */\n  static PlotColorPtr create(Config &config, const std::string &name) {return PlotColorPtr(new PlotColor(config, name));}\n};\n\n/** @brief Creates a class PlotColor.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotColor is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotColor Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotColor */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotColorPtr &plotColor, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_PlotLine\nstatic const char *docstringPlotLine = R\"(\n\\section{PlotLine}\\label{plotLineType}\nDefines the line style to be plotted.\n)\";\n#endif\n\nclass PlotLine;\ntypedef std::shared_ptr<PlotLine> PlotLinePtr;\n\n/** @brief Line style for plots\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotLine\n{\nprotected:\n  std::string  style;\n  Double       width;\n  PlotColorPtr color;\n\npublic:\n  virtual ~PlotLine() {}\n\n  virtual std::string str() const;\n\n  /** @brief creates an derived instance of this class. */\n  static PlotLinePtr create(Config &config, const std::string &name);\n};\n\n/** @brief Creates a class PlotLine.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a PlotLine is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] PlotLine Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotLine */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotLinePtr &PlotLine, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***** CLASS ***********************************/\n\n// Latex documentation\n#ifdef DOCSTRING_PlotSymbol\nstatic const char *docstringPlotSymbol = R\"(\n\\section{PlotSymbol}\\label{plotSymbolType}\nPlots a symbol as used e.g. in \\configClass{plotGraphLayer:linesAndPoints}{plotGraphLayerType:linesAndPoints}\nor \\configClass{plotMapLayer:points}{plotMapLayerType:points}.\n)\";\n#endif\n\nclass PlotSymbol;\ntypedef std::shared_ptr<PlotSymbol> PlotSymbolPtr;\n\n/** @brief Symbol options for GMT plots.\n* An Instance of this class can be created by @ref readConfig. */\nclass PlotSymbol\n{\n  Bool        colorFromValue_;\n  std::string scriptLine;\n  std::string legendLine;\n\npublic:\n  /// Constructor.\n  PlotSymbol(Config &config, const std::string &name);\n\n  /** @brief Return whether symbol color is determined externally. */\n  Bool requiresColorBar() const {return colorFromValue_;}\n\n  /** @brief Script entry. */\n  std::string str() const {return scriptLine;}\n\n  std::string legendStr() const {return legendLine;}\n\n  /** @brief creates an derived instance of this class. */\n  static PlotSymbolPtr create(Config &config, const std::string &name) {return PlotSymbolPtr(new PlotSymbol(config, name));}\n};\n\n/** @brief Creates a class PlotSymbol.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a plotSymbol is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] plotSymbol Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates PlotSymbol */\ntemplate<> Bool readConfig(Config &config, const std::string &name, PlotSymbolPtr &plotSymbol, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/***** CLASS ***********************************/\n\n/** @brief Basic options for GMT plots. */\nclass PlotBasics\n{\npublic:\n  std::string nameProgram;\n  FileName    fileNamePlot;\n  FileName    baseDirectory, workingDirectory;\n  Double      width, height;\n  Bool        drawGridOnTop;\n  std::string title;\n  Double      marginTitle;\n  UInt        titleSize;\n  Bool        transparent;\n  UInt        dpi;\n  Bool        removeFiles;\n  std::string optionsString;\n\n  void read(Config &config, const std::string &nameProgram_, const FileName &fileNamePlot_, const std::string &title_,\n            const std::string &defaultWidth, const std::string &defaultHeight, const std::vector<std::string> &optionsDefault=std::vector<std::string>());\n\n  FileName    fileNameScript() const;\n  std::string scriptHeader() const;\n  std::string scriptTrailer() const;\n  Bool        runScript() const;\n\n  /** @brief Axis anntotation in GMT plots. */\n  static std::string axisTicks(Bool isLog, Double vmin, Double vmax, Double annotation, Double frame, Double grid, const std::string &unit=\"\", const std::string &label=\"\");\n\n  static std::string scriptSetVariable(const std::string &var, const std::string &value);\n  static std::string scriptVariable(const std::string &var);\n  static std::string scriptError2Null();\n\n  static UInt gmtVersion();\n};\n\n/***********************************************/\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS_PLOTMISC__ */\n"
  },
  {
    "path": "source/programs/conversion/berneseKinematic2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file berneseKinematic2Orbit.cpp\n*\n* @brief Read kinematic orbits in Bernese format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-04-03\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead kinematic orbits in Bernese format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read kinematic orbits in Bernese format.\n* @ingroup programsConversionGroup */\nclass BerneseKinematic2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(BerneseKinematic2Orbit, SINGLEPROCESS, \"read kinematic orbits in Bernese format\", Conversion, Orbit, Covariance, Instrument)\nGROOPS_RENAMED_PROGRAM(Kinematic2Orbit, BerneseKinematic2Orbit, date2time(2020, 8, 4))\n\n/***********************************************/\n\nvoid BerneseKinematic2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName orbitName, covarianceName;\n    std::vector<FileName> fileNamesIn;\n    EarthRotationPtr earthRotation;\n\n    readConfig(config, \"outputfileOrbit\",      orbitName,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileCovariance\", covarianceName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",        earthRotation,  Config::OPTIONAL, \"file\", \"from TRF to CRF\");\n    readConfig(config, \"inputfile\",            fileNamesIn,    Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    OrbitArc        orbit;\n    Covariance3dArc covariance;\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n\n        // header\n        Double rms = 1.0;\n        std::string line;\n        for(UInt i=0; i<6; i++)\n        {\n          std::getline(file, line);\n          if(file.eof())\n            break;\n          if(line.find(\"RMS\") != std::string::npos)\n            rms = String::toDouble(line.substr(97, 10));\n        }\n\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            break;\n          std::stringstream ss(line.substr(18)); // skip station name\n          ss.exceptions(std::ios::badbit|std::ios::failbit);\n\n          UInt   week;\n          Double seconds;\n          Char   flag;\n\n          OrbitEpoch orbitEpoch;\n          ss>>week>>seconds>>orbitEpoch.position.x()>>orbitEpoch.position.y()>>orbitEpoch.position.z()>>flag;\n          orbitEpoch.time = date2time(1980, 1, 6) + mjd2time(week*7.) + seconds2time(seconds);\n\n          Covariance3dEpoch covEpoch;\n          ss>>covEpoch.covariance.xx()>>covEpoch.covariance.yy()>>covEpoch.covariance.zz();\n          ss>>covEpoch.covariance.xy()>>covEpoch.covariance.xz()>>covEpoch.covariance.yz();\n          covEpoch.time        = orbitEpoch.time;\n          covEpoch.covariance *= (rms*rms);\n\n          if(flag != 'K') //&&(flag!='G')) //&&(flag!='S')\n            continue;\n\n          orbit.push_back(orbitEpoch);\n          covariance.push_back(covEpoch);\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    } // for(idFile)\n\n    // ==============================\n\n    // Rotation TRF -> CRF\n    // -------------------\n    if(earthRotation)\n    {\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(orbit.size(), [&](UInt i)\n      {\n        const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(orbit.at(i).time));\n        orbit.at(i).position = rotation.rotate(orbit.at(i).position);\n        if(orbit.at(i).velocity.r() > 0)\n          orbit.at(i).velocity = rotation.rotate(orbit.at(i).velocity) + crossProduct(earthRotation->rotaryAxis(orbit.at(i).time), orbit.at(i).position);\n        if(covariance.size())\n          covariance.at(i).covariance = rotation.rotate(covariance.at(i).covariance);\n      });\n    }\n\n    // ==============================\n\n    // Write data\n    // ----------\n    if(!orbitName.empty())\n    {\n      logStatus<<\"write orbit data to file <\"<<orbitName<<\">\"<<Log::endl;\n      InstrumentFile::write(orbitName, orbit);\n      Arc::printStatistics(orbit);\n    }\n    if(!covarianceName.empty())\n    {\n      logStatus<<\"write covariance data to file <\"<<covarianceName<<\">\"<<Log::endl;\n      InstrumentFile::write(covarianceName, covariance);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/doodsonHarmonics/doodsonAdmittance2SupplementaryFiles.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonAdmittance2SupplementaryFiles.cpp\n*\n* @brief Write ascii doodson and admittance matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-07-22\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThe publication of an ocean tide model includes not only the atlas\nin the form of spherical harmonics coefficients,\nbut also the matrix of Doodson multipliers (\\config{outputfileDoodsonMatrix})\nand the \\config{outputfileAdmittanceMatrix}.\n\nThe \\config{outputfileMajorTideList} contains the \\config{fileNames}\nfor each contituent.\nThe required information is taken from the\n\\configFile{inputfileAdmittance}{admittance}.\n\nSee also \\program{DoodsonHarmonics2PotentialCoefficients}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileAdmittance.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write ascii doodson and admittance matrix.\n* @ingroup programsConversionGroup */\nclass DoodsonAdmittance2SupplementaryFiles\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonAdmittance2SupplementaryFiles, SINGLEPROCESS, \"write ascii doodson and admittance matrix\", Conversion, DoodsonHarmonics)\nGROOPS_RENAMED_PROGRAM(Admittance2Iers, DoodsonAdmittance2SupplementaryFiles, date2time(2023, 7, 1))\n\n/***********************************************/\n\nvoid DoodsonAdmittance2SupplementaryFiles::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameTideList, fileNameDoodson, fileNameMatrix;\n    FileName fileNames;\n    FileName fileNameAdmittance;\n\n    readConfig(config, \"outputfileMajorTideList\",    fileNameTideList,   Config::OPTIONAL, \"fileList.txt\",   \"\");\n    readConfig(config, \"fileNames\",                  fileNames,          Config::OPTIONAL, \"model_{doodson}_{name}_{cossin}.gfc\", \"template for fileList, variables: doodson, name, cossin\");\n    readConfig(config, \"outputfileDoodsonMatrix\",    fileNameDoodson,    Config::OPTIONAL, \"doodson.txt\",    \"\");\n    readConfig(config, \"outputfileAdmittanceMatrix\", fileNameMatrix,     Config::OPTIONAL, \"admittance.txt\", \"\");\n    readConfig(config, \"inputfileAdmittance\",        fileNameAdmittance, Config::MUSTSET,  \"\", \"interpolation of minor constituents\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read admittance file <\"<<fileNameAdmittance<<\">\"<<Log::endl;\n    Admittance admit;\n    readFileAdmittance(fileNameAdmittance, admit);\n\n    if(!fileNameTideList.empty())\n    {\n      logStatus<<\"write major tide list to file <\"<<fileNameTideList<<\">\"<<Log::endl;\n      OutFile file(fileNameTideList);\n      for(const auto &dood : admit.doodsonMajor)\n      {\n        VariableList varList;\n        varList.setVariable(\"doodson\", dood.code());\n        varList.setVariable(\"name\",    dood.name());\n        varList.setVariable(\"cossin\", \"cos\");\n        file<<fileNames(varList).str()<<\" \";\n        varList.setVariable(\"cossin\", \"sin\");\n        file<<fileNames(varList).str()<<std::endl;\n      }\n    }\n\n    if(!fileNameDoodson.empty())\n    {\n      logStatus<<\"write doodson coefficients to file <\"<<fileNameDoodson<<\">\"<<Log::endl;\n      OutFile file(fileNameDoodson);\n      for(const auto &dood : admit.doodsonMinor)\n      {\n        for(UInt i=0; i<6; i++)\n          file<<\" \"<<dood.d[i]%\"%3i\"s;\n        file<<std::endl;\n      }\n    }\n\n    if(!fileNameMatrix.empty())\n    {\n      logStatus<<\"write admittance matrix to file <\"<<fileNameMatrix<<\">\"<<Log::endl;\n      OutFile file(fileNameMatrix);\n      for(UInt i=0; i<admit.admittance.rows(); i++)\n      {\n        for(UInt k=0; k<admit.admittance.columns(); k++)\n          file<<admit.admittance(i,k)%\"%16.8e\"s;\n        file<<std::endl;\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/doodsonHarmonics/doodsonHarmonics2IersPotential.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonHarmonics2IersPotential.cpp\n*\n* @brief Convert doodson harmonics to IERS conventions according to FES2004.\n* cf. ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\n*\n* @author Daniel Rieser\n* @date 2012-03-05\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert doodson harmonics to IERS conventions according to FES2004.\ncf. \\url{ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert doodson harmonics to IERS conventions according to FES2004.\n* cf. ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\n* @ingroup programsConversionGroup */\nclass DoodsonHarmonics2IersPotential\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonHarmonics2IersPotential, SINGLEPROCESS, \"convert doodson harmonics file to IERS\", Conversion, DoodsonHarmonics)\n\n/***********************************************/\n\nvoid DoodsonHarmonics2IersPotential::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut, fileNameIn;\n    Double      factor;\n    UInt        minDegree, maxDegree = INFINITYDEGREE;\n    std::vector<std::string> headers;\n\n    readConfig(config, \"outputfile\",                       fileNameOut, Config::MUSTSET,  \"\",\"according to IERS2010, chapter 6.3.2, footnote 7\");\n    readConfig(config, \"inputfileDoodsonHarmoncis\",        fileNameIn,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"header\",                           headers,     Config::MUSTSET,  R\"|([\"Coefficients to compute variations in normalized Stokes coefficients (unit = 10^-11)\", \"Ocean tide model: FES2014b up to (100,100) in cm\"])|\", \"info for output header\");\n    readConfig(config, \"factor\",                           factor,      Config::DEFAULT,  \"1e11\", \"\");\n    readConfig(config, \"minDegree\",                        minDegree,   Config::DEFAULT,  \"1\",    \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree,   Config::OPTIONAL, \"\",     \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    // read tides\n    // ----------\n    logStatus<<\"read tides from <\"<<fileNameIn<<\">\"<<Log::endl;\n    DoodsonHarmonic d;\n    readFileDoodsonHarmonic(fileNameIn, d);\n    maxDegree = std::min(maxDegree, d.cnmCos.at(0).rows()-1);\n\n    // Coefficients to compute variations in normalized Stokes coefficients (unit = 10^-11)\n    // Ocean tide model: FES2004 normalized model (fev. 2004) up to (100,100)\n    // (long period from FES2002 up to (50,50) + equilibrium Om1/Om2, atmospheric tide NOT included)\n    // Doodson Darw  l   m    DelC+     DelS+       DelC-     DelS-\n    // 255.555 M2    2   1 -12.07164  -4.38919    -3.09008   1.50139\n    logStatus<<\"write tides to <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile file(fileNameOut);\n    for(const auto &header : headers)\n      file<<header<<std::endl;\n    file<<\"Doodson Darw  l   m    DelC+     DelS+       DelC-     DelS-\"<<std::endl;\n    for(UInt i=0; i<d.doodson.size(); i++)\n    {\n      for(UInt m=0; m<=maxDegree; m++)\n        for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n        {\n          const Double cPlus  = 0.5 * factor * (d.cnmCos.at(i)(n,m) - d.snmSin.at(i)(n,m));\n          const Double cMinus = 0.5 * factor * (d.cnmCos.at(i)(n,m) + d.snmSin.at(i)(n,m));\n          const Double sPlus  = 0.5 * factor * (d.cnmSin.at(i)(n,m) + d.snmCos.at(i)(n,m));\n          const Double sMinus = 0.5 * factor * (d.cnmSin.at(i)(n,m) - d.snmCos.at(i)(n,m));\n\n          file<<d.doodson.at(i).code()<<\" \"<<d.doodson.at(i).name()<<std::string(4ul-std::min(static_cast<std::size_t>(3), d.doodson.at(i).name().size()), ' ');\n          file<<n%\"%3i \"s<<m%\"%3i \"s;\n          file<<cPlus%\"%9.5f \"s<<sPlus%\"%9.5f   \"s<<cMinus%\"%9.5f \"s<<sMinus%\"%9.5f   \"s<<std::endl;\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/doodsonHarmonics/doodsonHarmonics2IersWaterHeight.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonHarmonics2IersWaterHeight.cpp\n*\n* @brief Convert doodson harmonics to IERS conventions according to FES2004.\n* cf. ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\n*\n* @author Daniel Rieser\n* @date 2012-03-05\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert doodson harmonics to IERS conventions according to FES2004.\ncf. \\url{ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert doodson harmonics to IERS conventions according to FES2004.\n* cf. ftp://tai.bipm.org/iers/conv2010/chapter6/tidemodels/fes2004.dat\n* @ingroup programsConversionGroup */\nclass DoodsonHarmonics2IersWaterHeight\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonHarmonics2IersWaterHeight, SINGLEPROCESS, \"convert doodson harmonics file to IERS\", Conversion, DoodsonHarmonics)\n\n/***********************************************/\n\nvoid DoodsonHarmonics2IersWaterHeight::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut, fileNameIn, fileNameTGP;\n    KernelPtr   kernel;\n    Double      factor;\n    UInt        minDegree, maxDegree = INFINITYDEGREE;\n    std::vector<std::string> headers;\n\n    readConfig(config, \"outputfile\",                       fileNameOut, Config::MUSTSET,  \"\",\"according to IERS2010, chapter 6.3.2, footnote 7\");\n    readConfig(config, \"inputfileDoodsonHarmoncis\",        fileNameIn,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileTideGeneratingPotential\", fileNameTGP, Config::MUSTSET,  \"{groopsDataDir}/tides/generatingTide_HW95.txt\", \"to compute Xi phase correction\");\n    readConfig(config, \"header\",                           headers,     Config::MUSTSET,  \"Ocean tide model: FES2014b up to (100,100) in cm\", \"info for output header\");\n    readConfig(config, \"kernel\",                           kernel,      Config::MUSTSET,  \"waterHeight\", \"data type of output values\");\n    readConfig(config, \"factor\",                           factor,      Config::DEFAULT,  \"100\", \"e.g. from [m] to [cm]\");\n    readConfig(config, \"minDegree\",                        minDegree,   Config::DEFAULT,  \"0\",   \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree,   Config::OPTIONAL, \"\",    \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    // read tides\n    // ----------\n    logStatus<<\"read tides from <\"<<fileNameIn<<\">\"<<Log::endl;\n    DoodsonHarmonic d;\n    readFileDoodsonHarmonic(fileNameIn, d);\n    maxDegree = std::min(maxDegree, d.cnmCos.at(0).rows()-1);\n\n    // read tide generating potential (TGP)\n    // ------------------------------------\n    logStatus<<\"read tide generating potential <\"<<fileNameTGP<<\">\"<<Log::endl;\n    TideGeneratingPotential tgp;\n    readFileTideGeneratingPotential(fileNameTGP, tgp);\n\n    // Ocean tide model: FES2004 normalized model (fev. 2004) up to (100,100) in cm\n    // (long period from FES2002 up to (50,50) + equilibrium Om1/Om2, atmospheric tide NOT included)\n    // Doodson Darw  n   m    Csin+     Ccos+       Csin-     Ccos-       C+   eps+      C-   eps-\n    // 255.555 M2    2   1 -0.991591 -0.360545   -0.253804  0.123315   1.0551 250.019 0.2822 295.914\n    logStatus<<\"write tides to <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile file(fileNameOut);\n    for(const auto &header : headers)\n      file<<header<<std::endl;\n    file<<\"Doodson Darw  n   m    Ccos+     Csin+       Ccos-     Csin-       C+   eps+      C-   eps-\"<<std::endl;\n    const Vector kn = factor * d.GM/d.R * kernel->inverseCoefficients(Vector3d(d.R,0,0), maxDegree); // convert units\n    for(UInt i=0; i<d.doodson.size(); i++)\n    {\n      const Double xi = tgp.xi(d.doodson.at(i));\n      logStatus<<d.doodson.at(i).code()<<\" \"<<d.doodson.at(i).name()<<std::string(6ul-std::min(static_cast<std::size_t>(6), d.doodson.at(i).name().size()), ' ')<<\"xi = \"<<RAD2DEG*xi<<Log::endl;\n      for(UInt m=0; m<=maxDegree; m++)\n        for(UInt n=std::max(minDegree,m); n<=maxDegree; n++)\n        {\n          // iers conventions 2010, eq. (6.15)\n          const Double cPlus  = 0.5 * (d.cnmCos.at(i)(n,m) - d.snmSin.at(i)(n,m));\n          const Double cMinus = 0.5 * (d.cnmCos.at(i)(n,m) + d.snmSin.at(i)(n,m));\n          const Double sPlus  = 0.5 * (d.cnmSin.at(i)(n,m) + d.snmCos.at(i)(n,m));\n          const Double sMinus = 0.5 * (d.cnmSin.at(i)(n,m) - d.snmCos.at(i)(n,m));\n\n          // iers conventions 2010, eq. (6.20) and (6.21)\n          const Double cCosPlus  = kn(n) * (cPlus  * std::cos(xi) - sPlus  * std::sin(xi));\n          const Double cCosMinus = kn(n) * (cMinus * std::cos(xi) - sMinus * std::sin(xi));\n          const Double cSinPlus  = kn(n) * (cPlus  * std::sin(xi) + sPlus  * std::cos(xi));\n          const Double cSinMinus = kn(n) * (cMinus * std::sin(xi) + sMinus * std::cos(xi));\n\n          // iers conventions 2010, eq. (6.20)\n          const Double cBarPlus  = std::sqrt(cCosPlus  * cCosPlus  + cSinPlus  * cSinPlus);\n          const Double cBarMinus = std::sqrt(cCosMinus * cCosMinus + cSinMinus * cSinMinus);\n          const Double epsPlus   = RAD2DEG * std::fmod(std::atan2(cCosPlus,  cSinPlus)  + 2*PI, 2*PI);\n          const Double epsMinus  = RAD2DEG * std::fmod(std::atan2(cCosMinus, cSinMinus) + 2*PI, 2*PI);\n\n          file<<d.doodson.at(i).code()<<\" \"<<d.doodson.at(i).name()<<std::string(4ul-std::min(static_cast<std::size_t>(3), d.doodson.at(i).name().size()), ' ');\n          file<<n%\"%3i \"s<<m%\"%3i \"s;\n          file<<cCosPlus%\"%9.6f \"s<<cSinPlus%\"%9.6f   \"s<<cCosMinus%\"%9.6f \"s<<cSinMinus%\"%9.6f   \"s;\n          file<<cBarPlus%\"%6.4f \"s<<epsPlus%\"%7.3f \"s<<cBarMinus%\"%6.4f \"s<<epsMinus%\"%7.3f\"s<<std::endl;\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/doodsonHarmonics/graceAod2DoodsonHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file graceAod2DoodsonHarmonics.cpp\n*\n* @brief Convert AOD1B tides into DoodsonHarmonics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-05-04\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the atmospheric and ocean tidal products (AOD1B)\nfrom the GRACE SDS format into \\configFile{outputfileDoodsonHarmonics}{doodsonHarmonic}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert AOD1B into DoodsonHarmonics.\n* @ingroup programsConversionGroup */\nclass GraceAod2DoodsonHarmonics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceAod2DoodsonHarmonics, SINGLEPROCESS, \"Convert AOD1B tides into DoodsonHarmonics.\", Conversion, DoodsonHarmonics)\nGROOPS_RENAMED_PROGRAM(GraceCsrAod2DoodsonHarmonics, GraceAod2DoodsonHarmonics, date2time(2020, 6, 14))\n\n/***********************************************/\n\nvoid GraceAod2DoodsonHarmonics::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameDoodson, fileNameTGP;\n    std::vector<FileName> fileNameInput;\n\n    readConfig(config, \"outputfileDoodsonHarmonics\",       fileNameDoodson, Config::MUSTSET, \"\", \"\" );\n    readConfig(config, \"inputfileTideGeneratingPotential\", fileNameTGP,     Config::MUSTSET, \"{groopsDataDir}/tides/generatingTide_HW95.txt\", \"to compute Xi phase correction\");\n    readConfig(config, \"inputfile\",                        fileNameInput,   Config::MUSTSET, \"\", \"\" );\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    // read tide generating potential (TGP)\n    // ------------------------------------\n    logStatus<<\"read tide generating potential <\"<<fileNameTGP<<\">\"<<Log::endl;\n    TideGeneratingPotential tgp;\n    readFileTideGeneratingPotential(fileNameTGP, tgp);\n\n    // ======================================================\n\n    Double GM = DEFAULT_GM;\n    Double R  = DEFAULT_R;\n    std::vector<Doodson>  doodson;\n    std::vector<Matrix>   cnmCos, snmCos, cnmSin, snmSin;\n\n    for(UInt i=0; i<fileNameInput.size(); i++)\n    {\n      logStatus<<\"read file <\"<<fileNameInput.at(i)<<\">\"<<Log::endl;\n      InFile file(fileNameInput.at(i));\n\n      // Header\n      // ------\n      std::string line;\n      std::string name;\n      UInt dataCount = 0;\n      UInt version = 9999;\n      UInt degree  = 180;\n      for(;;)\n      {\n        std::getline(file, line);\n        if(file.eof())\n          break;\n\n        if(line.find(\"PARTIAL TIDE\")==0)\n          name = String::trim(line.substr(31,4));\n\n        if(line.find(\"CONSTANT GM\")==0)\n          GM = String::toDouble(line.substr(31, 22));\n\n        if(line.find(\"CONSTANT A\")==0)\n          R = String::toDouble(line.substr(31, 22));\n\n        if(line.find(\"MAXIMUM DEGREE\")==0)\n          degree = String::toInt(line.substr(32, 3));\n\n        if(line.find(\"NUMBER OF DATA SETS\")==0)\n          dataCount = String::toInt(line.substr(31, 22));\n\n        if(line.find(\"SOFTWARE VERSION\")==0)\n          version = String::toInt(line.substr(50, 2));\n\n        // Header fertig\n        if(line.find(\"END OF HEADER\")==0)\n          break;\n      }\n\n      if(version==9999)\n        logWarning<<\"found not SOFTWARE VERSION\"<<Log::endl;\n\n      if(name.empty())\n        logWarning<<\"found not PARTIAL TIDE\"<<Log::endl;\n\n      if(dataCount!=2)\n        logWarning<<\"NUMBER OF DATA SETS not found or not 2: \"<<dataCount<<Log::endl;\n\n      doodson.push_back(Doodson(name));\n\n      for(UInt k=0; k<dataCount; k++)\n      {\n        // Data Header\n        std::getline(file, line);\n        std::string type = line.substr(41,3);\n\n        Matrix cnm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        Matrix snm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        for(UInt n=0; n<=degree; n++)\n          for(UInt m=0; m<=n; m++)\n          {\n            UInt n2,m2;\n            file>>n2>>m2;\n            file>>cnm(n2,m2)>>snm(n2,m2);\n            // rest of the line\n            std::getline(file, line);\n          }\n\n        if(type==\"cos\")\n        {\n          cnmCos.push_back(cnm);\n          snmCos.push_back(snm);\n        }\n        else if(type==\"sin\")\n        {\n          cnmSin.push_back(cnm);\n          snmSin.push_back(snm);\n        }\n        else\n        {\n          logError<<\"Unknown type: \"<<type<<Log::endl;\n        }\n      }\n    }\n\n    // ======================================================\n\n    auto cnmCosOld = cnmCos;\n    auto snmCosOld = snmCos;\n    auto cnmSinOld = cnmSin;\n    auto snmSinOld = snmSin;\n    for(UInt i=0; i<doodson.size(); i++)\n    {\n      const Double xi = tgp.xi(doodson.at(i));\n      cnmCos.at(i)  =  cnmCosOld.at(i) * cos(xi) + cnmSinOld.at(i) * sin(xi);\n      snmCos.at(i)  =  snmCosOld.at(i) * cos(xi) + snmSinOld.at(i) * sin(xi);\n      cnmSin.at(i)  = -cnmCosOld.at(i) * sin(xi) + cnmSinOld.at(i) * cos(xi);\n      snmSin.at(i)  = -snmCosOld.at(i) * sin(xi) + snmSinOld.at(i) * cos(xi);\n    }\n\n    // ======================================================\n\n    // Write tides\n    // -----------\n    logStatus<<\"write tides to <\"<<fileNameDoodson<<\">\"<<Log::endl;\n    writeFileDoodsonHarmonic(fileNameDoodson, DoodsonHarmonic(GM, R, doodson, cnmCos, snmCos, cnmSin, snmSin));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/doodsonHarmonics/iersPotential2DoodsonHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file iersPotential2DoodsonHarmonics.cpp\n*\n* @brief Read ocean tide file in IERS format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-11-02\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ocean tide file in IERS format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ocean tide file in IERS format.\n* @ingroup programsConversionGroup */\nclass IersPotential2DoodsonHarmonics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(IersPotential2DoodsonHarmonics, SINGLEPROCESS, \"Read ocean tide file in IERS format\", Conversion, DoodsonHarmonics)\n\n/***********************************************/\n\nvoid IersPotential2DoodsonHarmonics::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName  fileNameOut;\n    FileName  fileNameIn, fileNameTGP;\n    UInt      countHeader;\n    Double    GM, R;\n    UInt      minDegree, maxDegree = INFINITYDEGREE;\n\n    readConfig(config, \"outputfileDoodsonHarmoncis\", fileNameOut, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"inputfile\",                  fileNameIn,  Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"headerLines\",                countHeader, Config::MUSTSET, \"4\", \"skip number of header lines\");\n    readConfig(config, \"minDegree\",                  minDegree,   Config::DEFAULT, \"0\", \"\");\n    readConfig(config, \"maxDegree\",                  maxDegree,   Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"GM\",                         GM,          Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                          R,           Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    logStatus<<\"read file from <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n\n    // skip headerlines\n    std::string line;\n    for(UInt i=0; i<countHeader; i++)\n      std::getline(file, line);\n\n    std::vector<Doodson> doodson;\n    std::vector<Matrix>  cnmCos, cnmSin, snmCos, snmSin;\n    for(;;)\n    {\n      std::getline(file, line);\n      if(file.eof())\n        break;\n      if(line.empty())\n        continue;\n\n      // Coefficients to compute variations in normalized Stokes coefficients (unit = 10^-11)\n      // Ocean tide model: FES2004 normalized model (fev. 2004) up to (100,100)\n      // (long period from FES2002 up to (50,50) + equilibrium Om1/Om2, atmospheric tide NOT included)\n      // Doodson Darw  l   m    DelC+     DelS+       DelC-     DelS-\n      // 255.555 M2    2   1 -12.07164  -4.38919    -3.09008   1.50139\n      std::stringstream ss(line);\n      std::string doodstring, name;\n      UInt   n, m;\n      Double cPlus, sPlus, cMinus, sMinus;\n      ss>>doodstring>>name>>n>>m>>cPlus>>sPlus>>cMinus>>sMinus;\n      if(doodstring.size() == 6)\n        doodstring = '0'+doodstring;\n\n      // Constituent already exist?\n      UInt idx = std::distance(doodson.begin(), std::find(doodson.begin(), doodson.end(), Doodson(doodstring)));\n      if(idx >= doodson.size())\n      {\n        doodson.push_back(Doodson(doodstring));\n        logStatus<<doodstring<<\" \"<<name<<Log::endl;\n        cnmCos.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        cnmSin.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        snmCos.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        snmSin.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n      }\n\n      // iers conventions 2010, eq. (6.15)\n      if((n>=minDegree) && (n<=maxDegree))\n      {\n        cnmCos.at(idx)(n,m) =  (cPlus + cMinus) * 1e-11;\n        snmCos.at(idx)(n,m) =  (sPlus - sMinus) * 1e-11;\n        cnmSin.at(idx)(n,m) =  (sPlus + sMinus) * 1e-11;\n        snmSin.at(idx)(n,m) = -(cPlus - cMinus) * 1e-11;\n      }\n    }\n\n    // write results\n    // -------------\n    logStatus<<\"write tides to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileDoodsonHarmonic(fileNameOut, DoodsonHarmonic(GM, R, doodson, cnmCos, snmCos, cnmSin, snmSin));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/doodsonHarmonics/iersWaterHeight2DoodsonHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file iersWaterHeight2DoodsonHarmonics.cpp\n*\n* @brief Read ocean tide file in IERS format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-11-02\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ocean tide file in IERS format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ocean tide file in IERS format.\n* @ingroup programsConversionGroup */\nclass IersWaterHeight2DoodsonHarmonics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(IersWaterHeight2DoodsonHarmonics, SINGLEPROCESS, \"Read ocean tide file in IERS format\", Conversion, DoodsonHarmonics)\n\n/***********************************************/\n\nvoid IersWaterHeight2DoodsonHarmonics::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName  fileNameOut;\n    FileName  fileNameIn, fileNameTGP;\n    UInt      countHeader;\n    KernelPtr kernel;\n    Double    factor;\n    Double    GM, R;\n    UInt      minDegree, maxDegree = INFINITYDEGREE;\n\n    readConfig(config, \"outputfileDoodsonHarmoncis\",       fileNameOut, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"inputfile\",                        fileNameIn,  Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"headerLines\",                      countHeader, Config::MUSTSET, \"3\", \"skip number of header lines\");\n    readConfig(config, \"inputfileTideGeneratingPotential\", fileNameTGP, Config::MUSTSET, \"{groopsDataDir}/tides/generatingTide_HW95.txt\", \"to compute Xi phase correction\");\n    readConfig(config, \"kernel\",                           kernel,      Config::MUSTSET, \"waterHeight\", \"data type of input values\");\n    readConfig(config, \"factor\",                           factor,      Config::DEFAULT, \"0.01\", \"to convert in SI units\");\n    readConfig(config, \"minDegree\",                        minDegree,   Config::DEFAULT, \"0\", \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree,   Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"GM\",                               GM,          Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                                R,           Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    // read tide generating potential (TGP)\n    // ------------------------------------\n    logStatus<<\"read tide generating potential <\"<<fileNameTGP<<\">\"<<Log::endl;\n    TideGeneratingPotential tgp;\n    readFileTideGeneratingPotential(fileNameTGP, tgp);\n\n    // Koeffizienten einlesen\n    // ----------------------\n    logStatus<<\"read file from <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n\n    // skip headerlines\n    std::string line;\n    for(UInt i=0; i<countHeader; i++)\n      std::getline(file, line);\n\n    std::vector<Doodson> doodson;\n    std::vector<Matrix>  cnmCos, cnmSin, snmCos, snmSin;\n    std::vector<Double>  xi;\n    const Vector kn = factor * R/GM * kernel->coefficients(Vector3d(R,0,0), maxDegree);\n    for(;;)\n    {\n      std::getline(file, line);\n      if(file.eof())\n        break;\n      if(line.empty())\n        continue;\n\n      // Ocean tide model: FES2004 normalized model (fev. 2004) up to (100,100) in cm\n      // (long period from FES2002 up to (50,50) + equilibrium Om1/Om2, atmospheric tide NOT included)\n      // Doodson Darw  n   m    Csin+     Ccos+       Csin-     Ccos-       C+   eps+      C-   eps-\n      // 255.555 M2    2   1 -0.991591 -0.360545   -0.253804  0.123315   1.0551 250.019 0.2822 295.914\n      std::stringstream ss(line);\n      std::string doodstring, name;\n      UInt   n, m;\n      Double cSinPlus, cCosPlus, cSinMinus, cCosMinus;\n      Double cBarPlus, epsPlus, cBarMinus, epsMinus;\n      ss>>doodstring>>name>>n>>m>>cCosPlus>>cSinPlus>>cCosMinus>>cSinMinus>>cBarPlus>>epsPlus>>cBarMinus>>epsMinus;\n      if(doodstring.size() == 6)\n        doodstring = '0'+doodstring;\n\n      // Constituent already exist?\n      UInt idx = std::distance(doodson.begin(), std::find(doodson.begin(), doodson.end(), Doodson(doodstring)));\n      if(idx >= doodson.size())\n      {\n        doodson.push_back(Doodson(doodstring));\n        cnmCos.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        cnmSin.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        snmCos.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        snmSin.push_back(Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n        xi.push_back(tgp.xi(doodson.at(idx)));\n        logStatus<<doodstring<<\" \"<<name<<std::string(6ul-std::min(static_cast<std::size_t>(6), name.size()), ' ')<<\"xi = \"<<RAD2DEG*xi.back()<<Log::endl;\n      }\n\n      if((n>=minDegree) && (n<=maxDegree))\n      {\n        // variant 1: iers conventions 2010, eq. (6.20) and (6.21)\n        const Double cPlus  = cCosPlus  * std::cos(xi.at(idx)) + cSinPlus  * std::sin(xi.at(idx));\n        const Double cMinus = cCosMinus * std::cos(xi.at(idx)) + cSinMinus * std::sin(xi.at(idx));\n        const Double sPlus  = cSinPlus  * std::cos(xi.at(idx)) - cCosPlus  * std::sin(xi.at(idx));\n        const Double sMinus = cSinMinus * std::cos(xi.at(idx)) - cCosMinus * std::sin(xi.at(idx));\n\n        // variant 2: iers conventions 2010, eq. (6.21)\n//         const Double cPlus  = cBarPlus  * std::sin(DEG2RAD*epsPlus  + xi.at(idx));\n//         const Double cMinus = cBarMinus * std::sin(DEG2RAD*epsMinus + xi.at(idx));\n//         const Double sPlus  = cBarPlus  * std::cos(DEG2RAD*epsPlus  + xi.at(idx));\n//         const Double sMinus = cBarMinus * std::cos(DEG2RAD*epsMinus + xi.at(idx));\n\n        // iers conventions 2010, eq. (6.15)\n        cnmCos.at(idx)(n,m) =  kn(n) * (cPlus + cMinus);\n        snmCos.at(idx)(n,m) =  kn(n) * (sPlus - sMinus);\n        cnmSin.at(idx)(n,m) =  kn(n) * (sPlus + sMinus);\n        snmSin.at(idx)(n,m) = -kn(n) * (cPlus - cMinus);\n      }\n    }\n\n    // write results\n    // -------------\n    logStatus<<\"write tides to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileDoodsonHarmonic(fileNameOut, DoodsonHarmonic(GM, R, doodson, cnmCos, snmCos, cnmSin, snmSin));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/eop/iersC04IAU2000EarthOrientationParameter.cpp",
    "content": "/***********************************************/\n/**\n* @file iersC04IAU2000EarthOrientationParameter.cpp\n*\n* @brief Read Earth Orientation Parameter.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-14\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead a IERS Earth orientation data C04 (IAU2000A) file\nand write it as \\configFile{outputfileEOP}{earthOrientationParameter}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read Earth Orientation Parameter.\n* @ingroup programsConversionGroup */\nclass IersC04IAU2000EarthOrientationParameter\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(IersC04IAU2000EarthOrientationParameter, SINGLEPROCESS, \"read Earth Orientation Parameter\", Conversion)\nGROOPS_RENAMED_PROGRAM(Eop2003file, IersC04IAU2000EarthOrientationParameter, date2time(2020, 9, 8))\n\n/***********************************************/\n\nvoid IersC04IAU2000EarthOrientationParameter::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName inName, outName;\n    Time timeStart = Time();\n    Time timeEnd   = date2time(9999,1,1,0,0,0);\n\n    readConfig(config, \"outputfileEOP\", outName,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",     inName,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeStart\",     timeStart, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"timeEnd\",       timeEnd,   Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // Erdrotationsparameter einlesen\n    // ------------------------------\n    logStatus<<\"read input file\"<<Log::endl;\n    InFile file(inName);\n\n    // check version\n    std::string line;\n    std::getline(file, line);\n    Bool oldVersion = !String::startsWith(line, \"#\");\n\n    // old Header\n    if(oldVersion)\n    {\n      for(UInt i=0; i<14; i++)\n        std::getline(file, line);\n    }\n\n    std::vector<Double> mjd, xp, yp, du, ld, dX, dY;\n    while(std::getline(file, line))\n    {\n      if(String::startsWith(line, \"#\"))\n        continue;\n\n      std::stringstream ss(line);\n      ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n      Int   day, month, year, hour;\n      Double _mjd, _xp, _yp, _du, _ld, _dX, _dY, tmp;\n      if(oldVersion)\n        ss>>year>>month>>day>>_mjd>>_xp>>_yp>>_du>>_ld>>_dX>>_dY;\n      else\n        ss>>year>>month>>day>>hour>>_mjd>>_xp>>_yp>>_du>>_dX>>_dY>>tmp>>tmp>>_ld;\n\n      const Time time = mjd2time(_mjd);\n      if((time < timeStart) || (time > timeEnd))\n        continue;\n\n      mjd.push_back(_mjd);\n      xp.push_back(_xp);\n      yp.push_back(_yp);\n      du.push_back(_du);\n      ld.push_back(_ld);\n      dX.push_back(_dX);\n      dY.push_back(_dY);\n    }\n\n    logInfo<<\"  count = \"<<mjd.size()<<Log::endl;\n    if(mjd.size())\n    {\n      logInfo<<\"  start = \"<<mjd2time(mjd.at(0)).dateTimeStr()<<Log::endl;\n      logInfo<<\"  end   = \"<<mjd2time(mjd.back()).dateTimeStr()<<Log::endl;\n    }\n\n    Matrix EOP(mjd.size(), 7);\n    for(UInt i=0; i<EOP.rows(); i++)\n    {\n      EOP(i,0) = mjd.at(i);\n      EOP(i,1) = xp.at(i);\n      EOP(i,2) = yp.at(i);\n      EOP(i,3) = du.at(i);\n      EOP(i,4) = ld.at(i);\n      EOP(i,5) = dX.at(i);\n      EOP(i,6) = dY.at(i);\n    }\n\n    // Save to file\n    // ------------\n    logStatus<<\"write EOPs <\"<<outName<<\">\"<<Log::endl;\n    writeFileEarthOrientationParameter(outName, EOP);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/eop/iersHighFrequentEop2DoodsonEop.cpp",
    "content": "/***********************************************/\n/**\n* @file iersHighFrequentEop2DoodsonEop.cpp\n*\n* @brief Read Diurnal and Subdiurnal Earth Orientation variations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-05-15\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead Diurnal and Subdiurnal Earth Orientation variations according to updated IERS 2010 conventions\nand write them as \\configFile{outputfileDoodsonEOP}{doodsonEarthOrientationParameter}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileDoodsonEarthOrientationParameter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read Diurnal and Subdiurnal Earth Orientation variations.\n* @ingroup programsConversionGroup */\nclass IersHighFrequentEop2DoodsonEop\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(IersHighFrequentEop2DoodsonEop, SINGLEPROCESS, \"Read Diurnal and Subdiurnal Earth Orientation variations.\", Conversion)\n\n/***********************************************/\n\nstatic Bool stripComments(std::istream &stream)\n{\n  try\n  {\n    char c;\n    if(!(stream>>c))\n      return FALSE;\n    stream.putback(c);\n    if(c != '#')\n      return TRUE;\n    std::string line;\n    std::getline(stream, line); // skip rest of line\n    return stripComments(stream);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid IersHighFrequentEop2DoodsonEop::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameIn, fileNameDoodsonEop;\n\n    readConfig(config, \"outputfileDoodsonEOP\", fileNameDoodsonEop, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNameIn,         Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    std::vector<Doodson> doodson;\n    std::vector<Double>  xpCos, xpSin, ypCos, ypSin, ut1Cos, ut1Sin, lodCos, lodSin;\n\n    while(stripComments(file))\n    {\n      std::string name, doodName;\n      Int         arg;\n      Double      period;\n      Double      xs, xc, ys, yc, us, uc, ls, lc;\n      file>>name>>arg>>arg>>arg>>arg>>arg>>arg>>doodName>>period>>xs>>xc>>ys>>yc>>us>>uc>>ls>>lc;\n\n      doodson.push_back(Doodson(doodName));\n      xpCos.push_back(1e-6*xc); // micro arc sec -> arc sec\n      xpSin.push_back(1e-6*xs);\n      ypCos.push_back(1e-6*yc);\n      ypSin.push_back(1e-6*ys);\n      ut1Cos.push_back(1e-6*uc); // micro seconds -> seconds\n      ut1Sin.push_back(1e-6*us);\n      lodCos.push_back(1e-6*lc);\n      lodSin.push_back(1e-6*ls);\n    }\n\n    DoodsonEop doodsonEop;\n    doodsonEop.doodson = doodson;\n    doodsonEop.coeff   = Matrix(doodson.size(), 8);\n    for(UInt i=0; i<doodson.size(); i++)\n    {\n      doodsonEop.coeff(i, 0) = xpCos.at(i);\n      doodsonEop.coeff(i, 1) = xpSin.at(i);\n      doodsonEop.coeff(i, 2) = ypCos.at(i);\n      doodsonEop.coeff(i, 3) = ypSin.at(i);\n      doodsonEop.coeff(i, 4) = ut1Cos.at(i);\n      doodsonEop.coeff(i, 5) = ut1Sin.at(i);\n      doodsonEop.coeff(i, 6) = lodCos.at(i);\n      doodsonEop.coeff(i, 7) = lodSin.at(i);\n    }\n\n    // Save to file\n    // ------------\n    logStatus<<\"write doodson EOP file <\"<<fileNameDoodsonEop<<\">\"<<Log::endl;\n    writeFileDoodsonEarthOrientationParameter(fileNameDoodsonEop, doodsonEop);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/eop/iersRapidIAU2000EarthOrientationParameter.cpp",
    "content": "/***********************************************/\n/**\n* @file iersRapidIAU2000EarthOrientationParameter.cpp\n*\n* @brief Read Earth Orientation Parameter from rapid file format.\n*\n* @author Andreas KVas\n* @date 2016-03-21\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead a IERS Earth orientation rapid data and prediction file (IAU2000)\nand write it as \\configFile{outputfileEOP}{earthOrientationParameter}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read Earth Orientation Parameter.\n* @ingroup programsConversionGroup */\nclass IersRapidIAU2000EarthOrientationParameter\n{\n  Double getDouble(std::string s, const std::vector<Double>& vals, double f=1.0) const;\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(IersRapidIAU2000EarthOrientationParameter, SINGLEPROCESS, \"read Earth Orientation Parameter\", Conversion)\nGROOPS_RENAMED_PROGRAM(IersRapidEop2Earthrotation, IersRapidIAU2000EarthOrientationParameter, date2time(2020, 9, 8))\n\n/***********************************************/\n\nvoid IersRapidIAU2000EarthOrientationParameter::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName inName, outName;\n    Time timeStart = Time();\n    Time timeEnd   = date2time(9999,1,1);\n\n    readConfig(config, \"outputfileEOP\", outName,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",     inName,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeStart\",     timeStart, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"timeEnd\",       timeEnd,   Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // Erdrotationsparameter einlesen\n    // ------------------------------\n    logStatus<<\"read input file <\"<<inName<<\">\"<<Log::endl;\n    InFile file(inName);\n\n    std::vector<Double> mjd, xp, yp, du, ld, dX, dY;\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n\n      Double _mjd, _xp, _yp, _du, _dX, _dY, _ld;\n      if(!(std::stringstream(line.substr(7, 8))>>_mjd))\n        throw(Exception(\"Error reading MJD from EOP file.\"));\n\n      Time time = mjd2time(_mjd);\n      if((time<timeStart)||(time>timeEnd))\n        continue;\n\n      _xp = getDouble(line.substr( 18,  9),xp);\n      _yp = getDouble(line.substr( 37,  9),yp);\n      _du = getDouble(line.substr( 58, 10),du);\n      _ld = getDouble(line.substr( 79,  7),ld,1e3);\n      _dX = getDouble(line.substr( 97,  9),dX,1e3);\n      _dY = getDouble(line.substr(116,  9),dY,1e3);\n\n      mjd.push_back(_mjd);\n      xp.push_back(_xp);\n      yp.push_back(_yp);\n      du.push_back(_du);\n      ld.push_back(_ld*1e-3);\n      dX.push_back(_dX*1e-3);\n      dY.push_back(_dY*1e-3);\n    }\n\n    logInfo<<\"  count = \"<<mjd.size()<<Log::endl;\n    if(mjd.size())\n    {\n      logInfo<<\"  start = \"<<mjd2time(mjd.at(0)).dateTimeStr()<<Log::endl;\n      logInfo<<\"  end   = \"<<mjd2time(mjd.back()).dateTimeStr()<<Log::endl;\n    }\n\n    Matrix EOP(mjd.size(), 7);\n    for(UInt i=0; i<EOP.rows(); i++)\n    {\n      EOP(i,0) = mjd.at(i);\n      EOP(i,1) = xp.at(i);\n      EOP(i,2) = yp.at(i);\n      EOP(i,3) = du.at(i);\n      EOP(i,4) = ld.at(i);\n      EOP(i,5) = dX.at(i);\n      EOP(i,6) = dY.at(i);\n    }\n\n    // Save to file\n    // ------------\n    logStatus<<\"write EOPs\"<<Log::endl;\n    writeFileEarthOrientationParameter(outName, EOP);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble IersRapidIAU2000EarthOrientationParameter::getDouble(std::string s, const std::vector<Double>& vals, double f) const\n{\n  Double val;\n  if(std::stringstream(s)>>val)\n    return val;\n  else if(vals.size())\n      return vals.back()*f;\n  else\n    throw(Exception(\"Error reading value from EOP file.\"));\n}\n"
  },
  {
    "path": "source/programs/conversion/eop/igs2EarthOrientationParameter.cpp",
    "content": "/***********************************************/\n/**\n* @file igs2EarthOrientationParameter.cpp\n*\n* @brief Earth Orientation Parameter from IGS daily file.\n*\n* @author Andreas Kvas\n* @date 2015-04-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead Rapid Earth Orientation Parameter from IGS daily file\nand write it as \\configFile{outputfileEOP}{earthOrientationParameter}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Earth Orientation Parameter from IGS daily file.\n* @ingroup programsConversionGroup */\nclass Igs2EarthOrientationParameter\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Igs2EarthOrientationParameter, SINGLEPROCESS, \"Earth Orientation Parameter from IGS daily file\", Conversion)\nGROOPS_RENAMED_PROGRAM(IGS2EarthRotation, Igs2EarthOrientationParameter, date2time(2020, 9, 8))\n\n/***********************************************/\n\nvoid Igs2EarthOrientationParameter::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              outName;\n    std::vector<FileName> fileNameIn;\n    Time timeStart, timeEnd = date2time(9999,1,1);\n\n    readConfig(config, \"outputfileEOP\", outName,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",     fileNameIn, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeStart\",     timeStart,  Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"timeEnd\",       timeEnd,    Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    std::vector<Double> mjd, xp, yp, du, ld, dX, dY;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      InFile file(fileNameIn.at(idFile));\n\n      std::string line;\n      for(UInt i=0; i<9; i++)\n        std::getline(file, line); // header\n\n      Double _mjd, _xp, _yp, _du, _ld;\n      file>>_mjd>>_xp>>_yp>>_du>>_ld;\n\n      if((_mjd < timeStart.mjd()) || (_mjd > timeEnd.mjd()))\n        continue;\n\n      mjd.push_back(_mjd);\n      xp.push_back(_xp*1e-6);\n      yp.push_back(_yp*1e-6);\n      du.push_back(_du*1e-7);\n      ld.push_back(_ld*1e-7);\n      dX.push_back(0.0);\n      dY.push_back(0.0);\n    } // for(idFile)\n\n\n    logInfo<<\"  count = \"<<mjd.size()<<Log::endl;\n    if(mjd.size())\n    {\n      logInfo<<\"  start = \"<<mjd2time(mjd.at(0)).dateTimeStr()<<Log::endl;\n      logInfo<<\"  end   = \"<<mjd2time(mjd.back()).dateTimeStr()<<Log::endl;\n    }\n\n    Matrix EOP(mjd.size(), 7);\n    for(UInt i=0; i<EOP.rows(); i++)\n    {\n      EOP(i,0) = mjd.at(i);\n      EOP(i,1) = xp.at(i);\n      EOP(i,2) = yp.at(i);\n      EOP(i,3) = du.at(i);\n      EOP(i,4) = ld.at(i);\n      EOP(i,5) = dX.at(i);\n      EOP(i,6) = dY.at(i);\n    }\n\n    logStatus<<\"write EOPs\"<<Log::endl;\n    writeFileEarthOrientationParameter(outName, EOP);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssAntex2AntennaDefinition.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAntex2AntennaDefinition.cpp\n*\n* @brief Converts IGS ANTEX file to GNSS metadata and antenna definition files.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-11-23\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts metadata and antenna definitions from the \\href{https://files.igs.org/pub/data/format/antex14.txt}{IGS ANTEX format}.\nto \\configFile{antennaDefinition}{gnssAntennaDefinition}, \\configFile{transmitterInfo}{platform}, and\n\\configFile{transmitterList}{stringList} files for the respective GNSS and for the list of ground station antennas.\n\nThe \\file{transmitterInfo}{platform} files for GLONASS satellites should then be updated using \\program{GnssGlonassFrequencyNumberUpdate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileStringTable.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts IGS ANTEX file to GNSS metadata and antenna definition files.\n* @ingroup programsConversionGroup */\nclass GnssAntex2AntennaDefinition\n{\n  Bool getLine(InFile &file, std::string &line, std::string &label, Bool throwException=FALSE) const;\n  Bool testLabel(const std::string &labelInLine, const std::string &label, Bool optional=FALSE) const;\n  static Bool equal(GnssAntennaDefinitionPtr antenna, GnssAntennaDefinitionPtr antenna2);\n  void addAntenna(GnssAntennaDefinitionPtr antenna, std::vector<GnssAntennaDefinitionPtr> &antennaList);\n  void addTransmitter(const PlatformGnssAntenna &platformAntenna, const std::string &markerName, const std::string &markerNumber, std::vector<Platform> &transmitterList);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAntex2AntennaDefinition, SINGLEPROCESS, \"Converts IGS ANTEX file to GNSS metadata and antenna definition files.\", Conversion, Gnss)\n\n/***********************************************/\n\nvoid GnssAntex2AntennaDefinition::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameAntennaStation, fileNameAntennaTransmitter, fileNameTransmitterInfo;\n    FileName fileNameTransmitterListGps, fileNameTransmitterListGlonass, fileNameTransmitterListGalileo;\n    FileName fileNameTransmitterListBeiDou, fileNameTransmitterListQzss, fileNameTransmitterListIrnss;\n    FileName fileNameAntex;\n    Time     timeStart;\n    Bool     setZero;\n\n    readConfig(config, \"outputfileAntennaDefinitionStation\",     fileNameAntennaStation,         Config::OPTIONAL, \"\",  \"antenna center variations\");\n    readConfig(config, \"outputfileAntennaDefinitionTransmitter\", fileNameAntennaTransmitter,     Config::OPTIONAL, \"\",  \"antenna center variations\");\n    readConfig(config, \"outputfileTransmitterInfo\",              fileNameTransmitterInfo,        Config::OPTIONAL, \"\",  \"PRN is appended to file name\");\n    readConfig(config, \"outputfileTransmitterListGps\",           fileNameTransmitterListGps,     Config::OPTIONAL, \"\",  \"list of PRNs\");\n    readConfig(config, \"outputfileTransmitterListGlonass\",       fileNameTransmitterListGlonass, Config::OPTIONAL, \"\",  \"list of PRNs\");\n    readConfig(config, \"outputfileTransmitterListGalileo\",       fileNameTransmitterListGalileo, Config::OPTIONAL, \"\",  \"list of PRNs\");\n    readConfig(config, \"outputfileTransmitterListBeiDou\",        fileNameTransmitterListBeiDou,  Config::OPTIONAL, \"\",  \"list of PRNs\");\n    readConfig(config, \"outputfileTransmitterListQzss\",          fileNameTransmitterListQzss,    Config::OPTIONAL, \"\",  \"list of PRNs\");\n    readConfig(config, \"outputfileTransmitterListIrnss\",         fileNameTransmitterListIrnss,   Config::OPTIONAL, \"\",  \"list of PRNs\");\n    readConfig(config, \"inputfileAntex\",                         fileNameAntex,                  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeStart\",                              timeStart,                      Config::OPTIONAL, \"\",  \"ignore older antenna definitions\");\n    readConfig(config, \"createZeroModel\",                        setZero,                        Config::DEFAULT,  \"0\", \"create empty antenna patterns\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    std::vector<PlatformGnssAntenna> antennaInfos;\n\n    // Open file\n    // ---------\n    InFile file(fileNameAntex);\n    file.exceptions(std::ios::badbit|std::ios::failbit);\n\n    // Read Header\n    // -----------\n    std::string line, label;\n    do\n    {\n      getLine(file, line, label);\n    }\n    while(!testLabel(label, \"END OF HEADER\", TRUE));\n\n    // Read data\n    // ---------\n    for(;;)\n    {\n      PlatformGnssAntenna      antennaInfo;\n      GnssAntennaDefinitionPtr antenna = GnssAntennaDefinitionPtr(new GnssAntennaDefinition);\n      antennaInfo.antennaDef = antenna;\n\n      if(!getLine(file, line, label, FALSE))\n        break;\n      testLabel(label, \"START OF ANTENNA\");\n      getLine(file, line, label);\n\n      // BLOCK IIA           G01                 G032      1992-079A TYPE / SERIAL NO\n      // JAVRINGANT_DMT  SCIS                                        TYPE / SERIAL NO\n      testLabel(label, \"TYPE / SERIAL NO\");\n      antenna->name   = String::trim(line.substr( 0,16));\n      antenna->radome = String::trim(line.substr(16,4));\n      if(antenna->radome == \"NONE\")\n        antenna->radome.clear();\n      antenna->serial    = String::trim(line.substr(20,20));\n      antennaInfo.serial = String::trim(line.substr(40,10)); // SVN\n      antennaInfo.radome = String::trim(line.substr(50,10)); // COSPAR\n\n      getLine(file, line, label);\n      testLabel(label, \"METH / BY / # / DATE\");\n\n      getLine(file, line, label);\n      testLabel(label, \"DAZI\");\n      UInt azimutCount = 0;\n      Double dazi = String::toDouble(line.substr(2, 6));\n      if(dazi!=0)\n        azimutCount = static_cast<UInt>(360./dazi);\n\n      getLine(file, line, label);\n      testLabel(label, \"ZEN1 / ZEN2 / DZEN\");\n      Double zen1 = String::toDouble(line.substr(2, 6));\n      Double zen2 = String::toDouble(line.substr(8, 6));\n      Double dzen = String::toDouble(line.substr(14, 6));\n      UInt zenCount = static_cast<UInt>((zen2-zen1)/dzen+1);\n      getLine(file, line, label);\n      testLabel(label, \"# OF FREQUENCIES\");\n      UInt freqCount = String::toInt(line.substr(0, 6));\n      getLine(file, line, label);\n\n      // Optionals\n      // ---------\n      Int  year,month,day,hour,min;\n      Double sec;\n      if(testLabel(label, \"VALID FROM\", TRUE))\n      {\n        year  = String::toInt(line.substr(0, 6));\n        month = String::toInt(line.substr(6, 6));\n        day   = String::toInt(line.substr(12, 6));\n        hour  = String::toInt(line.substr(18, 6));\n        min   = String::toInt(line.substr(24, 6));\n        sec   = String::toDouble(line.substr(33, 13));\n        antennaInfo.timeStart = date2time(year, month, day, hour, min, sec);\n        getLine(file, line, label);\n      }\n      else\n        antennaInfo.timeStart = Time();\n\n      if(testLabel(label, \"VALID UNTIL\", TRUE))\n      {\n        year  = String::toInt(line.substr(0, 6));\n        month = String::toInt(line.substr(6, 6));\n        day   = String::toInt(line.substr(12, 6));\n        hour  = String::toInt(line.substr(18, 6));\n        min   = String::toInt(line.substr(24, 6));\n        sec   = String::toDouble(line.substr(33, 13));\n        if(sec >= 59)\n          sec = 60; // to prevent gaps, since VALID UNTIL is inclusive in ANTEX but timeEnd is exclusive in GROOPS\n        antennaInfo.timeEnd = date2time(year, month, day, hour, min, sec);\n        getLine(file, line, label);\n      }\n      else\n        antennaInfo.timeEnd = date2time(2500,1,1,0,0,0);\n\n      if(testLabel(label, \"SINEX CODE\", TRUE))\n      {\n        getLine(file, line, label);\n        while (testLabel(label, \"SINEX CODE\", TRUE))\n        {\n          logWarning<<\"Multiple lines with <SINEX CODE> detected for antenna \"<<antenna->name<<\" \"<<antenna->serial<<\" \"<<antennaInfo.serial<<Log::endl;\n          getLine(file, line, label);\n        }\n      }\n\n      while(testLabel(label, \"COMMENT\", TRUE))\n      {\n        if(!antennaInfo.comment.empty())\n          antennaInfo.comment += \"\\n\";\n        antennaInfo.comment += String::trim(line.substr(0,60));\n        getLine(file, line, label);\n      }\n\n      antenna->patterns.resize(freqCount);\n\n      for(UInt i=0; i<freqCount; i++)\n      {\n        testLabel(label, \"START OF FREQUENCY\");\n\n        antenna->patterns.at(i).type = GnssType();\n        switch(line.at(3))\n        {\n          case ' ': break;\n          case 'G': antenna->patterns.at(i).type += GnssType::GPS;      break;\n          case 'R': antenna->patterns.at(i).type += GnssType::GLONASS;  break;\n          case 'E': antenna->patterns.at(i).type += GnssType::GALILEO;  break;\n          case 'C': antenna->patterns.at(i).type += GnssType::BDS;      break;\n          case 'S': antenna->patterns.at(i).type += GnssType::SBAS;     break;\n          case 'I': antenna->patterns.at(i).type += GnssType::IRNSS;    break;\n          case 'J': antenna->patterns.at(i).type += GnssType::QZSS;     break;\n          default:\n            logWarning<<\"Unknown satellite system: '\"<<line<<\"'\"<<Log::endl;\n        }\n        switch(String::toInt(line.substr(4, 2)))\n        {\n          case 0: break;\n          case 1: antenna->patterns.at(i).type += GnssType::L1;  break;\n          case 2: antenna->patterns.at(i).type += GnssType::L2;  break;\n          case 3: antenna->patterns.at(i).type += GnssType::G3;  break;\n          case 4: antenna->patterns.at(i).type += GnssType::G1a; break;\n          case 5: antenna->patterns.at(i).type += GnssType::L5;  break;\n          case 6: antenna->patterns.at(i).type += GnssType::E6;  break;\n          case 7: antenna->patterns.at(i).type += GnssType::E5b; break;\n          case 8: antenna->patterns.at(i).type += GnssType::E5;  break;\n          case 9: antenna->patterns.at(i).type += GnssType::S9;  break;\n          default:\n            logWarning<<\"Unknown frequency: '\"<<line<<\"'\"<<Log::endl;\n        }\n        getLine(file, line, label);\n\n        testLabel(label, \"NORTH / EAST / UP\");\n        Double x = String::toDouble(line.substr(0, 10));\n        Double y = String::toDouble(line.substr(10, 10));\n        Double z = String::toDouble(line.substr(20, 10));\n        // from millimeters to meters\n        if(!setZero) antenna->patterns.at(i).offset = 1e-3 * Vector3d(x,y,z);\n\n        antenna->patterns.at(i).dZenit  = Angle(dzen*DEG2RAD);\n        if(azimutCount)\n          antenna->patterns.at(i).pattern = Matrix(azimutCount, zenCount);\n        else\n          antenna->patterns.at(i).pattern = Matrix(1, zenCount);\n\n        // read NOAZI\n        getLine(file, line, label);\n        for(UInt s=0; s<zenCount; s++)\n          if(!setZero) antenna->patterns.at(i).pattern(0,s) = 1e-3 * String::toDouble(line.substr(8+8*s, 8));\n\n        // Azimuth dependent values\n        getLine(file, line, label);\n        if(azimutCount)\n          for(UInt z=0; z<azimutCount+1; z++)\n          {\n            for(UInt s=0; s<zenCount; s++)\n              if(!setZero) antenna->patterns.at(i).pattern(z%azimutCount,s) = 1e-3 * String::toDouble(line.substr(8+8*s, 8));\n            getLine(file, line, label);\n          }\n\n        testLabel(label, \"END OF FREQUENCY\");\n        getLine(file, line, label);\n\n        // skip optional frequency RMS block\n        if(testLabel(label, \"START OF FREQ RMS\", TRUE))\n        {\n          for(;;)\n          {\n            getLine(file, line, label);\n            if(testLabel(label, \"END OF FREQ RMS\", TRUE))\n              break;\n          }\n          getLine(file, line, label);\n        }\n      }\n      testLabel(label, \"END OF ANTENNA\");\n\n      if((antennaInfo.timeEnd == date2time(2500,1,1,0,0,0)) || (antennaInfo.timeEnd > timeStart))\n        antennaInfos.push_back(antennaInfo);\n    } // for(antenna section)\n\n    // ==============================\n\n    // Satellites: Shift mean antenna offsets to PlatformEquipment::position\n    // ---------------------------------------------------------------------\n    for(auto &antennaInfo : antennaInfos)\n      if(!antennaInfo.serial.empty()) // with SVN\n      {\n        // transformation to left-handed antenna system\n        antennaInfo.local2antennaFrame = flipY() * rotaryZ(Angle(PI/2));\n\n        // set the PlatformEquipment::position as the mean of offsets of all patterns\n        auto antenna = antennaInfo.antennaDef;\n        for(UInt i=0; i<antenna->patterns.size(); i++)\n          antennaInfo.position += (1./antenna->patterns.size()) * antenna->patterns.at(i).offset;\n        // shift the origin of offsets from the reference point (CoM) to PlatformEquipment::position\n        for(UInt i=0; i<antenna->patterns.size(); i++)\n          antenna->patterns.at(i).offset = antennaInfo.local2antennaFrame.transform(antenna->patterns.at(i).offset - antennaInfo.position);\n      }\n\n    // ==============================\n\n    // Distinguish between different antennas for the same SVN by using different radome names\n    // ---------------------------------------------------------------------------------------\n    // sort SVNs, timeStart\n    std::stable_sort(antennaInfos.begin(), antennaInfos.end(), [](auto &a1, auto &a2) {return (a1.serial != a2.serial) ? (a1.serial < a2.serial) : (a1.timeEnd < a2.timeEnd);});\n\n    for(UInt i=antennaInfos.size()-1; i-->0;)\n      if(!antennaInfos.at(i).serial.empty() && (antennaInfos.at(i).serial == antennaInfos.at(i+1).serial)) // with same SVN as before\n      {\n        if(equal(antennaInfos.at(i).antennaDef, antennaInfos.at(i+1).antennaDef))\n          antennaInfos.at(i).radome = antennaInfos.at(i+1).radome; // copy COSPAR + valid until\n        else\n          antennaInfos.at(i).radome = antennaInfos.at(i).radome.substr(0, 9)+\" (valid unil \"s+antennaInfos.at(i).timeEnd.dateTimeStr()+\")\"s;\n      }\n\n    // ==============================\n\n    std::vector<GnssAntennaDefinitionPtr> antennaListStation, antennaListTransmitter;\n    std::vector<Platform>                 transmitterList;\n\n    for(auto &antennaInfo : antennaInfos)\n    {\n      auto antenna = antennaInfo.antennaDef;\n\n      if(!antennaInfo.serial.empty()) // satellites with SVN\n      {\n        // Satellites\n        std::string prn  = antenna->serial;\n        antenna->serial  = antennaInfo.serial; // SVN;\n        antenna->radome  = antennaInfo.radome; // COSPAR;\n        antennaInfo.name = antenna->name;      // BLOCK name\n        addAntenna(antenna, antennaListTransmitter);\n\n        if     (antenna->name.find(\"BLOCK\")   != std::string::npos) addTransmitter(antennaInfo, \"GPS\",     prn, transmitterList);\n        else if(antenna->name.find(\"GLONASS\") != std::string::npos) addTransmitter(antennaInfo, \"GLONASS\", prn, transmitterList);\n        else if(antenna->name.find(\"GALILEO\") != std::string::npos) addTransmitter(antennaInfo, \"GALILEO\", prn, transmitterList);\n        else if(antenna->name.find(\"BEIDOU\")  != std::string::npos) addTransmitter(antennaInfo, \"BEIDOU\",  prn, transmitterList);\n        else if(antenna->name.find(\"QZSS\")    != std::string::npos) addTransmitter(antennaInfo, \"QZSS\",    prn, transmitterList);\n        else if(antenna->name.find(\"IRNSS\")   != std::string::npos) addTransmitter(antennaInfo, \"IRNSS\",   prn, transmitterList);\n        else\n          logWarning<<\"Unknown satellite: \"<<prn<<\" \"<<antenna->serial<<\" (\"<<antenna->name<<\", \"<<antenna->radome<<\")\"<<Log::endl;\n      }\n      else if(antennaInfo.timeStart == Time() && antennaInfo.timeEnd == date2time(2500,1,1,0,0,0)) // stations\n      {\n        addAntenna(antenna, antennaListStation);\n      }\n      else\n        logWarning<<\"antenna '\"<<antenna->name<<\".\"<<antenna->serial<<\".\"<<antenna->radome<<\"' with validity period -> skipped\"<<Log::endl;\n    }\n\n    // ==============================\n\n    // save\n    // ----\n    if(!fileNameAntennaStation.empty() && antennaListStation.size())\n    {\n      logStatus<<\"save antennas to <\"<<fileNameAntennaStation<<\">\"<< Log::endl;\n      writeFileGnssAntennaDefinition(fileNameAntennaStation, antennaListStation);\n    }\n\n    if(!fileNameAntennaTransmitter.empty() && antennaListTransmitter.size())\n    {\n      logStatus<<\"save antennas to <\"<<fileNameAntennaTransmitter<<\">\"<< Log::endl;\n      writeFileGnssAntennaDefinition(fileNameAntennaTransmitter, antennaListTransmitter);\n    }\n\n    if(!fileNameTransmitterInfo.empty() && transmitterList.size())\n    {\n      logStatus<<\"save transmitter info to <\"<<fileNameTransmitterInfo<<\">\"<< Log::endl;\n      for(const auto &transmitter : transmitterList)\n        writeFilePlatform(fileNameTransmitterInfo.appendBaseName(\".\"+transmitter.markerNumber), transmitter);\n    }\n\n    auto writeTransmitterList = [&](const FileName &fileNameTransmitterList, const std::string &markerName)\n    {\n      if(!fileNameTransmitterList.empty() && transmitterList.size())\n      {\n        logStatus<<\"save transmitter list to <\"<<fileNameTransmitterList<<\">\"<< Log::endl;\n        std::set<std::string> list;\n        for(const auto &transmitter : transmitterList)\n          if(transmitter.markerName == markerName)\n            list.insert(transmitter.markerNumber);\n        writeFileStringList(fileNameTransmitterList, std::vector<std::string>(list.begin(), list.end()));\n      }\n    };\n\n    writeTransmitterList(fileNameTransmitterListGps,     \"GPS\");\n    writeTransmitterList(fileNameTransmitterListGlonass, \"GLONASS\");\n    writeTransmitterList(fileNameTransmitterListGalileo, \"GALILEO\");\n    writeTransmitterList(fileNameTransmitterListBeiDou,  \"BEIDOU\");\n    writeTransmitterList(fileNameTransmitterListQzss,    \"QZSS\");\n    writeTransmitterList(fileNameTransmitterListIrnss,   \"IRNSS\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nBool GnssAntex2AntennaDefinition::getLine(InFile &file, std::string &line, std::string &label, Bool throwException) const\n{\n  try\n  {\n    std::getline(file, line);\n    if(line.size()<80)\n      line.resize(80,' ');\n    label = line.substr(60,20);\n    return TRUE;\n  }\n  catch(std::exception &/*e*/)\n  {\n    if(throwException)\n      throw(Exception(std::string(\"IO Error: '\")+line+\"'\"));\n    line.clear();\n    line.resize(80,' ');\n    label = line.substr(60,20);\n    return FALSE;\n  }\n}\n\n/***********************************************/\n\nBool GnssAntex2AntennaDefinition::testLabel(const std::string &labelInLine, const std::string &label, Bool optional) const\n{\n  if(labelInLine.find(label)!=std::string::npos)\n    return TRUE;\n  if(optional)\n    return FALSE;\n  throw(Exception(std::string(\"In Line '\")+labelInLine+\"' label '\"+label+\"' expected\\n\"));\n}\n\n/***********************************************/\n\nBool GnssAntex2AntennaDefinition::equal(GnssAntennaDefinitionPtr antenna, GnssAntennaDefinitionPtr antenna2)\n{\n  try\n  {\n    // check if antennas are identical\n    if(antenna->patterns.size() != antenna2->patterns.size())\n      return FALSE;\n    for(UInt idPattern=0; idPattern<antenna->patterns.size(); idPattern++)\n    {\n      if((antenna->patterns.at(idPattern).type              != antenna2->patterns.at(idPattern).type) ||\n         (antenna->patterns.at(idPattern).pattern.rows()    != antenna2->patterns.at(idPattern).pattern.rows()) ||\n         (antenna->patterns.at(idPattern).pattern.columns() != antenna2->patterns.at(idPattern).pattern.columns()))\n        return FALSE;\n      if(((antenna->patterns.at(idPattern).offset - antenna2->patterns.at(idPattern).offset).r() > 0.0001) ||\n         (maxabs(antenna->patterns.at(idPattern).pattern - antenna2->patterns.at(idPattern).pattern) > 0.0001))\n        return FALSE;\n    }\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssAntex2AntennaDefinition::addAntenna(GnssAntennaDefinitionPtr antenna, std::vector<GnssAntennaDefinitionPtr> &antennaList)\n{\n  try\n  {\n    auto iter = std::find_if(antennaList.begin(), antennaList.end(), [&](auto &a){return ((a->name == antenna->name) && (a->serial == antenna->serial) && (a->radome == antenna->radome));});\n    if(iter == antennaList.end())\n      antennaList.push_back(antenna);\n    else if(!equal(antenna, *iter))\n      logWarning<<\"antenna '\"<<antenna->name<<\".\"<<antenna->serial<<\".\"<<antenna->radome<<\"' already in the list with different values -> skipped\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssAntex2AntennaDefinition::addTransmitter(const PlatformGnssAntenna &antennaInfo, const std::string &markerName, const std::string &markerNumber, std::vector<Platform> &transmitterList)\n{\n  try\n  {\n    const UInt idSat = std::distance(transmitterList.begin(), std::find_if(transmitterList.begin(), transmitterList.end(),\n                                                                           [&](auto &t){return t.markerNumber == markerNumber;}));\n    if(idSat >= transmitterList.size()) // new PRN?\n    {\n      Platform satelliteGps;\n      satelliteGps.markerName   = markerName;\n      satelliteGps.markerNumber = markerNumber;\n      transmitterList.push_back(satelliteGps);\n    }\n\n    PlatformGnssReceiver receiverInfo;\n    receiverInfo.name      = antennaInfo.name;\n    receiverInfo.serial    = antennaInfo.serial;\n    receiverInfo.timeStart = antennaInfo.timeStart;\n    receiverInfo.timeEnd   = antennaInfo.timeEnd;\n    transmitterList.at(idSat).equipments.push_back(std::make_shared<PlatformGnssAntenna>(antennaInfo));\n    transmitterList.at(idSat).equipments.push_back(std::make_shared<PlatformGnssReceiver>(receiverInfo));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssClock2ClockRinex.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssClock2ClockRinex.cpp\n*\n* @brief Converts GNSS clocks from GROOPS format to IGS clock RINEX format.\n*\n* @author Sebastian Strasser\n* @date 2019-01-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts GNSS clocks from GROOPS format to \\href{https://files.igs.org/pub/data/format/rinex_clock304.txt}{IGS clock RINEX format}.\nClocks can be provided via \\config{satelliteData} and/or \\config{stationData}.\nObserved signal types are inferred from \\configFile{inputfileSignalBias}{gnssSignalBias}.\nSatellites/stations used as clock references can be provided via \\config{referenceClock}.\n\nSee IGS clock RINEX format description for further details on header information.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n#include <chrono>\n\n/***** CLASS ***********************************/\n\n/** @brief Converts GNSS clocks from GROOPS format to IGS clock RINEX format.\n* @ingroup programsConversionGroup */\nclass GnssClock2ClockRinex\n{\npublic:\n  class Data\n  {\n  public:\n    FileName inNameClock;\n    std::string identifier;\n    MiscValueArc arc;\n    std::vector<Time> times;\n    UInt idEpoch;\n\n    Data() : idEpoch(0) {}\n  };\n\n  class SatelliteData : public Data\n  {\n  public:\n    FileName inNameBias;\n\n    SatelliteData() : Data() {}\n  };\n\n  class StationData : public Data\n  {\n  public:\n    FileName inNamePosition, inNameStationInfo;\n    Vector3d position;\n    std::string markerNumber;\n\n    StationData() : Data() {}\n  };\n\n  typedef std::shared_ptr<Data> DataPtr;\n\nprivate:\n  void readSatelliteData(std::vector<SatelliteData> &data, std::map<Char, std::set<std::string>> &system2ObsTypes) const;\n  void readStationData(std::vector<StationData> &data) const;\n  void writeEpoch(const Time &time, Char type, std::vector<DataPtr> &data, OutFile &file) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssClock2ClockRinex, SINGLEPROCESS, \"Converts GNSS clocks from GROOPS format to IGS clock RINEX format.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssClock2ClockRinex::SatelliteData &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileClock\",       var.inNameClock, Config::MUSTSET, \"\", \"clock instrument file\");\n  readConfig(config, \"inputfileSignalBias\",  var.inNameBias,  Config::MUSTSET, \"\", \"signal bias file\");\n  readConfig(config, \"identifier\",           var.identifier,  Config::MUSTSET, \"\", \"PRN (e.g. G23)\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssClock2ClockRinex::StationData &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileClock\",       var.inNameClock,       Config::MUSTSET, \"\", \"clock instrument file\");\n  readConfig(config, \"inputfilePosition\",    var.inNamePosition,    Config::MUSTSET, \"\", \"station position file\");\n  readConfig(config, \"inputfileStationInfo\", var.inNameStationInfo, Config::MUSTSET, \"\", \"station info file\");\n  readConfig(config, \"identifier\",           var.identifier,        Config::MUSTSET, \"\", \"station name (e.g. wtzz)\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssClock2ClockRinex::readSatelliteData(std::vector<SatelliteData> &data, std::map<Char, std::set<std::string>> &system2ObsTypes) const\n{\n  try\n  {\n    auto iter = data.begin();\n    while(iter != data.end())\n    {\n      GnssSignalBias bias;\n      try\n      {\n        iter->arc = InstrumentFile::read(iter->inNameClock);\n        readFileGnssSignalBias(iter->inNameBias, bias);\n      }\n      catch(std::exception &e)\n      {\n        logWarning << e.what() << \" continue...\" << Log::endl;\n        iter = data.erase(iter);\n        continue;\n      }\n\n      iter->times = iter->arc.times();\n      iter->identifier.resize(4, ' ');\n\n      // Code biases\n      for(const auto &type : bias.types)\n        if(type == GnssType::RANGE)\n          system2ObsTypes[type.str().at(3)].insert(type.str().substr(0,3));\n\n      // Phase biases (for wildcard types, i.e. L1*, write one line per matching code bias type with the same phase bias; example: C1C, C1W, L1* ==> C1C, C1W, L1C, L1W)\n      for(UInt i = 0; i < bias.types.size(); i++)\n        if(bias.types.at(i) == GnssType::PHASE)\n          for(UInt j = 0; j < bias.types.size(); j++)\n            if(bias.types.at(j) == (bias.types.at(i) & ~GnssType::TYPE) + GnssType::RANGE)\n              system2ObsTypes[bias.types.at(i).str().at(3)].insert(((bias.types.at(j) & ~GnssType::TYPE) + GnssType::PHASE).str().substr(0,3));\n      iter++;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssClock2ClockRinex::readStationData(std::vector<StationData> &data) const\n{\n  try\n  {\n    auto iter = data.begin();\n    while(iter != data.end())\n    {\n      Platform platform;\n      try\n      {\n        iter->arc = InstrumentFile::read(iter->inNameClock);\n        iter->position = Vector3d(InstrumentFile::read(iter->inNamePosition).at(0).data());\n        readFilePlatform(iter->inNameStationInfo, platform);\n      }\n      catch(std::exception &e)\n      {\n        logWarning << e.what() << \" continue...\" << Log::endl;\n        iter = data.erase(iter);\n        continue;\n      }\n\n      iter->times = iter->arc.times();\n      iter->identifier.resize(4, ' ');\n      std::transform(iter->identifier.begin(), iter->identifier.end(), iter->identifier.begin(), ::toupper);\n      iter->markerNumber = platform.markerNumber;\n      iter->markerNumber.resize(20, ' ');\n\n      iter++;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nvoid GnssClock2ClockRinex::writeEpoch(const Time &time, Char type, std::vector<DataPtr> &data, OutFile &file) const\n{\n  try\n  {\n    for(auto &&d : data)\n    {\n      if(d->idEpoch >= d->times.size() || d->times.at(d->idEpoch) != time)\n        continue; // no data for this epoch\n\n      file << 'A' << type << ' ' << d->identifier << ' '<< time%\"%y %m %d %H %M %09.6S\"s << 1%\"% 3i\"s << \"   \" << d->arc.at(d->idEpoch).value%\"%19.12e\"s << std::endl;\n      d->idEpoch++;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssClock2ClockRinex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<SatelliteData> satelliteData;\n    std::vector<StationData> stationData;\n    std::vector<std::string> comment, referenceClocks;\n    std::string program, institution, dcb, pcv, analysisCenter, referenceFrame;\n\n    readConfig(config, \"outputfileClockRinex\",  fileNameOut,     Config::MUSTSET,   \"\", \"\");\n    readConfig(config, \"satelliteData\",         satelliteData,   Config::OPTIONAL,  \"\", \"one element per satellite\");\n    readConfig(config, \"stationData\",           stationData,     Config::OPTIONAL,  \"\", \"one element per station\");\n    readConfig(config, \"comment\",               comment,         Config::OPTIONAL,  \"\", \"comment in header\");\n    readConfig(config, \"program\",               program,         Config::MUSTSET,   \"GROOPS\", \"name of program (for first line)\");\n    readConfig(config, \"institution\",           institution,     Config::MUSTSET,   \"TUG (TU Graz)\", \"name of agency (for first line)\");\n    readConfig(config, \"analysisCenter\",        analysisCenter,  Config::MUSTSET,   \"TUG  Graz University of Technology (TU Graz), Austria\", \"name of analysis center\");\n    readConfig(config, \"differentialCodeBias\",  dcb,             Config::OPTIONAL,  \"GROOPS            OSB co-estimated in LSA (see bias file)\", \"program and source for applied differential code bias\");\n    readConfig(config, \"phaseCenterVariations\", pcv,             Config::MUSTSET,   \"GROOPS            igs20.atx @ files.igs.org \", \"program and source for applied phase center variations\");\n    readConfig(config, \"referenceClock\",        referenceClocks, Config::MUSTSET,   \"\", \"identifier of reference satellite/station\");\n    readConfig(config, \"referenceFrame\",        referenceFrame,  Config::MUSTSET,   \"IGb14\", \"terrestrial reference frame for the stations\");\n    if(isCreateSchema(config)) return;\n\n    logStatus << \"read data files\" << Log::endl;\n    std::map<Char, std::set<std::string>> system2ObsTypes;\n    readSatelliteData(satelliteData, system2ObsTypes);\n    readStationData(stationData);\n\n    if(!satelliteData.size() && !stationData.size())\n      throw(Exception(\"no satellite or station data provided\"));\n\n    logStatus << \"write clock RINEX file <\" << fileNameOut << \">\" << Log::endl;\n    OutFile file(fileNameOut);\n\n    // Header: RINEX VERSION / TYPE\n    file << 3.02%\"%9.2f\"s << std::string(11, ' ') << 'C' << std::string(19, ' ') << (system2ObsTypes.size() == 1 ? system2ObsTypes.begin()->first : 'M')\n         << std::string(19, ' ') << \"RINEX VERSION / TYPE\" << std::endl;\n\n    // Header: PGM / RUN BY / DATE\n    auto systemTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());\n    program.resize(20, ' ');\n    institution.resize(20, ' ');\n    file << program << institution << std::put_time(gmtime(&systemTime), \"%Y%m%d %H%M%S\") << \" UTC PGM / RUN BY / DATE\" << std::endl;\n\n    // Header: COMMENT\n    for(auto &c : comment)\n    {\n      c.resize(60, ' ');\n      file << c << \"COMMENT\" << std::endl;\n    }\n\n    // Header: SYS / # / OBS TYPES\n    for(const auto &system : system2ObsTypes)\n    {\n      file << system.first << \"  \" << system.second.size()%\"% 3i\"s;\n      std::vector<std::string> types(system.second.begin(), system.second.end());\n      types.resize(static_cast<UInt>(std::ceil(types.size()/13.)*13), \"   \");\n      for(UInt i = 0; i < types.size(); i++)\n      {\n        file << \" \" << types.at(i);\n        if(i > 0 && (i+1)%13 == 0)\n          file << \"  SYS / # / OBS TYPES\" << std::endl << (i+1 < types.size() ? \"      \" : \"\");\n      }\n    }\n\n    // Header: TIME SYSTEM ID\n    file << std::string(3, ' ') << \"GPS\" << std::string(54, ' ') << \"TIME SYSTEM ID\" << std::endl;\n\n    // Header: SYS / DCBS APPLIED\n    dcb.resize(58, ' ');\n    for(const auto &system : system2ObsTypes)\n      file << system.first << \" \" << dcb << \"SYS / DCBS APPLIED\" << std::endl;\n\n    // Header: SYS / PCVS APPLIED\n    pcv.resize(58, ' ');\n    for(const auto &system : system2ObsTypes)\n      file << system.first << \" \" << pcv << \"SYS / PCVS APPLIED\" << std::endl;\n\n    // Header: # / TYPES OF DATA\n    std::vector<std::string> dataTypes;\n    if(satelliteData.size())\n      dataTypes.push_back(\"AS\");\n    if(stationData.size())\n      dataTypes.push_back(\"AR\");\n    file << dataTypes.size()%\"% 6i\"s;\n    dataTypes.resize(5, \"  \");\n    for(const auto &type : dataTypes)\n      file << std::string(4, ' ') << type;\n    file << std::string(24, ' ') << \"# / TYPES OF DATA\" << std::endl;\n\n    // Header: ANALYSIS CENTER\n    analysisCenter.resize(60, ' ');\n    file << analysisCenter << \"ANALYSIS CENTER\" << std::endl;\n\n    // Header: # OF CLK REF\n    file << referenceClocks.size()%\"% 6i\"s << std::string(54, ' ') << \"# OF CLK REF \" << std::endl;\n\n    // Header: ANALYSIS CLK REF\n    for(auto ref : referenceClocks)\n    {\n      ref.resize(60, ' ');\n      file << ref << \"ANALYSIS CLK REF\" << std::endl;\n    }\n\n    // Header: # OF SOLN STA / TRF\n    if(stationData.size())\n    {\n      referenceFrame.resize(50, ' ');\n      file << stationData.size()%\"% 6i\"s << std::string(4, ' ') << referenceFrame << \"# OF SOLN STA / TRF\" << std::endl;\n    }\n\n    // Header: SOLN STA NAME / NUM\n    if(stationData.size())\n      for(const auto &station : stationData)\n        file << station.identifier << \" \" << station.markerNumber << (station.position.x()*1e3)%\"%11.0f\"s << \" \"\n             << (station.position.y()*1e3)%\"%11.0f\"s << \" \" << (station.position.z()*1e3)%\"%11.0f\"s << \"SOLN STA NAME / NUM\" << std::endl;\n\n    // Header: # OF SOLN SATS\n    if(satelliteData.size())\n      file << satelliteData.size()%\"% 6i\"s << std::string(54, ' ') << \"# OF SOLN SATS \" << std::endl;\n\n    // Header: PRN LIST\n    const UInt count = std::ceil(satelliteData.size()/15.)*15;\n    for(UInt i = 0; i < count; i++)\n    {\n      file << (i < satelliteData.size() ? satelliteData.at(i).identifier : std::string(4, ' '));\n      if(i > 0 && (i+1)%15 == 0)\n        file << \"PRN LIST\" << std::endl;\n    }\n\n    file << std::string(60, ' ') << \"END OF HEADER\" << std::endl;\n\n    // Clock data\n    std::set<Time> times; // unique set of times covering all satellites and stations\n    for(auto &&data : satelliteData)\n      std::copy(data.times.begin(), data.times.end(), std::inserter(times, times.end()));\n    for(auto &&data : stationData)\n      std::copy(data.times.begin(), data.times.end(), std::inserter(times, times.end()));\n\n    UInt i = 0;\n    std::vector<DataPtr> satelliteDataPtrs, stationDataPtrs;\n    for(auto & data : satelliteData)\n      satelliteDataPtrs.push_back(std::make_shared<Data>(data));\n    for(auto & data : stationData)\n      stationDataPtrs.push_back(std::make_shared<Data>(data));\n    Log::Timer timer(times.size());\n    for(const auto &time : times)\n    {\n      timer.loopStep(i++);\n      writeEpoch(time, 'S', satelliteDataPtrs, file);\n      writeEpoch(time, 'R', stationDataPtrs,   file);\n    }\n    timer.loopEnd();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssClockRinex2InstrumentClock.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssClockRinex2InstrumentClock.cpp\n*\n* @brief Convert GNSS clock RINEX files to single value instrument files for satellites or stations.\n*\n* @author Sebastian Strasser\n* @date 2016-07-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring =\nR\"(\nThis program converts clocks from the \\href{https://files.igs.org/pub/data/format/rinex_clock304.txt}{IGS clock RINEX format},\nwhich contains the clocks of all satellites and stations in a single file,\ninto an \\file{instrument file (MISCVALUE)}{instrument} for each \\config{identifier}\n(satellite and/or station).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert GNSS clock RINEX files to single value instrument files for satellites or stations.\n* @ingroup programsConversionGroup */\nclass GnssClockRinex2InstrumentClock\n{\n  void readFile(const FileName &fileName, std::vector<std::string> identifier, std::vector<std::vector<Time>> &times, std::vector<std::vector<Double>> &clock) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssClockRinex2InstrumentClock, SINGLEPROCESS, \"Convert GNSS clock RINEX files to single value instrument files for satellites or stations.\", Conversion, Gnss, Instrument)\nGROOPS_RENAMED_PROGRAM(Igs2InstrumentClock, GnssClockRinex2InstrumentClock, date2time(2020, 8, 19))\n\n/***********************************************/\n\nvoid GnssClockRinex2InstrumentClock::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 fileNameOutInstrument;\n    std::vector<FileName>    fileNameInClockRinex;\n    TimeSeriesPtr            timesIntervalPtr;\n    std::vector<std::string> identifier;\n    UInt                     minEpochsPerInterval;\n\n    renameDeprecatedConfig(config, \"inputfileIgsClock\", \"inputfileClockRinex\", date2time(2020, 8, 19));\n\n    readConfig(config, \"outputfileInstrument\", fileNameOutInstrument, Config::MUSTSET,  \"\",  \"identifier is appended to each file\");\n    readConfig(config, \"inputfileClockRinex\",  fileNameInClockRinex,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"identifier\",           identifier,            Config::MUSTSET,  \"\",  \"satellite or station identifier, e.g. G23 or alic\");\n    readConfig(config, \"intervals\",            timesIntervalPtr,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"minEpochsPerInterval\", minEpochsPerInterval,  Config::DEFAULT,  \"2\", \"minimum number of epochs in an interval\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    // Read files\n    // ----------\n    std::vector<std::vector<Time>>   times(identifier.size());\n    std::vector<std::vector<Double>> clocks(identifier.size());\n\n    for(UInt i=0; i<fileNameInClockRinex.size(); i++)\n    {\n      logStatus<<\"Read file <\"<<fileNameInClockRinex.at(i)<<\">\"<<Log::endl;\n      readFile(fileNameInClockRinex.at(i), identifier, times, clocks);\n    }\n\n    // Conversion\n    // ----------\n    const std::vector<Time> timesInterval = timesIntervalPtr->times();\n    const UInt arcCount = timesInterval.size()-1;\n    for(UInt idIdentifier = 0; idIdentifier < identifier.size(); idIdentifier++)\n    {\n      std::vector<MiscValueArc> arcs;\n      UInt idx=0;\n\n      for(UInt idArc=0; idArc<arcCount; idArc++)\n      {\n        // find starting epoch of arc\n        while((idx<times.at(idIdentifier).size()) && (times.at(idIdentifier).at(idx)<timesInterval.at(idArc)))\n          idx++;\n\n        // fill arc with epochs\n        MiscValueArc arc;\n        for(UInt idEpoch=idx; (idEpoch<times.at(idIdentifier).size()) && (times.at(idIdentifier).at(idEpoch)<=timesInterval.at(idArc+1)); idEpoch++)\n          if(clocks.at(idIdentifier).at(idEpoch) != 0)\n          {\n            MiscValueEpoch epoch;\n            epoch.time = times.at(idIdentifier).at(idEpoch);\n            Vector x(1);\n            x(0) = clocks.at(idIdentifier).at(idEpoch);\n            epoch.setData(x);\n            arc.push_back(epoch);\n          }\n\n        if(arc.size()>=minEpochsPerInterval)\n          arcs.push_back(arc);\n        else if(arc.size())\n          logWarning<<identifier.at(idIdentifier)<<\": \"<<timesInterval.at(idArc).dateTimeStr()<<\" not enough epochs in arc (\"<<arc.size()<<\" < \"<<minEpochsPerInterval<<\")\"<<Log::endl;\n        else\n          logWarning<<identifier.at(idIdentifier)<<\": \"<<timesInterval.at(idArc).dateTimeStr()<<\" empty arc\"<<Log::endl;\n      }\n\n      // write instrument file\n      if(arcs.size())\n      {\n        logStatus<<\"Write clocks to file <\"<<fileNameOutInstrument.appendBaseName(\".\"+identifier.at(idIdentifier))<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameOutInstrument.appendBaseName(\".\"+identifier.at(idIdentifier)), arcs);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssClockRinex2InstrumentClock::readFile(const FileName &fileName, std::vector<std::string> identifier, std::vector<std::vector<Time>> &times, std::vector<std::vector<Double>> &clock) const\n{\n  try\n  {\n    InFile file(fileName);\n\n    // read header\n    Double fileVersion = 2.;\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(line.find(\"RINEX VERSION / TYPE\") != std::string::npos)\n        fileVersion = String::toDouble(line.substr(0,20));\n\n      if(line.find(\"END OF HEADER\") != std::string::npos)\n        break;\n    }\n\n    for(auto &&id : identifier)\n      std::transform(id.begin(), id.end(), id.begin(), ::toupper);\n\n    // read data\n    // ---------\n    UInt v3Offset = (fileVersion >= 3.04 ? 5 : 0);\n    while(std::getline(file, line))\n    {\n      std::string lineID = line.substr(0,7+v3Offset);\n      lineID.erase(std::find_if(lineID.rbegin(), lineID.rend(), [](auto c){return !std::isspace(c);}).base(), lineID.end()); // right trim spaces\n      std::transform(lineID.begin(), lineID.end(), lineID.begin(), ::toupper);\n\n      auto iter = std::find_if(identifier.begin(), identifier.end(), [lineID](std::string id)\n      {\n        return (lineID==\"AS \"+id || lineID==\"AR \"+id); }\n      );\n      if(iter != identifier.end())\n      {\n        UInt   year  = String::toInt(line.substr(v3Offset+8, 4));\n        UInt   month = String::toInt(line.substr(v3Offset+13, 2));\n        UInt   day   = String::toInt(line.substr(v3Offset+16, 2));\n        UInt   hour  = String::toInt(line.substr(v3Offset+19, 2));\n        UInt   min   = String::toInt(line.substr(v3Offset+22, 2));\n        Double sec   = String::toDouble(line.substr(v3Offset+24, 10));\n        Double clk   = String::toDouble(line.substr(v3Offset+40, 19));\n        Time   time  = date2time(year,month,day,hour,min,sec);\n\n        UInt idx = static_cast<UInt>(std::distance(identifier.begin(), iter));\n        if(times.at(idx).size() && (time<times.at(idx).back()))\n          throw(Exception(\"epochs not in increasing order\"));\n\n        if((times.at(idx).size()==0) || (time>times.at(idx).back()))\n        {\n          times.at(idx).push_back(time);\n          clock.at(idx).push_back(clk);\n        }\n      }\n    } // for(;;)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssEop2IgsErp.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssEop2IgsErp.cpp\n*\n* @brief Write GNSS Earth orientation parameters to IGS ERP file format.\n**\n* @author Sebastian Strasser\n* @date 2019-05-24\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite GNSS Earth orientation parameters to \\href{https://files.igs.org/pub/data/format/erp.txt}{IGS ERP file format}.\n\nRequires polar motion, polar motion rate, dUT1 and LOD parameters in the solution\nvector \\configFile{inputfileSolution}{matrix} and their sigmas in \\configFile{inputfileSigmax}{matrix}.\nSolution usually comes out of \\program{GnssProcessing}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"files/fileStringTable.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write GNSS Earth orientation parameters to IGS ERP file format.\n* @ingroup programsConversionGroup */\nclass GnssEop2IgsErp\n{\npublic:\n  class Epoch\n  {\n  public:\n    FileName fileNameSolution, fileNameSigmax, fileNameParameterNames, fileNameStationList;\n    std::vector<FileName> fileNameTransmitterList;\n    Time time;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssEop2IgsErp, SINGLEPROCESS, \"Write GNSS Earth orientation parameters to IGS ERP file format.\", Conversion, Gnss)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssEop2IgsErp::Epoch &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileSolution\",          var.fileNameSolution,        Config::MUSTSET,  \"\", \"parameter vector\");\n  readConfig(config, \"inputfileSigmax\",            var.fileNameSigmax,          Config::OPTIONAL, \"\", \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n  readConfig(config, \"inputfileParameterNames\",    var.fileNameParameterNames,  Config::MUSTSET,  \"\", \"parameter names\");\n  readConfig(config, \"inputfileTransmitterList\",   var.fileNameTransmitterList, Config::OPTIONAL, \"\", \"transmitter PRNs used in solution (used for transmitter count)\");\n  readConfig(config, \"inputfileStationList\",       var.fileNameStationList,     Config::OPTIONAL, \"\", \"stations used in solution (used for station count)\");\n  readConfig(config, \"time\",                       var.time,                    Config::MUSTSET,  \"\", \"reference time for epoch\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\n\nvoid GnssEop2IgsErp::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<Epoch> epochs;\n    std::vector<std::string> comments;\n\n    readConfig(config, \"outputfileIgsErp\", fileNameOut, Config::MUSTSET,  \"\", \"IGS ERP file\");\n    readConfig(config, \"epoch\",            epochs,      Config::MUSTSET,  \"\", \"e.g. daily solution\");\n    readConfig(config, \"comment\",          comments,    Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<std::string> lines;\n    for(const auto &epoch : epochs)\n    {\n      Vector x;\n      logStatus<<\"reading solution from <\"<<epoch.fileNameSolution<<\">\"<<Log::endl;\n      readFileMatrix(epoch.fileNameSolution, x);\n\n      Vector sigmax(x.rows());\n      if(!epoch.fileNameSigmax.empty())\n      {\n        logStatus<<\"reading standard deviations from <\"<<epoch.fileNameSigmax<<\">\"<<Log::endl;\n        readFileMatrix(epoch.fileNameSigmax, sigmax);\n      }\n\n      logStatus<<\"reading parameter names from <\"<<epoch.fileNameParameterNames<<\">\"<<Log::endl;\n      std::vector<ParameterName> parameterNames;\n      readFileParameterName(epoch.fileNameParameterNames, parameterNames);\n\n      std::vector<std::string> transmitterList;\n      for(const auto &fileName : epoch.fileNameTransmitterList)\n      {\n        logStatus<<\"reading transmitter list from <\"<<fileName<<\">\"<<Log::endl;\n        readFileStringList(fileName, transmitterList);\n      }\n\n      logStatus<<\"reading station list from <\"<<epoch.fileNameStationList<<\">\"<<Log::endl;\n      std::vector<std::string> stationList;\n      readFileStringList(epoch.fileNameStationList, stationList);\n\n      Double xp = 0, yp = 0, xpRate = 0, ypRate = 0, ut1 = 0, lod = 0;\n      Double sigmaXp = 0, sigmaYp = 0, sigmaXpRate = 0, sigmaYpRate = 0, sigmaUt1 = 0, sigmaLod = 0;\n      auto extract = [&x, &sigmax](UInt index, Double factor, Double &value, Double &sigma)\n      {\n        value = factor*x(index);\n        sigma = factor*sigmax(index);\n      };\n      for(UInt i = 0; i < parameterNames.size(); i++)\n        if(parameterNames.at(i).object == \"earth\")\n        {\n          if(parameterNames.at(i).type == \"polarMotion.xp\")\n          {\n            if(!parameterNames.at(i).temporal.size())\n              extract(i, 1e3, xp, sigmaXp); // mas => E-6\"\n            else if(parameterNames.at(i).temporal.substr(0,6) == \"trend.\")\n              extract(i, 1e3, xpRate, sigmaXpRate); // mas/d => E-6\"\n          }\n          else if(parameterNames.at(i).type == \"polarMotion.yp\")\n          {\n            if(!parameterNames.at(i).temporal.size())\n              extract(i, 1e3, yp, sigmaYp); // mas => E-6\"\n            else if(parameterNames.at(i).temporal.substr(0,6) == \"trend.\")\n              extract(i, 1e3, ypRate, sigmaYpRate); // mas/d => E-6\"\n          }\n          else if(parameterNames.at(i).type == \"UT1\")\n          {\n            if(!parameterNames.at(i).temporal.size())\n              extract(i, 1e4, ut1, sigmaUt1); // ms => .1us\n            else if(parameterNames.at(i).temporal.substr(0,6) == \"trend.\")\n              extract(i, 1e4, lod, sigmaLod); // ms/d => .1us/d\n          }\n        }\n\n      std::stringstream ss;\n      ss << epoch.time.mjd()%\"%9.2f\"s << xp%\"%9i\"s << yp%\"%9i\"s << ut1%\"%9i\"s << lod%\"%8i\"s << sigmaXp%\"%7i\"s << sigmaYp%\"%7i\"s << sigmaUt1%\"%7i\"s << sigmaLod%\"%7i\"s\n         << stationList.size()%\"%5i\"s << \"    0\" << transmitterList.size()%\"%5i\"s << xpRate%\"%7i\"s << ypRate%\"%7i\"s << sigmaXpRate%\"%7i\"s << sigmaYpRate%\"%7i\"s;\n      lines.push_back(ss.str());\n    }\n\n    logStatus<<\"writing ERPs to <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile outfile(fileNameOut);\n    outfile << \"version 2\" << std::endl;\n    for(const auto &comment : comments)\n      outfile << comment << std::endl;\n    outfile << std::string(115, '-') << std::endl;\n    outfile << \"   MJD       Xpole    Ypole  UT1-UTC     LOD   Xsig   Ysig  UTsig LODsig   Nr   Nf   Nt    Xrt    Yrt Xrtsig Yrtsig\" << std::endl;\n    outfile << \"              e-6\\\"     e-6\\\"     e-7s  e-7s/d   e-6\\\"   e-6\\\"   e-7s e-7s/d                e-6\\\"/d e-6\\\"/d e-6\\\"/d e-6\\\"/d\" << std::endl;\n    outfile << std::string(115, '-') << std::endl;\n    for(const auto &line : lines)\n      outfile << line << std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssGriddedDataTimeSeries2Ionex.cpp",
    "content": "/***********************************************/\n/**\n* @file programTemplate.cpp\n*\n* @brief Converts TEC maps from GROOPS GriddedDataTimeSeries format to IGS IONEX file format.\n*\n* @author Sebastian Strasser\n* @date 2021-09-15\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts TEC maps from GROOPS \\file{gridded data time series}{griddedDataTimeSeries} format\nto IGS \\href{https://files.igs.org/pub/data/format/ionex1.pdf}{IONEX file format}.\n\nCurrently only supports 2D TEC maps.\n\nSee also \\program{GnssIonex2GriddedDataTimeSeries}, \\configClass{IonosphereMap}{gnssParametrizationType:ionosphereMap}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"parser/dataVariables.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts TEC maps from GROOPS GriddedDataTimeSeries format to IGS IONEX file format.\n* @ingroup programsGroup */\nclass GnssGriddedDataTimeSeries2Ionex\n{\n  static std::string resize(std::string str, UInt length) {str.resize(length, ' '); return str;}\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssGriddedDataTimeSeries2Ionex, SINGLEPROCESS, \"Converts TEC maps from GROOPS GriddedDataTimeSeries format to IGS IONEX file format.\", Conversion, Gnss, Grid, TimeSplines)\n\n/***********************************************/\n\nvoid GnssGriddedDataTimeSeries2Ionex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameIn, fileNameOut;\n    TimeSeriesPtr timeSeries;\n    std::string program, institution, mappingFunction, observablesUsed;\n    std::vector<std::string> comments, descriptions;\n    Double elevationCutoff;\n    Int exponent;\n    ExpressionVariablePtr expression;\n\n    readConfig(config, \"outputfileIonex\",                fileNameOut,     Config::MUSTSET,  \"\",       \"\");\n    readConfig(config, \"inputfileGriddedDataTimeSeries\", fileNameIn,      Config::MUSTSET,  \"\",       \"must contain regular grid\");\n    readConfig(config, \"value\",                          expression,      Config::MUSTSET,  \"data0\",  \"expression (e.g. data column)\");\n    readConfig(config, \"timeSeries\",                     timeSeries,      Config::OPTIONAL, \"\",       \"(empty = use input file time series)\");\n    readConfig(config, \"program\",                        program,         Config::MUSTSET,  \"GROOPS\", \"name of program (for first line)\");\n    readConfig(config, \"institution\",                    institution,     Config::MUSTSET,  \"TUG (TU Graz)\", \"name of agency (for first line)\");\n    readConfig(config, \"description\",                    descriptions,    Config::OPTIONAL, \"\",       \"description in header\");\n    readConfig(config, \"comment\",                        comments,        Config::OPTIONAL, R\"([\"TEC values in 0.1 TECU, 9999 if no value available\"])\", \"comment in header\");\n    readConfig(config, \"mappingFunction\",                mappingFunction, Config::OPTIONAL, \"MSLM\",   \"see IONEX documentation\");\n    readConfig(config, \"elevationCutoff\",                elevationCutoff, Config::DEFAULT,  \"0\",      \"see IONEX documentation (0 if unknown)\");\n    readConfig(config, \"observablesUsed\",                observablesUsed, Config::OPTIONAL, \"\",       \"see IONEX documentation\");\n    readConfig(config, \"exponent\",                       exponent,        Config::DEFAULT,  \"-1\",     \"factor 10^exponent is applied to all values\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read gridded data time series file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFileGriddedDataTimeSeries fileGrid(fileNameIn);\n    GriddedDataRectangular grid;\n    if(!grid.init(fileGrid.grid()))\n      throw(Exception(\"grid must be rectangular\"));\n\n    std::vector<Time> times = fileGrid.times();\n    if(timeSeries)\n      times = timeSeries->times();\n\n    logStatus<<\"write IONEX file <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile file(fileNameOut);\n\n    file<<\"     1.0            IONOSPHERE MAPS     GNSS                IONEX VERSION / TYPE\"<<std::endl;\n    file<<resize(program, 20)<<resize(institution, 20)<<System::now()%\"%D %H:%M:%S \"s<<\"PGM / RUN BY / DATE\"<<std::endl;\n    for(auto &description : descriptions)\n      file<<resize(description, 60)<<\"DESCRIPTION\"<<std::endl;\n    file<<times.front()%\"  %y    %m    %d    %H    %M    %S\"s<<std::string(24, ' ')<<\"EPOCH OF FIRST MAP\"<<std::endl;\n    file<<times.back() %\"  %y    %m    %d    %H    %M    %S\"s<<std::string(24, ' ')<<\"EPOCH OF LAST MAP\"<<std::endl;\n    file<<medianSampling(times).seconds()%\"% 6i\"s<<std::string(54, ' ')<<\"INTERVAL\"<<std::endl;\n    file<<times.size()%\"% 6i\"s<<std::string(54, ' ')<<\"# OF MAPS IN FILE\"<<std::endl;\n    if(!mappingFunction.empty()) file<<\"  \"<<resize(mappingFunction, 4)<<std::string(54, ' ')<<\"MAPPING FUNCTION\"<<std::endl;\n    file<<elevationCutoff%\"%8.1f\"s<<std::string(52, ' ')<<\"ELEVATION CUTOFF\"<<std::endl;\n    if(!observablesUsed.empty()) file<<resize(observablesUsed, 60)<<\"OBSERVABLES USED\"<<std::endl;\n    file<<(fileGrid.grid().ellipsoid.a()/1000)%\"%8.1f\"s<<std::string(52, ' ')<<\"BASE RADIUS\"<<std::endl;\n    file<<\"     2\"<<std::string(54, ' ')<<\"MAP DIMENSION\"<<std::endl;\n    // Header: HGT1 / HGT 2 / DHGT, LAT1 / LAT2 / DLAT, LON1 / LON2 / DLON\n    const Double height = mean(Vector(grid.heights));\n    UInt columns = (grid.longitudes.front()+2*PI == grid.longitudes.back() ? grid.longitudes.size()-1 : grid.longitudes.size());\n    file<<\"  \"<<(height/1000)%\"%6.1f%6.1f\"s<<0%\"%6.1f\"s<<std::string(40, ' ')<<\"HGT1 / HGT2 / DHGT\"<<std::endl;\n    file<<\"  \"<<(grid.latitudes.front()*RAD2DEG)%\"%6.1f\"s<<(grid.latitudes.back()*RAD2DEG)%\"%6.1f\"s\n        <<((grid.latitudes.back()-grid.latitudes.front())/grid.latitudes.size()*RAD2DEG)%\"%6.1f\"s<<std::string(40, ' ')<<\"LAT1 / LAT2 / DLAT\"<<std::endl;\n    file<<\"  \"<<(grid.longitudes.front()*RAD2DEG)%\"%6.1f\"s<<(grid.longitudes.back()*RAD2DEG)%\"%6.1f\"s\n        <<((grid.longitudes.back()-grid.longitudes.front())/columns*RAD2DEG)%\"%6.1f\"s<<std::string(40, ' ')<<\"LON1 / LON2 / DLON\"<<std::endl;\n    file<<exponent%\"% 6i\"s<<std::string(54, ' ')<<\"EXPONENT\"<<std::endl;\n    for(auto &comment : comments)\n      file<<resize(comment ,60)<<\"COMMENT\"<<std::endl;\n    file<<std::string(60, ' ')<<\"END OF HEADER\"<<std::endl;\n\n    // Data records\n    const Double factor = std::pow(10, exponent);\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      file<<(idEpoch+1)%\"% 6i\"s<<std::string(54, ' ')<<\"START OF TEC MAP\"<<std::endl;\n      file<<times.at(idEpoch)%\"  %y    %m    %d    %H    %M    %S\"s<<std::string(24, ' ')<<\"EPOCH OF CURRENT MAP\"<<std::endl;\n      for(UInt i=0; i<grid.latitudes.size(); i++)\n      {\n        file<<\"  \"<<(grid.latitudes.at(i)*RAD2DEG)%\"% 6.1f\"s<< (grid.longitudes.front()*RAD2DEG)%\"%6.1f\"s<<(grid.longitudes.back()*RAD2DEG)%\"%6.1f\"s\n            <<((grid.longitudes.back()-grid.longitudes.front())/columns*RAD2DEG)%\"%6.1f\"s<<(height/1000)%\"%6.1f\"s<<std::string(28, ' ')<<\"LAT/LON1/LON2/DLON/H\"<<std::endl;\n\n        Matrix data = fileGrid.data(times.at(idEpoch));\n        VariableList varList;\n        addDataVariables(data, varList);\n\n        for(UInt k=0; k<grid.longitudes.size(); k++)\n        {\n          evaluateDataVariables(data, i*grid.longitudes.size()+k, varList);\n          Double value = expression->evaluate(varList);\n          if(k > 0 && k%16 == 0) // start new line after 16 values\n            file<<std::endl;\n          file<<(std::isnan(value) ? \" 9999\" : (value/factor)%\"% 5i\"s);\n        }\n        file<<std::endl;\n      }\n      file<<(idEpoch+1)%\"% 6i\"s<<std::string(54, ' ')<<\"END OF TEC MAP\"<<std::endl;\n    }\n    file<<std::string(60, ' ')<<\"END OF FILE\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssIonex2GriddedDataTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssIonex2GriddedDataTimeSeries.cpp\n*\n* @brief Converts TEC maps from IGS IONEX file format to GROOPS GriddedDataTimeSeries format.\n**\n* @author Sebastian Strasser\n* @date 2021-09-13\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts TEC maps from IGS \\href{https://files.igs.org/pub/data/format/ionex1.pdf}{IONEX file format}\nto GROOPS \\file{gridded data time series}{griddedDataTimeSeries} format.\n\nCurrently only supports 2D TEC maps.\n\nSee also \\program{GnssGriddedDataTimeSeries2Ionex}, \\configClass{IonosphereMap}{gnssParametrizationType:ionosphereMap}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts TEC maps from IGS IONEX file format to GROOPS GriddedDataTimeSeries format.\n* @ingroup programsGroup */\nclass GnssIonex2GriddedDataTimeSeries\n{\n  Bool getLine(InFile &file, std::string &line, std::string &label) const;\n  Bool testLabel(const std::string &labelInLine, const std::string &label, Bool optional=TRUE) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssIonex2GriddedDataTimeSeries, SINGLEPROCESS, \"Converts TEC maps from IGS IONEX file format to GROOPS GriddedDataTimeSeries format.\", Conversion, Gnss, Grid, TimeSplines)\n\n/***********************************************/\n\nvoid GnssIonex2GriddedDataTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<FileName> fileNamesIn;\n\n    readConfig(config, \"outputfileGriddedDataTimeSeries\", fileNameOut, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileIonex\",                  fileNamesIn, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    GriddedData grid;\n    std::vector<Matrix> data;\n    std::vector<Time> times;\n\n    for(const auto &fileName : fileNamesIn)\n    {\n      logStatus<<\"read IONEX file <\"<<fileName<<\">\"<<Log::endl;\n      InFile file(fileName);\n      file.exceptions(std::ios::badbit|std::ios::failbit);\n\n      Double factor = 0.1;\n      std::vector<Angle> latitudes, longitudes;\n      Double height = 0;\n      Double radius = DEFAULT_GRS80_a;\n\n      // read header\n      std::string line, label;\n      getLine(file, line, label);\n      testLabel(label, \"IONEX VERSION / TYPE\", FALSE);\n      while(getLine(file, line, label))\n      {\n        if(testLabel(label, \"END OF HEADER\"))\n          break;\n        else if(testLabel(label, \"MAP DIMENSION\"))\n        {\n          if(String::toInt(line.substr(0,6)) > 2)\n            throw(Exception(\"only 2-dimensional maps are supported yet\"));\n        }\n        else if(testLabel(label, \"LAT1 / LAT2 / DLAT\"))\n        {\n          Double lat1 = String::toDouble(line.substr(2,6));\n          Double lat2 = String::toDouble(line.substr(8,6));\n          Double dlat = String::toDouble(line.substr(14,6));\n          for(Double lat=lat1; (dlat > 0 ? lat<=lat2 : lat>=lat2); lat+=dlat)\n            latitudes.push_back(Angle(lat*DEG2RAD));\n        }\n        else if(testLabel(label, \"LON1 / LON2 / DLON\"))\n        {\n          Double lon1 = String::toDouble(line.substr(2,6));\n          Double lon2 = String::toDouble(line.substr(8,6));\n          Double dlon = String::toDouble(line.substr(14,6));\n          for(Double lon=lon1; (dlon > 0 ? lon<=lon2 : lon>=lon2); lon+=dlon)\n            longitudes.push_back(Angle(lon*DEG2RAD));\n        }\n        else if(testLabel(label, \"HGT1 / HGT2 / DHGT\"))\n        {\n          height = 1e3*String::toDouble(line.substr(2,6));\n        }\n        else if(testLabel(label, \"BASE RADIUS\"))\n        {\n          radius = 1e3*String::toDouble(line.substr(2,6));\n        }\n        else if(testLabel(label, \"EXPONENT\"))\n        {\n          factor = std::pow(10., String::toInt(line.substr(0,6)));\n        }\n      }\n\n      if(!grid.points.size())\n      {\n        GriddedDataRectangular gridRectangular;\n        gridRectangular.longitudes = longitudes;\n        gridRectangular.latitudes  = latitudes;\n        gridRectangular.heights.resize(latitudes.size(), height);\n        gridRectangular.ellipsoid  = Ellipsoid(radius,  0.); //  sphere\n        grid.init(gridRectangular);\n      }\n\n      // read data\n      while(getLine(file, line, label))\n        if(testLabel(label, \"START OF TEC MAP\"))\n        {\n          getLine(file, line, label);\n          testLabel(label, \"EPOCH OF CURRENT MAP\", FALSE);\n          Time time = date2time(String::toInt(line.substr(0,6)), String::toInt(line.substr(6,6)), String::toInt(line.substr(12,6)),\n                                String::toInt(line.substr(18,6)), String::toInt(line.substr(24,6)), String::toInt(line.substr(30,6)));\n\n          if(times.size() && time < times.back())\n          {\n            logWarning<<\"skipping epoch \"<<time.dateTimeStr()<<\" (unsorted)\"<<Log::endl;\n            continue;\n          }\n\n          // replace possible duplicate epoch by newer one (e.g. 00:00 from file 2 instead of 24:00 from file 1)\n          if(times.size() && time == times.back())\n            data.pop_back();\n          else\n            times.push_back(time);\n\n          Vector epochData(latitudes.size()*longitudes.size());\n          while(getLine(file, line, label))\n          {\n            if(testLabel(label, \"END OF TEC MAP\"))\n              break;\n            testLabel(label, \"LAT/LON1/LON2/DLON/H\", FALSE);\n            const Angle lat (String::toDouble(line.substr( 2,6))*DEG2RAD);\n            const Angle lon1(String::toDouble(line.substr( 8,6))*DEG2RAD);\n            const Angle lon2(String::toDouble(line.substr(14,6))*DEG2RAD);\n            const Angle dlon(String::toDouble(line.substr(20,6))*DEG2RAD);\n            const UInt count = static_cast<UInt>(std::round((lon2-lon1)/dlon))+1;\n            const UInt idxLat = std::distance(latitudes.begin(),  std::find(latitudes.begin(),  latitudes.end(),  lat));\n            const UInt idxLon = std::distance(longitudes.begin(), std::find(longitudes.begin(), longitudes.end(), lon1));\n            for(UInt i=0; i<(count+15)/16; i++)\n            {\n              getLine(file, line, label);\n              for(UInt k=0; k<std::min(count-i*16, UInt(16)); k++)\n                epochData.at(idxLat*longitudes.size() + (idxLon+i*16+k)%longitudes.size()) = factor * String::toDouble(line.substr(k*5,5));\n            }\n          }\n          data.push_back(epochData);\n        }\n    }\n\n    logStatus<<\"write gridded data time series to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedDataTimeSeries(fileNameOut, 1, times, grid, data);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssIonex2GriddedDataTimeSeries::getLine(InFile &file, std::string &line, std::string &label) const\n{\n  try\n  {\n    std::getline(file, line);\n    if(line.size() && line.back() == '\\r')\n      line.pop_back();\n    if(line.size()<80)\n      line.resize(80,' ');\n    label = line.substr(60,20);\n    return TRUE;\n  }\n  catch(...)\n  {\n    line.clear();\n    line.resize(80,' ');\n    label = line.substr(60,20);\n    return FALSE;\n  }\n}\n\n/***********************************************/\n\nBool GnssIonex2GriddedDataTimeSeries::testLabel(const std::string &labelInLine, const std::string &label, Bool optional) const\n{\n  if(labelInLine.find(label)!=std::string::npos)\n    return TRUE;\n  if(optional)\n    return FALSE;\n  throw(Exception(std::string(\"In line '\")+labelInLine+\"' label '\"+label+\"' expected\\n\"));\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssNormals2Sinex.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssNormals2Sinex.cpp\n*\n* @brief Write GNSS data/metadata and normal equations to SINEX format.\n*\n* @author Sebastian Strasser\n* @date 2019-05-21\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite GNSS data/metadata and \\file{normal equations}{normalEquation} to\n\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}.\n\nNormal equations usually come from \\program{GnssProcessing}\n(e.g. from \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork}).\nMetadata input files include \\configFile{stationInfo/transmitterInfo}{platform}, \\configFile{antennaDefinition}{gnssAntennaDefinition},\nand \\configFile{stationList/transmitterList}{stringList}, see \\program{GnssAntex2AntennaDefinition}.\n\nSee also \\program{Sinex2Normals} and \\program{NormalsSphericalHarmonics2Sinex}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"files/fileStringTable.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write GNSS data/metadata and normal equations to SINEX format.\n* @ingroup programsConversionGroup */\nclass GnssNormals2Sinex\n{\npublic:\n  class TransmitterConstellation\n  {\n  public:\n    FileName fileNameTransmitterList, fileNameTransmitterInfo, fileNameAntennaDef;\n    std::string variablePrn;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssNormals2Sinex, SINGLEPROCESS, \"Write GNSS data/metadata and normal equations to SINEX format.\", Conversion, Gnss, NormalEquation)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssNormals2Sinex::TransmitterConstellation &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileTransmitterList\",   var.fileNameTransmitterList, Config::MUSTSET,  \"\",    \"transmitter PRNs used in solution\");\n  readConfig(config, \"inputfileTransmitterInfo\",   var.fileNameTransmitterInfo, Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\", \"transmitter info file template\");\n  readConfig(config, \"inputfileAntennaDefinition\", var.fileNameAntennaDef,      Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\",   \"transmitter phase centers and variations (ANTEX)\");\n  readConfig(config, \"variablePrn\",                var.variablePrn,             Config::DEFAULT,  \"prn\", \"loop variable for PRNs from transmitter list\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssNormals2Sinex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameSinexNormals, fileNameSinexCoords, fileNameNormals, fileNameSolution, fileNameSigmax, fileNameApriori, fileNameAprioriSigma, fileNameAprMat;\n    FileName    fileNameStationList, fileNameStationInfo, fileNameAntennaDef;\n    Time        timeRef, timeStartObs, timeEndObs;\n    std::string variableStationName, antennaModel;\n    Double      sampling = 0;\n    std::vector<TransmitterConstellation> constellations;\n    Sinex       sinex;\n\n    readConfig(config, \"outputfileSinexNormals\",     fileNameSinexNormals, Config::OPTIONAL, \"\", \"full SINEX file including normal equations\");\n    readConfig(config, \"outputfileSinexCoordinates\", fileNameSinexCoords,  Config::OPTIONAL, \"\", \"SINEX file without normal equations (station coordinates file)\");\n    readConfig(config, \"inputfileNormals\",           fileNameNormals,      Config::MUSTSET,  \"\", \"normal equation matrix\");\n    readConfig(config, \"inputfileSolution\",          fileNameSolution,     Config::OPTIONAL, \"\", \"parameter vector\");\n    readConfig(config, \"inputfileSigmax\",            fileNameSigmax,       Config::OPTIONAL, \"\", \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n    readConfig(config, \"inputfileApriori\",           fileNameApriori,      Config::MUSTSET,  \"\", \"apriori parameter vector\");\n    readConfig(config, \"inputfileAprioriSigma\",      fileNameAprioriSigma, Config::OPTIONAL, \"\", \"constraint sigmas for apriori parameter vector\");\n    readConfig(config, \"inputfileAprioriMatrix\",     fileNameAprMat,       Config::OPTIONAL, \"\", \"normal equation matrix of applied constraints\");\n    readConfig(config, \"transmitterConstellation\",   constellations,       Config::MUSTSET,  \"\", \"transmitter constellation metadata\");\n    if(readConfigSequence(config, \"stations\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"inputfileStationList\",       fileNameStationList, Config::MUSTSET,  \"\", \"stations contained in normal equations\");\n      readConfig(config, \"inputfileStationInfo\",       fileNameStationInfo, Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/stationInfo/igs/stationInfo.{station}.xml\", \"station info file template\");\n      readConfig(config, \"inputfileAntennaDefinition\", fileNameAntennaDef,  Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\", \"station phase centers and variations (ANTEX)\");\n      readConfig(config, \"variableStationName\",        variableStationName, Config::DEFAULT,  \"station\", \"loop variable for station names from station list\");\n      readConfig(config, \"observationTimeStart\",       timeStartObs,        Config::MUSTSET,  \"\", \"start time for which solution has observations\");\n      readConfig(config, \"observationTimeEnd\",         timeEndObs,          Config::MUSTSET,  \"\", \"end time for which solution has observations\");\n      endSequence(config);\n    }\n    readConfig(config, \"time\",                       timeRef,             Config::MUSTSET,  \"\", \"reference time for parameters\");\n    readConfig(config, \"sampling\",                   sampling,            Config::OPTIONAL, \"\", \"[seconds] observation sampling\");\n    readConfig(config, \"antennaCalibrationModel\",    antennaModel,        Config::MUSTSET,  \"\", \"e.g. IGS14_WWWW (WWWW = ANTEX release GPS week)\");\n    readConfig(config, \"sinexHeader\",                sinex,               Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================================\n\n    // read data from files\n    // --------------------\n    Vector x;\n    if(!fileNameSolution.empty())\n    {\n      logStatus<<\"reading solution from <\"<<fileNameSolution<<\">\"<<Log::endl;\n      readFileMatrix(fileNameSolution, x);\n    }\n\n    Vector sigmax;\n    if(!fileNameSigmax.empty())\n    {\n      logStatus<<\"reading standard deviations from <\"<<fileNameSigmax<<\">\"<<Log::endl;\n      readFileMatrix(fileNameSigmax, sigmax);\n    }\n\n    Vector x0;\n    if(!fileNameApriori.empty())\n    {\n      logStatus<<\"reading apriori solution from <\"<<fileNameApriori<<\">\"<<Log::endl;\n      readFileMatrix(fileNameApriori, x0);\n    }\n\n    Vector sigmax0;\n    if(!fileNameAprioriSigma.empty())\n    {\n      logStatus<<\"reading constraint sigmas from <\"<<fileNameAprioriSigma<<\">\"<<Log::endl;\n      readFileMatrix(fileNameAprioriSigma, sigmax0);\n    }\n\n    Matrix N, n;\n    NormalEquationInfo info;\n    logStatus<<\"reading normal equation matrix from <\"<<fileNameNormals<<\">\"<<Log::endl;\n    readFileNormalEquation(fileNameNormals, info, N, n);\n    fillSymmetric(N);\n    const UInt countParameter = N.rows();\n\n    Matrix dN;\n    std::vector<Bool> parameterIsConstrained(countParameter, FALSE);\n    if(!fileNameAprMat.empty())\n    {\n      logStatus<<\"reading normal equation matrix of applied constraints <\"<<fileNameAprMat<<\">\"<<Log::endl;\n      Vector n;\n      NormalEquationInfo info;\n      readFileNormalEquation(fileNameAprMat, info, dN, n);\n      fillSymmetric(dN);\n      if(dN.rows() != parameterIsConstrained.size())\n        throw(Exception(\"Parameter count in constraint matrix and normal equation matrix differs (\" + dN.rows()%\"%i\"s + \" vs. \"+ N.rows()%\"%i\"s +\" ).\"));\n      for(UInt i=0; i<dN.rows(); i++)\n        parameterIsConstrained.at(i) = (dN(i, i) != 0.0);\n    }\n\n    logStatus<<\"reading station list from <\"<<fileNameStationList<<\">\"<<Log::endl;\n    std::vector<std::string> stationList;\n    readFileStringList(fileNameStationList, stationList);\n\n    logStatus<<\"reading station antenna definitions from <\"<<fileNameAntennaDef<<\">\"<<Log::endl;\n    std::vector<GnssAntennaDefinitionPtr> antennaDefinitionList;\n    readFileGnssAntennaDefinition(fileNameAntennaDef, antennaDefinitionList);\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(variableStationName, \"****\");\n    logStatus<<\"reading station infos from <\"<<fileNameStationInfo(fileNameVariableList)<<\">\"<<Log::endl;\n    std::vector<Platform> stationInfos;\n    for(const auto &station : stationList)\n    {\n      fileNameVariableList.setVariable(variableStationName, station);\n      Platform stationInfo;\n      readFilePlatform(fileNameStationInfo(fileNameVariableList), stationInfo);\n      stationInfo.fillGnssAntennaDefinition(antennaDefinitionList);\n      stationInfos.push_back(stationInfo);\n    }\n\n    std::vector<Platform> transmitterInfos;\n    for(const auto &constellation : constellations)\n    {\n      logStatus<<\"reading transmitter list from <\"<<constellation.fileNameTransmitterList<<\">\"<<Log::endl;\n      std::vector<std::string> transmitterList;\n      readFileStringList(constellation.fileNameTransmitterList, transmitterList);\n\n      logStatus<<\"reading transmitter antenna definitions from <\"<<constellation.fileNameAntennaDef<<\">\"<<Log::endl;\n      std::vector<GnssAntennaDefinitionPtr> antennaDefinitionList;\n      readFileGnssAntennaDefinition(constellation.fileNameAntennaDef, antennaDefinitionList);\n\n      fileNameVariableList.setVariable(constellation.variablePrn, \"***\");\n      logStatus<<\"reading transmitter infos from <\"<<constellation.fileNameTransmitterInfo(fileNameVariableList)<<\">\"<<Log::endl;\n      for(const auto &prn : transmitterList)\n      {\n        fileNameVariableList.setVariable(constellation.variablePrn, prn);\n        Platform transmitterInfo;\n        readFilePlatform(constellation.fileNameTransmitterInfo(fileNameVariableList), transmitterInfo);\n        transmitterInfo.fillGnssAntennaDefinition(antennaDefinitionList);\n        transmitterInfos.push_back(transmitterInfo);\n      }\n    }\n\n    // ==================================================\n\n    // add data to SINEX\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ID\");\n      *block<<\"*SITE PT __DOMES__ T _STATION DESCRIPTION__ _LONGITUDE_ _LATITUDE__ HEIGHT_\"<<std::endl;\n\n      auto rad2DegMinSec = [] (Double rad, Double &deg, Double &min, Double& sec)\n      {\n        deg = std::floor(rad*RAD2DEG);\n        min = std::floor((rad*RAD2DEG-deg)*60);\n        sec = ((rad*RAD2DEG-deg)*60-min)*60;\n      };\n\n      Ellipsoid ellipsoid;\n      for(const auto &stationInfo : stationInfos)\n      {\n        Angle lon, lat;\n        Double height, lonDeg, lonMin, lonSec, latDeg, latMin, latSec;\n        ellipsoid(stationInfo.approxPosition, lon, lat, height);\n        rad2DegMinSec(lon < 0 ? lon+2*PI : lon, lonDeg, lonMin, lonSec);\n        rad2DegMinSec(lat, latDeg, latMin, latSec);\n\n        std::stringstream ss;\n        *block<<\" \"<<String::upperCase(Sinex::resize(stationInfo.markerName, 4))<<\"  A \"<<Sinex::resize(stationInfo.markerNumber, 9)<<\" P \"<<Sinex::resize(stationInfo.comment, 22)<<\" \"\n              <<lonDeg%\"%3i \"s<<lonMin%\"%2i \"s<<lonSec%\"%4.1f \"s<<latDeg%\"%3i \"s<<latMin%\"%2i \"s<<latSec%\"%4.1f \"s<<height%\"%7.1f\"s<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ECCENTRICITY\");\n      *block<<\"*SITE PT SOLN T _DATA START_ __DATA_END__ AXE _ECC_U__ _ECC_N__ _ECC_E__\"<<std::endl;\n      for(const auto &stationInfo : stationInfos)\n      {\n        auto ant = stationInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n        if(!ant)\n        {\n          logWarning<<stationInfo.markerName<<\": no antenna found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<String::upperCase(Sinex::resize(stationInfo.markerName, 4))<<\"  A    1 P \"<<Sinex::time2str(ant->timeStart)<<\" \"\n              <<Sinex::time2str(ant->timeEnd)<<\" UNE \"<<ant->position.z()%\"%8.4f \"s<<ant->position.x()%\"%8.4f \"s<<ant->position.y()%\"%8.4f \"s<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/RECEIVER\");\n      *block<<\"*SITE PT SOLN T _DATA START_ __DATA_END__ ___RECEIVER_TYPE____ _S/N_ _FIRMWARE__\"<<std::endl;\n      for(const auto &stationInfo : stationInfos)\n      {\n        auto recv = stationInfo.findEquipment<PlatformGnssReceiver>(timeRef);\n        if(!recv)\n        {\n          logWarning<<stationInfo.markerName<<\": no receiver found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<String::upperCase(Sinex::resize(stationInfo.markerName, 4))<<\"  A    1 P \"<<Sinex::time2str(recv->timeStart)<<\" \"<<Sinex::time2str(recv->timeEnd)<<\" \"\n              <<Sinex::resize(recv->name, 20)<<\" \"<<(recv->serial.empty() ? \"-----\" : Sinex::resize(recv->serial, 5))\n              <<\" \"<<(recv->version.empty() ? std::string(11, '-') : Sinex::resize(recv->version, 11))<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ANTENNA\");\n      *block<<\"*SITE PT SOLN T _DATA START_ __DATA_END__ ____ANTENNA_TYPE____ _S/N_\"<<std::endl;\n      for(const auto &stationInfo : stationInfos)\n      {\n        auto ant = stationInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n        if(!ant)\n        {\n          logWarning<<stationInfo.markerName<<\": no antenna found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        Angle roll, pitch, yaw;\n        Rotary3d(ant->local2antennaFrame.matrix()).cardan(roll, pitch, yaw);\n        *block<<\" \"<<String::upperCase(Sinex::resize(stationInfo.markerName, 4))<<\"  A    1 P \"<<Sinex::time2str(ant->timeStart)<<\" \"<<Sinex::time2str(ant->timeEnd)<<\" \"\n              <<Sinex::resize(ant->name, 15)<<\" \"<<(ant->radome.empty() ? \"NONE\" : Sinex::resize(ant->radome, 4))<<\" \"<<(ant->serial.empty() ? \"-----\" : Sinex::resize(ant->serial, 5))\n              <<\" \"<<(yaw*RAD2DEG)%\"% 4i\"s<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/GPS_PHASE_CENTER\");\n      *block<<\"*____ANTENNA_TYPE____ _S/N_ _L1_U_ _L1_N_ _L1_E_ _L2_U_ _L2_N_ _L2_E_ _ANTMODEL_\"<<std::endl;\n      for(const auto &stationInfo : stationInfos)\n      {\n        auto ant = stationInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n        if(!ant)\n        {\n          logWarning<<stationInfo.markerName<<\": no antenna found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        auto p1 = std::find_if(ant->antennaDef->patterns.begin(), ant->antennaDef->patterns.end(), [](const GnssAntennaPattern &pattern) {return pattern.type == GnssType::L1_G;});\n        auto p2 = std::find_if(ant->antennaDef->patterns.begin(), ant->antennaDef->patterns.end(), [](const GnssAntennaPattern &pattern) {return pattern.type == GnssType::L2_G;});\n        if(p1 == ant->antennaDef->patterns.end() || p2 == ant->antennaDef->patterns.end())\n        {\n          logWarning<<stationInfo.markerName <<\": GPS phase center not found for antenna \"<<ant->name<<\" \"<<ant->radome<<\" \"<<ant->serial<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<Sinex::resize(ant->name, 15)<<\" \"<<(ant->radome.empty() ? \"NONE\" : Sinex::resize(ant->radome, 4))<<\" \"<<(ant->serial.empty() ? \"-----\" : Sinex::resize(ant->serial, 5))<<\" \"\n              <<Sinex::format(p1->offset.z())<<\" \"<<Sinex::format(p1->offset.x())<<\" \"<<Sinex::format(p1->offset.y())<<\" \"\n              <<Sinex::format(p2->offset.z())<<\" \"<<Sinex::format(p2->offset.x())<<\" \"<<Sinex::format(p2->offset.y())<<\" \"\n              <<Sinex::resize(antennaModel, 10)<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/GAL_PHASE_CENTER\");\n      *block<<\"*____ANTENNA_TYPE____ _S/N_ _L1_U_ _L1_N_ _L1_E_ _L5_U_ _L5_N_ _L5_E_ _ANTMODEL_\"<<std::endl;\n      *block<<\"*____ANTENNA_TYPE____ _S/N_ _L6_U_ _L6_N_ _L6_E_ _L7_U_ _L7_N_ _L7_E_ _ANTMODEL_\"<<std::endl;\n      *block<<\"*____ANTENNA_TYPE____ _S/N_ _L8_U_ _L8_N_ _L8_E_ ____________________ _ANTMODEL_\"<<std::endl;\n      for(const auto &stationInfo : stationInfos)\n      {\n        auto ant = stationInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n        if(!ant)\n        {\n          logWarning<<stationInfo.markerName<<\": no antenna found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        const auto &patterns = ant->antennaDef->patterns;\n        auto p1 = std::find_if(patterns.begin(), patterns.end(), [](const GnssAntennaPattern &pattern){return pattern.type == GnssType::L1_E;});\n        auto p5 = std::find_if(patterns.begin(), patterns.end(), [](const GnssAntennaPattern &pattern){return pattern.type == GnssType::L5_E;});\n        auto p6 = std::find_if(patterns.begin(), patterns.end(), [](const GnssAntennaPattern &pattern){return pattern.type == GnssType::L6_E;});\n        auto p7 = std::find_if(patterns.begin(), patterns.end(), [](const GnssAntennaPattern &pattern){return pattern.type == GnssType::L7_E;});\n        auto p8 = std::find_if(patterns.begin(), patterns.end(), [](const GnssAntennaPattern &pattern){return pattern.type == GnssType::L8_E;});\n        if(p1 == patterns.end() || p5 == patterns.end() || p6 == patterns.end() || p7 == patterns.end() || p8 == patterns.end())\n          continue;\n        *block<<\" \"<<Sinex::resize(ant->name, 15)<<\" \"<<(ant->radome.empty() ? \"NONE\" : Sinex::resize(ant->radome, 4))<<\" \"<<(ant->serial.empty() ? \"-----\" : Sinex::resize(ant->serial, 5))<<\" \"\n              <<Sinex::format(p1->offset.z())<<\" \"<<Sinex::format(p1->offset.x())<<\" \"<<Sinex::format(p1->offset.y())<<\" \"\n              <<Sinex::format(p5->offset.z())<<\" \"<<Sinex::format(p5->offset.x())<<\" \"<<Sinex::format(p5->offset.y())<<\" \"<<Sinex::resize(antennaModel, 10)<<std::endl;\n        *block<<\" \"<<Sinex::resize(ant->name, 15)<<\" \"<<(ant->radome.empty() ? \"NONE\" : Sinex::resize(ant->radome, 4))<<\" \"<<(ant->serial.empty() ? \"-----\" : Sinex::resize(ant->serial, 5))<<\" \"\n              <<Sinex::format(p6->offset.z())<<\" \"<<Sinex::format(p6->offset.x())<<\" \"<<Sinex::format(p6->offset.y())<<\" \"\n              <<Sinex::format(p7->offset.z())<<\" \"<<Sinex::format(p7->offset.x())<<\" \"<<Sinex::format(p7->offset.y())<<\" \"<<Sinex::resize(antennaModel, 10)<<std::endl;\n        *block<<\" \"<<Sinex::resize(ant->name, 15)<<\" \"<<(ant->radome.empty() ? \"NONE\" : Sinex::resize(ant->radome, 4))<<\" \"<<(ant->serial.empty() ? \"-----\" : Sinex::resize(ant->serial, 5))<<\" \"\n              <<Sinex::format(p8->offset.z())<<\" \"<<Sinex::format(p8->offset.x())<<\" \"<<Sinex::format(p8->offset.y())<<\" \"\n              <<std::string(20, ' ')<<\" \"<<Sinex::resize(antennaModel, 10)<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SATELLITE/ID\");\n      *block<<\"*SVN_ PR COSPAR_ID T _DATA_START_ __DATA_END__ ______ANTENNA_______\"<<std::endl;\n\n      std::map<std::string, Time> svn2TimeStart, svn2TimeEnd;\n      for(const auto &transmitterInfo : transmitterInfos)\n        for(const auto &instrument : transmitterInfo.equipments)\n        {\n          auto ant = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n          if(ant)\n          {\n            svn2TimeStart[ant->serial] = (svn2TimeStart[ant->serial] == Time() ? ant->timeStart : std::min(svn2TimeStart[ant->serial], ant->timeStart));\n            svn2TimeEnd[ant->serial]   = std::max(svn2TimeStart[ant->serial], ant->timeEnd);\n          }\n        }\n\n      for(const auto &transmitterInfo : transmitterInfos)\n      {\n        auto ant = transmitterInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n        if(!ant)\n        {\n          logWarning<<transmitterInfo.markerName<<\": no antenna found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<Sinex::resize(ant->serial, 4)<<\" \"<<transmitterInfo.markerNumber.substr(1,2)<<\" \"<<Sinex::resize(ant->radome, 9)<<\" P \"\n              <<Sinex::time2str(svn2TimeStart[ant->serial])<<\" \"<<Sinex::time2str(svn2TimeEnd[ant->serial])<<\" \"<<ant->name<<std::endl;\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SATELLITE/PHASE_CENTER\");\n      *block<<\"*SVN_ L SATA_Z SATA_X SATA_Y L SATA_Z SATA_X SATA_Y _ANTMODEL_ T M\"<<std::endl;\n\n      auto antennaOffsetStr = [&](const PlatformGnssAntenna &ant, const GnssAntennaPattern &pattern)\n      {\n        Vector3d offset = ant.position + ant.local2antennaFrame.inverseTransform(pattern.offset);\n        return pattern.type.str().substr(1,1)+\" \"+Sinex::format(offset.z())+\" \"+Sinex::format(offset.x())+\" \"+Sinex::format(offset.y());\n      };\n\n      for(const auto &transmitterInfo : transmitterInfos)\n      {\n        auto ant = transmitterInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n        if(!ant)\n        {\n          logWarning<<transmitterInfo.markerName<<\": no antenna found at \"<<timeRef.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        std::vector<const GnssAntennaPattern*> patterns;\n        for(const auto &pattern : ant->antennaDef->patterns)\n          if(pattern.type == GnssType::PHASE)\n            patterns.push_back(&pattern);\n        std::sort(patterns.begin(), patterns.end(), [](const auto &p1, const auto &p2){return p1->type < p2->type;});\n        for(UInt i=0; i<patterns.size(); i+=2)\n        {\n          *block<<\" \"<<ant->serial<<\" \"<<antennaOffsetStr(*ant, *patterns.at(i))<<\" \"<<(i+1 < patterns.size() ? antennaOffsetStr(*ant, *patterns.at(i+1)) : std::string(22, ' '))\n                <<\" \"<<Sinex::resize(antennaModel, 10)<<\" A \"<<(patterns.at(i)->pattern.rows() > 1 ? \"F\" : \"E\")<<std::endl;\n        }\n      }\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/EPOCHS\");\n      *block<<\"*SITE PT SOLN T _DATA_START_ __DATA_END__ _MEAN_EPOCH_\"<<std::endl;\n      for(const auto &stationInfo : stationInfos)\n        *block<<\" \"<<String::upperCase(Sinex::resize(stationInfo.markerName, 4))<<\"  A    1 P \"\n              <<Sinex::time2str(timeStartObs)<<\" \"<<Sinex::time2str(timeEndObs)<<\" \"<<Sinex::time2str(0.5*(timeStartObs+timeEndObs))<<std::endl;\n    }\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/STATISTICS\");\n      *block<<\"*____STATISTICAL_PARAMETER_____ _______VALUE(S)_______\"<<std::endl;\n      *block<<\" NUMBER OF OBSERVATIONS         \"<<info.observationCount%\"%22i\"s<<std::endl;\n      *block<<\" NUMBER OF UNKNOWNS             \"<<countParameter%\"%22i\"s<<std::endl;\n      *block<<\" NUMBER OF DEGREES OF FREEDOM   \"<<(info.observationCount-countParameter)%\"%22i\"s<<std::endl;\n      *block<<\" WEIGHTED SQUARE SUM OF O-C     \"<<info.lPl(0)%\"%22.15e\"s<<std::endl;\n      if(sampling > 0)\n        *block<<\" SAMPLING INTERVAL (SECONDS)    \"<<sampling%\"%22f\"s<<std::endl;\n    }\n\n    // ==================================================\n    auto writeVector = [&](SinexBlockPtr block, const Vector x, const Vector sigma=Vector())\n    {\n      for(UInt i=0; i<x.size(); i++)\n      {\n        const std::string &object   = info.parameterName.at(i).object;\n        const std::string &type     = info.parameterName.at(i).type;\n        const std::string &temporal = info.parameterName.at(i).temporal;\n\n        std::string parameterType;\n        std::string siteCode       = \"----\";\n        std::string pointCode      = \"--\";\n        std::string unit           = \"    \";\n        std::string constraintCode = parameterIsConstrained.at(i) ? \"1\" : \"2\";\n\n        // STAX, STAY, STAZ\n        const Bool isStation = std::find(stationList.begin(), stationList.end(), object) != stationList.end();\n        if(isStation && String::startsWith(type, \"position.\"))\n        {\n          parameterType = \"STA\"+String::upperCase(type.substr(9, 1))+\"  \";\n          unit          = \"m   \";\n          siteCode      = String::upperCase(object);\n          pointCode     = \" A\";\n        }\n        // XPO, YPO\n        else if(object == \"earth\" && String::startsWith(type, \"polarMotion.\") && temporal.empty())\n        {\n          parameterType = String::upperCase(type.substr(12, 1)) + \"PO   \";\n          unit          = \"mas \";\n        }\n        // XPOR, YPOR\n        else if(object == \"earth\" && String::startsWith(type, \"polarMotion.\") && String::startsWith(temporal, \"trend.\"))\n        {\n          parameterType = String::upperCase(type.substr(12, 1)) + \"POR  \";\n          unit          = \"ma/d\";\n        }\n        // UT1\n        else if(object == \"earth\" && type == \"UT1\" && temporal.empty())\n        {\n          parameterType  = \"UT    \";\n          unit           = \"ms  \";\n          constraintCode = parameterIsConstrained.at(i) ? \"0\" : \"2\";\n        }\n        // LOD\n        else if(object == \"earth\" && type == \"UT1\" && String::startsWith(temporal, \"trend.\"))\n        {\n          parameterType = \"LOD   \";\n          unit          = \"ms  \";\n        }\n        // SATA_X, SATA_Y, SATA_Z\n        else if(!isStation && type.size() == 22 && type.substr(0, 14) == \"antennaCenter.\")\n        {\n          const std::string frequency = type.substr(type.size()-6, 2);\n          if((frequency.at(0) != 'L') && (frequency.at(0) != '*'))\n            throw(Exception(\"unsupported antenna center parameter: \" + info.parameterName.at(i).str()));\n          if(type.at(14) == 'x')      parameterType  = \"SATA_Y\"; // swap X and Y names (definition different for GROOPS and IGS)\n          else if(type.at(14) == 'y') parameterType  = \"SATA_X\"; // swap X and Y names (definition different for GROOPS and IGS)\n          else if(type.at(14) == 'z') parameterType  = \"SATA_Z\";\n          else\n            throw(Exception(\"unsupported antenna center parameter: \"+info.parameterName.at(i).str()));\n          unit           = \"m   \";\n          siteCode       = object.substr(object.find('|')+1, 4); // SVN\n          pointCode      = (frequency.at(1) == '*') ? \"LC\"s : \"L\"s+frequency.at(1);\n          constraintCode = parameterIsConstrained.at(i) ? \"0\" : \"2\";\n        }\n        else\n          throw(Exception(\"unknown parameter type: \" + info.parameterName.at(i).str()));\n\n        *block<<(i+1)%\" %5i \"s<<parameterType<<\" \"<<siteCode<<\" \"<<pointCode<<\"    1 \"<<Sinex::time2str(timeRef)\n              <<\" \"<<unit<<\" \"<<constraintCode<<constraintCode<<x(i)%\" %21.14e\"s;\n        if(sigma.size())\n          *block<<sigma(i)%\" %11.4e\"s;\n        *block<<std::endl;\n      }\n    };\n    // ==================================================\n\n    // add apriori antennaOffset of SATA_X, SATA_Y, SATA_Z\n    // ---------------------------------------------------\n    Vector xAprioriAntennaOffset(x.size());\n    for(UInt i=0; i<info.parameterName.size(); i++)\n    {\n      const ParameterName &param = info.parameterName.at(i);\n      if((param.type.size() == 22) && (param.type.substr(0, 14) == \"antennaCenter.\"))\n      {\n        std::shared_ptr<PlatformGnssAntenna> antInfo;\n        for(const auto &transmitterInfo : transmitterInfos)\n        {\n          antInfo = transmitterInfo.findEquipment<PlatformGnssAntenna>(timeRef);\n          if(antInfo && (antInfo->str() == param.object))\n            break;\n        }\n        if(!antInfo)\n          throw(Exception(\"no antenna found for \"+param.str()));\n        const UInt idPattern = antInfo->antennaDef->findAntennaPattern(GnssType(param.type.substr(16, 6)), GnssAntennaDefinition::NoPatternFoundAction::USE_NEAREST_FREQUENCY);\n        if(idPattern == NULLINDEX)\n          throw(Exception(\"no antenna pattern found for \"+param.str()));\n        const Vector3d offset = antInfo->antennaDef->patterns.at(idPattern).offset + antInfo->local2antennaFrame.transform(antInfo->position);\n        if(param.type.at(14) == 'x') xAprioriAntennaOffset(i) += offset.x();\n        if(param.type.at(14) == 'y') xAprioriAntennaOffset(i) += offset.y();\n        if(param.type.at(14) == 'z') xAprioriAntennaOffset(i) += offset.z();\n      }\n    }\n\n    // -----------------\n    if(x.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/ESTIMATE\");\n      *block<<\"*INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___ESTIMATED_VALUE___ __STD_DEV__\"<<std::endl;\n      writeVector(block, x+xAprioriAntennaOffset, sigmax.size() ? sigmax : Vector(x.size()));\n    }\n    // -----------------\n    if(x0.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/APRIORI\");\n      *block<<\"*INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ____APRIORI_VALUE____ __STD_DEV__\"<<std::endl;\n      writeVector(block, x0+xAprioriAntennaOffset, Vector(x0.size()));\n    }\n    // -----------------\n    if(n.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/NORMAL_EQUATION_VECTOR\");\n      *block<<\"*INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___RIGHT_HAND_SIDE___\"<<std::endl;\n      writeVector(block, n);\n    }\n\n    // ==================================================\n    auto writeMatrix = [&](SinexBlockPtr block, const Matrix &N)\n    {\n      for(UInt i=0; i<N.rows(); i++)\n        for(UInt k=i; k<N.rows(); k++)\n          if(N(i,k))\n          {\n            *block<<(i+1)%\" %5i\"s<<(k+1)%\" %5i\"s<<N(i, k)%\" %21.14e\"s;\n            for(UInt l=1; (l<3) && (k+1<N.rows()) && N(i,k+1); l++, k++)\n              *block<<N(i, k+1)%\" %21.14e\"s;\n            *block<<std::endl;\n          }\n    };\n    // ==================================================\n\n    if(N.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/NORMAL_EQUATION_MATRIX U\");\n      *block<<\"*PARA1 PARA2 _______PARA2+0_______ _______PARA2+1_______ _______PARA2+2_______\"<<std::endl;\n      writeMatrix(block, N);\n    }\n    // -----------------\n    if(dN.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/MATRIX_APRIORI U INFO\");\n      *block<<\"*PARA1 PARA2 _______PARA2+0_______ _______PARA2+1_______ _______PARA2+2_______\"<<std::endl;\n      writeMatrix(block, dN);\n    }\n\n    // ==================================================\n\n    // write SINEX files\n    // -----------------\n    if(!fileNameSinexNormals.empty())\n    {\n      logStatus<<\"write full SINEX file <\"<<fileNameSinexNormals<<\">\"<<Log::endl;\n      sinex.header.replace(60, 5, countParameter%\"%05i\"s);\n      writeFileSinex(fileNameSinexNormals, sinex);\n    }\n    if(!fileNameSinexCoords.empty())\n    {\n      logStatus<<\"write coordinates SINEX file <\"<<fileNameSinexCoords<<\">\"<<Log::endl;\n      sinex.blocks.remove_if([](const SinexBlockPtr &b){return b->label == \"SOLUTION/NORMAL_EQUATION_VECTOR\";});\n      sinex.blocks.remove_if([](const SinexBlockPtr &b){return b->label == \"SOLUTION/NORMAL_EQUATION_MATRIX U\";});\n      sinex.blocks.remove_if([](const SinexBlockPtr &b){return b->label == \"SOLUTION/MATRIX_APRIORI U INFO\";});\n      sinex.header.replace(60, 5, countParameter%\"%05i\"s);\n      writeFileSinex(fileNameSinexCoords, sinex);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssOrbex2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssOrbex2StarCamera.cpp\n*\n* @brief Converts satellite attitude from ORBEX to StarCamera format.\n*\n* @author Sebastian Strasser\n* @date 2020-09-29\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts GNSS satellite attitude from \\href{http://acc.igs.org/misc/proposal_orbex_april2019.pdf}{ORBEX file format}\n(quaternions) to \\file{instrument file (STARCAMERA)}{instrument}.\nThe resulting star camera files contain the rotation from satellite body frame to TRF, or to CRF in case\n\\configClass{earthRotation}{earthRotationType} is provided.\n\nSee also \\program{GnssAttitude2Orbex}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts satellite attitude from ORBEX to StarCamera format.\n* @ingroup programsGroup */\nclass GnssOrbex2StarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssOrbex2StarCamera, SINGLEPROCESS, \"Converts satellite attitude from ORBEX to StarCamera format.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\nvoid GnssOrbex2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutStarCamera, fileNameInOrbex;\n    std::vector<std::string> identifiers;\n    EarthRotationPtr         earthRotation;\n\n    readConfig(config, \"outputfileStarCamera\", fileNameOutStarCamera, Config::MUSTSET,  \"\",  \"rotation from body frame to TRF/CRF, identifier is appended to each file\");\n    readConfig(config, \"inputfileOrbex\",       fileNameInOrbex,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"identifier\",           identifiers,           Config::OPTIONAL, \"\",  \"(empty = all) satellite identifier, e.g. G23 or E05\");\n    readConfig(config, \"earthRotation\",        earthRotation,         Config::OPTIONAL, \"file\",  \"rotation from TRF to CRF\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read ORBEX file <\"<<fileNameInOrbex<<\">\"<<Log::endl;\n    InFile file(fileNameInOrbex);\n    std::map<std::string, StarCameraArc> starCameraArcs;\n    std::string line;\n    Bool isDataBlock = FALSE;\n    Time time;\n    Rotary3d crf2trf;\n    while(std::getline(file, line))\n    {\n      if(String::startsWith(line, \"+EPHEMERIS/DATA\"))\n      {\n        isDataBlock = TRUE;\n        continue;\n      }\n      if(String::startsWith(line, \"-EPHEMERIS/DATA\"))\n        isDataBlock = FALSE;\n      if(!isDataBlock || String::startsWith(line, \"*\"))\n        continue;\n\n      if(String::startsWith(line, \"##\"))\n      {\n        time = date2time(String::toInt(line.substr(3,4)), String::toInt(line.substr(8,2)), String::toInt(line.substr(11,2)),\n                         String::toInt(line.substr(14,2)), String::toInt(line.substr(17,2)), String::toDouble(line.substr(20,15)));\n        if(earthRotation)\n          crf2trf = earthRotation->rotaryMatrix(time);\n      }\n\n      if(String::startsWith(line, \" ATT\"))\n      {\n        std::string id = line.substr(5,3);\n        if(identifiers.size() && std::find(identifiers.begin(), identifiers.end(), id) == identifiers.end())\n          continue;\n        Vector q(4);\n        std::stringstream ss(line.substr(23));\n        ss>>q(0)>>q(1)>>q(2)>>q(3);\n        Rotary3d trf2sat(q);\n\n        StarCameraEpoch epoch;\n        epoch.time = time;\n        epoch.rotary = inverse(trf2sat * crf2trf); // (trf/crf2sat --> sat2trf/crf)\n        starCameraArcs[id].push_back(epoch);\n      }\n    }\n\n    logStatus<<\"write star camera files <\"<<fileNameOutStarCamera<<\">\"<<Log::endl;\n    for(const auto &sat : starCameraArcs)\n      InstrumentFile::write(fileNameOutStarCamera.appendBaseName(\".\"+sat.first), sat.second);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssReceiver2RinexObservation.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssReceiver2RinexObservation.cpp\n*\n* @brief Converts GnssReceiver Instrument file to RINEX.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-03-05\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts a \\configFile{inputfileGnssReceiver}{instrument} into a\n\\href{https://files.igs.org/pub/data/format/rinex_4.00.pdf}{RINEX} observation file.\nThe \\configFile{inputfileStationInfo}{platform} contains the antenna\nand receiver information for the RINEX header.\nThe \\configClass{useType}{gnssType} and \\configClass{ignoreType}{gnssType} can be used to filter\nthe observation types that will be exported.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/system.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts GnssReceiver Instrument file to RINEX.\n* @ingroup programsConversionGroup */\nclass GnssReceiver2RinexObservation\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssReceiver2RinexObservation, SINGLEPROCESS, \"Converts GnssReceiver Instrument file to RINEX.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\nvoid GnssReceiver2RinexObservation::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameObs, fileNamePlatform;\n    std::string observer, angency;\n    std::vector<std::string> comments;\n    std::vector<GnssType> useType, ignoreType;\n\n    readConfig(config, \"outputfileRinexObservation\", fileNameOut,      Config::MUSTSET,  \"\",    \"RINEX observation file\");\n    readConfig(config, \"inputfileGnssReceiver\",      fileNameObs,      Config::MUSTSET,  \"\",    \"GNSS instrument file\");\n    readConfig(config, \"inputfileStationInfo\",       fileNamePlatform, Config::MUSTSET,  \"\",    \"antenna and receiver info\");\n    readConfig(config, \"comment\",                    comments,         Config::OPTIONAL, \"\",    \"write comments at begin of header\");\n    readConfig(config, \"observer\",                   observer,         Config::OPTIONAL, \"TUG\", \"header information\");\n    readConfig(config, \"angency\",                    angency,          Config::OPTIONAL, \"TUG\", \"header information\");\n    readConfig(config, \"useType\",                    useType,          Config::OPTIONAL, \"\",    \"only use observations that match any of these patterns\");\n    readConfig(config, \"ignoreType\",                 ignoreType,       Config::OPTIONAL, \"\",    \"ignore observations that match any of these patterns\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument file <\"<<fileNameObs<<\">\"<<Log::endl;\n    GnssReceiverArc arc = InstrumentFile::read(fileNameObs);\n    if(!arc.size())\n    {\n      logWarning<<\"Empty observation file\"<<Log::endl;\n      return;\n    }\n\n    // find all types\n    std::map<GnssType, std::set<GnssType>> types; // types per system\n    std::set<GnssType> glonass;                   // GLONASS frequencyNumbers\n    for(auto &epoch : arc)\n      for(GnssType satType : epoch.satellite)\n        for(UInt idType = GnssType::index(epoch.obsType, satType); (idType < epoch.obsType.size()) && (epoch.obsType.at(idType) == satType); idType++)\n          if((!useType.size() || (epoch.obsType.at(idType)+satType).isInList(useType)) && !(epoch.obsType.at(idType)+satType).isInList(ignoreType))\n          {\n            types[satType & GnssType::SYSTEM].insert(epoch.obsType.at(idType));\n            if(satType == GnssType::GLONASS)\n              glonass.insert(satType);\n          }\n\n    logStatus<<\"read platform file <\"<<fileNamePlatform<<\">\"<<Log::endl;\n    Platform platform;\n    readFilePlatform(fileNamePlatform, platform);\n\n    const Time timeStart = arc.front().time;\n    Vector3d com  = platform.referencePoint(timeStart);\n    auto antenna  = platform.findEquipment<PlatformGnssAntenna>(timeStart);\n    if(!antenna)\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": no antenna definition found at \"+timeStart.dateTimeStr()));\n    auto receiver = platform.findEquipment<PlatformGnssReceiver>(timeStart);\n\n    auto fixedSize = [](const std::string &str, UInt size)\n    {\n      return (str+std::string(size, ' ')).substr(0, size);\n    };\n\n    // header\n    // ------\n    logStatus<<\"write RINEX file <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile file(fileNameOut);\n    file<<\"     4.00           O                   M                   RINEX VERSION / TYPE\"<<std::endl;\n    for(auto &comment : comments)\n      file<<fixedSize(comment, 60)                                  <<\"COMMENT             \"<<std::endl;\n    file<<\"GROOPS              \"<<fixedSize(angency, 20)<<System::now()%\"%y%m%d %H%M%S LCL PGM / RUN BY / DATE\"s<<std::endl;\n    file<<fixedSize(observer, 20)<<fixedSize(angency, 40)           <<\"OBSERVER / AGENCY   \"<<std::endl;\n    file<<fixedSize(platform.markerName, 60)                        <<\"MARKER NAME         \"<<std::endl;\n    if(!platform.markerNumber.empty())\n      file<<fixedSize(platform.markerNumber, 20)<<\"                                        MARKER NUMBER       \"<<std::endl;\n    if(receiver)\n      file<<fixedSize(receiver->serial, 20)<<fixedSize(receiver->name, 20)<<fixedSize(receiver->version, 20)<<\"REC # / TYPE / VERS \"<<std::endl;\n    file<<fixedSize(antenna->serial, 20)<<fixedSize(antenna->name, 16)<<fixedSize(antenna->radome, 4)<<\"                    ANT # / TYPE        \"<<std::endl;\n    file<<platform.approxPosition.x()%\"%14.4f\"s<<platform.approxPosition.y()%\"%14.4f\"s<<platform.approxPosition.z()%\"%14.4f                  APPROX POSITION XYZ \"s<<std::endl;\n    file<<antenna->position.z()%\"%14.4f\"s<<antenna->position.y()%\"%14.4f\"s<<antenna->position.x()%\"%14.4f                  ANTENNA: DELTA H/E/N\"s<<std::endl;\n    file<<antenna->position.x()%\"%14.4f\"s<<antenna->position.y()%\"%14.4f\"s<<antenna->position.z()%\"%14.4f                  ANTENNA: DELTA X/Y/Z\"s<<std::endl;\n    const Vector3d boresight = antenna->local2antennaFrame.inverseTransform(Vector3d(0,0,1));\n    const Vector3d zerodir   = antenna->local2antennaFrame.inverseTransform(Vector3d(1,0,0));\n    file<<boresight.x()%\"%14.4f\"s<<boresight.y()%\"%14.4f\"s<<boresight.z()%\"%14.4f                  ANTENNA: B.SIGHT XYZ\"s<<std::endl;\n    file<<zerodir.x()  %\"%14.4f\"s<<zerodir.y()  %\"%14.4f\"s<<zerodir.z()  %\"%14.4f                  ANTENNA: ZERODIR XYZ\"s<<std::endl;\n    if(com.r() >= 1e-4)\n      file<<com.x()%\"%14.4f\"s<<com.y()%\"%14.4f\"s<<com.z()%\"%14.4f                  CENTER OF MASS: XYZ \"s<<std::endl;\n    for(auto &system : types)\n    {\n      file<<system.first.str().at(3)<<system.second.size()%\"  %3i\"s;\n      UInt count = 0;\n      for(auto &type : system.second)\n      {\n        if(++count > 13) // continuation line?\n        {\n          count = 1;\n          file<<\"  SYS / # / OBS TYPES \"<<std::endl<<\"      \";\n        }\n        file<<\" \"<<type.str().substr(0, 3);\n      }\n      file<<std::string(60-6-4*count, ' ')<<\"SYS / # / OBS TYPES \"<<std::endl;\n    }\n    file<<timeStart      %\"  %y    %m    %d    %H    %M  %11.7S     GPS         TIME OF FIRST OBS \"s<<std::endl;\n    file<<arc.back().time%\"  %y    %m    %d    %H    %M  %11.7S     GPS         TIME OF LAST OBS  \"s<<std::endl;\n    if(glonass.size())\n    {\n      file<<glonass.size()%\"%3i \"s;\n      UInt count = 0;\n      for(auto &type : glonass)\n      {\n        if(++count > 8) // continuation line?\n        {\n          count = 1;\n          file<<\"GLONASS SLOT / FRQ #\"<<std::endl<<\"    \";\n        }\n        file<<type.str().substr(3, 3)<<type.frequencyNumber()%\" %2i \"s;\n      }\n      file<<std::string(60-4-7*count, ' ')<<\"GLONASS SLOT / FRQ #\"<<std::endl;\n    }\n    file<<\"                                                            END OF HEADER       \"<<std::endl;\n\n    // data section\n    // ------------\n    for(auto &epoch : arc)\n    {\n      // antenna change?\n      if(antenna != platform.findEquipment<PlatformGnssAntenna>(epoch.time))\n      {\n        antenna = platform.findEquipment<PlatformGnssAntenna>(epoch.time);\n        if(!antenna)\n          throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": no antenna definition found at \"+epoch.time.dateTimeStr()));\n        file<<\"> \"<<antenna->timeStart%\"%y %m %d %H %M%11.7S  4  5\"s<<std::endl;\n        file<<fixedSize(antenna->serial, 20)<<fixedSize(antenna->name, 16)<<fixedSize(antenna->radome, 4)<<\"                    ANT # / TYPE        \"<<std::endl;\n        file<<antenna->position.z()%\"%14.4f\"s<<antenna->position.y()%\"%14.4f\"s<<antenna->position.x()%\"%14.4f                  ANTENNA: DELTA H/E/N\"s<<std::endl;\n        file<<antenna->position.x()%\"%14.4f\"s<<antenna->position.y()%\"%14.4f\"s<<antenna->position.z()%\"%14.4f                  ANTENNA: DELTA X/Y/Z\"s<<std::endl;\n        const Vector3d boresight = antenna->local2antennaFrame.inverseTransform(Vector3d(0,0,1));\n        const Vector3d zerodir   = antenna->local2antennaFrame.inverseTransform(Vector3d(1,0,0));\n        file<<boresight.x()%\"%14.4f\"s<<boresight.y()%\"%14.4f\"s<<boresight.z()%\"%14.4f                  ANTENNA: B.SIGHT XYZ\"s<<std::endl;\n        file<<zerodir.x()  %\"%14.4f\"s<<zerodir.y()  %\"%14.4f\"s<<zerodir.z()  %\"%14.4f                  ANTENNA: ZERODIR XYZ\"s<<std::endl;\n      }\n\n      // receiver change?\n      if(receiver != platform.findEquipment<PlatformGnssReceiver>(epoch.time))\n      {\n        receiver = platform.findEquipment<PlatformGnssReceiver>(epoch.time);\n        if(receiver)\n        {\n          file<<\"> \"<<receiver->timeStart%\"%y %m %d %H %M%11.7S  4  1\"s<<std::endl;\n          file<<fixedSize(receiver->serial, 20)<<fixedSize(receiver->name, 20)<<fixedSize(receiver->version, 20)<<\"REC # / TYPE / VERS \"<<std::endl;\n        }\n      }\n\n      // center of mass change?\n      if((com-platform.referencePoint(epoch.time)).r() >= 1e-4)\n      {\n        com = platform.referencePoint(epoch.time);\n        file<<\"> \"<<epoch.time%\"%y %m %d %H %M%11.7S  4  1\"s<<std::endl;\n        file<<com.x()%\"%14.4f\"s<<com.y()%\"%14.4f\"s<<com.z()%\"%14.4f                  CENTER OF MASS: XYZ \"s<<std::endl;\n      }\n\n      // Has satellite valid observation types?\n      auto isSat = [&](GnssType satType)\n      {\n        for(UInt idType = GnssType::index(epoch.obsType, satType); (idType < epoch.obsType.size()) && (epoch.obsType.at(idType) == satType); idType++)\n          if((!useType.size() || (epoch.obsType.at(idType)+satType).isInList(useType)) && !(epoch.obsType.at(idType)+satType).isInList(ignoreType))\n            return TRUE;\n        return FALSE;\n      };\n\n      const UInt countSat = std::count_if(epoch.satellite.begin(), epoch.satellite.end(), isSat);\n      if(!countSat)\n        continue;\n      file<<\"> \"<<epoch.time%\"%y %m %d %H %M%11.7S  0\"s<<countSat%\"%3i\"s;\n      if(epoch.clockError)\n        file<<epoch.clockError%\"      %15.12f\"s;\n      file<<std::endl;\n\n      UInt idObs = 0, idx;\n      for(GnssType satType : epoch.satellite)\n      {\n        UInt idType = GnssType::index(epoch.obsType, satType); // find type for the satellite system\n        if(isSat(satType))\n        {\n          file<<satType.str().substr(3, 3);\n          for(GnssType type : types.at(satType & GnssType::SYSTEM))\n            if(type.isInList(epoch.obsType, idx) && !std::isnan(epoch.observation.at(idObs+idx-idType)) &&\n               (!useType.size() || (type+satType).isInList(useType)) && !(type+satType).isInList(ignoreType))\n              file<<(epoch.observation.at(idObs+idx-idType) / ((type == GnssType::PHASE) ? (type+satType).wavelength() : 1.))%\"%14.3f  \"s; // convert to cycles\n            else\n              file<<\"                \";\n          file<<std::endl;\n        }\n\n        // to next satellite\n        while((idType < epoch.obsType.size()) && (epoch.obsType.at(idType) == satType))\n          idType++, idObs++;\n      } // for(satType)\n    } // for(epoch)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssRinexNavigation2OrbitClock.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssRinexNavigation2OrbitClock.cpp\n*\n* @brief Convert RINEX navigation file (e.g. broadcast ephemeris) to orbit and clock files.\n*\n* @author Sebastian Strasser\n* @author Patrick Dumitraschkewitz\n* @date 2017-02-28\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nEvaluates orbit and clock parameters from \\href{https://files.igs.org/pub/data/format/rinex_4.00.pdf}{RINEX} (version 2, 3, and 4)\nnavigation file \\config{inputfileRinex} at epochs given by \\configClass{timeSeries}{timeSeriesType} and writes them to\n\\configFile{outputfileOrbit}{instrument} and \\configFile{outputfileClock}{instrument}, respectively.\n\nOrbits are rotated from TRF (as broadcasted) to CRF via \\configClass{earthRotation}{earthRotationType},\nbut system-specific TRFs (WGS84, PZ-90, etc.) are not aligned to a common TRF.\n\nFurthermore, option is available to remove any satellite ephemeris data that has their satellite flag set to unhealthy.\n\nSee also \\program{OrbitAddVelocityAndAcceleration}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert RINEX navigation file (e.g. broadcast ephemeris) to orbit and clock files.\n* @ingroup programsConversionGroup */\nclass GnssRinexNavigation2OrbitClock\n{\n  class NavData\n  {\n  public:\n    NavData(const std::string &msgType, GnssType prn, const Time &timeClock, const Vector &clock, const std::vector<Vector> &data)\n      : msgType(msgType), prn(prn), timeClock(timeClock), clock(clock), data(data) {}\n\n    std::string         msgType;     // since RINEX 4\n    GnssType            prn;\n    Time                timeClock, timeEph; // time of clock and ephemeris in GPS time\n    Vector              clock;\n    std::vector<Vector> data;        // lines with 4 values\n\n    Double crs()      const  {return data.at(0)(1);}\n    Double delta_n()  const  {return data.at(0)(2);}\n    Double m0()       const  {return data.at(0)(3);}\n    Double cuc()      const  {return data.at(1)(0);}\n    Double e()        const  {return data.at(1)(1);}\n    Double cus()      const  {return data.at(1)(2);}\n    Double a()        const  {return std::pow(data.at(1)(3), 2);}\n    Double cic()      const  {return data.at(2)(1);}\n    Double omega0()   const  {return data.at(2)(2);}\n    Double cis()      const  {return data.at(2)(3);}\n    Double i0()       const  {return data.at(3)(0);}\n    Double crc()      const  {return data.at(3)(1);}\n    Double omega()    const  {return data.at(3)(2);}\n    Double omegaDot() const  {return data.at(3)(3);}\n    Double iDot()     const  {return data.at(4)(0);}\n  };\n\n  void readRinex(const FileName &fileName, std::map<GnssType, std::vector<NavData>> &satellites);\n  OrbitEpoch rungeKutta4(const Time &time, const OrbitEpoch &refEpoch, const Vector3d &sunMoonAcceleration, EarthRotationPtr earthRotation, const Double GM, const Double C20, const Double a_e) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssRinexNavigation2OrbitClock, SINGLEPROCESS, \"Convert RINEX navigation file (e.g. broadcast ephemeris) to orbit and clock files.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\nvoid GnssRinexNavigation2OrbitClock::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 outNameOrbit, outNameClock, inNameRinex;\n    TimeSeriesPtr            timeSeriesPtr;\n    EarthRotationPtr         earthRotation;\n    std::vector<GnssType>    useType, ignoreType;\n    Bool                     removeUnhealthySatellites = TRUE;\n\n    readConfig(config, \"outputfileOrbit\",           outNameOrbit,              Config::OPTIONAL, \"\",  \"PRN is appended to file name\");\n    readConfig(config, \"outputfileClock\",           outNameClock,              Config::OPTIONAL, \"\",  \"PRN is appended to file name\");\n    readConfig(config, \"inputfileRinex\",            inNameRinex,               Config::MUSTSET,  \"\",  \"RINEX navigation file\");\n    readConfig(config, \"timeSeries\",                timeSeriesPtr,             Config::MUSTSET,  \"\",  \"orbit and clock evaluation epochs\");\n    readConfig(config, \"earthRotation\",             earthRotation,             Config::MUSTSET,  \"\",  \"for rotation from TRF to CRF\");\n    readConfig(config, \"useType\",                   useType,                   Config::OPTIONAL, \"\",  \"(e.g. ***G12) only use satellites with PRN that match any of these patterns\");\n    readConfig(config, \"ignoreType\",                ignoreType,                Config::OPTIONAL, \"\",  \"(e.g. ***R**) ignore satellites PRN that match any of these patterns\");\n    readConfig(config, \"removeUnhealthySatellites\", removeUnhealthySatellites, Config::DEFAULT,  \"1\", \"Remove satellite ephemeris that have their sat flags set to unhealthy\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time> times = timeSeriesPtr->times();\n\n    // read file\n    logStatus<<\"read RINEX file <\"<<inNameRinex<<\">\"<<Log::endl;\n    std::map<GnssType, std::vector<NavData>> satellites;\n    readRinex(inNameRinex, satellites);\n\n    // check useType and ignoreType\n    // ----------------------------\n    for(auto iter=satellites.begin(); iter!=satellites.end();)\n    {\n      Bool use = (useType.size()==0) ? TRUE : FALSE;\n      if(iter->first.isInList(useType))\n        use = TRUE;\n      if(iter->first.isInList(ignoreType))\n        use = FALSE;\n\n      if(!use)\n        iter = satellites.erase(iter);\n      else\n        iter++;\n    }\n\n    // remove empty satellites\n    // -----------------------\n    for(auto iter=satellites.begin(); iter!=satellites.end();)\n    {\n      if(!iter->second.size())\n        iter = satellites.erase(iter);\n      else\n        iter++;\n    }\n\n    // remove unsupported\n    // ------------------\n    const std::vector<GnssType> supportedSystems{GnssType::GPS, GnssType::GALILEO, GnssType::BDS, GnssType::QZSS, GnssType::IRNSS, GnssType::GLONASS, GnssType::SBAS};\n    std::set<GnssType> unsupportedSatellites;\n    for(auto iter=satellites.begin(); iter!=satellites.end();)\n    {\n      if(iter->first.isInList(supportedSystems))\n        iter++;\n      else\n      {\n        unsupportedSatellites.insert(iter->first);\n        iter = satellites.erase(iter);\n      }\n    }\n    if(unsupportedSatellites.size())\n    {\n      std::stringstream ss;\n      for(auto sat : unsupportedSatellites)\n        ss<<\" \"<<sat.prnStr();\n      logWarning<<\"conversion not implemented yet for these satellites:\"<<ss.str()<<Log::endl;\n    }\n\n    // remove unhealthy satellites\n    // ---------------------------\n    if(removeUnhealthySatellites)\n      for(auto iter=satellites.begin(); iter!=satellites.end();)\n      {\n        Bool unhealthy = FALSE;\n        for(auto &navData : iter->second)\n        {\n          if((navData.prn == GnssType::GPS) || (navData.prn == GnssType::QZSS))\n          {\n            if((navData.msgType == \"CNAV\") || (navData.msgType == \"CNV2\"))\n            {\n              if(navData.data.at(5)(1) > 0)\n                unhealthy = TRUE;\n            }\n            else if(static_cast<UInt>(navData.data.at(5)(1)) & 32)\n              unhealthy = TRUE;\n          }\n          else if((navData.prn == GnssType::GLONASS) || (navData.prn == GnssType::SBAS))\n          {\n            if(static_cast<UInt>(navData.data.at(0)(3)) & (1+2+4))\n              unhealthy = TRUE;\n          }\n          else if(navData.prn == GnssType::GALILEO)\n          {\n            UInt dataSourceBits = static_cast<UInt>(navData.data.at(4)(1)) & (1+2+4);\n            UInt svH            = static_cast<UInt>(navData.data.at(5)(1)) & (1+8+64);\n            if(((dataSourceBits & 1) && (svH & 1))  || // E1B INAV\n               ((dataSourceBits & 2) && (svH & 8))  || // E5a FNAV\n               ((dataSourceBits & 4) && (svH & 64)))   // E5b INAV\n              unhealthy = TRUE;\n          }\n          else if(navData.prn == GnssType::BDS)\n          {\n            if(navData.msgType.empty() || navData.msgType == \"D1\" || navData.msgType == \"D2\")\n            {\n              if(static_cast<UInt>(navData.data.at(5)(1)) & 1)\n                unhealthy = TRUE;\n            }\n            else if(navData.msgType == \"CNV1\" || navData.msgType == \"CNV2\")\n            {\n              if(static_cast<UInt>(navData.data.at(7)(1)) & 1)\n                unhealthy = TRUE;\n            }\n            else if(navData.msgType == \"CNV3\")\n            {\n              if(static_cast<UInt>(navData.data.at(6)(1)) & 1)\n                unhealthy = TRUE;\n            }\n          }\n          else if(navData.prn == GnssType::IRNSS)\n          {\n            if(navData.data.at(5)(1) > 0)\n              unhealthy = TRUE;\n          }\n        } // for each data rectord\n\n        if(unhealthy)\n        {\n          logInfo<<\"  \"<<iter->first.prnStr()<<\" is unhealthy: disabled\"<<Log::endl;\n          iter = satellites.erase(iter);\n        }\n        else\n          iter++;\n      }\n\n    // disable satellties with inconsistent data records\n    // -------------------------------------------------\n    for(auto iter=satellites.begin(); iter!=satellites.end();)\n    {\n      Bool unhealthy = FALSE;\n      for(UInt it1=0; it1<iter->second.size(); it1++)\n        for(UInt it2=it1+1; it2<iter->second.size(); it2++)\n        {\n          auto &dat1 = iter->second.at(it1);\n          auto &dat2 = iter->second.at(it2);\n          if((dat1.msgType == dat2.msgType) && (dat1.timeClock == dat2.timeClock))\n          {\n            // check if data is same\n            Bool different = FALSE;\n            for(UInt i=0; i<std::min(dat1.data.size(), UInt(3)); i++)\n              for(UInt k=0; k<dat1.data.at(i).size(); k++)\n                if(std::fabs(dat1.data.at(i)(k)-dat2.data.at(i)(k)) > 1e-9 * std::max(std::fabs(dat1.data.at(i)(k)), std::fabs(dat2.data.at(i)(k))))\n                  different = TRUE;\n            if(different)\n            {\n              unhealthy = TRUE;\n              break;\n            }\n          }\n        } // for each data rectord\n\n      if(unhealthy)\n      {\n        logWarning<<\"  \"<<iter->first.prnStr()<<\" with inconsistent data sets: disabled\"<<Log::endl;\n        iter = satellites.erase(iter);\n      }\n      else\n        iter++;\n    }\n\n    // convert times to GPS time ephemeris\n    // -----------------------------------\n    for(auto &satellite : satellites)\n      for(auto &navData : satellite.second)\n      {\n        if((navData.prn == GnssType::GPS)     ||\n           (navData.prn == GnssType::GALILEO) ||\n           (navData.prn == GnssType::QZSS)    ||\n           (navData.prn == GnssType::IRNSS))\n        {\n          navData.timeEph = date2time(1980, 1, 6) + seconds2time(navData.data.at(2)(0));\n          if(navData.msgType == \"CNAV\" || navData.msgType == \"CNAV2\")\n            navData.timeEph = navData.timeClock;\n        }\n        else if(navData.prn == GnssType::GLONASS)\n        {\n          navData.timeEph = navData.timeClock = timeUTC2GPS(navData.timeClock);\n        }\n        else if(navData.prn == GnssType::SBAS)\n        {\n          navData.timeEph = navData.timeClock;\n        }\n        else if(navData.prn == GnssType::BDS)\n        {\n          navData.timeClock -= seconds2time(14);\n          navData.timeEph    = date2time(2006, 1, 1, 0, 0, 14) + seconds2time(navData.data.at(2)(0));\n        }\n\n        // Adjust week\n        while((navData.timeEph-navData.timeClock).mjd() > 3.5)\n          navData.timeEph -= mjd2time(7);\n        while((navData.timeEph-navData.timeClock).mjd() < -3.5)\n          navData.timeEph += mjd2time(7);\n      }\n\n    // compute orbit\n    // -------------\n    if(!outNameOrbit.empty())\n    {\n      logStatus<<\"writing \"<<satellites.size()<<\" orbit files <\"<<outNameOrbit.appendBaseName(\".{prn}\")<<\">\"<<Log::endl;\n      for(const auto &satellite : satellites)\n        if(satellite.second.size())\n        {\n          OrbitArc arc;\n          for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n          {\n            OrbitEpoch epoch;\n            epoch.time = times.at(idEpoch);\n\n            const NavData &navData = *std::min_element(satellite.second.begin(), satellite.second.end(),\n                                      [&](auto &d1, auto &d2){return std::fabs((d1.timeEph-times.at(idEpoch)).seconds()) < std::fabs((d2.timeEph-times.at(idEpoch)).seconds());});\n            const Double dt = (epoch.time - navData.timeEph).seconds();\n\n            if(satellite.first == GnssType::GLONASS)\n            {\n              const Double GM  = 3.9860044e14;\n              const Double C20 = -1082.63e-6;\n              const Double a_e = 6378136;\n\n              // reference epoch\n              Rotary3d crf2trf = earthRotation->rotaryMatrix(navData.timeEph);\n              epoch.time       = navData.timeEph;\n              epoch.position   = crf2trf.inverseRotate(1e3*Vector3d(navData.data.at(0)(0), navData.data.at(1)(0), navData.data.at(2)(0)));\n              epoch.velocity   = crf2trf.inverseRotate(1e3*Vector3d(navData.data.at(0)(1), navData.data.at(1)(1), navData.data.at(2)(1)))\n                               + crossProduct(earthRotation->rotaryAxis(navData.timeEph), epoch.position);\n              Vector3d sunMoonAcceleration = 1e3 * Vector3d(navData.data.at(0)(2), navData.data.at(1)(2), navData.data.at(2)(2));\n\n              // Runge-Kutta-4 integration with around 60 second step size\n              if(navData.timeEph != times.at(idEpoch))\n              {\n                UInt steps = static_cast<UInt>(std::max(std::round(std::fabs(dt/60.)), 1.));\n                for(UInt i=0; i<steps; i++)\n                  epoch = rungeKutta4(navData.timeEph+seconds2time((i+1)*dt/steps), epoch, sunMoonAcceleration, earthRotation, GM, C20, a_e);\n                // NOTE: integration can lead to errors up to ~10 m after 15 minutes, unclear if that's the accuracy limit or there's an issue somewhere in the code\n              }\n            }\n            else if(satellite.first == GnssType::SBAS)\n            {\n              // ref to  RTCA DO229\n              epoch.position     = Vector3d(navData.data.at(0)(0), navData.data.at(1)(0), navData.data.at(2)(0)) * 1e3;\n              epoch.velocity     = Vector3d(navData.data.at(0)(1), navData.data.at(1)(1), navData.data.at(2)(1)) * 1e3;\n              epoch.acceleration = Vector3d(navData.data.at(0)(2), navData.data.at(1)(2), navData.data.at(2)(2)) * 1e3;\n\n              epoch.position += epoch.velocity*dt + epoch.acceleration*dt*dt/2.0;\n              epoch.velocity += epoch.acceleration*dt;\n\n              Rotary3d crf2trf = earthRotation->rotaryMatrix(epoch.time);\n              Vector3d omega   = earthRotation->rotaryAxis(epoch.time);\n              epoch.position   = crf2trf.inverseRotate(epoch.position); // TRF -> CRF\n              epoch.velocity   = crf2trf.inverseRotate(epoch.velocity) + crossProduct(omega, epoch.position); // TRF -> CRF\n            }\n            else // all systems using GPS-like ephemerides\n            {\n              const std::map<GnssType, Double> GM      {{GnssType::GPS,     3.986005e14},\n                                                        {GnssType::GALILEO, 3.986004418e14},\n                                                        {GnssType::BDS,     3.986004418e14},\n                                                        {GnssType::QZSS,    3.986005e14},\n                                                        {GnssType::IRNSS,   3.986005e14}};\n\n              const std::map<GnssType, Double> omega_e {{GnssType::GPS,     7.2921151467e-5},\n                                                        {GnssType::GALILEO, 7.2921151467e-5},\n                                                        {GnssType::BDS,     7.292115e-5},\n                                                        {GnssType::QZSS,    7.2921151467e-5},\n                                                        {GnssType::IRNSS,   7.2921151467e-5}};\n\n              // GPS CNAV, GPS CNAV2 require different algorithm then LNAV for example\n              // BDS CNAV, CNAV2, CNAV3\n              // QZSS CNAV, CNAV2, CNAV3\n              // sqrt(A) in rx4 is actually not sqrt(A)\n              // https://www.gps.gov/technical/icwg/IS-GPS-800J.pdf\n              // https://www.gps.gov/technical/icwg/IS-GPS-705J.pdf\n              // http://en.beidou.gov.cn/SYSTEMS/ICD/201806/P020180608519640359959.pdf\n              // http://en.beidou.gov.cn/SYSTEMS/ICD/201806/P020180608518432765621.pdf\n              // https://qzss.go.jp/en/technical/download/pdf/ps-is-qzss/is-qzss-pnt-005.pdf?t=1708078968591\n              // A, n and r are then required to be computed different\n              Double n = std::sqrt(GM.at(satellite.first & GnssType::SYSTEM) / std::pow(navData.a(), 3)) + navData.delta_n();\n              if((navData.prn == GnssType::GPS || navData.prn == GnssType::BDS || navData.prn == GnssType::QZSS) &&\n                 (navData.msgType == \"CNAV\" || navData.msgType == \"CNV1\" || navData.msgType == \"CNV2\" || navData.msgType == \"CNV3\"))\n                n += 0.5 * navData.data.at(4)(1) * dt;\n\n              const Double M = std::fmod(navData.m0() + n * dt, 2.*PI);\n              Double E = M;\n              for(UInt i=0; i<10; i++)\n                E = M + navData.e() * std::sin(E);\n              E = std::fmod(E, 2.*PI);\n\n              // true anomaly\n              const Double nu = std::atan2(std::sqrt(1. - std::pow(navData.e(), 2.)) * std::sin(E), std::cos(E) - navData.e());\n              //argument of latitude\n              const Double du = navData.cuc() * std::cos(2. * (nu + navData.omega())) + navData.cus() * std::sin(2. * (nu + navData.omega()));\n              const Double u  = nu + navData.omega() + du;\n              // radius in orbital plane\n              const Double dr = navData.crc() * std::cos(2. * (nu + navData.omega())) + navData.crs() * std::sin(2. * (nu + navData.omega()));\n\n              Double r  = navData.a() * (1. - navData.e() * std::cos(E)) + dr;\n              // sqrt(A) in rx4 is actually not sqrt(A)\n              // A, n and r are then required to be computed different\n              if((navData.prn == GnssType::GPS || navData.prn == GnssType::BDS || navData.prn == GnssType::QZSS) &&\n                 (navData.msgType == \"CNAV\" || navData.msgType == \"CNV1\" || navData.msgType == \"CNV2\" || navData.msgType == \"CNV3\"))\n                r = (navData.a() + navData.data.at(0)(0) * dt) * (1. - navData.e() * std::cos(E)) + dr;\n\n              // inclination\n              const Double di = navData.cic() * std::cos(2. * (nu + navData.omega())) + navData.cis() * std::sin(2. * (nu + navData.omega()));\n              const Double i  = navData.i0() + navData.iDot() * dt + di;\n\n              // longitude of ascending node\n              Double lambda = navData.omega0()  + (navData.omegaDot() - omega_e.at(satellite.first & GnssType::SYSTEM)) * dt\n                            - omega_e.at(satellite.first & GnssType::SYSTEM) * navData.data.at(2)(0);\n              // CNAV toc = TOE. navData.data.at(2)(0) would be TOP for CNAV and CNAV2 GPS\n              // https://files.igs.org/pub/data/format/rinex_4.00.pdf\n              if(((navData.prn == GnssType::GPS) || (navData.prn == GnssType::QZSS)) &&\n                 (navData.msgType == \"CNAV\" || navData.msgType == \"CNV2\"))\n              {\n                Double gpsWeek = (navData.timeEph.mjdInt() - date2time(1980, 1, 6).mjdInt()) / 7;\n                Double gpsSecond = ((navData.timeEph.mjd() - date2time(1980, 1, 6).mjd()) / 7 - gpsWeek) * 7 * 24 * 3600;\n                lambda = navData.omega0()  + (navData.omegaDot() - omega_e.at(satellite.first & GnssType::SYSTEM)) * dt\n                       - omega_e.at(satellite.first & GnssType::SYSTEM) * gpsSecond;\n              }\n              // http://en.beidou.gov.cn/SYSTEMS/ICD/201902/P020190227702348791891.pdf p37\n              else if((navData.prn == GnssType::BDS) && (navData.prn.prn() <= 5 || (59 <= navData.prn.prn() && navData.prn.prn() <= 63)))\n                lambda = navData.omega0()  + navData.omegaDot() * dt\n                       - omega_e.at(satellite.first & GnssType::SYSTEM) * navData.data.at(2)(0);\n\n              // Position\n              const Double xOrb = r * std::cos(u);\n              const Double yOrb = r * std::sin(u);\n              epoch.position.x() = xOrb * std::cos(lambda) - yOrb * std::sin(lambda) * std::cos(i);\n              epoch.position.y() = xOrb * std::sin(lambda) + yOrb * std::cos(lambda) * std::cos(i);\n              epoch.position.z() = yOrb * std::sin(i);\n\n              // http://en.beidou.gov.cn/SYSTEMS/ICD/201902/P020190227702348791891.pdf p 37\n              if((navData.prn == GnssType::BDS) && (navData.prn.prn() <= 5 || (navData.prn.prn() >= 59 && navData.prn.prn() <= 63)))\n               epoch.position = (rotaryZ(Angle(omega_e.at(satellite.first & GnssType::SYSTEM)*dt))*rotaryX(Angle(-5*DEG2RAD))).rotate(epoch.position);\n\n              epoch.position = earthRotation->rotaryMatrix(epoch.time).inverseRotate(epoch.position); // TRF -> CRF\n            }\n            arc.push_back(epoch);\n          }\n\n          InstrumentFile::write(outNameOrbit.appendBaseName('.'+satellite.first.prnStr()), arc);\n        }\n    }\n\n    if(!outNameClock.empty())\n    {\n      logStatus<<\"writing \"<<satellites.size()<<\" clock files <\"<<outNameClock.appendBaseName(\".{prn}\")<<\">\"<<Log::endl;\n      for(const auto &satellite : satellites)\n        if(satellite.second.size())\n        {\n          MiscValueArc arc;\n          for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n          {\n            const NavData &navData = *std::min_element(satellite.second.begin(), satellite.second.end(),\n                                                      [&](auto &d1, auto &d2){return std::fabs((d1.timeClock-times.at(idEpoch)).seconds()) < std::fabs((d2.timeClock-times.at(idEpoch)).seconds());});\n\n            MiscValueEpoch epoch;\n            epoch.time = times.at(idEpoch);\n            const Double dt = (epoch.time - navData.timeClock).seconds();\n            for(UInt n=0; n<((navData.prn == GnssType::GLONASS || navData.prn == GnssType::SBAS) ? 2 : 3); n++)\n              epoch.value += navData.clock(n)*std::pow(dt, n);\n            arc.push_back(epoch);\n          }\n\n          // write clock file\n          InstrumentFile::write(outNameClock.appendBaseName(\".\"+satellite.first.prnStr()), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssRinexNavigation2OrbitClock::readRinex(const FileName &fileName, std::map<GnssType, std::vector<NavData>> &satellites)\n{\n  std::string line, label;\n\n  try\n  {\n    auto getLine = [](InFile &file, std::string &line, std::string &label)\n    {\n      try\n      {\n        std::getline(file, line);\n        if(line.back() == '\\r')\n          line.pop_back();\n        line.resize(std::max(UInt(80), line.size()), ' ');\n        label = line.substr(60, 20);\n        return file.good();\n      }\n      catch(...)\n      {\n        line.clear();\n        line.resize(80,' ');\n        label = line.substr(60, 20);\n        return FALSE;\n      }\n    };\n\n    auto testLabel = [](const std::string &labelInLine, const std::string &label, Bool optional=TRUE)\n    {\n      if(labelInLine.find(label) != std::string::npos)\n        return TRUE;\n      if(optional)\n        return FALSE;\n      throw(Exception(std::string(\"In Line '\")+labelInLine+\"' label '\"+label+\"' expected\\n\"));\n    };\n\n    InFile file(fileName);\n\n    getLine(file, line, label);\n    testLabel(label, \"RINEX VERSION / TYPE\", FALSE);\n    const Double rinexVersion = String::toDouble(line.substr(0, 9));\n    if(rinexVersion < 2)\n      logWarning<<\"old RINEX version: \"<<rinexVersion<<Log::endl;\n    if((line.at(20) != 'N') && !(rinexVersion < 3 && line.at(20) == 'G'))\n      throw(Exception(\"File must contain Navigation Data\"));\n    Char system = (rinexVersion) < 3 ? (line.at(20) == 'N' ? 'G' : 'R') : line.at(40);\n\n    // read header\n    // -----------\n    for(;;)\n    {\n      if(!getLine(file, line, label))\n        throw(Exception(\"error while reading RINEX header\"));\n      if(std::all_of(line.begin(), line.end(), isspace))\n      {\n        if(rinexVersion < 2)\n          break;\n        else\n          continue;\n      }\n      if(testLabel(label, \"END OF HEADER\"))\n        break;\n    }\n\n    // read data\n    // ---------\n    if(std::getline(file, line))\n      for(;;)\n      {\n        if(line.empty())\n          break;\n        line.resize(std::max(UInt(80), line.size()), ' ');\n\n        // RINEX 4 record identifier\n        std::string messageType;\n        if(rinexVersion >= 4)\n        {\n          if(line.substr(0,5) != \"> EPH\") // only ephemeris records are of interest\n          {\n            getline(file, line);\n            continue;\n          }\n          messageType = String::trim(line.substr(10,4));\n          std::getline(file, line);\n          line.resize(std::max(UInt(80), line.size()), ' ');\n        }\n\n        std::string prnStr = (rinexVersion < 3) ? system+line.substr(0,2): line.substr(0,3);\n        if(prnStr.at(1) == ' ') prnStr.at(1) = '0';\n        GnssType prn(\"***\"+prnStr);\n\n        // epoch\n        Int year   = String::toInt(line.substr(rinexVersion < 3 ?  3 :  4, rinexVersion < 3 ? 2 : 4));\n        Int month  = String::toInt(line.substr(rinexVersion < 3 ?  6 :  9, 2));\n        Int day    = String::toInt(line.substr(rinexVersion < 3 ?  9 : 12, 2));\n        Int hour   = String::toInt(line.substr(rinexVersion < 3 ? 12 : 15, 2));\n        Int minute = String::toInt(line.substr(rinexVersion < 3 ? 15 : 18, 2));\n        Double sec = String::toDouble(line.substr(rinexVersion < 3 ? 17 : 21, rinexVersion < 3 ? 5 : 2));\n        if(rinexVersion < 3)\n          year += ((year<=80) ? 2000 : 1900);\n        const Time time = date2time(year, month, day, hour, minute, sec);\n\n        // clock polynomial\n        Vector clock(3);\n        for(UInt i=0; i<clock.size(); i++)\n          clock(i) = String::toDouble(line.substr((rinexVersion < 3 ? 22 : 23)+i*19, 19));\n\n        // data\n        std::vector<Vector> data;\n        while(std::getline(file, line))\n        {\n          if(line.empty() || (line.at(0) != ' '))\n            break;\n          line.resize(std::max(UInt(80), line.size()), ' ');\n          Vector dataLine(4);\n          for(UInt k=0; k<4; k++)\n            dataLine(k) = String::toDouble(line.substr(((rinexVersion < 3) ? 3 : 4)+k*19, 19));\n          data.push_back(dataLine);\n        }\n\n        satellites[prn].push_back(NavData(messageType, prn, time, clock, data));\n      }\n  }\n  catch(std::exception &e)\n  {\n    logError<<\"'\"<<line<<\"'\"<<Log::endl;\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nOrbitEpoch GnssRinexNavigation2OrbitClock::rungeKutta4(const Time &time, const OrbitEpoch &refEpoch, const Vector3d &sunMoonAcceleration, EarthRotationPtr earthRotation,\n                                                       const Double GM, const Double C20, const Double a_e) const\n{\n  try\n  {\n    const Double dt = (time - refEpoch.time).seconds();\n\n    auto acceleration = [&](const OrbitEpoch &epoch)\n    {\n      Rotary3d crf2trf = earthRotation->rotaryMatrix(epoch.time);\n      Double r = epoch.position.r();\n      Vector3d ePos = crf2trf.rotate(epoch.position)/r;\n      Double mu = GM/std::pow(r, 2);\n      Double x = -mu*ePos.x() + 3./2.*C20*mu*ePos.x()*std::pow(a_e/r, 2)*(1.-5.*std::pow(ePos.z(), 2)) + sunMoonAcceleration.x();\n      Double y = -mu*ePos.y() + 3./2.*C20*mu*ePos.y()*std::pow(a_e/r, 2)*(1.-5.*std::pow(ePos.z(), 2)) + sunMoonAcceleration.y();\n      Double z = -mu*ePos.z() + 3./2.*C20*mu*ePos.z()*std::pow(a_e/r, 2)*(3.-5.*std::pow(ePos.z(), 2)) + sunMoonAcceleration.z();\n      return crf2trf.inverseRotate(Vector3d(x, y, z));\n    };\n\n    // orbit integration with Runge-Kutta-4 algorithm\n    OrbitEpoch k1 = refEpoch;\n    k1.acceleration = acceleration(refEpoch);\n\n    OrbitEpoch k2 = k1;\n    k2.time        += seconds2time(dt/2.);\n    k2.position    += dt/2. * k1.velocity;\n    k2.velocity    += dt/2. * k1.acceleration;\n    k2.acceleration = acceleration(k2);\n\n    OrbitEpoch k3 = k1;\n    k3.time        += seconds2time(dt/2.);\n    k3.position    += dt/2. * k2.velocity;\n    k3.velocity    += dt/2. * k2.acceleration;\n    k3.acceleration = acceleration(k3);\n\n    OrbitEpoch k4 = k1;\n    k4.time        += seconds2time(dt);\n    k4.position    += dt * k3.velocity;\n    k4.velocity    += dt * k3.acceleration;\n    k4.acceleration = acceleration(k4);\n\n    // Compute final value for this epoch\n    OrbitEpoch epoch = k1;\n    epoch.time        += seconds2time(dt);\n    epoch.position    += (dt/6.) * (k1.velocity + 2*k2.velocity + 2*k3.velocity + k4.velocity);\n    epoch.velocity    += (dt/6.) * (k1.acceleration + 2*k2.acceleration + 2*k3.acceleration + k4.acceleration);\n    epoch.acceleration = acceleration(epoch);\n\n    return epoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssSignalBias2SinexBias.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssSignalBias2SinexBias.cpp\n*\n* @brief Convert GNSS signal biases from GROOPS format to IGS SINEX Bias format.\n**\n* @author Sebastian Strasser\n* @date 2019-01-24\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert \\file{GNSS signal biases}{gnssSignalBias} from GROOPS format to \\href{https://files.igs.org/pub/data/format/sinex_bias_100.pdf}{IGS SINEX Bias format}.\nBiases can be provided via \\config{transmitterBiases} and/or \\config{receiverBiases}.\nPhase biases without attribute (e.g. \\verb|L1*|) are automatically expanded so each code\nbias has a corresponding phase bias\n(Example: \\verb|C1C|, \\verb|C1W|, \\verb|L1*| are converted to \\verb|C1C|, \\verb|C1W|, \\verb|L1C|, \\verb|L1W|).\n\nTime-variable biases (e.g. GPS L5 satellite phase bias) can be provided via \\config{timeVariableBias}.\nTheir time span will be based on the provided epochs ($t \\pm \\Delta t / 2$).\nThe slope of the bias can be optionally provided in the second data column.\n\nIf GLONASS receiver biases depend on frequency number, those must be defined in \\configFile{inputfileTransmitterInfo}{platform}\nto get the correct PRN/SVN assignment to the biases.\n\nSee IGS SINEX Bias format description for further details on header information.\n\nSee also \\program{GnssSinexBias2SignalBias} and \\program{GnssBiasClockAlignment}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileMatrix.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert GNSS signal biases from GROOPS format to IGS SINEX Bias format.\n* @ingroup programsConversionGroup */\nclass GnssSignalBias2SinexBias\n{\npublic:\n  class TimeVariableBias\n  {\n  public:\n    FileName inNameBias;\n    GnssType type;\n    Matrix   biases;\n  };\n\n  class Data\n  {\n  public:\n    FileName inNameBias, inNameTransmitterInfo;\n    std::string identifier;\n    GnssSignalBias biases;\n    std::vector<TimeVariableBias> timeVariableBiases;\n\n    inline Bool isTimeVariableBias(const GnssType &type) const\n    {\n      return std::find_if(timeVariableBiases.begin(), timeVariableBiases.end(), [&](const TimeVariableBias &bias){ return bias.type.type == (type & GnssType::NOPRN).type; }) != timeVariableBiases.end();\n    }\n  };\n\nprivate:\n  std::map<std::string, Platform> prn2platform;\n  std::map<Int, std::vector<std::string>> freqNo2prns;\n\n  static std::string resize(std::string str, UInt length) {str.resize(length, ' '); return str;}\n  void readData(std::vector<Data> &data) const;\n  void writeLine(SinexBlockPtr block, const Time &timeStart, const Time &timeEnd, std::string prn, std::string svn, std::string stationName,\n                 const GnssType &type, std::string unit, Double bias, Double sigma, Double biasSlope, Double biasSlopeSigma) const;\n  void writeData(SinexBlockPtr block, const Time &timeStart, const Time &timeEnd, const Data &data, Bool isStation) const;\n  UInt countBiases(const std::vector<Data> &data) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssSignalBias2SinexBias, SINGLEPROCESS, \"Convert GNSS signal biases from GROOPS format to IGS SINEX Bias format.\", Conversion, Gnss)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssSignalBias2SinexBias::TimeVariableBias &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileSignalBias\",  var.inNameBias,  Config::MUSTSET, \"\", \"columns: mjd, bias [m], (biasSlope [m/s])\");\n  readConfig(config, \"type\",                 var.type,        Config::MUSTSET, \"\", \"bias type\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssSignalBias2SinexBias::Data &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileSignalBias\",  var.inNameBias,         Config::MUSTSET,  \"\", \"signal bias file\");\n  readConfig(config, \"timeVariableBias\",     var.timeVariableBiases, Config::OPTIONAL, \"\", \"one entry per time variable bias type\");\n  readConfig(config, \"identifier\",           var.identifier,         Config::MUSTSET,  \"\", \"PRN or station name (e.g. G23 or wtzz)\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssSignalBias2SinexBias::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outNameSinexBias;\n    std::vector<FileName> inNameTransmitterInfo;\n    std::vector<Data> transmitterBiases, receiverBiases;\n    Time timeStart, timeEnd;\n    std::string agencyCode, fileAgencyCode, biasMode, method, receiverClockReferenceGnss, description, output, contact, software, hardware, input;\n    std::vector<std::string> satelliteClockReferenceObservables, comments;\n    Double sampling = NAN_EXPR;\n    Double intervalLength = NAN_EXPR;\n\n    readConfig(config, \"outputfileSinexBias\",      outNameSinexBias,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileTransmitterInfo\", inNameTransmitterInfo, Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\", \"one file per satellite\");\n    readConfig(config, \"transmitterBiases\",        transmitterBiases,     Config::OPTIONAL, \"\", \"one element per satellite\");\n    readConfig(config, \"receiverBiases\",           receiverBiases,        Config::OPTIONAL, \"\", \"one element per station\");\n    readConfig(config, \"agencyCode\",               agencyCode,            Config::MUSTSET,  \"TUG\", \"identify the agency providing the data\");\n    readConfig(config, \"fileAgencyCode\",           fileAgencyCode,        Config::MUSTSET,  \"TUG\", \"identify the agency creating the file\");\n    readConfig(config, \"timeStart\",                timeStart,             Config::MUSTSET,  \"\", \"start time of the data\");\n    readConfig(config, \"timeEnd\",                  timeEnd,               Config::MUSTSET,  \"\", \"end time of the data \");\n    if(readConfigChoice(config, \"biasMode\", biasMode, Config::MUSTSET, \"absolute\",  \"absolute or relative bias estimates\"))\n    {\n      readConfigChoiceElement(config, \"absolute\", biasMode, \"\");\n      readConfigChoiceElement(config, \"relative\", biasMode, \"\");\n      endChoice(config);\n    }\n    readConfig(config, \"observationSampling\", sampling,       Config::OPTIONAL, \"30\", \"[seconds]\");\n    readConfig(config, \"intervalLength\",      intervalLength, Config::OPTIONAL, \"86400\", \"[seconds] interval for bias parameter representation\");\n    readConfig(config, \"determinationMethod\", method,         Config::OPTIONAL, \"CO-ESTIMATED_IN_LSA\", \"determination method used to generate the bias results (see SINEX Bias format description)\");\n    readConfig(config, \"receiverClockReferenceGnss\",         receiverClockReferenceGnss,         Config::OPTIONAL, \"G\", \"(G, R, E, C) reference GNSS used for receiver clock estimation\");\n    readConfig(config, \"satelliteClockReferenceObservables\", satelliteClockReferenceObservables, Config::OPTIONAL, \"G  C1W  C2W\", \"one per system, reference code observable on first and second frequency (RINEX3 format)\");\n    readConfig(config, \"description\",         description,    Config::OPTIONAL, \"Graz University of Technology, Austria (TUG/TU Graz)\", \"organization gathering/altering the file contents\");\n    readConfig(config, \"contact\",             contact,        Config::OPTIONAL, \"\", \"contact name and/or email address\");\n    readConfig(config, \"input\",               input,          Config::OPTIONAL, \"GNSS observations from the IGS station network\", \"brief description of the input used to generate this solution\");\n    readConfig(config, \"output\",              output,         Config::OPTIONAL, \"Estimated signal biases from GNSS processing\", \"description of the file contents\");\n    readConfig(config, \"software\",            software,       Config::OPTIONAL, \"GROOPS (https://github.com/groops-devs/groops)\", \"software used to generate the file\");\n    readConfig(config, \"hardware\",            hardware,       Config::OPTIONAL, \"\", \"computer hardware on which above software was run\");\n    readConfig(config, \"comment\",             comments,       Config::OPTIONAL, \"\", \"comments in the comment block\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read transmitter platform files\"<<Log::endl;\n    for(const auto &fileName : inNameTransmitterInfo)\n    {\n      Platform platform;\n      readFilePlatform(fileName, platform);\n      prn2platform[platform.markerNumber] = platform;\n    }\n\n    logStatus<<\"read bias files\"<<Log::endl;\n    readData(transmitterBiases);\n    readData(receiverBiases);\n\n    // create map: GLONASS frequencyNumber -> list of PRNs\n    for(const auto &trans : transmitterBiases)\n      if(trans.identifier.at(0) == 'R') // GLONASS only\n      {\n        auto recv = prn2platform[trans.identifier].findEquipment<PlatformGnssReceiver>(0.5*(timeStart+timeEnd));\n        if(!recv)\n          throw(Exception(\"no receiver info found in transmitter info for \"+trans.identifier));\n        freqNo2prns[std::stoi(recv->version)].push_back(trans.identifier);\n      }\n\n    logStatus<<\"write SINEX bias file <\"<<outNameSinexBias<<\">\"<<Log::endl;\n    Sinex sinex;\n    // SINEX header line\n    std::stringstream ss;\n    ss<<\"%=BIA \"<<1%\"%4.2f\"s<<' '<<resize(fileAgencyCode, 3)<<' '<<Sinex::time2str(System::now(), TRUE)<<' '<<resize(agencyCode, 3)<<' '\n      <<Sinex::time2str(timeStart, TRUE)<<' '<<Sinex::time2str(timeEnd, TRUE)<<' ' <<String::upperCase(biasMode).at(0)<<' '\n      <<(countBiases(transmitterBiases)+countBiases(receiverBiases))%\"%08i\"s<<std::endl;\n    sinex.header = ss.str();\n    sinex.footer = \"%=ENDBIA\";\n\n    // Block: FILE/REFERENCE\n    {\n      SinexBlockPtr block = sinex.addBlock(\"FILE/REFERENCE\");\n      *block<<\"*INFO_TYPE_________ INFO________________________________________________________\"<<std::endl;\n      if(!description.empty()) *block<<\" DESCRIPTION        \"<<description<<std::endl;\n      if(!output.empty())      *block<<\" OUTPUT             \"<<output<<std::endl;\n      if(!input.empty())       *block<<\" INPUT              \"<<input<<std::endl;\n      if(!contact.empty())     *block<<\" CONTACT            \"<<contact<<std::endl;\n      if(!software.empty())    *block<<\" SOFTWARE           \"<<software<<std::endl;\n      if(!hardware.empty())    *block<<\" HARDWARE           \"<<hardware<<std::endl;\n    }\n\n    // Block: FILE/COMMENT\n    if(comments.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"FILE/COMMENT\");\n      for(auto comment : comments)\n        *block<<' '<<comment<<std::endl;\n    }\n\n    // Block: BIAS/DESCRIPTION\n    {\n      SinexBlockPtr block = sinex.addBlock(\"BIAS/DESCRIPTION\");\n      *block<<\"*KEYWORD________________________________ VALUE(S)_______________________________\"<<std::endl;\n      if(!std::isnan(sampling))       *block<<\" OBSERVATION_SAMPLING                    \"<<sampling%\"% 12i\"s<<std::endl;\n      if(!std::isnan(intervalLength)) *block<<\" PARAMETER_SPACING                       \"<<intervalLength%\"% 12i\"s<<std::endl;\n      if(!method.empty())             *block<<\" DETERMINATION METHOD                    \"<<method<<std::endl;\n      if(!biasMode.empty())           *block<<\" BIAS_MODE                               \"<<String::upperCase(biasMode)<<std::endl;\n      *block<<\" TIME_SYSTEM                             G\"<<std::endl;\n      if(!receiverClockReferenceGnss.empty()) *block<<\" RECEIVER_CLOCK_REFERENCE_GNSS           \"<<receiverClockReferenceGnss.at(0)<<std::endl;\n      for(auto sys : satelliteClockReferenceObservables)\n        *block<<\" SATELLITE_CLOCK_REFERENCE_OBSERVABLES   \"<<resize(sys, 11)<<std::endl;\n    }\n\n    // Block: BIAS/SOLUTION\n    {\n      SinexBlockPtr block = sinex.addBlock(\"BIAS/SOLUTION\");\n      *block<<\"*BIAS SVN_ PRN STATION__ OBS1 OBS2 BIAS_START____ BIAS_END______ UNIT __ESTIMATED_VALUE____ _STD_DEV___ __ESTIMATED_SLOPE____ _STD_DEV___\"<<std::endl;\n      for(const auto &data : transmitterBiases)\n        writeData(block, timeStart, timeEnd, data, /*isStation*/FALSE);\n      for(const auto &data : receiverBiases)\n        writeData(block, timeStart, timeEnd, data, /*isStation*/TRUE);\n    }\n\n    writeFileSinex(outNameSinexBias, sinex);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssSignalBias2SinexBias::readData(std::vector<Data> &data) const\n{\n  try\n  {\n    auto iter = data.begin();\n    while(iter != data.end())\n    {\n      try\n      {\n        readFileGnssSignalBias(iter->inNameBias, iter->biases);\n\n        // replace unknown attributes with X (code) or * (phase)\n        for(auto &type : iter->biases.types)\n          if((type.type & GnssType::ATTRIBUTE.type) == GnssType::UNKNOWN_ATTRIBUTE.type)\n          {\n            type = (type & ~GnssType::ATTRIBUTE);\n            if(type == GnssType::RANGE)\n              type += GnssType::X;\n          }\n\n        for(auto &&bias : iter->timeVariableBiases)\n        {\n          try\n          {\n            readFileMatrix(bias.inNameBias, bias.biases);\n          }\n          catch(std::exception &e)\n          {\n            logWarning<<e.what()<<\" continue...\"<<Log::endl;\n            continue;\n          }\n        }\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        iter = data.erase(iter);\n        continue;\n      }\n\n      iter++;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssSignalBias2SinexBias::writeLine(SinexBlockPtr block, const Time &timeStart, const Time &timeEnd, std::string prn, std::string svn, std::string stationName,\n                                         const GnssType &type, std::string unit, Double bias, Double biasSigma, Double biasSlope, Double biasSlopeSigma) const\n{\n  stationName = String::upperCase(stationName);\n\n  if(!String::trim(stationName).empty())\n  {\n    if(String::trim(prn).empty())\n      prn = type.str().at(3);\n    if(String::trim(svn).empty())\n      svn = type.str().at(3);\n  }\n\n  *block<<\" OSB  \"<<resize(svn, 4)<<' '<<resize(prn, 3)<<' '<<resize(stationName, 9)<<' '<<type.str().substr(0,3)<<std::string(7, ' ')\n        <<Sinex::time2str(timeStart, TRUE)<<' '<<Sinex::time2str(timeEnd, TRUE)<<' '<<resize(unit, 4)<<bias%\" % 21.14e\"s<<biasSigma%\" % 11.5e\"s;\n  if(biasSlope != 0.)\n    *block<<biasSlope%\" % 21.14e\"s<<biasSlopeSigma%\" % 11.5e\"s;\n  *block<<std::endl;\n}\n\n/***********************************************/\n\nvoid GnssSignalBias2SinexBias::writeData(SinexBlockPtr block, const Time &timeStart, const Time &timeEnd, const Data &data, Bool isStation) const\n{\n  try\n  {\n    auto getSvn = [&](const std::string &prn)\n    {\n      auto antenna = prn2platform.at(prn).findEquipment<PlatformGnssAntenna>(timeStart);\n      if(!antenna)\n        throw(Exception(\"no SVN found for \"+data.identifier));\n      return antenna->serial;\n    };\n\n    std::string prn = (isStation ? \"\" : data.identifier);\n    std::string svn = (isStation ? \"\" : getSvn(prn));\n    std::string stationName = (isStation ? data.identifier : \"\");\n\n    auto writeCodeBias = [&](const Time &timeStart, const Time &timeEnd, const GnssType &type, Double bias, Double biasSlope=0.)\n    {\n      // GLONASS station bias per satellite\n      if(isStation && type == GnssType::GLONASS && type.frequencyNumber() != 9999)\n      {\n        if(freqNo2prns.find(type.frequencyNumber()) == freqNo2prns.end())\n          return;\n        for(const auto &prn : freqNo2prns.at(type.frequencyNumber()))\n          writeLine(block, timeStart, timeEnd, prn, getSvn(prn), stationName, type, \"ns\", bias/LIGHT_VELOCITY*1e9, 0, biasSlope/LIGHT_VELOCITY*1e9, 0);\n        return;\n      }\n\n      writeLine(block, timeStart, timeEnd, prn, svn, stationName, type, \"ns\", bias/LIGHT_VELOCITY*1e9, 0, biasSlope/LIGHT_VELOCITY*1e9, 0);\n    };\n\n    auto writePhaseBias = [&](const Time &timeStart, const Time &timeEnd, const GnssType &type, Double bias, Double biasSlope=0.)\n    {\n      for(const auto &type2 : data.biases.types)\n        if(type2 == (type & ~GnssType::TYPE) + GnssType::RANGE)\n        {\n          // GLONASS station bias per satellite\n          if(isStation && type == GnssType::GLONASS && type.frequencyNumber() != 9999)\n          {\n            if(freqNo2prns.find(type.frequencyNumber()) == freqNo2prns.end())\n              continue;\n            for(const auto &prn : freqNo2prns.at(type.frequencyNumber()))\n              writeLine(block, timeStart, timeEnd, prn, getSvn(prn), stationName, (type2 & ~GnssType::TYPE) + GnssType::PHASE,\n                        \"ns\", bias/LIGHT_VELOCITY*1e9, 0, biasSlope/LIGHT_VELOCITY*1e9, 0);\n            continue;\n          }\n\n          writeLine(block, timeStart, timeEnd, prn, svn, stationName, (type2 & ~GnssType::TYPE) + GnssType::PHASE,\n                    \"ns\", bias/LIGHT_VELOCITY*1e9, 0, biasSlope/LIGHT_VELOCITY*1e9, 0);\n        }\n    };\n\n\n    // Code biases\n    for(UInt i = 0; i < data.biases.types.size(); i++)\n      if(data.biases.types.at(i) == GnssType::RANGE && !data.isTimeVariableBias(data.biases.types.at(i)))\n        writeCodeBias(timeStart, timeEnd, data.biases.types.at(i), data.biases.biases.at(i));\n\n    // Phase biases (for wildcard types, i.e. L1*, write one line per matching code bias type with the same phase bias; example: C1C, C1W, L1* ==> C1C, C1W, L1C, L1W)\n    for(UInt i = 0; i < data.biases.types.size(); i++)\n      if(data.biases.types.at(i) == GnssType::PHASE && !data.isTimeVariableBias(data.biases.types.at(i)))\n        writePhaseBias(timeStart, timeEnd, data.biases.types.at(i), data.biases.biases.at(i));\n\n    // Time-variable biases\n    for(const auto &bias : data.timeVariableBiases)\n    {\n      Double constBias = 0;\n      for(UInt i = 0; i < data.biases.types.size(); i++)\n        if((data.biases.types.at(i) & GnssType::NOPRN).type == bias.type.type) // exact match\n          {\n            constBias = data.biases.biases.at(i);\n            break;\n          }\n\n      std::vector<Time> times(bias.biases.rows());\n      for(UInt idEpoch = 0; idEpoch < bias.biases.rows(); idEpoch++)\n        times.at(idEpoch) = mjd2time(bias.biases(idEpoch, 0));\n      Time sampling = medianSampling(times);\n      for(UInt idEpoch = 0; idEpoch < bias.biases.rows(); idEpoch++)\n      {\n        const Time timeStart = times.at(idEpoch)-0.5*sampling;\n        const Time timeEnd   = times.at(idEpoch)+0.5*sampling;\n        const Double biasValue = constBias + bias.biases(idEpoch, 1);\n        const Double biasSlope = bias.biases.columns() > 2 ? bias.biases(idEpoch, 2) : 0;\n        if(bias.type == GnssType::RANGE)\n          writeCodeBias(timeStart, timeEnd, bias.type, biasValue, biasSlope);\n        else if(bias.type == GnssType::PHASE)\n          writePhaseBias(timeStart, timeEnd, bias.type, biasValue, biasSlope);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt GnssSignalBias2SinexBias::countBiases(const std::vector<Data> &data) const\n{\n  try\n  {\n    UInt count = 0;\n    for(const auto &d : data)\n    {\n      for(UInt i = 0; i < d.biases.types.size(); i++)\n        if(d.biases.types.at(i) == GnssType::RANGE)\n          count++;\n\n      // Phase biases (for wildcard types, i.e. L1*, write one line per matching code bias type with the same phase bias; example: C1C, C1W, L1* ==> C1C, C1W, L1C, L1W)\n      for(UInt i = 0; i < d.biases.types.size(); i++)\n        if(d.biases.types.at(i) == GnssType::PHASE)\n          for(UInt j = 0; j < d.biases.types.size(); j++)\n            if(d.biases.types.at(j) == (d.biases.types.at(i) & ~GnssType::TYPE) + GnssType::RANGE)\n              count++;\n    }\n\n    return count;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssSinexBias2SignalBias.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssSinexBias2SignalBias.cpp\n*\n* @brief Converts GNSS signal biases from SINEX Bias format to GnssSignalBias format.\n*\n* @author Sebastian Strasser\n* @date 2020-09-30\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts GNSS signal biases from \\href{https://files.igs.org/pub/data/format/sinex_bias_100.pdf}{IGS SINEX Bias format}\nto \\file{GnssSignalBias format}{gnssSignalBias}.\n\nOnly satellite observable-specific signal biases (OSB) are supported at the moment.\nIf multiple entries exist for the same bias, the weighted average (based on time span) of all entries is used.\nTime-variable biases are not supported at the moment.\n\nSee also \\program{GnssSignalBias2SinexBias}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n#include \"inputOutput/fileSinex.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts GNSS signal biases from SINEX Bias format to GnssSignalBias format.\n* @ingroup programsGroup */\nclass GnssSinexBias2SignalBias\n{\n  class Bias\n  {\n  public:\n    Time timeStart, timeEnd;\n    Double value, slope;\n  };\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssSinexBias2SignalBias, SINGLEPROCESS, \"Converts GNSS signal biases from SINEX Bias format to GnssSignalBias format.\", Conversion, Gnss)\n\n/***********************************************/\n\nvoid GnssSinexBias2SignalBias::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutSignalBias, fileNameInSinexBias, fileNameInGlonassSignalDefinition;\n    std::vector<std::string> identifiers;\n\n    readConfig(config, \"outputfileSignalBias\",             fileNameOutSignalBias,             Config::MUSTSET,  \"\", \"identifier is appended to file name\");\n    readConfig(config, \"inputfileSinexBias\",               fileNameInSinexBias,               Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileGlonassSignalDefinition\", fileNameInGlonassSignalDefinition, Config::OPTIONAL, \"{groopsDataDir}/gnss/transmitter/signalDefinition/signalDefinition.xml\", \"GLONASS frequency number mapping\");\n    readConfig(config, \"identifier\",                       identifiers,                       Config::OPTIONAL, \"\", \"(empty = all) satellite PRN, e.g. G23 or E05\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read SINEX Bias file <\"<<fileNameInSinexBias<<\">\"<<Log::endl;\n    Sinex sinex;\n    readFileSinex(fileNameInSinexBias, sinex);\n    const std::vector<std::string> &lines = sinex.findBlock(\"BIAS/SOLUTION\")->lines;\n\n    std::vector<GnssReceiverDefinitionPtr> signalDefinitions;\n    if(!fileNameInGlonassSignalDefinition.empty())\n    {\n      logStatus<<\"read GLONASS signal definition file <\"<<fileNameInGlonassSignalDefinition<<\">\"<<Log::endl;\n      readFileGnssReceiverDefinition(fileNameInGlonassSignalDefinition, signalDefinitions);\n    }\n\n    Bool printStationWarning = TRUE;\n    Bool printNonOsbWarning = TRUE;\n    std::map<std::string, std::map<GnssType, std::vector<Bias>>> id2type2biases;\n    for(const auto &line : lines)\n    {\n      std::string biasType = String::trim(line.substr(1,3));\n      std::string svn      = String::trim(line.substr(6,4));\n      std::string prn      = String::trim(line.substr(11,3));\n      std::string station  = String::trim(line.substr(15,9));\n\n      if(biasType != \"OSB\")\n      {\n        if(printNonOsbWarning)\n        {\n          logWarning<<\"bias types other than OSB (observable-specific signal bias) are not yet implemented and will be ignored.\"<<Log::endl;\n          printNonOsbWarning = FALSE;\n        }\n        continue;\n      }\n      if(station.size() && (!identifiers.size() || std::find(identifiers.begin(), identifiers.end(), station) != identifiers.end()))\n      {\n        if(printStationWarning)\n        {\n          logWarning<<\"station biases are not yet implemented and will be ignored.\"<<Log::endl;\n          printStationWarning = FALSE;\n        }\n        continue;\n      }\n      if(identifiers.size() && std::find(identifiers.begin(), identifiers.end(), prn) == identifiers.end())\n        continue;\n\n      GnssType gnssType = GnssType(line.substr(25,3)+prn);\n      if(gnssType == GnssType::GLONASS)\n      {\n        auto iter = std::find_if(signalDefinitions.begin(), signalDefinitions.end(), [&](const GnssReceiverDefinitionPtr &def){ return def->serial == svn; });\n        if(iter != signalDefinitions.end())\n          gnssType.setFrequencyNumber(String::toInt((*iter)->version));\n      }\n      std::string unit = String::trim(line.substr(65,4));\n      Bias bias;\n      bias.value = String::toDouble(line.substr(70,21));\n      bias.slope = line.size() >= 125 ? String::toDouble(line.substr(104,21)) : 0.;\n      bias.timeStart = Sinex::str2time(line, 35, FALSE, TRUE);\n      bias.timeEnd   = Sinex::str2time(line, 50, TRUE,  TRUE);\n      if(unit == \"ns\")\n      {\n        bias.value *= 1e-9*LIGHT_VELOCITY;\n        bias.slope *= 1e-9*LIGHT_VELOCITY;\n      }\n      else if(unit == \"cyc\")\n      {\n        bias.value *= gnssType.wavelength();\n        bias.slope *= gnssType.wavelength();\n      }\n      else\n        throw(Exception(\"unknown unit: \"+unit));\n      id2type2biases[prn][gnssType].push_back(bias);\n    }\n\n    if(id2type2biases.size())\n    {\n      logStatus<<\"write signal bias files <\"<<fileNameOutSignalBias<<\">\"<<Log::endl;\n      for(const auto &id : id2type2biases)\n      {\n        GnssSignalBias signalBias;\n        for(const auto &type : id.second)\n        {\n          signalBias.types.push_back(type.first);\n          Double weightedSum  = std::accumulate(type.second.begin(), type.second.end(), 0.,\n                                                [](Double a, const Bias &bias){ return a + bias.value*(bias.timeEnd-bias.timeStart).seconds(); });\n          Double sumOfWeights = std::accumulate(type.second.begin(), type.second.end(), 0.,\n                                                [](Double a, const Bias &bias){ return a + (bias.timeEnd-bias.timeStart).seconds(); });\n          signalBias.biases.push_back(weightedSum/sumOfWeights);\n        }\n        writeFileGnssSignalBias(fileNameOutSignalBias.appendBaseName(\".\"+id.first), signalBias);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssStationLog2Platform.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssStationLog2Platform.cpp\n*\n* @brief GNSS analysis.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2012-04-28\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://files.igs.org/pub/station/general/blank.log}{IGS station log format} or\n\\href{https://files.igs.org/pub/station/general/blank_v2.0.log}{IGS station log format v2.0} to \\configFile{outputfileStationPlatform}{platform}.\n\nIf \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition} is provided, station log data is cross-checked with the given antenna definitions.\nCross-checking station log data with a \\href{https://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX file} is\npossible with \\program{CheckStationsPlatformsWithSinex}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS analysis.\n* @ingroup programsConversionGroup */\nclass GnssStationLog2Platform\n{\n  Platform readFile(const FileName &fileName);\n  void     newAntenna (Platform &platform, PlatformGnssAntenna &antenna) const;\n  void     newReceiver(Platform &platform, PlatformGnssReceiver &receiver) const;\n  void     newFreqStandard(Platform &platform, PlatformEquipment &freqStandard) const;\n  Bool     readDouble(const std::string &line, Double &x) const;\n  Bool     readString(const std::string &line, std::string &x) const;\n  Bool     readTime  (const std::string &line, Time &x) const;\n  Bool     readEffectiveDate(const std::string &line, Time &xStart, Time &xEnd) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssStationLog2Platform, SINGLEPROCESS, \"GNSS analysis\", Conversion, Gnss)\nGROOPS_RENAMED_PROGRAM(GnssStationLog2StationInfo, GnssStationLog2Platform, date2time(2025, 5, 15))\n\n/***********************************************/\n\nvoid GnssStationLog2Platform::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameStationPlatform, fileNameStationLog, fileNameAntenna;\n\n    renameDeprecatedConfig(config, \"outputfileStationInfo\", \"outputfileStationPlatform\", date2time(2023, 1, 4));\n\n    readConfig(config, \"outputfileStationPlatform\",  fileNameStationPlatform, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStationLog\",        fileNameStationLog,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileAntennaDefinition\", fileNameAntenna,         Config::OPTIONAL, \"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\", \"used to check antennas\");\n    if(isCreateSchema(config)) return;\n\n    // ==========================\n\n    logStatus<<\"read station log <\"<<fileNameStationLog<<\">\"<<Log::endl;\n    Platform platform = readFile(fileNameStationLog);\n\n    // ==========================\n\n    // some tests\n    // ----------\n    if((platform.markerName.size() != 4) && (platform.markerName.size() != 9))\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": marker name should have 4 or 9 letters\"));\n    if(platform.approxPosition.r() < 6300e3)\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": No approx. position given\"));\n    if(!std::any_of(platform.equipments.begin(), platform.equipments.end(), [](const auto &p) {return std::dynamic_pointer_cast<PlatformGnssReceiver>(p);}))\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": No receiver given\"));\n    if(!std::any_of(platform.equipments.begin(), platform.equipments.end(), [](const auto &p) {return std::dynamic_pointer_cast<PlatformGnssAntenna>(p);}))\n      throw(Exception(platform.markerName+\".\"+platform.markerNumber+\": No antenna given\"));\n\n    // ==========================\n\n    // test antennas\n    // -------------\n    if(!fileNameAntenna.empty())\n    {\n      logStatus<<\"read antenna definition file <\"<<fileNameAntenna<<\">\"<<Log::endl;\n      std::vector<GnssAntennaDefinitionPtr> antennaList;\n      readFileGnssAntennaDefinition(fileNameAntenna, antennaList);\n\n      platform.fillGnssAntennaDefinition(antennaList);\n      // test antennas\n      for(const auto &equipment : platform.equipments)\n      {\n        auto antenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(equipment);\n        if(antenna && !antenna->antennaDef)\n          logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\": no antenna definition found for \"<<antenna->str()<<Log::endl;\n      }\n    }\n\n    // ==========================\n\n    logStatus<<\"write station info <\"<<fileNameStationPlatform<<\">\"<<Log::endl;\n    writeFilePlatform(fileNameStationPlatform, platform);\n\n    // test platform\n    try\n    {\n      readFilePlatform(fileNameStationPlatform, platform);\n    }\n    catch(std::exception &/*e*/)\n    {\n      logWarning<<\"not readable: '\"<<fileNameStationPlatform<<\"'\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nPlatform GnssStationLog2Platform::readFile(const FileName &fileName)\n{\n  std::string line;\n\n  try\n  {\n    Platform  platform;\n    PlatformGnssReceiver receiver;\n    PlatformGnssAntenna  antenna;\n    PlatformEquipment    freqStandard;\n\n    InFile file(fileName);\n\n    enum Section {OTHER     = 999,\n                  SITE      = 1,\n                  LOCATION  = 2,\n                  RECEIVER  = 3,\n                  ANTENNA   = 4,\n                  FREQUENCY = 6};\n    Section section = OTHER;\n\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n      if(line[line.length()-1] == '\\r')\n        line.erase(line.length()-1);\n\n      UInt pos = line.find_first_not_of(\" \\t\\n\\r\");\n      if((pos == std::string::npos) || (pos > 30))\n        continue;\n      Char firstLetter = line.at(pos);\n\n      // section change?\n      // ---------------\n      if(line.at(0) == '1') // GNSS Receiver Information\n      {\n        section = SITE;\n      }\n      else if(line.at(0) == '2') // GNSS Receiver Information\n      {\n        section = LOCATION;\n      }\n      else if(line.at(0) == '3') // GNSS Receiver Information\n      {\n        section = RECEIVER;\n        newReceiver(platform, receiver);\n        receiver = PlatformGnssReceiver();\n      }\n      else if(line.at(0) == '4')  // GNSS Antenna Information\n      {\n        section = ANTENNA;\n        newAntenna(platform, antenna);\n        antenna = PlatformGnssAntenna();\n      }\n      else if(line.at(0) == '6')  // Frequency Standard\n      {\n        section = FREQUENCY;\n        newFreqStandard(platform, freqStandard);\n        freqStandard = PlatformEquipment();\n      }\n      else if(line.at(0) == '7')  // Stop with/after Collocation Information\n      {\n        break;\n      }\n      else if((line.at(0) != ' ') && (line.at(0) != '\\t')) // other section\n      {\n        section = OTHER;\n      }\n\n      // =================================================\n\n      // skip other sections\n      if(section == OTHER)\n        continue;\n\n      // =================================================\n\n      if(section == SITE)\n      {\n        if(String::contains(line, \"Site Identification of the GNSS Monument\"))\n        {\n        }\n        else if(String::contains(line, \"Four Character ID\") || String::contains(line, \"Nine Character ID\"))\n        {\n          if(platform.markerName.empty())\n          {\n            readString(line, platform.markerName);\n            std::transform(platform.markerName.begin(), platform.markerName.end(), platform.markerName.begin(), ::toupper);\n          }\n        }\n        else if(String::contains(line, \"IERS DOMES Number\"))\n        {\n          if(platform.markerNumber.empty())\n            readString(line, platform.markerNumber);\n        }\n/*        else\n          logInfo<<\"unknown line '\"<<line<<\"'\"<<Log::endl;*/\n      } // if(section == SITE)\n\n      // =================================================\n\n      if(section == LOCATION)\n      {\n        if(String::contains(line, \"Site Location Information\"))\n        {\n        }\n        else if(String::contains(line, \"City or Town\"))\n        {\n          readString(line, platform.comment);\n        }\n        else if(String::contains(line, \"Country\"))\n        {\n          std::string country;\n          readString(line, country);\n          platform.comment += \", \" + country;\n        }\n        else if(String::contains(line, \"X coordinate\"))\n        {\n          readDouble(line, platform.approxPosition.x());\n        }\n        else if(String::contains(line, \"Y coordinate\"))\n        {\n          readDouble(line, platform.approxPosition.y());\n        }\n        else if(String::contains(line, \"Z coordinate\"))\n        {\n          readDouble(line, platform.approxPosition.z());\n        }\n        else if(platform.approxPosition.r() < 6300e3 && String::contains(line, \"Latitude\"))\n        {\n          readDouble(line, platform.approxPosition.x());\n        }\n        else if(platform.approxPosition.r() < 6300e3 && String::contains(line, \"Longitude\"))\n        {\n          readDouble(line, platform.approxPosition.y());\n        }\n        else if(platform.approxPosition.r() < 6300e3 && String::contains(line, \"Elevation\"))\n        {\n          readDouble(line, platform.approxPosition.z());\n        }\n/*        else\n          logInfo<<\"unknown line '\"<<line<<\"'\"<<Log::endl;*/\n      } // if(section == LOCATION)\n\n      // =================================================\n\n      if(section == RECEIVER)\n      {\n        if((String::contains(line, \"Additional Information\")) || (firstLetter==':'))\n        {\n//           std::string comment;\n//           readString(line, comment);\n//           receiver.comment += comment;\n        }\n        else if(String::contains(line, \"GNSS Receiver Information\"))\n        {\n        }\n        else if(String::contains(line, \"Receiver Type\"))\n        {\n          readString(line, receiver.name);\n          if((receiver.name != \"ASHTECH Z-XII3T\") && String::contains(receiver.name, \"ASHTECH\") && String::contains(receiver.name, \"Z-XII\"))\n            receiver.name = \"ASHTECH Z-XII3\";\n        }\n        else if(String::contains(line, \"Satellite System\"))\n        {\n        }\n        else if(String::contains(line, \"Serial Number\"))\n        {\n          readString(line, receiver.serial);\n        }\n        else if(String::contains(line, \"Firmware Version\"))\n        {\n          readString(line, receiver.version);\n        }\n        else if(String::contains(line, \"Elevation Cutoff\"))\n        {\n        }\n        else if(String::contains(line, \"Date Installed\"))\n        {\n          readTime(line, receiver.timeStart);\n        }\n        else if(String::contains(line, \"Date Removed\"))\n        {\n          readTime(line, receiver.timeEnd);\n        }\n        else if(String::contains(line, \"Temperature Stabiliz\"))\n        {\n        }\n//         else\n//           logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" unknown line in GNSS Receiver Information section '\"<<line<<\"'\"<<Log::endl;\n      } // if(section == RECEIVER)\n\n      // =================================================\n\n      if(section == ANTENNA)\n      {\n        if((String::contains(line, \"Additional Information\")) || (firstLetter==':'))\n        {\n//           std::string comment;\n//           readString(line, comment);\n//           antenna.comment += comment;\n        }\n        else if(String::contains(line, \"GNSS Antenna Information\"))\n        {\n        }\n        else if(String::contains(line, \"Antenna Type\"))\n        {\n          std::string text;\n          readString(line, text);\n          text = String::upperCase(text);\n          if(text.size() == 20) // with radome?\n          {\n            antenna.radome = text.substr(16, 4);\n            if(antenna.radome == \"NONE\")\n              antenna.radome.clear();\n          }\n          // if(text.substr(0, 8) == \"TRIMBLE \")\n          //   text = text.substr(8);\n          if(text == \"DORNE MARGOLIN T\")\n            text = \"AOAD/M_T\";\n          text = String::trim(text.substr(0, 15));\n          antenna.name = text;\n        }\n        else if(String::contains(line, \"Radome Serial Number\"))\n        {\n        }\n        else if(String::contains(line, \"Serial Number\"))\n        {\n          readString(line, antenna.serial);\n          antenna.serial = String::upperCase(antenna.serial).substr(0, 5);\n          if((antenna.serial==\"n/a\")||(antenna.serial==\"N/A\"))\n            antenna.serial.clear();\n        }\n        else if(String::contains(line, \"Antenna Reference Point\"))\n        {\n        }\n        else if(String::contains(line, \"Marker->ARP Up\"))\n        {\n          readDouble(line, antenna.position.z());\n        }\n        else if(String::contains(line, \"Marker->ARP East\"))\n        {\n          readDouble(line, antenna.position.y());\n        }\n        else if(String::contains(line, \"Marker->ARP North\"))\n        {\n          readDouble(line, antenna.position.x());\n        }\n        else if(String::contains(line, \"Alignment from True N\") || String::contains(line, \"Degree Offset from North\") /*old format*/)\n        {\n          Double deg;\n          if(readDouble(line, deg) && (deg!=0))\n            antenna.local2antennaFrame = rotaryZ(Angle(deg*DEG2RAD));\n        }\n        else if(String::contains(line, \"Antenna Radome Type\"))\n        {\n          std::string text;\n          readString(line, text);\n          if((!antenna.radome.empty()) && (text != antenna.radome))\n            logWarning<<\"Radome different: \"<<antenna.radome<<\" != \"<<text<<Log::endl;\n          antenna.radome = text;\n          std::transform(antenna.radome.begin(), antenna.radome.end(), antenna.radome.begin(), ::toupper);\n          if(antenna.radome == \"NONE\")\n            antenna.radome.clear();\n        }\n        else if(String::contains(line, \"Antenna Cable Type\"))\n        {\n        }\n        else if(String::contains(line, \"Antenna Cable Length\"))\n        {\n        }\n        else if(String::contains(line, \"Date Installed\"))\n        {\n          readTime(line, antenna.timeStart);\n        }\n        else if(String::contains(line, \"Date Removed\"))\n        {\n          readTime(line, antenna.timeEnd);\n        }\n        else if(String::contains(line, \"Antenna Height\")) // old format\n        {\n          readDouble(line, antenna.position.z());\n        }\n//         else\n//           logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" unknown line in GNSS Antenna Information section '\"<<line<<\"'\"<<Log::endl;\n      } // if(section == ANTENNA)\n\n      // =================================================\n\n      if(section == FREQUENCY)\n      {\n        if((String::contains(line, \"Notes\")) || (firstLetter==':'))\n        {\n        }\n        else if(String::contains(line, \"Standard Type\"))\n        {\n          std::string text;\n          readString(line, text);\n          text = String::upperCase(text);\n          if(String::contains(text, \"H-MASER\") || String::contains(text, \"HYDROGEN\"))\n            freqStandard.name = \"H-MASER\";\n        }\n        else if(String::contains(line, \"Input Frequency\"))\n        {\n        }\n        else if(String::contains(line, \"Effective Dates\"))\n        {\n          readEffectiveDate(line, freqStandard.timeStart, freqStandard.timeEnd);\n        }\n      } // if(section == FREQUENCY)\n\n    } // for(;;)\n\n    // if no Cartesian coordinates are given, try to use ellipsoidal coordinates\n    if(platform.approxPosition.r() > 0 && platform.approxPosition.r() < 6300e3)\n    {\n      Ellipsoid ellipsoid;\n      platform.approxPosition = ellipsoid(Angle(platform.approxPosition.y()*DEG2RAD), Angle(platform.approxPosition.x()*DEG2RAD), platform.approxPosition.z());\n    }\n\n    // insert last receiver/antenna/freqStandard\n    // -----------------------------------------\n    newReceiver(platform, receiver);\n    newAntenna(platform, antenna);\n    newFreqStandard(platform, freqStandard);\n\n    return platform;\n  }\n  catch(std::exception &e)\n  {\n    logError<<\"error: '\"<<line<<\"'\"<<Log::endl;\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssStationLog2Platform::newReceiver(Platform &platform, PlatformGnssReceiver &receiver) const\n{\n  try\n  {\n    if(receiver.name.empty() || receiver.name == \"no receiver\")\n      return;\n\n    if(receiver.timeStart == Time())\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" receiver timeStart not given\"<<Log::endl;\n\n    if(receiver.timeEnd == Time())\n      receiver.timeEnd = date2time(2500,1,1);\n    if(receiver.timeStart == receiver.timeEnd)\n      return;\n    if(receiver.timeStart >= receiver.timeEnd)\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\": receiver time error (new receiver start: \"\n                <<receiver.timeStart.dateTimeStr()<<\", new receiver end: \"<<receiver.timeEnd.dateTimeStr()<<\")\"<<Log::endl;\n\n    // find last receiver\n    auto iter = std::find_if(platform.equipments.rbegin(), platform.equipments.rend(),\n                             [](const auto x) {return x->getType() == PlatformEquipment::GNSSRECEIVER;});\n    if(iter == platform.equipments.rend())\n    {\n      platform.equipments.push_back(std::make_shared<PlatformGnssReceiver>(receiver));\n      return;\n    }\n    std::shared_ptr<PlatformGnssReceiver> lastReceiver = std::dynamic_pointer_cast<PlatformGnssReceiver>(*iter);\n\n    if((lastReceiver->name    == receiver.name)   &&\n       (lastReceiver->serial  == receiver.serial) &&\n       (lastReceiver->version == receiver.version))\n    {\n      lastReceiver->timeEnd = receiver.timeEnd;\n      return;\n    }\n\n    // test times\n    if(lastReceiver->timeEnd == date2time(2500,1,1))\n      lastReceiver->timeEnd = receiver.timeStart;\n\n    if(lastReceiver->timeEnd > receiver.timeStart)\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" receiver time error (previous receiver end: \"\n                <<lastReceiver->timeEnd.dateTimeStr()<<\", new receiver start: \"<<receiver.timeStart.dateTimeStr()<<\")\"<<Log::endl;\n\n    platform.equipments.push_back(std::make_shared<PlatformGnssReceiver>(receiver));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssStationLog2Platform::newAntenna(Platform &platform, PlatformGnssAntenna &antenna) const\n{\n  try\n  {\n    if(antenna.name.empty() || antenna.name == \"no antenna\")\n      return;\n\n    if(antenna.timeStart == Time())\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" antenna timeStart not given\"<<Log::endl;\n\n    if(antenna.timeEnd == Time())\n      antenna.timeEnd = date2time(2500,1,1);\n    if(antenna.timeStart == antenna.timeEnd)\n      return;\n    if(antenna.timeStart >= antenna.timeEnd)\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\": antenna time error (new antenna start: \"\n                <<antenna.timeStart.dateTimeStr()<<\", new antenna end: \"<<antenna.timeEnd.dateTimeStr()<<\")\"<<Log::endl;\n\n    // find last antenna\n    auto iter = std::find_if(platform.equipments.rbegin(), platform.equipments.rend(),\n                             [](const auto x) {return x->getType() == PlatformEquipment::GNSSANTENNA;});\n    if(iter == platform.equipments.rend())\n    {\n      platform.equipments.push_back(std::make_shared<PlatformGnssAntenna>(antenna));\n      return;\n    }\n    auto lastAntenna = std::dynamic_pointer_cast<PlatformGnssAntenna>(*iter);\n\n    if((lastAntenna->name    == antenna.name)   &&\n       (lastAntenna->serial  == antenna.serial) &&\n       (lastAntenna->radome  == antenna.radome) &&\n       ((lastAntenna->position-antenna.position).r() < 0.0001) &&\n      quadsum(lastAntenna->local2antennaFrame.matrix() - antenna.local2antennaFrame.matrix()) < 0.0001)\n    {\n      lastAntenna->timeEnd = antenna.timeEnd;\n      return;\n    }\n\n    // test times\n    if(lastAntenna->timeEnd == date2time(2500,1,1))\n      lastAntenna->timeEnd = antenna.timeStart;\n\n    if(lastAntenna->timeEnd > antenna.timeStart)\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" antenna time error (previous antenna end: \"\n                <<lastAntenna->timeEnd.dateTimeStr()<<\", new antenna start: \"<<antenna.timeStart.dateTimeStr()<<\")\"<<Log::endl;\n\n    platform.equipments.push_back(std::make_shared<PlatformGnssAntenna>(antenna));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssStationLog2Platform::newFreqStandard(Platform &platform, PlatformEquipment &freqStandard) const\n{\n  try\n  {\n    if(freqStandard.name.empty())\n      return;\n\n    if(freqStandard.timeEnd == Time())\n      freqStandard.timeEnd = date2time(2500,1,1);\n    else\n      freqStandard.timeEnd += mjd2time(1);\n    if(freqStandard.timeStart == freqStandard.timeEnd)\n      return;\n    if(freqStandard.timeStart >= freqStandard.timeEnd)\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\": freqStandard time error (new freqStandard start: \"\n                <<freqStandard.timeStart.dateTimeStr()<<\", new freqStandard end: \"<<freqStandard.timeEnd.dateTimeStr()<<\")\"<<Log::endl;\n\n    // find last freqStandard\n    auto iter = std::find_if(platform.equipments.rbegin(), platform.equipments.rend(),\n                             [](const auto x) {return x->getType() == PlatformEquipment::OTHER;});\n    if(iter == platform.equipments.rend())\n    {\n      platform.equipments.push_back(std::make_shared<PlatformEquipment>(freqStandard));\n      return;\n    }\n    auto lastFreqStandard = std::dynamic_pointer_cast<PlatformEquipment>(*iter);\n\n    if((lastFreqStandard->name == freqStandard.name) && (lastFreqStandard->serial == freqStandard.serial))\n    {\n      lastFreqStandard->timeEnd = freqStandard.timeEnd;\n      return;\n    }\n\n    // test times\n    if(lastFreqStandard->timeEnd == date2time(2500,1,1))\n      lastFreqStandard->timeEnd = freqStandard.timeStart;\n\n    if(lastFreqStandard->timeEnd > freqStandard.timeStart)\n      logWarning<<platform.markerName<<\".\"<<platform.markerNumber<<\" freqStandard time error (previous freqStandard end: \"\n                <<lastFreqStandard->timeEnd.dateTimeStr()<<\", new freqStandard start: \"<<freqStandard.timeStart.dateTimeStr()<<\")\"<<Log::endl;\n\n    platform.equipments.push_back(std::make_shared<PlatformEquipment>(freqStandard));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssStationLog2Platform::readDouble(const std::string &line, Double &x) const\n{\n  try\n  {\n    UInt pos = line.find(\":\");\n    if(pos == std::string::npos)\n      throw(Exception(\"':' expected\"));\n    std::string text = line.substr(pos+1);\n    std::stringstream ss(text);\n    Double f = 0;\n    ss>>f;\n    if((!ss.good())&&(!ss.eof()))\n      return FALSE;\n    x = f;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssStationLog2Platform::readString(const std::string &line, std::string &x) const\n{\n  try\n  {\n    UInt pos = line.find(\":\");\n    if(pos == std::string::npos)\n      throw(Exception(\"':' expected\"));\n    std::string text = String::trim(line.substr(pos+1));\n    if(text.empty() || String::startsWith(text, \"(\"))\n      return FALSE;\n    x = text;\n    std::replace_if(x.begin(), x.end(), [](char c){ return c < 0; }, '?'); // replace non ASCII characters\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool GnssStationLog2Platform::readTime(const std::string &line, Time &x) const\n{\n  try\n  {\n    UInt pos = line.find(\":\");\n    if(pos == std::string::npos)\n      throw(Exception(\"':' expected\"));\n    std::string text = String::trim(line.substr(pos+1));\n    if(text.empty() || String::startsWith(text, \"(\"))\n      return FALSE;\n    std::stringstream ss(text);\n\n    UInt year, month, day;\n    UInt hour = 0, min = 0;\n    char c;\n    ss>>year;\n\n    if(year < 1950) // old date style: 02-OCT-2000 00:00 UT\n    {\n      day = year;\n      if((!ss.good())&&(!ss.eof()))\n        return FALSE;\n      ss>>c; if(c!='-') return FALSE;\n      char tmp[3];\n      ss.read(tmp,3);\n      std::string monthName(tmp,3);\n      std::transform(monthName.begin(), monthName.end(), monthName.begin(), ::toupper);\n      const std::vector<std::string> months = {\"JAN\", \"FEB\", \"MAR\", \"APR\", \"MAY\", \"JUN\", \"JUL\", \"AUG\", \"SEP\", \"OCT\", \"NOV\", \"DEC\"};\n      auto pos = std::find(months.begin(), months.end(), monthName);\n      if(pos == months.end())\n        return FALSE;\n      month = std::distance(months.begin(), pos)+1;\n      ss>>c; if(c!='-') return FALSE;\n      ss>>year;\n      if((!ss.good())&&(!ss.eof()))\n        return FALSE;\n      ss>>hour>>c>>min;  // ignore problems when reading the clock\n    }\n    else // new date style: 2015-01-28T00:00Z\n    {\n      if((!ss.good())&&(!ss.eof()))\n        return FALSE;\n      ss>>c; if(c!='-') return FALSE;\n      ss>>month;\n      if((!ss.good())&&(!ss.eof()))\n        return FALSE;\n      ss>>c; if(c!='-') return FALSE;\n      ss>>day;\n      if((!ss.good())&&(!ss.eof()))\n        return FALSE;\n      ss>>c;\n      if(c=='T')\n        ss>>hour>>c>>min; // ignore problems when reading the clock\n    }\n\n    x = date2time(year, month, day, hour, min, 0);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    return FALSE;\n  }\n}\n\n/***********************************************/\n\nBool GnssStationLog2Platform::readEffectiveDate(const std::string &line, Time &xStart, Time &xEnd) const\n{\n  try\n  {\n    UInt pos = line.find(\":\");\n    if(pos == std::string::npos)\n      throw(Exception(\"':' expected\"));\n    std::string text = String::trim(line.substr(pos+1));\n    if(text.empty() || String::startsWith(text, \"(\"))\n      return FALSE;\n    std::stringstream ss(text);\n\n    UInt year, month, day;\n    char c;\n    ss>>year;\n    if((!ss.good())&&(!ss.eof()))\n      return FALSE;\n    ss>>c; if(c!='-') return FALSE;\n    ss>>month;\n    if((!ss.good())&&(!ss.eof()))\n      return FALSE;\n    ss>>c; if(c!='-') return FALSE;\n    ss>>day;\n    if((!ss.good())&&(!ss.eof()))\n      return FALSE;\n    xStart = date2time(year, month, day);\n\n    ss>>c; if(c!='/') return TRUE;\n    ss>>year>>c>>month>>c>>day;\n    if((!ss.good())&&(!ss.eof()))\n      return TRUE;\n    xEnd = date2time(year, month, day);\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    return FALSE;\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/gnssTroposphere2TropoSinex.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssTroposphere2TropoSinex.cpp\n*\n* @brief Convert GNSS troposphere data from GROOPS format to IGS SINEX_TRO format.\n*\n* @author Barbara Suesser-Rechberger\n* @author Sebastian Strasser\n* @date 2019-05-29\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert GNSS troposphere data from GROOPS format as estimated by \\program{GnssProcessing}\nto \\href{https://files.igs.org/pub/data/format/sinex_tro_v2.00.pdf}{IGS SINEX TRO} format.\n\nFor each station folling files are needed:\n\\begin{itemize}\n  \\item \\configFile{inputfileStationInfo}{platform},\n  \\item \\configFile{inputfileTroposphereData}{instrument}(MISVALUES),\n  \\item optional standard deviations with \\configFile{inputfileTroposphereSigmas}{instrument}(MISVALUES),\n  \\item \\configFile{inputfilePosition}{instrument}(VECTOR3D).\n\\end{itemize}\nThe \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition} contains antenna center offsets and variations\nof all used antennas. Created via \\program{GnssAntex2AntennaDefinition} or \\program{GnssAntennaDefinitionCreate}.\n\nFor considering the geoid height use \\configFile{inputfileGriddedGeoidHeight}{griddedData}\nas it might be computed by \\program{Gravityfield2GriddedData}.\nThe height closest to the station's position is used in each case.\n\nSee also \\program{GnssProcessing}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileInstrument.h\"\n#include \"inputOutput/system.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileStringTable.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert GNSS troposphere data from GROOPS format to IGS SINEX_TRO format.\n* @ingroup programsConversionGroup */\nclass GnssTroposphere2TropoSinex\n{\n  static std::string resize(std::string str, UInt length) {str.resize(length, ' '); return str;}\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  class Station\n  {\n  public:\n    FileName      fileNameTropoData, fileNameTropoSigmas, fileNameStationInfo, fileNamePosition;\n    Time          timesMid;\n    Platform      platform;\n    Vector3d      position;\n    Double        geoidHeight;\n    MiscValuesArc tropData, tropSigmas;\n  };\n};\n\nGROOPS_REGISTER_PROGRAM(GnssTroposphere2TropoSinex, SINGLEPROCESS, \"Convert GNSS troposphere data from GROOPS format to SINEX_TRO format.\", Conversion, Gnss)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssTroposphere2TropoSinex::Station &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileStationInfo\",       var.fileNameStationInfo, Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/stationInfo/stationInfo.{station}.xml\", \"platform file\");\n  readConfig(config, \"inputfileTroposphereData\",   var.fileNameTropoData,   Config::MUSTSET,  \"\", \"Troposphere data estimates (columns: mjd, trodry, trowet, tgndry, tgnwet, tgedry, tgewet)\");\n  readConfig(config, \"inputfileTroposphereSigmas\", var.fileNameTropoSigmas, Config::OPTIONAL, \"\", \"Troposphere data sigmas (columns: mjd, sigma_trowet, sigma_tgnwet, sigma_tgewet)\");\n  readConfig(config, \"inputfilePosition\",          var.fileNamePosition,    Config::OPTIONAL, \"\", \"Precise station position (columns: mjd, x, y, z [m in TRF])\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssTroposphere2TropoSinex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName             fileNameTropoSinex;\n    std::vector<Station> stations;\n    FileName             fileNameAntennaDef, fileNameGeoidHeight;\n    std::string          agencyCode, observationCode, solutionContents, gnssSystems, timeSystem, tropoModelingMethod, oceanTideModel, atmosphericTideModel, geoidModel, metDataSource, observationWeighting;\n    std::string          description, output, contact, software, hardware, input, versionNumber, systemCode, remark, antennaModel, aPrioriTropoModel, tropoMappingFunction, gradientMappingFunction;\n    Time                 timeStart, timeEnd;\n    std::vector<std::string> comment;\n    FileName             fileNameComment;\n    Double               troSampling=NAN_EXPR, dataSampling=NAN_EXPR, elevationCutoff=NAN_EXPR;\n\n    readConfig(config, \"outputfileTropoSinex\",        fileNameTropoSinex,      Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"station\",                     stations,                Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileAntennaDefinition\",  fileNameAntennaDef,      Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/antennaDefinition/igs/igs20/antennaDefinition_igs20.dat\", \"station phase centers and variations\");\n    readConfig(config, \"inputfileGriddedGeoidHeight\", fileNameGeoidHeight,     Config::OPTIONAL, \"\",    \"value closest to the station's position is used in each case\");\n    readConfig(config, \"dataSamplingInterval\",        dataSampling,            Config::OPTIONAL, \"\",    \"[sec] GNSS data sampling rate\");\n    readConfig(config, \"tropoSamplingInterval\",       troSampling,             Config::OPTIONAL, \"\",    \"[sec] Tropospheric parameter sampling interval\");\n    readConfig(config, \"tropoModelingMethod\",         tropoModelingMethod,     Config::OPTIONAL, \"Least Squares\", \"Tropospheric estimation method: Filter, Smoother, Least Squares, Piece-Wise Linear Interpolation\");\n    readConfig(config, \"aPrioriTropoModel\",           aPrioriTropoModel,       Config::OPTIONAL, \"VMF3 Operational 1x1° gridded + gradients (V3GR)\", \"A priori tropospheric model used\");\n    readConfig(config, \"tropoMappingFunction\",        tropoMappingFunction,    Config::OPTIONAL, \"Vienna Mapping Functions 3 (VMF3)\", \"Name of mapping function used for hydrostatic and wet delay\");\n    readConfig(config, \"gradientMappingFunction\",     gradientMappingFunction, Config::OPTIONAL, \"Chen & Herring (1997), C_dry=0.0031, C_wet=0.0007\", \"Name of mapping function used for gradients\");\n    readConfig(config, \"metDataSource\",               metDataSource,           Config::OPTIONAL, \"\",    \"source of surface meteorological observations used (see format desc.)\");\n    readConfig(config, \"observationWeighting\",        observationWeighting,    Config::OPTIONAL, \"\",    \"observation weighting model applied\");\n    readConfig(config, \"elevationCutoff\",             elevationCutoff,         Config::OPTIONAL, \"5\",   \"[deg]\");\n    readConfig(config, \"gnssSystems\",                 gnssSystems,             Config::OPTIONAL, \"\",    \"G=GPS, R=GLONASS, E=Galileo, C=BeiDou\");\n    readConfig(config, \"timeSystem\",                  timeSystem,              Config::OPTIONAL, \"G\",   \"G (GPS) or UTC\");\n    readConfig(config, \"oceanTideModel\",              oceanTideModel,          Config::OPTIONAL, \"\",    \"Name of applied Ocean tide loading model\");\n    readConfig(config, \"atmosphericTideModel\",        atmosphericTideModel,    Config::OPTIONAL, \"\",    \"Name of applied Atmospheric tide loading model\");\n    readConfig(config, \"geoidModel\",                  geoidModel,              Config::OPTIONAL, \"\",    \"Geoid model name for undulation values\");\n    readConfig(config, \"systemCode\",                  systemCode,              Config::OPTIONAL, \"\",    \"Terrestrial reference system code\");\n    readConfig(config, \"remark\",                      remark,                  Config::OPTIONAL, \"TUG\", \"Remark used to identify the origin of the coordinates (AC acronym)\");\n    readConfig(config, \"antennaCalibrationModel\",     antennaModel,            Config::OPTIONAL, \"\",    \"e.g. IGS20_WWWW (WWWW = ANTEX release GPS week)\");\n    if(readConfigSequence(config, \"sinexTroHeader\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"agencyCode\",       agencyCode,       Config::OPTIONAL, \"TUG\", \"Identify the agency providing the data\");\n      readConfig(config, \"timeStart\",        timeStart,        Config::OPTIONAL, \"\",    \"Start time of the data\");\n      readConfig(config, \"timeEnd\",          timeEnd,          Config::OPTIONAL, \"\",    \"End time of the data \");\n      readConfig(config, \"observationCode\",  observationCode,  Config::OPTIONAL, \"P\",   \"Technique used to generate the SINEX solution\");\n      readConfig(config, \"solutionContents\", solutionContents, Config::OPTIONAL, \"MIX\", \"Marker name if single station, MIX if multiple stations\");\n      readConfig(config, \"description\",      description,      Config::OPTIONAL, \"\",    \"Organizitions gathering/alerting the file contents\");\n      readConfig(config, \"output\",           output,           Config::OPTIONAL, \"\",    \"Description of the file contents\");\n      readConfig(config, \"contact\",          contact,          Config::OPTIONAL, \"\",    \"Address of the relevant contact e-mail\");\n      readConfig(config, \"software\",         software,         Config::OPTIONAL, \"GROOPS (https://github.com/groops-devs/groops)\", \"Software used to generate the file\");\n      readConfig(config, \"hardware\",         hardware,         Config::OPTIONAL, \"\",    \"Computer hardware on which above software was run\");\n      readConfig(config, \"input\",            input,            Config::OPTIONAL, \"\",    \"Brief description of the input used to generate this solution\");\n      readConfig(config, \"versionNumber\",    versionNumber,    Config::OPTIONAL, \"\",    \"Unique identifier of the product, same as in file name, e.g. 000\");\n      readConfig(config, \"inputfileComment\", fileNameComment,  Config::OPTIONAL, \"\",    \"comments in the comment block from a file (truncated at 80 characters per line)\");\n      readConfig(config, \"comment\",          comment,          Config::OPTIONAL, \"\",    \"comments in the comment block\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // ==================================================\n\n    logStatus<<\"reading station antenna definitions from <\"<<fileNameAntennaDef<<\">\"<<Log::endl;\n    std::vector<GnssAntennaDefinitionPtr> antennaDefinitionList;\n    readFileGnssAntennaDefinition(fileNameAntennaDef, antennaDefinitionList);\n\n    GriddedData gridGeoid;\n    if(!fileNameGeoidHeight.empty())\n    {\n      logStatus<<\"reading geoid heights <\"<<fileNameGeoidHeight<<\">\"<<Log::endl;\n      readFileGriddedData(fileNameGeoidHeight, gridGeoid);\n    }\n\n    logStatus<<\"reading station infos\"<<Log::endl;\n    for(auto &station : stations)\n    {\n      station.tropData   = InstrumentFile::read(station.fileNameTropoData);\n      station.tropSigmas = InstrumentFile::read(station.fileNameTropoSigmas);\n      Arc::checkSynchronized({station.tropData, station.tropSigmas});\n      station.timesMid = 0.5*(station.tropData.front().time+station.tropData.back().time);\n\n      readFilePlatform(station.fileNameStationInfo, station.platform);\n      station.platform.fillGnssAntennaDefinition(antennaDefinitionList);\n\n      // position\n      station.position = station.platform.approxPosition;\n      if(!station.fileNamePosition.empty())\n      {\n        Vector3dArc arc = InstrumentFile::read(station.fileNamePosition);\n        auto iter = std::min_element(arc.begin(), arc.end(), [&](const Epoch &e1, const Epoch &e2)\n                                    {return std::fabs((e1.time-station.timesMid).mjd()) < std::fabs((e2.time-station.timesMid).mjd());});\n        if(!arc.size() || ((arc.size() > 1) && (std::fabs((iter->time-station.timesMid).mjd()) > 0.5*medianSampling(arc.times()).mjd())))\n          throw(Exception(\"No position found in <\"+station.fileNamePosition.str()+\">\"));\n        station.position = iter->vector3d;\n      }\n\n      // find nearest geoid height\n      station.geoidHeight = NAN_EXPR;\n      if(gridGeoid.points.size() && gridGeoid.values.size())\n      {\n        auto iter = std::min_element(gridGeoid.points.begin(), gridGeoid.points.end(), [&](const Vector3d &p1, const Vector3d &p2)\n                                     {return (p1-station.position).quadsum() < (p2-station.position).quadsum();});\n        station.geoidHeight = gridGeoid.values.front().at(std::distance(gridGeoid.points.begin(), iter));\n      }\n    }\n\n    // ==================================================\n\n    // write SINEX_TRO file\n    // ----------------\n    logStatus<<\"write SINEX_TRO file <\"<<fileNameTropoSinex<<\">\"<<Log::endl;\n    Sinex sinex;\n    // SINEX_TRO header line\n    std::stringstream ss;\n    ss<<\"%=TRO 2.00 \"<<std::setw(3)<<agencyCode.substr(0, 3)<<\" \"<<Sinex::time2str(System::now(), TRUE)<<\" \"<<std::setw(3)<<agencyCode.substr(0, 3);\n    ss<<\" \"<<Sinex::time2str(timeStart, TRUE)<<\" \"<<Sinex::time2str(timeEnd, TRUE)<<\" \"<<std::setw(1)<<observationCode.substr(0, 1);\n    ss<<\" \"<<solutionContents.substr(0, 4);\n    sinex.header = ss.str();\n    sinex.footer = \"%=ENDTRO\";\n\n    std::vector<std::string> columns = {\"TROTOT\", \"TGNTOT\", \"TGETOT\"};\n    if(std::any_of(stations.begin(), stations.end(), [](auto &station) {return station.tropSigmas.size();}))\n      columns = {\"TROTOT\", \"STDDEV\", \"TGNTOT\", \"STDDEV\", \"TGETOT\", \"STDDEV\"};\n\n    // Block: FILE/REFERENCE\n    {\n      SinexBlockPtr block = sinex.addBlock(\"FILE/REFERENCE\");\n      *block<<\"*INFO_TYPE_________ INFO________________________________________________________\"<<std::endl;\n      if(!description.empty())   *block<<\" DESCRIPTION        \"<<description<<std::endl;\n      if(!output.empty())        *block<<\" OUTPUT             \"<<output<<std::endl;\n      if(!contact.empty())       *block<<\" CONTACT            \"<<contact<<std::endl;\n      if(!software.empty())      *block<<\" SOFTWARE           \"<<software<<std::endl;\n      if(!hardware.empty())      *block<<\" HARDWARE           \"<<hardware<<std::endl;\n      if(!input.empty())         *block<<\" INPUT              \"<<input<<std::endl;\n      if(!versionNumber.empty()) *block<<\" VERSION NUMBER     \"<<versionNumber<<std::endl;\n    }\n\n    // Block: TROP/DESCRIPTION\n    {\n      SinexBlockPtr block = sinex.addBlock(\"TROP/DESCRIPTION\");\n      *block<<\"*_________KEYWORD____________ ___VALUES(S)______________________________________\"<<std::endl;\n      *block<<\" TROPO PARAMETER NAMES       \"; for(const auto &c : columns)         {*block<<\" \"<<c;}    *block<<std::endl;\n      *block<<\" TROPO PARAMETER UNITS       \"; for(UInt i=0; i<columns.size(); i++) {*block<<\"  1e+03\";} *block<<std::endl;\n      *block<<\" TROPO PARAMETER WIDTH       \"; for(UInt i=0; i<columns.size(); i++) {*block<<\"      6\";} *block<<std::endl;\n      if(!tropoModelingMethod.empty())     *block<<\" TROPO MODELING METHOD        \"<<tropoModelingMethod<<std::endl;\n      if(!std::isnan(troSampling))         *block<<\" TROPO SAMPLING INTERVAL      \"<<troSampling%\"%f\"s<<std::endl;\n      if(!metDataSource.empty())           *block<<\" SOURCE OF MET/DATA           \"<<metDataSource<<std::endl;\n      if(!aPrioriTropoModel.empty())       *block<<\" A PRIORI TROPOSPHERE         \"<<aPrioriTropoModel<<std::endl;\n      if(!tropoMappingFunction.empty())    *block<<\" TROPO MAPPING FUNCTION       \"<<tropoMappingFunction<<std::endl;\n      if(!gradientMappingFunction.empty()) *block<<\" GRADS MAPPING FUNCTION       \"<<gradientMappingFunction<<std::endl;\n      if(!std::isnan(dataSampling))        *block<<\" DATA SAMPLING INTERVAL       \"<<dataSampling%\"%f\"s<<std::endl;\n      if(!std::isnan(elevationCutoff))     *block<<\" ELEVATION CUTOFF ANGLE       \"<<elevationCutoff%\"%f\"s<<std::endl;\n      if(!observationWeighting.empty())    *block<<\" OBSERVATION WEIGHTING        \"<<observationWeighting<<std::endl;\n      if(!gnssSystems.empty())             *block<<\" GNSS SYSTEMS                 \"<<gnssSystems<<std::endl;\n      if(!aPrioriTropoModel.empty())       *block<<\" TIME SYSTEM                  \"<<timeSystem<<std::endl;\n      if(!timeSystem.empty())              *block<<\" OCEAN TIDE LOADING MODEL     \"<<oceanTideModel<<std::endl;\n      if(!atmosphericTideModel.empty())    *block<<\" ATMOSPH TIDE LOADING MODEL   \"<<atmosphericTideModel<<std::endl;\n      if(!geoidModel.empty())              *block<<\" GEOID MODEL                  \"<<geoidModel<<std::endl;\n    }\n\n    // Block: FILE/COMMENT\n    if(comment.size() || !fileNameComment.empty())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ID\");\n      if(!fileNameComment.empty())\n      {\n        InFile commentFile(fileNameComment);\n        std::string line;\n        while(std::getline(commentFile, line))\n          *block<<\" \"<<line<<std::endl;\n      }\n      for(const auto &line : comment)\n        *block<<\" \"<<line<<std::endl;\n    }\n\n    // Block: SITE/ID\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ID\");\n      *block<<\"*STATION__ PT __DOMES__ T _STATION_DESCRIPTION__ _LONGITUDE _LATITUDE_ _HGT_ELI_ _HGT_MSL_\"<<std::endl;\n      Ellipsoid ellipsoid;\n      for(const auto &station : stations)\n      {\n        Angle lon, lat;\n        Double ellipsoidHeight;\n        ellipsoid(station.position, lon, lat, ellipsoidHeight);\n        *block<<\" \"<<String::upperCase(resize(station.platform.markerName, 9))<<\"  A \"<<resize(station.platform.markerNumber, 9)<<\" P \"<<resize(station.platform.comment, 22)<<\" \"\n              <<(std::fmod(lon+2*PI, 2*PI)*RAD2DEG)%\"%10.6f \"s<<(lat*RAD2DEG)%\"%10.6f \"s<<ellipsoidHeight%\"%9.3f \"s<<(std::isnan(station.geoidHeight) ? \"\" : station.geoidHeight % \"%9.3f\"s)<<std::endl;\n      }\n    }\n\n    // Block: SITE/COORDINATES\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/COORDINATES\");\n      *block<<\"*STATION__ PT SOLN T __DATA_START__ __DATA_END____ __STA_X_____  __STA_Y_____  __STA_Z_____ SYSTEM REMRK\"<<std::endl;\n      for(const auto &station : stations)\n      {\n        *block<<\" \"<<String::upperCase(resize(station.platform.markerName, 9))<<\"  A    1 P \"<<Sinex::time2str(timeStart, TRUE)<<\" \"<<Sinex::time2str(timeEnd, TRUE)<<\" \"<<station.position.x() % \"%12.3f \"s;\n        *block<<\" \"<<station.position.y()%\"%12.3f \"s<<\" \"<<station.position.z()%\"%12.3f \"s<<resize(systemCode, 6)<<\" \"<<resize(remark, 5)<<std::endl;\n      }\n    }\n\n    // BLOCK: SITE/RECEIVER\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/RECEIVER\");\n      *block<<\"*STATION__ PT SOLN T __DATA_START__ __DATA_END____ DESCRIPTION_________ S/N_________________ FIRMW______\"<<std::endl;\n      for(const auto &station : stations)\n      {\n        auto recv = station.platform.findEquipment<PlatformGnssReceiver>(station.timesMid);\n        if(!recv)\n        {\n          logWarning<<station.platform.markerName<<\": no receiver found at \"<<station.timesMid.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<String::upperCase(resize(station.platform.markerName, 9))<<\"  A    1 P \"<<Sinex::time2str(recv->timeStart, TRUE)<<\" \"<<Sinex::time2str(recv->timeEnd, TRUE)<<\" \"<<resize(recv->name, 20)\n              <<\" \"<<resize(recv->serial.empty() ? std::string(20, '-') : recv->serial, 20)<<\" \"<<resize(recv->version.empty() ? std::string(11, '-') : recv->version, 11)<<std::endl;\n      }\n    }\n\n    // BLOCK SITE/ANTENNA\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ANTENNA\");\n      *block<<\"*STATION__ PT SOLN T __DATA_START__ __DATA_END____ DESCRIPTION_________ S/N_________________ PCV_MODEL_\"<<std::endl;\n      for(const auto &station : stations)\n      {\n        auto ant = station.platform.findEquipment<PlatformGnssAntenna>(station.timesMid);\n        if(!ant)\n        {\n          logWarning<<station.platform.markerName<<\": no antenna found at \"<<station.timesMid.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<String::upperCase(resize(station.platform.markerName, 9))<<\"  A    1 P \"<<Sinex::time2str(ant->timeStart, TRUE)<<\" \"<<Sinex::time2str(ant->timeEnd, TRUE)<<\" \"\n              <<resize(ant->name, 15)<<\" \"<<(ant->radome.empty() ? \"NONE\" : resize(ant->radome, 4))<<\" \"<<resize(ant->serial.empty() ? std::string(20, '-') : ant->serial, 20)<<\" \"\n              <<resize(antennaModel, 10)<<std::endl;\n      }\n    }\n\n    // BLOCK SITE/ECCENTRICITY\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SITE/ECCENTRICITY\");\n      *block<<\"*\"<<std::setw(80)<<\"UP______ NORTH___ EAST____\"<<std::endl;\n      *block<<\"*STATION__ PT SOLN T __DATA_START__ __DATA_END____ AXE ARP->BENCHMARK(M)_________\"<<std::endl;\n      for(const auto &station : stations)\n      {\n        auto ant = station.platform.findEquipment<PlatformGnssAntenna>(station.timesMid);\n        if(!ant)\n        {\n          logWarning<<station.platform.markerName<<\": no antenna found at \"<<station.timesMid.dateTimeStr()<<Log::endl;\n          continue;\n        }\n        *block<<\" \"<<String::upperCase(resize(station.platform.markerName, 9))<<\"  A    1 P \"<<Sinex::time2str(ant->timeStart, TRUE)<<\" \"\n              <<Sinex::time2str(ant->timeEnd, TRUE)<<\" UNE \"<<ant->position.z() % \"%8.4f \"s<<ant->position.x() % \"%8.4f \"s<<ant->position.y() % \"%8.4f\"s<<std::endl;\n      }\n    }\n\n    // BLOCK: TROP/SOLUTION\n    {\n      SinexBlockPtr block = sinex.addBlock(\"TROP/SOLUTION\");\n      *block<<\"*STATION__ ____EPOCH_____\"; for(const auto &c : columns) {*block<<\" \"<<c;}; *block<<std::endl;\n      for(const auto &station : stations)\n        for(UInt idEpoch=0; idEpoch<station.tropData.size(); idEpoch++)\n        {\n          const Vector data = 1e3 * station.tropData.at(idEpoch).values;\n          *block<<\" \"<<String::upperCase(resize(station.platform.markerName, 9))<<\" \"<<Sinex::time2str(station.tropData.at(idEpoch).time, TRUE);\n          if(!station.tropSigmas.size())\n            *block<<(data(0)+data(1))%\" %6.1f\"s<<(data(2)+data(3))%\" %6.2f\"s<<(data(4)+data(5))%\" %6.2f\"s<<std::endl;\n          else\n          {\n            const Vector sigmas = 1e3 * station.tropSigmas.at(idEpoch).values;\n            *block<<(data(0)+data(1))%\" %6.1f\"s<<sigmas(0)%\" %6.1f\"s\n                  <<(data(2)+data(3))%\" %6.2f\"s<<sigmas(1)%\" %6.2f\"s\n                  <<(data(4)+data(5))%\" %6.2f\"s<<sigmas(2)%\" %6.2f\"s<<std::endl;\n          }\n        }\n    }\n\n    writeFileSinex(fileNameTropoSinex, sinex);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/rinexObservation2GnssReceiver.cpp",
    "content": "/***********************************************/\n/**\n* @file rinexObservation2GnssReceiver.cpp\n*\n* @brief Converts RINEX or Compact RINEX files to GROOPS GnssReceiver Instrument file.\n*\n* @author Sebastian Strasser\n* @date 2018-07-30\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://files.igs.org/pub/data/format/rinex_4.00.pdf}{RINEX} (version 2, 3, and 4) and\n\\href{https://terras.gsi.go.jp/ja/crx2rnx.html}{Compact RINEX} observation files to\n\\configFile{outputfileGnssReceiver}{instrument}.\n\nIn case of \\href{https://files.igs.org/pub/data/format/rinex211.txt}{RINEX v2.x} observation files\ncontaining GLONASS satellites, a mapping from PRN to frequency number must be provided via\n\\configFile{inputfileMatrixPrn2FrequencyNumber}{matrix}, see \\program{SinexMetadata2GlonassFrequencyNumber}.\nRINEX v3+ observation files already contain this information.\n\n\\configClass{useType}{gnssType} and \\configClass{ignoreType}{gnssType} can be used to filter\nthe observation types that will be exported.\n\nIf \\configFile{inputfileStationInfo}{platform} is set, RINEX antenna and receiver info\nwill be cross-checked with the provided file and warnings are raised in case of differences.\n\nA list of semi-codeless GPS receivers (observing C2D instead of C2W) can be provided via\n\\configFile{inputfileSemiCodelessReceivers}{stringList} with one receiver name per line.\nObservation types will be automatically corrected for these receivers.\n\nSome LEO satellites use special RINEX observation types, either from the unofficial RINEX v2.20\nor custom ones. These can be provided via \\configFile{inputfileSpecialObservationTypes}{stringTable}.\nThe file must  must contain a table with two columns, the first being the special type,\nand the second being the equivalent RINEX v3 type.\n\n%Example for RINEX v2.20:\n\n%\\begin{tabular}{ll}\n%LA & L1C \\\\\n%L1 & L1W \\\\\n%L2 & L2W \\\\\n%SA & S1C \\\\\n%S1 & S1W \\\\\n%S2 & S2W \\\\\n%\\end{tabular}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileStringTable.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts RINEX or Compact RINEX files to GROOPS GnssReceiver Instrument file.\n* @ingroup programsConversionGroup */\nclass RinexObservation2GnssReceiver\n{\n  struct FrequencyNumberInterval\n  {\n    FrequencyNumberInterval(const Time &timeStart_, const Time &timeEnd_, Int frequencyNumber_) : timeStart(timeStart_), timeEnd(timeEnd_), frequencyNumber(frequencyNumber_) {}\n\n    Time timeStart, timeEnd;\n    Int  frequencyNumber;\n  };\n\n  Double               rinexVersion, compactRinexVersion;\n  Time                 timeOfFirstObs;\n  Platform             stationInfo;\n  Platform             stationInfoRinex;\n  PlatformGnssAntenna  antennaRinex;\n  PlatformGnssReceiver receiverRinex;\n  GnssReceiverArc      receiverArc;\n\n  Bool isSemiCodelessReceiver = FALSE;\n  std::vector<std::string> semiCodelessReceivers;\n\n  std::vector<GnssType> useType, ignoreType;\n  std::map<std::string, std::vector<FrequencyNumberInterval>> prn2FrequencyNumbers;\n  std::map<std::string, std::string> specialTypes;\n  std::map<Char, std::vector<GnssType>> system2ObsTypes; // system, obsTypes\n\n  void readHeader(InFile &file, UInt lineCount=MAX_UINT);\n  void readObservationData(InFile &file);\n  void readCompactObservationData(InFile &file);\n  void checkStationInfo();\n  void addEpoch(const Time &time, const std::vector<GnssType> &satNumber, const std::vector<Vector> &obs, Double clockError=0.);\n  Bool getLine(InFile &file, std::string &line, std::string &label) const;\n  Bool testLabel(const std::string &labelInLine, const std::string &label, Bool optional=TRUE) const;\n  Time readEpochTime(const std::string &line) const;\n  std::vector<GnssType> getSystemObsTypes(const GnssType &prn, const Time &time) const;\n  Double readOptionalDouble(const std::string &line, size_t pos, size_t len);\n\n  static Bool isGpsAntiSpoofingEnabled(const Time &time);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(RinexObservation2GnssReceiver, SINGLEPROCESS, \"Converts RINEX or Compact RINEX files to GROOPS GnssReceiver Instrument file.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\nvoid RinexObservation2GnssReceiver::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameInPrn2FrequencyNumber, fileNameStationInfo, fileNameSemiCodelessReceivers, fileNameSpecialObservationTypes;\n    std::vector<FileName> fileNameInObs;\n\n    readConfig(config, \"outputfileGnssReceiver\",             fileNameOut,                       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileRinexObservation\",          fileNameInObs,                     Config::MUSTSET,  \"\", \"RINEX or Compact RINEX observation files\");\n    readConfig(config, \"inputfileMatrixPrn2FrequencyNumber\", fileNameInPrn2FrequencyNumber,     Config::OPTIONAL, \"{groopsDataDir}/gnss/transmitter/glonassPrnSvn2FrequencyNumber.txt\", \"(required for RINEX v2 files containing GLONASS observations), matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber\");\n    readConfig(config, \"inputfileStationInfo\",               fileNameStationInfo,               Config::OPTIONAL, \"\", \"used to determine semi-codeless receivers and to cross-check antenna and receiver info\");\n    readConfig(config, \"inputfileSemiCodelessReceivers\",     fileNameSemiCodelessReceivers,     Config::OPTIONAL, \"{groopsDataDir}/gnss/receiverStation/semiCodelessReceivers.txt\", \"list with one receiver name per line\");\n    readConfig(config, \"inputfileSpecialObservationTypes\",   fileNameSpecialObservationTypes,   Config::OPTIONAL, \"\", \"table mapping special observation types to RINEX 3 types, e.g.: LA L1C\");\n    readConfig(config, \"useType\",                            useType,                           Config::OPTIONAL, \"\", \"only use observations that match any of these patterns\");\n    readConfig(config, \"ignoreType\",                         ignoreType,                        Config::OPTIONAL, \"\", \"ignore observations that match any of these patterns\");\n    if(isCreateSchema(config)) return;\n\n    if(!fileNameStationInfo.empty())\n      readFilePlatform(fileNameStationInfo, stationInfo);\n\n    if(!fileNameSemiCodelessReceivers.empty())\n      readFileStringList(fileNameSemiCodelessReceivers, semiCodelessReceivers);\n\n    if(!fileNameSpecialObservationTypes.empty())\n    {\n      std::vector<std::vector<std::string>> table;\n      readFileStringTable(fileNameSpecialObservationTypes, table);\n      for(const auto & row : table)\n      {\n        if(row.size() >= 2)\n          specialTypes[row.at(0)] = row.at(1);\n        else\n          logWarning<<\"invalid special type mapping for \"<<row.at(0)<<Log::endl;\n      }\n    }\n\n    if(!fileNameInPrn2FrequencyNumber.empty())\n    {\n      Matrix A;\n      readFileMatrix(fileNameInPrn2FrequencyNumber, A);\n      for(UInt i = 0; i < A.rows(); i++)\n        prn2FrequencyNumbers[A(i,0)%\"R%02i\"s].push_back(FrequencyNumberInterval(mjd2time(A(i,2)), mjd2time(A(i,3)), static_cast<Int>(A(i,4))));\n    }\n\n    // read RINEX files\n    for(const auto &fileName : fileNameInObs)\n    {\n      try\n      {\n      logStatus<<\"read RINEX observation file <\"<<fileName<<\">\"<<Log::endl;\n      InFile file(fileName);\n      file.exceptions(std::ios::badbit|std::ios::failbit);\n\n      // read header\n      std::string line, label;\n      getLine(file, line, label);\n      compactRinexVersion = 0;\n      if(testLabel(label, \"CRINEX VERS   / TYPE\"))\n      {\n        compactRinexVersion = String::toDouble(line.substr(0, 20));\n        getLine(file, line, label);\n        testLabel(label, \"CRINEX PROG / DATE\", FALSE);\n        getLine(file, line, label);\n      }\n\n      testLabel(label, \"RINEX VERSION / TYPE\", FALSE);\n      rinexVersion = String::toDouble(line.substr(0, 9));\n      if(rinexVersion<2)\n        throw(Exception(\"Can only read RINEX files starting from RINEX version 2.0\"));\n      if(line.at(20)!='O')\n        throw(Exception(\"File must contain observation data\"));\n\n      // clean up data from previous file\n      system2ObsTypes.clear();\n      stationInfoRinex = Platform();\n      antennaRinex     = PlatformGnssAntenna();\n      receiverRinex    = PlatformGnssReceiver();\n\n      readHeader(file);\n      checkStationInfo();\n      if(compactRinexVersion > 0)\n        readCompactObservationData(file);\n      else\n        readObservationData(file);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\"; continue...\"<<Log::endl;\n      }\n    }\n\n    if(receiverArc.size() == 0)\n      throw(Exception(\"empty arc\"));\n\n    receiverArc.sort();\n    receiverArc.removeDuplicateEpochs(/*keepFirst*/FALSE);\n\n    logStatus<<\"write gnss data to <\"<<fileNameOut<<\">\"<<Log::endl;\n    Arc::printStatistics(receiverArc);\n    InstrumentFile::write(fileNameOut, receiverArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid RinexObservation2GnssReceiver::readHeader(InFile &file, UInt lineCount)\n{\n  try\n  {\n    std::string line, label;\n    UInt unknownLineCount = 0;\n\n    for(UInt idLine=0; idLine<lineCount; idLine++)\n    {\n      if(!getLine(file, line, label))\n        throw(Exception(\"error while reading RINEX header\"));\n      if(std::all_of(line.begin(), line.end(), isspace))\n        continue;\n      // ====================================\n      if(testLabel(label, \"END OF HEADER\"))\n        break;\n      // ====================================\n      else if(testLabel(label, \"PGM / RUN BY / DATE\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"COMMENT\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"MARKER NAME\"))\n      {\n        std::string markerName = String::trim(line.substr(0,4)); //trim(line.substr(0,60));\n        std::transform(markerName.begin(), markerName.end(), markerName.begin(), ::toupper);\n        if((!stationInfoRinex.markerName.empty()) && (stationInfoRinex.markerName != markerName))\n          logWarning<<\"Marker name changed '\"<<markerName<<\"' != '\"<<stationInfoRinex.markerName<<\"'\"<<Log::endl;\n        stationInfoRinex.markerName = markerName;\n      }\n      // ====================================\n      else if(testLabel(label, \"MARKER TYPE\"))\n      {\n        std::string comment = String::trim(line.substr(0,60));\n        if((!stationInfoRinex.comment.empty()) && (stationInfoRinex.comment != comment))\n          logWarning<<\"Marker type changed '\"<<comment<<\"' != '\"<<stationInfoRinex.comment<<\"'\"<<Log::endl;\n        stationInfoRinex.comment = comment;\n      }\n      // ====================================\n      else if(testLabel(label, \"MARKER NUMBER\"))\n      {\n        std::string markerNumber = String::trim(line.substr(0,20));\n        if((!stationInfoRinex.markerNumber.empty()) && (stationInfoRinex.markerNumber != markerNumber))\n          logWarning<<\"Marker number changed '\"<<markerNumber<<\"' != '\"<<stationInfoRinex.markerNumber<<\"'\"<<Log::endl;\n        stationInfoRinex.markerNumber = markerNumber;\n      }\n      // ====================================\n      else if(testLabel(label, \"OBSERVER / AGENCY\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"REC # / TYPE / VERS\"))\n      {\n        receiverRinex.serial  = String::trim(line.substr(0,20));\n        receiverRinex.name    = String::trim(line.substr(20,20));\n        receiverRinex.version = String::trim(line.substr(40,20));\n        std::transform(receiverRinex.name.begin(), receiverRinex.name.end(), receiverRinex.name.begin(), ::toupper); // convert to upper case\n      }\n      // ====================================\n      else if(testLabel(label, \"ANT # / TYPE\"))\n      {\n        antennaRinex.serial = String::trim(line.substr(0,20));\n        antennaRinex.name   = String::trim(line.substr(20,16));\n        antennaRinex.radome = String::trim(line.substr(36,4));\n        if(antennaRinex.radome == \"NONE\")\n          antennaRinex.radome.clear();\n      }\n      // ====================================\n      else if(testLabel(label, \"APPROX POSITION XYZ\"))\n      {\n        stationInfoRinex.approxPosition.x() = readOptionalDouble(line, 0,14);\n        stationInfoRinex.approxPosition.y() = readOptionalDouble(line,14,14);\n        stationInfoRinex.approxPosition.z() = readOptionalDouble(line,28,14);\n      }\n      // ====================================\n      else if(testLabel(label, \"ANTENNA: DELTA H/E/N\"))\n      {\n        antennaRinex.position.z() =  readOptionalDouble(line, 0,14);\n        antennaRinex.position.y() =  readOptionalDouble(line,14,14);\n        antennaRinex.position.x() =  readOptionalDouble(line,28,14);\n      }\n      // ====================================\n      else if(testLabel(label, \"ANTENNA: DELTA X/Y/Z\"))\n      {\n        antennaRinex.position.x() = readOptionalDouble(line, 0,14);\n        antennaRinex.position.y() = readOptionalDouble(line,14,14);\n        antennaRinex.position.z() = readOptionalDouble(line,28,14);\n      }\n      // ====================================\n      else if(testLabel(label, \"ANTENNA: B.SIGHT XYZ\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"ANTENNA: ZERODIR AZI \"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"ANTENNA: ZERODIR XYZ\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"CENTER OF MASS: XYZ\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"WAVELENGTH FACT L1/2\"))\n      {\n        Double factorL1 = String::toInt(line.substr(0, 6));\n        Double factorL2 = String::toInt(line.substr(6, 6));\n        if((factorL1!=1)||(factorL2!=1))\n        {\n          logInfo<<\"'\"<<line<<\"'\"<<Log::endl;\n          throw(Exception(\"not full cycle ambiguities\"));\n        }\n      }\n      // ====================================\n      else if(testLabel(label, \"# / TYPES OF OBSERV\") || // version 2\n              testLabel(label, \"SYS / # / OBS TYPES\"))   // version 3\n      {\n        const Char system = line[0] != ' ' ? line[0] : '*';\n        const Int typeCount = String::toInt(line.substr(1, 5));\n\n        std::stringstream ss(line.substr(7,53));\n        for(Int i = 0; i < typeCount; i++)\n        {\n          std::string type;\n          if(!(ss >> type)) // with possible continuation lines\n          {\n            getLine(file, line, label);\n            idLine++;\n            ss = std::stringstream(line.substr(7,53));\n            ss >> type;\n          }\n\n          if(specialTypes.find(type) != specialTypes.end())\n            type = specialTypes.at(type);\n\n          if(rinexVersion < 3 && type.size() == 2)\n          {\n            if(type[0] == 'P')\n              type = \"C\"s+type[1]+type[0]; // e.g. P1/P2 ==> C1P/C2P\n            else\n              type += '?'; // e.g. C1/L1/S2 ==> C1?/L1?/S2?\n          }\n\n          if(rinexVersion <= 3.02 && system == 'C' && type[1] == '1')\n            type[1] = '2'; // version 3.02: BeiDou C1C/L1I/... ==> C2C/L2I/...\n\n          system2ObsTypes[system].push_back(GnssType(type+system+\"**\"));\n        }\n      }\n      // ====================================\n      else if(testLabel(label, \"INTERVAL\"))\n      {\n        //interval = String::toDouble(line.substr(0, 10));\n      }\n      // ====================================\n      else if(testLabel(label, \"TIME OF FIRST OBS\"))\n      {\n        Int year   = String::toInt(line.substr(0, 6));\n        Int month  = String::toInt(line.substr(6, 6));\n        Int day    = String::toInt(line.substr(12, 6));\n        Int hour   = String::toInt(line.substr(18, 6));\n        Int min    = String::toInt(line.substr(24, 6));\n        Double sec = String::toDouble(line.substr(30, 13));\n        timeOfFirstObs = date2time(year, month, day, hour, min, sec);\n        if((line.substr(48,3)!=\"   \")&&(line.substr(48,3)!=\"GPS\"))\n          logWarning<<\"not GPS time\"<<Log::endl;\n      }\n      // ====================================\n      else if(testLabel(label, \"TIME OF LAST OBS\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"RCV CLOCK OFFS APPL\"))\n      {\n        Int flag = String::toInt(line.substr(0, 6));\n        if(flag!=0)\n          logWarning<<\"RCV CLOCK OFFS APPL\"<<Log::endl;\n      }\n      // ====================================\n      else if(testLabel(label, \"SYS / PHASE SHIFT\"))\n      {\n        if(rinexVersion < 3.01 && line.substr(1,59).find_first_not_of(' ') != std::string::npos)\n          logWarning<<\"SYS / PHASE SHIFT contains corrections that may have not been applied\"<<Log::endl;\n      }\n      // ====================================\n      else if(testLabel(label, \"GLONASS COD/PHS/BIS\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"GLONASS SLOT / FRQ #\"))\n      {\n        const Int satCount = String::toInt(line.substr(0, 3));\n\n        std::stringstream ss(line.substr(4,56));\n        for(Int i = 0; i < satCount; i++)\n        {\n          std::string prn;\n          if(!(ss >> prn)) // with possible continuation lines\n          {\n            getLine(file, line, label);\n            idLine++;\n            ss = std::stringstream(line.substr(4,56));\n            ss >> prn;\n          }\n          Int freqNo;\n          ss >> freqNo;\n          prn2FrequencyNumbers[prn] = {FrequencyNumberInterval(timeOfFirstObs, date2time(2500,1,1), freqNo)};\n        }\n      }\n      // ====================================\n      else if(testLabel(label, \"LEAP SECONDS\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"# OF SATELLITES\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"PRN / # OF OBS\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"CORR TO SYSTEM TIME\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"SIGNAL STRENGTH UNIT\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"DOI\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"LICENCE OF USE\"))\n      {\n      }\n      // ====================================\n      else if(testLabel(label, \"STATION INFORMATION\"))\n      {\n      }\n      // ====================================\n      else\n      {\n        if(++unknownLineCount < 20)\n        {\n          logWarning<<\"Unknown header label:\"<<Log::endl;\n          logWarning<<\"'\"<<line<<\"'\"<<Log::endl;\n        }\n        else if(unknownLineCount == 20)\n          logWarning<<\"skipping additional warnings about unknown header labels\"<<Log::endl;\n      }\n      // ====================================\n    }\n\n    // check if receiver measures semi-codeless (GPS L2)\n    auto recv = stationInfo.findEquipment<PlatformGnssReceiver>(timeOfFirstObs);\n    if(recv && std::find(semiCodelessReceivers.begin(), semiCodelessReceivers.end(), recv->name) != semiCodelessReceivers.end())\n      isSemiCodelessReceiver = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid RinexObservation2GnssReceiver::readObservationData(InFile &file)\n{\n  std::string line, label;\n\n  try\n  {\n    while(getLine(file, line, label))\n    {\n      if(std::all_of(line.begin(), line.end(), isspace))\n        continue;\n\n      if(label.substr(0,7) == \"COMMENT\")\n      {\n        logWarning<<\"ignoring comment line '\"<<line<<\"'\"<<Log::endl;\n        continue;\n      }\n\n      const Int  epochFlag = String::toInt(line.substr(rinexVersion < 3 ? 26 : 29, 3));\n      const UInt satCount  = String::toInt(line.substr(rinexVersion < 3 ? 29 : 32, 3));\n\n      // events?\n      if((epochFlag>=2)&&(epochFlag!=6))\n      {\n        readHeader(file, satCount);\n        continue;\n      }\n\n      const Time time = readEpochTime(line);\n      const Double clockOffset = String::toDouble(line.substr(rinexVersion < 3 ? 68 : 41, rinexVersion < 3 ? 12 :15));\n\n      // read observed satellites\n      std::vector<GnssType> satNumber(satCount);\n      if(rinexVersion < 3)\n      {\n        const UInt maxSatCountPerLine = 12;\n        for(UInt idSat = 0; idSat < satCount; idSat++)\n        {\n          if(idSat > 0 && idSat%maxSatCountPerLine == 0) // with possible continuation lines\n            getLine(file, line, label);\n          std::string prn = line.substr(32+3*(idSat%maxSatCountPerLine), 3);\n          if(prn.at(0) == ' ') prn.at(0) = 'G';\n          if(prn.at(1) == ' ') prn.at(1) = '0';\n          satNumber.at(idSat) = GnssType(\"***\"+prn);\n        }\n      }\n\n      // read observations\n      const UInt maxObsCountPerLine = rinexVersion < 3 ? 5 : MAX_UINT;\n      std::vector<Vector> obs(satCount);\n      for(UInt idSat = 0; idSat < satCount; idSat++)\n      {\n        getLine(file, line, label);\n\n        if(rinexVersion >= 3)\n          satNumber.at(idSat) = GnssType(\"***\"+line.substr(0,3));\n\n        const UInt obsCount = getSystemObsTypes(satNumber.at(idSat), time).size();\n        obs.at(idSat) = Vector(obsCount);\n        if(rinexVersion >= 3)\n          line.resize(3+16*obsCount, ' ');\n        for(UInt idType = 0; idType < obsCount; idType++)\n        {\n          if(idType > 0 && idType%maxObsCountPerLine == 0) // with possible continuation lines\n            getLine(file, line, label);\n          obs.at(idSat)(idType) = String::toDouble(line.substr((rinexVersion >= 3 ? 3 : 0)+16*(idType%maxObsCountPerLine), 14));\n\n          // TODO: LLI and signal strength\n        }\n      }\n\n      if(epochFlag==6)\n      {\n        logWarning<<\"skipping cycle slip records at \"+time.dateTimeStr()<<Log::endl;\n        continue;\n      }\n\n      addEpoch(time, satNumber, obs, clockOffset);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logError<<\"'\"<<line<<\"'\"<<Log::endl;\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// Compact RINEX reference: Hatanaka, Y. (2008) A Compression Format and Tools for GNSS Observation Data, Bulletin of the Geographical Survey Institute, 55, 21-30\nvoid RinexObservation2GnssReceiver::readCompactObservationData(InFile &file)\n{\n  std::string line, label;\n\n  try\n  {\n    std::string epochLine;\n    std::vector<Double> clockOffSetSeries;\n    std::map<GnssType, std::vector<std::vector<Double>>> prn2TypeObsSeries; // prn, obsType, observation series\n    while(getLine(file, line, label))\n    {\n      if(label.substr(0,7) == \"COMMENT\")\n      {\n        logWarning<<\"ignoring comment line '\"<<line<<\"'\"<<Log::endl;\n        continue;\n      }\n\n      if(line[0] == '&' || line[0] == '>') // epoch line initialization\n        epochLine = line;\n      else // differential epoch line\n      {\n        epochLine.resize(std::max(line.size(), epochLine.size()), ' ');\n        for(UInt i = 0; i < line.size(); i++)\n        {\n          if(line[i] == '&')\n            epochLine[i] = ' ';\n          else if(line[i] != ' ')\n            epochLine[i] = line[i];\n        }\n        line = epochLine;\n      }\n\n      const Int  epochFlag = String::toInt(line.substr(rinexVersion < 3 ? 26 : 29, 3));\n      const UInt satCount  = String::toInt(line.substr(rinexVersion < 3 ? 29 : 32, 3));\n\n      // events?\n      if((epochFlag>=2)&&(epochFlag!=6))\n      {\n        readHeader(file, satCount);\n        continue;\n      }\n\n      Time time = readEpochTime(line);\n\n      // read observed satellites\n      std::vector<GnssType> satNumber(satCount);\n      for(UInt idSat = 0; idSat < satCount; idSat++)\n      {\n        std::string prn = line.substr((rinexVersion < 3 ? 32 : 41)+3*(idSat), 3);\n        if(prn.at(0) == ' ') prn.at(0) = 'G';\n        if(prn.at(1) == ' ') prn.at(1) = '0';\n        satNumber.at(idSat) = GnssType(\"***\"+prn);\n      }\n\n      // read clock offset\n      getLine(file, line, label);\n      const Bool isEmpty = std::all_of(line.begin(), line.end(), isspace);\n      if(!isEmpty && line[1] == '&') // initializing value\n        clockOffSetSeries = {static_cast<Double>(line[0]-'0'), std::stod(line.substr(2))}; // {differential order, state at epoch}\n      else if(!isEmpty) // differential value\n      {\n        if(clockOffSetSeries.size() < clockOffSetSeries.at(0)+2)\n          clockOffSetSeries.push_back(std::stod(line)); // expand series by one if smaller than order+2\n        std::partial_sum(clockOffSetSeries.rbegin(), clockOffSetSeries.rend()-1, clockOffSetSeries.rbegin()); // update series using cumulative sum\n      }\n\n      // read observations\n      std::vector<Vector> obs(satCount);\n      for(UInt idSat = 0; idSat < satCount; idSat++)\n      {\n        getLine(file, line, label);\n\n        const UInt obsCount = getSystemObsTypes(satNumber.at(idSat), time).size();\n        obs.at(idSat) = Vector(obsCount);\n\n        prn2TypeObsSeries[satNumber.at(idSat)].resize(obsCount);\n\n        std::stringstream ss(line);\n        for(UInt idType = 0; idType < obsCount; idType++)\n        {\n          if(ss.get() == ' ' || !ss.good()) // check first character\n            continue; // skip missing data\n\n          const Bool isInitializing = (ss.get()== '&' ? TRUE : FALSE); // check second character\n          if(ss.good())\n            ss.unget(); // if second character existed, put it back into stream\n          else\n            ss.clear(); // else clear fail states\n          ss.unget();   // put first character back into stream\n\n          std::vector<Double> *obsSeries = &prn2TypeObsSeries[satNumber.at(idSat)].at(idType);\n          if(isInitializing)\n          {\n            obsSeries->assign(2, 0);           // {differential order, state at epoch}\n            obsSeries->at(0) = ss.get() - '0'; // set order\n            ss.get();                          // skip the &\n            ss >> obsSeries->at(1);            // set initial state\n          }\n          else // differential value\n          {\n            if(!obsSeries->size())\n              throw(Exception(\"error in compact RINEX file (differential value given but arc is not initialized)\"));\n            if(obsSeries->size() < obsSeries->at(0)+2)\n              obsSeries->push_back(0); // expand series by one if smaller than order+2\n            ss >> obsSeries->back();\n            std::partial_sum(obsSeries->rbegin(), obsSeries->rend()-1, obsSeries->rbegin()); // update series using cumulative sum\n          }\n\n          if(ss.good())\n            ss.get(); // skip the trailing space\n\n          obs.at(idSat).at(idType) = obsSeries->at(1)/1000;\n        }\n\n        // TODO: LLI and signal strength\n      }\n\n      if(epochFlag==6)\n      {\n        logWarning<<\"skipping cycle slip records at \"+time.dateTimeStr()<<Log::endl;\n        continue;\n      }\n\n      addEpoch(time, satNumber, obs, clockOffSetSeries.size() ? clockOffSetSeries.at(1) : 0);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logError<<\"'\"<<line<<\"'\"<<Log::endl;\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid RinexObservation2GnssReceiver::checkStationInfo()\n{\n  try\n  {\n    if((!stationInfo.markerName.empty()) && (stationInfo.markerName.substr(0,4) != stationInfoRinex.markerName.substr(0,4)))\n      logWarning<<timeOfFirstObs.dateTimeStr()<<\" Marker name differs '\"<<stationInfo.markerName<<\"' != '\"<<stationInfoRinex.markerName<<\"'\"<<Log::endl;\n    if((!stationInfo.markerNumber.empty()) && (stationInfo.markerNumber != stationInfoRinex.markerNumber))\n      logWarning<<timeOfFirstObs.dateTimeStr()<<\" Marker number differs '\"<<stationInfo.markerNumber<<\"' != '\"<<stationInfoRinex.markerNumber<<\"'\"<<Log::endl;\n\n    // test antenna\n    if(stationInfo.equipments.size())\n    {\n      auto antenna = stationInfo.findEquipment<PlatformGnssAntenna>(timeOfFirstObs);\n      if(antenna)\n      {\n        if((!antennaRinex.name.empty()) && (antenna->name != antennaRinex.name))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Antenna name differs '\"<<antenna->name<<\"' != '\"<<antennaRinex.name<<\"'\"<<Log::endl;\n        if((!antennaRinex.serial.empty()) && !String::startsWith(antennaRinex.serial, antenna->serial))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Antenna serial differs '\"<<antenna->serial<<\"' != '\"<<antennaRinex.serial<<\"'\"<<Log::endl;\n        if((!antennaRinex.radome.empty()) && (antenna->radome != antennaRinex.radome))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Antenna radome differs '\"<<antenna->radome<<\"' != '\"<<antennaRinex.radome<<\"'\"<<Log::endl;\n        if((antenna->position-antennaRinex.position).r()>=0.001 || std::isnan(antennaRinex.position.r()))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Antenna delta position differs\"<<Log::endl;\n\n        antennaRinex = *antenna;\n      }\n      else\n        logWarning << timeOfFirstObs.dateTimeStr() << \": Antenna not found in stationInfo: '\"<<antennaRinex.name<<\"'\"<<Log::endl;\n    }\n\n    // test receiver\n    if(stationInfo.equipments.size())\n    {\n      auto recv = stationInfo.findEquipment<PlatformGnssReceiver>(timeOfFirstObs);\n      if(recv)\n      {\n        if((!receiverRinex.name.empty()) && (recv->name != receiverRinex.name))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Receiver name differs '\"<<recv->name<<\"' != '\"<<receiverRinex.name<<\"'\"<<Log::endl;\n        if((!receiverRinex.serial.empty()) && !String::startsWith(receiverRinex.serial, recv->serial))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Receiver serial differs '\"<<recv->serial<<\"' != '\"<<receiverRinex.serial<<\"'\"<<Log::endl;\n        if((!receiverRinex.version.empty()) && (recv->version != receiverRinex.version))\n          logWarning<<timeOfFirstObs.dateTimeStr()<<\" Receiver version differs '\"<<recv->version<<\"' != '\"<<receiverRinex.version<<\"'\"<<Log::endl;\n\n        receiverRinex = *recv;\n      }\n      else\n        logWarning << timeOfFirstObs.dateTimeStr() << \": Receiver not found in stationInfo: '\"<<receiverRinex.name<<\"'\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid RinexObservation2GnssReceiver::addEpoch(const Time &time, const std::vector<GnssType> &satNumber, const std::vector<Vector> &obs, Double clockError)\n{\n  try\n  {\n    GnssReceiverEpoch epoch;\n    epoch.time = time;\n    epoch.clockError = clockError;\n\n    // collect types and satellites that occur at this epoch\n    const UInt satCount = satNumber.size();\n    std::set<GnssType> occuringTypes;\n    std::vector<Bool> isOccuringSat(satCount, FALSE);\n    for(UInt idSat=0; idSat<satCount; idSat++)\n    {\n      const std::vector<GnssType> obsTypes = getSystemObsTypes(satNumber.at(idSat), time);\n      for(UInt idType=0; idType<obsTypes.size(); idType++)\n      {\n        const GnssType type = obsTypes.at(idType) + satNumber.at(idSat);\n        Bool use = !useType.size() ? TRUE : FALSE;\n        if(GnssType::index(useType, type) != NULLINDEX)\n          use = TRUE;\n        if(GnssType::index(ignoreType, type) != NULLINDEX)\n          use = FALSE;\n        if(!use || obs.at(idSat)(idType) == 0.0)\n          continue;\n        occuringTypes.insert(type & GnssType::NOPRN);\n        isOccuringSat.at(idSat) = TRUE;\n      }\n    }\n\n    // add collected types to epoch\n    for(const auto &type : occuringTypes)\n      epoch.obsType.push_back(type);\n\n    // add satellites and observations to epoch\n    for(UInt idSat=0; idSat<satCount; idSat++)\n      if(isOccuringSat.at(idSat))\n      {\n        GnssType sat = satNumber.at(idSat);\n\n        // check GLONASS frequency number\n        if((sat & GnssType::SYSTEM) == GnssType::GLONASS)\n        {\n          const std::string prn = sat.str().substr(3,3);\n          try\n          {\n            auto iter = std::find_if(prn2FrequencyNumbers.at(prn).begin(), prn2FrequencyNumbers.at(prn).end(), [&](const auto &interval){ return time.isInInterval(interval.timeStart, interval.timeEnd); });\n            if(iter != prn2FrequencyNumbers.at(prn).end())\n              sat.setFrequencyNumber(iter->frequencyNumber);\n            else\n              throw(Exception(\"no frequency number found for \"+prn+\" at \"+time.dateTimeStr()+\" (frequency number file must be provided for RINEX v2.x)\"));\n          }\n          catch(std::exception &e)\n          {\n            if(sat.PRN.prn() > 24) // ignore test satellites with PRN 26, 27 etc. if frequency number is unknown\n              continue;\n            GROOPS_RETHROW(e);\n          }\n        }\n\n        epoch.satellite.push_back(sat);\n\n        const std::vector<GnssType> obsTypes = getSystemObsTypes(sat, time);\n        for(const auto &type : occuringTypes)\n        {\n          if((type & GnssType::SYSTEM) != (sat & GnssType::SYSTEM))\n            continue;\n\n          auto iter = std::find(obsTypes.begin(), obsTypes.end(), type);\n          if(iter == obsTypes.end())\n            continue;\n\n          const UInt idType = std::distance(obsTypes.begin(), iter);\n          epoch.observation.push_back(obs.at(idSat)(idType));\n          if(type == GnssType::PHASE && obs.at(idSat)(idType) != 0.0)\n            epoch.observation.back() *= (type+sat).wavelength(); // cycles -> meters\n        }\n      }\n\n    // skip empty epochs\n    if(epoch.satellite.size())\n      receiverArc.push_back(epoch);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool RinexObservation2GnssReceiver::getLine(InFile &file, std::string &line, std::string &label) const\n{\n  try\n  {\n    std::getline(file, line);\n    if(line.size() && line.back() == '\\r')\n      line.pop_back();\n    if(line.size()<80)\n      line.resize(80,' ');\n    label = line.substr(60,20);\n    return TRUE;\n  }\n  catch(...)\n  {\n    line.clear();\n    line.resize(80,' ');\n    label = line.substr(60,20);\n    return FALSE;\n  }\n}\n\n/***********************************************/\n\nBool RinexObservation2GnssReceiver::testLabel(const std::string &labelInLine, const std::string &label, Bool optional) const\n{\n  if(labelInLine.find(label)!=std::string::npos)\n    return TRUE;\n  if(optional)\n    return FALSE;\n  throw(Exception(std::string(\"In line '\")+labelInLine+\"' label '\"+label+\"' expected\\n\"));\n}\n\n/***********************************************/\n\nTime RinexObservation2GnssReceiver::readEpochTime(const std::string &line) const\n{\n  try\n  {\n    Int year   = String::toInt(line.substr(rinexVersion < 3 ?  1 :  2, rinexVersion < 3 ? 2 : 4));\n    Int month  = String::toInt(line.substr(rinexVersion < 3 ?  3 :  7, 3));\n    Int day    = String::toInt(line.substr(rinexVersion < 3 ?  6 : 10, 3));\n    Int hour   = String::toInt(line.substr(rinexVersion < 3 ?  9 : 13, 3));\n    Int minute = String::toInt(line.substr(rinexVersion < 3 ? 12 : 16, 3));\n    Double sec = String::toDouble(line.substr(rinexVersion < 3 ? 15 : 19, 11));\n    if(rinexVersion < 3)\n      year += (year<80 ? 2000 : 1900);\n    return date2time(year, month, day, hour, minute, sec);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nstd::vector<GnssType> RinexObservation2GnssReceiver::getSystemObsTypes(const GnssType &prn, const Time &time) const\n{\n  try\n  {\n    std::vector<GnssType> obsTypes = system2ObsTypes.at(rinexVersion < 3 ? '*' : prn.prnStr()[0]);\n\n    // GPS: replace observation types\n    if(prn == GnssType::GPS)\n      for(auto &&type : obsTypes)\n      {\n        if(type == (GnssType::RANGE + GnssType::L1 + GnssType::UNKNOWN_ATTRIBUTE))\n          type = GnssType::RANGE + GnssType::L1 + GnssType::C; // C1? ==> C1C\n        if(type == GnssType::P)\n          type = (type & GnssType::TYPE) + (type & GnssType::FREQUENCY) + GnssType::W; // **P ==> **W\n        if(isSemiCodelessReceiver && type == (GnssType::RANGE + GnssType::L2 + GnssType::W) && isGpsAntiSpoofingEnabled(time))\n          type = (type & GnssType::TYPE) + (type & GnssType::FREQUENCY) + GnssType::D; // C2W ==> C2D for semicodeless receivers if anti-spoofing is enabled\n      }\n\n    // GLONASS: replace observation types\n    if(prn == GnssType::GLONASS)\n      for(auto &&type : obsTypes)\n        if(type == (GnssType::RANGE + GnssType::UNKNOWN_ATTRIBUTE) && (type == GnssType::G1 || type == GnssType::G2))\n          type = GnssType::RANGE + (type & GnssType::FREQUENCY) + GnssType::C; // C1?/C2? ==> C1C/C2C\n\n    return obsTypes;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n\nDouble RinexObservation2GnssReceiver::readOptionalDouble(const std::string &line, size_t pos, size_t len)\n{\n  try\n  {\n    return String::toDouble(line.substr(pos, len));\n  }\n  catch(...)\n  {\n    return NAN_EXPR;\n  }\n}\n\n/***********************************************/\n\nBool RinexObservation2GnssReceiver::isGpsAntiSpoofingEnabled(const Time &time)\n{\n  try\n  {\n    const Double mjd = time.mjd();\n\n    if((                   mjd < 49383.)      ||\n    (mjd >= 49826.87499 && mjd < 49847.83334) ||\n    (mjd >= 49887.      && mjd < 49909.)      ||\n    (mjd >= 50000.      && mjd < 50022.)      ||\n    (mjd >= 50481.      && mjd < 50503.))\n      return FALSE;\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/sinex2StationDiscontinuities.cpp",
    "content": "/***********************************************/\n/**\n* @file sinex2StationDiscontinuities.cpp\n*\n* @brief Convert station discontinuities from SINEX (e.g. ITRF20) to InstrumentMiscValue.\n*\n* A value of 1 means position discontinuity, a value of 2 means velocity discontinuity.\n*\n* @author Sebastian Strasser\n* @date 2017-05-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert station discontinuities from\n\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}\n(e.g. ITRF20) to \\configFile{outputfileInstrument}{instrument} (MISCVALUE).\nA value of 1 means position discontinuity, a value of 2 means velocity discontinuity.\nStart and end epochs with value 0 are added in addition to the discontinuities from\nSINEX to define continuity interval borders.\n\nSee also \\program{Sinex2StationPosition} and \\program{Sinex2StationPostSeismicDeformation}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert station discontinuities from SINEX (e.g. ITRF20) to InstrumentMiscValue.\n* @ingroup programsConversionGroup */\nclass Sinex2StationDiscontinuities\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sinex2StationDiscontinuities, SINGLEPROCESS, \"Convert station discontinuities from SINEX (e.g. ITRF20) to InstrumentMiscValue.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\nvoid Sinex2StationDiscontinuities::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName, fileNameSinex;\n    std::vector<std::string> stationNames;\n    std::string variableLoopStation;\n\n    readConfig(config, \"outputfileInstrument\",     outName,             Config::MUSTSET,  \"\",        \"loop variable is replaced with station name (e.g. wtzz)\");\n    readConfig(config, \"inputfileDiscontinuities\", fileNameSinex,       Config::MUSTSET,  \"\",        \"SINEX (e.g. ITRF20) station discontinuities\");\n    readConfig(config, \"variableLoopStation\",      variableLoopStation, Config::DEFAULT,  \"station\", \"variable name for station loop\");\n    readConfig(config, \"stationName\",              stationNames,        Config::OPTIONAL, \"\",        \"only export these stations\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input file <\"<<fileNameSinex<<\">\"<<Log::endl;\n    Sinex sinex;\n    readFileSinex(fileNameSinex, sinex);\n    const std::vector<std::string> &lines = sinex.findBlock(\"SOLUTION/DISCONTINUITY\")->lines;\n    std::map<std::string, MiscValueArc> stations;\n    for(const auto &line : lines)\n    {\n      std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n        continue;\n\n      Time time = Sinex::str2time(line, 16, TRUE);\n      MiscValueEpoch epoch;\n      epoch.time = time;\n      std::string type = line.substr(42,1);\n      if(type == \"P\")\n        epoch.value = 1;\n      else if(type == \"V\")\n        epoch.value = 2;\n      else\n      {\n        logWarning<<\"Unknown discontinuity type for line: \"<<line<<Log::endl;\n        continue;\n      }\n      stations[name].push_back(epoch);\n    }\n\n    logStatus<<\"write output files <\"<<outName<<\">\"<<Log::endl;\n    VariableList fileNameVariableList;\n    for(auto &&station : stations)\n    {\n      station.second.sort();\n      while(station.second.size() && station.second.back().time == date2time(2500, 1, 1))\n        station.second.remove(station.second.size()-1);\n      MiscValueEpoch epoch;\n      station.second.insert(0, epoch); // start epoch\n      epoch.time = date2time(2500, 1, 1);\n      station.second.push_back(epoch); // end epoch\n\n      fileNameVariableList.setVariable(variableLoopStation, station.first);\n      InstrumentFile::write(outName(fileNameVariableList), station.second);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/sinex2StationPositions.cpp",
    "content": "/***********************************************/\n/**\n* @file sinex2StationPosition.cpp\n*\n* @brief Convert station positions from SINEX to InstrumentVector3d.\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2016-12-07\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nExtracts station positions from \\config{inputfileSinexSolution}\n(\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format description})\nand writes an \\configFile{outputfileInstrument}{instrument} of type VECTOR3D\nfor each station.  Positions will be computed at \\configClass{timeSeries}{timeSeriesType} based on position and velocity\nof each provided interval in the SINEX file.\nWith \\config{inputfileSinexDiscontinuities} the bounds of these time spans are adjusted to the exact epochs of discontinuities.\nThe \\config{inputfileSinexPostSeismicDeformations} adds the ITRF post-seismic deformation model to the affected stations.\nThe \\config{inputfileSinexFrequencies} adds annual and semi-annual frequencies.\n\nIf \\config{extrapolateBackward} or \\config{extrapolateForward} are provided, positions will also be computed for epochs\nbefore the first interval/after the last interval, based on the position and velocity of the first/last interval.\nPosition extrapolation will stop at the first discontinuity before the first interval/after the last interval.\n\nStations can be limited via \\config{stationName}, otherwise all stations in \\config{inputfileSinexSolution} will be used.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert GNSS station positions from SINEX to InstrumentVector3d.\n* @ingroup programsConversionGroup */\nclass Sinex2StationPositions\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sinex2StationPositions, SINGLEPROCESS, \"Convert station positions from SINEX to InstrumentVector3d.\", Conversion, Gnss, Instrument)\n\n/***********************************************/\n\nvoid Sinex2StationPositions::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 fileNameInstrument;\n    std::string              variableLoopStation;\n    FileName                 fileNameSinex, fileNameSinexDisc, fileNameSinexPsd, fileNameSinexFreq;\n    TimeSeriesPtr            timeSeries;\n    Bool                     extrapolateForward, extrapolateBackward;\n    std::vector<std::string> stationNames;\n\n    readConfig(config, \"outputfileInstrument\",                  fileNameInstrument,  Config::MUSTSET,   \"stationPosition.{station}.dat\", \"loop variable is replaced with station name (e.g. wtzz)\");\n    readConfig(config, \"variableLoopStation\",                   variableLoopStation, Config::DEFAULT,   \"station\", \"variable name for station loop\");\n    readConfig(config, \"inputfileSinexSolution\",                fileNameSinex,       Config::MUSTSET,   \"ITRF2020-IGS-TRF.SSC\",            \"SINEX file\");\n    readConfig(config, \"inputfileSinexDiscontinuities\",         fileNameSinexDisc,   Config::OPTIONAL,  \"ITRF2020-soln-gnss.snx\",          \"SINEX file\");\n    readConfig(config, \"inputfileSinexPostSeismicDeformations\", fileNameSinexPsd,    Config::OPTIONAL,  \"ITRF2020-psd-gnss.snx\",           \"SINEX file\");\n    readConfig(config, \"inputfileSinexFrequencies\",             fileNameSinexFreq,   Config::OPTIONAL,  \"ITRF2020-Frequencies-XYZ-CF.snx\", \"SINEX file (XYZ or ENU)\");\n    readConfig(config, \"timeSeries\",                            timeSeries,          Config::MUSTSET,   \"\",  \"compute positions for these epochs based on velocity\");\n    readConfig(config, \"extrapolateForward\",                    extrapolateForward,  Config::DEFAULT,   \"1\", \"also compute positions for epochs after last interval defined in SINEX file\");\n    readConfig(config, \"extrapolateBackward\",                   extrapolateBackward, Config::DEFAULT,   \"0\", \"also compute positions for epochs before first interval defined in SINEX file\");\n    readConfig(config, \"stationName\",                           stationNames,        Config::OPTIONAL,  \"\",  \"convert only these stations\");\n    if(isCreateSchema(config)) return;\n\n    struct Interval\n    {\n      std::string pointCode;\n      std::string solutionId;\n      Time        referenceTime, timeStart, timeEnd;\n      Vector3d    position, velocity;\n      Vector3dArc arc;\n      std::map<std::string, Vector3d> ampl3d;\n    };\n\n    struct Station\n    {\n      std::vector<Interval> intervals;\n      std::vector<Interval> discontinuities;\n      std::string pointCode, dome;\n      Vector3d    position;\n      Transform3d lnof2trf;\n    };\n\n    std::map<std::string, Station> stations;\n    std::vector<Time> times = timeSeries->times();\n\n    // =========================================================\n\n    if(!fileNameSinex.empty())\n    {\n      logStatus<<\"read SINEX solution file <\"<<fileNameSinex<<\">\"<<Log::endl;\n      Sinex sinex;\n      readFileSinex(fileNameSinex, sinex);\n\n      // SITE/ID\n      // -------\n      for(std::string &line : sinex.findBlock(\"SITE/ID\")->lines)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        // *Code PT __DOMES__ T _STATION DESCRIPTION__ APPROX_LON_ APPROX_LAT_ _APP_H_\n        std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        const Double longitude   = String::toDouble(line.substr(44, 3)) + String::toDouble(line.substr(48, 2))/60 + String::toDouble(line.substr(51, 4))/3600;\n        const Double latitude    = String::toDouble(line.substr(56, 3)) + (String::startsWith(String::trim(line.substr(56, 3)), \"-\") ? -1 : 1) * std::fabs(String::toDouble(line.substr(60, 2))/60 + String::toDouble(line.substr(62, 5))/3600);\n        const Double height      = String::toDouble(line.substr(68, 7));\n        stations[name].pointCode = String::trim(line.substr(6, 2));\n        stations[name].dome      = String::trim(line.substr(9, 9));\n        stations[name].position  = Ellipsoid()(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), height);\n        stations[name].lnof2trf  = localNorthEastUp(polar(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), 1.));\n      }\n\n      // SOLUTION/EPOCHS\n      // ---------------\n      for(std::string &line : sinex.findBlock(\"SOLUTION/EPOCHS\")->lines)\n      {\n        std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        Interval interval;\n        interval.pointCode  = String::trim(line.substr(6, 2));\n        interval.solutionId = String::trim(line.substr(9, 4));\n        interval.timeStart  = Sinex::str2time(line, 16, FALSE);\n        interval.timeEnd    = Sinex::str2time(line, 29, TRUE);\n        stations[name].intervals.push_back(interval);\n      }\n\n      // SOLUTION/ESTIMATE\n      // -----------------\n      UInt count = 0;\n      for(std::string &line : sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        // *INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___ESTIMATED_VALUE___ __STD_DEV__\n        //      1 STAX   7894  A    1 15:001:00000 m    2 -.219677819584269E+07 0.11095E+00\n        const std::string name = String::lowerCase(String::trim(line.substr(14, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n\n        const std::string parameterType = String::trim(line.substr(7, 6));\n        const std::string pointCode     = String::trim(line.substr(19, 2));\n        const std::string solutionId    = String::trim(line.substr(22, 4));\n        const Double      value         = String::toDouble(line.substr(47, 21));\n\n        if((parameterType != \"STAX\") && (parameterType != \"STAY\") && (parameterType != \"STAZ\") &&\n           (parameterType != \"VELX\") && (parameterType != \"VELY\") && (parameterType != \"VELZ\"))\n          continue;\n\n        auto interval = std::find_if(stations[name].intervals.begin(), stations[name].intervals.end(),\n                                     [&](const Interval &i) {return (i.solutionId == solutionId) && (i.pointCode == pointCode);});\n        if(interval == stations[name].intervals.end())\n          throw(Exception(name+\": interval for solutionId \"+solutionId+\" not found\"));\n\n        interval->referenceTime = Sinex::str2time(line, 27, FALSE);\n        Bool used = TRUE;\n        if(     parameterType == \"STAX\") interval->position.x() = value;\n        else if(parameterType == \"STAY\") interval->position.y() = value;\n        else if(parameterType == \"STAZ\") interval->position.z() = value;\n        else if(parameterType == \"VELX\") interval->velocity.x() = value;\n        else if(parameterType == \"VELY\") interval->velocity.y() = value;\n        else if(parameterType == \"VELZ\") interval->velocity.z() = value;\n        else\n          used = FALSE;\n        count += used;\n      }\n      logInfo<<\"  \"<<count<<\" of \"<<sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines.size()<<\" parameters used\"<<Log::endl;\n    }\n\n    // =========================================================\n\n    // test intervals\n    // --------------\n    for(auto &station : stations)\n    {\n      auto &intervals = station.second.intervals;\n      if(!intervals.size())\n      {\n        logWarning<<station.first<<\" without solution intervals\"<<Log::endl;\n        continue;\n      }\n\n      std::stable_sort(station.second.intervals.begin(), station.second.intervals.end(), [](auto &a, auto &b) {return a.timeEnd < b.timeEnd;});\n\n      // repair overlapping periods\n      for(UInt i=0; i<intervals.size()-1; i++)\n        if(intervals.at(i).timeEnd > intervals.at(i+1).timeStart)\n        {\n          if((intervals.at(i).timeEnd-intervals.at(i+1).timeStart).mjd() > 0.25)\n            logWarning<<station.first<<\" interval ends at \"<<intervals.at(i).timeEnd.dateTimeStr()<<\", next intervals starts at \"<<intervals.at(i+1).timeStart.dateTimeStr()<<Log::endl;\n          intervals.at(i).timeEnd = intervals.at(i+1).timeStart = 0.5*(intervals.at(i).timeEnd+intervals.at(i+1).timeStart);\n        }\n\n      // fill gaps\n      for(UInt i=0; i<intervals.size()-1; i++)\n        if(intervals.at(i).timeEnd < intervals.at(i+1).timeStart)\n          intervals.at(i).timeEnd = intervals.at(i+1).timeStart;\n\n      if(extrapolateBackward)\n        intervals.front().timeStart = Time();\n      if(extrapolateForward)\n        intervals.back().timeEnd = date2time(2500, 1, 1);\n    } // for(station)\n\n    // =========================================================\n\n    if(!fileNameSinexDisc.empty())\n    {\n      logStatus<<\"read SINEX discontinuities file <\"<<fileNameSinexDisc<<\">\"<<Log::endl;\n      Sinex sinex;\n      readFileSinex(fileNameSinexDisc, sinex);\n\n      // SOLUTION/DISCONTINUITY\n      // ----------------------\n      for(std::string &line : sinex.findBlock(\"SOLUTION/DISCONTINUITY\")->lines)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        //  ADEA  A    1 D 00:000:00000 98:084:11545 P - 1998/03/25-Earthquake_M8.1_Balleny_Islands_(616km)\n        std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        if(stations.find(name) == stations.end())\n          continue;\n        Interval interval;\n        interval.pointCode  = String::trim(line.substr(6, 2));\n        interval.solutionId = String::trim(line.substr(9, 4));\n        interval.timeStart  = Sinex::str2time(line, 16, FALSE);\n        interval.timeEnd    = Sinex::str2time(line, 29, TRUE);\n        if(line.substr(42,1) == \"P\") // position changes only\n          stations[name].discontinuities.push_back(interval);\n      }\n\n      // adjust intervals\n      // ----------------\n      for(auto &station : stations)\n      {\n        auto &intervals       = station.second.intervals;\n        auto &discontinuities = station.second.discontinuities;\n        if(!discontinuities.size())\n          continue;\n\n        std::stable_sort(discontinuities.begin(), discontinuities.end(), [](auto &a, auto &b) {return a.timeEnd < b.timeEnd;});\n\n        // repair overlapping periods\n        for(UInt i=0; i<discontinuities.size()-1; i++)\n          if(discontinuities.at(i).timeEnd != discontinuities.at(i+1).timeStart)\n          {\n            logWarning<<station.first<<\" discontinuity ends at \"<<discontinuities.at(i).timeEnd.dateTimeStr()<<\", next discontinuity starts at \"<<discontinuities.at(i).timeStart.dateTimeStr()<<Log::endl;\n            discontinuities.at(i).timeEnd = discontinuities.at(i+1).timeStart = 0.5*(discontinuities.at(i).timeEnd+discontinuities.at(i+1).timeStart);\n          }\n\n        // adjust solution intervals\n        Time timeStart = intervals.front().timeStart;\n        Time timeEnd   = intervals.back().timeEnd;\n        for(UInt i=0; i<intervals.size(); i++)\n        {\n          auto discontinuity = std::find_if(discontinuities.begin(), discontinuities.end(), [&] (auto &x) {return x.solutionId == intervals.at(i).solutionId;});\n          if(discontinuity != discontinuities.end())\n          {\n            if(intervals.at(i).pointCode != discontinuity->pointCode)\n              logWarning<<station.first<<\" point code differ \"<<intervals.at(i).pointCode<<\" != \"<<discontinuity->pointCode<<Log::endl;\n            intervals.at(i).pointCode = discontinuity->pointCode;\n            intervals.at(i).timeStart = std::max(timeStart, discontinuity->timeStart);\n            intervals.at(i).timeEnd   = std::min(timeEnd,   discontinuity->timeEnd);\n          }\n          else\n            logWarning<<station.first<<\" solution '\"<<intervals.at(i).solutionId<<\"' without discontinuity interval\"<<Log::endl;\n        }\n      }\n    }\n\n    // =========================================================\n\n    // create arcs\n    // -----------\n    for(auto &station : stations)\n      for(auto &interval : station.second.intervals)\n        for(auto &time : times)\n          if(time.isInInterval(interval.timeStart, interval.timeEnd))\n          {\n            Vector3dEpoch epoch;\n            epoch.time     = time;\n            epoch.vector3d = interval.position + interval.velocity * (time-interval.referenceTime).mjd()/365.25;\n            interval.arc.push_back(epoch);\n          }\n\n    // =========================================================\n\n    if(!fileNameSinexPsd.empty())\n    {\n      logStatus<<\"read SINEX post seismic deformation file <\"<<fileNameSinexPsd<<\">\"<<Log::endl;\n      Sinex sinex;\n      readFileSinex(fileNameSinexPsd, sinex);\n\n      // SITE/ID\n      // -------\n      for(std::string &line : sinex.findBlock(\"SITE/ID\")->lines)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        // *Code PT __DOMES__ T _STATION DESCRIPTION__ APPROX_LON_ APPROX_LAT_ _APP_H_\n        std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        if(stations.find(name) == stations.end())\n          continue;\n        const Double longitude = String::toDouble(line.substr(44, 3)) + String::toDouble(line.substr(48, 2))/60 + String::toDouble(line.substr(51, 4))/3600;\n        const Double latitude  = String::toDouble(line.substr(56, 3)) + (String::startsWith(String::trim(line.substr(56, 3)), \"-\") ? -1 : 1) * std::fabs(String::toDouble(line.substr(60, 2))/60 + String::toDouble(line.substr(62, 5))/3600);\n        const Double height    = String::toDouble(line.substr(68, 7));\n        const Double dist      = (stations[name].position - Ellipsoid()(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), height)).r();\n        if(dist > 10)\n          logWarning<<name<<\": approx position differ \"<<dist<<\" m\"<<Log::endl;\n        stations[name].lnof2trf = localNorthEastUp(polar(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), 1.));\n      }\n\n      UInt count = 0;\n      const std::vector<std::string> &lines = sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines;\n      for(UInt i=0; i<lines.size(); i+=2)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        // *INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___ESTIMATED_VALUE___ __STD_DEV__\n        //      1 ALOG_E AREB  A ---- 01:174:73993 m    2 -1.63377151539946e-01 1.85315e-02\n        //      2 TLOG_E AREB  A ---- 01:174:73993 m    2  8.15228736135023e+00 1.23120e+00\n        const std::string name = String::lowerCase(String::trim(lines.at(i).substr(14, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        if(stations.find(name) == stations.end())\n          continue;\n\n        // parameter type\n        const Bool isLog = (String::upperCase(lines.at(i).substr(7, 5))   == \"ALOG_\") &&\n                           (String::upperCase(lines.at(i+1).substr(7, 5)) == \"TLOG_\");\n        if(!isLog && ((String::upperCase(lines.at(i).substr(7, 5))   != \"AEXP_\") ||\n                      (String::upperCase(lines.at(i+1).substr(7, 5)) != \"TEXP_\")))\n          continue; // other parameter type\n\n        const Double A     = String::toDouble(lines.at(i).substr(47, 21));\n        const Double tau   = String::toDouble(lines.at(i+1).substr(47, 21)) * 365.25;\n        const Time   time0 = Sinex::str2time(lines.at(i), 27, FALSE);\n\n        Vector3d ampl3d;\n        const Char c = String::upperCase(lines.at(i).substr(12, 1)).at(0);\n        if(     c == 'N')                 ampl3d = stations[name].lnof2trf.transform(Vector3d(A, 0, 0));\n        else if(c == 'E')                 ampl3d = stations[name].lnof2trf.transform(Vector3d(0, A, 0));\n        else if((c == 'U') || (c == 'H')) ampl3d = stations[name].lnof2trf.transform(Vector3d(0, 0, A));\n\n        Bool used = FALSE;\n        for(auto &interval : stations[name].intervals)\n          for(UInt i=0; i<interval.arc.size(); i++)\n          {\n            used = TRUE;\n            if(interval.arc.at(i).time >= time0)\n            {\n              if(isLog)\n                interval.arc.at(i).vector3d += ampl3d * std::log(1.+(interval.arc.at(i).time-time0).mjd()/tau);\n              else\n                interval.arc.at(i).vector3d += ampl3d * (1.-std::exp(-(interval.arc.at(i).time-time0).mjd()/tau));\n            }\n          }\n        if(!used)\n          logWarning<<\"Unused: \"<<lines.at(i)<<Log::endl;\n        count += 2*used;\n      }\n      logInfo<<\"  \"<<count<<\" of \"<<sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines.size()<<\" parameters used\"<<Log::endl;\n    }\n\n    // =========================================================\n\n    if(!fileNameSinexFreq.empty())\n    {\n      logStatus<<\"read SINEX frequencies file <\"<<fileNameSinexFreq<<\">\"<<Log::endl;\n      Sinex sinex;\n      readFileSinex(fileNameSinexFreq, sinex);\n\n      for(std::string &line : sinex.findBlock(\"SITE/ID\")->lines)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        // *Code PT __DOMES__ T _STATION DESCRIPTION__ APPROX_LON_ APPROX_LAT_ _APP_H_\n        std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        if(stations.find(name) == stations.end())\n          continue;\n        const Double longitude = String::toDouble(line.substr(44, 3)) + String::toDouble(line.substr(48, 2))/60 + String::toDouble(line.substr(51, 4))/3600;\n        const Double latitude  = String::toDouble(line.substr(56, 3)) + (String::startsWith(String::trim(line.substr(56, 3)), \"-\") ? -1 : 1) * std::fabs(String::toDouble(line.substr(60, 2))/60 + String::toDouble(line.substr(62, 5))/3600);\n        const Double height    = String::toDouble(line.substr(68, 7));\n        const std::string dome = String::trim(line.substr(9, 9));\n        const Double dist      = (stations[name].position - Ellipsoid()(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), height)).r();\n        if(dist > 10)\n          logWarning<<name<<\": approx position differ \"<<dist<<\" m\"<<Log::endl;\n        // stations[name].lnof2trf = localNorthEastUp(polar(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), 1.));\n      }\n\n      UInt count = 0;\n      for(const std::string &line : sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines)\n      {\n        // *         1         2         3         4         5         6         7         8\n        // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n        // *INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___ESTIMATED_VALUE___ __STD_DEV__\n        //      1 A1COSX ALBH  A    1 15:001:00000 m    2  2.77340030328052e-05 1.64130e-04\n        std::string name = String::lowerCase(String::trim(line.substr(14, 4)));\n        if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n          continue;\n        if(stations.find(name) == stations.end())\n          continue;\n        const std::string pointCode  = String::trim(line.substr(19, 2));\n        const std::string solutionId = String::trim(line.substr(22, 4));\n        if(std::none_of(stations[name].intervals.begin(), stations[name].intervals.end(), [&](auto &x) {return x.pointCode == pointCode;}))\n          continue;\n\n        // parameter type\n        std::string para = String::upperCase(line.substr(7, 5));\n        if(!String::startsWith(para, \"A\") || !(String::endsWith(para, \"COS\") || String::endsWith(para, \"SIN\")))\n          continue;\n\n        Vector3d ampl3d;\n        const Double A = String::toDouble(line.substr(47, 21));\n        const Char   c = String::upperCase(line.substr(12, 1)).at(0);\n        if(     c == 'X') ampl3d = Vector3d(A, 0, 0);\n        else if(c == 'Y') ampl3d = Vector3d(0, A, 0);\n        else if(c == 'Z') ampl3d = Vector3d(0, 0, A);\n        else if(c == 'N') ampl3d = stations[name].lnof2trf.transform(Vector3d(A, 0, 0));\n        else if(c == 'E') ampl3d = stations[name].lnof2trf.transform(Vector3d(0, A, 0));\n        else if(c == 'U') ampl3d = stations[name].lnof2trf.transform(Vector3d(0, 0, A));\n\n        Bool used = FALSE;\n        for(auto &interval : stations[name].intervals)\n          if((interval.solutionId == solutionId) && (interval.pointCode == pointCode))\n          {\n            interval.ampl3d[para] += ampl3d;\n            used = TRUE;\n          }\n        count += used;\n        if(!used)\n         logWarning<<\"Unused: \"<<line<<Log::endl;\n      }\n      logInfo<<\"  \"<<count<<\" of \"<<sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines.size()<<\" parameters used\"<<Log::endl;\n\n      for(auto &station : stations)\n      {\n        // find oscillations in one of the intervals\n        std::map<std::string, Vector3d> ampl3d;\n        for(auto &interval : station.second.intervals)\n          if(interval.ampl3d.size())\n            ampl3d = interval.ampl3d;\n        // check if oscillations in all intervals the same\n        Bool same = TRUE;\n        for(auto &interval : station.second.intervals)\n          if(interval.ampl3d.size())\n            same = same && std::equal(ampl3d.begin(), ampl3d.end(), interval.ampl3d.begin(), [](auto &a, auto &b)\n                                     {return (a.first == b.first) && ((a.second-b.second).r() < 0.0001);});\n        if(same) // can extend to missing intervals\n          for(auto &interval : station.second.intervals)\n            if(!interval.ampl3d.size())\n              interval.ampl3d = ampl3d;\n\n        // check for empty intervals\n        for(auto &interval : station.second.intervals)\n          if(!interval.ampl3d.size())\n            logWarning<<station.first<<\" interval \"<<interval.timeStart.dateTimeStr()<<\" -- \"<<interval.timeEnd.dateTimeStr()<<\" without frequencies\"<<Log::endl;\n\n        // apply oscillations\n        for(auto &interval : station.second.intervals)\n          for(auto &A : interval.ampl3d)\n          {\n            const Bool isCos   = (A.first.substr(2, 3) == \"COS\");\n            const Double omega = 2*PI*String::toDouble(A.first.substr(1, 1)); // annual or semiannual\n            if(!isCos && (A.first.substr(2, 3) != \"SIN\"))\n              throw(Exception(\"COS/SIN expected\"));\n            for(UInt i=0; i<interval.arc.size(); i++)\n              interval.arc.at(i).vector3d += A.second * (isCos ? std::cos(omega*interval.arc.at(i).time.decimalYear()) : std::sin(omega*interval.arc.at(i).time.decimalYear()));\n          }\n      }\n    } // if(!fileNameSinexFreq.empty())\n\n    // =========================================================\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(variableLoopStation, \"****\");\n    logStatus<<\"write instrument files <\"<<fileNameInstrument(fileNameVariableList)<<\">\"<<Log::endl;\n    UInt count = 0;\n    for(auto &station : stations)\n    {\n      fileNameVariableList.setVariable(variableLoopStation, station.first);\n      std::vector<Arc> arcs;\n      for(auto &interval : station.second.intervals)\n        if(interval.arc.size())\n          arcs.push_back(interval.arc);\n      if(arcs.size())\n      {\n        InstrumentFile::write(fileNameInstrument(fileNameVariableList), arcs);\n        count++;\n      }\n    }\n    logInfo<<\"  \"<<count<<\" station files written\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/sinexMetadata2GlonassFrequencyNumber.cpp",
    "content": "/***********************************************/\n/**\n* @file sinexMetadata2GlonassFrequencyNumber.cpp\n*\n* @brief Create glonassPrnSvn2FrequencyNumber matrix from IGS SINEX metadata file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-12-20\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate \\configFile{outputfileMatrixPrn2FrequencyNumber}{matrix} matrix\nfrom \\href{https://www.igs.org/mgex/metadata/#metadata}{IGS SINEX metadata format}\nwith the columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber.\n\nSee also \\program{GnssGlonassFrequencyNumberUpdate}, \\program{GnssAntex2AntennaDefinition},\n\\program{RinexObservation2GnssReceiver}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"inputOutput/fileSinex.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create glonassPrnSvn2FrequencyNumber matrix from IGS SINEX metadata file.\n* @ingroup programsConversionGroup */\nclass SinexMetadata2GlonassFrequencyNumber\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SinexMetadata2GlonassFrequencyNumber, SINGLEPROCESS, \"Create glonassPrnSvn2FrequencyNumber matrix from IGS SINEX metadata file.\", Conversion, Gnss)\n\n/***********************************************/\n\nvoid SinexMetadata2GlonassFrequencyNumber::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNamePrn2FrequencyNumber, fileNameSinexMetadata;\n\n    readConfig(config, \"outputfileMatrixPrn2FrequencyNumber\", fileNamePrn2FrequencyNumber,  Config::MUSTSET, \"{groopsDataDir}/gnss/transmitter/glonassPrnSvn2FrequencyNumber.txt\", \"GROOPS matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber\");\n    readConfig(config, \"inputfileSinexMetadata\",              fileNameSinexMetadata,        Config::MUSTSET, \"igs_satellite_metadata.snx\", \"IGS SINEX metadata file\");\n    if(isCreateSchema(config)) return;\n\n    Sinex sinex;\n    readFileSinex(fileNameSinexMetadata, sinex);\n    std::vector<std::string> freqLines = sinex.findBlock(\"SATELLITE/FREQUENCY_CHANNEL\")->lines;\n    std::vector<std::string> prnLines  = sinex.findBlock(\"SATELLITE/PRN\")->lines;\n\n    std::vector<Vector> lines;\n    for(const auto &line : freqLines)\n    {\n      // *         1         2         3         4         5         6         7         8\n      // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n      // *SVN_ Valid_From____ Valid_To______ chn Comment________________________________\n      //  R701 2003:344:00000 2009:258:86399   1 [FC10]\n      std::string  svn = line.substr(1, 4);\n      Time   timeStart = Sinex::str2time(line,  6, FALSE/*zeroIsMaxTime*/, TRUE/*fourDigitYear*/);\n      Time   timeEnd   = Sinex::str2time(line, 21, TRUE /*zeroIsMaxTime*/, TRUE/*fourDigitYear*/);\n      Double chn       = String::toDouble(line.substr(36, 3));\n\n      for(const auto &line : prnLines)\n        if(line.substr(1, 4) == svn)\n        {\n          // *         1         2         3         4         5         6         7         8\n          // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n          // *SVN_ Valid_From____ Valid_To______ PRN Comment_________________________________\n          //  G001 1978:053:00000 1985:199:00000 G04\n          std::string prn = line.substr(36, 3);\n          Time tStart  = Sinex::str2time(line,  6, FALSE/*zeroIsMaxTime*/, TRUE/*fourDigitYear*/);\n          Time tEnd    = Sinex::str2time(line, 21, TRUE /*zeroIsMaxTime*/, TRUE/*fourDigitYear*/);\n          if((tStart < timeEnd) && (tEnd > timeStart))\n            lines.push_back(Vector({String::toDouble(prn.substr(1)), String::toDouble(svn.substr(1)), std::max(timeStart, tStart).mjd(), std::min(timeEnd, tEnd).mjd(), chn}));\n        }\n    }\n\n    std::sort(lines.begin(), lines.end(), [](auto &x, auto &y) {if(x(0) != y(0)) return x(0)<y(0); return x(2)<y(2);});\n\n    logStatus<<\"write frequency number file <\"<<fileNamePrn2FrequencyNumber<<\">\"<<Log::endl;\n    OutFile file(fileNamePrn2FrequencyNumber);\n    file<<\"# PRN SVN  MJD start          MJD end           chn\"<<std::endl;\n    file<<\"# -------------------------------------------------\"<<std::endl;\n    for(const auto &line : lines)\n      file<<line(0)%\" %02i\"s<<line(1)%\"  %03i\"s<<line(2)%\" %18.10f\"s<<line(3)%\" %18.10f\"s<<line(4)%\" %4i\"s<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/gnss/sinexMetadata2SatelliteModel.cpp",
    "content": "/***********************************************/\n/**\n* @file sinexMetadata2SatelliteModel.cpp\n*\n* @brief Create satellite model from IGS SINEX metadata file.\n*\n* TODO: Consider time-variability in transmit power.\n*\n* @author Sebastian Strasser\n* @date 2018-09-17\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate \\configFile{outputfileSatelliteModel}{satelliteModel} from \\href{https://www.igs.org/mgex/metadata/#metadata}{IGS SINEX metadata format}.\n\nIf \\configFile{inputfileSatelliteModel}{satelliteModel} is provided it is used as a basis and values are updated from the metadata file.\n\nSee also \\program{SatelliteModelCreate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"inputOutput/fileSinex.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create satellite model from IGS SINEX metadata file.\n* @ingroup programsConversionGroup */\nclass SinexMetadata2SatelliteModel\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SinexMetadata2SatelliteModel, SINGLEPROCESS, \"Create satellite model from IGS SINEX metadata file.\", Conversion, Gnss)\n\n/***********************************************/\n\nvoid SinexMetadata2SatelliteModel::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName inNameSinexMetadata, inNameSatelliteModel, outNameSatelliteModel;\n    std::string svn;\n\n    readConfig(config, \"outputfileSatelliteModel\", outNameSatelliteModel, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileSinexMetadata\",   inNameSinexMetadata,   Config::MUSTSET,  \"\", \"IGS SINEX metadata file\");\n    readConfig(config, \"inputfileSatelliteModel\",  inNameSatelliteModel,  Config::OPTIONAL, \"\", \"base satellite model\");\n    readConfig(config, \"svn\",                      svn,                   Config::MUSTSET,  \"\", \"e.g. G040, R736, E204, C211\");\n    if(isCreateSchema(config)) return;\n\n    Sinex sinex;\n    readFileSinex(inNameSinexMetadata, sinex);\n\n    SatelliteModelPtr satellite(new SatelliteModel);\n    if(!inNameSatelliteModel.empty())\n      readFileSatelliteModel(inNameSatelliteModel, satellite);\n\n    satellite->satelliteName = svn;\n\n    // mass and mass changes\n    std::vector<Double> masses;\n    std::vector<Time> massTimes;\n    for(const auto &line : sinex.findBlock(\"SATELLITE/MASS\")->lines)\n      if(line.size() >= 45 && line.substr(1,4) == svn)\n      {\n        massTimes.push_back(Sinex::str2time(line, 6, FALSE/*zeroIsMaxTime*/, TRUE/*fourDigitYear*/));\n        masses.push_back(String::toDouble(line.substr(36, 9)));\n      }\n    if(masses.size())\n      satellite->mass = masses.back();\n    else\n      logWarning<<\"mass missing for \" + svn<<Log::endl;\n    if(masses.size() > 1)\n    {\n      auto iter = std::remove_if(satellite->modules.begin(), satellite->modules.end(), [&](SatelliteModelModulePtr module){ return module->type() == SatelliteModelModule::MASSCHANGE; });\n      satellite->modules.erase(iter, satellite->modules.end());\n      SatelliteModelModuleMassChange *module = new SatelliteModelModuleMassChange;\n      module->times = massTimes;\n      module->mass = masses;\n      satellite->modules.push_back(SatelliteModelModulePtr(module));\n    }\n\n    // antenna thrust\n    std::vector<std::string> powerLines = sinex.findBlock(\"SATELLITE/TX_POWER\")->lines;\n    auto powerIter = std::find_if(powerLines.rbegin(), powerLines.rend(), [&](const std::string &line){ return (line.size() >= 40 && line.substr(1,4) == svn); });\n    if(powerIter != powerLines.rend())\n    {\n      auto iter = std::remove_if(satellite->modules.begin(), satellite->modules.end(), [&](SatelliteModelModulePtr module){ return module->type() == SatelliteModelModule::ANTENNATHRUST; });\n      satellite->modules.erase(iter, satellite->modules.end());\n      SatelliteModelModuleAntennaThrust *module = new SatelliteModelModuleAntennaThrust;\n      module->thrust = Vector3d(0, 0, String::toInt(powerIter->substr(36, 4)));\n      satellite->modules.push_back(SatelliteModelModulePtr(module));\n    }\n    else\n      logWarning<<\"transmit power missing for \" + svn<<Log::endl;\n\n    // surfaces\n    if(!satellite->surfaces.size())\n    {\n      // Box-wing surfaces\n      satellite->surfaces.resize(8);\n      satellite->surfaces.at(0).normal = Vector3d( 0, 0, 1); //  Z (TOWARDS THE EARTH)\n      satellite->surfaces.at(1).normal = Vector3d( 0, 0,-1); // -Z\n      satellite->surfaces.at(2).normal = Vector3d( 0, 1, 0); //  Y (ALONG SOLAR PANELS BEAMS)\n      satellite->surfaces.at(3).normal = Vector3d( 0,-1, 0); // -Y\n      satellite->surfaces.at(4).normal = Vector3d( 1, 0, 0); //  X (ALONG BUS DIRECTION ALWAYS ILLUMINATED BY THE SUN)\n      satellite->surfaces.at(5).normal = Vector3d(-1, 0, 0); // -X\n      satellite->surfaces.at(6).normal = Vector3d( 0, 0, 1); // SOLAR PANELS\n      satellite->surfaces.at(7).normal = Vector3d( 0, 0,-1);\n\n      // Rotation of solar panels\n      SatelliteModelModuleSolarPanel *module = new SatelliteModelModuleSolarPanel;\n      satellite->modules.push_back(SatelliteModelModulePtr(module));\n      module->rotationAxis = Vector3d(0,1,0);\n      module->normal       = Vector3d(0,0,1);\n      module->indexSurface.push_back(6);\n      module->indexSurface.push_back(7);\n    }\n\n    logStatus<<\"write satellite model file <\"<<outNameSatelliteModel<<\">\"<<Log::endl;\n    writeFileSatelliteModel(outNameSatelliteModel, satellite);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/goce/goceXml2Gradiometer.cpp",
    "content": "/***********************************************/\n/**\n* @file goceXml2Gradiometer.cpp\n*\n* @brief Read ESA XML GOCE Data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-10-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ESA XML GOCE Data.\nThe \\config{outputfileGradiometer} is written as \\file{instrument file (GRADIOMETER)}{instrument}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/xml.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ESA XML GOCE Data.\n* @ingroup programsConversionGroup */\nclass GoceXml2Gradiometer\n{\n  void readFileGoceGradiometer(const FileName &fileName, GradiometerArc &arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GoceXml2Gradiometer, SINGLEPROCESS, \"read ESA XML GOCE Data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid GoceXml2Gradiometer::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<FileName> fileName;\n\n    readConfig(config, \"outputfileGradiometer\", outName,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",             fileName, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    GradiometerArc arc;\n    for(UInt i=0; i<fileName.size(); i++)\n    {\n      logStatus<<\"read file <\"<<fileName.at(i)<<\">\"<<Log::endl;\n      readFileGoceGradiometer(fileName.at(i), arc);\n    }\n\n    logStatus<<\"write gradiometer file <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GoceXml2Gradiometer::readFileGoceGradiometer(const FileName &fileName, GradiometerArc &arc)\n{\n  try\n  {\n    GradiometerEpoch epoch;\n\n    InFile     file(fileName);\n    XmlNodePtr rootNode = XmlNode::read(file);\n    XmlNodePtr dataNode = getChild(rootNode, \"Data_Block\", TRUE);\n    XmlNodePtr ggtNode  = getChild(dataNode, \"EGG_GGT_DS\", TRUE);\n\n    UInt epochCount = childCount(ggtNode, \"EGG_GGT_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(ggtNode, \"EGG_GGT_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr tnsNode = getChild(epochNode, \"Gravity_Grad_Tensor\", TRUE);\n      std::string tnsStr;\n      readXml(tnsNode, \"U_G\", tnsStr, TRUE);\n\n      std::stringstream ss(tnsStr);\n      ss>>epoch.gravityGradient.xx();\n      ss>>epoch.gravityGradient.yy();\n      ss>>epoch.gravityGradient.zz();\n      ss>>epoch.gravityGradient.xy();\n      ss>>epoch.gravityGradient.xz();\n      ss>>epoch.gravityGradient.yz();\n\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/goce/goceXml2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file goceXml2Orbit.cpp\n*\n* @brief Read ESA XML GOCE Data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-10-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ESA XML GOCE Data.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/xml.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ESA XML GOCE Data.\n* @ingroup programsConversionGroup */\nclass GoceXml2Orbit\n{\n  void readFileGoceOrbit(const FileName &fileName, OrbitArc &arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GoceXml2Orbit, SINGLEPROCESS, \"read ESA XML GOCE Data\", Conversion, Orbit, Instrument)\n\n/***********************************************/\n\nvoid GoceXml2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<FileName> fileName;\n    EarthRotationPtr earthRotation;\n\n    readConfig(config, \"outputfileOrbit\", outName,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::OPTIONAL, \"file\", \"rotation from TRF to CRF\");\n    readConfig(config, \"inputfile\",       fileName,      Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc orbit;\n    for(UInt i=0; i<fileName.size(); i++)\n    {\n      logStatus<<\"read file <\"<<fileName.at(i)<<\">\"<<Log::endl;\n      readFileGoceOrbit(fileName.at(i), orbit);\n    }\n\n    if(earthRotation)\n    {\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(orbit.size(), [&](UInt i)\n      {\n        const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(orbit.at(i).time));\n        const Vector3d omega    = earthRotation->rotaryAxis(orbit.at(i).time);\n        orbit.at(i).position = rotation.rotate(orbit.at(i).position);\n        orbit.at(i).velocity = rotation.rotate(orbit.at(i).velocity) + crossProduct(omega, orbit.at(i).position);\n      });\n    }\n\n    logStatus<<\"write orbit data to file <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, orbit);\n    Arc::printStatistics(orbit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GoceXml2Orbit::readFileGoceOrbit(const FileName &fileName, OrbitArc &arc)\n{\n  try\n  {\n    OrbitEpoch epoch;\n\n    InFile     file(fileName);\n    XmlNodePtr rootNode = XmlNode::read(file);\n    XmlNodePtr sstNode  = getChild(rootNode, \"SST_PSO_2\",  TRUE);\n    sstNode  = getChild(sstNode, \"SST_PRD_2\",  TRUE);\n    sstNode  = getChild(sstNode, \"List_of_SP3c_Records\", TRUE);\n\n    UInt epochCount = childCount(sstNode, \"SP3c_Record\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(sstNode, \"SP3c_Record\", TRUE);\n\n      UInt   year, month, day, hour, min;\n      Double sec = 0;\n      XmlNodePtr timeNode  = getChild(epochNode, \"Time_Information\", TRUE);\n      timeNode  = getChild(timeNode,  \"GPS_Time\",  TRUE);\n      timeNode  = getChild(timeNode,  \"Start\",     TRUE);\n      timeNode  = getChild(timeNode,  \"Gregorian\", TRUE);\n      readXml(timeNode, \"Year\",         year,  TRUE);\n      readXml(timeNode, \"Month\",        month, TRUE);\n      readXml(timeNode, \"Day_of_Month\", day,   TRUE);\n      readXml(timeNode, \"Hour\",         hour,  TRUE);\n      readXml(timeNode, \"Minute\",       min,   TRUE);\n      readXml(timeNode, \"Second\",       sec,   TRUE);\n      epoch.time = date2time(year, month, day, hour, min, sec);\n\n      XmlNodePtr satNode = getChild(getChild(epochNode, \"List_of_Satellite_IDs\", TRUE), \"L15\", TRUE);\n      XmlNodePtr posNode = getChild(satNode, \"Position\", TRUE);\n      readXml(posNode, \"X\", epoch.position.x(),  TRUE);\n      readXml(posNode, \"Y\", epoch.position.y(),  TRUE);\n      readXml(posNode, \"Z\", epoch.position.z(),  TRUE);\n      epoch.position *= 1e3;\n      XmlNodePtr velNode = getChild(satNode, \"Velocity\", TRUE);\n      readXml(velNode, \"X\", epoch.velocity.x(),  TRUE);\n      readXml(velNode, \"Y\", epoch.velocity.y(),  TRUE);\n      readXml(velNode, \"Z\", epoch.velocity.z(),  TRUE);\n      epoch.velocity *= 0.1;\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n// void GoceXml2Orbit::readFileGoceOrbit(const FileName &fileName, OrbitArc &arc)\n// {\n//   try\n//   {\n//     OrbitEpoch epoch;\n//\n//     XmlNodePtr rootNode = XmlNode::readFile(fileName);\n//     XmlNodePtr dataNode = getChild(rootNode, \"Data_Block\", TRUE);\n//     XmlNodePtr sstNode  = getChild(dataNode, \"SST_PVT_DS\", TRUE);\n//\n//     UInt epochCount = childCount(sstNode, \"SST_PVT_1i\", TRUE);\n//     for(UInt i=0; i<epochCount; i++)\n//     {\n//       XmlNodePtr epochNode = getChild(sstNode, \"SST_PVT_1i\", TRUE);\n//       Double t = 0;\n//       readXml(epochNode, \"Tt_GPS\", t, TRUE);\n//       epoch.time = seconds2time(t) + date2time(1980,1,6);\n//\n//       XmlNodePtr posNode = getChild(epochNode, \"SST_Pos\", TRUE);\n//       std::string posStr;\n//       readXml(posNode, \"Position\", posStr, TRUE);\n//       std::stringstream ss(posStr);\n//       ss>>epoch.position.x()>>epoch.position.y()>>epoch.position.z();\n//\n//       std::string velStr;\n//       readXml(epochNode, \"SST_Vel\", velStr, TRUE);\n//       std::stringstream ss2(velStr);\n//       ss2>>epoch.velocity.x()>>epoch.velocity.y()>>epoch.velocity.z();\n//\n//       arc.push_back(epoch);\n//     }\n//   }\n//   catch(std::exception &e)\n//   {\n//     GROOPS_RETHROW(e)\n//   }\n// }\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/goce/goceXml2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file goceXml2StarCamera.cpp\n*\n* @brief Read ESA XML GOCE Data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-10-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ESA XML GOCE Data.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/xml.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ESA XML GOCE Data.\n* @ingroup programsConversionGroup */\nclass GoceXml2StarCamera\n{\n  void readFileGoceStarCamera(const FileName &fileName, StarCameraArc &arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GoceXml2StarCamera, SINGLEPROCESS, \"read ESA XML GOCE Data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid GoceXml2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<FileName> fileName;\n\n    readConfig(config, \"outputfileStarCamera\", outName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\", fileName, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arc;\n    for(UInt i=0; i<fileName.size(); i++)\n    {\n      logStatus<<\"read file '\"<<fileName.at(i)<<\"'\"<<Log::endl;\n      readFileGoceStarCamera(fileName.at(i), arc);\n    }\n\n    // Daten speichern\n    // ---------------\n    logStatus<<\"write gradiometer file <\"<<outName<<\">\"<<Log::endl;\n    std::list<Arc> arcList; arcList.push_back(arc);\n    InstrumentFile::write(outName, arcList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GoceXml2StarCamera::readFileGoceStarCamera(const FileName &fileName, StarCameraArc &arc)\n{\n  try\n  {\n    StarCameraEpoch epoch;\n\n    InFile     file(fileName);\n    XmlNodePtr rootNode = XmlNode::read(file);\n    XmlNodePtr dataNode = getChild(rootNode, \"Data_Block\", TRUE);\n    XmlNodePtr ggtNode  = getChild(dataNode, \"EGG_IAQ_DS\", TRUE);\n\n    UInt epochCount = childCount(ggtNode, \"EGG_IAQ_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(ggtNode, \"EGG_IAQ_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr tnsNode = getChild(epochNode, \"Corr_Quat\", TRUE);\n      std::string tnsStr;\n      readXml(tnsNode, \"Q_Grad\", tnsStr, TRUE);\n\n      std::stringstream ss(tnsStr);\n      Vector q(4);\n      ss>>q(1)>>q(2)>>q(3)>>q(0);\n      epoch.rotary = Rotary3d(q);\n\n      if(arc.size() && (epoch.time <= arc.at(arc.size()-1).time))\n        {logWarning<<\"(epoch.time <= arc.at(arc.size()-1).time)\"<<Log::endl; continue;}\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/goce/goceXmlEggNom1b.cpp",
    "content": "/***********************************************/\n/**\n* @file goceXmlEggNom1b.cpp\n*\n* @brief Read ESA XML GOCE Data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-10-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ESA XML GOCE Data.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/xml.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ESA XML GOCE Data.\n* @ingroup programsConversionGroup */\nclass GoceXmlEggNom1b\n{\n  void readGradiometer   (XmlNodePtr &dataNode, GradiometerArc    &arc);\n  void readAccelerometer (XmlNodePtr &dataNode, AccelerometerArc  &arc);\n  void readStarCamera    (XmlNodePtr &dataNode, StarCameraArc     &arc);\n  void readAngularRate   (XmlNodePtr &dataNode, AccelerometerArc  &arc);\n  void readAngularAcc    (XmlNodePtr &dataNode, AccelerometerArc  &arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GoceXmlEggNom1b, SINGLEPROCESS, \"Read ESA XML GOCE Data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid GoceXmlEggNom1b::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName sggName, accName, scaName, angRateName, angAccName;\n    std::vector<FileName> fileNames;\n\n    readConfig(config, \"outputfileGradiometer\",    sggName,       Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileAccelerometer\",  accName,       Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileStarCamera\",     scaName,       Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileAngularRate\",    angRateName,   Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileAngularAcc\",     angAccName,    Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfile\",                fileNames,     Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    GradiometerArc     gradiometerArc;\n    AccelerometerArc   accelerometerArc;\n    StarCameraArc      starCameraArc;\n    AccelerometerArc   angRateArc;\n    AccelerometerArc   angAccArc;\n\n    for(auto &fileName : fileNames)\n    {\n      logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n      InFile     file(fileName);\n      XmlNodePtr rootNode = XmlNode::read(file);\n      XmlNodePtr dataNode = getChild(rootNode, \"Data_Block\", TRUE);\n\n      if(!sggName.empty())     readGradiometer   (dataNode, gradiometerArc);\n      if(!accName.empty())     readAccelerometer (dataNode, accelerometerArc);\n      if(!scaName.empty())     readStarCamera    (dataNode, starCameraArc);\n      if(!angRateName.empty()) readAngularRate   (dataNode, angRateArc);\n      if(!angAccName.empty())  readAngularAcc    (dataNode, angAccArc);\n    }\n\n    // Daten speichern\n    // ---------------\n    if(!sggName.empty())\n    {\n      logStatus<<\"write gradiometer file <\"<<sggName<<\">\"<<Log::endl;\n      InstrumentFile::write(sggName, gradiometerArc);\n      Arc::printStatistics(gradiometerArc);\n    }\n\n    if(!accName.empty())\n    {\n      logStatus<<\"write accelerometer file <\"<<accName<<\">\"<<Log::endl;\n      InstrumentFile::write(accName, accelerometerArc);\n      Arc::printStatistics(accelerometerArc);\n    }\n\n    if(!scaName.empty())\n    {\n      logStatus<<\"write starCamera file <\"<<scaName<<\">\"<<Log::endl;\n      InstrumentFile::write(scaName, starCameraArc);\n      Arc::printStatistics(starCameraArc);\n    }\n\n    if(!angRateName.empty())\n    {\n      logStatus<<\"write angular rate file <\"<<angRateName<<\">\"<<Log::endl;\n      InstrumentFile::write(angRateName, angRateArc);\n      Arc::printStatistics(angRateArc);\n    }\n\n    if(!angRateName.empty())\n    {\n      logStatus<<\"write angular acceleration file <\"<<angAccName<<\">\"<<Log::endl;\n      InstrumentFile::write(angAccName, angAccArc);\n      Arc::printStatistics(angAccArc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid GoceXmlEggNom1b::readGradiometer(XmlNodePtr &dataNode, GradiometerArc &arc)\n{\n  try\n  {\n    GradiometerEpoch epoch;\n\n    XmlNodePtr node  = getChild(dataNode, \"EGG_GGT_DS\", TRUE);\n\n    UInt epochCount = childCount(node, \"EGG_GGT_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(node, \"EGG_GGT_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr node2 = getChild(epochNode, \"Gravity_Grad_Tensor\", TRUE);\n      std::string tnsStr;\n      readXml(node2, \"U_G\", tnsStr, TRUE);\n\n      std::stringstream ss(tnsStr);\n      ss>>epoch.gravityGradient.xx();\n      ss>>epoch.gravityGradient.yy();\n      ss>>epoch.gravityGradient.zz();\n      ss>>epoch.gravityGradient.xy();\n      ss>>epoch.gravityGradient.xz();\n      ss>>epoch.gravityGradient.yz();\n\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logWarning<<\"In GoceXmlEggNom1b::readGradiometer:\\n\"<<e.what()<<\" continue...\"<<Log::endl;\n  }\n}\n\n/***********************************************/\n\nvoid GoceXmlEggNom1b::readAccelerometer(XmlNodePtr &dataNode, AccelerometerArc &arc)\n{\n  try\n  {\n    AccelerometerEpoch epoch;\n\n    XmlNodePtr node  = getChild(dataNode, \"EGG_CCD_DS\", TRUE);\n\n    UInt epochCount = childCount(node, \"EGG_CCD_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(node, \"EGG_CCD_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr node2 = getChild(epochNode, \"Acc_Ccm\", TRUE);\n      std::string xStr, yStr, zStr;\n      readXml(node2, \"X\", xStr, TRUE);\n      readXml(node2, \"Y\", yStr, TRUE);\n      readXml(node2, \"Z\", zStr, TRUE);\n\n      Double tmp;\n      std::stringstream ssx(xStr);\n      std::stringstream ssy(yStr);\n      std::stringstream ssz(zStr);\n      ssx>>epoch.acceleration.x()>>tmp>>tmp;\n      ssy>>tmp>>epoch.acceleration.y()>>tmp;\n      ssz>>tmp>>tmp>>epoch.acceleration.z();\n\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logWarning<<\"In GoceXmlEggNom1b::readAccelerometer:\\n\"<<e.what()<<\" continue...\"<<Log::endl;\n  }\n}\n\n/***********************************************/\n\nvoid GoceXmlEggNom1b::readStarCamera(XmlNodePtr &dataNode, StarCameraArc &arc)\n{\n  try\n  {\n    StarCameraEpoch epoch;\n\n    XmlNodePtr node       = getChild(dataNode, \"EGG_IAQ_DS\", TRUE);\n    UInt       epochCount = childCount(node, \"EGG_IAQ_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(node, \"EGG_IAQ_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr node2 = getChild(epochNode, \"Corr_Quat\", TRUE);\n      std::string str;\n      readXml(node2, \"Q_Grad\", str, TRUE);\n\n      Vector q(4);\n      std::stringstream ss(str);\n      ss>>q(1)>>q(2)>>q(3)>>q(0);\n      epoch.rotary = Rotary3d(q);\n\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logWarning<<\"In GoceXmlEggNom1b::readStarCamera:\\n\"<<e.what()<<\" continue...\"<<Log::endl;\n  }\n}\n\n/***********************************************/\n\nvoid GoceXmlEggNom1b::readAngularRate(XmlNodePtr &dataNode,  AccelerometerArc &arc)\n{\n  try\n  {\n    AccelerometerEpoch epoch;\n\n    XmlNodePtr node       = getChild(dataNode, \"EGG_GAR_DS\", TRUE);\n    UInt       epochCount = childCount(node, \"EGG_GAR_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(node, \"EGG_GAR_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr node2 = getChild(epochNode, \"Corr_Est_Ang_Rate\", TRUE);\n      std::string text;\n      readXml(node2, \"Iar_Est\", text, TRUE);\n\n      std::stringstream ss(text);\n      ss>>epoch.acceleration.x();\n      ss>>epoch.acceleration.y();\n      ss>>epoch.acceleration.z();\n\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logWarning<<\"In GoceXmlEggNom1b::readAngularRate:\\n\"<<e.what()<<\" continue...\"<<Log::endl;\n  }\n}\n\n/***********************************************/\n\nvoid GoceXmlEggNom1b::readAngularAcc(XmlNodePtr &dataNode,  AccelerometerArc &arc)\n{\n  try\n  {\n    AccelerometerEpoch epoch;\n\n    XmlNodePtr node       = getChild(dataNode, \"EGG_CGA_DS\", TRUE);\n    UInt       epochCount = childCount(node, \"EGG_CGA_1i\", TRUE);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      XmlNodePtr epochNode = getChild(node, \"EGG_CGA_1i\", TRUE);\n      Double t = 0;\n      readXml(epochNode, \"Tt_GPS\", t, TRUE);\n      epoch.time = seconds2time(t) + date2time(1980,1,6);\n\n      XmlNodePtr node2 = getChild(epochNode, \"Cal_Grad_Ang_Acc\", TRUE);\n      std::string text;\n      readXml(node2, \"CGA\", text, TRUE);\n\n      std::stringstream ss(text);\n      ss>>epoch.acceleration.x();\n      ss>>epoch.acceleration.y();\n      ss>>epoch.acceleration.z();\n\n      arc.push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    logWarning<<\"In GoceXmlEggNom1b::readAngularAcc:\\n\"<<e.what()<<\" continue...\"<<Log::endl;\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/accelerometer2GraceL1b.cpp",
    "content": "/***********************************************/\n/**\n* @file accelerometer2GraceL1b.cpp\n*\n* @brief Read GROOPS accelerometer data and write GRACE L1B data.\n*\n* @author Felix Oehlinger\n* @date 2025-01-21\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts accelerometer data from the \\file{instrument file (ACCELEROMETER)}{instrument}\nformat into GRACE SDS format.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, \\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GROOPS accelerometer data and write GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass Accelerometer2GraceL1b\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Accelerometer2GraceL1b, SINGLEPROCESS, \"convert GROOPS ACC data into SDS L1B data\", Conversion, Grace, Instrument)\n\n/*************************************************************/\n\nvoid Accelerometer2GraceL1b::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut;\n    FileName    fileNameHeader, fileNameAcc, fileNameAng, fileNameFlags;\n    std::string satelliteId;\n\n    readConfig(config, \"outputfile\",                    fileNameOut,    Config::MUSTSET,  \"\", \"ACT1B\");\n    readConfig(config, \"inputfileHeader\",               fileNameHeader, Config::OPTIONAL, \"\", \"YAML Header, {epochmin}, {epochmax}, {epochcount} available\");\n    readConfig(config, \"inputfileAccelerometer\",        fileNameAcc,    Config::MUSTSET,  \"\", \"ACCELEROMETER\");\n    readConfig(config, \"inputfileAngularAccelerometer\", fileNameAng,    Config::OPTIONAL, \"\", \"ACCELEROMETER\");\n    readConfig(config, \"inputfileFlags\",                fileNameFlags,  Config::OPTIONAL, \"\", \"MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z)\");\n    readConfig(config, \"satelliteId\",                   satelliteId,    Config::MUSTSET,  \"\", \"A, B, C or D\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"write SDS output <\"<<fileNameOut<<\">\"<<Log::endl;\n    AccelerometerArc accArc   = InstrumentFile::read(fileNameAcc);\n    AccelerometerArc angArc   = InstrumentFile::read(fileNameAng);\n    MiscValuesArc    flagsArc = InstrumentFile::read(fileNameFlags);\n    Arc::checkSynchronized({accArc, angArc, flagsArc});\n\n    OutFile file(fileNameOut);\n    if(!fileNameHeader.empty())\n    {\n      VariableList varList = config.getVarList();\n      addDataVariables(\"epoch\", accArc.times(), varList);\n\n      InFile fileHeader(fileNameHeader);\n      std::string line;\n      while(std::getline(fileHeader, line))\n        file<<StringParser::parse(line, varList)<<std::endl;\n    }\n    else\n      file<<\"# End of YAML header\"<<std::endl;\n\n    Single::forEach(accArc.size(), [&](UInt i)\n    {\n      Vector3d acc, ang, res;\n      Byte     qualflg  = 0;\n\n      acc = accArc.at(i).acceleration;\n      if(angArc.size())\n        ang = angArc.at(i).acceleration;\n      if(flagsArc.size())\n      {\n        qualflg  = static_cast<Byte>(flagsArc.at(i).values.at(0));\n        res      = Vector3d(flagsArc.at(i).values.row(1, 3));\n      }\n\n      file<<static_cast<UInt>(std::round((accArc.at(i).time-mjd2time(51544.5)).seconds()))<<\" \"<<satelliteId;\n      file<<acc.x()%\" %.16g\"s<<acc.y()%\" %.16g\"s<<acc.z()%\" %.16g\"s;\n      file<<ang.x()%\" %.16g\"s<<ang.y()%\" %.16g\"s<<ang.z()%\" %.16g\"s;\n      file<<res.x()%\" %.16g\"s<<res.y()%\" %.16g\"s<<res.z()%\" %.16g  \"s;\n      for(UInt k=8; k-->0;)\n        file<<(((qualflg>>k) & 1) ? '1' : '0');\n      file<<std::endl;\n    });\n  }\n  catch(std::exception &e)\n  {\n      GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/fileGrace.cpp",
    "content": "/***********************************************/\n/**\n* @file fileGrace.cpp\n*\n* @brief GRACE L1A/L1B files (isBinary/ascii).\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-17\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/file.h\"\n#include \"fileGrace.h\"\n\n/***********************************************/\n\nFileInGrace::FileInGrace(const FileName &fileName, UInt &numberOfRecords)\n{\n  try\n  {\n    numberOfRecords = 0;\n\n    try\n    {\n      file.open(fileName, std::ios::in|std::ios::binary);\n      file.exceptions(std::ios::badbit | std::ios::failbit);\n    }\n    catch(std::exception &/*e*/)\n    {\n      logError<<\"error by opening file <\"<<fileName<<\">: continue...\"<<Log::endl;\n      return;\n    }\n\n    std::string line;\n    while(std::getline(file, line))\n    {\n      // GRACE\n      if(line.find(\"NUMBER OF DATA RECORDS\") == 0)\n        numberOfRecords = String::toInt(line.substr(31, 10));\n      if(line.find(\"FILE FORMAT\") == 0)\n        isBinary = (String::toInt(line.substr(31, 2)) == 0);\n      if(line.find(\"END OF HEADER\") == 0)\n        break;\n      // GRACE-FO\n      if(line.find(\"    num_records\") == 0)\n      {\n        numberOfRecords = String::toInt(line.substr(16, 10));\n        isBinary = FALSE;\n      }\n      if(line.find(\"# End of YAML header\") == 0)\n        break;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid FileInGrace::changeByteOrder(char *bytes, UInt n) const\n{\n  for(UInt i=0; i<n/2; i++)\n    std::swap(bytes[i], bytes[n-i-1]);\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Double &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Float &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Int32 &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Int64 &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(UInt16 &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(UInt32 &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(UInt64 &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Char &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(&x), sizeof(x));\n      changeByteOrder(reinterpret_cast<char*>(&x), sizeof(x));\n    }\n    else\n      file>>x;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Int8 &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      Byte b;\n      file.read(&b, 1);\n      x.value = b;\n    }\n    else\n      file>>x.value;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(const Flag &x)\n{\n  try\n  {\n    if(isBinary)\n    {\n      file.read(reinterpret_cast<char*>(x.value), x.size);\n      changeByteOrder(reinterpret_cast<char*>(x.value), x.size);\n    }\n    else\n    {\n      UInt64 v = 0;\n      Byte   c;\n      for(UInt i=0; i<8*x.size; i++)\n      {\n        file>>c;\n        v = (v<<1) + c-'0';\n      }\n      switch(x.size)\n      {\n        case 1 : *reinterpret_cast<Byte  *>(x.value) = v; break;\n        case 2 : *reinterpret_cast<UInt16*>(x.value) = v; break;\n        case 4 : *reinterpret_cast<UInt32*>(x.value) = v; break;\n        case 8 : *reinterpret_cast<UInt64*>(x.value) = v; break;\n        default:\n          throw(Exception(\"something strange\"));\n      };\n    }\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nFileInGrace &FileInGrace::operator>>(Vector3d &vec)\n{\n  try\n  {\n    *this>>vec.x()>>vec.y()>>vec.z();\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/fileGrace.h",
    "content": "/***********************************************/\n/**\n* @file fileGrace.h\n*\n* @brief GRACE L1A/L1B files (binary/ascii).\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-12-17\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_FILEGRACE__\n#define __GROOPS_FILEGRACE__\n\n#include \"base/vector3d.h\"\n#include \"inputOutput/file.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GRACE L1A/L1B files (binary/ascii).\n* @ingroup programsConversionGroup\n*/\nclass FileInGrace\n{\n  InFile file;\n  Bool   isBinary;\n\n  // change the byte order for n Bytes (e.g. Intel <-> SUN systems)\n  void changeByteOrder(char *bytes, UInt n) const;\n\npublic:\n  class Int8\n  {\n  public:\n    Int value;\n    operator Byte() {return value;}\n  };\n\n  class Flag\n  {\n  public:\n    void *value;\n    std::size_t size;\n    Flag(void *x, std::size_t s) : value(x), size(s) {}\n  };\n\n  template<typename T> static Flag flag(T &x) {return Flag(&x, sizeof(x));}\n\n  FileInGrace(const FileName &fileName, UInt &numberOfRecords);\n\n  FileInGrace &operator>>(Double &x);\n  FileInGrace &operator>>(Float  &x);\n  FileInGrace &operator>>(Int32  &x);\n  FileInGrace &operator>>(Int64  &x);\n  FileInGrace &operator>>(UInt16 &x);\n  FileInGrace &operator>>(UInt32 &x);\n  FileInGrace &operator>>(UInt64 &x);\n  FileInGrace &operator>>(Char   &x);\n  FileInGrace &operator>>(Int8   &x);\n  FileInGrace &operator>>(const Flag &x);\n  FileInGrace &operator>>(Vector3d &vec);\n};\n\n/**********************************************************************/\n\n#endif /* __GROOPS__ */\n\n"
  },
  {
    "path": "source/programs/conversion/grace/grace2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file grace2PotentialCoefficients.cpp\n*\n* @brief read GRACE data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts potential coefficients from the GRACE SDS format\ninto \\file{potential coefficients file}{potentialCoefficients}.\nThe program supports file formats for RL04 to RL06.\n\nWithin the program, the variables \\verb|epochStart|, \\verb|epochEnd| and \\verb|epochMid|\nare populated with the corresponding time-stamps in the file.\nThese can be used in to \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\nto auto-generate the file name.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileSphericalHarmonics.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read CSR GRACE data.\n* @ingroup programsConversionGroup */\nclass Grace2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Grace2PotentialCoefficients, SINGLEPROCESS, \"read GRACE data\", Conversion, Grace, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Grace2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n    readConfig(config, \"outputfilePotentialCoefficients\", fileNameOut, Config::MUSTSET, \"\", \"variables: epochStart, epochEnd, epochMid\");\n    readConfig(config, \"inputfile\",                       fileNameIn,  Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n\n    Double  GM = 0.3986004415e15;\n    Double  R  = 0.6378136460e07;\n    Matrix  cnm, snm, sigma2cnm, sigma2snm;\n    Time    timeStart = date2time(9999,1,1), timeEnd;\n\n    Bool seekR = FALSE;\n    Bool seekGM = FALSE;\n    Bool seekDegree = FALSE;\n\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(line.find(\"dimension\") != std::string::npos)\n        seekDegree=TRUE;\n      if( (line.find(\"degree\") != std::string::npos) && seekDegree )\n      {\n        auto start_search = line.find(\":\");\n        std::stringstream ss(line.substr(start_search+1));\n        UInt degree = INFINITYDEGREE;\n        ss>>degree;\n        cnm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        snm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2cnm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2snm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        seekDegree = FALSE;\n      }\n\n      if(line.find(\"SHM \")==0)\n      {\n        UInt degree = String::toInt(line.substr(6, 5));\n        cnm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        snm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2cnm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2snm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      }\n      if(line.find(\"EARTH \")==0)\n      {\n        GM = String::toDouble(line.substr(6, 16));\n        R  = String::toDouble(line.substr(23, 16));\n      }\n\n      if(line.find(\"mean_equator_radius\") != std::string::npos)\n        seekR = TRUE;\n      if( (line.find(\"value\") != std::string::npos) && seekR )\n      {\n        auto start_search = line.find(\":\");\n        std::stringstream ss(line.substr(start_search+1));\n        ss>>R;\n        seekR = FALSE;\n      }\n\n      if(line.find(\"earth_gravity_param\") != std::string::npos)\n        seekGM = TRUE;\n      if( (line.find(\"value\") != std::string::npos) && seekGM )\n      {\n        auto start_search = line.find(\":\");\n        std::stringstream ss(line.substr(start_search+1));\n        ss>>GM;\n        seekGM = FALSE;\n      }\n\n      if((line.find(\"GRCOEF\")==0)||(line.find(\"GRCOF2\")==0))\n      {\n        const UInt n    = String::toInt(line.substr(6, 5));\n        const UInt m    = String::toInt(line.substr(11, 5));\n        cnm(n,m)        = String::toDouble(line.substr(17, 18));\n        snm(n,m)        = String::toDouble(line.substr(36, 18));\n        sigma2cnm(n,m)  = String::toDouble(line.substr(55, 10));\n        sigma2snm(n,m)  = String::toDouble(line.substr(66, 10));\n        sigma2cnm(n,m) *= sigma2cnm(n,m);\n        sigma2snm(n,m) *= sigma2snm(n,m);\n\n        const UInt yearStart  = String::toInt(line.substr(77, 4));\n        const UInt monthStart = String::toInt(line.substr(81, 2));\n        const UInt dayStart   = String::toInt(line.substr(83, 2));\n        timeStart = std::min(timeStart, date2time(yearStart, monthStart, dayStart));\n\n        const UInt yearEnd    = String::toInt(line.substr(91, 4));\n        const UInt monthEnd   = String::toInt(line.substr(95, 2));\n        const UInt dayEnd     = String::toInt(line.substr(97, 2));\n        timeEnd = std::max(timeEnd, date2time(yearEnd, monthEnd, dayEnd));\n      }\n    }\n\n    VariableList fileNameVariableList;\n    fileNameVariableList.setVariable(\"epochStart\", timeStart.mjd());\n    fileNameVariableList.setVariable(\"epochEnd\",   timeEnd.mjd());\n    fileNameVariableList.setVariable(\"epochMid\",   (0.5*timeStart+0.5*timeEnd).mjd());\n    logStatus<<\"writing potential coefficients to file <\"<<fileNameOut(fileNameVariableList)<<\">\"<<Log::endl;\n    writeFileSphericalHarmonics(fileNameOut(fileNameVariableList), SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceAccelerometer2L1bAscii.cpp",
    "content": "/***********************************************/\n/**\n* @file graceAccelerometer2L1bAscii.cpp\n*\n* @brief Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\n*\n* @author Andreas Kvas\n* @date 2020-06-10\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\n* Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\n* @ingroup programsConversionGroup */\nclass GraceAccelerometer2L1bAscii\n{\nprivate:\n  std::string headerVariables() const;\n  std::string headerAttributes(UInt epochCount, const Time &t0, const Time &timeStart, const Time &timeEnd,\n                               const std::vector<std::string> &globalAttributes) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceAccelerometer2L1bAscii, SINGLEPROCESS, \"Convert GROOPS accelerometer files to the GRACE SDS L1B ASCII format.\", Conversion)\n\n/***********************************************/\n\nvoid GraceAccelerometer2L1bAscii::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameAcc;\n    std::string graceId;\n    std::vector<std::string> globalAttributes;\n\n    readConfig(config, \"outputfileAscii\",        fileNameOut,      Config::MUSTSET,  \"\", \"ASCII outputfile\");\n    readConfig(config, \"inputfileAccelerometer\", fileNameAcc,      Config::MUSTSET,  \"\", \"GROOPS acceleromter file\");\n    readConfig(config, \"satelliteIdentifier\",    graceId,          Config::MUSTSET,  \"\", \"satellite identifier (A or B for GRACE, C or D for GRACE-FO)\");\n    readConfig(config, \"globalAttributes\",       globalAttributes, Config::OPTIONAL, \"\", \"additional attributes as 'key: value' pairs\");\n    if(isCreateSchema(config)) return;\n\n    AccelerometerArc accelerometer = InstrumentFile::read(fileNameAcc);\n\n    const UInt epochCount = accelerometer.size();\n    Time timeStart = accelerometer.at(0).time;\n    Time timeEnd = accelerometer.at(epochCount-1).time;\n\n    Time t0 = date2time(2000, 1, 1, 12);\n\n    OutFile file(fileNameOut);\n    file<<headerAttributes(epochCount, t0, timeStart, timeEnd, globalAttributes);\n    file<<headerVariables()<<std::endl;\n    file<<\"# End of YAML header\"<<std::endl;;\n    for(UInt k = 0; k < epochCount; k++)\n    {\n      Int t = static_cast<Int>(std::round((accelerometer.at(k).time - t0).seconds()));\n      Vector3d acc = accelerometer.at(k).acceleration;\n      file<<t<<\" \"<<graceId<<\" \"<<acc.x()%\"%17.15e\"s<<\" \"<<acc.y()%\"%17.15e\"s<<\" \"<<acc.z()%\"%17.15e\"s;\n      file<<\" 0 0 0 \"<<0.0%\"%17.15e\"s<<\" \"<<0.0%\"%17.15e\"s<<\" \"<<0.0%\"%17.15e\"s<<\" 00000000\"<<std::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::string GraceAccelerometer2L1bAscii::headerAttributes(UInt epochCount, const Time &t0, const Time &timeStart, const Time &timeEnd,\n                                                          const std::vector<std::string> &globalAttributes) const\n{\n  std::stringstream ss;\n  ss<<\"header:\"<<std::endl;\n  ss<<\"  dimensions:\"<<std::endl;\n  ss<<\"    num_records: \"<<epochCount<<std::endl;\n  ss<<\"  global_attributes:\"<<std::endl;\n  ss<<\"    time_coverage_start: \"<<timeStart%\"%DT%H:%M:%SZ\"s<<std::endl;\n  ss<<\"    time_coverage_stop: \"<<timeEnd%\"%DT%H:%M:%SZ\"s<<std::endl;\n  for(auto s : globalAttributes)\n    ss<<\"    \"<<s<<std::endl;\n  ss<<\"non-standard_attributes:\"<<std::endl;\n  ss<<\"  epoch_time: \"<<t0%\"%DT%H:%M:%SZ\"s<<std::endl;\n  ss<<\"  start_time_epoch_secs: \"<<(timeStart-t0).seconds()%\"%i\"s<<std::endl;\n  ss<<\"  stop_time_epoch_secs: \"<<(timeEnd-t0).seconds()%\"%i\"s<<std::endl;\n\n  return ss.str();\n}\n\n/***********************************************/\n\nstd::string GraceAccelerometer2L1bAscii::headerVariables() const\n{\n  std::string header_string =\nR\"(variables:\n  - gps_time:\n      comment: 1st column\n      coverage_content_type: referenceInformation\n      long_name: Continuous seconds past 01-Jan-2000 11:59:47 UTC\n      units: second\n  - GRACEFO_id:\n      comment: 2nd column\n      coverage_content_type: referenceInformation\n      long_name: satellite identifier\n      units: char\n      valid_range: A, B, C,D\n      value_meanings:\n        - A = GRACE 1 (GRACE A)\n        - B = GRACE 1 (GRACE B)\n        - C = GRACE-FO 1 (GRACE C)\n        - D = GRACE-FO 2 (GRACE D)\n  - lin_accl_x:\n      comment: 3rd column\n      coverage_content_type: physicalMeasurement\n      long_name: Linear acceleration along X-axis\n      units: m/s2\n  - lin_accl_y:\n      comment: 4th column\n      coverage_content_type: physicalMeasurement\n      long_name: Linear acceleration along Y-axis\n      units: m/s2\n  - lin_accl_z:\n      comment: 5th column\n      coverage_content_type: physicalMeasurement\n      long_name: Linear acceleration along Z-axis\n      units: m/s2\n  - ang_accl_x:\n      comment: 6th column\n      coverage_content_type: physicalMeasurement\n      long_name: Angular acceleration about X-axis, 0 for ACT1B\n      units: rad/s2\n  - ang_accl_y:\n      comment: 7th column\n      coverage_content_type: physicalMeasurement\n      long_name: Angular acceleration about Y-axis, 0 for ACT1B\n      units: rad/s2\n  - ang_accl_z:\n      comment: 8th column\n      coverage_content_type: physicalMeasurement\n      long_name: Angular acceleration about Z-axis, 0 for ACT1B\n      units: rad/s2\n  - acl_x_res:\n      comment: 9th column\n      coverage_content_type: modelResult\n      long_name: Residual of lin_accl_x from non-CRN-filtered value, always 0\n      units: m/s2\n  - acl_y_res:\n      comment: 10th column\n      coverage_content_type: modelResult\n      long_name: Residual of lin_accl_y from non-CRN-filtered value, always 0\n      units: m/s2\n  - acl_z_res:\n      comment: 11th column\n      coverage_content_type: modelResult\n      long_name: Residual of lin_accl_z from non-CRN-filtered value, always 0\n      units: m/s2\n  - qualflg:\n      comment: 12th column\n      coverage_content_type: qualityInformation\n      flag_masks: 1b, 2b, 4b, 8b, 16b, 32b, 64b, 128b\n      flag_meanings:\n        - bit 0 = Not defined\n        - bit 1 = Not defined\n        - bit 2 = Not defined\n        - bit 3 = Not defined\n        - bit 4 = Not defined)\";\n\n    return header_string;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceCoefficients2BlockMeanTimeSplines.cpp",
    "content": "/***********************************************/\n/**\n* @file graceCoefficients2BlockMeanTimeSplines.cpp\n*\n* @brief read GRACE data.\n*\n* @author Andreas Kvas\n* @date 2019-09-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts potential coefficients from the GRACE SDS RL06 format\ninto \\configFile{outputfileTimeSplines}{timeSplinesGravityField}.\n\nThe \\configFile{outputfileTimeSeries}{instrument} contains the mid points\nof non-empty intervals and \\configFile{outputfileTimeIntervals}{instrument}\ncontains the monthly interval boundaries from first to last solution.\n\nThe output will always be monthly block means. If the SDS solutions do vary or overlap,\nthe nearest solution in terms of reference epoch is used.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE data.\n* @ingroup programsConversionGroup */\nclass GraceCoefficients2BlockMeanTimeSplines\n{\nprivate:\n SphericalHarmonics readPotentialCoefficients(const FileName &name, Time &timeStart, Time &timeEnd);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceCoefficients2BlockMeanTimeSplines, SINGLEPROCESS, \"read GRACE data\", Conversion, Grace, PotentialCoefficients)\n\n/***********************************************/\n\nvoid GraceCoefficients2BlockMeanTimeSplines::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameCov, fileNameTimes, fileNameIntervals;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileTimeSplines\",           fileNameOut,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileTimeSplinesCovariance\", fileNameCov,       Config::OPTIONAL, \"\", \"only the variances are saved\");\n    readConfig(config, \"outputfileTimeSeries\",            fileNameTimes,     Config::OPTIONAL, \"\", \"mid points of non-empty intervals\");\n    readConfig(config, \"outputfileTimeIntervals\",         fileNameIntervals, Config::OPTIONAL, \"\", \"monthly interval boundaries from first to last solution\");\n    readConfig(config, \"inputfile\",                       fileNameIn,        Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<SphericalHarmonics> harmonics;\n    std::vector<Time> solutionStart, solutionEnd;\n    Double GM = DEFAULT_GM;\n    Double R  = DEFAULT_R;\n    UInt   maxDegree = 0;\n    for(auto &f : fileNameIn)\n    {\n      logStatus<<\"read file <\"<<f<<\">\"<<Log::endl;\n      Time timeStart, timeEnd;\n      harmonics.push_back(readPotentialCoefficients(f, timeStart, timeEnd));\n\n      solutionStart.push_back(timeStart);\n      solutionEnd.push_back(timeEnd);\n      GM = harmonics.back().GM();\n      R  = harmonics.back().R();\n      maxDegree = std::max(maxDegree, harmonics.back().maxDegree());\n    }\n    const auto minTime = std::min_element(solutionStart.begin(), solutionStart.end());\n    const auto maxTime = std::max_element(solutionEnd.begin(), solutionEnd.end());\n\n    // monthly time intervals\n    // ----------------------\n    UInt year, month, day, dummy;\n    Double second;\n    minTime->date(year, month, day, dummy, dummy, second);\n\n    std::vector<Time> intervals = {date2time(year, month, 1)};\n    while(intervals.back() < *maxTime)\n    {\n      UInt year, month, day, dummy;\n      Double second;\n      intervals.back().date(year, month, day, dummy, dummy, second);\n      intervals.push_back(date2time(year, month+1, 1));\n    }\n\n    std::vector<Matrix> cnmList, snmList, sigma2List;\n    std::vector<Time> nonEmptyIntervals;\n    for(UInt idxInterval=0; idxInterval<intervals.size()-1; idxInterval++)\n    {\n      Time epochMid = 0.5*(intervals.at(idxInterval)+intervals.at(idxInterval+1));\n\n      std::vector<UInt> overlappingSolutions;\n      for(UInt k=0; k<solutionStart.size(); k++)\n        if(!((intervals.at(idxInterval) >= solutionEnd.at(k)) || (solutionStart.at(k) >= intervals.at(idxInterval+1))))\n          overlappingSolutions.push_back(k);\n\n      if(overlappingSolutions.size()>1)\n        logWarning<<\"Multiple solutions for interval (\"<<intervals.at(idxInterval).dateStr()<<\", \"<<intervals.at(idxInterval+1).dateStr()<<\"). Using nearest neighbour.\"<<Log::endl;\n\n      SphericalHarmonics harm;\n      if(overlappingSolutions.size() > 0)\n      {\n        auto it = std::min_element(overlappingSolutions.begin(), overlappingSolutions.end(), [&](UInt i, UInt j)\n        {return std::abs((epochMid - (solutionStart.at(i)*0.5+solutionEnd.at(i)*0.5)).mjd()) < std::abs((epochMid - (solutionStart.at(j)*0.5+solutionEnd.at(j)*0.5)).mjd());});\n\n        harm = harmonics.at(*it).get(maxDegree, 0, GM, R);\n        nonEmptyIntervals.push_back(epochMid);\n      }\n      else\n      {\n        logWarning<<\"Interval (\"<<intervals.at(idxInterval).dateStr()<<\", \"<<intervals.at(idxInterval+1).dateStr()<<\") is empty.\"<<Log::endl;\n        harm = harm.get(maxDegree, 0, GM, R);\n      }\n      cnmList.push_back(harm.cnm());\n      snmList.push_back(harm.snm());\n      sigma2List.push_back(harm.sigma2x());\n    }\n\n    // write timeSplines file\n    // ----------------------\n    logStatus<<\"write time splines to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileTimeSplinesGravityfield(fileNameOut, GM, R, 0, intervals, cnmList, snmList);\n\n    if(!fileNameCov.empty())\n    {\n      logStatus<<\"write covariance time splines to file <\"<<fileNameCov<<\">\"<<Log::endl;\n      writeFileTimeSplinesCovariance(fileNameCov, GM, R, 0, maxDegree, 0, intervals, sigma2List);\n    }\n    if(!fileNameTimes.empty())\n    {\n      logStatus<<\"write midpoints of non-empty intervals to <\"<<fileNameTimes<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameTimes, Arc(nonEmptyIntervals, Matrix(nonEmptyIntervals.size(), 1)));\n    }\n    if(!fileNameIntervals.empty())\n    {\n      logStatus<<\"write monthly intervals to <\"<<fileNameIntervals<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameIntervals, Arc(intervals, Matrix(intervals.size(), 1)));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSphericalHarmonics GraceCoefficients2BlockMeanTimeSplines::readPotentialCoefficients(const FileName &name, Time &timeStart, Time &timeEnd)\n{\n  try\n  {\n    InFile file(name);\n\n    Double  GM = 0.3986004415e15;\n    Double  R  = 0.6378136460e07;\n    Matrix  cnm, snm, sigma2cnm, sigma2snm;\n    timeStart = date2time(9999,1,1);\n    timeEnd   = date2time(1, 1, 1);\n\n    Bool seekR = FALSE;\n    Bool seekGM = FALSE;\n    Bool seekDegree = FALSE;\n\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(line.find(\"dimension\") != std::string::npos)\n        seekDegree=TRUE;\n      if( (line.find(\"degree\") != std::string::npos) && seekDegree )\n      {\n        auto start_search = line.find(\":\");\n        std::stringstream ss(line.substr(start_search+1));\n        UInt degree = INFINITYDEGREE;\n        ss>>degree;\n        cnm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        snm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2cnm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2snm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        seekDegree = FALSE;\n      }\n\n      if(line.find(\"SHM \")==0)\n      {\n        UInt degree = String::toInt(line.substr(6, 5));\n        cnm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        snm       = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2cnm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n        sigma2snm = Matrix(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      }\n      if(line.find(\"EARTH \")==0)\n      {\n        GM = String::toDouble(line.substr(6, 16));\n        R  = String::toDouble(line.substr(23, 16));\n      }\n\n      if(line.find(\"mean_equator_radius\") != std::string::npos)\n        seekR = TRUE;\n      if( (line.find(\"value\") != std::string::npos) && seekR )\n      {\n        auto start_search = line.find(\":\");\n        std::stringstream ss(line.substr(start_search+1));\n        ss>>R;\n        seekR = FALSE;\n      }\n\n      if(line.find(\"earth_gravity_param\") != std::string::npos)\n        seekGM = TRUE;\n      if( (line.find(\"value\") != std::string::npos) && seekGM )\n      {\n        auto start_search = line.find(\":\");\n        std::stringstream ss(line.substr(start_search+1));\n        ss>>GM;\n        seekGM = FALSE;\n      }\n\n      if((line.find(\"GRCOEF\")==0)||(line.find(\"GRCOF2\")==0))\n      {\n        const UInt n    = String::toInt(line.substr(6, 5));\n        const UInt m    = String::toInt(line.substr(11, 5));\n        cnm(n,m)        = String::toDouble(line.substr(17, 18));\n        snm(n,m)        = String::toDouble(line.substr(36, 18));\n        sigma2cnm(n,m)  = String::toDouble(line.substr(55, 10));\n        sigma2snm(n,m)  = String::toDouble(line.substr(66, 10));\n        sigma2cnm(n,m) *= sigma2cnm(n,m);\n        sigma2snm(n,m) *= sigma2snm(n,m);\n\n        const UInt yearStart  = String::toInt(line.substr(77, 4));\n        const UInt monthStart = String::toInt(line.substr(81, 2));\n        const UInt dayStart   = String::toInt(line.substr(83, 2));\n        timeStart = std::min(timeStart, date2time(yearStart, monthStart, dayStart));\n\n        const UInt yearEnd    = String::toInt(line.substr(91, 4));\n        const UInt monthEnd   = String::toInt(line.substr(95, 2));\n        const UInt dayEnd     = String::toInt(line.substr(97, 2));\n        timeEnd = std::max(timeEnd, date2time(yearEnd, monthEnd, dayEnd));\n      }\n    }\n\n    return SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1a2Accelerometer.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1a2Accelerometer.cpp\n*\n* @brief Read GRACE L1A data.\n*\n* @author Beate Klinger\n* @date 2017-01-03\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts Level-1A accelerometer data (ACC1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in \\verb|GRACEiolib.h| given at\n\\url{http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz}.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read Level-1A GRACE data.\n* @ingroup programsConversionGroup */\nclass GraceL1a2Accelerometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1a2Accelerometer, SINGLEPROCESS, \"read GRACE L1A data (ACC1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1a2Accelerometer::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutAcc, fileNameOutAng;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileAccelerometer\",        fileNameOutAcc, Config::OPTIONAL, \"\", \"ACCELEROMETER in SRF\");\n    readConfig(config, \"outputfileAngularAccelerometer\", fileNameOutAng, Config::OPTIONAL, \"\", \"ACCELEROMETER in SRF\");\n    readConfig(config, \"inputfile\",                      fileNameIn,     Config::MUSTSET,  \"\", \"ACC1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc, arcAngAcc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds, microSeconds;\n        Char              time_ref, GRACE_id;\n        Byte              qualflg;\n        UInt32            prodFlag;\n        Vector3d          acceleration, angularAcceleration; // linear acceleration, angular acceleration,\n        Double            biasVol=NAN_EXPR;                  // proof mass bias voltage (averaged) (V)\n        Float             vd=NAN_EXPR;                       // amplitude of the AC voltages that operates the position sensors (Vrms)\n        Float             x1Out, x2Out, x3Out;               // displacement of capacitive sensor X1, X2, X3 (m)\n        Float             y1Out, y2Out, z1Out;               // displacement of capacitive sensor Y1, Y2, Y3 (m)\n        Float             tesu;                              // temperature of SU electronics (°C)\n        Float             taicu;                             // temperature of ICU power supply board (°C)\n        Float             tisu;                              // temperature of internal core (°C)\n        Float             v15Picu;                           // ICU reference voltage +15 V\n        Float             v15Micu;                           // ICU reference voltage -15 V\n        Float             vr5Picu;                           // ICU reference voltage + 5 V\n        Float             tcicu;                             // temperature of ICU A/D converter board (°C)\n        Float             v15Psu;                            // SU voltage +15 V\n        Float             v15Msu;                            // SU voltage -15 V\n        Float             v48Psu;                            // SU voltage +48 V\n        Float             v48Msu;                            // SU voltage -48 V\n        Byte              status;                            // status\n        UInt16            icuBlkNr=0;                        // ICU block number\n        FileInGrace::Int8 PPS_source;                        // 10Hz clock count\n        Int32             sync_quality_index;\n        UInt32            status_flag;\n\n        try\n        {\n          file>>seconds>>microSeconds>>time_ref>>GRACE_id>>FileInGrace::flag(qualflg)>>FileInGrace::flag(prodFlag);\n          if(prodFlag & (1 <<  0))  file>>acceleration.y();\n          if(prodFlag & (1 <<  1))  file>>acceleration.z();\n          if(prodFlag & (1 <<  2))  file>>acceleration.x();\n          if(prodFlag & (1 <<  3))  file>>angularAcceleration.y();\n          if(prodFlag & (1 <<  4))  file>>angularAcceleration.z();\n          if(prodFlag & (1 <<  5))  file>>angularAcceleration.x();\n          if(prodFlag & (1 <<  6))  file>>biasVol;\n          if(prodFlag & (1 <<  7))  file>>vd;\n          if(prodFlag & (1 <<  8))  file>>x1Out;\n          if(prodFlag & (1 <<  9))  file>>x2Out;\n          if(prodFlag & (1 << 10))  file>>x3Out;\n          if(prodFlag & (1 << 11))  file>>y1Out;\n          if(prodFlag & (1 << 12))  file>>y2Out;\n          if(prodFlag & (1 << 13))  file>>z1Out;\n          if(prodFlag & (1 << 14))  file>>tesu;\n          if(prodFlag & (1 << 15))  file>>taicu;\n          if(prodFlag & (1 << 16))  file>>tisu;\n          if(prodFlag & (1 << 17))  file>>v15Picu;\n          if(prodFlag & (1 << 18))  file>>v15Micu;\n          if(prodFlag & (1 << 19))  file>>vr5Picu;\n          if(prodFlag & (1 << 20))  file>>tcicu;\n          if(prodFlag & (1 << 21))  file>>v15Psu;\n          if(prodFlag & (1 << 22))  file>>v15Msu;\n          if(prodFlag & (1 << 23))  file>>v48Psu;\n          if(prodFlag & (1 << 24))  file>>v48Msu;\n          if(prodFlag & (1 << 25))  file>>FileInGrace::flag(status);\n          if(prodFlag & (1 << 26))  file>>icuBlkNr;\n          if(prodFlag & (1 << 27))  file>>PPS_source;\n          if(prodFlag & (1 << 28))  file>>sync_quality_index;\n          if(prodFlag & (1 << 29))  file>>FileInGrace::flag(status_flag);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        if((qualflg & (1 << 1)) || (qualflg & (1 << 3))) // data with no pulse sync and invalid time tag (?) are removed\n          continue;\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(microSeconds*1e-6);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        if((prodFlag & (1<<0)) && (prodFlag & (1<<1)) && (prodFlag & (1<<2)))\n        {\n          AccelerometerEpoch epoch;\n          epoch.time         = time;\n          epoch.acceleration = acceleration;\n          arc.push_back(epoch);\n        }\n\n        if((prodFlag & (1<<3)) && (prodFlag & (1<<4)) && (prodFlag & (1<<5)))\n        {\n          AccelerometerEpoch epoch;\n          epoch.time         = time;\n          epoch.acceleration = angularAcceleration;\n          arcAngAcc.push_back(epoch);\n        }\n      } // for(idEpoch)\n    } // for(idFile)\n\n     // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n    arcAngAcc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcAngAcc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOutAcc.empty())\n    {\n      logInfo<<\"write linear  acceleration to <\"<<fileNameOutAcc<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutAcc, arc);\n    }\n    if(!fileNameOutAng.empty())\n    {\n      logInfo<<\"write angular acceleration to <\"<<fileNameOutAng<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutAng, arcAngAcc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1a2SatelliteTracking.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1a2SatelliteTracking.cpp\n*\n* @brief Read GRACE L1A data.\n*\n* @author Beate Klinger\n* @date 2018-01-29\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts Level-1A satellite tracking data (KBR1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in \\verb|GRACEiolib.h| given at\n\\url{http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz}.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read Level-1A GRACE data.\n* @ingroup programsConversionGroup */\nclass GraceL1a2SatelliteTracking\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1a2SatelliteTracking, SINGLEPROCESS, \"read GRACE L1A data (KBR1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1a2SatelliteTracking::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameSst;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileSatelliteTracking\", fileNameSst, Config::OPTIONAL, \"\", \"MISCVALUES(ant_id, K_phase, Ka_phase, K_SNR, Ka_SNR)\");\n    readConfig(config, \"inputfile\",                   fileNameIn,  Config::MUSTSET,  \"\", \"KBR1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds, microSeconds;    // receiver time, microseconds part\n        Char              GRACE_id;                 // GRACE satellite ID\n        FileInGrace::Int8 prn_id, ant_id;           // GPS PRN id or GRACE id, KBR antenna id\n        UInt16            prodFlag;\n        Byte              qualityFlag;\n        Double            CA_range, L1_range, L2_range;\n        Double            CA_phase, L1_phase, L2_phase;\n        UInt16            CA_SNR, L1_SNR, L2_SNR;\n        UInt16            CA_chan, L1_chan, L2_chan;\n        Double            K_phase, Ka_phase;                 // K-Band carrier phase, Ka-Band carrier phase\n        UInt16            K_SNR, Ka_SNR;                     // K-Band SNR, Ka-Band SNR\n\n        try\n        {\n          file>>seconds>>microSeconds>>GRACE_id>>prn_id>>ant_id>>FileInGrace::flag(prodFlag)>>FileInGrace::flag(qualityFlag);\n          if(prodFlag & (1<<0))  file>>CA_range;\n          if(prodFlag & (1<<1))  file>>L1_range;\n          if(prodFlag & (1<<2))  file>>L2_range;\n          if(prodFlag & (1<<3))  file>>CA_phase;\n          if(prodFlag & (1<<4))  file>>L1_phase;\n          if(prodFlag & (1<<5))  file>>L2_phase;\n          if(prodFlag & (1<<6))  file>>CA_SNR;\n          if(prodFlag & (1<<7))  file>>L1_SNR;\n          if(prodFlag & (1<<8))  file>>L2_SNR;\n          if(prodFlag & (1<<9))  file>>CA_chan;\n          if(prodFlag & (1<<10)) file>>L1_chan;\n          if(prodFlag & (1<<11)) file>>L2_chan;\n          if(prodFlag & (1<<12)) file>>K_phase;\n          if(prodFlag & (1<<13)) file>>Ka_phase;\n          if(prodFlag & (1<<14)) file>>K_SNR;\n          if(prodFlag & (1<<15)) file>>Ka_SNR;\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        if((ant_id == 9) || (ant_id == 11) || (ant_id == -11))\n        {\n          MiscValuesEpoch epoch(7);\n          epoch.time      = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(microSeconds*1e-6);\n          epoch.values(0) = ant_id;\n          epoch.values(1) = K_phase;\n          epoch.values(2) = Ka_phase;\n          epoch.values(3) = K_SNR;\n          epoch.values(4) = Ka_SNR;\n          arc.push_back(epoch);\n        }\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameSst.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameSst<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameSst, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1a2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1a2StarCamera.cpp\n*\n* @brief Read GRACE L1A data.\n*\n* @author Beate Klinger\n* @date 2017-01-03\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts orientation data measured by the star cameras\nfrom the GRACE Level-1A format (SCA1A) to the GROOPS instrument file format.\nFor further information see \\program{GraceL1a2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1A data.\n* @ingroup programsConversionGroup */\nclass GraceL1a2StarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1a2StarCamera, SINGLEPROCESS, \"read GRACE L1A data (SCA1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1a2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameSca1, fileNameSca2;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileStarCamera1\", fileNameSca1, Config::MUSTSET,  \"\", \"STARCAMERA1A, head 1\");\n    readConfig(config, \"outputfileStarCamera2\", fileNameSca2, Config::MUSTSET,  \"\", \"STARCAMERA1A, head 2\");\n    readConfig(config, \"inputfile\",             fileNameIn,   Config::MUSTSET,  \"\", \"SCA1A, !GRACE-FO is not working!\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc1, arc2;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds, microSeconds=0;\n        Char              GRACE_id;\n        FileInGrace::Int8 sca_id;\n        Char              scaDesign;\n        Double            q0, q1, q2, q3;\n        FileInGrace::Int8 nLocks, nStars;\n        FileInGrace::Int8 scaConfig1, scaConfig2, scaConfig3;\n        Byte              scaMode;\n        Byte              qualityFlag;\n\n        try\n        {\n          file>>seconds>>/*microSeconds>>*/GRACE_id>>sca_id>>scaDesign>>q0>>q1>>q2>>q3; // microSeconds in GRACE-FO data only\n          file>>nLocks>>nStars>>scaConfig1>>scaConfig2>>scaConfig3>>FileInGrace::flag(scaMode)>>FileInGrace::flag(qualityFlag);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc1.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n       {\n          StarCamera1AEpoch epoch;\n          epoch.time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(1e-6*microSeconds);\n          epoch.rcvTime = seconds;\n          epoch.epsTime = 0.0;\n          if(scaDesign == 'P') // primary = 1, secondary = 2\n            epoch.scaDesign = 1;\n          if(scaDesign == 'S')\n            epoch.scaDesign = 2;\n          epoch.q0      = q0;\n          epoch.q1      = q1;\n          epoch.q2      = q2;\n          epoch.q3      = q3;\n          epoch.nLocks  = UInt(nLocks);\n          epoch.nStars  = UInt(nStars);\n\n          if((UInt(sca_id) == 1) && !(qualityFlag & (1 << 0)) && (UInt(scaConfig1) < 7)) // invalid data is removed\n            arc1.push_back(epoch);\n\n          if((UInt(sca_id) == 2) && !(qualityFlag & (1 << 0)) && (UInt(scaConfig1) < 7)) // invalid data is removed\n            arc2.push_back(epoch);\n        }\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    if(!fileNameSca1.empty())\n    {\n      logStatus<<\"Star camera head 1:\"<<Log::endl;\n      Arc::printStatistics(arc1);\n      if(arc1.size())\n      {\n        logStatus<<\"write data to <\"<<fileNameSca1<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameSca1, arc1);\n      }\n    }\n\n    if(!fileNameSca2.empty())\n    {\n      logStatus<<\"Star camera head 2:\"<<Log::endl;\n      Arc::printStatistics(arc2);\n      if(arc2.size())\n      {\n        logStatus<<\"write data to <\"<<fileNameSca2<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameSca2, arc2);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1a2Temperature.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1a2Temperature.cpp\n*\n* @brief Read GRACE L1A data.\n*\n* @author Beate Klinger\n* @date 2017-03-09\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts Level-1A temperature measurments (HRT1B or HRT1A) to the GROOPS instrument file format.\nThe GRACE Level-1A format is described in GRACE given at \\url{http://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/sw/GraceReadSW_L1_2010-03-31.tar.gz}.\nMultiple \\config{inputfile}s must be given in the correct time order.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1A data.\n* @ingroup programsConversionGroup */\nclass GraceL1a2Temperature\n{\n  void readFile(const FileName &fileName, MiscValuesArc &arcTemp);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1a2Temperature, SINGLEPROCESS, \"read GRACE L1A data (HRT1B or HRT1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1a2Temperature::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileTemperature\", fileNameOut, Config::MUSTSET, \"\", \"MISCVALUES\");\n    readConfig(config, \"inputfile\",             fileNameIn,  Config::MUSTSET, \"\", \"HRT1B or HRT1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file '\"<<fileNameIn.at(idFile)<<\"'\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32 seconds, microSeconds;           // seconds, microseconds part\n        Char  timeRef, GRACE_id;               // time reference frame (R = Receiver Time, G = GPS time), GRACE satellite ID\n        Float TempMEPNegY;                     // I/F support structure to MEP -y  [°C]\n        Float TempMEPPosY;                     // I/F support structure to MEP +y  [°C]\n        Float TempMEPm;                        // I/F support structure to MEP mid [°C]\n        Float TempICU;                         // ICU Temperature Reference Point  [°C]\n        Float TempICURed;                      // ICU Tempeartuer Reference Point (redundant) [°C]\n        Float TempACCNegZ;                     // ACC thermal cage -z [°C]\n        Float TempACCPosZ;                     // ACC thermal cage +z [°C]\n        Float TempCFRPPosX, TempCFRPPosXRed;   // CFRP Frame at +x I/F to Baseplate (+redundant) [°C]\n        Float TempCFRPNegX, TempCFRPNegXRed;   // CFRP Frame at -x I/F to Baseplate (+redundant) [°C]\n        Float TempCFRPNegY, TempCFRPNegYRed;   // CFRP Frame at -y I/F to Baseplate (+redundant) [°C]\n        Float TempACCSen;                      // Harness to ACC sensor [°C]\n        Float TempICUSpec;                     // ICU special [°C]\n        Float TempMWANegY,  TempMWANegYOff;    // MWA -y Temp. Ref. Point, 2 out 3 (+nominally off) [°C]\n        Float TempMWAPosY,  TempMWAPosYOff;    // MWA +y Temp. Ref. Point, 2 out 3 (+nominally off) [°C]\n        Float TempHornPosX, TempHornPosXRed;   // Horn aperture +x (+redundant) [°C]\n        Float TempHornPl,   TempHornPlRed;     // Horn / platform I/F (+redundant) [°C]\n        Float TempHWMANegY;                    // Harnass to MWA electronics -y [°C]\n        Float TempHWMAPosY;                    // Harnass to MWA electronics +y [°C]\n        Float TempRFSamp;                      // RF-Sampling unit [°C]\n        Float TempUSONegY,  TempUSONegYRed;    // USO Temp. Ref. Point -y (+redundant) [°C]\n        Float TempUSOPosY,  TempUSOPosYRed;    // USO Temp. Ref. Point +y (+redundant) [°C]\n        Byte  qualityFlag;                     // data quality flag\n\n        try\n        {\n          file>>seconds>>microSeconds>>timeRef>>GRACE_id>>TempMEPNegY>>TempMEPPosY>>TempMEPm>>TempICU>>TempICURed>>TempACCNegZ>>TempACCPosZ;\n          file>>TempCFRPPosX>>TempCFRPPosXRed>>TempCFRPNegX>>TempCFRPNegXRed>>TempCFRPNegY>>TempCFRPNegYRed>>TempACCSen>>TempICUSpec;\n          file>>TempMWANegY>>TempMWANegYOff>>TempMWAPosY>>TempMWAPosYOff>>TempHornPosX>>TempHornPosXRed>>TempHornPl>>TempHornPlRed;\n          file>>TempHWMANegY>>TempHWMAPosY>>TempRFSamp>>TempUSONegY>>TempUSONegYRed>>TempUSOPosY>>TempUSOPosYRed>>FileInGrace::flag(qualityFlag);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        {\n          MiscValuesEpoch epoch(21);\n          epoch.time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(microSeconds*1e-6);\n          epoch.values(0)  = TempACCNegZ;\n          epoch.values(1)  = TempACCPosZ;\n          epoch.values(2)  = TempACCSen;\n          epoch.values(3)  = TempCFRPPosX;\n          epoch.values(4)  = TempCFRPNegX;\n          epoch.values(5)  = TempCFRPNegY;\n          epoch.values(6)  = TempCFRPNegYRed;\n          epoch.values(7)  = TempMEPNegY;\n          epoch.values(8)  = TempMEPPosY;\n          epoch.values(9)  = TempMEPm;\n          epoch.values(10) = TempICUSpec;\n          epoch.values(11) = TempICU;\n          epoch.values(12) = TempMWANegY;\n          epoch.values(13) = TempMWAPosY;\n          epoch.values(14) = TempHWMANegY;\n          epoch.values(15) = TempHWMAPosY;\n          epoch.values(16) = TempRFSamp;\n          epoch.values(17) = TempUSONegY;\n          epoch.values(18) = TempUSOPosY;\n          epoch.values(19) = TempHornPosX;\n          epoch.values(20) = TempHornPl;\n          arc.push_back(epoch);\n        }\n      }// for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write temperature data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2AccHousekeeping.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2AccHousekeeping.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2015-10-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts ACC housekeeping data (AHK1B or AHK1A) from the GRACE SDS format into \\file{instrument file (ACCHOUSEKEEPING)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2AccHousekeeping\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2AccHousekeeping, SINGLEPROCESS, \"read GRACE L1B data (AHK1B or AHK1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2AccHousekeeping::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileAccHousekeeping\", fileNameOut, Config::MUSTSET,  \"\", \"ACCHOUSEKEEPING\");\n    readConfig(config, \"inputfile\",                 fileNameIn,  Config::MUSTSET,  \"\", \"AHK1B or AHK1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds, time_frac;\n        Char              time_ref, GRACE_id;\n        Byte              qualflg;\n        UInt32            prodFlag;\n        Vector3d          acceleration, angularAcceleration; // linear acceleration, angular acceleration,\n        Double            biasVol=NAN_EXPR;                  // proof mass bias voltage (averaged) (V)\n        Float             vd=NAN_EXPR;                       // amplitude of the AC voltages that operates the position sensors (Vrms)\n        Float             x1Out=NAN_EXPR, x2Out=NAN_EXPR, x3Out=NAN_EXPR;   // displacement of capacitive sensor X1, X2, X3 (m)\n        Float             y1Out=NAN_EXPR, y2Out=NAN_EXPR, z1Out=NAN_EXPR;   // displacement of capacitive sensor Y1, Y2, Y3 (m)\n        Float             tesu =NAN_EXPR;                    // temperature of SU electronics (°C)\n        Float             taicu=NAN_EXPR;                    // temperature of ICU power supply board (°C)\n        Float             tisu =NAN_EXPR;                    // temperature of internal core (°C)\n        Float             v15Picu;                           // ICU reference voltage +15 V\n        Float             v15Micu;                           // ICU reference voltage -15 V\n        Float             vr5Picu;                           // ICU reference voltage + 5 V\n        Float             tcicu=NAN_EXPR;                    // temperature of ICU A/D converter board (°C)\n        Float             v15Psu;                            // SU voltage +15 V\n        Float             v15Msu;                            // SU voltage -15 V\n        Float             v48Psu;                            // SU voltage +48 V\n        Float             v48Msu;                            // SU voltage -48 V\n        Byte              status;                            // status\n        UInt16            icuBlkNr=0;                        // ICU block number\n        FileInGrace::Int8 PPS_source;                        // 10Hz clock count\n        Int32             sync_quality_index;\n        UInt32            status_flag;\n\n        try\n        {\n          file>>seconds>>time_frac>>time_ref>>GRACE_id>>FileInGrace::flag(qualflg)>>FileInGrace::flag(prodFlag);\n          if(prodFlag & (1 <<  0))  file>>acceleration.x();\n          if(prodFlag & (1 <<  1))  file>>acceleration.y();\n          if(prodFlag & (1 <<  2))  file>>acceleration.z();\n          if(prodFlag & (1 <<  3))  file>>angularAcceleration.x();\n          if(prodFlag & (1 <<  4))  file>>angularAcceleration.y();\n          if(prodFlag & (1 <<  5))  file>>angularAcceleration.z();\n          if(prodFlag & (1 <<  6))  file>>biasVol;\n          if(prodFlag & (1 <<  7))  file>>vd;\n          if(prodFlag & (1 <<  8))  file>>x1Out;\n          if(prodFlag & (1 <<  9))  file>>x2Out;\n          if(prodFlag & (1 << 10))  file>>x3Out;\n          if(prodFlag & (1 << 11))  file>>y1Out;\n          if(prodFlag & (1 << 12))  file>>y2Out;\n          if(prodFlag & (1 << 13))  file>>z1Out;\n          if(prodFlag & (1 << 14))  file>>tesu;\n          if(prodFlag & (1 << 15))  file>>taicu;\n          if(prodFlag & (1 << 16))  file>>tisu;\n          if(prodFlag & (1 << 17))  file>>v15Picu;\n          if(prodFlag & (1 << 18))  file>>v15Micu;\n          if(prodFlag & (1 << 19))  file>>vr5Picu;\n          if(prodFlag & (1 << 20))  file>>tcicu;\n          if(prodFlag & (1 << 21))  file>>v15Psu;\n          if(prodFlag & (1 << 22))  file>>v15Msu;\n          if(prodFlag & (1 << 23))  file>>v48Psu;\n          if(prodFlag & (1 << 24))  file>>v48Msu;\n          if(prodFlag & (1 << 25))  file>>FileInGrace::flag(status);\n          if(prodFlag & (1 << 26))  file>>icuBlkNr;\n          if(prodFlag & (1 << 27))  file>>PPS_source;\n          if(prodFlag & (1 << 28))  file>>sync_quality_index;\n          if(prodFlag & (1 << 29))  file>>FileInGrace::flag(status_flag);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n//         if(!((prodFlag & (1 << 14)) && (prodFlag & (1 << 15)) && (prodFlag & (1 << 16)) && (prodFlag & (1 << 20))))\n//           continue;\n\n        AccHousekeepingEpoch epoch;\n        epoch.time        = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(1e-6*time_frac);\n        epoch.biasVoltage = biasVol;\n        epoch.vd          = vd;\n        epoch.xOut        = Vector3d(x1Out, x2Out, x3Out);\n        epoch.yOut        = Vector3d(y1Out, y2Out, z1Out);\n        epoch.tempSU      = tesu;\n        epoch.tempICU     = taicu;\n        epoch.tempCore    = tisu;\n        epoch.tempICUConv = tcicu;\n        epoch.blkNrICU    = icuBlkNr;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Accelerometer.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Accelerometer.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts accelerometer data (ACC1B or ACT1B) from the GRACE SDS format into \\file{instrument file (ACCELEROMETER)}{instrument}.\n\nMultiple \\config{inputfile}s must be given in the correct time order.\nThe output is one arc of satellite data which can include data gaps.\nTo split the arc in multiple gap free arcs use \\program{InstrumentSynchronize}.\n\nThe GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\"\ngiven at \\url{https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/Handbook_1B_v1.3.pdf}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Accelerometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Accelerometer, SINGLEPROCESS, \"read GRACE L1B data (ACC1B or ACT1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2Accelerometer::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutAcc, fileNameOutAng, fileNameOutFlags;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileAccelerometer\",        fileNameOutAcc,   Config::OPTIONAL, \"\", \"ACCELEROMETER\");\n    readConfig(config, \"outputfileAngularAccelerometer\", fileNameOutAng,   Config::OPTIONAL, \"\", \"ACCELEROMETER\");\n    readConfig(config, \"outputfileFlags\",                fileNameOutFlags, Config::OPTIONAL, \"\", \"MISCVALUES(qualflg, acl_res.x, acl_res.y, acl_res.z)\");\n    readConfig(config, \"inputfile\",                      fileNameIn,       Config::MUSTSET,  \"\", \"ACC1B or ACT1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc, arcAngular, arcFlags;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32    seconds;\n        Char     GRACE_id;\n        Vector3d lin_accl, ang_acc, acl_res;\n        Byte     qualflg;\n\n        try\n        {\n          file>>seconds>>GRACE_id>>lin_accl>>ang_acc>>acl_res>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        {\n          AccelerometerEpoch epoch;\n          epoch.time         = time;\n          epoch.acceleration = lin_accl;\n          arc.push_back(epoch);\n        }\n\n        {\n          AccelerometerEpoch epoch;\n          epoch.time         = time;\n          epoch.acceleration = ang_acc;\n          arcAngular.push_back(epoch);\n        }\n\n        {\n          MiscValuesEpoch epoch(4);\n          epoch.time   = time;\n          epoch.values = {Double(qualflg), acl_res.x(), acl_res.y(), acl_res.z()};\n          arcFlags.push_back(epoch);\n        }\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n    arcAngular.sort();\n    arcFlags.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcAngular.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcFlags.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOutAcc.empty())\n    {\n      logInfo<<\"write linear  acceleration to <\"<<fileNameOutAcc<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutAcc, arc);\n    }\n    if(!fileNameOutAng.empty())\n    {\n      logInfo<<\"write angular acceleration to <\"<<fileNameOutAng<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutAng, arcAngular);\n    }\n    if(!fileNameOutFlags.empty())\n    {\n      logInfo<<\"write flags to <\"<<fileNameOutFlags<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutFlags, arcFlags);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2ClockOffset.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2ClockOffset.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2017-01-04\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts clock data (CLK1B or LLK1B) from the GRACE SDS format into \\file{instrument file (MISCVALUE)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2ClockOffset\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2ClockOffset, SINGLEPROCESS, \"read GRACE L1B data (CLK1B or LLK1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2ClockOffset::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileClock\", fileNameOut, Config::MUSTSET, \"\", \"MISCVALUE\");\n    readConfig(config, \"inputfile\",       fileNameIn,  Config::MUSTSET, \"\", \"CLK1B or LLK1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds;\n        Char              GRACE_id;\n        FileInGrace::Int8 clock_id;\n        Double            eps_time, eps_err, eps_drift, drift_err;\n        Byte              qualflg;\n\n        try\n        {\n          file>>seconds>>GRACE_id>>clock_id>>eps_time>>eps_err>>eps_drift>>drift_err>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        MiscValueEpoch epoch;\n        epoch.time  = time;\n        epoch.value = eps_time;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2GnssReceiver.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2GnssReceiver.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-04\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts GPS receiver data (phase and pseudo range) data\nfrom the GRACE SDS format (GPS1B or GPS1A) into \\file{instrument file (GNSSRECEIVER)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2GnssReceiver\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2GnssReceiver, SINGLEPROCESS, \"read GRACE L1B data (GPS1B or GPS1A)\", Conversion, Grace, Gnss, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2GnssReceiver::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileGnssReceiver\", fileNameOut, Config::MUSTSET,  \"\", \"GNSSRECEIVER\");\n    readConfig(config, \"inputfile\",              fileNameIn,  Config::MUSTSET,  \"\", \"GPS1B or GPS1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    GnssReceiverArc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds, seconds_frac;\n        Char              GRACE_id;\n        FileInGrace::Int8 prn_id, ant_id;\n        UInt16            prodFlag;\n        Byte              qualflg;\n        Double            CA_range=NAN_EXPR, L1_range=NAN_EXPR, L2_range=NAN_EXPR;\n        Double            CA_phase=NAN_EXPR, L1_phase=NAN_EXPR, L2_phase=NAN_EXPR;\n        UInt16            CA_SNR=0, L1_SNR=0, L2_SNR=0, CA_chan=0,L1_chan=0, L2_chan=0;\n        Double            K_phase, Ka_phase;                 // K-Band carrier phase, Ka-Band carrier phase\n        UInt16            K_SNR, Ka_SNR;                     // K-Band SNR, Ka-Band SNR\n\n        try\n        {\n          file>>seconds>>seconds_frac>>GRACE_id>>prn_id>>ant_id>>FileInGrace::flag(prodFlag)>>FileInGrace::flag(qualflg);\n          if(prodFlag & (1<<0))  file>>CA_range;\n          if(prodFlag & (1<<1))  file>>L1_range;\n          if(prodFlag & (1<<2))  file>>L2_range;\n          if(prodFlag & (1<<3))  file>>CA_phase;\n          if(prodFlag & (1<<4))  file>>L1_phase;\n          if(prodFlag & (1<<5))  file>>L2_phase;\n          if(prodFlag & (1<<6))  file>>CA_SNR;\n          if(prodFlag & (1<<7))  file>>L1_SNR;\n          if(prodFlag & (1<<8))  file>>L2_SNR;\n          if(prodFlag & (1<<9))  file>>CA_chan;\n          if(prodFlag & (1<<10)) file>>L1_chan;\n          if(prodFlag & (1<<11)) file>>L2_chan;\n          if(prodFlag & (1<<12)) file>>K_phase;\n          if(prodFlag & (1<<13)) file>>Ka_phase;\n          if(prodFlag & (1<<14)) file>>K_SNR;\n          if(prodFlag & (1<<15)) file>>Ka_SNR;\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(1e-6*seconds_frac);\n        if(arc.size() && (time < arc.back().time))\n          throw(Exception(\"time error: epoch(\"+time.dateTimeStr()+\") < last epoch(\"+arc.back().time.dateTimeStr()+\")\"));\n\n        if(ant_id != 0)\n        {\n          logWarning<<time.dateTimeStr()<<\": data from other antennas: \"<<(int)ant_id<<Log::endl;\n          continue;\n        }\n\n        if((prodFlag & 0x3f) != 0x3f)\n          logWarning<<time.dateTimeStr()<<\" (PRN = \"<<prn_id%\"%02i), Product: \"s<<prodFlag<<Log::endl;\n\n        // start new epoch?\n        if((arc.size() == 0) || (arc.back().time != time))\n        {\n          GnssReceiverEpoch epoch;\n          epoch.time    = time;\n          epoch.obsType = {GnssType::RANGE + GnssType::L1 + GnssType::C + GnssType::GPS,\n                           GnssType::RANGE + GnssType::L1 + GnssType::W + GnssType::GPS,\n                           GnssType::RANGE + GnssType::L2 + GnssType::W + GnssType::GPS,\n                           GnssType::PHASE + GnssType::L1 + GnssType::C + GnssType::GPS,\n                           GnssType::PHASE + GnssType::L1 + GnssType::W + GnssType::GPS,\n                           GnssType::PHASE + GnssType::L2 + GnssType::W + GnssType::GPS,\n                           GnssType::SNR   + GnssType::L1 + GnssType::C + GnssType::GPS,\n                           GnssType::SNR   + GnssType::L1 + GnssType::W + GnssType::GPS,\n                           GnssType::SNR   + GnssType::L2 + GnssType::W + GnssType::GPS};\n          arc.push_back(epoch);\n        }\n\n        arc.back().satellite.push_back(GnssType::GPS + GnssType(prn_id));\n        arc.back().observation.push_back(CA_range);\n        arc.back().observation.push_back(L1_range);\n        arc.back().observation.push_back(L2_range);\n        arc.back().observation.push_back(CA_phase);\n        arc.back().observation.push_back(L1_phase);\n        arc.back().observation.push_back(L2_phase);\n        arc.back().observation.push_back(CA_SNR);\n        arc.back().observation.push_back(L1_SNR);\n        arc.back().observation.push_back(L2_SNR);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write gnss data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Magnetometer.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Magnetometer.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2014-05-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts magnetometer data (MAG1B or MAG1A) from the GRACE SDS format into \\file{instrument file (MAGNETOMETER)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Magnetometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Magnetometer, SINGLEPROCESS, \"read GRACE L1B data (MAG1B or MAG1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2Magnetometer::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileMagnetometer\", fileNameOut, Config::MUSTSET,  \"\", \"MAGNETOMETER\");\n    readConfig(config, \"inputfile\",              fileNameIn,  Config::MUSTSET,  \"\", \"MAG1B or MAG1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32    seconds, time_frac;\n        Char     time_ref, GRACE_id;\n        Float    MfvX_RAW, MfvY_RAW, MfvZ_RAW;\n        Float    torque1A, torque2A, torque3A, torque1B, torque2B, torque3B;\n        Float    MF_BCalX, MF_BCalY, MF_BCalZ, torque_cal;\n        Byte     qualflg;\n\n        try\n        {\n          file>>seconds>>time_frac>>time_ref>>GRACE_id; // GRACEFO: time_ref and GRACE_id are interschanged\n          file>>MfvX_RAW>>MfvY_RAW>>MfvZ_RAW;\n          file>>torque1A>>torque2A>>torque3A>>torque1B>>torque2B>>torque3B;\n          file>>MF_BCalX>>MF_BCalY>>MF_BCalZ>>torque_cal>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(1e-6*time_frac);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        MagnetometerEpoch epoch;\n        epoch.time                     = time;\n        epoch.magneticField            = Vector3d(MfvX_RAW, MfvY_RAW, MfvZ_RAW);\n        epoch.torquerA                 = Vector3d(torque1A, torque2A, torque3A);\n        epoch.torquerB                 = Vector3d(torque1B, torque2B, torque3B);\n        epoch.magneticFieldCalibration = Vector3d(MF_BCalX, MF_BCalY, MF_BCalZ);\n        epoch.torquerCalibration       = torque_cal;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Mass.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Mass.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2013-11-24\n*\n*/\n/***********************************************/\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts mass data (MAS1B or MAS1A) from the GRACE SDS format into \\file{instrument file (MASS)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Mass\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Mass, SINGLEPROCESS, \"read GRACE L1B data (MAS1B or MAS1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2Mass::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileMass\", fileNameOut, Config::MUSTSET,  \"\", \"MASS\");\n    readConfig(config, \"inputfile\",      fileNameIn,  Config::MUSTSET,  \"\", \"MAS1B or MAS1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32    seconds, time_frac;\n        Char     time_ref, GRACE_id;\n        Byte     qualflg, prod_flag;\n        Double   mass_thr=0, mass_thr_err=0, mass_tnk=0, mass_tnk_err=0;\n        Double   gas_mass_thr1=0, gas_mass_thr2=0, gas_mass_tnk1=0, gas_mass_tnk2=0;\n\n        try\n        {\n          file>>seconds>>time_frac>>time_ref>>GRACE_id>>FileInGrace::flag(qualflg)>>FileInGrace::flag(prod_flag);\n          if(prod_flag & (1<<0)) file>>mass_thr;\n          if(prod_flag & (1<<1)) file>>mass_thr_err;\n          if(prod_flag & (1<<2)) file>>mass_tnk;\n          if(prod_flag & (1<<3)) file>>mass_tnk_err;\n          if(prod_flag & (1<<4)) file>>gas_mass_thr1;\n          if(prod_flag & (1<<5)) file>>gas_mass_thr2;\n          if(prod_flag & (1<<6)) file>>gas_mass_tnk1;\n          if(prod_flag & (1<<7)) file>>gas_mass_tnk2;\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(1e-6*time_frac);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        MassEpoch epoch;\n        epoch.time     = time;\n        if(GRACE_id=='C')\n        {\n          epoch.massThr = 601.21-(15.62718541166349-gas_mass_tnk1)-(15.63189368778949-gas_mass_tnk2);\n        }\n        else if(GRACE_id=='D')\n        {\n          epoch.massThr = 601.21-(15.60994853989272-gas_mass_tnk1)- (15.68091099702227-gas_mass_tnk2);\n        }\n        else\n            epoch.massThr  = mass_thr;\n        epoch.massTank = epoch.massThr;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Orbit.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the reduced dynamical orbit\nfrom the GRACE/GRACE-FO SDS format (GNV1B, GNI1B) into \\file{instrument file (ORBIT)}{instrument}.\n\nWhen GNV1B is used, the orbit can be rotated from the terrestrial reference frame (TRF) transformed into the celestial reference frame (CRF) by\nspecifying \\configClass{earthRotation}{earthRotationType}.\n\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE/GRACE-FO L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Orbit, SINGLEPROCESS, \"read GRACE/GRACE-FO L1B data (GNV1B, GNI1B)\", Conversion, Grace, Orbit, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOut,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::OPTIONAL, \"file\", \"to rotate GNV1B into CRF\");\n    readConfig(config, \"inputfile\",       fileNameIn,    Config::MUSTSET,  \"\", \"GNV1B/GNI1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32    seconds;\n        Char     GRACE_id, coord_ref;\n        Vector3d pos, pos_err, vel, vel_err;\n        Byte     qualflg;\n\n        try\n        {\n          file>>seconds>>GRACE_id>>coord_ref>>pos>>pos_err>>vel>>vel_err>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds);\n        if(arc.size() && (time <= arc.back().time))\n          continue;\n\n        if(coord_ref == 'E' && !earthRotation)\n          throw(Exception(time.dateTimeStr()+\": orbit not in CRF. Must specify earthRotation.\"));\n\n        OrbitEpoch epoch;\n        epoch.time     = time;\n        epoch.position = pos;\n        epoch.velocity = vel;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    if(earthRotation)\n    {\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(arc.size(), [&](UInt i)\n      {\n        const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(arc.at(i).time));\n        arc.at(i).position = rotation.rotate(arc.at(i).position);\n        if(arc.at(i).velocity.r() > 0)\n          arc.at(i).velocity = rotation.rotate(arc.at(i).velocity) + crossProduct(earthRotation->rotaryAxis(arc.at(i).time), arc.at(i).position);\n      });\n    }\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2SatelliteTracking.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2SatelliteTracking.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts low-low satellite data measured by the K-band ranging system\nfrom the GRACE SDS format (KBR1B or LRI1B) into \\file{instrument file (SATELLITETRACKING)}{instrument}.\nThe \\config{inputfile}s contain also corrections to antenna offsets\nand the so called light time correction. The corrections can be stored in additional files\nin the same format as the observations.\nIf a phase break is found an artificial gap is created.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2SatelliteTracking\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2SatelliteTracking, SINGLEPROCESS, \"read GRACE L1B data (KBR1B or LRI1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2SatelliteTracking::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameSst, fileNameAntCentr, fileNameLighttime, fileNameSnr, fileNameIonoCorr;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileSatelliteTracking\", fileNameSst,       Config::OPTIONAL, \"\", \"SATELLITETRACKING\");\n    readConfig(config, \"outputfileAntCentr\",          fileNameAntCentr,  Config::OPTIONAL, \"\", \"SATELLITETRACKING\");\n    readConfig(config, \"outputfileLighttime\",         fileNameLighttime, Config::OPTIONAL, \"\", \"SATELLITETRACKING\");\n    readConfig(config, \"outputfileSNR\",               fileNameSnr,       Config::OPTIONAL, \"\", \"MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)\");\n    readConfig(config, \"outputfileIonoCorr\",          fileNameIonoCorr,  Config::OPTIONAL, \"\", \"MISCVALUE\");\n    readConfig(config, \"inputfile\",                   fileNameIn,        Config::MUSTSET,  \"\", \"KBR1B or LRI1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    SatelliteTrackingArc arc, arcAntCentr, arcLight;\n    MiscValuesArc        arcSnr;\n    MiscValueArc         arcIonoCorr;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32    seconds;\n        Double   biased_range, range_rate, range_accl, iono_corr;\n        Double   lighttime_corr, lighttime_rate, lighttime_accl;\n        Double   ant_centr_corr, ant_centr_rate, ant_centr_accl;\n        UInt16   K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR;\n        Byte     qualflg;\n\n        try\n        {\n          file>>seconds;\n          file>>biased_range>>range_rate>>range_accl>>iono_corr;\n          file>>lighttime_corr>>lighttime_rate>>lighttime_accl;\n          file>>ant_centr_corr>>ant_centr_rate>>ant_centr_accl;\n          file>>K_A_SNR>>Ka_A_SNR>>K_B_SNR>>Ka_B_SNR;\n          file>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        if(((qualflg & 1) == 1) || (arc.size() && ((time-arc.back().time).seconds() <= 5.) && (std::fabs(biased_range-arc.back().range) > 100)))\n        {\n//           if(arc.size())\n//             logWarning<<time.dateTimeStr()<<\": skip epoch due to possible phase break, range change = \"<<biased_range-arc.back().range<<Log::endl;\n//           else\n//             logWarning<<time.dateTimeStr()<<\": skip epoch due to possible phase break, first epoch in file\"<<Log::endl;\n          continue;\n        }\n\n        {\n          SatelliteTrackingEpoch epoch;\n          epoch.time              = time;\n          epoch.range             = biased_range;\n          epoch.rangeRate         = range_rate;\n          epoch.rangeAcceleration = range_accl;\n          arc.push_back(epoch);\n        }\n\n        {\n          SatelliteTrackingEpoch epoch;\n          epoch.time              = time;\n          epoch.range             = lighttime_corr;\n          epoch.rangeRate         = lighttime_rate;\n          epoch.rangeAcceleration = lighttime_accl;\n          arcLight.push_back(epoch);\n        }\n\n        {\n          SatelliteTrackingEpoch epoch;\n          epoch.time              = time;\n          epoch.range             = ant_centr_corr;\n          epoch.rangeRate         = ant_centr_rate;\n          epoch.rangeAcceleration = ant_centr_accl;\n          arcAntCentr.push_back(epoch);\n        }\n\n        {\n          MiscValuesEpoch epoch(5);\n          epoch.time = time;\n          epoch.values = {Double(K_A_SNR), Double(Ka_A_SNR), Double(K_B_SNR), Double(Ka_B_SNR), Double(qualflg)};\n          arcSnr.push_back(epoch);\n        }\n\n        {\n          MiscValueEpoch epoch;\n          epoch.time = time;\n          epoch.value = iono_corr;\n          arcIonoCorr.push_back(epoch);\n        }\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n    arcAntCentr.sort();\n    arcLight.sort();\n    arcSnr.sort();\n    arcIonoCorr.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcAntCentr.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcLight.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcSnr.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameSst.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameSst<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameSst, arc);\n    }\n    if(!fileNameAntCentr.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameAntCentr<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameAntCentr, arcAntCentr);\n    }\n    if(!fileNameLighttime.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameLighttime<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameLighttime, arcLight);\n    }\n    if(!fileNameSnr.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameSnr<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameSnr, arcSnr);\n    }\n    if(!fileNameIonoCorr.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameIonoCorr<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameIonoCorr, arcIonoCorr);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2StarCamera.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GRACE SDS format (SCA1B) into \\file{instrument file (STARCAMERA)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2StarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2StarCamera, SINGLEPROCESS, \"read GRACE L1B data (SCA1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameSca, FileNameFlags;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileStarCamera\",      fileNameSca,   Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileStarCameraFlags\", FileNameFlags, Config::OPTIONAL, \"\", \"MISCVALUES(sca_id, qual_rss, qualflg)\");\n    readConfig(config, \"inputfile\",                 fileNameIn,    Config::MUSTSET,  \"\", \"SCA1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc, arcFlags;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds;\n        Char              GRACE_id;\n        FileInGrace::Int8 sca_id;\n        Double            quatangle, quaticoeff, quatjcoeff, quatkcoeff, qual_rss;\n        Byte              qualflg;\n\n        try\n        {\n          file>>seconds>>GRACE_id>>sca_id>>quatangle>>quaticoeff>>quatjcoeff>>quatkcoeff>>qual_rss>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        {\n          StarCameraEpoch epoch;\n          epoch.time   = time;\n          epoch.rotary = Rotary3d(Vector{quatangle, quaticoeff, quatjcoeff, quatkcoeff});\n          arc.push_back(epoch);\n        }\n\n        {\n          MiscValuesEpoch epoch(3);\n          epoch.time   = time;\n          epoch.values = {Double(sca_id), qual_rss, Double(qualflg)};\n          arcFlags.push_back(epoch);\n        }\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n    arcFlags.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    arcFlags.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameSca.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameSca<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameSca, arc);\n    }\n\n    if(!FileNameFlags.empty())\n    {\n      logInfo<<\"write data to <\"<<FileNameFlags<<\">\"<<Log::endl;\n      InstrumentFile::write(FileNameFlags, arcFlags);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2StarCameraCovariance.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2StarCameraCovariance.cpp\n*\n* @brief Covariance matrix from star camera flags.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-08-22\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes star camera covariance matrices (\\file{instrument file, COVARIANE3D}{instrument})\nfor a GRACE satellite under consideration of the active camera heads and an a priori variance factor.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Covariance matrix from star camera flags.\n* @ingroup programsConversionGroup */\nclass GraceL1b2StarCameraCovariance\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2StarCameraCovariance, PARALLEL, \"Covariance matrix from star camera flags\", Conversion, Grace, Covariance, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2StarCameraCovariance::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameCovariance;\n    FileName fileNameStarCamera, fileNameFlags, fileNameSoeQSA;\n    Double   sigma0;\n\n    readConfig(config, \"outputfileStarCameraCovariance\", fileNameCovariance, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCameraFlags\",       fileNameFlags,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileSequenceOfEventsQSA\",   fileNameSoeQSA,     Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"sigma0\",                         sigma0,             Config::DEFAULT,  \"6\", \"[seconds of arc]\");\n    if(isCreateSchema(config)) return;\n\n    // Covariance of one head\n    Tensor3d cov0;\n    cov0.xx() = std::pow(  sigma0*DEG2RAD/3600, 2);\n    cov0.yy() = std::pow(  sigma0*DEG2RAD/3600, 2);\n    cov0.zz() = std::pow(8*sigma0*DEG2RAD/3600, 2);\n    Tensor3d cov1  = rotaryX(Angle(-135*DEG2RAD)).rotate(cov0);\n    Tensor3d cov2  = rotaryX(Angle(+135*DEG2RAD)).rotate(cov0);\n    Matrix   inv1  = cov1.matrix(); inverse(inv1);\n    Matrix   inv2  = cov2.matrix(); inverse(inv2);\n    Matrix   inv12 = inv1+inv2;     inverse(inv12);\n    Tensor3d cov12(inv12);\n\n    // star camera orientations\n    MiscValuesArc qsa = InstrumentFile::read(fileNameSoeQSA);\n\n    logStatus<<\"computing covariance matrix\"<<Log::endl;\n    InstrumentFile flagsFile(fileNameFlags);\n\n    std::vector<Arc> arcList(flagsFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      MiscValuesArc flags = flagsFile.readArc(arcNo);\n      Covariance3dArc arc;\n\n      for(UInt i=0; i<flags.size(); i++)\n      {\n        // update rotations\n        while(qsa.size() && (qsa.front().time <= flags.at(i).time)) // Move to correct interval\n        {\n          const Rotary3d rot1(qsa.front().values.row(0,4)); // qsa is rotation SCA frame to SRF\n          const Rotary3d rot2(qsa.front().values.row(4,4));\n          cov1 = rot1.rotate(cov0);\n          cov2 = rot2.rotate(cov0);\n          Matrix inv1  = cov1.matrix(); inverse(inv1);\n          Matrix inv2  = cov2.matrix(); inverse(inv2);\n          Matrix inv12 = inv1+inv2;     inverse(inv12);\n          cov12 = inv12;\n          qsa.remove(0);\n        }\n\n        const Double factor = 1.;\n        // factor *= std::pow(epochFlags.values(1), 2); // = q_res;\n\n        Covariance3dEpoch epoch;\n        epoch.time = flags.at(i).time;\n        if(flags.at(i).values(0) == 1)      // SCA 1\n          epoch.covariance = factor * cov1;\n        else if(flags.at(i).values(0) == 2) // SCA 2\n          epoch.covariance = factor * cov2;\n        else if(flags.at(i).values(0) == 4) // SCA 1 + SCA 2\n          epoch.covariance = factor * cov12;\n        else\n        {\n//           logWarning<<epoch.time.dateTimeStr()<<\" Unknown SCA identification number: \"<<flags.at(i).values(0)<<Log::endl;\n          epoch.covariance = factor * cov12;\n        }\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write covariance data to file <\"<<fileNameCovariance<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameCovariance, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2SteeringMirror.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2SteeringMirror.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Andreas Kvas\n* @date 2019-11-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts GRACE-FO Steering Mirror output (LSM1B) to an \\file{instrument file (STARCAMERA)}{instrument}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2SteeringMirror\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2SteeringMirror, SINGLEPROCESS, \"read GRACE L1B data (LSM1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2SteeringMirror::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileStarCamera\", fileNameOut, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNameIn,  Config::MUSTSET,  \"\", \"LSM1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32    seconds;\n        Double   frac_seconds;\n        Char     gracefo_ID;\n        Double   pitch, yaw;\n        Byte     qualflg;\n\n        try\n        {\n          file>>seconds>>frac_seconds>>gracefo_ID>>yaw>>pitch>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(frac_seconds*1e-9);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        StarCameraEpoch epoch;\n        epoch.time = time;\n        epoch.rotary = rotaryZ(Angle(yaw*1e-6))*rotaryY(Angle(pitch*1e-6));\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Thruster.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Thruster.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2014-05-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts thruster data (THR1B or THR1A) from the GRACE SDS format into \\file{instrument file (THRUSTER)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Thruster\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Thruster, SINGLEPROCESS, \"read GRACE L1B data (THR1B or THR1A)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2Thruster::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileThruster\", fileNameOut, Config::MUSTSET,  \"\", \"THRUSTER\");\n    readConfig(config, \"inputfile\",          fileNameIn,  Config::MUSTSET,  \"\", \"THR1B or THR1A\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        constexpr UInt MAXTHRSTRS = 14;\n        Int32    seconds, time_frac;\n        Char     time_ref, GRACE_id;\n        UInt32   thrust_count[MAXTHRSTRS], on_time[MAXTHRSTRS], accum_dur[MAXTHRSTRS];\n        Byte     qualflg;\n\n        try\n        {\n          file>>seconds>>time_frac>>time_ref>>GRACE_id;\n          for(UInt k=0; k<MAXTHRSTRS; k++)\n            file>>thrust_count[k];\n          for(UInt k=0; k<MAXTHRSTRS; k++)\n            file>>on_time[k];\n          for(UInt k=0; k<MAXTHRSTRS; k++)\n            file>>accum_dur[k];\n          file>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds) + seconds2time(1e-6*time_frac);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n//         if(time_ref != 'G')\n//         {\n//           logWarning<<time.dateTimeStr()<<\" time is not GPS time: '\"<<time_ref<<\"' (ignored)\"<<Log::endl;\n//           continue;\n//         }\n\n        ThrusterEpoch epoch;\n        epoch.time     = time;\n        epoch.onTime1  = on_time[0];\n        epoch.onTime2  = on_time[1];\n        epoch.onTime3  = on_time[2];\n        epoch.onTime4  = on_time[3];\n        epoch.onTime5  = on_time[4];\n        epoch.onTime6  = on_time[5];\n        epoch.onTime7  = on_time[6];\n        epoch.onTime8  = on_time[7];\n        epoch.onTime9  = on_time[8];\n        epoch.onTime10 = on_time[9];\n        epoch.onTime11 = on_time[10];\n        epoch.onTime12 = on_time[11];\n        epoch.onTime13 = on_time[12];\n        epoch.onTime14 = on_time[13];\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2TimeOffset.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2TimeOffset.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2017-02-02\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts time data (TIM1A or TIM1B) from the GRACE SDS format into \\file{instrument file (MISCVALUE)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2TimeOffset\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2TimeOffset, SINGLEPROCESS, \"read GRACE L1B data (TIM1A or TIM1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2TimeOffset::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n    Double                fractionalScale;\n\n    readConfig(config, \"outputfileTime\",  fileNameOut,     Config::MUSTSET,  \"\",     \"MISCVALUE\");\n    readConfig(config, \"fractionalScale\", fractionalScale, Config::MUSTSET,  \"1e-6\", \"1e-6 for GRACE, 1e-9 for GRACE-FO\");\n    readConfig(config, \"inputfile\",       fileNameIn,      Config::MUSTSET,  \"\",     \"TIM1A or TIM1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32 obdh_time;\n        Char  GRACE_id;\n        Int32 TS_suppid, gpstime_intg, gpstime_frac, first_icu_blknr, final_icu_blknr;\n        Byte  qualflg;\n\n        try\n        {\n          file>>obdh_time>>GRACE_id>>TS_suppid>>gpstime_intg>>gpstime_frac>>first_icu_blknr>>final_icu_blknr>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        if((gpstime_intg == 0) || (obdh_time == 0))\n          continue;\n\n        MiscValueEpoch epoch;\n        epoch.time  = mjd2time(51544.5) + seconds2time(obdh_time);\n        epoch.value = (gpstime_intg-obdh_time) + fractionalScale * gpstime_frac;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Uso.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Uso.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Beate Klinger\n* @date 2018-03-27\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts clock data (USO1B) from the GRACE SDS format into \\file{instrument file (MISCVALUES)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Uso\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Uso, SINGLEPROCESS, \"read GRACE L1B data (USO1B)\", Conversion, Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceL1b2Uso::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileUso\", fileNameOut, Config::MUSTSET,  \"\", \"MISCVALUES(uso_freq, K_freq, Ka_freq)\");\n    readConfig(config, \"inputfile\",     fileNameIn,  Config::MUSTSET,  \"\", \"USO1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    Arc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n      UInt numberOfRecords;\n      FileInGrace file(fileNameIn.at(idFile), numberOfRecords);\n\n      for(UInt idEpoch=0; idEpoch<numberOfRecords; idEpoch++)\n      {\n        Int32             seconds;\n        Char              GRACE_id;\n        FileInGrace::Int8 uso_id;\n        Double            uso_freq, K_freq, Ka_freq;\n        Byte              qualflg;\n\n        try\n        {\n          file>>seconds>>GRACE_id>>uso_id>>uso_freq>>K_freq>>Ka_freq>>FileInGrace::flag(qualflg);\n        }\n        catch(std::exception &/*e*/)\n        {\n          // GRACE-FO number of records issue\n          logWarning<<arc.back().time.dateTimeStr()<<\": file ended at \"<<idEpoch<<\" of \"<<numberOfRecords<<\" expected records\"<<Log::endl;\n          break;\n        }\n\n        const Time time = mjd2time(51544.5) + seconds2time(seconds);\n        if(arc.size() && (time <= arc.back().time))\n          logWarning<<\"epoch(\"<<time.dateTimeStr()<<\") <= last epoch(\"<<arc.back().time.dateTimeStr()<<\")\"<<Log::endl;\n\n        MiscValuesEpoch epoch(3);\n        epoch.time      = time;\n        epoch.values(0) = uso_freq;\n        epoch.values(1) = K_freq;\n        epoch.values(2) = Ka_freq;\n        arc.push_back(epoch);\n      } // for(idEpoch)\n    } // for(idFile)\n\n    // =============================================\n\n    logStatus<<\"sort epochs\"<<Log::endl;\n    arc.sort();\n\n    logStatus<<\"eliminate duplicates\"<<Log::endl;\n    const UInt oldSize = arc.size();\n    arc.removeDuplicateEpochs(TRUE/*keepFirst*/);\n    if(arc.size() < oldSize)\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n\n    Arc::printStatistics(arc);\n    if(arc.size() == 0)\n      return;\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceL1b2Vector.cpp",
    "content": "/***********************************************/\n/**\n* @file graceL1b2Vector.cpp\n*\n* @brief Read GRACE L1B data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads vector orientation data (positions of instruments in the satellite frame) from the GRACE SDS format\n(VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B).\nThe \\configFile{outputfileVector}{matrix} is a $(3n\\times1)$ matrix containing $(x,y,z)$ for each record.\nThe GRACE SDS format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\"\ngiven at \\url{http://podaac.jpl.nasa.gov/grace/documentation.html}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"fileGrace.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE L1B data.\n* @ingroup programsConversionGroup */\nclass GraceL1b2Vector\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceL1b2Vector, SINGLEPROCESS, \"read GRACE L1B data (VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B)\", Conversion, Grace, Matrix)\n\n/***********************************************/\n\nvoid GraceL1b2Vector::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n\n    readConfig(config, \"outputfileVector\", fileNameOut, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",        fileNameIn,  Config::MUSTSET,  \"\", \"VGB1B, VGN1B, VGO1B, VKB1B, or VCM1B\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    UInt numberOfRecords;\n    FileInGrace file(fileNameIn, numberOfRecords);\n\n    Vector vec(3*numberOfRecords);\n\n    for(UInt i=0; i<numberOfRecords; i++)\n    {\n      Int32    seconds;\n      Char     GRACE_id;\n      Double   mag, x, y, z;\n      Byte     qualflg;\n\n      file>>seconds>>GRACE_id>>mag>>x>>y>>z>>FileInGrace::flag(qualflg);\n\n      const Time time = mjd2time(51544.5) + seconds2time(seconds);\n      logInfo<<time.dateTimeStr()<<\", flag = \"<<Int(qualflg)<<Log::endl;\n      vec(3*i+0) = mag*x;\n      vec(3*i+1) = mag*y;\n      vec(3*i+2) = mag*z;\n    }\n\n    // =============================================\n\n    if(!fileNameOut.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOut<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOut, vec);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/graceSequenceOfEvents.cpp",
    "content": "/***********************************************/\n/**\n* @file graceSequenceOfEvents.cpp\n*\n* @brief Read GRACE SOE file.\n*\n* @author Beate Klinger\n* @author Torsten Mayer-Guerr\n* @date 2015-01-09\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the GRACE SOE (sequence of events) file/format into \\file{instrument file (MISCVALUES)}{instrument}.\nThe GRACE SOE format is described in \"GRACE Level 1B Data Product User Handbook JPL D-22027\" and \"TN-03\\_SOE\\_format.txt\"\ngiven at \\url{http://podaac.jpl.nasa.gov/grace/documentation.html}.\nThe output is one arc of satellite data which can include data gaps.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GRACE SOE file.\n* @ingroup programsConversionGroup */\nclass GraceSequenceOfEvents\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceSequenceOfEvents, SINGLEPROCESS, \"read GRACE SOE file\", Conversion, Grace)\n\n/***********************************************/\n\nvoid GraceSequenceOfEvents::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameGraceA, fileNameGraceB;\n    FileName    fileName;\n    std::string eventType, mode;\n    Double      sampling = 0;\n\n    std::string choice;\n    readConfig(config, \"outputfileGraceA\", fileNameGraceA, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileGraceB\", fileNameGraceB, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfile\",        fileName,       Config::MUSTSET,  \"{groopsDataDir}/grace/TN-01_SOE.txt\", \"SoE file\");\n    if(readConfigChoice(config, \"events\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"ACCT\", choice, \"DSHL HeaterDisconnect\"))\n      {\n        eventType = \"ACCT\";\n        std::string choice;\n        if(readConfigChoice(config, \"mode\", choice, Config::OPTIONAL, \"\", \"\"))\n        {\n          if(readConfigChoiceElement(config, \"Heater\",   choice, \"DSHL HeaterDisconnect\")) {mode = \"DSHL-HeaterDisconnect-Event\";}\n          if(readConfigChoiceElement(config, \"SetPoint\", choice, \"temperature set point\")) {mode = \"SetPoint\";}\n          endChoice(config);\n        }\n      }\n      if(readConfigChoiceElement(config, \"AOCS\", choice, \"coarse pointing mode or attitude hold mode\"))\n      {\n        eventType = \"AOCS\";\n        std::string choice;\n        if(readConfigChoice(config, \"mode\", choice, Config::OPTIONAL, \"\", \"\"))\n        {\n          if(readConfigChoiceElement(config, \"CPM\", choice, \"coarse pointing mode\")) {mode = \"CPM\";}\n          if(readConfigChoiceElement(config, \"AHM\", choice, \"attitude hold mode\"))   {mode = \"AHM\";}\n          if(readConfigChoiceElement(config, \"SM\",  choice, \"science mode\"))         {mode = \"SM\";}\n          endChoice(config);\n        }\n      }\n      if(readConfigChoiceElement(config, \"ACCR\",  choice, \"ACCR\")) {eventType = \"ACCR\";}\n      if(readConfigChoiceElement(config, \"CMCAL\", choice, \"CoM calibration maneuver\"))\n      {\n        eventType = \"CMCAL\";\n        readConfig(config, \"sampling\", sampling, Config::OPTIONAL, \"\", \"[seconds] create events between start and end of maneuver\");\n      }\n      if(readConfigChoiceElement(config, \"KBRCAL\", choice, \"KBR calibration maneuver\"))\n      {\n        eventType = \"KBRCAL\";\n        readConfig(config, \"sampling\", sampling, Config::OPTIONAL, \"\", \"[seconds] create events between start and end of maneuver\");\n      }\n      if(readConfigChoiceElement(config, \"VCM\",   choice, \"CoM coordinates in SRF (m)\"))              {eventType = \"VCM\";}\n      if(readConfigChoiceElement(config, \"VKB\",   choice, \"KBR phase center coordinates in SRF (m)\")) {eventType = \"VKB\";}\n      if(readConfigChoiceElement(config, \"ICUVP\", choice, \"ICUVP\"))                                   {eventType = \"ICUVP\";}\n      if(readConfigChoiceElement(config, \"IPU\",   choice, \"IPU\"))                                     {eventType = \"IPU\";}\n      if(readConfigChoiceElement(config, \"IPUR\",  choice, \"IPUR\"))                                    {eventType = \"IPUR\";}\n      if(readConfigChoiceElement(config, \"KAMI\",  choice, \"KAMI: time tag offset to Ka-phase meas.\")) {eventType = \"KAMI\";}\n      if(readConfigChoiceElement(config, \"KMI\",   choice, \"K_MI: time tag offset to K-phase meas.\"))  {eventType = \"K_MI\";}\n      if(readConfigChoiceElement(config, \"KTOFF\", choice, \"KTOFF: time tag offset to KBR meas.\"))     {eventType = \"KTOFF\";}\n      if(readConfigChoiceElement(config, \"MANV\",  choice, \"MANV\"))                                    {eventType = \"MANV\";}\n      if(readConfigChoiceElement(config, \"MTE1\",  choice, \"MTE1\"))                                    {eventType = \"MTE1\";}\n      if(readConfigChoiceElement(config, \"MTE2\",  choice, \"MTE2\"))                                    {eventType = \"MTE2\";}\n      if(readConfigChoiceElement(config, \"OCC\",   choice, \"OCC\"))                                     {eventType = \"OCC\";}\n      if(readConfigChoiceElement(config, \"QSA\",   choice, \"SCA to SRF frame rotation\"))               {eventType = \"QSA\";}\n      if(readConfigChoiceElement(config, \"QKS\",   choice, \"SCA to KBR frame rotation\"))               {eventType = \"QKS\";}\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input file <\"<<fileName<<\">\"<<Log::endl;\n    MiscValuesArc arcGraceA;\n    MiscValuesArc arcGraceB;\n\n    InFile file(fileName);\n\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n      if(line.at(0) == 'x')\n        continue; // the line has been deleted from active use.\n\n      std::stringstream ss(line);\n      ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n      Double          seconds;\n      std::string     spaceCraft;\n      std::string     event;\n      UInt            count;\n      std::string     comment;\n      ss>>seconds>>spaceCraft>>event>>count;\n      MiscValuesEpoch epoch(count);\n      epoch.time = mjd2time(51544.5) + seconds2time(seconds);\n      for(UInt i=0; i<count; i++)\n        ss>>epoch.values(i);\n      std::getline(ss, comment);\n\n      if(event != eventType)\n        continue;\n\n      if((!mode.empty()) && (comment.find(mode) == std::string::npos))\n        continue;\n\n      if((event == \"CMCAL\") || (event == \"KBRCAL\"))\n        if((sampling > 0) && (epoch.values(0) == 0)) // maneuver stop\n        {\n          auto sample = [](const Time &timeEnd, const Time &sampling, MiscValuesArc &arc)\n          {\n            if(arc.size() == 0)\n              return;\n            for(;;)\n            {\n              MiscValuesEpoch epoch = arc.back();\n              epoch.time += sampling;\n              if(epoch.time > timeEnd)\n                return;\n              arc.push_back(epoch);\n            }\n          };\n\n          if(spaceCraft == \"GRACEA\")\n            sample(epoch.time, seconds2time(sampling), arcGraceA);\n          else if(spaceCraft == \"GRACEB\")\n            sample(epoch.time, seconds2time(sampling), arcGraceB);\n          continue;\n        }\n\n      if(spaceCraft == \"GRACEA\")\n        arcGraceA.push_back(epoch);\n      else if(spaceCraft == \"GRACEB\")\n        arcGraceB.push_back(epoch);\n    } // for(line)\n\n    logInfo<<\"GRACEA: events = \"<<arcGraceA.size()<<Log::endl;\n    logInfo<<\"GRACEB: events = \"<<arcGraceB.size()<<Log::endl;\n\n\n    // write data\n    // ----------\n    if(!fileNameGraceA.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameGraceA<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameGraceA, arcGraceA);\n    }\n\n    if(!fileNameGraceB.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameGraceB<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameGraceB, arcGraceB);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/orbit2GraceL1b.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2GraceL1b.cpp\n*\n* @brief Read GROOPS L1B data and convert to SDS file format.\n*\n* @author Torsten Mayer-Guerr\n* @date 2026-03-12\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts an \\file{instrument file (ORBIT)}{instrument} specified in the celestial reference frame (CRF)\nto the GRACE/GRACE-FO SDS format (GNV1B, GNI1B). If \\configClass{earthRotation}{earthRotationType} is provided,\nthe orbit is rotated into the terrestrial reference frame as required for the GNV1B product; otherwise,\na GNI1B product is written.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, \\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2Orbit}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GROOPS L1B data and convert to SDS data format.\n* @ingroup programsConversionGroup */\nclass Orbit2GraceL1b\n{\npublic:\n    void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2GraceL1b, SINGLEPROCESS, \"convert GROOPS L1B data to SDS data\", Conversion, Grace, Instrument)\n\n/*************************************************************/\n\nvoid Orbit2GraceL1b::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         fileNameOut;\n    FileName         fileNameHeader, fileNameOrbit;\n    std::string      satelliteId;\n    EarthRotationPtr earthRotation;\n\n    readConfig(config, \"outputfile\",      fileNameOut,    Config::MUSTSET,  \"\",     \"GNV1B/GNI1B\");\n    readConfig(config, \"inputfileHeader\", fileNameHeader, Config::OPTIONAL, \"\",     \"YAML Header, {epochmin}, {epochmax}, {epochcount} available\");\n    readConfig(config, \"inputfileOrbit\",  fileNameOrbit,  Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"satelliteId\",     satelliteId,    Config::MUSTSET,  \"\",     \"A, B, C or D\");\n    readConfig(config, \"earthRotation\",   earthRotation,  Config::OPTIONAL, \"file\", \"rotation into Earth fixed frame\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n\n    logStatus<<\"write SDS output <\"<<fileNameOut<<\">\"<<Log::endl;\n    OrbitArc orbit = InstrumentFile::read(fileNameOrbit);\n    OutFile file(fileNameOut);\n    if(!fileNameHeader.empty())\n    {\n      VariableList varList = config.getVarList();\n      addDataVariables(\"epoch\", orbit.times(), varList);\n\n      InFile fileHeader(fileNameHeader);\n      std::string line;\n      while(std::getline(fileHeader, line))\n        file<<StringParser::parse(line, varList)<<std::endl;\n    }\n    else\n      file<<\"# End of YAML header\"<<std::endl;\n\n    Single::forEach(orbit.size(), [&](UInt i)\n    {\n      Vector3d p = orbit.at(i).position;\n      Vector3d v = orbit.at(i).velocity;\n\n      if(earthRotation)\n      {\n        const Rotary3d rotation = earthRotation->rotaryMatrix(orbit.at(i).time);\n        if(v.r() > 0)\n          v = rotation.rotate(v - crossProduct(earthRotation->rotaryAxis(orbit.at(i).time), p));\n        p = rotation.rotate(p);\n      }\n\n      file<<static_cast<UInt>(std::round((orbit.at(i).time-mjd2time(51544.5)).seconds()))<<\" \"<<satelliteId<<\" \"<<((earthRotation) ? \"E\" : \"I\");\n      file<<p.x()%\" %18.16g\"s<<p.y()%\" %18.16g\"s<<p.z()%\" %18.16g\"s;\n      file<<\" 1e+33 1e+33 1e+33\";\n      file<<v.x()%\" %18.16g\"s<<v.y()%\" %18.16g\"s<<v.z()%\" %18.16g\"s;\n      file<<\" 1e+33 1e+33 1e+33\";\n      file<<\"  10000000\"<<std::endl;\n    });\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/satelliteTracking2GraceL1b.cpp",
    "content": "/***********************************************/\n/**\n* @file satelliteTracking2GraceL1b.cpp\n*\n* @brief Read GROOPS data and convert to GRACE L1B data.\n*\n* @author Felix Oehlinger\n* @date 2026-03-03\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts low-low satellite tracking data (KBR or LRI) from\nthe GROOPS format \\file{instrument file (SATELLITETRACKING)}{instrument}\nto the GRACE SDS format (KBR1B or LRI1B).\nIt reads the satellite tracking data and optionally corrections\n(antenna offsets and light time corrections) and flags into one \\config{outputfile}.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, \\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2SatelliteTracking}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GROOPS L1B data.\n* @ingroup programsConversionGroup */\nclass SatelliteTracking2GraceL1b\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SatelliteTracking2GraceL1b, SINGLEPROCESS, \"read GROOPS L1B data (KBR1B or LRI1B)\", Conversion, Grace, Instrument)\n\n/*************************************************************/\n\nvoid SatelliteTracking2GraceL1b::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut;\n    FileName    fileNameHeader, fileNameSst, fileNameAntCentr, fileNameLighttime, fileNameSnr, fileNameIonoCorr;\n    std::string satelliteId;\n\n    readConfig(config, \"outputfile\",                 fileNameOut,       Config::MUSTSET,  \"\", \"KBR1B or LRI1B\");\n    readConfig(config, \"inputfileHeader\",            fileNameHeader,    Config::OPTIONAL, \"\", \"YAML Header, {epochmin}, {epochmax}, {epochcount} available\");\n    readConfig(config, \"inputfileSatelliteTracking\", fileNameSst,       Config::MUSTSET,  \"\", \"SATELLITETRACKING\");\n    readConfig(config, \"inputfileIonoCorr\",          fileNameIonoCorr,  Config::OPTIONAL, \"\", \"MISCVALUE\");\n    readConfig(config, \"inputfileLighttime\",         fileNameLighttime, Config::OPTIONAL, \"\", \"SATELLITETRACKING\");\n    readConfig(config, \"inputfileAntCentr\",          fileNameAntCentr,  Config::OPTIONAL, \"\", \"SATELLITETRACKING\");\n    readConfig(config, \"inputfileSNR\",               fileNameSnr,       Config::OPTIONAL, \"\", \"MISCVALUES(K_A_SNR, Ka_A_SNR, K_B_SNR, Ka_B_SNR, qualflg)\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"write SDS output <\"<<fileNameOut<<\">\"<<Log::endl;\n    SatelliteTrackingArc arcSst      = InstrumentFile::read(fileNameSst);\n    SatelliteTrackingArc arcLight    = InstrumentFile::read(fileNameLighttime);\n    SatelliteTrackingArc arcAntCentr = InstrumentFile::read(fileNameAntCentr);\n    MiscValueArc         arcIonoCorr = InstrumentFile::read(fileNameIonoCorr);\n    MiscValuesArc        arcSnr      = InstrumentFile::read(fileNameSnr);\n    Arc::checkSynchronized({arcSst, arcIonoCorr, arcLight, arcAntCentr, arcSnr});\n\n    OutFile file(fileNameOut);\n    if(!fileNameHeader.empty())\n    {\n      VariableList varList = config.getVarList();\n      addDataVariables(\"epoch\", arcSst.times(), varList);\n\n      InFile fileHeader(fileNameHeader);\n      std::string line;\n      while(std::getline(fileHeader, line))\n        file<<StringParser::parse(line, varList)<<std::endl;\n    }\n    else\n      file<<\"# End of YAML header\"<<std::endl;\n\n    Single::forEach(arcSst.size(), [&](UInt i)\n    {\n      SatelliteTrackingEpoch sst, light, antCentr;\n      MiscValueEpoch         ionoCorr;\n      MiscValuesEpoch        snr(5);\n\n      sst = arcSst.at(i);\n      if(arcLight   .size()) light    = arcLight.at(i);\n      if(arcAntCentr.size()) antCentr = arcAntCentr.at(i);\n      if(arcIonoCorr.size()) ionoCorr = arcIonoCorr.at(i);\n      if(arcSnr     .size()) snr      = arcSnr.at(i);\n\n      file<<static_cast<UInt>(std::round((arcSst.at(i).time-mjd2time(51544.5)).seconds()));\n      file<<sst.range%\" %.16g\"s<<sst.rangeRate%\" %.16g\"s<<sst.rangeAcceleration%\" %.16g\"s;\n      file<<ionoCorr.value%\" %.16g\"s;\n      file<<light.range%\" %.16g\"s<<light.rangeRate%\" %.16g\"s<<light.rangeAcceleration%\" %.16g\"s;\n      file<<antCentr.range%\" %.16g\"s<<antCentr.rangeRate%\" %.16g\"s<<antCentr.rangeAcceleration%\" %.16g\"s;\n      file<<snr.values.at(0)%\" %i\"s<<snr.values.at(1)%\" %i\"s<<snr.values.at(2)%\" %i\"s<<snr.values.at(3)%\" %i  \"s;\n      const Byte qualflg = static_cast<Byte>(snr.values.at(4));\n      for(UInt k=8; k-->0;)\n        file<<(((qualflg>>k) & 1) ? '1' : '0');\n      file<<std::endl;\n    });\n  }\n  catch(std::exception &e)\n  {\n      GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grace/starCamera2GraceL1b.cpp",
    "content": "/***********************************************/\n/**\n* @file starCamera2GraceL1b.cpp\n*\n* @brief Read GROOPS L1B data and convert to SDS file format.\n*\n* @author Felix Öhlinger\n* @date 2026-03-06\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GROOPS format \\file{instrument file (STARCAMERA)}{instrument} to the GRACE SDS format (SCA1B).\n\nIt reads one \\config{inputfileStarCamera} and optionally one\n\\config{inputfileStarCameraFlags} containing \\file{MISCVALUES}{instrument}(sca\\_id, qual\\_rss, qualflg),\nand writes one SDS output file.\n\nThe text file \\config{inputfileHeader} is placed at the beginning of the \\config{outputfile}.\nThe \\reference{text parser}{general.parser:text} is applied so that all variables can be used.\nIn addition, the times of the data are available with the variables \\verb|{epochmin}|, |\\verb|{epochmax}|,\nand \\verb|{epochcount}|.\n\nSee also \\program{GraceL1b2StarCamera}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/stringParser.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read GROOPS L1B data and convert to SDS data format.\n* @ingroup programsConversionGroup */\nclass StarCamera2GraceL1b\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(StarCamera2GraceL1b, SINGLEPROCESS, \"convert GROOPS L1B data to SDS data (SCA1B)\", Conversion, Grace, Instrument)\n\n/*************************************************************/\n\nvoid StarCamera2GraceL1b::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut;\n    FileName    fileNameHeader, fileNameSca, fileNameFlags;\n    std::string satelliteId;\n\n    readConfig(config, \"outputfile\",               fileNameOut,    Config::MUSTSET,  \"\", \"SCA1B\");\n    readConfig(config, \"inputfileHeader\",          fileNameHeader, Config::OPTIONAL, \"\", \"YAML Header, {epochmin}, {epochmax}, {epochcount} available\");\n    readConfig(config, \"inputfileStarCamera\",      fileNameSca,    Config::MUSTSET,  \"\", \"STARCAMERA\");\n    readConfig(config, \"inputfileStarCameraFlags\", fileNameFlags,  Config::OPTIONAL, \"\", \"MISCVALUES(sca_id, qual_rss, qualflg)\");\n    readConfig(config, \"satelliteId\",              satelliteId,    Config::MUSTSET,  \"\", \"A, B, C or D\");\n    if(isCreateSchema(config)) return;\n\n        // =============================================\n\n    logStatus<<\"write SDS output <\"<<fileNameOut<<\">\"<<Log::endl;\n    StarCameraArc arcSca   = InstrumentFile::read(fileNameSca);\n    MiscValuesArc arcFlags = InstrumentFile::read(fileNameFlags);\n    Arc::checkSynchronized({arcSca, arcFlags});\n\n    OutFile file(fileNameOut);\n    if(!fileNameHeader.empty())\n    {\n      VariableList varList = config.getVarList();\n      addDataVariables(\"epoch\", arcSca.times(), varList);\n\n      InFile fileHeader(fileNameHeader);\n      std::string line;\n      while(std::getline(fileHeader, line))\n        file<<StringParser::parse(line, varList)<<std::endl;\n    }\n    else\n      file<<\"# End of YAML header\"<<std::endl;\n\n    Single::forEach(arcSca.size(), [&](UInt i)\n    {\n      const Vector q = arcSca.at(i).rotary.quaternion();\n      MiscValuesEpoch flags(3);\n      if(arcFlags.size()) flags = arcFlags.at(i);\n\n      file<<static_cast<UInt>(std::round((arcSca.at(i).time-mjd2time(51544.5)).seconds()))<<\" \"<<satelliteId;\n      file<<flags.values.at(0)%\" %i\"s; // sca_id\n      for(UInt k=0; k<4; k++)\n        file<<q(k)%\" %20.16g\"s;\n      file<<flags.values.at(1)%\" %.16g \"s; // qual_rss\n      const Byte qualflg  = static_cast<Byte>(flags.values(2));\n      for(UInt k=8; k-->0;)\n        file<<(((qualflg>>k) & 1) ? '1' : '0');\n      file<<std::endl;\n    });\n  }\n  catch(std::exception &e)\n  {\n      GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/graceAod2TimeSplines.cpp",
    "content": "/***********************************************/\n/**\n* @file graceAod2TimeSplines.cpp\n*\n* @brief Convert AOD1B dealiasing data into linear splines.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the atmospheric and ocean de-aliasing product (AOD1B)\nfrom the GRACE SDS format into \\file{time spline files}{timeSplinesGravityField}.\nMultiple \\config{inputfile}s must be given in the correct time order.\nA linear method is assumed for the interpolation between the given points in time.\n\nThe GRACE SDS format is described in \"AOD1B Product Description Document\"\ngiven at \\url{http://podaac.jpl.nasa.gov/grace/documentation.html}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert AOD1B dealiasing data into linear splines.\n* @ingroup programsConversionGroup */\nclass GraceAod2TimeSplines\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceAod2TimeSplines, SINGLEPROCESS, \"convert AOD1B dealiasing data into linear splines\", Conversion, TimeSplines)\nGROOPS_RENAMED_PROGRAM(GraceCsrAod2TimeSplines, GraceAod2TimeSplines, date2time(2020, 6, 14))\n\n/***********************************************/\n\nvoid GraceAod2TimeSplines::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outputName, atmosName, oceanName, obaName, miscName;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileDealiasing\",     outputName, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileAtmosphere\",     atmosName,  Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileOcean\",          oceanName,  Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileBottomPressure\", obaName,    Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileMisc\",           miscName,   Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfile\",                fileNameIn, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    Double GM = DEFAULT_GM;\n    Double R  = DEFAULT_R;\n    std::vector<Time>   timeList, timeAtmosList, timeOceanList, timeObaList, timeMiscList;\n    std::vector<Matrix> cnmList,      snmList;\n    std::vector<Matrix> cnmAtmosList, snmAtmosList;\n    std::vector<Matrix> cnmOceanList, snmOceanList;\n    std::vector<Matrix> cnmObaList,   snmObaList;\n    std::vector<Matrix> cnmMiscList,  snmMiscList;\n\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n        InFile file(fileNameIn.at(idFile));\n\n        // Header\n        std::string line;\n        UInt dataCount = 0;\n        UInt version   = 9999;\n        UInt degree    = 100;\n        while(!file.eof())\n        {\n          std::getline(file, line);\n          if(line.find(\"CONSTANT GM\")==0)\n            GM = String::toDouble(line.substr(31, 22));\n          if(line.find(\"CONSTANT A\")==0)\n            R = String::toDouble(line.substr(31, 22));\n          if(line.find(\"MAXIMUM DEGREE\")==0)\n            degree = String::toInt(line.substr(32, 3));\n          if(line.find(\"NUMBER OF DATA SETS\")==0)\n            dataCount = String::toInt(line.substr(31, 22));\n          if(line.find(\"SOFTWARE VERSION\")==0)\n            version = String::toInt(line.substr(50, 2));\n          if(line.find(\"END OF HEADER\")==0)\n            break;\n        }\n\n        if(version==9999)\n          logWarning<<\"No SOFTWARE VERSION header record found\"<<Log::endl;\n        if(dataCount==0)\n          logWarning<<\"No NUMBER OF DATA SETS header record found\"<<Log::endl;\n\n        for(UInt k=0; k<dataCount; k++)\n        {\n          // Data Header\n          std::getline(file, line);\n\n          Int year, month, day, hour;\n          if(version==0)\n          {\n            year  = String::toInt(line.substr(39, 4));\n            month = String::toInt(line.substr(44, 2));\n            day   = String::toInt(line.substr(47, 2));\n            hour  = String::toInt(line.substr(50, 2));\n          }\n          else\n          {\n            year  = String::toInt(line.substr(37, 4));\n            month = String::toInt(line.substr(42, 2));\n            day   = String::toInt(line.substr(45, 2));\n            hour  = String::toInt(line.substr(48, 2));\n          }\n          Time time = date2time(year, month, day, hour, 0, 0);\n\n          std::string type;\n          if(version==0)\n            type = \"glo\";\n          else\n            type = line.substr(65,3);\n\n          Matrix cnm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n          Matrix snm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n          if(type != \"tst\")\n          {\n            for(UInt n=0; n<=degree; n++)\n              for(UInt m=0; m<=n; m++)\n              {\n                UInt n2,m2;\n                file>>n2>>m2;\n                file>>cnm(n2,m2)>>snm(n2,m2);\n                std::getline(file, line); // get rest of line\n              }\n          }\n\n          if(type == \"glo\")\n          {\n            timeList.push_back(time);\n            cnmList.push_back(cnm);\n            snmList.push_back(snm);\n          }\n          else if(type == \"atm\")\n          {\n            timeAtmosList.push_back(time);\n            cnmAtmosList.push_back(cnm);\n            snmAtmosList.push_back(snm);\n          }\n          else if(type == \"ocn\")\n          {\n            timeOceanList.push_back(time);\n            cnmOceanList.push_back(cnm);\n            snmOceanList.push_back(snm);\n          }\n          else if(type == \"oba\")\n          {\n            timeObaList.push_back(time);\n            cnmObaList.push_back(cnm);\n            snmObaList.push_back(snm);\n          }\n          else\n          {\n            logInfo<<\"Type: \"<<type<<\", \"<<time.dateTimeStr()<<Log::endl;\n            timeMiscList.push_back(time);\n            cnmMiscList.push_back(cnm);\n            snmMiscList.push_back(snm);\n          }\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    }\n\n    if(!isRegular(timeList) || !isRegular(timeAtmosList) || !isRegular(timeOceanList) || !isRegular(timeObaList) || !isRegular(timeMiscList))\n    {\n      const Time sampling = medianSampling(timeList);\n      for(UInt i=0; i<timeList.size()-1; i++)\n        if((timeList.at(i+1)-timeList.at(i)) > sampling)\n          logWarning<<\"gap between \"<<timeList.at(i).dateTimeStr()<<\" and \"<<timeList.at(i+1).dateTimeStr()<<Log::endl;\n      throw(Exception(\"Spline time series is not regular.\"));\n    }\n\n    // write data\n    // ----------\n    if(!outputName.empty())\n    {\n      logStatus<<\"write dealiasing data to <\"<<outputName.str()<<\">\"<<Log::endl;\n      writeFileTimeSplinesGravityfield(outputName, GM, R, 1/*splineDegree*/, timeList, cnmList, snmList);\n    }\n\n    if(!atmosName.empty())\n    {\n      logStatus<<\"write atmosphere data to <\"<<atmosName.str()<<\">\"<<Log::endl;\n      writeFileTimeSplinesGravityfield(atmosName, GM, R, 1/*splineDegree*/, timeAtmosList, cnmAtmosList, snmAtmosList);\n    }\n\n    if(!oceanName.empty())\n    {\n      logStatus<<\"write ocean data to <\"<<oceanName.str()<<\">\"<<Log::endl;\n      writeFileTimeSplinesGravityfield(oceanName, GM, R, 1/*splineDegree*/, timeOceanList, cnmOceanList, snmOceanList);\n    }\n\n    if(!obaName.empty())\n    {\n      logStatus<<\"write bottom pressure data to <\"<<obaName.str()<<\">\"<<Log::endl;\n      writeFileTimeSplinesGravityfield(obaName, GM, R, 1/*splineDegree*/, timeObaList, cnmObaList, snmObaList);\n    }\n\n    if(!miscName.empty())\n    {\n      logStatus<<\"write misc data to <\"<<miscName.str()<<\">\"<<Log::endl;\n      writeFileTimeSplinesGravityfield(miscName, GM, R, 1/*splineDegree*/, timeMiscList, cnmMiscList, snmMiscList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grail/grailCdr2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file grailCdr2Orbit.cpp\n*\n* @brief read CDR GRAIL data.\n*\n* @author Beate Klinger\n* @date 2013-01-22\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the orbit from the GRAIL SDS format into  \\file{instrument file (ORBIT)}{instrument}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read CDR GRAIL data.\n* @ingroup programsConversionGroup */\nclass GrailCdr2Orbit\n{\n  void readFile(const FileName fileName, OrbitArc &arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GrailCdr2Orbit, SINGLEPROCESS, \"read CDR GRAIL data\", Conversion, Orbit, Instrument)\n\n/***********************************************/\n\nvoid GrailCdr2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<FileName> fileNames;\n\n    readConfig(config, \"outputfileOrbit\", outName,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",       fileNames, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc orbit;\n    for(auto &fileName : fileNames)\n    {\n      logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n      readFile(fileName, orbit);\n    }\n\n    logStatus<<\"write data to <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, orbit);\n    Arc::printStatistics(orbit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GrailCdr2Orbit::readFile(const FileName fileName, OrbitArc &arc)\n{\n  try\n  {\n    InFile file(fileName);\n    if(!file.good())\n    {\n      logWarning<<\"cannot open file: \"<<fileName.str()<<\", continue...\"<<Log::endl;\n      return;\n    }\n    file.exceptions(std::ios::badbit|std::ios::failbit);\n\n    // Header\n    UInt numberOfRecords = 0;\n    std::string line;\n    for(;;)\n    {\n      getline(file, line);\n      if(line.find(\"NUMBER OF DATA RECORDS\")==0)\n        numberOfRecords = String::toInt(line.substr(31, 10));\n      if(line.find(\"END OF HEADER\")==0)\n        break;\n    }\n\n    // Data\n    for(UInt i=0; i<numberOfRecords; i++)\n    {\n      std::string line;\n      try\n      {\n        std::getline(file, line);\n      }\n      catch(std::exception &/*e*/)\n      {\n        //logWarning<<std::endl<<e.what()<<\" continue...\"<<Log::endl;\n        break;\n      }\n      std::stringstream ss(line);\n\n      // time (TDB) >> seconds past 12:00:00 noon 01-Jan-2000\n      UInt seconds;\n      ss>>seconds;\n      OrbitEpoch epoch;\n      epoch.time = timeTT2GPS(mjd2time(51544.5)+seconds2time(seconds));\n\n      // satellite ID, coordinate reference frame\n      Int32 AB;\n      Byte  IE; //Byte\n      ss>>AB>>IE;\n\n      // position + formal error in position\n      Double x_error, y_error, z_error;\n      ss>>epoch.position.x()>>epoch.position.y()>>epoch.position.z();\n      ss>>x_error>>y_error>>z_error;\n\n      // velocity + formalerror in velocity\n      Double dx_error, dy_error, dz_error;\n      ss>>epoch.velocity.x()>>epoch.velocity.y()>>epoch.velocity.z();\n      ss>>dx_error>>dy_error>>dz_error;\n\n      // data quality flags >> data quality flags not defined!\n      //Int flag;\n      //ss>>flag;\n      //if(flag!=0)\n      //  continue;\n\n      arc.push_back(epoch);\n    }\n  }\n\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grail/grailCdr2SatelliteTracking.cpp",
    "content": "/***********************************************/\n/**\n* @file grailCdr2SatelliteTracking.cpp\n*\n* @brief read CDR GRAIL data.\n*\n* @author Beate Klinger\n* @date 2013-01-22\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts low-low satellite data measured by the K-band ranging system\nfrom the GRAIL format into \\file{instrument file (SATELLITETRACKING)}{instrument}.\nThe \\config{inputfile}s contain also corrections for antenna offsets\nand the so called light time correction.\nThe corrections can be stored in additional files in the same format as the observations.\nIf a phase break is found an artificial gap is created.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read CDR GRAIL data.\n* @ingroup programsConversionGroup */\nclass GrailCdr2SatelliteTracking\n{\n  Double timeBias;\n\n  void readFile(const FileName fileName,\n                SatelliteTrackingArc &arc,\n                SatelliteTrackingArc &arcAntenna,\n                SatelliteTrackingArc &arcLight,\n                SatelliteTrackingArc &arcTemperature);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GrailCdr2SatelliteTracking, SINGLEPROCESS, \"read CDR GRAIL data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid GrailCdr2SatelliteTracking::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName, antCentrName, lighttimeName, temperatureName;\n    std::vector<FileName> fileNames;\n\n    readConfig(config, \"outputfileSatelliteTracking\", outName,         Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileAntCentr\",          antCentrName,    Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileLighttime\",         lighttimeName,   Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileTemperature\",       temperatureName, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"approximateTimeBias\",         timeBias,        Config::DEFAULT,  \"0.0\", \"[seconds]\");\n    readConfig(config, \"inputfile\",                   fileNames,       Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    SatelliteTrackingArc arcSST, arcAntenna, arcLight, arcTemperature;\n    for(auto &fileName : fileNames)\n    {\n      logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n      readFile(fileName, arcSST, arcAntenna, arcLight, arcTemperature);\n    }\n\n    Arc::printStatistics(arcSST);\n\n    // Daten speichern\n    // ---------------\n    if(!outName.empty())\n    {\n      logStatus<<\"write data to <\"<<outName<<\">\"<<Log::endl;\n      InstrumentFile::write(outName, arcSST);\n    }\n    if(!antCentrName.empty())\n    {\n      logStatus<<\"write antenna center correction to <\"<<antCentrName<<\">\"<<Log::endl;\n      InstrumentFile::write(antCentrName, arcAntenna);\n    }\n    if(!lighttimeName.empty())\n    {\n      logStatus<<\"write light time correction to <\"<<lighttimeName<<\">\"<<Log::endl;\n      InstrumentFile::write(lighttimeName, arcLight);\n    }\n    if(!temperatureName.empty())\n    {\n      logStatus<<\"write temperature correction to <\"<<temperatureName<<\">\"<<Log::endl;\n      InstrumentFile::write(temperatureName, arcTemperature);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GrailCdr2SatelliteTracking::readFile(const FileName fileName, SatelliteTrackingArc &arc, SatelliteTrackingArc &arcAntenna, SatelliteTrackingArc &arcLight, SatelliteTrackingArc &arcTemperature)\n{\n  try\n  {\n    SatelliteTrackingEpoch epoch, epochAntenna, epochLight, epochTemperature;\n\n    InFile file(fileName);\n    if(!file.good())\n    {\n      logWarning<<\"cannot open file: \"<<fileName.str()<<\", continue...\"<<Log::endl;\n      return;\n    }\n    file.exceptions(std::ios::badbit|std::ios::failbit);\n\n    // Header einlesen\n    UInt numberOfRecords = 0;\n    std::string line;\n    for(;;)\n    {\n      getline(file, line);\n      if(line.find(\"NUMBER OF DATA RECORDS\")==0)\n        numberOfRecords = String::toInt(line.substr(31, 10));\n      // Header fertig ?\n      if(line.find(\"END OF HEADER\")==0)\n        break;\n    }\n\n    // Eigentliche Daten einlesen\n    for(UInt i=0; i<numberOfRecords; i++)\n    {\n      std::string line;\n      try\n      {\n        getline(file, line);\n      }\n      catch(std::exception &/*e*/)\n      {\n        break;\n      }\n\n      std::stringstream ss(line);\n\n      // time (TDB) >> seconds past 12:00:00 noon 01-Jan-2000\n      Int32 seconds;\n      ss>>seconds;\n      epoch.time            = timeTT2GPS(mjd2time(51544.5)+seconds2time(seconds+timeBias));\n      epochLight.time       = epoch.time;\n      epochAntenna.time     = epoch.time;\n      epochTemperature.time = epoch.time;\n\n      // range, range rate, range acceleration\n      ss>>epoch.range>>epoch.rangeRate>>epoch.rangeAcceleration;\n\n      // ionospheric range correction\n      Double iono;\n      ss>>iono;\n\n      // time of flight correction\n      ss>>epochLight.range>>epochLight.rangeRate>>epochLight.rangeAcceleration;\n\n      // Ka-band antenna offset correction\n      ss>>epochAntenna.range>>epochAntenna.rangeRate>>epochAntenna.rangeAcceleration;\n\n      Double dummy1, dummy2, dummy3, dummy4;\n      ss>>dummy1>>dummy2>>dummy3>>dummy4;\n\n      // data quality flags\n      Byte flag0, flag1, flag2, flag3, flag4, flag5, flag6, flag7;\n      ss>>flag0>>flag1>>flag2>>flag3>>flag4>>flag5>>flag6>>flag7;\n\n      // Ka-band temperature correction\n      ss>>dummy1>>epochTemperature.range>>epochTemperature.rangeRate>>epochTemperature.rangeAcceleration;\n\n      Bool phasebreak = ((flag7 & 1) == 1);\n      if(phasebreak)\n      logWarning<<epoch.time.dateTimeStr()<<\": flag=\"<<Int(flag7)<<Log::endl;\n\n      // Sprünge in den Daten suchen\n      if(arc.size() && (epoch.time <= arc.at(arc.size()-1).time))\n          throw(Exception(\"epoch.time <= arc.at(arc.size()-1).time\"));\n      if(phasebreak || (arc.size() && ((epoch.time-arc.at(arc.size()-1).time).seconds()<=5.1) && (fabs(epoch.range - arc.at(arc.size()-1).range)>80)) ||\n        (arc.size() && ((epoch.time-arc.at(arc.size()-1).time).seconds()<=5.1) && (fabs(epoch.rangeRate - arc.at(arc.size()-1).rangeRate)>0.5)) ||\n        (arc.size() && ((epoch.time-arc.at(arc.size()-1).time).seconds()<=5.1) && (fabs(epoch.rangeAcceleration - arc.at(arc.size()-1).rangeAcceleration)>0.0009)))\n      {\n        logWarning<<epoch.time.dateTimeStr()<<\": phase break? (epoch.range - arc.at(arc.size()-1).range) = \"<<epoch.range - arc.at(arc.size()-1).range<<Log::endl;\n        arc.remove(arc.size()-1);\n        arcAntenna.remove(arcAntenna.size()-1);\n        arcLight.remove(arcLight.size()-1);\n        arcTemperature.remove(arcTemperature.size()-1);\n        continue;\n      }\n      else\n      {\n        arc.push_back(epoch);\n        arcAntenna.push_back(epochAntenna);\n        arcLight.push_back(epochLight);\n        arcTemperature.push_back(epochTemperature);\n      }\n    }\n  }\n\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grail/grailCdr2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file grailCdr2StarCamera.cpp\n*\n* @brief read CDR GRAIL data.\n*\n* @author Beate Klinger\n* @date 2013-01-22\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts orientation data measured by a star camera (SRF to CRF)\nfrom the GRAIL SDS format into \\file{instrument file (STARCAMERA)}{instrument}.\nFor further information see \\program{GraceL1b2Accelerometer}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read CDR GRAIL data.\n* @ingroup programsConversionGroup */\nclass GrailCdr2StarCamera\n{\n  void readFile(const FileName fileName, StarCameraArc &arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GrailCdr2StarCamera, SINGLEPROCESS, \"read CDR GRAIL data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid GrailCdr2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<FileName> fileNames;\n\n    readConfig(config, \"outputfileStarCamera\", outName,   Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNames, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arc;\n    for(auto &fileName : fileNames)\n    {\n      logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n      readFile(fileName, arc);\n    }\n\n    logStatus<<\"write data to <\"<<outName.str()<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GrailCdr2StarCamera::readFile(const FileName fileName, StarCameraArc &arc)\n{\n  try\n  {\n    InFile file(fileName);\n    if(!file.good())\n    {\n      logWarning<<\"cannot open file: \"<<fileName.str()<<\", continue...\"<<Log::endl;\n      return;\n    }\n    file.exceptions(std::ios::badbit|std::ios::failbit);\n\n    // Header einlesen\n    UInt numberOfRecords = 0;\n    std::string line;\n    for(;;)\n    {\n      getline(file, line);\n      if(line.find(\"NUMBER OF DATA RECORDS\")==0)\n        numberOfRecords = String::toInt(line.substr(31, 10));\n      // Header fertig ?\n      if(line.find(\"END OF HEADER\")==0)\n        break;\n    }\n\n    // Eigentliche Daten einlesen\n    for(UInt i=0; i<numberOfRecords; i++)\n    {\n      std::string line;\n      try\n      {\n        getline(file, line);\n      }\n      catch(std::exception &/*e*/)\n      {\n        //logWarning<<std::endl<<e.what()<<\" continue...\"<<Log::endl;\n        break;\n      }\n\n      std::stringstream ss(line);\n\n      // time (TDB) >> receiver time, seconds past 12:00:00 noon 01-Jan-2000\n      Int32 seconds;\n      ss>>seconds;\n      StarCameraEpoch epoch;\n      epoch.time = mjd2time(51544.5) + seconds2time(seconds);\n\n      // satellite ID, SCA identification number\n      Byte AB;\n      Int  SCA;\n      ss>>AB>>SCA;\n\n      // quaternions + formal error of quaternions\n      Vector q(4);\n      Double q_res;\n      ss>>q(0)>>q(1)>>q(2)>>q(3)>>q_res;\n      epoch.rotary = Rotary3d(q);\n\n      // data quality flags >> not defined yet\n      //Byte flag;\n      //ss>>flag;\n\n      arc.push_back(epoch);\n    }\n  }\n\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grid/griddedData2NetCdf.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2NetCdf.cpp\n*\n* @brief Convert gridded data to a netCDF file.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2018-06-17\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts a \\configFile{inputfileGriddedData}{griddedData}\nto a COARDS compliant NetCDF file. The output data can be defined with \\config{dataVariable}.\nYou should add at least the attributes \\verb|units|, \\verb|long_name|, and maybe \\verb|_FillValue|\nto the variables. For the \\config{dataVariable:value} the standard \\reference{dataVariables}{general.parser:dataVariables}\nare available to select the data columns of \\configFile{inputfileGriddedData}{griddedData}.\n\nSee also \\program{NetCdfInfo}, \\program{GriddedDataTimeSeries2NetCdf}, \\program{NetCdf2GriddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"inputOutput/fileNetCdf.h\"\n#include \"files/fileGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert gridded data to a netCDF file.\n* @ingroup programsConversionGroup */\nclass GriddedData2NetCdf\n{\npublic:\n  class Attribute\n  {\n  public:\n    std::string         name;\n    std::string         text;\n    std::vector<Double> values;\n    NetCdf::DataType    dataType;\n  };\n\n  class DataVariable\n  {\n  public:\n    std::string            name;\n    ExpressionVariablePtr  valueExpr;\n    Vector                 values;\n    NetCdf::DataType       dataType;\n    std::vector<Attribute> attributes;\n    NetCdf::Variable       variable;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2NetCdf, SINGLEPROCESS, \"Convert gridded data to a netCDF file\", Conversion, Grid)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GriddedData2NetCdf::Attribute &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string choice;\n  if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n    return FALSE;\n  if(readConfigChoiceElement(config, \"text\", choice, \"\"))\n  {\n    readConfig(config, \"name\",  var.name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"value\", var.text, Config::MUSTSET, \"\", \"\");\n  }\n  if(readConfigChoiceElement(config, \"value\",  choice, \"\"))\n  {\n    std::string choice;\n    readConfig(config, \"name\",  var.name,   Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"value\", var.values, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"dataType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"double\", choice, \"\")) var.dataType = NetCdf::DOUBLE;\n      if(readConfigChoiceElement(config, \"float\",  choice, \"\")) var.dataType = NetCdf::FLOAT;\n      if(readConfigChoiceElement(config, \"int\",    choice, \"\")) var.dataType = NetCdf::INT;\n      endChoice(config);\n    }\n  }\n  endChoice(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GriddedData2NetCdf::DataVariable &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"name\",  var.name,      Config::MUSTSET,  \"data0\", \"netCDF variable name\");\n  readConfig(config, \"value\", var.valueExpr, Config::DEFAULT,  \"data0\", \"expression (variables 'height', 'data', 'longitude', 'latitude' and, 'area' are taken from the gridded data\");\n  std::string choice;\n  if(readConfigChoice(config, \"dataType\", choice, Config::MUSTSET, \"\", \"\"))\n  {\n    if(readConfigChoiceElement(config, \"double\", choice, \"\")) var.dataType = NetCdf::DOUBLE;\n    if(readConfigChoiceElement(config, \"float\",  choice, \"\")) var.dataType = NetCdf::FLOAT;\n    if(readConfigChoiceElement(config, \"int\",    choice, \"\")) var.dataType = NetCdf::INT;\n    endChoice(config);\n  }\n  readConfig(config, \"attribute\", var.attributes, Config::OPTIONAL, \"\", \"netCDF attributes\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GriddedData2NetCdf::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                  fileNameOut, fileNameIn;\n    std::vector<DataVariable> dataVariables;\n    std::vector<Attribute>    globalAttributes;\n\n    readConfig(config, \"outputfileNetCdf\",     fileNameOut,      Config::MUSTSET,  \"\", \"file name of NetCDF output\");\n    readConfig(config, \"inputfileGriddedData\", fileNameIn,       Config::MUSTSET,  \"\", \"input grid sequence\");\n    readConfig(config, \"dataVariable\",         dataVariables,    Config::MUSTSET,  \"\", \"metadata for data variables\");\n    readConfig(config, \"globalAttribute\",      globalAttributes, Config::OPTIONAL, \"\", \"additional meta data\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n\n    // read grid\n    // ---------\n    logStatus<<\"read gridded data <\"<<fileNameIn<<\">\"<<Log::endl;\n    GriddedDataRectangular grid;\n    readFileGriddedData(fileNameIn, grid);\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    for(auto &data : dataVariables)\n      data.valueExpr->simplify(varList);\n\n    for(auto &data : dataVariables)\n      data.values = Vector(grid.longitudes.size() * grid.latitudes.size());\n\n    UInt idx = 0;\n    for(UInt i=0; i<grid.latitudes.size(); i++)\n      for(UInt k=0; k<grid.longitudes.size(); k++)\n      {\n        evaluateDataVariables(grid, i, k, varList);\n        for(auto &data : dataVariables)\n          data.values(idx) = data.valueExpr->evaluate(varList);\n        idx++;\n      }\n\n    // write attributes\n    // ----------------\n    logStatus<<\"write NETCDF file <\"<<fileNameOut<<\">\"<<Log::endl;\n    NetCdf::OutFile file(fileNameOut);\n    for(const auto &attr : globalAttributes)\n    {\n      if(attr.text.empty())\n        file.addAttribute(attr.name, attr.dataType, attr.values);\n      else\n        file.addAttribute(attr.name, attr.text);\n    }\n    {\n      auto dim = file.addDimension(\"lat\", grid.latitudes.size());\n      auto var = file.addVariable(\"lat\", NetCdf::DOUBLE, {dim});\n      var.addAttribute(\"units\", \"degrees_north\");\n      Vector lats(grid.latitudes.size());\n      for(UInt i=0; i<grid.latitudes.size(); i++)\n        lats(i) = RAD2DEG * grid.latitudes.at(i);\n      var.setValues(lats);\n    }\n    {\n      auto dim = file.addDimension(\"lon\", grid.longitudes.size());\n      auto var = file.addVariable(\"lon\", NetCdf::DOUBLE, {dim});\n      var.addAttribute(\"units\", \"degrees_east\");\n      Vector lons(grid.longitudes.size());\n      for(UInt i=0; i<grid.longitudes.size(); i++)\n        lons(i) = RAD2DEG * grid.longitudes.at(i);\n      var.setValues(lons);\n    }\n    for(auto &data : dataVariables)\n    {\n      data.variable = file.addVariable(data.name, data.dataType, file.dimensions());\n      for(auto &attr : data.attributes)\n      {\n        if(attr.text.empty())\n          data.variable.addAttribute(attr.name, attr.dataType, attr.values);\n        else\n          data.variable.addAttribute(attr.name, attr.text);\n      }\n      data.variable.setValues({0, 0}, {grid.latitudes.size(), grid.longitudes.size()}, data.values);\n    }\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/conversion/grid/griddedDataTimeSeries2NetCdf.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataTimeSeries2NetCdf.cpp\n*\n* @brief Converts a griddedDataTimeSeries file to a netCDF file.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2018-06-17\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead a \\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nand converts it to a COARDS compliant NetCDF file.\n\nThe output data can be defined with \\config{dataVariable}.\nYou should add at least the attributes \\verb|units|, \\verb|long_name|, and maybe \\verb|_FillValue|\nto the variables. The \\config{dataVariable:inputColumn} selects the data from the input file.\n\nIf \\configClass{timeSeries}{timeSeriesType} is not set\nthe temporal nodal points from the inputfile are used.\n\nSee also \\program{NetCdfInfo}, \\program{GriddedData2NetCdf}, \\program{NetCdf2GriddedDataTimeSeries}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileNetCdf.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts a griddedDataTimeSeries file to a netCDF file.\n* @ingroup programsConversionGroup */\nclass GriddedDataTimeSeries2NetCdf\n{\npublic:\n  class Attribute\n  {\n  public:\n    std::string         name;\n    std::string         text;\n    std::vector<Double> values;\n    NetCdf::DataType    dataType;\n  };\n\n  class DataVariable\n  {\n  public:\n    std::string            name;\n    UInt                   dataField;\n    NetCdf::DataType       dataType;\n    std::vector<Attribute> attributes;\n    NetCdf::Variable       variable;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataTimeSeries2NetCdf, SINGLEPROCESS, \"Converts a griddedDataTimeSeries file to a netCDF file\", Conversion, Grid)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GriddedDataTimeSeries2NetCdf::Attribute &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string choice;\n  if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n    return FALSE;\n  if(readConfigChoiceElement(config, \"text\", choice, \"\"))\n  {\n    readConfig(config, \"name\",  var.name, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"value\", var.text, Config::MUSTSET, \"\", \"\");\n  }\n  if(readConfigChoiceElement(config, \"value\",  choice, \"\"))\n  {\n    std::string choice;\n    readConfig(config, \"name\",  var.name,   Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"value\", var.values, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"dataType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"double\", choice, \"\")) var.dataType = NetCdf::DOUBLE;\n      if(readConfigChoiceElement(config, \"float\",  choice, \"\")) var.dataType = NetCdf::FLOAT;\n      if(readConfigChoiceElement(config, \"int\",    choice, \"\")) var.dataType = NetCdf::INT;\n      endChoice(config);\n    }\n  }\n  endChoice(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GriddedDataTimeSeries2NetCdf::DataVariable &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"name\",        var.name,      Config::MUSTSET,  \"data0\", \"netCDF variable name\");\n  readConfig(config, \"inputColumn\", var.dataField, Config::DEFAULT,  \"0\",     \"input data column\");\n  std::string choice;\n  if(readConfigChoice(config, \"dataType\", choice, Config::MUSTSET, \"\", \"\"))\n  {\n    if(readConfigChoiceElement(config, \"double\", choice, \"\")) var.dataType = NetCdf::DOUBLE;\n    if(readConfigChoiceElement(config, \"float\",  choice, \"\")) var.dataType = NetCdf::FLOAT;\n    if(readConfigChoiceElement(config, \"int\",    choice, \"\")) var.dataType = NetCdf::INT;\n    endChoice(config);\n  }\n  readConfig(config, \"attribute\", var.attributes, Config::OPTIONAL, \"\", \"netCDF attributes\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GriddedDataTimeSeries2NetCdf::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                  fileNameOut, fileNameIn;\n    std::vector<DataVariable> dataVariables;\n    std::vector<Attribute>    globalAttributes;\n    TimeSeriesPtr             timeSeries;\n\n    readConfig(config, \"outputfileNetCdf\",               fileNameOut,      Config::MUSTSET,  \"\", \"file name of NetCDF output\");\n    readConfig(config, \"inputfileGriddedDataTimeSeries\", fileNameIn,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",                     timeSeries,       Config::OPTIONAL, \"\", \"otherwise times from inputfile are used\");\n    readConfig(config, \"dataVariable\",                   dataVariables,    Config::MUSTSET,  \"\", \"metadata for data variables\");\n    readConfig(config, \"globalAttribute\",                globalAttributes, Config::OPTIONAL, \"\", \"additional meta data\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n\n    logStatus<<\"read gridded data time series <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFileGriddedDataTimeSeries fileGriddedDataTimeSeries(fileNameIn);\n    GriddedDataRectangular grid;\n    if(!grid.init(fileGriddedDataTimeSeries.grid()))\n      throw(Exception(\"GriddedData must be a rectangle grid\"));\n    MiscGriddedData::printStatistics(grid);\n    std::vector<Time> times = fileGriddedDataTimeSeries.times();\n    if(timeSeries)\n      times = timeSeries->times();\n\n    // write attributes\n    // ----------------\n    logStatus<<\"write NETCDF file <\"<<fileNameOut<<\">\"<<Log::endl;\n    NetCdf::OutFile file(fileNameOut);\n    for(const auto &attr : globalAttributes)\n    {\n      if(attr.text.empty())\n        file.addAttribute(attr.name, attr.dataType, attr.values);\n      else\n        file.addAttribute(attr.name, attr.text);\n    }\n    {\n      NetCdf::Dimension dim = file.addDimension(\"time\"); // NC_UNLIMITED\n      NetCdf::Variable  var = file.addVariable(\"time\", NetCdf::DOUBLE, {dim});\n      var.addAttribute(\"units\", \"days since 1858-11-17 00:00:00\"); // MJD\n    }\n    {\n      NetCdf::Dimension dim = file.addDimension(\"lat\", grid.latitudes.size());\n      NetCdf::Variable  var = file.addVariable(\"lat\", NetCdf::DOUBLE, {dim});\n      var.addAttribute(\"units\", \"degrees_north\");\n      Vector lats(grid.latitudes.size());\n      for(UInt i=0; i<grid.latitudes.size(); i++)\n        lats(i) = RAD2DEG * grid.latitudes.at(i);\n      var.setValues(lats);\n    }\n    {\n      NetCdf::Dimension dim = file.addDimension(\"lon\", grid.longitudes.size());\n      NetCdf::Variable  var = file.addVariable(\"lon\", NetCdf::DOUBLE, {dim});\n      var.addAttribute(\"units\", \"degrees_east\");\n      Vector lons(grid.longitudes.size());\n      for(UInt i=0; i<grid.longitudes.size(); i++)\n        lons(i) = RAD2DEG * grid.longitudes.at(i);\n      var.setValues(lons);\n    }\n    for(auto &data : dataVariables)\n    {\n      data.variable = file.addVariable(data.name, data.dataType, file.dimensions());\n      for(auto &attr : data.attributes)\n      {\n        if(attr.text.empty())\n          data.variable.addAttribute(attr.name, attr.dataType, attr.values);\n        else\n          data.variable.addAttribute(attr.name, attr.text);\n      }\n    }\n\n    Single::forEach(times.size(), [&](UInt idEpoch)\n    {\n      Matrix values = fileGriddedDataTimeSeries.data(times.at(idEpoch));\n      for(auto &data : dataVariables)\n        data.variable.setValues({idEpoch, 0, 0}, {1, grid.latitudes.size(), grid.longitudes.size()}, Vector(values.column(data.dataField)));\n    });\n\n    Vector mjd(times.size());\n    for(UInt i=0; i<times.size(); i++)\n      mjd(i) = times.at(i).mjd();\n    file.variable(\"time\").setValues(mjd);\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/conversion/grid/netCdf2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file netCdf2GriddedData.cpp\n*\n* @brief Convert COARDS compliant grids to gridded data.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2023-07-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts a COARDS compliant NetCDF file into an\n\\configFile{outputfileGriddedData}{griddedData}.\nIf no specific input \\config{variableNameData} are selected all suitable data are used.\n\nIf the NETCDF file contains a time axis (\\config{variableNameData}) an specific epoch\ncan be selected with \\config{time}. The nearest epoch in file is used.\n\nSee also \\program{NetCdfInfo}, \\program{GriddedData2NetCdf}, \\program{NetCdf2GriddedDataTimeSeries}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileNetCdf.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert COARDS compliant grids to gridded data.\n* @ingroup programsConversionGroup */\nclass NetCdf2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NetCdf2GriddedData, SINGLEPROCESS, \"Convert COARDS compliant grids to gridded data\", Conversion, Grid)\n\n/***********************************************/\n\nvoid NetCdf2GriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameGriddedData, fileNameNetcdf;\n    std::string lonName, latName, timeName;\n    std::vector<std::string> dataNames;\n    Time        time;\n    Double      a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGriddedData, Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileNetCdf\",       fileNameNetcdf,      Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"variableNameLongitude\", lonName,             Config::MUSTSET,  \"lon\",  \"name of NetCDF variable\");\n    readConfig(config, \"variableNameLatitude\",  latName,             Config::MUSTSET,  \"lat\",  \"name of NetCDF variable\");\n    readConfig(config, \"variableNameTime\",      timeName,            Config::OPTIONAL, \"time\", \"if with time axis: name of NetCDF variable\");\n    readConfig(config, \"variableNameData\",      dataNames,           Config::OPTIONAL, \"\",     \"data variables, otherwise all suitable data are used\");\n    readConfig(config, \"time\",                  time,                Config::OPTIONAL, \"\",     \"if with time axis: nearest epoch is used\");\n    readConfig(config, \"R\",                     a,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",     f,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n    // open netCDF file\n    // ----------------\n    logStatus<<\"read NETCDF file <\"<<fileNameNetcdf<<\">\"<<Log::endl;\n    NetCdf::InFile file(fileNameNetcdf);\n    NetCdf::Variable  lon    = file.variable(lonName);\n    NetCdf::Variable  lat    = file.variable(latName);\n    NetCdf::Dimension dimLon = lon.dimensions().at(0);\n    NetCdf::Dimension dimLat = lat.dimensions().at(0);\n\n    // set up grid\n    // -----------\n    GriddedDataRectangular grid;\n    grid.ellipsoid  = Ellipsoid(a, f);\n    grid.longitudes = NetCdf::convertAngles(lon.values());\n    grid.latitudes  = NetCdf::convertAngles(lat.values());\n    grid.heights.resize(grid.latitudes.size(), 0.0);\n\n    // set up time axis\n    // ----------------\n    UInt idEpoch = 0;\n    NetCdf::Dimension dimTime;\n    if(!timeName.empty() && file.hasVariable(timeName))\n    {\n      auto var = file.variable(timeName);\n      dimTime  = var.dimensions().at(0);\n      std::vector<Time> epochs = NetCdf::convertTimes(var.values(), var.attribute(\"units\").value());\n      idEpoch = std::distance(epochs.begin(), std::min_element(epochs.begin(), epochs.end(),\n                              [&](Time &t1, Time &t2) {return std::fabs((t1-time).mjd()) < std::fabs((t2-time).mjd());}));\n      logInfo<<\"  epoch used: \"<<epochs.at(idEpoch).dateTimeStr()<<Log::endl;\n    }\n    else\n      timeName = std::string();\n\n    // set up data columns\n    // -------------------\n    if(!dataNames.size())\n    {\n      for(auto &var : file.variables())\n      {\n        auto dims = var.dimensions();\n        if((std::find(dims.begin(), dims.end(), dimLat) == dims.end()) ||\n           (std::find(dims.begin(), dims.end(), dimLon) == dims.end()))\n          continue;\n        UInt countDims = 0;\n        for(auto &dim : dims)\n          if((dim != dimLat) && (dim != dimLon) && (!timeName.empty() && (dim != dimTime)) && (dim.length() > 1))\n            countDims++;\n        if(countDims <= 1)\n          dataNames.push_back(var.name());\n      }\n      if(!dataNames.size())\n        logWarning<<\"No suitable variables found\"<<Log::endl;\n    }\n\n    // read data variables\n    // -------------------\n    UInt idxCol = 0;\n    for(const std::string &name : dataNames)\n    {\n      NetCdf::Variable var = file.variable(name);\n      std::vector<NetCdf::Dimension> dims = var.dimensions();\n\n      std::stringstream ss;\n      if(dims.size())\n      {\n        ss<<\"(\"<<dims.at(0).name();\n        for(UInt i=1; i<dims.size(); i++)\n          ss<<\", \"<<dims.at(i).name();\n        ss<<\")\";\n      }\n      logInfo<<\"  data\"<<idxCol<<\" = \"<<var.name()<<ss.str()<<Log::endl;\n      for(auto &attr : var.attributes())\n        logInfo<<\"    - \"<<attr.name()<<\" value = \"<<attr.value()<<Log::endl;\n\n      if((std::find(dims.begin(), dims.end(), dimLat) == dims.end()) ||\n         (std::find(dims.begin(), dims.end(), dimLon) == dims.end()))\n        throw(Exception(\"variable <\"+var.name()+\"> must have at least lat, lon dimensions\"));\n\n      std::vector<UInt> start(dims.size(), 0);\n      std::vector<UInt> count(dims.size(), 0);\n      UInt incLat = 0, incLon = 0, incCol = 0;\n      UInt countColumns = 1;\n      UInt inc = 1;\n      for(UInt k=dims.size(); k-->0;)\n      {\n        count.at(k) = dims.at(k).length();\n        if(!timeName.empty() && (dims.at(k) == dimTime))\n        {\n          start.at(k) = idEpoch;\n          count.at(k) = 1;\n        }\n        else\n        {\n          if(dims.at(k) == dimLat)\n            incLat = inc;\n          else if(dims.at(k) == dimLon)\n            incLon = inc;\n          else if(dims.at(k).length() > 1)\n          {\n            if(countColumns > 1)\n              throw(Exception(\"variable <\"+var.name()+\"> has wrong dimensions\"));\n            incCol = inc;\n            countColumns = dims.at(k).length();\n          }\n          inc *= dims.at(k).length();\n        }\n      }\n      idxCol += countColumns;\n\n      // get data\n      const Vector values = var.values(start, count);\n      for(UInt j=0; j<countColumns; j++)\n      {\n        Matrix data(grid.latitudes.size(), grid.longitudes.size());\n        for(UInt i=0; i<grid.latitudes.size(); i++)\n          for(UInt k=0; k<grid.longitudes.size(); k++)\n            data(i, k) = values(incLat*i+incLon*k+incCol*j);\n        grid.values.push_back(data);\n      }\n    }\n\n    // write grid\n    // ----------\n    logStatus<<\"write gridded data to <\"<<fileNameGriddedData<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameGriddedData, grid);\n    MiscGriddedData::printStatistics(grid);\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grid/netCdf2GriddedDataTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file netCdf2GriddedDataTimeSeries.cpp\n*\n* @brief Convert a NetCDF file to a GriddedDataTimeSeries file.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2023-07-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts a COARDS compliant NetCDF file into\n\\configFile{outputfileGriddedDataTimeSeries}{griddedDataTimeSeries}.\nIf no specific input \\config{variableNameData} are selected all suitable data are used.\n\nSee also \\program{NetCdfInfo}, \\program{NetCdf2GriddedData}, \\program{GriddedDataTimeSeries2NetCdf}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileNetCdf.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert a NetCDF file to a GriddedDataTimeSeries file.\n* @ingroup programsConversionGroup */\nclass NetCdf2GriddedDataTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NetCdf2GriddedDataTimeSeries, SINGLEPROCESS, \"Convert a NetCDF file to a GriddedDataTimeSeries file\", Conversion, Grid)\n\n/***********************************************/\n\nvoid NetCdf2GriddedDataTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut, fileNameNetcdf;\n    std::string lonName, latName, timeName;\n    std::vector<std::string> dataNames;\n    Double      a, f;\n\n    readConfig(config, \"outputfileGriddedDataTimeSeries\", fileNameOut,    Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileNetCdf\",                 fileNameNetcdf, Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"variableNameLongitude\",           lonName,        Config::MUSTSET,  \"lon\",  \"name of NetCDF variable\");\n    readConfig(config, \"variableNameLatitude\",            latName,        Config::MUSTSET,  \"lat\",  \"name of NetCDF variable\");\n    readConfig(config, \"variableNameTime\",                timeName,       Config::MUSTSET,  \"time\", \"name of NetCDF variable)\");\n    readConfig(config, \"variableNameData\",                dataNames,      Config::OPTIONAL, \"\",     \"data variables, otherwise all suitable data are used\");\n    readConfig(config, \"R\",                               a,              Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",               f,              Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n    // open netCDF file\n    // ----------------\n    logStatus<<\"read NETCDF file <\"<<fileNameNetcdf<<\">\"<<Log::endl;\n    NetCdf::InFile file(fileNameNetcdf);\n    NetCdf::Variable  lon    = file.variable(lonName);\n    NetCdf::Variable  lat    = file.variable(latName);\n    NetCdf::Dimension dimLon = lon.dimensions().at(0);\n    NetCdf::Dimension dimLat = lat.dimensions().at(0);\n\n    // set up grid\n    // -----------\n    GriddedDataRectangular griddedDataRectangular;\n    griddedDataRectangular.ellipsoid  = Ellipsoid(a, f);\n    griddedDataRectangular.longitudes = NetCdf::convertAngles(lon.values());\n    griddedDataRectangular.latitudes  = NetCdf::convertAngles(lat.values());\n    griddedDataRectangular.heights.resize(griddedDataRectangular.latitudes.size(), 0.0);\n    MiscGriddedData::printStatistics(griddedDataRectangular);\n    GriddedData grid(griddedDataRectangular);\n\n    // set up time axis\n    // ----------------\n    NetCdf::Variable  time    = file.variable(timeName);\n    NetCdf::Dimension dimTime = time.dimensions().at(0);\n    std::vector<Time> times   = NetCdf::convertTimes(time.values(), time.attribute(\"units\").value());\n\n    // set up data columns\n    // -------------------\n    if(!dataNames.size())\n    {\n      for(auto &var : file.variables())\n      {\n        auto dims = var.dimensions();\n        if((std::find(dims.begin(), dims.end(), dimLat)  == dims.end()) ||\n           (std::find(dims.begin(), dims.end(), dimLon)  == dims.end()) ||\n           (std::find(dims.begin(), dims.end(), dimTime) == dims.end()))\n          continue;\n        UInt countDims = 0;\n        for(auto &dim : dims)\n          if((dim != dimLat) && (dim != dimLon) && (dim != dimTime) && (dim.length() > 1))\n            countDims++;\n        if(countDims <= 1)\n          dataNames.push_back(var.name());\n      }\n      if(!dataNames.size())\n        logWarning<<\"No suitable variables found\"<<Log::endl;\n    }\n\n    class Var\n    {\n    public:\n      NetCdf::Variable  var;\n      std::vector<UInt> start, count;\n      UInt              idxTime;\n      UInt              incLat, incLon, incCol;\n      UInt              countColumns;\n    };\n\n    std::vector<Var> vars(dataNames.size());\n    UInt countColumns = 0;\n    for(UInt i=0; i<vars.size(); i++)\n    {\n      vars.at(i).var = file.variable(dataNames.at(i));\n      std::vector<NetCdf::Dimension> dims = vars.at(i).var.dimensions();\n\n      std::stringstream ss;\n      if(dims.size())\n      {\n        ss<<\"(\"<<dims.at(0).name();\n        for(UInt i=1; i<dims.size(); i++)\n          ss<<\", \"<<dims.at(i).name();\n        ss<<\")\";\n      }\n      logInfo<<\"  data\"<<countColumns<<\" = \"<<vars.at(i).var.name()<<ss.str()<<Log::endl;\n      for(auto &attr : vars.at(i).var.attributes())\n        logInfo<<\"    - \"<<attr.name()<<\" value = \"<<attr.value()<<Log::endl;\n\n      if((std::find(dims.begin(), dims.end(), dimLat)  == dims.end()) ||\n         (std::find(dims.begin(), dims.end(), dimLon)  == dims.end()) ||\n         (std::find(dims.begin(), dims.end(), dimTime) == dims.end()))\n        throw(Exception(\"variable <\"+vars.at(i).var.name()+\"> must have at least time, lat, lon dimensions\"));\n\n      vars.at(i).start = vars.at(i).count = std::vector<UInt>(dims.size(), 0);\n      vars.at(i).countColumns = 1;\n      UInt inc = 1;\n      for(UInt k=dims.size(); k-->0;)\n      {\n        vars.at(i).count.at(k) = dims.at(k).length();\n        if(dims.at(k) == dimTime)\n        {\n          vars.at(i).idxTime = k;\n        }\n        else\n        {\n          if(dims.at(k) == dimLat)\n            vars.at(i).incLat = inc;\n          else if(dims.at(k) == dimLon)\n            vars.at(i).incLon = inc;\n          else if(dims.at(k).length() > 1)\n          {\n            if(countColumns > 1)\n              throw(Exception(\"variable <\"+vars.at(i).var.name()+\"> has wrong dimensions\"));\n            vars.at(i).incCol = inc;\n            vars.at(i).countColumns = dims.at(k).length();\n          }\n          inc *= dims.at(k).length();\n        }\n      }\n      countColumns += vars.at(i).countColumns;\n    }\n\n    // read data variables\n    // -------------------\n    std::vector<Matrix> data(times.size(), Matrix(griddedDataRectangular.longitudes.size()*griddedDataRectangular.latitudes.size(), countColumns));\n    Single::forEach(times.size(), [&](UInt idEpoch)\n    {\n      UInt idxCol = 0;\n      for(auto &var : vars)\n      {\n        var.start.at(var.idxTime) = idEpoch;\n        var.count.at(var.idxTime) = 1;\n        const Vector values = var.var.values(var.start, var.count);\n        for(UInt i=0; i<griddedDataRectangular.latitudes.size(); i++)\n          for(UInt k=0; k<griddedDataRectangular.longitudes.size(); k++)\n            for(UInt j=0; j<var.countColumns; j++)\n              data.at(idEpoch)(i*griddedDataRectangular.longitudes.size()+k, idxCol+j) = values(var.incLat*i+var.incLon*k+var.incCol*j);\n        idxCol += var.countColumns;\n      }\n    });\n\n    // write grid\n    // ----------\n    logStatus<<\"write gridded data time series to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedDataTimeSeries(fileNameOut, 1/*splineDegree*/, times, grid, data);\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grid/netCdfInfo.cpp",
    "content": "/***********************************************/\n/**\n* @file netCdfInfo.cpp\n*\n* @brief Content information of a NetCDF file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-09-03\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nPrint content information of a NetCDF file like\ndimensions, variables and attributes.\n\nSee also \\program{NetCdf2GriddedData}, \\program{NetCdf2GriddedDataTimeSeries},\n\\program{GriddedData2NetCdf}, \\program{GriddedDataTimeSeries2NetCdf}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileNetCdf.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Content information of a NetCDF file.\n* @ingroup programsConversionGroup */\nclass NetCdfInfo\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NetCdfInfo, SINGLEPROCESS, \"Content information of a NetCDF file\", Conversion)\n\n/***********************************************/\n\nvoid NetCdfInfo::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameIn;\n\n    readConfig(config, \"inputfileNetCdf\", fileNameIn, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n    // open netCDF file\n    // ----------------\n    logStatus<<\"read netCDF file <\"<<fileNameIn<<\">\"<<Log::endl;\n    NetCdf::InFile file(fileNameIn);\n\n    logInfo<<\"  global attributes:\"<<Log::endl;\n    auto attributes = file.attributes();\n    for(auto &attr : attributes)\n      logInfo<<\"    - \"<<attr.name()<<\" = \"<<attr.value()<<Log::endl;\n\n    logInfo<<\"  dimensions:\"<<Log::endl;\n    auto dimensions = file.dimensions();\n    for(auto &dim : dimensions)\n      logInfo<<\"    - \"<<dim.name()<<\" = \"<<dim.length()<<Log::endl;\n\n    auto variables = file.variables();\n    for(auto &var : variables)\n    {\n      std::stringstream ss;\n      auto dimensions = var.dimensions();\n      if(dimensions.size())\n      {\n        ss<<\"  variable: \"<<var.name()<<\"(\";\n        ss<<dimensions.at(0).name();\n        for(UInt i=1; i<dimensions.size(); i++)\n          ss<<\", \"<<dimensions.at(i).name();\n        ss<<\")\";\n      }\n      else\n        ss<<\"  - \"<<var.name();\n      logInfo<<ss.str()<<Log::endl;\n\n      auto attributes = var.attributes();\n      for(auto &attr : attributes)\n        logInfo<<\"    - \"<<attr.name()<<\" value = \"<<attr.value()<<Log::endl;\n    }\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/grid/oceanTidesDTU2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file oceanTidesDTU2GriddedData.cpp\n*\n* @brief Convert DTU ocean tide grids to griddedData (amplitude, phase).\n*\n* @author Torsten Mayer-Guerr\n* @date 2024-11-09\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert DTU ocean tide grids to griddedData (amplitude, phase).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert DTU ocean tide grids to griddedData (amplitude, phase).\n* @ingroup programsConversionGroup */\nclass OceanTidesDTU2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(OceanTidesDTU2GriddedData, SINGLEPROCESS, \"Convert DTU ocean tide grids to griddedData (amplitude, phase)\", Conversion)\n\n/***********************************************/\n\nvoid OceanTidesDTU2GriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n    Double   a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut, Config::MUSTSET, \"\", \"data0=amplitude, data1=phase\");\n    readConfig(config, \"inputfile\",             fileNameIn,  Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"R\",                     a,           Config::DEFAULT, \"6378136.3\", \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",     f,           Config::DEFAULT, \"298.257\",   \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // =====================================================\n\n    // Create rectangular grid\n    // -----------------------\n    GriddedDataRectangular grid;\n    grid.ellipsoid = Ellipsoid(a,f);\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    for(UInt idx=0; idx<2; idx++) // amplitude, phase\n    {\n      // M2      DTU23 ocean tide constituent\n      //  Phase   (degrees)\n      //       2881      5761\n      //    -90.000    90.000\n      //      0.000   360.000\n      //    999.000   999.000\n      // (11f7.2)\n      UInt   rows, columns;\n      Double minLat, maxLat, minLon, maxLon;\n      Double noValue;\n      std::string line;\n      getline(file, line); // constituent\n      logInfo<<\"'\"<<line<<\"'\"<<Log::endl;\n      getline(file, line); // Amplitude or phase\n      file>>rows>>columns;\n      file>>minLat>>maxLat;\n      file>>minLon>>maxLon;\n      file>>noValue>>noValue;\n      getline(file, line);\n      getline(file, line); // format\n\n      grid.longitudes.resize(columns-1);\n      grid.latitudes.resize(rows);\n      grid.heights.resize(rows);\n      grid.values.resize(2, Matrix(rows, columns-1));\n      for(UInt k=0; k<columns; k++)\n        grid.longitudes.at(k%(columns-1)) = Angle(DEG2RAD*(minLon + k*(maxLon-minLon)/(columns-1)));\n      for(UInt i=0; i<rows; i++)\n        grid.latitudes.at(i) = Angle(DEG2RAD*(minLat + i*(maxLat-minLat)/(rows-1)));\n\n      for(UInt i=0; i<rows; i++)\n        for(UInt k=0; k<columns; k++)\n        {\n          file>>grid.values.at(idx)(i,k%(columns-1));\n          if(grid.values.at(idx)(i,k%(columns-1)) == noValue)\n            grid.values.at(idx)(i,k%(columns-1)) = 0.;\n        }\n      getline(file, line);\n    }\n\n    logStatus<<\"write gridded data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOut, grid);\n    MiscGriddedData::printStatistics(grid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/groopsAscii2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file groopsAscii2Orbit.cpp\n*\n* @brief Read Orbits given in groops kinematic orbit ASCII format.\n*\n* @author Norbert Zehentner\n* @date 2015-01-23\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead Orbits given in groops kinematic orbit ASCII format with covariance information.\n\nSee also \\program{Orbit2GroopsAscii}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read Orbits given in groops kinematic orbit ASCII format.\n* @ingroup programsConversionGroup */\nclass GroopsAscii2Orbit\n{\n  void readFile(const FileName &fileName, OrbitArc &arcOrb, Covariance3dArc &arcCov);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GroopsAscii2Orbit, SINGLEPROCESS, \"read Orbits given in groosp kinematic ASCII format\", Conversion, Orbit, Covariance, Instrument)\nGROOPS_RENAMED_PROGRAM(AsciiKinematic2OrbitCovariance, GroopsAscii2Orbit, date2time(2020, 6, 14))\n\n/***********************************************/\n\nvoid GroopsAscii2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOrbit, fileNameCovariance;\n    std::vector<FileName> fileNamesIn;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileOrbit\",      fileNameOrbit,      Config::OPTIONAL,  \"\", \"\");\n    readConfig(config, \"outputfileCovariance\", fileNameCovariance, Config::OPTIONAL,  \"\", \"\");\n    readConfig(config, \"earthRotation\",        earthRotation,      Config::MUSTSET,   \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNamesIn,        Config::MUSTSET,   \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ===============================================\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc        orbit;\n    Covariance3dArc cov;\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n\n        // skip header\n        std::string line;\n        std::getline(file, line);\n        std::getline(file, line);\n\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            break;\n          std::stringstream ss(line);\n          ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n          LongDouble mjd;\n          Vector3d   pos;\n          Vector     x(6);\n\n          ss>>mjd>>pos.x()>>pos.y()>>pos.z()>>x(0)>>x(1)>>x(2)>>x(3)>>x(4)>>x(5);\n\n          OrbitEpoch        epochOrb;\n          Covariance3dEpoch epochCov;\n          epochOrb.time = epochCov.time = mjd2time(mjd);\n          epochOrb.position = pos;\n          epochCov.setData(x);\n\n          orbit.push_back(epochOrb);\n          cov.push_back(epochCov);\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    } // for(fileName)\n\n    // Rotation TRF -> CRF\n    // -------------------\n    if(earthRotation)\n    {\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(orbit.size(), [&](UInt i)\n      {\n        const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(orbit.at(i).time));\n        orbit.at(i).position = rotation.rotate(orbit.at(i).position);\n        cov.at(i).covariance = rotation.rotate(cov.at(i).covariance);\n      });\n    }\n\n    if(!fileNameOrbit.empty())\n    {\n      logStatus<<\"write orbit data to file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOrbit, orbit);\n      Arc::printStatistics(orbit);\n    }\n\n    if(!fileNameCovariance.empty())\n    {\n      logStatus<<\"write covariance data to file <\"<<fileNameCovariance<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameCovariance, cov);\n      Arc::printStatistics(cov);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/hw2TideGeneratingPotential.cpp",
    "content": "/***********************************************/\n/**\n* @file hw2TideGeneratingPotential.cpp\n*\n* @brief Read tide generating potential from Hartmann and Wenzel 1995.\n* http://bowie.gsfc.nasa.gov/hw95/\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-09-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite \\file{tide generating potential}{tideGeneratingPotential}\nfrom Hartmann and Wenzel 1995 file, \\url{https://doi.org/10.1029/95GL03324}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"base/doodson.h\"\n#include \"base/tideGeneratingPotential.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read tide generating potential from Hartmann and Wenzel 1995.\n* @ingroup programsConversionGroup */\nclass Hw2TideGeneratingPotential\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Hw2TideGeneratingPotential, SINGLEPROCESS, \"Read tide generating potential from Hartmann and Wenzel 1995\", Conversion)\n\n/***********************************************/\n\nvoid Hw2TideGeneratingPotential::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName, inName;\n    UInt     headerLines;\n    Time     time0;\n\n    readConfig(config, \"outputfileTideGeneratingPotential\", outName,     Config::MUSTSET, \"\",           \"\");\n    readConfig(config, \"inputfile\",                         inName,      Config::MUSTSET, \"hw95.dat\",   \"\");\n    readConfig(config, \"headerLines\",                       headerLines, Config::DEFAULT, \"205\",        \"skip number of header lines\");\n    readConfig(config, \"referenceTime\",                     time0,       Config::DEFAULT, STRING_J2000, \"reference time\");\n    if(isCreateSchema(config)) return;\n\n    // =====================================================\n\n    TideGeneratingPotential tgp;\n    tgp.reserve(13000);\n\n    Double T = timeGPS2JC(time0); // julian centuries\n\n    UInt countPermanent = 0;\n    UInt countDegree1  = 0; Double ampDegree1  = 0.;\n    UInt countDegree4  = 0; Double ampDegree4  = 0.;\n    UInt countPlanet   = 0; Double ampPlanet   = 0.;\n    UInt countNDoodson = 0; Double ampNDoodson = 0.;\n\n    // =====================================================\n\n    InFile file(inName);\n\n    // skip header\n    std::string line;\n    for(UInt i=0; i<headerLines; i++)\n      getline(file, line);\n\n    while(file.good())\n    {\n      std::string line;\n      getline(file, line);\n      if(line.empty())\n        continue;\n\n      // line number\n      UInt number = String::toInt(line.substr(0, 6));\n      if(number == 999999)\n        break;\n\n      std::string generatingBody = line.substr(7, 2);\n      const UInt degree = String::toInt(line.substr(9, 2));\n\n      // doodson multipliers\n      std::vector<Int> kn(11);\n      for(UInt i=0; i<kn.size(); i++)\n        kn.at(i) = String::toInt(line.substr(11+3*i, 3));\n\n      // frequency\n      const Double frequency = 86400/3600*DEG2RAD*String::toDouble(line.substr(44, 12)); // degree/hour -> rad/day\n\n      // amplitudes\n      Double c0 = 1e-10 * String::toDouble(line.substr(56, 12));\n      Double s0 = 1e-10 * String::toDouble(line.substr(68, 12));\n      Double ct = 1e-10 * String::toDouble(line.substr(80, 10));\n      Double st = 1e-10 * String::toDouble(line.substr(90, 10));\n\n      // =======================================================\n\n      c0 += ct * T;\n      s0 += st * T;\n      Double ampl = std::sqrt(c0*c0+s0*s0);\n\n      // ignore permanent tides\n      // ----------------------\n      if(std::all_of(kn.begin(), kn.end(), [](Int n){return n==0;}))\n      {\n        countPermanent++;\n        continue;\n      }\n\n      // ignore degree 1\n      // ---------------\n      if(degree == 1)\n      {\n        countDegree1++;\n        ampDegree1 = std::max(ampDegree1, ampl);\n        continue;\n      }\n\n      // use only tides from sun & moon\n      // ------------------------------\n      if(std::any_of(kn.begin()+6, kn.end(), [](Int n){return n!=0;}) || ((generatingBody != \"SU\") && (generatingBody != \"MO\")))\n      {\n        countPlanet++;\n        ampPlanet = std::max(ampPlanet, ampl);\n        continue;\n      }\n\n      // use only degree n=2, n=3\n      // -------------------\n      if(degree > 3)\n      {\n        countDegree4++;\n        ampDegree4 = std::max(ampDegree4, ampl);\n        continue;\n      }\n\n      // skip all frequencies which cannot be doodson coded\n      // --------------------------------------------------\n      {\n        Bool flag = FALSE;\n        for(UInt i=0; i<6; i++)\n          flag |= (kn.at(i)+5 < -13) || (kn.at(i)+5 > 23);   //--> corresponding multipliers ranging from 0 to f\n        if(flag)\n        {\n          countNDoodson++;\n          ampNDoodson = std::max(ampNDoodson, ampl);\n          continue;\n        }\n      }\n\n      // test frequency\n      if(std::fabs(Doodson(kn).frequency()-frequency) > 1e-8)\n        logWarning<<Doodson(kn).name()<<\" frequency difference: \"<<Doodson(kn).frequency()<<\" - \"<<frequency<<\" = \"<<Doodson(kn).frequency()-frequency<<Log::endl;\n\n      tgp.push_back(TideGeneratingConstituent(Doodson(kn), degree, c0, s0));\n    } // while(file.good())\n\n    // find duplicates\n    // ---------------\n    std::stable_sort(tgp.begin(), tgp.end());\n    UInt countDuplicate = 0;\n    for(UInt i=1; i<tgp.size(); i++)\n      if(tgp.at(i-1) == tgp.at(i))\n      {\n        tgp.at(i-1).c += tgp.at(i).c;\n        tgp.at(i-1).s += tgp.at(i).s;\n        tgp.erase(tgp.begin()+i);\n        i--;\n        countDuplicate++;\n      }\n\n    logInfo<<\"constituents used:     \"<<tgp.size()<<Log::endl;\n    logInfo<<\"constituents skipped:\"<<Log::endl;\n    logInfo<<\"  permanent:           \"<<countPermanent<<Log::endl;\n    logInfo<<\"  degree 1:            \"<<countDegree1<<Log::endl;\n    logInfo<<\"  degree >3:           \"<<countDegree4<<Log::endl;\n    logInfo<<\"  not doodson codable: \"<<countNDoodson<<Log::endl;\n    logInfo<<\"  not sun or moon:     \"<<countPlanet<<Log::endl;\n    logInfo<<\"  duplicates:          \"<<countDuplicate<<Log::endl;\n    logInfo<<\"constituents total:    \"<<tgp.size()+countDegree1+countDegree4+countNDoodson+countPlanet+countPermanent+countDuplicate<<Log::endl;\n    logInfo<<\"  max. amplitude (degree 1):            \"<<ampDegree1 <<\" m^2/s^2\"<<Log::endl;\n    logInfo<<\"  max. amplitude (degree >3):           \"<<ampDegree4 <<\" m^2/s^2\"<<Log::endl;\n    logInfo<<\"  max. amplitude (not sun or moon):     \"<<ampPlanet  <<\" m^2/s^2\"<<Log::endl;\n    logInfo<<\"  max. amplitude (not doodson codable): \"<<ampNDoodson<<\" m^2/s^2\"<<Log::endl;\n\n    logStatus<<\"save TGP <\"<<outName<<\">\"<<Log::endl;\n    writeFileTideGeneratingPotential(outName, tgp);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/icgem2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file icgem2PotentialCoefficients.cpp\n*\n* @brief Read spherical harmonics in ICGEM format.\n*\n* @author Andreas Kvas\n* @date 2019-06-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead spherical harmonics in ICGEM format (\\url{http://icgem.gfz-potsdam.de/}).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileSphericalHarmonics.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write spherical harmonics in ICGEM format.\n* @ingroup programsConversionGroup */\nclass Icgem2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  class Coefficient\n  {\n  public:\n    Coefficient(UInt _n, UInt _m, Double _cnm, Double _snm, Double _cnm_e, Double _snm_e) : n(_n), m(_m), cnm(_cnm), snm(_snm), cnm_error(_cnm_e), snm_error(_snm_e) {}\n\n    enum Type {STATIC, STATIC_INTERVAL, TREND, OSC_COSINE, OSC_SINE };\n\n    UInt n, m;\n    Double cnm, snm, cnm_error, snm_error;\n\n    Time t0, t1;\n    Double period;\n\n    Type coefficientType;\n  };\n\n  class Field\n  {\n  public:\n    Field() {}\n\n    explicit Field(UInt maxDegree) :\n      _cnm(Matrix(maxDegree+1, maxDegree+1)),  _snm(Matrix(maxDegree+1, maxDegree+1)),\n      _cnm_error(Matrix(maxDegree+1, maxDegree+1)), _snm_error(Matrix(maxDegree+1, maxDegree+1)) {}\n\n    Matrix _cnm, _snm, _cnm_error, _snm_error;\n  };\n\n};\n\nGROOPS_REGISTER_PROGRAM(Icgem2PotentialCoefficients, SINGLEPROCESS, \"read spherical harmonics in ICGEM format\", Conversion, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Icgem2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameStatic, fileNameTrend, fileNameOscCos, fileNameOscSin, fileNameIntervals;\n    FileName fileNameIn;\n    Bool     useFormalErrors;\n\n    readConfig(config, \"outputfileStaticCoefficients\", fileNameStatic,    Config::MUSTSET,  \"\",  \"static potential coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference\");\n    readConfig(config, \"outputfileTrendCoefficients\",  fileNameTrend,     Config::OPTIONAL, \"\",  \"trend potential coefficients in GROOPS gfc format.  Available variables (icgem2.0): epochStart, epochEnd, epochMid; (icgem1.0) epochReference\");\n    readConfig(config, \"outputfileOscillationCosine\",  fileNameOscCos,    Config::OPTIONAL, \"\",  \"oscillation cosine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod\");\n    readConfig(config, \"outputfileOscillationSine\",    fileNameOscSin,    Config::OPTIONAL, \"\",  \"oscillation sine coefficients in GROOPS gfc format. Available variables (icgem2.0): epochStart, epochEnd, epochMid, oscillationPeriod; (icgem1.0) epochReference, oscillationPeriod\");\n    readConfig(config, \"outputfileIntervals\",          fileNameIntervals, Config::OPTIONAL, \"\",  \"two column ASCII file with all intervals found (only sensible for icgem2.0). The base name will be extended with .static, .trend, .annualCos, and .annualSin.\");\n    readConfig(config, \"inputfileIcgem\",               fileNameIn,        Config::MUSTSET,  \"\",  \"ICGEM GFC file\");\n    readConfig(config, \"useFormalErrors\",              useFormalErrors,   Config::DEFAULT,  \"0\", \"use formal errors if both formal and calibrated errors are given\");\n    if(isCreateSchema(config)) return;\n\n    // convenience functions\n    // ---------------------\n    auto parseTimeStamp = [](const std::string &timeStamp)\n    {\n      UInt year  = std::stoul(timeStamp.substr(0, 4));\n      UInt month = std::stoul(timeStamp.substr(4, 2));\n      UInt day   = std::stoul(timeStamp.substr(6, 2));\n      Double fraction = 0.0;\n      if(timeStamp.find('.') != std::string::npos)\n        fraction = std::stod(timeStamp.substr(8, timeStamp.size()-8));\n      return date2time(year, month, day) + mjd2time(fraction);\n    };\n\n    auto splitLine = [](const std::string &line)\n    {\n      std::vector<std::string> tokens;\n      std::stringstream ss(line);\n      std::string token;\n      while(ss >> token)\n        tokens.push_back(token);\n      return tokens;\n    };\n\n    // read header\n    // -----------\n    logStatus<<\"read header of file <\"<<fileNameIn<<\">\"<<Log::endl;\n    Double GM, R;\n    Bool hasFormalError = FALSE;\n    Bool hasCalibratedError = FALSE;\n    Bool isVersion2 = FALSE;\n\n    InFile inputFile(fileNameIn);\n    std::string line;\n    while(!inputFile.eof())\n    {\n      std::getline(inputFile, line);\n      if(String::startsWith(line, \"earth_gravity_constant\"))\n      {\n        std::stringstream ss(line);\n        std::string dummy; ss>>dummy; ss>>GM;\n      }\n      if(String::startsWith(line, \"radius\"))\n      {\n        std::stringstream ss(line);\n        std::string dummy; ss>>dummy; ss>>R;\n      }\n      if(String::startsWith(line, \"format\"))\n      {\n        std::stringstream ss(line);\n        std::string dummy; ss>>dummy; ss>>dummy;\n        if(dummy == \"icgem2.0\")\n          isVersion2 = TRUE;\n      }\n      if(String::startsWith(line, \"errors\"))\n      {\n        std::stringstream ss(line);\n        std::string dummy; ss>>dummy; ss>>dummy;\n        if(dummy == \"calibrated\")\n          hasCalibratedError = TRUE;\n\n        if(dummy == \"formal\")\n          hasFormalError = TRUE;\n\n        if(dummy == \"calibrated_and_formal\")\n        {\n          hasCalibratedError = TRUE;\n          hasFormalError = TRUE;\n        }\n\n      }\n      if(String::startsWith(line, \"end_of_head\"))\n        break;\n    }\n\n    // read data\n    // ---------\n    logStatus<<\"read potential coeffcients\"<<Log::endl;\n    std::vector<Coefficient> coefficients;\n    UInt maxDegree = 0;\n    while(!inputFile.eof())\n    {\n      std::getline(inputFile, line);\n      if(line.size() == 0)\n        continue;\n      std::vector<std::string> tokens = splitLine(line);\n      if(tokens.size()<5)\n        continue;\n      UInt offset = 1;\n      UInt n = std::stoul(tokens.at(offset++));\n      maxDegree = std::max(n, maxDegree);\n      UInt m = std::stoul(tokens.at(offset++));\n\n      Double cnm = std::stod(tokens.at(offset++));\n      Double snm = std::stod(tokens.at(offset++));\n\n      Double cnm_error = 0.0;\n      Double snm_error = 0.0;\n\n      if(hasFormalError && hasCalibratedError)\n      {\n        if(useFormalErrors) offset += 2;\n        cnm_error = std::stod(tokens.at(offset++));\n        snm_error = std::stod(tokens.at(offset++));\n      }\n      if(hasFormalError || hasCalibratedError)\n      {\n        cnm_error = std::stod(tokens.at(offset++));\n        snm_error = std::stod(tokens.at(offset++));\n      }\n      Coefficient c(n, m, cnm, snm, cnm_error*cnm_error, snm_error*snm_error);\n\n      Time versionOneRefTime;\n      if(tokens.front() == \"gfc\")\n      {\n        c.coefficientType = Coefficient::STATIC;\n      }\n      else if(tokens.front() == \"gfct\")\n      {\n        c.coefficientType = Coefficient::STATIC_INTERVAL;\n        c.t0 = parseTimeStamp(tokens.at(offset++));\n        versionOneRefTime = c.t0;\n        if(isVersion2)\n          c.t1 = parseTimeStamp(tokens.at(offset++));\n      }\n      else if(tokens.front() == \"trnd\")\n      {\n        c.coefficientType = Coefficient::TREND;\n        if(isVersion2)\n        {\n          c.t0 = parseTimeStamp(tokens.at(offset++));\n          c.t1 = parseTimeStamp(tokens.at(offset++));\n        }\n      }\n      else if(tokens.front() == \"acos\")\n      {\n        c.coefficientType = Coefficient::OSC_COSINE;\n        if(isVersion2)\n        {\n          c.t0 = parseTimeStamp(tokens.at(offset++));\n          c.t1 = parseTimeStamp(tokens.at(offset++));\n        }\n        c.period = std::stod(tokens.at(offset));\n      }\n      else if(tokens.front() == \"asin\")\n      {\n        c.coefficientType = Coefficient::OSC_SINE;\n        if(isVersion2)\n        {\n          c.t0 = parseTimeStamp(tokens.at(offset++));\n          c.t1 = parseTimeStamp(tokens.at(offset++));\n        }\n        c.period = std::stod(tokens.at(offset));\n      }\n      if(!isVersion2)\n      {\n        c.t0 = versionOneRefTime;\n        c.t1 = versionOneRefTime;\n      }\n      coefficients.push_back(c);\n    }\n    // sort and reorder data\n    // ---------------------\n    logStatus<<\"split coefficients into static and time-variable parts\"<<Log::endl;\n    if(!isVersion2)\n    {\n      Time refTime;\n      VariableList fileNameVariableList;\n      {\n        Field staticField(maxDegree);\n        for(const Coefficient &c : coefficients)\n        {\n          if( (c.coefficientType == Coefficient::STATIC) || (c.coefficientType == Coefficient::STATIC_INTERVAL) )\n          {\n            staticField._cnm(c.n, c.m) = c.cnm;\n            staticField._snm(c.n, c.m) = c.snm;\n            staticField._cnm_error(c.n, c.m) = c.cnm_error;\n            staticField._snm_error(c.n, c.m) = c.snm_error;\n            if(c.coefficientType == Coefficient::STATIC_INTERVAL)\n              refTime = c.t0;\n          }\n        }\n        SphericalHarmonics harm(GM, R, staticField._cnm, staticField._snm, staticField._cnm_error, staticField._snm_error);\n        fileNameVariableList.setVariable(\"epochReference\", refTime.mjd());\n        logStatus<<\"write static potential coefficients to <\"<<fileNameStatic(fileNameVariableList)<<\">\"<<Log::endl;\n        writeFileSphericalHarmonics(fileNameStatic(fileNameVariableList), harm);\n      }\n\n      if(!fileNameTrend.empty())\n      {\n        Field trendField(maxDegree);\n        UInt maxDegreeTemp = 0;\n        for(const Coefficient &c : coefficients)\n          if( (c.coefficientType == Coefficient::TREND) )\n          {\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n            trendField._cnm(c.n, c.m) = c.cnm;\n            trendField._snm(c.n, c.m) = c.snm;\n            trendField._cnm_error(c.n, c.m) = c.cnm_error;\n            trendField._snm_error(c.n, c.m) = c.snm_error;\n          }\n        SphericalHarmonics harm(GM, R, trendField._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n        trendField._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n        trendField._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n        trendField._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n        logStatus<<\"write trend potential coefficients to <\"<<fileNameTrend(fileNameVariableList)<<\">\"<<Log::endl;\n        writeFileSphericalHarmonics(fileNameTrend(fileNameVariableList), harm);\n      }\n\n      if(!fileNameOscCos.empty())\n      {\n        std::map<Double, Field> oscillationMap;\n        UInt maxDegreeTemp = 0;\n        for(const Coefficient &c : coefficients)\n          if( (c.coefficientType == Coefficient::OSC_COSINE) )\n          {\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n            if(oscillationMap.find(c.period) == oscillationMap.end())\n              oscillationMap[c.period] = Field(maxDegree);\n\n            oscillationMap[c.period]._cnm(c.n, c.m) = c.cnm;\n            oscillationMap[c.period]._snm(c.n, c.m) = c.snm;\n            oscillationMap[c.period]._cnm_error(c.n, c.m) = c.cnm_error;\n            oscillationMap[c.period]._snm_error(c.n, c.m) = c.snm_error;\n          }\n\n        for(auto &entry : oscillationMap)\n        {\n          Double period = entry.first;\n\n          SphericalHarmonics harm(GM, R, entry.second._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n          fileNameVariableList.setVariable(\"oscillationPeriod\", period);\n          logStatus<<\"write cosine potential coefficients to <\"<<fileNameOscCos(fileNameVariableList)<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameOscCos(fileNameVariableList), harm);\n        }\n      }\n      if(!fileNameOscCos.empty())\n      {\n        std::map<Double, Field> oscillationMap;\n        UInt maxDegreeTemp = 0;\n        for(const Coefficient &c : coefficients)\n          if( (c.coefficientType == Coefficient::OSC_SINE) )\n          {\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n            if(oscillationMap.find(c.period) == oscillationMap.end())\n              oscillationMap[c.period] = Field(maxDegree);\n\n            oscillationMap[c.period]._cnm(c.n, c.m) = c.cnm;\n            oscillationMap[c.period]._snm(c.n, c.m) = c.snm;\n            oscillationMap[c.period]._cnm_error(c.n, c.m) = c.cnm_error;\n            oscillationMap[c.period]._snm_error(c.n, c.m) = c.snm_error;\n          }\n\n        for(auto &entry : oscillationMap)\n        {\n          Double period = entry.first;\n\n          SphericalHarmonics harm(GM, R, entry.second._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n          fileNameVariableList.setVariable(\"oscillationPeriod\", period);\n          logStatus<<\"write sine potential coefficients to <\"<<fileNameOscSin(fileNameVariableList)<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameOscSin(fileNameVariableList), harm);\n        }\n      }\n\n    }\n    else // icgem2.0\n    {\n      VariableList fileNameVariableList;\n\n      Field staticGLobal(maxDegree);\n      for(const Coefficient &c : coefficients)\n        if(c.coefficientType == Coefficient::STATIC)\n        {\n          staticGLobal._cnm(c.n, c.m) = c.cnm;\n          staticGLobal._snm(c.n, c.m) = c.snm;\n          staticGLobal._cnm_error(c.n, c.m) = c.cnm_error;\n          staticGLobal._snm_error(c.n, c.m) = c.snm_error;\n        }\n\n      {\n        std::map< std::pair<Time,Time>, Field> staticInterval;\n        UInt maxDegreeTemp = maxDegree;\n        for(const Coefficient &c : coefficients)\n        {\n          if(c.coefficientType == Coefficient::STATIC_INTERVAL)\n          {\n            std::pair<Time, Time> interval(c.t0, c.t1);\n            if(staticInterval.find(interval) == staticInterval.end())\n              staticInterval[interval] = Field(staticGLobal);\n\n            staticInterval[interval]._cnm(c.n, c.m) = c.cnm;\n            staticInterval[interval]._snm(c.n, c.m) = c.snm;\n            staticInterval[interval]._cnm_error(c.n, c.m) = c.cnm_error;\n            staticInterval[interval]._snm_error(c.n, c.m) = c.snm_error;\n\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n          }\n        }\n        if(staticInterval.size() == 0)\n        {\n          SphericalHarmonics harm(GM, R, staticGLobal._cnm, staticGLobal._snm, staticGLobal._cnm_error, staticGLobal._snm_error);\n          logStatus<<\"write static potential coefficients to <\"<<fileNameStatic<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameStatic, harm);\n        }\n        std::vector<std::pair<Double,Double>> intervals;\n        for(auto &entry : staticInterval)\n        {\n          Time timeStart = entry.first.first;\n          Time timeEnd = entry.first.second;\n          fileNameVariableList.setVariable(\"epochStart\", timeStart.mjd());\n          fileNameVariableList.setVariable(\"epochMid\", timeStart.mjd()*0.5 + timeEnd.mjd()*0.5);\n          fileNameVariableList.setVariable(\"epochEnd\", timeEnd.mjd());\n\n          intervals.push_back(std::pair<Double,Double>(timeStart.mjd(), timeEnd.mjd()));\n\n           SphericalHarmonics harm(GM, R, entry.second._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n          logStatus<<\"write static potential coefficients for interval (\"<<timeStart.dateStr()<<\", \"<<timeEnd.dateStr()<<\") to <\"<<fileNameStatic(fileNameVariableList)<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameStatic(fileNameVariableList), harm);\n        }\n        if(!fileNameIntervals.empty())\n        {\n          OutFile intervalFile(fileNameIntervals.appendBaseName(\".static\"));\n          for(auto &i : intervals)\n            intervalFile<<i.first<<\" \"<<i.second<<std::endl;\n        }\n      }\n\n      if(!fileNameTrend.empty())\n      {\n        std::map< std::pair<Time,Time>, Field> trendMap;\n        UInt maxDegreeTemp = 0;\n        for(const Coefficient &c : coefficients)\n        {\n          if(c.coefficientType == Coefficient::TREND)\n          {\n            std::pair<Time, Time> interval(c.t0, c.t1);\n            if(trendMap.find(interval) == trendMap.end())\n              trendMap[interval] = Field(maxDegree);\n\n            trendMap[interval]._cnm(c.n, c.m) = c.cnm;\n            trendMap[interval]._snm(c.n, c.m) = c.snm;\n            trendMap[interval]._cnm_error(c.n, c.m) = c.cnm_error;\n            trendMap[interval]._snm_error(c.n, c.m) = c.snm_error;\n\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n          }\n        }\n        std::vector<std::pair<Double,Double>> intervals;\n        for(auto &entry : trendMap)\n        {\n          Time timeStart = entry.first.first;\n          Time timeEnd = entry.first.second;\n          fileNameVariableList.setVariable(\"epochStart\", timeStart.mjd());\n          fileNameVariableList.setVariable(\"epochMid\", timeStart.mjd()*0.5 + timeEnd.mjd()*0.5);\n          fileNameVariableList.setVariable(\"epochEnd\", timeEnd.mjd());\n\n          intervals.push_back(std::pair<Double,Double>(timeStart.mjd(), timeEnd.mjd()));\n\n          SphericalHarmonics harm(GM, R, entry.second._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n          logStatus<<\"write trend potential coefficients for interval (\"<<timeStart.dateStr()<<\", \"<<timeEnd.dateStr()<<\") to <\"<<fileNameTrend(fileNameVariableList)<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameTrend(fileNameVariableList), harm);\n        }\n        if(!fileNameIntervals.empty())\n        {\n          OutFile intervalFile(fileNameIntervals.appendBaseName(\".trend\"));\n          for(auto &i : intervals)\n            intervalFile<<i.first<<\" \"<<i.second<<std::endl;\n        }\n      }\n\n      if(!fileNameOscCos.empty())\n      {\n        std::map< std::tuple<Time,Time,Double>, Field> oscMap;\n        UInt maxDegreeTemp = 0;\n        for(const Coefficient &c : coefficients)\n        {\n          if(c.coefficientType == Coefficient::OSC_COSINE)\n          {\n            std::tuple<Time, Time, Double> interval(c.t0, c.t1, c.period);\n            if(oscMap.find(interval) == oscMap.end())\n              oscMap[interval] = Field(maxDegree);\n\n            oscMap[interval]._cnm(c.n, c.m) = c.cnm;\n            oscMap[interval]._snm(c.n, c.m) = c.snm;\n            oscMap[interval]._cnm_error(c.n, c.m) = c.cnm_error;\n            oscMap[interval]._snm_error(c.n, c.m) = c.snm_error;\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n          }\n        }\n        std::vector<std::pair<Double,Double>> intervals;\n        for(auto &entry : oscMap)\n        {\n          Time timeStart = std::get<0>(entry.first);\n          Time timeEnd = std::get<1>(entry.first);\n          Double period = std::get<2>(entry.first);\n          fileNameVariableList.setVariable(\"epochStart\", timeStart.mjd());\n          fileNameVariableList.setVariable(\"epochMid\", timeStart.mjd()*0.5 + timeEnd.mjd()*0.5);\n          fileNameVariableList.setVariable(\"epochEnd\", timeEnd.mjd());\n          fileNameVariableList.setVariable(\"oscillationPeriod\", period);\n\n          intervals.push_back(std::pair<Double,Double>(timeStart.mjd(), timeEnd.mjd()));\n\n          SphericalHarmonics harm(GM, R, entry.second._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n          logStatus<<\"write cosine potential coefficients for period \"<<period<<\" in interval (\"<<timeStart.dateStr()<<\", \"<<timeEnd.dateStr()<<\") to <\"<<fileNameOscCos(fileNameVariableList)<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameOscCos(fileNameVariableList), harm);\n        }\n        if(!fileNameIntervals.empty())\n        {\n          OutFile intervalFile(fileNameIntervals.appendBaseName(\".annualCos\"));\n          for(auto &i : intervals)\n            intervalFile<<i.first<<\" \"<<i.second<<std::endl;\n        }\n      }\n      if(!fileNameOscSin.empty())\n      {\n        std::map< std::tuple<Time,Time,Double>, Field> oscMap;\n        UInt maxDegreeTemp = 0;\n        for(const Coefficient &c : coefficients)\n        {\n          if(c.coefficientType == Coefficient::OSC_SINE)\n          {\n            std::tuple<Time, Time, Double> interval(c.t0, c.t1, c.period);\n            if(oscMap.find(interval) == oscMap.end())\n              oscMap[interval] = Field(maxDegree);\n\n            oscMap[interval]._cnm(c.n, c.m) = c.cnm;\n            oscMap[interval]._snm(c.n, c.m) = c.snm;\n            oscMap[interval]._cnm_error(c.n, c.m) = c.cnm_error;\n            oscMap[interval]._snm_error(c.n, c.m) = c.snm_error;\n            maxDegreeTemp = std::max(maxDegreeTemp, c.n);\n          }\n        }\n        std::vector<std::pair<Double,Double>> intervals;\n        for(auto &entry : oscMap)\n        {\n          Time timeStart = std::get<0>(entry.first);\n          Time timeEnd = std::get<1>(entry.first);\n          Double period = std::get<2>(entry.first);\n          fileNameVariableList.setVariable(\"epochStart\", timeStart.mjd());\n          fileNameVariableList.setVariable(\"epochMid\", timeStart.mjd()*0.5 + timeEnd.mjd()*0.5);\n          fileNameVariableList.setVariable(\"epochEnd\", timeEnd.mjd());\n          fileNameVariableList.setVariable(\"oscillationPeriod\", period);\n\n          intervals.push_back(std::pair<Double,Double>(timeStart.mjd(), timeEnd.mjd()));\n\n          SphericalHarmonics harm(GM, R, entry.second._cnm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._cnm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1),\n          entry.second._snm_error.slice(0, 0, maxDegreeTemp+1, maxDegreeTemp+1));\n          logStatus<<\"write sine potential coefficients for period\"<<period<<\" in interval (\"<<timeStart.dateStr()<<\", \"<<timeEnd.dateStr()<<\") to <\"<<fileNameOscSin(fileNameVariableList)<<\">\"<<Log::endl;\n          writeFileSphericalHarmonics(fileNameOscSin(fileNameVariableList), harm);\n        }\n        if(!fileNameIntervals.empty())\n        {\n          OutFile intervalFile(fileNameIntervals.appendBaseName(\".annualSin\"));\n          for(auto &i : intervals)\n            intervalFile<<i.first<<\" \"<<i.second<<std::endl;\n        }\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/iers2OceanPoleTide.cpp",
    "content": "/***********************************************/\n/**\n* @file iers2OceanPoleTide.cpp\n*\n* @brief Read Ocean pole tide model.\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-04-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead ocean pole tide model according to IERS conventions\nand convert into \\file{oceanPoleTide file}{oceanPoleTide}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileOceanPoleTide.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ocean pole tide model.\n* @ingroup programsConversionGroup */\nclass Iers2OceanPoleTide\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Iers2OceanPoleTide, SINGLEPROCESS, \"Read ocean pole tide model\", Conversion)\n\n/***********************************************/\n\nvoid Iers2OceanPoleTide::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outputName, inputName, loveNumberName;\n    Double GM, R, Omega;\n    Double rho, G, g;\n    UInt   maxDegree;\n\n    readConfig(config, \"outputfileOceanPole\",        outputName,     Config::MUSTSET, \"\",                \"\");\n    readConfig(config, \"inputfile\",                  inputName,      Config::MUSTSET, \"\",                \"\");\n    readConfig(config, \"inputfileLoadingLoveNumber\", loveNumberName, Config::MUSTSET, \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"\");\n    readConfig(config, \"maxDegree\",                  maxDegree,      Config::MUSTSET, \"\",                \"\");\n    readConfig(config, \"GM\",                         GM,             Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                          R,              Config::DEFAULT, STRING_DEFAULT_R,  \"Reference radius\");\n    readConfig(config, \"Omega\",                      Omega,          Config::DEFAULT, \"7.292115e-05\",    \"[rad/s] earth rotation\");\n    readConfig(config, \"rho\",                        rho,            Config::DEFAULT, \"1025\",            \"[kg/m**3] density of sea water\");\n    readConfig(config, \"G\",                          G,              Config::DEFAULT, \"6.673e-11\",       \"[m**3/(kg*s**2)] gravitational constant\");\n    readConfig(config, \"g\",                          g,              Config::DEFAULT, \"9.7803278\",       \"[m/s**2] gravity\");\n    if(isCreateSchema(config)) return;\n\n    // Loading Love Numbers\n    // --------------------\n    Vector kn;\n    readFileMatrix(loveNumberName, kn);\n\n    // read potential coefficients\n    // ---------------------------\n    logStatus<<\"read file <\"<<inputName<<\">\"<<Log::endl;\n    Matrix cnmReal(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snmReal(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix cnmImag(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snmImag(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    {\n      InFile file(inputName);\n      std::string line;\n      std::getline(file, line); // read header\n      while(file.good())\n      {\n        std::getline(file, line);\n        if(line.empty())\n          continue;\n        std::stringstream ss(line);\n        ss.exceptions(std::ios::badbit | std::ios::failbit);\n        UInt n,m;\n        ss>>n>>m;\n        if(n<=maxDegree)\n          ss>>cnmReal(n,m)>>snmReal(n,m)>>cnmImag(n,m)>>snmImag(n,m);\n      }\n    }\n\n    // apply factors\n    // -------------\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      const Double f = pow(Omega,2)*pow(R,4)*4*PI*G*rho/GM/g * (1.+kn(n))/(2.*n+1.);\n      cnmReal.row(n) *= f;\n      snmReal.row(n) *= f;\n      cnmImag.row(n) *= f;\n      snmImag.row(n) *= f;\n    }\n\n    // write result\n    // ------------\n    logStatus<<\"write ocean pole tide <\"<<outputName<<\">\"<<Log::endl;\n    writeFileOceanPoleTide(outputName, SphericalHarmonics(GM, R, cnmReal, snmReal), SphericalHarmonics(GM, R, cnmImag, snmImag));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/jplAscii2Ephemerides.cpp",
    "content": "/***********************************************/\n/**\n* @file jplAscii2Ephemerides.cpp\n*\n* @brief Read JPL DExxx ephemerides.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-08-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead JPL DExxx (ASCII) ephemerides.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileEphemerides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read JPL DExxx ephemerides.\n* @ingroup programsConversionGroup */\nclass JplAscii2Ephemerides\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(JplAscii2Ephemerides, SINGLEPROCESS, \"JPL DExxx (ASCII) ephemerides\", Conversion)\n\n/***********************************************/\n\nvoid JplAscii2Ephemerides::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameHeader;\n    std::vector<FileName> fileNamesIn;\n\n    readConfig(config, \"outputfileEphemerides\", fileNameOut,    Config::MUSTSET,  \"JPL_DE432.dat\",  \"\");\n    readConfig(config, \"inputfileHeader\",       fileNameHeader, Config::MUSTSET,  \"header.432_571\", \"\");\n    readConfig(config, \"inputfileData\",         fileNamesIn,    Config::MUSTSET,  \"ascp01950.432\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    auto readDouble = [](InFile &file)\n    {\n      std::string str;\n      file>>str;\n      return String::toDouble(str);\n    };\n\n    logStatus<<\"read header file <\"<<fileNameHeader<<\">\"<<Log::endl;\n    Double            earthMoonRatio = 0;\n    std::vector<UInt> index(15), subintervals(15), components(15), degree(15);\n\n    InFile file(fileNameHeader);\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(String::startsWith(line, \"GROUP   1041\")) // constants\n      {\n        UInt count;\n        file>>count;\n        for(UInt i=0; i<11; i++)\n          earthMoonRatio = readDouble(file);\n      }\n\n      if(String::startsWith(line, \"GROUP   1050\")) // index table\n      {\n        for(UInt i=0; i<index.size(); i++)\n          file>>index.at(i);\n        for(UInt i=0; i<degree.size(); i++)\n          file>>degree.at(i);\n        for(UInt i=0; i<subintervals.size(); i++)\n          file>>subintervals.at(i);\n        components = {3,  // MERCURY\n                      3,  // VENUS\n                      3,  // EARTH\n                      3,  // MARS\n                      3,  // JUPITER\n                      3,  // SATURN\n                      3,  // URANUS\n                      3,  // NEPTUNE\n                      3,  // PLUTO\n                      3,  // MOON\n                      3,  // SUN\n                      2,  // NUTATION\n                      3,  // LIBRATION\n                      3,  // Lunar mantle angular vel\n                      1}; // TT - TDB\n        for(UInt i=0; i<degree.size(); i++)\n          if(degree.at(i))\n            degree.at(i)--;\n        for(UInt i=0; i<subintervals.size(); i++)\n          if(subintervals.at(i) == 0)\n            components.at(i) = 0;\n      }\n    }\n\n    // ==============================\n\n    std::vector<Time> times;\n    std::vector<std::vector<std::vector<Matrix>>> coefficients;\n    for(FileName &filenameIn : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<filenameIn<<\">\"<<Log::endl;\n        InFile file(filenameIn);\n        for(;;)\n        {\n          UInt idx, count;\n          file>>idx>>count;\n          if(file.eof())\n            break;\n\n          Time timeStart = timeTT2GPS(mjd2time(readDouble(file)-2400000.5));\n          Time timeEnd   = timeTT2GPS(mjd2time(readDouble(file)-2400000.5));\n          logInfo<<\"[\"<<timeStart.dateTimeStr()<<\", \"<<timeEnd.dateTimeStr()<<\") days = \"<<(timeEnd-timeStart).mjd()<<Log::endl;\n\n          if(!times.size())\n            times.push_back(timeStart);\n\n          UInt idInterval = std::distance(times.begin(), std::find(times.begin(), times.end(), timeStart));\n          if(idInterval+1 < times.size()) // interval already exists?\n          {\n            if(times.at(idInterval+1) != timeEnd)\n              throw(Exception(\"expected \"+times.at(idInterval+1).dateTimeStr()+\" but get \"+timeEnd.dateTimeStr()));\n          }\n          else\n          {\n            if(idInterval+1 != times.size())\n              throw(Exception(\"expected \"+times.back().dateTimeStr()+\" but get \"+timeStart.dateTimeStr()));\n            times.push_back(timeEnd);\n            coefficients.resize(times.size()-1);\n            coefficients.back().resize(subintervals.size());\n          }\n\n          for(UInt idBody=0; idBody<subintervals.size(); idBody++)\n          {\n            coefficients.at(idInterval).at(idBody).resize(subintervals.at(idBody), Matrix(components.at(idBody), degree.at(idBody)+1));\n            for(UInt idSub=0; idSub<subintervals.at(idBody); idSub++)\n              for(UInt i=0; i<components.at(idBody); i++)\n                for(UInt n=0; n<=degree.at(idBody); n++)\n                  coefficients.at(idInterval).at(idBody).at(idSub)(i, n) = readDouble(file); // km -> m\n          }\n        }\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<std::endl<<e.what()<<\" continue...\"<<Log::endl;\n        continue;\n      }\n    } // for(inputFiles)\n\n    // ==============================\n\n    // km -> m\n    // -------\n    for(UInt idInterval=0; idInterval<coefficients.size(); idInterval++)\n      for(UInt idBody=0; idBody<std::min(std::size_t(11), subintervals.size()); idBody++)\n        for(UInt idSub=0; idSub<subintervals.at(idBody); idSub++)\n          coefficients.at(idInterval).at(idBody).at(idSub) *= 1000;\n\n    // ==============================\n\n    // write results\n    // -------------\n    logStatus<<\"write ephemerides to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileEphemerides(fileNameOut, earthMoonRatio, times, subintervals, components, degree, coefficients);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/normalsSphericalHarmonics2Sinex.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsSphericalHarmonics2Sinex.cpp\n*\n* @brief Write potential coefficients and normal equations to SINEX format.\n*\n* @author Saniya Behzadpour\n* @author Sebastian Strasser\n* @date 2015-03-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite potential coefficients and \\file{normal equations}{normalEquation} to\n\\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}.\n\nSee also \\program{Sinex2Normals} and \\program{GnssNormals2Sinex}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write potential coefficients and normal equations to SINEX format.\n* @ingroup programsConversionGroup */\nclass NormalsSphericalHarmonics2Sinex\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsSphericalHarmonics2Sinex, SINGLEPROCESS, \"Write potential coefficients and normal equations to SINEX format.\", Conversion, NormalEquation)\n\n/***********************************************/\n\nvoid NormalsSphericalHarmonics2Sinex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameSinex;\n    FileName    fileNameNormals;\n    FileName    fileNameSolution, fileNameSigmax, fileNameApriori, fileNameAprMat;\n    Time        time0;\n    Sinex       sinex;\n\n    readConfig(config, \"outputfileSinex\",        fileNameSinex,    Config::MUSTSET,  \"\", \"solutions in SINEX format\");\n    readConfig(config, \"inputfileNormals\",       fileNameNormals,  Config::MUSTSET,  \"\", \"normal equation matrix\");\n    readConfig(config, \"inputfileSolution\",      fileNameSolution, Config::OPTIONAL, \"\", \"parameter vector\");\n    readConfig(config, \"inputfileSigmax\",        fileNameSigmax,   Config::OPTIONAL, \"\", \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n    readConfig(config, \"inputfileApriori\",       fileNameApriori,  Config::MUSTSET,  \"\", \"apriori parameter vector\");\n    readConfig(config, \"inputfileAprioriMatrix\", fileNameAprMat,   Config::OPTIONAL, \"\", \"normal equation matrix of applied constraints\");\n    readConfig(config, \"time\",                   time0,            Config::MUSTSET,  \"\", \"reference time for parameters\");\n    readConfig(config, \"sinexHeader\",            sinex,            Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================================\n\n    // read data from files\n    // --------------------\n    Matrix x;\n    if(!fileNameSolution.empty())\n    {\n      logStatus<<\"reading solution from <\"<<fileNameSolution<<\">\"<<Log::endl;\n      readFileMatrix(fileNameSolution, x);\n    }\n\n    Matrix sigmax;\n    if(!fileNameSigmax.empty())\n    {\n      logStatus<<\"reading standard deviations from <\"<<fileNameSigmax<<\">\"<<Log::endl;\n      readFileMatrix(fileNameSigmax, sigmax);\n    }\n\n    Matrix x0;\n    if(!fileNameApriori.empty())\n    {\n      logStatus<<\"reading apriori solution from <\"<<fileNameApriori<<\">\"<<Log::endl;\n      readFileMatrix(fileNameApriori, x0);\n    }\n\n    Matrix N, n;\n    NormalEquationInfo info;\n    logStatus<<\"reading normal equation matrix from <\"<<fileNameNormals<<\">\"<<Log::endl;\n    readFileNormalEquation(fileNameNormals, info, N, n);\n    fillSymmetric(N);\n    UInt countParameter = N.rows();\n\n    Matrix dN;\n    std::vector<Bool> parameterIsConstrained(countParameter, FALSE);\n    if(!fileNameAprMat.empty())\n    {\n      logStatus<<\"reading normal equation matrix of applied constraints <\"<<fileNameAprMat<<\">\"<<Log::endl;\n      Vector n;\n      NormalEquationInfo info;\n      readFileNormalEquation(fileNameAprMat, info, dN, n);\n      fillSymmetric(dN);\n      if(dN.rows() != parameterIsConstrained.size())\n        throw(Exception(\"Parameter count in constraint matrix and normal equation matrix differs (\"+dN.rows()%\"%i\"s+\" vs. \"+N.rows()%\"%i\"s+\" ).\"));\n      for(UInt i=0; i<dN.rows(); i++)\n        parameterIsConstrained.at(i) = (dN(i, i) != 0.0);\n    }\n\n    // ==================================================\n\n    auto writeVector = [&](SinexBlockPtr block, const Vector x, const Vector sigma=Vector())\n    {\n      for(UInt i=0; i<x.size(); i++)\n      {\n        if(info.parameterName.at(i).type.substr(0,18) != \"sphericalHarmonics\")\n          throw(Exception(\"non spherical harmonics parameter: \" + info.parameterName.at(i).str()));\n\n        const UInt idxDegree = info.parameterName.at(i).type.find_first_of('_')+1;\n        const UInt idxOrder  = info.parameterName.at(i).type.find_last_of('_')+1;\n\n        const std::string degree = std::atoi(info.parameterName.at(i).type.substr(idxDegree,idxOrder-idxDegree-1).c_str())%\"%4i\"s; // degree\n        const std::string order  = std::atoi(info.parameterName.at(i).type.substr(idxOrder).c_str())%\"%4i\"s;                       // order\n\n        *block<<(i+1)%\" %5i \"s<<((info.parameterName.at(i).type[idxDegree-2]=='c') ? \"CN\" : \"SN\")<<\"     \";\n        *block<<degree<<\" -- \"<<order<<\" \"<<Sinex::time2str(time0)<<\" ---- \"<<(parameterIsConstrained.at(i) ? \"1\" : \"2\")<<x(i)%\" %21.14e\"s;\n        if(sigma.size())\n          *block<<sigma(i)%\" %11.4e\"s;\n        *block<<std::endl;\n      }\n    };\n\n    auto writeMatrix = [&](SinexBlockPtr block, const Matrix &N)\n    {\n      for(UInt i=0; i<N.rows(); i++)\n        for(UInt k=i; k<N.rows(); k++)\n          if(N(i,k))\n          {\n            *block<<(i+1)%\" %5i\"s<<(k+1)%\" %5i\"s<<N(i, k)%\" %21.14e\"s;\n            for(UInt l=1; (l<3) && (k+1<N.rows()) && N(i,k+1); l++, k++)\n              *block<<N(i, k+1)%\" %21.14e\"s;\n            *block<<std::endl;\n          }\n    };\n\n    // ==================================================\n\n    // add data to SINEX\n    // -----------------\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/STATISTICS\");\n      *block<<\"*____STATISTICAL_PARAMETER_____ _______VALUE(S)_______\"<<std::endl;\n      *block<<\" NUMBER OF OBSERVATIONS         \"<<info.observationCount%\"%22i\"s<<std::endl;\n      *block<<\" NUMBER OF UNKNOWNS             \"<<countParameter%\"%22i\"s<<std::endl;\n      *block<<\" NUMBER OF DEGREES OF FREEDOM   \"<<(info.observationCount-countParameter)%\"%22i\"s<<std::endl;\n      *block<<\" WEIGHTED SQUARE SUM OF O-C     \"<<info.lPl(0)%\"%22.15e\"s<<std::endl;\n    }\n\n    if(x.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/ESTIMATE\");\n      *block<<\"*INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___ESTIMATED_VALUE___ __STD_DEV__\"<<std::endl;\n      writeVector(block, x, sigmax);\n    }\n\n    if(x0.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/APRIORI\");\n      *block<<\"*INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ____APRIORI_VALUE____ __STD_DEV__\"<<std::endl;\n      writeVector(block, x0, Vector(x0.size()));\n    }\n\n    if(n.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/NORMAL_EQUATION_VECTOR\");\n      *block<<\"*INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___RIGHT_HAND_SIDE___\"<<std::endl;\n      writeVector(block, n);\n    }\n\n    if(N.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/NORMAL_EQUATION_MATRIX U\");\n      *block<<\"*PARA1 PARA2 _______PARA2+0_______ _______PARA2+1_______ _______PARA2+2_______\"<<std::endl;\n      writeMatrix(block, N);\n    }\n\n    if(dN.size())\n    {\n      SinexBlockPtr block = sinex.addBlock(\"SOLUTION/MATRIX_APRIORI U INFO\");\n      *block<<\"*PARA1 PARA2 _______PARA2+0_______ _______PARA2+1_______ _______PARA2+2_______\"<<std::endl;\n      writeMatrix(block, dN);\n    }\n\n    logStatus<<\"write SINEX file <\"<<fileNameSinex<<\">\"<<Log::endl;\n    if(sinex.header.size() > 65)\n      sinex.header.replace(60, 5, countParameter%\"%05i\"s);\n    writeFileSinex(fileNameSinex, sinex);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/orbit2GroopsAscii.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2GroopsAscii.cpp\n*\n* @brief write orbit positions to TVGOGO ASCII format.\n*\n* @author Norbert Zehentner\n* @date 2013-08-06\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert groops orbits and corresponding covariance information to ASCII format.\nThe format is used to publish TUG orbits. It contains a two line header\nwith a short description of the orbit defined in \\config{firstLine}.\nThe orbit is rotated to the Earth fixed frame (TRF) with \\configClass{earthRotation}{earthRotationType} and given as one line per epoch.\nThe epoch lines contained time [MJD GPS time], position x, y and z [m], and the epoch covariance xx, yy, zz, xy, xz and yz [$m^2$].\n\nSee also \\program{GroopsAscii2Orbit}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief write orbit positions into TVGOGO ASCII file.\n* @ingroup programsConversionGroup */\nclass Orbit2GroopsAscii\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2GroopsAscii, SINGLEPROCESS, \"write orbit positions to TUG ASCII format\", Conversion, Orbit, Covariance, Instrument)\nGROOPS_RENAMED_PROGRAM(Orbit2Ascii, Orbit2GroopsAscii, date2time(2020, 6, 14))\n\n/***********************************************/\n\nvoid Orbit2GroopsAscii::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         outName, inName, inNameCov;\n    std::string      textLine1, textDatum;\n    EarthRotationPtr earthRotation;\n\n    readConfig(config, \"outputfile\",          outName,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",      inName,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileCovariance\", inNameCov,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",       earthRotation,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"firstLine\",           textLine1,      Config::OPTIONAL, \"\", \"Text for first line\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read orbit file <\"<<inName<<\">\"<<Log::endl;\n    OrbitArc        orbit = InstrumentFile::read(inName);\n    Covariance3dArc cov   = InstrumentFile::read(inNameCov);\n    Arc::checkSynchronized({orbit, cov});\n\n    logStatus<<\"write file <\"<<outName<<\">\"<<Log::endl;\n    OutFile file(outName);\n    file<<\"# \"<<textLine1<<textDatum<<std::endl;\n    file<<\"# MJD GPS time [days]        x [m]           y [m]           z [m]        xx [m^2]        yy [m^2]        zz [m^2]        xy [m^2]        xz [m^2]        yz [m^2]\"<<std::endl;\n\n    Single::forEach(orbit.size(), [&](UInt i)\n    {\n      const Rotary3d rot      = earthRotation->rotaryMatrix(orbit.at(i).time);\n      const Vector3d position = rot.rotate(orbit.at(i).position);\n      Tensor3d cv;\n      if(cov.size())\n        cv = rot.rotate(cov.at(i).covariance);\n\n      file<<orbit.at(i).time%\"%21.15f\"s;\n      file<<position.x()%\" %15.4f\"s<<position.y()%\" %15.4f\"s<<position.z()%\" %15.4f\"s;\n      file<<cv.xx()%\" %15.8e\"s<<cv.yy()%\" %15.8e\"s<<cv.zz()%\" %15.8e\"s<<cv.xy()%\" %15.8e\"s<<cv.xz()%\" %15.8e\"s<<cv.yz()%\" %15.8e\"s;\n      file<<std::endl;\n    });\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/orbit2Sp3Format.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2Sp3Format.cpp\n*\n* @brief Write orbits (position, velocity, covariance) to SP3 format.\n*\n* @author Norbert Zehentner\n* @author Sebastian Strasser\n* @date 2012-12-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrites orbits to \\href{https://files.igs.org/pub/data/format/sp3d.pdf}{SP3 format}.\n\nSP3 orbits are usually given in the terrestrial reference frame (TRF), so providing \\configClass{earthRotation}{earthRotationType}\nautomatically rotates the orbits from the celestial reference frame (CRF) to the TRF.\nSince SP3 orbits often use the center of Earth as a reference, a correction from center of mass to center\nof Earth can be applied to the orbits by providing \\configClass{gravityfield}{gravityfieldType} (e.g. ocean tides).\n\nSee also \\program{Sp3Format2Orbit}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write orbits (position, velocity, covariance) to SP3 format.\n* @ingroup programsConversionGroup */\nclass Orbit2Sp3Format\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  class Satellite\n  {\n  public:\n    FileName inNameOrbit, inNameClock, inNameCov;\n    std::string identifier;\n    OrbitArc        orbit;\n    MiscValueArc    clock;\n    Covariance3dArc cov;\n    std::vector<Time> times;\n    UInt idEpoch = 0;\n    Double orbitAccuracy;\n  };\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2Sp3Format, SINGLEPROCESS, \"Write orbits (position, velocity, covariance) to SP3 format.\", Conversion, Orbit, Covariance, Instrument)\nGROOPS_RENAMED_PROGRAM(Orbit2Sp3, Orbit2Sp3Format, date2time(2020, 8, 4))\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, Orbit2Sp3Format::Satellite &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileOrbit\",      var.inNameOrbit,    Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"inputfileClock\",      var.inNameClock,    Config::OPTIONAL, \"\", \"\");\n  readConfig(config, \"inputfileCovariance\", var.inNameCov,      Config::OPTIONAL, \"\", \"\");\n  readConfig(config, \"identifier\",          var.identifier,     Config::MUSTSET,  \"\", \"3 characters (e.g. GNSS PRN: G01)\");\n  readConfig(config, \"orbitAccuracy\",       var.orbitAccuracy,  Config::DEFAULT,  \"0\", \"[m] used for accuracy codes in header (0 = unknown)\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid Orbit2Sp3Format::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         outName;\n    Bool             writeVel, useSp3k;\n    EarthRotationPtr earthRotation;\n    GravityfieldPtr  gravityfield;\n    std::string      textLine1;\n    std::vector<std::string> commentLines;\n    std::vector<Satellite>   satellites;\n\n    readConfig(config, \"outputfile\",          outName,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"satellite\",           satellites,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",       earthRotation,  Config::OPTIONAL, \"file\", \"rotate data into Earth-fixed frame\");\n    readConfig(config, \"gravityfield\",        gravityfield,   Config::DEFAULT,  R\"([{\"tides\": {\"tides\": {\"doodsonHarmonicTide\": {\"minDegree\":1, \"maxDegree\":1}}}}])\", \"degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)\");\n    readConfig(config, \"comment\",             commentLines,   Config::OPTIONAL, \"\", \"comment lines (77 char max)\");\n    readConfig(config, \"firstLine\",           textLine1,      Config::DEFAULT,  \"RAW   IGb14 FIT  TUG\", \"Text for first line e.g:  u+U  IGb14 KIN ITSG\");\n    readConfig(config, \"writeVelocity\",       writeVel,       Config::DEFAULT,  \"0\", \"write velocity in addition to position\");\n    readConfig(config, \"useSp3kFormat\",       useSp3k,        Config::DEFAULT,  \"0\", \"use the extended sp3k format\");\n    if(isCreateSchema(config)) return;\n\n    std::set<Time> timesSet; // unique set of times covering all satellites\n\n    auto iter = satellites.begin();\n    while(iter != satellites.end())\n    {\n      try\n      {\n        logStatus<<\"read orbit file <\"<<iter->inNameOrbit<<\">\"<<Log::endl;\n        iter->orbit = InstrumentFile::read(iter->inNameOrbit);\n        iter->clock = InstrumentFile::read(iter->inNameClock);\n        iter->cov   = InstrumentFile::read(iter->inNameCov);\n      }\n      catch(std::exception &e)\n      {\n        logWarning << e.what() << \" continue...\" << Log::endl;\n        iter = satellites.erase(iter);\n        continue;\n      }\n      iter->times = iter->orbit.times();\n      Arc::checkSynchronized({iter->orbit, iter->clock, iter->cov});\n      std::copy(iter->times.begin(), iter->times.end(), std::inserter(timesSet, timesSet.end()));\n      iter++;\n    }\n    const std::vector<Time> times(timesSet.begin(), timesSet.end());\n    const Double sampling = medianSampling(times).seconds();\n\n    logStatus<<\"write file <\"<<outName<<\">\"<<Log::endl;\n    OutFile file(outName);\n\n    const Time timeStart = times.at(0);\n    UInt year, month, day, hour, minute;\n    Double second;\n    timeStart.date(year, month, day, hour, minute, second);\n\n    // first line\n    file<<\"#\"<<(useSp3k?\"k\":\"d\")<<(writeVel?\"V\":\"P\")<<timeStart%\"%y %m %d %H %M %011.8S \"s<<times.size()%\"%7i \"s<<textLine1<<std::endl;\n\n    // second line\n    file<<\"## \"<<timeStart%\"%4W\"<<\" \"<<((timeStart.mjdInt()-44244)%7*86400+timeStart.mjdMod()*86400)%\"%15.8f \"s<<sampling%\"%14.8f \"s<<timeStart.mjdInt()%\"%5i \"s<<timeStart.mjdMod()%\"%15.13f\"s<<std::endl;\n\n    // satellite identifier lines\n    const UInt satPerLine = 17;\n    const UInt lineCount = std::max<UInt>(5, (satellites.size()+satPerLine+1)/satPerLine);\n    for(UInt i = 0; i < lineCount; i++)\n    {\n      if(i == 0)\n        file<<\"+  \"<<satellites.size()%\"% 3i\"s<<\"   \";\n      else\n        file<<\"+        \";\n      for(UInt j = 0; j < satPerLine; j++)\n      {\n        const UInt idSat = i*satPerLine+j;\n        if(idSat < satellites.size())\n          file<<satellites.at(i*satPerLine+j).identifier;\n        else\n          file<<\"  0\";\n      }\n      file<<std::endl;\n    }\n\n    // satellite accuracy lines\n    for(UInt i=0; i<lineCount; i++)\n    {\n      file<<\"++       \";\n      for(UInt j=0; j<satPerLine; j++)\n      {\n        const UInt idSat = i*satPerLine+j;\n        if(idSat < satellites.size() && satellites.at(i*satPerLine+j).orbitAccuracy > 0)\n          file<<std::round(std::log2(satellites.at(i*satPerLine+j).orbitAccuracy*1e3))%\"% 3i\"s;\n        else\n          file<<\"  0\";\n      }\n      file<<std::endl;\n    }\n\n    file<<\"%c M  cc GPS ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc\"<<std::endl;\n    file<<\"%c cc cc ccc ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc\"<<std::endl;\n    file<<\"%f  1.2500000  1.025000000  0.00000000000  0.000000000000000\"<<std::endl;\n    file<<\"%f  0.0000000  0.000000000  0.00000000000  0.000000000000000\"<<std::endl;\n    file<<\"%i    0    0    0    0      0      0      0      0         0\"<<std::endl;\n    file<<\"%i    0    0    0    0      0      0      0      0         0\"<<std::endl;\n\n    // comment lines\n    for(UInt i = 0; i < std::max<UInt>(commentLines.size(), 4); i++)\n    {\n      if(i < commentLines.size())\n        file<<\"/* \"<<commentLines.at(i)<<std::endl;\n      else\n        file<<\"/* CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\"<<std::endl;\n    }\n\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      file<<\"*  \"<<times.at(i)%\"%y %m %d %H %M %011.8S\"s<<std::endl;\n\n      Rotary3d rot;\n      Vector3d omega;\n      if(earthRotation)\n      {\n        rot   = earthRotation->rotaryMatrix(times.at(i));\n        if(writeVel)\n          omega = earthRotation->rotaryAxis(times.at(i));\n      }\n\n      const SphericalHarmonics harmonics = gravityfield->sphericalHarmonics(times.at(i), 1, 1);\n      const Vector coeff = harmonics.x(); // [c00, c10, c11, s11]\n      const Vector3d cm2ceCorrection = std::sqrt(3.) * harmonics.R() * Vector3d(coeff(2), coeff(3), coeff(1));\n\n      for(auto &&satellite : satellites)\n      {\n        if(satellite.idEpoch >= satellite.times.size() || satellite.times.at(satellite.idEpoch) != times.at(i))\n          continue; // no data for this epoch\n\n        const Vector3d position = rot.rotate(satellite.orbit.at(satellite.idEpoch).position) + cm2ceCorrection;\n        const std::string clock = satellite.clock.size() ? (satellite.clock.at(satellite.idEpoch).value*1e6)%\"%14.6f\"s : \" 999999.999999\";\n        if(useSp3k || (position.r() < 10000e3))\n          file<<\"P\"<<satellite.identifier<<(position.x()/1000)%\"%14.7f\"s<<(position.y()/1000)%\"%14.7f\"s<<(position.z()/1000)%\"%14.7f\"s<<clock<<\"             \"<<std::endl;\n        else\n          file<<\"P\"<<satellite.identifier<<(position.x()/1000)%\"%14.6f\"s<<(position.y()/1000)%\"%14.6f\"s<<(position.z()/1000)%\"%14.6f\"s<<clock<<\"             \"<<std::endl;\n\n        if(writeVel)\n        {\n          const Vector3d velocity = rot.rotate(satellite.orbit.at(satellite.idEpoch).velocity-crossProduct(omega, satellite.orbit.at(satellite.idEpoch).position));\n          if(useSp3k)\n            file<<\"V\"<<satellite.identifier<<(velocity.x()*10)%\"%14.7f\"s<<(velocity.y()*10)%\"%14.7f\"s<<(velocity.z()*10)%\"%14.7f 999999.999999             \"s<<std::endl;\n          else\n            file<<\"V\"<<satellite.identifier<<(velocity.x()*10)%\"%14.6f\"s<<(velocity.y()*10)%\"%14.6f\"s<<(velocity.z()*10)%\"%14.6f 999999.999999             \"s<<std::endl;\n        }\n\n        if(satellite.cov.size())\n        {\n          Tensor3d cv = earthRotation ? rot.rotate(satellite.cov.at(satellite.idEpoch).covariance) : satellite.cov.at(satellite.idEpoch).covariance;\n          if(useSp3k)\n          {\n            file<<\"EPx \"\n                <<std::min(1000*std::sqrt(cv.xx()), 99.)%\"%4.1f \"s\n                <<std::min(1000*std::sqrt(cv.yy()), 99.)%\"%4.1f \"s\n                <<std::min(1000*std::sqrt(cv.zz()), 99.)%\"%4.1f \"s;\n          }\n          else\n          {\n            file<<\"EP  \"\n                <<std::min(std::round(1000*std::sqrt(cv.xx())), 9999.)%\"%4i \"s\n                <<std::min(std::round(1000*std::sqrt(cv.yy())), 9999.)%\"%4i \"s\n                <<std::min(std::round(1000*std::sqrt(cv.zz())), 9999.)%\"%4i \"s;\n          }\n          file<<\"        \" // clk-sdev\n              <<std::min(std::round(10000000*cv.xy()/(std::sqrt(cv.xx())*std::sqrt(cv.yy()))), 99999999.)%\"%8.0f \"s\n              <<std::min(std::round(10000000*cv.xz()/(std::sqrt(cv.xx())*std::sqrt(cv.zz()))), 99999999.)%\"%8.0f \"s\n              <<\"         \" // xc\n              <<std::min(std::round(10000000*cv.yz()/(std::sqrt(cv.yy())*std::sqrt(cv.zz()))), 99999999.)%\"%8.0f \"s\n              <<\"         \" // yc\n              <<\"         \" // zc\n              <<std::endl;\n        }\n\n        satellite.idEpoch++;\n      }\n    });\n\n    file<<\"EOF\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/potentialCoefficients2Icgem.cpp",
    "content": "/***********************************************/\n/**\n* @file potentialCoefficients2Icgem.cpp\n*\n* @brief Write spherical harmonics in ICGEM format.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2005-01-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite spherical harmonics in ICGEM format.\nGROOPS uses this format as default but this program enables\nthe possibility to include comments and set the modelname.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileSphericalHarmonics.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write spherical harmonics in ICGEM format.\n* @ingroup programsConversionGroup */\nclass PotentialCoefficients2Icgem\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  class Oscillation\n  {\n  public:\n    FileName    fileNameCos, fileNameSin;\n    std::string period;\n    SphericalHarmonics harmCos, harmSin;\n  };\n};\n\nGROOPS_REGISTER_PROGRAM(PotentialCoefficients2Icgem, SINGLEPROCESS, \"write spherical harmonics in ICGEM format\", Conversion, PotentialCoefficients)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, PotentialCoefficients2Icgem::Oscillation &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n    readConfig(config, \"inputfileCosPotentialCoefficients\", var.fileNameCos, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileSinPotentialCoefficients\", var.fileNameSin, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"period\",                            var.period,      Config::MUSTSET, \"1.0\", \"period of oscillation [year]\");\n    endSequence(config);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PotentialCoefficients2Icgem::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 fileNameOut;\n    FileName                 fileNameStatic, fileNameTrend;\n    FileName                 fileNameComments;\n    std::string              modelname;\n    std::vector<std::string> comment;\n    std::vector<Oscillation> oscillation;\n    std::string              choice;\n    std::string              tides;\n    UInt                     minDegree, maxDegree = INFINITYDEGREE;\n    Double                   GM, R;\n    Time                     time;\n\n    readConfig(config, \"outputfile\",                     fileNameOut,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfilePotentialCoefficients\", fileNameStatic,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileTrend\",                 fileNameTrend,    Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"oscillation\",                    oscillation,      Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"comment\",                        comment,          Config::OPTIONAL, \"\", \"comment in header\");\n    readConfig(config, \"inputfileComment\",               fileNameComments, Config::OPTIONAL, \"\", \"file containing comments for header\");\n    readConfig(config, \"modelname\",                      modelname,        Config::MUSTSET,  \"\", \"name of the model\");\n    if(readConfigChoice(config, \"tideSystem\", choice,  Config::OPTIONAL, \"\", \"tide system of model\"))\n    {\n      if(readConfigChoiceElement(config, \"zero_tide\", choice)) tides = \"zero_tide\";\n      if(readConfigChoiceElement(config, \"tide_free\", choice)) tides = \"tide_free\";\n      endChoice(config);\n    }\n    readConfig(config, \"minDegree\",       minDegree,      Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",       maxDegree,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",              GM,             Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",               R,              Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"time\",            time,           Config::OPTIONAL, \"\", \"reference time\");\n    if(isCreateSchema(config)) return;\n\n    // read potential coefficients\n    // ---------------------------\n    logStatus<<\"read potential coefficients from file <\"<<fileNameStatic<<\">\"<<Log::endl;\n    SphericalHarmonics harm;\n    readFileSphericalHarmonics(fileNameStatic, harm);\n    harm = harm.get(maxDegree, minDegree, GM, R);\n\n    SphericalHarmonics harmTrend;\n    if(!fileNameTrend.empty())\n    {\n      logStatus<<\"read potential coefficients from file <\"<<fileNameTrend<<\">\"<<Log::endl;\n      readFileSphericalHarmonics(fileNameTrend, harmTrend);\n    }\n    harmTrend = harmTrend.get(harm.maxDegree(), minDegree, GM, R);\n\n    for(UInt i=0; i<oscillation.size(); i++)\n    {\n      logStatus<<\"read potential coefficients from file <\"<<oscillation.at(i).fileNameCos<<\">\"<<Log::endl;\n      readFileSphericalHarmonics(oscillation.at(i).fileNameCos, oscillation.at(i).harmCos);\n      oscillation.at(i).harmCos = oscillation.at(i).harmCos.get(harm.maxDegree(), minDegree, GM, R);\n\n      logStatus<<\"read potential coefficients from file <\"<<oscillation.at(i).fileNameSin<<\">\"<<Log::endl;\n      readFileSphericalHarmonics(oscillation.at(i).fileNameSin, oscillation.at(i).harmSin);\n      oscillation.at(i).harmSin = oscillation.at(i).harmSin.get(harm.maxDegree(), minDegree, GM, R);\n    }\n\n    const Bool hasSigmas = (harm.sigma2cnm().size()) && ((quadsum(harm.sigma2cnm())+quadsum(harm.sigma2snm())) != 0);\n\n    // description of data section\n    // ---------------------------\n    std::stringstream ssHeader;\n    ssHeader<<\"key     L    M         C                   S          \";\n    if(hasSigmas)\n      ssHeader<<\"      sigma C             sigma S       \";\n    if((!fileNameTrend.empty()) || oscillation.size())\n      ssHeader<<\" t0 [yyyymmdd]\";\n    if(oscillation.size())\n      ssHeader<<\"/period [y]\";\n\n    // Potentialkoeffizienten speichern\n    // --------------------------------\n    logStatus<<\"writing potential coefficients to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile file(fileNameOut);\n    for(UInt i=0; i<comment.size(); i++)\n      file<<comment.at(i)<<std::endl;\n    if(!fileNameComments.empty())\n    {\n      InFile commentFile(fileNameComments);\n      std::string line;\n      while(std::getline(commentFile, line))\n        file<<line<<std::endl;\n    }\n    if(comment.size() || !fileNameComments.empty())\n      file<<std::endl;\n    file<<\"begin_of_head \"<<std::string(ssHeader.str().size()-14, '=')<<std::endl<<std::endl;\n    file<<\"modelname              \"<<modelname<<std::endl;\n    file<<\"product_type           gravity_field\"<<std::endl;\n    file<<\"earth_gravity_constant \"<<harm.GM()%\"%16.10e\"s<<std::endl;\n    file<<\"radius                 \"<<harm.R() %\"%16.10e\"s<<std::endl;\n    file<<\"max_degree             \"<<harm.maxDegree()<<std::endl;\n    file<<\"norm                   fully_normalized\"<<std::endl;\n    if(!tides.empty())\n      file<<\"tide_system            \"<<tides<<std::endl;\n    file<<\"errors                 \"<<((hasSigmas) ? \"formal\" : \"no\")<<std::endl;\n    file<<std::endl;\n    // end_of_head\n    file<<ssHeader.str()<<std::endl;\n    file<<\"end_of_head \"<<std::string(ssHeader.str().size()-12, '=')<<std::endl;\n\n    std::string fdouble = \"%20.12e\";\n    std::string fint    = \"%5i\";\n\n    // data section\n    // ------------\n    for(UInt n=0; n<=harm.maxDegree(); n++)\n      for(UInt m=0; m<=n; m++)\n      {\n        Bool hasTemporal = ((harmTrend.cnm()(n,m)!= 0.) || (harmTrend.snm()(n,m)!= 0.));\n        for(UInt i=0; i<oscillation.size(); i++)\n        {\n          hasTemporal = hasTemporal || (oscillation.at(i).harmCos.cnm()(n,m)!= 0.) || (oscillation.at(i).harmCos.snm()(n,m)!= 0.);\n          hasTemporal = hasTemporal || (oscillation.at(i).harmSin.cnm()(n,m)!= 0.) || (oscillation.at(i).harmSin.snm()(n,m)!= 0.);\n        }\n\n        // static coefficients\n        file<<((hasTemporal) ? \"gfct\" : \"gfc \");\n        file<<n%fint<<m%fint;\n        file<<harm.cnm()(n,m)%fdouble<<harm.snm()(n,m)%fdouble;\n        if(hasSigmas)\n          file<<sqrt(harm.sigma2cnm()(n,m))%fdouble<<sqrt(harm.sigma2snm()(n,m))%fdouble;\n        if(hasTemporal)\n          file<<\" \"<<time%\"%y%m%d\"s;\n        file<<std::endl;\n\n        // trend\n        if((harmTrend.cnm()(n,m)!= 0.) || (harmTrend.snm()(n,m)!= 0.))\n        {\n          file<<\"trnd\"<<n%fint<<m%fint;\n          file<<harmTrend.cnm()(n,m)%fdouble<<harmTrend.snm()(n,m)%fdouble;\n          if(hasSigmas)\n            file<<sqrt(harmTrend.sigma2cnm()(n,m))%fdouble<<sqrt(harmTrend.sigma2snm()(n,m))%fdouble;\n          file<<std::endl;\n        }\n\n        // oscillations\n        for(UInt i=0; i<oscillation.size(); i++)\n          if((oscillation.at(i).harmCos.cnm()(n,m)!= 0.) ||\n             (oscillation.at(i).harmCos.snm()(n,m)!= 0.) ||\n             (oscillation.at(i).harmSin.cnm()(n,m)!= 0.) ||\n             (oscillation.at(i).harmSin.snm()(n,m)!= 0.))\n          {\n            file<<\"acos\"<<n%fint<<m%fint;\n            file<<oscillation.at(i).harmCos.cnm()(n,m)%fdouble<<oscillation.at(i).harmCos.snm()(n,m)%fdouble;\n            if(hasSigmas)\n              file<<sqrt(oscillation.at(i).harmCos.sigma2cnm()(n,m))%fdouble<<sqrt(oscillation.at(i).harmCos.sigma2snm()(n,m))%fdouble;\n            file<<\" \"<<oscillation.at(i).period<<std::endl;\n\n            file<<\"asin\"<<n%fint<<m%fint;\n            file<<oscillation.at(i).harmSin.cnm()(n,m)%fdouble<<oscillation.at(i).harmSin.snm()(n,m)%fdouble;\n            if(hasSigmas)\n              file<<sqrt(oscillation.at(i).harmSin.sigma2cnm()(n,m))%fdouble<<sqrt(oscillation.at(i).harmSin.sigma2snm()(n,m))%fdouble;\n            file<<\" \"<<oscillation.at(i).period<<std::endl;\n          }\n      } // for(n,m)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/psmslOceanBottomPressure2TimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file psmslOceanBottomPressure2TimeSeries.cpp\n*\n* @brief Read ocean bottom pressure (OBP) time series in the PSMSL file format.\n*\n* @author Andreas Kvas\n* @date 2019-12-10\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis programs reads ocean bottom pressure time series from the Permanent Service for Mean Sea Level (PSMSL).\n\nIn addition to the OBP measurements, the recorder position can be written to a \\file{grid file}{griddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read ocean bottom pressure (OBP) time series in the PSMSL file format\n* @ingroup programsConversionGroup */\nclass PsmslOceanBottomPressure2TimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PsmslOceanBottomPressure2TimeSeries, SINGLEPROCESS, \"read ocean bottom pressure (OBP) time series in the PSMSL file format\", Conversion)\nGROOPS_RENAMED_PROGRAM(ReadOceanBottomPressurePSMSL, PsmslOceanBottomPressure2TimeSeries, date2time(2020, 9, 10))\n\n/***********************************************/\n\nvoid PsmslOceanBottomPressure2TimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      outName, posName, timeName;\n    FileName      inName;\n    Double        a, f;\n    TimeSeriesPtr timeSeries;\n    Bool          isDaily, ignoreBadData;\n\n    readConfig(config, \"outputfileTimeSeries\", outName,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"outputfilePosition\",   posName,       Config::OPTIONAL, \"\",  \"recorder position as gridded data\");\n    readConfig(config, \"inputfile\",            inName,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"isDaily\",              isDaily,       Config::MUSTSET,  \"0\", \"\");\n    readConfig(config, \"ignoreBadData\",        ignoreBadData, Config::MUSTSET,  \"1\", \"\");\n    readConfig(config, \"R\",                    a,             Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"\");\n    readConfig(config, \"inverseFlattening\",    f,             Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,    Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time> times = timeSeries->times();\n\n    logStatus<<\"read inputfile <\"<<inName<<\">\"<<Log::endl;\n    InFile file(inName);\n\n    // Header einlesen\n    Double L=0, B=0;\n    std::string line;\n    while(std::getline(file, line))\n    {\n      std::stringstream ss(line);\n      std::string tag;\n      std::string tmp;\n      ss>>tag;\n      if(tag == \"Latitude\")\n        ss>>tmp>>tmp>>B;\n      if(tag == \"Longitude\")\n        ss>>tmp>>tmp>>L;\n      if(tag == \"Recno\")\n        break;\n    }\n\n    std::vector<Time>   times2;\n    std::vector<Double> values2;\n    while(std::getline(file, line))\n    {\n      std::stringstream ss(line);\n      std::string tag;\n      std::string tmp;\n      UInt year, day, flag;\n      Double hour;\n      ss>>tmp;\n      ss>>flag;\n      if(ignoreBadData && flag==1) continue;\n      ss>>year>>day;\n\n      Time time = date2time(year, 1, 0);\n      time += seconds2time(static_cast<Double>(day)*86400.0);\n      if(!isDaily)\n      {\n        ss>>hour;\n        time += seconds2time(hour*60.0*60.0);\n      }\n      Double total, tide, drift, resid;\n      if(!isDaily) ss>>total>>tide;\n      ss>>drift>>resid;\n      if(!ss.good())\n        continue;\n\n      times2.push_back(time);\n      values2.push_back(resid);\n    }\n\n    Double mean = 0.0;\n    for(UInt i=0; i<values2.size(); i++)\n      mean += values2.at(i);\n    mean /= values2.size();\n    for(UInt i=0; i<values2.size(); i++)\n      values2.at(i) -= mean;\n\n    UInt idx = 0;\n    std::vector<UInt>   count(times.size()-1, 0);\n    std::vector<Double> value(times.size()-1, 0.0);\n    for(UInt i=0; i<times2.size(); i++)\n    {\n      if(times2.at(i) < times.at(idx))\n        continue;\n      while((idx<times.size()-1) && (times2.at(i)>=times.at(idx+1))) idx++;\n      if((idx>=times.size()-1)||(times2.at(i)>=times.at(times.size()-1)))\n        break;\n\n      count.at(idx)++;\n      value.at(idx) += values2.at(i);\n    }\n\n    logStatus<<\"remove mean\"<<Log::endl;\n    mean = 0.0;\n    UInt meanCount = 0;\n    for(UInt i=0; i<value.size(); i++)\n      if(count.at(i) != 0)\n      {\n        value.at(i) /= count.at(i);\n        mean += value.at(i);\n        meanCount++;\n      }\n    mean /= meanCount;\n    meanCount = 0;\n    for(UInt i=0; i<value.size(); i++)\n      if(count.at(i)!=0)\n      {\n        value.at(i) -= mean;\n        meanCount++;\n      }\n      else\n        count.at(i)=0;\n\n    logInfo<<\"  mean  = \"<<mean<<Log::endl;\n    logInfo<<\"  count = \"<<meanCount<<Log::endl;\n    logInfo<<\"  L     = \"<<L<<Log::endl;\n    logInfo<<\"  B     = \"<<B<<Log::endl;\n\n    if(meanCount == 0)\n      return;\n\n    if(!outName.empty())\n    {\n      logStatus<<\"write time series to file <\"<<outName<<\">\"<<Log::endl;\n      Matrix A(meanCount,2);\n      UInt idx = 0;\n      for(UInt i=0; i<value.size(); i++)\n        if(count.at(i) != 0)\n        {\n          A(idx,0) = times.at(i).mjd();//(0.5*times.at(i)+0.5*times.at(i+1)).mjd();\n          A(idx,1) = value.at(i);\n          idx++;\n        }\n      InstrumentFile::write(outName, Arc(A));\n    }\n\n    if(!posName.empty())\n    {\n      logStatus<<\"write position to file <\"<<posName<<\">\"<<Log::endl;\n      Ellipsoid ellipsoid(a,f);\n      writeFileGriddedData(posName, GriddedData(ellipsoid, {ellipsoid(Angle(L*DEG2RAD), Angle(B*DEG2RAD), 0.0)}, {1.}, {}));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/champ2AccStar.cpp",
    "content": "/***********************************************/\n/**\n* @file champ2AccStar.cpp\n*\n* @brief read CHAMP accelerometer and star camera data.\n*\n* @author Torsten Mayer-Guerr\n* @author Norbert Zehentner\n* @date 2010-07-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in CHAMP accelerometer and star camera data given in the special CHAMP format.\nIn case of CHAMP accelerometer and star camera data is both stored in one file.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read CHAMP accelerometer and star camera data.\n* @ingroup programsConversionGroup */\nclass Champ2AccStar\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Champ2AccStar, SINGLEPROCESS, \"read CHAMP accelerometer and star camera data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid Champ2AccStar::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              outNameAcc, outNameAca, outNameStar;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileAccelerometer\",       outNameAcc,  Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileAngularAcceleration\", outNameAca,  Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileStarCamera\",          outNameStar, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfile\",                     fileNameIn,  Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    AccelerometerArc arcAcc;\n    AccelerometerArc arcAca;\n    StarCameraArc    arcSca;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n        InFile file(fileNameIn.at(idFile));\n\n        AccelerometerEpoch epochAcc;\n        AccelerometerEpoch epochAca;\n        StarCameraEpoch    epochSca;\n        Vector3d           acl_k0, acl_k1, acc1, acc2;\n        Bool biasFlag  = FALSE;\n        Bool scaleFlag = FALSE;\n        Bool aclFlag   = FALSE;\n        Bool acaFlag   = FALSE;\n        Bool attFlag   = FALSE;\n        Bool acc1Flag  = FALSE;\n        Bool acc2Flag  = FALSE;\n\n        std::string line;\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            continue;\n          std::stringstream ss(line);\n          ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n          // Header Information (corrections for the accelerometer)\n          if(line.find(\"+acl_k0\") == 0)\n          {\n            acl_k0.x() = String::toDouble(line.substr(12, 14));\n            acl_k0.y() = String::toDouble(line.substr(28, 14));\n            acl_k0.z() = String::toDouble(line.substr(44, 14));\n            biasFlag = TRUE;\n          }\n          else if(line.find(\"+acl_k1\") == 0)\n          {\n            acl_k1.x() = String::toDouble(line.substr(12, 14));\n            acl_k1.y() = String::toDouble(line.substr(28, 14));\n            acl_k1.z() = String::toDouble(line.substr(44, 14));\n            scaleFlag = TRUE;\n          }\n\n          // new epoch? => store old epoch\n          if((line.find(\"tim\") == 0) || (line.find(\"%eof\") == 0))\n          {\n            if(aclFlag)\n            {\n              if(acc1Flag) epochAcc.acceleration += acc1;   // Lorentz correction\n              if(acc2Flag) epochAcc.acceleration += acc2;   // correction for the radial component\n              if(biasFlag) epochAcc.acceleration -= acl_k0; // bias correction\n              if(scaleFlag)                                 // scale factor\n              {\n                epochAcc.acceleration.x() *= acl_k1.x();\n                epochAcc.acceleration.y() *= acl_k1.y();\n                epochAcc.acceleration.z() *= acl_k1.z();\n              }\n              // Umrechnung von mm/s^2  zu m/s^2 und Übergang von Akzelerometer System auf Satelliten Body system\n              Vector3d tmp(epochAcc.acceleration.x()*0.001, epochAcc.acceleration.y()*0.001, epochAcc.acceleration.z()*0.001);\n              epochAcc.acceleration.x() =  tmp.y();\n              epochAcc.acceleration.y() = -tmp.z();\n              epochAcc.acceleration.z() = -tmp.x();\n              arcAcc.push_back(epochAcc);\n            }\n\n            if(attFlag)\n            {\n              arcSca.push_back(epochSca);\n            }\n            if(acaFlag)\n            {\n              Vector3d tmp(epochAca.acceleration.x(), epochAca.acceleration.y(), epochAca.acceleration.z());\n              epochAca.acceleration.x() =  tmp.y();\n              epochAca.acceleration.y() = -tmp.z();\n              epochAca.acceleration.z() = -tmp.x();\n              arcAca.push_back(epochAca);\n            }\n          }\n\n          if(line.find(\"tim\") == 0) // epoch time of the new epoch\n          {\n            const UInt   year   = String::toInt(line.substr(4, 4));\n            const UInt   month  = String::toInt(line.substr(9, 2));\n            const UInt   day    = String::toInt(line.substr(12, 2));\n            const UInt   hour   = String::toInt(line.substr(15, 2));\n            const UInt   minute = String::toInt(line.substr(18, 2));\n            const Double second = String::toDouble(line.substr(21, 10));\n            epochAcc.time = epochAca.time = epochSca.time = date2time(year, month, day, hour, minute, second);\n            // start new epoch without data yet\n            acc1Flag = acc2Flag = aclFlag = acaFlag = attFlag = FALSE;\n          }\n          else if(line.find(\"acl\") == 0)   // accelerometer\n          {\n            epochAcc.acceleration.x() = String::toDouble(line.substr(8, 14));    // mm/s^2\n            epochAcc.acceleration.y() = String::toDouble(line.substr(22, 14));   // mm/s^2\n            epochAcc.acceleration.z() = String::toDouble(line.substr(36, 14));   // mm/s^2\n            aclFlag = TRUE;\n          }\n          else if((line.find(\"aca\") == 0) && (line.find(\"*******\") == std::string::npos)) // angular accelerations\n          {\n            epochAca.acceleration.x() = String::toDouble(line.substr(8, 14))/1000;  // mrad/s^2 => rad/s^2\n            epochAca.acceleration.y() = String::toDouble(line.substr(22, 14))/1000;  // mrad/s^2 => rad/s^2\n            epochAca.acceleration.z() = String::toDouble(line.substr(36, 14))/1000;  // mrad/s^2 => rad/s^2\n            acaFlag = TRUE;\n          }\n          else if(line.find(\"att\") == 0)   // attitude\n          {\n            Vector q(4);\n            q(1) = String::toDouble(line.substr(8, 14));\n            q(2) = String::toDouble(line.substr(22, 14));\n            q(3) = String::toDouble(line.substr(36, 14));\n            q(0) = String::toDouble(line.substr(50, 14));\n            attFlag = TRUE;\n            if(fabs(norm(q)-1)>1e-5)\n            {\n              logWarning<<\"quaternion strange norm = \"<<norm(q)<<Log::endl;\n              continue;\n            }\n            epochSca.rotary = Rotary3d(q);\n          }\n          else if(line.find(\"thr\") == 0) {}  // Thruster events\n          else if(line.find(\"hka\") == 0) {}  // housekeeping data\n          else if(line.find(\"acc\") == 0)     // accelerometer corrections\n          {\n            UInt tmp1 = String::toInt(line.substr(4, 2));\n            UInt tmp2 = String::toInt(line.substr(7, 1));\n            if(tmp1 == 1 && tmp2 == 0)\n            {\n              acc1.x() = String::toDouble(line.substr(8, 14));\n              acc1.y() = String::toDouble(line.substr(22, 14));\n              acc1.z() = String::toDouble(line.substr(36, 14));\n              acc1Flag = TRUE;\n            }\n            if(tmp1 == 2 && tmp2 == 0)\n            {\n              acc2.x() = String::toDouble(line.substr(8, 14));\n              acc2.y() = String::toDouble(line.substr(22, 14));\n              acc2.z() = String::toDouble(line.substr(36, 14));\n              acc2Flag = TRUE;\n            }\n          }\n        } // while(getline)\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    } // for(idFile)\n\n    if(!outNameAcc.empty())\n    {\n      logStatus<<\"write accelerometer data to file <\"<<outNameAcc<<\">\"<<Log::endl;\n      arcAcc.sort();\n      Arc::printStatistics(arcAcc);\n      InstrumentFile::write(outNameAcc, arcAcc);\n    }\n\n    if(!outNameStar.empty())\n    {\n      logStatus<<\"write star camera data to file <\"<<outNameStar<<\">\"<<Log::endl;\n      arcSca.sort();\n      Arc::printStatistics(arcSca);\n      InstrumentFile::write(outNameStar, arcSca);\n    }\n\n    if(!outNameAca.empty())\n    {\n      logStatus<<\"write angular accelerations to file <\"<<outNameAca<<\">\"<<Log::endl;\n      arcAca.sort();\n      Arc::printStatistics(arcAca);\n      InstrumentFile::write(outNameAca, arcAca);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/champ2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file champ2Orbit.cpp\n*\n* @brief read champ PSO orbits from the special CHORB format\n*\n* @author Norbert Zehentner\n* @date 2011-10-04\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in CHAMP precise science orbits in the special CHORB format.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read champ PSO orbits from the special CHORB format\n* @ingroup programsConversionGroup */\nclass Champ2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Champ2Orbit, SINGLEPROCESS, \"read champ PSO orbits from the special CHORB format\", Conversion, Orbit, Instrument)\n\n/***********************************************/\n\nvoid Champ2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOrbit;\n    std::vector<FileName> fileNamesInput;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOrbit,  Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"earthRotation\",   earthRotation,  Config::OPTIONAL, \"file\", \"\");\n    readConfig(config, \"inputfile\",       fileNamesInput, Config::MUSTSET,  \"\",     \"\");\n    if(isCreateSchema(config)) return;\n\n    OrbitArc arc;\n    for(auto &fileName : fileNamesInput)\n    {\n      logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n      InFile file(fileName);\n      std::string line;\n      while(std::getline(file, line))\n        if(String::startsWith(line, \"ORBIT\"))\n          break;\n\n      while(std::getline(file, line))\n      {\n        OrbitEpoch epoch;\n        UInt   day = String::toInt(line.substr(0, 6));\n        Double ms  = String::toDouble(line.substr(6, 11));\n        epoch.time         = timeTT2GPS(mjd2time(J2000+0.1*day) + seconds2time(1e-6*ms));\n        epoch.position.x() = 1e-3*String::toDouble(line.substr(17, 12));\n        epoch.position.y() = 1e-3*String::toDouble(line.substr(29, 12));\n        epoch.position.z() = 1e-3*String::toDouble(line.substr(41, 12));\n        epoch.velocity.x() = 1e-7*String::toDouble(line.substr(53, 12));\n        epoch.velocity.y() = 1e-7*String::toDouble(line.substr(65, 12));\n        epoch.velocity.z() = 1e-7*String::toDouble(line.substr(77, 12));\n        arc.push_back(epoch);\n      }\n    }\n\n    if(earthRotation)\n    {\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(arc.size(), [&](UInt i)\n      {\n        const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(arc.at(i).time));\n        arc.at(i).position = rotation.rotate(arc.at(i).position);\n        if(arc.at(i).velocity.r() > 0)\n          arc.at(i).velocity = rotation.rotate(arc.at(i).velocity) + crossProduct(earthRotation->rotaryAxis(arc.at(i).time), arc.at(i).position);\n      });\n    }\n\n    if(!fileNameOrbit.empty())\n    {\n      logStatus<<\"write orbit data to file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOrbit, arc);\n      Arc::printStatistics(arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/cosmic2OrbitStar.cpp",
    "content": "/***********************************************/\n/**\n* @file cosmic2OrbitStar.cpp\n*\n* @brief read cosmic orbit star camera data.\n*\n* @author Norbert Zehentner\n* @date 2014-07-28\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in cosmic orbit and star camera data given in the CHAMP format.\nIn case of cosmic orbit and star camera data is stored in one file.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-001.pdf}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read cosmic orbit and star camera data.\n* @ingroup programsConversionGroup */\nclass Cosmic2OrbitStar\n{\n  void readFileCosmic(const FileName &fileName, StarCameraArc &starArc, OrbitArc &orbArc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Cosmic2OrbitStar, SINGLEPROCESS, \"read COSMIC orbit and star camera data\", Conversion, Orbit, Instrument)\n\n/***********************************************/\n\nvoid Cosmic2OrbitStar::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outNameOrb;\n    FileName outNameStar;\n    std::vector<FileName> fileName;\n\n    readConfig(config, \"outputfileOrbit\",         outNameOrb,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileStarCamera\",    outNameStar, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",               fileName,    Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc orbArc;\n    StarCameraArc starArc;\n    for(UInt i=0; i<fileName.size(); i++)\n    {\n      logStatus<<\"read file <\"<<fileName.at(i)<<\">\"<<Log::endl;\n      readFileCosmic(fileName.at(i), starArc, orbArc);\n    }\n\n    // Daten speichern\n    // ---------------\n    logStatus<<\"write orbit to file <\"<<outNameOrb<<\">\"<<Log::endl;\n    std::list<Arc> arcList3; arcList3.push_back(orbArc);\n    InstrumentFile::write(outNameOrb, arcList3);\n    logStatus<<\"write star camera data to file <\"<<outNameStar<<\">\"<<Log::endl;\n    std::list<Arc> arcList2; arcList2.push_back(starArc);\n    InstrumentFile::write(outNameStar, arcList2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Cosmic2OrbitStar::readFileCosmic(const FileName &fileName, StarCameraArc &starArc, OrbitArc &orbArc)\n{\n  try\n  {\n    OrbitEpoch orbEpoch;\n    StarCameraEpoch starEpoch;\n    Bool     attFlag   = FALSE;\n    Bool     orbFlag   = FALSE;\n\n    std::ifstream file(fileName.c_str());\n    if(!file.good())\n    {\n      logWarning<<\"cannot open file: \"<<fileName.str()<<\", continue...\"<<Log::endl;\n      return;\n    }\n    file.exceptions(std::ios::badbit|std::ios::failbit);\n\n    //Daten einlesen, Headerzeilen werden hier direkt behandelt\n    for(;;)\n    {\n      std::string line;\n      try\n      {\n        getline(file, line);\n      }\n      catch(std::exception &/*e*/)\n      {\n        //logWarning<<std::endl<<e.what()<<\" continue...\"<<Log::endl;\n        break;\n      }\n\n      if(line.empty())\n        break;\n\n      std::string lineID1 = line.substr(0,3);\n\n      if(lineID1 == \"tim\")\n      {\n        // vorherige Epoche Korrekturen anbringen falls vorhanden und anschließen zurückgeben\n\n        if(attFlag)\n        {\n          if(starArc.size() && (starEpoch.time <= starArc.at(starArc.size()-1).time))\n          {\n            logWarning<<\"(starEpoch.time <= starArc.at(starArc.size()-1).time)\"<<Log::endl;\n            continue;\n          }\n          starArc.push_back(starEpoch);\n        }\n        if(orbFlag)\n        {\n          if(orbArc.size() && (orbEpoch.time <= orbArc.at(orbArc.size()-1).time))\n          {\n            logWarning<<\"(orbEpoch.time <= orbArc.at(orbArc.size()-1).time)\"<<Log::endl;\n            continue;\n          }\n          orbArc.push_back(orbEpoch);\n        }\n       // Flags für Korrekturen setzen, da diese nicht in allen epochen vorhanden sind\n        orbFlag   = FALSE;\n        attFlag   = FALSE;\n\n        // epoch time der neuen Epoche einlesen\n        UInt year, month, day, hour, minute;\n        Double second;\n        year = String::toInt(line.substr(4, 4));\n        month = String::toInt(line.substr(9, 2));\n        day = String::toInt(line.substr(12, 2));\n        hour = String::toInt(line.substr(15, 2));\n        minute = String::toInt(line.substr(18, 2));\n        second = String::toDouble(line.substr(21, 10));\n        orbEpoch.time = date2time(year, month, day, hour, minute, second);\n        starEpoch.time = date2time(year, month, day, hour, minute, second);\n      }\n      else if(lineID1 == \"pvi\")  // orbit position and velocity\n      {\n        if(line.find(\"nan\")==std::string::npos)\n        {\n          orbEpoch.position.x() = String::toDouble(line.substr(3, 14)) *1000;   // km => m\n          orbEpoch.position.y() = String::toDouble(line.substr(17, 14)) *1000;   // km => m\n          orbEpoch.position.z() = String::toDouble(line.substr(31, 14)) *1000;   // km => m\n          orbEpoch.velocity.x() = String::toDouble(line.substr(45, 14)) *1000;   // km => m\n          orbEpoch.velocity.y() = String::toDouble(line.substr(59, 14)) *1000;   // km => m\n          orbEpoch.velocity.z() = String::toDouble(line.substr(73, 14)) *1000;   // km => m\n          if(orbEpoch.position.r()<DEFAULT_R)\n          {\n  //           logWarning<<\"strange position = \"<<orbEpoch.position.r()<<Log::endl;\n            continue;\n          }\n          orbFlag = TRUE;\n        }\n      }\n      else if(lineID1 == \"att\")  // Attitude einlesen (als Quaternionen gegeben) Reihenfolge: Vektorkomponenten 1,2,3 unnd sklare Komponente\n      {\n        if(line.find(\"nan\")==std::string::npos)\n        {\n          Vector q(4);\n          q(1) = String::toDouble(line.substr(8, 14));\n          q(2) = String::toDouble(line.substr(22, 14));\n          q(3) = String::toDouble(line.substr(36, 14));\n          q(0) = String::toDouble(line.substr(50, 14));\n          if(fabs(norm(q)-1)>1e-5)\n          {\n  //           logWarning<<\"strange norm = \"<<norm(q)<<Log::endl;\n            continue;\n          }\n          attFlag = TRUE;\n          starEpoch.rotary = Rotary3d(q);\n        }\n      }\n    }  //for(UInt i=0; ; i++) Schleife über die zeilen des Files\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/conversion/satellites/jason2Starcamera.cpp",
    "content": "/***********************************************/\n/**\n* @file jason2Starcamera.cpp\n*\n* @brief read Jason star camera data.\n*\n* @author Norbert Zehentner\n* @date 2014-10-16\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in Jason star camera data given in a special  format.\nFiles available at: \\url{cddis.gsfc.nasa.gov/pub/doris/ancillary/quaternions/ja2/}.\nA description of the format can be found under:\n\\url{ftp://ftp.ids-doris.org/pub/ids/ancillary/quaternions/jason1_2_quaternion_solar_panel.pdf}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read Jason star camera data.\n* @ingroup programsConversionGroup */\nclass Jason2Starcamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Jason2Starcamera, SINGLEPROCESS, \"read Jason star camera data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid Jason2Starcamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              outNameStar;\n    std::vector<FileName> fileNamesIn;\n    UInt                  jasonNumber;\n\n    readConfig(config, \"outputfileStarCamera\", outNameStar, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"jasonNumber\",          jasonNumber, Config::MUSTSET, \"2\", \"Jason number (different file format), 1 for Sentinel\");\n    readConfig(config, \"inputfile\",            fileNamesIn, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arc;\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n\n        std::string line;\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            continue;\n\n          std::string lineID1 = line.substr(0,1);\n          if(lineID1 == \"#\" || lineID1 == \"Q\" || (line.length()<25))\n            continue;\n\n          const UInt   year   = String::toInt(line.substr(0, 4));\n          const UInt   month  = String::toInt(line.substr(5, 2));\n          const UInt   day    = String::toInt(line.substr(8, 2));\n          const UInt   hour   = String::toInt(line.substr(11, 2));\n          const UInt   minute = String::toInt(line.substr(14, 2));\n          const Double second = String::toDouble(line.substr(17, 6));\n          if((year < 1990) || (year > 2030))\n            continue;\n\n          std::stringstream ss(line.substr(23));\n          ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n          Vector q(4);\n          Double tmp;\n          if(jasonNumber == 1)\n            ss>>q(0)>>q(1)>>q(2)>>q(3);\n          else\n            ss>>tmp>>q(0)>>tmp>>tmp>>q(1)>>tmp>>tmp>>q(2)>>tmp>>tmp>>q(3)>>tmp;\n\n          if(fabs(norm(q)-1) > 1e-5)\n          {\n            logWarning<<timeUTC2GPS(date2time(year, month, day, hour, minute, second)).dateTimeStr()<<\" strange quaternion norm = \"<<norm(q)<<Log::endl;\n            continue;\n          }\n\n          StarCameraEpoch epoch;\n          epoch.time   = timeUTC2GPS(date2time(year, month, day, hour, minute, second));\n          epoch.rotary = Rotary3d(q);\n          arc.push_back(epoch);\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    }\n\n    logStatus<<\"write star camera data to file <\"<<outNameStar<<\">\"<<Log::endl;\n    InstrumentFile::write(outNameStar, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/conversion/satellites/sacc2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file sacc2Orbit.cpp\n*\n* @brief read SACC orbit data.\n*\n* @author Norbert Zehentner\n* @date 2014-08-22\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in SACC orbit data.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read SACC orbit data.\n* @ingroup programsConversionGroup */\nclass Sacc2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sacc2Orbit, SINGLEPROCESS, \"read SACC orbit data\", Conversion, Orbit, Instrument)\n\n/***********************************************/\n\nvoid Sacc2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOrbit;\n    std::vector<FileName> fileNamesIn;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOrbit, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",       fileNamesIn,   Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc arc;\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n\n        std::string line;\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            continue;\n          std::stringstream ss(line);\n          ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n          UInt       id, year, month, day, hour, minute;\n          Double     second;\n          OrbitEpoch epoch;\n\n          ss>>id>>year>>month>>day>>hour>>minute>>second;\n          ss>>epoch.position.x()>>epoch.position.y()>>epoch.position.z();\n          ss>>epoch.velocity.x()>>epoch.velocity.y()>>epoch.velocity.z();\n\n          epoch.time = timeUTC2GPS(date2time(year, month, day, hour, minute, second));\n          epoch.position *= 1000; // km => m\n          epoch.velocity *= 1000; // km/s => m/s\n          arc.push_back(epoch);\n        } // while(getline)\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    } // for(idFile)\n\n    if(!fileNameOrbit.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOrbit<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOrbit, arc);\n      Arc::printStatistics(arc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/conversion/satellites/sentinel2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file sentinel2orbit.cpp\n*\n* @brief Read Sentinel orbits from XML format.\n*\n* @author Barbara Suesser-Rechberger\n* @date 2019-11-25\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead Sentinel orbits from XML format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/xml.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n\n/***** CLASS ***********************************/\n\n/** @brief Read XML Sentinel Data.\n* @ingroup programsConversionGroup */\nclass SentinelXml2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SentinelXml2Orbit, SINGLEPROCESS, \"read XML Sentinel Data\", Conversion, Orbit, Instrument)\n\n/***********************************************/\n\nvoid SentinelXml2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOrbit;\n    std::vector<FileName> fileNamesIn;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOrbit, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",       fileNamesIn,   Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    OrbitArc orbit;\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n        XmlNodePtr rootNode    = XmlNode::read(file);\n        XmlNodePtr dataNode    = getChild(rootNode, \"Data_Block\",   TRUE);\n        XmlNodePtr osvListNode = getChild(dataNode, \"List_of_OSVs\", TRUE);\n\n        const UInt epochCount = childCount(osvListNode, \"OSV\", TRUE);\n        for(UInt i=0; i<epochCount; i++)\n        {\n          XmlNodePtr epochNode = getChild(osvListNode, \"OSV\", TRUE);\n\n          // Read UTC string and convert it into modified julian date and then into GPS time\n          std::string timeUTC;\n          Char   tmp;\n          UInt   year, month, day, hour, minute;\n          Double second;\n          readXml(epochNode, \"UTC\", timeUTC, TRUE);\n          std::stringstream ss(timeUTC.substr(4));\n          ss>>year>>tmp>>month>>tmp>>day>>tmp>>hour>>tmp>>minute>>tmp>>second;\n\n          OrbitEpoch epoch;\n          epoch.time = timeUTC2GPS(date2time(year, month, day, hour, minute, second));\n\n          // position coordinates\n          readXml(epochNode, \"X\", epoch.position.x(), TRUE);\n          readXml(epochNode, \"Y\", epoch.position.y(), TRUE);\n          readXml(epochNode, \"Z\", epoch.position.z(), TRUE);\n\n          // Velocity coordinates\n          readXml(epochNode, \"VX\", epoch.velocity.x(), TRUE);\n          readXml(epochNode, \"VY\", epoch.velocity.y(), TRUE);\n          readXml(epochNode, \"VZ\", epoch.velocity.z(), TRUE);\n\n          orbit.push_back(epoch);\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    }\n\n    // Rotation TRF -> CRF\n    // -------------------\n    if(earthRotation)\n    {\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(orbit.size(), [&](UInt i)\n      {\n        const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(orbit.at(i).time));\n        orbit.at(i).position    = rotation.rotate(orbit.at(i).position);\n        if(orbit.at(i).velocity.r() > 0)\n          orbit.at(i).velocity = rotation.rotate(orbit.at(i).velocity) + crossProduct(earthRotation->rotaryAxis(orbit.at(i).time), orbit.at(i).position);\n      });\n    }\n\n    if(!fileNameOrbit.empty())\n    {\n      logInfo<<\"write data to <\"<<fileNameOrbit<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOrbit, orbit);\n      Arc::printStatistics(orbit);\n    }\n  }\n  catch (std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/sentinel2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file sentinel2StarCamera.cpp\n*\n* @brief read Sentinel-1/2/3 star camera data.\n*\n* @author Barbara Suesser-Rechberger\n* @date 2020-10-21\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in Sentinel-1/2/3 star camera data given in the special format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"base/string.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read Sentinel-1/2/3 star camera data.\n* @ingroup programsConversionGroup */\nclass Sentinel2StarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sentinel2StarCamera, SINGLEPROCESS, \"read Sentinel-1/2/3 star camera data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid Sentinel2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              outNameStar;\n    std::vector<FileName> fileNamesIn;\n\n    readConfig(config, \"outputfileStarCamera\", outNameStar, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNamesIn,  Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arc;\n\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n\n        std::string line;\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            continue;\n\n          std::string lineID1 = line.substr(0,1);\n          if(lineID1 == \"#\")\n            continue;\n\n          // Time format in AUX_PROQUA file: YYYY/MM/DD HH:MM:SS.SSS  Q_COMPR QCOMP1 QCOMP2 QCOMP3\n          UInt   year   = String::toInt(line.substr(0, 4));\n          UInt   month  = String::toInt(line.substr(5, 2));\n          UInt   day    = String::toInt(line.substr(8, 2));\n          UInt   hour   = String::toInt(line.substr(11, 2));\n          UInt   minute = String::toInt(line.substr(14, 2));\n          Double second = String::toDouble(line.substr(17, 6));\n\n          std::stringstream ss(line.substr(23));\n          ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n          Vector q(4);\n          ss>>q(0)>>q(1)>>q(2)>>q(3);\n\n          StarCameraEpoch epoch;\n          epoch.time   = date2time(year, month, day, hour, minute, second);\n          epoch.rotary = Rotary3d(q);\n          arc.push_back(epoch);\n\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    }\n\n    logStatus<<\"write star camera data to file <\"<<outNameStar<<\">\"<<Log::endl;\n    Arc::printStatistics(arc);\n    InstrumentFile::write(outNameStar, arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/swarm2Starcamera.cpp",
    "content": "/***********************************************/\n/**\n* @file swarm2Starcamera.cpp\n*\n* @brief read SWARM attitude data.\n*\n* @author Norbert Zehentner\n* @date 2014-05-23\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads SWARM star camera data given in the cdf format\nand before converted to an ascii file using the program \\verb|cdfexport|\nprovided by the Goddard Space Flight Center (\\url{http://cdf.gsfc.nasa.gov/}).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read SWARM star camera data.\n* @ingroup programsConversionGroup */\nclass Swarm2Starcamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Swarm2Starcamera, SINGLEPROCESS, \"read SWARM star camera data\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid Swarm2Starcamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameSca;\n    std::vector<FileName> fileNamesIn;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileStarCamera\", fileNameSca,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",        earthRotation, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNamesIn,   Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arcSca;\n    for(const auto &fileName : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileName<<\">\"<<Log::endl;\n        InFile file(fileName);\n        file.exceptions(std::ios::badbit|std::ios::failbit);\n\n        // find begin of data\n        for(;;)\n        {\n          std::string line;\n          std::getline(file, line);\n          if(line.find(\"Timestamp\") != std::string::npos)\n            break;\n        }\n\n        // read data\n        for(;;)\n        {\n          std::string line;\n          try\n          {\n            std::getline(file, line);\n            if(line.empty())\n              continue;\n            }\n            catch(std::exception &/*e*/)\n            {\n              break;\n            }\n\n          const std::vector<std::string> monthStr = {\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\",\"Dec\"};\n          UInt   day     = String::toInt(line.substr(0, 2));\n          UInt   month   = std::distance(monthStr.begin(), std::find(monthStr.begin(), monthStr.end(), line.substr(3,3))) + 1;\n          UInt   year    = String::toInt(line.substr(7, 4));\n          UInt   hour    = String::toInt(line.substr(12, 2));\n          UInt   minute  = String::toInt(line.substr(15, 2));\n          Double seconds = String::toDouble(line.substr(18, 6));\n\n          Vector q(4);\n          q(1) = String::toDouble(line.substr(25, 12));\n          std::getline(file, line);\n          q(2) = String::toDouble(line.substr(25, 12));\n          std::getline(file, line);\n          q(3) = String::toDouble(line.substr(25, 12));\n          std::getline(file, line);\n          q(0) = String::toDouble(line.substr(25, 12));\n\n          if(std::fabs(norm(q)-1) > 1e-5)\n          {\n            logWarning<<\"strange norm = \"<<norm(q)<<Log::endl;\n            continue;\n          }\n\n          StarCameraEpoch epoch;\n          epoch.time   = timeUTC2GPS(date2time(year, month, day, hour, minute, seconds));\n          epoch.rotary = inverse(Rotary3d(q) * earthRotation->rotaryMatrix(epoch.time));\n          arcSca.push_back(epoch);\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    } // for(idFile)\n\n    // write data\n    // ----------\n    logStatus<<\"write star camera data to file <\"<<fileNameSca<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameSca, arcSca);\n    Arc::printStatistics(arcSca);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/terraSarTandem2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file terraSarTandem2Orbit.cpp\n*\n* @brief read TerraSar-X or Tandem-X orbits from the special CHORB format\n*\n* @author Norbert Zehentner\n* @date 2014-03-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in TerraSar-X or Tandem-X orbits in the special CHORB format and takes the appropriate\ntime frame as stated in the document header.\nA description of the format can be found under: \\url{http://op.gfz-potsdam.de/champ/docs_CHAMP/CH-GFZ-FD-002.pdf}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n\n/***** CLASS ***********************************/\n\n/** @brief read TerraSar-X or Tandem-X orbits from the special CHORB format\n* @ingroup programsConversionGroup */\nclass TerraSarTandem2Orbit\n{\n  EarthRotationPtr earthRotation;\n\n  void readOrbit(const FileName &fileName, std::vector<Time> &times, std::vector<Vector3d> &position, std::vector<Vector3d> &velocity, std::vector<Time> &timeSpan) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(TerraSarTandem2Orbit, SINGLEPROCESS, \"read TerraSar-X or Tandem-X orbits from the special CHORB format\", Conversion, Orbit, Instrument)\nGROOPS_RENAMED_PROGRAM(Tsxtdx2Orbit, Tsxtdx2Starcamera, date2time(2020, 8, 4))\n\n/***********************************************/\n\nvoid TerraSarTandem2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              orbitName;\n    std::vector<FileName> inOrbitName;\n\n    readConfig(config, \"outputfileOrbit\", orbitName,     Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfile\",       inOrbitName,   Config::MUSTSET, \"\", \"orbits in CHORB format\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    OrbitArc  orbitArc;\n\n    for(UInt k=0; k<inOrbitName.size(); k++)\n    {\n      std::vector<Time>     times;\n      std::vector<Vector3d> position;\n      std::vector<Vector3d> velocity;\n      std::vector<Time>     timeSpan;\n      UInt count=0;\n\n      logStatus<<\"read file <\"<<inOrbitName.at(k)<<\">\"<<Log::endl;\n      readOrbit(inOrbitName.at(k), times, position, velocity, timeSpan);\n      logInfo<<\"  pos:  \"<<times.size()<<Log::endl;\n\n      for(UInt i=0; i<times.size(); i++)\n      {\n        if(!timeSpan.empty())\n          if((times.at(i)<timeSpan.at(0)) || (times.at(i)>timeSpan.at(1)))\n            continue;\n        Double r = position.at(i).r();\n        if((r!=r)||(r<6380e3)||(r>100000e3))\n        {\n          logWarning<<\"strange position r=\"<<r<<Log::endl;\n          continue;\n        }\n\n        OrbitEpoch orbitEpoch;\n        orbitEpoch.time     = times.at(i);\n        orbitEpoch.position = position.at(i);\n        orbitEpoch.velocity = velocity.at(i);\n        orbitArc.push_back(orbitEpoch);\n        count++;\n      } // for(epoch i)\n      logInfo<<\"  used: \"<<count<<Log::endl;\n    }\n\n    // Daten speichern\n    // ---------------\n    orbitArc.sort();\n    orbitArc.removeDuplicateEpochs(TRUE);\n\n    if(!orbitName.empty())\n    {\n      logStatus<<\"write orbit data to file <\"<<orbitName<<\">\"<<Log::endl;\n      InstrumentFile::write(orbitName, orbitArc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid TerraSarTandem2Orbit::readOrbit(const FileName &fileName, std::vector<Time> &times, std::vector<Vector3d> &position, std::vector<Vector3d> &velocity, std::vector<Time> &timeSpan) const\n{\n  try\n  {\n    times.clear();\n    position.clear();\n    velocity.clear();\n    timeSpan.clear();\n    std::string rFrame;\n\n    // open file\n    // -------------\n    InFile file(fileName);\n    file.exceptions(std::ios::badbit|std::ios::failbit);\n\n    // read data\n    // ---------\n    Bool header = FALSE;\n    Bool isEOF = FALSE;\n    while(!isEOF)\n    {\n      if(!file.good())\n        break;\n      std::string line;\n      try\n      {\n        getline(file, line);\n      }\n      catch(std::exception &/*e*/)\n      {\n//        logWarning<<std::endl<<e.what()<<\" continue...\"<<Log::endl;\n        isEOF = TRUE;\n        break;\n      }\n      if(line.size()<5)\n      {\n        isEOF = TRUE;\n        break;\n      }\n\n      if(!header)\n      {\n        std::string lineID = line.substr(0,5);\n        if(lineID==\"RFRAM\")\n          rFrame = line.substr(7,3);\n        else if(lineID==\"COMEN\" && line.substr(7,8)==\"For best\")\n        {\n          getline(file, line);\n          timeSpan.push_back(seconds2time( String::toDouble(line.substr( 7, 2))*3600 + String::toDouble(line.substr(10, 2))*60 +  String::toDouble(line.substr(13, 2))));\n          timeSpan.push_back(seconds2time( String::toDouble(line.substr(18, 2))*3600 + String::toDouble(line.substr(21, 2))*60 +  String::toDouble(line.substr(24, 2))));\n        }\n        else if(lineID==\"ORBIT\")\n          header = TRUE;\n      }\n      else\n      {\n      // Epochenzeit\n      // -----------\n        UInt   day;\n        Double sec, x, y, z, vx, vy, vz;\n        day = String::toInt(line.substr(0, 6));\n        sec = String::toDouble(line.substr(6, 11));\n        x = String::toDouble(line.substr(17, 12));\n        y = String::toDouble(line.substr(29, 12));\n        z = String::toDouble(line.substr(41, 12));\n        vx = String::toDouble(line.substr(53, 12));\n        vy = String::toDouble(line.substr(65, 12));\n        vz = String::toDouble(line.substr(77, 12));\n       //Epochezeitpunkt ist in TT seit J2000 gegeben -> Umrechnung in GPS Zeit\n        Time time = mjd2time(J2000);\n        time += seconds2time((day)*pow(10,-1)*86400);\n        time += seconds2time(sec*pow(10,-6));\n        time = timeTT2GPS(time);\n//         if((!times.empty()) && (time<=times.back()))\n//         {\n//           logWarning<<\"new  time: \"<<time.dateTimeStr()<<Log::endl;\n//           logWarning<<\"last time: \"<<times.back().dateTimeStr()<<Log::endl;\n//           throw(Exception(\"times not in increasing order!\"));\n//         }\n        if(times.empty())\n        {\n          if(!timeSpan.empty())\n            timeSpan.at(0) += seconds2time(static_cast<Double>(time.mjdInt())*86400);\n          logInfo<<\"  First epoch: \"<<time.dateTimeStr()<<Log::endl;\n        }\n\n        times.push_back(time);\n        if(rFrame==\"CTS\")\n        {\n          Rotary3d rotation  = inverse(earthRotation->rotaryMatrix(time));\n          position.push_back(rotation.rotate(0.001*Vector3d(x,y,z))); // mm -> m\n          velocity.push_back(rotation.rotate(0.0000001*Vector3d(vx,vy,vz)));  // 10^-7 m/s -> 1 m/s\n        }\n        else\n        {\n        position.push_back(0.001*Vector3d(x,y,z)); // mm -> m\n        velocity.push_back(0.0000001*Vector3d(vx,vy,vz));  // 10^-7 m/s -> 1 m/s\n        }\n      }\n    } // while(!EOF)\n    if(!timeSpan.empty() && times.size()>15)\n    {\n      timeSpan.at(1) += seconds2time(static_cast<Double>(times.at(times.size()-10).mjdInt())*86400);\n      logInfo<<\"  Cut orbit to: \"<<timeSpan.at(0).dateTimeStr()<<\" < \"<<timeSpan.at(1).dateTimeStr()<<Log::endl;\n    }\n\n    if(!isEOF)\n      logWarning<<\"do not reached the end of file\"<<Log::endl;\n  }\n  catch(std::exception &/*e*/)\n  {\n    logWarning<<\"cannot open file: \"<<fileName<<\", continue...\"<<Log::endl;\n    return;\n//     GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/satellites/terraSarTandem2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file terraSarTandem2StarCamera.cpp\n*\n* @brief read TerraSar-X or Tandem-X star camera data.\n*\n* @author Norbert Zehentner\n* @date 2014-03-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads in TerraSar-X or Tandem-X star camera data given in the special format.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read TerraSar-X or Tandem-X star camera data.\n* @ingroup programsConversionGroup */\nclass TerraSarTandem2StarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(TerraSarTandem2StarCamera, SINGLEPROCESS, \"read TerraSar-X or Tandem-X star camera data\", Conversion, Instrument)\nGROOPS_RENAMED_PROGRAM(Tsxtdx2Starcamera, TerraSarTandem2StarCamera, date2time(2020, 8, 4))\n\n/***********************************************/\n\nvoid TerraSarTandem2StarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              outNameStar;\n    std::vector<FileName> fileNameIn;\n\n    readConfig(config, \"outputfileStarCamera\", outNameStar, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfile\",            fileNameIn,  Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read input files\"<<Log::endl;\n    StarCameraArc arc;\n    for(UInt idFile=0; idFile<fileNameIn.size(); idFile++)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<fileNameIn.at(idFile)<<\">\"<<Log::endl;\n        InFile file(fileNameIn.at(idFile));\n\n        std::string line;\n        while(std::getline(file, line))\n        {\n          if(line.empty())\n            continue;\n          std::stringstream ss(line);\n          ss.exceptions(std::ios::badbit | std::ios::failbit);\n\n          Vector q(4);\n          Double second;\n          ss>>second>>q(1)>>q(2)>>q(3)>>q(0);\n\n          if(std::fabs(norm(q)-1) > 1e-5)\n          {\n            logWarning<<\"strange norm = \"<<norm(q)<<Log::endl;\n            continue;\n          }\n\n          StarCameraEpoch epoch;\n          epoch.time   = mjd2time(44244.0) + seconds2time(second);\n          epoch.rotary = Rotary3d(q);\n          arc.push_back(epoch);\n        }\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n      }\n    }\n\n    logStatus<<\"write star camera data to file <\"<<outNameStar<<\">\"<<Log::endl;\n    Arc::printStatistics(arc);\n    InstrumentFile::write(outNameStar, arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/sinex2Normals.cpp",
    "content": "/***********************************************/\n/**\n* @file sinex2Normals.cpp\n*\n* @brief Convert SINEX to GROOPS normal equations.\n*\n* @author Sebastian Strasser\n* @date 2017-05-16\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert normal equations from \\href{http://www.iers.org/IERS/EN/Organization/AnalysisCoordinator/SinexFormat/sinex.html}{SINEX format}\nto \\file{normal equations}{normalEquation}.\n\nSee also \\program{GnssNormals2Sinex} and \\program{NormalsSphericalHarmonics2Sinex}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert SINEX to GROOPS normal equations.\n* @ingroup programsConversionGroup */\nclass Sinex2Normals\n{\n  Vector readVector(const Sinex &sinex, UInt &dimension, std::vector<ParameterName> &parameterNames, const std::string &label) const;\n  Matrix readMatrix(const Sinex &sinex, UInt dimension, const std::string &label) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sinex2Normals, SINGLEPROCESS, \"Convert SINEX to GROOPS normal equations.\", Conversion, NormalEquation)\n\n/***********************************************/\n\nvoid Sinex2Normals::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outNameNormals, outNameNormalsConstraint, outNameSolutionApriori, outNameSolution, inNameSinex;\n\n    readConfig(config, \"outputfileNormals\",           outNameNormals,           Config::OPTIONAL, \"\", \"N, n: unconstrained normal equations\");\n    readConfig(config, \"outputfileNormalsConstraint\", outNameNormalsConstraint, Config::OPTIONAL, \"\", \"N0, n0: normal equations of applied constraints\");\n    readConfig(config, \"outputfileSolution\",          outNameSolution,          Config::OPTIONAL, \"\", \"x: parameter vector\");\n    readConfig(config, \"outputfileSolutionApriori\",   outNameSolutionApriori,   Config::OPTIONAL, \"\", \"x0: a priori parameter vector\");\n    readConfig(config, \"inputFileSinex\",              inNameSinex,              Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logInfo<<\"read SINEX file\"<<Log::endl;\n    Sinex sinex;\n    readFileSinex(inNameSinex, sinex);\n\n    // dimension of system of equations\n    // --------------------------------\n    NormalEquationInfo info;\n    UInt dimension = 0;\n    if(sinex.header.size() > 65)\n      dimension = static_cast<UInt>(String::toInt(sinex.header.substr(60, 5)));\n\n    Vector n  = readVector(sinex, dimension, info.parameterName, \"SOLUTION/NORMAL_EQUATION_VECTOR\");\n    Vector x  = readVector(sinex, dimension, info.parameterName, \"SOLUTION/ESTIMATE\");\n    Vector x0 = readVector(sinex, dimension, info.parameterName, \"SOLUTION/APRIORI\");\n    Matrix N0 = readMatrix(sinex, dimension, \"SOLUTION/MATRIX_APRIORI\");\n    Matrix N  = readMatrix(sinex, dimension, \"SOLUTION/NORMAL_EQUATION_MATRIX\");\n\n    // try reconstruct missing information\n    if(!x.size())\n      x = Vector(dimension);\n    if(!x0.size())\n      x0 = Vector(dimension);\n    if(!N.size())\n    {\n      N = readMatrix(sinex, dimension, \"SOLUTION/MATRIX_ESTIMATE\");\n      if(N0.size())\n        N -= N0;\n    }\n    if(!n.size() && N.size())\n      n = N * (x-x0);\n\n    // SOLUTION/STATISTICS\n    auto iter = std::find_if(sinex.blocks.begin(), sinex.blocks.end(), [&](const auto &b) {return b->label == \"SOLUTION/STATISTICS\";});\n    if(iter != sinex.blocks.end())\n      for(auto &line : (*iter)->lines)\n      {\n        if(String::startsWith(line, \" NUMBER OF DEGREES OF FREEDOM\")) info.observationCount = String::toDouble(line.substr(32, 22)) + dimension;\n        if(String::startsWith(line, \" NUMBER OF OBSERVATIONS\"))       info.observationCount = String::toDouble(line.substr(32, 22));\n        if(String::startsWith(line, \" WEIGHTED SQUARE SUM OF O-C\"))   info.lPl(0)           = String::toDouble(line.substr(32, 22));\n      }\n\n    if(!info.observationCount)\n      info.observationCount = x.size();\n    if(!info.lPl(0))\n      info.lPl = (x-x0).trans()*(N*(x-x0));\n\n    // write output files\n    // ------------------\n    if(!outNameNormals.empty() && N.size())\n    {\n      logStatus<<\"write unconstrained normal equations to <\"<<outNameNormals<<\">\"<<Log::endl;\n      logInfo<<\"  unknown parameters: \"<<N.columns()<<Log::endl;\n      logInfo<<\"  observations:       \"<<info.observationCount<<Log::endl;\n      writeFileNormalEquation(outNameNormals, info, N, n);\n    }\n\n    if(!outNameNormalsConstraint.empty() && N0.size())\n    {\n      NormalEquationInfo infoConstraint(info.parameterName);\n        for(UInt i=0; i<N0.rows(); i++)\n          if(N0(i,i))\n            infoConstraint.observationCount++;\n      logStatus<<\"write normal equations of applied constraints to <\"<<outNameNormalsConstraint<<\">\"<<Log::endl;\n      logInfo<<\"  unknown parameters: \"<<N0.columns()<<Log::endl;\n      logInfo<<\"  observations:       \"<<infoConstraint.observationCount<<Log::endl;\n      writeFileNormalEquation(outNameNormalsConstraint, infoConstraint, N0, Vector(N0.rows()));\n    }\n\n    if(!outNameSolution.empty() && x.size())\n    {\n      logStatus<<\"write solution vector to <\"<<outNameSolution<<\">\"<<Log::endl;\n      writeFileMatrix(outNameSolution, x);\n    }\n\n    if(!outNameSolutionApriori.empty() && x0.size())\n    {\n      logStatus<<\"write a priori solution vector to <\"<<outNameSolutionApriori<<\">\"<<Log::endl;\n      writeFileMatrix(outNameSolutionApriori, x0);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Sinex2Normals::readVector(const Sinex &sinex, UInt &dimension, std::vector<ParameterName> &parameterNames, const std::string &label) const\n{\n  try\n  {\n    auto iter = std::find_if(sinex.blocks.begin(), sinex.blocks.end(), [&](const auto &b) {return b->label == label;});\n    if(iter == sinex.blocks.end())\n      return Vector();\n\n    if(dimension == 0)\n      for(auto &line : (*iter)->lines)\n        dimension = std::max(dimension, static_cast<UInt>(String::toInt(line.substr(1, 5))));\n\n    parameterNames.resize(dimension);\n    Vector x(dimension);\n    for(auto &line : (*iter)->lines)\n    {\n      // *INDEX _TYPE_ CODE PT SOLN _REF_EPOCH__ UNIT S ___ESTIMATED_VALUE___ __STD_DEV__\n      const UInt idx = static_cast<UInt>(String::toInt(line.substr(1, 5)))-1;\n      const std::string parameterType = String::trim(line.substr(7, 6));\n      x(idx) = String::toDouble(line.substr(47, 21));\n\n      // spherical harmonics coefficients\n      if(parameterType == \"CN\" || parameterType == \"SN\")\n      {\n        std::string type = \"sphericalHarmonics.\"\n                         + std::string(parameterType == \"CN\" ? \"c_\" : \"s_\")\n                         + String::trim(line.substr(14, 4)) + \"_\" // degree (siteCode)\n                         + String::trim(line.substr(22, 4));      // order (solutionId)\n        parameterNames.at(idx) = ParameterName(\"\", type);\n        continue;\n      }\n\n      std::string object = String::trim(line.substr(14, 4)); // siteCode\n      if(object == \"----\")\n        object = \"\";\n      if(parameterType.substr(0,3) != \"SAT\")\n        object = String::lowerCase(object);\n\n      std::string type = parameterType; // not all types implemented yet, see SINEX documentation;\n      if(     parameterType == \"STAX\")   type = \"position.x\";\n      else if(parameterType == \"STAY\")   type = \"position.y\";\n      else if(parameterType == \"STAZ\")   type = \"position.z\";\n      else if(parameterType == \"VELX\")   type = \"velocity.x\";\n      else if(parameterType == \"VELY\")   type = \"velocity.y\";\n      else if(parameterType == \"VELZ\")   type = \"velocity.z\";\n      else if(parameterType == \"XGC\")    type = \"geocenter.x\";\n      else if(parameterType == \"YGC\")    type = \"geocenter.y\";\n      else if(parameterType == \"ZGC\")    type = \"geocenter.z\";\n      else if(parameterType == \"LOD\")    type = \"LOD\";\n      else if(parameterType == \"UT\")     type = \"UT1\";\n      else if(parameterType == \"XPO\")    type = \"polarMotion.xp\";\n      else if(parameterType == \"YPO\")    type = \"polarMotion.yp\";\n      else if(parameterType == \"XPOR\")   type = \"polarMotionRate.xp\";\n      else if(parameterType == \"YPOR\")   type = \"polarMotionRate.yp\";\n      else if(parameterType == \"NUT_X\")  type = \"nutation.X\";\n      else if(parameterType == \"NUT_Y\")  type = \"nutation.Y\";\n      else if(parameterType == \"NUTR_X\") type = \"nutationRate.X\";\n      else if(parameterType == \"NUTR_Y\") type = \"nutationRate.Y\";\n      else if(parameterType == \"SAT__X\") type = \"position.x\";\n      else if(parameterType == \"SAT__Y\") type = \"position.y\";\n      else if(parameterType == \"SAT__Z\") type = \"position.z\";\n      else if(parameterType == \"SAT_VX\") type = \"velocity.x\";\n      else if(parameterType == \"SAT_VY\") type = \"velocity.y\";\n      else if(parameterType == \"SAT_VZ\") type = \"velocity.z\";\n      else if(parameterType == \"SATA_X\") type = \"antennaCenterVariations.xOffset\";\n      else if(parameterType == \"SATA_Y\") type = \"antennaCenterVariations.yOffset\";\n      else if(parameterType == \"SATA_Z\") type = \"antennaCenterVariations.zOffset\";\n\n      parameterNames.at(idx) = ParameterName(object, type);\n    }\n\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Sinex2Normals::readMatrix(const Sinex &sinex, UInt dimension, const std::string &label) const\n{\n  try\n  {\n    auto iter = std::find_if(sinex.blocks.begin(), sinex.blocks.end(), [&](const auto &b) {return String::startsWith(b->label, label);});\n    if(iter == sinex.blocks.end())\n      return Matrix();\n\n    Matrix N(dimension, dimension);\n    Bool isLower = FALSE;\n    for(auto &line : (*iter)->lines)\n    {\n      const UInt i = static_cast<UInt>(String::toInt(line.substr(1, 5))) - 1;\n      const UInt k = static_cast<UInt>(String::toInt(line.substr(7, 5))) - 1;\n      isLower = isLower || (k < i);\n      for(UInt l=0; l<3; l++)\n        if(line.length() >= 13+l*22+21)\n          N(i,k+l) += String::toDouble(line.substr(13+l*22, 21));\n    }\n    N.setType(Matrix::SYMMETRIC, isLower ? Matrix::LOWER : Matrix::UPPER);\n    fillSymmetric(N);\n    N.setType(Matrix::SYMMETRIC, Matrix::UPPER);\n\n    // convert correlation or covariance matrix to normals\n    if(String::endsWith((*iter)->label, \"CORR\"))\n    {\n      for(UInt i=1; i<dimension; i++)\n        N.column(0, i-1) *= N(i,i);\n      for(UInt i=0; i<dimension; i++)\n        N.row(i, dimension-i) *= N(i,i);\n    }\n    if(String::endsWith((*iter)->label, \"CORR\") || String::endsWith((*iter)->label, \"COVA\"))\n      inverse(N);\n\n    return N;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/cpf2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file cpf2Orbit.cpp\n*\n* @brief Read orbit data from SLR prediction (CPF) format\n*\n* @author Barbara Suesser-Rechberger\n* @date 2022-11-24\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html}{CPF file}\nand writes an \\file{instrument file (ORBIT)}{instrument}.\n\nThe time format of the CPF file is UTC.\nThe coordinate system used in the CPF format is usually represented in TRF.\nIf \\configClass{earthRotation}{earthRotationType} is provided the data are transformed\nfrom terrestrial (TRF) to celestial reference frame (CRF).\n\nSee also \\program{Orbit2Cpf}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read orbit from SLR prediction (CPF) format\n* @ingroup programsConversionGroup */\nclass Cpf2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Cpf2Orbit, SINGLEPROCESS, \"Read orbit from SLR prediction (CPF) format\", Conversion, Slr, Instrument)\n\n/***********************************************/\n\nvoid Cpf2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         fileNameOrbit;\n    FileName         fileNameIn;\n    EarthRotationPtr earthRotation;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOrbit, Config::MUSTSET, \"output/orbit_{satellite}_{loopNumberEphVersion:%03i}{loopNumberVersion:%02i}_{loopSource}_{loopTime:%D}.dat\", \"\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfile\",       fileNameIn,    Config::MUSTSET, \"\", \"SLR CPF file\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    std::string line;\n\n    std::string satelliteName;\n    std::map<Time, OrbitEpoch> orbEpoch;\n    Time time;\n\n    // Get a reference to OrbitEpoch object at specified time. OrbitEpoch object\n    // will be default created (all NAN) if it does not already exist.\n    auto orbitEpochGetOrInsert = [&orbEpoch](const Time &time)-> OrbitEpoch&\n    {\n      if(orbEpoch.count(time) == 0)\n      {\n        orbEpoch[time] = {};\n        orbEpoch[time].time = time;\n        orbEpoch[time].position = Vector3d(NAN,NAN,NAN);\n        orbEpoch[time].velocity = Vector3d(NAN,NAN,NAN);\n        orbEpoch[time].acceleration = Vector3d(NAN,NAN,NAN);\n      }\n      return orbEpoch[time];\n    };\n\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n      std::string type = String::upperCase(line.substr(0,2));\n      std::stringstream ss(line.substr(2));\n\n      if(type == \"H1\") // basic information 1\n      {\n        Int version, year, month, day, hour, ephemeridenSubSequenceNumber;\n        std::string cpf, source, ephemeridenSequenceNumber;\n\n        ss>>cpf>>version>>source>>year>>month>>day>>hour>>ephemeridenSequenceNumber>>ephemeridenSubSequenceNumber>>satelliteName;\n\n      } else if(type == \"H2\") // basic information 2\n      {\n        Int cosparId, sic, noradId, startYear, startMonth, startDay, startHour, startMinute, startSecond, endYear, endMonth, endDay, endHour, endMinute, endSecond, time, comp, targetType, refFrame, comCorr;\n\n        ss>>cosparId>>sic>>noradId>>startYear>>startMonth>>startDay>>startHour>>startMinute>>startSecond>>endYear>>endMonth>>endDay>>endHour>>endMinute>>endSecond>>time>>comp>>targetType>>refFrame>>comCorr;\n\n        if(refFrame > 0)\n        {\n          // Other reference frame than geocentric true body-fixed is not considered at the moment.\n          logStatus<<\"Other reference frame than geocentric true body-fixed is not considered at the moment: satellite <\"<<satelliteName<<\">\"<<Log::endl;\n          continue;\n        }\n\n        if(comCorr > 0)\n        {\n          // COM correction applied, Prediction is for retro-reflector array.\n          logStatus<<\"Center of mass correction applied. Prediction is for retroreflector array. Data set not considered: satellite: <\"<<satelliteName<<\">\"<<Log::endl;\n        }\n\n      } if(type == \"10\") // position record\n      {\n        Int directionFlag, mjdDay,leapSecondFlag;\n        Double sec, x, y, z;\n\n        ss>>directionFlag>>mjdDay>>sec>>leapSecondFlag>>x>>y>>z;\n\n        if(directionFlag > 0)\n        {\n          // direction flag 1 or 2 is not considered in the moment\n          logStatus<<\"Direction flag 1 or 2 is not considered in the moment: satellite <\"<<satelliteName<<\">\"<<Log::endl;\n          continue;\n        }\n\n        // SLR predictions are given in UTC\n        time = timeUTC2GPS(mjd2time(mjdDay) + seconds2time(sec));\n        OrbitEpoch& orbitEpoch = orbitEpochGetOrInsert(time);\n        // Set the position\n        orbitEpoch.position = Vector3d(x,y,z);\n\n      }\n      else if(type == \"20\") // velocity record\n      {\n        Int directionFlag;\n        Double velX, velY, velZ;\n\n        ss>>directionFlag>>velX>>velY>>velZ;\n\n        if(directionFlag > 0)\n        {\n          // direction flag 1 or 2 is not considered in the moment\n          logStatus<<\"Direction flag 1 or 2 is not considered: satellite <\"<<satelliteName<<\">\"<<Log::endl;\n          continue;\n        }\n\n        OrbitEpoch& orbitEpoch = orbitEpochGetOrInsert(time);\n        // Set velocity at correct time\n        orbitEpoch.velocity = Vector3d(velX,velY,velZ);\n\n      } else if(type == \"30\")\n      {\n        // Corrections\n        logStatus<<\"Record 30: Corrections not need for near earth satellites\" <<Log::endl;\n      } else if(type == \"99\")\n      {\n        // File end\n      }\n    } // while\n\n    OrbitArc orbArc;\n\n    for(const auto &orb : orbEpoch)\n      orbArc.push_back(orb.second);\n\n    if(earthRotation)\n    {\n      // Rotation from TRF to CRF\n      logStatus<<\"rotation from TRF to CRF\"<<Log::endl;\n      Single::forEach(orbArc.size(), [&](UInt i)\n      {\n      const Rotary3d rotation = inverse(earthRotation->rotaryMatrix(orbArc.at(i).time));\n      orbArc.at(i).position = rotation.rotate(orbArc.at(i).position);\n      if(orbArc.at(i).velocity.r() > 0)\n          orbArc.at(i).velocity = rotation.rotate(orbArc.at(i).velocity) + crossProduct(earthRotation->rotaryAxis(orbArc.at(i).time), orbArc.at(i).position);\n      });\n    }\n\n    // ==============================\n    // write results\n    // -------------\n    if(orbArc.size())\n    {\n      logStatus<<\"write orbit data to file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOrbit, orbArc);\n      Arc::printStatistics(orbArc);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/crd2NormalPoints.cpp",
    "content": "/***********************************************/\n/**\n* @file crd2NormalPoints.cpp\n*\n* @brief read SLR data from CRD format.\n*\n* @author Torsten Mayer-Guerr\n* @author Barbara Suesser-Rechberger\n* @date 2022-05-07\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/formats/crd.html}{CRD file}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding normal point data like range, accuracy, redundancy, wavelength and window size.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read SLR data from CRD format.\n* @ingroup programsConversionGroup */\nclass Crd2NormalPoints\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Crd2NormalPoints, SINGLEPROCESS, \"read SLR data from CRD format for a given satellite\", Conversion, Slr, Instrument)\n\n/***********************************************/\n\nvoid Crd2NormalPoints::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameNormalPoints;\n    FileName fileNameMeteorological;\n    FileName fileNameIn;\n\n    readConfig(config, \"outputfileNormalPoints\",    fileNameNormalPoints,   Config::MUSTSET,  \"output/normalsPoints_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"outputfileMeteorological\",  fileNameMeteorological, Config::MUSTSET,  \"output/meteorological_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"inputfileSlrData\",          fileNameIn,            Config::MUSTSET,  \"\", \"SLR CRD files\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    std::string stationMonumentNumber;\n    Double transmitWavelength;\n    std::string satelliteName;\n    Time sessionDate;\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    std::string line;\n\n    std::vector<SatelliteLaserRangingEpoch> normalPointEpoch;\n    std::map<Time, MeteorologicalEpoch> metEpoch;\n    std::multimap<std::string, std::map<Time, MeteorologicalEpoch>> metEpochStations;\n    std::multimap<std::string, std::vector<SatelliteLaserRangingEpoch>> normalPointEpochStations;\n    std::vector<std::string> stationMonumentNumbers;\n\n    // Get a reference to MeteorologicalEpoch object at specified time. MeteorologicalEpoch object\n    // will be default created (all NAN) if it does not already exist.\n    auto metEpochGetOrInsert = [&metEpoch](const Time &time)-> MeteorologicalEpoch&\n    {\n      if(metEpoch.count(time) == 0)\n      {\n        metEpoch[time] = {};\n        metEpoch[time].time = time;\n        metEpoch[time].temperature = NAN;\n        metEpoch[time].pressure = NAN;\n        metEpoch[time].humidity = NAN;\n        metEpoch[time].windSpeed = NAN;\n        metEpoch[time].solarRadiation = NAN;\n        metEpoch[time].precipitation = NAN;\n      }\n      return metEpoch[time];\n    };\n\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n      std::string type = String::upperCase(line.substr(0,2));\n      std::stringstream ss(line.substr(2));\n\n      if(type == \"H2\") // station header\n      {\n        std::string stationName;\n        ss>>stationName>>stationMonumentNumber;\n\n        if(!stationMonumentNumbers.empty())\n        {\n          if(std::find(stationMonumentNumbers.begin(), stationMonumentNumbers.end(), stationMonumentNumber) == stationMonumentNumbers.end())\n            stationMonumentNumbers.push_back(stationMonumentNumber);\n\n        }\n        else\n        {\n          stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n      }\n      else if(type == \"H3\") // target header\n      {\n        ss>>satelliteName;\n      }\n      else if(type == \"H4\") // session header\n      {\n        Int dataType,year, month, day;\n\n        ss>>dataType>>year>>month>>day;\n        // Session time in UTC\n        sessionDate = date2time(year, month, day);\n      }\n      else if(type == \"H5\") // Prediction Header\n      {\n      }\n      else if(type == \"H8\") // end of session\n      {\n        normalPointEpochStations.insert({stationMonumentNumber, normalPointEpoch});\n        metEpochStations.insert({stationMonumentNumber, metEpoch});\n\n        // Clear the vector and map for the next session\n        normalPointEpoch.clear();\n        metEpoch.clear();\n        continue;\n\n      }\n      else if(type == \"C0\")\n      {\n        Int detailType;\n        ss>>detailType>>transmitWavelength;\n      }\n      else if(type == \"11\") // normal points record\n      {\n        Double      seconds, timeOfFlight;\n        std::string systemId;\n        Int         epoch, count;\n        Double      window, binRms;\n        SatelliteLaserRangingEpoch nPointEpoch;\n\n        ss>>seconds>>timeOfFlight>>systemId>>epoch>>window>>count>>binRms;\n\n        // Time in UTC\n        Time time = sessionDate + seconds2time(seconds);\n\n        switch(epoch)\n        {\n          case 0: time -= seconds2time(timeOfFlight);     break; // ground receive time (at SRP) (two-way)\n          case 1: time -= seconds2time(0.5*timeOfFlight); break; // spacecraft bounce time (two-way)\n          case 2: /* standard */                          break; // ground transmit time (at SRP) (two-way)\n          default:\n            logWarning<<epoch<<\" Epoch Event (indicates the time event reference) not implemented\"<<Log::endl;\n        }\n\n        // GROOPS uses GPS time\n        nPointEpoch.time = timeUTC2GPS(time);\n        nPointEpoch.range = 0.5*timeOfFlight*LIGHT_VELOCITY;\n\n        if(count > 1)\n          nPointEpoch.accuracy = 0.5*binRms*1e-12/std::sqrt(count-1)*LIGHT_VELOCITY;\n        else\n          nPointEpoch.accuracy = 0.5*binRms*1e-12*LIGHT_VELOCITY;\n\n        nPointEpoch.redundancy = count;\n        nPointEpoch.wavelength = transmitWavelength*1e-9;\n        nPointEpoch.window = window;\n        nPointEpoch.azmiuth = NAN;\n        nPointEpoch.elevation = NAN;\n\n        normalPointEpoch.push_back(nPointEpoch);\n      }\n      else if(type == \"20\") // meteorological record\n      {\n        Double seconds, surfacePressure, surfaceTemperature, relativeHumidity;\n\n        ss>>seconds>>surfacePressure>>surfaceTemperature>>relativeHumidity;\n\n        // GROOPS uses GPS time\n        Time time = timeUTC2GPS(sessionDate + seconds2time(seconds));\n\n        // Is neccessary due to record 20 and 21 may be in unspecified order.\n        MeteorologicalEpoch& meteorologicalEpoch = metEpochGetOrInsert(time);\n        // surface temperature in [K]\n        meteorologicalEpoch.temperature = surfaceTemperature;\n        // pressure in [Pa]: 1 millibar = 1 hPa = 100 Pa\n        meteorologicalEpoch.pressure = surfacePressure*100;\n        // relative humidity in percent\n        meteorologicalEpoch.humidity = relativeHumidity;\n\n      }\n      else if(type == \"21\")\n      {\n        Double seconds, windSpeed;\n\n        ss>>seconds>>windSpeed;\n\n        // GROOPS uses GPS time\n        Time time = timeUTC2GPS(sessionDate + seconds2time(seconds));\n\n        // Is neccessary due to record 20 and 21 may be in unspecified order.\n        MeteorologicalEpoch& meteorologicalEpoch = metEpochGetOrInsert(time);\n        // Set wind speed at correct time\n        meteorologicalEpoch.windSpeed = windSpeed;\n      }\n      else if(type == \"30\")\n      {\n        // Angles are not considered in the moment.\n        logStatus<<\"Record 30 available\" <<Log::endl;\n      }\n      else\n      {\n      }\n    } // while\n\n    // write results\n    // -------------\n    for(auto stationMonumentNr : stationMonumentNumbers)\n    {\n      SatelliteLaserRangingArc arcSlr;\n      MeteorologicalArc arcMeteorological;\n\n      for(const auto &npStat : normalPointEpochStations)\n      {\n        if(npStat.first == stationMonumentNr)\n          for(const auto &np : npStat.second)\n            arcSlr.push_back(np);\n      }\n\n      for(const auto &metStat : metEpochStations)\n      {\n        if(metStat.first == stationMonumentNr)\n          for(const auto &met: metStat.second)\n            arcMeteorological.push_back(met.second);\n      }\n\n      VariableList varList;\n      varList.setVariable(\"station\", stationMonumentNr);\n\n      if(arcSlr.size())\n      {\n        logStatus<<\"write normal point data to file <\"<<fileNameNormalPoints(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameNormalPoints(varList), arcSlr);\n        Arc::printStatistics(arcSlr);\n      }\n\n      if(arcMeteorological.size())\n      {\n        logStatus<<\"write meteorological data to file <\"<<fileNameMeteorological(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameMeteorological(varList), arcMeteorological);\n        Arc::printStatistics(arcMeteorological);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/cstg2NormalPoints.cpp",
    "content": "/***********************************************/\n/**\n* @file cstg2NormalPoints.cpp\n*\n* @brief read SLR data from CSTG format.\n*\n* @author Barbara Suesser-Rechberger\n* @date 2022-12-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html}{CSTG file} provided by the \\href{https://ilrs.gsfc.nasa.gov/}{ILRS}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding normal point data like range, accuracy, redundancy, wavelength and window size.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include <string_view>\n\n/***** CLASS ***********************************/\n\n/** @brief Read SLR data from CSTG format.\n* @ingroup programsConversionGroup */\nclass Cstg2NormalPoints\n{\n  std::vector<std::string> splitString(const std::string& str);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Cstg2NormalPoints, SINGLEPROCESS, \"read SLR data from CSTG format for a given satellite\", Conversion, Slr, Instrument)\n\n/***********************************************/\n\nvoid Cstg2NormalPoints::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameNormalPoints;\n    FileName fileNameMeteorological;\n    FileName fileNameIn;\n\n    readConfig(config, \"outputfileNormalPoints\",    fileNameNormalPoints,   Config::MUSTSET,  \"output/normalsPoints_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"outputfileMeteorological\",  fileNameMeteorological, Config::MUSTSET,  \"output/meteorological_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"inputfileSlrData\",          fileNameIn,             Config::MUSTSET,  \"\", \"SLR CSTG file\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    std::string stationMonumentNumber;\n    std::string satelliteName;\n    Time sessionDate;\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n\n    std::vector<SatelliteLaserRangingEpoch> normalPointEpoch;\n    std::vector<MeteorologicalEpoch> metEpoch;\n    std::multimap<std::string, std::vector<MeteorologicalEpoch>> metEpochStations;\n    std::multimap<std::string, std::vector<SatelliteLaserRangingEpoch>> normalPointEpochStations;\n    std::vector<std::string> stationMonumentNumbers;\n    std::string fileLine;\n\n    while(std::getline(file, fileLine))\n    {\n      // Check for session marker\n      if (fileLine == \"99999\")\n      {\n        SatelliteLaserRangingEpoch nPointEpoch;\n        MeteorologicalEpoch mEpoch;\n        std::string headerLine;\n        std::getline(file, headerLine);\n\n        // Extract header data\n        Int year = std::stoi(headerLine.substr(7,2));\n        year += (year <= 50) ? 2000 : 1900;\n        // Session time in UTC\n        Time sessionDate = date2time(year,1,1)+mjd2time(std::stoi(headerLine.substr(9,3))-1);\n\n        // Store different station monument numbers\n        std::string stationMonumentNumber = headerLine.substr(12,4);\n        if(!stationMonumentNumbers.empty())\n        {\n          if(std::find(stationMonumentNumbers.begin(), stationMonumentNumbers.end(), stationMonumentNumber) == stationMonumentNumbers.end())\n            stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n        else\n        {\n          stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n        Double transmitWavelength = std::stod(headerLine.substr(20,4));\n        Int normalPointWindowIndicator = std::stoi(headerLine.substr(42,1));\n\n        // Extract all data records, until next session marker (\"99999\")\n        std::vector<std::string> dataRecords;\n        while(file.good())\n        {\n          // Remember current position, this is needed if the extracted line have to be put back into stream (undo effect of getline)\n          auto preReadPos = file.tellg();\n          std::getline(file,fileLine);\n\n          if(fileLine.empty())\n            continue;\n          if(fileLine != \"99999\")\n            dataRecords.push_back(fileLine);\n          else\n          {\n            // Set read pointer back to session marker (next getline will again extract the session marker)\n            file.seekg(preReadPos, file.beg);\n            break;\n          }\n        }\n\n        for(auto dataRecord : dataRecords)\n        {\n          // In cstg file the seconds are given in the units of 0.1 us, GROOPS uses GPS time\n          nPointEpoch.time = timeUTC2GPS(sessionDate + seconds2time(std::stod(dataRecord.substr(0, 12))*1e-7));\n          nPointEpoch.range = 0.5*std::stod(dataRecord.substr(12, 12))*1e-12*LIGHT_VELOCITY;\n\n          Double binRms = std::stod(dataRecord.substr(24, 7));\n          Int count = std::stoi(dataRecord.substr(43, 4));\n          if(count > 1)\n            nPointEpoch.accuracy = 0.5*binRms*1e-12/std::sqrt(count-1)*LIGHT_VELOCITY;\n          else\n            nPointEpoch.accuracy = 0.5*binRms*1e-12*LIGHT_VELOCITY;\n\n          nPointEpoch.redundancy = count;\n\n          /* ILRS: The user of the data should interpret the value given as follows:\n            3000 - 9999: units are 0.1 nanometer\n            1000 - 2999: units are 1.0 nanometer\n          */\n          if(transmitWavelength >= 3000)\n            nPointEpoch.wavelength = transmitWavelength*1e-10;\n          else\n            nPointEpoch.wavelength = transmitWavelength*1e-9;\n\n          if(normalPointWindowIndicator == 1)\n            nPointEpoch.window = 5;\n          else if(normalPointWindowIndicator == 3)\n            nPointEpoch.window = 15;\n          else if(normalPointWindowIndicator == 4)\n            nPointEpoch.window = 20;\n          else if(normalPointWindowIndicator == 5)\n            nPointEpoch.window = 30;\n          else if(normalPointWindowIndicator == 6)\n            nPointEpoch.window = 60;\n          else if(normalPointWindowIndicator == 7)\n            nPointEpoch.window = 120;\n          else if(normalPointWindowIndicator == 8)\n            nPointEpoch.window = 180;\n          else if(normalPointWindowIndicator == 9)\n            nPointEpoch.window = 300;\n          else\n            nPointEpoch.window = NAN;\n\n          nPointEpoch.azmiuth = NAN;\n          nPointEpoch.elevation = NAN;\n\n          mEpoch.time = nPointEpoch.time;\n          // surface temperature in [K]: in cstg file it is given in 0.1 degree Kelvin\n          mEpoch.temperature = std::stod(dataRecord.substr(36, 4))*1e-1;\n          // pressure in [Pa]: in cstg file it is given in 0.1 millibar = 10 Pa\n          mEpoch.pressure = std::stod(dataRecord.substr(31, 5))*10;\n          // relative humidity in percent\n          mEpoch.humidity = std::stod(dataRecord.substr(40, 3));\n\n          mEpoch.windSpeed = NAN;\n          mEpoch.solarRadiation = NAN;\n          mEpoch.precipitation = NAN;\n\n          normalPointEpoch.push_back(nPointEpoch);\n          metEpoch.push_back(mEpoch);\n\n        }\n\n        // End of session\n        normalPointEpochStations.insert({stationMonumentNumber, normalPointEpoch});\n        metEpochStations.insert({stationMonumentNumber, metEpoch});\n        normalPointEpoch.clear();\n        metEpoch.clear();\n      }\n    } //while\n\n    // write results\n    // -------------\n    for(auto stationMonumentNr : stationMonumentNumbers)\n    {\n      SatelliteLaserRangingArc arcSlr;\n      MeteorologicalArc arcMeteorological;\n\n      for(const auto &npStat : normalPointEpochStations)\n      {\n        if(npStat.first == stationMonumentNr)\n          for(const auto &np : npStat.second)\n            arcSlr.push_back(np);\n      }\n\n      for(const auto &metStat : metEpochStations)\n      {\n        if(metStat.first == stationMonumentNr)\n          for(const auto &met: metStat.second)\n            arcMeteorological.push_back(met);\n      }\n\n      VariableList varList;\n      varList.setVariable(\"station\", stationMonumentNr);\n\n      if(arcSlr.size())\n      {\n        logStatus<<\"write normal point data to file <\"<<fileNameNormalPoints(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameNormalPoints(varList), arcSlr);\n        Arc::printStatistics(arcSlr);\n      }\n\n      if(arcMeteorological.size())\n      {\n        logStatus<<\"write meteorological data to file <\"<<fileNameMeteorological(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameMeteorological(varList), arcMeteorological);\n        Arc::printStatistics(arcMeteorological);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<std::string> Cstg2NormalPoints::splitString(const std::string& str)\n{\n  std::vector<std::string> recordLines;\n\n  std::stringstream ss(str);\n  std::string line;\n  while(std::getline(ss, line, '\\n'))\n  {\n    recordLines.push_back(line);\n  }\n  return recordLines;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/merit2FullRate.cpp",
    "content": "/***********************************************/\n/**\n* @file merit2FullRate.cpp\n*\n* @brief Read SLR data (full-rate) from merit format.\n*\n* @author Barbara Suesser-Rechberger\n* @date 2023-01-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html}{MERIT II file}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding full rate data like range, accuracy, wavelength, azimuth and elevation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include <string_view>\n\n/***** CLASS ***********************************/\n\n/** @brief Read SLR data (full-rate) from merit format.\n* @ingroup programsConversionGroup */\nclass Merit2FullRate\n{\n  std::vector<std::string> splitString(const std::string& str);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Merit2FullRate, SINGLEPROCESS, \"Read SLR data (full-rate) from merit format.\", Conversion, Slr, Instrument)\n\n/***********************************************/\n\nvoid Merit2FullRate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameNormalPoints;\n    FileName fileNameMeteorological;\n    FileName fileNameIn;\n\n    readConfig(config, \"outputfileNormalPoints\",    fileNameNormalPoints,   Config::MUSTSET,  \"output/normalsPoints_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"outputfileMeteorological\",  fileNameMeteorological, Config::MUSTSET,  \"output/meteorological_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"inputfileSlrData\",          fileNameIn,             Config::MUSTSET,  \"\", \"SLR MERIT II file\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    std::string line;\n\n    std::string stationMonumentNumber;\n    std::multimap<std::string, MeteorologicalEpoch> metEpochStations;\n    std::multimap<std::string, SatelliteLaserRangingEpoch> fullRateEpochStations;\n    std::vector<std::string> stationMonumentNumbers;\n\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n      SatelliteLaserRangingEpoch fullRateEpoch;\n      MeteorologicalEpoch mEpoch;\n\n      Int normalPointWindowIndicator = String::toInt(line.substr(114, 1));\n      //logStatus<<\"normalPointWindowIndicator: <\"<< normalPointWindowIndicator<<\">\"<<Log::endl;\n\n      if(normalPointWindowIndicator == 0)\n      {\n        // Store different station monument numbers\n        std::string stationMonumentNumber = line.substr(24, 4);\n        if(!stationMonumentNumbers.empty())\n        {\n          if(std::find(stationMonumentNumbers.begin(), stationMonumentNumbers.end(), stationMonumentNumber) == stationMonumentNumbers.end())\n            stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n        else\n        {\n          stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n\n        Int year = String::toInt(line.substr(7,2));\n        year += (year <= 50) ? 2000 : 1900;\n\n        // Session time in UTC\n        Time sessionDate = date2time(year,1,1)+mjd2time(String::toInt(line.substr(9,3))-1);\n\n        // In merit II file the seconds are given in the units of 0.1 us\n        Time time = sessionDate + seconds2time(std::stod(line.substr(12,12))*1e-7);\n        Int epoch = String::toInt(line.substr(119,1));\n        Double timeOfFlight = std::stod(line.substr(45, 12))*1e-12;\n\n        switch(epoch)\n        {\n          case 0: time -= seconds2time(timeOfFlight);     break; // ground receive time (at SRP) (two-way)\n          case 1: time -= seconds2time(0.5*timeOfFlight); break; // spacecraft bounce time (two-way)\n          case 2: /* standard */                          break; // ground transmit time (at SRP) (two-way)\n          default:\n            logWarning<<epoch<<\" Epoch Event (indicates the time event reference) not implemented\"<<Log::endl;\n        }\n\n        // GROOPS uses GPS time\n        fullRateEpoch.time = timeUTC2GPS(time);\n        fullRateEpoch.range = 0.5*timeOfFlight*LIGHT_VELOCITY;\n\n        /* ILRS: The user of the data should interpret the value given as follows:\n          3000 - 9999: units are 0.1 nanometer\n          1000 - 2999: units are 1.0 nanometer\n        */\n        Double transmitWavelength = std::stod(line.substr(64, 4));\n        if(transmitWavelength >= 3000)\n          fullRateEpoch.wavelength = transmitWavelength*1e-10;\n        else\n          fullRateEpoch.wavelength = transmitWavelength*1e-9;\n\n        Double passRMS = std::stod(line.substr(58, 7));\n        fullRateEpoch.accuracy = 0.5*passRMS*1e-12*LIGHT_VELOCITY;\n\n        fullRateEpoch.redundancy = NAN;\n        fullRateEpoch.window = NAN;\n\n        // Azimuth and Elevation given in 0.1 mdegrees\n        fullRateEpoch.azmiuth = DEG2RAD*std::stod(line.substr(32, 7))*1e-4;\n        fullRateEpoch.elevation = DEG2RAD*std::stod(line.substr(39, 6))*1e-4;\n\n        mEpoch.time = fullRateEpoch.time;\n        // surface temperature in [K]: in cstg file it is given in 0.1 degree Kelvin\n        mEpoch.temperature = std::stod(line.substr(73, 4))*1e-1;\n        // pressure in [Pa]: in cstg file it is given in 0.1 millibar = 10 Pa\n        mEpoch.pressure = std::stod(line.substr(68, 5))*10;\n        // relative humidity in percent\n        mEpoch.humidity = std::stod(line.substr(77, 3));\n\n        mEpoch.windSpeed = NAN;\n        mEpoch.solarRadiation = NAN;\n        mEpoch.precipitation = NAN;\n\n        fullRateEpochStations.insert({stationMonumentNumber, fullRateEpoch});\n        metEpochStations.insert({stationMonumentNumber, mEpoch});\n\n      } else\n      {\n        logStatus<<\"File includes normal point data. Please use merit2NormalPoints conversion program!<\"<<fileNameNormalPoints<<\">\"<<Log::endl;\n      }\n    } // while\n\n\n    // write results\n    // -------------\n    for(auto stationMonumentNr : stationMonumentNumbers)\n    {\n      SatelliteLaserRangingArc arcSlr;\n      MeteorologicalArc arcMeteorological;\n\n      for(const auto &frStat : fullRateEpochStations)\n      {\n        if(frStat.first == stationMonumentNr)\n          arcSlr.push_back(frStat.second);\n      }\n\n      for(const auto &metStat : metEpochStations)\n      {\n        if(metStat.first == stationMonumentNr)\n          arcMeteorological.push_back(metStat.second);\n      }\n\n      VariableList varList;\n      varList.setVariable(\"station\", stationMonumentNr);\n\n      if(arcSlr.size())\n      {\n        logStatus<<\"write normal point data to file <\"<<fileNameNormalPoints(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameNormalPoints(varList), arcSlr);\n        Arc::printStatistics(arcSlr);\n      }\n\n      if(arcMeteorological.size())\n      {\n        logStatus<<\"write meteorological data to file <\"<<fileNameMeteorological(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameMeteorological(varList), arcMeteorological);\n        Arc::printStatistics(arcMeteorological);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/merit2NormalPoints.cpp",
    "content": "/***********************************************/\n/**\n* @file merit2NormalPoints.cpp\n*\n* @brief Read SLR data (normal points) from merit format.\n*\n* @author Barbara Suesser-Rechberger\n* @date 2023-01-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts \\href{https://ilrs.gsfc.nasa.gov/data_and_products/data/npt/npt_format.html}{MERIT II file}\nand writes an \\file{instrument file (METEOROLOGICAL)}{instrument} including meteorological data like\ntemperature, air pressure and humidity as well as an \\file{instrument file (SATELLITELASERRANGING)}{instrument}\nincluding normal point data like range, accuracy, redundancy, wavelength, window size, azimuth and elevation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include <string_view>\n\n/***** CLASS ***********************************/\n\n/** @brief Read SLR data (normal points) from merit format.\n* @ingroup programsConversionGroup */\nclass Merit2NormalPoints\n{\n  std::vector<std::string> splitString(const std::string& str);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Merit2NormalPoints, SINGLEPROCESS, \"Read SLR data (normal points) from merit format.\", Conversion, Slr, Instrument)\n\n/***********************************************/\n\nvoid Merit2NormalPoints::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameNormalPoints;\n    FileName fileNameMeteorological;\n    FileName fileNameIn;\n\n    readConfig(config, \"outputfileNormalPoints\",    fileNameNormalPoints,   Config::MUSTSET,  \"output/normalsPoints_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"outputfileMeteorological\",  fileNameMeteorological, Config::MUSTSET,  \"output/meteorological_{station}.dat\", \"variable {station} available\");\n    readConfig(config, \"inputfileSlrData\",          fileNameIn,             Config::MUSTSET,  \"\", \"SLR MERIT II file\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    std::string line;\n\n    std::string stationMonumentNumber;\n    std::multimap<std::string, MeteorologicalEpoch> metEpochStations;\n    std::multimap<std::string, SatelliteLaserRangingEpoch> normalPointEpochStations;\n    std::vector<std::string> stationMonumentNumbers;\n\n    while(std::getline(file, line))\n    {\n      if(line.empty())\n        continue;\n      SatelliteLaserRangingEpoch nPointEpoch;\n      MeteorologicalEpoch mEpoch;\n\n      Int normalPointWindowIndicator = String::toInt(line.substr(114, 1));\n      //logStatus<<\"normalPointWindowIndicator: <\"<< normalPointWindowIndicator<<\">\"<<Log::endl;\n\n\n      if(normalPointWindowIndicator > 0)\n      {\n        // Store different station monument numbers\n        std::string stationMonumentNumber = line.substr(24, 4);\n        if(!stationMonumentNumbers.empty())\n        {\n          if(std::find(stationMonumentNumbers.begin(), stationMonumentNumbers.end(), stationMonumentNumber) == stationMonumentNumbers.end())\n            stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n        else\n        {\n          stationMonumentNumbers.push_back(stationMonumentNumber);\n        }\n\n        Int year = String::toInt(line.substr(7,2));\n        //logStatus<<\"Year: <\"<< year<<\">\"<<Log::endl;\n        year += (year <= 50) ? 2000 : 1900;\n\n        // Session time in UTC\n        Time sessionDate = date2time(year,1,1)+mjd2time(String::toInt(line.substr(9,3))-1);\n\n        // In merit II file the seconds are given in the units of 0.1 us\n        Time time = sessionDate + seconds2time(std::stod(line.substr(12,12))*1e-7);\n        Int epoch = String::toInt(line.substr(119,1));\n        Double timeOfFlight = std::stod(line.substr(45, 12))*1e-12;\n\n        switch(epoch)\n        {\n          case 0: time -= seconds2time(timeOfFlight);     break; // ground receive time (at SRP) (two-way)\n          case 1: time -= seconds2time(0.5*timeOfFlight); break; // spacecraft bounce time (two-way)\n          case 2: /* standard */                          break; // ground transmit time (at SRP) (two-way)\n          default:\n            logWarning<<epoch<<\" Epoch Event (indicates the time event reference) not implemented\"<<Log::endl;\n        }\n\n        nPointEpoch.time = timeUTC2GPS(time);\n        nPointEpoch.range = 0.5*timeOfFlight*LIGHT_VELOCITY;\n\n        /* ILRS: The user of the data should interpret the value given as follows:\n          3000 - 9999: units are 0.1 nanometer\n          1000 - 2999: units are 1.0 nanometer\n        */\n        Double transmitWavelength = std::stod(line.substr(64, 4));\n        if(transmitWavelength >= 3000)\n          nPointEpoch.wavelength = transmitWavelength*1e-10;\n        else\n          nPointEpoch.wavelength = transmitWavelength*1e-9;\n\n        // In the merit format there is no information about the bin RMS, we take the pass RMS\n        Double passRMS = std::stod(line.substr(58, 7));\n        nPointEpoch.redundancy = std::stod(line.substr(115, 4));\n        logStatus<<\"epoch: <\"<< epoch<<\">\"<<Log::endl;\n\n        if(nPointEpoch.redundancy > 1)\n          nPointEpoch.accuracy = 0.5*passRMS*1e-12/std::sqrt(nPointEpoch.redundancy-1)*LIGHT_VELOCITY;\n        else\n          nPointEpoch.accuracy = 0.5*passRMS*1e-12*LIGHT_VELOCITY;\n\n\n        if(normalPointWindowIndicator == 1)\n          nPointEpoch.window = 5;\n        else if(normalPointWindowIndicator == 3)\n          nPointEpoch.window = 15;\n        else if(normalPointWindowIndicator == 4)\n          nPointEpoch.window = 20;\n        else if(normalPointWindowIndicator == 5)\n          nPointEpoch.window = 30;\n        else if(normalPointWindowIndicator == 6)\n          nPointEpoch.window = 60;\n        else if(normalPointWindowIndicator == 7)\n          nPointEpoch.window = 120;\n        else if(normalPointWindowIndicator == 8)\n          nPointEpoch.window = 180;\n        else if(normalPointWindowIndicator == 9)\n          nPointEpoch.window = 300;\n        else\n          nPointEpoch.window = NAN;\n\n        // Azimuth and Elevation given in 0.1 mdegrees\n        nPointEpoch.azmiuth = DEG2RAD*std::stod(line.substr(32, 7))*1e-4;\n        nPointEpoch.elevation = DEG2RAD*std::stod(line.substr(39, 6))*1e-4;\n\n        mEpoch.time = nPointEpoch.time;\n        // surface temperature in [K]: in cstg file it is given in 0.1 degree Kelvin\n        mEpoch.temperature = std::stod(line.substr(73, 4))*1e-1;\n        // pressure in [Pa]: in cstg file it is given in 0.1 millibar = 10 Pa\n        mEpoch.pressure = std::stod(line.substr(68, 5))*10;\n        // relative humidity in percent\n        mEpoch.humidity = std::stod(line.substr(77, 3));\n\n        mEpoch.windSpeed = NAN;\n        mEpoch.solarRadiation = NAN;\n        mEpoch.precipitation = NAN;\n\n        normalPointEpochStations.insert({stationMonumentNumber, nPointEpoch});\n        metEpochStations.insert({stationMonumentNumber, mEpoch});\n\n      } else\n      {\n        logStatus<<\"File includes full-rate data. Please use merit2FullRate conversion program!<\"<<fileNameNormalPoints<<\">\"<<Log::endl;\n        break;\n      }\n    } // while\n\n\n    // write results\n    // -------------\n    for(auto stationMonumentNr : stationMonumentNumbers)\n    {\n      SatelliteLaserRangingArc arcSlr;\n      MeteorologicalArc arcMeteorological;\n\n      for(const auto &npStat : normalPointEpochStations)\n      {\n        if(npStat.first == stationMonumentNr)\n          arcSlr.push_back(npStat.second);\n      }\n\n      for(const auto &metStat : metEpochStations)\n      {\n        if(metStat.first == stationMonumentNr)\n          arcMeteorological.push_back(metStat.second);\n      }\n\n      VariableList varList;\n      varList.setVariable(\"station\", stationMonumentNr);\n\n      if(arcSlr.size())\n      {\n        logStatus<<\"write normal point data to file <\"<<fileNameNormalPoints(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameNormalPoints(varList), arcSlr);\n        Arc::printStatistics(arcSlr);\n      }\n\n      if(arcMeteorological.size())\n      {\n        logStatus<<\"write meteorological data to file <\"<<fileNameMeteorological(varList)<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameMeteorological(varList), arcMeteorological);\n        Arc::printStatistics(arcMeteorological);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/orbit2Cpf.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2Cpf.cpp\n*\n* @brief write orbit positions to CPF.\n*\n* @author Cornelia Tieber-Hubmann\n* @date 2023-03-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrites groops orbits to \\href{https://ilrs.gsfc.nasa.gov/data_and_products/formats/cpf.html}{CPF file}.\n\nThe coordinate system used in the CPF format is usually presented in ITRF.\nThe required time format for the input orbit file is GPS.\nThe time format of the output CPF file is given in UTC.\n\nSee also \\program{Cpf2Orbit}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"base/time.h\"\n#include \"files/filePlatform.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief write orbit positions to CPF.\n* @ingroup programsConversionGroup */\nclass Orbit2Cpf\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2Cpf, SINGLEPROCESS, \"write orbit positions to CPF\", Conversion, Orbit, Instrument)\n\n\n/***********************************************/\n\nvoid Orbit2Cpf::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          fileNameOut, fileNameIn;\n    EarthRotationPtr  earthRotation;\n    FileName          fileNameSatelliteInfo;\n    UInt              subDailyEphemerisSequenceNumber;\n    UInt              targetClass;\n\n    readConfig(config, \"outputfile\",             fileNameOut,                     Config::MUSTSET,  \"{target}_cpf_{fileDate}_{ephVerNum}{ver}.tug\", \"\");\n    readConfig(config, \"inputfileOrbit\",         fileNameIn,                      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileSatelliteInfo\", fileNameSatelliteInfo,           Config::MUSTSET,  \"{groopsDataDir}/slr/satellite/satelliteInfo/satelliteInfo.{satellite}.xml\", \"Platform File\");\n    readConfig(config, \"earthRotation\",          earthRotation,                   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"versionNumber\",          subDailyEphemerisSequenceNumber, Config::DEFAULT,  \"01\", \"Version number of production day with zero leading fill, e.g. 01\");\n    readConfig(config, \"targetClass\",            targetClass,                     Config::DEFAULT,  \"1\",  \"set 1 for passive retroreflector, set 0 for no retroreflector (includes debris)\");\n    if(isCreateSchema(config)) return;\n\n    // parameters from platform file\n    std::string sic(\"-1\"), cospar(\"-1\"), norad(\"-1\"), targetName(\"-1\");\n    Platform platform;\n    readFilePlatform(fileNameSatelliteInfo, platform);\n    auto satId = platform.findEquipment<PlatformSatelliteIdentifier>(Time());\n    if(satId)\n    {\n      if(!satId->sic.empty())    sic        = satId->sic;\n      if(!satId->cospar.empty()) cospar     = satId->cospar;\n      if(!satId->norad.empty())  norad      = satId->norad;\n      if(!satId->name.empty())   targetName = satId->name;\n    }\n\n    // Set parameters for header\n    Int compatibilityTIVs = 1; // integrable, geocentric ephemeris\n    Int referenceFrame    = 0; // 0=geocentric true body-fixed (default), 1=geocentric space-fixed (i.e., Inertial) (True-of-Date), 2=geocentric space-fixed (Mean-of-Date J2000)\n    Int rotAngleType      = 0; // 0=Not Applicable, 1=Lunar Euler angles, 2=North pole Right Ascension and Declination, and angle to prime meridian\n    Int centerOfMassCorr  = 0; // 0=None applied. Prediction is for center of mass of target, 1=Applied. Prediction is for retro-reflector array\n    Int targetLocation    = 1; // 1=Earth orbit, 0&2-10 see CPF pdf\n\n    // Starting date of orbit\n    // see Consolidated Laser Ranging Prediction Format Version 2.00 - Start dates and times\n    logStatus<<\"read orbit file <\"<<fileNameIn<<\">\"<<Log::endl;\n    OrbitArc orbit = InstrumentFile::read(fileNameIn);\n    const Time timeStart = timeGPS2UTC(orbit.front().time);\n    const Time timeEnd   = timeGPS2UTC(orbit.back().time);\n    logInfo<<\"  timeStart (UTC): \"<<timeStart.dateTimeStr()<<Log::endl;\n\n    logStatus<<\"write file <\"<<fileNameOut<<\">\"<<Log::endl;\n    OutFile file(fileNameOut);\n    // Write the header information to output file\n    file<<\"H1 CPF 2 tug \"<<System::now()%\"%y %m %d %H %O\"s<<\" \"<<subDailyEphemerisSequenceNumber<<\" \"<<targetName<<\" \"<<\"NotesOptional\"<<std::endl;\n\t  file<<\"H2 \"<<cospar<<\" \"<<sic<<\" \"<<norad<<\" \"<<timeStart%\"%y %m %d %H %M %S \"s<<timeEnd%\"%y %m %d %H %M %S \"s\n               <<medianSampling(orbit.times()).seconds()<<\" \"<<compatibilityTIVs<<\" \"<<targetClass<<\" \"<<referenceFrame<<\" \"<<rotAngleType<<\" \"\n               <<centerOfMassCorr<<\" \"<<targetLocation<<std::endl;\n\t  file<<\"H9\"<<std::endl;\n\n    // Write position information in ECEF reference frame to output file\n    Single::forEach(orbit.size(), [&](UInt i)\n    {\n      const Vector3d positionCPF = earthRotation->rotaryMatrix(orbit.at(i).time).rotate(orbit.at(i).position);\n      const Time     timeUTC     = timeGPS2UTC(orbit.at(i).time);\n      file<<\"10 0 \"<<timeUTC.mjdInt()<<\" \"<<timeUTC.mjdMod()*86400.<<\" 0 \"<<positionCPF.x()%\"%14.9f \"s<<positionCPF.y()%\"%14.9f \"s<<positionCPF.z()%\"%14.9f\"s<<std::endl;\n    });\n\n    file<<\"99\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/sinexEccentricties2SlrPlatform.cpp",
    "content": "/***********************************************/\n/**\n* @file sinexEccentricties2SlrPlatform.cpp\n*\n* @brief Platform file from SINEX eccentricties.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-12-12\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nReads metadata like station name, station number, approximate station position and station eccentricities\nfrom \\href{https://ilrs.gsfc.nasa.gov/network/site_procedures/eccentricity.html}{Station Eccentricities Sinex File}\n(une version) and write them to the \\configFile{outputfileStationInfo}{platform} for each station.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Platform file from SINEX eccentricties.\n* @ingroup programsConversionGroup */\nclass SinexEccentricties2SlrPlatform\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SinexEccentricties2SlrPlatform, SINGLEPROCESS, \"Platform file from SINEX eccentricties.\", Conversion, Slr)\n\n/***********************************************/\n\nvoid SinexEccentricties2SlrPlatform::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNamePlatform, fileNameSinex;\n    std::vector<std::string> stationNames;\n    std::string variableLoopStation;\n\n    readConfig(config, \"outputfileStationInfo\", fileNamePlatform,    Config::MUSTSET,  \"\",        \"loop variable is replaced with station name\");\n    readConfig(config, \"variableLoopStation\",   variableLoopStation, Config::DEFAULT,  \"station\", \"variable name for station loop\");\n    readConfig(config, \"inputfileSinex\",        fileNameSinex,       Config::MUSTSET,  \"\",        \"SINEX file (.snx or .ssc)\");\n    readConfig(config, \"stationName\",           stationNames,        Config::OPTIONAL, \"\",        \"convert only these stations\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read SINEX file <\"<<fileNameSinex<<\">\"<<Log::endl;\n    Sinex sinex;\n    readFileSinex(fileNameSinex, sinex);\n\n    // SITE/ECCENTRICITY\n    // -----------------\n    std::map<std::string, Platform> platforms;\n    for(std::string &line : sinex.findBlock(\"SITE/ECCENTRICITY\")->lines)\n    {\n      // *SITE PT SOLN T DATA_START__ DATA_END____ UNE UP______ NORTH___ EAST____        CDP-SOD_\n      std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n        continue;\n      // if(line.at(14) != 'L')\n      //   continue;\n      if(line.substr(42, 3) != \"UNE\")\n        throw(Exception(\"SINEX file must provide eccentricities in UNE\"));\n\n      Platform &platform  = platforms[name];\n      platform.markerName = name;\n      auto station = std::make_shared<PlatformSlrStation>();\n      station->name = name;\n      if(line.size() >= 88)\n        station->name = String::trim(line.substr(80, 8)); // CDP-SOD\n      station->timeStart = Sinex::str2time(line, 16, FALSE);\n      station->timeEnd   = Sinex::str2time(line, 29, TRUE);\n      station->position = Vector3d(String::toDouble(line.substr(55, 8)), String::toDouble(line.substr(64, 8)), String::toDouble(line.substr(46, 8)));\n      platform.equipments.push_back(station);\n    }\n\n    // SITE/ID\n    // -------\n    for(std::string &line : sinex.findBlock(\"SITE/ID\")->lines)\n    {\n      // *         1         2         3         4         5         6         7         8\n      // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n      // *Code PT __DOMES__ T _STATION DESCRIPTION__ APPROX_LON_ APPROX_LAT_ _APP_H_     CDP-SOD_\n      line.resize(std::max(line.size(), UInt(44)), ' ');\n      std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n        continue;\n      Platform &platform = platforms[name];\n      platform.markerName   = name;\n      platform.markerNumber = String::trim(line.substr(9, 9));\n      platform.comment      = String::trim(line.substr(21, 11));\n      // approxPosition\n      if(line.size() >= 75)\n      {\n        const Double longitude   = String::toDouble(line.substr(44, 3)) + String::toDouble(line.substr(48, 2))/60 + String::toDouble(line.substr(51, 4))/3600;\n        const Double latitude    = String::toDouble(line.substr(56, 3)) + (String::startsWith(String::trim(line.substr(56, 3)), \"-\") ? -1 : 1) * std::fabs(String::toDouble(line.substr(60, 2))/60 + String::toDouble(line.substr(62, 5))/3600);\n        const Double height      = String::toDouble(line.substr(68, 7));\n        platform.approxPosition = Ellipsoid()(Angle(DEG2RAD*longitude), Angle(DEG2RAD*latitude), height);\n      }\n      if(line.size() >= 88)\n      {\n        const std::string CDP_SOD = String::trim(line.substr(80, 8)); // CDP-SOD\n        auto iter = std::find_if(platform.equipments.begin(), platform.equipments.end(),\n                                 [&](const auto &x) {return (x->name == CDP_SOD);});\n        if(iter != platform.equipments.end())\n        {\n          auto station = std::dynamic_pointer_cast<PlatformSlrStation>(*iter);\n          station->serial  = String::trim(line.substr(9, 9));\n          station->comment = String::trim(line.substr(32, 11));\n        }\n      }\n    }\n\n    // write platform files\n    // --------------------\n    VariableList varList;\n    varList.setVariable(variableLoopStation, \"****\");\n    logStatus<<\"write platform files <\"<<fileNamePlatform(varList)<<\">\"<<Log::endl;\n    for(auto &platformPair : platforms)\n    {\n      Platform &platform = platformPair.second;\n      if(!platform.equipments.size())\n        logWarning<<\"station \"<<platform.markerName<<\" without laser station\"<<Log::endl;\n      std::stable_sort(platform.equipments.begin(), platform.equipments.end(), [](auto &p1, auto &p2) {return p1->timeStart < p2->timeStart;});\n      for(UInt i=1; i<platform.equipments.size(); i++)\n        if(platform.equipments.at(i)->timeStart < platform.equipments.at(i-1)->timeEnd)\n          logWarning<<\"overlapping time intervals between \"<<platform.equipments.at(i-1)->name<<\" (\"<<platform.equipments.at(i-1)->serial<<\") \"\n                    <<\"ENU(\"<<platform.equipments.at(i-1)->position.x()<<\", \"<<platform.equipments.at(i-1)->position.y()<<\", \"<<platform.equipments.at(i-1)->position.z()<<\") ends \"<<platform.equipments.at(i-1)->timeEnd.dateTimeStr()\n                    <<\" and \"<<platform.equipments.at(i)->name<<\" (\"<<platform.equipments.at(i)->serial<<\") \"\n                    <<\"ENU(\"<<platform.equipments.at(i)->position.x()<<\", \"<<platform.equipments.at(i)->position.y()<<\", \"<<platform.equipments.at(i)->position.z()<<\") starts \"<<platform.equipments.at(i)->timeStart.dateTimeStr()<<Log::endl;\n      varList.setVariable(variableLoopStation, platform.markerName);\n      writeFilePlatform(fileNamePlatform(varList), platform);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/slrComModel2RangeBiasStationSatellite.cpp",
    "content": "/***********************************************/\n/**\n* @file slrComModel2RangeBiasStationSatellite.cpp\n*\n* @brief read CoM model.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-12-27\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts the tables of CoM corrections of José Rodríguez\n(\\url{https://icts-yebes.oan.es/slr/com_models/models/}) into station/satellite\nspecific \\configFile{outputfileRangeBias}{instrument}. Only the deviations to the default value in\n\\configFile{inputfileSatelliteInfo}{platform} are written. This program must be called for every\nprovided satellite. The range bias values can be used in\n\\configClass{parametrization:rangeBiasStationSatelliteApriori}{slrParametrizationType:rangeBiasStationSatelliteApriori}\nin \\program {SlrProcessing}.\n\nReference:\nRodriguez J., Otsubo T., Appleby G. Upgraded Modelling for the\nDetermination of Centre of Mass Corrections of Geodetic SLR\nSatellites: Impact on Key Parameters of the Terrestrial Reference\nFrame. Journal of Geodesy, 2019. doi: 10.1007/s00190-019-01315-0\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief read CoM model.\n* @ingroup programsConversionGroup */\nclass SlrComModel2RangeBiasStationSatellite\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SlrComModel2RangeBiasStationSatellite, SINGLEPROCESS, \"read CoM model\", Conversion, Slr)\n\n/***********************************************/\n\nvoid SlrComModel2RangeBiasStationSatellite::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 fileNameOut;\n    FileName                 fileNamePlatform, fileNameIn;\n    std::string              variableLoopStation;\n    std::vector<std::string> stationNames;\n\n    readConfig(config, \"outputfileRangeBias\",    fileNameOut,         Config::MUSTSET, \"rangeBias.{station}.{satellite}.txt\",  \"MISCVALUE, variable {station} available\");\n    readConfig(config, \"inputfileSatelliteInfo\", fileNamePlatform,    Config::MUSTSET, \"{groopsDataDir}/slr/satellites/satelliteInfo/satelliteInfo.{satellite}.xml\", \"\");\n    readConfig(config, \"inputfile\",              fileNameIn,          Config::MUSTSET, \"com/com_<aji|et1|la2|las|lg1|lg2|str>.dat\", \"from Rodriguez model\");\n    readConfig(config, \"variableLoopStation\",    variableLoopStation, Config::DEFAULT,  \"station\", \"variable name for station loop\");\n    readConfig(config, \"stationName\",            stationNames,        Config::OPTIONAL, \"\",        \"convert only these stations\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read platform file <\"<<fileNamePlatform<<\">\"<<Log::endl;\n    Platform platform;\n    readFilePlatform(fileNamePlatform, platform);\n\n    // read data\n    // ---------\n    std::map<std::string, MiscValueArc> arcs;     // per station\n    std::map<std::string, Time>         timesEnd; // per station\n\n    logStatus<<\"read file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFile file(fileNameIn);\n    std::string line;\n    while(std::getline(file, line))\n    {\n      if(line.empty() || String::startsWith(line, \"*\"))\n        continue;\n\n      std::string station;\n      UInt        dayStart, monthStart, yearStart;\n      UInt        dayEnd, monthEnd, yearEnd;\n      Double      wavelength, range;\n      std::stringstream ss(line);\n      ss>>station>>dayStart>>monthStart>>yearStart>>dayEnd>>monthEnd>>yearEnd>>wavelength>>range;\n\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), station) == stationNames.end())\n        continue;\n\n      const Time timeStart = date2time(yearStart, monthStart, dayStart);\n      const Time timeEnd   = date2time(yearEnd,   monthEnd,   dayEnd);\n\n      auto reflector = platform.findEquipment<PlatformLaserRetroReflector>(timeStart);\n      if(!reflector)\n       reflector = platform.findEquipment<PlatformLaserRetroReflector>(timeEnd);\n      if(!reflector)\n      {\n        logWarning<<\"reflector not found in [\"<<timeStart.dateStr()<<\", \"<<timeEnd.dateStr()<<\"] -> skipping\"<<Log::endl;\n        continue;\n      }\n\n      MiscValueEpoch epoch;\n      epoch.time  = timeStart;\n      epoch.value = 1e-3 * range - reflector->range(0, 0); // mm -> m\n      arcs[station].push_back(epoch);\n      timesEnd[station] = timeEnd;\n    }\n\n    // write results\n    // -------------\n    VariableList varList;\n    varList.setVariable(variableLoopStation, \"****\");\n    logStatus<<\"write range biases to file <\"<<fileNameOut(varList)<<\">\"<<Log::endl;\n    for(auto &stationArcs : arcs)\n    {\n      varList.setVariable(variableLoopStation, stationArcs.first);\n      if(stationArcs.second.size() && std::any_of(stationArcs.second.begin(), stationArcs.second.end(), [&](const auto &e){return (std::fabs(e.value) > 0.0001);}))\n      {\n        if(timesEnd[stationArcs.first] < date2time(2050, 1, 1))\n        {\n          MiscValueEpoch epoch;\n          epoch.time  = timesEnd[stationArcs.first];\n          epoch.value = 0;\n          stationArcs.second.push_back(epoch);\n        }\n        InstrumentFile::write(fileNameOut(varList), stationArcs.second);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/slr/slrSinexDataHandling2Files.cpp",
    "content": "/***********************************************/\n/**\n* @file slrSinexDataHandling2Files.cpp\n*\n* @brief Convert SLR SINEX data handling file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-12-15\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts SLR range and time bias from \\verb|ILRS_Data_Handling_File_xxxx.xx.xx.snx| provided at\n\\url{https://cddis.nasa.gov/archive/slr/products/resource/}. The range and time bias values can be used in\n\\configClass{parametrization:rangeBiasXxxApriori}{slrParametrizationType:rangeBiasStationApriori}\nin \\program {SlrProcessing}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileStringTable.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert SLR SINEX data handling file.\n* @ingroup programsConversionGroup */\nclass SlrSinexDataHandling2Files\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SlrSinexDataHandling2Files, SINGLEPROCESS, \"Convert SLR SINEX data handling file\", Conversion, Slr)\n\n/***********************************************/\n\nvoid SlrSinexDataHandling2Files::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 fileNameRangeBiasStation, fileNameRangeBiasSatellite, fileNameTimeBias;\n    FileName                 fileNameSinex, fileNameSatelliteId;\n    std::string              variableLoopStation, variableLoopSatellite;\n    std::vector<std::string> stationNames;\n\n    readConfig(config, \"outputfileRangeBiasStation\",          fileNameRangeBiasStation,   Config::OPTIONAL, \"rangeBias.{station}.txt\",             \"MISCVALUE [m]\");\n    readConfig(config, \"outputfileRangeBiasStationSatellite\", fileNameRangeBiasSatellite, Config::OPTIONAL, \"rangeBias.{station}.{satellite}.txt\", \"MISCVALUE [m]\");\n    readConfig(config, \"outputfileTimeBias\",                  fileNameTimeBias,           Config::OPTIONAL, \"timeBias.{station}.txt\",              \"MISCVALUES(bias [s], drift [s/d])\");\n    readConfig(config, \"variableLoopStation\",                 variableLoopStation,        Config::DEFAULT,  \"station\",                             \"variable name for station loop\");\n    readConfig(config, \"variableLoopSatellite\",               variableLoopSatellite,      Config::DEFAULT,  \"satellite\",                           \"variable name for satellite loop\");\n    readConfig(config, \"inputfileSinex\",                      fileNameSinex,              Config::MUSTSET,  \"ILRS_Data_Handling_File.snx\",         \"SINEX file (.snx)\");\n    readConfig(config, \"inputfileSatelliteId\",                fileNameSatelliteId,        Config::OPTIONAL, \"\",                                    \"table SP3 and satellite name\");\n    readConfig(config, \"stationName\",                         stationNames,               Config::OPTIONAL, \"\",                                    \"convert only these stations\");\n    if(isCreateSchema(config)) return;\n\n    // Read the mapping from SP3 ID to ILRS satellite name\n    std::vector<std::vector<std::string>> tableSatelliteId;\n    if(!fileNameSatelliteId.empty())\n    {\n      logStatus<<\"read satellite ID mapping file <\"<<fileNameSatelliteId<<\">\"<<Log::endl;\n      readFileStringTable(fileNameSatelliteId, tableSatelliteId);\n    }\n\n    std::map<std::string, MiscValueArc>                         rangeBiasesStation;\n    std::map<std::string, std::map<std::string, MiscValueArc>>  rangeBiasesStationSatellite;\n    std::map<std::string, MiscValuesArc>                        timeBiases;\n\n    logStatus<<\"read SINEX file <\"<<fileNameSinex<<\">\"<<Log::endl;\n    Sinex sinex;\n    readFileSinex(fileNameSinex, sinex);\n\n    // MODEL/RANGE_BIAS\n    // ----------------------\n    for(std::string &line : sinex.findBlock(\"MODEL/RANGE_BIAS\")->lines)\n    {\n      // *         1         2         3         4         5         6         7         8\n      // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n      // *CODE PT SOLN T START_DATE__ END_DATE____ M __E-VALUE___ STD_DEV _E-RATE__ UNIT   CMNTS\n      line.resize(80, ' ');\n      // 4-char station code\n      std::string station = String::lowerCase(String::trim(line.substr(1, 4)));\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), station) == stationNames.end())\n        continue;\n      if(line.at(42) != 'R') // range bias\n        continue;\n\n      Time timeStart = Sinex::str2time(line, 16, FALSE);\n      Time timeEnd   = Sinex::str2time(line, 29, TRUE);\n      MiscValueEpoch epoch;\n      epoch.time  = timeStart;\n      epoch.value = 1e-3 * String::toDouble(line.substr(44, 12)); // mm -> m\n      // satellite SP3c ID without the leading letter \"L\"\n      std::string satId = String::trim(line.substr(6, 2));\n      if(satId == \"--\")\n        satId = \"\";\n\n      if(satId.empty()) // station specific range bias\n      {\n        if(rangeBiasesStation[station].size() && (rangeBiasesStation[station].back().time >= timeStart-seconds2time(1)))\n          rangeBiasesStation[station].remove(rangeBiasesStation[station].size()-1);\n        rangeBiasesStation[station].push_back(epoch);\n        // zero bias after end of interval\n        epoch.time  = timeEnd;\n        epoch.value = 0.;\n        rangeBiasesStation[station].push_back(epoch);\n      }\n      else\n      {\n        // station-satellite specific range bias\n        auto iter = std::find_if(tableSatelliteId.begin(), tableSatelliteId.end(), [&](auto &t){return (t.size()>1) && ((t.front() == satId) || (t.front() == \"L\"+satId));});\n        if(iter != tableSatelliteId.end())\n          satId = iter->at(1); // replace SP3 ID by satellite name from table\n\n        if(rangeBiasesStationSatellite[station][satId].size() && (rangeBiasesStationSatellite[station][satId].back().time >= timeStart-seconds2time(1)))\n          rangeBiasesStationSatellite[station][satId].remove(rangeBiasesStationSatellite[station][satId].size()-1);\n        rangeBiasesStationSatellite[station][satId].push_back(epoch);\n        // zero bias after end of interval\n        epoch.time  = timeEnd;\n        epoch.value = 0.;\n        rangeBiasesStationSatellite[station][satId].push_back(epoch);\n      }\n    }\n\n    // MODEL/TIME_BIAS\n    // ---------------\n    for(std::string &line : sinex.findBlock(\"MODEL/TIME_BIAS\")->lines)\n    {\n      // *         1         2         3         4         5         6         7         8\n      // *12345678901234567890123456789012345678901234567890123456789012345678901234567890\n      // *CODE PT SOLN T START_DATE__ END_DATE____ M __E-VALUE___ STD_DEV _E-RATE__ UNIT   CMNTS\n      line.resize(80, ' ');\n      std::string station = String::lowerCase(String::trim(line.substr(1, 4)));\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), station) == stationNames.end())\n        continue;\n      if(line.at(42) != 'T')  // time bias\n        continue;\n      if((line.substr(6, 2) != \"  \") && (line.substr(6, 2) != \"--\"))\n      {\n        logWarning<<\"station-satellite specific time bias ignored in line '\"<<line<<\"'\"<<Log::endl;\n        continue;\n      }\n\n      Time timeStart = Sinex::str2time(line, 16, FALSE);\n      Time timeEnd   = Sinex::str2time(line, 29, TRUE);\n      if(timeBiases[station].size() && (timeBiases[station].back().time >= timeStart-seconds2time(1)))\n        timeBiases[station].remove(timeBiases[station].size()-1);\n\n      Double unit = 1.;\n      if(String::trim(line.substr(75, 4)) == \"ms\")\n        unit = 1e-3;\n      else if(String::trim(line.substr(75, 4)) == \"us\")\n        unit = 1e-6;\n      else\n      {\n        logWarning<<\"Unknown time unit (ms or us) '\"<<line<<\"'\"<<Log::endl;\n        continue;\n      }\n\n      MiscValuesEpoch epoch(2);\n      epoch.time  = timeStart;\n      epoch.values(0) = unit * String::toDouble(line.substr(44, 12)); // bias  ms/us -> s\n      epoch.values(1) = unit * String::toDouble(line.substr(65, 9));  // drift ms/us -> s/d\n      epoch.values(0) -= epoch.values(1) * 0.5 * (timeEnd-timeStart).mjd(); // move bias from mid to start of interval\n      timeBiases[station].push_back(epoch);\n      // zero bias after end of interval\n      epoch.time  = timeEnd;\n      epoch.values.setNull();\n      timeBiases[station].push_back(epoch);\n    }\n\n    // write results\n    // -------------\n    if(!fileNameRangeBiasStation.empty())\n    {\n      VariableList varList;\n      varList.setVariable(variableLoopStation, \"****\");\n      logStatus<<\"write station range biases to file <\"<<fileNameRangeBiasStation(varList)<<\">\"<<Log::endl;\n      for(auto &rangeBiasPair : rangeBiasesStation)\n        if(rangeBiasPair.second.size())\n        {\n          varList.setVariable(variableLoopStation, rangeBiasPair.first);\n          InstrumentFile::write(fileNameRangeBiasStation(varList), rangeBiasPair.second);\n        }\n    }\n\n    if(!fileNameRangeBiasSatellite.empty())\n    {\n      VariableList varList;\n      varList.setVariable(variableLoopStation,   \"****\");\n      varList.setVariable(variableLoopSatellite, \"****\");\n      logStatus<<\"write station-satellite range biases to file <\"<<fileNameRangeBiasSatellite(varList)<<\">\"<<Log::endl;\n      for(auto &pairStation : rangeBiasesStationSatellite)\n        for(auto &pairSatellite : pairStation.second)\n          if(pairSatellite.second.size())\n          {\n            varList.setVariable(variableLoopStation,   pairStation.first);\n            varList.setVariable(variableLoopSatellite, pairSatellite.first);\n            InstrumentFile::write(fileNameRangeBiasSatellite(varList), pairSatellite.second);\n          }\n    }\n\n    if(!fileNameTimeBias.empty())\n    {\n      VariableList varList;\n      varList.setVariable(variableLoopStation, \"****\");\n      logStatus<<\"write time biases to file <\"<<fileNameTimeBias(varList)<<\">\"<<Log::endl;\n      for(auto &timeBiasPair : timeBiases)\n        if(timeBiasPair.second.size())\n        {\n          varList.setVariable(variableLoopStation, timeBiasPair.first);\n          InstrumentFile::write(fileNameTimeBias(varList), timeBiasPair.second);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/sp3Format2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file sp3Format2Orbit.cpp\n*\n* @brief Read orbits from SP3 format.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2019-10-25\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead orbits from \\href{https://files.igs.org/pub/data/format/sp3d.pdf}{SP3 format}\nand write an \\file{instrument file (ORBIT)}{instrument}.\nThe additional \\config{outputfileClock} is an \\file{instrument file (MISCVALUE)}{instrument}\nand \\config{outputfileCovariance} is an \\file{instrument file (COVARIANCE3D)}{instrument}.\n\nWith \\config{satelliteIdentifier} a single satellite can be selected if the \\config{inputfile}s\ncontain more than one satellites. If \\config{satelliteIdentifier} is empty the first satellite is taken.\nAll satellites can be selected with \\config{satelliteIdentifier}=\\verb|<all>|.\nIn this case the identifier is appended to each output file.\n\nIf \\configClass{earthRotation}{earthRotationType} is provided the data are transformed\nfrom terrestrial (TRF) to celestial reference frame (CRF).\nSince SP3 orbits often use the center of Earth as a reference, a correction from center\nof Earth to center of mass can be applied to the orbits by providing \\configClass{gravityfield}{gravityfieldType} (e.g. ocean tides).\n\nSee also \\program{Orbit2Sp3Format}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read IGS orbits from SP3 format.\n* @ingroup programsConversionGroup */\nclass Sp3Format2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sp3Format2Orbit, SINGLEPROCESS, \"read orbits from SP3 format\", Conversion, Orbit, Covariance, Instrument)\nGROOPS_RENAMED_PROGRAM(Sp3file2Orbit, Sp3Format2Orbit, date2time(2020, 8, 4))\nGROOPS_RENAMED_PROGRAM(Igs2Orbit,     Sp3Format2Orbit, date2time(2020, 8, 4))\n\n/***********************************************/\n\nvoid Sp3Format2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOrbit, fileNameClock, fileNameCov;\n    std::string           identifier;\n    EarthRotationPtr      earthRotation;\n    GravityfieldPtr       gravityfield;\n    std::vector<FileName> fileNamesIn;\n\n    readConfig(config, \"outputfileOrbit\",      fileNameOrbit, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileClock\",      fileNameClock, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileCovariance\", fileNameCov,   Config::OPTIONAL, \"\", \"3x3 epoch covariance\");\n    readConfig(config, \"satelliteIdentifier\",  identifier,    Config::OPTIONAL, \"\", \"e.g. L09 for GRACE A, empty: take first satellite, <all>: identifier is appended to each file\");\n    readConfig(config, \"earthRotation\",        earthRotation, Config::OPTIONAL, \"file\", \"rotation from TRF to CRF\");\n    readConfig(config, \"gravityfield\",         gravityfield,  Config::DEFAULT,  R\"([{\"tides\": {\"tides\": {\"doodsonHarmonicTide\": {\"minDegree\":1, \"maxDegree\":1}}}}])\", \"degree 1 fluid mantle for CM2CE correction (SP3 orbits should be in center of Earth)\");\n    readConfig(config, \"inputfile\",            fileNamesIn,   Config::MUSTSET,  \"\", \"orbits in SP3 format\");\n    if(isCreateSchema(config)) return;\n\n    // ==============================\n\n    std::map<std::string, OrbitArc>        orbits;\n    std::map<std::string, MiscValueArc>    clocks;\n    std::map<std::string, Covariance3dArc> covs;\n    for(FileName &filenameIn : fileNamesIn)\n    {\n      try\n      {\n        logStatus<<\"read file <\"<<filenameIn<<\">\"<<Log::endl;\n        InFile file(filenameIn);\n        std::string line;\n        enum TimeSystem {GPS, UTC, TAI};\n        TimeSystem timeSystem = GPS;\n        Time        time;\n        std::string satId;\n        Rotary3d    rotation;\n        Vector3d    omega;\n        Vector3d    cm2ceCorrection;\n        while(std::getline(file, line))\n        {\n          // Header\n          // ------\n          if(String::startsWith(line, \"#\") ||   // first 2 lines\n             String::startsWith(line, \"/*\") ||  // comment lines\n             String::startsWith(line, \"%f\") ||  // floating point base base numbers\n             String::startsWith(line, \"%i\"))    // additional parameters\n            continue;\n\n          if(String::startsWith(line, \"+\"))     // satellite list and orbit accuracy lines\n          {\n            if(identifier.empty() && String::toInt(line.substr(3, 3)) > 0)\n              identifier = line.substr(9, 3);\n            continue;\n          }\n\n          if(String::startsWith(line, \"%c\"))    // file type and time system definition lines\n          {\n            if(line.substr(9, 3) == \"GPS\") timeSystem = GPS;\n            else if(line.substr(9, 3) == \"UTC\") timeSystem = UTC;\n            else if(line.substr(9, 3) == \"TAI\") timeSystem = TAI;\n            else logWarning<<\"Unknown time system (\"<<line.substr(9, 3)<<\"), assuming GPS time\"<<Log::endl;\n            std::getline(file, line); // skip second %c line\n            continue;\n          }\n\n          // Epoch\n          // -----\n          if(String::startsWith(line, \"* \"))\n          {\n            UInt   year  = String::toInt(line.substr(3, 4));\n            UInt   month = String::toInt(line.substr(8, 2));\n            UInt   day   = String::toInt(line.substr(11, 2));\n            UInt   hour  = String::toInt(line.substr(14, 2));\n            UInt   min   = String::toInt(line.substr(17, 2));\n            Double sec   = String::toDouble(line.substr(20, 11));\n            time = date2time(year, month, day, hour, min, sec);\n            if(timeSystem == UTC)\n              time = timeUTC2GPS(time);\n            else if(timeSystem == TAI)\n              time -= seconds2time(DELTA_TAI_GPS);\n\n            const SphericalHarmonics harmonics = gravityfield->sphericalHarmonics(time, 1, 1);\n            const Vector coeff = harmonics.x(); // [c00, c10, c11, s11]\n            cm2ceCorrection = std::sqrt(3.) * harmonics.R() * Vector3d(coeff(2), coeff(3), coeff(1));\n\n            if(earthRotation)\n            {\n              rotation = inverse(earthRotation->rotaryMatrix(time));\n              omega    = earthRotation->rotaryAxis(time);\n            }\n          }\n\n          // Position\n          // --------\n          if(String::startsWith(line, \"P\"))\n          {\n            satId = line.substr(1,3);\n            Double x = String::toDouble(line.substr(4, 14));\n            Double y = String::toDouble(line.substr(18, 14));\n            Double z = String::toDouble(line.substr(32, 14));\n            Double c = String::toDouble(line.substr(46, 14));\n            const Vector3d pos = 1e3*Vector3d(x,y,z); // km -> m\n            if(pos.r())\n            {\n              OrbitEpoch epoch;\n              epoch.time     = time;\n              epoch.position = rotation.rotate(1e3*Vector3d(x,y,z)-cm2ceCorrection); // km -> m\n              orbits[satId].push_back(epoch);\n            }\n            if(c < 999999)\n            {\n              MiscValueEpoch epoch;\n              epoch.time  = time;\n              epoch.value = 1e-6*c; // microsecond -> second\n              clocks[satId].push_back(epoch);\n            }\n          }\n\n          // Position covariance\n          // -------------------\n          if(String::startsWith(line, \"EP\"))\n          {\n            Double xx = String::toDouble(line.substr(4, 4));\n            Double yy = String::toDouble(line.substr(9, 4));\n            Double zz = String::toDouble(line.substr(14, 4));\n            Double xy = String::toDouble(line.substr(27, 8));\n            Double xz = String::toDouble(line.substr(36, 8));\n            Double yz = String::toDouble(line.substr(54, 8));\n            Covariance3dEpoch epochCov;\n            epochCov.time = time;\n            // mm -> m, correlation [1e-7] -> covariance\n            epochCov.setData(Vector({std::pow(1e-3*xx,2), std::pow(1e-3*yy,2), std::pow(1e-3*zz,2), 1e-13*xy*xx*yy, 1e-13*xz*xx*zz, 1e-13*yz*yy*zz}));\n            epochCov.covariance = rotation.rotate(epochCov.covariance);\n            covs[satId].push_back(epochCov);\n          }\n\n          // Velocity\n          // --------\n          if(String::startsWith(line, \"V\"))\n          {\n            satId = line.substr(1,3);\n            Double x = String::toDouble(line.substr(4, 14));\n            Double y = String::toDouble(line.substr(18, 14));\n            Double z = String::toDouble(line.substr(32, 14));\n            const Vector3d vel = 0.1*Vector3d(x,y,z);  // dm/s -> m/s\n            if(vel.r())\n              orbits[satId].back().velocity = rotation.rotate(vel) + crossProduct(omega, orbits[satId].back().position);\n          }\n\n          // end of file\n          // -----------\n          if(String::startsWith(line, \"EOF\"))\n            break;\n        } // for(;;)\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<std::endl<<e.what()<<\" continue...\"<<Log::endl;\n        break;\n      }\n    } // for(inputFiles)\n\n    // ==============================\n\n    // write results\n    // -------------\n    if(identifier == \"<all>\")\n    {\n      if(!fileNameOrbit.empty())\n        for(auto &pair : orbits)\n          if(pair.second.size())\n          {\n            logStatus<<\"write orbit data to file <\"<<fileNameOrbit.appendBaseName(\".\"+pair.first)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameOrbit.appendBaseName(\".\"+pair.first), pair.second);\n          }\n      if(!fileNameClock.empty())\n        for(auto &pair : clocks)\n          if(pair.second.size())\n          {\n            logStatus<<\"write clock data to file <\"<<fileNameClock.appendBaseName(\".\"+pair.first)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameClock.appendBaseName(\".\"+pair.first), pair.second);\n          }\n      if(!fileNameCov.empty())\n        for(auto &pair : covs)\n          if(pair.second.size())\n          {\n            logStatus<<\"write covariance data to file <\"<<fileNameCov.appendBaseName(\".\"+pair.first)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameCov.appendBaseName(\".\"+pair.first), pair.second);\n          }\n    }\n    else\n    {\n      // single satellite\n      if(!orbits[identifier].size())\n        logWarning<<\"No data found for identifier='\"<<identifier<<\"'\"<<Log::endl;\n\n      if(!fileNameOrbit.empty() && orbits[identifier].size())\n      {\n        logStatus<<\"write orbit data to file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameOrbit, orbits[identifier]);\n        Arc::printStatistics(orbits[identifier]);\n      }\n      if(!fileNameClock.empty() && clocks[identifier].size())\n      {\n        logStatus<<\"write clock data to file <\"<<fileNameClock<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameClock, clocks[identifier]);\n      }\n      if(!fileNameCov.empty() && covs[identifier].size())\n      {\n        logStatus<<\"write covariance data to file <\"<<fileNameCov<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameCov, covs[identifier]);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/starCamera2Orbex.cpp",
    "content": "/***********************************************/\n/**\n* @file starCamera2Orbex.cpp\n*\n* @brief Converts satellite attitude from StarCamera to ORBEX format.\n*\n* @author Andre Hauschild\n* @date 2024-10-10\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts satellite attitude from \\file{instrument file (STARCAMERA)}{instrument} to\n\\href{http://acc.igs.org/misc/ORBEX009.pdf}{ORBEX file format} (quaternions).\n\nIf \\configClass{earthRotation}{earthRotationType} is provided, the output file contains quaternions\nfor rotation from TRF to satellite body frame (IGS/ORBEX convention),\notherwise the rotation is from CRF to satellite body frame.\n\nSee also \\program{GnssOrbex2StarCamera}, \\program{SimulateStarCameraGnss}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts satellite attitude from StarCamera to ORBEX format.\n* @ingroup programsConversionGroup */\nclass StarCamera2Orbex\n{\npublic:\n  class Satellite\n  {\n  public:\n    FileName    fileNameAttitude;\n    std::string identifier, description;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(StarCamera2Orbex, SINGLEPROCESS, \"Converts satellite attitude from StarCamera to ORBEX format.\", Conversion, Instrument)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, StarCamera2Orbex::Satellite &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileStarCamera\", var.fileNameAttitude, Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"identifier\",          var.identifier,       Config::MUSTSET,  \"\", \"string identifier (e.g. GNSS PRN: G01)\");\n  readConfig(config, \"description\",         var.description,      Config::OPTIONAL, \"\", \"e.g. BLOCK IIR-B, GRACE\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid StarCamera2Orbex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                 fileNameOrbex;\n    std::vector<Satellite>   satellites;\n    EarthRotationPtr         earthRotation;\n    TimeSeriesPtr            timeSeriesPtr;\n    UInt                     interpolationDegree;\n    std::string              coordSystem, contact, createdBy, description, inputData;\n    std::vector<std::string> comments;\n\n    readConfig(config, \"outputfileOrbex\",     fileNameOrbex,       Config::MUSTSET,  \"\",      \"ORBEX file\");\n    readConfig(config, \"satellite\",           satellites,          Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"earthRotation\",       earthRotation,       Config::OPTIONAL, \"file\",  \"rotate data into Earth-fixed frame\");\n    readConfig(config, \"timeSeries\",          timeSeriesPtr,       Config::DEFAULT,  \"\",      \"resample to these epochs (otherwise input file epochs are used)\");\n    readConfig(config, \"interpolationDegree\", interpolationDegree, Config::MUSTSET,  \"7\",     \"for attitude and Earth rotation interpolation\");\n    readConfig(config, \"description\",         description,         Config::MUSTSET,  \"\",      \"description of file contents\");\n    readConfig(config, \"createdBy\",           createdBy,           Config::MUSTSET,  \"\",      \"name of agency\");\n    readConfig(config, \"inputData\",           inputData,           Config::MUSTSET,  \"p\",     \"description of input data (see ORBEX description)\");\n    readConfig(config, \"contact\",             contact,             Config::MUSTSET,  \"\",      \"email address\");\n    readConfig(config, \"referenceFrame\",      coordSystem,         Config::MUSTSET,  \"IGS20\", \"reference frame used in file\");\n    readConfig(config, \"comment\",             comments,            Config::OPTIONAL, \"\",      \"\");\n    if(isCreateSchema(config)) return;\n\n    class Record\n    {\n    public:\n      std::string identifier;\n      Vector      quaternion;\n\n      Record(const std::string &identifier, const_MatrixSliceRef quaternion) : identifier(identifier), quaternion(quaternion) {}\n    };\n\n    std::map<Time, std::vector<Record>> times2Records;\n    std::vector<Time> times = timeSeriesPtr->times();\n    for(auto &satellite : satellites)\n    {\n      satellite.identifier.resize(6, ' '); // max. 6 characters\n\n      try\n      {\n        StarCameraArc arc = InstrumentFile::read(satellite.fileNameAttitude);\n        for(UInt idEpoch=0; idEpoch<arc.size(); idEpoch++)\n          arc.at(idEpoch).rotary = inverse(arc.at(idEpoch).rotary);\n        if(earthRotation)\n          for(UInt idEpoch=0; idEpoch<arc.size(); idEpoch++)\n          arc.at(idEpoch).rotary *= inverse(earthRotation->rotaryMatrix(arc.at(idEpoch).time));\n        Matrix quaternion = arc.matrix().column(1, 4);\n\n        // (optionally) resample attitude\n        std::vector<Time> satTimes = arc.times();\n        if(times.size())\n        {\n          Polynomial polynomial(satTimes, interpolationDegree);\n          quaternion = polynomial.interpolate(times, quaternion);\n          satTimes = times;\n        }\n\n        for(UInt idEpoch=0; idEpoch<quaternion.rows(); idEpoch++)\n          times2Records[satTimes.at(idEpoch)].push_back(Record(satellite.identifier, (quaternion.row(idEpoch)/norm(quaternion.row(idEpoch))).trans())); // normalize quaternions\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<< Log::endl;\n        satellite.identifier = \"\";\n        continue;\n      }\n    }\n\n    if(times2Records.empty())\n      throw(Exception(\"No star camera input data found.\"));\n\n    times.clear();\n    for(const auto &epoch : times2Records)\n      times.push_back(epoch.first);\n\n    logStatus<<\"writing ORBEX file to <\"<<fileNameOrbex<<\">\"<<Log::endl;\n    OutFile outfile(fileNameOrbex);\n    outfile<<\"%=ORBEX  0.09\"<<std::endl;\n    outfile<<\"%%\"<<std::endl;\n    outfile<<\"*------------------------------------------------------------------------------------------------------\"<<std::endl;\n    outfile<<\"+FILE/DESCRIPTION\"<<std::endl;\n    outfile<<\" DESCRIPTION         \"<<description<<std::endl;\n    outfile<<\" CREATED_BY          \"<<createdBy<<std::endl;\n    outfile<<\" CREATION_DATE       \"<<System::now()%\"%y %m %d %H %M %S\"s<<std::endl;\n    outfile<<\" INPUT_DATA          \"<<inputData<<std::endl;\n    outfile<<\" CONTACT             \"<<contact<<std::endl;\n    outfile<<\" TIME_SYSTEM         GPS\"<<std::endl;\n    outfile<<\" START_TIME          \"<<times.front()%\"%y %m %d %H %M %012.9S000\"s<<std::endl; // ATTENTION: \"fake\" 15.12 precision due to max Time precision\n    outfile<<\" END_TIME            \"<<times.back() %\"%y %m %d %H %M %012.9S000\"s<<std::endl; // ATTENTION: \"fake\" 15.12 precision due to max Time precision\n    outfile<<\" EPOCH_INTERVAL      \"<<medianSampling(times).seconds()%\"%9.3f\"s<<std::endl;\n    outfile<<\" COORD_SYSTEM        \"<<coordSystem<<std::endl;\n    outfile<<\" FRAME_TYPE          \"<<(earthRotation ? \"ECEF\" : \"ECI\")<<std::endl;\n    outfile<<\" LIST_OF_REC_TYPES   ATT\"<<std::endl;\n    outfile<<\"-FILE/DESCRIPTION\"<<std::endl;\n    if(comments.size())\n    {\n      outfile<<\"*------------------------------------------------------------------------------------------------------\"<<std::endl;\n      for(auto &comment : comments)\n        outfile<<\"* \"<<comment<<std::endl;\n    }\n    outfile<<\"*------------------------------------------------------------------------------------------------------\"<<std::endl;\n    outfile<<\"+SATELLITE/ID_AND_DESCRIPTION\"<<std::endl;\n    for(const auto &satellite : satellites)\n      if(!satellite.identifier.empty())\n        outfile<<\" \"<<satellite.identifier<<satellite.description<<std::endl;\n    outfile<<\"-SATELLITE/ID_AND_DESCRIPTION\"<<std::endl;\n    outfile<<\"*------------------------------------------------------------------------------------------------------\"<<std::endl;\n    outfile<<\"+EPHEMERIS/DATA\"<<std::endl;\n    outfile<<\"*ATT RECORDS: TRANSFORMATION FROM \"<<(earthRotation ? \"TERRESTRIAL\" : \"CELESTIAL\")<<\" FRAME COORDINATES (T) TO SAT. BODY FRAME ONES (B) SUCH AS\"<<std::endl;\n    outfile<<\"*                                 (0,B) = q.(0,T).trans(q)\"<<std::endl;\n    outfile<<\"*REC ID_              N ___q0_(scalar)_____ ____q1__x__________ ____q2__y__________ ____q3__z__________\"<<std::endl;\n    for(const auto &epoch : times2Records)\n    {\n      outfile<<epoch.first%\"## %y %m %d %H %M %012.9S000 \"s<<epoch.second.size()%\"%3i\"s<<std::endl; // ATTENTION: \"fake\" 15.12 precision due to max Time precision\n      for(const auto &record : epoch.second)\n      {\n        outfile<<\" ATT \"<<record.identifier<<std::string(11, ' ')<<record.quaternion.size();\n        for(UInt i=0; i<record.quaternion.size(); i++)\n          outfile<<record.quaternion(i)%\" %19.16f\"s;\n        outfile<<std::endl;\n      }\n    }\n    outfile<<\"-EPHEMERIS/DATA\"<<std::endl;\n    outfile<<\"*------------------------------------------------------------------------------------------------------\"<<std::endl;\n    outfile<<\"%END_ORBEX\"<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/tle2Orbit.cpp",
    "content": "/***********************************************/\n/**\n* @file tle2Orbit.cpp\n*\n* @brief Orbit from Two Line Elements (TLE/3LE).\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-04-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the \\configFile{outputfileOrbit}{instrument}\nfrom two-line elements (TLE/3LE)\nas can be found at e.g. \\url{http://celestrak.org/NORAD/elements/}.\nThe first satellite in the input file that matches the wildcard of \\config{satelliteName} is used.\nIf more records with exactly the same name are found, the one with the closest reference epoch\nis used for each point in the \\configClass{timeSeries}{timeSeriesType}.\n\nThe program uses the Simplified General Perturbation (SGP) model. More information can\nbe found in the Revisiting Spacetrack Report 3 by Vallado et al. 2006.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"external/sgp4/SGP4.h\"\n#include \"base/string.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Orbit from Two Line Elements (TLE/3LE).\n* @ingroup programsGroup */\nclass Tle2Orbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Tle2Orbit, SINGLEPROCESS, \"orbit from Two Line Elements (TLE/3LE)\", Conversion, Instrument)\n\n/***********************************************/\n\nvoid Tle2Orbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         fileNameOrbit, fileNameTLE;\n    std::string      wildcardName;\n    TimeSeriesPtr    timeSeries;\n    EarthRotationPtr earthRotation;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOrbit, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"inputfileTLE\",    fileNameTLE,   Config::MUSTSET, \"\",  \"two line elements (TLE/3LE)\");\n    readConfig(config, \"satelliteName\",   wildcardName,  Config::DEFAULT, \"*\", \"first name of wildcard match is used\");\n    readConfig(config, \"timeSeries\",      timeSeries,    Config::MUSTSET, \"\",  \"output orbit at these times\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::MUSTSET, \"\",  \"rotation to CRF\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read TLE <\"<<fileNameTLE<<\">\"<<Log::endl;\n    std::vector<std::pair<Time, ElsetRec>> records;\n    InFile file(fileNameTLE);\n    const std::regex pattern = String::wildcard2regex(wildcardName);\n    std::string line, satName;\n    while(std::getline(file, line))\n    {\n      line = String::trim(line);\n      std::string line1, line2;\n      std::getline(file, line1);\n      std::getline(file, line2);\n      if((satName.empty() && std::regex_match(line, pattern)) || (line == satName))\n      {\n        satName = line;\n        if(!(line1.size() && line2.size() && (line1.at(0) == '1') && (line2.at(0) == '2')))\n          throw(Exception(\"parser error\"));\n\n        // first line\n        const Double xpdotp = 24*60/(2.*PI);\n        const Int yy  = String::toInt(line1.substr(18, 2)); // two digit year\n        Time satEpoch = date2time(yy + ((yy > 56) ? 1900 : 2000), 1, 1) + mjd2time(String::toDouble(line1.substr(20, 12))-1);\n        ElsetRec rec;\n        rec.ndot     = String::toDouble(line1.substr(33, 10))/ (xpdotp*1440.);\n        rec.nddot    = String::toDouble(line1.at(44)+\".\"s+line1.substr(45, 5)) * std::pow(10, String::toInt(line1.substr(50, 2)))/(xpdotp*1440.*1440.);\n        rec.bstar    = String::toDouble(line1.at(53)+\".\"s+line1.substr(54, 5)) * std::pow(10, String::toInt(line1.substr(59, 2)));\n        // second line\n        rec.inclo    = String::toDouble(line2.substr( 8, 8)) * DEG2RAD;\n        rec.nodeo    = String::toDouble(line2.substr(17, 8)) * DEG2RAD;\n        rec.ecco     = String::toDouble(\".\"s+line2.substr(26, 7));\n        rec.argpo    = String::toDouble(line2.substr(34, 8)) * DEG2RAD;\n        rec.mo       = String::toDouble(line2.substr(43, 8)) * DEG2RAD;\n        rec.no_kozai = String::toDouble(line2.substr(52, 11))/xpdotp;\n\n        rec.whichconst  = 2; // wgs72;\n        rec.jdsatepoch  = satEpoch.mjdInt() + 2400000.5;\n        rec.jdsatepochF = satEpoch.mjdMod();\n\n        records.push_back(std::make_pair(satEpoch, rec));\n        logInfo<<\" used satellite: '\"<<line<<\"' \"<<satEpoch.dateTimeStr()<<Log::endl;\n      }\n    }\n\n    if(!records.size())\n      throw(Exception(\"no satellite found\"));\n\n    logStatus<<\"integrate orbit\"<<Log::endl;\n    const std::vector<Time> times = timeSeries->times();\n    OrbitArc arc;\n\n    auto iterRecord = records.end();\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      auto iterRecordNew = std::min_element(records.begin(), records.end(),\n                                            [&](auto &r1, auto &r2) {return std::fabs((times.at(i)-r1.first).mjd()) < std::fabs((times.at(i)-r2.first).mjd());});\n      if(iterRecordNew != iterRecord)\n        sgp4init('a', iterRecordNew->second);\n      iterRecord = iterRecordNew;\n\n      Double p[3], v[3];\n      iterRecord->second.error = 0;\n      sgp4(iterRecord->second, (timeGPS2UTC(times.at(i))-iterRecord->first).seconds()/60., p, v);\n      if(iterRecord->second.error)\n        logWarning<<times.at(i).dateTimeStr()<<\" integration error\"<<Log::endl;\n\n      OrbitEpoch epoch;\n      epoch.time     = times.at(i);\n      epoch.position = Vector3d(1e3*p[0], 1e3*p[1], 1e3*p[2]);\n      epoch.velocity = Vector3d(1e3*v[0], 1e3*v[1], 1e3*v[2]);\n\n      // get actual precession and nutation\n      Double xp, yp, sp, deltaUT, LOD, X, Y, S;\n      earthRotation->earthOrientationParameter(times.at(i), xp, yp, sp, deltaUT, LOD, X, Y, S);\n      const Double   r2  = X*X + Y*Y;\n      const Double   E   = (r2 != 0.) ? std::atan2(Y, X) : 0.;\n      const Double   D   = std::atan(std::sqrt(r2/(1-r2)));\n\n      // rotate back precession\n      const Double JC     = timeGPS2JC(times.at(i));\n      const Double zetaA  = (2306.2181*JC + 0.30188*JC*JC + 0.017998*JC*JC*JC)* DEG2RAD/3600;\n      const Double zA     = (2306.2181*JC + 1.09468*JC*JC + 0.018203*JC*JC*JC)* DEG2RAD/3600;\n      const Rotary3d rot = rotaryZ(Angle(E)) * rotaryY(Angle(-D)) * rotaryZ(Angle(-E)) * rotaryZ(Angle(zetaA+zA));\n      epoch.position     = rot.rotate(epoch.position);\n      epoch.velocity     = rot.rotate(epoch.velocity);\n\n      arc.push_back(epoch);\n    });\n\n    logStatus<<\"write orbit <\"<<fileNameOrbit<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOrbit, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/viennaMappingFunctionGrid2File.cpp",
    "content": "/***********************************************/\n/**\n* @file viennaMappingFunctionGrid2File.cpp\n*\n* @brief Converts VMF grid time series to one file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-04-03\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the gridded time series of the Vienna Mapping Functions (VMF) into\nthe \\file{GROOPS file format}{griddedDataTimeSeries}.\n\nGridded VMF data is available at: \\url{https://vmf.geo.tuwien.ac.at/trop_products/GRID/}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/griddedData.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts VMF grid time series to one file.\n* @ingroup programsConversionGroup */\nclass ViennaMappingFunctionGrid2File\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ViennaMappingFunctionGrid2File, SINGLEPROCESS, \"converts VMF grid time series to one file.\", Conversion)\n\n/***********************************************/\n\nvoid ViennaMappingFunctionGrid2File::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameCoefficients;\n    std::vector<FileName> fileNamesIn;\n    TimeSeriesPtr         timeSeries;\n    Angle                 deltaL, deltaB;\n    Bool                  isCellRegistered;\n\n    readConfig(config, \"outputfileVmfCoefficients\", fileNameCoefficients, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"inputfile\",                 fileNamesIn,          Config::MUSTSET,  \"\",  \"files must be given for each point in time\");\n    readConfig(config, \"timeSeries\",                timeSeries,           Config::MUSTSET,  \"\",  \"times of input files\");\n    readConfig(config, \"deltaLambda\",               deltaL,               Config::DEFAULT,  \"1\", \"[deg] sampling in longitude\");\n    readConfig(config, \"deltaPhi\",                  deltaB,               Config::DEFAULT,  \"1\", \"[deg] sampling in latitude\");\n    readConfig(config, \"isCellRegistered\",          isCellRegistered,     Config::DEFAULT,  \"1\", \"grid points represent cells (VMF3), not grid corners (VMF1)\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    const std::vector<Time> times = timeSeries->times();\n    if(times.size()!=fileNamesIn.size())\n      throw(Exception(\"fileCount(\"+fileNamesIn.size()%\"%i) != timeCount(\"s+times.size()%\"%i)\"s));\n\n    std::vector<Angle> longitudes(static_cast<UInt>(std::round(2*PI/deltaL)));                           //!< Longitude (columns)\n    for(UInt i=0; i<longitudes.size(); i++)\n      longitudes.at(i) = Angle((i+(isCellRegistered ? 0.5 : 0))*deltaL);\n\n    std::vector<Angle> latitudes(static_cast<UInt>(std::round(PI/deltaB))+(isCellRegistered ? 0 : 1));  //!< Latitude (rows)\n    for(UInt i=0; i<latitudes.size(); i++)\n      latitudes.at(i) = Angle(PI/2-(i+(isCellRegistered ? 0.5 : 0))*deltaB);\n\n    GriddedDataRectangular gridRectangular;\n    gridRectangular.longitudes = longitudes;\n    gridRectangular.latitudes  = latitudes;\n    gridRectangular.heights.resize(latitudes.size(), 0.);\n    GriddedData grid(gridRectangular);\n\n    // ======================================================\n\n    logStatus<<\"read coefficients from files\"<<Log::endl;\n    std::vector<Matrix> data(times.size(), Matrix(grid.points.size(), 8));\n    Single::forEach(fileNamesIn.size(), [&](UInt i)\n    {\n      InFile file(fileNamesIn.at(i));\n\n      std::string line;\n      Double lon, lat;\n      for(UInt k=0; k<grid.points.size(); k++)\n      {\n        while(std::getline(file, line) && line.size() && (line.at(0) == '!' || line.at(0) == '#')); // skip header/comment lines\n        std::stringstream ss(line);\n        ss>>lat>>lon;\n        ss>>data.at(i)(k, 0)>>data.at(i)(k, 1)>>data.at(i)(k, 2)>>data.at(i)(k, 3); // ah, aw, zhd, zwd\n        ss>>data.at(i)(k, 4)>>data.at(i)(k, 5)>>data.at(i)(k, 6)>>data.at(i)(k, 7); // gradients\n      }\n      data.at(i).column(4, 4) *= 0.001; // gradients mm --> m\n    });\n\n    // ======================================================\n\n    if(!fileNameCoefficients.empty())\n    {\n      logStatus<<\"write VMF coefficients to <\"<<fileNameCoefficients<<\">\"<<Log::endl;\n      writeFileGriddedDataTimeSeries(fileNameCoefficients, 1, times, grid, data);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/conversion/viennaMappingFunctionStation2File.cpp",
    "content": "/***********************************************/\n/**\n* @file viennaMappingFunctionStation2File.cpp\n*\n* @brief Converts VMF station time series to one file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-01-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts Vienna Mapping Functions (VMF) station time series into \\file{GROOPS file format}{griddedDataTimeSeries}.\n\nStation-wise VMF data for GNSS is available at: \\url{https://vmf.geo.tuwien.ac.at/trop_products/GNSS/}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/griddedData.h\"\n#include \"base/string.h\"\n#include \"inputOutput/file.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"files/fileGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts VMF station time series to one file.\n* @ingroup programsConversionGroup */\nclass ViennaMappingFunctionStation2File\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ViennaMappingFunctionStation2File, SINGLEPROCESS, \"converts VMF station time series to one file.\", Conversion)\n\n/***********************************************/\n\nvoid ViennaMappingFunctionStation2File::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameVmfCoefficients;\n    FileName fileNameStationInfo, fileNameStation, fileNameIn;\n\n    readConfig(config, \"outputfileVmfCoefficients\", fileNameVmfCoefficients, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileStationInfo\",      fileNameStationInfo,     Config::MUSTSET,  \"{groopsDataDir}/gnss/receiverStation/stationInfo/igs/stationInfo.{station}.xml\", \"\");\n    readConfig(config, \"inputfileStation\",          fileNameStation,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileVmf\",              fileNameIn,              Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    VariableList fileNameVariableList;\n\n    logStatus<<\"read station list\"<<Log::endl;\n    GriddedData grid;\n    std::vector<std::string> stationNames;\n    {\n      Ellipsoid ellipsoid;\n      InFile file(fileNameStation);\n      std::string line;\n      while(std::getline(file, line))\n      {\n        std::string name;\n        Double      lat, lon, h;\n        std::stringstream ss(line);\n        ss>>name>>lat>>lon>>h;\n        stationNames.push_back(String::lowerCase(name));\n        grid.points.push_back(ellipsoid(Angle(lon*DEG2RAD), Angle(lat*DEG2RAD), h));\n      }\n\n      for(UInt idStation=0; idStation<stationNames.size(); idStation++)\n      {\n        try\n        {\n          // read position from stationInfo\n          Platform stationInfo;\n          fileNameVariableList.setVariable(\"station\", stationNames.at(idStation));\n          readFilePlatform(fileNameStationInfo(fileNameVariableList), stationInfo);\n\n          if((stationInfo.approxPosition-grid.points.at(idStation)).r() > 1e3)\n            logWarning<<stationNames.at(idStation)<<\": r = \"<<0.001*(stationInfo.approxPosition-grid.points.at(idStation)).r()<<\" km\"<<Log::endl;\n          grid.points.at(idStation) = stationInfo.approxPosition;\n        }\n        catch(std::exception &)\n        {\n          logWarning<<stationNames.at(idStation)<<\": stationInfo not found\"<<Log::endl;\n        }\n      }\n    }\n\n    // ======================================================\n\n    logStatus<<\"read coefficients from files\"<<Log::endl;\n    std::vector<Time>   times;\n    std::vector<Matrix> data; // ah, aw, zhd, zwd, gnh, geh, gnw, gew;\n    InFile file(fileNameIn);\n    for(;;)\n    {\n      std::string line;\n      while(std::getline(file, line) && line.size() && (line.at(0) == '!' || line.at(0) == '#')); // skip header/comment lines\n      if(line.empty())\n        break;\n\n      std::stringstream ss(line);\n      std::string name;\n      Double      mjd;\n      Double      ah, aw, zhd, zwd;\n      Double      pressure, temperature, waterVapour;\n      Double      gnh = 0, geh = 0, gnw = 0, gew = 0;\n      ss>>name>>mjd>>ah>>aw>>zhd>>zwd>>pressure>>temperature>>waterVapour>>gnh>>geh>>gnw>>gew;\n\n      name = String::lowerCase(name);\n      const UInt idStation = std::distance(stationNames.begin(), std::find(stationNames.begin(), stationNames.end(), name));\n      if(idStation >= stationNames.size())\n      {\n        logWarning<<name<<\" not in list -> use station info\"<<Log::endl;\n        Platform stationInfo; // read position from stationInfo\n        try\n        {\n          fileNameVariableList.setVariable(\"station\", name);\n          readFilePlatform(fileNameStationInfo(fileNameVariableList), stationInfo);\n        }\n        catch(std::exception &)\n        {\n          logWarning<<name<<\": skip station without coordinates\"<<Log::endl;\n          continue;\n        }\n\n        stationNames.push_back(name);\n        grid.points.push_back(stationInfo.approxPosition);\n        for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        {\n          Matrix newData(stationNames.size(), 8, NAN_EXPR);\n          std::swap(newData, data.at(idEpoch));\n          copy(newData, data.at(idEpoch).row(0, newData.rows()));\n        }\n      }\n\n      const UInt idEpoch = std::distance(times.begin(), std::find(times.begin(), times.end(), mjd2time(mjd)));\n      if(idEpoch >= times.size())\n      {\n        times.push_back(mjd2time(mjd));\n        data.resize(times.size(), Matrix(stationNames.size(), 8, NAN_EXPR));\n      }\n\n      data.at(idEpoch)(idStation, 0) = ah;\n      data.at(idEpoch)(idStation, 1) = aw;\n      data.at(idEpoch)(idStation, 2) = zhd;\n      data.at(idEpoch)(idStation, 3) = zwd;\n      data.at(idEpoch)(idStation, 4) = gnh/1000; // mm -> m\n      data.at(idEpoch)(idStation, 5) = geh/1000;\n      data.at(idEpoch)(idStation, 6) = gnw/1000;\n      data.at(idEpoch)(idStation, 7) = gew/1000;\n    }\n\n    // ======================================================\n\n    for(UInt idStation=0; idStation<stationNames.size(); idStation++)\n    {\n      UInt count = 0;\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        if(!data.at(idEpoch)(idStation, 0))\n          count++;\n      if(count)\n        logWarning<<stationNames.at(idStation)<<\" missing \"<<count<<\" epochs of \"<<times.size()<<Log::endl;\n    }\n\n    // ======================================================\n\n    logStatus<<\"write VMF coefficients to <\"<<fileNameVmfCoefficients<<\">\"<<Log::endl;\n    writeFileGriddedDataTimeSeries(fileNameVmfCoefficients, 1, times, grid, data);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/covariance/autoregressiveModel2CovarianceMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file autoregressiveModel2CovarianceMatrix.cpp\n*\n* @brief Compute the covariance structure of a sequence of VAR(0) to VAR(p) models\n*\n* @author Andreas Kvas\n* @date 2015-10-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the covariance structure of a random process represented by an AR model sequence.\nThe covariance matrix is determined by accumulating the normal equations of all AR models in \\config{autoregressiveModelSequence}\nand inverting the combined normal equation matrix.\nFor each output file in \\configFile{outputfileCovarianceMatrix}{matrix},\nthe covariance matrix of appropriate time lag is saved (the first file contains the auto-covariance,\nsecond file cross covariance and so on). The matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\Sigma(t-h, t)$.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"misc/kalmanProcessing.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute the covariance structure of a sequence of VAR(0) to VAR(p) models\n* @ingroup programsGroup */\nclass AutoregressiveModel2CovarianceMatrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(AutoregressiveModel2CovarianceMatrix, SINGLEPROCESS, \"Compute the covariance structure of a sequence of VAR(0) to VAR(p) models\", Covariance)\n\n/***********************************************/\n\nvoid AutoregressiveModel2CovarianceMatrix::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName> fileNameOut;\n    AutoregressiveModelSequencePtr arSequence;\n\n    readConfig(config, \"outputfileCovarianceMatrix\",     fileNameOut,       Config::MUSTSET, \"\", \"covariance matrix for each lag\");\n    readConfig(config, \"autoregressiveModelSequence\",    arSequence,        Config::MUSTSET, \"\", \"AR model sequence\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read autoregressive model sequence\"<<Log::endl;\n    const UInt blockCount = arSequence->maximumOrder()+1;\n    const UInt dimension  = arSequence->dimension();\n    auto blockIndex = MatrixDistributed::computeBlockIndex(dimension*blockCount, dimension);\n    MatrixDistributed N(blockIndex, Parallel::selfCommunicator());\n\n    logStatus<<\"set up normal equations\"<<Log::endl;\n    for(UInt r = 0; r<N.blockCount(); r++)\n      for(UInt c = r; c<N.blockCount(); c++)\n        arSequence->distributedNormalsBlock(N.blockCount(), r, c, N.N(r, c));\n\n    logStatus<<\"compute inverse of normal equations\"<<Log::endl;\n    N.cholesky(FALSE/*timing*/);\n    N.choleskyInverse(FALSE/*timing*/);\n    N.choleskyProduct(FALSE/*timing*/);\n    for(UInt column = 0; column<std::min(N.blockCount(), fileNameOut.size()); column++)\n    {\n      logStatus<<\"write covariance matrix to <\"<<fileNameOut.at(column)<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOut.at(column), N.N(0, column));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/covariance/covarianceFunction2DigitalFilter.cpp",
    "content": "/***********************************************/\n/**\n* @file covarianceFunction2DigitalFilter.cpp\n*\n* @brief Digital filter coefficients from covariance functions.\n*\n* @author Andreas Kvas\n* @date 2018-03-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes digital filter coefficients for a \\configClass{digital filter}{digitalFilterType} of given degree and\norder. The filter coefficients are computed by fitting them to an approximated\nimpulse response represented by the cholesky factor of the covariance matrix.\n\nThe parameter \\config{warmup} determines from which element of the cholesky matrix the\ncoefficients (default: half the covariance length) are fitted.\n\nPer default, the program computes filter coefficients which generate colored noise\nwhen applied to a white noise sequence. When \\config{decorrelationFilter} is set,\na decorrelation filter is computed which yields white noise when applied to colored noise.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Digital filter coefficients from covariance functions.\n* @ingroup programsGroup */\nclass CovarianceFunction2DigitalFilter\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(CovarianceFunction2DigitalFilter, SINGLEPROCESS, \"Digital filter coefficients from covariance function.\", Covariance)\n\n/***********************************************/\n\nvoid CovarianceFunction2DigitalFilter::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outFileFilter, inputFileCovariance;\n    UInt column, p, q;\n    Bool decorrelate;\n    UInt start = MAX_UINT;\n\n    readConfig(config, \"outputfileFilter\",     outFileFilter,       Config::MUSTSET, \"\", \"filter coefficients\");\n    readConfig(config, \"inputfileCovariance\",  inputFileCovariance, Config::MUSTSET, \"\", \"first column: time steps, following columns: covariance functions\");\n    readConfig(config, \"column\",               column,              Config::DEFAULT,  \"1\", \"Column with covariance function to be fitted\");\n    readConfig(config, \"warmup\",               start,               Config::OPTIONAL, \"\", \"number of samples until diagonal of Cholesky factor is flat (default: half covariance length)\");\n    readConfig(config, \"numeratorDegree\",      p,                   Config::DEFAULT,  \"3\", \"Maximum degree of numerator polynomial (MA constituent)\");\n    readConfig(config, \"denominatorDegree\",    q,                   Config::DEFAULT,  \"3\", \"Maximum degree of denominator polynomial (AR constitutent)\");\n    readConfig(config, \"decorrelationFilter\",  decorrelate,         Config::DEFAULT,  \"0\", \"compute a decorrelation filter\");\n    if(isCreateSchema(config)) return;\n\n    // read covariance function\n    // ------------------------\n    logStatus<<\"read covariance function file <\"<<inputFileCovariance<<\">\"<<Log::endl;\n    Matrix covFunc;\n    readFileMatrix(inputFileCovariance, covFunc);\n    Vector c = covFunc.column(column);\n\n    Matrix W(c.rows(), Matrix::SYMMETRIC, Matrix::UPPER);\n    for(UInt i = 0; i<W.rows(); i++)\n      for(UInt j = i; j<W.rows(); j++)\n        W(i, j) = c(j-i);\n\n    cholesky(W);\n\n    if(decorrelate)\n      inverse(W);\n\n    // compute best fitting filter\n    // ---------------------------\n    if(start == MAX_UINT)\n      start = W.rows()/2;\n\n    Vector b, a;\n    Matrix H_approx = W.trans().slice(start, start, W.rows()-start, W.rows()-start);\n\n    Vector l = H_approx.slice(p, 0, H_approx.rows()-p, 1);\n    Matrix A = H_approx.slice(p, 1, H_approx.rows()-p, q);\n\n    // AR part\n    Vector ar_hat = leastSquares(A, l);  // \"alpha\" AR coefficients\n    a = Vector(ar_hat.rows()+1, 1.0);\n    copy(-ar_hat, a.row(1, a.rows()-1)); // \"beta\" AR coefficients\n\n    // MA part\n    b = H_approx.slice(0, 0, p, q+1)*a;\n\n    logStatus << \"Writing filter to <\" << outFileFilter << \">\"<< Log::endl;\n    Matrix F(std::max(b.rows(), a.rows()), 3);\n    for(UInt i=0; i<F.rows(); i++)\n      F(i, 0) = static_cast<Double>(i);\n    copy(b, F.slice(0, 1, b.rows(), 1));\n    copy(a, F.slice(0, 2, a.rows(), 1));\n    writeFileMatrix(outFileFilter, F);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/covariance/covarianceFunction2PowerSpectralDensity.cpp",
    "content": "/***********************************************/\n/**\n* @file covarianceFunction2PowerSpectralDensity.cpp\n*\n* @brief Power Spectral Density (PSD) from covariance functions.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-07-03\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nOne sided Power Spectral Density (PSD) from a covariance function. The first column of \\configFile{inputfileCovarianceFunction}{matrix}\nshould contain the time lag in seconds.\nMultiple covariance functions (in the following column)s are supported.\nThe output is a \\file{matrix}{matrix} with first column contains the frequency $[Hz]$ and the other columns the PSD $[unit^2/Hz]$.\n\nConversion between covariance function $c_j$ and PSD $p_k$ is performed by discrete cosine transformation:\n\\begin{equation}\np_k = 2\\Delta t\\left(c_0 + c_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 c_j \\cos(\\pi jk/(n-1))\\right).\n\\end{equation}\n\nSee also \\program{PowerSpectralDensity2CovarianceFunction}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Power Spectral Density (PSD) from covariance functions.\n* @ingroup programsGroup */\nclass CovarianceFunction2PowerSpectralDensity\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(CovarianceFunction2PowerSpectralDensity, SINGLEPROCESS, \"Power Spectral Density (PSD) from covariance functions.\", Covariance)\nGROOPS_RENAMED_PROGRAM(CovarianceFunction2PSD, CovarianceFunction2PowerSpectralDensity, date2time(2020, 5, 24))\n\n/***********************************************/\n\nvoid CovarianceFunction2PowerSpectralDensity::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName psdName, covName;\n\n    readConfig(config, \"outputfilePSD\",                psdName,   Config::MUSTSET,  \"\",  \"first column: frequency [Hz], other columns PSD [unit^2/Hz]\");\n    readConfig(config, \"inputfileCovarianceFunction\",  covName,   Config::MUSTSET,  \"\",  \"first column: time steps, following columns: covariance functions\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read covariance function file <\"<<covName<<\">\"<<Log::endl;\n    Matrix covFunc;\n    readFileMatrix(covName, covFunc);\n    const Double sampling = covFunc(1,0) - covFunc(0,0);\n\n    Matrix A(covFunc.rows(), covFunc.columns());\n    for(UInt i=0; i<covFunc.rows(); i++)\n      A(i,0) = i/(2*sampling*(A.rows()-1));\n    for(UInt k=1; k<covFunc.columns(); k++)\n      copy(Fourier::covariance2psd(covFunc.column(k), sampling), A.column(k));\n\n    logStatus<<\"write PSD file <\"<<psdName<<\">\"<<Log::endl;\n    writeFileMatrix(psdName, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/covariance/covarianceMatrix2AutoregressiveModel.cpp",
    "content": "/***********************************************/\n/**\n* @file CovarianceMatrix2AutoregressiveModel.cpp\n*\n* @brief Compute a VAR(p) model from covariance matrices\n*\n* @author Andreas Kvas\n* @date 2015-10-19\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes a VAR(p) model from empirical covariance matrices.\nThe \\configFile{inputfileCovarianceMatrix}{matrix} represent the covariance structure of the process:\nthe first file should contain the auto-covariance, the second the cross-covariance of lag one,\nthe next cross-covariance of lag two and so on.\n\nCross-covariance matrices $\\Sigma_{\\Delta_k}$ are defined as the cross-covariance between epoch $t-k$ and $t$.\nIf the process realizations $x_{t}$ are arrange by ascending time stamps\n($\\{\\dots, x_{t-2}, x_{t-1}, x_{t}, x_{t+1}, x_{t+2},\\dots\\}$),\nthe covariance structure of the (stationary) process is therefore given by\n\\begin{equation}\n\\begin{bmatrix}\n\\Sigma & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\cdots \\\\\n\\Sigma_{\\Delta_1}^T & \\Sigma & \\Sigma_{\\Delta_1} &  \\cdots \\\\\n\\Sigma_{\\Delta_2}^T & \\Sigma_{\\Delta_1}^T & \\Sigma & \\cdots \\\\\n\\vdots & \\vdots & \\vdots & \\ddots \\\\\n\\end{bmatrix}.\n\\end{equation}\n\nThe estimate AR model is saved as single matrix \\config{outputfileAutoregressiveModel} according to the GROOPS AR model conventions.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute least squares prediction matrices (B, Q) from covariance matrices\n*\n* @ingroup programsGroup */\nclass CovarianceMatrix2AutoregressiveModel\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(CovarianceMatrix2AutoregressiveModel, SINGLEPROCESS, \"Compute a VAR(p) model from covariance matrices\", Covariance)\n\n/***********************************************/\n\nvoid CovarianceMatrix2AutoregressiveModel::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName> inNameCovariance;\n    FileName outNameModel;\n\n    readConfig(config, \"outputfileAutoregressiveModel\",   outNameModel,      Config::MUSTSET,   \"\",  \"coefficients and white noise covariance of AR(p) model\");\n    readConfig(config, \"inputfileCovarianceMatrix\",       inNameCovariance,  Config::MUSTSET,   \"\",  \"file name of covariance matrix\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read covariance matrices\"<<Log::endl;\n    const UInt order = inNameCovariance.size()-1;\n    std::vector<Matrix> C(order+1);\n    for(UInt k = 0; k<order+1; k++)\n      readFileMatrix(inNameCovariance.at(k), C.at(k));\n\n    if(C.front().getType() != Matrix::SYMMETRIC)\n      throw(Exception(\"Auto-covariance matrix must be symmetric.\"));\n\n    logStatus<<\"compute autoregressive model of order <\"<<order<<\">\"<<Log::endl;\n    if(order == 0)\n    {\n      Matrix model = matrixSquareRootInverse(C.front());\n      logStatus<<\"write autoregressive model to <\"<<outNameModel<<\">\"<<Log::endl;\n      writeFileMatrix(outNameModel, model);\n      return;\n    }\n    const UInt dim = C.front().rows();\n    Matrix n(dim*order, dim); // right hand side\n    MatrixDistributed N;\n    auto blockIndex = MatrixDistributed::computeBlockIndex(dim*order, dim);\n    N.initEmpty(blockIndex, Parallel::selfCommunicator());\n    for(UInt r = 0; r<N.blockCount(); r++)\n    {\n      copy(C.at(r+1), n.row(r*dim, dim));\n      for(UInt c = r; c<N.blockCount(); c++)\n      {\n        N.setBlock(r, c);\n        N.N(r, c) = C.at(c-r).trans(); // block toeplitz\n      }\n    }\n    Matrix X = N.solve(n, TRUE/*timing*/);\n\n    logStatus<<\"compute white noise covariance\"<<Log::endl;\n    Matrix Q = C.front();\n    fillSymmetric(Q);\n    Q.setType(Matrix::GENERAL);\n    matMult(-1.0, X.trans(), n, Q);\n    Q.setType(Matrix::SYMMETRIC);\n\n    try\n    {\n      Matrix W = Q; cholesky(W);\n    }\n    catch(std::exception &/*e*/)\n    {\n      logWarning<<\"white noise covariance is not positive definite\"<<Log::endl;\n    }\n\n    Matrix F = matrixSquareRootInverse(Q); // F = Q^(-1/2)\n    Matrix model(dim, (order+1)*dim); // [Ap, ..., A1, A0]\n    copy(F, model.column(order*dim, dim));\n    for(UInt k = 0; k<order; k++)\n      matMult(-1.0, F, X.row((order-k-1)*dim, dim).trans(), model.column(k*dim, dim)); // Ak = -Q^(1/2)*B_k, B0 = -I\n\n    logStatus<<\"write autoregressive model to <\"<<outNameModel<<\">\"<<Log::endl;\n    writeFileMatrix(outNameModel, model);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/covariance/covarianceMatrix2Correlation.cpp",
    "content": "/***********************************************/\n/**\n* @file covarianceMatrix2Correlation.cpp\n*\n* @brief Compute the correlation matrix from a covariance matrix\n*\n* @author Andreas Kvas\n* @date 2018-01-10\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the pearson correlation coefficient\n\\begin{equation}\n  \\rho_{ij} = \\frac{\\sigma_{ij}}{\\sigma_i \\sigma_j}\n\\end{equation}\nfrom a given covariance matrix stored in \\configFile{inputfileCovarianceMatrix}{matrix}.\nThe result is stored in \\configFile{outputfileCorrelationMatrix}{matrix}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute the correlation matrix from a covariance matrix.\n* @ingroup programsGroup */\nclass CovarianceMatrix2Correlation\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(CovarianceMatrix2Correlation, PARALLEL, \"compute the correlation matrix from a covariance matrix\", Covariance)\n\n/***********************************************/\n\nvoid CovarianceMatrix2Correlation::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n\n    readConfig(config, \"outputfileCorrelationMatrix\", fileNameOut, Config::MUSTSET, \"\",  \"correlation matrix\");\n    readConfig(config, \"inputfileCovarianceMatrix\",   fileNameIn,  Config::MUSTSET, \"\",  \"covariance matrix\");\n    if(isCreateSchema(config)) return;\n\n    Matrix covarianceMatrix;\n    readFileMatrix(fileNameIn, covarianceMatrix);\n    if(covarianceMatrix.getType() != Matrix::SYMMETRIC)\n      throw(Exception(\"Covariance matrix must be symmetric.\"));\n    fillSymmetric(covarianceMatrix);\n\n    Matrix correlationMatrix(covarianceMatrix.rows(), Matrix::SYMMETRIC, Matrix::UPPER);\n    for(UInt r=0; r<covarianceMatrix.rows(); r++)\n      for(UInt c=r; c<covarianceMatrix.columns(); c++)\n        correlationMatrix(r,c) = covarianceMatrix(r,c)/std::sqrt(covarianceMatrix(r,r)*covarianceMatrix(c,c));\n\n    logStatus<<\"write correlation matrix to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, correlationMatrix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/covariance/powerSpectralDensity2CovarianceFunction.cpp",
    "content": "/***********************************************/\n/**\n* @file powerSpectralDensity2CovarianceFunction.cpp\n*\n* @brief Covariance functions from Power Spectral Density (PSD).\n*\n* @author Matthias Ellmer\n* @date 2013-08-27\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCovariance function from Power Spectral Density (PSD).\nThe \\configFile{inputfilePSD}{matrix} contains in the first column the frequency $[Hz]$, followed by (possibly multiple) PSDs $[unit^2/Hz]$.\nThe output is a \\file{matrix}{matrix}, the first column containing time lag $[s]$ and the other columns the covariance functions $[unit^2]$.\nConversion between PSD $p_j$ and covariance function $c_k$ is performed by discrete cosine transformation:\n\\begin{equation}\nc_k = \\frac{1}{4\\Delta t (n-1)}\\left(p_0 + p_{n-1} (-1)^k + \\sum_{j=1}^{n-2} 2 p_j \\cos(\\pi jk/(n-1))\\right).\n\\end{equation}\n\nSee also \\program{CovarianceFunction2PowerSpectralDensity}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Covariance functions from Power Spectral Density (PSD).\n* @ingroup programsGroup */\nclass PowerSpectralDensity2CovarianceFunction\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PowerSpectralDensity2CovarianceFunction, SINGLEPROCESS, \"Covariance functions from Power Spectral Density (PSD).\", Covariance)\nGROOPS_RENAMED_PROGRAM(CovariancePsd2CovarianceFunction, PowerSpectralDensity2CovarianceFunction, date2time(2020, 5, 24))\n\n/***********************************************/\n\nvoid PowerSpectralDensity2CovarianceFunction::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameCov, fileNamePsd;\n\n    readConfig(config, \"outputfileCovarianceFunction\", fileNameCov, Config::MUSTSET, \"\", \"first column: time steps [seconds], following columns: covariance functions\");\n    readConfig(config, \"inputfilePSD\",                 fileNamePsd, Config::MUSTSET, \"\", \"first column: frequency [Hz], following columns PSD [unit^2/Hz]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read PSD file <\"<<fileNamePsd<<\">\"<<Log::endl;\n    Matrix psd;\n    readFileMatrix(fileNamePsd, psd);\n\n    Matrix cov(psd.rows(), psd.columns());\n    const Double dt = 1./(2*psd(psd.rows()-1, 0));\n    for(UInt i=0; i<cov.rows(); i++)\n      cov(i,0) = i*dt;\n\n    for(UInt k=1; k<cov.columns(); k++)\n      copy(Fourier::psd2covariance(psd.column(k), dt), cov.column(k));\n\n    logStatus<<\"write covariance file <\"<<fileNameCov<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameCov, cov);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/deprecated/gnssAttitude2Orbex.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAttitude2Orbex.cpp\n*\n* @brief DEPRECATED since 2024-11-30. Please use StarCamera2Orbex instead.\n*\n* @author Sebastian Strasser\n* @date 2019-05-29\n*\n* @deprecated Please use StarCamera2Orbex instead.\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2024-11-30. Please use \\program{StarCamera2Orbex} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileStringTable.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2024-11-30. Please use StarCamera2Orbex instead.\n* @ingroup programsConversionGroup */\nclass GnssAttitude2Orbex\n{\n  class Record\n  {\n  public:\n    std::string prn;\n    Vector      quaternion;\n\n    Record(const std::string &prn, const_MatrixSliceRef quaternion) : prn(prn), quaternion(quaternion) {}\n  };\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAttitude2Orbex, SINGLEPROCESS, \"DEPRECATED since 2024-11-30. Please use StarCamera2Orbex instead.\", Deprecated)\n\n/***********************************************/\n\nvoid GnssAttitude2Orbex::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOrbex, fileNameAttitude;\n    std::vector<FileName> fileNameTransmitterList;\n    std::string variablePrn, coordSystem, contact, createdBy, description, inputData;\n    std::vector<std::string> comments;\n    TimeSeriesPtr timeSeriesPtr;\n    EarthRotationPtr earthRotation;\n    UInt interpolationDegree;\n    Polynomial polynomial;\n\n    readConfig(config, \"outputfileOrbex\",          fileNameOrbex,           Config::MUSTSET,  \"\",      \"ORBEX file\");\n    readConfig(config, \"inputfileTransmitterList\", fileNameTransmitterList, Config::MUSTSET,  \"\",      \"ASCII list with transmitter PRNs\");\n    readConfig(config, \"inputfileAttitude\",        fileNameAttitude,        Config::MUSTSET,  \"attitude.{prn}.dat\", \"instrument file containing attitude\");\n    readConfig(config, \"variablePrn\",              variablePrn,             Config::DEFAULT,  \"prn\",   \"loop variable for PRNs from transmitter list\");\n    readConfig(config, \"timeSeries\",               timeSeriesPtr,           Config::DEFAULT,  \"\",      \"resample to these epochs (otherwise input file epochs are used)\");\n    readConfig(config, \"earthRotation\",            earthRotation,           Config::OPTIONAL, \"file\",  \"rotate data into Earth-fixed frame\");\n    readConfig(config, \"interpolationDegree\",      interpolationDegree,     Config::MUSTSET,  \"7\",     \"for attitude and Earth rotation interpolation\");\n    readConfig(config, \"description\",              description,             Config::MUSTSET,  \"\",      \"description of file contents\");\n    readConfig(config, \"createdBy\",                createdBy,               Config::MUSTSET,  \"\",      \"name of agency\");\n    readConfig(config, \"inputData\",                inputData,               Config::MUSTSET,  \"p\",     \"description of input data (see ORBEX description)\");\n    readConfig(config, \"contact\",                  contact,                 Config::MUSTSET,  \"\",      \"email address\");\n    readConfig(config, \"referenceFrame\",           coordSystem,             Config::MUSTSET,  \"IGb14\", \"reference frame used in file\");\n    readConfig(config, \"comment\",                  comments,                Config::OPTIONAL, \"\",      \"\");\n    if(isCreateSchema(config)) return;\n\n    logWarning<<\"DEPRECATED since 2024-11-30. Please use StarCamera2Orbex instead.\"<<Log::endl;\n\n    std::vector<Time> times = timeSeriesPtr->times();\n\n    std::vector<std::string> transmitterList;\n    for(const auto &fileName : fileNameTransmitterList)\n    {\n      logStatus<<\"reading transmitter list from <\"<<fileName<<\">\"<<Log::endl;\n      readFileStringList(fileName, transmitterList);\n    }\n\n    VariableList fileNameVariableList;\n    std::map<Time, std::vector<Record>> times2Records;\n    for(const auto &prn : transmitterList)\n    {\n      fileNameVariableList.setVariable(variablePrn, prn);\n      StarCameraArc arc = InstrumentFile::read(fileNameAttitude(fileNameVariableList));\n\n      for(UInt idEpoch=0; idEpoch<arc.size(); idEpoch++)\n      {\n        arc.at(idEpoch).rotary = inverse(arc.at(idEpoch).rotary);\n        if(earthRotation)\n          arc.at(idEpoch).rotary *= inverse(earthRotation->rotaryMatrix(arc.at(idEpoch).time));\n      }\n      Matrix quaternion = arc.matrix().column(1, 4);\n\n      // (optionally) resample attitude\n      std::vector<Time> prnTimes = arc.times();\n      if(times.size())\n      {\n        Polynomial polynomial(prnTimes, interpolationDegree);\n        quaternion = polynomial.interpolate(times, quaternion);\n        prnTimes = times;\n      }\n\n      for(UInt idEpoch=0; idEpoch<quaternion.rows(); idEpoch++)\n        times2Records[prnTimes.at(idEpoch)].push_back(Record(prn, (quaternion.row(idEpoch)/norm(quaternion.row(idEpoch))).trans())); // normalize quaternions\n    }\n\n    times.clear();\n    for(const auto &epoch : times2Records)\n      times.push_back(epoch.first);\n\n    logStatus<<\"writing ORBEX file to <\"<<fileNameOrbex<<\">\"<<Log::endl;\n    OutFile outfile(fileNameOrbex);\n    outfile << \"%=ORBEX  0.09\" << std::endl;\n    outfile << \"%%\" << std::endl;\n    outfile << \"*------------------------------------------------------------------------------------------------------\" << std::endl;\n    outfile << \"+FILE/DESCRIPTION\" << std::endl;\n    outfile << \" DESCRIPTION         \" << description << std::endl;\n    outfile << \" CREATED_BY          \" << createdBy << std::endl;\n    outfile << \" CREATION_DATE       \" << System::now()%\"%y %m %d %H %M %S\"s << std::endl;\n    outfile << \" INPUT_DATA          \" << inputData << std::endl;\n    outfile << \" CONTACT             \" << contact << std::endl;\n    outfile << \" TIME_SYSTEM         GPS\" << std::endl;\n    outfile << \" START_TIME          \" << times.front()%\"%y %m %d %H %M %012.9S000\"s << std::endl;// ATTENTION: \"fake\" 15.12 precision due to max Time precision\n    outfile << \" END_TIME            \" << times.back() %\"%y %m %d %H %M %012.9S000\"s << std::endl;// ATTENTION: \"fake\" 15.12 precision due to max Time precision\n    outfile << \" EPOCH_INTERVAL      \" << medianSampling(times).seconds()%\"%9.3f\"s << std::endl;\n    outfile << \" COORD_SYSTEM        \" << coordSystem << std::endl;\n    outfile << \" FRAME_TYPE          \" << (earthRotation ? \"ECEF\" : \"ECI\") << std::endl;\n    outfile << \" LIST_OF_REC_TYPES   ATT\" << std::endl;\n    outfile << \"-FILE/DESCRIPTION\" << std::endl;\n    if(comments.size())\n    {\n      outfile << \"*------------------------------------------------------------------------------------------------------\" << std::endl;\n      for(auto &comment : comments)\n        outfile << \"* \" << comment << std::endl;\n    }\n    outfile << \"*------------------------------------------------------------------------------------------------------\" << std::endl;\n    outfile << \"+SATELLITE/ID_AND_DESCRIPTION\" << std::endl;\n    for(const auto &prn : transmitterList)\n      outfile << \" \" << prn << std::endl;\n    outfile << \"-SATELLITE/ID_AND_DESCRIPTION\" << std::endl;\n    outfile << \"*------------------------------------------------------------------------------------------------------\" << std::endl;\n    outfile << \"+EPHEMERIS/DATA\" << std::endl;\n    outfile << \"*ATT RECORDS: TRANSFORMATION FROM TERRESTRIAL FRAME COORDINATES (T) TO SAT. BODY FRAME ONES (B) SUCH AS\" << std::endl;\n    outfile << \"*                                 (0,B) = q.(0,T).trans(q)\" << std::endl;\n    outfile << \"*REC ID_              N ___q0_(scalar)_____ ____q1__x__________ ____q2__y__________ ____q3__z__________\" << std::endl;\n    for(const auto &epoch : times2Records)\n    {\n      outfile << epoch.first%\"## %y %m %d %H %M %012.9S000 \"s << epoch.second.size()%\"%3i\"s << std::endl; // ATTENTION: \"fake\" 15.12 precision due to max Time precision\n      for(const auto &record : epoch.second)\n      {\n        outfile << \" ATT \" << record.prn << std::string(14, ' ') << record.quaternion.size();\n        for(UInt i = 0; i < record.quaternion.size(); i++)\n          outfile << record.quaternion(i)%\" %19.16f\"s;\n        outfile << std::endl;\n      }\n    }\n    outfile << \"-EPHEMERIS/DATA\" << std::endl;\n    outfile << \"*------------------------------------------------------------------------------------------------------\" << std::endl;\n    outfile << \"%END_ORBEX\" << std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/deprecated/gnssPrn2SvnBlockVariables.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssPrn2SvnBlockVariables.cpp\n*\n* @brief DEPRECATED since 2024-02-12. This program no longer works! See documentation for help.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-03-14\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2024-02-12. This program no longer works!\n\nSetup up a \\configClass{loop:platformEquipment}{loopType:platformEquipment} instead with\n\\begin{itemize}\n  \\item \\configFile{inputfilePlatform}{platform}: the old \\config{inputfileTransmitterInfo}\n  \\item \\config{equipmentType}         = \\verb|gnssAntenna|\n  \\item \\config{variableLoopName}      = \\verb|block|\n  \\item \\config{variableLoopSerial}    = \\verb|svn|\n  \\item \\config{variableLoopTimeStart} = \\verb|svnTimeStart|\n  \\item \\config{variableLoopTimeEnd}   = \\verb|svnTimeEnd|\n  \\item \\configClass{condition:expression}{conditionType:expression}\n  \\begin{itemize}\n    \\item \\config{expression} = \\verb|(svnTimeStart <= time) && (time < svnTimeEnd)|\n  \\end{itemize}\n\\end{itemize}\nAttribute this loop to programs, which uses the variables.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2024-02-12. This program no longer works! See documentation for help.\n* @ingroup programsGroup */\nclass GnssPrn2SvnBlockVariables\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssPrn2SvnBlockVariables, SINGLEPROCESS, \"DEPRECATED since 2024-02-12. This program no longer works! See documentation for help.\", Deprecated)\n\n/***********************************************/\n\nvoid GnssPrn2SvnBlockVariables::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    if(isCreateSchema(config)) return;\n\n    logError<<\"This program no longer works!!!!! See documentation for help.\"<<Log::endl;\n    logWarningOnce<<\"  Setup up a loop->platformEquipment instead with\"<<Log::endl;\n    logWarningOnce<<\"    - inputfilePlatform     = inputfileTransmitterInfo\"<<Log::endl;\n    logWarningOnce<<\"    - equipmentType         = gnssAntenna\"<<Log::endl;\n    logWarningOnce<<\"    - variableLoopName      = block\"<<Log::endl;\n    logWarningOnce<<\"    - variableLoopSerial    = svn\"<<Log::endl;\n    logWarningOnce<<\"    - variableLoopTimeStart = svnTimeStart\"<<Log::endl;\n    logWarningOnce<<\"    - variableLoopTimeEnd   = svnTimeEnd\"<<Log::endl;\n    logWarningOnce<<\"    - condition->expression\"<<Log::endl;\n    logWarningOnce<<\"      -- expression = (svnTimeStart <= time) && (time < svnTimeEnd)\"<<Log::endl;\n    logWarningOnce<<\"  Attribute the loop to programs, which uses the variables.\"<<Log::endl;\n    throw(Exception(\"This program no longer works! See documentation for help\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/deprecated/gnssStationInfoCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssStationInfoCreate.cpp\n*\n* @brief DEPRECATED since 2024-12-02. Use PlatformCreate instead.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-24\n*\n* @deprecated Use PlatformCreate instead.\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2024-12-02. Please use \\program{PlatformCreate} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2024-12-02. Please use PlatformCreate instead.\n* @ingroup programsGroup */\nclass GnssStationInfoCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssStationInfoCreate, SINGLEPROCESS, \"DEPRECATED since 2024-12-02. Please use PlatformCreate instead.\", Deprecated)\nGROOPS_RENAMED_PROGRAM(GnssCreateStationInfo, GnssStationInfoCreate, date2time(2019, 9, 5))\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, std::shared_ptr<PlatformGnssAntenna> &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    var = std::make_shared<PlatformGnssAntenna>();\n    Angle angleX, angleY, angleZ;\n    Bool  flipx, flipy, flipz;\n\n    readConfig(config, \"name\",        var->name,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",      var->serial,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"radome\",      var->radome,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",     var->comment,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\",   var->timeStart,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",     var->timeEnd,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"positionX\",   var->position.x(), Config::MUSTSET,  \"0\", \"[m] ARP in north, east, up or vehicle system\");\n    readConfig(config, \"positionY\",   var->position.y(), Config::MUSTSET,  \"0\", \"[m] ARP in north, east, up or vehicle system\");\n    readConfig(config, \"positionZ\",   var->position.z(), Config::MUSTSET,  \"0\", \"[m] ARP in north, east, up or vehicle system\");\n    readConfig(config, \"rotationX\",   angleX,            Config::DEFAULT,  \"0\", \"[degree] from local/vehicle to left-handed antenna system\");\n    readConfig(config, \"rotationY\",   angleY,            Config::DEFAULT,  \"0\", \"[degree] from local/vehicle to left-handed antenna system\");\n    readConfig(config, \"rotationZ\",   angleZ,            Config::DEFAULT,  \"0\", \"[degree] from local/vehicle to left-handed antenna system\");\n    readConfig(config, \"flipX\",       flipx,             Config::DEFAULT,  \"0\", \"flip x-axis (after rotation)\");\n    readConfig(config, \"flipY\",       flipy,             Config::DEFAULT,  \"0\", \"flip y-axis (after rotation)\");\n    readConfig(config, \"flipZ\",       flipz,             Config::DEFAULT,  \"0\", \"flip z-axis (after rotation)\");\n    endSequence(config);\n    if(isCreateSchema(config))\n      return TRUE;\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n    var->local2antennaFrame = rotaryZ(angleZ) * rotaryY(angleY) * rotaryX(angleX);\n    if(flipx) var->local2antennaFrame = flipX() * var->local2antennaFrame;\n    if(flipy) var->local2antennaFrame = flipY() * var->local2antennaFrame;\n    if(flipz) var->local2antennaFrame = flipZ() * var->local2antennaFrame;\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, std::shared_ptr<PlatformGnssReceiver> &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    var = std::make_shared<PlatformGnssReceiver>();\n\n    readConfig(config, \"name\",      var->name,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",    var->serial,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"version\",   var->version,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",   var->comment,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,   Config::OPTIONAL, \"\",  \"\");\n    endSequence(config);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, Platform::ReferencePoint &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    readConfig(config, \"comment\",   var.comment,        Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"xStart\",    var.pointStart.x(), Config::MUSTSET,  \"0\", \"[m] in north, east, up or vehicle system\");\n    readConfig(config, \"yStart\",    var.pointStart.y(), Config::MUSTSET,  \"0\", \"linear motion between start and end\");\n    readConfig(config, \"zStart\",    var.pointStart.z(), Config::MUSTSET,  \"0\", \"\");\n    readConfig(config, \"xEnd\",      var.pointEnd.x(),   Config::MUSTSET,  \"0\", \"[m] in north, east, up or vehicle system\");\n    readConfig(config, \"yEnd\",      var.pointEnd.y(),   Config::MUSTSET,  \"0\", \"linear motion between start and end\");\n    readConfig(config, \"zEnd\",      var.pointEnd.z(),   Config::MUSTSET,  \"0\", \"\");\n    readConfig(config, \"timeStart\", var.timeStart,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var.timeEnd,        Config::OPTIONAL, \"\",  \"\");\n    endSequence(config);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssStationInfoCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outFileName;\n    Platform station;\n    std::vector<std::shared_ptr<PlatformGnssAntenna>>  antennas;\n    std::vector<std::shared_ptr<PlatformGnssReceiver>> receivers;\n\n    readConfig(config, \"outputfileStationInfo\", outFileName,                Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"markerName\",            station.markerName,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"markerNumber\",          station.markerNumber,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",               station.comment,            Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"approxPositionX\",       station.approxPosition.x(), Config::DEFAULT,  \"0\", \"[m] in TRF\");\n    readConfig(config, \"approxPositionY\",       station.approxPosition.y(), Config::DEFAULT,  \"0\", \"[m] in TRF\");\n    readConfig(config, \"approxPositionZ\",       station.approxPosition.z(), Config::DEFAULT,  \"0\", \"[m] in TRF\");\n    readConfig(config, \"antenna\",               antennas,                   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"receiver\",              receivers,                  Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"referencePoint\",        station.referencePoints,    Config::OPTIONAL, \"\",  \"e.g. center of mass in satellite frame\");\n    if(isCreateSchema(config)) return;\n\n    logWarning<<\"DEPRECATED since 2024-12-02. Please use PlatformCreate instead.\"<<Log::endl;\n\n    // ============================\n\n    // check antennas\n    // --------------\n    if(antennas.size())\n    {\n      for(UInt i=0; i<antennas.size()-1; i++)\n        if(antennas.at(i)->timeEnd == Time())\n          antennas.at(i)->timeEnd = antennas.at(i+1)->timeStart;\n      if(antennas.back()->timeEnd == Time())\n        antennas.back()->timeEnd = date2time(2500,1,1);\n      station.equipments.insert(station.equipments.end(), antennas.begin(), antennas.end());\n    }\n\n    // check receivers\n    // ----------------\n    if(receivers.size())\n    {\n      for(UInt i=0; i<receivers.size()-1; i++)\n        if(receivers.at(i)->timeEnd == Time())\n          receivers.at(i)->timeEnd = receivers.at(i+1)->timeStart;\n      if(receivers.back()->timeEnd == Time())\n        receivers.back()->timeEnd = date2time(2500,1,1);\n      station.equipments.insert(station.equipments.end(), receivers.begin(), receivers.end());\n    }\n\n    // check reference points\n    // ----------------------\n    if(station.referencePoints.size())\n    {\n      for(UInt i=0; i<station.referencePoints.size()-1; i++)\n        if(station.referencePoints.at(i).timeEnd == Time())\n          station.referencePoints.at(i).timeEnd = station.referencePoints.at(i+1).timeStart;\n      if(station.referencePoints.back().timeEnd == Time())\n        station.referencePoints.back().timeEnd = date2time(2500,1,1);\n    }\n\n    // ============================\n\n    logStatus<<\"write platform <\"<<outFileName<<\">\"<<Log::endl;\n    writeFilePlatform(outFileName, station);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/deprecated/gridRectangular2NetCdf.cpp",
    "content": "/***********************************************/\n/**\n* @file gridRectangular2NetCdf.cpp\n*\n* @brief DEPRECATED since 2023-07-06. Please use GriddedData2NetCdf or GriddedDataTimeSeries2NetCdf instead.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2018-06-17\n*\n* @deprecated Please use GriddedData2NetCdf or GriddedDataTimeSeries2NetCdf instead.\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2023-07-06. Please use \\program{GriddedData2NetCdf} or \\program{GriddedDataTimeSeries2NetCdf} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"inputOutput/fileNetCdf.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2023-07-06. Please use GriddedData2NetCdf or GriddedDataTimeSeries2NetCdf instead.\n* @ingroup programsConversionGroup */\nclass GridRectangular2NetCdf\n{\npublic:\n  class Attribute\n  {\n  public:\n    std::string         name;\n    std::string         text;\n    std::vector<Double> values;\n    NetCdf::DataType    dataType;\n  };\n\n  class DataVariable\n  {\n  public:\n    std::string            name;\n    UInt                   dataField;\n    NetCdf::DataType       dataType;\n    std::vector<Attribute> attributes;\n    NetCdf::Variable       variable;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GridRectangular2NetCdf, SINGLEPROCESS, \"DEPRECATED since 2023-07-06. Please use GriddedData2NetCdf or GriddedDataTimeSeries2NetCdf instead.\", Deprecated)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GridRectangular2NetCdf::Attribute &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string choice;\n  if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n    return FALSE;\n  if(readConfigChoiceElement(config, \"text\", choice, \"\"))\n  {\n    readConfig(config, \"name\",  var.name,  Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"value\", var.text, Config::MUSTSET, \"\", \"\");\n  }\n  if(readConfigChoiceElement(config, \"value\",  choice, \"\"))\n  {\n    std::string choice;\n    readConfig(config, \"name\",  var.name,   Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"value\", var.values, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"dataType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"double\", choice, \"\")) var.dataType = NetCdf::DOUBLE;\n      if(readConfigChoiceElement(config, \"float\",  choice, \"\")) var.dataType = NetCdf::FLOAT;\n      if(readConfigChoiceElement(config, \"int\",    choice, \"\")) var.dataType = NetCdf::INT;\n      endChoice(config);\n    }\n  }\n  endChoice(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GridRectangular2NetCdf::DataVariable &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"selectDataField\", var.dataField, Config::DEFAULT,  \"0\",     \"input data column\");\n  readConfig(config, \"name\",            var.name,      Config::MUSTSET,  \"data0\", \"netCDF variable name\");\n  std::string choice;\n  if(readConfigChoice(config, \"dataType\", choice, Config::MUSTSET, \"\", \"\"))\n  {\n    if(readConfigChoiceElement(config, \"double\", choice, \"\")) var.dataType = NetCdf::DOUBLE;\n    if(readConfigChoiceElement(config, \"float\",  choice, \"\")) var.dataType = NetCdf::FLOAT;\n    if(readConfigChoiceElement(config, \"int\",    choice, \"\")) var.dataType = NetCdf::INT;\n    endChoice(config);\n  }\n  readConfig(config, \"attribute\", var.attributes, Config::OPTIONAL, \"\", \"netCDF attributes\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GridRectangular2NetCdf::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                  fileNameOut;\n    std::vector<FileName>     fileNameIn;\n    std::vector<DataVariable> dataVariables;\n    std::vector<Attribute>    globalAttributes;\n    TimeSeriesPtr             timeSeries;\n\n    readConfig(config, \"outputfileNetCdf\",         fileNameOut,      Config::MUSTSET,  \"\", \"file name of NetCDF output\");\n    readConfig(config, \"inputfileGridRectangular\", fileNameIn,       Config::MUSTSET,  \"\", \"input grid sequence\");\n    readConfig(config, \"times\",                    timeSeries,       Config::DEFAULT,  \"\", \"values for time axis (COARDS specification)\");\n    readConfig(config, \"dataVariable\",             dataVariables,    Config::MUSTSET,  \"\", \"metadata for data variables\");\n    readConfig(config, \"globalAttribute\",          globalAttributes, Config::OPTIONAL, \"\", \"additional meta data\");\n    if(isCreateSchema(config)) return;\n\n    logWarning<<\"DEPRECATED since 2023-07-06. Please use GriddedData2NetCdf or GriddedDataTimeSeries2NetCdf instead.\"<<Log::endl;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n    // check input\n    // -----------\n    std::vector<Time> times = timeSeries->times();\n    if(times.size() && (times.size() != fileNameIn.size()))\n      throw(Exception(\"Mismatch in input file number and epoch count (\"+fileNameIn.size()%\"%i vs. \"s+times.size()%\"%i).\"s));\n    else if(!times.size() && (fileNameIn.size() > 1))\n      throw(Exception(\"Specifying more than one input file without time axis results in undefined behavior.\"));\n\n    // write attributes\n    // ----------------\n    NetCdf::OutFile file(fileNameOut);\n    for(const auto &attr : globalAttributes)\n    {\n      if(attr.text.empty())\n        file.addAttribute(attr.name, attr.dataType, attr.values);\n      else\n        file.addAttribute(attr.name, attr.text);\n    }\n\n    Bool firstGrid = TRUE;\n    std::vector<Double> mjd;\n    for(UInt idEpoch=0; idEpoch<fileNameIn.size(); idEpoch++)\n    {\n      GriddedDataRectangular grid;\n      try\n      {\n        logStatus<<\"read file <\"<<fileNameIn.at(idEpoch)<<\">\"<<Log::endl;\n        readFileGriddedData(fileNameIn.at(idEpoch), grid);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<Log::endl;\n        continue;\n      }\n\n      // create dimensions and variables\n      // -------------------------------\n      if(firstGrid)\n      {\n        firstGrid = FALSE;\n        if(times.size())\n        {\n          auto dim = file.addDimension(\"time\");\n          auto var = file.addVariable(\"time\", NetCdf::DOUBLE, {dim});\n          var.addAttribute(\"units\", \"days since 1858-11-17 00:00:00\"); // MJD\n        }\n        {\n          auto dim = file.addDimension(\"lat\", grid.latitudes.size());\n          auto var = file.addVariable(\"lat\", NetCdf::DOUBLE, {dim});\n          var.addAttribute(\"units\", \"degrees_north\");\n          Vector lats(grid.latitudes.size());\n          for(UInt i=0; i<grid.latitudes.size(); i++)\n            lats(i) = RAD2DEG * grid.latitudes.at(i);\n          var.setValues(lats);\n        }\n        {\n          auto dim = file.addDimension(\"lon\", grid.longitudes.size());\n          auto var = file.addVariable(\"lon\", NetCdf::DOUBLE, {dim});\n          var.addAttribute(\"units\", \"degrees_east\");\n          Vector lons(grid.longitudes.size());\n          for(UInt i=0; i<grid.longitudes.size(); i++)\n            lons(i) = RAD2DEG * grid.longitudes.at(i);\n          var.setValues(lons);\n        }\n        for(auto &data : dataVariables)\n        {\n          data.variable = file.addVariable(data.name, data.dataType, file.dimensions());\n          for(auto &attr : data.attributes)\n          {\n            if(attr.text.empty())\n              data.variable.addAttribute(attr.name, attr.dataType, attr.values);\n            else\n              data.variable.addAttribute(attr.name, attr.text);\n          }\n        }\n      } // if(firstGrid)\n\n      for(auto &data : dataVariables)\n      {\n        Vector values = flatten(grid.values.at(data.dataField).trans());\n        if(times.size())\n          data.variable.setValues({mjd.size(), 0, 0}, {1, grid.latitudes.size(), grid.longitudes.size()}, values);\n        else\n          data.variable.setValues({0, 0}, {grid.latitudes.size(), grid.longitudes.size()}, values);\n      }\n      if(times.size())\n        mjd.push_back(times.at(idEpoch).mjd());\n    }\n\n    if(mjd.size())\n      file.variable(\"time\").setValues(mjd);\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/deprecated/netCdf2GridRectangular.cpp",
    "content": "/***********************************************/\n/**\n* @file netCdf2GridRectangular.cpp\n*\n* @brief DEPRECATED since 2023-07-06. Please use NetCdf2GriddedData or NetCdf2GriddedDataTimeSeries instead.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2018-06-17\n*\n* @deprecated Please use NetCdf2GriddedData or NetCdf2GriddedDataTimeSeries instead.\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2023-07-06. Please use \\program{NetCdf2GriddedData} or \\program{NetCdf2GriddedDataTimeSeries} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileNetCdf.h\"\n#include \"files/fileGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED. Please use NetCdf2GriddedData or NetCdf2GriddedDataTimeSeries instead.\n* @ingroup programsConversionGroup */\nclass NetCdf2GridRectangular\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NetCdf2GridRectangular, SINGLEPROCESS, \"DEPRECATED since 2023-07-06. Please use NetCdf2GriddedData or NetCdf2GriddedDataTimeSeries instead.\", Deprecated)\n\n/***********************************************/\n\nvoid NetCdf2GridRectangular::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    outName, inName;\n    std::string loopVar;\n    std::string lonName, latName, timeName;\n    std::vector<std::string> dataName;\n    Double      a, f;\n\n    readConfig(config, \"outputfileGridRectangular\", outName,  Config::MUSTSET,  \"\",         \"One grid for each epoch in the NetCDF file is written. Use loopTimeVariable as template.\");\n    readConfig(config, \"loopTimeVariable\",          loopVar,  Config::MUSTSET,  \"loopTime\", \"\");\n    readConfig(config, \"inputfileNetCdf\",           inName,   Config::MUSTSET,  \"\",         \"\");\n    readConfig(config, \"variableNameLongitude\",     lonName,  Config::MUSTSET,  \"lon\",      \"name of NetCDF variable\");\n    readConfig(config, \"variableNameLatitude\",      latName,  Config::MUSTSET,  \"lat\",      \"name of NetCDF variable\");\n    readConfig(config, \"variableNameTime\",          timeName, Config::OPTIONAL, \"time\",     \"name of NetCDF variable (leave blank for static grids)\");\n    readConfig(config, \"variableNameData\",          dataName, Config::OPTIONAL, \"\",         \"name of NetCDF variable\");\n    readConfig(config, \"R\",                         a,        Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",         f,        Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    logWarning<<\"DEPRECATED since 2023-07-06. Please use NetCdf2GriddedData or NetCdf2GriddedDataTimeSeries instead.\"<<Log::endl;\n\n#ifdef GROOPS_DISABLE_NETCDF\n    throw(Exception(\"Compiled without NetCDF library\"));\n#else\n    // add variable for output files\n    // -----------------------------\n    VariableList fileNameVariableList;\n    fileNameVariableList.undefineVariable(loopVar);\n\n    // open netCDF file\n    // ----------------\n    logStatus<<\"read file <\"<<inName<<\">\"<<Log::endl;\n    NetCdf::InFile file(inName);\n    NetCdf::Variable  lon    = file.variable(lonName);\n    NetCdf::Variable  lat    = file.variable(latName);\n    NetCdf::Dimension dimLon = lon.dimensions().at(0);\n    NetCdf::Dimension dimLat = lat.dimensions().at(0);\n\n    // set up grid\n    // -----------\n    GriddedDataRectangular grid;\n    grid.ellipsoid  = Ellipsoid(a, f);\n    grid.longitudes = NetCdf::convertAngles(lon.values());\n    grid.latitudes  = NetCdf::convertAngles(lat.values());\n    grid.heights.resize(grid.latitudes.size(), 0.0);\n\n    // set up time axis\n    // ----------------\n    std::vector<Time> epochs(1);\n    NetCdf::Dimension dimTime;\n    if(!timeName.empty())\n    {\n      auto var = file.variable(timeName);\n      dimTime  = var.dimensions().at(0);\n      epochs   = NetCdf::convertTimes(var.values(), var.attribute(\"units\").value());\n    }\n\n    // data variables\n    // --------------\n    Single::forEach(epochs.size(), [&](UInt idEpoch)\n    {\n      fileNameVariableList.setVariable(loopVar, epochs.at(idEpoch).mjd());\n\n      grid.values.clear();\n      for(const std::string &name : dataName)\n      {\n        auto var  = file.variable(name);\n        auto dims = var.dimensions();\n\n        std::vector<UInt> start(dims.size(), 0);\n        std::vector<UInt> count;\n        for(auto &dim : dims)\n          count.push_back(dim.length());\n\n        if((dims.size() != 2) && (timeName.empty() || (dims.size() != 3)))\n           throw(Exception(\"variable <\"+name+\"> has wrong dimensions\"));\n\n        if(!timeName.empty() && (dims.size() > 2))\n        {\n          if(dims.at(0) != dimTime)\n            throw(Exception(\"variable <\"+name+\"> must have time as first dimension\"));\n          start.at(0) = idEpoch;\n          count.at(0) = 1;\n        }\n\n        Matrix values = reshape(var.values(start, count), count.at(dims.size()-1), count.at(dims.size()-2));\n        if((dims.at(dims.size()-1) == dimLat) && (dims.at(dims.size()-2) == dimLon))\n          grid.values.push_back(values);\n        else if((dims.at(dims.size()-1) == dimLon) && (dims.at(dims.size()-2) == dimLat))\n          grid.values.push_back(values.trans());\n        else\n           throw(Exception(\"variable <\"+name+\"> must have (\"+latName+\", \"+lonName+\") dimensions\"));\n      }\n\n      writeFileGriddedData(outName(fileNameVariableList), grid);\n    });\n#endif\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/deprecated/sinex2StationPosition.cpp",
    "content": "/***********************************************/\n/**\n* @file sinex2StationPosition.cpp\n*\n* @brief DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\n*\n* @author Sebastian Strasser\n* @date 2016-12-07\n*\n* @deprecated Please use Sinex2StationPositions instead.\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2023-02-16. Please use \\program{Sinex2StationPositions} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"inputOutput/fileSinex.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\n* @ingroup programsConversionGroup */\nclass Sinex2StationPosition\n{\npublic:\n  class Interval\n  {\n  public:\n    std::string solutionId;\n    Time        referenceTime, timeStart, timeEnd;\n    Vector3d    position, velocity;\n\n    Bool operator<(const Interval &other) const {return timeStart < other.timeStart;}\n  };\n\n  class Station\n  {\n  public:\n    std::vector<Interval> intervals;\n    std::vector<Time>     discontinuities;\n\n    Vector3dArc arc(const std::vector<Time> &times, Bool extrapolateForward, Bool extrapolateBackward);\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sinex2StationPosition, SINGLEPROCESS, \"DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\", Deprecated)\nGROOPS_RENAMED_PROGRAM(GnssSinex2StationPosition, Sinex2StationPosition, date2time(2018, 12, 4))\n\n/***********************************************/\n\nvoid Sinex2StationPosition::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameInstrument, fileNameDiscontinuities, fileNameSinex;\n    std::vector<std::string> stationNames;\n    std::string variableLoopStation;\n    TimeSeriesPtr timeSeries;\n    Bool extrapolateForward, extrapolateBackward;\n\n    readConfig(config, \"outputfileInstrument\",     fileNameInstrument,      Config::MUSTSET,   \"\",        \"loop variable is replaced with station name (e.g. wtzz)\");\n    readConfig(config, \"inputfileSinex\",           fileNameSinex,           Config::MUSTSET,   \"\",        \"SINEX file (.snx or .ssc)\");\n    readConfig(config, \"inputfileDiscontinuities\", fileNameDiscontinuities, Config::OPTIONAL,  \"\",        \"discontinuities file per station; loop variable is replaced with station name (e.g. wtzz)\");\n    readConfig(config, \"variableLoopStation\",      variableLoopStation,     Config::DEFAULT,   \"station\", \"variable name for station loop\");\n    readConfig(config, \"stationName\",              stationNames,            Config::OPTIONAL,  \"\",        \"convert only these stations\");\n    readConfig(config, \"timeSeries\",               timeSeries,              Config::DEFAULT,   \"\",        \"compute positions for these epochs based on velocity\");\n    readConfig(config, \"extrapolateForward\",       extrapolateForward,      Config::DEFAULT,   \"0\",       \"also compute positions for epochs after last interval defined in SINEX file\");\n    readConfig(config, \"extrapolateBackward\",      extrapolateBackward,     Config::DEFAULT,   \"0\",       \"also compute positions for epochs before first interval defined in SINEX file\");\n    if(isCreateSchema(config)) return;\n\n    logWarning<<\"DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\"<<Log::endl;\n\n    logStatus<<\"read SINEX file <\"<<fileNameSinex<<\">\"<<Log::endl;\n    std::map<std::string, Station> stations;\n    Sinex sinex;\n    readFileSinex(fileNameSinex, sinex);\n\n    // SOLUTION/EPOCHS\n    // ---------------\n    for(std::string &line : sinex.findBlock(\"SOLUTION/EPOCHS\")->lines)\n    {\n      std::string name = String::lowerCase(String::trim(line.substr(1, 4)));\n      if(stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end())\n        continue;\n\n      Interval interval;\n      interval.solutionId = String::trim(line.substr(9, 4));\n      interval.timeStart  = Sinex::str2time(line, 16, FALSE);\n      interval.timeEnd    = Sinex::str2time(line, 29, TRUE);\n      stations[name].intervals.push_back(interval);\n    }\n    for(auto &station : stations)\n      std::sort(station.second.intervals.begin(), station.second.intervals.end());\n\n    // SOLUTION/ESTIMATE\n    // -----------------\n    for(std::string &line : sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines)\n    {\n      const std::string parameterType = String::trim(line.substr(7, 6));\n      const std::string name          = String::lowerCase(String::trim(line.substr(14, 4)));\n      const std::string solutionId    = String::trim(line.substr(22, 4));\n      const Double      value         = String::toDouble(line.substr(47, 21));\n\n      if((stationNames.size() && std::find(stationNames.begin(), stationNames.end(), name) == stationNames.end()) ||\n         (parameterType != \"STAX\" && parameterType != \"STAY\" && parameterType != \"STAZ\" &&\n          parameterType != \"VELX\" && parameterType != \"VELY\" && parameterType != \"VELZ\"))\n        continue;\n\n      auto interval = std::find_if(stations[name].intervals.begin(), stations[name].intervals.end(), [&](const Interval &i) {return i.solutionId == solutionId;});\n      if(interval == stations[name].intervals.end())\n        throw(Exception(name+\": interval for solutionId \"+solutionId+\" not found\"));\n\n      interval->referenceTime  = Sinex::str2time(line, 27, FALSE);\n      if(     parameterType == \"STAX\") interval->position.x() = value;\n      else if(parameterType == \"STAY\") interval->position.y() = value;\n      else if(parameterType == \"STAZ\") interval->position.z() = value;\n      else if(parameterType == \"VELX\") interval->velocity.x() = value;\n      else if(parameterType == \"VELY\") interval->velocity.y() = value;\n      else if(parameterType == \"VELZ\") interval->velocity.z() = value;\n    }\n\n    // discontinuities\n    // ---------------\n    VariableList fileNameVariableList;\n    if(!fileNameDiscontinuities.empty())\n    {\n      logStatus<<\"read discontinuity files <\"<<fileNameDiscontinuities<<\">\"<<Log::endl;\n      for(const auto &name : stationNames)\n      {\n        fileNameVariableList.setVariable(variableLoopStation, name);\n        try\n        {\n          if(stations.find(name) != stations.end())\n            stations[name].discontinuities = InstrumentFile::read(fileNameDiscontinuities(fileNameVariableList)).times();\n        }\n        catch(...)\n        {\n          logWarning<<name<<\": discontinuity file not found\"<<Log::endl;\n        }\n      }\n    }\n\n    if(stations.size())\n    {\n      logStatus<<\"write instrument files <\"<<fileNameInstrument<<\">\"<<Log::endl;\n      std::vector<Time> times = timeSeries->times();\n      for(auto &&station : stations)\n      {\n        Vector3dArc arc;\n        if(!times.size() && station.second.intervals.size()) // no times given ==> use reference time of last interval\n          arc = station.second.arc({station.second.intervals.back().referenceTime}, extrapolateForward, extrapolateBackward);\n        else\n          arc = station.second.arc(times, extrapolateForward, extrapolateBackward);\n        fileNameVariableList.setVariable(variableLoopStation, station.first);\n        InstrumentFile::write(fileNameInstrument(fileNameVariableList), arc);\n      }\n    }\n    else\n      logInfo<<\"no stations found\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3dArc Sinex2StationPosition::Station::arc(const std::vector<Time> &times, Bool extrapolateForward, Bool extrapolateBackward)\n{\n  try\n  {\n    Vector3dArc arc;\n    if(!intervals.size() || !times.size())\n      return arc;\n    if(!discontinuities.size())\n      discontinuities = {Time(), date2time(2500, 1, 1)};\n\n    // expand first/last interval in case of extrapolation so a simple interval search can be done afterwards for each epoch\n    if(extrapolateBackward && times.front() < intervals.front().timeStart)\n      intervals.front().timeStart = std::max(times.front(), *std::upper_bound(discontinuities.begin(), discontinuities.end(), intervals.front().timeStart));\n    if(extrapolateForward && times.back() >= intervals.back().timeEnd)\n      intervals.back().timeEnd = std::min(times.back()+seconds2time(1), *std::lower_bound(discontinuities.begin(), discontinuities.end(), intervals.back().timeEnd));\n\n    UInt idInterval = 0;\n    for(const auto &time : times)\n    {\n      while(idInterval+1 < intervals.size() && time >= intervals.at(idInterval+1).timeStart)\n        idInterval++;\n\n      if(time < intervals.at(idInterval).timeStart || time >= intervals.at(idInterval).timeEnd)\n        continue; // epoch is outside interval\n\n      Vector3dEpoch epoch;\n      epoch.time = time;\n      epoch.vector3d = intervals.at(idInterval).position + intervals.at(idInterval).velocity * (time-intervals.at(idInterval).referenceTime).mjd()/365.25;\n      arc.push_back(epoch);\n    }\n\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/deprecated/sinex2StationPostSeismicDeformation.cpp",
    "content": "/***********************************************/\n/**\n* @file sinex2StationPostSeismicDeformation.cpp\n*\n* @brief DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\n*\n* @author Sebastian Strasser\n* @date 2018-05-23\n*\n* @deprecated Please use Sinex2StationPositions instead.\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDEPRECATED since 2023-02-16. Please use \\program{Sinex2StationPositions} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n#include \"inputOutput/fileSinex.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\n* @ingroup programsConversionGroup */\nclass Sinex2StationPostSeismicDeformation\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Sinex2StationPostSeismicDeformation, SINGLEPROCESS, \"DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\", Deprecated)\n\n/***********************************************/\n\nvoid Sinex2StationPostSeismicDeformation::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameInstrument, fileNameSinex;\n    TimeSeriesPtr timeSeries;\n    std::string stationName;\n    Bool localLevelFrame;\n\n    readConfig(config, \"outputfileInstrument\", fileNameInstrument, Config::MUSTSET,  \"\",  \"deformation time series\");\n    readConfig(config, \"inputfileSinex\",       fileNameSinex,      Config::MUSTSET,  \"\",  \"ITRF post-seismic deformation SINEX file\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET,  \"\",  \"compute deformation for these epochs\");\n    readConfig(config, \"stationName\",          stationName,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"localLevelFrame\",      localLevelFrame,    Config::DEFAULT,  \"0\", \"output in North, East, Up local-level frame\");\n    if(isCreateSchema(config)) return;\n\n    logWarning<<\"DEPRECATED since 2023-02-16. Please use Sinex2StationPositions instead.\"<<Log::endl;\n\n    std::vector<Time> times = timeSeries->times();\n    Matrix A(times.size(), 4);\n    stationName = String::lowerCase(stationName);\n\n    logStatus<<\"read SINEX file <\"<<fileNameSinex<<\">\"<<Log::endl;\n    Sinex sinex;\n    readFileSinex(fileNameSinex, sinex);\n\n    const std::vector<std::string> &lines = sinex.findBlock(\"SOLUTION/ESTIMATE\")->lines;\n    for(UInt i=0; i<lines.size(); i+=2)\n    {\n      const std::string siteCode = String::lowerCase(String::trim(lines.at(i).substr(14, 4)));\n      if(siteCode != stationName)\n        continue;\n\n      const std::string parameterType1 = String::trim(lines.at(i).substr(7, 6));\n      const std::string parameterType2 = String::trim(lines.at(i+1).substr(7, 6));\n      if(parameterType1.front() != 'A' || parameterType2.front() != 'T')\n        throw(Exception(i%\"incorrect parameter pair at index %i: \"s+parameterType1+\" and \"+parameterType2));\n\n      const Double amplitude      = String::toDouble(lines.at(i).substr(47, 21));\n      const Double relaxationTime = String::toDouble(lines.at(i+1).substr(47, 21));\n      const Double referenceTime  = Sinex::str2time(lines.at(i), 27, FALSE).decimalYear();\n\n      UInt col = 3; // default 'U' oder 'H'\n      if(parameterType1.back() == 'N') col = 1;\n      else if(parameterType1.back() == 'E') col = 2;\n\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      {\n        if(times.at(idEpoch).decimalYear() < referenceTime)\n          continue;\n\n        if(parameterType1.substr(1,3) == \"EXP\")\n          A(idEpoch, col) += amplitude * (1. - std::exp(-(times.at(idEpoch).decimalYear()-referenceTime)/relaxationTime));\n        else if(parameterType1.substr(1,3) == \"LOG\")\n          A(idEpoch, col) += amplitude * std::log(1. + (times.at(idEpoch).decimalYear()-referenceTime) /relaxationTime);\n        else\n          throw(Exception(i%\"unknown parameter type at index %i: \"s+parameterType1));\n      }\n    }\n\n    if(!localLevelFrame)\n    {\n      const std::vector<std::string> &stationInfos = sinex.findBlock(\"SITE/ID\")->lines;\n      auto iter = std::find_if(stationInfos.begin(), stationInfos.end(), [&](const std::string &s){return String::lowerCase(s.substr(1,4)) == stationName;});\n      if(iter != stationInfos.end())\n      {\n        const Double longitude = String::toDouble(iter->substr(44, 3)) + String::toDouble(iter->substr(48, 2))/60 + String::toDouble(iter->substr(51, 4))/3600;\n        const Double latitude  = String::toDouble(iter->substr(56, 3)) + (String::startsWith(String::trim(iter->substr(56, 3)), \"-\") ? -1 : 1) * (String::toDouble(iter->substr(60, 2))/60 + String::toDouble(iter->substr(63, 4))/3600);\n        const Transform3d lnof2trf = localNorthEastUp(polar(Angle(longitude*DEG2RAD), Angle(latitude*DEG2RAD), 1.));\n        copy(A.column(1,3) * lnof2trf.matrix().trans(), A.column(1,3));\n      }\n    }\n\n    logStatus<<\"write Instrument file <\"<<fileNameInstrument<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameInstrument, Arc(times, A, Epoch::VECTOR3D));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonAdmittanceInterpolation.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonAdmittanceInterpolation.cpp\n*\n* @brief Visualize the interpolation of the minor tides.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-05-13\n* update 2012-08-02 (DR): write TGP amplitudes in 2nd column\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nTo visualize the interpolation of the minor tides.\nThe output is a \\file{matrix}{matrix} with the first column containing the tidal frequency,\nthe second column is the tide generating amplitude (from \\configFile{inputfileTideGeneratingPotential}{tideGeneratingPotential}), and the following\ncolumns the contribution of the major tides to the this tidal frequency as defined in in \\configFile{inputfileAdmittance}{admittance}.\n\n\\fig{!hb}{0.8}{doodsonAdmittanceInterpolation}{fig:doodsonAdmittanceInterpolation}{Linear interpolation of minor tides in the diurnal band.}\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/doodson.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileAdmittance.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Visualize the interpolation of the minor tides.\n* @ingroup programsGroup */\nclass DoodsonAdmittanceInterpolation\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonAdmittanceInterpolation, SINGLEPROCESS, \"visualize the interpolation of the minor tides.\", DoodsonHarmonics)\n\n/***********************************************/\n\nvoid DoodsonAdmittanceInterpolation::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      outName, admittanceName, tgpName;\n\n    readConfig(config, \"outputfile\",                       outName,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileAdmittance\",              admittanceName, Config::MUSTSET,  \"\", \"interpolation of minor constituents\");\n    readConfig(config, \"inputfileTideGeneratingPotential\", tgpName,        Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // read admittace file\n    // -------------------\n    logStatus<<\"read admittance file <\"<<admittanceName<<\">\"<<Log::endl;\n    Admittance admit;\n    readFileAdmittance(admittanceName, admit);\n\n    // read tide generating potential\n    // ------------------------------\n    std::vector<Double> majorAmpl(admit.doodsonMajor.size(), 1.0);\n    std::vector<Double> ampl(admit.doodsonMinor.size(), 1.0);\n    if(!tgpName.empty())\n    {\n      logStatus<<\"read tide generating potential <\"<<tgpName<<\">\"<<Log::endl;\n      TideGeneratingPotential tgp;\n      readFileTideGeneratingPotential(tgpName, tgp);\n\n      for(UInt i=0; i<tgp.size(); i++)\n      {\n        for(UInt k=0; k<admit.doodsonMajor.size(); k++)\n          if(dynamic_cast<Doodson&>(tgp.at(i)) == admit.doodsonMajor.at(k))\n            majorAmpl.at(k) = tgp.at(i).admit();\n        for(UInt k=0; k<admit.doodsonMinor.size(); k++)\n          if(dynamic_cast<Doodson&>(tgp.at(i)) == admit.doodsonMinor.at(k))\n            ampl.at(k) = tgp.at(i).admit();\n      }\n    }\n\n    // Computing\n    // ---------\n    logStatus<<\"computing interpolation\"<<Log::endl;\n    Matrix A(admit.doodsonMinor.size(), 2+admit.doodsonMajor.size());\n    for(UInt i=0; i<admit.doodsonMinor.size(); i++)\n    {\n      A(i,0) = admit.doodsonMinor.at(i).frequency()/(2*PI);\n      A(i,1) = ampl.at(i);\n      for(UInt k=0; k<admit.doodsonMajor.size(); k++)\n        A(i,2+k) = admit.admittance(k,i)/ampl.at(i)*majorAmpl.at(k);\n    }\n\n    // save results\n    // ------------\n    logStatus<<\"write interpolation to file <\"<<outName<<\">\"<<Log::endl;\n    writeFileMatrix(outName, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonAdmittanceTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonAdmittanceTimeSeries.cpp\n*\n* @brief cos/sin multipliers of all major tides.\n* Without admittance this would be a simple cos oscillation.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-05-13\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nTo visualize the interpolation of the minor tides it computes cosine multipliers of all major tides.\nWithout admittance this would be a simple cos oscillation.\nThe \\config{outputfileTimeSeries} is an \\file{instrument file}{instrument} (MISCVALUES) containining the cos of all the major tides.\n\n\\fig{!hb}{0.8}{doodsonAdmittanceTimeSeries}{fig:doodsonAdmittanceTimeSeries}{Cosine of the Mf tidal frequency with modulation from the interpolated minor tides.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileAdmittance.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief cos/sin multipliers of the major tides.\n* Without admittance this would be a simple cos oscillation.\n* @ingroup programsGroup */\nclass DoodsonAdmittanceTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonAdmittanceTimeSeries, SINGLEPROCESS, \"cos/sin multipliers of the major tides.\", DoodsonHarmonics, TimeSeries)\n\n/***********************************************/\n\nvoid DoodsonAdmittanceTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      fileNameOut, fileNameAdmittance;\n    TimeSeriesPtr timeSeries;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameOut,        Config::MUSTSET, \"\", \"MISCVALUES (cos of major tides, ...)\");\n    readConfig(config, \"inputfileAdmittance\",  fileNameAdmittance, Config::MUSTSET, \"\", \"cos/sin multipliers of the major tides\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // read admittace file\n    // -------------------\n    logStatus<<\"read admittance file <\"<<fileNameAdmittance<<\">\"<<Log::endl;\n    Admittance admit;\n    readFileAdmittance(fileNameAdmittance, admit);\n\n    // Computation\n    // -----------\n    logStatus<<\"computing time series\"<<Log::endl;\n    std::vector<Time> times  = timeSeries->times();\n    Matrix doodsonMatrix = Doodson::matrix(admit.doodsonMinor); // Matrix with Doodson multiplicators\n    Matrix A(times.size(), 1+admit.doodsonMajor.size());\n\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      Vector thetaf = doodsonMatrix * Doodson::arguments(times.at(i));\n      Vector cosMinor(thetaf.rows());\n      for(UInt k=0; k<thetaf.rows(); k++)\n        cosMinor(k) = std::cos(thetaf(k));\n      Vector cosMajor = admit.admittance * cosMinor;\n\n      A(i,0) = times.at(i).mjd();\n      for(UInt k=0; k<cosMajor.rows(); k++)\n        A(i,1+k) = cosMajor(k);\n    });\n\n    // save results\n    // ------------\n    logStatus<<\"write time series to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    for(UInt i=0; i<admit.doodsonMajor.size(); i++)\n      logInfo<<\"  \"<<admit.doodsonMajor.at(i).code()<<\" \"<<admit.doodsonMajor.at(i).name()<<Log::endl;\n    writeFileInstrument(fileNameOut, Arc(times, A));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonArguments2TimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonArguments2TimeSeries.cpp\n*\n* @brief time series of doodson/fundamental arguments.\n*\n* @author Torsten Mayer-Guerr\n* @date 2014-10-10\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nTime series of doodson/fundamental arguments.\nThe \\configFile{outputfileTimeSeries}{instrument} contains the six Doodson arguments,\nfollowed by the five fundamental arguments in radians.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/planets.h\"\n#include \"base/doodson.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of doodson/fundamental arguments.\n* @ingroup programsGroup */\nclass DoodsonArguments2TimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonArguments2TimeSeries, SINGLEPROCESS, \"doodson/fundamental arguments.\", DoodsonHarmonics, TimeSeries)\n\n/***********************************************/\n\nvoid DoodsonArguments2TimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      fileNameOut;\n    TimeSeriesPtr timeSeries;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameOut, Config::MUSTSET, \"\", \"each epoch: 6 doodson args, 5 fundamental args [rad]\");\n    readConfig(config, \"timeSeries\",           timeSeries,  Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // Computation\n    // -----------\n    logStatus<<\"computing time series\"<<Log::endl;\n    std::vector<Time> times  = timeSeries->times();\n    Matrix A(times.size(), 1+6+5);\n\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      A(i,0) = times.at(i).mjd();\n      copy(Doodson::arguments(times.at(i)).trans(),    A.slice(i,1,1,6));\n      copy(Planets::fundamentals(times.at(i)).trans(), A.slice(i,7,1,5));\n    });\n\n    // save results\n    // ------------\n    logStatus<<\"write time series to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileInstrument(fileNameOut, Arc(times, A));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonHarmonics2GriddedAmplitudeAndPhase.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonHarmonics2GriddedAmplitudeAndPhase.cpp\n*\n* @brief Amplitude and phase of a harmonic tidal constituent on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads a \\configFile{inputfileDoodsonHarmonics}{doodsonHarmonic} and evaluates a single tidal\nconstituent selected by \\config{dooddson} (Doodson number or Darwin´s name, e.g. 255.555 or M2).\nThis program computes the amplitude and phase from the cos and sin coefficients on\na given \\configClass{grid}{gridType}. The type of functional (e.g gravity anomalies or geoid heights)\ncan be choosen with \\configClass{kernel}{kernelType}.\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nTo visualize the results use \\program{PlotMap}.\n\n\\fig{!hb}{1.}{doodsonHarmonics2GriddedAmplitudeAndPhase}{fig:doodsonHarmonics2GriddedAmplitudeAndPhase}{M2 amplitude and phase of FES2014b.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Amplitude and phase of a harmonic tidal constituent on a grid.\n* @ingroup programsGroup */\nclass DoodsonHarmonics2GriddedAmplitudeAndPhase\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonHarmonics2GriddedAmplitudeAndPhase, PARALLEL, \"amplitude and phase of a harmonic tidal constituent on a grid.\", DoodsonHarmonics, Grid)\n\n/***********************************************/\n\nvoid DoodsonHarmonics2GriddedAmplitudeAndPhase::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName  fileNameGrid;\n    FileName  inputName;\n    Doodson   doodson;\n    Double    factor;\n    SphericalHarmonicsFilterPtr filter;\n    GridPtr   grid;\n    KernelPtr kernel;\n    Double    a, f;\n    UInt      minDegree, maxDegree = INFINITYDEGREE;\n\n    readConfig(config, \"outputfileGrid\",            fileNameGrid, Config::MUSTSET,   \"\",    \"ampl, phase [-pi,pi], cos, sin\");\n    readConfig(config, \"inputfileDoodsonHarmonics\", inputName,    Config::MUSTSET,   \"{groopsDataDir}/tides/\", \"\");\n    readConfig(config, \"doodson\",                   doodson,      Config::MUSTSET,   \"\",    \"tidal constituent\");\n    readConfig(config, \"filter\",                    filter,       Config::DEFAULT,   \"\",    \"\");\n    readConfig(config, \"grid\",                      grid,         Config::MUSTSET,   \"\",    \"\");\n    readConfig(config, \"kernel\",                    kernel,       Config::MUSTSET,   \"\",    \"\");\n    readConfig(config, \"minDegree\",                 minDegree,    Config::DEFAULT,   \"0\",   \"\");\n    readConfig(config, \"maxDegree\",                 maxDegree,    Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"factor\",                    factor,       Config::DEFAULT,   \"1.0\", \"the values on grid are multiplied by this factor\");\n    readConfig(config, \"R\",                         a,            Config::DEFAULT,   STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",         f,            Config::DEFAULT,   STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // read ocean tide file\n    // --------------------\n    logStatus<<\"read doodson harmonics file <\"<<inputName<<\">\"<<Log::endl;\n    SphericalHarmonics harmCos, harmSin;\n    {\n      DoodsonHarmonic d;\n      readFileDoodsonHarmonic(inputName, d);\n\n      Bool found = FALSE;\n      for(UInt i=0; i<d.doodson.size(); i++)\n        if(doodson == d.doodson.at(i))\n        {\n          harmCos = filter->filter(SphericalHarmonics(d.GM, d.R, d.cnmCos.at(i), d.snmCos.at(i)).get(maxDegree, minDegree));\n          harmSin = filter->filter(SphericalHarmonics(d.GM, d.R, d.cnmSin.at(i), d.snmSin.at(i)).get(maxDegree, minDegree));\n          found = TRUE;\n          break;\n        }\n      if(!found)\n        throw(Exception(\"tide \"+doodson.name()+\" not included in <\"+inputName.str()+\">\"));\n    }\n\n    // create grid values\n    // ------------------\n    logStatus<<\"create values on grid (cos, sin)\"<<Log::endl;\n    const std::vector<Vector3d> points = grid->points();\n    std::vector<std::vector<Double>> values(4); // ampl, phase, cos, sin\n    values.at(0).resize(points.size());\n    values.at(1).resize(points.size());\n    values.at(2) = MiscGriddedData::synthesisSphericalHarmonics(harmCos, points, kernel, comm);\n    values.at(3) = MiscGriddedData::synthesisSphericalHarmonics(harmSin, points, kernel, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      for(UInt i=0; i<points.size(); i++)\n      {\n        values.at(2).at(i) *= factor; // cos\n        values.at(3).at(i) *= factor; // sin\n        values.at(0).at(i)  = std::sqrt(pow(values.at(2).at(i),2) + pow(values.at(3).at(i),2)); // ampl\n        values.at(1).at(i)  = 0; // phase\n        if(values.at(0).at(i)>0)\n          values.at(1).at(i) = std::atan2(values.at(3).at(i), values.at(2).at(i));\n      }\n\n      logStatus<<\"write grid <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a,f), points, grid->areas(), values);\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonHarmonics2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonHarmonics2PotentialCoefficients.cpp\n*\n* @brief Write a lot of files with potential coefficients from harmonic tide model.\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-10-24\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThe \\configFile{inputfileDoodsonHarmonics}{doodsonHarmonic} contains a Fourier series of a time variable\ngravitational potential at specific tidal frequencies (tides)\n\\begin{equation}\nV(\\M x,t) = \\sum_{f} V_f^c(\\M x)\\cos(\\theta_f(t)) + V_f^s(\\M x)\\sin(\\theta_f(t)),\n\\end{equation}\nwhere $V_f^c(\\M x)$ and $V_f^s(\\M x)$ are spherical harmonics expansions.\nIf set the expansions are limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThe \\configFile{outputfilePotentialCoefficients}{potentialCoefficients} is not a single file but a series of files.\nFor each spherical harmonics expansion $V_f^c(\\M x)$ and $V_f^s(\\M x)$ a separate file is created\nwhere the variables \\config{variableLoopName}, \\config{variableLoopDoodson}, \\config{variableLoopCosSin} are set accordingly.\nThe file name should contain these variables, e.g. \\verb|coeff.{name}.{doodson}.{cossin}.gfc|.\n\nIf \\config{applyXi} the Doodson-Warburg phase correction (see IERS conventions) is applied to the cos/sin\npotentialCoefficients before.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write a lot of files with PotentialCoefficients from harmonic tide model.\n* @ingroup programsGroup */\nclass DoodsonHarmonics2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonHarmonics2PotentialCoefficients, SINGLEPROCESS, \"write a lot of files with potential coefficients from harmonic tide model.\", DoodsonHarmonics, PotentialCoefficients)\n\n/***********************************************/\n\nvoid DoodsonHarmonics2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut, fileNameIn;\n    FileName    fileNameTGP;\n    std::string nameName, nameDoodson, nameCosSin, nameIndex, nameCount;\n    UInt        minDegree, maxDegree = INFINITYDEGREE;\n    Double      GM, R;\n    Bool        applyXi;\n\n    readConfig(config, \"outputfilePotentialCoefficients\",  fileNameOut, Config::MUSTSET,  \"coeff_{doodson}_{name}_{cossin}.gfc\", \"\");\n    readConfig(config, \"variableLoopName\",                 nameName,    Config::OPTIONAL, \"name\",    \"variable with darwins's name of each constituent\");\n    readConfig(config, \"variableLoopDoodson\",              nameDoodson, Config::OPTIONAL, \"doodson\", \"variable with doodson code of each constituent\");\n    readConfig(config, \"variableLoopCosSin\",               nameCosSin,  Config::OPTIONAL, \"cossin\",  \"variable with 'cos' or 'sin' of each constituent\");\n    readConfig(config, \"variableLoopIndex\",                nameIndex,   Config::OPTIONAL, \"\",        \"variable with index of each constituent (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",                nameCount,   Config::OPTIONAL, \"\",        \"variable with total number of constituents\");\n    readConfig(config, \"inputfileDoodsonHarmonics\",        fileNameIn,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileTideGeneratingPotential\", fileNameTGP, Config::OPTIONAL, \"{groopsDataDir}/tides/generatingTide_HW95.txt\", \"to compute Xi phase correction\");\n    readConfig(config, \"minDegree\",                        minDegree,   Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                               GM,          Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                                R,           Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"applyXi\",                          applyXi,     Config::DEFAULT,  \"0\", \"apply Doodson-Warburg phase correction (see IERS conventions)\");\n    if(isCreateSchema(config)) return;\n\n    // read tide generating potential (TGP)\n    // ------------------------------------\n    TideGeneratingPotential tgp;\n    if(applyXi)\n    {\n      if(fileNameTGP.empty())\n        throw(Exception(\"Need TideGeneratingPotential to compute xi phase correction\"));\n      logStatus<<\"read tide generating potential <\"<<fileNameTGP<<\">\"<<Log::endl;\n      readFileTideGeneratingPotential(fileNameTGP, tgp);\n    }\n\n    // read ocean tide file\n    // --------------------\n    logStatus<<\"read doodson harmonics file <\"<<fileNameIn<<\">\"<<Log::endl;\n    DoodsonHarmonic d;\n    readFileDoodsonHarmonic(fileNameIn, d);\n\n    // write tides\n    // -----------\n    VariableList varList;\n    if(!nameName.empty())    varList.undefineVariable(nameName);\n    if(!nameDoodson.empty()) varList.undefineVariable(nameDoodson);\n    if(!nameCosSin.empty())  varList.undefineVariable(nameCosSin);\n    if(!nameIndex.empty())   varList.undefineVariable(nameIndex);\n    if(!nameCount.empty())   varList.setVariable(nameCount, static_cast<Double>(d.doodson.size()));\n    logStatus<<\"writing potential coefficients to files <\"<<fileNameOut(varList)<<\">\"<<Log::endl;\n\n    for(UInt i=0; i<d.doodson.size(); i++)\n    {\n      logStatus<<\"  \"<<d.doodson.at(i).code()<<\" \"<<d.doodson.at(i).name()<<Log::endl;\n      Double xi = 0.;\n      if(applyXi)\n        xi = tgp.xi(d.doodson.at(i));\n\n      const Matrix cnmCos = d.cnmCos.at(i) * cos(xi) - d.cnmSin.at(i) * sin(xi);\n      const Matrix snmCos = d.snmCos.at(i) * cos(xi) - d.snmSin.at(i) * sin(xi);\n      const Matrix cnmSin = d.cnmCos.at(i) * sin(xi) + d.cnmSin.at(i) * cos(xi);\n      const Matrix snmSin = d.snmCos.at(i) * sin(xi) + d.snmSin.at(i) * cos(xi);\n\n      const SphericalHarmonics harmCos(d.GM, d.R, cnmCos, snmCos);\n      const SphericalHarmonics harmSin(d.GM, d.R, cnmSin, snmSin);\n\n      if(!nameName.empty())    varList.setVariable(nameName, d.doodson.at(i).name());\n      if(!nameDoodson.empty()) varList.setVariable(nameDoodson, d.doodson.at(i).code());\n      if(!nameIndex.empty())   varList.setVariable(nameIndex, static_cast<Double>(i));\n      if(!nameCosSin.empty())  varList.setVariable(nameCosSin, \"cos\");\n      writeFileSphericalHarmonics(fileNameOut(varList), harmCos.get(maxDegree, minDegree, GM, R));\n      if(!nameCosSin.empty())  varList.setVariable(nameCosSin, \"sin\");\n      writeFileSphericalHarmonics(fileNameOut(varList), harmSin.get(maxDegree, minDegree, GM, R));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonHarmonicsCalculateAdmittance.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonHarmonicsCalculateAdmittance.cpp\n*\n* @brief Computes the admittance function from TGP.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-04-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes the admittance function to interpolate minor tides from\ntides given in \\configFile{inputfileDoodsonHarmonics}{doodsonHarmonic}\nusing \\configFile{inputfileTideGeneratingPotential}{tideGeneratingPotential}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"base/tideGeneratingPotential.h\"\n#include \"files/fileAdmittance.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Computes the admittance function from TGP.\n* @ingroup programsGroup */\nclass DoodsonHarmonicsCalculateAdmittance\n{\n  void admitMatrix(UInt degreeInterpolation, UInt degreeExtrapolation, UInt degree, Int order,\n                   const TideGeneratingPotential &tgpMajor, const std::vector<UInt> &majorIdx,\n                   const TideGeneratingPotential &tgp, MatrixSliceRef A) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonHarmonicsCalculateAdmittance, SINGLEPROCESS, \"computes the admittance function from TGP\", DoodsonHarmonics)\n\n/***********************************************/\n\nvoid DoodsonHarmonicsCalculateAdmittance::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameAdmit, fileNameDoodson, fileNameTGP;\n    Double   threshold;\n    UInt     degreeInterpolation, degreeExtrapolation = MAX_UINT;\n    std::vector<Doodson> doodsonExclude;\n\n    readConfig(config, \"outputfileAdmittance\",             fileNameAdmit,       Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileDoodsonHarmonics\",        fileNameDoodson,     Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileTideGeneratingPotential\", fileNameTGP,         Config::OPTIONAL, \"{groopsDataDir}/tides/generatingTide_HW95.txt\", \"TGP\");\n    readConfig(config, \"threshold\",                        threshold,           Config::DEFAULT,  \"1e-4\", \"[m^2/s^2] only interpolate tides with TGP greater than threshold\");\n    readConfig(config, \"degreeInterpolation\",              degreeInterpolation, Config::DEFAULT,  \"1\",    \"polynomial degree for interpolation\");\n    readConfig(config, \"degreeExtrapolation\",              degreeExtrapolation, Config::OPTIONAL, \"1\",    \"polynomial degree for extrapolation\");\n    readConfig(config, \"excludeDoodsonForInterpolation\",   doodsonExclude,      Config::OPTIONAL, R\"([\"164.554\", \"164.555\", \"164.556\", \"164.566\"])\", \"major tides not used for interpolation\");\n    if(isCreateSchema(config)) return;\n\n    // =====================================================\n\n    // read ocean tide file\n    // --------------------\n    logStatus<<\"read doodson harmonics file <\"<<fileNameDoodson<<\">\"<<Log::endl;\n    DoodsonHarmonic d;\n    readFileDoodsonHarmonic(fileNameDoodson, d);\n    if(!std::is_sorted(d.doodson.begin(), d.doodson.end()))\n      throw(Exception(\"must be sorted\"));\n\n    logStatus<<\"read tide generating potential <\"<<fileNameTGP<<\">\"<<Log::endl;\n    TideGeneratingPotential tgp;\n    readFileTideGeneratingPotential(fileNameTGP, tgp);\n\n    // =====================================================\n\n    auto isInList = [](const std::vector<Doodson> &list, const Doodson &doodson)\n    {\n      return std::find(list.begin(), list.end(), doodson) != list.end();\n    };\n\n    // eliminate small amplitudes (except all major tides)\n    tgp.erase(std::remove_if(tgp.begin(), tgp.end(), [&](auto &t)\n                             {return (t.amplitude() < threshold) && !isInList(d.doodson, t);}), tgp.end());\n\n    // add missing tides with zero admittance\n    for(auto &dood: d.doodson)\n    {\n      auto iter = std::lower_bound(tgp.begin(), tgp.end(), dood, [](const Doodson &tgp, const Doodson &dood){return tgp < dood;});\n      if((iter == tgp.end()) || (dynamic_cast<const Doodson&>(*iter) != dood))\n        tgp.insert(iter, TideGeneratingConstituent(dood, 0, 0., 0.));\n    }\n\n    // set tgp to zero for exluding doodson\n    for(auto &t : tgp)\n      if(isInList(doodsonExclude, t))\n        t.c = t.s = 0.;\n\n    TideGeneratingPotential tgpMajor;\n    std::vector<UInt>       idxMajor;\n    for(UInt i=0; i<tgp.size(); i++)\n      if(isInList(d.doodson, tgp.at(i)))\n      {\n        tgpMajor.push_back(tgp.at(i));\n        idxMajor.push_back(i);\n      }\n    if(tgpMajor.size() != d.doodson.size())\n      throw(Exception(\"major tides not unique\"));\n\n    // =====================================================\n\n    // interpolate each dgeree and order\n    // ---------------------------------\n    Matrix A(d.doodson.size(), tgp.size());\n    logStatus<<\"Interpolation  from \"<<A.rows()<<\" major tides to \"<<A.columns()<<\" tidal frequencies\"<<Log::endl;\n    for(UInt degree=2; degree<=3; degree++)\n      for(UInt order=0; order<=degree; order++)\n      {\n        TideGeneratingPotential tgpMajorBand;\n        std::vector<UInt>       idxMajorBand;\n        for(UInt i=0; i<tgpMajor.size(); i++)\n          if((tgpMajor.at(i).degree == degree) && (tgpMajor.at(i).d[0] == Int(order)) && tgpMajor.at(i).admit())\n          {\n            tgpMajorBand.push_back(tgpMajor.at(i));\n            idxMajorBand.push_back(i);\n          }\n\n        if(tgpMajorBand.size())\n          admitMatrix(degreeInterpolation, degreeExtrapolation, degree, order, tgpMajorBand, idxMajorBand, tgp, A);\n      }\n\n    // use major tides directly\n    // ------------------------\n    for(UInt k=0; k<d.doodson.size(); k++)\n    {\n      A.column(idxMajor.at(k)).setNull();\n      A(k, idxMajor.at(k)) = 1.0;\n    }\n\n    // delete unused minor tides\n    // -------------------------\n    UInt countUnused = 0;\n    for(UInt i=0; i<A.columns(); i++)\n      if(isStrictlyZero(A.column(i)))\n       countUnused++;\n    Matrix Afull(A);\n    A = Matrix(d.doodson.size(), Afull.columns()-countUnused);\n    UInt idx = 0;\n    for(UInt i=0; i<Afull.columns(); i++)\n      if(isStrictlyZero(Afull.column(i)))\n        tgp.erase(tgp.begin()+idx);\n      else\n        copy(Afull.column(i), A.column(idx++));\n\n    // =====================================================\n\n    // write results\n    // -------------\n    logStatus<<\"writing admittance file <\"<<fileNameAdmit<<\">\"<<Log::endl;\n    Admittance admit;\n    admit.doodsonMajor.insert(admit.doodsonMajor.begin(), tgpMajor.begin(), tgpMajor.end());\n    admit.doodsonMinor.insert(admit.doodsonMinor.begin(), tgp.begin(), tgp.end());\n    admit.admittance = A;\n    writeFileAdmittance(fileNameAdmit, admit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/************************************************/\n\nvoid DoodsonHarmonicsCalculateAdmittance::admitMatrix(UInt degreeInterpolation, UInt degreeExtrapolation, UInt degree, Int order,\n                                                      const TideGeneratingPotential &tgpMajor, const std::vector<UInt> &majorIdx,\n                                                      const TideGeneratingPotential &tgp, MatrixSliceRef A) const\n{\n  try\n  {\n    // extrapolation polynomial\n    Matrix B;\n    if(degreeExtrapolation != MAX_UINT)\n    {\n      degreeExtrapolation = std::min(degreeExtrapolation, tgpMajor.size()-1);\n      B = Matrix(tgpMajor.size(), degreeExtrapolation+1);\n      for(UInt i=0; i<tgpMajor.size(); i++)\n        for(UInt n=0; n<=degreeExtrapolation; n++)\n          B(i, n) = std::pow(tgpMajor.at(i).frequency(), n);\n      Matrix L(tgpMajor.size(), tgpMajor.size());\n      for(UInt i=0; i<L.columns(); i++)\n        L(i, i) = 1./tgpMajor.at(i).admit();\n      B = leastSquares(B, L);\n    }\n\n    // interpolation polynomial\n    degreeInterpolation = std::min(degreeInterpolation, tgpMajor.size()-1);\n    std::vector<Matrix> P(tgpMajor.size()-degreeInterpolation);\n    for(UInt i=0; i<P.size(); i++)\n    {\n      P.at(i) = Matrix(degreeInterpolation+1, degreeInterpolation+1);\n      for(UInt k=0; k<=degreeInterpolation; k++)\n        for(UInt n=0; n<=degreeInterpolation; n++)\n          P.at(i)(k, n) = std::pow(tgpMajor.at(k+i).frequency(), n);\n      inverse(P.at(i));\n      for(UInt k=0; k<=degreeInterpolation; k++)\n        P.at(i).column(k) *= 1./tgpMajor.at(k+i).admit();\n    }\n\n    UInt idx = 0;\n    for(UInt i=0; i<tgp.size(); i++)\n      if((tgp.at(i).degree == degree) && (tgp.at(i).d[0] == order) && tgp.at(i).admit())\n      {\n        const Double freq = tgp.at(i).frequency();\n        if((idx < P.size()-1) && (freq > tgpMajor.at(idx+(degreeInterpolation+1)/2).frequency()))\n          idx++;\n\n        const Double dfreq = PI/27.3216; // [rad/day] half tidal group\n        if(((tgpMajor.at(0).frequency()-dfreq <= freq) && (freq <= tgpMajor.back().frequency()+dfreq)) || (degreeExtrapolation == MAX_UINT))\n        {\n          // interpolation\n          for(UInt n=0; n<=degreeInterpolation; n++)\n            for(UInt k=0; k<=degreeInterpolation; k++)\n              A(majorIdx.at(k+idx), i) += tgp.at(i).admit() * std::pow(freq, n) * P.at(idx)(n, k);\n        }\n        else\n        {\n          // extrapolation\n          for(UInt n=0; n<B.rows(); n++)\n            for(UInt k=0; k<tgpMajor.size(); k++)\n              A(majorIdx.at(k), i) += tgp.at(i).admit() * std::pow(freq, n) * B(n, k);\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/doodsonHarmonicsChangePartialTides.cpp",
    "content": "/***********************************************/\n/**\n* @file doodsonHarmonicsChangePartialTides.cpp\n*\n* @brief Change partial tides in doodsonHarmonics file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2024-11-07\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nReads a file \\configFile{inputfileDoodsonHarmonic}{doodsonHarmonic} and write it to\n\\configFile{outputfileDoodsonHarmonics}{doodsonHarmonic}. If set the spherical harmonics\nexpansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusivly.\nThe \\configClass{useDoodson}{doodson} and \\configClass{ignoreDoodson}{doodson} can be used\nto filter the partial types that will be exported.\nAdditional partial tides can be interpolated using the file \\configFile{inputfileAdmittance}{admittance}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileAdmittance.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Change partial tides in doodsonHarmonics file.\n* @ingroup programsGroup */\nclass DoodsonHarmonicsChangePartialTides\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DoodsonHarmonicsChangePartialTides, SINGLEPROCESS, \"change partial tides in doodsonHarmonics file\", DoodsonHarmonics)\n\n/***********************************************/\n\nvoid DoodsonHarmonicsChangePartialTides::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n    FileName fileNameAdmit;\n    std::vector<Doodson> useDoodson, ignoreDoodson;\n    UInt     minDegree, maxDegree = INFINITYDEGREE;\n    Double   GM = 0, R = 0;\n\n    readConfig(config, \"outputfileDoodsonHarmonics\", fileNameOut,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileDoodsonHarmonics\",  fileNameIn,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileAdmittance\",        fileNameAdmit, Config::OPTIONAL, \"\", \"interpolation of minor constituents\");\n    readConfig(config, \"useDoodson\",                 useDoodson,    Config::OPTIONAL, \"\", \"use only these partial tides (additional tides will be interpolated)\");\n    readConfig(config, \"ignoreDoodson\",              ignoreDoodson, Config::OPTIONAL, \"\", \"ignore these partial tides\");\n    readConfig(config, \"minDegree\",                  minDegree,     Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",                  maxDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                         GM,            Config::OPTIONAL, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                          R,             Config::OPTIONAL, STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read doodson harmonics file <\"<<fileNameIn<<\">\"<<Log::endl;\n    DoodsonHarmonic d;\n    readFileDoodsonHarmonic(fileNameIn, d);\n    for(UInt i=0; i<d.doodson.size(); i++)\n    {\n      SphericalHarmonics harmCos = SphericalHarmonics(d.GM, d.R, d.cnmCos.at(i), d.snmCos.at(i)).get(maxDegree, minDegree, GM, R);\n      SphericalHarmonics harmSin = SphericalHarmonics(d.GM, d.R, d.cnmSin.at(i), d.snmSin.at(i)).get(maxDegree, minDegree, GM, R);\n      d.cnmCos.at(i) = harmCos.cnm();\n      d.snmCos.at(i) = harmCos.snm();\n      d.cnmSin.at(i) = harmSin.cnm();\n      d.snmSin.at(i) = harmSin.snm();\n    }\n\n    Admittance admit;\n    admit.doodsonMajor = admit.doodsonMinor = d.doodson;\n    admit.admittance   = identityMatrix(d.doodson.size());\n    if(!fileNameAdmit.empty())\n    {\n      logStatus<<\"read admittance file <\"<<fileNameAdmit<<\">\"<<Log::endl;\n      readFileAdmittance(fileNameAdmit, admit);\n    }\n\n    logStatus<<\"calculate partial tides\"<<Log::endl;\n    if(!useDoodson.size())\n      useDoodson = d.doodson;\n    std::sort(useDoodson.begin(), useDoodson.end());\n    std::vector<Doodson> doodsonNew;\n    std::vector<Matrix>  cnmCos, snmCos;\n    std::vector<Matrix>  cnmSin, snmSin;\n    for(auto &dood : useDoodson)\n      if(std::find(ignoreDoodson.begin(), ignoreDoodson.end(), dood) == ignoreDoodson.end())\n      {\n        UInt idx = std::distance(admit.doodsonMinor.begin(), std::find(admit.doodsonMinor.begin(), admit.doodsonMinor.end(), dood));\n        if(idx >= admit.doodsonMinor.size())\n        {\n          logWarning<<\"Unable to interpolate \"<<dood.code()<<\" (\"<<dood.name()<<\"), skipped.\"<<Log::endl;\n          continue;\n        }\n        cnmCos.push_back(Matrix(d.cnmCos.front().rows(), Matrix::SYMMETRIC, Matrix::LOWER));\n        snmCos.push_back(Matrix(d.cnmCos.front().rows(), Matrix::SYMMETRIC, Matrix::LOWER));\n        cnmSin.push_back(Matrix(d.cnmCos.front().rows(), Matrix::SYMMETRIC, Matrix::LOWER));\n        snmSin.push_back(Matrix(d.cnmCos.front().rows(), Matrix::SYMMETRIC, Matrix::LOWER));\n        for(UInt k=0; k<admit.doodsonMajor.size(); k++)\n        {\n          cnmCos.back() += admit.admittance(k, idx) * d.cnmCos.at(k);\n          snmCos.back() += admit.admittance(k, idx) * d.snmCos.at(k);\n          cnmSin.back() += admit.admittance(k, idx) * d.cnmSin.at(k);\n          snmSin.back() += admit.admittance(k, idx) * d.snmSin.at(k);\n        }\n        doodsonNew.push_back(dood);\n      }\n\n    logStatus<<\"writing doodson harmonics <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileDoodsonHarmonic(fileNameOut, DoodsonHarmonic(d.GM, d.R, doodsonNew, cnmCos, snmCos, cnmSin, snmSin));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/modelEquilibriumTide.cpp",
    "content": "/***********************************************/\n/**\n* @file modelEquilibriumTide.cpp\n*\n* @brief Equilibrium tide, taking the effect of loading and self attraction into account.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-05-21\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes the equilibrium ocean tide of the long periodic \\config{tideGeneratingPotential}.\nThe spherical harmonics expansion up to \\config{maxDegree} with \\config{GM} and \\config{R}\nis estimated using a least squares adjustment.\n\nThe \\configFile{inputfileDensityGrid}{griddedData} must be a global regular grid with the\nvertically averaged seawater density over the ocean and zero over land.\n\nIt takes iteratively self attraction and loading into account using the Love numbers\n\\configFile{inputfilePotentialLoadLoveNumber}{matrix} and\n\\configFile{inputfileDeformationLoadLoveNumber}{matrix}.\n\nAdditionally the effects of the solid Earth tide are considered,\nboth the gravitational (Love numbers \\config{k20}, \\config{k20plus})\nand the geometrical (Love numbers \\config{h20,0}, \\config{h20,2}) effect.\n\nSee also \\program{PotentialCoefficients2DoodsonHarmonics}.\n\n\\fig{!hb}{0.8}{modelEquilibriumTide}{fig:modelEquilibriumTide}{Equilibrium tide of SA constituent}\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"base/planets.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"misc/miscGriddedData.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Equilibrium tide, taking the effect of loading and self attraction into account.\n* @ingroup programsGroup */\nclass ModelEquilibriumTide\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ModelEquilibriumTide, PARALLEL, \"equilibrium tide, taking the effect of loading and self attraction into account.\", DoodsonHarmonics, Simulation)\n\n/***********************************************/\n\nvoid ModelEquilibriumTide::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName  fileNameCoeff;\n    FileName  fileNameDensityGrid;\n    FileName  loadName, deformationName;\n    UInt      maxDegree;\n    Double    GM, R;\n    Double    TGP, k20, k20plus, h20_0, h20_2;\n    UInt      iterationCount;\n\n    readConfig(config, \"outputfilePotentialCoefficients\",    fileNameCoeff,       Config::MUSTSET, \"\",                \"includes the loading\");\n    readConfig(config, \"maxDegree\",                          maxDegree,           Config::DEFAULT, \"120\",             \"\");\n    readConfig(config, \"GM\",                                 GM,                  Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                                  R,                   Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"inputfileDensityGrid\",               fileNameDensityGrid, Config::MUSTSET, \"\",                \"[kg/m^3] density of sea water, zero over land\");\n    readConfig(config, \"tideGeneratingPotential\",            TGP,                 Config::MUSTSET, \"-0.0856534056\",   \"[m^2/s^2]\");\n    readConfig(config, \"k20\",                                k20,                 Config::DEFAULT, \"0.30190\",         \"earth tide love number\");\n    readConfig(config, \"k20plus\",                            k20plus,             Config::DEFAULT, \"-0.00089\",        \"earth tide love number\");\n    readConfig(config, \"h20_0\",                              h20_0,               Config::DEFAULT, \"0.6078\",          \"earth tide love number\");\n    readConfig(config, \"h20_2\",                              h20_2,               Config::DEFAULT, \"-0.0006\",         \"earth tide love number\");\n    readConfig(config, \"inputfilePotentialLoadLoveNumber\",   loadName,            Config::MUSTSET, \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"\");\n    readConfig(config, \"inputfileDeformationLoadLoveNumber\", deformationName,     Config::MUSTSET, \"{groopsDataDir}/loading/deformationLoveNumbers_CE_Gegout97.txt\", \"\");\n    readConfig(config, \"iterationCount\",                     iterationCount,      Config::DEFAULT, \"5\",               \"\");\n    if(isCreateSchema(config)) return;\n\n    // =======================================\n\n    // init grid\n    // ---------\n    logStatus<<\"read density grid from file <\"<<fileNameDensityGrid<<\">\"<<Log::endl;\n    GriddedDataRectangular grid;\n    readFileGriddedData(fileNameDensityGrid, grid);\n    MiscGriddedData::printStatistics(grid);\n    Matrix density;\n    std::swap(density, grid.values.at(0));\n\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius, dLambda, dPhi;\n    grid.geocentric(lambda, phi, radius);\n    grid.areaElements(dLambda, dPhi);\n\n    // check assumption: same area for all longitudes\n    Bool failed = FALSE;\n    for(UInt k=0; k<lambda.size()-1; k++)\n      if(!failed && (std::fabs(dLambda.at(k+1)-dLambda.at(k)) > 1e-3*std::fabs(dLambda.at(k))))\n      {\n        logWarningOnce<<\"assumption of the same area/weight for all longitudes not fulfilled\"<<Log::endl;\n        failed = TRUE;\n      }\n\n    Double totalArea = 0;\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=0; k<lambda.size(); k++)\n        totalArea += dPhi.at(i) * dLambda.at(k) * std::pow(radius.at(i), 2);\n\n    Double oceanArea = 0;\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=0; k<lambda.size(); k++)\n        if(density(i, k) > 0)\n          oceanArea += dPhi.at(i) * dLambda.at(k) * std::pow(radius.at(i), 2);\n    logInfo<<\"  ocean area:   \"<<oceanArea/totalArea*100<<\"% of earth surface\"<<Log::endl;\n\n    Double meanDensity = 0;\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=0; k<lambda.size(); k++)\n        if(density(i, k) > 0)\n          meanDensity += density(i, k) * dPhi.at(i) * dLambda.at(k) * std::pow(radius.at(i), 2);\n    meanDensity /= oceanArea;\n    logInfo<<\"  mean density: \"<<meanDensity<<\" kg/m^2\"<<Log::endl;\n\n    // =======================================\n\n    // deformation load love numbers\n    // -----------------------------\n    Matrix load_kn, load_hnln;\n    readFileMatrix(deformationName, load_hnln);\n    readFileMatrix(loadName,        load_kn);\n\n    // =======================================\n\n    // init tgp\n    // --------\n    logStatus<<\"Tide raisung potential: TGP + Solid Earth Tide\"<<Log::endl;\n    Matrix height0(phi.size(), lambda.size());\n    Parallel::forEach(phi.size(), [&](UInt i)\n    {\n      const Vector3d p       = polar(Angle(0), phi.at(i), radius.at(i));\n      const Double   gravity = Planets::normalGravity(p);\n      Matrix         Cnm, Snm;\n      SphericalHarmonics::CnmSnm((1./radius.at(i))*p, 4, Cnm, Snm);\n\n      Double h0 =     std::pow(radius.at(i)/DEFAULT_R, 2) * TGP * Cnm(2,0) / gravity;           // direct tide\n      h0 += k20     * std::pow(DEFAULT_R/radius.at(i), 3) * TGP * Cnm(2,0) / gravity;           // earth tide potential\n      h0 += k20plus * std::pow(DEFAULT_R/radius.at(i), 5) * TGP * Cnm(4,0) / gravity;           // earth tide potential\n      h0 -= (h20_0 + h20_2*Cnm(2,0)/std::sqrt(5)) * std::pow(DEFAULT_R, 2)/GM * TGP * Cnm(2,0); // displacement\n      for(UInt k=0; k<lambda.size(); k++)\n        if(density(i, k) > 0)\n          height0(i, k) = h0;\n    }, comm);\n    Parallel::reduceSum(height0, 0, comm);\n    Parallel::broadCast(height0, 0, comm);\n\n    // =======================================\n\n    Matrix tide = height0;\n    Double massDiff = 0;\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=0; k<lambda.size(); k++)\n        if(density(i, k) > 0)\n          massDiff += tide(i, k) * density(i, k) * dPhi.at(i) * dLambda.at(k) * std::pow(radius.at(i), 2);\n    logInfo<<\"  total Mass change =  \"<<1000*massDiff/meanDensity/oceanArea<<\" mm\"<<Log::endl;\n    for(UInt i=0; i<phi.size(); i++)\n      for(UInt k=0; k<lambda.size(); k++)\n        if(density(i, k) > 0)\n          tide(i,k) -= massDiff/meanDensity/oceanArea;\n\n    // ========================================================\n\n    // precompute cos(m*lambda), sin(m*lambda)\n    Matrix cosml(lambda.size(), maxDegree+1);\n    Matrix sinml(lambda.size(), maxDegree+1);\n    for(UInt m=0; m<=maxDegree; m++)\n      for(UInt k=0; k<lambda.size(); k++)\n      {\n        cosml(k, m) = std::cos(m*static_cast<Double>(lambda.at(k)));\n        sinml(k, m) = std::sin(m*static_cast<Double>(lambda.at(k)));\n      }\n\n    // system of normal equations (order by order)\n    std::vector<Matrix> N, n;\n    N.push_back(Matrix(maxDegree+1, Matrix::SYMMETRIC));\n    n.push_back(Matrix(maxDegree+1, 1));\n    for(UInt m=1; m<=maxDegree; m++)\n    {\n      N.push_back(Matrix(2*(maxDegree+1-m), Matrix::SYMMETRIC));\n      n.push_back(Matrix(2*(maxDegree+1-m), 1));\n    }\n\n    SphericalHarmonics harm;\n    for(UInt iter=0; iter<iterationCount; iter++)\n    {\n      logStatus<<iter+1<<\". iteration\"<<Log::endl;\n      logStatus<<\"  compute spherical harmonics\"<<Log::endl;\n      // least squares adjustment order by order\n      for(UInt m=0; m<n.size(); m++)\n        n.at(m).setNull();\n\n      Parallel::forEach(phi.size(), [&](UInt i)\n      {\n        Vector l = tide.row(i).trans();\n        for(UInt k=0; k<lambda.size(); k++)\n          l(k) *= density(i, k);\n\n        // legendre functions with kernel coefficients\n        Matrix Pnm = SphericalHarmonics::Pnm(Angle(0.5*PI-phi.at(i)), radius.at(i)/R, maxDegree);\n        for(UInt n=0; n<=maxDegree; n++)\n          Pnm.slice(n, 0, 1, n+1) *= GM/R/(4.*PI*GRAVITATIONALCONSTANT*radius.at(i)) * (2*n+1);\n\n        const Double weight = dPhi.at(i) * dLambda.at(0)/(4*PI) * std::pow(radius.at(i)/R, 2); // assume same area for all longitudes\n        Matrix A = cosml.column(0) * Pnm.column(0).trans();\n        if(iter == 0)\n          rankKUpdate(weight, A, N.at(0));\n        matMult(weight, A.trans(), l, n.at(0));\n        for(UInt m=1; m<=maxDegree; m++)\n        {\n          Matrix A(lambda.size(), 2*(maxDegree+1-m));\n          matMult(1.0, cosml.column(m), Pnm.slice(m, m, maxDegree+1-m, 1).trans(), A.column(0, maxDegree+1-m));\n          matMult(1.0, sinml.column(m), Pnm.slice(m, m, maxDegree+1-m, 1).trans(), A.column(maxDegree+1-m, maxDegree+1-m));\n          if(iter == 0)\n            rankKUpdate(weight, A, N.at(m));\n          matMult(weight, A.trans(), l, n.at(m));\n        }\n      }, comm);\n\n      if(iter == 0)\n        for(UInt m=0; m<=maxDegree; m++)\n          Parallel::reduceSum(N.at(m), 0, comm);\n      for(UInt m=0; m<=maxDegree; m++)\n        Parallel::reduceSum(n.at(m), 0, comm);\n\n      // solve normals\n      // -------------\n      Matrix cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      Matrix snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n      if(Parallel::isMaster(comm))\n      {\n        copy(solve(Matrix(N.at(0)), n.at(0)), cnm.column(0));\n        for(UInt m=1; m<=maxDegree; m++)\n        {\n          const Vector x = solve(Matrix(N.at(m)), n.at(m));\n          copy(x.row(0,             maxDegree+1-m), cnm.slice(m, m, maxDegree+1-m, 1));\n          copy(x.row(maxDegree+1-m, maxDegree+1-m), snm.slice(m, m, maxDegree+1-m, 1));\n        }\n      } // if(Parallel::isMaster(comm))\n      Parallel::broadCast(cnm, 0, comm);\n      Parallel::broadCast(snm, 0, comm);\n      logInfo<<\"  c00 change =  \"<<1000*R*cnm(0,0)<<\" mm\"<<Log::endl;\n      cnm(0,0) = 0;\n      harm = SphericalHarmonics(GM, R, cnm, snm);\n\n      // synthesis spherical harmonics\n      // -----------------------------\n      logStatus<<\"  compute loading and self attraction\"<<Log::endl;\n      Matrix lsa(phi.size(), lambda.size());\n      Parallel::forEach(phi.size(), [&](UInt i) // Compute Legendre functions for each phi (row)\n      {\n        const Double gravity = Planets::normalGravity(polar(Angle(0), phi.at(i), radius.at(i)));\n        Matrix Pnm = SphericalHarmonics::Pnm(Angle(PI/2-phi.at(i)), radius.at(i)/R, maxDegree);\n        for(UInt n=0; n<=maxDegree; n++)\n          Pnm.slice(n,0,1,n+1) *= GM/R*(1.+load_kn(n,0)-load_hnln(n,0))/gravity;\n\n        Vector cm(maxDegree+1), sm(maxDegree+1);\n        cm(0) = inner(cnm.column(0), Pnm.column(0));\n        for(UInt m=1; m<=maxDegree; m++)\n        {\n          cm(m) = inner(cnm.slice(m, m, maxDegree-m+1, 1), Pnm.slice(m, m, maxDegree-m+1, 1));\n          sm(m) = inner(snm.slice(m, m, maxDegree-m+1, 1), Pnm.slice(m, m, maxDegree-m+1, 1));\n        }\n        Vector row = cosml * cm + sinml * sm;\n\n        for(UInt k=0; k<lambda.size(); k++)\n          if(density(i, k) > 0)\n            lsa(i, k) += row(k);\n      }, comm);\n      Parallel::reduceSum(lsa, 0, comm);\n\n      if(Parallel::isMaster(comm))\n      {\n        // compute new tide\n        Matrix tideOld = tide;\n        tide = height0 + lsa;\n\n        // mass conservation\n        Double massDiff = 0;\n        for(UInt i=0; i<phi.size(); i++)\n          for(UInt k=0; k<lambda.size(); k++)\n            if(density(i, k) > 0)\n              massDiff += tide(i, k) * density(i, k) * dPhi.at(i) * dLambda.at(k) * std::pow(radius.at(i), 2);\n        for(UInt i=0; i<phi.size(); i++)\n          for(UInt k=0; k<lambda.size(); k++)\n            if(density(i, k) > 0)\n              tide(i,k) -= massDiff/meanDensity/oceanArea;\n\n        logInfo<<\"  max. change in iteration =  \"<<1000*maxabs(tide-tideOld)<<\" mm\"<<Log::endl;\n      }\n\n      Parallel::broadCast(tide, 0, comm);\n    } // for(iter)\n\n    // =======================================\n\n    // add loading potential\n    // ---------------------\n    if(Parallel::isMaster(comm))\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        harm.cnm().row(n) *= 1.+load_kn(n,0);\n        harm.snm().row(n) *= 1.+load_kn(n,0);\n      }\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"writing potential coefficients to file <\"<<fileNameCoeff<<\">\"<<Log::endl;\n      writeFileSphericalHarmonics(fileNameCoeff, harm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/doodsonHarmonics/potentialCoefficients2DoodsonHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file potentialCoefficients2DoodsonHarmonics.cpp\n*\n* @brief DoodsonHarmonic file from a list of cos/sin potentialCoefficients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2007-10-24\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate a \\file{DoodsonHarmonic file}{doodsonHarmonic} from a list of\ncos/sin \\file{potentialCoefficients}{potentialCoefficients} for given \\config{doodson}\n(Doodson number or Darwin´s name, e.g. 255.555 or M2) tidal constituents.\nIf \\config{applyXi} the Doodson-Warburg phase correction (see IERS conventions) is applied before.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/doodson.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief DoodsonHarmonic file from a list of cos/sin potentialCoefficients.\n* @ingroup programsGroup */\nclass PotentialCoefficients2DoodsonHarmonics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  class Constituent\n  {\n    public:\n    Doodson  doodson;\n    FileName cosName, sinName;\n  };\n};\n\nGROOPS_REGISTER_PROGRAM(PotentialCoefficients2DoodsonHarmonics, SINGLEPROCESS, \"doodsonHarmonic file from cos/sin potentialCoefficients.\", DoodsonHarmonics, PotentialCoefficients)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, PotentialCoefficients2DoodsonHarmonics::Constituent &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"doodson\",                           var.doodson, Config::MUSTSET, \"\", \"\");\n  readConfig(config, \"inputfileCosPotentialCoefficients\", var.cosName, Config::MUSTSET, \"\", \"\");\n  readConfig(config, \"inputfileSinPotentialCoefficients\", var.sinName, Config::MUSTSET, \"\", \"\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid PotentialCoefficients2DoodsonHarmonics::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    FileName fileNameTGP;\n    std::vector<Constituent> constituent;\n    UInt     minDegree, maxDegree = INFINITYDEGREE;\n    Double   GM, R;\n    Bool     applyXi;\n\n    readConfig(config, \"outputfileDoodsonHarmonics\",       fileNameOut, Config::MUSTSET,   \"\",  \"\");\n    readConfig(config, \"inputfileTideGeneratingPotential\", fileNameTGP, Config::OPTIONAL, \"{groopsDataDir}/tides/generatingTide_HW95.txt\", \"to compute Xi phase correction\");\n    readConfig(config, \"constituent\",                      constituent, Config::MUSTSET,   \"\",  \"\");\n    readConfig(config, \"minDegree\",                        minDegree,   Config::DEFAULT,   \"0\", \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                               GM,          Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                                R,           Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"applyXi\",                          applyXi,     Config::DEFAULT,  \"1\",               \"apply Doodson-Warburg phase correction (see IERS conventions)\");\n    if(isCreateSchema(config)) return;\n\n    // sort and check if doodson numbers defined multiple times\n    // --------------------------------------------------------\n    std::sort(constituent.begin(), constituent.end(), [](Constituent &a, Constituent &b) {return a.doodson < b.doodson;});\n    if(std::unique(constituent.begin(), constituent.end(), [](Constituent &a, Constituent &b) {return a.doodson == b.doodson;}) != constituent.end())\n      throw(Exception(\"The same doodson number is defined multiple times\"));\n\n    // read tide generating potential (TGP)\n    // ------------------------------------\n    TideGeneratingPotential tgp;\n    if(applyXi)\n    {\n      if(fileNameTGP.empty())\n        throw(Exception(\"Need TideGeneratingPotential to compute xi phase correction\"));\n      logStatus<<\"read tide generating potential <\"<<fileNameTGP<<\">\"<<Log::endl;\n      readFileTideGeneratingPotential(fileNameTGP, tgp);\n    }\n\n    // read coefficients\n    // -----------------\n    logStatus<<\"read potential coefficients\"<<Log::endl;\n    std::vector<Doodson> doodson(constituent.size());\n    std::vector<Matrix>  cnmCos(constituent.size());\n    std::vector<Matrix>  snmCos(constituent.size());\n    std::vector<Matrix>  cnmSin(constituent.size());\n    std::vector<Matrix>  snmSin(constituent.size());\n    for(UInt i=0; i<constituent.size(); i++)\n    {\n      SphericalHarmonics harmCos, harmSin;\n      readFileSphericalHarmonics(constituent.at(i).cosName, harmCos);\n      readFileSphericalHarmonics(constituent.at(i).sinName, harmSin);\n      harmCos = harmCos.get(maxDegree, minDegree, GM, R);\n      harmSin = harmSin.get(maxDegree, minDegree, GM, R);\n\n      Double xi = 0.;\n      if(applyXi)\n        xi = tgp.xi(constituent.at(i).doodson);\n\n      doodson.at(i) =  constituent.at(i).doodson;\n      cnmCos.at(i)  =  harmCos.cnm() * cos(xi) + harmSin.cnm() * sin(xi);\n      snmCos.at(i)  =  harmCos.snm() * cos(xi) + harmSin.snm() * sin(xi);\n      cnmSin.at(i)  = -harmCos.cnm() * sin(xi) + harmSin.cnm() * cos(xi);\n      snmSin.at(i)  = -harmCos.snm() * sin(xi) + harmSin.snm() * cos(xi);\n    }\n\n    // write doodson harmonics\n    // -----------------------\n    logStatus<<\"writing doodson harmonics <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileDoodsonHarmonic(fileNameOut, DoodsonHarmonic(GM, R, doodson, cnmCos, snmCos, cnmSin, snmSin));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssAntennaDefinition2ParameterVector.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAntennaDefinition2ParameterVector.cpp\n*\n* @brief Estimate parameters of an antenna parametrization to fit an antenna definition.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-09-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nEstimates parameters of a parametrization of \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType},\nwhich represents all antennas from \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\nmatching the wildcard patterns of \\config{name}, \\config{serial}, \\config{radome}.\n\nThe provided values at the area weighted grid points of the pattern of each gnssType are used as pseudo-observations.\nA subset of patterns can be selected with \\configClass{types}{gnssType}.\n\nThe \\file{GnssAntennaDefinition file}{gnssAntennaDefinition} can be modified to the demands before with\n\\program{GnssAntennaDefinitionCreate}.\n\nSee also \\program{ParameterVector2GnssAntennaDefinition}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate parameters of an antenna parametrization to fit an antenna definition.\n* @ingroup programsGroup */\nclass GnssAntennaDefinition2ParameterVector\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAntennaDefinition2ParameterVector, SINGLEPROCESS, \"Estimate parameters of an antenna parametrization to fit an antenna definition\", Gnss)\nGROOPS_RENAMED_PROGRAM(GnssAntennaDefinition2Representation, GnssAntennaDefinition2ParameterVector, date2time(2020, 6, 26))\n\n/***********************************************/\n\nvoid GnssAntennaDefinition2ParameterVector::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                      fileNameSolution, fileNameParameterNames;\n    ParametrizationGnssAntennaPtr parametrization;\n    FileName                      fileNameAntenna;\n    std::string                   name, serial, radome;\n    std::vector<GnssType>         types;\n    Bool                          zeroNaN;\n\n    readConfig(config, \"outputfileSolution\",         fileNameSolution,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"outputfileParameterNames\",   fileNameParameterNames, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"antennaCenterVariations\",    parametrization,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileAntennaDefinition\", fileNameAntenna,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"name\",                       name,                   Config::OPTIONAL, \"*\", \"\");\n    readConfig(config, \"serial\",                     serial,                 Config::OPTIONAL, \"*\", \"\");\n    readConfig(config, \"radome\",                     radome,                 Config::OPTIONAL, \"*\", \"\");\n    readConfig(config, \"types\",                      types,                  Config::OPTIONAL, \"\",  \"if not set, all types in the file are used\");\n    readConfig(config, \"zeroNaN\",                    zeroNaN,                Config::DEFAULT,  \"1\", \"treat NaN values as zero, otherwise values are ignored\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    logStatus<<\"read antenna center variations <\"<<fileNameAntenna<<\">\"<<Log::endl;\n    std::vector<GnssAntennaDefinitionPtr> antennaList;\n    readFileGnssAntennaDefinition(fileNameAntenna, antennaList);\n\n    std::regex                 pattern = String::wildcard2regex(GnssAntennaDefinition::str(name, serial, radome));\n    std::vector<Vector>        solutions;\n    std::vector<ParameterName> parameterNames;\n    std::vector<ParameterName> baseNames;\n    parametrization->parameterName(baseNames);\n\n    for(GnssAntennaDefinitionPtr antenna : antennaList)\n      if(std::regex_match(antenna->str(), pattern))\n      {\n        const std::string antennaName = antenna->str();\n        logStatus<<\"estimate parameters for \"<<antennaName<<Log::endl;\n\n        auto typesAnt = types;\n        if(typesAnt.size() == 0)\n          for(auto &pattern : antenna->patterns)\n            typesAnt.push_back(pattern.type);\n\n        Vector x(typesAnt.size()*parametrization->parameterCount());\n        for(UInt idType=0; idType<typesAnt.size(); idType++)\n        {\n          const UInt idPattern = antenna->findAntennaPattern(typesAnt.at(idType), GnssAntennaDefinition::IGNORE_OBSERVATION);\n          if(idPattern == NULLINDEX)\n            continue;\n          GnssAntennaPattern &pattern = antenna->patterns.at(idPattern);\n          logInfo<<typesAnt.at(idType).str()<<Log::endl;\n\n          Matrix A(pattern.pattern.rows()*pattern.pattern.columns(), parametrization->parameterCount());\n          Vector l(pattern.pattern.rows()*pattern.pattern.columns());\n          UInt idx = 0;\n          for(UInt i=0; i<pattern.pattern.rows(); i++)\n            for(UInt k=0; k<pattern.pattern.columns(); k++)\n            {\n              // area weight\n              const Double p = std::sqrt((k == 0) ? (1-std::cos(0.5*Double(pattern.dZenit))) : std::sin(k*Double(pattern.dZenit)));\n              l(idx) = p * pattern.pattern(i,k);\n              axpy(p, parametrization->designMatrix(Angle(i*2*PI/pattern.pattern.rows()), Angle(PI/2-k*Double(pattern.dZenit))), A.row(idx));\n              if(std::isnan(l(idx)))\n              {\n                l(idx) = 0;\n                if(!zeroNaN)\n                  A.row(idx).setNull();\n              }\n              idx++;\n            }\n          solutions.push_back(leastSquares(A, l));\n\n          std::string typeStr = \".\" + typesAnt.at(idType).str();\n          for(const auto &base : baseNames)\n            parameterNames.push_back( ParameterName(antennaName, base.type + typeStr, base.temporal, base.interval) );\n        }\n      } // for(antenna)\n\n    // ============================\n\n    if(!fileNameSolution.empty())\n    {\n      logStatus<<\"write solution to <\"<<fileNameSolution<<\">\"<<Log::endl;\n      const UInt count = std::accumulate(solutions.begin(), solutions.end(), UInt(0), [](UInt count, const Vector &x) {return count + x.size();});\n      Vector x(count);\n      UInt idx = 0;\n      for(const Vector &solution : solutions)\n      {\n        copy(solution, x.row(idx, solution.rows()));\n        idx += solution.rows();\n      }\n      writeFileMatrix(fileNameSolution, x);\n    }\n\n    if(!fileNameParameterNames.empty())\n    {\n      logStatus<<\"write parameter names to <\"<<fileNameParameterNames<<\">\"<<Log::endl;\n      writeFileParameterName(fileNameParameterNames, parameterNames);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssAntennaDefinition2Skyplot.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAntennaDefinition2Skyplot.cpp\n*\n* @brief Create skyplot from Antenna definition.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-16\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nProduce a \\file{skyplot}{griddedData} of antenna center variations\nwhich can be plotted with \\program{PlotMap}.\n\nThe first antenna from \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}\nmatching the wildcard patterns of \\config{name}, \\config{serial}, \\config{radome} is used.\n\nFor each antenna pattern (gnssType) a separate data column is computed.\nA subset of patterns can be selected with \\configClass{types}{gnssType}.\n\nAzimuth and elevation are written as ellipsoidal longitude and latitude in a \\file{griddedData file}{griddedData}.\nThe choosen ellipsoid parameters \\config{R} and \\config{inverseFlattening} are arbitrary but should be the same\nas in \\configClass{grid}{gridType} and \\program{PlotMap}.\n\n\\fig{!hb}{1.0}{fileFormatGnssAntennaDefinition}{fig:gnssAntennaDefinition2Skyplot}{Antenna Center Variations of ASH701945D\\_M for two frequencies of GPS and GLONASS}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"classes/grid/grid.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create gridded data from Antenna definition.\n* @ingroup programsGroup */\nclass GnssAntennaDefinition2Skyplot\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAntennaDefinition2Skyplot, SINGLEPROCESS, \"Create gridded data from Antenna definition.\", Gnss, Grid)\nGROOPS_RENAMED_PROGRAM(GnssAntennaDefinition2GriddedData, GnssAntennaDefinition2Skyplot, date2time(2019, 9, 9))\n\n/***********************************************/\n\nvoid GnssAntennaDefinition2Skyplot::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameGrid;\n    FileName              fileNameAntenna;\n    std::string           name, serial, radome;\n    GridPtr               grid;\n    std::vector<GnssType> types;\n    Double                a, f;\n\n    readConfig(config, \"outputfileGriddedData\",      fileNameGrid,    Config::MUSTSET,   \"\",  \"data column for each gnssType\");\n    readConfig(config, \"inputfileAntennaDefinition\", fileNameAntenna, Config::MUSTSET,   \"\",  \"\");\n    readConfig(config, \"grid\",                       grid,            Config::MUSTSET,   \"\",  \"\");\n    readConfig(config, \"name\",                       name,            Config::OPTIONAL,  \"*\", \"\");\n    readConfig(config, \"serial\",                     serial,          Config::OPTIONAL,  \"*\", \"\");\n    readConfig(config, \"radome\",                     radome,          Config::OPTIONAL,  \"*\", \"\");\n    readConfig(config, \"types\",                      types,           Config::OPTIONAL,  \"\",  \"if not set, all types in the file are used\");\n    readConfig(config, \"R\",                          a,               Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",          f,               Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    logStatus<<\"read antenna center variations <\"<<fileNameAntenna<<\">\"<<Log::endl;\n    std::vector<GnssAntennaDefinitionPtr> antennaList;\n    readFileGnssAntennaDefinition(fileNameAntenna, antennaList);\n\n    std::regex pattern = String::wildcard2regex(GnssAntennaDefinition::str(name, serial, radome));\n    auto iter = std::find_if(antennaList.begin(), antennaList.end(), [&](const GnssAntennaDefinitionPtr &ant){return std::regex_match(ant->str(), pattern);});\n    if(iter == antennaList.end())\n      throw(Exception(\"antenna definition not found\"));\n    GnssAntennaDefinitionPtr antenna = *iter;\n\n    if(types.size() == 0)\n      for(auto &pattern : antenna->patterns)\n        types.push_back(pattern.type);\n\n    logStatus<<\"create values on grid\"<<Log::endl;\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    std::vector< std::vector<Double> > values(types.size(), std::vector<Double>(points.size()));\n    for(UInt i=0; i<points.size(); i++)\n      for(UInt idType=0; idType<types.size(); idType++)\n      {\n        const UInt idPattern = antenna->findAntennaPattern(types.at(idType), GnssAntennaDefinition::THROW_EXCEPTION);\n        values.at(idType).at(i) = antenna->patterns.at(idPattern).antennaVariations(points.at(i).lambda(), points.at(i).phi(), FALSE);\n      }\n\n    logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n    GriddedData griddedData(Ellipsoid(a, f), points, areas, values);\n    writeFileGriddedData(fileNameGrid, griddedData);\n    MiscGriddedData::printStatistics(griddedData);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssAntennaDefinitionCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAntennaDefinitionCreate.cpp\n*\n* @brief Create GNSS antenna definition file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-08-29\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate a \\file{GNSS antenna definition file}{gnssAntennaDefinition} (Antenna Center Variations, ACV) consisting of multiple antennas.\nThe antennas can be created from scratch or can be selected from existing files.\nThis program can also be used to modify existing files.\n\nFurthermore it can be used to create accuracy definition files containing azimuth and elevation dependent accuracy values for antennas.\nTo create an accuracy pattern for phase observations with \\verb|1 mm| accuracy at zenith and no azimuth dependency, define a\npattern with \\config{type}=\\verb|L|, \\config{values}=\\verb|0.001/cos(zenith/rho)|.\n\nThe antennas in \\configFile{outputfileAntennaDefinition}{gnssAntennaDefinition}\nare sorted by names and duplicates are removed (first one is kept).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"config/configRegister.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create GNSS antenna definition file.\n* @ingroup programsGroup */\nclass GnssAntennaDefinitionCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAntennaDefinitionCreate, SINGLEPROCESS, \"Create GNSS antenna definition file.\", Gnss)\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, GnssAntennaPattern &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    Angle maxZenith, dAzimuth;\n    ExpressionVariablePtr valueExpr;\n\n    readConfig(config, \"type\",         var.type,       Config::MUSTSET,  \"\",   \"pattern matching of observation types\");\n    readConfig(config, \"offsetX\",      var.offset.x(), Config::DEFAULT,  \"0\",  \"[m] antenna center offset\");\n    readConfig(config, \"offsetY\",      var.offset.y(), Config::DEFAULT,  \"0\",  \"[m] antenna center offset\");\n    readConfig(config, \"offsetZ\",      var.offset.z(), Config::DEFAULT,  \"0\",  \"[m] antenna center offset\");\n    readConfig(config, \"deltaAzimuth\", dAzimuth,       Config::MUSTSET,  \"5\",  \"[degree] step size\");\n    readConfig(config, \"deltaZenith\",  var.dZenit,     Config::MUSTSET,  \"5\",  \"[degree] step size\");\n    readConfig(config, \"maxZenith\",    maxZenith,      Config::DEFAULT,  \"90\", \"[degree]\");\n    readConfig(config, \"values\",       valueExpr,      Config::OPTIONAL, \"0\",  \"[m] expression (zenith, azimuth: variables)\");\n    endSequence(config);\n    if(isCreateSchema(config))\n      return TRUE;\n\n    UInt rows   = static_cast<UInt>(std::round(2*PI/dAzimuth));\n    UInt cols   = static_cast<UInt>(std::round(maxZenith/var.dZenit))+1;\n    var.pattern = Matrix(rows,cols);\n\n    if(valueExpr)\n    {\n      VariableList varList;\n      varList.undefineVariable(\"zenith\");\n      varList.undefineVariable(\"azimuth\");\n      valueExpr->simplify(varList);\n\n      for(UInt i=0; i<var.pattern.rows(); i++)\n        for(UInt k=0; k<var.pattern.columns(); k++)\n        {\n          varList.setVariable(\"azimuth\", i * 360./var.pattern.rows());\n          varList.setVariable(\"zenith\",  k * RAD2DEG * Double(var.dZenit));\n          var.pattern(i, k) = valueExpr->evaluate(varList);\n        }\n    }\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***** CLASS ***********************************/\n/***********************************************/\n\n// Latex documentation\nstatic const char *docstringGnssAntennaDefintionList = R\"(\n\\section{GnssAntennaDefintionList}\\label{gnssAntennaDefintionListType}\nProvides a list of GnssAntennaDefinitions as used in \\program{GnssAntennaDefinitionCreate}.\n)\";\n\nclass GnssAntennaDefintionList;\ntypedef std::shared_ptr<GnssAntennaDefintionList> GnssAntennaDefintionListPtr;\n\nclass GnssAntennaDefintionList\n{\nprotected:\n  static Bool match(GnssType type1, GnssType type2)\n  {\n    return (type1 == type2) &&\n           (!type1.hasWildcard(GnssType::PRN)       || type2.hasWildcard(GnssType::PRN))       &&\n           (!type1.hasWildcard(GnssType::SYSTEM)    || type2.hasWildcard(GnssType::SYSTEM))    &&\n           (!type1.hasWildcard(GnssType::FREQUENCY) || type2.hasWildcard(GnssType::FREQUENCY)) &&\n           (!type1.hasWildcard(GnssType::TYPE)      || type2.hasWildcard(GnssType::TYPE))      &&\n           (!type1.hasWildcard(GnssType::ATTRIBUTE) || type2.hasWildcard(GnssType::ATTRIBUTE)) &&\n           (!type1.hasWildcard(GnssType::FREQ_NO)   || type2.hasWildcard(GnssType::FREQ_NO));\n  }\n\npublic:\n  std::vector<GnssAntennaDefinitionPtr> antennas;\n\n  /// Creates an derived instance of this class.\n  static GnssAntennaDefintionListPtr create(Config &config, const std::string &name);\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListNew = R\"(\n\\subsection{New}\nCreates a new antenna.\n)\";\n\nclass GnssAntennaDefintionListNew : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListNew(Config &config)\n  {\n    try\n    {\n      antennas.push_back(GnssAntennaDefinitionPtr(new GnssAntennaDefinition()));\n      readConfig(config, \"name\",    antennas.back()->name,     Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"serial\",  antennas.back()->serial,   Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"radome\",  antennas.back()->radome,   Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"comment\", antennas.back()->comment,  Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"pattern\", antennas.back()->patterns, Config::MUSTSET,  \"\", \"\");\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListFromFile = R\"(\n\\subsection{FromFile}\nSelect all or the first antenna from an \\file{antenna definition file}{gnssAntennaDefinition}\nwhich matches the wildcards.\n)\";\n\nclass GnssAntennaDefintionListFromFile : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListFromFile(Config &config)\n  {\n    try\n    {\n      FileName    fileNameAntenna;\n      std::string name, serial, radome;\n      Bool        onlyFirstMatch;\n\n      readConfig(config, \"inputfileAntennaDefinition\", fileNameAntenna, Config::MUSTSET,  \"\",  \"\");\n      readConfig(config, \"name\",                       name,            Config::OPTIONAL, \"*\", \"\");\n      readConfig(config, \"serial\",                     serial,          Config::OPTIONAL, \"*\", \"\");\n      readConfig(config, \"radome\",                     radome,          Config::OPTIONAL, \"*\", \"\");\n      readConfig(config, \"onlyFirstMatch\",             onlyFirstMatch,  Config::DEFAULT,  \"0\", \"otherwise all machting antennas included\");\n      if(isCreateSchema(config)) return;\n\n      std::vector<GnssAntennaDefinitionPtr> antennasFile;\n      readFileGnssAntennaDefinition(fileNameAntenna, antennasFile);\n\n      std::regex pattern = String::wildcard2regex(GnssAntennaDefinition::str(name, serial, radome));\n      for(auto &antenna : antennasFile)\n        if(std::regex_match(antenna->str(), pattern))\n        {\n          antennas.push_back(antenna);\n          if(onlyFirstMatch)\n            break;\n        }\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListFromStationInfo = R\"(\n\\subsection{FromStationInfo}\nSelect all antennas from an \\file{antenna definition file}{gnssAntennaDefinition}\nwhich are used by a station within a defined time interval.\nWith \\config{specializeAntenna} an individual antenna is created for each different serial number\nusing the general type specific values from file.\n)\";\n\nclass GnssAntennaDefintionListFromStationInfo : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListFromStationInfo(Config &config)\n  {\n    try\n    {\n      FileName fileNameStationInfo, fileNameAntenna;\n      Time     timeStart, timeEnd = date2time(2500,1,1);\n      Bool     specialize;\n\n      readConfig(config, \"inputfileStationInfo\",       fileNameStationInfo, Config::MUSTSET,  \"\",  \"\");\n      readConfig(config, \"inputfileAntennaDefinition\", fileNameAntenna,     Config::MUSTSET,  \"\",  \"\");\n      readConfig(config, \"timeStart\",                  timeStart,           Config::OPTIONAL, \"\",  \"only antennas used in this time interval\");\n      readConfig(config, \"timeEnd\",                    timeEnd,             Config::OPTIONAL, \"\",  \"only antennas used in this time interval\");\n      readConfig(config, \"specializeAntenna\",          specialize,          Config::DEFAULT,  \"0\", \"e.g. separate different serial numbers from stationInfo\");\n      if(isCreateSchema(config)) return;\n\n      Platform stationInfo;\n      std::vector<GnssAntennaDefinitionPtr> antennasFile;\n      readFilePlatform(fileNameStationInfo, stationInfo);\n      readFileGnssAntennaDefinition(fileNameAntenna, antennasFile);\n      stationInfo.fillGnssAntennaDefinition(antennasFile);\n\n      for(const auto &instrument : stationInfo.equipments)\n      {\n        auto antennaInfo = std::dynamic_pointer_cast<PlatformGnssAntenna>(instrument);\n        if(antennaInfo && antennaInfo->timeEnd >= timeStart && antennaInfo->timeStart < timeEnd)\n        {\n          if(antennaInfo->antennaDef)\n          {\n            antennas.push_back(std::make_shared<GnssAntennaDefinition>(*antennaInfo->antennaDef));\n            if(specialize)\n            {\n              if(antennas.back()->name.empty())   antennas.back()->name   = antennaInfo->name;\n              if(antennas.back()->serial.empty()) antennas.back()->serial = antennaInfo->serial;\n              if(antennas.back()->radome.empty()) antennas.back()->radome = antennaInfo->radome;\n            }\n          }\n          else\n            logWarning<<stationInfo.markerName<<\".\"<<stationInfo.markerNumber<<\": no antenna definition found for \"<<antennaInfo->str()<<Log::endl;\n        }\n      }\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListResample = R\"(\n\\subsection{Resample}\nThe azimuth and elevation dependent antenna center variations (patterns) of all \\config{antenna}s\nare resampled to a new resolution.\n)\";\n\nclass GnssAntennaDefintionListResample : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListResample(Config &config)\n  {\n    try\n    {\n      std::vector<GnssAntennaDefintionListPtr> antennaLists;\n      Angle dAzimuth (NAN_EXPR);\n      Angle dZenith  (NAN_EXPR);\n      Angle maxZenith(NAN_EXPR);\n\n      readConfig(config, \"antenna\",      antennaLists, Config::MUSTSET,   \"\", \"\");\n      readConfig(config, \"deltaAzimuth\", dAzimuth,     Config::OPTIONAL, \"\", \"[degree] step size, empty: no change\");\n      readConfig(config, \"deltaZenith\",  dZenith,      Config::OPTIONAL, \"\", \"[degree] step size, empty: no change\");\n      readConfig(config, \"maxZenith\",    maxZenith,    Config::OPTIONAL, \"\", \"[degree], empty: no change\");\n      if(isCreateSchema(config)) return;\n\n      for(auto &antennaList : antennaLists)\n        for(auto &antenna : antennaList->antennas)\n          for(auto &pattern : antenna->patterns)\n          {\n            Double dz   = (dZenith   > 0) ? dZenith   : pattern.dZenit;\n            Double maxz = (maxZenith >=0) ? maxZenith : ((pattern.pattern.columns()-1) * Double(pattern.dZenit));\n            UInt cols   = static_cast<UInt>(std::round(maxz/dz))+1;\n            UInt rows   = (dAzimuth  > 0) ? static_cast<UInt>(std::round(2*PI/dAzimuth)) : pattern.pattern.rows();\n\n            if((pattern.dZenit != dz) || (pattern.pattern.rows() != rows) || (pattern.pattern.columns() != cols))\n            {\n              Matrix acv(rows, cols);\n              for(UInt i=0; i<rows; i++)\n                for(UInt k=0; k<cols; k++)\n                  acv(i, k) += pattern.antennaVariations(Angle(2*PI*i/rows), Angle(PI/2-k*dz), FALSE);\n              pattern.dZenit  = dz;\n              pattern.pattern = acv;\n            }\n          }\n\n      for(auto &antennaList : antennaLists)\n        antennas.insert(antennas.end(), antennaList->antennas.begin(), antennaList->antennas.end());\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListTransform = R\"(\n\\subsection{Transform}\nThis class can be used to separate general antenna patterns for different \\configClass{gnssType}{gnssType}s.\nIf the \\config{antenna}s contain only one pattern for all GPS observations on the L1 frequency (\\verb|*1*G**|),\nthe \\config{patternTypes}=\\verb|C1*G**| and \\verb|L1*G**| create two patterns with the \\verb|*1*G**| patterm as template.\nThe first matching pattern in the \\config{antenna} is used as template.\nAlso new \\config{additionalPattern} can be added (e.g. for \\verb|*5*G**|).\nWith \\config{addExistingPatterns} all already existing patterns that don't match completely to any of the above are added.\n)\";\n\nclass GnssAntennaDefintionListTransform : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListTransform(Config &config)\n  {\n    try\n    {\n      std::vector<GnssAntennaDefintionListPtr> antennaLists;\n      std::vector<GnssType>                    types;\n      std::vector<GnssAntennaPattern>          patternsAdd;\n      Bool                                     addExistingPatterns;\n\n      readConfig(config, \"antenna\",             antennaLists,        Config::MUSTSET,  \"\", \"\");\n      readConfig(config, \"patternTypes\",        types,               Config::OPTIONAL, \"\",  \"gnssType for each pattern (first match is used)\");\n      readConfig(config, \"additionalPattern\",   patternsAdd,         Config::OPTIONAL, \"\",  \"additional new patterns\");\n      readConfig(config, \"addExistingPatterns\", addExistingPatterns, Config::DEFAULT,  \"1\", \"add existing patterns that don't match completely any of the above\");\n      if(isCreateSchema(config)) return;\n\n      for(auto &antennaList : antennaLists)\n        for(auto &antenna : antennaList->antennas)\n        {\n          std::vector<GnssAntennaPattern> patternsOld = antenna->patterns;\n          antenna->patterns.clear();\n          for(GnssType type : types)\n          {\n            Bool found = FALSE;\n            for(auto &patternOld : patternsOld)\n              if(type == patternOld.type)\n              {\n                antenna->patterns.push_back(patternOld);\n                antenna->patterns.back().type = type;\n                found = TRUE;\n                break;\n              }\n            if(!found)\n              throw(Exception(antenna->str()+\": no pattern found which fits to all possible types: \"+type.str()));\n          }\n\n          for(auto &patternAdd : patternsAdd)\n          {\n            Bool found = FALSE;\n            for(auto &patternNew : antenna->patterns)\n              if(match(patternAdd.type, patternNew.type))\n              {\n                found = TRUE;\n                break;\n              }\n            if(!found)\n              antenna->patterns.push_back(patternAdd);\n          }\n\n          if(addExistingPatterns)\n            for(auto &patternOld : patternsOld)\n            {\n              Bool found = FALSE;\n              for(auto &patternNew : antenna->patterns)\n                if(match(patternOld.type, patternNew.type))\n                {\n                  found = TRUE;\n                  break;\n                }\n              if(!found)\n                antenna->patterns.push_back(patternOld);\n            }\n\n          std::sort(antenna->patterns.begin(), antenna->patterns.end(), [](GnssAntennaPattern &a, GnssAntennaPattern &b){return a.type < b.type;});\n        } // for(antennas)\n\n      for(auto &antennaList : antennaLists)\n        antennas.insert(antennas.end(), antennaList->antennas.begin(), antennaList->antennas.end());\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListRename = R\"(\n\\subsection{Rename}\nReplaces parts of the descrption of \\config{antenna}s.\nThe star \"\\verb|*|\" left this part untouched.\n)\";\n\nclass GnssAntennaDefintionListRename : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListRename(Config &config)\n  {\n    try\n    {\n      std::vector<GnssAntennaDefintionListPtr> antennaLists;\n      std::string name, serial, radome, comment;\n\n      readConfig(config, \"antenna\", antennaLists, Config::MUSTSET,  \"\",  \"\");\n      readConfig(config, \"name\",    name,         Config::OPTIONAL, \"*\", \"*: left this part untouched\");\n      readConfig(config, \"serial\",  serial,       Config::OPTIONAL, \"*\", \"*: left this part untouched\");\n      readConfig(config, \"radome\",  radome,       Config::OPTIONAL, \"*\", \"*: left this part untouched\");\n      readConfig(config, \"comment\", comment,      Config::OPTIONAL, \"*\", \"*: left this part untouched\");\n      if(isCreateSchema(config)) return;\n\n      for(auto &antennaList : antennaLists)\n        for(auto &antenna : antennaList->antennas)\n        {\n          if(name    != \"*\") antenna->name    = name;\n          if(serial  != \"*\") antenna->serial  = serial;\n          if(radome  != \"*\") antenna->radome  = radome;\n          if(comment != \"*\") antenna->comment = comment;\n          antennas.push_back(antenna);\n        } // for(antennas)\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListSetZero = R\"(\n\\subsection{SetZero}\nThe antenna center variations (patterns) or offsets\nof all \\config{antenna}s are set to zero.\n)\";\n\nclass GnssAntennaDefintionListSetZero : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListSetZero(Config &config)\n  {\n    try\n    {\n      std::vector<GnssAntennaDefintionListPtr> antennaLists;\n      std::vector<GnssType> types;\n      Bool zeroPattern, zeroOffset;\n\n      readConfig(config, \"antenna\",      antennaLists, Config::MUSTSET,  \"\",  \"\");\n      readConfig(config, \"patternTypes\", types,        Config::OPTIONAL, \"\",  \"only matching patterns, default: all\");\n      readConfig(config, \"zeroOffset\",   zeroOffset,   Config::DEFAULT,  \"1\", \"\");\n      readConfig(config, \"zeroPattern\",  zeroPattern,  Config::DEFAULT,  \"1\", \"\");\n      if(isCreateSchema(config)) return;\n\n      for(auto &antennaList : antennaLists)\n        for(auto &antenna : antennaList->antennas)\n          for(auto &pattern : antenna->patterns)\n            if(!types.size() || pattern.type.isInList(types))\n            {\n              if(zeroOffset)  pattern.offset = Vector3d(0., 0., 0.);\n              if(zeroPattern) pattern.pattern.setNull();\n            }\n\n      for(auto &antennaList : antennaLists)\n        antennas.insert(antennas.end(), antennaList->antennas.begin(), antennaList->antennas.end());\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nstatic const char *docstringGnssAntennaDefintionListRemoveCenterMean = R\"(\n\\subsection{RemoveCenterMean}\nThe antenna offset and antenna variations (patterns) are inseparable parts of the\nantenna model. With \\config{removeOffset} an estimated offset is removed from\nall selected patterns and added to the offset. With \\config{removeMean} an estimated\nconstant is removed additionally as it cannot be seperated from signal biases.\nThe mean and offset are defined as discretized (\\config{deltaAzimuth},\n\\config{dZenith}) integral of the spherical cap from zenith down to \\config{maxZenith}.\n)\";\n\nclass GnssAntennaDefintionListRemoveCenterMean : public GnssAntennaDefintionList\n{\npublic:\n  GnssAntennaDefintionListRemoveCenterMean(Config &config)\n  {\n    try\n    {\n      std::vector<GnssAntennaDefintionListPtr> antennaLists;\n      std::vector<GnssType> types;\n      Bool  removeOffset, removeMean;\n      Angle dAzimuth, dZenith, maxZenith;\n\n      readConfig(config, \"antenna\",      antennaLists, Config::MUSTSET, \"\",   \"\");\n      readConfig(config, \"patternTypes\", types,        Config::OPTIONAL, \"\",  \"only matching patterns, default: all\");\n      readConfig(config, \"removeMean\",   removeMean,   Config::MUSTSET, \"1\",  \"\");\n      readConfig(config, \"removeOffset\", removeOffset, Config::MUSTSET, \"1\",  \"\");\n      readConfig(config, \"deltaAzimuth\", dAzimuth,     Config::DEFAULT, \"1\",  \"[degree] sampling of pattern to estimate center/constant\");\n      readConfig(config, \"deltaZenith\",  dZenith,      Config::DEFAULT, \"1\",  \"[degree] sampling of pattern to estimate center/constant\");\n      readConfig(config, \"maxZenith\",    maxZenith,    Config::DEFAULT, \"90\", \"[degree] sampling of pattern to estimate center/constant\");\n      if(isCreateSchema(config)) return;\n\n      const UInt rows = static_cast<UInt>(std::round(2*PI/dAzimuth));\n      const UInt cols = static_cast<UInt>(std::round(maxZenith/dZenith));\n      Matrix A(rows*cols, 3*removeOffset+removeMean);\n      UInt idx = 0;\n      for(UInt i=0; i<rows; i++)\n        for(UInt k=0; k<cols; k++)\n        {\n          const Angle azimuth  (i*2*PI/rows);\n          const Angle elevation(PI/2-(k+0.5)*Double(dZenith));\n          if(removeOffset) A(idx, 0) = -std::cos(elevation) * std::cos(azimuth); // x\n          if(removeOffset) A(idx, 1) = -std::cos(elevation) * std::sin(azimuth); // y\n          if(removeOffset) A(idx, 2) = -std::sin(elevation);                     // z\n          if(removeMean)   A(idx, 3*removeOffset) = 1;                           // mean\n          A.row(idx) *= std::sqrt(std::cos(elevation));                          // area weights\n          idx++;\n        }\n\n      Vector l(rows*cols);\n      for(auto &antennaList : antennaLists)\n        for(auto &antenna : antennaList->antennas)\n          for(auto &pattern : antenna->patterns)\n            if(!types.size() || pattern.type.isInList(types))\n            {\n              Matrix PA = A;\n              UInt idx = 0;\n              for(UInt i=0; i<rows; i++)\n                for(UInt k=0; k<cols; k++)\n                {\n                  const Angle azimuth  (i*2*PI/rows);\n                  const Angle elevation(PI/2-(k+0.5)*Double(dZenith));\n                  l(idx) = pattern.antennaVariations(azimuth, elevation, FALSE/*applyOffset*/) * std::sqrt(std::cos(elevation));\n                  if(std::isnan(l(idx)))\n                  {\n                    l(idx) = 0.;\n                    PA.row(idx).setNull();\n                  }\n                  idx++;\n                }\n              Vector x = leastSquares(PA, l);\n              if(removeOffset)\n                pattern.offset += Vector3d(x(0), x(1), x(2));\n              // remove from pattern\n              for(UInt i=0; i<pattern.pattern.rows(); i++)\n                for(UInt k=0; k<pattern.pattern.columns(); k++)\n                {\n                  if(removeOffset)\n                  {\n                    const Angle azimuth  (i*2*PI/pattern.pattern.rows());\n                    const Angle elevation(PI/2-k*Double(pattern.dZenit));\n                    pattern.pattern(i, k) += std::cos(elevation) * std::cos(azimuth) * x(0)\n                                           + std::cos(elevation) * std::sin(azimuth) * x(1)\n                                           + std::sin(elevation)                     * x(2);\n                  }\n                  if(removeMean)\n                    pattern.pattern(i, k) -= x(3*removeOffset);\n                }\n            } // for(pattern)\n\n      for(auto &antennaList : antennaLists)\n        antennas.insert(antennas.end(), antennaList->antennas.begin(), antennaList->antennas.end());\n    }\n    catch(std::exception &e)\n    {\n      GROOPS_RETHROW(e)\n    }\n  }\n};\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(GnssAntennaDefintionList, \"gnssAntennaDefintionListType\",\n                      GnssAntennaDefintionListNew,\n                      GnssAntennaDefintionListFromFile,\n                      GnssAntennaDefintionListFromStationInfo,\n                      GnssAntennaDefintionListResample,\n                      GnssAntennaDefintionListTransform,\n                      GnssAntennaDefintionListRename,\n                      GnssAntennaDefintionListSetZero,\n                      GnssAntennaDefintionListRemoveCenterMean)\n\nGROOPS_READCONFIG_CLASS(GnssAntennaDefintionList, \"gnssAntennaDefintionListType\")\n\n/***********************************************/\n\nGnssAntennaDefintionListPtr GnssAntennaDefintionList::create(Config &config, const std::string &name)\n{\n  try\n  {\n    GnssAntennaDefintionListPtr ptr;\n    std::string           choice;\n    readConfigChoice(config, name, choice, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoiceElement(config, \"new\",              choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListNew(config));\n    if(readConfigChoiceElement(config, \"fromFile\",         choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListFromFile(config));\n    if(readConfigChoiceElement(config, \"fromStationInfo\",  choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListFromStationInfo(config));\n    if(readConfigChoiceElement(config, \"resample\",         choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListResample(config));\n    if(readConfigChoiceElement(config, \"transform\",        choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListTransform(config));\n    if(readConfigChoiceElement(config, \"rename\",           choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListRename(config));\n    if(readConfigChoiceElement(config, \"setZero\",          choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListSetZero(config));\n    if(readConfigChoiceElement(config, \"removeCenterMean\", choice, \"\"))\n      ptr = GnssAntennaDefintionListPtr(new GnssAntennaDefintionListRemoveCenterMean(config));\n    endChoice(config);\n    return ptr;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssAntennaDefinitionCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutAntenna;\n    std::vector<GnssAntennaDefintionListPtr> antennaLists;\n\n    readConfig(config, \"outputfileAntennaDefinition\", fileNameOutAntenna, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"antenna\",                     antennaLists,       Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    std::vector<GnssAntennaDefinitionPtr> antennas;\n    for(const auto &antennaList : antennaLists)\n      antennas.insert(antennas.end(), antennaList->antennas.begin(), antennaList->antennas.end());\n\n    std::stable_sort(antennas.begin(), antennas.end(), [](GnssAntennaDefinitionPtr a, GnssAntennaDefinitionPtr b)\n                     {return (a->name != b->name) ? (a->name < b->name) : ((a->serial != b->serial) ? (a->serial < b->serial) : (a->radome < b->radome));});\n    antennas.erase(std::unique(antennas.begin(), antennas.end(), [](GnssAntennaDefinitionPtr a, GnssAntennaDefinitionPtr b) {return (a->name == b->name) && (a->serial == b->serial) && (a->radome == b->radome);}), antennas.end());\n\n\n    logStatus<<\"write antenna definition <\"<<fileNameOutAntenna<<\">\"<<Log::endl;\n    writeFileGnssAntennaDefinition(fileNameOutAntenna, antennas);\n\n    for(const auto &antenna : antennas)\n    {\n      logInfo<<\" \"<<antenna->str()<<\" \"<<antenna->comment<<Log::endl;\n      for(const auto &pattern : antenna->patterns)\n        logInfo<<\"   \"<<pattern.type.str()<<\" offset(\"<<pattern.offset.x()*1e3%\"%5.1f, \"s<<pattern.offset.y()*1e3%\"%5.1f, \"s<<pattern.offset.z()*1e3%\"%6.1f) mm,\"s\n               <<\" pattern(\"s<<360./pattern.pattern.rows()%\"%4.1f° x \"s<<RAD2DEG*pattern.dZenit%\"%3.1f° ),\"s\n               <<\" maxZenith \"s<<(pattern.pattern.columns()-1)*RAD2DEG*pattern.dZenit%\"%4.1f°\"s<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssAntennaNormalsConstraint.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAntennaNormalsConstraint.cpp\n*\n* @brief Apply constraints to normals of antenna parametrization.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-09-14\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nApply constraints to \\file{normal equations}{normalEquation}\ncontaining \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}.\nUsually the antenna center variations are estimated together with other parameters\nlike station coordinates, signal biases and slant TEC in \\program{GnssProcessing}.\nThis results in a rank deficient matrix as not all parameters can be separated.\nThe deficient can be solved by adding pseudo observation equations as constraints.\n\nTo separate antenna center variations and signal biases\napply \\config{constraint:mean} for each GNSS \\configClass{type}{gnssType}.\nThe observation equation for the integral mean of antenna center variations (ACV)\nin all azimuth~$A$ and elevation~$E$ dependent directions\n\\begin{equation}\n  0 = \\iint ACV(A,E)\\, d\\Phi \\approx \\sum_i ACV(A_i,E_i)\\, \\Delta\\Phi_i\n\\end{equation}\nis approximated by a grid defined by\n\\config{deltaAzimuth}, \\config{deltaZenith}, and \\config{maxZenith}.\n\nTo separate from station coordinates use \\config{constraint:centerMean}\nand from slant TEC parameters use \\config{constraint:TEC}.\n\nThe constraints are applied separately to all antennas matching\nthe wildcard patterns of \\config{name}, \\config{serial}, \\config{radome}.\n\nSee also \\program{ParameterVector2GnssAntennaDefinition}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/fileParameterName.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Apply constraints to normals of antenna parametrization.\n* @ingroup programsGroup */\nclass GnssAntennaNormalsConstraint\n{\npublic:\n  class Constraint\n  {\n  public:\n    enum Type {CENTER, CENTERMEAN, CONSTANT, CONSTANTMEAN, TEC};\n    Type     type;\n    Bool     applyWeight;\n    GnssType gnssType;\n    Double   sigma;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAntennaNormalsConstraint, SINGLEPROCESS, \"Apply constraints to normals of antenna parametrization\", Gnss)\nGROOPS_RENAMED_PROGRAM(GnssAntennaRepresentationConstraint, GnssAntennaNormalsConstraint, date2time(2020, 6, 26))\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssAntennaNormalsConstraint::Constraint &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string choice;\n  if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n    return FALSE;\n  if(readConfigChoiceElement(config, \"center\", choice, \"zero center (x,y,z) of a single pattern\"))\n  {\n    var.type = GnssAntennaNormalsConstraint::Constraint::CENTER;\n    readConfig(config, \"type\",         var.gnssType,    Config::MUSTSET,  \"\",     \"applied for each matching types\");\n    readConfig(config, \"applyWeight\",  var.applyWeight, Config::DEFAULT,  \"1\",    \"from normal equations\");\n    readConfig(config, \"sigma\",        var.sigma,       Config::DEFAULT,  \"1e-5\", \"[m]\");\n  }\n  if(readConfigChoiceElement(config, \"centerMean\", choice, \"zero center (x,y,z) as (weighted) mean of all patterns\"))\n  {\n    var.type = GnssAntennaNormalsConstraint::Constraint::CENTERMEAN;\n    readConfig(config, \"applyWeight\",  var.applyWeight, Config::DEFAULT,  \"1\",    \"from normal equations\");\n    readConfig(config, \"sigma\",        var.sigma,       Config::DEFAULT,  \"1e-5\", \"[m]\");\n  }\n  if(readConfigChoiceElement(config, \"constant\", choice, \"zero constant (mean of all directions) of a single pattern\"))\n  {\n    var.type = GnssAntennaNormalsConstraint::Constraint::CONSTANT;\n    readConfig(config, \"type\",         var.gnssType,    Config::MUSTSET,  \"\",     \"applied for each matching types\");\n    readConfig(config, \"applyWeight\",  var.applyWeight, Config::DEFAULT,  \"1\",    \"from normal equations\");\n    readConfig(config, \"sigma\",        var.sigma,       Config::DEFAULT,  \"1e-5\", \"[m]\");\n  }\n  if(readConfigChoiceElement(config, \"constantMean\", choice, \"zero constant (mean of all directions) as (weighted) mean of all patterns\"))\n  {\n    var.type = GnssAntennaNormalsConstraint::Constraint::CONSTANTMEAN;\n    readConfig(config, \"applyWeight\",  var.applyWeight, Config::DEFAULT,  \"1\",    \"from normal equations\");\n    readConfig(config, \"sigma\",        var.sigma,       Config::DEFAULT,  \"1e-5\", \"[m]\");\n  }\n  if(readConfigChoiceElement(config, \"TEC\", choice, \"zero TEC computed as (weighetd) least squares from all types\"))\n  {\n    var.type = GnssAntennaNormalsConstraint::Constraint::TEC;\n    readConfig(config, \"type\",         var.gnssType,    Config::DEFAULT,  \"*\",    \"applied for combination of matching types\");\n    readConfig(config, \"applyWeight\",  var.applyWeight, Config::DEFAULT,  \"1\",    \"from normal equations\");\n    readConfig(config, \"sigma\",        var.sigma,       Config::DEFAULT,  \"1e-4\", \"[TECU]\");\n  }\n  endChoice(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssAntennaNormalsConstraint::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                      fileNameNormalsOut;\n    FileName                      fileNameNormalsIn;\n    std::vector<Constraint>       constraints;\n    ParametrizationGnssAntennaPtr parametrization;\n    std::string                   name, serial, radome;\n    Angle                         dAzimuth, dZenith, maxZenith;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", fileNameNormalsOut, Config::MUSTSET,  \"\",   \"with applied constraints\");\n    readConfig(config, \"inputfileNormalEquation\",  fileNameNormalsIn,  Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"constraint\",               constraints,        Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"antennaCenterVariations\",  parametrization,    Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"antennaName\",              name,               Config::OPTIONAL, \"*\",  \"apply constraints to all machting antennas\");\n    readConfig(config, \"antennaSerial\",            serial,             Config::OPTIONAL, \"*\",  \"apply constraints to all machting antennas\");\n    readConfig(config, \"antennaRadome\",            radome,             Config::OPTIONAL, \"*\",  \"apply constraints to all machting antennas\");\n    readConfig(config, \"deltaAzimuth\",             dAzimuth,           Config::DEFAULT,  \"1\",  \"[degree] sampling of pattern to estimate center/constant\");\n    readConfig(config, \"deltaZenith\",              dZenith,            Config::DEFAULT,  \"1\",  \"[degree] sampling of pattern to estimate center/constant\");\n    readConfig(config, \"maxZenith\",                maxZenith,          Config::DEFAULT,  \"90\", \"[degree] sampling of pattern to estimate center/constant\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    logStatus<<\"read normal equations <\"<<fileNameNormalsIn<<\">\"<<Log::endl;\n    Matrix             normals, rhs;\n    NormalEquationInfo info;\n    readFileNormalEquation(fileNameNormalsIn, info, normals, rhs);\n\n    // ============================\n\n    // find all antennas in normals/parameterNames\n    // -------------------------------------------\n    std::vector<std::string>           antennaName;\n    std::vector<std::vector<GnssType>> types; // for each antenna\n    std::vector<std::vector<UInt>>     index; // for each antenna, type: index in normals\n\n    std::vector<ParameterName> parametrizationNames;\n    parametrization->parameterName(parametrizationNames);\n    std::regex wildcard = String::wildcard2regex(GnssAntennaDefinition::str(name, serial, radome));\n\n    for(UInt i=0; i<info.parameterName.size(); i++)\n      if((info.parameterName.at(i).type.find(parametrizationNames.at(0).type) == 0) && std::regex_match(info.parameterName.at(i).object, wildcard))\n      {\n        // check antenna name\n        // ------------------\n        const UInt idAnt = std::distance(antennaName.begin(), std::find(antennaName.begin(), antennaName.end(), info.parameterName.at(i).object));\n        if(idAnt >= antennaName.size())\n        {\n          antennaName.push_back(info.parameterName.at(i).object);\n          types.push_back(std::vector<GnssType>());\n          index.push_back(std::vector<UInt>());\n        }\n\n        // extract GnssType\n        auto pos = info.parameterName.at(i).type.rfind('.');\n        if((pos == std::string::npos) || (pos+1 == info.parameterName.at(i).type.size()))\n          throw(Exception(info.parameterName.at(i).str() + \": GnssType not found in parameter name\"));\n        types.at(idAnt).push_back(GnssType(info.parameterName.at(i).type.substr(pos+1)));\n        index.at(idAnt).push_back(i);\n      }\n\n    // ============================\n\n    // partial derivatives of parametrization coeffcients with respect to center (x,y,z)\n    // performed by numerical integration and least squares adjustment\n    Matrix dacv_dcenter;\n    {\n      logStatus<<\"compute center constraint\"<<Log::endl;\n      const UInt rows = static_cast<UInt>(std::round(2*PI/dAzimuth));\n      const UInt cols = static_cast<UInt>(std::round(maxZenith/dZenith));\n\n      Matrix A(rows*cols, parametrization->parameterCount());\n      Matrix L(rows*cols, 3);\n      UInt idx = 0;\n      for(UInt i=0; i<rows; i++)\n        for(UInt k=0; k<cols; k++)\n        {\n          const Angle azimuth  (i*2*PI/rows);\n          const Angle elevation(PI/2-(k+0.5)*Double(dZenith));\n          copy(parametrization->designMatrix(azimuth, elevation), A.row(idx));\n          L(idx, 0) = -std::cos(elevation) * std::cos(azimuth);  // x\n          L(idx, 1) = -std::cos(elevation) * std::sin(azimuth);  // y\n          L(idx, 2) = -std::sin(elevation);                      // z\n          A.row(idx) *= std::sqrt(std::cos(elevation));          // area weights\n          L.row(idx) *= std::sqrt(std::cos(elevation));\n          idx++;\n        }\n      dacv_dcenter = leastSquares(A, L);\n    }\n\n    // ============================\n\n    // partial derivatives of parametrization coeffcients with respect to a constant\n    // performed by numerical integration and least squares adjustment\n    Matrix dacv_dconst;\n    {\n      logStatus<<\"compute constant constraint\"<<Log::endl;\n      const UInt rows = static_cast<UInt>(std::round(2*PI/dAzimuth));\n      const UInt cols = static_cast<UInt>(std::round(maxZenith/dZenith));\n\n      Matrix A(rows*cols, parametrization->parameterCount());\n      Vector l(rows*cols);\n      UInt idx = 0;\n      for(UInt i=0; i<rows; i++)\n        for(UInt k=0; k<cols; k++)\n        {\n          const Angle azimuth  (i*2*PI/rows);\n          const Angle elevation(PI/2-(k+0.5)*Double(dZenith));\n          copy(parametrization->designMatrix(azimuth, elevation), A.row(idx));\n          l(idx) = 1;                                   // constant\n          A.row(idx) *= std::sqrt(std::cos(elevation)); // area weights\n          l.row(idx) *= std::sqrt(std::cos(elevation));\n          idx++;\n        }\n      dacv_dconst = leastSquares(A, l);\n    }\n\n    // ============================\n\n    logStatus<<\"apply constraints to antennas\"<<Log::endl;\n    const UInt parameterCount = parametrization->parameterCount();\n    for(UInt idAnt=0; idAnt<antennaName.size(); idAnt++)\n    {\n      // antenna name\n      std::string str;\n      for(GnssType type : types.at(idAnt))\n        str += \" \"+type.str();\n      logInfo<<\" \"<<antennaName.at(idAnt)<<str<<Log::endl;\n\n      // weight matrices of each pattern: taken from normal equations\n      std::vector<Matrix> P(types.at(idAnt).size());\n      for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n      {\n        P.at(idType) = normals.slice(index.at(idAnt).at(idType), index.at(idAnt).at(idType), parameterCount, parameterCount);\n        fillSymmetric(P.at(idType));\n        P.at(idType).setType(Matrix::GENERAL);\n      }\n      Matrix I = identityMatrix(parameterCount);\n\n      // --- lambda ---------------------\n      auto accumulateNormals = [&](Double weight, const std::vector<Matrix> &A)\n      {\n        // accumulate constraint normals\n        for(UInt idType1=0; idType1<types.at(idAnt).size(); idType1++)\n          if(A.at(idType1).size())\n          {\n            rankKUpdate(weight, A.at(idType1), normals.slice(index.at(idAnt).at(idType1), index.at(idAnt).at(idType1), parameterCount, parameterCount));\n            for(UInt idType2=idType1+1; idType2<types.at(idAnt).size(); idType2++)\n              if(A.at(idType2).size())\n                matMult(weight, A.at(idType1).trans(), A.at(idType2), normals.slice(index.at(idAnt).at(idType1), index.at(idAnt).at(idType2), parameterCount, parameterCount));\n          }\n        info.observationCount += A.at(0).rows();\n      };\n      // --------------------------------\n\n      for(const auto &constraint : constraints)\n      {\n        switch(constraint.type)\n        {\n          case Constraint::CENTER:\n          {\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              if(types.at(idAnt).at(idType) == constraint.gnssType)\n              {\n                logInfo<<\"  - center   \"<<types.at(idAnt).at(idType).str()<<Log::endl;\n                Matrix N = dacv_dcenter.trans() * ((constraint.applyWeight ? P.at(idType) : I) * dacv_dcenter);\n                N.setType(Matrix::SYMMETRIC);\n                cholesky(N);\n                Matrix A = dacv_dcenter.trans() * (constraint.applyWeight ? P.at(idType) : I);\n                triangularSolve(1., N.trans(), A);\n                triangularSolve(1., N,         A);\n                rankKUpdate(1./std::pow(constraint.sigma, 2), A, normals.slice(index.at(idAnt).at(idType), index.at(idAnt).at(idType), parameterCount, parameterCount));\n                info.observationCount += 3;\n              }\n            break;\n          }\n          case Constraint::CENTERMEAN:\n          {\n            logInfo<<\"  - zero mean center\"<<Log::endl;\n            // normals: estimate antenna center\n            Matrix N(3, Matrix::SYMMETRIC);\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              N += dacv_dcenter.trans() * ((constraint.applyWeight ? P.at(idType) : I) * dacv_dcenter);\n            cholesky(N);\n\n            std::vector<Matrix> A(types.at(idAnt).size());\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n            {\n              A.at(idType) = (constraint.applyWeight ? (dacv_dcenter.trans()*P.at(idType)) : dacv_dcenter.trans());\n              triangularSolve(1., N.trans(), A.at(idType));\n              triangularSolve(1., N,         A.at(idType));\n            }\n\n            accumulateNormals(1./std::pow(constraint.sigma, 2), A);\n            break;\n          }\n          case Constraint::CONSTANT:\n          {\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              if(types.at(idAnt).at(idType) == constraint.gnssType)\n              {\n                logInfo<<\"  - constant \"<<types.at(idAnt).at(idType).str()<<Log::endl;\n                // normals: estimate antenna constant\n                Double N = inner(dacv_dconst, (constraint.applyWeight ? (P.at(idType)*dacv_dconst) : dacv_dconst));\n                Matrix A = (1./N) * (constraint.applyWeight ? (dacv_dconst.trans()*P.at(idType)) : dacv_dconst.trans());\n                // accumulate constraint normals\n                rankKUpdate(1./std::pow(constraint.sigma, 2), A, normals.slice(index.at(idAnt).at(idType), index.at(idAnt).at(idType), parameterCount, parameterCount));\n                info.observationCount += 1;\n              }\n            break;\n          }\n          case Constraint::CONSTANTMEAN:\n          {\n            // normals: estimate antenna center\n            Double N = 0;\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              N += inner(dacv_dconst, (constraint.applyWeight ? (P.at(idType)*dacv_dconst) : dacv_dconst));\n            std::vector<Matrix> A(types.at(idAnt).size());\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              A.at(idType) = (1./N) * (constraint.applyWeight ? (dacv_dconst.trans()*P.at(idType)) : dacv_dconst.trans());\n            accumulateNormals(1./std::pow(constraint.sigma, 2), A);\n            break;\n          }\n          case Constraint::TEC:\n          {\n            std::string str;\n            for(GnssType type : types.at(idAnt))\n              if(type == constraint.gnssType)\n                str += \" \"+type.str();\n            logInfo<<\"  - zero mean TEC\"<<str<<Log::endl;\n            Matrix N(parametrization->parameterCount(), Matrix::SYMMETRIC);\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              if(types.at(idAnt).at(idType) == constraint.gnssType)\n                axpy(std::pow(types.at(idAnt).at(idType).ionosphericFactor(), 2), (constraint.applyWeight ? P.at(idType) : I), N);\n            cholesky(N);\n\n            // constraint as pseudo observation equations\n            std::vector<Matrix> A(types.at(idAnt).size());\n            for(UInt idType=0; idType<types.at(idAnt).size(); idType++)\n              if(types.at(idAnt).at(idType) == constraint.gnssType)\n              {\n                A.at(idType) = types.at(idAnt).at(idType).ionosphericFactor() * (constraint.applyWeight ? P.at(idType) : I);\n                triangularSolve(1., N.trans(), A.at(idType));\n                triangularSolve(1., N,         A.at(idType));\n              }\n\n            accumulateNormals(1./std::pow(constraint.sigma, 2), A);\n            break;\n          }\n        }\n      }\n    } // for(idAnt)\n\n    // ============================\n\n    logStatus<<\"write constrained normal equations to <\"<<fileNameNormalsOut<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameNormalsOut, info, normals, rhs);\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssAttitudeInfoCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssAttitudeInfoCreate.cpp\n*\n* @brief Creates attitude info file used by SimulateStarCameraGnss.\n*\n* @author Sebastian Strasser\n* @date 2020-11-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreates attitude info file (\\file{Instrument(MISCVALUES)}{instrument})\nused by \\program{SimulateStarCameraGnss}. One or more \\config{attitudeInfo}s can be specified.\nThey are valid from \\config{timeStart} until the start of the subsequent \\config{attitudeInfo}.\n\\config{maxManeuverTime} is used by \\program{SimulateStarCameraGnss} to look\nfor ongoing orbit maneuvers before/after the given orbit that might affect the attitude at\nthe beginning or end of a given orbit.\n\n\\fig{!hb}{0.9}{gnssAttitudeModes}{fig:gnssAttitudeModes2}{Overview of attitude modes used by GNSS satellites}\n\nHere is a list of GNSS satellite types for which the attitude behavior is known and their\nrespective attitude modes and required parameters:\n\\begin{itemize}\n\\item \\textbf{GPS-II/IIA} [1]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: shadowMaxYawSteeringAndRecovery\n  \\item \\config{noonMode}: catchUpYawSteering\n  \\item \\config{maxYawRate}: 0.12~deg/s\n  \\item \\config{yawBias}: 0.5~deg\n  \\item \\config{maxManeuverTime}: 2~h\n\\end{itemize}\n\\item \\textbf{GPS-IIR/IIR-M} [1]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: catchUpYawSteering\n  \\item \\config{noonMode}: catchUpYawSteering\n  \\item \\config{maxYawRate}: 0.2~deg/s\n  \\item \\config{maxManeuverTime}: 30~min\n\\end{itemize}\n\\item \\textbf{GPS-IIF} [2]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: shadowConstantYawSteering\n  \\item \\config{noonMode}: catchUpYawSteering\n  \\item \\config{maxYawRate}: 0.11~deg/s\n  \\item \\config{yawBias}: -0.7~deg\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\item \\textbf{GLO-M} [3]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: shadowMaxYawSteeringAndStop\n  \\item \\config{noonMode}: centeredMaxYawSteering\n  \\item \\config{maxYawRate}: 0.25~deg/s\n  \\item \\config{noonBetaThreshold}: 2~deg\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\item \\textbf{GAL-1} [4]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering1\n  \\item \\config{noonMode}: smoothedYawSteering1\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\item \\textbf{GAL-2} [4]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering2\n  \\item \\config{noonMode}: smoothedYawSteering2\n  \\item \\config{midnightBetaThreshold}: 4.1~deg\n  \\item \\config{noonBetaThreshold}: 4.1~deg\n  \\item \\config{activationThreshold}: 10~deg\n  \\item \\config{maxManeuverTime}: 5656~s\n\\end{itemize}\n\\item \\textbf{BDS-2G/3G} [5, 6]\n\\begin{itemize}\n  \\item \\config{defaultMode}: orbitNormal\n  \\item \\config{midnightMode}: orbitNormal\n  \\item \\config{noonMode}: orbitNormal\n\\end{itemize}\n\\item \\textbf{BDS-2I} [5]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: betaDependentOrbitNormal\n  \\item \\config{noonMode}: betaDependentOrbitNormal\n  \\item \\config{maxYawRate}: 0.085~deg/s\n  \\item \\config{midnightBetaThreshold}: 4~deg\n  \\item \\config{noonBetaThreshold}: 4~deg\n  \\item \\config{activationThreshold}: 5~deg\n  \\item \\config{maxManeuverTime}: 24~h\n\\end{itemize}\n\\item \\textbf{BDS-2M} [5]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: betaDependentOrbitNormal\n  \\item \\config{noonMode}: betaDependentOrbitNormal\n  \\item \\config{maxYawRate}: 0.159~deg/s\n  \\item \\config{midnightBetaThreshold}: 4~deg\n  \\item \\config{noonBetaThreshold}: 4~deg\n  \\item \\config{activationThreshold}: 5~deg\n  \\item \\config{maxManeuverTime}: 13~h\n\\end{itemize}\n\\item \\textbf{BDS-3I/3SI} [6]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering2\n  \\item \\config{noonMode}: smoothedYawSteering2\n  \\item \\config{midnightBetaThreshold}: 3~deg\n  \\item \\config{noonBetaThreshold}: 3~deg\n  \\item \\config{activationThreshold}: 6~deg\n  \\item \\config{maxManeuverTime}: 5740~s\n\\end{itemize}\n\\item \\textbf{BDS-3M/3SM} [6]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: smoothedYawSteering2\n  \\item \\config{noonMode}: smoothedYawSteering2\n  \\item \\config{midnightBetaThreshold}: 3~deg\n  \\item \\config{noonBetaThreshold}: 3~deg\n  \\item \\config{activationThreshold}: 6~deg\n  \\item \\config{maxManeuverTime}: 3090~s\n\\end{itemize}\n\\item \\textbf{QZS-1} [7]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: betaDependentOrbitNormal\n  \\item \\config{noonMode}: betaDependentOrbitNormal\n  \\item \\config{maxYawRate}: 0.01~deg/s\n  \\item \\config{yawBias}: 180~deg\n  \\item \\config{midnightBetaThreshold}: 20~deg\n  \\item \\config{noonBetaThreshold}: 20~deg\n  \\item \\config{activationThreshold}: 18.5~deg\n  \\item \\config{maxManeuverTime}: 24~h\n\\end{itemize}\n\\item \\textbf{QZS-2G} [7]\n\\begin{itemize}\n  \\item \\config{defaultMode}: orbitNormal\n  \\item \\config{midnightMode}: orbitNormal\n  \\item \\config{noonMode}: orbitNormal\n  \\item \\config{yawBias}: 180~deg\n\\end{itemize}\n\\item \\textbf{QZS-2I} [7]\n\\begin{itemize}\n  \\item \\config{defaultMode}: nominalYawSteering\n  \\item \\config{midnightMode}: centeredMaxYawSteering\n  \\item \\config{noonMode}: centeredMaxYawSteering\n  \\item \\config{maxYawRate}: 0.055~deg/s\n  \\item \\config{midnightBetaThreshold}: 5~deg\n  \\item \\config{noonBetaThreshold}: 5~deg\n  \\item \\config{maxManeuverTime}: 1.5~h\n\\end{itemize}\n\\end{itemize}\n\nSome specific satellites may deviate in their attitude behavior or parameters\n(e.g. G013-G040, R713, C005, C015, C017, J001).\n\nReferences for the attitude behavior information:\n\\begin{enumerate}\n\\item \\href{https://doi.org/10.1007/s10291-008-0092-1}{Kouba (2009)}\n\\item \\href{https://doi.org/10.1007/s10291-016-0562-9}{Kuang et al. (2017)}\n\\item \\href{https://doi.org/10.1016/j.asr.2010.09.007}{Dilssner et al. (2011)}\n\\item \\url{https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3}\n\\item \\href{https://doi.org/10.1007/s10291-018-0783-1}{Wang et al. (2018)}\n\\item \\href{https://doi.org/10.1017/S0373463318000103}{Li et al. (2018)}\n\\item \\url{https://qzss.go.jp/en/technical/qzssinfo/index.html}\n\\end{enumerate}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Creates attitude info file used by SimulateStarCameraGnss.\n* @ingroup programsGroup */\nclass GnssAttitudeInfoCreate\n{\npublic:\n  enum AttitudeMode\n  {\n    NOMINAL_YAW_STEERING = 0,\n    ORBIT_NORMAL = 1,                         // e.g. BDS-2G, BDS-3G, QZS-2G\n    CATCH_UP_YAW_STEERING = 2,                // e.g. GPS-* (noon), GPS-IIR (midnight)\n    SHADOW_MAX_YAW_STEERING_AND_RECOVERY = 3, // e.g. GPS-IIA (midnight)\n    SHADOW_MAX_YAW_STEERING_AND_STOP = 4,     // e.g. GLO-M (midnight)\n    SHADOW_CONSTANT_YAW_STEERING = 5,         // e.g. GPS-IIF (midnight)\n    CENTERED_MAX_YAW_STEERING = 6,            // e.g. QZS-2I, GLO-M (noon)\n    SMOOTHED_YAW_STEERING_1 = 7,              // e.g. GAL-1\n    SMOOTHED_YAW_STEERING_2 = 8,              // e.g. GAL-2, BDS-3M, BDS-3I\n    BETA_DEPENDENT_ORBIT_NORMAL = 9           // e.g. BDS-2M, BDS-2I, QZS-1\n  };\n\n  class AttitudeInfo\n  {\n  public:\n    Time         timeStart;\n    AttitudeMode defaultMode;\n    AttitudeMode midnightMode;\n    AttitudeMode noonMode;\n    Double       maxYawRate;\n    Double       yawBias;\n    Double       midnightBetaThreshold;\n    Double       noonBetaThreshold;\n    Double       activationThreshold;\n    Double       maxManeuverTime;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssAttitudeInfoCreate, SINGLEPROCESS, \"Creates attitude info file used by SimulateStarCameraGnss.\", Gnss, Instrument)\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, GnssAttitudeInfoCreate::AttitudeInfo &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    auto readMode = [&](const std::string &name, const std::string &annotation)\n    {\n      GnssAttitudeInfoCreate::AttitudeMode mode = GnssAttitudeInfoCreate::AttitudeMode::NOMINAL_YAW_STEERING;\n      std::string choice;\n      readConfigChoice(config, name,  choice, Config::MUSTSET, \"nominalYawSteering\",  annotation);\n      if(readConfigChoiceElement(config, \"nominalYawSteering\", choice, \"yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse)\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::NOMINAL_YAW_STEERING;\n      if(readConfigChoiceElement(config, \"orbitNormal\", choice, \"keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G)\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::ORBIT_NORMAL;\n      if(name != \"defaultMode\" && readConfigChoiceElement(config, \"catchUpYawSteering\", choice, \"yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight))\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::CATCH_UP_YAW_STEERING;\n      if(name == \"midnightMode\" && readConfigChoiceElement(config, \"shadowMaxYawSteeringAndRecovery\", choice, \"yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight))\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::SHADOW_MAX_YAW_STEERING_AND_RECOVERY;\n      if(name == \"midnightMode\" && readConfigChoiceElement(config, \"shadowMaxYawSteeringAndStop\", choice, \"yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached, then stop (e.g. GLO-M (midnight))\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::SHADOW_MAX_YAW_STEERING_AND_STOP;\n      if(name == \"midnightMode\" && readConfigChoiceElement(config, \"shadowConstantYawSteering\", choice, \"yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight))\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::SHADOW_CONSTANT_YAW_STEERING;\n      if(name != \"defaultMode\" && readConfigChoiceElement(config, \"centeredMaxYawSteering\", choice, \"yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon))\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::CENTERED_MAX_YAW_STEERING;\n      if(name != \"defaultMode\" && readConfigChoiceElement(config, \"smoothedYawSteering1\", choice, \"yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1)\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::SMOOTHED_YAW_STEERING_1;\n      if(name != \"defaultMode\" && readConfigChoiceElement(config, \"smoothedYawSteering2\", choice, \"yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I)\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::SMOOTHED_YAW_STEERING_2;\n      if(name != \"defaultMode\" && readConfigChoiceElement(config, \"betaDependentOrbitNormal\", choice, \"switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1)\"))\n        mode = GnssAttitudeInfoCreate::AttitudeMode::BETA_DEPENDENT_ORBIT_NORMAL;\n      endChoice(config);\n\n      return mode;\n    };\n\n    readConfig(config, \"timeStart\",             var.timeStart,             Config::MUSTSET, \"0\",   \"\");\n    var.defaultMode  = readMode(\"defaultMode\",  \"default attitude mode\");\n    var.midnightMode = readMode(\"midnightMode\", \"attitude mode for maneuvers around orbit midnight\");\n    var.noonMode     = readMode(\"noonMode\",     \"attitude mode for maneuvers around orbit noon\");\n    readConfig(config, \"maxYawRate\",            var.maxYawRate,            Config::DEFAULT, \"0\",  \"[degree/s] maximum yaw rate of the satellite\");\n    readConfig(config, \"yawBias\",               var.yawBias,               Config::DEFAULT, \"0\",  \"[degree] yaw bias applied in satellite attitude control system\");\n    readConfig(config, \"midnightBetaThreshold\", var.midnightBetaThreshold, Config::DEFAULT, \"0\",  \"[degree] limit midnight maneuver to this absolute angle of the Sun above/below the satellite orbital plane\");\n    readConfig(config, \"noonBetaThreshold\",     var.noonBetaThreshold,     Config::DEFAULT, \"0\",  \"[degree] limit noon maneuver to this absolute angle of the Sun above/below the satellite orbital plane\");\n    readConfig(config, \"activationThreshold\",   var.activationThreshold,   Config::DEFAULT, \"0\",  \"[degree] limit maneuver to this yaw/Earth-spacecraft-Sun angle (depending on mode)\");\n    readConfig(config, \"maxManeuverTime\",       var.maxManeuverTime,       Config::DEFAULT, \"0\",  \"[s] maximum duration of maneuver or maximum maneuver lookup time before/after orbit start/end\");\n    endSequence(config);\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssAttitudeInfoCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<AttitudeInfo> attitudeInfos;\n\n    readConfig(config, \"outputfileAttitudeInfo\", fileNameOut,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"attitudeInfo\",           attitudeInfos, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    MiscValuesArc arc;\n    for(auto &info : attitudeInfos)\n    {\n      MiscValuesEpoch epoch(9);\n      epoch.time      = info.timeStart;\n      epoch.values(0) = info.defaultMode;\n      epoch.values(1) = info.midnightMode;\n      epoch.values(2) = info.noonMode;\n      epoch.values(3) = std::fabs(info.maxYawRate);\n      epoch.values(4) = info.yawBias;\n      epoch.values(5) = std::fabs(info.midnightBetaThreshold);\n      epoch.values(6) = std::fabs(info.noonBetaThreshold);\n      epoch.values(7) = std::fabs(info.activationThreshold);\n      epoch.values(8) = std::fabs(info.maxManeuverTime);\n      arc.push_back(epoch);\n    }\n\n    logStatus<<\"write attitude info file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileInstrument(fileNameOut, arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssBiasClockAlignment.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssBiasClockAlignment.cpp\n*\n* @brief Align GNSS transmitter clocks to reference clocks and adjust related receiver signal biases as well as GLONASS transmitter biases.\n*\n* @author Sebastian Strasser\n* @date 2019-09-03\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program can be used to absolutely align GNSS transmitter clocks to reference clocks (i.e. broadcast clocks).\nEach 'group' of \\config{transmitter}s, usually a system like GPS or Galileo, is aligned individually by a constant shift over all transmitters.\nIf \\config{alignClocksByFreqNo} is set, GLONASS transmitters will be divided by frequency number into groups of nominally two transmitters.\nThe offset between clocks and reference clocks will be shifted into receiver code biases, if \\config{receiver} is provided.\"\n\nBy setting \\config{alignFreqNoBiasesAtReceiver} and providing \\config{receiver}, this program can further align GLONASS transmitter signal\nbiases so that the differences between frequency number-dependent receiver signal biases are minimal, which helps if PPP users don't set\nup individual signal biases per frequency number at the receiver. Alignment is done by computing signal bias residuals to the mean over all\nfrequency numbers of a signal type at each receiver and then computing the means over all receivers for each frequency number and shifting\nthose from the receiver signal biases to the transmitter signal biases. Internal consistency of the biases is not affected by this.\n\nIf you only want to align GLONASS frequency numbers, provide the same clocks in\n\\configFile{inputfileClock}{instrument} and \\configFile{inputfileReferenceClock}{instrument}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Align GNSS transmitter clocks to reference clocks and adjust related receiver signal biases as well as GLONASS transmitter biases.\n* @ingroup programsGroup */\nclass GnssBiasClockAlignment\n{\npublic:\n  class Transmitter\n  {\n  public:\n    FileName outNameClock, outNameBias, inNameClock, inNameReferenceClock, inNameBias, inNameTransmitterInfo;\n    MiscValueArc clockArc, referenceClockArc;\n    GnssSignalBias biases;\n    Platform platform;\n  };\n\n  class Receiver\n  {\n  public:\n    FileName outNameBias, inNameBias;\n    GnssSignalBias biases;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssBiasClockAlignment, SINGLEPROCESS, \"Align GNSS transmitter clocks to reference clocks and adjust related receiver signal biases as well as GLONASS transmitter biases.\", Gnss, Instrument)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssBiasClockAlignment::Transmitter &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"outputfileClock\",          var.outNameClock,          Config::MUSTSET,  \"\", \"aligned clock instrument file\");\n  readConfig(config, \"outputfileSignalBias\",     var.outNameBias,           Config::OPTIONAL, \"\", \"(GLONASS only) aligned signal bias file\");\n  readConfig(config, \"inputfileClock\",           var.inNameClock,           Config::MUSTSET,  \"\", \"clock instrument file\");\n  readConfig(config, \"inputfileReferenceClock\",  var.inNameReferenceClock,  Config::MUSTSET,  \"\", \"reference clock instrument file\");\n  readConfig(config, \"inputfileSignalBias\",      var.inNameBias,            Config::OPTIONAL, \"\", \"(GLONASS only) signal bias file\");\n  readConfig(config, \"inputfileTransmitterInfo\", var.inNameTransmitterInfo, Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/transmitterInfo/igs/igs20/transmitterInfo_igs20.{prn}.xml\", \"transmitter platform file\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssBiasClockAlignment::Receiver &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"outputfileSignalBias\",    var.outNameBias,          Config::MUSTSET, \"\", \"aligned signal bias file\");\n  readConfig(config, \"inputfileSignalBias\",     var.inNameBias,           Config::MUSTSET, \"\", \"signal bias file\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssBiasClockAlignment::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<Transmitter> transmitters;\n    std::vector<Receiver> receivers;\n    Bool alignClocksByFreqNo, alignFreqNoBiasesAtReceiver;\n\n    readConfig(config, \"transmitter\",                 transmitters,                Config::MUSTSET,  \"\",  \"one element per satellite\");\n    readConfig(config, \"receiver\",                    receivers,                   Config::OPTIONAL, \"\",  \"one element per station\");\n    readConfig(config, \"alignClocksByFreqNo\",         alignClocksByFreqNo,         Config::DEFAULT,  \"1\", \"align clocks for each GLONASS frequency number separately\");\n    readConfig(config, \"alignFreqNoBiasesAtReceiver\", alignFreqNoBiasesAtReceiver, Config::DEFAULT,  \"1\", \"align frequency number-dependent code biases for each receiver\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read transmitter input files\"<<Log::endl;\n    std::map<GnssType, std::vector<UInt>> group2DataIds;\n    Single::forEach(transmitters.size(), [&](UInt i)\n    {\n      Transmitter *trans = &transmitters.at(i);\n      try\n      {\n        trans->clockArc          = InstrumentFile::read(trans->inNameClock);\n        trans->referenceClockArc = InstrumentFile::read(trans->inNameReferenceClock);\n        if(!trans->inNameBias.empty())\n          readFileGnssSignalBias(trans->inNameBias, trans->biases);\n        readFilePlatform(trans->inNameTransmitterInfo, trans->platform);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        return;\n      }\n\n      auto recv = trans->platform.findEquipment<PlatformGnssReceiver>(trans->clockArc.at(trans->clockArc.size()/2).time);\n      if(!recv)\n      {\n        logWarning<<\"no receiver info found in <\"<<trans->inNameTransmitterInfo<<\">, skipping satellite...\"<<Log::endl;\n        return;\n      }\n\n      GnssType group(\"***\"s+recv->serial.at(0));\n      if(alignClocksByFreqNo && group == GnssType::GLONASS && !recv->version.empty())\n        group.setFrequencyNumber(std::stoi(recv->version));\n      group2DataIds[group].push_back(i);\n    });\n\n    if(receivers.size())\n    {\n      logStatus<<\"read receiver input files\"<<Log::endl;\n      Single::forEach(receivers.size(), [&](UInt i)\n      {\n        try\n        {\n          readFileGnssSignalBias(receivers.at(i).inNameBias, receivers.at(i).biases);\n        }\n        catch(std::exception &e)\n        {\n          logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        }\n      });\n    }\n\n    // shift mean of transmitter clock diffs per group to receiver code biases\n    logInfo<<\"clock shifts per group:\"<<Log::endl;\n    for(const auto &group : group2DataIds)\n    {\n      // mean over all satellite clocks in group\n      std::vector<Double> clockDiffs;\n      for(UInt i : group.second)\n        for(UInt idEpoch = 0; idEpoch < transmitters.at(i).clockArc.size(); idEpoch++)\n          clockDiffs.push_back(transmitters.at(i).clockArc.at(idEpoch).value - transmitters.at(i).referenceClockArc.at(idEpoch).value);\n      const Double mean = std::accumulate(clockDiffs.begin(), clockDiffs.end(), 0.0)/clockDiffs.size();\n      logInfo<<group.first.str()<<group.second.size()%\" (%i sat)\"s<<\" = \"<<(mean*1e9)%\"%10.3f ns\"s<<\" = \"<<(mean*LIGHT_VELOCITY)%\"%10.3f m\"s<<Log::endl;\n\n      // update transmitter clocks\n      for(UInt i : group.second)\n        for(UInt idEpoch = 0; idEpoch < transmitters.at(i).clockArc.size(); idEpoch++)\n          transmitters.at(i).clockArc.at(idEpoch).value -= mean;\n\n      // update receiver code biases\n      for(auto &&rec : receivers)\n        for(UInt i = 0; i < rec.biases.types.size(); i++)\n          if(rec.biases.types.at(i) == group.first + GnssType::RANGE)\n            rec.biases.biases.at(i) -= mean * LIGHT_VELOCITY;\n    }\n\n    if(alignFreqNoBiasesAtReceiver)\n    {\n      if(!receivers.size())\n        throw(Exception(\"no receivers found, cannot align frequency number-dependent biases\"));\n\n      std::map<GnssType, std::vector<Double>> bias2Residuals;\n\n      // compute residuals of receiver biases to mean bias over all GLONASS frequency numbers per station\n      for(auto &&rec : receivers)\n      {\n        // GLONASS signal bias types independent of frequency number\n        std::set<GnssType> types;\n        for(const auto &type : rec.biases.types)\n          if(type == GnssType::GLONASS)\n            types.insert(type & ~GnssType::FREQ_NO & (type == GnssType::PHASE ? ~GnssType::ATTRIBUTE : GnssType::ALL));\n\n        for(const auto &type : types)\n        {\n          // mean over all frequency numbers for this type\n          std::vector<Double> values;\n          for(UInt i = 0; i < rec.biases.types.size(); i++)\n            if(rec.biases.types.at(i) == type)\n              values.push_back(rec.biases.biases.at(i));\n          const Double mean = ::mean(Vector(values));\n\n          // bias residuals per frequency number for this type\n          for(UInt i = 0; i < rec.biases.types.size(); i++)\n            if(rec.biases.types.at(i) == type)\n            {\n              GnssType t = rec.biases.types.at(i) & (type == GnssType::PHASE ? ~GnssType::ATTRIBUTE : GnssType::ALL);\n              bias2Residuals[t].push_back(rec.biases.biases.at(i) - mean);\n            }\n        }\n      }\n\n      // shift mean of receiver bias residuals over all stations to transmitter bias per type and frequency number\n      logInfo<<\"bias shifts per frequency number and type:\"<<Log::endl;\n      for(const auto &bias : bias2Residuals)\n      {\n        const GnssType type = bias.first;\n        const Double mean = ::mean(Vector(bias.second));\n        logInfo<<\" \"<<type.str()<<\" = \"<<mean%\"%10.3f m\"s<<Log::endl;\n\n        // remove mean from receiver bias of all stations\n        for(auto &&rec : receivers)\n          for(UInt i = 0; i < rec.biases.types.size(); i++)\n            if(rec.biases.types.at(i) == type)\n              rec.biases.biases.at(i) -= mean;\n\n        // add mean to transmitter bias\n        for(auto &trans : transmitters)\n          for(UInt i = 0; i < trans.biases.types.size(); i++)\n            if(trans.biases.types.at(i) == type)\n              trans.biases.biases.at(i) += mean;\n      }\n    }\n\n    logStatus<<\"writing aligned clock files <\"<<transmitters.at(0).outNameClock<<\">\"<<Log::endl;\n    for(const auto &trans : transmitters)\n      if(trans.clockArc.size())\n        InstrumentFile::write(trans.outNameClock, trans.clockArc);\n\n    if(receivers.size())\n    {\n      logStatus<<\"writing aligned receiver signal bias files <\"<<receivers.at(0).outNameBias<<\">\"<<Log::endl;\n      for(const auto &rec : receivers)\n        if(rec.biases.types.size())\n          writeFileGnssSignalBias(rec.outNameBias, rec.biases);\n\n      if(alignFreqNoBiasesAtReceiver)\n      {\n        logStatus<<\"writing aligned transmitter signal bias files <\"<<transmitters.at(0).outNameBias<<\">\"<<Log::endl;\n        for(const auto &trans : transmitters)\n          if(trans.outNameBias)\n            writeFileGnssSignalBias(trans.outNameBias, trans.biases);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssEstimateClockShift.cpp",
    "content": "/***********************************************/\n/**\n* @file GnssEstimateClockShift.cpp\n*\n* @brief Estimate clock shift for a constellation of satellites.\n*\n* @author Sebastian Strasser\n* @date 2018-02-06\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring =\nR\"(\nThis program estimates an epoch-wise clock shift in a constellation of GNSS satellites.\nEach separate \\config{data} represents a satellite... (e.g. 32 GPS satellites).\nThe shift to reference clocks can be estimated by providing \\configFile{inputfileInstrumentRef}{instrument}.\nClock shifts are estimated for each epoch given by \\configClass{timeSeries}{timeSeriesType}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"parallel/parallel.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate clock shift for a constellation of satellites.\n* @ingroup programsGroup */\nclass GnssEstimateClockShift\n{\npublic:\n  class Data\n  {\n  public:\n    FileName outNameInstrument, outNameInstrumentDiff, inNameInstrument, inNameInstrumentRef;\n    std::vector<Time> times;\n    std::vector<UInt> index;\n    Vector clock, clockDiff;\n    Bool   useable;\n\n    void init(const std::vector<Time> &timesGlobal, Double margin);\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssEstimateClockShift, SINGLEPROCESS, \"Estimate clock shift for a constellation of satellites.\", Gnss)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GnssEstimateClockShift::Data &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"outputfileInstrument\",     var.outNameInstrument,     Config::OPTIONAL, \"\", \"corrected clocks\");\n  readConfig(config, \"outputfileInstrumentDiff\", var.outNameInstrumentDiff, Config::OPTIONAL, \"\", \"clock difference after correction\");\n  readConfig(config, \"inputfileInstrument\",      var.inNameInstrument,      Config::MUSTSET,  \"\", \"input clocks\");\n  readConfig(config, \"inputfileInstrumentRef\",   var.inNameInstrumentRef,   Config::OPTIONAL, \"\", \"reference clocks (subtracted from input clocks)\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GnssEstimateClockShift::Data::init(const std::vector<Time> &timesGlobal, Double margin)\n{\n  try\n  {\n    useable = FALSE;\n\n    MiscValueArc arc, arcRef;\n    try\n    {\n      arc = InstrumentFile::read(inNameInstrument);\n      if(!inNameInstrumentRef.empty())\n        arcRef = InstrumentFile::read(inNameInstrumentRef);\n    }\n    catch(std::exception &e)\n    {\n      logWarning << e.what() << Log::endl;\n      return;\n    }\n\n    if(!arc.size() || (!inNameInstrumentRef.empty() && arc.times() != arcRef.times()))\n    {\n      logWarning << \"arcs empty or not synchronized: \" << arc.size() << \" != \" << arcRef.size() << \", skipping\" << Log::endl;\n      return;\n    }\n\n    times = arc.times();\n    clock = clockDiff = arc.matrix().column(1);\n    if(arcRef.size())\n      clockDiff -= arcRef.matrix().column(1);\n\n    // find indices of given epochs\n    Time timeMargin = seconds2time(margin);\n    index.resize(timesGlobal.size(), MAX_UINT);\n    UInt idEpochGlobal = 0;\n    for(UInt idEpoch = 0; idEpoch < times.size(); idEpoch++)\n    {\n      while(idEpochGlobal+1 < timesGlobal.size() && timesGlobal.at(idEpochGlobal+1) < times.at(idEpoch)+timeMargin)\n        idEpochGlobal++;\n      if(timesGlobal.at(idEpochGlobal) >= times.at(idEpoch)-timeMargin && timesGlobal.at(idEpochGlobal) <= times.at(idEpoch)+timeMargin)\n        index.at(idEpochGlobal) = idEpoch;\n    }\n\n    useable = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssEstimateClockShift::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          fileNameShiftTimeSeries;\n    std::vector<Data> data;\n    TimeSeriesPtr     timeSeries;\n    Double            margin;\n\n    readConfig(config, \"outputfileShiftTimeSeries\", fileNameShiftTimeSeries, Config::OPTIONAL, \"\",    \"columns: mjd, clock shift\");\n    readConfig(config, \"data\",                      data,                    Config::MUSTSET,  \"\",    \"e.g. satellite\");\n    readConfig(config, \"timeSeries\",                timeSeries,              Config::MUSTSET,  \"\",    \"clock epochs\");\n    readConfig(config, \"margin\",                    margin,                  Config::DEFAULT,  \"0.1\", \"[s] margin for time comparison\");\n    if(isCreateSchema(config)) return;\n\n    const std::vector<Time> times = timeSeries->times();\n\n    // initialize clock data\n    for(auto &&d : data)\n    {\n      logStatus << \"read instrument file <\" << d.inNameInstrument << \">\" << Log::endl;\n      d.init(times, margin);\n    }\n    data.erase(std::remove_if(data.begin(), data.end(), [](const Data &d){ return !d.useable; }), data.end());\n    if(!data.size())\n      throw(Exception(\"no data found\"));\n\n    std::vector<Double> shiftTimeSeries(times.size(), NAN_EXPR);\n    Single::forEach(times.size(), [&](UInt idEpoch)\n    {\n      // build observation vector\n      std::vector<Double> l;\n      for(const auto &d : data)\n        if(d.index.at(idEpoch) != MAX_UINT)\n          l.push_back(d.clockDiff(d.index.at(idEpoch)));\n\n      if(l.size() == 0)\n      {\n        logWarning<<\"No data found at epoch \"+times.at(idEpoch).dateTimeStr()+\". continue with next epoch\"<<Log::endl;\n        return;\n      }\n\n      // compute and remove shift\n      shiftTimeSeries.at(idEpoch) = mean(Vector(l));\n      for(auto &&d : data)\n        if(d.index.at(idEpoch) != MAX_UINT)\n        {\n          d.clock(d.index.at(idEpoch))     -= shiftTimeSeries.at(idEpoch);\n          d.clockDiff(d.index.at(idEpoch)) -= shiftTimeSeries.at(idEpoch);\n        }\n    });\n\n    // save output files\n    for(const auto &d : data)\n    {\n      if(!d.outNameInstrument.empty())\n      {\n        logStatus << \"write corrected instrument file <\" << d.outNameInstrument << \">\" << Log::endl;\n        Matrix A(d.times.size(), 2);\n        copy(d.clock, A.column(1));\n        InstrumentFile::write(d.outNameInstrument, Arc(d.times, A, Epoch::MISCVALUE));\n      }\n      if(!d.outNameInstrumentDiff.empty())\n      {\n        logStatus << \"write clock difference instrument file <\" << d.outNameInstrumentDiff << \">\" << Log::endl;\n        Matrix A(d.times.size(), 2);\n        copy(d.clockDiff, A.column(1));\n        InstrumentFile::write(d.outNameInstrumentDiff, Arc(d.times, A, Epoch::MISCVALUE));\n      }\n    }\n\n    if(!fileNameShiftTimeSeries.empty())\n    {\n      logStatus<<\"Write clock shift time series to file <\"<<fileNameShiftTimeSeries<<\">\"<<Log::endl;\n      Matrix A(shiftTimeSeries.size(), 2);\n      copy(Vector(shiftTimeSeries), A.column(1));\n      InstrumentFile::write(fileNameShiftTimeSeries, Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssGlonassFrequencyNumberUpdate.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssGlonassFrequencyNumberUpdate.cpp\n*\n* @brief Update/set GLONASS frequency number in transmitter info files.\n*\n* @author Sebastian Strasser\n* @date 2019-08-29\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nUpdate/set GLONASS frequency number in \\configFile{inputfileTransmitterInfo}{platform} files.\nThe \\configFile{inputfilePrn2FrequencyNumber}{matrix} can be generated with\n\\program{SinexMetadata2GlonassFrequencyNumber}.\n\nSee also \\program{GnssAntex2AntennaDefinition}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Update/set GLONASS frequency number in transmitter info files.\n* @ingroup programsGroup */\nclass GnssGlonassFrequencyNumberUpdate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssGlonassFrequencyNumberUpdate, SINGLEPROCESS, \"Update/set GLONASS frequency number in transmitter info files.\", Gnss)\n\n/***********************************************/\n\nvoid GnssGlonassFrequencyNumberUpdate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutTransmitterInfo, fileNameInTransmitterInfo, fileNameInPrnSvn2FrequencyNumber;\n    std::vector<std::string> prnList;\n    std::string variableNamePrn;\n\n    readConfig(config, \"outputfileTransmitterInfo\",    fileNameOutTransmitterInfo,       Config::OPTIONAL, \"\",    \"templated for PRN list (variableNamePrn)\");\n    readConfig(config, \"inputfileTransmitterInfo\",     fileNameInTransmitterInfo,        Config::MUSTSET,  \"\",    \"templated for PRN list (variableNamePrn)\");\n    readConfig(config, \"inputfilePrn2FrequencyNumber\", fileNameInPrnSvn2FrequencyNumber, Config::MUSTSET,  \"{groopsDataDir}/gnss/transmitter/glonassPrnSvn2FrequencyNumber.txt\", \"matrix with columns: GLONASS PRN, SVN, mjdStart, mjdEnd, frequencyNumber\");\n    readConfig(config, \"prn\",                          prnList,                          Config::OPTIONAL, \"\",    \"PRN (e.g. R01) for transmitter info files\");\n    readConfig(config, \"variableNamePrn\",              variableNamePrn,                  Config::OPTIONAL, \"prn\", \"variable name for PRN in transmitter info files\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Platform> transmitterInfos(prnList.size());\n    if(!fileNameInTransmitterInfo.empty())\n    {\n      VariableList varList;\n      varList.setVariable(variableNamePrn, \"R**\");\n      logStatus<<\"read transmitter infos from <\"<<fileNameInTransmitterInfo(varList)<<\">\"<< Log::endl;\n      for(UInt idPrn=0; idPrn<prnList.size(); idPrn++)\n      {\n        varList.setVariable(variableNamePrn, prnList.at(idPrn));\n        readFilePlatform(fileNameInTransmitterInfo(varList), transmitterInfos.at(idPrn));\n      }\n    }\n\n    logStatus<<\"read GLONASS PRN/SVN to frequency number matrix from <\"<<fileNameInPrnSvn2FrequencyNumber<<\">\"<< Log::endl;\n    Matrix prnSvn2FreqNo;\n    readFileMatrix(fileNameInPrnSvn2FrequencyNumber, prnSvn2FreqNo);\n\n    //---------------------------------------------------------------\n\n    std::vector<std::vector<std::shared_ptr<PlatformGnssReceiver>>> receiverInfos(prnList.size());\n    for(UInt i=0; i<prnSvn2FreqNo.rows(); i++)\n    {\n      const std::string prn    = prnSvn2FreqNo(i,0)%\"R%02i\"s;\n      const std::string svn    = prnSvn2FreqNo(i,1)%\"R%03i\"s;\n      const Time timeStart     = mjd2time(prnSvn2FreqNo(i,2));\n      const Time timeEnd       = mjd2time(prnSvn2FreqNo(i,3));\n      const std::string freqNo = prnSvn2FreqNo(i,4)%\"%i\"s;\n\n      Bool found = FALSE;\n      for(UInt idTrans=0; idTrans<transmitterInfos.size(); idTrans++)\n        if(transmitterInfos.at(idTrans).markerNumber == prn)\n        {\n          // new receiver list entry\n          auto recv = transmitterInfos.at(idTrans).findEquipment<PlatformGnssReceiver>(0.5*(timeStart+timeEnd));\n          if(!recv)\n            continue;\n          found = TRUE;\n\n          auto info = std::make_shared<PlatformGnssReceiver>(*recv);\n          info->timeStart = timeStart;\n          info->timeEnd   = timeEnd;\n          info->version   = freqNo;\n          receiverInfos.at(idTrans).push_back(info);\n        }\n\n      if(!found)\n        logWarning<<prn<<\": no transmitter info entry found for time period \"<<timeStart.dateTimeStr()<<\" to \"<<timeEnd.dateTimeStr()<<Log::endl;\n    }\n\n    //---------------------------------------------------------------\n\n    if(!fileNameOutTransmitterInfo.empty())\n    {\n      VariableList varList;\n      varList.setVariable(variableNamePrn, \"R**\");\n      logStatus<<\"write transmitter infos to <\"<<fileNameOutTransmitterInfo(varList)<<\">\"<< Log::endl;\n      for(UInt idPrn=0; idPrn<prnList.size(); idPrn++)\n      {\n        auto &eq = transmitterInfos.at(idPrn).equipments;\n        // remove old receivers\n        eq.erase(std::remove_if(eq.begin(), eq.end(), [](auto &x) {return std::dynamic_pointer_cast<PlatformGnssReceiver>(x);}), eq.end());\n        // insert new receivers\n        std::sort(receiverInfos.at(idPrn).begin(), receiverInfos.at(idPrn).end(), [](auto &info1, auto &info2){return info1->timeStart < info2->timeStart;});\n        eq.insert(eq.end(), receiverInfos.at(idPrn).begin(), receiverInfos.at(idPrn).end());\n\n        varList.setVariable(variableNamePrn, prnList.at(idPrn));\n        writeFilePlatform(fileNameOutTransmitterInfo(varList), transmitterInfos.at(idPrn));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssProcessing.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssProcessing.cpp\n*\n* @brief GNSS/LEO satellite orbit determination, station network analysis, PPP.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2010-08-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program processes GNSS observations. It calculates the linearized observation equations,\naccumulates them into a system of normal equations and solves it.\n\nThe primary use cases of this program are:\n\\begin{itemize}\n  \\item \\reference{GNSS satellite orbit determination and station network analysis}{cookbook.gnssNetwork}\n  \\item \\reference{Kinematic orbit determination of LEO satellites}{cookbook.kinematicOrbit}\n  \\item \\reference{GNSS precise point positioning (PPP)}{cookbook.gnssPpp}\n\\end{itemize}\n\nThe observation epochs are defined by \\configClass{timeSeries}{timeSeriesType}\nand only observations at these epochs (within a \\config{timeMargin}) are considered.\n\nTo calculate observation equations from the tracks, the model parameters or unknown parameters need to be\ndefined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined\n\\configClass{parametrization}{gnssParametrizationType}.\nSome of the \\configClass{parametrization}{gnssParametrizationType} also include a priori models.\n\nLastly it is required to define the process flow of the gnssProcessing. This is accomplished\nwith a list of \\configClass{processingSteps}{gnssProcessingStepType}.\nEach step is processed consecutively. Some steps allow the selection of parameters, epochs,\nor the normal equation structure, which affects all subsequent steps.\nA minimal example consists of following steps:\n\\begin{itemize}\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: iterative float solution with outlier downeighting\n  \\item \\configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}:\n        fix ambiguities to integer and remove them from the normals\n  \\item \\configClass{estimate}{gnssProcessingStepType:estimate}: few iteration for final outlier downweighting\n  \\item \\configClass{writeResults}{gnssProcessingStepType:writeResults}:\n        write the output files defined in \\configClass{parametrization}{gnssParametrizationType}\n\\end{itemize}\n\nIf the program is run on multiple processes the \\configClass{receiver}{gnssReceiverGeneratorType}s\n(stations or LEO satellites) are distributed over the processes.\n\nSee also \\program{GnssSimulateReceiver}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"config/configRegister.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.h\"\n#include \"gnss/gnssParametrization/gnssParametrization.h\"\n#include \"gnss/gnssProcessingStep/gnssProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS/LEO satellite orbit determination, station network analysis, PPP.\n* @ingroup programsGroup */\nclass GnssProcessing\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssProcessing, PARALLEL, \"GNSS/LEO satellite orbit determination, station network analysis, PPP\", Gnss)\n\n/***********************************************/\n\nvoid GnssProcessing::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    TimeSeriesPtr               timeSeries;\n    Double                      marginSeconds;\n    GnssTransmitterGeneratorPtr transmitterGenerator;\n    GnssReceiverGeneratorPtr    receiverGenerator;\n    GnssParametrizationPtr      gnssParametrization;\n    EarthRotationPtr            earthRotation;\n    GnssProcessingStepPtr       processingSteps;\n\n    readConfig(config, \"timeSeries\",      timeSeries,           Config::MUSTSET,  \"\",    \"defines observation epochs\");\n    readConfig(config, \"timeMargin\",      marginSeconds,        Config::DEFAULT,  \"0.1\", \"[seconds] margin to consider two times identical\");\n    readConfig(config, \"transmitter\",     transmitterGenerator, Config::MUSTSET,  \"\",    \"constellation of GNSS satellites\");\n    readConfig(config, \"receiver\",        receiverGenerator,    Config::MUSTSET,  \"\",    \"ground station network or LEO satellite\");\n    readConfig(config, \"earthRotation\",   earthRotation,        Config::MUSTSET,  \"\",    \"apriori earth rotation\");\n    readConfig(config, \"parametrization\", gnssParametrization,  Config::MUSTSET,  \"\",    \"models and parameters\");\n    readConfig(config, \"processingStep\",  processingSteps,      Config::MUSTSET,  \"\",    \"steps are processed consecutively\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    // init the GNSS system\n    // --------------------\n    logInfo<<\"Init GNSS\"<<Log::endl;\n    std::vector<Time> times = timeSeries->times();\n    GnssPtr gnss = std::make_shared<Gnss>();\n    gnss->init({}, times, seconds2time(marginSeconds), transmitterGenerator, receiverGenerator, earthRotation, gnssParametrization, comm);\n    receiverGenerator->preprocessing(gnss.get(), comm);\n    gnss->synchronizeTransceivers(comm);\n    transmitterGenerator = nullptr;\n    receiverGenerator    = nullptr;\n    gnssParametrization  = nullptr;\n    earthRotation        = nullptr;\n    logInfo<<\"  transmitter: \"<<std::count_if(gnss->transmitters.begin(), gnss->transmitters.end(), [](auto t) {return t->useable();})<<Log::endl;\n    logInfo<<\"  receiver:    \"<<std::count_if(gnss->receivers.begin(),    gnss->receivers.end(),    [](auto r) {return r->useable();})<<Log::endl;\n    if(!std::any_of(gnss->transmitters.begin(), gnss->transmitters.end(), [](auto trans){return trans->useable();}))\n    {\n      logWarningOnce<<times.front().dateTimeStr()<<\" - \"<<times.back().dateTimeStr()<<\": no useable transmitters\"<<Log::endl;\n      return;\n    }\n    if(!std::any_of(gnss->receivers.begin(), gnss->receivers.end(), [](auto recv){return recv->useable();}))\n    {\n      logWarningOnce<<times.front().dateTimeStr()<<\" - \"<<times.back().dateTimeStr()<<\": no useable receivers\"<<Log::endl;\n      return;\n    }\n\n    // count observation types\n    // -----------------------\n    logInfo<<\"types and number of observations:\"<<Log::endl;\n    std::vector<GnssType> types = gnss->types(~(GnssType::PRN + GnssType::FREQ_NO));\n    Vector countTypes(types.size());\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n        for(UInt idEpoch=0; idEpoch<recv->idEpochSize(); idEpoch++)\n          for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n          {\n            auto obs = recv->observation(idTrans, idEpoch);\n            if(obs)\n              for(UInt idType=0; idType<obs->size(); idType++)\n              {\n                const UInt idx = GnssType::index(types, obs->at(idType).type);\n                if(idx != NULLINDEX)\n                  countTypes(idx)++;\n              }\n          }\n    Parallel::reduceSum(countTypes, 0, comm);\n\n    for(UInt idType=0; idType<types.size(); idType++)\n      logInfo<<\"  \"<<types.at(idType).str()<<\":\"<<countTypes(idType)%\"%10i\"s<<Log::endl;\n    logInfo<<\"        + =========\"<<Log::endl;\n    logInfo<<\"  total:\"<<sum(countTypes)%\"%11i\"s<<Log::endl;\n\n    UInt countTracks = 0;\n    for(auto recv : gnss->receivers)\n      if(recv->isMyRank())\n        countTracks += recv->tracks.size();\n    Parallel::reduceSum(countTracks, 0, comm);\n    logInfo<<\"  number of tracks: \"<<countTracks<<Log::endl;\n\n    // Processing steps\n    // ----------------\n    GnssProcessingStep::State state(gnss, comm);\n    processingSteps->process(state);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssReceiverDefinitionCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssReceiverDefinitionCreate.cpp\n*\n* @brief Create GNSS receiver definition file.\n**\n* @author Sebastian Strasser\n* @date 2018-08-28\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate a \\file{GNSS receiver definition file}{gnssReceiverDefinition}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create GNSS receiver definition file.\n* @ingroup programsGroup */\nclass GnssReceiverDefinitionCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssReceiverDefinitionCreate, SINGLEPROCESS, \"Create GNSS receiver definition file.\", Gnss)\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, GnssReceiverDefinitionPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    var = GnssReceiverDefinitionPtr(new GnssReceiverDefinition);\n\n    readConfig(config, \"name\",     var->name,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",   var->serial,  Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"version\",  var->version, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",  var->comment, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"gnssType\", var->types,   Config::OPTIONAL, \"\",  \"\");\n    endSequence(config);\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GnssReceiverDefinitionCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<GnssReceiverDefinitionPtr> receivers;\n\n    readConfig(config, \"outputfileGnssReceiverDefinition\", fileNameOut, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"receiverDefinition\",               receivers,   Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"write GNSS receiver definition <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGnssReceiverDefinition(fileNameOut, receivers);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssResiduals2AccuracyDefinition.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssResiduals2AccuracyDefinition.cpp\n*\n* @brief Compute antenna accuracies from observation residuals.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-19\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute antenna accuracies from observation \\configFile{inputfileResiduals}{instrument}.\nThe \\configFile{inputfileStationInfo}{platform} is needed to assign\nthe residuals to the equipped antenna at observation times.\n\nThe \\configFile{outputfileAccuracyDefinition}{gnssAntennaDefinition} contains\nat first step the same accuracy information for all antennas as the input file.\nOnly the azimuth~$A$ and elevation~$E$ dependent grid points of the patterns\nwhere enough residuals are available ($>$ \\config{minRedundancy})\nare replaced by estimated accuracy\n\\begin{equation}\n \\sigma(A,E) = \\sqrt{\\frac{\\sum_i e_i^2(A,E)}{\\sum_i r_i(A,E)}},\n\\end{equation}\nwhere $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the\ncorresponding redundancies (number of observations minus the contribution to\nthe estimated parameters).\n\nThe \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} can be modified\nto the demands before with \\program{GnssAntennaDefinitionCreate}\n(e.g. with \\config{antenna:resample}).\n\nTo verify the results the \\configFile{outputfileAntennaMean}{gnssAntennaDefinition}\nand the accumulated \\configFile{outputfileAntennaRedundancy}{gnssAntennaDefinition}\nof the computed pattern grid points can be written.\n\nExample: Analysis of TerraSAR-X residuals of one month shows that low elevation\nGPS satellites are not tracked by the onboard receiver. An estimation of accuracies\nfor these directions is not possible from the residuals and the apriori accuracies\nare left untouched. The other directions show very low phase noise hardly elevation\nand azimuth dependent for L2W. A nearly zero mean indicates the use of adequate antennca\ncenter variations in the processing.\n\n\\fig{!hb}{0.8}{gnssResiduals2AccuracyDefinition}{fig:gnssResiduals2AccuracyDefinition}{L2W accuracies of TerraSAR-X determined from residuals of one month}\n\nSee also \\program{GnssResiduals2TransmitterAccuracyDefinition}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/filePlatform.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute antenna definition from observation residuals.\n* @ingroup programsGroup */\nclass GnssResiduals2AccuracyDefinition\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssResiduals2AccuracyDefinition, SINGLEPROCESS, \"Compute accuracy definition from observation residuals\", Gnss)\nGROOPS_RENAMED_PROGRAM(GnssResiduals2AntennaDefinition, GnssResiduals2AccuracyDefinition, date2time(2020, 6, 26))\n\n/***********************************************/\n\nvoid GnssResiduals2AccuracyDefinition::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameAntennaMean, fileNameAntennaAccuracy, fileNameAntennaRedundancy;\n    FileName              fileNameStationInfo, fileNameAntenna;\n    std::vector<FileName> fileNameResiduals;\n    Bool                  isTransmitter;\n    Double                thresholdOutlier, minRedundancy;\n\n    renameDeprecatedConfig(config, \"outputfileAntennaDefinition\", \"outputfileAntennaMean\", date2time(2020, 7, 4));\n\n    readConfig(config, \"outputfileAccuracyDefinition\", fileNameAntennaAccuracy,   Config::OPTIONAL, \"\",   \"elevation and azimuth dependent accuracy\");\n    readConfig(config, \"outputfileAntennaMean\",        fileNameAntennaMean,       Config::OPTIONAL, \"\",   \"weighted mean of the residuals\");\n    readConfig(config, \"outputfileAntennaRedundancy\",  fileNameAntennaRedundancy, Config::OPTIONAL, \"\",   \"redundancy of adjustment\");\n    readConfig(config, \"inputfileAccuracyDefinition\",  fileNameAntenna,           Config::MUSTSET,  \"\",   \"apriori accuracies\");\n    readConfig(config, \"inputfileStationInfo\",         fileNameStationInfo,       Config::MUSTSET,  \"\",   \"to assign residuals to antennas\");\n    readConfig(config, \"isTransmitter\",                isTransmitter,             Config::DEFAULT,  \"0\",  \"stationInfo is of a transmitter\");\n    readConfig(config, \"thresholdOutlier\",             thresholdOutlier,          Config::DEFAULT,  \"10\", \"ignore residuals with sigma/sigma0 greater than threshold\");\n    readConfig(config, \"minRedundancy\",                minRedundancy,             Config::DEFAULT,  \"3\",  \"min number of residuals. to estimate sigma\");\n    readConfig(config, \"inputfileResiduals\",           fileNameResiduals,         Config::MUSTSET,  \"\",   \"GNSS receiver residuals\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    Platform stationInfo;\n    if(!fileNameStationInfo.empty())\n      readFilePlatform(fileNameStationInfo, stationInfo);\n\n    GnssType typePRN;\n    if(isTransmitter)\n      typePRN = GnssType(\"***\"+stationInfo.markerNumber);\n\n    std::vector<GnssAntennaDefinitionPtr> antennaList;\n    if(!fileNameAntenna.empty())\n    {\n      readFileGnssAntennaDefinition(fileNameAntenna, antennaList);\n      stationInfo.fillGnssAntennaDefinition(antennaList);\n    }\n\n    // ============================\n\n    for(const FileName &fileName : fileNameResiduals)\n    {\n      logStatus<<\"read GNSS residuals <\"<<fileName<<\">\"<<Log::endl;\n      if(!System::exists(fileName))\n      {\n        logWarning<<\"file not exist -> continue\"<<Log::endl;\n        continue;\n      }\n\n      InstrumentFile fileReceiver(fileName);\n      for(UInt arcNo=0; arcNo<fileReceiver.arcCount(); arcNo++)\n      {\n        GnssReceiverArc arc = fileReceiver.readArc(arcNo);\n        for(auto &epoch : arc)\n        {\n          // find antenna for epoch\n          auto ant= stationInfo.findEquipment<PlatformGnssAntenna>(epoch.time);\n          if(!ant)\n            continue;\n          GnssAntennaDefinitionPtr antenna = ant->antennaDef;\n          if(!antenna)\n            throw(Exception(epoch.time.dateTimeStr()+\": antenna not found: \"+ant->str()));\n\n          UInt idObs = 0;\n          for(GnssType satType : epoch.satellite)\n          {\n            // find type for the satellite system\n            UInt idType = 0;\n            while(epoch.obsType.at(idType) != satType)\n              idType++;\n\n            // azimuth and elevation\n            if((epoch.obsType.at(idType+0) != (GnssType::AZIMUT    + GnssType::L1)) ||\n               (epoch.obsType.at(idType+1) != (GnssType::ELEVATION + GnssType::L1)) ||\n               (epoch.obsType.at(idType+2) != (GnssType::AZIMUT    + GnssType::L2)) ||\n               (epoch.obsType.at(idType+3) != (GnssType::ELEVATION + GnssType::L2)))\n              throw(Exception(\"azimuth and elevation expected\"));\n\n            Double azimuth   = epoch.observation.at(idObs+0);\n            Double elevation = epoch.observation.at(idObs+1);\n            if(isTransmitter)\n            {\n              azimuth   = epoch.observation.at(idObs+2);\n              elevation = epoch.observation.at(idObs+3);\n            }\n\n            idObs  += 4;  // skip azimuth and elevation\n            idType += 4;\n\n            // resiudals, redundancy, sigma/sigma0\n            while((idType<epoch.obsType.size()) && (idObs<epoch.observation.size()) && (epoch.obsType.at(idType) == satType))\n            {\n              GnssType type  = epoch.obsType.at(idType++);\n              Double   value = epoch.observation.at(idObs++);\n\n              Double redundancy=0, sigma=0;\n              if((idType < epoch.obsType.size()) && (type == epoch.obsType.at(idType))) // next redundancy?\n              {\n                type       = epoch.obsType.at(idType++);\n                redundancy = epoch.observation.at(idObs++);\n              }\n              if((idType < epoch.obsType.size()) && (type == epoch.obsType.at(idType))) // next sigma?\n              {\n                type  = epoch.obsType.at(idType++);\n                sigma = epoch.observation.at(idObs++);\n              }\n              while((idType < epoch.obsType.size()) && (type == epoch.obsType.at(idType))) // other additional information?\n                idObs++, idType++;\n\n              if(value)\n                for(GnssAntennaPattern &pattern : antenna->patterns)\n                  if(type+satType == pattern.type+typePRN)\n                  {\n                    const UInt idxL = static_cast<UInt>(std::round((Double(azimuth)+2*PI)/(2*PI)*pattern.pattern.rows()))%pattern.pattern.rows();\n                    const UInt idxB = static_cast<UInt>(std::round((PI/2-Double(elevation))/Double(pattern.dZenit)));\n                    if(idxB >= pattern.pattern.columns())\n                      break;\n\n                    if(!pattern.count.size())\n                    {\n                      pattern.sum        = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                      pattern.ePe        = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                      pattern.redundancy = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                      pattern.count      = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                    }\n\n                    // residuals?\n                    if((redundancy > 0) && (sigma > 0) && (sigma <= thresholdOutlier))\n                    {\n                      const Double p = 1./std::pow(sigma, 2); // weight\n                      pattern.ePe(idxL,idxB)        += std::pow(value, 2);\n                      pattern.redundancy(idxL,idxB) += redundancy;\n                      pattern.sum(idxL,idxB)        += p * value;\n                      pattern.count(idxL,idxB)      += p;\n                    }\n\n                    // observations?\n                    if(std::isnan(redundancy) || (redundancy <= 0))\n                    {\n                      pattern.ePe(idxL,idxB)        += std::pow(value, 2);\n                      pattern.redundancy(idxL,idxB) += 1;\n                      pattern.sum(idxL,idxB)        += value;\n                      pattern.count(idxL,idxB)      += 1;\n                    }\n\n                    break;\n                  }\n            } // while()\n          } // for(satType)\n        } // for(epoch)\n      } // for(arcNo)\n    } // for(idFile)\n\n    // ============================\n\n    // only one value at zenith\n    for(auto &antenna : antennaList)\n      for(auto &pattern : antenna->patterns)\n        if(pattern.count.size())\n        {\n          copy(Vector(pattern.pattern.rows(), sum(pattern.sum       .column(0))), pattern.sum       .column(0));\n          copy(Vector(pattern.pattern.rows(), sum(pattern.ePe       .column(0))), pattern.ePe       .column(0));\n          copy(Vector(pattern.pattern.rows(), sum(pattern.redundancy.column(0))), pattern.redundancy.column(0));\n          copy(Vector(pattern.pattern.rows(), sum(pattern.count     .column(0))), pattern.count     .column(0));\n        }\n\n    // ============================\n\n\n    if(!fileNameAntennaAccuracy.empty())\n    {\n      logStatus<<\"write accuracy definition <\"<<fileNameAntennaAccuracy<<\">\"<<Log::endl;\n      for(auto &antenna : antennaList)\n        for(auto &pattern : antenna->patterns)\n          if(pattern.count.size())\n          {\n            pattern.offset = Vector3d();\n            for(UInt i=0; i<pattern.pattern.rows(); i++)\n              for(UInt k=0; k<pattern.pattern.columns(); k++)\n                if(pattern.redundancy(i, k) >= minRedundancy)\n                  pattern.pattern(i, k) = std::sqrt(pattern.ePe(i, k)/pattern.redundancy(i, k));\n          }\n      writeFileGnssAntennaDefinition(fileNameAntennaAccuracy, antennaList);\n    }\n\n    for(auto &antenna : antennaList)\n      for(auto &pattern : antenna->patterns)\n      {\n        pattern.offset   = Vector3d();\n        pattern.pattern *= NAN_EXPR;\n      }\n\n    if(!fileNameAntennaMean.empty())\n    {\n      logStatus<<\"write antenna definition <\"<<fileNameAntennaMean<<\">\"<<Log::endl;\n      for(auto &antenna : antennaList)\n        for(auto &pattern : antenna->patterns)\n          if(pattern.count.size())\n            for(UInt i=0; i<pattern.pattern.rows(); i++)\n              for(UInt k=0; k<pattern.pattern.columns(); k++)\n                pattern.pattern(i, k) = pattern.sum(i, k)/pattern.count(i, k);\n      writeFileGnssAntennaDefinition(fileNameAntennaMean, antennaList);\n    }\n\n    if(!fileNameAntennaRedundancy.empty())\n    {\n      logStatus<<\"write redundancy <\"<<fileNameAntennaRedundancy<<\">\"<<Log::endl;\n      for(auto &antenna : antennaList)\n        for(auto &pattern : antenna->patterns)\n          if(pattern.count.size())\n            for(UInt i=0; i<pattern.pattern.rows(); i++)\n              for(UInt k=0; k<pattern.pattern.columns(); k++)\n                if(pattern.redundancy(i, k) >= minRedundancy)\n                  pattern.pattern(i, k) = pattern.redundancy(i, k);\n      writeFileGnssAntennaDefinition(fileNameAntennaRedundancy, antennaList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssResiduals2Skyplot.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssResiduals2Skyplot.cpp\n*\n* @brief Convert residuals into griddedData format for plotting.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-07-12\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite GNSS residuals together with azimuth and elevation to be plotted with \\program{PlotMap}.\nAzimuth and elevation are written as ellipsoidal longitude and latitude in a \\file{griddedData file}{griddedData}.\nThe choosen ellipsoid parameters \\config{R} and \\config{inverseFlattening} are arbitrary but should be the same\nas in \\program{PlotMap}. If with \\configClass{typeTransmitter}{gnssType} (e.g. '\\verb|***G18|')\na single transmitter is selected the azimuth and elevation are computed from the transmitter point of view.\n\nFor each GNSS \\configClass{type}{gnssType} an extra data column is created.\n\nA \\file{GNSS residual file}{instrument} includes additional information\nbesides the residuals, which can also be selected with \\configClass{type}{gnssType}\n\\begin{itemize}\n\\item \\verb|A1*|, \\verb|E1*|: azimuth and elevation at receiver\n\\item \\verb|A2*|, \\verb|E2*|: azimuth and elevation at transmitter\n\\item \\verb|I**|: Estimated slant total electron content (STEC)\n\\end{itemize}\n\nFurthermore these files may include for each residual \\configClass{type}{gnssType}\ninformation about the redundancy and the accuracy relation $\\sigma/\\sigma_0$\nof the estimated $\\sigma$ versus the apriori $\\sigma_0$ from the least squares adjustment.\nThe 3 values (residuals, redundancy, $\\sigma/\\sigma_0$) are coded with the same type.\nTo get access to all values the corresponding type must be repeated in \\configClass{type}{gnssType}.\n\n\\fig{!hb}{0.5}{gnssResiduals2Skyplot}{fig:gnssResiduals2Skyplot}{GPS C2W residuals of GRAZ station at 2012-01-01}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert residuals into griddedData format for plotting.\n* @ingroup programsGroup */\nclass GnssResiduals2Skyplot\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssResiduals2Skyplot, SINGLEPROCESS, \"Convert residuals into griddedData format for plotting\", Gnss, Grid)\nGROOPS_RENAMED_PROGRAM(GnssResiduals2GriddedData, GnssResiduals2Skyplot, date2time(2019, 9, 9))\n\n/***********************************************/\n\nvoid GnssResiduals2Skyplot::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameGriddedData;\n    std::vector<FileName> fileNameResiduals;\n    std::vector<GnssType> types;\n    GnssType              typeTransmitter;\n    Double                a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGriddedData, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"type\",                  types,               Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"typeTransmitter\",       typeTransmitter,     Config::OPTIONAL, \"\", \"choose transmitter view, e.g. '***G18'\");\n    readConfig(config, \"inputfileResiduals\",    fileNameResiduals,   Config::MUSTSET,  \"\", \"GNSS receiver residuals\");\n    readConfig(config, \"R\",                     a,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",     f,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    Ellipsoid                        ellipsoid(a, f);\n    std::vector<Vector3d>            points;\n    std::vector<std::vector<Double>> values(types.size());\n    for(const FileName &fileName : fileNameResiduals)\n    {\n      logStatus<<\"read GNSS residuals <\"<<fileName<<\">\"<<Log::endl;\n      if(!System::exists(fileName))\n      {\n        logWarning<<\"file not exist -> continue\"<<Log::endl;\n        continue;\n      }\n\n      InstrumentFile fileReceiver(fileName);\n      for(UInt arcNo=0; arcNo<fileReceiver.arcCount(); arcNo++)\n      {\n        GnssReceiverArc arc = fileReceiver.readArc(arcNo);\n        for(auto &epoch : arc)\n        {\n          UInt idObs = 0;\n          for(GnssType satType : epoch.satellite)\n          {\n            // find type for the satellite system\n            UInt idType = std::distance(epoch.obsType.begin(), std::find(epoch.obsType.begin(), epoch.obsType.end(), satType));\n\n            // azimuth and elevation\n            if((epoch.obsType.at(idType+0) != (GnssType::AZIMUT    + GnssType::L1)) ||\n               (epoch.obsType.at(idType+1) != (GnssType::ELEVATION + GnssType::L1)) ||\n               (epoch.obsType.at(idType+2) != (GnssType::AZIMUT    + GnssType::L2)) ||\n               (epoch.obsType.at(idType+3) != (GnssType::ELEVATION + GnssType::L2)))\n              throw(Exception(\"azimuth and elevation expected\"));\n\n            Double azimuth   = epoch.observation.at(idObs+0);\n            Double elevation = epoch.observation.at(idObs+1);\n            if(!typeTransmitter.hasWildcard(GnssType::PRN)) // isTransmitter\n            {\n              azimuth   = epoch.observation.at(idObs+2);\n              elevation = epoch.observation.at(idObs+3);\n            }\n            const Vector3d point = ellipsoid(Angle(azimuth), Angle(elevation), 0);\n\n            idObs  += 4;  // skip azimuth and elevation\n            idType += 4;\n\n            Bool                  found = FALSE;\n            std::vector<Double>   valuesPerPoint(types.size(), NAN_EXPR);\n            std::vector<GnssType> typesTmp = types;\n            while((idType<epoch.obsType.size()) && (idObs<epoch.observation.size()) && (epoch.obsType.at(idType) == satType))\n            {\n              const GnssType type  = epoch.obsType.at(idType++) + satType;\n              const Double   value = epoch.observation.at(idObs++);\n              const UInt     idx   = GnssType::index(typesTmp, type);\n              if((idx != NULLINDEX) && (type == typeTransmitter) && value)\n              {\n                valuesPerPoint.at(idx) = value;\n                typesTmp.at(idx) = GnssType(static_cast<UInt64>(-1));\n                found = TRUE;\n              }\n            } // while()\n\n            if(found)\n            {\n              points.push_back(point);\n              for(UInt i=0; i<values.size(); i++)\n                values.at(i).push_back(valuesPerPoint.at(i));\n            }\n          } // for(satType)\n        } // for(epoch)\n      } // for(arcNo)\n    } // for(idFile)\n\n    // ============================\n\n    logStatus<<\"save values to file <\"<<fileNameGriddedData<<\">\"<<Log::endl;\n    GriddedData griddedData(ellipsoid, points, std::vector<Double>(points.size(), 1), values);\n    writeFileGriddedData(fileNameGriddedData, griddedData);\n    MiscGriddedData::printStatistics(griddedData);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssResiduals2TransmitterAccuracyDefinition.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssResiduals2TransmitterAccuracyDefinition.cpp\n*\n* @brief Compute antenna accuracies from observation residuals.\n*\n* @author Torsten Mayer-Guerr\n* @date 2024-08-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute antenna accuracies from observation \\configFile{inputfileResiduals}{instrument}.\nThe \\configFile{inputfileTransmitterInfo}{platform} is needed to assign\nthe residuals to the equipped antenna at observation times.\n\nThe \\configFile{outputfileAccuracyDefinition}{gnssAntennaDefinition} contains\nat first step the same accuracy information for all antennas as the input file.\nOnly the azimuth~$A$ and elevation~$E$ dependent grid points of the patterns\nwhere enough residuals are available ($>$ \\config{minRedundancy})\nare replaced by estimated accuracy\n\\begin{equation}\n \\sigma(A,E) = \\sqrt{\\frac{\\sum_i e_i^2(A,E)}{\\sum_i r_i(A,E)}},\n\\end{equation}\nwhere $e_i$ are the azimuth and elevation dependent residuals and $r_i$ the\ncorresponding redundancies (number of observations minus the contribution to\nthe estimated parameters).\n\nThe \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} can be modified\nto the demands before with \\program{GnssAntennaDefinitionCreate}\n(e.g. with \\config{antenna:resample}).\n\nTo verify the results the \\configFile{outputfileAntennaMean}{gnssAntennaDefinition}\nand the accumulated \\configFile{outputfileAntennaRedundancy}{gnssAntennaDefinition}\nof the computed pattern grid points can be written.\n\nSee also \\program{GnssResiduals2AccuracyDefinition}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/filePlatform.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute antenna definition from observation residuals.\n* @ingroup programsGroup */\nclass GnssResiduals2TransmitterAccuracyDefinition\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssResiduals2TransmitterAccuracyDefinition, SINGLEPROCESS, \"Compute accuracy definition from observation residuals\", Gnss)\n\n/***********************************************/\n\nvoid GnssResiduals2TransmitterAccuracyDefinition::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameAntennaMean, fileNameAntennaAccuracy, fileNameAntennaRedundancy;\n    FileName              fileNameTransmitterInfo, fileNameAntenna;\n    std::vector<FileName> fileNameResiduals;\n    Double                minRedundancy;\n\n    readConfig(config, \"outputfileAccuracyDefinition\", fileNameAntennaAccuracy,   Config::OPTIONAL, \"\",   \"elevation and azimuth dependent accuracy\");\n    readConfig(config, \"outputfileAntennaMean\",        fileNameAntennaMean,       Config::OPTIONAL, \"\",   \"weighted mean of the residuals\");\n    readConfig(config, \"outputfileAntennaRedundancy\",  fileNameAntennaRedundancy, Config::OPTIONAL, \"\",   \"redundancy of adjustment\");\n    readConfig(config, \"inputfileAccuracyDefinition\",  fileNameAntenna,           Config::MUSTSET,  \"\",   \"apriori accuracies\");\n    readConfig(config, \"inputfileTransmitterInfo\",     fileNameTransmitterInfo,   Config::MUSTSET,  \"\",   \"to assign residuals to antennas\");\n    readConfig(config, \"minRedundancy\",                minRedundancy,             Config::DEFAULT,  \"3\",  \"min number of residuals. to estimate sigma\");\n    readConfig(config, \"inputfileResiduals\",           fileNameResiduals,         Config::MUSTSET,  \"\",   \"GNSS receiver residuals\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<GnssAntennaDefinitionPtr> antennaList;\n    readFileGnssAntennaDefinition(fileNameAntenna, antennaList);\n\n    std::map<GnssType, Platform> platforms;\n    for(const FileName &fileName : fileNameResiduals)\n    {\n      logStatus<<\"read GNSS residuals <\"<<fileName<<\">\"<<Log::endl;\n      if(!System::exists(fileName))\n      {\n        logWarning<<\"file not exist -> continue\"<<Log::endl;\n        continue;\n      }\n\n      InstrumentFile fileReceiver(fileName);\n      for(UInt arcNo=0; arcNo<fileReceiver.arcCount(); arcNo++)\n      {\n        GnssReceiverArc arc = fileReceiver.readArc(arcNo);\n        for(auto &epoch : arc)\n        {\n          UInt idObs = 0;\n          for(GnssType satType : epoch.satellite)\n          {\n            if(platforms.find(satType) == platforms.end())\n            {\n              VariableList fileNameVariableList;\n              fileNameVariableList.setVariable(\"prn\", satType.prnStr());\n              readFilePlatform(fileNameTransmitterInfo(fileNameVariableList), platforms[satType]);\n              platforms[satType].fillGnssAntennaDefinition(antennaList);\n            }\n            // find antenna for epoch\n            auto ant = platforms[satType].findEquipment<PlatformGnssAntenna>(epoch.time);\n            if(!ant)\n              continue;\n            GnssAntennaDefinitionPtr antenna = ant->antennaDef;\n            if(!antenna)\n              continue;\n              // throw(Exception(epoch.time.dateTimeStr()+\": antenna not found: \"+ant->str()));\n\n            // find type for the satellite system\n            UInt idType = 0;\n            while(epoch.obsType.at(idType) != satType)\n              idType++;\n\n            // azimuth and elevation\n            if((epoch.obsType.at(idType+0) != (GnssType::AZIMUT    + GnssType::L1)) ||\n               (epoch.obsType.at(idType+1) != (GnssType::ELEVATION + GnssType::L1)) ||\n               (epoch.obsType.at(idType+2) != (GnssType::AZIMUT    + GnssType::L2)) ||\n               (epoch.obsType.at(idType+3) != (GnssType::ELEVATION + GnssType::L2)))\n              throw(Exception(\"azimuth and elevation expected\"));\n\n            const Double azimuth   = epoch.observation.at(idObs+2); // transmitter\n            const Double elevation = epoch.observation.at(idObs+3); // transmitter\n\n            idObs  += 4;  // skip azimuth and elevation\n            idType += 4;\n\n            // resiudals, redundancy, sigma/sigma0\n            while((idType<epoch.obsType.size()) && (idObs<epoch.observation.size()) && (epoch.obsType.at(idType) == satType))\n            {\n              GnssType type  = epoch.obsType.at(idType++);\n              Double   value = epoch.observation.at(idObs++);\n\n              Double redundancy=0, sigma=0;\n              if((idType < epoch.obsType.size()) && (type == epoch.obsType.at(idType))) // next redundancy?\n              {\n                type       = epoch.obsType.at(idType++);\n                redundancy = epoch.observation.at(idObs++);\n              }\n              if((idType < epoch.obsType.size()) && (type == epoch.obsType.at(idType))) // next sigma?\n              {\n                type  = epoch.obsType.at(idType++);\n                sigma = epoch.observation.at(idObs++);\n              }\n              while((idType < epoch.obsType.size()) && (type == epoch.obsType.at(idType))) // other additional information?\n                idObs++, idType++;\n\n              if(!value)\n                continue;\n\n\n              for(GnssAntennaPattern &pattern : antenna->patterns)\n                if(type+satType == pattern.type)\n                {\n                  const UInt idxL = static_cast<UInt>(std::round((Double(azimuth)+2*PI)/(2*PI)*pattern.pattern.rows()))%pattern.pattern.rows();\n                  const UInt idxB = static_cast<UInt>(std::round((PI/2-Double(elevation))/Double(pattern.dZenit)));\n                  if(idxB >= pattern.pattern.columns())\n                    break;\n\n                  if(!pattern.count.size())\n                  {\n                    pattern.sum        = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                    pattern.ePe        = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                    pattern.redundancy = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                    pattern.count      = Matrix(pattern.pattern.rows(), pattern.pattern.columns());\n                  }\n\n                  // residuals?\n                  if((redundancy > 0) && (sigma > 0))\n                  {\n                    const Double p = 1./std::pow(sigma, 2); // weight\n                    pattern.ePe(idxL,idxB)        += p * std::pow(value, 2);\n                    pattern.redundancy(idxL,idxB) += redundancy;\n                    pattern.sum(idxL,idxB)        += p * value;\n                    pattern.count(idxL,idxB)      += p;\n                  }\n                }\n            } // while()\n          } // for(satType)\n        } // for(epoch)\n      } // for(arcNo)\n    } // for(idFile)\n\n    // ============================\n\n    // only one value at zenith\n    for(auto &antenna : antennaList)\n      for(auto &pattern : antenna->patterns)\n        if(pattern.count.size())\n        {\n          copy(Vector(pattern.pattern.rows(), sum(pattern.sum       .column(0))), pattern.sum       .column(0));\n          copy(Vector(pattern.pattern.rows(), sum(pattern.ePe       .column(0))), pattern.ePe       .column(0));\n          copy(Vector(pattern.pattern.rows(), sum(pattern.redundancy.column(0))), pattern.redundancy.column(0));\n          copy(Vector(pattern.pattern.rows(), sum(pattern.count     .column(0))), pattern.count     .column(0));\n        }\n\n    // ============================\n\n\n    if(!fileNameAntennaAccuracy.empty())\n    {\n      logStatus<<\"write accuracy definition <\"<<fileNameAntennaAccuracy<<\">\"<<Log::endl;\n      for(auto &antenna : antennaList)\n        for(auto &pattern : antenna->patterns)\n          if(pattern.count.size())\n          {\n            pattern.offset = Vector3d();\n            for(UInt i=0; i<pattern.pattern.rows(); i++)\n              for(UInt k=0; k<pattern.pattern.columns(); k++)\n                if(pattern.redundancy(i, k) >= minRedundancy)\n                  pattern.pattern(i, k) = std::sqrt(pattern.ePe(i, k)/pattern.redundancy(i, k)/pattern.count(i, k));\n          }\n      writeFileGnssAntennaDefinition(fileNameAntennaAccuracy, antennaList);\n    }\n\n    for(auto &antenna : antennaList)\n      for(auto &pattern : antenna->patterns)\n      {\n        pattern.offset   = Vector3d();\n        pattern.pattern *= NAN_EXPR;\n      }\n\n    if(!fileNameAntennaMean.empty())\n    {\n      logStatus<<\"write antenna definition <\"<<fileNameAntennaMean<<\">\"<<Log::endl;\n      for(auto &antenna : antennaList)\n        for(auto &pattern : antenna->patterns)\n          if(pattern.count.size())\n            for(UInt i=0; i<pattern.pattern.rows(); i++)\n              for(UInt k=0; k<pattern.pattern.columns(); k++)\n                pattern.pattern(i, k) = pattern.sum(i, k)/pattern.count(i, k);\n      writeFileGnssAntennaDefinition(fileNameAntennaMean, antennaList);\n    }\n\n    if(!fileNameAntennaRedundancy.empty())\n    {\n      logStatus<<\"write redundancy <\"<<fileNameAntennaRedundancy<<\">\"<<Log::endl;\n      for(auto &antenna : antennaList)\n        for(auto &pattern : antenna->patterns)\n          if(pattern.count.size())\n            for(UInt i=0; i<pattern.pattern.rows(); i++)\n              for(UInt k=0; k<pattern.pattern.columns(); k++)\n                if(pattern.redundancy(i, k) >= minRedundancy)\n                  pattern.pattern(i, k) = pattern.redundancy(i, k);\n      writeFileGnssAntennaDefinition(fileNameAntennaRedundancy, antennaList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssSignalBias2Matrix.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssSignalBias2Matrix.cpp\n*\n* @brief Computes signal biases for a given type list.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-03-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes signal biases for a given list of \\configClass{types}{gnssType}.\nIf the type list is empty, all types contained in \\configFile{inputfileSignalBias}{gnssSignalBias} are used.\nThe resulting \\configFile{outputfileMatrix}{matrix} contains a vector with an entry for each type.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileStringTable.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Computes signal biases for a given type list.\n* @ingroup programsGroup */\nclass GnssSignalBias2Matrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssSignalBias2Matrix, SINGLEPROCESS, \"Computes signal biases for a given type list\", Gnss)\n\n\n/***********************************************/\n\nvoid GnssSignalBias2Matrix::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameSignalBias, fileNameMatrix, fileNameTypes;\n    std::vector<GnssType> types;\n\n    readConfig(config, \"outputfileMatrix\",    fileNameMatrix,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileTypes\",     fileNameTypes,      Config::OPTIONAL, \"\", \"ASCII list of types\");\n    readConfig(config, \"inputfileSignalBias\", fileNameSignalBias, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"types\",               types,              Config::OPTIONAL, \"\", \"if not set, all types in the file are used\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read signal bias file <\"<<fileNameSignalBias<<\">\"<<Log::endl;\n    GnssSignalBias signalBias;\n    readFileGnssSignalBias(fileNameSignalBias, signalBias);\n\n    if(types.size() == 0)\n      types = signalBias.types;\n    Vector bias = signalBias.compute(types);\n\n    if(!fileNameTypes.empty())\n    {\n      logStatus<<\"write types to file <\"<<fileNameTypes<<\">\"<<Log::endl;\n      std::vector<std::string> typeNames;\n      for(const auto &type : types)\n        typeNames.push_back(type.str());\n      writeFileStringList(fileNameTypes, typeNames);\n    }\n\n    logStatus<<\"write matrix to file <\"<<fileNameMatrix<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameMatrix, bias);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/gnssSimulateReceiver.cpp",
    "content": "/***********************************************/\n/**\n* @file gnssSimulateReceiver.cpp\n*\n* @brief GNSS receiver simulation.\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Gürr\n* @date 2014-09-25\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates observations from receivers to GNSS satellites.\nThese simulated observations can then be used in \\program{GnssProcessing}, for example to conduct closed-loop simulations.\n\nOne or more GNSS constellations must be defined via \\configClass{transmitter}{gnssTransmitterGeneratorType}.\nReceivers such as ground station networks or Low Earth Orbit (LEO) satellites can be defined via \\configClass{receiver}{gnssReceiverGeneratorType}.\n\nIf multiple receivers defined an \\configFile{outputfileGnssReceiver}{instrument} and \\configFile{outputfileClock}{instrument}\nare written for each single receiver with the \\reference{variable}{general.parser} \\verb|{station}| being replaced by the receiver name.\n\nA list of simulated observation types can be defined via \\configClass{observationType}{gnssType}. Noise can be added to both observations and clock errors\nvia \\configClass{noiseObervation}{noiseGeneratorType} and \\configClass{noiseClockReceiver}{noiseGeneratorType}, respectively. Observation noise is\ninterpreted as a factor that is multiplied to the accuracy derived from the accuracy pattern of the respective observation type\n(see \\configFile{inputfileAccuracyDefinition}{gnssAntennaDefinition} in \\configClass{receiver}{gnssReceiverGeneratorType}).\n\nThe \\configClass{parametrization}{gnssParametrizationType} are used to simulate a priori models (e.g. troposphere, signal biases).\nParameter settings and outputfiles are ignored.\n\nIf the program is run on multiple processes the \\configClass{receiver}{gnssReceiverGeneratorType}s\n(stations or LEO satellites) are distributed over the processes.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"gnss/gnss.h\"\n#include \"gnss/gnssObservation.h\"\n#include \"gnss/gnssTransmitterGenerator/gnssTransmitterGenerator.h\"\n#include \"gnss/gnssReceiverGenerator/gnssReceiverGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GNSS receiver simulation.\n* @ingroup programsGroup */\nclass GnssSimulateReceiver\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GnssSimulateReceiver, PARALLEL, \"GNSS receiver simulation\", Gnss, Simulation)\n\n/***********************************************/\n\nvoid GnssSimulateReceiver::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName                    fileNameReceiver, fileNameClock;\n    TimeSeriesPtr               timeSeries;\n    Double                      marginSeconds;\n    GnssTransmitterGeneratorPtr transmitterGenerator;\n    GnssReceiverGeneratorPtr    receiverGenerator;\n    GnssParametrizationPtr      gnssParametrization;\n    EarthRotationPtr            earthRotation;\n    NoiseGeneratorPtr           noiseClock, noiseObs;\n    std::vector<GnssType>       obsTypes;\n\n    readConfig(config, \"outputfileGnssReceiver\",  fileNameReceiver,     Config::MUSTSET,  \"gnssReceiver_{loopTime:%D}.{station}.dat.gz\", \"variable {station} available, simulated observations\");\n    readConfig(config, \"outputfileClock\",         fileNameClock,        Config::OPTIONAL, \"clock_{loopTime:%D}.{station}.dat\", \"variable {station} available, simulated receiver clock errors\");\n    readConfig(config, \"timeSeries\",              timeSeries,           Config::MUSTSET,  \"\",    \"defines observation epochs\");\n    readConfig(config, \"timeMargin\",              marginSeconds,        Config::DEFAULT,  \"0.1\", \"[seconds] margin to consider two times identical\");\n    readConfig(config, \"transmitter\",             transmitterGenerator, Config::MUSTSET,  \"\",    \"constellation of GNSS satellites\");\n    readConfig(config, \"receiver\",                receiverGenerator,    Config::MUSTSET,  \"\",    \"ground station network or LEO satellite\");\n    readConfig(config, \"earthRotation\",           earthRotation,        Config::MUSTSET,  \"\",    \"apriori earth rotation\");\n    readConfig(config, \"parametrization\",         gnssParametrization,  Config::DEFAULT,  R\"([\"troposphere\"])\", \"models and parameters\");\n    readConfig(config, \"observationType\",         obsTypes,             Config::MUSTSET,  \"\",    \"simulated observation types\");\n    readConfig(config, \"noiseObservation\",        noiseObs,             Config::DEFAULT,  \"\",    \"[-] noise is multiplied with type accuracy pattern of receiver\");\n    readConfig(config, \"noiseClockReceiver\",      noiseClock,           Config::DEFAULT,  \"\",    \"[m] noise added to the simulated receiver clock\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    // init the GNSS system\n    // --------------------\n    logInfo<<\"Init GNSS\"<<Log::endl;\n    std::sort(obsTypes.begin(), obsTypes.end());\n    std::vector<Time> times = timeSeries->times();\n    Gnss gnss;\n    gnss.init(obsTypes, times, seconds2time(marginSeconds), transmitterGenerator, receiverGenerator, earthRotation, gnssParametrization, comm);\n    receiverGenerator->simulation(noiseClock, noiseObs, &gnss, comm);\n    gnss.synchronizeTransceivers(comm);\n    logInfo<<\"  transmitter: \"<<std::count_if(gnss.transmitters.begin(), gnss.transmitters.end(), [](auto t) {return t->useable();})<<Log::endl;\n    logInfo<<\"  receiver:    \"<<std::count_if(gnss.receivers.begin(),    gnss.receivers.end(),    [](auto r) {return r->useable();})<<Log::endl;\n    if(!std::any_of(gnss.transmitters.begin(), gnss.transmitters.end(), [](auto trans){return trans->useable();}))\n    {\n      logWarningOnce<<times.front().dateTimeStr()<<\" - \"<<times.back().dateTimeStr()<<\": no useable transmitters\"<<Log::endl;\n      return;\n    }\n    if(!std::any_of(gnss.receivers.begin(), gnss.receivers.end(), [](auto recv){return recv->useable();}))\n    {\n      logWarningOnce<<times.front().dateTimeStr()<<\" - \"<<times.back().dateTimeStr()<<\": no useable receivers\"<<Log::endl;\n      return;\n    }\n\n    // count observation types\n    // -----------------------\n    logInfo<<\"types and number of observations:\"<<Log::endl;\n    std::vector<GnssType> types = gnss.types(~(GnssType::PRN + GnssType::FREQ_NO));\n    Vector countTypes(types.size());\n    for(auto recv : gnss.receivers)\n      if(recv->isMyRank())\n        for(UInt idEpoch=0; idEpoch<recv->idEpochSize(); idEpoch++)\n          for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n          {\n            auto obs = recv->observation(idTrans, idEpoch);\n            if(obs)\n              for(UInt idType=0; idType<obs->size(); idType++)\n              {\n                const UInt idx = GnssType::index(types, obs->at(idType).type);\n                if(idx != NULLINDEX)\n                  countTypes(idx)++;\n              }\n          }\n    Parallel::reduceSum(countTypes, 0, comm);\n\n    for(UInt idType=0; idType<types.size(); idType++)\n      logInfo<<\"  \"<<types.at(idType).str()<<\":\"<<countTypes(idType)%\"%10i\"s<<Log::endl;\n    logInfo<<\"        + =========\"<<Log::endl;\n    logInfo<<\"  total:\"<<sum(countTypes)%\"%11i\"s<<Log::endl;\n\n    UInt countTracks = 0;\n    for(auto recv : gnss.receivers)\n      if(recv->isMyRank())\n        countTracks += recv->tracks.size();\n    Parallel::reduceSum(countTracks, 0, comm);\n    logInfo<<\"  number of tracks: \"<<countTracks<<Log::endl;\n\n    // ============================\n\n    // Write observations\n    // ------------------\n    if(!fileNameReceiver.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write receiver observations to files <\"<<fileNameReceiver(fileNameVariableList)<<\">\"<<Log::endl;\n      for(auto recv : gnss.receivers)\n        if(recv->isMyRank())\n        {\n          GnssReceiverArc arc;\n          for(UInt idEpoch=0; idEpoch<gnss.times.size(); idEpoch++)\n            if(recv->useable(idEpoch))\n            {\n              GnssReceiverEpoch epoch;\n              epoch.time       = gnss.times.at(idEpoch);\n              epoch.clockError = recv->clockError(idEpoch);\n\n              // get types\n              for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n                if(recv->observation(idTrans, idEpoch) && gnss.transmitters.at(idTrans)->useable(idEpoch))\n                  for(UInt idType=0; idType<recv->observation(idTrans, idEpoch)->size(); idType++)\n                    if(!recv->observation(idTrans, idEpoch)->at(idType).type.isInList(epoch.obsType))\n                      epoch.obsType.push_back(recv->observation(idTrans, idEpoch)->at(idType).type & ~(GnssType::PRN+GnssType::FREQ_NO));\n              std::sort(epoch.obsType.begin(), epoch.obsType.end());\n              if(!epoch.obsType.size())\n                continue;\n\n              for(UInt idTrans=0; idTrans<recv->idTransmitterSize(idEpoch); idTrans++)\n                if(recv->observation(idTrans, idEpoch) && gnss.transmitters.at(idTrans)->useable(idEpoch))\n                {\n                  const GnssObservation &obs = *recv->observation(idTrans, idEpoch);\n                  const GnssType prn = obs.at(0).type & (GnssType::SYSTEM + GnssType::PRN + GnssType::FREQ_NO);\n                  UInt idType = std::distance(epoch.obsType.begin(), std::find(epoch.obsType.begin(), epoch.obsType.end(), prn));\n\n                  epoch.satellite.push_back(prn);\n                  for(; (idType<epoch.obsType.size()) && (epoch.obsType.at(idType) == prn); idType++)\n                  {\n                    epoch.observation.push_back(NAN_EXPR);\n                    for(UInt i=0; i<obs.size(); i++)\n                      if(obs.at(i).type == epoch.obsType.at(idType))\n                      {\n                        epoch.observation.back() = obs.at(i).observation;\n                        break;\n                      }\n                  }\n                } // for(idTrans)\n\n              if(epoch.satellite.size())\n                arc.push_back(epoch);\n            } // for(idEpoch)\n\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          InstrumentFile::write(fileNameReceiver(fileNameVariableList), arc);\n        } // for(recv)\n    } // if(fileNameReceiver)\n\n    // ============================\n\n    // write clock errors\n    // ------------------\n    if(!fileNameClock.empty())\n    {\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(\"station\", \"****\");\n      logStatus<<\"write receiver clocks to files <\"<<fileNameClock(fileNameVariableList)<<\">\"<<Log::endl;\n      for(auto recv : gnss.receivers)\n        if(recv->isMyRank())\n        {\n          MiscValueArc arc;\n          for(UInt idEpoch=0; idEpoch<gnss.times.size(); idEpoch++)\n            if(recv->useable(idEpoch))\n            {\n              MiscValueEpoch epoch;\n              epoch.time  = gnss.times.at(idEpoch);\n              epoch.value = recv->clockError(idEpoch);\n              arc.push_back(epoch);\n            }\n          fileNameVariableList.setVariable(\"station\", recv->name());\n          InstrumentFile::write(fileNameClock(fileNameVariableList), arc);\n        } // for(recv)\n    } // if(fileNameClock)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/instrumentGnssReceiver2TimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentGnssReceiver2TimeSeries.cpp\n*\n* @brief Convert gnssReceiver file into instrument(MISCVLAUES) file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-04-09\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert selected GNSS observations or residuals into a simpler time series format.\nThe \\config{outputfileTimeSeries} is an \\file{instrument file}{instrument} (MISCVALUES).\nFor each epoch the first data column contains the PRN, the second the satellite system,\nfollowed by a column for each GNSS \\configClass{type}{gnssType}.\nAs normally more than one GNSS transmitter is tracked per epoch, the output file\nhas several lines per observed epoch (epochs with the same time, one for each transmitter).\n\nThe second data column of the output contains a number representating the system\n\\begin{itemize}\n\\item 71: 'G', GPS\n\\item 82: 'R', GLONASS\n\\item 69: 'E', GALILEO\n\\item 67: 'C', BDS\n\\item 83: 'S', SBAS\n\\item 74: 'J', QZSS\n\\item 73: 'I', IRNSS .\n\\end{itemize}\n\nA \\file{GNSS residual file}{instrument} includes additional information\nbesides the residuals, which can also be selected with \\configClass{type}{gnssType}\n\\begin{itemize}\n\\item \\verb|A1*|, \\verb|E1*|: azimuth and elevation at receiver\n\\item \\verb|A2*|, \\verb|E2*|: azimuth and elevation at transmitter\n\\item \\verb|I**|: Estimated slant total electron content (STEC)\n\\end{itemize}\n\nFurthermore these files may include for each residual \\configClass{type}{gnssType}\ninformation about the redundancy and the accuracy relation $\\sigma/\\sigma_0$\nof the estimated $\\sigma$ versus the apriori $\\sigma_0$ from the least squares adjustment.\nThe three values (residuals, redundancy, $\\sigma/\\sigma_0$) are coded with the same type.\nTo get access to all values the corresponding type must be repeated in \\configClass{type}{gnssType}.\n\nExample: Selected GPS phase residuals (\\configClass{type}{gnssType}='\\verb|L1*G|' and \\configClass{type}{gnssType}='\\verb|L2*G|').\nPlotted with \\program{PlotGraph} with two \\configClass{layer:linesAndPoints}{plotGraphLayerType}\n(\\config{valueX}='\\verb|data0|',  \\config{valueY}='\\verb|100*data3+data1|' and \\config{valueY}='\\verb|100*data4+data1|' respectively).\n\\fig{!hb}{0.8}{instrumentGnssReceiver2TimeSeries}{fig:instrumentGnssReceiver2TimeSeries}{GPS residuals in cm, shifted by PRN}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert gnssReceiver file into instrument(MISCVLAUES) file.\n* @ingroup programsGroup */\nclass InstrumentGnssReceiver2TimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentGnssReceiver2TimeSeries, SINGLEPROCESS, \"Convert gnssReceiver file into instrument(MISCVLAUES) file\", Gnss, TimeSeries, Residuals)\n\n/***********************************************/\n\nvoid InstrumentGnssReceiver2TimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNamesIn;\n    std::vector<GnssType> types;\n\n    readConfig(config, \"outputfileTimeSeries\",  fileNameOut, Config::MUSTSET, \"\",  \"Instrument (MISCVALUES): prn, system, values for each type\");\n    readConfig(config, \"inputfileGnssReceiver\", fileNamesIn, Config::MUSTSET, \"\",  \"GNSS receiver observations or residuals\");\n    readConfig(config, \"type\",                  types,       Config::MUSTSET, \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    std::vector<MiscValuesArc> arcList;\n    for(auto &fileName : fileNamesIn)\n    {\n      logStatus<<\"read GNSS receiver data <\"<<fileName<<\">\"<<Log::endl;\n      try\n      {\n        InstrumentFile fileReceiver(fileName);\n        for(UInt arcNo=0; arcNo<fileReceiver.arcCount(); arcNo++)\n        {\n          GnssReceiverArc arc = fileReceiver.readArc(arcNo);\n          MiscValuesArc arcNew;\n          for(auto &epoch : arc)\n          {\n            UInt idObs = 0;\n            for(GnssType typeSat : epoch.satellite)\n            {\n              // find first type for the satellite system\n              UInt idType = std::distance(epoch.obsType.begin(), std::find(epoch.obsType.begin(), epoch.obsType.end(), typeSat));\n\n              MiscValuesEpoch epochNew(2+types.size()); // prn, system, types\n              epochNew.time      = epoch.time;\n              epochNew.values(0) = static_cast<Double>(typeSat.prn());\n                   if(typeSat == GnssType::GPS)     epochNew.values(1) = static_cast<Double>('G');\n              else if(typeSat == GnssType::GLONASS) epochNew.values(1) = static_cast<Double>('R');\n              else if(typeSat == GnssType::GALILEO) epochNew.values(1) = static_cast<Double>('E');\n              else if(typeSat == GnssType::BDS)     epochNew.values(1) = static_cast<Double>('C');\n              else if(typeSat == GnssType::SBAS)    epochNew.values(1) = static_cast<Double>('S');\n              else if(typeSat == GnssType::QZSS)    epochNew.values(1) = static_cast<Double>('J');\n              else if(typeSat == GnssType::IRNSS)   epochNew.values(1) = static_cast<Double>('I');\n\n              // loop over all obs for this satellite\n              Bool                  found    = FALSE;\n              std::vector<GnssType> typesTmp = types;\n              while((idType<epoch.obsType.size()) && (idObs<epoch.observation.size()) && (epoch.obsType.at(idType) == typeSat))\n              {\n                const GnssType type  = epoch.obsType.at(idType++) + typeSat;\n                const Double   value = epoch.observation.at(idObs++);\n\n                const UInt     idx   = GnssType::index(typesTmp, type);\n                if((idx != NULLINDEX) && value)\n                {\n                  epochNew.values(2+idx) = value;\n                  typesTmp.at(idx) = GnssType(static_cast<UInt64>(-1));\n                  found = TRUE;\n                }\n              }\n\n              if(found)\n                arcNew.push_back(epochNew);\n            } // for(idTrans)\n          } // for(idEpoch)\n\n          if(arcNew.size())\n            arcList.push_back(arcNew);\n        } // for(idArc)\n      }\n      catch(...)\n      {\n        logError<<\"error by opening file, continue...\"<<Log::endl;\n      }\n    } // for(fileName)\n\n    // ============================\n\n    if(!arcList.size())\n      logWarning<<\"empty arc\"<<Log::endl;\n\n    logStatus<<\"write time series file <\"<<fileNameOut<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOut, arcList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gnss/parameterVector2GnssAntennaDefinition.cpp",
    "content": "/***********************************************/\n/**\n* @file parameterVector2GnssAntennaDefinition.cpp\n*\n* @brief Update antenna definition from parametrization.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-12-05\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nUpdates an \\file{GnssAntennaDefinition file}{gnssAntennaDefinition} with estimated parameters which belongs\nto the parametrization \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}.\nThe \\configFile{outfileAntennaDefinition}{gnssAntennaDefinition} contains all antennas\nfrom \\configFile{inputfileAntennaDefinition}{gnssAntennaDefinition}.\nThe antenna center variations representend by the \\configFile{inputfileSolution}{matrix} are added\nto the matching antennas.\n\nThe \\file{GnssAntennaDefinition file}{gnssAntennaDefinition} can be modified to the demands before with\n\\program{GnssAntennaDefinitionCreate}.\n\nThe following steps are used to estimate antenna center variations:\n\\begin{itemize}\n\\item \\program{GnssAntennaDefinitionCreate} or \\program{GnssAntex2AntennaDefinition}\n\\item \\program{GnssProcessing} with \\config{inputfileAntennaDefinition} as apriori\n      and writing \\file{normal equations}{normalEquation} with\n      parametrization of \\configClass{antennaCenterVariations}{parametrizationGnssAntennaType}\n\\item \\program{NormalsEliminate}: eliminate all other than antenna parameters\n\\item \\program{NormalsAccumulate}: accumulate normals over a sufficient long period\n\\item \\program{GnssAntennaNormalsConstraint}: constrain unsolvable parameter linear combinations\n\\item \\program{NormalsSolverVCE}: estimate the parameter vector\n\\item \\program{ParameterVector2GnssAntennaDefinition}: update \\config{inputfileAntennaDefinition}\n\\end{itemize}\n\nSee also \\program{ParameterVector2GnssAntennaDefinition}, \\program{GnssAntennaNormalsConstraint}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/string.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parametrizationGnssAntenna/parametrizationGnssAntenna.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Update antenna definition from parametrization.\n* @ingroup programsGroup */\nclass ParameterVector2GnssAntennaDefinition\n{\npublic:\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ParameterVector2GnssAntennaDefinition, SINGLEPROCESS, \"Update antenna definition from parametrization\", Gnss)\nGROOPS_RENAMED_PROGRAM(GnssRepresentation2AntennaDefinition, ParameterVector2GnssAntennaDefinition, date2time(2020, 6, 26))\n\n/***********************************************/\n\nvoid ParameterVector2GnssAntennaDefinition::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameAntennaOut;\n    FileName fileNameAntennaIn, fileNameSolution, fileNameParameterNames;\n    ParametrizationGnssAntennaPtr parametrization;\n\n    readConfig(config, \"outfileAntennaDefinition\",   fileNameAntennaOut,     Config::MUSTSET, \"\", \"all apriori antennas\");\n    readConfig(config, \"inputfileAntennaDefinition\", fileNameAntennaIn,      Config::MUSTSET, \"\", \"apriori antennas\");\n    readConfig(config, \"antennaCenterVariations\",    parametrization,        Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileSolution\",          fileNameSolution,       Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileParameterNames\",    fileNameParameterNames, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    logStatus<<\"read antenna definitions <\"<<fileNameAntennaIn<<\">\"<<Log::endl;\n    std::vector<GnssAntennaDefinitionPtr> antennas;\n    readFileGnssAntennaDefinition(fileNameAntennaIn, antennas);\n\n    logStatus<<\"read solution vector <\"<<fileNameSolution<<\">\"<<Log::endl;\n    Vector solution;\n    readFileMatrix(fileNameSolution, solution);\n\n    logStatus<<\"read parameter names <\"<<fileNameParameterNames<<\">\"<<Log::endl;\n    std::vector<ParameterName> parameterNames;\n    readFileParameterName(fileNameParameterNames, parameterNames);\n\n    std::vector<ParameterName> parametrizationNames;\n    parametrization->parameterName(parametrizationNames);\n\n    // ============================\n\n    // sort parameters into antenna, gnssType\n    // --------------------------------------\n    std::map<std::string, std::map<std::string, Vector>> solutions; // antenna, gnsType, solution\n    for(UInt i=0; i<parameterNames.size(); i++)\n    {\n      UInt idx = std::distance(parametrizationNames.begin(),\n                               std::find_if(parametrizationNames.begin(), parametrizationNames.end(), [&](const auto &name)\n                               {\n                                 auto pos = parameterNames.at(i).type.rfind('.');\n                                 return parameterNames.at(i).type.substr(0, pos) == name.type;\n                               }));\n      if(idx >= parametrization->parameterCount())\n        continue;\n\n      // extract GnssType\n      auto pos = parameterNames.at(i).type.rfind('.');\n      if((pos == std::string::npos) || (pos+1 == parameterNames.at(i).type.size()))\n        throw(Exception(parameterNames.at(i).str() + \": GnssType not found in parameter name\"));\n      std::string typeName = parameterNames.at(i).type.substr(pos+1);\n\n      if(!solutions[parameterNames.at(i).object][typeName].size())\n        solutions[parameterNames.at(i).object][typeName] = Vector(parametrization->parameterCount());\n      solutions[parameterNames.at(i).object][typeName](idx) = solution(i);\n    }\n\n    // add parametrization to all machting patterns\n    // -------------------------------------------\n    for(auto &solutionsAntenna : solutions)\n    {\n      // check antenna name\n      // ------------------\n      std::vector<std::string> parts = String::split(solutionsAntenna.first, GnssAntennaDefinition::sep);\n      auto antenna = GnssAntennaDefinition::find(antennas, parts.at(0), parts.at(1), parts.at(2));\n      if(!antenna)\n        throw(Exception(\"antenna not found in list: \"+solutionsAntenna.first));\n\n      for(auto &solutionsAntennaType : solutionsAntenna.second)\n      {\n        GnssType type(solutionsAntennaType.first);\n        Bool found = FALSE;\n        for(auto &pattern : antenna->patterns)\n          if(type == pattern.type)\n          {\n            logInfo<<antenna->str()<<\": add parametrization of \"<<type.str()<<\" to \"<<pattern.type.str()<<Log::endl;\n            found = TRUE;\n\n            Vector x = solutionsAntennaType.second;\n            for(UInt k=0; k<x.rows(); k++)\n            {\n              if(String::startsWith(parametrizationNames.at(k).type, \"antennaCenter.x\")) {pattern.offset.x() += x(k); x(k) = 0;}\n              if(String::startsWith(parametrizationNames.at(k).type, \"antennaCenter.y\")) {pattern.offset.y() += x(k); x(k) = 0;}\n              if(String::startsWith(parametrizationNames.at(k).type, \"antennaCenter.z\")) {pattern.offset.z() += x(k); x(k) = 0;}\n            }\n            if(!isStrictlyZero(x))\n              for(UInt i=0; i<pattern.pattern.rows(); i++)\n                for(UInt k=0; k<pattern.pattern.columns(); k++)\n                  pattern.pattern(i,k) += inner(parametrization->designMatrix(Angle(2*PI*i/pattern.pattern.rows()), Angle(PI/2-k*Double(pattern.dZenit))).trans(), x);\n\n            // type cannot match further patterns (all wildcards in type are already catched)?\n            if((!type.hasWildcard(GnssType::PRN)       || pattern.type.hasWildcard(GnssType::PRN)      ) &&\n               (!type.hasWildcard(GnssType::SYSTEM)    || pattern.type.hasWildcard(GnssType::SYSTEM)   ) &&\n               (!type.hasWildcard(GnssType::FREQUENCY) || pattern.type.hasWildcard(GnssType::FREQUENCY)) &&\n               (!type.hasWildcard(GnssType::TYPE)      || pattern.type.hasWildcard(GnssType::TYPE)     ) &&\n               (!type.hasWildcard(GnssType::ATTRIBUTE) || pattern.type.hasWildcard(GnssType::ATTRIBUTE)) &&\n               (!type.hasWildcard(GnssType::FREQ_NO)   || pattern.type.hasWildcard(GnssType::FREQ_NO)  ))\n              break;\n          }\n\n        if(!found)\n          logWarning<<antenna->str()<<\" has no pattern for \"<<type.str()<<Log::endl;\n      }\n    }\n\n    // ============================\n\n    if(!fileNameAntennaOut.empty())\n    {\n      logStatus<<\"write antenna definition <\"<<fileNameAntennaOut<<\">\"<<Log::endl;\n      writeFileGnssAntennaDefinition(fileNameAntennaOut, antennas);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/grace/ensembleAveragingScaleModel.cpp",
    "content": "/***********************************************/\n/**\n* @file ensembleAveragingScaleModel.cpp\n*\n* @brief First order Ensemble Averaging\n*\n* @author Saniya Behzadpour\n* @date 2018-05-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis programs estimate satellite-to-satellite-tracking (SST) deterministic signals due to eclipse transits from residuals.\nThe ensemble averaging method is used to characterize the average properties of signal shapes across all transit events.\nEach shape is assigned to one arc of 3 hours (default). This can be modefied by enabling \\config{averagingInterval}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief First order Ensemble Averaging\n* @ingroup programsGroup */\nclass EnsembleAveragingScaleModel\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(EnsembleAveragingScaleModel, SINGLEPROCESS, \"Ensamble Averaging of eclipse transit signals\", Grace)\n\n/***********************************************/\n\nvoid EnsembleAveragingScaleModel::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    FileName inName1, inName2, inNameSst;\n    UInt     timeMargin, waveLength, neighborNumber;\n    Bool     perArc = TRUE;\n\n    readConfig(config, \"outputfileScaleModel\" ,        outName,    Config::MUSTSET, \"\",   \"\");\n    readConfig(config, \"inputfileGrace1EclipseFactor\", inName1,    Config::MUSTSET, \"\",   \"GRACE-A eclipse factors computed with integrated orbit\");\n    readConfig(config, \"inputfileGrace2EclipseFactor\", inName2,    Config::MUSTSET, \"\",   \"GRACE-B eclipse factors computed with integrated orbit\");\n    readConfig(config, \"inputfileGraceResiduals\",      inNameSst,  Config::MUSTSET, \"\",   \"SST Residuals\");\n    readConfig(config, \"timeMargin\",                   timeMargin, Config::MUSTSET, \"25\", \"epochs before eclipse mode\");\n    readConfig(config, \"waveLength\",                   waveLength, Config::MUSTSET, \"60\", \"length of the sample wave\");\n    if(readConfigSequence(config, \"averagingInterval\", Config::OPTIONAL, \"\", \"\"))\n    {\n      perArc = FALSE;\n      readConfig(config, \"nearestNeighborNumber\",  neighborNumber,   Config::DEFAULT,  \"24\", \"\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    std::vector<MiscValueArc> arcListEF1, arcListEF2;\n    std::vector<SatelliteTrackingArc> arcListRes;\n    SatelliteTrackingArc sstArc;\n\n    logStatus<<\"read satellite data\"<<Log::endl;\n    InstrumentFile fileSst(inNameSst);\n    InstrumentFile fileEF1(inName1);\n    InstrumentFile fileEF2(inName2);\n    InstrumentFile::checkArcCount({fileSst, fileEF1, fileEF2});\n\n    UInt arcCount = fileSst.arcCount();\n    arcListRes.resize(arcCount);\n    arcListEF1.resize(arcCount);\n    arcListEF2.resize(arcCount);\n    UInt countSst = 0;\n\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n    {\n      arcListRes.at(arcNo)  = fileSst.readArc(arcNo);\n      arcListEF1.at(arcNo)  = fileEF1.readArc(arcNo);\n      arcListEF2.at(arcNo)  = fileEF2.readArc(arcNo);\n    }\n\n\n    std::vector<std::vector<Double>> sumWaveP (arcCount); //sum of the waves in each arc with positive criteria\n    std::vector<std::vector<Double>> sumWaveN (arcCount); //sum of the waves in each arc with negative criteria\n    std::vector<UInt> nP (arcCount); //number of the waves in each arc with positive criteria\n    std::vector<UInt> nN (arcCount); //number of the waves in each arc with positive criteria\n\n    logStatus<<\"find candidates and compute the sum\"<<Log::endl;\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n    {\n      sumWaveP.at(arcNo).resize(waveLength);\n      sumWaveN.at(arcNo).resize(waveLength);\n      nP.at(arcNo) = 1;\n      nN.at(arcNo) = 1;\n      Double criteria = 0;\n\n      countSst = arcListRes.at(arcNo).size();\n      for(UInt i=0; i<countSst; i++)\n      {\n        if(i < countSst - timeMargin)\n        {\n          criteria = arcListEF2.at(arcNo).at(i+timeMargin).value - arcListEF1.at(arcNo).at(i+timeMargin).value;\n          if(criteria >0)\n          {\n            UInt maxj = waveLength;\n            if (countSst - i < maxj)\n                maxj = countSst - i;\n            for(UInt j=i; j< i+maxj; j++)\n              sumWaveP.at(arcNo).at(j-i) += arcListRes.at(arcNo).at(j).rangeRate;\n            i = i + maxj;\n            nP.at(arcNo) = nP.at(arcNo) + 1 ;\n          }\n          else if(criteria < 0)\n          {\n            UInt maxj = waveLength;\n            if (countSst - i < maxj)\n                maxj = countSst - i;\n            for(UInt j=i; j< i+maxj; j++)\n              sumWaveN.at(arcNo).at(j-i) += arcListRes.at(arcNo).at(j).rangeRate;\n            i = i + maxj;\n            nN.at(arcNo) = nN.at(arcNo) + 1 ;\n          }\n        }\n      }\n    }\n\n    logStatus<<\"compute the first order averaging\"<<Log::endl;\n    UInt m = perArc ? arcCount: (UInt) arcCount/neighborNumber; //number of data segments\n    Matrix sumTotalP (waveLength,m);\n    Matrix sumTotalN (waveLength,m);\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      for(UInt i=0; i< m; i++)\n        if ((arcNo >= i*arcCount/m)&&(arcNo < (i+1)*arcCount/m))\n        {\n          for(UInt j=0; j< waveLength; j++)\n            sumTotalP(j,i) += sumWaveP.at(arcNo).at(j) / nP.at(arcNo);\n          for(UInt j=0; j< waveLength; j++)\n            sumTotalN(j,i) += sumWaveN.at(arcNo).at(j) / nN.at(arcNo);\n        }\n\n    // Compute the desired signal\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n    {\n      UInt k =0;\n      for(UInt i=0; i< m; i++)\n        if((arcNo >= i*arcCount/m)&&(arcNo < (i+1)*arcCount/m))\n          k= i;\n      Double criteria = 0;\n      countSst = arcListRes.at(arcNo).size();\n      for(UInt i=0; i<countSst; i++)\n      {\n        if(i < countSst - timeMargin)\n        {\n          criteria = arcListEF2.at(arcNo).at(i+timeMargin).value - arcListEF1.at(arcNo).at(i+timeMargin).value;\n          if(criteria > 0)\n          {\n            UInt maxj = waveLength;\n            if (countSst - i < maxj)\n                maxj = countSst - i;\n            for(UInt j=i; j< i+maxj; j++)\n            {\n              SatelliteTrackingEpoch epoch;\n              epoch.time  = arcListRes.at(arcNo).at(j).time;\n              epoch.range = epoch.rangeRate = epoch.rangeAcceleration = sumTotalP(j-i,k)/(arcCount/m);\n              sstArc.push_back(epoch);\n            }\n            i = i + maxj;\n          }\n          else if(criteria < 0)\n          {\n            UInt maxj = waveLength;\n            if (countSst - i < maxj)\n                maxj = countSst - i;\n            for(UInt j=i; j< i+maxj; j++)\n            {\n              SatelliteTrackingEpoch epoch;\n              epoch.time  = arcListRes.at(arcNo).at(j).time;\n              epoch.range = epoch.rangeRate = epoch.rangeAcceleration = sumTotalN(j-i,k)/(arcCount/m);\n              sstArc.push_back(epoch);\n            }\n            i = i + maxj;\n          }\n          else\n          {\n            SatelliteTrackingEpoch epoch;\n            epoch.time  = arcListRes.at(arcNo).at(i).time;\n            epoch.range = epoch.rangeRate = epoch.rangeAcceleration = 0;\n            sstArc.push_back(epoch);\n          }\n        }\n        else\n        {\n          SatelliteTrackingEpoch epoch;\n          epoch.time  = arcListRes.at(arcNo).at(i).time;\n          epoch.range = epoch.rangeRate = epoch.rangeAcceleration = 0;\n          sstArc.push_back(epoch);\n        }\n      }\n    }\n\n    logStatus<<\"write the output signal <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, sstArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***************************************/\n\n"
  },
  {
    "path": "source/programs/grace/graceAntennaCenterCorrectionArcCovariance.cpp",
    "content": "/***********************************************/\n/**\n* @file graceAntennaCenterCorrectionArcCovariance.cpp\n*\n* @brief Compute antenna center correction from orbit configuration.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes covariance information for the non­-stationary noise of the KBR antenna offset correction (AOC)\nfrom the orientation covariance matrices provided in Level-1B products via variance propagation.\nBy using the output \\configFile{outputfileSatelliteTrackingCovariance}{matrix} in \\program{PreprocessingSst},\nnoise model distinguishes between the stationary noise of ranging observations and the non­stationary AOC noise.\n\nThe covariances are derived from the partial derivative of the AOC w.r.t. the roll/pitch/yaw rotations\nand star camera covariances \\configFile{inputfileScaCovariance1}{matrix} and \\configFile{inputfileScaCovariance2}{matrix}.\n\nThe covariances for the range-rates and range-acceleration are computed by differentiating\nan interpolation polynomial of degree \\config{interpolationDegree}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"misc/grace/graceKBandGeometry.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute antenna center correction from orbit configuration.\n* @ingroup programsGroup */\nclass GraceAntennaCenterCorrectionArcCovariance\n{\n  void rotaryCholesky(const std::vector<Time> &times, const Covariance3dArc &starCameraCovariance, const Vector &sigmaAxisAcc, UInt degree, MatrixDistributed &normals) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceAntennaCenterCorrectionArcCovariance, PARALLEL, \"compute antenna center correction from orbit configuration\", Grace, Covariance)\n\n/***********************************************/\n\nvoid GraceAntennaCenterCorrectionArcCovariance::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName    fileNameCovariance;\n    FileName    fileNameOrbit1, fileNameOrbit2;\n    FileName    fileNameStarCamera1, fileNameStarCamera2;\n    FileName    fileNameScaCov1, fileNameScaCov2;\n    UInt        sstType;\n    Vector      sigmaAxisAcc(3);\n    Vector3d    center1, center2;\n    UInt        degree;\n    std::string choice;\n\n    readConfig(config, \"outputfileSatelliteTrackingCovariance\", fileNameCovariance, Config::OPTIONAL, \"\", \"corrections for range, range-rate, and range-accelerations\");\n    if(readConfigChoice(config, \"sstType\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"range\",             choice, \"\")) sstType = 0;\n      if(readConfigChoiceElement(config, \"rangeRate\",         choice, \"\")) sstType = 1;\n      if(readConfigChoiceElement(config, \"rangeAcceleration\", choice, \"\")) sstType = 2;\n      endChoice(config);\n    }\n    readConfig(config, \"inputfileOrbit1\",         fileNameOrbit1,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit2\",         fileNameOrbit2,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera1\",    fileNameStarCamera1, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera2\",    fileNameStarCamera2, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileScaCovariance1\", fileNameScaCov1,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileScaCovariance2\", fileNameScaCov2,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"sigmaAccelerometerX\",     sigmaAxisAcc(0),     Config::DEFAULT,  \"10e-7\", \"[rad/s^2]\");\n    readConfig(config, \"sigmaAccelerometerY\",     sigmaAxisAcc(1),     Config::DEFAULT,  \"2e-7\",  \"[rad/s^2]\");\n    readConfig(config, \"sigmaAccelerometerZ\",     sigmaAxisAcc(2),     Config::DEFAULT,  \"2e-7\",  \"[rad/s^2]\");\n    if(readConfigChoice(config, \"antennaCenters\",     choice,          Config::MUSTSET,  \"\",      \"KBR antenna phase center\"))\n    {\n      if(readConfigChoiceElement(config, \"value\", choice, \"\"))\n      {\n        readConfig(config, \"center1X\", center1.x(), Config::DEFAULT,   \"1.4451172588\", \"x-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center1Y\", center1.y(), Config::DEFAULT,  \"-0.0004233040\", \"y-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center1Z\", center1.z(), Config::DEFAULT,   \"0.0022786600\", \"z-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center2X\", center2.x(), Config::DEFAULT,   \"1.4443870350\", \"x-coordinate of antenna position in SRF [m] for GRACEB\");\n        readConfig(config, \"center2Y\", center2.y(), Config::DEFAULT,   \"0.0005761203\", \"y-coordinate of antenna position in SRF [m] for GRACEB\");\n        readConfig(config, \"center2Z\", center2.z(), Config::DEFAULT,   \"0.0033040887\", \"z-coordinate of antenna position in SRF [m] for GRACEB\");\n      }\n      if(readConfigChoiceElement(config, \"file\",  choice, \"\"))\n      {\n        FileName fileName;\n        readConfig(config, \"inputAntennaCenters\", fileName, Config::MUSTSET, \"\", \"\");\n        if(!isCreateSchema(config))\n        {\n          Matrix x;\n          readFileMatrix(fileName, x);\n          center1 = Vector3d(x(0,0), x(1,0), x(2,0));\n          center2 = Vector3d(x(3,0), x(4,0), x(5,0));\n        }\n      }\n      endChoice(config);\n    }\n    readConfig(config, \"interpolationDegree\", degree, Config::DEFAULT,  \"2\", \"differentiation by polynomial approximation of degree n\");\n    if(isCreateSchema(config)) return;\n\n    // =======================================================\n\n    logStatus<<\"read orbit and star camera data and generate antenna offset corrections\"<<Log::endl;\n    InstrumentFile  orbit1File(fileNameOrbit1);\n    InstrumentFile  orbit2File(fileNameOrbit2);\n    InstrumentFile  starCamera1File(fileNameStarCamera1);\n    InstrumentFile  starCamera2File(fileNameStarCamera2);\n    InstrumentFile  starCameraCovariance1File(fileNameScaCov1);\n    InstrumentFile  starCameraCovariance2File(fileNameScaCov2);\n    InstrumentFile::checkArcCount({orbit1File, orbit2File, starCamera1File, starCamera2File});\n\n    Parallel::forEach(orbit1File.arcCount(), [&](UInt arcNo)\n    {\n      OrbitArc        orbit1                = orbit1File.readArc(arcNo);\n      OrbitArc        orbit2                = orbit2File.readArc(arcNo);\n      StarCameraArc   starCamera1           = starCamera1File.readArc(arcNo);\n      StarCameraArc   starCamera2           = starCamera2File.readArc(arcNo);\n      Covariance3dArc starCameraCovariance1 = starCameraCovariance1File.readArc(arcNo);\n      Covariance3dArc starCameraCovariance2 = starCameraCovariance2File.readArc(arcNo);\n      Arc::checkSynchronized({orbit1, orbit2, starCamera1, starCamera2});\n\n      const std::vector<Time> times = orbit1.times();\n      const UInt   epochCount = times.size();\n\n      MatrixDistributed normals[2];\n      rotaryCholesky(times, starCameraCovariance1, sigmaAxisAcc, degree, normals[0]);\n      rotaryCholesky(times, starCameraCovariance2, sigmaAxisAcc, degree, normals[1]);\n\n      Matrix SparseJacobian[2];\n      GraceKBandGeometry::partialOfAntennaCenterCorrectionWrtRollPitchYaw(orbit1, orbit2, starCamera1, starCamera2, center1, center2, SparseJacobian[0], SparseJacobian[1]);\n\n      Matrix Cov(epochCount, Matrix::SYMMETRIC);\n      Polynomial p(times, degree);\n      for(UInt id=0; id<2; id++) // GRACE A/B\n      {\n        Matrix A(epochCount, 3*epochCount);\n        for(UInt i=0; i<epochCount; i++)\n          copy(SparseJacobian[id].row(i), A.slice(i, 3*i, 1, 3));\n\n        if(sstType == 0)      // range\n          A = A.trans();\n        else if(sstType == 1) // range rate\n          A = p.derivative(times, A).trans();\n        else if(sstType == 2) // range acceleration\n          A = p.derivative2nd(times, A).trans();\n\n        // apply covariance\n        normals[id].triangularTransSolve(A);\n        rankKUpdate(1., A, Cov);\n      }\n\n      writeFileMatrix(fileNameCovariance.appendBaseName(\".arc\"+arcNo%\"%03i\"s),  Cov);\n    }, comm); // forEach\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid GraceAntennaCenterCorrectionArcCovariance::rotaryCholesky(const std::vector<Time> &times, const Covariance3dArc &starCameraCovariance, const Vector &sigmaAxisAcc, UInt degree, MatrixDistributed &normals) const\n{\n  try\n  {\n    const UInt   epochCount = times.size();\n    const Double dt         = medianSampling(times).seconds();\n\n    std::vector<UInt> blockIndex(1, 0);\n    for(UInt i=0; i<epochCount; i++)\n      blockIndex.push_back( blockIndex.back()+3 );\n    normals.initEmpty(blockIndex, Parallel::selfCommunicator());\n    for(UInt i=0; i<epochCount; i++)\n      normals.setBlock(i, i);\n\n    // polynomial interpolation matrix\n    // -------------------------------\n    Matrix P(degree+1, degree+1);\n    for(UInt i=0; i<P.rows(); i++)\n    {\n      P(0,i) = 1.0;\n      for(UInt n=1; n<P.columns(); n++)\n        P(n,i) = (i-degree/2.) * P(n-1,i);\n    }\n    inverse(P);\n\n    // star camera observations\n    // ------------------------\n    UInt idxSca = 0;\n    const std::vector<Time> timesCov = starCameraCovariance.times();\n    for(UInt i=0; i<epochCount; i++)\n    {\n      // search time slot\n      while((idxSca < timesCov.size()) && (timesCov.at(idxSca) < times.at(i)))\n        idxSca++;\n      if(idxSca >= timesCov.size())\n        break;\n      if(timesCov.at(idxSca) > times.at(i))\n        continue;\n\n      normals.N(i,i) = starCameraCovariance.at(idxSca).covariance.matrix();\n      inverse(normals.N(i,i));\n    } // for(i=epochCount)\n\n    // angular accelerations observations\n    // ----------------------------------\n    for(UInt i=0; i<epochCount; i++)\n    {\n      // polynomial 2nd differentiation\n      const UInt idx = std::min(std::max(i, degree/2)-degree/2, epochCount-degree-1); // interval\n      Vector factors = Vector(degree+1);  // derivation coefficients\n      const Double tau = i-idx-degree/2.;\n      Double f = 1./(dt*dt);\n      for(UInt n=2; n<factors.rows(); n++)\n      {\n        axpy(n*(n-1)*f, P.column(n), factors);\n        f *= tau;\n      }\n\n      // dacc(i)/dq(k)\n      std::vector<Matrix> accA(factors.size());\n      for(UInt k=0; k<factors.size(); k++) // w_dot(i) = sum_k factor(k) alpha(k)\n        accA.at(k) = factors(k) * identityMatrix(3);\n\n      // decorrelation\n      for(UInt idAxis=0; idAxis<3; idAxis++)\n        for(UInt k=0; k<accA.size(); k++)\n          accA.at(k).row(idAxis) *= 1./sigmaAxisAcc(idAxis);\n\n      // accumulate normals\n      for(UInt k=0; k<factors.size(); k++)\n      {\n        rankKUpdate(1., accA.at(k), normals.N(idx+k, idx+k)); // N11(i)\n        for(UInt j=k+1; j<factors.size(); j++)                // N11(i), secondary diagonal\n        {\n          normals.setBlock(idx+k, idx+j);\n          matMult(1., accA.at(k).trans(), accA.at(j), normals.N(idx+k, idx+j));\n        }\n      }\n    } // for(i=epochCount)\n\n    // cholesky\n    // --------\n    normals.cholesky(FALSE/*timing*/);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/grace/graceOrbit2TransplantTimeOffset.cpp",
    "content": "/***********************************************/\n/**\n* @file graceOrbit2TransplantTimeOffset.cpp\n*\n* @brief Compute the time shift between two co-orbiting satellites from their orbit data.\n*\n* @author Andreas Kvas\n* @date 2022-04-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the time shift between two co-orbiting satellites based on dynamic orbit data.\nWhen applied to data of the first satellite, the computed time shift virtually shifts data of first satellite into the location of the second satellite.\nNote that \\config{inputfileOrbit1} and \\config{inputfileOrbit2} need velocity and acceleration data, which\ncan be computed with \\program{OrbitAddVelocityAndAcceleration}.\nThe program tries to find a minimum of the objective function\n\\begin{equation}\n  f(\\Delta t) = \\| r_1(t) - r_2(t + \\Delta t) \\|^2,\n\\end{equation}\nby applying Newton's method to the first derivative, thus iteratively computing\n\\begin{equation}\n  \\Delta t_{k+1} = \\Delta t_k + \\frac{f'(\\Delta t_k)}{f''(\\Delta t_k)}.\n\\end{equation}\nThis iteration is stopped when the difference between to consecutive time shift values falls below \\config{threshold} or\n\\config{maximumIterations} is reached. An \\config{initialGuess} of the time shift can speed up convergence.\n\nSee also \\program{OrbitAddVelocityAndAcceleration} and \\program{InstrumentApplyTimeOffset}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute the time shift between two co-orbiting satellites from their orbit data.\n* @ingroup programsGroup */\nclass GraceOrbit2TransplantTimeOffset\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceOrbit2TransplantTimeOffset, PARALLEL, \"compute the time shift between two co-orbiting satellites from their orbit data\", Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceOrbit2TransplantTimeOffset::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameTimeOffset;\n    FileName fileNameOrbit1,  fileNameOrbit2;\n    UInt     interpolationDegree, maxIter;\n    Double   initialGuess, threshold;\n\n    readConfig(config, \"outputfileTimeOffset\", fileNameTimeOffset,  Config::MUSTSET,  \"\",     \"estimated time offset in seconds (MISCVALUE)\");\n    readConfig(config, \"inputfileOrbit1\",      fileNameOrbit1,      Config::MUSTSET,  \"\",     \"orbit data of satellite 1\");\n    readConfig(config, \"inputfileOrbit2\",      fileNameOrbit2,      Config::MUSTSET,  \"\",     \"orbit data of satellite 2\");\n    readConfig(config, \"interpolationDegree\",  interpolationDegree, Config::DEFAULT,  \"7\",    \"polynomial degree for the interpolation of position, velocity and acceleration\");\n    readConfig(config, \"initialGuess\",         initialGuess,        Config::DEFAULT,  \"0.0\",  \"initial guess for the time shift [seconds]\");\n    readConfig(config, \"maximumIterations\",    maxIter,             Config::DEFAULT,  \"50\",   \"maximum number of iterations\");\n    readConfig(config, \"threshold\",            threshold,           Config::DEFAULT,  \"1e-5\", \"when the maximum difference between two iterations is below this value, stop [seconds]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read orbit data and estimate time shift\"<<Log::endl;\n    InstrumentFile  orbit1File(fileNameOrbit1);\n    InstrumentFile  orbit2File(fileNameOrbit2);\n    InstrumentFile::checkArcCount({orbit1File, orbit2File});\n\n    std::vector<Arc> arcList(orbit1File.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc orbit1 = orbit1File.readArc(arcNo);\n      OrbitArc orbit2 = orbit2File.readArc(arcNo);\n      Arc::checkSynchronized({orbit1, orbit2});\n\n      const std::vector<Time> times2 = orbit2.times();\n      Matrix dt(orbit2.size(), 2, initialGuess);\n\n      Polynomial polynomial;\n      polynomial.init(times2, interpolationDegree, FALSE/*throwException*/, FALSE/*isLeastSquares*/, -1.*(interpolationDegree+1), std::numeric_limits<Double>::infinity());\n\n      Matrix A1 = orbit1.matrix();\n      Matrix A2 = orbit2.matrix();\n\n      if(maxabs(A1.column(4, 3)) == 0.0 || maxabs(A1.column(7, 3)) == 0.0 || maxabs(A2.column(4, 3)) == 0.0 || maxabs(A2.column(7, 3)) == 0.0)\n        throw(Exception(\"dynamic orbits require both velocity and acceleration\"));\n\n      UInt iter;\n      for(iter=0; iter<maxIter; iter++)\n      {\n        std::vector<Time> timesNew = times2;\n        for(UInt k=0; k<timesNew.size(); k++)\n          timesNew[k] += seconds2time(dt(k, 1));\n\n        Vector dtk(dt.rows());\n        Matrix A2_interp = polynomial.interpolate(timesNew, A2.column(1, A2.columns()-1));\n        for(UInt k=0; k<timesNew.size(); k++)\n        {\n          Vector3d dr((A1.slice(k, 1, 1, 3) - A2_interp.slice(k, 0, 1, 3)).trans());\n          Vector3d v2(A2_interp.slice(k, 3, 1, 3).trans());\n          Vector3d a2(A2_interp.slice(k, 6, 1, 3).trans());\n\n          dtk(k) = inner(dr, v2) / (inner(dr, a2) + inner(v2, v2));\n          dt(k, 1) += dtk(k);\n        }\n        if(maxabs(dtk) < threshold)\n          break;\n      }\n      if(iter == maxIter)\n        logWarning<<\"maximum iterations reached\"<<Log::endl;\n\n      return Arc(times2, dt, Epoch::Type::MISCVALUE);\n    }, comm); // forEach\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write time offset to file <\"<<fileNameTimeOffset<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameTimeOffset, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/grace/graceSstResidualAnalysis.cpp",
    "content": "/***********************************************/\n/**\n* @file graceSstResidualAnalysis.cpp\n*\n* @brief Multiresolution analysis of GRACE SST residuals.\n*\n* @author Saniya Behzadpour\n* @date 2018-07-15\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program applies the Multi-Resolution Analysis (MRA) using\nDiscrete Wavelet Transform (DWT) to the monthly GRACE SST post-fit residuals.\nFirst, the residuals are transferred into wavelet domain by applying an 8 level\nDaubechies wavelet transform (default).\nIn the next step, detail coefficients are merged into three major groups\ndue to their approximate frequency subbands:\n\\begin{itemize}\n\\item Low scale details, corresponding to the frequency band above 10 mHz;\n\\item Intermediate scale details, corresponding to the approximate frequency\n      range above 3 mHz up to 10 mHz;\n\\item High scale details, corresponding to the approximate frequency range\nabove 0.5 mHz up to 10 mHz.\n\\end{itemize}\nIn the last step, each group is reconstructed back into time domain.\n)\";\n\n/***********************************************/\n\n#include \"base/wavelets.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"parallel/parallel.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Multiresolution analysis of GRACE SST residuals.\n* @ingroup programsGroup */\nclass GraceSstResidualAnalysis\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceSstResidualAnalysis, SINGLEPROCESS, \"Multiresolution analysis of GRACE SST residuals.\", Grace)\n\n/***********************************************/\n\nvoid GraceSstResidualAnalysis::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutHigh, fileNameOutMid, fileNameOutLow;\n    FileName fileNameInResiduals, fileNameInWavelet;\n    UInt     level = 8;\n\n    readConfig(config, \"outputfileInstrumentHighScale\", fileNameOutHigh,     Config::MUSTSET, \"\", \"High scale details\");\n    readConfig(config, \"outputfileInstrumentMidScale\",  fileNameOutMid,      Config::MUSTSET, \"\", \"Intermediate scale details\");\n    readConfig(config, \"outputfileInstrumentLowScale\",  fileNameOutLow,      Config::MUSTSET, \"\", \"Low scale details\");\n    readConfig(config, \"inputfileInstrument\",           fileNameInResiduals, Config::MUSTSET, \"\", \"GRACE SST Residuals\");\n    readConfig(config, \"inputfileWavelet\",              fileNameInWavelet,   Config::MUSTSET, \"{groopsDataDir}/wavelets/db20.txt\", \"wavelet coefficients\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"read GRACE SST residuals \"<<\"<\"<<fileNameInResiduals<<\">\"<<Log::endl;\n    SatelliteTrackingArc sstArc = InstrumentFile::read(fileNameInResiduals);\n    UInt posCount = sstArc.size();\n    std::vector<Double> signal(posCount);\n    for(UInt i=0; i<posCount; i++)\n      signal.at(i) = sstArc.at(i).rangeRate;\n\n    logStatus<<\"read wavelet filters \"<<\"<\"<<fileNameInWavelet<<\">\"<<Log::endl;\n    Vector wl;\n    readFileMatrix(fileNameInWavelet, wl);\n\n    std::vector<UInt>   length;\n    std::vector<UInt>   flag, flag2;\n    std::vector<Double> dwtCoeff,dwt_a08,idwt_a08,idwt_out;\n    std::vector<Double> dwt_d03, dwt_d02, dwt_d01;\n    std::vector<Double> idwt_d03,idwt_d02,idwt_d01;\n\n    //perform 8-Level DWT\n    Wavelets::discreteWaveletTransform(signal, wl, level, dwtCoeff,flag, length);\n\n    //compute cumulative flag vector\n    flag2.resize(length.size());\n    for (UInt i=0; i<length.size();i++)\n      flag2.at(i) = length.at(i);\n    for (UInt i=1; i<flag2.size();i++)\n      flag2.at(i) += flag2.at(i-1);\n\n    //merge detail coefficients into three major groups\n    dwt_a08.resize(dwtCoeff.size()); dwt_d03.resize(dwtCoeff.size());\n    dwt_d02.resize(dwtCoeff.size()); dwt_d01.resize(dwtCoeff.size());\n    for (UInt i = 0; i < dwtCoeff.size();i++)\n      if (i < flag2.at(0))\n        dwt_a08.at(i) = dwtCoeff.at(i);\n      else if (i < flag2.at(3))\n        dwt_d03.at(i) = dwtCoeff.at(i);\n      else if (i < flag2.at(5))\n        dwt_d02.at(i) = dwtCoeff.at(i);\n      else\n        dwt_d01.at(i) = dwtCoeff.at(i);\n\n    //apply inverse DWT, from wavelet domain to time domain\n    Wavelets::inverseDiscreteWaveletTransform(dwt_d03, wl, flag, idwt_d03, length);\n    Wavelets::inverseDiscreteWaveletTransform(dwt_d02, wl, flag, idwt_d02, length);\n    Wavelets::inverseDiscreteWaveletTransform(dwt_d01, wl, flag, idwt_d01, length);\n\n    SatelliteTrackingArc d03, d02, d01;\n    for(UInt i=0; i<posCount; i++)\n    {\n      SatelliteTrackingEpoch epoch;\n      epoch.time = sstArc.at(i).time;\n      epoch.range = epoch.rangeRate = epoch.rangeAcceleration = idwt_d03.at(i);\n      d03.push_back(epoch);\n    }\n\n    for(UInt i=0; i<posCount; i++)\n    {\n      SatelliteTrackingEpoch epoch;\n      epoch.time = sstArc.at(i).time;\n      epoch.range = epoch.rangeRate = epoch.rangeAcceleration = idwt_d02.at(i);\n      d02.push_back(epoch);\n    }\n\n    for(UInt i=0; i<posCount; i++)\n    {\n      SatelliteTrackingEpoch epoch;\n      epoch.time = sstArc.at(i).time;\n      epoch.range = epoch.rangeRate = epoch.rangeAcceleration = idwt_d01.at(i);\n      d01.push_back(epoch);\n    }\n\n    logStatus<<\"write decomposed signals\"<<Log::endl;\n    logStatus<<\"<\"<<fileNameOutHigh<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOutHigh, d03);\n    logStatus<<\"<\"<<fileNameOutMid<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOutMid,  d02);\n    logStatus<<\"<\"<<fileNameOutLow<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOutLow,  d01);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/*************************************************/\n"
  },
  {
    "path": "source/programs/grace/graceSstScaleModel.cpp",
    "content": "/***********************************************/\n/**\n* @file graceSstScaleModel.cpp\n*\n* @brief First order Ensemble Averaging\n*\n* @author Saniya Behzadpour\n* @date 2018-05-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis programs estimate satellite-to-satellite-tracking (SST) deterministic signals\ndue to eclipse transits and low-SNR values from post-fit residuals.\nThe low-SNR effects are estimated by directly using the residual values.\nThe ensemble averaging method is used to characterize the average properties of eclipse transit signal shapes across all transit events.\nEach shape is assigned to one arc of 3 hours (default). This can be modefied by enabling \\config{averagingInterval}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief First order Ensemble Averaging\n* @ingroup programsGroup */\nclass GraceSstScaleModel\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceSstScaleModel, SINGLEPROCESS, \"Ensamble Averaging of eclipse transit signals\", Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceSstScaleModel::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outNameEclipse, outNameSnr;\n    FileName inName1, inName2, inNameSst, inNameSnr;\n    UInt     timeMargin, waveLength, neighborNumber;\n    UInt     arcCount = 0;\n    UInt     countSst = 0;\n    Bool     perArc = TRUE;\n    Bool     lowSnr = FALSE;\n    Bool     eclipseTransit = FALSE;\n\n    readConfig(config, \"inputfileGraceResiduals\", inNameSst,  Config::MUSTSET, \"\",   \"SST Residuals\");\n    readConfig(config, \"timeMargin\",              timeMargin, Config::MUSTSET, \"25\", \"epochs before instrumental events\");\n    readConfig(config, \"waveLength\",              waveLength, Config::MUSTSET, \"60\", \"length of the sample wave\");\n    if(readConfigSequence(config, \"estimateEclipseTransitScale\", Config::OPTIONAL, \"\", \"\"))\n    {\n      eclipseTransit = TRUE;\n      readConfig(config, \"outputfileScaleModel\" ,        outNameEclipse, Config::MUSTSET, \"\", \"\");\n      readConfig(config, \"inputfileGrace1EclipseFactor\", inName1,        Config::MUSTSET, \"\", \"GRACE-A eclipse factors computed with integrated orbit\");\n      readConfig(config, \"inputfileGrace2EclipseFactor\", inName2,        Config::MUSTSET, \"\", \"GRACE-B eclipse factors computed with integrated orbit\");\n      if(readConfigSequence(config, \"averagingInterval\", Config::OPTIONAL, \"\", \"\"))\n      {\n        perArc = FALSE;\n        readConfig(config, \"nearestNeighborNumber\", neighborNumber, Config::DEFAULT, \"24\", \"\");\n        endSequence(config);\n      }\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateLowSnrScale\", Config::OPTIONAL, \"\", \"\"))\n    {\n      lowSnr = TRUE;\n      readConfig(config, \"outputfileScaleModel\", outNameSnr, Config::MUSTSET, \"\", \"\");\n      readConfig(config, \"inputfileGraceSstSNR\", inNameSnr,  Config::MUSTSET, \"\", \"GRACE SNR values\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    std::vector<MiscValueArc>         arcListEF1, arcListEF2;\n    std::vector<SatelliteTrackingArc> arcListRes;\n    SatelliteTrackingArc              sstArc_1, sstArc_2;\n\n    logStatus<<\"read satellite data\"<< lowSnr <<Log::endl;\n    InstrumentFile fileSst(inNameSst);\n    arcCount = fileSst.arcCount();\n    arcListRes.resize(arcCount);\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n        arcListRes.at(arcNo)  = fileSst.readArc(arcNo);\n\n    if(eclipseTransit)\n    {\n      InstrumentFile fileEF1(inName1);\n      InstrumentFile fileEF2(inName2);\n      InstrumentFile::checkArcCount({fileSst, fileEF1, fileEF2});\n      arcListEF1.resize(arcCount);\n      arcListEF2.resize(arcCount);\n      std::vector<std::vector<Double>> sumWaveP (arcCount); //sum of the waves in each arc with positive criteria\n      std::vector<std::vector<Double>> sumWaveN (arcCount); //sum of the waves in each arc with negative criteria\n      std::vector<UInt> nP (arcCount); //number of the waves in each arc with positive criteria\n      std::vector<UInt> nN (arcCount); //number of the waves in each arc with positive criteria\n\n      logStatus<<\"find candidates and compute the sum\"<<Log::endl;\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      {\n        arcListEF1.at(arcNo)  = fileEF1.readArc(arcNo);\n        arcListEF2.at(arcNo)  = fileEF2.readArc(arcNo);\n        sumWaveP.at(arcNo).resize(waveLength);\n        sumWaveN.at(arcNo).resize(waveLength);\n        nP.at(arcNo) = 1;\n        nN.at(arcNo) = 1;\n        Double criteria = 0;\n\n        countSst = arcListRes.at(arcNo).size();\n        for(UInt i=0; i<countSst; i++)\n        {\n          if(i < countSst - timeMargin)\n          {\n            criteria = arcListEF2.at(arcNo).at(i+timeMargin).value - arcListEF1.at(arcNo).at(i+timeMargin).value;\n            if(criteria >0)\n            {\n              UInt maxj = waveLength;\n              if (countSst - i < maxj)\n                  maxj = countSst - i;\n              for(UInt j=i; j< i+maxj; j++)\n                sumWaveP.at(arcNo).at(j-i) += arcListRes.at(arcNo).at(j).rangeRate;\n              i = i + maxj-1;\n              nP.at(arcNo) = nP.at(arcNo) + 1 ;\n            }\n            else if(criteria < 0)\n            {\n              UInt maxj = waveLength;\n              if (countSst - i < maxj)\n                  maxj = countSst - i;\n              for(UInt j=i; j< i+maxj; j++)\n                sumWaveN.at(arcNo).at(j-i) += arcListRes.at(arcNo).at(j).rangeRate;\n              i = i + maxj-1;\n              nN.at(arcNo) = nN.at(arcNo) + 1 ;\n            }\n          }\n        }\n      }\n\n      UInt m = perArc ? arcCount: (UInt) arcCount/neighborNumber; //number of data segments\n      Matrix sumTotalP (waveLength,m);\n      Matrix sumTotalN (waveLength,m);\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n        for(UInt i=0; i< m; i++)\n          if ((arcNo >= i*arcCount/m)&&(arcNo < (i+1)*arcCount/m))\n          {\n            for(UInt j=0; j< waveLength; j++)\n              sumTotalP(j,i) += sumWaveP.at(arcNo).at(j) / nP.at(arcNo);\n            for(UInt j=0; j< waveLength; j++)\n              sumTotalN(j,i) += sumWaveN.at(arcNo).at(j) / nN.at(arcNo);\n          }\n      // Compute the desired signal\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      {\n        UInt k =0;\n        for(UInt i=0; i< m; i++)\n          if ((arcNo >= i*arcCount/m)&&(arcNo < (i+1)*arcCount/m))\n              k= i;\n        Double criteria = 0;\n        countSst = arcListRes.at(arcNo).size();\n        for(UInt i=0; i<countSst; i++)\n        {\n          if(i < (countSst - timeMargin))\n          {\n            criteria = arcListEF2.at(arcNo).at(i+timeMargin).value - arcListEF1.at(arcNo).at(i+timeMargin).value;\n            if(criteria > 0)\n            {\n              UInt maxj = waveLength;\n              if (countSst - i < maxj)\n                  maxj = countSst - i;\n              for(UInt j=i; j< i+maxj; j++)\n              {\n                SatelliteTrackingEpoch epoch;\n                epoch.time  = arcListRes.at(arcNo).at(j).time;\n                epoch.range = epoch.rangeRate = epoch.rangeAcceleration = sumTotalP(j-i,k)/(arcCount/m);\n                sstArc_1.push_back(epoch);\n              }\n              i = i + maxj-1;\n            }\n            else if(criteria < 0)\n            {\n              UInt maxj = waveLength;\n              if (countSst - i < maxj)\n                  maxj = countSst - i;\n              for(UInt j=i; j< i+maxj; j++)\n              {\n                SatelliteTrackingEpoch epoch;\n                epoch.time  = arcListRes.at(arcNo).at(j).time;\n                epoch.range = epoch.rangeRate = epoch.rangeAcceleration = sumTotalN(j-i,k)/(arcCount/m);\n                sstArc_1.push_back(epoch);\n              }\n              i = i + maxj-1;\n            }\n            else\n            {\n              SatelliteTrackingEpoch epoch;\n              epoch.time  = arcListRes.at(arcNo).at(i).time;\n              epoch.range = epoch.rangeRate = epoch.rangeAcceleration = 0;\n              sstArc_1.push_back(epoch);\n            }\n          }\n          else\n          {\n            SatelliteTrackingEpoch epoch;\n            epoch.time  = arcListRes.at(arcNo).at(i).time;\n            epoch.range = epoch.rangeRate = epoch.rangeAcceleration = 0;\n            sstArc_1.push_back(epoch);\n          }\n        }\n      }\n      logStatus<<\"write the output eclipse transit signal <\"<<outNameEclipse<<\">\"<<Log::endl;\n      InstrumentFile::write(outNameEclipse, sstArc_1);\n    } //if (eclipseTransit)\n\n    if(lowSnr)\n    {\n      InstrumentFile fileSnr(inNameSnr);\n      InstrumentFile::checkArcCount({fileSst, fileSnr});\n      std::vector<MiscValuesArc> arcListSnr;\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      {\n        arcListSnr.push_back( fileSnr.readArc(arcNo) );\n        countSst = arcListRes.at(arcNo).size();\n        for(UInt i=0; i<countSst; i++)\n        {\n          SatelliteTrackingEpoch epoch;\n          epoch.time  = arcListRes.at(arcNo).at(i).time;\n          epoch.range = epoch.rangeRate = epoch.rangeAcceleration = 0;\n          if (arcListSnr.at(arcNo).at(i).values(2) < 590)\n               epoch.range = epoch.rangeRate = epoch.rangeAcceleration = arcListRes.at(arcNo).at(i).rangeRate;\n          sstArc_2.push_back(epoch);\n        }\n      }\n      logStatus<<\"write the output low SNR signal <\"<<outNameSnr<<\">\"<<Log::endl;\n      InstrumentFile::write(outNameSnr, sstArc_2);\n    } //if (lowSnr)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n/***************************************/\n\n"
  },
  {
    "path": "source/programs/grace/graceSstSpecialEvents.cpp",
    "content": "/***********************************************/\n/**\n* @file graceSstSpecialEvents.cpp\n*\n* @brief Detect GRACE events (eclipse, sun intrusion into star camera box).\n*\n* @author Saniya Behzadpour\n* @date 2018-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nTime-indexing deterministic signals in the GRACE K-Band measurements caused by Sun intrusions\ninto the star camera baffles of GRACE-A and eclipse transits of the satellites.\nThe events are determined by satellites' position (\\configFile{inputfileOrbit1/2}{instrument})\nand orientation (\\configFile{inputfileStarCamera1/2}{instrument}). Each type of event is represented\nby its mid-interval point per orbit revolution and is reported in \\configFile{outputfileEvents}{instrument}.\n\nThe waveform of each event is nearly constant within one month and can be approximated by a polynomial.\nFor the purpose of gravity field recovery, each waveform is parameterized by a polynomial and the coefficients\nof this polynomial are estimated as additional instrument calibration parameters in a common adjustment\nwith all other instrument, satellite, and gravity field parameters,\nsee \\configClass{parametrizationSatelliteTracking:specialEffect}{parametrizationSatelliteTrackingType:specialEffect}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/eclipse/eclipse.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Detect GRACE events (eclipse, sun intrusion into star camera box).\n* @ingroup programsGroup */\nclass GraceSstSpecialEvents\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceSstSpecialEvents, SINGLEPROCESS, \"Detect GRACE events (eclipse, sun intrusion into star camera box).\", Grace)\n\n/***********************************************/\n\nvoid GraceSstSpecialEvents::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName       fileNameOut, fileNameOutInterval;\n    FileName       fileNameOrbit1, fileNameOrbit2;\n    FileName       fileNameStarCamera1, fileNameStarCamera2;\n    EphemeridesPtr ephemerides;\n    EclipsePtr     eclipse;\n    Double         marginBefore, marginAfter;\n\n    readConfig(config, \"outputfileEvents\",     fileNameOut,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileIntervals\",  fileNameOutInterval, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileOrbit1\",      fileNameOrbit1,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit2\",      fileNameOrbit2,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera1\", fileNameStarCamera1, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera2\", fileNameStarCamera2, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"ephemerides\",          ephemerides,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"eclipse\",              eclipse,             Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"marginLeft\",           marginBefore,        Config::DEFAULT,  \"100\", \"margin size (on both sides) [seconds]\");\n    readConfig(config, \"marginRight\",          marginAfter,         Config::DEFAULT,  \"100\", \"margin size (on both sides) [seconds]\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"read star camera and orbit data\"<<Log::endl;\n    OrbitArc      orbit1      = InstrumentFile::read(fileNameOrbit1);\n    OrbitArc      orbit2      = InstrumentFile::read(fileNameOrbit2);\n    StarCameraArc starCamera1 = InstrumentFile::read(fileNameStarCamera1);\n    Arc::checkSynchronized({orbit1, orbit2, starCamera1});\n\n    MiscValueArc arc;\n    for(UInt i=0; i<orbit1.size(); i++)\n    {\n      // eclipse transit\n      // ---------------\n      const Double delta = eclipse->factor(orbit2.at(i).time, orbit2.at(i).position, ephemerides)\n                         - eclipse->factor(orbit1.at(i).time, orbit1.at(i).position, ephemerides);\n\n      if(fabs(delta) > 1e-10)\n      {\n        MiscValueEpoch epoch;\n        epoch.time  = orbit1.at(i).time;\n        epoch.value = (delta>0) ? 1 : 2;\n        arc.push_back(epoch);\n        continue;\n      }\n\n      // star camera box\n      // ----------------\n      const Vector3d direction = normalize(orbit1.at(i).position - ephemerides->position(orbit1.at(i).time, Ephemerides::SUN)); // from sun to satellite\n      const Vector3d normP     = rotaryZ(Angle(180*DEG2RAD)).rotate(rotaryX(Angle(+135*DEG2RAD)).rotate(starCamera1.at(i).rotary.inverseRotate(direction))); // Primary\n      const Vector3d normS     = rotaryZ(Angle(180*DEG2RAD)).rotate(rotaryX(Angle(-135*DEG2RAD)).rotate(starCamera1.at(i).rotary.inverseRotate(direction))); // Secondary\n      const Vector3d norm      = (normP.z() < normS.z()) ? normP : normS;\n      const Double foreAft     = RAD2DEG * std::atan(norm.x()/norm.z());\n      const Double upDown      = RAD2DEG * std::atan(norm.y()/norm.z());\n      const Double width       = 0.6;\n      if((std::fabs(foreAft) < 10+width) && (std::fabs(upDown) < 8.5+width) && ((std::fabs(std::fabs(foreAft)-10) < width) || (std::fabs(std::fabs(upDown)-8.5) < width)))\n      {\n        MiscValueEpoch epoch;\n        epoch.time  = orbit1.at(i).time;\n        if (std::fabs(std::fabs(upDown)-8.5) < width)\n        {\n          if (upDown>0)\n            epoch.value = ((foreAft>0) ? 5 : 6);\n          else\n            epoch.value = ((foreAft>0) ? 7 : 8);\n        }\n        else\n          epoch.value = ((foreAft>0) ? 3 : 4);\n        arc.push_back(epoch);\n      }\n    }\n\n    // =============================================\n\n    // Replace by mid epoch\n    // --------------------\n    MiscValueArc arcNew;\n    Double       type = -1;\n    Time         timeStart;\n    for(UInt i=0; i<arc.size(); i++)\n    {\n      if((arc.at(i).value != type) || (arc.at(i).time > arc.at(i-1).time+seconds2time(10*60)))\n      {\n        arcNew.push_back(arc.at(i));\n        timeStart = arc.at(i).time;\n        type      = arc.at(i).value;\n      }\n      if(arc.at(i).value == type)\n        arcNew.at(arcNew.size()-1).time = timeStart + 0.5*(arc.at(i).time-timeStart);\n    }\n\n    logStatus<<\"write events to file<\"<<fileNameOut<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOut, arcNew);\n    Arc::printStatistics(arcNew);\n\n    // =============================================\n\n    MiscValueArc arcInterval;\n    std::vector<Time> time = orbit1.times();\n    UInt idx = 0;\n    for(UInt idEpoch=0; idEpoch<time.size(); idEpoch++)\n    {\n      // find event\n      while((idx < arcNew.size()) && (arcNew.at(idx).time+seconds2time(marginAfter) < time.at(idEpoch)))\n        idx++;\n      if(idx >= arcNew.size())\n        break;\n      if(time.at(idEpoch) < arcNew.at(idx).time-seconds2time(marginBefore))\n        continue;\n\n      MiscValueEpoch epoch;\n      epoch.time  = time.at(idEpoch);\n      epoch.value = arcNew.at(idx).value;\n      arcInterval.push_back(epoch);\n    }//for\n\n    logStatus<<\"write intervals to file<\"<<fileNameOutInterval<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOutInterval, arcInterval);\n    Arc::printStatistics(arcInterval);\n\n    // =============================================\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/grace/graceThrusterResponse2Accelerometer.cpp",
    "content": "/***********************************************/\n/**\n* @file graceThrusterResponse2Accelerometer.cpp\n*\n* @brief Add modeled thruster responses to accelerometer.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-07-31\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nAdd modeled thruster responses to accelerometer data.\nThe epochs and durations are given in the \\configFile{inputfileThruster}{instrument} (THRUSTER).\n\nThe \\configFile{inputfileThrusterResponse}{matrix} is a $(6\\times 3)$ matrix with\nthe linear accelerations in the SRF ($x, y, z$) in one line per pair:\n\\begin{enumerate}\n\\item Negative Yaw,\n\\item Positive Pitch,\n\\item Positive Yaw,\n\\item Negative Pitch,\n\\item Negative Roll,\n\\item Positive Roll.\n\\end{enumerate}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Add modeled thruster responses to accelerometer.\n* @ingroup programsGroup */\nclass GraceThrusterResponse2Accelerometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GraceThrusterResponse2Accelerometer, SINGLEPROCESS, \"Add modeled thruster responses to accelerometer\", Grace, Instrument)\n\n/***********************************************/\n\nvoid GraceThrusterResponse2Accelerometer::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n    FileName fileNameThruster;\n    FileName fileNameResponse;\n\n    readConfig(config, \"outputfileAccelerometer\",   fileNameOut,      Config::MUSTSET, \"\", \"ACCELEROMETER\");\n    readConfig(config, \"inputfileAccelerometer\",    fileNameIn,       Config::MUSTSET, \"\", \"ACCELEROMETER\");\n    readConfig(config, \"inputfileThruster\",         fileNameThruster, Config::MUSTSET, \"\", \"THRUSTER\");\n    readConfig(config, \"inputfileThrusterResponse\", fileNameResponse, Config::MUSTSET, \"\", \"thruster model (matrix with one line per pair)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read accelerometer data <\"<<fileNameIn<<\">\"<<Log::endl;\n    AccelerometerArc  acc      = InstrumentFile::read(fileNameIn);\n    std::vector<Time> timesAcc = acc.times();\n    ThrusterArc       thruster = InstrumentFile::read(fileNameThruster);\n    Matrix            responses;\n    readFileMatrix(fileNameResponse, responses);\n\n    logStatus<<\"add modeled thruster responses\"<<Log::endl;\n    auto iter = timesAcc.begin();\n    for(UInt i=0; i<thruster.size(); i++)\n    {\n      // find acc epoch after thruster start\n      iter = std::upper_bound(iter, timesAcc.end(), thruster.at(i).time);\n      if(iter == timesAcc.end())   break;\n      if(iter == timesAcc.begin()) iter++;\n\n      Vector thrusterDuration = 1e-3*thruster.at(i).data(); // duration for each thruster\n      for(UInt k=0; k<responses.rows(); k++)\n        if(thrusterDuration(k) > 0)\n        {\n          auto   accEpoch = acc.begin() + std::distance(timesAcc.begin(), iter);\n          Double fraction = (accEpoch->time - thruster.at(i).time).seconds() / (accEpoch->time - (accEpoch-1)->time).seconds();  // fractional part at begin\n          do\n          {\n            if((accEpoch->time - thruster.at(i).time).seconds() - thrusterDuration(k) > 0)\n              fraction -= ((accEpoch->time - thruster.at(i).time).seconds() - thrusterDuration(k)) / (accEpoch->time - (accEpoch-1)->time).seconds(); // fractional part at end\n            accEpoch->acceleration += fraction * Vector3d(responses.row(k).trans());\n            fraction = 1;\n          }\n          while(((accEpoch++)->time - thruster.at(i).time).seconds() < thrusterDuration(k));\n        }\n    }\n\n    logInfo<<\"write accelerometer data to <\"<<fileNameOut<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOut, acc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/grace/instrumentSatelliteTrackingAntennaCenterCorrection.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentSatelliteTrackingAntennaCenterCorrection.cpp\n*\n* @brief Compute antenna center correction from orbit configuration.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-21\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the correction due to offset of the antenna center relative the center of mass.\nThe offsets $\\M c_A$ and $\\M c_B$ in \\configFile{inputfileAntennaCenters}{matrix} are given in the satellite\nreference frame. These offsets are rotated into the the inertial frame with $\\M D_A$ and $\\M D_B$ from\n\\configFile{inputfileStarCamera}{instrument} and projected onto the line of sight (LOS)\n\\begin{equation}\n  \\rho_{AOC} = \\M e_{AB}\\cdot(\\M D_A\\,\\M c_A - \\M D_B\\,\\M c_B),\n\\end{equation}\nwith the unit vector in line of sight direction\n\\begin{equation}\n  \\M e_{AB} = \\frac{\\M r_B - \\M r_A}{\\left\\lVert{\\M r_B - \\M r_A}\\right\\rVert}.\n\\end{equation}\nThe corrections for the range-rates and range-acceleration are computed by differentiating\nan interpolation polynomial of degree \\config{interpolationDegree}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute antenna center correction from orbit configuration.\n* @ingroup programsGroup */\nclass InstrumentSatelliteTrackingAntennaCenterCorrection\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentSatelliteTrackingAntennaCenterCorrection, PARALLEL, \"compute antenna center correction from orbit configuration\", Grace, Instrument)\n\n/***********************************************/\n\nvoid InstrumentSatelliteTrackingAntennaCenterCorrection::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName    outSSTName;\n    FileName    orbit1Name,  starCamera1Name;\n    FileName    orbit2Name,  starCamera2Name;\n    Vector3d    center1, center2;\n    UInt        degree;\n    std::string choice;\n\n    readConfig(config, \"outputfileSatelliteTracking\", outSSTName,      Config::OPTIONAL, \"\", \"corrections for range, range-rate, and range-accelerations\");\n    readConfig(config, \"inputfileOrbit1\",             orbit1Name,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit2\",             orbit2Name,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera1\",        starCamera1Name, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera2\",        starCamera2Name, Config::MUSTSET,  \"\", \"\");\n    if(readConfigChoice(config, \"antennaCenters\",     choice,          Config::MUSTSET, \"\", \"KBR antenna phase center\"))\n    {\n      if(readConfigChoiceElement(config, \"value\", choice, \"\"))\n      {\n        readConfig(config, \"center1X\", center1.x(), Config::DEFAULT,   \"1.4451172588\", \"x-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center1Y\", center1.y(), Config::DEFAULT,  \"-0.0004233040\", \"y-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center1Z\", center1.z(), Config::DEFAULT,   \"0.0022786600\", \"z-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center2X\", center2.x(), Config::DEFAULT,   \"1.4443870350\", \"x-coordinate of antenna position in SRF [m] for GRACEB\");\n        readConfig(config, \"center2Y\", center2.y(), Config::DEFAULT,   \"0.0005761203\", \"y-coordinate of antenna position in SRF [m] for GRACEB\");\n        readConfig(config, \"center2Z\", center2.z(), Config::DEFAULT,   \"0.0033040887\", \"z-coordinate of antenna position in SRF [m] for GRACEB\");\n      }\n      if(readConfigChoiceElement(config, \"file\",  choice, \"\"))\n      {\n        FileName fileName;\n        readConfig(config, \"inputAntennaCenters\", fileName, Config::MUSTSET, \"\", \"\");\n        if(!isCreateSchema(config))\n        {\n          Matrix x;\n          readFileMatrix(fileName, x);\n          center1 = Vector3d(x(0,0), x(1,0), x(2,0));\n          center2 = Vector3d(x(3,0), x(4,0), x(5,0));\n        }\n      }\n      endChoice(config);\n    }\n    readConfig(config, \"interpolationDegree\", degree, Config::DEFAULT,  \"2\", \"differentiation by polynomial approximation of degree n\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read orbit and star camera data and generate antenna offset corrections\"<<Log::endl;\n    InstrumentFile  orbit1File(orbit1Name);\n    InstrumentFile  orbit2File(orbit2Name);\n    InstrumentFile  starCamera1File(starCamera1Name);\n    InstrumentFile  starCamera2File(starCamera2Name);\n    InstrumentFile::checkArcCount({orbit1File, orbit2File, starCamera1File, starCamera2File});\n\n    std::vector<Arc> arcList(orbit1File.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc      orbit1      = orbit1File.readArc(arcNo);\n      OrbitArc      orbit2      = orbit2File.readArc(arcNo);\n      StarCameraArc starCamera1 = starCamera1File.readArc(arcNo);\n      StarCameraArc starCamera2 = starCamera2File.readArc(arcNo);\n      Arc::checkSynchronized({orbit1, orbit2, starCamera1, starCamera2});\n\n      Matrix A(orbit1.size(), 4);\n      for(UInt i=0; i<A.rows(); i++)\n      {\n        const Vector3d u = (orbit2.at(i).position - orbit1.at(i).position);                                       // center of mass vector\n        const Vector3d v = (starCamera2.at(i).rotary.rotate(center2) - starCamera1.at(i).rotary.rotate(center1)); // combined antenna offset vector\n        A(i,1) = u.r() - (u+v).r();  // COM - ANT -> AOC\n      }\n\n      const std::vector<Time> times = orbit1.times();\n      Polynomial p(times, degree);\n      copy(p.derivative(   times, A.column(1)), A.column(2));\n      copy(p.derivative2nd(times, A.column(1)), A.column(3));\n\n      return Arc(times, A, Epoch::Type::SATELLITETRACKING);\n    }, comm); // forEach\n\n    if(Parallel::isMaster(comm) && !outSSTName.empty())\n    {\n      logStatus<<\"write tracking data to file <\"<<outSSTName<<\">\"<<Log::endl;\n      InstrumentFile::write(outSSTName, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/grace/instrumentStarCameraAngularAccelerometerFusion.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentStarCameraAngularAccelerometerFusion.cpp\n*\n* @brief Estimation of the satellites orientation from star camera and angular accelerometer data.\n*\n* @author Beate Klinger\n* @author Torsten Mayer-Guerr\n* @date 2017-06-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates the satellites orientation from star camera data\n\\configFile{inputfileStarCamera}{instrument} and angular accelerometer data\n\\configFile{inputfileAngularAcc}{instrument}. The combination of both observation types\nis achieved in a least square adjustment. The optimal weighting between the two different\nobservation groups is achieved by means of VCE in combination with a robust estimator.\nThe system of linearized observation equations within the sensor fusion approach can be formulated as:\n\\begin{equation}\n  \\begin{bmatrix}\n  \\M l_{ACC1B}\\\\\n  \\M l_{SCA1B}\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  \\M A_{ACC1B} & \\M B_{ACC1B}\\\\\n  \\M A_{SCA1B} & \\M 0\n  \\end{bmatrix}\n  \\begin{bmatrix}\n  \\M q\\\\\n  \\M b\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n  \\frac{\\partial \\dot{\\boldsymbol{\\omega}}}{\\partial \\M q} & \\frac{\\partial \\dot{\\boldsymbol{\\omega}}}{\\partial \\M b}\\\\\n  \\M I & \\M 0\n  \\end{bmatrix}\n  \\begin{bmatrix}\n  \\M q\\\\\n  \\M b\n  \\end{bmatrix}\n\\end{equation}\nwith\n\\begin{equation}\\begin{split}\n  \\M l_{ACC1B}  &= \\dot{\\boldsymbol{\\omega}}_{ACC1B} - \\dot{\\boldsymbol{\\omega}}_{0}, \\\\\n  \\M l_{SCA1B}  &= \\M q_{SCA1B} - \\M q_{0}, \\\\\n  \\M q_{Fusion} &= \\M q + \\M q_{0}.\n\\end{split}\\end{equation}\nThe reference values $\\M q_{0}$ and $\\dot{\\boldsymbol{\\omega}}_{0}$ are derived\nfrom \\configFile{inputfileStarCameraReference}{instrument}. In the course of the estimation,\nthe accelerometer data is calibrated, by setting a bias factor $\\M b$ with \\config{accBias}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimation of the satellites orientation from star camera and angular accelerometer data.\n* @ingroup programsGroup */\nclass InstrumentStarCameraAngularAccelerometerFusion\n{\npublic:\n\n  class ArcObservation\n  {\n  public:\n    StarCameraArc    starCamera;\n    Covariance3dArc  starCameraCovariance;\n    AccelerometerArc angularAcc;\n    MiscValueArc     epochSigmaSca, epochSigmaAcc;\n    Vector           sigmaSca, sigmaAcc;\n    Vector           x;\n  };\n\n  FileName                   fileNameOutStarCamera;\n  FileName                   fileNameOutCovariance;\n  FileName                   fileNameOutCovarianceMatrix;\n  FileName                   fileNameOutAngularAcc;\n  FileName                   fileNameOutEpochSigmasStarCamera;\n  FileName                   fileNameOutEpochSigmasAccelerometer;\n  InstrumentFile             starCamera0File;\n  std::vector<Time>          timesSca;\n  Matrix                     quaternionSca;\n  Covariance3dArc            starCameraCovariance;\n  std::vector<Time>          timesAcc;\n  AccelerometerArc           angularAcc;\n  Bool                       correctAccNonSquare;\n  ParametrizationTemporalPtr accBias, accScale;\n  Bool                       perAxisSca, perAxisAcc;\n  Double                     sigmaSca0;\n  Double                     sigmaAccX, sigmaAccY, sigmaAccZ;\n  Double                     huber, huberPower;\n  UInt                       degree;\n  Matrix                     P; // polynomial interpolation\n  UInt                       iterCount;\n\n\n  Bool           index(const Time &time, std::vector<Time> &times, UInt &idx) const;\n  ArcObservation computeArc(UInt arc);\n  static Vector  computeRedundancy(std::vector<Matrix> &A, MatrixDistributed &normals, Double threshold=1e-4);\n  static void    estimateAccuracy(std::vector<Vector> &e, std::vector<Vector> &redundancy, Bool sigmaPerAxis, Double huber, Double huberPower, Vector &sigmaAxis, Vector &sigmaEpoch);\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentStarCameraAngularAccelerometerFusion, PARALLEL, \"estimation of the satellites orientation from star camera and angular accelerometer data.\", Grace, Instrument)\n\n/***********************************************/\n\ntemplate<> void save(OutArchive &oa, const InstrumentStarCameraAngularAccelerometerFusion::ArcObservation &arc)\n{\n  oa<<nameValue(\"starCamera\",           arc.starCamera);\n  oa<<nameValue(\"starCameraCovariance\", arc.starCameraCovariance);\n  oa<<nameValue(\"angularAcc\",           arc.angularAcc);\n  oa<<nameValue(\"sigmaSca\",             arc.sigmaSca);\n  oa<<nameValue(\"sigmaAcc\",             arc.sigmaAcc);\n  oa<<nameValue(\"epochSigmaSca\",        arc.epochSigmaSca);\n  oa<<nameValue(\"epochSigmaAcc\",        arc.epochSigmaAcc);\n  oa<<nameValue(\"x\",                    arc.x);\n}\n\ntemplate<> void load(InArchive  &ia, InstrumentStarCameraAngularAccelerometerFusion::ArcObservation &arc)\n{\n  ia>>nameValue(\"starCamera\",           arc.starCamera);\n  ia>>nameValue(\"starCameraCovariance\", arc.starCameraCovariance);\n  ia>>nameValue(\"angularAcc\",           arc.angularAcc);\n  ia>>nameValue(\"sigmaSca\",             arc.sigmaSca);\n  ia>>nameValue(\"sigmaAcc\",             arc.sigmaAcc);\n  ia>>nameValue(\"epochSigmaSca\",        arc.epochSigmaSca);\n  ia>>nameValue(\"epochSigmaAcc\",        arc.epochSigmaAcc);\n  ia>>nameValue(\"x\",                    arc.x);\n}\n\n/***********************************************/\n\nvoid InstrumentStarCameraAngularAccelerometerFusion::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOutSolution;\n    FileName fileNameStarCamera0;\n    FileName fileNameStarCamera, fileNameStarCameraCov, fileNameAngularAcc;\n\n    readConfig(config, \"outputfileStarCamera\",              fileNameOutStarCamera,               Config::MUSTSET,  \"\",      \"combined quaternions\");\n    readConfig(config, \"outputfileCovariance\",              fileNameOutCovariance,               Config::OPTIONAL, \"\",      \"epoch-wise covariance matrix\");\n    readConfig(config, \"outputfileCovarianceMatrix\",        fileNameOutCovarianceMatrix,         Config::OPTIONAL, \"\",      \"full arc-wise covariance matrix per arc. arc number is appended to filename\");\n    readConfig(config, \"outputfileEpochSigmaStarCamera\",    fileNameOutEpochSigmasStarCamera,    Config::OPTIONAL, \"\",      \"from vce and outlier detection\");\n    readConfig(config, \"outputfileEpochSigmaAccelerometer\", fileNameOutEpochSigmasAccelerometer, Config::OPTIONAL, \"\",      \"from vce and outlier detection\");\n    readConfig(config, \"outputfileAngularAcc\",              fileNameOutAngularAcc,               Config::OPTIONAL, \"\",      \"angular acceleration observations (bias removed)\");\n    readConfig(config, \"outputfileSolution\",                fileNameOutSolution,                 Config::OPTIONAL, \"\",      \"estimated parameter (one column for each arc)\");\n    readConfig(config, \"inputfileStarCameraReference\",      fileNameStarCamera0,                 Config::MUSTSET,  \"\",      \"quaternions as taylor point\");\n    readConfig(config, \"inputfileStarCamera\",               fileNameStarCamera,                  Config::MUSTSET,  \"\",      \"star camera observations\");\n    readConfig(config, \"inputfileStarCameraCovariance\",     fileNameStarCameraCov,               Config::OPTIONAL, \"\",      \"star camera observations\");\n    readConfig(config, \"inputfileAngularAcc\",               fileNameAngularAcc,                  Config::MUSTSET,  \"\",      \"angular acceleration observations\");\n    readConfig(config, \"correctAccNonQuadratic\",            correctAccNonSquare,                 Config::DEFAULT,  \"1\",     \"apply correction (non-square proof mass)\");\n    readConfig(config, \"accBias\",                           accBias,                             Config::DEFAULT,  \"\",      \"accelerometer bias per interval and axis\");\n    readConfig(config, \"accScale\",                          accScale,                            Config::DEFAULT,  \"\",      \"accelerometer scale per interval and axis\");\n    readConfig(config, \"sigmaStarcamera\",                   sigmaSca0,                           Config::DEFAULT,  \"1.\",    \"[rad]\");\n    readConfig(config, \"sigmaAccelerometerX\",               sigmaAccX,                           Config::DEFAULT,  \"10e-7\", \"[rad/s^2]\");\n    readConfig(config, \"sigmaAccelerometerY\",               sigmaAccY,                           Config::DEFAULT,  \"2e-7\",  \"[rad/s^2]\");\n    readConfig(config, \"sigmaAccelerometerZ\",               sigmaAccZ,                           Config::DEFAULT,  \"2e-7\",  \"[rad/s^2]\");\n    readConfig(config, \"estimateSigmaScaPerAxis\",           perAxisSca,                          Config::DEFAULT,  \"0\",     \"separate variance factor for roll, pitch, yaw, instead of one common factor.\"\"\");\n    readConfig(config, \"estimateSigmaAccPerAxis\",           perAxisAcc,                          Config::DEFAULT,  \"1\",     \"separate variance factor for each accelerometer axis, instead of one common factor.\");\n    readConfig(config, \"huber\",                             huber,                               Config::DEFAULT,  \"2.5\",   \"residuals > huber*sigma0 are downweighted\");\n    readConfig(config, \"huberPower\",                        huberPower,                          Config::DEFAULT,  \"1.5\",   \"residuals > huber: sigma=(e/huber)^power*sigma0\");\n    readConfig(config, \"interpolationDegree\",               degree,                              Config::DEFAULT,  \"2\",     \"\");\n    readConfig(config, \"iterationCount\",                    iterCount,                           Config::DEFAULT,  \"15\",    \"non linear equation solved iteratively\");\n    if(isCreateSchema(config)) return;\n\n    // Read instruments\n    // ----------------\n    StarCameraArc starCamera = InstrumentFile::read(fileNameStarCamera);\n    starCameraCovariance     = InstrumentFile::read(fileNameStarCameraCov);\n    Arc::checkSynchronized({starCamera, starCameraCovariance});\n    angularAcc               = InstrumentFile::read(fileNameAngularAcc);\n    timesSca                 = starCamera.times();\n    quaternionSca            = starCamera.matrix().column(1,4); // without time\n    timesAcc                 = angularAcc.times();\n\n    // polynomial interpolation matrix\n    // -------------------------------\n    P = Matrix(degree+1, degree+1);\n    for(UInt i=0; i<P.rows(); i++)\n    {\n      P(0,i) = 1.0;\n      for(UInt n=1; n<P.columns(); n++)\n        P(n,i) = (i-degree/2.) * P(n-1,i);\n    }\n    inverse(P);\n\n    // computing quaternions\n    // ---------------------\n    logStatus<<\"computing quaternions\"<<Log::endl;\n    starCamera0File.open(fileNameStarCamera0);\n    std::vector<ArcObservation> arcs(starCamera0File.arcCount());\n    Parallel::forEach(arcs, [this] (UInt arcNo) {return computeArc(arcNo);}, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        logInfo<<\"  \"<<arcNo%\"%2i. arc \"s\n               <<\"sigmaScaX = \"<<arcs.at(arcNo).sigmaSca(0)%\"%8.2e, \"s\n               <<\"sigmaScaY = \"<<arcs.at(arcNo).sigmaSca(1)%\"%8.2e, \"s\n               <<\"sigmaScaZ = \"<<arcs.at(arcNo).sigmaSca(2)%\"%8.2e, \"s\n               <<\"sigmaAccX = \"<<arcs.at(arcNo).sigmaAcc(0)%\"%8.2e, \"s\n               <<\"sigmaAccY = \"<<arcs.at(arcNo).sigmaAcc(1)%\"%8.2e, \"s\n               <<\"sigmaAccZ = \"<<arcs.at(arcNo).sigmaAcc(2)%\"%8.2e\"s<<Log::endl;\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutStarCamera.empty())\n    {\n      logStatus<<\"write starCamera file <\"<<fileNameOutStarCamera<<\">\"<<Log::endl;\n      std::vector<Arc> arcList(arcs.size());\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.at(arcNo) = arcs.at(arcNo).starCamera;\n      InstrumentFile::write(fileNameOutStarCamera, arcList);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutCovariance.empty())\n    {\n      logStatus<<\"write covariance file <\"<<fileNameOutCovariance<<\">\"<<Log::endl;\n      std::vector<Arc> arcList(arcs.size());\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.at(arcNo) = arcs.at(arcNo).starCameraCovariance;\n      InstrumentFile::write(fileNameOutCovariance, arcList);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutAngularAcc.empty())\n    {\n      logStatus<<\"write angular acceleration file <\"<<fileNameOutAngularAcc<<\">\"<<Log::endl;\n      std::vector<Arc> arcList(arcs.size());\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.at(arcNo) = arcs.at(arcNo).angularAcc;\n      InstrumentFile::write(fileNameOutAngularAcc, arcList);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutSolution.empty())\n    {\n      logStatus<<\"write solution file <\"<<fileNameOutSolution<<\">\"<<Log::endl;\n      Matrix x(arcs.at(0).x.rows(), arcs.size());\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        copy(arcs.at(arcNo).x, x.column(arcNo));\n      writeFileMatrix(fileNameOutSolution, x);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutEpochSigmasStarCamera.empty())\n    {\n      logStatus<<\"write star camera epoch sigmas to file <\"<<fileNameOutEpochSigmasStarCamera<<\">\"<<Log::endl;\n      std::vector<Arc> arcList(arcs.size());\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.at(arcNo) = arcs.at(arcNo).epochSigmaSca;\n      InstrumentFile::write(fileNameOutEpochSigmasStarCamera, arcList);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutEpochSigmasAccelerometer.empty())\n    {\n      logStatus<<\"write accelerometer epoch sigmas to file <\"<<fileNameOutEpochSigmasAccelerometer<<\">\"<<Log::endl;\n      std::vector<Arc> arcList(arcs.size());\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.at(arcNo) = arcs.at(arcNo).epochSigmaAcc;\n      InstrumentFile::write(fileNameOutEpochSigmasAccelerometer, arcList);\n    }\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool InstrumentStarCameraAngularAccelerometerFusion::index(const Time &time, std::vector<Time> &times, UInt &idx) const\n{\n  try\n  {\n    const Time timeMargin = seconds2time(1e-5);\n    // search time slot\n    while((idx < times.size()) && (times.at(idx)+timeMargin < time))\n      idx++;\n    if(idx >= times.size())\n      return FALSE;\n    if(times.at(idx)-timeMargin > time)\n      return FALSE;\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nInstrumentStarCameraAngularAccelerometerFusion::ArcObservation InstrumentStarCameraAngularAccelerometerFusion::computeArc(UInt arcNo)\n{\n  try\n  {\n    const StarCameraArc     starCamera0 = starCamera0File.readArc(arcNo);\n    const std::vector<Time> times       = starCamera0.times();\n    const UInt              epochCount  = starCamera0.size();\n    const Double            dt          = medianSampling(times).seconds();\n\n    // approximate values\n    // ------------------\n    Matrix q = starCamera0.matrix().column(1,4);\n    // check sign\n    UInt idxSca = 0;\n    for(UInt i=0; i<epochCount; i++)\n      if(index(times.at(i), timesSca, idxSca))\n        if(inner(quaternionSca.row(idxSca), q.row(i)) < 0)\n        {\n          q *= -1;\n          break;\n        }\n\n    // accelerometer calibration\n    // -------------------------\n    accBias->setInterval (times.at(0), times.back()+seconds2time(dt), TRUE/*estimatePerArc*/);\n    accScale->setInterval(times.at(0), times.back()+seconds2time(dt), TRUE/*estimatePerArc*/);\n\n    UInt countAccCal = 0;\n    const UInt idxAccBias  = countAccCal; countAccCal += 3 * accBias->parameterCount();\n    const UInt idxAccScale = countAccCal; countAccCal += 3 * accScale->parameterCount();\n\n    // epoch wise sigmas\n    // -----------------\n    Vector sigmaAxisSca = {sigmaSca0, sigmaSca0, sigmaSca0};\n    Vector sigmaEpochSca(epochCount);\n    for(UInt i=0; i<epochCount; i++)\n      sigmaEpochSca(i) = 1.;\n\n    Vector sigmaAxisAcc = {sigmaAccX, sigmaAccY, sigmaAccZ};\n    Vector sigmaEpochAcc(epochCount);\n    for(UInt i=0; i<epochCount; i++)\n      sigmaEpochAcc(i) = 1.;\n\n    // normal equations (kite structure)\n    // ---------------------------------\n    Double lPl      = 0;\n    UInt   obsCount = 0;\n    Vector n(3*epochCount+countAccCal);\n    Vector xAccCal(countAccCal);\n\n    std::vector<UInt> blockIndex(1, 0);\n    for(UInt i=0; i<epochCount; i++)\n      blockIndex.push_back( blockIndex.back()+3 );\n\n    const UInt idxBlockCal = epochCount;\n    if(countAccCal)\n      blockIndex.push_back( blockIndex.back()+countAccCal );\n\n    MatrixDistributed normals;\n    normals.initEmpty(blockIndex, Parallel::selfCommunicator());\n    const UInt blockCount = normals.blockCount();\n    for(UInt i=0; i<epochCount; i++)\n      normals.setBlock(i, i);\n\n    // =============================================\n\n    Double sigma0 = 1.;\n    std::vector<Bool> hasSca(epochCount, FALSE);\n    std::vector<Bool> hasAcc(epochCount, FALSE);\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      // init normal equations\n      // ---------------------\n      normals.setNull();\n      n.setNull();\n      lPl      = 0;\n      obsCount = 0;\n\n      std::vector<Matrix> Q(epochCount);\n      for(UInt i=0; i<epochCount; i++)\n        Q.at(i) = {{-q(i,1),  q(i,0),  q(i,3), -q(i,2)},\n                   {-q(i,2), -q(i,3),  q(i,0),  q(i,1)},\n                   {-q(i,3),  q(i,2), -q(i,1),  q(i,0)}};\n\n      // star camera observations\n      // ------------------------\n      std::vector<Matrix> scaA(epochCount);\n      std::vector<Vector> scaL(epochCount);\n      UInt                idxSca = 0;\n      for(UInt i=0; i<epochCount; i++)\n        if(index(times.at(i), timesSca, idxSca))\n        {\n          hasSca.at(i) = TRUE;\n\n          scaA.at(i) = identityMatrix(3);\n          scaL.at(i) = 2*Q.at(i)*quaternionSca.row(idxSca).trans();\n\n          // decorrelation\n          Matrix W = (starCameraCovariance.size()) ? starCameraCovariance.at(idxSca).covariance.matrix() : identityMatrix(3, Matrix::SYMMETRIC);\n          cholesky(W);\n          for(UInt idAxis=0; idAxis<3; idAxis++)\n            W.column(idAxis) *= sigmaEpochSca(i)*sigmaAxisSca(idAxis);\n          triangularSolve(1., W.trans(), scaA.at(i));\n          triangularSolve(1., W.trans(), scaL.at(i));\n\n          matMult(1., scaA.at(i).trans(), scaL.at(i), n.row(normals.blockIndex(i), normals.blockSize(i)));\n          rankKUpdate(1., scaA.at(i), normals.N(i,i));\n          lPl      += quadsum(scaL.at(i));\n          obsCount += scaL.at(i).rows();\n        } // for(i=epochCount)\n\n      // angular accelerations observations\n      // ----------------------------------\n      std::vector<UInt>                accIdxA(epochCount); // start of A matrix\n      std::vector<std::vector<Matrix>> accA(epochCount);    // quaternions\n      std::vector<Matrix>              accB(epochCount);    // bias & scale\n      std::vector<Vector>              accL(epochCount);\n      UInt                             idxAcc = 0;\n      for(UInt i=0; i<epochCount; i++)\n        if(index(times.at(i), timesAcc, idxAcc))\n        {\n          hasAcc.at(i) = TRUE;\n\n          // polynomial 2nd differentiation\n          const UInt idx = std::min(std::max(i, degree/2)-degree/2, epochCount-degree-1); // interval\n          Vector factors = Vector(degree+1);  // derivation coefficients\n          const Double tau = i-idx-degree/2.;\n          Double f = 1./(dt*dt);\n          for(UInt n=2; n<factors.rows(); n++)\n          {\n            axpy(n*(n-1)*f, P.column(n), factors);\n            f *= tau;\n          }\n\n          // reduced observations\n          accL.at(i) = angularAcc.at(idxAcc).acceleration.vector();\n          for(UInt k=0; k<factors.size(); k++)\n            matMult(-2*factors(k), Q.at(i), q.row(idx+k).trans(), accL.at(i));\n\n          if(correctAccNonSquare)\n          {\n            // polynomial differentiation\n            UInt idxRate = std::min(std::max(i, UInt(1))-1, epochCount-2);\n            std::vector<Double> factorsRate = {-1/dt, 0, 1/dt};\n            if((i == 0) || (i == epochCount-1))\n              factorsRate = {-1/dt, 1/dt};\n\n            Vector angularRate(3);\n            for(UInt k=0; k<factorsRate.size(); k++)\n              matMult(2*factorsRate.at(k), Q.at(i), q.row(idxRate+k).trans(), angularRate);\n\n            const Double Ix = 1.037e-5;\n            const Double Iy = 1.959e-5;\n            const Double Iz = Ix;\n            accL.at(i)(0) -= (Iz-Iy)/Ix * angularRate(2) * angularRate(1);\n            accL.at(i)(1) -= (Iz-Ix)/Iy * angularRate(2) * angularRate(0);\n            accL.at(i)(2) -= (Iy-Ix)/Iz * angularRate(1) * angularRate(0);\n          }\n\n          // dacc(i)/dq(k)\n          accIdxA.at(i) = idx;\n          accA.at(i).resize(factors.size());\n          for(UInt k=0; k<factors.size(); k++) // w_dot(i) = sum_k factor(k) alpha(k)\n            accA.at(i).at(k) = factors(k) * identityMatrix(3);\n\n          // calibration parameter\n          accB.at(i) = Matrix(3, countAccCal);\n          if(accBias->parameterCount())\n            accBias->designMatrix(times.at(i), identityMatrix(3), accB.at(i).column(idxAccBias, 3*accBias->parameterCount()));\n          if(accScale->parameterCount())\n          {\n            Matrix S(3, 3);\n            S(0, 0) = angularAcc.at(idxAcc).acceleration.x();\n            S(1, 1) = angularAcc.at(idxAcc).acceleration.y();\n            S(2, 2) = angularAcc.at(idxAcc).acceleration.z();\n            accScale->designMatrix(times.at(i), S, accB.at(i).column(idxAccScale, S.columns()*accScale->parameterCount()));\n          }\n\n          // decorrelation\n          for(UInt idAxis=0; idAxis<3; idAxis++)\n          {\n            accL.at(i)(idAxis) *= 1./(sigmaEpochAcc(i)*sigmaAxisAcc(idAxis));\n            for(UInt k=0; k<accA.at(i).size(); k++)\n              accA.at(i).at(k).row(idAxis) *= 1./(sigmaEpochAcc(i)*sigmaAxisAcc(idAxis));\n            if(accB.at(i).size())\n              accB.at(i).row(idAxis) *= 1./(sigmaEpochAcc(i)*sigmaAxisAcc(idAxis));\n          }\n\n          // accumulate normals\n          for(UInt k=0; k<factors.size(); k++)\n          {\n            matMult(1., accA.at(i).at(k).trans(), accL.at(i), n.row(normals.blockIndex(idx+k), normals.blockSize(idx+k)));\n            rankKUpdate(1., accA.at(i).at(k), normals.N(idx+k, idx+k));     // N11(i)\n            for(UInt j=k+1; j<factors.size(); j++)                          // N11(i), secondary diagonal\n            {\n              normals.setBlock(idx+k, idx+j);\n              matMult(1., accA.at(i).at(k).trans(), accA.at(i).at(j), normals.N(idx+k, idx+j));\n            }\n            if(accB.at(i).size())\n            {\n              normals.setBlock(idx+k, idxBlockCal);\n              matMult(1., accA.at(i).at(k).trans(), accB.at(i), normals.N(idx+k, idxBlockCal)); // N12(i)\n            }\n          }\n          if(accB.at(i).size())\n          {\n            normals.setBlock(idxBlockCal, idxBlockCal);\n            matMult(1., accB.at(i).trans(), accL.at(i), n.row(normals.blockIndex(idxBlockCal), normals.blockSize(idxBlockCal))); // n2\n            rankKUpdate(1., accB.at(i), normals.N(idxBlockCal, idxBlockCal)); // N22\n          }\n          lPl += quadsum(accL.at(i));\n          obsCount += accL.at(i).rows();\n        } // for(i=epochCount)\n\n      // regularize epochs without SCA\n      // -----------------------------\n      for(UInt i=0; i<epochCount; i++)\n        if(!hasSca.at(i))\n        {\n          const Double sigma = 0.25*DEG2RAD;\n          axpy(1./(sigma*sigma), identityMatrix(3), normals.N(i,i));\n        }\n\n      // Solve\n      // -----\n      const Vector dx = normals.solve(n, FALSE/*timing*/);\n      const Double sigma0Old = sigma0;\n      sigma0 = sqrt((lPl-inner(dx,n))/(obsCount-dx.rows()));\n      if(countAccCal)\n        xAccCal += dx.row(normals.blockIndex(idxBlockCal), normals.blockSize(idxBlockCal));\n\n      // update approximate values\n      // -------------------------\n      for(UInt i=0; i<epochCount; i++)\n      {\n        matMult(0.5, Q.at(i).trans(), dx.row(normals.blockIndex(i), normals.blockSize(i)), q.row(i).trans());\n        q.row(i) *= 1./norm(q.row(i));\n      }\n\n      // remove calibration parameter\n      // ----------------------------\n      if(countAccCal)\n      {\n        UInt idxAcc = 0;\n        for(UInt i=0; i<epochCount; i++)\n          if(index(times.at(i), timesAcc, idxAcc))\n          {\n            Vector accCal = accB.at(i) * dx.row(normals.blockIndex(idxBlockCal), normals.blockSize(idxBlockCal));\n            angularAcc.at(idxAcc).acceleration.x() -= (sigmaEpochAcc(i)*sigmaAxisAcc(0)) * accCal(0);\n            angularAcc.at(idxAcc).acceleration.y() -= (sigmaEpochAcc(i)*sigmaAxisAcc(1)) * accCal(1);\n            angularAcc.at(idxAcc).acceleration.z() -= (sigmaEpochAcc(i)*sigmaAxisAcc(2)) * accCal(2);\n          }\n      }\n\n      // Accuracy & outlier detection (star camera)\n      // ------------------------------------------\n      {\n        std::vector<Vector> e(epochCount);\n        std::vector<Vector> redundancy(epochCount);\n        std::vector<Matrix> A(epochCount+1);\n        for(UInt i=0; i<epochCount; i++)\n          if(scaL.at(i).size())\n          {\n            // decorrelated residuals\n            e.at(i) = scaL.at(i);\n            matMult(-1, scaA.at(i), dx.row(normals.blockIndex(i), normals.blockSize(i)), e.at(i));\n\n            // redundancy\n            A.at(i) = scaA.at(i);\n            redundancy.at(i) = computeRedundancy(A, normals);\n            A.at(i) = Matrix();\n          } // for(i=epochCount)\n\n        estimateAccuracy(e, redundancy, perAxisSca, huber, huberPower, sigmaAxisSca, sigmaEpochSca);\n      }\n\n      // Accuracy & outlier detection (accelerometer)\n      // --------------------------------------------\n      {\n        std::vector<Vector> e(epochCount);\n        std::vector<Vector> redundancy(epochCount);\n        std::vector<Matrix> A(epochCount+1);\n        for(UInt i=0; i<epochCount; i++)\n          if(accL.at(i).size())\n          {\n            // decorrelated residuals\n            e.at(i) = accL.at(i);\n            for(UInt k=0; k<accA.at(i).size(); k++)\n              matMult(-1, accA.at(i).at(k), dx.row(normals.blockIndex(accIdxA.at(i)+k), normals.blockSize(accIdxA.at(i)+k)), e.at(i));\n            if(countAccCal)\n              matMult(-1., accB.at(i), dx.row(normals.blockIndex(idxBlockCal), normals.blockSize(idxBlockCal)), e.at(i));\n\n            // redundancy\n            for(UInt k=0; k<accA.at(i).size(); k++)\n              A.at(accIdxA.at(i)+k) = accA.at(i).at(k);\n            A.back() = accB.at(i);\n            redundancy.at(i) = computeRedundancy(A, normals);\n            for(UInt k=0; k<accA.at(i).size(); k++)\n              A.at(accIdxA.at(i)+k) = Matrix();\n          } // for(i=epochCount)\n\n        estimateAccuracy(e, redundancy, perAxisAcc, huber, huberPower, sigmaAxisAcc, sigmaEpochAcc);\n      }\n\n      // convergence criteria\n      // --------------------\n      if(fabs(sigma0-sigma0Old)<1e-5)\n        break;\n    } // for(iter)\n\n    //=================================\n\n    // full variance covariance matrix\n    Matrix C;\n    if(!fileNameOutCovariance.empty() || !fileNameOutCovarianceMatrix.empty())\n    {\n      C = Matrix(normals.blockIndex(blockCount), Matrix::TRIANGULAR, Matrix::UPPER);\n      for(UInt i=0; i<blockCount; i++)\n        for(UInt k=i; k<blockCount; k++)\n          if(normals.isBlockUsed(i, k))\n            copy(normals.N(i,k), C.slice(normals.blockIndex(i), normals.blockIndex(k), normals.blockSize(i), normals.blockSize(k)));\n      cholesky2Inverse(C);\n      C *= sigma0 * sigma0;\n    }\n\n    if(!fileNameOutCovarianceMatrix.empty())\n      writeFileMatrix(fileNameOutCovarianceMatrix.appendBaseName(\".arc\"+arcNo%\"%03i\"s), C.slice(0,0,3*epochCount,3*epochCount));\n\n    // Results\n    ArcObservation arc;\n    arc.sigmaSca = sigmaAxisSca;\n    arc.sigmaAcc = sigmaAxisAcc;\n    arc.x        = xAccCal;\n\n    // star camera arc\n    if(!fileNameOutStarCamera.empty())\n      for(UInt i=0; i<epochCount; i++)\n        if(hasAcc.at(i) || hasSca.at(i))\n        {\n          StarCameraEpoch epoch;\n          epoch.time   = times.at(i);\n          epoch.rotary = Rotary3d(q.row(i).trans());\n          arc.starCamera.push_back(epoch);\n        }\n\n    // star camera covariance arc\n    if(!fileNameOutCovariance.empty())\n    {\n      for(UInt i=0; i<epochCount; i++)\n        if(hasAcc.at(i) || hasSca.at(i))\n        {\n          Covariance3dEpoch epoch;\n          epoch.time       = times.at(i);\n          epoch.covariance = Tensor3d(C.slice(3*i,3*i,3,3));\n          arc.starCameraCovariance.push_back(epoch);\n        }\n    }\n\n    // angular acceleration observation (calibrated)\n    if(!fileNameOutAngularAcc.empty())\n    {\n      UInt idxAcc = 0;\n      for(UInt i=0; i<epochCount; i++)\n        if(index(times.at(i), timesAcc, idxAcc))\n          arc.angularAcc.push_back(angularAcc.at(idxAcc));\n    }\n\n    // star Camera epoch sigmas\n    if(!fileNameOutEpochSigmasStarCamera.empty())\n    {\n      for(UInt i=0; i<epochCount; i++)\n        if(hasSca.at(i))\n        {\n          MiscValueEpoch epoch;\n          epoch.time  = times.at(i);\n          epoch.value = sigmaEpochSca(i);\n          arc.epochSigmaSca.push_back(epoch);\n        }\n    }\n\n    // accelerometer epoch sigmas\n    if(!fileNameOutEpochSigmasAccelerometer.empty())\n    {\n      for(UInt i=0; i<epochCount; i++)\n        if(hasAcc.at(i))\n        {\n          MiscValueEpoch epoch;\n          epoch.time  = times.at(i);\n          epoch.value = sigmaEpochAcc(i);\n          arc.epochSigmaAcc.push_back(epoch);\n        }\n    }\n\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector InstrumentStarCameraAngularAccelerometerFusion::computeRedundancy(std::vector<Matrix> &A, MatrixDistributed &normals, Double threshold)\n{\n  try\n  {\n    Vector redundancy = {1., 1., 1.};\n    for(UInt i=0; i<normals.blockCount()-1; i++)\n      if(A.at(i).size())\n      {\n        triangularSolve(1., normals.N(i,i).trans(), A.at(i).trans());\n        for(UInt idAxis=0; idAxis<3; idAxis++)\n          redundancy(idAxis) -= quadsum(A.at(i).row(idAxis));\n        for(UInt k=i+1; k<normals.blockCount(); k++)\n          if(normals.isBlockUsed(i,k))\n          {\n            if(!A.at(k).size())\n              A.at(k) = Matrix(A.at(i).rows(), normals.blockSize(k));\n            matMult(-1., A.at(i), normals.N(i,k), A.at(k));\n          }\n        if(quadsum(A.at(i)) < threshold)\n          break;\n      }\n    if(normals.isBlockUsed(normals.blockCount()-1, normals.blockCount()-1) && A.back().size())\n    {\n      triangularSolve(1., normals.N(normals.blockCount()-1,normals.blockCount()-1).trans(), A.back().trans());\n      for(UInt idAxis=0; idAxis<3; idAxis++)\n        redundancy(idAxis) -= quadsum(A.back().row(idAxis));\n    }\n\n    return redundancy;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentStarCameraAngularAccelerometerFusion::estimateAccuracy(std::vector<Vector> &e, std::vector<Vector> &redundancy,\n                                                                      Bool sigmaPerAxis, Double huber, Double huberPower,\n                                                                      Vector &sigmaAxis, Vector &sigmaEpoch)\n{\n  try\n  {\n    // total accuracy\n    Double ePe_sum       = 0;\n    Double redundany_sum = 0;\n    for(UInt idAxis=0; idAxis<3; idAxis++)\n    {\n      for(UInt i=0; i<e.size(); i++)\n        if(redundancy.at(i).size() && (sigmaEpoch(i) <= 1))\n        {\n          ePe_sum       += std::pow(e.at(i)(idAxis)/sigmaEpoch(i), 2);\n          redundany_sum += redundancy.at(i)(idAxis);\n        }\n\n      if(sigmaPerAxis)\n      {\n        Double factor = Vce::standardDeviation(ePe_sum, redundany_sum, huber, huberPower);\n        for(UInt i=0; i<e.size(); i++)\n          if(redundancy.at(i).size())\n            e.at(i)(idAxis) *= 1./factor;\n        sigmaAxis(idAxis) *= factor;\n        ePe_sum = redundany_sum = 0;\n      }\n    }\n\n    if(!sigmaPerAxis)\n    {\n      Double factor = Vce::standardDeviation(ePe_sum, redundany_sum, huber, huberPower);\n      for(UInt i=0; i<e.size(); i++)\n        if(redundancy.at(i).size())\n          e.at(i) *= 1/factor;\n      for(UInt idAxis=0; idAxis<3; idAxis++)\n        sigmaAxis(idAxis) *= factor;\n    }\n\n    // Outlier detection\n    for(UInt i=0; i<e.size(); i++)\n      if(redundancy.at(i).size())\n      {\n        const Double s = sigmaEpoch(i)*std::sqrt(quadsum(e.at(i))/(3*mean(redundancy.at(i))));\n        sigmaEpoch(i) = 1;\n        if((s > huber) && (mean(redundancy.at(i))>1e-3))\n          sigmaEpoch(i) = std::pow(s/huber, huberPower);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2AbsoluteGravity.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2AbsoluteGravity.cpp\n*\n* @brief Absolute gravity values on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-10-29\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the absolute value of gravity $\\left\\lVert{\\M g}\\right\\rVert$\nof a \\configClass{gravityfield}{gravityfieldType} on a given \\configClass{grid}{gridType}.\nThe result is multiplicated with \\config{factor}.\nTo get the full gravity vector in a terrestrial frame add\nthe centrifugal part, see \\configClass{gravityfield:tides:centrifugal}{tidesType:centrifugal}.\n\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\nIt is intended to compute gravity anomalies from absolute gravity observations.\nTo visualize the results use \\program{PlotMap}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Absolute gravity values on a grid.\n* @ingroup programsGroup */\nclass Gravityfield2AbsoluteGravity\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2AbsoluteGravity, PARALLEL, \"Absolute gravity values on a grid.\", Gravityfield)\n\n/***********************************************/\n\nvoid Gravityfield2AbsoluteGravity::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          outFileNameGrid;\n    GridPtr           grid;\n    GravityfieldPtr   gravityfield;\n    Double            factor;\n    Time              time;\n    Double            a, f;\n\n    readConfig(config, \"outputfileGriddedData\", outFileNameGrid, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid\",                  grid,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"factor\",                factor,          Config::DEFAULT,   \"1.0\", \"the result is multiplied by this factor, set -1 to subtract the field\");\n    readConfig(config, \"time\",                  time,            Config::OPTIONAL,  \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"R\",                     a,               Config::DEFAULT,   STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,               Config::DEFAULT,   STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // create grid\n    // -----------\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n\n    // Create values on grid\n    // ---------------------\n    logStatus<<\"create values on grid\"<<Log::endl;\n    std::vector<Double> field(points.size());\n    Parallel::forEach(field, [&](UInt i){return factor*gravityfield->gravity(time, points.at(i)).r();}, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      // write results\n      // -------------\n      logStatus<<\"save values to file <\"<<outFileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a,f), points, areas, {field});\n      writeFileGriddedData(outFileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // Master\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2AreaMeanTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2AreaMeanTimeSeries.cpp\n*\n* @brief Generates a time series as mean values over an area from a time variable gravity field.\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-09-24\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes a time series of time variable\n\\configClass{gravityfield}{gravityfieldType} functionals averaged over a given area,\ne.g. equivalent water heights in the amazon basin.  The type of functional\n(e.g gravity anomalies or geoid heights) can be choosen with \\configClass{kernel}{kernelType}.\nThe average is performed at each time step by a weigthed average over all \\configClass{grid}{gridType}\npoints where the weight is the associated area at each point. If \\config{removeMean} is set\nthe temporal mean is removed from the time series. To speed up the computation\nthe gravity field can be converted to spherical harmonics before the computation\nwith \\config{convertToHarmonics}.\n\nAdditionally the root mean square of the values in the area at each time step\ncan is computed if \\config{compueRms} is set.\n\nAdditionally the accuracy of the value at each time step can be computed if \\config{compueSigma} is set.\n\nThe \\configFile{outputfileTimeSeries}{instrument} is an instrument file with one, two, or three data columns.\nFirst data column contains the computed functionals and the following columns contain the RMS and the accuracies (optionally).\n\nTo visualize the results use \\program{PlotGraph}.\n\n\\fig{!hb}{0.8}{gravityfield2AreaMeanTimeSeries}{fig:gravityfield2AreaMeanTimeSeries}{Amazon basin: Area mean values of ITSG-Grace2016 monthly solutions with error bars from computed sigma.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generates a time series as mean values over an area from a time variable gravity field.\n* @ingroup programsGroup */\nclass Gravityfield2AreaMeanTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2AreaMeanTimeSeries, PARALLEL, \"generates a time series as mean values over an area from a time variable gravity field\", Gravityfield, TimeSeries)\n\n/***********************************************/\n\nvoid Gravityfield2AreaMeanTimeSeries::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameOut;\n    GridPtr         grid;\n    TimeSeriesPtr   timeSeries;\n    KernelPtr       kernel;\n    GravityfieldPtr gravityfield;\n    Bool            convertToHarmonics, computeRms, computeSigma, removeMean, multiplyWithArea;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameOut,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid\",                 grid,               Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",               kernel,             Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",         gravityfield,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"convertToHarmonics\",   convertToHarmonics, Config::DEFAULT,  \"1\", \"gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation\");\n    readConfig(config, \"multiplyWithArea\",     multiplyWithArea,   Config::DEFAULT,  \"0\", \"multiply time series with total area (useful for mass estimates)\");\n    readConfig(config, \"removeMean\",           removeMean,         Config::DEFAULT,  \"0\", \"remove the temporal mean of the series\");\n    readConfig(config, \"computeRms\",           computeRms,         Config::DEFAULT,  \"0\", \"additional rms each time step\");\n    readConfig(config, \"computeSigma\",         computeSigma,       Config::DEFAULT,  \"0\", \"additional error bars at each time step\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time>     times  = timeSeries->times();\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n\n    // create grid\n    // -----------\n    Double totalArea = 0.0;\n    for(UInt k=0; k<areas.size(); k++)\n      totalArea += areas.at(k);\n\n    for(UInt k=0; k<areas.size(); k++)\n      areas.at(k) *= multiplyWithArea ? std::pow(points.at(k).r(), 2) : 1.0/totalArea;\n\n    logInfo<<\"  area:             \"<<totalArea/(4*PI)*100<<\"% of Earth's surface (\"<<totalArea*pow(DEFAULT_R/1000,2)<<\" km^2)\"<<Log::endl;\n    logInfo<<\"  number of points: \"<<points.size()<<Log::endl;\n\n    // Create values on grid\n    // ---------------------\n    const UInt count = times.size();\n    std::vector<Double> value(count);\n    std::vector<Double> rms(count, 0.);\n    std::vector<Double> sigma(count, 1.0);\n\n    // slow general case\n    // -----------------\n    if(!convertToHarmonics)\n    {\n      logStatus<<\"create gravity functionals\"<<Log::endl;\n      Parallel::forEach(value, [&](UInt i)\n      {\n        Double mean = 0;\n        for(UInt k=0; k<points.size(); k++)\n          mean += areas.at(k) * gravityfield->field(times.at(i), points.at(k), *kernel);\n        return mean;\n      }, comm);\n\n      if(computeRms)\n      {\n        logStatus<<\"compute RMS\"<<Log::endl;\n        Parallel::forEach(rms, [&](UInt i)\n        {\n          Double rms = 0;\n          for(UInt k=0; k<points.size(); k++)\n            rms += areas.at(k) * pow(gravityfield->field(times.at(i), points.at(k), *kernel),2);\n          return sqrt(rms);\n        }, comm);\n      }\n\n      if(computeSigma)\n      {\n        logStatus<<\"compute accuracy\"<<Log::endl;\n        Vector B = areas; // B = linear function from spherical harmonics to block mean\n        Parallel::forEach(sigma, [&](UInt i) {return sqrt(inner(B, gravityfield->variance(times.at(i), points, *kernel) * B));}, comm);\n      }\n    }\n\n    // fast spherical harmonics case\n    // -----------------------------\n    if(convertToHarmonics)\n    {\n      logStatus<<\"create gravity functionals\"<<Log::endl;\n      Vector B;\n      Parallel::forEach(value, [&](UInt i)\n      {\n        const SphericalHarmonics harm = gravityfield->sphericalHarmonics(times.at(i));\n        const Vector x = harm.x();\n        if(B.rows() < x.rows())\n          B = MiscGriddedData::synthesisSphericalHarmonicsMatrix(harm.maxDegree(), harm.GM(), harm.R(), points, kernel, harm.isInterior()).trans() * Vector(areas);\n        return inner(B.row(0, x.rows()), x);\n      }, comm);\n\n      if(computeRms)\n      {\n        logStatus<<\"compute RMS\"<<Log::endl;\n        Matrix B;\n        Parallel::forEach(rms, [&](UInt i)\n        {\n          const SphericalHarmonics harm = gravityfield->sphericalHarmonics(times.at(i));\n          const Vector x = harm.x();\n          if(B.columns()<x.rows())\n          {\n            B = MiscGriddedData::synthesisSphericalHarmonicsMatrix(harm.maxDegree(), harm.GM(), harm.R(), points, kernel, harm.isInterior());\n            for(UInt k=0; k<points.size(); k++)\n              B.row(k) *= std::sqrt(areas.at(k));\n          }\n          return std::sqrt(quadsum(B.column(0, x.rows()) * x));\n        }, comm);\n      }\n\n      if(computeSigma)\n      {\n        logStatus<<\"compute accuracy\"<<Log::endl;\nlogWarning<<\"Variance propagation from spherical harmonics to AMV may be not correct implemented. Set convertToHarmonics to FALSE.\"<<Log::endl;\n        Vector B;\n        Parallel::forEach(sigma, [&](UInt i)\n        {\n          const SphericalHarmonics harm = gravityfield->sphericalHarmonics(times.at(i));\n          const Matrix C = gravityfield->sphericalHarmonicsCovariance(times.at(i));\n          if(B.rows() < C.rows())\n            B = MiscGriddedData::synthesisSphericalHarmonicsMatrix(harm.maxDegree(), harm.GM(), harm.R(), points, kernel, harm.isInterior()).trans() * Vector(areas);\n          // full covariance matrix\n          if(C.getType() == Matrix::SYMMETRIC)\n            return sqrt(inner(B.row(0, C.rows()), C * B.row(0, C.rows())));\n          // only diagonal matrix\n          Double sum = 0;\n          for(UInt i=0; i<C.rows(); i++)\n            sum += B(i)*C(i,0)*B(i);\n          return sqrt(sum);\n        }, comm);\n      }\n    }\n\n    if(!Parallel::isMaster(comm)) return;\n\n    // remove (weigthed) temporal mean\n    // -------------------------------\n    if(removeMean)\n    {\n      logStatus<<\"remove mean\"<<Log::endl;\n      Double mean   = 0.0;\n      Double weight = 0.0;\n      for(UInt i=0; i<count; i++)\n      {\n        mean   += value.at(i)/pow(sigma.at(i),2);\n        weight += 1./pow(sigma.at(i),2);\n      }\n      mean /= weight;\n      for(UInt i=0; i<count; i++)\n        value.at(i) -= mean;\n    }\n\n    // sort into matrix\n    // ----------------\n    Matrix A(count, 2+computeRms+computeSigma);\n    for(UInt i=0; i<count; i++)\n    {\n      UInt idx = 0;\n      A(i, idx++) = times.at(i).mjd();\n      A(i, idx++) = value.at(i);\n      if(computeRms)\n        A(i, idx++) = rms.at(i);\n      if(computeSigma)\n        A(i, idx++) = sigma.at(i);\n    }\n\n    // write file\n    // ----------\n    if(!fileNameOut.empty())\n    {\n      logStatus<<\"write time series to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2Deflections.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2Deflections.cpp\n*\n* @brief Deflections of the vertical on a grid.\n*\n* @author Christian Pock\n* @date 2012-06-05\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the deflections of the vertical $\\xi$ in north direction\nand $\\eta$ in east direction in radian\naccording to\n\\begin{equation}\n\\xi = g_x/\\gamma \\qquad\\text{and}\\qquad \\eta=g_y/\\gamma,\n\\end{equation}\nwhere $\\M g=\\nabla V$ is the gravity vector from \\configClass{gravityfield}{gravityfieldType} in\nthe local ellipsoidal system (north, east, up) and $\\gamma$ is the normal gravity at that point.\n\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/planets.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Deflections of the vertical on a grid.\n* @ingroup programsGroup */\nclass Gravityfield2Deflections\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2Deflections, PARALLEL, \"Deflections of the vertical - based on gravity field\", Gravityfield)\n\n/***********************************************/\n\nvoid Gravityfield2Deflections::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          fileNameGrid;\n    GridPtr           grid;\n    GravityfieldPtr   gravityfield;\n    Time              time;\n    Double            a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,    Config::MUSTSET,  \"\", \"xi (north), eta (east) [rad]\");\n    readConfig(config, \"grid\",                  grid,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"time\",                  time,            Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"R\",                     a,               Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,               Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // create grid\n    // -----------\n    Ellipsoid ellipsoid(a,f);\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n\n    // Compute deflections\n    // ------------------\n    logStatus<<\"compute deflections of the vertical\"<<Log::endl;\n    std::vector<Vector3d> g(points.size());\n    Parallel::forEach(g, [&](UInt i)\n    {\n      return localNorthEastUp(points.at(i), ellipsoid).inverseTransform(gravityfield->gravity(time, points.at(i)))/Planets::normalGravity(points.at(i));\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      std::vector<std::vector<Double>> field(2, std::vector<Double>(points.size()));\n      for(UInt i=0; i<points.size(); i++)\n      {\n        field.at(0).at(i) = g.at(i).x();\n        field.at(1).at(i) = g.at(i).y();\n      }\n\n      logStatus<<\"save values <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a,f), points, areas, field);\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2DegreeAmplitudes.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2DegreeAmplitudes.cpp\n*\n* @brief Computes degree amplitudes of a gravity field.\n*\n* @author Andreas Kvas\n* @date 2020-01-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes degree amplitudes from a \\configClass{gravityfield}{gravityfieldType}\nand saves them to a \\file{matrix}{matrix} file with three columns: the degree, the degree amplitude, and the formal errors.\n\nThe coefficients can be converted to different functionals with \\configClass{kernel}{kernelType}.\nThe gravity field can be evaluated at different altitudes by specifying \\config{evaluationRadius}.\nPolar regions can be excluded by setting \\config{polarGap}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nSee also \\program{PotentialCoefficients2DegreeAmplitudes}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Computes degree amplitudes of a gravity field.\n* @ingroup programsGroup */\nclass Gravityfield2DegreeAmplitudes\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2DegreeAmplitudes, SINGLEPROCESS, \"computes degree amplitudes of a gravity field\", Gravityfield, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Gravityfield2DegreeAmplitudes::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    enum DegreeType {RMS, CUMMULATE, MEDIAN};\n    DegreeType      degreeType = RMS;\n    FileName        fileNameCoeff;\n    UInt            minDegree, maxDegree = INFINITYDEGREE;\n    Time            time;\n    Double          GM, R;\n    Double          evalRadius = NAN_EXPR;\n    GravityfieldPtr gravityfield;\n    KernelPtr       kernel;\n    Angle           gap;\n\n    readConfig(config, \"outputfileMatrix\", fileNameCoeff, Config::MUSTSET,  \"\", \"three column matrix with degree, signal amplitude, formal error\");\n    readConfig(config, \"gravityfield\",     gravityfield,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",           kernel,        Config::MUSTSET,  \"\", \"\");\n    std::string choice;\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"type of variances\"))\n    {\n      if(readConfigChoiceElement(config, \"rms\",          choice, \"degree amplitudes (square root of degree variances)\")) degreeType = RMS;\n      if(readConfigChoiceElement(config, \"accumulation\", choice, \"cumulate variances over degrees\"))                     degreeType = CUMMULATE;\n      if(readConfigChoiceElement(config, \"median\",       choice, \"median of absolute values per degree\"))                degreeType = MEDIAN;\n      endChoice(config);\n    }\n    readConfig(config, \"time\",             time,         Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"evaluationRadius\", evalRadius,   Config::OPTIONAL, \"\", \"evaluate the gravity field at this radius (default: evaluate at surface\");\n    readConfig(config, \"polarGap\",         gap,          Config::DEFAULT,  \"0.0\", \"exclude polar regions (aperture angle in degrees)\");\n    readConfig(config, \"minDegree\",        minDegree,    Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",        maxDegree,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",               GM,           Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                R,            Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    // Check input\n    // -----------\n    if(maxDegree<minDegree)\n      throw(Exception(\"Maximum degree lower than minimum degree (\" + maxDegree%\"%i\"s + \" vs. \" + minDegree%\"%i\"s + \").\"));\n\n    if(std::isnan(evalRadius)) evalRadius = R;\n\n    // Create potential coefficients\n    // -----------------------------\n    logStatus<<\"create spherical harmonics\"<<Log::endl;\n    SphericalHarmonics harm = gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n    maxDegree = harm.maxDegree();\n    const Vector kn     = kernel->inverseCoefficients(Vector3d(0, 0, evalRadius), maxDegree, harm.isInterior());\n    const Bool hasSigma = harm.sigma2cnm().size() || harm.sigma2snm().size();\n\n    auto vectorMedian = [](std::vector<Double> &data)\n    {\n      std::partial_sort(data.begin(), data.begin()+data.size()/2+1, data.end());\n      return (data.size()%2) ? data.at(data.size()/2) : (0.5*(data.at(data.size()/2-1)+data.at(data.size()/2)));\n    };\n\n    auto vectorAccumulate = [](std::vector<Double> &data)\n    {\n      std::for_each(data.begin(), data.end(), [](Double &v) { v = v*v; });\n      std::partial_sum(data.begin(), data.end(), data.begin());\n      std::for_each(data.begin(), data.end(), [](Double &v) { v = std::sqrt(v); });\n    };\n\n    std::vector<Double> x, y, sigma;\n    for(UInt n=0; n<=maxDegree; n++)\n    {\n      const UInt   minOrder   = static_cast<UInt>(gap*static_cast<Double>(n)+0.5); // Sneeuw\n      const Double areaFactor = (minOrder>0) ? ((2.*n+1.)/(2.*n+2.-2.*minOrder)) : (1.0);\n      const Double factor     = areaFactor * std::pow(harm.GM()/harm.R() * std::pow(harm.R()/evalRadius, n+1) * kn(n), 2);\n\n      std::vector<Double> coefficients, formalErrors;\n      for(UInt m=minOrder; m<=n; m++)\n      {\n        coefficients.push_back(factor * std::pow(harm.cnm()(n, m),2));\n        if(hasSigma) formalErrors.push_back(factor * harm.sigma2cnm()(n, m));\n        if(m > 0)\n        {\n          coefficients.push_back(factor * std::pow(harm.snm()(n, m),2));\n          if(hasSigma) formalErrors.push_back(factor * harm.sigma2snm()(n, m));\n        }\n      }\n\n      // degree variances\n      // ----------------\n      x.push_back(n);\n      if( (degreeType == RMS) || (degreeType == CUMMULATE) )\n      {\n        y.push_back( std::sqrt(std::accumulate(coefficients.begin(), coefficients.end(), 0.0)) );\n        if(hasSigma) sigma.push_back( std::sqrt(std::accumulate(formalErrors.begin(), formalErrors.end(), 0.0)) );\n      }\n      else if(degreeType == MEDIAN)\n      {\n        y.push_back( std::sqrt( (2*n+1) * vectorMedian(coefficients)) );\n        if(hasSigma) sigma.push_back( std::sqrt( (2*n+1) * vectorMedian(formalErrors)) );\n      }\n    } // for(n)\n\n    if(degreeType == CUMMULATE)\n    {\n      vectorAccumulate(y);\n      if(hasSigma) vectorAccumulate(sigma);\n    }\n\n    Matrix data(x.size(), 3, NAN_EXPR);\n    copy(Vector(x), data.column(0));\n    copy(Vector(y), data.column(1));\n    if(hasSigma) copy(Vector(sigma), data.column(2));\n\n    // write\n    // -----\n    logStatus<<\"write degree amplitudes to file <\"<<fileNameCoeff<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameCoeff, data);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2DegreeAmplitudesPlotGrid.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2DegreeAmplitudesPlotGrid.cpp\n*\n* @brief Time series of degree amplitudes from a time variable gravityfield.\n*\n* @author Torsten Mayer-Guerr\n* @date 2016-01-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes a \\configClass{timeSeries}{timeSeriesType}\nof a time variable \\configClass{gravityfield}{gravityfieldType} and saves it as degree amplitudes.\nThe expansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusivly\n\\begin{equation}\n  \\sigma_n = \\frac{GM}{R}\\left(\\frac{R}{r}\\right)^{n+1}k_n\\sqrt{\\sum_{m=0}^n c_{nm}^2+s_{nm}^2}.\n\\end{equation}\n\nThe \\configFile{outputfileTimeSeries}{matrix} is a matrix with\nevery row containing the time, degree, degree amplitude, and the formal error.\n\nTo visualize the results use \\program{PlotGraph}).\n\nSee also \\program{Gravityfield2DegreeAmplitudes}.\n\n\\fig{!hb}{0.5}{gravityfield2DegreeAmplitudesPlotGrid}{fig:gravityfield2DegreeAmplitudesPlotGrid}{Degree amplitudes of monthly ITSG-Grace2016 solutions relative to GOCO05s.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of degree amplitudes from a time variable gravityfield.\n* @ingroup programsGroup */\nclass Gravityfield2DegreeAmplitudesPlotGrid\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2DegreeAmplitudesPlotGrid, SINGLEPROCESS, \"Time series of degree amplitudes from a time variable gravityfield.\", Gravityfield, TimeSeries)\nGROOPS_RENAMED_PROGRAM(Gravityfield2DegreeAmplitudeTimeSeries, Gravityfield2DegreeAmplitudesPlotGrid, date2time(2020, 07, 21))\n\n/***********************************************/\n\nvoid Gravityfield2DegreeAmplitudesPlotGrid::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        outName;\n    FileName        outNameDegree;\n    GravityfieldPtr gravityfield;\n    KernelPtr       kernel;\n    TimeSeriesPtr   timeSeries;\n    Angle           gap;\n    UInt            minDegree, maxDegree;\n    Double          evalRadius = NAN_EXPR;\n    Double          GM, R;\n\n    readConfig(config, \"outputfileTimeSeries\", outName,      Config::MUSTSET,  \"\",   \"each row: mjd, degree, amplitude, formal error\");\n    readConfig(config, \"gravityfield\",         gravityfield, Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"kernel\",               kernel,       Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,   Config::MUSTSET,  \"\",   \"\");\n    readConfig(config, \"evaluationRadius\",     evalRadius,   Config::OPTIONAL, \"\",   \"evaluate the gravity field at this radius (default: evaluate at surface\");\n    readConfig(config, \"polarGap\",             gap,          Config::DEFAULT,  \"0.\", \"exclude polar regions (aperture angle in degrees)\");\n    readConfig(config, \"minDegree\",            minDegree,    Config::MUSTSET,  \"0\",  \"minimal degree\");\n    readConfig(config, \"maxDegree\",            maxDegree,    Config::MUSTSET,  \"\",   \"maximal degree\");\n    readConfig(config, \"GM\",                   GM,           Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                    R,            Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    if(std::isnan(evalRadius)) evalRadius = R;\n    const std::vector<Time> times = timeSeries->times();\n    const Vector kn = kernel->inverseCoefficients(Vector3d(0, 0, evalRadius), maxDegree);\n\n    // time series of degree amplituds as matrix\n    //------------------------------------------\n    Matrix A(times.size()*(maxDegree+1-minDegree), 4); // mjd, degree, amplitude, formal error\n    UInt idx = 0;\n    for(UInt i=0; i<times.size(); i++)\n    {\n      SphericalHarmonics harm = gravityfield->sphericalHarmonics(times.at(i), maxDegree, minDegree, GM, R);\n      for(UInt n=minDegree; n<=maxDegree; n++)\n      {\n        const UInt   minOrder   = static_cast<UInt>(gap*static_cast<Double>(n)+0.5); // Sneeuw\n        const Double areaFactor = (minOrder > 0) ? ((2.*n+1.)/(2.*n+2.-2.*minOrder)) : (1.0);\n        const Double factor     = areaFactor * std::pow(harm.GM()/harm.R() * std::pow(harm.R()/evalRadius, n+1) * kn(n), 2);\n\n        Double ampl = 0;\n        for(UInt m=minOrder; m<=n; m++)\n          ampl += factor * (std::pow(harm.cnm()(n,m), 2) + std::pow(harm.snm()(n,m), 2));\n\n        Double sigma = 0;\n        if(harm.sigma2cnm().size())\n          for(UInt m=minOrder; m<=n; m++)\n            sigma += factor * (harm.sigma2cnm()(n,m) + harm.sigma2snm()(n,m));\n\n        A(idx, 0) = times.at(i).mjd();\n        A(idx, 1) = n;\n        A(idx, 2) = std::sqrt(ampl);\n        A(idx, 3) = std::sqrt(sigma);\n        idx++;\n      }\n    }\n\n    // write file\n    //-----------\n    logStatus<<\"write time series of degree amplitudes to file <\"<<outName<<\">\"<<Log::endl;\n    writeFileMatrix(outName, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2DisplacementTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2DisplacementTimeSeries.cpp\n*\n* @brief Generates a time series of station displacements.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-11-01\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes a time series of displacements of a list of stations (\\configClass{grid}{gridType})\ndue to the effect of time variable loading masses. The displacement~$\\M u$ of a station is calculated according to\n\\begin{equation}\\label{eq:displacement}\n\\M u(\\M r) = \\frac{1}{\\gamma}\\sum_{n=0}^\\infty \\left[\\frac{h_n}{1+k_n}V_n(\\M r)\\,\\M e_{up}\n+ R\\frac{l_n}{1+k_n}\\left(\n \\frac{\\partial V_n(\\M r)}{\\partial \\M e_{north}}\\M e_{north}\n+\\frac{\\partial V_n(\\M r)}{\\partial \\M e_{east}} \\M e_{east}\\right)\\right],\n\\end{equation}\nwhere $\\gamma$ is the normal gravity, the load Love and Shida numbers $h_n,l_n$ are given by\n\\configFile{inputfileDeformationLoadLoveNumber}{matrix} and the load Love numbers $k_n$ are given by\n\\configFile{inputfilePotentialLoadLoveNumber}{matrix}. The $V_n$ are the spherical harmonics expansion of\nthe full time variable gravitational potential (potential of the loading mass + deformation potential):\n\\begin{equation}\nV(\\M r) = \\sum_{n=0}^\\infty V_n(\\M r).\n\\end{equation}\nDeformations due to Earth tide and due to polar tides are computed using the IERS conventions.\nEq.~\\eqref{eq:displacement} is not used in these cases.\n\nThe \\config{outputfileTimeSeries} is an \\file{instrument file}{instrument}, MISCVALUES.\nThe data columns contain the deformation of each station in $x,y,z$ in a global terrestrial\nreference frame or alternatively in a local elliposidal frame (north, east, up)\nif \\config{localReferenceFrame} is set.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/planets.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generates a time series of station displacements.\n* @ingroup programsGroup */\nclass Gravityfield2DisplacementTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2DisplacementTimeSeries, SINGLEPROCESS, \"generates a time series of station displacements\", Gravityfield, TimeSeries)\nGROOPS_RENAMED_PROGRAM(DisplacementTimeSeries, Gravityfield2DisplacementTimeSeries, date2time(2020, 2, 9))\n\n/***********************************************/\n\nvoid Gravityfield2DisplacementTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         outputName;\n    FileName         deformationName, potentialName;\n    GridPtr          grid;\n    TimeSeriesPtr    timeSeries;\n    GravityfieldPtr  gravityfield;\n    TidesPtr         tides;\n    EarthRotationPtr earthRotation;\n    EphemeridesPtr   ephemerides;\n    Bool             removeMean, useLocalFrame;\n\n    readConfig(config, \"outputfileTimeSeries\",               outputName,      Config::MUSTSET,  \"\", \"x,y,z [m] per station\");\n    readConfig(config, \"grid\",                               grid,            Config::MUSTSET,  \"\",  \"station list\");\n    readConfig(config, \"timeSeries\",                         timeSeries,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",                       gravityfield,    Config::DEFAULT,  \"\", \"\");\n    readConfig(config, \"tides\",                              tides,           Config::DEFAULT,  \"\", \"\");\n    readConfig(config, \"earthRotation\",                      earthRotation,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"ephemerides\",                        ephemerides,     Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"inputfileDeformationLoadLoveNumber\", deformationName, Config::MUSTSET,  \"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\", \"\");\n    readConfig(config, \"inputfilePotentialLoadLoveNumber\",   potentialName,   Config::OPTIONAL, \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"if full potential is given and not only loading potential\");\n    readConfig(config, \"removeMean\",                         removeMean,      Config::DEFAULT,  \"0\", \"remove the temporal mean of each coordinate\");\n    readConfig(config, \"localReferenceFrame\",                useLocalFrame,   Config::DEFAULT,  \"0\", \"local left handed reference frame (north, east, up)\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time>     times  = timeSeries->times();\n    std::vector<Vector3d> points = grid->points();\n\n    // deformation load love numbers\n    // -----------------------------\n    Matrix love;\n    readFileMatrix(deformationName, love);\n    Vector hn = love.column(0);\n    Vector ln = love.column(1);\n\n    // models contain the total mass (loading mass & deformation mass effect)\n    if(!potentialName.empty())\n    {\n      Vector kn;\n      readFileMatrix(potentialName, kn);\n      for(UInt n=2; n<std::min(kn.rows(), hn.rows()); n++)\n        hn(n) /= (1.+kn(n));\n      for(UInt n=2; n<std::min(kn.rows(), ln.rows()); n++)\n        ln(n) /= (1.+kn(n));\n    }\n\n    // normal gravity\n    // --------------\n    Vector gravity(points.size());\n    for(UInt i=0; i<points.size(); i++)\n      gravity(i) = Planets::normalGravity(points.at(i));\n\n    // Earth rotation\n    // --------------\n    logStatus<<\"Compute Earth rotation\"<<Log::endl;\n    std::vector<Rotary3d> rotEarth(times.size());\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      rotEarth.at(i) = earthRotation->rotaryMatrix(times.at(i));\n    });\n\n    // displacements\n    // -------------\n    logStatus<<\"compute station displacements\"<<Log::endl;\n    std::vector< std::vector<Vector3d> > disp(points.size());\n    for(UInt k=0; k<points.size(); k++)\n      disp.at(k).resize(times.size());\n    gravityfield->deformation(times, points, gravity, hn, ln, disp);\n    tides->deformation(times, points, rotEarth, earthRotation, ephemerides, gravity, hn, ln, disp);\n\n    // local frame\n    // -----------\n    if(useLocalFrame)\n    {\n      logStatus<<\"rotate into local left handed reference frame (north, east, up)\"<<Log::endl;\n      for(UInt k=0; k<points.size(); k++)\n      {\n        const Transform3d lnof2trf = localNorthEastUp(points.at(k));\n        for(UInt i=0; i<times.size(); i++)\n          disp.at(k).at(i) = lnof2trf.inverseTransform(disp.at(k).at(i));\n      }\n    }\n\n    // sort into matrix\n    // ----------------\n    Matrix A(times.size(), 1+3*points.size());\n    for(UInt i=0; i<times.size(); i++)\n    {\n      A(i,0) = times.at(i).mjd();\n      for(UInt k=0; k<points.size(); k++)\n      {\n        A(i,3*k+1) =  disp.at(k).at(i).x();\n        A(i,3*k+2) =  disp.at(k).at(i).y();\n        A(i,3*k+3) =  disp.at(k).at(i).z();\n      }\n    }\n\n    // remove temporal mean\n    // --------------------\n    if(removeMean)\n    {\n      logStatus<<\"remove mean\"<<Log::endl;\n      for(UInt k=1; k<A.columns(); k++)\n        A.column(k) -= mean(A.column(k));\n    }\n\n    // write file\n    // ----------\n    if(!outputName.empty())\n    {\n      logStatus<<\"write time series to file <\"<<outputName<<\">\"<<Log::endl;\n      InstrumentFile::write(outputName, Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2EmpiricalCovariance.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2EmpiricalCovariance.cpp\n*\n* @brief Estimate a empircal covariance function from time series.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-03-30\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates an spatial and temporal covariance matrix from\na time series of gravity fields.\n\nFirstly for every time step $t_i$\na spherical harmonics vector $\\M x_i$ from the time variable gravity field\nis generated. The coefficients of the spherical harmonics expansion are\nin the sequence given by \\configClass{numbering}{sphericalHarmonicsNumberingType}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The coefficients are related to the\nreference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nIn the next step the empirical covariance matrix is estimated according to\n\\begin{equation}\n\\M\\Sigma(\\Delta i)_{full} = \\frac{1}{N}\\sum_{i=1}^N \\M x_i \\M x_{i+\\Delta i}^T,\n\\end{equation}\nwhere $\\Delta i$ is given by \\config{differenceStep}.\n\nFrom the diagonal elements of $\\M\\Sigma(\\Delta i)$ the isotropic accuracies\nare computed\n\\begin{equation}\n\\sigma_n^2 = \\frac{1}{2n+1}\\sum_{m=0}^n \\sigma_{cnm}^2+\\sigma_{snm}^2,\n\\end{equation}\nand a diagonal matrix is constructed $\\Sigma_{iso} = \\text{diag}(\\sigma_2^2,\\ldots,\\sigma_N^2)$.\nThe result is computed:\n\\begin{equation}\n\\M\\Sigma(\\Delta i) = \\alpha_{full}\\M\\Sigma(\\Delta i)_{full}+\\alpha_{iso}\\M\\Sigma(\\Delta i)_{iso}.\n\\end{equation}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate a empircal covariance function from time series.\n* @ingroup programsGroup */\nclass Gravityfield2EmpiricalCovariance\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2EmpiricalCovariance, PARALLEL, \"Estimate a empircal covariance function from time series\", Gravityfield, Covariance)\n\n/***********************************************/\n\nvoid Gravityfield2EmpiricalCovariance::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        outputName, fileNamePotCoeff;\n    UInt            minDegree, maxDegree = INFINITYDEGREE;\n    Time            time;\n    Double          GM, R;\n    GravityfieldPtr gravityfield;\n    TimeSeriesPtr   timeSeriesPtr, timesIntervalPtr;\n    Bool            removeMean;\n    UInt            delay;\n    SphericalHarmonicsNumberingPtr numbering;\n    Double          factorFullMatrix, factorIsotropic;\n\n    readConfig(config, \"outputfileCovarianceMatrix\",      outputName,       Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"outputfilePotentialCoefficients\", fileNamePotCoeff, Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"gravityfield\",                    gravityfield,     Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"minDegree\",                       minDegree,        Config::DEFAULT,  \"2\",   \"\");\n    readConfig(config, \"maxDegree\",                       maxDegree,        Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"GM\",                              GM,               Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                               R,                Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",                       numbering,        Config::MUSTSET,  \"\",    \"numbering scheme for solution vector\");\n    readConfig(config, \"removeMean\",                      removeMean,       Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"timeSeries\",                      timeSeriesPtr,    Config::MUSTSET,  \"\",    \"sampling of the gravityfield\");\n    readConfig(config, \"differenceStep\",                  delay,            Config::DEFAULT,  \"0\",   \"choose dt for: x,i(t) - x,j(t+dt)\");\n    readConfig(config, \"factorFullMatrixPart\",            factorFullMatrix, Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"factorIsotropicPart\",             factorIsotropic,  Config::DEFAULT,  \"0.1\", \"\");\n    readConfig(config, \"intervals\",                       timesIntervalPtr, Config::DEFAULT,  \"\",    \"\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    // init time intervals\n    // -------------------\n    std::vector<Time> timeSeries = timeSeriesPtr->times();\n    std::vector<Time> timesInterval;\n    if(timesIntervalPtr)\n      timesInterval = timesIntervalPtr->times();\n    if(timesInterval.size()==0)\n    {\n      timesInterval.push_back(timeSeries.at(0));\n      timesInterval.push_back(timeSeries.back()+seconds2time(1));\n    }\n\n    // ============================\n\n    // numbering of covariance matrix\n    // ------------------------------\n    std::vector< std::vector<UInt> > idxC, idxS;\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    const UInt dim = numbering->parameterCount(maxDegree, minDegree);\n\n    logStatus<<\"estimate covariance covariance function in each interval\"<<Log::endl;\n    UInt   countTotal = 0;\n    Matrix CovFull(dim, dim);\n    Parallel::forEach(timesInterval.size()-1, [&](UInt idInterval)\n    {\n      // init time series\n      // ----------------\n      std::vector<Time> times;\n      for(UInt i=0; i<timeSeries.size(); i++)\n        if(timeSeries.at(i).isInInterval(timesInterval.at(idInterval), timesInterval.at(idInterval+1)))\n          times.push_back(timeSeries.at(i));\n\n      // create time series of potential coefficients\n      // --------------------------------------------\n      UInt count = times.size();\n      std::vector<SphericalHarmonics> harm(count);\n      for(UInt i=0; i<count; i++)\n      {\n        harm.at(i) = gravityfield->sphericalHarmonics(times.at(i), maxDegree, minDegree, GM, R);\n        maxDegree = harm.at(i).maxDegree();\n      }\n\n      // remove temporal mean\n      // --------------------\n      if(removeMean)\n      {\n        SphericalHarmonics harmMean;\n        for(UInt i=0; i<count; i++)\n          harmMean += harm.at(i);\n        harmMean *= 1./count;\n        for(UInt i=0; i<count; i++)\n          harm.at(i) -= harmMean;\n      }\n\n      // covariance function\n      // -------------------\n      count = harm.size()-delay;\n      for(UInt i=0; i<count; i++)\n      {\n        Matrix cnm1 = harm.at(i).cnm();\n        Matrix snm1 = harm.at(i).snm();\n        Matrix cnm2 = harm.at(i+delay).cnm();\n        Matrix snm2 = harm.at(i+delay).snm();\n        // sort coefficients into vectors\n        Vector x1(dim), x2(dim);\n        for(UInt n=0; n<=maxDegree; n++)\n        {\n          if(idxC[n][0]!=NULLINDEX) x1(idxC[n][0]) = cnm1(n,0);\n          if(idxC[n][0]!=NULLINDEX) x2(idxC[n][0]) = cnm2(n,0);\n          for(UInt m=1; m<=n; m++)\n          {\n            if(idxC[n][m]!=NULLINDEX)  x1(idxC[n][m]) = cnm1(n,m);\n            if(idxC[n][m]!=NULLINDEX)  x2(idxC[n][m]) = cnm2(n,m);\n            if(idxS[n][m]!=NULLINDEX)  x1(idxS[n][m]) = snm1(n,m);\n            if(idxS[n][m]!=NULLINDEX)  x2(idxS[n][m]) = snm2(n,m);\n          }\n        }\n\n        matMult(1., x1, x2.trans(), CovFull);\n      }\n\n      countTotal += count;\n      if(removeMean)\n        countTotal -= 1;\n    }, comm);\n\n    Parallel::reduceSum(CovFull,    0, comm);\n    Parallel::reduceSum(countTotal, 0, comm);\n    if(!Parallel::isMaster(comm))\n       return;\n\n    // ============================\n\n    if(delay==0)\n      CovFull.setType(Matrix::SYMMETRIC);\n    CovFull *= 1./countTotal;\n    Matrix Cov = CovFull;\n    Cov *= factorFullMatrix;\n\n    if(factorIsotropic!=0)\n    {\n      Vector kn(maxDegree+1);\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        if(idxC[n][0]!=NULLINDEX) kn(n) += CovFull(idxC[n][0],idxC[n][0]);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m]!=NULLINDEX) kn(n) += CovFull(idxC[n][m],idxC[n][m]);\n          if(idxS[n][m]!=NULLINDEX) kn(n) += CovFull(idxS[n][m],idxS[n][m]);\n        }\n      }\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        if(idxC[n][0]!=NULLINDEX) Cov(idxC[n][0],idxC[n][0]) += factorIsotropic * kn(n)/(2*n+1);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m]!=NULLINDEX) Cov(idxC[n][m],idxC[n][m]) += factorIsotropic * kn(n)/(2*n+1);\n          if(idxS[n][m]!=NULLINDEX) Cov(idxS[n][m],idxS[n][m]) += factorIsotropic * kn(n)/(2*n+1);\n        }\n      }\n    }\n\n    // ============================\n\n    // Write\n    // -----\n    logStatus << \"save covariance matrix to <\"<<outputName<<\">\"<< Log::endl;\n    if(delay == 0)\n      Cov.setType(Matrix::SYMMETRIC);\n    writeFileMatrix(outputName, Cov);\n\n    logInfo<<\"  number of fields     : \"<<countTotal<<Log::endl;\n    logInfo<<\"  minDegree            : \"<<minDegree<< Log::endl;\n    logInfo<<\"  maxDegree            : \"<<maxDegree<< Log::endl;\n    logInfo<<\"  size of state vector : \"<<dim<<Log::endl;\n    logInfo<<\"  number of unknowns   : \"<<dim*(dim+1)/2<<Log::endl;\n    logInfo<<\"  redundancy           : \"<<countTotal*2./(dim+1)<<Log::endl;\n\n    // Spherical Harmonics\n    // -------------------\n    if(!fileNamePotCoeff.empty())\n    {\n      logStatus<<\"save potential coefficients to <\"<<fileNamePotCoeff<<\">\"<< Log::endl;\n      Matrix cnm(maxDegree+1, Matrix::SYMMETRIC);\n      Matrix snm(maxDegree+1, Matrix::SYMMETRIC);\n      Matrix sigma2cnm(maxDegree+1, Matrix::SYMMETRIC);\n      Matrix sigma2snm(maxDegree+1, Matrix::SYMMETRIC);\n\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        if(idxC[n][0]!=NULLINDEX) cnm(n,0) = sqrt(Cov(idxC[n][0],idxC[n][0]));\n        if(idxC[n][0]!=NULLINDEX) sigma2cnm(n,0) = Cov(idxC[n][0],idxC[n][0]);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m]!=NULLINDEX) cnm(n,m) = sqrt(Cov(idxC[n][m],idxC[n][m]));\n          if(idxS[n][m]!=NULLINDEX) snm(n,m) = sqrt(Cov(idxS[n][m],idxS[n][m]));\n          if(idxC[n][m]!=NULLINDEX) sigma2cnm(n,m) = Cov(idxC[n][m],idxC[n][m]);\n          if(idxS[n][m]!=NULLINDEX) sigma2snm(n,m) = Cov(idxS[n][m],idxS[n][m]);\n        }\n      }\n\n      writeFileSphericalHarmonics(fileNamePotCoeff, SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm));\n    }\n\n    // Test for positive definite\n    // --------------------------\n    try\n    {\n      if(delay==0)\n        cholesky(Cov);\n    }\n    catch(std::exception &/*e*/)\n    {\n      logWarning<<\"covariance matrix is not positive definite!\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2Gradients.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2Gradients.cpp\n*\n* @brief Gradients on a grid.\n*\n* @author Daniel Rieser\n* @date 2015-05-11\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes gravity gradients from \\configClass{gravityfield}{gravityfieldType}\non a \\configClass{grid}{gridType} in a global terrestrial reference frame\nor alternatively in a local elliposidal frame (north, east, up) if \\config{localReferenceFrame} is set.\nIn \\configFile{outputfileGriddedData}{griddedData} the values $[Vxx, Vyy, Vzz, Vxy, Vxz, Vyz]$\nwill be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Deflections of the vertical on a grid.\n* @ingroup programsGroup */\nclass Gravityfield2Gradients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2Gradients, PARALLEL, \"Gradients from gravity field\", Gravityfield)\n\n/***********************************************/\n\nvoid Gravityfield2Gradients::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameGrid;\n    GridPtr         grid;\n    GravityfieldPtr gravityfield;\n    Time            time;\n    Bool            useLocalFrame;\n    Double          a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,   Config::MUSTSET,  \"\", \"Vxx Vyy Vzz Vxy Vxz Vyz\");\n    readConfig(config, \"grid\",                  grid,           Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"localReferenceFrame\",   useLocalFrame,  Config::OPTIONAL, \"0\", \"local left handed reference frame (north, east, up)\");\n    readConfig(config, \"time\",                  time,           Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"R\",                     a,              Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,              Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // create grid\n    // -----------\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    Ellipsoid ellipsoid(a,f);\n\n    // Compute gradients\n    // ------------------\n    logStatus<<\"compute gradients\"<<Log::endl;\n    std::vector<Tensor3d> gradients(points.size());\n    Parallel::forEach(gradients, [&](UInt i){return gravityfield->gravityGradient(time, points.at(i));}, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      // convert\n      // -------\n      std::vector<std::vector<Double>> field(6, std::vector<Double>(points.size()));\n      for(UInt i=0; i<points.size(); i++)\n      {\n        if(useLocalFrame)\n          gradients.at(i) = localNorthEastUp(points.at(i), ellipsoid).inverseTransform(gradients.at(i));\n        field.at(0).at(i) = gradients.at(i).xx();\n        field.at(1).at(i) = gradients.at(i).yy();\n        field.at(2).at(i) = gradients.at(i).zz();\n        field.at(3).at(i) = gradients.at(i).xy();\n        field.at(4).at(i) = gradients.at(i).xz();\n        field.at(5).at(i) = gradients.at(i).yz();\n      }\n\n      // write results\n      // -------------\n      logStatus<<\"save values <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(ellipsoid, points, areas, field);\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2GravityVector.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2GravityVector.cpp\n*\n* @brief Gravity vector on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2025-03-29\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes gravity vectors from \\configClass{gravityfield}{gravityfieldType}\non a \\configClass{grid}{gridType} in a global terrestrial reference frame\nor alternatively in a local elliposidal frame (north, east, up) if \\config{localReferenceFrame} is set.\nIn \\configFile{outputfileGriddedData}{griddedData} the values $[gx, gy, gz]$\nwill be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Gravity vector on a grid.\n* @ingroup programsGroup */\nclass Gravityfield2GravityVector\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2GravityVector, PARALLEL, \"Gravity vector from gravity field\", Gravityfield)\n\n/***********************************************/\n\nvoid Gravityfield2GravityVector::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameGrid;\n    GridPtr         grid;\n    GravityfieldPtr gravityfield;\n    Time            time;\n    Bool            useLocalFrame;\n    Double          a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,   Config::MUSTSET,  \"\", \"gx, gy, gz\");\n    readConfig(config, \"grid\",                  grid,           Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"localReferenceFrame\",   useLocalFrame,  Config::OPTIONAL, \"0\", \"local left handed reference frame (north, east, up)\");\n    readConfig(config, \"time\",                  time,           Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"R\",                     a,              Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,              Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // create grid\n    // -----------\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    Ellipsoid ellipsoid(a,f);\n\n    // Compute gravity\n    // ---------------\n    logStatus<<\"compute gravity\"<<Log::endl;\n    std::vector<Vector3d> gravity(points.size());\n    Parallel::forEach(gravity, [&](UInt i){return gravityfield->gravity(time, points.at(i));}, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      std::vector<std::vector<Double>> field(3, std::vector<Double>(points.size()));\n      for(UInt i=0; i<points.size(); i++)\n      {\n        if(useLocalFrame)\n          gravity.at(i) = localNorthEastUp(points.at(i), ellipsoid).inverseTransform(gravity.at(i));\n        field.at(0).at(i) = gravity.at(i).x();\n        field.at(1).at(i) = gravity.at(i).y();\n        field.at(2).at(i) = gravity.at(i).z();\n      }\n\n      // write results\n      // -------------\n      logStatus<<\"save values <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(ellipsoid, points, areas, field);\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2GridCovarianceMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2GridCovarianceMatrix.cpp\n*\n* @brief Covariance matrix of values of a gravity field on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-05-30\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program propagates the covariance matrix of a \\configClass{gravityfield}{gravityfieldType}\nevaluated at \\config{time} to a \\configClass{grid}{gridType}. The full variance-covariance matrix is computed\nand written to a \\file{matrix file}{matrix}:\n\\begin{equation}\n\\mathbf{\\Sigma}_\\mathbf{y} = \\mathbf{F}\\mathbf{\\Sigma}_\\mathbf{x}\\mathbf{F}^T\n\\end{equation}\nThe \\configClass{kernel}{kernelType} determines the quantity of the grid values, for example,\n\\configClass{kernel:waterHeight}{kernelType:waterHeight}.\n\nSee also \\program{GravityfieldCovariancesPropagation2GriddedData}, \\program{GravityfieldVariancesPropagation2GriddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Covariance matrix of values of a gravity field on a grid.\n* @ingroup programsGroup */\nclass Gravityfield2GridCovarianceMatrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2GridCovarianceMatrix, SINGLEPROCESS, \"Covariance matrix of values of a gravity field on a grid.\", Gravityfield)\n\n/***********************************************/\n\nvoid Gravityfield2GridCovarianceMatrix::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        outName;\n    GridPtr         grid;\n    GravityfieldPtr gravityfield;\n    KernelPtr       kernel;\n    Time            time;\n\n    readConfig(config, \"outputfileMatrix\",     outName,      Config::MUSTSET,  \"\", \"symmetric grid covariance matrix\");\n    readConfig(config, \"grid\",                 grid,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",               kernel,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",         gravityfield, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"time\",                 time,         Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    if(isCreateSchema(config)) return;\n\n    // Fcreate covariance matrix\n    // ------------------\n    logStatus<<\"create covariance matrix\"<<Log::endl;\n    Matrix C = gravityfield->variance(time, grid->points(), *kernel);\n\n    // write file\n    // ----------\n    logStatus<<\"write covariance matrix to file <\"<<outName<<\">\"<<Log::endl;\n    writeFileMatrix(outName, C);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2GriddedData.cpp\n*\n* @brief Values of a gravity field on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-03-19\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes values of a \\configClass{gravityfield}{gravityfieldType} on a given \\configClass{grid}{gridType}.\nThe type of value (e.g gravity anomalies or geoid heights) can be choosen with \\configClass{kernel}{kernelType}.\nIf a time is given the gravity field will be evaluated at this point of time otherwise only the static part will be used.\nThe values will be saved together with points expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nTo speed up the computation the gravity field can be converted to spherical harmonics before the computation\nwith \\config{convertToHarmonics}.\n\nTo visualize the results use \\program{PlotMap}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Values of a gravity field on a grid.\n* @ingroup programsGroup */\nclass Gravityfield2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2GriddedData, PARALLEL, \"values of a gravity field on a grid.\", Gravityfield, Grid, Covariance)\n\n/***********************************************/\n\nvoid Gravityfield2GriddedData::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          fileNameGrid;\n    GridPtr           grid;\n    KernelPtr         kernel;\n    GravityfieldPtr   gravityfield;\n    Time              time;\n    Double            a, f;\n    Bool              convertToHarmonics;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid\",                  grid,               Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",                kernel,             Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"convertToHarmonics\",    convertToHarmonics, Config::DEFAULT,   \"1\", \"gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation\");\n    readConfig(config, \"time\",                  time,               Config::OPTIONAL,  \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"R\",                     a,                  Config::DEFAULT,   STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,                  Config::DEFAULT,   STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // Create values on grid\n    // ---------------------\n    logStatus<<\"create values on grid\"<<Log::endl;\n    std::vector<Double> field(grid->points().size());\n    if(!convertToHarmonics) // All representations, all point distributions\n      Parallel::forEach(field, [&](UInt i){return gravityfield->field(time, grid->points().at(i), *kernel);}, comm);\n    else // fast version\n      field = MiscGriddedData::synthesisSphericalHarmonics(gravityfield->sphericalHarmonics(time), grid->points(), kernel, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a,f), grid->points(), grid->areas(), {field});\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2GriddedDataTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2GriddedDataTimeSeries.cpp\n*\n* @brief Time series of gridded gravity fields.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-07-20\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes values of a \\configClass{gravityfield}{gravityfieldType} on a given \\configClass{grid}{gridType}\nfor each time step of \\configClass{timeSeries}{timeSeriesType}.\nThe type of value (e.g gravity anomalies or geoid heights) can be choosen with \\configClass{kernel}{kernelType}.\nTo speed up the computation the gravity field can be converted to spherical harmonics before the computation\nwith \\config{convertToHarmonics}.\nThe \\configFile{outputfileTimeSeries}{instrument} is an instrument (MISCVALUES) file with a data column\nfor each grid point per epoch.\n\nThis program enables the use of all instrument programs like \\program{InstrumentFilter},\n\\program{InstrumentArcStatistics} or \\program{InstrumentDetrend} to analyze and manipulate time series of gridded data.\n\nSee also \\program{TimeSeries2GriddedData}, \\program{Gravityfield2GriddedData}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of gridded gravity fields.\n* @ingroup programsGroup */\nclass Gravityfield2GriddedDataTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2GriddedDataTimeSeries, PARALLEL, \"time series of gridded gravity fields.\", Gravityfield, Grid, TimeSeries)\n\n/***********************************************/\n\nvoid Gravityfield2GriddedDataTimeSeries::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameOut;\n    GridPtr         grid;\n    KernelPtr       kernel;\n    GravityfieldPtr gravityfield;\n    TimeSeriesPtr   timeSeries;\n    Bool            convertToHarmonics;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameOut,        Config::MUSTSET, \"\",  \"each epoch: data of grid points (MISCVALUES)\");\n    readConfig(config, \"grid\",                 grid,               Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"kernel\",               kernel,             Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"gravityfield\",         gravityfield,       Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"convertToHarmonics\",   convertToHarmonics, Config::DEFAULT, \"1\", \"gravityfield is converted to spherical harmonics before evaluation, may accelerate the computation\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET, \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    // create grid\n    // -----------\n    const std::vector<Vector3d> points = grid->points();\n    const std::vector<Double>   areas  = grid->areas();\n    const std::vector<Time>     times  = timeSeries->times();\n\n    // Create values on grid\n    // ---------------------\n    logStatus<<\"create values on grid for each time\"<<Log::endl;\n    Matrix A(times.size(), 1+points.size()); // one time column + data\n    Parallel::forEach(times.size(), [&](UInt i)\n    {\n      if(!convertToHarmonics) // All representations, all point distributions\n      {\n        for(UInt k=0; k<points.size(); k++)\n          A(i, 1+k) = gravityfield->field(times.at(i), points.at(k), *kernel);\n      }\n      else // fast version\n      {\n        std::vector<Double> field = MiscGriddedData::synthesisSphericalHarmonics(gravityfield->sphericalHarmonics(times.at(i)), points, kernel, Parallel::selfCommunicator(), FALSE/*timing*/);\n        copy(Vector(field).trans(), A.slice(i, 1, 1, field.size()));\n      }\n    }, comm);\n    Parallel::reduceSum(A, 0, comm);\n\n    // Write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write time series to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2PotentialCoefficients.cpp\n*\n* @brief Writes a gravity field to a file with potential coefficients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program evaluates a time variable \\configClass{gravityfield}{gravityfieldType}\nat a given \\config{time} and saves it as a \\file{spherical harmonics file}{potentialCoefficients}.\nIf set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Writes a gravity field to a file with potential coefficients.\n* @ingroup programsGroup */\nclass Gravityfield2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2PotentialCoefficients, SINGLEPROCESS, \"writes a gravity field to a file with potential coefficients\", Gravityfield, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Gravityfield2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        fileNameCoeff;\n    UInt            minDegree, maxDegree = INFINITYDEGREE;\n    Time            time;\n    Double          GM, R;\n    GravityfieldPtr gravityfield;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", fileNameCoeff, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"gravityfield\",                    gravityfield,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"minDegree\",                       minDegree,     Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",                       maxDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                              GM,            Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                               R,             Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"time\",                            time,          Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    if(isCreateSchema(config)) return;\n\n    // Create potential coefficients\n    // -----------------------------\n    logStatus<<\"create spherical harmonics\"<<Log::endl;\n    SphericalHarmonics harm = gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n\n    // write\n    // -----\n    logStatus<<\"writing potential coefficients to file <\"<<fileNameCoeff<<\">\"<<Log::endl;\n    writeFileSphericalHarmonics(fileNameCoeff, harm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2PotentialCoefficientsTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2PotentialCoefficientsTimeSeries.cpp\n*\n* @brief Time series of potential coefficients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-10-02\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes a \\configClass{timeSeries}{timeSeriesType}\nof a time variable \\configClass{gravityfield}{gravityfieldType}\nand converts to coefficients of a spherical harmonics expansion.\nThe expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThe \\configFile{outputfileTimeSeries}{instrument} contains the potential coefficients\nas data columns for each epoch in the sequence given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of potential coefficients.\n* @ingroup programsGroup */\nclass Gravityfield2PotentialCoefficientsTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2PotentialCoefficientsTimeSeries, SINGLEPROCESS, \"time series of potential coefficients\", Gravityfield, TimeSeries)\n\n/***********************************************/\n\nvoid Gravityfield2PotentialCoefficientsTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                       fileNameOut;\n    GravityfieldPtr                gravityfield;\n    TimeSeriesPtr                  timeSeries;\n    UInt                           minDegree, maxDegree;\n    Double                         GM, R;\n    SphericalHarmonicsNumberingPtr numbering;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameOut,  Config::MUSTSET, \"\",  \"instrument file (MISCVALUES)\");\n    readConfig(config, \"gravityfield\",         gravityfield, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,   Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"minDegree\",            minDegree,    Config::MUSTSET, \"0\", \"\");\n    readConfig(config, \"maxDegree\",            maxDegree,    Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"GM\",                   GM,           Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                    R,            Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",            numbering,    Config::MUSTSET, \"\",  \"numbering scheme\");\n    if(isCreateSchema(config)) return;\n\n    const std::vector<Time>        times = timeSeries->times();\n    std::vector<std::vector<UInt>> idxC, idxS;\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n\n    Matrix A(times.size(), 1+numbering->parameterCount(maxDegree, minDegree));\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      SphericalHarmonics harm = gravityfield->sphericalHarmonics(times.at(idEpoch), maxDegree, minDegree, GM, R);\n      for(UInt n=minDegree; n<=maxDegree; n++)\n      {\n        if(idxC[n][0]!=NULLINDEX) A(idEpoch, 1+idxC[n][0]) = harm.cnm()(n, 0);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m]!=NULLINDEX) A(idEpoch, 1+idxC[n][m]) = harm.cnm()(n, m);\n          if(idxS[n][m]!=NULLINDEX) A(idEpoch, 1+idxS[n][m]) = harm.snm()(n, m);\n        }\n      }\n    }\n\n    logStatus<<\"write time series of potential coefficients to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOut, Arc(times, A));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2SphericalHarmonicsVector.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2SphericalHarmonicsVector.cpp\n*\n* @brief Converts a gravity field to a solution vector with potential coeffcients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2002-05-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program evaluates a time variable \\configClass{gravityfield}{gravityfieldType} at a given \\config{time}\nand saves a \\file{vector}{matrix} with the coefficients of a spherical harmonics expansion in the sequence given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}.\nIf set the expansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusively.\nThe coefficients are related to the reference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nThis coefficients vector can be used as a approximate solution, see \\program{NormalsMultiplyAdd},\nor as pseudo oberservations for regularization,\nsee \\configClass{normalEquation:regularization}{normalEquationType:regularization}.\n\nFor back transformation use \\program{Gravityfield2PotentialCoefficients}\nwith \\configClass{gravityfield:fromParametrization}{gravityfieldType:fromParametrization}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts a gravity field to a solution vector with potential coeffcients.\n* @ingroup programsGroup */\nclass Gravityfield2SphericalHarmonicsVector\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2SphericalHarmonicsVector, SINGLEPROCESS, \"converts a gravity field to a solution vector with potential coeffcients\", Gravityfield, Matrix)\n\n/***********************************************/\n\nvoid Gravityfield2SphericalHarmonicsVector::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        outName;\n    UInt            startIndex;\n    Time            time;\n    Double          GM, R;\n    UInt            minDegree, maxDegree;\n    Bool            useSigma;\n    GravityfieldPtr gravityfield;\n    SphericalHarmonicsNumberingPtr numbering;\n\n    readConfig(config, \"outputfileVector\", outName,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"gravityfield\", gravityfield, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startIndex\",   startIndex,   Config::DEFAULT,  \"0\", \"start index to put the coefficients in the solution vector\");\n    readConfig(config, \"minDegree\",    minDegree,    Config::MUSTSET,  \"2\", \"\");\n    readConfig(config, \"maxDegree\",    maxDegree,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"GM\",           GM,           Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",            R,            Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",    numbering,    Config::MUSTSET,  \"\",  \"numbering scheme for solution vector\");\n    readConfig(config, \"time\",         time,         Config::OPTIONAL, \"\",  \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"useSigma\",     useSigma,     Config::DEFAULT,  \"0\", \"use formal errors instead of coefficients\");\n    if(isCreateSchema(config)) return;\n\n    // create potential coefficients\n    // -----------------------------\n    logStatus<<\"create spherical harmonics\"<<Log::endl;\n    SphericalHarmonics harm = gravityfield->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n\n    // Create vector\n    // -------------\n    logStatus<<\"sorting potential coefficients into vector\"<<Log::endl;\n    UInt rhsCount = 1; // right hand sides\n    std::vector< std::vector<UInt> > idxC, idxS;\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    UInt dim = numbering->parameterCount(maxDegree, minDegree) + startIndex;\n    Matrix x(dim,rhsCount);\n    logInfo<<\"dimension of the vector: \"<<dim<<Log::endl;\n\n    Matrix cnm = (useSigma) ? harm.sigma2cnm() : harm.cnm();\n    Matrix snm = (useSigma) ? harm.sigma2snm() : harm.snm();\n\n    for(UInt j=0; j<rhsCount; j++)\n      for(UInt n=minDegree; n<=maxDegree; n++)\n      {\n        if(idxC[n][0]!=NULLINDEX) x(idxC[n][0]+startIndex,j) = (useSigma) ? std::sqrt(cnm(n,0)) : cnm(n,0);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m]!=NULLINDEX) x(idxC[n][m]+startIndex,j) = (useSigma) ? std::sqrt(cnm(n,m)) : cnm(n,m);\n          if(idxS[n][m]!=NULLINDEX) x(idxS[n][m]+startIndex,j) = (useSigma) ? std::sqrt(snm(n,m)) : snm(n,m);\n        }\n      }\n\n    // Write\n    // -----\n    logStatus<<\"write vector to file <\"<<outName<<\">\"<<Log::endl;\n    writeFileMatrix(outName, x);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2TimeSplines.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2TimeSplines.cpp\n*\n* @brief Estimate splines in time domain from a time variable gravity field.\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-09-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates splines in time domain from a time variable gravity field\nand writes \\configFile{outputfileTimeSplines}{timeSplinesGravityField}.\nThe \\configClass{gravityfield}{gravityfieldType} is sampled at \\configClass{sampling}{timeSeriesType}, converted to potential coefficients\nin the range between \\config{minDegree} and \\config{maxDegree} inclusively.\nThe time series of spherical harmonics can be temporal filtered with \\configClass{temporalFilter}{digitalFilterType}.\n\nIn the next step temporal splines with \\config{splineDegree} and nodal points given\nat \\configClass{splineTimeSeries}{timeSeriesType} are adjusted to the time series in a least squares sense.\nThis is very fast for block means (splineDegree = 0) but for other splines a large systems of equations\nmust be solved. In the adjustment process the time series of gravity fields can be interpreted as samples\nat the given times or as continuous function with linear behaviour between sampled points (\\config{linearInterpolation}).\n\nTo combine a series of potential coefficients to a spline file with block means (splineDegree = 0)\nuse the fast \\program{PotentialCoefficients2BlockMeanTimeSplines} instead.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate splines in time domain from a time variable gravity field.\n* @ingroup programsGroup */\nclass Gravityfield2TimeSplines\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2TimeSplines, SINGLEPROCESS, \"Estimate splines in time domain from a time variable gravity field\", Gravityfield, TimeSplines)\n\n/***********************************************/\n\nvoid Gravityfield2TimeSplines::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         outputName;\n    UInt             minDegree, maxDegree = INFINITYDEGREE;\n    Time             time;\n    Double           GM, R;\n    GravityfieldPtr  gravityfield;\n    TimeSeriesPtr    timeSeriesSplines, timeSeriesObs;\n    Bool             removeMean, interpolateLinear;\n    UInt             splineDegree;\n    DigitalFilterPtr digitalFilter;\n\n    readConfig(config, \"outputfileTimeSplines\", outputName,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"temporalFilter\",        digitalFilter,     Config::OPTIONAL, \"\",  \"filter sampled gravity field in time\");\n    readConfig(config, \"minDegree\",             minDegree,         Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",             maxDegree,         Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                    GM,                Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                     R,                 Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"sampling\",              timeSeriesObs,     Config::MUSTSET,  \"\",  \"gravity field is sampled at these times\");\n    readConfig(config, \"removeMean\",            removeMean,        Config::DEFAULT,  \"0\", \"remove the temporal mean of the series before estimating the splines\");\n    readConfig(config, \"linearInterpolation\",   interpolateLinear, Config::DEFAULT,  \"0\", \"assume linear behavior between sampled points\");\n    readConfig(config, \"splineDegree\",          splineDegree,      Config::MUSTSET,  \"\",  \"degree of splines\");\n    readConfig(config, \"splineTimeSeries\",      timeSeriesSplines, Config::MUSTSET,  \"\",  \"nodal points of splines in time domain\");\n    if(isCreateSchema(config)) return;\n\n    // ============================================\n\n    // sample gravity field to create time series of potential coefficients\n    // --------------------------------------------------------------------\n    logStatus<<\"generate time series of potential coefficients\"<<Log::endl;\n    std::vector<Time> timesObs = timeSeriesObs->times();\n\n    SphericalHarmonics shc = gravityfield->sphericalHarmonics(timesObs.front(), maxDegree, minDegree, GM, R);\n    maxDegree = shc.maxDegree();\n    Matrix sample(timesObs.size(), (maxDegree+1)*(maxDegree+1));\n    Single::forEach(timesObs.size(), [&](UInt i)\n    {\n      copy(gravityfield->sphericalHarmonics(timesObs.at(i), maxDegree, minDegree, GM, R).x().trans(), sample.row(i));\n    });\n\n    // remove temporal mean\n    if(removeMean)\n    {\n      logStatus<<\"remove temporal mean\"<<Log::endl;\n      for(UInt k=0; k<sample.columns(); k++)\n        sample.column(k) -= mean(sample.column(k));\n    }\n\n    // filter time series\n    if(digitalFilter)\n    {\n      logStatus<<\"apply temporal filter\"<<Log::endl;\n      sample = digitalFilter->filter(sample);\n    }\n\n    // ============================================\n\n    // test time series\n    // ----------------\n    std::vector<Time> timesSplines = timeSeriesSplines->times();\n    const UInt nodeCount = timesSplines.size()-1+splineDegree;\n    if(timesSplines.size()<2)\n      throw(Exception(\"2 points in time must be given at least\"));\n\n    // result\n    // ------\n    Matrix x(nodeCount, sample.columns());\n\n    // Test special cases\n    // ------------------\n    if((splineDegree==0) && (!interpolateLinear)) // block mean time splines\n    {\n      UInt idxObs  = 0;\n      for(UInt i=0; i<nodeCount; i++)\n      {\n        UInt count = 0;\n        for(; (idxObs<timesObs.size()) && (timesObs.at(idxObs)<timesSplines.at(i+1)); idxObs++)\n        {\n          if(timesObs.at(idxObs)<timesSplines.at(i))\n            continue;\n          x.row(i) += sample.row(idxObs);\n          count++;\n        }\n        x.row(i) *= 1./count;\n      }\n    }\n    else if((splineDegree==0) && interpolateLinear) // block mean time splines\n    {\n      UInt idxObs  = 0;\n      for(UInt i=0; i<nodeCount; i++)\n      {\n        const Double T = (timesSplines.at(i+1)-timesSplines.at(i)).mjd();\n        for(; (idxObs+1<timesObs.size()) && (timesObs.at(idxObs)<timesSplines.at(i+1)); idxObs++)\n        {\n          const Double tau1    = (timesObs.at(idxObs)  -timesSplines.at(i)).mjd()/T;\n          const Double tau2    = (timesObs.at(idxObs+1)-timesSplines.at(i)).mjd()/T;\n          const Double dtau    = tau2-tau1;\n          const Double factor1 = 1./dtau * ((tau2*std::min(1.,tau2) - 0.5*pow(std::min(1.,tau2),2)) - (tau2*std::max(0.,tau1) - 0.5*pow(std::max(0.,tau1),2)));\n          const Double factor2 = 1./dtau * ((0.5*pow(std::min(1.,tau2),2) - tau1*std::min(1.,tau2)) - (0.5*pow(std::max(0.,tau1),2) - tau1*std::max(0.,tau1)));\n          x.row(i) += factor1 * sample.row(idxObs) + factor2 * sample.row(idxObs+1);\n        }\n      }\n    }\n    else if((splineDegree==1) && (timesObs.size() == timesSplines.size())) // linear splines -> sampling points == splines values\n    {\n      x = sample;\n    }\n    else // high order splines (general case)\n    {\n      // coefficients of splines polynomials phi_i(tau) = sum_n coeff_{i,n}*tau^n\n      // ------------------------------------------------------------------------\n      Matrix coeff(splineDegree+1, splineDegree+1);\n      switch(splineDegree)\n      {\n        case 0: // Blockmittel\n          coeff(0,0) = 1.0;\n          break;\n        case 1: // Linear\n          coeff(1,1) =  1.0;                   // t\n          coeff(0,1) = -1.0; coeff(0,0) = 1.0; // 1-t\n          break;\n        case 2: // Quadratic\n          coeff(2,2) =  0.5;                                       //  0.5*t^2\n          coeff(1,2) = -1.0; coeff(1,1) =  1.0; coeff(1,0) = 0.5;  // -1.0*t^2 + t + 0.5\n          coeff(0,2) =  0.5; coeff(0,1) = -1.0; coeff(0,0) = 0.5;  //  0.5*t^2 - t + 0.5\n          break;\n        case 3: // Cubic\n          coeff(3,3) = +1./6.;                                                                 // +1./6.*t^3\n          coeff(2,3) = -3./6.; coeff(2,2) = +3./6.; coeff(2,1) = +3./6.; coeff(2,0) = +1./6.;  // -3./6.*t^3 + 3./6.*t^2 + 3./6.*t + 1./6.;\n          coeff(1,3) = +3./6.; coeff(1,2) = -6./6.; coeff(1,1) = +0./6.; coeff(1,0) = +4./6.;  // +3./6.*t^3 - 6./6.*t^2 + 0./6.*t + 4./6.;\n          coeff(0,3) = -1./6.; coeff(0,2) = +3./6.; coeff(0,1) = -3./6.; coeff(0,0) = +1./6.;  // -1./6.*t^3 - 3./6.*t^2 - 3./6.*t + 1./6.;\n          break;\n        default:\n          throw(Exception(\"degree of spline not implemented\"));\n      }\n\n      logStatus<<\"least squares adjustment\"<<Log::endl;\n      logInfo<<\"  size of design matrix \"<<timesObs.size()<<\" x \"<<nodeCount<<\" = \"<<8.*timesObs.size()*nodeCount/1024./1024.<<\" MB\"<<Log::endl;\n      Matrix At(nodeCount, timesObs.size());  // transpose of design matrix\n      Matrix N(nodeCount, Matrix::SYMMETRIC); // normal matrix\n\n      if(!interpolateLinear)\n      {\n        UInt idxObs  = 0;\n        for(UInt i=0; i<timesSplines.size()-1; i++)\n        {\n          const Double T = (timesSplines.at(i+1)-timesSplines.at(i)).mjd();\n          for(; (idxObs<timesObs.size()) && (timesObs.at(idxObs)<timesSplines.at(i+1)); idxObs++)\n          {\n            if(timesObs.at(idxObs)<timesSplines.at(i))\n              continue;\n            const Double tau = (timesObs.at(idxObs)-timesSplines.at(i)).mjd()/T;\n            for(UInt k=0; k<=splineDegree; k++)\n              for(UInt n=0; n<=splineDegree; n++)\n                At(i+k, idxObs) += coeff(k,n) * std::pow(tau, n);\n\n            // normal matrix\n            for(UInt k1=0; k1<=splineDegree; k1++)\n              for(UInt k2=0; k2<=splineDegree; k2++)\n                N(i+k1, i+k2) += At(i+k1,idxObs) * At(i+k2,idxObs);\n          }\n        }\n      }\n      else\n      {\n        // interpolateLinear\n        UInt idxObs = 0;\n        for(UInt i=0; i<timesSplines.size()-1; i++)\n        {\n          const Double T = (timesSplines.at(i+1)-timesSplines.at(i)).mjd();\n          while((idxObs+1<timesObs.size()) && (timesObs.at(idxObs)<timesSplines.at(i+1)))\n          {\n            const Double tau1 = (timesObs.at(idxObs)  -timesSplines.at(i)).mjd()/T;\n            const Double tau2 = (timesObs.at(idxObs+1)-timesSplines.at(i)).mjd()/T;\n            const Double dtau = tau2-tau1;\n\n            // linear interpolation between sampling points\n            // and integration of the scalar product of the line and the basis functions phi=sum_n coeff_n*tau^n\n            for(UInt z=0; z<=splineDegree; z++)\n              for(UInt n=0; n<=splineDegree; n++)\n              {\n                At(i+z,idxObs)   += T/dtau * coeff(z,n) * ((tau2*pow(std::min(1.,tau2),n+1)/(n+1) - pow(std::min(1.,tau2),n+2)/(n+2)) - (tau2*pow(std::max(0.,tau1),n+1)/(n+1) - pow(std::max(0.,tau1),n+2)/(n+2)));\n                At(i+z,idxObs+1) += T/dtau * coeff(z,n) * ((pow(std::min(1.,tau2),n+2)/(n+2) - tau1*pow(std::min(1.,tau2),n+1)/(n+1)) - (pow(std::max(0.,tau1),n+2)/(n+2) - tau1*pow(std::max(0.,tau1),n+1)/(n+1)));\n              }\n\n            if(timesObs.at(idxObs+1)>timesSplines.at(i+1))\n              break;\n            idxObs++;\n          }\n\n          // normal matrix\n          // Integral of the product of the basis functions <phi_z, phi_s>\n          for(UInt z=0; z<=splineDegree; z++)\n            for(UInt s=0; s<=splineDegree; s++)\n              for(UInt n1=0; n1<=splineDegree; n1++)\n                for(UInt n2=0; n2<=splineDegree; n2++)\n                  N(i+z, i+s) += T/(n1+n2+1) * coeff(z,n1) * coeff(s,n2);\n        }\n      } // if(interpolateLinear)\n\n      // Solve the equation system\n      // -----------------------------\n      logStatus<<\"solve the equation system\"<<Log::endl;\n      solveInPlace(N, At);\n      x = At * sample;\n    } // if(splineDegree>0)\n\n    // ============================================\n\n    // sort into coefficient triangles\n    // -------------------------------\n    std::vector<Matrix> cnm(nodeCount, Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n    std::vector<Matrix> snm(nodeCount, Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER));\n    for(UInt i=0; i<nodeCount; i++)\n    {\n      UInt idx = 0;\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        cnm.at(i)(n,0) = x(i, idx++);\n        for(UInt m=1; m<=n; m++)\n        {\n          cnm.at(i)(n,m) = x(i, idx++);\n          snm.at(i)(n,m) = x(i, idx++);\n        }\n      }\n    }\n\n    // write time splines\n    // ------------------\n    logStatus<<\"write time splines to file <\"<<outputName<<\">\"<<Log::endl;\n    writeFileTimeSplinesGravityfield(outputName, GM, R, splineDegree, timesSplines, cnm, snm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfield2TrendPotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfield2TrendPotentialCoefficients.cpp\n*\n* @brief Estimate temporal parametrization (e.g. trend, annual).\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-07-24\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates \\configClass{parametrizationTemporal}{parametrizationTemporalType}\n(e.g. mean, trend, annual) from a time variable gravity field.\n\nIn a first step a time variable \\configClass{gravityfield}{gravityfieldType}\nis sampled at \\configClass{timeSeries}{timeSeriesType}\nand converted to coefficients of a spherical harmonics expansion.\nThe expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusively.\nThe coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThese coefficients serves as observations of\na \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares} to estimate\n\\configClass{parametrizationTemporal}{parametrizationTemporalType} parameters.\nFor each temporal parameter an\n\\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\nis generated.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate temporal parametrization (e.g. trend, annual).\n* @ingroup programsGroup */\nclass Gravityfield2TrendPotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Gravityfield2TrendPotentialCoefficients, SINGLEPROCESS, \"estimate temporal parametrization (e.g. trend, annual)\", Gravityfield)\n\n/***********************************************/\n\nvoid Gravityfield2TrendPotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName>      fileNamesOut;\n    GravityfieldPtr            gravityfield;\n    TimeSeriesPtr              timeSeries;\n    ParametrizationTemporalPtr temporal;\n    UInt                       minDegree, maxDegree = INFINITYDEGREE;\n    Double                     GM, R;\n    Double                     huber, huberPower;\n    UInt                       maxIter;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", fileNamesOut, Config::MUSTSET,  \"\",  \"for each temporal parameter\");\n    readConfig(config, \"gravityfield\",                    gravityfield, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"timeSeries\",                      timeSeries,   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"parametrizationTemporal\",         temporal,     Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"minDegree\",                       minDegree,    Config::MUSTSET,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",                       maxDegree,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                              GM,           Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                               R,            Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"huber\",                           huber,        Config::DEFAULT,  \"2.5\", \"for robust least squares\");\n    readConfig(config, \"huberPower\",                      huberPower,   Config::DEFAULT,  \"1.5\", \"for robust least squares\");\n    readConfig(config, \"huberMaxIteration\",               maxIter,      Config::DEFAULT,  \"15\",  \"(maximum) number of iterations for robust estimation\");\n    if(isCreateSchema(config)) return;\n\n    const std::vector<Time> times = timeSeries->times();\n\n    if(maxDegree == INFINITYDEGREE)\n      maxDegree = gravityfield->sphericalHarmonics(times.front()).maxDegree();\n\n    // sampling of gravity field (observation vectors)\n    Matrix L(times.size(), (maxDegree+1)*(maxDegree+1));\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      copy(gravityfield->sphericalHarmonics(times.at(idEpoch), maxDegree, minDegree, GM, R).x().trans(), L.row(idEpoch));\n\n    // design matrix\n    temporal->setInterval(times.front(), times.back()+medianSampling(times), TRUE);\n    Matrix A(times.size(), temporal->parameterCount());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      copy(temporal->factors(times.at(idEpoch)).trans(), A.row(idEpoch));\n\n    logStatus<<\"estimate \"<<temporal->parameterCount()<<\" temporal parameters from \"<<times.size()<<\" epochs\"<<Log::endl;\n    Vector sigma;\n    Matrix x = Vce::robustLeastSquares(A, L, 1, huber, huberPower, maxIter, sigma);\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      if(sigma(idEpoch) > 1)\n        logInfo<<\"  \"<<times.at(idEpoch).dateTimeStr()<<\" outlier with sigma = \"<<sigma(idEpoch)<<Log::endl;\n\n\n    for(UInt i=0; i<fileNamesOut.size(); i++)\n    {\n      logStatus<<\"write potential coefficients to file <\"<<fileNamesOut.at(i)<<\">\"<<Log::endl;\n      Matrix cnm(maxDegree+1, Matrix::SYMMETRIC, Matrix::LOWER);\n      Matrix snm(maxDegree+1, Matrix::SYMMETRIC, Matrix::LOWER);\n      UInt idx = 0;\n      for(UInt n=0; n<=maxDegree; n++)\n      {\n        cnm(n, 0) = x(i, idx++);\n        for(UInt m=1; m<=n; m++)\n        {\n          cnm(n, m) = x(i, idx++);\n          snm(n, m) = x(i, idx++);\n        }\n      }\n      writeFileSphericalHarmonics(fileNamesOut.at(i), SphericalHarmonics(GM, R, cnm, snm));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfieldCovariancesPropagation2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldCovariancesPropagation2GriddedData.cpp\n*\n* @brief Covariances of values of a gravity field on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-11-06\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the covariance between a source point given\nby longitude/latitude (\\config{L}, \\config{B}) and the points of a \\configClass{grid}{gridType}\nin terms of the functional given by \\configClass{kernel}{kernelType} from the variance-covariance\nmatrix of a \\configClass{gravityfield}{gravityfieldType} evaluated at \\config{time}.\n\nIf \\config{computeCorrelation} is set, the program returns the correlation according to\n\\begin{equation}\nr_{ij} = \\frac{\\sigma_{ij}}{\\sigma_i \\sigma_j}\n\\end{equation}\nin the range of [-1, 1] instead of the covariance.\n\nSee also \\program{Gravityfield2GridCovarianceMatrix}, \\program{GravityfieldVariancesPropagation2GriddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Covariances of values of a gravity field on a grid.\n* @ingroup programsGroup */\nclass GravityfieldCovariancesPropagation2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GravityfieldCovariancesPropagation2GriddedData, PARALLEL, \"covariances of values of a gravity field on a grid\", Gravityfield, Grid)\n\n/***********************************************/\n\nvoid GravityfieldCovariancesPropagation2GriddedData::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameGrid;\n    GridPtr         grid;\n    KernelPtr       kernel;\n    GravityfieldPtr gravityfield;\n    Time            time;\n    Angle           L, B;\n    Double          height;\n    Double          a, f;\n    Bool            calcCorrelation;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,    Config::MUSTSET,  \"\", \"gridded data file containing the covariance betwenn source point and grid points\");\n    readConfig(config, \"grid\",                  grid,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",                kernel,          Config::MUSTSET, \"\", \"functional\");\n    readConfig(config, \"gravityfield\",          gravityfield,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"time\",                  time,            Config::OPTIONAL, \"\",  \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"L\",                     L,               Config::DEFAULT,  \"0\", \"longitude of variance point\");\n    readConfig(config, \"B\",                     B,               Config::DEFAULT,  \"0\", \"latitude of variance point\");\n    readConfig(config, \"height\",                height,          Config::DEFAULT,  \"0\", \"ellipsoidal height of source point\");\n    readConfig(config, \"computeCorrelation\",    calcCorrelation, Config::DEFAULT,  \"0\", \"compute correlations instead of covariances\");\n    readConfig(config, \"R\",                     a,               Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,               Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // Create grid\n    // -----------\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    Vector3d              point0 = Ellipsoid(a,f)(L,B,height);\n\n    // Compute covariances\n    // -------------------\n    logStatus<<\"calculate covariances on grid\"<<Log::endl;\n    std::vector<Double> field(points.size());\n    Parallel::forEach(field, [&](UInt i) {return gravityfield->covariance(time, point0, points.at(i), *kernel);}, comm);\n\n    std::vector<Double> sigma(points.size());\n    if(calcCorrelation)\n    {\n      logStatus<<\"calculate standard deviations on grid\"<<Log::endl;\n      Parallel::forEach(sigma, [&](UInt i) {return sqrt(gravityfield->variance(time, points.at(i), *kernel));}, comm);\n    }\n\n    if(Parallel::isMaster(comm))\n    {\n      if(calcCorrelation)\n      {\n        Double sigma0 = std::sqrt(gravityfield->variance(time, point0, *kernel));\n        for(UInt i=0; i<field.size(); i++)\n          field.at(i) /= (sigma0*sigma.at(i));\n      }\n\n      logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a,f), points, areas, {field});\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfieldReplacePotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldReplacePotentialCoefficients.cpp\n*\n* @brief Replace single potential coefficients in a gravity field\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2015-11-17\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nReplaces single potential coefficients in a gravity field.\nBoth \\configClass{gravityfield}{gravityfieldType}\nand \\configClass{gravityfieldReplacement}{gravityfieldType} are evaluated\nat \\config{time} and converted to spherical harmonic coefficients.\nSingle \\config{coefficients} are then replaced in \\configClass{gravityfield}{gravityfieldType}\nby the values from \\configClass{gravityfieldReplacement}{gravityfieldType}\nand the result is written to \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\nfrom \\config{minDegree} to \\config{maxDegree},\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Replace single potential coefficients in a gravity field.\n* @ingroup programsGroup */\nclass GravityfieldReplacePotentialCoefficients\n{\npublic:\n  class Coeff\n  {\n  public:\n    Bool isCnm;\n    UInt degree, order;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GravityfieldReplacePotentialCoefficients, SINGLEPROCESS, \"Replace single potential coefficients in a gravity field\", Gravityfield)\nGROOPS_RENAMED_PROGRAM(GravityfieldReplaceC20, GravityfieldReplacePotentialCoefficients, date2time(2020, 5, 24))\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, GravityfieldReplacePotentialCoefficients::Coeff &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  std::string choice;\n  if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n    return FALSE;\n  if(readConfigChoiceElement(config, \"cnm\", choice, \"\"))\n  {\n    var.isCnm = TRUE;\n    readConfig(config, \"degree\", var.degree, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"order\",  var.order,  Config::MUSTSET, \"\", \"\");\n  }\n  if(readConfigChoiceElement(config, \"snm\", choice, \"\"))\n  {\n    var.isCnm = FALSE;\n    readConfig(config, \"degree\", var.degree, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"order\",  var.order,  Config::MUSTSET, \"\", \"\");\n  }\n  endChoice(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid GravityfieldReplacePotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName           fileNameCoeff;\n    GravityfieldPtr    gravityfield1, gravityfield2;\n    std::vector<Coeff> coefficients;\n    UInt               minDegree, maxDegree = INFINITYDEGREE;\n    Double             GM, R;\n    Time               time;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", fileNameCoeff, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"gravityfield\",                    gravityfield1, Config::MUSTSET,  \"\", \"single coefficients are replaced by the other gravityfield\");\n    readConfig(config, \"gravityfieldReplacement\",         gravityfield2, Config::MUSTSET,  \"\", \"contains the coefficients for replacement\");\n    readConfig(config, \"coefficients\",                    coefficients,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"minDegree\",                       minDegree,     Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",                       maxDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                              GM,            Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                               R,             Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"time\",                            time,          Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"create spherical harmonics\"<<Log::endl;\n    SphericalHarmonics harm1 = gravityfield1->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n    SphericalHarmonics harm2 = gravityfield2->sphericalHarmonics(time, maxDegree, minDegree, GM, R);\n\n    for(auto &coeff : coefficients)\n    {\n      if(coeff.isCnm)\n      {\n        harm1.cnm()(coeff.degree, coeff.order) = harm2.cnm()(coeff.degree, coeff.order);\n        if(harm1.sigma2cnm().size())\n          harm1.sigma2cnm()(coeff.degree, coeff.order) = 0;\n        if(harm1.sigma2cnm().size() && harm2.sigma2cnm().size())\n          harm1.sigma2cnm()(coeff.degree, coeff.order) = harm2.sigma2cnm()(coeff.degree, coeff.order);\n      }\n      else\n      {\n        harm1.snm()(coeff.degree, coeff.order) = harm2.snm()(coeff.degree, coeff.order);\n        if(harm1.sigma2snm().size())\n          harm1.sigma2snm()(coeff.degree, coeff.order) = 0;\n        if(harm1.sigma2snm().size() && harm2.sigma2snm().size())\n          harm1.sigma2snm()(coeff.degree, coeff.order) = harm2.sigma2snm()(coeff.degree, coeff.order);\n      }\n    }\n\n    logStatus<<\"writing potential coefficients to file <\"<<fileNameCoeff<<\">\"<<Log::endl;\n    writeFileSphericalHarmonics(fileNameCoeff, harm1);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/gravityfield/gravityfieldVariancesPropagation2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file gravityfieldVariancesPropagation2GriddedData.cpp\n*\n* @brief Standard deviations of values of a gravity field on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-11-06\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program propagates variance-covariance matrix of a \\configClass{gravityfield}{gravityfieldType}\nevaluated at \\config{time} to the points of a \\configClass{grid}{gridType} in terms of the functional\ngiven by \\configClass{kernel}{kernelType}.\nThe resulting \\file{outputfileGriddedData}{griddedData} contains the standard deviations of the grid\npoints.\n\nSee also \\program{Gravityfield2GridCovarianceMatrix}, \\program{GravityfieldCovariancesPropagation2GriddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Standard deviations of values of a gravity field on a grid.\n* @ingroup programsGroup */\nclass GravityfieldVariancesPropagation2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GravityfieldVariancesPropagation2GriddedData, PARALLEL, \"standard deviations of values of a gravity field on a grid\", Gravityfield, Grid, Covariance)\n\n/***********************************************/\n\nvoid GravityfieldVariancesPropagation2GriddedData::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameGrid;\n    GridPtr         grid;\n    KernelPtr       kernel;\n    GravityfieldPtr gravityfield;\n    Time            time;\n    Double          a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid, Config::MUSTSET,  \"\", \"standard deviation at each grid point\");\n    readConfig(config, \"grid\",                  grid,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"kernel\",                kernel,       Config::MUSTSET,  \"\", \"functional\");\n    readConfig(config, \"gravityfield\",          gravityfield, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"time\",                  time,         Config::OPTIONAL, \"\", \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"R\",                     a,            Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,            Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // Compute standard deviations\n    // ---------------------------\n    logStatus<<\"calculate standard deviations on grid\"<<Log::endl;\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    std::vector<Double>   field(points.size());\n    Parallel::forEach(field, [&](UInt i) {return sqrt(gravityfield->variance(time, points.at(i), *kernel));}, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a,f), points, areas, {field});\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    } // if(Parallel::isMaster(comm))\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2AreaMeanTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2AreaMeanTimeSeries.cpp\n*\n* @brief Generates a time series as mean values over an area from a list of grid files\n*\n* @author Andreas Kvas\n* @date 2017-04-12\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes a time series of area mean values\nin a basin represented by \\configClass{border}{borderType} from a sequence of grid files.\nIf a file is not found, the epoch is skipped. Per default\nthe weighted average of all points in the given border is computed where the points are weighted by their area element.\n\nIf \\config{computeMean} is set, the time average of each grid points is subtracted before the computation.\nIf \\config{multiplyWithArea} is set, the weighted average is multiplied with the total basin area.\nThis is useful for computing the total mass in the basin.\n\nThe \\configFile{outputfileTimeSeries}{instrument} is an instrument file, where the first columns are the\nmean value each data column in the grid files, followed by the the weighted RMS\nfor each data column in the grid files if \\config{computeRms} is set.\nIf the number of data columns differs between the grid files, the remaining columns are padded with zeros.\n\nSee also \\program{Gravityfield2AreaMeanTimeSeries}.\n)\";\n\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/border/border.h\"\n\n\n/***** CLASS ***********************************/\n\n/** @brief Generates a time series as mean values over an area from a list of grid files.\n* @ingroup programsGroup */\nclass GriddedData2AreaMeanTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2AreaMeanTimeSeries, SINGLEPROCESS, \"generates a time series as mean values over an area from a list of grid files\", Grid, TimeSeries)\n\n/***********************************************/\n\nvoid GriddedData2AreaMeanTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        outputName;\n    std::vector<FileName> inputName;\n    BorderPtr       border;\n    TimeSeriesPtr   timeSeries;\n    Bool            computeRms, removeMean, multiplyWithArea;\n\n    readConfig(config, \"outputfileTimeSeries\", outputName,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileGriddedData\", inputName ,         Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"border\",               border,             Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"multiplyWithArea\",     multiplyWithArea,   Config::DEFAULT,  \"0\", \"multiply time series with total area (useful for mass estimates)\");\n    readConfig(config, \"removeMean\",           removeMean,         Config::DEFAULT,  \"0\", \"remove the temporal mean of the series\");\n    readConfig(config, \"computeRms\",           computeRms,         Config::DEFAULT,  \"0\", \"additional rms each time step\");\n    if(isCreateSchema(config)) return;\n\n    const UInt fileCount = inputName.size();\n    std::vector<Time> times  = timeSeries->times();\n    if(times.size() != fileCount)\n      throw(Exception(\"Number of input files and epochs do not match (\" + fileCount%\"%d\"s + \" vs. \" + times.size()%\"%d\"s + \").\"));\n\n    std::vector<Vector> values;\n    std::vector<Vector> rms;\n    std::vector<Time> gridTimes;\n    UInt maxDataFields = 0;\n    Single::forEach(times.size(), [&](UInt k)\n    {\n      GriddedData grid;\n      try\n      {\n        readFileGriddedData(inputName.at(k), grid);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<Log::endl;\n        return;\n      }\n\n      maxDataFields = std::max(maxDataFields, grid.values.size());\n      values.push_back(Vector(grid.values.size()));\n      rms.push_back(Vector(grid.values.size()));\n      gridTimes.push_back(times.at(k));\n\n      // find all points in border\n      std::vector<UInt> pointIndex;\n      for(UInt i = 0; i<grid.points.size(); i++)\n        if(border->isInnerPoint(grid.points.at(i), grid.ellipsoid))\n          pointIndex.push_back(i);\n\n      // compute total area\n      Double totalArea = 0.0;\n      for( UInt i : pointIndex )\n        totalArea += grid.areas.at(i);\n\n      // iterate over values\n      for(UInt i : pointIndex)\n      {\n        Double factor = multiplyWithArea ? std::pow(grid.points.at(i).r(), 2) : 1.0/totalArea;\n\n        // compute area mean\n        Vector data(grid.values.size());\n        for(UInt j = 0; j < data.size(); j++)\n          data(j) = grid.values.at(j).at(i);\n\n        axpy(grid.areas.at(i) * factor, data, values.back());\n\n        // compute RMS\n        if(computeRms)\n        {\n          Vector tmpRms(grid.values.size());\n          for(UInt j = 0; j < tmpRms.size(); j++)\n            tmpRms(j) = std::pow(grid.values.at(j).at(i), 2);\n\n          axpy(grid.areas.at(i) * factor, tmpRms, rms.back());\n        }\n      }\n    });\n\n    // write file\n    // ----------\n    const UInt countDataFields = computeRms ? 2*maxDataFields+1 : maxDataFields + 1;\n    Matrix A(values.size(), countDataFields);\n    for(UInt k = 0; k<values.size(); k++)\n    {\n      A(k, 0) = gridTimes.at(k).mjd();\n      copy(values.at(k).trans(), A.slice(k, 1, 1, values.at(k).size()));\n    }\n    if(removeMean)\n    {\n      logStatus<<\"remove mean of time series\"<<Log::endl;\n      Vector meanValue(maxDataFields);\n      for(UInt k = 0; k<values.size(); k++)\n        axpy(1.0/static_cast<Double>(values.size()), A.slice(k, 1, 1, maxDataFields).trans(), meanValue);\n\n      for(UInt k = 0; k<values.size(); k++)\n        axpy(-1.0,  meanValue.trans(), A.slice(k, 1, 1, maxDataFields));\n    }\n    if(computeRms)\n    {\n      for(UInt k = 0; k < rms.size(); k++)\n        for(UInt j = 0; j<rms.at(k).size(); j++)\n          A(k, maxDataFields+1+j) = std::sqrt(rms.at(k)(j));\n    }\n\n    logStatus<<\"write time series to file <\"<<outputName<<\">\"<<Log::endl;\n    InstrumentFile::write(outputName, Arc(A));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2GriddedDataStatistics.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2GriddedDataStatistics.cpp\n*\n* @brief Assign gridded data to grid points.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-07-03\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program assigns values \\configFile{inputfileGriddedData}{griddedData} to the nearest points\nof a new \\configClass{grid}{gridType}. If some of the new points are not filled in with data\n\\config{emptyValue} is used instead. If multiple points of the input fall on the same node\nthe result can be selected with \\config{statistics} (e.g. mean, root mean square, min, max, \\ldots).\nIt also is possible to simply count the number of data points that were assigned to each point.\n\nBe aware in case borders are given within \\configClass{grid}{gridType}, the \\configFile{outputfileGriddedData}{griddedData} will have points excluded before the assignement of old points to the new points.\nThe data from \\configFile{inputfileGriddedData}{griddedData} will not be limited by the given borders! See \\reference{GriddedDataConcatenate}{GriddedDataConcatenate} to limit the\n\\configFile{inputfileGriddedData}{griddedData} to given borders.\n\n\\fig{!hb}{0.8}{griddedData2GriddedDataStatistics}{fig:griddedData2GriddedDataStatistics}{Assignement of irregular distributed data to grid.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Assign gridded data to grid points.\n* @ingroup programsGroup */\nclass GriddedData2GriddedDataStatistics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2GriddedDataStatistics, SINGLEPROCESS, \"Assign gridded data to grid points\", Grid)\n\n/***********************************************/\n\nvoid GriddedData2GriddedDataStatistics::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    enum Type {MEAN, WMEAN, RMS, WRMS, STD, WSTD, SUM, MIN, MAX, COUNT, FIRST, LAST};\n    Type        type = MEAN;\n    FileName    fileNameOutGrid, fileNameInGrid;\n    GridPtr     gridPtr;\n    Double      emptyValue = NAN_EXPR;\n    Double      a, f;\n    std::string choice;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOutGrid, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileGriddedData\",  fileNameInGrid,  Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"grid\",                  gridPtr,         Config::MUSTSET,  \"\",    \"\");\n    if(readConfigChoice(config, \"statistic\", choice, Config::MUSTSET, \"\", \"statistic used if multiple values fall on the same cell\"))\n    {\n      if(readConfigChoiceElement(config, \"mean\",  choice, \"mean\"))                             type = MEAN;\n      if(readConfigChoiceElement(config, \"wmean\", choice, \"area weighted mean\"))               type = WMEAN;\n      if(readConfigChoiceElement(config, \"rms\",   choice, \"root mean square\"))                 type = RMS;\n      if(readConfigChoiceElement(config, \"wrms\",  choice, \"area weighted root mean square\"))   type = WRMS;\n      if(readConfigChoiceElement(config, \"std\",   choice, \"standard deviation\"))               type = STD;\n      if(readConfigChoiceElement(config, \"wstd\",  choice, \"area weighted standard deviation\")) type = WSTD;\n      if(readConfigChoiceElement(config, \"sum\",   choice, \"sum\"))                              type = SUM;\n      if(readConfigChoiceElement(config, \"min\",   choice, \"minimum value\"))                    type = MIN;\n      if(readConfigChoiceElement(config, \"max\",   choice, \"maximum value\"))                    type = MAX;\n      if(readConfigChoiceElement(config, \"count\", choice, \"number of values\"))                 type = COUNT;\n      if(readConfigChoiceElement(config, \"first\", choice, \"first value\"))                      type = FIRST;\n      if(readConfigChoiceElement(config, \"last\",  choice, \"last value\"))                       type = LAST;\n    }\n    endChoice(config);\n    readConfig(config, \"emptyValue\",        emptyValue, Config::DEFAULT, \"nan()\", \"value for nodes without data\");\n    readConfig(config, \"R\",                 a,          Config::DEFAULT, STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\", f,          Config::DEFAULT, STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // read grid\n    // ---------\n    logStatus<<\"read grid from file <\"<<fileNameInGrid<<\">\"<<Log::endl;\n    GriddedData grid;\n    readFileGriddedData(fileNameInGrid, grid);\n    MiscGriddedData::printStatistics(grid);\n    if((grid.areas.size() == 0) && ((type == WMEAN) || (type == WRMS) || (type == WSTD)))\n      throw(Exception(\"no area elements\"));\n\n    // Create grid\n    // -----------\n    logStatus<<\"create new grid\"<<Log::endl;\n    GriddedData gridNew(Ellipsoid(a, f), gridPtr->points(), gridPtr->areas(), {});\n    Double initialValue = 0;\n    if(type == MIN) initialValue =  1e99;\n    if(type == MAX) initialValue = -1e99;\n    gridNew.values.resize(grid.values.size(), std::vector<Double>(gridNew.points.size(), initialValue));\n\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius;\n    const Bool isRectangle = gridNew.isRectangle(lambda, phi, radius);\n\n    // additional variables\n    std::vector<std::vector<Double>> count, wmean, weight;\n    count.resize(gridNew.values.size(), std::vector<Double>(gridNew.points.size(), 0));\n    if((type == STD) || (type == WSTD))\n      wmean.resize(gridNew.values.size(), std::vector<Double>(gridNew.points.size(), 0));\n    if((type == WMEAN) || (type == WRMS) || (type == WSTD))\n      weight.resize(gridNew.values.size(), std::vector<Double>(gridNew.points.size(), 0));\n\n    // Assign grid\n    // -----------\n    logStatus<<\"assign grid\"<<Log::endl;\n    Single::forEach(grid.points.size(), [&](UInt i)\n    {\n      // find nearest neighbor\n      UInt idx = 0;\n      if(isRectangle)\n      {\n        const Angle lon = grid.points.at(i).lambda();\n        const Angle lat = grid.points.at(i).phi();\n        const UInt  col = std::distance(lambda.begin(), std::min_element(lambda.begin(), lambda.end(),\n                                        [&](Angle lon1, Angle lon2) {return std::fabs(std::remainder(lon-lon1, 2*PI)) < std::fabs(std::remainder(lon-lon2, 2*PI));}));\n        const UInt  row = std::distance(phi.begin(), std::min_element(phi.begin(), phi.end(),\n                                        [&](Angle lat1, Angle lat2) {return std::fabs(lat-lat1) < std::fabs(lat-lat2);}));\n        idx = row * lambda.size() + col;\n      }\n      else\n      {\n        Double minDistance = std::numeric_limits<Double>::max();\n        for(UInt k=0; k<gridNew.points.size(); k++)\n        {\n          const Double distance = (gridNew.points[k] - grid.points[i]).r();\n          if(distance < minDistance)\n          {\n            minDistance = distance;\n            idx = k;\n          }\n        }\n      }\n      Double w = 1;\n      if((type == WMEAN) || (type == WRMS) || (type == WSTD))\n        w = grid.areas.at(i);\n\n      for(UInt k=0; k<grid.values.size(); k++)\n      {\n        const Double v = grid.values.at(k).at(i);\n        if(std::isnan(v))\n          continue;\n\n        if(count.size())  count.at(k).at(idx)++;\n        if(weight.size()) weight.at(k).at(idx) += w;\n        if(wmean.size())  wmean.at(k).at(idx)  += w*v;\n\n        switch(type)\n        {\n          case MEAN:\n          case WMEAN:\n          case SUM:   gridNew.values.at(k).at(idx) += w*v;   break;\n          case RMS:\n          case WRMS:\n          case STD:\n          case WSTD:  gridNew.values.at(k).at(idx) += w*v*v; break;\n          case MIN:   gridNew.values.at(k).at(idx)  = std::min(v, gridNew.values.at(k).at(idx)); break;\n          case MAX:   gridNew.values.at(k).at(idx)  = std::max(v, gridNew.values.at(k).at(idx)); break;\n          case LAST:  gridNew.values.at(k).at(idx)  = v  ; break;\n          case FIRST: if(count.at(k).at(idx) == 1) gridNew.values.at(k).at(idx) = v; break;\n          default: ;\n        }\n      }\n    });\n\n    // post computation\n    // ----------------\n    for(UInt k=0; k<gridNew.values.size(); k++)\n      for(UInt idx=0; idx<gridNew.values.at(k).size(); idx++)\n        if(count.at(k).at(idx))\n        {\n          switch(type)\n          {\n            case MEAN:  gridNew.values.at(k).at(idx) /= count.at(k).at(idx);  break;\n            case WMEAN: gridNew.values.at(k).at(idx) /= weight.at(k).at(idx); break;\n            case RMS:   gridNew.values.at(k).at(idx) = std::sqrt(gridNew.values.at(k).at(idx)/count.at(k).at(idx));  break;\n            case WRMS:  gridNew.values.at(k).at(idx) = std::sqrt(gridNew.values.at(k).at(idx)/weight.at(k).at(idx)); break;\n            case STD:   wmean.at(k).at(idx) /= count.at(k).at(idx);\n                        gridNew.values.at(k).at(idx) = std::sqrt(count.at(k).at(idx)/(count.at(k).at(idx)-1.)*(gridNew.values.at(k).at(idx)/count.at(k).at(idx)-std::pow(wmean.at(k).at(idx), 2))); break;\n            case WSTD:  wmean.at(k).at(idx) /= weight.at(k).at(idx);\n                        gridNew.values.at(k).at(idx) = std::sqrt(count.at(k).at(idx)/(count.at(k).at(idx)-1.)*(gridNew.values.at(k).at(idx)/weight.at(k).at(idx)-std::pow(wmean.at(k).at(idx), 2))); break;\n            case COUNT: gridNew.values.at(k).at(idx) = count.at(k).at(idx); break;\n            default: ;\n          }\n        }\n        else\n          gridNew.values.at(k).at(idx) = emptyValue;\n\n    // Output\n    // ------\n    logStatus<<\"write grid to file <\"<<fileNameOutGrid<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOutGrid, gridNew);\n    MiscGriddedData::printStatistics(gridNew);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2GriddedDataTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2GriddedDataTimeSeries.cpp\n*\n* @brief Write time series of gridded data as gridded data time series file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite a series of \\configFile{inputfileGriddedData}{griddedData}\nwith the corresponding \\configClass{timeSeries}{timeSeriesType}\nas a single \\file{gridded data time series file}{griddedDataTimeSeries}.\nThe \\config{splineDegree} defines the possible temporal interpolation of data in the output file.\nFor a file with spline degree 0 (temporal block means) the time intervals\nin which the grids are valid are defined between adjacent points in time.\nTherefore one more point in time is needed than the number of input grid files for degree 0.\n\nSee also \\program{GriddedDataTimeSeries2GriddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write time series of gridded data as gridded data time series file.\n* @ingroup programsGroup */\nclass GriddedData2GriddedDataTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2GriddedDataTimeSeries, SINGLEPROCESS, \"Write time series of gridded data as gridded data time series file\", Grid, TimeSeries)\n\n/***********************************************/\n\nvoid GriddedData2GriddedDataTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNamesGrid;\n    TimeSeriesPtr         timeSeries;\n    UInt                  splineDegree;\n\n    readConfig(config, \"outputfileGriddedDataTimeSeries\", fileNameOut,   Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"inputfileGriddedData\",            fileNamesGrid, Config::MUSTSET, \"\",  \"file count must agree with number of times+splineDegre-1\");\n    readConfig(config, \"timeSeries\",                      timeSeries,    Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"splineDegree\",                    splineDegree,  Config::DEFAULT, \"1\", \"degree of splines\");\n    if(isCreateSchema(config)) return;\n\n    const std::vector<Time> times = timeSeries->times();\n    if(times.size()+splineDegree-1 != fileNamesGrid.size())\n      throw(Exception(\"fileCount(\"+fileNamesGrid.size()%\"%i) != timeCount(\"s+times.size()%\"%i)-1+splineDegree\"s));\n\n    GriddedData         grid;\n    std::vector<Matrix> data;\n    for(UInt idNode=0; idNode<fileNamesGrid.size(); idNode++)\n    {\n      try\n      {\n        logStatus<<\"read gridded data <\"<<fileNamesGrid.at(idNode)<<\">\"<<Log::endl;\n        readFileGriddedData(fileNamesGrid.at(idNode), grid);\n        if(!data.size())\n          data.resize(fileNamesGrid.size(), Matrix(grid.points.size(), grid.values.size()));\n        for(UInt k=0; k<grid.values.size(); k++)\n          for(UInt i=0; i<grid.values.at(k).size(); i++)\n            data.at(idNode)(i,k) = grid.values.at(k).at(i);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<Log::endl;\n      }\n    }\n\n    logStatus<<\"write time series to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    grid.values.clear();\n    writeFileGriddedDataTimeSeries(fileNameOut, splineDegree, times, grid, data);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2Matrix.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2Matrix.cpp\n*\n* @brief Write grid to matrix file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-06-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts \\configFile{inputfileGriddedData}{griddedData}\nto \\configFile{outputfileMatrix}{matrix} with data columns.\nThe grid is expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nThe content of the output matrix can be controlled by \\config{outColumn} expressions\napplied to every grid point. The common data variables for grids are available,\nsee \\reference{dataVariables}{general.parser:dataVariables}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileMatrix.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write grid to matrix file.\n* @ingroup programsGroup */\nclass GriddedData2Matrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2Matrix, SINGLEPROCESS, \"write grid to matrix file\", Grid, Matrix)\nGROOPS_RENAMED_PROGRAM(Grid2Matrix, GriddedData2Matrix, date2time(2020, 02, 02))\n\n/***********************************************/\n\nvoid GriddedData2Matrix::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameGrid;\n    Double   a, f;\n    std::vector<ExpressionVariablePtr> expression;\n\n    readConfig(config, \"outputfileMatrix\",     fileNameOut,  Config::MUSTSET,  \"\", \"point list as matrix with longitude and latitude values in columns and possible additional columns\");\n    readConfig(config, \"inputfileGriddedData\", fileNameGrid, Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"R\",                    a,            Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",    f,            Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    readConfig(config, \"outColumn\",            expression,   Config::OPTIONAL, R\"([\"longitude\", \"latitude\", \"height\", \"data0\"])\", \"expression (variables: longitude, latitude, height, area, data0, data1, ...)\");\n    if(isCreateSchema(config)) return;\n\n    // create grid\n    // -----------\n    logStatus<<\"read grid file <\"<<fileNameGrid<<\">\"<<Log::endl;\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    grid.ellipsoid = Ellipsoid(a,f);\n    MiscGriddedData::printStatistics(grid);\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    std::for_each(expression.begin(), expression.end(), [&](auto expr) {expr->simplify(varList);});\n\n    // calculate output grid\n    // ---------------------\n    logStatus<<\"calculate output matrix\"<<Log::endl;\n    Matrix A(grid.points.size(), expression.size());\n    Single::forEach(A.rows(), [&](UInt i)\n    {\n      evaluateDataVariables(grid, i, varList);\n      for(UInt k=0; k<A.columns(); k++)\n        A(i,k) = expression.at(k)->evaluate(varList);\n    });\n\n    // write\n    // -----\n    logStatus<<\"write matrix to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2PotentialCoefficients.cpp\n*\n* @brief Estimate potential coefficients from gridded gravity field functionals.\n* With quadrature formular or\n* least squares adjustment with block diagonal normals (order by order).\n*\n* @author Annette Eicker\n* @author Torsten Mayer-Guerr\n* @date 2005-05-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimate potential coefficients from \\configFile{inputfileGriddedData}{griddedData}\ngravity field functionals. It used a simple quadrature formular\n\\begin{equation}\n  c_{nm} = \\frac{1}{4\\pi}\\frac{R}{GM} \\sum_i f_i \\left(\\frac{r_i}{R}\\right)^{n+1} k_n C_{nm}(\\lambda_i,\\vartheta_i)\\,\\Delta\\Phi_i\n\\end{equation}\nor a \\config{leastSquares} adjustment with block diagonal normal matrix (order by order).\nFor the latter one the data must be regular distributed.\n\nThe \\config{value}s $f_i$ and the \\config{weight}s $\\Delta\\Phi_i$ are expressions\nusing the common data variables for grids, see \\reference{dataVariables}{general.parser:dataVariables}.\nMultiple \\configFile{outputfilePotentialCoefficients}{potentialCoefficients} can be estimated in one step.\nFor each an indivdual \\config{value} must be specified.\nThe type of the gridded data (e.g gravity anomalies or geoid heights)\nmust be set with \\configClass{kernel}{kernelType} $k_n$.\n\nThe expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusively. The coefficients are related\nto the reference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nFor irregular distributed data and using the full variance covariance matrix use\n\\program{NormalsSolverVCE} together with \\configClass{oberservation:terrestrial}{observationType:terrestrial}\nand \\configClass{parametrizationGravity:sphericalHarmonics}{parametrizationGravityType:sphericalHarmonics}.\n\nSee also \\program{GriddedDataTimeSeries2PotentialCoefficients}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate potential coefficients from gridded gravity field functionals.\n* With quadrature formular or\n* least squares adjustment with block diagonal normals (order by order).\n* @ingroup programsGroup */\nclass GriddedData2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2PotentialCoefficients, PARALLEL, \"Estimate potential coefficients from gridded gravity field functionals\", Grid, PotentialCoefficients)\n\n/***********************************************/\n\nvoid GriddedData2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<FileName> fileNameOut;\n    FileName              fileNameGrid;\n    std::vector<ExpressionVariablePtr> exprValue;\n    ExpressionVariablePtr exprArea;\n    KernelPtr             kernel;\n    Double                GM, R;\n    UInt                  minDegree, maxDegree;\n    Bool                  useLeastSquares;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", fileNameOut,     Config::MUSTSET,  \"\",      \"one file for each value expression\");\n    readConfig(config, \"inputfileGriddedData\",            fileNameGrid,    Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"value\",                           exprValue,       Config::MUSTSET,  \"data0\", \"expression to compute values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"weight\",                          exprArea,        Config::MUSTSET,  \"area\",  \"expression to compute values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"kernel\",                          kernel,          Config::MUSTSET,  \"\",      \"data type of input values\");\n    readConfig(config, \"minDegree\",                       minDegree,       Config::DEFAULT,  \"0\",     \"\");\n    readConfig(config, \"maxDegree\",                       maxDegree,       Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"GM\",                              GM,              Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                               R,               Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"leastSquares\",                    useLeastSquares, Config::DEFAULT,  \"0\",     \"false: quadrature formular, true: least squares adjustment order by order\");\n    if(isCreateSchema(config)) return;\n\n    if(fileNameOut.size() != exprValue.size())\n      throw(Exception(\"number of outputfilePotentialCoefficients must agree with number of value expressions\"));\n\n    // reading grids\n    // -------------\n    logStatus<<\"read grid from file <\"<<fileNameGrid<<\">\"<<Log::endl;\n    GriddedData grid;\n    readFileGriddedData(fileNameGrid, grid);\n    MiscGriddedData::printStatistics(grid);\n\n    // evaluate expressions\n    // --------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    std::for_each(exprValue.begin(), exprValue.end(), [&](auto expr) {expr->simplify(varList);});\n    exprArea ->simplify(varList);\n    std::vector<std::vector<Double>> values(exprValue.size(), std::vector<Double>(grid.points.size()));\n    for(UInt i=0; i<grid.points.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      for(UInt k=0; k<exprValue.size(); k++)\n        values.at(k).at(i) = exprValue.at(k)->evaluate(varList);\n      grid.areas.at(i) = exprArea->evaluate(varList);\n    }\n    grid.values = values;\n\n    // spherical harmonic analysis\n    // ---------------------------\n    std::vector<SphericalHarmonics> harmonics = MiscGriddedData::analysisSphericalHarmonics(grid, kernel, minDegree, maxDegree, GM, R, useLeastSquares, comm);\n\n    // write potential coefficients\n    // ----------------------------\n    if(Parallel::isMaster(comm))\n      for(UInt k=0; k<harmonics.size(); k++)\n      {\n        logStatus<<\"write potential coefficients to file <\"<<fileNameOut.at(k)<<\">\"<<Log::endl;\n        writeFileSphericalHarmonics(fileNameOut.at(k), harmonics.at(k));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2SphericalDistance.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2SphericalDistance.cpp\n*\n* @brief Spherical distance between all point pairs of two grids.\n*\n* @author Andreas KVas\n* @date 2018-01-10\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute the spherical distance on the unit sphere in radians between all point pairs of two grids.\nThe spherical distance is computed by\n\\begin{equation}\n  \\psi_{12} = \\arccos(\\M n_1 \\cdot \\M n_2),\n\\end{equation}\nwhere $\\M n_i$ is the (normalized) position. This implies that all points are projected onto the unit sphere.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/grid/grid.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Spherical distance between all point pairs of two grids.\n* @ingroup programsGroup */\nclass GriddedData2SphericalDistance\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2SphericalDistance, SINGLEPROCESS, \"spherical distance between all point pairs of two grids.\", Grid, Matrix)\n\n/***********************************************/\n\nvoid GriddedData2SphericalDistance::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameDistance;\n    GridPtr  gridPtr1, gridPtr2;\n\n    readConfig(config, \"outputfileMatrix\", fileNameDistance, Config::MUSTSET, \"\", \"matrix containing the spherical distance between all point pairs [rad]\");\n    readConfig(config, \"grid1\",             gridPtr1,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid2\",             gridPtr2,         Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Vector3d> points1 = gridPtr1->points();\n    std::vector<Vector3d> points2 = gridPtr2->points();\n    std::for_each(points1.begin(), points1.end(), [](Vector3d &p) {p.normalize();});\n    std::for_each(points2.begin(), points2.end(), [](Vector3d &p) {p.normalize();});\n\n    logStatus<<\"compute distance\"<<Log::endl;\n    Matrix S(points1.size(), points2.size());\n    for(UInt i=0; i<points1.size(); i++)\n      for(UInt k=0; k<points2.size(); k++)\n        S(i,k) = std::acos(std::min(std::max(inner(points1.at(i), points2.at(k)), -1.), 1.));\n\n    logStatus<<\"writing matrix to file <\"<<fileNameDistance<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameDistance, S);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedData2TimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedData2TimeSeries.cpp\n*\n* @brief Write time series of gridded data as time series file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-01-29\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite a series of \\configFile{inputfileGriddedData}{griddedData} with the corresponding\n\\configClass{timeSeries}{timeSeriesType} as a single time series file\n(\\file{instrument}{instrument}, MISCVALUES).\n\nIf \\config{groupDataByPoints} is true the \\config{outputfileTimeSeries} starts\nfor each epoch with all data (\\verb|data0|, \\verb|data1|\\ldots) for the first point,\nfollowed by all data of the second point and so on.\nIf \\config{groupDataByPoints} is false, the file starts with \\verb|data0|\nfor all points, followed by all \\verb|data1| and so on.\n\nThis enables the use of all instrument programs like \\program{InstrumentFilter} or\n\\program{InstrumentDetrend} to analyze and manipulate time series of gridded data.\n\nSee also \\program{TimeSeries2GriddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write time series of gridded data as time series file.\n* @ingroup programsGroup */\nclass GriddedData2TimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedData2TimeSeries, SINGLEPROCESS, \"Write time series of gridded data as time series file\", Grid, TimeSeries)\n\n/***********************************************/\n\nvoid GriddedData2TimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameInstrument;\n    std::vector<FileName> fileNamesGrid;\n    TimeSeriesPtr         timeSeries;\n    Bool                  groupData;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameInstrument, Config::MUSTSET, \"\",  \"each epoch: multiple data for points (MISCVALUES)\");\n    readConfig(config, \"inputfileGriddedData\", fileNamesGrid,      Config::MUSTSET, \"\",  \"file count must agree with number of times\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"groupDataByPoints\",    groupData,          Config::DEFAULT, \"1\", \"multiple data are given point by point, otherwise: data0 for all points, followed by all data1\");\n    if(isCreateSchema(config)) return;\n\n    const std::vector<Time> times = timeSeries->times();\n    if(times.size() != fileNamesGrid.size())\n      throw(Exception(\"number of files (\"+fileNamesGrid.size()%\"%i) must agree with number of times (\"s+times.size()%\"%i)\"s));\n\n    MiscValuesArc arc;\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      try\n      {\n        logStatus<<\"read gridded data <\"<<fileNamesGrid.at(idEpoch)<<\">\"<<Log::endl;\n        GriddedData grid;\n        readFileGriddedData(fileNamesGrid.at(idEpoch), grid);\n\n        MiscValuesEpoch epoch(grid.points.size() * grid.values.size());\n        epoch.time = times.at(idEpoch);\n        for(UInt k=0; k<grid.values.size(); k++)\n          for(UInt i=0; i<grid.values.at(k).size(); i++)\n            epoch.values(groupData ? (i*grid.values.size()+k) : (i+grid.points.size()*k)) = grid.values.at(k).at(i);\n        arc.push_back(epoch);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<Log::endl;\n      }\n    }\n\n    logStatus<<\"write time series to file <\"<<fileNameInstrument<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameInstrument, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataCalculate.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataCalculate.cpp\n*\n* @brief Calculate values of gridded data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-11-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program manipulates \\file{grid files}{griddedData} with data in columns similar to\n\\program{FunctionsCalculate}, see there for more details.\nIf several \\config{inputfile}s are given the data columns are copied side by side.\nAll \\config{inputfile}s must contain the same grid points.\nThe columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots.\n\nThe content of \\configFile{outputfileGriddedData}{griddedData} is controlled by \\config{outColumn}.\nThe algorithm to compute the output is as follows:\nThe expressions in \\config{outColumn} are evaluated once for each grid point of the input.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values\nfrom the input columns before.\nAdditional variables are available, e.g. \\verb|index|, \\verb|data0rms|,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nFor a simplified handling \\config{constant}s can be defined by \\verb|name=value|.\nIt is also possible to estimate \\config{parameter}s in a least squares adjustment.\nThe \\config{leastSquares} serves as template for observation equations for every point.\nThe expression \\config{leastSquares} is evaluated for each grid point.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nIn the next step the parameters are estimated in order to minimize the expressions in \\config{leastSquares}\nin the sense of least squares.\n\nAfterwards grid points are removed if one of the \\config{removalCriteria} expressions\nfor this grid point evaluates true (not zero).\n\nAn extra \\configFile{statistics:outputfile}{matrix} can be generated with one row of data.\nFor the computation of the \\config{outColumn} values\nall~\\reference{dataVariables}{general.parser:dataVariables} are available\n(e.g. \\verb|data3mean|, \\verb|data4std|) inclusively the \\config{constant}s and\nestimated \\config{parameter}s but without the \\verb|data0|,~\\verb|data1|,~\\ldots itself.\nThe variables and the numbering of the columns refers to the \\configFile{outputfileGriddedData}{griddedData}.\n\nSee also \\program{FunctionsCalculate}, \\program{InstrumentArcCalculate}, \\program{MatrixCalculate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***********************************************/\n\n/** @brief Calculate values of gridded data.\n* @ingroup programsGroup */\nclass GriddedDataCalculate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataCalculate, SINGLEPROCESS, \"Calculate values of gridded data.\", Grid)\n\n/***********************************************/\n\nvoid GriddedDataCalculate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                           fileNameOut, fileNameStatistics;\n    std::vector<FileName>              fileNamesIn;\n    std::vector<ExpressionVariablePtr> constExpr, paramExpr;\n    std::vector<ExpressionVariablePtr> lsaExpr, removeExpr;\n    std::vector<ExpressionVariablePtr> valueExpr, statisticsExpr;\n    ExpressionVariablePtr              lonExpr, latExpr, heightExpr, areaExpr;\n    Bool                               computeArea;\n    Double                             a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileGriddedData\",  fileNamesIn, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"constant\",              constExpr,   Config::OPTIONAL, \"\", \"define a constant by name=value\");\n    readConfig(config, \"parameter\",             paramExpr,   Config::OPTIONAL, \"\", \"define a parameter by name[=value]\");\n    readConfig(config, \"leastSquares\",          lsaExpr,     Config::OPTIONAL, \"\", \"try to minimize the expression by adjustment of the parameters\");\n    readConfig(config, \"removalCriteria\",       removeExpr,  Config::OPTIONAL, \"\", \"points are removed if one criterion evaluates true. data0 is the first data field.\");\n    readConfig(config, \"longitude\",             lonExpr,     Config::MUSTSET,  \"longitude\", \"expression\");\n    readConfig(config, \"latitude\",              latExpr,     Config::MUSTSET,  \"latitude\",  \"expression\");\n    readConfig(config, \"height\",                heightExpr,  Config::MUSTSET,  \"height\",    \"expression\");\n    readConfig(config, \"area\",                  areaExpr,    Config::OPTIONAL, \"area\",      \"expression: e.g. deltaL * 2.0 * sin(deltaB/2.0) * cos(latitude/rho)\");\n    readConfig(config, \"value\",                 valueExpr,   Config::OPTIONAL, R\"([\"data0\"])\", \"expression to compute values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"computeArea\",           computeArea, Config::DEFAULT,  \"0\",         \"automatically area computation of rectangular grids (overwrite area)\");\n    readConfig(config, \"R\",                     a,           Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",     f,           Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(readConfigSequence(config, \"statistics\", Config::OPTIONAL, \"\", \"\"))\n    {\n      readConfig(config, \"outputfile\", fileNameStatistics, Config::MUSTSET, \"\",         \"matrix with one row, columns are user defined\");\n      readConfig(config, \"outColumn\",  statisticsExpr,     Config::MUSTSET, \"data0rms\", \"expression to compute statistics columns, data* are the outputColumns\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // =====================================================\n\n    // read data\n    // ---------\n    GriddedData gridIn;\n    for(UInt idFile=0; idFile<fileNamesIn.size(); idFile++)\n    {\n      logStatus<<\"reading grid from file <\"<<fileNamesIn.at(idFile)<<\">\"<<Log::endl;\n      GriddedData grid;\n      readFileGriddedData(fileNamesIn.at(idFile), grid);\n\n      // test grid equivalence\n      if(gridIn.points.size() != 0)\n      {\n        if(gridIn.points.size() != grid.points.size())\n          throw(Exception(\"grid differ in point count\"));\n        for(UInt i=0; i<gridIn.points.size(); i++)\n          if(std::fabs((gridIn.points.at(i)-grid.points.at(i)).r()/gridIn.points.at(i).r())>1e-10)\n          {\n            logWarning<<\"grid points differ: ignored\"<<Log::endl;\n            break;\n          }\n        // append values\n        gridIn.values.insert(gridIn.values.end(), grid.values.begin(), grid.values.end());\n      }\n      else\n        gridIn = grid;\n    } // for(idFile)\n\n    // =====================================================\n\n    // create data variables\n    // ---------------------\n    VariableList varList;\n    // get real variable names, otherwise all named after config element\n    std::for_each(constExpr.begin(), constExpr.end(), [&](auto expr) {expr->parseVariableName();});\n    std::for_each(paramExpr.begin(), paramExpr.end(), [&](auto expr) {expr->parseVariableName();});\n    std::for_each(constExpr.begin(), constExpr.end(), [&](auto expr) {varList.addVariable(expr);});\n    std::for_each(paramExpr.begin(), paramExpr.end(), [&](auto expr) {varList.addVariable(expr);});\n    auto varListWoData = varList;\n    addDataVariables(gridIn, varList);\n\n    // =====================================================\n\n    // build observation equations\n    // ---------------------------\n    if(lsaExpr.size())\n    {\n      logStatus<<\"least squares adjustment\"<<Log::endl;\n      Vector l(gridIn.points.size()*lsaExpr.size());\n      Matrix A(gridIn.points.size()*lsaExpr.size(), paramExpr.size());\n\n      for(UInt k=0; k<lsaExpr.size(); k++)\n      {\n        std::vector<ExpressionVariablePtr> lsaA(paramExpr.size());\n        for(UInt s=0; s<paramExpr.size(); s++)\n        {\n          lsaA.at(s) = lsaExpr.at(k)->derivative(paramExpr.at(s)->name(), varList);\n          lsaA.at(s)->simplify(varList);\n        }\n        lsaExpr.at(k)->simplify(varList);\n\n        for(UInt i=0; i<gridIn.points.size(); i++)\n        {\n          evaluateDataVariables(gridIn, i, varList);\n          l(i+k*gridIn.points.size()) = -lsaExpr.at(k)->evaluate(varList); // observations\n          for(UInt s=0; s<lsaA.size(); s++)\n            A(i+k*gridIn.points.size(),s) = lsaA.at(s)->evaluate(varList); // columns of design matrix\n        }\n        undefineDataVariables(gridIn, varList);\n      }\n\n      Vector x = leastSquares(A,l);\n      for(UInt s=0; s<paramExpr.size(); s++)\n      {\n        x(s) += paramExpr.at(s)->evaluate(varList);\n        paramExpr.at(s)->setValue( x(s) );\n        varList.setVariable(paramExpr.at(s)->name(),  x(s) );\n        varListWoData.setVariable(paramExpr.at(s)->name(),  x(s) );\n        logInfo<<\"  \"<<paramExpr.at(s)->name()<<\" = \"<<x(s)<<Log::endl;\n      }\n    }\n\n    // =====================================================\n\n    // calculate output grid\n    // ---------------------\n    logStatus<<\"calculate output matrix\"<<Log::endl;\n    lonExpr->simplify(varList);\n    latExpr->simplify(varList);\n    heightExpr->simplify(varList);\n    if(areaExpr)\n      areaExpr->simplify(varList);\n    std::for_each(removeExpr.begin(), removeExpr.end(), [&](auto expr) {expr->simplify(varList);});\n    std::for_each(valueExpr.begin(),  valueExpr.end(),  [&](auto expr) {expr->simplify(varList);});\n\n    GriddedData gridOut;\n    gridOut.ellipsoid = Ellipsoid(a,f);\n    gridOut.values.resize(valueExpr.size());\n    Single::forEach(gridIn.points.size(), [&](UInt i)\n    {\n      evaluateDataVariables(gridIn, i, varList);\n      if(std::any_of(removeExpr.begin(), removeExpr.end(), [&](auto expr) {return expr->evaluate(varList) != 0.;}))\n        return;\n      Double L = lonExpr->evaluate(varList);\n      Double B = latExpr->evaluate(varList);\n      Double h = heightExpr->evaluate(varList);\n      gridOut.points.push_back( gridOut.ellipsoid(Angle(L*DEG2RAD), Angle(B*DEG2RAD), h) );\n      if(areaExpr)\n        gridOut.areas.push_back( areaExpr->evaluate(varList) );\n      for(UInt k=0; k<valueExpr.size(); k++)\n        gridOut.values.at(k).push_back( valueExpr.at(k)->evaluate(varList) );\n    }, /*timing*/(gridIn.points.size() > 10'000'000));\n\n    // =====================================================\n\n    if(computeArea)\n    {\n      logStatus<<\"compute area\"<<Log::endl;\n      if(!gridOut.computeArea())\n        logWarning<<\"Compute areas only possible with regular rectangular grids\"<<Log::endl;\n    }\n\n    // =====================================================\n\n    // save grid\n    // ---------\n    if(!fileNameOut.empty())\n    {\n      logStatus<<\"save grid <\"<<fileNameOut<<\">\"<<Log::endl;\n      writeFileGriddedData(fileNameOut, gridOut);\n      MiscGriddedData::printStatistics(gridOut);\n    }\n\n    // statistics\n    // ----------\n    if(!fileNameStatistics.empty())\n    {\n      logStatus<<\"write statistics to <\"<<fileNameStatistics<<\">\"<<Log::endl;\n      auto varList = varListWoData;\n      addDataVariables(gridOut, varList);\n      Matrix statistics(1, statisticsExpr.size());\n      for(UInt k=0; k<statistics.columns(); k++)\n        statistics(0, k) = statisticsExpr.at(k)->evaluate(varList);\n      writeFileMatrix(fileNameStatistics, statistics);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataConcatenate.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataConcatenate.cpp\n*\n* @brief Concatenate gridded data from several files.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-02-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program concatenate grid from several \\configFile{inputfileGriddedData}{griddedData}\nand write it to a new \\configFile{outputfileGriddedData}{griddedData}.\nInput files must have the same number of data columns.\nIf \\config{sort} is enabled, the points are sorted by latitudes starting from north/west to south east.\nIdentical points (within a \\config{margin}) can be removed with \\config{removeDuplicates}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n#include \"classes/border/border.h\"\n\n/***********************************************/\n\n/** @brief Concatenate gridded data from several files.\n* @ingroup programsGroup */\nclass GriddedDataConcatenate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataConcatenate, SINGLEPROCESS, \"Concatenate gridded data from several files\", Grid)\n\n/***********************************************/\n\nvoid GriddedDataConcatenate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameStatistics;\n    std::vector<FileName> fileNamesIn;\n    BorderPtr             border;\n    Bool                  sortPoints;\n    Double                a, f;\n    std::string           choice;\n    enum Keep {KEEPALL, KEEPFIRST, KEEPLAST};\n    Keep                  keep = KEEPALL;\n    Double                margin;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileGriddedData\",  fileNamesIn,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"border\",                border,           Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"sortPoints\",            sortPoints,       Config::DEFAULT,  \"0\", \"sort from north/west to south east\");\n    if(readConfigChoice(config, \"removeDuplicates\", choice, Config::OPTIONAL, \"\", \"remove duplicate points\"))\n    {\n      if(readConfigChoiceElement(config, \"keepFirst\", choice, \"keep first point, remove all other identicals\"))\n      {\n        readConfig(config, \"margin\", margin, Config::DEFAULT, \"1e-5\", \"margin distance for identical points [m]\");\n        keep = KEEPFIRST;\n      }\n      if(readConfigChoiceElement(config, \"keepLast\",  choice, \"keep last point, remove all other identicals\"))\n      {\n        readConfig(config, \"margin\", margin, Config::DEFAULT, \"1e-5\", \"margin distance for identical points [m]\");\n        keep = KEEPLAST;\n      }\n      endChoice(config);\n    }\n    readConfig(config, \"R\",                 a, Config::DEFAULT, STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\", f, Config::DEFAULT, STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // =====================================================\n\n    // read data\n    // ---------\n    GriddedData grid;\n    for(auto fileName : fileNamesIn)\n    {\n      GriddedData gridFile;\n      try\n      {\n        logStatus<<\"reading grid from file <\"<<fileName<<\">\"<<Log::endl;\n        readFileGriddedData(fileName, gridFile);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        continue;\n      }\n\n      if(grid.points.size() == 0)\n      {\n        grid = gridFile;\n        grid.ellipsoid = Ellipsoid(a,f);\n        continue;\n      }\n\n      if((grid.areas.size()==0) != (gridFile.areas.size()==0))\n        throw(Exception(\"all grids must have areas or none of them\"));\n      if(grid.values.size() != gridFile.values.size())\n        throw(Exception(\"all grids must agree in the number of data columns\"));\n\n      grid.points.insert(grid.points.end(), gridFile.points.begin(), gridFile.points.end());\n      grid.areas.insert (grid.areas.end(),  gridFile.areas.begin(),  gridFile.areas.end());\n      for(UInt k=0; k<grid.values.size(); k++)\n        grid.values.at(k).insert(grid.values.at(k).end(), gridFile.values.at(k).begin(), gridFile.values.at(k).end());\n    }\n\n    // =====================================================\n\n    auto movePoints = [&](UInt from, UInt to)\n    {\n      grid.points.at(to) = grid.points.at(from);\n      if(grid.areas.size())\n        grid.areas.at(to)  = grid.areas.at(from);\n      for(UInt k=0; k<grid.values.size(); k++)\n        grid.values.at(k).at(to) = grid.values.at(k).at(from);\n    };\n\n    // remove points outside border\n    // ----------------------------\n    if(border)\n    {\n      logStatus<<\"remove points outside border\"<<Log::endl;\n      UInt count = std::distance(grid.points.begin(), std::find_if(grid.points.begin(), grid.points.end(), [&](const Vector3d &p) {return !border->isInnerPoint(p, grid.ellipsoid);}));\n      for(UInt i=count+1; i<grid.points.size(); i++)\n        if(border->isInnerPoint(grid.points.at(i), grid.ellipsoid))\n          movePoints(i, count++);\n      logInfo<<\" \"<<grid.points.size()-count<<\" points removed!\"<<Log::endl;\n      grid.points.resize(count);\n      if(grid.areas.size())\n        grid.areas.resize(count);\n      for(UInt k=0; k<grid.values.size(); k++)\n        grid.values.at(k).resize(count);\n    }\n\n    // =====================================================\n\n    if(sortPoints || (keep != KEEPALL))\n    {\n      logStatus<<\"sort points\"<<Log::endl;\n      grid.sort();\n    }\n\n    // =====================================================\n\n    // eliminate duplicates\n    // --------------------\n    if(keep != KEEPALL)\n    {\n      logStatus<<\"eliminate duplicates\"<<Log::endl;\n      UInt count = std::distance(grid.points.begin(), std::adjacent_find(grid.points.begin(), grid.points.end(),\n                                 [&](const Vector3d &x, const Vector3d &y) {return (x-y).r() <= margin;}));\n      if(count < grid.points.size())\n        for(UInt i=++count; i<grid.points.size(); i++)\n        {\n          if((grid.points.at(i)-grid.points.at(count-1)).r() > margin)\n            movePoints(i, count++);\n          else if(keep == KEEPLAST)\n            movePoints(i, count-1);\n        }\n      logInfo<<\" \"<<grid.points.size()-count<<\" duplicates removed!\"<<Log::endl;\n      grid.points.resize(count);\n      if(grid.areas.size())\n        grid.areas.resize(count);\n      for(UInt k=0; k<grid.values.size(); k++)\n        grid.values.at(k).resize(count);\n    }\n\n    // =====================================================\n\n    // save grid\n    // ---------\n    logStatus<<\"save grid <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOut, grid);\n    MiscGriddedData::printStatistics(grid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataCreate.cpp\n*\n* @brief Create a grid an write it to file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-08-06\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program creates a \\configClass{grid}{gridType} and writes it to \\configFile{outputfileGrid}{griddedData}.\nThe grid is expressed as ellipsoidal coordinates (longitude, latitude, height)\nbased on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\nExtra \\config{value} columns can be appended using expressions\nwith the common \\reference{data variables}{general.parser:dataVariables} for gridded data.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create a grid an write it to file.\n* @ingroup programsGroup */\nclass GriddedDataCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataCreate, SINGLEPROCESS, \"create a grid an write it to file\", Grid)\nGROOPS_RENAMED_PROGRAM(Grid2File, GriddedDataCreate, date2time(2020, 01, 28))\n\n/***********************************************/\n\nvoid GriddedDataCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameGrid;\n    GridPtr  gridPtr;\n    Double   a, f;\n    std::vector<ExpressionVariablePtr> exprValues;\n\n    readConfig(config, \"outputfileGrid\",    fileNameGrid, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"grid\",              gridPtr,      Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"R\",                 a,            Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\", f,            Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    readConfig(config, \"value\",             exprValues,   Config::OPTIONAL, \"0.0\", \"expression (variables as 'longitude', 'height', 'area' are taken from the gridded data)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"create grid\"<<Log::endl;\n    GriddedData grid(Ellipsoid(a,f), gridPtr->points(), gridPtr->areas(), {});\n\n    if(exprValues.size())\n    {\n      VariableList varList;\n      addDataVariables(grid, varList);\n      for(auto exprValue : exprValues)\n        exprValue->simplify(varList);\n\n      grid.values.resize(exprValues.size(), std::vector<Double>(grid.points.size(), 0));\n      for(UInt i=0; i<grid.points.size(); i++)\n      {\n        evaluateDataVariables(grid, i, varList);\n        for(UInt k=0; k<exprValues.size(); k++)\n          grid.values.at(k).at(i) = exprValues.at(k)->evaluate(varList);\n      }\n    }\n\n    logStatus<<\"writing grid to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameGrid, grid);\n    MiscGriddedData::printStatistics(grid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataInterpolate.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataInterpolate.cpp\n*\n* @brief Interpolate values of rectangular grids to new points.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-05-11\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nInterpolate values of a regular rectangular \\configFile{inputfileGriddedData}{griddedData}\nto new points given by \\configClass{grid}{gridType} and write as \\configFile{outputfileGriddedData}{griddedData}.\nOnly longitude and latitude of points are considered; the height is ignored for interpolation.\n\n(Only nearest neighbor method is implemented at the moment.)\n\n\\fig{!hb}{0.8}{griddedDataInterpolate}{fig:griddedDataInterpolate}{Interpolation of point data from rectangular gridded data.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolate values of rectangular grids to new points.\n* @ingroup programsGroup */\nclass GriddedDataInterpolate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataInterpolate, SINGLEPROCESS, \"Interpolate values of rectangular grids to new points\", Grid)\n\n/***********************************************/\n\nvoid GriddedDataInterpolate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOutGrid, fileNameInGrid;\n    GridPtr     gridPtr;\n    std::string choice;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOutGrid, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileGriddedData\",  fileNameInGrid,  Config::MUSTSET, \"\", \"must be rectangular\");\n    readConfig(config, \"grid\",                  gridPtr,         Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"method\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"nearestNeighbor\", choice, \"\")) {};\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // read grid\n    // ---------\n    logStatus<<\"read grid from file <\"<<fileNameInGrid<<\">\"<<Log::endl;\n    GriddedDataRectangular grid;\n    readFileGriddedData(fileNameInGrid, grid);\n    MiscGriddedData::printStatistics(grid);\n\n    logStatus<<\"create grid\"<<Log::endl;\n    GriddedData pointList(grid.ellipsoid, gridPtr->points(), gridPtr->areas(), std::vector<std::vector<Double>>(grid.values.size(), std::vector<Double>(gridPtr->points().size(), 0.)));\n\n    // interpolate\n    // -----------\n    Single::forEach(pointList.points.size(), [&](UInt i)\n    {\n      Angle  L, B;\n      Double h;\n      grid.ellipsoid(pointList.points.at(i), L, B, h);\n\n      // find nearest neighbor\n      const UInt row = std::distance(grid.latitudes.begin(), std::min_element(grid.latitudes.begin(), grid.latitudes.end(),\n                                     [&B](Angle B1, Angle B2) {return std::fabs(B-B1) < std::fabs(B-B2);}));\n      const UInt col = std::distance(grid.longitudes.begin(), std::min_element(grid.longitudes.begin(), grid.longitudes.end(),\n                                     [&L](Angle L1, Angle L2) {return std::fabs(L-L1) < std::fabs(L-L2);}));\n\n      for(UInt k=0; k<grid.values.size(); k++)\n        pointList.values.at(k).at(i) = grid.values.at(k)(row, col);\n    });\n\n    // write\n    // -----\n    logStatus<<\"write interpolated values to file <\"<<fileNameOutGrid<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOutGrid, pointList);\n    MiscGriddedData::printStatistics(pointList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataReduceSampling.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataReduceSampling.cpp\n*\n* @brief Generate coarse grid by computing mean values.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-10-24\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nGenerate coarse grid by computing area weighted mean values.\nThe number of points is decimated by averaging integer multiplies of grid points\n(\\config{multiplierLongitude}, \\config{multiplierLatitude}).\n\nif \\config{volumeConserving} is set, data are interpreted as heights above ellipsoid\nand the tesseroid volume\n\\begin{equation}\n  V=\\int_r^{r+H}\\int_{\\varphi_1}^{\\varphi_2}\\int_{\\lambda_1}^{\\lambda_2} r^2\\cos\\varphi\\,d\\varphi\\,d\\lambda\\,dr\n\\end{equation}\nis conserved, where $r$ is the radius of the ellipsoid at grid center and\n$(\\varphi_1-\\varphi_2)\\times(\\lambda_1-\\lambda_2)$ are the grid cell boundaries.\nThis is meaninful for Digital Elevation Models (DEM).\n\nThe fine grid can be written, where the first coarse grid values (data0) are additionally appended.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate coarse grid by computing mean values.\n* @ingroup programsGroup */\nclass GriddedDataReduceSampling\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataReduceSampling, SINGLEPROCESS, \"Generate coarse grid by computing mean values\", Grid)\n\n/***********************************************/\n\nvoid GriddedDataReduceSampling::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutCoarseGrid, fileNameOutFineGrid;\n    FileName fileNameInFineGrid;\n    UInt     numberRows, numberCols;\n    Bool     volumeConserving;\n\n    readConfig(config, \"outputfileCoarseGridRectangular\", fileNameOutCoarseGrid, Config::OPTIONAL, \"\", \"coarse grid\");\n    readConfig(config, \"outputfileFineGridRectangular\",   fileNameOutFineGrid,   Config::OPTIONAL, \"\", \"fine grid with additional coarse grid values\");\n    readConfig(config, \"inputfileFineGridRectangular\",    fileNameInFineGrid,    Config::MUSTSET,  \"\", \"Digital Terrain Model\");\n    readConfig(config, \"multiplierLongitude\",             numberCols,            Config::MUSTSET,  \"8\", \"Generalizing factor\");\n    readConfig(config, \"multiplierLatitude\",              numberRows,            Config::MUSTSET,  \"8\", \"Generalizing factor\");\n    readConfig(config, \"volumeConserving\",                volumeConserving,      Config::DEFAULT,  \"0\", \"data are interpreted as heights above ellipsoid\");\n    if(isCreateSchema(config)) return;\n\n    // read grid\n    // ---------\n    logStatus<<\"read grid from file <\"<<fileNameInFineGrid<<\">\"<<Log::endl;\n    GriddedDataRectangular gridFine;\n    readFileGriddedData(fileNameInFineGrid, gridFine);\n\n    std::vector<Angle>  tmp;\n    std::vector<Double> radiusFine, longitude, latitude, dLambda, dPhi;\n    gridFine.geocentric(tmp, tmp, radiusFine);\n    gridFine.cellBorders(longitude, latitude);\n    gridFine.areaElements(dLambda, dPhi);\n\n    // Generate coarse grid\n    // --------------------\n    logStatus<<\"generate coarse grid\"<<Log::endl;\n    GriddedDataRectangular gridCoarse;\n    gridCoarse.ellipsoid = gridFine.ellipsoid;\n\n    gridCoarse.latitudes.resize(gridFine.latitudes.size()/numberRows);\n    for(UInt i=0; i<gridCoarse.latitudes.size(); i++)\n      gridCoarse.latitudes.at(i) = 0.5*(latitude.at(i*numberRows) + latitude.at((i+1)*numberRows));\n\n    gridCoarse.longitudes.resize(gridFine.longitudes.size()/numberCols);\n    for(UInt k=0; k<gridCoarse.longitudes.size(); k++)\n      gridCoarse.longitudes.at(k) = std::remainder(longitude.at(k*numberCols) + 0.5*std::remainder(longitude.at((k+1)*numberCols)-longitude.at(k*numberCols), 2*PI), 2*PI);\n\n    gridCoarse.heights.resize(gridCoarse.latitudes.size()); // Compute mean height\n    for(UInt i=0; i<gridCoarse.heights.size(); i++)\n    {\n      Double height = 0, weight = 0;\n      for(UInt ii=0; ii<numberRows; ii++)\n      {\n        height += dPhi.at(i) * gridFine.heights.at(i*numberRows+ii);\n        weight += dPhi.at(i);\n      }\n      gridCoarse.heights.at(i) = height/weight;\n    }\n\n    gridCoarse.values.resize(gridFine.values.size(), Matrix(gridCoarse.latitudes.size(), gridCoarse.longitudes.size()));\n\n    std::vector<Double> radiusCoarse, dLambdaCoarse, dPhiCoarse;\n    gridCoarse.geocentric(tmp, tmp, radiusCoarse);\n    gridCoarse.areaElements(dLambdaCoarse, dPhiCoarse);\n\n    // Compute mean values\n    // -------------------\n    logStatus<<\"compute mean values\"<<Log::endl;\n    if(!fileNameOutFineGrid.empty())\n      gridFine.values.push_back(Matrix(gridFine.latitudes.size(), gridFine.longitudes.size()));\n    Single::forEach(gridCoarse.latitudes.size(), [&](UInt i)\n    {\n      for(UInt k=0; k<gridCoarse.longitudes.size(); k++)\n      {\n        // compute volume of tesseroid V = (r2^3-r1^3)/3 * area with r2=r1+h\n        Vector volumes(gridCoarse.values.size());\n        for(UInt ii=0; ii<numberRows; ii++)\n          for(UInt kk=0; kk<numberCols; kk++)\n          {\n            const Double area = dPhi.at(i*numberRows+ii) * dLambda.at(k*numberCols+kk);\n            const Double r1   = radiusFine.at(i*numberRows+ii);\n            for(UInt idx=0; idx<gridCoarse.values.size(); idx++)\n              if(volumeConserving)\n                volumes(idx) += area * (std::pow(r1+gridFine.values.at(idx)(i*numberRows+ii, k*numberCols+kk), 3) - std::pow(r1, 3))/3.;\n            else\n              volumes(idx) += area * gridFine.values.at(idx)(i*numberRows+ii, k*numberCols+kk);\n          }\n\n        // height of tesseroid = (V*3/area - r1^3)^(1/3) - r1\n        const Double area = dPhiCoarse.at(i) * dLambdaCoarse.at(k);\n        const Double r1   = radiusCoarse.at(i);\n        for(UInt idx=0; idx<gridCoarse.values.size(); idx++)\n          if(volumeConserving)\n            gridCoarse.values.at(idx)(i, k) = std::pow(volumes(idx)*3/area + std::pow(r1, 3), 1./3.) - r1;\n          else\n            gridCoarse.values.at(idx)(i, k) = volumes(idx)/area;\n\n        if(!fileNameOutFineGrid.empty())\n          for(UInt ii=0; ii<numberRows; ii++)\n            for(UInt kk=0; kk<numberCols; kk++)\n              gridFine.values.back()(i*numberRows+ii, k*numberCols+kk) = gridCoarse.values.at(0)(i, k);\n      }\n    });\n\n    // write new grid\n    // --------------\n    if(!fileNameOutCoarseGrid.empty())\n    {\n      logStatus<<\"write coarse grid to file <\"<<fileNameOutCoarseGrid<<\">\"<<Log::endl;\n      writeFileGriddedData(fileNameOutCoarseGrid, gridCoarse);\n      MiscGriddedData::printStatistics(gridCoarse);\n    }\n\n    if(!fileNameOutFineGrid.empty())\n    {\n      logStatus<<\"write fine grid to file <\"<<fileNameOutFineGrid<<\">\"<<Log::endl;\n      writeFileGriddedData(fileNameOutFineGrid, gridFine);\n      MiscGriddedData::printStatistics(gridFine);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataTimeSeries2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDatatimeSeries2GriddedData.cpp\n*\n* @brief Write a griddedDataTimeSeries as griddedData for each epoch.\n*\n* @author Torsten Mayer-Guerr\n* @date 2021-09-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead a \\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nand write for each epoch a \\file{gridded data file}{griddedData} where\nthe \\config{variableLoopTime} and \\config{variableLoopIndex} are expanded for\neach point of the given \\configClass{timeSeries}{timeSeriesType}\nto create the file name for this epoch (see \\reference{text parser}{general.parser:text}).\n\nIf \\configClass{timeSeries}{timeSeriesType} is not set\nthe temporal nodal points from the inputfile are used.\n\nSee also \\program{GriddedData2GriddedDataTimeSeries}.\n)\";\n\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write a griddedDataTimeSeries as griddedData for each epoch.\n* @ingroup programsGroup */\nclass GriddedDataTimeSeries2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataTimeSeries2GriddedData, SINGLEPROCESS, \"Write a griddedDataTimeSeries as griddedData for each epoch\", Grid, TimeSeries)\n\n/***********************************************/\n\nvoid GriddedDataTimeSeries2GriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      fileNameOut, fileNameIn;\n    std::string   nameTime, nameIndex, nameCount;\n    TimeSeriesPtr timeSeries;\n\n    readConfig(config, \"outputfilesGriddedData\",         fileNameOut, Config::MUSTSET,  \"grid_{loopTime:%y-%m}.dat\", \"for each epoch\");\n    readConfig(config, \"variableLoopTime\",               nameTime,    Config::OPTIONAL, \"loopTime\", \"variable with time of each epoch\");\n    readConfig(config, \"variableLoopIndex\",              nameIndex,   Config::OPTIONAL, \"\",         \"variable with index of current epoch (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",              nameCount,   Config::OPTIONAL, \"\",         \"variable with total number of epochs\");\n    readConfig(config, \"inputfileGriddedDataTimeSeries\", fileNameIn,  Config::MUSTSET,  \"\",         \"\");\n    readConfig(config, \"timeSeries\",                     timeSeries,  Config::OPTIONAL, \"\",         \"otherwise times from inputfile are used\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read gridded data time series <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFileGriddedDataTimeSeries file(fileNameIn);\n    GriddedData grid = file.grid();\n    MiscGriddedData::printStatistics(grid);\n    grid.values = std::vector<std::vector<Double>>(file.dataCount(), std::vector<Double>(grid.points.size()));\n    std::vector<Time> times = file.times();\n    if(timeSeries)\n      times = timeSeries->times();\n\n    VariableList varList;\n    if(!nameTime.empty())  varList.undefineVariable(nameTime);\n    if(!nameIndex.empty()) varList.undefineVariable(nameIndex);\n    if(!nameCount.empty()) varList.setVariable(nameCount, times.size());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      if(!nameTime.empty())  varList.setVariable(nameTime, times.at(idEpoch).mjd());\n      if(!nameIndex.empty()) varList.setVariable(nameIndex, idEpoch);\n      logStatus<<\"write gridded data <\"<<fileNameOut(varList)<<\">\"<<Log::endl;\n      Matrix data = file.data(times.at(idEpoch));\n      for(UInt i=0; i<grid.points.size(); i++)\n        for(UInt k=0; k<data.columns(); k++)\n          grid.values.at(k).at(i) = data(i, k);\n      writeFileGriddedData(fileNameOut(varList), grid);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedDataTimeSeries2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedDataTimeSeries2PotentialCoefficients.cpp\n*\n* @brief Convert a griddedDataTimeSeries to a sequence of PotentialCoefficients files.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-11-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimate potential coefficients from\n\\configFile{inputfileGriddedDataTimeSeries}{griddedDataTimeSeries}\nin the same way as \\program{GriddedData2PotentialCoefficients}\nbut not only for one grid but for each epoch of\n\\configClass{timeSeries}{timeSeriesType} of if not set\nfor the temporal nodal points from the inputfile.\nThe \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}\n(one for each \\config{value}) are written for each epoch with the expansion\nof \\config{variableLoopTime} and \\config{variableLoopIndex}\n(see \\reference{text parser}{general.parser:text}).\n\nSee also \\program{GriddedData2PotentialCoefficients}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Convert a griddedDataTimeSeries to a sequence of PotentialCoefficients files.\n* @ingroup programsGroup */\nclass GriddedDataTimeSeries2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedDataTimeSeries2PotentialCoefficients, PARALLEL, \"Convert a griddedDataTimeSeries to a sequence of PotentialCoefficients files\", Grid, TimeSeries)\n\n/***********************************************/\n\nvoid GriddedDataTimeSeries2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<FileName> fileNameOut;\n    std::string           nameTime, nameIndex, nameCount;\n    FileName              fileNameIn;\n    TimeSeriesPtr         timeSeries;\n    std::vector<ExpressionVariablePtr> exprValue;\n    ExpressionVariablePtr exprArea;\n    KernelPtr             kernel;\n    Double                GM, R;\n    UInt                  minDegree, maxDegree;\n    Bool                  useLeastSquares;\n\n    readConfig(config, \"outputfilesPotentialCoefficients\", fileNameOut,     Config::MUSTSET,  \"coeff_{loopTime:%D}.gfc\", \"for each epoch\");\n    readConfig(config, \"variableLoopTime\",                 nameTime,        Config::OPTIONAL, \"loopTime\", \"variable with time of each epoch\");\n    readConfig(config, \"variableLoopIndex\",                nameIndex,       Config::OPTIONAL, \"\",         \"variable with index of current epoch (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",                nameCount,       Config::OPTIONAL, \"\",         \"variable with total number of epochs\");\n    readConfig(config, \"inputfileGriddedDataTimeSeries\",   fileNameIn,      Config::MUSTSET,  \"\",         \"\");\n    readConfig(config, \"timeSeries\",                       timeSeries,      Config::OPTIONAL, \"\",         \"otherwise times from inputfile are used\");\n    readConfig(config, \"value\",                            exprValue,       Config::MUSTSET,  \"data0\",    \"expression (variables: longitude, latitude, height, area, data0, data1, ...)\");\n    readConfig(config, \"weight\",                           exprArea,        Config::MUSTSET,  \"area\",     \"expression to compute values (input columns are named data0, data1, ...)\");\n    readConfig(config, \"kernel\",                           kernel,          Config::MUSTSET,  \"\",         \"kernel in which the grid values are given\");\n    readConfig(config, \"minDegree\",                        minDegree,       Config::DEFAULT,  \"0\",        \"\");\n    readConfig(config, \"maxDegree\",                        maxDegree,       Config::MUSTSET,  \"\",         \"\");\n    readConfig(config, \"GM\",                               GM,              Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                                R,               Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius for potential coefficients\");\n    readConfig(config, \"leastSquares\",                     useLeastSquares, Config::DEFAULT,  \"0\",     \"false: quadrature formular, true: least squares adjustment order by order\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read gridded data time series <\"<<fileNameIn<<\">\"<<Log::endl;\n    InFileGriddedDataTimeSeries file(fileNameIn);\n    GriddedData grid = file.grid();\n    if(!grid.areas.size())\n      grid.computeArea();\n    MiscGriddedData::printStatistics(grid);\n    std::vector<Time> times = file.times();\n    if(timeSeries)\n      times = timeSeries->times();\n\n    // evaluate expressions\n    // --------------------\n    logStatus<<\"calculate gridded data\"<<Log::endl;\n    VariableList varList;\n    addDataVariables(grid, varList);\n    exprArea ->simplify(varList);\n    std::vector<Double> areas(grid.points.size());\n    for(UInt i=0; i<grid.points.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      areas.at(i) = exprArea->evaluate(varList);\n    }\n\n    // evaluate data at each epoch\n    std::vector<std::vector<Double>> values(exprValue.size()*times.size(), std::vector<Double>(grid.points.size()));\n    Single::forEach(times.size(), [&](UInt idEpoch)\n    {\n      Matrix data = file.data(times.at(idEpoch));\n      grid.values.resize(data.columns());\n      for(UInt k=0; k<data.columns(); k++)\n        grid.values.at(k) = Vector(data.column(k));\n      VariableList varList;\n      addDataVariables(grid, varList);\n      std::for_each(exprValue.begin(), exprValue.end(), [&](auto expr) {expr->simplify(varList);});\n      for(UInt i=0; i<grid.points.size(); i++)\n      {\n        evaluateDataVariables(grid, i, varList);\n        for(UInt k=0; k<exprValue.size(); k++)\n          values.at(idEpoch*exprValue.size()+k).at(i) = exprValue.at(k)->evaluate(varList);\n      }\n    });\n    grid.areas  = std::move(areas);\n    grid.values = std::move(values);\n\n    // spherical harmonic analysis\n    // ---------------------------\n    std::vector<SphericalHarmonics> harmonics = MiscGriddedData::analysisSphericalHarmonics(grid, kernel, minDegree, maxDegree, GM, R, useLeastSquares, comm);\n\n    // write potential coefficients\n    // ----------------------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write \"<<harmonics.size()<<\" potential coefficient files\"<<Log::endl;\n      VariableList varList;\n      if(!nameTime.empty())  varList.undefineVariable(nameTime);\n      if(!nameIndex.empty()) varList.undefineVariable(nameIndex);\n      if(!nameCount.empty()) varList.setVariable(nameCount, times.size());\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      {\n        if(!nameTime.empty())  varList.setVariable(nameTime, times.at(idEpoch).mjd());\n        if(!nameIndex.empty()) varList.setVariable(nameIndex, idEpoch);\n        for(UInt k=0; k<exprValue.size(); k++)\n          writeFileSphericalHarmonics(fileNameOut.at(k)(varList), harmonics.at(idEpoch*exprValue.size()+k));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedTopography2AtmospherePotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedTopography2AtmospherePotentialCoefficients.cpp\n*\n* @brief Estimate interior and exterior potential coefficients for atmosphere above digital terrain models.\n*\n* @author Christian Pock\n* @author Daniel Rieser\n* @date 2013-10-16\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nEstimate interior and exterior potential coefficients for atmosphere above digital terrain models.\nCoefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.\nThe density of the atmosphere is assumed to be (Sjöberg, 1998)\n\\begin{equation}\n\\rho_0\\left(\\frac{R}{R+h}\\right)^\\nu,\n\\end{equation}\nwhere $R$ is the radial distance of the ellipsoid at each point, $h$ the radial height above the ellipsoid,\n$\\rho_0$ is \\config{densitySeaLevel} and \\config{nu} $\\nu$ is a constant factor. The density is integrated\nfrom \\config{radialLowerBound} and \\config{upperAtmosphericBoundary} above the ellipsoid.\nThe \\config{radialLowerBound} is typically the topography and can be computed as expression at every point\nfrom \\configFile{inputfileGriddedData}{griddedData}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/legendreFunction.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate interior and exterior atmospheric potential coefficients above digital terrain models.\n* @ingroup programsGroup */\nclass GriddedTopography2AtmospherePotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedTopography2AtmospherePotentialCoefficients, PARALLEL, \"Estimate interoir and exterior atmospheric potential coefficients above digital terrain models\", Grid, PotentialCoefficients)\n\n/***********************************************/\n\nvoid GriddedTopography2AtmospherePotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameOutExterior, fileNameOutInterior, fileNameInGrid;\n    ExpressionVariablePtr expressionLower;\n    Double                rho, ny, upperBoundary, factor;\n    UInt                  minDegree, maxDegree;\n    Double                GM, R;\n\n    readConfig(config, \"outputfilePotentialCoefficientsExterior\", fileNameOutExterior, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfilePotentialCoefficientsInterior\", fileNameOutInterior, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileGriddedData\",     fileNameInGrid,  Config::MUSTSET,  \"\",       \"Digital Terrain Model\");\n    readConfig(config, \"densitySeaLevel\",          rho,             Config::DEFAULT,  \"1.225\",  \"[kg/m**3]\");\n    readConfig(config, \"ny\",                       ny,              Config::DEFAULT,  \"680\",    \"Constant for Atmosphere\");\n    readConfig(config, \"radialLowerBound\",         expressionLower, Config::DEFAULT,  \"data0\",  \"expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data\");\n    readConfig(config, \"upperAtmosphericBoundary\", upperBoundary,   Config::DEFAULT,  \"11000\",  \"constant upper bound [m]\");\n    readConfig(config, \"factor\",                   factor,          Config::DEFAULT,  \"1.0\",    \"the result is multiplied by this factor, set -1 to subtract the field\");\n    readConfig(config, \"minDegree\",                minDegree,       Config::DEFAULT,  \"0\",      \"\");\n    readConfig(config, \"maxDegree\",                maxDegree,       Config::MUSTSET,  \"\",       \"\");\n    readConfig(config, \"GM\",                       GM,              Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                        R,               Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    // read rectangular grid\n    // ---------------------\n    std::vector<Double> lambda, phi, radius;\n    Matrix              topo;\n    if(Parallel::isMaster(comm))\n    {\n      // read rectangular grid\n      // ---------------------\n      logStatus<<\"read grid from file <\"<<fileNameInGrid<<\">\"<<Log::endl;\n      GriddedDataRectangular grid;\n      readFileGriddedData(fileNameInGrid, grid);\n      MiscGriddedData::printStatistics(grid);\n\n      // evaluate upper and lower height\n      // -------------------------------\n      logStatus<<\"evaluate expression for lower boundary\"<<Log::endl;\n      VariableList varList;\n      addDataVariables(grid, varList);\n      expressionLower->simplify(varList);\n\n      radius.resize(grid.heights.size());\n      for(UInt i=0; i<radius.size(); i++)\n        radius.at(i) = grid.ellipsoid(Angle(0), grid.latitudes.at(i), grid.heights.at(i)).r();\n\n      topo = Matrix(grid.latitudes.size(), grid.longitudes.size());\n      Single::forEach(grid.latitudes.size(), [&](UInt i)\n      {\n        for(UInt k=0; k<grid.longitudes.size(); k++)\n        {\n          evaluateDataVariables(grid, i, k, varList);\n          topo(i, k) = expressionLower->evaluate(varList);   //  Topography\n        }\n      });\n\n      grid.cellBorders(lambda, phi);\n      for(UInt i=0; i<phi.size(); i++)\n        phi.at(i) = grid.ellipsoid(Angle(0), Angle(phi.at(i)), 0.).phi(); // geocentric\n    } // if(Parallel::isMaster(comm))\n\n    Parallel::broadCast(topo,    0, comm);\n    Parallel::broadCast(radius,  0, comm);\n    Parallel::broadCast(lambda,  0, comm);\n    Parallel::broadCast(phi,     0, comm);\n\n    // precompute integral_sin, integral_cos\n    // -------------------------------------\n    Matrix cosm(lambda.size()-1, maxDegree+1);\n    Matrix sinm(lambda.size()-1, maxDegree+1);\n    for(UInt i=0; i<lambda.size()-1; i++)\n    {\n      cosm(i,0) = lambda.at(i+1)-lambda.at(i);\n      for(UInt m=1; m<=maxDegree; m++)\n      {\n        cosm(i,m) =  (std::sin(m*lambda.at(i+1)) - std::sin(m*lambda.at(i)))/m;\n        sinm(i,m) = -(std::cos(m*lambda.at(i+1)) - std::cos(m*lambda.at(i)))/m;\n      }\n    }\n\n    // computing quadrature formular\n    // -----------------------------\n    logStatus<<\"computing quadrature formular\"<<Log::endl;\n    Matrix cnmExt(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snmExt(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix cnmInt(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snmInt(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Parallel::forEach(phi.size(), [&](UInt i)\n    {\n      //     const Matrix Pnm = LegendreFunction::integral(std::sin(phi.at(i+1)), std::sin(phi.at(i)), maxDegree);\n      const Matrix Pnm = LegendreFunction::compute(std::cos(0.5*(PI-phi.at(i+1)-phi.at(i))), maxDegree)\n                       * std::fabs(std::sin(phi.at(i+1))-std::sin(phi.at(i))); // integral cos(phi) dPhi\n\n      const Double H0   = radius.at(i);\n      const Double term = factor * rho * GRAVITATIONALCONSTANT/GM *R*R*R;\n\n      Matrix fExt(lambda.size(), maxDegree+1);\n      Matrix fInt(lambda.size(), maxDegree+1);\n      for(UInt k=0; k<lambda.size(); k++)\n      {\n        const Double r1R  = (1.+upperBoundary/H0);\n        const Double r2R  = (1.+topo(i,k)/H0);\n\n        Double r1RnExt = term * std::pow(1.+upperBoundary/H0, 3.+minDegree-ny);\n        Double r2RnExt = term * std::pow(1.+topo(i,k)/H0,     3.+minDegree-ny);\n        Double r1RnInt = term * std::pow(1.+upperBoundary/H0, 2.-minDegree-ny);\n        Double r2RnInt = term * std::pow(1.+topo(i,k)/H0,     2.-minDegree-ny);\n\n        for(UInt n=minDegree; n<=maxDegree; n++)\n        {\n          if (n == ny-3.)\n            fExt(k,n) = term/(R*R*R) * std::pow(1./R, n) * std::pow(H0, ny) * std::log((H0+upperBoundary)/(H0+topo(i,k)));\n          else\n            fExt(k,n) = (r1RnExt-r2RnExt) * std::pow(H0/R, n+3.)/((2.*n+1.)*(3.+n-ny));\n\n          fInt(k,n) = (r1RnInt-r2RnInt) * std::pow(H0/R, 2.-n)/((2.*n+1.)*(2.-n-ny));\n\n          r1RnExt *=r1R;\n          r2RnExt *=r2R;\n          r1RnInt /=r1R;\n          r2RnInt /=r2R;\n        }\n      }\n\n      for(UInt n=minDegree; n<=maxDegree; n++)\n        for(UInt m=0; m<=n; m++)\n        {\n          cnmExt(n,m) += Pnm(n,m) * inner(cosm.column(m), fExt.column(n));\n          snmExt(n,m) += Pnm(n,m) * inner(sinm.column(m), fExt.column(n));\n          cnmInt(n,m) += Pnm(n,m) * inner(cosm.column(m), fInt.column(n));\n          snmInt(n,m) += Pnm(n,m) * inner(sinm.column(m), fInt.column(n));\n        }\n    }, comm);\n    Parallel::reduceSum(cnmExt, 0, comm);\n    Parallel::reduceSum(snmExt, 0, comm);\n    Parallel::reduceSum(cnmInt, 0, comm);\n    Parallel::reduceSum(snmInt, 0, comm);\n\n    // save potential coefficients\n    // ---------------------------\n    if(Parallel::isMaster(comm) && !fileNameOutExterior.empty())\n    {\n      logStatus<<\"write potential coefficients to file <\"<<fileNameOutExterior<<\">\"<<Log::endl;\n      writeFileSphericalHarmonics(fileNameOutExterior, SphericalHarmonics(GM, R, cnmExt, snmExt));\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutInterior.empty())\n    {\n      logStatus<<\"write potential coefficients (interior) to file <\"<<fileNameOutInterior<<\">\"<<Log::endl;\n      writeFileSphericalHarmonics(fileNameOutInterior, SphericalHarmonics(GM, R, cnmInt, snmInt, TRUE));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedTopography2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedTopography2PotentialCoefficients.cpp\n*\n* @brief Estimate potential coefficients from digital terrain models.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-11-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nEstimate potential coefficients from digital terrain models.\nCoefficients for interior $(1/r)^{n+1}$ and exterior ($r^n$) are computed.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/legendreFunction.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate potential coefficients from digital terrain models.\n* @ingroup programsGroup */\nclass GriddedTopography2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedTopography2PotentialCoefficients, PARALLEL, \"Estimate potential coefficients from digital terrain models\", Grid, PotentialCoefficients)\n\n/***********************************************/\n\nvoid GriddedTopography2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameOutExterior, fileNameOutInterior;\n    FileName              fileNameInGrid;\n    ExpressionVariablePtr expressionUpper, expressionLower, expressionRho;\n    Double                factor;\n    UInt                  minDegree, maxDegree;\n    Double                GM, R;\n\n    readConfig(config, \"outputfilePotentialCoefficients\",         fileNameOutExterior, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfilePotentialCoefficientsInterior\", fileNameOutInterior, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileGriddedData\", fileNameInGrid,  Config::MUSTSET, \"\",      \"Digital Terrain Model\");\n    readConfig(config, \"density\",              expressionRho,   Config::DEFAULT, \"2670\",  \"expression [kg/m^3]\");\n    readConfig(config, \"radialUpperBound\",     expressionUpper, Config::DEFAULT, \"data0\", \"expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data\");\n    readConfig(config, \"radialLowerBound\",     expressionLower, Config::DEFAULT, \"0\",     \"expression (variables 'L', 'B', 'height', 'data', and 'area' are taken from the gridded data\");\n    readConfig(config, \"factor\",               factor,          Config::DEFAULT, \"1.0\",   \"the result is multiplied by this factor\");\n    readConfig(config, \"minDegree\",            minDegree,       Config::DEFAULT, \"0\",     \"\");\n    readConfig(config, \"maxDegree\",            maxDegree,       Config::MUSTSET, \"\",      \"\");\n    readConfig(config, \"GM\",                   GM,              Config::DEFAULT, STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                    R,               Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Double> lambda, phi;\n    Matrix              rLower, rUpper, rho;\n    if(Parallel::isMaster(comm))\n    {\n      // read rectangular grid\n      // ---------------------\n      logStatus<<\"read grid from file <\"<<fileNameInGrid<<\">\"<<Log::endl;\n      GriddedDataRectangular grid;\n      readFileGriddedData(fileNameInGrid, grid);\n      MiscGriddedData::printStatistics(grid);\n\n      // evaluate upper and lower height\n      // -------------------------------\n      logStatus<<\"evaluate upper and lower height\"<<Log::endl;\n      VariableList varList;\n      addDataVariables(grid, varList);\n      expressionUpper->simplify(varList);\n      expressionLower->simplify(varList);\n      expressionRho  ->simplify(varList);\n\n      std::vector<Double> radius(grid.heights.size());\n      for(UInt i=0; i<radius.size(); i++)\n        radius.at(i) = grid.ellipsoid(Angle(0), grid.latitudes.at(i), grid.heights.at(i)).r();\n\n      rLower = rUpper = rho = Matrix(grid.latitudes.size(), grid.longitudes.size());\n      Single::forEach(grid.latitudes.size(), [&](UInt i)\n      {\n        for(UInt k=0; k<grid.longitudes.size(); k++)\n        {\n          evaluateDataVariables(grid, i, k, varList);\n          rUpper(i,k) = radius.at(i) + expressionUpper->evaluate(varList);\n          rLower(i,k) = radius.at(i) + expressionLower->evaluate(varList);\n          rho(i,k)    = expressionRho->evaluate(varList);\n        }\n      });\n\n      grid.cellBorders(lambda, phi);\n      for(UInt i=0; i<phi.size(); i++)\n        phi.at(i) = grid.ellipsoid(Angle(0), Angle(phi.at(i)), 0.).phi(); // geocentric\n    } // if(Parallel::isMaster(comm))\n\n    if(Parallel::size(comm) > 1)\n      logStatus<<\"broadcast data\"<<Log::endl;\n    Parallel::broadCast(rUpper,  0, comm);\n    Parallel::broadCast(rLower,  0, comm);\n    Parallel::broadCast(rho,     0, comm);\n    Parallel::broadCast(lambda,  0, comm);\n    Parallel::broadCast(phi,     0, comm);\n\n    // precompute integral_sin, integral_cos\n    // -------------------------------------\n    Matrix cosm(lambda.size()-1, maxDegree+1);\n    Matrix sinm(lambda.size()-1, maxDegree+1);\n    for(UInt i=0; i<lambda.size()-1; i++)\n    {\n      cosm(i,0) = std::remainder(lambda.at(i+1)-lambda.at(i), 2*PI);\n      for(UInt m=1; m<=maxDegree; m++)\n      {\n        cosm(i,m) =  (std::sin(m*lambda.at(i+1)) - std::sin(m*lambda.at(i)))/m;\n        sinm(i,m) = -(std::cos(m*lambda.at(i+1)) - std::cos(m*lambda.at(i)))/m;\n      }\n    }\n\n    // computing quadrature formular\n    // -----------------------------\n    logStatus<<\"computing quadrature formular\"<<Log::endl;\n    Matrix cnmExt, snmExt, cnmInt, snmInt;\n    if(!fileNameOutExterior.empty()) cnmExt = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    if(!fileNameOutExterior.empty()) snmExt = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    if(!fileNameOutInterior.empty()) cnmInt = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    if(!fileNameOutInterior.empty()) snmInt = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Parallel::forEach(phi.size()-1, [&](UInt i)\n    {\n      const Matrix Pnm = LegendreFunction::integral(std::sin(std::min(phi.at(i), phi.at(i+1))),\n                                                    std::sin(std::max(phi.at(i), phi.at(i+1))), maxDegree);\n      // const Matrix Pnm = LegendreFunction::compute(std::sin(0.5*(phi.at(i+1)+phi.at(i))), maxDegree)\n      //                  * std::fabs(std::sin(phi.at(i+1))-std::sin(phi.at(i))); // integral cos(phi) dPhi\n\n      if(!fileNameOutExterior.empty())\n      {\n        Matrix fExt(lambda.size()-1, maxDegree+1);\n        for(UInt k=0; k<lambda.size()-1; k++)\n          if(rho(i,k) && (std::fabs(rUpper(i,k)-rLower(i,k)) > 0.001))\n          {\n            const Double term = factor * rho(i,k) * GRAVITATIONALCONSTANT/GM * R*R*R;\n            const Double r1R  = rLower(i,k)/R;\n            const Double r2R  = rUpper(i,k)/R;\n            Double r1RnExt = term * std::pow(r1R, minDegree+3);\n            Double r2RnExt = term * std::pow(r2R, minDegree+3);\n            for(UInt n=minDegree; n<=maxDegree; n++)\n            {\n              fExt(k,n) = (r2RnExt-r1RnExt)/((2.*n+1)*(n+3.));\n              r1RnExt *= r1R;\n              r2RnExt *= r2R;\n            } // for(n)\n          } // for(i)\n\n        for(UInt n=minDegree; n<=maxDegree; n++)\n          for(UInt m=0; m<=n; m++)\n          {\n            cnmExt(n,m) += Pnm(n,m) * inner(cosm.column(m), fExt.column(n));\n            snmExt(n,m) += Pnm(n,m) * inner(sinm.column(m), fExt.column(n));\n          }\n      } // if(!fileNameOutExterior.empty())\n\n      if(!fileNameOutInterior.empty())\n      {\n        Matrix fInt(lambda.size()-1, maxDegree+1);\n        for(UInt k=0; k<lambda.size()-1; k++)\n         if(rho(i,k) && (std::fabs(rUpper(i,k)-rLower(i,k)) > 0.001))\n         {\n            const Double term = factor * rho(i,k) * GRAVITATIONALCONSTANT/GM * R*R*R;\n            const Double Rr1  = R/rLower(i,k);\n            const Double Rr2  = R/rUpper(i,k);\n            Double r1RnInt = term * std::pow(Rr1, minDegree-2.);\n            Double r2RnInt = term * std::pow(Rr2, minDegree-2.);\n            for(UInt n=minDegree; n<=maxDegree; n++)\n            {\n              if(n != 2)\n                fInt(k,n) = (r2RnInt-r1RnInt)/((2*n+1)*(2.-n));\n              else\n                fInt(k,n) = term * std::log(rUpper(i,k)/rLower(i,k))/(2*n+1);\n              r1RnInt *= Rr1;\n              r2RnInt *= Rr2;\n            } // for(n)\n          } // for(i)\n\n        for(UInt n=minDegree; n<=maxDegree; n++)\n          for(UInt m=0; m<=n; m++)\n          {\n            cnmInt(n,m) += Pnm(n,m) * inner(cosm.column(m), fInt.column(n));\n            snmInt(n,m) += Pnm(n,m) * inner(sinm.column(m), fInt.column(n));\n          }\n      } // if(!fileNameOutInterior.empty())\n    }, comm);\n    if(!fileNameOutExterior.empty()) Parallel::reduceSum(cnmExt, 0, comm);\n    if(!fileNameOutExterior.empty()) Parallel::reduceSum(snmExt, 0, comm);\n    if(!fileNameOutInterior.empty()) Parallel::reduceSum(cnmInt, 0, comm);\n    if(!fileNameOutInterior.empty()) Parallel::reduceSum(snmInt, 0, comm);\n\n    // save potential coefficients\n    // ---------------------------\n    if(Parallel::isMaster(comm) && !fileNameOutExterior.empty())\n    {\n      logStatus<<\"write potential coefficients to file <\"<<fileNameOutExterior<<\">\"<<Log::endl;\n      writeFileSphericalHarmonics(fileNameOutExterior, SphericalHarmonics(GM, R, cnmExt, snmExt));\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutInterior.empty())\n    {\n      logStatus<<\"write potential coefficients (interior) to file <\"<<fileNameOutInterior<<\">\"<<Log::endl;\n      writeFileSphericalHarmonics(fileNameOutInterior, SphericalHarmonics(GM, R, cnmInt, snmInt, TRUE));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/griddedTopographyEllipsoidal2Radial.cpp",
    "content": "/***********************************************/\n/**\n* @file griddedTopographyEllipsoidal2Radial.cpp\n*\n* @brief Interpolate digital terrain models from ellipoidal heights to radial heights.\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-10-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nInterpolate digital terrain models from ellipoidal heights to radial heights.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Interpolate digital terrain models from ellipoidal heights to radial heights.\n* @ingroup programsGroup */\nclass GriddedTopographyEllipsoidal2Radial\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GriddedTopographyEllipsoidal2Radial, SINGLEPROCESS, \"Interpolate digital terrain models from ellipoidal heights to radial heights\", Grid)\n\n/***********************************************/\n\nvoid GriddedTopographyEllipsoidal2Radial::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutGrid, fileNameInGrid;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOutGrid, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"inputfileGriddedData\",  fileNameInGrid,  Config::MUSTSET,  \"\", \"Digital Terrain Model\");\n    if(isCreateSchema(config)) return;\n\n    // read grid\n    // ---------\n    logStatus<<\"read grid from file <\"<<fileNameInGrid<<\">\"<<Log::endl;\n    GriddedDataRectangular grid;\n    readFileGriddedData(fileNameInGrid, grid);\n    MiscGriddedData::printStatistics(grid);\n\n    std::vector<Angle>  lambda, phi;\n    std::vector<Double> radius;\n    grid.geocentric(lambda, phi, radius);\n    const Double direction = ((phi.back() > phi.front()) ? +1 : -1); // north to south or vice versa\n\n    logStatus<<\"linear interpolation of elevation data\"<<Log::endl;\n    Double maxPhiShift    = 0.0;\n    Double maxHeightShift = 0.0;\n    Single::forEach(grid.longitudes.size(), [&](UInt k)\n    {\n      Vector heightOld = grid.values.at(0).column(k);\n      std::vector<Angle> phiTop(grid.latitudes.size()); // spherical latitude at top of topography\n      for(UInt i=0; i<phi.size(); i++)\n        phiTop.at(i) = grid.ellipsoid(grid.longitudes.at(k), grid.latitudes.at(i), heightOld(i)).phi();\n\n      // linear interpolation\n      for(UInt i=0; i<phi.size(); i++)\n      {\n        // find interval\n        const UInt idx = std::min(i + (direction*(phi.at(i)-phiTop.at(i)) > 0), phiTop.size()-1);\n        const Double w = (phi.at(i)-phiTop.at(idx-1)) / (phiTop.at(idx)-phiTop.at(idx-1));\n        grid.values.at(0)(i,k) = w * heightOld(idx) + (w-1) * heightOld(idx-1);\n\n        maxPhiShift    = std::max(maxPhiShift,    std::fabs(phiTop.at(i)-phi.at(i)));\n        maxHeightShift = std::max(maxHeightShift, std::fabs(grid.values.at(0)(i,k)-heightOld(i)));\n      }\n    });\n\n    logInfo<<\"  max. shifted latitude: \"<<maxPhiShift*RAD2DEG<<\"°\"<<Log::endl;\n    logInfo<<\"  max. height change:    \"<<maxHeightShift<<\" m\"<<Log::endl;\n\n    // write new grid\n    // --------------\n    if(!fileNameOutGrid.empty())\n    {\n      logStatus<<\"write grid to file <\"<<fileNameOutGrid<<\">\"<<Log::endl;\n      writeFileGriddedData(fileNameOutGrid, grid);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/matrix2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file matrix2GriddedData.cpp\n*\n* @brief Read gridded data from matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2006-03-17\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads a \\file{matrix file}{matrix} with data in columns\nand convert into \\file{gridded data}{griddedData}.\nThe input columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read gridded data from matrix.\n* @ingroup programsGroup */\nclass Matrix2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Matrix2GriddedData, SINGLEPROCESS, \"Read gridded data from matrix\", Grid, Matrix)\nGROOPS_RENAMED_PROGRAM(GridMatrix2GriddedData, Matrix2GriddedData, date2time(2020, 02, 12))\n\n/***********************************************/\n\nvoid Matrix2GriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameIn;\n    ExpressionVariablePtr exprLon, exprLat, exprHeight;\n    ExpressionVariablePtr exprX, exprY, exprZ;\n    ExpressionVariablePtr exprArea;\n    std::vector<ExpressionVariablePtr> exprValues;\n    Bool                  sortPoints, computeArea;\n    Double                a, f;\n    std::string           choice;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileMatrix\",       fileNameIn,  Config::MUSTSET,  \"\", \"\");\n    if(readConfigChoice(config, \"points\", choice,  Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"ellipsoidal\", choice, \"\"))\n      {\n        readConfig(config, \"longitude\", exprLon,    Config::MUSTSET,  \"data0\", \"expression\");\n        readConfig(config, \"latitude\",  exprLat,    Config::MUSTSET,  \"data1\", \"expression\");\n        readConfig(config, \"height\",    exprHeight, Config::MUSTSET,  \"data2\", \"expression\");\n      }\n      if(readConfigChoiceElement(config, \"cartesian\", choice, \"\"))\n      {\n        readConfig(config, \"x\", exprX, Config::MUSTSET,  \"data0\", \"expression\");\n        readConfig(config, \"y\", exprY, Config::MUSTSET,  \"data1\", \"expression\");\n        readConfig(config, \"z\", exprZ, Config::MUSTSET,  \"data2\", \"expression\");\n      }\n      endChoice(config);\n    }\n    readConfig(config, \"area\",              exprArea,    Config::OPTIONAL, \"\", \"expression (e.g. deltaL*2*sin(deltaB/2)*cos(data1/RHO))\");\n    readConfig(config, \"value\",             exprValues,  Config::OPTIONAL, R\"([\"data3\"])\", \"expression\");\n    readConfig(config, \"sortPoints\",        sortPoints,  Config::DEFAULT,  \"0\", \"sort from north/west to south east\");\n    readConfig(config, \"computeArea\",       computeArea, Config::DEFAULT,  \"0\", \"the area can be computed automatically for rectangular grids\");\n    readConfig(config, \"R\",                 a,           Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\", f,           Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // =====================================================\n\n    logStatus<<\"Read matrix from file <\"<<fileNameIn<<\">\"<<Log::endl;\n    Matrix A;\n    readFileMatrix(fileNameIn, A);\n    logInfo<<\"  matrix: \"<<A.rows()<<\" x \"<<A.columns()<<Log::endl;\n\n    std::vector<ExpressionVariablePtr> expr({exprX, exprY, exprZ, exprArea}); // collect all expr\n    expr.insert(expr.end(), exprValues.begin(), exprValues.end());            // collect all expr\n    VariableList varList;\n    addDataVariables(A, varList);\n    std::for_each(exprValues.begin(), exprValues.end(), [&](auto expr) {if(expr) expr->simplify(varList);});\n\n    // create grid\n    // -----------\n    logStatus<<\"create grid\"<<Log::endl;\n    GriddedData grid;\n    grid.ellipsoid = Ellipsoid(a,f);\n    grid.values.resize(exprValues.size());\n    Single::forEach(A.rows(), [&](UInt i)\n    {\n      evaluateDataVariables(A, i, varList);\n      if(exprLon)\n        grid.points.push_back(grid.ellipsoid(Angle(DEG2RAD*exprLon->evaluate(varList)), Angle(DEG2RAD*exprLat->evaluate(varList)), exprHeight->evaluate(varList)));\n      else\n        grid.points.push_back(Vector3d(exprX->evaluate(varList), exprY->evaluate(varList), exprZ->evaluate(varList)));\n      if(exprArea)\n        grid.areas.push_back( exprArea->evaluate(varList) );\n      for(UInt k=0; k<exprValues.size(); k++)\n        grid.values.at(k).push_back( exprValues.at(k)->evaluate(varList) );\n    }, /*timing*/(A.rows() > 1'000'000));\n\n    // =====================================================\n\n    if(sortPoints)\n    {\n      logStatus<<\"sort points\"<<Log::endl;\n      grid.sort();\n    }\n\n    if(computeArea)\n    {\n      logStatus<<\"compute area\"<<Log::endl;\n      if(!grid.computeArea())\n        logWarning<<\"Compute areas only possible with regular rectangular grids\"<<Log::endl;\n    }\n\n    // save grid\n    // ---------\n    logStatus<<\"save grid <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOut, grid);\n    MiscGriddedData::printStatistics(grid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/matrixRectangular2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file matrixRectangular2GriddedData.cpp\n*\n* @brief Read gridded data (matrix).\n*\n* @author Torsten Mayer-Guerr\n* @date 2013-11-16\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRead gridded data (matrix).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Read gridded data (matrix).\n* @ingroup programsGroup */\nclass MatrixRectangular2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(MatrixRectangular2GriddedData, SINGLEPROCESS, \"read gridded data (matrix)\", Grid, Matrix)\nGROOPS_RENAMED_PROGRAM(AsciiMatrix2GridRectangular, MatrixRectangular2GriddedData, date2time(2020, 2, 2))\n\n/***********************************************/\n\nvoid MatrixRectangular2GriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameIn, fileNameOut;\n    Angle    startL, startB, deltaL, deltaB;\n    Double   a, f;\n    Bool     rowMajor;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut,   Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileMatrix\",       fileNameIn,    Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"rowMajor\",              rowMajor,      Config::DEFAULT,  \"1\",   \"true: data is ordered row by row, false: columnwise\");\n    readConfig(config, \"startLongitude\",        startL,        Config::MUSTSET,  \"\",    \"longitude of upper left corner of the grid\");\n    readConfig(config, \"startLatitude\",         startB,        Config::MUSTSET,  \"\",    \"latitude of upper left corner of the grid\");\n    readConfig(config, \"deltaLongitude\",        deltaL,        Config::MUSTSET,  \"\",    \"sampling, negative for east to west data\");\n    readConfig(config, \"deltaLatitude\",         deltaB,        Config::MUSTSET,  \"\",    \"sampling, negative for south to north data\");\n    readConfig(config, \"R\",                     a,             Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",     f,             Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"Read matrix file <\"<<fileNameIn<<\">\"<<Log::endl;\n    Matrix A;\n    readFileMatrix(fileNameIn, A);\n    logInfo<<\"  matrix: \"<<A.rows()<<\" x \"<<A.columns()<<Log::endl;\n\n    // order of data\n    // -------------\n    const Bool top2Down   = (deltaB>0);\n    const Bool left2Right = (deltaL>0);\n\n    // Create rectangular grid\n    // -----------------------\n    GriddedDataRectangular grid;\n    grid.ellipsoid = Ellipsoid(a,f);\n    grid.longitudes.resize(A.columns());\n    grid.latitudes.resize(A.rows());\n    grid.heights.resize(A.rows(), 0.);\n    grid.values.resize(1, Matrix(A.rows(), A.columns()));\n    for(UInt s=0; s<A.columns(); s++)\n      grid.longitudes.at((left2Right) ? s : (A.columns()-s-1)) = Angle(startL+s*Double(deltaL));\n    for(UInt z=0; z<A.rows(); z++)\n      grid.latitudes.at(((top2Down) ? z : (A.rows()-z-1))) = Angle(startB-z*Double(deltaB));\n\n    // assign data\n    // -----------\n    for(UInt z=0; z<A.rows(); z++)\n      for(UInt s=0; s<A.columns(); s++)\n      {\n        // determine index\n        UInt z1 = ((top2Down)   ? z : (A.rows()-z-1));\n        UInt s1 = ((left2Right) ? s : (A.columns()-s-1));\n        if(!rowMajor)\n          std::swap(z1, s1);\n        grid.values.at(0)(z1,s1) = A(z,s);\n      }\n\n    MiscGriddedData::printStatistics(grid);\n\n    logStatus<<\"write gridded data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOut, grid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/griddedData/timeSeries2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file timeSeries2GriddedData.cpp\n*\n* @brief Write time series as gridded data for each epoch.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-01-29\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nInterpret the data columns of \\configFile{inputfileTimeSeries}{instrument}\nas data points of a corresponding \\configClass{grid}{gridType}.\n\nFor each epoch a \\file{gridded data file}{griddedData} is written where\nthe \\config{variableLoopTime} and \\config{variableLoopIndex} are expanded for\neach point of the given time series to create the file name for this epoch\n(see \\reference{text parser}{general.parser:text}).\n\nThe number of input data columns must be a multiple of the number $n$ of grid points.\nIf \\config{isGroupedDataByPoint} is true the \\configFile{inputfileTimeSeries}{instrument} starts\nwith all data (\\verb|data0|, \\verb|data1|\\ldots) for the first point, followed by all data of the second point and so on.\nIf \\config{isGroupedDataByPoint} is false, the file starts with \\verb|data0| for all points, followed by all \\verb|data1| and so on.\n\nSee also \\program{GriddedData2TimeSeries}.\n)\";\n\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write time series as gridded data for each epoch.\n* @ingroup programsGroup */\nclass TimeSeries2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(TimeSeries2GriddedData, SINGLEPROCESS, \"Write time series as gridded data for each epoch\", Grid, TimeSeries)\n\n/***********************************************/\n\nvoid TimeSeries2GriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameGrid, fileNameInstrument;\n    std::string nameTime, nameIndex, nameCount;\n    GridPtr     gridPtr;\n    Bool        groupData;\n    Double      a, f;\n\n    readConfig(config, \"outputfilesGriddedData\", fileNameGrid,       Config::MUSTSET,  \"grid_{loopTime:%y-%m}.dat\", \"for each epoch\");\n    readConfig(config, \"variableLoopTime\",       nameTime,           Config::OPTIONAL, \"loopTime\",                  \"variable with time of each epoch\");\n    readConfig(config, \"variableLoopIndex\",      nameIndex,          Config::OPTIONAL, \"\",                          \"variable with index of current epoch (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",      nameCount,          Config::OPTIONAL, \"\",                          \"variable with total number of epochs\");\n    readConfig(config, \"inputfileTimeSeries\",    fileNameInstrument, Config::MUSTSET,  \"\",                          \"each epoch: multiple data for points (MISCVALUES)\");\n    readConfig(config, \"grid\",                   gridPtr,            Config::MUSTSET,  \"\",                          \"corresponding grid points\");\n    readConfig(config, \"isDataGroupedByPoint\",   groupData,          Config::DEFAULT, \"1\",                          \"multiple data are given point by point, otherwise: first data0 for all points, followed by all data1\");\n    readConfig(config, \"R\",                      a,                  Config::DEFAULT,  STRING_DEFAULT_GRS80_a,      \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",      f,                  Config::DEFAULT,  STRING_DEFAULT_GRS80_f,      \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read time series <\"<<fileNameInstrument<<\">\"<<Log::endl;\n    MiscValuesArc arc = InstrumentFile::read(fileNameInstrument);\n    Arc::printStatistics(arc);\n\n    logStatus<<\"create grid\"<<Log::endl;\n    GriddedData grid(Ellipsoid(a,f), gridPtr->points(), gridPtr->areas(), {});\n\n    // number of data columns\n    const UInt countPoints = grid.points.size();\n    const UInt countData   = arc.at(0).values.rows();\n    const UInt columns     = countData/countPoints;\n    if((countData < countPoints) || (countData%countPoints != 0))\n      throw(Exception(\"number of data columns (\"+countData%\"%i) in time series must be a multiple of grid points (\"s+countPoints%\"%i)\"s));\n    grid.values.resize(columns, std::vector<Double>(countPoints));\n\n    const std::vector<Time> times = arc.times();\n    VariableList varList;\n    if(!nameTime.empty())  varList.undefineVariable(nameTime);\n    if(!nameIndex.empty()) varList.undefineVariable(nameIndex);\n    if(!nameCount.empty()) varList.setVariable(nameCount, times.size());\n\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      if(!nameTime.empty())  varList.setVariable(nameTime, times.at(idEpoch).mjd());\n      if(!nameIndex.empty()) varList.setVariable(nameIndex, idEpoch);\n      logStatus<<\"write gridded data <\"<<fileNameGrid(varList)<<\">\"<<Log::endl;\n\n      for(UInt i=0; i<grid.points.size(); i++)\n        for(UInt k=0; k<columns; k++)\n          grid.values.at(k).at(i) = arc.at(idEpoch).values((groupData) ? (i*columns+k) : (i+grid.points.size()*k));\n\n      writeFileGriddedData(fileNameGrid(varList), grid);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2AllanVariance.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2AllanVariance.cpp\n*\n* @brief Compute Allan variance from instrument files.\n*\n* @author Andreas Kvas\n* @date 2018-08-02\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the overlapping Allan variance from an\n\\configFile{inputfileInstrument}{instrument}.\nThe estimate is averaged over all arcs (arcs are assumed to contain no data gaps).\n\nThe overlapping Allan variance is defined as\n\\begin{equation}\n  \\sigma^2(m\\tau_0) = \\frac{1}{2(m\\tau_0)^2(N-2m)} \\sum_{n=1}^{N-2m}(x_{n+2m}-2x_{n+m}+x_n)^2,\n\\end{equation}\nwhere $m\\tau_0$ is the averaging interval defined by the median sampling $\\tau_0$.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute Allan variance from instrument files.\n* @ingroup programsGroup */\nclass Instrument2AllanVariance\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2AllanVariance, PARALLEL, \"Compute Allan variance from instrument files.\", Instrument, Covariance)\nGROOPS_RENAMED_PROGRAM(InstrumentComputeAllanVariance, Instrument2AllanVariance, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2AllanVariance::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameInstrument, fileNameVariance;\n\n    readConfig(config, \"outputfileAllanVariance\", fileNameVariance,   Config::MUSTSET, \"\", \"column 0: averaging interval [seconds], column 1-(n-1): Allan variance for each data column\");\n    readConfig(config, \"inputfileInstrument\",     fileNameInstrument, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameInstrument);\n    const UInt dataCount = instrumentFile.dataCount(TRUE/*mustDefined*/);\n\n    UInt arcEpochCount, arcCount;\n    Time sampling = seconds2time(1.0);\n    if(Parallel::isMaster(comm))\n    {\n      arcCount = instrumentFile.arcCount();\n      std::vector<Time> times;\n\n      arcEpochCount = 0;\n      for(UInt arcNo = 0; arcNo<arcCount; arcNo++)\n      {\n        Arc arc = instrumentFile.readArc(arcNo);\n        if(arc.size() == 0)\n          continue;\n        auto arcTimes = arc.times();\n\n        arcEpochCount = std::max(arc.size(), arcEpochCount);\n        times.insert(times.end(), arcTimes.begin(), arcTimes.end());\n      }\n      sampling = medianSampling(times);\n\n      logInfo<<\"  maximum arc length: \"<<arcEpochCount<<\" epochs\"<<Log::endl;\n      logInfo<<\"  median sampling:    \"<<sampling.seconds()<<\" seconds\"<<Log::endl;\n    }\n    Parallel::broadCast(arcEpochCount, 0, comm);\n    Parallel::broadCast(arcCount,      0, comm);\n\n    logStatus<<\"compute Allan variance\"<<Log::endl;\n    Matrix allanVariance(arcEpochCount/2, dataCount+1);\n    Vector samplesPerInterval(allanVariance.rows());\n    Parallel::forEach(arcCount, [&](UInt arcNo)\n    {\n      const Matrix data = instrumentFile.readArc(arcNo).matrix();\n      for(UInt m=1; m<allanVariance.rows(); m++)\n      {\n        if(2*m >= data.rows())\n          continue;\n\n        for(UInt i=1; i<data.columns(); i++)\n          for(UInt n=0; n<data.rows()-2*m; n++)\n            allanVariance(m, i) += std::pow(data(n+2*m, i) - 2*data(n+m, i) + data(n, i), 2);\n        samplesPerInterval(m) += data.rows()-2*m;\n      }\n    }, comm);\n    Parallel::reduceSum(allanVariance, 0, comm);\n    Parallel::reduceSum(samplesPerInterval, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      for(UInt m=1; m<allanVariance.rows(); m++)\n      {\n        allanVariance.row(m) *= 0.5/(std::pow(m*sampling.seconds(), 2) * samplesPerInterval(m));\n        allanVariance(m, 0) = (m*sampling.seconds());\n      }\n\n      writeFileMatrix(fileNameVariance, allanVariance.row(1, allanVariance.rows()-1));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2CovarianceFunctionVCE.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2CovarianceFunctionVCE.cpp\n*\n* @brief Covariance functions via variance component estimation.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-07-09\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis estimates a covariance function of \\configFile{inputfileInstrument}{instrument}\nfor all selected columns with \\config{startDataFields} and \\config{countDataFields}.\nThe estimation is performed robustly via variance component estimation.\nBad arcs are downweigthed and the accuracies can be written with \\configFile{outputfileSigmasPerArc}{matrix}.\nThe length of the covariance functions are determined by the longest arc.\nAdditionaly the data can be detrended with \\configClass{parameter}{parametrizationTemporalType}\nand \\configClass{parameterPerArc}{parametrizationTemporalType}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Covariance functions via variance component estimation.\n* @ingroup programsGroup */\nclass Instrument2CovarianceFunctionVCE\n{\n  Epoch::Type                    arcType;\n  std::vector<std::vector<Time>> arcTimes;\n  std::vector<Matrix>            arcData;\n  UInt                           startData, countData;\n  ParametrizationTemporalPtr     parameter;\n  ParametrizationTemporalPtr     parameterPerArc;\n\n  Matrix N;        // normal equation matrix\n  Vector n;        // right hand sides\n  Vector x;        // solution\n  Matrix Wz;       // monte carlo vector for redundancy computation\n  Double lPl;      // =l'Pl, weighted norm of the observations\n  UInt   obsCount; // number of observations\n\n  std::vector<Matrix> W;                // cholesky of the covariance matrix (per data column)\n  Vector              sigma, sigmaNew;  // per arc\n  Matrix              CosTransform;\n  Matrix              covFunc;\n  Matrix              Psd;\n  Matrix              ePe, redundancy;  // one row for each frequency, one column for each component\n\n  void computeObservationEquation(UInt arcNo, std::vector<Matrix> &W, Vector &Wl, Matrix &WA, Matrix &WB);\n  void buildNormals(UInt arcNo);\n  void computeRedundancies(UInt arcNo);\n  Arc  computeResiduals(UInt arcNo);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2CovarianceFunctionVCE, PARALLEL, \"Covariance functions via variance component estimation\", Instrument, Covariance)\n\n/***********************************************/\n\nvoid Instrument2CovarianceFunctionVCE::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameCov, fileNameArcSigma, fileNameResiduals, fileNameSolution;\n    FileName fileNameIn;\n    UInt     iterCount;\n    countData = MAX_UINT;\n\n    readConfig(config, \"outputfileCovarianceFunction\", fileNameCov,       Config::MUSTSET,   \"\", \"covariance functions\");\n    readConfig(config, \"outputfileSigmasPerArc\",       fileNameArcSigma,  Config::OPTIONAL,  \"\", \"accuracies of each arc\");\n    readConfig(config, \"outputfileResiduals\",          fileNameResiduals, Config::OPTIONAL,  \"\", \"\");\n    readConfig(config, \"outputfileSolution\",           fileNameSolution,  Config::OPTIONAL,  \"\", \"estimated parameter vector (global part only)\");\n    readConfig(config, \"inputfileInstrument\",          fileNameIn,        Config::MUSTSET,   \"\",  \"\");\n    readConfig(config, \"startDataFields\",              startData,         Config::DEFAULT,   \"0\", \"start\");\n    readConfig(config, \"countDataFields\",              countData,         Config::OPTIONAL,  \"\",  \"number of data fields (default: all after start)\");\n    readConfig(config, \"parameter\",                    parameter,         Config::DEFAULT,   \"\",  \"data is reduced by temporal representation\");\n    readConfig(config, \"parameterPerArc\",              parameterPerArc,   Config::DEFAULT,   \"\",  \"data is reduced by temporal representation\");\n    readConfig(config, \"iterationCount\",               iterCount,         Config::DEFAULT,   \"5\",  \"number of iterations for the estimation\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    // Determine max. length of ovariance functions\n    // --------------------------------------------\n    InstrumentFile instrumentFile(fileNameIn);\n    arcType = instrumentFile.getType();\n    const UInt arcCount = instrumentFile.arcCount();\n    if(arcCount < 5)\n      throw(Exception(\"Need at least 5 arcs for a reliable covariance estimation\"));\n\n    UInt   covLength = 0;\n    Double sampling  = 0;\n    if(Parallel::isMaster(comm))\n    {\n      arcTimes.resize(arcCount);\n      arcData.resize(arcCount);\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      {\n        Arc arc = instrumentFile.readArc(arcNo);\n        arcTimes.at(arcNo) = arc.times();\n        arcData.at(arcNo)  = arc.matrix();\n        if(arc.size() > covLength)\n          sampling = medianSampling(arcTimes.at(arcNo)).seconds();\n        covLength = std::max(covLength, arc.size());\n        countData = std::min(countData, arcData.at(arcNo).columns()-1-startData);\n      }\n    }\n    Parallel::broadCast(arcTimes,  0, comm);\n    Parallel::broadCast(arcData,   0, comm);\n    Parallel::broadCast(countData, 0, comm);\n    Parallel::broadCast(covLength, 0, comm);\n    Parallel::broadCast(sampling,  0, comm);\n\n    // init arc sigmas\n    // ---------------\n    sigma = Vector(arcCount);\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      sigma(arcNo) = 1.0;\n\n    // init covariance function\n    // ------------------------\n    CosTransform = Vce::cosTransform(covLength);\n    covFunc = Vce::readCovarianceFunction(FileName(), covLength, countData, sampling);\n    Psd = CosTransform * covFunc.column(1, countData);\n\n    W.resize(countData, Matrix(covLength, Matrix::SYMMETRIC));\n    for(UInt idData=0; idData<countData; idData++)\n    {\n      for(UInt z=0; z<covLength; z++)\n        for(UInt s=z; s<covLength; s++)\n          W.at(idData)(z,s) += covFunc(s-z, 1+idData);\n      cholesky(W.at(idData));\n    }\n\n    // =============================================\n\n    // Iteration\n    // ---------\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      logStatus<<\"starting iteration \"<<iter+1<<Log::endl;\n\n      // solve normal equations\n      // ----------------------\n      if(parameter->parameterCount())\n      {\n        logStatus<<\"accumulate system of normal equations\"<<Log::endl;\n        N = Matrix(countData*parameter->parameterCount(), Matrix::SYMMETRIC);\n        n = Vector(countData*parameter->parameterCount());\n        lPl      = 0;\n        obsCount = 0;\n        Parallel::forEach(arcCount, [this](UInt arcNo) {buildNormals(arcNo);}, comm);\n\n        // collect system of normal equations\n        // ----------------------------------\n        logStatus<<\"collect system of normal equations\"<<Log::endl;\n        Parallel::reduceSum(N,        0, comm);\n        Parallel::reduceSum(n,        0, comm);\n        Parallel::reduceSum(obsCount, 0, comm);\n        Parallel::reduceSum(lPl,      0, comm);\n\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        if(Parallel::isMaster(comm))\n        {\n          x = solve(N, n);\n          logInfo<<\"  aposteriori sigma = \"<<sqrt((lPl-inner(x, n))/(obsCount-x.rows()))<<Log::endl;\n\n          // N contains now the cholesky decomposition\n          Wz = Vce::monteCarlo(x.rows(), 100); // monte carlo vector for VCE\n          triangularSolve(1., N, Wz);\n        }\n        Parallel::broadCast(x,  0, comm);\n        Parallel::broadCast(Wz, 0, comm);\n\n        if(Parallel::isMaster(comm) && !fileNameSolution.empty())\n        {\n          logStatus<<\"write solution to <\"<<fileNameSolution<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameSolution, x);\n        }\n      } // if(parameter->parameterCount())\n      Parallel::barrier(comm);\n\n      if(!fileNameResiduals.empty())\n      {\n        logStatus<<\"compute residuals\"<<Log::endl;\n        std::vector<Arc> arcs(arcCount);\n        Parallel::forEach(arcs, [this](UInt arcNo) {return computeResiduals(arcNo);}, comm);\n\n        if(Parallel::isMaster(comm))\n        {\n          logStatus<<\"write residual file <\"<<fileNameResiduals<<\">\"<<Log::endl;\n          InstrumentFile::write(fileNameResiduals, arcs);\n        }\n      }\n\n      logStatus<<\"compute redundancies\"<<Log::endl;\n      sigmaNew = Vector(arcCount);\n      ePe = redundancy = Matrix(covLength, countData);\n      Parallel::forEach(arcCount, [this](UInt arcNo) {computeRedundancies(arcNo);}, comm);\n\n      // sigmas per arc\n      // --------------\n      Parallel::reduceSum(sigmaNew, 0, comm);\n      if(Parallel::isMaster(comm))\n      {\n        sigma = sigmaNew;\n        const Double sigma0 = Vce::meanSigma(sigma);\n        sigma *= 1./sigma0;\n        logInfo<<\"   sigma per arc (median): \"<<sigma0<<Log::endl;\n\n        if(!fileNameArcSigma.empty())\n        {\n          logStatus<<\"write arc sigma file <\"<<fileNameArcSigma<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameArcSigma, sigma);\n        }\n      }\n      Parallel::broadCast(sigma, 0, comm);\n\n      // estimate new PSD through variance component estimation\n      // ------------------------------------------------------\n      logStatus<<\"compute psd through variance component estimation\"<<Log::endl;\n      Parallel::reduceSum(ePe, 0, comm);\n      Parallel::reduceSum(redundancy, 0, comm);\n      if(Parallel::isMaster(comm))\n      {\n        Double maxFactor = 0;\n        Vce::estimatePsd(ePe, redundancy, Psd, maxFactor);\n        logInfo<<\"  max. PSD adjustment factor: \"<<maxFactor<<Log::endl;\n      } // if(Parallel::isMaster(comm))\n      Parallel::broadCast(Psd, 0, comm);\n      copy(CosTransform*Psd, covFunc.column(1, Psd.columns())); // compute new covariance function\n\n      for(UInt idData=0; idData<countData; idData++)\n      {\n        W.at(idData) = Matrix(covLength, Matrix::SYMMETRIC);\n        for(UInt z=0; z<covLength; z++)\n          for(UInt s=z; s<covLength; s++)\n              W.at(idData)(z,s) += covFunc(s-z, 1+idData);\n        cholesky(W.at(idData));\n      }\n\n      if(Parallel::isMaster(comm) && !fileNameCov.empty())\n      {\n        logStatus<<\"write covariance function file <\"<<fileNameCov<<\">\"<<Log::endl;\n        writeFileMatrix(fileNameCov, covFunc);\n      }\n    } // for(iter)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Instrument2CovarianceFunctionVCE::computeObservationEquation(UInt arcNo, std::vector<Matrix> &W, Vector &Wl, Matrix &WA, Matrix &WB)\n{\n  try\n  {\n    const UInt countEpoch = arcData.at(arcNo).rows();\n    parameterPerArc->setInterval(arcTimes.at(arcNo).front(), arcTimes.at(arcNo).back()+medianSampling(arcTimes.at(arcNo)), TRUE);\n\n    W.resize(countData);\n    Wl = Vector(countEpoch*countData);\n    WA = Matrix(Wl.rows(), countData*parameter->parameterCount());\n    WB = Matrix(Wl.rows(), countData*parameterPerArc->parameterCount());\n\n    for(UInt idData=0; idData<countData; idData++)\n    {\n      // observations\n      copy(arcData.at(arcNo).column(1+startData+idData), Wl.row(idData*countEpoch, countEpoch));\n\n      // design matrix\n      for(UInt idEpoch=0; idEpoch<arcTimes.at(arcNo).size(); idEpoch++)\n      {\n        if(parameter->parameterCount())\n          copy(parameter->factors(arcTimes.at(arcNo).at(idEpoch)).trans(),\n               WA.slice(idData*countEpoch+idEpoch, idData*parameter->parameterCount(), 1, parameter->parameterCount()));\n        if(parameterPerArc->parameterCount())\n          copy(parameterPerArc->factors(arcTimes.at(arcNo).at(idEpoch)).trans(),\n               WB.slice(idData*countEpoch+idEpoch, idData*parameterPerArc->parameterCount(), 1, parameterPerArc->parameterCount()));\n      }\n\n      // decorrelation\n      W.at(idData) = sigma(arcNo) * this->W.at(idData).slice(0, 0, countEpoch, countEpoch);\n      if(Wl.size()) triangularSolve(1., W.at(idData).trans(), Wl.row(idData*countEpoch, countEpoch));\n      if(WA.size()) triangularSolve(1., W.at(idData).trans(), WA.row(idData*countEpoch, countEpoch));\n      if(WB.size()) triangularSolve(1., W.at(idData).trans(), WB.row(idData*countEpoch, countEpoch));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Instrument2CovarianceFunctionVCE::buildNormals(UInt arcNo)\n{\n  try\n  {\n    std::vector<Matrix> W;\n    Vector Wl;\n    Matrix WA, WB;\n    computeObservationEquation(arcNo, W, Wl, WA, WB);\n\n    // eliminate arc dependent parameters\n    Vector tau;\n    if(WB.size())\n    {\n      tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl); // transform observations: l:= Q'l\n      QTransMult(WB, tau, WA); // transform design matrix A:=Q'A\n    }\n    // use only nullspace of design matrix WB\n    MatrixSlice A_bar( WA.row(WB.columns(), WA.rows()-WB.columns()) );\n    MatrixSlice l_bar( Wl.row(WB.columns(), Wl.rows()-WB.columns()) );\n\n    // build normals\n    this->lPl      += quadsum(l_bar);\n    this->obsCount += l_bar.rows();\n    matMult(1., A_bar.trans(), l_bar, n);\n    rankKUpdate(1., A_bar, N);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Instrument2CovarianceFunctionVCE::computeRedundancies(UInt arcNo)\n{\n  try\n  {\n    std::vector<Matrix> W;\n    Vector Wl;\n    Matrix WA, WB;\n    computeObservationEquation(arcNo, W, Wl, WA, WB);\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    if(WB.size())\n    {\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl);           // transform observations: l:= Q'l\n      Wl.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n      QMult(WB, tau, Wl);                // back transformation\n\n      if(WA.size())\n      {\n        QTransMult(WB, tau, WA); // transform design matrix A:=Q'A\n        WA.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n        QMult(WB, tau, WA); // back transformation\n      }\n\n      generateQ(WB, tau);\n      WB.setType(Matrix::GENERAL);\n    }\n\n    // decorrelated residuals\n    // ----------------------\n    Matrix We = Wl;\n    Matrix WAz(Wl.rows(), Wz.columns());\n    if(WA.size()) matMult(-1., WA,  x, We);\n    if(WA.size()) matMult( 1., WA, Wz, WAz);\n\n    // Variance component estimation\n    // -----------------------------\n    const UInt countEpoch = Wl.rows()/countData;\n    std::vector<UInt> index(countEpoch);\n    for(UInt i=0; i<index.size(); i++)\n      index.at(i) = i;\n    Double ePeSum=0, redundancySum=0;\n\n    for(UInt idData=0; idData<countData; idData++)\n    {\n      Matrix R;\n      Vector WWe;\n      Vce::redundancy(W.at(idData),\n                      We.row(idData*countEpoch, countEpoch),\n                      WAz.row(idData*countEpoch, countEpoch),\n                      WB.row(idData*countEpoch, countEpoch),\n                      R, WWe);\n      Vce::psd(R, WWe, index, sigma(arcNo), CosTransform, Psd.column(idData),\n               ePe.column(idData), redundancy.column(idData), ePeSum, redundancySum);\n    }\n    sigmaNew(arcNo) = sqrt(ePeSum/redundancySum) * sigma(arcNo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nArc Instrument2CovarianceFunctionVCE::computeResiduals(UInt arcNo)\n{\n  try\n  {\n    std::vector<Matrix> W;\n    Vector Wl;\n    Matrix WA, WB;\n    computeObservationEquation(arcNo, W, Wl, WA, WB);\n\n    // decorrelated residuals\n    if(WA.size())\n      matMult(-1., WA, x, Wl);\n    if(WB.size())\n      reduceLeastSquaresFit(WB, Wl);\n\n    // remove decorrelation\n    const UInt countEpoch = Wl.rows()/countData;\n    for(UInt idData=0; idData<countData; idData++)\n      triangularMult(1., W.at(idData).trans(), Wl.row(idData*countEpoch, countEpoch));\n\n    // observations\n    Matrix data = arcData.at(arcNo);\n    for(UInt idData=0; idData<countData; idData++)\n      copy(Wl.row(idData*countEpoch, countEpoch), data.column(1+startData+idData));\n\n    return Arc(arcTimes.at(arcNo), arcData.at(arcNo), arcType);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2CrossCorrelationFunction.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2CrossCorrelationFunction.cpp\n*\n* @brief Empirical computation of the correlation between two instrument files.\n*\n* @author Andreas Kvas\n* @date 2018-01-01\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the cross correlation between all corresponding data columns\nin two \\file{instrument files}{instrument}. The instrument files must be synchronized (\\program{InstrumentSynchronize}).\nThe \\configFile{outputfileCorrelation}{matrix} is a matrix with the first column containing the time lag followed by\ncross-correlation function for each data column. The maximum lag is defined by the maximum arc length.\n\nThe correlation is based on the unbiased estimate of the cross-covariance between data columns $x$ and $y$,\n\\begin{equation}\n  \\sigma_{xy}(h) = \\frac{1}{N}\\sum_{k=1} x_{k+h} y_k,\n\\end{equation}\nwhich is averaged over all arcs. From this estimate, the correlation for each lag is then computed via\n\\begin{equation}\n  r_{xy}(h) = \\frac{\\sigma_{xy}(h)}{\\sigma_x(0)\\sigma_y(0)},\n\\end{equation}\nwhich is the ratio between the biased estimates of the cross-covariance at lag $h$ and the auto-covariance of the individual data columns.\n\nFor instrument with data gaps, lag bins without any data are set to NAN.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Empirical computation of the correlation between two instrument files.\n* @ingroup programsGroup */\nclass Instrument2CrossCorrelationFunction\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2CrossCorrelationFunction, PARALLEL, \"Empirical computation of the correlation between two instrument files.\", Instrument, Statistics)\nGROOPS_RENAMED_PROGRAM(InstrumentComputeCorrelation, Instrument2CrossCorrelationFunction, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2CrossCorrelationFunction::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outputName;\n    FileName inputName, inputNameReference;\n\n    readConfig(config, \"outputfileCorrelation\",         outputName,         Config::MUSTSET, \"\", \"column 1: time lag, column 2..n cross-correlation\");\n    readConfig(config, \"inputfileInstrument\",           inputName,          Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrumentReference\",  inputNameReference, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // check input\n    // -----------\n    InstrumentFile instrumentFile(inputName);\n    InstrumentFile instrumentFileReference(inputNameReference);\n    InstrumentFile::checkArcCount({instrumentFile, instrumentFileReference});\n\n    const UInt arcCount  = instrumentFile.arcCount();\n    const UInt dataCount = std::min(instrumentFile.dataCount(TRUE/*mustDefined*/), instrumentFileReference.dataCount(TRUE/*mustDefined*/));\n\n    // determine arc length and data fields\n    // ------------------------------------\n    UInt   maxLag;\n    Double sampling = 1.0;\n    if(Parallel::isMaster(comm))\n    {\n      std::vector<Time> times;\n      Time maxArcLen;\n      for(UInt arcNo = 0; arcNo<arcCount; arcNo++)\n      {\n        Arc arc = instrumentFile.readArc(arcNo);\n        if(arc.size() == 0)\n          continue;\n        std::vector<Time> arcTimes = arc.times();\n        maxArcLen = std::max(arcTimes.back() - arcTimes.front(), maxArcLen);\n        times.insert(times.end(), arcTimes.begin(), arcTimes.end());\n      }\n      sampling = medianSampling(times).seconds();\n      maxLag   = static_cast<UInt>(std::round(maxArcLen.seconds()/sampling)+1);\n      logInfo<<\"  maximum arc length: \"<<maxLag<<\" epochs\"<<Log::endl;\n      logInfo<<\"  median sampling:    \"<<sampling<<\" seconds\"<<Log::endl;\n    }\n    Parallel::broadCast(maxLag,   0, comm);\n    Parallel::broadCast(sampling, 0, comm);\n\n    // estimate the covariance for each arc, then reduce\n    // -------------------------------------------------\n    logStatus<<\"Estimate cross-correlation for each arc\"<<Log::endl;\n    Vector count(maxLag*2-1);\n    Vector autoCovarianceX(dataCount);\n    Vector autoCovarianceY(dataCount);\n    Matrix crossCovariance(maxLag*2-1, dataCount+1);\n    Parallel::forEach(arcCount, [&](UInt arcNo)\n    {\n      const Arc arc    = instrumentFile.readArc(arcNo);\n      const Arc arcRef = instrumentFileReference.readArc(arcNo);\n      if(arc.size() == 0)\n        return;\n\n      const Matrix X = arc.matrix();\n      const Matrix Y = arcRef.matrix();\n\n      for(UInt i=0; i<dataCount; i++)\n        autoCovarianceX(i) += quadsum(X.column(i+1));\n      for(UInt i=0; i<dataCount; i++)\n        autoCovarianceY(i) += quadsum(Y.column(i+1));\n\n      std::vector<Time> times = arc.times();\n      if(isRegular(times)) // fast version possible?\n      {\n        count(maxLag-1) += X.rows();\n        for(UInt col=1; col<crossCovariance.columns(); col++)\n          crossCovariance(maxLag-1, col) += inner(X.column(col), Y.column(col));\n        for(UInt h=1; h<X.rows(); h++)\n        {\n          count(maxLag-1-h) += X.rows()-h;\n          count(maxLag-1+h) += X.rows()-h;\n          for(UInt col=1; col<crossCovariance.columns(); col++)\n          {\n            crossCovariance(maxLag-1-h, col) += inner(X.slice(0, col, X.rows()-h, 1), Y.slice(h, col, X.rows()-h, 1));\n            crossCovariance(maxLag-1+h, col) += inner(X.slice(h, col, X.rows()-h, 1), Y.slice(0, col, X.rows()-h, 1));\n          }\n        }\n      }\n      else // general case\n      {\n        for(UInt i=0; i<X.rows(); i++)\n          for(UInt k=0; k<Y.rows(); k++)\n          {\n            const UInt idx = static_cast<UInt>(std::round((times.at(i)-times.at(k)).seconds()/sampling)+maxLag-1);\n            count(idx)++;\n            for(UInt col=1; col<crossCovariance.columns(); col++)\n              crossCovariance(idx, col) += X(i, col) * Y(k, col);\n          }\n      }\n    }, comm);\n    Parallel::reduceSum(count, 0, comm);\n    Parallel::reduceSum(autoCovarianceX, 0, comm);\n    Parallel::reduceSum(autoCovarianceY, 0, comm);\n    Parallel::reduceSum(crossCovariance, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      autoCovarianceX *= 1./count(maxLag-1);\n      autoCovarianceY *= 1./count(maxLag-1);\n      for(UInt i=0; i<count.rows(); i++)\n        crossCovariance.row(i) *= 1./count(i);\n\n      for(UInt i=0; i<dataCount; i++)\n        crossCovariance.column(i+1) *= 1.0/std::sqrt(autoCovarianceX(i)*autoCovarianceY(i));\n\n      for(UInt h=0; h<maxLag; h++)\n      {\n        crossCovariance(maxLag-h-1, 0) = -sampling*h;\n        crossCovariance(h+maxLag-1, 0) =  sampling*h;\n      }\n\n      logStatus<<\"write cross correlation to <\"<<outputName<<\">\"<<Log::endl;\n      writeFileMatrix(outputName, crossCovariance);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2Histogram.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2Histogram.cpp\n*\n* @brief Compute a histogram (arc-wise) from an instrument file\n*\n* @author Andreas Kvas\n* @date 2017-07-09\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the arc-wise histogram from an \\file{instrument file}{instrument}.\nThe output is a \\file{matrix}{matrix} with the first column containing the lower bound of each bin.\nThe other columns contain the histograms for each arc.\n\n\\fig{!hb}{0.8}{instrument2Histogram}{fig:instrument2Histogram}{GRACE range-rate residuals of one month (one arc) divided into 50 bins.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute a histogram from a time series.\n* @ingroup programsGroup */\nclass Instrument2Histogram\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2Histogram, PARALLEL, \"compute a histogram from an instrument file\", Instrument, Statistics)\nGROOPS_RENAMED_PROGRAM(InstrumentComputeHistogram, Instrument2Histogram, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2Histogram::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameIn, fileNameOut;\n    UInt             selectData;\n    ExpressionVariablePtr exprMin, exprMax;\n    Bool             relative = TRUE;\n    Bool             cumulative = FALSE;\n    UInt             binCount = 0;\n\n    readConfig(config, \"outputfileMatrix\",     fileNameOut, Config::MUSTSET,  \"\",  \"column 1: lower bin bound; columns 2 to N: histogram of each arc\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"selectDataField\",      selectData,  Config::DEFAULT,  \"0\", \"select channel for histogram computation\");\n    readConfig(config, \"binCount\",             binCount,    Config::OPTIONAL, \"\",  \"(default: Freedman-Diaconis' choice, maximum of all channels)\");\n    readConfig(config, \"lowerBound\",           exprMin,     Config::DEFAULT,  \"dataMin\", \"lower bound for bins (default: global minimum, data values outside are ignored)\");\n    readConfig(config, \"upperBound\",           exprMax,     Config::DEFAULT,  \"dataMax\", \"upper bound for bins (default: global maximum, data values outside are ignored)\");\n    readConfig(config, \"relative\",             relative,    Config::DEFAULT,  \"1\", \"output relative frequencies\");\n    readConfig(config, \"cumulative\",           cumulative,  Config::DEFAULT,  \"0\", \"accumulate frequencies\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"reading instrument file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameIn);\n    const UInt arcCount = instrumentFile.arcCount();\n\n    // collect all data\n    // ----------------\n    std::vector<std::vector<Double>> arcWiseData(arcCount);\n    Parallel::forEach(arcWiseData, [&](UInt arcNo)\n    {\n      Matrix data = instrumentFile.readArc(arcNo).matrix();\n      std::vector<Double> values(data.rows());\n      for(UInt k=0; k<data.rows(); k++)\n        values.at(k) = data(k, selectData+1);\n      return values;\n    }, comm);\n    Parallel::broadCast(arcWiseData, 0, comm);\n\n    // determine bins\n    // --------------\n    std::vector<Double> bins;\n    if(Parallel::isMaster(comm))\n    {\n      std::vector<Double> globalData;\n      for(UInt arcNo=0; arcNo<arcWiseData.size(); arcNo++)\n        globalData.insert(globalData.end(), arcWiseData[arcNo].begin(), arcWiseData[arcNo].end());\n      std::sort(globalData.begin(), globalData.end());\n\n      VariableList varList;\n      varList.setVariable(\"dataMin\", globalData.front());\n      varList.setVariable(\"dataMax\", globalData.back());\n      const Double lowerBound = exprMin->evaluate(varList);\n      const Double upperBound = exprMax->evaluate(varList);\n\n      const UInt originalSize = globalData.size();\n      globalData.erase(std::remove_if(globalData.begin(), globalData.end(), [lowerBound, upperBound](Double x) {return (x<lowerBound) || (x>upperBound);}), globalData.end());\n      logInfo<<\"Discarded \"<<originalSize-globalData.size()<<\" elements.\"<<Log::endl;\n\n      // compute number of bins based on Freedman-Diaconis' choice\n      if(binCount == 0)\n      {\n        const UInt   count       = (globalData.size()+1)/2;\n        const Double q1          = globalData[count / 2];\n        const Double q3          = globalData[3 * count / 2];\n        const Double binSize     = 2.0 * (q3 - q1) / std::pow(globalData.size(), 1./3.);\n        const UInt   binCountMax = 100;\n        binCount = std::min(binCountMax, static_cast<UInt>(std::ceil((upperBound-lowerBound)/binSize)));\n        if(binCount == binCountMax)\n          logWarning << \"Bin count set to a maximum of <\" << binCountMax << \">\" << Log::endl;\n      }\n      logInfo<<\"Sort data into \"<<binCount<<\" bins in the range of [\"<<lowerBound<<\", \"<<upperBound<<\"]\"<<Log::endl;\n\n      bins.resize(1, lowerBound); // intervals\n      for(UInt k=0; k<binCount; k++)\n        bins.push_back(bins.back() + (upperBound-lowerBound)/binCount);\n      bins.back() = upperBound; // make sure upper bound is correct\n    }\n    Parallel::broadCast(bins, 0, comm);\n\n    // compute histogram\n    // -----------------\n    logStatus<<\"compute histogram\"<<Log::endl;\n    Matrix histogram(bins.size()-1, arcCount+1); // first column: lower bin bound\n\n    Parallel::forEach(arcCount, [&](UInt arcNo)\n    {\n      std::vector<Double> data = arcWiseData.at(arcNo);\n      for(UInt k = 0; k<bins.size()-2; k++)\n        histogram(k, arcNo+1) = std::count_if(data.begin(), data.end(), [&, bins, k](Double v){ return (v>=bins[k] && v<bins[k+1]); });\n\n      // last bin includes upper bound\n      histogram(bins.size()-2, arcNo+1) = std::count_if(data.begin(), data.end(), [&, bins](Double v){ return (v>=bins[bins.size()-2] && v<=bins.back()); });\n\n      if(relative)\n      {\n        UInt count = std::count_if(data.begin(), data.end(), [&, bins](Double v){ return (v>=bins.front() && v<=bins.back()); });\n        histogram.column(arcNo+1) *= 1./count;\n      }\n      if(cumulative)\n      {\n        for(UInt k = 1; k<bins.size()-1; k++)\n          histogram(k, arcNo+1) += histogram(k-1, arcNo+1);\n      }\n    }, comm);\n    Parallel::reduceSum(histogram, 0, comm);\n\n    logStatus<<\"write histogram to <\"<<fileNameOut<<\">\"<<Log::endl;\n    if(Parallel::isMaster(comm))\n    {\n      for(UInt k = 0; k<bins.size()-1; k++)\n        histogram(k, 0) = bins.at(k);\n      writeFileMatrix(fileNameOut, histogram);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2PowerSpectralDensity.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2PowerSpectralDensity.cpp\n*\n* @brief Compute PSD from instrument files.\n*\n* @author Andreas Kvas\n* @date 2016-02-02\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the power spectral density (PSD) for all data fields in an \\file{instrument file}{instrument}.\nThe PSD is computed using Lomb's method. For each arc and each frequency $f$, a sinusoid is fit to the data\n\\begin{equation}\n  l_i = a \\cos(2\\pi f t_i) + b \\sin(2\\pi f t_i) + e_i\n\\end{equation}\n\nThe PSD for this frequency is then computed by forming the square sum of adjusted observations:\n\\begin{equation}\n  P(f) = \\sum_i \\hat{l}^2_i.\n\\end{equation}\n\nThe resulting PSD is the average over all arcs. For regularly sampled time series,\nthis method yields the same results as FFT based PSD estimates.\n\nA regular frequency grid based on the longest arc and the median sampling is computed.\nThe maximum number of epochs per arc is determined by\n\\begin{equation}\n  N = \\frac{t_{\\text{end}} - t_{\\text{start}}}{\\Delta t_{\\text{median}} } + 1,\n\\end{equation}\nthe Nyquist frequency is given by\n\\begin{equation}\n  f_{\\text{nyq}} = \\frac{1}{2\\Delta t_{\\text{median}}}.\n\\end{equation}\n\nIf it is suspected that \\configFile{inputfileInstrument}{instrument} contains secular variations,\nthe input should be detrended using \\program{InstrumentDetrend}.\n\nSee also \\program{Instrument2CovarianceFunctionVCE},\n\\program{CovarianceFunction2PowerSpectralDensity}, \\program{PowerSpectralDensity2CovarianceFunction}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute PSD from instrument files.\n* @ingroup programsGroup */\nclass Instrument2PowerSpectralDensity\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2PowerSpectralDensity, PARALLEL, \"Compute PSD from instrument files.\", Instrument, Covariance)\nGROOPS_RENAMED_PROGRAM(InstrumentComputePSD, Instrument2PowerSpectralDensity, date2time(2018, 7, 18))\nGROOPS_RENAMED_PROGRAM(InstrumentComputePsd, Instrument2PowerSpectralDensity, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2PowerSpectralDensity::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameInstrument, fileNamePSD;\n\n    readConfig(config, \"outputfilePSD\",        fileNamePSD,         Config::MUSTSET,  \"\", \"estimated PSD: column 0: frequency vector, column 1-(n-1): PSD estimate for each channel\");\n    readConfig(config, \"inputfileInstrument\",  fileNameInstrument,  Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameInstrument);\n    const UInt arcCount  = instrumentFile.arcCount();\n    const UInt dataCount = instrumentFile.dataCount(TRUE/*mustDefined*/);\n\n    Vector freqs;\n    UInt   arcEpochCount;\n    Double sampling = 1.0;\n    if(Parallel::isMaster(comm))\n    {\n      std::vector<Time> times;\n      Time maxArcLen;\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      {\n        Arc arc = instrumentFile.readArc(arcNo);\n        if(arc.size() == 0)\n          continue;\n        std::vector<Time> arcTimes = arc.times();\n        maxArcLen = std::max(arcTimes.back() - arcTimes.front(), maxArcLen);\n        times.insert(times.end(), arcTimes.begin(), arcTimes.end());\n      }\n      sampling      = medianSampling(times).seconds();\n      arcEpochCount = static_cast<UInt>(std::round(maxArcLen.seconds()/sampling)+1);\n      logInfo<<\"  maximum arc length: \"<<arcEpochCount<<\" epochs\"<<Log::endl;\n      logInfo<<\"  median sampling:    \"<<sampling<<\" seconds\"<<Log::endl;\n\n      freqs = Fourier::frequencies(arcEpochCount, sampling);\n    }\n    Parallel::broadCast(freqs, 0, comm);\n    Parallel::broadCast(arcEpochCount, 0, comm);\n\n    logStatus<<\"compute PSD\"<<Log::endl;\n    Matrix PSD(freqs.rows(), dataCount+1);\n    Parallel::forEach(arcCount, [&](UInt arcNo)\n    {\n      Arc arc = instrumentFile.readArc(arcNo);\n      Matrix data = arc.matrix();\n\n      // time vector\n      Vector t(arc.size());\n      for(UInt i=0; i<t.rows(); i++)\n        t(i) = (arc.at(i).time-arc.at(0).time).seconds();\n\n      // square sum of observations\n      Vector lPl(data.columns()-1);\n      for(UInt i=0; i<lPl.rows(); i++)\n        lPl(i) = quadsum(data.column(i+1));\n\n      // estimate the power of each frequency\n      for(UInt k=0; k<freqs.size(); k++)\n      {\n        Matrix l = data.column(1, data.columns()-1);\n        Matrix A(l.rows(), 2);\n        const Double f = 2*PI*freqs.at(k);\n        for(UInt i=0; i<A.rows(); i++)\n        {\n          A(i, 0) = std::cos(f*t(i));\n          A(i, 1) = std::sin(f*t(i));\n        }\n        if((freqs.at(k) == 0) || (std::fabs(freqs.at(k)*sampling-0.5) < 1e-5)) // zero or nyquist freq?\n          A = A.column(0);\n\n        reduceLeastSquaresFit(A, l); // l = e_hat\n        for(UInt i=0; i<l.columns(); i++)\n          PSD(k, i+1) += lPl(i) - quadsum(l.column(i));\n      }\n    }, comm);\n    Parallel::reduceSum(PSD, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      PSD *= sampling/arcCount; // PSD unit: input^2/Hz\n      copy(freqs, PSD.column(0));\n      logStatus<<\"write PSD to file <\"<<fileNamePSD<<\">\"<<Log::endl;\n      writeFileMatrix(fileNamePSD, PSD);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2RmsPlotGrid.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2RmsPlotGrid.cpp\n*\n* @brief Compute RMS plot grid from instrument file(s) containing 3D data (e.g. orbits, station positions).\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2016-11-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes an RMS plot grid from one or more \\configFile{inputfileInstrument}{instrument}\ncontaining 3D data (e.g. orbits or station positions), which can then be plotted as gridded data in \\program{PlotGraph}.\nThe RMS is computed from the difference between \\configFile{inputfileInstrument}{instrument} and\n\\configFile{inputfileInstrumentReference}{instrument}.\nAll instrument files must be synchronized (see \\program{InstrumentSynchronize}).\n\nEach separate \\configFile{inputfileInstrument}{instrument} represents an entry (e.g. a satellite or station)\nin the resulting grid. Therefore, providing, for example, 32 orbit files of GPS satellites\nresults in a grid with columns: mjd, id (0-31), rms.\n\nThe first three data columns of the instrument data are considered for computation of the RMS values.\nThe \\config{factor} can be set to, for example, sqrt(3) to get 3D instead of 1D RMS values.\n\nIf \\configClass{timeIntervals}{timeSeriesType} are provided, each \\configFile{inputfileInstrument}{instrument}\nand \\configFile{inputfileInstrumentReference}{instrument} serves as a template with variable \\verb|loopTime|.\nThis allows concatenation of instrument files, for example to create a month-long RMS plot grid from daily GPS\norbit files (see below).\n\nHelmert parameters between the two frames can be estimated each epoch optionally if\n\\config{estimateShift}, \\config{estimateScale}, or \\config{estimateRotation} are set.\nIt uses a \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\n\\fig{!hb}{0.8}{instrument2RmsPlotGrid}{fig:instrument2RmsPlotGrid}{Comparison of estimated GPS orbits with IGS final solution.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute RMS plot grid from instrument file(s) containing 3D data (e.g. orbits, station positions).\n* @ingroup programsGroup */\nclass Instrument2RmsPlotGrid\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2RmsPlotGrid, SINGLEPROCESS, \"Compute RMS plot grid from instrument file(s) containing 3D data (e.g. orbits, station positions).\", Instrument, Plot, Gnss)\n\n/***********************************************/\n\nvoid Instrument2RmsPlotGrid::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOutRmsPlotGrid;\n    FileName              fileNameHelmertTimeSeries;\n    std::vector<FileName> fileNameInInstrument, fileNameInInstrumentRef;\n    TimeSeriesPtr         timesIntervalPtr;\n    Double                factor;\n    Bool                  estimateShift, estimateScale, estimateRotation;\n    Double                huber, huberPower;\n    UInt                  iterCount;\n\n    renameDeprecatedConfig(config, \"intervals\", \"timeIntervals\", date2time(2020, 7, 14));\n\n    readConfig(config, \"outputfileRmsPlotGrid\",        fileNameOutRmsPlotGrid,    Config::OPTIONAL, \"\",     \"columns: mjd, id, rms\");\n    readConfig(config, \"outputfileHelmertTimeSeries\",  fileNameHelmertTimeSeries, Config::OPTIONAL, \"\",     \"columns: mjd, tx, ty, tz, scale, rx, ry, rz\");\n    readConfig(config, \"inputfileInstrument\",          fileNameInInstrument,      Config::MUSTSET,  \"\",     \"one file per satellite/station\");\n    readConfig(config, \"inputfileInstrumentReference\", fileNameInInstrumentRef,   Config::MUSTSET,  \"\",     \"one file per satellite/station, same order as above\");\n    readConfig(config, \"timeIntervals\",                timesIntervalPtr,          Config::DEFAULT,  \"\",     \"for {loopTime} variable in inputfile\");\n    readConfig(config, \"factor\",                       factor,                    Config::DEFAULT,  \"1\",    \"e.g. sqrt(3) for 3D RMS\");\n    readConfig(config, \"estimateShift\",                estimateShift,             Config::DEFAULT,  \"1\",    \"coordinate center every epoch\");\n    readConfig(config, \"estimateScale\",                estimateScale,             Config::DEFAULT,  \"1\",    \"scale factor of position every epoch\");\n    readConfig(config, \"estimateRotation\",             estimateRotation,          Config::DEFAULT,  \"1\",    \"rotation every epoch\");\n    readConfig(config, \"huber\",                        huber,                     Config::DEFAULT,  \"2.5\", \"for robust least squares\");\n    readConfig(config, \"huberPower\",                   huberPower,                Config::DEFAULT,  \"1.5\", \"for robust least squares\");\n    readConfig(config, \"huberMaxIteration\",            iterCount,                 Config::DEFAULT,  \"30\",  \"(maximum) number of iterations for robust estimation\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    // init time intervals\n    // -------------------\n    std::vector<Time> timesInterval;\n    if(timesIntervalPtr)\n      timesInterval = timesIntervalPtr->times();\n\n    VariableList fileNameVariableList;\n    if(timesInterval.size())\n      addTimeVariables(fileNameVariableList);\n\n    const UInt countInterval   = timesInterval.size() ? timesInterval.size()-1 : 1;\n    const UInt countInstrument = fileNameInInstrument.size();\n\n    // ======================================================\n\n    // read instrument data and compute RMS plot grid\n    // -----------------------------------------\n    logStatus<<\"Reading instrument data and computing RMS plot grid\"<<Log::endl;\n    if(fileNameInInstrument.size() != fileNameInInstrumentRef.size())\n      throw Exception(\"Number of instrument and instrument reference files does not match: \" + fileNameInInstrument.size() % \"%i\"s + \" != \" + fileNameInInstrumentRef.size() % \"%i\"s);\n\n    Matrix RmsPlotGrid(countInterval*countInstrument,3);\n    std::vector<Vector> helmertTimeSeries;\n    UInt countOutput = 0;\n    Single::forEach(countInterval, [&](UInt idInterval)\n    {\n      Time time;\n      if(timesInterval.size())\n      {\n        evaluateTimeVariables(idInterval, timesInterval.at(idInterval), timesInterval.at(idInterval+1), fileNameVariableList);\n        time = 0.5*(timesInterval.at(idInterval+1)+timesInterval.at(idInterval));\n      }\n\n      // read instrument data of current interval\n      // ----------------------------------------\n      UInt epochCount = MAX_UINT;\n      std::vector<Arc> arcsInstrument(countInstrument), arcsInstrumentRef(countInstrument);\n      for(UInt idInstrument=0; idInstrument<countInstrument; idInstrument++)\n      {\n        Arc arc;\n        try\n        {\n          arc = InstrumentFile::read(fileNameInInstrument.at(idInstrument)(fileNameVariableList));\n        }\n        catch(std::exception &) {} // --> arc.size() == 0, see subsequent if()\n\n        if(!arc.size())\n        {\n          logWarning << \"Instrument file <\" << fileNameInInstrument.at(idInstrument)(fileNameVariableList) << \"> not found or empty, skipping.\" << Log::endl;\n          continue;\n        }\n\n        Arc arcRef;\n        try\n        {\n          arcRef = InstrumentFile::read(fileNameInInstrumentRef.at(idInstrument)(fileNameVariableList));\n        }\n        catch(std::exception &) {} // --> arcRef.size() == 0, see subsequent if()\n\n        if(!arcRef.size())\n        {\n          logWarning << \"Instrument reference file <\" << fileNameInInstrumentRef.at(idInstrument)(fileNameVariableList) << \"> not found or empty, skipping.\" << Log::endl;\n          continue;\n        }\n\n        // check if data of reference file matches instrument file\n        if(arc.size() != arcRef.size())\n          throw Exception(\"Instrument and instrument reference epoch counts do not match: \" + arc.size() % \"%i\"s + \" != \" + arcRef.size() % \"%i\"s + \" for files <\" +\n                          fileNameInInstrument.at(idInstrument)(fileNameVariableList).str() + \"> and <\" + fileNameInInstrumentRef.at(idInstrument)(fileNameVariableList).str() + \">\");\n\n        arcsInstrument.at(idInstrument)    = arc;\n        arcsInstrumentRef.at(idInstrument) = arcRef;\n        epochCount = std::min(epochCount, arc.size());\n      }\n\n      if(epochCount == MAX_UINT)\n      {\n        logWarning<<\"No instrument data found. continue with next epoch\"<<Log::endl;\n        return;\n      }\n\n      // Estimate Helmert transformation\n      // -------------------------------\n      Matrix l(3*arcsInstrument.size(), epochCount);\n      for(UInt idEpoch=0; idEpoch<epochCount; idEpoch++)\n      {\n        Time timeEpoch;\n        Matrix A(3*arcsInstrument.size(), 3*estimateShift+estimateScale+3*estimateRotation);\n        for(UInt idInstrument=0; idInstrument<countInstrument; idInstrument++)\n        {\n          if(arcsInstrument.at(idInstrument).size() == 0)\n            continue;\n          timeEpoch = arcsInstrument.at(idInstrument).at(idEpoch).time;\n\n          const Vector3d pos(arcsInstrument.at(idInstrument).at(idEpoch).data().row(0,3));\n          const Vector3d posRef(arcsInstrumentRef.at(idInstrument).at(idEpoch).data().row(0,3));\n          const Vector3d diff = pos - posRef;\n          l(3*idInstrument+0, idEpoch) = diff.x();\n          l(3*idInstrument+1, idEpoch) = diff.y();\n          l(3*idInstrument+2, idEpoch) = diff.z();\n\n          UInt idx = 0;\n          if(estimateShift)\n          {\n            A(3*idInstrument+0, idx++) = 1;\n            A(3*idInstrument+1, idx++) = 1;\n            A(3*idInstrument+2, idx++) = 1;\n          }\n          if(estimateScale)\n          {\n            A(3*idInstrument+0, idx)   = posRef.x()/DEFAULT_R;\n            A(3*idInstrument+1, idx)   = posRef.y()/DEFAULT_R;\n            A(3*idInstrument+2, idx++) = posRef.z()/DEFAULT_R;\n          }\n          if(estimateRotation)\n          {\n            A(3*idInstrument+1, idx)   =  posRef.z()/DEFAULT_R; //rx\n            A(3*idInstrument+2, idx++) = -posRef.y()/DEFAULT_R; //rx\n            A(3*idInstrument+0, idx)   = -posRef.z()/DEFAULT_R; //ry\n            A(3*idInstrument+2, idx++) =  posRef.x()/DEFAULT_R; //ry\n            A(3*idInstrument+0, idx)   =  posRef.y()/DEFAULT_R; //rz\n            A(3*idInstrument+1, idx++) = -posRef.x()/DEFAULT_R; //rz\n          }\n        }\n\n        Vector x;\n        if(A.size())\n        {\n          Vector sigma;\n          x = Vce::robustLeastSquares(A, l.column(idEpoch), 3, huber, huberPower, iterCount, sigma);\n          l.column(idEpoch) -= A*x;\n        }\n\n        Vector h(8);\n        h(0) = timeEpoch.mjd();\n        UInt idx = 0;\n        if(estimateShift)\n        {\n          h(1) = x(idx++);\n          h(2) = x(idx++);\n          h(3) = x(idx++);\n        }\n        if(estimateScale)\n        {\n          h(4) = x(idx++)/DEFAULT_R;\n        }\n        if(estimateRotation)\n        {\n          h(5) = x(idx++)/DEFAULT_R;\n          h(6) = x(idx++)/DEFAULT_R;\n          h(7) = x(idx++)/DEFAULT_R;\n        }\n        helmertTimeSeries.push_back(h);\n      }\n\n      // compute RMS values of current interval\n      // -------------------------------------\n      for(UInt idInstrument=0; idInstrument<countInstrument; idInstrument++)\n        if(norm(l.row(3*idInstrument,3))>1e-10)\n        {\n          RmsPlotGrid(countOutput, 0) = time.mjd();\n          RmsPlotGrid(countOutput, 1) = idInstrument;\n          RmsPlotGrid(countOutput, 2) = factor * norm(l.row(3*idInstrument,3))/std::sqrt(3*l.columns());  // 1D RMS\n          countOutput++;\n        }\n    });\n\n    // ======================================================\n\n    // save file\n    // ---------\n    if(!fileNameOutRmsPlotGrid.empty())\n    {\n      logStatus<<\"Write RMS plot grid to file <\"<<fileNameOutRmsPlotGrid<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOutRmsPlotGrid, RmsPlotGrid.row(0, countOutput));\n    }\n\n    if(!fileNameHelmertTimeSeries.empty())\n    {\n      logStatus<<\"Write Helmert time series to file <\"<<fileNameHelmertTimeSeries<<\">\"<<Log::endl;\n      Matrix H(helmertTimeSeries.size(), 8);\n      for(UInt i=0; i<H.rows(); i++)\n        copy(helmertTimeSeries.at(i).trans(), H.row(i));\n      writeFileMatrix(fileNameHelmertTimeSeries, H);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e);\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2Scaleogram.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2Scaleogram.cpp\n*\n* @brief Compute scalogram and detail levels of an instrument file.\n*\n* @author Andreas Kvas\n* @author Saniya Behzadpour\n* @date 2018-05-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the wavelet transform of a time series up to a \\config{maxLevel}.\nThe scalogram is written to a matrix which can be plotted by using a gridded layer in \\program{PlotGraph}.\nIndividual detail levels can be written to matrix files by setting \\configFile{outputfileLevels}{matrix}.\nThe data column to be decomposed must be set by \\config{selectDataField}.\n\nThe wavelet transform is implemented as a filter bank, so care should be taken when the input contains data gaps.\nLow/highpass wavelet filters are applied in forward and backward direction, input is padded symmetric.\nSee \\configClass{digitalFilter}{digitalFilterType} for details.\n\n\\fig{!hb}{0.8}{instrument2Scaleogram}{fig:Instrument2Scaleogram}{GRACE range-rate residuals of one month.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/wavelets.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n\n/***** CLASS ***********************************/\n\n/** @brief Compute scalogram and detail levels of an instrument file.\n* @ingroup programsGroup */\nclass Instrument2Scaleogram\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2Scaleogram, SINGLEPROCESS, \"Compute scalogram and detail levels of an instrument file.\", Instrument, Statistics)\nGROOPS_RENAMED_PROGRAM(InstrumentComputeScaleogram, Instrument2Scaleogram, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2Scaleogram::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameIn, fileNameOutGrid, fileNameLevels;\n    FileName fileNameWavelet;\n    UInt     dataField;\n    UInt     maxLevel = MAX_UINT;\n\n    readConfig(config, \"outputfileScaleogram\", fileNameOutGrid, Config::MUSTSET,  \"\",  \"matrix columns: mjd, level, value\");\n    readConfig(config, \"outputfileLevels\",     fileNameLevels,  Config::OPTIONAL, \"\",  \"use loopLevel as variable\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileWavelet\",     fileNameWavelet, Config::MUSTSET,  \"{groopsDataDir}/wavelets/\", \"wavelet coefficients\");\n    readConfig(config, \"selectDataField\",      dataField,       Config::DEFAULT,  \"0\", \"data column to transform\");\n    readConfig(config, \"maxLevel\",             maxLevel,        Config::OPTIONAL, \"\",  \"maximum level of decomposition (default: full)\");\n    if(isCreateSchema(config)) return;\n\n    VariableList fileNameVariableList;\n\n    logStatus<<\"read instrument file <\"<<fileNameIn<<\">\"<<Log::endl;\n    Arc arc = InstrumentFile::read(fileNameIn);\n    std::vector<Time> times = arc.times();\n    Matrix data = arc.matrix();\n\n    Vector wl;\n    readFileMatrix(fileNameWavelet, wl);\n    wl *= 1./std::sqrt(2); // normalized wavelet\n\n    logStatus<<\"compute wavelet transform\"<<Log::endl;\n    std::vector<Matrix> levels = Wavelets::waveletTransform(data.column(dataField+1), wl, maxLevel);\n    logInfo<<\"  levels = \"<<levels.size()<<Log::endl;\n\n    Matrix scaleogramGrid(times.size()*levels.size(), 3);\n    for(UInt k=0; k<levels.size(); k++)\n    {\n      std::vector<Time> interpTimes(levels.at(k).rows());\n      for(UInt i=0; i<interpTimes.size(); i++)\n        interpTimes.at(i) = times.front() + 1.*i/(interpTimes.size()-1) * (times.back()-times.front());\n\n      if(!fileNameLevels.empty())\n      {\n        Matrix output(levels.at(k).rows(), 2);\n        for(UInt i=0; i<interpTimes.size(); i++)\n        {\n          output(i, 0) = interpTimes.at(i).mjd();\n          output(i, 1) = levels.at(k)(i,0);\n        }\n        fileNameVariableList.setVariable(\"loopLevel\", k);\n        writeFileMatrix(fileNameLevels(fileNameVariableList), output);\n      }\n\n      copy(data.column(0),         scaleogramGrid.slice(k*times.size(), 0, times.size(), 1));\n      copy(Vector(data.rows(), k), scaleogramGrid.slice(k*times.size(), 1, times.size(), 1));\n      Polynomial poly(interpTimes, 0); // interpolation\n      copy(poly.interpolate(times, levels.at(k)), scaleogramGrid.slice(k*times.size(), 2, times.size(), 1));\n    }\n\n    logStatus<<\"write scaleogram to <\"<<fileNameOutGrid<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOutGrid, scaleogramGrid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2SpectralCoherence.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2SpectralCoherence.cpp\n*\n* @brief Empirical computation of the spectral coherence between two instrument files.\n*\n* @author Andreas Kvas\n* @date 2018-01-01\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the spectral coherence between two \\file{instrument files}{instrument}.\n\nThe (magnitude-squared) coherence is defined as\n\\begin{equation}\n  C_{xy}(f) = \\frac{|P_{xy}(f)|^2}{P_{xx}(f)P_{yy}(f)}\n\\end{equation}\nand is a measure in the range [0, 1] for the similarity of the signals $x$ and $y$ in frequency domain.\n$P_{xy}$ is the cross-spectral density between $x$ and $y$ and $P_{xx}$, $P_{yy}$ are auto-spectral densities.\nAuto- and cross-spectral densities are computed using Lomb's method (see \\program{Instrument2PowerSpectralDensity} for details).\n\nThe resulting PSD is the average over all arcs. For regularly sampled time series,\nthis method yields the same results as FFT based PSD estimates.\n\nA regular frequency grid based on the longest arc and the median sampling is computed.\nThe maximum number of epochs per arc is determined by\n\\begin{equation}\n  N = \\frac{t_{\\text{end}} - t_{\\text{start}}}{\\Delta t_{\\text{median}} } + 1,\n\\end{equation}\nthe Nyquist frequency is given by\n\\begin{equation}\n  f_{\\text{nyq}} = \\frac{1}{2\\Delta t_{\\text{median}}}.\n\\end{equation}\n\nIf it is suspected that \\configFile{inputfileInstrument}{instrument} contains secular variations,\nthe input should be detrended using \\program{InstrumentDetrend}.\n\nThe \\configFile{outputfileCoherence}{matrix} contains a matrix with the frequency vector as first column,\nthe coherence for each instrument channel is saved in the following columns.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Empirical computation of the spectral coherence between two instrument files.\n* @ingroup programsGroup */\nclass Instrument2SpectralCoherence\n{\n  Matrix designMatrix(const Vector &t, Double f, Bool isNyquist = FALSE);\n  std::vector<std::vector<std::complex<Double>>> leastSquaresFourier(const Vector &freqs, const_MatrixSliceRef arcMatrix, Bool countEven);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2SpectralCoherence, PARALLEL, \"Empirical computation of the spectral coherence between two instrument files.\", Instrument, Statistics)\nGROOPS_RENAMED_PROGRAM(InstrumentComputeSpectralCoherence, Instrument2SpectralCoherence, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2SpectralCoherence::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outputName;\n    FileName inputName, inputNameReference;\n\n    readConfig(config, \"outputfileCoherence\",           outputName,            Config::MUSTSET, \"\", \"column 1: frequency, column 2-n coherence\");\n    readConfig(config, \"inputfileInstrument\",           inputName,             Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrumentReference\",  inputNameReference,    Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // check input\n    // -----------\n    InstrumentFile instrumentFile(inputName);\n    InstrumentFile instrumentFileReference(inputNameReference);\n    InstrumentFile::checkArcCount({instrumentFile, instrumentFileReference});\n\n    // determine arc length and data fields\n    // ------------------------------------\n    Vector freqs;\n    UInt arcEpochCount, dataCount, arcCount;\n    Double sampling = 1.0;\n    if(Parallel::isMaster(comm))\n    {\n      arcCount = instrumentFile.arcCount();\n      std::vector<Time> times;\n      Time maxArcLen = seconds2time(0.0);\n\n      dataCount = 0;\n      for(UInt arcNo = 0; arcNo<arcCount; arcNo++)\n      {\n        Arc arc = instrumentFile.readArc(arcNo);\n        if(arc.size() == 0)\n          continue;\n        auto arcTimes = arc.times();\n\n        dataCount = std::max(dataCount, arc.at(0).data().rows());\n        maxArcLen = std::max(arcTimes.back() - arcTimes.front(), maxArcLen);\n        times.insert(times.end(), arcTimes.begin(), arcTimes.end());\n      }\n      sampling = medianSampling(times).seconds();\n\n      arcEpochCount = static_cast<UInt>(std::round(maxArcLen.seconds()/sampling)+1);\n\n      freqs = Fourier::frequencies(arcEpochCount, sampling);\n      logInfo<<\"  maximum arc length: \"<<arcEpochCount<<\" epochs\"<<Log::endl;\n      logInfo<<\"  median sampling:    \"<<sampling<<\" seconds\"<<Log::endl;\n    }\n    Parallel::broadCast(freqs,         0, comm);\n    Parallel::broadCast(arcEpochCount, 0, comm);\n    Parallel::broadCast(dataCount,     0, comm);\n    Parallel::broadCast(arcCount,      0, comm);\n    Bool countEven = (arcEpochCount%2) == 0; // flag that determines how to handle the nyquist frequency, see fourier.h for details\n\n    // estimate the covariance matrix for each arc, then reduce\n    // --------------------------------------------------------\n    logStatus<<\"Estimate spectral coherence for each arc\"<<Log::endl;\n    Matrix Gxx(freqs.rows(), dataCount);\n    Matrix Gyy(freqs.rows(), dataCount);\n\n    Matrix GxyReal(freqs.rows(), dataCount);\n    Matrix GxyImag(freqs.rows(), dataCount);\n\n    Parallel::forEach(arcCount, [&](UInt arcNo)\n    {\n      Arc arc = instrumentFile.readArc(arcNo);\n      Arc arcRef = instrumentFileReference.readArc(arcNo);\n\n      Matrix X = arc.matrix();\n      Matrix Y = arcRef.matrix();\n\n      std::vector<std::vector<std::complex<Double>>> F = leastSquaresFourier(freqs, X, countEven);\n      std::vector<std::vector<std::complex<Double>>> G = leastSquaresFourier(freqs, Y, countEven);\n\n      // accumulate estimates\n      for(UInt k = 0; k<std::min(F.size(), G.size()); k++)\n      {\n        for(UInt n = 0; n<freqs.rows(); n++)\n        {\n          auto c = F.at(k).at(n)*std::conj(G.at(k).at(n)); // cross PSD\n          GxyReal(n, k) += c.real();\n          GxyImag(n, k) += c.imag();\n          Gxx(n, k) += std::abs(F.at(k).at(n)*std::conj(F.at(k).at(n))); // auto PSDs\n          Gyy(n, k) += std::abs(G.at(k).at(n)*std::conj(G.at(k).at(n)));\n        }\n      }\n    }, comm);\n\n    Parallel::reduceSum(GxyReal, 0, comm);\n    Parallel::reduceSum(GxyImag, 0, comm);\n    Parallel::reduceSum(Gxx, 0, comm);\n    Parallel::reduceSum(Gyy, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      Matrix coherence(freqs.rows(), dataCount+1); // first row is frequency\n      copy(freqs, coherence.column(0));\n\n      for(UInt n = 0; n<freqs.rows(); n++)\n        for(UInt k=0; k<dataCount; k++)\n          coherence(n, k+1) = (GxyReal(n,k)*GxyReal(n,k) + GxyImag(n,k)*GxyImag(n,k))/(Gxx(n, k)*Gyy(n,k)); // C =|Gxy|^2/(Gxx*Gyy)\n\n      logStatus<<\"write coherence to <\"<<outputName<<\">\"<<Log::endl;\n      writeFileMatrix(outputName, coherence);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix Instrument2SpectralCoherence::designMatrix(const Vector &t, Double f, Bool isNyquist)\n{\n  Matrix A;\n  if(isNyquist)\n  {\n    A = Matrix(t.rows(), 1);\n    for(UInt i = 0; i<A.rows(); i++)\n      A(i, 0) = (i%2) == 0 ? 1.0 : -1.0;\n  }\n  else\n  {\n    A = Matrix(t.rows(), 2);\n    for(UInt i = 0; i<A.rows(); i++)\n    {\n      A(i, 0) = std::sin(2*PI*f*t(i));\n      A(i, 1) = std::cos(2*PI*f*t(i));\n    }\n  }\n\n  return A;\n}\n\n/***********************************************/\n\nstd::vector<std::vector<std::complex<Double>>> Instrument2SpectralCoherence::leastSquaresFourier(const Vector &freqs, const_MatrixSliceRef arcMatrix, Bool countEven)\n{\n  Vector t(arcMatrix.column(0));\n  t-=t(0);\n  t*=86400.0; // mjd -> seconds\n\n  std::vector< std::vector< std::complex<Double> > > F(arcMatrix.columns()-1);\n\n  for(UInt i = 0; i<F.size(); i++) // zero frequency: mean\n    F.at(i).push_back(std::complex<Double>(mean(arcMatrix.column(i+1)), 0.0));\n\n  UInt loopCount = countEven ? freqs.size()-2 : freqs.size()-1;\n  for(UInt k = 0; k<loopCount; k++)\n  {\n    Matrix A = designMatrix(t, freqs[k+1]);\n    Matrix l = Matrix(arcMatrix.column(1, arcMatrix.columns()-1));\n\n    Matrix x_hat = leastSquares(A, l);\n    for(UInt i = 0; i<arcMatrix.columns()-1; i++)\n      F.at(i).push_back(std::complex<Double>(0.5*x_hat(1, i), -0.5*x_hat(0, i)));\n  }\n  if(countEven) // special case nyquist frequency\n  {\n    Matrix A = designMatrix(t, 0.5, TRUE);\n    Matrix l = Matrix(arcMatrix.column(1, arcMatrix.columns()-1));\n\n    Matrix x_hat = leastSquares(A, l);\n    for(UInt i = 0; i<arcMatrix.columns()-1; i++)\n      F.at(i).push_back(std::complex<Double>(x_hat(0, i), 0.0));\n  }\n\n  return F;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrument2Spectrogram.cpp",
    "content": "/***********************************************/\n/**\n* @file instrument2Spectrogram.cpp\n*\n* @brief compute spectrogram using Short Time Fourier Transform applied to an instrument file.\n*\n* @author Saniya Behzadpour\n* @date 2018-07-05\n*/\n\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program applies the Short Time Fourier Transform (STFT) to selected data columns\nof \\configFile{inputfileInstrument}{instrument} and computes the spectrogram.\nThe STFT is computed at centered \\configClass{timeSeries}{timeSeriesType} with\nan (possible overlapping) rectangular window with \\config{windowLength} seconds.\nData gaps are zero padded within the window.\n\nThe \\configFile{outputfileSpectrogram}{matrix} is a matrix with each row the time (MJD),\nthe frequency $[Hz]$, and the amplitudes $[unit/\\sqrt{Hz}]$ for the selected data columns.\nIt can be plotted with \\program{PlotGraph}.\n\n\\fig{!hb}{0.8}{instrument2Spectrogram}{fig:instrument2Spectrogram}{GRACE range-rate residuals of one month (window of 6 hours).}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief compute spectrogram using Short Time Fourier Transform applied to an instrument file.\n* @ingroup programsGroup */\nclass Instrument2Spectrogram\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Instrument2Spectrogram, PARALLEL, \"spectrogram using Short Time Fourier Transform\", Instrument, Statistics)\nGROOPS_RENAMED_PROGRAM(InstrumentComputeSpectrogram, Instrument2Spectrogram, date2time(2020, 7, 7))\n\n/***********************************************/\n\nvoid Instrument2Spectrogram::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName      fileNameOut, fileNameIn;\n    TimeSeriesPtr timeSeries;\n    Double        windowLength;\n    UInt          startData, countData = MAX_UINT;\n\n    readConfig(config, \"outputfileSpectrogram\", fileNameOut,  Config::MUSTSET, \"\",  \"mjd, freq, ampl0, ampl1, ...\");\n    readConfig(config, \"inputfileInstrument\",   fileNameIn,   Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"timeSeries\",            timeSeries,   Config::MUSTSET, \"\",  \"center of SFFT window\");\n    readConfig(config, \"windowLength\",          windowLength, Config::MUSTSET, \"\",  \"[seconds]\");\n    readConfig(config, \"startDataFields\",       startData,    Config::DEFAULT, \"0\", \"start\");\n    readConfig(config, \"countDataFields\",       countData,    Config::OPTIONAL, \"\", \"number of data fields (default: all)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data <\"<<fileNameIn<<\">\"<<Log::endl;\n    const Arc    arc         = InstrumentFile::read(fileNameIn);\n    const Matrix A           = arc.matrix();\n    const Double sampling    = medianSampling(arc.times()).seconds();\n    const UInt   windowCount = static_cast<UInt>(std::round(windowLength/sampling));\n    const Vector freqs       = Fourier::frequencies(windowCount, sampling);\n    const std::vector<Time> times    = arc.times();\n    const std::vector<Time> timesBin = timeSeries->times();\n    logInfo<<\" sampling = \"<<sampling<<\" seconds\"<<Log::endl;\n    logInfo<<\" max. epoch in window = \"<<windowCount<<Log::endl;\n\n    countData = std::min(countData, A.columns()-1-startData);\n\n    logStatus<<\"computing spectrogram\"<<Log::endl;\n    Matrix spectrogram(timesBin.size()*freqs.rows(), 2+countData, NAN_EXPR);\n    auto iter = times.begin();\n    Parallel::forEach(timesBin.size(), [&](UInt i)\n    {\n      const UInt idx = i*freqs.rows();\n      copy(Vector(freqs.rows(), timesBin.at(i).mjd()), spectrogram.slice(idx, 0, freqs.rows(), 1)); // time\n      copy(freqs, spectrogram.slice(idx, 1, freqs.rows(), 1)); // frequencies\n\n      // find data in interval [timesBin-windowLength/2, timesBin+windowLength/2]\n      iter = std::lower_bound(iter, times.end(), timesBin.at(i)-seconds2time(windowLength/2));\n      const UInt row  = std::distance(times.begin(), iter);\n      const UInt rows = std::distance(iter, std::upper_bound(iter, times.end(), timesBin.at(i)+seconds2time(windowLength/2)));\n      if(rows == 0)\n        return;\n\n      // data with zero padding\n      Matrix signal(windowCount, countData);\n      copy(A.slice(row, 1+startData, std::min(rows, windowCount), countData), signal.row(0, std::min(rows, windowCount)));\n\n      // compute fft\n      for(UInt k=0; k<countData; k++)\n      {\n        std::vector<std::complex<Double>> f = Fourier::fft(signal.column(k));\n        for(UInt i=0; i<f.size(); i++)\n          spectrogram(idx+i, 2+k) = std::abs(f.at(i))*std::sqrt(sampling/f.size());\n      }\n    }, comm);\n    Parallel::reduceSum(spectrogram, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write spectrogram <\"<<fileNameOut<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOut, spectrogram);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentAccelerometer2ThermosphericDensity.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentAccelerometer2ThermosphericDensity.cpp\n*\n* @brief Estimate neutral density from accelerometer data.\n*\n* @author Sandro Krauss\n* @date 2020-06-22\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates neutral mass densities along the satellite trajectory based on \\file{accelerometer data}{instrument}.\nIn order to determine the neutral mass density the accelerometer input should only reflect the accelerations due to drag\n(e.g. \\configClass{miscAccelerations:atmosphericDrag}{miscAccelerationsType:atmosphericDrag}).\nThus, influences from solar and Earth radiation pressure must be reduced beforehand.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n#include \"classes/miscAccelerations/miscAccelerationsAtmosphericDrag.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate neutral density from accelerometer data.\n* @ingroup programsGroup */\nclass InstrumentAccelerometer2ThermosphericDensity\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentAccelerometer2ThermosphericDensity, PARALLEL, \"Estimate neutral density from accelerometer data\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentAccelerometer2ThermosphericDensity::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameOutDensity;\n    FileName         fileNameSatellite;\n    FileName         fileNameOrbit, fileNameStarCamera, fileNameAccelerometer;\n    EarthRotationPtr earthRotation;\n    ThermospherePtr  thermosphere;\n    Bool             useTemperature, useWind;\n    EphemeridesPtr   ephemerides;\n\n    readConfig(config, \"outputfileDensity\",      fileNameOutDensity,     Config::MUSTSET,  \"\",    \"MISCVALUE (kg/m^3)\");\n    readConfig(config, \"satelliteModel\",         fileNameSatellite,      Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"inputfileOrbit\",         fileNameOrbit,          Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileStarCamera\",    fileNameStarCamera,     Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileAccelerometer\", fileNameAccelerometer,  Config::MUSTSET,  \"\",    \"add non-gravitational forces in satellite reference frame\");\n    readConfig(config, \"thermosphere\",           thermosphere,           Config::MUSTSET,  \"\",    \"used to compute temperature and wind\");\n    readConfig(config, \"considerTemperature\",    useTemperature,         Config::DEFAULT,  \"1\",   \"compute drag and lift, otherwise simple drag coefficient is used\");\n    readConfig(config, \"considerWind\",           useWind,                Config::DEFAULT,  \"1\",   \"\");\n    readConfig(config, \"earthRotation\",          earthRotation,          Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",            ephemerides,            Config::OPTIONAL, \"jpl\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // open and test instrument files\n    // ------------------------------\n    InstrumentFile orbitFile, starCameraFile, accelerometerFile;\n    orbitFile.open(fileNameOrbit);\n    starCameraFile.open(fileNameStarCamera);\n    accelerometerFile.open(fileNameAccelerometer);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile, accelerometerFile});\n\n    SatelliteModelPtr satellite;\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    logStatus<<\"computing density\"<<Log::endl;\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc      orbit      = orbitFile.readArc(arcNo);\n      StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n      AccelerometerArc accelerometer = accelerometerFile.readArc(arcNo);\n      Arc::checkSynchronized({orbit, starCamera, accelerometer});\n\n      MiscValueArc output;\n      for(UInt k=0; k<orbit.size(); k++)\n      {\n        Rotary3d rotSat;\n        if(starCamera.size())\n          rotSat = starCamera.at(k).rotary;\n        const Time     time     = orbit.at(k).time;\n        const Rotary3d rotEarth = earthRotation->rotaryMatrix(time);\n        const Vector3d omega    = earthRotation->rotaryAxis(orbit.at(k).time);\n\n        if(satellite)\n        {\n          Vector3d positionSun;\n          if(ephemerides)\n            positionSun = ephemerides->position(time, Ephemerides::SUN);\n          satellite->changeState(time, orbit.at(k).position, orbit.at(k).velocity, positionSun, rotSat, rotEarth);\n        }\n\n        Double   modelDensity, temperature;\n        Vector3d wind;\n        thermosphere->state(time, rotEarth.rotate(orbit.at(k).position), modelDensity, temperature, wind);\n        if(!useTemperature)\n         temperature = 0;\n        if(!useWind)\n         wind = Vector3d();\n\n        // direction and speed of thermosphere relative to satellite in SRF\n        Vector3d direction = rotSat.inverseRotate(rotEarth.inverseRotate(wind) + crossProduct(omega, orbit.at(k).position) - orbit.at(k).velocity);\n        const Double v = direction.normalize();\n        const Vector3d acc = (1./satellite->mass) * MiscAccelerationsAtmosphericDrag::force(satellite, direction, v, 1., temperature);\n\n        MiscValueEpoch epoch;\n        epoch.time  = time;\n        epoch.value = accelerometer.at(k).acceleration.x() / acc.x(); // density\n        output.push_back(epoch);\n      }\n      return output;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write density data to file <\"<<fileNameOutDensity<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutDensity, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentAccelerometerApplyEstimatedParameters.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentAccelerometerApplyEstimatedParameters.cpp\n*\n* @brief Apply estimated acceleration parameters to an accelerometer file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2016-02-16\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program evaluates estimated satellite parameters and writes the result to an accelerometer file.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Apply estimated acceleration parameters to an accelerometer file\n* @ingroup programsGroup */\nclass InstrumentAccelerometerApplyEstimatedParameters\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentAccelerometerApplyEstimatedParameters, PARALLEL, \"apply estimated acceleration parameters to an accelerometer file.\", Instrument)\nGROOPS_RENAMED_PROGRAM(InstrumentAccelerometerEstimatedParameter, InstrumentAccelerometerApplyEstimatedParameters, date2time(2022, 8, 8))\n\n/***********************************************/\n\nvoid InstrumentAccelerometerApplyEstimatedParameters::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName                       fileNameOutAccelerometer;\n    FileName                       fileNameSatellite;\n    FileName                       fileNameOrbit, fileNameStarCamera, fileNameAccelerometer;\n    EarthRotationPtr               earthRotation;\n    EphemeridesPtr                 ephemerides;\n    ParametrizationAccelerationPtr parameterAcceleration;\n    FileName                       fileNameSolution;\n    Int                            rightSide, indexStart;\n    Double                         factor;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\",     date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"parameter\",      \"parametrizationAcceleration\", date2time(2020, 6,  3));\n\n    readConfig(config, \"outputfileAccelerometer\",     fileNameOutAccelerometer, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileSatelliteModel\",     fileNameSatellite,        Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"inputfileOrbit\",              fileNameOrbit,            Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"inputfileStarCamera\",         fileNameStarCamera,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"inputfileAccelerometer\",      fileNameAccelerometer,    Config::OPTIONAL, \"\",  \"add non-gravitational forces in satellite reference frame\");\n    readConfig(config, \"earthRotation\",               earthRotation,            Config::OPTIONAL, \"file\",  \"\");\n    readConfig(config, \"ephemerides\",                 ephemerides,              Config::OPTIONAL, \"jpl\", \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"parametrizationAcceleration\", parameterAcceleration,    Config::MUSTSET,  \"\",  \"orbit force parameters\");\n    readConfig(config, \"inputfileParameter\",          fileNameSolution,         Config::MUSTSET,  \"\",  \"estimated orbit force parameters\");\n    readConfig(config, \"indexStart\",                  indexStart,               Config::DEFAULT,  \"0\", \"position in the solution vector\");\n    readConfig(config, \"rightSide\",                   rightSide,                Config::DEFAULT,  \"0\", \"if solution contains several right hand sides, select one\");\n    readConfig(config, \"factor\",                      factor,                   Config::DEFAULT, \"1.0\", \"the result is multiplied by this factor\");\n    if(isCreateSchema(config)) return;\n\n    // open and test instrument files\n    // ------------------------------\n    InstrumentFile orbitFile(fileNameOrbit);\n    InstrumentFile starCameraFile(fileNameStarCamera);\n    InstrumentFile accelerometerFile(fileNameAccelerometer);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile, accelerometerFile});\n    UInt arcCount = orbitFile.arcCount();\n    if(!arcCount) arcCount = starCameraFile.arcCount();\n    if(!arcCount) arcCount = accelerometerFile.arcCount();\n\n    SatelliteModelPtr satellite;\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    Matrix mx;\n    readFileMatrix(fileNameSolution, mx);\n    Vector parameter = mx.slice((indexStart>=0) ? UInt(indexStart) : mx.rows()-UInt(-indexStart),\n                                (rightSide>=0)  ? UInt(rightSide) : mx.columns()-UInt(-rightSide),\n                                parameterAcceleration->parameterCount() + arcCount*parameterAcceleration->parameterCountArc(),\n                                1);\n\n    // Accelerometer-Daten erzeugen\n    // -----------------------\n    logStatus<<\"computing accelerations\"<<Log::endl;\n    std::vector<Arc> arcList(arcCount);\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc         orbit         = orbitFile.readArc(arcNo);\n      StarCameraArc    starCamera    = starCameraFile.readArc(arcNo);\n      AccelerometerArc accelerometer = accelerometerFile.readArc(arcNo);\n      Arc::checkSynchronized({orbit, starCamera, accelerometer});\n      std::vector<Time> times = orbit.times();\n      if(!times.size()) times = starCamera.times();\n      if(!times.size()) times = accelerometer.times();\n\n      parameterAcceleration->setIntervalArc(times.front(), times.back()+medianSampling(times));\n      const UInt countA = parameterAcceleration->parameterCount();\n      const UInt countB = parameterAcceleration->parameterCountArc();\n\n      AccelerometerArc accArc;\n      for(UInt i=0; i<times.size(); i++)\n      {\n        Rotary3d rotEarth, rotSat;\n        Vector3d position, velocity;\n        if(earthRotation)     rotEarth = earthRotation->rotaryMatrix(times.at(i));\n        if(starCamera.size()) rotSat   = starCamera.at(i).rotary;\n        if(orbit.size())      position = orbit.at(i).position;\n        if(orbit.size())      velocity = orbit.at(i).velocity;\n\n        Matrix A(3, countA);\n        Matrix B(3, countB);\n        parameterAcceleration->compute(satellite, times.at(i), position, velocity, rotSat, rotEarth, ephemerides, A, B);\n        Vector g(3);\n        if(countA) matMult(factor, A, parameter.row(0, countA), g);\n        if(countB) matMult(factor, B, parameter.row(arcNo*countB+countA, countB), g);\n\n        AccelerometerEpoch epoch;\n        epoch.time         = times.at(i);\n        epoch.acceleration = rotSat.inverseRotate(rotEarth.inverseRotate(Vector3d(g)));\n        if(accelerometer.size())\n          epoch.acceleration += accelerometer.at(i).acceleration;\n        accArc.push_back(epoch);\n      }\n\n      return accArc;\n    }, comm);\n\n    // write result\n    // ------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write accelerometer data to file <\"<<fileNameOutAccelerometer<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutAccelerometer, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentAccelerometerEstimateBiasScale.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentAccelerometerEstimateBiasScale.cpp\n*\n* @brief Estimate accelerometer bias and scale.\n*\n* @author Beate Klinger\n* @date 2014-11-27\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program calibrates \\configFile{inputfileAccelerometer}{instrument} with respect to\nsimulated accelerometer data, see \\program{SimulateAccelerometer}.\nThe parameters \\configFile{outputfileSolution}{matrix}\nof \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}\nare estimated and the effect is reduced to calibrate the \\file{accelerometer data}{instrument}.\n\nIf \\configFile{inputfileThruster}{instrument} is given, the corresponding epochs\n(within \\config{marginThruster}) are not used for the parameter estimation,\nbut the accelerometer epochs are still calibrated afterwards.\nAn arbitrary instrument file is allowed here.\n\nThe \\configFile{inputfileOrbit}{instrument}, \\configFile{inputfileStarCamera}{instrument},\n\\configClass{earthRotation}{earthRotationType}, \\configClass{ephemerides}{ephemeridesType},\nand \\configFile{satelliteModel}{satelliteModel} are only needed for some special parametrizations.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate accelerometer bias and scale.\n* @ingroup programsGroup */\nclass InstrumentAccelerometerEstimateBiasScale\n{\n  InstrumentFile                 accFile;\n  InstrumentFile                 accFileSim;\n  InstrumentFile                 thrusterFile;\n  InstrumentFile                 orbitFile;\n  InstrumentFile                 starCameraFile;\n  Double                         margin;\n  EarthRotationPtr               earthRotation;\n  EphemeridesPtr                 ephemerides;\n  ParametrizationAccelerationPtr parameterAcceleration;\n  SatelliteModelPtr              satellite;\n\n  void observationEquation(UInt arcNo, AccelerometerArc &acc, Vector &l, Matrix &A, Matrix &B);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentAccelerometerEstimateBiasScale, PARALLEL, \"estimate accelerometer bias and scale.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateBiasScale::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName accelerometerOutName, solutionOutName;\n    FileName accelerometerInName,  accelerometerInNameSim;\n    FileName thrusterInName;\n    FileName orbitInName;\n    FileName starCameraInName;\n    FileName satelliteModelInName;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\",     date2time(2020, 8, 19));\n    renameDeprecatedConfig(config, \"parameter\",      \"parametrizationAcceleration\", date2time(2020, 6,  3));\n\n    readConfig(config, \"outputfileAccelerometer\",     accelerometerOutName,   Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"outputfileSolution\",          solutionOutName,        Config::OPTIONAL, \"\",     \"\");\n    readConfig(config, \"inputfileAccelerometer\",      accelerometerInName,    Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileAccelerometerSim\",   accelerometerInNameSim, Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileThruster\",           thrusterInName,         Config::OPTIONAL, \"\",     \"remove thruster events\");\n    readConfig(config, \"marginThruster\",              margin,                 Config::DEFAULT,  \"1e-5\", \"margin size (on both sides) [seconds]\");\n    readConfig(config, \"inputfileOrbit\",              orbitInName,            Config::OPTIONAL, \"\",     \"\");\n    readConfig(config, \"inputfileStarCamera\",         starCameraInName,       Config::OPTIONAL, \"\",     \"\");\n    readConfig(config, \"earthRotation\",               earthRotation,          Config::OPTIONAL, \"file\", \"\");\n    readConfig(config, \"ephemerides\",                 ephemerides,            Config::OPTIONAL, \"jpl\",  \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"inputfileSatelliteModel\",     satelliteModelInName,   Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"parametrizationAcceleration\", parameterAcceleration,  Config::MUSTSET,  \"\",     \"\");\n    if(isCreateSchema(config)) return;\n\n     // ======================================================\n\n    // init instrument files + satellite model\n    // ---------------------------------------\n    logStatus<<\"read instrument data <\"<<accelerometerInName<<\">\"<<Log::endl;\n    logStatus<<\"read simulated instrument data <\"<<accelerometerInNameSim<<\">\"<<Log::endl;\n    accFile.open(accelerometerInName);\n    accFileSim.open(accelerometerInNameSim);\n    orbitFile.open(orbitInName);\n    starCameraFile.open(starCameraInName);\n    thrusterFile.open(thrusterInName);\n    InstrumentFile::checkArcCount({accFile, accFileSim, orbitFile, starCameraFile});\n\n    if(!satelliteModelInName.empty())\n      readFileSatelliteModel(satelliteModelInName, satellite);\n    const UInt countParameter = parameterAcceleration->parameterCount();\n\n     // ======================================================\n\n    // estiamte accelerometer bias/scale\n    // ---------------------------------\n    Vector x;\n    if(countParameter)\n    {\n      logStatus<<\"estimate bias/scale\"<<Log::endl;\n      logInfo<<\"  parameter count = \"<<countParameter<<Log::endl;\n      Matrix  N(countParameter, Matrix::SYMMETRIC);\n      Vector  n(countParameter);\n      Parallel::forEach(accFile.arcCount(), [&](UInt arcNo)\n      {\n        AccelerometerArc acc;\n        Vector           l;\n        Matrix           A, B;\n        observationEquation(arcNo, acc, l, A, B);\n\n        // remove thruster events (incl. margin)\n        Arc thruster = thrusterFile.readArc(arcNo);\n        if(thruster.size())\n        {\n          UInt idxThruster = 0;\n          for(UInt i=0; i<acc.size(); i++)\n          {\n            while(idxThruster<thruster.size() && ((thruster.at(idxThruster).time-acc.at(i).time).seconds() < -margin))\n              idxThruster++;\n            if(idxThruster<thruster.size() && ((thruster.at(idxThruster).time-acc.at(i).time).seconds() > margin))\n            {\n              if(l.size()) l.row(3*i,3).setNull();\n              if(A.size()) A.row(3*i,3).setNull();\n              if(B.size()) B.row(3*i,3).setNull();\n            }\n          }\n        }\n\n        // accumulate normals\n        // ------------------\n        if(B.size())\n          eliminationParameter(B, A, l);\n        if(A.size())\n        {\n          rankKUpdate(1, A, N);\n          matMult(1., A.trans(), l, n);\n        }\n      }, comm);\n      Parallel::reduceSum(N, 0, comm);\n      Parallel::reduceSum(n, 0, comm);\n\n      if(Parallel::isMaster(comm))\n      {\n        // regularize not used parameters\n        // ------------------------------\n        for(UInt i=0; i<N.rows(); i++)\n          if(N(i,i)==0)\n            N(i,i) = 1.0;\n\n        x = solve(N, n);\n\n        if(!solutionOutName.empty())\n        {\n          logStatus<<\"write solution to <\"<<solutionOutName<<\">\"<<Log::endl;\n          writeFileMatrix(solutionOutName, x);\n        }\n      } // if(Parallel::isMaster(comm))\n      Parallel::broadCast(x, 0, comm);\n    }\n\n    // Apply estimated parameters\n    // --------------------------\n    std::vector<Arc> arcList(accFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      AccelerometerArc acc;\n      Vector           l;\n      Matrix           A, B;\n      observationEquation(arcNo, acc, l, A, B);\n\n      Vector Ax(l.rows());\n      if(A.size())\n        Ax = A*x;\n      if(B.size())\n        matMult(1, B, leastSquares(Matrix(B), l-Ax), Ax);\n\n      for(UInt i=0; i<acc.size(); i++)\n      {\n        acc.at(i).acceleration.x() += Ax(3*i+0);\n        acc.at(i).acceleration.y() += Ax(3*i+1);\n        acc.at(i).acceleration.z() += Ax(3*i+2);\n      }\n\n      return acc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write calibrated accelerometer file <\"<<accelerometerOutName<<\">\"<<Log::endl;\n      InstrumentFile::write(accelerometerOutName, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateBiasScale::observationEquation(UInt arcNo, AccelerometerArc &acc, Vector &l, Matrix &A, Matrix &B)\n{\n  try\n  {\n    acc                         = accFile.readArc(arcNo);\n    AccelerometerArc accSim     = accFileSim.readArc(arcNo);\n    OrbitArc         orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc    starCamera = starCameraFile.readArc(arcNo);\n    const UInt       epochCount = acc.size();\n    Arc::checkSynchronized({acc, accSim, orbit, starCamera});\n\n    parameterAcceleration->setIntervalArc(acc.at(0).time, acc.back().time+medianSampling(acc.times()));\n\n    l = Vector(3*epochCount);\n    A = Matrix(3*epochCount, parameterAcceleration->parameterCount());\n    B = Matrix(3*epochCount, parameterAcceleration->parameterCountArc());\n\n    for(UInt i=0; i<epochCount; i++)\n    {\n      l(3*i+0) = accSim.at(i).acceleration.x()-acc.at(i).acceleration.x();\n      l(3*i+1) = accSim.at(i).acceleration.y()-acc.at(i).acceleration.y();\n      l(3*i+2) = accSim.at(i).acceleration.z()-acc.at(i).acceleration.z();\n\n      Rotary3d rotEarth, rotSat;\n      Vector3d position, velocity;\n      if(earthRotation)     rotEarth = earthRotation->rotaryMatrix(acc.at(i).time);\n      if(starCamera.size()) rotSat   = starCamera.at(i).rotary;\n      if(orbit.size())      position = orbit.at(i).position;\n      if(orbit.size())      velocity = orbit.at(i).velocity;\n\n      Matrix AEpoch(3, parameterAcceleration->parameterCount());\n      Matrix BEpoch(3, parameterAcceleration->parameterCountArc());\n      parameterAcceleration->compute(satellite, acc.at(i).time, position, velocity, rotSat, rotEarth, ephemerides, AEpoch, BEpoch);\n\n      const Matrix R = (rotEarth*rotSat).matrix();  // rotate into accelerometer frame\n      if(A.size()) matMult(1.0, R.trans(), AEpoch, A.row(3*i,3));\n      if(B.size()) matMult(1.0, R.trans(), BEpoch, B.row(3*i,3));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentAccelerometerEstimateParameters.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentAccelerometerEstimateParameters.cpp\n*\n* @brief Estimate parameters from accelerometer data.\n*\n* @author Andreas Kvas\n* @date 2022-07-27\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates calibration parameters for acceleration data given given an optional reference acceleration.\nSpecifically, the program solves the equation\n\\begin{equation}\n  \\mathbf{a} - \\mathbf{a}_\\text{ref} = \\mathbf{f}(\\mathbf{x}) + \\mathbf{e}\n\\end{equation}\nfor the unknown parameters $\\mathbf{x}$, where $\\mathbf{a}$ is given in \\configFile{inputfileAccelerometer}{instrument} and\n$\\mathbf{a}_\\text{ref}$ is given in  \\configFile{inputfileAccelerometerReference}{instrument}.\nThe parametrization of $\\mathbf{x}$ can be set via \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}.\nOptionally, the empirical covariance functions for the accelerations $\\mathbf{a}$ can be estimated by enabling \\config{estimateCovarianceFunctions}.\n\nThe estimated parameters are written to the file \\configFile{outputfileSolution}{matrix} and can be used by\n\\program{InstrumentAccelerometerApplyEstimatedParameters} to calibrate accelerometer measurements.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief  Estimate parameters from accelerometer data.\n* @ingroup programsGroup */\nclass InstrumentAccelerometerEstimateParameters\n{\n  InstrumentFile                 accFile, accFileSim, orbitFile, starCameraFile;\n  EarthRotationPtr               earthRotation;\n  EphemeridesPtr                 ephemerides;\n  ParametrizationAccelerationPtr parameterAcceleration;\n  SatelliteModelPtr              satellite;\n\n  Matrix N;        // normal equation matrix\n  Vector n;        // right hand sides\n  Vector x;        // solution\n  Matrix Wz;       // monte carlo vector for redundancy computation\n  Double lPl;      // =l'Pl, weighted norm of the observations\n  UInt   obsCount; // number of observations\n\n  Bool   estimateCovarianceFunctionVCE;\n  Bool   estimateArcSigmas;\n  Bool   estimateEpochSigmas;\n\n  Double sampling;\n  Matrix covFunc, CosTransform, Psd;\n  Vector arcSigmas, arcSigmasNew;\n  Matrix ePe, redundancy;  // one row for each frequency, one column for each component\n  std::vector<ObservationSigmaArc> arcListEpochSigma;\n\n  class ObservationEquationArc\n  {\n    public:\n      std::vector<Time> times;\n      Vector l;\n      Matrix A, B;\n      Vector xArc; // arc wise parameters\n  };\n\n  std::vector<ObservationEquationArc> observationEquations;\n\n  void computeObservationEquation(UInt arcNo);\n  void decorrelate(const std::vector<Time> &times, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch, std::vector<Matrix> &W, const std::list<MatrixSlice> &A);\n  void buildNormals(UInt arcNo);\n  void computeRedundancies(UInt arcNo);\n  ObservationSigmaArc computeEpochSigmas(UInt arcNo);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentAccelerometerEstimateParameters, PARALLEL, \"estimate accelerometer parameters.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateParameters::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    estimateCovarianceFunctionVCE = estimateArcSigmas = estimateEpochSigmas = FALSE;\n\n    FileName fileNameOutSolution, fileNameOutParameterName;\n    FileName fileNameOutCovFunc, fileNameOutArcSigmas, fileNameOutEpochSigmas;\n    FileName fileNameInAccelerometer,  fileNameInAccelerometerReference, fileNameInOrbit, fileNameInStarCamera, fileNameInSatelliteModel;\n    Double   sigmaX, sigmaY, sigmaZ;\n    UInt     maxIter;\n\n    readConfig(config, \"outputfileSolution\",              fileNameOutSolution,        Config::MUSTSET,  \"\",     \"values for estimated parameters\");\n    readConfig(config, \"outputfileParameterNames\",        fileNameOutParameterName,   Config::OPTIONAL, \"\",     \"names of the estimated parameters\");\n    if(readConfigSequence(config, \"estimateArcSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateArcSigmas = TRUE;\n      readConfig(config, \"outputfileArcSigmas\",           fileNameOutArcSigmas,   Config::OPTIONAL, \"\", \"accuracies of each arc\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateEpochSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateEpochSigmas = TRUE;\n      readConfig(config, \"outputfileEpochSigmas\",         fileNameOutEpochSigmas, Config::OPTIONAL, \"\", \"estimated epoch-wise sigmas\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateCovarianceFunctions\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateCovarianceFunctionVCE = TRUE;\n      readConfig(config, \"outputfileCovarianceFunction\",  fileNameOutCovFunc,     Config::OPTIONAL, \"\", \"covariance functions for x, y, z direction\");\n      endSequence(config);\n    }\n    readConfig(config, \"inputfileAccelerometer\",          fileNameInAccelerometer,          Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"inputfileAccelerometerReference\", fileNameInAccelerometerReference, Config::OPTIONAL, \"\",      \"if not given, reference acceleration is assumed zero\");\n    readConfig(config, \"inputfileOrbit\",                  fileNameInOrbit,                  Config::OPTIONAL, \"\",      \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"inputfileStarCamera\",             fileNameInStarCamera,             Config::OPTIONAL, \"\",      \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"inputfileSatelliteModel\",         fileNameInSatelliteModel,         Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model (may be needed by parametrizationAcceleration)\");\n    readConfig(config, \"earthRotation\",                   earthRotation,                    Config::OPTIONAL, \"file\",  \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"ephemerides\",                     ephemerides,                      Config::OPTIONAL, \"jpl\",   \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"parametrizationAcceleration\",     parameterAcceleration,            Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"sigmaX\",                          sigmaX,                           Config::DEFAULT,  \"1e-9\",  \"apriori accuracy in x-axis\");\n    readConfig(config, \"sigmaY\",                          sigmaY,                           Config::DEFAULT,  \"10e-9\", \"apriori accuracy in y-axis\");\n    readConfig(config, \"sigmaZ\",                          sigmaZ,                           Config::DEFAULT,  \"1e-9\",  \"apriori accuracy in z-axis\");\n    readConfig(config, \"iterationCount\",                  maxIter,                          Config::DEFAULT,  \"5\",     \"iteration count for determining the covariance function\");\n    if(isCreateSchema(config)) return;\n\n     // ======================================================\n\n    // init instrument files + satellite model\n    // ---------------------------------------\n    logStatus<<\"read instrument data <\"<<fileNameInAccelerometer<<\">\"<<Log::endl;\n    logStatus<<\"read reference data <\"<<fileNameInAccelerometerReference<<\">\"<<Log::endl;\n    accFile.open(fileNameInAccelerometer);\n    accFileSim.open(fileNameInAccelerometerReference);\n    orbitFile.open(fileNameInOrbit);\n    starCameraFile.open(fileNameInStarCamera);\n    InstrumentFile::checkArcCount({accFile, accFileSim, orbitFile, starCameraFile});\n    const UInt arcCount = accFile.arcCount();\n\n    if(!fileNameInSatelliteModel.empty())\n    {\n      logStatus<<\"read satellite model <\"<<fileNameInSatelliteModel<<\">\"<<Log::endl;\n      readFileSatelliteModel(fileNameInSatelliteModel, satellite);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutParameterName.empty())\n    {\n      logStatus<<\"write parameter names to <\"<<fileNameOutParameterName<<\">\"<<Log::endl;\n      std::vector<ParameterName> names, nameArc;\n      parameterAcceleration->parameterName(names);\n      parameterAcceleration->parameterNameArc(nameArc);\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      {\n        const std::string str = \"arc\"+arcNo%\"%i\"s+\".\";\n        for(UInt i=0; i<nameArc.size(); i++)\n        {\n          ParameterName param = nameArc.at(i);\n          param.type = str+param.type;\n          names.push_back(param);\n        }\n      }\n      writeFileParameterName(fileNameOutParameterName, names);\n    }\n\n    // ======================================================\n\n    // setup observation equations\n    // ---------------------------\n    logStatus<<\"compute observation equations\"<<Log::endl;\n    observationEquations.resize(arcCount);\n    const std::vector<UInt> processNo = Parallel::forEach(arcCount, [&](UInt arcNo) {computeObservationEquation(arcNo);}, comm);\n\n    // determine sampling\n    sampling  = 0.;\n    for(const auto &arc : observationEquations)\n      if(arc.times.size())\n        sampling += medianSampling(arc.times).seconds();\n    Parallel::reduceSum(sampling, 0, comm);\n    Parallel::broadCast(sampling, 0, comm);\n    sampling /= arcCount;\n\n    // Determine max. length of ovariance functions\n    UInt covLength = 0;\n    for(const auto &arc : observationEquations)\n      if(arc.times.size())\n        covLength = std::max(covLength, static_cast<UInt>(std::round((arc.times.back()-arc.times.front()).seconds()/sampling)+1));\n    Parallel::reduceMax(covLength, 0, comm);\n    Parallel::broadCast(covLength, 0, comm);\n\n    logInfo<<\"  length of covariance function: \"<<covLength<<\" epochs with a sampling of \"<<sampling<<\" seconds\"<<Log::endl;\n\n    // init arc sigmas and covariance function\n    // ---------------------------------------\n    arcSigmas    = Vector(arcCount, 1.0);\n    CosTransform = Vce::cosTransform(covLength);\n    covFunc = Vce::readCovarianceFunction(FileName(), covLength, 3, sampling);\n    covFunc.column(1)  *= std::pow(sigmaX, 2);\n    covFunc.column(2)  *= std::pow(sigmaY, 2);\n    covFunc.column(3)  *= std::pow(sigmaZ, 2);\n    Psd = CosTransform * covFunc.column(1, 3);\n\n    // init epoch sigmas\n    // -----------------\n    arcListEpochSigma.resize(arcCount);\n    Parallel::forEachProcess(arcCount, [this](UInt arcNo)\n    {\n      const auto &times = observationEquations.at(arcNo).times;\n      arcListEpochSigma.at(arcNo) = Arc(times, Matrix(times.size(), 2), Epoch::OBSERVATIONSIGMA);\n    }, processNo, comm, FALSE/*timing*/);\n\n    // start iteration\n    // ---------------\n    const UInt countParameter = parameterAcceleration->parameterCount();\n    for(UInt iter=0; iter<maxIter; iter++)\n    {\n      if(maxIter>1) logStatus<<\"starting iteration \"<<iter+1<<Log::endl;\n\n      // solve normal equations\n      // ----------------------\n      if(countParameter)\n      {\n        logStatus<<\"accumulate system of normal equations\"<<Log::endl;\n        N        = Matrix(countParameter, Matrix::SYMMETRIC);\n        n        = Vector(countParameter);\n        lPl      = 0;\n        obsCount = 0;\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {buildNormals(arcNo);}, processNo, comm);\n        Parallel::reduceSum(N,        0, comm);\n        Parallel::reduceSum(n,        0, comm);\n        Parallel::reduceSum(obsCount, 0, comm);\n        Parallel::reduceSum(lPl,      0, comm);\n\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        if(Parallel::isMaster(comm))\n        {\n          // regularize unused parameters\n          UInt countUnused = 0;\n          for(UInt k=0; k<N.rows(); k++)\n            if(N(k, k) == 0.0)\n            {\n              N(k, k) = 1.0;\n              countUnused++;\n            }\n          obsCount += countUnused;\n          if(countUnused)\n            logInfo<<\"  \"<<countUnused<<\" parameters unused -> set to zero\"<<Log::endl;\n\n          x = solve(N, n);\n          logInfo<<\"  aposteriori sigma = \"<<std::sqrt((lPl-inner(x, n))/(obsCount-x.rows()))<<Log::endl;\n\n          Wz = Vce::monteCarlo(x.rows(), 100); // monte carlo vector for VCE\n          triangularSolve(1., N, Wz);\n        }\n        Parallel::broadCast(x,  0, comm);\n        Parallel::broadCast(Wz, 0, comm);\n      }\n      Parallel::barrier(comm);\n\n      // compute redundancies\n      // --------------------\n      logStatus<<\"compute arc parameters and redundancies\"<<Log::endl;\n      arcSigmasNew = Vector(arcCount);\n      ePe = redundancy = Matrix(covLength, 3);\n      Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeRedundancies(arcNo);}, processNo, comm);\n      Parallel::barrier(comm);\n\n      // write parameter vector\n      // ----------------------\n      if(!fileNameOutSolution.empty())\n      {\n        // collect solution vector\n        std::vector<Vector> solutions(arcCount);\n        Parallel::forEachProcess(solutions, [this](UInt arcNo) {return observationEquations.at(arcNo).xArc;}, processNo, comm, FALSE/*timing*/);\n\n        if(Parallel::isMaster(comm))\n        {\n          // copy global and arc parameters to one vector\n          solutions.insert(solutions.begin(), x); // global parametes\n          const UInt count = std::accumulate(solutions.begin(), solutions.end(), UInt(0), [](UInt c, const Vector &x) {return c+x.size();});\n\n          Vector xOut(count);\n          UInt   idx = 0;\n          for(const Vector &solution : solutions)\n          {\n            copy(solution, xOut.row(idx, solution.rows()));\n            idx += solution.rows();\n          }\n\n          logStatus<<\"write solution to <\"<<fileNameOutSolution<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameOutSolution, xOut);\n        }\n      }\n\n      // sigmas per arc\n      // --------------\n      if(estimateArcSigmas)\n      {\n        Parallel::reduceSum(arcSigmasNew, 0, comm);\n        if(Parallel::isMaster(comm))\n        {\n          arcSigmas = arcSigmasNew;\n          const Double sigma0 = Vce::meanSigma(arcSigmas);\n          arcSigmas *= 1./sigma0;\n          logInfo<<\"  sigma per arc (median): \"<<sigma0<<Log::endl;\n\n          if(!fileNameOutArcSigmas.empty())\n          {\n            logStatus<<\"write arc sigma file <\"<<fileNameOutArcSigmas<<\">\"<<Log::endl;\n            writeFileMatrix(fileNameOutArcSigmas, arcSigmas);\n          }\n        }\n        Parallel::broadCast(arcSigmas, 0, comm);\n      }\n\n      // sigmas per epoch\n      // --------------\n      if(estimateEpochSigmas)\n      {\n        Parallel::forEachProcess(arcListEpochSigma, [this](UInt arcNo) {return computeEpochSigmas(arcNo);}, processNo, comm, FALSE/*timing*/);\n        if(Parallel::isMaster(comm))\n        {\n          UInt count = std::accumulate(arcListEpochSigma.begin(), arcListEpochSigma.end(), UInt(0), [](UInt c, auto &arc) {return c+arc.size();});\n          UInt countOutlier = 0;\n          for(auto &arc : arcListEpochSigma)\n            countOutlier += std::count_if(arc.begin(), arc.end(), [](const ObservationSigmaEpoch &e) {return (e.sigma > 0);});\n          logInfo<<\"  \"<<countOutlier<<\" of \"<<count<<\" outliers (\"<<100.*countOutlier/count%\"%.2f%%)\"s<<Log::endl;\n        }\n        if(Parallel::isMaster(comm) && !fileNameOutEpochSigmas.empty())\n        {\n          logStatus<<\"write epoch sigma file <\"<<fileNameOutEpochSigmas<<\">\"<<Log::endl;\n          InstrumentFile::write(fileNameOutEpochSigmas, arcListEpochSigma);\n        }\n      }\n\n      // estimate new PSD through variance component estimation\n      // ------------------------------------------------------\n      if(estimateCovarianceFunctionVCE)\n      {\n        logStatus<<\"compute psd through variance component estimation\"<<Log::endl;\n        Parallel::reduceSum(ePe, 0, comm);\n        Parallel::reduceSum(redundancy, 0, comm);\n        if(Parallel::isMaster(comm))\n        {\n          Double maxFactor = 0;\n          Vce::estimatePsd(ePe, redundancy, Psd, maxFactor);\n          logInfo<<\"  max. PSD adjustment factor: \"<<maxFactor<<Log::endl;\n        }\n        Parallel::broadCast(Psd, 0, comm);\n        copy(CosTransform*Psd, covFunc.column(1, Psd.columns())); // compute new covariance function\n\n        if(Parallel::isMaster(comm) && !fileNameOutCovFunc.empty())\n        {\n          logStatus<<\"write covariance function file <\"<<fileNameOutCovFunc<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameOutCovFunc, covFunc);\n        }\n      }\n    } // for(iter)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateParameters::computeObservationEquation(UInt arcNo)\n{\n  try\n  {\n    AccelerometerArc acc        = accFile.readArc(arcNo);\n    AccelerometerArc accSim     = accFileSim.readArc(arcNo);\n    OrbitArc         orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc    starCamera = starCameraFile.readArc(arcNo);\n    Arc::checkSynchronized({acc, accSim, orbit, starCamera});\n\n    const std::vector<Time> times = acc.times();\n    parameterAcceleration->setIntervalArc(times.front(), times.back()+medianSampling(times));\n\n    const UInt epochCount = acc.size();\n    Vector l(3*epochCount);\n    Matrix A(3*epochCount, parameterAcceleration->parameterCount());\n    Matrix B(3*epochCount, parameterAcceleration->parameterCountArc());\n\n    for(UInt i=0; i<epochCount; i++)\n    {\n      Rotary3d rotEarth, rotSat;\n      Vector3d position, velocity;\n      if(earthRotation)     rotEarth = earthRotation->rotaryMatrix(acc.at(i).time);\n      if(starCamera.size()) rotSat   = starCamera.at(i).rotary;\n      if(orbit.size())      position = orbit.at(i).position;\n      if(orbit.size())      velocity = orbit.at(i).velocity;\n\n      Vector lk = acc.at(i).acceleration.vector();\n      if(accSim.size())\n        lk -= accSim.at(i).acceleration.vector();\n      Matrix Ak(3, parameterAcceleration->parameterCount());\n      Matrix Bk(3, parameterAcceleration->parameterCountArc());\n      parameterAcceleration->compute(satellite, acc.at(i).time, position, velocity, rotSat, rotEarth, ephemerides, Ak, Bk);\n\n      const Matrix R = (rotEarth*rotSat).matrix();  // rotate into accelerometer frame\n      l(i)              = lk(0);\n      l(i+epochCount)   = lk(1);\n      l(i+2*epochCount) = lk(2);\n      if(A.size())\n      {\n        Ak = R.trans() * Ak;\n        copy(Ak.row(0), A.row(i));\n        copy(Ak.row(1), A.row(i+epochCount));\n        copy(Ak.row(2), A.row(i+2*epochCount));\n      }\n      if(B.size())\n      {\n        Bk = R.trans() * Bk;\n        copy(Bk.row(0), B.row(i));\n        copy(Bk.row(1), B.row(i+epochCount));\n        copy(Bk.row(2), B.row(i+2*epochCount));\n      }\n    }\n\n    observationEquations.at(arcNo).l = l;\n    observationEquations.at(arcNo).A = A;\n    observationEquations.at(arcNo).B = B;\n    observationEquations.at(arcNo).times = times;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateParameters::decorrelate(const std::vector<Time> &times, Double sigmaArc, const ObservationSigmaArc &sigmaEpoch,\n                                                            std::vector<Matrix> &W, const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    std::vector<UInt> index;\n    for(const Time &t : times)\n      index.push_back(static_cast<UInt>(std::round((t-times.front()).seconds()/sampling)));\n\n    W = std::vector<Matrix>(3, Matrix(times.size(), Matrix::SYMMETRIC, Matrix::UPPER));\n    for(UInt idAxis=0; idAxis<3; idAxis++)\n    {\n      for(UInt i=0; i<times.size(); i++)\n        for(UInt k=i; k<times.size(); k++)\n          W.at(idAxis)(i, k) = sigmaArc*sigmaArc * covFunc(index.at(k-i), idAxis+1);\n\n      if(sigmaEpoch.size())\n        for(UInt i=0; i<times.size(); i++)\n            W.at(idAxis)(i, i) += std::pow(sigmaEpoch.at(i).sigma, 2);\n\n      cholesky(W.at(idAxis));\n      for(MatrixSliceRef WA : A)\n        if(WA.size())\n          triangularSolve(1., W.at(idAxis).trans(), WA.row(idAxis*times.size(), times.size()));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateParameters::buildNormals(UInt arcNo)\n{\n  try\n  {\n    // decorrelate\n    Vector Wl = observationEquations.at(arcNo).l;\n    Matrix WA = observationEquations.at(arcNo).A;\n    Matrix WB = observationEquations.at(arcNo).B;\n    std::vector<Matrix> W;\n    decorrelate(observationEquations.at(arcNo).times, arcSigmas(arcNo), arcListEpochSigma.at(arcNo), W, {Wl, WA, WB});\n\n    // estimate arc dependent parameters\n    Vector tau;\n    if(WB.size())\n    {\n      tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl); // transform observations: l:= Q'l\n      QTransMult(WB, tau, WA); // transform design matrix A:=Q'A\n    }\n    // use only nullspace of design matrix WB\n    MatrixSlice A_bar( WA.row(WB.columns(), WA.rows()-WB.columns()) );\n    MatrixSlice l_bar( Wl.row(WB.columns(), Wl.rows()-WB.columns()) );\n\n    // build normals\n    this->lPl      += quadsum(l_bar);\n    this->obsCount += l_bar.rows();\n    matMult(1., A_bar.trans(), l_bar, n);\n    rankKUpdate(1., A_bar, N);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentAccelerometerEstimateParameters::computeRedundancies(UInt arcNo)\n{\n  try\n  {\n    Vector We = observationEquations.at(arcNo).l;\n    Matrix WA = observationEquations.at(arcNo).A;\n    Matrix WB = observationEquations.at(arcNo).B;\n    if(WA.size())\n      matMult(-1., WA,  x, We);\n\n    std::vector<Matrix> W;\n    decorrelate(observationEquations.at(arcNo).times, arcSigmas(arcNo), arcListEpochSigma.at(arcNo), W, {We, WA, WB});\n\n    // estimate & eliminate arc dependent parameters\n    // ---------------------------------------------\n    if(WB.size())\n    {\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, We);           // transform observations: l:= Q'l\n      observationEquations.at(arcNo).xArc = We.row(0, tau.rows());\n      triangularSolve(1., WB.row(0, tau.rows()), observationEquations.at(arcNo).xArc);\n      We.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n      QMult(WB, tau, We);                // back transformation\n\n      if(WA.size())\n      {\n        QTransMult(WB, tau, WA);           // transform design matrix A:=Q'A\n        WA.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n        QMult(WB, tau, WA);                // back transformation\n      }\n\n      generateQ(WB, tau);\n      WB.setType(Matrix::GENERAL);\n    }\n\n    if(!estimateArcSigmas && !estimateCovarianceFunctionVCE)\n      return;\n\n    // Without variance component estimation\n    // -------------------------------------\n    Matrix WAz(We.rows(), Wz.columns());\n    if(WA.size())\n      matMult( 1., WA, Wz, WAz);\n    if(!estimateCovarianceFunctionVCE)\n    {\n      const Double redundancy = We.rows() - quadsum(WAz) - quadsum(WB);\n      arcSigmasNew(arcNo) = std::sqrt(quadsum(We)/redundancy) * arcSigmas(arcNo);\n      return;\n    }\n\n    // Variance component estimation\n    // -----------------------------\n    std::vector<UInt> index;\n    for(const Time &t : observationEquations.at(arcNo).times)\n      index.push_back(static_cast<UInt>(std::round((t-observationEquations.at(arcNo).times.front()).seconds()/sampling)));\n    const UInt countEpoch = observationEquations.at(arcNo).times.size();\n    Double ePeSum=0, redundancySum=0;\n\n    for(UInt idAxis=0; idAxis<Psd.columns(); idAxis++)\n    {\n      Matrix R;\n      Vector WWe;\n      Vce::redundancy(W.at(idAxis), We.row(idAxis*countEpoch, countEpoch), WAz.row(idAxis*countEpoch, countEpoch), WB.row(idAxis*countEpoch, countEpoch), R, WWe);\n      Vce::psd(R, WWe, index, arcSigmas(arcNo), CosTransform, Psd.column(idAxis),\n               ePe.column(idAxis), redundancy.column(idAxis), ePeSum, redundancySum);\n    }\n    arcSigmasNew(arcNo) = std::sqrt(ePeSum/redundancySum) * arcSigmas(arcNo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nObservationSigmaArc InstrumentAccelerometerEstimateParameters::computeEpochSigmas(UInt arcNo)\n{\n  try\n  {\n    const Double huber = 2.5;\n    const Double threshold2 = std::pow(huber * arcSigmas(arcNo), 2) * sum(covFunc.slice(0, 1, 1, 3));\n    const UInt   epochCount = observationEquations.at(arcNo).times.size();\n\n    Vector e = observationEquations.at(arcNo).l;\n    if(observationEquations.at(arcNo).A.size())\n      matMult(-1.0, observationEquations.at(arcNo).A, x, e);\n    if(observationEquations.at(arcNo).B.size())\n      matMult(-1, observationEquations.at(arcNo).B, observationEquations.at(arcNo).xArc, e);\n\n    for(UInt i=0; i<epochCount; i++)\n    {\n      const Double e2 = quadsum(Vector({e(i), e(epochCount+i), e(2*epochCount+i)}));\n      arcListEpochSigma.at(arcNo).at(i).sigma = 0.;\n      if(e2 > threshold2)\n        arcListEpochSigma.at(arcNo).at(i).sigma = std::sqrt((e2-threshold2)/3);\n    }\n\n    return arcListEpochSigma.at(arcNo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentApplyTimeOffset.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentApplyTimeOffset.cpp\n*\n* @brief Apply a time offset to an instrument file.\n*\n* @author Andreas Kvas\n* @author Torsten Mayer-Guerr\n* @date 2022-04-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program applies a \\configFile{inputfileTimeOffset}{instrument} (MISCVALUE)\nto an \\configFile{inputfileInstrument}{instrument}.\nThe time offsets in seconds are multiplicated with a \\config{factor}.\nThe instrument files must be synchronized (see \\program{InstrumentSynchronize}).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Apply a time offset to an instrument file.\n* @ingroup programsGroup */\nclass InstrumentApplyTimeOffset\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentApplyTimeOffset, SINGLEPROCESS, \"Apply a time offset to an instrument file\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentApplyTimeOffset::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn, fileNameTimeOffset;\n    Double   factor;\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut,        Config::MUSTSET, \"\",    \"\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,         Config::MUSTSET, \"\",    \"\");\n    readConfig(config, \"inputfileTimeOffset\",  fileNameTimeOffset, Config::MUSTSET, \"\",    \"MISCVALUE with time offset in seconds\");\n    readConfig(config, \"factor\",               factor,             Config::DEFAULT, \"1.0\", \"applied to time offset\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameIn);\n    InstrumentFile timeOffsetFile(fileNameTimeOffset);\n    InstrumentFile::checkArcCount({instrumentFile, timeOffsetFile});\n\n    std::vector<Arc> arcList(instrumentFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc          arc           = instrumentFile.readArc(arcNo);\n      MiscValueArc arcTimeOffset = timeOffsetFile.readArc(arcNo);\n      Arc::checkSynchronized({arc, arcTimeOffset});\n\n      for(UInt i=0; i<arc.size(); i++)\n        arc.at(i).time += factor * seconds2time(arcTimeOffset.at(i).value);\n      return arc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentArcCalculate.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentArcCalculate.cpp\n*\n* @brief Instrument data calculation arc wise.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-01\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program manipulates the data columns every arc of an \\file{instrument file}{instrument} similar to\n\\program{FunctionsCalculate}, see there for more details.\nIf several \\configFile{inputfileInstrument}{instrument}s are given the data columns are copied side by side.\nFor this the instrument files must be synchronized (see \\program{InstrumentSynchronize}). For the data\ncolumns the standard data variables are available, see~\\reference{dataVariables}{general.parser:dataVariables}.\nFor the time column (MJD) a variable \\verb|epoch| (together with \\verb|epochmean|, \\verb|epochmin|, \\ldots)\nis defined additionally.\n\nThe content of \\configFile{outputfileInstrument}{instrument} is controlled by \\config{outColumn}.\nThe number of \\config{outColumn} must agree with the selected \\configClass{outType}{instrumentTypeType}.\nThe algorithm to compute the output is as follows:\nThe expressions in \\config{outColumn} are evaluated once for each epoch of the input.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nIf no \\config{outColumn} are specified all input columns are used instead directly.\nThe \\configClass{instrument type}{instrumentTypeType} can be specified with \\config{outType} and must be agree with the number of columns.\n\nAn extra \\config{statistics} file can be generated with one mid epoch per arc. For the computation of the \\config{outColumn} values\nall~\\reference{dataVariables}{general.parser:dataVariables} are available (e.g. \\verb|epochmin|, \\verb|data0mean|, \\verb|data1std|, \\ldots)\ninclusively the \\config{constant}s and estimated \\config{parameter}s but without the \\verb|data0|,~\\verb|data1|,~\\ldots itself.\nThe variables and the numbering of the columns refers to the \\configFile{outputfileInstrument}{instrument}.\n\nSee also \\program{FunctionsCalculate}, \\program{MatrixCalculate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***********************************************/\n\n/** @brief Instrument data calculation arc wise.\n* @ingroup programsGroup */\nclass InstrumentArcCalculate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentArcCalculate, PARALLEL, \"Instrument data calculation arc wise.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentArcCalculate::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName                           fileNameOut, fileNameStatistics;\n    std::vector<FileName>              fileNamesIn;\n    std::vector<ExpressionVariablePtr> constExpr, paramExpr;\n    std::vector<ExpressionVariablePtr> lsaExpr, removeExpr;\n    std::vector<ExpressionVariablePtr> outExpr, statisticsExpr;\n    Epoch::Type                        type = Epoch::EMPTY;\n\n    readConfig(config, \"outputfileInstrument\",    fileNameOut, Config::OPTIONAL, \"\",      \"\");\n    readConfig(config, \"inputfileInstrument\",     fileNamesIn, Config::MUSTSET,  \"\",      \"data columns are appended to the right\");\n    readConfig(config, \"constant\",                constExpr,   Config::OPTIONAL, \"\",      \"define a constant by name=value\");\n    readConfig(config, \"parameter\",               paramExpr,   Config::OPTIONAL, \"\",      \"define a parameter by name[=value]\");\n    readConfig(config, \"leastSquares\",            lsaExpr,     Config::OPTIONAL, \"\",      \"try to minimize the expression by adjustment of the parameters\");\n    readConfig(config, \"removalCriteria\",         removeExpr,  Config::OPTIONAL, \"\",      \"row is removed if one criterion evaluates true.\");\n    readConfig(config, \"outType\",                 type,        Config::OPTIONAL, \"\",      \"\");\n    readConfig(config, \"outColumn\",               outExpr,     Config::OPTIONAL, R\"([\"data0\"])\", \"expression of output columns, extra 'epoch' variable\");\n    if(readConfigSequence(config, \"statistics\", Config::OPTIONAL, \"\", \"\"))\n    {\n      readConfig(config, \"outputfileInstrument\", fileNameStatistics, Config::MUSTSET, \"\",         \"instrument file with mid epoch per arc, data columns are user defined\");\n      readConfig(config, \"outColumn\",            statisticsExpr,     Config::MUSTSET, \"data0rms\", \"expression to compute statistics columns, data* are from outColumn\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // open files\n    // ----------\n    std::vector<InstrumentFile> file(fileNamesIn.size());\n    for(UInt i=0; i<file.size(); i++)\n      file.at(i).open(fileNamesIn.at(i));\n    for(UInt i=1; i<file.size(); i++)\n      InstrumentFile::checkArcCount({file.at(0), file.at(i)});\n\n    // create data variables\n    // ---------------------\n    VariableList varListGlobal;\n    // get real variable names, otherwise all named after config element\n    std::for_each(constExpr.begin(), constExpr.end(), [&](auto expr) {expr->parseVariableName();});\n    std::for_each(paramExpr.begin(), paramExpr.end(), [&](auto expr) {expr->parseVariableName();});\n    std::for_each(constExpr.begin(), constExpr.end(), [&](auto expr) {varListGlobal.addVariable(expr);});\n    std::for_each(paramExpr.begin(), paramExpr.end(), [&](auto expr) {varListGlobal.addVariable(expr);});\n\n    // arc wise computation\n    // --------------------\n    logStatus<<\"computing arcs\"<<Log::endl;\n    std::vector<Arc> arcList(file.at(0).arcCount());\n    Matrix statistics(file.at(0).arcCount(), 1+statisticsExpr.size());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      // read data\n      std::vector<Arc> arc(file.size());\n      for(UInt i=0; i<arc.size(); i++)\n        arc.at(i) = file.at(i).readArc(arcNo);\n      for(UInt i=1; i<arc.size(); i++)\n        Arc::checkSynchronized({arc.at(0), arc.at(i)});\n\n      // copy data to one matrix + extra time vector\n      std::vector<Time> times = (arc.at(0).times());\n      std::vector<UInt> index(1, 0);\n      for(UInt i=0; i<arc.size(); i++)\n        index.push_back( arc.at(i).at(0).data().rows() + index.back() );\n      Matrix data(arc.at(0).size(), index.back());\n      for(UInt i=0; i<arc.size(); i++)\n        copy(arc.at(i).matrix().column(1, index.at(i+1)-index.at(i)), data.column(index.at(i), index.at(i+1)-index.at(i))); // without time column\n\n      auto varListArc       = varListGlobal;\n      auto varListArcWoData = varListGlobal;\n      addDataVariables(\"epoch\", times, varListArc);\n      addDataVariables(data, varListArc);\n\n      // least squares adjustment\n      if(lsaExpr.size())\n      {\n        Vector l(data.rows()*lsaExpr.size());\n        Matrix A(data.rows()*lsaExpr.size(), paramExpr.size());\n        for(UInt k=0; k<lsaExpr.size(); k++)\n        {\n          std::vector<ExpressionVariablePtr> designExpr(paramExpr.size());\n          for(UInt s=0; s<paramExpr.size(); s++)\n          {\n            designExpr.at(s) = lsaExpr.at(k)->derivative(paramExpr.at(s)->name(), varListArc);\n            designExpr.at(s)->simplify(varListArc);\n          }\n\n          for(UInt i=0; i<data.rows(); i++)\n          {\n            evaluateDataVariables(data, i, varListArc);\n            varListArc.setVariable(\"epoch\", times.at(i).mjd());\n            l(i+k*data.rows()) = -lsaExpr.at(k)->evaluate(varListArc); // observations\n            for(UInt s=0; s<designExpr.size(); s++)\n              A(i+k*data.rows(),s) = designExpr.at(s)->evaluate(varListArc); // columns of design matrix\n          }\n          undefineDataVariables(data, varListArc);\n          varListArc.undefineVariable(\"epoch\");\n        }\n\n        Vector x = leastSquares(A, l);\n        for(UInt s=0; s<paramExpr.size(); s++)\n        {\n          x(s) += paramExpr.at(s)->evaluate(varListArc);\n          varListArc.setVariable(paramExpr.at(s)->name(),  x(s) );\n          varListArcWoData.setVariable(paramExpr.at(s)->name(),  x(s) );\n        }\n      } // if(lsa)\n\n      // create output arc\n      std::vector<Time> timesOut(data.rows());\n      Matrix outData(data.rows(), 1 + (outExpr.size() ? outExpr.size() : data.columns())); // first column for time\n      UInt row = 0;\n      for(UInt i=0; i<outData.rows(); i++)\n      {\n        evaluateDataVariables(data, i, varListArc);\n        varListArc.setVariable(\"epoch\", times.at(i).mjd());\n        if(!std::any_of(removeExpr.begin(), removeExpr.end(), [&](auto expr) {return expr->evaluate(varListArc) != 0;}))\n        {\n          timesOut.at(row) = times.at(i);\n          for(UInt k=0; k<outData.columns()-1; k++)\n            outData(row, 1+k) = outExpr.size() ? outExpr.at(k)->evaluate(varListArc) : data(i, k);\n          row++;\n        }\n      }\n      timesOut.resize(row);\n      if(row < outData.rows())\n        outData = outData.row(0, row);\n\n      // arc statistics\n      if(statisticsExpr.size())\n      {\n        auto varList = varListArcWoData;\n        addDataVariables(\"epoch\", timesOut, varList);\n        addDataVariables(outData.column(1, outData.columns()-1), varList);\n        statistics(arcNo, 0) = (0.5*(timesOut.front()+timesOut.back()+medianSampling(timesOut))).mjd();\n        for(UInt k=0; k<statisticsExpr.size(); k++)\n          statistics(arcNo, 1+k) = statisticsExpr.at(k)->evaluate(varList);\n      }\n\n      return Arc(timesOut, outData, type);\n    }, comm);\n\n    // write results\n    // -------------\n    if(!fileNameOut.empty() && Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument data <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n\n    if(!fileNameStatistics.empty() && statistics.size())\n    {\n      Parallel::reduceSum(statistics, 0, comm);\n      if(Parallel::isMaster(comm))\n      {\n        logStatus<<\"write statistics file <\"<<fileNameStatistics<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameStatistics, Arc(statistics));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentArcCrossStatistics.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentArcCrossStatistics.cpp\n*\n* @brief Compute RMS of an instrument time series or differences.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-01-30\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes statistics of selected data columns between two \\file{instrument files}{instrument} arc wise.\nThe \\configFile{outputfileStatisticsTimeSeries}{instrument} contains for every arc one (mid) epoch\nwith statistics column(s). Possible statistics are\n\\begin{itemize}\n  \\item Correlation\n  \\begin{equation}\n    \\rho = \\frac{\\sum_i x_i y_i}{\\sqrt{(\\sum_i x_i^2) (\\sum_i y_i^2})},\n  \\end{equation}\n  \\item Error RMS\n  \\begin{equation}\n    rms = \\sqrt{\\frac{1}{N}\\sum_i (x_i-y_i)^2},\n  \\end{equation}\n  \\item Nash-Sutcliffe coefficient (NSC)\n  \\begin{equation}\n    nsc = 1- \\frac{\\sum_i (x_i-y_i)^2}{\\sum_i (y_i-\\bar{y})^2}.\n  \\end{equation}\n\\end{itemize}\nWith \\config{removeArcMean} the mean of each data column of each arc is reduced before.\n\nWith \\config{perColumn} separate statistics for each selected data column are computed,\notherwise an overall value is computed.\n\nSee also \\program{InstrumentArcStatistics}, \\program{InstrumentStatisticsTimeSeries}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute statistics for arcs of instrument data.\n* @ingroup programsGroup */\nclass InstrumentArcCrossStatistics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentArcCrossStatistics, PARALLEL, \"Compute RMS of an instrument time series or differences\", Instrument, Statistics)\n\n/***********************************************/\n\nvoid InstrumentArcCrossStatistics::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName    fileNameInstrumentOut;\n    FileName    fileNameInstrumentIn1, fileNameInstrumentIn2;\n    UInt        startData, countData = MAX_UINT;\n    Bool        removeMean, perColumn;\n    std::string choice;\n    std::function<double(const_MatrixSliceRef A, const_MatrixSliceRef B)> func;\n\n    readConfig(config, \"outputfileStatisticsTimeSeries\", fileNameInstrumentOut, Config::MUSTSET, \"\", \"statistics column(s) per arc, MISCVALUES\");\n    readConfig(config, \"inputfileInstrument\",            fileNameInstrumentIn1, Config::MUSTSET, \"\",   \"\");\n    readConfig(config, \"inputfileInstrumentReference\",   fileNameInstrumentIn2, Config::MUSTSET, \"\",   \"\");\n    if(readConfigChoice(config, \"statistics\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"correlation\",   choice, \"\"))                                func = [] (const_MatrixSliceRef A, const_MatrixSliceRef B) {return inner(A, B)/rootMeanSquare(A)/rootMeanSquare(B)/A.rows();};\n      if(readConfigChoiceElement(config, \"errorRMS\",      choice, \"rms of differences\"))              func = [] (const_MatrixSliceRef A, const_MatrixSliceRef B) {return rootMeanSquare(A-B);};\n      if(readConfigChoiceElement(config, \"nashSutcliffe\", choice, \"with respect to reference field\")) func = [] (const_MatrixSliceRef A, const_MatrixSliceRef B) {return 1-quadsum(A-B)/quadsum(A-mean(A));};\n      endChoice(config);\n    }\n    readConfig(config, \"removeArcMean\",   removeMean, Config::DEFAULT,  \"1\", \"\");\n    readConfig(config, \"startDataFields\", startData,  Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\", countData,  Config::OPTIONAL, \"\",  \"number of data fields (default: all)\");\n    readConfig(config, \"perColumn\",       perColumn,  Config::DEFAULT,  \"1\", \"compute statistic per column\");\n    if(isCreateSchema(config)) return;\n\n    // =================================================\n\n    logStatus<<\"read instrument file <\"<<fileNameInstrumentIn1<<\">\"<<Log::endl;\n    logStatus<<\"read instrument file <\"<<fileNameInstrumentIn2<<\">\"<<Log::endl;\n    InstrumentFile instrumentFile1(fileNameInstrumentIn1);\n    InstrumentFile instrumentFile2(fileNameInstrumentIn2);\n    InstrumentFile::checkArcCount({instrumentFile1, instrumentFile2});\n    std::vector<Matrix> rows(instrumentFile1.arcCount());\n    Parallel::forEach(rows, [&](UInt arcNo)\n    {\n      Arc arc1 = instrumentFile1.readArc(arcNo);\n      Arc arc2 = instrumentFile2.readArc(arcNo);\n      Arc::checkSynchronized({arc1, arc2});\n      if(arc1.size() == 0)\n        return Matrix();\n      const Matrix A = arc1.matrix();\n      const Matrix B = arc2.matrix();\n\n      // compute statistics\n      const UInt dataColumnCount = std::min(A.columns()-1-startData, countData);\n      const UInt columnCount     = perColumn ? dataColumnCount : 1;\n      Matrix row(1, 1+columnCount);\n      row(0, 0) = (0.5*(arc1.front().time+arc1.back().time)+medianSampling(arc1.times())).mjd();\n      for(UInt i=0; i<columnCount; i++)\n      {\n        const_MatrixSliceRef sliceA(A.column(1+startData+i, perColumn ? 1 : dataColumnCount));\n        const_MatrixSliceRef sliceB(B.column(1+startData+i, perColumn ? 1 : dataColumnCount));\n        row(0, 1+i) = (removeMean) ? func(sliceA-mean(sliceA), sliceB-mean(sliceB)) : func(sliceA, sliceB);\n      }\n      return row;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      // copy rows to matrix\n      rows.erase(std::remove_if(rows.begin(), rows.end(), [](const Matrix &A) {return !A.size();}), rows.end());\n      Matrix A(rows.size(), rows.at(0).columns());\n      for(UInt i=0; i<A.rows(); i++)\n        copy(rows.at(i), A.row(i));\n\n      logStatus<<\"write arc statistics to instrument file <\"<<fileNameInstrumentOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameInstrumentOut, Arc(A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/instruments/instrumentArcStatistics.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentArcStatistics.cpp\n*\n* @brief Compute statistics for arcs of instrument data.\n*\n* @author Sebastian Strasser\n* @author Matthias Ellmer\n* @author Torsten Mayer-Guerr\n* @date 2016-07-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes statistics of selected data columns of \\configFile{inputfileInstrument}{instrument} arc wise.\nThe \\configFile{outputfileStatisticsTimeSeries}{instrument} contains for every arc one (mid) epoch\nwith statistics column(s). Possible statistics are root mean square, standard deviation,\nmean, median, min, and max.\n\nWith \\config{perColumn} separate statistics for each selected data column are computed,\notherwise an overall value is computed.\n\nSee also \\program{InstrumentArcCrossStatistics}, \\program{InstrumentStatisticsTimeSeries}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute statistics for arcs of instrument data.\n* @ingroup programsGroup */\nclass InstrumentArcStatistics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentArcStatistics, PARALLEL, \"Compute statistics for arcs of instrument data\", Instrument, TimeSeries, Statistics)\n\n/***********************************************/\n\nvoid InstrumentArcStatistics::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName    fileNameInstrumentOut, fileNameInstrumentIn;\n    UInt        startData, countData = MAX_UINT;\n    Bool        perColumn, ignoreNan;\n    std::string choice;\n    std::function<double(const_MatrixSliceRef A)> func;\n\n    readConfig(config, \"outputfileStatisticsTimeSeries\", fileNameInstrumentOut, Config::MUSTSET, \"\", \"columns: mjd, statistics column(s) per instrument file\");\n    readConfig(config, \"inputfileInstrument\",            fileNameInstrumentIn,  Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"statistics\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"rootMeanSquare\",    choice)) func = rootMeanSquare;\n      if(readConfigChoiceElement(config, \"standardDeviation\", choice)) func = standardDeviation;\n      if(readConfigChoiceElement(config, \"mean\",              choice)) func = mean;\n      if(readConfigChoiceElement(config, \"median\",            choice)) func = median;\n      if(readConfigChoiceElement(config, \"min\",               choice)) func = static_cast<Double(*)(const_MatrixSliceRef)>(&min); // min and max are overloads, and the standard forbids automatic overload resolution in this context. So a manual cast is made in which the overload can be resolved successfully\n      if(readConfigChoiceElement(config, \"max\",               choice)) func = static_cast<Double(*)(const_MatrixSliceRef)>(&max);\n      if(readConfigChoiceElement(config, \"epochCount\",        choice)) func = [] (const_MatrixSliceRef A) {return static_cast<Double>(A.rows());};\n      endChoice(config);\n    }\n    readConfig(config, \"startDataFields\", startData, Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\", countData, Config::OPTIONAL, \"\",  \"number of data fields (default: all)\");\n    readConfig(config, \"perColumn\",       perColumn, Config::DEFAULT,  \"1\", \"compute statistic per column\");\n    readConfig(config, \"ignoreNan\",       ignoreNan, Config::DEFAULT,  \"0\", \"ignore NaN values in input\");\n    if(isCreateSchema(config)) return;\n\n    // =================================================\n\n    logStatus<<\"read instrument file <\"<<fileNameInstrumentIn<<\">\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameInstrumentIn);\n    std::vector<Matrix> rows(instrumentFile.arcCount());\n    Parallel::forEach(rows, [&](UInt arcNo)\n    {\n      const Arc    arc = instrumentFile.readArc(arcNo);\n      const Matrix A   = arc.matrix();\n      if(!A.size())\n        return Matrix();\n\n      // lambda function\n      auto removeNan = [](const_MatrixSliceRef A)\n      {\n        std::vector<Double> data = flatten(A);\n        data.erase(std::remove_if(data.begin(), data.end(), [](Double d) {return std::isnan(d);}), data.end());\n        return Vector(data);\n      };\n\n      // compute statistics\n      const UInt dataColumnCount = std::min(A.columns()-1-startData, countData);\n      const UInt columnCount     = perColumn ? dataColumnCount : 1;\n      Matrix row(1, 1+columnCount);\n      row(0, 0) =  (0.5*(arc.front().time+arc.back().time+medianSampling(arc.times()))).mjd();\n      for(UInt i=0; i<columnCount; i++)\n      {\n        const_MatrixSliceRef slice(A.column(1+startData+i, perColumn ? 1 : dataColumnCount));\n        row(0, 1+i) = func(ignoreNan ? removeNan(slice) : slice);\n      }\n      return row;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      // copy rows to matrix\n      rows.erase(std::remove_if(rows.begin(), rows.end(), [](const Matrix &A) {return !A.size();}), rows.end());\n      Matrix A(rows.size(), rows.at(0).columns());\n      for(UInt i=0; i<A.rows(); i++)\n        copy(rows.at(i), A.row(i));\n\n      logStatus<<\"write arc statistics to instrument file <\"<<fileNameInstrumentOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameInstrumentOut, Arc(A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentConcatenate.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentConcatenate.cpp\n*\n* @brief Concatenate arcs from several files.\n*\n* @author Torsten Mayer-Guerr\n* @author Norbert Zehentner\n* @date 2001-06-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program concatenate the arcs from several \\file{instrument files}{instrument}\nand write it to a new \\file{file}{instrument}. Input files must be of the same type.\nThe arcs are merged to one arc even though there is a gap inbetween.\nTo split the data into arcs use \\program{InstrumentSynchronize}.\nThree options are available: \\config{sort}, \\config{removeDuplicates} and \\config{checkForNaNs}.\nIf \\config{sort} is enabled, the program reads all files, no matter if they are sorted correctly in time, and\nthen sorts the epochs. If \\config{removeDuplicates} is enabled, the program checks the whole data set\nfor epochs that are contained twice. And if \\config{checkForNaNs} is enabled the data set is checked for\ninvalid epochs containing NaNs.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Concatenate arcs from several files.\n* @ingroup programsGroup */\nclass InstrumentConcatenate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentConcatenate, SINGLEPROCESS, \"concatenate arcs from several files\", Instrument)\nGROOPS_RENAMED_PROGRAM(ArcConcatenate, InstrumentConcatenate, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid InstrumentConcatenate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<FileName> inName;\n    Bool                  sort, checkNaN;\n    std::string           choiceRemoveDuplicates;\n    Double                margin;\n\n    readConfig(config, \"outputfile\", outName, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfile\",  inName,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"sort\",       sort,    Config::DEFAULT,  \"0\", \"sort epochs with increasing time\");\n    if(readConfigChoice(config, \"removeDuplicates\", choiceRemoveDuplicates, Config::OPTIONAL, \"\", \"remove duplicate epochs\"))\n    {\n      if(readConfigChoiceElement(config, \"keepFirst\", choiceRemoveDuplicates, \"keep first epoch with the same time stamp, remove all others\"))\n        readConfig(config, \"margin\", margin, Config::DEFAULT, \"1e-5\", \"margin for identical times [seconds]\");\n      if(readConfigChoiceElement(config, \"keepLast\",  choiceRemoveDuplicates, \"keep last epoch with the same time stamp, remove all others\"))\n        readConfig(config, \"margin\", margin, Config::DEFAULT, \"1e-5\", \"margin for identical times [seconds]\");\n      endChoice(config);\n    }\n    readConfig(config, \"checkForNaNs\", checkNaN, Config::DEFAULT,  \"0\", \"remove epochs with NaN values in one of the data fields\");\n    if(isCreateSchema(config)) return;\n\n    // read data\n    // ---------\n    Arc arc;\n    for(UInt i=0; i<inName.size(); i++)\n    {\n      try\n      {\n        logStatus<<\"read instrument file <\"<<inName.at(i)<<\">\"<<Log::endl;\n        arc.append(InstrumentFile::read(inName.at(i)));\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        continue;\n      }\n    }\n\n    // sort data\n    // ---------\n    if(sort || (choiceRemoveDuplicates == \"keepFirst\" || choiceRemoveDuplicates == \"keepLast\"))\n    {\n      logStatus<<\"sort epochs\"<<Log::endl;\n      arc.sort();\n    }\n\n    // eliminate duplicates\n    // --------------------\n    if(choiceRemoveDuplicates == \"keepFirst\" || choiceRemoveDuplicates == \"keepLast\")\n    {\n      logStatus<<\"eliminate duplicates\"<<Log::endl;\n      UInt oldSize = arc.size();\n      arc.removeDuplicateEpochs(choiceRemoveDuplicates == \"keepFirst\", margin);\n      logInfo<<\" \"<<oldSize-arc.size()<<\" duplicates removed!\"<<Log::endl;\n    }\n\n    // eliminate NaNs\n    // --------------------\n    if(checkNaN)\n    {\n      logStatus<<\"search for NaNs\"<<Log::endl;\n      UInt removed=0;\n      Log::Timer timer(arc.size());\n      for(UInt i=0; i<arc.size(); i++)\n      {\n        timer.loopStep(i);\n        if(std::isnan(sum(arc.at(i).data())))\n        {\n          arc.remove(i--);\n          removed++;\n        }\n      }\n      timer.loopEnd();\n      logInfo<<\" \"<<removed<<\" epochs with NaN values removed!\"<<Log::endl;\n    }\n\n    // save\n    // ----\n    logStatus<<\"write instrument file <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentCovarianceCheck.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentCovarianceCheck.cpp\n*\n* @brief Remove non invertible covriance matrices.\n*\n* @author Norbert Zehentner\n* @date 2016-01-20\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program checks \\configFile{inputfileCovariance3d}{instrument}\n3x3 covariance matrices if they are invertible or not and removes the invalid epochs.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Remove non invertible covariance matrices.\n* @ingroup programsGroup */\nclass InstrumentCovarianceCheck\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentCovarianceCheck, PARALLEL, \"Remove non invertible covariance matrices\", Instrument, Covariance)\n\n/***********************************************/\n\nvoid InstrumentCovarianceCheck::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n\n    readConfig(config, \"outputfileCovariance3d\", fileNameOut, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileCovariance3d\",  fileNameIn,  Config::MUSTSET,  \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read and check covariance <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile file(fileNameIn);\n    std::vector<Covariance3dArc> arcCov(file.arcCount());\n    UInt removed = 0;\n    Parallel::forEach(arcCov, [&](UInt arcNo)\n    {\n      Covariance3dArc arc = file.readArc(arcNo);\n      Covariance3dArc arcNew;\n      for(UInt i=0; i<arc.size(); i++)\n      {\n        try\n        {\n          Matrix W = arc.at(i).covariance.matrix();\n          cholesky(W);\n          arcNew.push_back(arc.at(i));\n        }\n        catch(std::exception &/*e*/)\n        {\n          removed++;\n        }\n      }\n      return arcNew;\n    }, comm);\n    Parallel::reduceSum(removed, 0, comm);\n    logInfo<<\"  \"<<removed<<\" epochs removed\"<<Log::endl;\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write covariance to file <\"<<fileNameOut<<\"> \"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcCov);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentDetrend.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentDetrend.cpp\n*\n* @brief Reduces temporal parametrization (e.g. trend, polynomial) per arc from instrument file.\n*\n* @author Sebastian Strasser\n* @date 2017-06-06\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nReduces \\configClass{parametrizationTemporal}{parametrizationTemporalType} (e.g. const, trend, polynomial)\nper arc from selected data columns of \\configFile{inputfileInstrument}{instrument}\nusing a robust \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\nThe \\configFile{outputfileTimeSeriesArcParameters}{instrument} contains for every arc one (mid) epoch\nwith the estimated parameters. The order is: first all data (\\verb|data0|, \\verb|data1|, \\ldots)\nof first temporal parameter, followed by all data of the second temporal parameter and so on.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Reduces temporal parametrization (e.g. trend, polynomial) from instrument file.\n* @ingroup programsGroup */\nclass InstrumentDetrend\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentDetrend, PARALLEL, \"Reduces temporal parametrization (e.g. trend, polynomial) per arc from instrument file.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentDetrend::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName                   fileNameOut, fileNameParameters;\n    FileName                   fileNameIn;\n    ParametrizationTemporalPtr temporal;\n    UInt                       startData, countData = MAX_UINT;\n    Double                     huber, huberPower;\n    UInt                       maxIter;\n\n    renameDeprecatedConfig(config, \"temporalRepresentation\", \"parametrizationTemporal\", date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileInstrument\",              fileNameOut,        Config::MUSTSET,  \"\",    \"detrended instrument time series\");\n    readConfig(config, \"outputfileTimeSeriesArcParameters\", fileNameParameters, Config::OPTIONAL, \"\",    \"time series of estimated parameters per arc\");\n    readConfig(config, \"inputfileInstrument\",               fileNameIn,         Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"parametrizationTemporal\",           temporal,           Config::MUSTSET,  \"\",    \"per arc, data is reduced by temporal representation\");\n    readConfig(config, \"startDataFields\",                   startData,          Config::DEFAULT,  \"0\",   \"start\");\n    readConfig(config, \"countDataFields\",                   countData,          Config::OPTIONAL, \"\",    \"number of data fields (default: all after start)\");\n    readConfig(config, \"huber\",                             huber,              Config::DEFAULT,  \"2.5\", \"for robust least squares\");\n    readConfig(config, \"huberPower\",                        huberPower,         Config::DEFAULT,  \"1.5\", \"for robust least squares\");\n    readConfig(config, \"huberMaxIteration\",                 maxIter,            Config::DEFAULT,  \"5\",   \"(maximum) number of iterations for robust estimation\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument files <\"<<fileNameIn<<\"> and detrending\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameIn);\n    countData = std::min(countData, instrumentFile.dataCount(TRUE/*mustDefined*/)-startData);\n\n    Matrix arcParameters;\n    if(!fileNameParameters.empty())\n      arcParameters = Matrix(instrumentFile.arcCount(), 1+countData*temporal->parameterCount());\n\n    std::vector<Arc> arcList(instrumentFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc arc = instrumentFile.readArc(arcNo);\n      if(arc.size() == 0)\n        return arc;\n\n      // fill design matrix\n      const std::vector<Time> times = arc.times();\n      temporal->setInterval(times.front(), times.back()+medianSampling(times), TRUE);\n      Matrix A(arc.size(), temporal->parameterCount());\n      for(UInt idEpoch=0; idEpoch<arc.size(); idEpoch++)\n        copy(temporal->factors(times.at(idEpoch)).trans(), A.row(idEpoch));\n\n      Matrix l = arc.matrix();\n      Vector sigma;\n      Matrix x = Vce::robustLeastSquares(A, l.column(1+startData, countData), 1, huber, huberPower, maxIter, sigma);\n      matMult(-1., A, x, l.column(1+startData, countData)); // residuals\n\n      if(arcParameters.size())\n      {\n        arcParameters(arcNo, 0) = (0.5*(times.front()+times.back()+medianSampling(times))).mjd();\n        copy(flatten(x.trans()).trans(), arcParameters.slice(arcNo, 1, 1, x.size()));\n      }\n\n      return Arc(times, l, arc.getType());\n    }, comm); // forEach\n\n    // ======================================================\n\n    if(!fileNameOut.empty() && Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n\n    if(!fileNameParameters.empty() && arcParameters.size())\n    {\n      Parallel::reduceSum(arcParameters, 0, comm);\n      if(Parallel::isMaster(comm))\n      {\n        logStatus<<\"write arc parameters to instrument file <\"<<fileNameParameters<<\">\"<<Log::endl;\n        InstrumentFile::write(fileNameParameters, Arc(arcParameters));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentEarthRotation.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentEarthRotation.cpp\n*\n* @brief Precompute Earth rotation matrix (CRF -> TRF) and save as StarCamera file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-05-12\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nPrecompute Earth rotation matrix from celestial to terrestrial frame\nand save as \\file{StarCamera file}{instrument}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***********************************************/\n\n/** @brief Precompute Earth rotation matrix (CRF -> TRF) and save as StarCamera file.\n* @ingroup programsGroup */\nclass InstrumentEarthRotation\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentEarthRotation, SINGLEPROCESS, \"Precompute Earth rotation matrix (CRF -> TRF) and save as StarCamera file.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentEarthRotation::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         fileNameStarCamera;\n    EarthRotationPtr earthRotation;\n    TimeSeriesPtr    timeSeries;\n\n    readConfig(config, \"outputfileStarCamera\", fileNameStarCamera, Config::MUSTSET, \"\", \"rotation from CRF to TRF\");\n    readConfig(config, \"earthRotation\",        earthRotation,      Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time> times = timeSeries->times();\n\n    logStatus<<\"computing earth rotation\"<<Log::endl;\n    Arc arc;\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      StarCameraEpoch epoch;\n      epoch.time = times.at(i);\n      epoch.rotary = earthRotation->rotaryMatrix(times.at(i));\n      arc.push_back(epoch);\n    });\n\n    logStatus<<\"write star camera data to file <\"<<fileNameStarCamera<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameStarCamera, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentEstimateEmpiricalCovariance.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentEstimateEmpiricalCovariance.cpp\n*\n* @brief Estimate the empirical covariance matrix of an instrument file.\n**\n* @author Andreas Kvas\n* @date 2017-06-06\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates the empirical auto- and cross-covariance of selected data columns per arc\nof \\configFile{inputfileInstrument}{instrument}.\nThe maximum computed lag is determined by the number of \\configFile{outputfileCovarianceMatrix}{matrix} specified\n(for a single output file only the auto-covariance is determined, for two output files auto- and cross-covariance is computed and so on).\n\nStationarity is assumed for the input time series, which means the temporal covariance matrix has Toeplitz structure.\n\\begin{equation}\n\\begin{bmatrix}\n\\Sigma & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\Sigma_{\\Delta_3} & \\Sigma_{\\Delta_4} \\\\\n       & \\Sigma            & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} & \\Sigma_{\\Delta_3} \\\\\n       &                   & \\Sigma            & \\Sigma_{\\Delta_1} & \\Sigma_{\\Delta_2} \\\\\n       &                   &                   & \\Sigma            & \\Sigma_{\\Delta_1} \\\\\n       &                   &                   &                   & \\Sigma            \\\\\n\\end{bmatrix}\n\\end{equation}\n\nThe matrix for lag $h$ describes the covariance between $x_{t-h}$ and $x_{t}$, i.e. $\\Sigma(t-h, t)$.\n\nTo get a reliable estimate, \\program{InstrumentDetrend} should be called first.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate the empirical covariance matrix of an instrument file.\n* @ingroup programsGroup */\nclass InstrumentEstimateEmpiricalCovariance\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentEstimateEmpiricalCovariance, PARALLEL, \"Estimate the empirical covariance matrix of an instrument file\", Instrument, Covariance)\n\n/***********************************************/\n\nvoid InstrumentEstimateEmpiricalCovariance::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<FileName> fileNameOut;\n    FileName              fileNameIn;\n    UInt                  startData, countData = MAX_UINT;\n\n    readConfig(config, \"outputfileCovarianceMatrix\", fileNameOut, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileInstrument\",        fileNameIn,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startDataFields\",            startData,   Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\",            countData,   Config::OPTIONAL, \"\",  \"number of data fields (default: all after start)\");\n    if(isCreateSchema(config)) return;\n\n    InstrumentFile instrumentFile(fileNameIn);\n    const UInt dim = std::min(countData, instrumentFile.dataCount(TRUE/*mustDefined*/)-startData);\n\n    Double countEpochs = 0;\n    std::vector<Matrix> covarianceMatrix(fileNameOut.size(), Matrix(dim, dim));\n    covarianceMatrix.front().setType(Matrix::SYMMETRIC);\n    Parallel::forEach(instrumentFile.arcCount(), [&](UInt arcNo)\n    {\n      Matrix data = instrumentFile.readArc(arcNo).matrix();\n      if(data.rows() < fileNameOut.size()) return;\n      countEpochs += data.rows();\n\n      rankKUpdate(1, data.column(startData+1, dim), covarianceMatrix.at(0)); // x_{t-h}*x_{t}^T\n      for(UInt h=1; h<fileNameOut.size(); h++)\n        matMult(1., data.slice(0, startData+1, data.rows()-h, dim).trans(), data.slice(h, startData+1, data.rows()-h, dim), covarianceMatrix.at(h)); // x_{t-h}*x_{t}^T\n    }, comm); // forEach\n\n    Parallel::reduceSum(countEpochs, 0, comm);\n    for(UInt h=0; h<covarianceMatrix.size(); h++)\n      Parallel::reduceSum(covarianceMatrix.at(h), 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      for(UInt h=0; h<fileNameOut.size(); h++)\n      {\n        logStatus<<\"write covariance matrix to <\"<<fileNameOut.at(h)<<\">.\"<<Log::endl;\n        writeFileMatrix(fileNameOut.at(h), 1./(countEpochs-instrumentFile.arcCount()*h) * covarianceMatrix.at(h));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentEstimateHelmertTransformation.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentEstimateHelmertTransformation.cpp\n*\n* @brief Estimate Helmert transformation parameters between two networks (frame realizations).\n*\n* @author Sebastian Strasser\n* @date 2018-01-31\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates a 3D Helmert transformation between two networks\n(frame realizations, e.g. GNSS satellite or station network).\nEach separate \\config{data} represents a satellite/station/\\ldots (e.g. 32 GPS satellites).\nThe instrument data (x,y,z position) considered can be set with \\config{startData}.\nThe Helmert parameters are set up according to \\configClass{parametrizationTemporal}{parametrizationTemporalType}\nfor each \\configClass{timeIntervals}{timeSeriesType} and are estimated using a\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate Helmert transformation parameters between two networks (frame realizations).\n* @ingroup programsGroup */\nclass InstrumentEstimateHelmertTransformation\n{\npublic:\n  class Data\n  {\n  public:\n    FileName outNameInstrumentTransformed, outNameInstrumentDiff, inNameInstrument, inNameInstrumentRef;\n    std::vector<Time> times;\n    std::vector<UInt> intervalBoundaries;\n    Matrix pos, posRef;\n    UInt   startData;\n    Bool   useable;\n\n    void init(const std::vector<Time> &intervals);\n    void removeEpochsOutsideIntervals(const FileName &fileName, const std::vector<Time> &intervals, Arc &arc) const;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentEstimateHelmertTransformation, SINGLEPROCESS, \"Compute RMS time series from instrument file(s).\", Instrument, Gnss)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, InstrumentEstimateHelmertTransformation::Data &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n\n  renameDeprecatedConfig(config, \"startData\", \"startDataFields\", date2time(2020, 7, 14));\n\n  readConfig(config, \"outputfileInstrument\",         var.outNameInstrumentTransformed, Config::OPTIONAL, \"\", \"transformed positions as instrument type Vector3d\");\n  readConfig(config, \"outputfileInstrumentDiff\",     var.outNameInstrumentDiff,        Config::OPTIONAL, \"\", \"position difference as instrument type Vector3d\");\n  readConfig(config, \"inputfileInstrument\",          var.inNameInstrument,             Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"inputfileInstrumentReference\", var.inNameInstrumentRef,          Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"startDataFields\",              var.startData,                    Config::DEFAULT,  \"0\", \"start index of position (x,y,z) columns\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid InstrumentEstimateHelmertTransformation::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                   fileNameHelmertTimeSeries;\n    std::vector<Data>          data;\n    TimeSeriesPtr              intervalsPtr;\n    Bool                       estimateShift, estimateScale, estimateRotation;\n    ParametrizationTemporalPtr parametrization;\n    Double                     huber, huberPower;\n    UInt                       iterCount;\n\n    renameDeprecatedConfig(config, \"temporalRepresentation\", \"parametrizationTemporal\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"intervals\",              \"timeIntervals\",           date2time(2020, 7, 14));\n\n    readConfig(config, \"outputfileHelmertTimeSeries\", fileNameHelmertTimeSeries, Config::OPTIONAL, \"\",  \"columns: mjd, Tx,Ty,Tz,s,Rx,Ry,Rz according to temporal parametrization\");\n    readConfig(config, \"data\",                        data,                      Config::MUSTSET,  \"\",  \"e.g. satellite, station\");\n    readConfig(config, \"timeIntervals\",               intervalsPtr,              Config::MUSTSET,  \"\",  \"parameters are estimated per interval\");\n    readConfig(config, \"parametrizationTemporal\",     parametrization,           Config::MUSTSET,  \"\",  \"temporal parametrization\");\n    readConfig(config, \"estimateShift\",               estimateShift,             Config::DEFAULT,  \"1\", \"coordinate center\");\n    readConfig(config, \"estimateScale\",               estimateScale,             Config::DEFAULT,  \"1\", \"scale factor of position\");\n    readConfig(config, \"estimateRotation\",            estimateRotation,          Config::DEFAULT,  \"1\", \"rotation\");\n    readConfig(config, \"huber\",                       huber,                     Config::DEFAULT,  \"2.5\", \"for robust least squares\");\n    readConfig(config, \"huberPower\",                  huberPower,                Config::DEFAULT,  \"1.5\", \"for robust least squares\");\n    readConfig(config, \"huberMaxIteration\",           iterCount,                 Config::DEFAULT,  \"30\",  \"(maximum) number of iterations for robust estimation\");\n    if(isCreateSchema(config)) return;\n\n    const std::vector<Time> intervals = intervalsPtr->times();\n    if(intervals.size() < 2)\n      throw(Exception(\"invalid intervals\"));\n\n    for(auto &&d : data)\n    {\n      logStatus << \"read instrument file <\" << d.inNameInstrument << \">\" << Log::endl;\n      d.init(intervals);\n    }\n    data.erase(std::remove_if(data.begin(), data.end(), [](const Data &d){ return !d.useable; }), data.end());\n\n    const UInt paramCount    = 3*estimateShift+estimateScale+3*estimateRotation;\n    const UInt intervalCount = intervals.size() - 1;\n    std::vector<Vector> helmertTimeSeries;\n    Single::forEach(intervalCount, [&](UInt idInterval)\n    {\n      parametrization->setInterval(intervals.at(idInterval), intervals.at(idInterval+1));\n      const UInt trendCount = parametrization->parameterCount();\n\n      // check if interval has data\n      UInt epochCount = 0;\n      for(const auto &d : data)\n        epochCount += d.intervalBoundaries.at(idInterval+1) - d.intervalBoundaries.at(idInterval);\n      if(epochCount == 0)\n      {\n        logWarning<<\"No data found in interval \"+intervals.at(idInterval).dateTimeStr()+\" -> \"+intervals.at(idInterval+1).dateTimeStr()+\". continue with next interval\"<<Log::endl;\n        return;\n      }\n\n      // check if interval is solvable\n      if(3*static_cast<UInt>(std::count_if(data.begin(), data.end(), [&](const Data &d){ return ((d.intervalBoundaries.at(idInterval+1)-d.intervalBoundaries.at(idInterval)) >= trendCount); })) < paramCount)\n        throw(Exception(\"interval \"+intervals.at(idInterval).dateTimeStr()+\" -> \"+intervals.at(idInterval+1).dateTimeStr()+\" not solvable\"));\n\n      // set up observation vector and design matrix\n      UInt idRow = 0;\n      Vector l(3*epochCount);\n      Matrix A(3*epochCount, paramCount*trendCount);\n      for(const auto &d : data)\n      {\n        for(UInt idEpoch=d.intervalBoundaries.at(idInterval); idEpoch<d.intervalBoundaries.at(idInterval+1); idEpoch++)\n        {\n          copy((d.pos.row(idEpoch) - d.posRef.row(idEpoch)).trans(), l.row(idRow, 3));\n\n          std::vector<UInt>   index;\n          std::vector<Double> factor;\n          parametrization->factors(d.times.at(idEpoch), index, factor);\n\n          for(UInt k = 0; k < index.size(); k++)\n          {\n            UInt idCol = index.at(k)*paramCount;\n            if(estimateShift)\n            {\n              A(idRow+0, idCol++) = factor.at(k);\n              A(idRow+1, idCol++) = factor.at(k);\n              A(idRow+2, idCol++) = factor.at(k);\n            }\n            if(estimateScale)\n            {\n              Vector3d position(d.posRef.row(idEpoch));\n              A(idRow+0, idCol)   = position.x()/DEFAULT_R*factor.at(k);\n              A(idRow+1, idCol)   = position.y()/DEFAULT_R*factor.at(k);\n              A(idRow+2, idCol++) = position.z()/DEFAULT_R*factor.at(k);\n            }\n            if(estimateRotation)\n            {\n              Vector3d position(d.posRef.row(idEpoch));\n              A(idRow+1, idCol)   =  position.z()/DEFAULT_R*factor.at(k); //rx\n              A(idRow+2, idCol++) = -position.y()/DEFAULT_R*factor.at(k); //rx\n              A(idRow+0, idCol)   = -position.z()/DEFAULT_R*factor.at(k); //ry\n              A(idRow+2, idCol++) =  position.x()/DEFAULT_R*factor.at(k); //ry\n              A(idRow+0, idCol)   =  position.y()/DEFAULT_R*factor.at(k); //rz\n              A(idRow+1, idCol++) = -position.x()/DEFAULT_R*factor.at(k); //rz\n            }\n          }\n          idRow += 3;\n        }\n      }\n\n      // solve system and compute residuals\n      Vector x;\n      if(A.size())\n      {\n        Vector sigma;\n        x = Vce::robustLeastSquares(A, l, 3, huber, huberPower, iterCount, sigma);\n        l -= A*x;\n      }\n\n      // write residuals into input data\n      idRow = 0;\n      for(const auto &d : data)\n        for(UInt idEpoch=d.intervalBoundaries.at(idInterval); idEpoch<d.intervalBoundaries.at(idInterval+1); idEpoch++)\n          copy(l.row(3*idRow++, 3).trans(), d.pos.row(idEpoch));\n\n      // add Helmert parameters to time series\n      Vector h(1+paramCount*trendCount);\n      h(0) = 0.5*(intervals.at(idInterval)+intervals.at(idInterval+1)).mjd();\n      if(x.size())\n      {\n        copy(x, h.row(1, x.size()));\n        for(UInt k = 0; k < trendCount; k++)\n          if(estimateScale || estimateRotation)\n            h.row(1+k*paramCount+3*estimateShift, paramCount-3*estimateShift) /= DEFAULT_R;\n      }\n      helmertTimeSeries.push_back(h);\n    });\n\n    // save output files\n    for(const auto &d : data)\n      if(!d.outNameInstrumentTransformed.empty())\n      {\n        logStatus << \"write transformed instrument file <\" << d.outNameInstrumentTransformed << \">\" << Log::endl;\n        Matrix A(d.times.size(), 4);\n        copy(d.pos+d.posRef, A.column(1,3));\n        InstrumentFile::write(d.outNameInstrumentTransformed, Arc(d.times, A, Epoch::VECTOR3D));\n      }\n\n    for(const auto &d : data)\n      if(!d.outNameInstrumentDiff.empty())\n      {\n        logStatus << \"write difference instrument file <\" << d.outNameInstrumentDiff << \">\" << Log::endl;\n        Matrix A(d.times.size(), 4);\n        copy(d.pos, A.column(1,3));\n        InstrumentFile::write(d.outNameInstrumentDiff, Arc(d.times, A, Epoch::VECTOR3D));\n      }\n\n    if(!fileNameHelmertTimeSeries.empty() && (estimateShift || estimateScale || estimateRotation))\n    {\n      logStatus<<\"write Helmert time series to file <\"<<fileNameHelmertTimeSeries<<\">\"<<Log::endl;\n      Matrix H(helmertTimeSeries.size(), 1+paramCount*parametrization->parameterCount());\n      for(UInt i=0; i<H.rows(); i++)\n        copy(helmertTimeSeries.at(i).trans(), H.row(i));\n      writeFileMatrix(fileNameHelmertTimeSeries, H);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentEstimateHelmertTransformation::Data::init(const std::vector<Time> &intervals)\n{\n  try\n  {\n    useable = FALSE;\n\n    Arc arc, arcRef;\n    try\n    {\n      arc    = InstrumentFile::read(inNameInstrument);\n      arcRef = InstrumentFile::read(inNameInstrumentRef);\n    }\n    catch(std::exception &e)\n    {\n      logWarning << e.what() << Log::endl;\n      return;\n    }\n    removeEpochsOutsideIntervals(inNameInstrument,    intervals, arc);\n    removeEpochsOutsideIntervals(inNameInstrumentRef, intervals, arcRef);\n\n    if(!arc.size() || arc.times() != arcRef.times())\n    {\n      logWarning << \"arcs empty or not synchronized: \" << arc.size() << \" != \" << arcRef.size() << \", skipping\" << Log::endl;\n      return;\n    }\n\n    times  = arc.times();\n    pos    = arc.matrix().column(1+startData,3);\n    posRef = arcRef.matrix().column(1+startData,3);\n\n    // find epochs IDs of interval boundaries\n    UInt idEpoch = 0;\n    intervalBoundaries.push_back(idEpoch);\n    for(UInt idInterval = 0; idInterval < intervals.size()-1; idInterval++)\n    {\n      while(idEpoch < times.size() && times.at(idEpoch) < intervals.at(idInterval+1))\n        idEpoch++;\n      intervalBoundaries.push_back(idEpoch);\n    }\n\n    useable = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentEstimateHelmertTransformation::Data::removeEpochsOutsideIntervals(const FileName &fileName, const std::vector<Time> &intervals, Arc &arc) const\n{\n  UInt removedEpochs = arc.size();\n  for(UInt idEpoch = arc.size(); idEpoch --> 0; )\n    if(arc.at(idEpoch).time < intervals.front() || arc.at(idEpoch).time >= intervals.back())\n      arc.remove(idEpoch);\n  removedEpochs -= arc.size();\n  if(removedEpochs > 0)\n    logWarning << \"removed \" << removedEpochs << \" epochs outside interval boundaries from <\" << fileName << \">\" << Log::endl;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentFilter.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentFilter.cpp\n*\n* @brief Filter any instrument data arc wise.\n*\n* @author Andreas Kvas\n* @date 2016-06-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program filter selected data columns of \\configFile{inputfileInstrument}{instrument}\nwith \\configClass{digitalFilter}{digitalFilterType} arc wise.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Filter any intrument file arc wise.\n* @ingroup programsGroup */\nclass InstrumentFilter\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentFilter, PARALLEL, \"filter any instrument file arc wise\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentFilter::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameOut, fileNameIn;\n    DigitalFilterPtr filter;\n    UInt             startData, countData = MAX_UINT;\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"digitalFilter\",        filter,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startDataFields\",      startData,   Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\",      countData,   Config::OPTIONAL, \"\",  \"number of data fields (default: all after start)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data <\"<<fileNameIn<<\"> and filter\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameIn);\n\n    std::vector<Arc> arcList(instrumentFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc arc = instrumentFile.readArc(arcNo);\n      if(arc.size() == 0)\n        return arc;\n      Matrix data = arc.matrix();\n      countData = std::min(countData, data.columns()-1-startData);\n      copy(filter->filter(data.column(1+startData, countData)), data.column(1+startData, countData));\n      return Arc(arc.times(), data, arc.getType());\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentInsertNAN.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentInsertNAN.cpp\n*\n* @brief insert epochs with data NAN into instrument files\n*\n* @author Matthias Ellmer\n* @date 2017-11-28\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program inserts NAN epochs into \\configFile{inputfileInstrument}{instrument} files,\neither at specific \\configClass{times}{timeSeriesType} or where gaps in the instrument are detected.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Insert epochs with data NAN into instrument files\n* @ingroup programsGroup */\nclass InstrumentInsertNAN\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentInsertNAN, PARALLEL, \"Insert epochs with data NAN into instrument files\", Instrument, Plot)\n\n/***********************************************/\n\nvoid InstrumentInsertNAN::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName      inputfileInstrument, outputfileInstrument;\n    TimeSeriesPtr timeSeries;\n    Bool          atGaps;\n    Bool          atArcEnds;\n\n    readConfig(config, \"outputfileInstrument\", outputfileInstrument, Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"inputfileInstrument\",  inputfileInstrument,  Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"times\",                timeSeries,           Config::DEFAULT, \"\",  \"Insert NAN at specific times.\");\n    readConfig(config, \"atGaps\",               atGaps,               Config::DEFAULT, \"0\", \"Insert NAN where epochs are more than 1.5 times the median sampling apart.\");\n    readConfig(config, \"atArcEnds\",            atArcEnds,            Config::DEFAULT, \"0\", \"Insert one epoch with data NAN at arc ends\");\n    if(isCreateSchema(config)) return;\n\n    const auto nanTimes = timeSeries->times();\n\n    InstrumentFile inFile(inputfileInstrument);\n    const UInt arcCount = inFile.arcCount();\n\n    std::vector<Arc> arcList(arcCount);\n    UInt total = 0;\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc arc = inFile.readArc(arcNo);\n      if(!arc.size())\n        return arc;\n\n      Epoch *epoch = Epoch::create(arc.getType());\n      epoch->setData(arc.at(0).data() * NAN_EXPR);\n\n      const auto times = arc.times();\n      const Time epsilonTime = Time(0,std::numeric_limits<Double>::epsilon());\n\n      // ----------\n\n      if(nanTimes.size())\n      {\n        // First value in nanTimes larger than times.begin()\n        UInt nanIndex = std::distance(nanTimes.begin(), std::upper_bound(nanTimes.begin(), nanTimes.end(), times.front()));\n        auto it = times.begin();\n\n        std::vector<UInt> indicesToInsert;\n        for(; nanIndex<nanTimes.size(); nanIndex++)\n        {\n          // Find the position of the nan epoch in this arc\n          it = std::lower_bound(it, times.end(), nanTimes.at(nanIndex));\n          if(it == times.end())\n            break;\n\n          indicesToInsert.push_back(std::distance(times.begin(), it));\n        }\n\n        // Insert starting from back to not screw up the indices.\n        std::reverse(indicesToInsert.begin(), indicesToInsert.end());\n        for(const UInt i : indicesToInsert)\n        {\n          epoch->time = times.at(i-1) + epsilonTime;\n          arc.insert(i, *epoch);\n          total++;\n        }\n      }\n\n      // ----------\n\n      if(atGaps && times.size() > 2)\n      {\n        std::vector<Time> diff(times.size());\n        std::adjacent_difference(times.begin(), times.end(), diff.begin());\n\n        std::vector<UInt> indicesToInsert;\n        const Double minGap = 1.5 * medianSampling(times).seconds();\n        for(UInt i=1; i<diff.size(); i++)\n        {\n          if(diff.at(i).seconds() > minGap)\n            indicesToInsert.push_back(i);\n        }\n\n        std::reverse(indicesToInsert.begin(), indicesToInsert.end());\n        for(const UInt i : indicesToInsert)\n        {\n          epoch->time = times.at(i-1) + epsilonTime;\n          arc.insert(i, *epoch);\n          total++;\n        }\n      }\n\n      // ----------\n\n      if(atArcEnds)\n      {\n        epoch->time = times.back() + epsilonTime;\n        arc.push_back(*epoch);\n        total++;\n      }\n\n      return arc;\n    }, comm);\n\n    Parallel::reduceSum(total, 0, comm);\n    logStatus<<\"  inserted \"<<total<<\" NaNs\"<<Log::endl;\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument to file <\"<<outputfileInstrument<<\">\"<<Log::endl;\n      InstrumentFile::write(outputfileInstrument, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentMultiplyAdd.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentMultiplyAdd.cpp\n*\n* @brief Multiply instrument data with a factor and add them together.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-06-24\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program multiply \\file{instrument data}{instrument} with a factor and add them together.\nAfterwards the mean of each arc and data column can be removed with \\config{removeArcMean}.\nThe instrument files must be synchronized (\\program{InstrumentSynchronize}).\n\nSee also \\program{InstrumentArcCalculate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Multiply instrument data with a factor and add them together.\n* @ingroup programsGroup */\nclass InstrumentMultiplyAdd\n{\npublic:\n  class Data\n  {\n    public:\n    FileName fileName;\n    Double   factor;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentMultiplyAdd, PARALLEL, \"Multiply instrument data with a factor and add them together\", Instrument)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, InstrumentMultiplyAdd::Data &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileInstrument\", var.fileName, Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"factor\",              var.factor,   Config::DEFAULT,  \"1.0\", \"\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid InstrumentMultiplyAdd::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<Data> data;\n    Bool removeMean;\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"instrument\",           data,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"removeArcMean\",        removeMean,  Config::DEFAULT,  \"0\", \"remove mean value of each arc\");\n    if(isCreateSchema(config)) return;\n\n    // open files and check consistency\n    std::vector<InstrumentFilePtr> instrumentFile(data.size());\n    for(UInt i=0; i<instrumentFile.size(); i++)\n    {\n      logStatus<<\"read instrument data <\"<<data.at(i).fileName<<\">\"<<Log::endl;\n      instrumentFile.at(i) = InstrumentFile::newFile(data.at(i).fileName);\n      InstrumentFile::checkArcCount({*instrumentFile.at(0), *instrumentFile.at(i)});\n      if(instrumentFile.at(i)->getType() != instrumentFile.at(0)->getType())\n        throw(Exception(\"instruments types are different: \"+instrumentFile.at(i)->getTypeName()+\", \"+instrumentFile.at(0)->getTypeName()));\n    }\n\n    logStatus<<\"combine instrument data\"<<Log::endl;\n    std::vector<Arc> arcList(instrumentFile.at(0)->arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc arc = instrumentFile.at(0)->readArc(arcNo);\n      Matrix A = data.at(0).factor * arc.matrix();\n      for(UInt i=1; i<instrumentFile.size(); i++)\n      {\n        Arc arc2 = instrumentFile.at(i)->readArc(arcNo);\n        Arc::checkSynchronized({arc, arc2});\n        axpy(data.at(i).factor, arc2.matrix(), A);\n      }\n\n      if(removeMean)\n        for(UInt k=0; k<A.columns(); k++)\n          A.column(k) -= mean(A.column(k));\n\n      return Arc(arc.times(), A, arc.getType());\n    }, comm);\n\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentReduceSampling.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentReduceSampling.cpp\n*\n* @brief Reduce sampling of instrument data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-01-06\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reduce the sampling of a instrument file. Only epochs with a time stamp\nwith a division by \\config{sampling} without remainder are kept (inside \\config{margin}).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Reduce sampling of instrument data.\n* @ingroup programsGroup */\nclass InstrumentReduceSampling\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentReduceSampling, SINGLEPROCESS, \"reduce sampling of instrument data.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentReduceSampling::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName inName, outName;\n    Double   seconds, margin;\n    Bool     relative2FirstEpoch;\n\n    readConfig(config, \"outputfileInstrument\", outName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",  inName,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"sampling\",             seconds, Config::MUSTSET,   \"\",     \"new sampling in seconds\");\n    readConfig(config, \"margin\",               margin,  Config::DEFAULT,   \"1e-5\", \"margin around the new sampling in seconds\");\n    readConfig(config, \"relative2FirstEpoch\",  relative2FirstEpoch,  Config::DEFAULT,   \"0\", \"compute sampling relative to time of first epoch\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data <\"<<inName<<\"> and reduce sampling\"<<Log::endl;\n    InstrumentFile  inFile(inName);\n    UInt arcCount = inFile.arcCount();\n    std::list<Arc> arcList;\n\n    Double refTime=0;\n    Single::forEach(arcCount, [&](UInt arcNo)\n    {\n      std::vector<Time> times;\n      Arc arc = inFile.readArc(arcNo);\n      if(arcNo==0 && relative2FirstEpoch)\n        refTime = arc.at(0).time.mjdMod();\n      for(UInt i=0; i<arc.size(); i++)\n      {\n\n        Double mod = std::fmod((arc.at(i).time.mjdMod()-refTime)*86400, seconds);\n\n        if(mod/seconds > 0.5)\n          mod -= seconds;\n        if(fabs(mod) <= margin)\n          if((times.size()==0) || (arc.at(i).time-times.back()).seconds()>(seconds-margin))\n            times.push_back(arc.at(i).time);\n      }\n\n      arc.synchronize(times, margin);\n      if(arc.size()!=0)\n        arcList.push_back(arc);\n    });\n\n    logStatus<<\"write instrument data to <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, arcList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentRemoveEpochsByCriteria.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentRemoveEpochsByCriteria.cpp\n*\n* @brief Remove epochs through evaluating expressions\n*\n* @author Norbert Zehentner\n* @author Beate Klinger\n* @author Matthias Ellmer\n* @author Andreas Kvas\n* @date 2015-05-19\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program removes epochs from \\configFile{inputfileInstrument}{instrument}\nby evaluating a set of \\config{removalCriteria} expressions. For the data\ncolumns the standard data variables are available,\nsee~\\reference{dataVariables}{general.parser:dataVariables}.\n\nThe instrument data can be reduced by data from \\configFile{inputfileInstrumentReference}{instrument}\nprior to evaluation of the expressions.\n\nTo reduce the data by its median, use an expression like \\verb|data1-data1mean|.\nTo remove epochs that deviate by more than 3 sigma use \\verb|abs(data1)>3*data1std|\nor \\verb|abs(data0-data0median)>3*1.4826*data0mad|.\n\nAll arcs in the input instrument file are concatenated, meaning expressions\nlike \\verb|data1mean| refer to the complete dataset. The removed epochs can be saved\nin a separate \\configFile{outputfileInstrumentRemovedEpochs}{instrument}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Remove epochs which meet one of several criteria.\n* @ingroup programsGroup */\nclass InstrumentRemoveEpochsByCriteria\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentRemoveEpochsByCriteria, SINGLEPROCESS, \"Remove epochs which criteria defined through expressions\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentRemoveEpochsByCriteria::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameRemovedEpochs;\n    FileName fileNameIn,  fileNameRef;\n    std::vector<ExpressionVariablePtr> expressions;\n    Double   margin;\n\n    readConfig(config, \"outputfileInstrument\",               fileNameOut,           Config::OPTIONAL, \"\", \"all data is stored in one arc\");\n    readConfig(config, \"outputfileInstrumentRemovedEpochs\",  fileNameRemovedEpochs, Config::OPTIONAL, \"\", \"all data is stored in one arc\");\n    readConfig(config, \"inputfileInstrument\",                fileNameIn,            Config::MUSTSET,  \"\", \"arcs are concatenated for processing\");\n    readConfig(config, \"inputfileInstrumentReference\",       fileNameRef,           Config::OPTIONAL, \"\", \"if given, the reference data is reduced prior to the expressions being evaluated\");\n    readConfig(config, \"removalCriteria\",                    expressions,           Config::MUSTSET,  \"abs(data0-data0median) > 3*1.4826*data0mad\",  \"epochs are removed if one criterion evaluates true. data0 is the first data field.\");\n    readConfig(config, \"margin\",                             margin,                Config::DEFAULT,  \"1e-5\", \"remove data around identified epochs (on both sides) [seconds]\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    // read instrument data\n    // --------------------\n    logStatus<<\"read instrument data <\"<<fileNameIn<<\">\"<<Log::endl;\n    const Arc arc = InstrumentFile::read(fileNameIn);\n    Matrix data = arc.matrix();\n    if(data.columns()<2)\n      throw(Exception(\"input file <\"+fileNameIn.str()+\"> does not have enough columns (Found: \"+data.columns()%\"%i).\"s));\n\n\n    // reduce reference data\n    // ---------------------\n    if(!fileNameRef.empty())\n    {\n      logStatus<<\"read reference data <\"<<fileNameRef<<\">\"<<Log::endl;\n      const Arc arcRef = InstrumentFile::read(fileNameRef);\n      Arc::checkSynchronized({arc, arcRef});\n\n      // Reduce reference data\n      Matrix reference = arcRef.matrix();\n      if(reference.columns() != data.columns())\n        throw(Exception(\"Reference file <\"+fileNameRef.str()+\"> has incompatible number of data columns with data file <\"+fileNameIn.str()+\"> (\"+ reference.columns() % \"%i vs \"s + data.columns() % \"%i ).\"s));\n      axpy(-1., reference.column(1, reference.columns()-1), data.column(1, data.columns()-1) );\n    }\n    // Remove time column\n    data = data.column(1, data.columns()-1);\n\n    // ======================================================\n\n    // initialize data variables\n    // -------------------------\n    VariableList varList;\n    addDataVariables(data, varList);\n    for(UInt i=0; i<expressions.size(); i++)\n      expressions.at(i)->simplify(varList);\n\n    // criteria evaluation\n    // -------------------\n    std::vector<Time> times;\n    logStatus<<\"evaluate criteria\"<<Log::endl;\n    Single::forEach(data.rows(), [&](UInt idEpoch)\n    {\n      evaluateDataVariables(data, idEpoch, varList);\n      for(UInt i=0; i<expressions.size(); i++)\n        if(expressions.at(i)->evaluate(varList))\n        {\n          times.push_back(arc.at(idEpoch).time);\n          break;\n        }\n    });\n\n    // ======================================================\n\n    // remove epochs within buffer\n    // ---------------------------\n    Arc arcNew, arcEpochsForRemoval;\n    if(times.size())\n    {\n      logStatus<<\"remove epochs (+/- \"<<margin<<\" sec) from instrument data\"<<Log::endl;\n      UInt idxTime = 0;\n      Single::forEach(arc.size(), [&](UInt i)\n      {\n        while((idxTime < times.size()) && ((times.at(idxTime)-arc.at(i).time).seconds() < -margin))\n          idxTime++;\n        if((idxTime >= times.size()) || ((times.at(idxTime)-arc.at(i).time).seconds() > +margin))\n          arcNew.push_back(arc.at(i));\n        else\n          arcEpochsForRemoval.push_back(arc.at(i));\n      });\n    }\n    else\n    {\n      arcNew = arc;\n    }\n\n    logInfo<<\"  \"<<arcEpochsForRemoval.size()<<\" epochs meet criteria\"<<Log::endl;\n    logInfo<<\"  \"<<arc.size()-arcNew.size()<<\" epochs removed\"<<Log::endl;\n\n    // ======================================================\n\n    // save file\n    // ---------\n    if((!fileNameOut.empty()) && ((times.size()!=0) || (fileNameIn.str() != fileNameOut.str())))\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcNew);\n      Arc::printStatistics(arcNew);\n    }\n    if(!fileNameRemovedEpochs.empty())\n    {\n      logStatus<<\"write removed epochs to file <\"<<fileNameRemovedEpochs<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameRemovedEpochs, arcEpochsForRemoval);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentRemoveEpochsByTimes.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentRemoveEpochsByTimes.cpp\n*\n* @brief Remove epochs from instrument data.\n*\n* @author Beate Klinger\n* @date 2015-02-03\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program compares an \\file{instrument file}{instrument} with a\n\\configClass{time series}{timeSeriesType}.\nEpochs contained within the time series (including a defined margin)\nare removed from the instrument file. The margin is added on\nboth sides of the epochs. The arcs of the instrument file are\nconcatenated to one arc. The removed epochs can be saved\nin a separate instrument file.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Remove epochs from instrument data.\n* @ingroup programsGroup */\nclass InstrumentRemoveEpochsByTimes\n{\n  InstrumentFile timeFile;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentRemoveEpochsByTimes, SINGLEPROCESS, \"Remove epochs from instrument data\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentRemoveEpochsByTimes::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      outName, outNameRemoved, inName;\n    Double        margin;\n    TimeSeriesPtr timeSeries;\n\n    readConfig(config, \"outputfileInstrument\",               outName,        Config::OPTIONAL, \"\", \"all epochs are concatenated in one arc\");\n    readConfig(config, \"outputfileInstrumentRemovedEpochs\",  outNameRemoved, Config::OPTIONAL, \"\", \"all epochs are concatenated in one arc\");\n    readConfig(config, \"inputfileInstrument\",                inName,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timePoints\",                         timeSeries,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"margin\",                             margin,         Config::DEFAULT,  \"1e-5\", \"margin size (on both sides) [seconds]\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    // read time series\n    // ----------------\n    logStatus<<\"read time series\"<<Log::endl;\n    std::vector<Time> times = timeSeries->times();\n    logStatus<<\"  epochs:  \"<<times.size()<<Log::endl;\n\n    // quick test\n    // ----------\n    if((times.size()==0) && (inName.str() == outName.str()))\n    {\n      logStatus<<\"No epochs to remove.\"<<Log::endl;\n      return;\n    }\n\n    // read instrument data\n    // --------------------\n    logStatus<<\"read instrument data <\"<<inName<<\">\"<<Log::endl;\n    Arc arc = InstrumentFile::read(inName);\n\n    // ======================================================\n\n    // remove epochs within buffer\n    // ---------------------------\n    Arc arcNew, arcRemoved;\n    if(times.size())\n    {\n      logStatus<<\"remove epochs (+/- \"<<margin<<\" sec) from instrument data\"<<Log::endl;\n      UInt idxTime = 0;\n      Single::forEach(arc.size(), [&](UInt i)\n      {\n        while((idxTime < times.size()) && ((arc.at(i).time-times.at(idxTime)).seconds() > margin))\n          idxTime++;\n\n        if((idxTime < times.size()) && ((times.at(idxTime)-arc.at(i).time).seconds() <= margin))\n          arcRemoved.push_back(arc.at(i));\n        else\n          arcNew.push_back(arc.at(i));\n      });\n      logInfo<<\"  \"<<arcRemoved.size()<<\" epochs removed\"<<Log::endl;\n    }\n    else\n    {\n      logStatus<<\"No epochs to remove.\"<<Log::endl;\n      arcNew = arc;\n    }\n\n    // ======================================================\n\n    // save instrument data\n    // --------------------\n    if(!outName.empty())\n    {\n      logStatus<<\"write instrument data to file <\"<<outName<<\">\"<<Log::endl;\n      InstrumentFile::write(outName, arcNew);\n      Arc::printStatistics(arcNew);\n    }\n\n    if(!outNameRemoved.empty())\n    {\n      logStatus<<\"write removed epochs to file <\"<<outNameRemoved<<\">\"<<Log::endl;\n      InstrumentFile::write(outNameRemoved, arcRemoved);\n      Arc::printStatistics(arcRemoved);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentRemoveEpochsThruster.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentRemoveEpochsThruster.cpp\n*\n* @brief Remove epochs from instrument data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-07-30\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program remove epochs from an \\file{instrument file}{instrument}.\nThe epochs are defined by a \\file{thruster file}{instrument}\nplus a defined margin before and after the thruster firings.\nThe arcs of the instrument file are concatenated to one arc.\nThe removed epochs can be saved in a separate instrument file.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Remove epochs from instrument data.\n* @ingroup programsGroup */\nclass InstrumentRemoveEpochsThruster\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentRemoveEpochsThruster, SINGLEPROCESS, \"Remove epochs from instrument data\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentRemoveEpochsThruster::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameOutRemoved, fileNameIn, fileNameThruster;\n    Double   marginBefore, marginAfter;\n\n    readConfig(config, \"outputfileInstrument\",               fileNameOut,        Config::OPTIONAL, \"\",    \"all epochs are concatenated in one arc\");\n    readConfig(config, \"outputfileInstrumentRemovedEpochs\",  fileNameOutRemoved, Config::OPTIONAL, \"\",    \"all epochs are concatenated in one arc\");\n    readConfig(config, \"inputfileInstrument\",                fileNameIn,         Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileThruster\",                  fileNameThruster,   Config::MUSTSET,  \"\",    \"THRUSTER\");\n    readConfig(config, \"marginBefore\",                       marginBefore,       Config::DEFAULT,  \"0.1\", \"margin before start of firing [seconds]\");\n    readConfig(config, \"marginAfter\",                        marginAfter,        Config::DEFAULT,  \"0.7\", \"margin after end of firing [seconds]\");\n    if(isCreateSchema(config)) return;\n\n    // thruster time series\n    // --------------------\n    logStatus<<\"read thruster data <\"<<fileNameThruster<<\">\"<<Log::endl;\n    ThrusterArc thruster = InstrumentFile::read(fileNameThruster);\n    std::vector<Time> timesStart = thruster.times();\n    std::vector<Time> timesEnd   = timesStart;\n    for(UInt i=0; i<thruster.size(); i++)\n      timesStart.at(i) -= seconds2time(marginBefore);\n    for(UInt i=0; i<thruster.size(); i++)\n      timesEnd.at(i) += seconds2time(1e-3*max(thruster.at(i).data()) + marginAfter);\n\n    logStatus<<\"read instrument data <\"<<fileNameIn<<\">\"<<Log::endl;\n    Arc arc = InstrumentFile::read(fileNameIn);\n\n    logStatus<<\"remove thruster epochs from instrument data\"<<Log::endl;\n    Arc arcNew, arcRemoved;\n    UInt idxThruster = 0;\n    Single::forEach(arc.size(), [&](UInt i)\n    {\n      while((idxThruster < timesEnd.size()) && ((arc.at(i).time-timesEnd.at(idxThruster)).seconds() >= 0)) // find next thruster epoch\n        idxThruster++;\n      if((idxThruster >= timesEnd.size()) || ((arc.at(i).time-timesStart.at(idxThruster)).seconds() < 0))\n        arcNew.push_back(arc.at(i));\n      else\n        arcRemoved.push_back(arc.at(i));\n    });\n\n    // save instrument data\n    // --------------------\n    if(!fileNameOut.empty())\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcNew);\n      Arc::printStatistics(arcNew);\n    }\n\n    if(!fileNameOutRemoved.empty())\n    {\n      logStatus<<\"write removed epochs to file <\"<<fileNameOutRemoved<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutRemoved, arcRemoved);\n      Arc::printStatistics(arcRemoved);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentResample.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentResample.cpp\n*\n* @brief Resample data to given time series.\n*\n* @author Andreas Kvas\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2019-10-07\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program resamples \\file{instrument data}{instrument} to a given\n\\configClass{timeSeries}{timeSeriesType} using a resampling\n\\configClass{method}{interpolatorTimeSeriesType}.\n\nThis program can also be used to reduce the sampling of an instrument file,\nbut a better way to reduce the sampling of noisy data with regular sampling\nis to use a low pass filter first with \\program{InstrumentFilter} and then thin\nout the data with \\program{InstrumentReduceSampling}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/interpolatorTimeSeries/interpolatorTimeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Resample data to given time series.\n* @ingroup programsGroup */\nclass InstrumentResample\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentResample, SINGLEPROCESS, \"Resample data to given time series\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentResample::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                  outName, inName;\n    InterpolatorTimeSeriesPtr interpolator;\n    TimeSeriesPtr             timeSeries;\n\n    readConfig(config, \"outputfileInstrument\", outName,      Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",  inName,       Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"method\",               interpolator, Config::MUSTSET, \"\", \"resampling method\");\n    readConfig(config, \"timeSeries\",           timeSeries,   Config::MUSTSET, \"\", \"resampled points in time\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data <\"<<inName<<\">\"<<Log::endl;\n    const Arc arc = InstrumentFile::read(inName);\n    const std::vector<Time> timesNew = timeSeries->times();\n\n    logStatus<<\"resample data\"<<Log::endl;\n    interpolator->init(arc.times(), FALSE/*throwException*/);\n    const Matrix A = interpolator->interpolate(timesNew, arc.matrix().column(1, Epoch::dataCount(arc.getType(), TRUE)));\n\n    Arc arcNew;\n    Epoch *epoch = Epoch::create(arc.getType());\n    for(UInt i=0; i<timesNew.size(); i++)\n      if(!std::isnan(A(i,0)))\n      {\n        epoch->time  = timesNew.at(i);\n        epoch->setData(A.row(i).trans());\n        arcNew.push_back(*epoch);\n    }\n    delete epoch;\n\n    logStatus<<\"write instrument data to file <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, arcNew);\n    Arc::printStatistics(arcNew);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentRotate.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentRotate.cpp\n*\n* @brief Rotate instrument data into a new reference frame.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-06-15\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program rotates \\file{instrument data}{instrument} into a new reference frame\n(using \\configFile{inputfileStarCamera}{instrument}).\nThe rotation is usually done from satellite frame into inertial frame.\n\nTo apply Earth rotation to orbits use \\program{Orbit2EarthFixedOrbit}\nFor other instrument data use \\program{InstrumentEarthRotation} before.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Rotate instrument data into a new reference frame.\n* @ingroup programsGroup */\nclass InstrumentRotate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentRotate, PARALLEL, \"Rotate instrument data into a new reference frame\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentRotate::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn, fileNameStarCamera;\n    Bool     inverseRotate;\n\n    readConfig(config, \"outputfileInstrument\",fileNameOut,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileInstrument\", fileNameIn,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileStarCamera\", fileNameStarCamera, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inverseRotate\",       inverseRotate,      Config::DEFAULT,  \"1\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // read orbit and rotate\n    // ---------------------\n    logStatus<<\"read and rotate data <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameIn);\n    InstrumentFile starCameraFile(fileNameStarCamera);\n    InstrumentFile::checkArcCount({instrumentFile, starCameraFile});\n\n    std::vector<Arc> arcList(instrumentFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc           arc        = instrumentFile.readArc(arcNo);\n      StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n      Arc::checkSynchronized({arc, starCamera});\n\n      for(UInt i=0; i<arc.size(); i++)\n      {\n        Rotary3d rot = starCamera.at(i).rotary;\n        if(inverseRotate)\n          rot = inverse(rot);\n\n        if(arc.getType() == Epoch::ORBIT)\n        {\n          auto &epoch = dynamic_cast<OrbitEpoch&>(arc.at(i));\n          epoch.position     = rot.rotate(epoch.position);\n          epoch.velocity     = rot.rotate(epoch.velocity);\n          epoch.acceleration = rot.rotate(epoch.acceleration);\n        }\n        else if(arc.getType() == Epoch::ACCELEROMETER)\n        {\n          auto &epoch = dynamic_cast<AccelerometerEpoch&>(arc.at(i));\n          epoch.acceleration = rot.rotate(epoch.acceleration);\n        }\n        else if(arc.getType() == Epoch::GRADIOMETER)\n        {\n          auto &epoch = dynamic_cast<GradiometerEpoch&>(arc.at(i));\n          epoch.gravityGradient = rot.rotate(epoch.gravityGradient);\n        }\n        else if(arc.getType() == Epoch::COVARIANCE3D)\n        {\n          auto &epoch = dynamic_cast<Covariance3dEpoch&>(arc.at(i));\n          epoch.covariance = rot.rotate(epoch.covariance);\n        }\n        else if(arc.getType() == Epoch::VECTOR3D)\n        {\n          auto &epoch = dynamic_cast<Vector3dEpoch&>(arc.at(i));\n          epoch.vector3d = rot.rotate(epoch.vector3d);\n        }\n        else\n          throw(Exception(\"rotation for \"+arc.getTypeName()+\" not implemented\"));\n      }\n      return arc;\n    }, comm); // forEach\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentSetType.cpp",
    "content": "/**\n* @file instrumentSetType.cpp\n*\n* @brief Reinterpret data columns of instrument file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2016-11-25\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConvert \\file{instrument data}{instrument} into instrument data with new \\configClass{type}{instrumentTypeType}.\nThe selected number of data columns must agree with the \\configClass{type}{instrumentTypeType}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Reinterpret data columns of instrument file.\n* @ingroup programsGroup */\nclass InstrumentSetType\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentSetType, SINGLEPROCESS, \"Reinterpret data columns of instrument file\", Instrument, Matrix)\nGROOPS_RENAMED_PROGRAM(InstrumentMatrix2Instrument, InstrumentSetType, date2time(2020, 02, 15))\n\n/***********************************************/\n\nvoid InstrumentSetType::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut, fileNameIn;\n    Epoch::Type type = Epoch::MISCVALUESOLD;\n    UInt        startData, countData = MAX_UINT;\n\n    renameDeprecatedConfig(config, \"inputfileTimeSeries\", \"inputfileInstrument\", date2time(2020, 02, 15));\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"type\",                 type,        Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"startDataFields\",      startData,   Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\",      countData,   Config::OPTIONAL, \"\",  \"number of data fields (default: all after start)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument data <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile file(fileNameIn);\n    countData = std::min(countData, file.dataCount(TRUE/*mustDefined*/)-startData);\n    if(type == Epoch::EMPTY)         type = static_cast<Epoch::Type>(countData);\n    if(type == Epoch::MISCVALUESOLD) type = Epoch::EMPTY;\n    if((Epoch::dataCount(type) != NULLINDEX) && (countData != Epoch::dataCount(type)))\n      throw(Exception(\"Selected type expects \"+Epoch::dataCount(type)%\"%i data columns, but \"s+countData%\"%i provided\"s));\n\n    std::vector<Arc> arcs;\n    for(UInt arcNo=0; arcNo<file.arcCount(); arcNo++)\n    {\n      Arc arc = file.readArc(arcNo);\n      arcs.push_back(Arc(arc.times(), arc.matrix().column(startData, 1+countData), type));\n    }\n\n    logStatus<<\"write instrument data <\"<<fileNameOut<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOut, arcs);\n    Arc::printStatistics(arcs);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentStarCamera2AccAngularRate.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentStarCamera2AccAngularRate.cpp\n*\n* @brief Derivation of angular rates from rotations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-04-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program derivate from a time series of quaternions\na series of angular rates and angular accelerations.\nThe derivatives are computed by a polynomial interpolation\nwith \\config{interpolationDegree} of the quaternions.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Derivation of angular rates from rotations.\n* @ingroup programsGroup */\nclass InstrumentStarCamera2AccAngularRate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentStarCamera2AccAngularRate, SINGLEPROCESS, \"derivation of angular rates from rotations\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentStarCamera2AccAngularRate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName angRateName, angAccName;\n    FileName starCameraName;\n    UInt     derivationDegree;\n\n    readConfig(config, \"outputfileAngularRate\", angRateName,      Config::OPTIONAL, \"\", \"[rad/s], VECTOR3D\");\n    readConfig(config, \"outputfileAngularAcc\",  angAccName,       Config::OPTIONAL, \"\", \"[rad/s**2], VECTOR3D\");\n    readConfig(config, \"inputfileStarCamera\",   starCameraName,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"interpolationDegree\",   derivationDegree, Config::DEFAULT,  \"2\", \"derivation by polynomial interpolation of degree n\");\n    if(isCreateSchema(config)) return;\n\n    // init interpolation coefficients\n    // -------------------------------\n\n    // calculate angular rates & accelerations\n    // ---------------------------------------\n    logStatus<<\"calculate angular rates & accelerations\"<<Log::endl;\n    InstrumentFile starCameraFile(starCameraName);\n    std::list<Arc> angRateArcList, angAccArcList;\n    Single::forEach(starCameraFile.arcCount(), [&](UInt arcNo)\n    {\n      const StarCameraArc scaArc = starCameraFile.readArc(arcNo);\n      const std::vector<Time> times = scaArc.times();\n      const Matrix q = scaArc.matrix().column(1,4);\n      Polynomial polynomial(times, derivationDegree);\n\n      // angular rate\n      // ------------\n      Matrix dq = polynomial.derivative(times, q);\n      Vector3dArc angRateArc;\n      for(UInt i=0; i<scaArc.size(); i++)\n      {\n        Vector3dEpoch angRate;\n        angRate.time = scaArc.at(i).time;\n        angRate.vector3d.x() = 2*(-q(i,1)*dq(i,0) + q(i,0)*dq(i,1) + q(i,3)*dq(i,2) - q(i,2)*dq(i,3));\n        angRate.vector3d.y() = 2*(-q(i,2)*dq(i,0) - q(i,3)*dq(i,1) + q(i,0)*dq(i,2) + q(i,1)*dq(i,3));\n        angRate.vector3d.z() = 2*(-q(i,3)*dq(i,0) + q(i,2)*dq(i,1) - q(i,1)*dq(i,2) + q(i,0)*dq(i,3));\n        angRateArc.push_back(angRate);\n      }\n      angRateArcList.push_back(angRateArc);\n\n      // angular accelerations\n      // ---------------------\n      if(!angAccName.empty())\n      {\n        Matrix ddq = polynomial.derivative2nd(times, q);\n        Vector3dArc angAccArc;\n        for(UInt i=0; i<scaArc.size(); i++)\n        {\n          Vector3dEpoch angAcc;\n          angAcc.time = scaArc.at(i).time;\n          angAcc.vector3d.x() = 2*(-q(i,1)*ddq(i,0) + q(i,0)*ddq(i,1) + q(i,3)*ddq(i,2) - q(i,2)*ddq(i,3));\n          angAcc.vector3d.y() = 2*(-q(i,2)*ddq(i,0) - q(i,3)*ddq(i,1) + q(i,0)*ddq(i,2) + q(i,1)*ddq(i,3));\n          angAcc.vector3d.z() = 2*(-q(i,3)*ddq(i,0) + q(i,2)*ddq(i,1) - q(i,1)*ddq(i,2) + q(i,0)*ddq(i,3));\n          angAccArc.push_back(angAcc);\n        }\n        angAccArcList.push_back(angAccArc);\n      }\n    });\n\n    // write data\n    // ----------\n    if(!angRateName.empty())\n    {\n      logStatus<<\"write angular rate data to file <\"<<angRateName<<\">\"<<Log::endl;\n      InstrumentFile::write(angRateName, angRateArcList);\n    }\n    if(!angAccName.empty())\n    {\n      logStatus<<\"write angular accelerations data to file <\"<<angAccName<<\">\"<<Log::endl;\n      InstrumentFile::write(angAccName, angAccArcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentStarCamera2RollPitchYaw.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentStarCamera2RollPitchYaw.cpp\n*\n* @brief Compute roll, pitch, yaw angles.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-06-14\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute roll, pitch, yaw angles from \\configFile{inputfileStarCamera}{instrument} data.\nOptional the angles are computed relative\nto a \\configFile{inputfileStarCameraReference}{instrument}.\n\nSee also \\program{SimulateStarCamera}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute roll, pitch, yaw angles.\n* @ingroup programsGroup */\nclass InstrumentStarCamera2RollPitchYaw\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentStarCamera2RollPitchYaw, PARALLEL, \"Compute roll, pitch, yaw angles\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentStarCamera2RollPitchYaw::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut;\n    FileName fileNameStarCamera, fileNameReference;\n\n    readConfig(config, \"outputfileInstrument\",         fileNameOut,        Config::MUSTSET,  \"\", \"roll, pitch, yaw [rad], VECTOR3D\");\n    readConfig(config, \"inputfileStarCamera\",          fileNameStarCamera, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCameraReference\", fileNameReference,  Config::OPTIONAL, \"\", \"nominal orientation\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read star camera data and compute roll, pitch, yaw\"<<Log::endl;\n    InstrumentFile  starCamera1File(fileNameStarCamera);\n    InstrumentFile  starCamera2File(fileNameReference);\n    InstrumentFile::checkArcCount({starCamera1File, starCamera2File});\n\n    std::vector<Arc> arcList(starCamera1File.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      StarCameraArc starCamera1 = starCamera1File.readArc(arcNo);\n      StarCameraArc starCamera2 = starCamera2File.readArc(arcNo);\n      Arc::checkSynchronized({starCamera1, starCamera2});\n\n      Vector3dArc arc;\n      for(UInt i=0; i<starCamera1.size(); i++)\n      {\n        if(starCamera2.size())\n          starCamera1.at(i).rotary = inverse(starCamera2.at(i).rotary) * starCamera1.at(i).rotary;\n\n        Angle roll, pitch, yaw;\n        inverse(starCamera1.at(i).rotary).cardan(roll, pitch, yaw);\n\n        Vector3dEpoch epoch;\n        epoch.time     = starCamera1.at(i).time;\n        epoch.vector3d = Vector3d(roll, pitch, yaw);\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm); // forEach\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write angles to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentStarCamera2RotaryMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentStarCamera2RotaryMatrix.cpp\n*\n* @brief Compute rotary matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-02-02\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nWrite \\configFile{inputfileStarCamera}{instrument} rotations\nas \\configFile{outputfileInstrument}{instrument} rotary matrices\n(for each epoch $xx, xy, xz, yx, yy, yz, zx, zy, zz$).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute rotary matrix.\n* @ingroup programsGroup */\nclass InstrumentStarCamera2RotaryMatrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentStarCamera2RotaryMatrix, PARALLEL, \"Compute rotary matrix\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentStarCamera2RotaryMatrix::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut, fileNameStarCamera;\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut,        Config::MUSTSET, \"\", \"xx, xy, xz, yx, yy, yz, zx, zy, zz (MISCVALUES)\");\n    readConfig(config, \"inputfileStarCamera\",  fileNameStarCamera, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read star camera data <\"<<fileNameStarCamera<<\">\"<<Log::endl;\n    InstrumentFile file(fileNameStarCamera);\n\n    std::vector<Arc> arcList(file.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      StarCameraArc starCamera = file.readArc(arcNo);\n      MiscValuesArc arc;\n      for(UInt i=0; i<starCamera.size(); i++)\n      {\n        MiscValuesEpoch epoch(6);\n        epoch.time   = starCamera.at(i).time;\n        epoch.values = flatten(starCamera.at(i).rotary.matrix().trans());\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm); // forEach\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write rotary matrix to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentStarCameraMultiply.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentStarCameraMultiply.cpp\n*\n* @brief Mutiply instrument data with a factor and add them together.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-06-24\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program applies several rotations given by \\configFile{inputfileStarCamera}{instrument}.\nThe resulting rotation is written as \\configFile{outputfileStarCamera}{instrument}.\nAll instrument files must be synchronized (\\program{InstrumentSynchronize}).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Mutiply instrument data with a factor and add them together.\n* @ingroup programsGroup */\nclass InstrumentStarCameraMultiply\n{\npublic:\n  class Data\n  {\n    public:\n    FileName fileName;\n    Bool     inverse;\n  };\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentStarCameraMultiply, SINGLEPROCESS, \"Mutiply instrument data with a factor and add them together\", Instrument)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, InstrumentStarCameraMultiply::Data &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"inputfileStarCamera\", var.fileName, Config::MUSTSET,  \"\", \"\");\n  readConfig(config, \"inverse\",             var.inverse,  Config::DEFAULT,  \"0\", \"\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nvoid InstrumentStarCameraMultiply::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    std::vector<Data> data;\n\n    readConfig(config, \"outputfileStarCamera\", outName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"instrument\",           data,    Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<InstrumentFilePtr> instrumentFile;\n    instrumentFile.resize(data.size());\n    for(UInt i=0; i<instrumentFile.size(); i++)\n      instrumentFile.at(i) = InstrumentFile::newFile(data.at(i).fileName);\n    for(UInt i=1; i<instrumentFile.size(); i++)\n      InstrumentFile::checkArcCount({*instrumentFile.at(0), *instrumentFile.at(i)});\n\n    // read data\n    // ---------\n    logStatus<<\"read starCamera data\"<<Log::endl;\n    UInt arcCount = instrumentFile.at(0)->arcCount();\n    std::vector<Arc> arcList;\n\n    Single::forEach(arcCount, [&](UInt arcNo)\n    {\n      StarCameraArc starCamera = instrumentFile.at(0)->readArc(arcNo);\n      UInt epochCount = starCamera.size();\n      if(data.at(0).inverse)\n        for(UInt k=0; k<epochCount; k++)\n          starCamera.at(k).rotary = inverse(starCamera.at(k).rotary);\n\n      for(UInt i=1; i<instrumentFile.size(); i++)\n      {\n        StarCameraArc starCamera2 = instrumentFile.at(i)->readArc(arcNo);\n        Arc::checkSynchronized({starCamera, starCamera2});\n        for(UInt k=0; k<epochCount; k++)\n        {\n          if(data.at(i).inverse)\n            starCamera.at(k).rotary = starCamera.at(k).rotary * inverse(starCamera2.at(k).rotary);\n          else\n            starCamera.at(k).rotary = starCamera.at(k).rotary * starCamera2.at(k).rotary;\n        }\n      }\n      arcList.push_back(starCamera);\n    });\n\n    // save file\n    // ---------\n    logStatus<<\"write instrument data to file <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, arcList);\n\n    Arc::printStatistics(arcList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentStatisticsTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentStatisticsTimeSeries.cpp\n*\n* @brief Compute time series of statistics for intervals of instrument data.\n*\n* @author Sebastian Strasser\n* @author Matthias Ellmer\n* @date 2016-07-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring =\nR\"(\nThis program computes a time series of statistics for one or more instrument files.\nPossible statistics are root mean square, standard deviation, mean, median, min, and max.\nThe columns of the output time series are defined either as one per \\configFile{inputfileInstrument}{instrument}\nor, if \\config{perColumn} is true, statistics are computed per column for each file.\nProviding e.g. 32 orbit files of GPS satellites results in a time series matrix\nwith columns: mjd, statisticsG01, statisticsG02, ..., statisticsG32.\nIf \\config{intervals} are provided, the input data is split into these intervals\nand one statistic is computed per interval. Otherwise, overall statistics are computed.\nThe instrument data considered for computation of the component-wise statistics\ncan be set with \\config{startDataFields} and \\config{countDataFields}.\nThe \\config{factor} can be set to e.g. sqrt(3) to get 3D instead of 1D RMS values.\n\nSee also \\program{InstrumentArcStatistics}, \\program{InstrumentArcCrossStatistics}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute time series of statistics for intervals of instrument data.\n* @ingroup programsGroup */\nclass InstrumentStatisticsTimeSeries\n{\n  static Double nanFunc(std::function<double(const_MatrixSliceRef A)> func, const_MatrixSliceRef A);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentStatisticsTimeSeries, SINGLEPROCESS, \"Compute time series of statistics for intervals of instrument data.\", Instrument, TimeSeries, Statistics)\n\n/***********************************************/\n\nDouble InstrumentStatisticsTimeSeries::nanFunc(std::function<double(const_MatrixSliceRef A)> func, const_MatrixSliceRef A)\n{\n  try\n  {\n    std::vector<Double> data = flatten(A);\n    data.erase(std::remove_if(data.begin(), data.end(), [](Double d){ return std::isnan(d); }), data.end());\n    return func(Vector(data));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid InstrumentStatisticsTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOutStatisticsTimeSeries;\n    std::vector<FileName> fileNameInInstrument;\n    TimeSeriesPtr         intervalsPtr;\n    UInt                  startData = 0, countData = MAX_UINT;\n    Bool                  perColumn, ignoreNan;\n    Double                factor;\n    std::string           choice;\n    std::function<double(const_MatrixSliceRef A)> func;\n\n    readConfig(config, \"outputfileStatisticsTimeSeries\", fileNameOutStatisticsTimeSeries, Config::MUSTSET, \"\", \"columns: mjd, statistics column(s) per instrument file\");\n    readConfig(config, \"inputfileInstrument\",            fileNameInInstrument,            Config::MUSTSET, \"\", \"\");\n    if(readConfigChoice(config, \"statistics\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"rootMeanSquare\",    choice)) func = rootMeanSquare;\n      if(readConfigChoiceElement(config, \"standardDeviation\", choice)) func = standardDeviation;\n      if(readConfigChoiceElement(config, \"mean\",              choice)) func = mean;\n      if(readConfigChoiceElement(config, \"median\",            choice)) func = median;\n      if(readConfigChoiceElement(config, \"sum\",               choice)) func = sum;\n      if(readConfigChoiceElement(config, \"min\",               choice)) func = static_cast<Double(*)(const_MatrixSliceRef)>(&min); // min and max are overloads, and the standard forbids automatic overload resolution in this context. So a manual cast is made in which the overload can be resolved successfully\n      if(readConfigChoiceElement(config, \"max\",               choice)) func = static_cast<Double(*)(const_MatrixSliceRef)>(&max);\n      if(readConfigChoiceElement(config, \"epochCount\",        choice)) func = [] (const_MatrixSliceRef A) { return static_cast<Double>(A.rows());};\n      endChoice(config);\n    }\n    readConfig(config, \"startDataFields\", startData,    Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\", countData,    Config::OPTIONAL, \"\",  \"number of data fields (default: all)\");\n    readConfig(config, \"perColumn\",       perColumn,    Config::DEFAULT,  \"0\", \"compute statistic per column\");\n    readConfig(config, \"ignoreNan\",       ignoreNan,    Config::DEFAULT,  \"0\", \"ignore NaN values in statistic computation\");\n    readConfig(config, \"intervals\",       intervalsPtr, Config::DEFAULT,  \"\",  \"intervals for statistics computation (one statistic per interval)\");\n    readConfig(config, \"factor\",          factor,       Config::DEFAULT,  \"1\", \"e.g. sqrt(3) for 3D RMS\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Vector> columns;\n\n    // init time intervals\n    std::vector<Time> intervals = intervalsPtr->times();\n    if(intervals.size() >= 2)\n    {\n      columns.push_back(Vector(intervals.size()-1));\n      for(UInt idInterval = 0; idInterval < intervals.size()-1; idInterval++)\n        columns.back()(idInterval) = (0.5*(intervals.at(idInterval)+intervals.at(idInterval+1))).mjd();\n    }\n    else\n      columns.push_back(Vector(1));\n\n    // read instrument files and compute statistics\n    for(UInt idInstrument = 0; idInstrument < fileNameInInstrument.size(); idInstrument++)\n    {\n      Arc arc;\n      try\n      {\n        logStatus<<\"read instrument file <\"<<fileNameInInstrument.at(idInstrument)<<\">\"<<Log::endl;\n        arc = InstrumentFile::read(fileNameInInstrument.at(idInstrument));\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        continue;\n      }\n\n      if(arc.size() == 0)\n        continue;\n\n      // determine data spans\n      Matrix A = arc.matrix();\n      std::vector<UInt> intervalEpochIds;\n      if(intervals.size() >= 2)\n      {\n        std::vector<Double> times = Vector(A.column(0));\n        for(UInt i = 0; i < intervals.size(); i++)\n        {\n          const auto it = std::find_if(times.begin(), times.end(), [intervals, i] (Double t) { return t >= intervals.at(i).mjd(); });\n          intervalEpochIds.push_back(std::distance(times.begin(), it));\n        }\n      }\n      else\n        intervalEpochIds = {0, arc.size()};\n\n      // compute statistics\n      const UInt dataColumnCount = std::min(A.columns()-1-startData, countData);\n      const UInt rowCount        = intervalEpochIds.size()-1;\n      const UInt columnCount     = perColumn ? dataColumnCount : 1;\n      for(UInt idCol = 0; idCol < columnCount; idCol++)\n      {\n        Vector column(rowCount);\n        for(UInt idRow = 0; idRow < rowCount; idRow++)\n        {\n          const UInt rows = intervalEpochIds.at(idRow+1)-intervalEpochIds.at(idRow);\n          if(rows)\n          {\n            Matrix slice = A.slice(intervalEpochIds.at(idRow), 1+startData+idCol, rows, perColumn ? 1 : dataColumnCount);\n            column(idRow) = factor * (ignoreNan ? nanFunc(func, slice) : func(slice));\n          }\n          else\n            column(idRow) = NAN_EXPR;\n        }\n        columns.push_back(column);\n      }\n    }\n\n    // save file\n    logStatus<<\"write statistics time series to file <\"<<fileNameOutStatisticsTimeSeries<<\">\"<<Log::endl;\n    Matrix A(columns.at(0).size(), columns.size());\n    for(UInt i = 0; i < columns.size(); i++)\n      copy(columns.at(i), A.column(i));\n    writeFileMatrix(fileNameOutStatisticsTimeSeries, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentSynchronize.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentSynchronize.cpp\n*\n* @brief Synchronize instrument data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2001-06-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads several \\file{instrument files}{instrument} and synchronize the data.\nEvery epoch with some missing data will be deleted so the remaining epochs\nhave data from every instrument.\n\nIn a second step the epochs are divided into arcs with maximal epochs\n(or \\config{maxArcLen}) without having a gap inside an arc.\nA Gap is defined by a time step with at least \\config{minGap} seconds\nbetween consecutive epochs or if not set the 1.5 of the median sampling.\nArc with an epoch count less than \\config{minArcLen} will be rejected.\n\nA specific region can be selected with \\configClass{border}{borderType}.\nIn this case one of the instrument data must be an orbit.\n\nIf \\configClass{timeIntervals}{timeSeriesType} is given the data are also divided into time bins.\nThe assignment of arcs to the bins can be saved in \\configFile{outputfileArcList}{arcList}.\nThis file can be used for the variational equation approach or \\program{KalmanBuildNormals}.\n\nInstrument files from \\config{irregularData} are not synchronized but\ndivided into the same number of arcs within the same time intervals.\nData outside the defined arcs will be deleted.\n)\";\n\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/planets.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/border/border.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Synchronize instrument data.\n* @ingroup programsGroup */\nclass InstrumentSynchronize\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  class Data\n  {\n    public:\n    FileName inName, outName;\n  };\n\n  class DataIrregular\n  {\n    public:\n    FileName inName, outName;\n    UInt     minArcLen;\n  };\n\nprivate:\n  enum ArcType {ALL, ASCENDING, DESCENDING};\n\n  OrbitArc          orbitArc;\n  std::vector<Time> times;\n  std::vector<Time> timesInterval;\n  ArcType           arcType;\n  BorderPtr         border;\n  UInt              searchInterval(UInt i);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentSynchronize, SINGLEPROCESS, \"Synchronize instrument data\", Instrument)\nGROOPS_RENAMED_PROGRAM(ArcSynchronize, InstrumentSynchronize, date2time(2020, 05, 25))\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, InstrumentSynchronize::Data &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"outputfileInstrument\", var.outName, Config::OPTIONAL, \"\", \"\");\n  readConfig(config, \"inputfileInstrument\",  var.inName,  Config::MUSTSET,  \"\", \"\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, InstrumentSynchronize::DataIrregular &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n    return FALSE;\n  readConfig(config, \"outputfileInstrument\", var.outName,   Config::OPTIONAL, \"\",  \"\");\n  readConfig(config, \"inputfileInstrument\",  var.inName,    Config::MUSTSET,  \"\",  \"\");\n  readConfig(config, \"minArcLength\",         var.minArcLen, Config::DEFAULT,  \"0\", \"minimal number of epochs in an arc\");\n  endSequence(config);\n  return TRUE;\n}\n\n/***********************************************/\n\nUInt InstrumentSynchronize::searchInterval(UInt i)\n{\n  // in time interval?\n  UInt idx = 0;\n  if(timesInterval.size())\n  {\n    if(times.at(i)<timesInterval.at(idx))\n      return MAX_UINT;\n    while((idx+1 < timesInterval.size()) && (times.at(i) >= timesInterval.at(idx+1)))\n      idx++;\n    if(idx+1 >= timesInterval.size())\n      return MAX_UINT;\n  }\n\n  // ascending / descending\n  if((arcType!=ALL)&&(i>0))\n  {\n    if((arcType == ASCENDING) && (orbitArc.at(i).position.z() < orbitArc.at(i-1).position.z()))\n      return MAX_UINT;\n    if((arcType == DESCENDING) && (orbitArc.at(i).position.z() > orbitArc.at(i-1).position.z()))\n      return MAX_UINT;\n  }\n\n  // in area?\n  if(!border || (border->isInnerPoint(Planets::celestial2TerrestrialFrame(times.at(i)).rotate(orbitArc.at(i).position))))\n    return idx;\n  return MAX_UINT;\n}\n\n/***********************************************/\n\nvoid InstrumentSynchronize::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<Data>          data;\n    std::vector<DataIrregular> data2;\n    Double            minGap = NAN_EXPR, margin;\n    UInt              minArcLen = 1, maxArcLen = MAX_UINT;\n    TimeSeriesPtr     timeSeries;\n    FileName          outArcList;\n    arcType  = ALL;\n\n    readConfig(config, \"data\",              data,       Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"margin\",            margin,     Config::DEFAULT,  \"1e-5\", \"margin for identical times [seconds]\");\n    readConfig(config, \"minGap\",            minGap,     Config::OPTIONAL, \"\",     \"minimal time to define a gap and to begin a new arc, 0: no dividing [seconds], if not set 1.5*median sampling is used\");\n    readConfig(config, \"minArcLength\",      minArcLen,  Config::DEFAULT,  \"1\",    \"minimal number of epochs of an arc\");\n    readConfig(config, \"maxArcLength\",      maxArcLen,  Config::OPTIONAL, \"\",     \"maximal number of epochs of an arc\");\n    std::string choice;\n    if(readConfigChoice(config, \"arcType\", choice, Config::OPTIONAL, \"\", \"all arcs or only ascending or descending arcs are selected\"))\n    {\n      if(readConfigChoiceElement(config, \"ascending\",  choice, \"\")) arcType = ASCENDING;\n      if(readConfigChoiceElement(config, \"descending\", choice, \"\")) arcType = DESCENDING;\n      endChoice(config);\n    }\n    readConfig(config, \"border\",            border,     Config::OPTIONAL, \"\", \"only data in a specific region is selected\");\n    readConfig(config, \"timeIntervals\",     timeSeries, Config::DEFAULT,  \"\", \"divide data into time bins\");\n    readConfig(config, \"outputfileArcList\", outArcList, Config::OPTIONAL, \"\", \"arc and time bin mapping\");\n    readConfig(config, \"irregularData\",     data2,      Config::OPTIONAL, \"\", \"instrument files with irregular sampling\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    // read data\n    // ---------\n    std::vector<Arc> arc(data.size());\n    for(UInt k=0; k<data.size(); k++)\n    {\n      logStatus<<\"read instrument file <\"<<data.at(k).inName<<\">\"<<Log::endl;\n      arc.at(k) = InstrumentFile::read(data.at(k).inName);\n      logInfo<<\"  epochs = \"<<arc.at(k).size()<<Log::endl;\n    }\n\n    std::vector<Arc> arcIrregular(data2.size());\n    for(UInt k=0; k<data2.size(); k++)\n    {\n      logStatus<<\"read irregular instrument file <\"<< data2.at(k).inName<<Log::endl;\n      arcIrregular.at(k) = InstrumentFile::read(data2.at(k).inName);\n      logInfo<<\"  epochs = \"<<arcIrregular.at(k).size()<<Log::endl;\n    }\n\n    // find orbit data\n    // ---------------\n    UInt indexOrbit = NULLINDEX;\n    if(border || (arcType != ALL))\n    {\n      for(UInt k=0; k<arc.size(); k++)\n        if(arc.at(k).getType() == Epoch::ORBIT)\n        {\n          indexOrbit = k;\n          break;\n        }\n      if(indexOrbit == NULLINDEX)\n        throw(Exception(\"One instrument file must be an orbit.\"));\n    }\n\n    // synchronize data\n    // ----------------\n    logStatus<<\"synchronize data\"<<Log::endl;\n    times.resize(arc.at(0).size());\n    std::vector<UInt> index(arc.size(),0);\n    for(UInt i=0; i<arc.at(0).size(); i++)\n    {\n      Time time = arc.at(0).at(i).time;\n\n      // this point of time in all files?\n      Bool synchron = TRUE;\n      Bool eof      = FALSE;\n      for(UInt k=1; k<arc.size(); k++)\n      {\n        while(((arc.at(k).at(index.at(k)).time-time).seconds() < -margin) && (++index.at(k)<arc.at(k).size()));\n\n        if(index.at(k)>=arc.at(k).size())\n        {\n          eof = TRUE;\n          break;\n        }\n        if(std::fabs((arc.at(k).at(index.at(k)).time-time).seconds()) > margin)\n        {\n          synchron = FALSE;\n          break;\n        }\n      }\n      if(eof)       break;\n      if(!synchron) continue;\n      times.at(index.at(0)++) = time;\n    }\n    times.resize(index.at(0));\n\n    if(times.size()==0)\n    {\n      logWarning<<\"found no data with identical time\"<<Log::endl;\n      return;\n    }\n\n    // delete other data\n    // -----------------\n    logStatus<<\"delete asynchronize data\"<<Log::endl;\n    for(UInt k=0; k<arc.size(); k++)\n      arc.at(k).synchronize(times, margin);\n\n    if(indexOrbit != NULLINDEX)\n      orbitArc = arc.at(indexOrbit);\n\n    // divide arcs\n    // -----------\n    logStatus<<\"divide arcs\"<<Log::endl;\n    // determine min gap size\n    Time timeGap;\n    if(!std::isnan(minGap))\n      timeGap = (minGap>0) ? seconds2time(minGap) : seconds2time(100*365*86400.);\n    else\n    {\n      // median sampling\n      std::vector<Time> timeDiff(times.size()-1);\n      for(UInt i=0; i<times.size()-1; i++)\n        timeDiff.at(i) = times.at(i+1)-times.at(i);\n      std::sort(timeDiff.begin(),timeDiff.end());\n      timeGap = 1.5*timeDiff.at(timeDiff.size()/2);\n      logInfo<<\"  begin new arc by a time step of at least \"<<timeGap.seconds()<<\" seconds\"<<Log::endl;\n    }\n    minArcLen = std::max(minArcLen, static_cast<UInt>(1));\n    timesInterval = timeSeries->times();\n    std::vector<UInt> arcsInterval(timesInterval.size(), 0);\n\n    std::vector<UInt> subArcStart, subArcLen;\n    std::vector< std::vector<UInt> > irregularSubArcStart(data2.size()), irregularSubArcLen(data2.size());\n\n    UInt idx = 0;\n    while((times.size()-idx) >= minArcLen)\n    {\n      // search state change\n      UInt idxStart    = idx;\n      UInt idxInterval = searchInterval(idx++);\n      while((idx<times.size()) && (times.at(idx)-times.at(idx-1) < timeGap) && ((idx-idxStart)<maxArcLen) && (idxInterval == searchInterval(idx)))\n        idx++;\n\n      // reject arc?\n      if((idxInterval == MAX_UINT) || ((idx-idxStart) < minArcLen))\n        continue;\n\n      // sort irregular data into arcs\n      Bool shortArc = FALSE;\n      for(UInt k=0; k<data2.size(); k++)\n      {\n        UInt idx2 = 0;\n        while((idx2<arcIrregular.at(k).size()) && ((arcIrregular.at(k).at(idx2).time-times.at(idxStart)).seconds() < -margin))\n          idx2++;\n        UInt idx2Start = idx2;\n        while((idx2<arcIrregular.at(k).size()) && ((arcIrregular.at(k).at(idx2).time-times.at(idx-1)).seconds() < +margin))\n          idx2++;\n        irregularSubArcStart.at(k).push_back(idx2Start);\n        irregularSubArcLen.at(k).push_back(idx2-idx2Start);\n        if(idx2-idx2Start < data2.at(k).minArcLen)\n          shortArc = TRUE;\n      }\n\n      // reject arc when too few irregular data epochs were found in the arc\n      if(shortArc)\n      {\n        for(UInt k=0; k<data2.size(); k++)\n        {\n          irregularSubArcStart.at(k).pop_back();\n          irregularSubArcLen.at(k).pop_back();\n        }\n        continue;\n      }\n\n      // valid arc -> save\n      subArcStart.push_back(idxStart);\n      subArcLen.push_back(idx-idxStart);\n\n      if(arcsInterval.size())\n        for(UInt i=idxInterval+1; i<arcsInterval.size(); i++)\n          arcsInterval.at(i) = subArcLen.size();\n    } // end while((times.size()-idx) >= minArcLen)\n\n    if(subArcStart.size()==0)\n    {\n      logWarning<<\"no arcs found\"<<Log::endl;\n      return;\n    }\n\n    // =============================================\n\n    // save files\n    // ----------\n    if(!outArcList.empty())\n    {\n      logStatus<<\"write arc list <\"<<outArcList<<\">\"<<Log::endl;\n      writeFileArcList(outArcList, arcsInterval, timesInterval);\n    }\n\n    std::vector<Arc> arcList;\n    for(UInt k=0; k<data.size(); k++)\n    {\n      arcList.resize(0);\n      for(UInt i=0; i<subArcStart.size(); i++)\n        arcList.push_back( arc.at(k).subArc(subArcStart.at(i), subArcLen.at(i)) );\n      if(!data.at(k).outName.empty())\n      {\n        logStatus<<\"write instrument file <\"<<data.at(k).outName<<\">\"<<Log::endl;\n        InstrumentFile::write(data.at(k).outName, arcList);\n      }\n    }\n\n    // write irregular data to file\n    for(UInt k=0; k<data2.size(); k++)\n    {\n      if(!data2.at(k).outName.empty())\n      {\n        logStatus<<\"write irregular instrument file <\"<<data2.at(k).outName<<\">\"<<Log::endl;\n        std::vector<Arc> arcIrregularList;\n        for(UInt i=0; i<irregularSubArcStart.at(k).size(); i++)\n          arcIrregularList.push_back( arcIrregular.at(k).subArc(irregularSubArcStart.at(k).at(i), irregularSubArcLen.at(k).at(i)) );\n        InstrumentFile::write(data2.at(k).outName, arcIrregularList);\n      }\n    }\n\n    Arc::printStatistics(arcList);\n    for(UInt i=1; i<arcsInterval.size(); i++)\n      if(arcsInterval.at(i-1) == arcsInterval.at(i))\n        logWarning << i<<\". intervall (\"<<timesInterval.at(i-1).dateTimeStr()<<\" - \"<<timesInterval.at(i).dateTimeStr()<<\") is empty\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n"
  },
  {
    "path": "source/programs/instruments/instrumentWaveletDecomposition.cpp",
    "content": "/***********************************************/\n/**\n* @file instrumentWaveletDecomposition.cpp\n*\n* @brief Wavelet decomposition of an instrument file.\n*\n* @author Saniya Behzadpour\n* @date 2018-07-17\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program performs a multilevel one-dimensional wavelet analysis on one \\config{selectDataField}\ndata column of \\configFile{inputfileInstrument}{instrument}.\nThe \\configFile{outputfileInstrument}{instrument} contains the decomposed levels in time domain ${a_J,d_J,...,d_1}$\n)\";\n\n\n/***********************************************/\n#include \"base/wavelets.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"parallel/parallel.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Wavelet decomposition of an instrument file.\n* @ingroup programsGroup */\nclass InstrumentWaveletDecomposition\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(InstrumentWaveletDecomposition, SINGLEPROCESS, \"Wavelet decomposition of an instrument file.\", Instrument)\n\n/***********************************************/\n\nvoid InstrumentWaveletDecomposition::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    FileName fileNameIn, fileNameInWavelet;\n    UInt     selectData;\n    UInt     level;\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut,       Config::MUSTSET, \"\", \"MISCVALUES, decomposed levels in time domain a_J,d_J,...,d_1\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,        Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"selectDataField\",      selectData,        Config::DEFAULT, \"0\", \"select a data column for decomposition\");\n    readConfig(config, \"inputfileWavelet\",     fileNameInWavelet, Config::MUSTSET, \"{groopsDataDir}/wavelets/\", \"wavelet coefficients\");\n    readConfig(config, \"level\",                level,             Config::MUSTSET, \"4\", \"level of decomposition\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read instrument file \"<<\"<\"<<fileNameIn<<\">\"<<Log::endl;\n    const Arc arc = InstrumentFile::read(fileNameIn);\n\n    logStatus<<\"read wavelet filters \"<<\"<\"<<fileNameInWavelet<<\">\"<<Log::endl;\n    Vector wl;\n    readFileMatrix(fileNameInWavelet, wl);\n\n    // perform n-Level DWT\n    std::vector<UInt>   length, flag;\n    std::vector<Double> dwtCoeff;\n    std::vector<Double> signal = Vector(arc.matrix().column(1+selectData));\n    Wavelets::discreteWaveletTransform(signal, wl, level, dwtCoeff, flag, length);\n\n    // detail coefficients in each column\n    UInt idx = 0;\n    std::vector<std::vector<Double>> dwt(level+1, std::vector<Double>(dwtCoeff.size(), 0.));\n    for(UInt j=0; j<level+1;j++)\n      for(UInt i=0; i<length.at(j); i++)\n      {\n        dwt.at(j).at(idx) = dwtCoeff.at(idx);\n        idx++;\n      }\n\n    // apply inverse DWT, from wavelet domain to time domain\n    std::vector<std::vector<Double>> idwt(level+1);\n    for (UInt j=0; j<level+1; j++)\n      Wavelets::inverseDiscreteWaveletTransform(dwt.at(j), wl, flag, idwt.at(j), length);\n\n    MiscValuesArc arcOut;\n    for(UInt i=0; i<arc.size(); i++)\n    {\n      MiscValuesEpoch epoch(level+1);\n      epoch.time = arc.at(i).time;\n      for(UInt j=0; j<level+1; j++)\n        epoch.values(j) = idwt.at(j).at(i);\n      arcOut.push_back(epoch);\n    }\n\n    logStatus<<\"write decomposed signals\"<<\"<\"<<fileNameOut<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOut, arcOut);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/*************************************************/\n"
  },
  {
    "path": "source/programs/instruments/localLevelFrame2StarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file localLevelFrame2StarCamera.cpp\n*\n* @brief Compute rotation matrix from local level frame (north, east, down) to TRF and save as StarCamera file.\n*\n* @author Sebastian Strasser\n* @date 2017-06-28\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute rotation (\\file{StarCamera file}{instrument}) from local level frame (ellipsoidal north, east, down)\nto TRF for positions given in \\configFile{inputfileInstrument}{instrument} (first 3 data columns).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***********************************************/\n\n/** @brief Rotation from local level frame (ellipsoidal north, east, down) to TRF.\n* @ingroup programsGroup */\nclass LocalLevelFrame2StarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(LocalLevelFrame2StarCamera, PARALLEL, \"Rotation from local level frame (ellipsoidal north, east, down) to TRF.\", Instrument, Simulation)\nGROOPS_RENAMED_PROGRAM(SimulateLocalLevelFrame, LocalLevelFrame2StarCamera, date2time(2018, 7, 4))\n\n/***********************************************/\n\nvoid LocalLevelFrame2StarCamera::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    Double a, f;\n    FileName fileNameStarCamera;\n    FileName fileNameInstrument;\n    Bool constantOrigin;\n\n    readConfig(config, \"outputfileStarCamera\", fileNameStarCamera, Config::MUSTSET,  \"\",  \"rotation matrix from local level frame (ellipsoidal north, east, down) to TRF\");\n    readConfig(config, \"inputfileInstrument\",  fileNameInstrument, Config::MUSTSET,  \"\",  \"origin of local level frame\");\n    readConfig(config, \"constantOriginPerArc\", constantOrigin,     Config::DEFAULT,  \"0\", \"use constant origin for all epochs of an arc (median position)\");\n    readConfig(config, \"R\",                    a,                  Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",    f,                  Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"compute local level frame rotation\"<<Log::endl;\n    Ellipsoid ellipsoid(a, f);\n    InstrumentFile epochFile(fileNameInstrument);\n    std::vector<Arc> arcList(epochFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc      arc = epochFile.readArc(arcNo);\n      Matrix   A   = arc.matrix();\n      Vector3d origin(median(A.column(1)), median(A.column(2)), median(A.column(3)));\n\n      StarCameraArc scaArc;\n      for(UInt k=0; k<A.rows(); k++)\n      {\n        // Local (north, east, down) -> global TRF\n        StarCameraEpoch epoch;\n        epoch.time   = arc.at(k).time;\n        epoch.rotary = localNorthEastDown((constantOrigin ? origin : Vector3d(A.slice(k,1,1,3))), ellipsoid);\n        scaArc.push_back(epoch);\n      }\n      return scaArc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write star camera data to file <\"<<fileNameStarCamera<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameStarCamera, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/kalmanFilter/kalmanBuildNormals.cpp",
    "content": "/***********************************************/\n/**\n* @file kalmanBuildNormals.cpp\n*\n* @brief Accumulate normals for sub monthly data sets.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2009-10-10\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program sets up normal equations based on \\configClass{observation}{observationType}\nfor short-term gravity field variations.\nIt computes the normal equations based on the intervals $i \\in \\{1, ..., N\\}$ given in the \\configFile{arcList}{arcList}.\nIt sets up the least squares adjustment\n\\begin{equation}\n    \\begin{bmatrix}\n    \\mathbf{l}_1 \\\\\n    \\mathbf{l}_2 \\\\\n    \\vdots \\\\\n    \\mathbf{l}_N \\\\\n  \\end{bmatrix}\n  =\n  \\begin{bmatrix}\n    \\mathbf{A}_1  &  & & \\\\\n    & \\mathbf{A}_2  & &\\\\\n    &  & \\ddots & \\\\\n    & & & \\mathbf{A}_N \\\\\n  \\end{bmatrix}\n  \\begin{bmatrix}\n    \\mathbf{x}^{(1)} \\\\\n    \\mathbf{x}^{(2)} \\\\\n    \\vdots \\\\\n    \\mathbf{x}^{(N)} \\\\\n  \\end{bmatrix}\n  +\n  \\begin{bmatrix}\n    \\mathbf{e}_1 \\\\\n    \\mathbf{e}_2 \\\\\n    \\vdots \\\\\n    \\mathbf{e}_N \\\\\n  \\end{bmatrix},\n\\end{equation}\nand subsequently computes the normal equations $\\mathbf{N}_i, \\mathbf{n}_i$ for each interval.\nIf \\config{eliminateNonGravityParameters} is true, all non-gravity parameters are eliminated before the normals\nare written to \\configFile{outputfileNormalEquation}{normalEquation}.\nFor each time interval in \\config{arcList} a single \\file{normal equation file}{normalEquation} is written.\n\nThis program computes the input normals for \\program{KalmanFilter} and \\program{KalmanSmootherLeastSquares}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/observation/observation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accumulate normals for sub monthly data sets.\n* @ingroup programsGroup */\nclass KalmanBuildNormals\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\nprivate:\n  ObservationPtr    observation;\n  std::vector<UInt> arcsInterval;\n  std::vector<Time> timesInterval;\n\n  // normal equation system (for each interval)\n  std::vector<UInt>    obsCount;\n  std::vector<Matrix>  N,  n;\n  std::vector<Vector>  lPl;\n\n  void computeArc(UInt arcNo);\n};\n\nGROOPS_REGISTER_PROGRAM(KalmanBuildNormals, PARALLEL, \"accumulate normals for sub monthly data sets.\", KalmanFilter, NormalEquation)\n\n/***********************************************/\n\nvoid KalmanBuildNormals::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName      fileNameNormals;\n    FileName      fileNameArcList;\n    Bool          eliminatePararmeter;\n\n    renameDeprecatedConfig(config, \"inputfileNormalequation\", \"inputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"arcList\",                 \"inputfileArcList\",        date2time(2020, 7, 7));\n\n    readConfig(config, \"outputfileNormalEquation\",      fileNameNormals,     Config::MUSTSET,  \"normals/normals_{loopTime:%D}.dat\", \"outputfile for normal equations\");\n    readConfig(config, \"observation\",                   observation,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileArcList\",              fileNameArcList,     Config::MUSTSET,  \"\",  \"list to correspond points of time to arc numbers\");\n    readConfig(config, \"eliminateNonGravityParameters\", eliminatePararmeter, Config::DEFAULT,  \"1\", \"eliminate additional parameters from normals, 0: all parameter are saved\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    const UInt arcCount = observation->arcCount();\n\n    // read arc list\n    // -------------\n    logStatus<<\"read arc list <\"<<fileNameArcList<<\">\"<<Log::endl;\n    readFileArcList(fileNameArcList, arcsInterval, timesInterval);\n    if(arcsInterval.back()>arcCount)\n      throw(Exception(\"count of arcs differ in observation and arcList\"));\n\n    VariableList fileNameVariableList;\n    addTimeVariables(fileNameVariableList);\n\n    // =======================\n\n    // setup observation equations\n    // ---------------------------\n    logStatus<<\"set up observation equations\"<<Log::endl;\n    // init normals\n    N.resize(arcsInterval.size()-1);\n    n.resize(arcsInterval.size()-1);\n    lPl.resize(arcsInterval.size()-1);\n    obsCount.resize(arcsInterval.size()-1, 0);\n    Parallel::forEachInterval(arcCount, arcsInterval, [this](UInt arcNo) {return computeArc(arcNo);}, comm);\n\n    // =======================\n\n    // collect system of normal equations\n    // ----------------------------------\n    if(Parallel::size(comm)>=3)\n    {\n      logStatus<<\"collect system of normal equations\"<<Log::endl;\n      for(UInt idxInterval=0; idxInterval<timesInterval.size()-1; idxInterval++)\n      {\n        UInt color = MAX_UINT;\n        if(N.at(idxInterval).size())\n          color = idxInterval;\n\n        Parallel::CommunicatorPtr commSplit= Parallel::splitCommunicator(color, Parallel::myRank(comm), comm);\n        if(commSplit && (Parallel::size(commSplit)>1))\n        {\n          Parallel::reduceSum(N.at(idxInterval),        0, commSplit);\n          Parallel::reduceSum(n.at(idxInterval),        0, commSplit);\n          Parallel::reduceSum(lPl.at(idxInterval),      0, commSplit);\n          Parallel::reduceSum(obsCount.at(idxInterval), 0, commSplit);\n          if(Parallel::myRank(commSplit) != 0)\n          {\n            N.at(idxInterval) = Matrix();\n            n.at(idxInterval) = Matrix();\n            lPl.at(idxInterval) = Vector();\n            obsCount.at(idxInterval) = 0;\n          }\n        }\n      } // for(idxInterval)\n    } // if(Parallel::size()>=3)\n\n    // =======================\n\n    logStatus<<\"computing normals\"<<Log::endl;\n    for(UInt idxInterval=0; idxInterval<timesInterval.size()-1; idxInterval++)\n      if(N.at(idxInterval).size())\n      {\n        NormalEquationInfo normalInfo;\n        observation->parameterName(normalInfo.parameterName);\n\n        // eliminate state parameters\n        if(eliminatePararmeter && (observation->parameterCount() > observation->gravityParameterCount()))\n        {\n          // regularize not used parameters\n          for(UInt i=observation->gravityParameterCount(); i<N.at(idxInterval).rows(); i++)\n            if(N.at(idxInterval)(i,i)==0)\n            {\n              N.at(idxInterval)(i,i)   += 1.0;\n              obsCount.at(idxInterval) += 1;\n            }\n\n          Double regul = 1;\n          for(;;)\n          {\n            try\n            {\n              UInt startElim = observation->gravityParameterCount();\n              UInt countElim = observation->parameterCount() - observation->gravityParameterCount();\n\n              // solve for state parameters and update correlation block\n              Matrix N22 = N.at(idxInterval).slice(startElim, startElim, countElim, countElim);\n              cholesky(N22); // N22 = W^T*W\n              triangularSolve(1.0, N22.trans(), N.at(idxInterval).slice(0, startElim, startElim, countElim).trans()); //N12*W^-1\n\n              // update coefficient matrix\n              rankKUpdate(-1.0, N.at(idxInterval).slice(0, startElim, startElim, countElim).trans(),\n                                N.at(idxInterval).slice(0, 0, startElim, startElim)); // N = N11 - N12 (W^T W)^-1 N12^T\n\n              // update right hand side\n              triangularSolve(1.0, N22.trans(), n.at(idxInterval).row(startElim, countElim)); // W^-T * n2\n              matMult(-1.0, N.at(idxInterval).slice(0, startElim, startElim, countElim),\n                            n.at(idxInterval).row(startElim, countElim),\n                            n.at(idxInterval).row(0, startElim)); // n = n1 - N12*W^-1 * W^-T*n2\n\n              // update normals\n              obsCount.at(idxInterval) -= countElim;\n              for(UInt i=0; i<lPl.at(idxInterval).rows(); i++)\n                lPl.at(idxInterval)(i) -= quadsum(n.at(idxInterval).slice(startElim, i, countElim, 1)); // lPl = lPl - n2^T N2^(-1) n2\n\n              N.at(idxInterval) =  N.at(idxInterval).slice(0, 0, startElim, startElim);\n              n.at(idxInterval) =  n.at(idxInterval).row(0, startElim);\n              break;\n            }\n            catch(std::exception &e)\n            {\n              logError<<\"error at \"<<timesInterval.at(idxInterval).dateStr()<<\": \"<<e.what()<<\" continue...\"<<Log::endl;\n              for(UInt i=observation->gravityParameterCount(); i<N.at(idxInterval).rows(); i++)\n                N.at(idxInterval)(i,i) += regul;\n              regul *= 10;\n            }\n          }\n\n          normalInfo.parameterName.resize(observation->gravityParameterCount());\n        }\n\n        // save normals\n        // ------------\n        normalInfo.lPl = lPl.at(idxInterval);\n        normalInfo.observationCount = obsCount.at(idxInterval);\n        evaluateTimeVariables(idxInterval, timesInterval.at(idxInterval), timesInterval.at(idxInterval+1), fileNameVariableList);\n        logStatus<<\"write normal equations to <\"<<fileNameNormals(fileNameVariableList)<<\">\"<<Log::endl;\n        writeFileNormalEquation(fileNameNormals(fileNameVariableList), normalInfo, N.at(idxInterval), n.at(idxInterval));\n      } // for(idxInterval)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid KalmanBuildNormals::computeArc(UInt arcNo)\n{\n  try\n  {\n    // observation equations\n    // ---------------------\n    Matrix l,A,B;\n    observation->observation(arcNo, l,A,B);\n    if(l.rows()==0)\n      return;\n\n    // if equations are orthogonaly transformed\n    // additional residuals are appended to l\n    // ----------------------------------------\n    Matrix l2;\n    if(l.rows()>A.rows())\n    {\n      l2 = l.row(A.rows(), l.rows()-A.rows());\n      l  = l.row(0, A.rows());\n    }\n\n    // eliminate arc related parameters\n    // --------------------------------\n    if(B.size()!=0)\n      eliminationParameter(B,A,l);\n\n    // search time interval\n    // --------------------\n    UInt idxInterval = 0;\n    while(arcsInterval.at(idxInterval+1)<=arcNo)\n      idxInterval++;\n\n    // accumulate normal equation system\n    // ---------------------------------\n    obsCount.at(idxInterval) += l.rows() + l2.rows();\n    if(lPl.at(idxInterval).size() == 0)\n      lPl.at(idxInterval) = Vector(l.columns());\n    for(UInt i=0; i<l.columns(); i++)\n      lPl.at(idxInterval)(i) += quadsum(l.column(i)) + quadsum(l2.column(i));\n    // right hand side\n    if(n.at(idxInterval).size() == 0)\n      n.at(idxInterval) = Matrix(A.columns(), l.columns());\n    matMult(1., A.trans(), l, n.at(idxInterval));\n    // normal matrix\n    if(N.at(idxInterval).size() == 0)\n      N.at(idxInterval) = Matrix(A.columns(), Matrix::SYMMETRIC);\n    rankKUpdate(1., A, N.at(idxInterval));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/kalmanFilter/kalmanFilter.cpp",
    "content": "/***********************************************/\n/**\n* @file kalmanFilter.cpp\n*\n* @brief Computes time variable gravity fields using Kalman filter approach\n*\n* @author Enrico Kurtenbach\n* @author Andreas Kvas\n* @date 2008-11-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThe program computes time variable gravity fields using the Kalman filter approach of\n\nKurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012).\nImproved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.\n\\url{https://doi.org/10.1016/j.jog.2012.02.006}.\n\nThe updated state $\\mathbf{x}_t^+$ is determined by solving the least squares adjustment\n\\begin{equation}\n\\mathbf{l}_t = \\mathbf{A}_t \\mathbf{x}_t + \\mathbf{e}_t \\hspace{25pt} \\mathbf{e}_t \\sim \\mathcal{N}(0, \\mathbf{R}_t)\\\\\n\\mathbf{B} \\mathbf{x}^+_{t-1} = \\mathbf{I} \\mathbf{x}_t + \\mathbf{v}_t\\hspace{25pt} \\mathbf{v} \\sim \\mathcal{N}(0,\\mathbf{Q} + \\mathbf{B} \\mathbf{P}^+_{t-1}\\mathbf{B}^T).\n\\end{equation}\nIn normal equation form this can be written as\n\\begin{equation}\n\\hat{\\mathbf{x}}_t = \\mathbf{x}^+_t = (\\mathbf{N}_t + \\mathbf{P}^{-^{-1}}_t)^{-1}(\\mathbf{n}_t + \\mathbf{P}^{-^{-1}}_t \\mathbf{x}^-_t),\n\\end{equation}\nwhere $\\mathbf{x}_t^- = \\mathbf{B} \\mathbf{x}^+_{t-1}$ and $\\mathbf{P}_t^{-} = \\mathbf{Q} + \\mathbf{B} \\mathbf{P}^+_{t-1}\\mathbf{B}^T$\nare the predicted state and its covariance matrix.\n\nThe process dynamic $\\mathbf{B}, \\mathbf{Q}$ is represented as an \\reference{autoregressive model}{fundamentals.autoregressiveModel},\nand passed to the program through \\configFile{inputfileAutoregressiveModel}{matrix}.\nThe sequence of normal equations $\\mathbf{N}_t, \\mathbf{n}_t$ are given as list of \\configFile{inputfileNormalEquations}{normalEquation},\nwhich can be generated using \\configClass{loops}{loopType}.\nIn the same way, the \\file{matrix files}{matrix} for \\config{outputfileUpdatedState} and \\config{inputfileUpdatedStateCovariance}\ncan also be specified using \\configClass{loops}{loopType}.\n\nIf no \\configFile{inputfileInitialState}{matrix} is set, a zero vector with appropriate dimensions is used.\nThe \\configFile{inputfileInitialStateCovarianceMatrix}{matrix} however must be given.\n\nSee also \\program{KalmanBuildNormals}, \\program{KalmanSmoother}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/kalmanProcessing.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Computes time variable gravity fields using Kalman filter approach\n* @ingroup programsGroup */\nclass KalmanFilter\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(KalmanFilter, SINGLEPROCESS, \"Computes time variable gravity fields using Kalman filter approach\", KalmanFilter, NormalEquation)\n\n/***********************************************/\n\nvoid KalmanFilter::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName> fileNameState, fileNameStateCovarianceMatrix;\n    FileName fileNameInitialState, fileNameInitialCovariance;\n    FileName fileNameArModel;\n    std::vector<FileName> fileNameNormals;\n\n    readConfig(config, \"outputfileUpdatedState\",                   fileNameState,                          Config::MUSTSET,   \"kalman/updatedState/x_{loopTime:%D}.txt\",                      \"estimated state x+ (nx1-matrix)\");\n    readConfig(config, \"outputfileUpdatedStateCovarianceMatrix\",   fileNameStateCovarianceMatrix,          Config::OPTIONAL, \"kalman/updatedStateCovariance/covariance_{loopTime:%D}.dat\",   \"estimated state' s covariance matrix Cov(x+)\");\n    readConfig(config, \"inputfileNormalEquations\",                 fileNameNormals,                        Config::MUSTSET,  \"\", \"normal equations input file\");\n    readConfig(config, \"inputfileInitialState\",                    fileNameInitialState,                   Config::OPTIONAL,  \"\", \"initial state x0\");\n    readConfig(config, \"inputfileInitialStateCovarianceMatrix\",    fileNameInitialCovariance,              Config::MUSTSET,   \"\", \"initial state's covariance matrix Cov(x0)\");\n    readConfig(config, \"inputfileAutoregressiveModel\",             fileNameArModel,                        Config::MUSTSET,   \"\", \"file name of autoregressive model\");\n    if(isCreateSchema(config)) return;\n\n    // check input\n    // -----------\n    const UInt epochCount = fileNameNormals.size();\n\n    if(fileNameState.size() != epochCount)\n      throw(Exception(\"Number of solution file names and normal equations does not match (\" + fileNameState.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    if( (fileNameStateCovarianceMatrix.size() > 0) && (fileNameStateCovarianceMatrix.size() != epochCount))\n      throw(Exception(\"Number of covariance matrix file names and normal equations does not match (\" + fileNameStateCovarianceMatrix.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    // set up ar model\n    // ---------------\n    logStatus<<\"read autoregressive model from <\"<<fileNameArModel<<\">\"<<Log::endl;\n    Matrix tmp;\n    readFileMatrix(fileNameArModel, tmp);\n    AutoregressiveModel arModel(tmp);\n\n    Matrix B, Q;\n    arModel.orderOneRepresentation(B, Q);\n\n    // load initial state:\n    // -------------------\n    logStatus<<\"initialize state's covariance matrix with <\"<<fileNameInitialCovariance<<\">\"<<Log::endl;\n    Matrix updatedStateCovariance;\n    readFileMatrix(fileNameInitialCovariance, updatedStateCovariance);\n\n    Matrix updatedState(updatedStateCovariance.rows(),1);\n    if(!fileNameInitialState.empty())\n    {\n      logStatus <<\"initialize initial state with <\"<<fileNameInitialState<<\">\"<< Log::endl;\n      readFileMatrix(fileNameInitialState, updatedState);\n    }\n\n    // Run the filter:\n    // ---------------\n    for(UInt k = 0; k<fileNameNormals.size(); k++)\n    {\n      Matrix predictedState = B*updatedState;\n      Matrix predictedStateCovariance = Q+B*updatedStateCovariance*B.trans();\n\n      try\n      {\n        NormalEquationInfo info;\n        Matrix N, n;\n        readFileNormalEquation(fileNameNormals.at(k), info, N, n);\n\n        inverse(predictedStateCovariance);\n        updatedStateCovariance = predictedStateCovariance;\n        axpy(1.0, N, updatedStateCovariance.slice(0, 0, N.rows(), n.rows()));\n        inverse(updatedStateCovariance);\n        fillSymmetric(updatedStateCovariance);\n\n        matMult(-1.0, N, predictedState.row(0, N.rows()), n);\n        updatedState = predictedState;\n        matMult(1.0, updatedStateCovariance.column(0, n.rows()), n, updatedState);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<Log::endl;\n        updatedState = predictedState;\n        updatedStateCovariance = predictedStateCovariance;\n      }\n\n      logStatus <<\"write updated state to <\"<<fileNameState.at(k)<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameState.at(k), updatedState);\n      if(!fileNameStateCovarianceMatrix.empty())\n      {\n        logStatus <<\"write updated state covariance to <\"<<fileNameStateCovarianceMatrix.at(k)<<\">\"<<Log::endl;\n        writeFileMatrix(fileNameStateCovarianceMatrix.at(k), updatedStateCovariance);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/kalmanFilter/kalmanSmoother.cpp",
    "content": "/***********************************************/\n/**\n* @file kalmanSmoother.cpp\n*\n* @brief Computes time variable gravity fields using Kalman smoother\n*\n* @author Enrico Kurtenbach\n* @author Andreas Kvas\n* @date 2008-11-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nApply the Rauch-Tung-Striebel smoother to a gravity field time series computed by \\program{KalmanFilter}.\nThis is the implementation of the approach presented in\n\nKurtenbach, E., Eicker, A., Mayer-Gürr, T., Holschneider, M., Hayn, M., Fuhrmann, M., and Kusche, J. (2012).\nImproved daily GRACE gravity field solutions using a Kalman smoother. Journal of Geodynamics, 59–60, 39–48.\n\\url{https://doi.org/10.1016/j.jog.2012.02.006}.\n\nThe result has zero phase and the squared magnitude response of \\configFile{inputfileAutoregressiveModel}{matrix}\n(see \\reference{autoregressiveModel}{fundamentals.autoregressiveModel} for details).\n\\configFile{inputfileUpdatedState}{matrix} and \\configFile{inputfileUpdatedStateCovariance}{matrix}\nare the output of a \\program{KalmanFilter} forward sweep.\nThe matrix files for\\configFile{outputfileUpdatedState}{matrix}, \\configFile{inputfileUpdatedState}{matrix}\nand \\configFile{inputfileUpdatedStateCovariance}{matrix} can also be specified using \\configClass{loops}{loopType}.\n\nSee also \\program{KalmanBuildNormals}, \\program{KalmanFilter} and \\program{KalmanSmootherLeastSquares}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/kalmanProcessing.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Computes time variable gravity fields using Kalman filter approach\n* @ingroup programsGroup */\nclass KalmanSmoother\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(KalmanSmoother, SINGLEPROCESS, \"Computes time variable gravity fields using Kalman smoother approach\", KalmanFilter, NormalEquation)\n\n/***********************************************/\n\nvoid KalmanSmoother::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName> fileNameSmoothedState,  fileNameSmoothedCovariance, fileNameUpdatedState, fileNameUpdatedCovariance;\n    FileName fileNameArModel;\n\n    readConfig(config, \"outputfileState\",                         fileNameSmoothedState,            Config::MUSTSET,   \"kalman/smoothedState/x_{loopTime:%D}.txt\",                    \"estimated parameters (nx1-matrix)\");\n    readConfig(config, \"outputfileStateCovarianceMatrix\",         fileNameSmoothedCovariance,       Config::OPTIONAL,  \"kalman/smoothedStateCovariance/covariance_{loopTime:%D}.dat\", \"estimated parameters' covariance matrix\");\n    readConfig(config, \"inputfileUpdatedState\",                   fileNameUpdatedState,             Config::MUSTSET,   \"kalman/updatedState/x_{loopTime:%D}.txt\", \"\");\n    readConfig(config, \"inputfileUpdatedStateCovarianceMatrix\",   fileNameUpdatedCovariance,        Config::MUSTSET,   \"kalman/updatedStateCovariance/covariance_{loopTime:%D}.dat\", \"\");\n    readConfig(config, \"inputfileAutoregressiveModel\",            fileNameArModel,                  Config::MUSTSET,   \"\", \"file name of autoregressive model\");\n    if(isCreateSchema(config)) return;\n\n    // check input\n    // -----------\n    const UInt epochCount = fileNameSmoothedState.size();\n\n    if(fileNameUpdatedState.size() != epochCount)\n      throw(Exception(\"Number of update state file names and state vectors does not match (\" + fileNameUpdatedState.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    if(fileNameUpdatedCovariance.size() != epochCount)\n      throw(Exception(\"Number of update state covariance file names and state vectors does not match (\" + fileNameUpdatedCovariance.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    if( (fileNameSmoothedCovariance.size() > 0) && (fileNameSmoothedCovariance.size() != epochCount))\n      throw(Exception(\"Number of smoothed state covariance file names and state vectors does not match (\" + fileNameSmoothedCovariance.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    // compute AR model\n    // ----------------\n    logStatus<<\"read autoregressive model from <\"<<fileNameArModel<<\">\"<<Log::endl;\n    Matrix tmp;\n    readFileMatrix(fileNameArModel, tmp);\n    AutoregressiveModel arModel(tmp);\n\n    Matrix B, Q;\n    arModel.orderOneRepresentation(B, Q);\n\n    // Initialize backward smoother:\n    Matrix smoothedState, smoothedStateCovariance;\n    Matrix updatedState, updatedStateCovariance;\n    Matrix predictedState, predictedStateCovariance;\n\n    logStatus <<\"initialize state with <\"<<fileNameUpdatedState.back()<<\"> and <\"<<fileNameUpdatedCovariance.back()<<\">\"<<Log::endl;\n    readFileMatrix(fileNameUpdatedState.back(), updatedState);\n    readFileMatrix(fileNameUpdatedCovariance.back(), updatedStateCovariance);\n\n    smoothedState = updatedState;\n    smoothedStateCovariance = updatedStateCovariance;\n    logStatus <<\"write smoothed state to <\"<<fileNameSmoothedState.back()<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameSmoothedState.back(), smoothedState);\n    if(fileNameSmoothedCovariance.size() > 0)\n    {\n      logStatus <<\"write smoothed state to <\"<<fileNameSmoothedCovariance.back()<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameSmoothedCovariance.back(), smoothedStateCovariance);\n    }\n\n    for(UInt k=epochCount-1; k>0; k--)\n    {\n      readFileMatrix(fileNameUpdatedState.at(k-1), updatedState);\n      readFileMatrix(fileNameUpdatedCovariance.at(k-1), updatedStateCovariance);\n\n      predictedState = B*updatedState;\n\n      // predicted state covariance\n      cholesky(updatedStateCovariance);\n      Matrix smootherGain = B;\n      triangularMult(1.0, updatedStateCovariance, smootherGain.trans());\n\n      predictedStateCovariance = Q;\n      rankKUpdate(1.0, smootherGain.trans(), predictedStateCovariance);\n\n      // transposed gain matrix K\n      triangularMult(1.0, updatedStateCovariance.trans(), smootherGain.trans());\n      solveInPlace(predictedStateCovariance, smootherGain);\n\n      // smoothed state\n      smoothedState = updatedState + smootherGain.trans()*(smoothedState-predictedState);\n\n      // smoothed state covariance\n      zeroUnusedTriangle(predictedStateCovariance);\n      predictedStateCovariance.setType(Matrix::GENERAL);\n      rankKUpdate(-1.0, predictedStateCovariance, smoothedStateCovariance);\n      fillSymmetric(smoothedStateCovariance);\n      smoothedStateCovariance.setType(Matrix::GENERAL);\n\n      smoothedStateCovariance = smootherGain.trans()*smoothedStateCovariance*smootherGain;\n      smoothedStateCovariance.setType(Matrix::SYMMETRIC);\n      zeroUnusedTriangle(updatedStateCovariance);\n      updatedStateCovariance.setType(Matrix::GENERAL);\n      rankKUpdate(1.0, updatedStateCovariance, smoothedStateCovariance);\n\n      logStatus <<\"write smoothed state to <\"<<fileNameSmoothedState.at(k-1)<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameSmoothedState.at(k-1), smoothedState);\n      if(!fileNameSmoothedCovariance.empty())\n      {\n        logStatus <<\"write smoothed state covariance to <\"<<fileNameSmoothedCovariance.at(k-1)<<\">\"<<Log::endl;\n        writeFileMatrix(fileNameSmoothedCovariance.at(k-1), smoothedStateCovariance);\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/kalmanFilter/kalmanSmootherLeastSquares.cpp",
    "content": "/***********************************************/\n/**\n* @file kalmanSmootherLeastSquares.cpp\n*\n* @brief Computes smoothed estimates of time variable gravity field using a constraint least squares adjustment.\n*\n* @author Andreas Kvas\n* @date 2015-10-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates temporal gravity field variations with a constraint least squares adjustment.\nPrior information is introduced by means of a \\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType}\nwhich represent a stationary random process (see the \\reference{autoregressive model description}{fundamentals.autoregressiveModel}) for details.\n\nThe output files for the estimated gravity field (\\configFile{outputfileSolution}{matrix}), the\ncorresponding standard deviations (\\configFile{outputfileSigmax}{matrix}) and the full covariance matrix\n(\\configFile{outputfileCovariance}{matrix}) can be specified using \\configClass{loops}{loopType}.\nSimilarly, the \\configFile{inputfileNormalEquations}{normalEquation}\ncan also be specified using \\configClass{loops}{loopType}.\n\nSee also \\program{KalmanBuildNormals}, \\program{KalmanFilter} and\\program{KalmanSmoother}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/kalmanProcessing.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Computes smoothed estimates of time variable gravity field using a constraint least squares adjustment.\n* RTS smoother implemented as least squares adjustment.\n* @ingroup programsGroup */\nclass KalmanSmootherLeastSquares\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(KalmanSmootherLeastSquares, PARALLEL, \"Smoothed time variable gravity field by least squares adjustment\", KalmanFilter, NormalEquation)\n\n/***********************************************/\n\nvoid KalmanSmootherLeastSquares::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<FileName> fileNameSolution, fileNameSigmax, fileNameCovariance, fileNameNormals;\n    AutoregressiveModelSequencePtr arSequence;\n\n    readConfig(config, \"outputfileSolution\",             fileNameSolution,               Config::MUSTSET,   \"kalman/smoothedState/x_{loopTime:%D}.txt\", \"file name of solution vector (use time tags)\");\n    readConfig(config, \"outputfileSigmax\"  ,             fileNameSigmax,                 Config::OPTIONAL,  \"kalman/smoothedStateSigma/sigmax_{loopTime:%D}.txt\", \"file name of sigma vector (use time tags)\");\n    readConfig(config, \"outputfileCovariance\"  ,         fileNameCovariance,             Config::OPTIONAL,  \"kalman/smoothedStateCovariance/covariance_{loopTime:%D}.dat\", \"file name of full covariance matrix (use time tags)\");\n    readConfig(config, \"inputfileNormalEquations\"  ,     fileNameNormals,                Config::MUSTSET,   \"\", \"input normal equations (loopTime will be expanded)\");\n    readConfig(config, \"autoregressiveModelSequence\",    arSequence,                     Config::MUSTSET,   \"\", \"file containing AR model for spatiotemporal constraint\");\n    if(isCreateSchema(config)) return;\n\n    // check input\n    // -----------\n    const UInt epochCount = fileNameNormals.size();\n\n    if(fileNameSolution.size() != epochCount)\n      throw(Exception(\"Number of solution file names and normal equations does not match (\" + fileNameSolution.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    if( (fileNameSigmax.size() > 0) && (fileNameSigmax.size() != epochCount))\n      throw(Exception(\"Number of standard deviation file names and normal equations does not match (\" + fileNameSigmax.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    if( (fileNameCovariance.size() > 0) && (fileNameCovariance.size() != epochCount))\n      throw(Exception(\"Number of covariance matrix file names and normal equations does not match (\" + fileNameCovariance.size()%\"%i\"s + \" vs. \" + epochCount%\"%i\"s + \").\"));\n\n    // set up normals of process\n    // -------------------------\n    logInfo<<\"process is modelled by an AR(\"<<arSequence->maximumOrder()<<\") model\"<<Log::endl;\n    const UInt stateCount = arSequence->dimension();\n    logInfo<<\"dimension of state vector (\"<<stateCount<<\"x\"<<1<<\")\"<<Log::endl;\n\n    // set up normal equations\n    // -----------------------\n    logStatus<<\"set up normal equations\"<<Log::endl;\n    std::vector<UInt> blockIndex(1, 0);\n    for(UInt k = 0; k<epochCount; k++)\n      blockIndex.push_back(blockIndex.back() + stateCount);\n\n    MatrixDistributed normals;\n    normals.initEmpty(blockIndex, comm);\n    Vector rhs(blockIndex.back());\n\n    // each process reads the normals it requires for filling the main diagonal\n    Double lPlSum = 0.0;\n    UInt obsCountSum = 0;\n    Single::forEach(epochCount, [&](UInt k)\n    {\n      normals.setBlock(k, k);\n      if(normals.isMyRank(k, k))\n      {\n        NormalEquationInfo info;\n        Matrix satelliteNormals, satelliteRightHandSide;\n        try\n        {\n          readFileNormalEquation(fileNameNormals.at(k), info,  satelliteNormals, satelliteRightHandSide);\n        }\n        catch(std::exception &/*e*/)\n        {\n          logWarning<<\"Unable to read normal equation from <\"<<fileNameNormals.at(k)<<\">\"<<Log::endl;\n          return;\n        }\n        lPlSum += info.lPl(0);\n        obsCountSum += info.observationCount;\n        copy(satelliteNormals, normals.N(k, k));\n        copy(satelliteRightHandSide, rhs.row(k*stateCount, stateCount));\n      }\n    });\n\n    Parallel::reduceSum(lPlSum, 0, comm);\n    Parallel::reduceSum(obsCountSum, 0, comm);\n    Parallel::reduceSum(rhs, 0, comm);\n    Parallel::broadCast(rhs, 0, comm);\n\n    // add process normals\n    // -------------------\n    logStatus<<\"add normals of pseudo-observations\"<<Log::endl;\n    auto index = arSequence->distributedNormalsBlockIndex(epochCount);\n    Single::forEach(index.size(), [&](UInt k)\n    {\n      normals.setBlock(index[k].first, index[k].second);\n      if(normals.isMyRank(index[k].first, index[k].second))\n        arSequence->distributedNormalsBlock(normals.blockCount(), index[k].first, index[k].second, normals.N(index[k].first, index[k].second));\n    });\n\n    logStatus<<\"solve normal equation system\"<<Log::endl;\n    Parallel::barrier(comm);\n    Matrix x = normals.solve(rhs, TRUE/*timing*/); // normals now holds Cholesky R\n    if(Parallel::isMaster(comm))\n      logInfo<<\"  a posteriori sigma = \"<<sqrt((lPlSum-inner(x,rhs))/obsCountSum)<<Log::endl;\n\n    if(!fileNameSigmax.empty() || !fileNameCovariance.empty())\n    {\n      logStatus<<\"compute sparse inverse of normal equations\"<<Log::endl;\n      normals.cholesky2SparseInverse();\n    }\n    Parallel::barrier(comm);\n\n    // write results to disk\n    // ---------------------\n    for(UInt k=0; k<epochCount; k++)\n    {\n      if(Parallel::isMaster(comm))\n      {\n        logStatus<<\"write solution vector to <\"<< fileNameSolution.at(k) <<\">.\"<<Log::endl;\n        writeFileMatrix(fileNameSolution.at(k), x.row(k*stateCount, stateCount));\n      }\n\n      if((fileNameSigmax.size()>0) && normals.isMyRank(k, k))\n      {\n        Vector sigmax(normals.N(k,k).rows());\n        for(UInt l = 0; l<sigmax.rows(); l++)\n          sigmax(l) = std::sqrt(normals.N(k, k)(l, l));\n        writeFileMatrix(fileNameSigmax.at(k), sigmax);\n      }\n\n      if((fileNameCovariance.size()>0) && normals.isMyRank(k, k))\n        writeFileMatrix(fileNameCovariance.at(k), normals.N(k, k));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/digitalFilter2FrequencyResponse.cpp",
    "content": "/***********************************************/\n/**\n* @file digitalFilter2FrequencyResponse.cpp\n*\n* @brief Amplitude and phase response of a filter cascade\n*\n* @author Andreas Kvas\n* @date 2017-02-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute amplitude-, phase-, group delay and frequency response of a \\configClass{digitalFilter}{digitalFilterType} cascade.\nThe \\configFile{outputfileResponse}{matrix} is a matrix with following columns:\nfreq $[Hz]$, ampl, phase $[rad]$, group delay $[-]$, real, imag.\n\nWhen \\config{unwrapPhase} is set to true, $2\\pi$ jumps of the phase response are removed before writing the output to file.\n\nThe response of the filter cascade is given by the product of each individual frequency response:\n\\begin{equation}\n  H(f) = \\prod_f H_j(f).\n\\end{equation}\nAmplitude and phase response are computed from the frequency response via\n\\begin{equation}\n  A(f) = |H(f)| \\hspace{5pt}\\text{and}\\hspace{5pt} \\Phi(f) = \\arctan \\frac{\\mathcal{I}(H(f))}{\\mathcal{R}(H(f))}.\n\\end{equation}\nThe group delay is computed by numerically differentiating the phase response\n\\begin{equation}\n  \\tau_g(f_k) = \\frac{1}{2} \\left[\\frac{\\Phi(f_k) - \\Phi(f_{k-1})}{2\\pi(f_k-f_{k-1})} + \\frac{\\Phi(f_{k+1}) - \\Phi(f_{k})}{2\\pi(f_{k+1}-f_{k})}\\right] \\approx \\frac{d\\Phi}{df}\\frac{df}{d\\omega}.\n\\end{equation}\nThe frequency vector for a \\config{length} $N$ and a \\config{sampling} $\\Delta t$ is given by\n\\begin{equation}\n  f_k = \\frac{k}{N \\Delta t}, \\hspace{15pt} k \\in \\{0, \\dots, \\left\\lfloor\\frac{N+2}{2}\\right\\rfloor-1\\}.\n\\end{equation}\n\nSee also \\program{DigitalFilter2ImpulseResponse}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/fourier.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Amplitude and phase response of a filter cascade.\n* @ingroup programsGroup */\nclass DigitalFilter2FrequencyResponse\n{\nprivate:\n  Vector groupDelay(const Vector &f, const Vector &phase);\n  Vector unwrap(const Vector &phase);\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DigitalFilter2FrequencyResponse, SINGLEPROCESS, \"amplitude and phase response of a filter cascade\", Misc)\n\n/***********************************************/\n\nvoid DigitalFilter2FrequencyResponse::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         fileNameOut;\n    UInt             length;\n    Double           sampling;\n    DigitalFilterPtr filter;\n    Bool             skipZero = FALSE;\n    Bool             unwrapPhase = FALSE;\n\n    readConfig(config, \"outputfileResponse\", fileNameOut, Config::MUSTSET,  \"\",    \"columns: freq [Hz], ampl, phase [rad], group delay [-], real, imag\");\n    readConfig(config, \"digitalFilter\",      filter,      Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"length\",             length,      Config::DEFAULT,  \"512\", \"length of the data series in time domain\");\n    readConfig(config, \"sampling\",           sampling,    Config::DEFAULT,  \"1.0\", \"sampling to determine frequency [seconds]\");\n    readConfig(config, \"skipZeroFrequency\",  skipZero,    Config::DEFAULT,  \"0\",   \"omit zero frequency when writing to file\");\n    readConfig(config, \"unwrapPhase\",        unwrapPhase, Config::DEFAULT,  \"0\",   \"unwrap phase response\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"compute frequency response\"<<Log::endl;\n    Matrix A((length+2)/2, 6);\n    copy(Fourier::frequencies(length, sampling), A.column(0));\n\n    auto F = filter->frequencyResponse(length);\n    Vector amplitude, phase;\n    Fourier::complex2AmplitudePhase(F, amplitude, phase);\n    Vector unwrappedPhase = unwrap(phase);\n    Vector grpDel = groupDelay(A.column(0), unwrappedPhase);\n    if(unwrapPhase)\n      phase = unwrappedPhase;\n\n    copy(amplitude,  A.column(1));\n    copy(phase,      A.column(2));\n    copy(grpDel,     A.column(3));\n    for(UInt i=0; i<A.rows(); i++)\n    {\n      A(i, 4) = F.at(i).real();\n      A(i, 5) = F.at(i).imag();\n    }\n\n    logStatus<<\"write response to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector DigitalFilter2FrequencyResponse::unwrap(const Vector &phase)\n{\n  Vector uPhase = phase;\n\n  for(UInt n = 1; n<uPhase.rows(); n++)\n  {\n    while( (uPhase(n) - uPhase(n-1)) <= PI)\n      uPhase(n) += 2*PI;\n\n    while( (uPhase(n) - uPhase(n-1)) >= PI)\n      uPhase(n) -= 2*PI;\n  }\n\n  return uPhase;\n}\n\n/***********************************************/\n\nVector DigitalFilter2FrequencyResponse::groupDelay(const Vector &f, const Vector &uPhase)\n{\n  Vector grpDel(uPhase.rows());\n\n  grpDel(0) = -(uPhase(1)-uPhase(0))/(f(1)-f(0));\n  for(UInt n = 1; n<uPhase.rows()-1; n++)\n    grpDel(n) = -( (uPhase(n)-uPhase(n-1))/(f(n)-f(n-1)) + (uPhase(n+1)-uPhase(n))/(f(n+1)-f(n)))*0.5;\n  grpDel(grpDel.rows()-1) = -(uPhase(grpDel.rows()-1)-uPhase(grpDel.rows()-2))/(f(grpDel.rows()-1)-f(grpDel.rows()-2));\n\n  return grpDel/(2*PI);\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/digitalFilter2ImpulseResponse.cpp",
    "content": "/***********************************************/\n/**\n* @file digitalFilter2ImpulseResponse.cpp\n*\n* @brief Impulse response of a filter cascade.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-02\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nImpulse response of a \\configClass{digitalFilter}{digitalFilterType} cascade.\nThe impulse response is computed by filtering a sequence with \\config{length} samples and a unit impulse at index \\config{pulseLag}.\n\nThe \\configFile{outputfileResponse}{matrix} is a matrix with the time stamp (zero at \\config{pulseLag})\nin the first column and the impulse response $h_k$ in the second column.\n\nSee also \\program{DigitalFilter2FrequencyResponse}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/digitalFilter/digitalFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Impulse response of a filter cascade.\n* @ingroup programsGroup */\nclass DigitalFilter2ImpulseResponse\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(DigitalFilter2ImpulseResponse, SINGLEPROCESS, \"impulse response of a filter cascade\", Misc)\n\n/***********************************************/\n\nvoid DigitalFilter2ImpulseResponse::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName         fileNameOut;\n    DigitalFilterPtr filter;\n    UInt             length, lag;\n    Double           sampling;\n\n    readConfig(config, \"outputfileResponse\", fileNameOut, Config::MUSTSET,  \"\",    \"columns: time [seconds], response\");\n    readConfig(config, \"digitalFilter\",      filter,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"length\",             length,      Config::DEFAULT,  \"201\", \"length of the impulse response\");\n    readConfig(config, \"pulseLag\",           lag,         Config::DEFAULT,  \"100\", \"start of the pulse in the data series\");\n    readConfig(config, \"sampling\",           sampling,    Config::DEFAULT,  \"1.0\", \"[seconds]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"compute impulse response\"<<Log::endl;\n    Matrix A(length, 2);\n    for(UInt i=0; i<length; i++)\n      A(i,0) = sampling*i-sampling*lag;\n    A(lag,1) = 1.;\n    copy(filter->filter(A.column(1)), A.column(1));\n\n    logStatus<<\"write response to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/earthOrientationParameterTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file earthOrientationParameterTimeSeries.cpp\n*\n* @brief Time series of EOP.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-05-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes a \\configClass{timeSeries}{timeSeriesType} (GPS time) of Earth Orientation Parameter (EOP).\nThe \\file{instrument file}{instrument} (MISCVALUES) contains the elements at each epoch in the following order:\n\\begin{itemize}\n\\item $x_p$ [rad]\n\\item $y_p$ [rad]\n\\item $s_p$ [rad]\n\\item $UT1-UTC$ [seconds]\n\\item length of day (LOD) [seconds]\n\\item $X$ [rad]\n\\item $Y$ [rad]\n\\item $S$ [rad]\n\\end{itemize}\nThe values are in situ values with all corrections and models applied. The time series can be used to\nprecompute Earth rotation with a low temporal resolution (e.g. 10 min) and reuse the file in\n\\configClass{earthRotation:file}{earthRotationType:file} to interpolate the data to the needed epochs\n(e.g. to rotate orbit data). As some Earth rotation models are quite slow this can accelerate the computation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of EOP.\n* @ingroup programsGroup */\nclass EarthOrientationParameterTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(EarthOrientationParameterTimeSeries, PARALLEL, \"Time series of EOP\", Misc, TimeSeries)\n\n/***********************************************/\n\nvoid EarthOrientationParameterTimeSeries::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameEOP;\n    EarthRotationPtr earthRotation;\n    TimeSeriesPtr    timeSeries;\n\n    readConfig(config, \"outputfileEOP\", fileNameEOP,   Config::MUSTSET,  \"\", \"each row: mjd(GPS), xp, yp, sp, dUT1, LOD, X, Y, S\");\n    readConfig(config, \"earthRotation\", earthRotation, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",    timeSeries,    Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"Computing Earth rotation\"<<Log::endl;\n    std::vector<Time> times = timeSeries->times();\n    Matrix A(times.size(), 9);\n    Parallel::forEach(times.size(), [&](UInt i) {earthRotation->earthOrientationParameter(times.at(i), A(i,1), A(i,2), A(i,3), A(i,4), A(i,5), A(i,6), A(i,7), A(i,8));}, comm);\n    Parallel::reduceSum(A, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"writing EOP to file <\"<<fileNameEOP<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameEOP, Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/earthRotaryVectorTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file earthRotaryVectorTimeSeries.cpp\n*\n* @brief Time series of Earth's rotary axis.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-06-08\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes a \\configFile{outputfileTimeSeries}{instrument} of Earth's rotary axis\nand its temporal derivative at \\configClass{timeSeries}{timeSeriesType} (GPS time).\nThe \\file{instrument file}{instrument} (MISCVALUES) contains the elements at each epoch in the following order:\n\\begin{itemize}\n\\item $\\omega_x [rad/s]$\n\\item $\\omega_y [rad/s]$\n\\item $\\omega_z [rad/s]$\n\\item $\\dot{\\omega}_x [rad/s^2]$\n\\item $\\dot{\\omega}_y [rad/s^2]$\n\\item $\\dot{\\omega}_z [rad/s^2]$.\n\\end{itemize}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Time series of Earth's rotary axis.\n* @ingroup programsGroup */\nclass EarthRotaryVectorTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(EarthRotaryVectorTimeSeries, PARALLEL, \"Time series of Earth's rotary axis\", Misc, TimeSeries)\n\n/***********************************************/\n\nvoid EarthRotaryVectorTimeSeries::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameOut;\n    EarthRotationPtr earthRotation;\n    TimeSeriesPtr    timeSeries;\n    Bool             inTRF = FALSE;\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameOut,   Config::MUSTSET,  \"\", \"wx, wy, wz [rad], dwx, dwy, dwz [rad/s^2]\");\n    readConfig(config, \"earthRotation\",        earthRotation, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",           timeSeries,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inTRF\",                inTRF,         Config::DEFAULT,  \"0\", \"terrestrial reference frame, otherwise celestial\");\n    if(isCreateSchema(config)) return;\n\n\n    logStatus<<\"Computing Earth rotation\"<<Log::endl;\n    std::vector<Time> times = timeSeries->times();\n    Matrix A(times.size(), 7);\n    Parallel::forEach(times.size(), [&](UInt i)\n    {\n      Rotary3d rotEarth;\n      if(inTRF)\n        rotEarth = earthRotation->rotaryMatrix(times.at(i));\n      const Vector3d axis    = rotEarth.rotate(earthRotation->rotaryAxis(times.at(i)));\n      const Vector3d axisDot = rotEarth.rotate(earthRotation->rotaryAxisDerivate(times.at(i)));\n      A(i,1) = axis.x();\n      A(i,2) = axis.y();\n      A(i,3) = axis.z();\n      A(i,4) = axisDot.x();\n      A(i,5) = axisDot.y();\n      A(i,6) = axisDot.z();\n    }, comm);\n    Parallel::reduceSum(A, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"writing time series to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, Arc(times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/eclipseFactor2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file eclipseFactor2GriddedData.cpp\n*\n* @brief Eclipse factor on a grid.\n*\n* @author Andreas Strasser\n* @date 2023-10-13\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the output of a \\configClass{eclipse}{eclipseType} model on a given\n\\configClass{grid}{gridType}. The time for the evaluation can be specified in \\config{time}.\nThe values will be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R}\nand \\config{inverseFlattening}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/eclipse/eclipse.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"misc/miscGriddedData.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Eclipse factor on a grid.\n* @ingroup programsGroup */\nclass EclipseFactor2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(EclipseFactor2GriddedData, PARALLEL, \"eclipse factor on a grid.\", Misc, Grid)\n\n/***********************************************/\n\nvoid EclipseFactor2GriddedData::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameGrid;\n    GridPtr          grid;\n    EclipsePtr       eclipse;\n    EphemeridesPtr   ephemerides;\n    EarthRotationPtr earthRotation;\n    Time             time;\n    Double           a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,  Config::MUSTSET,  \"\",  \"eclipse factor\");\n    readConfig(config, \"grid\",                  grid,          Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"eclipse\",               eclipse,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"ephemerides\",           ephemerides,   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"earthRotation\",         earthRotation, Config::OPTIONAL, \"file\", \"\");\n    readConfig(config, \"time\",                  time,          Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"R\",                     a,             Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,             Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // compute\n    // -------\n    logStatus<<\"computing eclipse factor\"<<Log::endl;\n    Rotary3d rotation;\n    if(earthRotation)\n      rotation = earthRotation->rotaryMatrix(time);\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   values(points.size());\n\n    Parallel::forEach(values, [&](UInt i)\n    {\n      return eclipse->factor(time, rotation.inverseRotate(points.at(i)), ephemerides);\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(Ellipsoid(a, f), points, grid->areas(), {values});\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/filterMatrixWindowedPotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file filterMatrixWindowedPotentialCoefficients.cpp\n*\n* @brief Create a spherical harmonic window matrix.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2020-07-21\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate a spherical harmonic window matrix. The window matrix $\\mathbf{W}$ is generated in space domain through\nspherical harmonic synthesis and analysis matrices.\nThe resulting linear operator can be written as\n\\begin{equation}\n\\mathbf{W} = \\mathbf{K} \\mathbf{A} \\mathbf{\\Omega} \\mathbf{S} \\mathbf{K}^{-1}.\n\\end{equation}\nHere, $\\mathbf{K}$ is a diagonal matrix with the \\configClass{kernel}{kernelType} coefficients on the main diagonal,\n$\\mathbf{S}$ is the spherical harmonic synthesis matrix, $\\mathbf{\\Omega}$ is defined by the values in\n\\file{inputfileGriddedData}{griddedData} and the\nexpression \\config{value}, $\\mathbf{A}$ is the spherical harmonic analysis matrix.\nThe resulting window matrix is written to a \\file{matrix}{matrix} file.\n\nThe spherical harmonic degree range, and coefficient numbering are defined by\n\\config{minDegree}, \\config{maxDegree}, and \\configClass{numbering}{sphericalHarmonicsNumberingType}.\n\nNote that a proper window function $\\mathbf{\\Omega}$ should contain values in the range [0, 1].\nThe window function $\\mathbf{\\Omega}$ can feature a smooth transition between 0 and 1 to avoid ringing effects.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create a spherical harmonic window matrix.\n* @ingroup programsGroup */\nclass FilterMatrixWindowedPotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FilterMatrixWindowedPotentialCoefficients, PARALLEL, \"create a spherical harmonic window matrix.\", Misc, PotentialCoefficients, Matrix)\n\n/***********************************************/\n\nvoid FilterMatrixWindowedPotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName  fileNameOut, fileNameIn;\n    KernelPtr kernel;\n    UInt      minDegree, maxDegree;\n    Double    GM, R;\n    SphericalHarmonicsNumberingPtr numbering;\n    ExpressionVariablePtr exprValue;\n\n    readConfig(config, \"outputfileWindowMatrix\", fileNameOut, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"inputfileGriddedData\",   fileNameIn,  Config::MUSTSET,  \"\",  \"gridded data which defines the window function in space domain\");\n    readConfig(config, \"value\",                  exprValue,   Config::MUSTSET,  \"data0\", \"expression to compute the window function (input columns are named data0, data1, ...)\");\n    readConfig(config, \"kernel\",                 kernel,      Config::MUSTSET,  \"\",  \"kernel for windowing\");\n    readConfig(config, \"minDegree\",              minDegree,   Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",              maxDegree,   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"GM\",                     GM,          Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                      R,           Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",              numbering,   Config::MUSTSET,  \"\",  \"numbering scheme for solution vector\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<UInt> n, m, cs;\n    numbering->numbering(maxDegree, minDegree, n, m, cs);\n    const UInt coefficientsCount = numbering->parameterCount(maxDegree, minDegree);\n\n    GriddedData grid;\n    readFileGriddedData(fileNameIn, grid);\n    const std::vector<Vector3d> points = grid.points;\n    const std::vector<Double>   areas  = grid.areas;\n\n    // evaluate expression\n    // -------------------\n    VariableList varList;\n    addDataVariables(grid, varList);\n    exprValue->simplify(varList);\n\n    Vector windowFunction(points.size());\n    for(UInt i=0; i<points.size(); i++)\n    {\n      evaluateDataVariables(grid, i, varList);\n      windowFunction(i) = exprValue->evaluate(varList);\n    }\n\n    logStatus<<\"create window matrix\"<<Log::endl;\n    Matrix A(coefficientsCount, coefficientsCount);\n    const UInt blockSize = 256; // compute block of points to speed up computation\n    Parallel::forEach((points.size()+blockSize-1)/blockSize, [&](UInt idx)\n    {\n      const UInt pointCount = std::min(points.size(), (idx+1)*blockSize) - idx*blockSize;\n      Matrix A1(pointCount, coefficientsCount);\n      Matrix A2(pointCount, coefficientsCount);\n\n      for(UInt i=0; i<pointCount; i++)\n      {\n        const UInt   idPoint = idx*blockSize + i;\n        const Double r       = points.at(idPoint).r();\n\n        Matrix Cnm, Snm;\n        SphericalHarmonics::CnmSnm(normalize(points.at(idPoint)), maxDegree, Cnm, Snm);\n\n        Vector k1 = std::sqrt(areas.at(idPoint)/(4*PI)) * kernel->inverseCoefficients(points.at(idPoint), maxDegree);\n        Vector k2 = std::sqrt(areas.at(idPoint)/(4*PI)) * kernel->coefficients(points.at(idPoint), maxDegree);\n        for(UInt n=0; n<=maxDegree; n++)\n        {\n          k1(n) *= std::pow(R/r, n+1);\n          k2(n) *= std::pow(r/R, n+1);\n        }\n\n        for(UInt k=0; k<A.columns(); k++)\n        {\n          A1(i, k) = k1(n[k]) * (cs[k] ? Cnm(n[k], m[k]) : Snm(n[k], m[k])) * windowFunction(idPoint);\n          A2(i, k) = k2(n[k]) * (cs[k] ? Cnm(n[k], m[k]) : Snm(n[k], m[k]));\n        }\n      }\n\n      matMult(1., A2.trans(), A1, A);\n    }, comm);\n    Parallel::reduceSum(A, 0, comm);\n\n    // write\n    // -----\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"writing window matrix to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOut, A);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/functionsCalculate.cpp",
    "content": "/***********************************************/\n/**\n* @file functionsCalculate.cpp\n*\n* @brief Functions Calculate.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-09-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program manipulates \\file{matrix files}{matrix} with data in columns.\nIf several \\config{inputfile}s are given the data columns are copied side by side.\nAll \\config{inputfile}s must contain the same number of rows.\nThe columns are enumerated by \\verb|data0|,~\\verb|data1|,~\\ldots.\n\nThe content of \\configFile{outputfile}{matrix} is controlled by \\config{outColumn}.\nThe algorithm to compute the output is as follows:\nThe expressions in \\config{outColumn} are evaluated once for each row of the input.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nAdditional variables are available, e.g. \\verb|index|, \\verb|data0rms|, see~\\reference{dataVariables}{general.parser:dataVariables}.\nIf no \\config{outColumn} are specified all input columns are used instead directly.\n\nFor a simplified handling \\config{constant}s can be defined by \\verb|name=value|, e.g. \\verb|annual=365.25|.\nIt is also possible to estimate \\config{parameter}s in a least squares adjustment.\nThe \\config{leastSquares} serves as template for observation equations for every row.\nThe expression \\config{leastSquares} is evaluated for each row in the \\config{inputfile}.\nThe variables \\verb|data0|,~\\verb|data1|,~\\ldots are replaced by the according values from the input columns before.\nIn the next step the parameters are estimated in order to minimize the expressions in \\config{leastSquares}\nin the sense of least squares.\n\nAfterwards complete rows are removed if one of the \\config{removalCriteria} expressions for this row evaluates true (not zero).\n\nAn extra \\config{statistics} file can be generated with one row of data. For the computation of the \\config{outColumn} values\nall~\\reference{dataVariables}{general.parser:dataVariables} are available (e.g. \\verb|data3mean|, \\verb|data4std|)\ninclusively the \\config{constant}s and estimated \\config{parameter}s but without the \\verb|data0|,~\\verb|data1|,~\\ldots itself.\nThe variables and the numbering of the columns refers to the \\configFile{outputfile}{matrix}.\n\nFirst example: To calculate the mean of two values at each row set \\config{outColumn} to \\verb|0.5*(data1+data0)|.\n\nSecond example: An input file contain a column with times and a column with values.\nTo remove a trend from the values define the \\config{parameter}s \\verb|trend| and \\verb|bias|.\nThe observation equation in \\config{leastSquares} is \\verb|data1 - (trend*data0+bias)|.\nFor output you can define the following columns for example:\n\\begin{itemize}\n\\item \\config{outColumn}=\\verb|data0|: points in time.\n\\item \\config{outColumn}=\\verb|data1|: the values itself.\n\\item \\config{outColumn}=\\verb|trend*data0+bias|: the linear fit.\n\\item \\config{outColumn}=\\verb|data1-trend*data0-bias|: the residuals.\n\\end{itemize}\nThe extra statistics file could contain in this case:\n\\begin{itemize}\n\\item \\config{outColumn}=\\verb|data0max-data0min|: time span.\n\\item \\config{outColumn}=\\verb|bias|: estimated parameter.\n\\item \\config{outColumn}=\\verb|trend|: estimated parameter.\n\\item \\config{outColumn}=\\verb|data3rms|: root mean square of the residuals.\n\\end{itemize}\n\nSee also \\program{InstrumentArcCalculate}, \\program{GriddedDataCalculate}, \\program{MatrixCalculate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n\n/***********************************************/\n\n/** @brief Functions Calculate.\n* @ingroup programsGroup */\nclass FunctionsCalculate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FunctionsCalculate, SINGLEPROCESS, \"Functions Calulate\", Misc, Matrix, TimeSeries)\n\n/***********************************************/\n\nvoid FunctionsCalculate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                           fileNameOut, fileNameStatistics;\n    std::vector<FileName>              fileNamesIn;\n    std::vector<ExpressionVariablePtr> constExpr, paramExpr;\n    std::vector<ExpressionVariablePtr> lsaExpr, removeExpr;\n    std::vector<ExpressionVariablePtr> outExpr, statisticsExpr;\n\n    readConfig(config, \"outputfile\",      fileNameOut, Config::OPTIONAL, \"\",      \"\");\n    readConfig(config, \"inputfile\",       fileNamesIn, Config::MUSTSET,  \"\",      \"\");\n    readConfig(config, \"constant\",        constExpr,   Config::OPTIONAL, \"\",      \"define a constant by name=value\");\n    readConfig(config, \"parameter\",       paramExpr,   Config::OPTIONAL, \"\",      \"define a parameter by name[=value]\");\n    readConfig(config, \"leastSquares\",    lsaExpr,     Config::OPTIONAL, \"\",      \"try to minimize the expression by adjustment of the parameters\");\n    readConfig(config, \"removalCriteria\", removeExpr,  Config::OPTIONAL, \"\",      \"row is removed if one criterion evaluates true.\");\n    readConfig(config, \"outColumn\",       outExpr,     Config::OPTIONAL, R\"([\"data0\"])\", \"expression to compute output columns (input columns are named data0, data1, ...)\");\n    if(readConfigSequence(config, \"statistics\", Config::OPTIONAL, \"\", \"\"))\n    {\n      readConfig(config, \"outputfile\", fileNameStatistics, Config::MUSTSET, \"\",         \"matrix with one row, columns are user defined\");\n      readConfig(config, \"outColumn\",  statisticsExpr,     Config::MUSTSET, \"data0rms\", \"expression to compute statistics columns, data* are the outputColumns\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // read data\n    // ---------\n    Matrix data;\n    {\n      std::vector<Matrix> data2(fileNamesIn.size());\n      for(UInt i=0; i<fileNamesIn.size(); i++)\n      {\n        logStatus<<\"read input from <\"<<fileNamesIn.at(i)<<\">\"<<Log::endl;\n        readFileMatrix(fileNamesIn.at(i), data2.at(i));\n      }\n      // test data\n      for(UInt i=1; i<data2.size(); i++)\n        if(data2.at(i).rows() != data2.at(0).rows())\n          throw(Exception(\"all input data must have the same count of rows\"));\n      UInt cols = 0;\n      for(UInt i=0; i<data2.size(); i++)\n        cols += data2.at(i).columns();\n      data = Matrix(data2.at(0).rows(), cols);\n      UInt idx = 0;\n      for(UInt i=0; i<data2.size(); i++)\n      {\n        copy(data2.at(i), data.column(idx,data2.at(i).columns()));\n        idx += data2.at(i).columns();\n      }\n    }\n\n    // create data variables\n    // ---------------------\n    // get real variable names, otherwise all named after config element\n    std::for_each(constExpr.begin(), constExpr.end(), [&](auto expr) {expr->parseVariableName();});\n    std::for_each(paramExpr.begin(), paramExpr.end(), [&](auto expr) {expr->parseVariableName();});\n\n    VariableList varList;\n    std::for_each(constExpr.begin(), constExpr.end(), [&](auto expr) {varList.addVariable(expr);});\n    std::for_each(paramExpr.begin(), paramExpr.end(), [&](auto expr) {varList.addVariable(expr);});\n    auto varListWoData = varList;\n    addDataVariables(data, varList);\n\n    // build observation equations\n    // ---------------------------\n    if(lsaExpr.size())\n    {\n      logStatus<<\"least squares adjustment\"<<Log::endl;\n      Vector l(data.rows()*lsaExpr.size());\n      Matrix A(data.rows()*lsaExpr.size(), paramExpr.size());\n\n      for(UInt k=0; k<lsaExpr.size(); k++)\n      {\n        std::vector<ExpressionVariablePtr> lsaA(paramExpr.size());\n        for(UInt s=0; s<paramExpr.size(); s++)\n        {\n          lsaA.at(s) = lsaExpr.at(k)->derivative(paramExpr.at(s)->name(), varList);\n          lsaA.at(s)->simplify(varList);\n        }\n        lsaExpr.at(k)->simplify(varList);\n\n        for(UInt i=0; i<data.rows(); i++)\n        {\n          evaluateDataVariables(data, i, varList);\n          l(i+k*data.rows()) = -lsaExpr.at(k)->evaluate(varList);  // observations\n          for(UInt s=0; s<lsaA.size(); s++)\n            A(i+k*data.rows(), s) = lsaA.at(s)->evaluate(varList);  // columns of design matrix\n        }\n        undefineDataVariables(data, varList);\n      }\n\n      Vector x = leastSquares(A,l);\n      for(UInt s=0; s<paramExpr.size(); s++)\n      {\n        x(s) += paramExpr.at(s)->evaluate(varList);\n        paramExpr.at(s)->setValue( x(s) );\n        varList.setVariable(paramExpr.at(s)->name(),  x(s) );\n        varListWoData.setVariable(paramExpr.at(s)->name(),  x(s) );\n        logInfo<<\"  \"<<paramExpr.at(s)->name()<<\" = \"<<x(s)<<Log::endl;\n      }\n    }\n\n    // calculate output matrix\n    // -----------------------\n    logStatus<<\"calculate output matrix\"<<Log::endl;\n    std::for_each(outExpr.begin(),    outExpr.end(),    [&](auto expr) {expr->simplify(varList);});\n    std::for_each(removeExpr.begin(), removeExpr.end(), [&](auto expr) {expr->simplify(varList);});\n    Matrix outData(data.rows(), outExpr.size() ? outExpr.size() : data.columns());\n    UInt row = 0;\n    for(UInt i=0; i<outData.rows(); i++)\n    {\n      evaluateDataVariables(data, i, varList);\n      if(!std::any_of(removeExpr.begin(), removeExpr.end(), [&](auto expr) {return expr->evaluate(varList) != 0;}))\n      {\n        for(UInt k=0; k<outData.columns(); k++)\n          outData(row, k) = outExpr.size() ? outExpr.at(k)->evaluate(varList) : data(i, k);\n        row++;\n      }\n    }\n    if(row < outData.rows())\n    {\n      logInfo<<\"  \"<<outData.rows()-row<<\" rows removed\"<<Log::endl;\n      outData = outData.row(0, row);\n    }\n\n    // write output\n    // ------------\n    if(!fileNameOut.empty())\n    {\n      logStatus<<\"write output to <\"<<fileNameOut<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOut, outData);\n    }\n\n    // statistics\n    // ----------\n    if(!fileNameStatistics.empty())\n    {\n      logStatus<<\"write statistics to <\"<<fileNameStatistics<<\">\"<<Log::endl;\n      auto varList = varListWoData;\n      addDataVariables(outData, varList);\n      Matrix statistics(1, statisticsExpr.size());\n      for(UInt k=0; k<statistics.columns(); k++)\n        statistics(0, k) = statisticsExpr.at(k)->evaluate(varList);\n      writeFileMatrix(fileNameStatistics, statistics);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/grs2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file grs2PotentialCoefficients.cpp\n*\n* @brief Spherical harmonics from Geodetic Reference System (GRS).\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2004-12-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program creates potential coefficients from the defining constants\nof a Geodetic Reference System (GRS). The potential coeffiencts excludes the centrifugal part.\nThe form of the reference ellipsoid is either determined by the dynamical form factor \\config{J2},\nor the geometric \\config{inverseFlattening}. One of those form parameters must be specified.\n\nThe default values create the GRS80.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileSphericalHarmonics.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Spherical harmonics from Geodetic Reference System (GRS).\n* @ingroup programsGroup */\nclass Grs2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Grs2PotentialCoefficients, SINGLEPROCESS, \"spherical harmonics from Geodetic Reference System (GRS)\", Misc, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Grs2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName outName;\n    Double   GM, R, omega;\n    Double J2 = NAN_EXPR;\n    Double inverseFlattening = NAN_EXPR;\n    UInt     degree;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", outName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"maxDegree\", degree, Config::MUSTSET, \"10\",           \"\");\n    readConfig(config, \"GM\",        GM,     Config::DEFAULT, \"3.986005e+14\", \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",         R,      Config::DEFAULT, STRING_DEFAULT_GRS80_a,  \"reference radius\");\n    readConfig(config, \"omega\",     omega,  Config::DEFAULT, \"7292115e-11\",  \"Angular velocity of rotation\");\n    readConfig(config, \"J2\",        J2,     Config::OPTIONAL, \"108263e-8\",    \"Dynamical form factor\");\n    readConfig(config, \"inverseFlattening\", inverseFlattening, Config::OPTIONAL, \"\",    \"Geometric inverse flattening of reference ellipsoid (0: sphere, ignored when J2 is set)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"create spherical harmonics\"<<Log::endl;\n    Matrix cnm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm(degree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    Double e;\n    if(!std::isnan(J2))\n    {\n      Double e_sec, q0;\n      Double e_old = 1.0;\n      e     = 0.5;\n\n      do\n      {\n        e_sec = e * sqrt(1-e*e)/(1-e*e);\n        q0    = (1.0 + (3.0/(e_sec*e_sec)))*atan(e_sec)-(3.0/e_sec);\n        e_old = e;\n        e     = sqrt(3.0*J2 + (4.0*omega*omega*R*R*R * e*e*e) / (15.0*GM*q0));\n      }\n      while( fabs(e-e_old) > 1.0e-13);\n    }\n    else if(!std::isnan(inverseFlattening))\n    {\n      Double e2 = inverseFlattening == 0.0 ? 0.0 : (2 - 1/inverseFlattening) / inverseFlattening;\n      e = std::sqrt(e2);\n      Double eprime = e / std::sqrt(1 - e*e);\n\n      Double q0 = 0.0;\n      for(UInt n = 1; n < 21; n++)\n         q0 += -2 * std::pow(-1, n) * n * std::pow(eprime, 2 * n + 1) / ((2. * n + 1) * (2. * n + 3));\n      J2 = (e2 - 4.0 / 15 * (omega*omega * R*R*R) / GM * std::pow(e, 3) / (2 * q0)) / 3;\n    }\n    else\n      throw(Exception(\"either inverseFlattening or J2 must be set\"));\n\n    cnm(0,0) = 1.0;\n    for(UInt n=2; n<=degree; n+=2)\n    {\n      UInt m = n/2;\n      Double factor = (e == 0.0) ? 1 : (1.-m+5.*m*(J2/(e*e)));\n      Double Jn = pow(-1.,m+1)*((3*pow(e*e,m))/((2.*m+1.)*(2.*m+3.))) * factor;\n      cnm(n,0) = -Jn/sqrt(2.*n+1.);\n    }\n\n    logStatus<<\"writing potential coefficients to file <\"<<outName<<\">\"<<Log::endl;\n    writeFileSphericalHarmonics(outName, SphericalHarmonics(GM, R, cnm, snm));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/kaula2SigmaPotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file kaula2SigmaPotentialCoefficients.cpp\n*\n* @brief Create variances according kaulas rule of thumb.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate signal standard deviations of potential coefficients according Kaula's rule of thumb\n\\begin{equation}\n  \\sigma_n = \\frac{f}{n^p},\n\\end{equation}\nwith the degree $n$, the \\config{factor} $f$, and the \\config{power} $p$.\n\nThe standard deviations are written as formal errors of\n \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileSphericalHarmonics.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create variances according kaulas rule of thumb.\n* The coefficients are writen as SphericalHarmonics.\n* @ingroup programsGroup */\nclass Kaula2SigmaPotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Kaula2SigmaPotentialCoefficients, SINGLEPROCESS, \"Create variances according kaulas rule of thumb\", Misc, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Kaula2SigmaPotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName potentialCoefficientsName;\n    UInt     minDegree, maxDegree;\n    Double   GM, R;\n    Double   power, factor;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", potentialCoefficientsName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"minDegree\", minDegree, Config::DEFAULT,  \"2\", \"\");\n    readConfig(config, \"maxDegree\", maxDegree, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"GM\",        GM,        Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",         R,         Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"power\",     power,     Config::DEFAULT,  \"2\",    \"sigma = factor/degree^power\");\n    readConfig(config, \"factor\",    factor,    Config::DEFAULT,  \"1e-5\", \"sigma = factor/degree^power\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"create potential coefficients\"<<Log::endl;\n    Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      const Double v = factor/std::pow(n, power);\n      sigma2cnm(n,0) = v*v;\n      for(UInt m=1; m<=n; m++)\n        sigma2cnm(n,m) = sigma2snm(n,m) = v*v;\n    }\n\n    logStatus<<\"writing potential coefficients to file <\"<<potentialCoefficientsName<<\">\"<<Log::endl;\n    writeFileSphericalHarmonics(potentialCoefficientsName, SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/kernel2Coefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file kernel2Coefficients.cpp\n*\n* @brief Compute kernel coefficients.\n*\n* @author Andreas Kvas\n* @date 2019-03-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes and returns the coefficients and inverse coefficients of a \\configClass{kernel}{kernelType}\nfrom from \\config{minDegree} to \\config{maxDegree} at a given \\config{height}.\n\nThe main purpose is for visualization with \\program{PlotGraph}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief  Compute kernel coefficients.\n* @ingroup programsGroup */\nclass Kernel2Coefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Kernel2Coefficients, SINGLEPROCESS, \"compute kernel coefficients\", Misc)\nGROOPS_RENAMED_PROGRAM(KernelComputeCoefficients, Kernel2Coefficients, date2time(2020, 9, 1))\n\n/***********************************************/\n\nvoid Kernel2Coefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName  fileNameOut;\n    KernelPtr kernel;\n    Double    R, H;\n    UInt      minDegree, maxDegree;\n\n    readConfig(config, \"outputfileMatrix\", fileNameOut,  Config::MUSTSET, \"\",  \"matrix with columns degree, coefficients and inverse coefficients\");\n    readConfig(config, \"kernel\",           kernel,       Config::MUSTSET, \"\",  \"\");\n    readConfig(config, \"minDegree\",        minDegree,    Config::DEFAULT, \"0\", \"minimum degree of returned coefficients\");\n    readConfig(config, \"maxDegre\",         maxDegree,    Config::MUSTSET, \"\",  \"compute coefficients up to maxDegree\");\n    readConfig(config, \"height\",           H,            Config::DEFAULT, \"0\", \"evaluate kernel at R+height [m]\");\n    readConfig(config, \"R\",                R,            Config::DEFAULT, STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    Vector kn  = kernel->coefficients(Vector3d(0, 0, R), maxDegree);\n    Vector kn2 = kernel->inverseCoefficients(Vector3d(0, 0, R), maxDegree);\n\n    Matrix coeffs(maxDegree+1-minDegree, 3);\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      coeffs(n-minDegree, 0) = n;\n      coeffs(n-minDegree, 1) = kn(n) * std::pow((R+H)/R, n+1);\n      coeffs(n-minDegree, 2) = kn2(n) * std::pow(R/(R+H), n+1);\n    }\n\n    logStatus<<\"write kernel coefficients to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, coeffs);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/kernel2SigmaPotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file kernel2SigmaPotentialCoefficients.cpp\n*\n* @brief Create variances of spherical harmonics by convolution a kernel with white noise.\n* The coefficients are writen as SphericalHarmonics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate variances of spherical harmonics by convolution a kernel with white noise,\ne.g. to display filter coefficients of a Gaussian filter.\nThe coefficients are written as formal errors of \\configFile{outputfilePotentialCoefficients}{potentialCoefficients}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create variances of spherical harmonics by convolution a kernel with white noise.\n* The coefficients are writen as SphericalHarmonics.\n* @ingroup programsGroup */\nclass Kernel2SigmaPotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Kernel2SigmaPotentialCoefficients, SINGLEPROCESS, \"create variances of spherical harmonics by convolution a kernel with white noise\", Misc, PotentialCoefficients)\n\n/***********************************************/\n\nvoid Kernel2SigmaPotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName  potentialCoefficientsName;\n    KernelPtr kernel;\n    UInt      minDegree, maxDegree = INFINITYDEGREE;\n    Double    GM, R;\n    Double    factor;\n\n    readConfig(config, \"outputfilePotentialCoefficients\", potentialCoefficientsName, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"kernel\",    kernel,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"minDegree\", minDegree, Config::DEFAULT,  \"2\", \"\");\n    readConfig(config, \"maxDegree\", maxDegree, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",        GM,        Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",         R,         Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"factor\",    factor,    Config::DEFAULT,  \"1\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"create potential coefficients\"<<Log::endl;\n    Matrix cnm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm      (maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2cnm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix sigma2snm(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    const Vector kn = kernel->coefficients(Vector3d(0,0,R), maxDegree);\n    for(UInt n=minDegree; n<=maxDegree; n++)\n    {\n      const Double v = std::pow(factor*R/GM*kn(n), 2)/(2.*n+1.);\n      sigma2cnm(n,0) = v;\n      for(UInt m=1; m<=n; m++)\n        sigma2cnm(n,m) = sigma2snm(n,m) = v;\n    }\n\n    logStatus<<\"writing potential coefficients to file\"<<Log::endl;\n    writeFileSphericalHarmonics(potentialCoefficientsName, SphericalHarmonics(GM, R, cnm, snm, sigma2cnm, sigma2snm));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/kernelEvaluate.cpp",
    "content": "/***********************************************/\n/**\n* @file kernelEvaluate.cpp\n*\n* @brief Compute kernel values for distant angles.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-05-30\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCompute \\configClass{kernel}{kernelType} values for distant angles.\nThe main purpose is for visualization with \\program{PlotGraph}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/kernel/kernel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute kernel values for distant angles.\n* @ingroup programsGroup */\nclass KernelEvaluate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(KernelEvaluate, SINGLEPROCESS, \"Compute kernel values for distant angles\", Misc)\n\n/***********************************************/\n\nvoid KernelEvaluate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName  fileNameOut;\n    KernelPtr kernel;\n    Angle     minv, maxv, sampling;\n    Double    R, H;\n\n    readConfig(config, \"outputfileMatrix\", fileNameOut, Config::MUSTSET,  \"\", \"matrix with first column the angle [degree], second the kernel value\");\n    readConfig(config, \"kernel\",           kernel,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"minAngle\",         minv,        Config::DEFAULT,  \"-180\", \"[degree]\");\n    readConfig(config, \"maxAngle\",         maxv,        Config::DEFAULT,  \"180\",  \"[degree]\");\n    readConfig(config, \"sampling\",         sampling,    Config::DEFAULT,  \"1\",    \"[degree]\");\n    readConfig(config, \"height\",           H,           Config::DEFAULT,  \"0\",    \"evaluate at R+height [m]\");\n    readConfig(config, \"R\",                R,           Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n    const UInt count = static_cast<UInt>((maxv-minv)/sampling+1);\n    Matrix A(count, 2);\n    Single::forEach(count, [&](UInt i)\n    {\n      const Double psi = std::min(Double(maxv), minv + i*Double(sampling));\n      A(i,0) = psi*RAD2DEG;\n      A(i,1) = kernel->kernel(Vector3d((R+H)*sin(psi), 0, (R+H)*cos(psi)), Vector3d(0, 0, R));\n    });\n\n    logStatus<<\"writing output file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/magneticField2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file magneticField2GriddedData.cpp\n*\n* @brief Magentic field vector.\n**\n* @author Torsten Mayer-Guerr\n* @date 2019-05-25\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nComputes x, y, z of the magentic field vector.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Magentic field vector.\n* @ingroup programsGroup */\nclass MagneticField2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(MagneticField2GriddedData, PARALLEL, \"magentic field vector\", Misc, Grid)\n\n/***********************************************/\n\nvoid MagneticField2GriddedData::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameGrid;\n    MagnetospherePtr magnetosphere;\n    GridPtr          grid;\n    Time             time;\n    Bool             useLocalFrame;\n    Double           a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,  Config::MUSTSET,  \"\", \"x, y, z [Tesla = kg/A/s**2]\");\n    readConfig(config, \"magnetosphere\",         magnetosphere, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid\",                  grid,          Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"time\",                  time,          Config::OPTIONAL, STRING_J2000, \"\");\n    readConfig(config, \"localReferenceFrame\",   useLocalFrame, Config::OPTIONAL, \"0\", \"local left handed reference frame (north, east, up)\");\n    readConfig(config, \"R\",                     a,             Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,             Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // compute\n    // -------\n    logStatus<<\"compute magnetic field\"<<Log::endl;\n    Ellipsoid             ellipsoid(a, f);\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    std::vector<Vector3d> values(points.size());\n    Parallel::forEach(values, [&](UInt i) {return magnetosphere->magenticFieldVector(time, points.at(i));}, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      // convert\n      std::vector<std::vector<Double>> field(3, std::vector<Double>(points.size()));\n      for(UInt i=0; i<points.size(); i++)\n      {\n        if(useLocalFrame)\n          values.at(i) = localNorthEastUp(points.at(i), ellipsoid).inverseTransform(values.at(i));\n        field.at(0).at(i) = values.at(i).x();\n        field.at(1).at(i) = values.at(i).y();\n        field.at(2).at(i) = values.at(i).z();\n      }\n\n      // write\n      logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(ellipsoid, points, areas, field);\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/matrixCalculate.cpp",
    "content": "/***********************************************/\n/**\n* @file matrixCalculate.cpp\n*\n* @brief Matrix manipulation.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program creates a \\file{matrix}{matrix} from multiple matrices.\nAll \\configClass{matrices}{matrixGeneratorType} are summed up. The size of the resulting matrix is exandeded to fit all matrices.\nThe class \\configClass{matrixGenerator}{matrixGeneratorType} allows complex matrix operations before.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/matrixGenerator/matrixGenerator.h\"\n\n/***********************************************/\n\n/** @brief Matrix manipulation.\n* @ingroup programsGroup */\nclass MatrixCalculate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(MatrixCalculate, SINGLEPROCESS, \"Matrix manipulation\", Misc, Matrix)\n\n/***********************************************/\n\nvoid MatrixCalculate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName           fileName;\n    MatrixGeneratorPtr matrixGenerator;\n\n    readConfig(config, \"outputfileMatrix\", fileName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"matrix\", matrixGenerator, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"calculate matrix\"<<Log::endl;\n    Matrix A = matrixGenerator->compute();\n    logInfo<<\"  dimension of resulting matrix: \"<<A.rows()<<\" x \"<<A.columns()<<Log::endl;\n\n    logStatus<<\"write matrix to <\"<<fileName<<\">\"<<Log::endl;\n    writeFileMatrix(fileName, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/observationEquations2Files.cpp",
    "content": "/***********************************************/\n/**\n* @file observationEquations2Files.cpp\n*\n* @brief Write the design matrix and observation vector.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-12-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the linearized and decorrelated equation system for each arc $i$:\n\\begin{equation}\n\\M l_i  = \\M A_i \\M x + \\M B_i \\M y_i + \\M e_i\n\\end{equation}\nusing class \\configClass{observation}{observationType} and writes $\\M A_i$, $\\M B_i$ and $\\M l_i$ as \\file{matrix}{matrix} files.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/observation/observation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write the design matrix and observation vector.\n* @ingroup programsGroup */\nclass ObservationEquations2Files\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ObservationEquations2Files, PARALLEL, \"write the design matrix and observation vector\", Misc)\n\n/***********************************************/\n\nvoid ObservationEquations2Files::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName       fileNameL, fileNameA, fileNameB;\n    FileName       fileNamePara;\n    std::string    nameArc;\n    ObservationPtr observation;\n\n    readConfig(config, \"outputfileObservationVector\", fileNameL,    Config::OPTIONAL, \"l_{arc:%03i}.dat\",   \"one file for each arc\");\n    readConfig(config, \"outputfileDesignMatrix\",      fileNameA,    Config::OPTIONAL, \"A_{arc:%03i}.dat\",   \"one file for each arc, without arc related parameters\");\n    readConfig(config, \"outputfileDesignMatrixArc\",   fileNameB,    Config::OPTIONAL, \"\",                   \"one file for each arc, arc related parameters\");\n    readConfig(config, \"variableArc\",                 nameArc,      Config::OPTIONAL, \"arc\",                \"variable with arc number\");\n    readConfig(config, \"outputfileParameterNames\",    fileNamePara, Config::OPTIONAL, \"parameterNames.txt\", \"without arc related parameters\");\n    readConfig(config, \"observation\",                 observation,  Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    if(Parallel::isMaster(comm) && !fileNamePara.empty())\n    {\n      logStatus<<\"write parameter names to <\"<<fileNamePara<<\">\"<<Log::endl;\n      std::vector<ParameterName> names;\n      observation->parameterName(names);\n      writeFileParameterName(fileNamePara, names);\n    }\n\n    if(fileNameL.empty() && fileNameA.empty() && fileNameB.empty())\n      return;\n\n    logStatus<<\"setup observation equations\"<<Log::endl;\n    Parallel::forEach(observation->arcCount(), [&] (UInt arcNo)\n    {\n      Matrix l, A, B;\n      observation->observation(arcNo, l, A, B);\n\n      VariableList fileNameVariableList;\n      fileNameVariableList.setVariable(nameArc, arcNo);\n      if(!fileNameL.empty()) writeFileMatrix(fileNameL(fileNameVariableList), l);\n      if(!fileNameA.empty()) writeFileMatrix(fileNameA(fileNameVariableList), A);\n      if(!fileNameB.empty()) writeFileMatrix(fileNameB(fileNameVariableList), B);\n    }, comm);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/platformCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file platformCreate.cpp\n*\n* @brief create a platform file equipped with instruments.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-11-11\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate a \\file{Platform file}{platform} from scratch by defining attributes such as\n\\config{markerName}, \\config{markerNumber}, \\config{comment}, \\config{approxPosition},\n\\config{equipment}.\n\nSee also \\program{GnssAntex2AntennaDefinition} and \\program{GnssStationLog2Platform}.\n\n\\fig{!hb}{0.8}{fileFormatPlatform}{fig:platformCreate}{Platform for stations, LEOs, and GNSS satellites.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/filePlatform.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief create a platform file equipped with instruments.\n* @ingroup programsGroup */\nclass PlatformCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlatformCreate, SINGLEPROCESS, \"create a platform file equipped with instruments\", Misc)\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentGnssAntenna(Config &config)\n{\n  try\n  {\n    auto var = new PlatformGnssAntenna();\n    Angle angleX, angleY, angleZ;\n    Bool  flipx, flipy, flipz;\n\n    readConfig(config, \"name\",      var->name,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",    var->serial,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"radome\",    var->radome,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",   var->comment,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"positionX\", var->position.x(), Config::MUSTSET,  \"0\", \"[m] ARP in north, east, up or vehicle system\");\n    readConfig(config, \"positionY\", var->position.y(), Config::MUSTSET,  \"0\", \"[m] ARP in north, east, up or vehicle system\");\n    readConfig(config, \"positionZ\", var->position.z(), Config::MUSTSET,  \"0\", \"[m] ARP in north, east, up or vehicle system\");\n    readConfig(config, \"rotationX\", angleX,            Config::DEFAULT,  \"0\", \"[degree] from local/vehicle to left-handed antenna system\");\n    readConfig(config, \"rotationY\", angleY,            Config::DEFAULT,  \"0\", \"[degree] from local/vehicle to left-handed antenna system\");\n    readConfig(config, \"rotationZ\", angleZ,            Config::DEFAULT,  \"0\", \"[degree] from local/vehicle to left-handed antenna system\");\n    readConfig(config, \"flipX\",     flipx,             Config::DEFAULT,  \"0\", \"flip x-axis (after rotation)\");\n    readConfig(config, \"flipY\",     flipy,             Config::DEFAULT,  \"0\", \"flip y-axis (after rotation)\");\n    readConfig(config, \"flipZ\",     flipz,             Config::DEFAULT,  \"0\", \"flip z-axis (after rotation)\");\n    if(isCreateSchema(config))\n      return PlatformEquipmentPtr(var);\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n    var->local2antennaFrame = rotaryZ(angleZ) * rotaryY(angleY) * rotaryX(angleX);\n    if(flipx) var->local2antennaFrame = flipX() * var->local2antennaFrame;\n    if(flipy) var->local2antennaFrame = flipY() * var->local2antennaFrame;\n    if(flipz) var->local2antennaFrame = flipZ() * var->local2antennaFrame;\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentGnssReceiver(Config &config)\n{\n  try\n  {\n    auto var = new PlatformGnssReceiver();\n\n    readConfig(config, \"name\",      var->name,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",    var->serial,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"version\",   var->version,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",   var->comment,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,   Config::OPTIONAL, \"\",  \"\");\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentLaserRetroReflector(Config &config)\n{\n  try\n  {\n    auto var = new PlatformLaserRetroReflector();\n    Angle  angleX, angleY, angleZ;\n    Bool   flipx, flipy, flipz;\n    Double range = NAN;\n    FileName fileNameMatrix;\n\n    readConfig(config, \"name\",                 var->name,         Config::MUSTSET,  \"\",   \"e.g. GFZ, ITE, IPIE\");\n    readConfig(config, \"serial\",               var->serial,       Config::OPTIONAL, \"\",   \"\");\n    readConfig(config, \"comment\",              var->comment,      Config::OPTIONAL, \"\",   \"\");\n    readConfig(config, \"timeStart\",            var->timeStart,    Config::OPTIONAL, \"\",   \"\");\n    readConfig(config, \"timeEnd\",              var->timeEnd,      Config::OPTIONAL, \"\",   \"\");\n    readConfig(config, \"positionX\",            var->position.x(), Config::MUSTSET,  \"0\",  \"[m] optial reference point RP in satellite system\");\n    readConfig(config, \"positionY\",            var->position.y(), Config::MUSTSET,  \"0\",  \"[m] optial reference point RP in satellite system\");\n    readConfig(config, \"positionZ\",            var->position.z(), Config::MUSTSET,  \"0\",  \"[m] optial reference point RP in satellite system\");\n    readConfig(config, \"rotationX\",            angleX,            Config::DEFAULT,  \"0\",  \"[degree] from local/vehicle to LRR system\");\n    readConfig(config, \"rotationY\",            angleY,            Config::DEFAULT,  \"0\",  \"[degree] from local/vehicle to LRR system\");\n    readConfig(config, \"rotationZ\",            angleZ,            Config::DEFAULT,  \"0\",  \"[degree] from local/vehicle to LRR system\");\n    readConfig(config, \"flipX\",                flipx,             Config::DEFAULT,  \"0\",  \"flip x-axis (after rotation)\");\n    readConfig(config, \"flipY\",                flipy,             Config::DEFAULT,  \"0\",  \"flip y-axis (after rotation)\");\n    readConfig(config, \"flipZ\",                flipz,             Config::DEFAULT,  \"0\",  \"flip z-axis (after rotation)\");\n    readConfig(config, \"range\",                range,             Config::DEFAULT,  \"0\",  \"[m] range bias (only without range matrix)\");\n    readConfig(config, \"inputfileRangeMatrix\", fileNameMatrix,    Config::OPTIONAL, \"\",   \"[m] (azimuth(0..360) x zenith(0..dZenit*rows)\");\n    readConfig(config, \"dZenit\",               var->dZenit,       Config::DEFAULT,  \"10\", \"[degree] increment of range matrix\");\n    if(isCreateSchema(config))\n      return PlatformEquipmentPtr(var);\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n    var->platform2reflectorFrame = rotaryZ(angleZ) * rotaryY(angleY) * rotaryX(angleX);\n    if(flipx) var->platform2reflectorFrame = flipX() * var->platform2reflectorFrame;\n    if(flipy) var->platform2reflectorFrame = flipY() * var->platform2reflectorFrame;\n    if(flipz) var->platform2reflectorFrame = flipZ() * var->platform2reflectorFrame;\n    if(!fileNameMatrix.empty())\n      readFileMatrix(fileNameMatrix, var->range);\n    else\n      var->range  = Matrix(1, 1, range);\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentGeodeticSatellite(Config &config)\n{\n  try\n  {\n    auto var = new PlatformLaserRetroReflector();\n    Double range;\n\n    readConfig(config, \"name\",      var->name,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",    var->serial,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",   var->comment,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"range\",     range,             Config::MUSTSET,  \"\",  \"[m] standard center-of-mass correction\");\n    if(isCreateSchema(config))\n      return PlatformEquipmentPtr(var);\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n    var->dZenit = 0;\n    var->range  = Matrix(1, 1, range);\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentSlrStation(Config &config)\n{\n  try\n  {\n    auto var = new PlatformSlrStation();\n\n    readConfig(config, \"name\",      var->name,         Config::MUSTSET,  \"\",  \"CDP SOD 8-digit No.\");\n    readConfig(config, \"serial\",    var->serial,       Config::OPTIONAL, \"\",  \"IERS DOMES\");\n    readConfig(config, \"comment\",   var->comment,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"positionX\", var->position.x(), Config::OPTIONAL, \"0\", \"[m] eccentricity in north\");\n    readConfig(config, \"positionY\", var->position.y(), Config::OPTIONAL, \"0\", \"[m] eccentricity in east\");\n    readConfig(config, \"positionZ\", var->position.z(), Config::OPTIONAL, \"0\", \"[m] eccentricity in up\");\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentSatelliteIdentifier(Config &config)\n{\n  try\n  {\n    auto var = new PlatformSatelliteIdentifier();\n\n    readConfig(config, \"name\",      var->name,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",    var->serial,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"cospar\",    var->cospar,    Config::OPTIONAL, \"\",  \"Satellite COSPAR ID\");\n    readConfig(config, \"norad\",     var->norad,     Config::OPTIONAL, \"\",  \"Satellite Catalog (NORAD) Number\");\n    readConfig(config, \"sic\",       var->sic,       Config::OPTIONAL, \"\",  \"SIC Code\");\n    readConfig(config, \"sp3\",       var->sp3,       Config::OPTIONAL, \"\",  \"SP3\");\n    readConfig(config, \"comment\",   var->comment,   Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,   Config::OPTIONAL, \"\",  \"\");\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic PlatformEquipmentPtr createEquipmentOther(Config &config)\n{\n  try\n  {\n    auto var = new PlatformEquipment();\n\n    readConfig(config, \"name\",      var->name,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"serial\",    var->serial,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",   var->comment,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeStart\", var->timeStart,    Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var->timeEnd,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"positionX\", var->position.x(), Config::OPTIONAL, \"0\", \"[m] in north, east, up or vehicle system\");\n    readConfig(config, \"positionY\", var->position.y(), Config::OPTIONAL, \"0\", \"[m] in north, east, up or vehicle system\");\n    readConfig(config, \"positionZ\", var->position.z(), Config::OPTIONAL, \"0\", \"[m] in north, east, up or vehicle system\");\n\n    if(var->timeEnd == Time())\n      var->timeEnd = date2time(2500,1,1);\n\n    return PlatformEquipmentPtr(var);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, PlatformEquipmentPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    std::string type;\n    if(readConfigChoice(config, name, type, mustSet, defaultValue, annotation))\n    {\n      if(readConfigChoiceElement(config, \"gnssAntenna\",         type, \"\"))\n        var = createEquipmentGnssAntenna(config);\n      if(readConfigChoiceElement(config, \"gnssReceiver\",        type, \"\"))\n        var = createEquipmentGnssReceiver(config);\n      if(readConfigChoiceElement(config, \"laserRetroReflector\", type, \"\"))\n        var = createEquipmentLaserRetroReflector(config);\n      if(readConfigChoiceElement(config, \"geodeticSatellite\",   type, \"e.g. LAGEOS\"))\n        var = createEquipmentGeodeticSatellite(config);\n      if(readConfigChoiceElement(config, \"slrStation\",          type, \"\"))\n        var = createEquipmentSlrStation(config);\n      if(readConfigChoiceElement(config, \"satelliteIdentifier\", type, \"\"))\n        var = createEquipmentSatelliteIdentifier(config);\n      if(readConfigChoiceElement(config, \"other\",               type, \"\"))\n        var = createEquipmentOther(config);\n      endChoice(config);\n      return TRUE;\n    }\n\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstatic Bool readConfig(Config &config, const std::string &name, Platform::ReferencePoint &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    readConfig(config, \"comment\",   var.comment,        Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"xStart\",    var.pointStart.x(), Config::MUSTSET,  \"0\", \"[m] in north, east, up or vehicle system\");\n    readConfig(config, \"yStart\",    var.pointStart.y(), Config::MUSTSET,  \"0\", \"linear motion between start and end\");\n    readConfig(config, \"zStart\",    var.pointStart.z(), Config::MUSTSET,  \"0\", \"\");\n    readConfig(config, \"xEnd\",      var.pointEnd.x(),   Config::MUSTSET,  \"0\", \"[m] in north, east, up or vehicle system\");\n    readConfig(config, \"yEnd\",      var.pointEnd.y(),   Config::MUSTSET,  \"0\", \"linear motion between start and end\");\n    readConfig(config, \"zEnd\",      var.pointEnd.z(),   Config::MUSTSET,  \"0\", \"\");\n    readConfig(config, \"timeStart\", var.timeStart,      Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"timeEnd\",   var.timeEnd,        Config::OPTIONAL, \"\",  \"\");\n    endSequence(config);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PlatformCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNamePlatform;\n    Platform platform;\n\n    readConfig(config, \"outputfilePlatform\", fileNamePlatform,            Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"markerName\",         platform.markerName,         Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"markerNumber\",       platform.markerNumber,       Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"comment\",            platform.comment,            Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"approxPositionX\",    platform.approxPosition.x(), Config::DEFAULT,  \"0\", \"[m] in TRF\");\n    readConfig(config, \"approxPositionY\",    platform.approxPosition.y(), Config::DEFAULT,  \"0\", \"[m] in TRF\");\n    readConfig(config, \"approxPositionZ\",    platform.approxPosition.z(), Config::DEFAULT,  \"0\", \"[m] in TRF\");\n    readConfig(config, \"equipment\",          platform.equipments,         Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"referencePoint\",     platform.referencePoints,    Config::OPTIONAL, \"\",  \"e.g. center of mass in satellite frame\");\n    if(isCreateSchema(config)) return;\n\n    // check reference points\n    // ----------------------\n    if(platform.referencePoints.size())\n    {\n      for(UInt i=0; i<platform.referencePoints.size()-1; i++)\n        if(platform.referencePoints.at(i).timeEnd == Time())\n          platform.referencePoints.at(i).timeEnd = platform.referencePoints.at(i+1).timeStart;\n      if(platform.referencePoints.back().timeEnd == Time())\n        platform.referencePoints.back().timeEnd = date2time(2500,1,1);\n    }\n\n    logStatus<<\"write platform to <\"<<fileNamePlatform<<\">\"<<Log::endl;\n    writeFilePlatform(fileNamePlatform, platform);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/potentialCoefficients2BlockMeanTimeSplines.cpp",
    "content": "/***********************************************/\n/**\n* @file potentialCoefficients2BlockMeanTimeSplines.cpp\n*\n* @brief Write monthly potential coeffcients into one time spline file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program is a simplified version of \\program{Gravityfield2TimeSplines}.\nIt reads a series of potential coefficient files (\\configFile{inputfilePotentialCoefficients}{potentialCoefficients})\nand creates a time splines file with spline degree 0 (temporal block means) or degree 1 (linear splines).\nThe time intervals in which the potential coefficients are valid are defined between adjacent\npoints in time given by \\config{splineTimeSeries}. Therefore one more point in time is needed\nthan the number of potential coefficient files for degree 0.\n\nThe coefficients can be filtered with \\configClass{filter}{sphericalHarmonicsFilterType}.\nIf set the expansion is limited in the range between \\config{minDegree} and \\config{maxDegree} inclusivly.\nThe coefficients are related to the reference radius~\\config{R} and the Earth gravitational constant \\config{GM}.\n\nThis program is useful e.g. to combine monthly GRACE solutions to one file.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write monthly potential coeffcients into one time spline file.\n* @ingroup programsGroup */\nclass PotentialCoefficients2BlockMeanTimeSplines\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PotentialCoefficients2BlockMeanTimeSplines, SINGLEPROCESS, \"write monthly potential coeffcients into one time spline file\", Misc, PotentialCoefficients, TimeSplines)\n\n/***********************************************/\n\nvoid PotentialCoefficients2BlockMeanTimeSplines::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              outputName, covName;\n    std::vector<FileName> inputName;\n    TimeSeriesPtr         timeSeries;\n    SphericalHarmonicsFilterPtr filter;\n    UInt                  minDegree, maxDegree = INFINITYDEGREE;\n    Double                GM, R;\n    Bool                  removeMean;\n    Bool                  interpolate;\n    UInt                  splineDegree;\n\n    readConfig(config, \"outputfileTimeSplines\",           outputName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileTimeSplinesCovariance\", covName,    Config::OPTIONAL, \"\", \"only the variances are saved\");\n    readConfig(config, \"inputfilePotentialCoefficients\",  inputName,  Config::MUSTSET,  \"{groopsDataDir}/potential/\", \"\");\n    readConfig(config, \"filter\",           filter,        Config::DEFAULT,  \"\",  \"\");\n    readConfig(config, \"minDegree\",        minDegree,     Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",        maxDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",               GM,            Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                R,             Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"removeMean\",       removeMean,    Config::DEFAULT,  \"0\", \"remove the temporal mean of the series before estimating the splines\");\n    readConfig(config, \"interpolate\",      interpolate,   Config::DEFAULT,  \"0\", \"interpolate missing files\");\n    readConfig(config, \"splineTimeSeries\", timeSeries,    Config::MUSTSET,  \"\",  \"input files must be between points in time\");\n    readConfig(config, \"splineDegree\",     splineDegree,  Config::DEFAULT,  \"0\", \"degree of splines\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time> times  = timeSeries->times();\n    const UInt timeCount = times.size();\n    const UInt fileCount = inputName.size();\n    if(timeCount-1+splineDegree != fileCount)\n      throw(Exception(\"fileCount(\"+fileCount%\"%i) != timeCount(\"s+timeCount%\"%i)-1+splineDegree\"s));\n\n    // read data\n    // ---------\n    logStatus<<\"read potential coefficients from files\"<<Log::endl;\n    std::vector<Matrix> cnmList(fileCount), snmList(fileCount);\n    std::vector<Matrix> sigma2List(fileCount);\n    std::vector<Bool>   isZero(fileCount, FALSE);\n    Single::forEach(fileCount, [&](UInt i)\n    {\n      SphericalHarmonics harm;\n      try\n      {\n        readFileSphericalHarmonics(inputName.at(i), harm);\n        harm = filter->filter(harm);\n      }\n      catch(std::exception &e)\n      {\n        logError<<e.what()<<\": continue...\"<<Log::endl;\n        harm = SphericalHarmonics();\n        isZero.at(i) = TRUE;\n      }\n\n      harm      = harm.get(maxDegree, minDegree, GM, R);\n      maxDegree = harm.maxDegree();\n      GM        = harm.GM();\n      R         = harm.R();\n\n      cnmList.at(i)    = harm.cnm();\n      snmList.at(i)    = harm.snm();\n      sigma2List.at(i) = harm.sigma2x();\n    });\n\n    // interpolate missing data\n    // ------------------------\n    if(interpolate)\n    {\n      logStatus<<\"interpolate missing data\"<<Log::endl;\n      UInt idxStart = NULLINDEX;\n      for(UInt i=0; i<fileCount; i++)\n      {\n        if(!isZero.at(i))\n          idxStart = i;\n        else\n        {\n          UInt idxEnd = NULLINDEX;\n          for(UInt k=i+1; k<fileCount; k++)\n            if(!isZero.at(k))\n            {\n              idxEnd = k;\n              break;\n            }\n          if((idxStart==NULLINDEX)||(idxEnd==NULLINDEX))\n            throw(Exception(\"Cannot interpolate data at begin or end\"));\n          Double tau = static_cast<Double>(i-idxStart)/(idxEnd-idxStart);\n          cnmList.at(i)    = (1-tau) * cnmList.at(idxStart)    + tau * cnmList.at(idxEnd);\n          snmList.at(i)    = (1-tau) * snmList.at(idxStart)    + tau * snmList.at(idxEnd);\n          sigma2List.at(i) = (1-tau) * sigma2List.at(idxStart) + tau * sigma2List.at(idxEnd);\n        }\n      }\n    }\n\n    // remove mean\n    // -----------\n    if(removeMean)\n    {\n      logStatus<<\"remove mean\"<<Log::endl;\n      UInt count = 0;\n      for(UInt i=0; i<fileCount; i++)\n        if(!isZero.at(i))\n          count++;\n\n      Matrix cnmMean = cnmList.at(0);\n      for(UInt i=1; i<fileCount; i++)\n        if(!isZero.at(i))\n          cnmMean += cnmList.at(i);\n      cnmMean *= 1./count;\n      for(UInt i=0; i<fileCount; i++)\n        if(interpolate || !isZero.at(i))\n          cnmList.at(i) -= cnmMean;\n\n      Matrix snmMean = snmList.at(0);\n      for(UInt i=1; i<fileCount; i++)\n        if(!isZero.at(i))\n          snmMean += snmList.at(i);\n      snmMean *= 1./count;\n      for(UInt i=0; i<fileCount; i++)\n        if(interpolate || !isZero.at(i))\n          snmList.at(i) -= snmMean;\n    }\n\n    // write timeSplines file\n    // ----------------------\n    if(!outputName.empty())\n    {\n      logStatus<<\"write time splines to file <\"<<outputName<<\">\"<<Log::endl;\n      writeFileTimeSplinesGravityfield(outputName, GM, R, splineDegree, times, cnmList, snmList);\n    }\n\n    if(!covName.empty())\n    {\n      logStatus<<\"write covariance time splines to file <\"<<covName<<\">\"<<Log::endl;\n      writeFileTimeSplinesCovariance(covName, GM, R, minDegree, maxDegree, splineDegree, times, sigma2List);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/potentialCoefficients2DegreeAmplitudes.cpp",
    "content": "/***********************************************/\n/**\n* @file potentialCoefficients2DegreeAmplitudes.cpp\n*\n* @brief Degree amplitudes of potential coefficients.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-04-28\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes degree amplitudes from\n\\file{potentialCoefficients files}{potentialCoefficients}\nand saves them to a \\file{matrix}{matrix} file.\n\nThe coefficients can be filtered with \\configClass{filter}{sphericalHarmonicsFilterType} and converted\nto different functionals with \\configClass{kernel}{kernelType}. The gravity field can be evaluated at\ndifferent altitudes by specifying \\config{evaluationRadius}. Polar regions can be excluded\nby setting \\config{polarGap}. If set the expansion is limited in the range between \\config{minDegree}\nand \\config{maxDegree} inclusivly. The coefficients are related to the reference radius~\\config{R}\nand the Earth gravitational constant \\config{GM}.\n\nThe \\configFile{outputfileMatrix}{matrix} contains in the first 3 columns the degree, the degree amplitude, and\nthe formal errors. For each additional \\configFile{inputfilePotentialCoefficients}{potentialCoefficients} three columns\nare appended: the degree amplitude, the formal errors, and the difference to the first file.\n\nFor example the data columns for 4 \\configFile{inputfilePotentialCoefficients}{potentialCoefficients} are\n\\begin{itemize}\n\\item degree=\\verb|data0|\n\\item PotentialCoefficients0: signal=\\verb|data1|, error=\\verb|data2|,\n\\item PotentialCoefficients1: signal=\\verb|data3|, error=\\verb|data4|,  difference=\\verb|data5|,\n\\item PotentialCoefficients2: signal=\\verb|data6|, error=\\verb|data7|,  difference=\\verb|data8|,\n\\item PotentialCoefficients3: signal=\\verb|data9|, error=\\verb|data10|, difference=\\verb|data11|.\n\\end{itemize}\n\nSee also \\program{Gravityfield2DegreeAmplitudes}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/sphericalHarmonicsFilter/sphericalHarmonicsFilter.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Degree amplitudes of potential coefficients.\n* @ingroup programsGroup */\nclass PotentialCoefficients2DegreeAmplitudes\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PotentialCoefficients2DegreeAmplitudes, SINGLEPROCESS, \"degree amplitudes of potential coefficients\", Misc, Gravityfield, PotentialCoefficients)\n\n/***********************************************/\n\nvoid PotentialCoefficients2DegreeAmplitudes::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameOut;\n    std::vector<FileName> fileNamesIn;\n    enum DegreeType       {RMS, CUMMULATE};\n    KernelPtr             kernel;\n    SphericalHarmonicsFilterPtr filter;\n    DegreeType            degreeType = RMS;\n    Double                r = NAN_EXPR;\n    Angle                 gap(0.0);\n    UInt                  minDegree, maxDegree = INFINITYDEGREE;\n    Double                GM, R;\n    std::string           choice;\n\n    readConfig(config, \"outputfileMatrix\",               fileNameOut, Config::MUSTSET, \"\", \"matrix with degree, signal amplitude, formal error, differences\");\n    readConfig(config, \"inputfilePotentialCoefficients\", fileNamesIn, Config::MUSTSET,  \"{groopsDataDir}/potential/\", \"\");\n    readConfig(config, \"kernel\",                         kernel,      Config::MUSTSET, \"geoidHeight\", \"\");\n    readConfig(config, \"filter\",                         filter,      Config::OPTIONAL, \"\", \"filter the coefficients\");\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"type of variances\"))\n    {\n      if(readConfigChoiceElement(config, \"rms\",          choice, \"degree amplitudes (square root of degree variances)\")) degreeType = RMS;\n      if(readConfigChoiceElement(config, \"accumulation\", choice, \"cumulate variances over degrees\"))                     degreeType = CUMMULATE;\n      endChoice(config);\n    }\n    readConfig(config, \"evaluationRadius\", r,         Config::OPTIONAL, \"\", \"evaluate the gravity field at this radius (default: evaluate at surface\");\n    readConfig(config, \"polarGap\",         gap,       Config::DEFAULT,  \"0.0\", \"exclude polar regions (aperture angle in degrees)\");\n    readConfig(config, \"minDegree\",        minDegree, Config::DEFAULT,  \"2\", \"\");\n    readConfig(config, \"maxDegree\",        maxDegree, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",               GM,        Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                R,         Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    if(isCreateSchema(config)) return;\n\n\n    std::vector<SphericalHarmonics> harm(fileNamesIn.size());\n    for(UInt i=0; i<fileNamesIn.size(); i++)\n      if(System::exists(fileNamesIn.at(i)))\n      {\n        logStatus<<\"read potential coefficients <\"<<fileNamesIn.at(i)<<\">\"<<Log::endl;\n        readFileSphericalHarmonics(fileNamesIn.at(i), harm.at(i));\n        if(maxDegree == INFINITYDEGREE) maxDegree = harm.at(i).maxDegree();\n        maxDegree = std::max(maxDegree, harm.at(i).maxDegree());\n      }\n      else\n        logWarning<<\"file <\"<<fileNamesIn.at(i)<<\"> not exist. continue\"<<Log::endl;\n\n    if(std::isnan(r)) r = R;\n\n\n    logStatus<<\"compute degree amplitudes\"<<Log::endl;\n    Matrix A(maxDegree+1-minDegree, 3*harm.size(), NAN_EXPR);\n    UInt idx = 1;\n    for(UInt i=0; i<harm.size(); i++)\n    {\n      harm.at(i) = harm.at(i).get(INFINITYDEGREE, minDegree, GM, R);\n      if(filter)\n        harm.at(i) = filter->filter(harm.at(i));\n\n      // use standard deviation instead of variances\n      for(UInt n=0; n<harm.at(i).sigma2cnm().rows(); n++)\n        for(UInt m=0; m<=n; m++)\n        {\n          harm.at(i).sigma2cnm()(n,m) = std::sqrt(harm.at(i).sigma2cnm()(n,m));\n          harm.at(i).sigma2snm()(n,m) = std::sqrt(harm.at(i).sigma2snm()(n,m));\n        }\n\n      const Vector kn = kernel->inverseCoefficients(Vector3d(r, 0, 0), maxDegree);\n\n      // degree variances\n      // ----------------\n      auto variances = [&](const_MatrixSliceRef cnm, const_MatrixSliceRef snm)\n      {\n        Vector variance(maxDegree+1-minDegree, NAN_EXPR);\n        for(UInt n=minDegree; n<std::min(maxDegree+1, cnm.rows()); n++)\n        {\n          const UInt   minOrder   = static_cast<UInt>(gap*static_cast<Double>(n)+0.5); // Sneeuw\n          const Double areaFactor = (minOrder>0) ? ((2.*n+1.)/(2.*n+2.-2.*minOrder)) : (1.0);\n          const Double factor     = areaFactor * std::pow(GM/R * std::pow(R/r, n+1) * kn(n), 2);\n          variance(n-minDegree)   = factor * (quadsum(cnm.slice(n, minOrder, 1, n+1-minOrder)) + quadsum(snm.slice(n, minOrder, 1, n+1-minOrder)));\n        } // for(n)\n        return variance;\n      };\n      // ----------------\n\n      copy(variances(harm.at(i).cnm(),       harm.at(i).snm()),       A.column(idx++)); // signal\n      copy(variances(harm.at(i).sigma2cnm(), harm.at(i).sigma2snm()), A.column(idx++)); // formal errors\n      if(i > 0)                                                                         // differences\n      {\n        const UInt size = std::min(harm.at(i).maxDegree(), harm.at(0).maxDegree()) + 1;\n        copy(variances(harm.at(i).cnm().slice(0,0,size,size)-harm.at(0).cnm().slice(0,0,size,size),\n                       harm.at(i).snm().slice(0,0,size,size)-harm.at(0).snm().slice(0,0,size,size)), A.column(idx++));\n      }\n    }\n\n    if(degreeType == CUMMULATE)\n      for(UInt n=1; n<A.rows(); n++)\n        axpy(1., A.row(n-1), A.row(n));\n\n    for(UInt n=0; n<A.rows(); n++)\n      for(UInt i=0; i<A.columns(); i++)\n        A(n,i) = std::sqrt(A(n,i));\n\n    for(UInt n=0; n<A.rows(); n++)\n      A(n,0) = n+minDegree;\n\n    // write\n    // -----\n    logStatus<<\"write degree amplitudes to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/radialBasisSplines2KernelCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file radialBasisSplines2KernelCoefficients.cpp\n*\n* @brief Kernel/Covariance-function from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n// Latex documentation\n\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program calculates the coefficients $k_n$ of a \\configClass{kernel:coefficients}{kernelType:coefficients} according to\n\\begin{equation}\n  k_n = \\frac{GM}{4\\pi R}\\frac{\\sigma_n}{\\sqrt{2n+1}}.\n\\end{equation}\nfrom a given \\configClass{gravityfield}{gravityfieldType},\nwith \\config{R} and \\config{GM} describing the reference radius and the geocentric constant, respectively.\nThe $\\sigma_n$\nstand for the gravity field accuracies (from degree \\config{minDegree} to \\config{maxDegree}), if they are given.\nIf no accuracies are provided, the $\\sigma_n$\nrepresent the square root of the degree variances of the gravity field.\nIf \\config{maxDegree} exceeds the maximum degree given by \\configClass{gravityfield}{gravityfieldType},\nthe higher degrees are complemented by Kaula's rule\nThe output of the coefficients is given in the file  \\configFile{outputfileCoefficients}{matrix}.\n)\";\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Kernel/Covariance-function from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule.\n* @ingroup programsGroup */\nclass RadialBasisSplines2KernelCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(RadialBasisSplines2KernelCoefficients, SINGLEPROCESS, \"Kernel/Covariance-function from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule\", Misc)\nGROOPS_RENAMED_PROGRAM(KernelDegreeVariances, RadialBasisSplines2KernelCoefficients, date2time(2020, 11, 9))\n\n/***********************************************/\n\nvoid RadialBasisSplines2KernelCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        fileNameCoeff;\n    GravityfieldPtr gravityfield;\n    UInt            minDegree, maxDegree = INFINITYDEGREE;\n    Double          GM, R;\n    Double          kaulaPower, kaulaFactor;\n\n    readConfig(config, \"outputfileCoefficients\", fileNameCoeff, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"gravityfield\",           gravityfield,  Config::OPTIONAL, \"\",  \"use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule\");\n    readConfig(config, \"minDegree\",              minDegree,     Config::MUSTSET,  \"2\", \"\");\n    readConfig(config, \"maxDegree\",              maxDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"GM\",                     GM,            Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                      R,             Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"kaulaPower\",             kaulaPower,    Config::DEFAULT,  \"2\",    \"sigma = kaulaFactor/degree^kaulaPower\");\n    readConfig(config, \"kaulaFactor\",            kaulaFactor,   Config::DEFAULT,  \"1e-5\", \"sigma = kaulaFactor/degree^kaulaPower\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"use accuracies, if not given use signal, if not given use kaulas rule\"<<Log::endl;\n    Vector coeff;\n    if(gravityfield)\n    {\n      // Use variances\n      SphericalHarmonics field = gravityfield->sphericalHarmonics(Time(), maxDegree, minDegree, GM, R);\n      maxDegree  = field.maxDegree();\n      coeff = Vector(maxDegree+1);\n      for(UInt n=minDegree; n<=maxDegree; n++)\n      {\n        Double sum = 0.;\n        if(field.sigma2cnm().size())\n          for(UInt m=0; m<=n; m++)\n            sum += field.sigma2cnm()(n,m) + field.sigma2snm()(n,m);\n        // If no variances, use signal instead\n        if(sum==0)\n          for(UInt m=0; m<=n; m++)\n            sum += std::pow(field.cnm()(n,m), 2) + std::pow(field.snm()(n,m), 2);\n        coeff(n) = GM/R * std::sqrt(sum/(4*PI)/(2.*n+1.));\n      }\n    }\n\n    if(coeff.rows() == 0)\n    {\n      if(maxDegree == INFINITYDEGREE)\n        throw(Exception(\"maxDegree or gravityfield must be given\"));\n      coeff = Vector(maxDegree+1);\n    }\n\n    // Fill the rest with kaula\n    for(UInt n=maxDegree+1; n-->minDegree;)\n    {\n      if(coeff(n)!=0)\n        break;\n      const Double sum = (2*n+1) * std::pow(kaulaFactor/std::pow(n, kaulaPower), 2);\n      coeff(n) = GM/R * std::sqrt(sum/(4*PI)/(2.*n+1.));\n    }\n\n    logStatus<<\"write coefficient vector to file <\"<<fileNameCoeff<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameCoeff, coeff);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/satelliteModelCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file satelliteModelCreate.cpp\n*\n* @brief Create satellite macro model.\n*\n* @author Torsten Mayer-Guerr\n* @author Sandro Krauss\n* @date 2015-27-05\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program creates a satellite macro model for the estimation of non-gravitational accelerations acting on a satellite.\nMandatory input values are the \\config{satelliteName}, \\config{mass}, \\config{coefficientDrag} and information\nabout the satellite \\config{surfaces}. For low Earth orbiting satellites, like GRACE for instance, a good guess\nfor the drag coefficient could be 2.3. Apart from that, it is latter on possible to estimate a more precise variable drag coefficient\n(e.g. \\configClass{miscAccelerations:atmosphericDrag}{miscAccelerationsType:atmosphericDrag}), which will override this initial guess.\nConcerning the satellite surfaces an external file must be imported which must contain information about each single\n satellite plate in terms of plate \\config{area}, the associated plate normal and re-radiation properties\n(reflexion, diffusion and absorption) properties in the visible and IR part. Examplarily, a description of\nthe macro model for GRACE can be found under:\n\\url{https://podaac-tools.jpl.nasa.gov/drive/files/allData/grace/docs/ProdSpecDoc_v4.6.pdf}\nAdditionally, it is possible to add further information like antennaThrust, solar panel, temporal mass changes and\nmassInstrument using the modules option.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create satellite macro model.\n* @ingroup programsGroup */\nclass SatelliteModelCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SatelliteModelCreate, SINGLEPROCESS, \"Create satellite macro model.\", Misc)\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, SatelliteModelModulePtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    std::string choice;\n    if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    // Antenna thrust\n    // --------------\n    if(readConfigChoiceElement(config, \"antennaThrust\", choice, \"\"))\n    {\n      SatelliteModelModuleAntennaThrust *modul = new SatelliteModelModuleAntennaThrust;\n      var = SatelliteModelModulePtr(modul);\n\n      readConfig(config, \"thrustX\", modul->thrust.x(), Config::DEFAULT,  \"0\", \"\");\n      readConfig(config, \"thrustY\", modul->thrust.y(), Config::DEFAULT,  \"0\", \"\");\n      readConfig(config, \"thrustZ\", modul->thrust.z(), Config::DEFAULT,  \"0\", \"\");\n    }\n\n    // Solar Panel\n    // -----------\n    if(readConfigChoiceElement(config, \"solarPanel\", choice, \"\"))\n    {\n      SatelliteModelModuleSolarPanel *modul = new SatelliteModelModuleSolarPanel;\n      var = SatelliteModelModulePtr(modul);\n\n      readConfig(config, \"rotationAxisX\", modul->rotationAxis.x(), Config::DEFAULT,  \"0\", \"\");\n      readConfig(config, \"rotationAxisY\", modul->rotationAxis.y(), Config::DEFAULT,  \"0\", \"\");\n      readConfig(config, \"rotationAxisZ\", modul->rotationAxis.z(), Config::DEFAULT,  \"0\", \"\");\n      readConfig(config, \"normalX\",       modul->normal.x(),       Config::DEFAULT,  \"0\", \"Direction to sun\");\n      readConfig(config, \"normalY\",       modul->normal.y(),       Config::DEFAULT,  \"0\", \"Direction to sun\");\n      readConfig(config, \"normalZ\",       modul->normal.z(),       Config::DEFAULT,  \"0\", \"Direction to sun\");\n      readConfig(config, \"indexSurface\",  modul->indexSurface,     Config::MUSTSET,   \"\", \"index of solar panel surfaces\");\n    }\n\n    // Satellite mass change\n    // ---------------------\n    if(readConfigChoiceElement(config, \"massChange\", choice, \"\"))\n    {\n      SatelliteModelModuleMassChange *modul = new SatelliteModelModuleMassChange;\n      var = SatelliteModelModulePtr(modul);\n\n      readConfig(config, \"time\", modul->times, Config::MUSTSET,  \"\", \"\");\n      readConfig(config, \"mass\", modul->mass,  Config::MUSTSET,  \"\", \"\");\n    }\n\n    // Satellite mass change\n    // ---------------------\n    if(readConfigChoiceElement(config, \"massInstrument\", choice, \"\"))\n    {\n      std::vector<FileName> fileName;\n      readConfig(config, \"inputfileInstrument\", fileName, Config::MUSTSET,  \"\", \"\");\n\n      if(!isCreateSchema(config))\n      {\n        MassArc massArc;\n        for(UInt i=0; i<fileName.size(); i++)\n          massArc.append(InstrumentFile::read(fileName.at(i)));\n        massArc.sort();\n\n        SatelliteModelModuleMassChange *modul = new SatelliteModelModuleMassChange;\n        var = SatelliteModelModulePtr(modul);\n        for(UInt i=0; i<massArc.size(); i++)\n          if(massArc.at(i).massThr > 0.0)\n          {\n            modul->times.push_back(massArc.at(i).time);\n            modul->mass.push_back(massArc.at(i).massThr);\n          }\n      }\n    }\n\n    endChoice(config);\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, std::vector<SatelliteModel::Surface> &surfaces, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    FileName fileNameIn;\n    ExpressionVariablePtr typeExpr, areaExpr;\n    ExpressionVariablePtr normalXExpr, normalYExpr, normalZExpr;\n    ExpressionVariablePtr absorptionVisibleExpr, diffusionVisibleExpr, reflexionVisibleExpr;\n    ExpressionVariablePtr absorptionInfraredExpr, diffusionInfraredExpr, reflexionInfraredExpr;\n    ExpressionVariablePtr specificHeatCapacityExpr;\n\n    readConfig(config, \"inputfile\",            fileNameIn,               Config::MUSTSET, \"\",       \"each line must contain one surface element\");\n    readConfig(config, \"type\",                 typeExpr,                 Config::MUSTSET, \"0\",      \"0: plate, 1: sphere, 2: cylinder\");\n    readConfig(config, \"area\",                 areaExpr,                 Config::MUSTSET, \"data0\",  \"[m^2]\");\n    readConfig(config, \"normalX\",              normalXExpr,              Config::MUSTSET, \"data1\",  \"\");\n    readConfig(config, \"normalY\",              normalYExpr,              Config::MUSTSET, \"data2\",  \"\");\n    readConfig(config, \"normalZ\",              normalZExpr,              Config::MUSTSET, \"data3\",  \"\");\n    readConfig(config, \"reflexionVisible\",     reflexionVisibleExpr,     Config::MUSTSET, \"data4\",  \"\");\n    readConfig(config, \"diffusionVisible\",     diffusionVisibleExpr,     Config::MUSTSET, \"data5\",  \"\");\n    readConfig(config, \"absorptionVisible\",    absorptionVisibleExpr,    Config::MUSTSET, \"data6\",  \"\");\n    readConfig(config, \"reflexionInfrared\",    reflexionInfraredExpr,    Config::MUSTSET, \"data7\",  \"\");\n    readConfig(config, \"diffusionInfrared\",    diffusionInfraredExpr,    Config::MUSTSET, \"data8\",  \"\");\n    readConfig(config, \"absorptionInfrared\",   absorptionInfraredExpr,   Config::MUSTSET, \"data9\",  \"\");\n    readConfig(config, \"specificHeatCapacity\", specificHeatCapacityExpr, Config::MUSTSET, \"data10\", \"0: no thermal radiation, -1: direct reemission [Ws/K/m^2]\");\n    endSequence(config);\n    if(isCreateSchema(config))\n      return TRUE;\n\n    // read data\n    // ---------\n    logStatus<<\"read input from <\"<<fileNameIn<<\">\"<<Log::endl;\n    Matrix data;\n    readFileMatrix(fileNameIn, data);\n\n    // calculate output\n    // -----------------\n    VariableList varList;\n    addDataVariables(data, varList);\n    surfaces.resize(data.rows());\n    for(UInt i=0; i<data.rows(); i++)\n    {\n      evaluateDataVariables(data, i, varList);\n\n      // evaluate expression\n      surfaces.at(i).type                 = static_cast<SatelliteModel::Surface::Type>(typeExpr->evaluate(varList));\n      surfaces.at(i).area                 = areaExpr                ->evaluate(varList);\n      surfaces.at(i).normal.x()           = normalXExpr             ->evaluate(varList);\n      surfaces.at(i).normal.y()           = normalYExpr             ->evaluate(varList);\n      surfaces.at(i).normal.z()           = normalZExpr             ->evaluate(varList);\n      surfaces.at(i).absorptionVisible    = absorptionVisibleExpr   ->evaluate(varList);\n      surfaces.at(i).diffusionVisible     = diffusionVisibleExpr    ->evaluate(varList);\n      surfaces.at(i).reflexionVisible     = reflexionVisibleExpr    ->evaluate(varList);\n      surfaces.at(i).absorptionInfrared   = absorptionInfraredExpr  ->evaluate(varList);\n      surfaces.at(i).diffusionInfrared    = diffusionInfraredExpr   ->evaluate(varList);\n      surfaces.at(i).reflexionInfrared    = reflexionInfraredExpr   ->evaluate(varList);\n      surfaces.at(i).specificHeatCapacity = specificHeatCapacityExpr->evaluate(varList);\n\n      surfaces.at(i).normal.normalize();\n    }\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ntemplate<> Bool readConfig(Config &config, const std::string &name, SatelliteModelPtr &satellite, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    if(!readConfigSequence(config, name, mustSet, defaultValue, annotation))\n      return FALSE;\n\n    satellite = SatelliteModelPtr(new SatelliteModel);\n\n    renameDeprecatedConfig(config, \"modul\", \"module\", date2time(2020, 8, 20));\n\n    readConfig(config, \"satelliteName\",   satellite->satelliteName,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"mass\",            satellite->mass,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"coefficientDrag\", satellite->coefficientDrag, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"surfaces\",        satellite->surfaces,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"module\",          satellite->modules,         Config::OPTIONAL, \"\", \"\");\n    endSequence(config);\n\n    // extra module to set specificHeatCapacity without changing the file format\n    if(std::any_of(satellite->surfaces.begin(), satellite->surfaces.end(), [](auto &x) {return x.specificHeatCapacity > 0;}))\n    {\n      auto module = std::make_shared<SatelliteModelModuleSetSpecificHeatCapacity>();\n      for(UInt i=0; i<satellite->surfaces.size(); i++)\n        if(satellite->surfaces.at(i).specificHeatCapacity > 0)\n        {\n          module->specificHeatCapacity.push_back(satellite->surfaces.at(i).specificHeatCapacity);\n          module->indexSurface.push_back(i);\n        }\n      satellite->modules.push_back(module);\n    }\n\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SatelliteModelCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<SatelliteModelPtr> satellites;\n\n    readConfig(config, \"outputfileSatelliteModel\", fileNameOut, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"satellite\",                satellites,  Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // write file\n    // ----------\n    logStatus<<\"write satellite model file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileSatelliteModel(fileNameOut, satellites);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/synthesisSphericalHarmonicsMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file synthesisSphericalHarmonicsMatrix.cpp\n*\n* @brief Matrix for synthesizing spherical harmonics on a grid.\n*\n* @author Torsten Mayer-Guerr\n* @date 2025-01-23\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program builds a linear operator matrix for spherical harmonic analysis or synthesis based on\nthe points defined in \\configClass{grid}{gridType}. Depending on the chosen\n\\config{type} (synthesis, quadrature, or leastSquares), the resulting matrix can be used to:\n\\begin{itemize}\n  \\item \\textbf{synthesis}: Map spherical harmonic coefficients to values on a grid,\n  \\item \\textbf{quadrature}: Integrate grid-based functionals into spherical harmonic coefficients by\n        a simple quadrature formula,\n  \\item \\textbf{leastSquares}: Estimate coefficients from grid data via a least squares approach.\n\\end{itemize}\n\nhe spherical harmonic degree range is constrained by\n\\config{minDegree} and \\config{maxDegree}, and the ordering of the coefficients is given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType}. The reference gravitational\nconstant is \\config{GM}, and the reference radius is \\config{R}.\n\nThe computed matrix is written to \\configFile{outputfileMatrix}{matrix} with dimensions\n(number of grid points)~$\\times$~(number of spherical harmonic coefficients). For\n\\config{type} = \\emph{leastSquares}, the program applies a QR-based pseudo-inverse so that the\noutput matrix can directly form the normal-equation building blocks for a blockwise\nleast-squares solution in spherical harmonic space.\n\nSee also \\program{Gravityfield2GriddedData}, \\program{GriddedData2PotentialCoefficients},\n\\program{Gravityfield2SphericalHarmonicsVector}, and \\program{MatrixCalculate} for additional\ntools to convert between grids and spherical harmonics.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/kernel/kernel.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Matrix for synthesizing spherical harmonics on a grid.\n* @ingroup programsGroup */\nclass SynthesisSphericalHarmonicsMatrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SynthesisSphericalHarmonicsMatrix, PARALLEL, \"matrix for synthesizing spherical harmonics on a grid\", Misc, PotentialCoefficients, Matrix)\n\n/***********************************************/\n\nvoid SynthesisSphericalHarmonicsMatrix::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName    fileNameOut;\n    GridPtr     grid;\n    KernelPtr   kernel;\n    UInt        minDegree, maxDegree;\n    Double      GM, R;\n    SphericalHarmonicsNumberingPtr numbering;\n    enum Type {SYNTHESIS, QUADRATURE, LEASTSQUARES};\n    Type        type;\n    std::string choice;\n\n    readConfig(config, \"outputfileMatrix\", fileNameOut, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"grid\",             grid,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"kernel\",           kernel,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"minDegree\",        minDegree,   Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"maxDegree\",        maxDegree,   Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"GM\",               GM,          Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                R,           Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",        numbering,   Config::MUSTSET,  \"\",  \"numbering scheme of sh coefficients\");\n    if(readConfigChoice(config, \"type\", choice, Config::MUSTSET, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"synthesis\",    choice, \"synthesize spherical harmonics on a grid\")) type = SYNTHESIS;\n      if(readConfigChoiceElement(config, \"quadrature\",   choice, \"calculate spherical harmonics from grid\"))  type = QUADRATURE;\n      if(readConfigChoiceElement(config, \"leastSquares\", choice, \"estimated spherical harmonics from grid\"))  type = LEASTSQUARES;\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    std::vector<std::vector<UInt>> idxC, idxS;\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n\n    logStatus<<\"calcalute matrix for \"<<numbering->parameterCount(maxDegree, minDegree)<<\" coefficients\"<<Log::endl;\n    Matrix A = Matrix(grid->points().size(), numbering->parameterCount(maxDegree, minDegree));\n    Parallel::forEach(grid->points().size(), [&](UInt k)\n    {\n      Matrix Cnm, Snm;\n      Vector factors;\n      SphericalHarmonics::CnmSnm(1./R * grid->points().at(k), maxDegree, Cnm, Snm, (type == QUADRATURE)/*isInterior*/);\n      if(type == QUADRATURE)\n        factors = grid->points().at(k).r()/(4*PI*GM) * grid->areas().at(k) * kernel->coefficients(grid->points().at(k), maxDegree);\n      else\n        factors = GM/R * kernel->inverseCoefficients(grid->points().at(k), maxDegree);\n\n      for(UInt n=minDegree; n<=maxDegree; n++)\n      {\n        if(idxC[n][0]!=NULLINDEX) A(k, idxC[n][0]) = factors(n) * Cnm(n,0);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m]!=NULLINDEX) A(k, idxC[n][m]) = factors(n) * Cnm(n,m);\n          if(idxS[n][m]!=NULLINDEX) A(k, idxS[n][m]) = factors(n) * Snm(n,m);\n        }\n      }\n    }, comm);\n    Parallel::reduceSum(A, 0, comm);\n    if(!Parallel::isMaster(comm))\n      return;\n\n    // A' := (A'PA)^(-1) A'P\n    if(type == LEASTSQUARES)\n    {\n      logStatus<<\"compute pseudo inverse\"<<Log::endl;\n      for(UInt k=0; k<grid->points().size(); k++)\n        A.row(k) *= std::sqrt(grid->areas().at(k));\n      const Vector tau = QR_decomposition(A);\n      const Matrix R   = A.row(0, A.columns());\n      generateQ(A, tau);\n      triangularSolve(1., R, A.trans());\n      for(UInt k=0; k<grid->points().size(); k++)\n        A.row(k) *= std::sqrt(grid->areas().at(k));\n    }\n\n    // write\n    // -----\n    logStatus<<\"write matrix to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameOut, (type == SYNTHESIS) ? A : A.trans());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/temporalRepresentation2TimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file temporalRepresentation2TimeSeries.cpp\n*\n* @brief Design matrix of temporal representation.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-07-07\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the design matrix of temporal representation at a given time series.\nThe output matrix contains the time steps in MJD in the first column, the other columns contain the design matrix.\nThe intention of this program is to visualize the parametrization together with \\program{PlotGraph}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Design matrix of temporal representation.\n* @ingroup programsGroup */\nclass TemporalRepresentation2TimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(TemporalRepresentation2TimeSeries, SINGLEPROCESS, \"Design matrix of temporal representation.\", Misc, TimeSeries)\n\n/***********************************************/\n\nvoid TemporalRepresentation2TimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                   fileNameMatrix;\n    TimeSeriesPtr              timeSeries;\n    ParametrizationTemporalPtr temporal;\n\n    readConfig(config, \"outputfileMatrix\", fileNameMatrix, Config::MUSTSET, \"\", \"Time (MJD) in first column, design matrix follows\");\n    readConfig(config, \"timeSeries\",       timeSeries,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"temporal\",         temporal,       Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"Compute design matrix\"<<Log::endl;\n    std::vector<Time> times = timeSeries->times();\n    Matrix A(times.size(), 1+temporal->parameterCount());\n    for(UInt i=0; i<times.size(); i++)\n    {\n      A(i,0) = times.at(i).mjd();\n      copy(temporal->factors(times.at(i)).trans(), A.slice(i,1,1,temporal->parameterCount()));\n    }\n\n    logStatus<<\"write matrix to file <\"<<fileNameMatrix<<\">\"<<Log::endl;\n    writeFileMatrix(fileNameMatrix, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/thermosphericState2GriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file thermosphericState2GriddedData.cpp\n*\n* @brief Thermospheric state values.\n**\n* @author Torsten Mayer-Guerr\n* @date 2020-07-05\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program converts the output (neutral mass density,temperature) of an empirical thermosphere model (e.g. JB2008) on a given \\configClass{grid}{gridType}.\nAdditionally, also the thermospheric winds estimated by using the horizontal wind model HWM 2014 can be assessed.\nThe time for the evaluation can be specified in \\config{time}. The values will be saved together with points expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and \\config{inverseFlattening}.\n\\fig{!hb}{1.0}{thermosphericState2GriddedData}{fig:thermosphericState2GriddedData}{JB2008 model in 300 km height at 2003-07-01 12:00.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Thermospheric state values.\n* @ingroup programsGroup */\nclass ThermosphericState2GriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ThermosphericState2GriddedData, PARALLEL, \"thermospheric state values\", Misc, Grid)\n\n/***********************************************/\n\nvoid ThermosphericState2GriddedData::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName        fileNameGrid;\n    ThermospherePtr thermosphere;\n    GridPtr         grid;\n    Time            time;\n    Bool            useLocalFrame;\n    Double          a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameGrid,  Config::MUSTSET,  \"\", \"density [kg/m**3], temperature [K], wind (x, y, z) [m/s**2]\");\n    readConfig(config, \"thermosphere\",          thermosphere,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid\",                  grid,          Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"time\",                  time,          Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"localReferenceFrame\",   useLocalFrame, Config::OPTIONAL, \"1\", \"wind in local north, east, up, otherwise global terrestrial\");\n    readConfig(config, \"R\",                     a,             Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\",     f,             Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // compute\n    // -------\n    logStatus<<\"compute thermosphere\"<<Log::endl;\n    Ellipsoid             ellipsoid(a, f);\n    std::vector<Vector3d> points = grid->points();\n    std::vector<Double>   areas  = grid->areas();\n    std::vector<Vector>   values(points.size());\n    Parallel::forEach(values, [&](UInt i)\n    {\n      Double   density, temperature;\n      Vector3d wind;\n      thermosphere->state(time, points.at(i), density, temperature, wind);\n      if(useLocalFrame)\n        wind = localNorthEastUp(points.at(i), ellipsoid).inverseTransform(wind);\n      return Vector({density, temperature, wind.x(), wind.y(), wind.z()});\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      // convert\n      std::vector<std::vector<Double>> field(5, std::vector<Double>(points.size()));\n      for(UInt i=0; i<points.size(); i++)\n        for(UInt k=0; k<field.size(); k++)\n          field.at(k).at(i) = values.at(i).at(k);\n\n      logStatus<<\"save values to file <\"<<fileNameGrid<<\">\"<<Log::endl;\n      GriddedData griddedData(ellipsoid, points, areas, field);\n      writeFileGriddedData(fileNameGrid, griddedData);\n      MiscGriddedData::printStatistics(griddedData);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/timeSeries2PotentialCoefficients.cpp",
    "content": "/***********************************************/\n/**\n* @file timeSeries2PotentialCoefficients.cpp\n*\n* @brief Write time series as potential coefficients for each epoch.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-07-20\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nInterpret the data columns of \\configFile{inputfileTimeSeries}{instrument}\nas potential coefficients. The sequence of coefficients is given by\n\\configClass{numbering}{sphericalHarmonicsNumberingType} starting from data column \\config{startDataFields}.\n\nFor each epoch a \\configFile{outputfilesPotentialCoefficients}{potentialCoefficients}\nis written where the \\config{variableLoopTime} and \\config{variableLoopIndex} are expanded for\neach point of the given time series to create the file name for this epoch,\nsee \\reference{text parser}{general.parser:text}.\n\nSee also \\program{Gravityfield2PotentialCoefficientsTimeSeries}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/sphericalHarmonics.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Write time series as potential coefficients for each epoch.\n* @ingroup programsGroup */\nclass TimeSeries2PotentialCoefficients\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(TimeSeries2PotentialCoefficients, SINGLEPROCESS, \"write time series as potential coefficients for each epoch.\", Misc, TimeSeries, PotentialCoefficients)\n\n/***********************************************/\n\nvoid TimeSeries2PotentialCoefficients::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    fileNameOut, fileNameInstrument;\n    std::string nameTime, nameIndex, nameCount;\n    UInt        startData;\n    UInt        minDegree, maxDegree;\n    Double      GM, R;\n    SphericalHarmonicsNumberingPtr numbering;\n\n    readConfig(config, \"outputfilesPotentialCoefficients\", fileNameOut,        Config::MUSTSET,  \"coeff_{loopTime:%y-%m}.gfc\", \"for each epoch\");\n    readConfig(config, \"variableLoopTime\",                 nameTime,           Config::OPTIONAL, \"loopTime\",        \"variable with time of each epoch\");\n    readConfig(config, \"variableLoopIndex\",                nameIndex,          Config::OPTIONAL, \"\",                \"variable with index of current epoch (starts with zero)\");\n    readConfig(config, \"variableLoopCount\",                nameCount,          Config::OPTIONAL, \"\",                \"variable with total number of epochs\");\n    readConfig(config, \"inputfileTimeSeries\",              fileNameInstrument, Config::MUSTSET,  \"\",                \"each epoch: multiple data for points (MISCVALUES)\");\n    readConfig(config, \"startDataFields\",                  startData,          Config::DEFAULT,  \"0\",               \"first data column\");\n    readConfig(config, \"minDegree\",                        minDegree,          Config::MUSTSET,  \"0\",               \"minimal degree\");\n    readConfig(config, \"maxDegree\",                        maxDegree,          Config::MUSTSET,  \"\",                \"maximal degree\");\n    readConfig(config, \"GM\",                               GM,                 Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                                R,                  Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"numbering\",                        numbering,          Config::MUSTSET,  \"\",                \"numbering scheme\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<std::vector<UInt>> idxC, idxS;\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    const UInt parameterCount = numbering->parameterCount(maxDegree, minDegree);\n\n    logStatus<<\"read time series <\"<<fileNameInstrument<<\">\"<<Log::endl;\n    MiscValuesArc arc = InstrumentFile::read(fileNameInstrument);\n    Arc::printStatistics(arc);\n    const UInt dataCount = Epoch::dataCount(arc.getType(), TRUE/*mustDefined*/);\n    if(dataCount < startData + parameterCount)\n      throw(Exception(\"file contains not enough data columns: \"+dataCount%\"%i < \"s+startData%\"%i + \"s+parameterCount%\"%i\"s));\n\n    // write data\n    // ----------\n    const std::vector<Time> times = arc.times();\n    VariableList varList;\n    if(!nameTime.empty())  varList.undefineVariable(nameTime);\n    if(!nameIndex.empty()) varList.undefineVariable(nameIndex);\n    if(!nameCount.empty()) varList.setVariable(nameCount, times.size());\n\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      Matrix cnm(maxDegree+1, Matrix::SYMMETRIC, Matrix::LOWER);\n      Matrix snm(maxDegree+1, Matrix::SYMMETRIC, Matrix::LOWER);\n      for(UInt n=minDegree; n<=maxDegree; n++)\n      {\n        if(idxC[n][0] != NULLINDEX) cnm(n,0) = arc.at(idEpoch).values(startData+idxC[n][0]);\n        for(UInt m=1; m<=n; m++)\n        {\n          if(idxC[n][m] != NULLINDEX) cnm(n,m) = arc.at(idEpoch).values(startData+idxC[n][m]);\n          if(idxS[n][m] != NULLINDEX) snm(n,m) = arc.at(idEpoch).values(startData+idxS[n][m]);\n        }\n      }\n\n      if(!nameTime.empty())  varList.setVariable(nameTime, times.at(idEpoch).mjd());\n      if(!nameIndex.empty()) varList.setVariable(nameIndex, idEpoch);\n      logStatus<<\"write potential coefficients <\"<<fileNameOut(varList)<<\">\"<<Log::endl;\n      writeFileSphericalHarmonics(fileNameOut(varList), SphericalHarmonics(GM, R, cnm, snm));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/timeSeriesCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file timeSeriesCreate.cpp\n*\n* @brief Create a time series.\n*\n* @author Norbert Zehentner\n* @date 2016-04-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program generates an \\file{instrument file}{instrument},\ncontaining a time series.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parser/dataVariables.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create a time series.\n* @ingroup programsGroup */\nclass TimeSeriesCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(TimeSeriesCreate, SINGLEPROCESS, \"Create a time series\", Misc, TimeSeries)\nGROOPS_RENAMED_PROGRAM(InstrumentCreateTimeSeries, TimeSeriesCreate, date2time(2020, 01, 29))\n\n/***********************************************/\n\nvoid TimeSeriesCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      fileNameTimeSeries;\n    TimeSeriesPtr timeSeries;\n    std::vector<ExpressionVariablePtr> dataExpr;\n\n    renameDeprecatedConfig(config, \"outputfileFile\", \"outputfileTimeSeries\", date2time(2020, 01, 29));\n\n    readConfig(config, \"outputfileTimeSeries\", fileNameTimeSeries, Config::MUSTSET,  \"\", \"instrument file\");\n    readConfig(config, \"timeSeries\",           timeSeries,         Config::MUSTSET,  \"\", \"time series to be created\");\n    readConfig(config, \"data\",                 dataExpr,           Config::OPTIONAL, \"\", \"expression of output columns, extra 'epoch' variable\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"create time series\"<<Log::endl;\n    std::vector<Time> times = timeSeries->times();\n\n    VariableList varList;\n    addDataVariables(\"epoch\", times, varList);\n    std::for_each(dataExpr.begin(), dataExpr.end(), [&](auto expr) {expr->simplify(varList);});\n\n    Matrix A(times.size(), 1+dataExpr.size());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      varList.setVariable(\"epoch\", times.at(idEpoch).mjd());\n      for(UInt k=0; k<dataExpr.size(); k++)\n        A(idEpoch, 1+k) = dataExpr.at(k)->evaluate(varList);\n    }\n\n    logStatus<<\"write instrument data to file <\"<<fileNameTimeSeries<<\">\"<<Log::endl;\n    Arc arc(times, A);\n    InstrumentFile::write(fileNameTimeSeries, arc);\n    Arc::printStatistics(arc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/misc/variational2OrbitAndStarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file variational2OrbitAndStarCamera.cpp\n*\n* @brief Extracts orbit and star camera data from variational file.\n*\n* @author Sebastian Strasser\n* @author Andreas Kvas\n* @date 2016-07-13\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nExtracts the reference \\configFile{outputfileOrbit}{instrument}, \\configFile{outputfileStarCamera}{instrument},\nand \\configFile{outputfileEarthRotation}{instrument} from \\configFile{inputfileVariational}{variationalEquation}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileVariationalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Extracts orbit and star camera data from variational file.\n* @ingroup programsGroup */\nclass Variational2OrbitAndStarCamera\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Variational2OrbitAndStarCamera, SINGLEPROCESS, \"Extracts orbit and star camera data from variational file.\", Misc, VariationalEquation, Instrument)\nGROOPS_RENAMED_PROGRAM(Variational2Orbit, Variational2OrbitAndStarCamera, date2time(2022, 10, 7))\n\n/***********************************************/\n\nvoid Variational2OrbitAndStarCamera::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOutOrbit, fileNameOutStarCamera, fileNameOutEarthRotation, fileNameInVariational;\n\n    renameDeprecatedConfig(config, \"outputFileOrbit\",      \"outputfileOrbit\",      date2time(2020, 7, 15));\n    renameDeprecatedConfig(config, \"inputFileVariational\", \"inputfileVariational\", date2time(2020, 7, 15));\n\n    readConfig(config, \"outputfileOrbit\",         fileNameOutOrbit,         Config::OPTIONAL, \"\", \"output orbit (instrument) file\");\n    readConfig(config, \"outputfileStarCamera\",    fileNameOutStarCamera,    Config::OPTIONAL, \"\", \"output satellite attidude as star camera (instrument) file\");\n    readConfig(config, \"outputfileEarthRotation\", fileNameOutEarthRotation, Config::OPTIONAL, \"\", \"output Earth rotation as star camera (instrument) file\");\n    readConfig(config, \"inputfileVariational\",    fileNameInVariational,    Config::MUSTSET,  \"\", \"input variational file\");\n    if(isCreateSchema(config)) return;\n\n    if(fileNameOutOrbit.empty() && fileNameOutStarCamera.empty() && fileNameOutEarthRotation.empty())\n      return;\n\n    FileVariationalEquation fileVariational(fileNameInVariational);\n    std::list<Arc> arcListOrbit, arcListStarCamera, arcListEarthRotation;\n    for(UInt arcNo = 0; arcNo < fileVariational.arcCount(); arcNo++)\n    {\n      VariationalEquationArc arc = fileVariational.readArc(arcNo);\n      arcListOrbit.push_back(arc.orbitArc());\n\n      StarCameraArc starCamera;\n      for(UInt i=0; i<arc.times.size(); i++)\n      {\n        StarCameraEpoch e;\n        e.time   = arc.times.at(i);\n        e.rotary = arc.rotSat.at(i);\n        starCamera.push_back(e);\n      }\n      arcListStarCamera.push_back(starCamera);\n\n      StarCameraArc earthRotation;\n      for(UInt i=0; i<arc.times.size(); i++)\n      {\n        StarCameraEpoch e;\n        e.time   = arc.times.at(i);\n        e.rotary = arc.rotEarth.at(i);\n        earthRotation.push_back(e);\n      }\n      arcListEarthRotation.push_back(earthRotation);\n    }\n\n    if(!fileNameOutOrbit.empty())\n    {\n      logStatus<<\"write orbit to file <\"<<fileNameOutOrbit<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutOrbit, arcListOrbit);\n    }\n    if(!fileNameOutStarCamera.empty())\n    {\n      logStatus<<\"write star camera to file <\"<<fileNameOutStarCamera<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOutStarCamera, arcListStarCamera);\n    }\n    if(!fileNameOutEarthRotation.empty())\n    {\n      logStatus<<\"write Earth rotation to file <\"<<fileNameOutEarthRotation<<\">\"<< Log::endl;\n      InstrumentFile::write(fileNameOutEarthRotation, arcListEarthRotation);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsAccumulate.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsAccumulate.cpp\n*\n* @brief Accumulate normal equations and write it to file.\n*\n* @author Andreas Kvas\n* @date 2013-10-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program accumulates normal equations and writes the total combined system to\n\\configFile{outputfileNormalequation}{normalEquation}.\nThe \\configFile{inputfileNormalEquation}{normalEquation}s must have all the same size and the same block structure.\n\nThis program is the simplified and fast version of the more general program \\program{NormalsBuild}.\nFor input normals with different parameters, see \\program{NormalsReorderAndAccumulate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accumulate normal equations and write it to file.\n* @ingroup programsGroup */\nclass NormalsAccumulate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsAccumulate, SINGLEPROCESS, \"accumulate normal equations and write to file\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsAccumulate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<FileName> fileNameInAll;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", fileNameOut,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileNormalEquation\",  fileNameInAll, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    logStatus<<\"read normal equations info\"<<Log::endl;\n    Matrix nOut;\n    NormalEquationInfo infoOut;\n    std::vector<FileName> fileNameIn;\n    std::vector<Matrix>   usedBlocksIn;\n    for(UInt i=0; i<fileNameInAll.size(); i++)\n    {\n      Matrix nIn;\n      NormalEquationInfo infoIn;\n      try\n      {\n        readFileNormalEquation(fileNameInAll.at(i), infoIn, nIn);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        continue;\n      }\n\n      fileNameIn.push_back(fileNameInAll.at(i));\n      usedBlocksIn.push_back(infoIn.usedBlocks);\n      if(!infoOut.blockIndex.size())\n      {\n        infoOut = infoIn;\n        nOut    = nIn;\n        continue;\n      }\n\n      if(infoOut.blockIndex.size() != infoIn.blockIndex.size())\n        throw(Exception(\"normals must have the same size and block structure\"));\n      for(UInt z=0; z<infoOut.blockIndex.size(); z++)\n        if(infoOut.blockIndex.at(z) != infoIn.blockIndex.at(z))\n          throw(Exception(\"normals must have the same size and block structure\"));\n      for(UInt z=0; z<infoOut.blockIndex.size()-1; z++)\n        for(UInt s=z; s<infoOut.blockIndex.size()-1; s++)\n          if(infoIn.usedBlocks(z,s))\n            infoOut.usedBlocks(z,s) = 1;\n      for(UInt i=0; i<infoOut.parameterName.size(); i++)\n        if(!infoOut.parameterName.at(i).combine(infoIn.parameterName.at(i)))\n          logWarning << \"Parameter names do not match at index \" << i << \": '\" << infoOut.parameterName.at(i).str() << \"' != '\" << infoIn.parameterName.at(i).str() << \"'\" << Log::endl;\n\n      nOut += nIn;\n      infoOut.lPl              += infoIn.lPl;\n      infoOut.observationCount += infoIn.observationCount;\n    }\n\n    // ==================================\n\n    logStatus<<\"read and write block normals\"<<Log::endl;\n    Log::Timer timer(infoOut.blockIndex.size()*(infoOut.blockIndex.size()-1)/2);\n    UInt idx = 0;\n    for(UInt z=0; z<infoOut.blockIndex.size()-1; z++)\n      for(UInt s=z; s<infoOut.blockIndex.size()-1; s++)\n      {\n        timer.loopStep(idx++);\n\n        if(infoOut.usedBlocks(z,s) == 0)\n          continue;\n\n        std::string ext;\n        if(infoOut.blockIndex.size()-1 > 1)\n          ext = \".\"+z%\"%02i-\"s+s%\"%02i\"s;\n\n        Matrix N;\n        for(UInt i=0; i<fileNameIn.size(); i++)\n          if(usedBlocksIn.at(i)(z,s))\n          {\n            logStatus<<\"read matrix <\"<<fileNameIn.at(i).appendBaseName(ext)<<\">\"<<Log::endl;\n            Matrix N2;\n            readFileMatrix(fileNameIn.at(i).appendBaseName(ext), N2);\n            if(N.size())\n              N += N2;\n            else\n              N = N2;\n          }\n\n        logStatus<<\"write matrix <\"<<fileNameOut.appendBaseName(ext)<<\">\"<<Log::endl;\n        writeFileMatrix(fileNameOut.appendBaseName(ext), N);\n      }\n    timer.loopEnd();\n\n    // ==================================\n\n    logStatus<<\"write normal equations to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameOut, infoOut, nOut);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsBuild.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsBuild.cpp\n*\n* @brief Accumulate normal equations and write it to file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-03-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program accumulates \\configClass{normalEquation}{normalEquationType}s and\nwrites the total combined system to \\configFile{outputfileNormalequation}{normalEquation}.\nFor a detailed description of the used algorithm see \\configClass{normalEquation}{normalEquationType}.\nLarge normal equation systems can be divided into blocks with \\config{normalsBlockSize}.\n\nA simplifed and fast version of this program is \\program{NormalsAccumulate}.\nFor input normals with different parameters see \\program{NormalsReorderAndAccumulate}.\nTo solve the system of normal equations use \\program{NormalsSolverVCE}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accumulate normal equations and write it to file.\n* @ingroup programsGroup */\nclass NormalsBuild\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsBuild, PARALLEL, \"accumulate normal equations and write it to file\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsBuild::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          fileNameNormals;\n    NormalEquationPtr normals;\n    UInt              blockSize;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"normalequation\",           \"normalEquation\",           date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", fileNameNormals, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"normalEquation\",           normals,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"normalsBlockSize\",         blockSize,       Config::DEFAULT,  \"2048\", \"block size for distributing the normal equations, 0: one block\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"init normal equations\"<<Log::endl;\n    normals->init(blockSize, comm);\n    logInfo<<\"  number of unknown parameters: \"<<normals->parameterCount()<<Log::endl;\n    logInfo<<\"  number of right hand sides:   \"<<normals->rightHandSideCount()<<Log::endl;\n\n    logStatus<<\"accumulate normal equations\"<<Log::endl;\n    normals->build();\n\n    logStatus<<\"write normal equations to <\"<<fileNameNormals<<\">\"<<Log::endl;\n    normals->write(fileNameNormals);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsBuildShortTimeStaticLongTime.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsBuildShortTimeStaticLongTime.cpp\n*\n* @brief Normal equations with static, short time, and long time gravity field parameters.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-08-13\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program sets up normal equations based on \\configClass{observation}{observationType}.\nAdditionally short time and long time variations can be parametrized based on the static parameters\nin \\configClass{observation}{observationType} in an efficient way. The observation equations\nare divided into time intervals $i \\in \\{1, ..., N\\}$ (e.g. daily) as defined in\n\\configFile{inputfileArcList}{arcList}.\n\nWith \\config{estimateLongTimeVariations} additional temporal variations can be co-estimated\nfor a subset of the parameters selected by \\configClass{parameterSelection}{parameterSelectorType}.\nThese parameters might be spherical harmonic coefficients with a limited maximum degree.\nThe temporal variations are represented by base functions $\\Phi_k(t_i)$ (e.g. trend and annual oscillation)\ngiven by \\configClass{parametrizationTemporal}{parametrizationTemporalType}.\nThe temporal base functions are evaluated at the mid time~$t_i$ of each interval~$i$, multiplicated\nwith the design matrix $\\M A_i$ of the selected parameters, and the design matrix is extended\naccordingly.\n\n\\fig{!hb}{0.8}{normalsBuildShortTimeStaticLongTime}{fig:normalsBuildShortTimeStaticLongTime}{Schema of the extended design matrix.}\n\nWith \\config{estimateShortTimeVariations} short time variations of the gravity field can be co-estimated.\nTheir purpose is to mitigate temporal aliasing.\nThe short time parameters selected by \\configClass{parameterSelection}{parameterSelectorType}\n(e.g. daily constant or linear splines every 6 hour) are constrained by an\n\\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType}. If only a static parameter\nset is selected the coressponding part of the design matrix is copied and modeled as a constant value\nper interval in \\configFile{inputfileArcList}{arcList} additionally so the corresponding temporal factor can be expressed as\n\\begin{equation}\n  \\Phi_i(t)  =\n  \\begin{cases}\n    1 &\\text{if} \\hspace{5pt} t \\in [t_i, t_{i+1}) \\\\\n    0 & \\text{otherwise}\n  \\end{cases}.\n\\end{equation}\n\nBefore writing the normal equations to \\configFile{outputfileNormalEquation}{normalEquation}\nshort time gravity and satellite specific parameters can be eliminated with \\config{eliminateParameter}.\n\nExample: For the computation of the mean gravity field ITSG-Grace2018s with additional trend and annual signal\nthe normal equations are computed month by month and accumulated afterwards (see \\program{NormalsAccumulate}).\nThe observations were divided into daily intervals with \\configFile{inputfileArcList}{arcList}.\nThe static gravity field has been parametrized as spherical harmonics\nup to degree $n=200$ in \\configClass{observation:parametrizationGravity}{parametrizationGravityType}.\nThe trend and annual signals defined by\n\\configClass{estimateLongTimeVariations:parametrizationTemporal}{parametrizationTemporalType}\nwere estimated for selected parameters up to degree $n=120$.\nTo mitigate temporal aliasing daily gravity fields up to degree $n=40$ were setup and constrained\nwith an \\configClass{autoregressiveModelSequence}{autoregressiveModelSequenceType} up to order three.\n\nA detailed description of the approach is given in:\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). \\url{https://doi.org/10.1007/s00190-019-01314-1}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/observation/observation.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/kalmanProcessing.h\"\n#include \"misc/normalsShortTimeStaticLongTime.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Normal equations with static, short time, and long time gravity field parameters.\n* @ingroup programsGroup */\nclass NormalsBuildShortTimeStaticLongTime\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsBuildShortTimeStaticLongTime, PARALLEL, \"Normal equations with static, short time, and long time gravity field parameters\", NormalEquation)\nGROOPS_RENAMED_PROGRAM(KalmanStaticTemporalNormals, NormalsBuildShortTimeStaticLongTime, date2time(2020, 12, 7))\n\n/***********************************************/\n\nvoid NormalsBuildShortTimeStaticLongTime::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName                       fileNameNormals;\n    ObservationPtr                 observation;\n    AutoregressiveModelSequencePtr arSequence;\n    ParameterSelectorPtr           parameterShortTime;\n    ParametrizationTemporalPtr     temporalLongTime;\n    ParameterSelectorPtr           parameterLongTime;\n    FileName                       fileNameArcList;\n    UInt                           defaultBlockSize;\n    Bool                           eliminateParameter;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"arcList\",                  \"inputfileArcList\",         date2time(2020, 7, 7));\n\n    readConfig(config, \"outputfileNormalEquation\", fileNameNormals, Config::MUSTSET, \"\", \"outputfile for normal equations\");\n    readConfig(config, \"observation\",              observation,     Config::MUSTSET, \"\", \"\");\n    if(readConfigSequence(config, \"estimateShortTimeVariations\", Config::OPTIONAL, \"\", \"co-estimate short time gravity field variations\"))\n    {\n      readConfig(config, \"autoregressiveModelSequence\", arSequence,         Config::MUSTSET, \"\", \"AR model sequence for constraining short time gravity variations\");\n      readConfig(config, \"parameterSelection\",          parameterShortTime, Config::MUSTSET, \"\", \"parameters describing the short time gravity field\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateLongTimeVariations\", Config::OPTIONAL, \"\", \"co-estimate long time gravity field variations\"))\n    {\n      readConfig(config, \"parametrizationTemporal\", temporalLongTime,  Config::MUSTSET, \"\", \"parametrization of time variations (trend, annual, ...)\");\n      readConfig(config, \"parameterSelection\",      parameterLongTime, Config::MUSTSET, \"\", \"parameters describing the long time gravity field\");\n      endSequence(config);\n    }\n    readConfig(config, \"inputfileArcList\",   fileNameArcList,    Config::MUSTSET, \"\",     \"list to correspond points of time to arc numbers\");\n    readConfig(config, \"defaultBlockSize\",   defaultBlockSize,   Config::DEFAULT, \"2048\", \"block size for distributing the normal equations, 0: one block\");\n    readConfig(config, \"eliminateParameter\", eliminateParameter, Config::DEFAULT, \"1\",    \"eliminate short time and state parameter\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"read arc list <\"<<fileNameArcList<<\">\"<<Log::endl;\n    std::vector<UInt> arcsInterval;\n    std::vector<Time> timesInterval;\n    readFileArcList(fileNameArcList, arcsInterval, timesInterval);\n\n    // init normal equations\n    // ---------------------\n    logStatus<<\"initialize normal equations\"<<Log::endl;\n    NormalsShortTimeStaticLongTime normals;\n    normals.init(observation, timesInterval, defaultBlockSize, comm, TRUE/*sortStateBeforeGravityParameter*/,\n                 (arSequence) ? arSequence->dimension() : 0, parameterShortTime,\n                 temporalLongTime, parameterLongTime);\n    normals.setBlocks(arcsInterval);\n\n    // setup observation equations\n    // ---------------------------\n    logStatus<<\"accumulate normals from observation equations\"<<Log::endl;\n    Parallel::forEachInterval(observation->arcCount(), arcsInterval, [&](UInt arcNo)\n    {\n      // search time interval\n      UInt idInterval = 0;\n      while(arcsInterval.at(idInterval+1) <= arcNo)\n        idInterval++;\n      observation->setInterval(timesInterval.at(idInterval), timesInterval.at(idInterval+1));\n\n      // observation equations\n      Matrix l, A, B;\n      observation->observation(arcNo, l, A, B);\n      if(l.rows() == 0)\n        return;\n\n      normals.accumulate(idInterval, l, A, B);\n    }, comm);\n    observation = nullptr;\n\n    // collect system of normal equations\n    // ----------------------------------\n    logStatus<<\"collect system of normal equations\"<<Log::endl;\n    normals.reduceSum();\n\n    // add normals of short time model\n    // -------------------------------\n    if(arSequence)\n    {\n      logStatus<<\"add normals of short time model\"<<Log::endl;\n      normals.addShortTimeNormals(1., arSequence->normalEquationSequence());\n    }\n\n    // eliminate interval & state parameters\n    // -------------------------------------\n    if(eliminateParameter)\n    {\n      logStatus<<\"eliminate interval parameters from normal equations\"<<Log::endl;\n      normals.regularizeUnusedParameters(normals.blockIndexStatic);\n      normals.cholesky(TRUE/*timing*/, 0, normals.blockIndexStatic, TRUE/*collect*/);\n      normals.triangularTransSolve(normals.n, 0, normals.blockIndexStatic);\n      if(Parallel::isMaster(comm))\n      {\n        normals.obsCount -= normals.blockIndex(normals.blockIndexStatic);\n        // lPl = lPl - n2^T N2^(-1) n2\n        for(UInt i=0; i<normals.lPl.rows(); i++)\n          normals.lPl(i) -= quadsum(normals.n.slice(0, i, normals.blockIndex(normals.blockIndexStatic),1));\n        // remove additional parameters\n        normals.n = normals.n.row(normals.blockIndex(normals.blockIndexStatic), normals.parameterCount() - normals.blockIndex(normals.blockIndexStatic));\n        normals.parameterNames.erase(normals.parameterNames.begin(), normals.parameterNames.begin()+normals.blockIndex(normals.blockIndexStatic));\n      }\n      normals.eraseBlocks(0, normals.blockIndexStatic);\n    } // if(eliminateParameter)\n\n    // Write normal equations\n    // ----------------------\n    logStatus<<\"write normal equations to <\"<<fileNameNormals<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameNormals, NormalEquationInfo(normals.parameterNames, normals.lPl, normals.obsCount), normals, normals.n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsCreate.cpp\n*\n* @brief Create normal equations from calculated matrices\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate \\file{normal equations}{normalEquation}\nfrom calculated matrices (\\configClass{matrixGenerator}{matrixGeneratorType}).\n\nThe \\configFile{inputfileParameterNames}{parameterName} can be created with \\program{ParameterNamesCreate}.\n\nThe \\configClass{normalMatrix}{matrixGeneratorType} must be symmetric.\nThe \\configClass{rightHandSide}{matrixGeneratorType} must have the same number of rows\nand can contain multiple columns for multiple solutions.\n\nThe Vector $\\M l^T\\M P\\M l$ is the quadratic sum of observations for each column of the right hand side.\nIt is used to determine the aposteriori accuracy\n\\begin{equation}\n\\hat{\\sigma}^2 = \\frac{\\hat{\\M e}^T\\M P\\hat{\\M e}}{n-m} = \\frac{\\M l^T\\M P\\M l - \\M n^T\\hat{\\M x}}{n-m}.\n\\end{equation}\nIf the vector is not given, it is automatically determined by assuming $\\hat{\\sigma}^2=1$.\n\nThe number of observations~$n$ is given by the expression \\config{observationCount}.\nThe variable \\verb|observationCount| can be used, if it is set by a normal equation file\n\\configFile{inputfileNormalEquationObsCount}{normalEquation}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/matrixGenerator/matrixGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create normal equations from calculated matrices.\n* @ingroup programsGroup */\nclass NormalsCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsCreate, SINGLEPROCESS, \"create normal equations from calculated matrices\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName              fileNameNormals;\n    FileName              fileNameParameterName;\n    FileName              fileNameNormalsObsCount;\n    MatrixGeneratorPtr    generate_N, generate_n, generate_lPl;\n    ExpressionVariablePtr exprObsCount;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\",        \"outputfileNormalEquation\",        date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequationObsCount\", \"inputfileNormalEquationObsCount\", date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\",        fileNameNormals,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileParameterNames\",         fileNameParameterName,   Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"normalMatrix\",                    generate_N,              Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"rightHandSide\",                   generate_n,              Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"lPl\",                             generate_lPl,            Config::DEFAULT,  \"\", \"vector with size of rhs columns\");\n    readConfig(config, \"inputfileNormalEquationObsCount\", fileNameNormalsObsCount, Config::OPTIONAL, \"\", \"sets the variable observationCount\");\n    readConfig(config, \"observationCount\",                exprObsCount,            Config::MUSTSET,  \"observationCount\", \"(variables: rows, columns (rhs), observationCount)\");\n    if(isCreateSchema(config)) return;\n\n    // create matrices\n    // ---------------\n    logStatus<<\"create matrices\"<<Log::endl;\n    Matrix N = generate_N->compute();\n    Matrix n = generate_n->compute();\n    NormalEquationInfo info(std::vector<ParameterName>(N.rows()), generate_lPl->compute());\n\n    // checks\n    if((N.rows() != N.columns()) || (N.getType() != Matrix::SYMMETRIC))\n      throw(Exception(\"Normal matrix must quadratix and symmetric\"));\n    if((n.rows() != N.rows()) || (n.getType() != Matrix::GENERAL))\n      throw(Exception(\"Right hand side: dimension error\"));\n    if(info.lPl.size() && (info.lPl.rows() != n.columns()))\n      throw(Exception(\"lPl: dimension error\"));\n\n    // compute observation count\n    // -------------------------\n    VariableList varList;\n    varList.setVariable(\"rows\",    n.rows());\n    varList.setVariable(\"columns\", n.columns());\n    if(!fileNameNormalsObsCount.empty())\n    {\n      Matrix n;\n      NormalEquationInfo info;\n      readFileNormalEquation(fileNameNormalsObsCount, info, n);\n      varList.setVariable(\"observationCount\", info.observationCount);\n    }\n    info.observationCount = static_cast<UInt>(exprObsCount->evaluate(varList));\n\n    // simulate lPl\n    // ------------\n    if(info.lPl.size() == 0)\n    {\n      logStatus<<\"Simulate lPl\"<<Log::endl;\n      Matrix x = n;\n      Matrix N2 = N;\n      for(UInt i=0; i<N2.rows(); i++)\n        if(N2(i,i) == 0)\n          N2(i,i) = 1.;\n      solveInPlace(N2, x);\n      // sigma^2 = (lPl-n'x)/(m-n)\n      info.lPl = Vector(n.columns());\n      for(UInt i=0; i<info.lPl.rows(); i++)\n        info.lPl(i) = (info.observationCount-x.rows()) + inner(x.column(i), n.column(i));\n    }\n\n    // parameter names\n    // ---------------\n    if(!fileNameParameterName.empty())\n      readFileParameterName(fileNameParameterName, info.parameterName);\n\n    // write normal equations\n    // ----------------------\n    logStatus<<\"write normal equations to <\"<<fileNameNormals<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameNormals, info, N, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsEliminate.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsEliminate.cpp\n*\n* @brief Eliminate parameters from a system of normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2003-03-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program eliminates parameters from a system of \\configFile{inputfileNormalEquation}{normalEquation}s.\nTo just remove (cutting out) parameters use \\program{NormalsReorder}.\n\nThe \\configClass{remainingParameters}{parameterSelectorType} allows the selection\nof parameters that will remain, all others will be eliminated. The order of remaining parameters\ncan be modified via the parameter selection. Block size of the output normal matrix can be adjusted with\n\\config{outBlockSize}. If it is set to zero, the \\configFile{outputfileNormalEquation}{normalEquation}\nis written to a single block file.\n\nFor example the normal equations are divided into two groups of\nparameters $\\hat{\\M x}_1$ and $\\hat{\\M x}_2$ according to\n\\begin{equation}\n\\begin{pmatrix}\n  \\M N_{11} & \\M N_{12} \\\\\n  \\M N_{21} & \\M N_{22}\n\\end{pmatrix}\n\\begin{pmatrix} \\hat{\\M x}_1 \\\\ \\hat{\\M x}_2 \\end{pmatrix}\n=\n\\begin{pmatrix}\n  \\M n_1 \\\\\n  \\M n_2\n\\end{pmatrix}.\n\\end{equation}\nand $\\hat{\\M x}_2$ shall be eliminated, the reduced system of normal equations is given by\n\\begin{equation}\n\\bar{\\M N}\\hat{\\M x} = \\bar{\\M n}\n\\qquad\\text{with}\\qquad\n\\bar{\\M N}=\\M N_{11}-\\M N_{12}\\M N_{22}^{-1}\\M N_{12}^T\n\\qquad\\text{and}\\qquad\\bar{\\M n} =  \\M n_1 - \\M N_{12}\\M N_{22}^{-1}\\M n_2.\n\\end{equation}\n\nSee also \\program{NormalsReorder}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Eliminate parameters from a system of normal equations.\n* @ingroup programsGroup */\nclass NormalsEliminate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsEliminate, PARALLEL, \"Eliminate parameters from a system of normal equations.\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsEliminate::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outName, inName;\n    ParameterSelectorPtr parameterSelector;\n    UInt blockSize;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", outName,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileNormalEquation\",  inName,             Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"remainingParameters\",      parameterSelector,  Config::MUSTSET,  \"\",     \"parameter order/selection of output normal equations\");\n    readConfig(config, \"outBlockSize\",             blockSize,          Config::DEFAULT,  \"2048\", \"block size for distributing the normal equations, 0: one block\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    logStatus<<\"init normal equations\"<<Log::endl;\n    MatrixDistributed normal;\n    Matrix rhs;\n    NormalEquationInfo info;\n    readFileNormalEquation(inName, info, normal, rhs, comm);\n\n    // compute index vectors and block structure for remaining parameters\n    std::vector<UInt> indexVector = parameterSelector->indexVector(info.parameterName);\n    const UInt parameterCountOld  = normal.parameterCount();\n    const UInt parameterCountNew  = indexVector.size();\n    std::vector<UInt> blockIndex  = MatrixDistributed::computeBlockIndex(parameterCountNew, blockSize);\n\n    // compute index vectors and block structure for to-be-eliminated parameters\n    std::vector<UInt> eliminationIndexVector = ParameterSelector::indexVectorComplement(indexVector, parameterCountOld);\n    const UInt eliminationCount = eliminationIndexVector.size();\n    std::vector<UInt> eliminationBlockIndex  = MatrixDistributed::computeBlockIndex(eliminationCount, blockSize);\n    if(eliminationCount == parameterCountOld)\n      logWarning<<\"eliminating all original parameters\"<<Log::endl;\n\n    logInfo<<\"  number of unknown parameters (old): \"<<parameterCountOld<<Log::endl;\n    logInfo<<\"  number of unknown parameters (new): \"<<parameterCountNew<<Log::endl;\n    logInfo<<\"  number of right hand sides:         \"<<info.lPl.rows()<<Log::endl;\n\n    // create list of remaining parameter names\n    std::vector<ParameterName> parameterNamesOld = info.parameterName;\n    info.parameterName.resize(parameterCountNew);\n    for(UInt i=0; i<parameterCountNew; i++)\n      info.parameterName.at(i) = (indexVector.at(i) != NULLINDEX) ? parameterNamesOld.at(indexVector.at(i)) : ParameterName();\n\n    // prepend to-be-eliminated parameters to (remaining) index vector and block structure\n    if(eliminationCount > 0)\n    {\n      for(auto &&index : blockIndex)\n        index += eliminationCount;\n      eliminationBlockIndex.pop_back();\n      blockIndex.insert(blockIndex.begin(), eliminationBlockIndex.begin(), eliminationBlockIndex.end());\n      indexVector.insert(indexVector.begin(), eliminationIndexVector.begin(), eliminationIndexVector.end());\n    }\n\n    logStatus<<\"reorder normal matrix\"<<Log::endl;\n    normal.reorder(indexVector, blockIndex);\n    rhs = reorder(rhs, indexVector);\n\n    if(eliminationCount > 0)\n    {\n      logStatus<<\"eliminate parameters from normal equations\"<<Log::endl;\n      const UInt eliminationBlocks = eliminationBlockIndex.size();\n      for(UInt i=0; i<eliminationBlocks; i++)\n      {\n        normal.setBlock(i, i);\n        if(normal.isMyRank(i,i))\n        {\n          Matrix &N = normal.N(i,i);\n          for(UInt k=0; k<N.rows(); k++)\n            if(N(k,k) == 0.)\n              N(k,k) += 1.0;\n        }\n      }\n      normal.cholesky(TRUE, 0, eliminationBlocks, TRUE);\n      normal.triangularTransSolve(rhs, 0, eliminationBlocks);\n      normal.eraseBlocks(0, eliminationBlocks);\n      info.observationCount -= eliminationCount;\n      for(UInt i=0; i<info.lPl.rows(); i++)\n        info.lPl(i) -= quadsum(rhs.slice(0, i, eliminationCount, 1)); // lPl = lPl - n1' N1^(-1) n1\n      rhs = rhs.row(eliminationCount, rhs.rows()-eliminationCount);\n    }\n    else\n      logWarningOnce<<\"no parameters eliminated\"<<Log::endl;\n\n    logStatus<<\"write normal equations to <\"<<outName<<\">\"<<Log::endl;\n    writeFileNormalEquation(outName, info, normal, rhs);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsMultiplyAdd.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsMultiplyAdd.cpp\n*\n* @brief n += alpha*N*x.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-02-19\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program modifies \\configFile{inputfileNormalEquation}{normalEquation} in a way\nthat $\\bar{\\M x}$ is estimated instead of $\\M x$.\n\\begin{equation}\n \\bar{\\M x} := \\M x + \\alpha\\, \\M x_0,\n\\end{equation}\nwhere $\\M x_0$ is \\configFile{inputfileParameter}{matrix} and $\\alpha$ is \\config{factor}.\nThis can be used to re-add reduced reference fields before a combined estimation\nat normal equation level.\nTherefore the right hand side of the normal equations is modified by\n\\begin{equation}\n \\bar{\\M n} := \\M n + \\alpha\\,\\M N\\M x_0,\n\\end{equation}\nand the quadratic sum of observations by\n\\begin{equation}\n \\bar{\\M l^T\\M P\\M l} := \\M l^T\\M P\\M l + \\alpha^2\\,\\M x_0^T\\M N\\M x_0 + 2\\alpha\\,\\M x_0^T\\M n\n\\end{equation}\n\nAs the normal matrix itself is not modified, rewriting of the matrix can be disabled by setting\n\\config{writeNormalMatrix} to false.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief n += alpha*N*x.\n* @ingroup programsGroup */\nclass NormalsMultiplyAdd\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsMultiplyAdd, PARALLEL, \"n += alpha*N*x\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsMultiplyAdd::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outName, normalsName, xName;\n    Double   factor;\n    Bool     writeMatrix;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", outName,     Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileNormalEquation\",  normalsName, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileParameter\",       xName,       Config::MUSTSET,  \"\",    \"x\");\n    readConfig(config, \"factor\",                   factor,      Config::DEFAULT,  \"1.0\", \"alpha\");\n    readConfig(config, \"writeNormalMatrix\",        writeMatrix, Config::DEFAULT,  \"1\",   \"write full coefficient matrix, right hand sides and info files\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    logStatus<<\"init normal equations\"<<Log::endl;\n    MatrixDistributed normal;\n    Matrix n;\n    NormalEquationInfo info;\n    readFileNormalEquation(normalsName, info, normal, n, comm);\n    logInfo<<\"  number of parameters:       \"<<normal.parameterCount()<<Log::endl;\n    logInfo<<\"  number of right hand sides: \"<<info.lPl.rows()<<Log::endl;\n\n    Matrix x;\n    if(Parallel::isMaster(comm))\n    {\n      readFileMatrix(xName, x);\n      if((x.rows() != n.rows()) || (x.columns() != n.columns()))\n      {\n        std::stringstream ss;\n        ss<<\"Dimension error N(\"<<n.rows()<<\" x \"<<n.rows()<<\")*x(\"<<x.rows()<<\" x \"<<x.columns()<<\") = n(\"<<n.rows()<<\" x \"<<n.columns()<<\")\";\n        throw(Exception(ss.str()));\n      }\n    }\n\n    // ==================================\n\n    logStatus<<\"multiply normal matrix\"<<Log::endl;\n    Parallel::broadCast(x, 0, comm);\n    x *= factor;\n    Matrix Nx(x.rows(), x.columns());\n    for(UInt i=0; i<normal.blockCount(); i++)\n    {\n      if(normal.isMyRank(i,i))\n        matMult(1., normal.N(i,i), x.row(normal.blockIndex(i), normal.blockSize(i)), Nx.row(normal.blockIndex(i), normal.blockSize(i)));\n      for(UInt k=i+1; k<normal.blockCount(); k++)\n        if(normal.isMyRank(i,k))\n        {\n          matMult(1., normal.N(i,k),         x.row(normal.blockIndex(k), normal.blockSize(k)), Nx.row(normal.blockIndex(i), normal.blockSize(i)));\n          matMult(1., normal.N(i,k).trans(), x.row(normal.blockIndex(i), normal.blockSize(i)), Nx.row(normal.blockIndex(k), normal.blockSize(k)));\n        }\n    }\n    Parallel::reduceSum(Nx, 0, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      for(UInt i=0; i<info.lPl.rows(); i++)\n        info.lPl(i) += 2.*inner(x.column(i), n.column(i)) + inner(x.column(i), Nx.column(i));\n      n += Nx;\n    }\n\n    // ==================================\n\n    // write normal equations\n    // ----------------------\n    logStatus<<\"write normal equations to <\"<<outName<<\">\"<<Log::endl;\n    if((normalsName==outName) || !writeMatrix)\n    {\n      logStatus<<\"(only the information file and the right hand sides)\"<<Log::endl;\n      if(Parallel::isMaster(comm))\n        writeFileNormalEquation(outName, info, n);\n    }\n    else\n      writeFileNormalEquation(outName, info, normal, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsRegularizationBorders.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsRegularizationBorders.cpp\n*\n* @brief Two regularization matrices for inside und outside of Border.\n* The diagonal is saved as Vector.\n*\n* @author Annette Eicker\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program sets up two regularization matrices for two different regional areas.\nFor a given set of points defined by \\configClass{grid}{gridType} it is evaluated, whether each point\n(corresponding to an unknown parameter of a respective parameterization by space localizing basis functions)\nis inside or outside a certain area given by \\configClass{border}{borderType}.\nEach regularization matrix is a diagonal matrix, one of them features a one if the\npoint is inside, and a zero if the point lies outside the area. The other matrix features\na zero if the point is inside, and a one if the point lies outside the area\nThis results in two regularization matrices with\n\\begin{equation}\n\\M R_1+\\M R_2=\\M I.\n\\end{equation}\nThe two matrices are provided as vectors of the diagonal\nin the output files \\configFile{outputfileOutside}{matrix} and \\configFile{outputfileInside}{matrix}.\nThe regularization matrices are then used by \\configClass{normalEquation:regularization}{normalEquationType:regularization}.\nAs an example, the two different areas could be oceanic regions on the one hand and continental areas on the other hand.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/grid/grid.h\"\n#include \"classes/border/border.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Two regularization matrices for inside und outside of Border.\n* The diagonal is saved as Vector.\n* @ingroup programsGroup */\nclass NormalsRegularizationBorders\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsRegularizationBorders, SINGLEPROCESS, \"Two regularization matrices for inside und outside of Border\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsRegularizationBorders::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName  insideName, outsideName;\n    GridPtr   grid;\n    BorderPtr border;\n    Double    a, f;\n\n    readConfig(config, \"outputfileInside\",  insideName,  Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileOutside\", outsideName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"grid\",              grid,        Config::MUSTSET, \"\", \"nodal point distribution of parameters, e.g harmonics splines\");\n    readConfig(config, \"border\",            border,      Config::MUSTSET, \"\", \"regularization areas, e.g land and ocean\");\n    readConfig(config, \"R\",                 a,           Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates for border\");\n    readConfig(config, \"inverseFlattening\", f,           Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates for border, 0: spherical coordinates\");\n    if(isCreateSchema(config)) return;\n\n\n    Ellipsoid ellipsoid(a, f);\n    std::vector<Vector3d> points = grid->points();\n    logInfo<<\"  nodal points: \"<<points.size()<<Log::endl;\n\n    Vector  diag1(points.size()); // fill with 1 or 0\n    Vector  diag2(points.size()); // fill with 1 or 0\n\n    for(UInt k=0; k<points.size(); k++)\n    {\n      if(border->isInnerPoint(points.at(k), ellipsoid))\n        diag1(k)=1;\n      else\n        diag2(k)=1;\n    }\n\n    logStatus<<\"write diagonal matrices to file\"<<Log::endl;\n    if(!insideName.empty())\n      writeFileMatrix(insideName, diag1);\n    if(!outsideName.empty())\n      writeFileMatrix(outsideName, diag2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsRegularizationSphericalHarmonics.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsRegularizationSphericalHarmonics.cpp\n*\n* @brief Diagonal regularization matrix from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule.\n* The inverse accuracies @f$1/\\sigma_n^2@f$ are used as weights in the regularization matrix.\n* The diagonal is saved as Vector.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-08\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nDiagonal regularization matrix from gravity field accuracies,\nif not given from signal (cnm,snm), if not given from kaulas rule.\nThe inverse accuracies $1/\\sigma_n^2$ are used as weights in the regularization matrix.\nThe diagonal is saved as Vector.\n\nThe corresponding pseudo observations can be computed with \\program{Gravityfield2SphericalHarmonicsVector}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Diagonal regularization matrix from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule.\n* The inverse accuracies @f$1/\\sigma_n^2@f$ are used as weights in the regularization matrix.\n* The diagonal is saved as Vector.\n* @ingroup programsGroup */\nclass NormalsRegularizationSphericalHarmonics\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsRegularizationSphericalHarmonics, SINGLEPROCESS, \"diagonal regularization matrix from gravity field accuracies, if not given from signal (cnm,snm), if not given from kaulas rule\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsRegularizationSphericalHarmonics::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        fileNameDiagonal;\n    UInt            minRegularizationDegree = 0;\n    UInt            maxRegularizationDegree = INFINITYDEGREE;\n    UInt            minDegree, maxDegree;\n    GravityfieldPtr gravityfield;\n    SphericalHarmonicsNumberingPtr numbering;\n    Double          GM, R;\n    Bool            makeIsotropic;\n    Double          kaulaPower, kaulaFactor;\n\n    readConfig(config, \"outputfileDiagonalmatrix\", fileNameDiagonal,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"gravityfield\",             gravityfield,            Config::OPTIONAL, \"\",  \"use sigmas, if not given use signal (cnm,snm), if not given use kaulas rule\");\n    readConfig(config, \"minRegularizationDegree\",  minRegularizationDegree, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"maxRegularizationDegree\",  maxRegularizationDegree, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"minDegree\",                minDegree,               Config::MUSTSET,  \"2\", \"\");\n    readConfig(config, \"maxDegree\",                maxDegree,               Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"numbering\",                numbering,               Config::MUSTSET,  \"\",  \"numbering scheme for regul matrix\");\n    readConfig(config, \"GM\",                       GM,                      Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfig(config, \"R\",                        R,                       Config::DEFAULT,  STRING_DEFAULT_R,  \"reference radius\");\n    readConfig(config, \"makeIsotropic\",            makeIsotropic,           Config::DEFAULT,  \"0\",    \"\");\n    readConfig(config, \"kaulaPower\",               kaulaPower,              Config::DEFAULT,  \"2\",    \"sigma = kaulaFactor*degree**kaulaPower\");\n    readConfig(config, \"kaulaFactor\",              kaulaFactor,             Config::DEFAULT,  \"1e-5\", \"sigma = kaulaFactor*degree**kaulaPower\");\n    if(isCreateSchema(config)) return;\n\n    minRegularizationDegree = std::max(minRegularizationDegree, minDegree);\n    maxRegularizationDegree = std::min(maxRegularizationDegree, maxDegree);\n    Matrix cnm2(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    Matrix snm2(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n    // coefficients from gravityfield\n    // ------------------------------\n    logStatus<<\"use accuracies, if not given use signal, if not given use kaulas rule\"<<Log::endl;\n    if(gravityfield)\n    {\n      // Use variances\n      SphericalHarmonics field = gravityfield->sphericalHarmonics(Time(), maxRegularizationDegree, minRegularizationDegree, GM, R);\n      cnm2 = field.sigma2cnm();\n      snm2 = field.sigma2snm();\n      if(cnm2.size() == 0)\n        cnm2 = snm2 = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n\n      // If no variances, use signal instead\n      for(UInt n=minRegularizationDegree; n<=maxRegularizationDegree; n++)\n        for(UInt m=0; m<=n; m++)\n        {\n          if(cnm2(n,m) == 0) cnm2(n,m) = std::pow(field.cnm()(n,m),2);\n          if(snm2(n,m) == 0) snm2(n,m) = std::pow(field.snm()(n,m),2);\n        }\n    }\n\n    // Fill the rest with kaula\n    for(UInt n=minRegularizationDegree; n<=maxRegularizationDegree; n++)\n    {\n      if(cnm2(n,0)==0) cnm2(n,0) = std::pow(kaulaFactor/std::pow(n, kaulaPower), 2);\n      for(UInt m=1; m<=n; m++)\n      {\n        if(cnm2(n,m)==0) cnm2(n,m) = std::pow(kaulaFactor/std::pow(n, kaulaPower), 2);\n        if(snm2(n,m)==0) snm2(n,m) = std::pow(kaulaFactor/std::pow(n, kaulaPower), 2);\n      }\n    }\n\n    // All orders set to the mean accuracy\n    if(makeIsotropic)\n    {\n      logStatus<<\"make signals isotrop\"<<Log::endl;\n      for(UInt n=minRegularizationDegree; n<=maxRegularizationDegree; n++)\n      {\n        Double kn = 0;\n        for(UInt m=0; m<=n; m++)\n          kn += (cnm2(n,m) + snm2(n,m))/(2*n+1);\n        for(UInt m=0; m<=n; m++)\n          cnm2(n,m) = snm2(n,m) = kn;\n        snm2(n,0) = 0;\n      }\n    }\n\n    logStatus<<\"create diagonal regularization matrix\"<<Log::endl;\n    Vector regul(numbering->parameterCount(maxDegree, minDegree));\n    logInfo<<\"  parameters: \"<<regul.rows()<<Log::endl;\n    std::vector< std::vector<UInt> > idxC, idxS;\n    numbering->numbering(maxDegree, minDegree, idxC, idxS);\n    for(UInt n=minRegularizationDegree; n<=maxRegularizationDegree; n++)\n    {\n      if((idxC[n][0]!=NULLINDEX) && (cnm2(n,0)!=0)) regul(idxC[n][0]) = 1/cnm2(n,0);\n      for(UInt m=1; m<=maxRegularizationDegree; m++)\n      {\n        if((idxC[n][m]!=NULLINDEX) && (cnm2(n,m)!=0)) regul(idxC[n][m]) = 1/cnm2(n,m);\n        if((idxS[n][m]!=NULLINDEX) && (snm2(n,m)!=0)) regul(idxS[n][m]) = 1/snm2(n,m);\n      }\n    }\n\n    // write diagonal matrix\n    // ---------------------\n    logStatus<<\"write diagonal matrix to file\"<<Log::endl;\n    writeFileMatrix(fileNameDiagonal, regul);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsReorder.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsReorder.cpp\n*\n* @brief Reorder normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @author Sebastian Strasser\n* @date 2011-02-15\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nReorder \\configFile{inputfileNormalEquation}{normalEquation} by selecting parameters in a specific order.\nThe \\configClass{parameterSelection}{parameterSelectorType} also allows one to change dimension of the normal equations,\neither by cutting parameters or by inserting zero rows/columns for additional parameters.\nWithout \\configClass{parameterSelection}{parameterSelectorType} the order of parameters remains the same.\nAdditionally the block sizes of the files can be adjusted. If \\config{outBlockSize} is set to zero,\nthe normal matrix is written to a single block file, which is needed by some programs.\n\nTo eliminate parameters without changing the result of the other parameters use \\program{NormalsEliminate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Reorder normal equations.\n* @ingroup programsGroup */\nclass NormalsReorder\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsReorder, PARALLEL, \"Reorder normal equations\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsReorder::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outName, inName;\n    ParameterSelectorPtr parameterSelector;\n    UInt     blockSize;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", outName,           Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileNormalEquation\",  inName,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"parameterSelection\",       parameterSelector, Config::OPTIONAL, \"\",     \"parameter order/selection of output normal equations\");\n    readConfig(config, \"outBlockSize\",             blockSize,         Config::DEFAULT,   \"2048\", \"block size for distributing the normal equations, 0: one block\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    logStatus<<\"init normal equations\"<<Log::endl;\n    MatrixDistributed normal;\n    Matrix rhs;\n    NormalEquationInfo info;\n    readFileNormalEquation(inName, info, normal, rhs, comm);\n\n    std::vector<UInt> indexVector(normal.parameterCount());\n    if(parameterSelector)\n      indexVector = parameterSelector->indexVector(info.parameterName);\n    else\n      std::iota(indexVector.begin(), indexVector.end(), 0);\n\n    logInfo<<\"  number of unknown parameters (old): \"<<normal.parameterCount()<<Log::endl;\n    logInfo<<\"  number of unknown parameters (new): \"<<indexVector.size()<<Log::endl;\n    logInfo<<\"  number of right hand sides:         \"<<info.lPl.rows()<<Log::endl;\n\n    logStatus<<\"reorder normal matrix\"<<Log::endl;\n    normal.reorder(indexVector, MatrixDistributed::computeBlockIndex(indexVector.size(), blockSize));\n    rhs = reorder(rhs, indexVector);\n    std::vector<ParameterName> parameterNames(indexVector.size());\n    for(UInt i = 0; i < indexVector.size(); i++)\n      parameterNames.at(i) = (indexVector.at(i) != NULLINDEX ? info.parameterName.at(indexVector.at(i)) : ParameterName());\n\n    logStatus<<\"write normal equations to <\"<<outName<<\">\"<<Log::endl;\n    writeFileNormalEquation(outName, NormalEquationInfo(parameterNames, info.lPl, info.observationCount), normal, rhs);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsReorderAndAccumulate.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsReorderAndAccumulate.cpp\n*\n* @brief Accumulate normal equations and write it to file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2025-10-30\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program accumulates \\configFile{inputfileNormalEquation}{normalEquation}s with respect\nto the parameter names and writes the total combined system to \\configFile{outputfileNormalequation}{normalEquation}.\n\nThe combined normal equation is extended to include all parameter names uniquely from all input normals.\nThe input normals are sorted so that parameters with the same name are accumulated.\nThis requires that the names in each normal equation are unique.\n\nThe output can be written as multiple small block files with \\config{outBlockSize},\nor as single block with \\config{outBlockSize}=0,\nor blocked with respect to the first part of the parameter names (object), if \\config{outBlockSize} left empty.\n\nSee also \\program{NormalsBuild} and \\program{NormalsAccumulate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"files/fileParameterName.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Accumulate normal equations and write it to file.\n* @ingroup programsGroup */\nclass NormalsReorderAndAccumulate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsReorderAndAccumulate, PARALLEL, \"accumulate normal equations and write to file\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsReorderAndAccumulate::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut;\n    std::vector<FileName> fileNamesInAll;\n    UInt     blockSize = NULLINDEX;\n\n    readConfig(config, \"outputfileNormalEquation\", fileNameOut,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileNormalEquation\",  fileNamesInAll, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outBlockSize\",             blockSize,      Config::OPTIONAL, \"2048\", \"block size for distributing the normal equations, 0: one block, empty: blocking by objects\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    logStatus<<\"read normal equations info\"<<Log::endl;\n    std::vector<FileName>      fileNamesIn;\n    std::vector<ParameterName> parameterNames;\n    std::set<ParameterName>    sortedNames;\n    UInt                       rhsCount = 0;\n\n    Single::forEach(fileNamesInAll.size(), [&](UInt i)\n    {\n      Matrix rhs;\n      NormalEquationInfo info;\n      try\n      {\n        readFileNormalEquation(fileNamesInAll.at(i), info, rhs);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        return;\n      }\n\n      fileNamesIn.push_back(fileNamesInAll.at(i));\n      rhsCount = std::max(rhsCount, info.lPl.size());\n      for(const auto &parameterName : info.parameterName)\n        if(sortedNames.find(parameterName) == sortedNames.end())\n        {\n          sortedNames.insert(parameterName);\n          parameterNames.push_back(parameterName);\n        }\n    });\n\n    logInfo<<\"  number of unknown parameters (new): \"<<parameterNames.size()<<Log::endl;\n    logInfo<<\"  number of right hand sides:         \"<<rhsCount<<Log::endl;\n    if(!parameterNames.size())\n      return;\n\n    // ==================================\n\n    std::vector<UInt> blockIndex;\n    if(blockSize != NULLINDEX)\n    {\n      blockIndex = MatrixDistributed::computeBlockIndex(parameterNames.size(), blockSize);\n    }\n    else\n    {\n      std::stable_sort(parameterNames.begin(), parameterNames.end(), [](auto &p1, auto &p2){return p1.object < p2.object;});\n      blockIndex.push_back(0);\n      auto blockObject = parameterNames.front().object;\n      for(UInt i=0; i<parameterNames.size(); i++)\n        if(parameterNames.at(i).object != blockObject)\n        {\n          blockIndex.push_back(i);\n          blockObject = parameterNames.at(i).object;\n        }\n      blockIndex.push_back(parameterNames.size());\n    }\n    logInfo<<\"  number of blocks:                   \"<<blockIndex.size()-1<<Log::endl;\n\n    // ==================================\n\n    logStatus<<\"accumulate normals\"<<Log::endl;\n    MatrixDistributed  normalsSum;\n    Matrix             rhsSum(blockIndex.back(), rhsCount);\n    Vector             lPl(rhsCount);\n    UInt               observationCount = 0;\n    normalsSum.initEmpty(blockIndex, comm);\n    // write parameter name file\n    writeFileParameterName(fileNameOut.replaceFullExtension(\".parameterNames.txt\"), parameterNames);\n\n    Single::forEach(fileNamesIn.size(), [&](UInt idxFile)\n    {\n      MatrixDistributed  normals;\n      Matrix             rhs;\n      NormalEquationInfo info;\n      try\n      {\n        readFileNormalEquation(fileNamesIn.at(idxFile), info, normals, rhs, comm);\n      }\n      catch(std::exception &e)\n      {\n        logWarning<<e.what()<<\" continue...\"<<Log::endl;\n        return;\n      }\n\n      // create index vector and reorder\n      std::vector<UInt>  indexVector;\n      auto iter = info.parameterName.begin(); // assume ordered list to accelerate search\n      for(const auto &name : parameterNames)\n      {\n        iter = std::find(iter, info.parameterName.end(), name);\n        if(iter == info.parameterName.end()) // not found? -> restart search from begin\n          iter = std::find(info.parameterName.begin(), info.parameterName.end(), name);\n        indexVector.push_back((iter != info.parameterName.end()) ? std::distance(info.parameterName.begin(), iter) : NULLINDEX);\n      }\n      normals.reorder(indexVector, blockIndex);\n      rhs = reorder(rhs, indexVector);\n\n      // accumulate\n      rhsSum.column(0, rhs.columns()) += rhs;\n      lPl.row(0, rhs.columns())       += info.lPl;\n      observationCount                += info.observationCount;\n      for(UInt i=0; i<normals.blockCount(); i++)\n        for(UInt k=i; k<normals.blockCount(); k++)\n          if(normals.isMyRank(i, k))\n          {\n            normalsSum.setBlock(i, k);\n            normalsSum.N(i, k) += normals.N(i, k);\n          }\n    });\n\n    // ==================================\n\n    logStatus<<\"write normal equations to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameOut, NormalEquationInfo(parameterNames, lPl, observationCount), normalsSum, rhsSum);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsScale.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsScale.cpp\n*\n* @brief Scales rows and columns of a normal equation system.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-02-23\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nScales rows and columns of a system of \\configFile{inputfileNormalEquation}{normalEquation}\ngiven by a diagonal matrix \\configFile{inputfileFactorVector}{matrix} $\\M S$\n\\begin{equation}\n  \\bar{\\M N} := \\M S \\M N \\M S \\qquad\\text{and}\\qquad \\bar{\\M n} := \\M S \\M n.\n\\end{equation}\nThe estimated solution is now\n\\begin{equation}\n  \\bar{\\M x} := \\M S^{-1} \\M x.\n\\end{equation}\nThis is effectively the same as rescaling columns of the design matrix.\nThis program is useful when combining normal equations from different sources,\nfor example in case the units of certain parameters don't match.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Scales rows and columns of a normal equation system.\n* @ingroup programsGroup */\nclass NormalsScale\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsScale, PARALLEL, \"Scales rows and columns of a normal equation system\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsScale::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outName, normalsName, factorName;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", outName,     Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileNormalEquation\",  normalsName, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileFactorVector\",    factorName,  Config::MUSTSET, \"\", \"Vector containing the factors\");\n    if(isCreateSchema(config)) return;\n\n    // ==================================\n\n    logStatus<<\"read normal equations <\"<<outName<<\">\"<<Log::endl;\n    MatrixDistributed normal;\n    Matrix n;\n    NormalEquationInfo info;\n    readFileNormalEquation(normalsName, info, normal, n, comm);\n    logInfo<<\"  number of parameters:       \"<<normal.parameterCount()<<Log::endl;\n    logInfo<<\"  number of right hand sides: \"<<info.lPl.rows()<<Log::endl;\n\n    logStatus<<\"read factor vector <\"<<factorName<<\">\"<<Log::endl;\n    Vector factor;\n    readFileMatrix(factorName, factor);\n\n    if(Parallel::isMaster(comm) && (factor.rows() != n.rows()))\n      throw(Exception(\"Dimension error factor(\"+factor.rows()%\"%i) != n(\"s+n.rows()%\"%i)\"s));\n\n    // ==================================\n\n    logStatus<<\"scale normal matrix\"<<Log::endl;\n    for(UInt i=0; i<normal.blockCount(); i++)\n      for(UInt k=i; k<normal.blockCount(); k++)\n        if(normal.isMyRank(i,k))\n        {\n          Matrix &N = normal.N(i,k);\n          for(UInt z=0; z<N.rows(); z++)\n            N.row(z) *= factor(z+normal.blockIndex(i));\n          for(UInt s=0; s<N.columns(); s++)\n            N.column(s) *= factor(s+normal.blockIndex(k));\n        }\n\n    if(Parallel::isMaster(comm))\n      for(UInt z=0; z<n.rows(); z++)\n        n.row(z) *= factor(z)*factor(z);\n\n    // ==================================\n\n    // write normal equations\n    // ----------------------\n    logStatus<<\"write normal equations to <\"<<outName<<\">\"<<Log::endl;\n    writeFileNormalEquation(outName, info, normal, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsSolverVCE.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsSolverVCE.cpp\n*\n* @brief solve normal equations.\n* Using cholesky decomposition.\n* Relative weighting of different normal equations by variance component estimation (VCE).\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-03-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program accumulates \\configClass{normalEquation}{normalEquationType}\nand solves the total combined system.\nThe relative weigthing between the individual normals is determined iteratively\nby means of variance component estimation (VCE). For a detailed description\nof the used algorithm see \\configClass{normalEquation}{normalEquationType}.\n\nBesides the estimated parameter vector (\\configFile{outputfileSolution}{matrix}) the\nestimated accuracies (\\configFile{outputfileSigmax}{matrix}) and the full covariance matrix\n(\\configFile{outputfileCovariance}{matrix}) can be saved. Also the combined normal system\ncan be written to \\configFile{outputfileNormalEquation}{normalEquation}.\n\nThe \\configFile{outputfileContribution}{matrix} is a matrix with rows for each estimated\nparameter and columns for each \\configClass{normalEquation}{normalEquationType}\nand indicates the contribution of the individual normals to the estimated parameters.\nEach row sum up to one.\n\nSee also \\program{NormalsBuild}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/normalEquation/normalEquation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Solve normal equations.\n* Using cholesky decomposition.\n* relative weighting of different normal equations by variance component estimation (VCE).\n* @ingroup programsGroup */\nclass NormalsSolverVCE\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsSolverVCE, PARALLEL, \"solve normal equations (relative weighting by variance component estimation (VCE))\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsSolverVCE::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          fileNameSolution, fileNameSigmax;\n    FileName          fileNameCovariance, fileNameNormals, fileNameContribution, fileNameVarianceFactors;\n    NormalEquationPtr normals;\n    FileName          fileNameX0;\n    UInt              rhsNo;\n    UInt              maxIter;\n    UInt              blockSize;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"normalequation\",           \"normalEquation\",           date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileSolution\",        fileNameSolution,        Config::OPTIONAL, \"\",     \"parameter vector\");\n    readConfig(config, \"outputfileSigmax\",          fileNameSigmax,          Config::OPTIONAL, \"\",     \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n    readConfig(config, \"outputfileCovariance\",      fileNameCovariance,      Config::OPTIONAL, \"\",     \"full covariance matrix\");\n    readConfig(config, \"outputfileContribution\",    fileNameContribution,    Config::OPTIONAL, \"\",     \"contribution of normal system components to the solution vector\");\n    readConfig(config, \"outputfileVarianceFactors\", fileNameVarianceFactors, Config::OPTIONAL, \"\",     \"estimated variance factors as vector\");\n    readConfig(config, \"outputfileNormalEquation\",  fileNameNormals,         Config::OPTIONAL, \"\",     \"the combined normal equation system\");\n    readConfig(config, \"normalEquation\",            normals,                 Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"inputfileApproxSolution\",   fileNameX0,              Config::OPTIONAL, \"\",     \"to accelerate convergence\");\n    readConfig(config, \"rightHandSideNumberVCE\",    rhsNo,                   Config::DEFAULT,  \"0\",    \"the right hand side number for estimation of variance factors\");\n    readConfig(config, \"normalsBlockSize\",          blockSize,               Config::DEFAULT,  \"2048\", \"block size for distributing the normal equations, 0: one block\");\n    readConfig(config, \"maxIterationCount\",         maxIter,                 Config::DEFAULT,  \"20\",   \"maximum number of iterations for variance component estimation\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"init normal equations\"<<Log::endl;\n    normals->init(blockSize, comm);\n    logInfo<<\"  number of unknown parameters: \"<<normals->parameterCount()<<Log::endl;\n    logInfo<<\"  number of right hand sides:   \"<<normals->rightHandSideCount()<<Log::endl;\n\n    // set approximate solution\n    // ------------------------\n    if(!fileNameX0.empty())\n    {\n      logStatus<<\"read approximate solution <\"<<fileNameX0<<\">\"<<Log::endl;\n      Matrix x0;\n      readFileMatrix(fileNameX0, x0);\n      normals->setApproximateSolution(x0);\n    }\n\n    // Iteration\n    // ---------\n    Bool ready = FALSE;\n    if(maxIter<1) maxIter = 1; // at least one step\n    for(UInt iter=0; (iter<maxIter)&&(!ready); iter++)\n    {\n      logStatus<<iter+1<<\". iteration step\"<<Log::endl;\n\n      logStatus<<\"accumulate normal equations\"<<Log::endl;\n      ready = normals->build(rhsNo);\n      logInfo<<\"  observation count = \"<<normals->observationCount()<<Log::endl;\n\n      if(!fileNameNormals.empty())\n      {\n        logStatus<<\"write normal equations to file <\"<<fileNameNormals<<\">\"<<Log::endl;\n        normals->write(fileNameNormals);\n      }\n\n      Vector sigmas = normals->varianceComponentFactors();\n      if(Parallel::isMaster(comm))\n      {\n        for (UInt i=0; i<sigmas.rows(); i++)\n          sigmas(i) = std::sqrt(sigmas(i));\n        constexpr UInt maxCount = 20;\n        logInfo<<\"  applied variance factors\"<<Log::endl;\n        for(UInt i=0; i<std::min(maxCount-2, sigmas.rows()); i++)\n          logInfo<<\"    \"<<i+1<<\": sigma = \"<<sigmas(i)<<Log::endl;\n        if(sigmas.rows()>maxCount)\n          logInfo<<\"    \"<<maxCount-1<<\": sigma = ...\"<<Log::endl;\n        if(sigmas.rows()>=maxCount-2)\n        {\n          logInfo<<\"    \"<<sigmas.rows()-1<<\": sigma = \"<<sigmas(sigmas.rows()-2)<<Log::endl;\n          logInfo<<\"    \"<<sigmas.rows()  <<\": sigma = \"<<sigmas(sigmas.rows()-1)<<Log::endl;\n        }\n\n        if(!fileNameVarianceFactors.empty())\n        {\n          logStatus<<\"write variance factors to <\"<<fileNameVarianceFactors<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameVarianceFactors, sigmas);\n        }\n      }\n\n      logStatus<<\"solve normal equations\"<<Log::endl;\n      Matrix x = normals->solve();\n      logInfo<<\"  sigma (total) = \"<<normals->aposterioriSigma()<<Log::endl;\n\n      if(Parallel::isMaster(comm) && !fileNameSolution.empty())\n      {\n        logStatus<<\"write solution to <\"<<fileNameSolution<<\">\"<<Log::endl;\n        writeFileMatrix(fileNameSolution, x);\n      }\n    } // for(iter)\n\n    // Inverse\n    if(!fileNameSigmax.empty())\n    {\n      logStatus<<\"inverte cholesky matrix and write standard deviations to <\"<<fileNameSigmax<<\">\"<<Log::endl;\n      Vector sigmax = normals->sigmaParameter();\n      if(Parallel::isMaster(comm))\n        writeFileMatrix(fileNameSigmax, sigmax);\n    }\n\n    // Covariance matrix\n    if(!fileNameCovariance.empty())\n    {\n      logStatus<<\"compute covariance matrix and write to <\"<<fileNameCovariance<<\">\"<<Log::endl;\n      normals->writeCovariance(fileNameCovariance);\n    }\n\n    // contributions\n    if(!fileNameContribution.empty())\n    {\n      logStatus<<\"compute contributions and write to <\"<<fileNameContribution<<\">\"<<Log::endl;\n      Matrix contrib = normals->contribution();\n      if(Parallel::isMaster(comm))\n        writeFileMatrix(fileNameContribution, contrib);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/normalsTemporalCombination.cpp",
    "content": "/***********************************************/\n/**\n* @file normalsTemporalCombination.cpp\n*\n* @brief Normal equations of trend, annual from a time series of normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2016-03-03\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program reads a times series of \\configFile{inputfileNormalequation}{normalEquation}\nwith asscociated \\configClass{timeSeries}{timeSeriesType} and setup a new combined normal equation system.\nFor each parameter a \\configClass{parametrizationTemporal}{parametrizationTemporalType} is used.\n\nIt can be used to estimate trend and annual spherical harmonic coefficients from monthly GRACE normal equations.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Normal equations of trend, annual from a time series of normal equations.\n* @ingroup programsGroup */\nclass NormalsTemporalCombination\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NormalsTemporalCombination, PARALLEL, \"normal equations of trend, annual from a time series of normal equations\", NormalEquation)\n\n/***********************************************/\n\nvoid NormalsTemporalCombination::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName                   fileNameOut;\n    std::vector<FileName>      fileNameIn;\n    ParametrizationTemporalPtr temporal;\n    TimeSeriesPtr              timeSeries;\n\n    renameDeprecatedConfig(config, \"outputfileNormalequation\", \"outputfileNormalEquation\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"temporalRepresentation\", \"parametrizationTemporal\", date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNormalEquation\", fileNameOut, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileNormalEquation\",  fileNameIn,  Config::MUSTSET, \"\", \"normal equations for each point in time\");\n    readConfig(config, \"timeSeries\",               timeSeries,  Config::MUSTSET, \"\", \"times of each normal equations\");\n    readConfig(config, \"parametrizationTemporal\",  temporal,    Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    // Create time series\n    // ------------------\n    std::vector<Time> times  = timeSeries->times();\n    if(times.size() != fileNameIn.size())\n      throw(Exception(\"fileCount(\"+fileNameIn.size()%\"%i) != timeCount(\"s+times.size()%\"%i)-1\"s));\n\n    // =============================================\n\n    // read normal equations\n    // ---------------------\n    logStatus<<\"read normal equations\"<<Log::endl;\n    MatrixDistributed  normal;\n    Matrix             nTotal;\n    NormalEquationInfo infoTotal;\n\n    Single::forEach(times.size(), [&](UInt idEpoch)\n    {\n      // read normals\n      // ------------\n      Matrix N, n;\n      NormalEquationInfo info;\n      try\n      {\n        readFileNormalEquation(fileNameIn.at(idEpoch), info, N, n);\n      }\n      catch(std::exception &e)\n      {\n        logWarningOnce<<e.what()<<\" continue...\"<<Log::endl;\n        return;\n      }\n\n      // init normals\n      // ------------\n      const Vector factorTemporal = temporal->factors(times.at(idEpoch));\n      if(normal.parameterCount()==0)\n      {\n        std::vector<UInt> blockIndex(factorTemporal.size()+1);\n        for(UInt i=0; i<=factorTemporal.rows(); i++)\n          blockIndex.at(i) = i*N.rows();\n        normal.initEmpty(blockIndex, comm);\n        nTotal = Matrix(normal.parameterCount(), n.columns());\n        infoTotal.lPl = Vector(n.columns());\n      }\n\n      // test dimension\n      // --------------\n      if((n.rows() != normal.blockSize(0)) || (n.columns() != nTotal.columns()))\n        throw(Exception(\"Normal equation dimension mismatch\"));\n\n      // parameter names\n      // ---------------\n      if(!infoTotal.parameterName.size())\n        infoTotal.parameterName = info.parameterName;\n      else\n        for(UInt i=0; i<infoTotal.parameterName.size(); i++)\n          if(!infoTotal.parameterName.at(i).combine(info.parameterName.at(i)))\n            logWarning<<\"Parameter names do not match at index \"<<i<<\": '\"<<infoTotal.parameterName.at(i).str()<<\"' != '\"<< info.parameterName.at(i).str()<<\"'\"<< Log::endl;\n\n      // setup normal matrix\n      // -------------------\n      fillSymmetric(N);\n      for(UInt i=0; i<normal.blockCount(); i++)\n        for(UInt k=i; k<normal.blockCount(); k++)\n          if(factorTemporal(i) != 0 && factorTemporal(k) != 0)\n          {\n            normal.setBlock(i, k);\n\n            if(normal.isMyRank(i,k))\n              axpy(factorTemporal(i)*factorTemporal(k), N, normal.N(i,k));\n          }\n\n      if(Parallel::isMaster(comm))\n      {\n        for(UInt i=0; i<normal.blockCount(); i++)\n          axpy(factorTemporal(i), n, nTotal.row(normal.blockIndex(i), normal.blockSize(i)));\n        infoTotal.observationCount += info.observationCount;\n        infoTotal.lPl += info.lPl;\n      }\n    });\n\n    // =============================================\n\n    // adjust parameter names based on temporal representation\n    // -------------------------------------------------------\n    std::vector<ParameterName> baseName;\n    std::swap(infoTotal.parameterName, baseName);\n    temporal->parameterName(baseName, infoTotal.parameterName);\n\n    // write normal equations\n    // ----------------------\n    logStatus<<\"write normal equations to <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameOut, infoTotal, normal, nTotal);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/parameterNamesCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file parameterNamesCreate.cpp\n*\n* @brief Generate a parameter names file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2019-09-28\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nGenerate a \\configFile{outputfileParameterNames}{parameterName} by \\configClass{parameterName}{parameterNamesType}.\nThis file can be used in \\program{NormalsCreate} or in the class \\configClass{parameterSelector}{parameterSelectorType}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parameterNames/parameterNames.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate a parameter names file.\n* @ingroup programsGroup */\nclass ParameterNamesCreate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ParameterNamesCreate, SINGLEPROCESS, \"Generate a parameter names file.\", NormalEquation)\n\n/***********************************************/\n\nvoid ParameterNamesCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          fileNameParameterNames;\n    ParameterNamesPtr parameterNames;\n\n    readConfig(config, \"outputfileParameterNames\", fileNameParameterNames, Config::MUSTSET, \"\", \"output parameter names file\");\n    readConfig(config, \"parameterName\",            parameterNames,         Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"writing parameter names file <\"<<fileNameParameterNames<<\">\"<<Log::endl;\n    writeFileParameterName(fileNameParameterNames, parameterNames->parameterNames());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/normals/parameterSelection2IndexVector.cpp",
    "content": "/***********************************************/\n/**\n* @file parameterSelection2IndexVector.cpp\n*\n* @brief Generate index vector from parameter selection.\n*\n* @author Sebastian Strasser\n* @date 2018-05-18\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nGenerate index vector from parameter selection in \\file{matrix format}{matrix}.\nThis vector can be used in \\program{MatrixCalculate}\nwith \\configClass{matrix:reorder}{matrixGeneratorType:reorder}\nto reorder arbitrary vectors and matrices similar to \\program{NormalsReorder}.\n\nThe \\configClass{parameterSelection}{parameterSelectorType} allows reordering and dimension changes,\neither by cutting parameters or by inserting additional parameters.\n\\configFile{outputfileIndexVector}{matrix} contains indices of parameters in\n\\configFile{inputfileParameterNames}{parameterName} or -1 for newly added parameters.\n\\configFile{outputfileParameterNames}{parameterName} contains the selected parameter names.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate index vector from parameter selection.\n* @ingroup programsGroup */\nclass ParameterSelection2IndexVector\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(ParameterSelection2IndexVector, SINGLEPROCESS, \"Generate index vector from parameter selection.\", NormalEquation)\nGROOPS_RENAMED_PROGRAM(NormalsParameterSelection2IndexVector, ParameterSelection2IndexVector, date2time(2018, 7, 4))\n\n/***********************************************/\n\nvoid ParameterSelection2IndexVector::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameIndexVector, fileNameParameterNamesOut, fileNameParameterNamesIn;\n    ParameterSelectorPtr selector;\n\n    readConfig(config, \"outputfileIndexVector\",    fileNameIndexVector,       Config::OPTIONAL,  \"\", \"indices of source parameters in target normal equations\");\n    readConfig(config, \"outputfileParameterNames\", fileNameParameterNamesOut, Config::OPTIONAL,  \"\", \"output parameter names file\");\n    readConfig(config, \"inputfileParameterNames\",  fileNameParameterNamesIn,  Config::MUSTSET,   \"\", \"parameter names file of source normal equations\");\n    readConfig(config, \"parameterSelection\",       selector,                  Config::MUSTSET,   \"\", \"parameter order/selection of target normal equations\");\n    if(isCreateSchema(config)) return;\n\n    std::vector<ParameterName> parameterNames;\n    readFileParameterName(fileNameParameterNamesIn, parameterNames);\n    const std::vector<UInt> indexVector = selector->indexVector(parameterNames);\n\n    if(!fileNameIndexVector.empty())\n    {\n      Vector vector(indexVector.size());\n      for(UInt i = 0; i < indexVector.size(); i++)\n        vector(i) = (indexVector.at(i) != NULLINDEX ? static_cast<Double>(indexVector.at(i)) : -1);\n\n      logStatus<<\"writing index vector <\"<<fileNameIndexVector<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameIndexVector, vector);\n    }\n\n    if(!fileNameParameterNamesOut.empty())\n    {\n      std::vector<ParameterName> parameterNamesOut(indexVector.size());\n      for(UInt i = 0; i < indexVector.size(); i++)\n        if(indexVector.at(i) != NULLINDEX)\n          parameterNamesOut.at(i) = parameterNames.at(indexVector.at(i));\n\n      logStatus<<\"writing parameter names file <\"<<fileNameParameterNamesOut<<\">\"<<Log::endl;\n      writeFileParameterName(fileNameParameterNamesOut, parameterNamesOut);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2ArgumentOfLatitude.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2ArgumentOfLatitude.cpp\n*\n* @brief Computes argument of latitude.\n*\n* @author Torsten Mayer-Guerr\n* @date 2016-07-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the argument of latitude of an \\file{orbit}{instrument}\nand writes it as \\file{instrument file}{instrument} (MISCVALUE(S)).\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n\n\\fig{!hb}{0.8}{instrumentOrbit2ArgumentOfLatitude}{fig:instrumentOrbit2ArgumentOfLatitude}{Derivation filtered GRACE range-rate residuals.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/planets.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Argument of latitude.\n* @ingroup programsGroup */\nclass Orbit2ArgumentOfLatitude\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2ArgumentOfLatitude, PARALLEL, \"Argument of latitude.\", Orbit, Instrument)\nGROOPS_RENAMED_PROGRAM(InstrumentOrbit2ArgumentOfLatitude, Orbit2ArgumentOfLatitude, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid Orbit2ArgumentOfLatitude::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n\n    readConfig(config, \"outputfileArgOfLatitude\", fileNameOut,         Config::MUSTSET,  \"\", \"instrument file (MISCVALUE(S): argLat, ...)\");\n    readConfig(config, \"inputfileOrbit\",          fileNameOrbit,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",     fileNamesInstrument, Config::OPTIONAL, \"\", \"data are appended\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"computing argument of latitude\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    UInt dataCount = 2;  // time, arg\n    std::vector<InstrumentFilePtr> instrumentFile;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      instrumentFile.push_back(InstrumentFile::newFile(fileName));\n      InstrumentFile::checkArcCount({orbitFile, *instrumentFile.back()});\n      dataCount += instrumentFile.back()->dataCount(TRUE/*mustDefined*/);\n    }\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      const OrbitArc orbit = orbitFile.readArc(arcNo);\n      Matrix A(orbit.size(), dataCount);\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        if(orbit.at(i).velocity.r()==0)\n          throw(Exception(\"no velocity given\"));\n        const Vector3d z = normalize(crossProduct(orbit.at(i).position, orbit.at(i).velocity));\n        const Vector3d x = normalize(crossProduct(Vector3d(0,0,1), z));\n        const Vector3d y = crossProduct(z, x);\n        A(i, 1) = atan2(inner(orbit.at(i).position,y), inner(orbit.at(i).position, x)); // Argument of latitude of satellite\n      }\n\n      UInt idx = 2;\n      for(auto &file: instrumentFile)\n      {\n        Arc arc = file->readArc(arcNo);\n        Arc::checkSynchronized({orbit, arc});\n        Matrix B = arc.matrix();\n        copy(B.column(1, B.columns()-1), A.column(idx, B.columns()-1));\n        idx += B.columns()-1;\n      }\n\n      return Arc(orbit.times(), A);\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write argument of latitude to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2BetaPrimeAngle.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2BetaPrimeAngle.cpp\n*\n* @brief Computes beta prime angle.\n*\n* @author Beate Klinger\n* @author Norbert Zehentner\n* @date 2016-08-01\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the beta prime angle (between the orbital plane and earth-sun direction)\nand writes it as MISCVALUE(S) \\file{instrument file}{instrument}. The angle is calculated w.r.t the sun (per default),\nbut can be changed.\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Beta prime angle.\n* @ingroup programsGroup */\nclass Orbit2BetaPrimeAngle\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2BetaPrimeAngle, PARALLEL, \"Beta prime angle\", Orbit, Instrument)\nGROOPS_RENAMED_PROGRAM(InstrumentOrbit2BetaPrimeAngle, Orbit2BetaPrimeAngle, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid Orbit2BetaPrimeAngle::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n    EphemeridesPtr        ephemerides;\n    Ephemerides::Planet   planet;\n    std::string           choice;\n\n    readConfig(config, \"outputfileBetaAngle\", fileNameOut,         Config::MUSTSET,  \"\",    \"instrument file (MISCVALUE(S): beta', ...)\");\n    readConfig(config, \"inputfileOrbit\",      fileNameOrbit,       Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileInstrument\", fileNamesInstrument, Config::OPTIONAL, \"\",    \"data are appended\");\n    readConfig(config, \"ephemerides\",         ephemerides,         Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"planet\",              planet,              Config::DEFAULT,  \"sun\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"computing beta prime angle\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    UInt dataCount = 2;  // time, beta\n    std::vector<InstrumentFilePtr> instrumentFile;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      instrumentFile.push_back(InstrumentFile::newFile(fileName));\n      InstrumentFile::checkArcCount({orbitFile, *instrumentFile.back()});\n      dataCount += instrumentFile.back()->dataCount(TRUE/*mustDefined*/);\n    }\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      const OrbitArc orbit = orbitFile.readArc(arcNo);\n      Matrix A(orbit.size(), dataCount);\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        if(orbit.at(i).velocity.r()==0)\n          throw(Exception(\"no velocity given\"));\n        const Vector3d planetPos = normalize(ephemerides->position(orbit.at(i).time, planet)); // direction from central-body to planet (earth-sun direction)\n        A(i, 1) = std::acos(inner(normalize(crossProduct(normalize(orbit.at(i).velocity), normalize(orbit.at(i).position))), planetPos)) - PI/2;\n      }\n\n      UInt idx = 2;\n      for(auto &file: instrumentFile)\n      {\n        Arc arc = file->readArc(arcNo);\n        Arc::checkSynchronized({orbit, arc});\n        Matrix B = arc.matrix();\n        copy(B.column(1, B.columns()-1), A.column(idx, B.columns()-1));\n        idx += B.columns()-1;\n      }\n\n      return Arc(orbit.times(), A);\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write beta prime angle to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2EarthFixedOrbit.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2EarthFixedOrbit.cpp\n*\n* @brief Rotate an orbit into a rotation earth fixed frame.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-12-07\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nNormally the orbits in GROOPS are given in the celestial reference frame (CRF) with the\norigin in the center of mass (CoM). This program rotates the orbit with\n\\configClass{earthRotation}{earthRotationType} from CRF to the TRF.\n\nTo additionally tranform into the center of solid Earth (CE) frame (or center of Figure (CF)),\na correction can be applied by providing degree one coefficients of a\n\\configClass{gravityfield}{gravityfieldType} (e.g. ocean tides).\n\nIf \\config{celestial2terrestrial} is set to no, the inverse transformation is applied.\n\nSee also \\program{InstrumentRotate}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Rotate an orbit into a rotation earth fixed frame.\n* @ingroup programsGroup */\nclass Orbit2EarthFixedOrbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2EarthFixedOrbit, PARALLEL, \"rotate an orbit into a rotation earth fixed frame\", Orbit)\n\n/***********************************************/\n\nvoid Orbit2EarthFixedOrbit::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameOut, fileNameIn;\n    EarthRotationPtr earthRotation;\n    GravityfieldPtr  gravityfield;\n    Bool             crf2trf;\n\n    readConfig(config, \"outputfileOrbit\",       fileNameOut,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",        fileNameIn,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",         earthRotation, Config::MUSTSET,  \"\", \"transformation from CRF to TRF\");\n    readConfig(config, \"gravityfield\",          gravityfield,  Config::DEFAULT,  R\"([{\"tides\": {\"tides\": {\"doodsonHarmonicTide\": {\"minDegree\":1, \"maxDegree\":1}}}}])\", \"degree 1 fluid mantle for CM2CE correction\");\n    readConfig(config, \"celestial2terrestrial\", crf2trf,       Config::DEFAULT,  \"1\", \"yes: crf->trf, no: trf->crf\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read orbit file <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameIn);\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      OrbitArc orbit = orbitFile.readArc(arcNo);\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        const SphericalHarmonics harmonics = gravityfield->sphericalHarmonics(orbit.at(i).time, 1, 1);\n        const Vector coeff = harmonics.x(); // [c00, c10, c11, s11]\n        const Vector3d cm2ceCorrection = std::sqrt(3.) * harmonics.R() * Vector3d(coeff(2), coeff(3), coeff(1));\n        const Rotary3d rot = earthRotation->rotaryMatrix(orbit.at(i).time);;\n\n        if(crf2trf)\n        {\n          orbit.at(i).position = rot.rotate(orbit.at(i).position) + cm2ceCorrection;\n          if(orbit.at(i).velocity.r() > 0)\n          {\n            const Vector3d omega = rot.rotate(earthRotation->rotaryAxis(orbit.at(i).time));\n            orbit.at(i).velocity = rot.rotate(orbit.at(i).velocity) - crossProduct(omega, orbit.at(i).position);\n            if(orbit.at(i).acceleration.r() > 0)\n              orbit.at(i).acceleration = rot.rotate(orbit.at(i).acceleration)\n                                       - crossProduct(omega, crossProduct(omega, orbit.at(i).position))\n                                       - 2*crossProduct(omega, orbit.at(i).velocity);\n          }\n        }\n        else\n        {\n          if(orbit.at(i).velocity.r() > 0)\n          {\n            const Vector3d omega = rot.rotate(earthRotation->rotaryAxis(orbit.at(i).time));\n            if(orbit.at(i).acceleration.r() > 0)\n              orbit.at(i).acceleration = rot.inverseRotate(orbit.at(i).acceleration\n                                                        + crossProduct(omega, crossProduct(omega, orbit.at(i).position))\n                                                        + 2*crossProduct(omega, orbit.at(i).velocity));\n            orbit.at(i).velocity = rot.inverseRotate(orbit.at(i).velocity + crossProduct(omega, orbit.at(i).position));\n          }\n          orbit.at(i).position = rot.inverseRotate(orbit.at(i).position - cm2ceCorrection);\n        }\n      }\n      return orbit;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write rotated orbit to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2EclipseFactor.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2EclipseFactor.cpp\n*\n* @brief Create instrument file containing eclipse factors.\n*\n* @author Beate Klinger\n* @date 2016-06-10\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program generates an \\file{instrument file}{instrument} (MISCVALUE(S)) containing the eclipse factor for a given set of orbit.\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/eclipse/eclipse.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create instrument file containing eclipse factors.\n* @ingroup programsGroup */\nclass Orbit2EclipseFactor\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2EclipseFactor, PARALLEL, \"Create instrument file containing eclipse factors.\", Orbit, Instrument)\nGROOPS_RENAMED_PROGRAM(InstrumentOrbit2EclipseFactor, Orbit2EclipseFactor, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid Orbit2EclipseFactor::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameEclipse, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n    EphemeridesPtr        ephemerides;\n    EclipsePtr            eclipse;\n\n    readConfig(config, \"outputfileEclipseFactor\", fileNameEclipse,     Config::MUSTSET,  \"\", \"instrument file (MISCVALUE(S): eclipse, ...)\");\n    readConfig(config, \"inputfileOrbit\",          fileNameOrbit,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",     fileNamesInstrument, Config::OPTIONAL, \"\", \"data are appended\");\n    readConfig(config, \"ephemerides\",             ephemerides,         Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"eclipse\",                 eclipse,             Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"computing eclipse factor\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    UInt dataCount = 2;\n    std::vector<InstrumentFilePtr> instrumentFile;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      instrumentFile.push_back(InstrumentFile::newFile(fileName));\n      InstrumentFile::checkArcCount({orbitFile, *instrumentFile.back()});\n      dataCount += instrumentFile.back()->dataCount(TRUE/*mustDefined*/);\n    }\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      const OrbitArc orbit = orbitFile.readArc(arcNo);\n      Matrix A(orbit.size(), dataCount);\n      for(UInt i=0; i<orbit.size(); i++)\n        A(i, 1) = eclipse->factor(orbit.at(i).time, orbit.at(i).position, ephemerides);\n\n      UInt idx = 2;\n      for(auto &file: instrumentFile)\n      {\n        Arc arc = file->readArc(arcNo);\n        Arc::checkSynchronized({orbit, arc});\n        Matrix B = arc.matrix();\n        copy(B.column(1, B.columns()-1), A.column(idx, B.columns()-1));\n        idx += B.columns()-1;\n      }\n\n      return Arc(orbit.times(), A);\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write eclipse factor to file <\"<<fileNameEclipse<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameEclipse, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2Groundtracks.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2Groundtracks.cpp\n*\n* @brief Groundtracks of a satellite as gridded data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-05-21\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program write \\file{satellites positions}{instrument} as \\file{gridded data}{griddedData}\n(\\config{outputfileTrackGriddedData}) in a terrestrial reference frame. The points are expressed as ellipsoidal coordinates\n(longitude, latitude, height) based on a reference ellipsoid with parameters \\config{R} and\n\\config{inverseFlattening}. The orbit data are given in the celestial frame so \\configClass{earthRotation}{earthRotationType}\nis needed to transform the data into the terrestrial frame.\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each point.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Groundtracks of a satellite as gridded data.\n* @ingroup programsGroup */\nclass Orbit2Groundtracks\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2Groundtracks, SINGLEPROCESS, \"groundtracks of a satellite as gridded data.\", Orbit, Instrument, Grid)\nGROOPS_RENAMED_PROGRAM(ArcGroundtracks, Orbit2Groundtracks, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid Orbit2Groundtracks::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOut, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n    EarthRotationPtr      earthRotation;\n    Double                a, f;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut,         Config::MUSTSET,  \"\", \"positions as gridded data\");\n    readConfig(config, \"inputfileOrbit\",        fileNameOrbit,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",   fileNamesInstrument, Config::OPTIONAL, \"\", \"values at grid points\");\n    readConfig(config, \"earthRotation\",         earthRotation,       Config::MUSTSET,  \"\", \"transformation from CRF to TRF\");\n    readConfig(config, \"R\",                     a,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates\");\n    readConfig(config, \"inverseFlattening\",     f,                   Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates\");\n    if(isCreateSchema(config)) return;\n\n    // positions\n    // ---------\n    logStatus<<\"read orbit file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n    OrbitArc orbit = InstrumentFile::read(fileNameOrbit);\n    std::vector<Vector3d> points;\n    for(UInt i=0; i<orbit.size(); i++)\n      points.push_back(earthRotation->rotaryMatrix(orbit.at(i).time).rotate(orbit.at(i).position));\n\n    // values\n    // ------\n    std::vector<std::vector<Double>> values;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      logStatus<<\"read instrument file <\"<<fileName<<\">\"<<Log::endl;\n      Arc arc = InstrumentFile::read(fileName);\n      Arc::checkSynchronized({arc, orbit});\n\n      const Matrix A = arc.matrix();\n      for(UInt k=1; k<A.columns(); k++)\n        values.push_back(Vector(A.column(k)));\n    }\n\n    // write gridded data\n    // ------------------\n    logStatus<<\"write gridded data <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOut, GriddedData(Ellipsoid(a,f), points, {}, values));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2Kepler.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2Kepler.cpp\n*\n* @brief Keplerian elements from orbit position and velocity at each epoch.\n*\n* @author Torsten Mayer-Guerr\n* @date 2010-07-20\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the osculating Keplerian elements from position and velocity\nof a given \\configFile{inputfileOrbit}{instrument}.\nThe \\configFile{inputfileOrbit}{instrument} must contain positions and velocities (see \\program{OrbitAddVelocityAndAcceleration}).\n\nThe \\config{outputfileKepler} is an \\file{instrument file}{instrument} (MISCVALUES)\nwith the Keplerian elements at each epoch in the following order\n\\begin{itemize}\n\\item Ascending Node $\\Omega$ [degree]\n\\item Inclination $i$ [degree]\n\\item Argument of perigee $\\omega$ [degree]\n\\item major axis $a$ [m]\n\\item eccentricity $e$\n\\item mean anomaly $M$ [degree]\n\\item transit time of perigee $\\tau$ [mjd]\n\\end{itemize}\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/kepler.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Keplerian elements from orbit position and velocity at each epoch.\n* @ingroup programsGroup */\nclass Orbit2Kepler\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2Kepler, PARALLEL, \"keplerian elements from orbit position and velocity at each epoch\", Orbit, Instrument, TimeSeries)\n\n/***********************************************/\n\nvoid Orbit2Kepler::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n    Double                GM;\n\n    readConfig(config, \"outputfileKepler\",    fileNameOut,         Config::MUSTSET,  \"\", \"instrument file (MISCVALUES: Omega, i, omega [degree], a [m], e, M [degree], tau [mjd], ...)\");\n    readConfig(config, \"inputfileOrbit\",      fileNameOrbit,       Config::MUSTSET,  \"\", \"position and velocity at each epoch define the kepler orbit\");\n    readConfig(config, \"inputfileInstrument\", fileNamesInstrument, Config::OPTIONAL, \"\", \"data is appended\");\n    readConfig(config, \"GM\",                  GM,                  Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"calculate Keplerian elements\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    UInt dataCount = 8;\n    std::vector<InstrumentFilePtr> instrumentFile;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      instrumentFile.push_back(InstrumentFile::newFile(fileName));\n      InstrumentFile::checkArcCount({orbitFile, *instrumentFile.back()});\n      dataCount += instrumentFile.back()->dataCount(TRUE/*mustDefined*/);\n    }\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      const OrbitArc orbit = orbitFile.readArc(arcNo);\n      Matrix A(orbit.size(), dataCount);\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        if(orbit.at(i).velocity.r()==0)\n          throw(Exception(\"no velocity given\"));\n\n        const Kepler kepler(orbit.at(i).time, orbit.at(i).position, orbit.at(i).velocity, GM);\n        const Double M = (orbit.at(i).time-kepler.tau).seconds() * std::sqrt(GM/std::pow(kepler.a,3));\n\n        A(i, 1) = std::fmod(kepler.Omega+2*PI, 2*PI) * RAD2DEG;\n        A(i, 2) = kepler.i * RAD2DEG;\n        A(i, 3) = std::fmod(kepler.omega+2*PI, 2*PI) * RAD2DEG;\n        A(i, 4) = kepler.a;\n        A(i, 5) = kepler.e;\n        A(i, 6) = std::fmod(M+2*PI, 2*PI) * RAD2DEG;\n        A(i, 7) = kepler.tau.mjd();\n      }\n\n      UInt idx = 8;\n      for(auto &file: instrumentFile)\n      {\n        Arc arc = file->readArc(arcNo);\n        Arc::checkSynchronized({orbit, arc});\n        Matrix B = arc.matrix();\n        copy(B.column(1, B.columns()-1), A.column(idx, B.columns()-1));\n        idx += B.columns()-1;\n      }\n\n      return Arc(orbit.times(), A);\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write time series of Keplerian elements to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2MagneticField.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2MagneticField.cpp\n*\n* @brief Magentic field vector along orbit.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-05-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the magentic field vector($x, y, z$ $[Tesla = kg/A/s^2]$ in CRF))\nalong an \\file{orbit}{instrument} and writes it as \\file{instrument file}{instrument} (MISCVALUES).\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as data columns to each epoch.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/magnetosphere/magnetosphere.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Magentic field vector along orbit.\n* @ingroup programsGroup */\nclass Orbit2MagneticField\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2MagneticField, PARALLEL, \"Thermospheric state along orbit.\", Orbit, Instrument)\n\n/***********************************************/\n\nvoid Orbit2MagneticField::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n    MagnetospherePtr      magnetosphere;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileMagneticField\", fileNameOut,         Config::MUSTSET,  \"\", \"instrument file (x,y,z in CRF [Tesla = kg/A/s^2]), ...)\");\n    readConfig(config, \"inputfileOrbit\",          fileNameOrbit,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",     fileNamesInstrument, Config::OPTIONAL, \"\", \"data are appended to output file\");\n    readConfig(config, \"magnetosphere\",           magnetosphere,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"earthRotation\",           earthRotation,       Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"computing thermospheric state\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    UInt dataCount = 4; // (time, x, y, z)\n    std::vector<InstrumentFilePtr> instrumentFile;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      instrumentFile.push_back(InstrumentFile::newFile(fileName));\n      InstrumentFile::checkArcCount({orbitFile, *instrumentFile.back()});\n      dataCount += instrumentFile.back()->dataCount(TRUE/*mustDefined*/);\n    }\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      const OrbitArc orbit = orbitFile.readArc(arcNo);\n      Matrix A(orbit.size(), dataCount);\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        const Rotary3d rotEarth = earthRotation->rotaryMatrix(orbit.at(i).time);\n        Vector3d field = rotEarth.inverseRotate(magnetosphere->magenticFieldVector(orbit.at(i).time, rotEarth.rotate(orbit.at(i).position)));\n\n        A(i, 1) = field.x();\n        A(i, 2) = field.y();\n        A(i, 3) = field.z();\n      }\n\n      UInt idx = 4;\n      for(auto &file: instrumentFile)\n      {\n        Arc arc = file->readArc(arcNo);\n        Arc::checkSynchronized({orbit, arc});\n        Matrix B = arc.matrix();\n        copy(B.column(1, B.columns()-1), A.column(idx, B.columns()-1));\n        idx += B.columns()-1;\n      }\n\n      return Arc(orbit.times(), A);\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write magnetic field vector to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbit2ThermosphericState.cpp",
    "content": "/***********************************************/\n/**\n* @file orbit2ThermosphericState.cpp\n*\n* @brief Thermospheric state along orbit.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-03-07\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes the thermosperic state (density, temperature, wind (x,y,z in CRF))\nbased on emprical models along an \\file{orbit}{instrument}\nand writes it as \\file{instrument file}{instrument} (MISCVALUES).\nThe wind is given in an celestial reference frame (CRF).\nThe data of \\configFile{inputfileInstrument}{instrument} are appended as values to each epoch.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/thermosphere/thermosphere.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Thermospheric state along orbit.\n* @ingroup programsGroup */\nclass Orbit2ThermosphericState\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(Orbit2ThermosphericState, PARALLEL, \"Thermospheric state along orbit.\", Orbit, Instrument)\nGROOPS_RENAMED_PROGRAM(InstrumentOrbit2ThermosphericState, Orbit2ThermosphericState, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid Orbit2ThermosphericState::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName              fileNameOut, fileNameOrbit;\n    std::vector<FileName> fileNamesInstrument;\n    ThermospherePtr       thermosphere;\n    EarthRotationPtr      earthRotation;\n\n    readConfig(config, \"outputfileThermosphericState\", fileNameOut,         Config::MUSTSET,  \"\", \"instrument file (MISCVALUES: density, temperature, wind (x,y,z in CRF), ...)\");\n    readConfig(config, \"inputfileOrbit\",               fileNameOrbit,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileInstrument\",          fileNamesInstrument, Config::OPTIONAL, \"\", \"data are appended to output file\");\n    readConfig(config, \"thermosphere\",                 thermosphere,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",                earthRotation,       Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // =======================\n\n    logStatus<<\"computing thermospheric state\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    UInt dataCount = 6; // time, density, temperature, wind(x,yz)\n    std::vector<InstrumentFilePtr> instrumentFile;\n    for(auto &fileName : fileNamesInstrument)\n    {\n      instrumentFile.push_back(InstrumentFile::newFile(fileName));\n      InstrumentFile::checkArcCount({orbitFile, *instrumentFile.back()});\n      dataCount += instrumentFile.back()->dataCount(TRUE/*mustDefined*/);\n    }\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      const OrbitArc orbit = orbitFile.readArc(arcNo);\n      Matrix A(orbit.size(), dataCount);\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        const Rotary3d rotEarth = earthRotation->rotaryMatrix(orbit.at(i).time);\n        Double   density, temperature;\n        Vector3d wind;\n        thermosphere->state(orbit.at(i).time, rotEarth.rotate(orbit.at(i).position), density, temperature, wind);\n        wind = rotEarth.inverseRotate(wind) + crossProduct(earthRotation->rotaryAxis(orbit.at(i).time), orbit.at(i).position);\n\n        A(i, 1) = density;\n        A(i, 2) = temperature;\n        A(i, 3) = wind.x();\n        A(i, 4) = wind.y();\n        A(i, 5) = wind.z();\n      }\n\n      UInt idx = 6;\n      for(auto &file: instrumentFile)\n      {\n        Arc arc = file->readArc(arcNo);\n        Arc::checkSynchronized({orbit, arc});\n        Matrix B = arc.matrix();\n        copy(B.column(1, B.columns()-1), A.column(idx, B.columns()-1));\n        idx += B.columns()-1;\n      }\n\n      return Arc(orbit.times(), A);\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write thermospheric state to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/orbitAddVelocityAndAcceleration.cpp",
    "content": "/***********************************************/\n/**\n* @file orbitAddVelocityAndAcceleration.cpp\n*\n* @brief Compute velocities and accelerations from a given orbit and save to one file.\n*\n* @author Norbert Zehentner\n* @author Torsten Mayer-Guerr\n* @date 2014-04-16\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program computes velocities and accelerations from a given \\file{orbit}{instrument}\nby differentiating a moving polynomial.\nThe values are saved in one output file which then contains orbit, velocity and acceleration.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute velocities and accelerations from a given orbit.\n* @ingroup programsGroup */\nclass OrbitAddVelocityAndAcceleration\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(OrbitAddVelocityAndAcceleration, PARALLEL, \"Compute velocities and accelerations from a given orbit\", Orbit, Instrument)\nGROOPS_RENAMED_PROGRAM(InstrumentOrbit2VelocityAcceleration, OrbitAddVelocityAndAcceleration, date2time(2020, 05, 25))\n\n/***********************************************/\n\nvoid OrbitAddVelocityAndAcceleration::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut, fileNameIn;\n    UInt     degree;\n\n    readConfig(config, \"outputfileOrbit\",  fileNameOut, Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",   fileNameIn,  Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"polynomialDegree\", degree,      Config::DEFAULT, \"8\", \"Polynomial degree, must be even!\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    logStatus<<\"read orbit data <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameIn);\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&] (UInt arcNo)\n    {\n      OrbitArc orbit = orbitFile.readArc(arcNo);\n      UInt idx = 0;\n      for(UInt idEpoch=0; idEpoch<orbit.size(); idEpoch++)\n      {\n        // find optimal interval\n        // ---------------------\n        while((idx+degree < orbit.size()) && (orbit.at(idx+degree).time < orbit.at(idEpoch).time))\n          idx++;\n        if(idx+degree >= orbit.size())\n          break;\n\n        UInt   idxOpt   = MAX_UINT;\n        Double deltaOpt = 1e99;\n        while((idx+degree < orbit.size()) && (orbit.at(idx).time <= orbit.at(idEpoch).time))\n        {\n          // interpolation point should be in the mid of the interval\n          // => search minimum of the difference of the time before and after the interpolation point\n          const Double delta = std::fabs(((orbit.at(idx+degree).time-orbit.at(idEpoch).time)-(orbit.at(idEpoch).time-orbit.at(idx).time)).seconds());\n          if(delta <= deltaOpt)\n          {\n            idxOpt   = idx;\n            deltaOpt = delta;\n          }\n          idx++;\n        }\n        idx = idxOpt;\n\n        // polynomial interpolation\n        // ------------------------\n        Matrix A(degree+1, degree+1);\n        for(UInt k=0; k<degree+1; k++)\n        {\n          const Double factor = (orbit.at(idx+k).time-orbit.at(idEpoch).time).seconds();\n          A(0,k) = 1.0;\n          for(UInt n=1; n<=degree; n++)\n            A(n,k) = factor * A(n-1,k);\n        }\n        Matrix coeff(degree+1, 2);\n        coeff(1, 0) = 1.; // velocity\n        coeff(2, 1) = 2.; // acceleration\n        solveInPlace(A, coeff);\n\n        orbit.at(idEpoch).velocity     = Vector3d();\n        orbit.at(idEpoch).acceleration = Vector3d();\n        for(UInt k=0; k<coeff.rows(); k++)\n        {\n          orbit.at(idEpoch).velocity     += coeff(k,0) * orbit.at(idx+k).position;\n          orbit.at(idEpoch).acceleration += coeff(k,1) * orbit.at(idx+k).position;\n        }\n      }\n      return orbit;\n    }, comm);\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write orbit data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/orbit/planetOrbit.cpp",
    "content": "/***********************************************/\n/**\n* @file planetOrbit.cpp\n*\n* @brief Orbits of sun, moon, and planets.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-04-12\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreates an \\file{orbit file}{instrument} of sun, moon, or planets.\nThe orbit is given in the celestial reference frame (CRF)\nor alternatively in the terrestrial reference frame (TRF)\nif \\configClass{earthRotation}{earthRotationType} is provided.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Orbits of sun, moon, and planets.\n* @ingroup programsGroup */\nclass PlanetOrbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlanetOrbit, SINGLEPROCESS, \"orbits of sun, moon and, planets\", Orbit, Instrument)\n\n/***********************************************/\n\nvoid PlanetOrbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName            fileNameOrbit;\n    TimeSeriesPtr       timeSeries;\n    EarthRotationPtr    earthRotation;\n    EphemeridesPtr      ephemerides;\n    Ephemerides::Planet planet;\n    std::string         choice;\n\n    readConfig(config, \"outputfileOrbit\", fileNameOrbit, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"planet\",          planet,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",      timeSeries,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"ephemerides\",     ephemerides,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",   earthRotation, Config::OPTIONAL, \"\", \"transform orbits into TRF\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"computing\"<<Log::endl;\n    std::vector<Time> times  = timeSeries->times();\n    OrbitArc orbit;\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      OrbitEpoch epoch;\n      epoch.time = times.at(i);\n      ephemerides->ephemeris(times.at(i), planet, epoch.position, epoch.velocity);\n\n      if(earthRotation)\n      {\n        const Rotary3d rotEarth = earthRotation->rotaryMatrix(times.at(i));\n        const Vector3d omega    = earthRotation->rotaryAxis(times.at(i));\n        epoch.velocity = rotEarth.rotate(epoch.velocity - crossProduct(omega, epoch.position));\n        epoch.position = rotEarth.rotate(epoch.position);\n      }\n\n      orbit.push_back(epoch);\n    });\n\n    logStatus<<\"write orbit data to file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOrbit, orbit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/plot/plotDegreeAmplitudes.cpp",
    "content": "/***********************************************/\n/**\n* @file plotDegreeAmplitudes.cpp\n*\n* @brief Plot Degree Amplitudes.\n*\n* @author Enrico Kurtenbach\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2015-10-26\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nPlot degree amplitudes of potential coefficients computed by \\program{Gravityfield2DegreeAmplitudes}\nor \\program{PotentialCoefficients2DegreeAmplitudes} using the GMT Generic Mapping Tools\n(\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\nThis is a convenience program with meaningful default values. The same plots can be generated with the more general \\program{PlotGraph}.\n\n\\fig{!hb}{0.8}{plotDegreeAmplitudes}{fig:plotDegreeAmplitudes}{Comparison of GRACE solutions (2008-06) with GOCO06s.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"plot/plotMisc.h\"\n#include \"plot/plotGraphLayer.h\"\n#include \"plot/plotLegend.h\"\n\n/***********************************************/\n\n/** @brief Plot Degree Amplitudes.\n* @ingroup programsGroup */\nclass PlotDegreeAmplitudes\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlotDegreeAmplitudes, SINGLEPROCESS, \"Plot Degree Amplitudes\", Plot, Gravityfield, PotentialCoefficients)\n\n/***********************************************/\n\nvoid PlotDegreeAmplitudes::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          fileNamePlot;\n    std::string       title;\n    std::vector<PlotGraphLayerPtr> layer;\n    Double            annotationX=NAN_EXPR, frameX=NAN_EXPR, gridX=NAN_EXPR;\n    Double            annotationY=NAN_EXPR, frameY=NAN_EXPR, gridY=NAN_EXPR;\n    UInt              minX=INFINITYDEGREE, maxX=INFINITYDEGREE;\n    Double            minY=NAN_EXPR, maxY=NAN_EXPR;\n    Bool              logX, logY;\n    std::string       labelX, labelY, unitY;\n    PlotLinePtr       gridLine;\n    PlotLegendPtr     legend;\n    PlotBasics        plotBasics;\n\n    renameDeprecatedConfig(config, \"annotationDegree\", \"majorTickSpacingDegree\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frameDegree\",      \"minorTickSpacingDegree\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"gridDegree\",       \"gridLineSpacingDegree\",  date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"annotationY\",      \"majorTickSpacingY\",      date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frameY\",           \"minorTickSpacingY\",      date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"gridY\",            \"gridLineSpacingY\",       date2time(2020, 4, 23));\n\n    readConfig(config, \"outputfile\",             fileNamePlot, Config::MUSTSET,  \"\",     \"*.png, *.jpg, *.eps, ...\");\n    readConfig(config, \"title\",                  title,        Config::OPTIONAL, \"\",     \"\");\n    readConfig(config, \"layer\",                  layer,        Config::MUSTSET,  \"degreeAmplitudesSimple\", \"\");\n    readConfig(config, \"minDegree\",              minX,         Config::OPTIONAL, \"0\",    \"\");\n    readConfig(config, \"maxDegree\",              maxX,         Config::OPTIONAL, \"\",     \"\");\n    readConfig(config, \"majorTickSpacingDegree\", annotationX,  Config::OPTIONAL, \"\",     \"boundary annotation\");\n    readConfig(config, \"minorTickSpacingDegree\", frameX,       Config::OPTIONAL, \"\",     \"frame tick spacing\");\n    readConfig(config, \"gridLineSpacingDegree\",  gridX,        Config::OPTIONAL, \"\",     \"gridline spacing\");\n    readConfig(config, \"labelDegree\",            labelX,       Config::OPTIONAL, \"[degree]\", \"description of the x-axis\");\n    readConfig(config, \"logarithmicDegree\",      logX,         Config::DEFAULT,  \"0\",    \"use logarithmic scale for the x-axis\");\n    readConfig(config, \"minY\",                   minY,         Config::OPTIONAL, \"1e-6\", \"\");\n    readConfig(config, \"maxY\",                   maxY,         Config::OPTIONAL, \"1\",    \"\");\n    readConfig(config, \"majorTickSpacingY\",      annotationY,  Config::OPTIONAL, \"\",     \"boundary annotation\");\n    readConfig(config, \"minorTickSpacingY\",      frameY,       Config::OPTIONAL, \"\",     \"frame tick spacing\");\n    readConfig(config, \"gridLineSpacingY\",       gridY,        Config::OPTIONAL, \"\",     \"gridline spacing\");\n    readConfig(config, \"unitY\",                  unitY,        Config::OPTIONAL, \"\",     \"appended to axis values\");\n    readConfig(config, \"labelY\",                 labelY,       Config::OPTIONAL, \"geoid height [m]\",  \"description of the y-axis\");\n    readConfig(config, \"logarithmicY\",           logY,         Config::DEFAULT,  \"1\",    \"use logarithmic scale for the y-axis\");\n    readConfig(config, \"gridLine\",               gridLine,     Config::OPTIONAL, R\"({\"solid\": {\"width\":\"0.25\", \"color\":\"gray\"}})\", \"The style of the grid lines.\");\n    readConfig(config, \"legend\",                 legend,       Config::OPTIONAL, \"1\",    \"\");\n    plotBasics.read(config, \"PlotDegreeAmplitudes\", fileNamePlot, title, \"12\", \"10\");\n    if(isCreateSchema(config)) return;\n\n    // ===========================================================\n\n    // calculate min and max\n    // ---------------------\n    // x-axis\n    Double minDegree  =  1e99;\n    Double maxDegree  = -1e99;\n    for(UInt k = 0; k<layer.size(); k++)\n      layer.at(k)->getIntervalX(logX, minDegree, maxDegree);\n    if(minX==INFINITYDEGREE) minX = static_cast<UInt>(minDegree);\n    if(maxX==INFINITYDEGREE) maxX = static_cast<UInt>(maxDegree);\n\n    // y-axis\n    Double minSignal  =  1e99;\n    Double maxSignal  = -1e99;\n    for(UInt k = 0; k<layer.size(); k++)\n      layer.at(k)->getIntervalY(logY, minX, maxX, minSignal, maxSignal);\n    if(std::isnan(minY)) minY = minSignal;\n    if(std::isnan(maxY)) maxY = maxSignal;\n\n    // create data files\n    // -----------------\n    logStatus<<\"create temporary data files\"<<Log::endl;\n    for(UInt i=0; i<layer.size(); i++)\n      layer.at(i)->writeDataFile(plotBasics.workingDirectory, i, minX, maxX, minY, maxY);\n\n    // create scriptfile\n    // -----------------\n    logStatus<<\"create scriptfile\"<<Log::endl;\n    {\n      OutFile file(plotBasics.fileNameScript());\n      file<<plotBasics.scriptHeader();\n      file<<PlotBasics::scriptSetVariable(\"range\", minX%\"%i/\"s+maxX%\"%i/\"s+minY%\"%g/\"s+maxY%\"%g\"s)<<std::endl;\n      file<<\"gmt psbasemap -Y\"<<-plotBasics.height-plotBasics.marginTitle<<\"c -R\"<<PlotBasics::scriptVariable(\"range\");\n      file<<\" -JX\"<<plotBasics.width<<\"c\"<<((logX) ? \"l\" : \"\")<<\"/\"<<plotBasics.height<<\"c\"<<((logY) ? \"l\" : \"\");\n      file<<\" -BWSne\";\n      file<<\" -Bx\"<<PlotBasics::axisTicks(logX, minX, maxX, annotationX, frameX, gridX, \"\",    labelX);\n      file<<\" -By\"<<PlotBasics::axisTicks(logY, minY, maxY, annotationY, frameY, gridY, unitY, labelY);\n      if(gridLine)\n        file<<\" --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str();\n      file<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      for(UInt i=0; i<layer.size(); i++)\n        file<<layer.at(i)->scriptEntry();\n      if(legend)\n      {\n        std::vector<std::string> legendText;\n        for(UInt i=0; i<layer.size(); i++)\n          legendText.push_back(layer.at(i)->legendEntry());\n\n        legend->writeDataFile(plotBasics.workingDirectory, legendText);\n        file<<legend->scriptEntry();\n        file<<std::endl;\n      }\n      file<<plotBasics.scriptTrailer();\n    } // end scriptfile\n\n    // run scriptfile\n    // --------------\n    logStatus<<\"run scriptfile\"<<Log::endl;\n    plotBasics.runScript();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/plot/plotGraph.cpp",
    "content": "/***********************************************/\n/**\n* @file plotGraph.cpp\n*\n* @brief Plot functions (x,y).\n*\n* @author Enrico Kurtenbach\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2015-10-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nGenerates a two dimensional xy plot using the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThe plotting area is defined by the two axes \\configClass{axisX/Y}{plotAxisType}. An alternative \\configClass{axisY2}{plotAxisType}\non the right hand side can be added. The content of the graph itself is defined\nby one or more \\configClass{layer}{plotGraphLayerType}s.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\nSee also: \\program{PlotDegreeAmplitudes}, \\program{PlotMap}, \\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"plot/plotMisc.h\"\n#include \"plot/plotAxis.h\"\n#include \"plot/plotGraphLayer.h\"\n#include \"plot/plotLegend.h\"\n#include \"plot/plotColorbar.h\"\n\n/***********************************************/\n\n/** @brief Plot functions (x,y).\n* @ingroup programsGroup */\nclass PlotGraph\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlotGraph, SINGLEPROCESS, \"Plot functions (x,y)\", Plot, TimeSeries)\n\n/***********************************************/\n\nvoid PlotGraph::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          fileNamePlot;\n    std::string       title;\n    std::vector<PlotGraphLayerPtr> layer;\n    PlotAxisPtr       axisX, axisY, axisY2;\n    PlotColorbarPtr   colorbar;\n    PlotLegendPtr     legend;\n    PlotBasics        plotBasics;\n\n    readConfig(config, \"outputfile\", fileNamePlot, Config::MUSTSET,  \"\",  \"*.png, *.jpg, *.eps, ...\");\n    readConfig(config, \"title\",      title,        Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"layer\",      layer,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"axisX\",      axisX,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"axisY\",      axisY,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"axisY2\",     axisY2,       Config::OPTIONAL, \"\",  \"Second y-axis on right hand side\");\n    readConfig(config, \"colorbar\",   colorbar,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"legend\",     legend,       Config::OPTIONAL, \"1\", \"\");\n    plotBasics.read(config, \"PlotGraph\", fileNamePlot, title, \"12\", \"7\", {\"TIME_SYSTEM=MJD\"s});\n    if(isCreateSchema(config)) return;\n\n    // ===========================================================\n\n    // colorbar needed?\n    // ----------------\n    for(UInt i=0; i<layer.size(); i++)\n      if(layer.at(i)->requiresColorBar() && !colorbar)\n        throw(Exception(\"layer need definition of a colorbar\"));\n\n    // calculate min and max\n    // ---------------------\n    // x-axis\n    Double minX  =  1e99;\n    Double maxX  = -1e99;\n    for(UInt k=0; k<layer.size(); k++)\n      layer.at(k)->getIntervalX(axisX->isLogarithmic(), minX, maxX);\n    axisX->setAutoInterval(minX, maxX);\n    logInfo<<\"  plot x range  (\"<<axisX->getMin()<<\" .. \"<<axisX->getMax()<<\") of (\"<<minX<<\" .. \"<<maxX<<\")\"<<Log::endl;\n\n    // y-axis\n    Double minY  =  1e99;\n    Double maxY  = -1e99;\n    Double minY2 =  1e99;\n    Double maxY2 = -1e99;\n    for(UInt k=0; k<layer.size(); k++)\n    {\n      if(axisY2 && layer.at(k)->drawOnSecondAxis())\n        layer.at(k)->getIntervalY(axisY2->isLogarithmic(), axisX->getMin(), axisX->getMax(), minY2, maxY2);\n      else\n        layer.at(k)->getIntervalY(axisY->isLogarithmic(), axisX->getMin(), axisX->getMax(), minY, maxY);\n    }\n    axisY->setAutoInterval(minY, maxY);\n    if(axisY2)\n      axisY2->setAutoInterval(minY2, maxY2);\n    logInfo<<\"  plot y range  (\"<<axisY->getMin()<<\" .. \"<<axisY->getMax()<<\") of (\"<<minY<<\" .. \"<<maxY<<\")\"<<Log::endl;\n    if(axisY2)\n      logInfo<<\"  plot y2 range (\"<<axisY2->getMin()<<\" .. \"<<axisY2->getMax()<<\") of (\"<<minY2<<\" .. \"<<maxY2<<\")\"<<Log::endl;\n\n    // z-axis\n    if(colorbar)\n    {\n      Double minZ  =  1e99;\n      Double maxZ  = -1e99;\n      for(UInt k = 0; k<layer.size(); k++)\n        if(axisY2 && layer.at(k)->drawOnSecondAxis())\n          layer.at(k)->getIntervalZ(colorbar->isLogarithmic(), minX, maxX, minY2, maxY2, minZ, maxZ);\n        else\n          layer.at(k)->getIntervalZ(colorbar->isLogarithmic(), minX, maxX, minY, maxY, minZ, maxZ);\n      colorbar->setAutoInterval(minZ, maxZ);\n      logInfo<<\"  plot z range  (\"<<colorbar->getMin()<<\" .. \"<<colorbar->getMax()<<\") of (\"<<minZ<<\" .. \"<<maxZ<<\")\"<<Log::endl;\n    }\n\n    // create data files\n    // -----------------\n    logStatus<<\"create temporary data files\"<<Log::endl;\n    for(UInt i=0; i<layer.size(); i++)\n      if(axisY2 && layer.at(i)->drawOnSecondAxis())\n        layer.at(i)->writeDataFile(plotBasics.workingDirectory, i, minX, maxX, minY2, maxY2);\n      else\n        layer.at(i)->writeDataFile(plotBasics.workingDirectory, i, minX, maxX, minY, maxY);\n    axisX->writeDataFile(plotBasics.workingDirectory, \"x\");\n    axisY->writeDataFile(plotBasics.workingDirectory, \"y\");\n    if(axisY2) axisY2->writeDataFile(plotBasics.workingDirectory, \"y2\");\n\n    // intervals\n    // ---------\n    std::string JX, JX2;\n    {\n      std::stringstream ss;\n      ss<<\"-R\"<<PlotBasics::scriptVariable(\"range\")<<\" -JX\"<<axisX->direction()*plotBasics.width<<\"c\"<<axisX->axisModifier()<<\"/\"<<axisY->direction()*plotBasics.height<<\"c\"<<axisY->axisModifier();\n      JX = ss.str();\n    }\n    if(axisY2)\n    {\n      std::stringstream ss;\n      ss<<\"-R\"<<PlotBasics::scriptVariable(\"rangeY2\")<<\" -JX\"<<axisX->direction()*plotBasics.width<<\"c\"<<axisX->axisModifier()<<\"/\"<<axisY2->direction()*plotBasics.height<<\"c\"<<axisY2->axisModifier();\n      JX2 = ss.str();\n    }\n\n    // create scriptfile\n    // -----------------\n    logStatus<<\"create scriptfile\"<<Log::endl;\n    {\n      OutFile file(plotBasics.fileNameScript());\n      file<<plotBasics.scriptHeader();\n      if(colorbar)\n        file<<colorbar->scriptColorTable();\n      file<<PlotBasics::scriptSetVariable(\"range\", axisX->getMin()%\"%.12e/\"s+axisX->getMax()%\"%.12e/\"s+axisY->getMin()%\"%.12e/\"s+axisY->getMax()%\"%.12e\"s)<<std::endl;\n      if(axisY2)\n        file<<PlotBasics::scriptSetVariable(\"rangeY2\", axisX->getMin()%\"%.12e/\"s+axisX->getMax()%\"%.12e/\"s+axisY2->getMin()%\"%.12e/\"s+axisY2->getMax()%\"%.12e\"s)<<std::endl;\n      // x-axis\n      file<<\"gmt psbasemap -Y\"<<-fabs(plotBasics.height)-plotBasics.marginTitle<<\"c \"<<JX<<\" -BSn \"<<axisX->scriptEntry(\"x\")<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      // y-axis\n      file<<\"gmt psbasemap \"<<JX<<\" -BW\"<<((axisY2) ? \" \" : \"e \")<<axisY->scriptEntry(\"y\")<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      Bool isAxisY2 = FALSE;\n      // second y-axis\n      if(axisY2)\n      {\n        file<<\"gmt psbasemap \"<<JX2<<\" -BE \"<<axisY2->scriptEntry(\"y\")<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n        isAxisY2 = TRUE;\n      }\n\n      // data sets\n      for(UInt i=0; i<layer.size(); i++)\n      {\n        if(isAxisY2 && !layer.at(i)->drawOnSecondAxis())\n        {\n          file<<\"gmt psxy \"<<JX<<\" -Bw -T -O -K >> groopsPlot.ps\"<<std::endl;\n          isAxisY2 = FALSE;\n        }\n        else if((!isAxisY2) && axisY2 && layer.at(i)->drawOnSecondAxis())\n        {\n          file<<\"gmt psxy \"<<JX2<<\" -Be -T -O -K >> groopsPlot.ps\"<<std::endl;\n          isAxisY2 = TRUE;\n        }\n        file<<layer.at(i)->scriptEntry();\n      }\n      file<<std::endl;\n\n      // write axis again\n      file<<\"gmt psbasemap \"<<JX<<\" -BSn \"<<axisX->scriptEntry(\"x\", plotBasics.drawGridOnTop)<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<\"gmt psbasemap \"<<JX<<\" -BW\"<<((axisY2) ? \" \" : \"e \")<<axisY->scriptEntry(\"y\", plotBasics.drawGridOnTop)<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      if(axisY2)\n        file<<\"gmt psbasemap \"<<JX2<<\" -BE \"<<axisY2->scriptEntry(\"y\", plotBasics.drawGridOnTop)<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n\n      if(colorbar)\n        file<<colorbar->scriptEntry(plotBasics.width, plotBasics.height, ((axisY2) ? axisY2->getMargin() : 0.0), axisX->getMargin());\n\n      if(legend)\n      {\n        std::vector<std::string> legendText;\n        for(UInt i=0; i<layer.size(); i++)\n          legendText.push_back(layer.at(i)->legendEntry());\n\n        legend->writeDataFile(plotBasics.workingDirectory, legendText);\n        file<<legend->scriptEntry();\n      }\n\n      file<<plotBasics.scriptTrailer();\n    } // end scriptfile\n\n    // run scriptfile\n    // --------------\n    logStatus<<\"run scriptfile\"<<Log::endl;\n    plotBasics.runScript();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/plot/plotMap.cpp",
    "content": "/***********************************************/\n/**\n* @file plotMap.cpp\n*\n* @brief Plot maps.\n*\n* @author Enrico Kurtenbach\n* @author Torsten Mayer-Guerr\n* @author Christian Pock\n* @author Andreas Kvas\n* @date 2015-10-20\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nGenerates a map using the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThe base map is defined by a \\configClass{projection}{plotMapProjectionType} of an ellipsoid (\\config{R}, \\config{inverseFlattening}).\nThe content of the map itself is defined by one or more \\configClass{layer}{plotMapLayerType}s.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\nSee also: \\program{PlotDegreeAmplitudes}, \\program{PlotGraph}, \\program{PlotMatrix}, \\program{PlotSphericalHarmonicsTriangle}.\n\n\\fig{!hb}{0.8}{plotMap}{fig:plotMap}{A Robinson projection with griddedData (geoid), coast, polygon (amazon), and points (IGS stations) layer.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"plot/plotColorbar.h\"\n#include \"plot/plotMapLayer.h\"\n#include \"plot/plotMapProjection.h\"\n#include \"plot/plotMisc.h\"\n\n/***********************************************/\n\n/** @brief Plot maps.\n* @ingroup programsGroup */\nclass PlotMap\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlotMap, SINGLEPROCESS, \"Plot maps\", Plot, Grid)\n\n/***********************************************/\n\nvoid PlotMap::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName                     fileNamePlot;\n    std::string                  title;\n    Bool                         statisticInfos;\n    std::vector<PlotMapLayerPtr> layer;\n    Double                       a, f;\n    Angle                        minL(NAN_EXPR), maxL(NAN_EXPR), minB(NAN_EXPR), maxB(NAN_EXPR);\n    Angle                        annotation, frame, grid;\n    PlotColorbarPtr              colorbar;\n    PlotMapProjectionPtr         projection;\n    PlotBasics                   plotBasics;\n\n    renameDeprecatedConfig(config, \"annotation\", \"majorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frame\",      \"minorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"grid\",       \"gridLineSpacing\",  date2time(2020, 4, 23));\n\n    readConfig(config, \"outputfile\",        fileNamePlot,   Config::MUSTSET,  \"\",  \"*.png, *.jpg, *.eps, ...\");\n    readConfig(config, \"title\",             title,          Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"statisticInfos\",    statisticInfos, Config::DEFAULT,  \"0\", \"\");\n    readConfig(config, \"layer\",             layer,          Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"R\",                 a,              Config::DEFAULT,  STRING_DEFAULT_GRS80_a, \"reference radius for ellipsoidal coordinates on output\");\n    readConfig(config, \"inverseFlattening\", f,              Config::DEFAULT,  STRING_DEFAULT_GRS80_f, \"reference flattening for ellipsoidal coordinates on output, 0: spherical coordinates\");\n    readConfig(config, \"minLambda\",         minL,           Config::OPTIONAL, \"-180\", \"min. longitude (default: compute from input data)\");\n    readConfig(config, \"maxLambda\",         maxL,           Config::OPTIONAL, \"180\",  \"max. longitude (default: compute from input data)\");\n    readConfig(config, \"minPhi\",            minB,           Config::OPTIONAL, \"-90\",  \"min. latitude (default: compute from input data)\");\n    readConfig(config, \"maxPhi\",            maxB,           Config::OPTIONAL, \"90\",   \"max. latitude (default: compute from input data)\");\n    readConfig(config, \"majorTickSpacing\",  annotation,     Config::DEFAULT,  \"0\",    \"boundary annotation\");\n    readConfig(config, \"minorTickSpacing\",  frame,          Config::DEFAULT,  \"0\",    \"frame tick spacing\");\n    readConfig(config, \"gridLineSpacing\",   grid,           Config::DEFAULT,  \"0\",    \"gridline spacing\");\n    readConfig(config, \"colorbar\",          colorbar,       Config::OPTIONAL, \"1\",    \"\");\n    readConfig(config, \"projection\",        projection,     Config::MUSTSET,  \"\",     \"map projection\");\n    plotBasics.read(config, \"PlotMap\", fileNamePlot, title, \"12\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ===========================================================\n\n    // calculate boundary\n    // ------------------\n    Ellipsoid ellipsoid(a, f);\n    Angle minL2(+180.*DEG2RAD);\n    Angle maxL2(-180.*DEG2RAD);\n    Angle minB2(+ 90.*DEG2RAD);\n    Angle maxB2(- 90.*DEG2RAD);\n    for(UInt i=0; i<layer.size(); i++)\n      layer.at(i)->boundary(ellipsoid, minL2, maxL2, minB2, maxB2);\n    if(std::isnan(minL)) minL = minL2;\n    if(std::isnan(maxL)) maxL = maxL2;\n    if(std::isnan(minB)) minB = minB2;\n    if(std::isnan(maxB)) maxB = maxB2;\n\n    if(minL == Angle(+180.*DEG2RAD) && (maxL == Angle(-180.*DEG2RAD)))\n      std::swap(minL, maxL);\n    if(minB > maxB)\n      std::swap(minB, maxB);\n\n    // colorbar needed?\n    // ----------------\n    Bool needColorBar = FALSE;\n    for(UInt i=0; i<layer.size(); i++)\n      needColorBar = needColorBar || layer.at(i)->requiresColorBar();\n    if(needColorBar && !colorbar)\n      throw(Exception(\"Layer requires a color bar\"));\n\n    // calculate min and max\n    // ---------------------\n    if(needColorBar)\n    {\n      Double vmin =  1e99;\n      Double vmax = -1e99;\n      for(UInt i=0; i<layer.size(); i++)\n        layer.at(i)->getIntervalZ(colorbar->isLogarithmic(), vmin, vmax);\n      colorbar->setAutoInterval(vmin, vmax);\n    }\n\n    plotBasics.optionsString += \" PROJ_ELLIPSOID=\"+a%\"%f\"s + f%\"/%f\"s;\n    if(std::isnan(plotBasics.height))\n    {\n      plotBasics.height = projection->aspectRatio() * plotBasics.width;\n      if(projection->aspectRatio() == 0)\n        plotBasics.height = (maxB-minB)/(maxL-minL) * plotBasics.width;\n    }\n\n    // create data files\n    // -----------------\n    logStatus<<\"create temporary data files\"<<Log::endl;\n    for(UInt i=0; i<layer.size(); i++)\n      layer.at(i)->writeDataFile(ellipsoid, plotBasics.workingDirectory, i);\n\n    // calculate annotation\n    // --------------------\n    Double margin = (annotation!=0) ? 0.5 : 0.0;\n\n    // create scriptfile\n    // -----------------\n    logStatus<<\"create scriptfile\"<<Log::endl;\n    {\n      OutFile file(plotBasics.fileNameScript());\n      file<<plotBasics.scriptHeader();\n      if(statisticInfos)\n        for(UInt i=0; i<layer.size(); i++)\n          file<<layer.at(i)->scriptStatisticsInfo(plotBasics.titleSize, plotBasics.width, plotBasics.workingDirectory, i);\n      if(colorbar)\n        file<<colorbar->scriptColorTable();\n      file<<std::endl;\n      file<<PlotBasics::scriptSetVariable(\"region\", RAD2DEG*minL%\"%g/\"s+RAD2DEG*maxL%\"%g/\"s+RAD2DEG*minB%\"%g/\"s+RAD2DEG*maxB%\"%g\"s)<<std::endl;\n      file<<PlotBasics::scriptSetVariable(\"projection\", projection->scriptEntry(plotBasics.width, plotBasics.height).substr(2))<<std::endl;\n      file<<\"gmt psbasemap -Y\"<<-plotBasics.height-margin-plotBasics.marginTitle<<\"c \"<<projection->scriptEntry(plotBasics.width, plotBasics.height);\n      file<<\" -R\"<<PlotBasics::scriptVariable(\"region\")<<\" -Bg\"<<grid*RAD2DEG<<\"a\"<<annotation*RAD2DEG<<\"f\"<<frame*RAD2DEG<<\"WSNE -O -K >> groopsPlot.ps\"<<std::endl;\n      for(UInt i=0; i<layer.size(); i++)\n        file<<layer.at(i)->scriptEntry();\n      file<<\"gmt psbasemap -J -R -BWSNE -Ba\"<<annotation*RAD2DEG<<\"f\"<<frame*RAD2DEG<<\"g\"<<(plotBasics.drawGridOnTop ? grid*RAD2DEG : 0.)<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      if(colorbar)\n        file<<colorbar->scriptEntry(plotBasics.width, plotBasics.height, margin, margin);\n      for(UInt i=0; i<layer.size(); i++)\n        file<<layer.at(i)->legendEntry(plotBasics.workingDirectory, i);\n      file<<plotBasics.scriptTrailer();\n    }\n\n    // run scriptfile\n    // --------------\n    logStatus<<\"run scriptfile\"<<Log::endl;\n    plotBasics.runScript();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/plot/plotMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file plotMatrix.cpp\n*\n* @brief Plot coefficients of a Matrix.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2008-08-29\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nPlot the coefficients of a \\configFile{inputfileMatrix}{matrix}\nusing the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\n\\fig{!hb}{0.6}{plotMatrix}{fig:plotMatrix}{Upper left part of the DDK filter matrix.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"files/fileMatrix.h\"\n#include \"plot/plotColorbar.h\"\n#include \"plot/plotMisc.h\"\n\n/***********************************************/\n\n/** @brief Plot coefficients of a Matrix.\n* @ingroup programsGroup */\nclass PlotMatrix\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlotMatrix, SINGLEPROCESS, \"Plot coefficients of a Matrix.\", Plot, Matrix)\n\n/***********************************************/\n\nvoid PlotMatrix::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        fileNamePlot;\n    FileName        fileNameMatrix;\n    std::string     title;\n    UInt            minY, maxY=NULLINDEX, minX, maxX=NULLINDEX;\n    Double          annotationX=NAN_EXPR, frameX=NAN_EXPR, gridX=NAN_EXPR;\n    Double          annotationY=NAN_EXPR, frameY=NAN_EXPR, gridY=NAN_EXPR;\n    PlotLinePtr     gridLine;\n    PlotColorbarPtr colorbar;\n    PlotBasics      plotBasics;\n\n    renameDeprecatedConfig(config, \"annotationX\", \"majorTickSpacingX\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frameX\",      \"minorTickSpacingX\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"gridX\",       \"gridLineSpacingX\",  date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"annotationY\", \"majorTickSpacingY\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frameY\",      \"minorTickSpacingY\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"gridY\",       \"gridLineSpacingY\",  date2time(2020, 4, 23));\n\n    readConfig(config, \"outputfile\",        fileNamePlot,   Config::MUSTSET,  \"\", \"*.png, *.jpg, *.eps, ...\");\n    readConfig(config, \"title\",             title,          Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"inputfileMatrix\",   fileNameMatrix, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"minColumn\",         minX,           Config::DEFAULT,  \"0\", \"minimum column index to plot\");\n    readConfig(config, \"maxColumn\",         maxX,           Config::OPTIONAL, \"\",  \"maximum column index to plot\");\n    readConfig(config, \"majorTickSpacingX\", annotationX,    Config::OPTIONAL, \"\",  \"boundary annotation\");\n    readConfig(config, \"minorTickSpacingX\", frameX,         Config::OPTIONAL, \"\",  \"frame tick spacing\");\n    readConfig(config, \"gridLineSpacingX\",  gridX,          Config::OPTIONAL, \"\",  \"gridline spacing\");\n    readConfig(config, \"minRow\",            minY,           Config::DEFAULT,  \"0\", \"minimum row index to plot\");\n    readConfig(config, \"maxRow\",            maxY,           Config::OPTIONAL, \"\",  \"maximum row index to plot\");\n    readConfig(config, \"majorTickSpacingY\", annotationY,    Config::OPTIONAL, \"\",  \"boundary annotation\");\n    readConfig(config, \"minorTickSpacingY\", frameY,         Config::OPTIONAL, \"\",  \"frame tick spacing\");\n    readConfig(config, \"gridLineSpacingY\",  gridY,          Config::OPTIONAL, \"\",  \"gridline spacing\");\n    readConfig(config, \"gridLine\",          gridLine,       Config::OPTIONAL, R\"({\"solid\": {\"width\":\"0.25\", \"color\":\"gray\"}})\", \"The style of the grid lines.\");\n    readConfig(config, \"colorbar\",          colorbar,       Config::MUSTSET,  \"\",  \"\");\n    plotBasics.read(config, \"PlotMatrix\", fileNamePlot, title, \"12\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ===========================================================\n\n    // read matrix\n    // -----------\n    logStatus<<\"read matrix\"<<Log::endl;\n    Matrix M;\n    readFileMatrix(fileNameMatrix, M);\n    if(M.getType()==Matrix::SYMMETRIC)\n      fillSymmetric(M);\n\n    // calculate min and max\n    // ---------------------\n    if(maxX==NULLINDEX) maxX = M.columns()-1;\n    if(maxY==NULLINDEX) maxY = M.rows()-1;\n    Double minZ =  1e99;\n    Double maxZ = -1e99;\n    for(UInt z=0; z<M.rows(); z++)\n      for(UInt s=0; s<M.columns(); s++)\n      {\n        if(colorbar->isLogarithmic())\n          M(z,s) = std::fabs(M(z,s));\n        if(M(z,s) || !colorbar->isLogarithmic())\n        {\n          minZ = std::min(minZ, M(z,s));\n          maxZ = std::max(maxZ, M(z,s));\n        }\n      }\n    colorbar->setAutoInterval(minZ, maxZ);\n\n    logInfo<<\"  matrix dimension: (\"<<M.rows()<<\" x \"<<M.columns()<<\")\"<<Log::endl;\n    logInfo<<\"  plot z range  (\"<<colorbar->getMin()<<\" .. \"<<colorbar->getMax()<<\") of (\"<<minZ<<\" .. \"<<maxZ<<\")\"<<Log::endl;\n\n    // determine annotation x\n    const Double scaleX = std::pow(10.0, 1-std::ceil(std::log10(maxX-minX))); // only one significant digit\n    const Double scaleY = std::pow(10.0, 1-std::ceil(std::log10(maxY-minY))); // only one significant digit\n    if(std::isnan(gridX)) gridX = std::max(1., std::round((maxX-minX)*scaleX)/(scaleX*10));\n    if(std::isnan(gridY)) gridY = std::max(1., std::round((maxY-minY)*scaleY)/(scaleY*10));\n\n    if(std::isnan(plotBasics.height))\n      plotBasics.height = plotBasics.width*(maxY-minY)/(maxX-minX);\n\n    // write data files\n    // ----------------\n    logStatus<<\"create temporary data files\"<<Log::endl;\n    {\n      OutFile file(plotBasics.workingDirectory.append(\"data.dat\"), std::ios::out | std::ios::binary);\n      for(UInt z=minY; z<=std::min(maxY, M.rows()-1); z++)\n        for(UInt s=minX; s<=std::min(maxX, M.columns()-1); s++)\n          if(M(z,s))\n          {\n            std::vector<Double> line = {Double(s), Double(z), M(z,s)};\n            file.write(reinterpret_cast<char*>(line.data()), line.size()*sizeof(Double));\n          }\n    }\n\n    // create scriptfile\n    // -----------------\n    logStatus<<\"create scriptfile\"<<Log::endl;\n    {\n      OutFile file(plotBasics.fileNameScript());\n      file<<plotBasics.scriptHeader();\n      file<<colorbar->scriptColorTable();\n      file<<\"gmt psbasemap -Y\"<<-plotBasics.height-plotBasics.marginTitle<<\"c -R\"<<minX-0.5<<\"/\"<<maxX+0.5<<\"/\"<<minY-0.5<<\"/\"<<maxY+0.5<<\" -JX\"<<plotBasics.width<<\"c/\"<<-plotBasics.height<<\"c\";\n      file<<\" -BWSne -Bx\"<<PlotBasics::axisTicks(FALSE, minX, maxX, annotationX, frameX, 0)<<\" -By\"<<PlotBasics::axisTicks(FALSE, minY, maxY, annotationY, frameY, 0);\n      file<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<\"gmt xyz2grd data.dat -bi3d -Gdata.grd -r -V -I1 -R\"<<std::endl;\n      file<<\"gmt grdimage  data.grd --COLOR_NAN=255/255/255 -Q -R -J -CgroopsPlot.cpt\";\n      if(gridLine)\n        file<<\" -Bxg\"<<gridX<<\"-0.5 -Byg\"<<gridY<<\"-0.5 --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str();\n      file<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<colorbar->scriptEntry(plotBasics.width, plotBasics.height, 0.0/*marginX*/, 0.8/*marginY*/);\n      file<<plotBasics.scriptTrailer();\n    } // end scriptfile\n\n    // run scriptfile\n    // --------------\n    logStatus<<\"run scriptfile\"<<Log::endl;\n    plotBasics.runScript();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/plot/plotSphericalHarmonicsTriangle.cpp",
    "content": "/***********************************************/\n/**\n* @file plotSphericalHarmonicsTriangle.cpp\n*\n* @brief Plot triangle of potential coefficients.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2008-08-29\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nPlot the potential coefficients of a spherical harmonic expansion\nusing the GMT Generic Mapping Tools (\\url{https://www.generic-mapping-tools.org}).\nA variety of image file formats are supported (e.g. png, jpg, eps) determined by the extension of \\config{outputfile}.\n\nThis program plots the formal errors (sigmas).\nIf \\configClass{gravityfield}{gravityfieldType} provides no sigmas\ne.g. with \\config{setSigmasToZero} in \\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\nthe coefficients itself are plotted instead.\n\nThe plot programs create a temporary directory in the path of \\config{outputfile}, writes all needed data into it,\ngenerates a batch/shell script with the GMT commands, execute it, and remove the temporary directory.\nWith setting \\config{options:removeFiles}=false the last step is skipped and it is possible to adjust the plot manually\nto specific publication needs. Individual GMT settings are adjusted with \\config{options:options}=\"\\verb|FORMAT=value|\",\nsee \\url{https://docs.generic-mapping-tools.org/latest/gmt.conf.html}.\n\n\\fig{!hb}{0.8}{plotSphericalHarmonicsTriangle}{fig:plotSphericalHarmonicsTriangle}{Formal errors of GOCO06s.}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"plot/plotColorbar.h\"\n#include \"plot/plotMisc.h\"\n\n/***********************************************/\n\n/** @brief Plot triangle of potential coefficients.\n* @ingroup programsGroup */\nclass PlotSphericalHarmonicsTriangle\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PlotSphericalHarmonicsTriangle, SINGLEPROCESS, \"Plot triangle of potential coefficients\", Plot, PotentialCoefficients)\n\n/***********************************************/\n\nvoid PlotSphericalHarmonicsTriangle::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName        fileNamePlot;\n    std::string     title;\n    GravityfieldPtr gravityfield;\n    Double          annotation=NAN_EXPR, frame=NAN_EXPR, grid=NAN_EXPR;\n    Time            time;\n    UInt            minDegree=0, maxDegree=INFINITYDEGREE;\n    PlotLinePtr     gridLine;\n    PlotColorbarPtr colorbar;\n    PlotBasics      plotBasics;\n\n    renameDeprecatedConfig(config, \"annotation\", \"majorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"frame\",      \"minorTickSpacing\", date2time(2020, 4, 23));\n    renameDeprecatedConfig(config, \"grid\",       \"gridLineSpacing\",  date2time(2020, 4, 23));\n\n    readConfig(config, \"outputfile\",       fileNamePlot,  Config::MUSTSET,  \"\",  \"*.png, *.jpg, *.eps, ...\");\n    readConfig(config, \"title\",            title,         Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"gravityfield\",     gravityfield,  Config::MUSTSET,  \"\",  \"use sigmas, if not given use signal (cnm,snm)\");\n    readConfig(config, \"time\",             time,          Config::OPTIONAL, \"\",  \"at this time the gravity field will be evaluated\");\n    readConfig(config, \"minDegree\",        minDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"maxDegree\",        maxDegree,     Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"majorTickSpacing\", annotation,    Config::OPTIONAL, \"\",  \"boundary annotation\");\n    readConfig(config, \"minorTickSpacing\", frame,         Config::OPTIONAL, \"\",  \"frame tick spacing\");\n    readConfig(config, \"gridLineSpacing\",  grid,          Config::DEFAULT,  \"0\", \"gridline spacing\");\n    readConfig(config, \"gridLine\",         gridLine,      Config::OPTIONAL, R\"({\"solid\": {\"width\":\"0.25\", \"color\":\"gray\"}})\", \"The style of the grid lines.\");\n    readConfig(config, \"colorbar\",         colorbar,      Config::MUSTSET,  R\"({\"logarithmic\":\"1\"})\", \"\");\n    plotBasics.read(config, \"PlotSphericalHarmonicsTriangle\", fileNamePlot, title, \"12\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // ===========================================================\n\n    logStatus<<\"use accuracies, if not given use signal\"<<Log::endl;\n    SphericalHarmonics harm = gravityfield->sphericalHarmonics(time, maxDegree, minDegree);\n    maxDegree = harm.maxDegree();\n    Matrix cnm = harm.sigma2cnm();\n    Matrix snm = harm.sigma2snm();\n    if(cnm.size() == 0)\n      cnm = snm = Matrix(maxDegree+1, Matrix::TRIANGULAR, Matrix::LOWER);\n    for(UInt n=minDegree; n<=maxDegree; n++)\n      for(UInt m=0; m<=n; m++)\n      {\n        cnm(n,m) = cnm(n,m) ? std::sqrt(cnm(n,m)) : harm.cnm()(n,m);\n        snm(n,m) = snm(n,m) ? std::sqrt(snm(n,m)) : harm.snm()(n,m);\n      }\n\n    // calculate min and max\n    // ---------------------\n    Double minZ =  1e99;\n    Double maxZ = -1e99;\n    for(UInt n=minDegree; n<=maxDegree; n++)\n      for(UInt m=0; m<=n; m++)\n      {\n        if(colorbar->isLogarithmic())\n        {\n          cnm(n,m) = std::fabs(cnm(n,m));\n          snm(n,m) = std::fabs(snm(n,m));\n        }\n        if(cnm(n,m))\n        {\n          minZ = std::min(minZ, cnm(n,m));\n          maxZ = std::max(maxZ, cnm(n,m));\n        }\n        if(snm(n,m))\n        {\n          minZ = std::min(minZ, snm(n,m));\n          maxZ = std::max(maxZ, snm(n,m));\n        }\n      }\n    colorbar->setAutoInterval(minZ, maxZ);\n\n    if(std::isnan(plotBasics.height))\n      plotBasics.height = plotBasics.width*(maxDegree+1-minDegree)/(2*maxDegree+1);\n    const Double shiftX = plotBasics.width*maxDegree/(2*maxDegree+1);\n\n    // write data files\n    // ----------------\n    logStatus<<\"create temporary data files\"<<Log::endl;\n    {\n      OutFile file1(plotBasics.workingDirectory.append(\"data.cnm.dat\"), std::ios::out | std::ios::binary);\n      OutFile file2(plotBasics.workingDirectory.append(\"data.snm.dat\"), std::ios::out | std::ios::binary);\n      for(UInt n=minDegree; n<=maxDegree; n++)\n        for(UInt m=0; m<=n; m++)\n        {\n          if(cnm(n,m))\n          {\n            const std::vector<Double> line = {Double(n), Double(m), cnm(n,m)};\n            file1.write(reinterpret_cast<const char*>(line.data()), line.size()*sizeof(Double));\n          }\n          if(snm(n,m))\n          {\n            const std::vector<Double> line = {Double(n), Double(m), snm(n,m)};\n            file2.write(reinterpret_cast<const char*>(line.data()), line.size()*sizeof(Double));\n          }\n        }\n    }\n\n    // create scriptfile\n    // -----------------\n    logStatus<<\"create scriptfile\"<<Log::endl;\n    {\n      OutFile file(plotBasics.fileNameScript());\n      file<<plotBasics.scriptHeader();\n      if(colorbar)\n        file<<colorbar->scriptColorTable();\n      file<<std::endl;\n      file<<\"gmt psbasemap -Y\"<<-plotBasics.height-plotBasics.marginTitle<<\"c -R0.5/\"<<maxDegree+0.5<<\"/-0.5/\"<<maxDegree+0.5<<\" -JX\"<<-shiftX<<\"c/\"<<-plotBasics.height<<\"c -BWSn\";\n      file<<\" -Bx\"<<PlotBasics::axisTicks(FALSE, 0.5, maxDegree+0.5, annotation, frame, 0, \"\", \"s@-nm@-\");\n      file<<\" -By\"<<PlotBasics::axisTicks(FALSE, 0.5, maxDegree+0.5, annotation, frame, 0, \"\", \"degree\");\n      file<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<\"gmt xyz2grd   data.snm.dat -Gdata.snm.grd -: -r -bi3d -I1 -R\"<<std::endl;\n      file<<\"gmt grdimage  data.snm.grd --COLOR_NAN=255/255/255 -Q -R -J -CgroopsPlot.cpt -B -O -K >> groopsPlot.ps\"<<std::endl;\n      if(grid > 0)\n        file<<\"gmt psbasemap -R -J -Bwsn -Bg\"<<grid<<\"-0.5 --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<std::endl;\n      file<<\"gmt psbasemap -X\"<<shiftX<<\"c -Y0c -R-0.5/\"<<maxDegree+0.5<<\"/-0.5/\"<<maxDegree+0.5<<\" -JX\"<<plotBasics.width*(maxDegree+1)/(2*maxDegree+1)<<\"c/-\"<<plotBasics.height<<\"c -BSEn\";\n      file<<\" -Bx\"<<PlotBasics::axisTicks(FALSE, 0.5, maxDegree+0.5, annotation, frame, 0, \"\", \"c@-nm@-\");\n      file<<\" -By\"<<PlotBasics::axisTicks(FALSE, 0.5, maxDegree+0.5, annotation, frame, 0, \"\", \"\");\n      file<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<\"gmt xyz2grd   data.cnm.dat -Gdata.cnm.grd -: -r -bi3d  -I1 -R\"<<std::endl;\n      file<<\"gmt grdimage  data.cnm.grd --COLOR_NAN=255/255/255 -Q -R -J -CgroopsPlot.cpt -B -O -K >> groopsPlot.ps\"<<std::endl;\n      if(grid > 0)\n        file<<\"gmt psbasemap -R -J -Besn -Bg\"<<grid<<\"-0.5 --MAP_GRID_PEN_PRIMARY=\"<<gridLine->str()<<\" -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<\"gmt psxy -X\"<<-shiftX<<\"c -R -J -T -O -K >> groopsPlot.ps\"<<std::endl;\n      file<<std::endl;\n      if(colorbar)\n        file<<colorbar->scriptEntry(plotBasics.width, plotBasics.height, 0.8/*marginX*/, 0.8/*marginY*/);\n      file<<plotBasics.scriptTrailer();\n    } // end scriptfile\n\n    // run scriptfile\n    // --------------\n    logStatus<<\"run scriptfile\"<<Log::endl;\n    plotBasics.runScript();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingDualSst.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingDualSst.cpp\n*\n* @brief Estimate covariance function / arc weights for two simultaneous SST-ll observations.\n*\n* @author Torsten Mayer-Guerr\n* @author Andreas Kvas\n* @date 2019-11-25\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis programs processes satellite-to-satellite-tracking (SST) and orbit observations in a GRACE like configuration.\nFour different observation groups are considered separately: two types of SST and POD1/POD2 for the two satellites.\nThis program works similar to \\program{PreprocessingSst}, see there for details. Here only the settings explained,\nwhich are different.\n\nBoth SST observation types are reduced by the same background models and the same impact\nof accelerometer measurements. The covariance matrix of the reduced observations should not consider\nthe the instrument noise only (\\configClass{covarianceSst1/2}{covarianceSstType}) but must\ntake the cross correlations \\configClass{covarianceAcc}{covarianceSstType} into account.\nThe covariance matrix of the reduced observations is given by\n\\begin{equation}\n  \\M\\Sigma(\\begin{bmatrix} \\Delta l_{SST1} \\\\ \\Delta l_{SST2} \\end{bmatrix})\n  = \\begin{bmatrix} \\M\\Sigma_{SST1} + \\M\\Sigma_{ACC} & \\M\\Sigma_{ACC} \\\\\n                   \\M\\Sigma_{ACC} & \\M\\Sigma_{SST2} + \\M\\Sigma_{ACC}\n    \\end{bmatrix}.\n\\end{equation}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"misc/observation/observationMiscDualSstVariational.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"misc/kalmanProcessing.h\"\n#include \"misc/normalsShortTimeStaticLongTime.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate covariance function / arc weights.\n* @ingroup programsGroup */\nclass PreprocessingDualSst\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\nprivate:\n  ObservationMiscDualSstVariationalPtr observationMisc;\n  std::vector<ObservationMiscDualSstVariational::Arc> observationArc;\n  InstrumentFile                       fileCovEpochPod1, fileCovEpochPod2;\n  std::vector<UInt>                    arcsInterval;\n  std::vector<Time>                    timesInterval;\n\n  static constexpr UInt TYPESIZE = 5;\n  enum Type : UInt {SST1, SST2, ACC, POD1, POD2};\n  std::array<std::string, TYPESIZE> typeName; // = {\"SST1\", \"SST2, \"ACC\", \"POD1\", \"POD2\"};\n\n  Bool estimateCovarianceFunctionVCE;\n  Bool estimateArcSigmas;\n  Bool estimateEpochSigmas;\n  Bool estimateResiduals;\n  Bool estimateSigmaShortTimeModel;\n\n  // normal equations\n  // ----------------\n  NormalsShortTimeStaticLongTime normals;\n  Matrix x;  // solution\n  Matrix Wz; // monte carlo vector for redundancy computation\n\n  // covariance\n  std::array<UInt,   TYPESIZE> covColumns;\n  std::array<Vector, TYPESIZE> sigma, sigmaNew;\n  std::array<Matrix, TYPESIZE> covFunc, Psd, ePe, redundancy, CosTransform;\n  std::array<Double, TYPESIZE> sampling;\n  std::array<std::vector<ObservationSigmaArc>, TYPESIZE> arcListEpochSigma;\n  std::array<std::vector<std::vector<Matrix>>, TYPESIZE> Cov; // Several independant matrices per arc\n  std::array<Vector, TYPESIZE> sigmaCov;\n  Double                       interpolationDegree;\n\n  // residuals\n  std::array<std::vector<Arc>, TYPESIZE> arcListResiduals;\n\n  UInt findInterval(UInt arcNo) const;\n  void decorrelate(UInt arcNo, std::array<Matrix, TYPESIZE> &Cov, std::array<Matrix, TYPESIZE> &W, const std::list<MatrixSlice> &A);\n  void buildNormals(UInt arcNo);\n  void computeRedundancies(UInt arcNo);\n  void computeResiduals(UInt arcNo);\n  void computeEpochSigmas(UInt arcNo);\n\n  // Dual SST PSD VCE\n  void varianceComponentEstimationPsd(const_MatrixSliceRef R, const_MatrixSliceRef WWe, const std::array<std::vector<Time>, TYPESIZE> &times,\n                                      const std::array<std::vector<UInt>, TYPESIZE> &index, const std::array<Double, TYPESIZE> &sigma,\n                                      const std::array<Matrix, TYPESIZE> &CosTransform, const std::array<Matrix, TYPESIZE> &Psd,\n                                      std::array<Matrix, TYPESIZE> &ePe, std::array<Matrix, TYPESIZE> &redundancy,\n                                      std::array<Double, TYPESIZE> &ePeSum, std::array<Double, TYPESIZE> &redundancySum);\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingDualSst, PARALLEL, \"Estimate covariance function / arc weights.\", Preprocessing, Covariance, Residuals, KalmanFilter)\n\n/***********************************************/\n/***********************************************/\n\nvoid PreprocessingDualSst::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    typeName   = {\"SST1\", \"SST2\", \"ACC\", \"POD1\", \"POD2\"};\n    covColumns = {1, 1, 1, 3, 3};\n    estimateCovarianceFunctionVCE = estimateArcSigmas = estimateEpochSigmas = estimateResiduals = FALSE;\n    estimateSigmaShortTimeModel = FALSE;\n\n    FileName                       fileNameSolution, fileNameSigmax, fileNameParaName;\n    std::array<FileName, TYPESIZE> fileNameOutArcSigma, fileNameOutEpochSigma, fileNameOutCovFunc, fileNameResiduals;\n    std::array<FileName, TYPESIZE> fileNameInArcSigma, fileNameInEpochSigma, fileNameInCovFunc;\n    std::array<std::vector<FileName>, TYPESIZE> fileNamesInCov;\n    std::array<FileName, TYPESIZE> fileNameInSigmasCov;\n    FileName                       fileNameInCovEpochPod1,  fileNameInCovEpochPod2;\n    std::array<Double, TYPESIZE>   sigma0; sigma0.fill(1.0);\n    AutoregressiveModelSequencePtr arSequence;\n    ParameterSelectorPtr           parameterShortTime;\n    Double                         downweightPod;\n    FileName                       fileNameArcList;\n    UInt                           iterCount;\n    std::string                    iterVariableName;\n    UInt                           defaultBlockSize;\n\n    readConfig(config, \"outputfileSolution\",      fileNameSolution, Config::OPTIONAL, \"\", \"estimated parameter vector (static part only)\");\n    readConfig(config, \"outputfileSigmax\",        fileNameSigmax,   Config::OPTIONAL, \"\", \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n    readConfig(config, \"outputfileParameterName\", fileNameParaName, Config::OPTIONAL, \"\", \"estimated signal parameters (index is appended)\");\n    if(readConfigSequence(config, \"estimateArcSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateArcSigmas = TRUE;\n      readConfig(config, \"outputfileSigmasPerArcSst1\", fileNameOutArcSigma.at(SST1), Config::OPTIONAL, \"\", \"accuracies of each arc (SST1)\");\n      readConfig(config, \"outputfileSigmasPerArcSst2\", fileNameOutArcSigma.at(SST2), Config::OPTIONAL, \"\", \"accuracies of each arc (SST2)\");\n      readConfig(config, \"outputfileSigmasPerArcAcc\",  fileNameOutArcSigma.at(ACC),  Config::OPTIONAL, \"\", \"accuracies of each arc (ACC)\");\n      readConfig(config, \"outputfileSigmasPerArcPod1\", fileNameOutArcSigma.at(POD1), Config::OPTIONAL, \"\", \"accuracies of each arc (POD1)\");\n      readConfig(config, \"outputfileSigmasPerArcPod2\", fileNameOutArcSigma.at(POD2), Config::OPTIONAL, \"\", \"accuracies of each arc (POD2)\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateEpochSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateEpochSigmas = TRUE;\n      readConfig(config, \"outputfileSigmasPerEpochSst1\", fileNameOutEpochSigma.at(SST1), Config::OPTIONAL, \"\", \"accuracies of each epoch (SST1)\");\n      readConfig(config, \"outputfileSigmasPerEpochSst2\", fileNameOutEpochSigma.at(SST2), Config::OPTIONAL, \"\", \"accuracies of each epoch (SST2)\");\n      readConfig(config, \"outputfileSigmasPerEpochAcc\",  fileNameOutEpochSigma.at(ACC),  Config::OPTIONAL, \"\", \"accuracies of each epoch (ACC)\");\n      readConfig(config, \"outputfileSigmasPerEpochPod1\", fileNameOutEpochSigma.at(POD1), Config::OPTIONAL, \"\", \"accuracies of each epoch (POD1)\");\n      readConfig(config, \"outputfileSigmasPerEpochPod2\", fileNameOutEpochSigma.at(POD2), Config::OPTIONAL, \"\", \"accuracies of each epoch (POD2)\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateCovarianceFunctions\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateCovarianceFunctionVCE = TRUE;\n      readConfig(config, \"outputfileCovarianceFunctionSst1\", fileNameOutCovFunc.at(SST1), Config::OPTIONAL, \"\", \"covariance function\");\n      readConfig(config, \"outputfileCovarianceFunctionSst2\", fileNameOutCovFunc.at(SST2), Config::OPTIONAL, \"\", \"covariance function\");\n      readConfig(config, \"outputfileCovarianceFunctionAcc\",  fileNameOutCovFunc.at(ACC),  Config::OPTIONAL, \"\", \"covariance function\");\n      readConfig(config, \"outputfileCovarianceFunctionPod1\", fileNameOutCovFunc.at(POD1), Config::OPTIONAL, \"\", \"covariance functions for along, cross, radial direction\");\n      readConfig(config, \"outputfileCovarianceFunctionPod2\", fileNameOutCovFunc.at(POD2), Config::OPTIONAL, \"\", \"covariance functions for along, cross, radial direction\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"computeResiduals\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateResiduals = TRUE;\n      readConfig(config, \"outputfileSst1Residuals\", fileNameResiduals.at(SST1), Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"outputfileSst2Residuals\", fileNameResiduals.at(SST2), Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"outputfileAccResiduals\",  fileNameResiduals.at(ACC),  Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"outputfilePod1Residuals\", fileNameResiduals.at(POD1), Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"outputfilePod2Residuals\", fileNameResiduals.at(POD2), Config::OPTIONAL, \"\", \"\");\n      endSequence(config);\n    }\n    readConfig(config, \"observation\", observationMisc, Config::MUSTSET,  \"\", \"\");\n    if(readConfigSequence(config, \"covarianceSst1\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                              sigma0.at(SST1),               Config::DEFAULT,  \"1\", \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",              fileNameInArcSigma.at(SST1),   Config::OPTIONAL, \"\",  \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",            fileNameInEpochSigma.at(SST1), Config::OPTIONAL, \"\",  \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",        fileNameInCovFunc.at(SST1),    Config::OPTIONAL, \"\",  \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovarianceMatrixArc\",       fileNamesInCov.at(SST1),       Config::OPTIONAL, \"\",  \"Must be given per sst arc with correct dimensions.\");\n      readConfig(config, \"inputfileSigmasCovarianceMatrixArc\", fileNameInSigmasCov.at(SST1),  Config::OPTIONAL, \"\",  \"Vector with one sigma for each <inputfileCovarianceMatrixArc>\");\n      readConfig(config, \"sampling\",                           sampling.at(SST1),             Config::DEFAULT,  \"5\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"covarianceSst2\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                              sigma0.at(SST2),               Config::DEFAULT,  \"1\", \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",              fileNameInArcSigma.at(SST2),   Config::OPTIONAL, \"\",  \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",            fileNameInEpochSigma.at(SST2), Config::OPTIONAL, \"\",  \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",        fileNameInCovFunc.at(SST2),        Config::OPTIONAL, \"\",  \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovarianceMatrixArc\",       fileNamesInCov.at(SST2),       Config::OPTIONAL, \"\",  \"Must be given per sst arc with correct dimensions.\");\n      readConfig(config, \"inputfileSigmasCovarianceMatrixArc\", fileNameInSigmasCov.at(SST2),  Config::OPTIONAL, \"\",  \"Vector with one sigma for each <inputfileCovarianceMatrixArc>\");\n      readConfig(config, \"sampling\",                           sampling.at(SST2),             Config::DEFAULT,  \"2\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"covarianceAcc\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                              sigma0.at(ACC),                Config::DEFAULT,  \"1\", \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",              fileNameInArcSigma.at(ACC),    Config::OPTIONAL, \"\",  \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",            fileNameInEpochSigma.at(ACC),  Config::OPTIONAL, \"\",  \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",        fileNameInCovFunc.at(ACC),     Config::OPTIONAL, \"\",  \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovarianceMatrixArc\",       fileNamesInCov.at(ACC),        Config::OPTIONAL, \"\",  \"Must be given per sst arc with correct dimensions.\");\n      readConfig(config, \"inputfileSigmasCovarianceMatrixArc\", fileNameInSigmasCov.at(ACC),   Config::OPTIONAL, \"\",  \"Vector with one sigma for each <inputfileCovarianceMatrixArc>\");\n      readConfig(config, \"sampling\",                           sampling.at(ACC),              Config::DEFAULT,  \"5\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"covariancePod1\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                        sigma0.at(POD1),               Config::DEFAULT,  \"1\",  \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",        fileNameInArcSigma.at(POD1),   Config::OPTIONAL, \"\",   \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",      fileNameInEpochSigma.at(POD1), Config::OPTIONAL, \"\",   \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",  fileNameInCovFunc.at(POD1),    Config::OPTIONAL, \"\",   \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovariancePodEpoch\",  fileNameInCovEpochPod1,        Config::OPTIONAL, \"\",   \"3x3 epoch covariances\");\n      readConfig(config, \"sampling\",                     sampling.at(POD1),             Config::DEFAULT,  \"30\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"covariancePod2\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                        sigma0.at(POD2),               Config::DEFAULT,  \"1\",  \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",        fileNameInArcSigma.at(POD2),   Config::OPTIONAL, \"\",   \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",      fileNameInEpochSigma.at(POD2), Config::OPTIONAL, \"\",   \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",  fileNameInCovFunc.at(POD2),    Config::OPTIONAL, \"\",   \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovariancePodEpoch\",  fileNameInCovEpochPod2,        Config::OPTIONAL, \"\",   \"3x3 epoch covariances\");\n      readConfig(config, \"sampling\",                     sampling.at(POD2),             Config::DEFAULT,  \"30\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateShortTimeVariations\", Config::OPTIONAL, \"\", \"co-estimate short time gravity field variations\"))\n    {\n      readConfig(config, \"estimateSigma\",               estimateSigmaShortTimeModel, Config::DEFAULT, \"0\", \"estimate standard deviation via VCE\");\n      readConfig(config, \"autoregressiveModelSequence\", arSequence,                  Config::MUSTSET, \"\",  \"AR model sequence for constraining short time gravity variations\");\n      readConfig(config, \"parameterSelection\",          parameterShortTime,          Config::MUSTSET, \"\",  \"parameters describing the short time gravity field\");\n      endSequence(config);\n    }\n    readConfig(config, \"downweightPod\",          downweightPod,    Config::DEFAULT,  \"1\",    \"downweight factor for POD\");\n    readConfig(config, \"inputfileArcList\",       fileNameArcList,  Config::OPTIONAL, \"\",     \"list to correspond points of time to arc numbers\");\n    readConfig(config, \"iterationCount\",         iterCount,        Config::DEFAULT,  \"3\",    \"(maximum) number of iterations for the estimation of calibration parameter and error PSD\");\n    readConfig(config, \"variableNameIterations\", iterVariableName, Config::OPTIONAL, \"\",     \"All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk\");\n    readConfig(config, \"defaultBlockSize\",       defaultBlockSize, Config::DEFAULT,  \"2048\", \"block size of static normal equation blocks\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    // init\n    // ----\n    interpolationDegree        = observationMisc->interpolationDegree;\n    const UInt arcCount        = observationMisc->arcCount();\n    const UInt countAParameter = observationMisc->parameterCount();\n\n    arcsInterval  = {0, arcCount};\n    timesInterval = {Time(), date2time(9999,1,1)};\n    if(!fileNameArcList.empty())\n    {\n      logStatus<<\"read arc list <\"<<fileNameArcList<<\">\"<<Log::endl;\n      readFileArcList(fileNameArcList, arcsInterval, timesInterval);\n    }\n\n    // init arc sigmas\n    // ---------------\n    for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n    {\n      sigma.at(idType) = Vector(arcCount, 1.0);\n      if(!fileNameInArcSigma.at(idType).empty())\n        readFileMatrix(fileNameInArcSigma.at(idType), sigma.at(idType));\n      if(sigma.at(idType).rows()  != arcCount)\n        throw(Exception(\"sigmasPerArc \"+typeName.at(idType)+\" contains wrong number of arcs\"));\n    }\n\n    fileCovEpochPod1.open(fileNameInCovEpochPod1);\n    fileCovEpochPod2.open(fileNameInCovEpochPod2);\n\n    // ===================================================\n\n    // normal equations of short time model\n    // ------------------------------------\n    UInt countShortTimeParameters = 0;\n    std::vector<std::vector<std::vector<Matrix>>> normalsShortTime;\n    if(arSequence)\n    {\n      logStatus<<\"initialize normal equations of short time gravity field model\"<<Log::endl;\n      countShortTimeParameters = arSequence->dimension();\n      normalsShortTime = arSequence->normalEquationSequence();\n    }\n\n    // init normal equations\n    // ---------------------\n    logStatus<<\"initialize normal equations\"<<Log::endl;\n    normals.init(observationMisc, timesInterval, defaultBlockSize, comm, FALSE/*sortStateBeforeGravityParameter*/, countShortTimeParameters, parameterShortTime);\n\n    // parameter names\n    // ---------------\n    if(!fileNameParaName.empty() && Parallel::isMaster(comm))\n    {\n      logStatus<<\"write parameter names <\"<<fileNameParaName<<\">\"<<Log::endl;\n      writeFileParameterName(fileNameParaName, normals.parameterNames);\n    }\n\n    // =============================================\n\n    // setup observation equations\n    // ---------------------------\n    logStatus<<\"set up observation equations\"<<Log::endl;\n    observationArc.resize(arcCount);\n    std::vector<UInt> processNo = Parallel::forEachInterval(arcCount, arcsInterval, [this](UInt arcNo)\n    {\n      const UInt idInterval = findInterval(arcNo);\n      if(timesInterval.size())\n        observationMisc->setInterval(timesInterval.at(idInterval), timesInterval.at(idInterval+1));\n      observationArc.at(arcNo) = observationMisc->computeArc(arcNo);\n    }, comm);\n    observationMisc = nullptr;\n\n    // =============================================\n\n    // set used blocks\n    // ---------------\n    logStatus<<\"setup normal equations\"<<Log::endl;\n    normals.setBlocks(arcsInterval);\n\n    // =============================================\n\n    // read SST covariance matrices\n    // ----------------------------\n    for(UInt idType : {SST1, SST2, ACC})\n    {\n      Cov.at(idType).resize(arcCount);\n      if(fileNamesInCov.at(idType).size())\n      {\n        logStatus<<\"read arc-wise covariance matrices\"<<Log::endl;\n        Parallel::forEachProcess(arcCount, [&](UInt arcNo)\n        {\n          Cov.at(idType).at(arcNo).resize(fileNamesInCov.at(idType).size());\n          for(UInt i=0; i<fileNamesInCov.at(idType).size(); i++)\n            readFileMatrix(fileNamesInCov.at(idType).at(i).appendBaseName(\".arc\"+arcNo%\"%03i\"s), Cov.at(idType).at(arcNo).at(i));\n        }, processNo, comm);\n      }\n\n      sigmaCov.at(idType) = Vector(fileNamesInCov.at(idType).size(), 1.);\n      if(!fileNameInSigmasCov.at(idType).empty())\n        readFileMatrix(fileNameInSigmasCov.at(idType), sigmaCov.at(idType));\n      if(sigmaCov.at(idType).rows() != fileNamesInCov.at(idType).size())\n        throw(Exception(\"Number of sigmas not compatible with number of given arc-wise covariance matrices\"));\n    }\n\n    // =============================================\n\n    // Estimation of common component (ACC) only possible if both SSTs observed together\n    // ---------------------------------------------------------------------------------\n    UInt countArcBothSst = 0;\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      if(observationArc.at(arcNo).times.at(SST1).size() && observationArc.at(arcNo).times.at(SST2).size())\n        countArcBothSst++;\n    Parallel::reduceSum(countArcBothSst, 0, comm);\n    Parallel::broadCast(countArcBothSst, 0, comm);\n    if(countArcBothSst == 0)\n    {\n      logWarningOnce<<\"Estimation of common component (ACC) disabled: Need common SST1 and SST2 observations\"<<Log::endl;\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n        observationArc.at(arcNo).times.at(ACC).clear();\n    }\n\n    // Initalize covariance functions\n    // ------------------------------\n    std::array<UInt, TYPESIZE> covLength; covLength.fill(0);\n    for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n    {\n      // Determine max. length of ovariance functions\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n        if(observationArc.at(arcNo).times.at(idType).size())\n          covLength.at(idType) = std::max(covLength.at(idType), static_cast<UInt>(std::round((observationArc.at(arcNo).times.at(idType).back()-observationArc.at(arcNo).times.at(idType).front()).seconds()/sampling.at(idType))+1));\n      Parallel::reduceMax(covLength.at(idType), 0, comm);\n      Parallel::broadCast(covLength.at(idType), 0, comm);\n\n      // transformation PSD <-> covFunc\n      CosTransform.at(idType) = Vce::cosTransform(covLength.at(idType));\n\n      // init covariance function\n      covFunc.at(idType) = Vce::readCovarianceFunction(fileNameInCovFunc.at(idType),  covLength.at(idType),  covColumns.at(idType), sampling.at(idType));\n      covFunc.at(idType).column(1, covColumns.at(idType))  *= std::pow(sigma0.at(idType), 2);\n      Psd.at(idType) = CosTransform.at(idType) * covFunc.at(idType).column(1, covColumns.at(idType));\n\n      // init epoch sigmas\n      arcListEpochSigma.at(idType).resize(arcCount);\n      if(estimateEpochSigmas)\n      {\n        InstrumentFile file(fileNameInEpochSigma.at(idType));\n        for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n          if(Parallel::myRank(comm) == processNo.at(arcNo))\n          {\n            arcListEpochSigma.at(idType).at(arcNo) = file.readArc(arcNo);\n            if(!arcListEpochSigma.at(idType).at(arcNo).size())\n              for(UInt i=0; i<observationArc.at(arcNo).times.at(idType).size(); i++)\n              {\n                ObservationSigmaEpoch epoch;\n                epoch.time = observationArc.at(arcNo).times.at(idType).at(i);\n                arcListEpochSigma.at(idType).at(arcNo).push_back(epoch);\n              }\n          }\n      } // if(estimateEpochSigmas)\n    } // for(idType)\n\n    // =============================================\n\n    // Iteration\n    // ---------\n    Double sigma2ShortTimeModel = 1.;\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      logInfo<<\"starting iteration \"<<iter<<Log::endl;\n      VariableList variableIteration;\n      if(iterVariableName.size())\n        variableIteration.setVariable(iterVariableName, iter);\n\n      // solve normal equations\n      // ----------------------\n      if(countAParameter)\n      {\n        logStatus<<\"accumulate system of normal equations\"<<Log::endl;\n        normals.setNull();\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {buildNormals(arcNo);}, processNo, comm);\n        logStatus<<\"collect system of normal equations\"<<Log::endl;\n        normals.reduceSum();\n\n        // add normals of short time model\n        // -------------------------------\n        if(normalsShortTime.size())\n        {\n          logStatus<<\"add normals of short time model\"<<Log::endl;\n          normals.addShortTimeNormals(sigma2ShortTimeModel, normalsShortTime);\n        }\n\n        // cholesky and forward step\n        // -------------------------\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        const Double sigma = normals.solve(x, Wz);\n        logInfo<<\"  aposteriori sigma = \"<<sigma<<Log::endl;\n\n        if(Parallel::isMaster(comm) && !fileNameSolution.empty())\n        {\n          logStatus<<\"write solution to <\"<<fileNameSolution(variableIteration)<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameSolution(variableIteration), x);\n        }\n\n        if(!fileNameSigmax.empty())\n        {\n          logStatus<<\"inverte cholesky matrix and write standard deviations to <\"<<fileNameSigmax(variableIteration)<<\">\"<<Log::endl;\n          Vector sigma = normals.parameterStandardDeviation();\n          if(Parallel::isMaster(comm))\n            writeFileMatrix(fileNameSigmax(variableIteration), sigma);\n        } // if(!fileNameSigmax.empty())\n\n        if(estimateSigmaShortTimeModel && normalsShortTime.size())\n        {\n          logStatus<<\"compute standard deviation of short time gravity model\"<<Log::endl;\n          Double s2 = normals.estimateShortTimeNormalsVariance(sigma2ShortTimeModel, normalsShortTime, x, Wz);\n          logInfo<<\"  sigma: \"<<std::sqrt(s2)<<Log::endl;\n          if(!std::isnan(s2) && (s2 > 0))\n            sigma2ShortTimeModel = s2;\n        }\n      } // if(countAParameter)\n      Parallel::barrier(comm);\n\n      // compute residuals\n      // --------------------\n      if(estimateResiduals || estimateEpochSigmas)\n      {\n        logStatus<<\"compute residuals\"<<Log::endl;\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n        {\n          arcListResiduals.at(idType).clear();\n          arcListResiduals.at(idType).resize(arcCount);\n        }\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeResiduals(arcNo);}, processNo, comm);\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n        {\n          Parallel::forEachProcess(arcListResiduals.at(idType), [this, idType](UInt arcNo) {return arcListResiduals.at(idType).at(arcNo);}, processNo, comm, FALSE/*timing*/);\n          if(Parallel::isMaster(comm) && (!fileNameResiduals.at(idType).empty()))\n          {\n            logStatus<<\"write residual file <\"<<fileNameResiduals.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameResiduals.at(idType)(variableIteration), arcListResiduals.at(idType));\n          }\n        }\n      }\n\n      // compute redundancies\n      // --------------------\n      if(estimateArcSigmas || estimateCovarianceFunctionVCE)\n      {\n        logStatus<<\"compute redundancies\"<<Log::endl;\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n        {\n          sigmaNew.at(idType) = Vector(arcCount);\n          ePe.at(idType) = redundancy.at(idType) = Matrix(covLength.at(idType), covColumns.at(idType));\n        }\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeRedundancies(arcNo);}, processNo, comm);\n      }\n\n      // sigmas per arc\n      // --------------\n      if(estimateArcSigmas)\n      {\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n        {\n          Parallel::reduceSum(sigmaNew.at(idType), 0, comm);\n          if(Parallel::isMaster(comm))\n          {\n            sigma.at(idType) = (1./Vce::meanSigma(sigmaNew.at(idType))) * sigmaNew.at(idType);\n            logInfo<<\"  \"<<typeName.at(idType)<<\" sigma per arc (median): \"<<Vce::meanSigma(sigmaNew.at(idType))<<Log::endl;\n            for(UInt arcNo=0; arcNo<sigma.at(idType).size(); arcNo++)\n              if(sigma.at(idType)(arcNo) < 0)\n                sigma.at(idType)(arcNo) = 1;\n          }\n          Parallel::broadCast(sigma.at(idType), 0, comm);\n        }\n\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n          if(Parallel::isMaster(comm) && !fileNameOutArcSigma.at(idType).empty())\n          {\n            logStatus<<\"write arc sigma file <\"<<fileNameOutArcSigma.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            writeFileMatrix(fileNameOutArcSigma.at(idType)(variableIteration), sigma.at(idType));\n          }\n      }\n\n      // sigmas per epoch\n      // --------------\n      if(estimateEpochSigmas)\n      {\n        logStatus<<\"estimate epoch sigmas\"<<Log::endl;\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeEpochSigmas(arcNo);}, processNo, comm);\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n        {\n          Parallel::forEachProcess(arcListEpochSigma.at(idType), [this, idType](UInt arcNo) {return arcListEpochSigma.at(idType).at(arcNo);}, processNo, comm, FALSE/*timing*/);\n          if(Parallel::isMaster(comm) && !fileNameOutEpochSigma.at(idType).empty())\n          {\n            logStatus<<\"write epoch sigma file <\"<<fileNameOutEpochSigma.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameOutEpochSigma.at(idType)(variableIteration), arcListEpochSigma.at(idType));\n          }\n        }\n        Parallel::barrier(comm);\n      } // if(estimateEpochSigmas)\n\n      // estimate new PSD through variance component estimation\n      // ------------------------------------------------------\n      if(estimateCovarianceFunctionVCE)\n      {\n        logStatus<<\"estimate PSDs\"<<Log::endl;\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n        {\n          Parallel::reduceSum(ePe.at(idType), 0, comm);\n          Parallel::reduceSum(redundancy.at(idType), 0, comm);\n          if(Parallel::isMaster(comm))\n          {\n            Double maxFactor = 0;\n            Vce::estimatePsd(ePe.at(idType), redundancy.at(idType), Psd.at(idType), maxFactor);\n            if((idType == POD1) || (idType == POD2))\n              maxFactor /= downweightPod;\n            logInfo<<\"  max. PSD adjustment factor \"<<typeName.at(idType)<<\": \"<<maxFactor<<Log::endl;\n          }\n          Parallel::broadCast(Psd.at(idType), 0, comm);\n          // compute new covariance function\n          copy(CosTransform.at(idType) * Psd.at(idType), covFunc.at(idType).column(1, covColumns.at(idType)));\n        }\n\n        // Write covariance function to file\n        for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n          if(Parallel::isMaster(comm) && !fileNameOutCovFunc.at(idType).empty())\n          {\n            logStatus<<\"write covariance function file <\"<<fileNameOutCovFunc.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            writeFileMatrix(fileNameOutCovFunc.at(idType)(variableIteration), covFunc.at(idType));\n          }\n      }\n\n      // downweight POD\n      // --------------\n      for(UInt idType : {POD1, POD2})\n      {\n        Psd.at(idType) *= std::pow(downweightPod, 2);\n        covFunc.at(idType).column(1, covColumns.at(idType)) *= std::pow(downweightPod, 2);\n      }\n    } // for(iter)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt PreprocessingDualSst::findInterval(UInt arcNo) const\n{\n  for(UInt idInterval=0; idInterval+1<arcsInterval.size(); idInterval++)\n    if(arcNo < arcsInterval.at(idInterval+1))\n      return idInterval;\n  return 0;\n}\n\n/***********************************************/\n\nvoid PreprocessingDualSst::decorrelate(UInt arcNo, std::array<Matrix, TYPESIZE> &Cov, std::array<Matrix, TYPESIZE> &W, const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    const auto &times = observationArc.at(arcNo).times;\n\n    // count observations and calculate index\n    // --------------------------------------\n    std::array<UInt, TYPESIZE> idx;\n    std::array<std::list<MatrixSlice>, TYPESIZE> WA; // type specific slices of A\n    UInt obsCount = 0;\n    for(UInt idType : {SST1, SST2, POD1, POD2})\n    {\n      idx.at(idType) = obsCount;\n      obsCount      += covColumns.at(idType) * times.at(idType).size();\n      for(const MatrixSlice &a : A)\n        WA.at(idType).push_back(a.row(idx.at(idType), covColumns.at(idType) * times.at(idType).size()));\n    }\n\n    if(times.at(SST1).size() || times.at(SST2).size())\n    {\n      std::list<MatrixSlice> WA;\n      for(const MatrixSlice &a : A)\n        WA.push_back(a.row(idx.at(SST1), times.at(SST1).size()+times.at(SST2).size()));\n\n      for(UInt idType : {SST1, SST2, ACC})\n        if(this->Cov.at(idType).at(arcNo).size())\n        {\n          Cov.at(idType) = std::pow(sigmaCov.at(idType).at(0), 2) * this->Cov.at(idType).at(arcNo).at(0);\n          for(UInt i=1; i<this->Cov.at(idType).at(arcNo).size(); i++)\n            axpy(std::pow(sigmaCov.at(idType).at(i), 2), this->Cov.at(idType).at(arcNo).at(i), Cov.at(idType));\n        }\n\n      for(UInt idType : {SST1, SST2, ACC})\n        CovarianceSst::covariance(times.at(idType), sigma.at(idType)(arcNo), arcListEpochSigma.at(idType).at(arcNo), covFunc.at(idType), Cov.at(idType));\n      W.at(ACC) = ObservationMiscDualSstVariational::decorrelate(times.at(SST1), times.at(SST2), times.at(ACC), Cov.at(SST1), Cov.at(SST2), Cov.at(ACC), interpolationDegree, WA);\n    }\n\n    if(times.at(POD1).size())\n      W.at(POD1) = CovariancePod::decorrelate(observationArc.at(arcNo).pod1, sigma.at(POD1)(arcNo), arcListEpochSigma.at(POD1).at(arcNo), fileCovEpochPod1.readArc(arcNo), covFunc.at(POD1), WA.at(POD1));\n\n    if(times.at(POD2).size())\n      W.at(POD2) = CovariancePod::decorrelate(observationArc.at(arcNo).pod2, sigma.at(POD2)(arcNo), arcListEpochSigma.at(POD2).at(arcNo), fileCovEpochPod2.readArc(arcNo), covFunc.at(POD2), WA.at(POD2));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingDualSst::buildNormals(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).A.size() == 0)\n      return;\n\n    // Decorrelation\n    // -------------\n    Matrix Wl = observationArc.at(arcNo).l;\n    Matrix WA = observationArc.at(arcNo).A;\n    Matrix WB = observationArc.at(arcNo).B;\n    std::array<Matrix, TYPESIZE> Cov, W;\n    decorrelate(arcNo, Cov, W, {Wl, WA, WB});\n\n    normals.accumulate(findInterval(arcNo), Wl, WA, WB);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingDualSst::computeRedundancies(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).l.size() == 0)\n      return;\n\n    // count observations and calculate index\n    // --------------------------------------\n    const auto &times = observationArc.at(arcNo).times;\n    std::array<UInt, TYPESIZE> count, idx;\n    UInt obsCount = 0;\n    for(UInt idType : {SST1, SST2, POD1, POD2}) // without ACC\n    {\n      count.at(idType) = times.at(idType).size();\n      idx.at(idType)   = obsCount;\n      obsCount        += covColumns.at(idType) * count.at(idType);\n    }\n    count.at(ACC) = times.at(ACC).size();\n\n    // Decorrelation\n    // -------------\n    Matrix Wl = observationArc.at(arcNo).l;\n    Matrix WA = observationArc.at(arcNo).A;\n    Matrix WB = observationArc.at(arcNo).B;\n    std::array<Matrix, TYPESIZE> Cov, W;\n    decorrelate(arcNo, Cov, W, {Wl, WA, WB});\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    if(WB.size())\n    {\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl);             // transform observations: l:= Q'l\n      Wl.row(0, WB.columns()).setNull();   // residuals: remove WB*x\n      QMult(WB, tau, Wl);                  // back transformation\n      if(WA.size())\n      {\n        QTransMult(WB, tau, WA);           // transform design matrix A:=Q'A\n        WA.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n        QMult(WB, tau, WA);                // back transformation\n      }\n      generateQ(WB, tau);\n    }\n\n    // decorrelated residuals\n    // ----------------------\n    Matrix We = Wl;\n    Matrix WAz(Wl.rows(), Wz.columns());\n    const UInt idInterval = findInterval(arcNo);\n    normals.designMatMult(idInterval, -1., WA, x,  We);\n    normals.designMatMult(idInterval, +1., WA, Wz, WAz);\n\n    // ============================================\n\n    // variance component estimation\n    // -----------------------------\n    Matrix R;\n    Vector WWe;\n    std::array<std::vector<UInt>, TYPESIZE> index;\n    std::array<Double, TYPESIZE> ePeSum, redundancySum; ePeSum.fill(0); redundancySum.fill(0);\n    for(UInt idType : {SST1, SST2, ACC, POD1, POD2})\n    {\n      index.at(idType).resize(times.at(idType).size());\n      for(UInt i=0; i<index.at(idType).size(); i++)\n        index.at(idType).at(i) = static_cast<UInt>(std::round((times.at(idType).at(i)-times.at(idType).front()).seconds()/sampling.at(idType)));\n    }\n\n    if(count.at(SST1) || count.at(SST2))\n    {\n      Vce::redundancy(W.at(ACC), We.row(idx.at(SST1), count.at(SST1)+count.at(SST2)),\n                      WAz.row(idx.at(SST1), count.at(SST1)+count.at(SST2)), WB.row(idx.at(SST1), count.at(SST1)+count.at(SST2)), R, WWe);\n      varianceComponentEstimationPsd(R, WWe, times, index, {sigma.at(SST1)(arcNo), sigma.at(SST2)(arcNo), sigma.at(ACC)(arcNo), 0., 0.},\n                                     CosTransform, Psd, ePe, redundancy, ePeSum, redundancySum);\n    }\n\n    for(UInt idType : {POD1, POD2})\n      if(count.at(idType))\n      {\n        Vce::redundancy(W.at(idType), We.row(idx.at(idType), 3*count.at(idType)),\n                        WAz.row(idx.at(idType), 3*count.at(idType)), WB.row(idx.at(idType), 3*count.at(idType)), R, WWe);\n        Vce::psd(R, WWe, index.at(idType), sigma.at(idType)(arcNo), CosTransform.at(idType), Psd.at(idType),\n                 ePe.at(idType), redundancy.at(idType), ePeSum.at(idType), redundancySum.at(idType));\n      }\n\n    for(UInt idType : {SST1, SST2, ACC, POD1, POD2}) // compute new sigma (for this arc)\n      if(redundancySum.at(idType) > 0.3)\n        sigmaNew.at(idType)(arcNo) = std::sqrt(ePeSum.at(idType)/redundancySum.at(idType)) * sigma.at(idType)(arcNo);\n\n    // estimation of ACC arc sigmas not possible if not both SSTs are observed\n    if((!count.at(SST1) || !count.at(SST2)) && sigmaNew.at(ACC)(arcNo))\n      sigmaNew.at(ACC)(arcNo) = -1;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingDualSst::varianceComponentEstimationPsd(const_MatrixSliceRef R, const_MatrixSliceRef WWe,\n                                                          const std::array<std::vector<Time>, TYPESIZE> &times,\n                                                          const std::array<std::vector<UInt>, TYPESIZE> &index, const std::array<Double, TYPESIZE> &sigma,\n                                                          const std::array<Matrix, TYPESIZE> &CosTransform, const std::array<Matrix, TYPESIZE> &Psd,\n                                                          std::array<Matrix, TYPESIZE> &ePe, std::array<Matrix, TYPESIZE> &redundancy,\n                                                          std::array<Double, TYPESIZE> &ePeSum, std::array<Double, TYPESIZE> &redundancySum)\n{\n  try\n  {\n    std::array<Vector, TYPESIZE> e, r;\n    std::array<UInt, 2> idx = {0, index.at(SST1).size()};\n    for(UInt idType : {SST1, SST2})\n      if(CosTransform.at(idType).rows())\n      {\n        e.at(idType) = r.at(idType) = Vector(CosTransform.at(idType).rows());\n        for(UInt i=0; i<index.at(idType).size(); i++)\n          for(UInt k=i; k<index.at(idType).size(); k++)\n          {\n            e.at(idType)(index.at(idType).at(k)-index.at(idType).at(i)) += WWe(i+idx.at(idType),0) * WWe(k+idx.at(idType),0);\n            r.at(idType)(index.at(idType).at(k)-index.at(idType).at(i)) += R(i+idx.at(idType), k+idx.at(idType));\n          }\n        e.at(idType).row(1, e.at(idType).rows()-1) *= 2.; // consider lower triangular of matrix\n        r.at(idType).row(1, r.at(idType).rows()-1) *= 2.;\n      }\n\n    // mixed term: ACC\n    // ---------------\n    if(CosTransform.at(ACC).rows())\n    {\n      e.at(ACC) = r.at(ACC) = Vector(CosTransform.at(ACC).rows());\n      Polynomial polynomial(times.at(ACC), interpolationDegree);\n      fillSymmetric(R);\n      Matrix WWe1 = polynomial.interpolate(times.at(SST1), WWe.row(idx.at(SST1), index.at(SST1).size()),        1, 0, TRUE/*adjoint*/);  // F1'*WWe1\n      Matrix WWe2 = polynomial.interpolate(times.at(SST2), WWe.row(idx.at(SST2), index.at(SST2).size()),        1, 0, TRUE/*adjoint*/);  // F2'*WWe2\n      Matrix R1   = polynomial.interpolate(times.at(SST1), R.row(idx.at(SST1), index.at(SST1).size()),          1, 0, TRUE/*adjoint*/);  // F1'*(R11,R12)\n      Matrix R12  = polynomial.interpolate(times.at(SST2), R1.trans().row(idx.at(SST2), index.at(SST2).size()), 1, 0, TRUE/*adjoint*/);  // F2'*R12'*F1\n             R1   = polynomial.interpolate(times.at(SST1), R1.trans().row(idx.at(SST1), index.at(SST1).size()), 1, 0, TRUE/*adjoint*/);  // F1'*R11*F1\n      Matrix R2   = polynomial.interpolate(times.at(SST2), R.slice(idx.at(SST2), idx.at(SST2), index.at(SST2).size(), index.at(SST2).size()), 1, 0, TRUE); // F2'*R22\n             R2   = polynomial.interpolate(times.at(SST2), R2.trans(),                                          1, 0, TRUE/*adjoint*/);  // F2'*R22*F2\n\n      for(UInt i=0; i<index.at(ACC).size(); i++)\n        for(UInt k=0; k<index.at(ACC).size(); k++)\n        {\n          const UInt idiff = (i < k) ? (index.at(ACC).at(k)-index.at(ACC).at(i)) : (index.at(ACC).at(i)-index.at(ACC).at(k));\n          e.at(ACC)(idiff) += WWe1(i,0)*WWe1(k,0) +  WWe2(i,0)*WWe2(k,0) + WWe1(i,0)*WWe2(k,0) + WWe2(i,0)*WWe1(k,0);\n          r.at(ACC)(idiff) += R1(i,k) + R2(i,k) + R12(i,k) + R12(k,i);\n        }\n    }\n\n    for(UInt idType : {SST1, SST2, ACC})\n      for(UInt idFreq=0; idFreq<Psd.at(idType).rows(); idFreq++)\n      {\n        const Double ePeTmp        = std::pow(sigma.at(idType), 2) * Psd.at(idType)(idFreq, 0) * inner(e.at(idType), CosTransform.at(idType).column(idFreq));\n        const Double redundancyTmp = std::pow(sigma.at(idType), 2) * Psd.at(idType)(idFreq, 0) * inner(r.at(idType), CosTransform.at(idType).column(idFreq));\n        ePe.at(idType)(idFreq, 0)        += ePeTmp;\n        redundancy.at(idType)(idFreq, 0) += redundancyTmp;\n        ePeSum.at(idType)                += ePeTmp;\n        redundancySum.at(idType)         += redundancyTmp;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingDualSst::computeResiduals(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).l.size() == 0)\n      return;\n\n    // count observations and calculate index\n    // --------------------------------------\n    const auto &times = observationArc.at(arcNo).times;\n    std::array<UInt, TYPESIZE> count, idx;\n    UInt obsCount = 0;\n    for(UInt idType : {SST1, SST2, POD1, POD2}) // without ACC\n    {\n      count.at(idType) = times.at(idType).size();\n      idx.at(idType)   = obsCount;\n      obsCount        += covColumns.at(idType) * count.at(idType);\n    }\n    count.at(ACC) = times.at(ACC).size();\n\n    // Residuals\n    // ---------\n    Matrix e = observationArc.at(arcNo).l;\n    normals.designMatMult(findInterval(arcNo), -1., observationArc.at(arcNo).A, x, e);\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    std::array<Matrix, TYPESIZE> Cov, W;\n    if(observationArc.at(arcNo).B.size())\n    {\n      Matrix We = e;\n      Matrix WB = observationArc.at(arcNo).B;\n      decorrelate(arcNo, Cov, W, {We, WB});\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, We); // transform observations: l:= Q'l\n      Matrix y = We.row(0, tau.rows());\n      triangularSolve(1., WB.row(0, tau.rows()), y);\n      matMult(-1, observationArc.at(arcNo).B, y, e);\n    }\n    else\n      decorrelate(arcNo, Cov, W, {});\n\n    // residuals\n    // ---------\n    std::array<Matrix, TYPESIZE> residuals;\n    if(Cov.at(ACC).size())\n    {\n      Polynomial polynomial(times.at(ACC), interpolationDegree);\n      Matrix WWe = e.row(idx.at(SST1), count.at(SST1)+count.at(SST2));\n      triangularSolve(1., W.at(ACC).trans(), WWe);\n      triangularSolve(1., W.at(ACC),         WWe);\n      residuals.at(SST1) = Cov.at(SST1) * WWe.row(idx.at(SST1), count.at(SST1)); // collocation for residual separation\n      residuals.at(SST2) = Cov.at(SST2) * WWe.row(idx.at(SST2), count.at(SST2));\n      residuals.at(ACC)  = Cov.at(ACC)  * (polynomial.interpolate(times.at(SST1), WWe.row(idx.at(SST1), count.at(SST1)), 1, 0, TRUE/*adjoint*/) +\n                                          polynomial.interpolate(times.at(SST2), WWe.row(idx.at(SST2), count.at(SST2)), 1, 0, TRUE/*adjoint*/));\n    }\n    else\n    {\n      residuals.at(SST1) = e.row(idx.at(SST1), count.at(SST1)); // collocation for residual separation\n      residuals.at(SST2) = e.row(idx.at(SST2), count.at(SST2));\n    }\n    residuals.at(POD1) = e.row(idx.at(POD1), covColumns.at(POD1) * count.at(POD1));\n    residuals.at(POD2) = e.row(idx.at(POD2), covColumns.at(POD2) * count.at(POD2));\n\n    // create Sst arc\n    // --------------\n    for(UInt idType : {SST1, SST2, ACC})\n      for(UInt i=0; i<count.at(idType); i++)\n      {\n        SatelliteTrackingEpoch epoch;\n        epoch.time  = times.at(idType).at(i);\n        epoch.range = epoch.rangeRate = epoch.rangeAcceleration = residuals.at(idType)(i,0);\n        arcListResiduals.at(idType).at(arcNo).push_back(epoch);\n      }\n\n    // create Pod arcs\n    // ---------------\n    for(UInt idType : {POD1, POD2})\n      for(UInt i=0; i<count.at(idType); i++)\n      {\n        OrbitEpoch epoch;\n        epoch.time     = times.at(idType).at(i);\n        epoch.position = Vector3d(residuals.at(idType).row(3*i, 3));\n        arcListResiduals.at(idType).at(arcNo).push_back(epoch);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingDualSst::computeEpochSigmas(UInt arcNo)\n{\n  try\n  {\n    const Double huber = 2.5;\n\n    for(UInt idType : {SST1, SST2, ACC})\n      if(covFunc.at(idType).size())\n      {\n        const Double threshold2 = std::pow(huber*sigma.at(idType)(arcNo), 2) * covFunc.at(idType)(0,1);\n        for(UInt i=0; i<observationArc.at(arcNo).times.at(idType).size(); i++)\n        {\n          const Double e2 = std::pow(dynamic_cast<const SatelliteTrackingEpoch &>(arcListResiduals.at(idType).at(arcNo).at(i)).rangeRate, 2);\n          arcListEpochSigma.at(idType).at(arcNo).at(i).sigma = 0.;\n          if(e2 > threshold2)\n            arcListEpochSigma.at(idType).at(arcNo).at(i).sigma = std::sqrt(e2-threshold2);\n        }\n      }\n\n    for(UInt idType : {POD1, POD2})\n      if(covFunc.at(idType).size())\n      {\n        const Double threshold2 = std::pow(huber*sigma.at(idType)(arcNo), 2) * sum(covFunc.at(idType).slice(0, 1, 1, 3));\n        for(UInt i=0; i<observationArc.at(arcNo).times.at(idType).size(); i++)\n        {\n          const Double e2 = dynamic_cast<const OrbitEpoch &>(arcListResiduals.at(idType).at(arcNo).at(i)).position.quadsum();\n          arcListEpochSigma.at(idType).at(arcNo).at(i).sigma = 0.;\n          if(e2 > threshold2)\n            arcListEpochSigma.at(idType).at(arcNo).at(i).sigma = std::sqrt((e2-threshold2)/3);\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingGradiometer.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingGradiometer.cpp\n*\n* @brief Estimate covariance function / arc weights.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-05-11\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates empirical covariance functions of the gradiometer instrument noise and determine arc wise variances to\ndownweight arcs with outliers. This program works similar to \\program{PreprocessingPod}, see there for details.\nHere only the settings explained, which are different.\n\n...\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"misc/observation/observationMisc.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate covariance function / arc weights.\n* @ingroup programsGroup */\nclass PreprocessingGradiometer\n{\n  SggRightSidePtr            rhs; // right hand sides\n  InstrumentFile             orbitFile;\n  InstrumentFile             starCameraFile;\n  EarthRotationPtr           earthRotation;\n  EphemeridesPtr             ephemerides;\n  ParametrizationTemporalPtr sggBias;\n  Vector                     sigmas, sigmasNew;\n\n  // covariance\n  // ----------\n  Double sampling;\n  UInt   covLength;\n  Matrix covFunc;\n  Matrix CovCholesky;\n  Matrix Psd, ePe, redundancy; // one row for each frequency, one column for each component\n  Matrix CosTransform;\n\n  GradiometerArc computeArc(UInt arc);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingGradiometer, PARALLEL, \"Estimate covariance function / arc weights.\", Preprocessing)\n\n/***********************************************/\n\nvoid PreprocessingGradiometer::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outCovName, outResidualsName, outSigmaName;\n    FileName orbitName, starCameraName, covName;\n    UInt     iterCount;\n\n    readConfig(config, \"outputfileCovarianceFunction\", outCovName,       Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"outputfileSigmasPerArc\",       outSigmaName,     Config::OPTIONAL, \"\", \"accuracies of each arc\");\n    readConfig(config, \"outputfileSggResiduals\",       outResidualsName, Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"rightHandSide\",                rhs,              Config::MUSTSET,  \"\", \"input for the observation vector\");\n    readConfig(config, \"inputfileOrbit\",               orbitName,        Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera\",          starCameraName,   Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"earthRotation\",                earthRotation,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"ephemerides\",                  ephemerides,      Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"parametrizationBias\",          sggBias,          Config::DEFAULT,  \"\",    \"per arc\");\n    if(readConfigSequence(config, \"covarianceSgg\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"inputfileCovarianceFunction\",  covName,   Config::OPTIONAL, \"\",  \"approximate covariances in time\");\n      readConfig(config, \"covarianceLength\",             covLength, Config::MUSTSET,  \"\",  \"counts observation epochs\");\n      readConfig(config, \"sampling\",                     sampling,  Config::MUSTSET,  \"5\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    readConfig(config, \"iterationCount\", iterCount, Config::DEFAULT,  \"3\", \"for the estimation of calibration parameter and error PSD\");\n    if(isCreateSchema(config)) return;\n\n    // ======================================================\n\n    // test instrument files\n    // ---------------------\n    orbitFile.open(orbitName);\n    starCameraFile.open(starCameraName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile, *rhs->gradiometerFile});\n    for(UInt k=0; k<rhs->referenceFile.size(); k++)\n      InstrumentFile::checkArcCount({orbitFile, *rhs->referenceFile.at(k)});\n    const UInt arcCount = orbitFile.arcCount();\n\n    // =======================\n\n    // init covariance function\n    // ------------------------\n    CosTransform = Vce::cosTransform(covLength);\n    covFunc      = Vce::readCovarianceFunction(covName, covLength, 6, sampling);\n    Psd          = CosTransform * covFunc.column(1,6);\n\n    // init arc sigmas\n    // ---------------\n    sigmas = Vector(arcCount);\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      sigmas(arcNo) = 1.0;\n\n    // =============================================\n\n    // Iteration\n    // ---------\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      // new covariance matricies\n      // ------------------------\n      CovCholesky = Matrix(6*covFunc.rows(), Matrix::SYMMETRIC, Matrix::UPPER);\n      for(UInt sggNo=0; sggNo<6; sggNo++)\n        for(UInt i=0; i<covFunc.rows(); i++)\n          for(UInt k=i; k<covFunc.rows(); k++)\n            CovCholesky(6*i+sggNo, 6*k+sggNo) = covFunc(k-i, 1+sggNo);\n      cholesky(CovCholesky);\n\n      logStatus<<\"set up observation equations\"<<Log::endl;\n      ePe        = Matrix(covLength, 6); // xx, xy, xz, yy, yz, zz\n      redundancy = Matrix(covLength, 6);\n      sigmasNew  = Vector(arcCount);\n      std::vector<Arc> arcList(arcCount);\n      Parallel::forEach(arcList, [this](UInt arcNo) {return computeArc(arcNo);}, comm);\n      Parallel::reduceSum(ePe,        0, comm);\n      Parallel::reduceSum(redundancy, 0, comm);\n      Parallel::reduceSum(sigmasNew,  0, comm);\n\n      // sigmas per arc\n      // --------------\n      // median sigma per arc;\n      if(Parallel::isMaster(comm))\n      {\n        sigmas = sigmasNew;\n        Double sigma0 = Vce::meanSigma(sigmas);\n        sigmas *= 1./sigma0;\n\n        logInfo<<\"  sigma per arc (median): \"<<sigma0<<Log::endl;\n\n        if(!outSigmaName.empty())\n        {\n          logStatus<<\"write arc sigma file <\"<<outSigmaName<<\">\"<<Log::endl;\n          writeFileMatrix(outSigmaName, sigmas);\n        }\n      }\n      Parallel::broadCast(sigmas, 0, comm);\n\n      // estimate new PSD\n      // ----------------\n      if(Parallel::isMaster(comm))\n      {\n        Double maxFactor = 0;\n        Vce::estimatePsd(ePe, redundancy, Psd, maxFactor);\n        logInfo<<\"  max. PSD adjustment factor: \"<<maxFactor<<Log::endl;\n      } // if(Parallel::isMaster(comm))\n      Parallel::broadCast(Psd, 0, comm);\n      copy(CosTransform * Psd, covFunc.column(1,Psd.columns())); // compute new covariance function\n\n      if(Parallel::isMaster(comm) && !outCovName.empty())\n      {\n        logStatus<<\"write covariance function file <\"<<outCovName<<\">\"<<Log::endl;\n        writeFileMatrix(outCovName, covFunc);\n      }\n\n      // gradiometer residuals\n      // ---------------------\n      if(Parallel::isMaster(comm) && !outResidualsName.empty())\n      {\n        logStatus<<\"write gradiometer residuals file <\"<<outResidualsName<<\">\"<<Log::endl;\n        InstrumentFile::write(outResidualsName, arcList);\n      }\n    } // for(iter)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nGradiometerArc PreprocessingGradiometer::computeArc(UInt arcNo)\n{\n  try\n  {\n    OrbitArc      orbit      = orbitFile.readArc(arcNo);\n    StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n    UInt          epochCount = orbit.size();\n\n    // =============================================\n\n    // reduced observations\n    // ---------------------\n    GradiometerArc sggArc = rhs->gradiometerFile->readArc(arcNo);\n    Arc::checkSynchronized({sggArc, orbit, starCamera});\n    std::vector<GradiometerArc> reference(rhs->referenceFile.size());\n    for(UInt k=0; k<rhs->referenceFile.size(); k++)\n    {\n      reference.at(k) = rhs->referenceFile.at(k)->readArc(arcNo);\n      Arc::checkSynchronized({orbit, reference.at(k)});\n    }\n\n    for(UInt i=0; i<epochCount; i++)\n    {\n      const Time     time     = orbit.at(i).time;\n      const Rotary3d rotEarth = earthRotation->rotaryMatrix(time);\n      const Vector3d posEarth = rotEarth.rotate(orbit.at(i).position);\n\n      // referencefield + tides\n      const Tensor3d tns = rhs->referencefield->gravityGradient(time, posEarth)\n                          + rhs->tides->gradient(time, posEarth, rotEarth, earthRotation, ephemerides);\n      // observed minus computed\n      sggArc.at(i).gravityGradient -= starCamera.at(i).rotary.inverseRotate(rotEarth.inverseRotate(tns));\n      // gradients from files\n      for(UInt k=0; k<reference.size(); k++)\n        sggArc.at(i).gravityGradient -= reference.at(k).at(i).gravityGradient;\n    }\n\n    // =============================================\n\n    Vector l(6*epochCount);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      l(6*i+0) = sggArc.at(i).gravityGradient.xx();\n      l(6*i+1) = sggArc.at(i).gravityGradient.xy();\n      l(6*i+2) = sggArc.at(i).gravityGradient.xz();\n      l(6*i+3) = sggArc.at(i).gravityGradient.yy();\n      l(6*i+4) = sggArc.at(i).gravityGradient.yz();\n      l(6*i+5) = sggArc.at(i).gravityGradient.zz();\n    }\n\n    Matrix A, B;\n\n    // gradiometer bias for each component\n    // -----------------------------------\n    const std::vector<Time> times = orbit.times();\n    sggBias->setInterval(times.front(), times.back()+medianSampling(times), TRUE);\n    if(sggBias->parameterCount())\n    {\n      B = Matrix(6*epochCount, 6*sggBias->parameterCount());\n      const Matrix I = identityMatrix(6);\n      for(UInt i=0; i<epochCount; i++)\n        sggBias->designMatrix(times.at(i), I, B.row(6*i, 6));\n    }\n\n    // =============================================\n\n    // Decorrelation\n    // -------------\n    Matrix WA = A;\n    Matrix WB = B;\n    Matrix Wl = l;\n\n    Matrix W  = sigmas(arcNo) * CovCholesky.slice(0,0,6*epochCount,6*epochCount);\n    if(WA.size()) triangularSolve(1., W.trans(), WA);\n    if(WB.size()) triangularSolve(1., W.trans(), WB);\n    if(Wl.size()) triangularSolve(1., W.trans(), Wl);\n\n    // =============================================\n\n    // solution vector & decorrelated residuals\n    // ----------------------------------------\n    Vector tau = QR_decomposition(WB);\n    QTransMult(WB, tau, Wl); // transform observations: l:= Q'l\n    if(WA.size())\n      QTransMult(WB, tau, WA); // transform design matrix A:=Q'A\n    Matrix We = Wl; // transformed residuals\n//     if(WA.size())\n//       matMult(-1., WA, x, We);\n    // solution of arc dependent parameters\n    Vector y = We.row(0, WB.columns());\n    triangularSolve(1., WB.row(0, tau.rows()), y);\n    // residuals\n    We.row(0, WB.columns()).setNull(); // remove WB*x\n    QMult(WB, tau, We); // back transformation\n    generateQ(WB, tau);\n\n    // ============================================\n\n    // Variance component estimation\n    // -----------------------------\n    std::vector<UInt> index(epochCount);\n    for(UInt i=0; i<index.size(); i++)\n      index.at(i) = i;\n    Double ePeSum=0, redundancySum=0;\n    {\n      Matrix R;\n      Vector WWe;\n      Vce::redundancy(W, We, WA, WB, R, WWe);\n      Vce::psd(R, WWe, index, sigmas(arcNo), CosTransform, Psd, ePe, redundancy, ePeSum, redundancySum);\n    }\n    sigmasNew(arcNo) = std::sqrt(ePeSum/redundancySum) * sigmas(arcNo);  // compute new sigma (for this arc)\n\n    // =============================================\n\n    // compute residuals\n    // -----------------\n    const Vector e = l - B*y;\n//     if(A.size())\n//       e -= A*x;\n\n    for(UInt i=0; i<epochCount; i++)\n    {\n      sggArc.at(i).gravityGradient.xx() = e(6*i+0);\n      sggArc.at(i).gravityGradient.xy() = e(6*i+1);\n      sggArc.at(i).gravityGradient.xz() = e(6*i+2);\n      sggArc.at(i).gravityGradient.yy() = e(6*i+3);\n      sggArc.at(i).gravityGradient.yz() = e(6*i+4);\n      sggArc.at(i).gravityGradient.zz() = e(6*i+5);\n    }\n\n    return sggArc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingPod.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingPod.cpp\n*\n* @brief Estimate covariance function / arc weights.\n*\n* @author Torsten Mayer-Guerr\n* @date 2011-06-30\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program estimates empirical covariance functions of the instrument noise and determines arc-wise variances to\ndownweight arcs with outliers.\n\nA complete least squares adjustment for gravity field determination is performed by computing the \\config{observation}\nequations, see \\configClass{observation:podIntegral}{observationType:podIntegral} or\n\\configClass{observation:podVariational}{observationType:podVariational} for details. The normal equations\nare accumulated and solved to \\configFile{outputfileSolution}{matrix} together with the estimated accuracies\n\\configFile{outputfileSigmax}{matrix}. The estimated residuals~$\\hat{\\M e}=\\M l-\\M A\\hat{\\M x}$ can be computed with\n\\config{computeResiduals}.\n\nFor each component (along, cross, radial) of the kinematic orbit positions a noise covariance function is estimated\n\\begin{equation}\n  \\text{cov}(\\Delta t_i) = \\sum_{n=0}^{N-1} a_n^2 \\cos\\left(\\frac{\\pi}{T} n\\Delta t_i\\right).\n\\end{equation}\nThe covariance matrix is composed of the sum of matrices $F_n$ and unknown variance factors\n\\begin{equation}\n  \\M\\Sigma = a_1^2\\M F_1 + a_2^2 \\M F_2 + \\cdots + a_N^2\\M F_N,\n\\end{equation}\nwith the cosine transformation matrices\n\\begin{equation}\n  \\M F_n = \\left(\\cos\\left(\\frac{\\pi}{T} n(t_i-t_k)\\right)\\right)_{ik}.\n\\end{equation}\n\nAn additional variance factor can be computed (\\config{estimateArcSigmas}) for each arc~$k$  according to\n\\begin{equation}\n  \\hat{\\sigma}_k^2 = \\frac{\\hat{\\M e}_k^T\\M\\Sigma^{-1}\\hat{\\M e}_k}{r_k},\n\\end{equation}\nwhere $r_k$ is the redundancy. This variance factor should be around one for normally behaving arcs\nas the noise characteristics are already considered by the covariance matrix but bad arcs get a much larger variance.\nBy applying this factor bad arcs or arcs with large outliers are downweighted.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileParameterName.h\"\n#include \"misc/observation/observationMiscPod.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/varianceComponentEstimation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate covariance function / arc weights.\n* @ingroup programsGroup */\nclass PreprocessingPod\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\nprivate:\n  ObservationMiscPodPtr observationMisc;\n  std::vector<ObservationMiscPod::Arc> observationArc;\n  InstrumentFile fileCovPodEpoch;\n\n  std::vector< std::vector<UInt> > arcIndexN;\n  std::vector< std::vector<UInt> > arcIndexA;\n\n  Bool estimateCovarianceFunctionVCE;\n  Bool estimateArcSigmas;\n  Bool estimateResiduals;\n\n  // normal equations\n  // ----------------\n  MatrixDistributed normals;\n  Matrix n;        // right hand sides\n  Matrix x;        // solution\n  Matrix Wz;       // monte carlo vector for redundancy computation\n  Double lPl;      // =l'Pl, weighted norm of the observations\n  UInt   obsCount; // number of observations\n\n  // covariance\n  // ----------\n  Vector  sigmaPod, sigmaPodNew;\n  Double  samplingPod;\n  Matrix  covFuncPod;         // (covLength x 3) one column for x,y,z\n  Matrix  PsdPod;\n  Matrix  ePePod;\n  Matrix  redundancyPod;      // one row for each frequency, one column for each component\n  Matrix  CosTransformPod;\n\n  // residuals\n  std::vector<Arc> arcListPod;\n\n  void computeObservationEquation(UInt arcNo);\n  void buildNormals(UInt arcNo);\n  void computeRedundancies(UInt arcNo);\n  void computeResiduals(UInt arcNo);\n  Arc  collectArcPod(UInt arcNo) const {return arcListPod.at(arcNo);}\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingPod, PARALLEL, \"Estimate covariance function / arc weights.\", Preprocessing, Covariance, Residuals)\n\n/***********************************************/\n\nvoid PreprocessingPod::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    estimateCovarianceFunctionVCE = estimateArcSigmas = estimateResiduals = FALSE;\n\n    FileName fileNameSolution, fileNameSigmax, fileNameParaName;\n    FileName fileNameArcSigmaPod, fileNameCovPod, fileNameResidualsPod;\n    FileName fileNameArcList;\n    FileName sigmaPodName, covPodEpochName, covPodName;\n    Double   sigma0Pod=1;\n    Double   adjustmentThreshold;\n    UInt     iterCount;\n\n    renameDeprecatedConfig(config, \"arcList\", \"inputfileArcList\", date2time(2020, 7, 7));\n\n    readConfig(config, \"outputfileSolution\",      fileNameSolution, Config::OPTIONAL, \"\", \"estimated parameter vector (static part only)\");\n    readConfig(config, \"outputfileSigmax\",        fileNameSigmax,   Config::OPTIONAL, \"\", \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n    readConfig(config, \"outputfileParameterName\", fileNameParaName, Config::OPTIONAL, \"\", \"names of estimated parameters (static part only)\");\n    if(readConfigSequence(config, \"estimateArcSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateArcSigmas = TRUE;\n      readConfig(config, \"outputfileSigmasPerArcPod\", fileNameArcSigmaPod, Config::OPTIONAL, \"\", \"accuracies of each arc (POD2)\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateCovarianceFunctions\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateCovarianceFunctionVCE = TRUE;\n      readConfig(config, \"outputfileCovarianceFunctionPod\", fileNameCovPod, Config::OPTIONAL, \"\", \"covariance functions for along, cross, radial direction\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"computeResiduals\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateResiduals = TRUE;\n      readConfig(config, \"outputfilePodResiduals\", fileNameResidualsPod, Config::OPTIONAL, \"\", \"\");\n      endSequence(config);\n    }\n    readConfig(config, \"observation\", observationMisc,        Config::MUSTSET,  \"\", \"\");\n    if(readConfigSequence(config, \"covariancePod\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                        sigma0Pod,       Config::DEFAULT,  \"1\",  \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",        sigmaPodName,    Config::OPTIONAL, \"\",   \"apriori different accuracies for each arc (multiplied with sigma)\");\n      readConfig(config, \"inputfileCovarianceFunction\",  covPodName,      Config::OPTIONAL, \"\",   \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovariancePodEpoch\",  covPodEpochName, Config::OPTIONAL, \"\",   \"3x3 epoch covariances\");\n      readConfig(config, \"sampling\",                     samplingPod,     Config::DEFAULT,  \"30\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    readConfig(config, \"inputfileArcList\",    fileNameArcList,     Config::OPTIONAL, \"\",   \"list to correspond points of time to arc numbers\");\n    readConfig(config, \"adjustmentThreshold\", adjustmentThreshold, Config::DEFAULT,  \"0\",  \"Adjustment factor threshold: Iteration will be stopped once both SST and POD adjustment factors are under this threshold\");\n    readConfig(config, \"iterationCount\",      iterCount,           Config::DEFAULT,  \"3\",  \"(maximum) number of iterations for the estimation of calibration parameters and error PSD\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    // init\n    // ----\n    const UInt arcCount        = observationMisc->arcCount();\n    const UInt countAParameter = observationMisc->parameterCount();\n\n    std::vector<UInt> arcsInterval = {0, arcCount};\n    if(!fileNameArcList.empty())\n    {\n      logStatus<<\"read arc list <\"<<fileNameArcList<<\">\"<<Log::endl;\n      std::vector<Time> timesInterval;\n      readFileArcList(fileNameArcList, arcsInterval, timesInterval);\n    }\n\n    // init arc sigmas\n    // ---------------\n    sigmaPod = Vector(arcCount);\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      sigmaPod(arcNo) = 1.0;\n    if(!sigmaPodName.empty()) readFileMatrix(sigmaPodName, sigmaPod);\n    if(sigmaPod.rows() != arcCount) throw(Exception(\"sigmasPerArc (POD) contains wrong number of arcs\"));\n\n    fileCovPodEpoch.open(covPodEpochName);\n\n    // =============================================\n\n    // Init normal equations\n    // ---------------------\n    logStatus<<\"Init normal equations\"<<Log::endl;\n    std::vector<UInt> blockIndex(1, 0);\n    blockIndex.push_back(countAParameter);\n    normals.init(blockIndex, comm);\n    n = Matrix(normals.parameterCount(), observationMisc->rightSideCount());\n\n    // ===================================================\n\n    // parameter names\n    // ---------------\n    if(!fileNameParaName.empty() && Parallel::isMaster(comm))\n    {\n      logStatus<<\"write parameter names <\"<<fileNameParaName<<\">\"<<Log::endl;\n      observationMisc->setInterval(date2time(9999,1,1), date2time(9999,1,2));\n      std::vector<ParameterName> paraNameStatic;\n      observationMisc->parameterName(paraNameStatic);\n      writeFileParameterName(fileNameParaName, paraNameStatic);\n    }\n\n    // =============================================\n\n    // setup observation equations\n    // ---------------------------\n    logStatus<<\"set up observation equations\"<<Log::endl;\n    observationArc.resize(arcCount);\n    arcIndexN.resize(arcCount);\n    arcIndexA.resize(arcCount);\n    std::vector<UInt> processNo = Parallel::forEachInterval(arcCount, arcsInterval, [this](UInt arcNo) {computeObservationEquation(arcNo);}, comm);\n    observationMisc = ObservationMiscPodPtr(nullptr);\n\n    // =============================================\n\n    // Determine max. length of covariance functions\n    // --------------------------------------------\n    UInt covLengthPod = 0;\n    for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n      if(observationArc.at(arcNo).times.size())\n      {\n        const UInt len = static_cast<UInt>(round((observationArc.at(arcNo).times.back()-observationArc.at(arcNo).times.at(0)).seconds()/samplingPod))+1;\n        covLengthPod = std::max(covLengthPod, len);\n      }\n    Parallel::reduceMax(covLengthPod, 0, comm);\n    Parallel::broadCast(covLengthPod, 0, comm);\n\n    // =============================================\n\n    // init covariance function\n    // ------------------------\n    CosTransformPod = Vce::cosTransform(covLengthPod);\n    covFuncPod = Vce::readCovarianceFunction(covPodName, covLengthPod, 3, samplingPod);\n    covFuncPod.column(1,3) *= pow(sigma0Pod,2);\n    PsdPod = CosTransformPod * covFuncPod.column(1,3);\n\n    // =============================================\n\n    // Iteration\n    // ---------\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      logInfo<<\"starting iteration \"<<iter+1<<Log::endl;\n      bool thresholdReached = false;\n\n      // solve normal equations\n      // ----------------------\n      if(countAParameter)\n      {\n        logStatus<<\"accumulate system of normal equations\"<<Log::endl;\n        normals.setNull();\n        n.setNull();\n        lPl      = 0;\n        obsCount = 0;\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {buildNormals(arcNo);}, processNo, comm);\n\n        // collect system of normal equations\n        // ----------------------------------\n        logStatus<<\"collect system of normal equations\"<<Log::endl;\n        Parallel::reduceSum(n, 0, comm);\n        Parallel::reduceSum(obsCount, 0, comm);\n        Parallel::reduceSum(lPl, 0, comm);\n        normals.reduceSum();\n\n        // =============================================\n\n        // Regularize not used parameters\n        // ------------------------------\n        for(UInt i=0; i<normals.blockCount(); i++)\n          if(normals.isMyRank(i,i))\n          {\n            Matrix &N = normals.N(i,i);\n            for(UInt k=0; k<N.rows(); k++)\n              if(N(k,k) == 0)\n                N(k,k) = 1.;\n          }\n\n        // =============================================\n\n        // cholesky and forward step\n        // -------------------------\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        x = normals.solve(n, TRUE/*timing*/);\n        Parallel::broadCast(x, 0, comm);\n        if(Parallel::isMaster(comm))\n          logInfo<<\"  aposteriori sigma = \"<<sqrt((lPl-inner(x, n))/(obsCount-normals.parameterCount()))<<Log::endl;\n\n        // N contains now the cholesky decomposition\n        Wz = Vce::monteCarlo(normals.parameterCount(), 100);\n        normals.triangularSolve(Wz);\n        Parallel::broadCast(Wz, 0, comm);\n\n        if(Parallel::isMaster(comm) && !fileNameSolution.empty())\n        {\n          logStatus<<\"write solution to <\"<<fileNameSolution<<\">\"<<Log::endl;\n          const UInt blockIndexStatic = 0;\n          writeFileMatrix(fileNameSolution, x.row(normals.blockIndex(blockIndexStatic), normals.parameterCount()-normals.blockIndex(blockIndexStatic)));\n        }\n\n        if(!fileNameSigmax.empty())\n        {\n          logStatus<<\"inverte Cholesky matrix and write standard deviations to <\"<<fileNameSigmax<<\">\"<<Log::endl;\n          const UInt blockIndexStatic = 0;\n          for(UInt i=blockIndexStatic; i<normals.blockCount(); i++)\n            for(UInt k=i; k<normals.blockCount(); k++)\n              if(normals.rank(i,k) != 0)\n              {\n                if(normals.isMyRank(i,k))\n                  Parallel::send(normals.N(i,k), 0, comm);\n                else if(Parallel::isMaster(comm))\n                  Parallel::receive(normals.N(i,k), normals.rank(i,k), comm);\n              }\n          if(Parallel::isMaster(comm))\n          {\n            const UInt count = normals.parameterCount()-normals.blockIndex(blockIndexStatic);\n            Matrix W(count, Matrix::TRIANGULAR);\n            for(UInt i=blockIndexStatic; i<normals.blockCount(); i++)\n              for(UInt k=i; k<normals.blockCount(); k++)\n                copy(normals.N(i,k), W.slice(normals.blockIndex(i)-normals.blockIndex(blockIndexStatic), normals.blockIndex(k)-normals.blockIndex(blockIndexStatic), normals.blockSize(i), normals.blockSize(k)));\n            inverse(W);\n            Vector diagonal(count);\n            for(UInt z=0; z<count; z++)\n              diagonal(z) = sqrt(quadsum(W.slice(z,z,1,count-z)));\n            writeFileMatrix(fileNameSigmax, diagonal);\n          }\n          for(UInt i=blockIndexStatic; i<normals.blockCount(); i++)\n            for(UInt k=i; k<normals.blockCount(); k++)\n              if(!normals.isMyRank(i,k))\n                normals.N(i,k) = Matrix();\n        } // if(!fileNameSigmax.empty())\n\n      } // if(countAParameter)\n      Parallel::barrier(comm);\n\n      // =============================================\n\n      if(estimateResiduals)\n      {\n        logStatus<<\"compute residuals\"<<Log::endl;\n        arcListPod.clear(); arcListPod.resize(arcCount);\n        Parallel::forEachProcess(arcCount,   [this](UInt arcNo) {computeResiduals(arcNo);},     processNo, comm);\n        Parallel::forEachProcess(arcListPod, [this](UInt arcNo) {return collectArcPod(arcNo);}, processNo, comm);\n\n        if(Parallel::isMaster(comm) && (!fileNameResidualsPod.empty()))\n        {\n          logStatus<<\"write residual file <\"<<fileNameResidualsPod<<\">\"<<Log::endl;\n          InstrumentFile::write(fileNameResidualsPod, arcListPod);\n        }\n      } // if(estimateResiduals)\n\n      // =============================================\n\n      if((estimateArcSigmas || estimateCovarianceFunctionVCE))\n      {\n        logStatus<<\"compute redundancies\"<<Log::endl;\n        sigmaPodNew = Vector(arcCount);\n        ePePod = redundancyPod = Matrix(covLengthPod, 3); // for x,y,z\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeRedundancies(arcNo);}, processNo, comm);\n      }\n\n      // =============================================\n\n      // sigmas per arc\n      // --------------\n      if(estimateArcSigmas)\n      {\n        Parallel::reduceSum(sigmaPodNew, 0, comm);\n        if(Parallel::isMaster(comm))\n        {\n          sigmaPod = sigmaPodNew;\n          Double sigma0Pod = Vce::meanSigma(sigmaPod);\n          sigmaPod *= 1./sigma0Pod;\n          logInfo<<\"  POD sigma per arc (median): \"<<sigma0Pod<<Log::endl;\n\n          if(!fileNameArcSigmaPod.empty())\n          {\n            logStatus<<\"write arc sigma file <\"<<fileNameArcSigmaPod<<\">\"<<Log::endl;\n            writeFileMatrix(fileNameArcSigmaPod, sigmaPod);\n          }\n        }\n        Parallel::broadCast(sigmaPod, 0, comm);\n      } // if(estimateArcSigmas)\n\n      // =============================================\n\n      // estimate new PSD through variance component estimation\n      // ------------------------------------------------------\n      if(estimateCovarianceFunctionVCE)\n      {\n        Parallel::reduceSum(ePePod, 0, comm);\n        Parallel::reduceSum(redundancyPod, 0, comm);\n\n        logStatus<<\"compute psd through variance component estimation\"<<Log::endl;\n        if(Parallel::isMaster(comm))\n        {\n          Double maxFactor = 0;\n          Vce::estimatePsd(ePePod, redundancyPod, PsdPod, maxFactor);\n          logInfo<<\"  max. PSD adjustment factor: \"<<maxFactor<<Log::endl;\n          if (maxFactor < adjustmentThreshold)\n          {\n            logStatus<<\"  adjustment threshold \"<<adjustmentThreshold<<\" reached after iteration \"<<iter+1<<\".\"<<Log::endl;\n            thresholdReached = true;\n          }\n        } // if(Parallel::isMaster(comm))\n        Parallel::broadCast(PsdPod, 0, comm);\n        Parallel::broadCast(thresholdReached, 0, comm);\n        // compute new covariance function\n        copy(CosTransformPod*PsdPod, covFuncPod.column(1,PsdPod.columns()));\n\n        if(Parallel::isMaster(comm) && !fileNameCovPod.empty())\n        {\n          logStatus<<\"write covariance function file <\"<<fileNameCovPod<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameCovPod, covFuncPod);\n        }\n      } // if(estimateCovarianceFunctionVCE)\n\n      // =============================================\n\n      // bail if the iteration threshold has been reached\n      Parallel::broadCast(thresholdReached, 0, comm);\n      if (thresholdReached)\n        break;\n\n      if((!estimateArcSigmas) && (!estimateCovarianceFunctionVCE))\n        break; // iterations not needed\n    } // for(iter)\n\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingPod::computeObservationEquation(UInt arcNo)\n{\n  try\n  {\n    arcIndexN.at(arcNo).clear();\n    arcIndexA.at(arcNo).clear();\n    for(UInt idBlock=0; idBlock<normals.blockCount(); idBlock++)\n    {\n      arcIndexN.at(arcNo).push_back( idBlock );\n      arcIndexA.at(arcNo).push_back( normals.blockIndex(idBlock) );\n    }\n\n    // compute observation equations\n    // -----------------------------\n    observationArc.at(arcNo) = observationMisc->computeArc(arcNo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingPod::buildNormals(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).A.size() == 0)\n      return;\n\n    // Decorrelation\n    // -------------\n    Matrix Wl = observationArc.at(arcNo).l;\n    Matrix WA = observationArc.at(arcNo).A;\n    Matrix WB = observationArc.at(arcNo).B;\n    CovariancePod::decorrelate(observationArc.at(arcNo).pod, sigmaPod(arcNo), ObservationSigmaArc(),\n                               fileCovPodEpoch.readArc(arcNo), covFuncPod, {Wl, WA, WB});\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    Vector tau;\n    if(WB.size())\n    {\n      tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl); // transform observations: l:= Q'l\n      QTransMult(WB, tau, WA); // transform design matrix A:=Q'A\n    }\n    // use only nullspace of design matrix WB\n    MatrixSlice A_bar( WA.row(WB.columns(), WA.rows()-WB.columns()) );\n    MatrixSlice l_bar( Wl.row(WB.columns(), Wl.rows()-WB.columns()) );\n\n    // build normals\n    // -------------\n    lPl      += quadsum(l_bar);\n    obsCount += l_bar.rows();\n    for(UInt i=0; i<arcIndexA.at(arcNo).size(); i++)\n    {\n      const UInt idxN1 = arcIndexN.at(arcNo).at(i);\n      const UInt idxA1 = arcIndexA.at(arcNo).at(i);\n      // right hand sides\n      matMult(1., A_bar.column(idxA1, normals.blockSize(idxN1)).trans(), l_bar, n.row(normals.blockIndex(idxN1), normals.blockSize(idxN1)));\n      // normal matrix diagonal block\n      if(normals.N(idxN1, idxN1).size() == 0)\n        normals.N(idxN1, idxN1) = Matrix(normals.blockSize(idxN1), Matrix::SYMMETRIC);\n      rankKUpdate(1.0, A_bar.column(idxA1, normals.blockSize(idxN1)), normals.N(idxN1, idxN1));\n      // normal matrix, other blocks\n      for(UInt k=1; k<arcIndexA.at(arcNo).size(); k++)\n      {\n        const UInt idxN2 = arcIndexN.at(arcNo).at(k);\n        const UInt idxA2 = arcIndexA.at(arcNo).at(k);\n        if(normals.N(idxN1, idxN2).size() == 0)\n          normals.N(idxN1, idxN2) = Matrix(normals.blockSize(idxN1), normals.blockSize(idxN2));\n        matMult(1.0, A_bar.column(idxA1, normals.blockSize(idxN1)).trans(),\n                     A_bar.column(idxA2, normals.blockSize(idxN2)), normals.N(idxN1, idxN2));\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingPod::computeRedundancies(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).l.size() == 0)\n      return;\n\n    // count observations and calculate index\n    // --------------------------------------\n    const UInt countPod = observationArc.at(arcNo).times.size();\n\n    // Decorrelation\n    // -------------\n    Matrix Wl = observationArc.at(arcNo).l;\n    Matrix WA = observationArc.at(arcNo).A;\n    Matrix WB = observationArc.at(arcNo).B;\n    Matrix WPod = CovariancePod::decorrelate(observationArc.at(arcNo).pod, sigmaPod(arcNo), ObservationSigmaArc(),\n                                             fileCovPodEpoch.readArc(arcNo), covFuncPod, {Wl, WA, WB});\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    if(WB.size())\n    {\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl); // transform observations: l:= Q'l\n      Wl.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n      QMult(WB, tau, Wl); // back transformation\n\n      if(WA.size())\n      {\n        QTransMult(WB, tau, WA); // transform design matrix A:=Q'A\n        WA.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n        QMult(WB, tau, WA); // back transformation\n      }\n\n      generateQ(WB, tau);\n      WB.setType(Matrix::GENERAL);\n    }\n\n    // decorrelated residuals\n    // ----------------------\n    Matrix We = Wl;\n    Matrix WAz(Wl.rows(), Wz.columns());\n    for(UInt i=0; i<arcIndexA.at(arcNo).size(); i++)\n    {\n      const UInt idxN = arcIndexN.at(arcNo).at(i);\n      const UInt idxA = arcIndexA.at(arcNo).at(i);\n      matMult(-1., WA.column(idxA, normals.blockSize(idxN)),  x.row(normals.blockIndex(idxN), normals.blockSize(idxN)), We);\n      matMult( 1., WA.column(idxA, normals.blockSize(idxN)), Wz.row(normals.blockIndex(idxN), normals.blockSize(idxN)), WAz);\n    }\n\n    // ============================================\n\n    if(!estimateCovarianceFunctionVCE)\n    {\n      const Double redundancy = 3*countPod - quadsum(WAz) - quadsum(WB);\n      sigmaPodNew(arcNo) = sqrt(quadsum(We)/redundancy) * sigmaPod(arcNo);\n\n      return;\n    } // if(!estimateCovarianceFunctions)\n\n    // ============================================\n\n    // Variance component estimation\n    // -----------------------------\n    std::vector<UInt> index(countPod);\n    for(UInt i=0; i<index.size(); i++)\n      index.at(i) = static_cast<UInt>(round((observationArc.at(arcNo).times.at(i)-observationArc.at(arcNo).times.at(0)).seconds()/samplingPod));\n    Double ePeSum=0, redundancySum=0;\n    Matrix R;\n    Vector WWe;\n    Vce::redundancy(WPod, We, WAz, WB, R, WWe);\n    Vce::psd(R, WWe, index, sigmaPod(arcNo), CosTransformPod, PsdPod, ePePod, redundancyPod, ePeSum, redundancySum);\n    sigmaPodNew(arcNo) = sqrt(ePeSum/redundancySum) * sigmaPod(arcNo);  // compute new sigma (for this arc)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingPod::computeResiduals(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).l.size() == 0)\n      return;\n\n    // Residuals\n    // ---------\n    Matrix e = observationArc.at(arcNo).l;\n    for(UInt i=0; i<arcIndexA.at(arcNo).size(); i++)\n    {\n      const UInt idxN = arcIndexN.at(arcNo).at(i);\n      const UInt idxA = arcIndexA.at(arcNo).at(i);\n      matMult(-1., observationArc.at(arcNo).A.column(idxA, normals.blockSize(idxN)), x.row(normals.blockIndex(idxN), normals.blockSize(idxN)), e);\n    }\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    if(observationArc.at(arcNo).B.size())\n    {\n      Matrix We = e;\n      Matrix WB = observationArc.at(arcNo).B;\n      CovariancePod::decorrelate(observationArc.at(arcNo).pod, sigmaPod(arcNo), ObservationSigmaArc(),\n                                 fileCovPodEpoch.readArc(arcNo), covFuncPod, {We, WB});\n\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, We); // transform observations: l:= Q'l\n      Matrix y = We.row(0, tau.rows());\n      triangularSolve(1., WB.row(0, tau.rows()), y);\n      matMult(-1, observationArc.at(arcNo).B, y, e);\n    }\n\n    // create Pod arc\n    // ---------------\n    Arc arcPod;\n    for(UInt i=0; i<observationArc.at(arcNo).times.size(); i++)\n    {\n      OrbitEpoch epoch;\n      epoch.time     = observationArc.at(arcNo).times.at(i);\n      epoch.position = Vector3d(e(3*i+0,0), e(3*i+1,0), e(3*i+2,0));\n      arcListPod.at(arcNo).push_back(epoch);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingSst.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingSst.cpp\n*\n* @brief Estimate covariance function / arc weights.\n*\n* @author Torsten Mayer-Guerr\n* @author Matthias Ellmer\n* @author Andreas Kvas\n* @date 2011-09-23\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program processes satellite-to-satellite-tracking (SST) and kinematic orbit observations in a GRACE like configuration.\nThree different observation groups are considered separately: SST and POD1/POD2 for the two satellites.\nThis program works similar to \\program{PreprocessingPod}, see there for details. Here only deviations\nin the settings are explained.\n\nPrecise orbit data (POD) often contains systematic errors in addition to stochastic noise. In this case the\nvariance component estimation fails and assigns too much weight to the POD data. Therefore an additional\n\\config{downweightPod} factor can be applied to the standard deviation of POD for the next least squares adjustment\nin the iteration. This factor should also applied as \\config{sigma} in \\configClass{observation}{observationType}\nfor computation of the final solution e.g. with \\program{NormalsSolverVCE}.\n\nShort time variations of the gravity field can be co-estimated together with the static/monthly\nmean gravity field. The short time parameters must also be set in \\configClass{observation:parametrizationGravity}{parametrizationGravityType} and\ncan then be selected by \\configClass{estimateShortTimeVariations:parameterSelection}{parameterSelectorType}.\nIf these parameters are not time variable, for example when a range of static parameters is selected,\nthey are set up as constant for each time interval defined in \\config{inputfileArcList}. The parameters are constrained by an\n\\configClass{estimateShortTimeVariations:autoregressiveModelSequence}{autoregressiveModelSequenceType}. The weight of\nthe constrain equations in terms of the standard deviation can be estimated by means of\nVariance Component Estimation (VCE) if \\config{estimateShortTimeVariations:estimateSigma} is set.\nThe mathematical background of this co-estimation can be found in:\n\nKvas, A., Mayer-Gürr, T. GRACE gravity field recovery with background model uncertainties.\nJ Geod 93, 2543–2552 (2019). \\url{https://doi.org/10.1007/s00190-019-01314-1}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"misc/observation/observationMiscSst.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"misc/kalmanProcessing.h\"\n#include \"misc/normalsShortTimeStaticLongTime.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Estimate covariance function / arc weights.\n* @ingroup programsGroup */\nclass PreprocessingSst\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\nprivate:\n  ObservationMiscSstPtr                observationMisc;\n  std::vector<ObservationMiscSst::Arc> observationArc;\n  InstrumentFile                       fileCovEpochPod1, fileCovEpochPod2;\n  std::vector<UInt>                    arcsInterval;\n  std::vector<Time>                    timesInterval;\n\n  static constexpr UInt TYPESIZE = 3;\n  enum Type : UInt {SST, POD1, POD2};\n  std::array<std::string, TYPESIZE> typeName; // = {\"SST\", \"POD1\", \"POD2\"};\n\n  Bool estimateCovarianceFunctionVCE;\n  Bool estimateSigmasCovSst;\n  Bool estimateArcSigmas;\n  Bool estimateEpochSigmas;\n  Bool estimateResiduals;\n  Bool estimateSigmaShortTimeModel;\n\n  // normal equations\n  // ----------------\n  NormalsShortTimeStaticLongTime normals;\n  Matrix x;  // solution\n  Matrix Wz; // monte carlo vector for redundancy computation\n\n  // covariance\n  std::array<UInt,   TYPESIZE> covColumns;\n  std::array<Vector, TYPESIZE> sigma, sigmaNew;\n  std::array<Matrix, TYPESIZE> covFunc, Psd, ePe, redundancy, CosTransform;\n  std::array<Double, TYPESIZE> sampling;\n  std::array<std::vector<ObservationSigmaArc>, TYPESIZE> arcListEpochSigma;\n\n  std::vector<std::vector<Matrix>> CovSst; // Several independant matrices per arc\n  Vector  sigmasCovSst, ePeCovSst, redundancyCovSst;\n\n  // residuals\n  std::array<std::vector<Arc>, TYPESIZE> arcListResiduals;\n\n  UInt findInterval(UInt arcNo) const;\n  void decorrelate(UInt arcNo, const std::array<UInt, TYPESIZE> &count, std::array<Matrix, TYPESIZE> &W, const std::list<MatrixSlice> &A);\n  void buildNormals(UInt arcNo);\n  void computeRedundancies(UInt arcNo);\n  void computeResiduals(UInt arcNo);\n  void computeEpochSigmas(UInt arcNo);\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingSst, PARALLEL, \"Estimate covariance function / arc weights.\", Preprocessing, Covariance, Residuals, KalmanFilter)\n\n/***********************************************/\n/***********************************************/\n\nvoid PreprocessingSst::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    typeName   = {\"SST\", \"POD1\", \"POD2\"};\n    covColumns = {1, 3, 3};\n    estimateCovarianceFunctionVCE = estimateArcSigmas = estimateEpochSigmas = estimateResiduals = FALSE;\n    estimateSigmaShortTimeModel = FALSE;\n    estimateSigmasCovSst = FALSE;\n\n    FileName                       fileNameSolution, fileNameSigmax, fileNameParaName;\n    std::array<FileName, TYPESIZE> fileNameOutArcSigma, fileNameOutEpochSigma, fileNameOutCovFunc, fileNameResiduals;\n    std::array<FileName, TYPESIZE> fileNameInArcSigma, fileNameInEpochSigma, fileNameInCovFunc;\n    FileName                       fileNameOutSigmasCovSst, fileNameInSigmasCovSst;\n    FileName                       fileNameInCovEpochPod1,  fileNameInCovEpochPod2;\n    std::vector<FileName>          fileNamesCovSst;\n    std::array<Double, TYPESIZE>   sigma0; sigma0.fill(1.0);\n    AutoregressiveModelSequencePtr arSequence;\n    ParameterSelectorPtr           parameterShortTime;\n    Double                         downweightPod;\n    FileName                       fileNameArcList;\n    UInt                           iterCount;\n    std::string                    iterVariableName;\n    UInt                           defaultBlockSize;\n\n    readConfig(config, \"outputfileSolution\",      fileNameSolution, Config::OPTIONAL, \"\", \"estimated parameter vector (static part only)\");\n    readConfig(config, \"outputfileSigmax\",        fileNameSigmax,   Config::OPTIONAL, \"\", \"standard deviations of the parameters (sqrt of the diagonal of the inverse normal equation)\");\n    readConfig(config, \"outputfileParameterName\", fileNameParaName, Config::OPTIONAL, \"\", \"estimated signal parameters (index is appended)\");\n    if(readConfigSequence(config, \"estimateArcSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateArcSigmas = TRUE;\n      readConfig(config, \"outputfileSigmasPerArcSst\",  fileNameOutArcSigma.at(SST),  Config::OPTIONAL, \"\", \"accuracies of each arc (SST)\");\n      readConfig(config, \"outputfileSigmasPerArcPod1\", fileNameOutArcSigma.at(POD1), Config::OPTIONAL, \"\", \"accuracies of each arc (POD1)\");\n      readConfig(config, \"outputfileSigmasPerArcPod2\", fileNameOutArcSigma.at(POD2), Config::OPTIONAL, \"\", \"accuracies of each arc (POD2)\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateEpochSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateEpochSigmas = TRUE;\n      readConfig(config, \"outputfileSigmasPerEpochSst\",  fileNameOutEpochSigma.at(SST),  Config::OPTIONAL, \"\", \"accuracies of each epoch (SST)\");\n      readConfig(config, \"outputfileSigmasPerEpochPod1\", fileNameOutEpochSigma.at(POD1), Config::OPTIONAL, \"\", \"accuracies of each epoch (POD1)\");\n      readConfig(config, \"outputfileSigmasPerEpochPod2\", fileNameOutEpochSigma.at(POD2), Config::OPTIONAL, \"\", \"accuracies of each epoch (POD2)\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateCovarianceFunctions\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateCovarianceFunctionVCE = TRUE;\n      readConfig(config, \"outputfileCovarianceFunctionSst\",  fileNameOutCovFunc.at(SST),  Config::OPTIONAL, \"\", \"covariance function\");\n      readConfig(config, \"outputfileCovarianceFunctionPod1\", fileNameOutCovFunc.at(POD1), Config::OPTIONAL, \"\", \"covariance functions for along, cross, radial direction\");\n      readConfig(config, \"outputfileCovarianceFunctionPod2\", fileNameOutCovFunc.at(POD2), Config::OPTIONAL, \"\", \"covariance functions for along, cross, radial direction\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateSstArcCovarianceSigmas\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateSigmasCovSst = TRUE;\n      readConfig(config, \"outputfileSigmasCovarianceMatrixArc\", fileNameOutSigmasCovSst, Config::OPTIONAL, \"\", \"one variance factor per matrix\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"computeResiduals\", Config::OPTIONAL, \"\", \"\"))\n    {\n      estimateResiduals = TRUE;\n      readConfig(config, \"outputfileSstResiduals\",  fileNameResiduals.at(SST),  Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"outputfilePod1Residuals\", fileNameResiduals.at(POD1), Config::OPTIONAL, \"\", \"\");\n      readConfig(config, \"outputfilePod2Residuals\", fileNameResiduals.at(POD2), Config::OPTIONAL, \"\", \"\");\n      endSequence(config);\n    }\n    readConfig(config, \"observation\", observationMisc, Config::MUSTSET,  \"\", \"\");\n    if(readConfigSequence(config, \"covarianceSst\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                              sigma0.at(SST),               Config::DEFAULT,  \"1\", \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",              fileNameInArcSigma.at(SST),   Config::OPTIONAL, \"\",  \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",            fileNameInEpochSigma.at(SST), Config::OPTIONAL, \"\",  \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",        fileNameInCovFunc.at(SST),    Config::OPTIONAL, \"\",  \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovarianceMatrixArc\",       fileNamesCovSst,              Config::OPTIONAL, \"\",  \"Must be given per sst arc with correct dimensions.\");\n      readConfig(config, \"inputfileSigmasCovarianceMatrixArc\", fileNameInSigmasCovSst,       Config::OPTIONAL, \"\",  \"Vector with one sigma for each <inputfileCovarianceMatrixArc>\");\n      readConfig(config, \"sampling\",                           sampling.at(SST),             Config::DEFAULT,  \"5\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"covariancePod1\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                        sigma0.at(POD1),               Config::DEFAULT,  \"1\",  \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",        fileNameInArcSigma.at(POD1),   Config::OPTIONAL, \"\",   \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",      fileNameInEpochSigma.at(POD1), Config::OPTIONAL, \"\",   \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",  fileNameInCovFunc.at(POD1),    Config::OPTIONAL, \"\",   \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovariancePodEpoch\",  fileNameInCovEpochPod1,        Config::OPTIONAL, \"\",   \"3x3 epoch covariances\");\n      readConfig(config, \"sampling\",                     sampling.at(POD1),             Config::DEFAULT,  \"30\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"covariancePod2\", Config::MUSTSET, \"\", \"\"))\n    {\n      readConfig(config, \"sigma\",                        sigma0.at(POD2),               Config::DEFAULT,  \"1\",  \"apriori factor of covariance function\");\n      readConfig(config, \"inputfileSigmasPerArc\",        fileNameInArcSigma.at(POD2),   Config::OPTIONAL, \"\",   \"apriori different accuaries for each arc (multiplicated with sigma)\");\n      readConfig(config, \"inputfileSigmasPerEpoch\",      fileNameInEpochSigma.at(POD2), Config::OPTIONAL, \"\",   \"apriori different accuaries for each epoch\");\n      readConfig(config, \"inputfileCovarianceFunction\",  fileNameInCovFunc.at(POD2),    Config::OPTIONAL, \"\",   \"approximate covariances in time\");\n      readConfig(config, \"inputfileCovariancePodEpoch\",  fileNameInCovEpochPod2,        Config::OPTIONAL, \"\",   \"3x3 epoch covariances\");\n      readConfig(config, \"sampling\",                     sampling.at(POD2),             Config::DEFAULT,  \"30\", \"[seconds] sampling of the covariance function\");\n      endSequence(config);\n    }\n    if(readConfigSequence(config, \"estimateShortTimeVariations\", Config::OPTIONAL, \"\", \"co-estimate short time gravity field variations\"))\n    {\n      readConfig(config, \"estimateSigma\",               estimateSigmaShortTimeModel, Config::DEFAULT, \"0\", \"estimate standard deviation via VCE\");\n      readConfig(config, \"autoregressiveModelSequence\", arSequence,                  Config::MUSTSET, \"\",  \"AR model sequence for constraining short time gravity variations\");\n      readConfig(config, \"parameterSelection\",          parameterShortTime,          Config::MUSTSET, \"\",  \"parameters describing the short time gravity field\");\n      endSequence(config);\n    }\n    readConfig(config, \"downweightPod\",          downweightPod,      Config::DEFAULT,  \"1\",    \"downweight factor for POD\");\n    readConfig(config, \"inputfileArcList\",       fileNameArcList,    Config::OPTIONAL, \"\",     \"list to correspond points of time to arc numbers\");\n    readConfig(config, \"iterationCount\",         iterCount,          Config::DEFAULT,  \"3\",    \"(maximum) number of iterations for the estimation of calibration parameter and error PSD\");\n    readConfig(config, \"variableNameIterations\", iterVariableName,   Config::OPTIONAL, \"\",     \"All output fileNames in preprocessing iteration are expanded with this variable prior to writing to disk\");\n    readConfig(config, \"defaultBlockSize\",       defaultBlockSize,   Config::DEFAULT,  \"2048\", \"block size of static normal equation blocks\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    // init\n    // ----\n    const UInt arcCount        = observationMisc->arcCount();\n    const UInt countAParameter = observationMisc->parameterCount();\n\n    arcsInterval  = {0, arcCount};\n    timesInterval = {Time(), date2time(9999,1,1)};\n    if(!fileNameArcList.empty())\n    {\n      logStatus<<\"read arc list <\"<<fileNameArcList<<\">\"<<Log::endl;\n      readFileArcList(fileNameArcList, arcsInterval, timesInterval);\n    }\n\n    // init arc sigmas\n    // ---------------\n    for(UInt idType : {SST, POD1, POD2})\n    {\n      sigma.at(idType) = Vector(arcCount, 1.0);\n      if(!fileNameInArcSigma.at(idType).empty())\n        readFileMatrix(fileNameInArcSigma.at(idType), sigma.at(idType));\n      if(sigma.at(idType).rows()  != arcCount)\n        throw(Exception(\"sigmasPerArc \"+typeName.at(idType)+\" contains wrong number of arcs\"));\n    }\n\n    fileCovEpochPod1.open(fileNameInCovEpochPod1);\n    fileCovEpochPod2.open(fileNameInCovEpochPod2);\n\n    // ===================================================\n\n    // normal equations of short time model\n    // ------------------------------------\n    UInt countShortTimeParameters = 0;\n    std::vector<std::vector<std::vector<Matrix>>> normalsShortTime;\n    if(arSequence)\n    {\n      logStatus<<\"initialize normal equations of short time gravity field model\"<<Log::endl;\n      countShortTimeParameters = arSequence->dimension();\n      normalsShortTime = arSequence->normalEquationSequence();\n    }\n\n    // init normal equations\n    // ---------------------\n    logStatus<<\"initialize normal equations\"<<Log::endl;\n    normals.init(observationMisc, timesInterval, defaultBlockSize, comm, FALSE/*sortStateBeforeGravityParameter*/, countShortTimeParameters, parameterShortTime);\n\n    // parameter names\n    // ---------------\n    if(!fileNameParaName.empty() && Parallel::isMaster(comm))\n    {\n      logStatus<<\"write parameter names <\"<<fileNameParaName<<\">\"<<Log::endl;\n      writeFileParameterName(fileNameParaName, normals.parameterNames);\n    }\n\n    // =============================================\n\n    // setup observation equations\n    // ---------------------------\n    logStatus<<\"set up observation equations\"<<Log::endl;\n    observationArc.resize(arcCount);\n    std::vector<UInt> processNo = Parallel::forEachInterval(arcCount, arcsInterval, [this](UInt arcNo)\n    {\n      const UInt idInterval = findInterval(arcNo);\n      if(timesInterval.size())\n        observationMisc->setInterval(timesInterval.at(idInterval), timesInterval.at(idInterval+1));\n      observationArc.at(arcNo) = observationMisc->computeArc(arcNo);\n    }, comm);\n    observationMisc = nullptr;\n\n    // =============================================\n\n    // set used blocks\n    // ---------------\n    logStatus<<\"setup normal equations\"<<Log::endl;\n    normals.setBlocks(arcsInterval);\n\n    // =============================================\n\n    // read SST covariance matrices\n    // ----------------------------\n    CovSst.resize(arcCount);\n    if(fileNamesCovSst.size())\n    {\n      logStatus<<\"read arc-wise sst covariance matrices\"<<Log::endl;\n      Parallel::forEachProcess(arcCount, [&](UInt arcNo)\n      {\n        CovSst.at(arcNo).resize(fileNamesCovSst.size());\n        for(UInt i=0; i<fileNamesCovSst.size(); i++)\n          readFileMatrix(fileNamesCovSst.at(i).appendBaseName(\".arc\"+arcNo%\"%03i\"s), CovSst.at(arcNo).at(i));\n      }, processNo, comm);\n    }\n\n    sigmasCovSst = Vector(fileNamesCovSst.size(), 1.);\n    if(!fileNameInSigmasCovSst.empty())\n    {\n      readFileMatrix(fileNameInSigmasCovSst, sigmasCovSst);\n      if(sigmasCovSst.rows() != fileNamesCovSst.size())\n        throw(Exception(\"Number of sigmas not compatible with number of given arc-wise SST covariance matrices\"));\n    }\n\n    // =============================================\n\n    std::array<UInt, TYPESIZE> covLength; covLength.fill(0);\n    for(UInt idType : {SST, POD1, POD2})\n    {\n      // Determine max. length of ovariance functions\n      for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n        if(observationArc.at(arcNo).times.at(idType).size())\n          covLength.at(idType) = std::max(covLength.at(idType), static_cast<UInt>(std::round((observationArc.at(arcNo).times.at(idType).back()-observationArc.at(arcNo).times.at(idType).front()).seconds()/sampling.at(idType))+1));\n      Parallel::reduceMax(covLength.at(idType), 0, comm);\n      Parallel::broadCast(covLength.at(idType), 0, comm);\n\n      // transformation PSD <-> covFunc\n      CosTransform.at(idType) = Vce::cosTransform(covLength.at(idType));\n\n      // init covariance function\n      covFunc.at(idType)  = Vce::readCovarianceFunction(fileNameInCovFunc.at(idType),  covLength.at(idType),  covColumns.at(idType), sampling.at(idType));\n      covFunc.at(idType).column(1, covColumns.at(idType))  *= std::pow(sigma0.at(idType), 2);\n      Psd.at(idType) = CosTransform.at(idType) * covFunc.at(idType).column(1, covColumns.at(idType));\n\n      // init epoch sigmas\n      arcListEpochSigma.at(idType).resize(arcCount);\n      if(estimateEpochSigmas)\n      {\n        InstrumentFile file(fileNameInEpochSigma.at(idType));\n        for(UInt arcNo=0; arcNo<arcCount; arcNo++)\n          if(Parallel::myRank(comm) == processNo.at(arcNo))\n          {\n            arcListEpochSigma.at(idType).at(arcNo) = file.readArc(arcNo);\n            if(!arcListEpochSigma.at(idType).at(arcNo).size())\n              for(UInt i=0; i<observationArc.at(arcNo).times.at(idType).size(); i++)\n              {\n                ObservationSigmaEpoch epoch;\n                epoch.time = observationArc.at(arcNo).times.at(idType).at(i);\n                arcListEpochSigma.at(idType).at(arcNo).push_back(epoch);\n              }\n          }\n      } // if(estimateEpochSigmas)\n    } // for(idType)\n\n    // =============================================\n\n    // Iteration\n    // ---------\n    Double sigma2ShortTimeModel = 1.;\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      logInfo<<\"starting iteration \"<<iter<<Log::endl;\n      VariableList variableIteration;\n      if(iterVariableName.size())\n        variableIteration.setVariable(iterVariableName, iter);\n\n      // solve normal equations\n      // ----------------------\n      if(countAParameter)\n      {\n        logStatus<<\"accumulate system of normal equations\"<<Log::endl;\n        normals.setNull();\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {buildNormals(arcNo);}, processNo, comm);\n        logStatus<<\"collect system of normal equations\"<<Log::endl;\n        normals.reduceSum();\n\n        // add normals of short time model\n        // -------------------------------\n        if(normalsShortTime.size())\n        {\n          logStatus<<\"add normals of short time model\"<<Log::endl;\n          normals.addShortTimeNormals(sigma2ShortTimeModel, normalsShortTime);\n        }\n\n        // cholesky and forward step\n        // -------------------------\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        const Double sigma = normals.solve(x, Wz);\n        logInfo<<\"  aposteriori sigma = \"<<sigma<<Log::endl;\n\n        if(Parallel::isMaster(comm) && !fileNameSolution.empty())\n        {\n          logStatus<<\"write solution to <\"<<fileNameSolution(variableIteration)<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameSolution(variableIteration), x);\n        }\n\n        if(!fileNameSigmax.empty())\n        {\n          logStatus<<\"inverte cholesky matrix and write standard deviations to <\"<<fileNameSigmax(variableIteration)<<\">\"<<Log::endl;\n          Vector sigma = normals.parameterStandardDeviation();\n          if(Parallel::isMaster(comm))\n            writeFileMatrix(fileNameSigmax(variableIteration), sigma);\n        } // if(!fileNameSigmax.empty())\n\n        if(estimateSigmaShortTimeModel && normalsShortTime.size())\n        {\n          logStatus<<\"compute standard deviation of short time gravity model\"<<Log::endl;\n          Double s2 = normals.estimateShortTimeNormalsVariance(sigma2ShortTimeModel, normalsShortTime, x, Wz);\n          logInfo<<\"  sigma: \"<<std::sqrt(s2)<<Log::endl;\n          if(!std::isnan(s2) && (s2 > 0))\n            sigma2ShortTimeModel = s2;\n        }\n      } // if(countAParameter)\n      Parallel::barrier(comm);\n\n      // compute residuals\n      // --------------------\n      if(estimateResiduals || estimateEpochSigmas)\n      {\n        logStatus<<\"compute residuals\"<<Log::endl;\n        for(UInt idType : {SST, POD1, POD2})\n        {\n          arcListResiduals.at(idType).clear();\n          arcListResiduals.at(idType).resize(arcCount);\n        }\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeResiduals(arcNo);}, processNo, comm, FALSE/*timing*/);\n        for(UInt idType : {SST, POD1, POD2})\n        {\n          Parallel::forEachProcess(arcListResiduals.at(idType), [this, idType](UInt arcNo) {return arcListResiduals.at(idType).at(arcNo);}, processNo, comm, FALSE/*timing*/);\n          if(Parallel::isMaster(comm) && (!fileNameResiduals.at(idType).empty()))\n          {\n            logStatus<<\"write residual file <\"<<fileNameResiduals.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameResiduals.at(idType)(variableIteration), arcListResiduals.at(idType));\n          }\n        }\n      }\n\n      // compute redundancies\n      // --------------------\n      if((estimateArcSigmas || estimateCovarianceFunctionVCE || estimateSigmasCovSst))\n      {\n        logStatus<<\"compute redundancies\"<<Log::endl;\n        for(UInt idType : {SST, POD1, POD2})\n        {\n          sigmaNew.at(idType) = Vector(arcCount);\n          ePe.at(idType) = redundancy.at(idType) = Matrix(covLength.at(idType), covColumns.at(idType));\n        }\n        ePeCovSst = redundancyCovSst = Vector(sigmasCovSst.rows());\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeRedundancies(arcNo);}, processNo, comm);\n      }\n\n      // sigmas per arc\n      // --------------\n      if(estimateArcSigmas)\n      {\n        for(UInt idType : {SST, POD1, POD2})\n        {\n          Parallel::reduceSum(sigmaNew.at(idType), 0, comm);\n          if(Parallel::isMaster(comm))\n          {\n            sigma.at(idType) = (1./Vce::meanSigma(sigmaNew.at(idType))) * sigmaNew.at(idType);\n            logInfo<<\"  \"<<typeName.at(idType)<<\" sigma per arc (median): \"<<Vce::meanSigma(sigmaNew.at(idType))<<Log::endl;\n          }\n          Parallel::broadCast(sigma.at(idType), 0, comm);\n        }\n\n        for(UInt idType : {SST, POD1, POD2})\n          if(Parallel::isMaster(comm) && !fileNameOutArcSigma.at(idType).empty())\n          {\n            logStatus<<\"write arc sigma file <\"<<fileNameOutArcSigma.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            writeFileMatrix(fileNameOutArcSigma.at(idType)(variableIteration), sigma.at(idType));\n          }\n      }\n\n      // sigmas per epoch\n      // --------------\n      if(estimateEpochSigmas)\n      {\n        logStatus<<\"estimate epoch sigmas\"<<Log::endl;\n        Parallel::forEachProcess(arcCount, [this](UInt arcNo) {computeEpochSigmas(arcNo);}, processNo, comm);\n        for(UInt idType : {SST, POD1, POD2})\n        {\n          Parallel::forEachProcess(arcListEpochSigma.at(idType), [this, idType](UInt arcNo) {return arcListEpochSigma.at(idType).at(arcNo);}, processNo, comm, FALSE/*timing*/);\n          if(Parallel::isMaster(comm) && !fileNameOutEpochSigma.at(idType).empty())\n          {\n            logStatus<<\"write epoch sigma file <\"<<fileNameOutEpochSigma.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            InstrumentFile::write(fileNameOutEpochSigma.at(idType)(variableIteration), arcListEpochSigma.at(idType));\n          }\n        }\n        Parallel::barrier(comm);\n      } // if(estimateEpochSigmas)\n\n      // estimate new PSD through variance component estimation\n      // ------------------------------------------------------\n      if(estimateCovarianceFunctionVCE)\n      {\n        logStatus<<\"estimate PSDs\"<<Log::endl;\n        for(UInt idType : {SST, POD1, POD2})\n        {\n          Parallel::reduceSum(ePe.at(idType), 0, comm);\n          Parallel::reduceSum(redundancy.at(idType), 0, comm);\n          if(Parallel::isMaster(comm))\n          {\n            Double maxFactor = 0;\n            Vce::estimatePsd(ePe.at(idType), redundancy.at(idType), Psd.at(idType), maxFactor);\n            if((idType == POD1) || (idType == POD2))\n              maxFactor /= downweightPod;\n            logInfo<<\"  max. PSD adjustment factor \"<<typeName.at(idType)<<\": \"<<maxFactor<<Log::endl;\n          }\n          Parallel::broadCast(Psd.at(idType), 0, comm);\n          // compute new covariance function\n          copy(CosTransform.at(idType) * Psd.at(idType), covFunc.at(idType).column(1, covColumns.at(idType)));\n        }\n\n        // Write covariance function to file\n        for(UInt idType : {SST, POD1, POD2})\n          if(Parallel::isMaster(comm) && !fileNameOutCovFunc.at(idType).empty())\n          {\n            logStatus<<\"write covariance function file <\"<<fileNameOutCovFunc.at(idType)(variableIteration)<<\">\"<<Log::endl;\n            writeFileMatrix(fileNameOutCovFunc.at(idType)(variableIteration), covFunc.at(idType));\n          }\n      }\n\n      // estimate variance factor for arc-wise SST covariance matrices\n      // -------------------------------------------------------------\n      if(estimateSigmasCovSst)\n      {\n        Parallel::reduceSum(ePeCovSst, 0, comm);\n        Parallel::reduceSum(redundancyCovSst, 0, comm);\n        if(Parallel::isMaster(comm))\n        {\n          for(UInt i=0; i<sigmasCovSst.rows(); i++)\n          {\n            const Double alpha = std::sqrt(ePeCovSst(i)/redundancyCovSst(i));\n            sigmasCovSst(i) *= alpha;\n            logStatus<<\"  sigma of SST covariance matrix (current/total): \"<<alpha<<\"/\"<<sigmasCovSst(i)<<Log::endl;\n          }\n        }\n        Parallel::broadCast(sigmasCovSst, 0, comm);\n\n        if(Parallel::isMaster(comm) && !fileNameOutSigmasCovSst.empty())\n        {\n          logStatus<<\"write arc-wise SST variance factors <\"<<fileNameOutSigmasCovSst(variableIteration)<<\">\"<<Log::endl;\n          writeFileMatrix(fileNameOutSigmasCovSst(variableIteration), sigmasCovSst);\n        }\n      }\n\n      // downweight POD\n      // --------------\n      for(UInt idType : {POD1, POD2})\n      {\n        Psd.at(idType) *= std::pow(downweightPod, 2);\n        covFunc.at(idType).column(1, covColumns.at(idType)) *= std::pow(downweightPod, 2);\n      }\n    } // for(iter)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt PreprocessingSst::findInterval(UInt arcNo) const\n{\n  for(UInt idInterval=0; idInterval+1<arcsInterval.size(); idInterval++)\n    if(arcNo < arcsInterval.at(idInterval+1))\n      return idInterval;\n  return 0;\n}\n\n/***********************************************/\n\nvoid PreprocessingSst::decorrelate(UInt arcNo, const std::array<UInt, TYPESIZE> &count, std::array<Matrix, TYPESIZE> &W, const std::list<MatrixSlice> &A)\n{\n  try\n  {\n    // count observations and calculate index\n    // --------------------------------------\n    std::array<UInt, TYPESIZE> idx;\n    std::array<std::list<MatrixSlice>, TYPESIZE> WA; // type specific slices of A\n    UInt obsCount = 0;\n    for(UInt idType : {SST, POD1, POD2})\n    {\n      idx.at(idType) = obsCount;\n      obsCount      += covColumns.at(idType) * count.at(idType);\n      for(const MatrixSlice &a : A)\n        WA.at(idType).push_back(a.row(idx.at(idType), covColumns.at(idType) * count.at(idType)));\n    }\n\n    if(count.at(SST))\n    {\n      W.at(SST) = Matrix();\n      if(CovSst.at(arcNo).size())\n      {\n        W.at(SST) = std::pow(sigmasCovSst.at(0),2) * CovSst.at(arcNo).at(0);\n        for(UInt i=1; i<CovSst.at(arcNo).size(); i++)\n          axpy(std::pow(sigmasCovSst.at(i),2), CovSst.at(arcNo).at(i), W.at(SST));\n      }\n\n      CovarianceSst::decorrelate(observationArc.at(arcNo).times.at(SST), sigma.at(SST)(arcNo), arcListEpochSigma.at(SST).at(arcNo), covFunc.at(SST), W.at(SST), WA.at(SST));\n    }\n\n    if(count.at(POD1))\n      W.at(POD1) = CovariancePod::decorrelate(observationArc.at(arcNo).pod1, sigma.at(POD1)(arcNo), arcListEpochSigma.at(POD1).at(arcNo), fileCovEpochPod1.readArc(arcNo), covFunc.at(POD1), WA.at(POD1));\n\n    if(count.at(POD2))\n      W.at(POD2) = CovariancePod::decorrelate(observationArc.at(arcNo).pod2, sigma.at(POD2)(arcNo), arcListEpochSigma.at(POD2).at(arcNo), fileCovEpochPod2.readArc(arcNo), covFunc.at(POD2), WA.at(POD2));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingSst::buildNormals(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).A.size() == 0)\n      return;\n\n    // Decorrelation\n    // -------------\n    Matrix Wl = observationArc.at(arcNo).l;\n    Matrix WA = observationArc.at(arcNo).A;\n    Matrix WB = observationArc.at(arcNo).B;\n    std::array<Matrix, TYPESIZE> W;\n    decorrelate(arcNo, {observationArc.at(arcNo).times.at(SST).size(), observationArc.at(arcNo).times.at(POD1).size(), observationArc.at(arcNo).times.at(POD2).size()},\n                W, {Wl, WA, WB});\n\n    normals.accumulate(findInterval(arcNo), Wl, WA, WB);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingSst::computeRedundancies(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).l.size() == 0)\n      return;\n\n    // count observations and calculate index\n    // --------------------------------------\n    std::array<UInt, TYPESIZE> count, idx;\n    UInt obsCount = 0;\n    for(UInt idType : {SST, POD1, POD2})\n    {\n      count.at(idType) = observationArc.at(arcNo).times.at(idType).size();\n      idx.at(idType)   = obsCount;\n      obsCount        += covColumns.at(idType) * count.at(idType);\n    }\n\n    // Decorrelation\n    // -------------\n    Matrix Wl = observationArc.at(arcNo).l;\n    Matrix WA = observationArc.at(arcNo).A;\n    Matrix WB = observationArc.at(arcNo).B;\n    std::array<Matrix, TYPESIZE> W;\n    decorrelate(arcNo, count, W, {Wl, WA, WB});\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    if(WB.size())\n    {\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, Wl);             // transform observations: l:= Q'l\n      Wl.row(0, WB.columns()).setNull();   // residuals: remove WB*x\n      QMult(WB, tau, Wl);                  // back transformation\n\n      if(WA.size())\n      {\n        QTransMult(WB, tau, WA);           // transform design matrix A:=Q'A\n        WA.row(0, WB.columns()).setNull(); // residuals: remove WB*x\n        QMult(WB, tau, WA);                // back transformation\n      }\n\n      generateQ(WB, tau);\n    }\n\n    // decorrelated residuals\n    // ----------------------\n    Matrix We = Wl;\n    Matrix WAz(Wl.rows(), Wz.columns());\n    normals.designMatMult(findInterval(arcNo), -1., WA, x,  We);\n    normals.designMatMult(findInterval(arcNo), +1., WA, Wz, WAz);\n\n    // ============================================\n\n    if(!estimateCovarianceFunctionVCE)\n    {\n      for(UInt idType : {SST, POD1, POD2})\n        if(count.at(idType))\n        {\n          const Double redundancy = covColumns.at(idType)*count.at(idType)\n                                  - quadsum(WAz.row(idx.at(idType), covColumns.at(idType)*count.at(idType)))\n                                  - quadsum(WB.row (idx.at(idType), covColumns.at(idType)*count.at(idType)));\n          if(redundancy > 0.3)\n            sigmaNew.at(idType)(arcNo) = std::sqrt(quadsum(We.row(idx.at(idType),  covColumns.at(idType)*count.at(idType)))/redundancy) * sigma.at(idType)(arcNo);\n        }\n      return;\n    } // if(!estimateCovarianceFunctionVCE)\n\n    // ============================================\n\n    // variance component estimation\n    // -----------------------------\n    Matrix R;\n    Vector WWe;\n    std::array<std::vector<UInt>, TYPESIZE> index;\n    std::array<Double, TYPESIZE> ePeSum, redundancySum; ePeSum.fill(0); redundancySum.fill(0);\n    for(UInt idType : {SST, POD1, POD2})\n    {\n      index.at(idType).resize(observationArc.at(arcNo).times.at(idType).size());\n      for(UInt i=0; i<index.at(idType).size(); i++)\n        index.at(idType).at(i) = static_cast<UInt>(std::round((observationArc.at(arcNo).times.at(idType).at(i)-observationArc.at(arcNo).times.at(idType).front()).seconds()/sampling.at(idType)));\n    }\n\n    if(count.at(SST))\n    {\n      Vce::redundancy(W.at(SST), We.row(idx.at(SST), count.at(SST)),\n                      WAz.row(idx.at(SST), count.at(SST)), WB.row(idx.at(SST), count.at(SST)), R, WWe);\n      Vce::psd(R, WWe, index.at(SST), sigma.at(SST)(arcNo), CosTransform.at(SST), Psd.at(SST),\n               ePe.at(SST), redundancy.at(SST), ePeSum.at(SST), redundancySum.at(SST));\n\n      // Arc-wise covariance matrices\n      if(estimateSigmasCovSst)\n        for(UInt i=0; i<CovSst.at(arcNo).size(); i++)\n          Vce::matrix(R, WWe, std::pow(sigmasCovSst(i),2) * CovSst.at(arcNo).at(i), ePeCovSst(i), redundancyCovSst(i));\n    }\n\n    for(UInt idType : {POD1, POD2})\n      if(count.at(idType))\n      {\n        Vce::redundancy(W.at(idType), We.row(idx.at(idType), 3*count.at(idType)),\n                        WAz.row(idx.at(idType), 3*count.at(idType)), WB.row(idx.at(idType), 3*count.at(idType)), R, WWe);\n        Vce::psd(R, WWe, index.at(idType), sigma.at(idType)(arcNo), CosTransform.at(idType), Psd.at(idType),\n                 ePe.at(idType), redundancy.at(idType), ePeSum.at(idType), redundancySum.at(idType));\n      }\n\n\n    for(UInt idType : {SST, POD1, POD2})  // compute new sigma (for this arc)\n      if(redundancySum.at(idType) > 0.3)\n        sigmaNew.at(idType)(arcNo) = std::sqrt(ePeSum.at(idType)/redundancySum.at(idType)) * sigma.at(idType)(arcNo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingSst::computeResiduals(UInt arcNo)\n{\n  try\n  {\n    if(observationArc.at(arcNo).l.size() == 0)\n      return;\n\n    // count observations and calculate index\n    // --------------------------------------\n    std::array<UInt, TYPESIZE> count, idx;\n    UInt obsCount = 0;\n    for(UInt idType : {SST, POD1, POD2})\n    {\n      count.at(idType) = observationArc.at(arcNo).times.at(idType).size();\n      idx.at(idType)   = obsCount;\n      obsCount        += covColumns.at(idType) * count.at(idType);\n    }\n\n    // Residuals\n    // ---------\n    Matrix e = observationArc.at(arcNo).l;\n    normals.designMatMult(findInterval(arcNo), -1., observationArc.at(arcNo).A, x, e);\n\n    // eliminate arc dependent parameters\n    // ----------------------------------\n    if(observationArc.at(arcNo).B.size())\n    {\n      Matrix We = e;\n      Matrix WB = observationArc.at(arcNo).B;\n      std::array<Matrix, TYPESIZE> W;\n      decorrelate(arcNo, count, W, {We, WB});\n      Vector tau = QR_decomposition(WB);\n      QTransMult(WB, tau, We); // transform observations: l:= Q'l\n      Matrix y = We.row(0, tau.rows());\n      triangularSolve(1., WB.row(0, tau.rows()), y);\n      matMult(-1, observationArc.at(arcNo).B, y, e);\n    }\n\n    // create Sst arc\n    // --------------\n    for(UInt i=0; i<count.at(SST); i++)\n    {\n      SatelliteTrackingEpoch epoch;\n      epoch.time  = observationArc.at(arcNo).times.at(SST).at(i);\n      epoch.range = epoch.rangeRate = epoch.rangeAcceleration = e(idx.at(SST)+i,0);\n      arcListResiduals.at(SST).at(arcNo).push_back(epoch);\n    }\n\n    // create Pod arcs\n    // ---------------\n    for(UInt idType : {POD1, POD2})\n      for(UInt i=0; i<count.at(idType); i++)\n      {\n        OrbitEpoch epoch;\n        epoch.time     = observationArc.at(arcNo).times.at(idType).at(i);\n        epoch.position = Vector3d(e.row(idx.at(idType)+3*i, 3));\n        arcListResiduals.at(idType).at(arcNo).push_back(epoch);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingSst::computeEpochSigmas(UInt arcNo)\n{\n  try\n  {\n    const Double huber = 2.5;\n\n    if(covFunc.at(SST).size())\n    {\n      const Double threshold2 = std::pow(huber*sigma.at(SST)(arcNo), 2) * covFunc.at(SST)(0,1);\n      for(UInt i=0; i<observationArc.at(arcNo).times.at(SST).size(); i++)\n      {\n        const Double e2 = std::pow(dynamic_cast<const SatelliteTrackingEpoch &>(arcListResiduals.at(SST).at(arcNo).at(i)).rangeRate, 2);\n        arcListEpochSigma.at(SST).at(arcNo).at(i).sigma = 0.;\n        if(e2 > threshold2)\n          arcListEpochSigma.at(SST).at(arcNo).at(i).sigma = std::sqrt(e2-threshold2);\n      }\n    }\n\n    for(UInt idType : {POD1, POD2})\n      if(covFunc.at(idType).size())\n      {\n        const Double threshold2 = std::pow(huber*sigma.at(idType)(arcNo), 2) * sum(covFunc.at(idType).slice(0, 1, 1, 3));\n        for(UInt i=0; i<observationArc.at(arcNo).times.at(idType).size(); i++)\n        {\n          const Double e2 = dynamic_cast<const OrbitEpoch &>(arcListResiduals.at(idType).at(arcNo).at(i)).position.quadsum();\n          arcListEpochSigma.at(idType).at(arcNo).at(i).sigma = 0.;\n          if(e2 > threshold2)\n            arcListEpochSigma.at(idType).at(arcNo).at(i).sigma = std::sqrt((e2-threshold2)/3);\n        }\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingVariationalEquation.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingVariationalEquation.cpp\n*\n* @brief Integrate Variational Equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-05-30\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program integrates an orbit dynamically using the given forces and set up the state transition matrix\nfor each time step. These are the prerequisites for a least squares adjustment (e.g. gravity field determination) using\nthe variational equation approach. The variational equations are computed arc-wise as defined by \\configFile{inputfileOrbit}{instrument}.\nThis means for each arc new initial state parameters are set up.\n\nIn a first step the \\configClass{forces}{forcesType} acting on the satellite are evaluated at the apriori positions given\nby \\configFile{inputfileOrbit}{instrument}. Non-conservative forces like solar radiation pressure need the orientation of the\nsatellite (\\configFile{inputfileStarCamera}{instrument}) and additionally, a satellite macro model (\\config{satelliteModel})\nwith the surface properties. Furthermore \\configFile{inputfileAccelerometer}{instrument} observations are also considered.\n\nIn a second step the accelerations are integrated twice to a dynamic orbit using a moving polynomial with the degree\n\\config{integrationDegree}. The orbit is corrected to be self-consistent. This means the forces should be evaluated\nat the new integrated positions instead of the apriori ones. This correction is computed in a linear approximation\nusing the gradient of the forces with respect to the positions (\\config{gradientfield}). As this term is small generally\nonly the largest force components have to be considered. A low degree spherical harmonic expansion of the static gravity\nfield (about up to degree 5) is sufficient in almost all cases. In this step also the state transition matrix (the partial\nderivatives of the current state, position and velocity) with respect to the initial state is computed.\nThe integrated orbit together with the state transitions are stored in \\configFile{outputfileVariational}{variationalEquation},\nthe integrated orbit only in \\configFile{outputfileOrbit}{instrument}.\n\nTo improve the numerical stability a reference ellipse can be reduced beforehand using Enke's method (\\config{useEnke}).\nMathematically the result is the same, but as the large central term is removed before and restored\nafterwards more digits are available for the computation.\n\nThe integrated orbit should be fitted to observations afterwards by the programs\n\\program{PreprocessingVariationalEquationOrbitFit} and/or \\program{PreprocessingVariationalEquationSstFit}.\nThey apply a least squares adjustment by estimating some satellite parameters (e.g. an accelerometer bias).\nIf the fitted orbit is too far away from the original \\configFile{inputfileOrbit}{instrument} the linearization may not be\naccurate enough. In this case \\program{PreprocessingVariationalEquation} should be run again with the fitted orbit\nas \\configFile{inputfileOrbit}{instrument} and introducing the \\config{estimatedParameters} as additional forces.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/equinoctial.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/forces/forces.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Integrate Variational Equations.\n* @ingroup programsGroup */\nclass PreprocessingVariationalEquation\n{\n  SatelliteModelPtr              satellite;\n  InstrumentFile                 orbitFile;\n  InstrumentFile                 starCameraFile;\n  InstrumentFile                 accelerometerFile;\n  ForcesPtr                      forces;\n  EarthRotationPtr               earthRotation;\n  EphemeridesPtr                 ephemerides;\n  GravityfieldPtr                gradientfield;\n  ParametrizationAccelerationPtr parameterAcceleration;\n  Matrix                         parameter;\n  Double                         GM;\n  Double                         maxPosDiff;\n  UInt                           integrationDegree;\n  std::vector<Vector>            coeff_g, coeff_tg;\n\n  VariationalEquationArc computeArc(UInt arcNo);\n  Matrix integrate2Position(Double deltaT, const_MatrixSliceRef g) const;\n  Matrix integrate2Velocity(Double deltaT, const_MatrixSliceRef g) const;\n  Matrix solve(Double deltaT, const std::vector<Tensor3d> &tensor, const_MatrixSliceRef l) const;\n  Matrix refine(Double deltaT, const std::vector<Tensor3d> &tensor, const_MatrixSliceRef x) const;\n  Matrix approxInverse(Double deltaT, const std::vector<Tensor3d> &tensor, const_MatrixSliceRef x) const;\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingVariationalEquation, PARALLEL, \"Integrate Variational Equations.\", Preprocessing, VariationalEquation)\n\n/***********************************************/\n/***********************************************/\n\nvoid PreprocessingVariationalEquation::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOutVariational, fileNameOutOrbit;\n    FileName fileNameSatellite;\n    FileName orbitName, starCameraName, accName;\n    FileName fileNameSolution;\n    GM = 0;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\", date2time(2020, 8, 19));\n\n    readConfig(config, \"outputfileVariational\",       fileNameOutVariational, Config::MUSTSET,   \"\", \"approximate position and integrated state matrix\");\n    readConfig(config, \"outputfileOrbit\",             fileNameOutOrbit,       Config::OPTIONAL,  \"\", \"integrated orbit\");\n    readConfig(config, \"inputfileSatelliteModel\",     fileNameSatellite,      Config::OPTIONAL,  \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"inputfileOrbit\",              orbitName,              Config::MUSTSET,   \"\", \"approximate position, used to evaluate the force\");\n    readConfig(config, \"inputfileStarCamera\",         starCameraName,         Config::MUSTSET,   \"\", \"rotation from body frame to CRF\");\n    readConfig(config, \"inputfileAccelerometer\",      accName,                Config::OPTIONAL,  \"\", \"non-gravitational forces in satellite reference frame\");\n    readConfig(config, \"forces\",                      forces,                 Config::MUSTSET,   \"\", \"\");\n    if(readConfigSequence(config, \"estimatedParameters\", Config::OPTIONAL, \"\", \"satellite parameters e.g. from orbit fit\"))\n    {\n      renameDeprecatedConfig(config, \"parameter\", \"parametrizationAcceleration\", date2time(2020, 6, 3));\n\n      readConfig(config, \"parametrizationAcceleration\", parameterAcceleration, Config::MUSTSET,  \"\", \"orbit force parameters\");\n      readConfig(config, \"inputfileParameter\",          fileNameSolution,      Config::MUSTSET,  \"\", \"estimated orbit force parameters\");\n      endSequence(config);\n    }\n    readConfig(config, \"earthRotation\",     earthRotation,     Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",       ephemerides,       Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"gradientfield\",     gradientfield,     Config::MUSTSET,  \"\",    \"low order field to estimate the change of the gravity by position adjustement\");\n    readConfig(config, \"integrationDegree\", integrationDegree, Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    if(readConfigSequence(config, \"useEnke\", Config::OPTIONAL, \"1\", \"integrate differential forces to an elliptical reference trajectory\"))\n    {\n      readConfig(config, \"GM\", GM, Config::DEFAULT,  STRING_DEFAULT_GM, \"geocentric gravitational constant used for elliptical reference orbit\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    if(integrationDegree%2 == 0)\n      throw(Exception(\"polynomial degree for integration must be odd.\"));\n\n    if(!fileNameSatellite.empty()) readFileSatelliteModel(fileNameSatellite, satellite);\n\n    // open and test instrument files\n    // ------------------------------\n    orbitFile.open(orbitName);\n    starCameraFile.open(starCameraName);\n    accelerometerFile.open(accName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile, accelerometerFile});\n\n    // init calibration parameters\n    if(parameterAcceleration)\n    {\n      readFileMatrix(fileNameSolution, parameter);\n      if(parameterAcceleration->parameterCount() > parameter.rows())\n        throw(Exception(\"parameter and inputfileParameter must agree\"));\n    }\n\n    // init integration\n    // ----------------\n    coeff_g.resize (integrationDegree);\n    coeff_tg.resize(integrationDegree);\n    for(UInt idx=0; idx<coeff_g.size(); idx++)\n    {\n      // polynomial matrix\n      Matrix W(integrationDegree+1, integrationDegree+1);\n      for(UInt i=0; i<W.columns(); i++)\n      {\n        W(i,0) = 1.;\n        for(UInt n=1; n<W.rows(); n++)\n          W(i,n) = (Double(i)-idx) * W(i,n-1);\n      }\n      inverse(W);\n\n      coeff_g.at(idx)  = Vector(W.rows());\n      coeff_tg.at(idx) = Vector(W.rows());\n      for(UInt i=0; i<W.rows(); i++)\n        for(UInt n=0; n<W.columns(); n++)\n        {\n          coeff_g.at(idx)(i)  += 1./(n+1.) * W(n,i);\n          coeff_tg.at(idx)(i) += 1./(n+2.) * W(n,i);\n        }\n    }\n\n    // compute arcs\n    // ------------\n    logStatus<<\"integrate arcs\"<<Log::endl;\n    maxPosDiff = 0;\n    std::vector<VariationalEquationArc> arcs(orbitFile.arcCount());\n    Parallel::forEach(arcs, [this](UInt arcNo) {return computeArc(arcNo);}, comm);\n    Parallel::reduceMax(maxPosDiff, 0, comm);\n    logInfo<<\"  max diff (orbit-reference orbit) \"<<maxPosDiff<<\" m\"<<Log::endl;\n\n    // write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write variational equation to file <\"<<fileNameOutVariational<<\">\"<<Log::endl;\n      writeFileVariationalEquation(fileNameOutVariational, satellite, arcs);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutOrbit.empty())\n    {\n      logStatus<<\"write orbit to file <\"<<fileNameOutOrbit<<\">\"<<Log::endl;\n      std::list<Arc> arcList;\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.push_back(arcs.at(arcNo).orbitArc());\n      InstrumentFile::write(fileNameOutOrbit, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVariationalEquationArc PreprocessingVariationalEquation::computeArc(UInt arcNo)\n{\n  try\n  {\n    OrbitArc          orbit         = orbitFile.readArc(arcNo);\n    StarCameraArc     starCamera    = starCameraFile.readArc(arcNo);\n    AccelerometerArc  accelerometer = accelerometerFile.readArc(arcNo);\n    Arc::checkSynchronized({orbit, starCamera, accelerometer});\n    std::vector<Time> times         = orbit.times();\n    const UInt        epochCount    = orbit.size();\n    const Double      T             = (times.back()-times.at(0)).seconds();\n    const Double      deltaT        = T/(epochCount-1);\n\n    // computeEarthRotation\n    std::vector<Rotary3d> rotEarth(times.size());\n    for(UInt k=0; k<times.size(); k++)\n      rotEarth.at(k) = earthRotation->rotaryMatrix(times.at(k));\n\n    // computeGravityGradient\n    std::vector<Tensor3d> tensor(orbit.size());\n    for(UInt i=0; i<orbit.size(); i++)\n    {\n      Vector3d posEarth = rotEarth.at(i).rotate(orbit.at(i).position);\n      tensor.at(i)      = rotEarth.at(i).inverseRotate(gradientfield->gravityGradient(orbit.at(i).time, posEarth));\n    }\n\n    // computeForce\n    std::vector<Vector3d> force(orbit.size());\n    for(UInt k=0; k<orbit.size(); k++)\n    {\n      // forces are returned in TRF, rotate to CRF\n      force.at(k) = rotEarth.at(k).inverseRotate(forces->acceleration(satellite, orbit.at(k).time, orbit.at(k).position, orbit.at(k).velocity,\n                                         starCamera.at(k).rotary, rotEarth.at(k), earthRotation, ephemerides));\n      // accelerometer\n      if(accelerometer.size())\n        force.at(k) += starCamera.at(k).rotary.rotate(accelerometer.at(k).acceleration);\n    }\n\n    if(parameterAcceleration)\n    {\n      parameterAcceleration->setIntervalArc(times.at(0), times.back()+seconds2time(deltaT));\n      const UInt countA = parameterAcceleration->parameterCount();\n      const UInt countB = parameterAcceleration->parameterCountArc();\n\n      for(UInt k=0; k<times.size(); k++)\n      {\n        Matrix A(3, countA);\n        Matrix B(3, countB);\n        parameterAcceleration->compute(satellite, times.at(k), orbit.at(k).position, orbit.at(k).velocity,\n                                    starCamera.at(k).rotary, rotEarth.at(k), ephemerides, A, B);\n        Vector g2(3);\n        if(countA) matMult(1., A, parameter.row(0, countA), g2);\n        if(countB) matMult(1., B, parameter.row(arcNo*(countB+6)+countA, countB), g2);\n        force.at(k) += rotEarth.at(k).inverseRotate(Vector3d(g2(0), g2(1), g2(2)));\n      }\n    }\n\n    // sort into vector\n    Vector g(3*epochCount);\n    for(UInt k=0; k<epochCount; k++)\n    {\n      g(3*k+0) = force.at(k).x();\n      g(3*k+1) = force.at(k).y();\n      g(3*k+2) = force.at(k).z();\n    }\n\n    // =============================================\n\n    // approx position\n    // ---------------\n    Vector posApprox(3*epochCount);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      posApprox(3*i+0) = orbit.at(i).position.x();\n      posApprox(3*i+1) = orbit.at(i).position.y();\n      posApprox(3*i+2) = orbit.at(i).position.z();\n    }\n\n    // Elliptical reference orbit\n    // --------------------------\n    Vector posRef(3*epochCount);\n    Vector velRef(3*epochCount);\n    if(GM>0) // useEnke\n    {\n      // Collect orbit epochs for mean orbit estimation. Try to use 100 evenly\n      // spaced epochs along the arc, or all of the epochs if the arc is shorter.\n      UInt stagger = (orbit.size() < 100) ? 1 : orbit.size()/100;\n\n      OrbitArc sparseOrbit;\n      for(UInt k=0; k<orbit.size(); k += stagger)\n        sparseOrbit.push_back(orbit.at(k));\n\n      // Osculating orbit at first epoch\n      Vector3d velocity = sparseOrbit.at(0).velocity;\n      if(velocity.r()==0)\n        velocity = (1/(sparseOrbit.at(1).time-sparseOrbit.at(0).time).seconds()) * (sparseOrbit.at(1).position-sparseOrbit.at(0).position);\n\n      // We use an equinoctial orbit because Kepler is not accurate enough\n      Equinoctial referenceOrbit(sparseOrbit.at(0).time, sparseOrbit.at(0).position, velocity, GM);\n\n      UInt   iter    = 0;\n      UInt   maxIter = 100;\n      Vector dx;\n      do\n      {\n        // We will fit to positions only\n        Vector obs(3*sparseOrbit.size());\n        for(UInt i=0; i<sparseOrbit.size(); i++)\n        {\n          const Vector3d dpos = sparseOrbit.at(i).position - referenceOrbit.position(sparseOrbit.at(i).time);\n          obs(3*i+0) = dpos.x();\n          obs(3*i+1) = dpos.y();\n          obs(3*i+2) = dpos.z();\n        }\n\n        Matrix A(3*sparseOrbit.size(), 6);\n        for(UInt i=0; i<sparseOrbit.size(); i++)\n          copy(referenceOrbit.stateTransitionMatrix(sparseOrbit.at(i).time).row(0,3), A.row(3*i,3));\n\n        dx = leastSquares(A, obs);\n        referenceOrbit.a  += dx(0);\n        referenceOrbit.h  += dx(1);\n        referenceOrbit.k  += dx(2);\n        referenceOrbit.p  += dx(3);\n        referenceOrbit.q  += dx(4);\n        referenceOrbit.l0 += dx(5);\n      }\n      while((++iter < maxIter) && (maxabs(dx) > 1e-9));\n\n      if(iter == maxIter)\n        logWarning<<\"no convergence in equinoctial fit\"<< Log::endl;\n\n      for(UInt i=0; i<epochCount; i++)\n      {\n        OrbitEpoch epoch;\n        referenceOrbit.orbit(times.at(i), epoch.position, epoch.velocity, epoch.acceleration);\n\n        // acceleration reduced by reference acceleration\n        g(3*i+0) -= epoch.acceleration.x();\n        g(3*i+1) -= epoch.acceleration.y();\n        g(3*i+2) -= epoch.acceleration.z();\n\n        // Observed position and velocity\n        posRef(3*i+0) = epoch.position.x();\n        posRef(3*i+1) = epoch.position.y();\n        posRef(3*i+2) = epoch.position.z();\n\n        velRef(3*i+0) = epoch.velocity.x();\n        velRef(3*i+1) = epoch.velocity.y();\n        velRef(3*i+2) = epoch.velocity.z();\n      }\n    } // if(useEnke)\n\n    // =============================================\n\n    // State matrix: position partial derivatives with respect to boundary values\n    // --------------------------------------------------------------------------\n    Matrix PosState(3*epochCount, 6);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      PosState(3*i+0, 0) = PosState(3*i+1, 1) = PosState(3*i+2, 2) = 1.; // d(pos)/d(pos0)\n      PosState(3*i+0, 3) = PosState(3*i+1, 4) = PosState(3*i+2, 5) = i*deltaT/T; //(times.at(i)-times.at(0)).seconds()/T;     // d(pos)/d(vel0)\n    }\n\n    // Position\n    // --------\n    Matrix pos0  = integrate2Position(deltaT, g);\n    Vector state = leastSquares(Matrix(PosState), posApprox-posRef-pos0);\n    matMult(1, PosState, state, pos0);\n    pos0 = solve(deltaT, tensor, pos0 - (posApprox-posRef)) + posApprox;\n\n    // =============================================\n\n    // State with indirect effect\n    // --------------------------\n    PosState = solve(deltaT, tensor, PosState);\n\n    Matrix AccState(3*epochCount, 6);\n    for(UInt i=0; i<epochCount; i++)\n      matMult(1., tensor.at(i).matrix(), PosState.row(3*i,3), AccState.row(3*i,3));\n\n    Matrix VelState(3*epochCount, 6);\n    for(UInt i=0; i<epochCount; i++)\n    {\n      VelState(3*i+0, 3) = VelState(3*i+1, 4) = VelState(3*i+2, 5) = 1/T;\n    }\n    // indirect effect\n    axpy(1., integrate2Velocity(deltaT, AccState), VelState);\n\n    // =============================================\n\n    // Acceleration\n    // ------------\n    Matrix acc0 = g;\n    Matrix posDelta = pos0 - posApprox;\n    for(UInt i=0; i<epochCount; i++)\n      matMult(1., tensor.at(i).matrix(), posDelta.row(3*i,3), acc0.row(3*i,3));\n\n    // Velocity\n    // --------\n    Matrix vel0 = integrate2Velocity(deltaT, acc0);\n    for(UInt i=0; i<epochCount; i++)\n      for(UInt j=0; j<vel0.columns(); j++)\n        axpy(1/T, state.row(3,3), vel0.slice(3*i,j,3,1));\n    vel0 += velRef; // velRef is either 0, or when useEnke, the velocity from equinoctial equations.\n\n    // fit to reference orbit\n    // ----------------------\n    {\n      Vector state = leastSquares(Matrix(PosState), posApprox-pos0);\n      matMult(1, PosState, state, pos0);\n      matMult(1, VelState, state, vel0);\n    }\n\n    // =============================================\n\n    VariationalEquationArc arc;\n    arc.times    = times;\n    arc.pos0     = pos0;\n    arc.vel0     = vel0;\n    arc.PosState = PosState;\n    arc.VelState = VelState;\n    arc.rotEarth = rotEarth; // CRF -> TRF\n    arc.rotSat.resize(orbit.size());\n    for(UInt k=0; k<orbit.size(); k++)\n      arc.rotSat.at(k) = starCamera.at(k).rotary; // Sat -> CRF\n\n    // for statistics\n    maxPosDiff = std::max(maxPosDiff, maxabs(arc.pos0-posApprox));\n\n    return arc;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix PreprocessingVariationalEquation::integrate2Position(Double deltaT, const_MatrixSliceRef g) const\n{\n  try\n  {\n    const UInt epochCount = g.rows()/3;\n    Matrix result(g.rows(), g.columns());  // \\int_0^t (t-t') f(t') dt'\n\n    UInt idx       = 0;\n    UInt evalPoint = 0;\n    Matrix int_g(3, g.columns());   // \\int_0^t f(t') dt'\n    Matrix int_tg(3, g.columns());  // \\int_0^t t'f(t') dt'\n    for(UInt i=0; i<epochCount-1; i++)\n    {\n      Matrix tmp(3, g.columns());\n      for(UInt k=0; k<coeff_g.at(idx).rows(); k++)\n        axpy(deltaT * coeff_g.at(idx)(k), g.row(3*(i+k-evalPoint),3), tmp);\n      for(UInt k=0; k<coeff_tg.at(idx).rows(); k++)\n        axpy(deltaT*deltaT * coeff_tg.at(idx)(k), g.row(3*(i+k-evalPoint),3), int_tg);\n      axpy(i*deltaT, tmp, int_tg);\n      int_g += tmp;\n\n      // select polynomial coefficients\n      if(i<integrationDegree/2)\n        idx++, evalPoint++;\n      if(i>=epochCount-1-integrationDegree/2-1)\n        idx++, evalPoint++;\n\n      axpy((i+1)*deltaT, int_g,  result.row(3*(i+1),3)); //  t * \\int_0^t f(t') dt'\n      axpy(-1.,          int_tg, result.row(3*(i+1),3)); // -1 * \\int_0^t t'f(t') dt'\n    } // for(i)\n\n    return result;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix PreprocessingVariationalEquation::integrate2Velocity(Double deltaT, const_MatrixSliceRef g) const\n{\n  try\n  {\n    const UInt epochCount = g.rows()/3;\n    Matrix result(g.rows(), g.columns());\n\n    UInt idx       = 0;\n    UInt evalPoint = 0;\n    for(UInt i=0; i<epochCount-1; i++)\n    {\n      copy(result.row(3*i,3), result.row(3*(i+1),3));\n      for(UInt k=0; k<coeff_g.at(idx).rows(); k++)\n        axpy(deltaT*coeff_g.at(idx)(k), g.row(3*(i+k-evalPoint),3), result.row(3*(i+1),3));\n\n      // select polynomial coefficients\n      if(i<integrationDegree/2)\n        idx++, evalPoint++;\n      if(i>=epochCount-1-integrationDegree/2-1)\n        idx++, evalPoint++;\n    } // for(i)\n\n    return result;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// indirect effect (dependency of gravity due to position change)\n// x = (I-integrate(T))^-1 l\n// with the iterative solver BiCGSTAB\n// BiCGSTAB (http://en.wikipedia.org/wiki/Biconjugate_gradient_stabilized_method)\nMatrix PreprocessingVariationalEquation::solve(Double deltaT, const std::vector<Tensor3d> &tensor, const_MatrixSliceRef l) const\n{\n  try\n  {\n    // Approximate solution\n    // --------------------\n    Matrix x = approxInverse(deltaT, tensor, l);\n    Matrix delta;\n\n    for(UInt iter2=0; iter2<50; iter2++)\n    {\n      Matrix r  = l - refine(deltaT, tensor, x);\n      Matrix r0 = r;\n      const UInt rhsCount = x.columns();\n      Vector rho(rhsCount), alpha(rhsCount), omega(rhsCount);\n      for(UInt i=0; i<rhsCount; i++)\n        rho(i) = alpha(i) = omega(i) = 1.;\n      Matrix v(x.rows(), rhsCount);\n      Matrix p(x.rows(), rhsCount);\n\n      for(UInt iter=0; iter<1; iter++)\n      {\n        for(UInt i=0; i<rhsCount; i++)\n        {\n          Double rhoOld = rho(i);\n          rho(i) = inner(r0.column(i), r.column(i));\n          Double beta = (rho(i)/rhoOld)*(alpha(i)/omega(i));\n          axpy(-omega(i), v.column(i), p.column(i));\n          p.column(i) *= beta;\n          axpy(1., r.column(i), p.column(i));\n        }\n        Matrix pHat = approxInverse(deltaT, tensor, p);\n        v = refine(deltaT, tensor, pHat);\n        for(UInt i=0; i<rhsCount; i++)\n        {\n          alpha(i) = rho(i)/inner(r0.column(i), v.column(i));\n          axpy(-alpha(i), v.column(i), r.column(i));\n        }\n        Matrix sHat = approxInverse(deltaT, tensor, r);\n        Matrix t = refine(deltaT, tensor, sHat);\n        Matrix xOld = x;\n        for(UInt i=0; i<rhsCount; i++)\n        {\n          omega(i) = inner(t.column(i), r.column(i))/inner(t.column(i), t.column(i));\n          axpy( alpha(i), pHat.column(i), x.column(i));\n          axpy( omega(i), sHat.column(i), x.column(i));\n          axpy(-omega(i), t.column(i), r.column(i));\n        }\n        delta = x-xOld;\n        if(maxabs(delta) < 1e-7)\n          break;\n      }  // for(iter)\n\n      if(maxabs(delta) < 1e-7)\n        break;\n    } // for(iter2)\n\n    return x;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// y = (I-K*T)x = x - integrate(T*x)\nMatrix PreprocessingVariationalEquation::refine(Double deltaT, const std::vector<Tensor3d> &tensor, const_MatrixSliceRef x) const\n{\n  try\n  {\n    Matrix y  = x;\n    Matrix Tx(x.rows(), x.columns());\n    for(UInt i=0; i<tensor.size(); i++)\n      matMult(1., tensor.at(i).matrix(), x.row(3*i,3), Tx.row(3*i,3));\n    y -= integrate2Position(deltaT, Tx);\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// y = (I-K*T)^-1 x\nMatrix PreprocessingVariationalEquation::approxInverse(Double deltaT, const std::vector<Tensor3d> &tensor, const_MatrixSliceRef x) const\n{\n  try\n  {\n    Matrix y   = x;\n    Matrix tmp = tensor.at(0).matrix() * y.row(0,3);\n    Matrix Ty  = 0.5*deltaT*deltaT * tmp;\n    Matrix tTy = -deltaT*deltaT/6  * tmp;\n\n    for(UInt i=1; i<tensor.size(); i++)\n    {\n      axpy(i,  Ty, y.row(3*i,3));\n      axpy(1, tTy, y.row(3*i,3));\n\n      Matrix K(3,3);\n      K(0,0) = K(1,1) = K(2,2) = 1.;\n      axpy(-1./6.*deltaT*deltaT, tensor.at(i).matrix(), K);\n      solveInPlace(K, y.row(3*i,3));\n\n      const Matrix tmp = tensor.at(i).matrix() * y.row(3*i,3);\n      axpy( deltaT*deltaT,   tmp, Ty);\n      axpy(-deltaT*deltaT*i, tmp, tTy);\n    }\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingVariationalEquationOrbitFit.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingVariationalEquationOrbitFit.cpp\n*\n* @brief Fit variational equations to orbit observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2012-05-30\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program fits an \\configFile{inputfileVariational}{variationalEquation} to an observed \\configFile{inputfileOrbit}{instrument} by estimating parameters\nin a least squares adjustment. Additional to the initial satellite state for each arc, these parameters can be\n\\configClass{parametrizationGravity}{parametrizationGravityType}, satellite \\configClass{parametrizationAcceleration}{parametrizationAccelerationType}\nand stochastic pulses (velocity jumps) at given times, \\configClass{stochasticPulse}{timeSeriesType}. The estimated parameters can be stored with\n\\configFile{outputfileSolution}{matrix} and an extra file with the parameter names is created. The fitted orbit is written\nas new reference in \\configFile{outputfileVariational}{variationalEquation} and additionally in \\configFile{outputfileOrbit}{instrument}.\n\nThe observed orbit positions (\\configFile{inputfileOrbit}{instrument}) together with the epoch-wise covariance matrix\n(\\configFile{inputfileCovariancePodEpoch}{instrument}) must be split in the same arcs as the variational equations but not\nnecessarily uniformly distributed (use irregularData in \\program{InstrumentSynchronize}). An iterative downweighting of\noutliers is performed by M-Huber method.\n\nThe observation equations (parameter sensitivity matrix) are computed by integration of the variational equations\n(\\configFile{inputfileVariational}{variationalEquation}) using a polynomial with \\config{integrationDegree} and interpolated to the\nobservation epochs using a polynomial with \\config{interpolationDegree}.\n\nAll parameters used here must be reestimated in the full least squares adjustment\nfor the gravity field determination to get a solution which is not biased towards the reference field.\nThe solutions of additional estimations are relative (deltas) as the parameters are already used as Taylor point\nin the reference orbit.\n\nSee also \\program{PreprocessingVariationalEquation}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Fit variational equations to orbit observations\n* @ingroup programsGroup */\nclass PreprocessingVariationalEquationOrbitFit\n{\npublic:\n  VariationalEquationFromFile    variationalEquationFromFile;\n  InstrumentFile                 podFile;\n  InstrumentFile                 covPodEpochFile;\n  EphemeridesPtr                 ephemerides;\n  ParametrizationAccelerationPtr parameterAcceleration;\n  ParametrizationGravityPtr      parameterGravity;\n  UInt                           interpolationDegree;\n  UInt                           arcCount;\n\n  // normal equations\n  // ----------------\n  Matrix N;           // =A'PA, Normal matrix\n  Vector n;           // =A'Pl, right hand side\n  Double lPl;         // =l'Pl, weighted norm of the observations\n  UInt   obsCount;    // number of observations\n  UInt   outlierCount;\n  Vector x;\n  Double sigma0;\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  void buildNormals(UInt arcNo);\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingVariationalEquationOrbitFit, PARALLEL, \"fit variational equations to orbit observations\", Preprocessing, VariationalEquation)\n\n/***********************************************/\n/***********************************************/\n\nvoid PreprocessingVariationalEquationOrbitFit::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOutVariational, fileNameOutOrbit, fileNameOutSolution;\n    FileName fileNameInVariational;\n    FileName podName, covPodEpochName;\n    UInt              integrationDegree;\n    UInt              iterCount;\n    std::vector<Time> stochasticPulse;\n    TimeSeriesPtr     stochasticPulsePtr;\n\n    renameDeprecatedConfig(config, \"representation\", \"parametrizationGravity\",      date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"parameter\",      \"parametrizationAcceleration\", date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileVariational\",       fileNameOutVariational, Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"outputfileOrbit\",             fileNameOutOrbit,       Config::OPTIONAL, \"\",    \"integrated orbit\");\n    readConfig(config, \"outputfileSolution\",          fileNameOutSolution,    Config::OPTIONAL, \"\",    \"estimated calibration and state parameters\");\n    readConfig(config, \"inputfileVariational\",        fileNameInVariational,  Config::MUSTSET,  \"\",    \"approximate position and integrated state matrix\");\n    readConfig(config, \"inputfileOrbit\",              podName,                Config::MUSTSET,  \"\",    \"kinematic positions of satellite as observations\");\n    readConfig(config, \"inputfileCovariancePodEpoch\", covPodEpochName,        Config::OPTIONAL, \"\",    \"3x3 epoch wise covariances\");\n    readConfig(config, \"ephemerides\",                 ephemerides,            Config::OPTIONAL, \"jpl\", \"may be needed by parametrizationAcceleration\");\n    readConfig(config, \"parametrizationGravity\",      parameterGravity,       Config::DEFAULT,  \"\",    \"gravity field parametrization\");\n    readConfig(config, \"parametrizationAcceleration\", parameterAcceleration,  Config::DEFAULT,  \"\",    \"orbit force parameters\");\n    readConfig(config, \"stochasticPulse\",             stochasticPulsePtr,     Config::DEFAULT,  \"\",    \"\");\n    readConfig(config, \"integrationDegree\",           integrationDegree,      Config::DEFAULT,  \"7\",   \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,    Config::DEFAULT,  \"7\",   \"orbit interpolation by polynomial approximation of degree n\");\n    readConfig(config, \"iterationCount\",              iterCount,              Config::DEFAULT,  \"10\",  \"for the estimation of calibration parameter and error PSD\");\n    if(isCreateSchema(config)) return;\n\n    if(integrationDegree%2 == 0)\n      throw(Exception(\"polnomial degree for integration must be odd.\"));\n\n    if(stochasticPulsePtr)\n      stochasticPulse = stochasticPulsePtr->times();\n\n    // init\n    // ----\n    podFile.open(podName);\n    covPodEpochFile.open(covPodEpochName);\n    InstrumentFile::checkArcCount({podFile, covPodEpochFile});\n    variationalEquationFromFile.open(fileNameInVariational, parameterGravity, parameterAcceleration, stochasticPulse, ephemerides, integrationDegree);\n\n    // =============================================\n\n    x = Vector(variationalEquationFromFile.parameterCount());\n    sigma0 = 1;\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      // build normals\n      // -------------\n      logStatus<<\"accumulate normal equations\"<<Log::endl;\n      N            = Matrix(variationalEquationFromFile.parameterCount(), Matrix::SYMMETRIC);\n      n            = Vector(variationalEquationFromFile.parameterCount());\n      lPl          = 0;\n      obsCount     = 0;\n      outlierCount = 0;\n\n      Parallel::forEach(podFile.arcCount(), [this](UInt arcNo) {buildNormals(arcNo);}, comm);\n\n      Parallel::reduceSum(N,            0, comm);\n      Parallel::reduceSum(n,            0, comm);\n      Parallel::reduceSum(lPl,          0, comm);\n      Parallel::reduceSum(obsCount,     0, comm);\n      Parallel::reduceSum(outlierCount, 0, comm);\n\n      // Estimate parameters\n      // -------------------\n      if(Parallel::isMaster(comm))\n      {\n        // Regularize unused parameters\n        for(UInt i=0; i<N.rows(); i++)\n          if(N(i,i) == 0)\n            N(i,i) = 1.0;\n\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        x = solve(N,n);\n        sigma0 = Vce::standardDeviation(lPl-inner(n,x), obsCount-x.rows(), 2.5/*huber*/, 1./*huberPower*/);\n        logInfo<<\"  aposteriori sigma: \"<<sigma0<<Log::endl;\n        logInfo<<\"  outlier \"<<outlierCount<<\" of \"<<obsCount<<\" (\"<<100.*outlierCount/obsCount<<\"%)\"<<Log::endl;\n      }\n\n      Parallel::broadCast(outlierCount, 0, comm);\n      if((iter>0) && (outlierCount==0))\n        break;\n\n      logInfo<<\"  parameter count = \"<<variationalEquationFromFile.parameterCount()<<Log::endl;\n      Parallel::broadCast(x, 0, comm);\n      Parallel::broadCast(sigma0, 0, comm);\n    } // for(iter)\n\n    if(Parallel::isMaster(comm) && !fileNameOutSolution.empty())\n    {\n      logStatus<<\"write solution to <\"<<fileNameOutSolution<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOutSolution, x);\n\n      std::vector<ParameterName> parameterName;\n      variationalEquationFromFile.parameterName(parameterName);\n      writeFileParameterName(fileNameOutSolution.replaceFullExtension(\".parameterName.txt\"), parameterName);\n    }\n\n    // =============================================================================\n\n    // Improve orbits with estimated parameters\n    // ----------------------------------------\n    std::vector<VariationalEquationArc> arcs(variationalEquationFromFile.arcCount());\n    Parallel::forEach(arcs, [this](UInt arcNo) {return variationalEquationFromFile.refineVariationalEquationArc(arcNo, x);}, comm);\n\n    // =============================================================================\n\n    if(Parallel::isMaster(comm) && !fileNameOutVariational.empty())\n    {\n      logStatus<<\"write variational equation to file <\"<<fileNameOutVariational<<\">\"<<Log::endl;\n      writeFileVariationalEquation(fileNameOutVariational, variationalEquationFromFile.satellite(), arcs);\n    }\n\n    // =============================================\n\n    if(Parallel::isMaster(comm) && !fileNameOutOrbit.empty())\n    {\n      logStatus<<\"write orbit to file <\"<<fileNameOutOrbit<<\">\"<<Log::endl;\n      std::list<Arc> arcList;\n      for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n        arcList.push_back( arcs.at(arcNo).orbitArc() );\n      InstrumentFile::write(fileNameOutOrbit, arcList);\n    }\n\n    // =============================================\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingVariationalEquationOrbitFit::buildNormals(UInt arcNo)\n{\n  try\n  {\n    OrbitArc pod = podFile.readArc(arcNo);\n    if(pod.size() == 0)\n      return;\n\n    Vector l(3*pod.size());\n    for(UInt k=0; k<pod.size(); k++)\n    {\n      l(3*k+0) = pod.at(k).position.x();\n      l(3*k+1) = pod.at(k).position.y();\n      l(3*k+2) = pod.at(k).position.z();\n    }\n\n    std::vector<Time> timePod = pod.times();\n    VariationalEquationFromFile::ObservationEquation eqn = variationalEquationFromFile.integrateArc(timePod.front(), timePod.back(), TRUE/*position*/, FALSE/*velocity*/);\n    Polynomial polynomial(eqn.times, interpolationDegree);\n    l -= polynomial.interpolate(timePod, eqn.pos0, 3); // reference orbit\n    Matrix A = polynomial.interpolate(timePod, eqn.PosDesign, 3);\n\n    // decorrelation\n    Covariance3dArc covPod = covPodEpochFile.readArc(arcNo);\n    Arc::checkSynchronized({pod, covPod});\n    for(UInt i=0; i<covPod.size(); i++)\n    {\n      Matrix W = covPod.at(i).covariance.matrix();\n      W.setType(Matrix::SYMMETRIC);\n      cholesky(W);\n\n      triangularSolve(1., W.trans(), l.row(3*i,3));\n      triangularSolve(1., W.trans(), A.row(3*i,3));\n    }\n\n    // downweight outliers\n    if(quadsum(x))\n    {\n      const Double huber = 2.5;\n      Vector e = l;\n      matMult(-1, A, x, e);\n      for(UInt k=0; k<pod.size(); k++)\n      {\n        Double s = sqrt(quadsum(e.row(3*k,3))/3);\n        if(s>huber*sigma0)\n        {\n          l.row(3*k,3) *= huber*sigma0/s;\n          A.row(3*k,3) *= huber*sigma0/s;\n          outlierCount += 3;\n        }\n      }\n    }\n\n    lPl += quadsum(l);\n    obsCount += l.rows();\n    rankKUpdate(1., A, N);\n    matMult(1., A.trans(), l, n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/preprocessing/preprocessingVariationalEquationSstFit.cpp",
    "content": "/***********************************************/\n/**\n* @file preprocessingVariationalEquationSstFit.cpp\n*\n* @brief Fit variational equations to sst/orbit observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2015-07-06\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program fits two \\configFile{inputfileVariational1/2}{variationalEquation} to satellite-to-satellite-tracking (SST) and orbit\nobservations in a GRACE like configuration. It works similar to \\program{PreprocessingVariationalEquationOrbitFit},\nsee there for details.\n\nAs the relative weighting of the observation types is important complex description of the covariances can be set with\n\\configClass{covarianceSst}{covarianceSstType}, \\configClass{covariancePod1}{covariancePodType}, \\configClass{covariancePod2}{covariancePodType}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"files/fileParameterName.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"misc/observation/observationMiscSstVariational.h\"\n#include \"misc/observation/covariancePod.h\"\n#include \"misc/observation/covarianceSst.h\"\n#include \"misc/observation/variationalEquation.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Fit variational equations to sst/orbit observations.\n* @ingroup programsGroup */\nclass PreprocessingVariationalEquationSstFit\n{\npublic:\n  ObservationMiscSstVariationalPtr observationMisc;\n  CovarianceSstPtr covSst;\n  CovariancePodPtr covPod1, covPod2;\n  std::vector<ObservationMiscSst::Arc> observationArc;\n\n  // normal equations\n  // ----------------\n  Matrix N_Sst, N_Pod;              // =A'PA, Normal matrix\n  Vector n_Sst, n_Pod;              // =A'Pl, right hand side\n  Double lPl_Sst, lPl_Pod;          // =l'Pl, weighted norm of the observations\n  UInt   obsCountSst, obsCountPod;  // number of observations\n  UInt   outlierCountSst, outlierCountPod;\n  Double sigma0Sst, sigma0Pod;\n  Vector x, x1, x2;\n\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n\n  void buildNormals(UInt arcNo);\n};\n\nGROOPS_REGISTER_PROGRAM(PreprocessingVariationalEquationSstFit, PARALLEL, \"fit variational equations to sst/orbit observations\", Preprocessing, VariationalEquation)\n\n/***********************************************/\n\nvoid PreprocessingVariationalEquationSstFit::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOutVariational1, fileNameOutVariational2;\n    FileName fileNameOutOrbit1, fileNameOutOrbit2;\n    FileName fileNameOutSolution1, fileNameOutSolution2;\n    UInt     iterCount;\n\n    readConfig(config, \"outputfileVariational1\", fileNameOutVariational1, Config::MUSTSET,  \"\", \"approximate position and integrated state matrix\");\n    readConfig(config, \"outputfileVariational2\", fileNameOutVariational2, Config::MUSTSET,  \"\", \"approximate position and integrated state matrix\");\n    readConfig(config, \"outputfileOrbit1\",       fileNameOutOrbit1,       Config::OPTIONAL, \"\", \"integrated orbit\");\n    readConfig(config, \"outputfileOrbit2\",       fileNameOutOrbit2,       Config::OPTIONAL, \"\", \"integrated orbit\");\n    readConfig(config, \"outputfileSolution1\",    fileNameOutSolution1,    Config::OPTIONAL, \"\", \"estimated calibration and state parameters\");\n    readConfig(config, \"outputfileSolution2\",    fileNameOutSolution2,    Config::OPTIONAL, \"\", \"estimated calibration and state parameters\");\n    observationMisc = ObservationMiscSstVariationalPtr(new ObservationMiscSstVariational(config));\n    readConfig(config, \"covarianceSst\",          covSst,                  Config::MUSTSET,  \"\", \"covariance matrix of satellite to satellite tracking observations\");\n    readConfig(config, \"covariancePod1\",         covPod1,                 Config::MUSTSET,  \"\", \"covariance matrix of kinematic orbits (satellite 1)\");\n    readConfig(config, \"covariancePod2\",         covPod2,                 Config::MUSTSET,  \"\", \"covariance matrix of kinematic orbits (satellite 2)\");\n    readConfig(config, \"iterationCount\",         iterCount,               Config::DEFAULT,  \"10\", \"for the estimation of calibration parameter and error PSD\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"set up observation equations\"<<Log::endl;\n    observationArc.resize(observationMisc->arcCount());\n    std::vector<UInt> processNo = Parallel::forEach(observationMisc->arcCount(), [this](UInt arcNo) {observationArc.at(arcNo) = observationMisc->computeArc(arcNo, covSst, covPod1, covPod2);}, comm);\n\n    x = Vector(observationMisc->parameterCount());\n    sigma0Sst = 1;\n    sigma0Pod = 1;\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      // build normals\n      // -------------\n      logStatus<<\"accumulate normal equations\"<<Log::endl;\n      logInfo<<\"  parameter count = \"<<observationMisc->parameterCount()<<Log::endl;\n      N_Sst   = Matrix(observationMisc->parameterCount(), Matrix::SYMMETRIC);\n      N_Pod   = Matrix(observationMisc->parameterCount(), Matrix::SYMMETRIC);\n      n_Sst   = Vector(observationMisc->parameterCount());\n      n_Pod   = Vector(observationMisc->parameterCount());\n      lPl_Sst = 0;\n      lPl_Pod = 0;\n      obsCountSst = outlierCountSst = 0;\n      obsCountPod = outlierCountPod = 0;\n\n      Parallel::forEachProcess(observationMisc->arcCount(), [this](UInt arcNo) {buildNormals(arcNo);}, processNo, comm);\n\n      Parallel::reduceSum(N_Sst,           0, comm);\n      Parallel::reduceSum(N_Pod,           0, comm);\n      Parallel::reduceSum(n_Sst,           0, comm);\n      Parallel::reduceSum(n_Pod,           0, comm);\n      Parallel::reduceSum(lPl_Sst,         0, comm);\n      Parallel::reduceSum(lPl_Pod,         0, comm);\n      Parallel::reduceSum(obsCountSst,     0, comm);\n      Parallel::reduceSum(obsCountPod,     0, comm);\n      Parallel::reduceSum(outlierCountSst, 0, comm);\n      Parallel::reduceSum(outlierCountPod, 0, comm);\n      UInt outlierCount = outlierCountSst + outlierCountPod;\n\n      // Estimate parameters\n      // -------------------\n      if(Parallel::isMaster(comm))\n      {\n        Matrix N = pow(1./sigma0Sst,2) * N_Sst + pow(1./sigma0Pod,2) * N_Pod;\n        Vector n = pow(1./sigma0Sst,2) * n_Sst + pow(1./sigma0Pod,2) * n_Pod;\n\n        // Regularize unused parameters\n        for(UInt i=0; i<N.rows(); i++)\n          if(N(i,i) == 0)\n            N(i,i) = 1.0;\n\n        logStatus<<\"solve system of normal equations\"<<Log::endl;\n        x = solve(N,n);\n\n        // variance component estimation\n        cholesky2Inverse(N);\n        fillSymmetric(N);\n        fillSymmetric(N_Pod);\n        fillSymmetric(N_Sst);\n        const Double ePe_Sst = lPl_Sst - 2*inner(x, n_Sst) + inner(x, N_Sst*x);\n        const Double ePe_Pod = lPl_Pod - 2*inner(x, n_Pod) + inner(x, N_Pod*x);\n        const Double r_Sst   = obsCountSst - pow(1./sigma0Sst,2)*inner(N, N_Sst);\n        const Double r_Pod   = obsCountPod - pow(1./sigma0Pod,2)*inner(N, N_Pod);\n        sigma0Sst = Vce::standardDeviation(ePe_Sst, r_Sst, 2.5/*huber*/, 1./*huberPower*/);\n        sigma0Pod = Vce::standardDeviation(ePe_Pod, r_Pod, 2.5/*huber*/, 1./*huberPower*/);\n\n        logInfo<<\"  aposteriori sigma (SST): \"<<sigma0Sst<<Log::endl;\n        logInfo<<\"  aposteriori sigma (POD): \"<<sigma0Pod<<Log::endl;\n        logInfo<<\"  outlier (SST) \"<<outlierCountSst<<\" of \"<<obsCountSst<<\" (\"<<100.*outlierCountSst/obsCountSst<<\"%)\"<<Log::endl;\n        logInfo<<\"  outlier (POD) \"<<outlierCountPod<<\" of \"<<obsCountPod<<\" (\"<<100.*outlierCountPod/obsCountPod<<\"%)\"<<Log::endl;\n      }\n\n      Parallel::broadCast(outlierCount, 0, comm);\n      if((iter>0) && (outlierCount==0))\n        break;\n\n      Parallel::broadCast(x, 0, comm);\n      Parallel::broadCast(sigma0Sst, 0, comm);\n      Parallel::broadCast(sigma0Pod, 0, comm);\n    } // for(iter)\n\n    // Split solution\n    // --------------\n    const UInt gravityCount = observationMisc->variationalEquation1.parameterCountGravity();\n    const UInt state1Count  = observationMisc->variationalEquation1.parameterCount() - gravityCount;\n    const UInt state2Count  = observationMisc->variationalEquation2.parameterCount() - gravityCount;\n\n    UInt countAParameter = 0;\n    const UInt idxGravity  = countAParameter; countAParameter += gravityCount;\n    const UInt idxState1   = countAParameter; countAParameter += state1Count;\n    const UInt idxState2   = countAParameter; countAParameter += state2Count;\n\n    x1 = Vector(gravityCount+state1Count);\n    if(gravityCount) copy(x.row(idxGravity, gravityCount), x1.row(0, gravityCount));\n    if(state1Count)  copy(x.row(idxState1, state1Count),   x1.row(gravityCount, state1Count));\n\n    x2 = Vector(gravityCount+state2Count);\n    if(gravityCount) copy(x.row(idxGravity, gravityCount), x2.row(0, gravityCount));\n    if(state2Count)  copy(x.row(idxState2, state2Count),   x2.row(gravityCount, state2Count));\n\n    if(Parallel::isMaster(comm) && !fileNameOutSolution1.empty())\n    {\n      logStatus<<\"write solution to <\"<<fileNameOutSolution1<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOutSolution1, x1);\n\n      std::vector<ParameterName> parameterName;\n      observationMisc->variationalEquation1.parameterName(parameterName);\n      writeFileParameterName(fileNameOutSolution1.replaceFullExtension(\".parameterName.txt\"), parameterName);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutSolution2.empty())\n    {\n      logStatus<<\"write solution to <\"<<fileNameOutSolution2<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOutSolution2, x2);\n\n      std::vector<ParameterName> parameterName;\n      observationMisc->variationalEquation2.parameterName(parameterName);\n      writeFileParameterName(fileNameOutSolution2.replaceFullExtension(\".parameterName.txt\"), parameterName);\n    }\n\n    // =============================================================================\n\n    // Improve orbits with estimated parameters\n    // ----------------------------------------\n    logStatus<<\"Improve orbits with estimated parameters\"<<Log::endl;\n    std::vector<VariationalEquationArc> arcs1(observationMisc->variationalEquation1.arcCount());\n    std::vector<VariationalEquationArc> arcs2(observationMisc->variationalEquation2.arcCount());\n    Parallel::forEach(arcs1, [&](UInt arcNo) {return observationMisc->variationalEquation1.refineVariationalEquationArc(arcNo, x1);}, comm);\n    Parallel::forEach(arcs2, [&](UInt arcNo) {return observationMisc->variationalEquation2.refineVariationalEquationArc(arcNo, x2);}, comm);\n\n    // =============================================================================\n\n    if(Parallel::isMaster(comm) && !fileNameOutVariational1.empty())\n    {\n      logStatus<<\"write variational equation to file <\"<<fileNameOutVariational1<<\">\"<<Log::endl;\n      writeFileVariationalEquation(fileNameOutVariational2, observationMisc->variationalEquation1.satellite(), arcs1);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutVariational2.empty())\n    {\n      logStatus<<\"write variational equation to file <\"<<fileNameOutVariational2<<\">\"<<Log::endl;\n      writeFileVariationalEquation(fileNameOutVariational2, observationMisc->variationalEquation2.satellite(), arcs2);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutOrbit1.empty())\n    {\n      logStatus<<\"write orbit to file <\"<<fileNameOutOrbit1<<\">\"<<Log::endl;\n      std::list<Arc> arcList;\n      for(UInt arcNo=0; arcNo<arcs1.size(); arcNo++)\n        arcList.push_back( arcs1.at(arcNo).orbitArc() );\n      InstrumentFile::write(fileNameOutOrbit1, arcList);\n    }\n\n    if(Parallel::isMaster(comm) && !fileNameOutOrbit2.empty())\n    {\n      logStatus<<\"write orbit to file <\"<<fileNameOutOrbit2<<\">\"<<Log::endl;\n      std::list<Arc> arcList;\n      for(UInt arcNo=0; arcNo<arcs2.size(); arcNo++)\n        arcList.push_back( arcs2.at(arcNo).orbitArc() );\n      InstrumentFile::write(fileNameOutOrbit2, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid PreprocessingVariationalEquationSstFit::buildNormals(UInt arcNo)\n{\n  try\n  {\n    Vector l = observationArc.at(arcNo).l;\n    Matrix A = observationArc.at(arcNo).A;\n\n    // count observations and calculate index\n    // --------------------------------------\n    const UInt countSst  = observationArc.at(arcNo).times.at(0).size();\n    const UInt countPod1 = observationArc.at(arcNo).times.at(1).size();\n    const UInt countPod2 = observationArc.at(arcNo).times.at(2).size();\n\n    UInt obsCount = 0;\n    const UInt idxSst  = obsCount; obsCount += countSst;\n    const UInt idxPod1 = obsCount; obsCount += 3*countPod1;\n    const UInt idxPod2 = obsCount; obsCount += 3*countPod2;\n\n    // downweight outliers\n    if(quadsum(x))\n    {\n      const Double huber = 2.5;\n\n      Vector e = l;\n      matMult(-1, A, x, e);\n\n      for(UInt k=0; k<countSst; k++)\n      {\n        const Double s = fabs(e(idxSst+k));\n        if(s>huber*sigma0Sst)\n        {\n          l.row(idxSst+k) *= huber*sigma0Sst/s;\n          A.row(idxSst+k) *= huber*sigma0Sst/s;\n          outlierCountSst++;\n        }\n      }\n\n      for(UInt k=0; k<countPod1; k++)\n      {\n        const Double s = sqrt(quadsum(e.row(idxPod1+3*k,3))/3);\n        if(s>huber*sigma0Pod)\n        {\n          l.row(idxPod1+3*k,3) *= huber*sigma0Pod/s;\n          A.row(idxPod1+3*k,3) *= huber*sigma0Pod/s;\n          outlierCountPod += 3;\n        }\n      }\n\n      for(UInt k=0; k<countPod2; k++)\n      {\n        const Double s = sqrt(quadsum(e.row(idxPod2+3*k,3))/3);\n        if(s>huber*sigma0Pod)\n        {\n          l.row(idxPod2+3*k,3) *= huber*sigma0Pod/s;\n          A.row(idxPod2+3*k,3) *= huber*sigma0Pod/s;\n          outlierCountPod += 3;\n        }\n      }\n\n    } // if(quadsum(x))\n\n    // Sst\n    rankKUpdate(1., A.row(idxSst, countSst), N_Sst);\n    matMult(1., A.row(idxSst, countSst).trans(), l.row(idxSst, countSst), n_Sst);\n    lPl_Sst      += quadsum(l.row(idxSst, countSst));\n    obsCountSst  += countSst;\n\n    // Pod\n    rankKUpdate(1., A.row(idxPod1, 3*(countPod1+countPod2)), N_Pod);\n    matMult(1., A.row(idxPod1, 3*(countPod1+countPod2)).trans(), l.row(idxPod1, 3*(countPod1+countPod2)), n_Pod);\n    lPl_Pod      += quadsum(l.row(idxPod1, 3*(countPod1+countPod2)));\n    obsCountPod  += 3*(countPod1+countPod2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/program.cpp",
    "content": "/***********************************************/\n/**\n* @file program.cpp\n*\n* @brief Interface for applications in groops.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-07-27\n*\n*/\n/***********************************************/\n\n// define GROOPS_TAGS to autogenerate tagStrings\n#define GROOPS_STRINGIFY(x) ,#x\n#define GROOPS_TAGS(tag_, ...)\\\nenum Tags {tag_, __VA_ARGS__};\\\nconst char *tagStrings[] = {#tag_ _GROOPS_FOR_EACH(GROOPS_STRINGIFY, __VA_ARGS__)};\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"program.h\"\n\n/***********************************************/\n\nstd::vector<Program::Program*> Program::Program::programList(Program *program)\n{\n  static std::vector<Program*> list;\n  if(program != nullptr)\n    list.push_back(program);\n  return list;\n}\n\n/***********************************************/\n\n// sort programlist according to first tag, followed by alphabetical order of names\nvoid Program::Program::sortList(std::vector<Program*> &list)\n{\n  std::sort(list.begin(), list.end(), [](Program *a, Program *b) {return (a->tags().at(0) != b->tags().at(0)) ? (a->tags().at(0) < b->tags().at(0)) : (a->name() < b->name());});\n}\n\n/***********************************************/\n\nstd::vector<Program::RenamedProgram::Renamed>\n  Program::RenamedProgram::renamedList(const Renamed &renamed)\n{\n  static std::vector<Renamed> list;\n  if(!renamed.oldName.empty())\n    list.push_back(renamed);\n  return list;\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/program.h",
    "content": "/***********************************************/\n/**\n* @file program.h\n*\n* @brief Interface for applications in groops.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-07-27\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_PROGRAM__\n#define __GROOPS_PROGRAM__\n\n#include \"base/import.h\"\n#include \"inputOutput/logging.h\"\n#include \"config/config.h\"\n#include \"parallel/parallel.h\"\n\n/***** DEFINE **********************************/\n\n#ifndef GROOPS_TAGS\n#define GROOPS_TAGS(tag_, ...) enum Tags {tag_, __VA_ARGS__};\n#endif\n\nnamespace Program\n{\n  constexpr Bool SINGLEPROCESS = TRUE;\n  constexpr Bool PARALLEL      = FALSE;\n\n  /** @brief Tags to desribe programs. Used in @a GROOPS_REGISTER_PROGRAM. */\n  GROOPS_TAGS(NONE,\n              Covariance,\n              DoodsonHarmonics,\n              Gnss,\n              Grace,\n              Gravityfield,\n              Grid,\n              Instrument,\n              KalmanFilter,\n              Matrix,\n              Misc,\n              Noise,\n              NormalEquation,\n              Orbit,\n              Plot,\n              PotentialCoefficients,\n              Preprocessing,\n              Residuals,\n              Simulation,\n              Slr,\n              SpatialTimeSeries,\n              Statistics,\n              System,\n              TimeSeries,\n              TimeSplines,\n              VariationalEquation,\n              /* others */\n              Conversion, Provisional, Deprecated)\n\n  extern const char *tagStrings[];\n} // namespace Program\n\n/***** DEFINE **********************************/\n\n#ifndef DOCSTRING\n#define DOCSTRING \"\" //\"documentation is missing.\\n\"\n// #warning ******** documentation is missing  **********\n#endif\n\n/***** DEFINE **********************************/\n\n/** @brief Register a program in schema and documentation.\n* A list of tags (from @a GROOPS_TAGS) followed the @a _name of the program and the short @a _description.\n* The first tag should agree with the first part of the name/directory.\n* The list should also include tags for the output/input file formats. */\n#define GROOPS_REGISTER_PROGRAM(_name, _parallel, _description, ...) \\\nnamespace Program\\\n{\\\n  class _Program##_name : public Program\\\n  {\\\n  public:\\\n    std::string       name()              const {return #_name;}\\\n    std::string       description()       const {return _description;}\\\n    std::string       documentation()     const {return DOCSTRING;}\\\n    std::vector<Tags> tags()              const {return std::vector<Tags>{__VA_ARGS__};}\\\n    Bool              isSingleProcess()   const {return _parallel;}\\\n    void              run(Config &config, Parallel::CommunicatorPtr comm) const\\\n    {\\\n      ::_name tmp;\\\n      if(!isSingleProcess())\\\n        tmp.run(config, comm);\\\n      else if(::Parallel::isMaster(comm))\\\n        tmp.run(config, ::Parallel::selfCommunicator());\\\n    }\\\n  };\\\n  static _Program##_name program##_name;\\\n}\\\n// end macro\n\n/***** DEFINE **********************************/\n\n/** @brief Register an old name of a renamed program.\n* This macro can be used to keep old config files working. */\n#define GROOPS_RENAMED_PROGRAM(_oldname, _newname, _time) \\\nnamespace Program\\\n{\\\n  class _RenamedProgram##_oldname : public RenamedProgram\\\n  {\\\n  public:\\\n    _RenamedProgram##_oldname(const Renamed &renamed) : RenamedProgram(renamed) {}\\\n  };\\\n  static _RenamedProgram##_oldname renamedprogram##_oldname(RenamedProgram::Renamed(#_oldname, #_newname, _time));\\\n}\\\n// end macro\n\n/***** CLASS ***********************************/\n\nnamespace Program\n{\n\n/** @brief Interface for applications in groops.\n* @ingroup programsGroup\n* An application must implement a @a run(Config &config) function. */\nclass Program\n{\npublic:\n  Program() {programList(this);}\n  virtual ~Program() {}\n\n  virtual std::string       name()              const = 0;\n  virtual std::string       description()       const = 0;\n  virtual std::string       documentation()     const = 0;\n  virtual std::vector<Tags> tags()              const = 0;\n  virtual Bool              isSingleProcess()   const = 0;\n  virtual void              run(Config &config, Parallel::CommunicatorPtr comm) const = 0;\n\n  static std::vector<Program*> programList(Program *program=nullptr);\n  static void sortList(std::vector<Program*> &list);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Interface for renamed applications.\n* @ingroup programsGroup */\nclass RenamedProgram\n{\npublic:\n  class Renamed\n  {\n  public:\n    std::string oldName;\n    std::string newName;\n    Time        time;\n    Renamed(const std::string &oldName_, const std::string &newName_, const Time &time_) : oldName(oldName_), newName(newName_), time(time_) {}\n  };\n\n  RenamedProgram(const Renamed &renamed) {renamedList(renamed);}\n  virtual ~RenamedProgram() {}\n\n  static std::vector<Renamed> renamedList(const Renamed &renamed = Renamed(\"\", \"\", Time()));\n};\n\n} // namespace Program\n\n/***********************************************/\n\n#endif /* __GROOPS__ */\n\n"
  },
  {
    "path": "source/programs/programTemplate.cpp",
    "content": "/***********************************************/\n/**\n* @file programTemplate.cpp\n*\n* @brief Short description.\n*\n* 1. rename class ProgramTemplate\n* 2. give a short description of the program\n* 3. add this file to the sources list (Makefile.source or sourcesCXX.txt)\n*\n* @author Author\n* @author Second author\n* @date yyyy-mm-dd\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nPut documenation here...\n\nReferences to other programs with \\program{Gravityfield2GriddedData}.\n\nDescribe elements with \\config{factor}.\n\nDescription of config elements with links with \\configClass{configElement}{gravityfieldType}\ncontains the name of config element and name of the class.\n\nDescription of file formats: The \\configFile{outputfileEOP}{matrix} is a matrix \\ldots\nor alternatively: The \\config{outputfileEOP} is a \\file{matrix}{matrix}  \\ldots\n(file types: admittance, arcList, doodsonEarthOrientationParameter, doodsonHarmonic, earthOrientationParameter, earthTide,\ngnssAntennaDefinition, gnssIonosphereMaps, gnssReceiverDefinition, gnssSignalBias, platform, gradioAccelerometerCalibration,\ngriddedData, instrument, matrix, meanPolarMotion, normalEquation, oceanPoleTide, parameterName, polygon, potentialCoefficients,\nsatelliteModel, stringList, stringTable, tideGeneratingPotential, timeSplinesCovariance, timeSplinesGravityField, variationalEquation)\n\nDescription with links to subsections:\n\\configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}\nMaybe a label must be added to the subclass docstring.\n\nReferences to other parts of the documentation:\n\\reference{dataVariables}{general.parser:dataVariables}.\n\n%Figures: \\fig{position}{width}{fileName without .png}{label}{caption}\nExample: \\fig{!hb}{0.5}{regionalGeoidTopography}{fig:regionalGeoidTopographyTemplate}{Topography and geoid heights}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Short description.\n* Detailed description.\n* @ingroup programsGroup */\nclass ProgramTemplate\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\n// Give some tags of the program for description.\n// The first tag should agree with the first part of the name/directory.\n// For a full list of tags see program.h (GROOPS_TAGS),\n// Conversion, Provisional, Deprecated\n// Covariance, DoodsonHarmonics, Gnss, Grace, Gravityfield, Grid, Instrument, KalmanFilter, Matrix, Misc,\n// Noise, NormalEquation, Orbit, Plot, PotentialCoefficients, Preprocessing, Residuals, Simulation, SpatialTimeSeries,\n// Statistics, System, TimeSeries, TimeSplines, VariationalEquation\nGROOPS_REGISTER_PROGRAM(ProgramTemplate, PARALLEL/*or SINGLEPROCESS*/, \"short description.\", Provisional/*, further tags, ...*/)\n\n/***********************************************/\n\nvoid ProgramTemplate::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOut;\n    UInt     count;\n\n    readConfig(config, \"outputfile\", fileNameOut, Config::MUSTSET,  \"\", \"description\");\n    readConfig(config, \"count\",      count,       Config::DEFAULT,  \"100\" /* default value */, \"description\");\n    if(isCreateSchema(config)) return;\n\n    // a short function (see c++ lambda functions)\n    auto compute = [](UInt i) {return i*i;};\n\n    // non-parallel loop\n    // -----------------\n    logStatus<<\"starting non parallel loop\"<<Log::endl;\n    std::vector<Double> result(count);\n    Single::forEach(count, [&](UInt i)\n    {\n      result.at(i) = compute(i);\n    });\n\n    // same with paralleization\n    // ------------------------\n    logStatus<<\"starting parallel loop\"<<Log::endl;\n    Parallel::forEach(result, [&](UInt i) {return compute(i);}, comm);\n    // or insertion of code directly as alternative:\n    Parallel::forEach(result, [](UInt i) {return i*i;}, comm);\n    // for functions without return:\n    Parallel::forEach(count, [&](UInt i) {compute(i);}, comm);\n\n    // Write results\n    // -------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"writing output file <\"<<fileNameOut<<\">\"<<Log::endl;\n      writeFileMatrix(fileNameOut, Vector(result));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseAccelerometer.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseAccelerometer.cpp\n*\n* @brief Add noise and bias to accelerometer data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-21\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program adds noise and biases to simulated \\file{accelerometer data}{instrument}\ngenerated by \\program{SimulateAccelerometer}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Add noise and bias to accelerometer data.\n* @ingroup programsGroup */\nclass NoiseAccelerometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseAccelerometer, PARALLEL, \"add noise and bias to accelerometer data\", Simulation, Noise, Instrument)\n\n/***********************************************/\n\nvoid NoiseAccelerometer::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          accelerometerInName, accelerometerOutName;\n    NoiseGeneratorPtr noiseGeneratorAlong, noiseGeneratorCross, noiseGeneratorRadial;\n    Vector3d          bias;\n\n    readConfig(config, \"outputfileAccelerometer\", accelerometerOutName, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileAccelerometer\",  accelerometerInName,  Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"biasAlong\",               bias.x(),             Config::DEFAULT,  \"0\", \"[m/s**2]\");\n    readConfig(config, \"biasCross\",               bias.y(),             Config::DEFAULT,  \"0\", \"[m/s**2]\");\n    readConfig(config, \"biasRadial\",              bias.z(),             Config::DEFAULT,  \"0\", \"[m/s**2]\");\n    readConfig(config, \"noiseAlong\",              noiseGeneratorAlong,  Config::DEFAULT,  \"\",  \"[m/s**2]\");\n    readConfig(config, \"noiseCross\",              noiseGeneratorCross,  Config::DEFAULT,  \"\",  \"[m/s**2]\");\n    readConfig(config, \"noiseRadial\",             noiseGeneratorRadial, Config::DEFAULT,  \"\",  \"[m/s**2]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"add noise to accelerometer data <\"<<accelerometerInName<<\">\"<<Log::endl;\n    InstrumentFile accFile(accelerometerInName);\n    std::vector<Arc> arcList(accFile.arcCount());\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      AccelerometerArc acc = accFile.readArc(arcNo);\n      const Vector eX = noiseGeneratorAlong->noise(acc.size());\n      const Vector eY = noiseGeneratorCross->noise(acc.size());\n      const Vector eZ = noiseGeneratorRadial->noise(acc.size());\n      for(UInt i=0; i<acc.size(); i++)\n        acc.at(i).acceleration += bias + Vector3d(eX(i), eY(i), eZ(i));\n      return acc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write accelerometer data to file <\"<<accelerometerOutName<<\">\"<<Log::endl;\n      InstrumentFile::write(accelerometerOutName, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseGriddedData.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseGriddedData.cpp\n*\n* @brief Add noise to gridded data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2020-03-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program adds noise to \\file{gridded data data}{griddedData}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileGriddedData.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Add noise to gridded data.\n* @ingroup programsGroup */\nclass NoiseGriddedData\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseGriddedData, SINGLEPROCESS, \"add noise to gridded data\", Simulation, Noise, Grid)\n\n/***********************************************/\n\nvoid NoiseGriddedData::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          fileNameOut, fileNameIn;\n    NoiseGeneratorPtr noiseGenerator;\n    UInt              startData, countData = MAX_UINT;\n\n    readConfig(config, \"outputfileGriddedData\", fileNameOut,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileGriddedData\",  fileNameIn,     Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"noise\",                 noiseGenerator, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startDataFields\",       startData,      Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\",       countData,      Config::OPTIONAL, \"\",  \"number of data fields (default: all after start)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"add noise to data <\"<<fileNameIn<<\">\"<<Log::endl;\n    GriddedData grid;\n    readFileGriddedData(fileNameIn, grid);\n    for(UInt i=startData; i<std::min(grid.values.size(), startData+countData); i++)\n    {\n      const Vector e = noiseGenerator->noise(grid.points.size(), 1);\n      for(UInt k=0; k<grid.points.size(); k++)\n        grid.values.at(i).at(k) += e(k);\n    }\n\n    logStatus<<\"write gridded data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n    writeFileGriddedData(fileNameOut, grid);\n    MiscGriddedData::printStatistics(grid);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseInstrument.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseInstrument.cpp\n*\n* @brief Add noise to instrument data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2017-09-02\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program adds noise to \\file{instrument data}{instrument}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Add noise to instrument data.\n* @ingroup programsGroup */\nclass NoiseInstrument\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseInstrument, PARALLEL, \"add noise to instrument data\", Simulation, Noise, Instrument)\n\n/***********************************************/\n\nvoid NoiseInstrument::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          fileNameOut, fileNameIn;\n    NoiseGeneratorPtr noiseGenerator;\n    UInt              startData, countData = MAX_UINT;\n\n    readConfig(config, \"outputfileInstrument\", fileNameOut,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"inputfileInstrument\",  fileNameIn,     Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"noise\",                noiseGenerator, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"startDataFields\",      startData,      Config::DEFAULT,  \"0\", \"start\");\n    readConfig(config, \"countDataFields\",      countData,      Config::OPTIONAL, \"\",  \"number of data fields (default: all after start)\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"add noise to data <\"<<fileNameIn<<\">\"<<Log::endl;\n    InstrumentFile instrumentFile(fileNameIn);\n\n    std::vector<Arc> arcList(instrumentFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      Arc    arc  = instrumentFile.readArc(arcNo);\n      Matrix data = arc.matrix();\n      countData   = std::min(countData, data.columns()-1-startData);\n      data.column(1+startData, countData) += noiseGenerator->noise(data.rows(), countData);\n      return Arc(arc.times(), data, arc.getType());\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write instrument data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseNormalsSolution.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseNormalsSolution.cpp\n*\n* @brief Create correlated errors from normal equations.\n*\n* @author Andreas Kvas\n* @date 2017-06-27\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThe inverse of the normal matrix of \\configFile{inputfileNormalEquation}{normalEquation}\nrepresents the covariance matrix of the estimated parameters. This program generates a noise vector with\n\\begin{equation}\n\\M\\Sigma(\\M e) = \\M N^{-1},\n\\end{equation}\nif generated input noise is standard white noise.\n\nThe noise vector is computed with\n\\begin{equation}\n\\M e = \\M W^{-T} \\M z,\n\\end{equation}\nwhere $\\M z$ is the generated \\configClass{noise}{noiseGeneratorType} and\n$\\M W$ is the cholesky upper triangle matrix of the normal matrix $\\M N=\\M W^T\\M W$.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** * @brief Create a correlated error vector from a system of normal equations.\n* @ingroup programsGroup */\nclass NoiseNormalsSolution\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseNormalsSolution, PARALLEL, \"Create a correlated error vector from a system of normal equations.\", Simulation, Noise, NormalEquation)\nGROOPS_RENAMED_PROGRAM(NormalsSimulateNoise, NoiseNormalsSolution, date2time(2020, 7, 20))\n\n/***********************************************/\n\nvoid NoiseNormalsSolution::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          outName, normalsName;\n    NoiseGeneratorPtr noise;\n    UInt              sampleCount;\n    Bool              useEVD;\n\n    renameDeprecatedConfig(config, \"inputfileNormalequation\",  \"inputfileNormalEquation\",  date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileNoise\",         outName,     Config::MUSTSET,  \"\",  \"generated noise as matrix: parameterCount x sampleCount\");\n    readConfig(config, \"inputfileNormalEquation\", normalsName, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"noise\",                   noise,       Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"sampleCount\",             sampleCount, Config::DEFAULT,  \"1\", \"number of samples to be generated\");\n    readConfig(config, \"useEigenvalueDecomposition\", useEVD,   Config::DEFAULT,  \"0\", \"use eigenvalue decomposition\");\n    if(isCreateSchema(config)) return;\n\n    if(useEVD)\n    {\n      if(!Parallel::isMaster(comm))\n        return;\n\n      Matrix N;\n      Matrix n;\n      NormalEquationInfo info;\n      readFileNormalEquation(normalsName, info, N, n);\n      logInfo<<\"  number of parameters: \"<<N.rows()<<Log::endl;\n\n      Matrix rhs = noise->noise(n.rows(), sampleCount);\n\n      Vector eig = eigenValueDecomposition(N);\n      const Double maxE = maxabs(eig);\n\n      Matrix y = N*rhs;\n      for(UInt k = 0; k<y.rows(); k++)\n      {\n        Double factor = (eig(k)<(maxE*1e-13)) ? 0.0 : 1.0/std::sqrt(eig(k));\n        y.row(k)*=factor;\n      }\n      Matrix out = N.trans()*y;\n\n      logStatus<<\"write noise vectors to file <\"<<outName<<\">\"<<Log::endl;\n      writeFileMatrix(outName, out);\n      return;\n    }\n\n    // read normal equations\n    // ---------------------\n    logStatus<<\"read normal equations <\"<<normalsName<<\">\"<<Log::endl;\n    MatrixDistributed normal;\n    Matrix n;\n    NormalEquationInfo info;\n    readFileNormalEquation(normalsName, info, normal, n, comm);\n    logInfo<<\"  number of parameters: \"<<normal.parameterCount()<<Log::endl;\n\n    Matrix rhs = noise->noise(n.rows(), sampleCount);\n\n    // compute cholesky\n    // ----------------\n    logStatus<<\"compute cholesky decomposition\"<<Log::endl;\n    normal.cholesky(TRUE/*timing*/); // N = W^T W\n    normal.triangularSolve(rhs);     // W^-1 e\n\n    // save to file\n    // ------------\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write noise vectors to file <\"<<outName<<\">\"<<Log::endl;\n      writeFileMatrix(outName, rhs);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseOrbit.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseOrbit.cpp\n*\n* @brief Add white or colored noise to orbits positions and velocities.\n*\n* @author Torsten Mayer-Guerr\n* @author Matthias Ellmer\n* @date 2003-01-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program adds noise to simulated \\file{satellite}{instrument}'s positions\nand velocities generated by \\program{SimulateOrbit} (along, cross, radial).\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise options.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Add noise to orbit positions and velocities.\n* @ingroup programsGroup */\nclass NoiseOrbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseOrbit, PARALLEL, \"add noise to orbit positions and velocities\", Simulation, Noise, Instrument)\n\n/***********************************************/\n\nvoid NoiseOrbit::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          inName, outName;\n    NoiseGeneratorPtr noiseGeneratorPosition, noiseGeneratorVelocity;\n\n    readConfig(config, \"outputfileOrbit\", outName,                Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",  inName,                 Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"noisePosition\",   noiseGeneratorPosition, Config::DEFAULT,  \"\", \"along, cross, radial [m]\");\n    readConfig(config, \"noiseVelocity\",   noiseGeneratorVelocity, Config::DEFAULT,  \"\", \"along, cross, radial [m/s]\");\n    if(isCreateSchema(config)) return;\n\n    // Read satellite\n    // -----------------\n    logStatus<<\"add noise to orbit data <\"<<inName<<\">\"<<Log::endl;\n    InstrumentFile  orbitFile(inName);\n    std::vector<Arc> arcList(orbitFile.arcCount());\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc orbit  = orbitFile.readArc(arcNo);\n      Matrix   epsPos = noiseGeneratorPosition->noise(orbit.size(), 3);\n      Matrix   epsVel = noiseGeneratorVelocity->noise(orbit.size(), 3);\n\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        // rotate into satellite system\n        // ----------------------------\n        Rotary3d rot;\n        if(orbit.size()>1)\n        {\n          Vector3d x;\n          if(i==0)\n            x = orbit.at(i+1).position - orbit.at(i).position;\n          else\n            x = orbit.at(i).position - orbit.at(i-1).position;\n          Vector3d z = normalize(orbit.at(i).position);\n          Vector3d y = normalize(crossProduct(z, x));\n          x = crossProduct(y, z);\n          rot = Rotary3d(x,y);\n        }\n\n        orbit.at(i).position += rot.rotate(Vector3d(epsPos(i,0), epsPos(i,1), epsPos(i,2)));\n        orbit.at(i).velocity += rot.rotate(Vector3d(epsVel(i,0), epsVel(i,1), epsVel(i,2)));\n      }\n      return orbit;\n    }, comm);\n\n    // Save\n    // ----\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write orbit data to file <\"<<outName<<\">\"<<Log::endl;\n      InstrumentFile::write(outName, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseSatelliteTracking.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseSatelliteTracking.cpp\n*\n* @brief Apply GRACE differential filter to white noise and add the result to satellite tracking data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2003-01-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program adds noise to simulated satellite tracking data generated by \\program{SimulateSatelliteTracking}.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise generation.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Apply GRACE differential filter to white noise and add the result to satellite tracking data.\n* @ingroup programsGroup */\nclass NoiseSatelliteTracking\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseSatelliteTracking, PARALLEL, \"generate noise and add the result to satellite tracking data\", Simulation, Noise, Instrument)\n\n/***********************************************/\n\nvoid NoiseSatelliteTracking::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName          inName, outName;\n    NoiseGeneratorPtr noiseRange, noiseRate, noiseAcc;\n\n    readConfig(config, \"outputfileSatelliteTracking\", outName,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileSatelliteTracking\",  inName,     Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"noiseRange\",                  noiseRange, Config::DEFAULT,  \"\", \"[m]\");\n    readConfig(config, \"noiseRangeRate\",              noiseRate,  Config::DEFAULT,  \"\", \"[m/s]\");\n    readConfig(config, \"noiseRangeAcceleration\",      noiseAcc,   Config::DEFAULT,  \"\", \"[m/s^2]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"add noise to tracking data\"<<Log::endl;\n    InstrumentFile sstFile(inName);\n    std::vector<Arc> arcList(sstFile.arcCount());\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      SatelliteTrackingArc sst = sstFile.readArc(arcNo);\n      Matrix data = sst.matrix();\n      data.column(1) += noiseRange->noise(data.rows());\n      data.column(2) += noiseRate->noise(data.rows());\n      data.column(3) += noiseAcc->noise(data.rows());\n      return Arc(sst.times(), data, sst.getType());\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write tracking data to file <\"<<outName<<\">\"<<Log::endl;\n      InstrumentFile::write(outName, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseStarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseStarCamera.cpp\n*\n* @brief Add noise to star camera observations.\n*\n* @author Torsten Mayer-Guerr\n* @author Matthias Ellmer\n* @date 2011-05-24\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program adds noise to rotation observations. The noise is computed via a pseudo random sequence.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise options.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Add white noise to quaternion observations.\n  * @ingroup programsGroup */\nclass NoiseStarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseStarCamera, PARALLEL, \"add noise to rotation observations\", Simulation, Noise, Instrument)\n\n/***********************************************/\n\nvoid NoiseStarCamera::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName inName, outName,  outNameCovariance;\n    NoiseGeneratorPtr noiseRoll, noisePitch, noiseYaw;\n\n    readConfig(config, \"outputfileStarCamera\", outName,    Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"inputfileStarCamera\",  inName,     Config::MUSTSET, \"\", \"\");\n    readConfig(config, \"noiseRoll\",            noiseRoll,  Config::MUSTSET, \"\", \"[rad]\");\n    readConfig(config, \"noisePitch\",           noisePitch, Config::MUSTSET, \"\", \"[rad]\");\n    readConfig(config, \"noiseYaw\",             noiseYaw,   Config::MUSTSET, \"\", \"[rad]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"add noise to star Camera data\"<<Log::endl;\n    InstrumentFile scaFile(inName);\n    UInt arcCount = scaFile.arcCount();\n    std::vector<Arc> arcList(arcCount);\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      StarCameraArc scaArc = scaFile.readArc(arcNo);\n\n      const UInt   posCount = scaArc.size();\n      const Vector eRoll    = noiseRoll->noise(posCount);\n      const Vector ePitch   = noisePitch->noise(posCount);\n      const Vector eYaw     = noiseYaw->noise(posCount);\n\n      StarCameraArc arc;\n      for(UInt i=0; i<posCount; i++)\n      {\n        Angle roll, pitch, yaw;\n        scaArc.at(i).rotary.cardan(roll, pitch, yaw);\n\n        Angle nRoll  = Angle(roll  + eRoll(i));\n        Angle nPitch = Angle(pitch + ePitch(i));\n        Angle nYaw   = Angle(yaw   + eYaw(i));\n\n        StarCameraEpoch epoch;\n        epoch.time   = scaArc.at(i).time;\n        epoch.rotary = rotaryZ(nYaw) * rotaryY(nPitch) * rotaryX(nRoll);\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm); // forEach\n\n    logStatus<<\"write star camera data to file <\"<<outName<<\">\"<<Log::endl;\n    if(Parallel::isMaster(comm))\n      InstrumentFile::write(outName, arcList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/noiseTimeSeries.cpp",
    "content": "/***********************************************/\n/**\n* @file noiseTimeSeries.cpp\n*\n* @brief Generate one or more time series of noise.\n*\n* @author Matthias Ellmer\n* @date 2015-11-03\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program generates \\configFile{outputfileNoise}{instrument} with the requested characteristics.\nSee \\configClass{noiseGenerator}{noiseGeneratorType} for details on noise options.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Generate one or more time series of noise.\n* @ingroup programsGroup */\nclass NoiseTimeSeries\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(NoiseTimeSeries, SINGLEPROCESS, \"generate random noise\", Simulation, Noise, TimeSeries)\n\n/***********************************************/\n\nvoid NoiseTimeSeries::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName          outNameNoise, outNameCovariance;\n    NoiseGeneratorPtr noiseGenerator;\n    TimeSeriesPtr     timeSeries;\n    UInt              series;\n\n    readConfig(config, \"outputfileNoise\",              outNameNoise,      Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"outputfileCovarianceFunction\", outNameCovariance, Config::OPTIONAL, \"\",  \"\");\n    readConfig(config, \"noise\",                        noiseGenerator,    Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"timeSeries\",                   timeSeries,        Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"columns\",                      series,            Config::MUSTSET,  \"1\", \"number of noise series (columns)\");\n    if(isCreateSchema(config)) return;\n\n    // Set up time series\n    std::vector<Time> times = timeSeries->times();\n\n    logStatus<<\"generating noise\"<<Log::endl;\n    Matrix noise(times.size(), 1+series);\n    copy(noiseGenerator->noise(noise.rows(), series), noise.column(1, series));\n\n    logStatus<<\"writing noise to file <\"<< outNameNoise <<\">\"<<Log::endl;\n    InstrumentFile::write(outNameNoise, Arc(times, noise));\n\n    if(!outNameCovariance.empty())\n    {\n      logStatus<<\"writing covariance function to file <\"<< outNameCovariance <<\">\"<<Log::endl;\n      writeFileMatrix(outNameCovariance, noiseGenerator->covarianceFunction(times.size(), medianSampling(times).seconds()));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateAccelerometer.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateAccelerometer.cpp\n*\n* @brief simulate accelerometer data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-21\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulate \\file{accelerometer data}{instrument}. The orientation of the accelerometer\nis given by \\configFile{inputfileStarCamera}{instrument} otherwise the celestial reference frame (CRF) is used.\nFor computation of non-conservative forces a \\configFile{satelliteModel}{satelliteModel} is needed.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/forces/forces.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simulate accelerometer data.\n* @ingroup programsGroup */\nclass SimulateAccelerometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateAccelerometer, PARALLEL, \"simulate accelerometer data\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateAccelerometer::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName             fileNameAccelerometer;\n    FileName             fileNameSatellite;\n    FileName             orbitName, starCameraName;\n    EarthRotationPtr     earthRotation;\n    EphemeridesPtr       ephemerides;\n    ForcesPtr            forces;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\", date2time(2020, 8, 19));\n\n    readConfig(config, \"outputfileAccelerometer\", fileNameAccelerometer, Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileSatelliteModel\", fileNameSatellite,     Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"inputfileOrbit\",          orbitName,             Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"inputfileStarCamera\",     starCameraName,        Config::OPTIONAL, \"\",    \"\");\n    readConfig(config, \"earthRotation\",           earthRotation,         Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",             ephemerides,           Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"forces\",                  forces,                Config::MUSTSET,  \"\",    \"\");\n    if(isCreateSchema(config)) return;\n\n    InstrumentFile orbitFile(orbitName);\n    InstrumentFile starCameraFile(starCameraName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n\n    SatelliteModelPtr satellite;\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    logStatus<<\"computing accelerations\"<<Log::endl;\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc      orbit      = orbitFile.readArc(arcNo);\n      StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n      Arc::checkSynchronized({orbit, starCamera});\n\n      AccelerometerArc accelerometer;\n      for(UInt k=0; k<orbit.size(); k++)\n      {\n        Rotary3d rotSat;\n        if(starCamera.size())\n          rotSat = starCamera.at(k).rotary;\n        const Time     time     = orbit.at(k).time;\n        const Rotary3d rotEarth = earthRotation->rotaryMatrix(time);\n        const Vector3d acc      = forces->acceleration(satellite, time, orbit.at(k).position, orbit.at(k).velocity, rotSat, rotEarth, earthRotation, ephemerides);\n\n        AccelerometerEpoch epoch;\n        epoch.time         = time;\n        epoch.acceleration = rotSat.inverseRotate(rotEarth.inverseRotate(acc));\n        accelerometer.push_back(epoch);\n      }\n      return accelerometer;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write accelerometer data to file <\"<<fileNameAccelerometer<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameAccelerometer, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateAccelerometerCoMOffset.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateAccelerometerCoMOffset.cpp\n*\n* @brief Create accelerations due to CoM offset.\n*\n* @author Beate Klinger\n* @date 2016-05-12\n*\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program generates an \\file{accelerometer file}{instrument} containing perturbing accelerations\ndue to a given center of mass (CoM) offset. This includes centrifugal effects,\nEuler forces and the effect of gravity gradients.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/polynomial.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create accelerations due to CoM offset.\n* @ingroup programsGroup */\nclass SimulateAccelerometerCoMOffset\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateAccelerometerCoMOffset, PARALLEL, \"Create accelerations due to CoM offset.\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateAccelerometerCoMOffset::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameOut;\n    FileName         fileNameOrbit, fileNameStarCamera;\n    Bool             applyAngularRate, applyAngularAcc;\n    GravityfieldPtr  gradientfield;\n    EarthRotationPtr earthRotation;\n    UInt             derivationDegree;\n    Vector           offset(3);\n\n    readConfig(config, \"outputfileAccelerometer\",   fileNameOut,        Config::MUSTSET,  \"\", \"effect of offset\");\n    readConfig(config, \"inputfileOrbit\",            fileNameOrbit,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera\",       fileNameStarCamera, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"applyAngularRate\",          applyAngularRate,   Config::DEFAULT,  \"1\", \"compute effect of centrifugal forces\");\n    readConfig(config, \"applyAngularAccelerations\", applyAngularAcc,    Config::DEFAULT,  \"1\", \"compute effect of Euler forces\");\n    readConfig(config, \"gradientfield\",             gradientfield,      Config::DEFAULT,  \"\", \"low order field to estimate the change of the gravity by position adjustement\");\n    readConfig(config, \"earthRotation\",             earthRotation,      Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"interpolationDegree\",       derivationDegree,   Config::DEFAULT,  \"2\", \"derivation of quaternions by polynomial interpolation of degree n\");\n    readConfig(config, \"CoMOffsetX\",                offset(0),          Config::MUSTSET,  \"50e-6\", \"offset [m]\");\n    readConfig(config, \"CoMOffsetY\",                offset(1),          Config::MUSTSET,  \"50e-6\", \"offset [m]\");\n    readConfig(config, \"CoMOffsetZ\",                offset(2),          Config::MUSTSET,  \"50e-6\", \"offset [m]\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"compute accelerations (CoM)\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    InstrumentFile starCameraFile(fileNameStarCamera);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n    std::vector<Arc> arcList(orbitFile.arcCount());\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc         orbit      = orbitFile.readArc(arcNo);\n      StarCameraArc    starCamera = starCameraFile.readArc(arcNo);\n      Arc::checkSynchronized({orbit, starCamera});\n\n      // quaternions\n      const std::vector<Time> times = orbit.times();\n      Polynomial polynomial(times, derivationDegree);\n      Matrix q   = starCamera.matrix().column(1,4);\n      Matrix dq  = polynomial.derivative(times, q);\n      Matrix ddq = polynomial.derivative2nd(times, q);\n\n      AccelerometerArc accelerometerArc;\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        // Gravity gradient in satellite system (SRF)\n        Rotary3d rotEarth = earthRotation->rotaryMatrix(orbit.at(i).time);\n        Tensor3d T = gradientfield->gravityGradient(orbit.at(i).time, rotEarth.rotate(orbit.at(i).position));\n        T = starCamera.at(i).rotary.inverseRotate(rotEarth.inverseRotate(T));\n\n        // angular rates/accelerations\n        Vector w(3), wd(3);\n        Matrix Q(3, 4);\n        Q(0,0) = -q(i,1);  Q(0,1) = +q(i,0);  Q(0,2) = +q(i,3);  Q(0,3) = -q(i,2);\n        Q(1,1) = -q(i,2);  Q(1,1) = -q(i,3);  Q(1,2) = +q(i,0);  Q(1,3) = +q(i,1);\n        Q(2,2) = -q(i,3);  Q(2,1) = +q(i,2);  Q(2,2) = -q(i,1);  Q(2,3) = +q(i,0);\n        if(applyAngularRate)\n          w = 2*Q *  dq.row(i).trans();\n        if(applyAngularAcc)\n          wd = 2*Q * ddq.row(i).trans(); // angular accelerations\n\n        // Center of mass offset\n        Matrix M = -T.matrix();\n        M(0,0) += -w(1)*w(1)-w(2)*w(2); M(0,1) +=  w(0)*w(1)-wd(2);     M(0,2) +=  w(0)*w(2)+wd(1);\n        M(1,0) +=  w(0)*w(1)+wd(2);     M(1,1) += -w(0)*w(0)-w(2)*w(2); M(1,2) +=  w(1)*w(2)-wd(0);\n        M(2,0) +=  w(0)*w(2)-wd(1);     M(2,1) +=  w(1)*w(2)+wd(0);     M(2,2) += -w(0)*w(0)-w(1)*w(1);\n        Vector a = M * offset;\n\n        AccelerometerEpoch epoch;\n        epoch.time = orbit.at(i).time;\n        epoch.acceleration.x() = a(0);\n        epoch.acceleration.y() = a(1);\n        epoch.acceleration.z() = a(2);\n        accelerometerArc.push_back(epoch);\n      }\n      return accelerometerArc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write data to file <\"<<fileNameOut<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameOut, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateGradiometer.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateGradiometer.cpp\n*\n* @brief Simulate error free gradiometer data.\n*\n* @author Torsten Mayer-Guerr\n* @date 2008-08-15\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates error free \\file{gradiometer data}{instrument} along a satellite's orbit.\nThe orientation of the full tensor gradiometer is given by \\configFile{inputfileStarCamera}{instrument}\notherwise the celestial reference frame (CRF) is used.\nThe gravity gradients are given by \\configClass{gravityfield}{gravityfieldType} and\n\\configClass{tides}{tidesType}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n\n/***********************************************/\n\n/** @brief Simulate error free gradiometer data.\n* @ingroup programsGroup */\nclass SimulateGradiometer\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateGradiometer, PARALLEL, \"simulate error free gradiometer data\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateGradiometer::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName         fileNameGradiometer;\n    FileName         orbitName, starCameraName;\n    EarthRotationPtr earthRotation;\n    EphemeridesPtr   ephemerides;\n    GravityfieldPtr  gravityfield;\n    TidesPtr         tides;\n\n    readConfig(config, \"outputfileGradiometer\", fileNameGradiometer, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",        orbitName,           Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileStarCamera\",   starCameraName,      Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"earthRotation\",         earthRotation,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"ephemerides\",           ephemerides,         Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"gravityfield\",          gravityfield,        Config::DEFAULT,  \"\", \"\");\n    readConfig(config, \"tides\",                 tides,               Config::DEFAULT,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // open and test instrument files\n    // ------------------------------\n    InstrumentFile orbitFile(orbitName);\n    InstrumentFile starCameraFile(starCameraName);\n    InstrumentFile::checkArcCount({orbitFile, starCameraFile});\n\n    logStatus<<\"computing gravity field\"<<Log::endl;\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc      orbit      = orbitFile.readArc(arcNo);\n      StarCameraArc starCamera = starCameraFile.readArc(arcNo);\n      Arc::checkSynchronized({orbit, starCamera});\n\n      GradiometerArc gradiometer;\n      for(UInt k=0; k<orbit.size(); k++)\n      {\n        Rotary3d rotSat;\n        if(starCamera.size())\n          rotSat = starCamera.at(k).rotary;\n        const Time     time     = orbit.at(k).time;\n        const Rotary3d rotEarth = earthRotation->rotaryMatrix(time);\n        const Vector3d posEarth = rotEarth.rotate(orbit.at(k).position);\n        const Tensor3d tns      = gravityfield->gravityGradient(time, posEarth)\n                                + tides->gradient(time, posEarth, rotEarth, earthRotation, ephemerides);\n\n        GradiometerEpoch epoch;\n        epoch.time            = time;\n        epoch.gravityGradient = rotSat.inverseRotate(rotEarth.inverseRotate(tns));\n        gradiometer.push_back(epoch);\n      }\n      return gradiometer;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write gradiometer file <\"<<fileNameGradiometer<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameGradiometer, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateKeplerOrbit.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateKeplerOrbit.cpp\n*\n* @brief Compute Keplerian orbit.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-10-31\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates a Keplerian \\file{orbit}{instrument} at a given \\config{timeSeries}\nstarting from the given \\config{integrationConstants}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/kepler.h\"\n#include \"base/equinoctial.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Compute Keplerian orbit.\n* @ingroup programsGroup */\nclass SimulateKeplerOrbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateKeplerOrbit, SINGLEPROCESS, \"compute Keplerian orbit\", Simulation, Orbit, Instrument)\n\n/***********************************************/\n\nvoid SimulateKeplerOrbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName      outName;\n    Double        GM;\n    TimeSeriesPtr timeSeries;\n    Vector3d      position, velocity;\n    std::string   choice;\n    Time          time0;\n\n    readConfig(config, \"outputfileOrbit\", outName,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"timeSeries\",      timeSeries,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"GM\",              GM,            Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n    readConfigChoice(config, \"integrationConstants\", choice, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoiceElement(config, \"kepler\", choice, \"\"))\n    {\n      Double a, e;\n      Angle  i, Omega, omega, M;\n      readConfig(config, \"majorAxis\",         a,     Config::MUSTSET, \"\", \"[m]\");\n      readConfig(config, \"eccentricity\",      e,     Config::MUSTSET, \"\", \"[-]\");\n      readConfig(config, \"inclination\",       i,     Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"ascendingNode\",     Omega, Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"argumentOfPerigee\", omega, Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"meanAnomaly\",       M,     Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"time\",              time0, Config::MUSTSET, \"\", \"integration constants are valid at this epoch\");\n      if(!isCreateSchema(config))\n      {\n        Kepler kepler(time0, Omega, i, omega, a, e, M, GM);\n        kepler.orbit(time0, position, velocity);\n      }\n    }\n    if(readConfigChoiceElement(config, \"positionAndVelocity\", choice, \"\"))\n    {\n      readConfig(config, \"position0x\", position.x(), Config::MUSTSET, \"\", \"[m] in CRF\");\n      readConfig(config, \"position0y\", position.y(), Config::MUSTSET, \"\", \"[m] in CRF\");\n      readConfig(config, \"position0z\", position.z(), Config::MUSTSET, \"\", \"[m] in CRF\");\n      readConfig(config, \"velocity0x\", velocity.x(), Config::MUSTSET, \"\", \"[m/s]\");\n      readConfig(config, \"velocity0y\", velocity.y(), Config::MUSTSET, \"\", \"[m/s]\");\n      readConfig(config, \"velocity0z\", velocity.z(), Config::MUSTSET, \"\", \"[m/s]\");\n      readConfig(config, \"time\",       time0,        Config::MUSTSET, \"\", \"integration constants are valid at this epoch\");\n    }\n    endChoice(config);\n    if(isCreateSchema(config)) return;\n\n    std::vector<Time> times = timeSeries->times();\n    Equinoctial kepler(time0, position, velocity, GM);\n\n    // Info\n    // ----\n    Kepler k(kepler);\n    logInfo<<\"Kepler elements\"<<Log::endl;\n    logInfo<<\"  majorAxis a    : \"<<k.a/1000<<\" km\"<<Log::endl;\n    logInfo<<\"  eccentricity e : \"<<k.e<<Log::endl;\n    logInfo<<\"  inclination i  : \"<<k.i*RAD2DEG<<\" Degree\"<<Log::endl;\n    logInfo<<\"  ascending node : \"<<k.Omega*RAD2DEG<<\" Degree\"<<Log::endl;\n    logInfo<<\"  perigee        : \"<<k.omega*RAD2DEG<<\" Degree\"<<Log::endl;\n\n    // Computation\n    // -----------\n    logStatus<<\"computing\"<<Log::endl;\n    OrbitArc orbit;\n    Single::forEach(times.size(), [&](UInt i)\n    {\n      OrbitEpoch epoch;\n      epoch.time = times.at(i);\n      kepler.orbit(times.at(i), epoch.position, epoch.velocity, epoch.acceleration);\n      orbit.push_back(epoch);\n    });\n\n    // write results\n    // -------------\n    logStatus<<\"write orbit data to file <\"<<outName<<\">\"<<Log::endl;\n    InstrumentFile::write(outName, orbit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateOrbit.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateOrbit.cpp\n*\n* @brief Pure dynamical orbit integration.\n*\n* @author Matthias Ellmer\n* @date 2004-09-12\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program integrates an \\file{orbit}{instrument} from a given force function (dynamic orbit).\nThe force functions are given by \\configClass{forces}{forcesType}.\nFor computation of non-conservative forces a \\file{satelliteModel}{satelliteModel} is needed.\nThe integration method must be selected with \\configClass{propagator}{orbitPropagatorType}.\nBecause the orbit data are calculated in the celestial reference frame (CRF) you need\n\\configClass{earthRotation}{earthRotationType} to transform the force function\nfrom the terrestrial reference frame (TRF).\nThe integration start and end time, as well as the sampling, are derived from\nthe \\config{timeSeries} option. It is possible to integrate the arc in \\config{reverse},\nwhere the initial conditions are assumed to be met at the end time of the \\config{timeSeries}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/kepler.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/forces/forces.h\"\n#include \"classes/orbitPropagator/orbitPropagator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Pure dynamical orbit integration.\n * @ingroup programsGroup */\nclass SimulateOrbit\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateOrbit, SINGLEPROCESS, \"pure dynamical orbit integration\", Simulation, Orbit, Instrument)\n\n/***********************************************/\n\nvoid SimulateOrbit::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName             fileNameOrbit;\n    FileName             fileNameSatellite;\n    FileName             fileNameStart;\n    TimeSeriesPtr        timeSeries;\n    OrbitPropagatorPtr   orbitPropagator;\n    OrbitEpoch           startEpoch;\n    EarthRotationPtr     earthRotation;\n    EphemeridesPtr       ephemerides;\n    ForcesPtr            forces;\n    Bool                 reverse;\n    Double               margin;\n\n    renameDeprecatedConfig(config, \"satelliteModel\", \"inputfileSatelliteModel\", date2time(2020, 8, 19));\n\n    readConfig(config, \"outputfileOrbit\",         fileNameOrbit,     Config::MUSTSET,   \"\",   \"orbit file to be written.\");\n    readConfig(config, \"inputfileSatelliteModel\", fileNameSatellite, Config::OPTIONAL, \"{groopsDataDir}/satelliteModel/\", \"satellite macro model\");\n    readConfig(config, \"timeSeries\",              timeSeries,        Config::MUSTSET,   \"\",   \"time points for simulated orbit epochs.\");\n\n    std::string choice;\n    readConfigChoice(config, \"integrationConstants\", choice, Config::MUSTSET, \"\", \"\");\n    if(readConfigChoiceElement(config, \"kepler\", choice, \"\"))\n    {\n      Double GM, a, e;\n      Angle  i, Omega, omega, M;\n      readConfig(config, \"majorAxis\",         a,     Config::MUSTSET, \"\", \"[m]\");\n      readConfig(config, \"eccentricity\",      e,     Config::MUSTSET, \"\", \"[-]\");\n      readConfig(config, \"inclination\",       i,     Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"ascendingNode\",     Omega, Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"argumentOfPerigee\", omega, Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"meanAnomaly\",       M,     Config::MUSTSET, \"\", \"[degree]\");\n      readConfig(config, \"GM\",                GM,    Config::DEFAULT,  STRING_DEFAULT_GM, \"Geocentric gravitational constant\");\n      if(!isCreateSchema(config))\n      {\n        Kepler kepler(Time(), Omega, i, omega, a, e, M, GM);\n        kepler.orbit(Time(), startEpoch.position, startEpoch.velocity);\n      }\n    }\n    if(readConfigChoiceElement(config, \"positionAndVelocity\", choice, \"\"))\n    {\n      readConfig(config, \"position0x\", startEpoch.position.x(), Config::MUSTSET, \"\", \"[m] in CRF\");\n      readConfig(config, \"position0y\", startEpoch.position.y(), Config::MUSTSET, \"\", \"[m] in CRF\");\n      readConfig(config, \"position0z\", startEpoch.position.z(), Config::MUSTSET, \"\", \"[m] in CRF\");\n      readConfig(config, \"velocity0x\", startEpoch.velocity.x(), Config::MUSTSET, \"\", \"[m/s]\");\n      readConfig(config, \"velocity0y\", startEpoch.velocity.y(), Config::MUSTSET, \"\", \"[m/s]\");\n      readConfig(config, \"velocity0z\", startEpoch.velocity.z(), Config::MUSTSET, \"\", \"[m/s]\");\n    }\n    if(readConfigChoiceElement(config, \"file\", choice, \"\"))\n    {\n      readConfig(config, \"inputfileOrbit\", fileNameStart, Config::MUSTSET,  \"\",     \"only epoch at timeStart is used\");\n      readConfig(config, \"margin\",         margin,        Config::DEFAULT,  \"1e-5\", \"[seconds] used when finding initial epoch in orbitFile\");\n    }\n    endChoice(config);\n\n    readConfig(config, \"propagator\",     orbitPropagator,   Config::MUSTSET,  \"polynomial\", \"orbit propagation method.\");\n    readConfig(config, \"earthRotation\",  earthRotation,     Config::MUSTSET,  \"\",    \"\");\n    readConfig(config, \"ephemerides\",    ephemerides,       Config::OPTIONAL, \"jpl\", \"\");\n    readConfig(config, \"forces\",         forces,            Config::MUSTSET,  \"\",    \"considered in orbit propagation.\");\n    readConfig(config, \"reverse\",        reverse,           Config::DEFAULT,  \"0\",   \"start integration at last epoch in timeSeries, going backward in time.\");\n    if(isCreateSchema(config)) return;\n\n    // Setup\n    // -----\n    SatelliteModelPtr satellite;\n    if(!fileNameSatellite.empty())\n      readFileSatelliteModel(fileNameSatellite, satellite);\n\n    std::vector<Time> times = timeSeries->times();\n    Time timeStart = times.front();\n    Time sampling  = 1./(times.size()-1) * (times.back()-times.front());\n    if(!isRegular(times))\n      throw(Exception(\"Time intervals must be regularly spaced.\"));\n\n    // Need to flip?\n    if(reverse)\n    {\n      timeStart = times.back();\n      sampling  = -sampling;\n    }\n\n    // read startEpoch from file\n    // -------------------------\n    if(!fileNameStart.empty())\n    {\n      OrbitArc orbit = InstrumentFile::read(fileNameStart);\n      for(UInt i=0; i<orbit.size(); i++)\n        if(std::fabs((orbit.at(i).time-timeStart).seconds())<margin)\n          startEpoch = orbit.at(i);\n      if(std::fabs((startEpoch.time-timeStart).seconds())>margin)\n        throw (Exception(\"Requested start time \"+timeStart.dateTimeStr()+\" not present in file <\"+fileNameStart.str()+\">\"));\n    }\n\n    // Integrate\n    // ---------\n    logStatus<<\"integrating orbit\"<<Log::endl;\n    startEpoch.time = timeStart;\n    OrbitArc orbit = orbitPropagator->integrateArc(startEpoch, sampling, times.size(), forces, satellite, earthRotation, ephemerides);\n    if(reverse)\n      orbit = OrbitPropagator::flip(orbit);\n\n    // Save\n    // ----\n    logStatus<<\"write orbit data to file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameOrbit, orbit);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateSatelliteTracking.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateSatelliteTracking.cpp\n*\n* @brief Simulate tracking data (range, range-rate, range-accelerations) between 2 satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-21\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates \\file{tracking data}{instrument} (range, range-rate, range-accelerations)\nbetween 2 satellites. The range is given by\n\\begin{equation}\n\\rho(t) = \\left\\lVert{\\M r_B(t) - \\M r_A(t)}\\right\\rVert = \\M e_{AB}(t)\\cdot\\M r_{AB}(t),\n\\end{equation}\nwith $\\M r_{AB} = \\M r_B - \\M r_A$ and the unit vector in line of sight (LOS) direction\n\\begin{equation}\\label{sst.los}\n\\M e_{AB} = \\frac{\\M r_{AB}}{\\left\\lVert{\\M r_{AB}}\\right\\rVert}=\\frac{\\M r_{AB}}{\\rho}.\n\\end{equation}\nRange-rates~$\\dot{\\rho}$ and range accelrations~$\\ddot{\\rho}$ are obtained by differentation\n\\begin{equation}\\label{obsRangeRate}\n\\dot{\\rho}  = \\M e_{AB}\\cdot\\dot{\\M r}_{AB} + \\dot{\\M e}_{AB}\\cdot\\M r_{AB}\n            = \\M e_{AB}\\cdot\\dot{\\M r}_{AB},\n\\end{equation}\n\\begin{equation}\\label{obsRangeAccl}\n\\begin{split}\n\\ddot{\\rho} &= \\M e_{AB}\\cdot\\ddot{\\M r}_{AB} +\\dot{\\M e}_{AB}\\cdot\\dot{\\M r}_{AB}\n            = \\M e_{AB}\\cdot\\ddot{\\M r}_{AB} +\n   \\frac{1}{\\rho}\\left(\\dot{\\M r}_{AB}^2-\\dot{\\rho}^2\\right). \\\\\n\\end{split}\n\\end{equation}\nwith the derivative of the unit vector\n\\begin{equation}\n\\dot{\\M e}_{AB}=\\frac{d}{dt}\\left(\\frac{\\M r_{AB}}{\\rho}\\right)\n=\\frac{\\dot{\\M r}_{AB}}{\\rho}-\\frac{\\dot{\\rho}\\cdot\\M r_{AB}}{\\rho^2}\n=\\frac{1}{\\rho}\\left({\\dot{\\M r}_{AB}-\\dot{\\rho}\\cdot\\M e_{AB}}\\right).\n\\end{equation}\nThe \\configFile{inputfileOrbit}{instrument}s must contain positions, velocities, and acceleration\n(see \\program{OrbitAddVelocityAndAcceleration}).\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simulate tracking data (range, range-rate, range-accelerations) between 2 satellites.\n* @ingroup programsGroup */\nclass SimulateSatelliteTracking\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateSatelliteTracking, PARALLEL, \"simulate tracking data (range, range-rate, range-accelerations) between 2 satellites\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateSatelliteTracking::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName outName, orbit1Name, orbit2Name;\n\n    readConfig(config, \"outputfileSatelliteTracking\", outName,    Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit1\",             orbit1Name, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit2\",             orbit2Name, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    // Tracking-Daten erzeugen\n    // -----------------------\n    logStatus<<\"read orbits and generate tracking data\"<<Log::endl;\n    InstrumentFile orbit1File(orbit1Name);\n    InstrumentFile orbit2File(orbit2Name);\n    InstrumentFile::checkArcCount({orbit1File, orbit2File});\n    std::vector<Arc> arcList(orbit1File.arcCount());\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc orbit1 = orbit1File.readArc(arcNo);\n      OrbitArc orbit2 = orbit2File.readArc(arcNo);\n      Arc::checkSynchronized({orbit1, orbit2});\n\n      SatelliteTrackingArc arc;\n      for(UInt i=0; i<orbit1.size(); i++)\n      {\n        Vector3d vrange         = orbit2.at(i).position     - orbit1.at(i).position;\n        Vector3d vvelocity      = orbit2.at(i).velocity     - orbit1.at(i).velocity;\n        Vector3d vacceleration  = orbit2.at(i).acceleration - orbit1.at(i).acceleration;\n\n        SatelliteTrackingEpoch epoch;\n        epoch.time              = orbit1.at(i).time;\n        epoch.range             = vrange.norm();\n        epoch.rangeRate         = inner(vrange,vvelocity)/epoch.range;\n        epoch.rangeAcceleration = (vvelocity.quadsum()-pow(epoch.rangeRate,2))/epoch.range\n                                + inner(vrange,vacceleration)/epoch.range;\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write tracking data to file <\"<<outName<<\">\"<<Log::endl;\n      InstrumentFile::write(outName, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateStarCamera.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateStarCamera.cpp\n*\n* @brief Rotation from satellite (x: along, y: cross, z: nadir) to inertial frame.\n*\n* @author Torsten Mayer-Guerr\n* @date 2005-01-21\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates \\file{star camera}{instrument} measurements at each satellite's position.\nThe satellite's orientation follows a local orbit frame with the x-axis in along track (along velocity),\ny-axis is cross track (normal to position and velocity vector) and z-axis pointing nadir (negative position vector).\nAs for non circular orbit the position and velocity are not exact normal, the default is the x-axis to be exact\nalong velocity and the z-axis forms a right hand system (not exact nadir) or with \\config{nadirPointing} the z-axis\nis exact nadir and x-axis approximates along.\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Rotation from satellite (x: along, y: cross, z: nadir) to inertial frame.\n* @ingroup programsGroup */\nclass SimulateStarCamera\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateStarCamera, PARALLEL, \"Rotation from satellite (x: along, y: cross, z: nadir) to inertial frame.\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateStarCamera::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName orbitName, starCameraName;\n    Bool     isNadirPointing;\n\n    readConfig(config, \"outputfileStarCamera\", starCameraName,  Config::MUSTSET, \"\",  \"rotation from satellite to inertial frame (x: along, y: cross, z: nadir)\");\n    readConfig(config, \"inputfileOrbit\",       orbitName,       Config::MUSTSET, \"\",  \"position and velocity defines the orientation of the satellite at each epoch\");\n    readConfig(config, \"nadirPointing\",        isNadirPointing, Config::DEFAULT, \"0\", \"false: exact along and nearly nadir, true: nearly along and exact nadir\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read orbit and generate star camera data\"<<Log::endl;\n    InstrumentFile  orbitFile(orbitName);\n    std::vector<Arc> arcList(orbitFile.arcCount());\n\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc orbit = orbitFile.readArc(arcNo);\n      StarCameraArc arc;\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n\n        Vector3d velocity = orbit.at(i).velocity; // velocity vector\n        if(velocity.r()==0)\n        {\n          if(i<orbit.size()-1)\n            velocity = orbit.at(i+1).position - orbit.at(i).position;\n          else\n            velocity = orbit.at(i).position - orbit.at(i-1).position;\n        }\n\n        Vector3d y = normalize(crossProduct(velocity, orbit.at(i).position)); // cross\n        Vector3d x = normalize((isNadirPointing) ? crossProduct(orbit.at(i).position, y) : velocity);  // along\n\n        StarCameraEpoch epoch;\n        epoch.time   = orbit.at(i).time;\n        epoch.rotary = Rotary3d(x, y);\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm);\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write star camera data to file <\"<<starCameraName<<\">\"<<Log::endl;\n      InstrumentFile::write(starCameraName, arcList);\n      Arc::printStatistics(arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateStarCameraGnss.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateStarCameraGnss.cpp\n*\n* @brief Simulates star camera data for a GNSS satellite based on an attitude model.\n*\n* @author Sebastian Strasser\n* @date 2020-11-02\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates \\file{star camera}{instrument} measurements at each satellite position\nof \\configFile{inputfileOrbit}{instrument}.\nThe resulting rotation matrices rotate from body frame to inertial frame. The body frame refers\nto the IGS-specific (not the manufacturer-specific) body frame, as described by\n\\href{https://doi.org/10.1016/j.asr.2015.06.019}{Montenbruck et al. (2015)}.\nThe \\configFile{inputfileOrbit}{instrument} must contain velocities\n(use \\program{OrbitAddVelocityAndAcceleration} if needed).\n\nInformation about the attitude mode(s) used by the GNSS satellite may be provided via\n\\configFile{inputfileAttitudeInfo}{instrument}. This file can be created with\n\\program{GnssAttitudeInfoCreate}. It contains one or more time-dependent entries,\neach defining the default attitude mode, the attitude modes used around orbit noon and\nmidnight, and some parameters required by the various modes.\nIf no \\configFile{inputfileAttitudeInfo}{instrument} is selected, the program defaults\nto a nominal yaw-steering attitude model.\nA sufficiently high \\config{modelingResolution} ensures that the attitude behavior is modeled properly\nat all times.\n\nThe attitude behavior is defined by the respective mode. Here is a list of the supported\nmodes with a brief explanation and references:\n\\begin{itemize}\n\\item \\textbf{nominalYawSteering}:\n      Yaw to keep solar panels aligned to Sun (e.g. most GNSS satellites outside eclipse) [1]\n\\item \\textbf{orbitNormal}:\n      Keep fixed yaw angle, for example point X-axis in flight direction (e.g. BDS-2G, BDS-3G, QZS-2G) [1]\n\\item \\textbf{catchUpYawSteering}:\n      Yaw at maximum yaw rate to catch up to nominal yaw angle (e.g. GPS-* (noon), GPS-IIR (midnight)) [2, 3]\n\\item \\textbf{shadowMaxYawSteeringAndRecovery}:\n      Yaw at maximum yaw rate from shadow start to end, recover after shadow (e.g. GPS-IIA (midnight)) [2]\n\\item \\textbf{shadowMaxYawSteeringAndStop}:\n      Yaw at maximum yaw rate from shadow start until nominal yaw angle at shadow end is reached,\n      then stop (e.g. GLO-M (midnight)) [4]\n\\item \\textbf{shadowConstantYawSteering}:\n      Yaw at constant yaw rate from shadow start to end (e.g. GPS-IIF (midnight)) [3]\n\\item \\textbf{centeredMaxYawSteering}:\n      Yaw at maximum yaw rate centered around noon/midnight (e.g. QZS-2I, GLO-M (noon)) [4, 8]\n\\item \\textbf{smoothedYawSteering1}:\n      Yaw based on an auxiliary Sun vector for a smooth yaw maneuver (e.g. GAL-1) [5]\n\\item \\textbf{smoothedYawSteering2}:\n      Yaw based on a modified yaw-steering law for a smooth yaw maneuver (e.g. GAL-2, BDS-3M, BDS-3I) [5, 6]\n\\item \\textbf{betaDependentOrbitNormal}:\n      Switch to orbit normal mode if below beta angle threshold (e.g. BDS-2M, BDS-2I, QZS-1) [7, 8]\n\\end{itemize}\n\n\\fig{!hb}{0.9}{gnssAttitudeModes}{fig:gnssAttitudeModes1}{Overview of attitude modes used by GNSS satellites}\n\nSee \\program{GnssAttitudeInfoCreate} for more details on which satellite uses which attitude modes\nand the required parameters for each mode.\n\nReferences for the attitude modes:\n\\begin{enumerate}\n\\item \\href{https://doi.org/10.1016/j.asr.2015.06.019}{Montenbruck et al. (2015)}\n\\item \\href{https://doi.org/10.1007/s10291-008-0092-1}{Kouba (2009)}\n\\item \\href{https://doi.org/10.1007/s10291-016-0562-9}{Kuang et al. (2017)}\n\\item \\href{https://doi.org/10.1016/j.asr.2010.09.007}{Dilssner et al. (2011)}\n\\item \\url{https://www.gsc-europa.eu/support-to-developers/galileo-satellite-metadata#3}\n\\item \\href{https://doi.org/10.1007/s10291-018-0783-1}{Wang et al. (2018)}\n\\item \\href{https://doi.org/10.1017/S0373463318000103}{Li et al. (2018)}\n\\item \\url{https://qzss.go.jp/en/technical/qzssinfo/index.html}\n\\end{enumerate}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/kepler.h\"\n#include \"base/polynomial.h\"\n#include \"classes/eclipse/eclipse.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simulates star camera data for a GNSS satellite based on an attitude model.\n* @ingroup programsGroup */\nclass SimulateStarCameraGnss\n{\n  enum AttitudeMode\n  {\n    NOMINAL_YAW_STEERING = 0,\n    ORBIT_NORMAL = 1,                         // e.g. BDS-2G, BDS-3G, QZS-2G\n    CATCH_UP_YAW_STEERING = 2,                // e.g. GPS-* (noon), GPS-IIR (midnight)\n    SHADOW_MAX_YAW_STEERING_AND_RECOVERY = 3, // e.g. GPS-IIA (midnight)\n    SHADOW_MAX_YAW_STEERING_AND_STOP = 4,     // e.g. GLO-M (midnight)\n    SHADOW_CONSTANT_YAW_STEERING = 5,         // e.g. GPS-IIF (midnight)\n    CENTERED_MAX_YAW_STEERING = 6,            // e.g. QZS-2I, GLO-M (noon)\n    SMOOTHED_YAW_STEERING_1 = 7,              // e.g. GAL-1\n    SMOOTHED_YAW_STEERING_2 = 8,              // e.g. GAL-2, BDS-3M, BDS-3I\n    BETA_DEPENDENT_ORBIT_NORMAL = 9           // e.g. BDS-2M, BDS-2I, QZS-1\n  };\n\n  class AttitudeInfo\n  {\n  public:\n    Time         timeStart;\n    AttitudeMode defaultMode;\n    AttitudeMode midnightMode;\n    AttitudeMode noonMode;\n    Double       maxYawRate;\n    Double       yawBias;\n    Double       midnightBetaThreshold;\n    Double       noonBetaThreshold;\n    Double       activationThreshold;\n    Double       maxManeuverTime;\n\n    AttitudeInfo(const Time &time, const Vector &data)\n    {\n      timeStart             = time;\n      defaultMode           = AttitudeMode(data(0));\n      midnightMode          = AttitudeMode(data(1));\n      noonMode              = AttitudeMode(data(2));\n      maxYawRate            = DEG2RAD*std::fabs(data(3));\n      yawBias               = DEG2RAD*data(4);\n      midnightBetaThreshold = DEG2RAD*std::fabs(data(5));\n      noonBetaThreshold     = DEG2RAD*std::fabs(data(6));\n      activationThreshold   = DEG2RAD*std::fabs(data(7));\n      maxManeuverTime       = std::fabs(data(8));\n    }\n  };\n\n  class Epoch\n  {\n  public:\n    Time     time;\n    Double   yawAngle;\n    Double   yawRate;\n    Double   orbitAngle;\n    Double   betaAngle;\n    Vector3d pos;\n    Vector3d vel;\n    Vector3d posSun;\n\n    Epoch() : yawAngle(0), yawRate(0), orbitAngle(0), betaAngle(0) {}\n  };\n\n  EphemeridesPtr ephemerides;\n  EclipsePtr     eclipse;\n  std::vector<Epoch>        epochs;\n  std::vector<AttitudeInfo> attitudeInfos;\n\n  // helper methods\n  Double       wrapAngle(Double angle) const;  ///< Returns angle wrapped to [-PI, PI).\n  Rotary3d     orbitNormal2crf(const Vector3d &posSat, const Vector3d &velSat) const;\n  AttitudeInfo getAttitudeInfo(const Time &time) const;\n  Epoch        createDefaultEpoch(const Time &time, const Vector3d &posSat, const Vector3d &velSat) const;\n  Bool         findShadowBoundaries(UInt idMidnightEpoch, Epoch &shadowStart, Epoch &shadowEnd) const;\n  UInt         catchUpYawAngle(const Epoch startEpoch, Double maxYawRate, Bool backwards=FALSE);\n\n  // attitude mode methods\n  void modelNominalYawSteering(Epoch &epoch) const;\n  void modelOrbitNormal(Epoch &epoch, const AttitudeInfo &attitudeInfo) const;\n  UInt modelCatchUpYawSteering(UInt idEpoch, const AttitudeInfo &attitudeInfo);\n  UInt modelShadowMaxYawSteeringAndRecovery(UInt idEpoch, const AttitudeInfo &attitudeInfo);\n  UInt modelShadowMaxYawSteeringAndStop(UInt idEpoch, const AttitudeInfo &attitudeInfo);\n  UInt modelShadowConstantYawSteering(UInt idEpoch);\n  UInt modelCenteredMaxYawSteering(UInt idEpoch, const AttitudeInfo &attitudeInfo);\n  UInt modelSmoothedYawSteering1(UInt idEpoch);\n  UInt modelSmoothedYawSteering2(UInt idEpoch, const AttitudeInfo &attitudeInfo);\n  UInt modelBetaDependentOrbitNormal(UInt idEpoch, const AttitudeInfo &attitudeInfo);\n\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateStarCameraGnss, SINGLEPROCESS, \"Simulates star camera data for a GNSS satellite based on an attitude model.\", Simulation, Gnss, Instrument)\n\n/***********************************************/\n\nvoid SimulateStarCameraGnss::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameStarCamera, fileNameOrbit, fileNameAttitudeInfo;\n    Double   modelingResolution;\n    UInt     interpolationDegree;\n\n    readConfig(config, \"outputfileStarCamera\",  fileNameStarCamera,   Config::MUSTSET,  \"\",  \"rotation from body frame to CRF\");\n    readConfig(config, \"inputfileOrbit\",        fileNameOrbit,        Config::MUSTSET,  \"\",  \"attitude is modeled based on this orbit\");\n    readConfig(config, \"inputfileAttitudeInfo\", fileNameAttitudeInfo, Config::OPTIONAL, \"{groopsDataDir}/gnss/transmitter/attitudeInfo/attitudeInfo.{svn}.txt\", \"attitude modes used by the satellite and respective parameters\");\n    readConfig(config, \"interpolationDegree\",   interpolationDegree,  Config::DEFAULT,  \"7\", \"polynomial degree for orbit interpolation\");\n    readConfig(config, \"modelingResolution\",    modelingResolution,   Config::DEFAULT,  \"1\", \"[s] resolution for attitude model evaluation\");\n    readConfig(config, \"ephemerides\",           ephemerides,          Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"eclipse\",               eclipse,              Config::MUSTSET,  \"\",  \"model to determine if satellite is in Earth's shadow\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"read orbit file <\"<<fileNameOrbit<<\">\"<<Log::endl;\n    OrbitArc orbitArc = InstrumentFile::read(fileNameOrbit);\n    if(orbitArc.size()==0)\n      throw(Exception(\"empty orbit file\"));\n    if(orbitArc.size() && orbitArc.at(0).velocity.r()==0.)\n      throw(Exception(\"orbit does not contain velocity data\"));\n\n    if(fileNameAttitudeInfo.empty())\n    {\n      logStatus<<\"no attitude info provided, using nominal yaw-steering attitude\"<<Log::endl;\n      attitudeInfos.push_back(AttitudeInfo(Time(), Vector(9)));\n    }\n    else\n    {\n      logStatus<<\"read attitude info from file <\"<<fileNameAttitudeInfo<<\">\"<<Log::endl;\n      MiscValuesArc arc = InstrumentFile::read(fileNameAttitudeInfo);\n      for(auto epoch : arc)\n        attitudeInfos.push_back(AttitudeInfo(epoch.time, epoch.data()));\n    }\n\n    // increase sampling and compute beta angle, orbit angle, and yaw angle/rate from default attitude mode for all epochs\n    const std::vector<Time> timesOrbit = orbitArc.times();\n    const Time deltaTime = seconds2time(std::fabs(modelingResolution));\n    std::vector<Time> times;\n    for(UInt i=0; timesOrbit.front()+i*deltaTime<=timesOrbit.back(); i++)\n      times.push_back(timesOrbit.front() + i*deltaTime);\n    Polynomial polynomial(timesOrbit, interpolationDegree);\n    {\n      Matrix positionVelocity = polynomial.interpolate(times, orbitArc.matrix().column(1, 6), 1);\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        epochs.push_back(createDefaultEpoch(times.at(idEpoch), Vector3d(positionVelocity.slice(idEpoch, 0, 1, 3)), Vector3d(positionVelocity.slice(idEpoch, 3, 1, 3))));\n    }\n\n    // Kepler-integrate forwards and backwards in time to consider maneuvers at orbit boundaries\n    auto keplerExtend = [&](const Time &timeStart, const Vector3d &posStart, const Vector3d &velStart, Double integrationStep, Double integrationLimit)\n    {\n      Kepler kepler(timeStart, posStart, velStart);\n      for(UInt i=1; (i-1)*std::fabs(integrationStep)<=std::fabs(integrationLimit); i++)\n      {\n        Time time = timeStart + seconds2time(i*integrationStep);\n        Vector3d pos, vel;\n        kepler.orbit(time, pos, vel);\n        epochs.push_back(createDefaultEpoch(time, pos, vel));\n        times.push_back(time);\n      }\n    };\n    keplerExtend(orbitArc.front().time, orbitArc.front().position, orbitArc.front().velocity, -deltaTime.seconds(), getAttitudeInfo(orbitArc.front().time).maxManeuverTime);\n    keplerExtend(orbitArc.back().time,  orbitArc.back().position,  orbitArc.back().velocity,   deltaTime.seconds(), getAttitudeInfo(orbitArc.back().time).maxManeuverTime);\n    std::sort(epochs.begin(), epochs.end(), [](auto &e1, auto &e2){ return e1.time<e2.time; });\n    std::sort(times.begin(), times.end());\n\n    // model transitions caused by change of default attitude mode\n    AttitudeMode previousDefaultMode = getAttitudeInfo(epochs.front().time).defaultMode;\n    for(UInt idEpoch=1; idEpoch<epochs.size(); idEpoch++)\n    {\n      const AttitudeInfo attitudeInfo = getAttitudeInfo(epochs.at(idEpoch).time);\n      if(attitudeInfo.defaultMode!=previousDefaultMode)\n      {\n        if(attitudeInfo.maxYawRate>0.)\n        {\n          epochs.at(idEpoch-1).yawRate = wrapAngle(epochs.at(idEpoch).yawAngle-epochs.at(idEpoch-1).yawAngle)>=0 ? attitudeInfo.maxYawRate : -attitudeInfo.maxYawRate;\n          catchUpYawAngle(epochs.at(idEpoch-1), attitudeInfo.maxYawRate);\n        }\n        else\n          logWarning<<\"default attitude mode change at \"<<epochs.at(idEpoch-1).time.dateTimeStr()<<\" but unable to model transition because maxYawRate data is missing\"<<Log::endl;\n      }\n      previousDefaultMode = attitudeInfo.defaultMode;\n    }\n\n    // apply specific attitude modes for noon and midnight\n    for(UInt idEpoch=0; idEpoch<epochs.size(); idEpoch++)\n    {\n      const AttitudeInfo attitudeInfo = getAttitudeInfo(epochs.at(idEpoch).time);\n      const AttitudeMode attitudeMode = std::fabs(epochs.at(idEpoch).orbitAngle)<=PI/2 ? attitudeInfo.midnightMode : attitudeInfo.noonMode;\n      if(attitudeMode==attitudeInfo.defaultMode)\n        continue; // same as default mode => nothing to adjust\n\n      switch(attitudeMode)\n      {\n        case NOMINAL_YAW_STEERING:                 modelNominalYawSteering(epochs.at(idEpoch));                           break;\n        case ORBIT_NORMAL:                         modelOrbitNormal(epochs.at(idEpoch), attitudeInfo);                    break;\n        case CATCH_UP_YAW_STEERING:                idEpoch = modelCatchUpYawSteering(idEpoch, attitudeInfo);              break;\n        case SHADOW_MAX_YAW_STEERING_AND_RECOVERY: idEpoch = modelShadowMaxYawSteeringAndRecovery(idEpoch, attitudeInfo); break;\n        case SHADOW_MAX_YAW_STEERING_AND_STOP:     idEpoch = modelShadowMaxYawSteeringAndStop(idEpoch, attitudeInfo);     break;\n        case SHADOW_CONSTANT_YAW_STEERING:         idEpoch = modelShadowConstantYawSteering(idEpoch);                     break;\n        case CENTERED_MAX_YAW_STEERING:            idEpoch = modelCenteredMaxYawSteering(idEpoch, attitudeInfo);          break;\n        case SMOOTHED_YAW_STEERING_1:              idEpoch = modelSmoothedYawSteering1(idEpoch);                          break;\n        case SMOOTHED_YAW_STEERING_2:              idEpoch = modelSmoothedYawSteering2(idEpoch, attitudeInfo);            break;\n        case BETA_DEPENDENT_ORBIT_NORMAL:          idEpoch = modelBetaDependentOrbitNormal(idEpoch, attitudeInfo);        break;\n        default: throw(Exception(attitudeMode%\"unknown attitude mode: %i\"s));\n      }\n    }\n\n    // Compute output star camera data\n    Matrix quaternions(times.size(), 4);\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n    {\n      copy(rotaryZ(-Angle(epochs.at(idEpoch).yawAngle)).quaternion().trans(), quaternions.row(idEpoch));\n      if(idEpoch>0 && inner(quaternions.row(idEpoch), quaternions.row(idEpoch-1))<0.)\n        quaternions.row(idEpoch) *= -1; // ensure same sign for correct interpolation\n    }\n    polynomial.init(times, interpolationDegree);\n    quaternions = polynomial.interpolate(timesOrbit, quaternions, 1);\n    StarCameraArc starCameraArc;\n    for(UInt idEpoch=0; idEpoch<timesOrbit.size(); idEpoch++)\n    {\n      StarCameraEpoch starCameraEpoch;\n      starCameraEpoch.time   = timesOrbit.at(idEpoch);\n      starCameraEpoch.rotary = orbitNormal2crf(orbitArc.at(idEpoch).position, orbitArc.at(idEpoch).velocity) * Rotary3d(quaternions.row(idEpoch).trans());\n      starCameraArc.push_back(starCameraEpoch);\n    }\n\n    logStatus<<\"write star camera file <\"<<fileNameStarCamera<<\">\"<<Log::endl;\n    InstrumentFile::write(fileNameStarCamera, starCameraArc);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SimulateStarCameraGnss::wrapAngle(Double angle) const\n{\n  while(angle>= PI) angle -= 2*PI;\n  while(angle< -PI) angle += 2*PI;\n\n  return angle;\n}\n\n/***********************************************/\n\nRotary3d SimulateStarCameraGnss::orbitNormal2crf(const Vector3d &posSat, const Vector3d &velSat) const\n{\n  try\n  {\n    Vector3d r = normalize(posSat);\n    Vector3d n = normalize(crossProduct(posSat, velSat));\n\n    return Rotary3d(crossProduct(-n, -r), -n);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSimulateStarCameraGnss::AttitudeInfo SimulateStarCameraGnss::getAttitudeInfo(const Time &time) const\n{\n  try\n  {\n    auto iter = std::find_if(attitudeInfos.rbegin(), attitudeInfos.rend(), [&](auto info){ return info.timeStart<=time; });\n    if(iter==attitudeInfos.rend())\n      throw(Exception(\"no attitude modes found for \"+time.dateTimeStr()));\n    return *iter;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSimulateStarCameraGnss::Epoch SimulateStarCameraGnss::createDefaultEpoch(const Time &time, const Vector3d &posSat, const Vector3d &velSat) const\n{\n  try\n  {\n    Epoch epoch;\n    epoch.time   = time;\n    epoch.pos    = posSat;\n    epoch.vel    = velSat;\n    epoch.posSun = ephemerides->position(epoch.time, Ephemerides::SUN);\n\n    // Argument of latitude of satellite and sun\n    const Vector3d z  = normalize(crossProduct(epoch.pos, epoch.vel));\n    const Vector3d x  = normalize(crossProduct(Vector3d(0,0,1), z));\n    const Vector3d y  = crossProduct(z, x);\n    const Double   u  = std::atan2(inner(epoch.pos, y), inner(epoch.pos, x));\n    const Double   u0 = std::atan2(inner(epoch.posSun, y), inner(epoch.posSun, x));\n\n    epoch.orbitAngle = wrapAngle(u - u0 + PI);\n    epoch.betaAngle  = std::acos(inner(-z, epoch.posSun)/epoch.posSun.r()) - PI/2;\n\n    const AttitudeInfo attitudeInfo = getAttitudeInfo(time);\n    if(attitudeInfo.defaultMode==NOMINAL_YAW_STEERING)\n      modelNominalYawSteering(epoch);\n    else if(attitudeInfo.defaultMode==ORBIT_NORMAL)\n      modelOrbitNormal(epoch, attitudeInfo);\n    else\n      throw(Exception(\"only nominal yaw-steering mode or orbit normal mode are supported as default attitude modes\"));\n\n    return epoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool SimulateStarCameraGnss::findShadowBoundaries(UInt idMidnightEpoch, Epoch &shadowStart, Epoch &shadowEnd) const\n{\n  try\n  {\n    if(eclipse->factor(epochs.at(idMidnightEpoch).time, epochs.at(idMidnightEpoch).pos, ephemerides)>0.)\n      return FALSE; // satellite never entered full shadow\n\n    auto isOutsideShadow = [&](auto &epoch){ return eclipse->factor(epoch.time, epoch.pos, ephemerides)>0.; };\n\n    auto iterEnd = std::find_if(epochs.begin()+idMidnightEpoch+1, epochs.end(), isOutsideShadow);\n    if(iterEnd==epochs.end())\n      return FALSE;\n\n    auto iterStart = std::find_if(std::make_reverse_iterator(epochs.begin()+idMidnightEpoch), epochs.rend(), isOutsideShadow);\n    if(iterStart==epochs.rend())\n      return FALSE;\n\n    shadowStart = *(iterStart-1);\n    shadowEnd   = *(iterEnd-1);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::catchUpYawAngle(const Epoch startEpoch, Double maxYawRate, Bool backwards)\n{\n  try\n  {\n    const Double startYawRate = (startEpoch.yawRate>=0 ? maxYawRate : -maxYawRate);\n    Double previousYawAngleDiff = 0.;\n    auto hasCaughtUpYaw = [&](UInt idEpoch)\n    {\n      Double yawAngle     = wrapAngle(startEpoch.yawAngle + startYawRate*(epochs.at(idEpoch).time-startEpoch.time).seconds());\n      Double yawAngleDiff = wrapAngle(epochs.at(idEpoch).yawAngle - yawAngle);\n\n      // Stop once true yaw angle catches up with nominal yaw angle\n      if(((previousYawAngleDiff>0. && yawAngleDiff<0.) || (previousYawAngleDiff<0. && yawAngleDiff>0.)) && std::fabs(yawAngleDiff-previousYawAngleDiff)<PI)\n        return TRUE;\n\n      previousYawAngleDiff        = yawAngleDiff;\n      epochs.at(idEpoch).yawAngle = yawAngle;\n      epochs.at(idEpoch).yawRate  = startYawRate;\n\n      return FALSE;\n    };\n\n    UInt idStartEpoch = std::distance(epochs.begin(), std::find_if(epochs.begin(), epochs.end(), [&](auto &epoch){ return epoch.time>startEpoch.time; }));\n    if(backwards)\n    {\n      for(UInt idEpoch=idStartEpoch+1; idEpoch-->0;)\n        if(hasCaughtUpYaw(idEpoch))\n          return idEpoch;\n    }\n    else\n    {\n      for(UInt idEpoch=idStartEpoch; idEpoch<epochs.size(); idEpoch++)\n        if(hasCaughtUpYaw(idEpoch))\n          return idEpoch;\n    }\n\n    return backwards ? 0 : epochs.size();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SimulateStarCameraGnss::modelNominalYawSteering(Epoch &epoch) const\n{\n  try\n  {\n    epoch.yawAngle = wrapAngle(std::atan2(-std::tan(epoch.betaAngle), std::sin(epoch.orbitAngle)));\n    epoch.yawRate  = epoch.vel.r()/epoch.pos.r() * std::tan(epoch.betaAngle)*std::cos(epoch.orbitAngle) /\n                     (std::sin(epoch.orbitAngle)*std::sin(epoch.orbitAngle) + std::tan(epoch.betaAngle)*std::tan(epoch.betaAngle));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SimulateStarCameraGnss::modelOrbitNormal(Epoch &epoch, const AttitudeInfo &attitudeInfo) const\n{\n  try\n  {\n    epoch.yawAngle = wrapAngle(attitudeInfo.yawBias);\n    epoch.yawRate  = 0.;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelCatchUpYawSteering(UInt idEpoch, const AttitudeInfo &attitudeInfo)\n{\n  try\n  {\n    if(attitudeInfo.maxYawRate==0.)\n      throw(Exception(\"required data missing for model: CATCH_UP_YAW_STEERING (maxYawRate)\"));\n\n    // check if maximum yaw rate is exceeded between current and next epoch\n    if(idEpoch+1<epochs.size() && std::fabs(epochs.at(idEpoch).yawRate)<=attitudeInfo.maxYawRate && std::fabs(epochs.at(idEpoch+1).yawRate)>attitudeInfo.maxYawRate)\n    {\n      Epoch startEpoch = epochs.at(idEpoch+1);\n\n      // consider anomalous turns at low beta angle for satellites with yaw bias\n      if(attitudeInfo.yawBias!=0. && std::fabs(startEpoch.betaAngle)<std::fabs(attitudeInfo.yawBias) && attitudeInfo.yawBias*startEpoch.betaAngle>0.)\n        startEpoch.yawRate = (startEpoch.betaAngle-attitudeInfo.yawBias)>=0. ? -attitudeInfo.maxYawRate : attitudeInfo.maxYawRate;\n\n      return catchUpYawAngle(startEpoch, attitudeInfo.maxYawRate);\n    }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelShadowMaxYawSteeringAndRecovery(UInt idEpoch, const AttitudeInfo &attitudeInfo)\n{\n  try\n  {\n    if(attitudeInfo.maxYawRate==0.)\n      throw(Exception(\"required data missing for model: SHADOW_MAX_YAW_STEERING_AND_RECOVERY (maxYawRate)\"));\n\n    // check if satellite crosses midnight between current and next epoch\n    if(std::fabs(epochs.at(idEpoch).orbitAngle)<=PI/2 && idEpoch+1<epochs.size() && epochs.at(idEpoch).orbitAngle<0. && epochs.at(idEpoch+1).orbitAngle>=0)\n    {\n      Epoch shadowStart, shadowEnd;\n      if(!findShadowBoundaries(idEpoch, shadowStart, shadowEnd))\n        return idEpoch; // cannot model maneuver without knowing shadow start and end\n\n      // shadow maneuver\n      Double startYawRate = 0.;\n      if(attitudeInfo.yawBias>0.)\n        startYawRate = attitudeInfo.maxYawRate;\n      else if(attitudeInfo.yawBias<0.)\n        startYawRate = -attitudeInfo.maxYawRate;\n      else\n        startYawRate = (shadowStart.yawRate>=0. ? attitudeInfo.maxYawRate : -attitudeInfo.maxYawRate);\n      for(auto &&epoch : epochs)\n        if(epoch.time>=shadowStart.time && epoch.time<=shadowEnd.time)\n        {\n          epoch.yawAngle = wrapAngle(shadowStart.yawAngle + startYawRate*(epoch.time-shadowStart.time).seconds());\n          epoch.yawRate = startYawRate;\n        }\n\n      // post-shadow recovery maneuver\n      const Double shadowEndNominalYawAngle = shadowEnd.yawAngle;\n      shadowEnd.yawAngle = wrapAngle(shadowStart.yawAngle + startYawRate*(shadowEnd.time-shadowStart.time).seconds());\n      shadowEnd.yawRate  = wrapAngle(shadowEnd.yawAngle-shadowEndNominalYawAngle)>=0 ? -attitudeInfo.maxYawRate : attitudeInfo.maxYawRate;\n      return catchUpYawAngle(shadowEnd, attitudeInfo.maxYawRate);\n    }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelShadowMaxYawSteeringAndStop(UInt idEpoch, const AttitudeInfo &attitudeInfo)\n{\n  try\n  {\n    if(attitudeInfo.maxYawRate==0.)\n      throw(Exception(\"required data missing for model: SHADOW_MAX_YAW_STEERING_AND_STOP (maxYawRate)\"));\n\n    // check if satellite crosses midnight between current and next epoch\n    if(std::fabs(epochs.at(idEpoch).orbitAngle)<=PI/2 && idEpoch+1<epochs.size() && epochs.at(idEpoch).orbitAngle<0. && epochs.at(idEpoch+1).orbitAngle>=0)\n    {\n      Epoch shadowStart, shadowEnd;\n      if(!findShadowBoundaries(idEpoch, shadowStart, shadowEnd))\n        return idEpoch; // cannot model maneuver without knowing shadow start and end\n\n      // shadow maneuver\n      for(UInt i=0; i<epochs.size(); i++)\n        if(epochs.at(i).time>shadowStart.time && epochs.at(i).time<=shadowEnd.time)\n        {\n          epochs.at(i).yawAngle = shadowEnd.yawAngle;\n          epochs.at(i).yawRate = 0.;\n          idEpoch = i;\n        }\n      catchUpYawAngle(shadowStart, attitudeInfo.maxYawRate);\n    }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelShadowConstantYawSteering(UInt idEpoch)\n{\n  try\n  {\n    // check if satellite crosses midnight between current and next epoch\n    if(std::fabs(epochs.at(idEpoch).orbitAngle)<=PI/2 && idEpoch+1<epochs.size() && epochs.at(idEpoch).orbitAngle<0. && epochs.at(idEpoch+1).orbitAngle>=0)\n    {\n      Epoch shadowStart, shadowEnd;\n      if(!findShadowBoundaries(idEpoch, shadowStart, shadowEnd))\n        return idEpoch; // cannot model maneuver without knowing shadow start and end\n\n      // shadow maneuver\n      const Double startYawRate = wrapAngle(shadowEnd.yawAngle-shadowStart.yawAngle)/(shadowEnd.time-shadowStart.time).seconds();\n      for(UInt i=0; i<epochs.size(); i++)\n        if(epochs.at(i).time>=shadowStart.time && epochs.at(i).time<=shadowEnd.time)\n        {\n          epochs.at(i).yawAngle = wrapAngle(shadowStart.yawAngle + startYawRate*(epochs.at(i).time-shadowStart.time).seconds());\n          epochs.at(i).yawRate  = startYawRate;\n          idEpoch = i;\n        }\n    }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelCenteredMaxYawSteering(UInt idEpoch, const AttitudeInfo &attitudeInfo)\n{\n  try\n  {\n    if(attitudeInfo.maxYawRate==0.)\n      throw(Exception(\"required data missing for model: CENTERED_MAX_YAW_STEERING (maxYawRate)\"));\n\n    if(std::fabs(epochs.at(idEpoch).orbitAngle)<=PI/2) // satellite is in midnight half of the orbit\n    {\n      Bool hasCrossedMidnight = idEpoch+1<epochs.size() && wrapAngle(epochs.at(idEpoch).orbitAngle)<0. &&  wrapAngle(epochs.at(idEpoch+1).orbitAngle)>=0;\n      Bool isModeActive = attitudeInfo.midnightBetaThreshold==0. || std::abs(epochs.at(idEpoch).betaAngle)<attitudeInfo.midnightBetaThreshold;\n      if(!hasCrossedMidnight || !isModeActive)\n        return idEpoch;\n    }\n    else // satellite is in noon half of the orbit\n    {\n      Bool hasCrossedNoon = idEpoch+1<epochs.size() && wrapAngle(epochs.at(idEpoch).orbitAngle+PI)<0. &&  wrapAngle(epochs.at(idEpoch+1).orbitAngle+PI)>=0;\n      Bool isModeActive = attitudeInfo.noonBetaThreshold==0. || std::abs(epochs.at(idEpoch).betaAngle)<attitudeInfo.noonBetaThreshold;\n      if(!hasCrossedNoon || !isModeActive)\n        return idEpoch;\n    }\n\n    catchUpYawAngle(epochs.at(idEpoch+1), attitudeInfo.maxYawRate, TRUE/*backwards*/);\n    return catchUpYawAngle(epochs.at(idEpoch+1), attitudeInfo.maxYawRate);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelSmoothedYawSteering1(UInt idEpoch)\n{\n  try\n  {\n    const Double sinBetaX = std::sin(15.0*DEG2RAD);\n    const Double sinBetaY = std::sin(2.0*DEG2RAD);\n\n    auto computeS0 = [&](const Epoch &epoch) { return orbitNormal2crf(epoch.pos, epoch.vel).inverseRotate(normalize(epoch.posSun-epoch.pos)); };\n    auto isInAuxiliaryRegion = [&](const Vector3d &S0) { return std::fabs(S0.x())<sinBetaX && std::fabs(S0.y())<sinBetaY; };\n\n    if(idEpoch+1<epochs.size() && isInAuxiliaryRegion(computeS0(epochs.at(idEpoch+1))) && !isInAuxiliaryRegion(computeS0(epochs.at(idEpoch))))\n    {\n      const Double Gamma = (computeS0(epochs.at(idEpoch+1)).y()<0 ? -1 : 1);\n      for(UInt i=idEpoch+2; i<epochs.size(); i++)\n      {\n        const Vector3d S0 = computeS0(epochs.at(i));\n        if(!isInAuxiliaryRegion(S0))\n          return i;\n\n        const Double SHy = 0.5*(sinBetaY*Gamma + S0.y()) + 0.5*(sinBetaY*Gamma - S0.y()) * std::cos(PI*std::fabs(S0.x())/sinBetaX);\n        const Vector3d SH(S0.x(), SHy, std::sqrt(1. - S0.x()*S0.x() - SHy*SHy)*(S0.z()<0 ? -1 : 1));\n        const Double denom = std::sqrt(1. - SH.z()*SH.z());\n        epochs.at(i).yawAngle = std::atan2(SH.y()/denom, SH.x()/denom);\n      }\n    }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelSmoothedYawSteering2(UInt idEpoch, const AttitudeInfo &attitudeInfo)\n{\n  try\n  {\n    if(attitudeInfo.activationThreshold==0. || attitudeInfo.maxManeuverTime==0. ||\n       (std::fabs(epochs.at(idEpoch).orbitAngle<=PI/2 ? attitudeInfo.midnightBetaThreshold : attitudeInfo.noonBetaThreshold))==0.)\n      throw(Exception(\"required data missing for model: SMOOTHED_YAW_STEERING_2 (betaThreshold, activationThreshold, maxManeuverTime)\"));\n\n    auto isUsingModifiedLaw = [&](const Epoch &epoch)\n    {\n      Vector3d n = crossProduct(epoch.pos, epoch.vel);\n      Double epsilon = std::acos(inner(normalize(epoch.pos), normalize(crossProduct(n, crossProduct(n, epoch.posSun)))));\n      if(epsilon>PI/2)\n        epsilon = PI - epsilon;\n\n      if(std::fabs(epochs.at(idEpoch).orbitAngle)<=PI/2) // satellite is in midnight half of the orbit\n        return std::fabs(epochs.at(idEpoch).betaAngle)<attitudeInfo.midnightBetaThreshold && std::fabs(epsilon)<attitudeInfo.activationThreshold;\n      else // satellite is in noon half of the orbit\n        return std::fabs(epochs.at(idEpoch).betaAngle)<attitudeInfo.noonBetaThreshold && std::fabs(epsilon)<attitudeInfo.activationThreshold;\n    };\n\n    if(idEpoch+1<epochs.size() && isUsingModifiedLaw(epochs.at(idEpoch+1)) && !isUsingModifiedLaw(epochs.at(idEpoch)))\n      for(UInt i = idEpoch+2; i<epochs.size(); i++)\n      {\n        if(!isUsingModifiedLaw(epochs.at(i)))\n          return idEpoch;\n\n        const Double offset = (epochs.at(idEpoch+1).yawAngle<0 ? -PI/2 : PI/2);\n        const Double tMod   = (epochs.at(i).time - epochs.at(idEpoch+1).time).seconds();\n        epochs.at(i).yawAngle = offset + (epochs.at(idEpoch+1).yawAngle - offset) * std::cos(2*PI/attitudeInfo.maxManeuverTime * tMod);\n      }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nUInt SimulateStarCameraGnss::modelBetaDependentOrbitNormal(UInt idEpoch, const AttitudeInfo &attitudeInfo)\n{\n  try\n  {\n    if(attitudeInfo.maxYawRate==0. ||attitudeInfo.activationThreshold==0. || attitudeInfo.maxManeuverTime==0. ||\n       (std::fabs(epochs.at(idEpoch).orbitAngle<=PI/2 ? attitudeInfo.midnightBetaThreshold : attitudeInfo.noonBetaThreshold))==0.)\n      throw(Exception(\"required data missing for model: BETA_DEPENDENT_ORBIT_NORMAL (maxYawRate, betaThreshold, activationThreshold, maxManeuverTime)\"));\n\n    auto isBelowBetaThreshold = [&](auto &epoch)\n    {\n      return std::fabs(epoch.betaAngle)<(std::fabs(epoch.orbitAngle)<=PI/2 ? attitudeInfo.midnightBetaThreshold : attitudeInfo.noonBetaThreshold);\n    };\n    auto isBelowYawThreshold = [&](auto &epoch) { return std::fabs(wrapAngle(epoch.yawAngle+attitudeInfo.yawBias))<=attitudeInfo.activationThreshold; };\n\n    if(idEpoch+1<epochs.size() && isBelowBetaThreshold(epochs.at(idEpoch)) && !isBelowYawThreshold(epochs.at(idEpoch)) && isBelowYawThreshold(epochs.at(idEpoch+1)))\n    {\n      UInt idEpochEnd = idEpoch+1;\n      for(UInt i=idEpoch+1; i<epochs.size(); i++)\n      {\n        if(!isBelowBetaThreshold(epochs.at(i)))\n          break;\n        if(isBelowYawThreshold(epochs.at(i)))\n          idEpochEnd = i;\n      }\n      if((epochs.at(idEpochEnd).time-epochs.at(idEpoch+1).time).seconds()*attitudeInfo.maxYawRate<attitudeInfo.activationThreshold)\n        return idEpoch; // period in orbit normal mode would be shorter than period required for transition\n\n      const Double yawRateEntry = (wrapAngle(epochs.at(idEpoch).yawAngle-attitudeInfo.yawBias)>=0.)    ? -attitudeInfo.maxYawRate :  attitudeInfo.maxYawRate;\n      const Double yawRateExit  = (wrapAngle(epochs.at(idEpochEnd).yawAngle-attitudeInfo.yawBias)>=0.) ?  attitudeInfo.maxYawRate : -attitudeInfo.maxYawRate;\n      for(UInt i=idEpoch+1; i<=idEpochEnd; i++)\n        modelOrbitNormal(epochs.at(i), attitudeInfo);\n      epochs.at(idEpoch).yawRate = yawRateEntry;\n      catchUpYawAngle(epochs.at(idEpoch), attitudeInfo.maxYawRate);\n      epochs.at(idEpochEnd).yawRate = yawRateExit;\n      return catchUpYawAngle(epochs.at(idEpochEnd), attitudeInfo.maxYawRate);\n    }\n\n    return idEpoch;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateStarCameraGrace.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateStarCameraGrace.cpp\n*\n* @brief Simulates the orientation of the two GRACE satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2009-08-02\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nSimulates \\file{star camera data}{instrument} of the two GRACE satellites.\n\\begin{itemize}\n\\item x: the antenna center pointing to the other satellite.\n\\item y: normal to line of sight and the radial direction.\n\\item z: forms a right handed system.\n\\end{itemize}\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Simulates the orientation of the two GRACE satellites.\n* @ingroup programsGroup */\nclass SimulateStarCameraGrace\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateStarCameraGrace, SINGLEPROCESS, \"Simulates the orientation of the two GRACE satellites.\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateStarCameraGrace::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName    outStarCamera1Name, outStarCamera2Name;\n    FileName    orbit1Name, orbit2Name;\n    Vector3d    center1(1,0,0), center2(1,0,0);\n    std::string choice;\n\n    readConfig(config, \"outputfileStarCamera1\",   outStarCamera1Name, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileStarCamera2\",   outStarCamera2Name, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit1\",         orbit1Name,         Config::MUSTSET,  \"\", \"position define the orientation of the satellite at each epoch\");\n    readConfig(config, \"inputfileOrbit2\",         orbit2Name,         Config::MUSTSET,  \"\", \"position define the orientation of the satellite at each epoch\");\n    if(readConfigChoice(config, \"antennaCenters\", choice,             Config::OPTIONAL, \"\", \"KBR antenna phase center\"))\n    {\n      if(readConfigChoiceElement(config, \"value\", choice, \"\"))\n      {\n        readConfig(config, \"center1X\", center1.x(), Config::DEFAULT,   \"1.4451172588\", \"x-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center1Y\", center1.y(), Config::DEFAULT,  \"-0.0004233040\", \"y-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center1Z\", center1.z(), Config::DEFAULT,   \"0.0022786600\", \"z-coordinate of antenna position in SRF [m] for GRACEA\");\n        readConfig(config, \"center2X\", center2.x(), Config::DEFAULT,   \"1.4443870350\", \"x-coordinate of antenna position in SRF [m] for GRACEB\");\n        readConfig(config, \"center2Y\", center2.y(), Config::DEFAULT,   \"0.0005761203\", \"y-coordinate of antenna position in SRF [m] for GRACEB\");\n        readConfig(config, \"center2Z\", center2.z(), Config::DEFAULT,   \"0.0033040887\", \"z-coordinate of antenna position in SRF [m] for GRACEB\");\n      }\n      if(readConfigChoiceElement(config, \"file\",  choice, \"\"))\n      {\n        FileName fileName;\n        readConfig(config, \"inputAntennaCenters\", fileName, Config::MUSTSET, \"\", \"\");\n        if(!isCreateSchema(config))\n        {\n          Matrix x;\n          readFileMatrix(fileName, x);\n          center1 = Vector3d(x(0,0), x(1,0), x(2,0));\n          center2 = Vector3d(x(3,0), x(4,0), x(5,0));\n        }\n      }\n      endChoice(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    const Rotary3d rotKFrame1 = inverse(Rotary3d(center1, Vector3d(0,1,0)));\n    const Rotary3d rotKFrame2 = inverse(Rotary3d(center2, Vector3d(0,1,0)));\n\n    logStatus<<\"read orbit and generate star camera data\"<<Log::endl;\n    InstrumentFile orbit1File(orbit1Name);\n    InstrumentFile orbit2File(orbit2Name);\n    InstrumentFile::checkArcCount({orbit1File, orbit2File});\n\n    std::list<Arc> arcList1, arcList2;\n    for(UInt arc=0; arc<orbit1File.arcCount(); arc++)\n    {\n      OrbitArc orbit1 = orbit1File.readArc(arc);\n      OrbitArc orbit2 = orbit2File.readArc(arc);\n      Arc::checkSynchronized({orbit1, orbit2});\n\n      StarCameraArc arc1, arc2;\n      for(UInt i=0; i<orbit1.size(); i++)\n      {\n        // Line of sight\n        const Vector3d e12 = normalize(orbit2.at(i).position - orbit1.at(i).position);\n\n        StarCameraEpoch epoch1, epoch2;\n        epoch1.time   = orbit1.at(i).time;\n        epoch2.time   = orbit2.at(i).time;\n        epoch1.rotary = Rotary3d( e12, crossProduct( e12, orbit1.at(i).position)) * rotKFrame1;\n        epoch2.rotary = Rotary3d(-e12, crossProduct(-e12, orbit2.at(i).position)) * rotKFrame2;\n\n        arc1.push_back(epoch1);\n        arc2.push_back(epoch2);\n      }\n      arcList1.push_back(arc1);\n      arcList2.push_back(arc2);\n    }\n\n    logStatus<<\"write star camera data to file <\"<<outStarCamera1Name<<\">\"<<Log::endl;\n    InstrumentFile::write(outStarCamera1Name, arcList1);\n    logStatus<<\"write star camera data to file <\"<<outStarCamera2Name<<\">\"<<Log::endl;\n    InstrumentFile::write(outStarCamera2Name, arcList2);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateStarCameraSentinel1.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateStarCameraSentinel1.cpp\n*\n* @brief simulate star camera data for Sentinel 1A.\n*\n* @author Norbert Zehentner\n* @date 2016-03-23\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates \\file{star camera}{instrument} measurements at each satellite's position for the Sentinel 1A satellite.\nThe \\configFile{inputfileOrbit}{instrument} must contain positions and velocities (see \\program{OrbitAddVelocityAndAcceleration}).\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"files/fileInstrument.h\"\n#ifndef GROOPS_DISABLE_ERFA\n#include <erfa.h>\n#endif\n\n/***** CLASS ***********************************/\n\n/** @brief simulate star camera data for Sentinel 1A.\n* @ingroup programsGroup */\nclass SimulateStarCameraSentinel1\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateStarCameraSentinel1, PARALLEL, \"simulate star camera data for Sentinel 1\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateStarCameraSentinel1::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName orbitName, starCameraName;\n\n    readConfig(config, \"outputfileStarCamera\", starCameraName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"inputfileOrbit\",       orbitName,      Config::MUSTSET, \"\", \"position and velocity defines the orientation of the satellite at each epoch\");\n    if(isCreateSchema(config)) return;\n\n    // StarCamera-Daten erzeugen\n    // -----------------------\n    logStatus<<\"read orbit and generate star camera data\"<<Log::endl;\n    Ellipsoid      ellipsoid(DEFAULT_GRS80_a, DEFAULT_GRS80_f);\n    InstrumentFile orbitFile(orbitName);\n\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc orbit = orbitFile.readArc(arcNo);\n      StarCameraArc arc;\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        // get rotation form inertial to TOD frame\n        Double rc2i[3][3];\n#ifdef GROOPS_DISABLE_ERFA\n        throw(Exception(\"compiled without ERFA library\"));\n#else\n        const Time timeTT = timeGPS2TT(orbit.at(i).time);\n        Double X=0, Y=0, S=0;\n        eraXys00b(2400000.5+timeTT.mjdInt(), timeTT.mjdMod(), &X, &Y, &S);\n        eraC2ixys(X, Y, S, rc2i);\n#endif\n        Matrix R(3,3);\n        R(0,0) = rc2i[0][0]; R(0,1) = rc2i[1][0]; R(0,2) = rc2i[2][0];\n        R(1,0) = rc2i[0][1]; R(1,1) = rc2i[1][1]; R(1,2) = rc2i[2][1];\n        R(2,0) = rc2i[0][2]; R(2,1) = rc2i[1][2]; R(2,2) = rc2i[2][2];\n        Rotary3d rot(R);\n\n        Vector3d pos = orbit.at(i).position;\n        Vector3d vel = orbit.at(i).velocity;\n        const Double omega = 0.729211585e-4;\n        vel.x() +=  omega*pos.y(); // Correct velocity for earth rotation\n        vel.y() += -omega*pos.x();\n        // correct position\n        // compute subsatellite point\n        Angle  L, B;\n        Double h;\n        ellipsoid(pos, L, B, h); // FIXME rot.rotate(pos)???\n        Vector3d posGround = ellipsoid(L, B, 0);\n        Vector3d x         = normalize(vel);\n        Rotary3d rotC2ZD   = Rotary3d(x, crossProduct(x, pos-posGround)) * rot;\n\n        // part 2: rotation from zero-Doppler reference frame to sentinel 1 reference frame (body)\n        ellipsoid(rot.rotate(pos), L, B, h); // compute height\n        const Double   rThetaRef  = 0.513999;  // rad\n        const Double   rAlphaRoll = 9.878564e-7; // rad/meter\n        const Double   rHref      = 711700;\n        const Rotary3d rot2       = rotaryX(Angle(rThetaRef - rAlphaRoll*(h-rHref)));\n\n        StarCameraEpoch epoch;\n        epoch.time   = orbit.at(i).time;\n        epoch.rotary = rotC2ZD*rot2;\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm); // forEach\n\n    // write\n    // -----\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write star camera data to file <\"<<starCameraName<<\">\"<<Log::endl;\n      InstrumentFile::write(starCameraName, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/simulation/simulateStarCameraTerrasar.cpp",
    "content": "/***********************************************/\n/**\n* @file simulateStarCameraTerrasar.cpp\n*\n* @brief Simulate star camera data for Terrasar.\n*\n* @author Torsten Mayer-Guerr\n* @date 2024-06-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program simulates \\configFile{outputfileStarCamera}{instrument} measurements at each satellite's position for the Terrasar satellite.\nThe \\configFile{inputfileOrbit}{instrument} must contain positions and velocities (see \\program{OrbitAddVelocityAndAcceleration}).\nThe resulting rotation matrices rotate from satellite frame to inertial frame.\n\nH. Fiedler, E. Boerner, J. Mittermayer and G. Krieger,\nTotal zero Doppler Steering-a new method for minimizing the Doppler centroid,\nin IEEE Geoscience and Remote Sensing Letters, vol. 2, no. 2, pp. 141-145, April 2005, \\url{https://www.doi.org/10.1109/LGRS.2005.844591}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"base/kepler.h\"\n#include \"files/fileInstrument.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief simulate star camera data for Terrasar.\n* @ingroup programsGroup */\nclass SimulateStarCameraTerrasar\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SimulateStarCameraTerrasar, PARALLEL, \"simulate star camera data for Terrasar\", Simulation, Instrument)\n\n/***********************************************/\n\nvoid SimulateStarCameraTerrasar::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    FileName fileNameOrbit, fileNameStarCamera;\n\n    readConfig(config, \"outputfileStarCamera\", fileNameStarCamera, Config::MUSTSET, \"\", \"rotation from satellite to inertial frame (x: along, y: cross, z: nadir)\");\n    readConfig(config, \"inputfileOrbit\",       fileNameOrbit,      Config::MUSTSET, \"\", \"position and velocity defines the orientation of the satellite at each epoch\");\n    if(isCreateSchema(config)) return;\n\n    // StarCamera-Daten erzeugen\n    // -----------------------\n    logStatus<<\"read orbit and generate star camera data\"<<Log::endl;\n    InstrumentFile orbitFile(fileNameOrbit);\n    std::vector<Arc> arcList(orbitFile.arcCount());\n    Parallel::forEach(arcList, [&](UInt arcNo)\n    {\n      OrbitArc orbit = orbitFile.readArc(arcNo);\n      StarCameraArc arc;\n      for(UInt i=0; i<orbit.size(); i++)\n      {\n        // Argument of latitude of satellite\n        const Vector3d z = normalize(crossProduct(orbit.at(i).position, orbit.at(i).velocity));\n        const Vector3d x = normalize(crossProduct(Vector3d(0,0,1), z));\n        const Vector3d y = crossProduct(z, x);\n        const Double   u = atan2(inner(orbit.at(i).position, y), inner(orbit.at(i).position, x));\n\n        Kepler k(orbit.at(i).time, orbit.at(i).position, orbit.at(i).velocity);\n        const Double N   = 167./11.; // 86400/std::sqrt(std::pow(k.a, 3)/k.GM);  // number of revolutions per day\n        const Double yaw = std::atan((std::sin(k.i)*std::cos(u))/(N-std::cos(k.i)));\n\n        StarCameraEpoch epoch;\n        epoch.time   = orbit.at(i).time;\n        epoch.rotary = Rotary3d(normalize(orbit.at(i).velocity), -z) * rotaryZ(Angle(yaw));\n        arc.push_back(epoch);\n      }\n      return arc;\n    }, comm); // forEach\n\n    if(Parallel::isMaster(comm))\n    {\n      logStatus<<\"write star camera data to file <\"<<fileNameStarCamera<<\">\"<<Log::endl;\n      InstrumentFile::write(fileNameStarCamera, arcList);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/slr/slrProcessing.cpp",
    "content": "/***********************************************/\n/**\n* @file slrProcessing.cpp\n*\n* @brief Satellite Laser Ranging (SLR) processing.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-26\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program processes SLR normal point or full rate observations. It calculates the linearized observation equations,\naccumulates them into a system of normal equations and solves it.\n\nTo calculate observation equations from the passes, the model parameters or unknown parameters need to be\ndefined beforehand. These unknown parameters can be chosen arbitrarily by the user with an adequate list of defined\n\\configClass{parametrization}{slrParametrizationType}.\nSome of the \\configClass{parametrization}{slrParametrizationType} also include a priori models.\n\nLastly it is required to define the process flow of the SLR processing. This is accomplished\nwith a list of \\configClass{processingSteps}{slrProcessingStepType}.\nEach step is processed consecutively. Some steps allow the selection of parameters, station, or satellites,\nwhich affects all subsequent steps.\n\nThe \\configClass{timeSeries}{timeSeriesType} is used to precompute Earth rotation and station displacements\nwith a uniform sampling. In a second step these values are interpolated to the observation epochs.\nA sampling of about 10 minutes should be adequate.\n\nIt should be noted that GROOPS uses GPS time format, but normal point/full rate data files and CPF files, provided by ILRS data centers\nare given in UTC time format.\n%See also \\program{SlrSimulation}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrStationGenerator/slrStationGenerator.h\"\n#include \"slr/slrSatelliteGenerator/slrSatelliteGenerator.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Satellite Laser Ranging (SLR) processing.\n* @ingroup programsGroup */\nclass SlrProcessing\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(SlrProcessing, SINGLEPROCESS, \"Satellite Laser Ranging (SLR) processing\", Slr)\n\n/***********************************************/\n\nvoid SlrProcessing::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    TimeSeriesPtr            timeSeries;\n    SlrSatelliteGeneratorPtr satelliteGenerator;\n    SlrStationGeneratorPtr   stationGenerator;\n    SlrParametrizationPtr    slrParametrization;\n    EarthRotationPtr         earthRotation;\n    SlrProcessingStepPtr     processingSteps;\n\n    readConfig(config, \"timeSeries\",      timeSeries,          Config::MUSTSET, \"\",  \"defines station movements and earth rotation epochs\");\n    readConfig(config, \"satellite\",       satelliteGenerator,  Config::MUSTSET, \"\",  \"satellites\");\n    readConfig(config, \"station\",         stationGenerator,    Config::MUSTSET, \"\",  \"ground station network\");\n    readConfig(config, \"earthRotation\",   earthRotation,       Config::MUSTSET, \"\",  \"apriori earth rotation\");\n    readConfig(config, \"parametrization\", slrParametrization,  Config::MUSTSET, \"\",  \"models and parameters\");\n    readConfig(config, \"processingStep\",  processingSteps,     Config::MUSTSET, \"\",  \"steps are processed consecutively\");\n    if(isCreateSchema(config)) return;\n\n    // ============================\n\n    // init the SLR system\n    // --------------------\n    logInfo<<\"Init SLR\"<<Log::endl;\n    SlrPtr slr = std::make_shared<Slr>();\n    slr->init(timeSeries->times(), satelliteGenerator, stationGenerator, earthRotation, slrParametrization);\n//     stationGenerator->preprocessing(slr.get(), comm);\n    satelliteGenerator = nullptr;\n    stationGenerator   = nullptr;\n    slrParametrization = nullptr;\n    earthRotation      = nullptr;\n    logInfo<<\"summary:\"<<Log::endl;\n    logInfo<<\"  satellites:   \"<<std::count_if(slr->satellites.begin(), slr->satellites.end(), [](auto s) {return s->useable();})<<Log::endl;\n    logInfo<<\"  stations:     \"<<std::count_if(slr->stations.begin(),   slr->stations.end(),   [](auto s) {return s->useable();})<<Log::endl;\n    if(!std::any_of(slr->satellites.begin(), slr->satellites.end(), [](auto s){return s->useable();}))\n    {\n      logWarningOnce<<\"no useable satellites\"<<Log::endl;\n      return;\n    }\n    if(!std::any_of(slr->stations.begin(), slr->stations.end(), [](auto s){return s->useable();}))\n    {\n      logWarningOnce<<\"no useable stations\"<<Log::endl;\n      return;\n    }\n\n    // count observations\n    // ------------------\n    UInt countObs    = 0;\n    UInt countPasses = 0;\n    for(auto &station : slr->stations)\n      for(auto &obsSat : station->observations)\n        for(auto &obs : obsSat)\n        {\n          countObs += obs->observations.rows();\n          countPasses++;\n        }\n    logInfo<<\"  observations: \"<<countObs<<Log::endl;\n    logInfo<<\"  passes:       \"<<countPasses<<Log::endl;\n\n    // Processing steps\n    // ----------------\n    SlrProcessingStep::State state(slr);\n    processingSteps->process(state);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/fileConvert.cpp",
    "content": "/***********************************************/\n/**\n* @file fileConvert.cpp\n*\n* @brief Converts GROOPS file between different file formats (ASCII, XML, binary).\n*\n* @author Sebastian Strasser\n* @date 2016-02-16\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nConverts GROOPS file between different file formats (ASCII, XML, JSON, binary),\nsee \\reference{file formats}{general.fileFormat} for details.\nWith an additional extension of '.gz' files are directly compressed and uncompressed.\nIt prints also some information about the content.\nTherefore it can be used to get an idea about the content of binary files.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/fileArchive.h\"\n#include \"files/fileAdmittance.h\"\n#include \"files/fileArcList.h\"\n#include \"files/fileDoodsonEarthOrientationParameter.h\"\n#include \"files/fileDoodsonHarmonic.h\"\n#include \"files/fileEarthOrientationParameter.h\"\n#include \"files/fileEarthTide.h\"\n#include \"files/fileGnssAntennaDefinition.h\"\n#include \"files/fileGnssReceiverDefinition.h\"\n#include \"files/fileGnssSignalBias.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileGriddedData.h\"\n#include \"files/fileGriddedDataTimeSeries.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileMeanPolarMotion.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"files/fileOceanPoleTide.h\"\n#include \"files/fileParameterName.h\"\n#include \"files/filePolygon.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileSatelliteModel.h\"\n#include \"files/fileSphericalHarmonics.h\"\n#include \"files/fileStringTable.h\"\n#include \"files/fileTideGeneratingPotential.h\"\n#include \"files/fileTimeSplinesGravityfield.h\"\n#include \"files/fileVariationalEquation.h\"\n#include \"misc/miscGriddedData.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Converts GROOPS file between different file formats (ASCII, XML, binary).\n* @ingroup programsGroup */\nclass FileConvert\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FileConvert, SINGLEPROCESS, \"Converts GROOPS file between different file formats (ASCII, XML, JSON, binary).\",\n                        System, Instrument, VariationalEquation, DoodsonHarmonics, Grid, Matrix, PotentialCoefficients, TimeSplines)\n\n/***********************************************/\n\nvoid FileConvert::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameInput, fileNameOutput;\n\n    renameDeprecatedConfig(config, \"outputFile\", \"outputfile\", date2time(2020, 8, 20));\n    renameDeprecatedConfig(config, \"inputFile\",  \"inputfile\",  date2time(2020, 8, 20));\n\n    readConfig(config, \"outputfile\", fileNameOutput, Config::OPTIONAL, \"\", \"GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)\");\n    readConfig(config, \"inputfile\",  fileNameInput,  Config::MUSTSET,  \"\", \"GROOPS formats: .xml, .txt, .json, .dat (optional with additional .gz)\");\n    if(isCreateSchema(config)) return;\n\n    // =============================================\n\n    logStatus<<\"Converting from <\"<<fileNameInput<<\"> to <\"<< fileNameOutput<<\">\"<<Log::endl;\n    std::string type;\n    {\n      InFileArchive infile(fileNameInput, \"\"/*arbitrary type*/, 25000101);\n      logInfo<<\"  type    = \"<<infile.type()<<Log::endl;\n      logInfo<<\"  version = \"<<infile.version()<<Log::endl;\n      type = infile.type();\n    }\n\n    if(type.empty() && !fileNameOutput.empty())\n      throw(Exception(\"Not a GROOPS file or with very old format without type information\"));\n\n    // =============================================\n\n    if(type == FILE_INSTRUMENT_TYPE)\n    {\n      InstrumentFile file(fileNameInput);\n      const Epoch::Type type = file.getType();\n      logInfo<<\"  instr   = \"<<Epoch::getTypeName(type)<<\" (\"<<static_cast<Int>(type)<<\")\"<<Log::endl;\n      std::vector<Arc> arcList(file.arcCount());\n      for(UInt arcNo=0; arcNo<file.arcCount(); arcNo++)\n        arcList.at(arcNo) = file.readArc(arcNo);\n      Arc::printStatistics(arcList);\n      if(!fileNameOutput.empty())\n        InstrumentFile::write(fileNameOutput, arcList);\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_VARIATIONALEQUATION_TYPE)\n    {\n      FileVariationalEquation file(fileNameInput);\n      if(file.satellite())\n        logInfo<<\"  name    = \"<<file.satellite()->satelliteName<<Log::endl;\n      logInfo<<\"  arcs    = \"<<file.arcCount()<<Log::endl;\n      if(!fileNameOutput.empty())\n      {\n        std::vector<VariationalEquationArc> arcs(file.arcCount());\n        for(UInt arcNo=0; arcNo<arcs.size(); arcNo++)\n          arcs.at(arcNo) = file.readArc(arcNo);\n        writeFileVariationalEquation(fileNameOutput, file.satellite(), arcs);\n      }\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_DOODSONHARMONIC_TYPE)\n    {\n      DoodsonHarmonic x;\n      readFileDoodsonHarmonic(fileNameInput,  x);\n      for(UInt i=0; i<x.doodson.size(); i++)\n        logInfo<<\"  \"<<x.doodson.at(i).code()<<\" (\"<<x.doodson.at(i).name()<<\")\"<<Log::endl;\n      if(!fileNameOutput.empty())\n        writeFileDoodsonHarmonic(fileNameOutput, x);\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_MATRIX_TYPE)\n    {\n      Matrix x;\n      readFileMatrix(fileNameInput,  x);\n      std::string type = \"matrix\";\n      if(x.getType() == Matrix::SYMMETRIC)\n        type += \"Symmetric\"s + (x.isUpper() ? \"Upper\"s : \"Lower\"s);\n      else if(x.getType() == Matrix::TRIANGULAR)\n        type += \"Triangular\"s + (x.isUpper() ? \"Upper\"s : \"Lower\"s);\n      logInfo<<\"  \"<<type<<\"(\"<<x.rows()<<\" x \"<<x.columns()<<\")\"<<Log::endl;\n      if(!fileNameOutput.empty())\n        writeFileMatrix(fileNameOutput, x);\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_GRIDDEDDATA_TYPE || type == \"gridRectangular\")\n    {\n      GriddedData x;\n      readFileGriddedData(fileNameInput,  x);\n      MiscGriddedData::printStatistics(x);\n      if(!fileNameOutput.empty())\n        writeFileGriddedData(fileNameOutput, x);\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_GRIDDEDDATATIMESERIES_TYPE)\n    {\n      InFileGriddedDataTimeSeries file(fileNameInput);\n      logInfo<<\"  spline degree = \"<<file.splineDegree()<<Log::endl;\n      logInfo<<\"  node count    = \"<<file.nodeCount()<<Log::endl;\n      logInfo<<\"  data columns  = \"<<file.dataCount()<<Log::endl;\n      logInfo<<\"  sampling      = \"<<medianSampling(file.times()).mjd()<<\" days\"<<Log::endl;\n      logInfo<<\"  interval      = [\"<<file.times().front().dateTimeStr()<<\", \"<<file.times().back().dateTimeStr()<<\"]\"<<Log::endl;\n      MiscGriddedData::printStatistics(file.grid());\n\n      if(!fileNameOutput.empty())\n      {\n        std::vector<Matrix> data(file.nodeCount());\n        for(UInt i=0; i<file.nodeCount(); i++)\n          data.at(i) = file.data(i);\n        writeFileGriddedDataTimeSeries(fileNameOutput, file.splineDegree(), file.times(), file.grid(), data);\n      }\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_TIMESPLINESGRAVITYFIELD_TYPE)\n    {\n      InFileTimeSplinesGravityfield file(fileNameInput);\n      logInfo<<\"  spline degree = \"<<file.splineDegree()<<Log::endl;\n      logInfo<<\"  node count    = \"<<file.nodeCount()<<Log::endl;\n      logInfo<<\"  sampling      = \"<<medianSampling(file.times()).mjd()<<\" days\"<<Log::endl;\n      logInfo<<\"  interval      = [\"<<file.times().front().dateTimeStr()<<\", \"<<file.times().back().dateTimeStr()<<\"]\"<<Log::endl;\n\n      if(!fileNameOutput.empty())\n      {\n        Double GM = DEFAULT_GM, R = DEFAULT_R;\n        std::vector<Matrix> cnm(file.nodeCount());\n        std::vector<Matrix> snm(file.nodeCount());\n        for(UInt i=0; i<file.nodeCount(); i++)\n        {\n          SphericalHarmonics harm = file.sphericalHarmonics(i);\n          GM        = harm.GM();\n          R         = harm.R();\n          cnm.at(i) = harm.cnm();\n          snm.at(i) = harm.snm();\n        }\n        writeFileTimeSplinesGravityfield(fileNameOutput, GM, R, file.splineDegree(), file.times(), cnm, snm);\n      }\n      return;\n    }\n\n    // =============================================\n\n    if(type == FILE_TIMESPLINESCOVARIANCE_TYPE)\n    {\n      InFileTimeSplinesCovariance file(fileNameInput);\n      logInfo<<\"  GM            = \"<<file.GM()<<Log::endl;\n      logInfo<<\"  R             = \"<<file.R()<<Log::endl;\n      logInfo<<\"  minDegree     = \"<<file.minDegree()<<Log::endl;\n      logInfo<<\"  maxDegree     = \"<<file.maxDegree()<<Log::endl;\n      logInfo<<\"  spline degree = \"<<file.splineDegree()<<Log::endl;\n      logInfo<<\"  node count    = \"<<file.nodeCount()<<Log::endl;\n      logInfo<<\"  sampling      = \"<<medianSampling(file.times()).mjd()<<\" days\"<<Log::endl;\n      logInfo<<\"  interval      = [\"<<file.times().front().dateTimeStr()<<\", \"<<file.times().back().dateTimeStr()<<\"]\"<<Log::endl;\n\n      if(!fileNameOutput.empty())\n      {\n        std::vector<Matrix> C(file.nodeCount());\n        for(UInt i=0; i<file.nodeCount(); i++)\n          C.at(i) = file.covariance(i);\n        writeFileTimeSplinesCovariance(fileNameOutput, file.GM(), file.R(), file.minDegree(), file.maxDegree(), file.splineDegree(), file.times(), C);\n      }\n      return;\n    }\n\n    // =============================================\n\n    if(fileNameOutput.empty())\n      return;\n\n    // =============================================\n\n    // Standard file types\n    // -------------------\n    if(type == FILE_ADMITTANCE_TYPE)\n    {\n      Admittance x;\n      readFileAdmittance (fileNameInput,  x);\n      writeFileAdmittance(fileNameOutput, x);\n    }\n    else if(type == FILE_ARCLIST_TYPE)\n    {\n      std::vector<UInt> arcsInterval;\n      std::vector<Time> timesInterval;\n      readFileArcList (fileNameInput,  arcsInterval, timesInterval);\n      writeFileArcList(fileNameOutput, arcsInterval, timesInterval);\n    }\n    else if(type == FILE_DOODSONEARTHORIENTATIONPARAMETER_TYPE)\n    {\n      DoodsonEop x;\n      readFileDoodsonEarthOrientationParameter (fileNameInput,  x);\n      writeFileDoodsonEarthOrientationParameter(fileNameOutput, x);\n    }\n    // else if(type == FILE_DOODSONHARMONIC_TYPE) see above\n    else if(type == FILE_EARTHORIENTATIONPARAMETER_TYPE)\n    {\n      Matrix x;\n      readFileEarthOrientationParameter (fileNameInput,  x);\n      writeFileEarthOrientationParameter(fileNameOutput, x);\n    }\n    else if(type == FILE_EARTHTIDE_TYPE)\n    {\n      Matrix kReal, kImag, kPlus;\n      Matrix doodson20, doodson21, doodson22;\n      Vector ampIp20, ampOp20, ampIp21, ampOp21, amp22;\n      Double h2_0, h2_2, l2_0, l2_2, l21_1, l22_1, h21_imag, l21_imag, h22_imag, l22_imag, h3, l3;\n      Matrix deformationArg21, deformationArg20;\n      Vector dR21_ip, dR21_op, dR20_ip, dR20_op, dT21_ip, dT21_op, dT20_ip, dT20_op;\n      readFileEarthTide(fileNameInput, kReal, kImag, kPlus, doodson20, doodson21, doodson22,\n                        ampIp20, ampOp20, ampIp21, ampOp21, amp22, h2_0, h2_2, l2_0, l2_2, l21_1, l22_1, h21_imag, l21_imag, h22_imag, l22_imag, h3, l3,\n                        deformationArg21, deformationArg20, dR21_ip, dR21_op, dR20_ip, dR20_op, dT21_ip, dT21_op, dT20_ip, dT20_op);\n      writeFileEarthTide(fileNameOutput, kReal, kImag, kPlus, doodson20, doodson21, doodson22,\n                        ampIp20, ampOp20, ampIp21, ampOp21, amp22, h2_0, h2_2, l2_0, l2_2, l21_1, l22_1, h21_imag, l21_imag, h22_imag, l22_imag, h3, l3,\n                        deformationArg21, deformationArg20, dR21_ip, dR21_op, dR20_ip, dR20_op, dT21_ip, dT21_op, dT20_ip, dT20_op);\n    }\n    else if(type == FILE_GNSSANTENNADEFINITION_TYPE)\n    {\n      std::vector<GnssAntennaDefinitionPtr> x;\n      readFileGnssAntennaDefinition (fileNameInput,  x);\n      writeFileGnssAntennaDefinition(fileNameOutput, x);\n    }\n    else if(type == FILE_GNSSSIGNALBIAS_TYPE)\n    {\n      GnssSignalBias x;\n      readFileGnssSignalBias (fileNameInput,  x);\n      writeFileGnssSignalBias(fileNameOutput, x);\n    }\n    else if((type == FILE_PLATFORM_TYPE) || (type == \"stationInfo\"))\n    {\n      Platform x;\n      readFilePlatform (fileNameInput,  x);\n      writeFilePlatform(fileNameOutput, x);\n    }\n    // else if(type == FILE_GRIDRECTANGULAR_TYPE)  see above\n    // else if(type == FILE_MATRIX_TYPE)  see above\n    else if(type == FILE_MEANPOLARMOTION_TYPE)\n    {\n      MeanPolarMotion x;\n      readFileMeanPolarMotion (fileNameInput,  x);\n      writeFileMeanPolarMotion(fileNameOutput, x);\n    }\n    else if(type == FILE_NORMALEQUATION_TYPE)\n    {\n      throw(Exception(\"Conversion of FILE_NORMALEQUATION_TYPE not implemented.\"));\n    }\n    else if(type == FILE_OCEANPOLETIDE_TYPE)\n    {\n      SphericalHarmonics harmReal, harmImag;\n      readFileOceanPoleTide (fileNameInput,  harmReal, harmImag);\n      writeFileOceanPoleTide(fileNameOutput, harmReal, harmImag);\n    }\n    else if(type == FILE_PARAMETERNAME_TYPE)\n    {\n      std::vector<ParameterName> x;\n      readFileParameterName (fileNameInput,  x);\n      writeFileParameterName(fileNameOutput, x);\n    }\n    else if(type == FILE_POLYGON_TYPE)\n    {\n      std::vector<Polygon> x;\n      readFilePolygon (fileNameInput,  x);\n      writeFilePolygon(fileNameOutput, x);\n    }\n    // else if(type == FILE_INSTRUMENT_TYPE)  see above\n    else if(type == FILE_SATELLITEMODEL_TYPE)\n    {\n      std::vector<SatelliteModelPtr> x;\n      readFileSatelliteModel (fileNameInput,  x);\n      writeFileSatelliteModel(fileNameOutput, x);\n    }\n    else if(type == FILE_POTENTIALCOEFFICIENTS_TYPE)\n    {\n      SphericalHarmonics x;\n      readFileSphericalHarmonics (fileNameInput,  x);\n      writeFileSphericalHarmonics(fileNameOutput, x);\n    }\n    // else if(type == FILE_STRINGLIST_TYPE)  not really GROOPS format\n    else if(type == FILE_TIDEGENERATINGPOTENTIAL_TYPE)\n    {\n      TideGeneratingPotential x;\n      readFileTideGeneratingPotential (fileNameInput,  x);\n      writeFileTideGeneratingPotential(fileNameOutput, x);\n    }\n    // else if(type == FILE_TIMESPLINESGRAVITYFIELD_TYPE) see above\n    // else if(type == FILE_TIMESPLINESCOVARIANCE_TYPE)   see above\n    // else if(type == FILE_VALUEGRID_TYPE)               see above\n    // else if(type == FILE_VARIATIONALEQUATION_TYPE)     see above\n    else\n      throw(Exception(\"Conversion of file type not implemented.\"));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n"
  },
  {
    "path": "source/programs/system/fileCreateDirectories.cpp",
    "content": "/***********************************************/\n/**\n* @file fileCreateDirectories.cpp\n*\n* @brief Creates the directory and parent directories as needed.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-12\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreates the directory and parent directories as needed.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Creates the directory and parent directories as needed.\n* @ingroup programsGroup */\nclass FileCreateDirectories\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FileCreateDirectories, SINGLEPROCESS, \"Creates the directory and parent directories as needed.\", System)\n\n/***********************************************/\n\nvoid FileCreateDirectories::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName> fileNames;\n\n    readConfig(config, \"directory\", fileNames, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    for(UInt i=0; i<fileNames.size(); i++)\n    {\n      logStatus<<\"Create directory <\"<<fileNames.at(i)<<\">\"<<Log::endl;\n      if(!System::createDirectories(fileNames.at(i)))\n        throw(Exception(\"Cannot create directory <\"+fileNames.at(i).str()+\">\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/fileMove.cpp",
    "content": "/***********************************************/\n/**\n* @file fileMove.cpp\n*\n* @brief Move/rename file or directory.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-05-31\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nMove/rename file or directory. If the \\config{outputfile} is an existing directory\nthe \\config{inputfile} is moved into it.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Move/rename file or directory.\n* @ingroup programsGroup */\nclass FileMove\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FileMove, SINGLEPROCESS, \"Move/rename file or directory.\", System)\n\n/***********************************************/\n\nvoid FileMove::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileNameOld, fileNameNew;\n\n    readConfig(config, \"outputfile\", fileNameNew, Config::MUSTSET, \"\", \"target name or directory for the move/rename\");\n    readConfig(config, \"inputfile\",  fileNameOld, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"Move file <\"<<fileNameOld<<\"> to <\"<<fileNameNew<<\">\"<<Log::endl;\n    if(!System::move(fileNameOld, fileNameNew))\n      logWarning<<\"Unable to move/rename file <\"<<fileNameOld<<\">\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/fileRemove.cpp",
    "content": "/***********************************************/\n/**\n* @file fileRemove.cpp\n*\n* @brief Remove files or directories.\n*\n* @author Torsten Mayer-Guerr\n* @date 2018-05-12\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRemove files or directories.\nDeletes also the content recursivley if one of \\config{files} is a directory.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Remove files or directories.\n* @ingroup programsGroup */\nclass FileRemove\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FileRemove, SINGLEPROCESS, \"Remove files or directories.\", System)\n\n/***********************************************/\n\nvoid FileRemove::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    std::vector<FileName> fileNames;\n\n    readConfig(config, \"files\", fileNames, Config::MUSTSET, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    for(UInt i=0; i<fileNames.size(); i++)\n      if(!fileNames.at(i).empty())\n      {\n        logStatus<<\"Remove file <\"<<fileNames.at(i)<<\">\"<<Log::endl;\n        if(!System::remove(fileNames.at(i)))\n          logWarning<<\"Unable to remove file <\"<<fileNames.at(i)<<\">.\"<<Log::endl;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/fileTextCreate.cpp",
    "content": "/***********************************************/\n/**\n* @file fileTextCreate.cpp\n*\n* @brief Create text file.\n*\n* @author Torsten Mayer-Guerr\n* @date 2023-05-31\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nCreate text \\config{outputfile} containing \\config{line}s.\nThis program can be a powerful tool,\nif the \\config{line} is repeated with a \\configClass{loop}{loopType}\ntogether with the \\reference{text parser}{general.parser:text}.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/file.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Create text file.\n* @ingroup programsGroup */\nclass FileTextCreate\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(FileTextCreate, SINGLEPROCESS, \"Create text file.\", System)\n\n/***********************************************/\n\nvoid FileTextCreate::run(Config &config, Parallel::CommunicatorPtr /*comm*/)\n{\n  try\n  {\n    FileName fileName;\n    std::vector<std::string> lines;\n\n    readConfig(config, \"outputfile\", fileName, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"line\",       lines,    Config::OPTIONAL, \"\", \"\");\n    if(isCreateSchema(config)) return;\n\n    logStatus<<\"Create <\"<<fileName<<\"> with \"<<lines.size()<<\" lines\"<<Log::endl;\n    OutFile file(fileName);\n    for(auto &line : lines)\n      file<<line<<std::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/groupPrograms.cpp",
    "content": "/***********************************************/\n/**\n* @file groupPrograms.cpp\n*\n* @brief Runs programs in group and can catch errors.\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2017-09-01\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRuns \\config{program}s in a group, which can be used to structure a config file.\nIf \\config{catchErrors} is enabled and an error occurs, the remaining \\config{program}s\nare skipped and execution continues with \\config{errorProgram}s, in case any are defined.\nOtherwise an exception is thrown.\n\nThe \\config{silently} option disables the screen ouput of the \\config{program}s.\nWith \\config{outputfileLog} a log file is written for this group additional to a global log file.\nThis might be helpful within \\program{LoopPrograms} with parallel iterations.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief  Runs programs in group and can catch errors.\n* @ingroup programsGroup */\nclass GroupPrograms\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(GroupPrograms, PARALLEL, \"Runs programs in group and can catch errors.\", System)\nGROOPS_RENAMED_PROGRAM(GroupProgramme, GroupPrograms, date2time(2020, 6, 3))\n\n/***********************************************/\n\nvoid GroupPrograms::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  Log::GroupPtr groupPtr;\n  try {Parallel::broadCastExceptions(comm, [&](Parallel::CommunicatorPtr comm)\n  {\n    Bool          silently;\n    ProgramConfig programs, errorPrograms;\n    Bool          continueAfterError = FALSE;\n    FileName      fileNameLog;\n\n    renameDeprecatedConfig(config, \"programme\", \"program\", date2time(2020, 6, 3));\n\n    readConfig(config, \"outputfileLog\", fileNameLog, Config::OPTIONAL, \"\",  \"additional log file\");\n    readConfig(config, \"silently\",      silently,    Config::DEFAULT,  \"0\", \"without showing the output.\");\n    readConfig(config, \"program\",       programs,    Config::OPTIONAL, \"\",  \"\");\n    if(readConfigSequence(config, \"catchErrors\", Config::OPTIONAL, \"\", \"\"))\n    {\n      continueAfterError = TRUE;\n      readConfig(config, \"errorProgram\", errorPrograms, Config::OPTIONAL, \"\", \"executed if an error occured\");\n      endSequence(config);\n    }\n    if(isCreateSchema(config)) return;\n\n    // -------------------------------\n\n    Parallel::barrier(comm);\n    groupPtr = Log::group(Parallel::isMaster(comm), silently);\n    Log::setLogFile(fileNameLog);\n    Log::currentLogFileOnly(TRUE);\n    if(Parallel::size(comm) > 1)\n      logStatus<<\"=== Starting GROOPS subgroup with \"<<Parallel::size(comm)<<\" processes ===\"<<Log::endl;\n    else\n      logStatus<<\"=== Starting GROOPS subgroup ===\"<<Log::endl;\n    Log::currentLogFileOnly(FALSE);\n    Parallel::barrier(comm);\n\n    try\n    {\n      Parallel::broadCastExceptions(comm, [&](Parallel::CommunicatorPtr comm)\n      {\n        VariableList varList;\n        programs.run(varList, comm);\n      });\n    }\n    catch(std::exception &e)\n    {\n      if(!continueAfterError || Parallel::isExternal(e))\n        throw;\n      if(Parallel::isMaster(comm))\n        logError<<e.what()<<\"  continue with error programs...\"<<Log::endl;\n      VariableList varList;\n      errorPrograms.run(varList, comm);\n    }\n\n    Parallel::barrier(comm);\n    Log::currentLogFileOnly(TRUE);\n    logStatus<<\"=== Finished GROOPS subgroup ===\"<<Log::endl;\n  });}\n  catch(std::exception &e)\n  {\n    if(groupPtr)\n    {\n      Log::currentLogFileOnly(TRUE);\n      if(Parallel::isMaster(comm))\n      {\n        logError<<\"****** Error ******\"<<Log::endl;\n        logError<<e.what()<<Log::endl;\n        logStatus<<\"=== Finished GROOPS subgroup with error ===\"<<Log::endl;\n      }\n    }\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/ifPrograms.cpp",
    "content": "/***********************************************/\n/**\n* @file ifPrograms.cpp\n*\n* @brief Runs programs if condition is met.\n*\n* @author Andreas Kvas\n* @date 2017-01-04\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nRuns a list of \\config{program}s if a \\configClass{condition}{conditionType} is met.\nOtherwise \\config{elseProgram}s are executed.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/condition/condition.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief  Runs programs if condition is met.\n* @ingroup programsGroup */\nclass IfPrograms\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(IfPrograms, PARALLEL, \"Runs programs if condition is met.\", System)\nGROOPS_RENAMED_PROGRAM(IfProgramme, IfPrograms, date2time(2020, 6, 3))\n\n/***********************************************/\n\nvoid IfPrograms::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    ConditionPtr  conditionPtr;\n    ProgramConfig programs, elsePrograms;\n\n    renameDeprecatedConfig(config, \"programme\", \"program\", date2time(2020, 6, 3));\n\n    readConfig(config, \"condition\",   conditionPtr, Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"program\",     programs,     Config::OPTIONAL, \"\", \"executed if condition evaluates to true\");\n    readConfig(config, \"elseProgram\", elsePrograms, Config::OPTIONAL, \"\", \"executed if condition evaluates to false\");\n    if(isCreateSchema(config)) return;\n\n    VariableList varList;\n    if(conditionPtr->condition(varList))\n    {\n      logInfo<<\"  condition is true.\"<<Log::endl;\n      programs.run(varList, comm);\n    }\n    else\n    {\n      logInfo<<\"  condition is false.\"<<Log::endl;\n      elsePrograms.run(varList, comm);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/loopPrograms.cpp",
    "content": "/***********************************************/\n/**\n* @file loopPrograms.cpp\n*\n* @brief Runs programs multiple times.\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2017-02-05\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nThis program runs a list of programs in a \\configClass{loop}{loopType}.\n\nIf \\config{continueAfterError}=\\verb|yes| and an error occurs, the remaining programs in the current iteration\nare skipped and the loop continues with the next iteration. Otherwise an exception is thrown.\n\nIf this program is executed on multiple processing nodes, the iterations can be computed in parallel,\nsee \\reference{parallelization}{general.parallelization}. The first process serves as load balancer\nand the other processes are assigned to iterations according to \\config{processCountPerIteration}.\nFor example, running a loop containing three iterations on 13 processes with \\config{processCountPerIteration}=\\verb|4|,\nruns the three iterations in parallel, with each iteration being assigned four processes.\nWith \\config{parallelLog}=\\verb|yes| all processes write output to screen and the log file.\nAs the output can be quite confusing in this case, running \\program{GroupPrograms} with an extra \\config{outputfileLog}\nfor each iteration (use the loop variables for the name of the log files) might be helpful.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"classes/loop/loop.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief  Runs programs multiple times.\n* @ingroup programsGroup */\nclass LoopPrograms\n{\npublic:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(LoopPrograms, PARALLEL, \"Runs programs multiple times.\", System)\nGROOPS_RENAMED_PROGRAM(LoopProgramme, LoopPrograms, date2time(2020, 6, 3))\n\n/***********************************************/\n\nvoid LoopPrograms::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    LoopPtr       loopPtr;\n    Bool          continueAfterError;\n    UInt          processCount;\n    Bool          parallelLog;\n    ProgramConfig programs;\n\n    renameDeprecatedConfig(config, \"programme\",     \"program\", date2time(2020, 6, 3));\n    renameDeprecatedConfig(config, \"parallelLoops\", \"processCountPerLoopStep\", date2time(2020, 12, 28));\n    renameDeprecatedConfig(config, \"processCountPerLoopStep\", \"processCountPerIteration\", date2time(2020, 1, 14));\n\n    readConfig(config, \"loop\",                     loopPtr,            Config::MUSTSET,  \"\",  \"subprograms are called for every iteration\");\n    readConfig(config, \"continueAfterError\",       continueAfterError, Config::DEFAULT,  \"0\", \"continue with next iteration after error, otherwise throw exception\");\n    readConfig(config, \"processCountPerIteration\", processCount,       Config::DEFAULT,  \"0\", \"0: use all processes for each iteration\");\n    readConfig(config, \"parallelLog\",              parallelLog,        Config::DEFAULT,  \"1\", \"write to screen/log file from all processing nodes in parallelized loops\");\n    readConfig(config, \"program\",                  programs,           Config::OPTIONAL, \"\",  \"\");\n    if(isCreateSchema(config)) return;\n\n    VariableList varList;\n    if(!loopPtr->iteration(varList))\n      return;\n\n    // Every process executes every iteration\n    // --------------------------------------\n    if((processCount == 0) || (processCount+1 >= Parallel::size(comm)) || (Parallel::size(comm) < 3))\n    {\n      Log::Timer timer(loopPtr->count());\n      do\n      {\n        logStatus<<\"=== \"<<loopPtr->index()<<\". loop ===\"<<Log::endl;\n        timer.loopStep(loopPtr->index()-1);\n        try\n        {\n          Parallel::broadCastExceptions(comm, [&](Parallel::CommunicatorPtr comm)\n          {\n            auto varListTmp = varList;\n            programs.run(varListTmp, comm);\n          });\n        }\n        catch(std::exception &e)\n        {\n          if(!continueAfterError || Parallel::isExternal(e))\n            throw;\n          if(Parallel::isMaster(comm))\n            logError<<e.what()<<\"  continue...\"<<Log::endl;\n        }\n      }\n      while(loopPtr->iteration(varList));\n      timer.loopEnd();\n      return;\n    }\n\n    // Iterations in parallel\n    // ----------------------\n    processCount = std::min(processCount, Parallel::size(comm)-1);\n    UInt rank = Parallel::myRank(comm);\n    auto commLocal = Parallel::splitCommunicator((rank > 0) ? (rank-1)/processCount : NULLINDEX, rank, comm); // processes of an iteration\n    auto commLoop  = Parallel::splitCommunicator(((rank == 0) || ((rank-1)%processCount == 0)) ?  0 : NULLINDEX, rank, comm); // 'main' processes of all iterations\n    Log::GroupPtr groupPtr = Log::group(((rank == 0) || ((rank-1)%processCount == 0)), (rank>0) && !parallelLog); // group is freed in the destructor\n\n    if(commLoop && Parallel::isMaster(commLoop))\n    {\n      // parallel version: main node\n      // ---------------------------\n      Log::Timer timer(loopPtr->count(), Parallel::size(commLoop)-1, TRUE);\n      do\n      {\n        timer.loopStep(loopPtr->index()-1);\n        UInt process;\n        Parallel::receive(process, NULLINDEX, commLoop);     // which process needs work?\n        Parallel::send(loopPtr->index(), process, commLoop); // send new loop number to be computed at process\n      }\n      while(loopPtr->iteration(varList));\n      // send to all processes the end signal (NULLINDEX)\n      for(UInt i=1; i<Parallel::size(commLoop); i++)\n      {\n        UInt process;\n        Parallel::receive(process, NULLINDEX, commLoop); // which process needs work?\n        Parallel::send(NULLINDEX, process, commLoop);    // end signal\n      }\n      Parallel::barrier(comm);\n      timer.loopEnd();\n    }\n    else\n    {\n      // clients\n      // -------\n      for(;;)\n      {\n        UInt index;\n        if(Parallel::isMaster(commLocal))\n        {\n          Parallel::send(Parallel::myRank(commLoop), 0, commLoop);\n          Parallel::receive(index, 0, commLoop);\n        }\n        Parallel::broadCast(index, 0, commLocal);\n        if(index == NULLINDEX) // end signal?\n          break;\n        while(loopPtr->index() != index)\n          loopPtr->iteration(varList);\n\n        try\n        {\n          Parallel::broadCastExceptions(commLocal, [&](Parallel::CommunicatorPtr commLocal)\n          {\n            auto varListTmp = varList;\n            programs.run(varListTmp, commLocal);\n          });\n        }\n        catch(std::exception &e)\n        {\n          if(!continueAfterError || Parallel::isExternal(e))\n            throw;\n          if(Parallel::isMaster(commLocal))\n            logError<<e.what()<<\"  continue...\"<<Log::endl;\n        }\n      }\n      Parallel::barrier(comm);\n    } // clients\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/programs/system/runCommand.cpp",
    "content": "/***********************************************/\n/**\n* @file runCommand.cpp\n*\n* @brief Execute system commands.\n*\n* @author Matthias Ellmer\n* @author Torsten Mayer-Guerr\n* @date 2016-07-13\n*/\n/***********************************************/\n\n// Latex documentation\n#define DOCSTRING docstring\nstatic const char *docstring = R\"(\nExecute system \\config{command}s. If \\config{executeParallel} is set and\nmultiple \\config{command}s are given they are executed in parallel at\ndistributed nodes, otherwise they are executed consecutively at master node only.\n)\";\n\n/***********************************************/\n\n#include \"programs/program.h\"\n#include \"inputOutput/system.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Execute system commands.\n* @ingroup programsGroup */\nclass RunCommand\n{\n public:\n  void run(Config &config, Parallel::CommunicatorPtr comm);\n};\n\nGROOPS_REGISTER_PROGRAM(RunCommand, PARALLEL, \"Execute system commands\", System)\n\n/***********************************************/\n\nvoid RunCommand::run(Config &config, Parallel::CommunicatorPtr comm)\n{\n  try\n  {\n    std::vector<FileName> command;\n    Bool silently;\n    Bool continueAfterError;\n    Bool executeParallel;\n\n    readConfig(config, \"command\",            command,            Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"silently\",           silently,           Config::DEFAULT,  \"0\", \"without showing the output.\");\n    readConfig(config, \"continueAfterError\", continueAfterError, Config::DEFAULT,  \"0\", \"continue with next command after error, otherwise throw exception\");\n    readConfig(config, \"executeParallel\",    executeParallel,    Config::DEFAULT,  \"0\", \"execute several commands in parallel\");\n    if(isCreateSchema(config)) return;\n\n    // lambda function\n    // ---------------\n    auto run = [&](UInt i)\n    {\n      logStatus<<\"Run command: \\\"\"<<command.at(i)<<\"\\\"\"<<Log::endl;\n      std::vector<std::string> outputs;\n      if(!System::exec(command.at(i), outputs))\n      {\n        if(continueAfterError)\n          logWarning<<\"Command \\\"\"<<command.at(i)<<\"\\\" exited with error\"<<Log::endl;\n        else\n          throw(Exception(\"Command \\\"\"+command.at(i).str()+\"\\\" exited with error\"));\n      }\n      if(!silently)\n        for(const auto &output : outputs)\n          logInfo<<output<<Log::endl;\n    };\n    // ---------------\n\n    if(executeParallel)\n    {\n      Log::GroupPtr groupPtr = Log::group(TRUE, FALSE); // group is freed in the destructor\n      Parallel::forEach(command.size(), run, comm, FALSE);\n    }\n    else if(Parallel::isMaster(comm))\n      for(UInt i=0; i<command.size(); i++)\n        run(i);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slr.cpp",
    "content": "/***********************************************/\n/**\n* @file slr.cpp\n*\n* @brief global navigation satellite system.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr.h\"\n#include \"slr/slrObservation.h\"\n#include \"slr/slrDesignMatrix.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrStation.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n#include \"slr/slrSatelliteGenerator/slrSatelliteGenerator.h\"\n#include \"slr/slrStationGenerator/slrStationGenerator.h\"\n\n/***********************************************/\n\nvoid Slr::init(const std::vector<Time> &times, SlrSatelliteGeneratorPtr satelliteGenerator, SlrStationGeneratorPtr stationGenerator,\n               EarthRotationPtr earthRotation, SlrParametrizationPtr parametrization)\n{\n  try\n  {\n    // init earth rotation\n    // -------------------\n    this->times = times;\n    polynomialEop.init(times, 3);\n    eop = Matrix(times.size(), 8); // Matrix eop columns: xp, yp, sp, deltaUT, LOD, X, Y, S\n    for(UInt i=0; i<times.size(); i++)\n      earthRotation->earthOrientationParameter(times.at(i), eop(i,0), eop(i,1), eop(i,2), eop(i,3), eop(i,4), eop(i,5), eop(i,6), eop(i,7));\n    // UT1-UTC => UT1-GPS (avoid leap seconds jumps for interpolation)\n    for(UInt i=0; i<times.size(); i++)\n      eop(i,3) -= (times.at(i)-timeGPS2UTC(times.at(i))).seconds();\n\n    funcRotationCrf2Trf = std::bind(&Slr::rotationCrf2Trf, this, std::placeholders::_1);\n\n    // init satellites\n    // -----------------\n    satellites = satelliteGenerator->satellites(times);\n    for(UInt idSat=0; idSat<satellites.size(); idSat++)\n      satellites.at(idSat)->id_ = idSat;\n\n    // init stations\n    // --------------\n    stations = stationGenerator->stations(times, satellites, earthRotation);\n    for(UInt idStat=0; idStat<stations.size(); idStat++)\n      stations.at(idStat)->id_ = idStat;\n\n    // init parametrization\n    // --------------------\n    this->parametrization = parametrization;\n    if(parametrization)\n    {\n      parametrization->init(this, parametrization->getParametrizationGravity());\n      funcReduceModels = std::bind(&SlrParametrization::observationCorrections, parametrization, std::placeholders::_1);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nRotary3d Slr::rotationCrf2Trf(const Time &time) const\n{\n  try\n  {\n    Matrix eop = polynomialEop.interpolate({time}, this->eop);\n    const Double xp      = eop(0, 0);\n    const Double yp      = eop(0, 1);\n    const Double sp      = eop(0, 2);\n    const Double deltaUT = eop(0, 3) + (time-timeGPS2UTC(time)).seconds();\n    const Double X       = eop(0, 5);\n    const Double Y       = eop(0, 6);\n    const Double S       = eop(0, 7);\n\n    const Double ERA = Planets::ERA(timeGPS2UTC(time) + seconds2time(deltaUT));\n    const Double r2  = X*X + Y*Y;\n    const Double E   = (r2!=0.) ? std::atan2(Y, X) : 0.;\n    const Double D   = std::atan(std::sqrt(r2/(1-r2)));\n\n    return  rotaryX(Angle(-yp)) * rotaryY(Angle(-xp)) *\n            rotaryZ(Angle(sp+ERA-S-E)) *\n            rotaryY(Angle(D)) * rotaryZ(Angle(E));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Slr::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    logStatus<<\"setup parameters\"<<Log::endl;\n    normalEquationInfo.initNewParameterNames();\n    if(parametrization)\n      parametrization->initParameter(normalEquationInfo);\n    normalEquationInfo.calculateIndex();\n    if(normalEquationInfo.parameterCount())\n    {\n      logInfo<<\"+ =======\"<<Log::endl;\n      logInfo<<normalEquationInfo.parameterCount()%\"%9i parameters in \"s<<normalEquationInfo.blockCount()<<\" normal equation matrix blocks\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector Slr::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo) const\n{\n  try\n  {\n    return parametrization ? parametrization->aprioriParameter(normalEquationInfo) : Vector();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nBool Slr::basicObservationEquations(const SlrNormalEquationInfo &/*normalEquationInfo*/, UInt idStat, UInt idSat, UInt idPass, SlrObservationEquation &eqn) const\n{\n  try\n  {\n    eqn.compute(*stations.at(idStat)->observations.at(idSat).at(idPass),\n                *stations.at(idStat), *satellites.at(idSat), funcRotationCrf2Trf, funcReduceModels, TRUE);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Slr::designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    if(eqn.l.rows() && parametrization)\n      parametrization->designMatrix(normalEquationInfo, eqn, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Slr::constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(parametrization)\n      parametrization->constraints(normalEquationInfo, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble Slr::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    return parametrization ? parametrization->updateParameter(normalEquationInfo, x, Wz) : 0.;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Slr::updateCovariance(const SlrNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    if(parametrization)\n      parametrization->updateCovariance(normalEquationInfo, covariance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Slr::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix)\n{\n  try\n  {\n    if(parametrization)\n      parametrization->writeResults(normalEquationInfo, suffix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Byte> Slr::selectStations(PlatformSelectorPtr selector)\n{\n  try\n  {\n    std::vector<const Platform*> platforms(stations.size(), nullptr);\n    for(UInt idStat=0; idStat<stations.size(); idStat++)\n      if(stations.at(idStat)->useable())\n        platforms.at(idStat) = &stations.at(idStat)->platform;\n    return selector->select(times.front(), times.back(), platforms);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nstd::vector<Byte> Slr::selectSatellites(PlatformSelectorPtr selector)\n{\n  try\n  {\n    std::vector<const Platform*> platforms(satellites.size(), nullptr);\n    for(UInt idSat=0; idSat<satellites.size(); idSat++)\n      if(satellites.at(idSat)->useable())\n        platforms.at(idSat) = &satellites.at(idSat)->platform;\n    return selector->select(times.front(), times.back(), platforms);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nBool Slr::InfoParameterChange::update(Double change)\n{\n  try\n  {\n    count++;\n    rms += change*change;\n    if(std::fabs(change) > std::fabs(maxChange))\n    {\n      maxChange = change;\n      return TRUE;\n    }\n    return FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid Slr::InfoParameterChange::print(Double convertToMeter, Double &maxChangeTotal)\n{\n  try\n  {\n    rms = std::sqrt(rms/count);\n    if(!info.empty())\n    {\n      std::string space(5-std::min(unit.size(), std::size_t(4)), ' ');\n      logInfo<<\"  rms =\"<<rms%\"%7.1f \"s<<unit<<\",\"<<space<<\"max =\"<<maxChange%\"%8.1f \"s<<unit<<\",\"<<space<<info<<Log::endl;\n    }\n\n    maxChangeTotal = std::max(maxChangeTotal, std::fabs(convertToMeter*maxChange));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slr.h",
    "content": "/***********************************************/\n/**\n* @file slr.h\n*\n* @brief global navigation satellite system classes.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLR__\n#define __GROOPS_SLR__\n\n#include \"parallel/parallel.h\"\n#include \"base/parameterName.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"slr/slrObservation.h\"\n#include \"slr/slrDesignMatrix.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrStation.h\"\n#include \"slr/slrNormalEquationInfo.h\"\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Slr;\ntypedef std::shared_ptr<Slr> SlrPtr;\n\nclass MatrixDistributed;\nclass SlrSatelliteGenerator;\nclass SlrStationGenerator;\nclass SlrParametrization;\nclass EarthRotation;\nclass PlatformSelector;\ntypedef std::shared_ptr<SlrSatelliteGenerator> SlrSatelliteGeneratorPtr;\ntypedef std::shared_ptr<SlrStationGenerator>   SlrStationGeneratorPtr;\ntypedef std::shared_ptr<SlrParametrization>    SlrParametrizationPtr;\ntypedef std::shared_ptr<EarthRotation>         EarthRotationPtr;\ntypedef std::shared_ptr<PlatformSelector>      PlatformSelectorPtr;\n\n/***** CLASS ***********************************/\n\nclass Slr\n{\npublic:\n  std::vector<SlrSatellitePtr>                     satellites;\n  std::vector<SlrStationPtr>                       stations;\n  SlrParametrizationPtr                            parametrization;\n  std::function<void(SlrObservationEquation &eqn)> funcReduceModels;\n  std::function<Rotary3d(const Time &time)>        funcRotationCrf2Trf;\n\n  Polynomial        polynomialEop;\n  std::vector<Time> times;\n  Matrix            eop;             // Matrix eop columns: xp, yp, sp, deltaUT, LOD, X, Y, S\n\n  void init(const std::vector<Time> &times, SlrSatelliteGeneratorPtr satelliteGenerator, SlrStationGeneratorPtr stationGenerator,\n            EarthRotationPtr earthRotation, SlrParametrizationPtr parametrization);\n  Rotary3d rotationCrf2Trf(const Time &time) const; // Inertial system (CRF) -> earth fixed system (TRF).\n\n  void   initParameter            (SlrNormalEquationInfo &normalEquationInfo);\n  Vector aprioriParameter         (const SlrNormalEquationInfo &normalEquationInfo) const;\n  Bool   basicObservationEquations(const SlrNormalEquationInfo &normalEquationInfo, UInt idStat, UInt idSat, UInt idPass, SlrObservationEquation &eqn) const;\n  void   designMatrix             (const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const;\n  void   constraints              (const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const;\n  Double updateParameter          (const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz);\n  void   updateCovariance         (const SlrNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance);\n  void   writeResults             (const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix=\"\");\n\n  std::vector<Byte> selectStations(PlatformSelectorPtr selector);\n  std::vector<Byte> selectSatellites(PlatformSelectorPtr selector);\n\n  class InfoParameterChange\n  {\n  public:\n    std::string unit;\n    UInt        count;\n    Double      rms;\n    Double      maxChange;\n    std::string info;\n\n    InfoParameterChange(const std::string &unit) : unit(unit), count(0), rms(0), maxChange(0) {}\n    Bool update(Double change);\n    void print(Double convertToMeter, Double &maxChangeTotal);\n  };\n};\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrDesignMatrix.cpp",
    "content": "/***********************************************/\n/**\n* @file slrDesignMatrix.cpp\n*\n* @brief Management of sparse design matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"slr/slrNormalEquationInfo.h\"\n#include \"slrDesignMatrix.h\"\n\n/***********************************************/\n\nSlrDesignMatrix::SlrDesignMatrix(const SlrNormalEquationInfo &normalEquationInfo_, const_MatrixSliceRef l_) :\n      normalEquationInfo(normalEquationInfo_),\n      blockIndices(normalEquationInfo.blockIndices()),\n      indexUsedParameter(normalEquationInfo.blockCount()),\n      countUsedParameter(normalEquationInfo.blockCount()),\n      row(0),\n      rows(l_.rows()),\n      A(l_.rows(), normalEquationInfo.parameterCount()),\n      l(l_)\n{\n}\n\n/***********************************************/\n\nvoid SlrDesignMatrix::init(const_MatrixSliceRef l)\n{\n  try\n  {\n    this->l = l;\n    if(A.rows() < l.rows())\n      A = Matrix(l.rows(), blockIndices.back());\n    row  = 0;\n    rows = l.rows();\n\n    for(UInt i : indexUsedBlock)\n    {\n      for(UInt k=0; k<indexUsedParameter[i].size(); k++)\n        A.column(blockIndices[i]+indexUsedParameter[i][k], countUsedParameter[i][k]).setNull();\n      indexUsedParameter[i].clear();\n      countUsedParameter[i].clear();\n    }\n\n    indexUsedBlock.clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrDesignMatrix &SlrDesignMatrix::selectRows(UInt row_, UInt rows_)\n{\n  try\n  {\n    row  = row_;\n    rows = rows_;\n    if(!rows)\n      rows = l.rows()-row_;\n    return *this;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrixSlice SlrDesignMatrix::column(const SlrParameterIndex &index)\n{\n  try\n  {\n    const UInt block = normalEquationInfo.block(index);\n    const UInt col   = normalEquationInfo.index(index) - normalEquationInfo.blockIndex(block);\n    const UInt cols  = normalEquationInfo.count(index);\n\n    const auto iter = std::lower_bound(indexUsedBlock.begin(), indexUsedBlock.end(), block);\n    if(iter == indexUsedBlock.end() || block < *iter)\n      indexUsedBlock.insert(iter, block);\n\n    constexpr UInt gap = 32;\n    UInt idx = 0;\n    while((idx < indexUsedParameter[block].size()) && (indexUsedParameter[block][idx]+countUsedParameter[block][idx]+gap < col))\n      idx++;\n    if((idx >= indexUsedParameter[block].size()) || (col+cols+gap < indexUsedParameter[block][idx]))\n    {\n      indexUsedParameter[block].insert(indexUsedParameter[block].begin()+idx, col);\n      countUsedParameter[block].insert(countUsedParameter[block].begin()+idx, cols);\n    }\n    else // merge\n    {\n      const UInt end = std::max(col+cols, indexUsedParameter[block][idx]+countUsedParameter[block][idx]);\n      indexUsedParameter[block][idx] = std::min(col, indexUsedParameter[block][idx]);\n      countUsedParameter[block][idx] = end - indexUsedParameter[block][idx];\n      // merge with following parameter group?\n      while((idx+1 < indexUsedParameter[block].size()) && (indexUsedParameter[block][idx]+countUsedParameter[block][idx]+gap >= indexUsedParameter[block][idx+1]))\n      {\n        countUsedParameter[block][idx] = std::max(countUsedParameter[block][idx], indexUsedParameter[block][idx+1]+countUsedParameter[block][idx+1]-indexUsedParameter[block][idx]);\n        indexUsedParameter[block].erase(indexUsedParameter[block].begin()+idx+1);\n        countUsedParameter[block].erase(countUsedParameter[block].begin()+idx+1);\n      }\n    }\n\n    return A.slice(row, blockIndices[block]+col, rows, cols);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix SlrDesignMatrix::mult(const_MatrixSliceRef x)\n{\n  try\n  {\n    Matrix y(rows, x.columns());\n\n    for(UInt block : indexUsedBlock)\n      for(UInt k=0; k<indexUsedParameter[block].size(); k++)\n      {\n        const UInt index = blockIndices[block]+indexUsedParameter[block][k];\n        const UInt count = countUsedParameter[block][k];\n        matMult(1., A.slice(row, index, rows, count), x.row(index, count), y);\n      }\n\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nMatrix SlrDesignMatrix::mult(const std::vector<Matrix> &x, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    Matrix y(rows, x.at(startBlock).columns());\n    for(UInt block : indexUsedBlock)\n      if((startBlock <= block) && (block < startBlock+countBlock))\n        for(UInt k=0; k<indexUsedParameter[block].size(); k++)\n        {\n          const UInt index = blockIndices[block]+indexUsedParameter[block][k];\n          const UInt count = countUsedParameter[block][k];\n          matMult(1., A.slice(row, index, rows, count), x.at(block).row(indexUsedParameter[block][k], count), y);\n        }\n    return y;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrDesignMatrix::transMult(const_MatrixSliceRef l, std::vector<Matrix> &x, UInt startBlock, UInt countBlock)\n{\n  try\n  {\n    for(UInt block : indexUsedBlock)\n      if((startBlock <= block) && (block < startBlock+countBlock))\n        for(UInt k=0; k<indexUsedParameter[block].size(); k++)\n        {\n          const UInt index = blockIndices[block]+indexUsedParameter[block][k];\n          const UInt count = countUsedParameter[block][k];\n          matMult(1., A.slice(row, index, rows, count).trans(), l, x.at(block).row(indexUsedParameter[block][k], count));\n        }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrDesignMatrix::accumulateNormals(MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount)\n{\n  try\n  {\n    for(UInt ii=0; ii<indexUsedBlock.size(); ii++)\n    {\n      const UInt blocki = indexUsedBlock[ii];\n      normals.setBlock(blocki, blocki);\n      if(!normals.N(blocki, blocki).size())\n        normals.N(blocki, blocki) = Matrix(normals.blockSize(blocki), Matrix::SYMMETRIC);\n\n      for(UInt kk=ii+1; kk<indexUsedBlock.size(); kk++)\n      {\n        const UInt blockk = indexUsedBlock[kk];\n        normals.setBlock(blocki, blockk);\n        if(!normals.N(blocki, blockk).size())\n          normals.N(blocki, blockk) = Matrix(normals.blockSize(blocki), normals.blockSize(blockk));\n      }\n\n      for(UInt i=0; i<indexUsedParameter[blocki].size(); i++)\n      {\n        const UInt index = indexUsedParameter[blocki][i];\n        const UInt count = countUsedParameter[blocki][i];\n        const const_MatrixSlice Ai(A.slice(row, blockIndices[blocki]+index, rows, count).trans());\n\n        // right hand side\n        matMult(1., Ai, l.row(row, rows), n.at(blocki).row(index, count));\n\n        // diagonal block\n        rankKUpdate(1., Ai.trans(), normals.N(blocki, blocki).slice(index, index, count, count));\n        for(UInt k=i+1; k<indexUsedParameter[blocki].size(); k++)\n          matMult(1., Ai, A.slice(row, blockIndices[blocki]+indexUsedParameter[blocki][k], rows, countUsedParameter[blocki][k]),\n                  normals.N(blocki, blocki).slice(index, indexUsedParameter[blocki][k], count, countUsedParameter[blocki][k]));\n\n        // other blocks\n        for(UInt kk=ii+1; kk<indexUsedBlock.size(); kk++)\n        {\n          const UInt blockk = indexUsedBlock[kk];\n          for(UInt k=0; k<indexUsedParameter[blockk].size(); k++)\n            matMult(1., Ai, A.slice(row, blockIndices[blockk]+indexUsedParameter[blockk][k], rows, countUsedParameter[blockk][k]),\n                    normals.N(blocki, blockk).slice(index, indexUsedParameter[blockk][k], count, countUsedParameter[blockk][k]));\n        }\n      }\n    }\n\n    // accumulate right hand side\n    obsCount += rows;\n    lPl      += quadsum(l);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrDesignMatrix.h",
    "content": "/***********************************************/\n/**\n* @file slrDesignMatrix.h\n*\n* @brief Management of sparse design matrix.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRDESIGNMATRIX__\n#define __GROOPS_SLRDESIGNMATRIX__\n\n#include \"parallel/matrixDistributed.h\"\n#include \"slr/slrNormalEquationInfo.h\"\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\n/** @brief Management of sparse design matrix. */\nclass SlrDesignMatrix\n{\n  const SlrNormalEquationInfo   &normalEquationInfo;\n  std::vector<UInt>              blockIndices;\n  std::vector<UInt>              indexUsedBlock;\n  std::vector<std::vector<UInt>> indexUsedParameter;\n  std::vector<std::vector<UInt>> countUsedParameter;\n  UInt                           row, rows;\n  Matrix                         A;\n\npublic:\n  Vector l;\n\n  SlrDesignMatrix(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef l=Vector());\n ~SlrDesignMatrix() {}\n\n  void             init(const_MatrixSliceRef l);\n  SlrDesignMatrix &selectRows(UInt row, UInt rows);\n  MatrixSlice      column(const SlrParameterIndex &index);\n  Matrix           mult(const_MatrixSliceRef x);\n  Matrix           mult(const std::vector<Matrix> &x, UInt startBlock, UInt countBlock);\n  void             transMult(const_MatrixSliceRef l, std::vector<Matrix> &x, UInt startBlock, UInt countBlock);\n  void             accumulateNormals(MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount);\n};\n\n/// @}\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrNormalEquationInfo.cpp",
    "content": "/***********************************************/\n/**\n* @file slrNormalEquationInfo.cpp\n*\n* @brief SLR normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/parallel.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"base/parameterName.h\"\n#include \"slrNormalEquationInfo.h\"\n\n/***********************************************/\n\nSlrNormalEquationInfo::SlrNormalEquationInfo(UInt countStations, UInt countSatellites) :\n    estimateStation(countStations, TRUE), estimateSatellite(countSatellites, TRUE), defaultBlockSize(2048)\n{\n}\n\n/***********************************************/\n\nvoid SlrNormalEquationInfo::initNewParameterNames()\n{\n  try\n  {\n    indexGravity.clear();\n    parameters.clear();\n    block_.clear();\n    index_.clear();\n    count_.clear();\n    parameterNames_.clear();\n    blockIndices_.clear();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrParameterIndex SlrNormalEquationInfo::addParameters(UInt idStat, UInt idSat, const std::vector<ParameterName> &parameterNames)\n{\n  if(!parameterNames.size())\n    return SlrParameterIndex(NULLINDEX);\n  parameters.push_back(std::make_tuple(idStat, idSat, parameters.size(), parameterNames));\n  return SlrParameterIndex(parameters.size()-1);\n}\n\n/***********************************************/\n\nvoid SlrNormalEquationInfo::calculateIndex()\n{\n  try\n  {\n    auto newBlock = [&]()\n    {\n      const UInt parameterCount = this->parameterCount();\n      if(blockSize(blockCount()-1))\n        blockIndices_.push_back(parameterCount);\n    };\n\n    auto insert = [&](auto iter, UInt defaultBlockSize)\n    {\n      if((defaultBlockSize > 0) && (blockSize(blockCount()-1) >= defaultBlockSize))\n        newBlock();\n      const UInt idx   = std::get<2>(*iter);\n      index_.at(idx)   = blockIndices_.back();\n      block_.at(idx)   = blockCount()-1;\n      count_.at(idx)   = std::get<3>(*iter).size();\n      parameterNames_.insert(parameterNames_.end(), std::get<3>(*iter).begin(), std::get<3>(*iter).end());\n      blockIndices_.back() += std::get<3>(*iter).size();\n    };\n\n    block_.resize(parameters.size(), NULLINDEX);\n    index_.resize(parameters.size(), NULLINDEX);\n    count_.resize(parameters.size(), 0);\n    blockIndices_ = {0, 0};\n    parameterNames_.reserve(std::accumulate(parameters.begin(), parameters.end(), UInt(0), [](UInt count, const auto &p){return count+std::get<3>(p).size();}));\n\n    std::stable_sort(parameters.begin(), parameters.end(), [](auto &p1, auto &p2)\n                    {\n                      if(std::get<0>(p1) != std::get<0>(p2)) return (std::get<0>(p1) < std::get<0>(p2)); // idStat\n                      return (std::get<1>(p1) < std::get<1>(p2));                                        // idSat\n                    });\n    auto iter = parameters.begin();\n\n    // station interval parameters\n    newBlock();\n    for(UInt idStat=0; idStat<estimateStation.size(); idStat++)\n    {\n      Bool firstBlock = TRUE;\n      while((iter != parameters.end()) && (std::get<0>(*iter) == idStat) && (std::get<1>(*iter) == NULLINDEX))\n      {\n        insert(iter, firstBlock ? defaultBlockSize : 0); // do not split parameters of a station\n        firstBlock = FALSE;\n        iter++;\n      }\n    }\n\n    // satellite interval parameters\n    newBlock();\n    for(UInt idSat=0; idSat<estimateSatellite.size(); idSat++)\n    {\n      Bool firstBlock = TRUE;\n      while((iter != parameters.end()) && (std::get<0>(*iter) == NULLINDEX) && (std::get<1>(*iter) == idSat))\n      {\n        insert(iter, firstBlock ? defaultBlockSize : 0); // do not split parameters of a satellite\n        firstBlock = FALSE;\n        iter++;\n      }\n    }\n\n    // other interval parameters\n    newBlock();\n    while((iter != parameters.end()) && (std::get<0>(*iter) == NULLINDEX) && (std::get<1>(*iter) == NULLINDEX))\n    {\n      insert(iter, defaultBlockSize);\n      iter++;\n    }\n\n    // remove possible last empty block\n    if(blockCount() && !blockSize(blockCount()-1))\n      blockIndices_.pop_back();\n\n    parameters.clear();\n    parameters.shrink_to_fit();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrNormalEquationInfo.h",
    "content": "/***********************************************/\n/**\n* @file slrNormalEquationInfo.h\n*\n* @brief SLR normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRNORMALEQUATIONINFO__\n#define __GROOPS_SLRNORMALEQUATIONINFO__\n\n#include <regex>\n#include \"parallel/parallel.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"base/parameterName.h\"\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** CLASS ***********************************/\n\nclass SlrParameterIndex\n{\n  UInt index;\n\npublic:\n  SlrParameterIndex(UInt idx=NULLINDEX) : index(idx) {}\n  explicit operator bool() const {return index != NULLINDEX;}\n\n  friend class SlrNormalEquationInfo;\n  friend class SlrDesignMatrix;\n};\n\n/***** CLASS ***********************************/\n\nclass SlrNormalEquationInfo\n{\npublic:\n  std::vector<std::pair<std::regex, Bool>> enableParametrizations; // wildcard matching, enable/disable\n  std::vector<Byte>                        estimateStation;\n  std::vector<Byte>                        estimateSatellite;\n  UInt                                     defaultBlockSize;\n  std::vector<SlrParameterIndex>           indexGravity;\n\n  SlrNormalEquationInfo(UInt countStations, UInt countSatellites);\n\n  void initNewParameterNames();\n  SlrParameterIndex parameterNamesStation  (UInt idStat, const std::vector<ParameterName> &parameterNames) {return addParameters(idStat,    NULLINDEX, parameterNames);}\n  SlrParameterIndex parameterNamesSatellite(UInt idSat,  const std::vector<ParameterName> &parameterNames) {return addParameters(NULLINDEX, idSat,     parameterNames);}\n  SlrParameterIndex parameterNamesOther    (const std::vector<ParameterName> &parameterNames)              {return addParameters(NULLINDEX, NULLINDEX, parameterNames);}\n  void calculateIndex();\n\n  UInt block(const SlrParameterIndex &index) const {return block_.at(index.index);}\n  UInt index(const SlrParameterIndex &index) const {return index_.at(index.index);}\n  UInt count(const SlrParameterIndex &index) const {return count_.at(index.index);}\n\n  const std::vector<ParameterName> &parameterNames() const {return parameterNames_;}\n  const std::vector<UInt>          &blockIndices()   const {return blockIndices_;}\n\n  UInt parameterCount()   const {return blockIndices_.back();}                      //!< Number of rows/columns (dimension) of distributed matrix\n  UInt blockIndex(UInt i) const {return blockIndices_.at(i);}                       //!< Start index of block @a i\n  UInt blockSize(UInt i)  const {return blockIndices_.at(i+1)-blockIndices_.at(i);} //!< Size of block @a i\n  UInt blockCount()       const {return blockIndices_.size()-1;}                    //!< Number of block rows/columns\n\nprivate:\n  std::vector<std::tuple<UInt, UInt, UInt, std::vector<ParameterName>>> parameters; // idStat, idSat, idx, name\n  std::vector<UInt>          block_, index_, count_;\n  std::vector<ParameterName> parameterNames_;\n  std::vector<UInt>          blockIndices_;\n  std::vector<UInt>          blockCountEpoch_;\n\n  SlrParameterIndex addParameters(UInt idStat, UInt idSat, const std::vector<ParameterName> &parameterNames);\n};\n\n/// @}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrObservation.cpp",
    "content": "/***********************************************/\n/**\n* @file slrObservation.cpp\n*\n* @brief Code & Phase observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrStation.h\"\n#include \"slr/slrObservation.h\"\n\n/***********************************************/\n\nstatic Bool positionVelocityTime(const SlrStation &station, const SlrSatellite &satellite,\n                                 const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, const Time &timeTrans,\n                                 Vector3d &posTrans, Vector3d &velTrans, Time &timeBounce, Vector3d &posBounce, Vector3d &velBounce,\n                                 Time &timeRecv, Vector3d &posRecv)\n{\n  try\n  {\n    // station position at transmit time\n    posTrans = rotationCrf2Trf(timeTrans).inverseRotate(station.position(timeTrans));\n    if(std::isnan(posTrans.quadsum()))\n      return FALSE;\n\n    // satellite position at bounce time\n    posBounce = satellite.position(timeTrans);\n    if(std::isnan(posBounce.quadsum()))\n      return FALSE;\n    Vector3d posOld;\n    for(UInt i=0; (i<10) && ((posBounce-posOld).r() > 0.0001); i++) // iteration\n    {\n      timeBounce = timeTrans + seconds2time((posBounce-posTrans).r()/LIGHT_VELOCITY);\n      posOld     = posBounce;\n      posBounce  = satellite.position(timeBounce) + satellite.centerOfMass2Reflector(timeBounce, normalize(posBounce-posTrans));\n    }\n    velBounce = satellite.velocity(timeBounce);\n\n    // station position at receive time\n    timeRecv = timeBounce + seconds2time((posBounce-posTrans).r()/LIGHT_VELOCITY);\n    posRecv  = rotationCrf2Trf(timeRecv).inverseRotate(station.position(timeRecv));\n    for(UInt i=0; (i<10) && ((posRecv-posOld).r() > 0.0001); i++) // iteration\n    {\n      timeRecv = timeBounce + seconds2time((posRecv-posBounce).r()/LIGHT_VELOCITY);\n      posOld   = posRecv;\n      posRecv  = rotationCrf2Trf(timeRecv).inverseRotate(station.position(timeRecv));\n    }\n    velTrans = 1./(timeRecv-timeTrans).seconds() * (posRecv-posTrans);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n\n/***********************************************/\n\nBool SlrObservation::init(const SlrStation &station, const SlrSatellite &satellite,\n                          const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, Angle elevationCutOff)\n{\n  try\n  {\n    if((!station.useable()) || (!satellite.useable()))\n      return FALSE;\n\n    const UInt obsCount = observations.rows();\n    Vector useable(obsCount);\n    Vector sigmas0Tmp(obsCount);\n    std::vector<Time> timesTransCorrected = station.correctedTimes(timesTrans);\n\n    for(UInt i=0; i<obsCount; i++)\n    {\n      Time timeBounce, timeRecv;\n      Vector3d posTrans, posBounce, posRecv;\n      Vector3d velTrans, velBounce;\n      if(!positionVelocityTime(station, satellite, rotationCrf2Trf, timesTransCorrected.at(i),\n                               posTrans, velTrans, timeBounce, posBounce, velBounce, timeRecv, posRecv))\n        continue;\n\n      // direction to satellite in local frame (north, east, up)\n      const Vector3d k         = station.global2localFrame(timesTransCorrected.at(i)).transform(rotationCrf2Trf(timesTransCorrected.at(i)).rotate(normalize(posBounce-posTrans)));\n      const Angle    azimut    = k.lambda();\n      const Angle    elevation = k.phi();\n\n      sigmas0Tmp(i) = station.accuracy(timesTransCorrected.at(i),\n                                       observations(i)-0.5*((posBounce-posTrans).r() + (posRecv-posBounce).r()),\n                                       sigmas0(i), redundancies(i), laserWavelength(i), azimut, elevation);\n      useable(i) = (k.phi() >= elevationCutOff) && (sigmas0Tmp(i) > 0) && !std::isnan(posRecv.quadsum());\n    }\n\n    // Remove unused observations\n    const UInt obsCountNew = sum(useable);\n    auto timesTmp      = timesTrans;\n    auto obsTmp        = observations;\n    auto wavelengthTmp = laserWavelength;\n    timesTrans.resize(obsCountNew);\n    observations       = Vector(obsCountNew);\n    residuals          = Vector(obsCountNew);\n    redundancies       = Vector(obsCountNew);\n    sigmas0            = Vector(obsCountNew);\n    sigmas             = Vector(obsCountNew);\n    laserWavelength    = Vector(obsCountNew);\n    UInt idx = 0;\n    for(UInt i=0; i<useable.size(); i++)\n      if(useable(i))\n      {\n        timesTrans.at(idx)   = timesTmp.at(i);\n        observations(idx)    = obsTmp(i);\n        sigmas(idx) = sigmas0(idx) = sigmas0Tmp(i);\n        laserWavelength(idx) = wavelengthTmp(i);\n        idx++;\n      }\n\n    return (obsCountNew > 0);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrObservation::setHomogenizedResiduals(const_MatrixSliceRef residuals_, const_MatrixSliceRef redundancies_)\n{\n  try\n  {\n    residuals    = residuals_;\n    redundancies = redundancies_;\n    for(UInt i=0; i<residuals.rows(); i++)\n      residuals(i) *= sigmas(i);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nvoid SlrObservationEquation::compute(const SlrObservation &observation, const SlrStation &station_, const SlrSatellite &satellite_,\n                                     const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n                                     const std::function<void(SlrObservationEquation &eqn)> &reduceModels, Bool homogenize)\n{\n  try\n  {\n\n    type        = RANGE;\n    station     = &station_;\n    satellite   = &satellite_;\n\n    const UInt obsCount = observation.observations.rows();\n    sigmas      = observation.sigmas;\n    sigmas0     = observation.sigmas0;\n    l           = observation.observations;\n    A           = Matrix(obsCount, 8);\n    index.resize(obsCount);\n    std::iota(index.begin(), index.end(), 0);\n    count       = std::vector<UInt>(obsCount, 1);\n    timesStat   = station->correctedTimes(observation.timesTrans);\n    timesSat.resize(obsCount);\n    posStat.resize(obsCount);\n    posSat.resize(obsCount);\n    azimutStat.resize(obsCount);\n    elevationStat.resize(obsCount);\n    laserWavelength = observation.laserWavelength;\n\n    for(UInt i=0; i<obsCount; i++)\n    {\n      Time     timesRecv;\n      Vector3d posRecv, velStat, velSat;\n      positionVelocityTime(station_, satellite_, rotationCrf2Trf, timesStat.at(i),\n                           posStat.at(i), velStat, timesSat.at(i), posSat.at(i), velSat, timesRecv, posRecv);\n\n      // reduced observations\n      l(i) -= 0.5*((posSat.at(i)-posStat.at(i)).r() + (posRecv-posSat.at(i)).r());\n\n      // curved space-time\n      const Double r1  = posStat.at(i).r();\n      const Double r2  = posSat.at(i).r();\n      const Double r12 = (posStat.at(i) - posSat.at(i)).r();\n      l(i) += 2*DEFAULT_GM/std::pow(LIGHT_VELOCITY,2)*log((r1+r2+r12)/(r1+r2-r12));\n\n      // geometry of roundtrip\n      // ---------------------\n      const Vector3d k1     = normalize(posSat.at(i) - posStat.at(i)); // unit vector stat -> sat\n      const Vector3d k2     = normalize(posRecv - posSat.at(i));       // unit vector sat -> stat\n      const Double   d1Stat = inner(k1, velStat)/LIGHT_VELOCITY;\n      const Double   d1Sat  = inner(k1, velSat) /LIGHT_VELOCITY;\n      const Double   d2Stat = inner(k2, velStat)/LIGHT_VELOCITY;\n      const Double   d2Sat  = inner(k2, velSat) /LIGHT_VELOCITY;\n\n      // direction to satellite in local frame (north, east, up)\n      const Vector3d kLocal = station_.global2localFrame(timesStat.at(i)).transform(rotationCrf2Trf(timesStat.at(i)).rotate(k1));\n      azimutStat.at(i)    = kLocal.lambda();\n      elevationStat.at(i) = kLocal.phi();\n\n      // design matrix\n      // -------------\n      A(i, idxPosStat+0) = 0.5*(k1.x() * (-1+d1Sat) + k2.x() * (+1+d1Sat+d1Stat+d2Stat));  // station coord x\n      A(i, idxPosStat+1) = 0.5*(k1.y() * (-1+d1Sat) + k2.y() * (+1+d1Sat+d1Stat+d2Stat));  // station coord y\n      A(i, idxPosStat+2) = 0.5*(k1.z() * (-1+d1Sat) + k2.z() * (+1+d1Sat+d1Stat+d2Stat));  // station coord z\n      A(i, idxPosSat+0)  = 0.5*(k1.x() * (+1+d1Sat) + k2.x() * (-1+d1Sat+d1Stat+d2Stat));  // satellite coord x\n      A(i, idxPosSat+1)  = 0.5*(k1.y() * (+1+d1Sat) + k2.y() * (-1+d1Sat+d1Stat+d2Stat));  // satellite coord y\n      A(i, idxPosSat+2)  = 0.5*(k1.z() * (+1+d1Sat) + k2.z() * (-1+d1Sat+d1Stat+d2Stat));  // satellite coord z\n      A(i, idxTime)      = 0.5*LIGHT_VELOCITY*(d1Sat-d1Stat+d2Stat-d2Sat);                 // with respect to transmit time\n      A(i, idxRange)     = 1.0;                                                            // one way range correction (troposphere, ...)\n    }\n\n    if(reduceModels)\n      reduceModels(*this);\n\n    // homogenize\n    // -----------\n    if(homogenize)\n      for(UInt i=0; i<obsCount; i++)\n      {\n        if(l.size()) l.row(i) *= 1/sigmas(i);\n        if(A.size()) A.row(i) *= 1/sigmas(i);\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrObservation.h",
    "content": "/***********************************************/\n/**\n* @file slrObservation.h\n*\n* @brief Code & Phase observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLROBSERVATION__\n#define __GROOPS_SLROBSERVATION__\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SlrStation;\nclass SlrSatellite;\nclass SlrObservation;\ntypedef std::shared_ptr<SlrObservation> SlrObservationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Observations.\n* Between one station and one satellite (one pass). */\nclass SlrObservation\n{\npublic:\n  std::vector<Time> timesTrans;      ///< transmitted time\n  Vector            observations;    ///< original observations\n  Vector            residuals;       ///< estimated postfit residuals\n  Vector            redundancies;    ///< partial redundancies of the least squares adjustment\n  Vector            sigmas0;         ///< expected (apriori) accuracies\n  Vector            sigmas;          ///< modfied accuracies (downweighted outliers)\n  Vector            laserWavelength; ///< laser wavelength\n\n  SlrObservation() {}\n\n  Bool init(const SlrStation &station, const SlrSatellite &satellite,\n            const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf, Angle elevationCutOff);\n\n  void setHomogenizedResiduals(const_MatrixSliceRef residuals, const_MatrixSliceRef redundancy);\n};\n\n/***** CLASS ***********************************/\n\n/** @brief Reduced observations (obs - computed) and design matrix.\n* Between one station and one satellite for one pass. */\nclass SlrObservationEquation\n{\npublic:\n  enum {idxPosStat = 0,  // x,y,z (CRF)\n        idxPosSat  = 3,  // x,y,z (CRF)\n        idxTime    = 6,  // transmit time offset\n        idxRange   = 7}; // One way range\n\n  enum Type {RANGE, DIRECTIONS};\n\n  Type  type;\n  const SlrStation   *station;\n  const SlrSatellite *satellite;\n\n  // weighted observations (with 1/sigma)\n  Vector l;\n  Matrix A; // design matrix\n  Vector sigmas;\n  Vector sigmas0;\n\n  // approximate values (Taylor point)\n  std::vector<UInt>     index, count; // observations per epoch\n  std::vector<Vector3d> posStat,   posSat;\n  std::vector<Time>     timesStat, timesSat;\n  std::vector<Angle>    azimutStat, elevationStat;\n  Vector                laserWavelength;\n\n  SlrObservationEquation() : station(nullptr), satellite(nullptr) {}\n\n  void compute(const SlrObservation &observation, const SlrStation &station, const SlrSatellite &satellite,\n               const std::function<Rotary3d(const Time &time)> &rotationCrf2Trf,\n               const std::function<void(SlrObservationEquation &eqn)> &reduceModels, Bool homogenize);\n};\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrization.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrization.cpp\n*\n* @brief Parametrization of SLR observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_SlrParametrization\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"slr/slrParametrization/slrParametrizationTroposphere.h\"\n#include \"slr/slrParametrization/slrParametrizationDynamicOrbits.h\"\n#include \"slr/slrParametrization/slrParametrizationGravityField.h\"\n#include \"slr/slrParametrization/slrParametrizationStaticPositions.h\"\n#include \"slr/slrParametrization/slrParametrizationEarthRotation.h\"\n#include \"slr/slrParametrization/slrParametrizationRangeBiasSatelliteApriori.h\"\n#include \"slr/slrParametrization/slrParametrizationRangeBiasSatellite.h\"\n#include \"slr/slrParametrization/slrParametrizationRangeBiasStationApriori.h\"\n#include \"slr/slrParametrization/slrParametrizationRangeBiasStation.h\"\n#include \"slr/slrParametrization/slrParametrizationRangeBiasStationSatellite.h\"\n#include \"slr/slrParametrization/slrParametrizationRangeBiasStationSatelliteApriori.h\"\n#include \"slr/slrParametrization/slrParametrizationTimeBiasApriori.h\"\n#include \"slr/slrParametrization/slrParametrizationTimeBias.h\"\n#include \"slr/slrParametrization/slrParametrizationConstraints.h\"\n#include \"slr/slrParametrization/slrParametrizationGroup.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(SlrParametrization, \"slrParametrizationType\",\n                      SlrParametrizationTroposphere,\n                      SlrParametrizationDynamicOrbits,\n                      SlrParametrizationGravityField,\n                      SlrParametrizationStaticPositions,\n                      SlrParametrizationEarthRotation,\n                      SlrParametrizationRangeBiasStationApriori,\n                      SlrParametrizationRangeBiasStation,\n                      SlrParametrizationRangeBiasSatelliteApriori,\n                      SlrParametrizationRangeBiasSatellite,\n                      SlrParametrizationRangeBiasStationSatelliteApriori,\n                      SlrParametrizationRangeBiasStationSatellite,\n                      SlrParametrizationTimeBiasApriori,\n                      SlrParametrizationTimeBias,\n                      SlrParametrizationConstraints,\n                      SlrParametrizationGroup)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(SlrParametrization, \"slrParametrizationType\")\n\n/***********************************************/\n\nSlrParametrization::SlrParametrization(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"parametrization of SLR observations\"))\n    {\n      if(readConfigChoiceElement(config, \"troposphere\",                      type, \"tropospheric delays\"))\n        base.push_back(new SlrParametrizationTroposphere(config));\n      if(readConfigChoiceElement(config, \"dynamicOrbits\",                    type, \"satellite orbits by variational equations\"))\n        base.push_back(new SlrParametrizationDynamicOrbits(config));\n      if(readConfigChoiceElement(config, \"gravityField\",                     type, \"gravity field of the Earth\"))\n        base.push_back(new SlrParametrizationGravityField(config));\n      if(readConfigChoiceElement(config, \"staticPositions\",                  type, \"static positions with no-net constraints\"))\n        base.push_back(new SlrParametrizationStaticPositions(config));\n      if(readConfigChoiceElement(config, \"earthRotation\",                    type, \"Earth rotation\"))\n        base.push_back(new SlrParametrizationEarthRotation(config));\n      if(readConfigChoiceElement(config, \"rangeBiasStationApriori\",          type, \"apriori range bias from file\"))\n        base.push_back(new SlrParametrizationRangeBiasStationApriori(config));\n      if(readConfigChoiceElement(config, \"rangeBiasStation\",                 type, \"range bias\"))\n        base.push_back(new SlrParametrizationRangeBiasStation(config));\n      if(readConfigChoiceElement(config, \"rangeBiasSatelliteApriori\",        type, \"apriori range bias from file\"))\n        base.push_back(new SlrParametrizationRangeBiasSatelliteApriori(config));\n      if(readConfigChoiceElement(config, \"rangeBiasSatellite\",               type, \"range bias\"))\n        base.push_back(new SlrParametrizationRangeBiasSatellite(config));\n      if(readConfigChoiceElement(config, \"rangeBiasStationSatelliteApriori\", type, \"apriori range bias from file\"))\n        base.push_back(new SlrParametrizationRangeBiasStationSatelliteApriori(config));\n      if(readConfigChoiceElement(config, \"rangeBiasStationSatellite\",        type, \"range bias\"))\n        base.push_back(new SlrParametrizationRangeBiasStationSatellite(config));\n      if(readConfigChoiceElement(config, \"timeBiasApriori\",                  type, \"apriori time bias at station from file\"))\n        base.push_back(new SlrParametrizationTimeBiasApriori(config));\n      if(readConfigChoiceElement(config, \"timeBias\",                         type, \"time bias at station\"))\n        base.push_back(new SlrParametrizationTimeBias(config));\n      if(readConfigChoiceElement(config, \"constraints\",                      type, \"parameter constraints\"))\n        base.push_back(new SlrParametrizationConstraints(config));\n      if(readConfigChoiceElement(config, \"group\",                            type, \"grouping parametrizations\"))\n        base.push_back(new SlrParametrizationGroup(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrParametrization::~SlrParametrization()\n{\n  for(auto b : base)\n    delete b;\n}\n\n/***********************************************/\n\nstd::vector<const SlrParametrizationGravityField*> SlrParametrization::getParametrizationGravity() const\n{\n  try\n  {\n    std::vector<const SlrParametrizationGravityField*> params;\n    for(auto b : base)\n      b->getParametrizationGravity(params);\n    return params;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField)\n{\n  try\n  {\n    for(auto b : base)\n      b->init(slr, paramGravityField);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    for(auto b : base)\n      b->observationCorrections(eqn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto b : base)\n      b->initParameter(normalEquationInfo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector SlrParametrization::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo) const\n{\n  try\n  {\n    Vector x0(normalEquationInfo.parameterCount());\n    for(auto b : base)\n      b->aprioriParameter(normalEquationInfo, x0);\n    return x0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    for(auto b : base)\n      b->designMatrix(normalEquationInfo, eqn, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    for(auto b : base)\n      b->constraints(normalEquationInfo, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrization::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    Double change = 0;\n    for(auto b : base)\n      change = std::max(change, b->updateParameter(normalEquationInfo, x, Wz));\n    return change;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::updateCovariance(const SlrNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    for(auto b : base)\n      b->updateCovariance(normalEquationInfo, covariance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrization::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    for(auto b : base)\n      b->writeResults(normalEquationInfo, suffix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nBool SlrParametrizationBase::isEnabled(const SlrNormalEquationInfo &normalEquationInfo, const std::string &name)\n{\n  try\n  {\n    Bool enabled = TRUE;\n    for(const auto &pattern : normalEquationInfo.enableParametrizations)\n      if(std::regex_match(name, pattern.first))\n        enabled = pattern.second;\n    return enabled;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrization.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrization.h\n*\n* @brief Parametrization of SLR observations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRSPARAMETRIZATION__\n#define __GROOPS_SLRSPARAMETRIZATION__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrization = R\"(\n\\section{SlrParametrization}\\label{slrParametrizationType}\nThis class defines the models and parameters of the linearized observation equations\nfor normal points (see \\program{SlrProcessing})\n\\begin{equation}\\label{slrParametrizationType:model}\n  \\M l - \\M f(\\M x_0) = \\left.\\frac{\\partial \\M f(\\M x)}{\\partial \\M x}\\right|_{\\M x_0} \\Delta\\M x + \\M\\epsilon,\n\\end{equation}\nwhere the left side is the observation vector minus the effects computed from the a priori models.\nAfter each least squares adjustment\n(see \\configClass{SlrProcessing:processingStep:estimate}{slrProcessingStepType:estimate})\nthe a priori parameters are updated\n\\begin{equation}\\label{slrParametrizationType:update}\n  \\M x_0 := \\M x_0 + \\Delta\\hat{\\M x}.\n\\end{equation}\nThe vector $\\M x_0$ can be written with\n\\configClass{SlrProcessing:processingStep:writeAprioriSolution}{slrProcessingStepType:writeAprioriSolution}.\nAny \\config{outputfiles} defined in the parametrizations are written with\n\\configClass{SlrProcessing:processingStep:writeResults}{slrProcessingStepType:writeResults}.\n\nEach parametrization (and possible constraint equations) has a \\config{name} which enables\nactivating/deactivating the estimation of subsets of $\\Delta\\M x$ with\n\\configClass{SlrProcessing:processingStep:selectParametrizations}{slrProcessingStepType:selectParametrizations}.\nThe a priori model $\\M f(\\M x_0)$ is unaffected and is always reduced.\n\nThe model for the one way range observations between station $s$ and reflector $r$\ncan be described as\n\\begin{equation}\\label{slrParametrizationType:slrFullModel}\n\\begin{split}\n  f_s^r(\\M x) &= \\frac{1}{2}\\left(\\left\\lVert \\M r^r(t_{bounce})-\\M r_s(t_{trans}) \\right\\rVert\n                          + \\left\\lVert \\M r_s(t_{recv})-\\M r^r(t_{bounce}) \\right\\rVert\\right)  \\\\\n              &+ \\text{troposphere}(t,\\M r_{ss}^r)\n               + \\text{bias}^r + \\text{bias}_s + \\text{bias}_s^r + \\text{other}(\\ldots) + \\epsilon_r^s\n\\end{split}\n\\end{equation}\n\nSee also \\program{SlrProcessing}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrObservation.h\"\n#include \"slr/slrDesignMatrix.h\"\n#include \"slr/slrNormalEquationInfo.h\"\n\n\n/**\n* @defgroup slrParametrizationGroup SlrParametrization\n* @brief Parametrization of SLR observations.\n* @ingroup classesGroup\n* The interface is given by @ref SlrParametrization. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SlrParametrization;\nclass SlrParametrizationBase;\nclass SlrParametrizationGravityField;\ntypedef std::shared_ptr<SlrParametrization> SlrParametrizationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Parametrization of SLR observations.\n* An instance of this class can be created with @ref readConfig. */\nclass SlrParametrization\n{\n  std::vector<SlrParametrizationBase*> base;\n\npublic:\n  /// Constructor.\n  SlrParametrization(Config &config, const std::string &name);\n\n ~SlrParametrization();\n\n  std::vector<const SlrParametrizationGravityField*> getParametrizationGravity() const;\n\n  /** @brief init base on satellites and stations in @p slr. */\n  void init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField);\n\n  /** @brief Correct observation equations/apply models. */\n  void observationCorrections(SlrObservationEquation &eqn) const;\n\n  /** @brief Register parameters in @p normalEquationInfo. */\n  void initParameter(SlrNormalEquationInfo &normalEquationInfo);\n\n  /** @brief Total parameter vector used as priori Taylor point. */\n  Vector aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo) const;\n\n  /** @brief Design matrix for the basic observation equations @p eqn. */\n  void designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const;\n\n  /** @brief Add additional (pseudo-) observations equations to the normals. */\n  void constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const;\n\n  /** @brief Update the values based on the passed estimated dx. */\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz);\n\n  /** @brief Update the covariance information passed by @p covariance matrix. */\n  void updateCovariance(const SlrNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance);\n\n  /** @brief Write the output files defined in the parametrizations. */\n  void writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const;\n\n  /** @brief creates an derived instance of this class. */\n  static SlrParametrizationPtr create(Config &config, const std::string &name) {return SlrParametrizationPtr(new SlrParametrization(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class SlrParametrization.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and an class without points is created.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SlrParametrization */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SlrParametrizationPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass SlrParametrizationBase\n{\npublic:\n  virtual ~SlrParametrizationBase() {}\n\n  static Bool isEnabled(const SlrNormalEquationInfo &normalEquationInfo, const std::string &name);\n\n  virtual void   getParametrizationGravity(std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/) const {}\n  virtual void   init(Slr */*slr*/, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/) {}\n  virtual void   observationCorrections(SlrObservationEquation &/*eqn*/) const {}\n  virtual void   initParameter(SlrNormalEquationInfo &/*normalEquationInfo*/) {}\n  virtual void   aprioriParameter(const SlrNormalEquationInfo &/*normalEquationInfo*/, MatrixSliceRef /*x0*/) const {}\n  virtual void   designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &/*eqn*/, SlrDesignMatrix &/*A*/) const {}\n  virtual void   constraints(const SlrNormalEquationInfo &/*normalEquationInfo*/, MatrixDistributed &/*normals*/, std::vector<Matrix> &/*n*/, Double &/*lPl*/, UInt &/*obsCount*/) const {}\n  virtual Double updateParameter(const SlrNormalEquationInfo &/*normalEquationInfo*/, const_MatrixSliceRef /*x*/, const_MatrixSliceRef /*Wz*/) {return 0;}\n  virtual void   updateCovariance(const SlrNormalEquationInfo &/*normalEquationInfo*/, const MatrixDistributed &/*covariance*/) {}\n  virtual void   writeResults(const SlrNormalEquationInfo &/*normalEquationInfo*/, const std::string &/*suffix*/) const {}\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationConstraints.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationConstraints.h\n*\n* @brief Parameter constraints.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONCONSTRAINTS__\n#define __GROOPS_SLRPARAMETRIZATIONCONSTRAINTS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationConstraints = R\"(\n\\subsection{Constraints}\\label{slrParametrizationType:constraints}\nAdd a pseudo observation equation (constraint)\nfor each selected \\configClass{parameters}{parameterSelectorType}\n\\begin{equation}\n  b-x_0 = 1 \\cdot dx + \\epsilon,\n\\end{equation}\nwhere $b$ is the \\config{bias} and $x_0$ is the a priori value of the parameter\nif \\config{relativeToApriori} is not set.\nThe standard deviation \\config{sigma} is used to weight the observation equations.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"slr/slr.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Parameter constraints.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationConstraints : public SlrParametrizationBase\n{\n  std::string          name;\n  ParameterSelectorPtr parameterSelector;\n  Double               sigma;\n  Double               bias;\n  Bool                 relativeToApriori;\n  Slr                 *slr;\n\npublic:\n  SlrParametrizationConstraints(Config &config);\n\n  void init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/) {this->slr = slr;}\n  void constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n};\n\n/***********************************************/\n\ninline SlrParametrizationConstraints::SlrParametrizationConstraints(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",              name,              Config::OPTIONAL, \"constraint.name\",  \"\");\n    readConfig(config, \"parameters\",        parameterSelector, Config::MUSTSET,  \"\",  \"parameter to constrain\");\n    readConfig(config, \"sigma\",             sigma,             Config::MUSTSET,  \"\",  \"sigma of the constraint (same unit as parameter)\");\n    readConfig(config, \"bias\",              bias,              Config::DEFAULT,  \"0\", \"constrain all selected parameters towards this value\");\n    readConfig(config, \"relativeToApriori\", relativeToApriori, Config::DEFAULT,  \"0\", \"constrain only dx and not full x=dx+x0\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationConstraints::constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    Vector x0 = Vector(normalEquationInfo.parameterCount());\n    if(!relativeToApriori)\n      x0 = slr->aprioriParameter(normalEquationInfo);\n\n    const Double weight = 1./std::pow(sigma, 2);\n    const std::vector<UInt> indices = parameterSelector->indexVector(normalEquationInfo.parameterNames());\n    UInt count = 0;\n    for(UInt index : indices)\n      if(index != NULLINDEX)\n      {\n        const UInt idBlock    = normals.index2block(index);\n        const UInt blockIndex = normals.blockIndex(idBlock);\n        normals.setBlock(idBlock, idBlock);\n        normals.N(idBlock, idBlock)(index-blockIndex, index-blockIndex) += weight;\n        n.at(idBlock)(index-blockIndex, 0) += weight * (bias - x0.at(index));\n        lPl += weight * std::pow(bias - x0.at(index), 2);\n        obsCount++;\n        count++;\n      }\n\n    if(count)\n      logStatus<<\"constrain \"<<name<<\" (\"<<count<<\" parameters)\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationDynamicOrbits.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationDynamicOrbits.cpp\n*\n* @brief Orbits by variational equations.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/timeSeries/timeSeries.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"misc/observation/variationalEquationFromFile.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrParametrization/slrParametrizationDynamicOrbits.h\"\n\n/***********************************************/\n\nSlrParametrizationDynamicOrbits::SlrParametrizationDynamicOrbits(Config &config)\n{\n  try\n  {\n    TimeSeriesPtr stochasticPulse;\n\n    readConfig(config, \"name\",                        name,                        Config::OPTIONAL, \"parameter.dynamicOrbits\", \"used for parameter selection\");\n    readConfig(config, \"selectSatellites\",            selectorSatellites,          Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"outputfileOrbit\",             fileNameOrbit,               Config::OPTIONAL, \"\",     \"variable {satellite} available\");\n    readConfig(config, \"outputfileParameters\",        fileNameParameter,           Config::OPTIONAL, \"\",     \"variable {satellite} available\");\n    readConfig(config, \"inputfileVariational\",        fileNameVariational,         Config::MUSTSET,  \"variational_{loopTime:%D}.{satellite}.dat\", \"variable {satellite} available\");\n    readConfig(config, \"stochasticPulse\",             stochasticPulse,             Config::DEFAULT,  \"\",     \"[mu/s] parametrization of stochastic pulses\");\n    readConfig(config, \"parametrizationAcceleration\", parametrizationAcceleration, Config::DEFAULT,  \"\",     \"orbit force parameters\");\n    readConfig(config, \"ephemerides\",                 ephemerides,                 Config::MUSTSET,  \"\",     \"\");\n    readConfig(config, \"integrationDegree\",           integrationDegree,           Config::DEFAULT,  \"7\",    \"integration of forces by polynomial approximation of degree n\");\n    readConfig(config, \"interpolationDegree\",         interpolationDegree,         Config::DEFAULT,  \"7\",    \"for orbit interpolation and velocity calculation\");\n    if(isCreateSchema(config)) return;\n\n    pulses = stochasticPulse->times();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrParametrizationDynamicOrbits::~SlrParametrizationDynamicOrbits()\n{\n  for(Parameter *para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\nvoid SlrParametrizationDynamicOrbits::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField)\n{\n  try\n  {\n    this->slr = slr;\n    auto selectedSatellites = slr->selectSatellites(selectorSatellites);\n    VariableList varList;\n    varList.setVariable(\"satellite\", \"****\");\n\n    this->paramGravityField = paramGravityField;\n    std::vector<ParametrizationGravityPtr> parameterGravity(paramGravityField.size());\n    for(UInt i=0; i<paramGravityField.size(); i++)\n      parameterGravity.at(i) = paramGravityField.at(i)->parametrization;\n\n    parameters.resize(slr->satellites.size(), nullptr);\n    for(UInt idSat=0; idSat<slr->satellites.size(); idSat++)\n      if(selectedSatellites.at(idSat) && slr->satellites.at(idSat)->useable())\n      {\n        auto para = new Parameter();\n        parameters.at(idSat) = para;\n        para->sat = slr->satellites.at(idSat);\n\n        varList.setVariable(\"satellite\", slr->satellites.at(idSat)->name());\n        FileVariationalEquation file(fileNameVariational(varList));\n        if(file.arcCount() > 1)\n          throw(Exception(\"<\"+fileNameVariational(varList).str()+\"> must not contain more than one arc\"));\n        VariationalEquationArc arc = file.readArc(0/*arcNo*/);\n\n        VariationalEquation variationalEquation;\n        variationalEquation.init(file.satellite(), parameterGravity, parametrizationAcceleration, pulses, ephemerides, integrationDegree);\n        variationalEquation.setArc(arc);\n\n        // parameter names\n        variationalEquation.parameterNameSatellite(para->parameterNames);\n        variationalEquation.parameterNameSatelliteArc(para->parameterNames);\n        for(auto &name : para->parameterNames)\n          name.object = para->sat->name();\n\n        // integrate arc\n        logStatus<<\"integrate variational equations of \"<<slr->satellites.at(idSat)->name()<<Log::endl;\n        para->times     = arc.times;\n        para->PosDesign = Matrix(3*para->times.size(), variationalEquation.parameterCount());\n        para->VelDesign = Matrix(3*para->times.size(), variationalEquation.parameterCount());\n        para->pos       = Vector(3*para->times.size());\n        para->vel       = Vector(3*para->times.size());\n        para->x         = Vector(variationalEquation.parameterCount());\n        para->idxParameterSatellite = variationalEquation.parameterCountGravity();\n        para->polynomial.init(para->times, interpolationDegree);\n        // Log::Timer timer(para->times.size());\n        for(UInt idEpoch=0; idEpoch<para->times.size(); idEpoch++)\n        {\n          // timer.loopStep(idEpoch);\n          variationalEquation.position(idEpoch, para->pos.row(3*idEpoch,3), para->PosDesign.row(3*idEpoch,3));\n          variationalEquation.velocity(idEpoch, para->vel.row(3*idEpoch,3), para->VelDesign.row(3*idEpoch,3));\n        } // for(idEpoch)\n        // timer.loopEnd();\n\n        // set satellites position and velocity to arc values\n        reshape(para->polynomial.interpolate(para->sat->times, para->pos, 3), para->sat->pos.trans());\n        reshape(para->polynomial.interpolate(para->sat->times, para->vel, 3), para->sat->vel.trans());\n      } // for(idSat)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationDynamicOrbits::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n   for(auto para : parameters)\n      if(para)\n        para->index = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto para : parameters)\n      if(para && para->sat->useable() && normalEquationInfo.estimateSatellite.at(para->sat->idSat()))\n      {\n        para->index = normalEquationInfo.parameterNamesSatellite(para->sat->idSat(), para->parameterNames);\n        countPara += para->parameterNames.size();\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i dynamic orbit parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationDynamicOrbits::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para && para->index)\n        copy(para->x.row(para->idxParameterSatellite, normalEquationInfo.count(para->index)),\n             x0.row(normalEquationInfo.index(para->index), normalEquationInfo.count(para->index)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationDynamicOrbits::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.satellite->idSat());\n    if(!para || !para->index)\n      return;\n\n    const Matrix PosDesign = para->polynomial.interpolate(eqn.timesSat, para->PosDesign, 3);\n\n    // gravity\n    UInt idx = 0;\n    for(auto paraGravity : paramGravityField)\n    {\n      if(paraGravity->indexParameter)\n      {\n        MatrixSlice Design(A.column(paraGravity->indexParameter));\n        for(UInt idEpoch=0; idEpoch<eqn.timesSat.size(); idEpoch++)\n          matMult(1., eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxPosSat, eqn.count.at(idEpoch), 3),\n                  PosDesign.slice(3*idEpoch, idx, 3, Design.columns()),\n                  Design.row(eqn.index.at(idEpoch), eqn.count.at(idEpoch)));\n      }\n      idx += paraGravity->parametrization->parameterCount();\n    }\n\n    // satellite related parameters, includes satellite state (6 parameter)\n    MatrixSlice Design(A.column(para->index));\n    for(UInt idEpoch=0; idEpoch<eqn.timesSat.size(); idEpoch++)\n      matMult(1., eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxPosSat, eqn.count.at(idEpoch), 3),\n              PosDesign.slice(3*idEpoch, para->idxParameterSatellite, 3, Design.columns()),\n              Design.row(eqn.index.at(idEpoch), eqn.count.at(idEpoch)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrizationDynamicOrbits::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Slr::InfoParameterChange info(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        Vector dx(para->x.rows());\n\n        // gravity\n        UInt idx = 0;\n        for(auto paraGravity : paramGravityField)\n        {\n          const UInt count = paraGravity->parametrization->parameterCount();\n          if(paraGravity->indexParameter)\n            copy(x.row(normalEquationInfo.index(paraGravity->indexParameter), count), dx.row(idx, count));\n          idx += count;\n        }\n\n        // satellite related parameters, includes satellite state (6 parameter)\n        copy(x.row(normalEquationInfo.index(para->index), normalEquationInfo.count(para->index)),\n             dx.row(para->idxParameterSatellite, normalEquationInfo.count(para->index)));\n\n        para->x   += dx;\n        para->pos += para->PosDesign * dx;\n        para->vel += para->VelDesign * dx;\n\n        auto sat = para->sat;\n        Matrix posOld = sat->pos;\n\n        reshape(para->polynomial.interpolate(sat->times, para->pos, 3), sat->pos.trans());\n        reshape(para->polynomial.interpolate(sat->times, para->vel, 3), sat->vel.trans());\n\n        for(UInt idEpoch=0; idEpoch<sat->times.size(); idEpoch++)\n        {\n          const Double dr = norm(sat->pos.row(idEpoch)-posOld.row(idEpoch));\n          if(info.update(1e3*dr))\n            info.info = \"position satellite (\"+sat->name()+\", \"+sat->times.at(idEpoch).dateTimeStr()+\")\";\n        }\n      }\n    info.print(1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationDynamicOrbits::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameOrbit.empty())\n    {\n      VariableList varList;\n      varList.setVariable(\"satellite\", \"***\");\n      logStatus<<\"write satellite orbits to files <\"<<fileNameOrbit(varList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n\n          OrbitArc arc;\n          for(UInt idEpoch=0; idEpoch<para->times.size(); idEpoch++)\n          {\n            OrbitEpoch epoch;\n            epoch.time     = para->times.at(idEpoch);\n            epoch.position = Vector3d(para->pos.row(3*idEpoch, 3));\n            epoch.velocity = Vector3d(para->vel.row(3*idEpoch, 3));\n            arc.push_back(epoch);\n          }\n          varList.setVariable(\"satellite\", para->sat->name());\n          InstrumentFile::write(fileNameOrbit(varList).appendBaseName(suffix), arc);\n        }\n    }\n\n    if(!fileNameParameter.empty())\n    {\n      VariableList varList;\n      varList.setVariable(\"satellite\", \"***\");\n      logStatus<<\"write estimated satellite parameters to files <\"<<fileNameParameter(varList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n          varList.setVariable(\"satellite\", para->sat->name());\n          writeFileMatrix(fileNameParameter(varList).appendBaseName(suffix), para->x);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationDynamicOrbits.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationDynamicOrbits.h\n*\n* @brief Orbits by variational equations.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONDYNAMICORBITS__\n#define __GROOPS_SLRPARAMETRIZATIONDYNAMICORBITS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationDynamicOrbits = R\"(\n\\subsection{DynamicOrbits}\\label{slrParametrizationType:dynamicOrbits}\nThe estimation of (reduced) dynamic orbits is formulated as variational equations.\nIt is based on \\configFile{inputfileVariational}{variationalEquation} calculated with \\program{PreprocessingVariationalEquation}.\nNecessary integrations are performed by integrating a moving interpolation polynomial of degree \\config{integrationDegree}.\nThe \\configClass{parametrizationAcceleration}{parametrizationAccelerationType} must include at least those\nparameters that were estimated in \\program{PreprocessingVariationalEquationOrbitFit}.\nAdditional \\configClass{stochasticPulse}{timeSeriesType} parameters can be set up to reduce orbit mismodeling.\n\nThe parameters and \\file{parameter names}{parameterName} are divided into global\n\\begin{itemize}\n\\item \\verb|<satellite>:<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:stochasticPulse.x::<time>|,\n\\item \\verb|<satellite>:stochasticPulse.y::<time>|,\n\\item \\verb|<satellite>:stochasticPulse.z::<time>|,\n\\end{itemize}\nand arc related parameters\n\\begin{itemize}\n\\item \\verb|<satellite>:arc<no>.<parametrizationAcceleration>:*:*|,\n\\item \\verb|<satellite>:arc<no>.position0.x::|,\n\\item \\verb|<satellite>:arc<no>.position0.y::|,\n\\item \\verb|<satellite>:arc<no>.position0.z::|.\n\\item \\verb|<satellite>:arc<no>.velocity0.x::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.y::|,\n\\item \\verb|<satellite>:arc<no>.velocity0.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/parametrizationAcceleration/parametrizationAcceleration.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n#include \"slr/slrParametrization/slrParametrizationGravityField.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Orbits by variational equations.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationDynamicOrbits : public SlrParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    SlrSatellitePtr            sat;\n    SlrParameterIndex          index;\n    UInt                       idxParameterSatellite;\n    std::vector<ParameterName> parameterNames;\n    std::vector<Time>          times;\n    Matrix                     PosDesign, VelDesign;\n    Vector                     pos, vel;\n    Vector                     x;\n    Polynomial                 polynomial;\n  };\n\n  Slr                           *slr;\n  std::string                    name;\n  PlatformSelectorPtr            selectorSatellites;\n  std::vector<const SlrParametrizationGravityField*> paramGravityField;\n  FileName                       fileNameOrbit, fileNameParameter, fileNameVariational;\n  std::vector<Time>              pulses;\n  ParametrizationAccelerationPtr parametrizationAcceleration;\n  EphemeridesPtr                 ephemerides;\n  UInt                           integrationDegree, interpolationDegree;\n  std::vector<Parameter*>        parameters;\n\npublic:\n  SlrParametrizationDynamicOrbits(Config &config);\n ~SlrParametrizationDynamicOrbits();\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix    (const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter (const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults    (const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationEarthRotation.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationEarthRotation.cpp\n*\n* @brief EarthRotation.\n* @see SlrParametrization\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"base/planets.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"slr/slrParametrization/slrParametrizationEarthRotation.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief EarthRotation.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\n\n/***********************************************/\n\nSlrParametrizationEarthRotation::SlrParametrizationEarthRotation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",             name,                    Config::OPTIONAL, \"parameter.earthRotation\", \"used for parameter selection\");\n    readConfig(config, \"outputfileEOP\",    fileNameEOP,             Config::OPTIONAL, \"\", \"EOP time series (mjd, xp, yp, sp, dUT1, LOD, X, Y, S)\");\n    readConfig(config, \"estimatePole\",     parametrizationPole,     Config::DEFAULT,  \"\", \"xp, yp [mas]\");\n    readConfig(config, \"estimateUT1\",      parametrizationUT1,      Config::DEFAULT,  \"\", \"rotation angle [ms]\");\n    readConfig(config, \"estimateNutation\", parametrizationNutation, Config::DEFAULT,  \"\", \"dX, dY [mas]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationEarthRotation::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n    xPole     = Vector(2*parametrizationPole->parameterCount());\n    xUT1      = Vector(parametrizationUT1->parameterCount());\n    xNutation = Vector(2*parametrizationNutation->parameterCount());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationEarthRotation::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    indexParameterPole     = SlrParameterIndex();\n    indexParameterUT1      = SlrParameterIndex();\n    indexParameterNutation = SlrParameterIndex();\n\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n    UInt countPara = 0;\n\n    // Polar motion\n    if(parametrizationPole->parameterCount())\n    {\n      std::vector<ParameterName> parameterNames;\n      parametrizationPole->parameterName({ParameterName(\"earth\", \"polarMotion.xp\"), ParameterName(\"earth\", \"polarMotion.yp\")}, parameterNames);\n      indexParameterPole = normalEquationInfo.parameterNamesOther(parameterNames);\n      countPara += parameterNames.size();\n    }\n\n    // Earth rotation angle (UT1)\n    if(parametrizationUT1->parameterCount())\n    {\n      std::vector<ParameterName> parameterNames;\n      parametrizationUT1->parameterName({ParameterName(\"earth\", \"UT1\")}, parameterNames);\n      indexParameterUT1 = normalEquationInfo.parameterNamesOther(parameterNames);\n      countPara += parameterNames.size();\n    }\n\n    // Nutation\n    if(parametrizationNutation->parameterCount())\n    {\n      std::vector<ParameterName> parameterNames;\n      parametrizationNutation->parameterName({ParameterName(\"earth\", \"nutation.X\"), ParameterName(\"earth\", \"nutation.Y\")}, parameterNames);\n      indexParameterNutation = normalEquationInfo.parameterNamesOther(parameterNames);\n      countPara += parameterNames.size();\n    }\n\n    if(countPara)\n      logInfo<<countPara%\"%9i Earth rotation parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationEarthRotation::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(indexParameterPole)\n      copy(xPole, x0.row(normalEquationInfo.index(indexParameterPole), xPole.rows()));\n    if(indexParameterUT1)\n      copy(xUT1, x0.row(normalEquationInfo.index(indexParameterUT1), xUT1.rows()));\n    if(indexParameterNutation)\n      copy(xNutation, x0.row(normalEquationInfo.index(indexParameterNutation), xNutation.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationEarthRotation::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    if(!(indexParameterPole || indexParameterUT1 || indexParameterNutation))\n      return;\n\n    const Matrix eop = slr->polynomialEop.interpolate(eqn.timesStat, slr->eop);\n    for(UInt idEpoch=0; idEpoch<eqn.timesStat.size(); idEpoch++)\n    {\n      const Time   time     = eqn.timesStat.at(idEpoch);\n      const Double xp       = eop(idEpoch, 0);\n      const Double yp       = eop(idEpoch, 1);\n      const Double sp       = eop(idEpoch, 2);\n      const Double deltaUT  = eop(idEpoch, 3) + (time-timeGPS2UTC(time)).seconds();\n      const Double X        = eop(idEpoch, 5);\n      const Double Y        = eop(idEpoch, 6);\n      const Double S        = eop(idEpoch, 7);\n      const Double ERA      = Planets::ERA(timeGPS2UTC(time) + seconds2time(deltaUT));\n      const Matrix rotW     = (rotaryY(Angle(xp)) * rotaryX(Angle(yp))).matrix(); // Polar motion rotation matrix\n      const Matrix rotERA   = rotaryZ(Angle(S-ERA-sp)).matrix();   // Earth rotation angle rotation matrix\n      const Double X2       = X*X;\n      const Double Y2       = Y*Y;\n      const Double a        = 0.5 + 0.125*(X2+Y2);\n      const Matrix rotQ({{1.-a*X2,   -a*X*Y,             X},    // Precession & nutation rotation matrix\n                         {  -a*X*Y, 1.-a*Y2,             Y},\n                         {      -X,      -Y, 1.-a*(X2+Y2)}});\n      const Vector posEarth = slr->rotationCrf2Trf(time).rotate(eqn.posStat.at(idEpoch)).vector();\n\n      // temporal parametrization\n      auto designMatrixTemporal = [&](ParametrizationTemporalPtr parametrization, const_MatrixSliceRef B, const SlrParameterIndex &index)\n      {\n        std::vector<UInt>   idx;\n        std::vector<Double> factor;\n        parametrization->factors(time, idx, factor);\n        MatrixSlice Design(A.column(index).row(eqn.index.at(idEpoch), eqn.count.at(idEpoch)));\n        for(UInt i=0; i<factor.size(); i++)\n          axpy(factor.at(i), B, Design.column(B.columns()*idx.at(i), B.columns()));\n      };\n\n      // Polar motion\n      // ------------\n      if(indexParameterPole)\n      {\n        // partial derivatives of position(CRF) with respect to xp, yp\n        Matrix partWxp(3,3), partWyp(3,3);\n        partWxp(0,2) = partWyp(2,1) = -1;\n        partWxp(2,0) = partWyp(1,2) =  1;\n\n        Matrix B(3,2);\n        matMult(DEG2RAD/3600e3, partWxp, posEarth, B.column(0));\n        matMult(DEG2RAD/3600e3, partWyp, posEarth, B.column(1));\n        B = eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxPosStat, eqn.count.at(idEpoch), 3) * (rotQ * (rotERA * B));\n        designMatrixTemporal(parametrizationPole, B, indexParameterPole);\n      }\n\n      // Earth rotation angle (UT1)\n      // --------------------------\n      if(indexParameterUT1)\n      {\n        // partial derivatives of position(CRF) with respect to UT1\n        Matrix partERA({{std::sin(S-ERA-sp), -std::cos(S-ERA-sp),  0},\n                        {std::cos(S-ERA-sp),  std::sin(S-ERA-sp),  0},\n                        {                 0,                   0,  0}});\n\n        Matrix B = 1e-3 * 2*PI*1.00273781191135448/86400. * (eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxPosStat, eqn.count.at(idEpoch), 3) * (rotQ * (partERA * (rotW * posEarth))));\n        designMatrixTemporal(parametrizationUT1, B, indexParameterUT1);\n      }\n\n      // Nutation\n      // --------\n      if(indexParameterNutation)\n      {\n        // partial derivatives of position(CRF) with respect to X, Y\n        Matrix partQX({{-2*X*a-X2*X/4,   -Y*a-Y*X2/4,                  1},\n                      {  -Y*a-X2*Y/4,       -X*Y2/4,                  0},\n                      {           -1,             0, -2*X*a-X*(X2+Y2)/4}});\n        Matrix partQY({{      -X2*Y/4,   -X*a-X*Y2/4,                  0},\n                      {  -X*a-X*Y2/4, -2*Y*a-Y*Y2/4,                  1},\n                      {            0,            -1, -2*Y*a-Y*(X2+Y2)/4}});\n\n        Matrix B(3,2);\n        Matrix p = rotERA * (rotW * posEarth);\n        matMult(DEG2RAD/3600e3, partQX, p, B.column(0));\n        matMult(DEG2RAD/3600e3, partQY, p, B.column(1));\n        B = eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxPosStat, eqn.count.at(idEpoch), 3) * B;\n        designMatrixTemporal(parametrizationNutation, B, indexParameterNutation);\n      }\n    } // for(idEpoch)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrizationEarthRotation::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n\n    // Polar motion\n    // ------------\n    if(indexParameterPole)\n    {\n      Slr::InfoParameterChange info(\"mm\");\n      const Vector dx = DEG2RAD/3600e3 * x.row(normalEquationInfo.index(indexParameterPole), 2*parametrizationPole->parameterCount());\n      xPole += dx;\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      for(UInt idEpoch=0; idEpoch<slr->times.size(); idEpoch++)\n      {\n        parametrizationPole->factors(slr->times.at(idEpoch), index, factor);\n        Vector p(2);\n        for(UInt k=0; k<factor.size(); k++)\n          axpy(factor.at(k), dx.row(2*index.at(k),2), p);\n\n        // update xp,yp\n        slr->eop(idEpoch, 0) += p(0);\n        slr->eop(idEpoch, 1) += p(1);\n        if(info.update(1e3*DEFAULT_R*norm(p)))\n          info.info = \"earth rotation (pole)\";\n      } // for(idEpoch)\n      info.print(1e-3, maxChange);\n    } // if(ParameterPole)\n\n    // Earth Rotation Angle (UT1)\n    // --------------------------\n    if(indexParameterUT1)\n    {\n      Slr::InfoParameterChange info(\"mm\");\n      const Vector dx = 1e-3 * x.row(normalEquationInfo.index(indexParameterUT1), parametrizationUT1->parameterCount());\n      xUT1 += dx;\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      for(UInt idEpoch=0; idEpoch<slr->times.size(); idEpoch++)\n      {\n        parametrizationUT1->factors(slr->times.at(idEpoch), index, factor);\n        Double p = 0;\n        for(UInt k=0; k<factor.size(); k++)\n          p += factor.at(k) * dx(index.at(k));\n\n        slr->eop(idEpoch, 3) += p;\n        if(info.update(1e3*DEFAULT_R*2*PI*1.00273781191135448/86400*p))\n          info.info = \"earth rotation (UT1)\";\n      } // for(idEpoch)\n      info.print(1e-3, maxChange);\n    } // if(ParameterUT1)\n\n    // Nutation\n    // --------\n    if(indexParameterNutation)\n    {\n      Slr::InfoParameterChange info(\"mm\");\n      const Vector dx = DEG2RAD/3600e3 * x.row(normalEquationInfo.index(indexParameterNutation), 2*parametrizationNutation->parameterCount());\n      xNutation += dx;\n      std::vector<UInt>   index;\n      std::vector<Double> factor;\n      for(UInt idEpoch=0; idEpoch<slr->times.size(); idEpoch++)\n      {\n        parametrizationNutation->factors(slr->times.at(idEpoch), index, factor);\n        Vector p(2);\n        for(UInt k=0; k<factor.size(); k++)\n          axpy(factor.at(k), dx.row(2*index.at(k),2), p);\n\n        // update X,Y\n        slr->eop(idEpoch, 5) += p(0);\n        slr->eop(idEpoch, 6) += p(1);\n        if(info.update(1e3*DEFAULT_R*norm(p)))\n          info.info = \"earth rotation (XY)\";\n      } // for(idEpoch)\n      info.print(1e-3, maxChange);\n    } // if(ParameterNutation)\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationEarthRotation::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameEOP.empty())\n    {\n      logStatus<<\"write EOP to files <\"<<fileNameEOP.appendBaseName(suffix)<<\">\"<<Log::endl;\n      Matrix A(slr->eop.rows(), 1+slr->eop.columns()); // prepend time column\n      copy(slr->eop, A.column(1, slr->eop.columns()));\n      InstrumentFile::write(fileNameEOP.appendBaseName(suffix), Arc(slr->times, A));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationEarthRotation.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationEarthRotation.h\n*\n* @brief EarthRotation.\n* @see SlrParametrization\n*\n* @author Sebastian Strasser\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONEARTHROTATION__\n#define __GROOPS_SLRPARAMETRIZATIONEARTHROTATION__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationEarthRotation = R\"(\n\\subsection{EarthRotation}\\label{slrParametrizationType:earthRotation}\nEarth rotation parameters (ERPs) can be estimated by defining\n\\config{estimatePole} ($x_p$, $y_p$) and \\config{estimateUT1} ($dUT1, LOD$).\n\nEstimating length of day (LOD) with the sign according to IGS conventions requires a negative\nvalue in \\configClass{parametrizationTemporal:trend:timeStep}{parametrizationTemporalType:trend}.\n\nConstraints on the defined parameters can be added via\n\\configClass{parametrization:constraints}{slrParametrizationType:constraints}.\nAn example would be to set up \\configClass{estimateUT1:constant}{parametrizationTemporalType:constant}\nso the $dUT1$ parameter is included in the normal equation system . Since $dUT1$ cannot be\ndetermined by SLR, a hard constraint to its a priori value can then be added.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|earth:polarMotion.xp:<temporal>:<interval>|,\n\\item \\verb|earth:polarMotion.yp:<temporal>:<interval>|,\n\\item \\verb|earth:UT1:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.X:<temporal>:<interval>|,\n\\item \\verb|earth:nutation.>:<temporal>:<interval>|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief EarthRotation.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationEarthRotation : public SlrParametrizationBase\n{\n  Slr                       *slr;\n  std::string                name;\n  FileName                   fileNameEOP;\n  ParametrizationTemporalPtr parametrizationPole, parametrizationUT1, parametrizationNutation;\n  SlrParameterIndex          indexParameterPole,  indexParameterUT1, indexParameterNutation;\n  Vector                     xPole, xUT1, xNutation;\n\npublic:\n  SlrParametrizationEarthRotation(Config &config);\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationGravityField.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationGravityField.cpp\n*\n* @brief GravityField.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"base/planets.h\"\n#include \"files/fileInstrument.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"slr/slrParametrization/slrParametrizationGravityField.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GravityField.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\n\n/***********************************************/\n\nSlrParametrizationGravityField::SlrParametrizationGravityField(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                name,            Config::OPTIONAL, \"parameter.gravityField\", \"used for parameter selection\");\n//     readConfig(config, \"outputfileParameter\", fileName,        Config::OPTIONAL, \"\", \"\");\n    readConfig(config, \"parametrization\",     parametrization, Config::MUSTSET,  \"\", \"\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationGravityField::getParametrizationGravity(std::vector<const SlrParametrizationGravityField*> &paramGravityField) const\n{\n  paramGravityField.push_back(this);\n}\n\n/***********************************************/\n\nvoid SlrParametrizationGravityField::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n    this->x   = Vector(parametrization->parameterCount());\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationGravityField::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    indexParameter = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    std::vector<ParameterName> parameterNames;\n    parametrization->parameterName(parameterNames);\n    for(auto &parameterName : parameterNames)\n      parameterName.object = \"gravityfield\";\n    indexParameter = normalEquationInfo.parameterNamesOther(parameterNames);\n\n    logInfo<<parametrization->parameterCount()%\"%9i gravity field parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationGravityField::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    if(indexParameter)\n      copy(x, x0.row(normalEquationInfo.index(indexParameter), x.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrizationGravityField::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    if(indexParameter)\n      this->x += x.row(normalEquationInfo.index(indexParameter), parametrization->parameterCount());\n    return 0;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationGravityField::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &/*suffix*/) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n//     if(!fileName.empty())\n//     {\n//       logStatus<<\"write sphercial haramonics to files <\"<<fileName.appendBaseName(suffix)<<\">\"<<Log::endl;\n//       writeFileSphericalHarmonics(fileName.appendBaseName(suffix), parametrization->sphericalHarmonics(Time(), x, sigma2x));\n//     }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationGravityField.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationGravityField.h\n*\n* @brief GravityField.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONGRAVITYFIELD__\n#define __GROOPS_SLRPARAMETRIZATIONGRAVITYFIELD__\n\n// Latex documentation\n\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationGravityField = R\"(\n\\subsection{GravityField}\\label{slrParametrizationType:gravityField}\nEstimates a (time depending) gravity field together with at least one\n\\configClass{parametrization:dynamicOrbits}{slrParametrizationType:dynamicOrbits}.\nThe parametrization of the gravity field can be set with\n\\configClass{parametrization}{parametrizationGravityType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|gravityfield:<parametrization>:*:*|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationGravity/parametrizationGravity.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief GravityField.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationGravityField : public SlrParametrizationBase\n{\n  Slr                      *slr;\n  std::string               name;\n\npublic:\n  ParametrizationGravityPtr parametrization;\n  SlrParameterIndex         indexParameter;\n  Vector                    x;\n\n  SlrParametrizationGravityField(Config &config);\n\n  void   getParametrizationGravity(std::vector<const SlrParametrizationGravityField*> &paramGravityField) const override;\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationGroup.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationGroup.h\n*\n* @brief Group.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONGROUP__\n#define __GROOPS_SLRPARAMETRIZATIONGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationGroup = R\"(\n\\subsection{Group}\\label{slrParametrizationType:group}\nGroups a set of parameters. This class can be used to structure complex parametrizations\nand has no further effect itself.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Group.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationGroup : public SlrParametrizationBase\n{\n  SlrParametrizationPtr base;\n\npublic:\n  SlrParametrizationGroup(Config &config);\n ~SlrParametrizationGroup() {}\n\n  void   getParametrizationGravity(std::vector<const SlrParametrizationGravityField*> &paramGravityField) const override;\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   observationCorrections(SlrObservationEquation &eqn) const override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  void   constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   updateCovariance(const SlrNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\ninline SlrParametrizationGroup::SlrParametrizationGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"parametrization\", base, Config::MUSTSET, \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::getParametrizationGravity(std::vector<const SlrParametrizationGravityField*> &paramGravityField) const\n{\n  std::vector<const SlrParametrizationGravityField*> params = base->getParametrizationGravity();\n  paramGravityField.insert(paramGravityField.end(), params.begin(), params.end());\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField)\n{\n  try\n  {\n    base->init(slr, paramGravityField);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    base->initParameter(normalEquationInfo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    base->observationCorrections(eqn);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    x0 += base->aprioriParameter(normalEquationInfo);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    base->designMatrix(normalEquationInfo, eqn, A);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    base->constraints(normalEquationInfo, normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double SlrParametrizationGroup::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz)\n{\n  try\n  {\n    return base->updateParameter(normalEquationInfo, x, Wz);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::updateCovariance(const SlrNormalEquationInfo &normalEquationInfo, const MatrixDistributed &covariance)\n{\n  try\n  {\n    base->updateCovariance(normalEquationInfo, covariance);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationGroup::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    base->writeResults(normalEquationInfo, suffix);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationRangeBiasSatellite.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationRangeBiasSatellite.h\n*\n* @brief Range biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONRANGEBIASSATELLITE__\n#define __GROOPS_SLRPARAMETRIZATIONRANGEBIASSATELLITE__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationRangeBiasSatellite = R\"(\n\\subsection{RangeBiasSatellite}\\label{slrParametrizationType:rangeBiasSatellite}\nEstimates a constant satellite range bias in $[m]$ for\n\\configClass{selectSatellites}{platformSelectorType}.\n\nThe \\file{parameter names}{parameterName} a \\verb|<satellite>:rangeBias::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationRangeBiasSatellite : public SlrParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    SlrSatellitePtr   satellite;\n    SlrParameterIndex index;\n    Double            range;\n  };\n\n  Slr                    *slr;\n  std::string             name;\n  PlatformSelectorPtr     selectorSatellites;\n  std::vector<Parameter*> parameters;\n  FileName                fileNameRangeBias;\n\npublic:\n  SlrParametrizationRangeBiasSatellite(Config &config);\n ~SlrParametrizationRangeBiasSatellite();\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   observationCorrections(SlrObservationEquation &eqn) const override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n/***********************************************/\n\ninline SlrParametrizationRangeBiasSatellite::SlrParametrizationRangeBiasSatellite(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                     name,                     Config::OPTIONAL, \"parameter.rangeBiasSatellite\", \"used for parameter selection\");\n    readConfig(config, \"selectSatellites\",         selectorSatellites,       Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileRangeBias\",      fileNameRangeBias,        Config::MUSTSET,  \"rangeBias_{satellite}.dat\", \"variable {satellite} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SlrParametrizationRangeBiasSatellite::~SlrParametrizationRangeBiasSatellite()\n{\n  for(auto para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatellite::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n    std::vector<Byte> selectedSatellites = slr->selectSatellites(selectorSatellites);\n    parameters.resize(slr->satellites.size(), nullptr);\n    for(UInt idSat=0; idSat<slr->satellites.size(); idSat++)\n      if(selectedSatellites.at(idSat))\n      {\n        auto para = new Parameter();\n        parameters.at(idSat) = para;\n        para->satellite = slr->satellites.at(idSat);\n        para->range     = 0.;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatellite::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    const UInt idSat = eqn.satellite->idSat();\n    if((eqn.type == SlrObservationEquation::RANGE) && (parameters.size() > idSat) && parameters.at(idSat))\n      eqn.l -= parameters.at(idSat)->range;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatellite::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para)\n        para->index = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto para : parameters)\n      if(para && para->satellite->useable() && normalEquationInfo.estimateSatellite.at(para->satellite->idSat()))\n      {\n        para->index = normalEquationInfo.parameterNamesSatellite(para->satellite->idSat(), {ParameterName(para->satellite->name(), \"rangeBias\")});\n        countPara++;\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i satellite range bias parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatellite::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para && para->index)\n        x0(normalEquationInfo.index(para->index), 0) = para->range;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatellite::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    auto para = this->parameters.at(eqn.satellite->idSat());\n    if((eqn.type == SlrObservationEquation::RANGE) && para && para->index)\n      axpy(1., eqn.A.column(SlrObservationEquation::idxRange), A.column(para->index));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double SlrParametrizationRangeBiasSatellite::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Slr::InfoParameterChange infoStat(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        const Double dBias = x(normalEquationInfo.index(para->index), 0);\n        para->range += dBias;\n        if(infoStat.update(1e3*dBias))\n          infoStat.info = \"range bias satellite (\"+para->satellite->name()+\")\";\n      }\n    infoStat.print(1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatellite::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameRangeBias.empty())\n    {\n      VariableList varList;\n      varList.setVariable(\"satellite\", \"****\");\n      logStatus<<\"write range bias to files <\"<<fileNameRangeBias(varList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n          MiscValueEpoch epoch;\n          epoch.time  = slr->times.front();\n          epoch.value = para->range;\n          MiscValueArc arc;\n          arc.push_back(epoch);\n          varList.setVariable(\"satellite\", para->satellite->name());\n          InstrumentFile::write(fileNameRangeBias(varList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationRangeBiasSatelliteApriori.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationRangeBiasSatelliteApriori.h\n*\n* @brief Range biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONRANGEBIASSATELLITEAPRIORI__\n#define __GROOPS_SLRPARAMETRIZATIONRANGEBIASSATELLITEAPRIORI__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationRangeBiasSatelliteApriori = R\"(\n\\subsection{RangeBiasSatelliteApriori}\\label{slrParametrizationType:rangeBiasSatelliteApriori}\nA priori satellite range bias value for \\configClass{selectSatellites}{platformSelectorType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationRangeBiasSatelliteApriori : public SlrParametrizationBase\n{\n  PlatformSelectorPtr       selectorSatellites;\n  FileName                  fileNameRangeBias;\n  std::vector<MiscValueArc> range; // per satellite\n\npublic:\n  SlrParametrizationRangeBiasSatelliteApriori(Config &config);\n ~SlrParametrizationRangeBiasSatelliteApriori() {}\n\n  void init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void observationCorrections(SlrObservationEquation &eqn) const override;\n};\n\n/***********************************************/\n\ninline SlrParametrizationRangeBiasSatelliteApriori::SlrParametrizationRangeBiasSatelliteApriori(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectSatellites\",   selectorSatellites, Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"inputfileRangeBias\", fileNameRangeBias,  Config::MUSTSET,  \"\", \"variable {satellite} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatelliteApriori::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    Bool found = FALSE;\n    auto selectedSatellites = slr->selectSatellites(selectorSatellites);\n    VariableList varList;\n    for(UInt idSat=0; idSat<slr->satellites.size(); idSat++)\n      if(selectedSatellites.at(idSat))\n      {\n        varList.setVariable(\"satellite\", slr->satellites.at(idSat)->name());\n        try\n        {\n          MiscValueArc arc = InstrumentFile::read(fileNameRangeBias(varList));\n          if(range.size() <= idSat)\n            range.resize(idSat+1);\n          range.at(idSat) = arc;\n          found = TRUE;\n        }\n        catch(std::exception &/*e*/)\n        {\n          // logWarningOnce<<\"Unable to read range bias file <\"<<fileNameRangeBias(varList)<<\">, ignoring.\"<<Log::endl;\n        }\n      }\n\n    if(!found)\n    {\n      varList.setVariable(\"satellite\", \"****\");\n      logWarningOnce<<\"Initialization of all range bias failed. Wrong file name <\"<<fileNameRangeBias(varList)<<\">?\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasSatelliteApriori::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    const UInt idSat = eqn.satellite->idSat();\n    if((eqn.type != SlrObservationEquation::RANGE) || (range.size() <= idSat) ||  !range.at(idSat).size())\n      return;\n\n    const MiscValueArc &arc = range.at(idSat);\n    for(UInt i=0; (i<arc.size()) && (arc.at(i).time <= eqn.timesStat.back()); i++)\n      if((i+1 >= arc.size()) || (arc.at(i+1).time >= eqn.timesStat.front()))\n      {\n        eqn.l -= arc.at(i).value;\n        break;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationRangeBiasStation.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationRangeBiasStation.h\n*\n* @brief Range biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATION__\n#define __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATION__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationRangeBiasStation = R\"(\n\\subsection{RangeBiasStation}\\label{slrParametrizationType:rangeBiasStation}\nEstimates a constant station range bias in $[m]$ for\n\\configClass{selectStations}{platformSelectorType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>:rangeBias::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationRangeBiasStation : public SlrParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    SlrStationPtr     station;\n    SlrParameterIndex index;\n    Double            range;\n  };\n\n  Slr                    *slr;\n  std::string             name;\n  PlatformSelectorPtr     selectorStations;\n  std::vector<Parameter*> parameters;\n  FileName                fileNameRangeBias;\n\npublic:\n  SlrParametrizationRangeBiasStation(Config &config);\n ~SlrParametrizationRangeBiasStation();\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   observationCorrections(SlrObservationEquation &eqn) const override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n/***********************************************/\n\ninline SlrParametrizationRangeBiasStation::SlrParametrizationRangeBiasStation(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                name,              Config::OPTIONAL, \"parameter.rangeBiasStation\", \"used for parameter selection\");\n    readConfig(config, \"selectStations\",      selectorStations,  Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileRangeBias\", fileNameRangeBias, Config::MUSTSET,  \"rangeBias_{station}.txt\", \"variable {station} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SlrParametrizationRangeBiasStation::~SlrParametrizationRangeBiasStation()\n{\n  for(auto para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStation::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n\n    auto selectedStations = slr->selectStations(selectorStations);\n    parameters.resize(slr->stations.size(), nullptr);\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat))\n      {\n        auto para = new Parameter();\n        parameters.at(idStat) = para;\n        para->station = slr->stations.at(idStat);\n        para->range   = 0.;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStation::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    const UInt idStat = eqn.station->idStat();\n    if((eqn.type == SlrObservationEquation::RANGE) && (parameters.size() > idStat) && parameters.at(idStat))\n      eqn.l -= parameters.at(idStat)->range;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStation::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para)\n        para->index = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto para : parameters)\n      if(para && para->station->useable() && normalEquationInfo.estimateStation.at(para->station->idStat()))\n      {\n        para->index = normalEquationInfo.parameterNamesStation(para->station->idStat(), {ParameterName(para->station->name(), \"rangeBias\")});\n        countPara++;\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i station range bias parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStation::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para && para->index)\n        x0(normalEquationInfo.index(para->index), 0) = para->range;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStation::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    auto para = this->parameters.at(eqn.station->idStat());\n    if((eqn.type == SlrObservationEquation::RANGE) && para && para->index)\n      axpy(1., eqn.A.column(SlrObservationEquation::idxRange), A.column(para->index));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double SlrParametrizationRangeBiasStation::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Slr::InfoParameterChange infoStat(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        const Double dBias = x(normalEquationInfo.index(para->index), 0);\n        para->range += dBias;\n        if(infoStat.update(1e3*dBias))\n          infoStat.info = \"range bias station (\"+para->station->name()+\")\";\n      }\n    infoStat.print(1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStation::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameRangeBias.empty())\n    {\n      VariableList varList;\n      varList.setVariable(\"station\", \"****\");\n      logStatus<<\"write range bias to files <\"<<fileNameRangeBias(varList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto para : parameters)\n        if(para && para->index)\n        {\n          MiscValueEpoch epoch;\n          epoch.time  = slr->times.front();\n          epoch.value = para->range;\n          MiscValueArc arc;\n          arc.push_back(epoch);\n          varList.setVariable(\"station\", para->station->name());\n          InstrumentFile::write(fileNameRangeBias(varList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationRangeBiasStationApriori.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationRangeBiasStationApriori.h\n*\n* @brief Range biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATIONAPRIORI__\n#define __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATIONAPRIORI__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationRangeBiasStationApriori = R\"(\n\\subsection{RangeBiasStationApriori}\\label{slrParametrizationType:rangeBiasStationApriori}\nA priori station range bias value for all \\configClass{selectStations}{platformSelectorType}.\nThe \\href{https://ilrs.gsfc.nasa.gov/}{ILRS} provides the mean range biases \\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File},\nbut these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive\nsatellites and not for active ones.\nUse \\program{SlrSinexDataHandling2Files} to convert the range biases from\n\\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File} to \\file{instrument file}{instrument}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationRangeBiasStationApriori : public SlrParametrizationBase\n{\n  PlatformSelectorPtr       selectorStations;\n  FileName                  fileNameRangeBias;\n  std::vector<MiscValueArc> range; // per station\n\npublic:\n  SlrParametrizationRangeBiasStationApriori(Config &config);\n ~SlrParametrizationRangeBiasStationApriori() {}\n\n  void init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void observationCorrections(SlrObservationEquation &eqn) const override;\n};\n\n/***********************************************/\n\ninline SlrParametrizationRangeBiasStationApriori::SlrParametrizationRangeBiasStationApriori(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectStations\",     selectorStations,  Config::MUSTSET, R\"([\"all\"])\", \"\");\n    readConfig(config, \"inputfileRangeBias\", fileNameRangeBias, Config::MUSTSET, \"{groopsDataDir}/slr/stations/rangeBias/rangeBias.{station}.txt\", \"variable {station} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationApriori::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    Bool found = FALSE;\n    auto selectedStations   = slr->selectStations(selectorStations);\n    VariableList varList;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat))\n      {\n        varList.setVariable(\"station\", slr->stations.at(idStat)->name());\n        try\n        {\n          MiscValueArc arc = InstrumentFile::read(fileNameRangeBias(varList));\n          if(range.size() <= idStat)\n            range.resize(idStat+1);\n          range.at(idStat) = arc;\n          found = TRUE;\n        }\n        catch(std::exception &/*e*/)\n        {\n          // logWarningOnce<<\"Unable to read range bias file <\"<<fileNameRangeBias(varList)<<\">, ignoring.\"<<Log::endl;\n        }\n      }\n\n    if(!found)\n    {\n      varList.setVariable(\"station\", \"****\");\n      logWarningOnce<<\"Initialization of all range bias failed. Wrong file name <\"<<fileNameRangeBias(varList)<<\">?\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationApriori::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    const UInt idStat = eqn.station->idStat();\n    if((eqn.type != SlrObservationEquation::RANGE) || (range.size() <= idStat) ||  !range.at(idStat).size())\n      return;\n\n    const MiscValueArc &arc = range.at(idStat);\n    for(UInt i=0; (i<arc.size()) && (arc.at(i).time <= eqn.timesStat.back()); i++)\n      if((i+1 >= arc.size()) || (arc.at(i+1).time >= eqn.timesStat.front()))\n      {\n        eqn.l -= arc.at(i).value;\n        break;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationRangeBiasStationSatellite.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationRangeBiasStationSatellite.h\n*\n* @brief Range biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATIONSATELLITE__\n#define __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATIONSATELLITE__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationRangeBiasStationSatellite = R\"(\n\\subsection{RangeBiasStationSatellite}\\label{slrParametrizationType:rangeBiasStationSatellite}\nEstimates the station-satellite range bias in $[m]$ between all\n\\configClass{selectStations}{platformSelectorType} -\n\\configClass{selectSatellites}{platformSelectorType} pairs.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>.<satellite>:rangeBias::|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationRangeBiasStationSatellite : public SlrParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    SlrStationPtr     station;\n    SlrSatellitePtr   satellite;\n    SlrParameterIndex index;\n    Double            range;\n  };\n\n  Slr                 *slr;\n  std::string          name;\n  PlatformSelectorPtr  selectorStations, selectorSatellites;\n  std::vector<std::vector<Parameter*>> parameters; // for each station, satellite\n  FileName             fileNameRangeBias;\n\npublic:\n  SlrParametrizationRangeBiasStationSatellite(Config &config);\n ~SlrParametrizationRangeBiasStationSatellite();\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   observationCorrections(SlrObservationEquation &eqn) const override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n/***********************************************/\n\ninline SlrParametrizationRangeBiasStationSatellite::SlrParametrizationRangeBiasStationSatellite(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                name,               Config::OPTIONAL, \"parameter.rangeBiasSatellite\", \"used for parameter selection\");\n    readConfig(config, \"selectStations\",      selectorStations,   Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectSatellites\",    selectorSatellites, Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"outputfileRangeBias\", fileNameRangeBias,  Config::MUSTSET,  \"rangeBias_{station}_{satellite}.txt\", \"variable {station} and {satellite} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SlrParametrizationRangeBiasStationSatellite::~SlrParametrizationRangeBiasStationSatellite()\n{\n  for(auto &parametersStation : parameters)\n    for(auto para : parametersStation)\n      delete para;\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatellite::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n\n    auto selectedStations   = slr->selectStations(selectorStations);\n    auto selectedSatellites = slr->selectSatellites(selectorSatellites);\n    parameters.resize(slr->stations.size());\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat))\n        for(UInt idSat=0; idSat<slr->satellites.size(); idSat++)\n          if(selectedSatellites.at(idSat))\n          {\n            auto para = new Parameter();\n            parameters.at(idStat).resize(slr->satellites.size(), nullptr);\n            parameters.at(idStat).at(idSat) = para;\n            para->station   = slr->stations.at(idStat);\n            para->satellite = slr->satellites.at(idSat);\n            para->range     = 0.;\n          }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatellite::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    const UInt idStat = eqn.station->idStat();\n    const UInt idSat  = eqn.satellite->idSat();\n    if((eqn.type == SlrObservationEquation::RANGE) && (parameters.size() > idStat) && (parameters.at(idStat).size() > idSat) && parameters.at(idStat).at(idSat))\n      eqn.l -= parameters.at(idStat).at(idSat)->range;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatellite::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto parametersStation : parameters)\n      for(auto para : parametersStation)\n        if(para)\n          para->index = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto &parametersStation : parameters)\n      for(auto para : parametersStation)\n        if(para && para->satellite->useable() && normalEquationInfo.estimateSatellite.at(para->satellite->idSat())\n                && para->station->useable()   && normalEquationInfo.estimateStation.at(para->station->idStat()))\n        {\n          para->index = normalEquationInfo.parameterNamesStation(para->station->idStat(),\n                                                                 {ParameterName(para->station->name()+\".\"+para->satellite->name(), \"rangeBias\")});\n          countPara++;\n        }\n    if(countPara)\n      logInfo<<countPara%\"%9i satellite range bias parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatellite::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto &parametersStation : parameters)\n      for(auto para : parametersStation)\n        x0(normalEquationInfo.index(para->index), 0) = para->range;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatellite::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    auto &parametersStation = this->parameters.at(eqn.station->idStat());\n    if(parametersStation.size())\n    {\n      auto para = parametersStation.at(eqn.satellite->idSat());\n      if((eqn.type == SlrObservationEquation::RANGE) && para && para->index)\n        axpy(1., eqn.A.column(SlrObservationEquation::idxRange), A.column(para->index));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Double SlrParametrizationRangeBiasStationSatellite::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Slr::InfoParameterChange infoStat(\"mm\");\n    for(auto &parametersStation : parameters)\n      for(auto para : parametersStation)\n        if(para && para->index)\n        {\n          const Double dBias = x(normalEquationInfo.index(para->index), 0);\n          para->range += dBias;\n          if(infoStat.update(1e3*dBias))\n            infoStat.info = \"range bias station - satellite (\"+para->station->name()+\".\"+para->satellite->name()+\")\";\n        }\n    infoStat.print(1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatellite::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameRangeBias.empty())\n    {\n      VariableList varList;\n      varList.setVariable(\"station\",   \"****\");\n      varList.setVariable(\"satellite\", \"****\");\n      logStatus<<\"write range bias to files <\"<<fileNameRangeBias(varList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(auto &parametersStation : parameters)\n        for(auto para : parametersStation)\n          if(para && para->index)\n          {\n            MiscValueEpoch epoch;\n            epoch.time  = slr->times.front();\n            epoch.value = para->range;\n            MiscValueArc arc;\n            arc.push_back(epoch);\n            varList.setVariable(\"station\",   para->station->name());\n            varList.setVariable(\"satellite\", para->satellite->name());\n            InstrumentFile::write(fileNameRangeBias(varList).appendBaseName(suffix), arc);\n          }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationRangeBiasStationSatelliteApriori.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationRangeBiasStationSatelliteApriori.h\n*\n* @brief Range biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATIONSATELLITEAPRIORI__\n#define __GROOPS_SLRPARAMETRIZATIONRANGEBIASSTATIONSATELLITEAPRIORI__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationRangeBiasStationSatelliteApriori = R\"(\n\\subsection{RangeBiasStationSatelliteApriori}\\label{slrParametrizationType:rangeBiasStationSatelliteApriori}\nA priori station-satellite range bias value between all \\configClass{selectStations}{platformSelectorType} -\n\\configClass{selectSatellites}{platformSelectorType} pairs.\n\nFor standard \\href{https://ilrs.gsfc.nasa.gov/}{ILRS} processing this class should be setup twice.\nOnce for the model from José Rodríguez (see \\program{SlrComModel2RangeBiasStationSatellite}) and additionally for\nbiases from the \\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File} converted with \\program{SlrSinexDataHandling2Files}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationRangeBiasStationSatelliteApriori : public SlrParametrizationBase\n{\n  PlatformSelectorPtr selectorStations, selectorSatellites;\n  FileName            fileNameRangeBias;\n  std::vector<std::vector<MiscValueArc>> range; // per station, satellite\n\npublic:\n  SlrParametrizationRangeBiasStationSatelliteApriori(Config &config);\n ~SlrParametrizationRangeBiasStationSatelliteApriori() {}\n\n  void init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void observationCorrections(SlrObservationEquation &eqn) const override;\n};\n\n/***********************************************/\n\ninline SlrParametrizationRangeBiasStationSatelliteApriori::SlrParametrizationRangeBiasStationSatelliteApriori(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectStations\",     selectorStations,   Config::MUSTSET, R\"([\"all\"])\", \"\");\n    readConfig(config, \"selectSatellites\",   selectorSatellites, Config::MUSTSET, R\"([\"all\"])\", \"\");\n    readConfig(config, \"inputfileRangeBias\", fileNameRangeBias,  Config::MUSTSET, \"{groopsDataDir}/slr/rangeBiasStationSatellite/modelRodriguez/rangeBias.{station}.{satellite}.txt\", \"variable {station} and {satellite} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatelliteApriori::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    Bool found = FALSE;\n    auto selectedStations   = slr->selectStations(selectorStations);\n    auto selectedSatellites = slr->selectSatellites(selectorSatellites);\n    VariableList varList;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat))\n        for(UInt idSat=0; idSat<slr->satellites.size(); idSat++)\n          if(selectedSatellites.at(idSat))\n          {\n            varList.setVariable(\"station\",   slr->stations.at(idStat)->name());\n            varList.setVariable(\"satellite\", slr->satellites.at(idSat)->name());\n            try\n            {\n              MiscValueArc arc = InstrumentFile::read(fileNameRangeBias(varList));\n              if(range.size() <= idStat)\n                range.resize(idStat+1);\n              if(range.at(idStat).size() <= idSat)\n                range.at(idStat).resize(idSat+1);\n              range.at(idStat).at(idSat) = arc;\n              found = TRUE;\n            }\n            catch(std::exception &/*e*/)\n            {\n              // logWarningOnce<<\"Unable to read range bias file <\"<<fileNameRangeBias(varList)<<\">, ignoring.\"<<Log::endl;\n            }\n          }\n\n    if(!found)\n    {\n      varList.setVariable(\"station\",   \"****\");\n      varList.setVariable(\"satellite\", \"****\");\n      logWarningOnce<<\"Initialization of all range bias failed. Wrong file name <\"<<fileNameRangeBias(varList)<<\">?\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationRangeBiasStationSatelliteApriori::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    const UInt idStat = eqn.station->idStat();\n    const UInt idSat  = eqn.satellite->idSat();\n    if((eqn.type != SlrObservationEquation::RANGE) || (range.size() <= idStat) || (range.at(idStat).size() <= idSat) || !range.at(idStat).at(idSat).size())\n      return;\n\n    const MiscValueArc &arc = range.at(idStat).at(idSat);\n    for(UInt i=0; (i<arc.size()) && (arc.at(i).time <= eqn.timesStat.back()); i++)\n      if((i+1 >= arc.size()) || (arc.at(i+1).time >= eqn.timesStat.front()))\n      {\n        eqn.l -= arc.at(i).value;\n        break;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationStaticPositions.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationStaticPositions.cpp\n*\n* @brief Position estimation with no-net constraints.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"inputOutput/system.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileGriddedData.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n#include \"slr/slrParametrization/slrParametrizationStaticPositions.h\"\n\n/***********************************************/\n\nSlrParametrizationStaticPositions::SlrParametrizationStaticPositions(Config &config)\n{\n  try\n  {\n    sigmaNoNetTranslation = sigmaNoNetRotation = sigmaNoNetScale = 0;\n    huber = 1e99; huberPower = 0;\n\n    readConfig(config, \"name\",                      name,                   Config::OPTIONAL, \"parameter.staticPositions\", \"used for parameter selection\");\n    readConfig(config, \"selectStations\",            selectorStations,       Config::MUSTSET,  \"\", \"\");\n    readConfig(config, \"outputfileGriddedPosition\", fileNameGrid,           Config::OPTIONAL, \"output/gridPosition_{loopTime:%D}.dat\",              \"delta north east up for all stations\");\n    readConfig(config, \"outputfilePosition\",        fileNamePosition,       Config::OPTIONAL, \"output/stationPosition_{loopTime:%D}.{station}.dat\", \"variable {station} available, full estimated coordinates (in TRF)\");\n    readConfig(config, \"nameConstraint\",            nameConstraint,         Config::OPTIONAL, \"constraint.staticPositions\", \"used for parameter selection\");\n    readConfig(config, \"selectNoNetStations\",       selectorNoNetStations,  Config::DEFAULT,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"inputfileNoNetPositions\",   fileNameNoNetPositions, Config::OPTIONAL, \"{groopsDataDir}/slr/stations/position/slrf2020_CM/stationPosition.{station}.dat\", \"variable {station} available, precise coordinates used for no-net constraints (in TRF)\");\n    readConfig(config, \"noNetTranslationSigma\",     sigmaNoNetTranslation,  Config::OPTIONAL, \"0\",     \"(0 = unconstrained) sigma [m] for no-net translation constraint on station coordinates\");\n    readConfig(config, \"noNetRotationSigma\",        sigmaNoNetRotation,     Config::OPTIONAL, \"0.001\", \"(0 = unconstrained) sigma [m] at Earth's surface for no-net rotation constraint on station coordinates\");\n    readConfig(config, \"noNetScaleSigma\",           sigmaNoNetScale,        Config::OPTIONAL, \"0\",     \"(0 = unconstrained) sigma [m] for no-net scale constraint on station coordinates\");\n    readConfig(config, \"huber\",                     huber,                  Config::OPTIONAL, \"2.5\",   \"stations > huber*sigma0 are downweighted in no-net constraint\");\n    readConfig(config, \"huberPower\",                huberPower,             Config::OPTIONAL, \"1.5\",   \"stations > huber: sigma=(e/huber)^huberPower*sigma0\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationStaticPositions::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr  = slr;\n    index.resize(slr->stations.size());\n    selectedStations = slr->selectStations(selectorStations);\n\n    // apriori positions\n    pos.resize(slr->stations.size());\n    pos0.resize(slr->stations.size());\n    for(auto stat : slr->stations)\n      if(selectedStations.at(stat->idStat()) && stat->useable())\n        pos.at(stat->idStat()) = pos0.at(stat->idStat()) = stat->pos;\n\n    // no net-positions\n    // ----------------\n    if(sigmaNoNetRotation || sigmaNoNetTranslation || sigmaNoNetScale)\n    {\n      std::vector<const Platform*> platforms(slr->stations.size(), nullptr);\n      for(auto stat : slr->stations)\n        if(selectedStations.at(stat->idStat()) && stat->useable())\n          platforms.at(stat->idStat()) = &stat->platform;\n\n      // no net positions\n      noNetPos = pos;\n      if(!fileNameNoNetPositions.empty())\n      {\n        noNetPos = std::vector<Vector3d>(pos0.size(), Vector3d(NAN_EXPR, NAN_EXPR, NAN_EXPR));\n        Bool someDisabled = FALSE;\n        do\n        {\n          someDisabled = FALSE;\n          selectedNoNetStations = selectorNoNetStations->select(slr->times.front(), slr->times.back(), platforms);\n          for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n            if(selectedNoNetStations.at(idStat) && std::isnan(noNetPos.at(idStat).r()))\n            {\n              try\n              {\n                VariableList fileNameVariableList;\n                fileNameVariableList.setVariable(\"station\", slr->stations.at(idStat)->name());\n                if(!System::exists(fileNameNoNetPositions(fileNameVariableList)))\n                  throw(Exception(\"file <\"+fileNameNoNetPositions(fileNameVariableList).str()+\"> not exist\"));\n                const Time timesMid = 0.5*(slr->times.front()+slr->times.back());\n                Vector3dArc arc = InstrumentFile::read(fileNameNoNetPositions(fileNameVariableList));\n                auto iter = std::min_element(arc.begin(), arc.end(), [&](const Epoch &e1, const Epoch &e2)\n                                            {return std::fabs((e1.time-timesMid).mjd()) < std::fabs((e2.time-timesMid).mjd());});\n                if(!arc.size() || ((arc.size() > 1) && (std::fabs((iter->time-timesMid).mjd()) > 0.5*medianSampling(arc.times()).mjd())))\n                  throw(Exception(\"No a-priori position found\"));\n                noNetPos.at(idStat) = iter->vector3d;\n              }\n              catch(std::exception &e)\n              {\n                logWarningOnce<<slr->stations.at(idStat)->name()<<\": \"<<e.what()<<\" -> not used for computation of net translation/rotation/scale\"<<Log::endl;\n                platforms.at(idStat) = nullptr;\n                someDisabled = TRUE;\n              }\n            }\n        }\n        while(someDisabled);\n      } // if(!fileNameNoNetPositions.empty())\n\n      selectedNoNetStations = selectorNoNetStations->select(slr->times.front(), slr->times.back(), platforms);\n      const UInt countStation = std::count(selectedNoNetStations.begin(), selectedNoNetStations.end(), TRUE);\n      logInfo<<\"  \"<<countStation<<\" stations contribute to the computation of net translation/rotation/scale\"<<Log::endl;\n      if(!countStation)\n        throw(Exception(\"no stations contribute to the computation of net translation/rotation/scale\"));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationStaticPositions::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    std::fill(index.begin(), index.end(), SlrParameterIndex());\n    applyConstraint = FALSE;\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countPara = 0;\n    for(auto stat : slr->stations)\n      if(stat->useable() && selectedStations.at(stat->idStat()) && normalEquationInfo.estimateStation.at(stat->idStat()))\n      {\n        std::vector<ParameterName> parameterNames({{stat->name(), \"position.x\"}, {stat->name(), \"position.y\"}, {stat->name(), \"position.z\"}});\n        index.at(stat->idStat()) = normalEquationInfo.parameterNamesStation(stat->idStat(), parameterNames);\n        countPara += parameterNames.size();\n      }\n    if(countPara)\n      logInfo<<countPara%\"%9i station static position parameters\"s<<Log::endl;\n\n    applyConstraint = isEnabled(normalEquationInfo, nameConstraint) && (sigmaNoNetRotation || sigmaNoNetTranslation) && countPara;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationStaticPositions::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(UInt idStat=0; idStat<index.size(); idStat++)\n      if(index.at(idStat))\n        copy(pos.at(idStat).vector(), x0.row(normalEquationInfo.index(index.at(idStat)), 3));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationStaticPositions::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    if(index.at(eqn.station->idStat()))\n    {\n      MatrixSlice Design(A.column(index.at(eqn.station->idStat())));\n      for(UInt idEpoch=0; idEpoch<eqn.timesStat.size(); idEpoch++)\n        matMult(1., eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxPosStat, eqn.count.at(idEpoch), 3),\n                slr->rotationCrf2Trf(eqn.timesStat.at(idEpoch)).matrix().trans(),\n                Design.row(eqn.index.at(idEpoch), eqn.count.at(idEpoch)));\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationStaticPositions::constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const\n{\n  try\n  {\n    if(!applyConstraint)\n      return;\n\n    UInt noNetCount = 0;\n    const UInt idxNNT = noNetCount; if(sigmaNoNetTranslation) noNetCount += 3;\n    const UInt idxNNR = noNetCount; if(sigmaNoNetRotation)    noNetCount += 3;\n    const UInt idxNNS = noNetCount; if(sigmaNoNetScale)       noNetCount += 1;\n\n    UInt stationCount = 0;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedNoNetStations.at(idStat) && index.at(idStat))\n        stationCount++;\n\n    // observation equations\n    Vector l(3*stationCount);\n    Matrix A(l.rows(), noNetCount);\n    UInt i = 0;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedNoNetStations.at(idStat) && index.at(idStat))\n      {\n        copy((noNetPos.at(idStat)-pos.at(idStat)).vector(), l.row(3*i, 3));\n        if(sigmaNoNetTranslation)\n          copy(identityMatrix(3), A.slice(3*i, idxNNT, 3, 3));\n        if(sigmaNoNetRotation)\n        {\n          const Vector3d pos = noNetPos.at(idStat)/DEFAULT_R;\n          A(3*i+0, idxNNR+1) =  pos.z(); A(3*i+0, idxNNR+2) = -pos.y();\n          A(3*i+1, idxNNR+0) = -pos.z(); A(3*i+1, idxNNR+2) =  pos.x();\n          A(3*i+2, idxNNR+0) =  pos.y(); A(3*i+2, idxNNR+1) = -pos.x();\n        }\n        if(sigmaNoNetScale)\n        {\n          const Vector3d posForScale = noNetPos.at(idStat)/DEFAULT_R;\n          A(3*i+0, idxNNS+0) = posForScale.x();\n          A(3*i+1, idxNNS+0) = posForScale.y();\n          A(3*i+2, idxNNS+0) = posForScale.z();\n        }\n        i++;\n      }\n\n    // compute station weights for no-net constraint\n    Vector x(A.columns()), sigma;\n    if(rootMeanSquare(l) > 1e-4)\n      x = Vce::robustLeastSquares(A, l, 3, huber, huberPower, 30, sigma);\n\n    // compute noNetEstimator = (A'PA)^(-1) A'P\n    for(UInt i=0; i<sigma.rows(); i++)\n      A.row(3*i, 3) *= 1./sigma(i);\n    const Vector tau = QR_decomposition(A);\n    const Matrix W = A.row(0, noNetCount);\n    generateQ(A, tau);\n    triangularSolve(1., W, A.trans());\n    for(UInt i=0; i<sigma.rows(); i++)\n      A.row(3*i, 3) *= 1./sigma(i);\n    noNetEstimator = A.trans();\n\n    if(sigmaNoNetTranslation) logStatus<<\"apply no-net translation to station positions, apriori (\"<<1e3*x(idxNNT+0)%\"%.1f, \"s<<1e3*x(idxNNT+1)%\"%.1f, \"s<<1e3*x(idxNNT+2)%\"%.1f) mm\"s<<Log::endl;\n    if(sigmaNoNetRotation)    logStatus<<\"apply no-net rotation to station positions,    apriori (\"<<1e3*x(idxNNR+0)%\"%.1f, \"s<<1e3*x(idxNNR+1)%\"%.1f, \"s<<1e3*x(idxNNR+2)%\"%.1f) mm\"s<<Log::endl;\n    if(sigmaNoNetScale)       logStatus<<\"apply no-net scale to receiver positions,      apriori (\"<<1e3*x(idxNNS+0)%\"%.1f) mm\"s<<Log::endl;\n    if(sigmaNoNetRotation || sigmaNoNetTranslation || sigmaNoNetScale)\n    {\n      logStatus<<\"  no-net coordinate residuals rms = \"<<1e3*rootMeanSquare(l-A*x)%\"%.1f mm, \"s<<Log::endl;\n      UInt i = 0;\n      if(sigma.size())\n        for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n          if(selectedNoNetStations.at(idStat) && index.at(idStat))\n          {\n            if(sigma(i) > std::pow(3./huber, huberPower))\n              logWarning<<\"  \"<<slr->stations.at(idStat)->name()<<\" outlier sigma = \"<<sigma(i)%\"%.2f\"s<<Log::endl;\n            i++;\n          }\n    }\n\n    // weighted no-net constraints\n    SlrDesignMatrix Design(normalEquationInfo, x);\n    if(sigmaNoNetTranslation) Design.l.row(idxNNT, 3)  *= 1./sigmaNoNetTranslation;\n    if(sigmaNoNetRotation)    Design.l.row(idxNNR, 3)  *= 1./sigmaNoNetRotation;\n    if(sigmaNoNetScale)       Design.l.row(idxNNS, 1)  *= 1./sigmaNoNetScale;\n    if(sigmaNoNetTranslation) A.trans().row(idxNNT, 3) *= 1./sigmaNoNetTranslation;\n    if(sigmaNoNetRotation)    A.trans().row(idxNNR, 3) *= 1./sigmaNoNetRotation;\n    if(sigmaNoNetScale)       A.trans().row(idxNNS, 1) *= 1./sigmaNoNetScale;\n    i = 0;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedNoNetStations.at(idStat) && index.at(idStat))\n        copy(A.row(3*i++,3).trans(), Design.column(index.at(idStat)));\n    Design.accumulateNormals(normals, n, lPl, obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrizationStaticPositions::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return 0;\n\n    // compute no-net translation and not-net rotation\n    std::string infoNoNet;\n    if(applyConstraint)\n    {\n      UInt noNetCount = 0;\n      const UInt idxNNT = noNetCount; if(sigmaNoNetTranslation) noNetCount += 3;\n      const UInt idxNNR = noNetCount; if(sigmaNoNetRotation)    noNetCount += 3;\n      const UInt idxNNS = noNetCount; if(sigmaNoNetScale)       noNetCount += 1;\n      Vector noNetPara(noNetCount);\n      UInt i=0;\n      for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n        if(selectedNoNetStations.at(idStat) && index.at(idStat))\n        {\n          Vector dpos = (pos.at(idStat)-noNetPos.at(idStat)).vector();\n          dpos += x.row(normalEquationInfo.index(index.at(idStat)), 3);\n          matMult(1., noNetEstimator.column(3*i++, 3), dpos, noNetPara);\n        }\n      if(sigmaNoNetTranslation) infoNoNet += \", netTranslation (\"+1e3*noNetPara(idxNNT+0)%\"%.1f, \"s+1e3*noNetPara(idxNNT+1)%\"%.1f, \"s+1e3*noNetPara(idxNNT+2)%\"%.1f) mm\"s;\n      if(sigmaNoNetRotation)    infoNoNet += \", netRotation (\"   +1e3*noNetPara(idxNNR+0)%\"%.1f, \"s+1e3*noNetPara(idxNNR+1)%\"%.1f, \"s+1e3*noNetPara(idxNNR+2)%\"%.1f) mm\"s;\n      if(sigmaNoNetScale)       infoNoNet += \", netScale (\"      +1e3*noNetPara(idxNNS+0)%\"%.1f) mm\"s;\n    }\n\n    // update positions\n    Double maxChange = 0;\n    Slr::InfoParameterChange info(\"mm\");\n    for(UInt idStat=0; idStat<index.size(); idStat++)\n      if(index.at(idStat))\n      {\n        const Vector3d dpos(x.row(normalEquationInfo.index(index.at(idStat)), 3));\n        pos.at(idStat) += dpos;\n        slr->stations.at(idStat)->pos += dpos;\n        if(info.update(1e3*dpos.r()))\n          info.info = \"position station (\"+slr->stations.at(idStat)->name()+\")\"+infoNoNet;\n      }\n    info.print(1e-3, maxChange);\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationStaticPositions::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    if(!fileNameGrid.empty())\n    {\n      // collect positions\n      Matrix data(slr->stations.size(), 6); // x, y, z , dx, dy, dz\n      for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n        if(index.at(idStat))\n        {\n          const Transform3d trf2local = slr->stations.at(idStat)->global2localFrame(slr->stations.at(idStat)->times.front());\n          copy(pos.at(idStat).vector().trans(), data.slice(idStat, 0, 1, 3));\n          copy(trf2local.transform(pos.at(idStat)-pos0.at(idStat)).vector().trans(), data.slice(idStat, 3, 1, 3)); // dpos in NEU (north, east, up) system\n        }\n\n      logStatus<<\"write station grid file <\"<<fileNameGrid.appendBaseName(suffix)<<\">\"<<Log::endl;\n      std::vector<Vector3d>            point;\n      std::vector<std::vector<Double>> value(3);\n      for(UInt idStat=0; idStat<data.rows(); idStat++)\n        if(index.at(idStat))\n        {\n          point.push_back(Vector3d(data.slice(idStat, 0, 1, 3)));\n          value.at(0).push_back(data(idStat, 3)); // north\n          value.at(1).push_back(data(idStat, 4)); // east\n          value.at(2).push_back(data(idStat, 5)); // up\n        }\n      writeFileGriddedData(fileNameGrid.appendBaseName(suffix), GriddedData(Ellipsoid(), point, std::vector<Double>(point.size(), 1.), value));\n    }\n\n    if(!fileNamePosition.empty())\n    {\n      VariableList varList;\n      varList.setVariable(\"station\", \"****\");\n      logStatus<<\"write positions to files <\"<<fileNamePosition(varList).appendBaseName(suffix)<<\">\"<<Log::endl;\n      for(UInt idStat=0; idStat<index.size(); idStat++)\n        if(index.at(idStat))\n        {\n          Vector3dEpoch epoch;\n          epoch.time     = slr->stations.at(idStat)->times.at(static_cast<UInt>(std::floor(0.5*slr->stations.at(idStat)->times.size())));\n          epoch.vector3d = pos.at(idStat);\n          Vector3dArc arc;\n          arc.push_back(epoch);\n          varList.setVariable(\"station\", slr->stations.at(idStat)->name());\n          InstrumentFile::write(fileNamePosition(varList).appendBaseName(suffix), arc);\n        }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationStaticPositions.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationStaticPositions.h\n*\n* @brief Position estimation with no-net constraints.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONSTATICPOSITIONS__\n#define __GROOPS_SLRPARAMETRIZATIONSTATICPOSITIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationStaticPositions = R\"(\n\\subsection{StaticPositions}\\label{slrParametrizationType:staticPositions}\nEstimates a static position for all\n\\configClass{selectReceivers}{platformSelectorType} in the terrestrial frame.\n\nNo-net constraints can be applied for a subset of stations,\n\\configClass{selectNoNetReceivers}{platformSelectorType}, with a\nstandard deviation of \\config{noNetTranslationSigma} and \\config{noNetRotationSigma} and \\config{noNetScaleSigma} and \\config{noNetScaleSigma}.\nIf the template \\configFile{inputfileNoNetPositions}{stringList} is provided\nthe constraints are applied relatively to these positions. Only stations with an existing position file\nare considered. Without \\configFile{inputfileNoNetPositions}{stringList}\nthe constraints are applied towards the apriori values from\n\\configClass{SlrProcessing:station}{slrStationGeneratorType}.\nAs a single corrupted station position can disturb the no-net conditions,\nthe rotation/translation parameters are estimated in a\n\\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}\nbeforehand. The computed weight matrix is used to downweight corrupted stations\nin the constraint equations.\n\nIn case you want to align to an ITRF/ILRS reference frame, precise coordinates can be\ngenerated with \\program{Sinex2StationPositions}.\n\nThe \\file{parameter names}{parameterName} are\n\\begin{itemize}\n\\item \\verb|<station>:position.x::|,\n\\item \\verb|<station>:position.y::|,\n\\item \\verb|<station>:position.z::|.\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Position estimation with no-net constraints.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationStaticPositions : public SlrParametrizationBase\n{\n  Slr                           *slr;\n  std::string                    name, nameConstraint;\n  PlatformSelectorPtr            selectorStations, selectorNoNetStations;\n  std::vector<Byte>              selectedStations, selectedNoNetStations;\n  FileName                       fileNameGrid, fileNamePosition, fileNameNoNetPositions;\n  Bool                           applyConstraint;\n  Double                         sigmaNoNetTranslation, sigmaNoNetRotation, sigmaNoNetScale;\n  Double                         huber, huberPower;\n  std::vector<SlrParameterIndex> index; // for each station\n  std::vector<Vector3d>          pos, pos0, noNetPos;\n  mutable Matrix                 noNetEstimator;\n\npublic:\n  SlrParametrizationStaticPositions(Config &config);\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  void   constraints(const SlrNormalEquationInfo &normalEquationInfo, MatrixDistributed &normals, std::vector<Matrix> &n, Double &lPl, UInt &obsCount) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationTimeBias.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationTimeBias.cpp\n*\n* @brief Time biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrParametrization/slrParametrizationTimeBias.h\"\n\n/***********************************************/\n\nSlrParametrizationTimeBias::SlrParametrizationTimeBias(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",             name,                    Config::OPTIONAL, \"parameter.timeBias\", \"used for parameter selection\");\n    readConfig(config, \"selectStations\",   selectorStations,        Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"estimateTimeBias\", parametrizationTemporal, Config::MUSTSET,  \"\", \"[ms]\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrParametrizationTimeBias::~SlrParametrizationTimeBias()\n{\n  for(auto para : paraStations)\n    delete para;\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTimeBias::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n\n    auto selectedStations = slr->selectStations(selectorStations);\n    paraStations.resize(slr->stations.size(), nullptr);\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat) && slr->stations.at(idStat)->useable())\n      {\n        auto para = new Parameter();\n        paraStations.at(idStat) = para;\n        para->x       = Vector(parametrizationTemporal->parameterCount());\n        para->station = slr->stations.at(idStat);\n        if(!para->station->timeBiases.size())\n          para->station->timeBiases = Vector(para->station->times.size());\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTimeBias::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : paraStations)\n      if(para)\n        para->index = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    UInt countParaStat = 0;\n    for(auto para : paraStations)\n      if(para && para->station->useable() && normalEquationInfo.estimateStation.at(para->station->idStat()))\n      {\n        std::vector<ParameterName> parameterNames;\n        parametrizationTemporal->parameterName({ParameterName(para->station->name(), \"timeBias\")}, parameterNames);\n        para->index = normalEquationInfo.parameterNamesStation(para->station->idStat(), parameterNames);\n        countParaStat += para->x.rows();\n      }\n    if(countParaStat)\n      logInfo<<countParaStat%\"%9i time bias parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTimeBias::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    for(auto para : paraStations)\n      if(para && para->index)\n        copy(para->x, x0.row(normalEquationInfo.index(para->index), para->x.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTimeBias::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    auto paraStations = this->paraStations.at(eqn.station->idStat());\n    if(paraStations && paraStations->index)\n    {\n      MatrixSlice Design(A.column(paraStations->index));\n      for(UInt idEpoch=0; idEpoch<eqn.timesStat.size(); idEpoch++)\n      {\n        const const_MatrixSlice B(eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxTime, eqn.count.at(idEpoch), 1));\n        std::vector<UInt>   idx;\n        std::vector<Double> factor;\n        parametrizationTemporal->factors(eqn.timesStat.at(idEpoch), idx, factor);\n        for(UInt i=0; i<factor.size(); i++)\n          axpy(1e-3*factor.at(i), B, Design.slice(eqn.index.at(idEpoch), idx.at(i), eqn.count.at(idEpoch), 1)); // [ms]\n      }\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrizationTimeBias::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    Double maxChange = 0;\n    Slr::InfoParameterChange info(\"ms\");\n    for(auto para : paraStations)\n      if(para && para->index)\n      {\n        const Vector dx = 1e-3 * x.row(normalEquationInfo.index(para->index), para->x.rows());\n        para->x += dx;\n\n        for(UInt idEpoch=0; idEpoch<para->station->times.size(); idEpoch++)\n        {\n          Double dt = inner(parametrizationTemporal->factors(para->station->times.at(idEpoch)), dx);\n          para->station->timeBiases(idEpoch) += dt;\n          if(info.update(1e3*dt))\n            info.info = \"time bias station (\"+para->station->name()+\")\";\n        }\n      }\n    info.print(0., maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationTimeBias.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationTimeBias.h\n*\n* @brief Time biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONTIMEBIAS__\n#define __GROOPS_SLRPARAMETRIZATIONTIMEBIAS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationTimeBias = R\"(\n\\subsection{TimeBias}\\label{slrParametrizationType:timeBias}\nEstimates a \\configClass{temporal changing}{parametrizationTemporalType}\ntime bias in $[ms]$ for \\configClass{selectStations}{platformSelectorType}.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>:timeBias:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationTimeBias : public SlrParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    SlrStationPtr     station;\n    SlrParameterIndex index;\n    Vector            x;\n  };\n\n  Slr                       *slr;\n  std::string                name;\n  PlatformSelectorPtr        selectorStations;\n  ParametrizationTemporalPtr parametrizationTemporal;\n  std::vector<Parameter*>    paraStations;\n\npublic:\n  SlrParametrizationTimeBias(Config &config);\n ~SlrParametrizationTimeBias();\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationTimeBiasApriori.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationTimeBiasApriori.h\n*\n* @brief Time biases.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONTIMEBIASAPRIORI__\n#define __GROOPS_SLRPARAMETRIZATIONTIMEBIASAPRIORI__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationTimeBiasApriori = R\"(\n\\subsection{TimeBiasApriori}\\label{slrParametrizationType:timeBiasApriori}\nA priori time bias value for all \\configClass{selectStations}{platformSelectorType}.\nThe \\href{https://ilrs.gsfc.nasa.gov/}{ILRS} provides the mean time biases \\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File},\nbut these have been determined using the passive satellites LAGEOS and Etalon and are therefore only suitable for passive\nsatellites and not for active ones.\nUse \\program{SlrSinexDataHandling2Files} to convert the time biases from\n\\href{https://ilrs.gsfc.nasa.gov/network/site_information/data_correction.html}{ILRS Data Handling File} to \\file{instrument file}{instrument}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Range biases.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationTimeBiasApriori : public SlrParametrizationBase\n{\n  FileName            fileNameTimeBias;\n  PlatformSelectorPtr selectorStations;\n\npublic:\n  SlrParametrizationTimeBiasApriori(Config &config);\n ~SlrParametrizationTimeBiasApriori() {}\n\n  void init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n};\n\n/***********************************************/\n\ninline SlrParametrizationTimeBiasApriori::SlrParametrizationTimeBiasApriori(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectStations\",    selectorStations, Config::MUSTSET,  R\"([\"all\"])\", \"\");\n    readConfig(config, \"inputfileTimeBias\", fileNameTimeBias, Config::MUSTSET,  \"{groopsDataDir}/slr/stations/timeBias/timeBias.{station}.txt\", \"variable {station} available\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrParametrizationTimeBiasApriori::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    Bool found = FALSE;\n    auto selectedStations = slr->selectStations(selectorStations);\n    VariableList varList;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat))\n      {\n        auto station = slr->stations.at(idStat);\n        varList.setVariable(\"station\", station->name());\n        try\n        {\n          MiscValuesArc arc = InstrumentFile::read(fileNameTimeBias(varList));\n          Vector bias(station->times.size());\n          UInt idArc = 0;\n          for(UInt i=0; i<bias.rows(); i++)\n          {\n            while((idArc+1 < arc.size()) && (arc.at(idArc).time <= station->times.at(i)))\n              idArc++;\n            if(arc.at(idArc).time > station->times.at(i))\n              break;\n            bias(i) = arc.at(idArc).values(0) + arc.at(idArc).values(1) * (station->times.at(i)-arc.at(idArc).time).mjd();\n          }\n          if(quadsum(bias))\n          {\n            if(station->timeBiases.size())\n              station->timeBiases += bias;\n            else\n              station->timeBiases = bias;\n          }\n          found = TRUE;\n        }\n        catch(std::exception &/*e*/)\n        {\n          // logWarningOnce<<\"Unable to read time bias file <\"<<fileNameTimeBias(varList)<<\">, ignoring.\"<<Log::endl;\n        }\n      }\n\n    if(!found)\n    {\n      varList.setVariable(\"station\", \"****\");\n      logWarningOnce<<\"Initialization of all time bias failed. Wrong file name <\"<<fileNameTimeBias(varList)<<\">?\"<<Log::endl;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationTroposphere.cpp",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationTroposphere.cpp\n*\n* @brief Troposphere.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"classes/troposphere/troposphere.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrParametrization/slrParametrizationTroposphere.h\"\n\n/***********************************************/\n\nSlrParametrizationTroposphere::SlrParametrizationTroposphere(Config &config)\n{\n  try\n  {\n    readConfig(config, \"name\",                  name,             Config::OPTIONAL, \"parameter.troposphere\", \"used for parameter selection\");\n    readConfig(config, \"selectStations\",        selectorStations, Config::MUSTSET,  \"\",  \"\");\n    readConfig(config, \"outputfileTroposphere\", fileNameTropo,    Config::OPTIONAL, \"output/troposphere_{loopTime:%D}.{station}.txt\", \"columns: MJD, ZHD, ZWD, dry north gradient, wet north gradient, dry east gradient, wet east gradient\");\n    readConfig(config, \"troposphere\",           troposphere,      Config::MUSTSET,  R\"({\"mendesAndPavlis\":{}})\",  \"a priori troposphere model\");\n    readConfig(config, \"troposphereEstimation\", parametrization,  Config::DEFAULT,  \"\",  \"[m] parametrization of zenith delays\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrParametrizationTroposphere::~SlrParametrizationTroposphere()\n{\n  for(Parameter *para : parameters)\n    delete para;\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTroposphere::init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &/*paramGravityField*/)\n{\n  try\n  {\n    this->slr = slr;\n    auto selectedStations = slr->selectStations(selectorStations);\n    parameters.resize(slr->stations.size(), nullptr);\n    UInt idTropo = 0;\n    std::vector<std::string> names;\n    std::vector<Vector3d>    positions;\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      if(selectedStations.at(idStat) && slr->stations.at(idStat)->useable())\n      {\n        names.push_back(slr->stations.at(idStat)->name());\n        positions.push_back(slr->stations.at(idStat)->position(slr->times.front()));\n        auto para = new Parameter();\n        parameters.at(idStat) = para;\n        para->idStat = idStat;\n        para->idTropo   = idTropo++;\n        para->x         = Vector(parametrization->parameterCount());\n        para->zenitDelay.resize(slr->times.size(), 0);\n      }\n\n    troposphere->init(names, positions);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTroposphere::initParameter(SlrNormalEquationInfo &normalEquationInfo)\n{\n  try\n  {\n    for(auto para : parameters)\n      if(para)\n        para->index = SlrParameterIndex();\n    if(!isEnabled(normalEquationInfo, name))\n      return;\n\n    // wet troposphere\n    UInt countPara = 0;\n    if(parametrization->parameterCount())\n      for(auto para : parameters)\n        if(para && normalEquationInfo.estimateStation.at(para->idStat))\n        {\n          std::vector<ParameterName> parameterNames;\n          parametrization->parameterName({ParameterName(slr->stations.at(para->idStat)->name(), \"troposphere\")}, parameterNames);\n          para->index = normalEquationInfo.parameterNamesStation(para->idStat, parameterNames);\n          countPara += parameterNames.size();\n        }\n    if(countPara)\n      logInfo<<countPara%\"%9i troposphere parameters\"s<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTroposphere::observationCorrections(SlrObservationEquation &eqn) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.station->idStat());\n    if((eqn.type != SlrObservationEquation::RANGE) || !para)\n      return;\n\n    for(UInt idEpoch=0; idEpoch<eqn.timesStat.size(); idEpoch++)\n    {\n      // apriori value\n      Double delay = troposphere->slantDelay(para->idTropo, eqn.timesStat.at(idEpoch), LIGHT_VELOCITY/eqn.laserWavelength(idEpoch),\n                                             eqn.azimutStat.at(idEpoch), eqn.elevationStat.at(idEpoch));\n\n      // estimated wet effect\n      if(parametrization->parameterCount())\n        delay += troposphere->mappingFunctionWet(para->idTropo, eqn.timesStat.at(idEpoch), LIGHT_VELOCITY/eqn.laserWavelength(idEpoch),\n                                                 eqn.azimutStat.at(idEpoch), eqn.elevationStat.at(idEpoch))\n               * inner(parametrization->factors(eqn.timesStat.at(idEpoch)), para->x);\n\n      eqn.l(idEpoch) -= delay;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTroposphere::aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const\n{\n  try\n  {\n    // update wet troposphere\n    for(auto para : parameters)\n      if(para && para->index)\n        copy(para->x, x0.row(normalEquationInfo.index(para->index), para->x.rows()));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTroposphere::designMatrix(const SlrNormalEquationInfo &/*normalEquationInfo*/, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const\n{\n  try\n  {\n    auto para = parameters.at(eqn.station->idStat());\n    if((eqn.type != SlrObservationEquation::RANGE) || !para || !para->index)\n      return;\n\n    for(UInt idEpoch=0; idEpoch<eqn.timesStat.size(); idEpoch++)\n    {\n      const Double mappingFunction = troposphere->mappingFunctionWet(para->idTropo, eqn.timesStat.at(idEpoch), LIGHT_VELOCITY/eqn.laserWavelength(idEpoch),\n                                                                        eqn.azimutStat.at(idEpoch), eqn.elevationStat.at(idEpoch));\n      const const_MatrixSlice B(eqn.A.slice(eqn.index.at(idEpoch), SlrObservationEquation::idxRange, eqn.count.at(idEpoch), 1));\n      std::vector<UInt>   idx;\n      std::vector<Double> factor;\n      parametrization->factors(eqn.timesStat.at(idEpoch), idx, factor);\n      MatrixSlice Design(A.column(para->index));\n      for(UInt i=0; i<factor.size(); i++)\n        axpy(mappingFunction*factor.at(i), B, Design.slice(eqn.index.at(idEpoch), idx.at(i), eqn.count.at(idEpoch), 1));\n    } // for(idEpoch)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrParametrizationTroposphere::updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef /*Wz*/)\n{\n  try\n  {\n    // update wet troposphere\n    Double maxChange = 0;\n    Slr::InfoParameterChange info(\"mm\");\n    for(auto para : parameters)\n      if(para && para->index)\n      {\n        auto recv = slr->stations.at(para->idStat);\n        para->x += x.row(normalEquationInfo.index(para->index), parametrization->parameterCount());\n        std::vector<UInt>   index;\n        std::vector<Double> factor;\n        for(UInt idEpoch=0; idEpoch<slr->times.size(); idEpoch++)\n        {\n          parametrization->factors(slr->times.at(idEpoch), index, factor);\n          Double z = 0;\n          for(UInt k=0; k<factor.size(); k++)\n            z += factor.at(k) * para->x(index.at(k));\n          const Double zOld = para->zenitDelay.at(idEpoch);\n          para->zenitDelay.at(idEpoch) = z;\n          if(info.update(1e3*(z-zOld)))\n            info.info = \"troposphere wet (\"+recv->name()+\", \"+slr->times.at(idEpoch).dateTimeStr()+\")\";\n        }\n      }\n    info.print(1e-3, maxChange);\n\n    return maxChange;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrParametrizationTroposphere::writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const\n{\n  try\n  {\n    if(!isEnabled(normalEquationInfo, name) || fileNameTropo.empty())\n      return;\n\n    VariableList varList;\n    varList.setVariable(\"station\", \"****\");\n    for(auto para : parameters)\n      if(para && normalEquationInfo.estimateStation.at(para->idStat))\n      {\n        Double laserWavelength = 0;\n        for(const auto &obsSat : slr->stations.at(para->idStat)->observations)\n          if(obsSat.size())\n          {\n            laserWavelength = obsSat.front()->laserWavelength(0);\n            break;\n          }\n\n        Matrix A(slr->times.size(), 12);\n        std::vector<Time> times;\n        for(UInt idEpoch=0; idEpoch<slr->times.size(); idEpoch++)\n        {\n          Double zenithWetDelay, zenithDryDelay, gradientWetNorth, gradientDryNorth, gradientWetEast, gradientDryEast, aDry, aWet;\n          troposphere->getAprioriValues(para->idTropo, slr->times.at(idEpoch), LIGHT_VELOCITY/laserWavelength,\n                                        zenithDryDelay, zenithWetDelay,\n                                        gradientDryNorth, gradientWetNorth, gradientDryEast, gradientWetEast, aDry, aWet);\n          times.push_back(slr->times.at(idEpoch));\n          A(idEpoch,  0) = slr->times.at(idEpoch).mjd();\n          A(idEpoch,  1) = zenithDryDelay;                                // tropospheric zenith dry delay [m] (only from model)\n          A(idEpoch,  2) = zenithWetDelay + para->zenitDelay.at(idEpoch); // tropospheric zenith wet delay [m] (model + delta estimate)\n          A(idEpoch,  3) = gradientDryNorth;                              // tropospheric dry gradient - north direction [m] (model + delta estimate, due to same mapping function)\n          A(idEpoch,  4) = gradientWetNorth;                              // tropospheric wet gradient - north direction [m] (only from model)\n          A(idEpoch,  5) = gradientDryEast;                               // tropospheric dry gradient - east component [m] (model + delta estimate, due to same mapping function)\n          A(idEpoch,  6) = gradientWetEast;                               // tropospheric wet gradient - east component [m] (only from model)\n          A(idEpoch,  7) = para->zenitDelay.at(idEpoch);                  // tropospheric zenith wet delay [m] (delta estimate)\n          A(idEpoch,  8) = 0;                                             // tropospheric gradient - north [m] (delta estimate)\n          A(idEpoch,  9) = 0;                                             // tropospheric gradient - east  [m] (delta estimate)\n          A(idEpoch, 10) = aDry;                                          // dry mapping function coefficient a []\n          A(idEpoch, 11) = aWet;                                          // wet mapping function coefficient a []\n        }\n\n        varList.setVariable(\"station\", slr->stations.at(para->idStat)->name());\n        InstrumentFile::write(fileNameTropo(varList).appendBaseName(suffix), Arc(times, A));\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrParametrization/slrParametrizationTroposphere.h",
    "content": "/***********************************************/\n/**\n* @file slrParametrizationTroposphere.h\n*\n* @brief Troposphere.\n* @see SlrParametrization\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPARAMETRIZATIONTROPOSPHERE__\n#define __GROOPS_SLRPARAMETRIZATIONTROPOSPHERE__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrParametrization\nstatic const char *docstringSlrParametrizationTroposphere = R\"(\n\\subsection{Troposphere}\\label{slrParametrizationType:troposphere}\nA priori tropospheric correction is handled by a \\configClass{troposphere}{troposphereType} model (e.g. Mendes and Pavlis).\nAdditional parameters in $[m]$ for zenith delay can be set up via\n\\configClass{troposphereEstimation}{parametrizationTemporalType}.\nThese parameters can be soft-constrained using\n\\configClass{parametrization:constraints}{slrParametrizationType:constraints}\nto avoid an unsolvable system of normal equations in case of data gaps.\n\nThe \\file{parameter names}{parameterName} are \\verb|<station>:troposphere:<temporal>:<interval>|.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/troposphere/troposphere.h\"\n#include \"classes/parametrizationTemporal/parametrizationTemporal.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrParametrization/slrParametrization.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Troposphere.\n* @ingroup slrParametrizationGroup\n* @see SlrParametrization */\nclass SlrParametrizationTroposphere : public SlrParametrizationBase\n{\n  class Parameter\n  {\n  public:\n    UInt                idStat, idTropo;\n    SlrParameterIndex   index;\n    Vector              x;\n    std::vector<Double> zenitDelay;\n  };\n\n  Slr                       *slr;\n  std::string                name;\n  PlatformSelectorPtr        selectorStations;\n  FileName                   fileNameTropo;\n  TropospherePtr             troposphere;\n  ParametrizationTemporalPtr parametrization;\n  std::vector<Parameter*>    parameters;\n\n\npublic:\n  SlrParametrizationTroposphere(Config &config);\n ~SlrParametrizationTroposphere();\n\n  void   init(Slr *slr, const std::vector<const SlrParametrizationGravityField*> &paramGravityField) override;\n  void   observationCorrections(SlrObservationEquation &eqn) const override;\n  void   initParameter(SlrNormalEquationInfo &normalEquationInfo) override;\n  void   aprioriParameter(const SlrNormalEquationInfo &normalEquationInfo, MatrixSliceRef x0) const override;\n  void   designMatrix(const SlrNormalEquationInfo &normalEquationInfo, const SlrObservationEquation &eqn, SlrDesignMatrix &A) const override;\n  Double updateParameter(const SlrNormalEquationInfo &normalEquationInfo, const_MatrixSliceRef x, const_MatrixSliceRef Wz) override;\n  void   writeResults(const SlrNormalEquationInfo &normalEquationInfo, const std::string &suffix) const override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrPlatform.h",
    "content": "/***********************************************/\n/**\n* @file slrPlatform.h\n*\n* @brief SLR station or satellite.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPLATFORM__\n#define __GROOPS_SLRPLATFORM__\n\n#include \"files/filePlatform.h\"\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SlrPlatform;\ntypedef std::shared_ptr<SlrPlatform> SlrPlatformPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for SLR station or satellite.\n* eg. GPS satellites. */\nclass SlrPlatform\n{\n   Bool     useable_;\n\npublic:\n   UInt     id_; // set by Slr::init()\n   Platform platform;\n   Double   rangeBias;\n\npublic:\n  /// Constructor.\n  SlrPlatform(const Platform &platform);\n\n  /// Destructor.\n  virtual ~SlrPlatform() {}\n\n  /** @brief name. */\n  std::string name() const {return platform.name;}\n\n  /** @brief Is the platform usable at given epoch (or all epochs). */\n  Bool useable() const {return useable_;}\n\n  /** @brief Disable platform. */\n  virtual void disable(const std::string &reason);\n\n  void save(OutArchive &oa) const;\n  void load(InArchive  &ia);\n};\n\n/***********************************************/\n\ninline SlrPlatform::SlrPlatform(const Platform &platform)\n  : useable_(TRUE), platform(platform), rangeBias(0.) {}\n\n\n/***********************************************/\n\ninline void SlrPlatform::disable(const std::string &/*reason*/)\n{\n  try\n  {\n    useable_ = FALSE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrPlatform::save(OutArchive &oa) const\n{\n  oa<<nameValue(\"useable\", useable_);\n}\n\n/***********************************************/\n\ninline void SlrPlatform::load(InArchive  &ia)\n{\n  ia>>nameValue(\"useable\", useable_);\n}\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStep.cpp",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStep.cpp\n*\n* @brief Processing steps for SLR normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_SlrProcessingStep\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"config/configRegister.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepEstimate.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepWriteResults.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepWriteNormalEquations.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepWriteAprioriSolution.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepWriteResiduals.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepWriteUsedStationList.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepWriteUsedSatelliteList.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepPrintResidualStatistics.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepSelectParametrizations.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepSelectSatellites.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepSelectStations.h\"\n#include \"slr/slrProcessingStep/slrProcessingStepGroup.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(SlrProcessingStep, \"slrProcessingStepType\",\n                      SlrProcessingStepEstimate,\n                      SlrProcessingStepWriteResults,\n                      SlrProcessingStepWriteNormalEquations,\n                      SlrProcessingStepWriteAprioriSolution,\n                      SlrProcessingStepWriteResiduals,\n                      SlrProcessingStepWriteUsedStationList,\n                      SlrProcessingStepWriteUsedSatelliteList,\n                      SlrProcessingStepPrintResidualStatistics,\n                      SlrProcessingStepSelectParametrizations,\n                      SlrProcessingStepSelectSatellites,\n                      SlrProcessingStepSelectStations,\n                      SlrProcessingStepGroup)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(SlrProcessingStep, \"slrProcessingStepType\")\n\n/***********************************************/\n\nSlrProcessingStep::SlrProcessingStep(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"estimate\",                       type, \"least squares adjustment\"))\n        bases.push_back(new SlrProcessingStepEstimate(config));\n      if(readConfigChoiceElement(config, \"writeResults\",                   type, \"write all estimated parameters\"))\n        bases.push_back(new SlrProcessingStepWriteResults(config));\n      if(readConfigChoiceElement(config, \"writeNormalEquations\",           type, \"write unconstrained and constraint normal equations\"))\n        bases.push_back(new SlrProcessingStepWriteNormalEquations(config));\n      if(readConfigChoiceElement(config, \"writeAprioriSolution\",           type, \"write apriori solution vector\"))\n        bases.push_back(new SlrProcessingStepWriteAprioriSolution(config));\n      if(readConfigChoiceElement(config, \"writeResiduals\",                 type, \"write observation residuals\"))\n        bases.push_back(new SlrProcessingStepWriteResiduals(config));\n      if(readConfigChoiceElement(config, \"writeUsedStationList\",           type, \"write used stations\"))\n        bases.push_back(new SlrProcessingStepWriteUsedStationList(config));\n      if(readConfigChoiceElement(config, \"writeUsedSatelliteList\",         type, \"write used satellites\"))\n        bases.push_back(new SlrProcessingStepWriteUsedSatelliteList(config));\n      if(readConfigChoiceElement(config, \"printResidualStatistics\",        type, \"print residual statistics\"))\n        bases.push_back(new SlrProcessingStepPrintResidualStatistics(config));\n      if(readConfigChoiceElement(config, \"selectParametrizations\",         type, \"select parametrizations for all subsequent processing steps\"))\n        bases.push_back(new SlrProcessingStepSelectParametrizations(config));\n      if(readConfigChoiceElement(config, \"selectSatellites\",               type, \"use this subset of satellites in all subsequent processing steps\"))\n        bases.push_back(new SlrProcessingStepSelectSatellites(config));\n      if(readConfigChoiceElement(config, \"selectStations\",                 type, \"use this subset of stations in all subsequent processing steps\"))\n        bases.push_back(new SlrProcessingStepSelectStations(config));\n      if(readConfigChoiceElement(config, \"group\",                          type, \"group processing steps\"))\n        bases.push_back(new SlrProcessingStepGroup(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrProcessingStep::~SlrProcessingStep()\n{\n  for(auto base : bases)\n    delete base;\n}\n\n/***********************************************/\n\nvoid SlrProcessingStep::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    for(auto base : bases)\n    {\n      if(base->expectInitializedParameters() && state.changedNormalEquationInfo)\n      {\n        state.slr->initParameter(state.normalEquationInfo);\n        state.changedNormalEquationInfo = FALSE;\n      }\n      base->process(state);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n/***********************************************/\n\nSlrProcessingStep::State::State(SlrPtr slr) :\n  slr(slr), normalEquationInfo(slr->stations.size(), slr->satellites.size()),\n  changedNormalEquationInfo(TRUE), sigmaFactor(slr->stations.size(), 1.0)\n{\n  try\n  {\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrProcessingStep::State::regularizeNotUsedParameters(UInt blockStart, UInt blockCount)\n{\n  try\n  {\n    UInt countZeros = 0;\n    for(UInt i=blockStart; i<blockStart+blockCount; i++)\n      if(normals.isMyRank(i,i))\n      {\n        Matrix &N = normals.N(i,i);\n        for(UInt k=0; k<N.rows(); k++)\n          if(N(k,k)==0.)\n          {\n            N(k,k) += 1.0;\n            countZeros++;\n            logWarning<<\"    \"<<normalEquationInfo.parameterNames().at(normals.blockIndex(i)+k).str()<<\" has zero diagonal element\"<<Log::endl;\n          }\n      }\n    if(countZeros)\n    {\n      logWarning<<\"  \"<<countZeros<<\" parameters have zero diagonal elements -> set to one\"<<Log::endl;\n      obsCount -= countZeros;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrProcessingStep::State::buildNormals(Bool constraintsOnly)\n{\n  try\n  {\n    normals.initEmpty(normalEquationInfo.blockIndices(), Parallel::selfCommunicator());\n    n.resize(normals.blockCount());\n    for(UInt i=0; i<normals.blockCount(); i++)\n      n.at(i) = Vector(normals.blockSize(i));\n    lPl = Vector(1);\n    obsCount = 0;\n\n    if(!normalEquationInfo.parameterCount())\n      return;\n\n    // Loop over all stations\n    // ----------------------\n    if(!constraintsOnly)\n    {\n      logStatus<<\"accumulate normals\"<<Log::endl;\n      SlrDesignMatrix A(normalEquationInfo);\n      SlrObservationEquation eqn;\n      UInt idLoop = 0;\n      Log::Timer timer(slr->stations.size());\n      for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n      {\n        timer.loopStep(idLoop++);\n        auto station = slr->stations.at(idStat);\n        if(normalEquationInfo.estimateStation.at(idStat))\n          for(UInt idSat=0; idSat<station->observations.size(); idSat++)\n            if(normalEquationInfo.estimateSatellite.at(idSat))\n              for(UInt idPass=0; idPass<station->observations.at(idSat).size(); idPass++)\n                if(slr->basicObservationEquations(normalEquationInfo, idStat, idSat, idPass, eqn))\n                {\n                  A.init(eqn.l);\n                  slr->designMatrix(normalEquationInfo, eqn, A);\n                  A.accumulateNormals(normals, n, lPl(0), obsCount);\n                }\n      } // for(idStat)\n      timer.loopEnd();\n    }\n\n    // other observations and constraints\n    // ----------------------------------\n    slr->constraints(normalEquationInfo, normals, n, lPl(0), obsCount);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrProcessingStep::State::estimateSolution(Bool computeResiduals, Bool computeWeights, Bool adjustSigma0, Double huber, Double huberPower)\n{\n  try\n  {\n    // setup normal equations\n    buildNormals(FALSE/*constraintsOnly*/);\n\n    if(normalEquationInfo.parameterCount())\n    {\n      logStatus<<\"solve\"<<Log::endl;\n      regularizeNotUsedParameters(0, normals.blockCount());\n      normals.cholesky(TRUE/*timing*/);\n      normals.triangularTransSolve(n); // forward step\n      for(UInt z=0; z<normals.blockCount(); z++)\n      {\n        lPl(0)   -= quadsum(n.at(z)); // lPl = lPl - n1' N1^(-1) n1\n        obsCount -= normals.blockSize(z);\n      }\n      normals.triangularSolve(n); // Backward step\n\n      // Compute sigma\n      // -------------\n      const Double sigma = Vce::standardDeviation(lPl(0), obsCount, huber, huberPower);\n      logInfo<<\"  sigma = \"<<sigma%\"%.2f\"s<<Log::endl;\n      if((sigma!=sigma) || (sigma<=0))\n        logWarning<<\"  Cannot compute sigma = sqrt(\"<<lPl(0)<<\"/\"<<obsCount<<\")\"<<Log::endl;\n    }\n\n    // generate monte carlo vectors\n    // ----------------------------\n    Matrix Wz;\n    if(computeResiduals)\n    {\n      constexpr UInt monteCarloColumns = 100;\n      std::vector<Matrix> monteCarlo(normals.blockCount()); // Monte Carlo Vector for redundancy computation\n      for(UInt i=0; i<normals.blockCount(); i++)\n        monteCarlo.at(i) = Vce::monteCarlo(normals.blockSize(i), monteCarloColumns);\n\n      normals.triangularSolve(monteCarlo);\n\n      Wz = Matrix(normalEquationInfo.parameterCount(), monteCarloColumns);\n      for(UInt i=0; i<normalEquationInfo.blockCount(); i++)\n        if(normalEquationInfo.blockSize(i))\n          copy(monteCarlo.at(i), Wz.row(normalEquationInfo.blockIndex(i), normalEquationInfo.blockSize(i)));\n    }\n\n    // free memory\n    normals.initEmpty(normals.blockIndex(), normals.communicator());\n\n    // copy solution to one vector\n    // ---------------------------\n    Vector x = Vector(normalEquationInfo.parameterCount());\n    for(UInt i=0; i<normalEquationInfo.blockCount(); i++)\n      if(normalEquationInfo.blockSize(i))\n        copy(n.at(i), x.row(normalEquationInfo.blockIndex(i), normalEquationInfo.blockSize(i)));\n    n.clear();\n    n.shrink_to_fit();\n    if(!computeResiduals)\n    {\n      if(normalEquationInfo.parameterCount())\n        logInfo<<\"Parameter changes\"<<Log::endl;\n      return slr->updateParameter(normalEquationInfo, x, Matrix());\n    }\n\n    // Residual tracking\n    // -----------------\n    logStatus<<\"Compute residuals\"<<Log::endl;\n    Slr::InfoParameterChange infosResiduals(\"mm\");\n    SlrDesignMatrix A(normalEquationInfo);\n    SlrObservationEquation eqn;\n    UInt idLoop = 0;\n    Log::Timer timer(slr->stations.size());\n    for(UInt idStat=0; idStat<slr->stations.size(); idStat++)\n    {\n      timer.loopStep(idLoop++);\n      auto station = slr->stations.at(idStat);\n      if(normalEquationInfo.estimateStation.at(idStat))\n      {\n        for(UInt idSat=0; idSat<station->observations.size(); idSat++)\n          if(normalEquationInfo.estimateSatellite.at(idSat))\n            for(UInt idPass=0; idPass<station->observations.at(idSat).size(); idPass++)\n              if(slr->basicObservationEquations(normalEquationInfo, idStat, idSat, idPass, eqn))\n              {\n                A.init(eqn.l);\n                slr->designMatrix(normalEquationInfo, eqn, A);\n                Vector We  = eqn.l - A.mult(x); // homogenized residuals\n                Matrix AWz = A.mult(Wz);        // redundancies\n\n                // redundancies\n                Vector r(We.rows());\n                for(UInt i=0; i<We.rows(); i++)\n                  r(i) = 1. - quadsum(AWz.row(i));\n\n                // find max. residual (for statistics)\n                for(UInt k=0; k<We.rows(); k++)\n                  if(std::fabs(eqn.sigmas(k)-eqn.sigmas0(k)) < 1e-8) // without outlier\n                    if(infosResiduals.update(1e3*(We(k)*eqn.sigmas(k) - station->observations.at(idSat).at(idPass)->residuals(k))))\n                      infosResiduals.info = eqn.station->name()+\" -> \"+eqn.satellite->name()+\", \"+eqn.timesStat.at(k).dateTimeStr();\n\n                station->observations.at(idSat).at(idPass)->setHomogenizedResiduals(We, r);\n              }\n      }\n    } // for(idStat)\n    timer.loopEnd();\n\n    // new weights\n    // -----------\n    if(computeWeights || adjustSigma0)\n    {\n      if(computeWeights) logStatus<<\"Downweight outliers\"<<Log::endl;\n      if(adjustSigma0)   logStatus<<\"Estimate variance factors\"<<Log::endl;\n      for(auto station : slr->stations)\n        if(normalEquationInfo.estimateStation.at(station->idStat()))\n          for(UInt iter=0; iter<10; iter++)\n          {\n            if(adjustSigma0)\n            {\n              Double ePe = 0, redundancy = 0;\n              for(UInt idSat=0; idSat<station->observations.size(); idSat++)\n                if(normalEquationInfo.estimateSatellite.at(idSat))\n                  for(auto &obs : station->observations.at(idSat))\n                    for(UInt i=0; i<obs->residuals.rows(); i++)\n                      if((obs->sigmas0(i) > 0) && (obs->redundancies(i) > 0))\n                      {\n                        ePe        += std::pow(obs->residuals(i)/obs->sigmas(i), 2);\n                        redundancy += obs->redundancies(i);\n                      }\n              const Double factor = (redundancy > 3) ? Vce::standardDeviation(ePe, redundancy, huber, huberPower) : 1.;\n              sigmaFactor.at(station->idStat()) *= factor;\n\n              // adjust sigma and sigma0\n              for(UInt idSat=0; idSat<station->observations.size(); idSat++)\n                if(normalEquationInfo.estimateSatellite.at(idSat))\n                  for(auto &obs : station->observations.at(idSat))\n                    for(UInt i=0; i<obs->residuals.rows(); i++)\n                    {\n                      obs->sigmas0(i) *= factor;\n                      obs->sigmas(i)  *= factor;\n                    }\n            } // if(adjustSigma0)\n\n            if(computeWeights)\n            {\n              for(UInt idSat=0; idSat<station->observations.size(); idSat++)\n                if(normalEquationInfo.estimateSatellite.at(idSat))\n                  for(auto &obs : station->observations.at(idSat))\n                    for(UInt i=0; i<obs->residuals.rows(); i++)\n                    {\n                      obs->sigmas(i) = obs->sigmas0(i);\n                      if(obs->redundancies(i) > 0.1)\n                      {\n                        const Double s = std::fabs(obs->residuals(i))/std::sqrt(obs->redundancies(i))/obs->sigmas0(i);\n                        obs->sigmas(i) *= (s > huber) ? std::pow(s/huber, huberPower) : 1.;\n                      }\n                    }\n            } // if(computeWeights)\n\n            if(!(computeWeights && adjustSigma0))\n              break; // iteration not needed\n          } // for(station, iter)\n    } // if(computeWeights || adjustSigma0)\n\n    // residual analysis\n    // -----------------\n    logInfo<<\"Residuals changes (without outliers)\"<<Log::endl;\n    Double maxChange = 0;\n    infosResiduals.print(1e-3, maxChange);\n\n    if(normalEquationInfo.parameterCount())\n      logInfo<<\"Parameter changes\"<<Log::endl;\n    return slr->updateParameter(normalEquationInfo, x, Wz);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrProcessingStep::State::residualsStatistics(UInt idStat, UInt idSat, Double &ePe, Double &redundancy, UInt &obsCount, UInt &outlierCount)\n{\n  try\n  {\n    const UInt idSatStart = ((idSat!=NULLINDEX) ? idSat : 0);\n    const UInt idSatEnd   = ((idSat!=NULLINDEX) ? idSat : MAX_UINT);\n    for(auto station : slr->stations)\n      if(normalEquationInfo.estimateStation.at(station->idStat()) && ((idStat == NULLINDEX) || (idStat == station->idStat())))\n        for(UInt idSat=idSatStart; (idSat<=idSatEnd) && (idSat<station->observations.size()); idSat++)\n          if(normalEquationInfo.estimateSatellite.at(idSat))\n            for(auto &obs : station->observations.at(idSat))\n              for(UInt i=0; i<obs->residuals.rows(); i++)\n              {\n                ePe        += std::pow(obs->residuals(i)/obs->sigmas(i), 2);\n                redundancy += obs->redundancies(i);\n                obsCount++;\n                if(obs->sigmas(i) > obs->sigmas0(i))\n                  outlierCount++;\n              }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStep.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStep.h\n*\n* @brief Processing steps for SLR normal equations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEP__\n#define __GROOPS_SLRPROCESSINGSTEP__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStep = R\"(\n\\section{SlrProcessingStep}\\label{slrProcessingStepType}\nProcessing step in \\program{SlrProcessing}.\n\nProcessing steps enable a dynamic definition of the consecutive steps performed during any kind of SLR processing.\nThe most common steps are \\configClass{estimate}{slrProcessingStepType:estimate}, which performs an iterative least\nsquares adjustment, and \\configClass{writeResults}{slrProcessingStepType:writeResults}, which writes all output files\ndefined in \\program{SlrProcessing} and is usually the last step.\nSome steps such as \\configClass{selectParametrizations}{slrProcessingStepType:selectParametrizations}\nand \\configClass{selectStations}{slrProcessingStepType:selectStations} affect all subsequent steps.\nIn case these steps are used within a \\configClass{group}{slrProcessingStepType:group} step,\nthey only affect the steps within this level.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"parallel/matrixDistributed.h\"\n#include \"slr/slr.h\"\n\n/**\n* @defgroup slrProcessingStepGroup SlrProcessingStep\n* @brief Processing steps in @ref SlrProcessing.\n* @ingroup slrGroup\n* The interface is given by @ref SlrProcessingStep. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Slr;\nclass SlrProcessingStep;\nclass SlrProcessingStepBase;\ntypedef std::shared_ptr<SlrProcessingStep> SlrProcessingStepPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of stations.\n* An Instance of this class can be created by @ref readConfig. */\nclass SlrProcessingStep\n{\n  std::vector<SlrProcessingStepBase*> bases;\n\npublic:\n  class State\n  {\n  public:\n    SlrPtr                 slr;\n    SlrNormalEquationInfo  normalEquationInfo;\n    Bool                   changedNormalEquationInfo;\n    MatrixDistributed      normals;\n    std::vector<Matrix>    n;           // at master (after solve)\n    Vector                 lPl;         // at master (after solve)\n    UInt                   obsCount;    // at master (after solve)\n    Vector                 sigmaFactor; // for each station\n\n    /** @brief Constructor. */\n    State(SlrPtr slr);\n\n    void   regularizeNotUsedParameters(UInt blockStart, UInt blockCount);\n    void   buildNormals(Bool constraintsOnly);\n    Double estimateSolution(Bool computeResiduals,  Bool computeWeights, Bool adjustSigma0, Double huber, Double huberPower);\n    void   residualsStatistics(UInt idStat, UInt idSat, Double &ePe, Double &redundancy, UInt &obsCount, UInt &outlierCount);\n  };\n\n  /** @brief Constructor from config. */\n  SlrProcessingStep(Config &config, const std::string &name);\n\n  /// Destructor.\n ~SlrProcessingStep();\n\n  /** @brief Perform the processing steps. */\n  void process(State &state);\n\n  /** @brief creates an derived instance of this class. */\n  static SlrProcessingStepPtr create(Config &config, const std::string &name) {return SlrProcessingStepPtr(new SlrProcessingStep(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class SlrProcessingStep.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SlrProcessingStep */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SlrProcessingStepPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass SlrProcessingStepBase\n{\npublic:\n  virtual ~SlrProcessingStepBase() {}\n\n  /** @brief Execute the processing step. */\n  virtual void process(SlrProcessingStep::State &state) = 0;\n  virtual Bool expectInitializedParameters() const {return TRUE;}\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepEstimate.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepEstimate.h\n*\n* @brief SLR processing step: Estimate.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPESTIMATE__\n#define __GROOPS_SLRPROCESSINGSTEPESTIMATE__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepEstimate = R\"(\n\\subsection{Estimate}\\label{slrProcessingStepType:estimate}\nIterative non-linear least squares adjustment.\nIn every iteration it accumulates the system of normal equations, solves the system and updates the estimated parameters.\nThe estimated parameters serve as a priori values in the next iteration and the following processing steps.\nIterates until either every single parameter update (converted to an influence in meter)\nis below a \\config{convergenceThreshold} or \\config{maxIterationCount} is reached.\n\nWith \\config{computeResiduals} the observation equations are computed\nagain after each update to compute the observation residuals.\n\nThe overall standard deviation of a single observation used for the weighting\nis composed of several factors\n\\begin{equation}\n  \\hat{\\sigma}_i = \\hat{\\sigma}_i^{huber} \\hat{\\sigma}^{stat} \\sigma_{apriori}^{stat},\n\\end{equation} where the $\\sigma_{apriori}^{stat}$ is given by \\configClass{station}{slrStationGeneratorType}:accuracy.\nThe other factors are estimated iteratively from the residuals.\n\nWith \\config{computeWeights} a standardized variance $\\hat{s}_i^2$\nfor each residual $\\hat{\\epsilon}_i$ is computed\n\\begin{equation}\n  \\hat{s}_i^2 = \\frac{1}{\\hat{\\sigma}^{stat} \\sigma_{apriori}^{stat}}\\frac{\\hat{\\epsilon}_i^2}{r_i}\n  \\qquad\\text{with}\\qquad\n  r_i = \\left(\\M A\\left(\\M A^T\\M A\\right)^{-1}\\M A^T\\right)_{ii}\n\\end{equation}\ntaking the redundancy $r_i$ into account. If $\\hat{s}_i$ is above a threshold \\config{huber}\nthe observation gets a higher standard deviation used for weighting according to\n\\begin{equation}\n  \\hat{\\sigma}_i^{huber} =\n  \\left\\{ \\begin{array}{ll}\n    1                              & s < huber,\\\\\n    (\\hat{s}_i/huber)^{huberPower} & s \\ge huber\n  \\end{array} \\right.,\n\\end{equation}\nsimilar to \\reference{robust least squares adjustment}{fundamentals.robustLeastSquares}.\n\nWith \\config{adjustSigma0} an individual variance factor can be computed for each station separately\n\\begin{equation}\n  \\hat{\\sigma}^{stat} = \\sqrt{\\frac{\\hat{\\M\\epsilon}^T\\M P\\hat{\\M\\epsilon}}{r}}.\n\\end{equation}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: Estimate.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepEstimate : public SlrProcessingStepBase\n{\n  Bool   computeResiduals, adjustSigma0, computeWeights;\n  Double huber, huberPower;\n  Double convergenceThreshold;\n  UInt   iterCount;\n\npublic:\n  SlrProcessingStepEstimate(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepEstimate::SlrProcessingStepEstimate(Config &config)\n{\n  try\n  {\n    readConfig(config, \"computeResiduals\",     computeResiduals,     Config::DEFAULT, \"1\",    \"\");\n    readConfig(config, \"adjustSigma0\",         adjustSigma0,         Config::DEFAULT, \"1\",    \"adjust sigma0 by scale factor (per station)\");\n    readConfig(config, \"computeWeights\",       computeWeights,       Config::DEFAULT, \"1\",    \"downweight outliers\");\n    readConfig(config, \"huber\",                huber,                Config::DEFAULT, \"2.5\",  \"residuals > huber*sigma0 are downweighted\");\n    readConfig(config, \"huberPower\",           huberPower,           Config::DEFAULT, \"1.5\",  \"residuals > huber: sigma=(e/huber)^huberPower*sigma0\");\n    readConfig(config, \"convergenceThreshold\", convergenceThreshold, Config::DEFAULT, \"0.01\", \"[m] stop iteration once full convergence is reached\");\n    readConfig(config, \"maxIterationCount\",    iterCount,            Config::DEFAULT, \"3\",    \"maximum number of iterations\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepEstimate::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== estimate ================================================\"<<Log::endl;\n    for(UInt iter=0; iter<iterCount; iter++)\n    {\n      logStatus<<iter+1<<\". iteration  --------------------------\"<<Log::endl;\n      if(convergenceThreshold > state.estimateSolution(computeResiduals, computeWeights, adjustSigma0, huber, huberPower))\n        break;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepGroup.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepGroup.h\n*\n* @brief SLR processing step: Group.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPGROUP__\n#define __GROOPS_SLRPROCESSINGSTEPGROUP__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepGroup = R\"(\n\\subsection{Group}\\label{slrProcessingStepType:group}\nPerform these processing steps. This step can be used to structure complex processing flows.\nThe \\configClass{select..}{slrProcessingStepType:selectParametrizations} processing steps\ndefined within a group only affect the steps within this group.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: Group.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepGroup : public SlrProcessingStepBase\n{\n  SlrProcessingStepPtr processingSteps;\n\npublic:\n  SlrProcessingStepGroup(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline SlrProcessingStepGroup::SlrProcessingStepGroup(Config &config)\n{\n  try\n  {\n    readConfig(config, \"processingStep\", processingSteps, Config::MUSTSET, \"\", \"steps are processed consecutively\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepGroup::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== process group ===========================================\"<<Log::endl;\n    SlrNormalEquationInfo normalEquationInfoOld = state.normalEquationInfo;\n    processingSteps->process(state);\n    state.normalEquationInfo = std::move(normalEquationInfoOld);\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepPrintResidualStatistics.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepPrintResidualStatistics.h\n*\n* @brief SLR processing step: PrintResidualStatistics.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPPRINTRESIDUALSTATISTICS__\n#define __GROOPS_SLRPROCESSINGSTEPPRINTRESIDUALSTATISTICS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepPrintResidualStatistics = R\"(\n\\subsection{PrintResidualStatistics}\\label{slrProcessingStepType:printResidualStatistics}\nPrint residual statistics.\n\\begin{verbatim}\n  station   sigma redundancy obsCount outlier\n  ----------------------------------------------\n  1874       0.52   0.86      22      1 (4.55 %)\n  1889       1.20   0.98     186      5 (2.69 %)\n  1890       0.63   0.77      14      1 (7.14 %)\n  1891       0.49   0.50       6      0 (0.00 %)\n  7237       1.08   0.95     236     14 (5.93 %)\n  7394       0.36   0.88      26      0 (0.00 %)\n  7811       0.38   0.41       5      0 (0.00 %)\n  7819       1.21   0.94     120      1 (0.83 %)\n  7821       0.69   0.95     202      3 (1.49 %)\n  7827       0.40   0.85      29      1 (3.45 %)\n  7839       0.52   0.93     143     10 (6.99 %)\n  7840       0.15   0.80      16      0 (0.00 %)\n  7841       0.26   0.90      56      1 (1.79 %)\n  7941       0.55   0.92     277      5 (1.81 %)\n  8834       0.66   0.88     101      1 (0.99 %)\n  ----------------------------------------------\n  satellite sigma redundancy obsCount outlier\n  ----------------------------------------------\n  lageos1    1.04   0.94     722     24 (3.32 %)\n  lageos2    0.91   0.95     590     11 (1.86 %)\n  etalon1    1.19   0.78      57      2 (3.51 %)\n  etalon2    1.10   0.81      70      6 (8.57 %)\n  ----------------------------------------------\n\\end{verbatim}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: PrintResidualStatistics.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepPrintResidualStatistics : public SlrProcessingStepBase\n{\npublic:\n  SlrProcessingStepPrintResidualStatistics(Config &/*config*/) {}\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline void SlrProcessingStepPrintResidualStatistics::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== print residual statistics  ==============================\"<<Log::endl;\n    constexpr Double huber      = 2.5;\n    constexpr Double huberPower = 1.5;\n\n    logInfo<<\"  station   sigma redundancy obsCount outlier\"<<Log::endl;\n    logInfo<<\"  ----------------------------------------------\"<<Log::endl;\n    for(UInt idStat=0; idStat<state.slr->stations.size(); idStat++)\n      if(state.normalEquationInfo.estimateStation.at(idStat))\n      {\n        Double  ePe = 0, redundancy = 0;\n        UInt    obsCount = 0, outlierCount = 0;\n        state.residualsStatistics(idStat, NULLINDEX/*idSat*/, ePe, redundancy, obsCount, outlierCount);\n        if(obsCount)\n        {\n          std::string name = state.slr->stations.at(idStat)->name();\n          name.resize(10, ' ');\n          logInfo<<\"  \"<<name.substr(0, 10)\n                 <<state.sigmaFactor(idStat) * Vce::standardDeviation(ePe, redundancy, huber, huberPower)%\"%5.2f\"s<<(redundancy/obsCount)%\"%7.2f\"s\n                 <<obsCount%\"%8i\"s<<outlierCount%\"%7i (\"s<<(100.*outlierCount/obsCount)%\"%4.2f %%)\"s<<Log::endl;\n        }\n      }\n\n    logInfo<<\"  ----------------------------------------------\"<<Log::endl;\n    logInfo<<\"  satellite sigma redundancy obsCount outlier\"<<Log::endl;\n    logInfo<<\"  ----------------------------------------------\"<<Log::endl;\n    for(UInt idSat=0; idSat<state.slr->satellites.size(); idSat++)\n      if(state.normalEquationInfo.estimateSatellite.at(idSat))\n      {\n        Double  ePe = 0, redundancy = 0;\n        UInt    obsCount = 0, outlierCount = 0;\n        state.residualsStatistics(NULLINDEX/*idStat*/, idSat, ePe, redundancy, obsCount, outlierCount);\n        if(obsCount)\n        {\n          std::string name = state.slr->satellites.at(idSat)->name();\n          name.resize(10, ' ');\n          logInfo<<\"  \"<<name.substr(0, 10)\n                 <<Vce::standardDeviation(ePe, redundancy, huber, huberPower)%\"%5.2f\"s<<(redundancy/obsCount)%\"%7.2f\"s\n                 <<obsCount%\"%8i\"s<<outlierCount%\"%7i (\"s<<(100.*outlierCount/obsCount)%\"%4.2f %%)\"s<<Log::endl;\n        }\n      }\n    logInfo<<\"  ----------------------------------------------\"<<Log::endl;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepSelectParametrizations.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepSelectParametrizations.h\n*\n* @brief SLR processing step: SelectParametrizations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPSELECTPARAMETRIZATIONS__\n#define __GROOPS_SLRPROCESSINGSTEPSELECTPARAMETRIZATIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepSelectParametrizations = R\"(\n\\subsection{SelectParametrizations}\\label{slrProcessingStepType:selectParametrizations}\nEnable/disable parameter groups and constraint groups for subsequent steps,\ne.g. \\configClass{processingStep:estimate}{slrProcessingStepType:estimate} or\n\\configClass{processingStep:writeResults}{slrProcessingStepType:writeResults}.\nThe \\config{name} and \\config{nameConstraint} of these groups\nare defined in \\configClass{parametrizations}{slrParametrizationType}.\nPrior models or previously estimated parameters used as new apriori $\\M x_0$ values are unaffected\nand they are always reduced from the observations. This means all unselected parameters are kept fixed\nto their last result.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"base/string.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: SelectParametrizations.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepSelectParametrizations : public SlrProcessingStepBase\n{\npublic:\n  class EnableDisable\n  {\n  public:\n    Bool enable;\n    std::vector<std::string> wildcards;\n  };\n\n  std::vector<EnableDisable> patterns;\n\n  SlrProcessingStepSelectParametrizations(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ntemplate<> inline Bool readConfig(Config &config, const std::string &name, SlrProcessingStepSelectParametrizations::EnableDisable &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation)\n{\n  try\n  {\n    std::string choice;\n    if(!readConfigChoice(config, name, choice, mustSet, defaultValue, annotation))\n      return FALSE;\n    if(readConfigChoiceElement(config, \"enable\", choice, \"\"))\n    {\n      var.enable = TRUE;\n      readConfig(config, \"name\", var.wildcards, Config::MUSTSET, \"*\", \"wildcards: * and ?\");\n    }\n    if(readConfigChoiceElement(config, \"disable\", choice, \"\"))\n    {\n      var.enable = FALSE;\n      readConfig(config, \"name\", var.wildcards, Config::MUSTSET, \"*\", \"wildcards: * and ?\");\n    }\n    endChoice(config);\n    return TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline SlrProcessingStepSelectParametrizations::SlrProcessingStepSelectParametrizations(Config &config)\n{\n  try\n  {\n    readConfig(config, \"parametrization\", patterns, Config::MUSTSET, \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepSelectParametrizations::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select parametrization =======================================\"<<Log::endl;\n    state.changedNormalEquationInfo = TRUE;\n    for(const auto &pattern : patterns)\n      for(const auto &wildcard: pattern.wildcards)\n      {\n        state.normalEquationInfo.enableParametrizations.emplace_back(String::wildcard2regex(wildcard), pattern.enable);\n        logInfo<<\"  \"<<(pattern.enable ? \"enable \" : \"disable\")<<\" parametrization: \"<<wildcard<<Log::endl;\n      }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepSelectSatellites.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepSelectSatellites.h\n*\n* @brief SLR processing step: SelectSatellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPSELECTSATELLITES__\n#define __GROOPS_SLRPROCESSINGSTEPSELECTSATELLITES__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepSelectSatellites = R\"(\n\\subsection{SelectSatellites}\\label{slrProcessingStepType:selectSatellites}\nThis step can be used to process only a subset of satellites in subsequent processing steps.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: SelectSatellites.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepSelectSatellites : public SlrProcessingStepBase\n{\n  PlatformSelectorPtr selectorSatellites;\n\npublic:\n  SlrProcessingStepSelectSatellites(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline SlrProcessingStepSelectSatellites::SlrProcessingStepSelectSatellites(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectSatellites\", selectorSatellites, Config::MUSTSET,  \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepSelectSatellites::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select satellites ========================================\"<<Log::endl;\n    state.normalEquationInfo.estimateSatellite = state.slr->selectSatellites(selectorSatellites);\n    for(auto sat : state.slr->satellites)\n      if(!sat->useable())\n        state.normalEquationInfo.estimateSatellite.at(sat->idSat()) = FALSE;\n    logInfo<<\"  \"<<std::count(state.normalEquationInfo.estimateSatellite.begin(), state.normalEquationInfo.estimateSatellite.end(), TRUE)<<\" satellites selected\"<<Log::endl;\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepSelectStations.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepSelectStations.h\n*\n* @brief SLR processing step: SelectStations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPSELECTSTATION__\n#define __GROOPS_SLRPROCESSINGSTEPSELECTSTATION__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepSelectStations = R\"(\n\\subsection{SelectStations}\\label{slrProcessingStepType:selectStations}\nThis step can be used to process only a subset of stations in subsequent processing steps.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: SelectStations.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepSelectStations : public SlrProcessingStepBase\n{\n  PlatformSelectorPtr selectorStations;\n\npublic:\n  SlrProcessingStepSelectStations(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n  Bool expectInitializedParameters() const override {return FALSE;}\n};\n\n/***********************************************/\n\ninline SlrProcessingStepSelectStations::SlrProcessingStepSelectStations(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectStations\", selectorStations, Config::MUSTSET,  \"\", \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepSelectStations::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== select stations ========================================\"<<Log::endl;\n    state.normalEquationInfo.estimateStation = state.slr->selectStations(selectorStations);\n    for(auto stat : state.slr->stations)\n      if(!stat->useable())\n        state.normalEquationInfo.estimateStation.at(stat->idStat()) = FALSE;\n    logInfo<<\"  \"<<std::count(state.normalEquationInfo.estimateStation.begin(), state.normalEquationInfo.estimateStation.end(), TRUE)<<\" stations selected\"<<Log::endl;\n    state.changedNormalEquationInfo = TRUE;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepWriteAprioriSolution.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepWriteAprioriSolution.h\n*\n* @brief SLR processing step: WriteAprioriSolution.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPWRITEAPRIORISOLUTION__\n#define __GROOPS_SLRPROCESSINGSTEPWRITEAPRIORISOLUTION__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepWriteAprioriSolution = R\"(\n\\subsection{WriteAprioriSolution}\\label{slrProcessingStepType:writeAprioriSolution}\nWrites the current apriori vector $\\M x_0$\n(see \\configClass{parametrizations}{slrParametrizationType}).\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileParameterName.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: WriteAprioriSolution.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepWriteAprioriSolution : public SlrProcessingStepBase\n{\n  FileName             fileNameApriori, fileNameParameterNames;\n  ParameterSelectorPtr parameterSelector;\n\npublic:\n  SlrProcessingStepWriteAprioriSolution(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepWriteAprioriSolution::SlrProcessingStepWriteAprioriSolution(Config &config)\n{\n  try\n  {\n    readConfig(config, \"outputfileAprioriSolution\", fileNameApriori,        Config::OPTIONAL, \"output/x0_{loopTime:%D}.txt\",            \"a priori parameters\");\n    readConfig(config, \"outputfileParameterNames\",  fileNameParameterNames, Config::OPTIONAL, \"output/parameterNames_{loopTime:%D}.txt\", \"parameter names\");\n    readConfig(config, \"remainingParameters\",       parameterSelector,      Config::OPTIONAL, \"\",  \"parameter order/selection of output normal equations\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepWriteAprioriSolution::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    std::vector<UInt> indexVector(state.normalEquationInfo.parameterCount());\n    if(parameterSelector)\n      indexVector = parameterSelector->indexVector(state.normalEquationInfo.parameterNames());\n    else\n      std::iota(indexVector.begin(), indexVector.end(), 0);\n\n    if(!fileNameApriori.empty())\n    {\n      logStatus<<\"write apriori solution to <\"<<fileNameApriori<<\">\"<<Log::endl;\n      const Vector x0 = reorder(state.slr->aprioriParameter(state.normalEquationInfo), indexVector);\n      writeFileMatrix(fileNameApriori, x0);\n    }\n\n    if(!fileNameParameterNames.empty())\n    {\n      logStatus<<\"write parameter name file <\"<<fileNameParameterNames<<\">\"<<Log::endl;\n      std::vector<ParameterName> parameterNames;\n      for(UInt i=0; i<indexVector.size(); i++)\n        parameterNames.push_back((indexVector.at(i) != NULLINDEX) ? state.normalEquationInfo.parameterNames().at(indexVector.at(i)) : ParameterName());\n      writeFileParameterName(fileNameParameterNames, parameterNames);\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepWriteNormalEquations.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepWriteNormalEquations.h\n*\n* @brief SLR processing step: WriteNormalEquations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPWRITENORMALEQUATIONS__\n#define __GROOPS_SLRPROCESSINGSTEPWRITENORMALEQUATIONS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepWriteNormalEquations = R\"(\n\\subsection{WriteNormalEquations}\\label{slrProcessingStepType:writeNormalEquations}\nAccumulates the normal equations matrix and writes it.\nIf \\configClass{remainingParameters}{parameterSelectorType}\nis set only the selected parameters are written to the normal equations\nand all other parameters are eliminated beforehand (implicitly solved).\n\nThe solution of the normals would results in $\\Delta\\M x$\n(see \\configClass{parametrizations}{slrParametrizationType}). To write the\nappropriate apriori vector $\\M x_0$ use\n\\configClass{processingStep:writeAprioriSolution}{slrProcessingStepType:writeAprioriSolution}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileNormalEquation.h\"\n#include \"classes/parameterSelector/parameterSelector.h\"\n#include \"slr/slrNormalEquationInfo.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: WriteNormalEquations.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepWriteNormalEquations : public SlrProcessingStepBase\n{\n  FileName             fileNameNormals;\n  ParameterSelectorPtr parameterSelector;\n  Bool                 constraintsOnly;\n  UInt                 defaultBlockSize;\n\npublic:\n  SlrProcessingStepWriteNormalEquations(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepWriteNormalEquations::SlrProcessingStepWriteNormalEquations(Config &config)\n{\n  try\n  {\n    defaultBlockSize = NULLINDEX;\n    readConfig(config, \"outputfileNormalEquations\", fileNameNormals,   Config::MUSTSET,  \"output/normals_{loopTime:%D}.dat\", \"normals\");\n    readConfig(config, \"remainingParameters\",       parameterSelector, Config::OPTIONAL, \"\",  \"parameter order/selection of output normal equations\");\n    readConfig(config, \"constraintsOnly\",           constraintsOnly,   Config::DEFAULT,  \"0\", \"write only normals of constraints without observations\");\n    readConfig(config, \"defaultNormalsBlockSize\",   defaultBlockSize,  Config::OPTIONAL, \"\",  \"block size for distributing the normal equations, 0: one block, empty: original block size\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepWriteNormalEquations::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== write normal equations ==================================\"<<Log::endl;\n    std::vector<UInt> blockIndex, indexVector(state.normalEquationInfo.parameterCount());\n    std::iota(indexVector.begin(), indexVector.end(), 0);\n\n    // compute index vectors and block structure for remaining parameters\n    UInt eliminationBlocks = 0, eliminationCount = 0;\n    if(parameterSelector)\n    {\n      indexVector = parameterSelector->indexVector(state.normalEquationInfo.parameterNames());\n      std::vector<UInt> eliminationIndexVector = ParameterSelector::indexVectorComplement(indexVector, state.normalEquationInfo.parameterCount());\n      eliminationCount = eliminationIndexVector.size();\n      indexVector.insert(indexVector.begin(), eliminationIndexVector.begin(), eliminationIndexVector.end());\n\n      blockIndex = MatrixDistributed::computeBlockIndex(eliminationCount, 2048);\n      eliminationBlocks = blockIndex.size()-1;\n      if(defaultBlockSize == 0)\n        blockIndex.push_back(indexVector.size());\n      else\n        while(blockIndex.back() < indexVector.size())\n          blockIndex.push_back(std::min(blockIndex.back()+((defaultBlockSize == NULLINDEX) ? 2048 : defaultBlockSize), indexVector.size()));\n    }\n    else if(defaultBlockSize != NULLINDEX)\n      blockIndex = MatrixDistributed::computeBlockIndex(state.normalEquationInfo.parameterCount(), defaultBlockSize);\n\n    // accumulate normals\n    state.buildNormals(constraintsOnly);\n    // merge right hand side to one matrix\n    Matrix rhs(state.normals.parameterCount(), state.lPl.rows());\n    for(UInt i=0; i<state.normals.blockCount(); i++)\n      copy(state.n.at(i), rhs.row(state.normals.blockIndex(i), state.normals.blockSize(i)));\n    Vector x0 = state.slr->aprioriParameter(state.normalEquationInfo);\n\n    // reorder normals\n    if((defaultBlockSize != NULLINDEX) || parameterSelector)\n    {\n      state.normals.reorder(indexVector, blockIndex);\n      rhs = reorder(rhs, indexVector);\n      x0  = reorder(x0,  indexVector);\n      if((eliminationCount > 0) && !constraintsOnly)\n      {\n        state.regularizeNotUsedParameters(0, eliminationBlocks);\n        state.normals.cholesky(TRUE, 0, eliminationBlocks, TRUE);\n        state.normals.triangularTransSolve(rhs, 0, eliminationBlocks);\n        state.obsCount -= eliminationCount;\n        for(UInt i=0; i<state.lPl.rows(); i++)\n          state.lPl(i) -= quadsum(rhs.slice(0, i, eliminationCount, 1)); // lPl = lPl - n1' N1^(-1) n1\n      }\n      state.normals.eraseBlocks(0, eliminationBlocks);\n      rhs = rhs.row(eliminationCount, rhs.rows()-eliminationCount);\n      x0  = x0.row (eliminationCount, x0.rows()-eliminationCount);\n    }\n\n    // add a priori solution: n += N*x0\n    Matrix Nx(x0.rows(), x0.columns());\n    for(UInt i=0; i<state.normals.blockCount(); i++)\n    {\n      if(state.normals.isMyRank(i,i))\n        matMult(1., state.normals.N(i,i), x0.row(state.normals.blockIndex(i), state.normals.blockSize(i)), Nx.row(state.normals.blockIndex(i), state.normals.blockSize(i)));\n      for(UInt k=i+1; k<state.normals.blockCount(); k++)\n        if(state.normals.isMyRank(i,k))\n        {\n          matMult(1., state.normals.N(i,k),         x0.row(state.normals.blockIndex(k), state.normals.blockSize(k)), Nx.row(state.normals.blockIndex(i), state.normals.blockSize(i)));\n          matMult(1., state.normals.N(i,k).trans(), x0.row(state.normals.blockIndex(i), state.normals.blockSize(i)), Nx.row(state.normals.blockIndex(k), state.normals.blockSize(k)));\n        }\n    }\n    for(UInt i=0; i<state.lPl.rows(); i++)\n      state.lPl(i) += 2.*inner(x0.column(i), rhs.column(i)) + inner(x0.column(i), Nx.column(i));\n    rhs += Nx;\n\n    // parameter names\n    std::vector<ParameterName> parameterNames;\n    for(UInt i=eliminationCount; i<indexVector.size(); i++)\n      parameterNames.push_back((indexVector.at(i) != NULLINDEX) ? state.normalEquationInfo.parameterNames().at(indexVector.at(i)) : ParameterName());\n\n    logStatus<<\"write normal equations to <\"<<fileNameNormals<<\">\"<<Log::endl;\n    writeFileNormalEquation(fileNameNormals, NormalEquationInfo(parameterNames, state.lPl, state.obsCount), state.normals, rhs);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepWriteResiduals.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepWriteResiduals.h\n*\n* @brief SLR processing step: WriteResiduals.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPWRITERESIDUALS__\n#define __GROOPS_SLRPROCESSINGSTEPWRITERESIDUALS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepWriteResiduals = R\"(\n\\subsection{WriteResiduals}\\label{slrProcessingStepType:writeResiduals}\nWrites the \\file{observation residuals}{instrument} for all\n\\configClass{selectStations}{platformSelectorType}. For for each station-satellite\npair a file is written. The file name is interpreted as a template with\nthe variables \\verb|{station}| and \\verb|{satellite}| being replaced by the station name.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: WriteResiduals.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepWriteResiduals : public SlrProcessingStepBase\n{\n  PlatformSelectorPtr selectorStations, selectorSatellites;\n  FileName            fileNameResiduals;\n\npublic:\n  SlrProcessingStepWriteResiduals(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepWriteResiduals::SlrProcessingStepWriteResiduals(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectStations\",      selectorStations,   Config::MUSTSET, \"\", \"subset of used stations\");\n    readConfig(config, \"selectSatellites\",    selectorSatellites, Config::MUSTSET, \"\", \"subset of used satellites\");\n    readConfig(config, \"outputfileResiduals\", fileNameResiduals,  Config::MUSTSET, \"output/residuals_{loopTime:%D}.{station}.{satellite}.dat\", \"variable {station} available\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepWriteResiduals::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    auto selectedStations   = state.slr->selectStations(selectorStations);\n    auto selectedSatellites = state.slr->selectSatellites(selectorSatellites);\n\n    VariableList varList;\n    varList.setVariable(\"station\",   \"****\");\n    varList.setVariable(\"satellite\", \"****\");\n    logStatus<<\"write residuals to file <\"<<fileNameResiduals(varList)<<\">\"<<Log::endl;\n    for(auto stat : state.slr->stations)\n      if(selectedStations.at(stat->idStat()) && state.normalEquationInfo.estimateStation.at(stat->idStat()) && stat->useable())\n        for(auto sat : state.slr->satellites)\n          if(selectedSatellites.at(sat->idSat()) && state.normalEquationInfo.estimateSatellite.at(sat->idSat()) && sat->useable())\n          {\n            std::vector<SatelliteLaserRangingArc> arcList;\n            for(auto &obs : stat->observations.at(sat->idSat()))\n            {\n              SlrObservationEquation eqn;\n              eqn.compute(*obs, *stat, *sat, state.slr->funcRotationCrf2Trf, state.slr->funcReduceModels, FALSE);\n              Matrix data(obs->observations.rows(), 1+Epoch::dataCount(Epoch::SATELLITELASERRANGING));\n              copy(obs->residuals,    data.column(1)); // data1 range [seconds]\n              copy(obs->redundancies, data.column(3)); // data3 redundancy\n              for(UInt i=0; i<data.rows(); i++)\n              {\n                data(i, 2) = obs->sigmas(i)/obs->sigmas0(i); // data2 rms\n                data(i, 5) = obs->laserWavelength(i);        // data5 laser wavelength\n                data(i, 6) = eqn.azimutStat.at(i);           // data5 azmiuth\n                data(i, 7) = eqn.elevationStat.at(i);        // data6 elevation\n              }\n\n              arcList.push_back(Arc(obs->timesTrans, data, Epoch::SATELLITELASERRANGING));\n            }\n\n            if(arcList.size())\n            {\n              VariableList varList;\n              varList.setVariable(\"station\",   stat->name());\n              varList.setVariable(\"satellite\", sat->name());\n              InstrumentFile::write(fileNameResiduals(varList), arcList);\n            }\n          } // for(stat, sat)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepWriteResults.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepWriteResults.h\n*\n* @brief SLR processing step: WriteResults.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPWRITERESULTS__\n#define __GROOPS_SLRPROCESSINGSTEPWRITERESULTS__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepWriteResults = R\"(\n\\subsection{WriteResults}\\label{slrProcessingStepType:writeResults}\nIn this step all \\config{outputfiles} defined in \\configClass{parametrizations}{slrParametrizationType}\nare written. It considers the settings of\n\\configClass{processingStep:selectParametrizations}{slrProcessingStepType:selectParametrizations}\nand \\configClass{processingStep:selectStations}{slrProcessingStepType:selectStations}.\n\nIt is usually the last processing step, but can also be used at other points in the\nprocessing in combination with \\config{suffix} to write intermediate results.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: WriteResults.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepWriteResults : public SlrProcessingStepBase\n{\n  std::string suffix;\n\npublic:\n  SlrProcessingStepWriteResults(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepWriteResults::SlrProcessingStepWriteResults(Config &config)\n{\n  readConfig(config, \"suffix\", suffix, Config::OPTIONAL, \"\", \"appended to every output file name (e.g. orbit.G01.suffix.dat)\");\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepWriteResults::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    logStatus<<\"=== write results  ==========================================\"<<Log::endl;\n    state.slr->writeResults(state.normalEquationInfo, !suffix.empty() ? \".\"+suffix : \"\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepWriteUsedSatelliteList.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepWriteUsedSatelliteList.h\n*\n* @brief SLR processing step: WriteUsedSatelliteList.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPWRITEUSEDSATELLITELIST__\n#define __GROOPS_SLRPROCESSINGSTEPWRITEUSEDSATELLITELIST__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepWriteUsedSatelliteList = R\"(\n\\subsection{WriteUsedSatelliteList}\\label{slrProcessingStepType:writeUsedSatelliteList}\nWrites a \\file{list}{stringList} of satellites which are used in the last step and\nselected by \\configClass{selectSatellites}{platformSelectorType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: WriteUsedSatelliteList.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepWriteUsedSatelliteList : public SlrProcessingStepBase\n{\n  PlatformSelectorPtr selectorSatellites;\n  FileName            fileNameOutSatelliteList;\n\npublic:\n  SlrProcessingStepWriteUsedSatelliteList(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepWriteUsedSatelliteList::SlrProcessingStepWriteUsedSatelliteList(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectSatellites\",            selectorSatellites,       Config::MUSTSET, \"\", \"subset of used satellites\");\n    readConfig(config, \"outputfileUsedSatelliteList\", fileNameOutSatelliteList, Config::MUSTSET, \"output/satelliteList.txt\", \"ascii file with names\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepWriteUsedSatelliteList::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    auto selectedSatellites = state.slr->selectSatellites(selectorSatellites);\n    logStatus<<\"write used satellite list to file <\"<<fileNameOutSatelliteList<<\">\"<<Log::endl;\n    std::vector<std::string> usedSatelliteList;\n    for(auto sat : state.slr->satellites)\n      if(selectedSatellites.at(sat->idSat()) && state.normalEquationInfo.estimateSatellite.at(sat->idSat()) && sat->useable())\n        usedSatelliteList.push_back(sat->name());\n    writeFileStringList(fileNameOutSatelliteList, usedSatelliteList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrProcessingStep/slrProcessingStepWriteUsedStationList.h",
    "content": "/***********************************************/\n/**\n* @file slrProcessingStepWriteUsedStationList.h\n*\n* @brief SLR processing step: WriteUsedStationList.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRPROCESSINGSTEPWRITEUSEDSTATIONLIST__\n#define __GROOPS_SLRPROCESSINGSTEPWRITEUSEDSTATIONLIST__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrProcessingStep\nstatic const char *docstringSlrProcessingStepWriteUsedStationList = R\"(\n\\subsection{WriteUsedStationList}\\label{slrProcessingStepType:writeUsedStationList}\nWrites a \\file{list}{stringList} of stations (stations) which are used in the last step and\nselected by \\configClass{selectStations}{platformSelectorType}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/platformSelector/platformSelector.h\"\n#include \"slr/slrProcessingStep/slrProcessingStep.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR processing step: WriteUsedStationList.\n* @ingroup slrProcessingStepGroup\n* @see SlrProcessingStep */\nclass SlrProcessingStepWriteUsedStationList : public SlrProcessingStepBase\n{\n  PlatformSelectorPtr selectorStations;\n  FileName            fileNameUsedStationList;\n\npublic:\n  SlrProcessingStepWriteUsedStationList(Config &config);\n  void process(SlrProcessingStep::State &state) override;\n};\n\n/***********************************************/\n\ninline SlrProcessingStepWriteUsedStationList::SlrProcessingStepWriteUsedStationList(Config &config)\n{\n  try\n  {\n    readConfig(config, \"selectStations\",            selectorStations,        Config::MUSTSET, \"\", \"subset of used stations\");\n    readConfig(config, \"outputfileUsedStationList\", fileNameUsedStationList, Config::MUSTSET, \"output/stationList.txt\", \"ascii file with names of used stations\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline void SlrProcessingStepWriteUsedStationList::process(SlrProcessingStep::State &state)\n{\n  try\n  {\n    auto selectedStations = state.slr->selectStations(selectorStations);\n    logStatus<<\"write used station list to file <\"<<fileNameUsedStationList<<\">\"<<Log::endl;\n    std::vector<std::string> usedStationList;\n    for(auto stat : state.slr->stations)\n      if(selectedStations.at(stat->idStat()) && state.normalEquationInfo.estimateStation.at(stat->idStat()) && stat->useable())\n        usedStationList.push_back(stat->name());\n    writeFileStringList(fileNameUsedStationList, usedStationList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrSatellite.h",
    "content": "/***********************************************/\n/**\n* @file slrSatellite.h\n*\n* @brief SLR satellite.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRSATELLITE__\n#define __GROOPS_SLRSATELLITE__\n\n#include \"base/polynomial.h\"\n#include \"slr/slrPlatform.h\"\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SlrSatellite;\ntypedef std::shared_ptr<SlrSatellite> SlrSatellitePtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for SLR satellite.\n* eg. GPS satellites. */\nclass SlrSatellite : public SlrPlatform\n{\npublic:\n  Polynomial        polynomial;\n  std::vector<Time> times;\n  Matrix            pos, vel; // CoM in CRF (epoch x (x,y,z))\n  Matrix            srf2crf;\n\n  SlrSatellite(const Platform &platform, const std::vector<Time> &times,\n               const_MatrixSliceRef position, const_MatrixSliceRef velocity, const_MatrixSliceRef srf2crf, UInt interpolationDegree)\n    : SlrPlatform(platform), polynomial(times, interpolationDegree, FALSE/*throwException*/), times(times), pos(position), vel(velocity), srf2crf(srf2crf) {}\n\n  /// Destructor.\n  virtual ~SlrSatellite() {}\n\n  /** @brief Identify number in the SLR system. */\n  UInt idSat() const {return id_;}\n\n  /** @brief center of mass in celestial reference frame (CRF). */\n  Vector3d position(const Time &time) const;\n\n  /** @brief velocity in CRF [m/s]. */\n  Vector3d velocity(const Time &time) const;\n\n  /** @brief Vector from center of mass to the reflector in CRF [m].\n  * With corrections (e.g. range bias).\n  * @param time of reflection\n  * @param direction towards the reflector in CRF. */\n  Vector3d centerOfMass2Reflector(const Time &time, const Vector3d &direction) const;\n};\n\n/***********************************************/\n\ninline Vector3d SlrSatellite::position(const Time &time) const\n{\n  try\n  {\n    return Vector3d(polynomial.interpolate({time}, pos));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d SlrSatellite::velocity(const Time &time) const\n{\n  try\n  {\n    return Vector3d(polynomial.interpolate({time}, vel));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\ninline Vector3d SlrSatellite::centerOfMass2Reflector(const Time &time, const Vector3d &direction) const\n{\n  try\n  {\n    auto lrr = platform.findEquipment<PlatformLaserRetroReflector>(time);\n    if(!lrr)\n      throw(Exception(\"no LRR found for \"+platform.name));\n    const Rotary3d srf2crf = Rotary3d(polynomial.interpolate({time}, this->srf2crf).trans());\n    Vector3d offset  = srf2crf.rotate(lrr->position-platform.referencePoint(time));\n\n    if(lrr->range.size() == 1)\n      offset -= lrr->range(0,0) * direction;\n    else if(lrr->range.size() > 1)\n    {\n      const Vector3d d = lrr->platform2reflectorFrame.transform(srf2crf.inverseRotate(direction));\n      Double tauA      = std::fmod(Double(d.lambda())/(2*PI)+1,1) * lrr->range.rows();\n      Double tauZ      = (PI/2-Double(d.phi()))/Double(lrr->dZenit);\n      const UInt idxA1 = static_cast<UInt>(std::floor(tauA));\n      const UInt idxA2 = (idxA1+1)%lrr->range.rows();\n      const UInt idxZ1 = std::min(static_cast<UInt>(std::floor(tauZ)), lrr->range.columns()-1);\n      const UInt idxZ2 = std::min(idxZ1+1, lrr->range.columns()-1);\n      tauA -= std::floor(tauA);\n      tauZ -= std::floor(tauZ);\n\n      // bilinear interpolation\n      offset -= ((1-tauA) * (1-tauZ) * lrr->range(idxA1, idxZ1)\n               + (1-tauA) *  (tauZ)  * lrr->range(idxA1, idxZ2)\n               +  (tauA)  * (1-tauZ) * lrr->range(idxA2, idxZ1)\n               +  (tauA)  *  (tauZ)  * lrr->range(idxA2, idxZ2)) * direction;\n    }\n\n    return offset;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrSatelliteGenerator/slrSatelliteGenerator.cpp",
    "content": "/***********************************************/\n/**\n* @file slrSatelliteGenerator.cpp\n*\n* @brief Provides a list of satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_SlrSatelliteGenerator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"config/config.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrSatelliteGenerator/slrSatelliteGenerator.h\"\n#include \"slr/slrSatelliteGenerator/slrSatelliteGeneratorSatellites.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(SlrSatelliteGenerator, \"slrSatelliteGeneratorType\",\n                      SlrSatelliteGeneratorSatellites)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(SlrSatelliteGenerator, \"slrSatelliteGeneratorType\")\n\n/***********************************************/\n\nSlrSatelliteGenerator::SlrSatelliteGenerator(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"satellites\", type, \"\"))\n        base.push_back(new SlrSatelliteGeneratorSatellites(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrSatelliteGenerator::~SlrSatelliteGenerator()\n{\n  for(UInt i=0; i<base.size(); i++)\n    delete base.at(i);\n}\n\n/***********************************************/\n\nstd::vector<SlrSatellitePtr> SlrSatelliteGenerator::satellites(const std::vector<Time> &times)\n{\n  try\n  {\n    std::vector<SlrSatellitePtr> satellites;\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->init(times, satellites);\n    return satellites;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrSatelliteGenerator/slrSatelliteGenerator.h",
    "content": "/***********************************************/\n/**\n* @file slrSatelliteGenerator.h\n*\n* @brief Provides a list of satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRSATELLITEGENERATOR__\n#define __GROOPS_SLRSATELLITEGENERATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrSatelliteGenerator\nstatic const char *docstringSlrSatelliteGenerator = R\"(\n\\section{SlrSatelliteGenerator}\\label{slrSatelliteGeneratorType}\nDefinition and basic information of SLR satellites.\n\nSee also \\program{SlrProcessing}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"slr/slrSatellite.h\"\n\n/**\n* @defgroup slrSatelliteGeneratorGroup SlrSatelliteGenerator\n* @brief Provides a list of satellites.\n* @ingroup classesGroup\n* The interface is given by @ref SlrSatelliteGenerator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SlrSatelliteGenerator;\nclass SlrSatelliteGeneratorBase;\ntypedef std::shared_ptr<SlrSatelliteGenerator> SlrSatelliteGeneratorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of satellites.\n* An Instance of this class can be created by @ref readConfig. */\nclass SlrSatelliteGenerator\n{\n  std::vector<SlrSatelliteGeneratorBase*> base;\n\npublic:\n  /** @brief Constructor from config. */\n  SlrSatelliteGenerator(Config &config, const std::string &name);\n\n  /// Destructor.\n ~SlrSatelliteGenerator();\n\n  /** @brief Iniatialize and returns a vector of satellites. */\n  std::vector<SlrSatellitePtr> satellites(const std::vector<Time> &times);\n\n  /** @brief creates an derived instance of this class. */\n  static SlrSatelliteGeneratorPtr create(Config &config, const std::string &name) {return SlrSatelliteGeneratorPtr(new SlrSatelliteGenerator(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class SlrSatelliteGenerator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SlrSatelliteGenerator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SlrSatelliteGeneratorPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass SlrSatelliteGeneratorBase\n{\npublic:\n  virtual ~SlrSatelliteGeneratorBase() {}\n  virtual void init(const std::vector<Time> &times, std::vector<SlrSatellitePtr> &satellites) = 0;\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrSatelliteGenerator/slrSatelliteGeneratorSatellites.cpp",
    "content": "/***********************************************/\n/**\n* @file slrSatelliteGeneratorSatellites.cpp\n*\n* @brief Provides a list of SLR satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/polynomial.h\"\n#include \"inputOutput/logging.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileStringTable.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrSatelliteGenerator/slrSatelliteGeneratorSatellites.h\"\n\n/***********************************************/\n\nSlrSatelliteGeneratorSatellites::SlrSatelliteGeneratorSatellites(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileSatelliteList\", fileNamesSatelliteList, Config::MUSTSET,  \"{groopsDataDir}/slr/satellites/satelliteList.txt\", \"ascii file with satellite names, used to loop variable {satellite}\");\n    readConfig(config, \"inputfileSatelliteInfo\", fileNameSatelliteInfo,  Config::MUSTSET,  \"{groopsDataDir}/slr/satellites/satelliteInfo/satelliteInfo.{satellite}.xml\", \"variable {satellite} available\");\n    readConfig(config, \"inputfileOrbit\",         fileNameOrbit,          Config::MUSTSET,  \"{satellite}_orbit_{loopTime:%D}.dat\",    \"variable {satellite} available\");\n    readConfig(config, \"inputfileAttitude\",      fileNameAttitude,       Config::OPTIONAL, \"{satellite}_attitude_{loopTime:%D}.dat\", \"variable {satellite} available\");\n    readConfig(config, \"interpolationDegree\",    interpolationDegree,    Config::DEFAULT,  \"7\", \"for orbit interpolation and velocity calculation\");\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrSatelliteGeneratorSatellites::init(const std::vector<Time> &/*times*/, std::vector<SlrSatellitePtr> &satellites)\n{\n  try\n  {\n    logStatus<<\"init satellites\"<<Log::endl;\n    std::vector<std::string> satelliteList;\n    for(const auto &fileNameSatelliteList : fileNamesSatelliteList)\n    {\n      std::vector<std::string> list;\n      readFileStringList(fileNameSatelliteList, list);\n      satelliteList.insert(satelliteList.end(), list.begin(), list.end());\n    }\n    VariableList varList;\n    for(const std::string &satellite : satelliteList)\n    {\n      try\n      {\n        varList.setVariable(\"satellite\", satellite);\n\n        Platform platform;\n        readFilePlatform(fileNameSatelliteInfo(varList), platform);\n        platform.name = satellite;\n\n        // read orbit\n        // ----------\n        OrbitArc orbit;\n        try\n        {\n          orbit = InstrumentFile::read(fileNameOrbit(varList));\n        }\n        catch(std::exception &/*e*/)\n        {\n          logWarningOnce<<\"Unable to read orbit file <\"<<fileNameOrbit(varList)<<\">, disabling satellite.\"<<Log::endl;\n          continue;\n        }\n\n        // read attitude\n        // -------------\n        StarCameraArc attitude;\n        if(!fileNameAttitude.empty())\n        {\n          try\n          {\n            attitude = InstrumentFile::read(fileNameAttitude(varList));\n          }\n          catch(std::exception &/*e*/)\n          {\n            logWarningOnce<<\"Unable to read attitude file <\"<<fileNameAttitude(varList)<<\">, disabling satellite.\"<<Log::endl;\n            continue;\n          }\n        }\n        if(!attitude.size()) // simulate along track, cross, nadir\n        {\n          for(UInt i=0; i<orbit.size(); i++)\n          {\n            StarCameraEpoch epoch;\n            epoch.time   = orbit.at(i).time;\n            epoch.rotary = Rotary3d(orbit.at(i).velocity, crossProduct(orbit.at(i).velocity, orbit.at(i).position));\n            attitude.push_back(epoch);\n          }\n        }\n\n        Arc::checkSynchronized({orbit, attitude});\n        std::vector<Time> times = orbit.times();\n        const Matrix data = orbit.matrix();\n        Matrix pos     = data.column(1, 3);\n        Matrix vel     = data.column(4, 3);\n        Matrix srf2crf = attitude.matrix().column(1, 4);\n\n        satellites.push_back(std::make_shared<SlrSatellite>(platform, times, pos, vel, srf2crf, interpolationDegree));\n      }\n      catch(std::exception &e)\n      {\n        logWarningOnce<<\"Unable to initialize satellite: \"<<e.what()<<Log::endl;\n      }\n    } // for(idSat)\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrSatelliteGenerator/slrSatelliteGeneratorSatellites.h",
    "content": "/***********************************************/\n/**\n* @file slrSatelliteGeneratorSatellites.h\n*\n* @brief Provides a list of SLR satellites.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRSLRSATELLITEGENERATORSATELLITES__\n#define __GROOPS_SLRSLRSATELLITEGENERATORSATELLITES__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrSatelliteGenerator\nstatic const char *docstringSlrSatelliteGeneratorSatellites = R\"(\n\\subsection{Satellites}\\label{slrSatelliteGeneratorType:satellites}\nA list of satellite names must be provided via \\configFile{inputfileSatelliteList}{stringList}.\nThe other input files are read for each satellite, where the file name is interpreted as a template\nwith the variable \\verb|{satellite}| being replaced by the satellite name from list.\nThe \\configFile{inputfileSatelliteInfo}{platform} contains information about laser retro-reflector,\noptical reference point, retro-reflector orientation, range corrections and center of mass.\nIt can be created via \\program{PlatformCreate}.\nIf \\configFile{inputfileAttitude}{instrument} ist not provided an orbit reference frame\n(along, cross, nearly nadir) is assumed.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"slr/slrSatelliteGenerator/slrSatelliteGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of SLR satellites.\n* @ingroup slrSatelliteGeneratorGroup\n* @see SlrSatelliteGenerator */\nclass SlrSatelliteGeneratorSatellites : public SlrSatelliteGeneratorBase\n{\n  std::vector<FileName> fileNamesSatelliteList;\n  FileName              fileNameSatelliteInfo;\n  FileName              fileNameOrbit, fileNameAttitude;\n  UInt                  interpolationDegree;\n\npublic:\n  SlrSatelliteGeneratorSatellites(Config &config);\n  void init(const std::vector<Time> &times, std::vector<SlrSatellitePtr> &satellites) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/slr/slrStation.cpp",
    "content": "/***********************************************/\n/**\n* @file slrStation.cpp\n*\n* @brief SLR station.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n// #include <random>\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"parser/expressionParser.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileInstrument.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/system.h\"\n#include \"misc/varianceComponentEstimation.h\"\n#include \"slr/slrObservation.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrStation.h\"\n\n/***********************************************/\n\nSlrStation::SlrStation(const Platform &platform, const std::vector<Time> &times, const Vector3d &pos, const_MatrixSliceRef offset,\n                       ExpressionVariablePtr accuracyExpr, UInt interpolationDegree)\n  : SlrPlatform(platform), polynomial(times, interpolationDegree, FALSE/*throwException*/), accuracyExpr(accuracyExpr), times(times), pos(pos), offset(offset)\n{\n  global2local = inverse(localNorthEastUp(platform.approxPosition, Ellipsoid()));\n}\n\n/***********************************************/\n\nvoid SlrStation::disable(const std::string &reason)\n{\n  try\n  {\n    SlrPlatform::disable(reason);\n    if(!reason.empty())\n      disableReason = reason;\n    observations.clear();\n    observations.shrink_to_fit();\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nVector3d SlrStation::position(const Time &time) const\n{\n  try\n  {\n    return pos + global2local.inverseTransform(Vector3d(polynomial.interpolate({time}, offset)));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nTransform3d SlrStation::global2localFrame(const Time &/*time*/) const\n{\n  return global2local;\n}\n\n/***********************************************/\n\nstd::vector<Time> SlrStation::correctedTimes(const std::vector<Time> &times) const\n{\n  try\n  {\n    if(!timeBiases.size())\n      return times;\n\n    std::vector<Time> timesCorrected = times;\n    Vector bias = polynomial.interpolate({times}, timeBiases);\n    for(UInt i=0; i<times.size(); i++)\n      timesCorrected.at(i) -= seconds2time(bias(i));\n    return timesCorrected;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nDouble SlrStation::accuracy(const Time &/*time*/, Double residual, Double accuracy, Double redundancy,\n                            Double laserWavelength, Angle azimut, Angle elevation) const\n{\n  try\n  {\n    accuracyVariableList.setVariable(\"residual\",        residual);\n    accuracyVariableList.setVariable(\"accuracy\",        accuracy);\n    accuracyVariableList.setVariable(\"redundancy\",      redundancy);\n    accuracyVariableList.setVariable(\"laserWavelength\", laserWavelength);\n    accuracyVariableList.setVariable(\"azimut\",          azimut);\n    accuracyVariableList.setVariable(\"elevation\",       elevation);\n    return accuracyExpr->evaluate(accuracyVariableList);\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrStation.h",
    "content": "/***********************************************/\n/**\n* @file slrStation.h\n*\n* @brief SLR station.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRSTATION__\n#define __GROOPS_SLRSTATION__\n\n#include \"parser/expressionParser.h\"\n#include \"files/fileInstrument.h\"\n#include \"slr/slrObservation.h\"\n#include \"slr/slrPlatform.h\"\n#include \"slr/slrSatellite.h\"\n\n/** @addtogroup slrGroup */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass SlrStation;\ntypedef std::shared_ptr<SlrStation> SlrStationPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Abstract class for SLR station. */\nclass SlrStation : public SlrPlatform\n{\n  Polynomial            polynomial;\n  Transform3d           global2local;\n  mutable VariableList  accuracyVariableList;\n  ExpressionVariablePtr accuracyExpr;\n\npublic:\n  std::vector<Time>         times;      // of offset and timeBiases\n  Vector3d                  pos;        // regularized marker pos in global system\n  Matrix                    offset;     // pos to SRF in local system\n  Vector                    timeBiases; // Observed time - corrected time [seconds]\n  std::vector<std::string>  preprocessingInfos;\n  std::string               disableReason;\n  std::vector<std::vector<SlrObservationPtr>> observations; // observations at station (for each satellite, for each pass)\n\n  SlrStation(const Platform &platform, const std::vector<Time> &times, const Vector3d &pos, const_MatrixSliceRef offset,\n             ExpressionVariablePtr accuracyExpr, UInt interpolationDegree);\n\n  /// Destructor.\n  virtual ~SlrStation() {}\n\n  /** @brief Identify number in the SLR system. */\n  UInt idStat() const {return id_;}\n\n  /** @brief Disable station completely. */\n  void disable(const std::string &reason) override;\n\n  /** @brief system reference point (SRF) in TRF. */\n  Vector3d position(const Time &time) const;\n\n  /** @brief Rotation from terrestrial reference frame (TRF) to local frame (north, east, up). */\n  Transform3d global2localFrame(const Time &time) const;\n\n  /** @brief Corrected for system time biases. */\n  std::vector<Time> correctedTimes(const std::vector<Time> &times) const;\n\n  /** @brief Direction (and other parameters) dependent standard deviation.\n  * @a azmiut and @a elevation must be given in the antenna frame (left-handed). */\n  Double accuracy(const Time &time, Double residual, Double accuracy, Double redundancy,\n                  Double laserWavelength, Angle azimut, Angle elevation) const;\n}; //class SlrStation\n\n/***********************************************/\n\n/// @}\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrStationGenerator/slrStationGenerator.cpp",
    "content": "/***********************************************/\n/**\n* @file slrStationGenerator.cpp\n*\n* @brief Provides a list of stations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#define DOCSTRING_SlrStationGenerator\n\n#include \"base/import.h\"\n#include \"config/configRegister.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"slr/slrStation.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrStationGenerator/slrStationGenerator.h\"\n#include \"slr/slrStationGenerator/slrStationGeneratorStations.h\"\n#include \"slr/slrStationGenerator/slrStationGenerator.h\"\n\n/***********************************************/\n\nGROOPS_REGISTER_CLASS(SlrStationGenerator, \"slrStationGeneratorType\",\n                      SlrStationGeneratorStations)\n\nGROOPS_READCONFIG_UNBOUNDED_CLASS(SlrStationGenerator, \"slrStationGeneratorType\")\n\n/***********************************************/\n\nSlrStationGenerator::SlrStationGenerator(Config &config, const std::string &name)\n{\n  try\n  {\n    std::string type;\n    while(readConfigChoice(config, name, type, Config::OPTIONAL, \"\", \"\"))\n    {\n      if(readConfigChoiceElement(config, \"stations\", type, \"\"))\n        base.push_back(new SlrStationGeneratorStations(config));\n      endChoice(config);\n      if(isCreateSchema(config))\n        return;\n    }\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nSlrStationGenerator::~SlrStationGenerator()\n{\n  for(UInt i=0; i<base.size(); i++)\n    delete base.at(i);\n}\n\n/***********************************************/\n\nstd::vector<SlrStationPtr> SlrStationGenerator::stations(const std::vector<Time> &times, const std::vector<SlrSatellitePtr> &satellites,\n                                                         EarthRotationPtr earthRotation)\n{\n  try\n  {\n    std::vector<SlrStationPtr> stations;\n    for(UInt i=0; i<base.size(); i++)\n      base.at(i)->init(times, satellites, earthRotation, stations);\n    return stations;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\n// void SlrStationGenerator::preprocessing(Slr *slr)\n// {\n//   try\n//   {\n//     for(UInt i=0; i<base.size(); i++)\n//       base.at(i)->preprocessing(slr);\n//   }\n//   catch(std::exception &e)\n//   {\n//     GROOPS_RETHROW(e)\n//   }\n// }\n\n/***********************************************/\n\n// void SlrStationGenerator::simulation(const std::vector<SlrType> &types, NoiseGeneratorPtr noiseClock, NoiseGeneratorPtr noiseObs,\n//                                        Slr *slr)\n// {\n//   try\n//   {\n//     for(UInt i=0; i<base.size(); i++)\n//       base.at(i)->simulation(types, noiseClock, noiseObs, slr);\n//   }\n//   catch(std::exception &e)\n//   {\n//     GROOPS_RETHROW(e)\n//   }\n// }\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrStationGenerator/slrStationGenerator.h",
    "content": "/***********************************************/\n/**\n* @file slrStationGenerator.h\n*\n* @brief Provides a list of stations.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRRECEIVERGENERATOR__\n#define __GROOPS_SLRRECEIVERGENERATOR__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrStationGenerator\nstatic const char *docstringSlrStationGenerator = R\"(\n\\section{SlrStationGenerator}\\label{slrStationGeneratorType}\nDefinition and basic information of SLR ground stations.\n\nSee also \\program{SlrProcessing}.\n)\";\n#endif\n\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"config/config.h\"\n#include \"classes/earthRotation/earthRotation.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"slr/slrStation.h\"\n#include \"slr/slrSatellite.h\"\n\n/**\n* @defgroup slrStationGeneratorGroup SlrStationGenerator\n* @brief Provides a list of stations.\n* @ingroup classesGroup\n* The interface is given by @ref SlrStationGenerator. */\n/// @{\n\n/***** TYPES ***********************************/\n\nclass Slr;\nclass SlrStationGenerator;\nclass SlrStationGeneratorBase;\ntypedef std::shared_ptr<SlrStationGenerator> SlrStationGeneratorPtr;\n\n/***** CLASS ***********************************/\n\n/** @brief Provides a list of stations.\n* An Instance of this class can be created by @ref readConfig. */\nclass SlrStationGenerator\n{\n  std::vector<SlrStationGeneratorBase*> base;\n\npublic:\n  /** @brief Constructor from config. */\n  SlrStationGenerator(Config &config, const std::string &name);\n\n  /// Destructor.\n ~SlrStationGenerator();\n\n  /** @brief Iniatialize and returns a vector of stations. */\n  std::vector<SlrStationPtr> stations(const std::vector<Time> &times, const std::vector<SlrSatellitePtr> &satellites,\n                                      EarthRotationPtr earthRotation);\n\n  /** @brief preprocess the observations of stations. */\n  void preprocessing(Slr *slr);\n\n//   /** @brief simulate the observations of stations. */\n//   void simulation(NoiseGeneratorPtr noiseObs, Slr *slr);\n\n  /** @brief creates an derived instance of this class. */\n  static SlrStationGeneratorPtr create(Config &config, const std::string &name) {return SlrStationGeneratorPtr(new SlrStationGenerator(config, name));}\n};\n\n/***** FUNCTIONS *******************************/\n\n/** @brief Creates an instance of the class SlrStationGenerator.\n* Search for a node with @a name in the Config node.\n* if @a name is not found the function returns FALSE and @a var is untouched.\n* @param config The config node which includes the node with the options for this class\n* @param name Tag name in the config.\n* @param[out] var Created class.\n* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.\n* @param defaultValue Ignored at the moment.\n* @param annotation Description of the function of this class.\n* @relates SlrStationGenerator */\ntemplate<> Bool readConfig(Config &config, const std::string &name, SlrStationGeneratorPtr &var, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);\n\n/// @}\n\n/***** CLASS ***********************************/\n\n// Internal class\nclass SlrStationGeneratorBase\n{\npublic:\n  virtual ~SlrStationGeneratorBase() {}\n\n  virtual void init(const std::vector<Time> &times, const std::vector<SlrSatellitePtr> &satellites,\n                    EarthRotationPtr earthRotation, std::vector<SlrStationPtr> &stations) = 0;\n\n//   virtual void preprocessing(Slr *slr, Parallel::CommunicatorPtr comm) = 0;\n//\n//   virtual void simulation(NoiseGeneratorPtr noiseObs, Slr *slr, Parallel::CommunicatorPtr comm) = 0;\n\n  static void printPreprocessingInfos(const std::string &header, const std::vector<SlrStationPtr> &stations,\n                                      Bool disabledOnly);\n};\n\n/***********************************************/\n\n#endif /* __GROOPS___ */\n"
  },
  {
    "path": "source/slr/slrStationGenerator/slrStationGeneratorStations.cpp",
    "content": "/***********************************************/\n/**\n* @file slrStationGeneratorStations.cpp\n*\n* @brief SLR ground station network.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#include \"base/import.h\"\n#include \"base/string.h\"\n#include \"base/planets.h\"\n#include \"config/config.h\"\n#include \"inputOutput/logging.h\"\n#include \"inputOutput/system.h\"\n#include \"files/filePlatform.h\"\n#include \"files/fileInstrument.h\"\n#include \"files/fileMatrix.h\"\n#include \"files/fileStringTable.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/tides/tides.h\"\n#include \"slr/slr.h\"\n#include \"slr/slrStation.h\"\n#include \"slr/slrSatellite.h\"\n#include \"slr/slrStationGenerator/slrStationGenerator.h\"\n#include \"slr/slrStationGenerator/slrStationGeneratorStations.h\"\n\n/***********************************************/\n\nSlrStationGeneratorStations::SlrStationGeneratorStations(Config &config)\n{\n  try\n  {\n    readConfig(config, \"inputfileStationList\",               fileNameStationList,     Config::MUSTSET,  \"{groopsDataDir}/slr/stations/stationList.txt\", \"ascii file with station names\");\n    readConfig(config, \"inputfileStationInfo\",               fileNameStationInfo,     Config::MUSTSET,  \"{groopsDataDir}/slr/stations/stationInfo/stationInfo.{station}.xml\", \"station metadata\");\n    readConfig(config, \"inputfileStationPosition\",           fileNameStationPosition, Config::OPTIONAL, \"{groopsDataDir}/slr/stations/position/slrf2020_CM/stationPosition.{station}.dat\", \"station position\");\n    readConfig(config, \"disableStationWithoutPosition\",      disableWithoutPosition,  Config::DEFAULT,  \"0\",   \"drop stations without apriori position\");\n    readConfig(config, \"inputfileObservations\",              fileNameObs,             Config::OPTIONAL, \"normalPoints_{satellite}_{station}_{loopTime:%D}.dat\", \"variable {station} {satellite} available\");\n    readConfig(config, \"accuracy\",                           accuracyExpr,            Config::MUSTSET,  \"if(abs(residual)>30, NAN, accuracy)\", \"[m] used for weighting, variables: {residual}, {accuracy}, {redundancy}, {laserWavelength}, {azimut}, {elevation}\");\n    readConfig(config, \"loadingDisplacement\",                gravityfield,            Config::DEFAULT,  \"\",    \"loading deformation\");\n    readConfig(config, \"tidalDisplacement\",                  tides,                   Config::DEFAULT,  \"\",    \"tidal deformation\");\n    readConfig(config, \"ephemerides\",                        ephemerides,             Config::OPTIONAL, \"jpl\", \"for tidal deformation\");\n    readConfig(config, \"inputfileDeformationLoadLoveNumber\", deformationName,         Config::MUSTSET,  \"{groopsDataDir}/loading/deformationLoveNumbers_CM_Gegout97.txt\", \"\");\n    readConfig(config, \"inputfilePotentialLoadLoveNumber\",   potentialName,           Config::OPTIONAL, \"{groopsDataDir}/loading/loadLoveNumbers_Gegout97.txt\", \"if full potential is given and not only loading potential\");\n    readConfig(config, \"elevationCutOff\",                    elevationCutOff,         Config::DEFAULT,  \"5\", \"[degree] ignore observations below cutoff\");\n    readConfig(config, \"interpolationDegree\",                interpolationDegree,     Config::DEFAULT,  \"7\", \"for position interpolation\");\n    if(isCreateSchema(config)) return;\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n\nvoid SlrStationGeneratorStations::init(const std::vector<Time> &times, const std::vector<SlrSatellitePtr> &satellites,\n                                       EarthRotationPtr earthRotation, std::vector<SlrStationPtr> &stationsAll)\n{\n  try\n  {\n    logStatus<<\"init station network\"<<Log::endl;\n    std::vector<std::string> stationNames;\n    readFileStringList(fileNameStationList, stationNames);\n    VariableList varList;\n    std::vector<SlrStationPtr> stations;\n    for(const std::string &stationName : stationNames)\n    {\n      try\n      {\n        varList.setVariable(\"station\", stationName);\n\n        Platform platform;\n        readFilePlatform(fileNameStationInfo(varList), platform);\n        platform.name = stationName;\n        // is station available in this time interval?\n        if(!std::any_of(times.begin(), times.end(), [&](const Time &time) {return platform.findEquipment<PlatformSlrStation>(time);}))\n          continue;\n\n        // approximate station position\n        if(!fileNameStationPosition.empty())\n        {\n          try\n          {\n            if(!System::exists(fileNameStationPosition(varList)))\n              throw(Exception(\"file <\"+fileNameStationPosition(varList).str()+\"> not exist\"));\n            const Time timesMid = 0.5*(times.front()+times.back());\n            Vector3dArc arc = InstrumentFile::read(fileNameStationPosition(varList));\n            auto iter = std::min_element(arc.begin(), arc.end(), [&](const Epoch &e1, const Epoch &e2)\n                                        {return std::fabs((e1.time-timesMid).mjd()) < std::fabs((e2.time-timesMid).mjd());});\n            if(!arc.size() || ((arc.size() > 1) && (std::fabs((iter->time-timesMid).mjd()) > 0.5*medianSampling(arc.times()).mjd())))\n              throw(Exception(\"No a-priori position found\"));\n            platform.approxPosition = iter->vector3d;\n          }\n          catch(std::exception &e)\n          {\n            if(disableWithoutPosition)\n              throw;\n          }\n        }\n\n        Matrix offset(times.size(), 3);\n        for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        {\n          auto station = platform.findEquipment<PlatformSlrStation>(times.at(idEpoch));\n          if(station)\n            axpy(1., (station->position - platform.referencePoint(times.at(idEpoch))).vector().trans(), offset.row(idEpoch));\n        }\n\n        auto station = std::make_shared<SlrStation>(platform, times, platform.approxPosition, offset, accuracyExpr, interpolationDegree);\n\n        // read observations\n        // -----------------\n        if(!fileNameObs.empty())\n        {\n          auto rotationCrf2Trf = std::bind(&EarthRotation::rotaryMatrix, earthRotation, std::placeholders::_1);\n          station->observations.resize(satellites.size());\n          for(UInt idSat=0; idSat<satellites.size(); idSat++)\n          {\n            VariableList varList;\n            varList.setVariable(\"station\",   stationName);\n            varList.setVariable(\"satellite\", satellites.at(idSat)->name());\n            if(!System::exists(fileNameObs(varList)))\n              continue;\n\n            InstrumentFile file(fileNameObs(varList));\n            for(UInt idPass=0; idPass<file.arcCount(); idPass++)\n            {\n              SatelliteLaserRangingArc arc = file.readArc(idPass);\n              SlrObservationPtr obs = std::make_shared<SlrObservation>();\n              obs->timesTrans       = arc.times();\n              obs->observations     = arc.matrix().column(1);\n              obs->sigmas0          = arc.matrix().column(2);\n              obs->redundancies     = arc.matrix().column(3);\n              obs->laserWavelength  = arc.matrix().column(5);\n              if(obs->init(*station, *satellites.at(idSat), rotationCrf2Trf, elevationCutOff))\n                station->observations.at(idSat).push_back(obs);\n            }\n          }\n\n          if(std::none_of(station->observations.begin(), station->observations.end(), [](auto &o) {return o.size();}))\n            continue; // station without observations\n        }\n\n        stations.push_back(station);\n      }\n      catch(std::exception &e)\n      {\n        logWarningOnce<<stationName<<\" disabled: \"<<e.what()<<Log::endl;\n      }\n    } // for(stationNames)\n\n    // store valid stations\n    // ---------------------\n    stationsAll.insert(stationsAll.end(), stations.begin(), stations.end());\n    logInfo<<\"  \"<<stations.size()<<\" of \"<<stationNames.size()<<\" stations used\"<<Log::endl;\n\n    // tides & loading\n    // ---------------\n    logStatus<<\"compute tides & loading\"<<Log::endl;\n    Vector hn, ln;\n    if(!deformationName.empty())\n    {\n      Matrix love;\n      readFileMatrix(deformationName, love);\n      hn = love.column(0);\n      ln = love.column(1);\n\n      // models contain the total mass (loading mass & deformation mass effect)\n      if(!potentialName.empty())\n      {\n        Vector kn;\n        readFileMatrix(potentialName, kn);\n        for(UInt n=2; n<std::min(kn.rows(), hn.rows()); n++)\n          hn(n) /= (1.+kn(n));\n        for(UInt n=2; n<std::min(kn.rows(), ln.rows()); n++)\n          ln(n) /= (1.+kn(n));\n      }\n    }\n\n    std::vector<Vector3d> positions;\n    for(auto &stat : stations)\n      positions.push_back(stat->position(times.front()));\n\n    Vector gravity(positions.size()); // normal gravity\n    for(UInt i=0; i<gravity.size(); i++)\n      gravity(i) = Planets::normalGravity(positions.at(i));\n\n    std::vector<Rotary3d> rotEarth(times.size());\n    for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n      rotEarth.at(idEpoch) = earthRotation->rotaryMatrix(times.at(idEpoch));\n\n    std::vector<std::vector<Vector3d>> disp(positions.size(), std::vector<Vector3d>(times.size()));\n    tides->deformation(times, positions, rotEarth, earthRotation, ephemerides, gravity, hn, ln, disp);\n    gravityfield->deformation(times, positions, gravity, hn, ln, disp);\n    tides        = nullptr;\n    gravityfield = nullptr;\n\n    // add displacements\n    for(UInt i=0; i<stations.size(); i++)\n      for(UInt idEpoch=0; idEpoch<times.size(); idEpoch++)\n        axpy(1., stations.at(i)->global2localFrame(times.at(idEpoch)).transform(disp.at(i).at(idEpoch)).vector().trans(), stations.at(i)->offset.row(idEpoch));\n  }\n  catch(std::exception &e)\n  {\n    GROOPS_RETHROW(e)\n  }\n}\n\n/***********************************************/\n"
  },
  {
    "path": "source/slr/slrStationGenerator/slrStationGeneratorStations.h",
    "content": "/***********************************************/\n/**\n* @file slrStationGeneratorStations.h\n*\n* @brief SLR ground station network.\n*\n* @author Torsten Mayer-Guerr\n* @date 2022-04-28\n*\n*/\n/***********************************************/\n\n#ifndef __GROOPS_SLRRECEIVERGENERATORSTATIONNETWORK__\n#define __GROOPS_SLRRECEIVERGENERATORSTATIONNETWORK__\n\n// Latex documentation\n#ifdef DOCSTRING_SlrStationGenerator\nstatic const char *docstringSlrStationGeneratorStations = R\"(\n\\subsection{Stations}\\label{slrStationGeneratorType:stations}\nA list of station names must be provided via \\configFile{inputfileStationList}{stringList}.\nIt defines the variable \\verb|{station}| for the station specific input files.\nThe \\configFile{inputfileStationInfo}{platform} contains metadata information like station number,\nstation name and approximate station postion in terrestrial reference frame (TRF)\nconsidering the station eccentricities. They can be created via \\program{SinexEccentricties2SlrPlatform}\nor \\program{PlatformCreate}. The \\configFile{inputfileObservations}{instrument} are separate files\nfor each \\verb|{station}|-\\verb|{satellite}| pair. They can be converted from CRD\nformat via \\program{Crd2NormalPoints}, CSTG format via \\program{Cstg2NormalPoints}\nand MERIT II format via \\program{Merit2NormalPoints} and \\program{Merit2FullRate}.\n\nThe apriori observation weighting is defined by the expression \\config{accuracy} in $[m]$.\nThe following variables are defined for each observation from the\n\\configFile{inputfileObservations}{instrument}: \\verb|{residual}|, \\verb|{accuracy}|,\n\\verb|{redundancy}|, \\verb|{laserWavelength}|, \\verb|{azimut}|, \\verb|{elevation}|.\nObservations with non-positive accuracies are removed.\nThis can be used for a rough outlier removal by an expression such as\n\\config{accuracy} = \\verb|if(abs(residual)>30, NAN, accuracy)|.\n\nThe effects of loading and tidal deformation on station positions can be corrected for\nvia \\configClass{loadingDisplacement}{gravityfieldType} and\n\\configClass{tidalDisplacement}{tidesType}, respectively.\nTidal deformations typically include:\n\\begin{itemize}\n  \\item \\configClass{earthTide}{tidesType:earthTide}: Earth tidal deformations (IERS conventions)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tidal deformations\n        (e.g. fes2014b\\_n720, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: atmospheric tidal deformation\n        (e.g. AOD1B RL06, \\config{minDegree}=\\verb|1|)\n  \\item \\configClass{poleTide}{tidesType:poleTide}: pole tidal deformations (IERS conventions)\n  \\item \\configClass{poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tidal deformations (IERS conventions)\n\\end{itemize}\n)\";\n#endif\n\n/***********************************************/\n\n#include \"config/config.h\"\n#include \"classes/gravityfield/gravityfield.h\"\n#include \"classes/tides/tides.h\"\n#include \"classes/ephemerides/ephemerides.h\"\n#include \"classes/noiseGenerator/noiseGenerator.h\"\n#include \"slr/slrStationGenerator/slrStationGenerator.h\"\n\n/***** CLASS ***********************************/\n\n/** @brief SLR ground station network.\n* @ingroup slrStationGeneratorGroup\n* @see SlrStationGenerator */\nclass SlrStationGeneratorStations : public SlrStationGeneratorBase\n{\n  FileName              fileNameStationList, fileNameStationInfo;\n  FileName              fileNameStationPosition;\n  FileName              fileNameObs;\n  Bool                  disableWithoutPosition;\n  ExpressionVariablePtr accuracyExpr;\n  GravityfieldPtr       gravityfield;\n  TidesPtr              tides;\n  EphemeridesPtr        ephemerides;\n  FileName              deformationName, potentialName;\n  Angle                 elevationCutOff;\n  UInt                  interpolationDegree;\n  std::vector<SlrStationPtr> stations;\n\npublic:\n  SlrStationGeneratorStations(Config &config);\n\n  void init(const std::vector<Time> &times, const std::vector<SlrSatellitePtr> &satellites,\n            EarthRotationPtr earthRotation, std::vector<SlrStationPtr> &stations) override;\n};\n\n/***********************************************/\n\n#endif\n"
  },
  {
    "path": "source/sourcesCXX.txt",
    "content": "set(SOURCES\nbase/constants.cpp\nbase/doodson.cpp\nbase/ellipsoid.cpp\nbase/equinoctial.cpp\nbase/format.cpp\nbase/fourier.cpp\nbase/gnssType.cpp\nbase/griddedData.cpp\nbase/kepler.cpp\nbase/legendreFunction.cpp\nbase/legendrePolynomial.cpp\nbase/matrix.cpp\nbase/parameterName.cpp\nbase/planets.cpp\nbase/polynomial.cpp\nbase/rotary3d.cpp\nbase/sphericalHarmonics.cpp\nbase/string.cpp\nbase/time.cpp\nbase/transform3d.cpp\nbase/wavelets.cpp\n\nexternal/sgp4/SGP4.cpp\n\nparser/dataVariables.cpp\nparser/expressionParser.cpp\nparser/stringParser.cpp\nparser/xml.cpp\n\ninputOutput/archive.cpp\ninputOutput/archiveAscii.cpp\ninputOutput/archiveBinary.cpp\ninputOutput/archiveJson.cpp\ninputOutput/archiveXml.cpp\ninputOutput/file.cpp\ninputOutput/fileArchive.cpp\ninputOutput/fileName.cpp\ninputOutput/fileNetCdf.cpp\ninputOutput/fileSinex.cpp\ninputOutput/logging.cpp\ninputOutput/settings.cpp\ninputOutput/system.cpp\n\nparallel/matrixDistributed.cpp\n\nfiles/fileAdmittance.cpp\nfiles/fileArcList.cpp\nfiles/fileDoodsonEarthOrientationParameter.cpp\nfiles/fileDoodsonHarmonic.cpp\nfiles/fileEarthOrientationParameter.cpp\nfiles/fileEarthTide.cpp\nfiles/fileEphemerides.cpp\nfiles/fileGnssAntennaDefinition.cpp\nfiles/fileGnssReceiverDefinition.cpp\nfiles/fileGnssSignalBias.cpp\nfiles/fileGriddedData.cpp\nfiles/fileGriddedDataTimeSeries.cpp\nfiles/fileInstrument.cpp\nfiles/fileMatrix.cpp\nfiles/fileMeanPolarMotion.cpp\nfiles/fileNormalEquation.cpp\nfiles/fileOceanPoleTide.cpp\nfiles/fileParameterName.cpp\nfiles/filePlatform.cpp\nfiles/filePolygon.cpp\nfiles/fileSatelliteModel.cpp\nfiles/fileSphericalHarmonics.cpp\nfiles/fileStringTable.cpp\nfiles/fileTideGeneratingPotential.cpp\nfiles/fileTimeSplinesGravityfield.cpp\nfiles/fileVariationalEquation.cpp\n\nconfig/config.cpp\nconfig/generateDocumentation.cpp\n\nclasses/border/border.cpp\nclasses/condition/condition.cpp\nclasses/digitalFilter/digitalFilter.cpp\nclasses/digitalFilter/digitalFilterButterworth.cpp\nclasses/digitalFilter/digitalFilterNotch.cpp\nclasses/earthRotation/earthRotation.cpp\nclasses/earthRotation/earthRotationFile.cpp\nclasses/earthRotation/earthRotationIers1996.cpp\nclasses/earthRotation/earthRotationIers2003.cpp\nclasses/earthRotation/earthRotationIers2010b.cpp\nclasses/earthRotation/earthRotationIers2010.cpp\nclasses/earthRotation/earthRotationStarCamera.cpp\nclasses/eclipse/eclipse.cpp\nclasses/ephemerides/ephemerides.cpp\nclasses/forces/forces.cpp\nclasses/gravityfield/gravityfield.cpp\nclasses/gravityfield/gravityfieldEarthquakeOscillation.cpp\nclasses/gravityfield/gravityfieldFilter.cpp\nclasses/gravityfield/gravityfieldFromParametrization.cpp\nclasses/gravityfield/gravityfieldGroup.cpp\nclasses/gravityfield/gravityfieldInInterval.cpp\nclasses/gravityfield/gravityfieldOscillation.cpp\nclasses/gravityfield/gravityfieldPotentialCoefficients.cpp\nclasses/gravityfield/gravityfieldPotentialCoefficientsInterior.cpp\nclasses/gravityfield/gravityfieldTides.cpp\nclasses/gravityfield/gravityfieldTimeSplines.cpp\nclasses/gravityfield/gravityfieldTopography.cpp\nclasses/gravityfield/gravityfieldTrend.cpp\nclasses/grid/grid.cpp\nclasses/instrumentType/instrumentType.cpp\nclasses/interpolatorTimeSeries/interpolatorTimeSeries.cpp\nclasses/kernel/kernel.cpp\nclasses/kernel/kernelBlackmanLowPass.cpp\nclasses/kernel/kernelBottomPressure.cpp\nclasses/kernel/kernelCoefficients.cpp\nclasses/kernel/kernelDeformation.cpp\nclasses/kernel/kernelFilterGauss.cpp\nclasses/kernel/kernelGeoid.cpp\nclasses/kernel/kernelHotine.cpp\nclasses/kernel/kernelPoisson.cpp\nclasses/kernel/kernelRadialGradient.cpp\nclasses/kernel/kernelSelenoid.cpp\nclasses/kernel/kernelSingleLayer.cpp\nclasses/kernel/kernelStokes.cpp\nclasses/kernel/kernelTruncation.cpp\nclasses/kernel/kernelWaterHeight.cpp\nclasses/loop/loop.cpp\nclasses/magnetosphere/magnetosphere.cpp\nclasses/matrixGenerator/matrixGenerator.cpp\nclasses/miscAccelerations/miscAccelerations.cpp\nclasses/miscAccelerations/miscAccelerationsAlbedo.cpp\nclasses/noiseGenerator/noiseGenerator.cpp\nclasses/normalEquation/normalEquation.cpp\nclasses/normalEquation/normalEquationDesign.cpp\nclasses/normalEquation/normalEquationDesignVCE.cpp\nclasses/normalEquation/normalEquationFile.cpp\nclasses/normalEquation/normalEquationRegularization.cpp\nclasses/normalEquation/normalEquationRegularizationGeneralized.cpp\nclasses/observation/observation.cpp\nclasses/observation/observationDeflections.cpp\nclasses/observation/observationDualSstVariational.cpp\nclasses/observation/observationGradiometer.cpp\nclasses/observation/observationPodAcceleration.cpp\nclasses/observation/observationPodEnergy.cpp\nclasses/observation/observationPodIntegral.cpp\nclasses/observation/observationPodVariational.cpp\nclasses/observation/observationSstIntegral.cpp\nclasses/observation/observationSstVariational.cpp\nclasses/observation/observationStationLoading.cpp\nclasses/observation/observationTerrestrial.cpp\nclasses/orbitPropagator/orbitPropagator.cpp\nclasses/orbitPropagator/orbitPropagatorGaussJackson.cpp\nclasses/parameterNames/parameterNames.cpp\nclasses/parameterSelector/parameterSelector.cpp\nclasses/parametrizationGnssAntenna/parametrizationGnssAntenna.cpp\nclasses/parametrizationAcceleration/parametrizationAcceleration.cpp\nclasses/parametrizationGravity/parametrizationGravity.cpp\nclasses/parametrizationGravity/parametrizationGravityEarthquakeOscillation.cpp\nclasses/parametrizationGravity/parametrizationGravityLinearTransformation.cpp\nclasses/parametrizationGravity/parametrizationGravityRadialBasis.cpp\nclasses/parametrizationGravity/parametrizationGravitySphericalHarmonics.cpp\nclasses/parametrizationGravity/parametrizationGravityTemporal.cpp\nclasses/parametrizationSatelliteTracking/parametrizationSatelliteTracking.cpp\nclasses/parametrizationTemporal/parametrizationTemporal.cpp\nclasses/parametrizationTemporal/parametrizationTemporalConstant.cpp\nclasses/parametrizationTemporal/parametrizationTemporalDoodsonHarmonic.cpp\nclasses/parametrizationTemporal/parametrizationTemporalFourier.cpp\nclasses/parametrizationTemporal/parametrizationTemporalOscillation.cpp\nclasses/parametrizationTemporal/parametrizationTemporalPolynomial.cpp\nclasses/parametrizationTemporal/parametrizationTemporalSplines.cpp\nclasses/platformSelector/platformSelector.cpp\nclasses/sphericalHarmonicsFilter/sphericalHarmonicsFilter.cpp\nclasses/sphericalHarmonicsNumbering/sphericalHarmonicsNumbering.cpp\nclasses/thermosphere/thermosphere.cpp\nclasses/tides/tides.cpp\nclasses/tides/tidesAstronomical.cpp\nclasses/tides/tidesCentrifugal.cpp\nclasses/tides/tidesDoodsonHarmonic.cpp\nclasses/tides/tidesEarth.cpp\nclasses/tides/tidesGroup.cpp\nclasses/tides/tidesOceanPole.cpp\nclasses/tides/tidesPole.cpp\nclasses/tides/tidesSolidMoon.cpp\nclasses/timeSeries/timeSeries.cpp\nclasses/troposphere/troposphere.cpp\nclasses/troposphere/troposphereGpt.cpp\nclasses/troposphere/troposphereViennaMapping.cpp\n\ngnss/gnssParametrization/gnssParametrization.cpp\ngnss/gnssParametrization/gnssParametrizationAmbiguities.cpp\ngnss/gnssParametrization/gnssParametrizationClocks.cpp\ngnss/gnssParametrization/gnssParametrizationClocksModel.cpp\ngnss/gnssParametrization/gnssParametrizationCodeBiases.cpp\ngnss/gnssParametrization/gnssParametrizationEarthRotation.cpp\ngnss/gnssParametrization/gnssParametrizationIonosphereMap.cpp\ngnss/gnssParametrization/gnssParametrizationIonosphereSTEC.cpp\ngnss/gnssParametrization/gnssParametrizationIonosphereVTEC.cpp\ngnss/gnssParametrization/gnssParametrizationKinematicPositions.cpp\ngnss/gnssParametrization/gnssParametrizationLeoDynamicOrbits.cpp\ngnss/gnssParametrization/gnssParametrizationReceiverAntennas.cpp\ngnss/gnssParametrization/gnssParametrizationSignalBiases.cpp\ngnss/gnssParametrization/gnssParametrizationStaticPositions.cpp\ngnss/gnssParametrization/gnssParametrizationTecBiases.cpp\ngnss/gnssParametrization/gnssParametrizationTemporalBias.cpp\ngnss/gnssParametrization/gnssParametrizationTransmitterAntennas.cpp\ngnss/gnssParametrization/gnssParametrizationTransmitterDynamicOrbits.cpp\ngnss/gnssParametrization/gnssParametrizationTroposphere.cpp\ngnss/gnssProcessingStep/gnssProcessingStep.cpp\ngnss/gnssReceiverGenerator/gnssReceiverGenerator.cpp\ngnss/gnssReceiverGenerator/gnssReceiverGeneratorLowEarthOrbiter.cpp\ngnss/gnssReceiverGenerator/gnssReceiverGeneratorStationNetwork.cpp\ngnss/gnssTransmitterGenerator/gnssTransmitterGenerator.cpp\ngnss/gnssTransmitterGenerator/gnssTransmitterGeneratorGnss.cpp\ngnss/gnss.cpp\ngnss/gnssDesignMatrix.cpp\ngnss/gnssLambda.cpp\ngnss/gnssNormalEquationInfo.cpp\ngnss/gnssObservation.cpp\ngnss/gnssReceiver.cpp\n\nslr/slrParametrization/slrParametrization.cpp\nslr/slrParametrization/slrParametrizationDynamicOrbits.cpp\nslr/slrParametrization/slrParametrizationEarthRotation.cpp\nslr/slrParametrization/slrParametrizationGravityField.cpp\nslr/slrParametrization/slrParametrizationStaticPositions.cpp\nslr/slrParametrization/slrParametrizationTimeBias.cpp\nslr/slrParametrization/slrParametrizationTroposphere.cpp\nslr/slrProcessingStep/slrProcessingStep.cpp\nslr/slrSatelliteGenerator/slrSatelliteGenerator.cpp\nslr/slrSatelliteGenerator/slrSatelliteGeneratorSatellites.cpp\nslr/slrStationGenerator/slrStationGenerator.cpp\nslr/slrStationGenerator/slrStationGeneratorStations.cpp\nslr/slr.cpp\nslr/slrDesignMatrix.cpp\nslr/slrNormalEquationInfo.cpp\nslr/slrObservation.cpp\nslr/slrStation.cpp\n\nmisc/grace/graceKBandGeometry.cpp\nmisc/observation/covariancePod.cpp\nmisc/observation/covarianceSst.cpp\nmisc/observation/integralEquation.cpp\nmisc/observation/observationMisc.cpp\nmisc/observation/observationMiscDualSstVariational.cpp\nmisc/observation/observationMiscPod.cpp\nmisc/observation/observationMiscPodIntegral.cpp\nmisc/observation/observationMiscPodVariational.cpp\nmisc/observation/observationMiscSst.cpp\nmisc/observation/observationMiscSstIntegral.cpp\nmisc/observation/observationMiscSstVariational.cpp\nmisc/observation/variationalEquation.cpp\nmisc/observation/variationalEquationFromFile.cpp\nmisc/kalmanProcessing.cpp\nmisc/miscGriddedData.cpp\nmisc/normalsShortTimeStaticLongTime.cpp\nmisc/varianceComponentEstimation.cpp\n\nplot/plotAxis.cpp\nplot/plotColorbar.cpp\nplot/plotGraphLayer.cpp\nplot/plotLegend.cpp\nplot/plotMapLayer.cpp\nplot/plotMapProjection.cpp\nplot/plotMisc.cpp\n\nprograms/program.cpp\nprograms/covariance/autoregressiveModel2CovarianceMatrix.cpp\nprograms/covariance/covarianceFunction2DigitalFilter.cpp\nprograms/covariance/covarianceFunction2PowerSpectralDensity.cpp\nprograms/covariance/covarianceMatrix2AutoregressiveModel.cpp\nprograms/covariance/covarianceMatrix2Correlation.cpp\nprograms/covariance/powerSpectralDensity2CovarianceFunction.cpp\nprograms/doodsonHarmonics/doodsonAdmittanceInterpolation.cpp\nprograms/doodsonHarmonics/doodsonAdmittanceTimeSeries.cpp\nprograms/doodsonHarmonics/doodsonArguments2TimeSeries.cpp\nprograms/doodsonHarmonics/doodsonHarmonics2GriddedAmplitudeAndPhase.cpp\nprograms/doodsonHarmonics/doodsonHarmonics2PotentialCoefficients.cpp\nprograms/doodsonHarmonics/doodsonHarmonicsCalculateAdmittance.cpp\nprograms/doodsonHarmonics/doodsonHarmonicsChangePartialTides.cpp\nprograms/doodsonHarmonics/modelEquilibriumTide.cpp\nprograms/doodsonHarmonics/potentialCoefficients2DoodsonHarmonics.cpp\nprograms/gnss/gnssAntennaDefinition2ParameterVector.cpp\nprograms/gnss/gnssAntennaDefinition2Skyplot.cpp\nprograms/gnss/gnssAntennaDefinitionCreate.cpp\nprograms/gnss/gnssAntennaNormalsConstraint.cpp\nprograms/gnss/gnssAttitudeInfoCreate.cpp\nprograms/gnss/gnssBiasClockAlignment.cpp\nprograms/gnss/gnssEstimateClockShift.cpp\nprograms/gnss/gnssGlonassFrequencyNumberUpdate.cpp\nprograms/gnss/gnssProcessing.cpp\nprograms/gnss/gnssReceiverDefinitionCreate.cpp\nprograms/gnss/gnssResiduals2AccuracyDefinition.cpp\nprograms/gnss/gnssResiduals2TransmitterAccuracyDefinition.cpp\nprograms/gnss/gnssResiduals2Skyplot.cpp\nprograms/gnss/gnssSignalBias2Matrix.cpp\nprograms/gnss/gnssSimulateReceiver.cpp\nprograms/gnss/instrumentGnssReceiver2TimeSeries.cpp\nprograms/gnss/parameterVector2GnssAntennaDefinition.cpp\nprograms/grace/ensembleAveragingScaleModel.cpp\nprograms/grace/graceAntennaCenterCorrectionArcCovariance.cpp\nprograms/grace/graceOrbit2TransplantTimeOffset.cpp\nprograms/grace/graceSstResidualAnalysis.cpp\nprograms/grace/graceSstScaleModel.cpp\nprograms/grace/graceSstSpecialEvents.cpp\nprograms/grace/graceThrusterResponse2Accelerometer.cpp\nprograms/grace/instrumentSatelliteTrackingAntennaCenterCorrection.cpp\nprograms/grace/instrumentStarCameraAngularAccelerometerFusion.cpp\nprograms/gravityfield/gravityfield2AbsoluteGravity.cpp\nprograms/gravityfield/gravityfield2AreaMeanTimeSeries.cpp\nprograms/gravityfield/gravityfield2Deflections.cpp\nprograms/gravityfield/gravityfield2DegreeAmplitudes.cpp\nprograms/gravityfield/gravityfield2DegreeAmplitudesPlotGrid.cpp\nprograms/gravityfield/gravityfield2DisplacementTimeSeries.cpp\nprograms/gravityfield/gravityfield2EmpiricalCovariance.cpp\nprograms/gravityfield/gravityfield2Gradients.cpp\nprograms/gravityfield/gravityfield2GravityVector.cpp\nprograms/gravityfield/gravityfield2GridCovarianceMatrix.cpp\nprograms/gravityfield/gravityfield2GriddedData.cpp\nprograms/gravityfield/gravityfield2GriddedDataTimeSeries.cpp\nprograms/gravityfield/gravityfield2PotentialCoefficients.cpp\nprograms/gravityfield/gravityfield2PotentialCoefficientsTimeSeries.cpp\nprograms/gravityfield/gravityfield2SphericalHarmonicsVector.cpp\nprograms/gravityfield/gravityfield2TimeSplines.cpp\nprograms/gravityfield/gravityfield2TrendPotentialCoefficients.cpp\nprograms/gravityfield/gravityfieldCovariancesPropagation2GriddedData.cpp\nprograms/gravityfield/gravityfieldReplacePotentialCoefficients.cpp\nprograms/gravityfield/gravityfieldVariancesPropagation2GriddedData.cpp\nprograms/griddedData/griddedData2AreaMeanTimeSeries.cpp\nprograms/griddedData/griddedData2GriddedDataStatistics.cpp\nprograms/griddedData/griddedData2GriddedDataTimeSeries.cpp\nprograms/griddedData/griddedData2Matrix.cpp\nprograms/griddedData/griddedData2PotentialCoefficients.cpp\nprograms/griddedData/griddedData2SphericalDistance.cpp\nprograms/griddedData/griddedData2TimeSeries.cpp\nprograms/griddedData/griddedDataCalculate.cpp\nprograms/griddedData/griddedDataConcatenate.cpp\nprograms/griddedData/griddedDataCreate.cpp\nprograms/griddedData/griddedDataInterpolate.cpp\nprograms/griddedData/griddedDataReduceSampling.cpp\nprograms/griddedData/griddedDataTimeSeries2GriddedData.cpp\nprograms/griddedData/griddedDataTimeSeries2PotentialCoefficients.cpp\nprograms/griddedData/griddedTopography2AtmospherePotentialCoefficients.cpp\nprograms/griddedData/griddedTopography2PotentialCoefficients.cpp\nprograms/griddedData/griddedTopographyEllipsoidal2Radial.cpp\nprograms/griddedData/matrix2GriddedData.cpp\nprograms/griddedData/matrixRectangular2GriddedData.cpp\nprograms/griddedData/timeSeries2GriddedData.cpp\nprograms/instruments/instrument2AllanVariance.cpp\nprograms/instruments/instrument2CovarianceFunctionVCE.cpp\nprograms/instruments/instrument2CrossCorrelationFunction.cpp\nprograms/instruments/instrument2Histogram.cpp\nprograms/instruments/instrument2PowerSpectralDensity.cpp\nprograms/instruments/instrument2RmsPlotGrid.cpp\nprograms/instruments/instrument2Scaleogram.cpp\nprograms/instruments/instrument2SpectralCoherence.cpp\nprograms/instruments/instrument2Spectrogram.cpp\nprograms/instruments/instrumentAccelerometer2ThermosphericDensity.cpp\nprograms/instruments/instrumentAccelerometerApplyEstimatedParameters.cpp\nprograms/instruments/instrumentAccelerometerEstimateBiasScale.cpp\nprograms/instruments/instrumentAccelerometerEstimateParameters.cpp\nprograms/instruments/instrumentApplyTimeOffset.cpp\nprograms/instruments/instrumentArcCalculate.cpp\nprograms/instruments/instrumentArcCrossStatistics.cpp\nprograms/instruments/instrumentArcStatistics.cpp\nprograms/instruments/instrumentConcatenate.cpp\nprograms/instruments/instrumentCovarianceCheck.cpp\nprograms/instruments/instrumentDetrend.cpp\nprograms/instruments/instrumentEarthRotation.cpp\nprograms/instruments/instrumentEstimateEmpiricalCovariance.cpp\nprograms/instruments/instrumentEstimateHelmertTransformation.cpp\nprograms/instruments/instrumentFilter.cpp\nprograms/instruments/instrumentInsertNAN.cpp\nprograms/instruments/instrumentMultiplyAdd.cpp\nprograms/instruments/instrumentReduceSampling.cpp\nprograms/instruments/instrumentRemoveEpochsByCriteria.cpp\nprograms/instruments/instrumentRemoveEpochsByTimes.cpp\nprograms/instruments/instrumentRemoveEpochsThruster.cpp\nprograms/instruments/instrumentResample.cpp\nprograms/instruments/instrumentRotate.cpp\nprograms/instruments/instrumentSetType.cpp\nprograms/instruments/instrumentStarCamera2AccAngularRate.cpp\nprograms/instruments/instrumentStarCamera2RollPitchYaw.cpp\nprograms/instruments/instrumentStarCamera2RotaryMatrix.cpp\nprograms/instruments/instrumentStarCameraMultiply.cpp\nprograms/instruments/instrumentStatisticsTimeSeries.cpp\nprograms/instruments/instrumentSynchronize.cpp\nprograms/instruments/instrumentWaveletDecomposition.cpp\nprograms/instruments/localLevelFrame2StarCamera.cpp\nprograms/kalmanFilter/kalmanBuildNormals.cpp\nprograms/kalmanFilter/kalmanFilter.cpp\nprograms/kalmanFilter/kalmanSmoother.cpp\nprograms/kalmanFilter/kalmanSmootherLeastSquares.cpp\nprograms/misc/digitalFilter2FrequencyResponse.cpp\nprograms/misc/digitalFilter2ImpulseResponse.cpp\nprograms/misc/earthOrientationParameterTimeSeries.cpp\nprograms/misc/earthRotaryVectorTimeSeries.cpp\nprograms/misc/eclipseFactor2GriddedData.cpp\nprograms/misc/filterMatrixWindowedPotentialCoefficients.cpp\nprograms/misc/functionsCalculate.cpp\nprograms/misc/grs2PotentialCoefficients.cpp\nprograms/misc/kaula2SigmaPotentialCoefficients.cpp\nprograms/misc/kernel2SigmaPotentialCoefficients.cpp\nprograms/misc/kernel2Coefficients.cpp\nprograms/misc/kernelEvaluate.cpp\nprograms/misc/magneticField2GriddedData.cpp\nprograms/misc/matrixCalculate.cpp\nprograms/misc/observationEquations2Files.cpp\nprograms/misc/platformCreate.cpp\nprograms/misc/potentialCoefficients2BlockMeanTimeSplines.cpp\nprograms/misc/potentialCoefficients2DegreeAmplitudes.cpp\nprograms/misc/radialBasisSplines2KernelCoefficients.cpp\nprograms/misc/satelliteModelCreate.cpp\nprograms/misc/synthesisSphericalHarmonicsMatrix.cpp\nprograms/misc/temporalRepresentation2TimeSeries.cpp\nprograms/misc/thermosphericState2GriddedData.cpp\nprograms/misc/timeSeries2PotentialCoefficients.cpp\nprograms/misc/timeSeriesCreate.cpp\nprograms/misc/variational2OrbitAndStarCamera.cpp\nprograms/normals/normalsAccumulate.cpp\nprograms/normals/normalsBuild.cpp\nprograms/normals/normalsBuildShortTimeStaticLongTime.cpp\nprograms/normals/normalsCreate.cpp\nprograms/normals/normalsEliminate.cpp\nprograms/normals/normalsMultiplyAdd.cpp\nprograms/normals/normalsRegularizationBorders.cpp\nprograms/normals/normalsRegularizationSphericalHarmonics.cpp\nprograms/normals/normalsReorder.cpp\nprograms/normals/normalsReorderAndAccumulate.cpp\nprograms/normals/normalsScale.cpp\nprograms/normals/normalsSolverVCE.cpp\nprograms/normals/normalsTemporalCombination.cpp\nprograms/normals/parameterNamesCreate.cpp\nprograms/normals/parameterSelection2IndexVector.cpp\nprograms/orbit/orbit2ArgumentOfLatitude.cpp\nprograms/orbit/orbit2BetaPrimeAngle.cpp\nprograms/orbit/orbit2EarthFixedOrbit.cpp\nprograms/orbit/orbit2EclipseFactor.cpp\nprograms/orbit/orbit2Groundtracks.cpp\nprograms/orbit/orbit2Kepler.cpp\nprograms/orbit/orbit2MagneticField.cpp\nprograms/orbit/orbit2ThermosphericState.cpp\nprograms/orbit/orbitAddVelocityAndAcceleration.cpp\nprograms/orbit/planetOrbit.cpp\nprograms/plot/plotDegreeAmplitudes.cpp\nprograms/plot/plotGraph.cpp\nprograms/plot/plotMap.cpp\nprograms/plot/plotMatrix.cpp\nprograms/plot/plotSphericalHarmonicsTriangle.cpp\nprograms/preprocessing/preprocessingDualSst.cpp\nprograms/preprocessing/preprocessingGradiometer.cpp\nprograms/preprocessing/preprocessingPod.cpp\nprograms/preprocessing/preprocessingSst.cpp\nprograms/preprocessing/preprocessingVariationalEquation.cpp\nprograms/preprocessing/preprocessingVariationalEquationOrbitFit.cpp\nprograms/preprocessing/preprocessingVariationalEquationSstFit.cpp\nprograms/simulation/noiseAccelerometer.cpp\nprograms/simulation/noiseGriddedData.cpp\nprograms/simulation/noiseInstrument.cpp\nprograms/simulation/noiseNormalsSolution.cpp\nprograms/simulation/noiseOrbit.cpp\nprograms/simulation/noiseSatelliteTracking.cpp\nprograms/simulation/noiseStarCamera.cpp\nprograms/simulation/noiseTimeSeries.cpp\nprograms/simulation/simulateAccelerometerCoMOffset.cpp\nprograms/simulation/simulateAccelerometer.cpp\nprograms/simulation/simulateGradiometer.cpp\nprograms/simulation/simulateKeplerOrbit.cpp\nprograms/simulation/simulateOrbit.cpp\nprograms/simulation/simulateSatelliteTracking.cpp\nprograms/simulation/simulateStarCamera.cpp\nprograms/simulation/simulateStarCameraGnss.cpp\nprograms/simulation/simulateStarCameraGrace.cpp\nprograms/simulation/simulateStarCameraSentinel1.cpp\nprograms/simulation/simulateStarCameraTerrasar.cpp\nprograms/slr/slrProcessing.cpp\nprograms/system/fileConvert.cpp\nprograms/system/fileCreateDirectories.cpp\nprograms/system/fileMove.cpp\nprograms/system/fileRemove.cpp\nprograms/system/fileTextCreate.cpp\nprograms/system/groupPrograms.cpp\nprograms/system/ifPrograms.cpp\nprograms/system/loopPrograms.cpp\nprograms/system/runCommand.cpp\n\nprograms/conversion/doodsonHarmonics/doodsonAdmittance2SupplementaryFiles.cpp\nprograms/conversion/doodsonHarmonics/doodsonHarmonics2IersPotential.cpp\nprograms/conversion/doodsonHarmonics/doodsonHarmonics2IersWaterHeight.cpp\nprograms/conversion/doodsonHarmonics/graceAod2DoodsonHarmonics.cpp\nprograms/conversion/doodsonHarmonics/iersWaterHeight2DoodsonHarmonics.cpp\nprograms/conversion/doodsonHarmonics/iersPotential2DoodsonHarmonics.cpp\nprograms/conversion/eop/iersC04IAU2000EarthOrientationParameter.cpp\nprograms/conversion/eop/iersHighFrequentEop2DoodsonEop.cpp\nprograms/conversion/eop/iersRapidIAU2000EarthOrientationParameter.cpp\nprograms/conversion/eop/igs2EarthOrientationParameter.cpp\nprograms/conversion/gnss/gnssAntex2AntennaDefinition.cpp\nprograms/conversion/gnss/gnssClock2ClockRinex.cpp\nprograms/conversion/gnss/gnssClockRinex2InstrumentClock.cpp\nprograms/conversion/gnss/gnssEop2IgsErp.cpp\nprograms/conversion/gnss/gnssGriddedDataTimeSeries2Ionex.cpp\nprograms/conversion/gnss/gnssIonex2GriddedDataTimeSeries.cpp\nprograms/conversion/gnss/gnssNormals2Sinex.cpp\nprograms/conversion/gnss/gnssOrbex2StarCamera.cpp\nprograms/conversion/gnss/gnssReceiver2RinexObservation.cpp\nprograms/conversion/gnss/gnssRinexNavigation2OrbitClock.cpp\nprograms/conversion/gnss/gnssSignalBias2SinexBias.cpp\nprograms/conversion/gnss/gnssSinexBias2SignalBias.cpp\nprograms/conversion/gnss/gnssStationLog2Platform.cpp\nprograms/conversion/gnss/gnssTroposphere2TropoSinex.cpp\nprograms/conversion/gnss/rinexObservation2GnssReceiver.cpp\nprograms/conversion/gnss/sinex2StationDiscontinuities.cpp\nprograms/conversion/gnss/sinex2StationPositions.cpp\nprograms/conversion/gnss/sinexMetadata2GlonassFrequencyNumber.cpp\nprograms/conversion/gnss/sinexMetadata2SatelliteModel.cpp\nprograms/conversion/goce/goceXml2Gradiometer.cpp\nprograms/conversion/goce/goceXml2Orbit.cpp\nprograms/conversion/goce/goceXml2StarCamera.cpp\nprograms/conversion/goce/goceXmlEggNom1b.cpp\nprograms/conversion/grace/fileGrace.cpp\nprograms/conversion/grace/accelerometer2GraceL1b.cpp\nprograms/conversion/grace/grace2PotentialCoefficients.cpp\nprograms/conversion/grace/graceAccelerometer2L1bAscii.cpp\nprograms/conversion/grace/graceCoefficients2BlockMeanTimeSplines.cpp\nprograms/conversion/grace/graceL1a2Accelerometer.cpp\nprograms/conversion/grace/graceL1a2SatelliteTracking.cpp\nprograms/conversion/grace/graceL1a2StarCamera.cpp\nprograms/conversion/grace/graceL1a2Temperature.cpp\nprograms/conversion/grace/graceL1b2Accelerometer.cpp\nprograms/conversion/grace/graceL1b2AccHousekeeping.cpp\nprograms/conversion/grace/graceL1b2ClockOffset.cpp\nprograms/conversion/grace/graceL1b2GnssReceiver.cpp\nprograms/conversion/grace/graceL1b2Magnetometer.cpp\nprograms/conversion/grace/graceL1b2Mass.cpp\nprograms/conversion/grace/graceL1b2Orbit.cpp\nprograms/conversion/grace/graceL1b2SatelliteTracking.cpp\nprograms/conversion/grace/graceL1b2StarCameraCovariance.cpp\nprograms/conversion/grace/graceL1b2StarCamera.cpp\nprograms/conversion/grace/graceL1b2SteeringMirror.cpp\nprograms/conversion/grace/graceL1b2Thruster.cpp\nprograms/conversion/grace/graceL1b2TimeOffset.cpp\nprograms/conversion/grace/graceL1b2Uso.cpp\nprograms/conversion/grace/graceL1b2Vector.cpp\nprograms/conversion/grace/graceSequenceOfEvents.cpp\nprograms/conversion/grace/orbit2GraceL1b.cpp\nprograms/conversion/grace/satelliteTracking2GraceL1b.cpp\nprograms/conversion/grace/starCamera2GraceL1b.cpp\nprograms/conversion/grail/grailCdr2Orbit.cpp\nprograms/conversion/grail/grailCdr2SatelliteTracking.cpp\nprograms/conversion/grail/grailCdr2StarCamera.cpp\nprograms/conversion/grid/griddedData2NetCdf.cpp\nprograms/conversion/grid/griddedDataTimeSeries2NetCdf.cpp\nprograms/conversion/grid/netCdf2GriddedData.cpp\nprograms/conversion/grid/netCdf2GriddedDataTimeSeries.cpp\nprograms/conversion/grid/netCdfInfo.cpp\nprograms/conversion/grid/oceanTidesDTU2GriddedData.cpp\nprograms/conversion/satellites/champ2AccStar.cpp\nprograms/conversion/satellites/champ2Orbit.cpp\nprograms/conversion/satellites/cosmic2OrbitStar.cpp\nprograms/conversion/satellites/jason2Starcamera.cpp\nprograms/conversion/satellites/sacc2Orbit.cpp\nprograms/conversion/satellites/sentinel2Orbit.cpp\nprograms/conversion/satellites/sentinel2StarCamera.cpp\nprograms/conversion/satellites/swarm2Starcamera.cpp\nprograms/conversion/satellites/terraSarTandem2Orbit.cpp\nprograms/conversion/satellites/terraSarTandem2StarCamera.cpp\nprograms/conversion/slr/cpf2Orbit.cpp\nprograms/conversion/slr/crd2NormalPoints.cpp\nprograms/conversion/slr/cstg2NormalPoints.cpp\nprograms/conversion/slr/merit2FullRate.cpp\nprograms/conversion/slr/merit2NormalPoints.cpp\nprograms/conversion/slr/orbit2Cpf.cpp\nprograms/conversion/slr/sinexEccentricties2SlrPlatform.cpp\nprograms/conversion/slr/slrComModel2RangeBiasStationSatellite.cpp\nprograms/conversion/slr/slrSinexDataHandling2Files.cpp\nprograms/conversion/berneseKinematic2Orbit.cpp\nprograms/conversion/graceAod2TimeSplines.cpp\nprograms/conversion/groopsAscii2Orbit.cpp\nprograms/conversion/hw2TideGeneratingPotential.cpp\nprograms/conversion/icgem2PotentialCoefficients.cpp\nprograms/conversion/iers2OceanPoleTide.cpp\nprograms/conversion/jplAscii2Ephemerides.cpp\nprograms/conversion/normalsSphericalHarmonics2Sinex.cpp\nprograms/conversion/orbit2GroopsAscii.cpp\nprograms/conversion/orbit2Sp3Format.cpp\nprograms/conversion/potentialCoefficients2Icgem.cpp\nprograms/conversion/psmslOceanBottomPressure2TimeSeries.cpp\nprograms/conversion/sinex2Normals.cpp\nprograms/conversion/sp3Format2Orbit.cpp\nprograms/conversion/starCamera2Orbex.cpp\nprograms/conversion/tle2Orbit.cpp\nprograms/conversion/viennaMappingFunctionGrid2File.cpp\nprograms/conversion/viennaMappingFunctionStation2File.cpp\n\nprograms/deprecated/gnssAttitude2Orbex.cpp\nprograms/deprecated/gnssPrn2SvnBlockVariables.cpp\nprograms/deprecated/gnssStationInfoCreate.cpp\nprograms/deprecated/gridRectangular2NetCdf.cpp\nprograms/deprecated/netCdf2GridRectangular.cpp\nprograms/deprecated/sinex2StationPosition.cpp\nprograms/deprecated/sinex2StationPostSeismicDeformation.cpp\n\ngroops.cpp\n)\n"
  },
  {
    "path": "source/sourcesF77.txt",
    "content": "set(SOURCES ${SOURCES}\nexternal/lapack/blasWrapper.f\nexternal/lapack/lapackWrapper.f\n)\n\nif((NOT ${DISABLE_IERS}) OR (NOT DEFINED DISABLE_IERS))\n    set(SOURCES ${SOURCES}\n    external/iers/pmsdnut.f\n    external/iers/ray.f\n    external/iers/CNMTX.F\n    external/iers/FUNDARG.f\n    external/iers/ORTHO_EOP.F\n    external/iers/PMSDNUT2.F\n    external/iers/UTLIBR.F\n    )\nendif()\n\nif((NOT ${DISABLE_IGRF}) OR (NOT DEFINED DISABLE_IGRF))\n    set(SOURCES ${SOURCES}\n    external/igrf/igrf14.f\n    )\nendif()\n\nif((NOT ${DISABLE_JB2008}) OR (NOT DEFINED DISABLE_JB2008))\n    set(SOURCES ${SOURCES}\n    external/jb2008/JB2008.f\n    )\nendif()\n"
  },
  {
    "path": "source/sourcesF90.txt",
    "content": "if((NOT ${DISABLE_HWM14}) OR (NOT DEFINED DISABLE_HWM14))\n    set(SOURCES ${SOURCES}\n    external/hwm/hwm14.f90\n    )\nendif()\n\nif((NOT ${DISABLE_NRLMSIS}) OR (NOT DEFINED DISABLE_NRLMSIS))\n    set(SOURCES ${SOURCES}\n    external/nrlmsis2/alt2gph.F90\n    external/nrlmsis2/msis_constants.F90\n    external/nrlmsis2/msis_init.F90\n    external/nrlmsis2/msis_gfn.F90\n    external/nrlmsis2/msis_tfn.F90\n    external/nrlmsis2/msis_dfn.F90\n    external/nrlmsis2/msis_calc.F90\n    external/nrlmsis2/nrlmsis2Wrapper.F90\n    )\nendif()\n"
  }
]